mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 19:30:30 +09:00
media: spi: rk1608: add virtual sub sensor for dsp combine mode.
dts example:
virtual-sub-sensor-config-0 {
id = <1>;
in_mipi = <2>;
out_mipi = <1>;
};
Signed-off-by: Sach Lin <sach.lin@rock-chips.com>
Change-Id: I990c2969783301816560514a0be986bf61cd4192
This commit is contained in:
@@ -556,16 +556,17 @@ static int rk1608_lsb_w32(struct spi_device *spi, s32 addr, s32 data)
|
||||
}
|
||||
|
||||
static int rk1608_msg_init_sensor(struct rk1608_state *pdata,
|
||||
struct msg_init *msg, int id)
|
||||
struct msg_init *msg, int in_mipi, int out_mipi,
|
||||
int id, int cam_id)
|
||||
{
|
||||
u32 idx = pdata->dphy[id]->fmt_inf_idx;
|
||||
|
||||
msg->msg_head.size = sizeof(struct msg_init);
|
||||
msg->msg_head.type = id_msg_init_sensor_t;
|
||||
msg->msg_head.id.camera_id = id;
|
||||
msg->msg_head.id.camera_id = cam_id;
|
||||
msg->msg_head.mux.sync = 1;
|
||||
msg->in_mipi_phy = pdata->dphy[id]->in_mipi;
|
||||
msg->out_mipi_phy = pdata->dphy[id]->out_mipi;
|
||||
msg->in_mipi_phy = in_mipi;
|
||||
msg->out_mipi_phy = out_mipi;
|
||||
msg->mipi_lane = pdata->dphy[id]->fmt_inf[idx].mipi_lane;
|
||||
msg->bayer = 0;
|
||||
memcpy(msg->sensor_name, pdata->dphy[id]->sensor_name,
|
||||
@@ -573,6 +574,7 @@ static int rk1608_msg_init_sensor(struct rk1608_state *pdata,
|
||||
|
||||
msg->i2c_slave_addr = pdata->dphy[id]->i2c_addr;
|
||||
msg->i2c_bus = pdata->dphy[id]->i2c_bus;
|
||||
msg->sub_sensor_num = pdata->dphy[id]->sub_sensor_num;
|
||||
|
||||
return rk1608_send_msg_to_dsp(pdata, &msg->msg_head);
|
||||
}
|
||||
@@ -598,7 +600,7 @@ static int rk1608_msg_init_dsp_time(struct rk1608_state *pdata,
|
||||
}
|
||||
|
||||
static int rk1608_msg_set_input_size(struct rk1608_state *pdata,
|
||||
struct msg_in_size *msg, int id)
|
||||
struct msg_in_size *msg, int id, int cam_id)
|
||||
{
|
||||
u32 i;
|
||||
u32 msg_size = sizeof(struct msg);
|
||||
@@ -620,14 +622,14 @@ static int rk1608_msg_set_input_size(struct rk1608_state *pdata,
|
||||
|
||||
msg->msg_head.size = msg_size / sizeof(int);
|
||||
msg->msg_head.type = id_msg_set_input_size_t;
|
||||
msg->msg_head.id.camera_id = id;
|
||||
msg->msg_head.id.camera_id = cam_id;
|
||||
msg->msg_head.mux.sync = 1;
|
||||
|
||||
return rk1608_send_msg_to_dsp(pdata, &msg->msg_head);
|
||||
}
|
||||
|
||||
static int rk1608_msg_set_output_size(struct rk1608_state *pdata,
|
||||
struct msg_set_output_size *msg, int id)
|
||||
struct msg_set_output_size *msg, int id, int cam_id)
|
||||
{
|
||||
u32 i;
|
||||
u32 msg_size = sizeof(struct msg_out_size_head);
|
||||
@@ -649,7 +651,7 @@ static int rk1608_msg_set_output_size(struct rk1608_state *pdata,
|
||||
|
||||
msg->head.msg_head.size = msg_size / sizeof(int);
|
||||
msg->head.msg_head.type = id_msg_set_output_size_t;
|
||||
msg->head.msg_head.id.camera_id = id;
|
||||
msg->head.msg_head.id.camera_id = cam_id;
|
||||
msg->head.msg_head.mux.sync = 1;
|
||||
msg->head.width = fmt_inf->hactive;
|
||||
msg->head.height = fmt_inf->vactive;
|
||||
@@ -933,6 +935,54 @@ static int rk1608_disp_read_eeprom_request(struct rk1608_state *pdata)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rk1608_init_virtual_sub_sensor(
|
||||
struct rk1608_state *pdata, int id, int index)
|
||||
{
|
||||
struct msg *msg = NULL;
|
||||
struct msg_init *msg_init = NULL;
|
||||
struct msg_in_size *msg_in_size = NULL;
|
||||
struct msg_set_output_size *msg_out_size = NULL;
|
||||
int cam_id = pdata->dphy[id]->sub_sensor[index].id;
|
||||
int in_mipi = pdata->dphy[id]->sub_sensor[index].in_mipi;
|
||||
int out_mipi = pdata->dphy[id]->sub_sensor[index].out_mipi;
|
||||
int ret = 0;
|
||||
|
||||
msg = kzalloc(sizeof(*msg), GFP_KERNEL);
|
||||
if (!msg) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
msg_init = kzalloc(sizeof(*msg_init), GFP_KERNEL);
|
||||
if (!msg_init) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
msg_in_size = kzalloc(sizeof(*msg_in_size), GFP_KERNEL);
|
||||
if (!msg_in_size) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
msg_out_size = kzalloc(sizeof(*msg_out_size), GFP_KERNEL);
|
||||
if (!msg_out_size) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = rk1608_msg_init_sensor(pdata, msg_init, in_mipi, out_mipi, id, cam_id);
|
||||
ret |= rk1608_msg_set_input_size(pdata, msg_in_size, id, cam_id);
|
||||
ret |= rk1608_msg_set_output_size(pdata, msg_out_size, id, cam_id);
|
||||
ret |= rk1608_msg_set_stream_in_on(pdata, msg, cam_id);
|
||||
|
||||
err:
|
||||
kfree(msg_init);
|
||||
kfree(msg_in_size);
|
||||
kfree(msg_out_size);
|
||||
kfree(msg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rk1608_init_sensor(struct rk1608_state *pdata, int id)
|
||||
{
|
||||
struct msg *msg = NULL;
|
||||
@@ -940,6 +990,9 @@ static int rk1608_init_sensor(struct rk1608_state *pdata, int id)
|
||||
struct msg_in_size *msg_in_size = NULL;
|
||||
struct msg_set_output_size *msg_out_size = NULL;
|
||||
struct msg_init_dsp_time *msg_init_time = NULL;
|
||||
int in_mipi = pdata->dphy[id]->in_mipi;
|
||||
int out_mipi = pdata->dphy[id]->out_mipi;
|
||||
int cam_id = id;
|
||||
int ret = 0;
|
||||
|
||||
if (!pdata->sensor[id]) {
|
||||
@@ -975,12 +1028,13 @@ static int rk1608_init_sensor(struct rk1608_state *pdata, int id)
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = rk1608_msg_init_sensor(pdata, msg_init, id);
|
||||
|
||||
ret = rk1608_msg_init_sensor(pdata, msg_init, in_mipi, out_mipi, id, cam_id);
|
||||
ret |= rk1608_msg_init_dsp_time(pdata, msg_init_time, id);
|
||||
ret |= rk1608_msg_set_input_size(pdata, msg_in_size, id);
|
||||
ret |= rk1608_msg_set_output_size(pdata, msg_out_size, id);
|
||||
ret |= rk1608_msg_set_stream_in_on(pdata, msg, id);
|
||||
ret |= rk1608_msg_set_stream_out_on(pdata, msg, id);
|
||||
ret |= rk1608_msg_set_input_size(pdata, msg_in_size, id, cam_id);
|
||||
ret |= rk1608_msg_set_output_size(pdata, msg_out_size, id, cam_id);
|
||||
ret |= rk1608_msg_set_stream_in_on(pdata, msg, cam_id);
|
||||
ret |= rk1608_msg_set_stream_out_on(pdata, msg, cam_id);
|
||||
|
||||
err:
|
||||
kfree(msg_init);
|
||||
@@ -1175,11 +1229,25 @@ static int rk1608_sensor_power(struct v4l2_subdev *sd, int on)
|
||||
static int rk1608_stream_on(struct rk1608_state *pdata)
|
||||
{
|
||||
int id = 0, cnt = 0, ret = 0;
|
||||
int sub_sensor_num = 0, index = 0;
|
||||
|
||||
mutex_lock(&pdata->lock);
|
||||
id = pdata->sd.grp_id;
|
||||
pdata->sensor_cnt = 0;
|
||||
pdata->set_exp_cnt = 1;
|
||||
|
||||
sub_sensor_num = pdata->dphy[id]->sub_sensor_num;
|
||||
for (index = 0; index < sub_sensor_num; index++) {
|
||||
ret = rk1608_init_virtual_sub_sensor(pdata, id, index);
|
||||
if (ret) {
|
||||
dev_err(pdata->dev, "Init rk1608[%d] sub[%d] is failed!",
|
||||
id,
|
||||
index);
|
||||
mutex_unlock(&pdata->lock);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = rk1608_init_sensor(pdata, id);
|
||||
if (ret) {
|
||||
dev_err(pdata->dev, "Init rk1608[%d] is failed!",
|
||||
@@ -1221,9 +1289,18 @@ static int rk1608_stream_on(struct rk1608_state *pdata)
|
||||
|
||||
static int rk1608_stream_off(struct rk1608_state *pdata)
|
||||
{
|
||||
u32 sub_sensor_num = 0, index = 0, sub_id = 0;
|
||||
|
||||
mutex_lock(&pdata->sensor_lock);
|
||||
pdata->sensor_cnt = 0;
|
||||
mutex_unlock(&pdata->sensor_lock);
|
||||
|
||||
sub_sensor_num = pdata->dphy[pdata->sd.grp_id]->sub_sensor_num;
|
||||
for (index = 0; index < sub_sensor_num; index++) {
|
||||
sub_id = pdata->dphy[pdata->sd.grp_id]->sub_sensor[index].id;
|
||||
rk1608_deinit(pdata, sub_id);
|
||||
}
|
||||
|
||||
rk1608_deinit(pdata, pdata->sd.grp_id);
|
||||
|
||||
return 0;
|
||||
@@ -2096,7 +2173,7 @@ static int rk1608_get_calib_version_temperature_sn(struct rk1608_state *pdata,
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (head->item[i].size > 128) {
|
||||
if (head->item[i].size > sizeof(calibdata_->calib_sn_code)) {
|
||||
dev_err(pdata->dev, "%s: %s size:%d error!\n",
|
||||
__func__, head->item[i].name, head->item[i].size);
|
||||
goto err;
|
||||
@@ -2113,7 +2190,7 @@ static int rk1608_get_calib_version_temperature_sn(struct rk1608_state *pdata,
|
||||
|
||||
pos = head->item[i].offset;
|
||||
|
||||
ret = kernel_read(fp, (char *)&calibdata_->calib_sn_code, head->item[i].size, &pos);
|
||||
ret = kernel_read(fp, (char *)calibdata_->calib_sn_code, head->item[i].size, &pos);
|
||||
if (ret <= 0) {
|
||||
dev_err(pdata->dev, "%s: read error: ret=%d\n", __func__, ret);
|
||||
goto err;
|
||||
|
||||
@@ -213,6 +213,7 @@ struct msg_init {
|
||||
s8 bayer;
|
||||
u8 sensor_name[32];
|
||||
u8 i2c_slave_addr;
|
||||
u8 sub_sensor_num;
|
||||
};
|
||||
|
||||
struct preisp_vc_cfg {
|
||||
@@ -330,7 +331,7 @@ struct msg_calib_temp {
|
||||
u32 calib_exist;
|
||||
u32 calib_sn_size;
|
||||
u32 calib_sn_offset;
|
||||
u32 calib_sn_code;
|
||||
u8 calib_sn_code[64];
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -235,6 +235,10 @@ static int rk1608_g_frame_interval(struct v4l2_subdev *sd,
|
||||
{
|
||||
struct rk1608_dphy *pdata = to_state(sd);
|
||||
|
||||
if (!(pdata->rk1608_sd)) {
|
||||
dev_info(pdata->dev, "pdata->rk1608_sd NULL\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
pdata->rk1608_sd->grp_id = sd->grp_id;
|
||||
v4l2_subdev_call(pdata->rk1608_sd,
|
||||
video,
|
||||
@@ -597,6 +601,7 @@ static int rk1608_dphy_dt_property(struct rk1608_dphy *dphy)
|
||||
struct device_node *parent_node = of_node_get(node);
|
||||
struct device_node *prev_node = NULL;
|
||||
u32 idx = 0;
|
||||
u32 sub_idx = 0;
|
||||
|
||||
ret = of_property_read_u32(node, "id", &dphy->sd.grp_id);
|
||||
if (ret)
|
||||
@@ -754,6 +759,53 @@ static int rk1608_dphy_dt_property(struct rk1608_dphy *dphy)
|
||||
}
|
||||
dphy->fmt_inf_num = idx;
|
||||
|
||||
prev_node = NULL;
|
||||
/* get virtual sub sensor */
|
||||
node = NULL;
|
||||
while (!IS_ERR_OR_NULL(node =
|
||||
of_get_next_child(parent_node, prev_node))) {
|
||||
if (!strncasecmp(node->name,
|
||||
"virtual-sub-sensor-config",
|
||||
strlen("virtual-sub-sensor-config"))) {
|
||||
|
||||
if (sub_idx >= 4) {
|
||||
dev_err(dphy->dev, "get too mach sub_sensor node, max 4.\n");
|
||||
break;
|
||||
}
|
||||
|
||||
ret = of_property_read_u32(node, "id",
|
||||
&dphy->sub_sensor[sub_idx].id);
|
||||
if (ret)
|
||||
dev_warn(dphy->dev, "Can not get sub sensor id!");
|
||||
else
|
||||
dev_info(dphy->dev, "get sub sensor id:%d",
|
||||
dphy->sub_sensor[sub_idx].id);
|
||||
|
||||
ret = of_property_read_u32(node, "in_mipi",
|
||||
&dphy->sub_sensor[sub_idx].in_mipi);
|
||||
if (ret)
|
||||
dev_warn(dphy->dev, "Can not get sub sensor in_mipi!");
|
||||
else
|
||||
dev_info(dphy->dev, "get sub sensor in_mipi:%d",
|
||||
dphy->sub_sensor[sub_idx].in_mipi);
|
||||
|
||||
ret = of_property_read_u32(node, "out_mipi",
|
||||
&dphy->sub_sensor[sub_idx].out_mipi);
|
||||
if (ret)
|
||||
dev_warn(dphy->dev, "Can not get sub sensor out_mipi!");
|
||||
else
|
||||
dev_info(dphy->dev, "get sub sensor out_mipi:%d",
|
||||
dphy->sub_sensor[sub_idx].out_mipi);
|
||||
|
||||
sub_idx++;
|
||||
}
|
||||
|
||||
of_node_put(prev_node);
|
||||
prev_node = node;
|
||||
}
|
||||
dphy->sub_sensor_num = sub_idx;
|
||||
/* get virtual sub sensor end */
|
||||
|
||||
of_node_put(prev_node);
|
||||
of_node_put(parent_node);
|
||||
|
||||
|
||||
@@ -28,6 +28,13 @@ struct rk1608_fmt_inf {
|
||||
u32 vcrop;
|
||||
};
|
||||
|
||||
struct rk1608_sub_sensor_cfg {
|
||||
u32 id;
|
||||
u32 in_mipi;
|
||||
u32 out_mipi;
|
||||
u32 reserved;
|
||||
};
|
||||
|
||||
struct rk1608_dphy {
|
||||
struct v4l2_subdev sd;
|
||||
struct v4l2_subdev *rk1608_sd;
|
||||
@@ -63,6 +70,10 @@ struct rk1608_dphy {
|
||||
struct rk1608_fmt_inf fmt_inf[RK1608_MAX_FMTINF];
|
||||
|
||||
bool first_stream;
|
||||
|
||||
/* for virtual sub sensor */
|
||||
u32 sub_sensor_num;
|
||||
struct rk1608_sub_sensor_cfg sub_sensor[4];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user