From 3f1e1d3358318c5bfe076d314fba5fddd28b3e35 Mon Sep 17 00:00:00 2001 From: Ziyuan Xu Date: Tue, 2 Mar 2021 16:34:01 +0800 Subject: [PATCH] media: rockchip: isp: import dma API for memory synchronisation for thunderboot Change-Id: I29b4b4fb381ff6ba4cc7ef203c431ec0b1b6055b Signed-off-by: Ziyuan Xu --- drivers/media/platform/rockchip/isp/dev.c | 19 +++++--- drivers/media/platform/rockchip/isp/dev.h | 1 + drivers/media/platform/rockchip/isp/rkisp.c | 52 +++++++++++++++------ 3 files changed, 53 insertions(+), 19 deletions(-) diff --git a/drivers/media/platform/rockchip/isp/dev.c b/drivers/media/platform/rockchip/isp/dev.c index d297a4dc29f7..aeaea25c4f4d 100644 --- a/drivers/media/platform/rockchip/isp/dev.c +++ b/drivers/media/platform/rockchip/isp/dev.c @@ -664,22 +664,26 @@ static int rkisp_get_reserved_mem(struct rkisp_device *isp_dev) /* Get reserved memory region from Device-tree */ np = of_parse_phandle(dev->of_node, "memory-region-thunderboot", 0); if (!np) { - dev_err(dev, "No %s specified\n", "memory-region-thunderboot"); - return -1; + dev_info(dev, "No memory-region-thunderboot specified\n"); + return 0; } ret = of_address_to_resource(np, 0, &r); if (ret) { dev_err(dev, "No memory address assigned to the region\n"); - return -1; + return ret; } isp_dev->resmem_pa = r.start; isp_dev->resmem_size = resource_size(&r); + isp_dev->resmem_addr = dma_map_single(dev, phys_to_virt(r.start), + sizeof(struct rkisp_thunderboot_resmem_head), + DMA_BIDIRECTIONAL); + ret = dma_mapping_error(dev, isp_dev->resmem_addr); + dev_info(dev, "Allocated reserved memory, paddr: 0x%x\n", (u32)isp_dev->resmem_pa); - - return 0; + return ret; } static int rkisp_plat_probe(struct platform_device *pdev) @@ -717,7 +721,10 @@ static int rkisp_plat_probe(struct platform_device *pdev) sprintf(isp_dev->name, "%s%d", DRIVER_NAME, isp_dev->dev_id); - rkisp_get_reserved_mem(isp_dev); + ret = rkisp_get_reserved_mem(isp_dev); + if (ret) + return ret; + mutex_init(&isp_dev->apilock); mutex_init(&isp_dev->iqlock); atomic_set(&isp_dev->pipe.power_cnt, 0); diff --git a/drivers/media/platform/rockchip/isp/dev.h b/drivers/media/platform/rockchip/isp/dev.h index d42de2d25f06..755ae7d8c6e4 100644 --- a/drivers/media/platform/rockchip/isp/dev.h +++ b/drivers/media/platform/rockchip/isp/dev.h @@ -209,6 +209,7 @@ struct rkisp_device { struct mutex apilock; /* mutex to serialize the calls of stream */ struct mutex iqlock; /* mutex to serialize the calls of iq */ wait_queue_head_t sync_onoff; + dma_addr_t resmem_addr; phys_addr_t resmem_pa; size_t resmem_size; int dev_id; diff --git a/drivers/media/platform/rockchip/isp/rkisp.c b/drivers/media/platform/rockchip/isp/rkisp.c index fb9f52cd1eb8..2d8e4fdb6ed4 100644 --- a/drivers/media/platform/rockchip/isp/rkisp.c +++ b/drivers/media/platform/rockchip/isp/rkisp.c @@ -1897,10 +1897,17 @@ static long rkisp_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) } rkisp_chk_tb_over(isp_dev); + dma_sync_single_for_cpu(isp_dev->dev, isp_dev->resmem_addr, + sizeof(struct rkisp_thunderboot_resmem_head), + DMA_FROM_DEVICE); + resmem_va = phys_to_virt(isp_dev->resmem_pa); head = (struct rkisp_thunderboot_resmem_head *)resmem_va; if (head->complete != RKISP_TB_OK) { resmem->resmem_size = 0; + dma_unmap_single(isp_dev->dev, isp_dev->resmem_pa, + sizeof(struct rkisp_thunderboot_resmem_head), + DMA_FROM_DEVICE); free_reserved_area(phys_to_virt(isp_dev->resmem_pa), phys_to_virt(isp_dev->resmem_pa) + isp_dev->resmem_size, -1, "rkisp_thunderboot"); @@ -1910,10 +1917,14 @@ static long rkisp_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) } break; case RKISP_CMD_FREE_SHARED_BUF: - if (isp_dev->resmem_pa && isp_dev->resmem_size) + if (isp_dev->resmem_pa && isp_dev->resmem_size) { + dma_unmap_single(isp_dev->dev, isp_dev->resmem_pa, + sizeof(struct rkisp_thunderboot_resmem_head), + DMA_FROM_DEVICE); free_reserved_area(phys_to_virt(isp_dev->resmem_pa), phys_to_virt(isp_dev->resmem_pa) + isp_dev->resmem_size, -1, "rkisp_thunderboot"); + } isp_dev->resmem_pa = 0; isp_dev->resmem_size = 0; @@ -2118,13 +2129,34 @@ void rkisp_unregister_isp_subdev(struct rkisp_device *isp_dev) media_entity_cleanup(&sd->entity); } +#define shm_head_poll_timeout(isp_dev, cond, sleep_us, timeout_us) \ +({ \ + u64 __timeout_us = (timeout_us); \ + unsigned long __sleep_us = (sleep_us); \ + ktime_t __timeout = ktime_add_us(ktime_get(), __timeout_us); \ + might_sleep_if((__sleep_us) != 0); \ + for (;;) { \ + dma_sync_single_for_cpu(isp_dev->dev, isp_dev->resmem_addr, \ + sizeof(struct rkisp_thunderboot_resmem_head), \ + DMA_FROM_DEVICE); \ + if (cond) \ + break; \ + if (__timeout_us && \ + ktime_compare(ktime_get(), __timeout) > 0) { \ + break; \ + } \ + if (__sleep_us) \ + usleep_range((__sleep_us >> 2) + 1, __sleep_us); \ + } \ + (cond) ? 0 : -ETIMEDOUT; \ +}) + #ifdef CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP void rkisp_chk_tb_over(struct rkisp_device *isp_dev) { struct rkisp_thunderboot_resmem_head *head; enum rkisp_tb_state tb_state; void *resmem_va; - u32 i; if (!isp_dev->resmem_pa || !isp_dev->resmem_size) { v4l2_info(&isp_dev->v4l2_dev, @@ -2135,17 +2167,11 @@ void rkisp_chk_tb_over(struct rkisp_device *isp_dev) resmem_va = phys_to_virt(isp_dev->resmem_pa); head = (struct rkisp_thunderboot_resmem_head *)resmem_va; if (isp_dev->hw_dev->is_thunderboot) { - if ((!head->complete)) { - for (i = 0; i < 100; i++) { - usleep_range(5000, 6000); - if (head->complete) - break; - } - - if (!head->complete) - v4l2_info(&isp_dev->v4l2_dev, - "wait thunderboot over timeout\n"); - } + shm_head_poll_timeout(isp_dev, !!head->enable, 2000, 200 * USEC_PER_MSEC); + shm_head_poll_timeout(isp_dev, !!head->complete, 5000, 500 * USEC_PER_MSEC); + if (head->complete != RKISP_TB_OK) + v4l2_info(&isp_dev->v4l2_dev, + "wait thunderboot over timeout\n"); v4l2_info(&isp_dev->v4l2_dev, "thunderboot info: %d, %d, %d, %d, %d, %d, 0x%x\n",