66#include <sys/param.h>
77#include "esp_lcd_panel_interface.h"
88#include "esp_lcd_mipi_dsi.h"
9+ #include "esp_intr_alloc.h"
910#include "esp_clk_tree.h"
1011#include "esp_cache.h"
1112#include "mipi_dsi_priv.h"
@@ -33,7 +34,8 @@ struct esp_lcd_dpi_panel_t {
3334 size_t bits_per_pixel ; // Bits per pixel
3435 lcd_color_format_t in_color_format ; // Input color format
3536 lcd_color_format_t out_color_format ; // Output color format
36- dw_gdma_channel_handle_t dma_chan ; // DMA channel
37+ dw_gdma_channel_handle_t dma_chan ; // DMA channel
38+ intr_handle_t brg_intr ; // DSI Bridge interrupt handle
3739 dw_gdma_link_list_handle_t link_lists [DPI_PANEL_MAX_FB_NUM ]; // DMA link list
3840 esp_async_fbcpy_handle_t fbcpy_handle ; // Use DMA2D to do frame buffer copy
3941 SemaphoreHandle_t draw_sem ; // A semaphore used to synchronize the draw operations when DMA2D is used
@@ -71,20 +73,9 @@ bool mipi_dsi_dma_trans_done_cb(dw_gdma_channel_handle_t chan, const dw_gdma_tra
7173{
7274 bool yield_needed = false;
7375 esp_lcd_dpi_panel_t * dpi_panel = (esp_lcd_dpi_panel_t * )user_data ;
74- mipi_dsi_hal_context_t * hal = & dpi_panel -> bus -> hal ;
7576 uint8_t fb_index = dpi_panel -> cur_fb_index ;
7677 dw_gdma_link_list_handle_t link_list = dpi_panel -> link_lists [fb_index ];
7778
78- // clear the interrupt status
79- uint32_t error_status = mipi_dsi_brg_ll_get_interrupt_status (hal -> bridge );
80- mipi_dsi_brg_ll_clear_interrupt_status (hal -> bridge , error_status );
81- if (unlikely (error_status & MIPI_DSI_LL_EVENT_UNDERRUN )) {
82- // when an underrun happens, the LCD display may already becomes blue
83- // it's too late to recover the display, so we just print an error message
84- // as a hint to the user that he should optimize the memory bandwidth (with AXI-ICM)
85- ESP_DRAM_LOGE (TAG , "can't fetch data from external memory fast enough, underrun happens" );
86- }
87-
8879 // restart the DMA transfer, keep refreshing the LCD
8980 dw_gdma_block_markers_t markers = {
9081 .is_valid = true,
@@ -94,15 +85,40 @@ bool mipi_dsi_dma_trans_done_cb(dw_gdma_channel_handle_t chan, const dw_gdma_tra
9485 dw_gdma_channel_use_link_list (chan , link_list );
9586 dw_gdma_channel_enable_ctrl (chan , true);
9687
88+ #if !MIPI_DSI_BRG_LL_EVENT_VSYNC
9789 // the DMA descriptor is large enough to carry a whole frame buffer, so this event can also be treated as a fake "vsync end"
9890 if (dpi_panel -> on_refresh_done ) {
9991 if (dpi_panel -> on_refresh_done (& dpi_panel -> base , NULL , dpi_panel -> user_ctx )) {
10092 yield_needed = true;
10193 }
10294 }
95+ #endif
10396 return yield_needed ;
10497}
10598
99+ void mipi_dsi_bridge_isr_handler (void * args )
100+ {
101+ esp_lcd_dpi_panel_t * dpi_panel = (esp_lcd_dpi_panel_t * )args ;
102+ mipi_dsi_hal_context_t * hal = & dpi_panel -> bus -> hal ;
103+ // clear the interrupt status
104+ uint32_t intr_status = mipi_dsi_brg_ll_get_interrupt_status (hal -> bridge );
105+ mipi_dsi_brg_ll_clear_interrupt_status (hal -> bridge , intr_status );
106+
107+ if (intr_status & MIPI_DSI_BRG_LL_EVENT_UNDERRUN ) {
108+ // when an underrun happens, the LCD display may already becomes blue
109+ // it's too late to recover the display, so we just print an error message
110+ // as a hint to the user that he should optimize the memory bandwidth (with AXI-ICM)
111+ ESP_DRAM_LOGE (TAG , "can't fetch data from external memory fast enough, underrun happens" );
112+ }
113+ if (intr_status & MIPI_DSI_BRG_LL_EVENT_VSYNC ) {
114+ if (dpi_panel -> on_refresh_done ) {
115+ if (dpi_panel -> on_refresh_done (& dpi_panel -> base , NULL , dpi_panel -> user_ctx )) {
116+ portYIELD_FROM_ISR ();
117+ }
118+ }
119+ }
120+ }
121+
106122// Please note, errors happened in this function is just propagated to the caller
107123// dpi_panel_del() is actually doing the error handling
108124static esp_err_t dpi_panel_create_dma_link (esp_lcd_dpi_panel_t * dpi_panel )
@@ -172,25 +188,19 @@ esp_err_t esp_lcd_new_panel_dpi(esp_lcd_dsi_bus_handle_t bus, const esp_lcd_dpi_
172188 // the deprecated way to set the pixel format
173189#pragma GCC diagnostic push
174190#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
175- bool has_pixel_fmt = panel_config -> pixel_format != 0 ;
176- bool has_in_fmt = panel_config -> in_color_format != 0 ;
177- ESP_RETURN_ON_FALSE (has_pixel_fmt ^ has_in_fmt , ESP_ERR_INVALID_ARG , TAG ,
178- "must set exactly one of pixel_format or in_color_format" );
179- if (panel_config -> pixel_format ) {
180- switch (panel_config -> pixel_format ) {
181- case LCD_COLOR_PIXEL_FORMAT_RGB565 :
182- bits_per_pixel = 16 ;
183- break ;
184- case LCD_COLOR_PIXEL_FORMAT_RGB666 :
185- // RGB data in the memory must be constructed in 6-6-6 (18 bits) for each pixel
186- bits_per_pixel = 18 ;
187- break ;
188- case LCD_COLOR_PIXEL_FORMAT_RGB888 :
189- bits_per_pixel = 24 ;
190- break ;
191- }
192- in_color_format = COLOR_TYPE_ID (COLOR_SPACE_RGB , panel_config -> pixel_format );
193- }
191+ switch (panel_config -> pixel_format ) {
192+ case LCD_COLOR_PIXEL_FORMAT_RGB565 :
193+ bits_per_pixel = 16 ;
194+ break ;
195+ case LCD_COLOR_PIXEL_FORMAT_RGB666 :
196+ // RGB data in the memory must be constructed in 6-6-6 (18 bits) for each pixel
197+ bits_per_pixel = 18 ;
198+ break ;
199+ case LCD_COLOR_PIXEL_FORMAT_RGB888 :
200+ bits_per_pixel = 24 ;
201+ break ;
202+ }
203+ in_color_format = COLOR_TYPE_ID (COLOR_SPACE_RGB , panel_config -> pixel_format );
194204#pragma GCC diagnostic pop
195205 // the recommended way to set the input color format
196206 if (panel_config -> in_color_format ) {
@@ -278,6 +288,14 @@ esp_err_t esp_lcd_new_panel_dpi(esp_lcd_dsi_bus_handle_t bus, const esp_lcd_dpi_
278288 esp_pm_lock_acquire (dpi_panel -> pm_lock );
279289#endif
280290
291+ // install interrupt service
292+ int isr_flags = ESP_INTR_FLAG_LOWMED ;
293+ #if CONFIG_LCD_DSI_ISR_CACHE_SAFE
294+ isr_flags |= ESP_INTR_FLAG_IRAM ;
295+ #endif
296+ ESP_GOTO_ON_ERROR (esp_intr_alloc (soc_mipi_dsi_signals [bus_id ].brg_irq_id , isr_flags , mipi_dsi_bridge_isr_handler ,
297+ dpi_panel , & dpi_panel -> brg_intr ), err , TAG , "allocate DSI Bridge interrupt failed" );
298+
281299 // create DMA resources
282300 ESP_GOTO_ON_ERROR (dpi_panel_create_dma_link (dpi_panel ), err , TAG , "initialize DMA link failed" );
283301
@@ -377,6 +395,9 @@ static esp_err_t dpi_panel_del(esp_lcd_panel_t *panel)
377395 if (dpi_panel -> draw_sem ) {
378396 vSemaphoreDeleteWithCaps (dpi_panel -> draw_sem );
379397 }
398+ if (dpi_panel -> brg_intr ) {
399+ esp_intr_free (dpi_panel -> brg_intr );
400+ }
380401#if CONFIG_PM_ENABLE
381402 if (dpi_panel -> pm_lock ) {
382403 esp_pm_lock_release (dpi_panel -> pm_lock );
@@ -458,9 +479,8 @@ static esp_err_t dpi_panel_init(esp_lcd_panel_t *panel)
458479 mipi_dsi_brg_ll_enable_dpi_output (hal -> bridge , true);
459480 mipi_dsi_brg_ll_update_dpi_config (hal -> bridge );
460481
461- // enable the underrun interrupt, we use this as a signal of bandwidth shortage
462- // note, we opt to not install a dedicated interrupt handler just for this error condition, instead, we check it in the DMA callback
463- mipi_dsi_brg_ll_enable_interrupt (hal -> bridge , MIPI_DSI_LL_EVENT_UNDERRUN , true);
482+ // always enable the interrupt to detect the underflow condition
483+ mipi_dsi_brg_ll_enable_interrupt (hal -> bridge , MIPI_DSI_BRG_LL_EVENT_UNDERRUN , true);
464484
465485 return ESP_OK ;
466486}
@@ -622,10 +642,13 @@ esp_err_t esp_lcd_dpi_panel_register_event_callbacks(esp_lcd_panel_handle_t pane
622642 if (user_ctx ) {
623643 ESP_RETURN_ON_FALSE (esp_ptr_internal (user_ctx ), ESP_ERR_INVALID_ARG , TAG , "user context not in internal RAM" );
624644 }
625- #endif // CONFIG_LCD_DSI_ISR_HANDLER_IN_IRAM
645+ #endif // CONFIG_LCD_DSI_ISR_CACHE_SAFE
626646 dpi_panel -> on_color_trans_done = cbs -> on_color_trans_done ;
627647 dpi_panel -> on_refresh_done = cbs -> on_refresh_done ;
628648 dpi_panel -> user_ctx = user_ctx ;
629649
650+ // enable the vsync interrupt if the callback is provided
651+ mipi_dsi_brg_ll_enable_interrupt (dpi_panel -> bus -> hal .bridge , MIPI_DSI_BRG_LL_EVENT_VSYNC , cbs -> on_refresh_done != NULL );
652+
630653 return ESP_OK ;
631654}
0 commit comments