Qcom平台 TC358840 调试指南

Key-Word:TC358840、MSM8953、Android9.0

简介 : HDMI 转 MIPI(CSI) 芯片

平台 : MSM8953

芯片 : TC358840XBG (最大支持4K 30fps)

Format : rgb 转 Ycbcr422-8bit

软件平台 :Android – P(9.0 )

信号输出源:电脑主机

目前调通的配置:1080p 30fps 4lane (预览30帧、录像30帧)

Author: Leo   2020.12.30

1. 前言:

TC358840 是一个 HDMI 转 CSI 信号的转换,信号由其他设备输入进来。对平台端msm8953 而言,可以当做一个摄像头处理。

在840(TC358840后面简称840)芯片初始化后,其他信号设备会经 HDMI 接口读取芯片的EDID 数据,

探测芯片端支持的最大分辨率,探测成功后,默认输出840芯片最大支持的分辨率。(一个芯片内可同时储存多种EDID数据,即同时支持多种分辨率。)

调试时用电脑主机接上初始化完的芯片(写EDID等数据),电脑上会显示识别到一个新的显示器。

具体的分辨率见电脑显示设置。

2. 遇到的问题

  1. 840芯片 寄存器读取ID失败。
  2. 840芯片 寄存器写入不起作用。
  3. 840芯片 识别到后,数据流异常。无法预览、拍照、录像。
  4. 数据出流后颜色异常,颜色发绿。

2.1 解决

  1.  840芯片的从机地址由INT 脚的电平决定,上拉为0x1F,下拉为0x0F。实际使用要两种都尝试一下。 我们实际调试中发现,硬件链接到普通IIC上(非CCI),在kernel中写 一个iic驱动,读取的从机地址为0F,用vendorcam 驱动的方式 slave_addr为1F。
  2.  写入大小端不一致,解决办法见 CCI 写问题。见附录。
  3.  通过底层添加 csid csi等驱动log后,发现并无异常 frame id 会递增说明接收到了帧。最后排查发现是初始化代码中没有设置输出流的帧格式,导致无法正确解析到帧。
  4.  颜色异常修改数据格式后解决。.filter_arrangement = SENSOR_UYVY, 

后续存在问题:

  1.  1080P 60fps的画面输出调试,甚至更高的其他分辨率如4K 30fps。
  2.  外部信号输入需要动态调节的,比如同一个信号输入源分辨率、帧率的改变。不同信号源之间,HDMI 线的插拔切换。

3. 达到的功能点

  1. 840 芯片相对主控来说作为一个cam 设备,但信号是从外部信号源输入840后再转化为mipi信号。
  2. 相机要能够正常的打开使用。

功能点的验证和预期结果:

  1.  插入外部1080p、30fps的信号 (插到电脑主机上会自动输出匹配格式的信号)。
  2.  打开qcom相机,电脑能够识别到一个外部显示器(数据格式分辨率、帧率都可以看出来 这里是 RGB 1080p 30fps)
  3.  查看预览、拍照、录像、画面是否正常,颜色是否正常。
  4.  在相机设置中相片尺寸需要调节为 HD 1080P,这样拍照的照片才是 1920x1080的分辨率。
  5.  录像测试: 切到录像模式,录像后,退出。用adb pull sdcard/DCIM/camera 到本地电脑上,查看录像文件信息,可以看到帧率为30帧。

功能点实测:

1、 和预期一致。验证通过。

4. kernel drv 配置

首先是一个YUV camera的适配:

第一步就是配置好dts和vendor的驱动,保证 cam 读取ID 匹配正常。

需要注意,这是一个YUV的cam,因此不需要效果 chromatix文件的配置,所以一切和效果相关的配置都需要去掉。

供电:实际的电路供电修改过,因此实际的dts配置以实际应用的为准。

这里简单说明。有三路供电。1V2 1V8和3V3。

dts中把 1V2和1V8 配置上即可。

其他如rst、pwd脚、挂载位置、角度、cci 总线位置,根据硬件接线配置。

mclk配置:使用外置晶振提供clk时钟,不使用平台的mclk

4.1 CCI 读问题

经过加log实测发现,840芯片大小端和平台端相反。因此按照默认的写入方式,芯片的初始化是不正确的。需要做修改。

CCI 读取问题:

如840的识别ID寄存器地址是 0xx00,按照CCI 的默认读取方式读出是0x47(0x0047)。

但是按照IIC的读取方式和我们的一般认知应该是0x4700。

为了保证对比方便(后续会把写入的寄存器值再读出来做对比)和认知一致,我们在读取函数中作如下修改。

kernel\msm-4.9\drivers\media\platform\msm\camera_v2\sensor\io\msm_camera_cci_i2c.c 54
int32_t msm_camera_cci_i2c_read
===>
	rc = cci_ctrl.status;
	if (data_type == MSM_CAMERA_I2C_BYTE_DATA)
		*data = buf[0];
	else {
		*data = buf[0] << 8 | buf[1];
===> 修改为
	rc = cci_ctrl.status;
	if (data_type == MSM_CAMERA_I2C_BYTE_DATA)
		*data = buf[0];
	else {
	//	*data = buf[0] << 8 | buf[1];
		*data = buf[1] << 8 | buf[0];
	}

这样修改后,读取出的 0x00 就是0x4700了。和平台大小端一致,而且是按照我们的阅读顺序,高位在左,低位在右。

4.2 CCI 写问题

写寄存器比较麻烦,需要修改多处。有以下几个问题。

  1.  840的初始化数组,有三种不同的类型,有8bit、16bit、32bit、的寄存器。
  2. 咨询芯片厂商,8bit的要按照8bit的去写,16bit的按照16bit的去写,32bit可以拆分为两个 16bit的去写入,且数据的写入顺序不能修改。因此至少要按照两种类型去写入。
  3.  vendor的cam驱动中,初始化数组res0中,数据类型是固定的,只能设置为 byte(8bit)或者word(16bit)类型,不能为每个数据设置类型。

这里通过修改vemdor的cam驱动和底层的写函数来实现。

  1. 区分不同的数据类型。在cam的初始化数组中,通过添加延时,来区分8bit或者16bit的数据类型。通过观察,默认数据有三种 8bit无延时,16bit无延时,16bit有延时(这类保持默认延时,不做修改)。因此,在每个16bit的后面都加0x01(1us)的延时,通过判断延时时间是否>0就可以把8bit和16bit的数据类型区分开。默认设置初始化数据类型为 word 类型。

2.  修改底层驱动,根据延时判断数据类型。

查看驱动流程,所有的读写都是通过队列来完成的,最终都会调用到这个函数。

msm_cci.c kernel\msm-4.9\drivers\media\platform\msm\camera_v2\sensor\cci
int32_t msm_cci_data_queue(...)

默认写函数关键代码如下:

/* max of 10 data bytes */
		do {
			if (i2c_msg->data_type == MSM_CAMERA_I2C_BYTE_DATA) {
				data[i++] = i2c_cmd->reg_data;
				reg_addr++;
			} else {
				if ((i + 1) <= cci_dev->payload_size) {
					data[i++] = (i2c_cmd->reg_data &
						0xFF00) >> 8; /* MSB */
					data[i++] = i2c_cmd->reg_data &
						0x00FF; /* LSB */
					reg_addr++;
				} else
					break;
			}
			i2c_cmd++;
			--cmd_size;
		} while (((c_ctrl->cmd == MSM_CCI_I2C_WRITE_SEQ) || pack--) &&
				(cmd_size > 0) && (i <= cci_dev->payload_size));

可以看到这里判断了数据类型,并且若是word类型,data数组中分别放置高8bit和低8bit。

这里做两个修改:

  1. 通过延时区分8bit、16bit 数据类型。

添加如下内容

+#if 1
+		if (i2c_cmd->delay > 0)
+			i2c_msg->data_type = MSM_CAMERA_I2C_WORD_DATA;
+		else
+			i2c_msg->data_type = MSM_CAMERA_I2C_BYTE_DATA;
+#endif
		i = 0;
		data[i++] = CCI_I2C_WRITE_CMD;

2. 由于大小端相反,交换高低8bit数据。

data[i++] = (i2c_cmd->reg_data &
						0xFF00) >> 8; /* MSB */
					data[i++] = i2c_cmd->reg_data &
						0x00FF; /* LSB */
					reg_addr++;
===> 修改为
					data[i++] = i2c_cmd->reg_data &
						0x00FF; /* LSB */
					data[i++] = (i2c_cmd->reg_data &
						0xFF00) >> 8; /* MSB */

5. vendor drv 配置

TC358840的驱动是在 gc5025的驱动上修改的,只是名字还是用的gc5025,实际驱动和gc5025毫无关系。

1.  修改device-vendor.mk 

\vendor\qcom\proprietary\common\config 

由于是YUV cam,去掉所有效果相关的 lib。只保留 MM_CAMERA += libmmcamera_gc5025

2. 修改 cam config 配置文件

msm8953_camera.xml vendor\qcom\proprietary\
mm-camera\mm-camera2\media-controller\modules\sensors\configs\	

  <CameraModuleConfig>
    <CameraId>0</CameraId>
    <SensorName>gc5025</SensorName>
    <ModesSupported>1</ModesSupported>
    <Position>BACK</Position>
    <MountAngle>90</MountAngle>
    <CSIInfo>
      <CSIDCore>0</CSIDCore>
      <LaneMask>0x1F</LaneMask>
      <LaneAssign>0x4320</LaneAssign>
      <ComboMode>0</ComboMode>
    </CSIInfo>
    <LensInfo>
      <FocalLength>5.24</FocalLength>
      <FNumber>1.05</FNumber>
      <TotalFocusDistance>47</TotalFocusDistance>
      <HorizontalViewAngle>94</HorizontalViewAngle>
      <VerticalViewAngle>49.5</VerticalViewAngle>
      <MinFocusDistance>0.1</MinFocusDistance>
    </LensInfo>
  </CameraModuleConfig>

3.  去除 charomatix 配置文件的链接

vendor/qcom/proprietary/mm-camera/
mm-camera2/mediacontroller/modules/sensors/configs/project.mk
去除 gc5025的效果文件的编译。
+# include $(CLEAR_VARS)
+# LOCAL_MODULE:= gc5025_chromatix.xml
+# LOCAL_MODULE_CLASS := EXECUTABLES
+# LOCAL_SRC_FILES := gc5025_chromatix.xml
+# LOCAL_MODULE_TAGS := optional
+# LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/etc/camera
+# LOCAL_MODULE_OWNER := qti
+# include $(BUILD_PREBUILT)

4.  去除 charomatix 配置文件的编译

vendor/qcom/proprietary/mm-camera/mm-camera2/media-controller/modules/sensors/chromatix/0310/chromatix_gc5025/Android.mk
ifeq ($(call is-vendor-board-platform,QCOM),true)
- include $(call all-subdir-makefiles)
+ # include $(call all-subdir-makefiles)
endif

5.  延长帧检测时间。由于在840的初始化代码中,有很多必要且很长的延时,因此为了避免帧检测时间过短,导致还没初始化完成的时候就误判退出,加长了帧检测时间的设置。

vendor/qcom/proprietary/mm-camera/mm-camera2/media-controller/mct/bus/mct_bus.c
-#define MCT_BUS_NANOSECOND_SCALER 1000000000
+//#define MCT_BUS_NANOSECOND_SCALER 1000000000
+#define MCT_BUS_NANOSECOND_SCALER   3000000000 // 3s
 #define MAX_MCT_BUS_QUEUE_LENGTH 1000

补充:

EDID :

       EDID,Extended display identification data,中文名称扩展显示器识别数据,是VESA在制定DDC显示器数据通道通信协议时,制定的有关显示器识别数据的标准。EDID存储在显示器中的DDC存储器中,当电脑主机与显示器连接后,电脑主机会通道DDC通道读取显示器DDC存储器中的存储的EDID。

      EDID其中包含有关显示器及其性能的参数,包括供应商信息、最大图像大小、颜色设置、厂商预设置、频率范围的限制以及显示器名和序列号的字符串等等。形象地说,EDID就是显示器的身份证、户口本、技能证书等证件的集合,目的就是告诉别人我是谁,我从哪来,我能干什么。

说人话:就是电脑主机输出端,读取到 EDID 信息,获取到芯片端最大支持的信息,然后是输出对应的数据流。

      对我们来说,我们关心的,就是芯片中对自身支持的最大分辨率、帧率的一个信息。EDID 在成功写入芯片后,就代表了芯片对外界的一个回应信息,在电脑主机插入芯片的HDMI接口的时候,主机会读取芯片的EDID数据,从而明白主机本身应该输出多大分辨率和帧率的数据流。

     840芯片同时可储存多组EDID信息,即同时支持多种分辨率。如同时支持1080P@60fps、1080P@30fps、720P@60fps、720P@60fps等等。

你再快,也永远有人比你快!Fighting ~~

  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值