mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-12-27 11:06:41 -05:00
media: amlogic-c3: Use v4l2-isp for validation
Convert c3-isp-params.c to use the helpers defined in v4l2-isp.h to perform validation of a ISP parameters buffer. Reviewed-by: Keke Li <keke.li@amlogic.com> Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com> Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com> Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Tested-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com> Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com> Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
This commit is contained in:
committed by
Hans Verkuil
parent
3a2730a450
commit
9f7d23d558
@@ -10,6 +10,7 @@ config VIDEO_C3_ISP
|
||||
select VIDEO_V4L2_SUBDEV_API
|
||||
select VIDEOBUF2_DMA_CONTIG
|
||||
select VIDEOBUF2_VMALLOC
|
||||
select V4L2_ISP
|
||||
help
|
||||
Video4Linux2 driver for Amlogic C3 ISP pipeline.
|
||||
The C3 ISP is used for processing raw images and
|
||||
|
||||
@@ -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,36 @@ 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_info c3_isp_params_blocks_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_blocks_info));
|
||||
|
||||
static void c3_isp_params_cfg_blocks(struct c3_isp_params *params)
|
||||
{
|
||||
struct c3_isp_params_cfg *config = params->buff->cfg;
|
||||
@@ -568,14 +560,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 +763,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;
|
||||
struct c3_isp_params_cfg *cfg = buf->cfg;
|
||||
int ret;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* 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 +779,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_blocks_info,
|
||||
ARRAY_SIZE(c3_isp_params_blocks_info));
|
||||
}
|
||||
|
||||
static int c3_isp_params_vb2_buf_init(struct vb2_buffer *vb)
|
||||
|
||||
Reference in New Issue
Block a user