diff options
Diffstat (limited to 'drivers/media/platform/amlogic/c3/isp/c3-isp-params.c')
| -rw-r--r-- | drivers/media/platform/amlogic/c3/isp/c3-isp-params.c | 166 |
1 files changed, 44 insertions, 122 deletions
diff --git a/drivers/media/platform/amlogic/c3/isp/c3-isp-params.c b/drivers/media/platform/amlogic/c3/isp/c3-isp-params.c index c80667dd7662..6f9ca7a7dd88 100644 --- a/drivers/media/platform/amlogic/c3/isp/c3-isp-params.c +++ b/drivers/media/platform/amlogic/c3/isp/c3-isp-params.c @@ -3,11 +3,13 @@ * Copyright (C) 2024 Amlogic, Inc. All rights reserved */ +#include <linux/build_bug.h> #include <linux/cleanup.h> #include <linux/media/amlogic/c3-isp-config.h> #include <linux/pm_runtime.h> #include <media/v4l2-ioctl.h> +#include <media/v4l2-isp.h> #include <media/v4l2-mc.h> #include <media/videobuf2-vmalloc.h> @@ -51,11 +53,6 @@ union c3_isp_params_block { typedef void (*c3_isp_block_handler)(struct c3_isp_device *isp, const union c3_isp_params_block *block); -struct c3_isp_params_handler { - size_t size; - c3_isp_block_handler handler; -}; - #define to_c3_isp_params_buffer(vbuf) \ container_of(vbuf, struct c3_isp_params_buffer, vb) @@ -523,41 +520,37 @@ static void c3_isp_params_cfg_blc(struct c3_isp_device *isp, ISP_TOP_BEO_CTRL_BLC_EN); } -static const struct c3_isp_params_handler c3_isp_params_handlers[] = { - [C3_ISP_PARAMS_BLOCK_AWB_GAINS] = { - .size = sizeof(struct c3_isp_params_awb_gains), - .handler = c3_isp_params_cfg_awb_gains, - }, - [C3_ISP_PARAMS_BLOCK_AWB_CONFIG] = { - .size = sizeof(struct c3_isp_params_awb_config), - .handler = c3_isp_params_cfg_awb_config, - }, - [C3_ISP_PARAMS_BLOCK_AE_CONFIG] = { - .size = sizeof(struct c3_isp_params_ae_config), - .handler = c3_isp_params_cfg_ae_config, - }, - [C3_ISP_PARAMS_BLOCK_AF_CONFIG] = { - .size = sizeof(struct c3_isp_params_af_config), - .handler = c3_isp_params_cfg_af_config, - }, - [C3_ISP_PARAMS_BLOCK_PST_GAMMA] = { - .size = sizeof(struct c3_isp_params_pst_gamma), - .handler = c3_isp_params_cfg_pst_gamma, - }, - [C3_ISP_PARAMS_BLOCK_CCM] = { - .size = sizeof(struct c3_isp_params_ccm), - .handler = c3_isp_params_cfg_ccm, - }, - [C3_ISP_PARAMS_BLOCK_CSC] = { - .size = sizeof(struct c3_isp_params_csc), - .handler = c3_isp_params_cfg_csc, - }, - [C3_ISP_PARAMS_BLOCK_BLC] = { - .size = sizeof(struct c3_isp_params_blc), - .handler = c3_isp_params_cfg_blc, - }, +static const c3_isp_block_handler c3_isp_params_handlers[] = { + [C3_ISP_PARAMS_BLOCK_AWB_GAINS] = c3_isp_params_cfg_awb_gains, + [C3_ISP_PARAMS_BLOCK_AWB_CONFIG] = c3_isp_params_cfg_awb_config, + [C3_ISP_PARAMS_BLOCK_AE_CONFIG] = c3_isp_params_cfg_ae_config, + [C3_ISP_PARAMS_BLOCK_AF_CONFIG] = c3_isp_params_cfg_af_config, + [C3_ISP_PARAMS_BLOCK_PST_GAMMA] = c3_isp_params_cfg_pst_gamma, + [C3_ISP_PARAMS_BLOCK_CCM] = c3_isp_params_cfg_ccm, + [C3_ISP_PARAMS_BLOCK_CSC] = c3_isp_params_cfg_csc, + [C3_ISP_PARAMS_BLOCK_BLC] = c3_isp_params_cfg_blc, +}; + +#define C3_ISP_PARAMS_BLOCK_INFO(block, data) \ + [C3_ISP_PARAMS_BLOCK_ ## block] = { \ + .size = sizeof(struct c3_isp_params_ ## data), \ + } + +static const struct v4l2_isp_params_block_type_info +c3_isp_params_block_types_info[] = { + C3_ISP_PARAMS_BLOCK_INFO(AWB_GAINS, awb_gains), + C3_ISP_PARAMS_BLOCK_INFO(AWB_CONFIG, awb_config), + C3_ISP_PARAMS_BLOCK_INFO(AE_CONFIG, ae_config), + C3_ISP_PARAMS_BLOCK_INFO(AF_CONFIG, af_config), + C3_ISP_PARAMS_BLOCK_INFO(PST_GAMMA, pst_gamma), + C3_ISP_PARAMS_BLOCK_INFO(CCM, ccm), + C3_ISP_PARAMS_BLOCK_INFO(CSC, csc), + C3_ISP_PARAMS_BLOCK_INFO(BLC, blc), }; +static_assert(ARRAY_SIZE(c3_isp_params_handlers) == + ARRAY_SIZE(c3_isp_params_block_types_info)); + static void c3_isp_params_cfg_blocks(struct c3_isp_params *params) { struct c3_isp_params_cfg *config = params->buff->cfg; @@ -568,14 +561,14 @@ static void c3_isp_params_cfg_blocks(struct c3_isp_params *params) /* Walk the list of parameter blocks and process them */ while (block_offset < config->data_size) { - const struct c3_isp_params_handler *block_handler; const union c3_isp_params_block *block; + c3_isp_block_handler block_handler; block = (const union c3_isp_params_block *) &config->data[block_offset]; - block_handler = &c3_isp_params_handlers[block->header.type]; - block_handler->handler(params->isp, block); + block_handler = c3_isp_params_handlers[block->header.type]; + block_handler(params->isp, block); block_offset += block->header.size; } @@ -771,26 +764,15 @@ static int c3_isp_params_vb2_buf_prepare(struct vb2_buffer *vb) struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct c3_isp_params_buffer *buf = to_c3_isp_params_buffer(vbuf); struct c3_isp_params *params = vb2_get_drv_priv(vb->vb2_queue); - struct c3_isp_params_cfg *cfg = buf->cfg; struct c3_isp_params_cfg *usr_cfg = vb2_plane_vaddr(vb, 0); size_t payload_size = vb2_get_plane_payload(vb, 0); - size_t header_size = offsetof(struct c3_isp_params_cfg, data); - size_t block_offset = 0; - size_t cfg_size; - - /* Payload size can't be greater than the destination buffer size */ - if (payload_size > params->vfmt.fmt.meta.buffersize) { - dev_dbg(params->isp->dev, - "Payload size is too large: %zu\n", payload_size); - return -EINVAL; - } + struct c3_isp_params_cfg *cfg = buf->cfg; + int ret; - /* Payload size can't be smaller than the header size */ - if (payload_size < header_size) { - dev_dbg(params->isp->dev, - "Payload size is too small: %zu\n", payload_size); - return -EINVAL; - } + ret = v4l2_isp_params_validate_buffer_size(params->isp->dev, vb, + params->vfmt.fmt.meta.buffersize); + if (ret) + return ret; /* * Use the internal scratch buffer to avoid userspace modifying @@ -798,70 +780,10 @@ static int c3_isp_params_vb2_buf_prepare(struct vb2_buffer *vb) */ memcpy(cfg, usr_cfg, payload_size); - /* Only v0 is supported at the moment */ - if (cfg->version != C3_ISP_PARAMS_BUFFER_V0) { - dev_dbg(params->isp->dev, - "Invalid params buffer version: %u\n", cfg->version); - return -EINVAL; - } - - /* Validate the size reported in the parameter buffer header */ - cfg_size = header_size + cfg->data_size; - if (cfg_size != payload_size) { - dev_dbg(params->isp->dev, - "Data size %zu and payload size %zu are different\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 c3_isp_params_block_header)) { - const struct c3_isp_params_block_header *block; - const struct c3_isp_params_handler *handler; - - block = (struct c3_isp_params_block_header *) - &cfg->data[block_offset]; - - if (block->type >= ARRAY_SIZE(c3_isp_params_handlers)) { - dev_dbg(params->isp->dev, - "Invalid params block type\n"); - return -EINVAL; - } - - if (block->size > cfg_size) { - dev_dbg(params->isp->dev, - "Block size is greater than cfg size\n"); - return -EINVAL; - } - - if ((block->flags & (C3_ISP_PARAMS_BLOCK_FL_ENABLE | - C3_ISP_PARAMS_BLOCK_FL_DISABLE)) == - (C3_ISP_PARAMS_BLOCK_FL_ENABLE | - C3_ISP_PARAMS_BLOCK_FL_DISABLE)) { - dev_dbg(params->isp->dev, - "Invalid parameters block flags\n"); - return -EINVAL; - } - - handler = &c3_isp_params_handlers[block->type]; - if (block->size != handler->size) { - dev_dbg(params->isp->dev, - "Invalid params block size\n"); - return -EINVAL; - } - - block_offset += block->size; - cfg_size -= block->size; - } - - if (cfg_size) { - dev_dbg(params->isp->dev, - "Unexpected data after the params buffer end\n"); - return -EINVAL; - } - - return 0; + return v4l2_isp_params_validate_buffer(params->isp->dev, vb, + (struct v4l2_isp_params_buffer *)cfg, + c3_isp_params_block_types_info, + ARRAY_SIZE(c3_isp_params_block_types_info)); } static int c3_isp_params_vb2_buf_init(struct vb2_buffer *vb) |
