1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements.  See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership.  The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License.  You may obtain a copy of the License at
9  *
10  *  http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied.  See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 #include <assert.h>
21 #include <errno.h>
22 #include <stdbool.h>
23 #include <stdint.h>
24 #include <zephyr/irq.h>
25 #include <system_DA1469x.h>
26 #include <da1469x_config.h>
27 #include <da1469x_lcdc.h>
28 #include <zephyr/sys/util.h>
29 
30 #define CLK_SYS_REG_SET_FIELD(_field, _var, _val)	\
31 	((_var)) =	\
32 	((_var) & ~(CRG_SYS_CLK_SYS_REG_ ## _field ## _Msk)) | 	\
33 	(((_val) << CRG_SYS_CLK_SYS_REG_ ## _field ## _Pos) & 	\
34 	CRG_SYS_CLK_SYS_REG_ ## _field ## _Msk)
35 
36 #define LCDC_BGCOLOR_REG_SET_FIELD(_field, _var, _val) 	\
37 	((_var)) =	\
38 	((_var) & ~(LCDC_LCDC_BGCOLOR_REG_ ## _field ## _Msk)) | 	\
39 	(((_val) << LCDC_LCDC_BGCOLOR_REG_ ## _field ## _Pos) & 	\
40 	LCDC_LCDC_BGCOLOR_REG_ ## _field ## _Msk)
41 
42 #define LCDC_RESXY_REG_SET_FIELD(_field, _var, _val)	\
43 	((_var)) =	\
44 	((_var) & ~(LCDC_LCDC_RESXY_REG_ ## _field ## _Msk)) |	\
45 	(((_val) << LCDC_LCDC_RESXY_REG_ ## _field ## _Pos) & 	\
46 	LCDC_LCDC_RESXY_REG_ ## _field ## _Msk)
47 
48 #define LCDC_FRONTPORCHXY_REG_SET_FIELD(_field, _var, _val)	\
49 	((_var)) =	\
50 	((_var) & ~(LCDC_LCDC_FRONTPORCHXY_REG_ ## _field ## _Msk)) |	\
51 	(((_val) << LCDC_LCDC_FRONTPORCHXY_REG_ ## _field ## _Pos) &	\
52 	LCDC_LCDC_FRONTPORCHXY_REG_ ## _field ## _Msk)
53 
54 #define LCDC_BLANKINGXY_REG_SET_FIELD(_field, _var, _val)	\
55 	((_var)) =	\
56 	((_var) & ~(LCDC_LCDC_BLANKINGXY_REG_ ## _field ## _Msk)) |	\
57 	(((_val) << LCDC_LCDC_BLANKINGXY_REG_ ## _field ## _Pos) & 	\
58 	LCDC_LCDC_BLANKINGXY_REG_ ## _field ## _Msk)
59 
60 #define LCDC_BACKPORCHXY_REG_SET_FIELD(_field, _var, _val)	\
61 	((_var)) =	\
62 	((_var) & ~(LCDC_LCDC_BACKPORCHXY_REG_ ## _field ## _Msk)) |	\
63 	(((_val) << LCDC_LCDC_BACKPORCHXY_REG_ ## _field ## _Pos) &		\
64 	LCDC_LCDC_BACKPORCHXY_REG_ ## _field ## _Msk)
65 
66 #define LCDC_DBIB_CMD_REG_SET_FIELD(_field, _var, _val)	\
67 	((_var)) =	\
68 	((_var) & ~(LCDC_LCDC_DBIB_CMD_REG_ ## _field ## _Msk)) |	\
69 	(((_val) << LCDC_LCDC_DBIB_CMD_REG_ ## _field ## _Pos) &	\
70 	LCDC_LCDC_DBIB_CMD_REG_ ## _field ## _Msk)
71 
72 #define LCDC_CLKCTRL_REG_SET_FIELD(_field, _var, _val)	\
73 	((_var)) =	\
74 	((_var) & ~(LCDC_LCDC_CLKCTRL_REG_ ## _field ## _Msk)) |	\
75 	(((_val) << LCDC_LCDC_CLKCTRL_REG_ ## _field ## _Pos) &		\
76 	LCDC_LCDC_CLKCTRL_REG_ ## _field ## _Msk)
77 
78 #define LCDC_DBIB_CFG_REG_SET_FIELD(_field, _var, _val)	\
79 	((_var)) =	\
80 	((_var) & ~(LCDC_LCDC_DBIB_CFG_REG_ ## _field ## _Msk)) |	\
81 	(((_val) << LCDC_LCDC_DBIB_CFG_REG_ ## _field ## _Pos) &	\
82 	LCDC_LCDC_DBIB_CFG_REG_ ## _field ## _Msk)
83 
84 #define LCDC_LAYER0_STARTXY_REG_SET_FIELD(_field, _var, _val)	\
85 	((_var)) =	\
86 	((_var) & ~(LCDC_LCDC_LAYER0_STARTXY_REG_ ## _field ## _Msk)) |	\
87 	(((_val) << LCDC_LCDC_LAYER0_STARTXY_REG_ ## _field ## _Pos) &	\
88 	LCDC_LCDC_LAYER0_STARTXY_REG_ ## _field ## _Msk)
89 
90 #define LCDC_LAYER0_MODE_REG_SET_FIELD(_field, _var, _val)	\
91 	((_var)) =	\
92 	((_var) & ~(LCDC_LCDC_LAYER0_MODE_REG_ ## _field ## _Msk)) |	\
93 	(((_val) << LCDC_LCDC_LAYER0_MODE_REG_ ## _field ## _Pos) &		\
94 	LCDC_LCDC_LAYER0_MODE_REG_ ## _field ## _Msk)
95 
96 #define LCDC_LAYER0_STRIDE_REG_SET_FIELD(_field, _var, _val)	\
97 	((_var)) =	\
98 	((_var) & ~(LCDC_LCDC_LAYER0_STRIDE_REG_ ## _field ## _Msk)) |	\
99 	(((_val) << LCDC_LCDC_LAYER0_STRIDE_REG_ ## _field ## _Pos) &	\
100 	LCDC_LCDC_LAYER0_STRIDE_REG_ ## _field ## _Msk)
101 
102 #define LCDC_LAYER0_SIZEXY_REG_SET_FIELD(_field, _var, _val)	\
103 	((_var)) =	\
104 	((_var) & ~(LCDC_LCDC_LAYER0_SIZEXY_REG_ ## _field ## _Msk)) |	\
105 	(((_val) << LCDC_LCDC_LAYER0_SIZEXY_REG_ ## _field ## _Pos) &	\
106 	LCDC_LCDC_LAYER0_SIZEXY_REG_ ## _field ## _Msk)
107 
108 #define LCDC_LAYER0_RESXY_REG_SET_FIELD(_field, _var, _val)	\
109 	((_var)) =	\
110 	((_var) & ~(LCDC_LCDC_LAYER0_RESXY_REG_ ## _field ## _Msk)) |	\
111 	(((_val) << LCDC_LCDC_LAYER0_RESXY_REG_ ## _field ## _Pos) &	\
112 	LCDC_LCDC_LAYER0_RESXY_REG_ ## _field ## _Msk)
113 
114 #define LCDC_MODE_REG_SET_FIELD(_field, _var, _val)	\
115 	((_var)) =	\
116 	((_var) & ~(LCDC_LCDC_MODE_REG_ ## _field ## _Msk)) |	\
117 	(((_val) << LCDC_LCDC_MODE_REG_ ## _field ## _Pos) & 	\
118 	LCDC_LCDC_MODE_REG_ ## _field ## _Msk)
119 
120 #define LCDC_DBIB_CMD_REG_GET_FIELD(_field)	\
121 	((LCDC->LCDC_DBIB_CMD_REG & LCDC_LCDC_DBIB_CMD_REG_ ## _field ## _Msk) >>	\
122 	LCDC_LCDC_DBIB_CMD_REG_ ## _field ## _Pos)
123 
124 #define LCDC_DBIB_CFG_REG_GET_FIELD(_field)	\
125 	((LCDC->LCDC_DBIB_CFG_REG & LCDC_LCDC_DBIB_CFG_REG_ ## _field ## _Msk) >>	\
126 	LCDC_LCDC_DBIB_CFG_REG_ ## _field ## _Pos)
127 
128 /* Min. horizontal frame width, in pixels, required by the host controller */
129 #define MIPI_DBI_SMARTBOND_MIN_ACTIVE_FRAME_WIDTH    4
130 
131 /**
132  * Write to DBIB configuration register
133  *
134  * @param value  Value to be written to DBIB configuration register
135  *
136  */
137 static inline void
lcdc_dbib_cfg_reg_write(uint32_t value)138 lcdc_dbib_cfg_reg_write(uint32_t value)
139 {
140 	while (LCDC_STATUS_REG_GET_FIELD(LCDC_DBIB_CMD_FIFO_FULL));
141 	LCDC->LCDC_DBIB_CFG_REG = value;
142 }
143 
144 uint16_t
da1469x_lcdc_stride_calculation(uint8_t lcm,uint16_t x_res)145 da1469x_lcdc_stride_calculation(uint8_t lcm, uint16_t x_res)
146 {
147 	uint8_t num_of_bytes = 0;
148 
149 	switch (lcm) {
150 	case LCDC_SMARTBOND_L0_RGBA8888:
151 	case LCDC_SMARTBOND_L0_ARGB8888:
152 	case LCDC_SMARTBOND_L0_ABGR8888:
153 	case LCDC_SMARTBOND_L0_BGRA8888:
154 		num_of_bytes = 4;
155 		break;
156 	case LCDC_SMARTBOND_L0_RGBA5551:
157 	case LCDC_SMARTBOND_L0_RGB565:
158 		num_of_bytes = 2;
159 		break;
160 	case LCDC_SMARTBOND_L0_RGB332:
161 	case LCDC_SMARTBOND_L0_L8:
162 		num_of_bytes = 1;
163 		break;
164 	case LCDC_SMARTBOND_L0_L1:
165 		num_of_bytes = DIV_ROUND_UP(x_res, 8);
166 		break;
167 	case LCDC_SMARTBOND_L0_L4:
168 		num_of_bytes = DIV_ROUND_UP(x_res, 4);
169 		break;
170 	default:
171 		assert(0);
172 		break;
173 	}
174 
175 	return (((num_of_bytes * x_res) + 0x3) & ~0x3);
176 }
177 
178 void
da1469x_lcdc_force_cs_line(bool force,bool cs_level)179 da1469x_lcdc_force_cs_line(bool force, bool cs_level)
180 {
181 	uint32_t lcdc_dbib_cfg_reg = LCDC->LCDC_DBIB_CFG_REG;
182 	LCDC_DBIB_CFG_REG_SET_FIELD(LCDC_DBIB_CSX_FORCE, lcdc_dbib_cfg_reg, force ? 1 : 0);
183 	LCDC_DBIB_CFG_REG_SET_FIELD(LCDC_DBIB_CSX_FORCE_VAL, lcdc_dbib_cfg_reg, cs_level ? 1 : 0);
184 	lcdc_dbib_cfg_reg_write(lcdc_dbib_cfg_reg);
185 }
186 
187 void
da1469x_lcdc_send_cmd_data(bool cmd,const uint8_t * buf,size_t len)188 da1469x_lcdc_send_cmd_data(bool cmd, const uint8_t *buf, size_t len)
189 {
190 	uint32_t lcdc_dbib_cmd_reg = 0;
191 
192 	for (int i = 0; i < len; i++) {
193 
194 		/*
195 		 * Workaround for D/C not aligned correctly with CLK. If SPI4 and not using hold and
196 		 * type changes wait until DBIB FIFO is empty. In any other case wait until there is
197 		 * some space empty in FIFO.
198 		 */
199 		if (LCDC_DBIB_CFG_REG_GET_FIELD(LCDC_DBIB_SPI4_EN) &&
200 			!LCDC_DBIB_CFG_REG_GET_FIELD(LCDC_DBIB_SPI_HOLD) &&
201 				LCDC_DBIB_CMD_REG_GET_FIELD(LCDC_DBIB_CMD_SEND) != cmd) {
202 			while (LCDC_STATUS_REG_GET_FIELD(LCDC_DBIB_CMD_PENDING));
203 		} else {
204 			while (LCDC_STATUS_REG_GET_FIELD(LCDC_DBIB_CMD_FIFO_FULL));
205 		}
206 
207 		LCDC_DBIB_CMD_REG_SET_FIELD(LCDC_DBIB_CMD_SEND, lcdc_dbib_cmd_reg, cmd ? 0x1 : 0x0);
208 		LCDC_DBIB_CMD_REG_SET_FIELD(LCDC_DBIB_CMD_VAL, lcdc_dbib_cmd_reg, buf[i]);
209 		LCDC->LCDC_DBIB_CMD_REG = lcdc_dbib_cmd_reg;
210 	}
211 }
212 
213 int
da1469x_lcdc_layer_configure(lcdc_smartbond_layer_cfg * layer)214 da1469x_lcdc_layer_configure(lcdc_smartbond_layer_cfg *layer)
215 {
216 	uint32_t reg = 0;
217 
218 	/* Check against LCDC requirements */
219 	if (layer->frame_buf & 0x3) {
220 		assert(0);
221 		return -EIO;
222 	}
223 	if (layer->stride & 0x3) {
224 		assert(0);
225 		return -EIO;
226 	}
227 
228 	/* Controller's DMA can only handle physical addresses */
229 	LCDC->LCDC_LAYER0_BASEADDR_REG = black_orca_phy_addr(layer->frame_buf);
230 
231 	LCDC_LAYER0_STARTXY_REG_SET_FIELD(LCDC_L0_START_X, reg, layer->start_x);
232 	LCDC_LAYER0_STARTXY_REG_SET_FIELD(LCDC_L0_START_Y, reg, layer->start_y);
233 	LCDC->LCDC_LAYER0_STARTXY_REG = reg;
234 
235 	LCDC_LAYER0_SIZEXY_REG_SET_FIELD(LCDC_L0_SIZE_X, reg, layer->size_x);
236 	LCDC_LAYER0_SIZEXY_REG_SET_FIELD(LCDC_L0_SIZE_Y, reg, layer->size_y);
237 	LCDC->LCDC_LAYER0_SIZEXY_REG = reg;
238 
239 	LCDC_LAYER0_RESXY_REG_SET_FIELD(LCDC_L0_RES_X, reg, layer->size_x);
240 	LCDC_LAYER0_RESXY_REG_SET_FIELD(LCDC_L0_RES_Y, reg, layer->size_y);
241 	LCDC->LCDC_LAYER0_RESXY_REG = reg;
242 
243 	/*
244 	 * Stride should be updated while there is no active frame activity. However, in the
245 	 * continuous mode (RGB or JDI parallel interfaces) there is no partial update and so
246 	 * stride is not changed at runtime. For the rest of the layer settings, and while in
247 	 * continuous mode, there is a protection mechanism that updates layer settings upon
248 	 * completion of the current active frame.
249 	 */
250 	reg = LCDC->LCDC_LAYER0_STRIDE_REG;
251 	LCDC_LAYER0_STRIDE_REG_SET_FIELD(LCDC_L0_STRIDE, reg, layer->stride);
252 	LCDC->LCDC_LAYER0_STRIDE_REG = reg;
253 
254 	LCDC_LAYER0_MODE_REG_SET_FIELD(LCDC_L0_EN, reg, 1);
255 	LCDC_LAYER0_MODE_REG_SET_FIELD(LCDC_L0_COLOUR_MODE, reg, layer->color_format);
256 	LCDC->LCDC_LAYER0_MODE_REG = reg;
257 
258 	return 0;
259 }
260 
261 void
da1469x_lcdc_bgcolor_configure(lcdc_smartbond_bgcolor_cfg * bgcolor)262 da1469x_lcdc_bgcolor_configure(lcdc_smartbond_bgcolor_cfg *bgcolor)
263 {
264 	uint32_t lcdc_bgcolor_reg = 0;
265 	LCDC_BGCOLOR_REG_SET_FIELD(LCDC_BG_RED, lcdc_bgcolor_reg, bgcolor->red);
266 	LCDC_BGCOLOR_REG_SET_FIELD(LCDC_BG_GREEN, lcdc_bgcolor_reg, bgcolor->green);
267 	LCDC_BGCOLOR_REG_SET_FIELD(LCDC_BG_BLUE, lcdc_bgcolor_reg, bgcolor->blue);
268 	LCDC_BGCOLOR_REG_SET_FIELD(LCDC_BG_ALPHA, lcdc_bgcolor_reg, bgcolor->alpha);
269 	LCDC->LCDC_BGCOLOR_REG = lcdc_bgcolor_reg;
270 }
271 
272 void
da1469x_lcdc_set_status(bool enable,bool div1,uint8_t clk_div)273 da1469x_lcdc_set_status(bool enable, bool div1, uint8_t clk_div)
274 {
275 	unsigned int key;
276 	uint32_t clk_sys_reg;
277 
278 	/* Globally disable interrupts as some registers may also be used by other devices */
279 	key = DA1469X_IRQ_DISABLE();
280 	clk_sys_reg = CRG_SYS->CLK_SYS_REG;
281 
282 	if (enable) {
283 		CLK_SYS_REG_SET_FIELD(LCD_CLK_SEL, clk_sys_reg, div1);
284 		CLK_SYS_REG_SET_FIELD(LCD_ENABLE, clk_sys_reg, 1);
285 
286 		irq_enable(LCD_CONTROLLER_IRQn);
287 	} else {
288 		/* Forcefully reset the host controller */
289 		CRG_SYS->CLK_SYS_REG |= CRG_SYS_CLK_SYS_REG_LCD_RESET_REQ_Msk;
290 		CLK_SYS_REG_SET_FIELD(LCD_RESET_REQ, clk_sys_reg, 0);
291 		CLK_SYS_REG_SET_FIELD(LCD_CLK_SEL, clk_sys_reg, 0);
292 		CLK_SYS_REG_SET_FIELD(LCD_ENABLE, clk_sys_reg, 0);
293 
294 		irq_disable(LCD_CONTROLLER_IRQn);
295 	}
296 
297 	CRG_SYS->CLK_SYS_REG = clk_sys_reg;
298 
299 	/*
300 	 * Setup the correct clock divider to achieve the requested pixel speed.
301 	 * Zero value means division by one.
302 	 */
303 	LCDC_CLKCTRL_REG_SET_FIELD(LCDC_CLK_DIV, LCDC->LCDC_CLKCTRL_REG,
304 						clk_div ? clk_div - 1 : clk_div);
305 	DA1469X_IRQ_ENABLE(key);
306 }
307 
308 int
da1469x_lcdc_timings_configure(uint16_t x_res,uint16_t y_res,lcdc_smartbond_timing_cfg * timing)309 da1469x_lcdc_timings_configure(uint16_t x_res, uint16_t y_res, lcdc_smartbond_timing_cfg *timing)
310 {
311 	uint16_t resx = x_res;
312 	uint16_t resy = y_res;
313 	uint32_t lcdc_resxy_reg = 0;
314 
315 	/* Check if the active frame confronts to host requirements */
316 	if (resx < MIPI_DBI_SMARTBOND_MIN_ACTIVE_FRAME_WIDTH) {
317 		assert(0);
318 		return -EIO;
319 	}
320 
321 	LCDC_RESXY_REG_SET_FIELD(LCDC_RES_X, lcdc_resxy_reg, resx);
322 	LCDC_RESXY_REG_SET_FIELD(LCDC_RES_Y, lcdc_resxy_reg, resy);
323 	LCDC->LCDC_RESXY_REG = lcdc_resxy_reg;
324 
325 	/* Bug fix: LCDC will produce minus 1 pixel period so value should be increased by one. */
326 	resx += (timing->hfront_porch ? timing->hfront_porch + 1 : timing->hfront_porch);
327 	resy += timing->vfront_porch;
328 
329 	LCDC_FRONTPORCHXY_REG_SET_FIELD(LCDC_FPORCH_X, lcdc_resxy_reg, resx);
330 	LCDC_FRONTPORCHXY_REG_SET_FIELD(LCDC_FPORCH_Y, lcdc_resxy_reg, resy);
331 	LCDC->LCDC_FRONTPORCHXY_REG = lcdc_resxy_reg;
332 
333 	/* LCDC imposes min values for X and Y blanking window */
334 	resx += MAX(timing->hsync_len, LCDC_SMARTBOND_HSYN_MIN_LEN);
335 	resy += MAX(timing->vsync_len, LCDC_SMARTBOND_VSYN_MIN_LEN);
336 
337 	LCDC_BLANKINGXY_REG_SET_FIELD(LCDC_BLANKING_X, lcdc_resxy_reg, resx);
338 	LCDC_BLANKINGXY_REG_SET_FIELD(LCDC_BLANKING_Y, lcdc_resxy_reg, resy);
339 	LCDC->LCDC_BLANKINGXY_REG = lcdc_resxy_reg;
340 
341 	/* Bug fix: LCDC will produce plus 1 pixel period so value should be decreased by one. */
342 	resx += (timing->hback_porch ? timing->hback_porch - 1 : timing->hback_porch);
343 	resy += timing->vback_porch;
344 
345 	LCDC_BACKPORCHXY_REG_SET_FIELD(LCDC_BPORCH_X, lcdc_resxy_reg, resx);
346 	LCDC_BACKPORCHXY_REG_SET_FIELD(LCDC_BPORCH_Y, lcdc_resxy_reg, resy);
347 	LCDC->LCDC_BACKPORCHXY_REG = lcdc_resxy_reg;
348 
349 	return 0;
350 }
351 
352 void
da1469x_lcdc_te_set_status(bool enable,bool inversion)353 da1469x_lcdc_te_set_status(bool enable, bool inversion)
354 {
355 	uint32_t lcdc_dbib_cfg_reg = LCDC->LCDC_DBIB_CFG_REG;
356 
357 	if (enable) {
358 		LCDC->LCDC_GPIO_REG |= (inversion ? LCDC_LCDC_GPIO_REG_LCDC_TE_INV_Msk : 0);
359 		lcdc_dbib_cfg_reg_write(lcdc_dbib_cfg_reg & ~LCDC_LCDC_DBIB_CFG_REG_LCDC_DBIB_TE_DIS_Msk);
360 		LCDC->LCDC_INTERRUPT_REG |= (LCDC_LCDC_INTERRUPT_REG_LCDC_TE_IRQ_EN_Msk |
361 							LCDC_LCDC_INTERRUPT_REG_LCDC_VSYNC_IRQ_EN_Msk);
362 	} else {
363 		LCDC->LCDC_INTERRUPT_REG &= ~(LCDC_LCDC_INTERRUPT_REG_LCDC_TE_IRQ_EN_Msk |
364 							LCDC_LCDC_INTERRUPT_REG_LCDC_VSYNC_IRQ_EN_Msk);
365 		lcdc_dbib_cfg_reg_write(lcdc_dbib_cfg_reg | LCDC_LCDC_DBIB_CFG_REG_LCDC_DBIB_TE_DIS_Msk);
366 	}
367 }
368 
369 int
da1469x_lcdc_mipi_dbi_interface_configure(lcdc_smartbond_mipi_dbi_cfg * mipi_dbi)370 da1469x_lcdc_mipi_dbi_interface_configure(lcdc_smartbond_mipi_dbi_cfg *mipi_dbi)
371 {
372 	uint32_t lcdc_dbib_cfg_reg = LCDC->LCDC_DBIB_CFG_REG;
373 
374 	switch (mipi_dbi->line_mode) {
375 	case LCDC_SMARTBOND_MODE_SPI3:
376 		LCDC_DBIB_CFG_REG_SET_FIELD(LCDC_DBIB_SPI3_EN, lcdc_dbib_cfg_reg, 1);
377 		LCDC_DBIB_CFG_REG_SET_FIELD(LCDC_DBIB_SPI4_EN, lcdc_dbib_cfg_reg, 0);
378 		break;
379 	case LCDC_SMARTBOND_MODE_SPI4:
380 		LCDC_DBIB_CFG_REG_SET_FIELD(LCDC_DBIB_SPI4_EN, lcdc_dbib_cfg_reg, 1);
381 		LCDC_DBIB_CFG_REG_SET_FIELD(LCDC_DBIB_SPI3_EN, lcdc_dbib_cfg_reg, 0);
382 		break;
383 	default:
384 		assert(0);
385 		return -EIO;
386 	}
387 
388 	/* Common settings required for DBIB engine */
389 	LCDC_DBIB_CFG_REG_SET_FIELD(LCDC_DBIB_DMA_EN, lcdc_dbib_cfg_reg, 1);
390 	LCDC_DBIB_CFG_REG_SET_FIELD(LCDC_DBIB_RESX, lcdc_dbib_cfg_reg, 1);
391 
392 	LCDC_DBIB_CFG_REG_SET_FIELD(LCDC_DBIB_SPI_CPHA, lcdc_dbib_cfg_reg, mipi_dbi->cpha ? 0 : 1);
393 	LCDC_DBIB_CFG_REG_SET_FIELD(LCDC_DBIB_SPI_CPOL, lcdc_dbib_cfg_reg, mipi_dbi->cpol ? 0 : 1);
394 	LCDC_DBIB_CFG_REG_SET_FIELD(LCDC_DBIB_CSX_FORCE_VAL, lcdc_dbib_cfg_reg,
395 			mipi_dbi->cs_active_high ? 1 : 0);
396 	LCDC_DBIB_CFG_REG_SET_FIELD(LCDC_DBIB_FMT, lcdc_dbib_cfg_reg, mipi_dbi->color_mode);
397 
398 	lcdc_dbib_cfg_reg_write(lcdc_dbib_cfg_reg);
399 
400 	return 0;
401 }
402 
403 void
da1469x_lcdc_parallel_interface_configure(lcdc_smartbond_mode_cfg * mode)404 da1469x_lcdc_parallel_interface_configure(lcdc_smartbond_mode_cfg *mode)
405 {
406 	uint32_t lcdc_dbib_cfg_reg;
407 	uint32_t lcdc_mode_reg;
408 
409 	/* Common settings required for DBIB engine */
410 	lcdc_dbib_cfg_reg = LCDC->LCDC_DBIB_CFG_REG;
411 	LCDC_DBIB_CFG_REG_SET_FIELD(LCDC_DBIB_DMA_EN, lcdc_dbib_cfg_reg, 1);
412 	LCDC_DBIB_CFG_REG_SET_FIELD(LCDC_DBIB_RESX, lcdc_dbib_cfg_reg, 1);
413 	LCDC_DBIB_CFG_REG_SET_FIELD(LCDC_DBIB_TE_DIS, lcdc_dbib_cfg_reg, 1);
414 
415 	/* Only RGB222 is supported in RGB parallel interface */
416 	LCDC_DBIB_CFG_REG_SET_FIELD(LCDC_DBIB_FMT, lcdc_dbib_cfg_reg, LCDC_SMARTBOND_OCM_RGB222);
417 	lcdc_dbib_cfg_reg_write(lcdc_dbib_cfg_reg);
418 
419 	/* Configure the mode register */
420 	lcdc_mode_reg = LCDC->LCDC_MODE_REG;
421 	LCDC_MODE_REG_SET_FIELD(LCDC_MIPI_OFF, lcdc_mode_reg, 1);
422 	/* Select RGB interface */
423 	LCDC_MODE_REG_SET_FIELD(LCDC_OUT_MODE, lcdc_mode_reg, 0);
424 	LCDC_MODE_REG_SET_FIELD(LCDC_VSYNC_POL, lcdc_mode_reg, mode->vsync_pol);
425 	LCDC_MODE_REG_SET_FIELD(LCDC_HSYNC_POL, lcdc_mode_reg, mode->hsync_pol);
426 	LCDC_MODE_REG_SET_FIELD(LCDC_DE_POL, lcdc_mode_reg, mode->de_pol);
427 	LCDC_MODE_REG_SET_FIELD(LCDC_PIXCLKOUT_POL, lcdc_mode_reg, mode->pixelclk_pol);
428 	LCDC->LCDC_MODE_REG = lcdc_mode_reg;
429 
430 	/* Enable RGB parallel interface */
431 	LCDC->LCDC_GPIO_REG |= LCDC_LCDC_GPIO_REG_LCDC_PARIF_SEL_Msk;
432 }
433