mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-03 03:31:41 +03:00
feat(lcd): add MIPI-to-HDMI example (lt9611)
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "hal/assert.h"
|
||||
#include "soc/mipi_dsi_bridge_reg.h"
|
||||
#include "soc/mipi_dsi_bridge_struct.h"
|
||||
#include "hal/mipi_dsi_types.h"
|
||||
#include "hal/lcd_types.h"
|
||||
@@ -16,6 +17,8 @@
|
||||
|
||||
#define MIPI_DSI_LL_GET_BRG(bus_id) (bus_id == 0 ? &MIPI_DSI_BRIDGE : NULL)
|
||||
|
||||
#define MIPI_DSI_BRG_HTOTAL_MAX DSI_BRG_HTOTAL_V
|
||||
|
||||
#define MIPI_DSI_BRG_LL_EVENT_UNDERRUN (1 << 0)
|
||||
#if HAL_CONFIG(CHIP_SUPPORT_MIN_REV) >= 300
|
||||
#define MIPI_DSI_BRG_LL_EVENT_VSYNC (1 << 1)
|
||||
@@ -212,7 +215,7 @@ static inline void mipi_dsi_brg_ll_set_horizontal_timing(dsi_brg_dev_t *dev, uin
|
||||
* @brief Set the under run discard count for the bridge controller
|
||||
*
|
||||
* @param dev Pointer to the DSI bridge controller register base address
|
||||
* @param under_run_discard_count Under run discard count
|
||||
* @param under_run_discard_count Trigger underrun interrupt when underrun occurs and line_cnt is less than this field.
|
||||
*/
|
||||
static inline void mipi_dsi_brg_ll_set_underrun_discard_count(dsi_brg_dev_t *dev, uint32_t under_run_discard_count)
|
||||
{
|
||||
|
||||
@@ -51,15 +51,6 @@ typedef enum {
|
||||
MIPI_DSI_LL_COLOR_CODE_24BIT = 5, // 24-bit
|
||||
} mipi_dsi_ll_color_coding_t;
|
||||
|
||||
/**
|
||||
* @brief MIPI DSI Video mode burst type
|
||||
*/
|
||||
typedef enum {
|
||||
MIPI_DSI_LL_VIDEO_NON_BURST_WITH_SYNC_PULSES, // Non-burst mode with sync pulses
|
||||
MIPI_DSI_LL_VIDEO_NON_BURST_WITH_SYNC_EVENTS, // Non-burst mode with sync events
|
||||
MIPI_DSI_LL_VIDEO_BURST_WITH_SYNC_PULSES, // Burst mode with sync pulses
|
||||
} mipi_dsi_ll_video_burst_type_t;
|
||||
|
||||
/**
|
||||
* @brief Set the DSI Host controller power state
|
||||
*
|
||||
@@ -284,11 +275,25 @@ static inline void mipi_dsi_host_ll_dpi_enable_lp_command(dsi_host_dev_t *dev, b
|
||||
* @brief Set MIPI DSI video burst type
|
||||
*
|
||||
* @param dev Pointer to the DSI Host controller register base address
|
||||
* @param mode Video mode type
|
||||
* @param type Video burst type
|
||||
*/
|
||||
static inline void mipi_dsi_host_ll_dpi_set_video_burst_type(dsi_host_dev_t *dev, mipi_dsi_ll_video_burst_type_t type)
|
||||
static inline void mipi_dsi_host_ll_dpi_set_video_burst_type(dsi_host_dev_t *dev, mipi_dsi_video_burst_type_t type)
|
||||
{
|
||||
dev->vid_mode_cfg.vid_mode_type = type;
|
||||
// Public enum order is not the DSI Host VID_MODE_TYPE encoding.
|
||||
switch (type) {
|
||||
case MIPI_DSI_VIDEO_NON_BURST_WITH_SYNC_PULSES:
|
||||
dev->vid_mode_cfg.vid_mode_type = 0;
|
||||
break;
|
||||
case MIPI_DSI_VIDEO_NON_BURST_WITH_SYNC_EVENTS:
|
||||
dev->vid_mode_cfg.vid_mode_type = 1;
|
||||
break;
|
||||
case MIPI_DSI_VIDEO_BURST_WITH_SYNC_PULSES:
|
||||
dev->vid_mode_cfg.vid_mode_type = 2;
|
||||
break;
|
||||
default:
|
||||
HAL_ASSERT(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -154,8 +154,9 @@ bool mipi_dsi_hal_host_gen_read_short_packet(mipi_dsi_hal_context_t *hal, uint8_
|
||||
* @param hbp Horizontal Back Porch
|
||||
* @param active_width Active Width
|
||||
* @param hfp Horizontal Front Porch
|
||||
* @return True if the compensated timing is valid, otherwise false
|
||||
*/
|
||||
void mipi_dsi_hal_host_dpi_set_horizontal_timing(mipi_dsi_hal_context_t *hal, uint32_t hsw, uint32_t hbp, uint32_t active_width, uint32_t hfp);
|
||||
bool mipi_dsi_hal_host_dpi_set_horizontal_timing(mipi_dsi_hal_context_t *hal, uint32_t hsw, uint32_t hbp, uint32_t active_width, uint32_t hfp);
|
||||
|
||||
/**
|
||||
* @brief Set vertical timing parameters for DPI
|
||||
|
||||
@@ -58,6 +58,19 @@ typedef enum {
|
||||
MIPI_DSI_PATTERN_BER_VERTICAL, /*!< Vertical Bit Error Rate(BER) pattern */
|
||||
} mipi_dsi_pattern_type_t;
|
||||
|
||||
/**
|
||||
* @brief MIPI DSI DPI video burst type
|
||||
*
|
||||
* Selects how pixel packets are scheduled in DPI video mode:
|
||||
* burst vs non-burst, and sync pulses vs sync events.
|
||||
*/
|
||||
typedef enum {
|
||||
MIPI_DSI_VIDEO_BURST_WITH_SYNC_PULSES, /*!< Burst mode with sync pulses */
|
||||
MIPI_DSI_VIDEO_NON_BURST_WITH_SYNC_PULSES, /*!< Non-burst mode with sync pulses */
|
||||
MIPI_DSI_VIDEO_NON_BURST_WITH_SYNC_EVENTS, /*!< Non-burst mode with sync events */
|
||||
MIPI_DSI_VIDEO_BURST_TYPE_MAX, /*!< Number of burst types, used for parameter check */
|
||||
} mipi_dsi_video_burst_type_t;
|
||||
|
||||
#if SOC_MIPI_DSI_SUPPORTED
|
||||
|
||||
/**
|
||||
|
||||
@@ -256,26 +256,39 @@ bool mipi_dsi_hal_host_gen_read_dcs_command(mipi_dsi_hal_context_t *hal, uint8_t
|
||||
return mipi_dsi_hal_host_gen_read_short_packet(hal, vc, MIPI_DSI_DT_DCS_READ_0, header_data, ret_param, param_buf_size);
|
||||
}
|
||||
|
||||
void mipi_dsi_hal_host_dpi_set_horizontal_timing(mipi_dsi_hal_context_t *hal, uint32_t hsw, uint32_t hbp, uint32_t active_width, uint32_t hfp)
|
||||
bool mipi_dsi_hal_host_dpi_set_horizontal_timing(mipi_dsi_hal_context_t *hal, uint32_t hsw, uint32_t hbp, uint32_t active_width, uint32_t hfp)
|
||||
{
|
||||
// set the horizontal timing based on user's expectation
|
||||
uint32_t htotal = hsw + hbp + active_width + hfp;
|
||||
int compensation = (int)roundf(hal->real_dpi_clock_freq_mhz / hal->expect_dpi_clock_freq_mhz * htotal) - (int)htotal;
|
||||
int compensated_hfp = (int)hfp + compensation;
|
||||
int compensated_htotal = (int)htotal + compensation;
|
||||
if (compensated_hfp <= 0 || compensated_htotal > MIPI_DSI_BRG_HTOTAL_MAX) {
|
||||
HAL_LOGE(TAG, "invalid compensated timing: hfp=%d, htotal=%d", compensated_hfp, compensated_htotal);
|
||||
return false;
|
||||
}
|
||||
if (fabsf(hal->real_dpi_clock_freq_mhz - hal->expect_dpi_clock_freq_mhz) > 0.01f) {
|
||||
HAL_LOGW(TAG, "DPI clock adjusted from %.2f MHz to %.2f MHz, compensated hfp=%d, compensated htotal=%d",
|
||||
hal->expect_dpi_clock_freq_mhz, hal->real_dpi_clock_freq_mhz,
|
||||
compensated_hfp, compensated_htotal);
|
||||
}
|
||||
|
||||
float dpi2lane_clk_ratio = hal->lane_bit_rate_mbps / hal->expect_dpi_clock_freq_mhz / 8.0f;
|
||||
uint32_t host_hsw = (uint32_t)roundf(hsw * dpi2lane_clk_ratio);
|
||||
uint32_t host_hbp = (uint32_t)roundf(hbp * dpi2lane_clk_ratio);
|
||||
uint32_t host_act = (uint32_t)roundf(active_width * dpi2lane_clk_ratio);
|
||||
uint32_t host_hfp = (uint32_t)roundf(hfp * dpi2lane_clk_ratio);
|
||||
uint32_t host_htotal = (uint32_t)roundf(htotal * dpi2lane_clk_ratio);
|
||||
int compensation = (int)host_htotal - (int)(host_hsw + host_hbp + host_act + host_hfp);
|
||||
mipi_dsi_host_ll_dpi_set_horizontal_timing(hal->host, host_hsw, host_hbp, host_act + compensation, host_hfp);
|
||||
int host_compensation = (int)host_htotal - (int)(host_hsw + host_hbp + host_act + host_hfp);
|
||||
mipi_dsi_host_ll_dpi_set_horizontal_timing(hal->host, host_hsw, host_hbp, host_act + host_compensation, host_hfp);
|
||||
HAL_LOGD(TAG, "host video timing: hsw=%" PRIu32 ", hbp=%" PRIu32 ", act=%" PRIu32 ", hfp=%" PRIu32,
|
||||
host_hsw, host_hbp, host_act + compensation, host_hfp);
|
||||
host_hsw, host_hbp, host_act + host_compensation, host_hfp);
|
||||
|
||||
// compensate the video timing to achieve the same refresh rate as expected
|
||||
compensation = (int)roundf(hal->real_dpi_clock_freq_mhz / hal->expect_dpi_clock_freq_mhz * htotal) - (int)htotal;
|
||||
mipi_dsi_brg_ll_set_horizontal_timing(hal->bridge, hsw, hbp, active_width, hfp + compensation);
|
||||
mipi_dsi_brg_ll_set_horizontal_timing(hal->bridge, hsw, hbp, active_width, compensated_hfp);
|
||||
HAL_LOGD(TAG, "brg video timing: hsw=%" PRIu32 ", hbp=%" PRIu32 ", act=%" PRIu32 ", hfp=%" PRIu32,
|
||||
hsw, hbp, active_width, hfp + compensation);
|
||||
hsw, hbp, active_width, (uint32_t)compensated_hfp);
|
||||
return true;
|
||||
}
|
||||
|
||||
void mipi_dsi_hal_host_dpi_set_vertical_timing(mipi_dsi_hal_context_t *hal, uint32_t vsw, uint32_t vbp, uint32_t active_height, uint32_t vfp)
|
||||
|
||||
Reference in New Issue
Block a user