导航

    全志在线开发者论坛

    • 注册
    • 登录
    • 搜索
    • 版块
    • 话题
    • 在线文档
    • 社区主页

    T113 tina linux 适配 ili9488 屏幕 i80 16bit

    爱搞机专区
    5
    8
    4623
    正在加载更多帖子
    • 从旧到新
    • 从新到旧
    • 最多赞同
    回复
    • 在新帖中回复
    登录后回复
    此主题已被删除。只有拥有主题管理权限的用户可以查看。
    • hsinyuwang
      hsinyuwang LV 6 最后由 编辑

      前言

      在上一篇文章已经搞定了 T113 tina linux 移植 gpsp 模拟器 接下来适配屏幕驱动。
      因为 GBA 原生分辨率是 240x160,所以屏幕选用的是 480x320 的 ili9488,正好可以整数倍缩放。

      初始化屏幕

      先从 tina linux 自带的驱动中 copy 一份 st7789v_cpu 的代码,然后对照 ili9488 屏幕厂商提供的初始化代码做修改

      a17e9449-0aef-4c18-b866-6d4fcde83329-image.png
      完整代码

      /*
       * drivers/video/fbdev/sunxi/disp2/disp/lcd/ili9488_cpu.c
       *
       * Copyright (c) 2007-2018 Allwinnertech Co., Ltd.
       * Author: zhengxiaobin <zhengxiaobin@allwinnertech.com>
       *
       * This software is licensed under the terms of the GNU General Public
       * License version 2, as published by the Free Software Foundation, and
       * may be copied, distributed, and modified under those terms.
       *
       * This program is distributed in the hope that it will be useful,
       * but WITHOUT ANY WARRANTY; without even the implied warranty of
       * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       * GNU General Public License for more details.
       *
       *
       */
      
      #include "ili9488_cpu.h"
      
      #define CPU_TRI_MODE
      
      #define DBG_INFO(format, args...) (printk("[ILI9488 LCD INFO] LINE:%04d-->%s:"format, __LINE__, __func__, ##args))
      #define DBG_ERR(format, args...) (printk("[ILI9488 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)
      
      static void lcd_panel_ili9488_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)
      {
      #if 0
      	u32 i = 0, j = 0;
      	u32 items;
      	u8 lcd_gamma_tbl[][2] = {
      	    //{input value, corrected value}
      	    {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));
      #endif
      }
      
      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_ili9488_init(sel, info);
      
      	kfree(info);
      	return;
      }
      
      static void LCD_panel_exit(u32 sel)
      {
      	sunxi_lcd_cpu_write_index(0, 0x28);
          sunxi_lcd_delay_ms(10);
      	sunxi_lcd_cpu_write_index(0, 0x10);
          sunxi_lcd_delay_ms(120);
      }
      
      
      static void lcd_panel_ili9488_init(u32 sel, struct disp_panel_para *info)
      {
      	DBG_INFO("\n");
      	/*lcd_cs, active low */
      	lcd_cs(0);
      	sunxi_lcd_delay_ms(10);
      	panel_reset(1);
      	sunxi_lcd_delay_ms(20);
      	panel_reset(0);
      	sunxi_lcd_delay_ms(20);
      	panel_reset(1);
      	sunxi_lcd_delay_ms(120);
      
      	sunxi_lcd_cpu_write_index(0, 0xF7);
      	sunxi_lcd_cpu_write_data(0, 0xA9);
      	sunxi_lcd_cpu_write_data(0, 0x51);
      	sunxi_lcd_cpu_write_data(0, 0x2C);
      	sunxi_lcd_cpu_write_data(0, 0x82);
      
      	sunxi_lcd_cpu_write_index(0, 0xC0);
      	sunxi_lcd_cpu_write_data(0, 0x11);
      	sunxi_lcd_cpu_write_data(0, 0x09);
      
      	sunxi_lcd_cpu_write_index(0, 0xC1);
      	sunxi_lcd_cpu_write_data(0, 0x41);
      
      	sunxi_lcd_cpu_write_index(0, 0xC5);
      	sunxi_lcd_cpu_write_data(0, 0x00);
      	sunxi_lcd_cpu_write_data(0, 0x2A);
      	sunxi_lcd_cpu_write_data(0, 0x80);
      
      	sunxi_lcd_cpu_write_index(0, 0xB1);
      	sunxi_lcd_cpu_write_data(0, 0xB0);
      	sunxi_lcd_cpu_write_data(0, 0x11);
      
      	sunxi_lcd_cpu_write_index(0, 0xB4);
      	sunxi_lcd_cpu_write_data(0, 0x02);
      
      	sunxi_lcd_cpu_write_index(0, 0xB6);
      	sunxi_lcd_cpu_write_data(0, 0x02);
      	sunxi_lcd_cpu_write_data(0, 0x22);
      
      	sunxi_lcd_cpu_write_index(0, 0xB7);
      	sunxi_lcd_cpu_write_data(0, 0xC6);
      
      	sunxi_lcd_cpu_write_index(0, 0xBE);
      	sunxi_lcd_cpu_write_data(0, 0x00);
      	sunxi_lcd_cpu_write_data(0, 0x04);
      
      	sunxi_lcd_cpu_write_index(0, 0xE9);
      	sunxi_lcd_cpu_write_data(0, 0x00);
      
      	sunxi_lcd_cpu_write_index(0, 0x3A);
      	sunxi_lcd_cpu_write_data(0, 0x55);
      
      	sunxi_lcd_cpu_write_index(0, 0xE0);
      	sunxi_lcd_cpu_write_data(0, 0x00);
      	sunxi_lcd_cpu_write_data(0, 0x07);
      	sunxi_lcd_cpu_write_data(0, 0x12);
      	sunxi_lcd_cpu_write_data(0, 0x0B);
      	sunxi_lcd_cpu_write_data(0, 0x18);
      	sunxi_lcd_cpu_write_data(0, 0x0B);
      	sunxi_lcd_cpu_write_data(0, 0x3F);
      	sunxi_lcd_cpu_write_data(0, 0x9B);
      	sunxi_lcd_cpu_write_data(0, 0x4B);
      	sunxi_lcd_cpu_write_data(0, 0x0B);
      	sunxi_lcd_cpu_write_data(0, 0x0F);
      	sunxi_lcd_cpu_write_data(0, 0x0B);
      	sunxi_lcd_cpu_write_data(0, 0x15);
      	sunxi_lcd_cpu_write_data(0, 0x17);
      	sunxi_lcd_cpu_write_data(0, 0x0F);
      
      	sunxi_lcd_cpu_write_index(0, 0xE1);
      	sunxi_lcd_cpu_write_data(0, 0x00);
      	sunxi_lcd_cpu_write_data(0, 0x16);
      	sunxi_lcd_cpu_write_data(0, 0x1B);
      	sunxi_lcd_cpu_write_data(0, 0x02);
      	sunxi_lcd_cpu_write_data(0, 0x0F);
      	sunxi_lcd_cpu_write_data(0, 0x06);
      	sunxi_lcd_cpu_write_data(0, 0x34);
      	sunxi_lcd_cpu_write_data(0, 0x46);
      	sunxi_lcd_cpu_write_data(0, 0x48);
      	sunxi_lcd_cpu_write_data(0, 0x04);
      	sunxi_lcd_cpu_write_data(0, 0x0D);
      	sunxi_lcd_cpu_write_data(0, 0x0D);
      	sunxi_lcd_cpu_write_data(0, 0x35);
      	sunxi_lcd_cpu_write_data(0, 0x36);
      	sunxi_lcd_cpu_write_data(0, 0x0F);
      
      	sunxi_lcd_cpu_write_index(0, 0x2A);
      	sunxi_lcd_cpu_write_data(0, 0x00);
      	sunxi_lcd_cpu_write_data(0, 0x00);
      	sunxi_lcd_cpu_write_data(0, 0x01);
      	sunxi_lcd_cpu_write_data(0, 0xDF);
      
      	sunxi_lcd_cpu_write_index(0, 0x2B);
      	sunxi_lcd_cpu_write_data(0, 0x00);
      	sunxi_lcd_cpu_write_data(0, 0x00);
      	sunxi_lcd_cpu_write_data(0, 0x01);
      	sunxi_lcd_cpu_write_data(0, 0x3F);
      
      	sunxi_lcd_cpu_write_index(0, 0x36);
      	sunxi_lcd_cpu_write_data(0, 0x68);
      
      
      #if defined(CPU_TRI_MODE)
      	/* enable te, mode 0 */
      
      	sunxi_lcd_cpu_write_index(0, 0x35);
      	sunxi_lcd_cpu_write_data(0, 0x00);
      
      #endif
      	sunxi_lcd_cpu_write_index(0, 0x11);
      	sunxi_lcd_delay_ms(120);
      	sunxi_lcd_cpu_write_index(0, 0x29);
      	sunxi_lcd_cpu_write_index(0, 0x2c);
      }
      
      
      /* panel driver name, must mach the name of lcd_drv_name in sys_config.fex */
      struct __lcd_panel ili9488_cpu_panel = {
      	.name = "ili9488_cpu",
      	.func = {
      		.cfg_panel_info = LCD_cfg_panel_info,
      		.cfg_open_flow = LCD_open_flow,
      		.cfg_close_flow = LCD_close_flow,
      	},
      };
      
      

      Kconfig 添加

      config LCD_SUPPORT_ILI9488_CPU
      	bool "LCD support ili9488_cpu panel"
      	default n
      	---help---
      		If you want to support ili9488_cpu panel for display driver, select it.
      
      

      Makefile 添加

      disp-$(CONFIG_LCD_SUPPORT_ILI9488_CPU) += lcd/ili9488_cpu.o
      

      panels.c 添加

      #ifdef CONFIG_LCD_SUPPORT_ILI9488_CPU
      	&ili9488_cpu_panel,
      #endif
      

      panels.h 添加

      #ifdef CONFIG_LCD_SUPPORT_ILI9488_CPU
      extern struct __lcd_panel ili9488_cpu_panel;
      #endif
      

      再打开 m kernel_menuconfig

      Device Drivers  --->
      	Graphics support  ---> 
      		Frame buffer Devices  --->
      			Video support for sunxi  --->
      				LCD panels select  --->
      					 [*] LCD support ili9488_cpu panel   
      

      修改 board.dts

      disp

      &disp {
      	disp_init_enable         = <1>;
      	disp_mode                = <0>;
      
      	screen0_output_type      = <1>;
      	screen0_output_mode      = <4>;
      
      	screen1_output_type      = <3>;
      	screen1_output_mode      = <4>;
      	
      	screen1_output_format    = <0>;
      	screen1_output_bits      = <0>;
      	screen1_output_eotf      = <4>;
      	screen1_output_cs        = <257>;
      	screen1_output_dvi_hdmi  = <2>;
      	screen1_output_range     = <2>;
      	screen1_output_scan      = <0>;
      	screen1_output_aspect_ratio = <8>;
      	dev0_output_type         = <1>;
      	dev0_output_mode         = <4>;
      	dev0_screen_id           = <0>;
      	dev0_do_hpd              = <0>;
      
      	dev1_output_type         = <4>;
      	dev1_output_mode         = <10>;
      	dev1_screen_id           = <1>;
      	dev1_do_hpd              = <1>;
      
      	def_output_dev           = <1>;
      	hdmi_mode_check          = <3>;
      	disp_rotation_used		 = <1>;
      	degree0					 = <0>;
      	fb0_format               = <10>;
      	fb0_buffer_num           = <1>;	
      	/*fb0_width                = <800>;*/
      	/*fb0_height               = <480>;*/  /*read from lcd*/
      	fb1_format               = <0>;
      	fb1_width                = <0>;
      	fb1_height               = <0>;
      	chn_cfg_mode             = <1>;
      
      	disp_para_zone           = <1>;
      	/*VCC-LCD*/
      /*	dc1sw-supply = <&reg_dc1sw>;*/
      	/*VCC-DSI*/
      /*	eldo3-supply = <&reg_eldo3>;*/
      	/*VCC-PD*/
      /*	dcdc1-supply = <&reg_dcdc1>;*/
      };
      

      lcd0

      &lcd0 {
      
      	/* part 1 */
      	lcd_used            = <1>;
      	lcd_driver_name     = "ili9488_cpu";
      
      	/* part 2 */
      	lcd_if              = <1>;
      	lcd_cpu_if	        = <8>;
      
      	/* part 3 */
      	lcd_x               = <480>;
      	lcd_y               = <320>;
      	lcd_width           = <72>;
      	lcd_height          = <48>;
      	lcd_dclk_freq       = <10>;
      	lcd_hbp             = <2>;
      	lcd_ht              = <486>;
      	lcd_hspw            = <2>;
      	lcd_vbp             = <20>;
      	lcd_vt              = <342>;
      	lcd_vspw            = <2>;
      
      	/* part 4 */
      	lcd_pwm_used        = <1>;
      	lcd_pwm_ch          = <8>;
      	lcd_pwm_freq        = <50000>;
      	lcd_pwm_pol         = <1>;
      	lcd_pwm_max_limit   = <255>;
      	lcd_bright_curve_en = <0>;
      
      	/* part 5 */
      	lcd_cpu_mode        = <1>;
      	lcd_cpu_te          = <1>;
      
      	/* part 6 */
      	lcd_frm             = <2>;
      	lcd_gamma_en        = <0>;
      	lcd_cmap_en         = <0>;
      	lcd_rb_swap			= <0>;
      
      	/* part 7 */
      	// reset pin
      	lcd_gpio_0 = <&pio PD 0 GPIO_ACTIVE_HIGH>;
      	// cs pin
      	lcd_gpio_1 = <&pio PD 9 GPIO_ACTIVE_HIGH>;
      	pinctrl-0 = <&rgb16_pins_a>;
      	pinctrl-1 = <&rgb16_pins_b>;
      };
      

      然后在pio中添加

      rgb16_pins_a: rgb16@0 {
      		pins = "PD1", "PD2","PD3","PD4","PD5","PD6", "PD7", "PD8", \
      				"PD10", "PD11", "PD12", "PD13", "PD14", "PD15", "PD16", "PD17", \
      				"PD18", "PD19", "PD20", "PD21";
      		function = "lcd0";
      		drive-strength = <30>;
      		bias-disable;
      	};
      
      	rgb16_pins_b: rgb16@1 {
      		pins = "PD1", "PD2","PD3","PD4","PD5","PD6", "PD7", "PD8", \
      				"PD10", "PD11", "PD12", "PD13", "PD14", "PD15", "PD16", "PD17", \
      				"PD18", "PD19", "PD20", "PD21";
      		function = "io_disabled";
      		bias-disable;
      	};
      

      测试 gpsp 显示

      ca5d44c6-e1ee-4864-94d7-e6c97e85998f-19DB19AA9558848CC4814892EA6EF828.png

      S 1 条回复 最后回复 回复 引用 分享 1
      • hsinyuwang
        hsinyuwang LV 6 最后由 编辑

        尚未解决问题

        • fb0_format 修改为10 后启动 log 是绿色
        fb0_format = <10>;
        

        E682965F3BAED8FE731BE29E9A3AD129.png

        • 屏幕实时帧率与期望帧率相差较大
        	lcd_x               = <480>;
        	lcd_y               = <320>;
        	lcd_width           = <72>;
        	lcd_height          = <48>;
        	lcd_dclk_freq       = <10>;
        	lcd_hbp             = <2>;
        	lcd_ht              = <486>;
        	lcd_hspw            = <2>;
        	lcd_vbp             = <20>;
        	lcd_vt              = <342>;
        	lcd_vspw            = <2>;
        
                lcd_cpu_mode        = <1>;
        	lcd_cpu_te          = <1>;
        

        QQ截图20230624193313.png

        W 1 条回复 最后回复 回复 引用 分享 1
        • W
          whycanservice2 LV 8 @hsinyuwang 最后由 编辑

          @hsinyuwang 12M的频率应该不会误差很大,你要修改 ht vt。。

          1 条回复 最后回复 回复 引用 分享 0
          • S
            soso90 LV 7 @hsinyuwang 最后由 编辑

            @hsinyuwang 终于看到有点i80接口的帖子,此处缺少一个原理图~~ 有机会复刻的话,到时传一个,哈哈哈

            1 条回复 最后回复 回复 引用 分享 0
            • W
              wj8331585 LV 6 最后由 编辑

              请问你开启了SDL双缓冲SDL_DOUBLEBUF了吗?

              我测试提示段错误。是还要配置什么环境的吗?
              screen = SDL_SetVideoMode(480, 32, 16, SDL_SWSURFACE | SDL_DOUBLEBUF);

              hsinyuwang 1 条回复 最后回复 回复 引用 分享 0
              • hsinyuwang
                hsinyuwang LV 6 @wj8331585 最后由 编辑

                @wj8331585 DOUBLEBUF 只要驱动支持就可以

                W 1 条回复 最后回复 回复 引用 分享 0
                • W
                  wj8331585 LV 6 @hsinyuwang 最后由 编辑

                  @hsinyuwang 我用的是芒果派的tina linux,它支持SDL_DOUBLEBUF吗?

                  1 条回复 最后回复 回复 引用 分享 0
                  • D
                    dyufeimen LV 2 最后由 编辑

                    麻烦提供一份接线图吗?我按照你的配置,屏幕没反应

                    1 条回复 最后回复 回复 引用 分享 0
                    • 1 / 1
                    • First post
                      Last post

                    Copyright © 2024 深圳全志在线有限公司 粤ICP备2021084185号 粤公网安备44030502007680号

                    行为准则 | 用户协议 | 隐私权政策