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