您尚未登录。

楼主 # 2025-05-25 18:43:39

william9527
会员
注册时间: 2025-05-18
已发帖子: 12
积分: 22

T113-S3和Tina2.0使用8080接口16位并行LCD屏幕时一定要加上这条指令

自从用F1C200S调试8080接口16位并行LCD屏幕成功后,就迫不及待的用T113-S3做实验,本来想着挺简单的,但是被一条指令搞了一天,就是它:

if (info->lcd_cpu_mode == LCD_CPU_AUTO_MODE)
{
	DBG_INFO(" cpu auto mode.\n");
	sunxi_lcd_cpu_set_auto_mode(sel);
}

不知道是不是我的LCD特殊的原因,看着别人的屏幕不用这条指令也能点亮,无语中,LCD屏幕是ST7796SV芯片,背光PWM用的是PWM4(PE10),屏幕RESET管脚是PG10,未开启“TE”模式。写一下配置,为后面的兄弟避坑了。
board.dts

&pio {
        ......
        rgb16_pins_a: rgb16@0 {
		allwinner,pins = "PD1", "PD2", "PD3", "PD4", "PD5", \
			"PD6", "PD7", "PD8", "PD10", "PD11", "PD12", \
			"PD13", "PD14", "PD15", "PD16", "PD17", \
			"PD18", "PD19", "PD20", "PD21";
		allwinner,pname = "lcdb0", "lcdb1", "lcdb2", "lcdb3", "lcdb4", \
			"lcdg0", "lcdg1", "lcdg2", "lcdg3", "lcdg4", "lcdg5", \
			"lcdr0", "lcdr1", "lcdr2", "lcdr3", "lcdr4", \
			"lcdwr", "lcdrs", "lcdrd", "lcdcs";
		allwinner,function = "lcd0";
		allwinner,muxsel = <2>;
		allwinner,drive = <3>;
		allwinner,pull = <0>;
	};

	rgb16_pins_b: rgb16@1 {
		allwinner,pins = "PD1", "PD2", "PD3", "PD4", "PD5", \
			"PD6", "PD7", "PD8", "PD10", "PD11", "PD12", \
			"PD13", "PD14", "PD15", "PD16", "PD17", \
			"PD18", "PD19", "PD20", "PD21";
		allwinner,pname = "lcdb0", "lcdb1", "lcdb2", "lcdb3", "lcdb4", \
			"lcdg0", "lcdg1", "lcdg2", "lcdg3", "lcdg4", "lcdg5", \
			"lcdr0", "lcdr1", "lcdr2", "lcdr3", "lcdr4", \
			"lcdwr", "lcdrs", "lcdrd", "lcdcs";
		allwinner,function = "io_disabled";
		allwinner,muxsel = <7>;
		allwinner,drive = <3>;
		allwinner,pull = <0>;
	};
}

/* 8080i 16bit */
&lcd0 {
	// part 1
	lcd_used            = <1>;
	lcd_driver_name     = "st7796sv_cpu";

	// part 2
	lcd_if              = <1>;
	lcd_cpu_if	      = <8>;

	// part 3
	lcd_x               = <480>;
	lcd_y               = <320>;
	lcd_width           = <84>;
	lcd_height          = <56>;
	lcd_dclk_freq       = <24>;

	lcd_hbp             = <100>;
	lcd_ht              = <618>;
	lcd_hspw            = <50>;
	lcd_vbp             = <8>;
	lcd_vt              = <336>;
	lcd_vspw            = <4>;

	// part 4
	lcd_pwm_used        = <1>;
	lcd_pwm_ch          = <4>;
	lcd_pwm_freq        = <50000>;
	lcd_pwm_pol         = <1>;
	lcd_pwm_max_limit   = <255>;
	lcd_backlight       = <150>;

	// part 5
	lcd_cpu_mode        = <0>;
	lcd_cpu_te          = <0>;

	// part 6
	lcd_frm             = <0>;
	lcd_gamma_en        = <0>;
	lcd_cmap_en         = <0>;
	lcd_rb_swap			= <0>;

	// part 7
	// reset pin
	lcd_gpio_0 = <&pio PG 10 1 0 3 1>;

	pinctrl-0 = <&rgb16_pins_a>;
	pinctrl-1 = <&rgb16_pins_b>;
};

st7796sv_cpu.c

#include "st7796sv_cpu.h"

// #define CPU_TRI_MODE

#define DBG_INFO(format, args...) (printk("[ST7796SV LCD INFO] LINE:%04d-->%s:"format, __LINE__, __func__, ##args))
#define DBG_ERR(format, args...) (printk("[ST7796SV LCD ERR] LINE:%04d-->%s:"format, __LINE__, __func__, ##args))
#define panel_reset(val) sunxi_lcd_gpio_set_value(sel, 0, val)
// #define lcd_cs(val)  sunxi_lcd_gpio_set_value(sel, 1, val)

#define LCD_WIDTH 480
#define LCD_HEIGHT 320

#define MADCTL_MY   0x80  // 纵向交换
#define MADCTL_MX   0x40  // 横向交换
#define MADCTL_MV   0x20  // 纵横交换
#define MADCTL_ML   0x10  // 从下到上刷新
#define MADCTL_RGB  0x00  // RGB
#define MADCTL_BGR  0x08  // BGR
#define MADCTL_MH   0x04  // 从右到左刷新

typedef enum
{
    LCD_DIRECTION_0,
    LCD_DIRECTION_90,
    LCD_DIRECTION_180,
    LCD_DIRECTION_270
} eLcdDirection;

static void lcd_panel_st7796sv_init(u32 sel, struct disp_panel_para *info);
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);

static void LCD_cfg_panel_info(struct panel_extend_para *info)
{
}

static s32 LCD_open_flow(u32 sel)
{
	LCD_OPEN_FUNC(sel, LCD_power_on, 120);
#ifdef CPU_TRI_MODE
	LCD_OPEN_FUNC(sel, LCD_panel_init, 100);
	LCD_OPEN_FUNC(sel, sunxi_lcd_tcon_enable, 50);
#else
	LCD_OPEN_FUNC(sel, sunxi_lcd_tcon_enable, 100);
	LCD_OPEN_FUNC(sel, LCD_panel_init, 50);
#endif
	LCD_OPEN_FUNC(sel, LCD_bl_open, 0);

	return 0;
}

static s32 LCD_close_flow(u32 sel)
{
	LCD_CLOSE_FUNC(sel, LCD_bl_close, 20);
#ifdef CPU_TRI_MODE
	LCD_CLOSE_FUNC(sel, sunxi_lcd_tcon_disable, 10);
	LCD_CLOSE_FUNC(sel, LCD_panel_exit, 50);
#else
	LCD_CLOSE_FUNC(sel, LCD_panel_exit, 10);
	LCD_CLOSE_FUNC(sel, sunxi_lcd_tcon_disable, 10);
#endif
	LCD_CLOSE_FUNC(sel, LCD_power_off, 0);

	return 0;
}

static void LCD_power_on(u32 sel)
{
	/*config lcd_power pin to open lcd power0 */
	sunxi_lcd_power_enable(sel, 0);
	sunxi_lcd_pin_cfg(sel, 1);
}

static void LCD_power_off(u32 sel)
{
	/*lcd_cs, active low */
	// lcd_cs(1);
	sunxi_lcd_delay_ms(10);
	/*lcd_rst, active hight */
	panel_reset(1);
	sunxi_lcd_delay_ms(10);

	sunxi_lcd_pin_cfg(sel, 0);
	/*config lcd_power pin to close lcd power0 */
	sunxi_lcd_power_disable(sel, 0);
}

static void LCD_bl_open(u32 sel)
{
	sunxi_lcd_pwm_enable(sel);
	/*config lcd_bl_en pin to open lcd backlight */
	sunxi_lcd_backlight_enable(sel);
}

static void LCD_bl_close(u32 sel)
{
	/*config lcd_bl_en pin to close lcd backlight */
	sunxi_lcd_backlight_disable(sel);
	sunxi_lcd_pwm_disable(sel);
}

/*static int bootup_flag = 0;*/
static void LCD_panel_init(u32 sel)
{
	struct disp_panel_para *info =
	    kmalloc(sizeof(struct disp_panel_para), GFP_KERNEL);

	DBG_INFO("\n");
	bsp_disp_get_panel_info(sel, info);
	lcd_panel_st7796sv_init(sel, info);

	kfree(info);
	return;
}

static void LCD_panel_exit(u32 sel)
{
	sunxi_lcd_cpu_write_index(sel, 0x28);
	sunxi_lcd_cpu_write_index(sel, 0x10);
}

void lcdSetWindows(u32 sel, u16 x, u16 y, u16 width, u16 height)
{
    u16 temp;

    // 横向
    temp = x + width - 1;
    if (temp >= LCD_WIDTH) {
        temp = LCD_WIDTH - 1;
    }

    sunxi_lcd_cpu_write_index(sel, 0x2a);
    sunxi_lcd_cpu_write_data(sel, (x >> 8) & 0xFF); 
    sunxi_lcd_cpu_write_data(sel, x & 0xFF);
    sunxi_lcd_cpu_write_data(sel, (temp >> 8) && 0xFF); 
    sunxi_lcd_cpu_write_data(sel, temp & 0xFF);

    // 纵向
    temp = y + height - 1;
    if (temp >= LCD_HEIGHT) {
        temp = LCD_HEIGHT - 1;
    }

    sunxi_lcd_cpu_write_index(sel, 0x2b);
    sunxi_lcd_cpu_write_data(sel, (y >> 8) && 0xFF); 
    sunxi_lcd_cpu_write_data(sel, y & 0xFF);
    sunxi_lcd_cpu_write_data(sel, (temp >> 8) && 0xFF); 
    sunxi_lcd_cpu_write_data(sel, temp & 0xFF);

    // 开始写入屏幕
    sunxi_lcd_cpu_write_index(sel, 0x2c);
}

void lcdSetDirection(u32 sel, eLcdDirection dir)
{
    u8 temp = 0;

    switch (dir) {
    case LCD_DIRECTION_0:
        temp = MADCTL_MX;
        break;

    case LCD_DIRECTION_90:
        temp = MADCTL_MV;
        break;

    case LCD_DIRECTION_180:
        temp = MADCTL_MY;
        break;

    case LCD_DIRECTION_270:
        temp = MADCTL_MY | MADCTL_MX | MADCTL_MV;
        break;

    default:
        break;
    }

    temp |= MADCTL_BGR;

    sunxi_lcd_cpu_write_index(sel, 0x36);
    sunxi_lcd_cpu_write_data(sel, temp);

    lcdSetWindows(sel, 0, 0, LCD_WIDTH, LCD_HEIGHT);
}

static void lcd_panel_st7796sv_init(u32 sel, struct disp_panel_para *info)
{
	u8 initCmd[] = {
        0x81, 0x11,
        2, 0xfb, 0xc3,
        2, 0xfb, 0x96,
        2, 0x36, 0x48,
        2, 0x3a, 0x55,
        2, 0xb4, 0x01,
        2, 0xb7, 0xc6,
        9, 0xe8, 0x40, 0x8a, 0x00, 0x00, 0x29, 0x19, 0xa5, 0x33,
        2, 0xc1, 0x06,
        2, 0xc2, 0xa7,
        2, 0xc5, 0x18,
        15, 0xe0, 0x0F, 0x09, 0x0b, 0x06, 0x04, 0x15, 0x2f, 0X54, 0x42, 0x3c, 0x17, 0x14, 0x18, 0x1b,
        15, 0xe1, 0xf0, 0x09, 0x0b, 0x06, 0x04, 0x03, 0x2d, 0x43, 0x42, 0x3b, 0x16, 0x14, 0x17, 0x1b,
        2, 0xeb, 0x3c,
        0x82, 0xeb, 0x69,
        1, 0x29,
        0x00
    };

    u8* cmdIndex = initCmd;
    u8 count, temp;
    u16 index;

    DBG_INFO(" %d, %d\n", info->lcd_x, info->lcd_y);

    /*lcd_cs, active low */
    // lcd_cs(0);

    // reset
    panel_reset(1);
    sunxi_lcd_delay_ms(10);
    panel_reset(0);
    sunxi_lcd_delay_ms(20);
    panel_reset(1);
    sunxi_lcd_delay_ms(150);

    // init lcd
    while (*cmdIndex) {
        temp = *cmdIndex++;
        count = (temp & 0x7F) - 1;

		sunxi_lcd_cpu_write_index(sel, *cmdIndex++);

        for (index = 0; index < count; ++index)
        {
            sunxi_lcd_cpu_write_data(sel, *cmdIndex++);
        }

        if (temp >= 0x80) {
            sunxi_lcd_delay_ms(150);
        }
    }

#if defined(CPU_TRI_MODE)
	/* enable te, mode 0 */

	sunxi_lcd_cpu_write_index(0, 0x35);
	sunxi_lcd_cpu_write_data(0, 0x00);

	sunxi_lcd_cpu_write_index(0, 0x44);
	sunxi_lcd_cpu_write_data(0, 0x00);
	sunxi_lcd_cpu_write_data(0, 0x80);
#endif

	lcdSetDirection(sel, LCD_DIRECTION_90);

	sunxi_lcd_cpu_write_index(sel, 0x2c);

	if (info->lcd_cpu_mode == LCD_CPU_AUTO_MODE)
	{
		DBG_INFO(" cpu auto mode.\n");
		sunxi_lcd_cpu_set_auto_mode(sel);
	}
}


/* panel driver name, must mach the name of lcd_drv_name in sys_config.fex */
struct __lcd_panel st7796sv_cpu_panel = {
	.name = "st7796sv_cpu",
	.func = {
		.cfg_panel_info = LCD_cfg_panel_info,
		.cfg_open_flow = LCD_open_flow,
		.cfg_close_flow = LCD_close_flow,
	},
};

t113UseTFT.png

离线

页脚

工信部备案:粤ICP备20025096号 Powered by FluxBB

感谢为中文互联网持续输出优质内容的各位老铁们。 QQ: 516333132, 微信(wechat): whycan_cn (哇酷网/挖坑网/填坑网) service@whycan.cn