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