media: rockchip: isp: add lock to save tb info

multi sensor share same tb info buf, and this buf will
overwrittern when first sensor stream on but second fast_work
schedule slowly. So to save tb info for all dev at first read.

Change-Id: I335b9e3bd317202a348be17965be112a1259bb3e
Signed-off-by: Cai YiWei <cyw@rock-chips.com>
This commit is contained in:
Cai YiWei
2023-08-12 16:41:02 +08:00
committed by Tao Huang
parent 3ba7441b0d
commit 4ce5cb8b0f
2 changed files with 60 additions and 37 deletions

View File

@@ -1616,7 +1616,9 @@ static void rkisp_stream_fast(struct work_struct *work)
if (ispdev->isp_ver != ISP_V32) if (ispdev->isp_ver != ISP_V32)
return; return;
mutex_lock(&ispdev->hw_dev->dev_lock);
rkisp_chk_tb_over(ispdev); rkisp_chk_tb_over(ispdev);
mutex_unlock(&ispdev->hw_dev->dev_lock);
if (ispdev->tb_head.complete != RKISP_TB_OK) if (ispdev->tb_head.complete != RKISP_TB_OK)
return; return;
ret = v4l2_pipeline_pm_get(&stream->vnode.vdev.entity); ret = v4l2_pipeline_pm_get(&stream->vnode.vdev.entity);

View File

@@ -3817,8 +3817,52 @@ void rkisp_unregister_isp_subdev(struct rkisp_device *isp_dev)
}) })
#ifdef CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP #ifdef CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP
static void rkisp_save_tb_info(struct rkisp_device *isp_dev)
{
struct rkisp_isp_params_vdev *params_vdev = &isp_dev->params_vdev;
void *resmem_va = phys_to_virt(isp_dev->resmem_pa);
struct rkisp_thunderboot_resmem_head *head = resmem_va;
int size = 0, offset = 0;
void *param = NULL;
switch (isp_dev->isp_ver) {
case ISP_V32:
size = sizeof(struct rkisp32_thunderboot_resmem_head);
offset = size * isp_dev->dev_id;
break;
default:
break;
}
if (size && size < isp_dev->resmem_size) {
dma_sync_single_for_cpu(isp_dev->dev, isp_dev->resmem_addr + offset,
size, DMA_FROM_DEVICE);
params_vdev->is_first_cfg = true;
if (isp_dev->isp_ver == ISP_V32) {
struct rkisp32_thunderboot_resmem_head *tmp = resmem_va + offset;
param = &tmp->cfg;
head = &tmp->head;
v4l2_info(&isp_dev->v4l2_dev,
"tb param module en:0x%llx upd:0x%llx cfg upd:0x%llx\n",
tmp->cfg.module_en_update,
tmp->cfg.module_ens,
tmp->cfg.module_cfg_update);
}
if (param)
params_vdev->ops->save_first_param(params_vdev, param);
} else if (size > isp_dev->resmem_size) {
v4l2_err(&isp_dev->v4l2_dev,
"resmem size:%zu no enough for head:%d\n",
isp_dev->resmem_size, size);
head->complete = RKISP_TB_NG;
}
memcpy(&isp_dev->tb_head, head, sizeof(*head));
}
void rkisp_chk_tb_over(struct rkisp_device *isp_dev) void rkisp_chk_tb_over(struct rkisp_device *isp_dev)
{ {
struct rkisp_isp_params_vdev *params_vdev = &isp_dev->params_vdev;
struct rkisp_hw_dev *hw = isp_dev->hw_dev; struct rkisp_hw_dev *hw = isp_dev->hw_dev;
struct rkisp_thunderboot_resmem_head *head; struct rkisp_thunderboot_resmem_head *head;
enum rkisp_tb_state tb_state; enum rkisp_tb_state tb_state;
@@ -3827,6 +3871,9 @@ void rkisp_chk_tb_over(struct rkisp_device *isp_dev)
if (!isp_dev->is_thunderboot) if (!isp_dev->is_thunderboot)
return; return;
if (isp_dev->isp_ver == ISP_V32 && params_vdev->is_first_cfg)
goto end;
resmem_va = phys_to_virt(isp_dev->resmem_pa); resmem_va = phys_to_virt(isp_dev->resmem_pa);
head = (struct rkisp_thunderboot_resmem_head *)resmem_va; head = (struct rkisp_thunderboot_resmem_head *)resmem_va;
dma_sync_single_for_cpu(isp_dev->dev, isp_dev->resmem_addr, dma_sync_single_for_cpu(isp_dev->dev, isp_dev->resmem_addr,
@@ -3837,12 +3884,16 @@ void rkisp_chk_tb_over(struct rkisp_device *isp_dev)
if (head->complete != RKISP_TB_OK) { if (head->complete != RKISP_TB_OK) {
v4l2_err(&isp_dev->v4l2_dev, "wait thunderboot over timeout\n"); v4l2_err(&isp_dev->v4l2_dev, "wait thunderboot over timeout\n");
} else { } else {
struct rkisp_isp_params_vdev *params_vdev = &isp_dev->params_vdev; int i, timeout = 50;
void *param = NULL;
u32 size = 0, offset = 0, timeout = 50;
/* wait for all isp dev to register */ /* wait for all isp dev to register */
if (head->camera_num > 1) { if (head->camera_num > 1) {
if (head->camera_num > hw->dev_num) {
v4l2_err(&isp_dev->v4l2_dev,
"thunderboot invalid camera num:%d, dev num:%d\n",
head->camera_num, hw->dev_num);
goto end;
}
while (timeout--) { while (timeout--) {
if (hw->dev_num >= head->camera_num && if (hw->dev_num >= head->camera_num &&
hw->isp[hw->dev_num - 1]->is_probe_end) hw->isp[hw->dev_num - 1]->is_probe_end)
@@ -3850,41 +3901,11 @@ void rkisp_chk_tb_over(struct rkisp_device *isp_dev)
usleep_range(200, 210); usleep_range(200, 210);
} }
} }
for (i = 0; i < head->camera_num; i++)
switch (isp_dev->isp_ver) { rkisp_save_tb_info(hw->isp[i]);
case ISP_V32:
size = sizeof(struct rkisp32_thunderboot_resmem_head);
offset = size * isp_dev->dev_id;
break;
default:
break;
}
if (size && size < isp_dev->resmem_size) {
dma_sync_single_for_cpu(isp_dev->dev, isp_dev->resmem_addr + offset,
size, DMA_FROM_DEVICE);
params_vdev->is_first_cfg = true;
if (isp_dev->isp_ver == ISP_V32) {
struct rkisp32_thunderboot_resmem_head *tmp = resmem_va + offset;
param = &tmp->cfg;
head = &tmp->head;
v4l2_info(&isp_dev->v4l2_dev,
"tb param module en:0x%llx upd:0x%llx cfg upd:0x%llx\n",
tmp->cfg.module_en_update,
tmp->cfg.module_ens,
tmp->cfg.module_cfg_update);
}
if (param)
params_vdev->ops->save_first_param(params_vdev, param);
} else if (size > isp_dev->resmem_size) {
v4l2_err(&isp_dev->v4l2_dev,
"resmem size:%zu no enough for head:%d\n",
isp_dev->resmem_size, size);
head->complete = RKISP_TB_NG;
}
} }
memcpy(&isp_dev->tb_head, head, sizeof(*head)); end:
head = &isp_dev->tb_head;
v4l2_info(&isp_dev->v4l2_dev, v4l2_info(&isp_dev->v4l2_dev,
"thunderboot info: %d, %d, %d, %d, %d, %d | %d %d\n", "thunderboot info: %d, %d, %d, %d, %d, %d | %d %d\n",
head->enable, head->enable,