内核中lcd驱动分析
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
==============================内核中LCD驱动分析
20151008 aw LCD
===========driver/video/sun7i
--disp/
--Hdmi/
--lcd/ lcd_init
obj-$(CONFIG_LYCHEE_FB_SUN7I) += disp.o
disp-objs := dev_disp.o dev_fb.o dev_capture.o dev_disp_attrnode.o\
OSAL/OSAL_Cache.o OSAL/OSAL_Clock.o OSAL/OSAL_Dma.o OSAL/OSAL_Int.o OSAL/OSAL_IrqLock.o\
OSAL/OSAL_Lib_C.o OSAL/OSAL_Pin.o OSAL/OSAL_Semi.o OSAL/OSAL_Thread.o OSAL/OSAL_Time.o OSAL/OSAL_Parser.o\
de_bsp/de/ebios/de_be.o de_bsp/de/ebios/de_fe.o de_bsp/de/ebios/de_hwc.o\
de_bsp/de/ebios/de_layer.o de_bsp/de/ebios/de_lcdc.o de_bsp/de/ebios/de_tvec.o\
de_bsp/de/disp_clk.o de_bsp/de/disp_combined.o de_bsp/de/disp_de.o de_bsp/de/disp_display.o\
de_bsp/de/disp_event.o de_bsp/de/disp_hdmi.o de_bsp/de/disp_hwc.o de_bsp/de/disp_layer.o\
de_bsp/de/disp_lcd.o de_bsp/de/disp_scaler.o de_bsp/de/disp_sprite.o de_bsp/de/disp_tv.o\
de_bsp/de/disp_vga.o de_bsp/de/disp_video.o\
#de_bsp/lcd/lcd0_panel_cfg.o de_bsp/lcd/lcd1_panel_cfg.o\
de_bsp/lcd/lcd0_panel_cfg 没有在此处编译,在sun7i/lcd 目录下makeifle中被编译
obj-$(CONFIG_LYCHEE_LCD_SUN7I) += lcd.o
lcd-objs := dev_lcd.o lcd0_panel_cfg.o lcd1_panel_cfg.o
所以: 与具体lcd相关的文件为lcd0_panel_cfg.c
#step1: 修改测试
========================================================
Z:\lichee\linux-3.4\drivers\video\sun7i\disp
[ 0.357126] hyh in disp_probe
[ 0.357477] [DISP]capture_module_init
[ 0.358364] [DISP]capture_probe hyh in probe capture
[ 0.358575] [DISP]==capture finish==
[ 0.358590] hyh in lcd_module_init
[ 0.358599] [LCD] lcd_module_init
[ 0.359482] [DISP WRN] file:drivers/video/sun7i/disp/de_bsp/de/disp_lcd.c,line:497: fetch [lcd0_para] lcd_pwm_used fail!! ----LCD_get_sys_config(__u32 sel, __disp_lcd_cfg_t *lcd_cfg)
[ 0.366399] called by Fb_init hyh in parser_disp_init_para
[ 0.366457] hyh test flow: g_fbi.disp_init.b_init..1
[ 0.366470] hyh test flow2: g_fbi.disp_init.b_init..1
[ 0.366491] [DISP WRN] file:drivers/video/sun7i/disp/OSAL/OSAL_Clock.c,line:347: NULL hdle
[ 0.366579] [DISP WRN] file:drivers/video/sun7i/disp/OSAL/OSAL_Clock.c,line:200: NULL hdle
[ 0.366602] [DISP WRN] file:drivers/video/sun7i/disp/OSAL/OSAL_Clock.c,line:347: NULL hdle
[ 0.366629] [DISP WRN] file:drivers/video/sun7i/disp/OSAL/OSAL_Clock.c,line:347: NULL hdle
[ 0.366648] [DISP WRN] file:drivers/video/sun7i/disp/OSAL/OSAL_Clock.c,line:347: NULL hdle
[ 0.366667] [DISP WRN] file:drivers/video/sun7i/disp/OSAL/OSAL_Clock.c,line:347: NULL hdle
[ 0.679569] do_read_logo enter
[ 0.679651] create file error
[ 0.679675] [DISP WRN] file:drivers/video/sun7i/disp/OSAL/OSAL_Clock.c,line:347: NULL hdle
[ 0.679694] [DISP WRN] file:drivers/video/sun7i/disp/OSAL/OSAL_Clock.c,line:347: NULL hdle
[ 0.679719] boot logo wxh = 1280x400
=============================================
============
1:disp_module_init 首先运行
调用disp_probe 拿到设备的资源--> Display Engine Backend
info = &g_fbi;
info->dev = &pdev->dev;
platform_set_drvdata(pdev,info);
info->base_image0 = 0xf1e60000;
info->base_image1 = 0xf1e40000;
info->base_scaler0 = 0xf1e00000;
info->base_scaler1 = 0xf1e20000;
info->base_lcdc0 = 0xf1c0c000;
info->base_lcdc1 = 0xf1c0d000;
info->base_tvec0 = 0xf1c0a000;
info->base_tvec1 = 0xf1c1b000;
info->base_ccmu = 0xf1c20000;
info->base_sdram = 0xf1c01000;
info->base_pioc = 0xf1c20800;
info->base_pwm = 0xf1c20c00;
info->base_hdmi = 0xf1c16000;
对相关参数设定。
2.capture_module_init 运行
3.在lcd/目录下lcd_module_init()运行
int __init lcd_module_init(void)
{
int ret = 0, err;
printk("hyh in lcd_module_init\n");
__inf("lcd_module_init\n");
alloc_chrdev_region(&devid, 0, 1, "lcd");
my_cdev = cdev_alloc();
cdev_init(my_cdev, &lcd_fops);
my_cdev->owner = THIS_MODULE;
err = cdev_add(my_cdev, devid, 1);
if (err)
{
__wrn("cdev_add fail.\n");
return -1;
}
lcd_class = class_create(THIS_MODULE, "lcd");
if (IS_ERR(lcd_class))
{
__wrn("class_create fail\n");
return -1;
}
device_create(lcd_class, NULL, devid, NULL, "lcd");
lcd_init(); //与具体LCD相关lcd0_panel_cfg
return ret;
}
=========================================================#step3 拿到LCD配置参数
int lcd_init(void)
{
static __lcd_panel_fun_t lcd0_cfg;
static __lcd_panel_fun_t lcd1_cfg;
memset(&lcd0_cfg, 0, sizeof(__lcd_panel_fun_t));
memset(&lcd1_cfg, 0, sizeof(__lcd_panel_fun_t));
LCD_get_panel_funs_0(&lcd0_cfg);
LCD_get_panel_funs_1(&lcd1_cfg);
LCD_set_panel_funs(&lcd0_cfg, &lcd1_cfg);
DRV_DISP_Init();// 参考a20 显示驱动模块说明
Fb_Init(0);// dev_fb.c 中实现
return 0;
}
========================================================#step4 对fb进行设置
在Fb_Init() 中
1.register_framebuffer(g_fbi.fbinfo[i]);
2.parser_disp_init_para(&(g_fbi.disp_init));
typedef struct
{
struct device * dev;
__u32 base_image0;
__u32 base_image1;
__u32 base_scaler0;
__u32 base_scaler1;
__u32 base_lcdc0;
__u32 base_lcdc1;
__u32 base_tvec0;
__u32 base_tvec1;
__u32 base_hdmi;
__u32 base_ccmu;
__u32 base_sdram;
__u32 base_pioc;
__u32 base_pwm;
__disp_init_t disp_init;
__bool fb_enable[FB_MAX];
__fb_mode_t fb_mode[FB_MAX];
__u32 layer_hdl[FB_MAX][2];//[fb_id
][0]:screen0 layer handle;[fb_id][1]:screen1 layer handle
struct fb_info * fbinfo[FB_MAX];
__disp_fb_create_para_t fb_para[FB_MAX];
wait_queue_head_t wait[2];
wait_queue_head_t wait_frame;
unsigned long wait_count[2];
unsigned long wait_frame_count;
struct work_struct resume_work[2];
struct timer_list disp_timer[2];
//add by heyihang.Jan 28, 2013
struct work_struct vsync_work[2];
ktime_t vsync_timestamp[2];
struct work_struct commit_work;
__bool b_no_output;
__u32 reg_active[2];
struct list_head update_regs_list;
struct sw_sync_timeline *timeline;
int timeline_max;
struct mutex update_regs_list_lock;
spinlock_t update_reg_lock;
struct sync_fence *acquireFence[8];
}fb_info_t; --->g_fbi 结构体
static struct fb_ops dispfb_ops =
{
.owner = THIS_MODULE,
.fb_open = Fb_open,//return 0
.fb_release = Fb_release,//return 0
.fb_pan_display = Fb_pan_display,
.fb_ioctl = Fb_ioctl,
.fb_check_var = Fb_check_var,//return 0
.fb_set_par = Fb_set_par,
.fb_setcolreg = Fb_setcolreg,
.fb_setcmap = Fb_setcmap,
.fb_blank = Fb_blank,
.fb_cursor = Fb_cursor,//return 0
};
------------framebuffer 分配初始化和注册 dev_fb.c
g_fbi.fbinfo[i] = framebuffer_alloc(0, g_fbi.dev);//#step4.1
g_fbi.fbinfo[i]->fbops = &dispfb_ops;//操作集合
g_fbi.fbinfo[i]->flags = 0;
g_fbi.fbinfo[i]->device = g_fbi.dev;//
g_fbi.fbinfo[i]->par = &g_fbi;
g_fbi.fbinfo[i]->var.xoffset = 0;
g_fbi.fbinfo[i]->var.yoffset = 0;
g_fbi.fbinfo[i]->var.xres = 800;
g_fbi.fbinfo[i]->var.yres = 480;
g_fbi.fbinfo[i]->var.xres_virtual = 800;
g_fbi.fbinfo[i]->var.yres_virtual = 480*2;
g_fbi.fbinfo[i]->var.nonstd = 0;
g_fbi.fbinfo[i]->var.bits_per_pixel = 32;
g_fbi.fbinfo[i]->var.transp.length = 8;
g_fbi.fbinfo[i]->var.red.length = 8;
g_fbi.fbinfo[i]->var.green.length = 8;
g_fbi.fbinfo[i]->var.blue.length = 8;
g_fbi.fbinfo[i]->var.transp.offset = 24;
g_fbi.fbinfo[i]->var.red.offset = 16;
g_fbi.fbinfo[i]->var.green.offset = 8;
g_fbi.fbinfo[i]->var.blue.offset = 0;
g_fbi.fbinfo[i]->var.activate = FB_ACTIVATE_FORCE;
g_fbi.fbinfo[i]->fix.type = FB_TYPE_PACKED_PIXELS;
g_fbi.fbinfo[i]->fix.type_aux = 0;
g_fbi.fbinfo[i]->fix.visual = FB_VISUAL_TRUECOLOR
;
g_fbi.fbinfo[i]->fix.xpanstep = 1;
g_fbi.fbinfo[i]->fix.ypanstep = 1;
g_fbi.fbinfo[i]->fix.ywrapstep = 0;
g_fbi.fbinfo[i]->fix.accel = FB_ACCEL_NONE;
g_fbi.fbinfo[i]->fix.line_length = g_fbi.fbinfo[i]->var.xres_virtual * 4; //800*4
g_fbi.fbinfo[i]->fix.smem_len = g_fbi.fbinfo[i]->fix.line_length * g_fbi.fbinfo[i]->var.yres_virtual * 2; //800*4 * 480*2 *2
g_fbi.fbinfo[i]->screen_base = 0x0;
g_fbi.fbinfo[i]->fix.smem_start = 0x0;
printk("AAAA: g_fbi %p, g_fbi.fbinfo %p\n",&g_fbi, g_fbi.fbinfo[i]);
register_framebuffer(g_fbi.fbinfo[i]);#step4
parser_disp_init_para(&(g_fbi.disp_init));#step5
----------------------------------------------------print
[ 0.359346] [LCD] lcd_module_init
[ 0.360246] [DISP WRN] file:drivers/video/sun7i/disp/de_bsp/de/disp_lcd.c,line:497: fetch [lcd0_para] lcd_pwm_used fail!!
[ 0.362204] AAAA: g_fbi c0845b30, g_fbi.fbinfo ef2f4400
[ 0.362762] AAAA: g_fbi c0845b30, g_fbi.fbinfo ef2f4000
[ 0.364819] AAAA: g_fbi c0845b30, g_fbi.fbinfo ef37dc00
[ 0.365422] AAAA: g_fbi c0845b30, g_fbi.fbinfo ef37d800
[ 0.365903] AAAA: g_fbi c0845b30, g_fbi.fbinfo ef37d400
[ 0.366984] AAAA: g_fbi c0845b30, g_fbi.fbinfo ef37d000
[ 0.367503] AAAA: g_fbi c0845b30, g_fbi.fbinfo ef37fc00
[ 0.367985] AAAA: g_fbi c0845b30, g_fbi.fbinfo ef37f800
[ 0.368478] [DISP WRN] file:drivers/video/sun7i/disp/OSAL/OSAL_Clock.c,line:347: NULL hdle
[ 0.368577] [DISP WRN] file:drivers/video/sun7i/disp/OSAL/OSAL_Clock.c,line:200: NULL hdle
[ 0.368599] [DISP WRN] file:drivers/video/sun7i/disp/OSAL/OSAL_Clock.c,line:347: NULL hdle
[ 0.368624] [DISP WRN] file:drivers/video/sun7i/disp/OSAL/OSAL_Clock.c,line:347: NULL hdle
[ 0.368643] [DISP WRN] file:drivers/video/sun7i/disp/OSAL/OSAL_Clock.c,line:347: NULL hdle
[ 0.368662] [DISP WRN] file:drivers/video/sun7i/disp/OSAL/OSAL_Clock.c,line:347: NULL hdle
[ 0.680296] do_read_logo enter
[ 0.680374] create file error
[ 0.680395] [DISP WRN] file:drivers/video/sun7i/disp/OSAL/OSAL_Clock.c,line:347: NULL hdle
[ 0.680415] [DISP WRN] file:drivers/video/sun7i/disp/OSAL/OSAL_Clock.c,line:347: NULL hdle
[ 0.680440] boot logo wxh = 1280x400
----------
uboot中获得方法:
screen_width = disp_ioctl(NULL, DISP_CMD_SCN_GET_WIDTH, (void*)arg);
screen_height = disp_ioctl(NULL, DISP_CMD_SCN_GET_HEIGHT, (void*)arg);
===============================#step4.1
g_fbi.fbinfo[i] = framebuffer_alloc(0, g_fbi.dev);
struct fb_info *framebuffer_alloc(size_t size, struct device *dev)
{
#define BYTES_PER_LONG (BITS_PER_LONG/8)
#define PADDING (BYTES_PER_LONG - (sizeof(struct fb_info) % BYTES_PER_LONG))
int fb_info_size = sizeof(struct fb_info);
struct fb_info *info;
char *p;
if (size)
fb_info_size += PADDI
NG;
p = kzalloc(fb_info_size + size, GFP_KERNEL);
if (!p)
return NULL;
info = (struct fb_info *) p;
if (size)
info->par = p + fb_info_size;
info->device = dev;
#ifdef CONFIG_FB_BACKLIGHT
mutex_init(&info->bl_curve_mutex);
#endif
return info;
#undef PADDING
#undef BYTES_PER_LONG
}
register_framebuffer(g_fbi.fbinfo[i])
->do_register_framebuffer(fb_info)
:registered_fb[i] = fb_info;
:fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event);
==========================================================
DRV_DISP_Init 下午追踪: 2015-10-13
lichee/tools/pack/chips/sun7i/configs/android/wing-k70/sys_config.fex 结合全志A20系统配置手册.
;-------------------------------------------------------------------------------
;disp init configuration
;
;disp_mode (0:screen0
; 3:two_same_screen_diff_contets
;screenx_output_type (0:none; 1:lcd; 2:tv; 3:hdmi; 4:vga)
;screenx_output_mode (used for tv/hdmi output, 0:480i 1:576i 2:480p 3:576p 4:720p50 5:720p60 6:1080i50 7:1080i60 8:1080p24 9:1080p50 10:1080p60 11:pal 14:ntsc)
;screenx_output_mode (used for vga output, 0:1680*1050 1:1440*900 2:1360*768 3:1280*1024 4:1024*768 5:800*600 6:640*480 10:1920*1080 11:1280*720)
;fbx format (4:RGB655 5:RGB565 6:RGB556 7:ARGB1555 8:RGBA5551 9:RGB888 10:ARGB8888 12:ARGB4444)
;fbx pixel sequence (0:ARGB 1:BGRA 2:ABGR 3:RGBA) --- 0 for linux, 2 for android
;lcd0_bright (lcd0 init bright,the range:[0,256],default:197
;lcd1_bright (lcd1 init bright,the range:[0,256],default:197
;-------------------------------------------------------------------------------
[disp_init]
disp_init_enable = 1
disp_mode = 0
screen0_output_type = 1
screen0_output_mode = 4
screen1_output_type = 1
screen1_output_mode = 4
fb0_framebuffer_num = 2
fb0_format = 10
fb0_pixel_sequence = 0
fb0_scaler_mode_enable = 0
fb0_width = 0 注意: 按照输出设备的分辨率
fb0_height = 0
fb1_framebuffer_num = 2
fb1_format = 10
fb1_pixel_sequence = 0
fb1_scaler_mode_enable = 0
fb1_width = 0
fb1_height = 0
lcd0_backlight = 197
lcd1_backlight = 197
lcd0_bright = 50
lcd0_contrast = 50
lcd0_saturation = 57
lcd0_hue = 50
lcd1_bright = 50
lcd1_contrast = 50
lcd1_saturation = 57
lcd1_hue = 50
;-------------------------------------------------------------------------------
;lcd0 configuration
;lcd_dclk_freq: in MHZ unit
;lcd_pwm_freq: in HZ unit
;lcd_if: 0:hv(sync+de); 1:8080; 2:ttl; 3:lvds; 4
:hv2dsi
;lcd_width: width of lcd in mm
;lcd_height: height of lcd in mm
;lcd_hbp: hsync back porch
;lcd_ht: hsync total cycle
;lcd_vbp: vsync back porch
;lcd_vt: vysnc total cycle *2
;lcd_hv_if: 0:hv parallel 1:hv serial
;lcd_hv_smode: 0:RGB888 1:CCIR656
;lcd_hv_s888_if serial RGB format
;lcd_hv_syuv_if: serial YUV format
;lcd_hspw: hsync plus width
;lcd_vspw: vysnc plus width
;lcd_lvds_ch: 0:single channel; 1:dual channel
;lcd_lvds_mode: 0:NS mode; 1:JEIDA mode
;lcd_lvds_bitwidth: 0:24bit; 1:18bit
;lcd_lvds_io_cross: 0:normal; 1:pn cross
;lcd_cpu_if: 0:18bit; 1:16bit mode0; 2:16bit mode1; 3:16bit mode2; 4:16bit mode3; 5:9bit; 6:8bit 256K; 7:8bit 65K
;lcd_frm: 0:disable; 1:enable rgb666 dither; 2:enable rgb656 dither
;lcd_gpio_0: SCL
;lcd_gpio_1 SDA
;-------------------------------------------------------------------------------
[lcd0_para]
lcd_used = 1
lcd_driver_name = "default_lcd"
lcd_x = 1280 --------> 修改测试1
lcd_y = 400 -------->
lcd_width = 179
lcd_height = 56
lcd_dclk_freq = 38
lcd_pwm_not_used = 0
lcd_pwm_ch = 0
lcd_pwm_freq = 10000
lcd_pwm_pol = 1
lcd_if = 3
lcd_hbp = 20
lcd_ht = 1364
lcd_vbp = 45
lcd_vt = 938
lcd_vspw = 2
lcd_hspw = 10
lcd_hv_if = 0
lcd_hv_smode = 0
lcd_hv_s888_if = 0
lcd_hv_syuv_if = 0
lcd_lvds_ch = 0
lcd_lvds_mode = 0
lcd_lvds_bitwidth = 0
lcd_lvds_io_cross = 0
lcd_cpu_if = 0
lcd_frm = 0
lcd_io_cfg0 = 0x00000000
lcd_gamma_correction_en = 0
lcd_gamma_tbl_0 = 0x00000000
lcd_gamma_tbl_1 = 0x00010101
lcd_gamma_tbl_255 = 0x00ffffff
lcd_bl_en_used = 1
lcd_bl_en = port:PH08<1><0>
lcd_power_used = 1
lcd_power = port:PH07<1><0>
;lcd_pwm_used = 0
;lcd_pwm = port:PB02<2><0>
lcdd0 = port:PD00<3><0><2>
lcdd1 = port:PD01<3><0><2>
lcdd2 = port:PD02<3><0><2>
lcdd3 = port:PD03<3><0><2>
lcdd4 = port:PD04<3><0><2>
lcdd5 = port:PD05<3><0><2>
lcdd6 = port:PD06<3><0><2>
lcdd7 = port:PD07<3><0><2>
lcdd8 = port:PD08<3><0><2>
lcdd9 = port:PD09<3><0><2>
lcdd10 = port:PD10<2><0>
lcdd11
= port:PD11<2><0>
lcdd12 = port:PD12<2><0>
lcdd13 = port:PD13<2><0>
lcdd14 = port:PD14<2><0>
lcdd15 = port:PD15<2><0>
lcdd16 = port:PD16<2><0>
lcdd17 = port:PD17<2><0>
lcdd18 = port:PD18<2><0>
lcdd19 = port:PD19<2><0>
lcdd20 = port:PD20<2><0>
lcdd21 = port:PD21<2><0>
lcdd22 = port:PD22<2><0>
lcdd23 = port:PD23<2><0>
lcdclk = port:PD24<2><0>
lcdde = port:PD25<2><0>
lcdhsync = port:PD26<2><0>
lcdvsync = port:PD27<2><0>
;-------------------------------------------------------------------------------
;pwm configure
;-------------------------------------------------------------------------------
[pwm0_para]
pwm_used = 1
pwm_positive = port:PB02<2><0>