设备树配置
&lcd0 {
base_config_start = <1>;
lcd_used = <1>;
lcd_driver_name = "d320fpc2403";
lcd_backlight = <50>;
lcd_if = <4>;
lcd_x = <1024>;
lcd_y = <768>;
lcd_width = <64>;
lcd_height = <48>;
lcd_dclk_freq = <54>;
lcd_pwm_used = <1>;
lcd_pwm_ch = <9>;
lcd_pwm_freq = <5000>;
lcd_pwm_pol = <1>;
lcd_pwm_max_limit = <255>;
lcd_hbp = <50>;
lcd_ht = <1114>;
lcd_hspw = <10>;
lcd_vbp = <29>;
lcd_vt = <809>;
lcd_vspw = <8>;
lcd_dsi_if = <0>;
lcd_dsi_lane = <4>;
lcd_dsi_format = <0>;
lcd_dsi_te = <0>;
lcd_dsi_eotp = <0>;
lcd_frm = <0>;
lcd_io_phase = <0x0000>;
lcd_hv_clk_phase = <0>;
lcd_hv_sync_polarity= <0>;
lcd_gamma_en = <0>;
lcd_bright_curve_en = <0>;
lcd_cmap_en = <0>;
lcdgamma4iep = <22>;
lcd_gpio_0 = <&pio PE 17 1 0 3 1>;
pinctrl-0 = <&dsi4lane_pins_a>;
pinctrl-1 = <&dsi4lane_pins_b>;
base_config_end = <1>;
};
驱动
/* drivers/video/sunxi/disp2/disp/lcd/d320fpc2403.c
*
* Copyright (c) 2025 Weidongshan <weidongshan@qq.com>
*
* d320fpc2403 panel driver
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include "d320fpc2403.h"
static void lcd_power_on(u32 sel);
static void lcd_power_off(u32 sel);
static void lcd_bl_open(u32 sel);
static void lcd_bl_close(u32 sel);
static void lcd_panel_init(u32 sel);
static void lcd_panel_exit(u32 sel);
#define panel_reset(sel, val) sunxi_lcd_gpio_set_value(sel, 0, val)
static void lcd_cfg_panel_info(struct panel_extend_para *info)
{
u32 i = 0, j = 0;
u32 items;
u8 lcd_gamma_tbl[][2] = {
{ 0, 0 }, { 15, 15 }, { 30, 30 }, { 45, 45 },
{ 60, 60 }, { 75, 75 }, { 90, 90 }, { 105, 105 },
{ 120, 120 }, { 135, 135 }, { 150, 150 }, { 165, 165 },
{ 180, 180 }, { 195, 195 }, { 210, 210 }, { 225, 225 },
{ 240, 240 }, { 255, 255 },
};
u32 lcd_cmap_tbl[2][3][4] = {
{
{ LCD_CMAP_G0, LCD_CMAP_B1, LCD_CMAP_G2, LCD_CMAP_B3 },
{ LCD_CMAP_B0, LCD_CMAP_R1, LCD_CMAP_B2, LCD_CMAP_R3 },
{ LCD_CMAP_R0, LCD_CMAP_G1, LCD_CMAP_R2, LCD_CMAP_G3 },
},
{
{ LCD_CMAP_B3, LCD_CMAP_G2, LCD_CMAP_B1, LCD_CMAP_G0 },
{ LCD_CMAP_R3, LCD_CMAP_B2, LCD_CMAP_R1, LCD_CMAP_B0 },
{ LCD_CMAP_G3, LCD_CMAP_R2, LCD_CMAP_G1, LCD_CMAP_R0 },
},
};
items = sizeof(lcd_gamma_tbl) / 2;
for (i = 0; i < items - 1; i++) {
u32 num = lcd_gamma_tbl[i + 1][0] - lcd_gamma_tbl[i][0];
for (j = 0; j < num; j++) {
u32 value = 0;
value = lcd_gamma_tbl[i][1] +
((lcd_gamma_tbl[i + 1][1] -
lcd_gamma_tbl[i][1]) *
j) / num;
info->lcd_gamma_tbl[lcd_gamma_tbl[i][0] + j] =
(value << 16) + (value << 8) + value;
}
}
info->lcd_gamma_tbl[255] = (lcd_gamma_tbl[items - 1][1] << 16) +
(lcd_gamma_tbl[items - 1][1] << 8) +
lcd_gamma_tbl[items - 1][1];
memcpy(info->lcd_cmap_tbl, lcd_cmap_tbl, sizeof(lcd_cmap_tbl));
}
static s32 lcd_open_flow(u32 sel)
{
LCD_OPEN_FUNC(sel, lcd_power_on, 120);
LCD_OPEN_FUNC(sel, lcd_panel_init, 10);
LCD_OPEN_FUNC(sel, sunxi_lcd_tcon_enable, 10);
LCD_OPEN_FUNC(sel, lcd_bl_open, 0);
return 0;
}
static s32 lcd_close_flow(u32 sel)
{
LCD_CLOSE_FUNC(sel, lcd_bl_close, 0);
LCD_CLOSE_FUNC(sel, lcd_panel_exit, 200);
LCD_CLOSE_FUNC(sel, sunxi_lcd_tcon_disable, 0);
LCD_CLOSE_FUNC(sel, lcd_power_off, 500);
return 0;
}
static void lcd_power_on(u32 sel)
{
/* reset lcd by gpio */
panel_reset(sel, 1);
sunxi_lcd_delay_ms(100);
panel_reset(sel, 0);
sunxi_lcd_delay_ms(500);
panel_reset(sel, 1);
sunxi_lcd_delay_ms(500);
sunxi_lcd_pin_cfg(sel, 1);
}
static void lcd_power_off(u32 sel)
{
sunxi_lcd_pin_cfg(sel, 0);
sunxi_lcd_delay_ms(20);
panel_reset(sel, 0);
sunxi_lcd_delay_ms(5);
}
static void lcd_bl_open(u32 sel)
{
sunxi_lcd_pwm_enable(sel);
}
static void lcd_bl_close(u32 sel)
{
sunxi_lcd_backlight_disable(sel);
}
#define REGFLAG_DELAY 0XFC
#define REGFLAG_END_OF_TABLE 0xFD /* END OF REGISTERS MARKER */
struct LCM_setting_table {
u8 cmd;
u32 count;
u8 para_list[64];
};
static struct LCM_setting_table lcm_initialization_setting[] = {
{ 0xdf, 3, { 0x91, 0x68, 0xf9 } },
{ 0xde, 1, { 0x00 } },
// {0xc2, 1, {0x30}},
{ 0xb2, 2, { 0x00, 0x7e } },
{ 0xb3, 2, { 0x00, 0x7e } },
{ 0xc1, 6, { 0x00, 0x10, 0x00, 0x00, 0x00, 0x00 } },
{ 0xbb, 7, { 0x02, 0x24, 0x07, 0x61, 0x19, 0x44, 0x44 } },
{ 0xbe, 2, { 0x1a, 0xf2 } },
{ 0xc3,
14,
{ 0x10, 0x17, 0x5a, 0x17, 0x5a, 0x05, 0x05, 0x05, 0x05, 0x15, 0x15,
0x31, 0x05, 0xdf } },
{ 0xc4, 7, { 0x11, 0x80, 0x00, 0xdf, 0x09, 0x06, 0x14 } },
{ 0xce, 23, { 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x0f, 0x03 } },
{ 0xcf, 9, { 0x00, 0x01, 0x40, 0x01, 0xca, 0x01, 0xca, 0x01, 0xca } },
{ 0xd0, 23, { 0x00, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
0x1f, 0x1f, 0x1f, 0x03, 0x01, 0x05, 0x07, 0x09,
0x0b, 0x1e, 0x15, 0x1f, 0x1f, 0x15, 0x1f } },
{ 0xd1, 23, { 0x00, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
0x1f, 0x1f, 0x1f, 0x02, 0x00, 0x04, 0x06, 0x08,
0x0a, 0x1e, 0x15, 0x1f, 0x1f, 0x15, 0x1f } },
{ 0xd2, 23, { 0x00, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
0x1f, 0x1f, 0x1f, 0x00, 0x02, 0x0a, 0x08, 0x06,
0x04, 0x1f, 0x15, 0x1f, 0x1f, 0x15, 0x1e } },
{ 0xd3, 23, { 0x00, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
0x1f, 0x1f, 0x1f, 0x01, 0x03, 0x0b, 0x09, 0x07,
0x05, 0x1f, 0x15, 0x1f, 0x1f, 0x15, 0x1e } },
{ 0xd4, 37, { 0x30, 0x00, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x11, 0x00,
0x01, 0xc0, 0x04, 0x01, 0x01, 0x11, 0x80, 0x01,
0xc0, 0x05, 0x01, 0x01, 0x00, 0x00, 0x00, 0x04,
0x00, 0x06, 0x18, 0x02, 0xe3 } },
{ 0xd5, 8, { 0x68, 0x73, 0x00, 0x08, 0x08, 0x00, 0x03, 0x00 } },
{ 0xb7, 6, { 0x00, 0xd8, 0x00, 0x00, 0xd8, 0x00 } },
{ 0xc8, 38, { 0x7f, 0x69, 0x5a, 0x4e, 0x4a, 0x3b, 0x40, 0x2a,
0x44, 0x43, 0x44, 0x63, 0x51, 0x59, 0x4c, 0x48,
0x3a, 0x28, 0x0f, 0x7f, 0x69, 0x5a, 0x4e, 0x4a,
0x3b, 0x40, 0x2a, 0x44, 0x43, 0x44, 0x63, 0x51,
0x59, 0x4c, 0x48, 0x3a, 0x28, 0x0f } },
{ 0xde, 1, { 0x02 } },
{ 0xbb, 4, { 0x00, 0x5b, 0x5c, 0x41 } },
{ 0xb5, 3, { 0x00, 0x5a, 0x0a } },
{ 0xc6, 1, { 0x22 } },
{ 0xd7, 1, { 0x12 } },
{ 0xe7, 2, { 0x00, 0x00 } },
{ 0xde, 1, { 0x04 } },
{ 0xcc, 1, { 0x02 } },
{ 0xe7, 1, { 0x01 } },
{ 0xde, 1, { 0x00 } },
{ 0x35, 1, { 0x00 } },
{ 0x11, 0, { 0x00 } },
{ REGFLAG_DELAY, REGFLAG_DELAY, { 120 } },
{ 0x29, 0, { 0x00 } },
{ REGFLAG_DELAY, REGFLAG_DELAY, { 20 } },
{ REGFLAG_END_OF_TABLE, REGFLAG_END_OF_TABLE, {} },
};
static void lcd_panel_init(u32 sel)
{
u32 i = 0;
sunxi_lcd_dsi_clk_enable(sel);
sunxi_lcd_delay_ms(100);
for (i = 0;; i++) {
if (lcm_initialization_setting[i].cmd == REGFLAG_END_OF_TABLE)
break;
else if (lcm_initialization_setting[i].cmd == REGFLAG_DELAY)
sunxi_lcd_delay_ms(lcm_initialization_setting[i].count);
else {
dsi_dcs_wr(0, lcm_initialization_setting[i].cmd,
lcm_initialization_setting[i].para_list,
lcm_initialization_setting[i].count);
}
}
}
static void lcd_panel_exit(u32 sel)
{
sunxi_lcd_dsi_dcs_write_0para(sel, 0x28);
sunxi_lcd_delay_ms(80);
sunxi_lcd_dsi_dcs_write_0para(sel, 0x10);
sunxi_lcd_delay_ms(50);
}
/*sel: 0:lcd0; 1:lcd1*/
static s32 lcd_user_defined_func(u32 sel, u32 para1, u32 para2, u32 para3)
{
return 0;
}
struct __lcd_panel d320fpc2403_panel = {
/* panel driver name, must mach the name of
* lcd_drv_name in sys_config.fex
*/
.name = "d320fpc2403",
.func =
{
.cfg_panel_info = lcd_cfg_panel_info,
.cfg_open_flow = lcd_open_flow,
.cfg_close_flow = lcd_close_flow,
.lcd_user_defined_func = lcd_user_defined_func,
},
};

