forked from espressif/esp-idf
rgb_lcd: support update pclk at runtime
This commit is contained in:
@@ -88,10 +88,12 @@ struct esp_rgb_panel_t {
|
||||
void *user_ctx; // Reserved user's data of callback functions
|
||||
int x_gap; // Extra gap in x coordinate, it's used when calculate the flush window
|
||||
int y_gap; // Extra gap in y coordinate, it's used when calculate the flush window
|
||||
portMUX_TYPE spinlock; // to protect panel specific resource from concurrent access (e.g. between task and ISR)
|
||||
struct {
|
||||
unsigned int disp_en_level: 1; // The level which can turn on the screen by `disp_gpio_num`
|
||||
unsigned int stream_mode: 1; // If set, the LCD transfers data continuously, otherwise, it stops refreshing the LCD when transaction done
|
||||
unsigned int fb_in_psram: 1; // Whether the frame buffer is in PSRAM
|
||||
unsigned int need_update_pclk: 1; // Whether to update the PCLK before start a new transaction
|
||||
} flags;
|
||||
dma_descriptor_t dma_nodes[]; // DMA descriptor pool of size `num_dma_nodes`
|
||||
};
|
||||
@@ -187,6 +189,7 @@ esp_err_t esp_lcd_new_rgb_panel(const esp_lcd_rgb_panel_config_t *rgb_panel_conf
|
||||
rgb_panel->flags.disp_en_level = !rgb_panel_config->flags.disp_active_low;
|
||||
rgb_panel->on_frame_trans_done = rgb_panel_config->on_frame_trans_done;
|
||||
rgb_panel->user_ctx = rgb_panel_config->user_ctx;
|
||||
rgb_panel->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED;
|
||||
// fill function table
|
||||
rgb_panel->base.del = rgb_panel_del;
|
||||
rgb_panel->base.reset = rgb_panel_reset;
|
||||
@@ -227,6 +230,18 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_rgb_panel_set_pclk(esp_lcd_panel_handle_t panel, uint32_t freq_hz)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(panel, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
esp_rgb_panel_t *rgb_panel = __containerof(panel, esp_rgb_panel_t, base);
|
||||
// the pclk frequency will be updated in `lcd_rgb_panel_start_transmission()`
|
||||
portENTER_CRITICAL(&rgb_panel->spinlock);
|
||||
rgb_panel->flags.need_update_pclk = true;
|
||||
rgb_panel->timings.pclk_hz = freq_hz;
|
||||
portEXIT_CRITICAL(&rgb_panel->spinlock);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t rgb_panel_del(esp_lcd_panel_t *panel)
|
||||
{
|
||||
esp_rgb_panel_t *rgb_panel = __containerof(panel, esp_rgb_panel_t, base);
|
||||
@@ -499,6 +514,15 @@ static void lcd_rgb_panel_start_transmission(esp_rgb_panel_t *rgb_panel)
|
||||
// reset FIFO of DMA and LCD, incase there remains old frame data
|
||||
gdma_reset(rgb_panel->dma_chan);
|
||||
lcd_ll_stop(rgb_panel->hal.dev);
|
||||
|
||||
// check whether to update the PCLK frequency
|
||||
portENTER_CRITICAL_SAFE(&rgb_panel->spinlock);
|
||||
if (unlikely(rgb_panel->flags.need_update_pclk)) {
|
||||
rgb_panel->flags.need_update_pclk = false;
|
||||
rgb_panel->timings.pclk_hz = lcd_hal_cal_pclk_freq(&rgb_panel->hal, rgb_panel->src_clk_hz, rgb_panel->timings.pclk_hz);
|
||||
}
|
||||
portEXIT_CRITICAL_SAFE(&rgb_panel->spinlock);
|
||||
|
||||
lcd_ll_fifo_reset(rgb_panel->hal.dev);
|
||||
gdma_start(rgb_panel->dma_chan, (intptr_t)rgb_panel->dma_nodes);
|
||||
// delay 1us is sufficient for DMA to pass data to LCD FIFO
|
||||
|
Reference in New Issue
Block a user