summaryrefslogtreecommitdiff
path: root/drivers/media/platform/rockchip/rkisp1
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/platform/rockchip/rkisp1')
-rw-r--r--drivers/media/platform/rockchip/rkisp1/Kconfig1
-rw-r--r--drivers/media/platform/rockchip/rkisp1/rkisp1-common.h1
-rw-r--r--drivers/media/platform/rockchip/rkisp1/rkisp1-csi.c4
-rw-r--r--drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c31
-rw-r--r--drivers/media/platform/rockchip/rkisp1/rkisp1-params.c151
5 files changed, 72 insertions, 116 deletions
diff --git a/drivers/media/platform/rockchip/rkisp1/Kconfig b/drivers/media/platform/rockchip/rkisp1/Kconfig
index 731c9acbf6ef..f53eb1f3f3e7 100644
--- a/drivers/media/platform/rockchip/rkisp1/Kconfig
+++ b/drivers/media/platform/rockchip/rkisp1/Kconfig
@@ -10,6 +10,7 @@ config VIDEO_ROCKCHIP_ISP1
select VIDEOBUF2_VMALLOC
select V4L2_FWNODE
select GENERIC_PHY_MIPI_DPHY
+ select V4L2_ISP
default n
help
Enable this to support the Image Signal Processing (ISP) module
diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
index 6028ecdd23de..5e6a4d5f6fd1 100644
--- a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
+++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
@@ -227,6 +227,7 @@ struct rkisp1_isp {
struct media_pad pads[RKISP1_ISP_PAD_MAX];
const struct rkisp1_mbus_info *sink_fmt;
__u32 frame_sequence;
+ bool frame_active;
};
/*
diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-csi.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-csi.c
index 841e58c20f7f..ddc6182f3e4b 100644
--- a/drivers/media/platform/rockchip/rkisp1/rkisp1-csi.c
+++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-csi.c
@@ -368,8 +368,8 @@ static int rkisp1_csi_s_stream(struct v4l2_subdev *sd, int enable)
source_pad = media_entity_remote_source_pad_unique(&sd->entity);
if (IS_ERR(source_pad)) {
- dev_dbg(rkisp1->dev, "Failed to get source for CSI: %ld\n",
- PTR_ERR(source_pad));
+ dev_dbg(rkisp1->dev, "Failed to get source for CSI: %pe\n",
+ source_pad);
return -EPIPE;
}
diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c
index 8c29a1c9309a..2311672cedb1 100644
--- a/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c
+++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c
@@ -936,8 +936,8 @@ static int rkisp1_isp_s_stream(struct v4l2_subdev *sd, int enable)
sink_pad = &isp->pads[RKISP1_ISP_PAD_SINK_VIDEO];
source_pad = media_pad_remote_pad_unique(sink_pad);
if (IS_ERR(source_pad)) {
- dev_dbg(rkisp1->dev, "Failed to get source for ISP: %ld\n",
- PTR_ERR(source_pad));
+ dev_dbg(rkisp1->dev, "Failed to get source for ISP: %pe\n",
+ source_pad);
return -EPIPE;
}
@@ -965,6 +965,7 @@ static int rkisp1_isp_s_stream(struct v4l2_subdev *sd, int enable)
}
isp->frame_sequence = -1;
+ isp->frame_active = false;
sd_state = v4l2_subdev_lock_and_get_active_state(sd);
@@ -1086,12 +1087,15 @@ void rkisp1_isp_unregister(struct rkisp1_device *rkisp1)
* Interrupt handlers
*/
-static void rkisp1_isp_queue_event_sof(struct rkisp1_isp *isp)
+static void rkisp1_isp_sof(struct rkisp1_isp *isp)
{
struct v4l2_event event = {
.type = V4L2_EVENT_FRAME_SYNC,
};
+ isp->frame_sequence++;
+ isp->frame_active = true;
+
event.u.frame_sync.frame_sequence = isp->frame_sequence;
v4l2_event_queue(isp->sd.devnode, &event);
}
@@ -1111,15 +1115,20 @@ irqreturn_t rkisp1_isp_isr(int irq, void *ctx)
rkisp1_write(rkisp1, RKISP1_CIF_ISP_ICR, status);
- /* Vertical sync signal, starting generating new frame */
- if (status & RKISP1_CIF_ISP_V_START) {
- rkisp1->isp.frame_sequence++;
- rkisp1_isp_queue_event_sof(&rkisp1->isp);
+ /*
+ * Vertical sync signal, starting new frame. Defer handling of vsync
+ * after RKISP1_CIF_ISP_FRAME if the previous frame was not completed
+ * yet.
+ */
+ if (status & RKISP1_CIF_ISP_V_START && !rkisp1->isp.frame_active) {
+ status &= ~RKISP1_CIF_ISP_V_START;
+ rkisp1_isp_sof(&rkisp1->isp);
if (status & RKISP1_CIF_ISP_FRAME) {
WARN_ONCE(1, "irq delay is too long, buffers might not be in sync\n");
rkisp1->debug.irq_delay++;
}
}
+
if (status & RKISP1_CIF_ISP_PIC_SIZE_ERROR) {
/* Clear pic_size_error */
isp_err = rkisp1_read(rkisp1, RKISP1_CIF_ISP_ERR);
@@ -1138,6 +1147,7 @@ irqreturn_t rkisp1_isp_isr(int irq, void *ctx)
if (status & RKISP1_CIF_ISP_FRAME) {
u32 isp_ris;
+ rkisp1->isp.frame_active = false;
rkisp1->debug.complete_frames++;
/* New frame from the sensor received */
@@ -1152,5 +1162,12 @@ irqreturn_t rkisp1_isp_isr(int irq, void *ctx)
rkisp1_params_isr(rkisp1);
}
+ /*
+ * Deferred handling of vsync if RKISP1_CIF_ISP_V_START and
+ * RKISP1_CIF_ISP_FRAME occurred in the same irq.
+ */
+ if (status & RKISP1_CIF_ISP_V_START)
+ rkisp1_isp_sof(&rkisp1->isp);
+
return IRQ_HANDLED;
}
diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
index f1585f8fa0f4..c9f88635224c 100644
--- a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
+++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
@@ -6,12 +6,14 @@
*/
#include <linux/bitfield.h>
+#include <linux/build_bug.h>
#include <linux/math.h>
#include <linux/string.h>
#include <media/v4l2-common.h>
#include <media/v4l2-event.h>
#include <media/v4l2-ioctl.h>
+#include <media/v4l2-isp.h>
#include <media/videobuf2-core.h>
#include <media/videobuf2-vmalloc.h> /* for ISP params */
@@ -2097,122 +2099,133 @@ 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,
},
[RKISP1_EXT_PARAMS_BLOCK_TYPE_WDR] = {
- .size = sizeof(struct rkisp1_ext_params_wdr_config),
.handler = rkisp1_ext_params_wdr,
.group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
},
};
+#define RKISP1_PARAMS_BLOCK_INFO(block, data) \
+ [RKISP1_EXT_PARAMS_BLOCK_TYPE_ ## block] = { \
+ .size = sizeof(struct rkisp1_ext_params_ ## data ## _config), \
+ }
+
+static const struct v4l2_isp_params_block_type_info
+rkisp1_ext_params_block_types_info[] = {
+ RKISP1_PARAMS_BLOCK_INFO(BLS, bls),
+ RKISP1_PARAMS_BLOCK_INFO(DPCC, dpcc),
+ RKISP1_PARAMS_BLOCK_INFO(SDG, sdg),
+ RKISP1_PARAMS_BLOCK_INFO(AWB_GAIN, awb_gain),
+ RKISP1_PARAMS_BLOCK_INFO(FLT, flt),
+ RKISP1_PARAMS_BLOCK_INFO(BDM, bdm),
+ RKISP1_PARAMS_BLOCK_INFO(CTK, ctk),
+ RKISP1_PARAMS_BLOCK_INFO(GOC, goc),
+ RKISP1_PARAMS_BLOCK_INFO(DPF, dpf),
+ RKISP1_PARAMS_BLOCK_INFO(DPF_STRENGTH, dpf_strength),
+ RKISP1_PARAMS_BLOCK_INFO(CPROC, cproc),
+ RKISP1_PARAMS_BLOCK_INFO(IE, ie),
+ RKISP1_PARAMS_BLOCK_INFO(LSC, lsc),
+ RKISP1_PARAMS_BLOCK_INFO(AWB_MEAS, awb_meas),
+ RKISP1_PARAMS_BLOCK_INFO(HST_MEAS, hst),
+ RKISP1_PARAMS_BLOCK_INFO(AEC_MEAS, aec),
+ RKISP1_PARAMS_BLOCK_INFO(AFC_MEAS, afc),
+ RKISP1_PARAMS_BLOCK_INFO(COMPAND_BLS, compand_bls),
+ RKISP1_PARAMS_BLOCK_INFO(COMPAND_EXPAND, compand_curve),
+ RKISP1_PARAMS_BLOCK_INFO(COMPAND_COMPRESS, compand_curve),
+ RKISP1_PARAMS_BLOCK_INFO(WDR, wdr),
+};
+
+static_assert(ARRAY_SIZE(rkisp1_ext_params_handlers) ==
+ ARRAY_SIZE(rkisp1_ext_params_block_types_info));
+
static void rkisp1_ext_params_config(struct rkisp1_params *params,
struct rkisp1_ext_params_cfg *cfg,
u32 block_group_mask)
@@ -2646,31 +2659,16 @@ static int rkisp1_params_prepare_ext_params(struct rkisp1_params *params,
{
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;
- }
+ int ret;
- 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;
- }
+ ret = v4l2_isp_params_validate_buffer_size(params->rkisp1->dev, vb,
+ params->metafmt->buffersize);
+ if (ret)
+ return ret;
/*
* Copy the parameters buffer to the internal scratch buffer to avoid
@@ -2678,71 +2676,10 @@ static int rkisp1_params_prepare_ext_params(struct rkisp1_params *params,
*/
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;
+ return v4l2_isp_params_validate_buffer(params->rkisp1->dev, vb,
+ (struct v4l2_isp_params_buffer *)cfg,
+ rkisp1_ext_params_block_types_info,
+ ARRAY_SIZE(rkisp1_ext_params_block_types_info));
}
static int rkisp1_params_vb2_buf_prepare(struct vb2_buffer *vb)