高通安卓调试LCD几方面总结(二)

   最近工作太忙了,而且经常出差,所以有一个多月没有来得及更新博客了,唉,之前一个项目LCD也遇到几个棘手的问题,压力山大。

   闲话少说,直接进入正题了,在上一篇里写了高通平台android2.3里的kernel和bootloader(LK)里LCD驱动的移植,这一篇主要写一下在4.0里LCD驱动的移植。

    (1) kernel

   高通的android4.0和2.3在kernel里的LCD驱动是有区别的,主要在于4.0里少了latedisplay.c这个文件。这里我以renesas公司的r61408这颗IC来介绍。我使用的是RGB565的接口,由于kernel里有高通公司提供的其它家IC的代码,我同样是以truly的来作为参考的,代码的框架不变。首先就是在kernel\drivers\video\msm下以truly的代码为模板,创建一个名为lcdc_r61408.c的文件,文件里的内容照着truly的来做。

   这里先来把Makefile和Kconfig文件修改好。在kernel\drivers\video\msm文件夹下的Makefile里添加:

        obj-$(CONFIG_FB_MSM_LCDC_RENESAS_R61408) += lcdc_renesas_r61408.o
     在此目录下打开Kconfig文件,在里面添加:

 config FB_MSM_LCDC_RENESAS_R61408
  bool
  select FB_MSM_LCDC_PANEL
  default n

config FB_MSM_LCDC_RENESAS_R61408_PT_PANEL
  depends on FB_MSM_LCDC_HW
  bool "LCDC Renesas PT Panel"
  select FB_MSM_LCDC_RENESAS_R61408
  default n
  ---help---
  Support for LCDC Renesas PT panel
    还要在kernel\arch\arm\configs目录下的board config文件里添加:

             CONFIG_FB_MSM_LCDC_RENESAS_R61408_PT_PANEL=y

    在lcdc_r61408.c文件里主要就是要写向LCD用SPI发指令和发数据的函数,我们的这个项目里使用的是GPIO口模拟的SPI总线,所以SPI的时序一定要写正确,R61408在用SPI发指令的时候data和command是在写8bit数据前通过SDO口的高和低来判别的,但是有些LCD的IC,比如NT35510,需要在发8bit数据之前要发送R/W,H/L,D/C几个信号来区别接下来发的数据表示什么。所以一定要根据所选用的LCD的IC的spec严格的来写SPI的时序,否则有可能造成LCD的初始化都不成功。

   在kernel里,LCD的驱动的调用的流程是:

msm_fb_open()  (msm_fb.c)
  -> msm_fb_blank_sub(FB_BLANK_UNBLANK, info, mfd->op_enable)
    -> if (!mfd->panel_power_on) {
           ret = pdata->on(mfd->pdev); //这里的on指向的就是lcdc.c里的lcdc_on()函数
                -> lcdc_on()	/*这个函数里开启LCDC时钟,并且打开LCD*/
              -> clk_prepare_enable(pixel_mdp_clk);
                 clk_prepare_enable(pixel_lcdc_clk);
                 if (lcdc_pdata && lcdc_pdata->lcdc_power_save)
                   lcdc_pdata->lcdc_power_save(1);/*函数指针,指向board-display.c里的msm_lcdc_power_save()*/
                 if (lcdc_pdata && lcdc_pdata->lcdc_gpio_config)	/*这里lcdc_gpio_config指针是空,所以不会接着调 下一步*/
                       ret = lcdc_pdata->lcdc_gpio_config(1);
                 ret = panel_next_on(pdev);/*函数指针,指向lcdc_renesas_r61408.c里的lcdc_renesas_panel_on()函数*/

panel_next_on(pdev) (lcdc.c)

  -> lcdc_renesas_panel_on() (lcdc_renesas_r61408.c)
    -> renesas_disp_reginit() 	/*初始化LCD的寄存器*/
      -> renesas_spi_write_bytes() /*设用SPI写函数*/

lcdc_renesas_panel_init(void) (lcdc_renesas_r61408.c)

-> platform_driver_register(&this_driver);/*注册LCD驱动,此时renesas_probe函数会调一次,主要是为了从board-display.c里获取SPI和背光各管脚的定义值*/
   /*设置与LCD相关的参数,具体各参数意义参考上一篇*/
   pinfo->xres = 480;
   pinfo->yres = 800;
   MSM_FB_SINGLE_MODE_PANEL(pinfo);
   pinfo->type = LCDC_PANEL;
   pinfo->pdest = DISPLAY_1;
   pinfo->wait_cycle = 0;
   pinfo->bpp = 16;
   pinfo->fb_num = 2;
   pinfo->clk_rate = 30720000;
   pinfo->bl_max = 32;
   pinfo->bl_min = 1;
   pinfo->lcdc.h_back_porch = 10;/* hsw = 8 + hbp=16 */
   pinfo->lcdc.h_front_porch = 150;100
   pinfo->lcdc.h_pulse_width = 10;
   pinfo->lcdc.v_back_porch = 22;///12/* vsw=1 + vbp = 7 */
   pinfo->lcdc.v_front_porch = 10;
   pinfo->lcdc.v_pulse_width = 2;
   pinfo->lcdc.border_clr = 0;	/* blk */
   pinfo->lcdc.underflow_clr = 0xff;/* blue */
   pinfo->lcdc.hsync_skew = 0;

   platform_device_register(&this_device);/*这里又注册了一个device,这个device和board-display.c里 的device是通过id来区别的,然后会再次调用renesas_probe函数*/
     -> msm_fb_add_device(pdev)	/*向高通的FB架构里将上面的LCD信息注册进去*/

    在关闭LCD的时候,kernel里驱动调用流程刚好是和上面反向的。

   这里有一点,因为我们使用的背光是通过PMIC的一个1号脚来控制的,使用PMIC管脚产生PWM的使用方法是,在board-display.c里初始化GPIO的函数里,加上这么一句:

                     pmapp_disp_backlight_init();
    然后在board-display.c里加上如下配置:

static int lcdc_set_bl(int level)
{
  int ret;
  //PRINTK("lcdc_renesas_set_bl,level = %d\r\n",level);
  ret = pmapp_disp_backlight_set_brightness(level);
  if (ret)
    pr_err("%s: can't set lcd backlight!\n", __func__);
  return ret;
}
static struct msm_panel_common_pdata lcdc_panel_data = {
  .panel_config_gpio = NULL,
  .pmic_backlight = lcdc_set_bl,
  .gpio_num	  = lcdc_gpio_table,
}
    最后在lcdc_renesas_r61408.c的pmic_backlight这个函数指针就可以实现背光的控制和调节。

 (2) bootloader(lk)

   和上一篇一样,首先要在目录/bootable/bootloader/lk/target/$(Projec)下更改lcd的makefile文件rules.mk,在rules.mk下添加:

                   DEFINES += DISPLAY_LCDC_PANEL_R61408=1
   代码的流程可以跟着truly的例子来做,这里简单的介绍一下流程:
void kmain()(/bootable/bootloader/lk/kernel/main.c)
  -> thread_resume (thread_create("bootstrap2", &bootstrap2, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
    -> bootstrap2
      -> target_init(); (bootable\bootloader\lk\target\$(project)\Init.c)
        -> /*这里是bootloader里按键的驱动*/
          #if (!ENABLE_NANDWRITE)
          keys_init();
          keypad_init();
          #endif

          display_init();	/*初台化LCD驱动*/
          dprintf(INFO, "Diplay initialized\n");
           display_image_on_screen(); /*向LCD里发送图像数据*/

display_init()  (/bootable/bootloader/lk/platform/msm7627a/platform.c)
/*这里lcdc_init()和panel_lcdc_init()的顺序如果调过来LCD显示就不正常,我也很奇怪,不知道是为什么*/
-> fb_config = lcdc_init();
  -> mdp_lcdc_clock_init();/*初始化LCDC的时钟*/
      lcd_timing = get_lcd_timing();/*获取LCD相关的硬件设置*/
      fb_cfg = lcdc_init_set(lcd_timing);/*根据上面得到的设置数据来设置CPU的寄存器*/

-> panel_lcdc_init();	/*初始化LCD,要完成的有RESET,SPI的读写函数等等*/

    LCDC接口的LCD驱动在LK里相对MIPI的来说流程比较简单,SPI的时序参考KERNEL里的一般就没有什么问题的。

    到这里,LCDC和MIPI的两种LCD在高通平台上的驱动也算是写完了,小弟也正处在学习的过程当中,写得不好。

文章转自:http://blog.csdn.net/dacaozuo/article/details/7934774

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值