diff options
Diffstat (limited to 'drivers/staging/media')
41 files changed, 511 insertions, 259 deletions
diff --git a/drivers/staging/media/atomisp/i2c/atomisp-lm3554.c b/drivers/staging/media/atomisp/i2c/atomisp-lm3554.c index 362ed44b4eff..e046489cd253 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-lm3554.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-lm3554.c @@ -835,7 +835,6 @@ static int lm3554_probe(struct i2c_client *client) int err = 0; struct lm3554 *flash; unsigned int i; - int ret; flash = kzalloc(sizeof(*flash), GFP_KERNEL); if (!flash) @@ -844,7 +843,7 @@ static int lm3554_probe(struct i2c_client *client) flash->pdata = lm3554_platform_data_func(client); if (IS_ERR(flash->pdata)) { err = PTR_ERR(flash->pdata); - goto fail1; + goto free_flash; } v4l2_i2c_subdev_init(&flash->sd, client, &lm3554_ops); @@ -852,12 +851,12 @@ static int lm3554_probe(struct i2c_client *client) flash->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; flash->mode = ATOMISP_FLASH_MODE_OFF; flash->timeout = LM3554_MAX_TIMEOUT / LM3554_TIMEOUT_STEPSIZE - 1; - ret = + err = v4l2_ctrl_handler_init(&flash->ctrl_handler, ARRAY_SIZE(lm3554_controls)); - if (ret) { + if (err) { dev_err(&client->dev, "error initialize a ctrl_handler.\n"); - goto fail3; + goto unregister_subdev; } for (i = 0; i < ARRAY_SIZE(lm3554_controls); i++) @@ -866,14 +865,15 @@ static int lm3554_probe(struct i2c_client *client) if (flash->ctrl_handler.error) { dev_err(&client->dev, "ctrl_handler error.\n"); - goto fail3; + err = flash->ctrl_handler.error; + goto free_handler; } flash->sd.ctrl_handler = &flash->ctrl_handler; err = media_entity_pads_init(&flash->sd.entity, 0, NULL); if (err) { dev_err(&client->dev, "error initialize a media entity.\n"); - goto fail2; + goto free_handler; } flash->sd.entity.function = MEDIA_ENT_F_FLASH; @@ -884,16 +884,27 @@ static int lm3554_probe(struct i2c_client *client) err = lm3554_gpio_init(client); if (err) { - dev_err(&client->dev, "gpio request/direction_output fail"); - goto fail3; + dev_err(&client->dev, "gpio request/direction_output fail.\n"); + goto cleanup_media; + } + + err = atomisp_register_i2c_module(&flash->sd, NULL, LED_FLASH); + if (err) { + dev_err(&client->dev, "fail to register atomisp i2c module.\n"); + goto uninit_gpio; } - return atomisp_register_i2c_module(&flash->sd, NULL, LED_FLASH); -fail3: + + return 0; + +uninit_gpio: + lm3554_gpio_uninit(client); +cleanup_media: media_entity_cleanup(&flash->sd.entity); +free_handler: v4l2_ctrl_handler_free(&flash->ctrl_handler); -fail2: +unregister_subdev: v4l2_device_unregister_subdev(&flash->sd); -fail1: +free_flash: kfree(flash); return err; diff --git a/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c b/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c index 5e3670c4fc29..6c95f57a52e9 100644 --- a/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c +++ b/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c @@ -1714,6 +1714,8 @@ static int ov5693_detect(struct i2c_client *client) } ret = ov5693_read_reg(client, OV5693_8BIT, OV5693_SC_CMMN_CHIP_ID_L, &low); + if (ret) + return ret; id = ((((u16)high) << 8) | (u16)low); if (id != OV5693_ID) { diff --git a/drivers/staging/media/atomisp/pci/atomisp_csi2.c b/drivers/staging/media/atomisp/pci/atomisp_csi2.c index 11b6b1216473..4a9268bac8a9 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_csi2.c +++ b/drivers/staging/media/atomisp/pci/atomisp_csi2.c @@ -22,13 +22,11 @@ #include "atomisp_internal.h" #include "atomisp-regs.h" -static struct v4l2_mbus_framefmt *__csi2_get_format(struct - atomisp_mipi_csi2_device - * csi2, - struct v4l2_subdev_state *sd_state, - enum - v4l2_subdev_format_whence - which, unsigned int pad) +static struct +v4l2_mbus_framefmt *__csi2_get_format(struct atomisp_mipi_csi2_device *csi2, + struct v4l2_subdev_state *sd_state, + enum v4l2_subdev_format_whence which, + unsigned int pad) { if (which == V4L2_SUBDEV_FORMAT_TRY) return v4l2_subdev_get_try_format(&csi2->subdev, sd_state, @@ -43,7 +41,7 @@ static struct v4l2_mbus_framefmt *__csi2_get_format(struct * @fh : V4L2 subdev file handle * @code : pointer to v4l2_subdev_pad_mbus_code_enum structure * return -EINVAL or zero on success -*/ + */ static int csi2_enum_mbus_code(struct v4l2_subdev *sd, struct v4l2_subdev_state *sd_state, struct v4l2_subdev_mbus_code_enum *code) @@ -69,7 +67,7 @@ static int csi2_enum_mbus_code(struct v4l2_subdev *sd, * @pad: pad num * @fmt: pointer to v4l2 format structure * return -EINVAL or zero on success -*/ + */ static int csi2_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_state *sd_state, struct v4l2_subdev_format *fmt) @@ -104,12 +102,12 @@ int atomisp_csi2_set_ffmt(struct v4l2_subdev *sd, else actual_ffmt->code = atomisp_in_fmt_conv[0].code; - actual_ffmt->width = clamp_t( - u32, ffmt->width, ATOM_ISP_MIN_WIDTH, - ATOM_ISP_MAX_WIDTH); - actual_ffmt->height = clamp_t( - u32, ffmt->height, ATOM_ISP_MIN_HEIGHT, - ATOM_ISP_MAX_HEIGHT); + actual_ffmt->width = clamp_t(u32, ffmt->width, + ATOM_ISP_MIN_WIDTH, + ATOM_ISP_MAX_WIDTH); + actual_ffmt->height = clamp_t(u32, ffmt->height, + ATOM_ISP_MIN_HEIGHT, + ATOM_ISP_MAX_HEIGHT); tmp_ffmt = *ffmt = *actual_ffmt; @@ -132,7 +130,7 @@ int atomisp_csi2_set_ffmt(struct v4l2_subdev *sd, * @pad: pad num * @fmt: pointer to v4l2 format structure * return -EINVAL or zero on success -*/ + */ static int csi2_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_state *sd_state, struct v4l2_subdev_format *fmt) @@ -147,7 +145,7 @@ static int csi2_set_format(struct v4l2_subdev *sd, * @enable: Enable/disable stream (1/0) * * Return 0 on success or a negative error code otherwise. -*/ + */ static int csi2_set_stream(struct v4l2_subdev *sd, int enable) { return 0; @@ -184,7 +182,7 @@ static const struct v4l2_subdev_ops csi2_ops = { * @remote : Pointer to remote pad array * @flags : Link flags * return -EINVAL or zero on success -*/ + */ static int csi2_link_setup(struct media_entity *entity, const struct media_pad *local, const struct media_pad *remote, u32 flags) @@ -222,10 +220,10 @@ static const struct media_entity_operations csi2_media_ops = { }; /* -* ispcsi2_init_entities - Initialize subdev and media entity. -* @csi2: Pointer to ispcsi2 structure. -* return -ENOMEM or zero on success -*/ + * ispcsi2_init_entities - Initialize subdev and media entity. + * @csi2: Pointer to ispcsi2 structure. + * return -ENOMEM or zero on success + */ static int mipi_csi2_init_entities(struct atomisp_mipi_csi2_device *csi2, int port) { @@ -249,9 +247,8 @@ static int mipi_csi2_init_entities(struct atomisp_mipi_csi2_device *csi2, if (ret < 0) return ret; - csi2->formats[CSI2_PAD_SINK].code = - csi2->formats[CSI2_PAD_SOURCE].code = - atomisp_in_fmt_conv[0].code; + csi2->formats[CSI2_PAD_SINK].code = atomisp_in_fmt_conv[0].code; + csi2->formats[CSI2_PAD_SOURCE].code = atomisp_in_fmt_conv[0].code; return 0; } @@ -379,21 +376,22 @@ static void atomisp_csi2_configure_isp2401(struct atomisp_sub_device *asd) (isp->inputs[asd->input_curr].camera->ctrl_handler, &ctrl) == 0) mipi_freq = ctrl.value; - clk_termen = atomisp_csi2_configure_calc(coeff_clk_termen, - mipi_freq, TERMEN_DEFAULT); - clk_settle = atomisp_csi2_configure_calc(coeff_clk_settle, - mipi_freq, SETTLE_DEFAULT); - dat_termen = atomisp_csi2_configure_calc(coeff_dat_termen, - mipi_freq, TERMEN_DEFAULT); - dat_settle = atomisp_csi2_configure_calc(coeff_dat_settle, - mipi_freq, SETTLE_DEFAULT); + clk_termen = atomisp_csi2_configure_calc(coeff_clk_termen, mipi_freq, + TERMEN_DEFAULT); + clk_settle = atomisp_csi2_configure_calc(coeff_clk_settle, mipi_freq, + SETTLE_DEFAULT); + dat_termen = atomisp_csi2_configure_calc(coeff_dat_termen, mipi_freq, + TERMEN_DEFAULT); + dat_settle = atomisp_csi2_configure_calc(coeff_dat_settle, mipi_freq, + SETTLE_DEFAULT); + for (n = 0; n < csi2_port_lanes[port] + 1; n++) { hrt_address base = csi2_port_base[port] + csi2_lane_base[n]; atomisp_css2_hw_store_32(base + CSI2_REG_RX_CSI_DLY_CNT_TERMEN, - n == 0 ? clk_termen : dat_termen); + n == 0 ? clk_termen : dat_termen); atomisp_css2_hw_store_32(base + CSI2_REG_RX_CSI_DLY_CNT_SETTLE, - n == 0 ? clk_settle : dat_settle); + n == 0 ? clk_settle : dat_settle); } } @@ -405,7 +403,7 @@ void atomisp_csi2_configure(struct atomisp_sub_device *asd) /* * atomisp_mipi_csi2_cleanup - Routine for module driver cleanup -*/ + */ void atomisp_mipi_csi2_cleanup(struct atomisp_device *isp) { } diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/media/hantro/hantro_drv.c index 20e508158871..fb82b9297a2b 100644 --- a/drivers/staging/media/hantro/hantro_drv.c +++ b/drivers/staging/media/hantro/hantro_drv.c @@ -179,7 +179,7 @@ err_cancel_job: hantro_job_finish_no_pm(ctx->dev, ctx, VB2_BUF_STATE_ERROR); } -static struct v4l2_m2m_ops vpu_m2m_ops = { +static const struct v4l2_m2m_ops vpu_m2m_ops = { .device_run = device_run, }; @@ -263,9 +263,6 @@ static int hantro_try_ctrl(struct v4l2_ctrl *ctrl) if (sps->bit_depth_luma_minus8 != 0) /* Only 8-bit is supported */ return -EINVAL; - if (sps->flags & V4L2_HEVC_SPS_FLAG_SCALING_LIST_ENABLED) - /* No scaling support */ - return -EINVAL; } return 0; } @@ -450,6 +447,11 @@ static const struct hantro_ctrl controls[] = { }, { .codec = HANTRO_HEVC_DECODER, .cfg = { + .id = V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX, + }, + }, { + .codec = HANTRO_HEVC_DECODER, + .cfg = { .id = V4L2_CID_HANTRO_HEVC_SLICE_HEADER_SKIP, .name = "Hantro HEVC slice header skip bytes", .type = V4L2_CTRL_TYPE_INTEGER, @@ -978,7 +980,7 @@ static int hantro_probe(struct platform_device *pdev) vpu->mdev.dev = vpu->dev; strscpy(vpu->mdev.model, DRIVER_NAME, sizeof(vpu->mdev.model)); strscpy(vpu->mdev.bus_info, "platform: " DRIVER_NAME, - sizeof(vpu->mdev.model)); + sizeof(vpu->mdev.bus_info)); media_device_init(&vpu->mdev); vpu->mdev.ops = &hantro_m2m_media_ops; vpu->v4l2_dev.mdev = &vpu->mdev; diff --git a/drivers/staging/media/hantro/hantro_g1_h264_dec.c b/drivers/staging/media/hantro/hantro_g1_h264_dec.c index 236ce24ca00c..f49dbfb8a843 100644 --- a/drivers/staging/media/hantro/hantro_g1_h264_dec.c +++ b/drivers/staging/media/hantro/hantro_g1_h264_dec.c @@ -29,7 +29,7 @@ static void set_params(struct hantro_ctx *ctx, struct vb2_v4l2_buffer *src_buf) u32 reg; /* Decoder control register 0. */ - reg = G1_REG_DEC_CTRL0_DEC_AXI_WR_ID(0x0); + reg = G1_REG_DEC_CTRL0_DEC_AXI_AUTO; if (sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD) reg |= G1_REG_DEC_CTRL0_SEQ_MBAFF_E; if (sps->profile_idc > 66) { diff --git a/drivers/staging/media/hantro/hantro_g1_regs.h b/drivers/staging/media/hantro/hantro_g1_regs.h index c1756e3d5391..c623b3b0be18 100644 --- a/drivers/staging/media/hantro/hantro_g1_regs.h +++ b/drivers/staging/media/hantro/hantro_g1_regs.h @@ -68,6 +68,8 @@ #define G1_REG_DEC_CTRL0_PICORD_COUNT_E BIT(9) #define G1_REG_DEC_CTRL0_DEC_AHB_HLOCK_E BIT(8) #define G1_REG_DEC_CTRL0_DEC_AXI_WR_ID(x) (((x) & 0xff) << 0) +/* Setting AXI ID to 0xff to get auto generated ID to avoid possible conflicts */ +#define G1_REG_DEC_CTRL0_DEC_AXI_AUTO G1_REG_DEC_CTRL0_DEC_AXI_WR_ID(0xff) #define G1_REG_DEC_CTRL1 0x010 #define G1_REG_DEC_CTRL1_PIC_MB_WIDTH(x) (((x) & 0x1ff) << 23) #define G1_REG_DEC_CTRL1_MB_WIDTH_OFF(x) (((x) & 0xf) << 19) diff --git a/drivers/staging/media/hantro/hantro_g1_vp8_dec.c b/drivers/staging/media/hantro/hantro_g1_vp8_dec.c index 6180b23e7d94..851eb67f19f5 100644 --- a/drivers/staging/media/hantro/hantro_g1_vp8_dec.c +++ b/drivers/staging/media/hantro/hantro_g1_vp8_dec.c @@ -463,7 +463,8 @@ int hantro_g1_vp8_dec_run(struct hantro_ctx *ctx) G1_REG_CONFIG_DEC_MAX_BURST(16); vdpu_write_relaxed(vpu, reg, G1_REG_CONFIG); - reg = G1_REG_DEC_CTRL0_DEC_MODE(10); + reg = G1_REG_DEC_CTRL0_DEC_MODE(10) | + G1_REG_DEC_CTRL0_DEC_AXI_AUTO; if (!V4L2_VP8_FRAME_IS_KEY_FRAME(hdr)) reg |= G1_REG_DEC_CTRL0_PIC_INTER_E; if (!(hdr->flags & V4L2_VP8_FRAME_FLAG_MB_NO_SKIP_COEFF)) diff --git a/drivers/staging/media/hantro/hantro_g2_hevc_dec.c b/drivers/staging/media/hantro/hantro_g2_hevc_dec.c index 340efb57fd18..76a921163b9a 100644 --- a/drivers/staging/media/hantro/hantro_g2_hevc_dec.c +++ b/drivers/staging/media/hantro/hantro_g2_hevc_dec.c @@ -516,6 +516,56 @@ static void set_buffers(struct hantro_ctx *ctx) hantro_write_addr(vpu, G2_TILE_BSD, ctx->hevc_dec.tile_bsd.dma); } +static void prepare_scaling_list_buffer(struct hantro_ctx *ctx) +{ + struct hantro_dev *vpu = ctx->dev; + const struct hantro_hevc_dec_ctrls *ctrls = &ctx->hevc_dec.ctrls; + const struct v4l2_ctrl_hevc_scaling_matrix *sc = ctrls->scaling; + const struct v4l2_ctrl_hevc_sps *sps = ctrls->sps; + u8 *p = ((u8 *)ctx->hevc_dec.scaling_lists.cpu); + unsigned int scaling_list_enabled; + unsigned int i, j, k; + + scaling_list_enabled = !!(sps->flags & V4L2_HEVC_SPS_FLAG_SCALING_LIST_ENABLED); + hantro_reg_write(vpu, &g2_scaling_list_e, scaling_list_enabled); + + if (!scaling_list_enabled) + return; + + for (i = 0; i < ARRAY_SIZE(sc->scaling_list_dc_coef_16x16); i++) + *p++ = sc->scaling_list_dc_coef_16x16[i]; + + for (i = 0; i < ARRAY_SIZE(sc->scaling_list_dc_coef_32x32); i++) + *p++ = sc->scaling_list_dc_coef_32x32[i]; + + /* 128-bit boundary */ + p += 8; + + /* write scaling lists column by column */ + + for (i = 0; i < 6; i++) + for (j = 0; j < 4; j++) + for (k = 0; k < 4; k++) + *p++ = sc->scaling_list_4x4[i][4 * k + j]; + + for (i = 0; i < 6; i++) + for (j = 0; j < 8; j++) + for (k = 0; k < 8; k++) + *p++ = sc->scaling_list_8x8[i][8 * k + j]; + + for (i = 0; i < 6; i++) + for (j = 0; j < 8; j++) + for (k = 0; k < 8; k++) + *p++ = sc->scaling_list_16x16[i][8 * k + j]; + + for (i = 0; i < 2; i++) + for (j = 0; j < 8; j++) + for (k = 0; k < 8; k++) + *p++ = sc->scaling_list_32x32[i][8 * k + j]; + + hantro_write_addr(vpu, HEVC_SCALING_LIST, ctx->hevc_dec.scaling_lists.dma); +} + static void hantro_g2_check_idle(struct hantro_dev *vpu) { int i; @@ -556,6 +606,8 @@ int hantro_g2_hevc_dec_run(struct hantro_ctx *ctx) set_buffers(ctx); prepare_tile_info_buffer(ctx); + prepare_scaling_list_buffer(ctx); + hantro_end_prepare_run(ctx); hantro_reg_write(vpu, &g2_mode, HEVC_DEC_MODE); diff --git a/drivers/staging/media/hantro/hantro_hevc.c b/drivers/staging/media/hantro/hantro_hevc.c index 5347f5a41c2a..ee03123e7704 100644 --- a/drivers/staging/media/hantro/hantro_hevc.c +++ b/drivers/staging/media/hantro/hantro_hevc.c @@ -20,6 +20,8 @@ /* tile border coefficients of filter */ #define VERT_SAO_RAM_SIZE 48 /* bytes per pixel */ +#define SCALING_LIST_SIZE (16 * 64) + #define MAX_TILE_COLS 20 #define MAX_TILE_ROWS 22 @@ -256,6 +258,11 @@ int hantro_hevc_dec_prepare_run(struct hantro_ctx *ctx) if (WARN_ON(!ctrls->decode_params)) return -EINVAL; + ctrls->scaling = + hantro_get_ctrl(ctx, V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX); + if (WARN_ON(!ctrls->scaling)) + return -EINVAL; + ctrls->sps = hantro_get_ctrl(ctx, V4L2_CID_MPEG_VIDEO_HEVC_SPS); if (WARN_ON(!ctrls->sps)) @@ -284,6 +291,12 @@ void hantro_hevc_dec_exit(struct hantro_ctx *ctx) hevc_dec->tile_sizes.dma); hevc_dec->tile_sizes.cpu = NULL; + if (hevc_dec->scaling_lists.cpu) + dma_free_coherent(vpu->dev, hevc_dec->scaling_lists.size, + hevc_dec->scaling_lists.cpu, + hevc_dec->scaling_lists.dma); + hevc_dec->scaling_lists.cpu = NULL; + if (hevc_dec->tile_filter.cpu) dma_free_coherent(vpu->dev, hevc_dec->tile_filter.size, hevc_dec->tile_filter.cpu, @@ -327,6 +340,14 @@ int hantro_hevc_dec_init(struct hantro_ctx *ctx) hevc_dec->tile_sizes.size = size; + hevc_dec->scaling_lists.cpu = dma_alloc_coherent(vpu->dev, SCALING_LIST_SIZE, + &hevc_dec->scaling_lists.dma, + GFP_KERNEL); + if (!hevc_dec->scaling_lists.cpu) + return -ENOMEM; + + hevc_dec->scaling_lists.size = SCALING_LIST_SIZE; + hantro_hevc_ref_init(ctx); return 0; diff --git a/drivers/staging/media/hantro/hantro_hw.h b/drivers/staging/media/hantro/hantro_hw.h index df7b5e3a57b9..267a6d33a47b 100644 --- a/drivers/staging/media/hantro/hantro_hw.h +++ b/drivers/staging/media/hantro/hantro_hw.h @@ -104,6 +104,7 @@ struct hantro_h264_dec_hw_ctx { /** * struct hantro_hevc_dec_ctrls * @decode_params: Decode params + * @scaling: Scaling matrix * @sps: SPS info * @pps: PPS info * @hevc_hdr_skip_length: the number of data (in bits) to skip in the @@ -112,6 +113,7 @@ struct hantro_h264_dec_hw_ctx { */ struct hantro_hevc_dec_ctrls { const struct v4l2_ctrl_hevc_decode_params *decode_params; + const struct v4l2_ctrl_hevc_scaling_matrix *scaling; const struct v4l2_ctrl_hevc_sps *sps; const struct v4l2_ctrl_hevc_pps *pps; u32 hevc_hdr_skip_length; @@ -124,6 +126,7 @@ struct hantro_hevc_dec_ctrls { * @tile_sao: Tile SAO buffer * @tile_bsd: Tile BSD control buffer * @ref_bufs: Internal reference buffers + * @scaling_lists: Scaling lists buffer * @ref_bufs_poc: Internal reference buffers picture order count * @ref_bufs_used: Bitfield of used reference buffers * @ctrls: V4L2 controls attached to a run @@ -135,6 +138,7 @@ struct hantro_hevc_dec_hw_ctx { struct hantro_aux_buf tile_sao; struct hantro_aux_buf tile_bsd; struct hantro_aux_buf ref_bufs[NUM_REF_PICTURES]; + struct hantro_aux_buf scaling_lists; int ref_bufs_poc[NUM_REF_PICTURES]; u32 ref_bufs_used; struct hantro_hevc_dec_ctrls ctrls; diff --git a/drivers/staging/media/imx/TODO b/drivers/staging/media/imx/TODO index 2384f4c6b09d..06c94f20ecf8 100644 --- a/drivers/staging/media/imx/TODO +++ b/drivers/staging/media/imx/TODO @@ -27,8 +27,3 @@ - i.MX7: all of the above, since it uses the imx media core - i.MX7: use Frame Interval Monitor - -- i.MX7: runtime testing with parallel sensor, links setup and streaming - -- i.MX7: runtime testing with different formats, for the time only 10-bit bayer - is tested diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c index bb1305c9daaf..1caa100be33d 100644 --- a/drivers/staging/media/imx/imx-media-csi.c +++ b/drivers/staging/media/imx/imx-media-csi.c @@ -139,6 +139,8 @@ static inline bool is_parallel_16bit_bus(struct v4l2_fwnode_endpoint *ep) * Check for conditions that require the IPU to handle the * data internally as generic data, aka passthrough mode: * - raw bayer media bus formats, or + * - BT.656 and BT.1120 (8/10-bit YUV422) data can always be processed + * on-the-fly * - the CSI is receiving from a 16-bit parallel bus, or * - the CSI is receiving from an 8-bit parallel bus and the incoming * media bus format is other than UYVY8_2X8/YUYV8_2X8. @@ -147,6 +149,9 @@ static inline bool requires_passthrough(struct v4l2_fwnode_endpoint *ep, struct v4l2_mbus_framefmt *infmt, const struct imx_media_pixfmt *incc) { + if (ep->bus_type == V4L2_MBUS_BT656) // including BT.1120 + return 0; + return incc->bayer || is_parallel_16bit_bus(ep) || (is_parallel_bus(ep) && infmt->code != MEDIA_BUS_FMT_UYVY8_2X8 && @@ -1924,7 +1929,7 @@ static int imx_csi_async_register(struct csi_priv *priv) unsigned int port; int ret; - v4l2_async_notifier_init(&priv->notifier); + v4l2_async_nf_init(&priv->notifier); /* get this CSI's port id */ ret = fwnode_property_read_u32(dev_fwnode(priv->dev), "reg", &port); @@ -1935,8 +1940,8 @@ static int imx_csi_async_register(struct csi_priv *priv) port, 0, FWNODE_GRAPH_ENDPOINT_NEXT); if (ep) { - asd = v4l2_async_notifier_add_fwnode_remote_subdev( - &priv->notifier, ep, struct v4l2_async_subdev); + asd = v4l2_async_nf_add_fwnode_remote(&priv->notifier, ep, + struct v4l2_async_subdev); fwnode_handle_put(ep); @@ -1950,8 +1955,7 @@ static int imx_csi_async_register(struct csi_priv *priv) priv->notifier.ops = &csi_notify_ops; - ret = v4l2_async_subdev_notifier_register(&priv->sd, - &priv->notifier); + ret = v4l2_async_subdev_nf_register(&priv->sd, &priv->notifier); if (ret) return ret; @@ -2040,8 +2044,8 @@ static int imx_csi_probe(struct platform_device *pdev) return 0; cleanup: - v4l2_async_notifier_unregister(&priv->notifier); - v4l2_async_notifier_cleanup(&priv->notifier); + v4l2_async_nf_unregister(&priv->notifier); + v4l2_async_nf_cleanup(&priv->notifier); free: v4l2_ctrl_handler_free(&priv->ctrl_hdlr); mutex_destroy(&priv->lock); @@ -2055,8 +2059,8 @@ static int imx_csi_remove(struct platform_device *pdev) v4l2_ctrl_handler_free(&priv->ctrl_hdlr); mutex_destroy(&priv->lock); - v4l2_async_notifier_unregister(&priv->notifier); - v4l2_async_notifier_cleanup(&priv->notifier); + v4l2_async_nf_unregister(&priv->notifier); + v4l2_async_nf_cleanup(&priv->notifier); v4l2_async_unregister_subdev(sd); media_entity_cleanup(&sd->entity); @@ -2082,4 +2086,3 @@ module_platform_driver(imx_csi_driver); MODULE_DESCRIPTION("i.MX CSI subdev driver"); MODULE_AUTHOR("Steve Longerbeam <steve_longerbeam@mentor.com>"); MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:imx-ipuv3-csi"); diff --git a/drivers/staging/media/imx/imx-media-dev-common.c b/drivers/staging/media/imx/imx-media-dev-common.c index d186179388d0..80b69a9a752c 100644 --- a/drivers/staging/media/imx/imx-media-dev-common.c +++ b/drivers/staging/media/imx/imx-media-dev-common.c @@ -367,6 +367,8 @@ struct imx_media_dev *imx_media_dev_init(struct device *dev, imxmd->v4l2_dev.notify = imx_media_notify; strscpy(imxmd->v4l2_dev.name, "imx-media", sizeof(imxmd->v4l2_dev.name)); + snprintf(imxmd->md.bus_info, sizeof(imxmd->md.bus_info), + "platform:%s", dev_name(imxmd->md.dev)); media_device_init(&imxmd->md); @@ -379,7 +381,7 @@ struct imx_media_dev *imx_media_dev_init(struct device *dev, INIT_LIST_HEAD(&imxmd->vdev_list); - v4l2_async_notifier_init(&imxmd->notifier); + v4l2_async_nf_init(&imxmd->notifier); return imxmd; @@ -403,11 +405,10 @@ int imx_media_dev_notifier_register(struct imx_media_dev *imxmd, /* prepare the async subdev notifier and register it */ imxmd->notifier.ops = ops ? ops : &imx_media_notifier_ops; - ret = v4l2_async_notifier_register(&imxmd->v4l2_dev, - &imxmd->notifier); + ret = v4l2_async_nf_register(&imxmd->v4l2_dev, &imxmd->notifier); if (ret) { v4l2_err(&imxmd->v4l2_dev, - "v4l2_async_notifier_register failed with %d\n", ret); + "v4l2_async_nf_register failed with %d\n", ret); return ret; } diff --git a/drivers/staging/media/imx/imx-media-dev.c b/drivers/staging/media/imx/imx-media-dev.c index 338b8bd0bb07..f85462214e22 100644 --- a/drivers/staging/media/imx/imx-media-dev.c +++ b/drivers/staging/media/imx/imx-media-dev.c @@ -94,7 +94,7 @@ static int imx_media_probe(struct platform_device *pdev) return 0; cleanup: - v4l2_async_notifier_cleanup(&imxmd->notifier); + v4l2_async_nf_cleanup(&imxmd->notifier); v4l2_device_unregister(&imxmd->v4l2_dev); media_device_cleanup(&imxmd->md); @@ -113,9 +113,9 @@ static int imx_media_remove(struct platform_device *pdev) imxmd->m2m_vdev = NULL; } - v4l2_async_notifier_unregister(&imxmd->notifier); + v4l2_async_nf_unregister(&imxmd->notifier); imx_media_unregister_ipu_internal_subdevs(imxmd); - v4l2_async_notifier_cleanup(&imxmd->notifier); + v4l2_async_nf_cleanup(&imxmd->notifier); media_device_unregister(&imxmd->md); v4l2_device_unregister(&imxmd->v4l2_dev); media_device_cleanup(&imxmd->md); diff --git a/drivers/staging/media/imx/imx-media-of.c b/drivers/staging/media/imx/imx-media-of.c index b677cf0e0c84..59f1eb7b62bc 100644 --- a/drivers/staging/media/imx/imx-media-of.c +++ b/drivers/staging/media/imx/imx-media-of.c @@ -29,9 +29,9 @@ int imx_media_of_add_csi(struct imx_media_dev *imxmd, } /* add CSI fwnode to async notifier */ - asd = v4l2_async_notifier_add_fwnode_subdev(&imxmd->notifier, - of_fwnode_handle(csi_np), - struct v4l2_async_subdev); + asd = v4l2_async_nf_add_fwnode(&imxmd->notifier, + of_fwnode_handle(csi_np), + struct v4l2_async_subdev); if (IS_ERR(asd)) { ret = PTR_ERR(asd); if (ret == -EEXIST) diff --git a/drivers/staging/media/imx/imx6-mipi-csi2.c b/drivers/staging/media/imx/imx6-mipi-csi2.c index 9de0ebd439dc..a0941fc2907b 100644 --- a/drivers/staging/media/imx/imx6-mipi-csi2.c +++ b/drivers/staging/media/imx/imx6-mipi-csi2.c @@ -647,7 +647,7 @@ static int csi2_async_register(struct csi2_dev *csi2) struct fwnode_handle *ep; int ret; - v4l2_async_notifier_init(&csi2->notifier); + v4l2_async_nf_init(&csi2->notifier); ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(csi2->dev), 0, 0, FWNODE_GRAPH_ENDPOINT_NEXT); @@ -663,8 +663,8 @@ static int csi2_async_register(struct csi2_dev *csi2) dev_dbg(csi2->dev, "data lanes: %d\n", vep.bus.mipi_csi2.num_data_lanes); dev_dbg(csi2->dev, "flags: 0x%08x\n", vep.bus.mipi_csi2.flags); - asd = v4l2_async_notifier_add_fwnode_remote_subdev( - &csi2->notifier, ep, struct v4l2_async_subdev); + asd = v4l2_async_nf_add_fwnode_remote(&csi2->notifier, ep, + struct v4l2_async_subdev); fwnode_handle_put(ep); if (IS_ERR(asd)) @@ -672,8 +672,7 @@ static int csi2_async_register(struct csi2_dev *csi2) csi2->notifier.ops = &csi2_notify_ops; - ret = v4l2_async_subdev_notifier_register(&csi2->sd, - &csi2->notifier); + ret = v4l2_async_subdev_nf_register(&csi2->sd, &csi2->notifier); if (ret) return ret; @@ -768,8 +767,8 @@ static int csi2_probe(struct platform_device *pdev) return 0; clean_notifier: - v4l2_async_notifier_unregister(&csi2->notifier); - v4l2_async_notifier_cleanup(&csi2->notifier); + v4l2_async_nf_unregister(&csi2->notifier); + v4l2_async_nf_cleanup(&csi2->notifier); clk_disable_unprepare(csi2->dphy_clk); pllref_off: clk_disable_unprepare(csi2->pllref_clk); @@ -783,8 +782,8 @@ static int csi2_remove(struct platform_device *pdev) struct v4l2_subdev *sd = platform_get_drvdata(pdev); struct csi2_dev *csi2 = sd_to_dev(sd); - v4l2_async_notifier_unregister(&csi2->notifier); - v4l2_async_notifier_cleanup(&csi2->notifier); + v4l2_async_nf_unregister(&csi2->notifier); + v4l2_async_nf_cleanup(&csi2->notifier); v4l2_async_unregister_subdev(sd); clk_disable_unprepare(csi2->dphy_clk); clk_disable_unprepare(csi2->pllref_clk); diff --git a/drivers/staging/media/imx/imx7-media-csi.c b/drivers/staging/media/imx/imx7-media-csi.c index 127183732912..2288dadb2683 100644 --- a/drivers/staging/media/imx/imx7-media-csi.c +++ b/drivers/staging/media/imx/imx7-media-csi.c @@ -1099,13 +1099,13 @@ static int imx7_csi_async_register(struct imx7_csi *csi) struct fwnode_handle *ep; int ret; - v4l2_async_notifier_init(&csi->notifier); + v4l2_async_nf_init(&csi->notifier); ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(csi->dev), 0, 0, FWNODE_GRAPH_ENDPOINT_NEXT); if (ep) { - asd = v4l2_async_notifier_add_fwnode_remote_subdev( - &csi->notifier, ep, struct v4l2_async_subdev); + asd = v4l2_async_nf_add_fwnode_remote(&csi->notifier, ep, + struct v4l2_async_subdev); fwnode_handle_put(ep); @@ -1119,7 +1119,7 @@ static int imx7_csi_async_register(struct imx7_csi *csi) csi->notifier.ops = &imx7_csi_notify_ops; - ret = v4l2_async_subdev_notifier_register(&csi->sd, &csi->notifier); + ret = v4l2_async_subdev_nf_register(&csi->sd, &csi->notifier); if (ret) return ret; @@ -1210,12 +1210,12 @@ static int imx7_csi_probe(struct platform_device *pdev) return 0; subdev_notifier_cleanup: - v4l2_async_notifier_unregister(&csi->notifier); - v4l2_async_notifier_cleanup(&csi->notifier); + v4l2_async_nf_unregister(&csi->notifier); + v4l2_async_nf_cleanup(&csi->notifier); cleanup: - v4l2_async_notifier_unregister(&imxmd->notifier); - v4l2_async_notifier_cleanup(&imxmd->notifier); + v4l2_async_nf_unregister(&imxmd->notifier); + v4l2_async_nf_cleanup(&imxmd->notifier); v4l2_device_unregister(&imxmd->v4l2_dev); media_device_unregister(&imxmd->md); media_device_cleanup(&imxmd->md); @@ -1232,15 +1232,15 @@ static int imx7_csi_remove(struct platform_device *pdev) struct imx7_csi *csi = v4l2_get_subdevdata(sd); struct imx_media_dev *imxmd = csi->imxmd; - v4l2_async_notifier_unregister(&imxmd->notifier); - v4l2_async_notifier_cleanup(&imxmd->notifier); + v4l2_async_nf_unregister(&imxmd->notifier); + v4l2_async_nf_cleanup(&imxmd->notifier); media_device_unregister(&imxmd->md); v4l2_device_unregister(&imxmd->v4l2_dev); media_device_cleanup(&imxmd->md); - v4l2_async_notifier_unregister(&csi->notifier); - v4l2_async_notifier_cleanup(&csi->notifier); + v4l2_async_nf_unregister(&csi->notifier); + v4l2_async_nf_cleanup(&csi->notifier); v4l2_async_unregister_subdev(sd); mutex_destroy(&csi->lock); diff --git a/drivers/staging/media/imx/imx7-mipi-csis.c b/drivers/staging/media/imx/imx7-mipi-csis.c index 41e33535de55..2b73fa55c938 100644 --- a/drivers/staging/media/imx/imx7-mipi-csis.c +++ b/drivers/staging/media/imx/imx7-mipi-csis.c @@ -1162,7 +1162,7 @@ static int mipi_csis_async_register(struct csi_state *state) unsigned int i; int ret; - v4l2_async_notifier_init(&state->notifier); + v4l2_async_nf_init(&state->notifier); ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(state->dev), 0, 0, FWNODE_GRAPH_ENDPOINT_NEXT); @@ -1187,8 +1187,8 @@ static int mipi_csis_async_register(struct csi_state *state) dev_dbg(state->dev, "data lanes: %d\n", state->bus.num_data_lanes); dev_dbg(state->dev, "flags: 0x%08x\n", state->bus.flags); - asd = v4l2_async_notifier_add_fwnode_remote_subdev( - &state->notifier, ep, struct v4l2_async_subdev); + asd = v4l2_async_nf_add_fwnode_remote(&state->notifier, ep, + struct v4l2_async_subdev); if (IS_ERR(asd)) { ret = PTR_ERR(asd); goto err_parse; @@ -1198,7 +1198,7 @@ static int mipi_csis_async_register(struct csi_state *state) state->notifier.ops = &mipi_csis_notify_ops; - ret = v4l2_async_subdev_notifier_register(&state->sd, &state->notifier); + ret = v4l2_async_subdev_nf_register(&state->sd, &state->notifier); if (ret) return ret; @@ -1429,8 +1429,8 @@ unregister_all: mipi_csis_debugfs_exit(state); cleanup: media_entity_cleanup(&state->sd.entity); - v4l2_async_notifier_unregister(&state->notifier); - v4l2_async_notifier_cleanup(&state->notifier); + v4l2_async_nf_unregister(&state->notifier); + v4l2_async_nf_cleanup(&state->notifier); v4l2_async_unregister_subdev(&state->sd); disable_clock: mipi_csis_clk_disable(state); @@ -1445,8 +1445,8 @@ static int mipi_csis_remove(struct platform_device *pdev) struct csi_state *state = mipi_sd_to_csis_state(sd); mipi_csis_debugfs_exit(state); - v4l2_async_notifier_unregister(&state->notifier); - v4l2_async_notifier_cleanup(&state->notifier); + v4l2_async_nf_unregister(&state->notifier); + v4l2_async_nf_cleanup(&state->notifier); v4l2_async_unregister_subdev(&state->sd); pm_runtime_disable(&pdev->dev); diff --git a/drivers/staging/media/imx/imx8mq-mipi-csi2.c b/drivers/staging/media/imx/imx8mq-mipi-csi2.c index a6f562009b9a..7adbdd14daa9 100644 --- a/drivers/staging/media/imx/imx8mq-mipi-csi2.c +++ b/drivers/staging/media/imx/imx8mq-mipi-csi2.c @@ -643,7 +643,7 @@ static int imx8mq_mipi_csi_async_register(struct csi_state *state) unsigned int i; int ret; - v4l2_async_notifier_init(&state->notifier); + v4l2_async_nf_init(&state->notifier); ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(state->dev), 0, 0, FWNODE_GRAPH_ENDPOINT_NEXT); @@ -669,8 +669,8 @@ static int imx8mq_mipi_csi_async_register(struct csi_state *state) state->bus.num_data_lanes, state->bus.flags); - asd = v4l2_async_notifier_add_fwnode_remote_subdev(&state->notifier, - ep, struct v4l2_async_subdev); + asd = v4l2_async_nf_add_fwnode_remote(&state->notifier, ep, + struct v4l2_async_subdev); if (IS_ERR(asd)) { ret = PTR_ERR(asd); goto err_parse; @@ -680,7 +680,7 @@ static int imx8mq_mipi_csi_async_register(struct csi_state *state) state->notifier.ops = &imx8mq_mipi_csi_notify_ops; - ret = v4l2_async_subdev_notifier_register(&state->sd, &state->notifier); + ret = v4l2_async_subdev_nf_register(&state->sd, &state->notifier); if (ret) return ret; @@ -937,8 +937,8 @@ cleanup: imx8mq_mipi_csi_pm_suspend(&pdev->dev, true); media_entity_cleanup(&state->sd.entity); - v4l2_async_notifier_unregister(&state->notifier); - v4l2_async_notifier_cleanup(&state->notifier); + v4l2_async_nf_unregister(&state->notifier); + v4l2_async_nf_cleanup(&state->notifier); v4l2_async_unregister_subdev(&state->sd); icc: imx8mq_mipi_csi_release_icc(pdev); @@ -953,8 +953,8 @@ static int imx8mq_mipi_csi_remove(struct platform_device *pdev) struct v4l2_subdev *sd = platform_get_drvdata(pdev); struct csi_state *state = mipi_sd_to_csi2_state(sd); - v4l2_async_notifier_unregister(&state->notifier); - v4l2_async_notifier_cleanup(&state->notifier); + v4l2_async_nf_unregister(&state->notifier); + v4l2_async_nf_cleanup(&state->notifier); v4l2_async_unregister_subdev(&state->sd); pm_runtime_disable(&pdev->dev); diff --git a/drivers/staging/media/ipu3/include/uapi/intel-ipu3.h b/drivers/staging/media/ipu3/include/uapi/intel-ipu3.h index fa3d6ee5adf2..585f55981c86 100644 --- a/drivers/staging/media/ipu3/include/uapi/intel-ipu3.h +++ b/drivers/staging/media/ipu3/include/uapi/intel-ipu3.h @@ -234,7 +234,9 @@ struct ipu3_uapi_ae_ccm { * struct ipu3_uapi_ae_config - AE config * * @grid_cfg: config for auto exposure statistics grid. See struct - * &ipu3_uapi_ae_grid_config + * &ipu3_uapi_ae_grid_config, as Imgu did not support output + * auto exposure statistics, so user can ignore this configuration + * and use the RGB table in auto-whitebalance statistics instead. * @weights: &IPU3_UAPI_AE_WEIGHTS is based on 32x24 blocks in the grid. * Each grid cell has a corresponding value in weights LUT called * grid value, global histogram is updated based on grid value and @@ -534,6 +536,9 @@ struct ipu3_uapi_ff_status { * * @awb_raw_buffer: auto white balance meta data &ipu3_uapi_awb_raw_buffer * @ae_raw_buffer: auto exposure raw data &ipu3_uapi_ae_raw_buffer_aligned + * current Imgu does not output the auto exposure statistics + * to ae_raw_buffer, the user such as 3A algorithm can use the + * RGB table in &ipu3_uapi_awb_raw_buffer to do auto-exposure. * @af_raw_buffer: &ipu3_uapi_af_raw_buffer for auto focus meta data * @awb_fr_raw_buffer: value as specified by &ipu3_uapi_awb_fr_raw_buffer * @stats_4a_config: 4a statistics config as defined by &ipu3_uapi_4a_config. diff --git a/drivers/staging/media/ipu3/ipu3-css-fw.c b/drivers/staging/media/ipu3/ipu3-css-fw.c index 45aff76198e2..981693eed815 100644 --- a/drivers/staging/media/ipu3/ipu3-css-fw.c +++ b/drivers/staging/media/ipu3/ipu3-css-fw.c @@ -124,12 +124,11 @@ int imgu_css_fw_init(struct imgu_css *css) /* Check and display fw header info */ css->fwp = (struct imgu_fw_header *)css->fw->data; - if (css->fw->size < sizeof(struct imgu_fw_header *) || + if (css->fw->size < struct_size(css->fwp, binary_header, 1) || css->fwp->file_header.h_size != sizeof(struct imgu_fw_bi_file_h)) goto bad_fw; - if (sizeof(struct imgu_fw_bi_file_h) + - css->fwp->file_header.binary_nr * sizeof(struct imgu_fw_info) > - css->fw->size) + if (struct_size(css->fwp, binary_header, + css->fwp->file_header.binary_nr) > css->fw->size) goto bad_fw; dev_info(dev, "loaded firmware version %.64s, %u binaries, %zu bytes\n", diff --git a/drivers/staging/media/ipu3/ipu3-css-fw.h b/drivers/staging/media/ipu3/ipu3-css-fw.h index 3c078f15a295..c0bc57fd678a 100644 --- a/drivers/staging/media/ipu3/ipu3-css-fw.h +++ b/drivers/staging/media/ipu3/ipu3-css-fw.h @@ -171,7 +171,7 @@ struct imgu_fw_bi_file_h { struct imgu_fw_header { struct imgu_fw_bi_file_h file_header; - struct imgu_fw_info binary_header[1]; /* binary_nr items */ + struct imgu_fw_info binary_header[]; /* binary_nr items */ }; /******************* Firmware functions *******************/ diff --git a/drivers/staging/media/ipu3/ipu3-css.c b/drivers/staging/media/ipu3/ipu3-css.c index 608dcacf12b2..8c70497d744c 100644 --- a/drivers/staging/media/ipu3/ipu3-css.c +++ b/drivers/staging/media/ipu3/ipu3-css.c @@ -5,6 +5,7 @@ #include <linux/iopoll.h> #include <linux/slab.h> +#include "ipu3.h" #include "ipu3-css.h" #include "ipu3-css-fw.h" #include "ipu3-css-params.h" @@ -53,7 +54,6 @@ static const struct imgu_css_format imgu_css_formats[] = { .frame_format = IMGU_ABI_FRAME_FORMAT_NV12, .osys_format = IMGU_ABI_OSYS_FORMAT_NV12, .osys_tiling = IMGU_ABI_OSYS_TILING_NONE, - .bytesperpixel_num = 1 * IPU3_CSS_FORMAT_BPP_DEN, .chroma_decim = 4, .width_align = IPU3_UAPI_ISP_VEC_ELEMS, .flags = IPU3_CSS_FORMAT_FL_OUT | IPU3_CSS_FORMAT_FL_VF, @@ -64,7 +64,6 @@ static const struct imgu_css_format imgu_css_formats[] = { .frame_format = IMGU_ABI_FRAME_FORMAT_RAW_PACKED, .bayer_order = IMGU_ABI_BAYER_ORDER_BGGR, .bit_depth = 10, - .bytesperpixel_num = 64, .width_align = 2 * IPU3_UAPI_ISP_VEC_ELEMS, .flags = IPU3_CSS_FORMAT_FL_IN, }, { @@ -73,7 +72,6 @@ static const struct imgu_css_format imgu_css_formats[] = { .frame_format = IMGU_ABI_FRAME_FORMAT_RAW_PACKED, .bayer_order = IMGU_ABI_BAYER_ORDER_GBRG, .bit_depth = 10, - .bytesperpixel_num = 64, .width_align = 2 * IPU3_UAPI_ISP_VEC_ELEMS, .flags = IPU3_CSS_FORMAT_FL_IN, }, { @@ -82,7 +80,6 @@ static const struct imgu_css_format imgu_css_formats[] = { .frame_format = IMGU_ABI_FRAME_FORMAT_RAW_PACKED, .bayer_order = IMGU_ABI_BAYER_ORDER_GRBG, .bit_depth = 10, - .bytesperpixel_num = 64, .width_align = 2 * IPU3_UAPI_ISP_VEC_ELEMS, .flags = IPU3_CSS_FORMAT_FL_IN, }, { @@ -91,7 +88,6 @@ static const struct imgu_css_format imgu_css_formats[] = { .frame_format = IMGU_ABI_FRAME_FORMAT_RAW_PACKED, .bayer_order = IMGU_ABI_BAYER_ORDER_RGGB, .bit_depth = 10, - .bytesperpixel_num = 64, .width_align = 2 * IPU3_UAPI_ISP_VEC_ELEMS, .flags = IPU3_CSS_FORMAT_FL_IN, }, @@ -150,17 +146,8 @@ static int imgu_css_queue_init(struct imgu_css_queue *queue, f->height = ALIGN(clamp_t(u32, f->height, IPU3_CSS_MIN_RES, IPU3_CSS_MAX_H), 2); queue->width_pad = ALIGN(f->width, queue->css_fmt->width_align); - if (queue->css_fmt->frame_format != IMGU_ABI_FRAME_FORMAT_RAW_PACKED) - f->plane_fmt[0].bytesperline = DIV_ROUND_UP(queue->width_pad * - queue->css_fmt->bytesperpixel_num, - IPU3_CSS_FORMAT_BPP_DEN); - else - /* For packed raw, alignment for bpl is by 50 to the width */ - f->plane_fmt[0].bytesperline = - DIV_ROUND_UP(f->width, - IPU3_CSS_FORMAT_BPP_DEN) * - queue->css_fmt->bytesperpixel_num; - + f->plane_fmt[0].bytesperline = + imgu_bytesperline(f->width, queue->css_fmt->frame_format); sizeimage = f->height * f->plane_fmt[0].bytesperline; if (queue->css_fmt->chroma_decim) sizeimage += 2 * sizeimage / queue->css_fmt->chroma_decim; diff --git a/drivers/staging/media/ipu3/ipu3-css.h b/drivers/staging/media/ipu3/ipu3-css.h index 6108a068b228..ab64e9521203 100644 --- a/drivers/staging/media/ipu3/ipu3-css.h +++ b/drivers/staging/media/ipu3/ipu3-css.h @@ -82,7 +82,6 @@ struct imgu_css_format { enum imgu_abi_bayer_order bayer_order; enum imgu_abi_osys_format osys_format; enum imgu_abi_osys_tiling osys_tiling; - u32 bytesperpixel_num; /* Bytes per pixel in first plane * 50 */ u8 bit_depth; /* Effective bits per pixel */ u8 chroma_decim; /* Chroma plane decimation, 0=no chroma plane */ u8 width_align; /* Alignment requirement for width_pad */ diff --git a/drivers/staging/media/ipu3/ipu3-v4l2.c b/drivers/staging/media/ipu3/ipu3-v4l2.c index 38a240764509..0473457b4e64 100644 --- a/drivers/staging/media/ipu3/ipu3-v4l2.c +++ b/drivers/staging/media/ipu3/ipu3-v4l2.c @@ -592,11 +592,12 @@ static const struct imgu_fmt *find_format(struct v4l2_format *f, u32 type) static int imgu_vidioc_querycap(struct file *file, void *fh, struct v4l2_capability *cap) { - struct imgu_video_device *node = file_to_intel_imgu_node(file); + struct imgu_device *imgu = video_drvdata(file); strscpy(cap->driver, IMGU_NAME, sizeof(cap->driver)); strscpy(cap->card, IMGU_NAME, sizeof(cap->card)); - snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s", node->name); + snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s", + pci_name(imgu->pci_dev)); return 0; } @@ -696,7 +697,7 @@ static int imgu_fmt(struct imgu_device *imgu, unsigned int pipe, int node, /* CSS expects some format on OUT queue */ if (i != IPU3_CSS_QUEUE_OUT && - !imgu_pipe->nodes[inode].enabled) { + !imgu_pipe->nodes[inode].enabled && !try) { fmts[i] = NULL; continue; } @@ -864,7 +865,7 @@ static int imgu_vidioc_g_meta_fmt(struct file *file, void *fh, /******************** function pointers ********************/ -static struct v4l2_subdev_internal_ops imgu_subdev_internal_ops = { +static const struct v4l2_subdev_internal_ops imgu_subdev_internal_ops = { .open = imgu_subdev_open, }; @@ -1136,7 +1137,9 @@ static int imgu_v4l2_node_setup(struct imgu_device *imgu, unsigned int pipe, def_pix_fmt.height = def_bus_fmt.height; def_pix_fmt.field = def_bus_fmt.field; def_pix_fmt.num_planes = 1; - def_pix_fmt.plane_fmt[0].bytesperline = def_pix_fmt.width * 2; + def_pix_fmt.plane_fmt[0].bytesperline = + imgu_bytesperline(def_pix_fmt.width, + IMGU_ABI_FRAME_FORMAT_RAW_PACKED); def_pix_fmt.plane_fmt[0].sizeimage = def_pix_fmt.height * def_pix_fmt.plane_fmt[0].bytesperline; def_pix_fmt.flags = 0; diff --git a/drivers/staging/media/ipu3/ipu3.h b/drivers/staging/media/ipu3/ipu3.h index eb46b527dd23..d2ad0a95c5aa 100644 --- a/drivers/staging/media/ipu3/ipu3.h +++ b/drivers/staging/media/ipu3/ipu3.h @@ -164,4 +164,16 @@ void imgu_v4l2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state); int imgu_s_stream(struct imgu_device *imgu, int enable); +static inline u32 imgu_bytesperline(const unsigned int width, + enum imgu_abi_frame_format frame_format) +{ + if (frame_format == IMGU_ABI_FRAME_FORMAT_NV12) + return ALIGN(width, IPU3_UAPI_ISP_VEC_ELEMS); + /* + * 64 bytes for every 50 pixels, the line length + * in bytes is multiple of 64 (line end alignment). + */ + return DIV_ROUND_UP(width, 50) * 64; +} + #endif diff --git a/drivers/staging/media/meson/vdec/esparser.h b/drivers/staging/media/meson/vdec/esparser.h index ff51fe7fda66..9351e62c70e6 100644 --- a/drivers/staging/media/meson/vdec/esparser.h +++ b/drivers/staging/media/meson/vdec/esparser.h @@ -17,13 +17,17 @@ int esparser_power_up(struct amvdec_session *sess); /** * esparser_queue_eos() - write End Of Stream sequence to the ESPARSER * - * @core vdec core struct + * @core: vdec core struct + * @data: EOS sequence + * @len: length of EOS sequence */ int esparser_queue_eos(struct amvdec_core *core, const u8 *data, u32 len); /** * esparser_queue_all_src() - work handler that writes as many src buffers * as possible to the ESPARSER + * + * @work: work struct */ void esparser_queue_all_src(struct work_struct *work); diff --git a/drivers/staging/media/meson/vdec/vdec.c b/drivers/staging/media/meson/vdec/vdec.c index e51d69c4729d..8549d95be0f2 100644 --- a/drivers/staging/media/meson/vdec/vdec.c +++ b/drivers/staging/media/meson/vdec/vdec.c @@ -994,7 +994,6 @@ static int vdec_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct video_device *vdev; struct amvdec_core *core; - struct resource *r; const struct of_device_id *of_id; int irq; int ret; @@ -1006,13 +1005,11 @@ static int vdec_probe(struct platform_device *pdev) core->dev = dev; platform_set_drvdata(pdev, core); - r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dos"); - core->dos_base = devm_ioremap_resource(dev, r); + core->dos_base = devm_platform_ioremap_resource_byname(pdev, "dos"); if (IS_ERR(core->dos_base)) return PTR_ERR(core->dos_base); - r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "esparser"); - core->esparser_base = devm_ioremap_resource(dev, r); + core->esparser_base = devm_platform_ioremap_resource_byname(pdev, "esparser"); if (IS_ERR(core->esparser_base)) return PTR_ERR(core->esparser_base); diff --git a/drivers/staging/media/meson/vdec/vdec.h b/drivers/staging/media/meson/vdec/vdec.h index f95445ac0658..0906b8fb5cc6 100644 --- a/drivers/staging/media/meson/vdec/vdec.h +++ b/drivers/staging/media/meson/vdec/vdec.h @@ -60,10 +60,12 @@ struct amvdec_session; * @dos_clk: DOS clock * @vdec_1_clk: VDEC_1 clock * @vdec_hevc_clk: VDEC_HEVC clock + * @vdec_hevcf_clk: VDEC_HEVCF clock * @esparser_reset: RESET for the PARSER - * @vdec_dec: video device for the decoder + * @vdev_dec: video device for the decoder * @v4l2_dev: v4l2 device * @cur_sess: current decoding session + * @lock: video device lock */ struct amvdec_core { void __iomem *dos_base; @@ -88,7 +90,7 @@ struct amvdec_core { struct v4l2_device v4l2_dev; struct amvdec_session *cur_sess; - struct mutex lock; /* video device lock */ + struct mutex lock; }; /** @@ -120,6 +122,7 @@ struct amvdec_ops { * @recycle: optional call to tell the codec to recycle a dst buffer. Must go * in pair with @can_recycle * @drain: optional call if the codec has a custom way of draining + * @resume: optional call to resume after a resolution change * @eos_sequence: optional call to get an end sequence to send to esparser * for flush. Mutually exclusive with @drain. * @isr: mandatory call when the ISR triggers @@ -185,6 +188,7 @@ enum amvdec_status { * @m2m_ctx: v4l2 m2m context * @ctrl_handler: V4L2 control handler * @ctrl_min_buf_capture: V4L2 control V4L2_CID_MIN_BUFFERS_FOR_CAPTURE + * @lock: cap & out queues lock * @fmt_out: vdec pixel format for the OUTPUT queue * @pixfmt_cap: V4L2 pixel format for the CAPTURE queue * @src_buffer_size: size in bytes of the OUTPUT buffers' only plane @@ -200,9 +204,12 @@ enum amvdec_status { * @streamon_cap: stream on flag for capture queue * @streamon_out: stream on flag for output queue * @sequence_cap: capture sequence counter + * @sequence_out: output sequence counter * @should_stop: flag set if userspace signaled EOS via command * or empty buffer * @keyframe_found: flag set once a keyframe has been parsed + * @num_dst_bufs: number of destination buffers + * @changed_format: the format changed * @canvas_alloc: array of all the canvas IDs allocated * @canvas_num: number of canvas IDs allocated * @vififo_vaddr: virtual address for the VIFIFO @@ -214,6 +221,9 @@ enum amvdec_status { * @timestamps: chronological list of src timestamps * @ts_spinlock: spinlock for the timestamps list * @last_irq_jiffies: tracks last time the vdec triggered an IRQ + * @last_offset: tracks last offset of vififo + * @wrap_count: number of times the vififo wrapped around + * @fw_idx_to_vb2_idx: firmware buffer index to vb2 buffer index * @status: current decoding status * @priv: codec private data */ @@ -225,7 +235,7 @@ struct amvdec_session { struct v4l2_m2m_ctx *m2m_ctx; struct v4l2_ctrl_handler ctrl_handler; struct v4l2_ctrl *ctrl_min_buf_capture; - struct mutex lock; /* cap & out queues lock */ + struct mutex lock; const struct amvdec_format *fmt_out; u32 pixfmt_cap; diff --git a/drivers/staging/media/meson/vdec/vdec_helpers.h b/drivers/staging/media/meson/vdec/vdec_helpers.h index cfaed52ab526..88137d15aa3a 100644 --- a/drivers/staging/media/meson/vdec/vdec_helpers.h +++ b/drivers/staging/media/meson/vdec/vdec_helpers.h @@ -52,8 +52,9 @@ void amvdec_dst_buf_done_offset(struct amvdec_session *sess, * * @sess: current session * @ts: timestamp to add + * @tc: timecode to add * @offset: offset in the VIFIFO where the associated packet was written - * @flags the vb2_v4l2_buffer flags + * @flags: the vb2_v4l2_buffer flags */ void amvdec_add_ts(struct amvdec_session *sess, u64 ts, struct v4l2_timecode tc, u32 offset, u32 flags); diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c index 76e97cbe2512..951e19231da2 100644 --- a/drivers/staging/media/rkvdec/rkvdec-h264.c +++ b/drivers/staging/media/rkvdec/rkvdec-h264.c @@ -1015,8 +1015,9 @@ static int rkvdec_h264_adjust_fmt(struct rkvdec_ctx *ctx, struct v4l2_pix_format_mplane *fmt = &f->fmt.pix_mp; fmt->num_planes = 1; - fmt->plane_fmt[0].sizeimage = fmt->width * fmt->height * - RKVDEC_H264_MAX_DEPTH_IN_BYTES; + if (!fmt->plane_fmt[0].sizeimage) + fmt->plane_fmt[0].sizeimage = fmt->width * fmt->height * + RKVDEC_H264_MAX_DEPTH_IN_BYTES; return 0; } diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c index 7131156c1f2c..4fd4a2907da7 100644 --- a/drivers/staging/media/rkvdec/rkvdec.c +++ b/drivers/staging/media/rkvdec/rkvdec.c @@ -280,31 +280,20 @@ static int rkvdec_try_output_fmt(struct file *file, void *priv, return 0; } -static int rkvdec_s_fmt(struct file *file, void *priv, - struct v4l2_format *f, - int (*try_fmt)(struct file *, void *, - struct v4l2_format *)) +static int rkvdec_s_capture_fmt(struct file *file, void *priv, + struct v4l2_format *f) { struct rkvdec_ctx *ctx = fh_to_rkvdec_ctx(priv); struct vb2_queue *vq; + int ret; - if (!try_fmt) - return -EINVAL; - - vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); + /* Change not allowed if queue is busy */ + vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, + V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); if (vb2_is_busy(vq)) return -EBUSY; - return try_fmt(file, priv, f); -} - -static int rkvdec_s_capture_fmt(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct rkvdec_ctx *ctx = fh_to_rkvdec_ctx(priv); - int ret; - - ret = rkvdec_s_fmt(file, priv, f, rkvdec_try_capture_fmt); + ret = rkvdec_try_capture_fmt(file, priv, f); if (ret) return ret; @@ -319,10 +308,21 @@ static int rkvdec_s_output_fmt(struct file *file, void *priv, struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx; const struct rkvdec_coded_fmt_desc *desc; struct v4l2_format *cap_fmt; - struct vb2_queue *peer_vq; + struct vb2_queue *peer_vq, *vq; int ret; /* + * In order to support dynamic resolution change, the decoder admits + * a resolution change, as long as the pixelformat remains. Can't be + * done if streaming. + */ + vq = v4l2_m2m_get_vq(m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + if (vb2_is_streaming(vq) || + (vb2_is_busy(vq) && + f->fmt.pix_mp.pixelformat != ctx->coded_fmt.fmt.pix_mp.pixelformat)) + return -EBUSY; + + /* * Since format change on the OUTPUT queue will reset the CAPTURE * queue, we can't allow doing so when the CAPTURE queue has buffers * allocated. @@ -331,7 +331,7 @@ static int rkvdec_s_output_fmt(struct file *file, void *priv, if (vb2_is_busy(peer_vq)) return -EBUSY; - ret = rkvdec_s_fmt(file, priv, f, rkvdec_try_output_fmt); + ret = rkvdec_try_output_fmt(file, priv, f); if (ret) return ret; @@ -967,7 +967,6 @@ static const char * const rkvdec_clk_names[] = { static int rkvdec_probe(struct platform_device *pdev) { struct rkvdec_dev *rkvdec; - struct resource *res; unsigned int i; int ret, irq; @@ -999,8 +998,7 @@ static int rkvdec_probe(struct platform_device *pdev) */ clk_set_rate(rkvdec->clocks[0].clk, 500 * 1000 * 1000); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - rkvdec->regs = devm_ioremap_resource(&pdev->dev, res); + rkvdec->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(rkvdec->regs)) return PTR_ERR(rkvdec->regs); diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c b/drivers/staging/media/sunxi/cedrus/cedrus.c index c0d005dafc6c..c76fc97d97a0 100644 --- a/drivers/staging/media/sunxi/cedrus/cedrus.c +++ b/drivers/staging/media/sunxi/cedrus/cedrus.c @@ -28,6 +28,50 @@ #include "cedrus_dec.h" #include "cedrus_hw.h" +static int cedrus_try_ctrl(struct v4l2_ctrl *ctrl) +{ + if (ctrl->id == V4L2_CID_STATELESS_H264_SPS) { + const struct v4l2_ctrl_h264_sps *sps = ctrl->p_new.p_h264_sps; + + if (sps->chroma_format_idc != 1) + /* Only 4:2:0 is supported */ + return -EINVAL; + if (sps->bit_depth_luma_minus8 != sps->bit_depth_chroma_minus8) + /* Luma and chroma bit depth mismatch */ + return -EINVAL; + if (sps->bit_depth_luma_minus8 != 0) + /* Only 8-bit is supported */ + return -EINVAL; + } else if (ctrl->id == V4L2_CID_MPEG_VIDEO_HEVC_SPS) { + const struct v4l2_ctrl_hevc_sps *sps = ctrl->p_new.p_hevc_sps; + struct cedrus_ctx *ctx = container_of(ctrl->handler, struct cedrus_ctx, hdl); + + if (sps->chroma_format_idc != 1) + /* Only 4:2:0 is supported */ + return -EINVAL; + + if (sps->bit_depth_luma_minus8 != sps->bit_depth_chroma_minus8) + /* Luma and chroma bit depth mismatch */ + return -EINVAL; + + if (ctx->dev->capabilities & CEDRUS_CAPABILITY_H265_10_DEC) { + if (sps->bit_depth_luma_minus8 != 0 && sps->bit_depth_luma_minus8 != 2) + /* Only 8-bit and 10-bit are supported */ + return -EINVAL; + } else { + if (sps->bit_depth_luma_minus8 != 0) + /* Only 8-bit is supported */ + return -EINVAL; + } + } + + return 0; +} + +static const struct v4l2_ctrl_ops cedrus_ctrl_ops = { + .try_ctrl = cedrus_try_ctrl, +}; + static const struct cedrus_control cedrus_controls[] = { { .cfg = { @@ -62,6 +106,7 @@ static const struct cedrus_control cedrus_controls[] = { { .cfg = { .id = V4L2_CID_STATELESS_H264_SPS, + .ops = &cedrus_ctrl_ops, }, .codec = CEDRUS_CODEC_H264, }, @@ -120,6 +165,7 @@ static const struct cedrus_control cedrus_controls[] = { { .cfg = { .id = V4L2_CID_MPEG_VIDEO_HEVC_SPS, + .ops = &cedrus_ctrl_ops, }, .codec = CEDRUS_CODEC_H265, }, @@ -137,6 +183,12 @@ static const struct cedrus_control cedrus_controls[] = { }, { .cfg = { + .id = V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX, + }, + .codec = CEDRUS_CODEC_H265, + }, + { + .cfg = { .id = V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE, .max = V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_SLICE_BASED, .def = V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_SLICE_BASED, @@ -207,6 +259,7 @@ static int cedrus_init_ctrls(struct cedrus_dev *dev, struct cedrus_ctx *ctx) v4l2_ctrl_handler_free(hdl); kfree(ctx->ctrls); + ctx->ctrls = NULL; return hdl->error; } @@ -282,7 +335,7 @@ static int cedrus_open(struct file *file) ret = PTR_ERR(ctx->fh.m2m_ctx); goto err_ctrls; } - ctx->dst_fmt.pixelformat = V4L2_PIX_FMT_SUNXI_TILED_NV12; + ctx->dst_fmt.pixelformat = V4L2_PIX_FMT_NV12_32L32; cedrus_prepare_format(&ctx->dst_fmt); ctx->src_fmt.pixelformat = V4L2_PIX_FMT_MPEG2_SLICE; /* @@ -550,6 +603,7 @@ static const struct cedrus_variant sun50i_h6_cedrus_variant = { CEDRUS_CAPABILITY_MPEG2_DEC | CEDRUS_CAPABILITY_H264_DEC | CEDRUS_CAPABILITY_H265_DEC | + CEDRUS_CAPABILITY_H265_10_DEC | CEDRUS_CAPABILITY_VP8_DEC, .mod_rate = 600000000, }; diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h b/drivers/staging/media/sunxi/cedrus/cedrus.h index 88afba17b78b..c345f2984041 100644 --- a/drivers/staging/media/sunxi/cedrus/cedrus.h +++ b/drivers/staging/media/sunxi/cedrus/cedrus.h @@ -32,6 +32,7 @@ #define CEDRUS_CAPABILITY_H264_DEC BIT(2) #define CEDRUS_CAPABILITY_MPEG2_DEC BIT(3) #define CEDRUS_CAPABILITY_VP8_DEC BIT(4) +#define CEDRUS_CAPABILITY_H265_10_DEC BIT(5) enum cedrus_codec { CEDRUS_CODEC_MPEG2, @@ -78,6 +79,7 @@ struct cedrus_h265_run { const struct v4l2_ctrl_hevc_pps *pps; const struct v4l2_ctrl_hevc_slice_params *slice_params; const struct v4l2_ctrl_hevc_decode_params *decode_params; + const struct v4l2_ctrl_hevc_scaling_matrix *scaling_matrix; }; struct cedrus_vp8_run { diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c index 40e8c4123f76..a16c1422558f 100644 --- a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c +++ b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c @@ -72,6 +72,8 @@ void cedrus_device_run(void *priv) V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS); run.h265.decode_params = cedrus_find_control_data(ctx, V4L2_CID_MPEG_VIDEO_HEVC_DECODE_PARAMS); + run.h265.scaling_matrix = cedrus_find_control_data(ctx, + V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX); break; case V4L2_PIX_FMT_VP8_FRAME: diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c index de7442d4834d..b4173a8926d6 100644 --- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c +++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c @@ -520,6 +520,11 @@ static int cedrus_h264_start(struct cedrus_ctx *ctx) unsigned int mv_col_size; int ret; + /* + * NOTE: All buffers allocated here are only used by HW, so we + * can add DMA_ATTR_NO_KERNEL_MAPPING flag when allocating them. + */ + /* Formula for picture buffer size is taken from CedarX source. */ if (ctx->src_fmt.width > 2048) @@ -538,23 +543,23 @@ static int cedrus_h264_start(struct cedrus_ctx *ctx) ctx->codec.h264.pic_info_buf_size = pic_info_size; ctx->codec.h264.pic_info_buf = - dma_alloc_coherent(dev->dev, ctx->codec.h264.pic_info_buf_size, - &ctx->codec.h264.pic_info_buf_dma, - GFP_KERNEL); + dma_alloc_attrs(dev->dev, ctx->codec.h264.pic_info_buf_size, + &ctx->codec.h264.pic_info_buf_dma, + GFP_KERNEL, DMA_ATTR_NO_KERNEL_MAPPING); if (!ctx->codec.h264.pic_info_buf) return -ENOMEM; /* * That buffer is supposed to be 16kiB in size, and be aligned - * on 16kiB as well. However, dma_alloc_coherent provides the - * guarantee that we'll have a CPU and DMA address aligned on - * the smallest page order that is greater to the requested - * size, so we don't have to overallocate. + * on 16kiB as well. However, dma_alloc_attrs provides the + * guarantee that we'll have a DMA address aligned on the + * smallest page order that is greater to the requested size, + * so we don't have to overallocate. */ ctx->codec.h264.neighbor_info_buf = - dma_alloc_coherent(dev->dev, CEDRUS_NEIGHBOR_INFO_BUF_SIZE, - &ctx->codec.h264.neighbor_info_buf_dma, - GFP_KERNEL); + dma_alloc_attrs(dev->dev, CEDRUS_NEIGHBOR_INFO_BUF_SIZE, + &ctx->codec.h264.neighbor_info_buf_dma, + GFP_KERNEL, DMA_ATTR_NO_KERNEL_MAPPING); if (!ctx->codec.h264.neighbor_info_buf) { ret = -ENOMEM; goto err_pic_buf; @@ -582,10 +587,11 @@ static int cedrus_h264_start(struct cedrus_ctx *ctx) mv_col_size = field_size * 2 * CEDRUS_H264_FRAME_NUM; ctx->codec.h264.mv_col_buf_size = mv_col_size; - ctx->codec.h264.mv_col_buf = dma_alloc_coherent(dev->dev, - ctx->codec.h264.mv_col_buf_size, - &ctx->codec.h264.mv_col_buf_dma, - GFP_KERNEL); + ctx->codec.h264.mv_col_buf = + dma_alloc_attrs(dev->dev, + ctx->codec.h264.mv_col_buf_size, + &ctx->codec.h264.mv_col_buf_dma, + GFP_KERNEL, DMA_ATTR_NO_KERNEL_MAPPING); if (!ctx->codec.h264.mv_col_buf) { ret = -ENOMEM; goto err_neighbor_buf; @@ -600,10 +606,10 @@ static int cedrus_h264_start(struct cedrus_ctx *ctx) ctx->codec.h264.deblk_buf_size = ALIGN(ctx->src_fmt.width, 32) * 12; ctx->codec.h264.deblk_buf = - dma_alloc_coherent(dev->dev, - ctx->codec.h264.deblk_buf_size, - &ctx->codec.h264.deblk_buf_dma, - GFP_KERNEL); + dma_alloc_attrs(dev->dev, + ctx->codec.h264.deblk_buf_size, + &ctx->codec.h264.deblk_buf_dma, + GFP_KERNEL, DMA_ATTR_NO_KERNEL_MAPPING); if (!ctx->codec.h264.deblk_buf) { ret = -ENOMEM; goto err_mv_col_buf; @@ -616,10 +622,10 @@ static int cedrus_h264_start(struct cedrus_ctx *ctx) ctx->codec.h264.intra_pred_buf_size = ALIGN(ctx->src_fmt.width, 64) * 5 * 2; ctx->codec.h264.intra_pred_buf = - dma_alloc_coherent(dev->dev, - ctx->codec.h264.intra_pred_buf_size, - &ctx->codec.h264.intra_pred_buf_dma, - GFP_KERNEL); + dma_alloc_attrs(dev->dev, + ctx->codec.h264.intra_pred_buf_size, + &ctx->codec.h264.intra_pred_buf_dma, + GFP_KERNEL, DMA_ATTR_NO_KERNEL_MAPPING); if (!ctx->codec.h264.intra_pred_buf) { ret = -ENOMEM; goto err_deblk_buf; @@ -629,24 +635,28 @@ static int cedrus_h264_start(struct cedrus_ctx *ctx) return 0; err_deblk_buf: - dma_free_coherent(dev->dev, ctx->codec.h264.deblk_buf_size, - ctx->codec.h264.deblk_buf, - ctx->codec.h264.deblk_buf_dma); + dma_free_attrs(dev->dev, ctx->codec.h264.deblk_buf_size, + ctx->codec.h264.deblk_buf, + ctx->codec.h264.deblk_buf_dma, + DMA_ATTR_NO_KERNEL_MAPPING); err_mv_col_buf: - dma_free_coherent(dev->dev, ctx->codec.h264.mv_col_buf_size, - ctx->codec.h264.mv_col_buf, - ctx->codec.h264.mv_col_buf_dma); + dma_free_attrs(dev->dev, ctx->codec.h264.mv_col_buf_size, + ctx->codec.h264.mv_col_buf, + ctx->codec.h264.mv_col_buf_dma, + DMA_ATTR_NO_KERNEL_MAPPING); err_neighbor_buf: - dma_free_coherent(dev->dev, CEDRUS_NEIGHBOR_INFO_BUF_SIZE, - ctx->codec.h264.neighbor_info_buf, - ctx->codec.h264.neighbor_info_buf_dma); + dma_free_attrs(dev->dev, CEDRUS_NEIGHBOR_INFO_BUF_SIZE, + ctx->codec.h264.neighbor_info_buf, + ctx->codec.h264.neighbor_info_buf_dma, + DMA_ATTR_NO_KERNEL_MAPPING); err_pic_buf: - dma_free_coherent(dev->dev, ctx->codec.h264.pic_info_buf_size, - ctx->codec.h264.pic_info_buf, - ctx->codec.h264.pic_info_buf_dma); + dma_free_attrs(dev->dev, ctx->codec.h264.pic_info_buf_size, + ctx->codec.h264.pic_info_buf, + ctx->codec.h264.pic_info_buf_dma, + DMA_ATTR_NO_KERNEL_MAPPING); return ret; } @@ -654,23 +664,28 @@ static void cedrus_h264_stop(struct cedrus_ctx *ctx) { struct cedrus_dev *dev = ctx->dev; - dma_free_coherent(dev->dev, ctx->codec.h264.mv_col_buf_size, - ctx->codec.h264.mv_col_buf, - ctx->codec.h264.mv_col_buf_dma); - dma_free_coherent(dev->dev, CEDRUS_NEIGHBOR_INFO_BUF_SIZE, - ctx->codec.h264.neighbor_info_buf, - ctx->codec.h264.neighbor_info_buf_dma); - dma_free_coherent(dev->dev, ctx->codec.h264.pic_info_buf_size, - ctx->codec.h264.pic_info_buf, - ctx->codec.h264.pic_info_buf_dma); + dma_free_attrs(dev->dev, ctx->codec.h264.mv_col_buf_size, + ctx->codec.h264.mv_col_buf, + ctx->codec.h264.mv_col_buf_dma, + DMA_ATTR_NO_KERNEL_MAPPING); + dma_free_attrs(dev->dev, CEDRUS_NEIGHBOR_INFO_BUF_SIZE, + ctx->codec.h264.neighbor_info_buf, + ctx->codec.h264.neighbor_info_buf_dma, + DMA_ATTR_NO_KERNEL_MAPPING); + dma_free_attrs(dev->dev, ctx->codec.h264.pic_info_buf_size, + ctx->codec.h264.pic_info_buf, + ctx->codec.h264.pic_info_buf_dma, + DMA_ATTR_NO_KERNEL_MAPPING); if (ctx->codec.h264.deblk_buf_size) - dma_free_coherent(dev->dev, ctx->codec.h264.deblk_buf_size, - ctx->codec.h264.deblk_buf, - ctx->codec.h264.deblk_buf_dma); + dma_free_attrs(dev->dev, ctx->codec.h264.deblk_buf_size, + ctx->codec.h264.deblk_buf, + ctx->codec.h264.deblk_buf_dma, + DMA_ATTR_NO_KERNEL_MAPPING); if (ctx->codec.h264.intra_pred_buf_size) - dma_free_coherent(dev->dev, ctx->codec.h264.intra_pred_buf_size, - ctx->codec.h264.intra_pred_buf, - ctx->codec.h264.intra_pred_buf_dma); + dma_free_attrs(dev->dev, ctx->codec.h264.intra_pred_buf_size, + ctx->codec.h264.intra_pred_buf, + ctx->codec.h264.intra_pred_buf_dma, + DMA_ATTR_NO_KERNEL_MAPPING); } static void cedrus_h264_trigger(struct cedrus_ctx *ctx) diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c index ef0311a16d01..8829a7bab07e 100644 --- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c +++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c @@ -238,6 +238,69 @@ static void cedrus_h265_skip_bits(struct cedrus_dev *dev, int num) } } +static void cedrus_h265_write_scaling_list(struct cedrus_ctx *ctx, + struct cedrus_run *run) +{ + const struct v4l2_ctrl_hevc_scaling_matrix *scaling; + struct cedrus_dev *dev = ctx->dev; + u32 i, j, k, val; + + scaling = run->h265.scaling_matrix; + + cedrus_write(dev, VE_DEC_H265_SCALING_LIST_DC_COEF0, + (scaling->scaling_list_dc_coef_32x32[1] << 24) | + (scaling->scaling_list_dc_coef_32x32[0] << 16) | + (scaling->scaling_list_dc_coef_16x16[1] << 8) | + (scaling->scaling_list_dc_coef_16x16[0] << 0)); + + cedrus_write(dev, VE_DEC_H265_SCALING_LIST_DC_COEF1, + (scaling->scaling_list_dc_coef_16x16[5] << 24) | + (scaling->scaling_list_dc_coef_16x16[4] << 16) | + (scaling->scaling_list_dc_coef_16x16[3] << 8) | + (scaling->scaling_list_dc_coef_16x16[2] << 0)); + + cedrus_h265_sram_write_offset(dev, VE_DEC_H265_SRAM_OFFSET_SCALING_LISTS); + + for (i = 0; i < 6; i++) + for (j = 0; j < 8; j++) + for (k = 0; k < 8; k += 4) { + val = ((u32)scaling->scaling_list_8x8[i][j + (k + 3) * 8] << 24) | + ((u32)scaling->scaling_list_8x8[i][j + (k + 2) * 8] << 16) | + ((u32)scaling->scaling_list_8x8[i][j + (k + 1) * 8] << 8) | + scaling->scaling_list_8x8[i][j + k * 8]; + cedrus_write(dev, VE_DEC_H265_SRAM_DATA, val); + } + + for (i = 0; i < 2; i++) + for (j = 0; j < 8; j++) + for (k = 0; k < 8; k += 4) { + val = ((u32)scaling->scaling_list_32x32[i][j + (k + 3) * 8] << 24) | + ((u32)scaling->scaling_list_32x32[i][j + (k + 2) * 8] << 16) | + ((u32)scaling->scaling_list_32x32[i][j + (k + 1) * 8] << 8) | + scaling->scaling_list_32x32[i][j + k * 8]; + cedrus_write(dev, VE_DEC_H265_SRAM_DATA, val); + } + + for (i = 0; i < 6; i++) + for (j = 0; j < 8; j++) + for (k = 0; k < 8; k += 4) { + val = ((u32)scaling->scaling_list_16x16[i][j + (k + 3) * 8] << 24) | + ((u32)scaling->scaling_list_16x16[i][j + (k + 2) * 8] << 16) | + ((u32)scaling->scaling_list_16x16[i][j + (k + 1) * 8] << 8) | + scaling->scaling_list_16x16[i][j + k * 8]; + cedrus_write(dev, VE_DEC_H265_SRAM_DATA, val); + } + + for (i = 0; i < 6; i++) + for (j = 0; j < 4; j++) { + val = ((u32)scaling->scaling_list_4x4[i][j + 12] << 24) | + ((u32)scaling->scaling_list_4x4[i][j + 8] << 16) | + ((u32)scaling->scaling_list_4x4[i][j + 4] << 8) | + scaling->scaling_list_4x4[i][j]; + cedrus_write(dev, VE_DEC_H265_SRAM_DATA, val); + } +} + static void cedrus_h265_setup(struct cedrus_ctx *ctx, struct cedrus_run *run) { @@ -287,11 +350,12 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, ctx->codec.h265.mv_col_buf_size = num_buffers * ctx->codec.h265.mv_col_buf_unit_size; + /* Buffer is never accessed by CPU, so we can skip kernel mapping. */ ctx->codec.h265.mv_col_buf = - dma_alloc_coherent(dev->dev, - ctx->codec.h265.mv_col_buf_size, - &ctx->codec.h265.mv_col_buf_addr, - GFP_KERNEL); + dma_alloc_attrs(dev->dev, + ctx->codec.h265.mv_col_buf_size, + &ctx->codec.h265.mv_col_buf_addr, + GFP_KERNEL, DMA_ATTR_NO_KERNEL_MAPPING); if (!ctx->codec.h265.mv_col_buf) { ctx->codec.h265.mv_col_buf_size = 0; // TODO: Abort the process here. @@ -527,7 +591,12 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, /* Scaling list. */ - reg = VE_DEC_H265_SCALING_LIST_CTRL0_DEFAULT; + if (sps->flags & V4L2_HEVC_SPS_FLAG_SCALING_LIST_ENABLED) { + cedrus_h265_write_scaling_list(ctx, run); + reg = VE_DEC_H265_SCALING_LIST_CTRL0_FLAG_ENABLED; + } else { + reg = VE_DEC_H265_SCALING_LIST_CTRL0_DEFAULT; + } cedrus_write(dev, VE_DEC_H265_SCALING_LIST_CTRL0, reg); /* Neightbor information address. */ @@ -599,10 +668,11 @@ static int cedrus_h265_start(struct cedrus_ctx *ctx) /* The buffer size is calculated at setup time. */ ctx->codec.h265.mv_col_buf_size = 0; + /* Buffer is never accessed by CPU, so we can skip kernel mapping. */ ctx->codec.h265.neighbor_info_buf = - dma_alloc_coherent(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE, - &ctx->codec.h265.neighbor_info_buf_addr, - GFP_KERNEL); + dma_alloc_attrs(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE, + &ctx->codec.h265.neighbor_info_buf_addr, + GFP_KERNEL, DMA_ATTR_NO_KERNEL_MAPPING); if (!ctx->codec.h265.neighbor_info_buf) return -ENOMEM; @@ -614,16 +684,18 @@ static void cedrus_h265_stop(struct cedrus_ctx *ctx) struct cedrus_dev *dev = ctx->dev; if (ctx->codec.h265.mv_col_buf_size > 0) { - dma_free_coherent(dev->dev, ctx->codec.h265.mv_col_buf_size, - ctx->codec.h265.mv_col_buf, - ctx->codec.h265.mv_col_buf_addr); + dma_free_attrs(dev->dev, ctx->codec.h265.mv_col_buf_size, + ctx->codec.h265.mv_col_buf, + ctx->codec.h265.mv_col_buf_addr, + DMA_ATTR_NO_KERNEL_MAPPING); ctx->codec.h265.mv_col_buf_size = 0; } - dma_free_coherent(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE, - ctx->codec.h265.neighbor_info_buf, - ctx->codec.h265.neighbor_info_buf_addr); + dma_free_attrs(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE, + ctx->codec.h265.neighbor_info_buf, + ctx->codec.h265.neighbor_info_buf_addr, + DMA_ATTR_NO_KERNEL_MAPPING); } static void cedrus_h265_trigger(struct cedrus_ctx *ctx) diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c index e2f2ff609c7e..2d7663726467 100644 --- a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c +++ b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c @@ -99,7 +99,7 @@ void cedrus_dst_format_set(struct cedrus_dev *dev, cedrus_write(dev, VE_PRIMARY_FB_LINE_STRIDE, reg); break; - case V4L2_PIX_FMT_SUNXI_TILED_NV12: + case V4L2_PIX_FMT_NV12_32L32: default: reg = VE_PRIMARY_OUT_FMT_TILED_32_NV12; cedrus_write(dev, VE_PRIMARY_OUT_FMT, reg); diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h index 92ace87c1c7d..bdb062ad8682 100644 --- a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h +++ b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h @@ -494,6 +494,8 @@ #define VE_DEC_H265_ENTRY_POINT_OFFSET_ADDR (VE_ENGINE_DEC_H265 + 0x64) #define VE_DEC_H265_TILE_START_CTB (VE_ENGINE_DEC_H265 + 0x68) #define VE_DEC_H265_TILE_END_CTB (VE_ENGINE_DEC_H265 + 0x6c) +#define VE_DEC_H265_SCALING_LIST_DC_COEF0 (VE_ENGINE_DEC_H265 + 0x78) +#define VE_DEC_H265_SCALING_LIST_DC_COEF1 (VE_ENGINE_DEC_H265 + 0x7c) #define VE_DEC_H265_LOW_ADDR (VE_ENGINE_DEC_H265 + 0x80) diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c b/drivers/staging/media/sunxi/cedrus/cedrus_video.c index 825af5fd35e0..33726175d980 100644 --- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c +++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c @@ -56,7 +56,7 @@ static struct cedrus_format cedrus_formats[] = { .capabilities = CEDRUS_CAPABILITY_VP8_DEC, }, { - .pixelformat = V4L2_PIX_FMT_SUNXI_TILED_NV12, + .pixelformat = V4L2_PIX_FMT_NV12_32L32, .directions = CEDRUS_DECODE_DST, }, { @@ -124,7 +124,7 @@ void cedrus_prepare_format(struct v4l2_pix_format *pix_fmt) sizeimage = max_t(u32, SZ_1K, sizeimage); break; - case V4L2_PIX_FMT_SUNXI_TILED_NV12: + case V4L2_PIX_FMT_NV12_32L32: /* 32-aligned stride. */ bytesperline = ALIGN(width, 32); @@ -568,9 +568,9 @@ int cedrus_queue_init(void *priv, struct vb2_queue *src_vq, src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; src_vq->io_modes = VB2_MMAP | VB2_DMABUF; + src_vq->dma_attrs = DMA_ATTR_NO_KERNEL_MAPPING; src_vq->drv_priv = ctx; src_vq->buf_struct_size = sizeof(struct cedrus_buffer); - src_vq->min_buffers_needed = 1; src_vq->ops = &cedrus_qops; src_vq->mem_ops = &vb2_dma_contig_memops; src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; @@ -587,7 +587,6 @@ int cedrus_queue_init(void *priv, struct vb2_queue *src_vq, dst_vq->io_modes = VB2_MMAP | VB2_DMABUF; dst_vq->drv_priv = ctx; dst_vq->buf_struct_size = sizeof(struct cedrus_buffer); - dst_vq->min_buffers_needed = 1; dst_vq->ops = &cedrus_qops; dst_vq->mem_ops = &vb2_dma_contig_memops; dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; diff --git a/drivers/staging/media/tegra-video/vi.c b/drivers/staging/media/tegra-video/vi.c index d321790b07d9..69d9787d5338 100644 --- a/drivers/staging/media/tegra-video/vi.c +++ b/drivers/staging/media/tegra-video/vi.c @@ -1272,7 +1272,7 @@ static int tegra_channel_init(struct tegra_vi_channel *chan) } if (!IS_ENABLED(CONFIG_VIDEO_TEGRA_TPG)) - v4l2_async_notifier_init(&chan->notifier); + v4l2_async_nf_init(&chan->notifier); return 0; @@ -1811,8 +1811,8 @@ static int tegra_vi_graph_parse_one(struct tegra_vi_channel *chan, continue; } - tvge = v4l2_async_notifier_add_fwnode_subdev(&chan->notifier, remote, - struct tegra_vi_graph_entity); + tvge = v4l2_async_nf_add_fwnode(&chan->notifier, remote, + struct tegra_vi_graph_entity); if (IS_ERR(tvge)) { ret = PTR_ERR(tvge); dev_err(vi->dev, @@ -1834,7 +1834,7 @@ static int tegra_vi_graph_parse_one(struct tegra_vi_channel *chan, cleanup: dev_err(vi->dev, "failed parsing the graph: %d\n", ret); - v4l2_async_notifier_cleanup(&chan->notifier); + v4l2_async_nf_cleanup(&chan->notifier); of_node_put(node); return ret; } @@ -1868,13 +1868,12 @@ static int tegra_vi_graph_init(struct tegra_vi *vi) continue; chan->notifier.ops = &tegra_vi_async_ops; - ret = v4l2_async_notifier_register(&vid->v4l2_dev, - &chan->notifier); + ret = v4l2_async_nf_register(&vid->v4l2_dev, &chan->notifier); if (ret < 0) { dev_err(vi->dev, "failed to register channel %d notifier: %d\n", chan->portnos[0], ret); - v4l2_async_notifier_cleanup(&chan->notifier); + v4l2_async_nf_cleanup(&chan->notifier); } } @@ -1887,8 +1886,8 @@ static void tegra_vi_graph_cleanup(struct tegra_vi *vi) list_for_each_entry(chan, &vi->vi_chans, list) { vb2_video_unregister_device(&chan->video); - v4l2_async_notifier_unregister(&chan->notifier); - v4l2_async_notifier_cleanup(&chan->notifier); + v4l2_async_nf_unregister(&chan->notifier); + v4l2_async_nf_cleanup(&chan->notifier); } } |