diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2021-09-01 20:34:52 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2021-09-01 20:34:52 +0300 |
commit | 835d31d319d9c8c4eb6cac074643360ba0ecab10 (patch) | |
tree | 824dc6286c3f34357de0a0c12d0311eca9a6da8d /drivers/media/platform | |
parent | 0d290223a6c77107b1c3988959e49279a8dafaba (diff) | |
parent | 9c3a0f285248899dfa81585bc5d5bc9ebdb8fead (diff) | |
download | linux-835d31d319d9c8c4eb6cac074643360ba0ecab10.tar.xz |
Merge tag 'media/v5.15-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media updates from Mauro Carvalho Chehab:
- new sensor drivers: imx335, imx412, ov9282
- new IR transmitter driver: meson-ir-tx
- handro driver gained support for H.264 for Rockchip VDPU2
- imx gained support for i.MX8MQ
- ti-vpe has gained support for other SoC variants
- lots of cleanups, fixes, board additions and doc improvements
* tag 'media/v5.15-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (195 commits)
media: venus: venc: add support for V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM control
media: venus: venc: Add support for intra-refresh period
media: v4l2-ctrls: Add intra-refresh period control
media: docs: ext-ctrls-codec: Document cyclic intra-refresh zero control value
media: venus: helper: do not set constrained parameters for UBWC
media: venus: venc: Fix potential null pointer dereference on pointer fmt
media: venus: hfi: fix return value check in sys_get_prop_image_version()
media: tegra-cec: Handle errors of clk_prepare_enable()
media: cec-pin: rename timer overrun variables
media: TDA1997x: report -ENOLINK after disconnecting HDMI source
media: TDA1997x: fix tda1997x_query_dv_timings() return value
media: Fix cosmetic error in TDA1997x driver
media: v4l2-dv-timings.c: fix wrong condition in two for-loops
media: imx: add a driver for i.MX8MQ mipi csi rx phy and controller
media: dt-bindings: media: document the nxp,imx8mq-mipi-csi2 receiver phy and controller
media: imx: imx7_mipi_csis: convert some switch cases to the default
media: imx: imx7-media-csi: Fix buffer return upon stream start failure
media: imx: imx7-media-csi: Don't set PIXEL_BIT in CSICR1
media: imx: imx7-media-csi: Set TWO_8BIT_SENSOR for >= 10-bit formats
media: dt-bindings: media: nxp,imx7-csi: Add i.MX8MM support
...
Diffstat (limited to 'drivers/media/platform')
27 files changed, 697 insertions, 344 deletions
diff --git a/drivers/media/platform/atmel/atmel-sama5d2-isc.c b/drivers/media/platform/atmel/atmel-sama5d2-isc.c index 925aa80a139b..b66f1d174e9d 100644 --- a/drivers/media/platform/atmel/atmel-sama5d2-isc.c +++ b/drivers/media/platform/atmel/atmel-sama5d2-isc.c @@ -255,6 +255,23 @@ static void isc_sama5d2_config_rlp(struct isc_device *isc) struct regmap *regmap = isc->regmap; u32 rlp_mode = isc->config.rlp_cfg_mode; + /* + * In sama5d2, the YUV planar modes and the YUYV modes are treated + * in the same way in RLP register. + * Normally, YYCC mode should be Luma(n) - Color B(n) - Color R (n) + * and YCYC should be Luma(n + 1) - Color B (n) - Luma (n) - Color R (n) + * but in sama5d2, the YCYC mode does not exist, and YYCC must be + * selected for both planar and interleaved modes, as in fact + * both modes are supported. + * + * Thus, if the YCYC mode is selected, replace it with the + * sama5d2-compliant mode which is YYCC . + */ + if ((rlp_mode & ISC_RLP_CFG_MODE_YCYC) == ISC_RLP_CFG_MODE_YCYC) { + rlp_mode &= ~ISC_RLP_CFG_MODE_MASK; + rlp_mode |= ISC_RLP_CFG_MODE_YYCC; + } + regmap_update_bits(regmap, ISC_RLP_CFG + isc->offsets.rlp, ISC_RLP_CFG_MODE_MASK, rlp_mode); } diff --git a/drivers/media/platform/coda/coda-bit.c b/drivers/media/platform/coda/coda-bit.c index 2f42808c43a4..c484c008ab02 100644 --- a/drivers/media/platform/coda/coda-bit.c +++ b/drivers/media/platform/coda/coda-bit.c @@ -2053,17 +2053,25 @@ static int __coda_start_decoding(struct coda_ctx *ctx) u32 src_fourcc, dst_fourcc; int ret; + q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); + q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); + src_fourcc = q_data_src->fourcc; + dst_fourcc = q_data_dst->fourcc; + if (!ctx->initialized) { ret = __coda_decoder_seq_init(ctx); if (ret < 0) return ret; + } else { + ctx->frame_mem_ctrl &= ~(CODA_FRAME_CHROMA_INTERLEAVE | (0x3 << 9) | + CODA9_FRAME_TILED2LINEAR); + if (dst_fourcc == V4L2_PIX_FMT_NV12 || dst_fourcc == V4L2_PIX_FMT_YUYV) + ctx->frame_mem_ctrl |= CODA_FRAME_CHROMA_INTERLEAVE; + if (ctx->tiled_map_type == GDI_TILED_FRAME_MB_RASTER_MAP) + ctx->frame_mem_ctrl |= (0x3 << 9) | + ((ctx->use_vdoa) ? 0 : CODA9_FRAME_TILED2LINEAR); } - q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); - q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); - src_fourcc = q_data_src->fourcc; - dst_fourcc = q_data_dst->fourcc; - coda_write(dev, ctx->parabuf.paddr, CODA_REG_BIT_PARA_BUF_ADDR); ret = coda_alloc_framebuffers(ctx, q_data_dst, src_fourcc); diff --git a/drivers/media/platform/davinci/vpfe_capture.c b/drivers/media/platform/davinci/vpfe_capture.c index f9f7dd17c57c..0a2226b321d7 100644 --- a/drivers/media/platform/davinci/vpfe_capture.c +++ b/drivers/media/platform/davinci/vpfe_capture.c @@ -189,7 +189,7 @@ int vpfe_register_ccdc_device(const struct ccdc_hw_device *dev) if (!ccdc_cfg) { /* * TODO. Will this ever happen? if so, we need to fix it. - * Proabably we need to add the request to a linked list and + * Probably we need to add the request to a linked list and * walk through it during vpfe probe */ printk(KERN_ERR "vpfe capture not initialized\n"); diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c index 3b8a24bb724c..fa648721eaab 100644 --- a/drivers/media/platform/exynos4-is/media-dev.c +++ b/drivers/media/platform/exynos4-is/media-dev.c @@ -1238,8 +1238,8 @@ static const struct media_device_ops fimc_md_ops = { .link_notify = fimc_md_link_notify, }; -static ssize_t fimc_md_sysfs_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t subdev_conf_mode_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct fimc_md *fmd = dev_get_drvdata(dev); @@ -1249,9 +1249,9 @@ static ssize_t fimc_md_sysfs_show(struct device *dev, return strscpy(buf, "V4L2 video node only API (vid-dev)\n", PAGE_SIZE); } -static ssize_t fimc_md_sysfs_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t subdev_conf_mode_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { struct fimc_md *fmd = dev_get_drvdata(dev); bool subdev_api; @@ -1278,8 +1278,7 @@ static ssize_t fimc_md_sysfs_store(struct device *dev, * sub-dev - for media controller API, subdevs must be configured in user * space before starting streaming. */ -static DEVICE_ATTR(subdev_conf_mode, S_IWUSR | S_IRUGO, - fimc_md_sysfs_show, fimc_md_sysfs_store); +static DEVICE_ATTR_RW(subdev_conf_mode); static int cam_clk_prepare(struct clk_hw *hw) { diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c index 070a0f3fc337..58f9463f3b8c 100644 --- a/drivers/media/platform/marvell-ccic/mcam-core.c +++ b/drivers/media/platform/marvell-ccic/mcam-core.c @@ -692,7 +692,7 @@ static void mcam_dma_sg_done(struct mcam_camera *cam, int frame) * Scatter/gather mode requires stopping the controller between * frames so we can put in a new DMA descriptor array. If no new * buffer exists at frame completion, the controller is left stopped; - * this function is charged with gettig things going again. + * this function is charged with getting things going again. */ static void mcam_sg_restart(struct mcam_camera *cam) { diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c index 53025c8c7531..20f59c59ff8a 100644 --- a/drivers/media/platform/omap3isp/isp.c +++ b/drivers/media/platform/omap3isp/isp.c @@ -2037,8 +2037,10 @@ static int isp_subdev_notifier_complete(struct v4l2_async_notifier *async) mutex_lock(&isp->media_dev.graph_mutex); ret = media_entity_enum_init(&isp->crashed, &isp->media_dev); - if (ret) + if (ret) { + mutex_unlock(&isp->media_dev.graph_mutex); return ret; + } list_for_each_entry(sd, &v4l2_dev->subdevs, list) { if (sd->notifier != &isp->notifier) diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h index 8df2d497d706..5ec851115eca 100644 --- a/drivers/media/platform/qcom/venus/core.h +++ b/drivers/media/platform/qcom/venus/core.h @@ -234,6 +234,7 @@ struct venc_controls { u32 h264_loop_filter_mode; s32 h264_loop_filter_alpha; s32 h264_loop_filter_beta; + u32 h264_8x8_transform; u32 hevc_i_qp; u32 hevc_p_qp; @@ -256,6 +257,7 @@ struct venc_controls { u32 header_mode; bool aud_enable; + u32 intra_refresh_period; struct { u32 h264; diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index 1fe6d463dc99..8012f5c7bf34 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -1137,6 +1137,9 @@ int venus_helper_set_format_constraints(struct venus_inst *inst) if (!IS_V6(inst->core)) return 0; + if (inst->opb_fmt == HFI_COLOR_FORMAT_NV12_UBWC) + return 0; + pconstraint.buffer_type = HFI_BUFFER_OUTPUT2; pconstraint.num_planes = 2; pconstraint.plane_format[0].stride_multiples = 128; diff --git a/drivers/media/platform/qcom/venus/hfi_cmds.c b/drivers/media/platform/qcom/venus/hfi_cmds.c index f51024786991..60f4b8e4b8d0 100644 --- a/drivers/media/platform/qcom/venus/hfi_cmds.c +++ b/drivers/media/platform/qcom/venus/hfi_cmds.c @@ -1239,6 +1239,14 @@ pkt_session_set_property_4xx(struct hfi_session_set_property_pkt *pkt, break; } + case HFI_PROPERTY_PARAM_VENC_H264_TRANSFORM_8X8: { + struct hfi_h264_8x8_transform *in = pdata, *tm = prop_data; + + tm->enable_type = in->enable_type; + pkt->shdr.hdr.size += sizeof(u32) + sizeof(*tm); + break; + } + case HFI_PROPERTY_CONFIG_VENC_MAX_BITRATE: case HFI_PROPERTY_CONFIG_VDEC_POST_LOOP_DEBLOCKER: case HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE: diff --git a/drivers/media/platform/qcom/venus/hfi_helper.h b/drivers/media/platform/qcom/venus/hfi_helper.h index b0a9beb4163c..bec4feb63ceb 100644 --- a/drivers/media/platform/qcom/venus/hfi_helper.h +++ b/drivers/media/platform/qcom/venus/hfi_helper.h @@ -507,6 +507,7 @@ #define HFI_PROPERTY_PARAM_VENC_MAX_NUM_B_FRAMES 0x2005020 #define HFI_PROPERTY_PARAM_VENC_H264_VUI_BITSTREAM_RESTRC 0x2005021 #define HFI_PROPERTY_PARAM_VENC_PRESERVE_TEXT_QUALITY 0x2005023 +#define HFI_PROPERTY_PARAM_VENC_H264_TRANSFORM_8X8 0x2005025 #define HFI_PROPERTY_PARAM_VENC_HIER_P_MAX_NUM_ENH_LAYER 0x2005026 #define HFI_PROPERTY_PARAM_VENC_DISABLE_RC_TIMESTAMP 0x2005027 #define HFI_PROPERTY_PARAM_VENC_INITIAL_QP 0x2005028 @@ -562,6 +563,10 @@ struct hfi_bitrate { u32 layer_id; }; +struct hfi_h264_8x8_transform { + u32 enable_type; +}; + #define HFI_CAPABILITY_FRAME_WIDTH 0x01 #define HFI_CAPABILITY_FRAME_HEIGHT 0x02 #define HFI_CAPABILITY_MBS_PER_FRAME 0x03 diff --git a/drivers/media/platform/qcom/venus/hfi_msgs.c b/drivers/media/platform/qcom/venus/hfi_msgs.c index d9fde66f6fa8..9a2bdb002edc 100644 --- a/drivers/media/platform/qcom/venus/hfi_msgs.c +++ b/drivers/media/platform/qcom/venus/hfi_msgs.c @@ -261,7 +261,7 @@ sys_get_prop_image_version(struct device *dev, smem_tbl_ptr = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_IMG_VER_TBL, &smem_blk_sz); - if (smem_tbl_ptr && smem_blk_sz >= SMEM_IMG_OFFSET_VENUS + VER_STR_SZ) + if (!IS_ERR(smem_tbl_ptr) && smem_blk_sz >= SMEM_IMG_OFFSET_VENUS + VER_STR_SZ) memcpy(smem_tbl_ptr + SMEM_IMG_OFFSET_VENUS, img_ver, VER_STR_SZ); } diff --git a/drivers/media/platform/qcom/venus/venc.c b/drivers/media/platform/qcom/venus/venc.c index 8dd49d4f124c..bc1c42dd53c0 100644 --- a/drivers/media/platform/qcom/venus/venc.c +++ b/drivers/media/platform/qcom/venus/venc.c @@ -183,6 +183,8 @@ venc_try_fmt_common(struct venus_inst *inst, struct v4l2_format *f) else return NULL; fmt = find_format(inst, pixmp->pixelformat, f->type); + if (!fmt) + return NULL; } pixmp->width = clamp(pixmp->width, frame_width_min(inst), @@ -547,6 +549,7 @@ static int venc_set_properties(struct venus_inst *inst) struct hfi_quantization_range quant_range; struct hfi_enable en; struct hfi_ltr_mode ltr_mode; + struct hfi_intra_refresh intra_refresh = {}; u32 ptype, rate_control, bitrate; u32 profile, level; int ret; @@ -567,6 +570,7 @@ static int venc_set_properties(struct venus_inst *inst) struct hfi_h264_vui_timing_info info; struct hfi_h264_entropy_control entropy; struct hfi_h264_db_control deblock; + struct hfi_h264_8x8_transform h264_transform; ptype = HFI_PROPERTY_PARAM_VENC_H264_VUI_TIMING_INFO; info.enable = 1; @@ -597,6 +601,17 @@ static int venc_set_properties(struct venus_inst *inst) ret = hfi_session_set_property(inst, ptype, &deblock); if (ret) return ret; + + ptype = HFI_PROPERTY_PARAM_VENC_H264_TRANSFORM_8X8; + h264_transform.enable_type = 0; + if (ctr->profile.h264 == HFI_H264_PROFILE_HIGH || + ctr->profile.h264 == HFI_H264_PROFILE_CONSTRAINED_HIGH) + h264_transform.enable_type = ctr->h264_8x8_transform; + + ret = hfi_session_set_property(inst, ptype, &h264_transform); + if (ret) + return ret; + } if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_H264 || @@ -802,6 +817,31 @@ static int venc_set_properties(struct venus_inst *inst) en.enable = 1; ret = hfi_session_set_property(inst, ptype, &en); + } + + if ((inst->fmt_cap->pixfmt == V4L2_PIX_FMT_H264 || + inst->fmt_cap->pixfmt == V4L2_PIX_FMT_HEVC) && + (rate_control == HFI_RATE_CONTROL_CBR_VFR || + rate_control == HFI_RATE_CONTROL_CBR_CFR)) { + intra_refresh.mode = HFI_INTRA_REFRESH_NONE; + intra_refresh.cir_mbs = 0; + + if (ctr->intra_refresh_period) { + u32 mbs; + + mbs = ALIGN(inst->width, 16) * ALIGN(inst->height, 16); + mbs /= 16 * 16; + if (mbs % ctr->intra_refresh_period) + mbs++; + mbs /= ctr->intra_refresh_period; + + intra_refresh.mode = HFI_INTRA_REFRESH_RANDOM; + intra_refresh.cir_mbs = mbs; + } + + ptype = HFI_PROPERTY_PARAM_VENC_INTRA_REFRESH; + + ret = hfi_session_set_property(inst, ptype, &intra_refresh); if (ret) return ret; } diff --git a/drivers/media/platform/qcom/venus/venc_ctrls.c b/drivers/media/platform/qcom/venus/venc_ctrls.c index 637c92f6c5be..1ada42df314d 100644 --- a/drivers/media/platform/qcom/venus/venc_ctrls.c +++ b/drivers/media/platform/qcom/venus/venc_ctrls.c @@ -17,7 +17,6 @@ #define SLICE_BYTE_SIZE_MAX 1024 #define SLICE_BYTE_SIZE_MIN 1024 #define SLICE_MB_SIZE_MAX 300 -#define INTRA_REFRESH_MBS_MAX 300 #define AT_SLICE_BOUNDARY \ V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY #define MAX_LTR_FRAME_COUNT 4 @@ -227,8 +226,6 @@ static int venc_op_s_ctrl(struct v4l2_ctrl *ctrl) } mutex_unlock(&inst->lock); break; - case V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB: - break; case V4L2_CID_MPEG_VIDEO_GOP_SIZE: ret = venc_calc_bpframes(ctrl->val, ctr->num_b_frames, &bframes, &ctr->num_p_frames); @@ -319,6 +316,28 @@ static int venc_op_s_ctrl(struct v4l2_ctrl *ctrl) case V4L2_CID_COLORIMETRY_HDR10_MASTERING_DISPLAY: ctr->mastering = *ctrl->p_new.p_hdr10_mastering; break; + case V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD: + ctr->intra_refresh_period = ctrl->val; + break; + case V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM: + if (ctr->profile.h264 != HFI_H264_PROFILE_HIGH && + ctr->profile.h264 != HFI_H264_PROFILE_CONSTRAINED_HIGH) + return -EINVAL; + + /* + * In video firmware, 8x8 transform is supported only for + * high profile(HP) and constrained high profile(CHP). + * If client wants to disable 8x8 transform for HP/CHP, + * it is better to set profile as main profile(MP). + * Because there is no difference between HP and MP + * if we disable 8x8 transform for HP. + */ + + if (ctrl->val == 0) + return -EINVAL; + + ctr->h264_8x8_transform = ctrl->val; + break; default: return -EINVAL; } @@ -334,7 +353,7 @@ int venc_ctrl_init(struct venus_inst *inst) { int ret; - ret = v4l2_ctrl_handler_init(&inst->ctrl_handler, 57); + ret = v4l2_ctrl_handler_init(&inst->ctrl_handler, 58); if (ret) return ret; @@ -438,6 +457,9 @@ int venc_ctrl_init(struct venus_inst *inst) V4L2_CID_MPEG_VIDEO_H264_I_FRAME_MIN_QP, 1, 51, 1, 1); v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops, + V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM, 0, 1, 1, 0); + + v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops, V4L2_CID_MPEG_VIDEO_H264_P_FRAME_MIN_QP, 1, 51, 1, 1); v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops, @@ -503,10 +525,6 @@ int venc_ctrl_init(struct venus_inst *inst) V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA, -6, 6, 1, 0); v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops, - V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB, - 0, INTRA_REFRESH_MBS_MAX, 1, 0); - - v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops, V4L2_CID_MPEG_VIDEO_GOP_SIZE, 0, (1 << 16) - 1, 1, 30); v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops, @@ -564,6 +582,10 @@ int venc_ctrl_init(struct venus_inst *inst) V4L2_CID_COLORIMETRY_HDR10_MASTERING_DISPLAY, v4l2_ctrl_ptr_create(NULL)); + v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops, + V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD, 0, + ((4096 * 2304) >> 8), 1, 0); + ret = inst->ctrl_handler.error; if (ret) goto err; diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c b/drivers/media/platform/rcar-vin/rcar-v4l2.c index cca15a10c0b3..0d141155f0e3 100644 --- a/drivers/media/platform/rcar-vin/rcar-v4l2.c +++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c @@ -253,8 +253,8 @@ static int rvin_try_format(struct rvin_dev *vin, u32 which, int ret; sd_state = v4l2_subdev_alloc_state(sd); - if (sd_state == NULL) - return -ENOMEM; + if (IS_ERR(sd_state)) + return PTR_ERR(sd_state); if (!rvin_format_from_pixel(vin, pix->pixelformat)) pix->pixelformat = RVIN_DEFAULT_FORMAT; diff --git a/drivers/media/platform/rockchip/rga/rga.c b/drivers/media/platform/rockchip/rga/rga.c index bf3fd71ec3af..6759091b15e0 100644 --- a/drivers/media/platform/rockchip/rga/rga.c +++ b/drivers/media/platform/rockchip/rga/rga.c @@ -863,12 +863,12 @@ static int rga_probe(struct platform_device *pdev) if (IS_ERR(rga->m2m_dev)) { v4l2_err(&rga->v4l2_dev, "Failed to init mem2mem device\n"); ret = PTR_ERR(rga->m2m_dev); - goto unreg_video_dev; + goto rel_vdev; } ret = pm_runtime_resume_and_get(rga->dev); if (ret < 0) - goto unreg_video_dev; + goto rel_vdev; rga->version.major = (rga_read(rga, RGA_VERSION_INFO) >> 24) & 0xFF; rga->version.minor = (rga_read(rga, RGA_VERSION_INFO) >> 20) & 0x0F; @@ -882,11 +882,23 @@ static int rga_probe(struct platform_device *pdev) rga->cmdbuf_virt = dma_alloc_attrs(rga->dev, RGA_CMDBUF_SIZE, &rga->cmdbuf_phy, GFP_KERNEL, DMA_ATTR_WRITE_COMBINE); + if (!rga->cmdbuf_virt) { + ret = -ENOMEM; + goto rel_vdev; + } rga->src_mmu_pages = (unsigned int *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 3); + if (!rga->src_mmu_pages) { + ret = -ENOMEM; + goto free_dma; + } rga->dst_mmu_pages = (unsigned int *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 3); + if (rga->dst_mmu_pages) { + ret = -ENOMEM; + goto free_src_pages; + } def_frame.stride = (def_frame.width * def_frame.fmt->depth) >> 3; def_frame.size = def_frame.stride * def_frame.height; @@ -894,7 +906,7 @@ static int rga_probe(struct platform_device *pdev) ret = video_register_device(vfd, VFL_TYPE_VIDEO, -1); if (ret) { v4l2_err(&rga->v4l2_dev, "Failed to register video device\n"); - goto rel_vdev; + goto free_dst_pages; } v4l2_info(&rga->v4l2_dev, "Registered %s as /dev/%s\n", @@ -902,10 +914,15 @@ static int rga_probe(struct platform_device *pdev) return 0; +free_dst_pages: + free_pages((unsigned long)rga->dst_mmu_pages, 3); +free_src_pages: + free_pages((unsigned long)rga->src_mmu_pages, 3); +free_dma: + dma_free_attrs(rga->dev, RGA_CMDBUF_SIZE, rga->cmdbuf_virt, + rga->cmdbuf_phy, DMA_ATTR_WRITE_COMBINE); rel_vdev: video_device_release(vfd); -unreg_video_dev: - video_unregister_device(rga->vfd); unreg_v4l2_dev: v4l2_device_unregister(&rga->v4l2_dev); err_put_clk: diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-capture.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-capture.c index 60cd2200e7ae..41988eb0ec0a 100644 --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-capture.c +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-capture.c @@ -750,7 +750,7 @@ static int rkisp1_vb2_queue_setup(struct vb2_queue *queue, return 0; } -static void rkisp1_vb2_buf_queue(struct vb2_buffer *vb) +static int rkisp1_vb2_buf_init(struct vb2_buffer *vb) { struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct rkisp1_buffer *ispbuf = @@ -780,6 +780,15 @@ static void rkisp1_vb2_buf_queue(struct vb2_buffer *vb) if (cap->pix.info->comp_planes == 3 && cap->pix.cfg->uv_swap) swap(ispbuf->buff_addr[RKISP1_PLANE_CR], ispbuf->buff_addr[RKISP1_PLANE_CB]); + return 0; +} + +static void rkisp1_vb2_buf_queue(struct vb2_buffer *vb) +{ + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct rkisp1_buffer *ispbuf = + container_of(vbuf, struct rkisp1_buffer, vb); + struct rkisp1_capture *cap = vb->vb2_queue->drv_priv; spin_lock_irq(&cap->buf.lock); list_add_tail(&ispbuf->queue, &cap->buf.queue); @@ -1039,6 +1048,7 @@ err_ret_buffers: static const struct vb2_ops rkisp1_vb2_ops = { .queue_setup = rkisp1_vb2_queue_setup, + .buf_init = rkisp1_vb2_buf_init, .buf_queue = rkisp1_vb2_buf_queue, .buf_prepare = rkisp1_vb2_buf_prepare, .wait_prepare = vb2_ops_wait_prepare, diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h index 038c303a8aed..bb73f4e17b66 100644 --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h @@ -156,15 +156,11 @@ struct rkisp1_vdev_node { * @vb: vb2 buffer * @queue: entry of the buffer in the queue * @buff_addr: dma addresses of each plane, used only by the capture devices: selfpath, mainpath - * @vaddr: virtual address for buffers used by params and stats devices */ struct rkisp1_buffer { struct vb2_v4l2_buffer vb; struct list_head queue; - union { - u32 buff_addr[VIDEO_MAX_PLANES]; - void *vaddr; - }; + u32 buff_addr[VIDEO_MAX_PLANES]; }; /* diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c index 529c6e21815f..8fa5b0abf1f9 100644 --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c @@ -1143,7 +1143,7 @@ static void rkisp1_params_apply_params_cfg(struct rkisp1_params *params, cur_buf = list_first_entry(¶ms->params, struct rkisp1_buffer, queue); - new_params = (struct rkisp1_params_cfg *)(cur_buf->vaddr); + new_params = (struct rkisp1_params_cfg *)vb2_plane_vaddr(&cur_buf->vb.vb2_buf, 0); rkisp1_isp_isr_other_config(params, new_params); rkisp1_isp_isr_meas_config(params, new_params); @@ -1382,7 +1382,6 @@ static void rkisp1_params_vb2_buf_queue(struct vb2_buffer *vb) struct vb2_queue *vq = vb->vb2_queue; struct rkisp1_params *params = vq->drv_priv; - params_buf->vaddr = vb2_plane_vaddr(vb, 0); spin_lock_irq(¶ms->config_lock); list_add_tail(¶ms_buf->queue, ¶ms->params); spin_unlock_irq(¶ms->config_lock); diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-stats.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-stats.c index c1d07a2e8839..e88bdd612d71 100644 --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-stats.c +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-stats.c @@ -112,7 +112,6 @@ static void rkisp1_stats_vb2_buf_queue(struct vb2_buffer *vb) struct vb2_queue *vq = vb->vb2_queue; struct rkisp1_stats *stats_dev = vq->drv_priv; - stats_buf->vaddr = vb2_plane_vaddr(vb, 0); spin_lock_irq(&stats_dev->lock); list_add_tail(&stats_buf->queue, &stats_dev->stat); @@ -305,9 +304,8 @@ rkisp1_stats_send_measurement(struct rkisp1_stats *stats, u32 isp_ris) if (!cur_buf) return; - cur_stat_buf = - (struct rkisp1_stat_buffer *)(cur_buf->vaddr); - + cur_stat_buf = (struct rkisp1_stat_buffer *) + vb2_plane_vaddr(&cur_buf->vb.vb2_buf, 0); if (isp_ris & RKISP1_CIF_ISP_AWB_DONE) rkisp1_stats_get_awb_meas(stats, cur_stat_buf); diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c index 49503c20d320..28a06dc343fd 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c @@ -1418,7 +1418,7 @@ static void s5p_mfc_try_run_v5(struct s5p_mfc_dev *dev) if (test_and_clear_bit(0, &dev->hw_lock) == 0) mfc_err("Failed to unlock hardware\n"); - /* This is in deed imporant, as no operation has been + /* This is indeed important, as no operation has been * scheduled, reduce the clock count as no one will * ever do this, because no interrupt related to this try_run * will ever come from hardware. */ diff --git a/drivers/media/platform/sti/delta/delta-ipc.c b/drivers/media/platform/sti/delta/delta-ipc.c index 186d88f02ecd..21d3e08e259a 100644 --- a/drivers/media/platform/sti/delta/delta-ipc.c +++ b/drivers/media/platform/sti/delta/delta-ipc.c @@ -175,8 +175,7 @@ int delta_ipc_open(struct delta_ctx *pctx, const char *name, msg.ipc_buf_size = ipc_buf_size; msg.ipc_buf_paddr = ctx->ipc_buf->paddr; - memcpy(msg.name, name, sizeof(msg.name)); - msg.name[sizeof(msg.name) - 1] = 0; + strscpy(msg.name, name, sizeof(msg.name)); msg.param_size = param->size; memcpy(ctx->ipc_buf->vaddr, param->data, msg.param_size); diff --git a/drivers/media/platform/ti-vpe/cal-camerarx.c b/drivers/media/platform/ti-vpe/cal-camerarx.c index 124a4e2bdefe..4bf7a8c2e711 100644 --- a/drivers/media/platform/ti-vpe/cal-camerarx.c +++ b/drivers/media/platform/ti-vpe/cal-camerarx.c @@ -45,22 +45,30 @@ static inline void camerarx_write(struct cal_camerarx *phy, u32 offset, u32 val) * ------------------------------------------------------------------ */ -static s64 cal_camerarx_get_external_rate(struct cal_camerarx *phy) +static s64 cal_camerarx_get_ext_link_freq(struct cal_camerarx *phy) { - struct v4l2_ctrl *ctrl; - s64 rate; - - ctrl = v4l2_ctrl_find(phy->sensor->ctrl_handler, V4L2_CID_PIXEL_RATE); - if (!ctrl) { - phy_err(phy, "no pixel rate control in subdev: %s\n", - phy->sensor->name); - return -EPIPE; + struct v4l2_fwnode_bus_mipi_csi2 *mipi_csi2 = &phy->endpoint.bus.mipi_csi2; + u32 num_lanes = mipi_csi2->num_data_lanes; + const struct cal_format_info *fmtinfo; + u32 bpp; + s64 freq; + + fmtinfo = cal_format_by_code(phy->formats[CAL_CAMERARX_PAD_SINK].code); + if (!fmtinfo) + return -EINVAL; + + bpp = fmtinfo->bpp; + + freq = v4l2_get_link_freq(phy->source->ctrl_handler, bpp, 2 * num_lanes); + if (freq < 0) { + phy_err(phy, "failed to get link freq for subdev '%s'\n", + phy->source->name); + return freq; } - rate = v4l2_ctrl_g_ctrl_int64(ctrl); - phy_dbg(3, phy, "sensor Pixel Rate: %llu\n", rate); + phy_dbg(3, phy, "Source Link Freq: %llu\n", freq); - return rate; + return freq; } static void cal_camerarx_lane_config(struct cal_camerarx *phy) @@ -116,34 +124,19 @@ void cal_camerarx_disable(struct cal_camerarx *phy) #define TCLK_MISS 1 #define TCLK_SETTLE 14 -static void cal_camerarx_config(struct cal_camerarx *phy, s64 external_rate) +static void cal_camerarx_config(struct cal_camerarx *phy, s64 link_freq) { unsigned int reg0, reg1; unsigned int ths_term, ths_settle; - unsigned int csi2_ddrclk_khz; - struct v4l2_fwnode_bus_mipi_csi2 *mipi_csi2 = - &phy->endpoint.bus.mipi_csi2; - u32 num_lanes = mipi_csi2->num_data_lanes; /* DPHY timing configuration */ - /* - * CSI-2 is DDR and we only count used lanes. - * - * csi2_ddrclk_khz = external_rate / 1000 - * / (2 * num_lanes) * phy->fmtinfo->bpp; - */ - csi2_ddrclk_khz = div_s64(external_rate * phy->fmtinfo->bpp, - 2 * num_lanes * 1000); - - phy_dbg(1, phy, "csi2_ddrclk_khz: %d\n", csi2_ddrclk_khz); - /* THS_TERM: Programmed value = floor(20 ns/DDRClk period) */ - ths_term = 20 * csi2_ddrclk_khz / 1000000; + ths_term = div_s64(20 * link_freq, 1000 * 1000 * 1000); phy_dbg(1, phy, "ths_term: %d (0x%02x)\n", ths_term, ths_term); /* THS_SETTLE: Programmed value = floor(105 ns/DDRClk period) + 4 */ - ths_settle = (105 * csi2_ddrclk_khz / 1000000) + 4; + ths_settle = div_s64(105 * link_freq, 1000 * 1000 * 1000) + 4; phy_dbg(1, phy, "ths_settle: %d (0x%02x)\n", ths_settle, ths_settle); reg0 = camerarx_read(phy, CAL_CSI2_PHY_REG0); @@ -240,25 +233,42 @@ static void cal_camerarx_enable_irqs(struct cal_camerarx *phy) CAL_CSI2_COMPLEXIO_IRQ_FIFO_OVR_MASK | CAL_CSI2_COMPLEXIO_IRQ_SHORT_PACKET_MASK | CAL_CSI2_COMPLEXIO_IRQ_ECC_NO_CORRECTION_MASK; - - /* Enable CIO error IRQs. */ + const u32 vc_err_mask = + CAL_CSI2_VC_IRQ_CS_IRQ_MASK(0) | + CAL_CSI2_VC_IRQ_CS_IRQ_MASK(1) | + CAL_CSI2_VC_IRQ_CS_IRQ_MASK(2) | + CAL_CSI2_VC_IRQ_CS_IRQ_MASK(3) | + CAL_CSI2_VC_IRQ_ECC_CORRECTION_IRQ_MASK(0) | + CAL_CSI2_VC_IRQ_ECC_CORRECTION_IRQ_MASK(1) | + CAL_CSI2_VC_IRQ_ECC_CORRECTION_IRQ_MASK(2) | + CAL_CSI2_VC_IRQ_ECC_CORRECTION_IRQ_MASK(3); + + /* Enable CIO & VC error IRQs. */ cal_write(phy->cal, CAL_HL_IRQENABLE_SET(0), - CAL_HL_IRQ_CIO_MASK(phy->instance)); + CAL_HL_IRQ_CIO_MASK(phy->instance) | + CAL_HL_IRQ_VC_MASK(phy->instance)); cal_write(phy->cal, CAL_CSI2_COMPLEXIO_IRQENABLE(phy->instance), cio_err_mask); + cal_write(phy->cal, CAL_CSI2_VC_IRQENABLE(phy->instance), + vc_err_mask); } static void cal_camerarx_disable_irqs(struct cal_camerarx *phy) { /* Disable CIO error irqs */ cal_write(phy->cal, CAL_HL_IRQENABLE_CLR(0), - CAL_HL_IRQ_CIO_MASK(phy->instance)); + CAL_HL_IRQ_CIO_MASK(phy->instance) | + CAL_HL_IRQ_VC_MASK(phy->instance)); cal_write(phy->cal, CAL_CSI2_COMPLEXIO_IRQENABLE(phy->instance), 0); + cal_write(phy->cal, CAL_CSI2_VC_IRQENABLE(phy->instance), 0); } static void cal_camerarx_ppi_enable(struct cal_camerarx *phy) { cal_write_field(phy->cal, CAL_CSI2_PPI_CTRL(phy->instance), + 1, CAL_CSI2_PPI_CTRL_ECC_EN_MASK); + + cal_write_field(phy->cal, CAL_CSI2_PPI_CTRL(phy->instance), 1, CAL_CSI2_PPI_CTRL_IF_EN_MASK); } @@ -270,16 +280,21 @@ static void cal_camerarx_ppi_disable(struct cal_camerarx *phy) static int cal_camerarx_start(struct cal_camerarx *phy) { - s64 external_rate; + s64 link_freq; u32 sscounter; u32 val; int ret; - external_rate = cal_camerarx_get_external_rate(phy); - if (external_rate < 0) - return external_rate; + if (phy->enable_count > 0) { + phy->enable_count++; + return 0; + } + + link_freq = cal_camerarx_get_ext_link_freq(phy); + if (link_freq < 0) + return link_freq; - ret = v4l2_subdev_call(phy->sensor, core, s_power, 1); + ret = v4l2_subdev_call(phy->source, core, s_power, 1); if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV) { phy_err(phy, "power on failed in subdev\n"); return ret; @@ -311,7 +326,7 @@ static int cal_camerarx_start(struct cal_camerarx *phy) * 2. CSI PHY and link initialization sequence. * * a. Deassert the CSI-2 PHY reset. Do not wait for reset completion - * at this point, as it requires the external sensor to send the + * at this point, as it requires the external source to send the * CSI-2 HS clock. */ cal_write_field(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance), @@ -325,7 +340,7 @@ static int cal_camerarx_start(struct cal_camerarx *phy) camerarx_read(phy, CAL_CSI2_PHY_REG0); /* Program the PHY timing parameters. */ - cal_camerarx_config(phy, external_rate); + cal_camerarx_config(phy, link_freq); /* * b. Assert the FORCERXMODE signal. @@ -370,12 +385,12 @@ static int cal_camerarx_start(struct cal_camerarx *phy) cal_camerarx_power(phy, true); /* - * Start the sensor to enable the CSI-2 HS clock. We can now wait for + * Start the source to enable the CSI-2 HS clock. We can now wait for * CSI-2 PHY reset to complete. */ - ret = v4l2_subdev_call(phy->sensor, video, s_stream, 1); + ret = v4l2_subdev_call(phy->source, video, s_stream, 1); if (ret) { - v4l2_subdev_call(phy->sensor, core, s_power, 0); + v4l2_subdev_call(phy->source, core, s_power, 0); cal_camerarx_disable_irqs(phy); phy_err(phy, "stream on failed in subdev\n"); return ret; @@ -399,14 +414,18 @@ static int cal_camerarx_start(struct cal_camerarx *phy) /* Finally, enable the PHY Protocol Interface (PPI). */ cal_camerarx_ppi_enable(phy); + phy->enable_count++; + return 0; } static void cal_camerarx_stop(struct cal_camerarx *phy) { - unsigned int i; int ret; + if (--phy->enable_count > 0) + return; + cal_camerarx_ppi_disable(phy); cal_camerarx_disable_irqs(phy); @@ -418,27 +437,17 @@ static void cal_camerarx_stop(struct cal_camerarx *phy) CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL, CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL_MASK); - /* Wait for power down completion */ - for (i = 0; i < 10; i++) { - if (cal_read_field(phy->cal, - CAL_CSI2_COMPLEXIO_CFG(phy->instance), - CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_MASK) == - CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_RESETONGOING) - break; - usleep_range(1000, 1100); - } - phy_dbg(3, phy, "CAL_CSI2_COMPLEXIO_CFG(%d) = 0x%08x Complex IO in Reset (%d) %s\n", + phy_dbg(3, phy, "CAL_CSI2_COMPLEXIO_CFG(%d) = 0x%08x Complex IO in Reset\n", phy->instance, - cal_read(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance)), i, - (i >= 10) ? "(timeout)" : ""); + cal_read(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance))); /* Disable the phy */ cal_camerarx_disable(phy); - if (v4l2_subdev_call(phy->sensor, video, s_stream, 0)) + if (v4l2_subdev_call(phy->source, video, s_stream, 0)) phy_err(phy, "stream off failed in subdev\n"); - ret = v4l2_subdev_call(phy->sensor, core, s_power, 0); + ret = v4l2_subdev_call(phy->source, core, s_power, 0); if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV) phy_err(phy, "power off failed in subdev\n"); } @@ -558,16 +567,16 @@ static int cal_camerarx_parse_dt(struct cal_camerarx *phy) endpoint->bus.mipi_csi2.flags); /* Retrieve the connected device and store it for later use. */ - phy->sensor_ep_node = of_graph_get_remote_endpoint(ep_node); - phy->sensor_node = of_graph_get_port_parent(phy->sensor_ep_node); - if (!phy->sensor_node) { + phy->source_ep_node = of_graph_get_remote_endpoint(ep_node); + phy->source_node = of_graph_get_port_parent(phy->source_ep_node); + if (!phy->source_node) { phy_dbg(3, phy, "Can't get remote parent\n"); - of_node_put(phy->sensor_ep_node); + of_node_put(phy->source_ep_node); ret = -EINVAL; goto done; } - phy_dbg(1, phy, "Found connected device %pOFn\n", phy->sensor_node); + phy_dbg(1, phy, "Found connected device %pOFn\n", phy->source_node); done: of_node_put(ep_node); @@ -602,12 +611,18 @@ cal_camerarx_get_pad_format(struct cal_camerarx *phy, static int cal_camerarx_sd_s_stream(struct v4l2_subdev *sd, int enable) { struct cal_camerarx *phy = to_cal_camerarx(sd); + int ret = 0; + + mutex_lock(&phy->mutex); if (enable) - return cal_camerarx_start(phy); + ret = cal_camerarx_start(phy); + else + cal_camerarx_stop(phy); - cal_camerarx_stop(phy); - return 0; + mutex_unlock(&phy->mutex); + + return ret; } static int cal_camerarx_sd_enum_mbus_code(struct v4l2_subdev *sd, @@ -615,27 +630,36 @@ static int cal_camerarx_sd_enum_mbus_code(struct v4l2_subdev *sd, struct v4l2_subdev_mbus_code_enum *code) { struct cal_camerarx *phy = to_cal_camerarx(sd); + int ret = 0; + + mutex_lock(&phy->mutex); /* No transcoding, source and sink codes must match. */ - if (code->pad == CAL_CAMERARX_PAD_SOURCE) { + if (cal_rx_pad_is_source(code->pad)) { struct v4l2_mbus_framefmt *fmt; - if (code->index > 0) - return -EINVAL; + if (code->index > 0) { + ret = -EINVAL; + goto out; + } fmt = cal_camerarx_get_pad_format(phy, sd_state, CAL_CAMERARX_PAD_SINK, code->which); code->code = fmt->code; - return 0; - } + } else { + if (code->index >= cal_num_formats) { + ret = -EINVAL; + goto out; + } - if (code->index >= cal_num_formats) - return -EINVAL; + code->code = cal_formats[code->index].code; + } - code->code = cal_formats[code->index].code; +out: + mutex_unlock(&phy->mutex); - return 0; + return ret; } static int cal_camerarx_sd_enum_frame_size(struct v4l2_subdev *sd, @@ -644,38 +668,46 @@ static int cal_camerarx_sd_enum_frame_size(struct v4l2_subdev *sd, { struct cal_camerarx *phy = to_cal_camerarx(sd); const struct cal_format_info *fmtinfo; + int ret = 0; if (fse->index > 0) return -EINVAL; + mutex_lock(&phy->mutex); + /* No transcoding, source and sink formats must match. */ - if (fse->pad == CAL_CAMERARX_PAD_SOURCE) { + if (cal_rx_pad_is_source(fse->pad)) { struct v4l2_mbus_framefmt *fmt; fmt = cal_camerarx_get_pad_format(phy, sd_state, CAL_CAMERARX_PAD_SINK, fse->which); - if (fse->code != fmt->code) - return -EINVAL; + if (fse->code != fmt->code) { + ret = -EINVAL; + goto out; + } fse->min_width = fmt->width; fse->max_width = fmt->width; fse->min_height = fmt->height; fse->max_height = fmt->height; + } else { + fmtinfo = cal_format_by_code(fse->code); + if (!fmtinfo) { + ret = -EINVAL; + goto out; + } - return 0; + fse->min_width = CAL_MIN_WIDTH_BYTES * 8 / ALIGN(fmtinfo->bpp, 8); + fse->max_width = CAL_MAX_WIDTH_BYTES * 8 / ALIGN(fmtinfo->bpp, 8); + fse->min_height = CAL_MIN_HEIGHT_LINES; + fse->max_height = CAL_MAX_HEIGHT_LINES; } - fmtinfo = cal_format_by_code(fse->code); - if (!fmtinfo) - return -EINVAL; - - fse->min_width = CAL_MIN_WIDTH_BYTES * 8 / ALIGN(fmtinfo->bpp, 8); - fse->max_width = CAL_MAX_WIDTH_BYTES * 8 / ALIGN(fmtinfo->bpp, 8); - fse->min_height = CAL_MIN_HEIGHT_LINES; - fse->max_height = CAL_MAX_HEIGHT_LINES; +out: + mutex_unlock(&phy->mutex); - return 0; + return ret; } static int cal_camerarx_sd_get_fmt(struct v4l2_subdev *sd, @@ -685,10 +717,14 @@ static int cal_camerarx_sd_get_fmt(struct v4l2_subdev *sd, struct cal_camerarx *phy = to_cal_camerarx(sd); struct v4l2_mbus_framefmt *fmt; + mutex_lock(&phy->mutex); + fmt = cal_camerarx_get_pad_format(phy, sd_state, format->pad, format->which); format->format = *fmt; + mutex_unlock(&phy->mutex); + return 0; } @@ -702,21 +738,18 @@ static int cal_camerarx_sd_set_fmt(struct v4l2_subdev *sd, unsigned int bpp; /* No transcoding, source and sink formats must match. */ - if (format->pad == CAL_CAMERARX_PAD_SOURCE) + if (cal_rx_pad_is_source(format->pad)) return cal_camerarx_sd_get_fmt(sd, sd_state, format); /* - * Default to the first format is the requested media bus code isn't + * Default to the first format if the requested media bus code isn't * supported. */ fmtinfo = cal_format_by_code(format->format.code); if (!fmtinfo) fmtinfo = &cal_formats[0]; - /* - * Clamp the size, update the code. The field and colorspace are - * accepted as-is. - */ + /* Clamp the size, update the code. The colorspace is accepted as-is. */ bpp = ALIGN(fmtinfo->bpp, 8); format->format.width = clamp_t(unsigned int, format->format.width, @@ -726,20 +759,23 @@ static int cal_camerarx_sd_set_fmt(struct v4l2_subdev *sd, CAL_MIN_HEIGHT_LINES, CAL_MAX_HEIGHT_LINES); format->format.code = fmtinfo->code; + format->format.field = V4L2_FIELD_NONE; /* Store the format and propagate it to the source pad. */ + + mutex_lock(&phy->mutex); + fmt = cal_camerarx_get_pad_format(phy, sd_state, CAL_CAMERARX_PAD_SINK, format->which); *fmt = format->format; fmt = cal_camerarx_get_pad_format(phy, sd_state, - CAL_CAMERARX_PAD_SOURCE, + CAL_CAMERARX_PAD_FIRST_SOURCE, format->which); *fmt = format->format; - if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) - phy->fmtinfo = fmtinfo; + mutex_unlock(&phy->mutex); return 0; } @@ -798,6 +834,7 @@ struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal, struct platform_device *pdev = to_platform_device(cal->dev); struct cal_camerarx *phy; struct v4l2_subdev *sd; + unsigned int i; int ret; phy = kzalloc(sizeof(*phy), GFP_KERNEL); @@ -807,6 +844,8 @@ struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal, phy->cal = cal; phy->instance = instance; + mutex_init(&phy->mutex); + phy->res = platform_get_resource_byname(pdev, IORESOURCE_MEM, (instance == 0) ? "cal_rx_core0" : @@ -838,14 +877,17 @@ struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal, sd->dev = cal->dev; phy->pads[CAL_CAMERARX_PAD_SINK].flags = MEDIA_PAD_FL_SINK; - phy->pads[CAL_CAMERARX_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; + for (i = CAL_CAMERARX_PAD_FIRST_SOURCE; i < CAL_CAMERARX_NUM_PADS; ++i) + phy->pads[i].flags = MEDIA_PAD_FL_SOURCE; sd->entity.ops = &cal_camerarx_media_ops; ret = media_entity_pads_init(&sd->entity, ARRAY_SIZE(phy->pads), phy->pads); if (ret) goto error; - cal_camerarx_sd_init_cfg(sd, NULL); + ret = cal_camerarx_sd_init_cfg(sd, NULL); + if (ret) + goto error; ret = v4l2_device_register_subdev(&cal->v4l2_dev, sd); if (ret) @@ -866,7 +908,8 @@ void cal_camerarx_destroy(struct cal_camerarx *phy) v4l2_device_unregister_subdev(&phy->subdev); media_entity_cleanup(&phy->subdev.entity); - of_node_put(phy->sensor_ep_node); - of_node_put(phy->sensor_node); + of_node_put(phy->source_ep_node); + of_node_put(phy->source_node); + mutex_destroy(&phy->mutex); kfree(phy); } diff --git a/drivers/media/platform/ti-vpe/cal-video.c b/drivers/media/platform/ti-vpe/cal-video.c index 15fb5360cf13..7799da1cc261 100644 --- a/drivers/media/platform/ti-vpe/cal-video.c +++ b/drivers/media/platform/ti-vpe/cal-video.c @@ -102,8 +102,8 @@ static const struct cal_format_info *find_format_by_code(struct cal_ctx *ctx, return NULL; } -static int cal_enum_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_fmtdesc *f) +static int cal_legacy_enum_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_fmtdesc *f) { struct cal_ctx *ctx = video_drvdata(file); const struct cal_format_info *fmtinfo; @@ -128,7 +128,7 @@ static int __subdev_get_format(struct cal_ctx *ctx, sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; sd_fmt.pad = 0; - ret = v4l2_subdev_call(ctx->phy->sensor, pad, get_fmt, NULL, &sd_fmt); + ret = v4l2_subdev_call(ctx->phy->source, pad, get_fmt, NULL, &sd_fmt); if (ret) return ret; @@ -151,7 +151,7 @@ static int __subdev_set_format(struct cal_ctx *ctx, sd_fmt.pad = 0; *mbus_fmt = *fmt; - ret = v4l2_subdev_call(ctx->phy->sensor, pad, set_fmt, NULL, &sd_fmt); + ret = v4l2_subdev_call(ctx->phy->source, pad, set_fmt, NULL, &sd_fmt); if (ret) return ret; @@ -189,8 +189,8 @@ static void cal_calc_format_size(struct cal_ctx *ctx, f->fmt.pix.bytesperline, f->fmt.pix.sizeimage); } -static int cal_try_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) +static int cal_legacy_try_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) { struct cal_ctx *ctx = video_drvdata(file); const struct cal_format_info *fmtinfo; @@ -216,7 +216,7 @@ static int cal_try_fmt_vid_cap(struct file *file, void *priv, fse.code = fmtinfo->code; fse.which = V4L2_SUBDEV_FORMAT_ACTIVE; for (fse.index = 0; ; fse.index++) { - ret = v4l2_subdev_call(ctx->phy->sensor, pad, enum_frame_size, + ret = v4l2_subdev_call(ctx->phy->source, pad, enum_frame_size, NULL, &fse); if (ret) break; @@ -249,8 +249,8 @@ static int cal_try_fmt_vid_cap(struct file *file, void *priv, return 0; } -static int cal_s_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) +static int cal_legacy_s_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) { struct cal_ctx *ctx = video_drvdata(file); struct vb2_queue *q = &ctx->vb_vidq; @@ -266,7 +266,7 @@ static int cal_s_fmt_vid_cap(struct file *file, void *priv, return -EBUSY; } - ret = cal_try_fmt_vid_cap(file, priv, f); + ret = cal_legacy_try_fmt_vid_cap(file, priv, f); if (ret < 0) return ret; @@ -300,8 +300,8 @@ static int cal_s_fmt_vid_cap(struct file *file, void *priv, return 0; } -static int cal_enum_framesizes(struct file *file, void *fh, - struct v4l2_frmsizeenum *fsize) +static int cal_legacy_enum_framesizes(struct file *file, void *fh, + struct v4l2_frmsizeenum *fsize) { struct cal_ctx *ctx = video_drvdata(file); const struct cal_format_info *fmtinfo; @@ -321,7 +321,7 @@ static int cal_enum_framesizes(struct file *file, void *fh, fse.code = fmtinfo->code; fse.which = V4L2_SUBDEV_FORMAT_ACTIVE; - ret = v4l2_subdev_call(ctx->phy->sensor, pad, enum_frame_size, NULL, + ret = v4l2_subdev_call(ctx->phy->source, pad, enum_frame_size, NULL, &fse); if (ret) return ret; @@ -337,8 +337,8 @@ static int cal_enum_framesizes(struct file *file, void *fh, return 0; } -static int cal_enum_input(struct file *file, void *priv, - struct v4l2_input *inp) +static int cal_legacy_enum_input(struct file *file, void *priv, + struct v4l2_input *inp) { if (inp->index > 0) return -EINVAL; @@ -348,20 +348,20 @@ static int cal_enum_input(struct file *file, void *priv, return 0; } -static int cal_g_input(struct file *file, void *priv, unsigned int *i) +static int cal_legacy_g_input(struct file *file, void *priv, unsigned int *i) { *i = 0; return 0; } -static int cal_s_input(struct file *file, void *priv, unsigned int i) +static int cal_legacy_s_input(struct file *file, void *priv, unsigned int i) { return i > 0 ? -EINVAL : 0; } /* timeperframe is arbitrary and continuous */ -static int cal_enum_frameintervals(struct file *file, void *priv, - struct v4l2_frmivalenum *fival) +static int cal_legacy_enum_frameintervals(struct file *file, void *priv, + struct v4l2_frmivalenum *fival) { struct cal_ctx *ctx = video_drvdata(file); const struct cal_format_info *fmtinfo; @@ -378,7 +378,7 @@ static int cal_enum_frameintervals(struct file *file, void *priv, return -EINVAL; fie.code = fmtinfo->code; - ret = v4l2_subdev_call(ctx->phy->sensor, pad, enum_frame_interval, + ret = v4l2_subdev_call(ctx->phy->source, pad, enum_frame_interval, NULL, &fie); if (ret) return ret; @@ -388,13 +388,27 @@ static int cal_enum_frameintervals(struct file *file, void *priv, return 0; } -static const struct v4l2_ioctl_ops cal_ioctl_video_ops = { +static int cal_legacy_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a) +{ + struct cal_ctx *ctx = video_drvdata(file); + + return v4l2_g_parm_cap(video_devdata(file), ctx->phy->source, a); +} + +static int cal_legacy_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a) +{ + struct cal_ctx *ctx = video_drvdata(file); + + return v4l2_s_parm_cap(video_devdata(file), ctx->phy->source, a); +} + +static const struct v4l2_ioctl_ops cal_ioctl_legacy_ops = { .vidioc_querycap = cal_querycap, - .vidioc_enum_fmt_vid_cap = cal_enum_fmt_vid_cap, + .vidioc_enum_fmt_vid_cap = cal_legacy_enum_fmt_vid_cap, .vidioc_g_fmt_vid_cap = cal_g_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = cal_try_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = cal_s_fmt_vid_cap, - .vidioc_enum_framesizes = cal_enum_framesizes, + .vidioc_try_fmt_vid_cap = cal_legacy_try_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = cal_legacy_s_fmt_vid_cap, + .vidioc_enum_framesizes = cal_legacy_enum_framesizes, .vidioc_reqbufs = vb2_ioctl_reqbufs, .vidioc_create_bufs = vb2_ioctl_create_bufs, .vidioc_prepare_buf = vb2_ioctl_prepare_buf, @@ -402,15 +416,17 @@ static const struct v4l2_ioctl_ops cal_ioctl_video_ops = { .vidioc_qbuf = vb2_ioctl_qbuf, .vidioc_dqbuf = vb2_ioctl_dqbuf, .vidioc_expbuf = vb2_ioctl_expbuf, - .vidioc_enum_input = cal_enum_input, - .vidioc_g_input = cal_g_input, - .vidioc_s_input = cal_s_input, - .vidioc_enum_frameintervals = cal_enum_frameintervals, + .vidioc_enum_input = cal_legacy_enum_input, + .vidioc_g_input = cal_legacy_g_input, + .vidioc_s_input = cal_legacy_s_input, + .vidioc_enum_frameintervals = cal_legacy_enum_frameintervals, .vidioc_streamon = vb2_ioctl_streamon, .vidioc_streamoff = vb2_ioctl_streamoff, .vidioc_log_status = v4l2_ctrl_log_status, .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, .vidioc_unsubscribe_event = v4l2_event_unsubscribe, + .vidioc_g_parm = cal_legacy_g_parm, + .vidioc_s_parm = cal_legacy_s_parm, }; /* ------------------------------------------------------------------ @@ -421,13 +437,28 @@ static const struct v4l2_ioctl_ops cal_ioctl_video_ops = { static int cal_mc_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f) { + unsigned int i; + unsigned int idx; + if (f->index >= cal_num_formats) return -EINVAL; - f->pixelformat = cal_formats[f->index].fourcc; - f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + idx = 0; - return 0; + for (i = 0; i < cal_num_formats; ++i) { + if (f->mbus_code && cal_formats[i].code != f->mbus_code) + continue; + + if (idx == f->index) { + f->pixelformat = cal_formats[i].fourcc; + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + return 0; + } + + idx++; + } + + return -EINVAL; } static void cal_mc_try_fmt(struct cal_ctx *ctx, struct v4l2_format *f, @@ -656,8 +687,13 @@ static void cal_release_buffers(struct cal_ctx *ctx, static int cal_video_check_format(struct cal_ctx *ctx) { const struct v4l2_mbus_framefmt *format; + struct media_pad *remote_pad; + + remote_pad = media_entity_remote_pad(&ctx->pad); + if (!remote_pad) + return -ENODEV; - format = &ctx->phy->formats[CAL_CAMERARX_PAD_SOURCE]; + format = &ctx->phy->formats[remote_pad->index]; if (ctx->fmtinfo->code != format->code || ctx->v_fmt.fmt.pix.height != format->height || @@ -692,9 +728,15 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count) goto error_pipeline; } + ret = cal_ctx_prepare(ctx); + if (ret) { + ctx_err(ctx, "Failed to prepare context: %d\n", ret); + goto error_pipeline; + } + spin_lock_irq(&ctx->dma.lock); buf = list_first_entry(&ctx->dma.queue, struct cal_buffer, list); - ctx->dma.pending = buf; + ctx->dma.active = buf; list_del(&buf->list); spin_unlock_irq(&ctx->dma.lock); @@ -719,6 +761,7 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count) error_stop: cal_ctx_stop(ctx); pm_runtime_put_sync(ctx->cal->dev); + cal_ctx_unprepare(ctx); error_pipeline: media_pipeline_stop(&ctx->vdev.entity); @@ -738,6 +781,8 @@ static void cal_stop_streaming(struct vb2_queue *vq) pm_runtime_put_sync(ctx->cal->dev); + cal_ctx_unprepare(ctx); + cal_release_buffers(ctx, VB2_BUF_STATE_ERROR); media_pipeline_stop(&ctx->vdev.entity); @@ -785,20 +830,20 @@ static int cal_ctx_v4l2_init_formats(struct cal_ctx *ctx) memset(&mbus_code, 0, sizeof(mbus_code)); mbus_code.index = j; mbus_code.which = V4L2_SUBDEV_FORMAT_ACTIVE; - ret = v4l2_subdev_call(ctx->phy->sensor, pad, enum_mbus_code, + ret = v4l2_subdev_call(ctx->phy->source, pad, enum_mbus_code, NULL, &mbus_code); if (ret == -EINVAL) break; if (ret) { ctx_err(ctx, "Error enumerating mbus codes in subdev %s: %d\n", - ctx->phy->sensor->name, ret); + ctx->phy->source->name, ret); return ret; } ctx_dbg(2, ctx, "subdev %s: code: %04x idx: %u\n", - ctx->phy->sensor->name, mbus_code.code, j); + ctx->phy->source->name, mbus_code.code, j); for (k = 0; k < cal_num_formats; k++) { fmtinfo = &cal_formats[k]; @@ -816,7 +861,7 @@ static int cal_ctx_v4l2_init_formats(struct cal_ctx *ctx) if (i == 0) { ctx_err(ctx, "No suitable format reported by subdev %s\n", - ctx->phy->sensor->name); + ctx->phy->source->name); return -EINVAL; } @@ -841,22 +886,57 @@ static int cal_ctx_v4l2_init_formats(struct cal_ctx *ctx) return 0; } +static int cal_ctx_v4l2_init_mc_format(struct cal_ctx *ctx) +{ + const struct cal_format_info *fmtinfo; + struct v4l2_pix_format *pix_fmt = &ctx->v_fmt.fmt.pix; + + fmtinfo = cal_format_by_code(MEDIA_BUS_FMT_UYVY8_2X8); + if (!fmtinfo) + return -EINVAL; + + pix_fmt->width = 640; + pix_fmt->height = 480; + pix_fmt->field = V4L2_FIELD_NONE; + pix_fmt->colorspace = V4L2_COLORSPACE_SRGB; + pix_fmt->ycbcr_enc = V4L2_YCBCR_ENC_601; + pix_fmt->quantization = V4L2_QUANTIZATION_LIM_RANGE; + pix_fmt->xfer_func = V4L2_XFER_FUNC_SRGB; + pix_fmt->pixelformat = fmtinfo->fourcc; + + ctx->v_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + /* Save current format */ + cal_calc_format_size(ctx, fmtinfo, &ctx->v_fmt); + ctx->fmtinfo = fmtinfo; + + return 0; +} + int cal_ctx_v4l2_register(struct cal_ctx *ctx) { struct video_device *vfd = &ctx->vdev; int ret; - ret = cal_ctx_v4l2_init_formats(ctx); - if (ret) - return ret; - if (!cal_mc_api) { struct v4l2_ctrl_handler *hdl = &ctx->ctrl_handler; - ret = v4l2_ctrl_add_handler(hdl, ctx->phy->sensor->ctrl_handler, + ret = cal_ctx_v4l2_init_formats(ctx); + if (ret) { + ctx_err(ctx, "Failed to init formats: %d\n", ret); + return ret; + } + + ret = v4l2_ctrl_add_handler(hdl, ctx->phy->source->ctrl_handler, NULL, true); if (ret < 0) { - ctx_err(ctx, "Failed to add sensor ctrl handler\n"); + ctx_err(ctx, "Failed to add source ctrl handler\n"); + return ret; + } + } else { + ret = cal_ctx_v4l2_init_mc_format(ctx); + if (ret) { + ctx_err(ctx, "Failed to init format: %d\n", ret); return ret; } } @@ -868,13 +948,13 @@ int cal_ctx_v4l2_register(struct cal_ctx *ctx) } ret = media_create_pad_link(&ctx->phy->subdev.entity, - CAL_CAMERARX_PAD_SOURCE, + CAL_CAMERARX_PAD_FIRST_SOURCE, &vfd->entity, 0, MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED); if (ret) { ctx_err(ctx, "Failed to create media link for context %u\n", - ctx->index); + ctx->dma_ctx); video_unregister_device(vfd); return ret; } @@ -926,9 +1006,9 @@ int cal_ctx_v4l2_init(struct cal_ctx *ctx) | (cal_mc_api ? V4L2_CAP_IO_MC : 0); vfd->v4l2_dev = &ctx->cal->v4l2_dev; vfd->queue = q; - snprintf(vfd->name, sizeof(vfd->name), "CAL output %u", ctx->index); + snprintf(vfd->name, sizeof(vfd->name), "CAL output %u", ctx->dma_ctx); vfd->release = video_device_release_empty; - vfd->ioctl_ops = cal_mc_api ? &cal_ioctl_mc_ops : &cal_ioctl_video_ops; + vfd->ioctl_ops = cal_mc_api ? &cal_ioctl_mc_ops : &cal_ioctl_legacy_ops; vfd->lock = &ctx->mutex; video_set_drvdata(vfd, ctx); diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c index 76fe7a8b33f6..8e469d518a74 100644 --- a/drivers/media/platform/ti-vpe/cal.c +++ b/drivers/media/platform/ti-vpe/cal.c @@ -290,11 +290,42 @@ void cal_quickdump_regs(struct cal_dev *cal) * ------------------------------------------------------------------ */ +#define CAL_MAX_PIX_PROC 4 + +static int cal_reserve_pix_proc(struct cal_dev *cal) +{ + unsigned long ret; + + spin_lock(&cal->v4l2_dev.lock); + + ret = find_first_zero_bit(&cal->reserved_pix_proc_mask, CAL_MAX_PIX_PROC); + + if (ret == CAL_MAX_PIX_PROC) { + spin_unlock(&cal->v4l2_dev.lock); + return -ENOSPC; + } + + cal->reserved_pix_proc_mask |= BIT(ret); + + spin_unlock(&cal->v4l2_dev.lock); + + return ret; +} + +static void cal_release_pix_proc(struct cal_dev *cal, unsigned int pix_proc_num) +{ + spin_lock(&cal->v4l2_dev.lock); + + cal->reserved_pix_proc_mask &= ~BIT(pix_proc_num); + + spin_unlock(&cal->v4l2_dev.lock); +} + static void cal_ctx_csi2_config(struct cal_ctx *ctx) { u32 val; - val = cal_read(ctx->cal, CAL_CSI2_CTX0(ctx->index)); + val = cal_read(ctx->cal, CAL_CSI2_CTX(ctx->phy->instance, ctx->csi2_ctx)); cal_set_field(&val, ctx->cport, CAL_CSI2_CTX_CPORT_MASK); /* * DT type: MIPI CSI-2 Specs @@ -304,15 +335,16 @@ static void cal_ctx_csi2_config(struct cal_ctx *ctx) * 0x2A: RAW8 1 pixel = 1 byte * 0x1E: YUV422 2 pixels = 4 bytes */ - cal_set_field(&val, 0x1, CAL_CSI2_CTX_DT_MASK); - cal_set_field(&val, 0, CAL_CSI2_CTX_VC_MASK); + cal_set_field(&val, ctx->datatype, CAL_CSI2_CTX_DT_MASK); + cal_set_field(&val, ctx->vc, CAL_CSI2_CTX_VC_MASK); cal_set_field(&val, ctx->v_fmt.fmt.pix.height, CAL_CSI2_CTX_LINES_MASK); cal_set_field(&val, CAL_CSI2_CTX_ATT_PIX, CAL_CSI2_CTX_ATT_MASK); cal_set_field(&val, CAL_CSI2_CTX_PACK_MODE_LINE, CAL_CSI2_CTX_PACK_MODE_MASK); - cal_write(ctx->cal, CAL_CSI2_CTX0(ctx->index), val); - ctx_dbg(3, ctx, "CAL_CSI2_CTX0(%d) = 0x%08x\n", ctx->index, - cal_read(ctx->cal, CAL_CSI2_CTX0(ctx->index))); + cal_write(ctx->cal, CAL_CSI2_CTX(ctx->phy->instance, ctx->csi2_ctx), val); + ctx_dbg(3, ctx, "CAL_CSI2_CTX(%u, %u) = 0x%08x\n", + ctx->phy->instance, ctx->csi2_ctx, + cal_read(ctx->cal, CAL_CSI2_CTX(ctx->phy->instance, ctx->csi2_ctx))); } static void cal_ctx_pix_proc_config(struct cal_ctx *ctx) @@ -354,16 +386,16 @@ static void cal_ctx_pix_proc_config(struct cal_ctx *ctx) break; } - val = cal_read(ctx->cal, CAL_PIX_PROC(ctx->index)); + val = cal_read(ctx->cal, CAL_PIX_PROC(ctx->pix_proc)); cal_set_field(&val, extract, CAL_PIX_PROC_EXTRACT_MASK); cal_set_field(&val, CAL_PIX_PROC_DPCMD_BYPASS, CAL_PIX_PROC_DPCMD_MASK); cal_set_field(&val, CAL_PIX_PROC_DPCME_BYPASS, CAL_PIX_PROC_DPCME_MASK); cal_set_field(&val, pack, CAL_PIX_PROC_PACK_MASK); cal_set_field(&val, ctx->cport, CAL_PIX_PROC_CPORT_MASK); cal_set_field(&val, 1, CAL_PIX_PROC_EN_MASK); - cal_write(ctx->cal, CAL_PIX_PROC(ctx->index), val); - ctx_dbg(3, ctx, "CAL_PIX_PROC(%d) = 0x%08x\n", ctx->index, - cal_read(ctx->cal, CAL_PIX_PROC(ctx->index))); + cal_write(ctx->cal, CAL_PIX_PROC(ctx->pix_proc), val); + ctx_dbg(3, ctx, "CAL_PIX_PROC(%u) = 0x%08x\n", ctx->pix_proc, + cal_read(ctx->cal, CAL_PIX_PROC(ctx->pix_proc))); } static void cal_ctx_wr_dma_config(struct cal_ctx *ctx) @@ -371,27 +403,25 @@ static void cal_ctx_wr_dma_config(struct cal_ctx *ctx) unsigned int stride = ctx->v_fmt.fmt.pix.bytesperline; u32 val; - val = cal_read(ctx->cal, CAL_WR_DMA_CTRL(ctx->index)); + val = cal_read(ctx->cal, CAL_WR_DMA_CTRL(ctx->dma_ctx)); cal_set_field(&val, ctx->cport, CAL_WR_DMA_CTRL_CPORT_MASK); cal_set_field(&val, ctx->v_fmt.fmt.pix.height, CAL_WR_DMA_CTRL_YSIZE_MASK); cal_set_field(&val, CAL_WR_DMA_CTRL_DTAG_PIX_DAT, CAL_WR_DMA_CTRL_DTAG_MASK); - cal_set_field(&val, CAL_WR_DMA_CTRL_MODE_CONST, - CAL_WR_DMA_CTRL_MODE_MASK); cal_set_field(&val, CAL_WR_DMA_CTRL_PATTERN_LINEAR, CAL_WR_DMA_CTRL_PATTERN_MASK); cal_set_field(&val, 1, CAL_WR_DMA_CTRL_STALL_RD_MASK); - cal_write(ctx->cal, CAL_WR_DMA_CTRL(ctx->index), val); - ctx_dbg(3, ctx, "CAL_WR_DMA_CTRL(%d) = 0x%08x\n", ctx->index, - cal_read(ctx->cal, CAL_WR_DMA_CTRL(ctx->index))); + cal_write(ctx->cal, CAL_WR_DMA_CTRL(ctx->dma_ctx), val); + ctx_dbg(3, ctx, "CAL_WR_DMA_CTRL(%d) = 0x%08x\n", ctx->dma_ctx, + cal_read(ctx->cal, CAL_WR_DMA_CTRL(ctx->dma_ctx))); - cal_write_field(ctx->cal, CAL_WR_DMA_OFST(ctx->index), + cal_write_field(ctx->cal, CAL_WR_DMA_OFST(ctx->dma_ctx), stride / 16, CAL_WR_DMA_OFST_MASK); - ctx_dbg(3, ctx, "CAL_WR_DMA_OFST(%d) = 0x%08x\n", ctx->index, - cal_read(ctx->cal, CAL_WR_DMA_OFST(ctx->index))); + ctx_dbg(3, ctx, "CAL_WR_DMA_OFST(%d) = 0x%08x\n", ctx->dma_ctx, + cal_read(ctx->cal, CAL_WR_DMA_OFST(ctx->dma_ctx))); - val = cal_read(ctx->cal, CAL_WR_DMA_XSIZE(ctx->index)); + val = cal_read(ctx->cal, CAL_WR_DMA_XSIZE(ctx->dma_ctx)); /* 64 bit word means no skipping */ cal_set_field(&val, 0, CAL_WR_DMA_XSIZE_XSKIP_MASK); /* @@ -400,34 +430,32 @@ static void cal_ctx_wr_dma_config(struct cal_ctx *ctx) * written per line. */ cal_set_field(&val, stride / 8, CAL_WR_DMA_XSIZE_MASK); - cal_write(ctx->cal, CAL_WR_DMA_XSIZE(ctx->index), val); - ctx_dbg(3, ctx, "CAL_WR_DMA_XSIZE(%d) = 0x%08x\n", ctx->index, - cal_read(ctx->cal, CAL_WR_DMA_XSIZE(ctx->index))); - - val = cal_read(ctx->cal, CAL_CTRL); - cal_set_field(&val, CAL_CTRL_BURSTSIZE_BURST128, - CAL_CTRL_BURSTSIZE_MASK); - cal_set_field(&val, 0xF, CAL_CTRL_TAGCNT_MASK); - cal_set_field(&val, CAL_CTRL_POSTED_WRITES_NONPOSTED, - CAL_CTRL_POSTED_WRITES_MASK); - cal_set_field(&val, 0xFF, CAL_CTRL_MFLAGL_MASK); - cal_set_field(&val, 0xFF, CAL_CTRL_MFLAGH_MASK); - cal_write(ctx->cal, CAL_CTRL, val); - ctx_dbg(3, ctx, "CAL_CTRL = 0x%08x\n", cal_read(ctx->cal, CAL_CTRL)); + cal_write(ctx->cal, CAL_WR_DMA_XSIZE(ctx->dma_ctx), val); + ctx_dbg(3, ctx, "CAL_WR_DMA_XSIZE(%d) = 0x%08x\n", ctx->dma_ctx, + cal_read(ctx->cal, CAL_WR_DMA_XSIZE(ctx->dma_ctx))); } void cal_ctx_set_dma_addr(struct cal_ctx *ctx, dma_addr_t addr) { - cal_write(ctx->cal, CAL_WR_DMA_ADDR(ctx->index), addr); + cal_write(ctx->cal, CAL_WR_DMA_ADDR(ctx->dma_ctx), addr); +} + +static void cal_ctx_wr_dma_enable(struct cal_ctx *ctx) +{ + u32 val = cal_read(ctx->cal, CAL_WR_DMA_CTRL(ctx->dma_ctx)); + + cal_set_field(&val, CAL_WR_DMA_CTRL_MODE_CONST, + CAL_WR_DMA_CTRL_MODE_MASK); + cal_write(ctx->cal, CAL_WR_DMA_CTRL(ctx->dma_ctx), val); } static void cal_ctx_wr_dma_disable(struct cal_ctx *ctx) { - u32 val = cal_read(ctx->cal, CAL_WR_DMA_CTRL(ctx->index)); + u32 val = cal_read(ctx->cal, CAL_WR_DMA_CTRL(ctx->dma_ctx)); cal_set_field(&val, CAL_WR_DMA_CTRL_MODE_DIS, CAL_WR_DMA_CTRL_MODE_MASK); - cal_write(ctx->cal, CAL_WR_DMA_CTRL(ctx->index), val); + cal_write(ctx->cal, CAL_WR_DMA_CTRL(ctx->dma_ctx), val); } static bool cal_ctx_wr_dma_stopped(struct cal_ctx *ctx) @@ -441,6 +469,31 @@ static bool cal_ctx_wr_dma_stopped(struct cal_ctx *ctx) return stopped; } +int cal_ctx_prepare(struct cal_ctx *ctx) +{ + int ret; + + ctx->use_pix_proc = !ctx->fmtinfo->meta; + + if (ctx->use_pix_proc) { + ret = cal_reserve_pix_proc(ctx->cal); + if (ret < 0) { + ctx_err(ctx, "Failed to reserve pix proc: %d\n", ret); + return ret; + } + + ctx->pix_proc = ret; + } + + return 0; +} + +void cal_ctx_unprepare(struct cal_ctx *ctx) +{ + if (ctx->use_pix_proc) + cal_release_pix_proc(ctx->cal, ctx->pix_proc); +} + void cal_ctx_start(struct cal_ctx *ctx) { ctx->sequence = 0; @@ -448,14 +501,17 @@ void cal_ctx_start(struct cal_ctx *ctx) /* Configure the CSI-2, pixel processing and write DMA contexts. */ cal_ctx_csi2_config(ctx); - cal_ctx_pix_proc_config(ctx); + if (ctx->use_pix_proc) + cal_ctx_pix_proc_config(ctx); cal_ctx_wr_dma_config(ctx); /* Enable IRQ_WDMA_END and IRQ_WDMA_START. */ cal_write(ctx->cal, CAL_HL_IRQENABLE_SET(1), - CAL_HL_IRQ_MASK(ctx->index)); + CAL_HL_IRQ_WDMA_END_MASK(ctx->dma_ctx)); cal_write(ctx->cal, CAL_HL_IRQENABLE_SET(2), - CAL_HL_IRQ_MASK(ctx->index)); + CAL_HL_IRQ_WDMA_START_MASK(ctx->dma_ctx)); + + cal_ctx_wr_dma_enable(ctx); } void cal_ctx_stop(struct cal_ctx *ctx) @@ -479,11 +535,18 @@ void cal_ctx_stop(struct cal_ctx *ctx) /* Disable IRQ_WDMA_END and IRQ_WDMA_START. */ cal_write(ctx->cal, CAL_HL_IRQENABLE_CLR(1), - CAL_HL_IRQ_MASK(ctx->index)); + CAL_HL_IRQ_WDMA_END_MASK(ctx->dma_ctx)); cal_write(ctx->cal, CAL_HL_IRQENABLE_CLR(2), - CAL_HL_IRQ_MASK(ctx->index)); + CAL_HL_IRQ_WDMA_START_MASK(ctx->dma_ctx)); ctx->dma.state = CAL_DMA_STOPPED; + + /* Disable CSI2 context */ + cal_write(ctx->cal, CAL_CSI2_CTX(ctx->phy->instance, ctx->csi2_ctx), 0); + + /* Disable pix proc */ + if (ctx->use_pix_proc) + cal_write(ctx->cal, CAL_PIX_PROC(ctx->pix_proc), 0); } /* ------------------------------------------------------------------ @@ -577,6 +640,16 @@ static irqreturn_t cal_irq(int irq_cal, void *data) cal_write(cal, CAL_CSI2_COMPLEXIO_IRQSTATUS(i), cio_stat); } + + if (status & CAL_HL_IRQ_VC_MASK(i)) { + u32 vc_stat = cal_read(cal, CAL_CSI2_VC_IRQSTATUS(i)); + + dev_err_ratelimited(cal->dev, + "CIO%u VC error: %#08x\n", + i, vc_stat); + + cal_write(cal, CAL_CSI2_VC_IRQSTATUS(i), vc_stat); + } } } @@ -588,8 +661,8 @@ static irqreturn_t cal_irq(int irq_cal, void *data) /* Clear Interrupt status */ cal_write(cal, CAL_HL_IRQSTATUS(1), status); - for (i = 0; i < ARRAY_SIZE(cal->ctx); ++i) { - if (status & CAL_HL_IRQ_MASK(i)) + for (i = 0; i < cal->num_contexts; ++i) { + if (status & CAL_HL_IRQ_WDMA_END_MASK(i)) cal_irq_wdma_end(cal->ctx[i]); } } @@ -602,8 +675,8 @@ static irqreturn_t cal_irq(int irq_cal, void *data) /* Clear Interrupt status */ cal_write(cal, CAL_HL_IRQSTATUS(2), status); - for (i = 0; i < ARRAY_SIZE(cal->ctx); ++i) { - if (status & CAL_HL_IRQ_MASK(i)) + for (i = 0; i < cal->num_contexts; ++i) { + if (status & CAL_HL_IRQ_WDMA_START_MASK(i)) cal_irq_wdma_start(cal->ctx[i]); } } @@ -635,20 +708,20 @@ static int cal_async_notifier_bound(struct v4l2_async_notifier *notifier, int pad; int ret; - if (phy->sensor) { + if (phy->source) { phy_info(phy, "Rejecting subdev %s (Already set!!)", subdev->name); return 0; } - phy->sensor = subdev; - phy_dbg(1, phy, "Using sensor %s for capture\n", subdev->name); + phy->source = subdev; + phy_dbg(1, phy, "Using source %s for capture\n", subdev->name); pad = media_entity_get_fwnode_pad(&subdev->entity, - of_fwnode_handle(phy->sensor_ep_node), + of_fwnode_handle(phy->source_ep_node), MEDIA_PAD_FL_SOURCE); if (pad < 0) { - phy_err(phy, "Sensor %s has no connected source pad\n", + phy_err(phy, "Source %s has no connected source pad\n", subdev->name); return pad; } @@ -658,7 +731,7 @@ static int cal_async_notifier_bound(struct v4l2_async_notifier *notifier, MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED); if (ret) { - phy_err(phy, "Failed to create media link for sensor %s\n", + phy_err(phy, "Failed to create media link for source %s\n", subdev->name); return ret; } @@ -670,15 +743,30 @@ static int cal_async_notifier_complete(struct v4l2_async_notifier *notifier) { struct cal_dev *cal = container_of(notifier, struct cal_dev, notifier); unsigned int i; - int ret = 0; + int ret; - for (i = 0; i < ARRAY_SIZE(cal->ctx); ++i) { - if (cal->ctx[i]) - cal_ctx_v4l2_register(cal->ctx[i]); + for (i = 0; i < cal->num_contexts; ++i) { + ret = cal_ctx_v4l2_register(cal->ctx[i]); + if (ret) + goto err_ctx_unreg; } - if (cal_mc_api) - ret = v4l2_device_register_subdev_nodes(&cal->v4l2_dev); + if (!cal_mc_api) + return 0; + + ret = v4l2_device_register_subdev_nodes(&cal->v4l2_dev); + if (ret) + goto err_ctx_unreg; + + return 0; + +err_ctx_unreg: + for (; i > 0; --i) { + if (!cal->ctx[i - 1]) + continue; + + cal_ctx_v4l2_unregister(cal->ctx[i - 1]); + } return ret; } @@ -701,10 +789,10 @@ static int cal_async_notifier_register(struct cal_dev *cal) struct cal_v4l2_async_subdev *casd; struct fwnode_handle *fwnode; - if (!phy->sensor_node) + if (!phy->source_node) continue; - fwnode = of_fwnode_handle(phy->sensor_node); + fwnode = of_fwnode_handle(phy->source_node); casd = v4l2_async_notifier_add_fwnode_subdev(&cal->notifier, fwnode, struct cal_v4l2_async_subdev); @@ -777,10 +865,8 @@ static void cal_media_unregister(struct cal_dev *cal) unsigned int i; /* Unregister all the V4L2 video devices. */ - for (i = 0; i < ARRAY_SIZE(cal->ctx); i++) { - if (cal->ctx[i]) - cal_ctx_v4l2_unregister(cal->ctx[i]); - } + for (i = 0; i < cal->num_contexts; i++) + cal_ctx_v4l2_unregister(cal->ctx[i]); cal_async_notifier_unregister(cal); media_device_unregister(&cal->mdev); @@ -825,13 +911,6 @@ static int cal_media_init(struct cal_dev *cal) */ static void cal_media_cleanup(struct cal_dev *cal) { - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(cal->ctx); i++) { - if (cal->ctx[i]) - cal_ctx_v4l2_cleanup(cal->ctx[i]); - } - v4l2_device_unregister(&cal->v4l2_dev); media_device_cleanup(&cal->mdev); @@ -848,14 +927,17 @@ static struct cal_ctx *cal_ctx_create(struct cal_dev *cal, int inst) struct cal_ctx *ctx; int ret; - ctx = devm_kzalloc(cal->dev, sizeof(*ctx), GFP_KERNEL); + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); if (!ctx) return NULL; ctx->cal = cal; ctx->phy = cal->phy[inst]; - ctx->index = inst; + ctx->dma_ctx = inst; + ctx->csi2_ctx = inst; ctx->cport = inst; + ctx->vc = 0; + ctx->datatype = CAL_CSI2_CTX_DT_ANY; ret = cal_ctx_v4l2_init(ctx); if (ret) @@ -864,6 +946,13 @@ static struct cal_ctx *cal_ctx_create(struct cal_dev *cal, int inst) return ctx; } +static void cal_ctx_destroy(struct cal_ctx *ctx) +{ + cal_ctx_v4l2_cleanup(ctx); + + kfree(ctx); +} + static const struct of_device_id cal_of_match[] = { { .compatible = "ti,dra72-cal", @@ -976,7 +1065,6 @@ static int cal_init_camerarx_regmap(struct cal_dev *cal) static int cal_probe(struct platform_device *pdev) { struct cal_dev *cal; - struct cal_ctx *ctx; bool connected = false; unsigned int i; int ret; @@ -1045,7 +1133,7 @@ static int cal_probe(struct platform_device *pdev) goto error_camerarx; } - if (cal->phy[i]->sensor_node) + if (cal->phy[i]->source_node) connected = true; } @@ -1057,15 +1145,17 @@ static int cal_probe(struct platform_device *pdev) /* Create contexts. */ for (i = 0; i < cal->data->num_csi2_phy; ++i) { - if (!cal->phy[i]->sensor_node) + if (!cal->phy[i]->source_node) continue; - cal->ctx[i] = cal_ctx_create(cal, i); - if (!cal->ctx[i]) { - cal_err(cal, "Failed to create context %u\n", i); + cal->ctx[cal->num_contexts] = cal_ctx_create(cal, i); + if (!cal->ctx[cal->num_contexts]) { + cal_err(cal, "Failed to create context %u\n", cal->num_contexts); ret = -ENODEV; goto error_context; } + + cal->num_contexts++; } /* Register the media device. */ @@ -1076,11 +1166,8 @@ static int cal_probe(struct platform_device *pdev) return 0; error_context: - for (i = 0; i < ARRAY_SIZE(cal->ctx); i++) { - ctx = cal->ctx[i]; - if (ctx) - cal_ctx_v4l2_cleanup(ctx); - } + for (i = 0; i < cal->num_contexts; i++) + cal_ctx_destroy(cal->ctx[i]); error_camerarx: for (i = 0; i < cal->data->num_csi2_phy; i++) @@ -1106,16 +1193,17 @@ static int cal_remove(struct platform_device *pdev) cal_media_unregister(cal); - for (i = 0; i < ARRAY_SIZE(cal->phy); i++) { - if (cal->phy[i]) - cal_camerarx_disable(cal->phy[i]); - } + for (i = 0; i < cal->data->num_csi2_phy; i++) + cal_camerarx_disable(cal->phy[i]); - cal_media_cleanup(cal); + for (i = 0; i < cal->num_contexts; i++) + cal_ctx_destroy(cal->ctx[i]); for (i = 0; i < cal->data->num_csi2_phy; i++) cal_camerarx_destroy(cal->phy[i]); + cal_media_cleanup(cal); + if (ret >= 0) pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); @@ -1127,6 +1215,7 @@ static int cal_runtime_resume(struct device *dev) { struct cal_dev *cal = dev_get_drvdata(dev); unsigned int i; + u32 val; if (cal->data->flags & DRA72_CAL_PRE_ES2_LDO_DISABLE) { /* @@ -1143,6 +1232,17 @@ static int cal_runtime_resume(struct device *dev) */ cal_write(cal, CAL_HL_IRQENABLE_SET(0), CAL_HL_IRQ_OCPO_ERR_MASK); + val = cal_read(cal, CAL_CTRL); + cal_set_field(&val, CAL_CTRL_BURSTSIZE_BURST128, + CAL_CTRL_BURSTSIZE_MASK); + cal_set_field(&val, 0xf, CAL_CTRL_TAGCNT_MASK); + cal_set_field(&val, CAL_CTRL_POSTED_WRITES_NONPOSTED, + CAL_CTRL_POSTED_WRITES_MASK); + cal_set_field(&val, 0xff, CAL_CTRL_MFLAGL_MASK); + cal_set_field(&val, 0xff, CAL_CTRL_MFLAGH_MASK); + cal_write(cal, CAL_CTRL, val); + cal_dbg(3, cal, "CAL_CTRL = 0x%08x\n", cal_read(cal, CAL_CTRL)); + return 0; } diff --git a/drivers/media/platform/ti-vpe/cal.h b/drivers/media/platform/ti-vpe/cal.h index db0e408eaa94..527e22d022f3 100644 --- a/drivers/media/platform/ti-vpe/cal.h +++ b/drivers/media/platform/ti-vpe/cal.h @@ -29,7 +29,7 @@ #include <media/videobuf2-v4l2.h> #define CAL_MODULE_NAME "cal" -#define CAL_NUM_CONTEXT 2 +#define CAL_MAX_NUM_CONTEXT 8 #define CAL_NUM_CSI2_PORTS 2 /* @@ -44,7 +44,22 @@ #define CAL_MAX_HEIGHT_LINES 16383 #define CAL_CAMERARX_PAD_SINK 0 -#define CAL_CAMERARX_PAD_SOURCE 1 +#define CAL_CAMERARX_PAD_FIRST_SOURCE 1 +#define CAL_CAMERARX_NUM_SOURCE_PADS 1 +#define CAL_CAMERARX_NUM_PADS (1 + CAL_CAMERARX_NUM_SOURCE_PADS) + +static inline bool cal_rx_pad_is_sink(u32 pad) +{ + /* Camera RX has 1 sink pad, and N source pads */ + return pad == 0; +} + +static inline bool cal_rx_pad_is_source(u32 pad) +{ + /* Camera RX has 1 sink pad, and N source pads */ + return pad >= CAL_CAMERARX_PAD_FIRST_SOURCE && + pad <= CAL_CAMERARX_NUM_SOURCE_PADS; +} struct device; struct device_node; @@ -73,6 +88,7 @@ struct cal_format_info { u32 code; /* Bits per pixel */ u8 bpp; + bool meta; }; /* buffer for one video frame */ @@ -149,22 +165,29 @@ struct cal_data { struct cal_camerarx { void __iomem *base; struct resource *res; - struct device *dev; struct regmap_field *fields[F_MAX_FIELDS]; struct cal_dev *cal; unsigned int instance; struct v4l2_fwnode_endpoint endpoint; - struct device_node *sensor_ep_node; - struct device_node *sensor_node; - struct v4l2_subdev *sensor; + struct device_node *source_ep_node; + struct device_node *source_node; + struct v4l2_subdev *source; struct media_pipeline pipe; struct v4l2_subdev subdev; - struct media_pad pads[2]; - struct v4l2_mbus_framefmt formats[2]; - const struct cal_format_info *fmtinfo; + struct media_pad pads[CAL_CAMERARX_NUM_PADS]; + struct v4l2_mbus_framefmt formats[CAL_CAMERARX_NUM_PADS]; + + /* + * Lock for camerarx ops. Protects: + * - formats + * - enable_count + */ + struct mutex mutex; + + unsigned int enable_count; }; struct cal_dev { @@ -184,11 +207,14 @@ struct cal_dev { /* Camera Core Module handle */ struct cal_camerarx *phy[CAL_NUM_CSI2_PORTS]; - struct cal_ctx *ctx[CAL_NUM_CONTEXT]; + u32 num_contexts; + struct cal_ctx *ctx[CAL_MAX_NUM_CONTEXT]; struct media_device mdev; struct v4l2_device v4l2_dev; struct v4l2_async_notifier notifier; + + unsigned long reserved_pix_proc_mask; }; /* @@ -212,14 +238,20 @@ struct cal_ctx { /* Used to store current pixel format */ struct v4l2_format v_fmt; - /* Current subdev enumerated format */ + /* Current subdev enumerated format (legacy) */ const struct cal_format_info **active_fmt; unsigned int num_active_fmt; unsigned int sequence; struct vb2_queue vb_vidq; - unsigned int index; - unsigned int cport; + u8 dma_ctx; + u8 cport; + u8 csi2_ctx; + u8 pix_proc; + u8 vc; + u8 datatype; + + bool use_pix_proc; }; extern unsigned int cal_debug; @@ -237,11 +269,11 @@ extern bool cal_mc_api; dev_err((cal)->dev, fmt, ##arg) #define ctx_dbg(level, ctx, fmt, arg...) \ - cal_dbg(level, (ctx)->cal, "ctx%u: " fmt, (ctx)->index, ##arg) + cal_dbg(level, (ctx)->cal, "ctx%u: " fmt, (ctx)->dma_ctx, ##arg) #define ctx_info(ctx, fmt, arg...) \ - cal_info((ctx)->cal, "ctx%u: " fmt, (ctx)->index, ##arg) + cal_info((ctx)->cal, "ctx%u: " fmt, (ctx)->dma_ctx, ##arg) #define ctx_err(ctx, fmt, arg...) \ - cal_err((ctx)->cal, "ctx%u: " fmt, (ctx)->index, ##arg) + cal_err((ctx)->cal, "ctx%u: " fmt, (ctx)->dma_ctx, ##arg) #define phy_dbg(level, phy, fmt, arg...) \ cal_dbg(level, (phy)->cal, "phy%u: " fmt, (phy)->instance, ##arg) @@ -297,6 +329,8 @@ struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal, unsigned int instance); void cal_camerarx_destroy(struct cal_camerarx *phy); +int cal_ctx_prepare(struct cal_ctx *ctx); +void cal_ctx_unprepare(struct cal_ctx *ctx); void cal_ctx_set_dma_addr(struct cal_ctx *ctx, dma_addr_t addr); void cal_ctx_start(struct cal_ctx *ctx); void cal_ctx_stop(struct cal_ctx *ctx); diff --git a/drivers/media/platform/ti-vpe/cal_regs.h b/drivers/media/platform/ti-vpe/cal_regs.h index f752096dcf7f..40e4f972fcb7 100644 --- a/drivers/media/platform/ti-vpe/cal_regs.h +++ b/drivers/media/platform/ti-vpe/cal_regs.h @@ -72,22 +72,8 @@ #define CAL_CSI2_TIMING(m) (0x314U + (m) * 0x80U) #define CAL_CSI2_VC_IRQENABLE(m) (0x318U + (m) * 0x80U) #define CAL_CSI2_VC_IRQSTATUS(m) (0x328U + (m) * 0x80U) -#define CAL_CSI2_CTX0(m) (0x330U + (m) * 0x80U) -#define CAL_CSI2_CTX1(m) (0x334U + (m) * 0x80U) -#define CAL_CSI2_CTX2(m) (0x338U + (m) * 0x80U) -#define CAL_CSI2_CTX3(m) (0x33cU + (m) * 0x80U) -#define CAL_CSI2_CTX4(m) (0x340U + (m) * 0x80U) -#define CAL_CSI2_CTX5(m) (0x344U + (m) * 0x80U) -#define CAL_CSI2_CTX6(m) (0x348U + (m) * 0x80U) -#define CAL_CSI2_CTX7(m) (0x34cU + (m) * 0x80U) -#define CAL_CSI2_STATUS0(m) (0x350U + (m) * 0x80U) -#define CAL_CSI2_STATUS1(m) (0x354U + (m) * 0x80U) -#define CAL_CSI2_STATUS2(m) (0x358U + (m) * 0x80U) -#define CAL_CSI2_STATUS3(m) (0x35cU + (m) * 0x80U) -#define CAL_CSI2_STATUS4(m) (0x360U + (m) * 0x80U) -#define CAL_CSI2_STATUS5(m) (0x364U + (m) * 0x80U) -#define CAL_CSI2_STATUS6(m) (0x368U + (m) * 0x80U) -#define CAL_CSI2_STATUS7(m) (0x36cU + (m) * 0x80U) +#define CAL_CSI2_CTX(phy, csi2_ctx) (0x330U + (phy) * 0x80U + (csi2_ctx) * 4) +#define CAL_CSI2_STATUS(phy, csi2_ctx) (0x350U + (phy) * 0x80U + (csi2_ctx) * 4) /* CAL CSI2 PHY register offsets */ #define CAL_CSI2_PHY_REG0 0x000 @@ -139,7 +125,8 @@ #define CAL_HL_IRQ_EOI_LINE_NUMBER_READ0 0 #define CAL_HL_IRQ_EOI_LINE_NUMBER_EOI0 0 -#define CAL_HL_IRQ_MASK(m) BIT(m) +#define CAL_HL_IRQ_WDMA_END_MASK(m) BIT(m) +#define CAL_HL_IRQ_WDMA_START_MASK(m) BIT(m) #define CAL_HL_IRQ_OCPO_ERR_MASK BIT(6) @@ -419,32 +406,16 @@ #define CAL_CSI2_TIMING_STOP_STATE_X16_IO1_MASK BIT(14) #define CAL_CSI2_TIMING_FORCE_RX_MODE_IO1_MASK BIT(15) -#define CAL_CSI2_VC_IRQ_FS_IRQ_0_MASK BIT(0) -#define CAL_CSI2_VC_IRQ_FE_IRQ_0_MASK BIT(1) -#define CAL_CSI2_VC_IRQ_LS_IRQ_0_MASK BIT(2) -#define CAL_CSI2_VC_IRQ_LE_IRQ_0_MASK BIT(3) -#define CAL_CSI2_VC_IRQ_CS_IRQ_0_MASK BIT(4) -#define CAL_CSI2_VC_IRQ_ECC_CORRECTION0_IRQ_0_MASK BIT(5) -#define CAL_CSI2_VC_IRQ_FS_IRQ_1_MASK BIT(8) -#define CAL_CSI2_VC_IRQ_FE_IRQ_1_MASK BIT(9) -#define CAL_CSI2_VC_IRQ_LS_IRQ_1_MASK BIT(10) -#define CAL_CSI2_VC_IRQ_LE_IRQ_1_MASK BIT(11) -#define CAL_CSI2_VC_IRQ_CS_IRQ_1_MASK BIT(12) -#define CAL_CSI2_VC_IRQ_ECC_CORRECTION0_IRQ_1_MASK BIT(13) -#define CAL_CSI2_VC_IRQ_FS_IRQ_2_MASK BIT(16) -#define CAL_CSI2_VC_IRQ_FE_IRQ_2_MASK BIT(17) -#define CAL_CSI2_VC_IRQ_LS_IRQ_2_MASK BIT(18) -#define CAL_CSI2_VC_IRQ_LE_IRQ_2_MASK BIT(19) -#define CAL_CSI2_VC_IRQ_CS_IRQ_2_MASK BIT(20) -#define CAL_CSI2_VC_IRQ_ECC_CORRECTION0_IRQ_2_MASK BIT(21) -#define CAL_CSI2_VC_IRQ_FS_IRQ_3_MASK BIT(24) -#define CAL_CSI2_VC_IRQ_FE_IRQ_3_MASK BIT(25) -#define CAL_CSI2_VC_IRQ_LS_IRQ_3_MASK BIT(26) -#define CAL_CSI2_VC_IRQ_LE_IRQ_3_MASK BIT(27) -#define CAL_CSI2_VC_IRQ_CS_IRQ_3_MASK BIT(28) -#define CAL_CSI2_VC_IRQ_ECC_CORRECTION0_IRQ_3_MASK BIT(29) +#define CAL_CSI2_VC_IRQ_FS_IRQ_MASK(n) BIT(0 + ((n) * 8)) +#define CAL_CSI2_VC_IRQ_FE_IRQ_MASK(n) BIT(1 + ((n) * 8)) +#define CAL_CSI2_VC_IRQ_LS_IRQ_MASK(n) BIT(2 + ((n) * 8)) +#define CAL_CSI2_VC_IRQ_LE_IRQ_MASK(n) BIT(3 + ((n) * 8)) +#define CAL_CSI2_VC_IRQ_CS_IRQ_MASK(n) BIT(4 + ((n) * 8)) +#define CAL_CSI2_VC_IRQ_ECC_CORRECTION_IRQ_MASK(n) BIT(5 + ((n) * 8)) #define CAL_CSI2_CTX_DT_MASK GENMASK(5, 0) +#define CAL_CSI2_CTX_DT_DISABLED 0 +#define CAL_CSI2_CTX_DT_ANY 1 #define CAL_CSI2_CTX_VC_MASK GENMASK(7, 6) #define CAL_CSI2_CTX_CPORT_MASK GENMASK(12, 8) #define CAL_CSI2_CTX_ATT_MASK BIT(13) diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c index 6f51e5c75543..823c15facd1b 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.c +++ b/drivers/media/platform/vsp1/vsp1_entity.c @@ -676,9 +676,9 @@ int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity, * rectangles. */ entity->config = v4l2_subdev_alloc_state(&entity->subdev); - if (entity->config == NULL) { + if (IS_ERR(entity->config)) { media_entity_cleanup(&entity->subdev.entity); - return -ENOMEM; + return PTR_ERR(entity->config); } return 0; |