1 #include "bflb_dbi.h"
2 #include "bflb_clock.h"
3 #include "hardware/dbi_reg.h"
4
5 #if (DBI_YUV_SUPPORT)
6 /* YUV to RGB parameter list, do not modify. */
7
8 #define YUV_PRE_OFFSET_0 0
9 #define YUV_PRE_OFFSET_1 0x180
10 #define YUV_PRE_OFFSET_2 0x180
11
12 #define YUV_POST_OFFSET_0 0
13 #define YUV_POST_OFFSET_1 0
14 #define YUV_POST_OFFSET_2 0
15
16 #define YUV_MATRIX00 0x200
17 #define YUV_MATRIX01 0
18 #define YUV_MATRIX02 0x2ce
19
20 #define YUV_MATRIX10 0x200
21 #define YUV_MATRIX11 0xf50
22 #define YUV_MATRIX12 0xe92
23
24 #define YUV_MATRIX20 0x200
25 #define YUV_MATRIX21 0x38b
26 #define YUV_MATRIX22 0
27
28 #endif
29
bflb_dbi_init(struct bflb_device_s * dev,const struct bflb_dbi_config_s * config)30 void bflb_dbi_init(struct bflb_device_s *dev, const struct bflb_dbi_config_s *config)
31 {
32 uint32_t reg_base;
33 uint32_t regval;
34 uint32_t div;
35
36 reg_base = dev->reg_base;
37
38 regval = getreg32(reg_base + DBI_CONFIG_OFFSET);
39
40 /* disable DBI transaction */
41 regval &= ~DBI_CR_DBI_EN;
42 putreg32(regval, reg_base + DBI_CONFIG_OFFSET);
43
44 /* dbi work mode select */
45 regval &= ~DBI_CR_DBI_SEL_MASK;
46 regval |= config->dbi_mode << DBI_CR_DBI_SEL_SHIFT;
47
48 /* clock phase and polarity cfg */
49 switch (config->clk_mode) {
50 case DBI_CLOCK_MODE_0:
51 /* CPOL=0 CHPHA=0 */
52 regval &= ~DBI_CR_DBI_SCL_POL;
53 regval |= DBI_CR_DBI_SCL_PH;
54 break;
55 case DBI_CLOCK_MODE_1:
56 /* CPOL=0 CHPHA=1 */
57 regval &= ~DBI_CR_DBI_SCL_POL;
58 regval &= ~DBI_CR_DBI_SCL_PH;
59 break;
60 case DBI_CLOCK_MODE_2:
61 /* CPOL=1 CHPHA=0 */
62 regval |= DBI_CR_DBI_SCL_POL;
63 regval |= DBI_CR_DBI_SCL_PH;
64 break;
65 case DBI_CLOCK_MODE_3:
66 /* CPOL=1 CHPHA=1 */
67 regval |= DBI_CR_DBI_SCL_POL;
68 regval &= ~DBI_CR_DBI_SCL_PH;
69 break;
70 default:
71 break;
72 }
73
74 /* disable pixel data continuous transfer mode (CS) */
75 regval &= ~DBI_CR_DBI_CONT_EN;
76
77 /* disable dummy between command phase and data phase */
78 regval &= ~DBI_CR_DBI_DMY_EN;
79
80 /* CS will stay asserted before FIFO is empty */
81 #if (DBI_QSPI_SUPPORT)
82 if (config->dbi_mode == DBI_MODE_EX_QSPI) {
83 /* The CS of the qspi must be asserted in a single transaction */
84 regval |= DBI_CR_DBI_CS_STRETCH;
85 } else
86 #endif
87 {
88 /* Other modes don't care */
89 regval &= ~DBI_CR_DBI_CS_STRETCH;
90 }
91
92 /* enable command phase */
93 regval |= DBI_CR_DBI_CMD_EN;
94 putreg32(regval, reg_base + DBI_CONFIG_OFFSET);
95
96 /* clock cfg */
97 /* integer frequency segmentation by rounding */
98 div = (bflb_clk_get_peripheral_clock(BFLB_DEVICE_TYPE_DBI, dev->idx) / 2 * 10 / config->clk_freq_hz + 5) / 10;
99 div = (div) ? (div - 1) : 0;
100 div = (div > 0xff) ? 0xff : div;
101 regval = 0;
102 regval |= div << DBI_CR_DBI_PRD_S_SHIFT;
103 regval |= div << DBI_CR_DBI_PRD_I_SHIFT;
104 regval |= div << DBI_CR_DBI_PRD_D_PH_0_SHIFT;
105 regval |= div << DBI_CR_DBI_PRD_D_PH_1_SHIFT;
106 putreg32(regval, reg_base + DBI_PRD_OFFSET);
107
108 /* dbi output pixel format cfg */
109 regval = getreg32(reg_base + DBI_PIX_CNT_OFFSET);
110 if (config->pixel_output_format == DBI_PIXEL_OUTPUT_FORMAT_RGB_565) {
111 regval &= ~DBI_CR_DBI_PIX_FORMAT;
112 } else {
113 regval |= DBI_CR_DBI_PIX_FORMAT;
114 }
115 putreg32(regval, reg_base + DBI_PIX_CNT_OFFSET);
116
117 /* dbi input pixel format */
118 regval = getreg32(reg_base + DBI_FIFO_CONFIG_0_OFFSET);
119 regval &= ~DBI_FIFO_FORMAT_MASK;
120 regval |= config->pixel_input_format << DBI_FIFO_FORMAT_SHIFT;
121
122 /* clear fifo */
123 regval |= DBI_TX_FIFO_CLR;
124
125 /* disable YUV mode */
126 regval &= ~DBI_FIFO_YUV_MODE;
127
128 /* disable dma mode */
129 regval &= ~DBI_DMA_TX_EN;
130 putreg32(regval, reg_base + DBI_FIFO_CONFIG_0_OFFSET);
131
132 /* tx fifo threshold cfg */
133 regval = getreg32(reg_base + DBI_FIFO_CONFIG_1_OFFSET);
134 regval &= ~DBI_TX_FIFO_TH_MASK;
135 regval |= (config->tx_fifo_threshold << DBI_TX_FIFO_TH_SHIFT) & DBI_TX_FIFO_TH_MASK;
136 putreg32(regval, reg_base + DBI_FIFO_CONFIG_1_OFFSET);
137
138 #if (DBI_QSPI_SUPPORT)
139 regval = getreg32(reg_base + DBI_QSPI_CONFIG_OFFSET);
140
141 /* cmd wire */
142 if (config->cmd_wire_mode) {
143 regval |= DBI_CR_QSPI_CMD_4B;
144 } else {
145 regval &= ~DBI_CR_QSPI_CMD_4B;
146 }
147
148 /* address wire */
149 if (config->addr_wire_mode) {
150 regval |= DBI_CR_QSPI_ADR_4B;
151 } else {
152 regval &= ~DBI_CR_QSPI_ADR_4B;
153 }
154
155 /* data/pixel wire */
156 if (config->data_wire_mode) {
157 regval |= DBI_CR_QSPI_DAT_4B;
158 } else {
159 regval &= ~DBI_CR_QSPI_DAT_4B;
160 }
161
162 putreg32(regval, reg_base + DBI_QSPI_CONFIG_OFFSET);
163 #endif
164
165 #if (DBI_YUV_SUPPORT)
166 /* YUV to RGB parameter list. */
167 regval = 0;
168 regval |= (YUV_PRE_OFFSET_0 << DBI_CR_Y2R_PRE_0_SHIFT) & DBI_CR_Y2R_PRE_0_MASK;
169 regval |= (YUV_PRE_OFFSET_1 << DBI_CR_Y2R_PRE_1_SHIFT) & DBI_CR_Y2R_PRE_1_MASK;
170 regval |= (YUV_PRE_OFFSET_2 << DBI_CR_Y2R_PRE_2_SHIFT) & DBI_CR_Y2R_PRE_2_MASK;
171 regval |= DBI_CR_Y2R_EN;
172 putreg32(regval, reg_base + DBI_YUV_RGB_CONFIG_0_OFFSET);
173
174 regval = 0;
175 regval |= (YUV_POST_OFFSET_0 << DBI_CR_Y2R_POS_0_SHIFT) & DBI_CR_Y2R_POS_0_MASK;
176 regval |= (YUV_POST_OFFSET_1 << DBI_CR_Y2R_POS_1_SHIFT) & DBI_CR_Y2R_POS_1_MASK;
177 regval |= (YUV_POST_OFFSET_2 << DBI_CR_Y2R_POS_2_SHIFT) & DBI_CR_Y2R_POS_2_MASK;
178 putreg32(regval, reg_base + DBI_YUV_RGB_CONFIG_1_OFFSET);
179
180 regval = 0;
181 regval |= (YUV_MATRIX00 << DBI_CR_Y2R_MTX_00_SHIFT) & DBI_CR_Y2R_MTX_00_MASK;
182 regval |= (YUV_MATRIX01 << DBI_CR_Y2R_MTX_01_SHIFT) & DBI_CR_Y2R_MTX_01_MASK;
183 regval |= ((YUV_MATRIX02 & 0x0ff) << DBI_CR_Y2R_MTX_02_L_SHIFT) & DBI_CR_Y2R_MTX_02_L_MASK;
184 putreg32(regval, reg_base + DBI_YUV_RGB_CONFIG_2_OFFSET);
185
186 regval = 0;
187 regval |= (((YUV_MATRIX02 & 0xf00) >> 8) << DBI_CR_Y2R_MTX_02_U_SHIFT) & DBI_CR_Y2R_MTX_02_U_MASK;
188 regval |= (YUV_MATRIX10 << DBI_CR_Y2R_MTX_10_SHIFT) & DBI_CR_Y2R_MTX_10_MASK;
189 regval |= (YUV_MATRIX11 << DBI_CR_Y2R_MTX_11_SHIFT) & DBI_CR_Y2R_MTX_11_MASK;
190 regval |= ((YUV_MATRIX12 & 0x00f) << DBI_CR_Y2R_MTX_12_L_SHIFT) & DBI_CR_Y2R_MTX_12_L_MASK;
191 putreg32(regval, reg_base + DBI_YUV_RGB_CONFIG_3_OFFSET);
192
193 regval = 0;
194 regval |= (((YUV_MATRIX12 & 0xff0) >> 4) << DBI_CR_Y2R_MTX_12_U_SHIFT) & DBI_CR_Y2R_MTX_12_U_MASK;
195 regval |= (YUV_MATRIX20 << DBI_CR_Y2R_MTX_20_SHIFT) & DBI_CR_Y2R_MTX_20_MASK;
196 regval |= (YUV_MATRIX21 << DBI_CR_Y2R_MTX_21_SHIFT) & DBI_CR_Y2R_MTX_21_MASK;
197 putreg32(regval, reg_base + DBI_YUV_RGB_CONFIG_4_OFFSET);
198
199 regval = 0;
200 regval |= (YUV_MATRIX22 << DBI_CR_Y2R_MTX_22_SHIFT) & DBI_CR_Y2R_MTX_22_MASK;
201 putreg32(regval, reg_base + DBI_YUV_RGB_CONFIG_5_OFFSET);
202 #endif
203 }
204
bflb_dbi_deinit(struct bflb_device_s * dev)205 void bflb_dbi_deinit(struct bflb_device_s *dev)
206 {
207 uint32_t reg_base;
208 uint32_t regval;
209
210 reg_base = dev->reg_base;
211
212 /* disable DBI transaction */
213 regval = getreg32(reg_base + DBI_CONFIG_OFFSET);
214 regval &= ~DBI_CR_DBI_EN;
215 putreg32(regval, reg_base + DBI_CONFIG_OFFSET);
216
217 /* clear fifo */
218 regval = getreg32(reg_base + DBI_FIFO_CONFIG_0_OFFSET);
219 regval |= DBI_TX_FIFO_CLR;
220 putreg32(regval, reg_base + DBI_FIFO_CONFIG_0_OFFSET);
221 }
222
223 #if DBI_QSPI_SUPPORT
bflb_dbi_qspi_set_addr(struct bflb_device_s * dev,uint8_t addr_byte_size,uint32_t addr_val)224 void bflb_dbi_qspi_set_addr(struct bflb_device_s *dev, uint8_t addr_byte_size, uint32_t addr_val)
225 {
226 uint32_t reg_base;
227 uint32_t regval;
228
229 reg_base = dev->reg_base;
230
231 addr_byte_size = addr_byte_size ? (addr_byte_size - 1) : addr_byte_size;
232
233 /* set address size */
234 regval = getreg32(reg_base + DBI_QSPI_CONFIG_OFFSET);
235 regval &= ~DBI_CR_QSPI_ADR_BC_MASK;
236 regval |= (addr_byte_size << DBI_CR_QSPI_ADR_BC_SHIFT) & DBI_CR_QSPI_ADR_BC_MASK;
237 putreg32(regval, reg_base + DBI_QSPI_CONFIG_OFFSET);
238
239 /* set address value */
240 putreg32(addr_val, reg_base + DBI_QSPI_ADR_OFFSET);
241 }
242 #endif
243
bflb_dbi_fill_fifo(struct bflb_device_s * dev,uint32_t words_cnt,uint32_t * data_buff)244 static void bflb_dbi_fill_fifo(struct bflb_device_s *dev, uint32_t words_cnt, uint32_t *data_buff)
245 {
246 uint32_t reg_base;
247 uint32_t regval;
248 uint32_t fifo_cnt;
249
250 reg_base = dev->reg_base;
251
252 for (; words_cnt > 0;) {
253 /* get fifo available count */
254 regval = getreg32(reg_base + DBI_FIFO_CONFIG_1_OFFSET);
255 fifo_cnt = (regval & DBI_TX_FIFO_CNT_MASK) >> DBI_TX_FIFO_CNT_SHIFT;
256
257 if (fifo_cnt) {
258 fifo_cnt = (fifo_cnt > words_cnt) ? words_cnt : fifo_cnt;
259 words_cnt -= fifo_cnt;
260 } else {
261 continue;
262 }
263
264 /* fill fifo */
265 for (; fifo_cnt > 0; fifo_cnt--, data_buff++) {
266 putreg32(*data_buff, reg_base + DBI_FIFO_WDATA_OFFSET);
267 }
268 }
269 }
270
bflb_dbi_get_words_cnt_form_pixel(struct bflb_device_s * dev,uint32_t pixle_cnt)271 static uint32_t bflb_dbi_get_words_cnt_form_pixel(struct bflb_device_s *dev, uint32_t pixle_cnt)
272 {
273 uint32_t reg_base;
274 uint32_t regval;
275 uint32_t words_cnt;
276 uint8_t pixel_input_format;
277
278 reg_base = dev->reg_base;
279
280 /* get fifo input pixel_format */
281 regval = getreg32(reg_base + DBI_FIFO_CONFIG_0_OFFSET);
282 pixel_input_format = (regval & DBI_FIFO_FORMAT_MASK) >> DBI_FIFO_FORMAT_SHIFT;
283
284 switch (pixel_input_format) {
285 /* 32-bit/pixel format list */
286 case DBI_PIXEL_INPUT_FORMAT_NBGR_8888:
287 case DBI_PIXEL_INPUT_FORMAT_NRGB_8888:
288 case DBI_PIXEL_INPUT_FORMAT_BGRN_8888:
289 case DBI_PIXEL_INPUT_FORMAT_RGBN_8888:
290 words_cnt = pixle_cnt;
291 break;
292
293 /* 24-bit/pixel format list */
294 case DBI_PIXEL_INPUT_FORMAT_RGB_888:
295 case DBI_PIXEL_INPUT_FORMAT_BGR_888:
296 words_cnt = (pixle_cnt * 3 + 3) / 4;
297 break;
298
299 /* 16-bit/pixel format list */
300 case DBI_PIXEL_INPUT_FORMAT_BGR_565:
301 case DBI_PIXEL_INPUT_FORMAT_RGB_565:
302 words_cnt = (pixle_cnt + 1) / 2;
303 break;
304
305 default:
306 words_cnt = 0;
307 break;
308 }
309
310 return words_cnt;
311 }
312
bflb_dbi_send_cmd_data(struct bflb_device_s * dev,uint8_t cmd,uint8_t data_len,uint8_t * data_buff)313 int bflb_dbi_send_cmd_data(struct bflb_device_s *dev, uint8_t cmd, uint8_t data_len, uint8_t *data_buff)
314 {
315 uint32_t reg_base;
316 uint32_t regval;
317
318 reg_base = dev->reg_base;
319
320 /* null */
321 if (data_len && data_buff == NULL) {
322 return 0;
323 }
324
325 /* disable DBI transaction */
326 regval = getreg32(reg_base + DBI_CONFIG_OFFSET);
327 regval &= ~DBI_CR_DBI_EN;
328 putreg32(regval, reg_base + DBI_CONFIG_OFFSET);
329
330 if (((regval & DBI_CR_DBI_CMD_EN) == 0) && (data_len == 0)) {
331 /* There is no data or command phase, nothing to do */
332 return 0;
333 }
334
335 /* normal data mode */
336 regval &= ~DBI_CR_DBI_DAT_TP;
337
338 /* write mode */
339 regval |= DBI_CR_DBI_DAT_WR;
340
341 /* set data len */
342 if (data_len) {
343 regval |= DBI_CR_DBI_DAT_EN;
344 regval &= ~DBI_CR_DBI_DAT_BC_MASK;
345 regval |= ((data_len - 1) << DBI_CR_DBI_DAT_BC_SHIFT) & DBI_CR_DBI_DAT_BC_MASK;
346 } else {
347 regval &= ~DBI_CR_DBI_DAT_EN;
348 }
349 putreg32(regval, reg_base + DBI_CONFIG_OFFSET);
350
351 /* set cmd */
352 if (regval & DBI_CR_DBI_CMD_EN) {
353 regval = getreg32(reg_base + DBI_CMD_OFFSET);
354 regval &= ~DBI_CR_DBI_CMD_MASK;
355 regval |= cmd << DBI_CR_DBI_CMD_SHIFT;
356 putreg32(regval, reg_base + DBI_CMD_OFFSET);
357 }
358
359 /* clear fifo */
360 regval = getreg32(reg_base + DBI_FIFO_CONFIG_0_OFFSET);
361 regval |= DBI_TX_FIFO_CLR;
362 putreg32(regval, reg_base + DBI_FIFO_CONFIG_0_OFFSET);
363
364 /* clear complete interrupt */
365 regval = getreg32(reg_base + DBI_INT_STS_OFFSET);
366 regval |= DBI_CR_DBI_END_CLR;
367 putreg32(regval, reg_base + DBI_INT_STS_OFFSET);
368
369 /* first fill some data into the fifo */
370 if (data_len) {
371 if (data_len <= SPI_FIFO_NUM_MAX * 4) {
372 bflb_dbi_fill_fifo(dev, (data_len + 3) / 4, (uint32_t *)data_buff);
373 data_len = 0;
374 } else {
375 bflb_dbi_fill_fifo(dev, SPI_FIFO_NUM_MAX, (uint32_t *)data_buff);
376 data_len -= SPI_FIFO_NUM_MAX * 4;
377 }
378 }
379
380 /* trigger the transaction */
381 regval = getreg32(reg_base + DBI_CONFIG_OFFSET);
382 regval |= DBI_CR_DBI_EN;
383 putreg32(regval, reg_base + DBI_CONFIG_OFFSET);
384
385 /* Fill the rest of the data into the fifo */
386 if (data_len) {
387 bflb_dbi_fill_fifo(dev, (data_len + 3) / 4, (uint32_t *)data_buff);
388 }
389
390 /* Wait transfer complete */
391 do {
392 regval = getreg32(reg_base + DBI_INT_STS_OFFSET);
393 } while ((regval & DBI_END_INT) == 0);
394
395 /* clear end int */
396 regval |= DBI_CR_DBI_END_CLR;
397 putreg32(regval, reg_base + DBI_INT_STS_OFFSET);
398
399 return 0;
400 }
401
bflb_dbi_send_cmd_read_data(struct bflb_device_s * dev,uint8_t cmd,uint8_t data_len,uint8_t * data_buff)402 int bflb_dbi_send_cmd_read_data(struct bflb_device_s *dev, uint8_t cmd, uint8_t data_len, uint8_t *data_buff)
403 {
404 uint32_t reg_base;
405 uint32_t regval;
406
407 reg_base = dev->reg_base;
408
409 /* disable DBI transaction */
410 regval = getreg32(reg_base + DBI_CONFIG_OFFSET);
411 regval &= ~DBI_CR_DBI_EN;
412 putreg32(regval, reg_base + DBI_CONFIG_OFFSET);
413
414 if (((regval & DBI_CR_DBI_CMD_EN) == 0) && (data_len == 0)) {
415 /* There is no data or command phase, nothing to do */
416 return 0;
417 }
418
419 /* normal data mode */
420 regval &= ~DBI_CR_DBI_DAT_TP;
421
422 /* read mode */
423 regval &= ~DBI_CR_DBI_DAT_WR;
424
425 /* set data len */
426 if (data_len) {
427 regval |= DBI_CR_DBI_DAT_EN;
428 regval &= ~DBI_CR_DBI_DAT_BC_MASK;
429 regval |= ((data_len - 1) << DBI_CR_DBI_DAT_BC_SHIFT) & DBI_CR_DBI_DAT_BC_MASK;
430 } else {
431 regval &= ~DBI_CR_DBI_DAT_EN;
432 }
433 putreg32(regval, reg_base + DBI_CONFIG_OFFSET);
434
435 /* set cmd */
436 if (regval & DBI_CR_DBI_CMD_EN) {
437 regval = getreg32(reg_base + DBI_CMD_OFFSET);
438 regval &= ~DBI_CR_DBI_CMD_MASK;
439 regval |= cmd << DBI_CR_DBI_CMD_SHIFT;
440 putreg32(regval, reg_base + DBI_CMD_OFFSET);
441 }
442
443 /* clear fifo */
444 regval = getreg32(reg_base + DBI_FIFO_CONFIG_0_OFFSET);
445 regval |= DBI_TX_FIFO_CLR;
446 putreg32(regval, reg_base + DBI_FIFO_CONFIG_0_OFFSET);
447
448 /* clear complete interrupt */
449 regval = getreg32(reg_base + DBI_INT_STS_OFFSET);
450 regval |= DBI_CR_DBI_END_CLR;
451 putreg32(regval, reg_base + DBI_INT_STS_OFFSET);
452
453 /* trigger the transaction */
454 regval = getreg32(reg_base + DBI_CONFIG_OFFSET);
455 regval |= DBI_CR_DBI_EN;
456 putreg32(regval, reg_base + DBI_CONFIG_OFFSET);
457
458 /* Wait transfer complete */
459 do {
460 regval = getreg32(reg_base + DBI_INT_STS_OFFSET);
461 } while ((regval & DBI_END_INT) == 0);
462
463 /* clear end int */
464 regval |= DBI_CR_DBI_END_CLR;
465 putreg32(regval, reg_base + DBI_INT_STS_OFFSET);
466
467 /* Null pointer error */
468 if (data_buff == NULL) {
469 return 0;
470 }
471
472 /* copy data to buff */
473 regval = getreg32(reg_base + DBI_RDATA_0_OFFSET);
474 for (uint8_t i = 0; (data_len > 0) && (i < 4); i++, data_len--) {
475 *data_buff = (uint8_t)regval;
476 data_buff++;
477 regval >>= 8;
478 }
479 regval = getreg32(reg_base + DBI_RDATA_1_OFFSET);
480 for (uint8_t i = 0; (data_len > 0) && (i < 4); i++, data_len--) {
481 *data_buff = (uint8_t)regval;
482 data_buff++;
483 regval >>= 8;
484 }
485
486 return 0;
487 }
488
bflb_dbi_send_cmd_pixel(struct bflb_device_s * dev,uint8_t cmd,uint32_t pixel_cnt,void * pixel_buff)489 int bflb_dbi_send_cmd_pixel(struct bflb_device_s *dev, uint8_t cmd, uint32_t pixel_cnt, void *pixel_buff)
490 {
491 uint32_t reg_base;
492 uint32_t regval;
493
494 reg_base = dev->reg_base;
495
496 /* disable DBI transaction */
497 regval = getreg32(reg_base + DBI_CONFIG_OFFSET);
498 regval &= ~DBI_CR_DBI_EN;
499 putreg32(regval, reg_base + DBI_CONFIG_OFFSET);
500
501 if (((regval & DBI_CR_DBI_CMD_EN) == 0) && (pixel_cnt == 0)) {
502 /* There is no data or command phase, nothing to do */
503 return 0;
504 }
505
506 /* pixel mode */
507 regval |= DBI_CR_DBI_DAT_TP;
508
509 /* write mode */
510 regval |= DBI_CR_DBI_DAT_WR;
511
512 /* pixle data phase enable */
513 if (pixel_cnt) {
514 regval |= DBI_CR_DBI_DAT_EN;
515 } else {
516 regval &= ~DBI_CR_DBI_DAT_EN;
517 }
518 putreg32(regval, reg_base + DBI_CONFIG_OFFSET);
519
520 /* set cmd */
521 if (regval & DBI_CR_DBI_CMD_EN) {
522 regval = getreg32(reg_base + DBI_CMD_OFFSET);
523 regval &= ~DBI_CR_DBI_CMD_MASK;
524 regval |= cmd << DBI_CR_DBI_CMD_SHIFT;
525 putreg32(regval, reg_base + DBI_CMD_OFFSET);
526 }
527
528 /* pixel cnt */
529 if (pixel_cnt) {
530 regval = getreg32(reg_base + DBI_PIX_CNT_OFFSET);
531 regval &= ~DBI_CR_DBI_PIX_CNT_MASK;
532 regval |= ((pixel_cnt - 1) << DBI_CR_DBI_PIX_CNT_SHIFT) & DBI_CR_DBI_PIX_CNT_MASK;
533 putreg32(regval, reg_base + DBI_PIX_CNT_OFFSET);
534 }
535
536 /* clear fifo */
537 regval = getreg32(reg_base + DBI_FIFO_CONFIG_0_OFFSET);
538 regval |= DBI_TX_FIFO_CLR;
539 putreg32(regval, reg_base + DBI_FIFO_CONFIG_0_OFFSET);
540
541 /* clear complete interrupt */
542 regval = getreg32(reg_base + DBI_INT_STS_OFFSET);
543 regval |= DBI_CR_DBI_END_CLR;
544 putreg32(regval, reg_base + DBI_INT_STS_OFFSET);
545
546 /* trigger the transaction */
547 regval = getreg32(reg_base + DBI_CONFIG_OFFSET);
548 regval |= DBI_CR_DBI_EN;
549 putreg32(regval, reg_base + DBI_CONFIG_OFFSET);
550
551 /* No need to fill in fifo, for DMA mode */
552 if (pixel_buff == NULL) {
553 return 0;
554 }
555
556 /* fill the data into the fifo, can only be used in non-DMA mode */
557 bflb_dbi_fill_fifo(dev, bflb_dbi_get_words_cnt_form_pixel(dev, pixel_cnt), (uint32_t *)pixel_buff);
558
559 /* Wait transfer complete */
560 do {
561 regval = getreg32(reg_base + DBI_INT_STS_OFFSET);
562 } while ((regval & DBI_END_INT) == 0);
563
564 /* clear end int */
565 regval |= DBI_CR_DBI_END_CLR;
566 putreg32(regval, reg_base + DBI_INT_STS_OFFSET);
567
568 return 0;
569 }
570
bflb_dbi_link_txdma(struct bflb_device_s * dev,bool enable)571 void bflb_dbi_link_txdma(struct bflb_device_s *dev, bool enable)
572 {
573 uint32_t reg_base;
574 uint32_t regval;
575
576 reg_base = dev->reg_base;
577
578 regval = getreg32(reg_base + DBI_FIFO_CONFIG_0_OFFSET);
579 if (enable) {
580 regval |= DBI_DMA_TX_EN;
581 } else {
582 regval &= ~DBI_DMA_TX_EN;
583 }
584 putreg32(regval, reg_base + DBI_FIFO_CONFIG_0_OFFSET);
585 }
586
bflb_dbi_txint_mask(struct bflb_device_s * dev,bool mask)587 void bflb_dbi_txint_mask(struct bflb_device_s *dev, bool mask)
588 {
589 uint32_t reg_base;
590 uint32_t regval;
591
592 reg_base = dev->reg_base;
593
594 regval = getreg32(reg_base + DBI_INT_STS_OFFSET);
595 if (mask) {
596 regval |= DBI_CR_DBI_TXF_MASK;
597 } else {
598 regval &= ~DBI_CR_DBI_TXF_MASK;
599 }
600 putreg32(regval, reg_base + DBI_INT_STS_OFFSET);
601 }
602
bflb_dbi_tcint_mask(struct bflb_device_s * dev,bool mask)603 void bflb_dbi_tcint_mask(struct bflb_device_s *dev, bool mask)
604 {
605 uint32_t reg_base;
606 uint32_t regval;
607
608 reg_base = dev->reg_base;
609
610 regval = getreg32(reg_base + DBI_INT_STS_OFFSET);
611 if (mask) {
612 regval |= DBI_CR_DBI_END_MASK;
613 } else {
614 regval &= ~DBI_CR_DBI_END_MASK;
615 }
616 putreg32(regval, reg_base + DBI_INT_STS_OFFSET);
617 }
618
bflb_dbi_errint_mask(struct bflb_device_s * dev,bool mask)619 void bflb_dbi_errint_mask(struct bflb_device_s *dev, bool mask)
620 {
621 uint32_t reg_base;
622 uint32_t regval;
623
624 reg_base = dev->reg_base;
625
626 regval = getreg32(reg_base + DBI_INT_STS_OFFSET);
627 if (mask) {
628 regval |= DBI_CR_DBI_FER_MASK;
629 } else {
630 regval &= ~DBI_CR_DBI_FER_MASK;
631 }
632 putreg32(regval, reg_base + DBI_INT_STS_OFFSET);
633 }
634
bflb_dbi_get_intstatus(struct bflb_device_s * dev)635 uint32_t bflb_dbi_get_intstatus(struct bflb_device_s *dev)
636 {
637 uint32_t reg_base;
638 uint32_t regval;
639 uint32_t int_sts;
640
641 reg_base = dev->reg_base;
642 int_sts = 0;
643
644 regval = getreg32(reg_base + DBI_INT_STS_OFFSET);
645
646 /* transfer completion interrupt */
647 if (regval & DBI_END_INT) {
648 int_sts |= DBI_INTSTS_TC;
649 }
650
651 /* fifo threshold interrupt */
652 if (regval & DBI_TXF_INT) {
653 int_sts |= SPI_INTSTS_TX_FIFO;
654 }
655
656 /* fifo error (underflow or overflow) interrupt */
657 if (regval & DBI_FER_INT) {
658 int_sts |= SPI_INTSTS_FIFO_ERR;
659 }
660
661 return int_sts;
662 }
663
bflb_dbi_int_clear(struct bflb_device_s * dev,uint32_t int_clear)664 void bflb_dbi_int_clear(struct bflb_device_s *dev, uint32_t int_clear)
665 {
666 uint32_t reg_base;
667 uint32_t regval;
668
669 reg_base = dev->reg_base;
670
671 regval = getreg32(reg_base + DBI_INT_STS_OFFSET);
672
673 /* transfer completion interrupt */
674 if (int_clear & DBI_INTCLR_TC) {
675 regval |= DBI_CR_DBI_END_CLR;
676 }
677
678 putreg32(regval, reg_base + DBI_INT_STS_OFFSET);
679 }
680
bflb_dbi_feature_control(struct bflb_device_s * dev,int cmd,size_t arg)681 int bflb_dbi_feature_control(struct bflb_device_s *dev, int cmd, size_t arg)
682 {
683 int ret = 0;
684 uint32_t reg_base;
685 uint32_t regval;
686
687 reg_base = dev->reg_base;
688
689 switch (cmd) {
690 case DBI_CMD_CLEAR_TX_FIFO:
691 /* clear fifo */
692 regval = getreg32(reg_base + DBI_FIFO_CONFIG_0_OFFSET);
693 regval |= DBI_TX_FIFO_CLR;
694 putreg32(regval, reg_base + DBI_FIFO_CONFIG_0_OFFSET);
695 break;
696
697 case DBI_CMD_GET_TX_FIFO_CNT:
698 /* get fifo available count */
699 regval = getreg32(reg_base + DBI_FIFO_CONFIG_1_OFFSET);
700 ret = (regval & DBI_TX_FIFO_CNT_MASK) >> DBI_TX_FIFO_CNT_SHIFT;
701 break;
702
703 case DBI_CMD_MASK_CMD_PHASE:
704 /* mask command phase, arg use true or false,
705 true: no command phase, false: command will be sent
706 don't-care if QSPI mode is selected (command always sent)
707 */
708 regval = getreg32(reg_base + DBI_CONFIG_OFFSET);
709 #if (DBI_QSPI_SUPPORT)
710 /* the setting is not valid for the qspi mode */
711 if ((regval & DBI_CR_DBI_SEL_MASK) >> DBI_CR_DBI_SEL_SHIFT == DBI_MODE_EX_QSPI) {
712 break;
713 }
714 #endif
715 if (arg) {
716 regval &= ~DBI_CR_DBI_CMD_EN;
717 } else {
718 regval |= DBI_CR_DBI_CMD_EN;
719 }
720 putreg32(regval, reg_base + DBI_CONFIG_OFFSET);
721 break;
722
723 case DBI_CMD_CS_CONTINUE:
724 /* set CS continue mode, arg use true or false */
725 regval = getreg32(reg_base + DBI_CONFIG_OFFSET);
726 if (arg) {
727 regval |= DBI_CR_DBI_CONT_EN;
728 } else {
729 regval &= ~DBI_CR_DBI_CONT_EN;
730 }
731 putreg32(regval, reg_base + DBI_CONFIG_OFFSET);
732 break;
733
734 case DBI_CMD_SET_DUMMY_CNT:
735 /* set dummy cycle(s) between command phase and data phase
736 arg range: 0 ~ 16,
737 don't-care if QSPI mode is selected (no dummy cycle)
738 */
739 regval = getreg32(reg_base + DBI_CONFIG_OFFSET);
740 #if (DBI_QSPI_SUPPORT)
741 /* the setting is not valid for the qspi mode */
742 if ((regval & DBI_CR_DBI_SEL_MASK) >> DBI_CR_DBI_SEL_SHIFT == DBI_MODE_EX_QSPI) {
743 break;
744 }
745 #endif
746 if (arg) {
747 regval |= DBI_CR_DBI_DMY_EN;
748 regval &= ~DBI_CR_DBI_DMY_CNT_MASK;
749 regval |= ((arg - 1) << DBI_CR_DBI_DMY_CNT_SHIFT) & DBI_CR_DBI_DMY_CNT_MASK;
750 } else {
751 regval &= ~DBI_CR_DBI_DMY_EN;
752 }
753 putreg32(regval, reg_base + DBI_CONFIG_OFFSET);
754 break;
755
756 case DBI_CMD_GET_SIZE_OF_PIXEL_CNT:
757 /* gets the pixel_data size(byte), arg: pixel number */
758 ret = bflb_dbi_get_words_cnt_form_pixel(dev, arg) * 4;
759 break;
760
761 case DBI_CMD_INPUT_PIXEL_FORMAT:
762 /* dbi input pixel format, arg use @ref DBI_PIXEL_INPUT_FORMAT */
763 regval = getreg32(reg_base + DBI_FIFO_CONFIG_0_OFFSET);
764 regval &= ~DBI_FIFO_FORMAT_MASK;
765 regval |= (arg << DBI_FIFO_FORMAT_SHIFT) & DBI_FIFO_FORMAT_MASK;
766 putreg32(regval, reg_base + DBI_FIFO_CONFIG_0_OFFSET);
767 break;
768
769 case DBI_CMD_OUTPUT_PIXEL_FORMAT:
770 /* dbi output pixel format, arg use @ref DBI_PIXEL_OUTPUT_FORMAT */
771 regval = getreg32(reg_base + DBI_PIX_CNT_OFFSET);
772 if (arg == DBI_PIXEL_OUTPUT_FORMAT_RGB_565) {
773 regval &= ~DBI_CR_DBI_PIX_FORMAT;
774 } else if (arg == DBI_PIXEL_OUTPUT_FORMAT_RGB_888) {
775 regval |= DBI_CR_DBI_PIX_FORMAT;
776 }
777 putreg32(regval, reg_base + DBI_PIX_CNT_OFFSET);
778 break;
779
780 #if (DBI_YUV_SUPPORT)
781 case DBI_CMD_YUV_TO_RGB_ENABLE:
782 /* yuv to rgb cfg, arg use true or false */
783 regval = getreg32(reg_base + DBI_FIFO_CONFIG_0_OFFSET);
784 if (arg) {
785 regval |= DBI_FIFO_YUV_MODE;
786 } else {
787 regval &= ~DBI_FIFO_YUV_MODE;
788 }
789 putreg32(regval, reg_base + DBI_FIFO_CONFIG_0_OFFSET);
790 break;
791 #endif
792
793 default:
794 ret = -EPERM;
795 break;
796 }
797
798 return ret;
799 }
800