@@ -34,6 +34,12 @@ enum lcdic_cmd_type {
3434 LCDIC_TX = 1 ,
3535};
3636
37+ enum lcdic_cmd_te {
38+ LCDIC_TE_NO_SYNC = 0 ,
39+ LCDIC_TE_RISING_EDGE = 1 ,
40+ LCDIC_TE_FALLING_EDGE = 2 ,
41+ };
42+
3743/* Limit imposed by size of data length field in LCDIC command */
3844#define LCDIC_MAX_XFER 0x40000
3945/* Max reset width (in terms of Timer0_Period, see RST_CTRL register) */
@@ -102,6 +108,10 @@ struct mipi_dbi_lcdic_data {
102108 uint32_t unaligned_word __aligned (4 );
103109 /* Tracks lcdic_data_fmt value we should use for pixel data */
104110 uint8_t pixel_fmt ;
111+ /* Tracks TE edge setting we should use for pixel data */
112+ uint8_t te_edge ;
113+ /* Are we starting a new display frame */
114+ bool new_frame ;
105115 const struct mipi_dbi_config * active_cfg ;
106116 struct k_sem xfer_sem ;
107117 struct k_sem lock ;
@@ -376,6 +386,7 @@ static void mipi_dbi_lcdic_set_cmd(LCDIC_Type *base,
376386 enum lcdic_cmd_type dir ,
377387 enum lcdic_cmd_dc dc ,
378388 enum lcdic_data_fmt data_fmt ,
389+ enum lcdic_cmd_te te_sync ,
379390 uint32_t buf_len )
380391{
381392 union lcdic_trx_cmd cmd = {0 };
@@ -387,6 +398,7 @@ static void mipi_dbi_lcdic_set_cmd(LCDIC_Type *base,
387398 cmd .bits .trx = dir ;
388399 cmd .bits .cmd_done_int = true;
389400 cmd .bits .data_format = data_fmt ;
401+ cmd .bits .te_sync_mode = te_sync ;
390402 /* Write command */
391403 base -> TFIFO_WDATA = cmd .u32 ;
392404}
@@ -401,6 +413,7 @@ static int mipi_dbi_lcdic_write_display(const struct device *dev,
401413 struct mipi_dbi_lcdic_data * dev_data = dev -> data ;
402414 LCDIC_Type * base = config -> base ;
403415 int ret ;
416+ enum lcdic_cmd_te te_sync = LCDIC_TE_NO_SYNC ;
404417 uint32_t interrupts = 0U ;
405418
406419 ret = k_sem_take (& dev_data -> lock , K_FOREVER );
@@ -413,6 +426,26 @@ static int mipi_dbi_lcdic_write_display(const struct device *dev,
413426 goto out ;
414427 }
415428
429+ if (dev_data -> new_frame ) {
430+ switch (dev_data -> te_edge ) {
431+ case MIPI_DBI_TE_RISING_EDGE :
432+ te_sync = LCDIC_TE_RISING_EDGE ;
433+ break ;
434+ case MIPI_DBI_TE_FALLING_EDGE :
435+ te_sync = LCDIC_TE_FALLING_EDGE ;
436+ break ;
437+ default :
438+ te_sync = LCDIC_TE_NO_SYNC ;
439+ break ;
440+ }
441+ dev_data -> new_frame = false;
442+ }
443+
444+ if (!desc -> frame_incomplete ) {
445+ /* Next frame will be a new one */
446+ dev_data -> new_frame = true;
447+ }
448+
416449 /* State reset is required before transfer */
417450 mipi_dbi_lcdic_reset_state (dev );
418451
@@ -448,6 +481,7 @@ static int mipi_dbi_lcdic_write_display(const struct device *dev,
448481 */
449482 mipi_dbi_lcdic_set_cmd (base , LCDIC_TX , LCDIC_DATA ,
450483 dev_data -> pixel_fmt ,
484+ te_sync ,
451485 dev_data -> cmd_bytes );
452486#ifdef CONFIG_MIPI_DBI_NXP_LCDIC_DMA
453487 /* Enable command complete interrupt */
@@ -506,7 +540,7 @@ static int mipi_dbi_lcdic_write_cmd(const struct device *dev,
506540
507541 /* Write command */
508542 mipi_dbi_lcdic_set_cmd (base , LCDIC_TX , LCDIC_COMMAND ,
509- LCDIC_DATA_FMT_BYTE , 1 );
543+ LCDIC_DATA_FMT_BYTE , LCDIC_TE_NO_SYNC , 1 );
510544 /* Use standard byte writes */
511545 dev_data -> pixel_fmt = LCDIC_DATA_FMT_BYTE ;
512546 base -> TFIFO_WDATA = cmd ;
@@ -530,18 +564,10 @@ static int mipi_dbi_lcdic_write_cmd(const struct device *dev,
530564 dev_data -> xfer_buf ,
531565 dev_data -> cmd_bytes );
532566 }
533- if (cmd == MIPI_DCS_WRITE_MEMORY_START ) {
534- /* Use pixel format data width, so we can byte swap
535- * if needed
536- */
537- mipi_dbi_lcdic_set_cmd (base , LCDIC_TX , LCDIC_DATA ,
538- dev_data -> pixel_fmt ,
539- dev_data -> cmd_bytes );
540- } else {
541- mipi_dbi_lcdic_set_cmd (base , LCDIC_TX , LCDIC_DATA ,
542- LCDIC_DATA_FMT_BYTE ,
543- dev_data -> cmd_bytes );
544- }
567+ mipi_dbi_lcdic_set_cmd (base , LCDIC_TX , LCDIC_DATA ,
568+ LCDIC_DATA_FMT_BYTE ,
569+ LCDIC_TE_NO_SYNC ,
570+ dev_data -> cmd_bytes );
545571#ifdef CONFIG_MIPI_DBI_NXP_LCDIC_DMA
546572 if (((((uint32_t )dev_data -> xfer_buf ) & 0x3 ) == 0 ) ||
547573 (dev_data -> cmd_bytes < 4 )) {
@@ -618,6 +644,50 @@ static int mipi_dbi_lcdic_reset(const struct device *dev, k_timeout_t delay)
618644 return 0 ;
619645}
620646
647+ static int mipi_dbi_lcdic_configure_te (const struct device * dev ,
648+ uint8_t edge ,
649+ k_timeout_t delay )
650+ {
651+ const struct mipi_dbi_lcdic_config * config = dev -> config ;
652+ LCDIC_Type * base = config -> base ;
653+ struct mipi_dbi_lcdic_data * data = dev -> data ;
654+ uint32_t lcdic_freq , ttew , reg ;
655+ uint32_t delay_us = k_ticks_to_us_ceil32 (delay .ticks );
656+
657+ /* Calculate delay based off timer0 ratio. Formula given
658+ * by RM is as follows:
659+ * TE delay = Timer1_Period * ttew
660+ * Timer1_Period = 2^(TIMER_RATIO1) * Timer0_Period
661+ * Timer0_Period = 2^(TIMER_RATIO0) / LCDIC_Clock_Freq
662+ */
663+ if (clock_control_get_rate (config -> clock_dev , config -> clock_subsys ,
664+ & lcdic_freq )) {
665+ return - EIO ;
666+ }
667+
668+ /*
669+ * Calculate TTEW. Done in multiple steps to avoid overflowing
670+ * the uint32_t type. Full formula is:
671+ * (lcdic_freq * delay_us) /
672+ * ((2 ^ (TIMER_RATIO1 + TIMER_RATIO0)) * USEC_PER_SEC)
673+ */
674+ ttew = lcdic_freq / (1 << config -> timer0_ratio );
675+ ttew *= delay_us ;
676+ ttew /= (1 << config -> timer1_ratio );
677+ ttew /= USEC_PER_SEC ;
678+
679+ /* Check to see if the delay is shorter than we can support */
680+ if ((ttew == 0 ) && (delay_us != 0 )) {
681+ LOG_ERR ("Timer ratios too large to support this TE delay" );
682+ return - ENOTSUP ;
683+ }
684+ reg = base -> TE_CTRL ;
685+ reg &= ~LCDIC_TE_CTRL_TTEW_MASK ;
686+ reg |= LCDIC_TE_CTRL_TTEW (ttew );
687+ base -> TE_CTRL = reg ;
688+ data -> te_edge = edge ;
689+ return 0 ;
690+ }
621691
622692
623693/* Initializes LCDIC peripheral */
@@ -671,6 +741,8 @@ static int mipi_dbi_lcdic_init(const struct device *dev)
671741 base -> TIMER_CTRL = LCDIC_TIMER_CTRL_TIMER_RATIO1 (config -> timer1_ratio ) |
672742 LCDIC_TIMER_CTRL_TIMER_RATIO0 (config -> timer0_ratio );
673743
744+ data -> te_edge = MIPI_DBI_TE_NO_EDGE ;
745+
674746#ifdef CONFIG_MIPI_DBI_NXP_LCDIC_DMA
675747 /* Attach the LCDIC DMA request signal to the DMA channel we will
676748 * use with hardware triggering.
@@ -687,6 +759,7 @@ static int mipi_dbi_lcdic_init(const struct device *dev)
687759static DEVICE_API (mipi_dbi , mipi_dbi_lcdic_driver_api ) = {
688760 .command_write = mipi_dbi_lcdic_write_cmd ,
689761 .write_display = mipi_dbi_lcdic_write_display ,
762+ .configure_te = mipi_dbi_lcdic_configure_te ,
690763 .reset = mipi_dbi_lcdic_reset ,
691764};
692765
@@ -718,7 +791,8 @@ static void mipi_dbi_lcdic_isr(const struct device *dev)
718791 /* Command done. Queue next command */
719792 data -> cmd_bytes = MIN (data -> xfer_bytes , LCDIC_MAX_XFER );
720793 mipi_dbi_lcdic_set_cmd (base , LCDIC_TX , LCDIC_DATA ,
721- LCDIC_DATA_FMT_BYTE ,
794+ data -> pixel_fmt ,
795+ LCDIC_TE_NO_SYNC ,
722796 data -> cmd_bytes );
723797 if (data -> cmd_bytes & 0x3 ) {
724798 /* Save unaligned portion of transfer into
0 commit comments