当前位置:   article > 正文

RK3288 Android 7.1 mipi副屏无法读取屏ID_mipi android7.1 mipi_dsi_dcs_write

mipi android7.1 mipi_dsi_dcs_write

一、整体思路

        手上有个产品需要兼容一个新的Mipi副屏,兼容的方法跟  RK3399 Android 7.1 MIPI副屏兼容  一样,都是在uboot阶段通过将读取到的屏ID与DTS中的值就行比较,如果不相同就将其他的panel节点的status值修改为disabled,只留一个status为okay的Panel节点。最后kernel阶段就会加载status为okay的panel。

        该方法最关键的部分就是读取panel的ID寄存器,只有能成功读取到屏ID,才能区分新旧屏。

二、uboot 读取屏ID

1、方法

询问屏厂商获取屏ID寄存器地址,直接通过dsi的io接口读取。我这里的新屏的ID寄存器地址是0xda

  1. panel:panel@0 {
  2. compatible = "simple-panel-dsi";
  3. .........
  4. ..............
  5. num = <0>;
  6. id = [93];
  7. id-reg = <0xda>;
  8. panel-init-sequence = [
  9. 15 00 02 E0 00
  10. 15 00 02 E1 93
  11. 15 00 02 E2 65
  12. 15 00 02 E3 F8
  13. 15 00 02 80 01
  14. 15 00 02 E0 01
  15. 15 00 02 00 00
  16. 15 00 02 01
  17. ..............
  18. ..............
2、代码实现

rockchip_dsi_panel.c

  1. static int rockchip_dsi_panel_getId(struct display_state *state)
  2. {
  3. struct panel_state *panel_state = &state->panel_state;
  4. struct rockchip_dsi_panel *panel = panel_state->private;
  5. u8 *buf;
  6. u8 mid[3];
  7. int reg,g_mipi_id;
  8. u8 max_size[2];
  9. int i,len,ret = -1;
  10. int count = 3;
  11. len = panel->id->len;
  12. buf = malloc(sizeof(char) * len);
  13. //读屏ID前要将屏使能脚和复位脚拉高
  14. fdtdec_set_gpio(&panel->enable_gpio, 1);
  15. if (panel->delay_prepare)
  16. msleep(panel->delay_prepare);
  17. fdtdec_set_gpio(&panel->reset_gpio, 0);
  18. if (panel->delay_reset)
  19. msleep(panel->delay_reset);
  20. if (panel->delay_init)
  21. msleep(panel->delay_init);
  22. while(count>0){
  23. if(len > 1){
  24. max_size[0] = len;
  25. ret = mipi_dsi_set_maximum_return_packet_size(state, max_size,1);
  26. }
  27. //通过mipi_dsi_dcs_read接口读取屏ID
  28. ret = mipi_dsi_dcs_read(state,panel->id_reg, buf,len);
  29. if(ret != 0){
  30. msleep(5);
  31. }
  32. count --;
  33. }
  34. if(ret == 0)//ret == 0 证明读到了寄存器的id
  35. for(i = 0; i < len; i++){
  36. dbg("read buf id[%d] = %x,panel target id[%d] = %x\n", i, *(buf + i), i, *(panel->id->buf + i));
  37. if(*(buf + i) != *(panel->id->buf + i))
  38. return -1;
  39. }else{
  40. dbg("read panel(num = %d) timeout or no response\n",panel->num);
  41. if(panel->num == 1)
  42. panel_state->num = 1; //panel->num
  43. return -1;
  44. }
  45. panel_state->num = panel->num; //panel_state->num 被当作是连接的副屏编号
  46. return 0;
  47. }

其中最关键的是io接口的调用

  1. //通过mipi_dsi_dcs_read接口读取屏ID
  2. ret = mipi_dsi_dcs_read(state,panel->id_reg, buf,len);

通过代码追溯,其最终的调用是

  1. static inline void dsi_write(struct dw_mipi_dsi *dsi, u32 reg, u32 val)
  2. {
  3. writel(val, dsi->base + reg);
  4. }
3、编译烧录验证,出现问题

通过串口打印的log发现,执行mipi_dsi_dcs_read接口发现dsi无法正常通信,报错截图如下:

看Log直接报:failed to write cmd

4、问题排查

前面提到,在读屏ID前要将屏使能脚和复位脚拉高,可以先验证这个是否正常。验证方法可以在代码set high后写一个循环,让uboot卡在那里,然后用万用表检测。

像这样:

  1. static int rockchip_dsi_panel_getId(struct display_state *state)
  2. {
  3. 。............
  4. ............
  5. fdtdec_set_gpio(&panel->enable_gpio, 1); //gpio_direction_output(GPIO_BANK7 | GPIO_A2, 1);
  6. if (panel->delay_prepare)
  7. msleep(panel->delay_prepare);
  8. fdtdec_set_gpio(&panel->reset_gpio, 0); //gpio_direction_output((GPIO_BANK3 | GPIO_B4), 1);
  9. if (panel->delay_reset)
  10. msleep(panel->delay_reset);
  11. if (panel->delay_init)
  12. msleep(panel->delay_init);
  13. while(1); //卡住
  14. ..................

烧录验证,使用万用表测,发现使能脚能拉高,但是复位脚显示是0V。那就找到问题所在了。

uboot阶段无法控制gpio pin的电平,可以先检查这个引脚是否在其他地方被占用了。本着从这个角度思考,我检查DTS中是否其他地方也配置了这个gpio,但grep了后发现并没有。

那就换个角度排查:是否被复用为其他function了。

5、io读取gpio寄存器

为了检查一下复位引脚的gpio的复用情况,可以使用RK提供的io工具读取相关的gpio寄存器,结合TRM手册,检查寄存器相关的bit的值,就可以知道复用情况了。

按照下面步骤一步一步来:

5.1 打开原理图,查找复位脚的gpio编号

可以看到,复位脚的gpio编号就是:GPIO3_B4

5.2 打开rk3288的TRM手册

搜 gpio3b4

可以看到,gpio3b4的function由寄存器的第8bit控制,当该bit设为0时,function为gpio;设为1时,function为flash0_cle。得到了这些关键信息,下面我们就需要读取该寄存器第8bit的值到底是多少。

往上翻滚一下手册,就可以看到:

可以得知,该寄存器的基地址名称为"GRF",还有就是偏移量为0x0024。

就差基地址了!!!!

在TRM中搜 GRF

可以得知,GRF 的基地址为0xff770000.

因此,gpio3b4的寄存器完整地址为:0xff770000 + 0x0024 = 0xff770024.

走到这一步,已经搞定一半了。接一下只需要在头文件把rk的io工具打开,烧录验验证一下。

5.3 打开io工具
  1. diff --git a/include/configs/rk_default_config.h
  2. b/include/configs/rk_default_config.h
  3. index 9852917d4f..305de26347 100755
  4. --- a/include/configs/rk_default_config.h
  5. +++ b/include/configs/rk_default_config.h
  6. @@ -304,7 +304,7 @@
  7. /* rk io command tool */
  8. -#undef CONFIG_RK_IO_TOOL
  9. +#define CONFIG_RK_IO_TOOL
5.4 设置bootdelay
  1. diff --git a/common/autoboot.c b/common/autoboot.c
  2. index c27cc2c751..fe28adb2fd 100644
  3. --- a/common/autoboot.c
  4. +++ b/common/autoboot.c
  5. @@ -146,6 +146,7 @@ static int abortboot_normal(int bootdelay)
  6. {
  7. int abort = 0;
  8. unsigned long ts;
  9. + bootdelay = 3; //此处添加时间可自由定义,单位:秒
  10. #ifdef CONFIG_MENUPROMPT
  11. printf(CONFIG_MENUPROMPT);

目的就为了方便进入uboot环境调试

5.5 编译烧录刷uboot.img,io读取寄存器

make distclean 后编译,将生成的uboot.img进行烧录

进入uboot环境:

输入命令   io -4 -r 0xff770024

读取结果如下:

  1. rkboot # io -4 -r 0xff770024
  2. 0xff770024: 00005559

00005559  转换为二进制为:0001  0101 1011  0111

可以得知,gpio3b4的寄存器的第8bit值为1,结合前面的分析可知,值为1,function为flash0_cle。显然,复位脚一直拉不高的原因找到了。

5.6 查看寄存器写入规则

查看TRM,了解该寄存器的写入规则,如下图:

根据Description,大概的意思就是,bit0~15的值能否写入是由bit16~31控制。就拿我要将gpio3b4寄存器的第8bit来说,如果要在第8bit写入0,生效的前提是该寄存器的第24bit置1。

所以,根据上面所讲,要将屏复位脚的function选为GPIO,该往寄存器写入: 0x1000000

0x1000000 转为二进制为:0001 0000 0000 0000 0000 0000 0000  (第8bit为0,第24bit为1)

5.7 代码实现
  1. static int rockchip_dsi_panel_getId(struct display_state *state)
  2. {
  3. ...................
  4. writel(0x1000000,0xff770024); //使用writel函数写入
  5. fdtdec_set_gpio(&panel->enable_gpio, 1); //gpio_direction_output(GPIO_BANK7 | GPIO_A2, 1);
  6. if (panel->delay_prepare)
  7. msleep(panel->delay_prepare);
  8. fdtdec_set_gpio(&panel->reset_gpio, 0); //gpio_direction_output((GPIO_BANK3 | GPIO_B4), 1);
  9. if (panel->delay_reset)
  10. msleep(panel->delay_reset);
  11. ........................
5.8 编译烧录刷uboot.img,验证

进入uboot 环境,重新读取寄存器

输入 io -4 -r 0xff770024

结果如下:

  1. rkboot # io -4 -r 0xff770024
  2. 0xff770024: 00005459

0x5459 转为二进制:0101 0100 0101 1001

可以看到第8bit已经变为0

看串口打印的log,如下:

  1. final DSI-Link bandwidth: 800 Mbps x 2
  2. ---liyj--enter dw_mipi_dsi_init
  3. ---liyj--- __func__ : rockchip_dsi_panel_parse_dt enable_gpio->gpio = 1794
  4. ---liyj--- __func__ : rockchip_dsi_panel_parse_dt reset_gpio->gpio = 780
  5. DSI-READ: dts id reg = 0xda
  6. DSI-READ: dts id[0] = 93
  7. ---liyj--- FILE : drivers/video/rockchip_dsi_panel.c enter func : rockchip_dsi_panel_parse_cmds LINE : 94
  8. rockchip_dsi_panel_parse_cmds: total_len=978, cmd_cnt=196
  9. sssss __LINE_ : 420
  10. ---liyj--- __func__ : rockchip_dsi_panel_prepare reset_gpio num = 780
  11. ---liyj--- __func__ : rockchip_dsi_panel_prepare enable_gpio num = 1794
  12. ---liyj---File:drivers/video/rockchip_mipi_dsi.c Enter func : mipi_dsi_dcs_read Line : 187
  13. ---liyj---msg->rx_len == 1
  14. ---liyj---File:drivers/video/rockchip_mipi_dsi.c Enter func : mipi_dsi_dcs_read Line : 187
  15. ---liyj---msg->rx_len == 1
  16. ---liyj---File:drivers/video/rockchip_mipi_dsi.c Enter func : mipi_dsi_dcs_read Line : 187
  17. ---liyj---msg->rx_len == 1
  18. DSI-READ: read buf id[0] = 93,panel target id[0] = 93
  19. DSI-READ: dsi find panel id

可以看到能正常读取屏ID了,屏也能正常亮起来

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/330248
推荐阅读
  

闽ICP备14008679号