1. 说明:模组内部包括ISP(OAX4000)和Sensor(OX05B1S)两部分,本方案均已提供获取方法。
2. OAX4000 温度读取方案
2.1 寄存器方案
直接读取0x4030和0x4031寄存器,同0x912C和0x912D寄存器。
0x4030[7:0]: OAX4000 temperature integer part, same as 0x912C[7:0]
0X4031[7:0]: OAX4000 temperature decimal part, same as 0x912D[7:0]
2.2 hostcmd方案
基于v4l2-subdev 增加 ioctl 操作command
diff --git a/nvidia-oot/drivers/media/i2c/nv_ox05b1s.c b/nvidia-oot/drivers/media/i2c/nv_ox05b1s.c
index 0a245383a..60b51ae19 100644
--- a/nvidia-oot/drivers/media/i2c/nv_ox05b1s.c
+++ b/nvidia-oot/drivers/media/i2c/nv_ox05b1s.c
@@ -206,6 +206,7 @@ static struct mutex serdes_lock__;
#define VIDIOC_PRIVATE_IOCTL_ISP_UPGRADE_FIRMWARE _IOW('V', BASE_VIDIOC_PRIVATE + 2, uint32_t)
#define VIDIOC_PRIVATE_IOCTL_ISP_GET_FIRMWARE_VERSION _IOR('V', BASE_VIDIOC_PRIVATE + 3, uint32_t)
#define VIDIOC_PRIVATE_IOCTL_ISP_RESET _IO('V', BASE_VIDIOC_PRIVATE + 4)
+#define VIDIOC_PRIVATE_IOCTL_ISP_READ_REG _IOWR('V', BASE_VIDIOC_PRIVATE + 5, struct reg_8)
bool SendCmd_Sensor_stream_on(struct ox05b1s *priv);
bool SendCmd_Sensor_stream_off(struct ox05b1s *priv);
@@ -3323,6 +3324,16 @@ long ox05b1s_v4l2subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *ar
dev_info(tc_dev->dev, "Isp reset\n");
ret = OAX4000_reset(priv);
break;
+ case VIDIOC_PRIVATE_IOCTL_ISP_READ_REG:
+ {
+ struct reg_8 *reg_io = (struct reg_8 *)arg;
+ // dev_info(tc_dev->dev, "Isp read reg: 0x%x\n", reg_io->addr);
+ ret = ox05b1s_read_reg(s_data, reg_io->addr, ®_io->val);
+ // if (ret == 0) {
+ // dev_info(tc_dev->dev, "Read reg 0x%x: 0x%x\n", reg_io->addr, reg_io->val);
+ // }
+ break;
+ }
// ignore cmd:3224131130
case VIDIOC_CROPCAP:
break;
3. OX05B1S 温度读取方案
3.1 寄存器方案
0x40F0[7:0]: sensor temperature integer part
0x40F1[7:0]: sensor temperature decimal part
3.2 hostcmd 方案
缺点:不宜高频读取,容易与FW不停更新sccb,造成系统繁忙,报time out。
基于v4l2-subdev 增加 ioctl 操作command和oax4000 hostcmd。
diff --git a/nvidia-oot/drivers/media/i2c/nv_ox05b1s.c b/nvidia-oot/drivers/media/i2c/nv_ox05b1s.c
index 60b51ae19..c5e4be145 100644
--- a/nvidia-oot/drivers/media/i2c/nv_ox05b1s.c
+++ b/nvidia-oot/drivers/media/i2c/nv_ox05b1s.c
@@ -207,9 +207,11 @@ static struct mutex serdes_lock__;
#define VIDIOC_PRIVATE_IOCTL_ISP_GET_FIRMWARE_VERSION _IOR('V', BASE_VIDIOC_PRIVATE + 3, uint32_t)
#define VIDIOC_PRIVATE_IOCTL_ISP_RESET _IO('V', BASE_VIDIOC_PRIVATE + 4)
#define VIDIOC_PRIVATE_IOCTL_ISP_READ_REG _IOWR('V', BASE_VIDIOC_PRIVATE + 5, struct reg_8)
+#define VIDIOC_PRIVATE_IOCTL_ISP_HOSTCMD_READ_REG _IOWR('V', BASE_VIDIOC_PRIVATE + 6, struct reg_8)
bool SendCmd_Sensor_stream_on(struct ox05b1s *priv);
bool SendCmd_Sensor_stream_off(struct ox05b1s *priv);
+bool SendCmd_sensor_temperature_get(struct ox05b1s *priv);
bool SendCmd_ISP_stream_on(struct ox05b1s *priv);
bool SendCmd_ISP_stream_off(struct ox05b1s *priv);
bool SendCmd_PageWrite(struct ox05b1s *priv, unsigned char* buf, uint16_t pgIdx);
@@ -224,9 +226,12 @@ int writeBurstRegister(struct ox05b1s *priv, uint32_t addr, unsigned char* pData
int BurstWriteRegister(struct ox05b1s *priv, unsigned int addr, unsigned char* value, bool b16bitAddress, unsigned int num);
int Clear_CRC(struct ox05b1s *priv);
+#define CMD_OUTPUT_VALUE_0 0x00 (0x3C07)
+
#define BURST_SIZE (32)
// sensor related host command
#define CMD_ACCESS_SCCB_SLAVE_DEVICE (0x00)
+#define CMD_TEMP_GET (0x02)
// non-sensor related host command
#define CMD_STREAMING_CTRL (0x19)
// extra system host command
@@ -2071,11 +2076,44 @@ bool SendCmd_Sensor_stream_off(struct ox05b1s *priv)
para[4] = 0x00; //para num hi
para[5] = 0x06; //para num lo
para[6] = 0x00; //
- para[7] = 0x00; //
- para[8] = 0x01; //[7:4]:MTX portX gate control, [3:0]: MTX select
- para[9] = 0x00; //
- para[10] = 0x01;
- para[11] = 0x00;
+ para[7] = 0x00; //
+ para[8] = 0x01; //[7:4]:MTX portX gate control, [3:0]: MTX select
+ para[9] = 0x00; //
+ para[10] = 0x01;
+ para[11] = 0x00;
+
+ return HostCmd_Sensor_Set(priv,para, para_num, 100);
+ #endif
+
+ return 0;
+}
+
+bool SendCmd_sensor_temperature_get(struct ox05b1s *priv)
+{
+ #ifdef CONFIG_ULTRON_POS
+ struct camera_common_data *s_data = priv->s_data;
+ uint8_t para_num = 12;
+ uint8_t para[12];
+ static ox05b1s_reg m_i2c_write_regs_2[1] = {
+ {0x4053, 0x00}
+ };
+ int rc = 0;
+
+ dev_info(&priv->i2c_client->dev, "SendCmd_sensor_temperature_get\n");
+ rc = regmap_write(s_data->regmap, m_i2c_write_regs_2[0].addr, m_i2c_write_regs_2[0].val);
+ if (rc < 0) {
+ dev_err(&priv->i2c_client->dev,"OAX4000:Failed to write 0x4053 rc %d", rc);
+ return 0;
+ }
+
+ para[0] = 0x00; //crc
+ para[1] = 0x00;
+ para[2] = 0;//g_hc_seqIdx++; // hc_seq_num
+ para[3] = CMD_TEMP_GET; //stream ctrl
+ para[4] = 0x00; //para num hi
+ para[5] = 0x01; //para num lo
+ para[6] = 0x00; //get sensor 0 temperature
+
return HostCmd_Sensor_Set(priv,para, para_num, 100);
#endif
@@ -3281,6 +3319,7 @@ long ox05b1s_v4l2subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *ar
struct tegracam_device *tc_dev = to_tegracam_device(s_data);
void* priv = NULL;
uint32_t value;
+ struct reg_8 *reg_io = NULL;
if (!arg) {
dev_err(tc_dev->dev, "Null argument for cmd: %u\n", cmd);
@@ -3326,7 +3365,7 @@ long ox05b1s_v4l2subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *ar
break;
case VIDIOC_PRIVATE_IOCTL_ISP_READ_REG:
{
- struct reg_8 *reg_io = (struct reg_8 *)arg;
+ reg_io = (struct reg_8 *)arg;
// dev_info(tc_dev->dev, "Isp read reg: 0x%x\n", reg_io->addr);
ret = ox05b1s_read_reg(s_data, reg_io->addr, ®_io->val);
// if (ret == 0) {
@@ -3334,6 +3373,17 @@ long ox05b1s_v4l2subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *ar
// }
break;
}
+ case VIDIOC_PRIVATE_IOCTL_ISP_HOSTCMD_READ_REG:
+ {
+ // reg_io = (struct reg_8 *)arg;
+ // dev_info(tc_dev->dev, "Isp read reg: 0x%x\n", reg_io->addr);
+ ret = SendCmd_sensor_temperature_get(priv);
+ // if (ret == 0) {
+ // dev_info(tc_dev->dev, "Read reg 0x%x: 0x%x\n", reg_io->addr, reg_io->val);
+ // }
+ break;
+ }
+
// ignore cmd:3224131130
case VIDIOC_CROPCAP:
break;
4. 计算公式
double calculate_tpm_temperature(int tpm_int, int tpm_dec) {
const int threshold = 192; // 0xC0 = 192
if (tpm_int >= threshold) {
return -1.0 * ((tpm_int - threshold) + tpm_dec / 256.0);
} else {
return tpm_int + tpm_dec / 256.0;
}
}
5. 温度读取
struct reg_8 value = {0};
value.addr = 0x912c;
ret = ioctl(fd, VIDIOC_PRIVATE_IOCTL_ISP_READ_REG, &value);
if (ret < 0) {
perror("Upgrade command failed to send.\n");
//return ret;
}
temp_int = value.val;
// printf("TEMP reg 0x912c, value: 0x%x\n", temp_int);
value.addr = 0x912d;
ret = ioctl(fd, VIDIOC_PRIVATE_IOCTL_ISP_READ_REG, &value);
if (ret < 0) {
perror("Upgrade command failed to send.\n");
//return ret;
}
temp_dec = value.val;
// printf("TEMP reg 0x912d, value: 0x%x\n", temp_dec);
close(fd);
// calc temperature
double temp1 = calculate_tpm_temperature(temp_int, temp_dec);
printf("TEMP %.2f°C (INT: %3d, DEC: %3d)\n\n", temp1, temp_int, temp_dec);
6. 测试结果
OAX4000读取结果:
OX05B1S 温度读取结果: