bdk: display: improve and deduplicate more

- Add delay after a DSI soft reset
- Remove more duplicated configs
- Improve code to save code size
- Improve comments
- Do not allow display_backlight to be used with OLED
This commit is contained in:
CTCaer
2025-12-25 11:36:06 +02:00
parent 67140d026c
commit a7ad3d4984
3 changed files with 67 additions and 73 deletions

View File

@@ -67,6 +67,15 @@ static void _display_dsi_wait(u32 timeout, u32 off, u32 mask)
usleep(5);
}
static void _display_dsi_soft_reset()
{
// Disable DSI interface.
DSI(DSI_POWER_CONTROL) = 0;
// Settle time.
usleep(10);
}
static void _display_dsi_send_cmd(u8 cmd, u32 param, u32 wait)
{
DSI(DSI_WR_DATA) = (param << 8) | cmd;
@@ -374,50 +383,48 @@ void display_init()
PMC(APBDEV_PMC_IO_DPD_REQ) = PMC_IO_DPD_REQ_DPD_OFF;
PMC(APBDEV_PMC_IO_DPD2_REQ) = PMC_IO_DPD_REQ_DPD_OFF;
// Configure LCD/BL pins.
// Configure LCD/WLED driver pins.
if (!_nx_aula)
{
// Configure LCD pins.
// Configure LCD driver pins.
PINMUX_AUX(PINMUX_AUX_NFC_EN) = PINMUX_PULL_DOWN;
PINMUX_AUX(PINMUX_AUX_NFC_INT) = PINMUX_PULL_DOWN;
// Configure Backlight pins.
// Configure WLED driver pins.
PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = PINMUX_PULL_DOWN;
PINMUX_AUX(PINMUX_AUX_LCD_BL_EN) = PINMUX_PULL_DOWN;
// Enable LCD AVDD.
// Enable LCD driver AVDD channels (+5.4V CH2 EN, -5.4V CH1 EN).
gpio_direction_output(GPIO_PORT_I, GPIO_PIN_0 | GPIO_PIN_1, GPIO_HIGH);
usleep(10000); // Wait minimum 4.2ms to stabilize.
// Configure Backlight PWM/EN pins (BL PWM, BL EN).
// Configure WLED driver PWM/EN pins.
gpio_direction_output(GPIO_PORT_V, GPIO_PIN_0 | GPIO_PIN_1, GPIO_LOW);
// Enable Backlight power.
// Enable WLED driver.
gpio_write(GPIO_PORT_V, GPIO_PIN_1, GPIO_HIGH);
}
// Configure LCD RST pin.
// Configure Panel Reset pin.
PINMUX_AUX(PINMUX_AUX_LCD_RST) = PINMUX_PULL_DOWN;
gpio_direction_output(GPIO_PORT_V, GPIO_PIN_2, GPIO_LOW);
// Power up supply regulator for display interface.
MIPI_CAL(MIPI_CAL_MIPI_BIAS_PAD_CFG2) = 0;
MIPI_CAL(MIPI_CAL_MIPI_BIAS_PAD_CFG0) = 0;
if (!tegra_t210)
{
MIPI_CAL(MIPI_CAL_MIPI_BIAS_PAD_CFG0) = 0;
APB_MISC(APB_MISC_GP_DSI_PAD_CONTROL) = 0;
}
// Set DISP1 clock source, parent clock and DSI/PCLK to command mode.
// T210: DIVM: 1, DIVN: 20, DIVP: 3. PLLD_OUT: 100.0 MHz, PLLD_OUT0 (DSI-BCLK): 50.0 MHz. (PCLK: 16.66 MHz)
// T210B01: DIVM: 1, DIVN: 20, DIVP: 3. PLLD_OUT: 97.8 MHz, PLLD_OUT0 (DSI-BCLK): 48.9 MHz. (PCLK: 16.30 MHz)
clock_enable_plld(3, 20, true, tegra_t210);
// Setup Display Interface initial window configuration.
reg_write_array((vu32 *)DISPLAY_A_BASE, _di_dc_setup_win_config, ARRAY_SIZE(_di_dc_setup_win_config));
// Setup Display Interface initial configuration.
reg_write_array((vu32 *)DISPLAY_A_BASE, _di_dc_init_config, ARRAY_SIZE(_di_dc_init_config));
// Setup dsi init sequence packets.
// Setup DSI init sequence packets.
reg_write_array((vu32 *)DSI_BASE, _di_dsi_seq_pkt_reset_config0, ARRAY_SIZE(_di_dsi_seq_pkt_reset_config0));
DSI(tegra_t210 ? DSI_INIT_SEQ_DATA_15 : DSI_INIT_SEQ_DATA_15_B01) = 0;
reg_write_array((vu32 *)DSI_BASE, _di_dsi_seq_pkt_reset_config1, ARRAY_SIZE(_di_dsi_seq_pkt_reset_config1));
@@ -428,9 +435,16 @@ void display_init()
// Setup init seq packet lengths, timings and power on DSI.
reg_write_array((vu32 *)DSI_BASE, _di_dsi_init_config, ARRAY_SIZE(_di_dsi_init_config));
usleep(10);
// DSI soft reset.
_display_dsi_soft_reset();
// Set DSI LP timings.
reg_write_array((vu32 *)DSI_BASE, _di_dsi_timing_lp_config, ARRAY_SIZE(_di_dsi_timing_lp_config));
usleep(10000);
// Enable LCD Reset.
// Enable Panel Reset.
gpio_write(GPIO_PORT_V, GPIO_PIN_2, GPIO_HIGH);
usleep(60000);
@@ -444,7 +458,7 @@ void display_init()
if (!display_dsi_read(MIPI_DCS_GET_DISPLAY_ID, 3, &_panel_id_raw))
break;
usleep(10000);
usleep(5000);
}
// Decode Display ID.
@@ -454,7 +468,7 @@ void display_init()
_panel_id = PANEL_JDI_XXX062M;
// For Aula ensure that we have a compatible panel id.
if (_nx_aula && _panel_id == 0xCCCC)
if (_nx_aula)
_panel_id = PANEL_SAM_AMS699VC01;
// Initialize display panel.
@@ -537,7 +551,7 @@ void display_init()
reg_write_array((vu32 *)DSI_BASE, _di_dsi_seq_pkt_video_non_burst_no_eot_config, ARRAY_SIZE(_di_dsi_seq_pkt_video_non_burst_no_eot_config));
// Set 1-by-1 pixel/clock and pixel clock to 234 / 3 = 78 MHz. For 60 Hz refresh rate.
DISPLAY_A(DC_DISP_DISP_CLOCK_CONTROL) = PIXEL_CLK_DIVIDER_PCD1 | SHIFT_CLK_DIVIDER(4); // 4: div3.
DISPLAY_A(DC_DISP_DISP_CLOCK_CONTROL) = PIXEL_CLK_DIVIDER_PCD1 | SHIFT_CLK_DIVIDER(4); // div3. Default: div4.
// Set DSI mode to HOST.
reg_write_array((vu32 *)DSI_BASE, _di_dsi_host_mode_config, ARRAY_SIZE(_di_dsi_host_mode_config));
@@ -577,8 +591,8 @@ void display_init()
}
usleep(10000);
// Enable video display controller.
reg_write_array((vu32 *)DISPLAY_A_BASE, _di_dc_video_enable_config, ARRAY_SIZE(_di_dc_video_enable_config));
// Setup video mode.
reg_write_array((vu32 *)DISPLAY_A_BASE, _di_dc_video_mode_config, ARRAY_SIZE(_di_dc_video_mode_config));
}
void display_backlight_pwm_init()
@@ -600,6 +614,9 @@ void display_backlight_pwm_init()
void display_backlight(bool enable)
{
if (_panel_id == PANEL_SAM_AMS699VC01)
return;
// Backlight PWM GPIO.
gpio_write(GPIO_PORT_V, GPIO_PIN_0, enable ? GPIO_HIGH : GPIO_LOW);
}
@@ -630,7 +647,7 @@ static void _display_pwm_backlight_brightness(u32 duty, u32 step_delay)
if (old_value < duty)
{
for (u32 i = old_value; i < duty + 1; i++)
for (u32 i = old_value; i <= duty; i++)
{
PWM(PWM_CONTROLLER_PWM_CSR_0) = PWM_CSR_EN | (i << 16);
usleep(step_delay);
@@ -638,14 +655,12 @@ static void _display_pwm_backlight_brightness(u32 duty, u32 step_delay)
}
else
{
for (u32 i = old_value; i > duty; i--)
for (int i = old_value; i >= (int)duty; i--)
{
PWM(PWM_CONTROLLER_PWM_CSR_0) = PWM_CSR_EN | (i << 16);
usleep(step_delay);
}
}
if (!duty)
PWM(PWM_CONTROLLER_PWM_CSR_0) = 0;
}
void display_backlight_brightness(u32 brightness, u32 step_delay)
@@ -688,8 +703,11 @@ static void _display_panel_and_hw_end(bool no_panel_deinit)
// T210B01: DIVM: 1, DIVN: 20, DIVP: 3. PLLD_OUT: 97.8 MHz, PLLD_OUT0 (DSI-BCLK): 48.9 MHz. (PCLK: 16.30 MHz)
clock_enable_plld(3, 20, true, hw_get_chip_id() == GP_HIDREV_MAJOR_T210);
// Set timings for lowpower clocks.
reg_write_array((vu32 *)DSI_BASE, _di_dsi_timing_deinit_config, ARRAY_SIZE(_di_dsi_timing_deinit_config));
// DSI soft reset.
_display_dsi_soft_reset();
// Set DSI LP timings.
reg_write_array((vu32 *)DSI_BASE, _di_dsi_timing_lp_config, ARRAY_SIZE(_di_dsi_timing_lp_config));
if (_panel_id != PANEL_SAM_AMS699VC01)
usleep(10000);
@@ -750,16 +768,16 @@ static void _display_panel_and_hw_end(bool no_panel_deinit)
(_panel_id == PANEL_SAM_AMS699VC01) ? 120000 : 50000);
skip_panel_deinit:
// Disable LCD power pins.
gpio_write(GPIO_PORT_V, GPIO_PIN_2, GPIO_LOW); // LCD Reset disable.
// Disable Panel Reset.
gpio_write(GPIO_PORT_V, GPIO_PIN_2, GPIO_LOW);
usleep(10000);
if (!_nx_aula) // HOS uses panel id.
{
gpio_write(GPIO_PORT_I, GPIO_PIN_1, GPIO_LOW); // LCD AVDD -5.4V disable.
gpio_write(GPIO_PORT_I, GPIO_PIN_0, GPIO_LOW); // LCD AVDD +5.4V disable.
// Disable LCD driver AVDD channels.
gpio_write(GPIO_PORT_I, GPIO_PIN_0 | GPIO_PIN_1, GPIO_LOW);
// Make sure LCD PWM backlight pin is in PWM0 mode.
// Make sure LCD driver PWM pin is in PWM0 mode.
gpio_config(GPIO_PORT_V, GPIO_PIN_0, GPIO_MODE_SPIO); // Backlight PWM.
PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = PINMUX_TRISTATE | PINMUX_PULL_DOWN | 1; // Set PWM0 mode.
}
@@ -771,10 +789,10 @@ skip_panel_deinit:
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = BIT(CLK_L_DISP1);
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = BIT(CLK_L_DISP1);
// Power down pads.
// Power down.
DSI(DSI_PAD_CONTROL_0) = DSI_PAD_CONTROL_VS1_PULLDN_CLK | DSI_PAD_CONTROL_VS1_PULLDN(0xF) |
DSI_PAD_CONTROL_VS1_PDIO_CLK | DSI_PAD_CONTROL_VS1_PDIO(0xF);
DSI(DSI_POWER_CONTROL) = 0;
_display_dsi_soft_reset();
// Disable DSI AVDD.
max7762x_regulator_enable(REGULATOR_LDO0, false);

View File

@@ -31,6 +31,7 @@
/*! Display registers. */
// All Display/DSI/MIPI register defines and macros are index based (not offset).
// DC_CMD/DC_COM/WINC Non-shadowed. DC_DISP/DC_WIN/DC_WINBUF Shadowed.
// Display controller scratch registers.
#define DC_D_WINBUF_DD_SCRATCH_REGISTER_0 0xED

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2024 CTCaer
* Copyright (c) 2018-2025 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -16,10 +16,9 @@
*/
// Display A config.
static const reg_cfg_t _di_dc_setup_win_config[] = {
static const reg_cfg_t _di_dc_init_config[] = {
/* Display init */
{DC_CMD_STATE_ACCESS, READ_MUX_ASSEMBLY | WRITE_MUX_ASSEMBLY},
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
{DC_CMD_REG_ACT_CONTROL, WIN_A_ACT_HCNTR_SEL | WIN_B_ACT_HCNTR_SEL | WIN_C_ACT_HCNTR_SEL | WIN_D_ACT_HCNTR_SEL},
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
@@ -32,10 +31,11 @@ static const reg_cfg_t _di_dc_setup_win_config[] = {
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE | WIN_D_UPDATE},
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ | WIN_D_ACT_REQ},
/* Setup Windows A/B/C */
/* Disable A/B/C/D Windows */
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT | WINDOW_B_SELECT | WINDOW_C_SELECT | WINDOW_D_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_WIN_DV_CONTROL, 0},
/* Setup default YUV colorspace conversion coefficients */
{DC_WINC_CSC_YOF, 0xF0},
{DC_WINC_CSC_KYRGB, 0x12A},
@@ -45,8 +45,8 @@ static const reg_cfg_t _di_dc_setup_win_config[] = {
{DC_WINC_CSC_KVG, 0x32F},
{DC_WINC_CSC_KUB, 0x204},
{DC_WINC_CSC_KVB, 0},
/* End of color coefficients */
/* Init color, format and background */
{DC_DISP_DISP_COLOR_CONTROL, BASE_COLOR_SIZE_888},
{DC_DISP_DISP_INTERFACE_CONTROL, DISP_DATA_FORMAT_DF1P1C},
{DC_COM_PIN_OUTPUT_POLARITY(1), LSC0_OUTPUT_POLARITY_LOW},
@@ -55,6 +55,8 @@ static const reg_cfg_t _di_dc_setup_win_config[] = {
{DC_COM_CRC_CONTROL, 0},
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE | WIN_D_UPDATE},
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ | WIN_D_ACT_REQ},
/* Stop display */
{DC_WINBUF_BLEND_LAYER_CONTROL, WIN_BLEND_BYPASS | WIN_BLEND_DEPTH(255)},
{DC_CMD_DISPLAY_COMMAND_OPTION0, 0},
{DC_DISP_DISP_WIN_OPTIONS, 0},
@@ -113,7 +115,7 @@ static const reg_cfg_t _di_dsi_init_config[] = {
{DSI_PAD_CONTROL_1, 0},
/* DSI PHY timings */
/* DSI PHY timings Init - 19.2 MHz */
{DSI_PHY_TIMING_0, 0x6070603},
{DSI_PHY_TIMING_1, 0x40A0E05},
{DSI_PHY_TIMING_2, 0x30109},
@@ -125,12 +127,13 @@ static const reg_cfg_t _di_dsi_init_config[] = {
{DSI_PAD_CONTROL_0, DSI_PAD_CONTROL_VS1_PULLDN(0) | DSI_PAD_CONTROL_VS1_PDIO(0)}, // Power up.
{DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE},
{DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE},
{DSI_POWER_CONTROL, 0},
{DSI_POWER_CONTROL, 0},
};
// DSI LP config.
static const reg_cfg_t _di_dsi_timing_lp_config[] = {
{DSI_PAD_CONTROL_1, 0},
/* DSI PHY timings */
/* DSI PHY timings LP - 50 MHz */
{DSI_PHY_TIMING_0, 0x6070603},
{DSI_PHY_TIMING_1, 0x40A0E05},
{DSI_PHY_TIMING_2, 0x30118},
@@ -143,7 +146,6 @@ static const reg_cfg_t _di_dsi_init_config[] = {
{DSI_HOST_CONTROL, DSI_HOST_CONTROL_CRC_RESET | DSI_HOST_CONTROL_TX_TRIG_HOST | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC},
{DSI_CONTROL, DSI_CONTROL_LANES(3) | DSI_CONTROL_HOST_ENABLE},
{DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE},
{DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE},
{DSI_MAX_THRESHOLD, 64},
{DSI_TRIGGER, 0},
{DSI_TX_CRC, 0},
@@ -201,7 +203,7 @@ static const reg_cfg_t _di_dsi_panel_init_config_jdi[] = {
static const reg_cfg_t _di_dsi_seq_pkt_video_non_burst_no_eot_config[] = {
{DSI_PAD_CONTROL_1, 0},
/* DSI PHY timings */
/* DSI PHY timings HP - 234 MHz */
{DSI_PHY_TIMING_0, 0x6070603},
{DSI_PHY_TIMING_1, 0x40A0E05},
{DSI_PHY_TIMING_2, 0x30172},
@@ -294,7 +296,7 @@ static const reg_cfg_t _di_mipi_dsi_cal_unused_config[] = {
};
// Display A enable config.
static const reg_cfg_t _di_dc_video_enable_config[] = {
static const reg_cfg_t _di_dc_video_mode_config[] = {
/* Set panel timings */
{DC_DISP_DISP_TIMING_OPTIONS, VSYNC_H_POSITION(0)},
{DC_DISP_REF_TO_SYNC, V_REF_TO_SYNC(1) | H_REF_TO_SYNC(0)},
@@ -307,7 +309,6 @@ static const reg_cfg_t _di_dc_video_enable_config[] = {
{DC_DISP_SHIFT_CLOCK_OPTIONS, SC1_H_QUALIFIER_NONE | SC0_H_QUALIFIER_NONE},
{DC_COM_PIN_OUTPUT_ENABLE(1), 0},
{DC_DISP_DATA_ENABLE_OPTIONS, DE_SELECT_ACTIVE | DE_CONTROL_NORMAL},
{DC_DISP_DISP_CLOCK_CONTROL, 0},
/* Start continuous display. */
{DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY},
@@ -319,8 +320,6 @@ static const reg_cfg_t _di_dc_video_enable_config[] = {
{DC_CMD_GENERAL_INCR_SYNCPT, SYNCPT_GENERAL_COND(COND_REG_WR_SAFE) | SYNCPT_GENERAL_INDX(1)},
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
{DC_DISP_DISP_CLOCK_CONTROL, PIXEL_CLK_DIVIDER_PCD1 | SHIFT_CLK_DIVIDER(4)}, // 4: div3.
};
// Display A disable config.
@@ -346,30 +345,6 @@ static const reg_cfg_t _di_dc_video_disable_config[] = {
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
};
// DSI deinit config.
static const reg_cfg_t _di_dsi_timing_deinit_config[] = {
{DSI_POWER_CONTROL, 0},
{DSI_PAD_CONTROL_1, 0},
/* DSI PHY timings */
{DSI_PHY_TIMING_0, 0x6070603},
{DSI_PHY_TIMING_1, 0x40A0E05},
{DSI_PHY_TIMING_2, 0x30118},
{DSI_BTA_TIMING, 0x190A14},
/* DSI timeout */
{DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xFFFF)},
{DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x1343) | DSI_TIMEOUT_TA(0x2000)},
{DSI_TO_TALLY, 0},
{DSI_HOST_CONTROL, DSI_HOST_CONTROL_CRC_RESET | DSI_HOST_CONTROL_TX_TRIG_HOST | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC},
{DSI_CONTROL, DSI_CONTROL_LANES(3) | DSI_CONTROL_HOST_ENABLE},
{DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE},
{DSI_MAX_THRESHOLD, 64},
{DSI_TRIGGER, 0},
{DSI_TX_CRC, 0},
{DSI_INIT_SEQ_CONTROL, 0}
};
// DSI panel JDI deinit config.
static const reg_cfg_t _di_dsi_panel_deinit_config_jdi[] = {
{DSI_WR_DATA, 0x439}, // MIPI_DSI_DCS_LONG_WRITE: 4 bytes.