mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 19:08:57 +09:00
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:
@@ -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);
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user