22
22
#include <fsl_inputmux.h>
23
23
#include <fsl_smartdma.h>
24
24
#endif
25
+ #ifdef CONFIG_MIPI_DSI_MCUX_NXP_DCNANO_LCDIF
26
+ #include <zephyr/drivers/mipi_dbi.h>
27
+ #endif
25
28
26
29
#include <soc.h>
27
30
28
31
LOG_MODULE_REGISTER (dsi_mcux_host , CONFIG_MIPI_DSI_LOG_LEVEL );
29
32
33
+ #if CONFIG_MIPI_DSI_MCUX_NXP_DCNANO_LCDIF
34
+ #define MIPI_DSI_MAX_PAYLOAD_SIZE 0xFFFF
35
+ #endif
36
+
30
37
struct mcux_mipi_dsi_config {
31
38
MIPI_DSI_HOST_Type * base ;
32
39
dsi_dpi_config_t dpi_config ;
@@ -44,6 +51,9 @@ struct mcux_mipi_dsi_config {
44
51
#else
45
52
void (* irq_config_func )(const struct device * dev );
46
53
#endif
54
+ #ifdef CONFIG_MIPI_DSI_MCUX_NXP_DCNANO_LCDIF
55
+ const struct device * mipi_dbi ;
56
+ #endif
47
57
};
48
58
49
59
struct mcux_mipi_dsi_data {
@@ -60,6 +70,11 @@ struct mcux_mipi_dsi_data {
60
70
uint32_t smartdma_stack [32 ];
61
71
uint8_t dma_slot ;
62
72
#endif
73
+ #ifdef CONFIG_MIPI_DSI_MCUX_NXP_DCNANO_LCDIF
74
+ uint32_t width ;
75
+ uint32_t height ;
76
+ uint8_t src_bytes_per_pixel ;
77
+ #endif
63
78
};
64
79
65
80
@@ -196,7 +211,111 @@ static void dsi_transfer_complete(MIPI_DSI_HOST_Type *base,
196
211
k_sem_give (& data -> transfer_sem );
197
212
}
198
213
214
+ #ifdef CONFIG_MIPI_DSI_MCUX_NXP_DCNANO_LCDIF
215
+ static status_t dsi_mcux_dcnano_transfer (const struct device * dev , uint8_t channel ,
216
+ struct mipi_dsi_msg * msg , dsi_transfer_t * dsi_xfer )
217
+ {
218
+ const struct mcux_mipi_dsi_config * config = dev -> config ;
219
+ struct mcux_mipi_dsi_data * data = dev -> data ;
220
+ uint8_t * tx_buf = (uint8_t * )msg -> tx_buf ;
221
+
222
+ /* Record the bpp, width, height of the buffer according to command. They are
223
+ * necessary to configure the DCNano DBI in the following memory write.
224
+ */
225
+ if (channel == 0U ) {
226
+ if (msg -> cmd == MIPI_DCS_SET_PIXEL_FORMAT ) {
227
+ if (tx_buf [0 ] == MIPI_DCS_PIXEL_FORMAT_16BIT ) {
228
+ data -> src_bytes_per_pixel = 2U ;
229
+ } else {
230
+ data -> src_bytes_per_pixel = 3U ;
231
+ }
232
+ } else if (msg -> cmd == MIPI_DCS_SET_COLUMN_ADDRESS ) {
233
+ data -> width = ((tx_buf [2 ] << 8U ) | tx_buf [3 ]) -
234
+ ((tx_buf [0 ] << 8U ) | tx_buf [1 ]) + 1U ;
235
+ } else if (msg -> cmd == MIPI_DCS_SET_PAGE_ADDRESS ) {
236
+ data -> height = ((tx_buf [2 ] << 8U ) | tx_buf [3 ]) -
237
+ ((tx_buf [0 ] << 8U ) | tx_buf [1 ]) + 1U ;
238
+ }
239
+ }
240
+
241
+ /* When the DSI channel is 0, for and only for DCS long write like
242
+ * MIPI_DCS_WRITE_MEMORY_START or MIPI_DCS_WRITE_MEMORY_CONTINUE, we can
243
+ * use DCNano DBI to speed up the frame buffer write. The DCS command and the
244
+ * following data are all handled by DCNano DBI, while on MIPI-DSI side special
245
+ * handling shall be done so that it can be properly used with DCNano DBI,
246
+ * like MIPI DBI FIFO configuration of send level and payload size, etc.
247
+ */
248
+ if (((msg -> cmd == MIPI_DCS_WRITE_MEMORY_START ) ||
249
+ (msg -> cmd == MIPI_DCS_WRITE_MEMORY_CONTINUE )) && (channel == 0U )) {
250
+ enum display_pixel_format pixfmt ;
251
+ struct mipi_dbi_config dbi_config = {
252
+ .mode = MIPI_DBI_MODE_8080_BUS_16_BIT ,
253
+ };
254
+ struct display_buffer_descriptor desc = {
255
+ .width = data -> width ,
256
+ .height = data -> height ,
257
+ .pitch = data -> width ,
258
+ };
259
+
260
+ /* Every time buffer 64 pixels first before the transfer. */
261
+ DSI_SetDbiPixelFifoSendLevel (config -> base , 64U );
262
+
263
+ /* Set payload size. */
264
+ if ((desc .height * desc .width * data -> src_bytes_per_pixel ) >
265
+ MIPI_DSI_MAX_PAYLOAD_SIZE ) {
266
+ desc .height = MIPI_DSI_MAX_PAYLOAD_SIZE /
267
+ (desc .width * data -> src_bytes_per_pixel );
268
+ }
269
+
270
+ DSI_SetDbiPixelPayloadSize (config -> base ,
271
+ (desc .height * desc .width * data -> src_bytes_per_pixel ) >> 1U );
272
+
273
+ /* Get the source buffer pixel format and DBI output format
274
+ * Currently only support RGB565 and RGB888 when using DCNano DBI.
275
+ */
276
+ switch (data -> src_bytes_per_pixel ) {
277
+ case 2 :
278
+ pixfmt = PIXEL_FORMAT_RGB_565 ;
279
+ dbi_config .mode |= MIPI_DBI_MODE_RGB565 ;
280
+ DSI_SetDbiPixelFormat (config -> base , kDSI_DbiRGB565 );
281
+ break ;
282
+ case 3 :
283
+ pixfmt = PIXEL_FORMAT_RGB_888 ;
284
+ /* If using the DBI, only RGB888 option 1 is supported. */
285
+ dbi_config .mode |= MIPI_DBI_MODE_RGB888_1 ;
286
+ DSI_SetDbiPixelFormat (config -> base , kDSI_DbiRGB888 );
287
+ break ;
288
+ default :
289
+ /* MIPI-DSI do not support other format of DBI pixel. */
290
+ LOG_ERR ("Pixel type not supported yet." );
291
+ return - EIO ;
292
+ }
293
+
294
+ /* Send the command first. */
295
+ if (msg -> cmd == MIPI_DCS_WRITE_MEMORY_START ) {
296
+ mipi_dbi_command_write (config -> mipi_dbi , & dbi_config ,
297
+ MIPI_DCS_WRITE_MEMORY_START , NULL , 0 );
298
+ } else {
299
+ mipi_dbi_command_write (config -> mipi_dbi , & dbi_config ,
300
+ MIPI_DCS_WRITE_MEMORY_CONTINUE , NULL , 0 );
301
+ }
302
+
303
+ /* Send the frame buffer data. */
304
+ mipi_dbi_write_display (config -> mipi_dbi , & dbi_config , msg -> tx_buf ,
305
+ & desc , pixfmt );
306
+
307
+ msg -> tx_len = desc .height * desc .width * data -> src_bytes_per_pixel ;
308
+ } else {
309
+ /* For other DCS commands, the DCNano DBI cannot be used. */
310
+ if (DSI_TransferBlocking (config -> base , dsi_xfer ) != kStatus_Success ) {
311
+ LOG_ERR ("Transmission failed" );
312
+ return - EIO ;
313
+ }
314
+ }
199
315
316
+ return 0 ;
317
+ }
318
+ #else
200
319
/* Helper function to transfer DSI color (Interrupt based implementation) */
201
320
static int dsi_mcux_tx_color (const struct device * dev , uint8_t channel ,
202
321
struct mipi_dsi_msg * msg )
@@ -246,6 +365,7 @@ static int dsi_mcux_tx_color(const struct device *dev, uint8_t channel,
246
365
}
247
366
return xfer .txDataSize ;
248
367
}
368
+ #endif
249
369
250
370
/* ISR is used for DSI interrupt based implementation, unnecessary if DMA is used */
251
371
static int mipi_dsi_isr (const struct device * dev )
@@ -479,11 +599,16 @@ static int dsi_mcux_detach(const struct device *dev, uint8_t channel,
479
599
static ssize_t dsi_mcux_transfer (const struct device * dev , uint8_t channel ,
480
600
struct mipi_dsi_msg * msg )
481
601
{
602
+ #if DT_PROP (DT_NODELABEL (mipi_dsi ), ulps_control )
603
+ struct mcux_mipi_dsi_data * data = dev -> data ;
604
+ #endif
605
+
606
+ #ifndef CONFIG_MIPI_DSI_MCUX_NXP_DCNANO_LCDIF
482
607
const struct mcux_mipi_dsi_config * config = dev -> config ;
608
+ #endif
483
609
484
610
dsi_transfer_t dsi_xfer = {0 };
485
611
status_t status ;
486
- int ret ;
487
612
488
613
dsi_xfer .virtualChannel = channel ;
489
614
dsi_xfer .txDataSize = msg -> tx_len ;
@@ -494,8 +619,6 @@ static ssize_t dsi_mcux_transfer(const struct device *dev, uint8_t channel,
494
619
dsi_xfer .flags = (msg -> flags & MIPI_DSI_MSG_USE_LPM ) ? 0 : kDSI_TransferUseHighSpeed ;
495
620
496
621
#if DT_PROP (DT_NODELABEL (mipi_dsi ), ulps_control )
497
- struct mcux_mipi_dsi_data * data = dev -> data ;
498
-
499
622
data -> flags = (msg -> flags & MIPI_DSI_MSG_USE_LPM ) ? MIPI_DSI_MSG_USE_LPM : 0U ;
500
623
if (msg -> flags & MCUX_DSI_2L_ULPS ) {
501
624
data -> flags |= MCUX_DSI_2L_ULPS ;
@@ -522,6 +645,9 @@ static ssize_t dsi_mcux_transfer(const struct device *dev, uint8_t channel,
522
645
dsi_xfer .sendDscCmd = true;
523
646
dsi_xfer .dscCmd = msg -> cmd ;
524
647
dsi_xfer .txDataType = kDSI_TxDataDcsLongWr ;
648
+ #ifndef CONFIG_MIPI_DSI_MCUX_NXP_DCNANO_LCDIF
649
+ int ret ;
650
+
525
651
if (msg -> flags & MCUX_DSI_2L_FB_DATA ) {
526
652
/*
527
653
* Special case- transfer framebuffer data using
@@ -535,6 +661,7 @@ static ssize_t dsi_mcux_transfer(const struct device *dev, uint8_t channel,
535
661
}
536
662
return ret ;
537
663
}
664
+ #endif
538
665
break ;
539
666
case MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM :
540
667
dsi_xfer .txDataType = kDSI_TxDataGenShortWrNoParam ;
@@ -560,15 +687,19 @@ static ssize_t dsi_mcux_transfer(const struct device *dev, uint8_t channel,
560
687
return - ENOTSUP ;
561
688
}
562
689
690
+ #ifdef CONFIG_MIPI_DSI_MCUX_NXP_DCNANO_LCDIF
691
+ status = dsi_mcux_dcnano_transfer (dev , channel , msg , & dsi_xfer );
692
+ #else
563
693
status = DSI_TransferBlocking (config -> base , & dsi_xfer );
564
-
565
- dsi_mcux_transfer_complete (dev );
694
+ #endif
566
695
567
696
if (status != kStatus_Success ) {
568
697
LOG_ERR ("Transmission failed" );
569
698
return - EIO ;
570
699
}
571
700
701
+ dsi_mcux_transfer_complete (dev );
702
+
572
703
if (msg -> rx_len != 0 ) {
573
704
/* Return rx_len on a read */
574
705
return msg -> rx_len ;
@@ -648,6 +779,8 @@ static int mcux_mipi_dsi_init(const struct device *dev)
648
779
COND_CODE_1(CONFIG_MIPI_DSI_MCUX_2L_SMARTDMA, \
649
780
(.smart_dma = DEVICE_DT_GET(DT_INST_DMAS_CTLR_BY_NAME(id, smartdma)),), \
650
781
(.irq_config_func = mipi_dsi_##n##_irq_config_func,)) \
782
+ COND_CODE_1(CONFIG_MIPI_DSI_MCUX_NXP_DCNANO_LCDIF, \
783
+ (.mipi_dbi = DEVICE_DT_GET(DT_NODELABEL(zephyr_lcdif)),), ()) \
651
784
.base = (MIPI_DSI_HOST_Type *)DT_INST_REG_ADDR(id), \
652
785
.auto_insert_eotp = DT_INST_PROP(id, autoinsert_eotp), \
653
786
.noncontinuous_hs_clk = DT_INST_PROP(id, noncontinuous_hs_clk), \
0 commit comments