简介

屏的接口种类非常多,常见的包括 RGB、HDMI、VGA、LVDS、EDP、MIPI等接口。
其中,在 Android 移动设备上,大多采用的是MIPI接口。
某些时候,由于某种需求,需要将 Android 设备上的 MIPI 数据显示到其他接口的屏上,此时,则需要利用相关转换芯片将 MIPI 接口的数据转换成其他接口的数据。
在 msm8916 上有过这样的需求:将 MIPI 数据转换成 RGB 进行输出,当时采用的转换芯片是 ICN6211。以下记录之。

RGB 简介

R(红)、G(绿)、B(蓝)是自然界三原色,三原色按照不同比例进行相加,混合成不同的颜色。
RGB其取值范围分别为0~255,其值越大,则越亮,当RGB都取值为255时,则为白色。相反全为0时,则为黑色。
而RGB接口就是分三原色进行输入的图形视频接口,也叫作色差分量接口。

RGB 接口中包括三大类信号:数据信号、时钟信号和控制信号。

  • 数据信号,通过数据线传输,一般分为6 bit 或者 8 bit传输(R0R5/G0G5/B0~B5 或 R0R7/G0G7/B0~B7),也即是数据信号线分为18根或者24根

  • 时钟信号,特指像素时钟信号,传输数据和对数据信号进行读取的基准。

  • 控制信号,包括数据使能信号DE(或有效显示数据选通信号)、行同步信号HS、帧同步信号VS

ICN6211 简介

ICN6211 是一款 MIPI 转 RGB 的芯片,下面是它的简要特性:

  • 其最高支持 MIPI DSI 的4 Lane 输入;当4lane输入时,其支持的最大带宽为1GBps

  • 其能对 MIPI DSI的 RGB565-16bpp、RGB666-18bpp 以及 RGB888-24bpp 的数据包进行解码转换

  • 其能输出 18 bpp 或者 24 bpp 像素的 RGB 图形数据,像素时钟的范围在 5MHz ~ 154MHz

  • 其支持的最大分辨率为 FHD(1920x1080p) 以及 WUXGA(1920x1200p)

  • 支持 I2C 接口

icn6211 Functional Block Diagram

System Application Diagram

屏的显示分为两部分,一部分是开机显示厂商 logo,一部分是系统启动完毕后正常的显示。下面就这两部分的开发细节进行介绍。

添加 MIPI 转 RGB 支持

针对 MIPI 接口的屏,屏的配置参数通过 DATA0-、DATA0+ 这对数据线下发到屏端。
如果初始化正确,则切换到 HS 模式下,直接把数据从DATA0~DATA3刷出去即可。
那么针对 ICN6211-MIPI-RGB 的屏,又是怎么操作的呢?其实也非常简单,在给定 ICN6211 正确的电压后,将屏的配置参数通过 ICN6211 的I2C下发到屏端即可。
后续数据的传输则不再需要操心。

ICN6211 参数图

bootloader

mdss_dsi_panel_initialize() 函数中,会下发屏的配置参数。
它原本是调用 MIPI 接口函数 mipi_dsi_cmds_tx() 去下发的参数,在这里改成或者添加 I2C 的传输接口即可。

int mdss_dsi_panel_initialize(struct mipi_dsi_panel_config *pinfo, uint32_tbroadcast)
{if (pinfo->i2c_cmds_table) {mipi_i2c_cmds_tx(pinfo->i2c_cmds_table);}
}static struct qup_i2c_dev  *i2c_dev;
static int qrd_lcd_i2c_write(int addr, int reg, int val)
{int ret = 0;uint8_t data_buf[] = { reg, val };/* Create a i2c_msg buffer, that is used to put the controller into writemode and then to write some data. */struct i2c_msg msg_buf[] = { {addr,I2C_M_WR, 2, data_buf}};ret = qup_i2c_xfer(i2c_dev, msg_buf, 1);if(ret < 0) {dprintf(CRITICAL, "qup_i2c_xfer error %d\n", ret);return ret;}return 0;
}/*write i2c command*/int mipi_i2c_cmds_tx(struct i2c_on_command_table *i2c_cmds_table)
{int i = 0;i2c_dev = qup_blsp_i2c_init(BLSP_ID_1, QUP_ID_1, 100000, 19200000);if(!i2c_dev) {dprintf(CRITICAL, "qup_blsp_i2c_init failed \n");ASSERT(0);}for(i = 0; i < i2c_cmds_table->cmds_cnt; i++){qrd_lcd_i2c_write(i2c_cmds_table->slave_addr, i2c_cmds_table->cmds_list[i].reg, i2c_cmds_table->cmds_list[i].val);}
}

当然,pinfo->i2c_cmds_table 这个table,按照 qcom 的屏处理流程,它是在 msm8916/oem_panel.c 里面进行处理的,下面直接贴出处理代码片段:

case ICN6211_QHD_VIDEO_PANEL:panelstruct->paneldata    = &icn6211_qhd_video_panel_data;panelstruct->panelres     = &icn6211_qhd_video_panel_res;panelstruct->color        = &icn6211_qhd_video_color;panelstruct->videopanel   = &icn6211_qhd_video_video_panel;panelstruct->commandpanel = &icn6211_qhd_video_command_panel;panelstruct->state        = &icn6211_qhd_video_state;panelstruct->laneconfig   = &icn6211_qhd_video_lane_config;panelstruct->paneltiminginfo= &icn6211_qhd_video_timing_info;panelstruct->panelresetseq= &hx8389b_qhd_video_reset_seq;pinfo->mipi.i2c_cmds_table = &icn6211_i2c_on_command_table; pinfo->mipi.i2c_cmds_table->cmds_cnt = ICN6211_QHD_VIDEO_ON_COMMAND;pinfo->mipi.i2c_cmds_table->slave_addr = ICN6211_I2C_SLAVE_ADDR;pinfo->mipi.i2c_cmds_table->blsp_id = I2C_BLSP_ID;pinfo->mipi.i2c_cmds_table->qup_id = I2C_QUP_ID;panelstruct->backlightinfo = &icn6211_qhd_video_backlight;memcpy(phy_db->timing,icn6211_qhd_video_timings, TIMING_SIZE);break;

kernel

在 msm8916 的 kernel 部分,对一个屏驱动的处理分为三步:

  • 解析该屏的设备树文件(DTSI)

  • 注册屏初始化命令传输接口

  • 下发初始化命令,使能 Panel

下面就一步一步的来看怎么添加的:

  1. 解析 I2C 命令

     static int mdss_panel_parse_dt(struct device_node *np,struct mdss_dsi_ctrl_pdata *ctrl_pdata){//...rc = of_property_read_string(np,"qcom,mdss-command-access", &data);if (!rc && !strcmp(data, "i2c")) {  /*the property is self defined, it may not exist in some dts configure*/                                          ctrl_pdata->cmd_access = CMD_ACCESS_I2C;ctrl_pdata->i2c_handle = mdss_get_icn6211_i2c_client();if (!ctrl_pdata->i2c_handle){pr_err("ctrl_pdata->i2c_handle is null\n");//goto error;   /*modified by fangchengbing  return error will lead to crash*/}mdss_i2c_parse_dcs_cmds(np, &ctrl_pdata->i2c_on_cmds, "qcom,mdss-i2c-on-command");} else {  /*normal flow*///....}}/*** @brief parse i2c command in dtsi file, format [%d %d] ==> [reg, val]* store them in struct i2c_cmd_list** @param np* @param pcmds where i2c will store* @param cmd_key flag contain i2c command** @return */static int mdss_i2c_parse_dcs_cmds(struct device_node *np,struct i2c_cmd_list *pcmds, char *cmd_key){const char *data;int blen = 0;char *buf;int i = 0, j = 0;data = of_get_property(np, cmd_key, &blen);if (!data) {pr_err("%s: failed, key=%s\n", __func__, cmd_key);return -ENOMEM;}if (blen < 0 && blen / 2 == 1)pr_err("%s format err\n", cmd_key);pr_debug("mdss_i2c_parse_dcs_cmds blen = %d\n", blen);buf = kzalloc(sizeof(char) * blen, GFP_KERNEL);if (!buf)return -ENOMEM;memcpy(buf, data, blen);pcmds->cmds = kzalloc(sizeof(struct i2c_ctrl_hdr) * blen / 2, GFP_KERNEL);pcmds->cmds_cnt = blen / 2;for (i = 0; i < blen; i+=2){j = i / 2;pcmds->cmds[j].reg = buf[i];pcmds->cmds[j].val = buf[i+1];}return 0;}
    
  2. 控制器初始化时,注册屏初始化命令表:

     void mdss_dsi_ctrl_init(struct mdss_dsi_ctrl_pdata *ctrl){//...if (ctrl->cmd_access == CMD_ACCESS_DSI)ctrl->cmdlist_commit = mdss_dsi_cmdlist_commit;else if (ctrl->cmd_access == CMD_ACCESS_I2C)ctrl->cmdlist_commit = mdss_i2c_cmdlist_commit;//...}/*** @brief  write i2c command to mipi@rgb chip** @param ctrl include i2c_client* @param from_mdp not important** @return */int mdss_i2c_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp){int rc = 0;int i = 0;struct i2c_cmd_list on_cmds;on_cmds = ctrl->i2c_on_cmds;mutex_lock(&ctrl->cmd_mutex);if (ctrl->i2c_handle) {for (i = 0; i < on_cmds.cmds_cnt; i++){rc = i2c_smbus_write_byte_data(ctrl->i2c_handle, on_cmds.cmds[i].reg, on_cmds.cmds[i].val);if (rc < 0) {mutex_unlock(&ctrl->cmd_mutex);return rc;}}}mutex_unlock(&ctrl->cmd_mutex);return rc;}
    
  3. 下发屏参数命令

     static int mdss_dsi_panel_on(struct mdss_panel_data *pdata){//...if (ctrl->cmd_access == CMD_ACCESS_DSI) {if (ctrl->on_cmds.cmd_cnt)mdss_dsi_panel_cmds_send(ctrl, &ctrl->on_cmds);} else if (ctrl->cmd_access == CMD_ACCESS_I2C) {if (ctrl->i2c_on_cmds.cmds_cnt)ctrl->cmdlist_commit(ctrl, 0);}//...}
    

注意!

最重要的有一点不要忘记,平台需要利用 I2C 总线去下发屏初始化参数,根据 I2C 协议,需要给定 I2C 设备在总线上的地址:

在 bootloader 里直接配置上 0x2C 即可,在 kernel 里面,dtsi 中配置如下:

i2c@78b6000 {icn6211_mipi_rgb@2C {compatible = "qcom,icn6211_mipi_rgb";reg = <0x2C>;};};

总结

其实 MIPI 转 RGB 的修改点不多,也不难。就一个地方:初始化命令通过 MIPI 的 DATA0 下发,转移到了 I2C 下发。

2016-08-15

后志

实际上,当年这种做法,并不适合平台间的移植。在今天看来,我们可以把 mipi-2-rgb 分解为两部分:数据流部分和控制流部分。
所谓数据流,其实就是平台数据的输出,对于平台来说,无论外围是 mipi lcd 还是 rgb转换芯片亦或是 hdmi 转换芯片,平台只需要把符合要求的 mipi 数据,通过 mipi lane 丢出去就可以了,至于mipi数据怎么转换成 rgb 数据,那就不是平台的事情了,是外带的转换芯片的事情了。
所谓控制流,其实就是通过 i2c 下发控制命令初始化 rgb 、hdmi 转换芯片的事情。相对于平台来说,转换芯片,无非就是一个i2c或者spi或者其他总线的外设而已,就是一个i2c子设备而已,它无需要多么复杂的逻辑来控制。
那么二者合一,即数据流和控制流加在一起,代码处理,完全没必要按照当年的做法来到处修改,对于mipi来说,按照真实的mipi lcd造一个 fake lcd dtsi 设备树给平台,骗过平台,让平台误认为外面是一个 mipi lcd,可以输出 mipi 数据即可;而针对转换芯片来说,开机上电,按照 i2c 子设备的加载方式,单独一个驱动,处理即可。当然,后面工程中,实际上也是按照这个思路来处理的。

附加一句:在 mipi-2-rgb lcd的基础上,去理解 camera 外设调试,道理亦然。差别在于两点:1.camera的是输入方向;2.camera的上电时序比较严格。仅此而已。
2020-2-14

Qualcomm msm8916 MIPI to RGB 调试相关推荐

  1. 联芯 1860平台 icn6211 mipi to RGB 转换芯片 调试 和 st7789 LCD调试spi 9bit 模式

    关键字:联芯科技,LC1860,LC186x,Chipone Technology,icn6211,mipi bridge,mipi to RGB,mipi转换芯片,RGB666,st7789,st7 ...

  2. Qualcomm平台Mipi DSI转RGB

    概述 Qualcomm平台显示接口基本上都只有Mipi,在较高端的平台可能还会支持HDMI等串行接口,但类似RGB接口的并行却不会支持.往往在设计一些产品时,客户指定的就是一些高通平台本身不支持的接口 ...

  3. mipi接口LCD调试流程(基于Android4.0版本以后)

    MIPI联盟,即移动产业处理器接口(MobileIndustry Processor Interface简称MIPI)联盟.MIPI(移动产业处理器接口)是MIPI联盟发起的为移动应用处理器制定的开放 ...

  4. ROS上同时预览depth,IR,RGB 调试记录

    ROS上同时预览depth,IR,RGB 调试记录 用rviz同时显示RGB,IR,DEPTH(验证设备:astraprosm,canglong2,deeyea) 1.编译libuvc库 cd lib ...

  5. MIPI转换芯片、ICN6211、ICN6202、MIPI转RGB、MiPI转LVDS、分辨率最高1080P、MIPI转双路LVDS

    MIPI转换芯片.ICN6211.ICN6202.MIPI转RGB.MiPI转LVDS.分辨率最高1080P.MIPI转双路LVDS 1:ICN6211是一颗MIPI转RGB的桥接芯片如下图 2:IC ...

  6. android lcd调试 高通平台lcd调试深入分析总结(mipi和rgb接口)

    各位网友:最近发现我这篇文章转载的到处都是,有的则以原创存在,转载时请注明出处,还有文中错误的地方请指正!谢谢合作. 一:点亮lcd in kernel 其实点亮lcd很简单必须保证以后几个步骤正确: ...

  7. 全志 Tina Linux LCD显示屏调试指南 支持MIPI DSI RGB LVDS I8080 SPI等接口,开发板支持百问网T113 D1-H哪吒 DongshanPI-D1s V853

    1 概述 编写目的 本文档将介绍sunxi 平台Display Engine 模块中LCD 的调试方法. LCD 调试方法,调试手段. LCD 驱动编写. lcd0 节点下各个属性的解释. 典型LCD ...

  8. Camera | 3.瑞芯微平台MIPI摄像头常用调试命令

    瑞芯微专栏 前面2篇我们讲解了camera的一些基础概念和知识. 本文主要讲述在瑞芯微平台上摄像头开发常用的调试命令. 0.环境 soc : rk3568 board: EVB1-DDR4-V10 软 ...

  9. 嵌入式Linux MIPI接口LCD调试-关于DRM显示与应用调试的干货浓缩

    经过一段时间自己学习和理解,个人对于MIPI LCD接口的调试有了自己的一点心得,当然也收获了Linux DRM显示框架及调试的一些心得,DRM真的很难很难,本文也无法顾及所有的细节,之前也发了一些D ...

  10. Nvidia Agx Xavier平台MIPI CSI-DHPY驱动调试

    1. 前言 这边使用Toshiba TC358748X 的DVP转MIPI的芯片, 通过排线连接到nvidia xavier平台, 通过移植官方通用驱动,调试过程需要一些问题 2. 硬件连接 3. 视 ...

最新文章

  1. 自然语言处理(NLP)之用深度学习实现命名实体识别(NER)
  2. day21IO流+FIle递归
  3. Android 之 布局训练
  4. js三进制计算机,js 笔记 - 二进制位运算符
  5. LESSON 11.4 原理进阶:AdaBoost算法流程详解
  6. 李宏毅深度学习——深度学习介绍
  7. Windows FFMPEG开发环境配置
  8. 贪吃蛇代码c语言改分,刚学C语言,想写一个贪吃蛇的代码
  9. Today Take a Look at Nike's Valentine's Day Sneakers
  10. 关于跨域以及跨域的实现方式
  11. 暴风影音皮肤_暴风影音16周年纪念版 v9.04
  12. 微信小程序利用腾讯云IM即时通讯发送文字+表情开发
  13. 关于C++的placement new和placement delete
  14. 白鹭egret的自定义素材解析器
  15. Excel 2019:二级级联下拉框设置
  16. 三只大老虎和三只小老虎过河
  17. 每天一个IDA小技巧(二):基本代码转换
  18. 【转】Esri和Autodesk携手致力实现GIS与BIM融合
  19. 医疗供应链-药品SPD管理
  20. 电影TS、TC、BD版和HD版

热门文章

  1. python加减乘除求余
  2. 微信红包雨怎么抢_微信红包雨怎么发? 微信红包雨的操作方法?
  3. mysql生成连续数字或日期
  4. Arduino基础项目十三:通过开关控制风扇
  5. 第三集 怪物学院 第十六章
  6. 链队列——-链式存储实现队列的入队出队(带next,front,rear指针)
  7. byte[]数组转String中文乱码
  8. mac电脑怎么彻底删除卸载桌面软件图标的软件?
  9. 设置vs2107背景图片
  10. 产品经理-自然资源行业4大产品线整理