diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2024-09-23 15:27:58 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2024-09-23 15:27:58 -0700 |
commit | abf2050f51fdca0fd146388f83cddd95a57a008d (patch) | |
tree | df5379313194c874ea574f9267a9b24a5bbb122e /drivers/media/platform | |
parent | 9ab27b018649c9504e894496cb4d7d8afcffd897 (diff) | |
parent | 81ee62e8d09ee3c7107d11c8bbfd64073ab601ad (diff) |
Merge tag 'media/v6.12-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media updates from Mauro Carvalho Chehab:
- New CEC driver: Extron DA HD 4K Plus
- Lots of driver fixes, cleanups and improvements
* tag 'media/v6.12-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (179 commits)
media: atomisp: Use clamp() in ia_css_eed1_8_vmem_encode()
media: atomisp: Fix eed1_8 code assigning signed values to an unsigned variable
media: atomisp: set lock before calling vb2_queue_init()
media: atomisp: Improve binary finding debug logging
media: atomisp: Drop dev_dbg() calls from hmm_[alloc|free]()
media: atomisp: csi2-bridge: Add DMI quirk for t4ka3 on Xiaomi Mipad2
media: atomisp: add missing wait_prepare/finish ops
media: atomisp: Remove unused declaration
media: atomisp: use clamp() in compute_coring()
media: atomisp: use clamp() in ia_css_eed1_8_encode()
media: atomisp: Simplify ia_css_pipe_create_cas_scaler_desc_single_output()
media: atomisp: Replace rarely used macro from math_support.h
media: atomisp: Remove duplicated leftover, i.e. sh_css_dvs_info.h
media: atomisp: bnr: fix trailing statement
media: atomisp: move trailing */ to separate lines
media: atomisp: move trailing statement to next line.
media: atomisp: Fix trailing statement in ia_css_de.host.c
media: atomisp: Fix spelling mistakes in atomisp.h
media: atomisp: Fix spelling mistakes in atomisp_platform.h
media: atomisp: Fix spelling mistake in csi_rx_public.h
...
Diffstat (limited to 'drivers/media/platform')
60 files changed, 1439 insertions, 370 deletions
diff --git a/drivers/media/platform/allegro-dvt/allegro-core.c b/drivers/media/platform/allegro-dvt/allegro-core.c index da61f9beb6b4..73606cee586e 100644 --- a/drivers/media/platform/allegro-dvt/allegro-core.c +++ b/drivers/media/platform/allegro-dvt/allegro-core.c @@ -179,7 +179,7 @@ struct allegro_dev { struct list_head channels; }; -static struct regmap_config allegro_regmap_config = { +static const struct regmap_config allegro_regmap_config = { .name = "regmap", .reg_bits = 32, .val_bits = 32, @@ -188,7 +188,7 @@ static struct regmap_config allegro_regmap_config = { .cache_type = REGCACHE_NONE, }; -static struct regmap_config allegro_sram_config = { +static const struct regmap_config allegro_sram_config = { .name = "sram", .reg_bits = 32, .val_bits = 32, @@ -1415,11 +1415,11 @@ static int allegro_mcu_send_encode_frame(struct allegro_dev *dev, static int allegro_mcu_wait_for_init_timeout(struct allegro_dev *dev, unsigned long timeout_ms) { - unsigned long tmo; + unsigned long time_left; - tmo = wait_for_completion_timeout(&dev->init_complete, - msecs_to_jiffies(timeout_ms)); - if (tmo == 0) + time_left = wait_for_completion_timeout(&dev->init_complete, + msecs_to_jiffies(timeout_ms)); + if (time_left == 0) return -ETIMEDOUT; reinit_completion(&dev->init_complete); @@ -2481,14 +2481,14 @@ static void allegro_mcu_interrupt(struct allegro_dev *dev) static void allegro_destroy_channel(struct allegro_channel *channel) { struct allegro_dev *dev = channel->dev; - unsigned long timeout; + unsigned long time_left; if (channel_exists(channel)) { reinit_completion(&channel->completion); allegro_mcu_send_destroy_channel(dev, channel); - timeout = wait_for_completion_timeout(&channel->completion, - msecs_to_jiffies(5000)); - if (timeout == 0) + time_left = wait_for_completion_timeout(&channel->completion, + msecs_to_jiffies(5000)); + if (time_left == 0) v4l2_warn(&dev->v4l2_dev, "channel %d: timeout while destroying\n", channel->mcu_channel_id); @@ -2544,7 +2544,7 @@ static void allegro_destroy_channel(struct allegro_channel *channel) static int allegro_create_channel(struct allegro_channel *channel) { struct allegro_dev *dev = channel->dev; - unsigned long timeout; + unsigned long time_left; if (channel_exists(channel)) { v4l2_warn(&dev->v4l2_dev, @@ -2595,9 +2595,9 @@ static int allegro_create_channel(struct allegro_channel *channel) reinit_completion(&channel->completion); allegro_mcu_send_create_channel(dev, channel); - timeout = wait_for_completion_timeout(&channel->completion, - msecs_to_jiffies(5000)); - if (timeout == 0) + time_left = wait_for_completion_timeout(&channel->completion, + msecs_to_jiffies(5000)); + if (time_left == 0) channel->error = -ETIMEDOUT; if (channel->error) goto err; diff --git a/drivers/media/platform/atmel/atmel-isi.c b/drivers/media/platform/atmel/atmel-isi.c index c1108df72dd5..5c823d3f9cc0 100644 --- a/drivers/media/platform/atmel/atmel-isi.c +++ b/drivers/media/platform/atmel/atmel-isi.c @@ -242,7 +242,7 @@ static irqreturn_t isi_interrupt(int irq, void *dev_id) #define WAIT_ISI_DISABLE 0 static int atmel_isi_wait_status(struct atmel_isi *isi, int wait_reset) { - unsigned long timeout; + unsigned long time_left; /* * The reset or disable will only succeed if we have a * pixel clock from the camera. @@ -257,9 +257,9 @@ static int atmel_isi_wait_status(struct atmel_isi *isi, int wait_reset) isi_writel(isi, ISI_CTRL, ISI_CTRL_DIS); } - timeout = wait_for_completion_timeout(&isi->complete, - msecs_to_jiffies(500)); - if (timeout == 0) + time_left = wait_for_completion_timeout(&isi->complete, + msecs_to_jiffies(500)); + if (time_left == 0) return -ETIMEDOUT; return 0; diff --git a/drivers/media/platform/chips-media/coda/coda-bit.c b/drivers/media/platform/chips-media/coda/coda-bit.c index ed47d5bd8d61..84ded154adfe 100644 --- a/drivers/media/platform/chips-media/coda/coda-bit.c +++ b/drivers/media/platform/chips-media/coda/coda-bit.c @@ -585,7 +585,7 @@ static int coda_alloc_context_buffers(struct coda_ctx *ctx, if (!ctx->slicebuf.vaddr && q_data->fourcc == V4L2_PIX_FMT_H264) { /* worst case slice size */ - size = (DIV_ROUND_UP(q_data->rect.width, 16) * + size = (unsigned long)(DIV_ROUND_UP(q_data->rect.width, 16) * DIV_ROUND_UP(q_data->rect.height, 16)) * 3200 / 8 + 512; ret = coda_alloc_context_buf(ctx, &ctx->slicebuf, size, "slicebuf"); diff --git a/drivers/media/platform/imagination/Kconfig b/drivers/media/platform/imagination/Kconfig index 7139ae22219b..a302c955483d 100644 --- a/drivers/media/platform/imagination/Kconfig +++ b/drivers/media/platform/imagination/Kconfig @@ -2,6 +2,7 @@ config VIDEO_E5010_JPEG_ENC tristate "Imagination E5010 JPEG Encoder Driver" depends on VIDEO_DEV + depends on ARCH_K3 || COMPILE_TEST select VIDEOBUF2_DMA_CONTIG select VIDEOBUF2_VMALLOC select V4L2_MEM2MEM_DEV diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateful.c b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateful.c index 11ca2c2fbaad..e62c1c18758b 100644 --- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateful.c +++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateful.c @@ -595,7 +595,7 @@ static void mtk_init_vdec_params(struct mtk_vcodec_dec_ctx *ctx) } } -static struct vb2_ops mtk_vdec_frame_vb2_ops = { +static const struct vb2_ops mtk_vdec_frame_vb2_ops = { .queue_setup = vb2ops_vdec_queue_setup, .buf_prepare = vb2ops_vdec_buf_prepare, .wait_prepare = vb2_ops_wait_prepare, diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c index b903e39fee89..3307dc15fc1d 100644 --- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c +++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c @@ -854,7 +854,7 @@ static int vb2ops_vdec_out_buf_validate(struct vb2_buffer *vb) return 0; } -static struct vb2_ops mtk_vdec_request_vb2_ops = { +static const struct vb2_ops mtk_vdec_request_vb2_ops = { .queue_setup = vb2ops_vdec_queue_setup, .wait_prepare = vb2_ops_wait_prepare, .wait_finish = vb2_ops_wait_finish, diff --git a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_req_if.c b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_req_if.c index 73d5cef33b2a..1e1b32faac77 100644 --- a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_req_if.c +++ b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_req_if.c @@ -347,11 +347,16 @@ static int vdec_h264_slice_decode(void *h_vdec, struct mtk_vcodec_mem *bs, return vpu_dec_reset(vpu); fb = inst->ctx->dev->vdec_pdata->get_cap_buffer(inst->ctx); + if (!fb) { + mtk_vdec_err(inst->ctx, "fb buffer is NULL"); + return -ENOMEM; + } + src_buf_info = container_of(bs, struct mtk_video_dec_buf, bs_buffer); dst_buf_info = container_of(fb, struct mtk_video_dec_buf, frame_buffer); - y_fb_dma = fb ? (u64)fb->base_y.dma_addr : 0; - c_fb_dma = fb ? (u64)fb->base_c.dma_addr : 0; + y_fb_dma = fb->base_y.dma_addr; + c_fb_dma = fb->base_c.dma_addr; mtk_vdec_debug(inst->ctx, "+ [%d] FB y_dma=%llx c_dma=%llx va=%p", inst->num_nalu, y_fb_dma, c_fb_dma, fb); diff --git a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_req_multi_if.c b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_req_multi_if.c index 2d4611e7fa0b..1ed0ccec5665 100644 --- a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_req_multi_if.c +++ b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_req_multi_if.c @@ -724,11 +724,16 @@ static int vdec_h264_slice_single_decode(void *h_vdec, struct mtk_vcodec_mem *bs return vpu_dec_reset(vpu); fb = inst->ctx->dev->vdec_pdata->get_cap_buffer(inst->ctx); + if (!fb) { + mtk_vdec_err(inst->ctx, "fb buffer is NULL"); + return -ENOMEM; + } + src_buf_info = container_of(bs, struct mtk_video_dec_buf, bs_buffer); dst_buf_info = container_of(fb, struct mtk_video_dec_buf, frame_buffer); - y_fb_dma = fb ? (u64)fb->base_y.dma_addr : 0; - c_fb_dma = fb ? (u64)fb->base_c.dma_addr : 0; + y_fb_dma = fb->base_y.dma_addr; + c_fb_dma = fb->base_c.dma_addr; mtk_vdec_debug(inst->ctx, "[h264-dec] [%d] y_dma=%llx c_dma=%llx", inst->ctx->decoded_frame_cnt, y_fb_dma, c_fb_dma); diff --git a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp8_req_if.c b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp8_req_if.c index e27e728f392e..232ef3bd246a 100644 --- a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp8_req_if.c +++ b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp8_req_if.c @@ -334,14 +334,18 @@ static int vdec_vp8_slice_decode(void *h_vdec, struct mtk_vcodec_mem *bs, src_buf_info = container_of(bs, struct mtk_video_dec_buf, bs_buffer); fb = inst->ctx->dev->vdec_pdata->get_cap_buffer(inst->ctx); - dst_buf_info = container_of(fb, struct mtk_video_dec_buf, frame_buffer); + if (!fb) { + mtk_vdec_err(inst->ctx, "fb buffer is NULL"); + return -ENOMEM; + } - y_fb_dma = fb ? (u64)fb->base_y.dma_addr : 0; + dst_buf_info = container_of(fb, struct mtk_video_dec_buf, frame_buffer); + y_fb_dma = fb->base_y.dma_addr; if (inst->ctx->q_data[MTK_Q_DATA_DST].fmt->num_planes == 1) c_fb_dma = y_fb_dma + inst->ctx->picinfo.buf_w * inst->ctx->picinfo.buf_h; else - c_fb_dma = fb ? (u64)fb->base_c.dma_addr : 0; + c_fb_dma = fb->base_c.dma_addr; inst->vsi->dec.bs_dma = (u64)bs->dma_addr; inst->vsi->dec.bs_sz = bs->size; diff --git a/drivers/media/platform/microchip/microchip-isc-base.c b/drivers/media/platform/microchip/microchip-isc-base.c index f3a5cbacadbe..28e56f6a695d 100644 --- a/drivers/media/platform/microchip/microchip-isc-base.c +++ b/drivers/media/platform/microchip/microchip-isc-base.c @@ -902,8 +902,11 @@ static int isc_set_fmt(struct isc_device *isc, struct v4l2_format *f) return 0; } -static int isc_validate(struct isc_device *isc) +static int isc_link_validate(struct media_link *link) { + struct video_device *vdev = + media_entity_to_video_device(link->sink->entity); + struct isc_device *isc = video_get_drvdata(vdev); int ret; int i; struct isc_format *sd_fmt = NULL; @@ -1906,20 +1909,6 @@ int microchip_isc_pipeline_init(struct isc_device *isc) } EXPORT_SYMBOL_GPL(microchip_isc_pipeline_init); -static int isc_link_validate(struct media_link *link) -{ - struct video_device *vdev = - media_entity_to_video_device(link->sink->entity); - struct isc_device *isc = video_get_drvdata(vdev); - int ret; - - ret = v4l2_subdev_link_validate(link); - if (ret) - return ret; - - return isc_validate(isc); -} - static const struct media_entity_operations isc_entity_operations = { .link_validate = isc_link_validate, }; diff --git a/drivers/media/platform/microchip/microchip-sama5d2-isc.c b/drivers/media/platform/microchip/microchip-sama5d2-isc.c index 5ac149cf3647..60b6d922d764 100644 --- a/drivers/media/platform/microchip/microchip-sama5d2-isc.c +++ b/drivers/media/platform/microchip/microchip-sama5d2-isc.c @@ -353,33 +353,29 @@ static const u32 isc_sama5d2_gamma_table[][GAMMA_ENTRIES] = { static int isc_parse_dt(struct device *dev, struct isc_device *isc) { struct device_node *np = dev->of_node; - struct device_node *epn = NULL; + struct device_node *epn; struct isc_subdev_entity *subdev_entity; unsigned int flags; - int ret; INIT_LIST_HEAD(&isc->subdev_entities); - while (1) { + for_each_endpoint_of_node(np, epn) { struct v4l2_fwnode_endpoint v4l2_epn = { .bus_type = 0 }; - - epn = of_graph_get_next_endpoint(np, epn); - if (!epn) - return 0; + int ret; ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(epn), &v4l2_epn); if (ret) { - ret = -EINVAL; + of_node_put(epn); dev_err(dev, "Could not parse the endpoint\n"); - break; + return -EINVAL; } subdev_entity = devm_kzalloc(dev, sizeof(*subdev_entity), GFP_KERNEL); if (!subdev_entity) { - ret = -ENOMEM; - break; + of_node_put(epn); + return -ENOMEM; } subdev_entity->epn = epn; @@ -400,9 +396,8 @@ static int isc_parse_dt(struct device *dev, struct isc_device *isc) list_add_tail(&subdev_entity->list, &isc->subdev_entities); } - of_node_put(epn); - return ret; + return 0; } static int microchip_isc_probe(struct platform_device *pdev) diff --git a/drivers/media/platform/microchip/microchip-sama7g5-isc.c b/drivers/media/platform/microchip/microchip-sama7g5-isc.c index 73445f33d26b..e97abe3e35af 100644 --- a/drivers/media/platform/microchip/microchip-sama7g5-isc.c +++ b/drivers/media/platform/microchip/microchip-sama7g5-isc.c @@ -336,36 +336,32 @@ static const u32 isc_sama7g5_gamma_table[][GAMMA_ENTRIES] = { static int xisc_parse_dt(struct device *dev, struct isc_device *isc) { struct device_node *np = dev->of_node; - struct device_node *epn = NULL; + struct device_node *epn; struct isc_subdev_entity *subdev_entity; unsigned int flags; - int ret; bool mipi_mode; INIT_LIST_HEAD(&isc->subdev_entities); mipi_mode = of_property_read_bool(np, "microchip,mipi-mode"); - while (1) { + for_each_endpoint_of_node(np, epn) { struct v4l2_fwnode_endpoint v4l2_epn = { .bus_type = 0 }; - - epn = of_graph_get_next_endpoint(np, epn); - if (!epn) - return 0; + int ret; ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(epn), &v4l2_epn); if (ret) { - ret = -EINVAL; + of_node_put(epn); dev_err(dev, "Could not parse the endpoint\n"); - break; + return -EINVAL; } subdev_entity = devm_kzalloc(dev, sizeof(*subdev_entity), GFP_KERNEL); if (!subdev_entity) { - ret = -ENOMEM; - break; + of_node_put(epn); + return -ENOMEM; } subdev_entity->epn = epn; @@ -389,9 +385,8 @@ static int xisc_parse_dt(struct device *dev, struct isc_device *isc) list_add_tail(&subdev_entity->list, &isc->subdev_entities); } - of_node_put(epn); - return ret; + return 0; } static int microchip_xisc_probe(struct platform_device *pdev) diff --git a/drivers/media/platform/nvidia/tegra-vde/h264.c b/drivers/media/platform/nvidia/tegra-vde/h264.c index d8812fc06c67..0e56a4331b0d 100644 --- a/drivers/media/platform/nvidia/tegra-vde/h264.c +++ b/drivers/media/platform/nvidia/tegra-vde/h264.c @@ -623,14 +623,14 @@ static int tegra_vde_decode_end(struct tegra_vde *vde) unsigned int read_bytes, macroblocks_nb; struct device *dev = vde->dev; dma_addr_t bsev_ptr; - long timeout; + long time_left; int ret; - timeout = wait_for_completion_interruptible_timeout( + time_left = wait_for_completion_interruptible_timeout( &vde->decode_completion, msecs_to_jiffies(1000)); - if (timeout < 0) { - ret = timeout; - } else if (timeout == 0) { + if (time_left < 0) { + ret = time_left; + } else if (time_left == 0) { bsev_ptr = tegra_vde_readl(vde, vde->bsev, 0x10); macroblocks_nb = tegra_vde_readl(vde, vde->sxe, 0xC8) & 0x1FFF; read_bytes = bsev_ptr ? bsev_ptr - vde->bitstream_data_addr : 0; diff --git a/drivers/media/platform/nxp/imx-mipi-csis.c b/drivers/media/platform/nxp/imx-mipi-csis.c index b9729a8883d6..44e1402e8be1 100644 --- a/drivers/media/platform/nxp/imx-mipi-csis.c +++ b/drivers/media/platform/nxp/imx-mipi-csis.c @@ -861,18 +861,21 @@ static void mipi_csis_log_counters(struct mipi_csis_device *csis, bool non_error { unsigned int num_events = non_errors ? MIPI_CSIS_NUM_EVENTS : MIPI_CSIS_NUM_EVENTS - 8; + unsigned int counters[MIPI_CSIS_NUM_EVENTS]; unsigned long flags; unsigned int i; spin_lock_irqsave(&csis->slock, flags); + for (i = 0; i < num_events; ++i) + counters[i] = csis->events[i].counter; + spin_unlock_irqrestore(&csis->slock, flags); for (i = 0; i < num_events; ++i) { - if (csis->events[i].counter > 0 || csis->debug.enable) + if (counters[i] > 0 || csis->debug.enable) dev_info(csis->dev, "%s events: %d\n", csis->events[i].name, - csis->events[i].counter); + counters[i]); } - spin_unlock_irqrestore(&csis->slock, flags); } static int mipi_csis_dump_regs(struct mipi_csis_device *csis) @@ -1344,7 +1347,7 @@ err_parse: * Suspend/resume */ -static int __maybe_unused mipi_csis_runtime_suspend(struct device *dev) +static int mipi_csis_runtime_suspend(struct device *dev) { struct v4l2_subdev *sd = dev_get_drvdata(dev); struct mipi_csis_device *csis = sd_to_mipi_csis_device(sd); @@ -1359,7 +1362,7 @@ static int __maybe_unused mipi_csis_runtime_suspend(struct device *dev) return 0; } -static int __maybe_unused mipi_csis_runtime_resume(struct device *dev) +static int mipi_csis_runtime_resume(struct device *dev) { struct v4l2_subdev *sd = dev_get_drvdata(dev); struct mipi_csis_device *csis = sd_to_mipi_csis_device(sd); @@ -1379,8 +1382,8 @@ static int __maybe_unused mipi_csis_runtime_resume(struct device *dev) } static const struct dev_pm_ops mipi_csis_pm_ops = { - SET_RUNTIME_PM_OPS(mipi_csis_runtime_suspend, mipi_csis_runtime_resume, - NULL) + RUNTIME_PM_OPS(mipi_csis_runtime_suspend, mipi_csis_runtime_resume, + NULL) }; /* ----------------------------------------------------------------------------- @@ -1571,7 +1574,7 @@ static struct platform_driver mipi_csis_driver = { .driver = { .of_match_table = mipi_csis_of_match, .name = CSIS_DRIVER_NAME, - .pm = &mipi_csis_pm_ops, + .pm = pm_ptr(&mipi_csis_pm_ops), }, }; diff --git a/drivers/media/platform/nxp/imx-pxp.h b/drivers/media/platform/nxp/imx-pxp.h index 44f95c749d2e..476f2042fa6f 100644 --- a/drivers/media/platform/nxp/imx-pxp.h +++ b/drivers/media/platform/nxp/imx-pxp.h @@ -594,12 +594,17 @@ (((v) << 18) & BM_PXP_CSC1_COEF0_C0) #define BP_PXP_CSC1_COEF0_UV_OFFSET 9 #define BM_PXP_CSC1_COEF0_UV_OFFSET 0x0003FE00 + +/* + * We use v * (1 << 9) instead of v << 9, to workaround a gcc5 bug. + * The compiler cannot understand that the expression is constant. + */ #define BF_PXP_CSC1_COEF0_UV_OFFSET(v) \ - (((v) << 9) & BM_PXP_CSC1_COEF0_UV_OFFSET) + (((v) * (1 << 9)) & BM_PXP_CSC1_COEF0_UV_OFFSET) #define BP_PXP_CSC1_COEF0_Y_OFFSET 0 #define BM_PXP_CSC1_COEF0_Y_OFFSET 0x000001FF #define BF_PXP_CSC1_COEF0_Y_OFFSET(v) \ - (((v) << 0) & BM_PXP_CSC1_COEF0_Y_OFFSET) + ((v) & BM_PXP_CSC1_COEF0_Y_OFFSET) #define HW_PXP_CSC1_COEF1 (0x000001b0) diff --git a/drivers/media/platform/nxp/imx8mq-mipi-csi2.c b/drivers/media/platform/nxp/imx8mq-mipi-csi2.c index ba2e81f24965..d4a6c5532969 100644 --- a/drivers/media/platform/nxp/imx8mq-mipi-csi2.c +++ b/drivers/media/platform/nxp/imx8mq-mipi-csi2.c @@ -693,7 +693,7 @@ unlock: return ret ? -EAGAIN : 0; } -static int __maybe_unused imx8mq_mipi_csi_suspend(struct device *dev) +static int imx8mq_mipi_csi_suspend(struct device *dev) { struct v4l2_subdev *sd = dev_get_drvdata(dev); struct csi_state *state = mipi_sd_to_csi2_state(sd); @@ -705,7 +705,7 @@ static int __maybe_unused imx8mq_mipi_csi_suspend(struct device *dev) return 0; } -static int __maybe_unused imx8mq_mipi_csi_resume(struct device *dev) +static int imx8mq_mipi_csi_resume(struct device *dev) { struct v4l2_subdev *sd = dev_get_drvdata(dev); struct csi_state *state = mipi_sd_to_csi2_state(sd); @@ -716,7 +716,7 @@ static int __maybe_unused imx8mq_mipi_csi_resume(struct device *dev) return imx8mq_mipi_csi_pm_resume(dev); } -static int __maybe_unused imx8mq_mipi_csi_runtime_suspend(struct device *dev) +static int imx8mq_mipi_csi_runtime_suspend(struct device *dev) { struct v4l2_subdev *sd = dev_get_drvdata(dev); struct csi_state *state = mipi_sd_to_csi2_state(sd); @@ -731,7 +731,7 @@ static int __maybe_unused imx8mq_mipi_csi_runtime_suspend(struct device *dev) return ret; } -static int __maybe_unused imx8mq_mipi_csi_runtime_resume(struct device *dev) +static int imx8mq_mipi_csi_runtime_resume(struct device *dev) { struct v4l2_subdev *sd = dev_get_drvdata(dev); struct csi_state *state = mipi_sd_to_csi2_state(sd); @@ -747,10 +747,9 @@ static int __maybe_unused imx8mq_mipi_csi_runtime_resume(struct device *dev) } static const struct dev_pm_ops imx8mq_mipi_csi_pm_ops = { - SET_RUNTIME_PM_OPS(imx8mq_mipi_csi_runtime_suspend, - imx8mq_mipi_csi_runtime_resume, - NULL) - SET_SYSTEM_SLEEP_PM_OPS(imx8mq_mipi_csi_suspend, imx8mq_mipi_csi_resume) + RUNTIME_PM_OPS(imx8mq_mipi_csi_runtime_suspend, + imx8mq_mipi_csi_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(imx8mq_mipi_csi_suspend, imx8mq_mipi_csi_resume) }; /* ----------------------------------------------------------------------------- @@ -958,7 +957,7 @@ static struct platform_driver imx8mq_mipi_csi_driver = { .driver = { .of_match_table = imx8mq_mipi_csi_of_match, .name = MIPI_CSI2_DRIVER_NAME, - .pm = &imx8mq_mipi_csi_pm_ops, + .pm = pm_ptr(&imx8mq_mipi_csi_pm_ops), }, }; diff --git a/drivers/media/platform/qcom/camss/camss-video.c b/drivers/media/platform/qcom/camss/camss-video.c index cd72feca618c..3b8fc31d957c 100644 --- a/drivers/media/platform/qcom/camss/camss-video.c +++ b/drivers/media/platform/qcom/camss/camss-video.c @@ -297,12 +297,6 @@ static void video_stop_streaming(struct vb2_queue *q) ret = v4l2_subdev_call(subdev, video, s_stream, 0); - if (entity->use_count > 1) { - /* Don't stop if other instances of the pipeline are still running */ - dev_dbg(video->camss->dev, "Video pipeline still used, don't stop streaming.\n"); - return; - } - if (ret) { dev_err(video->camss->dev, "Video pipeline stop failed: %d\n", ret); return; diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index 51b1d3550421..d64985ca6e88 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -2283,6 +2283,8 @@ static int camss_probe(struct platform_device *pdev) v4l2_async_nf_init(&camss->notifier, &camss->v4l2_dev); + pm_runtime_enable(dev); + num_subdevs = camss_of_parse_ports(camss); if (num_subdevs < 0) { ret = num_subdevs; @@ -2323,8 +2325,6 @@ static int camss_probe(struct platform_device *pdev) } } - pm_runtime_enable(dev); - return 0; err_register_subdevs: @@ -2332,6 +2332,7 @@ err_register_subdevs: err_v4l2_device_unregister: v4l2_device_unregister(&camss->v4l2_dev); v4l2_async_nf_cleanup(&camss->notifier); + pm_runtime_disable(dev); err_genpd_cleanup: camss_genpd_cleanup(camss); diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c index 165c947a6703..84e95a46dfc9 100644 --- a/drivers/media/platform/qcom/venus/core.c +++ b/drivers/media/platform/qcom/venus/core.c @@ -430,6 +430,7 @@ static void venus_remove(struct platform_device *pdev) struct device *dev = core->dev; int ret; + cancel_delayed_work_sync(&core->work); ret = pm_runtime_get_sync(dev); WARN_ON(ret < 0); diff --git a/drivers/media/platform/qcom/venus/firmware.c b/drivers/media/platform/qcom/venus/firmware.c index fe7da2b30482..66a18830e66d 100644 --- a/drivers/media/platform/qcom/venus/firmware.c +++ b/drivers/media/platform/qcom/venus/firmware.c @@ -316,10 +316,10 @@ int venus_firmware_init(struct venus_core *core) core->fw.dev = &pdev->dev; - iommu_dom = iommu_domain_alloc(&platform_bus_type); - if (!iommu_dom) { + iommu_dom = iommu_paging_domain_alloc(core->fw.dev); + if (IS_ERR(iommu_dom)) { dev_err(core->fw.dev, "Failed to allocate iommu domain\n"); - ret = -ENOMEM; + ret = PTR_ERR(iommu_dom); goto err_unregister; } diff --git a/drivers/media/platform/qcom/venus/hfi_cmds.c b/drivers/media/platform/qcom/venus/hfi_cmds.c index 3418d2dd9371..3ae063094e3e 100644 --- a/drivers/media/platform/qcom/venus/hfi_cmds.c +++ b/drivers/media/platform/qcom/venus/hfi_cmds.c @@ -156,7 +156,7 @@ void pkt_sys_image_version(struct hfi_sys_get_property_pkt *pkt) pkt->hdr.size = sizeof(*pkt); pkt->hdr.pkt_type = HFI_CMD_SYS_GET_PROPERTY; pkt->num_properties = 1; - pkt->data[0] = HFI_PROPERTY_SYS_IMAGE_VERSION; + pkt->data = HFI_PROPERTY_SYS_IMAGE_VERSION; } int pkt_session_init(struct hfi_session_init_pkt *pkt, void *cookie, @@ -331,7 +331,7 @@ int pkt_session_ftb(struct hfi_session_fill_buffer_pkt *pkt, void *cookie, pkt->alloc_len = out_frame->alloc_len; pkt->filled_len = out_frame->filled_len; pkt->offset = out_frame->offset; - pkt->data[0] = out_frame->extradata_size; + pkt->data = out_frame->extradata_size; return 0; } @@ -402,7 +402,7 @@ static int pkt_session_get_property_1x(struct hfi_session_get_property_pkt *pkt, pkt->shdr.hdr.pkt_type = HFI_CMD_SESSION_GET_PROPERTY; pkt->shdr.session_id = hash32_ptr(cookie); pkt->num_properties = 1; - pkt->data[0] = ptype; + pkt->data = ptype; return 0; } @@ -1110,7 +1110,7 @@ pkt_session_get_property_3xx(struct hfi_session_get_property_pkt *pkt, switch (ptype) { case HFI_PROPERTY_CONFIG_VDEC_ENTROPY: - pkt->data[0] = HFI_PROPERTY_CONFIG_VDEC_ENTROPY; + pkt->data = HFI_PROPERTY_CONFIG_VDEC_ENTROPY; break; default: ret = pkt_session_get_property_1x(pkt, cookie, ptype); diff --git a/drivers/media/platform/qcom/venus/hfi_cmds.h b/drivers/media/platform/qcom/venus/hfi_cmds.h index 1adf2d2ae5f2..a83125bc17aa 100644 --- a/drivers/media/platform/qcom/venus/hfi_cmds.h +++ b/drivers/media/platform/qcom/venus/hfi_cmds.h @@ -74,7 +74,7 @@ struct hfi_sys_set_property_pkt { struct hfi_sys_get_property_pkt { struct hfi_pkt_hdr hdr; u32 num_properties; - u32 data[1]; + u32 data; }; struct hfi_sys_set_buffers_pkt { @@ -82,7 +82,7 @@ struct hfi_sys_set_buffers_pkt { u32 buffer_type; u32 buffer_size; u32 num_buffers; - u32 buffer_addr[1]; + u32 buffer_addr[]; }; struct hfi_sys_ping_pkt { @@ -151,7 +151,7 @@ struct hfi_session_empty_buffer_compressed_pkt { u32 input_tag; u32 packet_buffer; u32 extradata_buffer; - u32 data[1]; + u32 data; }; struct hfi_session_empty_buffer_uncompressed_plane0_pkt { @@ -168,7 +168,7 @@ struct hfi_session_empty_buffer_uncompressed_plane0_pkt { u32 input_tag; u32 packet_buffer; u32 extradata_buffer; - u32 data[1]; + u32 data; }; struct hfi_session_empty_buffer_uncompressed_plane1_pkt { @@ -177,7 +177,7 @@ struct hfi_session_empty_buffer_uncompressed_plane1_pkt { u32 filled_len; u32 offset; u32 packet_buffer2; - u32 data[1]; + u32 data; }; struct hfi_session_empty_buffer_uncompressed_plane2_pkt { @@ -186,7 +186,7 @@ struct hfi_session_empty_buffer_uncompressed_plane2_pkt { u32 filled_len; u32 offset; u32 packet_buffer3; - u32 data[1]; + u32 data; }; struct hfi_session_fill_buffer_pkt { @@ -198,7 +198,7 @@ struct hfi_session_fill_buffer_pkt { u32 output_tag; u32 packet_buffer; u32 extradata_buffer; - u32 data[1]; + u32 data; }; struct hfi_session_flush_pkt { @@ -217,7 +217,7 @@ struct hfi_session_resume_pkt { struct hfi_session_get_property_pkt { struct hfi_session_hdr_pkt shdr; u32 num_properties; - u32 data[1]; + u32 data; }; struct hfi_session_release_buffer_pkt { diff --git a/drivers/media/platform/qcom/venus/hfi_helper.h b/drivers/media/platform/qcom/venus/hfi_helper.h index e4c05d62cfc7..f44059f19505 100644 --- a/drivers/media/platform/qcom/venus/hfi_helper.h +++ b/drivers/media/platform/qcom/venus/hfi_helper.h @@ -761,7 +761,7 @@ struct hfi_multi_stream_3x { struct hfi_multi_view_format { u32 views; - u32 view_order[1]; + u32 view_order[]; }; #define HFI_MULTI_SLICE_OFF 0x1 @@ -1005,13 +1005,13 @@ struct hfi_uncompressed_plane_constraints { struct hfi_uncompressed_plane_info { u32 format; u32 num_planes; - struct hfi_uncompressed_plane_constraints plane_constraints[1]; + struct hfi_uncompressed_plane_constraints plane_constraints; }; struct hfi_uncompressed_format_supported { u32 buffer_type; u32 format_entries; - struct hfi_uncompressed_plane_info plane_info[1]; + struct hfi_uncompressed_plane_info plane_info; }; struct hfi_uncompressed_plane_actual { @@ -1038,7 +1038,7 @@ struct hfi_codec_supported { struct hfi_properties_supported { u32 num_properties; - u32 properties[1]; + u32 properties[]; }; struct hfi_max_sessions_supported { @@ -1085,12 +1085,12 @@ struct hfi_resource_ocmem_requirement { struct hfi_resource_ocmem_requirement_info { u32 num_entries; - struct hfi_resource_ocmem_requirement requirements[1]; + struct hfi_resource_ocmem_requirement requirements[]; }; struct hfi_property_sys_image_version_info_type { u32 string_size; - u8 str_image_version[1]; + u8 str_image_version[]; }; struct hfi_codec_mask_supported { @@ -1141,7 +1141,7 @@ struct hfi_extradata_header { u32 port_index; u32 type; u32 data_size; - u8 data[1]; + u8 data[]; }; struct hfi_batch_info { @@ -1236,7 +1236,7 @@ static inline void hfi_bufreq_set_count_min_host(struct hfi_buffer_requirements struct hfi_data_payload { u32 size; - u8 data[1]; + u8 data[]; }; struct hfi_enable_picture { @@ -1264,12 +1264,12 @@ struct hfi_interlace_format_supported { struct hfi_buffer_alloc_mode_supported { u32 buffer_type; u32 num_entries; - u32 data[1]; + u32 data[]; }; struct hfi_mb_error_map { u32 error_map_size; - u8 error_map[1]; + u8 error_map[]; }; struct hfi_metadata_pass_through { diff --git a/drivers/media/platform/qcom/venus/hfi_parser.c b/drivers/media/platform/qcom/venus/hfi_parser.c index c43839539d4d..3df241dc3a11 100644 --- a/drivers/media/platform/qcom/venus/hfi_parser.c +++ b/drivers/media/platform/qcom/venus/hfi_parser.c @@ -157,7 +157,7 @@ static void parse_raw_formats(struct venus_core *core, u32 codecs, u32 domain, void *data) { struct hfi_uncompressed_format_supported *fmt = data; - struct hfi_uncompressed_plane_info *pinfo = fmt->plane_info; + struct hfi_uncompressed_plane_info *pinfo = &fmt->plane_info; struct hfi_uncompressed_plane_constraints *constr; struct raw_formats rawfmts[MAX_FMT_ENTRIES] = {}; u32 entries = fmt->format_entries; diff --git a/drivers/media/platform/qcom/venus/hfi_plat_bufs_v6.c b/drivers/media/platform/qcom/venus/hfi_plat_bufs_v6.c index f5a655973c08..6289166786ec 100644 --- a/drivers/media/platform/qcom/venus/hfi_plat_bufs_v6.c +++ b/drivers/media/platform/qcom/venus/hfi_plat_bufs_v6.c @@ -1063,51 +1063,51 @@ struct enc_bufsize_ops { u32 (*persist)(void); }; -static struct dec_bufsize_ops dec_h264_ops = { +static const struct dec_bufsize_ops dec_h264_ops = { .scratch = h264d_scratch_size, .scratch1 = h264d_scratch1_size, .persist1 = h264d_persist1_size, }; -static struct dec_bufsize_ops dec_h265_ops = { +static const struct dec_bufsize_ops dec_h265_ops = { .scratch = h265d_scratch_size, .scratch1 = h265d_scratch1_size, .persist1 = h265d_persist1_size, }; -static struct dec_bufsize_ops dec_vp8_ops = { +static const struct dec_bufsize_ops dec_vp8_ops = { .scratch = vpxd_scratch_size, .scratch1 = vp8d_scratch1_size, .persist1 = vp8d_persist1_size, }; -static struct dec_bufsize_ops dec_vp9_ops = { +static const struct dec_bufsize_ops dec_vp9_ops = { .scratch = vpxd_scratch_size, .scratch1 = vp9d_scratch1_size, .persist1 = vp9d_persist1_size, }; -static struct dec_bufsize_ops dec_mpeg2_ops = { +static const struct dec_bufsize_ops dec_mpeg2_ops = { .scratch = mpeg2d_scratch_size, .scratch1 = mpeg2d_scratch1_size, .persist1 = mpeg2d_persist1_size, }; -static struct enc_bufsize_ops enc_h264_ops = { +static const struct enc_bufsize_ops enc_h264_ops = { .scratch = h264e_scratch_size, .scratch1 = h264e_scratch1_size, .scratch2 = enc_scratch2_size, .persist = enc_persist_size, }; -static struct enc_bufsize_ops enc_h265_ops = { +static const struct enc_bufsize_ops enc_h265_ops = { .scratch = h265e_scratch_size, .scratch1 = h265e_scratch1_size, .scratch2 = enc_scratch2_size, .persist = enc_persist_size, }; -static struct enc_bufsize_ops enc_vp8_ops = { +static const struct enc_bufsize_ops enc_vp8_ops = { .scratch = vp8e_scratch_size, .scratch1 = vp8e_scratch1_size, .scratch2 = enc_scratch2_size, @@ -1186,7 +1186,7 @@ static int bufreq_dec(struct hfi_plat_buffers_params *params, u32 buftype, u32 codec = params->codec; u32 width = params->width, height = params->height, out_min_count; u32 out_width = params->out_width, out_height = params->out_height; - struct dec_bufsize_ops *dec_ops; + const struct dec_bufsize_ops *dec_ops; bool is_secondary_output = params->dec.is_secondary_output; bool is_interlaced = params->dec.is_interlaced; u32 max_mbs_per_frame = params->dec.max_mbs_per_frame; @@ -1260,7 +1260,7 @@ static int bufreq_enc(struct hfi_plat_buffers_params *params, u32 buftype, struct hfi_buffer_requirements *bufreq) { enum hfi_version version = params->version; - struct enc_bufsize_ops *enc_ops; + const struct enc_bufsize_ops *enc_ops; u32 width = params->width; u32 height = params->height; bool is_tenbit = params->enc.is_tenbit; diff --git a/drivers/media/platform/raspberrypi/pisp_be/Kconfig b/drivers/media/platform/raspberrypi/pisp_be/Kconfig index 38c0f8305d62..46765a2e4c4d 100644 --- a/drivers/media/platform/raspberrypi/pisp_be/Kconfig +++ b/drivers/media/platform/raspberrypi/pisp_be/Kconfig @@ -2,6 +2,7 @@ config VIDEO_RASPBERRYPI_PISP_BE tristate "Raspberry Pi PiSP Backend (BE) ISP driver" depends on V4L_PLATFORM_DRIVERS depends on VIDEO_DEV + depends on ARCH_BCM2835 || COMPILE_TEST select VIDEO_V4L2_SUBDEV_API select MEDIA_CONTROLLER select VIDEOBUF2_DMA_CONTIG diff --git a/drivers/media/platform/renesas/rcar-vin/rcar-core.c b/drivers/media/platform/renesas/rcar-vin/rcar-core.c index 809c3a38cc4a..695d884a22d1 100644 --- a/drivers/media/platform/renesas/rcar-vin/rcar-core.c +++ b/drivers/media/platform/renesas/rcar-vin/rcar-core.c @@ -1274,16 +1274,7 @@ static const struct rvin_info rcar_info_r8a77995 = { .scaler = rvin_scaler_gen3, }; -static const struct rvin_info rcar_info_r8a779a0 = { - .model = RCAR_GEN3, - .use_mc = true, - .use_isp = true, - .nv12 = true, - .max_width = 4096, - .max_height = 4096, -}; - -static const struct rvin_info rcar_info_r8a779g0 = { +static const struct rvin_info rcar_info_gen4 = { .model = RCAR_GEN3, .use_mc = true, .use_isp = true, @@ -1354,12 +1345,18 @@ static const struct of_device_id rvin_of_id_table[] = { .data = &rcar_info_r8a77995, }, { + /* Keep to be compatible with old DTS files. */ .compatible = "renesas,vin-r8a779a0", - .data = &rcar_info_r8a779a0, + .data = &rcar_info_gen4, }, { + /* Keep to be compatible with old DTS files. */ .compatible = "renesas,vin-r8a779g0", - .data = &rcar_info_r8a779g0, + .data = &rcar_info_gen4, + }, + { + .compatible = "renesas,rcar-gen4-vin", + .data = &rcar_info_gen4, }, { /* Sentinel */ }, }; diff --git a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c index e68fcdaea207..c7fdee347ac8 100644 --- a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c +++ b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c @@ -865,6 +865,7 @@ static const struct of_device_id rzg2l_csi2_of_table[] = { { .compatible = "renesas,rzg2l-csi2", }, { /* sentinel */ } }; +MODULE_DEVICE_TABLE(of, rzg2l_csi2_of_table); static struct platform_driver rzg2l_csi2_pdrv = { .remove_new = rzg2l_csi2_remove, diff --git a/drivers/media/platform/renesas/vsp1/vsp1_video.c b/drivers/media/platform/renesas/vsp1/vsp1_video.c index fdb46ec0c872..e728f9f5160e 100644 --- a/drivers/media/platform/renesas/vsp1/vsp1_video.c +++ b/drivers/media/platform/renesas/vsp1/vsp1_video.c @@ -1082,6 +1082,27 @@ static const struct v4l2_file_operations vsp1_video_fops = { }; /* ----------------------------------------------------------------------------- + * Media entity operations + */ + +static int vsp1_video_link_validate(struct media_link *link) +{ + /* + * Ideally, link validation should be implemented here instead of + * calling vsp1_video_verify_format() in vsp1_video_streamon() + * manually. That would however break userspace that start one video + * device before configures formats on other video devices in the + * pipeline. This operation is just a no-op to silence the warnings + * from v4l2_subdev_link_validate(). + */ + return 0; +} + +static const struct media_entity_operations vsp1_video_media_ops = { + .link_validate = vsp1_video_link_validate, +}; + +/* ----------------------------------------------------------------------------- * Suspend and Resume */ @@ -1215,6 +1236,7 @@ struct vsp1_video *vsp1_video_create(struct vsp1_device *vsp1, /* ... and the video node... */ video->video.v4l2_dev = &video->vsp1->v4l2_dev; + video->video.entity.ops = &vsp1_video_media_ops; video->video.fops = &vsp1_video_fops; snprintf(video->video.name, sizeof(video->video.name), "%s %s", rwpf->entity.subdev.name, direction); diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.c index f956b90a407a..60c97bb7b18b 100644 --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.c +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.c @@ -178,3 +178,17 @@ void rkisp1_sd_adjust_crop(struct v4l2_rect *crop, rkisp1_sd_adjust_crop_rect(crop, &crop_bounds); } + +void rkisp1_bls_swap_regs(enum rkisp1_fmt_raw_pat_type pattern, + const u32 input[4], u32 output[4]) +{ + static const unsigned int swap[4][4] = { + [RKISP1_RAW_RGGB] = { 0, 1, 2, 3 }, + [RKISP1_RAW_GRBG] = { 1, 0, 3, 2 }, + [RKISP1_RAW_GBRG] = { 2, 3, 0, 1 }, + [RKISP1_RAW_BGGR] = { 3, 2, 1, 0 }, + }; + + for (unsigned int i = 0; i < 4; ++i) + output[i] = input[swap[pattern][i]]; +} diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h index 26573f6ae575..ca952fd0829b 100644 --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h @@ -33,9 +33,10 @@ struct regmap; #define RKISP1_ISP_SD_SRC BIT(0) #define RKISP1_ISP_SD_SINK BIT(1) -/* min and max values for the widths and heights of the entities */ -#define RKISP1_ISP_MAX_WIDTH 4032 -#define RKISP1_ISP_MAX_HEIGHT 3024 +/* + * Minimum values for the width and height of entities. The maximum values are + * model-specific and stored in the rkisp1_info structure. + */ #define RKISP1_ISP_MIN_WIDTH 32 #define RKISP1_ISP_MIN_HEIGHT 32 @@ -115,6 +116,8 @@ enum rkisp1_isp_pad { * @RKISP1_FEATURE_SELF_PATH: The ISP has a self path * @RKISP1_FEATURE_DUAL_CROP: The ISP has the dual crop block at the resizer input * @RKISP1_FEATURE_DMA_34BIT: The ISP uses 34-bit DMA addresses + * @RKISP1_FEATURE_BLS: The ISP has a dedicated BLS block + * @RKISP1_FEATURE_COMPAND: The ISP has a companding block * * The ISP features are stored in a bitmask in &rkisp1_info.features and allow * the driver to implement support for features present in some ISP versions @@ -126,6 +129,8 @@ enum rkisp1_feature { RKISP1_FEATURE_SELF_PATH = BIT(2), RKISP1_FEATURE_DUAL_CROP = BIT(3), RKISP1_FEATURE_DMA_34BIT = BIT(4), + RKISP1_FEATURE_BLS = BIT(5), + RKISP1_FEATURE_COMPAND = BIT(6), }; #define rkisp1_has_feature(rkisp1, feature) \ @@ -140,6 +145,8 @@ enum rkisp1_feature { * @isr_size: number of entries in the @isrs array * @isp_ver: ISP version * @features: bitmask of rkisp1_feature features implemented by the ISP + * @max_width: maximum input frame width + * @max_height: maximum input frame height * * This structure contains information about the ISP specific to a particular * ISP model, version, or integration in a particular SoC. @@ -151,6 +158,8 @@ struct rkisp1_info { unsigned int isr_size; enum rkisp1_cif_isp_version isp_ver; unsigned int features; + unsigned int max_width; + unsigned int max_height; }; /* @@ -232,7 +241,7 @@ struct rkisp1_vdev_node { /* * struct rkisp1_buffer - A container for the vb2 buffers used by the video devices: - * params, stats, mainpath, selfpath + * stats, mainpath, selfpath * * @vb: vb2 buffer * @queue: entry of the buffer in the queue @@ -245,6 +254,26 @@ struct rkisp1_buffer { }; /* + * struct rkisp1_params_buffer - A container for the vb2 buffers used by the + * params video device + * + * @vb: vb2 buffer + * @queue: entry of the buffer in the queue + * @cfg: scratch buffer used for caching the ISP configuration parameters + */ +struct rkisp1_params_buffer { + struct vb2_v4l2_buffer vb; + struct list_head queue; + void *cfg; +}; + +static inline struct rkisp1_params_buffer * +to_rkisp1_params_buffer(struct vb2_v4l2_buffer *vbuf) +{ + return container_of(vbuf, struct rkisp1_params_buffer, vb); +} + +/* * struct rkisp1_dummy_buffer - A buffer to write the next frame to in case * there are no vb2 buffers available. * @@ -372,9 +401,11 @@ struct rkisp1_params_ops { * @ops: pointer to the variant-specific operations * @config_lock: locks the buffer list 'params' * @params: queue of rkisp1_buffer - * @vdev_fmt: v4l2_format of the metadata format + * @metafmt the currently enabled metadata format * @quantization: the quantization configured on the isp's src pad + * @ycbcr_encoding the YCbCr encoding * @raw_type: the bayer pattern on the isp video sink pad + * @enabled_blocks: bitmask of enabled ISP blocks */ struct rkisp1_params { struct rkisp1_vdev_node vnode; @@ -383,11 +414,14 @@ struct rkisp1_params { spinlock_t config_lock; /* locks the buffers list 'params' */ struct list_head params; - struct v4l2_format vdev_fmt; + + const struct v4l2_meta_format *metafmt; enum v4l2_quantization quantization; enum v4l2_ycbcr_encoding ycbcr_encoding; enum rkisp1_fmt_raw_pat_type raw_type; + + u32 enabled_blocks; }; /* @@ -573,6 +607,9 @@ void rkisp1_sd_adjust_crop_rect(struct v4l2_rect *crop, void rkisp1_sd_adjust_crop(struct v4l2_rect *crop, const struct v4l2_mbus_framefmt *bounds); +void rkisp1_bls_swap_regs(enum rkisp1_fmt_raw_pat_type pattern, + const u32 input[4], u32 output[4]); + /* * rkisp1_mbus_info_get_by_code - get the isp info of the media bus code * diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-csi.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-csi.c index 4202642e0523..841e58c20f7f 100644 --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-csi.c +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-csi.c @@ -307,6 +307,7 @@ static int rkisp1_csi_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_state *sd_state, struct v4l2_subdev_format *fmt) { + struct rkisp1_csi *csi = to_rkisp1_csi(sd); const struct rkisp1_mbus_info *mbus_info; struct v4l2_mbus_framefmt *sink_fmt, *src_fmt; @@ -326,10 +327,10 @@ static int rkisp1_csi_set_fmt(struct v4l2_subdev *sd, sink_fmt->width = clamp_t(u32, fmt->format.width, RKISP1_ISP_MIN_WIDTH, - RKISP1_ISP_MAX_WIDTH); + csi->rkisp1->info->max_width); sink_fmt->height = clamp_t(u32, fmt->format.height, RKISP1_ISP_MIN_HEIGHT, - RKISP1_ISP_MAX_HEIGHT); + csi->rkisp1->info->max_height); fmt->format = *sink_fmt; diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c index bb0202386c70..dd114ab77800 100644 --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c @@ -509,7 +509,10 @@ static const struct rkisp1_info px30_isp_info = { .isp_ver = RKISP1_V12, .features = RKISP1_FEATURE_MIPI_CSI2 | RKISP1_FEATURE_SELF_PATH - | RKISP1_FEATURE_DUAL_CROP, + | RKISP1_FEATURE_DUAL_CROP + | RKISP1_FEATURE_BLS, + .max_width = 3264, + .max_height = 2448, }; static const char * const rk3399_isp_clks[] = { @@ -530,7 +533,10 @@ static const struct rkisp1_info rk3399_isp_info = { .isp_ver = RKISP1_V10, .features = RKISP1_FEATURE_MIPI_CSI2 | RKISP1_FEATURE_SELF_PATH - | RKISP1_FEATURE_DUAL_CROP, + | RKISP1_FEATURE_DUAL_CROP + | RKISP1_FEATURE_BLS, + .max_width = 4416, + .max_height = 3312, }; static const char * const imx8mp_isp_clks[] = { @@ -550,7 +556,10 @@ static const struct rkisp1_info imx8mp_isp_info = { .isr_size = ARRAY_SIZE(imx8mp_isp_isrs), .isp_ver = RKISP1_V_IMX8MP, .features = RKISP1_FEATURE_MAIN_STRIDE - | RKISP1_FEATURE_DMA_34BIT, + | RKISP1_FEATURE_DMA_34BIT + | RKISP1_FEATURE_COMPAND, + .max_width = 4096, + .max_height = 3072, }; static const struct of_device_id rkisp1_of_match[] = { diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c index 91301d17d356..d94917211828 100644 --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c @@ -517,6 +517,7 @@ static int rkisp1_isp_enum_frame_size(struct v4l2_subdev *sd, struct v4l2_subdev_state *sd_state, struct v4l2_subdev_frame_size_enum *fse) { + struct rkisp1_isp *isp = to_rkisp1_isp(sd); const struct rkisp1_mbus_info *mbus_info; if (fse->pad == RKISP1_ISP_PAD_SINK_PARAMS || @@ -539,9 +540,9 @@ static int rkisp1_isp_enum_frame_size(struct v4l2_subdev *sd, return -EINVAL; fse->min_width = RKISP1_ISP_MIN_WIDTH; - fse->max_width = RKISP1_ISP_MAX_WIDTH; + fse->max_width = isp->rkisp1->info->max_width; fse->min_height = RKISP1_ISP_MIN_HEIGHT; - fse->max_height = RKISP1_ISP_MAX_HEIGHT; + fse->max_height = isp->rkisp1->info->max_height; return 0; } @@ -772,10 +773,10 @@ static void rkisp1_isp_set_sink_fmt(struct rkisp1_isp *isp, sink_fmt->width = clamp_t(u32, format->width, RKISP1_ISP_MIN_WIDTH, - RKISP1_ISP_MAX_WIDTH); + isp->rkisp1->info->max_width); sink_fmt->height = clamp_t(u32, format->height, RKISP1_ISP_MIN_HEIGHT, - RKISP1_ISP_MAX_HEIGHT); + isp->rkisp1->info->max_height); /* * Adjust the color space fields. Accept any color primaries and diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c index 173d1ea41874..320581a9f866 100644 --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c @@ -5,6 +5,9 @@ * Copyright (C) 2017 Rockchip Electronics Co., Ltd. */ +#include <linux/math.h> +#include <linux/string.h> + #include <media/v4l2-common.h> #include <media/v4l2-event.h> #include <media/v4l2-ioctl.h> @@ -33,6 +36,59 @@ #define RKISP1_ISP_CC_COEFF(n) \ (RKISP1_CIF_ISP_CC_COEFF_0 + (n) * 4) +#define RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS BIT(0) +#define RKISP1_EXT_PARAMS_BLOCK_GROUP_LSC BIT(1) + +union rkisp1_ext_params_config { + struct rkisp1_ext_params_block_header header; + struct rkisp1_ext_params_bls_config bls; + struct rkisp1_ext_params_dpcc_config dpcc; + struct rkisp1_ext_params_sdg_config sdg; + struct rkisp1_ext_params_lsc_config lsc; + struct rkisp1_ext_params_awb_gain_config awbg; + struct rkisp1_ext_params_flt_config flt; + struct rkisp1_ext_params_bdm_config bdm; + struct rkisp1_ext_params_ctk_config ctk; + struct rkisp1_ext_params_goc_config goc; + struct rkisp1_ext_params_dpf_config dpf; + struct rkisp1_ext_params_dpf_strength_config dpfs; + struct rkisp1_ext_params_cproc_config cproc; + struct rkisp1_ext_params_ie_config ie; + struct rkisp1_ext_params_awb_meas_config awbm; + struct rkisp1_ext_params_hst_config hst; + struct rkisp1_ext_params_aec_config aec; + struct rkisp1_ext_params_afc_config afc; + struct rkisp1_ext_params_compand_bls_config compand_bls; + struct rkisp1_ext_params_compand_curve_config compand_curve; +}; + +enum rkisp1_params_formats { + RKISP1_PARAMS_FIXED, + RKISP1_PARAMS_EXTENSIBLE, +}; + +static const struct v4l2_meta_format rkisp1_params_formats[] = { + [RKISP1_PARAMS_FIXED] = { + .dataformat = V4L2_META_FMT_RK_ISP1_PARAMS, + .buffersize = sizeof(struct rkisp1_params_cfg), + }, + [RKISP1_PARAMS_EXTENSIBLE] = { + .dataformat = V4L2_META_FMT_RK_ISP1_EXT_PARAMS, + .buffersize = sizeof(struct rkisp1_ext_params_cfg), + }, +}; + +static const struct v4l2_meta_format * +rkisp1_params_get_format_info(u32 dataformat) +{ + for (unsigned int i = 0; i < ARRAY_SIZE(rkisp1_params_formats); i++) { + if (rkisp1_params_formats[i].dataformat == dataformat) + return &rkisp1_params_formats[i]; + } + + return &rkisp1_params_formats[RKISP1_PARAMS_FIXED]; +} + static inline void rkisp1_param_set_bits(struct rkisp1_params *params, u32 reg, u32 bit_mask) { @@ -112,54 +168,20 @@ static void rkisp1_bls_config(struct rkisp1_params *params, new_control &= RKISP1_CIF_ISP_BLS_ENA; /* fixed subtraction values */ if (!arg->enable_auto) { - const struct rkisp1_cif_isp_bls_fixed_val *pval = - &arg->fixed_val; - - switch (params->raw_type) { - case RKISP1_RAW_BGGR: - rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_D_FIXED, - pval->r); - rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_C_FIXED, - pval->gr); - rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_B_FIXED, - pval->gb); - rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_A_FIXED, - pval->b); - break; - case RKISP1_RAW_GBRG: - rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_C_FIXED, - pval->r); - rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_D_FIXED, - pval->gr); - rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_A_FIXED, - pval->gb); - rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_B_FIXED, - pval->b); - break; - case RKISP1_RAW_GRBG: - rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_B_FIXED, - pval->r); - rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_A_FIXED, - pval->gr); - rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_D_FIXED, - pval->gb); - rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_C_FIXED, - pval->b); - break; - case RKISP1_RAW_RGGB: - rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_A_FIXED, - pval->r); - rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_B_FIXED, - pval->gr); - rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_C_FIXED, - pval->gb); - rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_D_FIXED, - pval->b); - break; - default: - break; - } - + static const u32 regs[] = { + RKISP1_CIF_ISP_BLS_A_FIXED, + RKISP1_CIF_ISP_BLS_B_FIXED, + RKISP1_CIF_ISP_BLS_C_FIXED, + RKISP1_CIF_ISP_BLS_D_FIXED, + }; + u32 swapped[4]; + + rkisp1_bls_swap_regs(params->raw_type, regs, swapped); + + rkisp1_write(params->rkisp1, swapped[0], arg->fixed_val.r); + rkisp1_write(params->rkisp1, swapped[1], arg->fixed_val.gr); + rkisp1_write(params->rkisp1, swapped[2], arg->fixed_val.gb); + rkisp1_write(params->rkisp1, swapped[3], arg->fixed_val.b); } else { if (arg->en_windows & BIT(1)) { rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_H2_START, @@ -1239,6 +1261,93 @@ rkisp1_dpf_strength_config(struct rkisp1_params *params, rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_DPF_STRENGTH_R, arg->r); } +static void rkisp1_compand_write_px_curve(struct rkisp1_params *params, + unsigned int addr, const u8 *curve) +{ + const unsigned int points_per_reg = 6; + const unsigned int num_regs = + DIV_ROUND_UP(RKISP1_CIF_ISP_COMPAND_NUM_POINTS, + points_per_reg); + + /* + * The compand curve is specified as a piecewise linear function with + * 64 points. X coordinates are stored as a log2 of the displacement + * from the previous point, in 5 bits, with 6 values per register. The + * last register stores 4 values. + */ + for (unsigned int reg = 0; reg < num_regs; ++reg) { + unsigned int num_points = + min(RKISP1_CIF_ISP_COMPAND_NUM_POINTS - + reg * points_per_reg, points_per_reg); + u32 val = 0; + + for (unsigned int i = 0; i < num_points; i++) + val |= (*curve++ & 0x1f) << (i * 5); + + rkisp1_write(params->rkisp1, addr, val); + addr += 4; + } +} + +static void +rkisp1_compand_write_curve_mem(struct rkisp1_params *params, + unsigned int reg_addr, unsigned int reg_data, + const u32 curve[RKISP1_CIF_ISP_COMPAND_NUM_POINTS]) +{ + for (unsigned int i = 0; i < RKISP1_CIF_ISP_COMPAND_NUM_POINTS; i++) { + rkisp1_write(params->rkisp1, reg_addr, i); + rkisp1_write(params->rkisp1, reg_data, curve[i]); + } +} + +static void +rkisp1_compand_bls_config(struct rkisp1_params *params, + const struct rkisp1_cif_isp_compand_bls_config *arg) +{ + static const u32 regs[] = { + RKISP1_CIF_ISP_COMPAND_BLS_A_FIXED, + RKISP1_CIF_ISP_COMPAND_BLS_B_FIXED, + RKISP1_CIF_ISP_COMPAND_BLS_C_FIXED, + RKISP1_CIF_ISP_COMPAND_BLS_D_FIXED, + }; + u32 swapped[4]; + + rkisp1_bls_swap_regs(params->raw_type, regs, swapped); + + rkisp1_write(params->rkisp1, swapped[0], arg->r); + rkisp1_write(params->rkisp1, swapped[1], arg->gr); + rkisp1_write(params->rkisp1, swapped[2], arg->gb); + rkisp1_write(params->rkisp1, swapped[3], arg->b); +} + +static void +rkisp1_compand_expand_config(struct rkisp1_params *params, + const struct rkisp1_cif_isp_compand_curve_config *arg) +{ + rkisp1_compand_write_px_curve(params, RKISP1_CIF_ISP_COMPAND_EXPAND_PX_N(0), + arg->px); + rkisp1_compand_write_curve_mem(params, RKISP1_CIF_ISP_COMPAND_EXPAND_Y_ADDR, + RKISP1_CIF_ISP_COMPAND_EXPAND_Y_WRITE_DATA, + arg->y); + rkisp1_compand_write_curve_mem(params, RKISP1_CIF_ISP_COMPAND_EXPAND_X_ADDR, + RKISP1_CIF_ISP_COMPAND_EXPAND_X_WRITE_DATA, + arg->x); +} + +static void +rkisp1_compand_compress_config(struct rkisp1_params *params, + const struct rkisp1_cif_isp_compand_curve_config *arg) +{ + rkisp1_compand_write_px_curve(params, RKISP1_CIF_ISP_COMPAND_COMPRESS_PX_N(0), + arg->px); + rkisp1_compand_write_curve_mem(params, RKISP1_CIF_ISP_COMPAND_COMPRESS_Y_ADDR, + RKISP1_CIF_ISP_COMPAND_COMPRESS_Y_WRITE_DATA, + arg->y); + rkisp1_compand_write_curve_mem(params, RKISP1_CIF_ISP_COMPAND_COMPRESS_X_ADDR, + RKISP1_CIF_ISP_COMPAND_COMPRESS_X_WRITE_DATA, + arg->x); +} + static void rkisp1_isp_isr_other_config(struct rkisp1_params *params, const struct rkisp1_params_cfg *new_params) @@ -1249,6 +1358,12 @@ rkisp1_isp_isr_other_config(struct rkisp1_params *params, module_cfg_update = new_params->module_cfg_update; module_ens = new_params->module_ens; + if (!rkisp1_has_feature(params->rkisp1, BLS)) { + module_en_update &= ~RKISP1_CIF_ISP_MODULE_BLS; + module_cfg_update &= ~RKISP1_CIF_ISP_MODULE_BLS; + module_ens &= ~RKISP1_CIF_ISP_MODULE_BLS; + } + /* update dpc config */ if (module_cfg_update & RKISP1_CIF_ISP_MODULE_DPCC) rkisp1_dpcc_config(params, @@ -1501,21 +1616,551 @@ static void rkisp1_isp_isr_meas_config(struct rkisp1_params *params, } } -static bool rkisp1_params_get_buffer(struct rkisp1_params *params, - struct rkisp1_buffer **buf, - struct rkisp1_params_cfg **cfg) +/*------------------------------------------------------------------------------ + * Extensible parameters format handling + */ + +static void +rkisp1_ext_params_bls(struct rkisp1_params *params, + const union rkisp1_ext_params_config *block) +{ + const struct rkisp1_ext_params_bls_config *bls = &block->bls; + + if (bls->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) { + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_BLS_CTRL, + RKISP1_CIF_ISP_BLS_ENA); + return; + } + + rkisp1_bls_config(params, &bls->config); + + if ((bls->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE) && + !(params->enabled_blocks & BIT(bls->header.type))) + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_BLS_CTRL, + RKISP1_CIF_ISP_BLS_ENA); +} + +static void +rkisp1_ext_params_dpcc(struct rkisp1_params *params, + const union rkisp1_ext_params_config *block) { - if (list_empty(¶ms->params)) - return false; + const struct rkisp1_ext_params_dpcc_config *dpcc = &block->dpcc; + + if (dpcc->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) { + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_DPCC_MODE, + RKISP1_CIF_ISP_DPCC_MODE_DPCC_ENABLE); + return; + } - *buf = list_first_entry(¶ms->params, struct rkisp1_buffer, queue); - *cfg = vb2_plane_vaddr(&(*buf)->vb.vb2_buf, 0); + rkisp1_dpcc_config(params, &dpcc->config); - return true; + if ((dpcc->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE) && + !(params->enabled_blocks & BIT(dpcc->header.type))) + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_DPCC_MODE, + RKISP1_CIF_ISP_DPCC_MODE_DPCC_ENABLE); +} + +static void +rkisp1_ext_params_sdg(struct rkisp1_params *params, + const union rkisp1_ext_params_config *block) +{ + const struct rkisp1_ext_params_sdg_config *sdg = &block->sdg; + + if (sdg->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) { + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL, + RKISP1_CIF_ISP_CTRL_ISP_GAMMA_IN_ENA); + return; + } + + rkisp1_sdg_config(params, &sdg->config); + + if ((sdg->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE) && + !(params->enabled_blocks & BIT(sdg->header.type))) + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL, + RKISP1_CIF_ISP_CTRL_ISP_GAMMA_IN_ENA); +} + +static void +rkisp1_ext_params_lsc(struct rkisp1_params *params, + const union rkisp1_ext_params_config *block) +{ + const struct rkisp1_ext_params_lsc_config *lsc = &block->lsc; + + if (lsc->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) { + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_LSC_CTRL, + RKISP1_CIF_ISP_LSC_CTRL_ENA); + return; + } + + rkisp1_lsc_config(params, &lsc->config); + + if ((lsc->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE) && + !(params->enabled_blocks & BIT(lsc->header.type))) + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_LSC_CTRL, + RKISP1_CIF_ISP_LSC_CTRL_ENA); +} + +static void +rkisp1_ext_params_awbg(struct rkisp1_params *params, + const union rkisp1_ext_params_config *block) +{ + const struct rkisp1_ext_params_awb_gain_config *awbg = &block->awbg; + + if (awbg->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) { + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL, + RKISP1_CIF_ISP_CTRL_ISP_AWB_ENA); + return; + } + + params->ops->awb_gain_config(params, &awbg->config); + + if ((awbg->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE) && + !(params->enabled_blocks & BIT(awbg->header.type))) + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL, + RKISP1_CIF_ISP_CTRL_ISP_AWB_ENA); +} + +static void +rkisp1_ext_params_flt(struct rkisp1_params *params, + const union rkisp1_ext_params_config *block) +{ + const struct rkisp1_ext_params_flt_config *flt = &block->flt; + + if (flt->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) { + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_FILT_MODE, + RKISP1_CIF_ISP_FLT_ENA); + return; + } + + rkisp1_flt_config(params, &flt->config); + + if ((flt->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE) && + !(params->enabled_blocks & BIT(flt->header.type))) + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_FILT_MODE, + RKISP1_CIF_ISP_FLT_ENA); +} + +static void +rkisp1_ext_params_bdm(struct rkisp1_params *params, + const union rkisp1_ext_params_config *block) +{ + const struct rkisp1_ext_params_bdm_config *bdm = &block->bdm; + + if (bdm->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) { + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_DEMOSAIC, + RKISP1_CIF_ISP_DEMOSAIC_BYPASS); + return; + } + + rkisp1_bdm_config(params, &bdm->config); + + if ((bdm->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE) && + !(params->enabled_blocks & BIT(bdm->header.type))) + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_DEMOSAIC, + RKISP1_CIF_ISP_DEMOSAIC_BYPASS); +} + +static void +rkisp1_ext_params_ctk(struct rkisp1_params *params, + const union rkisp1_ext_params_config *block) +{ + const struct rkisp1_ext_params_ctk_config *ctk = &block->ctk; + + if (ctk->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) { + rkisp1_ctk_enable(params, false); + return; + } + + rkisp1_ctk_config(params, &ctk->config); + + if ((ctk->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE) && + !(params->enabled_blocks & BIT(ctk->header.type))) + rkisp1_ctk_enable(params, true); +} + +static void +rkisp1_ext_params_goc(struct rkisp1_params *params, + const union rkisp1_ext_params_config *block) +{ + const struct rkisp1_ext_params_goc_config *goc = &block->goc; + + if (goc->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) { + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL, + RKISP1_CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA); + return; + } + + params->ops->goc_config(params, &goc->config); + + /* + * Unconditionally re-enable the GOC module which gets disabled by + * goc_config(). + */ + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL, + RKISP1_CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA); +} + +static void +rkisp1_ext_params_dpf(struct rkisp1_params *params, + const union rkisp1_ext_params_config *block) +{ + const struct rkisp1_ext_params_dpf_config *dpf = &block->dpf; + + if (dpf->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) { + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_DPF_MODE, + RKISP1_CIF_ISP_DPF_MODE_EN); + return; + } + + rkisp1_dpf_config(params, &dpf->config); + + if ((dpf->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE) && + !(params->enabled_blocks & BIT(dpf->header.type))) + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_DPF_MODE, + RKISP1_CIF_ISP_DPF_MODE_EN); +} + +static void +rkisp1_ext_params_dpfs(struct rkisp1_params *params, + const union rkisp1_ext_params_config *block) +{ + const struct rkisp1_ext_params_dpf_strength_config *dpfs = &block->dpfs; + + rkisp1_dpf_strength_config(params, &dpfs->config); +} + +static void +rkisp1_ext_params_cproc(struct rkisp1_params *params, + const union rkisp1_ext_params_config *block) +{ + const struct rkisp1_ext_params_cproc_config *cproc = &block->cproc; + + if (cproc->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) { + rkisp1_param_clear_bits(params, RKISP1_CIF_C_PROC_CTRL, + RKISP1_CIF_C_PROC_CTR_ENABLE); + return; + } + + rkisp1_cproc_config(params, &cproc->config); + + if ((cproc->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE) && + !(params->enabled_blocks & BIT(cproc->header.type))) + rkisp1_param_set_bits(params, RKISP1_CIF_C_PROC_CTRL, + RKISP1_CIF_C_PROC_CTR_ENABLE); +} + +static void +rkisp1_ext_params_ie(struct rkisp1_params *params, + const union rkisp1_ext_params_config *block) +{ + const struct rkisp1_ext_params_ie_config *ie = &block->ie; + + if (ie->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) { + rkisp1_ie_enable(params, false); + return; + } + + rkisp1_ie_config(params, &ie->config); + + if ((ie->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE) && + !(params->enabled_blocks & BIT(ie->header.type))) + rkisp1_ie_enable(params, true); +} + +static void +rkisp1_ext_params_awbm(struct rkisp1_params *params, + const union rkisp1_ext_params_config *block) +{ + const struct rkisp1_ext_params_awb_meas_config *awbm = &block->awbm; + + if (awbm->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) { + params->ops->awb_meas_enable(params, &awbm->config, + false); + return; + } + + params->ops->awb_meas_config(params, &awbm->config); + + if ((awbm->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE) && + !(params->enabled_blocks & BIT(awbm->header.type))) + params->ops->awb_meas_enable(params, &awbm->config, + true); +} + +static void +rkisp1_ext_params_hstm(struct rkisp1_params *params, + const union rkisp1_ext_params_config *block) +{ + const struct rkisp1_ext_params_hst_config *hst = &block->hst; + + if (hst->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) { + params->ops->hst_enable(params, &hst->config, false); + return; + } + + params->ops->hst_config(params, &hst->config); + + if ((hst->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE) && + !(params->enabled_blocks & BIT(hst->header.type))) + params->ops->hst_enable(params, &hst->config, true); +} + +static void +rkisp1_ext_params_aecm(struct rkisp1_params *params, + const union rkisp1_ext_params_config *block) +{ + const struct rkisp1_ext_params_aec_config *aec = &block->aec; + + if (aec->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) { + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_EXP_CTRL, + RKISP1_CIF_ISP_EXP_ENA); + return; + } + + params->ops->aec_config(params, &aec->config); + + if ((aec->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE) && + !(params->enabled_blocks & BIT(aec->header.type))) + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_EXP_CTRL, + RKISP1_CIF_ISP_EXP_ENA); +} + +static void +rkisp1_ext_params_afcm(struct rkisp1_params *params, + const union rkisp1_ext_params_config *block) +{ + const struct rkisp1_ext_params_afc_config *afc = &block->afc; + + if (afc->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) { + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_AFM_CTRL, + RKISP1_CIF_ISP_AFM_ENA); + return; + } + + params->ops->afm_config(params, &afc->config); + + if ((afc->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE) && + !(params->enabled_blocks & BIT(afc->header.type))) + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_AFM_CTRL, + RKISP1_CIF_ISP_AFM_ENA); +} + +static void rkisp1_ext_params_compand_bls(struct rkisp1_params *params, + const union rkisp1_ext_params_config *block) +{ + const struct rkisp1_ext_params_compand_bls_config *bls = + &block->compand_bls; + + if (bls->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) { + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_COMPAND_CTRL, + RKISP1_CIF_ISP_COMPAND_CTRL_BLS_ENABLE); + return; + } + + rkisp1_compand_bls_config(params, &bls->config); + + if ((bls->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE) && + !(params->enabled_blocks & BIT(bls->header.type))) + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_COMPAND_CTRL, + RKISP1_CIF_ISP_COMPAND_CTRL_BLS_ENABLE); +} + +static void rkisp1_ext_params_compand_expand(struct rkisp1_params *params, + const union rkisp1_ext_params_config *block) +{ + const struct rkisp1_ext_params_compand_curve_config *curve = + &block->compand_curve; + + if (curve->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) { + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_COMPAND_CTRL, + RKISP1_CIF_ISP_COMPAND_CTRL_EXPAND_ENABLE); + return; + } + + rkisp1_compand_expand_config(params, &curve->config); + + if ((curve->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE) && + !(params->enabled_blocks & BIT(curve->header.type))) + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_COMPAND_CTRL, + RKISP1_CIF_ISP_COMPAND_CTRL_EXPAND_ENABLE); +} + +static void rkisp1_ext_params_compand_compress(struct rkisp1_params *params, + const union rkisp1_ext_params_config *block) +{ + const struct rkisp1_ext_params_compand_curve_config *curve = + &block->compand_curve; + + if (curve->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) { + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_COMPAND_CTRL, + RKISP1_CIF_ISP_COMPAND_CTRL_COMPRESS_ENABLE); + return; + } + + rkisp1_compand_compress_config(params, &curve->config); + + if ((curve->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE) && + !(params->enabled_blocks & BIT(curve->header.type))) + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_COMPAND_CTRL, + RKISP1_CIF_ISP_COMPAND_CTRL_COMPRESS_ENABLE); +} + +typedef void (*rkisp1_block_handler)(struct rkisp1_params *params, + const union rkisp1_ext_params_config *config); + +static const struct rkisp1_ext_params_handler { + size_t size; + rkisp1_block_handler handler; + unsigned int group; + unsigned int features; +} rkisp1_ext_params_handlers[] = { + [RKISP1_EXT_PARAMS_BLOCK_TYPE_BLS] = { + .size = sizeof(struct rkisp1_ext_params_bls_config), + .handler = rkisp1_ext_params_bls, + .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS, + .features = RKISP1_FEATURE_BLS, + }, + [RKISP1_EXT_PARAMS_BLOCK_TYPE_DPCC] = { + .size = sizeof(struct rkisp1_ext_params_dpcc_config), + .handler = rkisp1_ext_params_dpcc, + .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS, + }, + [RKISP1_EXT_PARAMS_BLOCK_TYPE_SDG] = { + .size = sizeof(struct rkisp1_ext_params_sdg_config), + .handler = rkisp1_ext_params_sdg, + .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS, + }, + [RKISP1_EXT_PARAMS_BLOCK_TYPE_AWB_GAIN] = { + .size = sizeof(struct rkisp1_ext_params_awb_gain_config), + .handler = rkisp1_ext_params_awbg, + .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS, + }, + [RKISP1_EXT_PARAMS_BLOCK_TYPE_FLT] = { + .size = sizeof(struct rkisp1_ext_params_flt_config), + .handler = rkisp1_ext_params_flt, + .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS, + }, + [RKISP1_EXT_PARAMS_BLOCK_TYPE_BDM] = { + .size = sizeof(struct rkisp1_ext_params_bdm_config), + .handler = rkisp1_ext_params_bdm, + .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS, + }, + [RKISP1_EXT_PARAMS_BLOCK_TYPE_CTK] = { + .size = sizeof(struct rkisp1_ext_params_ctk_config), + .handler = rkisp1_ext_params_ctk, + .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS, + }, + [RKISP1_EXT_PARAMS_BLOCK_TYPE_GOC] = { + .size = sizeof(struct rkisp1_ext_params_goc_config), + .handler = rkisp1_ext_params_goc, + .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS, + }, + [RKISP1_EXT_PARAMS_BLOCK_TYPE_DPF] = { + .size = sizeof(struct rkisp1_ext_params_dpf_config), + .handler = rkisp1_ext_params_dpf, + .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS, + }, + [RKISP1_EXT_PARAMS_BLOCK_TYPE_DPF_STRENGTH] = { + .size = sizeof(struct rkisp1_ext_params_dpf_strength_config), + .handler = rkisp1_ext_params_dpfs, + .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS, + }, + [RKISP1_EXT_PARAMS_BLOCK_TYPE_CPROC] = { + .size = sizeof(struct rkisp1_ext_params_cproc_config), + .handler = rkisp1_ext_params_cproc, + .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS, + }, + [RKISP1_EXT_PARAMS_BLOCK_TYPE_IE] = { + .size = sizeof(struct rkisp1_ext_params_ie_config), + .handler = rkisp1_ext_params_ie, + .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS, + }, + [RKISP1_EXT_PARAMS_BLOCK_TYPE_LSC] = { + .size = sizeof(struct rkisp1_ext_params_lsc_config), + .handler = rkisp1_ext_params_lsc, + .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_LSC, + }, + [RKISP1_EXT_PARAMS_BLOCK_TYPE_AWB_MEAS] = { + .size = sizeof(struct rkisp1_ext_params_awb_meas_config), + .handler = rkisp1_ext_params_awbm, + .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS, + }, + [RKISP1_EXT_PARAMS_BLOCK_TYPE_HST_MEAS] = { + .size = sizeof(struct rkisp1_ext_params_hst_config), + .handler = rkisp1_ext_params_hstm, + .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS, + }, + [RKISP1_EXT_PARAMS_BLOCK_TYPE_AEC_MEAS] = { + .size = sizeof(struct rkisp1_ext_params_aec_config), + .handler = rkisp1_ext_params_aecm, + .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS, + }, + [RKISP1_EXT_PARAMS_BLOCK_TYPE_AFC_MEAS] = { + .size = sizeof(struct rkisp1_ext_params_afc_config), + .handler = rkisp1_ext_params_afcm, + .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS, + }, + [RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_BLS] = { + .size = sizeof(struct rkisp1_ext_params_compand_bls_config), + .handler = rkisp1_ext_params_compand_bls, + .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS, + .features = RKISP1_FEATURE_COMPAND, + }, + [RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_EXPAND] = { + .size = sizeof(struct rkisp1_ext_params_compand_curve_config), + .handler = rkisp1_ext_params_compand_expand, + .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS, + .features = RKISP1_FEATURE_COMPAND, + }, + [RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_COMPRESS] = { + .size = sizeof(struct rkisp1_ext_params_compand_curve_config), + .handler = rkisp1_ext_params_compand_compress, + .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS, + .features = RKISP1_FEATURE_COMPAND, + }, +}; + +static void rkisp1_ext_params_config(struct rkisp1_params *params, + struct rkisp1_ext_params_cfg *cfg, + u32 block_group_mask) +{ + size_t block_offset = 0; + + if (WARN_ON(!cfg)) + return; + + /* Walk the list of parameter blocks and process them. */ + while (block_offset < cfg->data_size) { + const struct rkisp1_ext_params_handler *block_handler; + const union rkisp1_ext_params_config *block; + + block = (const union rkisp1_ext_params_config *) + &cfg->data[block_offset]; + block_offset += block->header.size; + + /* + * Make sure the block is supported by the platform and in the + * list of groups to configure. + */ + block_handler = &rkisp1_ext_params_handlers[block->header.type]; + if (!(block_handler->group & block_group_mask)) + continue; + + if ((params->rkisp1->info->features & block_handler->features) != + block_handler->features) + continue; + + block_handler->handler(params, block); + + if (block->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) + params->enabled_blocks &= ~BIT(block->header.type); + else if (block->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE) + params->enabled_blocks |= BIT(block->header.type); + } } static void rkisp1_params_complete_buffer(struct rkisp1_params *params, - struct rkisp1_buffer *buf, + struct rkisp1_params_buffer *buf, unsigned int frame_sequence) { list_del(&buf->queue); @@ -1527,17 +2172,24 @@ static void rkisp1_params_complete_buffer(struct rkisp1_params *params, void rkisp1_params_isr(struct rkisp1_device *rkisp1) { struct rkisp1_params *params = &rkisp1->params; - struct rkisp1_params_cfg *new_params; - struct rkisp1_buffer *cur_buf; + struct rkisp1_params_buffer *cur_buf; spin_lock(¶ms->config_lock); - if (!rkisp1_params_get_buffer(params, &cur_buf, &new_params)) + cur_buf = list_first_entry_or_null(¶ms->params, + struct rkisp1_params_buffer, queue); + if (!cur_buf) goto unlock; - rkisp1_isp_isr_other_config(params, new_params); - rkisp1_isp_isr_lsc_config(params, new_params); - rkisp1_isp_isr_meas_config(params, new_params); + if (params->metafmt->dataformat == V4L2_META_FMT_RK_ISP1_PARAMS) { + rkisp1_isp_isr_other_config(params, cur_buf->cfg); + rkisp1_isp_isr_lsc_config(params, cur_buf->cfg); + rkisp1_isp_isr_meas_config(params, cur_buf->cfg); + } else { + rkisp1_ext_params_config(params, cur_buf->cfg, + RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS | + RKISP1_EXT_PARAMS_BLOCK_GROUP_LSC); + } /* update shadow register immediately */ rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL, @@ -1603,8 +2255,7 @@ void rkisp1_params_pre_configure(struct rkisp1_params *params, enum v4l2_ycbcr_encoding ycbcr_encoding) { struct rkisp1_cif_isp_hst_config hst = rkisp1_hst_params_default_config; - struct rkisp1_params_cfg *new_params; - struct rkisp1_buffer *cur_buf; + struct rkisp1_params_buffer *cur_buf; params->quantization = quantization; params->ycbcr_encoding = ycbcr_encoding; @@ -1633,11 +2284,18 @@ void rkisp1_params_pre_configure(struct rkisp1_params *params, /* apply the first buffer if there is one already */ - if (!rkisp1_params_get_buffer(params, &cur_buf, &new_params)) + cur_buf = list_first_entry_or_null(¶ms->params, + struct rkisp1_params_buffer, queue); + if (!cur_buf) goto unlock; - rkisp1_isp_isr_other_config(params, new_params); - rkisp1_isp_isr_meas_config(params, new_params); + if (params->metafmt->dataformat == V4L2_META_FMT_RK_ISP1_PARAMS) { + rkisp1_isp_isr_other_config(params, cur_buf->cfg); + rkisp1_isp_isr_meas_config(params, cur_buf->cfg); + } else { + rkisp1_ext_params_config(params, cur_buf->cfg, + RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS); + } /* update shadow register immediately */ rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL, @@ -1649,8 +2307,7 @@ unlock: void rkisp1_params_post_configure(struct rkisp1_params *params) { - struct rkisp1_params_cfg *new_params; - struct rkisp1_buffer *cur_buf; + struct rkisp1_params_buffer *cur_buf; spin_lock_irq(¶ms->config_lock); @@ -1662,11 +2319,16 @@ void rkisp1_params_post_configure(struct rkisp1_params *params) * ordering doesn't affect other ISP versions negatively, do so * unconditionally. */ - - if (!rkisp1_params_get_buffer(params, &cur_buf, &new_params)) + cur_buf = list_first_entry_or_null(¶ms->params, + struct rkisp1_params_buffer, queue); + if (!cur_buf) goto unlock; - rkisp1_isp_isr_lsc_config(params, new_params); + if (params->metafmt->dataformat == V4L2_META_FMT_RK_ISP1_PARAMS) + rkisp1_isp_isr_lsc_config(params, cur_buf->cfg); + else + rkisp1_ext_params_config(params, cur_buf->cfg, + RKISP1_EXT_PARAMS_BLOCK_GROUP_LSC); /* update shadow register immediately */ rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL, @@ -1742,12 +2404,12 @@ static int rkisp1_params_enum_fmt_meta_out(struct file *file, void *priv, struct v4l2_fmtdesc *f) { struct video_device *video = video_devdata(file); - struct rkisp1_params *params = video_get_drvdata(video); - if (f->index > 0 || f->type != video->queue->type) + if (f->index >= ARRAY_SIZE(rkisp1_params_formats) || + f->type != video->queue->type) return -EINVAL; - f->pixelformat = params->vdev_fmt.fmt.meta.dataformat; + f->pixelformat = rkisp1_params_formats[f->index].dataformat; return 0; } @@ -1762,9 +2424,40 @@ static int rkisp1_params_g_fmt_meta_out(struct file *file, void *fh, if (f->type != video->queue->type) return -EINVAL; - memset(meta, 0, sizeof(*meta)); - meta->dataformat = params->vdev_fmt.fmt.meta.dataformat; - meta->buffersize = params->vdev_fmt.fmt.meta.buffersize; + *meta = *params->metafmt; + + return 0; +} + +static int rkisp1_params_try_fmt_meta_out(struct file *file, void *fh, + struct v4l2_format *f) +{ + struct video_device *video = video_devdata(file); + struct v4l2_meta_format *meta = &f->fmt.meta; + + if (f->type != video->queue->type) + return -EINVAL; + + *meta = *rkisp1_params_get_format_info(meta->dataformat); + + return 0; +} + +static int rkisp1_params_s_fmt_meta_out(struct file *file, void *fh, + struct v4l2_format *f) +{ + struct video_device *video = video_devdata(file); + struct rkisp1_params *params = video_get_drvdata(video); + struct v4l2_meta_format *meta = &f->fmt.meta; + + if (f->type != video->queue->type) + return -EINVAL; + + if (vb2_is_busy(video->queue)) + return -EBUSY; + + params->metafmt = rkisp1_params_get_format_info(meta->dataformat); + *meta = *params->metafmt; return 0; } @@ -1794,8 +2487,8 @@ static const struct v4l2_ioctl_ops rkisp1_params_ioctl = { .vidioc_streamoff = vb2_ioctl_streamoff, .vidioc_enum_fmt_meta_out = rkisp1_params_enum_fmt_meta_out, .vidioc_g_fmt_meta_out = rkisp1_params_g_fmt_meta_out, - .vidioc_s_fmt_meta_out = rkisp1_params_g_fmt_meta_out, - .vidioc_try_fmt_meta_out = rkisp1_params_g_fmt_meta_out, + .vidioc_s_fmt_meta_out = rkisp1_params_s_fmt_meta_out, + .vidioc_try_fmt_meta_out = rkisp1_params_try_fmt_meta_out, .vidioc_querycap = rkisp1_params_querycap, .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, .vidioc_unsubscribe_event = v4l2_event_unsubscribe, @@ -1807,22 +2500,46 @@ static int rkisp1_params_vb2_queue_setup(struct vb2_queue *vq, unsigned int sizes[], struct device *alloc_devs[]) { + struct rkisp1_params *params = vq->drv_priv; + *num_buffers = clamp_t(u32, *num_buffers, RKISP1_ISP_PARAMS_REQ_BUFS_MIN, RKISP1_ISP_PARAMS_REQ_BUFS_MAX); *num_planes = 1; - sizes[0] = sizeof(struct rkisp1_params_cfg); + sizes[0] = params->metafmt->buffersize; return 0; } +static int rkisp1_params_vb2_buf_init(struct vb2_buffer *vb) +{ + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct rkisp1_params_buffer *params_buf = to_rkisp1_params_buffer(vbuf); + struct rkisp1_params *params = vb->vb2_queue->drv_priv; + + params_buf->cfg = kvmalloc(params->metafmt->buffersize, + GFP_KERNEL); + if (!params_buf->cfg) + return -ENOMEM; + + return 0; +} + +static void rkisp1_params_vb2_buf_cleanup(struct vb2_buffer *vb) +{ + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct rkisp1_params_buffer *params_buf = to_rkisp1_params_buffer(vbuf); + + kvfree(params_buf->cfg); + params_buf->cfg = NULL; +} + static void rkisp1_params_vb2_buf_queue(struct vb2_buffer *vb) { struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); - struct rkisp1_buffer *params_buf = - container_of(vbuf, struct rkisp1_buffer, vb); + struct rkisp1_params_buffer *params_buf = to_rkisp1_params_buffer(vbuf); struct vb2_queue *vq = vb->vb2_queue; struct rkisp1_params *params = vq->drv_priv; @@ -1831,12 +2548,133 @@ static void rkisp1_params_vb2_buf_queue(struct vb2_buffer *vb) spin_unlock_irq(¶ms->config_lock); } +static int rkisp1_params_prepare_ext_params(struct rkisp1_params *params, + struct vb2_buffer *vb) +{ + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct rkisp1_params_buffer *params_buf = to_rkisp1_params_buffer(vbuf); + size_t header_size = offsetof(struct rkisp1_ext_params_cfg, data); + struct rkisp1_ext_params_cfg *cfg = params_buf->cfg; + size_t payload_size = vb2_get_plane_payload(vb, 0); + struct rkisp1_ext_params_cfg *usr_cfg = + vb2_plane_vaddr(&vbuf->vb2_buf, 0); + size_t block_offset = 0; + size_t cfg_size; + + /* + * Validate the buffer payload size before copying the parameters. The + * payload has to be smaller than the destination buffer size and larger + * than the header size. + */ + if (payload_size > params->metafmt->buffersize) { + dev_dbg(params->rkisp1->dev, + "Too large buffer payload size %zu\n", payload_size); + return -EINVAL; + } + + if (payload_size < header_size) { + dev_dbg(params->rkisp1->dev, + "Buffer payload %zu smaller than header size %zu\n", + payload_size, header_size); + return -EINVAL; + } + + /* + * Copy the parameters buffer to the internal scratch buffer to avoid + * userspace modifying the buffer content while the driver processes it. + */ + memcpy(cfg, usr_cfg, payload_size); + + /* Only v1 is supported at the moment. */ + if (cfg->version != RKISP1_EXT_PARAM_BUFFER_V1) { + dev_dbg(params->rkisp1->dev, + "Unsupported extensible format version: %u\n", + cfg->version); + return -EINVAL; + } + + /* Validate the size reported in the parameters buffer header. */ + cfg_size = header_size + cfg->data_size; + if (cfg_size != payload_size) { + dev_dbg(params->rkisp1->dev, + "Data size %zu different than buffer payload size %zu\n", + cfg_size, payload_size); + return -EINVAL; + } + + /* Walk the list of parameter blocks and validate them. */ + cfg_size = cfg->data_size; + while (cfg_size >= sizeof(struct rkisp1_ext_params_block_header)) { + const struct rkisp1_ext_params_block_header *block; + const struct rkisp1_ext_params_handler *handler; + + block = (const struct rkisp1_ext_params_block_header *) + &cfg->data[block_offset]; + + if (block->type >= ARRAY_SIZE(rkisp1_ext_params_handlers)) { + dev_dbg(params->rkisp1->dev, + "Invalid parameters block type\n"); + return -EINVAL; + } + + if (block->size > cfg_size) { + dev_dbg(params->rkisp1->dev, + "Premature end of parameters data\n"); + return -EINVAL; + } + + if ((block->flags & (RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE | + RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE)) == + (RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE | + RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE)) { + dev_dbg(params->rkisp1->dev, + "Invalid parameters block flags\n"); + return -EINVAL; + } + + handler = &rkisp1_ext_params_handlers[block->type]; + if (block->size != handler->size) { + dev_dbg(params->rkisp1->dev, + "Invalid parameters block size\n"); + return -EINVAL; + } + + block_offset += block->size; + cfg_size -= block->size; + } + + if (cfg_size) { + dev_dbg(params->rkisp1->dev, + "Unexpected data after the parameters buffer end\n"); + return -EINVAL; + } + + return 0; +} + static int rkisp1_params_vb2_buf_prepare(struct vb2_buffer *vb) { - if (vb2_plane_size(vb, 0) < sizeof(struct rkisp1_params_cfg)) + struct rkisp1_params *params = vb->vb2_queue->drv_priv; + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct rkisp1_params_buffer *params_buf = to_rkisp1_params_buffer(vbuf); + struct rkisp1_params_cfg *cfg = vb2_plane_vaddr(&vbuf->vb2_buf, 0); + size_t payload = vb2_get_plane_payload(vb, 0); + + if (params->metafmt->dataformat == V4L2_META_FMT_RK_ISP1_EXT_PARAMS) + return rkisp1_params_prepare_ext_params(params, vb); + + /* + * For the fixed parameters format the payload size must be exactly the + * size of the parameters structure. + */ + if (payload != sizeof(*cfg)) return -EINVAL; - vb2_set_plane_payload(vb, 0, sizeof(struct rkisp1_params_cfg)); + /* + * Copy the parameters buffer to the internal scratch buffer to avoid + * userspace modifying the buffer content while the driver processes it. + */ + memcpy(params_buf->cfg, cfg, payload); return 0; } @@ -1844,7 +2682,7 @@ static int rkisp1_params_vb2_buf_prepare(struct vb2_buffer *vb) static void rkisp1_params_vb2_stop_streaming(struct vb2_queue *vq) { struct rkisp1_params *params = vq->drv_priv; - struct rkisp1_buffer *buf; + struct rkisp1_params_buffer *buf; LIST_HEAD(tmp_list); /* @@ -1858,16 +2696,19 @@ static void rkisp1_params_vb2_stop_streaming(struct vb2_queue *vq) list_for_each_entry(buf, &tmp_list, queue) vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); + + params->enabled_blocks = 0; } static const struct vb2_ops rkisp1_params_vb2_ops = { .queue_setup = rkisp1_params_vb2_queue_setup, + .buf_init = rkisp1_params_vb2_buf_init, + .buf_cleanup = rkisp1_params_vb2_buf_cleanup, .wait_prepare = vb2_ops_wait_prepare, .wait_finish = vb2_ops_wait_finish, .buf_queue = rkisp1_params_vb2_buf_queue, .buf_prepare = rkisp1_params_vb2_buf_prepare, .stop_streaming = rkisp1_params_vb2_stop_streaming, - }; static const struct v4l2_file_operations rkisp1_params_fops = { @@ -1890,26 +2731,13 @@ static int rkisp1_params_init_vb2_queue(struct vb2_queue *q, q->drv_priv = params; q->ops = &rkisp1_params_vb2_ops; q->mem_ops = &vb2_vmalloc_memops; - q->buf_struct_size = sizeof(struct rkisp1_buffer); + q->buf_struct_size = sizeof(struct rkisp1_params_buffer); q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; q->lock = &node->vlock; return vb2_queue_init(q); } -static void rkisp1_init_params(struct rkisp1_params *params) -{ - params->vdev_fmt.fmt.meta.dataformat = - V4L2_META_FMT_RK_ISP1_PARAMS; - params->vdev_fmt.fmt.meta.buffersize = - sizeof(struct rkisp1_params_cfg); - - if (params->rkisp1->info->isp_ver == RKISP1_V12) - params->ops = &rkisp1_v12_params_ops; - else - params->ops = &rkisp1_v10_params_ops; -} - int rkisp1_params_register(struct rkisp1_device *rkisp1) { struct rkisp1_params *params = &rkisp1->params; @@ -1938,7 +2766,14 @@ int rkisp1_params_register(struct rkisp1_device *rkisp1) vdev->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_META_OUTPUT; vdev->vfl_dir = VFL_DIR_TX; rkisp1_params_init_vb2_queue(vdev->queue, params); - rkisp1_init_params(params); + + params->metafmt = &rkisp1_params_formats[RKISP1_PARAMS_FIXED]; + + if (params->rkisp1->info->isp_ver == RKISP1_V12) + params->ops = &rkisp1_v12_params_ops; + else + params->ops = &rkisp1_v10_params_ops; + video_set_drvdata(vdev, params); node->pad.flags = MEDIA_PAD_FL_SOURCE; diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-regs.h b/drivers/media/platform/rockchip/rkisp1/rkisp1-regs.h index fccf4c17ee8d..bf0260600a19 100644 --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-regs.h +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-regs.h @@ -704,6 +704,12 @@ #define RKISP1_CIF_ISP_DPF_SPATIAL_COEFF_MAX 0x1f #define RKISP1_CIF_ISP_DPF_NLL_COEFF_N_MAX 0x3ff +/* COMPAND */ +#define RKISP1_CIF_ISP_COMPAND_CTRL_EXPAND_ENABLE BIT(0) +#define RKISP1_CIF_ISP_COMPAND_CTRL_COMPRESS_ENABLE BIT(1) +#define RKISP1_CIF_ISP_COMPAND_CTRL_SOFT_RESET_FLAG BIT(2) +#define RKISP1_CIF_ISP_COMPAND_CTRL_BLS_ENABLE BIT(3) + /* =================================================================== */ /* CIF Registers */ /* =================================================================== */ @@ -1394,6 +1400,23 @@ #define RKISP1_CIF_ISP_VSM_DELTA_H (RKISP1_CIF_ISP_VSM_BASE + 0x0000001c) #define RKISP1_CIF_ISP_VSM_DELTA_V (RKISP1_CIF_ISP_VSM_BASE + 0x00000020) +#define RKISP1_CIF_ISP_COMPAND_BASE 0x00003200 +#define RKISP1_CIF_ISP_COMPAND_CTRL (RKISP1_CIF_ISP_COMPAND_BASE + 0x00000000) +#define RKISP1_CIF_ISP_COMPAND_BLS_A_FIXED (RKISP1_CIF_ISP_COMPAND_BASE + 0x00000004) +#define RKISP1_CIF_ISP_COMPAND_BLS_B_FIXED (RKISP1_CIF_ISP_COMPAND_BASE + 0x00000008) +#define RKISP1_CIF_ISP_COMPAND_BLS_C_FIXED (RKISP1_CIF_ISP_COMPAND_BASE + 0x0000000c) +#define RKISP1_CIF_ISP_COMPAND_BLS_D_FIXED (RKISP1_CIF_ISP_COMPAND_BASE + 0x00000010) +#define RKISP1_CIF_ISP_COMPAND_EXPAND_PX_N(n) (RKISP1_CIF_ISP_COMPAND_BASE + 0x00000014 + (n) * 4) +#define RKISP1_CIF_ISP_COMPAND_COMPRESS_PX_N(n) (RKISP1_CIF_ISP_COMPAND_BASE + 0x00000040 + (n) * 4) +#define RKISP1_CIF_ISP_COMPAND_EXPAND_Y_ADDR (RKISP1_CIF_ISP_COMPAND_BASE + 0x0000006c) +#define RKISP1_CIF_ISP_COMPAND_EXPAND_Y_WRITE_DATA (RKISP1_CIF_ISP_COMPAND_BASE + 0x00000070) +#define RKISP1_CIF_ISP_COMPAND_COMPRESS_Y_ADDR (RKISP1_CIF_ISP_COMPAND_BASE + 0x00000074) +#define RKISP1_CIF_ISP_COMPAND_COMPRESS_Y_WRITE_DATA (RKISP1_CIF_ISP_COMPAND_BASE + 0x00000078) +#define RKISP1_CIF_ISP_COMPAND_EXPAND_X_ADDR (RKISP1_CIF_ISP_COMPAND_BASE + 0x0000007c) +#define RKISP1_CIF_ISP_COMPAND_EXPAND_X_WRITE_DATA (RKISP1_CIF_ISP_COMPAND_BASE + 0x00000080) +#define RKISP1_CIF_ISP_COMPAND_COMPRESS_X_ADDR (RKISP1_CIF_ISP_COMPAND_BASE + 0x00000084) +#define RKISP1_CIF_ISP_COMPAND_COMPRESS_X_WRITE_DATA (RKISP1_CIF_ISP_COMPAND_BASE + 0x00000088) + #define RKISP1_CIF_ISP_CSI0_BASE 0x00007000 #define RKISP1_CIF_ISP_CSI0_CTRL0 (RKISP1_CIF_ISP_CSI0_BASE + 0x00000000) diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-resizer.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-resizer.c index 1fa991227fa9..f073e72a0d37 100644 --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-resizer.c +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-resizer.c @@ -494,10 +494,10 @@ static void rkisp1_rsz_set_sink_fmt(struct rkisp1_resizer *rsz, sink_fmt->width = clamp_t(u32, format->width, RKISP1_ISP_MIN_WIDTH, - RKISP1_ISP_MAX_WIDTH); + rsz->rkisp1->info->max_width); sink_fmt->height = clamp_t(u32, format->height, RKISP1_ISP_MIN_HEIGHT, - RKISP1_ISP_MAX_HEIGHT); + rsz->rkisp1->info->max_height); /* * Adjust the color space fields. Accept any color primaries and diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-stats.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-stats.c index 2795eef91bdd..a502719e916a 100644 --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-stats.c +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-stats.c @@ -304,48 +304,25 @@ static void rkisp1_stats_get_hst_meas_v12(struct rkisp1_stats *stats, static void rkisp1_stats_get_bls_meas(struct rkisp1_stats *stats, struct rkisp1_stat_buffer *pbuf) { + static const u32 regs[] = { + RKISP1_CIF_ISP_BLS_A_MEASURED, + RKISP1_CIF_ISP_BLS_B_MEASURED, + RKISP1_CIF_ISP_BLS_C_MEASURED, + RKISP1_CIF_ISP_BLS_D_MEASURED, + }; struct rkisp1_device *rkisp1 = stats->rkisp1; const struct rkisp1_mbus_info *in_fmt = rkisp1->isp.sink_fmt; struct rkisp1_cif_isp_bls_meas_val *bls_val; + u32 swapped[4]; + + rkisp1_bls_swap_regs(in_fmt->bayer_pat, regs, swapped); bls_val = &pbuf->params.ae.bls_val; - if (in_fmt->bayer_pat == RKISP1_RAW_BGGR) { - bls_val->meas_b = - rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_A_MEASURED); - bls_val->meas_gb = - rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_B_MEASURED); - bls_val->meas_gr = - rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_C_MEASURED); - bls_val->meas_r = - rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_D_MEASURED); - } else if (in_fmt->bayer_pat == RKISP1_RAW_GBRG) { - bls_val->meas_gb = - rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_A_MEASURED); - bls_val->meas_b = - rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_B_MEASURED); - bls_val->meas_r = - rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_C_MEASURED); - bls_val->meas_gr = - rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_D_MEASURED); - } else if (in_fmt->bayer_pat == RKISP1_RAW_GRBG) { - bls_val->meas_gr = - rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_A_MEASURED); - bls_val->meas_r = - rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_B_MEASURED); - bls_val->meas_b = - rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_C_MEASURED); - bls_val->meas_gb = - rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_D_MEASURED); - } else if (in_fmt->bayer_pat == RKISP1_RAW_RGGB) { - bls_val->meas_r = - rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_A_MEASURED); - bls_val->meas_gr = - rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_B_MEASURED); - bls_val->meas_gb = - rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_C_MEASURED); - bls_val->meas_b = - rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_D_MEASURED); - } + + bls_val->meas_r = rkisp1_read(rkisp1, swapped[0]); + bls_val->meas_gr = rkisp1_read(rkisp1, swapped[1]); + bls_val->meas_gb = rkisp1_read(rkisp1, swapped[2]); + bls_val->meas_b = rkisp1_read(rkisp1, swapped[3]); } static const struct rkisp1_stats_ops rkisp1_v10_stats_ops = { diff --git a/drivers/media/platform/samsung/exynos-gsc/gsc-core.c b/drivers/media/platform/samsung/exynos-gsc/gsc-core.c index 618ae55fe396..f45f5c8612a6 100644 --- a/drivers/media/platform/samsung/exynos-gsc/gsc-core.c +++ b/drivers/media/platform/samsung/exynos-gsc/gsc-core.c @@ -1225,7 +1225,7 @@ static void gsc_remove(struct platform_device *pdev) static int gsc_m2m_suspend(struct gsc_dev *gsc) { unsigned long flags; - int timeout; + long time_left; spin_lock_irqsave(&gsc->slock, flags); if (!gsc_m2m_pending(gsc)) { @@ -1236,12 +1236,12 @@ static int gsc_m2m_suspend(struct gsc_dev *gsc) set_bit(ST_M2M_SUSPENDING, &gsc->state); spin_unlock_irqrestore(&gsc->slock, flags); - timeout = wait_event_timeout(gsc->irq_queue, - test_bit(ST_M2M_SUSPENDED, &gsc->state), - GSC_SHUTDOWN_TIMEOUT); + time_left = wait_event_timeout(gsc->irq_queue, + test_bit(ST_M2M_SUSPENDED, &gsc->state), + GSC_SHUTDOWN_TIMEOUT); clear_bit(ST_M2M_SUSPENDING, &gsc->state); - return timeout == 0 ? -EAGAIN : 0; + return time_left == 0 ? -EAGAIN : 0; } static void gsc_m2m_resume(struct gsc_dev *gsc) diff --git a/drivers/media/platform/samsung/exynos4-is/fimc-core.c b/drivers/media/platform/samsung/exynos4-is/fimc-core.c index aae74b501a42..adfc2d73d04b 100644 --- a/drivers/media/platform/samsung/exynos4-is/fimc-core.c +++ b/drivers/media/platform/samsung/exynos4-is/fimc-core.c @@ -822,7 +822,7 @@ err: static int fimc_m2m_suspend(struct fimc_dev *fimc) { unsigned long flags; - int timeout; + long time_left; spin_lock_irqsave(&fimc->slock, flags); if (!fimc_m2m_pending(fimc)) { @@ -833,12 +833,12 @@ static int fimc_m2m_suspend(struct fimc_dev *fimc) set_bit(ST_M2M_SUSPENDING, &fimc->state); spin_unlock_irqrestore(&fimc->slock, flags); - timeout = wait_event_timeout(fimc->irq_queue, - test_bit(ST_M2M_SUSPENDED, &fimc->state), - FIMC_SHUTDOWN_TIMEOUT); + time_left = wait_event_timeout(fimc->irq_queue, + test_bit(ST_M2M_SUSPENDED, &fimc->state), + FIMC_SHUTDOWN_TIMEOUT); clear_bit(ST_M2M_SUSPENDING, &fimc->state); - return timeout == 0 ? -EAGAIN : 0; + return time_left == 0 ? -EAGAIN : 0; } static int fimc_m2m_resume(struct fimc_dev *fimc) diff --git a/drivers/media/platform/st/sti/bdisp/bdisp-v4l2.c b/drivers/media/platform/st/sti/bdisp/bdisp-v4l2.c index 1328b4eb6b9f..c7ee6e1a4451 100644 --- a/drivers/media/platform/st/sti/bdisp/bdisp-v4l2.c +++ b/drivers/media/platform/st/sti/bdisp/bdisp-v4l2.c @@ -1160,7 +1160,7 @@ static void bdisp_irq_timeout(struct work_struct *ptr) static int bdisp_m2m_suspend(struct bdisp_dev *bdisp) { unsigned long flags; - int timeout; + long time_left; spin_lock_irqsave(&bdisp->slock, flags); if (!test_bit(ST_M2M_RUNNING, &bdisp->state)) { @@ -1171,13 +1171,13 @@ static int bdisp_m2m_suspend(struct bdisp_dev *bdisp) set_bit(ST_M2M_SUSPENDING, &bdisp->state); spin_unlock_irqrestore(&bdisp->slock, flags); - timeout = wait_event_timeout(bdisp->irq_queue, - test_bit(ST_M2M_SUSPENDED, &bdisp->state), - BDISP_WORK_TIMEOUT); + time_left = wait_event_timeout(bdisp->irq_queue, + test_bit(ST_M2M_SUSPENDED, &bdisp->state), + BDISP_WORK_TIMEOUT); clear_bit(ST_M2M_SUSPENDING, &bdisp->state); - if (!timeout) { + if (!time_left) { dev_err(bdisp->dev, "%s IRQ timeout\n", __func__); return -EAGAIN; } diff --git a/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c b/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c index 097a3a08ef7d..d07e980aba61 100644 --- a/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c +++ b/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c @@ -35,7 +35,18 @@ struct sun4i_csi_traits { bool has_isp; }; +static int sun4i_csi_video_link_validate(struct media_link *link) +{ + dev_warn_once(link->graph_obj.mdev->dev, + "Driver bug: link validation not implemented\n"); + return 0; +} + static const struct media_entity_operations sun4i_csi_video_entity_ops = { + .link_validate = sun4i_csi_video_link_validate, +}; + +static const struct media_entity_operations sun4i_csi_subdev_entity_ops = { .link_validate = v4l2_subdev_link_validate, }; @@ -214,6 +225,7 @@ static int sun4i_csi_probe(struct platform_device *pdev) subdev->internal_ops = &sun4i_csi_subdev_internal_ops; subdev->flags = V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; subdev->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE; + subdev->entity.ops = &sun4i_csi_subdev_entity_ops; subdev->owner = THIS_MODULE; snprintf(subdev->name, sizeof(subdev->name), "sun4i-csi-0"); v4l2_set_subdevdata(subdev, csi); diff --git a/drivers/media/platform/ti/am437x/am437x-vpfe.c b/drivers/media/platform/ti/am437x/am437x-vpfe.c index 77e12457d149..009ff68a2b43 100644 --- a/drivers/media/platform/ti/am437x/am437x-vpfe.c +++ b/drivers/media/platform/ti/am437x/am437x-vpfe.c @@ -2287,7 +2287,7 @@ static const struct v4l2_async_notifier_operations vpfe_async_ops = { static struct vpfe_config * vpfe_get_pdata(struct vpfe_device *vpfe) { - struct device_node *endpoint = NULL; + struct device_node *endpoint; struct device *dev = vpfe->pdev; struct vpfe_subdev_info *sdinfo; struct vpfe_config *pdata; @@ -2306,14 +2306,11 @@ vpfe_get_pdata(struct vpfe_device *vpfe) if (!pdata) return NULL; - for (i = 0; ; i++) { + i = 0; + for_each_endpoint_of_node(dev->of_node, endpoint) { struct v4l2_fwnode_endpoint bus_cfg = { .bus_type = 0 }; struct device_node *rem; - endpoint = of_graph_get_next_endpoint(dev->of_node, endpoint); - if (!endpoint) - break; - sdinfo = &pdata->sub_devs[i]; sdinfo->grp_id = 0; @@ -2371,9 +2368,10 @@ vpfe_get_pdata(struct vpfe_device *vpfe) of_node_put(rem); if (IS_ERR(pdata->asd[i])) goto cleanup; + + i++; } - of_node_put(endpoint); return pdata; cleanup: diff --git a/drivers/media/platform/ti/cal/cal-camerarx.c b/drivers/media/platform/ti/cal/cal-camerarx.c index 4afc2ad00330..42dfe08b765f 100644 --- a/drivers/media/platform/ti/cal/cal-camerarx.c +++ b/drivers/media/platform/ti/cal/cal-camerarx.c @@ -798,7 +798,7 @@ static const struct v4l2_subdev_internal_ops cal_camerarx_internal_ops = { .init_state = cal_camerarx_sd_init_state, }; -static struct media_entity_operations cal_camerarx_media_ops = { +static const struct media_entity_operations cal_camerarx_media_ops = { .link_validate = v4l2_subdev_link_validate, }; diff --git a/drivers/media/platform/ti/cal/cal.c b/drivers/media/platform/ti/cal/cal.c index 528909ae4bd6..5c2c04142aee 100644 --- a/drivers/media/platform/ti/cal/cal.c +++ b/drivers/media/platform/ti/cal/cal.c @@ -549,7 +549,7 @@ void cal_ctx_start(struct cal_ctx *ctx) void cal_ctx_stop(struct cal_ctx *ctx) { struct cal_camerarx *phy = ctx->phy; - long timeout; + long time_left; WARN_ON(phy->vc_enable_count[ctx->vc] == 0); @@ -565,9 +565,9 @@ void cal_ctx_stop(struct cal_ctx *ctx) ctx->dma.state = CAL_DMA_STOP_REQUESTED; spin_unlock_irq(&ctx->dma.lock); - timeout = wait_event_timeout(ctx->dma.wait, cal_ctx_wr_dma_stopped(ctx), - msecs_to_jiffies(500)); - if (!timeout) { + time_left = wait_event_timeout(ctx->dma.wait, cal_ctx_wr_dma_stopped(ctx), + msecs_to_jiffies(500)); + if (!time_left) { ctx_err(ctx, "failed to disable dma cleanly\n"); cal_ctx_wr_dma_disable(ctx); } diff --git a/drivers/media/platform/ti/davinci/vpif_capture.c b/drivers/media/platform/ti/davinci/vpif_capture.c index c28794b6677b..16326437767f 100644 --- a/drivers/media/platform/ti/davinci/vpif_capture.c +++ b/drivers/media/platform/ti/davinci/vpif_capture.c @@ -1487,7 +1487,7 @@ static struct vpif_capture_config * vpif_capture_get_pdata(struct platform_device *pdev, struct v4l2_device *v4l2_dev) { - struct device_node *endpoint = NULL; + struct device_node *endpoint; struct device_node *rem = NULL; struct vpif_capture_config *pdata; struct vpif_subdev_info *sdinfo; @@ -1517,16 +1517,12 @@ vpif_capture_get_pdata(struct platform_device *pdev, if (!pdata->subdev_info) return NULL; - for (i = 0; i < VPIF_CAPTURE_NUM_CHANNELS; i++) { + i = 0; + for_each_endpoint_of_node(pdev->dev.of_node, endpoint) { struct v4l2_fwnode_endpoint bus_cfg = { .bus_type = 0 }; unsigned int flags; int err; - endpoint = of_graph_get_next_endpoint(pdev->dev.of_node, - endpoint); - if (!endpoint) - break; - rem = of_graph_get_remote_port_parent(endpoint); if (!rem) { dev_dbg(&pdev->dev, "Remote device at %pOF not found\n", @@ -1577,6 +1573,10 @@ vpif_capture_get_pdata(struct platform_device *pdev, goto err_cleanup; of_node_put(rem); + + i++; + if (i >= VPIF_CAPTURE_NUM_CHANNELS) + break; } done: diff --git a/drivers/media/platform/verisilicon/Kconfig b/drivers/media/platform/verisilicon/Kconfig index 149d0b32c324..3272a24db71d 100644 --- a/drivers/media/platform/verisilicon/Kconfig +++ b/drivers/media/platform/verisilicon/Kconfig @@ -21,6 +21,14 @@ config VIDEO_HANTRO To compile this driver as a module, choose M here: the module will be called hantro-vpu. +config VIDEO_HANTRO_HEVC_RFC + bool "Use reference frame compression for HEVC" + depends on VIDEO_HANTRO + default n + help + Enable the reference frame compression feature for the HEVC codec. + It will use more memory but save bandwidth on memory bus. + config VIDEO_HANTRO_IMX8M bool "Hantro VPU i.MX8M support" depends on VIDEO_HANTRO diff --git a/drivers/media/platform/verisilicon/Makefile b/drivers/media/platform/verisilicon/Makefile index eb38a1833b02..f6f019d04ff0 100644 --- a/drivers/media/platform/verisilicon/Makefile +++ b/drivers/media/platform/verisilicon/Makefile @@ -14,13 +14,6 @@ hantro-vpu-y += \ hantro_g2.o \ hantro_g2_hevc_dec.o \ hantro_g2_vp9_dec.o \ - rockchip_vpu2_hw_jpeg_enc.o \ - rockchip_vpu2_hw_h264_dec.o \ - rockchip_vpu2_hw_mpeg2_dec.o \ - rockchip_vpu2_hw_vp8_dec.o \ - rockchip_vpu981_hw_av1_dec.o \ - rockchip_av1_filmgrain.o \ - rockchip_av1_entropymode.o \ hantro_jpeg.o \ hantro_h264.o \ hantro_hevc.o \ @@ -35,6 +28,13 @@ hantro-vpu-$(CONFIG_VIDEO_HANTRO_SAMA5D4) += \ sama5d4_vdec_hw.o hantro-vpu-$(CONFIG_VIDEO_HANTRO_ROCKCHIP) += \ + rockchip_vpu2_hw_jpeg_enc.o \ + rockchip_vpu2_hw_h264_dec.o \ + rockchip_vpu2_hw_mpeg2_dec.o \ + rockchip_vpu2_hw_vp8_dec.o \ + rockchip_vpu981_hw_av1_dec.o \ + rockchip_av1_filmgrain.o \ + rockchip_av1_entropymode.o \ rockchip_vpu_hw.o hantro-vpu-$(CONFIG_VIDEO_HANTRO_SUNXI) += \ diff --git a/drivers/media/platform/verisilicon/hantro_drv.c b/drivers/media/platform/verisilicon/hantro_drv.c index 34b123dafd89..05bbac853c4f 100644 --- a/drivers/media/platform/verisilicon/hantro_drv.c +++ b/drivers/media/platform/verisilicon/hantro_drv.c @@ -722,6 +722,7 @@ static const struct of_device_id of_hantro_match[] = { { .compatible = "rockchip,rk3399-vpu", .data = &rk3399_vpu_variant, }, { .compatible = "rockchip,rk3568-vepu", .data = &rk3568_vepu_variant, }, { .compatible = "rockchip,rk3568-vpu", .data = &rk3568_vpu_variant, }, + { .compatible = "rockchip,rk3588-vepu121", .data = &rk3568_vepu_variant, }, { .compatible = "rockchip,rk3588-av1-vpu", .data = &rk3588_vpu981_variant, }, #endif #ifdef CONFIG_VIDEO_HANTRO_IMX8M @@ -992,6 +993,49 @@ static const struct media_device_ops hantro_m2m_media_ops = { .req_queue = v4l2_m2m_request_queue, }; +/* + * Some SoCs, like RK3588 have multiple identical Hantro cores, but the + * kernel is currently missing support for multi-core handling. Exposing + * separate devices for each core to userspace is bad, since that does + * not allow scheduling tasks properly (and creates ABI). With this workaround + * the driver will only probe for the first core and early exit for the other + * cores. Once the driver gains multi-core support, the same technique + * for detecting the main core can be used to cluster all cores together. + */ +static int hantro_disable_multicore(struct hantro_dev *vpu) +{ + struct device_node *node = NULL; + const char *compatible; + bool is_main_core; + int ret; + + /* Intentionally ignores the fallback strings */ + ret = of_property_read_string(vpu->dev->of_node, "compatible", &compatible); + if (ret) + return ret; + + /* The first compatible and available node found is considered the main core */ + do { + node = of_find_compatible_node(node, NULL, compatible); + if (of_device_is_available(node)) + break; + } while (node); + + if (!node) + return -EINVAL; + + is_main_core = (vpu->dev->of_node == node); + + of_node_put(node); + + if (!is_main_core) { + dev_info(vpu->dev, "missing multi-core support, ignoring this instance\n"); + return -ENODEV; + } + + return 0; +} + static int hantro_probe(struct platform_device *pdev) { const struct of_device_id *match; @@ -1011,6 +1055,10 @@ static int hantro_probe(struct platform_device *pdev) match = of_match_node(of_hantro_match, pdev->dev.of_node); vpu->variant = match->data; + ret = hantro_disable_multicore(vpu); + if (ret) + return ret; + /* * Support for nxp,imx8mq-vpu is kept for backwards compatibility * but it's deprecated. Please update your DTS file to use diff --git a/drivers/media/platform/verisilicon/hantro_g2.c b/drivers/media/platform/verisilicon/hantro_g2.c index b880a6849d58..5c1d799d8618 100644 --- a/drivers/media/platform/verisilicon/hantro_g2.c +++ b/drivers/media/platform/verisilicon/hantro_g2.c @@ -56,3 +56,32 @@ size_t hantro_g2_motion_vectors_offset(struct hantro_ctx *ctx) return ALIGN((cr_offset * 3) / 2, G2_ALIGN); } + +static size_t hantro_g2_mv_size(struct hantro_ctx *ctx) +{ + const struct hantro_hevc_dec_ctrls *ctrls = &ctx->hevc_dec.ctrls; + const struct v4l2_ctrl_hevc_sps *sps = ctrls->sps; + unsigned int pic_width_in_ctbs, pic_height_in_ctbs; + unsigned int max_log2_ctb_size; + + max_log2_ctb_size = sps->log2_min_luma_coding_block_size_minus3 + 3 + + sps->log2_diff_max_min_luma_coding_block_size; + pic_width_in_ctbs = (sps->pic_width_in_luma_samples + + (1 << max_log2_ctb_size) - 1) >> max_log2_ctb_size; + pic_height_in_ctbs = (sps->pic_height_in_luma_samples + (1 << max_log2_ctb_size) - 1) + >> max_log2_ctb_size; + + return pic_width_in_ctbs * pic_height_in_ctbs * (1 << (2 * (max_log2_ctb_size - 4))) * 16; +} + +size_t hantro_g2_luma_compress_offset(struct hantro_ctx *ctx) +{ + return hantro_g2_motion_vectors_offset(ctx) + + hantro_g2_mv_size(ctx); +} + +size_t hantro_g2_chroma_compress_offset(struct hantro_ctx *ctx) +{ + return hantro_g2_luma_compress_offset(ctx) + + hantro_hevc_luma_compressed_size(ctx->dst_fmt.width, ctx->dst_fmt.height); +} diff --git a/drivers/media/platform/verisilicon/hantro_g2_hevc_dec.c b/drivers/media/platform/verisilicon/hantro_g2_hevc_dec.c index d3f8c33eb16c..85a44143b378 100644 --- a/drivers/media/platform/verisilicon/hantro_g2_hevc_dec.c +++ b/drivers/media/platform/verisilicon/hantro_g2_hevc_dec.c @@ -367,11 +367,14 @@ static int set_ref(struct hantro_ctx *ctx) const struct v4l2_ctrl_hevc_decode_params *decode_params = ctrls->decode_params; const struct v4l2_hevc_dpb_entry *dpb = decode_params->dpb; dma_addr_t luma_addr, chroma_addr, mv_addr = 0; + dma_addr_t compress_luma_addr, compress_chroma_addr = 0; struct hantro_dev *vpu = ctx->dev; struct vb2_v4l2_buffer *vb2_dst; struct hantro_decoded_buffer *dst; size_t cr_offset = hantro_g2_chroma_offset(ctx); size_t mv_offset = hantro_g2_motion_vectors_offset(ctx); + size_t compress_luma_offset = hantro_g2_luma_compress_offset(ctx); + size_t compress_chroma_offset = hantro_g2_chroma_compress_offset(ctx); u32 max_ref_frames; u16 dpb_longterm_e; static const struct hantro_reg cur_poc[] = { @@ -445,6 +448,8 @@ static int set_ref(struct hantro_ctx *ctx) chroma_addr = luma_addr + cr_offset; mv_addr = luma_addr + mv_offset; + compress_luma_addr = luma_addr + compress_luma_offset; + compress_chroma_addr = luma_addr + compress_chroma_offset; if (dpb[i].flags & V4L2_HEVC_DPB_ENTRY_LONG_TERM_REFERENCE) dpb_longterm_e |= BIT(V4L2_HEVC_DPB_ENTRIES_NUM_MAX - 1 - i); @@ -452,6 +457,8 @@ static int set_ref(struct hantro_ctx *ctx) hantro_write_addr(vpu, G2_REF_LUMA_ADDR(i), luma_addr); hantro_write_addr(vpu, G2_REF_CHROMA_ADDR(i), chroma_addr); hantro_write_addr(vpu, G2_REF_MV_ADDR(i), mv_addr); + hantro_write_addr(vpu, G2_REF_COMP_LUMA_ADDR(i), compress_luma_addr); + hantro_write_addr(vpu, G2_REF_COMP_CHROMA_ADDR(i), compress_chroma_addr); } vb2_dst = hantro_get_dst_buf(ctx); @@ -465,19 +472,27 @@ static int set_ref(struct hantro_ctx *ctx) chroma_addr = luma_addr + cr_offset; mv_addr = luma_addr + mv_offset; + compress_luma_addr = luma_addr + compress_luma_offset; + compress_chroma_addr = luma_addr + compress_chroma_offset; hantro_write_addr(vpu, G2_REF_LUMA_ADDR(i), luma_addr); hantro_write_addr(vpu, G2_REF_CHROMA_ADDR(i), chroma_addr); - hantro_write_addr(vpu, G2_REF_MV_ADDR(i++), mv_addr); + hantro_write_addr(vpu, G2_REF_MV_ADDR(i), mv_addr); + hantro_write_addr(vpu, G2_REF_COMP_LUMA_ADDR(i), compress_luma_addr); + hantro_write_addr(vpu, G2_REF_COMP_CHROMA_ADDR(i++), compress_chroma_addr); hantro_write_addr(vpu, G2_OUT_LUMA_ADDR, luma_addr); hantro_write_addr(vpu, G2_OUT_CHROMA_ADDR, chroma_addr); hantro_write_addr(vpu, G2_OUT_MV_ADDR, mv_addr); + hantro_write_addr(vpu, G2_OUT_COMP_LUMA_ADDR, compress_luma_addr); + hantro_write_addr(vpu, G2_OUT_COMP_CHROMA_ADDR, compress_chroma_addr); for (; i < V4L2_HEVC_DPB_ENTRIES_NUM_MAX; i++) { hantro_write_addr(vpu, G2_REF_LUMA_ADDR(i), 0); hantro_write_addr(vpu, G2_REF_CHROMA_ADDR(i), 0); hantro_write_addr(vpu, G2_REF_MV_ADDR(i), 0); + hantro_write_addr(vpu, G2_REF_COMP_LUMA_ADDR(i), 0); + hantro_write_addr(vpu, G2_REF_COMP_CHROMA_ADDR(i), 0); } hantro_reg_write(vpu, &g2_refer_lterm_e, dpb_longterm_e); @@ -594,8 +609,7 @@ int hantro_g2_hevc_dec_run(struct hantro_ctx *ctx) /* Don't disable output */ hantro_reg_write(vpu, &g2_out_dis, 0); - /* Don't compress buffers */ - hantro_reg_write(vpu, &g2_ref_compress_bypass, 1); + hantro_reg_write(vpu, &g2_ref_compress_bypass, !ctx->hevc_dec.use_compression); /* Bus width and max burst */ hantro_reg_write(vpu, &g2_buswidth, BUS_WIDTH_128); diff --git a/drivers/media/platform/verisilicon/hantro_g2_regs.h b/drivers/media/platform/verisilicon/hantro_g2_regs.h index 82606783591a..b943b1816db7 100644 --- a/drivers/media/platform/verisilicon/hantro_g2_regs.h +++ b/drivers/media/platform/verisilicon/hantro_g2_regs.h @@ -318,6 +318,10 @@ #define G2_TILE_BSD_ADDR (G2_SWREG(183)) #define G2_DS_DST (G2_SWREG(186)) #define G2_DS_DST_CHR (G2_SWREG(188)) +#define G2_OUT_COMP_LUMA_ADDR (G2_SWREG(190)) +#define G2_REF_COMP_LUMA_ADDR(i) (G2_SWREG(192) + ((i) * 0x8)) +#define G2_OUT_COMP_CHROMA_ADDR (G2_SWREG(224)) +#define G2_REF_COMP_CHROMA_ADDR(i) (G2_SWREG(226) + ((i) * 0x8)) #define g2_strm_buffer_len G2_DEC_REG(258, 0, 0xffffffff) #define g2_strm_start_offset G2_DEC_REG(259, 0, 0xffffffff) diff --git a/drivers/media/platform/verisilicon/hantro_hevc.c b/drivers/media/platform/verisilicon/hantro_hevc.c index 2c14330bc562..83cd12b0ddd6 100644 --- a/drivers/media/platform/verisilicon/hantro_hevc.c +++ b/drivers/media/platform/verisilicon/hantro_hevc.c @@ -25,6 +25,11 @@ #define MAX_TILE_COLS 20 #define MAX_TILE_ROWS 22 +static bool hevc_use_compression = IS_ENABLED(CONFIG_VIDEO_HANTRO_HEVC_RFC); +module_param_named(hevc_use_compression, hevc_use_compression, bool, 0644); +MODULE_PARM_DESC(hevc_use_compression, + "Use reference frame compression for HEVC"); + void hantro_hevc_ref_init(struct hantro_ctx *ctx) { struct hantro_hevc_dec_hw_ctx *hevc_dec = &ctx->hevc_dec; @@ -275,5 +280,8 @@ int hantro_hevc_dec_init(struct hantro_ctx *ctx) hantro_hevc_ref_init(ctx); + hevc_dec->use_compression = + hevc_use_compression & hantro_needs_postproc(ctx, ctx->vpu_dst_fmt); + return 0; } diff --git a/drivers/media/platform/verisilicon/hantro_hw.h b/drivers/media/platform/verisilicon/hantro_hw.h index 7737320cc8cc..c9b6556f8b2b 100644 --- a/drivers/media/platform/verisilicon/hantro_hw.h +++ b/drivers/media/platform/verisilicon/hantro_hw.h @@ -42,6 +42,13 @@ #define MAX_POSTPROC_BUFFERS 64 +#define CBS_SIZE 16 /* compression table size in bytes */ +#define CBS_LUMA 8 /* luminance CBS is composed of 1 8x8 coded block */ +#define CBS_CHROMA_W (8 * 2) /* chrominance CBS is composed of two 8x4 coded + * blocks, with Cb CB first then Cr CB following + */ +#define CBS_CHROMA_H 4 + struct hantro_dev; struct hantro_ctx; struct hantro_buf; @@ -144,6 +151,7 @@ struct hantro_hevc_dec_ctrls { * @ref_bufs_used: Bitfield of used reference buffers * @ctrls: V4L2 controls attached to a run * @num_tile_cols_allocated: number of allocated tiles + * @use_compression: use reference buffer compression */ struct hantro_hevc_dec_hw_ctx { struct hantro_aux_buf tile_sizes; @@ -156,6 +164,7 @@ struct hantro_hevc_dec_hw_ctx { u32 ref_bufs_used; struct hantro_hevc_dec_ctrls ctrls; unsigned int num_tile_cols_allocated; + bool use_compression; }; /** @@ -510,6 +519,33 @@ hantro_hevc_mv_size(unsigned int width, unsigned int height) return width * height / 16; } +static inline size_t +hantro_hevc_luma_compressed_size(unsigned int width, unsigned int height) +{ + u32 pic_width_in_cbsy = + round_up((width + CBS_LUMA - 1) / CBS_LUMA, CBS_SIZE); + u32 pic_height_in_cbsy = (height + CBS_LUMA - 1) / CBS_LUMA; + + return round_up(pic_width_in_cbsy * pic_height_in_cbsy, CBS_SIZE); +} + +static inline size_t +hantro_hevc_chroma_compressed_size(unsigned int width, unsigned int height) +{ + u32 pic_width_in_cbsc = + round_up((width + CBS_CHROMA_W - 1) / CBS_CHROMA_W, CBS_SIZE); + u32 pic_height_in_cbsc = (height / 2 + CBS_CHROMA_H - 1) / CBS_CHROMA_H; + + return round_up(pic_width_in_cbsc * pic_height_in_cbsc, CBS_SIZE); +} + +static inline size_t +hantro_hevc_compressed_size(unsigned int width, unsigned int height) +{ + return hantro_hevc_luma_compressed_size(width, height) + + hantro_hevc_chroma_compressed_size(width, height); +} + static inline unsigned short hantro_av1_num_sbs(unsigned short dimension) { return DIV_ROUND_UP(dimension, 64); @@ -525,6 +561,8 @@ hantro_av1_mv_size(unsigned int width, unsigned int height) size_t hantro_g2_chroma_offset(struct hantro_ctx *ctx); size_t hantro_g2_motion_vectors_offset(struct hantro_ctx *ctx); +size_t hantro_g2_luma_compress_offset(struct hantro_ctx *ctx); +size_t hantro_g2_chroma_compress_offset(struct hantro_ctx *ctx); int hantro_g1_mpeg2_dec_run(struct hantro_ctx *ctx); int rockchip_vpu2_mpeg2_dec_run(struct hantro_ctx *ctx); diff --git a/drivers/media/platform/verisilicon/hantro_postproc.c b/drivers/media/platform/verisilicon/hantro_postproc.c index 41e93176300b..232c93eea7ee 100644 --- a/drivers/media/platform/verisilicon/hantro_postproc.c +++ b/drivers/media/platform/verisilicon/hantro_postproc.c @@ -213,9 +213,13 @@ static unsigned int hantro_postproc_buffer_size(struct hantro_ctx *ctx) else if (ctx->vpu_src_fmt->fourcc == V4L2_PIX_FMT_VP9_FRAME) buf_size += hantro_vp9_mv_size(pix_mp.width, pix_mp.height); - else if (ctx->vpu_src_fmt->fourcc == V4L2_PIX_FMT_HEVC_SLICE) + else if (ctx->vpu_src_fmt->fourcc == V4L2_PIX_FMT_HEVC_SLICE) { buf_size += hantro_hevc_mv_size(pix_mp.width, pix_mp.height); + if (ctx->hevc_dec.use_compression) + buf_size += hantro_hevc_compressed_size(pix_mp.width, + pix_mp.height); + } else if (ctx->vpu_src_fmt->fourcc == V4L2_PIX_FMT_AV1_FRAME) buf_size += hantro_av1_mv_size(pix_mp.width, pix_mp.height); diff --git a/drivers/media/platform/verisilicon/hantro_v4l2.c b/drivers/media/platform/verisilicon/hantro_v4l2.c index df6f2536263b..62d3962c18d9 100644 --- a/drivers/media/platform/verisilicon/hantro_v4l2.c +++ b/drivers/media/platform/verisilicon/hantro_v4l2.c @@ -303,11 +303,7 @@ static int hantro_try_fmt(const struct hantro_ctx *ctx, coded = capture == ctx->is_encoder; - vpu_debug(4, "trying format %c%c%c%c\n", - (pix_mp->pixelformat & 0x7f), - (pix_mp->pixelformat >> 8) & 0x7f, - (pix_mp->pixelformat >> 16) & 0x7f, - (pix_mp->pixelformat >> 24) & 0x7f); + vpu_debug(4, "trying format %p4cc\n", &pix_mp->pixelformat); fmt = hantro_find_format(ctx, pix_mp->pixelformat); if (!fmt) { diff --git a/drivers/media/platform/verisilicon/rockchip_vpu981_hw_av1_dec.c b/drivers/media/platform/verisilicon/rockchip_vpu981_hw_av1_dec.c index cc4483857489..65e8f2d07400 100644 --- a/drivers/media/platform/verisilicon/rockchip_vpu981_hw_av1_dec.c +++ b/drivers/media/platform/verisilicon/rockchip_vpu981_hw_av1_dec.c @@ -257,7 +257,8 @@ static int rockchip_vpu981_av1_dec_tiles_reallocate(struct hantro_ctx *ctx) struct hantro_dev *vpu = ctx->dev; struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls; - unsigned int num_tile_cols = 1 << ctrls->tile_group_entry->tile_col; + const struct v4l2_av1_tile_info *tile_info = &ctrls->frame->tile_info; + unsigned int num_tile_cols = tile_info->tile_cols; unsigned int height = ALIGN(ctrls->frame->frame_height_minus_1 + 1, 64); unsigned int height_in_sb = height / 64; unsigned int stripe_num = ((height + 8) + 63) / 64; diff --git a/drivers/media/platform/verisilicon/rockchip_vpu981_regs.h b/drivers/media/platform/verisilicon/rockchip_vpu981_regs.h index 850ff0f84424..e4008da64f19 100644 --- a/drivers/media/platform/verisilicon/rockchip_vpu981_regs.h +++ b/drivers/media/platform/verisilicon/rockchip_vpu981_regs.h @@ -327,7 +327,7 @@ #define av1_apf_threshold AV1_DEC_REG(55, 0, 0xffff) #define av1_apf_single_pu_mode AV1_DEC_REG(55, 30, 0x1) -#define av1_apf_disable AV1_DEC_REG(55, 30, 0x1) +#define av1_apf_disable AV1_DEC_REG(55, 31, 0x1) #define av1_dec_max_burst AV1_DEC_REG(58, 0, 0xff) #define av1_dec_buswidth AV1_DEC_REG(58, 8, 0x7) @@ -337,10 +337,10 @@ #define av1_dec_mc_polltime AV1_DEC_REG(58, 17, 0x3ff) #define av1_dec_mc_pollmode AV1_DEC_REG(58, 27, 0x3) -#define av1_filt_ref_adj_3 AV1_DEC_REG(59, 0, 0x3f) -#define av1_filt_ref_adj_2 AV1_DEC_REG(59, 7, 0x3f) -#define av1_filt_ref_adj_1 AV1_DEC_REG(59, 14, 0x3f) -#define av1_filt_ref_adj_0 AV1_DEC_REG(59, 21, 0x3f) +#define av1_filt_ref_adj_3 AV1_DEC_REG(59, 0, 0x7f) +#define av1_filt_ref_adj_2 AV1_DEC_REG(59, 7, 0x7f) +#define av1_filt_ref_adj_1 AV1_DEC_REG(59, 14, 0x7f) +#define av1_filt_ref_adj_0 AV1_DEC_REG(59, 21, 0x7f) #define av1_ref0_sign_bias AV1_DEC_REG(59, 28, 0x1) #define av1_ref1_sign_bias AV1_DEC_REG(59, 29, 0x1) #define av1_ref2_sign_bias AV1_DEC_REG(59, 30, 0x1) diff --git a/drivers/media/platform/verisilicon/rockchip_vpu_hw.c b/drivers/media/platform/verisilicon/rockchip_vpu_hw.c index f97527670783..964122e7c355 100644 --- a/drivers/media/platform/verisilicon/rockchip_vpu_hw.c +++ b/drivers/media/platform/verisilicon/rockchip_vpu_hw.c @@ -82,7 +82,6 @@ static const struct hantro_fmt rockchip_vpu981_postproc_fmts[] = { { .fourcc = V4L2_PIX_FMT_NV12, .codec_mode = HANTRO_MODE_NONE, - .match_depth = true, .postprocessed = true, .frmsize = { .min_width = ROCKCHIP_VPU981_MIN_SIZE, diff --git a/drivers/media/platform/xilinx/xilinx-vipp.c b/drivers/media/platform/xilinx/xilinx-vipp.c index 996684a73038..bfe48cc0ab52 100644 --- a/drivers/media/platform/xilinx/xilinx-vipp.c +++ b/drivers/media/platform/xilinx/xilinx-vipp.c @@ -199,18 +199,13 @@ static int xvip_graph_build_dma(struct xvip_composite_device *xdev) struct media_pad *sink_pad; struct xvip_graph_entity *ent; struct v4l2_fwnode_link link; - struct device_node *ep = NULL; + struct device_node *ep; struct xvip_dma *dma; int ret = 0; dev_dbg(xdev->dev, "creating links for DMA engines\n"); - while (1) { - /* Get the next endpoint and parse its link. */ - ep = of_graph_get_next_endpoint(node, ep); - if (ep == NULL) - break; - + for_each_endpoint_of_node(node, ep) { dev_dbg(xdev->dev, "processing endpoint %pOF\n", ep); ret = v4l2_fwnode_parse_link(of_fwnode_handle(ep), &link); |