diff options
Diffstat (limited to 'drivers/media/platform')
173 files changed, 8845 insertions, 2257 deletions
diff --git a/drivers/media/platform/allegro-dvt/allegro-core.c b/drivers/media/platform/allegro-dvt/allegro-core.c index eb03df0d8652..510c3c9661d9 100644 --- a/drivers/media/platform/allegro-dvt/allegro-core.c +++ b/drivers/media/platform/allegro-dvt/allegro-core.c @@ -197,8 +197,6 @@ static const struct regmap_config allegro_sram_config = { .cache_type = REGCACHE_NONE, }; -#define fh_to_channel(__fh) container_of(__fh, struct allegro_channel, fh) - struct allegro_channel { struct allegro_dev *dev; struct v4l2_fh fh; @@ -302,6 +300,11 @@ struct allegro_channel { unsigned int error; }; +static inline struct allegro_channel *file_to_channel(struct file *filp) +{ + return container_of(file_to_v4l2_fh(filp), struct allegro_channel, fh); +} + static inline int allegro_channel_get_i_frame_qp(struct allegro_channel *channel) { @@ -3214,8 +3217,7 @@ static int allegro_open(struct file *file) } list_add(&channel->list, &dev->channels); - file->private_data = &channel->fh; - v4l2_fh_add(&channel->fh); + v4l2_fh_add(&channel->fh, file); allegro_channel_adjust(channel); @@ -3229,7 +3231,7 @@ error: static int allegro_release(struct file *file) { - struct allegro_channel *channel = fh_to_channel(file->private_data); + struct allegro_channel *channel = file_to_channel(file); v4l2_m2m_ctx_release(channel->fh.m2m_ctx); @@ -3237,7 +3239,7 @@ static int allegro_release(struct file *file) v4l2_ctrl_handler_free(&channel->ctrl_handler); - v4l2_fh_del(&channel->fh); + v4l2_fh_del(&channel->fh, file); v4l2_fh_exit(&channel->fh); kfree(channel); @@ -3280,7 +3282,7 @@ static int allegro_enum_fmt_vid(struct file *file, void *fh, static int allegro_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f) { - struct allegro_channel *channel = fh_to_channel(fh); + struct allegro_channel *channel = file_to_channel(file); f->fmt.pix.field = V4L2_FIELD_NONE; f->fmt.pix.width = channel->width; @@ -3322,7 +3324,7 @@ static int allegro_try_fmt_vid_cap(struct file *file, void *fh, static int allegro_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f) { - struct allegro_channel *channel = fh_to_channel(fh); + struct allegro_channel *channel = file_to_channel(file); struct vb2_queue *vq; int err; @@ -3346,7 +3348,7 @@ static int allegro_s_fmt_vid_cap(struct file *file, void *fh, static int allegro_g_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *f) { - struct allegro_channel *channel = fh_to_channel(fh); + struct allegro_channel *channel = file_to_channel(file); f->fmt.pix.field = V4L2_FIELD_NONE; @@ -3393,7 +3395,7 @@ static int allegro_try_fmt_vid_out(struct file *file, void *fh, static int allegro_s_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *f) { - struct allegro_channel *channel = fh_to_channel(fh); + struct allegro_channel *channel = file_to_channel(file); int err; err = allegro_try_fmt_vid_out(file, fh, f); @@ -3434,7 +3436,7 @@ static int allegro_channel_cmd_start(struct allegro_channel *channel) static int allegro_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *cmd) { - struct allegro_channel *channel = fh_to_channel(fh); + struct allegro_channel *channel = file_to_channel(file); int err; err = v4l2_m2m_ioctl_try_encoder_cmd(file, fh, cmd); @@ -3483,8 +3485,7 @@ static int allegro_enum_framesizes(struct file *file, void *fh, static int allegro_ioctl_streamon(struct file *file, void *priv, enum v4l2_buf_type type) { - struct v4l2_fh *fh = file->private_data; - struct allegro_channel *channel = fh_to_channel(fh); + struct allegro_channel *channel = file_to_channel(file); int err; if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { @@ -3493,13 +3494,13 @@ static int allegro_ioctl_streamon(struct file *file, void *priv, return err; } - return v4l2_m2m_streamon(file, fh->m2m_ctx, type); + return v4l2_m2m_streamon(file, channel->fh.m2m_ctx, type); } static int allegro_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a) { - struct allegro_channel *channel = fh_to_channel(fh); + struct allegro_channel *channel = file_to_channel(file); struct v4l2_fract *timeperframe; if (a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) @@ -3516,7 +3517,7 @@ static int allegro_g_parm(struct file *file, void *fh, static int allegro_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a) { - struct allegro_channel *channel = fh_to_channel(fh); + struct allegro_channel *channel = file_to_channel(file); struct v4l2_fract *timeperframe; int div; diff --git a/drivers/media/platform/amlogic/c3/mipi-csi2/c3-mipi-csi2.c b/drivers/media/platform/amlogic/c3/mipi-csi2/c3-mipi-csi2.c index 1011ab3ebac7..b9e4ef3fc308 100644 --- a/drivers/media/platform/amlogic/c3/mipi-csi2/c3-mipi-csi2.c +++ b/drivers/media/platform/amlogic/c3/mipi-csi2/c3-mipi-csi2.c @@ -388,13 +388,12 @@ static void c3_mipi_csi_cfg_host(struct c3_csi_device *csi) c3_mipi_csi_write(csi, CSI2_HOST_N_LANES, csi->bus.num_data_lanes - 1); } -static int c3_mipi_csi_start_stream(struct c3_csi_device *csi, - struct v4l2_subdev *src_sd) +static int c3_mipi_csi_start_stream(struct c3_csi_device *csi) { s64 link_freq; s64 lane_rate; - link_freq = v4l2_get_link_freq(src_sd->ctrl_handler, 0, 0); + link_freq = v4l2_get_link_freq(csi->src_pad, 0, 0); if (link_freq < 0) { dev_err(csi->dev, "Unable to obtain link frequency: %lld\n", link_freq); @@ -434,7 +433,7 @@ static int c3_mipi_csi_enable_streams(struct v4l2_subdev *sd, pm_runtime_resume_and_get(csi->dev); - c3_mipi_csi_start_stream(csi, src_sd); + c3_mipi_csi_start_stream(csi); ret = v4l2_subdev_enable_streams(src_sd, csi->src_pad->index, BIT(0)); if (ret) { diff --git a/drivers/media/platform/amlogic/meson-ge2d/ge2d.c b/drivers/media/platform/amlogic/meson-ge2d/ge2d.c index 0c004bb8ba05..5744853a4003 100644 --- a/drivers/media/platform/amlogic/meson-ge2d/ge2d.c +++ b/drivers/media/platform/amlogic/meson-ge2d/ge2d.c @@ -82,6 +82,11 @@ struct ge2d_ctx { u32 xy_swap; }; +static inline struct ge2d_ctx *file_to_ge2d_ctx(struct file *filp) +{ + return container_of(file_to_v4l2_fh(filp), struct ge2d_ctx, fh); +} + struct meson_ge2d { struct v4l2_device v4l2_dev; struct v4l2_m2m_dev *m2m_dev; @@ -452,7 +457,7 @@ static int vidioc_enum_fmt(struct file *file, void *priv, struct v4l2_fmtdesc *f static int vidioc_g_selection(struct file *file, void *priv, struct v4l2_selection *s) { - struct ge2d_ctx *ctx = priv; + struct ge2d_ctx *ctx = file_to_ge2d_ctx(file); struct ge2d_frame *f; bool use_frame = false; @@ -502,7 +507,7 @@ static int vidioc_g_selection(struct file *file, void *priv, static int vidioc_s_selection(struct file *file, void *priv, struct v4l2_selection *s) { - struct ge2d_ctx *ctx = priv; + struct ge2d_ctx *ctx = file_to_ge2d_ctx(file); struct meson_ge2d *ge2d = ctx->ge2d; struct ge2d_frame *f; int ret = 0; @@ -569,8 +574,8 @@ static void vidioc_setup_cap_fmt(struct ge2d_ctx *ctx, struct v4l2_pix_format *f static int vidioc_try_fmt_cap(struct file *file, void *priv, struct v4l2_format *f) { + struct ge2d_ctx *ctx = file_to_ge2d_ctx(file); const struct ge2d_fmt *fmt = find_fmt(f); - struct ge2d_ctx *ctx = priv; struct v4l2_pix_format fmt_cap; vidioc_setup_cap_fmt(ctx, &fmt_cap); @@ -590,7 +595,7 @@ static int vidioc_try_fmt_cap(struct file *file, void *priv, struct v4l2_format static int vidioc_s_fmt_cap(struct file *file, void *priv, struct v4l2_format *f) { - struct ge2d_ctx *ctx = priv; + struct ge2d_ctx *ctx = file_to_ge2d_ctx(file); struct meson_ge2d *ge2d = ctx->ge2d; struct vb2_queue *vq; struct ge2d_frame *frm; @@ -626,7 +631,7 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv, struct v4l2_format *f static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f) { - struct ge2d_ctx *ctx = priv; + struct ge2d_ctx *ctx = file_to_ge2d_ctx(file); struct vb2_queue *vq; struct ge2d_frame *frm; @@ -665,7 +670,7 @@ static int vidioc_try_fmt_out(struct file *file, void *priv, struct v4l2_format static int vidioc_s_fmt_out(struct file *file, void *priv, struct v4l2_format *f) { - struct ge2d_ctx *ctx = priv; + struct ge2d_ctx *ctx = file_to_ge2d_ctx(file); struct meson_ge2d *ge2d = ctx->ge2d; struct vb2_queue *vq; struct ge2d_frame *frm, *frm_cap; @@ -855,8 +860,7 @@ static int ge2d_open(struct file *file) return ret; } v4l2_fh_init(&ctx->fh, video_devdata(file)); - file->private_data = &ctx->fh; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); ge2d_setup_ctrls(ctx); @@ -871,8 +875,7 @@ static int ge2d_open(struct file *file) static int ge2d_release(struct file *file) { - struct ge2d_ctx *ctx = - container_of(file->private_data, struct ge2d_ctx, fh); + struct ge2d_ctx *ctx = file_to_ge2d_ctx(file); struct meson_ge2d *ge2d = ctx->ge2d; mutex_lock(&ge2d->mutex); @@ -880,7 +883,7 @@ static int ge2d_release(struct file *file) v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); v4l2_ctrl_handler_free(&ctx->ctrl_handler); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); kfree(ctx); diff --git a/drivers/media/platform/amphion/vpu.h b/drivers/media/platform/amphion/vpu.h index cac0f1a64fea..bfd171a3ded4 100644 --- a/drivers/media/platform/amphion/vpu.h +++ b/drivers/media/platform/amphion/vpu.h @@ -328,7 +328,7 @@ static inline const char *vpu_core_type_desc(enum vpu_core_type type) static inline struct vpu_inst *to_inst(struct file *filp) { - return container_of(filp->private_data, struct vpu_inst, fh); + return container_of(file_to_v4l2_fh(filp), struct vpu_inst, fh); } #define ctrl_to_inst(ctrl) \ diff --git a/drivers/media/platform/amphion/vpu_v4l2.c b/drivers/media/platform/amphion/vpu_v4l2.c index 74668fa362e2..fcb2eff813ac 100644 --- a/drivers/media/platform/amphion/vpu_v4l2.c +++ b/drivers/media/platform/amphion/vpu_v4l2.c @@ -24,6 +24,11 @@ #include "vpu_msgs.h" #include "vpu_helpers.h" +static char *vpu_type_name(u32 type) +{ + return V4L2_TYPE_IS_OUTPUT(type) ? "output" : "capture"; +} + void vpu_inst_lock(struct vpu_inst *inst) { mutex_lock(&inst->lock); @@ -42,7 +47,7 @@ dma_addr_t vpu_get_vb_phy_addr(struct vb2_buffer *vb, u32 plane_no) vb->planes[plane_no].data_offset; } -unsigned int vpu_get_vb_length(struct vb2_buffer *vb, u32 plane_no) +static unsigned int vpu_get_vb_length(struct vb2_buffer *vb, u32 plane_no) { if (plane_no >= vb->num_planes) return 0; @@ -81,7 +86,7 @@ void vpu_v4l2_set_error(struct vpu_inst *inst) vpu_inst_unlock(inst); } -int vpu_notify_eos(struct vpu_inst *inst) +static int vpu_notify_eos(struct vpu_inst *inst) { static const struct v4l2_event ev = { .id = 0, @@ -573,7 +578,8 @@ static void vpu_vb2_buf_finish(struct vb2_buffer *vb) call_void_vop(inst, on_queue_empty, q->type); } -void vpu_vb2_buffers_return(struct vpu_inst *inst, unsigned int type, enum vb2_buffer_state state) +static void vpu_vb2_buffers_return(struct vpu_inst *inst, unsigned int type, + enum vb2_buffer_state state) { struct vb2_v4l2_buffer *buf; @@ -718,8 +724,6 @@ static int vpu_v4l2_release(struct vpu_inst *inst) v4l2_ctrl_handler_free(&inst->ctrl_handler); mutex_destroy(&inst->lock); - v4l2_fh_del(&inst->fh); - v4l2_fh_exit(&inst->fh); call_void_vop(inst, cleanup); @@ -756,7 +760,7 @@ int vpu_v4l2_open(struct file *file, struct vpu_inst *inst) inst->min_buffer_cap = 2; inst->min_buffer_out = 2; v4l2_fh_init(&inst->fh, func->vfd); - v4l2_fh_add(&inst->fh); + v4l2_fh_add(&inst->fh, file); ret = call_vop(inst, ctrl_init); if (ret) @@ -770,7 +774,6 @@ int vpu_v4l2_open(struct file *file, struct vpu_inst *inst) } inst->fh.ctrl_handler = &inst->ctrl_handler; - file->private_data = &inst->fh; inst->state = VPU_CODEC_STATE_DEINIT; inst->workqueue = alloc_ordered_workqueue("vpu_inst", WQ_MEM_RECLAIM); if (inst->workqueue) { @@ -788,6 +791,8 @@ int vpu_v4l2_open(struct file *file, struct vpu_inst *inst) return 0; error: + v4l2_fh_del(&inst->fh, file); + v4l2_fh_exit(&inst->fh); vpu_inst_put(inst); return ret; } @@ -807,6 +812,9 @@ int vpu_v4l2_close(struct file *file) call_void_vop(inst, release); vpu_inst_unlock(inst); + v4l2_fh_del(&inst->fh, file); + v4l2_fh_exit(&inst->fh); + vpu_inst_unregister(inst); vpu_inst_put(inst); diff --git a/drivers/media/platform/amphion/vpu_v4l2.h b/drivers/media/platform/amphion/vpu_v4l2.h index 56f2939fa84d..4a87b06ae520 100644 --- a/drivers/media/platform/amphion/vpu_v4l2.h +++ b/drivers/media/platform/amphion/vpu_v4l2.h @@ -26,15 +26,12 @@ void vpu_skip_frame(struct vpu_inst *inst, int count); struct vb2_v4l2_buffer *vpu_find_buf_by_sequence(struct vpu_inst *inst, u32 type, u32 sequence); struct vb2_v4l2_buffer *vpu_find_buf_by_idx(struct vpu_inst *inst, u32 type, u32 idx); void vpu_v4l2_set_error(struct vpu_inst *inst); -int vpu_notify_eos(struct vpu_inst *inst); int vpu_notify_source_change(struct vpu_inst *inst); int vpu_set_last_buffer_dequeued(struct vpu_inst *inst, bool eos); -void vpu_vb2_buffers_return(struct vpu_inst *inst, unsigned int type, enum vb2_buffer_state state); int vpu_get_num_buffers(struct vpu_inst *inst, u32 type); bool vpu_is_source_empty(struct vpu_inst *inst); dma_addr_t vpu_get_vb_phy_addr(struct vb2_buffer *vb, u32 plane_no); -unsigned int vpu_get_vb_length(struct vb2_buffer *vb, u32 plane_no); static inline struct vpu_format *vpu_get_format(struct vpu_inst *inst, u32 type) { if (V4L2_TYPE_IS_OUTPUT(type)) @@ -43,11 +40,6 @@ static inline struct vpu_format *vpu_get_format(struct vpu_inst *inst, u32 type) return &inst->cap_format; } -static inline char *vpu_type_name(u32 type) -{ - return V4L2_TYPE_IS_OUTPUT(type) ? "output" : "capture"; -} - static inline int vpu_vb_is_codecconfig(struct vb2_v4l2_buffer *vbuf) { #ifdef V4L2_BUF_FLAG_CODECCONFIG diff --git a/drivers/media/platform/aspeed/aspeed-video.c b/drivers/media/platform/aspeed/aspeed-video.c index 54cae0da9aca..b83e43245277 100644 --- a/drivers/media/platform/aspeed/aspeed-video.c +++ b/drivers/media/platform/aspeed/aspeed-video.c @@ -4,6 +4,7 @@ #include <linux/atomic.h> #include <linux/bitfield.h> +#include <linux/cleanup.h> #include <linux/clk.h> #include <linux/delay.h> #include <linux/device.h> @@ -25,6 +26,8 @@ #include <linux/workqueue.h> #include <linux/debugfs.h> #include <linux/ktime.h> +#include <linux/regmap.h> +#include <linux/mfd/syscon.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-dev.h> #include <media/v4l2-device.h> @@ -203,6 +206,25 @@ #define VE_MEM_RESTRICT_START 0x310 #define VE_MEM_RESTRICT_END 0x314 +/* SCU's registers */ +#define SCU_MISC_CTRL 0xC0 +#define SCU_DPLL_SOURCE BIT(20) + +/* GFX's registers */ +#define GFX_CTRL 0x60 +#define GFX_CTRL_ENABLE BIT(0) +#define GFX_CTRL_FMT GENMASK(9, 7) + +#define GFX_H_DISPLAY 0x70 +#define GFX_H_DISPLAY_DE GENMASK(28, 16) +#define GFX_H_DISPLAY_TOTAL GENMASK(12, 0) + +#define GFX_V_DISPLAY 0x78 +#define GFX_V_DISPLAY_DE GENMASK(27, 16) +#define GFX_V_DISPLAY_TOTAL GENMASK(11, 0) + +#define GFX_DISPLAY_ADDR 0x80 + /* * VIDEO_MODE_DETECT_DONE: a flag raised if signal lock * VIDEO_RES_CHANGE: a flag raised if res_change work on-going @@ -262,6 +284,7 @@ struct aspeed_video_perf { /* * struct aspeed_video - driver data * + * version: holds the version of aspeed SoC * res_work: holds the delayed_work for res-detection if unlock * buffers: holds the list of buffer queued from user * flags: holds the state of video @@ -273,6 +296,7 @@ struct aspeed_video_perf { * yuv420: a flag raised if JPEG subsampling is 420 * format: holds the video format * hq_mode: a flag raised if HQ is enabled. Only for VIDEO_FMT_ASPEED + * input: holds the video input * frame_rate: holds the frame_rate * jpeg_quality: holds jpeq's quality (0~11) * jpeg_hq_quality: holds hq's quality (1~12) only if hq_mode enabled @@ -298,6 +322,9 @@ struct aspeed_video { struct video_device vdev; struct mutex video_lock; /* v4l2 and videobuf2 lock */ + struct regmap *scu; + struct regmap *gfx; + u32 version; u32 jpeg_mode; u32 comp_size_read; @@ -316,6 +343,7 @@ struct aspeed_video { bool yuv420; enum aspeed_video_format format; bool hq_mode; + enum aspeed_video_input input; unsigned int frame_rate; unsigned int jpeg_quality; unsigned int jpeg_hq_quality; @@ -331,21 +359,25 @@ struct aspeed_video { #define to_aspeed_video(x) container_of((x), struct aspeed_video, v4l2_dev) struct aspeed_video_config { + u32 version; u32 jpeg_mode; u32 comp_size_read; }; static const struct aspeed_video_config ast2400_config = { + .version = 4, .jpeg_mode = AST2400_VE_SEQ_CTRL_JPEG_MODE, .comp_size_read = AST2400_VE_COMP_SIZE_READ_BACK, }; static const struct aspeed_video_config ast2500_config = { + .version = 5, .jpeg_mode = AST2500_VE_SEQ_CTRL_JPEG_MODE, .comp_size_read = AST2400_VE_COMP_SIZE_READ_BACK, }; static const struct aspeed_video_config ast2600_config = { + .version = 6, .jpeg_mode = AST2500_VE_SEQ_CTRL_JPEG_MODE, .comp_size_read = AST2600_VE_COMP_SIZE_READ_BACK, }; @@ -485,6 +517,7 @@ static const struct v4l2_dv_timings_cap aspeed_video_timings_cap = { static const char * const format_str[] = {"Standard JPEG", "Aspeed JPEG"}; +static const char * const input_str[] = {"HOST VGA", "BMC GFX"}; static unsigned int debug; @@ -609,6 +642,14 @@ static int aspeed_video_start_frame(struct aspeed_video *video) aspeed_video_free_buf(video, &video->bcd); } + if (video->input == VIDEO_INPUT_GFX) { + u32 val; + + // update input buffer address as gfx's + regmap_read(video->gfx, GFX_DISPLAY_ADDR, &val); + aspeed_video_write(video, VE_TGS_0, val); + } + spin_lock_irqsave(&video->lock, flags); buf = list_first_entry_or_null(&video->buffers, struct aspeed_video_buffer, link); @@ -1026,9 +1067,23 @@ static void aspeed_video_get_timings(struct aspeed_video *v, } } +static void aspeed_video_get_resolution_gfx(struct aspeed_video *video, + struct v4l2_bt_timings *det) +{ + u32 h_val, v_val; + + regmap_read(video->gfx, GFX_H_DISPLAY, &h_val); + regmap_read(video->gfx, GFX_V_DISPLAY, &v_val); + + det->width = FIELD_GET(GFX_H_DISPLAY_DE, h_val) + 1; + det->height = FIELD_GET(GFX_V_DISPLAY_DE, v_val) + 1; + video->v4l2_input_status = 0; +} + #define res_check(v) test_and_clear_bit(VIDEO_MODE_DETECT_DONE, &(v)->flags) -static void aspeed_video_get_resolution(struct aspeed_video *video) +static void aspeed_video_get_resolution_vga(struct aspeed_video *video, + struct v4l2_bt_timings *det) { bool invalid_resolution = true; int rc; @@ -1036,7 +1091,6 @@ static void aspeed_video_get_resolution(struct aspeed_video *video) u32 mds; u32 src_lr_edge; u32 src_tb_edge; - struct v4l2_bt_timings *det = &video->detected_timings; det->width = MIN_WIDTH; det->height = MIN_HEIGHT; @@ -1113,14 +1167,20 @@ static void aspeed_video_get_resolution(struct aspeed_video *video) aspeed_video_get_timings(video, det); - /* - * Enable mode-detect watchdog, resolution-change watchdog and - * automatic compression after frame capture. - */ + /* Enable mode-detect watchdog, resolution-change watchdog */ aspeed_video_update(video, VE_INTERRUPT_CTRL, 0, VE_INTERRUPT_MODE_DETECT_WD); - aspeed_video_update(video, VE_SEQ_CTRL, 0, - VE_SEQ_CTRL_AUTO_COMP | VE_SEQ_CTRL_EN_WATCHDOG); + aspeed_video_update(video, VE_SEQ_CTRL, 0, VE_SEQ_CTRL_EN_WATCHDOG); +} + +static void aspeed_video_get_resolution(struct aspeed_video *video) +{ + struct v4l2_bt_timings *det = &video->detected_timings; + + if (video->input == VIDEO_INPUT_GFX) + aspeed_video_get_resolution_gfx(video, det); + else + aspeed_video_get_resolution_vga(video, det); v4l2_dbg(1, debug, &video->v4l2_dev, "Got resolution: %dx%d\n", det->width, det->height); @@ -1156,7 +1216,7 @@ static void aspeed_video_set_resolution(struct aspeed_video *video) aspeed_video_write(video, VE_SRC_SCANLINE_OFFSET, act->width * 4); /* Don't use direct mode below 1024 x 768 (irqs don't fire) */ - if (size < DIRECT_FETCH_THRESHOLD) { + if (video->input == VIDEO_INPUT_VGA && size < DIRECT_FETCH_THRESHOLD) { v4l2_dbg(1, debug, &video->v4l2_dev, "Capture: Sync Mode\n"); aspeed_video_write(video, VE_TGS_0, FIELD_PREP(VE_TGS_FIRST, @@ -1171,10 +1231,20 @@ static void aspeed_video_set_resolution(struct aspeed_video *video) VE_CTRL_INT_DE | VE_CTRL_DIRECT_FETCH, VE_CTRL_INT_DE); } else { + u32 ctrl, val, bpp; + v4l2_dbg(1, debug, &video->v4l2_dev, "Capture: Direct Mode\n"); + ctrl = VE_CTRL_DIRECT_FETCH; + if (video->input == VIDEO_INPUT_GFX) { + regmap_read(video->gfx, GFX_CTRL, &val); + bpp = FIELD_GET(GFX_CTRL_FMT, val) ? 32 : 16; + if (bpp == 16) + ctrl |= VE_CTRL_INT_DE; + aspeed_video_write(video, VE_TGS_1, act->width * (bpp >> 3)); + } aspeed_video_update(video, VE_CTRL, VE_CTRL_INT_DE | VE_CTRL_DIRECT_FETCH, - VE_CTRL_DIRECT_FETCH); + ctrl); } size *= 4; @@ -1207,6 +1277,22 @@ err_mem: aspeed_video_free_buf(video, &video->srcs[0]); } +/* + * Update relative parameters when timing changed. + * + * @video: the struct of aspeed_video + * @timings: the new timings + */ +static void aspeed_video_update_timings(struct aspeed_video *video, struct v4l2_bt_timings *timings) +{ + video->active_timings = *timings; + aspeed_video_set_resolution(video); + + video->pix_fmt.width = timings->width; + video->pix_fmt.height = timings->height; + video->pix_fmt.sizeimage = video->max_compressed_size; +} + static void aspeed_video_update_regs(struct aspeed_video *video) { u8 jpeg_hq_quality = clamp((int)video->jpeg_hq_quality - 1, 0, @@ -1219,6 +1305,8 @@ static void aspeed_video_update_regs(struct aspeed_video *video) u32 ctrl = 0; u32 seq_ctrl = 0; + v4l2_dbg(1, debug, &video->v4l2_dev, "input(%s)\n", + input_str[video->input]); v4l2_dbg(1, debug, &video->v4l2_dev, "framerate(%d)\n", video->frame_rate); v4l2_dbg(1, debug, &video->v4l2_dev, "jpeg format(%s) subsample(%s)\n", @@ -1234,6 +1322,9 @@ static void aspeed_video_update_regs(struct aspeed_video *video) else aspeed_video_update(video, VE_BCD_CTRL, VE_BCD_CTRL_EN_BCD, 0); + if (video->input == VIDEO_INPUT_VGA) + ctrl |= VE_CTRL_AUTO_OR_CURSOR; + if (video->frame_rate) ctrl |= FIELD_PREP(VE_CTRL_FRC, video->frame_rate); @@ -1252,7 +1343,9 @@ static void aspeed_video_update_regs(struct aspeed_video *video) aspeed_video_update(video, VE_SEQ_CTRL, video->jpeg_mode | VE_SEQ_CTRL_YUV420, seq_ctrl); - aspeed_video_update(video, VE_CTRL, VE_CTRL_FRC, ctrl); + aspeed_video_update(video, VE_CTRL, + VE_CTRL_FRC | VE_CTRL_AUTO_OR_CURSOR | + VE_CTRL_SOURCE, ctrl); aspeed_video_update(video, VE_COMP_CTRL, VE_COMP_CTRL_DCT_LUM | VE_COMP_CTRL_DCT_CHR | VE_COMP_CTRL_EN_HQ | VE_COMP_CTRL_HQ_DCT_LUM | @@ -1280,6 +1373,7 @@ static void aspeed_video_init_regs(struct aspeed_video *video) aspeed_video_write(video, VE_JPEG_ADDR, video->jpeg.dma); /* Set control registers */ + aspeed_video_write(video, VE_SEQ_CTRL, VE_SEQ_CTRL_AUTO_COMP); aspeed_video_write(video, VE_CTRL, ctrl); aspeed_video_write(video, VE_COMP_CTRL, VE_COMP_CTRL_RSVD); @@ -1311,12 +1405,7 @@ static void aspeed_video_start(struct aspeed_video *video) aspeed_video_get_resolution(video); /* Set timings since the device is being opened for the first time */ - video->active_timings = video->detected_timings; - aspeed_video_set_resolution(video); - - video->pix_fmt.width = video->active_timings.width; - video->pix_fmt.height = video->active_timings.height; - video->pix_fmt.sizeimage = video->max_compressed_size; + aspeed_video_update_timings(video, &video->detected_timings); } static void aspeed_video_stop(struct aspeed_video *video) @@ -1401,10 +1490,10 @@ static int aspeed_video_enum_input(struct file *file, void *fh, { struct aspeed_video *video = video_drvdata(file); - if (inp->index) + if (inp->index >= VIDEO_INPUT_MAX) return -EINVAL; - strscpy(inp->name, "Host VGA capture", sizeof(inp->name)); + sprintf(inp->name, "%s capture", input_str[inp->index]); inp->type = V4L2_INPUT_TYPE_CAMERA; inp->capabilities = V4L2_IN_CAP_DV_TIMINGS; inp->status = video->v4l2_input_status; @@ -1414,16 +1503,57 @@ static int aspeed_video_enum_input(struct file *file, void *fh, static int aspeed_video_get_input(struct file *file, void *fh, unsigned int *i) { - *i = 0; + struct aspeed_video *video = video_drvdata(file); + + *i = video->input; return 0; } static int aspeed_video_set_input(struct file *file, void *fh, unsigned int i) { - if (i) + struct aspeed_video *video = video_drvdata(file); + + if (i >= VIDEO_INPUT_MAX) return -EINVAL; + if (i == video->input) + return 0; + + if (vb2_is_busy(&video->queue)) + return -EBUSY; + + if (IS_ERR(video->scu)) { + v4l2_dbg(1, debug, &video->v4l2_dev, + "%s: scu isn't ready for input-control\n", __func__); + return -EINVAL; + } + + if (IS_ERR(video->gfx) && i == VIDEO_INPUT_GFX) { + v4l2_dbg(1, debug, &video->v4l2_dev, + "%s: gfx isn't ready for GFX input\n", __func__); + return -EINVAL; + } + + video->input = i; + + if (video->version == 6) { + /* modify dpll source per current input */ + if (video->input == VIDEO_INPUT_VGA) + regmap_update_bits(video->scu, SCU_MISC_CTRL, + SCU_DPLL_SOURCE, 0); + else + regmap_update_bits(video->scu, SCU_MISC_CTRL, + SCU_DPLL_SOURCE, SCU_DPLL_SOURCE); + } + + aspeed_video_update_regs(video); + + /* update signal status */ + aspeed_video_get_resolution(video); + if (!video->v4l2_input_status) + aspeed_video_update_timings(video, &video->detected_timings); + return 0; } @@ -1527,13 +1657,7 @@ static int aspeed_video_set_dv_timings(struct file *file, void *fh, if (vb2_is_busy(&video->queue)) return -EBUSY; - video->active_timings = timings->bt; - - aspeed_video_set_resolution(video); - - video->pix_fmt.width = timings->bt.width; - video->pix_fmt.height = timings->bt.height; - video->pix_fmt.sizeimage = video->max_compressed_size; + aspeed_video_update_timings(video, &timings->bt); timings->type = V4L2_DV_BT_656_1120; @@ -1909,6 +2033,7 @@ static int aspeed_video_debugfs_show(struct seq_file *s, void *data) val08 = aspeed_video_read(v, VE_CTRL); if (FIELD_GET(VE_CTRL_DIRECT_FETCH, val08)) { seq_printf(s, " %-20s:\tDirect fetch\n", "Mode"); + seq_printf(s, " %-20s:\t%s\n", "Input", input_str[v->input]); seq_printf(s, " %-20s:\t%s\n", "VGA bpp mode", FIELD_GET(VE_CTRL_INT_DE, val08) ? "16" : "32"); } else { @@ -2068,12 +2193,29 @@ static int aspeed_video_setup_video(struct aspeed_video *video) return 0; } +/* + * Get regmap without checking res, such as clk/reset, that could lead to + * conflict. + */ +static struct regmap *aspeed_regmap_lookup(struct device_node *np, const char *property) +{ + struct device_node *syscon_np __free(device_node) = of_parse_phandle(np, property, 0); + + if (!syscon_np) + return ERR_PTR(-ENODEV); + + return device_node_to_regmap(syscon_np); +} + static int aspeed_video_init(struct aspeed_video *video) { int irq; int rc; struct device *dev = video->dev; + video->scu = aspeed_regmap_lookup(dev->of_node, "aspeed,scu"); + video->gfx = aspeed_regmap_lookup(dev->of_node, "aspeed,gfx"); + irq = irq_of_parse_and_map(dev->of_node, 0); if (!irq) { dev_err(dev, "Unable to find IRQ\n"); @@ -2165,6 +2307,7 @@ static int aspeed_video_probe(struct platform_device *pdev) if (!config) return -ENODEV; + video->version = config->version; video->jpeg_mode = config->jpeg_mode; video->comp_size_read = config->comp_size_read; diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c index 7f1ce95cdc3f..8c19f125da3e 100644 --- a/drivers/media/platform/cadence/cdns-csi2rx.c +++ b/drivers/media/platform/cadence/cdns-csi2rx.c @@ -5,8 +5,10 @@ * Copyright (C) 2017 Cadence Design Systems Inc. */ +#include <linux/bitfield.h> #include <linux/clk.h> #include <linux/delay.h> +#include <linux/export.h> #include <linux/io.h> #include <linux/iopoll.h> #include <linux/module.h> @@ -17,6 +19,7 @@ #include <linux/reset.h> #include <linux/slab.h> +#include <media/cadence/cdns-csi2rx.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> #include <media/v4l2-fwnode.h> @@ -52,7 +55,9 @@ #define CSI2RX_STREAM_DATA_CFG_VC_SELECT(n) BIT((n) + 16) #define CSI2RX_STREAM_CFG_REG(n) (CSI2RX_STREAM_BASE(n) + 0x00c) -#define CSI2RX_STREAM_CFG_FIFO_MODE_LARGE_BUF (1 << 8) +#define CSI2RX_STREAM_CFG_FIFO_MODE_LARGE_BUF BIT(8) +#define CSI2RX_STREAM_CFG_NUM_PIXELS_MASK GENMASK(5, 4) +#define CSI2RX_STREAM_CFG_NUM_PIXELS(n) ((n) >> 1U) #define CSI2RX_LANES_MAX 4 #define CSI2RX_STREAMS_MAX 4 @@ -87,7 +92,10 @@ enum csi2rx_pads { struct csi2rx_fmt { u32 code; + /* width of a single pixel on CSI-2 bus */ u8 bpp; + /* max pixels per clock supported on output bus */ + u8 max_pixels; }; struct csi2rx_event { @@ -132,6 +140,7 @@ struct csi2rx_priv { struct reset_control *pixel_rst[CSI2RX_STREAMS_MAX]; struct phy *dphy; + u8 num_pixels[CSI2RX_STREAMS_MAX]; u8 lanes[CSI2RX_LANES_MAX]; u8 num_lanes; u8 max_lanes; @@ -149,22 +158,22 @@ struct csi2rx_priv { }; static const struct csi2rx_fmt formats[] = { - { .code = MEDIA_BUS_FMT_YUYV8_1X16, .bpp = 16, }, - { .code = MEDIA_BUS_FMT_UYVY8_1X16, .bpp = 16, }, - { .code = MEDIA_BUS_FMT_YVYU8_1X16, .bpp = 16, }, - { .code = MEDIA_BUS_FMT_VYUY8_1X16, .bpp = 16, }, - { .code = MEDIA_BUS_FMT_SBGGR8_1X8, .bpp = 8, }, - { .code = MEDIA_BUS_FMT_SGBRG8_1X8, .bpp = 8, }, - { .code = MEDIA_BUS_FMT_SGRBG8_1X8, .bpp = 8, }, - { .code = MEDIA_BUS_FMT_SRGGB8_1X8, .bpp = 8, }, - { .code = MEDIA_BUS_FMT_Y8_1X8, .bpp = 8, }, - { .code = MEDIA_BUS_FMT_SBGGR10_1X10, .bpp = 10, }, - { .code = MEDIA_BUS_FMT_SGBRG10_1X10, .bpp = 10, }, - { .code = MEDIA_BUS_FMT_SGRBG10_1X10, .bpp = 10, }, - { .code = MEDIA_BUS_FMT_SRGGB10_1X10, .bpp = 10, }, - { .code = MEDIA_BUS_FMT_RGB565_1X16, .bpp = 16, }, - { .code = MEDIA_BUS_FMT_RGB888_1X24, .bpp = 24, }, - { .code = MEDIA_BUS_FMT_BGR888_1X24, .bpp = 24, }, + { .code = MEDIA_BUS_FMT_YUYV8_1X16, .bpp = 16, .max_pixels = 2, }, + { .code = MEDIA_BUS_FMT_UYVY8_1X16, .bpp = 16, .max_pixels = 2, }, + { .code = MEDIA_BUS_FMT_YVYU8_1X16, .bpp = 16, .max_pixels = 2, }, + { .code = MEDIA_BUS_FMT_VYUY8_1X16, .bpp = 16, .max_pixels = 2, }, + { .code = MEDIA_BUS_FMT_SBGGR8_1X8, .bpp = 8, .max_pixels = 4, }, + { .code = MEDIA_BUS_FMT_SGBRG8_1X8, .bpp = 8, .max_pixels = 4, }, + { .code = MEDIA_BUS_FMT_SGRBG8_1X8, .bpp = 8, .max_pixels = 4, }, + { .code = MEDIA_BUS_FMT_SRGGB8_1X8, .bpp = 8, .max_pixels = 4, }, + { .code = MEDIA_BUS_FMT_Y8_1X8, .bpp = 8, .max_pixels = 4, }, + { .code = MEDIA_BUS_FMT_SBGGR10_1X10, .bpp = 10, .max_pixels = 2, }, + { .code = MEDIA_BUS_FMT_SGBRG10_1X10, .bpp = 10, .max_pixels = 2, }, + { .code = MEDIA_BUS_FMT_SGRBG10_1X10, .bpp = 10, .max_pixels = 2, }, + { .code = MEDIA_BUS_FMT_SRGGB10_1X10, .bpp = 10, .max_pixels = 2, }, + { .code = MEDIA_BUS_FMT_RGB565_1X16, .bpp = 16, .max_pixels = 1, }, + { .code = MEDIA_BUS_FMT_RGB888_1X24, .bpp = 24, .max_pixels = 1, }, + { .code = MEDIA_BUS_FMT_BGR888_1X24, .bpp = 24, .max_pixels = 1, }, }; static void csi2rx_configure_error_irq_mask(void __iomem *base, @@ -370,7 +379,9 @@ static int csi2rx_start(struct csi2rx_priv *csi2rx) reset_control_deassert(csi2rx->pixel_rst[i]); - writel(CSI2RX_STREAM_CFG_FIFO_MODE_LARGE_BUF, + writel(CSI2RX_STREAM_CFG_FIFO_MODE_LARGE_BUF | + FIELD_PREP(CSI2RX_STREAM_CFG_NUM_PIXELS_MASK, + csi2rx->num_pixels[i]), csi2rx->base + CSI2RX_STREAM_CFG_REG(i)); /* @@ -569,6 +580,33 @@ static int csi2rx_init_state(struct v4l2_subdev *subdev, return csi2rx_set_fmt(subdev, state, &format); } +int cdns_csi2rx_negotiate_ppc(struct v4l2_subdev *subdev, unsigned int pad, + u8 *ppc) +{ + struct csi2rx_priv *csi2rx = v4l2_subdev_to_csi2rx(subdev); + const struct csi2rx_fmt *csi_fmt; + struct v4l2_subdev_state *state; + struct v4l2_mbus_framefmt *fmt; + + if (!ppc || pad < CSI2RX_PAD_SOURCE_STREAM0 || pad >= CSI2RX_PAD_MAX) + return -EINVAL; + + state = v4l2_subdev_lock_and_get_active_state(subdev); + fmt = v4l2_subdev_state_get_format(state, pad); + csi_fmt = csi2rx_get_fmt_by_code(fmt->code); + + /* Reduce requested PPC if it is too high */ + *ppc = min(*ppc, csi_fmt->max_pixels); + + v4l2_subdev_unlock_state(state); + + csi2rx->num_pixels[pad - CSI2RX_PAD_SOURCE_STREAM0] = + CSI2RX_STREAM_CFG_NUM_PIXELS(*ppc); + + return 0; +} +EXPORT_SYMBOL_FOR_MODULES(cdns_csi2rx_negotiate_ppc, "j721e-csi2rx"); + static const struct v4l2_subdev_pad_ops csi2rx_pad_ops = { .enum_mbus_code = csi2rx_enum_mbus_code, .get_fmt = v4l2_subdev_get_fmt, @@ -595,6 +633,7 @@ static const struct v4l2_subdev_internal_ops csi2rx_internal_ops = { static const struct media_entity_operations csi2rx_media_ops = { .link_validate = v4l2_subdev_link_validate, + .get_fwnode_pad = v4l2_subdev_get_fwnode_pad_1_to_1, }; static int csi2rx_async_bound(struct v4l2_async_notifier *notifier, diff --git a/drivers/media/platform/chips-media/coda/coda-common.c b/drivers/media/platform/chips-media/coda/coda-common.c index e6e3f5ec24f6..9a57b042d9fd 100644 --- a/drivers/media/platform/chips-media/coda/coda-common.c +++ b/drivers/media/platform/chips-media/coda/coda-common.c @@ -56,6 +56,11 @@ #define fh_to_ctx(__fh) container_of(__fh, struct coda_ctx, fh) +static inline struct coda_ctx *file_to_ctx(struct file *filp) +{ + return fh_to_ctx(file_to_v4l2_fh(filp)); +} + int coda_debug; module_param(coda_debug, int, 0644); MODULE_PARM_DESC(coda_debug, "Debug level (0-2)"); @@ -422,7 +427,7 @@ out: static int coda_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { - struct coda_ctx *ctx = fh_to_ctx(priv); + struct coda_ctx *ctx = file_to_ctx(file); strscpy(cap->driver, CODA_NAME, sizeof(cap->driver)); strscpy(cap->card, coda_product_name(ctx->dev->devtype->product), @@ -442,7 +447,7 @@ static int coda_enum_fmt(struct file *file, void *priv, { struct video_device *vdev = video_devdata(file); const struct coda_video_device *cvd = to_coda_video_device(vdev); - struct coda_ctx *ctx = fh_to_ctx(priv); + struct coda_ctx *ctx = file_to_ctx(file); const u32 *formats; if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) @@ -492,7 +497,7 @@ static int coda_g_fmt(struct file *file, void *priv, struct v4l2_format *f) { struct coda_q_data *q_data; - struct coda_ctx *ctx = fh_to_ctx(priv); + struct coda_ctx *ctx = file_to_ctx(file); q_data = get_q_data(ctx, f->type); if (!q_data) @@ -653,7 +658,7 @@ static int coda_try_fmt(struct coda_ctx *ctx, const struct coda_codec *codec, static int coda_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - struct coda_ctx *ctx = fh_to_ctx(priv); + struct coda_ctx *ctx = file_to_ctx(file); const struct coda_q_data *q_data_src; const struct coda_codec *codec; struct vb2_queue *src_vq; @@ -759,7 +764,7 @@ static void coda_set_default_colorspace(struct v4l2_pix_format *fmt) static int coda_try_fmt_vid_out(struct file *file, void *priv, struct v4l2_format *f) { - struct coda_ctx *ctx = fh_to_ctx(priv); + struct coda_ctx *ctx = file_to_ctx(file); struct coda_dev *dev = ctx->dev; const struct coda_q_data *q_data_dst; const struct coda_codec *codec; @@ -853,7 +858,7 @@ static int coda_s_fmt(struct coda_ctx *ctx, struct v4l2_format *f, static int coda_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - struct coda_ctx *ctx = fh_to_ctx(priv); + struct coda_ctx *ctx = file_to_ctx(file); struct coda_q_data *q_data_src; const struct coda_codec *codec; struct v4l2_rect r; @@ -905,7 +910,7 @@ static int coda_s_fmt_vid_cap(struct file *file, void *priv, static int coda_s_fmt_vid_out(struct file *file, void *priv, struct v4l2_format *f) { - struct coda_ctx *ctx = fh_to_ctx(priv); + struct coda_ctx *ctx = file_to_ctx(file); const struct coda_codec *codec; struct v4l2_format f_cap; struct vb2_queue *dst_vq; @@ -961,7 +966,7 @@ static int coda_s_fmt_vid_out(struct file *file, void *priv, static int coda_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *rb) { - struct coda_ctx *ctx = fh_to_ctx(priv); + struct coda_ctx *ctx = file_to_ctx(file); int ret; ret = v4l2_m2m_reqbufs(file, ctx->fh.m2m_ctx, rb); @@ -981,7 +986,7 @@ static int coda_reqbufs(struct file *file, void *priv, static int coda_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) { - struct coda_ctx *ctx = fh_to_ctx(priv); + struct coda_ctx *ctx = file_to_ctx(file); if (ctx->inst_type == CODA_INST_DECODER && buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) @@ -992,7 +997,7 @@ static int coda_qbuf(struct file *file, void *priv, static int coda_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) { - struct coda_ctx *ctx = fh_to_ctx(priv); + struct coda_ctx *ctx = file_to_ctx(file); int ret; ret = v4l2_m2m_dqbuf(file, ctx->fh.m2m_ctx, buf); @@ -1020,7 +1025,7 @@ void coda_m2m_buf_done(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf, static int coda_g_selection(struct file *file, void *fh, struct v4l2_selection *s) { - struct coda_ctx *ctx = fh_to_ctx(fh); + struct coda_ctx *ctx = file_to_ctx(file); struct coda_q_data *q_data; struct v4l2_rect r, *rsel; @@ -1066,7 +1071,7 @@ static int coda_g_selection(struct file *file, void *fh, static int coda_s_selection(struct file *file, void *fh, struct v4l2_selection *s) { - struct coda_ctx *ctx = fh_to_ctx(fh); + struct coda_ctx *ctx = file_to_ctx(file); struct coda_q_data *q_data; switch (s->target) { @@ -1121,7 +1126,7 @@ static void coda_wake_up_capture_queue(struct coda_ctx *ctx) static int coda_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *ec) { - struct coda_ctx *ctx = fh_to_ctx(fh); + struct coda_ctx *ctx = file_to_ctx(file); struct vb2_v4l2_buffer *buf; int ret; @@ -1202,7 +1207,7 @@ static bool coda_mark_last_dst_buf(struct coda_ctx *ctx) static int coda_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *dc) { - struct coda_ctx *ctx = fh_to_ctx(fh); + struct coda_ctx *ctx = file_to_ctx(file); struct coda_dev *dev = ctx->dev; struct vb2_v4l2_buffer *buf; struct vb2_queue *dst_vq; @@ -1281,7 +1286,7 @@ static int coda_decoder_cmd(struct file *file, void *fh, static int coda_enum_framesizes(struct file *file, void *fh, struct v4l2_frmsizeenum *fsize) { - struct coda_ctx *ctx = fh_to_ctx(fh); + struct coda_ctx *ctx = file_to_ctx(file); struct coda_q_data *q_data_dst; const struct coda_codec *codec; @@ -1314,7 +1319,7 @@ static int coda_enum_framesizes(struct file *file, void *fh, static int coda_enum_frameintervals(struct file *file, void *fh, struct v4l2_frmivalenum *f) { - struct coda_ctx *ctx = fh_to_ctx(fh); + struct coda_ctx *ctx = file_to_ctx(file); struct coda_q_data *q_data; const struct coda_codec *codec; @@ -1353,7 +1358,7 @@ static int coda_enum_frameintervals(struct file *file, void *fh, static int coda_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a) { - struct coda_ctx *ctx = fh_to_ctx(fh); + struct coda_ctx *ctx = file_to_ctx(file); struct v4l2_fract *tpf; if (a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) @@ -1436,7 +1441,7 @@ static uint32_t coda_timeperframe_to_frate(struct v4l2_fract *timeperframe) static int coda_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a) { - struct coda_ctx *ctx = fh_to_ctx(fh); + struct coda_ctx *ctx = file_to_ctx(file); struct v4l2_fract *tpf; if (a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) @@ -2637,8 +2642,7 @@ static int coda_open(struct file *file) if (ctx->ops->seq_end_work) INIT_WORK(&ctx->seq_end_work, ctx->ops->seq_end_work); v4l2_fh_init(&ctx->fh, video_devdata(file)); - file->private_data = &ctx->fh; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); ctx->dev = dev; ctx->idx = idx; @@ -2721,7 +2725,7 @@ err_clk_ahb: err_clk_enable: pm_runtime_put_sync(dev->dev); err_pm_get: - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); err_coda_name_init: ida_free(&dev->ida, ctx->idx); @@ -2733,7 +2737,7 @@ err_coda_max: static int coda_release(struct file *file) { struct coda_dev *dev = video_drvdata(file); - struct coda_ctx *ctx = fh_to_ctx(file->private_data); + struct coda_ctx *ctx = file_to_ctx(file); coda_dbg(1, ctx, "release instance (%p)\n", ctx); @@ -2759,7 +2763,7 @@ static int coda_release(struct file *file) clk_disable_unprepare(dev->clk_ahb); clk_disable_unprepare(dev->clk_per); pm_runtime_put_sync(dev->dev); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); ida_free(&dev->ida, ctx->idx); if (ctx->ops->release) diff --git a/drivers/media/platform/chips-media/wave5/wave5-helper.c b/drivers/media/platform/chips-media/wave5/wave5-helper.c index 2c9d8cbca6e4..f03ad9c0de22 100644 --- a/drivers/media/platform/chips-media/wave5/wave5-helper.c +++ b/drivers/media/platform/chips-media/wave5/wave5-helper.c @@ -27,7 +27,7 @@ const char *state_to_str(enum vpu_instance_state state) } } -void wave5_cleanup_instance(struct vpu_instance *inst) +void wave5_cleanup_instance(struct vpu_instance *inst, struct file *filp) { int i; @@ -46,7 +46,7 @@ void wave5_cleanup_instance(struct vpu_instance *inst) wave5_vdi_free_dma_memory(inst->dev, &inst->bitstream_vbuf); v4l2_ctrl_handler_free(&inst->v4l2_ctrl_hdl); if (inst->v4l2_fh.vdev) { - v4l2_fh_del(&inst->v4l2_fh); + v4l2_fh_del(&inst->v4l2_fh, filp); v4l2_fh_exit(&inst->v4l2_fh); } list_del_init(&inst->list); @@ -59,7 +59,7 @@ int wave5_vpu_release_device(struct file *filp, int (*close_func)(struct vpu_instance *inst, u32 *fail_res), char *name) { - struct vpu_instance *inst = wave5_to_vpu_inst(filp->private_data); + struct vpu_instance *inst = file_to_vpu_inst(filp); int ret = 0; v4l2_m2m_ctx_release(inst->v4l2_fh.m2m_ctx); @@ -78,7 +78,7 @@ int wave5_vpu_release_device(struct file *filp, } } - wave5_cleanup_instance(inst); + wave5_cleanup_instance(inst, filp); return ret; } @@ -142,7 +142,7 @@ int wave5_vpu_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subscr int wave5_vpu_g_fmt_out(struct file *file, void *fh, struct v4l2_format *f) { - struct vpu_instance *inst = wave5_to_vpu_inst(fh); + struct vpu_instance *inst = file_to_vpu_inst(file); int i; f->fmt.pix_mp.width = inst->src_fmt.width; diff --git a/drivers/media/platform/chips-media/wave5/wave5-helper.h b/drivers/media/platform/chips-media/wave5/wave5-helper.h index 9937fce553fc..976a402e426f 100644 --- a/drivers/media/platform/chips-media/wave5/wave5-helper.h +++ b/drivers/media/platform/chips-media/wave5/wave5-helper.h @@ -14,7 +14,7 @@ #define MAX_FMTS 12 const char *state_to_str(enum vpu_instance_state state); -void wave5_cleanup_instance(struct vpu_instance *inst); +void wave5_cleanup_instance(struct vpu_instance *inst, struct file *filp); int wave5_vpu_release_device(struct file *filp, int (*close_func)(struct vpu_instance *inst, u32 *fail_res), char *name); diff --git a/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c b/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c index a9ce032cc5a2..e3038c18ca36 100644 --- a/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c +++ b/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c @@ -505,7 +505,7 @@ static int wave5_vpu_dec_enum_fmt_cap(struct file *file, void *fh, struct v4l2_f static int wave5_vpu_dec_try_fmt_cap(struct file *file, void *fh, struct v4l2_format *f) { - struct vpu_instance *inst = wave5_to_vpu_inst(fh); + struct vpu_instance *inst = file_to_vpu_inst(file); struct dec_info *p_dec_info = &inst->codec_info->dec_info; const struct v4l2_frmsize_stepwise *frmsize; const struct vpu_format *vpu_fmt; @@ -546,7 +546,7 @@ static int wave5_vpu_dec_try_fmt_cap(struct file *file, void *fh, struct v4l2_fo static int wave5_vpu_dec_s_fmt_cap(struct file *file, void *fh, struct v4l2_format *f) { - struct vpu_instance *inst = wave5_to_vpu_inst(fh); + struct vpu_instance *inst = file_to_vpu_inst(file); int i, ret; dev_dbg(inst->dev->dev, @@ -605,7 +605,7 @@ static int wave5_vpu_dec_s_fmt_cap(struct file *file, void *fh, struct v4l2_form static int wave5_vpu_dec_g_fmt_cap(struct file *file, void *fh, struct v4l2_format *f) { - struct vpu_instance *inst = wave5_to_vpu_inst(fh); + struct vpu_instance *inst = file_to_vpu_inst(file); int i; f->fmt.pix_mp.width = inst->dst_fmt.width; @@ -629,7 +629,7 @@ static int wave5_vpu_dec_g_fmt_cap(struct file *file, void *fh, struct v4l2_form static int wave5_vpu_dec_enum_fmt_out(struct file *file, void *fh, struct v4l2_fmtdesc *f) { - struct vpu_instance *inst = wave5_to_vpu_inst(fh); + struct vpu_instance *inst = file_to_vpu_inst(file); const struct vpu_format *vpu_fmt; dev_dbg(inst->dev->dev, "%s: index: %u\n", __func__, f->index); @@ -646,7 +646,7 @@ static int wave5_vpu_dec_enum_fmt_out(struct file *file, void *fh, struct v4l2_f static int wave5_vpu_dec_try_fmt_out(struct file *file, void *fh, struct v4l2_format *f) { - struct vpu_instance *inst = wave5_to_vpu_inst(fh); + struct vpu_instance *inst = file_to_vpu_inst(file); const struct v4l2_frmsize_stepwise *frmsize; const struct vpu_format *vpu_fmt; int width, height; @@ -677,7 +677,7 @@ static int wave5_vpu_dec_try_fmt_out(struct file *file, void *fh, struct v4l2_fo static int wave5_vpu_dec_s_fmt_out(struct file *file, void *fh, struct v4l2_format *f) { - struct vpu_instance *inst = wave5_to_vpu_inst(fh); + struct vpu_instance *inst = file_to_vpu_inst(file); const struct vpu_format *vpu_fmt; int i, ret; @@ -726,7 +726,7 @@ static int wave5_vpu_dec_s_fmt_out(struct file *file, void *fh, struct v4l2_form static int wave5_vpu_dec_g_selection(struct file *file, void *fh, struct v4l2_selection *s) { - struct vpu_instance *inst = wave5_to_vpu_inst(fh); + struct vpu_instance *inst = file_to_vpu_inst(file); dev_dbg(inst->dev->dev, "%s: type: %u | target: %u\n", __func__, s->type, s->target); @@ -760,7 +760,7 @@ static int wave5_vpu_dec_g_selection(struct file *file, void *fh, struct v4l2_se static int wave5_vpu_dec_s_selection(struct file *file, void *fh, struct v4l2_selection *s) { - struct vpu_instance *inst = wave5_to_vpu_inst(fh); + struct vpu_instance *inst = file_to_vpu_inst(file); if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; @@ -871,7 +871,7 @@ unlock_and_return: static int wave5_vpu_dec_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *dc) { - struct vpu_instance *inst = wave5_to_vpu_inst(fh); + struct vpu_instance *inst = file_to_vpu_inst(file); struct v4l2_m2m_ctx *m2m_ctx = inst->v4l2_fh.m2m_ctx; int ret; @@ -1757,8 +1757,7 @@ static int wave5_vpu_open_dec(struct file *filp) return -ENOMEM; v4l2_fh_init(&inst->v4l2_fh, vdev); - filp->private_data = &inst->v4l2_fh; - v4l2_fh_add(&inst->v4l2_fh); + v4l2_fh_add(&inst->v4l2_fh, filp); INIT_LIST_HEAD(&inst->list); @@ -1836,7 +1835,7 @@ static int wave5_vpu_open_dec(struct file *filp) return 0; cleanup_inst: - wave5_cleanup_instance(inst); + wave5_cleanup_instance(inst, filp); return ret; } diff --git a/drivers/media/platform/chips-media/wave5/wave5-vpu-enc.c b/drivers/media/platform/chips-media/wave5/wave5-vpu-enc.c index 35913a7de834..9bfaa9fb3ceb 100644 --- a/drivers/media/platform/chips-media/wave5/wave5-vpu-enc.c +++ b/drivers/media/platform/chips-media/wave5/wave5-vpu-enc.c @@ -360,7 +360,7 @@ static int wave5_vpu_enc_enum_framesizes(struct file *f, void *fh, struct v4l2_f static int wave5_vpu_enc_enum_fmt_cap(struct file *file, void *fh, struct v4l2_fmtdesc *f) { - struct vpu_instance *inst = wave5_to_vpu_inst(fh); + struct vpu_instance *inst = file_to_vpu_inst(file); const struct vpu_format *vpu_fmt; dev_dbg(inst->dev->dev, "%s: index: %u\n", __func__, f->index); @@ -377,7 +377,7 @@ static int wave5_vpu_enc_enum_fmt_cap(struct file *file, void *fh, struct v4l2_f static int wave5_vpu_enc_try_fmt_cap(struct file *file, void *fh, struct v4l2_format *f) { - struct vpu_instance *inst = wave5_to_vpu_inst(fh); + struct vpu_instance *inst = file_to_vpu_inst(file); const struct v4l2_frmsize_stepwise *frmsize; const struct vpu_format *vpu_fmt; int width, height; @@ -411,7 +411,7 @@ static int wave5_vpu_enc_try_fmt_cap(struct file *file, void *fh, struct v4l2_fo static int wave5_vpu_enc_s_fmt_cap(struct file *file, void *fh, struct v4l2_format *f) { - struct vpu_instance *inst = wave5_to_vpu_inst(fh); + struct vpu_instance *inst = file_to_vpu_inst(file); int i, ret; dev_dbg(inst->dev->dev, "%s: fourcc: %u width: %u height: %u num_planes: %u field: %u\n", @@ -445,7 +445,7 @@ static int wave5_vpu_enc_s_fmt_cap(struct file *file, void *fh, struct v4l2_form static int wave5_vpu_enc_g_fmt_cap(struct file *file, void *fh, struct v4l2_format *f) { - struct vpu_instance *inst = wave5_to_vpu_inst(fh); + struct vpu_instance *inst = file_to_vpu_inst(file); int i; f->fmt.pix_mp.width = inst->dst_fmt.width; @@ -469,7 +469,7 @@ static int wave5_vpu_enc_g_fmt_cap(struct file *file, void *fh, struct v4l2_form static int wave5_vpu_enc_enum_fmt_out(struct file *file, void *fh, struct v4l2_fmtdesc *f) { - struct vpu_instance *inst = wave5_to_vpu_inst(fh); + struct vpu_instance *inst = file_to_vpu_inst(file); const struct vpu_format *vpu_fmt; dev_dbg(inst->dev->dev, "%s: index: %u\n", __func__, f->index); @@ -486,7 +486,7 @@ static int wave5_vpu_enc_enum_fmt_out(struct file *file, void *fh, struct v4l2_f static int wave5_vpu_enc_try_fmt_out(struct file *file, void *fh, struct v4l2_format *f) { - struct vpu_instance *inst = wave5_to_vpu_inst(fh); + struct vpu_instance *inst = file_to_vpu_inst(file); const struct v4l2_frmsize_stepwise *frmsize; const struct vpu_format *vpu_fmt; int width, height; @@ -515,7 +515,7 @@ static int wave5_vpu_enc_try_fmt_out(struct file *file, void *fh, struct v4l2_fo static int wave5_vpu_enc_s_fmt_out(struct file *file, void *fh, struct v4l2_format *f) { - struct vpu_instance *inst = wave5_to_vpu_inst(fh); + struct vpu_instance *inst = file_to_vpu_inst(file); const struct vpu_format *vpu_fmt; const struct v4l2_format_info *info; int i, ret; @@ -543,7 +543,7 @@ static int wave5_vpu_enc_s_fmt_out(struct file *file, void *fh, struct v4l2_form if (!info) return -EINVAL; - inst->cbcr_interleave = (info->comp_planes == 2) ? true : false; + inst->cbcr_interleave = info->comp_planes == 2; switch (inst->src_fmt.pixelformat) { case V4L2_PIX_FMT_NV21: @@ -576,7 +576,7 @@ static int wave5_vpu_enc_s_fmt_out(struct file *file, void *fh, struct v4l2_form static int wave5_vpu_enc_g_selection(struct file *file, void *fh, struct v4l2_selection *s) { - struct vpu_instance *inst = wave5_to_vpu_inst(fh); + struct vpu_instance *inst = file_to_vpu_inst(file); dev_dbg(inst->dev->dev, "%s: type: %u | target: %u\n", __func__, s->type, s->target); @@ -605,7 +605,7 @@ static int wave5_vpu_enc_g_selection(struct file *file, void *fh, struct v4l2_se static int wave5_vpu_enc_s_selection(struct file *file, void *fh, struct v4l2_selection *s) { - struct vpu_instance *inst = wave5_to_vpu_inst(fh); + struct vpu_instance *inst = file_to_vpu_inst(file); if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) return -EINVAL; @@ -628,7 +628,7 @@ static int wave5_vpu_enc_s_selection(struct file *file, void *fh, struct v4l2_se static int wave5_vpu_enc_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *ec) { - struct vpu_instance *inst = wave5_to_vpu_inst(fh); + struct vpu_instance *inst = file_to_vpu_inst(file); struct v4l2_m2m_ctx *m2m_ctx = inst->v4l2_fh.m2m_ctx; int ret; @@ -661,7 +661,7 @@ static int wave5_vpu_enc_encoder_cmd(struct file *file, void *fh, struct v4l2_en static int wave5_vpu_enc_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a) { - struct vpu_instance *inst = wave5_to_vpu_inst(fh); + struct vpu_instance *inst = file_to_vpu_inst(file); dev_dbg(inst->dev->dev, "%s: type: %u\n", __func__, a->type); @@ -681,7 +681,7 @@ static int wave5_vpu_enc_g_parm(struct file *file, void *fh, struct v4l2_streamp static int wave5_vpu_enc_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a) { - struct vpu_instance *inst = wave5_to_vpu_inst(fh); + struct vpu_instance *inst = file_to_vpu_inst(file); dev_dbg(inst->dev->dev, "%s: type: %u\n", __func__, a->type); @@ -1582,8 +1582,7 @@ static int wave5_vpu_open_enc(struct file *filp) return -ENOMEM; v4l2_fh_init(&inst->v4l2_fh, vdev); - filp->private_data = &inst->v4l2_fh; - v4l2_fh_add(&inst->v4l2_fh); + v4l2_fh_add(&inst->v4l2_fh, filp); INIT_LIST_HEAD(&inst->list); @@ -1779,7 +1778,7 @@ static int wave5_vpu_open_enc(struct file *filp) return 0; cleanup_inst: - wave5_cleanup_instance(inst); + wave5_cleanup_instance(inst, filp); return ret; } diff --git a/drivers/media/platform/chips-media/wave5/wave5-vpu.h b/drivers/media/platform/chips-media/wave5/wave5-vpu.h index 3847332551fc..5943bdaa9c4c 100644 --- a/drivers/media/platform/chips-media/wave5/wave5-vpu.h +++ b/drivers/media/platform/chips-media/wave5/wave5-vpu.h @@ -46,6 +46,11 @@ static inline struct vpu_instance *wave5_to_vpu_inst(struct v4l2_fh *vfh) return container_of(vfh, struct vpu_instance, v4l2_fh); } +static inline struct vpu_instance *file_to_vpu_inst(struct file *filp) +{ + return wave5_to_vpu_inst(file_to_v4l2_fh(filp)); +} + static inline struct vpu_instance *wave5_ctrl_to_vpu_inst(struct v4l2_ctrl *vctrl) { return container_of(vctrl->handler, struct vpu_instance, v4l2_ctrl_hdl); diff --git a/drivers/media/platform/imagination/e5010-jpeg-enc.c b/drivers/media/platform/imagination/e5010-jpeg-enc.c index ae868d9f73e1..c4e0097cb8b7 100644 --- a/drivers/media/platform/imagination/e5010-jpeg-enc.c +++ b/drivers/media/platform/imagination/e5010-jpeg-enc.c @@ -253,7 +253,7 @@ static int e5010_enum_fmt(struct file *file, void *priv, struct v4l2_fmtdesc *f) { int i, index = 0; struct e5010_fmt *fmt = NULL; - struct e5010_context *ctx = file->private_data; + struct e5010_context *ctx = to_e5010_context(file); if (!V4L2_TYPE_IS_MULTIPLANAR(f->type)) { v4l2_err(&ctx->e5010->v4l2_dev, "ENUMFMT with Invalid type: %d\n", f->type); @@ -279,7 +279,7 @@ static int e5010_enum_fmt(struct file *file, void *priv, struct v4l2_fmtdesc *f) static int e5010_g_fmt(struct file *file, void *priv, struct v4l2_format *f) { - struct e5010_context *ctx = file->private_data; + struct e5010_context *ctx = to_e5010_context(file); struct e5010_q_data *queue; int i; struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; @@ -380,14 +380,14 @@ static int e5010_jpeg_try_fmt(struct v4l2_format *f, struct e5010_context *ctx) static int e5010_try_fmt(struct file *file, void *priv, struct v4l2_format *f) { - struct e5010_context *ctx = file->private_data; + struct e5010_context *ctx = to_e5010_context(file); return e5010_jpeg_try_fmt(f, ctx); } static int e5010_s_fmt(struct file *file, void *priv, struct v4l2_format *f) { - struct e5010_context *ctx = file->private_data; + struct e5010_context *ctx = to_e5010_context(file); struct vb2_queue *vq; int ret = 0, i = 0; struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; @@ -462,7 +462,7 @@ static int e5010_enum_framesizes(struct file *file, void *priv, struct v4l2_frms static int e5010_g_selection(struct file *file, void *fh, struct v4l2_selection *s) { - struct e5010_context *ctx = file->private_data; + struct e5010_context *ctx = to_e5010_context(file); struct e5010_q_data *queue; if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) @@ -490,7 +490,7 @@ static int e5010_g_selection(struct file *file, void *fh, struct v4l2_selection static int e5010_s_selection(struct file *file, void *fh, struct v4l2_selection *s) { - struct e5010_context *ctx = file->private_data; + struct e5010_context *ctx = to_e5010_context(file); struct e5010_q_data *queue; struct vb2_queue *vq; struct v4l2_rect base_rect; @@ -742,8 +742,7 @@ static int e5010_open(struct file *file) } v4l2_fh_init(&ctx->fh, vdev); - file->private_data = ctx; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); ctx->e5010 = e5010; ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(e5010->m2m_dev, ctx, queue_init); @@ -770,7 +769,7 @@ static int e5010_open(struct file *file) err_ctrls_setup: v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); exit: - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); mutex_unlock(&e5010->mutex); free: @@ -781,13 +780,13 @@ free: static int e5010_release(struct file *file) { struct e5010_dev *e5010 = video_drvdata(file); - struct e5010_context *ctx = file->private_data; + struct e5010_context *ctx = to_e5010_context(file); dprintk(e5010, 1, "Releasing instance: 0x%p, m2m_ctx: 0x%p\n", ctx, ctx->fh.m2m_ctx); mutex_lock(&e5010->mutex); v4l2_ctrl_handler_free(&ctx->ctrl_handler); v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); kfree(ctx); mutex_unlock(&e5010->mutex); @@ -1262,7 +1261,7 @@ static void e5010_buf_queue(struct vb2_buffer *vb) static int e5010_encoder_cmd(struct file *file, void *priv, struct v4l2_encoder_cmd *cmd) { - struct e5010_context *ctx = file->private_data; + struct e5010_context *ctx = to_e5010_context(file); int ret; struct vb2_queue *cap_vq; diff --git a/drivers/media/platform/imagination/e5010-jpeg-enc.h b/drivers/media/platform/imagination/e5010-jpeg-enc.h index 71f49ead6898..da57bc1baa46 100644 --- a/drivers/media/platform/imagination/e5010-jpeg-enc.h +++ b/drivers/media/platform/imagination/e5010-jpeg-enc.h @@ -120,6 +120,11 @@ struct e5010_context { u8 chroma_qp[QP_TABLE_SIZE]; }; +static inline struct e5010_context *to_e5010_context(struct file *filp) +{ + return container_of(file_to_v4l2_fh(filp), struct e5010_context, fh); +} + /* * Buffer structure * Contains info for all buffers diff --git a/drivers/media/platform/m2m-deinterlace.c b/drivers/media/platform/m2m-deinterlace.c index 5188f3189096..e07e57d4206b 100644 --- a/drivers/media/platform/m2m-deinterlace.c +++ b/drivers/media/platform/m2m-deinterlace.c @@ -142,6 +142,11 @@ struct deinterlace_ctx { struct dma_interleaved_template *xt; }; +static inline struct deinterlace_ctx *file_to_ctx(struct file *filp) +{ + return container_of(file_to_v4l2_fh(filp), struct deinterlace_ctx, fh); +} + /* * mem2mem callbacks */ @@ -512,13 +517,13 @@ static int vidioc_g_fmt(struct deinterlace_ctx *ctx, struct v4l2_format *f) static int vidioc_g_fmt_vid_out(struct file *file, void *priv, struct v4l2_format *f) { - return vidioc_g_fmt(priv, f); + return vidioc_g_fmt(file_to_ctx(file), f); } static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - return vidioc_g_fmt(priv, f); + return vidioc_g_fmt(file_to_ctx(file), f); } static int vidioc_try_fmt(struct v4l2_format *f, struct deinterlace_fmt *fmt) @@ -539,8 +544,8 @@ static int vidioc_try_fmt(struct v4l2_format *f, struct deinterlace_fmt *fmt) static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { + struct deinterlace_ctx *ctx = file_to_ctx(file); struct deinterlace_fmt *fmt; - struct deinterlace_ctx *ctx = priv; fmt = find_format(f); if (!fmt || !(fmt->types & MEM2MEM_CAPTURE)) @@ -633,20 +638,20 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, ret = vidioc_try_fmt_vid_cap(file, priv, f); if (ret) return ret; - return vidioc_s_fmt(priv, f); + return vidioc_s_fmt(file_to_ctx(file), f); } static int vidioc_s_fmt_vid_out(struct file *file, void *priv, struct v4l2_format *f) { - struct deinterlace_ctx *ctx = priv; + struct deinterlace_ctx *ctx = file_to_ctx(file); int ret; ret = vidioc_try_fmt_vid_out(file, priv, f); if (ret) return ret; - ret = vidioc_s_fmt(priv, f); + ret = vidioc_s_fmt(ctx, f); if (!ret) ctx->colorspace = f->fmt.pix.colorspace; @@ -656,8 +661,8 @@ static int vidioc_s_fmt_vid_out(struct file *file, void *priv, static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type type) { + struct deinterlace_ctx *ctx = file_to_ctx(file); struct deinterlace_q_data *s_q_data, *d_q_data; - struct deinterlace_ctx *ctx = priv; s_q_data = get_q_data(V4L2_BUF_TYPE_VIDEO_OUTPUT); d_q_data = get_q_data(V4L2_BUF_TYPE_VIDEO_CAPTURE); @@ -842,7 +847,6 @@ static int deinterlace_open(struct file *file) return -ENOMEM; v4l2_fh_init(&ctx->fh, video_devdata(file)); - file->private_data = &ctx->fh; ctx->dev = pcdev; ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(pcdev->m2m_dev, ctx, &queue_init); @@ -861,7 +865,7 @@ static int deinterlace_open(struct file *file) } ctx->colorspace = V4L2_COLORSPACE_REC709; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); dprintk(pcdev, "Created instance %p, m2m_ctx: %p\n", ctx, ctx->fh.m2m_ctx); @@ -872,11 +876,11 @@ static int deinterlace_open(struct file *file) static int deinterlace_release(struct file *file) { struct deinterlace_dev *pcdev = video_drvdata(file); - struct deinterlace_ctx *ctx = file->private_data; + struct deinterlace_ctx *ctx = file_to_ctx(file); dprintk(pcdev, "Releasing instance %p\n", ctx); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); kfree(ctx->xt); diff --git a/drivers/media/platform/marvell/cafe-driver.c b/drivers/media/platform/marvell/cafe-driver.c index ef810249def6..f9796de92aa7 100644 --- a/drivers/media/platform/marvell/cafe-driver.c +++ b/drivers/media/platform/marvell/cafe-driver.c @@ -14,7 +14,7 @@ * Written by Jonathan Corbet, corbet@lwn.net. * * v4l2_device/v4l2_subdev conversion by: - * Copyright (C) 2009 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2009 Hans Verkuil <hverkuil@kernel.org> */ #include <linux/kernel.h> #include <linux/module.h> diff --git a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c index 7eb12449b63a..6268d651bdcf 100644 --- a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c +++ b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c @@ -119,9 +119,9 @@ static inline struct mtk_jpeg_ctx *ctrl_to_ctx(struct v4l2_ctrl *ctrl) return container_of(ctrl->handler, struct mtk_jpeg_ctx, ctrl_hdl); } -static inline struct mtk_jpeg_ctx *mtk_jpeg_fh_to_ctx(struct v4l2_fh *fh) +static inline struct mtk_jpeg_ctx *mtk_jpeg_file_to_ctx(struct file *filp) { - return container_of(fh, struct mtk_jpeg_ctx, fh); + return container_of(file_to_v4l2_fh(filp), struct mtk_jpeg_ctx, fh); } static inline struct mtk_jpeg_src_buf *mtk_jpeg_vb2_to_srcbuf( @@ -212,7 +212,7 @@ static int mtk_jpeg_enum_fmt(struct mtk_jpeg_fmt *mtk_jpeg_formats, int n, static int mtk_jpeg_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - struct mtk_jpeg_ctx *ctx = mtk_jpeg_fh_to_ctx(priv); + struct mtk_jpeg_ctx *ctx = mtk_jpeg_file_to_ctx(file); struct mtk_jpeg_dev *jpeg = ctx->jpeg; return mtk_jpeg_enum_fmt(jpeg->variant->formats, @@ -223,7 +223,7 @@ static int mtk_jpeg_enum_fmt_vid_cap(struct file *file, void *priv, static int mtk_jpeg_enum_fmt_vid_out(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - struct mtk_jpeg_ctx *ctx = mtk_jpeg_fh_to_ctx(priv); + struct mtk_jpeg_ctx *ctx = mtk_jpeg_file_to_ctx(file); struct mtk_jpeg_dev *jpeg = ctx->jpeg; return mtk_jpeg_enum_fmt(jpeg->variant->formats, @@ -305,7 +305,7 @@ static int mtk_jpeg_g_fmt_vid_mplane(struct file *file, void *priv, struct vb2_queue *vq; struct mtk_jpeg_q_data *q_data = NULL; struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; - struct mtk_jpeg_ctx *ctx = mtk_jpeg_fh_to_ctx(priv); + struct mtk_jpeg_ctx *ctx = mtk_jpeg_file_to_ctx(file); struct mtk_jpeg_dev *jpeg = ctx->jpeg; int i; @@ -351,7 +351,7 @@ static int mtk_jpeg_g_fmt_vid_mplane(struct file *file, void *priv, static int mtk_jpeg_try_fmt_vid_cap_mplane(struct file *file, void *priv, struct v4l2_format *f) { - struct mtk_jpeg_ctx *ctx = mtk_jpeg_fh_to_ctx(priv); + struct mtk_jpeg_ctx *ctx = mtk_jpeg_file_to_ctx(file); struct mtk_jpeg_dev *jpeg = ctx->jpeg; struct mtk_jpeg_fmt *fmt; @@ -380,7 +380,7 @@ static int mtk_jpeg_try_fmt_vid_cap_mplane(struct file *file, void *priv, static int mtk_jpeg_try_fmt_vid_out_mplane(struct file *file, void *priv, struct v4l2_format *f) { - struct mtk_jpeg_ctx *ctx = mtk_jpeg_fh_to_ctx(priv); + struct mtk_jpeg_ctx *ctx = mtk_jpeg_file_to_ctx(file); struct mtk_jpeg_dev *jpeg = ctx->jpeg; struct mtk_jpeg_fmt *fmt; @@ -470,7 +470,7 @@ static int mtk_jpeg_s_fmt_vid_out_mplane(struct file *file, void *priv, if (ret) return ret; - return mtk_jpeg_s_fmt_mplane(mtk_jpeg_fh_to_ctx(priv), f, + return mtk_jpeg_s_fmt_mplane(mtk_jpeg_file_to_ctx(file), f, MTK_JPEG_FMT_FLAG_OUTPUT); } @@ -483,7 +483,7 @@ static int mtk_jpeg_s_fmt_vid_cap_mplane(struct file *file, void *priv, if (ret) return ret; - return mtk_jpeg_s_fmt_mplane(mtk_jpeg_fh_to_ctx(priv), f, + return mtk_jpeg_s_fmt_mplane(mtk_jpeg_file_to_ctx(file), f, MTK_JPEG_FMT_FLAG_CAPTURE); } @@ -512,7 +512,7 @@ static int mtk_jpeg_subscribe_event(struct v4l2_fh *fh, static int mtk_jpeg_enc_g_selection(struct file *file, void *priv, struct v4l2_selection *s) { - struct mtk_jpeg_ctx *ctx = mtk_jpeg_fh_to_ctx(priv); + struct mtk_jpeg_ctx *ctx = mtk_jpeg_file_to_ctx(file); if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) return -EINVAL; @@ -537,7 +537,7 @@ static int mtk_jpeg_enc_g_selection(struct file *file, void *priv, static int mtk_jpeg_dec_g_selection(struct file *file, void *priv, struct v4l2_selection *s) { - struct mtk_jpeg_ctx *ctx = mtk_jpeg_fh_to_ctx(priv); + struct mtk_jpeg_ctx *ctx = mtk_jpeg_file_to_ctx(file); if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; @@ -566,7 +566,7 @@ static int mtk_jpeg_dec_g_selection(struct file *file, void *priv, static int mtk_jpeg_enc_s_selection(struct file *file, void *priv, struct v4l2_selection *s) { - struct mtk_jpeg_ctx *ctx = mtk_jpeg_fh_to_ctx(priv); + struct mtk_jpeg_ctx *ctx = mtk_jpeg_file_to_ctx(file); if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) return -EINVAL; @@ -588,8 +588,8 @@ static int mtk_jpeg_enc_s_selection(struct file *file, void *priv, static int mtk_jpeg_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) { - struct v4l2_fh *fh = file->private_data; - struct mtk_jpeg_ctx *ctx = mtk_jpeg_fh_to_ctx(priv); + struct v4l2_fh *fh = file_to_v4l2_fh(file); + struct mtk_jpeg_ctx *ctx = mtk_jpeg_file_to_ctx(file); struct vb2_queue *vq; struct vb2_buffer *vb; struct mtk_jpeg_src_buf *jpeg_src_buf; @@ -1171,8 +1171,7 @@ static int mtk_jpeg_open(struct file *file) INIT_LIST_HEAD(&ctx->dst_done_queue); spin_lock_init(&ctx->done_queue_lock); v4l2_fh_init(&ctx->fh, vfd); - file->private_data = &ctx->fh; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); ctx->jpeg = jpeg; ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(jpeg->m2m_dev, ctx, @@ -1197,7 +1196,7 @@ static int mtk_jpeg_open(struct file *file) return 0; error: - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); mutex_unlock(&jpeg->lock); free: @@ -1208,12 +1207,12 @@ free: static int mtk_jpeg_release(struct file *file) { struct mtk_jpeg_dev *jpeg = video_drvdata(file); - struct mtk_jpeg_ctx *ctx = mtk_jpeg_fh_to_ctx(file->private_data); + struct mtk_jpeg_ctx *ctx = mtk_jpeg_file_to_ctx(file); mutex_lock(&jpeg->lock); v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); v4l2_ctrl_handler_free(&ctx->ctrl_hdl); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); kfree(ctx); mutex_unlock(&jpeg->lock); diff --git a/drivers/media/platform/mediatek/mdp/mtk_mdp_m2m.c b/drivers/media/platform/mediatek/mdp/mtk_mdp_m2m.c index d0fd77dcf8e2..03c07948dfdd 100644 --- a/drivers/media/platform/mediatek/mdp/mtk_mdp_m2m.c +++ b/drivers/media/platform/mediatek/mdp/mtk_mdp_m2m.c @@ -348,9 +348,9 @@ static int mtk_mdp_try_crop(struct mtk_mdp_ctx *ctx, u32 type, return 0; } -static inline struct mtk_mdp_ctx *fh_to_ctx(struct v4l2_fh *fh) +static inline struct mtk_mdp_ctx *file_to_ctx(struct file *filp) { - return container_of(fh, struct mtk_mdp_ctx, fh); + return container_of(file_to_v4l2_fh(filp), struct mtk_mdp_ctx, fh); } static inline struct mtk_mdp_ctx *ctrl_to_ctx(struct v4l2_ctrl *ctrl) @@ -589,7 +589,7 @@ static const struct vb2_ops mtk_mdp_m2m_qops = { static int mtk_mdp_m2m_querycap(struct file *file, void *fh, struct v4l2_capability *cap) { - struct mtk_mdp_ctx *ctx = fh_to_ctx(fh); + struct mtk_mdp_ctx *ctx = file_to_ctx(file); struct mtk_mdp_dev *mdp = ctx->mdp_dev; strscpy(cap->driver, MTK_MDP_MODULE_NAME, sizeof(cap->driver)); @@ -627,7 +627,7 @@ static int mtk_mdp_m2m_enum_fmt_vid_out(struct file *file, void *priv, static int mtk_mdp_m2m_g_fmt_mplane(struct file *file, void *fh, struct v4l2_format *f) { - struct mtk_mdp_ctx *ctx = fh_to_ctx(fh); + struct mtk_mdp_ctx *ctx = file_to_ctx(file); struct mtk_mdp_frame *frame; struct v4l2_pix_format_mplane *pix_mp; int i; @@ -666,7 +666,7 @@ static int mtk_mdp_m2m_g_fmt_mplane(struct file *file, void *fh, static int mtk_mdp_m2m_try_fmt_mplane(struct file *file, void *fh, struct v4l2_format *f) { - struct mtk_mdp_ctx *ctx = fh_to_ctx(fh); + struct mtk_mdp_ctx *ctx = file_to_ctx(file); if (!mtk_mdp_try_fmt_mplane(ctx, f)) return -EINVAL; @@ -676,7 +676,7 @@ static int mtk_mdp_m2m_try_fmt_mplane(struct file *file, void *fh, static int mtk_mdp_m2m_s_fmt_mplane(struct file *file, void *fh, struct v4l2_format *f) { - struct mtk_mdp_ctx *ctx = fh_to_ctx(fh); + struct mtk_mdp_ctx *ctx = file_to_ctx(file); struct vb2_queue *vq; struct mtk_mdp_frame *frame; struct v4l2_pix_format_mplane *pix_mp; @@ -722,7 +722,7 @@ static int mtk_mdp_m2m_s_fmt_mplane(struct file *file, void *fh, static int mtk_mdp_m2m_reqbufs(struct file *file, void *fh, struct v4l2_requestbuffers *reqbufs) { - struct mtk_mdp_ctx *ctx = fh_to_ctx(fh); + struct mtk_mdp_ctx *ctx = file_to_ctx(file); return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs); } @@ -730,7 +730,7 @@ static int mtk_mdp_m2m_reqbufs(struct file *file, void *fh, static int mtk_mdp_m2m_streamon(struct file *file, void *fh, enum v4l2_buf_type type) { - struct mtk_mdp_ctx *ctx = fh_to_ctx(fh); + struct mtk_mdp_ctx *ctx = file_to_ctx(file); int ret; if (!mtk_mdp_ctx_state_is_set(ctx, MTK_MDP_VPU_INIT)) { @@ -768,8 +768,8 @@ static inline bool mtk_mdp_is_target_crop(u32 target) static int mtk_mdp_m2m_g_selection(struct file *file, void *fh, struct v4l2_selection *s) { + struct mtk_mdp_ctx *ctx = file_to_ctx(file); struct mtk_mdp_frame *frame; - struct mtk_mdp_ctx *ctx = fh_to_ctx(fh); bool valid = false; if (s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { @@ -835,8 +835,8 @@ static int mtk_mdp_check_scaler_ratio(struct mtk_mdp_variant *var, int src_w, static int mtk_mdp_m2m_s_selection(struct file *file, void *fh, struct v4l2_selection *s) { + struct mtk_mdp_ctx *ctx = file_to_ctx(file); struct mtk_mdp_frame *frame; - struct mtk_mdp_ctx *ctx = fh_to_ctx(fh); struct v4l2_rect new_r; struct mtk_mdp_variant *variant = ctx->mdp_dev->variant; int ret; @@ -1065,14 +1065,13 @@ static int mtk_mdp_m2m_open(struct file *file) mutex_init(&ctx->slock); ctx->id = mdp->id_counter++; v4l2_fh_init(&ctx->fh, vfd); - file->private_data = &ctx->fh; ret = mtk_mdp_ctrls_create(ctx); if (ret) goto error_ctrls; /* Use separate control handler per file handle */ ctx->fh.ctrl_handler = &ctx->ctrl_handler; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); INIT_LIST_HEAD(&ctx->list); ctx->mdp_dev = mdp; @@ -1126,7 +1125,7 @@ err_load_vpu: error_m2m_ctx: v4l2_ctrl_handler_free(&ctx->ctrl_handler); error_ctrls: - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); mutex_unlock(&mdp->lock); err_lock: @@ -1137,14 +1136,14 @@ err_lock: static int mtk_mdp_m2m_release(struct file *file) { - struct mtk_mdp_ctx *ctx = fh_to_ctx(file->private_data); + struct mtk_mdp_ctx *ctx = file_to_ctx(file); struct mtk_mdp_dev *mdp = ctx->mdp_dev; flush_workqueue(mdp->job_wq); mutex_lock(&mdp->lock); v4l2_m2m_ctx_release(ctx->m2m_ctx); v4l2_ctrl_handler_free(&ctx->ctrl_handler); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); mtk_mdp_vpu_deinit(&ctx->vpu); mdp->ctx_num--; diff --git a/drivers/media/platform/mediatek/mdp3/mtk-mdp3-comp.c b/drivers/media/platform/mediatek/mdp3/mtk-mdp3-comp.c index 683c066ed975..7fcb2fbdd64e 100644 --- a/drivers/media/platform/mediatek/mdp3/mtk-mdp3-comp.c +++ b/drivers/media/platform/mediatek/mdp3/mtk-mdp3-comp.c @@ -1530,6 +1530,9 @@ static const struct of_device_id mdp_comp_dt_ids[] __maybe_unused = { }, { .compatible = "mediatek,mt8195-mdp3-tcc", .data = (void *)MDP_COMP_TYPE_TCC, + }, { + .compatible = "mediatek,mt8188-mdp3-rdma", + .data = (void *)MDP_COMP_TYPE_RDMA, }, {} }; diff --git a/drivers/media/platform/mediatek/mdp3/mtk-mdp3-core.c b/drivers/media/platform/mediatek/mdp3/mtk-mdp3-core.c index 8de2c8e4d333..6559d72d5d42 100644 --- a/drivers/media/platform/mediatek/mdp3/mtk-mdp3-core.c +++ b/drivers/media/platform/mediatek/mdp3/mtk-mdp3-core.c @@ -282,7 +282,7 @@ static int mdp_probe(struct platform_device *pdev) } mdp->rproc_handle = scp_get_rproc(mdp->scp); - dev_dbg(&pdev->dev, "MDP rproc_handle: %pK", mdp->rproc_handle); + dev_dbg(&pdev->dev, "MDP rproc_handle: %p", mdp->rproc_handle); mutex_init(&mdp->vpu_lock); mutex_init(&mdp->m2m_lock); diff --git a/drivers/media/platform/mediatek/mdp3/mtk-mdp3-m2m.c b/drivers/media/platform/mediatek/mdp3/mtk-mdp3-m2m.c index 59ce5cce0698..9ef956b565a7 100644 --- a/drivers/media/platform/mediatek/mdp3/mtk-mdp3-m2m.c +++ b/drivers/media/platform/mediatek/mdp3/mtk-mdp3-m2m.c @@ -10,9 +10,9 @@ #include <media/videobuf2-dma-contig.h> #include "mtk-mdp3-m2m.h" -static inline struct mdp_m2m_ctx *fh_to_ctx(struct v4l2_fh *fh) +static inline struct mdp_m2m_ctx *file_to_ctx(struct file *filp) { - return container_of(fh, struct mdp_m2m_ctx, fh); + return container_of(file_to_v4l2_fh(filp), struct mdp_m2m_ctx, fh); } static inline struct mdp_m2m_ctx *ctrl_to_ctx(struct v4l2_ctrl *ctrl) @@ -285,7 +285,7 @@ static int mdp_m2m_querycap(struct file *file, void *fh, static int mdp_m2m_enum_fmt_mplane(struct file *file, void *fh, struct v4l2_fmtdesc *f) { - struct mdp_m2m_ctx *ctx = fh_to_ctx(fh); + struct mdp_m2m_ctx *ctx = file_to_ctx(file); return mdp_enum_fmt_mplane(ctx->mdp_dev, f); } @@ -293,7 +293,7 @@ static int mdp_m2m_enum_fmt_mplane(struct file *file, void *fh, static int mdp_m2m_g_fmt_mplane(struct file *file, void *fh, struct v4l2_format *f) { - struct mdp_m2m_ctx *ctx = fh_to_ctx(fh); + struct mdp_m2m_ctx *ctx = file_to_ctx(file); struct mdp_frame *frame; struct v4l2_pix_format_mplane *pix_mp; @@ -311,7 +311,7 @@ static int mdp_m2m_g_fmt_mplane(struct file *file, void *fh, static int mdp_m2m_s_fmt_mplane(struct file *file, void *fh, struct v4l2_format *f) { - struct mdp_m2m_ctx *ctx = fh_to_ctx(fh); + struct mdp_m2m_ctx *ctx = file_to_ctx(file); struct mdp_frame *frame = ctx_get_frame(ctx, f->type); struct mdp_frame *capture; const struct mdp_format *fmt; @@ -354,7 +354,7 @@ static int mdp_m2m_s_fmt_mplane(struct file *file, void *fh, static int mdp_m2m_try_fmt_mplane(struct file *file, void *fh, struct v4l2_format *f) { - struct mdp_m2m_ctx *ctx = fh_to_ctx(fh); + struct mdp_m2m_ctx *ctx = file_to_ctx(file); if (!mdp_try_fmt_mplane(ctx->mdp_dev, f, &ctx->curr_param, ctx->id)) return -EINVAL; @@ -365,7 +365,7 @@ static int mdp_m2m_try_fmt_mplane(struct file *file, void *fh, static int mdp_m2m_g_selection(struct file *file, void *fh, struct v4l2_selection *s) { - struct mdp_m2m_ctx *ctx = fh_to_ctx(fh); + struct mdp_m2m_ctx *ctx = file_to_ctx(file); struct mdp_frame *frame; bool valid = false; @@ -417,7 +417,7 @@ static int mdp_m2m_g_selection(struct file *file, void *fh, static int mdp_m2m_s_selection(struct file *file, void *fh, struct v4l2_selection *s) { - struct mdp_m2m_ctx *ctx = fh_to_ctx(fh); + struct mdp_m2m_ctx *ctx = file_to_ctx(file); struct mdp_frame *frame = ctx_get_frame(ctx, s->type); struct mdp_frame *capture; struct v4l2_rect r; @@ -585,14 +585,13 @@ static int mdp_m2m_open(struct file *file) ctx->mdp_dev = mdp; v4l2_fh_init(&ctx->fh, vdev); - file->private_data = &ctx->fh; ret = mdp_m2m_ctrls_create(ctx); if (ret) goto err_exit_fh; /* Use separate control handler per file handle */ ctx->fh.ctrl_handler = &ctx->ctrl_handler; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); mutex_init(&ctx->ctx_lock); ctx->m2m_ctx = v4l2_m2m_ctx_init(mdp->m2m_dev, ctx, mdp_m2m_queue_init); @@ -629,7 +628,7 @@ err_release_m2m_ctx: v4l2_m2m_ctx_release(ctx->m2m_ctx); err_release_handler: v4l2_ctrl_handler_free(&ctx->ctrl_handler); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); err_exit_fh: v4l2_fh_exit(&ctx->fh); ida_free(&mdp->mdp_ida, ctx->id); @@ -643,7 +642,7 @@ err_free_ctx: static int mdp_m2m_release(struct file *file) { - struct mdp_m2m_ctx *ctx = fh_to_ctx(file->private_data); + struct mdp_m2m_ctx *ctx = file_to_ctx(file); struct mdp_dev *mdp = video_drvdata(file); struct device *dev = &mdp->pdev->dev; @@ -653,7 +652,7 @@ static int mdp_m2m_release(struct file *file) mdp_vpu_put_locked(mdp); v4l2_ctrl_handler_free(&ctx->ctrl_handler); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); ida_free(&mdp->mdp_ida, ctx->id); mutex_unlock(&mdp->m2m_lock); diff --git a/drivers/media/platform/mediatek/mdp3/mtk-mdp3-vpu.c b/drivers/media/platform/mediatek/mdp3/mtk-mdp3-vpu.c index da3a892ad867..fae3e1ad2df7 100644 --- a/drivers/media/platform/mediatek/mdp3/mtk-mdp3-vpu.c +++ b/drivers/media/platform/mediatek/mdp3/mtk-mdp3-vpu.c @@ -221,7 +221,7 @@ int mdp_vpu_dev_init(struct mdp_vpu_dev *vpu, struct mtk_scp *scp, } dev_dbg(&mdp->pdev->dev, - "VPU param:%pK pa:%pad sz:%zx, work:%pK pa:%pad sz:%zx, config:%pK pa:%pad sz:%zx", + "VPU param:%p pa:%pad sz:%zx, work:%p pa:%pad sz:%zx, config:%p pa:%pad sz:%zx", vpu->param, &vpu->param_addr, vpu->param_size, vpu->work, &vpu->work_addr, vpu->work_size, vpu->config, &vpu->config_addr, vpu->config_size); diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c index 98838217b97d..d691bd533103 100644 --- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c +++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c @@ -87,7 +87,7 @@ static int stateful_try_decoder_cmd(struct file *file, void *priv, struct v4l2_d static int stateful_decoder_cmd(struct file *file, void *priv, struct v4l2_decoder_cmd *cmd) { - struct mtk_vcodec_dec_ctx *ctx = fh_to_dec_ctx(priv); + struct mtk_vcodec_dec_ctx *ctx = file_to_dec_ctx(file); struct vb2_queue *src_vq, *dst_vq; int ret; @@ -132,7 +132,7 @@ static int stateless_try_decoder_cmd(struct file *file, void *priv, struct v4l2_ static int stateless_decoder_cmd(struct file *file, void *priv, struct v4l2_decoder_cmd *cmd) { - struct mtk_vcodec_dec_ctx *ctx = fh_to_dec_ctx(priv); + struct mtk_vcodec_dec_ctx *ctx = file_to_dec_ctx(file); int ret; ret = v4l2_m2m_ioctl_stateless_try_decoder_cmd(file, priv, cmd); @@ -158,7 +158,7 @@ static int stateless_decoder_cmd(struct file *file, void *priv, struct v4l2_deco static int vidioc_try_decoder_cmd(struct file *file, void *priv, struct v4l2_decoder_cmd *cmd) { - struct mtk_vcodec_dec_ctx *ctx = fh_to_dec_ctx(priv); + struct mtk_vcodec_dec_ctx *ctx = file_to_dec_ctx(file); if (ctx->dev->vdec_pdata->uses_stateless_api) return stateless_try_decoder_cmd(file, priv, cmd); @@ -168,7 +168,7 @@ static int vidioc_try_decoder_cmd(struct file *file, void *priv, struct v4l2_dec static int vidioc_decoder_cmd(struct file *file, void *priv, struct v4l2_decoder_cmd *cmd) { - struct mtk_vcodec_dec_ctx *ctx = fh_to_dec_ctx(priv); + struct mtk_vcodec_dec_ctx *ctx = file_to_dec_ctx(file); if (ctx->dev->vdec_pdata->uses_stateless_api) return stateless_decoder_cmd(file, priv, cmd); @@ -233,7 +233,7 @@ void mtk_vcodec_dec_set_default_params(struct mtk_vcodec_dec_ctx *ctx) static int vidioc_vdec_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) { - struct mtk_vcodec_dec_ctx *ctx = fh_to_dec_ctx(priv); + struct mtk_vcodec_dec_ctx *ctx = file_to_dec_ctx(file); if (ctx->state == MTK_STATE_ABORT) { mtk_v4l2_vdec_err(ctx, "[%d] Call on QBUF after unrecoverable error", ctx->id); @@ -246,7 +246,7 @@ static int vidioc_vdec_qbuf(struct file *file, void *priv, static int vidioc_vdec_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) { - struct mtk_vcodec_dec_ctx *ctx = fh_to_dec_ctx(priv); + struct mtk_vcodec_dec_ctx *ctx = file_to_dec_ctx(file); if (ctx->state == MTK_STATE_ABORT) { mtk_v4l2_vdec_err(ctx, "[%d] Call on DQBUF after unrecoverable error", ctx->id); @@ -259,7 +259,7 @@ static int vidioc_vdec_dqbuf(struct file *file, void *priv, static int vidioc_vdec_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { - struct mtk_vcodec_dec_ctx *ctx = fh_to_dec_ctx(priv); + struct mtk_vcodec_dec_ctx *ctx = file_to_dec_ctx(file); struct device *dev = &ctx->dev->plat_dev->dev; strscpy(cap->driver, dev->driver->name, sizeof(cap->driver)); @@ -354,7 +354,7 @@ static int vidioc_try_fmt_vid_cap_mplane(struct file *file, void *priv, struct v4l2_format *f) { const struct mtk_video_fmt *fmt; - struct mtk_vcodec_dec_ctx *ctx = fh_to_dec_ctx(priv); + struct mtk_vcodec_dec_ctx *ctx = file_to_dec_ctx(file); const struct mtk_vcodec_dec_pdata *dec_pdata = ctx->dev->vdec_pdata; fmt = mtk_vdec_find_format(f, dec_pdata); @@ -372,7 +372,7 @@ static int vidioc_try_fmt_vid_out_mplane(struct file *file, void *priv, { struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp; const struct mtk_video_fmt *fmt; - struct mtk_vcodec_dec_ctx *ctx = fh_to_dec_ctx(priv); + struct mtk_vcodec_dec_ctx *ctx = file_to_dec_ctx(file); const struct mtk_vcodec_dec_pdata *dec_pdata = ctx->dev->vdec_pdata; fmt = mtk_vdec_find_format(f, dec_pdata); @@ -393,7 +393,7 @@ static int vidioc_try_fmt_vid_out_mplane(struct file *file, void *priv, static int vidioc_vdec_g_selection(struct file *file, void *priv, struct v4l2_selection *s) { - struct mtk_vcodec_dec_ctx *ctx = fh_to_dec_ctx(priv); + struct mtk_vcodec_dec_ctx *ctx = file_to_dec_ctx(file); struct mtk_q_data *q_data; if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) @@ -442,7 +442,7 @@ static int vidioc_vdec_g_selection(struct file *file, void *priv, static int vidioc_vdec_s_selection(struct file *file, void *priv, struct v4l2_selection *s) { - struct mtk_vcodec_dec_ctx *ctx = fh_to_dec_ctx(priv); + struct mtk_vcodec_dec_ctx *ctx = file_to_dec_ctx(file); if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; @@ -464,7 +464,7 @@ static int vidioc_vdec_s_selection(struct file *file, void *priv, static int vidioc_vdec_s_fmt(struct file *file, void *priv, struct v4l2_format *f) { - struct mtk_vcodec_dec_ctx *ctx = fh_to_dec_ctx(priv); + struct mtk_vcodec_dec_ctx *ctx = file_to_dec_ctx(file); struct v4l2_pix_format_mplane *pix_mp; struct mtk_q_data *q_data; int ret = 0; @@ -594,7 +594,7 @@ static int vidioc_enum_framesizes(struct file *file, void *priv, struct v4l2_frmsizeenum *fsize) { int i = 0; - struct mtk_vcodec_dec_ctx *ctx = fh_to_dec_ctx(priv); + struct mtk_vcodec_dec_ctx *ctx = file_to_dec_ctx(file); const struct mtk_vcodec_dec_pdata *dec_pdata = ctx->dev->vdec_pdata; if (fsize->index != 0) @@ -623,10 +623,10 @@ static int vidioc_enum_framesizes(struct file *file, void *priv, return -EINVAL; } -static int vidioc_enum_fmt(struct v4l2_fmtdesc *f, void *priv, +static int vidioc_enum_fmt(struct file *file, struct v4l2_fmtdesc *f, bool output_queue) { - struct mtk_vcodec_dec_ctx *ctx = fh_to_dec_ctx(priv); + struct mtk_vcodec_dec_ctx *ctx = file_to_dec_ctx(file); const struct mtk_vcodec_dec_pdata *dec_pdata = ctx->dev->vdec_pdata; const struct mtk_video_fmt *fmt; int i, j = 0; @@ -660,19 +660,19 @@ static int vidioc_enum_fmt(struct v4l2_fmtdesc *f, void *priv, static int vidioc_vdec_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - return vidioc_enum_fmt(f, priv, false); + return vidioc_enum_fmt(file, f, false); } static int vidioc_vdec_enum_fmt_vid_out(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - return vidioc_enum_fmt(f, priv, true); + return vidioc_enum_fmt(file, f, true); } static int vidioc_vdec_g_fmt(struct file *file, void *priv, struct v4l2_format *f) { - struct mtk_vcodec_dec_ctx *ctx = fh_to_dec_ctx(priv); + struct mtk_vcodec_dec_ctx *ctx = file_to_dec_ctx(file); struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; struct vb2_queue *vq; struct mtk_q_data *q_data; diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c index 9247d92d431d..46d176e6de63 100644 --- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c +++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c @@ -206,8 +206,7 @@ static int fops_vcodec_open(struct file *file) mutex_lock(&dev->dev_mutex); ctx->id = dev->id_counter++; v4l2_fh_init(&ctx->fh, video_devdata(file)); - file->private_data = &ctx->fh; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); INIT_LIST_HEAD(&ctx->list); ctx->dev = dev; if (ctx->dev->vdec_pdata->is_subdev_supported) { @@ -283,7 +282,7 @@ err_load_fw: err_m2m_ctx_init: v4l2_ctrl_handler_free(&ctx->ctrl_hdl); err_ctrls_setup: - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); kfree(ctx); mutex_unlock(&dev->dev_mutex); @@ -294,7 +293,7 @@ err_ctrls_setup: static int fops_vcodec_release(struct file *file) { struct mtk_vcodec_dec_dev *dev = video_drvdata(file); - struct mtk_vcodec_dec_ctx *ctx = fh_to_dec_ctx(file->private_data); + struct mtk_vcodec_dec_ctx *ctx = file_to_dec_ctx(file); mtk_v4l2_vdec_dbg(0, ctx, "[%d] decoder", ctx->id); mutex_lock(&dev->dev_mutex); @@ -308,7 +307,7 @@ static int fops_vcodec_release(struct file *file) v4l2_m2m_ctx_release(ctx->m2m_ctx); mtk_vcodec_dec_release(ctx); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); v4l2_ctrl_handler_free(&ctx->ctrl_hdl); diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.h b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.h index aececca7ecf8..d047d7c580fb 100644 --- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.h +++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.h @@ -314,6 +314,11 @@ static inline struct mtk_vcodec_dec_ctx *fh_to_dec_ctx(struct v4l2_fh *fh) return container_of(fh, struct mtk_vcodec_dec_ctx, fh); } +static inline struct mtk_vcodec_dec_ctx *file_to_dec_ctx(struct file *filp) +{ + return fh_to_dec_ctx(file_to_v4l2_fh(filp)); +} + static inline struct mtk_vcodec_dec_ctx *ctrl_to_dec_ctx(struct v4l2_ctrl *ctrl) { return container_of(ctrl->handler, struct mtk_vcodec_dec_ctx, ctrl_hdl); diff --git a/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc.c b/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc.c index a01dc25a7699..d815e962ab89 100644 --- a/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc.c +++ b/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc.c @@ -159,7 +159,7 @@ static int vidioc_enum_framesizes(struct file *file, void *fh, struct v4l2_frmsizeenum *fsize) { const struct mtk_video_fmt *fmt; - struct mtk_vcodec_enc_ctx *ctx = fh_to_enc_ctx(fh); + struct mtk_vcodec_enc_ctx *ctx = file_to_enc_ctx(file); if (fsize->index != 0) return -EINVAL; @@ -183,7 +183,7 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f) { const struct mtk_vcodec_enc_pdata *pdata = - fh_to_enc_ctx(priv)->dev->venc_pdata; + file_to_enc_ctx(file)->dev->venc_pdata; return vidioc_enum_fmt(f, pdata->capture_formats, pdata->num_capture_formats); @@ -193,15 +193,14 @@ static int vidioc_enum_fmt_vid_out(struct file *file, void *priv, struct v4l2_fmtdesc *f) { const struct mtk_vcodec_enc_pdata *pdata = - fh_to_enc_ctx(priv)->dev->venc_pdata; + file_to_enc_ctx(file)->dev->venc_pdata; return vidioc_enum_fmt(f, pdata->output_formats, pdata->num_output_formats); } -static int mtk_vcodec_enc_get_chip_name(void *priv) +static int mtk_vcodec_enc_get_chip_name(struct mtk_vcodec_enc_ctx *ctx) { - struct mtk_vcodec_enc_ctx *ctx = fh_to_enc_ctx(priv); struct device *dev = &ctx->dev->plat_dev->dev; if (of_device_is_compatible(dev->of_node, "mediatek,mt8173-vcodec-enc")) @@ -221,9 +220,9 @@ static int mtk_vcodec_enc_get_chip_name(void *priv) static int vidioc_venc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { - struct mtk_vcodec_enc_ctx *ctx = fh_to_enc_ctx(priv); + struct mtk_vcodec_enc_ctx *ctx = file_to_enc_ctx(file); struct device *dev = &ctx->dev->plat_dev->dev; - int platform_name = mtk_vcodec_enc_get_chip_name(priv); + int platform_name = mtk_vcodec_enc_get_chip_name(ctx); strscpy(cap->driver, dev->driver->name, sizeof(cap->driver)); snprintf(cap->card, sizeof(cap->card), "MT%d video encoder", platform_name); @@ -234,7 +233,7 @@ static int vidioc_venc_querycap(struct file *file, void *priv, static int vidioc_venc_s_parm(struct file *file, void *priv, struct v4l2_streamparm *a) { - struct mtk_vcodec_enc_ctx *ctx = fh_to_enc_ctx(priv); + struct mtk_vcodec_enc_ctx *ctx = file_to_enc_ctx(file); struct v4l2_fract *timeperframe = &a->parm.output.timeperframe; if (a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) @@ -257,7 +256,7 @@ static int vidioc_venc_s_parm(struct file *file, void *priv, static int vidioc_venc_g_parm(struct file *file, void *priv, struct v4l2_streamparm *a) { - struct mtk_vcodec_enc_ctx *ctx = fh_to_enc_ctx(priv); + struct mtk_vcodec_enc_ctx *ctx = file_to_enc_ctx(file); if (a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) return -EINVAL; @@ -414,7 +413,7 @@ static void mtk_venc_set_param(struct mtk_vcodec_enc_ctx *ctx, static int vidioc_venc_s_fmt_cap(struct file *file, void *priv, struct v4l2_format *f) { - struct mtk_vcodec_enc_ctx *ctx = fh_to_enc_ctx(priv); + struct mtk_vcodec_enc_ctx *ctx = file_to_enc_ctx(file); const struct mtk_vcodec_enc_pdata *pdata = ctx->dev->venc_pdata; struct vb2_queue *vq; struct mtk_q_data *q_data = mtk_venc_get_q_data(ctx, f->type); @@ -469,7 +468,7 @@ static int vidioc_venc_s_fmt_cap(struct file *file, void *priv, static int vidioc_venc_s_fmt_out(struct file *file, void *priv, struct v4l2_format *f) { - struct mtk_vcodec_enc_ctx *ctx = fh_to_enc_ctx(priv); + struct mtk_vcodec_enc_ctx *ctx = file_to_enc_ctx(file); const struct mtk_vcodec_enc_pdata *pdata = ctx->dev->venc_pdata; struct vb2_queue *vq; struct mtk_q_data *q_data = mtk_venc_get_q_data(ctx, f->type); @@ -524,7 +523,7 @@ static int vidioc_venc_g_fmt(struct file *file, void *priv, struct v4l2_format *f) { struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp; - struct mtk_vcodec_enc_ctx *ctx = fh_to_enc_ctx(priv); + struct mtk_vcodec_enc_ctx *ctx = file_to_enc_ctx(file); struct vb2_queue *vq; struct mtk_q_data *q_data = mtk_venc_get_q_data(ctx, f->type); int i; @@ -557,7 +556,7 @@ static int vidioc_try_fmt_vid_cap_mplane(struct file *file, void *priv, struct v4l2_format *f) { const struct mtk_video_fmt *fmt; - struct mtk_vcodec_enc_ctx *ctx = fh_to_enc_ctx(priv); + struct mtk_vcodec_enc_ctx *ctx = file_to_enc_ctx(file); const struct mtk_vcodec_enc_pdata *pdata = ctx->dev->venc_pdata; fmt = mtk_venc_find_format(f->fmt.pix.pixelformat, pdata); @@ -579,7 +578,7 @@ static int vidioc_try_fmt_vid_out_mplane(struct file *file, void *priv, struct v4l2_format *f) { const struct mtk_video_fmt *fmt; - struct mtk_vcodec_enc_ctx *ctx = fh_to_enc_ctx(priv); + struct mtk_vcodec_enc_ctx *ctx = file_to_enc_ctx(file); const struct mtk_vcodec_enc_pdata *pdata = ctx->dev->venc_pdata; fmt = mtk_venc_find_format(f->fmt.pix.pixelformat, pdata); @@ -600,7 +599,7 @@ static int vidioc_try_fmt_vid_out_mplane(struct file *file, void *priv, static int vidioc_venc_g_selection(struct file *file, void *priv, struct v4l2_selection *s) { - struct mtk_vcodec_enc_ctx *ctx = fh_to_enc_ctx(priv); + struct mtk_vcodec_enc_ctx *ctx = file_to_enc_ctx(file); struct mtk_q_data *q_data = mtk_venc_get_q_data(ctx, s->type); if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) @@ -630,7 +629,7 @@ static int vidioc_venc_g_selection(struct file *file, void *priv, static int vidioc_venc_s_selection(struct file *file, void *priv, struct v4l2_selection *s) { - struct mtk_vcodec_enc_ctx *ctx = fh_to_enc_ctx(priv); + struct mtk_vcodec_enc_ctx *ctx = file_to_enc_ctx(file); struct mtk_q_data *q_data = mtk_venc_get_q_data(ctx, s->type); if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) @@ -655,7 +654,7 @@ static int vidioc_venc_s_selection(struct file *file, void *priv, static int vidioc_venc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) { - struct mtk_vcodec_enc_ctx *ctx = fh_to_enc_ctx(priv); + struct mtk_vcodec_enc_ctx *ctx = file_to_enc_ctx(file); if (ctx->state == MTK_STATE_ABORT) { mtk_v4l2_venc_err(ctx, "[%d] Call on QBUF after unrecoverable error", @@ -669,7 +668,7 @@ static int vidioc_venc_qbuf(struct file *file, void *priv, static int vidioc_venc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) { - struct mtk_vcodec_enc_ctx *ctx = fh_to_enc_ctx(priv); + struct mtk_vcodec_enc_ctx *ctx = file_to_enc_ctx(file); int ret; if (ctx->state == MTK_STATE_ABORT) { @@ -707,7 +706,7 @@ static int vidioc_venc_dqbuf(struct file *file, void *priv, static int vidioc_encoder_cmd(struct file *file, void *priv, struct v4l2_encoder_cmd *cmd) { - struct mtk_vcodec_enc_ctx *ctx = fh_to_enc_ctx(priv); + struct mtk_vcodec_enc_ctx *ctx = file_to_enc_ctx(file); struct vb2_queue *src_vq, *dst_vq; int ret; diff --git a/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv.c b/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv.c index a1e4483abcdb..fb1c3bdc2dae 100644 --- a/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv.c +++ b/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv.c @@ -129,8 +129,7 @@ static int fops_vcodec_open(struct file *file) */ ctx->id = dev->id_counter++; v4l2_fh_init(&ctx->fh, video_devdata(file)); - file->private_data = &ctx->fh; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); INIT_LIST_HEAD(&ctx->list); ctx->dev = dev; init_waitqueue_head(&ctx->queue[0]); @@ -192,7 +191,7 @@ err_load_fw: err_m2m_ctx_init: v4l2_ctrl_handler_free(&ctx->ctrl_hdl); err_ctrls_setup: - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); kfree(ctx); mutex_unlock(&dev->dev_mutex); @@ -203,14 +202,14 @@ err_ctrls_setup: static int fops_vcodec_release(struct file *file) { struct mtk_vcodec_enc_dev *dev = video_drvdata(file); - struct mtk_vcodec_enc_ctx *ctx = fh_to_enc_ctx(file->private_data); + struct mtk_vcodec_enc_ctx *ctx = file_to_enc_ctx(file); mtk_v4l2_venc_dbg(1, ctx, "[%d] encoder", ctx->id); mutex_lock(&dev->dev_mutex); v4l2_m2m_ctx_release(ctx->m2m_ctx); mtk_vcodec_enc_release(ctx); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); v4l2_ctrl_handler_free(&ctx->ctrl_hdl); diff --git a/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv.h b/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv.h index 0bd85d0fb379..5b304a551236 100644 --- a/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv.h +++ b/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv.h @@ -217,9 +217,9 @@ struct mtk_vcodec_enc_dev { struct mtk_vcodec_dbgfs dbgfs; }; -static inline struct mtk_vcodec_enc_ctx *fh_to_enc_ctx(struct v4l2_fh *fh) +static inline struct mtk_vcodec_enc_ctx *file_to_enc_ctx(struct file *filp) { - return container_of(fh, struct mtk_vcodec_enc_ctx, fh); + return container_of(file_to_v4l2_fh(filp), struct mtk_vcodec_enc_ctx, fh); } static inline struct mtk_vcodec_enc_ctx *ctrl_to_enc_ctx(struct v4l2_ctrl *ctrl) diff --git a/drivers/media/platform/nvidia/tegra-vde/v4l2.c b/drivers/media/platform/nvidia/tegra-vde/v4l2.c index e3726cab0c82..d94978ae2baf 100644 --- a/drivers/media/platform/nvidia/tegra-vde/v4l2.c +++ b/drivers/media/platform/nvidia/tegra-vde/v4l2.c @@ -46,9 +46,9 @@ static const struct v4l2_ctrl_config ctrl_cfgs[] = { }, }; -static inline struct tegra_ctx *fh_to_tegra_ctx(struct v4l2_fh *fh) +static inline struct tegra_ctx *file_to_tegra_ctx(struct file *file) { - return container_of(fh, struct tegra_ctx, fh); + return container_of(file_to_v4l2_fh(file), struct tegra_ctx, fh); } static void tegra_set_control_data(struct tegra_ctx *ctx, void *data, u32 id) @@ -506,7 +506,7 @@ static int tegra_querycap(struct file *file, void *priv, static int tegra_enum_decoded_fmt(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - struct tegra_ctx *ctx = fh_to_tegra_ctx(priv); + struct tegra_ctx *ctx = file_to_tegra_ctx(file); if (WARN_ON(!ctx->coded_fmt_desc)) return -EINVAL; @@ -522,7 +522,7 @@ static int tegra_enum_decoded_fmt(struct file *file, void *priv, static int tegra_g_decoded_fmt(struct file *file, void *priv, struct v4l2_format *f) { - struct tegra_ctx *ctx = fh_to_tegra_ctx(priv); + struct tegra_ctx *ctx = file_to_tegra_ctx(file); *f = ctx->decoded_fmt; return 0; @@ -531,8 +531,8 @@ static int tegra_g_decoded_fmt(struct file *file, void *priv, static int tegra_try_decoded_fmt(struct file *file, void *priv, struct v4l2_format *f) { + struct tegra_ctx *ctx = file_to_tegra_ctx(file); struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; - struct tegra_ctx *ctx = fh_to_tegra_ctx(priv); const struct tegra_coded_fmt_desc *coded_desc; unsigned int i; @@ -571,7 +571,7 @@ static int tegra_try_decoded_fmt(struct file *file, void *priv, static int tegra_s_decoded_fmt(struct file *file, void *priv, struct v4l2_format *f) { - struct tegra_ctx *ctx = fh_to_tegra_ctx(priv); + struct tegra_ctx *ctx = file_to_tegra_ctx(file); struct vb2_queue *vq; int err; @@ -593,7 +593,7 @@ static int tegra_s_decoded_fmt(struct file *file, void *priv, static int tegra_enum_coded_fmt(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - struct tegra_ctx *ctx = fh_to_tegra_ctx(priv); + struct tegra_ctx *ctx = file_to_tegra_ctx(file); const struct tegra_vde_soc *soc = ctx->vde->soc; if (f->index >= soc->num_coded_fmts) @@ -607,7 +607,7 @@ static int tegra_enum_coded_fmt(struct file *file, void *priv, static int tegra_g_coded_fmt(struct file *file, void *priv, struct v4l2_format *f) { - struct tegra_ctx *ctx = fh_to_tegra_ctx(priv); + struct tegra_ctx *ctx = file_to_tegra_ctx(file); *f = ctx->coded_fmt; return 0; @@ -631,7 +631,7 @@ static int tegra_try_coded_fmt(struct file *file, void *priv, struct v4l2_format *f) { struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; - struct tegra_ctx *ctx = fh_to_tegra_ctx(priv); + struct tegra_ctx *ctx = file_to_tegra_ctx(file); const struct tegra_vde_soc *soc = ctx->vde->soc; int size = pix_mp->plane_fmt[0].sizeimage; const struct tegra_coded_fmt_desc *desc; @@ -656,7 +656,7 @@ static int tegra_try_coded_fmt(struct file *file, void *priv, static int tegra_s_coded_fmt(struct file *file, void *priv, struct v4l2_format *f) { - struct tegra_ctx *ctx = fh_to_tegra_ctx(priv); + struct tegra_ctx *ctx = file_to_tegra_ctx(file); struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx; const struct tegra_coded_fmt_desc *desc; struct vb2_queue *peer_vq, *vq; @@ -718,7 +718,7 @@ static int tegra_s_coded_fmt(struct file *file, void *priv, static int tegra_enum_framesizes(struct file *file, void *priv, struct v4l2_frmsizeenum *fsize) { - struct tegra_ctx *ctx = fh_to_tegra_ctx(priv); + struct tegra_ctx *ctx = file_to_tegra_ctx(file); const struct tegra_coded_fmt_desc *fmt; if (fsize->index) @@ -832,14 +832,13 @@ static int tegra_open(struct file *file) goto free_ctrls; } - file->private_data = &ctx->fh; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); tegra_reset_coded_fmt(ctx); - tegra_try_coded_fmt(file, file->private_data, &ctx->coded_fmt); + tegra_try_coded_fmt(file, &ctx->fh, &ctx->coded_fmt); tegra_reset_decoded_fmt(ctx); - tegra_try_decoded_fmt(file, file->private_data, &ctx->decoded_fmt); + tegra_try_decoded_fmt(file, &ctx->fh, &ctx->decoded_fmt); return 0; @@ -853,11 +852,11 @@ free_ctx: static int tegra_release(struct file *file) { - struct v4l2_fh *fh = file->private_data; - struct tegra_ctx *ctx = fh_to_tegra_ctx(fh); + struct tegra_ctx *ctx = file_to_tegra_ctx(file); + struct v4l2_fh *fh = file_to_v4l2_fh(file); struct tegra_vde *vde = ctx->vde; - v4l2_fh_del(fh); + v4l2_fh_del(fh, file); v4l2_m2m_ctx_release(fh->m2m_ctx); v4l2_ctrl_handler_free(&ctx->hdl); v4l2_fh_exit(fh); diff --git a/drivers/media/platform/nxp/dw100/dw100.c b/drivers/media/platform/nxp/dw100/dw100.c index 3d1db1121bf9..97744c7b7c03 100644 --- a/drivers/media/platform/nxp/dw100/dw100.c +++ b/drivers/media/platform/nxp/dw100/dw100.c @@ -266,7 +266,7 @@ static inline int dw100_dump_regs(struct seq_file *m) static inline struct dw100_ctx *dw100_file2ctx(struct file *file) { - return container_of(file->private_data, struct dw100_ctx, fh); + return container_of(file_to_v4l2_fh(file), struct dw100_ctx, fh); } static struct dw100_q_data *dw100_get_q_data(struct dw100_ctx *ctx, @@ -607,7 +607,6 @@ static int dw100_open(struct file *file) mutex_init(&ctx->vq_mutex); v4l2_fh_init(&ctx->fh, video_devdata(file)); - file->private_data = &ctx->fh; ctx->dw_dev = dw_dev; ctx->q_data[DW100_QUEUE_SRC].fmt = &formats[0]; @@ -651,7 +650,7 @@ static int dw100_open(struct file *file) goto err; } - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); return 0; @@ -668,7 +667,7 @@ static int dw100_release(struct file *file) { struct dw100_ctx *ctx = dw100_file2ctx(file); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); v4l2_ctrl_handler_free(&ctx->hdl); v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); diff --git a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c index 8681dd193033..df3ccdf767ba 100644 --- a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c +++ b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c @@ -644,9 +644,9 @@ static void print_mxc_buf(struct mxc_jpeg_dev *jpeg, struct vb2_buffer *buf, } } -static inline struct mxc_jpeg_ctx *mxc_jpeg_fh_to_ctx(struct v4l2_fh *fh) +static inline struct mxc_jpeg_ctx *mxc_jpeg_file_to_ctx(struct file *filp) { - return container_of(fh, struct mxc_jpeg_ctx, fh); + return container_of(file_to_v4l2_fh(filp), struct mxc_jpeg_ctx, fh); } static int enum_fmt(const struct mxc_jpeg_fmt *mxc_formats, int n, @@ -1604,8 +1604,8 @@ end: static int mxc_jpeg_decoder_cmd(struct file *file, void *priv, struct v4l2_decoder_cmd *cmd) { - struct v4l2_fh *fh = file->private_data; - struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(fh); + struct v4l2_fh *fh = file_to_v4l2_fh(file); + struct mxc_jpeg_ctx *ctx = mxc_jpeg_file_to_ctx(file); unsigned long flags; int ret; @@ -1637,8 +1637,8 @@ static int mxc_jpeg_decoder_cmd(struct file *file, void *priv, static int mxc_jpeg_encoder_cmd(struct file *file, void *priv, struct v4l2_encoder_cmd *cmd) { - struct v4l2_fh *fh = file->private_data; - struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(fh); + struct v4l2_fh *fh = file_to_v4l2_fh(file); + struct mxc_jpeg_ctx *ctx = mxc_jpeg_file_to_ctx(file); unsigned long flags; int ret; @@ -2200,8 +2200,7 @@ static int mxc_jpeg_open(struct file *file) } v4l2_fh_init(&ctx->fh, mxc_vfd); - file->private_data = &ctx->fh; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); ctx->mxc_jpeg = mxc_jpeg; @@ -2234,7 +2233,7 @@ static int mxc_jpeg_open(struct file *file) err_ctrls_setup: v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); error: - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); mutex_unlock(&mxc_jpeg->lock); free: @@ -2256,7 +2255,7 @@ static int mxc_jpeg_querycap(struct file *file, void *priv, static int mxc_jpeg_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv); + struct mxc_jpeg_ctx *ctx = mxc_jpeg_file_to_ctx(file); struct mxc_jpeg_q_data *q_data = mxc_jpeg_get_q_data(ctx, f->type); if (ctx->mxc_jpeg->mode == MXC_JPEG_ENCODE) { @@ -2296,7 +2295,7 @@ static int mxc_jpeg_enum_fmt_vid_cap(struct file *file, void *priv, static int mxc_jpeg_enum_fmt_vid_out(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv); + struct mxc_jpeg_ctx *ctx = mxc_jpeg_file_to_ctx(file); u32 type = ctx->mxc_jpeg->mode == MXC_JPEG_DECODE ? MXC_JPEG_FMT_TYPE_ENC : MXC_JPEG_FMT_TYPE_RAW; int ret; @@ -2437,7 +2436,7 @@ static int mxc_jpeg_try_fmt(struct v4l2_format *f, static int mxc_jpeg_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv); + struct mxc_jpeg_ctx *ctx = mxc_jpeg_file_to_ctx(file); struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg; struct device *dev = jpeg->dev; struct mxc_jpeg_q_data tmp_q; @@ -2456,7 +2455,7 @@ static int mxc_jpeg_try_fmt_vid_cap(struct file *file, void *priv, static int mxc_jpeg_try_fmt_vid_out(struct file *file, void *priv, struct v4l2_format *f) { - struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv); + struct mxc_jpeg_ctx *ctx = mxc_jpeg_file_to_ctx(file); struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg; struct device *dev = jpeg->dev; struct mxc_jpeg_q_data tmp_q; @@ -2508,20 +2507,20 @@ static int mxc_jpeg_s_fmt(struct mxc_jpeg_ctx *ctx, static int mxc_jpeg_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - return mxc_jpeg_s_fmt(mxc_jpeg_fh_to_ctx(priv), f); + return mxc_jpeg_s_fmt(mxc_jpeg_file_to_ctx(file), f); } static int mxc_jpeg_s_fmt_vid_out(struct file *file, void *priv, struct v4l2_format *f) { int ret; - struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv); + struct mxc_jpeg_ctx *ctx = mxc_jpeg_file_to_ctx(file); struct vb2_queue *dst_vq; struct mxc_jpeg_q_data *q_data_cap; enum v4l2_buf_type cap_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; struct v4l2_format fc; - ret = mxc_jpeg_s_fmt(mxc_jpeg_fh_to_ctx(priv), f); + ret = mxc_jpeg_s_fmt(ctx, f); if (ret) return ret; @@ -2550,7 +2549,7 @@ static int mxc_jpeg_s_fmt_vid_out(struct file *file, void *priv, static int mxc_jpeg_g_fmt_vid(struct file *file, void *priv, struct v4l2_format *f) { - struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv); + struct mxc_jpeg_ctx *ctx = mxc_jpeg_file_to_ctx(file); struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg; struct device *dev = jpeg->dev; struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; @@ -2588,7 +2587,7 @@ static int mxc_jpeg_g_fmt_vid(struct file *file, void *priv, static int mxc_jpeg_dec_g_selection(struct file *file, void *fh, struct v4l2_selection *s) { - struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(fh); + struct mxc_jpeg_ctx *ctx = mxc_jpeg_file_to_ctx(file); struct mxc_jpeg_q_data *q_data_cap; if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) @@ -2617,7 +2616,7 @@ static int mxc_jpeg_dec_g_selection(struct file *file, void *fh, struct v4l2_sel static int mxc_jpeg_enc_g_selection(struct file *file, void *fh, struct v4l2_selection *s) { - struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(fh); + struct mxc_jpeg_ctx *ctx = mxc_jpeg_file_to_ctx(file); struct mxc_jpeg_q_data *q_data_out; if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) @@ -2645,7 +2644,7 @@ static int mxc_jpeg_enc_g_selection(struct file *file, void *fh, struct v4l2_sel static int mxc_jpeg_g_selection(struct file *file, void *fh, struct v4l2_selection *s) { - struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(fh); + struct mxc_jpeg_ctx *ctx = mxc_jpeg_file_to_ctx(file); if (ctx->mxc_jpeg->mode == MXC_JPEG_DECODE) return mxc_jpeg_dec_g_selection(file, fh, s); @@ -2655,7 +2654,7 @@ static int mxc_jpeg_g_selection(struct file *file, void *fh, struct v4l2_selecti static int mxc_jpeg_s_selection(struct file *file, void *fh, struct v4l2_selection *s) { - struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(fh); + struct mxc_jpeg_ctx *ctx = mxc_jpeg_file_to_ctx(file); struct mxc_jpeg_q_data *q_data_out; if (ctx->mxc_jpeg->mode != MXC_JPEG_ENCODE) @@ -2735,7 +2734,7 @@ static const struct v4l2_ioctl_ops mxc_jpeg_ioctl_ops = { static int mxc_jpeg_release(struct file *file) { struct mxc_jpeg_dev *mxc_jpeg = video_drvdata(file); - struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(file->private_data); + struct mxc_jpeg_ctx *ctx = mxc_jpeg_file_to_ctx(file); struct device *dev = mxc_jpeg->dev; mutex_lock(&mxc_jpeg->lock); @@ -2747,7 +2746,7 @@ static int mxc_jpeg_release(struct file *file) ctx->slot); v4l2_ctrl_handler_free(&ctx->ctrl_handler); v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); kfree(ctx); mutex_unlock(&mxc_jpeg->lock); diff --git a/drivers/media/platform/nxp/imx-mipi-csis.c b/drivers/media/platform/nxp/imx-mipi-csis.c index 2beb5f43c2c0..d5de7854f579 100644 --- a/drivers/media/platform/nxp/imx-mipi-csis.c +++ b/drivers/media/platform/nxp/imx-mipi-csis.c @@ -54,23 +54,19 @@ /* CSIS common control */ #define MIPI_CSIS_CMN_CTRL 0x04 -#define MIPI_CSIS_CMN_CTRL_UPDATE_SHADOW BIT(16) -#define MIPI_CSIS_CMN_CTRL_INTER_MODE BIT(10) +#define MIPI_CSIS_CMN_CTRL_UPDATE_SHADOW(n) BIT((n) + 16) +#define MIPI_CSIS_CMN_CTRL_INTERLEAVE_MODE_DT BIT(10) +#define MIPI_CSIS_CMN_CTRL_LANE_NUMBER(n) ((n) << 8) +#define MIPI_CSIS_CMN_CTRL_LANE_NUMBER_MASK GENMASK(9, 8) #define MIPI_CSIS_CMN_CTRL_UPDATE_SHADOW_CTRL BIT(2) -#define MIPI_CSIS_CMN_CTRL_RESET BIT(1) -#define MIPI_CSIS_CMN_CTRL_ENABLE BIT(0) - -#define MIPI_CSIS_CMN_CTRL_LANE_NR_OFFSET 8 -#define MIPI_CSIS_CMN_CTRL_LANE_NR_MASK (3 << 8) +#define MIPI_CSIS_CMN_CTRL_SW_RESET BIT(1) +#define MIPI_CSIS_CMN_CTRL_CSI_EN BIT(0) /* CSIS clock control */ #define MIPI_CSIS_CLK_CTRL 0x08 -#define MIPI_CSIS_CLK_CTRL_CLKGATE_TRAIL_CH3(x) ((x) << 28) -#define MIPI_CSIS_CLK_CTRL_CLKGATE_TRAIL_CH2(x) ((x) << 24) -#define MIPI_CSIS_CLK_CTRL_CLKGATE_TRAIL_CH1(x) ((x) << 20) -#define MIPI_CSIS_CLK_CTRL_CLKGATE_TRAIL_CH0(x) ((x) << 16) -#define MIPI_CSIS_CLK_CTRL_CLKGATE_EN_MSK (0xf << 4) -#define MIPI_CSIS_CLK_CTRL_WCLK_SRC BIT(0) +#define MIPI_CSIS_CLK_CTRL_CLKGATE_TRAIL(n, x) ((x) << ((n) * 4 + 16)) +#define MIPI_CSIS_CLK_CTRL_CLKGATE_EN_MASK GENMASK(7, 4) +#define MIPI_CSIS_CLK_CTRL_WCLK_SRC(n) BIT(n) /* CSIS Interrupt mask */ #define MIPI_CSIS_INT_MSK 0x10 @@ -87,7 +83,7 @@ #define MIPI_CSIS_INT_MSK_ERR_WRONG_CFG BIT(3) #define MIPI_CSIS_INT_MSK_ERR_ECC BIT(2) #define MIPI_CSIS_INT_MSK_ERR_CRC BIT(1) -#define MIPI_CSIS_INT_MSK_ERR_UNKNOWN BIT(0) +#define MIPI_CSIS_INT_MSK_ERR_ID BIT(0) /* CSIS Interrupt source */ #define MIPI_CSIS_INT_SRC 0x14 @@ -98,16 +94,16 @@ #define MIPI_CSIS_INT_SRC_ODD_AFTER BIT(28) #define MIPI_CSIS_INT_SRC_ODD (0x3 << 28) #define MIPI_CSIS_INT_SRC_NON_IMAGE_DATA (0xf << 28) -#define MIPI_CSIS_INT_SRC_FRAME_START BIT(24) -#define MIPI_CSIS_INT_SRC_FRAME_END BIT(20) -#define MIPI_CSIS_INT_SRC_ERR_SOT_HS BIT(16) -#define MIPI_CSIS_INT_SRC_ERR_LOST_FS BIT(12) -#define MIPI_CSIS_INT_SRC_ERR_LOST_FE BIT(8) -#define MIPI_CSIS_INT_SRC_ERR_OVER BIT(4) +#define MIPI_CSIS_INT_SRC_FRAME_START(n) BIT((n) + 24) +#define MIPI_CSIS_INT_SRC_FRAME_END(n) BIT((n) + 20) +#define MIPI_CSIS_INT_SRC_ERR_SOT_HS(n) BIT((n) + 16) +#define MIPI_CSIS_INT_SRC_ERR_LOST_FS(n) BIT((n) + 12) +#define MIPI_CSIS_INT_SRC_ERR_LOST_FE(n) BIT((n) + 8) +#define MIPI_CSIS_INT_SRC_ERR_OVER(n) BIT((n) + 4) #define MIPI_CSIS_INT_SRC_ERR_WRONG_CFG BIT(3) #define MIPI_CSIS_INT_SRC_ERR_ECC BIT(2) #define MIPI_CSIS_INT_SRC_ERR_CRC BIT(1) -#define MIPI_CSIS_INT_SRC_ERR_UNKNOWN BIT(0) +#define MIPI_CSIS_INT_SRC_ERR_ID BIT(0) #define MIPI_CSIS_INT_SRC_ERRORS 0xfffff /* D-PHY status control */ @@ -123,8 +119,8 @@ #define MIPI_CSIS_DPHY_CMN_CTRL_HSSETTLE_MASK GENMASK(31, 24) #define MIPI_CSIS_DPHY_CMN_CTRL_CLKSETTLE(n) ((n) << 22) #define MIPI_CSIS_DPHY_CMN_CTRL_CLKSETTLE_MASK GENMASK(23, 22) -#define MIPI_CSIS_DPHY_CMN_CTRL_DPDN_SWAP_CLK BIT(6) -#define MIPI_CSIS_DPHY_CMN_CTRL_DPDN_SWAP_DAT BIT(5) +#define MIPI_CSIS_DPHY_CMN_CTRL_S_DPDN_SWAP_CLK BIT(6) +#define MIPI_CSIS_DPHY_CMN_CTRL_S_DPDN_SWAP_DAT BIT(5) #define MIPI_CSIS_DPHY_CMN_CTRL_ENABLE_DAT BIT(1) #define MIPI_CSIS_DPHY_CMN_CTRL_ENABLE_CLK BIT(0) #define MIPI_CSIS_DPHY_CMN_CTRL_ENABLE (0x1f << 0) @@ -174,26 +170,28 @@ /* ISP Configuration register */ #define MIPI_CSIS_ISP_CONFIG_CH(n) (0x40 + (n) * 0x10) -#define MIPI_CSIS_ISPCFG_MEM_FULL_GAP_MSK (0xff << 24) +#define MIPI_CSIS_ISPCFG_MEM_FULL_GAP_MASK GENMASK(31, 24) #define MIPI_CSIS_ISPCFG_MEM_FULL_GAP(x) ((x) << 24) #define MIPI_CSIS_ISPCFG_PIXEL_MODE_SINGLE (0 << 12) #define MIPI_CSIS_ISPCFG_PIXEL_MODE_DUAL (1 << 12) #define MIPI_CSIS_ISPCFG_PIXEL_MODE_QUAD (2 << 12) /* i.MX8M[MNP] only */ -#define MIPI_CSIS_ISPCFG_PIXEL_MASK (3 << 12) -#define MIPI_CSIS_ISPCFG_ALIGN_32BIT BIT(11) -#define MIPI_CSIS_ISPCFG_FMT(fmt) ((fmt) << 2) -#define MIPI_CSIS_ISPCFG_FMT_MASK (0x3f << 2) +#define MIPI_CSIS_ISPCFG_PIXEL_MODE_MASK GENMASK(13, 12) +#define MIPI_CSIS_ISPCFG_PARALLEL BIT(11) +#define MIPI_CSIS_ISPCFG_DATAFORMAT(fmt) ((fmt) << 2) +#define MIPI_CSIS_ISPCFG_DATAFORMAT_MASK GENMASK(7, 2) /* ISP Image Resolution register */ #define MIPI_CSIS_ISP_RESOL_CH(n) (0x44 + (n) * 0x10) +#define MIPI_CSIS_ISP_RESOL_VRESOL(n) ((n) << 16) +#define MIPI_CSIS_ISP_RESOL_HRESOL(n) ((n) << 0) #define CSIS_MAX_PIX_WIDTH 0xffff #define CSIS_MAX_PIX_HEIGHT 0xffff /* ISP SYNC register */ #define MIPI_CSIS_ISP_SYNC_CH(n) (0x48 + (n) * 0x10) -#define MIPI_CSIS_ISP_SYNC_HSYNC_LINTV_OFFSET 18 -#define MIPI_CSIS_ISP_SYNC_VSYNC_SINTV_OFFSET 12 -#define MIPI_CSIS_ISP_SYNC_VSYNC_EINTV_OFFSET 0 +#define MIPI_CSIS_ISP_SYNC_HSYNC_LINTV(n) ((n) << 18) +#define MIPI_CSIS_ISP_SYNC_VSYNC_SINTV(n) ((n) << 12) +#define MIPI_CSIS_ISP_SYNC_VSYNC_EINTV(n) ((n) << 0) /* ISP shadow registers */ #define MIPI_CSIS_SDW_CONFIG_CH(n) (0x80 + (n) * 0x10) @@ -203,23 +201,23 @@ /* Debug control register */ #define MIPI_CSIS_DBG_CTRL 0xc0 #define MIPI_CSIS_DBG_INTR_MSK 0xc4 -#define MIPI_CSIS_DBG_INTR_MSK_DT_NOT_SUPPORT BIT(25) -#define MIPI_CSIS_DBG_INTR_MSK_DT_IGNORE BIT(24) -#define MIPI_CSIS_DBG_INTR_MSK_ERR_FRAME_SIZE BIT(20) -#define MIPI_CSIS_DBG_INTR_MSK_TRUNCATED_FRAME BIT(16) -#define MIPI_CSIS_DBG_INTR_MSK_EARLY_FE BIT(12) -#define MIPI_CSIS_DBG_INTR_MSK_EARLY_FS BIT(8) -#define MIPI_CSIS_DBG_INTR_MSK_CAM_VSYNC_FALL BIT(4) -#define MIPI_CSIS_DBG_INTR_MSK_CAM_VSYNC_RISE BIT(0) +#define MIPI_CSIS_DBG_INTR_MSK_DT_NOT_SUPPORT BIT(25) +#define MIPI_CSIS_DBG_INTR_MSK_DT_IGNORE BIT(24) +#define MIPI_CSIS_DBG_INTR_MSK_ERR_FRAME_SIZE(n) BIT((n) + 20) +#define MIPI_CSIS_DBG_INTR_MSK_TRUNCATED_FRAME(n) BIT((n) + 16) +#define MIPI_CSIS_DBG_INTR_MSK_EARLY_FE(n) BIT((n) + 12) +#define MIPI_CSIS_DBG_INTR_MSK_EARLY_FS(n) BIT((n) + 8) +#define MIPI_CSIS_DBG_INTR_MSK_CAM_VSYNC_FALL(n) BIT((n) + 4) +#define MIPI_CSIS_DBG_INTR_MSK_CAM_VSYNC_RISE(n) BIT((n) + 0) #define MIPI_CSIS_DBG_INTR_SRC 0xc8 -#define MIPI_CSIS_DBG_INTR_SRC_DT_NOT_SUPPORT BIT(25) -#define MIPI_CSIS_DBG_INTR_SRC_DT_IGNORE BIT(24) -#define MIPI_CSIS_DBG_INTR_SRC_ERR_FRAME_SIZE BIT(20) -#define MIPI_CSIS_DBG_INTR_SRC_TRUNCATED_FRAME BIT(16) -#define MIPI_CSIS_DBG_INTR_SRC_EARLY_FE BIT(12) -#define MIPI_CSIS_DBG_INTR_SRC_EARLY_FS BIT(8) -#define MIPI_CSIS_DBG_INTR_SRC_CAM_VSYNC_FALL BIT(4) -#define MIPI_CSIS_DBG_INTR_SRC_CAM_VSYNC_RISE BIT(0) +#define MIPI_CSIS_DBG_INTR_SRC_DT_NOT_SUPPORT BIT(25) +#define MIPI_CSIS_DBG_INTR_SRC_DT_IGNORE BIT(24) +#define MIPI_CSIS_DBG_INTR_SRC_ERR_FRAME_SIZE(n) BIT((n) + 20) +#define MIPI_CSIS_DBG_INTR_SRC_TRUNCATED_FRAME(n) BIT((n) + 16) +#define MIPI_CSIS_DBG_INTR_SRC_EARLY_FE(n) BIT((n) + 12) +#define MIPI_CSIS_DBG_INTR_SRC_EARLY_FS(n) BIT((n) + 8) +#define MIPI_CSIS_DBG_INTR_SRC_CAM_VSYNC_FALL(n) BIT((n) + 4) +#define MIPI_CSIS_DBG_INTR_SRC_CAM_VSYNC_RISE(n) BIT((n) + 0) #define MIPI_CSIS_FRAME_COUNTER_CH(n) (0x0100 + (n) * 4) @@ -228,10 +226,11 @@ #define MIPI_CSIS_PKTDATA_EVEN 0x3000 #define MIPI_CSIS_PKTDATA_SIZE SZ_4K -#define DEFAULT_SCLK_CSIS_FREQ 166000000UL +#define MIPI_CSIS_MAX_CHANNELS 4 struct mipi_csis_event { bool debug; + unsigned int channel; u32 mask; const char * const name; unsigned int counter; @@ -239,33 +238,70 @@ struct mipi_csis_event { static const struct mipi_csis_event mipi_csis_events[] = { /* Errors */ - { false, MIPI_CSIS_INT_SRC_ERR_SOT_HS, "SOT Error" }, - { false, MIPI_CSIS_INT_SRC_ERR_LOST_FS, "Lost Frame Start Error" }, - { false, MIPI_CSIS_INT_SRC_ERR_LOST_FE, "Lost Frame End Error" }, - { false, MIPI_CSIS_INT_SRC_ERR_OVER, "FIFO Overflow Error" }, - { false, MIPI_CSIS_INT_SRC_ERR_WRONG_CFG, "Wrong Configuration Error" }, - { false, MIPI_CSIS_INT_SRC_ERR_ECC, "ECC Error" }, - { false, MIPI_CSIS_INT_SRC_ERR_CRC, "CRC Error" }, - { false, MIPI_CSIS_INT_SRC_ERR_UNKNOWN, "Unknown Error" }, - { true, MIPI_CSIS_DBG_INTR_SRC_DT_NOT_SUPPORT, "Data Type Not Supported" }, - { true, MIPI_CSIS_DBG_INTR_SRC_DT_IGNORE, "Data Type Ignored" }, - { true, MIPI_CSIS_DBG_INTR_SRC_ERR_FRAME_SIZE, "Frame Size Error" }, - { true, MIPI_CSIS_DBG_INTR_SRC_TRUNCATED_FRAME, "Truncated Frame" }, - { true, MIPI_CSIS_DBG_INTR_SRC_EARLY_FE, "Early Frame End" }, - { true, MIPI_CSIS_DBG_INTR_SRC_EARLY_FS, "Early Frame Start" }, + { false, 0, MIPI_CSIS_INT_SRC_ERR_SOT_HS(0), "SOT 0 Error" }, + { false, 0, MIPI_CSIS_INT_SRC_ERR_SOT_HS(1), "SOT 1 Error" }, + { false, 0, MIPI_CSIS_INT_SRC_ERR_SOT_HS(2), "SOT 2 Error" }, + { false, 0, MIPI_CSIS_INT_SRC_ERR_SOT_HS(3), "SOT 3 Error" }, + { false, 0, MIPI_CSIS_INT_SRC_ERR_LOST_FS(0), "Lost Frame Start Error 0" }, + { false, 1, MIPI_CSIS_INT_SRC_ERR_LOST_FS(1), "Lost Frame Start Error 1" }, + { false, 2, MIPI_CSIS_INT_SRC_ERR_LOST_FS(2), "Lost Frame Start Error 2" }, + { false, 3, MIPI_CSIS_INT_SRC_ERR_LOST_FS(3), "Lost Frame Start Error 3" }, + { false, 0, MIPI_CSIS_INT_SRC_ERR_LOST_FE(0), "Lost Frame End Error 0" }, + { false, 1, MIPI_CSIS_INT_SRC_ERR_LOST_FE(1), "Lost Frame End Error 1" }, + { false, 2, MIPI_CSIS_INT_SRC_ERR_LOST_FE(2), "Lost Frame End Error 2" }, + { false, 3, MIPI_CSIS_INT_SRC_ERR_LOST_FE(3), "Lost Frame End Error 3" }, + { false, 0, MIPI_CSIS_INT_SRC_ERR_OVER(0), "FIFO Overflow Error 0" }, + { false, 1, MIPI_CSIS_INT_SRC_ERR_OVER(1), "FIFO Overflow Error 1" }, + { false, 2, MIPI_CSIS_INT_SRC_ERR_OVER(2), "FIFO Overflow Error 2" }, + { false, 3, MIPI_CSIS_INT_SRC_ERR_OVER(3), "FIFO Overflow Error 3" }, + { false, 0, MIPI_CSIS_INT_SRC_ERR_WRONG_CFG, "Wrong Configuration Error" }, + { false, 0, MIPI_CSIS_INT_SRC_ERR_ECC, "ECC Error" }, + { false, 0, MIPI_CSIS_INT_SRC_ERR_CRC, "CRC Error" }, + { false, 0, MIPI_CSIS_INT_SRC_ERR_ID, "Unknown ID Error" }, + { true, 0, MIPI_CSIS_DBG_INTR_SRC_DT_NOT_SUPPORT, "Data Type Not Supported" }, + { true, 0, MIPI_CSIS_DBG_INTR_SRC_DT_IGNORE, "Data Type Ignored" }, + { true, 0, MIPI_CSIS_DBG_INTR_SRC_ERR_FRAME_SIZE(0), "Frame Size Error 0" }, + { true, 1, MIPI_CSIS_DBG_INTR_SRC_ERR_FRAME_SIZE(1), "Frame Size Error 1" }, + { true, 2, MIPI_CSIS_DBG_INTR_SRC_ERR_FRAME_SIZE(2), "Frame Size Error 2" }, + { true, 3, MIPI_CSIS_DBG_INTR_SRC_ERR_FRAME_SIZE(3), "Frame Size Error 3" }, + { true, 0, MIPI_CSIS_DBG_INTR_SRC_TRUNCATED_FRAME(0), "Truncated Frame 0" }, + { true, 1, MIPI_CSIS_DBG_INTR_SRC_TRUNCATED_FRAME(1), "Truncated Frame 1" }, + { true, 2, MIPI_CSIS_DBG_INTR_SRC_TRUNCATED_FRAME(2), "Truncated Frame 2" }, + { true, 3, MIPI_CSIS_DBG_INTR_SRC_TRUNCATED_FRAME(3), "Truncated Frame 3" }, + { true, 0, MIPI_CSIS_DBG_INTR_SRC_EARLY_FE(0), "Early Frame End 0" }, + { true, 1, MIPI_CSIS_DBG_INTR_SRC_EARLY_FE(1), "Early Frame End 1" }, + { true, 2, MIPI_CSIS_DBG_INTR_SRC_EARLY_FE(2), "Early Frame End 2" }, + { true, 3, MIPI_CSIS_DBG_INTR_SRC_EARLY_FE(3), "Early Frame End 3" }, + { true, 0, MIPI_CSIS_DBG_INTR_SRC_EARLY_FS(0), "Early Frame Start 0" }, + { true, 1, MIPI_CSIS_DBG_INTR_SRC_EARLY_FS(1), "Early Frame Start 1" }, + { true, 2, MIPI_CSIS_DBG_INTR_SRC_EARLY_FS(2), "Early Frame Start 2" }, + { true, 3, MIPI_CSIS_DBG_INTR_SRC_EARLY_FS(3), "Early Frame Start 3" }, /* Non-image data receive events */ - { false, MIPI_CSIS_INT_SRC_EVEN_BEFORE, "Non-image data before even frame" }, - { false, MIPI_CSIS_INT_SRC_EVEN_AFTER, "Non-image data after even frame" }, - { false, MIPI_CSIS_INT_SRC_ODD_BEFORE, "Non-image data before odd frame" }, - { false, MIPI_CSIS_INT_SRC_ODD_AFTER, "Non-image data after odd frame" }, + { false, 0, MIPI_CSIS_INT_SRC_EVEN_BEFORE, "Non-image data before even frame" }, + { false, 0, MIPI_CSIS_INT_SRC_EVEN_AFTER, "Non-image data after even frame" }, + { false, 0, MIPI_CSIS_INT_SRC_ODD_BEFORE, "Non-image data before odd frame" }, + { false, 0, MIPI_CSIS_INT_SRC_ODD_AFTER, "Non-image data after odd frame" }, /* Frame start/end */ - { false, MIPI_CSIS_INT_SRC_FRAME_START, "Frame Start" }, - { false, MIPI_CSIS_INT_SRC_FRAME_END, "Frame End" }, - { true, MIPI_CSIS_DBG_INTR_SRC_CAM_VSYNC_FALL, "VSYNC Falling Edge" }, - { true, MIPI_CSIS_DBG_INTR_SRC_CAM_VSYNC_RISE, "VSYNC Rising Edge" }, + { false, 0, MIPI_CSIS_INT_SRC_FRAME_START(0), "Frame Start 0" }, + { false, 1, MIPI_CSIS_INT_SRC_FRAME_START(1), "Frame Start 1" }, + { false, 2, MIPI_CSIS_INT_SRC_FRAME_START(2), "Frame Start 2" }, + { false, 3, MIPI_CSIS_INT_SRC_FRAME_START(3), "Frame Start 3" }, + { false, 0, MIPI_CSIS_INT_SRC_FRAME_END(0), "Frame End 0" }, + { false, 1, MIPI_CSIS_INT_SRC_FRAME_END(1), "Frame End 1" }, + { false, 2, MIPI_CSIS_INT_SRC_FRAME_END(2), "Frame End 2" }, + { false, 3, MIPI_CSIS_INT_SRC_FRAME_END(3), "Frame End 3" }, + { true, 0, MIPI_CSIS_DBG_INTR_SRC_CAM_VSYNC_FALL(0), "VSYNC Falling Edge 0" }, + { true, 1, MIPI_CSIS_DBG_INTR_SRC_CAM_VSYNC_FALL(1), "VSYNC Falling Edge 1" }, + { true, 2, MIPI_CSIS_DBG_INTR_SRC_CAM_VSYNC_FALL(2), "VSYNC Falling Edge 2" }, + { true, 3, MIPI_CSIS_DBG_INTR_SRC_CAM_VSYNC_FALL(3), "VSYNC Falling Edge 3" }, + { true, 0, MIPI_CSIS_DBG_INTR_SRC_CAM_VSYNC_RISE(0), "VSYNC Rising Edge 0" }, + { true, 1, MIPI_CSIS_DBG_INTR_SRC_CAM_VSYNC_RISE(1), "VSYNC Rising Edge 1" }, + { true, 2, MIPI_CSIS_DBG_INTR_SRC_CAM_VSYNC_RISE(2), "VSYNC Rising Edge 2" }, + { true, 3, MIPI_CSIS_DBG_INTR_SRC_CAM_VSYNC_RISE(3), "VSYNC Rising Edge 3" }, }; -#define MIPI_CSIS_NUM_EVENTS ARRAY_SIZE(mipi_csis_events) +#define MIPI_CSIS_NUM_EVENTS ARRAY_SIZE(mipi_csis_events) +#define MIPI_CSIS_NUM_ERROR_EVENTS 38 enum mipi_csis_clk { MIPI_CSIS_CLK_PCLK, @@ -297,7 +333,9 @@ struct mipi_csis_device { struct clk_bulk_data *clks; struct reset_control *mrst; struct regulator *mipi_phy_regulator; + const struct mipi_csis_info *info; + unsigned int num_channels; struct v4l2_subdev sd; struct media_pad pads[CSIS_PADS_NUM]; @@ -517,7 +555,7 @@ static void mipi_csis_sw_reset(struct mipi_csis_device *csis) u32 val = mipi_csis_read(csis, MIPI_CSIS_CMN_CTRL); mipi_csis_write(csis, MIPI_CSIS_CMN_CTRL, - val | MIPI_CSIS_CMN_CTRL_RESET); + val | MIPI_CSIS_CMN_CTRL_SW_RESET); usleep_range(10, 20); } @@ -527,9 +565,9 @@ static void mipi_csis_system_enable(struct mipi_csis_device *csis, int on) val = mipi_csis_read(csis, MIPI_CSIS_CMN_CTRL); if (on) - val |= MIPI_CSIS_CMN_CTRL_ENABLE; + val |= MIPI_CSIS_CMN_CTRL_CSI_EN; else - val &= ~MIPI_CSIS_CMN_CTRL_ENABLE; + val &= ~MIPI_CSIS_CMN_CTRL_CSI_EN; mipi_csis_write(csis, MIPI_CSIS_CMN_CTRL, val); val = mipi_csis_read(csis, MIPI_CSIS_DPHY_CMN_CTRL); @@ -549,8 +587,8 @@ static void __mipi_csis_set_format(struct mipi_csis_device *csis, /* Color format */ val = mipi_csis_read(csis, MIPI_CSIS_ISP_CONFIG_CH(0)); - val &= ~(MIPI_CSIS_ISPCFG_ALIGN_32BIT | MIPI_CSIS_ISPCFG_FMT_MASK - | MIPI_CSIS_ISPCFG_PIXEL_MASK); + val &= ~(MIPI_CSIS_ISPCFG_PARALLEL | MIPI_CSIS_ISPCFG_PIXEL_MODE_MASK | + MIPI_CSIS_ISPCFG_DATAFORMAT_MASK); /* * YUV 4:2:2 can be transferred with 8 or 16 bits per clock sample @@ -568,24 +606,23 @@ static void __mipi_csis_set_format(struct mipi_csis_device *csis, if (csis_fmt->data_type == MIPI_CSI2_DT_YUV422_8B) val |= MIPI_CSIS_ISPCFG_PIXEL_MODE_DUAL; - val |= MIPI_CSIS_ISPCFG_FMT(csis_fmt->data_type); + val |= MIPI_CSIS_ISPCFG_DATAFORMAT(csis_fmt->data_type); mipi_csis_write(csis, MIPI_CSIS_ISP_CONFIG_CH(0), val); /* Pixel resolution */ - val = format->width | (format->height << 16); - mipi_csis_write(csis, MIPI_CSIS_ISP_RESOL_CH(0), val); + mipi_csis_write(csis, MIPI_CSIS_ISP_RESOL_CH(0), + MIPI_CSIS_ISP_RESOL_VRESOL(format->height) | + MIPI_CSIS_ISP_RESOL_HRESOL(format->width)); } static int mipi_csis_calculate_params(struct mipi_csis_device *csis, const struct csis_pix_format *csis_fmt) { - struct media_pad *src_pad = - &csis->source.sd->entity.pads[csis->source.pad->index]; s64 link_freq; u32 lane_rate; /* Calculate the line rate from the pixel rate. */ - link_freq = v4l2_get_link_freq(src_pad, csis_fmt->width, + link_freq = v4l2_get_link_freq(csis->source.pad, csis_fmt->width, csis->bus.num_data_lanes * 2); if (link_freq < 0) { dev_err(csis->dev, "Unable to obtain link frequency: %d\n", @@ -635,10 +672,10 @@ static void mipi_csis_set_params(struct mipi_csis_device *csis, u32 val; val = mipi_csis_read(csis, MIPI_CSIS_CMN_CTRL); - val &= ~MIPI_CSIS_CMN_CTRL_LANE_NR_MASK; - val |= (lanes - 1) << MIPI_CSIS_CMN_CTRL_LANE_NR_OFFSET; + val &= ~MIPI_CSIS_CMN_CTRL_LANE_NUMBER_MASK; + val |= MIPI_CSIS_CMN_CTRL_LANE_NUMBER(lanes - 1); if (csis->info->version == MIPI_CSIS_V3_3) - val |= MIPI_CSIS_CMN_CTRL_INTER_MODE; + val |= MIPI_CSIS_CMN_CTRL_INTERLEAVE_MODE_DT; mipi_csis_write(csis, MIPI_CSIS_CMN_CTRL, val); __mipi_csis_set_format(csis, format, csis_fmt); @@ -647,15 +684,15 @@ static void mipi_csis_set_params(struct mipi_csis_device *csis, MIPI_CSIS_DPHY_CMN_CTRL_HSSETTLE(csis->hs_settle) | MIPI_CSIS_DPHY_CMN_CTRL_CLKSETTLE(csis->clk_settle)); - val = (0 << MIPI_CSIS_ISP_SYNC_HSYNC_LINTV_OFFSET) - | (0 << MIPI_CSIS_ISP_SYNC_VSYNC_SINTV_OFFSET) - | (0 << MIPI_CSIS_ISP_SYNC_VSYNC_EINTV_OFFSET); - mipi_csis_write(csis, MIPI_CSIS_ISP_SYNC_CH(0), val); + mipi_csis_write(csis, MIPI_CSIS_ISP_SYNC_CH(0), + MIPI_CSIS_ISP_SYNC_HSYNC_LINTV(0) | + MIPI_CSIS_ISP_SYNC_VSYNC_SINTV(0) | + MIPI_CSIS_ISP_SYNC_VSYNC_EINTV(0)); val = mipi_csis_read(csis, MIPI_CSIS_CLK_CTRL); - val |= MIPI_CSIS_CLK_CTRL_WCLK_SRC; - val |= MIPI_CSIS_CLK_CTRL_CLKGATE_TRAIL_CH0(15); - val &= ~MIPI_CSIS_CLK_CTRL_CLKGATE_EN_MSK; + val |= MIPI_CSIS_CLK_CTRL_WCLK_SRC(0); + val |= MIPI_CSIS_CLK_CTRL_CLKGATE_TRAIL(0, 15); + val &= ~MIPI_CSIS_CLK_CTRL_CLKGATE_EN_MASK; mipi_csis_write(csis, MIPI_CSIS_CLK_CTRL, val); mipi_csis_write(csis, MIPI_CSIS_DPHY_BCTRL_L, @@ -671,7 +708,7 @@ static void mipi_csis_set_params(struct mipi_csis_device *csis, /* Update the shadow register. */ val = mipi_csis_read(csis, MIPI_CSIS_CMN_CTRL); mipi_csis_write(csis, MIPI_CSIS_CMN_CTRL, - val | MIPI_CSIS_CMN_CTRL_UPDATE_SHADOW | + val | MIPI_CSIS_CMN_CTRL_UPDATE_SHADOW(0) | MIPI_CSIS_CMN_CTRL_UPDATE_SHADOW_CTRL); } @@ -704,12 +741,17 @@ static int mipi_csis_clk_get(struct mipi_csis_device *csis) if (ret < 0) return ret; - /* Set clock rate */ - ret = clk_set_rate(csis->clks[MIPI_CSIS_CLK_WRAP].clk, - csis->clk_frequency); - if (ret < 0) - dev_err(csis->dev, "set rate=%d failed: %d\n", - csis->clk_frequency, ret); + if (csis->clk_frequency) { + /* + * Set the clock rate. This is deprecated, for backward + * compatibility with old device trees. + */ + ret = clk_set_rate(csis->clks[MIPI_CSIS_CLK_WRAP].clk, + csis->clk_frequency); + if (ret < 0) + dev_err(csis->dev, "set rate=%d failed: %d\n", + csis->clk_frequency, ret); + } return ret; } @@ -757,16 +799,19 @@ static irqreturn_t mipi_csis_irq_handler(int irq, void *dev_id) /* Update the event/error counters */ if ((status & MIPI_CSIS_INT_SRC_ERRORS) || csis->debug.enable) { - for (i = 0; i < MIPI_CSIS_NUM_EVENTS; i++) { + for (i = 0; i < ARRAY_SIZE(csis->events); i++) { struct mipi_csis_event *event = &csis->events[i]; + if (event->channel >= csis->num_channels) + continue; + if ((!event->debug && (status & event->mask)) || (event->debug && (dbg_status & event->mask))) event->counter++; } } - if (status & MIPI_CSIS_INT_SRC_FRAME_START) + if (status & MIPI_CSIS_INT_SRC_FRAME_START(0)) mipi_csis_queue_event_sof(csis); spin_unlock_irqrestore(&csis->slock, flags); @@ -843,7 +888,7 @@ static void mipi_csis_clear_counters(struct mipi_csis_device *csis) static void mipi_csis_log_counters(struct mipi_csis_device *csis, bool non_errors) { unsigned int num_events = non_errors ? MIPI_CSIS_NUM_EVENTS - : MIPI_CSIS_NUM_EVENTS - 8; + : MIPI_CSIS_NUM_ERROR_EVENTS; unsigned int counters[MIPI_CSIS_NUM_EVENTS]; unsigned long flags; unsigned int i; @@ -854,45 +899,67 @@ static void mipi_csis_log_counters(struct mipi_csis_device *csis, bool non_error spin_unlock_irqrestore(&csis->slock, flags); for (i = 0; i < num_events; ++i) { + const struct mipi_csis_event *event = &csis->events[i]; + + if (event->channel >= csis->num_channels) + continue; + if (counters[i] > 0 || csis->debug.enable) dev_info(csis->dev, "%s events: %d\n", - csis->events[i].name, - counters[i]); + event->name, counters[i]); } } +struct mipi_csis_reg_info { + u32 addr; + unsigned int offset; + const char * const name; +}; + +static void mipi_csis_dump_channel_reg(struct mipi_csis_device *csis, + const struct mipi_csis_reg_info *reg, + unsigned int channel) +{ + dev_info(csis->dev, "%16s%u: 0x%08x\n", reg->name, channel, + mipi_csis_read(csis, reg->addr + channel * reg->offset)); +} + static int mipi_csis_dump_regs(struct mipi_csis_device *csis) { - static const struct { - u32 offset; - const char * const name; - } registers[] = { - { MIPI_CSIS_CMN_CTRL, "CMN_CTRL" }, - { MIPI_CSIS_CLK_CTRL, "CLK_CTRL" }, - { MIPI_CSIS_INT_MSK, "INT_MSK" }, - { MIPI_CSIS_DPHY_STATUS, "DPHY_STATUS" }, - { MIPI_CSIS_DPHY_CMN_CTRL, "DPHY_CMN_CTRL" }, - { MIPI_CSIS_DPHY_SCTRL_L, "DPHY_SCTRL_L" }, - { MIPI_CSIS_DPHY_SCTRL_H, "DPHY_SCTRL_H" }, - { MIPI_CSIS_ISP_CONFIG_CH(0), "ISP_CONFIG_CH0" }, - { MIPI_CSIS_ISP_RESOL_CH(0), "ISP_RESOL_CH0" }, - { MIPI_CSIS_SDW_CONFIG_CH(0), "SDW_CONFIG_CH0" }, - { MIPI_CSIS_SDW_RESOL_CH(0), "SDW_RESOL_CH0" }, - { MIPI_CSIS_DBG_CTRL, "DBG_CTRL" }, - { MIPI_CSIS_FRAME_COUNTER_CH(0), "FRAME_COUNTER_CH0" }, + static const struct mipi_csis_reg_info common_registers[] = { + { MIPI_CSIS_CMN_CTRL, 0, "CMN_CTRL" }, + { MIPI_CSIS_CLK_CTRL, 0, "CLK_CTRL" }, + { MIPI_CSIS_INT_MSK, 0, "INT_MSK" }, + { MIPI_CSIS_DPHY_STATUS, 0, "DPHY_STATUS" }, + { MIPI_CSIS_DPHY_CMN_CTRL, 0, "DPHY_CMN_CTRL" }, + { MIPI_CSIS_DPHY_SCTRL_L, 0, "DPHY_SCTRL_L" }, + { MIPI_CSIS_DPHY_SCTRL_H, 0, "DPHY_SCTRL_H" }, + { MIPI_CSIS_DBG_CTRL, 0, "DBG_CTRL" }, + }; + static const struct mipi_csis_reg_info channel_registers[] = { + { MIPI_CSIS_ISP_CONFIG_CH(0), 0x10, "ISP_CONFIG_CH" }, + { MIPI_CSIS_ISP_RESOL_CH(0), 0x10, "ISP_RESOL_CH" }, + { MIPI_CSIS_SDW_CONFIG_CH(0), 0x10, "SDW_CONFIG_CH" }, + { MIPI_CSIS_SDW_RESOL_CH(0), 0x10, "SDW_RESOL_CH" }, + { MIPI_CSIS_FRAME_COUNTER_CH(0), 4, "FRAME_COUNTER_CH" }, }; - - unsigned int i; - u32 cfg; if (!pm_runtime_get_if_in_use(csis->dev)) return 0; dev_info(csis->dev, "--- REGISTERS ---\n"); - for (i = 0; i < ARRAY_SIZE(registers); i++) { - cfg = mipi_csis_read(csis, registers[i].offset); - dev_info(csis->dev, "%14s: 0x%08x\n", registers[i].name, cfg); + for (unsigned int i = 0; i < ARRAY_SIZE(common_registers); i++) { + const struct mipi_csis_reg_info *reg = &common_registers[i]; + + dev_info(csis->dev, "%17s: 0x%08x\n", reg->name, + mipi_csis_read(csis, reg->addr)); + } + + for (unsigned int chan = 0; chan < csis->num_channels; chan++) { + for (unsigned int i = 0; i < ARRAY_SIZE(channel_registers); ++i) + mipi_csis_dump_channel_reg(csis, &channel_registers[i], + chan); } pm_runtime_put(csis->dev); @@ -998,7 +1065,7 @@ err_unlock: } static int mipi_csis_enum_mbus_code(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_state *state, struct v4l2_subdev_mbus_code_enum *code) { /* @@ -1011,7 +1078,7 @@ static int mipi_csis_enum_mbus_code(struct v4l2_subdev *sd, if (code->index > 0) return -EINVAL; - fmt = v4l2_subdev_state_get_format(sd_state, code->pad); + fmt = v4l2_subdev_state_get_format(state, code->pad); code->code = fmt->code; return 0; } @@ -1028,10 +1095,10 @@ static int mipi_csis_enum_mbus_code(struct v4l2_subdev *sd, } static int mipi_csis_set_fmt(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_state *state, struct v4l2_subdev_format *sdformat) { - struct csis_pix_format const *csis_fmt; + const struct csis_pix_format *csis_fmt; struct v4l2_mbus_framefmt *fmt; unsigned int align; @@ -1040,7 +1107,7 @@ static int mipi_csis_set_fmt(struct v4l2_subdev *sd, * modified. */ if (sdformat->pad == CSIS_PAD_SOURCE) - return v4l2_subdev_get_fmt(sd, sd_state, sdformat); + return v4l2_subdev_get_fmt(sd, state, sdformat); if (sdformat->pad != CSIS_PAD_SINK) return -EINVAL; @@ -1078,7 +1145,7 @@ static int mipi_csis_set_fmt(struct v4l2_subdev *sd, &sdformat->format.height, 1, CSIS_MAX_PIX_HEIGHT, 0, 0); - fmt = v4l2_subdev_state_get_format(sd_state, sdformat->pad); + fmt = v4l2_subdev_state_get_format(state, sdformat->pad); fmt->code = csis_fmt->code; fmt->width = sdformat->format.width; @@ -1092,7 +1159,7 @@ static int mipi_csis_set_fmt(struct v4l2_subdev *sd, sdformat->format = *fmt; /* Propagate the format from sink to source. */ - fmt = v4l2_subdev_state_get_format(sd_state, CSIS_PAD_SOURCE); + fmt = v4l2_subdev_state_get_format(state, CSIS_PAD_SOURCE); *fmt = sdformat->format; /* The format on the source pad might change due to unpacking. */ @@ -1132,7 +1199,7 @@ static int mipi_csis_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad, } static int mipi_csis_init_state(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state) + struct v4l2_subdev_state *state) { struct v4l2_subdev_format fmt = { .pad = CSIS_PAD_SINK, @@ -1149,7 +1216,7 @@ static int mipi_csis_init_state(struct v4l2_subdev *sd, V4L2_MAP_QUANTIZATION_DEFAULT(false, fmt.format.colorspace, fmt.format.ycbcr_enc); - return mipi_csis_set_fmt(sd, sd_state, &fmt); + return mipi_csis_set_fmt(sd, state, &fmt); } static int mipi_csis_log_status(struct v4l2_subdev *sd) @@ -1413,9 +1480,13 @@ static int mipi_csis_parse_dt(struct mipi_csis_device *csis) { struct device_node *node = csis->dev->of_node; - if (of_property_read_u32(node, "clock-frequency", - &csis->clk_frequency)) - csis->clk_frequency = DEFAULT_SCLK_CSIS_FREQ; + of_property_read_u32(node, "clock-frequency", &csis->clk_frequency); + + csis->num_channels = 1; + of_property_read_u32(node, "fsl,num-channels", &csis->num_channels); + if (csis->num_channels < 1 || csis->num_channels > MIPI_CSIS_MAX_CHANNELS) + return dev_err_probe(csis->dev, -EINVAL, + "Invalid fsl,num-channels value\n"); return 0; } @@ -1440,10 +1511,8 @@ static int mipi_csis_probe(struct platform_device *pdev) /* Parse DT properties. */ ret = mipi_csis_parse_dt(csis); - if (ret < 0) { - dev_err(dev, "Failed to parse device tree: %d\n", ret); + if (ret < 0) return ret; - } /* Acquire resources. */ csis->regs = devm_platform_ioremap_resource(pdev, 0); diff --git a/drivers/media/platform/nxp/imx-pxp.c b/drivers/media/platform/nxp/imx-pxp.c index 7f8ffbac582f..6cc9b07ea53a 100644 --- a/drivers/media/platform/nxp/imx-pxp.c +++ b/drivers/media/platform/nxp/imx-pxp.c @@ -248,7 +248,7 @@ struct pxp_ctx { static inline struct pxp_ctx *file2ctx(struct file *file) { - return container_of(file->private_data, struct pxp_ctx, fh); + return container_of(file_to_v4l2_fh(file), struct pxp_ctx, fh); } static struct pxp_q_data *get_q_data(struct pxp_ctx *ctx, @@ -1660,7 +1660,6 @@ static int pxp_open(struct file *file) } v4l2_fh_init(&ctx->fh, video_devdata(file)); - file->private_data = &ctx->fh; ctx->dev = dev; hdl = &ctx->hdl; v4l2_ctrl_handler_init(hdl, 4); @@ -1699,7 +1698,7 @@ static int pxp_open(struct file *file) goto open_unlock; } - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); atomic_inc(&dev->num_inst); dprintk(dev, "Created instance: %p, m2m_ctx: %p\n", @@ -1717,7 +1716,7 @@ static int pxp_release(struct file *file) dprintk(dev, "Releasing instance %p\n", ctx); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); v4l2_ctrl_handler_free(&ctx->hdl); mutex_lock(&dev->dev_mutex); diff --git a/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.c b/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.c index 981648a03113..adc8d9960bf0 100644 --- a/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.c +++ b/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.c @@ -374,6 +374,8 @@ static int mxc_isi_pm_suspend(struct device *dev) mxc_isi_video_suspend(pipe); } + mxc_isi_m2m_suspend(&isi->m2m); + return pm_runtime_force_suspend(dev); } @@ -403,6 +405,12 @@ static int mxc_isi_pm_resume(struct device *dev) } } + ret = mxc_isi_m2m_resume(&isi->m2m); + if (ret) { + dev_err(dev, "Failed to resume ISI (%d) for m2m\n", ret); + err = ret; + } + return err; } diff --git a/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.h b/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.h index 206995bedca4..e84af5127e4e 100644 --- a/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.h +++ b/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.h @@ -202,9 +202,8 @@ struct mxc_isi_video { struct video_device vdev; struct media_pad pad; - /* Protects is_streaming, and the vdev and vb2_q operations */ + /* Protects the vdev and vb2_q operations */ struct mutex lock; - bool is_streaming; struct v4l2_pix_format_mplane pix; const struct mxc_isi_format_info *fmtinfo; @@ -343,6 +342,8 @@ int mxc_isi_video_buffer_prepare(struct mxc_isi_dev *isi, struct vb2_buffer *vb2 #ifdef CONFIG_VIDEO_IMX8_ISI_M2M int mxc_isi_m2m_register(struct mxc_isi_dev *isi, struct v4l2_device *v4l2_dev); int mxc_isi_m2m_unregister(struct mxc_isi_dev *isi); +void mxc_isi_m2m_suspend(struct mxc_isi_m2m *m2m); +int mxc_isi_m2m_resume(struct mxc_isi_m2m *m2m); #else static inline int mxc_isi_m2m_register(struct mxc_isi_dev *isi, struct v4l2_device *v4l2_dev) @@ -353,6 +354,13 @@ static inline int mxc_isi_m2m_unregister(struct mxc_isi_dev *isi) { return 0; } +static inline void mxc_isi_m2m_suspend(struct mxc_isi_m2m *m2m) +{ +} +static inline int mxc_isi_m2m_resume(struct mxc_isi_m2m *m2m) +{ + return 0; +} #endif int mxc_isi_channel_acquire(struct mxc_isi_pipe *pipe, @@ -362,7 +370,7 @@ void mxc_isi_channel_get(struct mxc_isi_pipe *pipe); void mxc_isi_channel_put(struct mxc_isi_pipe *pipe); void mxc_isi_channel_enable(struct mxc_isi_pipe *pipe); void mxc_isi_channel_disable(struct mxc_isi_pipe *pipe); -int mxc_isi_channel_chain(struct mxc_isi_pipe *pipe, bool bypass); +int mxc_isi_channel_chain(struct mxc_isi_pipe *pipe); void mxc_isi_channel_unchain(struct mxc_isi_pipe *pipe); void mxc_isi_channel_config(struct mxc_isi_pipe *pipe, diff --git a/drivers/media/platform/nxp/imx8-isi/imx8-isi-hw.c b/drivers/media/platform/nxp/imx8-isi/imx8-isi-hw.c index 5623914f95e6..9225a7ac1c3e 100644 --- a/drivers/media/platform/nxp/imx8-isi/imx8-isi-hw.c +++ b/drivers/media/platform/nxp/imx8-isi/imx8-isi-hw.c @@ -587,7 +587,7 @@ void mxc_isi_channel_release(struct mxc_isi_pipe *pipe) * * TODO: Support secondary line buffer for downscaling YUV420 images. */ -int mxc_isi_channel_chain(struct mxc_isi_pipe *pipe, bool bypass) +int mxc_isi_channel_chain(struct mxc_isi_pipe *pipe) { /* Channel chaining requires both line and output buffer. */ const u8 resources = MXC_ISI_CHANNEL_RES_OUTPUT_BUF diff --git a/drivers/media/platform/nxp/imx8-isi/imx8-isi-m2m.c b/drivers/media/platform/nxp/imx8-isi/imx8-isi-m2m.c index 22e49d3a1287..00afcbfbdde4 100644 --- a/drivers/media/platform/nxp/imx8-isi/imx8-isi-m2m.c +++ b/drivers/media/platform/nxp/imx8-isi/imx8-isi-m2m.c @@ -43,7 +43,6 @@ struct mxc_isi_m2m_ctx_queue_data { struct v4l2_pix_format_mplane format; const struct mxc_isi_format_info *info; u32 sequence; - bool streaming; }; struct mxc_isi_m2m_ctx { @@ -74,9 +73,9 @@ to_isi_m2m_buffer(struct vb2_v4l2_buffer *buf) return container_of(buf, struct mxc_isi_m2m_buffer, buf.vb); } -static inline struct mxc_isi_m2m_ctx *to_isi_m2m_ctx(struct v4l2_fh *fh) +static inline struct mxc_isi_m2m_ctx *file_to_isi_m2m_ctx(struct file *filp) { - return container_of(fh, struct mxc_isi_m2m_ctx, fh); + return container_of(file_to_v4l2_fh(filp), struct mxc_isi_m2m_ctx, fh); } static inline struct mxc_isi_m2m_ctx_queue_data * @@ -236,6 +235,70 @@ static void mxc_isi_m2m_vb2_buffer_queue(struct vb2_buffer *vb2) v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); } +static int mxc_isi_m2m_vb2_prepare_streaming(struct vb2_queue *q) +{ + struct mxc_isi_m2m_ctx *ctx = vb2_get_drv_priv(q); + const struct v4l2_pix_format_mplane *out_pix = &ctx->queues.out.format; + const struct v4l2_pix_format_mplane *cap_pix = &ctx->queues.cap.format; + const struct mxc_isi_format_info *cap_info = ctx->queues.cap.info; + const struct mxc_isi_format_info *out_info = ctx->queues.out.info; + struct mxc_isi_m2m *m2m = ctx->m2m; + int ret; + + guard(mutex)(&m2m->lock); + + if (m2m->usage_count == INT_MAX) + return -EOVERFLOW; + + ret = pm_runtime_resume_and_get(m2m->isi->dev); + if (ret) + return ret; + + /* + * Acquire the pipe and initialize the channel with the first user of + * the M2M device. + */ + if (m2m->usage_count == 0) { + bool bypass = cap_pix->width == out_pix->width && + cap_pix->height == out_pix->height && + cap_info->encoding == out_info->encoding; + + ret = mxc_isi_channel_acquire(m2m->pipe, + &mxc_isi_m2m_frame_write_done, + bypass); + if (ret) + goto err_pm; + + mxc_isi_channel_get(m2m->pipe); + } + + m2m->usage_count++; + + /* + * Allocate resources for the channel, counting how many users require + * buffer chaining. + */ + if (!ctx->chained && out_pix->width > MXC_ISI_MAX_WIDTH_UNCHAINED) { + ret = mxc_isi_channel_chain(m2m->pipe); + if (ret) + goto err_deinit; + + m2m->chained_count++; + ctx->chained = true; + } + + return 0; + +err_deinit: + if (--m2m->usage_count == 0) { + mxc_isi_channel_put(m2m->pipe); + mxc_isi_channel_release(m2m->pipe); + } +err_pm: + pm_runtime_put(m2m->isi->dev); + return ret; +} + static int mxc_isi_m2m_vb2_start_streaming(struct vb2_queue *q, unsigned int count) { @@ -265,13 +328,46 @@ static void mxc_isi_m2m_vb2_stop_streaming(struct vb2_queue *q) } } +static void mxc_isi_m2m_vb2_unprepare_streaming(struct vb2_queue *q) +{ + struct mxc_isi_m2m_ctx *ctx = vb2_get_drv_priv(q); + struct mxc_isi_m2m *m2m = ctx->m2m; + + guard(mutex)(&m2m->lock); + + /* + * If the last context is this one, reset it to make sure the device + * will be reconfigured when streaming is restarted. + */ + if (m2m->last_ctx == ctx) + m2m->last_ctx = NULL; + + /* Free the channel resources if this is the last chained context. */ + if (ctx->chained && --m2m->chained_count == 0) + mxc_isi_channel_unchain(m2m->pipe); + ctx->chained = false; + + /* Turn off the light with the last user. */ + if (--m2m->usage_count == 0) { + mxc_isi_channel_disable(m2m->pipe); + mxc_isi_channel_put(m2m->pipe); + mxc_isi_channel_release(m2m->pipe); + } + + WARN_ON(m2m->usage_count < 0); + + pm_runtime_put(m2m->isi->dev); +} + static const struct vb2_ops mxc_isi_m2m_vb2_qops = { .queue_setup = mxc_isi_m2m_vb2_queue_setup, .buf_init = mxc_isi_m2m_vb2_buffer_init, .buf_prepare = mxc_isi_m2m_vb2_buffer_prepare, .buf_queue = mxc_isi_m2m_vb2_buffer_queue, + .prepare_streaming = mxc_isi_m2m_vb2_prepare_streaming, .start_streaming = mxc_isi_m2m_vb2_start_streaming, .stop_streaming = mxc_isi_m2m_vb2_stop_streaming, + .unprepare_streaming = mxc_isi_m2m_vb2_unprepare_streaming, }; static int mxc_isi_m2m_queue_init(void *priv, struct vb2_queue *src_vq, @@ -427,7 +523,7 @@ static int mxc_isi_m2m_try_fmt_vid(struct file *file, void *fh, const enum mxc_isi_video_type type = f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ? MXC_ISI_VIDEO_M2M_OUT : MXC_ISI_VIDEO_M2M_CAP; - struct mxc_isi_m2m_ctx *ctx = to_isi_m2m_ctx(fh); + struct mxc_isi_m2m_ctx *ctx = file_to_isi_m2m_ctx(file); __mxc_isi_m2m_try_fmt_vid(ctx, &f->fmt.pix_mp, type); @@ -437,7 +533,7 @@ static int mxc_isi_m2m_try_fmt_vid(struct file *file, void *fh, static int mxc_isi_m2m_g_fmt_vid(struct file *file, void *fh, struct v4l2_format *f) { - struct mxc_isi_m2m_ctx *ctx = to_isi_m2m_ctx(fh); + struct mxc_isi_m2m_ctx *ctx = file_to_isi_m2m_ctx(file); const struct mxc_isi_m2m_ctx_queue_data *qdata = mxc_isi_m2m_ctx_qdata(ctx, f->type); @@ -452,7 +548,7 @@ static int mxc_isi_m2m_s_fmt_vid(struct file *file, void *fh, const enum mxc_isi_video_type type = f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ? MXC_ISI_VIDEO_M2M_OUT : MXC_ISI_VIDEO_M2M_CAP; - struct mxc_isi_m2m_ctx *ctx = to_isi_m2m_ctx(fh); + struct mxc_isi_m2m_ctx *ctx = file_to_isi_m2m_ctx(file); struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp; const struct mxc_isi_format_info *info; struct vb2_queue *vq; @@ -481,136 +577,6 @@ static int mxc_isi_m2m_s_fmt_vid(struct file *file, void *fh, return 0; } -static int mxc_isi_m2m_streamon(struct file *file, void *fh, - enum v4l2_buf_type type) -{ - struct mxc_isi_m2m_ctx *ctx = to_isi_m2m_ctx(fh); - struct mxc_isi_m2m_ctx_queue_data *q = mxc_isi_m2m_ctx_qdata(ctx, type); - const struct v4l2_pix_format_mplane *out_pix = &ctx->queues.out.format; - const struct v4l2_pix_format_mplane *cap_pix = &ctx->queues.cap.format; - const struct mxc_isi_format_info *cap_info = ctx->queues.cap.info; - const struct mxc_isi_format_info *out_info = ctx->queues.out.info; - struct mxc_isi_m2m *m2m = ctx->m2m; - bool bypass; - int ret; - - if (q->streaming) - return 0; - - mutex_lock(&m2m->lock); - - if (m2m->usage_count == INT_MAX) { - ret = -EOVERFLOW; - goto unlock; - } - - bypass = cap_pix->width == out_pix->width && - cap_pix->height == out_pix->height && - cap_info->encoding == out_info->encoding; - - /* - * Acquire the pipe and initialize the channel with the first user of - * the M2M device. - */ - if (m2m->usage_count == 0) { - ret = mxc_isi_channel_acquire(m2m->pipe, - &mxc_isi_m2m_frame_write_done, - bypass); - if (ret) - goto unlock; - - mxc_isi_channel_get(m2m->pipe); - } - - m2m->usage_count++; - - /* - * Allocate resources for the channel, counting how many users require - * buffer chaining. - */ - if (!ctx->chained && out_pix->width > MXC_ISI_MAX_WIDTH_UNCHAINED) { - ret = mxc_isi_channel_chain(m2m->pipe, bypass); - if (ret) - goto deinit; - - m2m->chained_count++; - ctx->chained = true; - } - - /* - * Drop the lock to start the stream, as the .device_run() operation - * needs to acquire it. - */ - mutex_unlock(&m2m->lock); - ret = v4l2_m2m_ioctl_streamon(file, fh, type); - if (ret) { - /* Reacquire the lock for the cleanup path. */ - mutex_lock(&m2m->lock); - goto unchain; - } - - q->streaming = true; - - return 0; - -unchain: - if (ctx->chained && --m2m->chained_count == 0) - mxc_isi_channel_unchain(m2m->pipe); - ctx->chained = false; - -deinit: - if (--m2m->usage_count == 0) { - mxc_isi_channel_put(m2m->pipe); - mxc_isi_channel_release(m2m->pipe); - } - -unlock: - mutex_unlock(&m2m->lock); - return ret; -} - -static int mxc_isi_m2m_streamoff(struct file *file, void *fh, - enum v4l2_buf_type type) -{ - struct mxc_isi_m2m_ctx *ctx = to_isi_m2m_ctx(fh); - struct mxc_isi_m2m_ctx_queue_data *q = mxc_isi_m2m_ctx_qdata(ctx, type); - struct mxc_isi_m2m *m2m = ctx->m2m; - - v4l2_m2m_ioctl_streamoff(file, fh, type); - - if (!q->streaming) - return 0; - - mutex_lock(&m2m->lock); - - /* - * If the last context is this one, reset it to make sure the device - * will be reconfigured when streaming is restarted. - */ - if (m2m->last_ctx == ctx) - m2m->last_ctx = NULL; - - /* Free the channel resources if this is the last chained context. */ - if (ctx->chained && --m2m->chained_count == 0) - mxc_isi_channel_unchain(m2m->pipe); - ctx->chained = false; - - /* Turn off the light with the last user. */ - if (--m2m->usage_count == 0) { - mxc_isi_channel_disable(m2m->pipe); - mxc_isi_channel_put(m2m->pipe); - mxc_isi_channel_release(m2m->pipe); - } - - WARN_ON(m2m->usage_count < 0); - - mutex_unlock(&m2m->lock); - - q->streaming = false; - - return 0; -} - static const struct v4l2_ioctl_ops mxc_isi_m2m_ioctl_ops = { .vidioc_querycap = mxc_isi_m2m_querycap, @@ -631,8 +597,8 @@ static const struct v4l2_ioctl_ops mxc_isi_m2m_ioctl_ops = { .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf, .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs, - .vidioc_streamon = mxc_isi_m2m_streamon, - .vidioc_streamoff = mxc_isi_m2m_streamoff, + .vidioc_streamon = v4l2_m2m_ioctl_streamon, + .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, .vidioc_unsubscribe_event = v4l2_event_unsubscribe, @@ -668,7 +634,6 @@ static int mxc_isi_m2m_open(struct file *file) mutex_init(&ctx->vb2_lock); v4l2_fh_init(&ctx->fh, vdev); - file->private_data = &ctx->fh; ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(m2m->m2m_dev, ctx, &mxc_isi_m2m_queue_init); @@ -685,16 +650,10 @@ static int mxc_isi_m2m_open(struct file *file) if (ret) goto err_ctx; - ret = pm_runtime_resume_and_get(m2m->isi->dev); - if (ret) - goto err_ctrls; - - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); return 0; -err_ctrls: - mxc_isi_m2m_ctx_ctrls_delete(ctx); err_ctx: v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); err_fh: @@ -706,20 +665,17 @@ err_fh: static int mxc_isi_m2m_release(struct file *file) { - struct mxc_isi_m2m *m2m = video_drvdata(file); - struct mxc_isi_m2m_ctx *ctx = to_isi_m2m_ctx(file->private_data); + struct mxc_isi_m2m_ctx *ctx = file_to_isi_m2m_ctx(file); v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); mxc_isi_m2m_ctx_ctrls_delete(ctx); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); mutex_destroy(&ctx->vb2_lock); kfree(ctx); - pm_runtime_put(m2m->isi->dev); - return 0; } @@ -733,6 +689,40 @@ static const struct v4l2_file_operations mxc_isi_m2m_fops = { }; /* ----------------------------------------------------------------------------- + * Suspend & resume + */ + +void mxc_isi_m2m_suspend(struct mxc_isi_m2m *m2m) +{ + if (m2m->usage_count == 0) + return; + + v4l2_m2m_suspend(m2m->m2m_dev); + + if (m2m->chained_count > 0) + mxc_isi_channel_unchain(m2m->pipe); + + mxc_isi_channel_disable(m2m->pipe); + mxc_isi_channel_put(m2m->pipe); +} + +int mxc_isi_m2m_resume(struct mxc_isi_m2m *m2m) +{ + if (m2m->usage_count == 0) + return 0; + + mxc_isi_channel_get(m2m->pipe); + + if (m2m->chained_count > 0) + mxc_isi_channel_chain(m2m->pipe); + + m2m->last_ctx = NULL; + v4l2_m2m_resume(m2m->m2m_dev); + + return 0; +} + +/* ----------------------------------------------------------------------------- * Registration */ diff --git a/drivers/media/platform/nxp/imx8-isi/imx8-isi-pipe.c b/drivers/media/platform/nxp/imx8-isi/imx8-isi-pipe.c index d76eb58deb09..a41c51dd9ce0 100644 --- a/drivers/media/platform/nxp/imx8-isi/imx8-isi-pipe.c +++ b/drivers/media/platform/nxp/imx8-isi/imx8-isi-pipe.c @@ -855,7 +855,7 @@ int mxc_isi_pipe_acquire(struct mxc_isi_pipe *pipe, /* Chain the channel if needed for wide resolutions. */ if (sink_fmt->width > MXC_ISI_MAX_WIDTH_UNCHAINED) { - ret = mxc_isi_channel_chain(pipe, bypass); + ret = mxc_isi_channel_chain(pipe); if (ret) mxc_isi_channel_release(pipe); } diff --git a/drivers/media/platform/nxp/imx8-isi/imx8-isi-video.c b/drivers/media/platform/nxp/imx8-isi/imx8-isi-video.c index 8654150728a8..13682bf6e9f8 100644 --- a/drivers/media/platform/nxp/imx8-isi/imx8-isi-video.c +++ b/drivers/media/platform/nxp/imx8-isi/imx8-isi-video.c @@ -937,6 +937,47 @@ static void mxc_isi_video_init_channel(struct mxc_isi_video *video) mxc_isi_channel_set_output_format(pipe, video->fmtinfo, &video->pix); } +static int mxc_isi_vb2_prepare_streaming(struct vb2_queue *q) +{ + struct mxc_isi_video *video = vb2_get_drv_priv(q); + struct media_device *mdev = &video->pipe->isi->media_dev; + struct media_pipeline *pipe; + int ret; + + /* Get a pipeline for the video node and start it. */ + scoped_guard(mutex, &mdev->graph_mutex) { + ret = mxc_isi_pipe_acquire(video->pipe, + &mxc_isi_video_frame_write_done); + if (ret) + return ret; + + pipe = media_entity_pipeline(&video->vdev.entity) + ? : &video->pipe->pipe; + + ret = __video_device_pipeline_start(&video->vdev, pipe); + if (ret) + goto err_release; + } + + /* Verify that the video format matches the output of the subdev. */ + ret = mxc_isi_video_validate_format(video); + if (ret) + goto err_stop; + + /* Allocate buffers for discard operation. */ + ret = mxc_isi_video_alloc_discard_buffers(video); + if (ret) + goto err_stop; + + return 0; + +err_stop: + video_device_pipeline_stop(&video->vdev); +err_release: + mxc_isi_pipe_release(video->pipe); + return ret; +} + static int mxc_isi_vb2_start_streaming(struct vb2_queue *q, unsigned int count) { struct mxc_isi_video *video = vb2_get_drv_priv(q); @@ -985,13 +1026,24 @@ static void mxc_isi_vb2_stop_streaming(struct vb2_queue *q) mxc_isi_video_return_buffers(video, VB2_BUF_STATE_ERROR); } +static void mxc_isi_vb2_unprepare_streaming(struct vb2_queue *q) +{ + struct mxc_isi_video *video = vb2_get_drv_priv(q); + + mxc_isi_video_free_discard_buffers(video); + video_device_pipeline_stop(&video->vdev); + mxc_isi_pipe_release(video->pipe); +} + static const struct vb2_ops mxc_isi_vb2_qops = { .queue_setup = mxc_isi_vb2_queue_setup, .buf_init = mxc_isi_vb2_buffer_init, .buf_prepare = mxc_isi_vb2_buffer_prepare, .buf_queue = mxc_isi_vb2_buffer_queue, + .prepare_streaming = mxc_isi_vb2_prepare_streaming, .start_streaming = mxc_isi_vb2_start_streaming, .stop_streaming = mxc_isi_vb2_stop_streaming, + .unprepare_streaming = mxc_isi_vb2_unprepare_streaming, }; /* ----------------------------------------------------------------------------- @@ -1145,97 +1197,6 @@ static int mxc_isi_video_s_fmt(struct file *file, void *priv, return 0; } -static int mxc_isi_video_streamon(struct file *file, void *priv, - enum v4l2_buf_type type) -{ - struct mxc_isi_video *video = video_drvdata(file); - struct media_device *mdev = &video->pipe->isi->media_dev; - struct media_pipeline *pipe; - int ret; - - if (vb2_queue_is_busy(&video->vb2_q, file)) - return -EBUSY; - - /* - * Get a pipeline for the video node and start it. This must be done - * here and not in the queue .start_streaming() handler, so that - * pipeline start errors can be reported from VIDIOC_STREAMON and not - * delayed until subsequent VIDIOC_QBUF calls. - */ - mutex_lock(&mdev->graph_mutex); - - ret = mxc_isi_pipe_acquire(video->pipe, &mxc_isi_video_frame_write_done); - if (ret) { - mutex_unlock(&mdev->graph_mutex); - return ret; - } - - pipe = media_entity_pipeline(&video->vdev.entity) ? : &video->pipe->pipe; - - ret = __video_device_pipeline_start(&video->vdev, pipe); - if (ret) { - mutex_unlock(&mdev->graph_mutex); - goto err_release; - } - - mutex_unlock(&mdev->graph_mutex); - - /* Verify that the video format matches the output of the subdev. */ - ret = mxc_isi_video_validate_format(video); - if (ret) - goto err_stop; - - /* Allocate buffers for discard operation. */ - ret = mxc_isi_video_alloc_discard_buffers(video); - if (ret) - goto err_stop; - - ret = vb2_streamon(&video->vb2_q, type); - if (ret) - goto err_free; - - video->is_streaming = true; - - return 0; - -err_free: - mxc_isi_video_free_discard_buffers(video); -err_stop: - video_device_pipeline_stop(&video->vdev); -err_release: - mxc_isi_pipe_release(video->pipe); - return ret; -} - -static void mxc_isi_video_cleanup_streaming(struct mxc_isi_video *video) -{ - lockdep_assert_held(&video->lock); - - if (!video->is_streaming) - return; - - mxc_isi_video_free_discard_buffers(video); - video_device_pipeline_stop(&video->vdev); - mxc_isi_pipe_release(video->pipe); - - video->is_streaming = false; -} - -static int mxc_isi_video_streamoff(struct file *file, void *priv, - enum v4l2_buf_type type) -{ - struct mxc_isi_video *video = video_drvdata(file); - int ret; - - ret = vb2_ioctl_streamoff(file, priv, type); - if (ret) - return ret; - - mxc_isi_video_cleanup_streaming(video); - - return 0; -} - static int mxc_isi_video_enum_framesizes(struct file *file, void *priv, struct v4l2_frmsizeenum *fsize) { @@ -1291,9 +1252,8 @@ static const struct v4l2_ioctl_ops mxc_isi_video_ioctl_ops = { .vidioc_expbuf = vb2_ioctl_expbuf, .vidioc_prepare_buf = vb2_ioctl_prepare_buf, .vidioc_create_bufs = vb2_ioctl_create_bufs, - - .vidioc_streamon = mxc_isi_video_streamon, - .vidioc_streamoff = mxc_isi_video_streamoff, + .vidioc_streamon = vb2_ioctl_streamon, + .vidioc_streamoff = vb2_ioctl_streamoff, .vidioc_enum_framesizes = mxc_isi_video_enum_framesizes, @@ -1332,10 +1292,6 @@ static int mxc_isi_video_release(struct file *file) if (ret) dev_err(video->pipe->isi->dev, "%s fail\n", __func__); - mutex_lock(&video->lock); - mxc_isi_video_cleanup_streaming(video); - mutex_unlock(&video->lock); - pm_runtime_put(video->pipe->isi->dev); return ret; } @@ -1357,7 +1313,7 @@ void mxc_isi_video_suspend(struct mxc_isi_pipe *pipe) { struct mxc_isi_video *video = &pipe->video; - if (!video->is_streaming) + if (!vb2_is_streaming(&video->vb2_q)) return; mxc_isi_pipe_disable(pipe); @@ -1388,7 +1344,7 @@ int mxc_isi_video_resume(struct mxc_isi_pipe *pipe) { struct mxc_isi_video *video = &pipe->video; - if (!video->is_streaming) + if (!vb2_is_streaming(&video->vb2_q)) return 0; mxc_isi_video_init_channel(video); diff --git a/drivers/media/platform/nxp/mx2_emmaprp.c b/drivers/media/platform/nxp/mx2_emmaprp.c index 0c6cc120fd2a..3aae8c0b690c 100644 --- a/drivers/media/platform/nxp/mx2_emmaprp.c +++ b/drivers/media/platform/nxp/mx2_emmaprp.c @@ -214,6 +214,11 @@ struct emmaprp_ctx { struct emmaprp_q_data q_data[2]; }; +static inline struct emmaprp_ctx *file_to_emmaprp_ctx(struct file *filp) +{ + return container_of(file_to_v4l2_fh(filp), struct emmaprp_ctx, fh); +} + static struct emmaprp_q_data *get_q_data(struct emmaprp_ctx *ctx, enum v4l2_buf_type type) { @@ -451,13 +456,13 @@ static int vidioc_g_fmt(struct emmaprp_ctx *ctx, struct v4l2_format *f) static int vidioc_g_fmt_vid_out(struct file *file, void *priv, struct v4l2_format *f) { - return vidioc_g_fmt(priv, f); + return vidioc_g_fmt(file_to_emmaprp_ctx(file), f); } static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - return vidioc_g_fmt(priv, f); + return vidioc_g_fmt(file_to_emmaprp_ctx(file), f); } static int vidioc_try_fmt(struct v4l2_format *f) @@ -497,8 +502,8 @@ static int vidioc_try_fmt(struct v4l2_format *f) static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { + struct emmaprp_ctx *ctx = file_to_emmaprp_ctx(file); struct emmaprp_fmt *fmt; - struct emmaprp_ctx *ctx = priv; fmt = find_format(f); if (!fmt || !(fmt->types & MEM2MEM_CAPTURE)) { @@ -514,8 +519,8 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, static int vidioc_try_fmt_vid_out(struct file *file, void *priv, struct v4l2_format *f) { + struct emmaprp_ctx *ctx = file_to_emmaprp_ctx(file); struct emmaprp_fmt *fmt; - struct emmaprp_ctx *ctx = priv; fmt = find_format(f); if (!fmt || !(fmt->types & MEM2MEM_OUTPUT)) { @@ -575,7 +580,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, if (ret) return ret; - return vidioc_s_fmt(priv, f); + return vidioc_s_fmt(file_to_emmaprp_ctx(file), f); } static int vidioc_s_fmt_vid_out(struct file *file, void *priv, @@ -587,7 +592,7 @@ static int vidioc_s_fmt_vid_out(struct file *file, void *priv, if (ret) return ret; - return vidioc_s_fmt(priv, f); + return vidioc_s_fmt(file_to_emmaprp_ctx(file), f); } static const struct v4l2_ioctl_ops emmaprp_ioctl_ops = { @@ -725,7 +730,6 @@ static int emmaprp_open(struct file *file) return -ENOMEM; v4l2_fh_init(&ctx->fh, video_devdata(file)); - file->private_data = &ctx->fh; ctx->dev = pcdev; if (mutex_lock_interruptible(&pcdev->dev_mutex)) { @@ -747,7 +751,7 @@ static int emmaprp_open(struct file *file) clk_prepare_enable(pcdev->clk_emma_ahb); ctx->q_data[V4L2_M2M_SRC].fmt = &formats[1]; ctx->q_data[V4L2_M2M_DST].fmt = &formats[0]; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); mutex_unlock(&pcdev->dev_mutex); dprintk(pcdev, "Created instance %p, m2m_ctx: %p\n", ctx, ctx->fh.m2m_ctx); @@ -758,14 +762,14 @@ static int emmaprp_open(struct file *file) static int emmaprp_release(struct file *file) { struct emmaprp_dev *pcdev = video_drvdata(file); - struct emmaprp_ctx *ctx = file->private_data; + struct emmaprp_ctx *ctx = file_to_emmaprp_ctx(file); dprintk(pcdev, "Releasing instance %p\n", ctx); mutex_lock(&pcdev->dev_mutex); clk_disable_unprepare(pcdev->clk_emma_ahb); clk_disable_unprepare(pcdev->clk_emma_ipg); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); mutex_unlock(&pcdev->dev_mutex); diff --git a/drivers/media/platform/qcom/camss/Makefile b/drivers/media/platform/qcom/camss/Makefile index d26a9c24a430..23960d02877d 100644 --- a/drivers/media/platform/qcom/camss/Makefile +++ b/drivers/media/platform/qcom/camss/Makefile @@ -6,9 +6,10 @@ qcom-camss-objs += \ camss-csid.o \ camss-csid-4-1.o \ camss-csid-4-7.o \ + camss-csid-340.o \ camss-csid-680.o \ camss-csid-gen2.o \ - camss-csid-780.o \ + camss-csid-gen3.o \ camss-csiphy-2ph-1-0.o \ camss-csiphy-3ph-1-0.o \ camss-csiphy.o \ @@ -17,9 +18,10 @@ qcom-camss-objs += \ camss-vfe-4-7.o \ camss-vfe-4-8.o \ camss-vfe-17x.o \ + camss-vfe-340.o \ camss-vfe-480.o \ camss-vfe-680.o \ - camss-vfe-780.o \ + camss-vfe-gen3.o \ camss-vfe-gen1.o \ camss-vfe.o \ camss-video.o \ diff --git a/drivers/media/platform/qcom/camss/camss-csid-340.c b/drivers/media/platform/qcom/camss/camss-csid-340.c new file mode 100644 index 000000000000..22a30510fb79 --- /dev/null +++ b/drivers/media/platform/qcom/camss/camss-csid-340.c @@ -0,0 +1,190 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Qualcomm MSM Camera Subsystem - CSID (CSI Decoder) Module 340 + * + * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include <linux/completion.h> +#include <linux/bitfield.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/kernel.h> + +#include "camss.h" +#include "camss-csid.h" +#include "camss-csid-gen2.h" + +#define CSID_RST_STROBES (0x010) +#define CSID_RST_SW_REGS BIT(0) +#define CSID_RST_IRQ BIT(1) +#define CSID_RST_IFE_CLK BIT(2) +#define CSID_RST_PHY_CLK BIT(3) +#define CSID_RST_CSID_CLK BIT(4) + +#define CSID_IRQ_STATUS (0x070) +#define CSID_IRQ_MASK (0x074) +#define CSID_IRQ_MASK_RST_DONE BIT(0) +#define CSID_IRQ_CLEAR (0x078) +#define CSID_IRQ_CMD (0x080) +#define CSID_IRQ_CMD_CLEAR BIT(0) + +#define CSID_CSI2_RX_CFG0 (0x100) +#define CSI2_RX_CFG0_NUM_ACTIVE_LANES_MASK GENMASK(1, 0) +#define CSI2_RX_CFG0_DLX_INPUT_SEL_MASK GENMASK(17, 4) +#define CSI2_RX_CFG0_PHY_NUM_SEL_MASK GENMASK(21, 20) +#define CSI2_RX_CFG0_PHY_NUM_SEL_BASE_IDX 1 +#define CSI2_RX_CFG0_PHY_TYPE_SEL BIT(24) + +#define CSID_CSI2_RX_CFG1 (0x104) +#define CSI2_RX_CFG1_PACKET_ECC_CORRECTION_EN BIT(0) +#define CSI2_RX_CFG1_MISR_EN BIT(6) +#define CSI2_RX_CFG1_CGC_MODE BIT(7) + +#define CSID_RDI_CFG0(rdi) (0x300 + 0x100 * (rdi)) +#define CSID_RDI_CFG0_BYTE_CNTR_EN BIT(0) +#define CSID_RDI_CFG0_TIMESTAMP_EN BIT(1) +#define CSID_RDI_CFG0_DECODE_FORMAT_MASK GENMASK(15, 12) +#define CSID_RDI_CFG0_DECODE_FORMAT_NOP CSID_RDI_CFG0_DECODE_FORMAT_MASK +#define CSID_RDI_CFG0_DT_MASK GENMASK(21, 16) +#define CSID_RDI_CFG0_VC_MASK GENMASK(23, 22) +#define CSID_RDI_CFG0_DTID_MASK GENMASK(28, 27) +#define CSID_RDI_CFG0_ENABLE BIT(31) + +#define CSID_RDI_CTRL(rdi) (0x308 + 0x100 * (rdi)) +#define CSID_RDI_CTRL_HALT_AT_FRAME_BOUNDARY 0 +#define CSID_RDI_CTRL_RESUME_AT_FRAME_BOUNDARY 1 + +static void __csid_configure_rx(struct csid_device *csid, + struct csid_phy_config *phy, int vc) +{ + u32 val; + + val = FIELD_PREP(CSI2_RX_CFG0_NUM_ACTIVE_LANES_MASK, phy->lane_cnt - 1); + val |= FIELD_PREP(CSI2_RX_CFG0_DLX_INPUT_SEL_MASK, phy->lane_assign); + val |= FIELD_PREP(CSI2_RX_CFG0_PHY_NUM_SEL_MASK, + phy->csiphy_id + CSI2_RX_CFG0_PHY_NUM_SEL_BASE_IDX); + writel_relaxed(val, csid->base + CSID_CSI2_RX_CFG0); + + val = CSI2_RX_CFG1_PACKET_ECC_CORRECTION_EN; + writel_relaxed(val, csid->base + CSID_CSI2_RX_CFG1); +} + +static void __csid_ctrl_rdi(struct csid_device *csid, int enable, u8 rdi) +{ + writel_relaxed(!!enable, csid->base + CSID_RDI_CTRL(rdi)); +} + +static void __csid_configure_rdi_stream(struct csid_device *csid, u8 enable, u8 vc) +{ + struct v4l2_mbus_framefmt *input_format = &csid->fmt[MSM_CSID_PAD_FIRST_SRC + vc]; + const struct csid_format_info *format = csid_get_fmt_entry(csid->res->formats->formats, + csid->res->formats->nformats, + input_format->code); + u8 lane_cnt = csid->phy.lane_cnt; + u8 dt_id; + u32 val; + + if (!lane_cnt) + lane_cnt = 4; + + /* + * DT_ID is a two bit bitfield that is concatenated with + * the four least significant bits of the five bit VC + * bitfield to generate an internal CID value. + * + * CSID_RDI_CFG0(vc) + * DT_ID : 28:27 + * VC : 26:22 + * DT : 21:16 + * + * CID : VC 3:0 << 2 | DT_ID 1:0 + */ + dt_id = vc & 0x03; + + val = CSID_RDI_CFG0_DECODE_FORMAT_NOP; /* only for RDI path */ + val |= FIELD_PREP(CSID_RDI_CFG0_DT_MASK, format->data_type); + val |= FIELD_PREP(CSID_RDI_CFG0_VC_MASK, vc); + val |= FIELD_PREP(CSID_RDI_CFG0_DTID_MASK, dt_id); + + if (enable) + val |= CSID_RDI_CFG0_ENABLE; + + dev_dbg(csid->camss->dev, "CSID%u: Stream %s (dt:0x%x vc=%u)\n", + csid->id, enable ? "enable" : "disable", format->data_type, vc); + + writel_relaxed(val, csid->base + CSID_RDI_CFG0(vc)); +} + +static void csid_configure_stream(struct csid_device *csid, u8 enable) +{ + int i; + + for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS; i++) { + if (csid->phy.en_vc & BIT(i)) { + __csid_configure_rdi_stream(csid, enable, i); + __csid_configure_rx(csid, &csid->phy, i); + __csid_ctrl_rdi(csid, enable, i); + } + } +} + +static int csid_reset(struct csid_device *csid) +{ + unsigned long time; + + writel_relaxed(CSID_IRQ_MASK_RST_DONE, csid->base + CSID_IRQ_MASK); + writel_relaxed(CSID_IRQ_MASK_RST_DONE, csid->base + CSID_IRQ_CLEAR); + writel_relaxed(CSID_IRQ_CMD_CLEAR, csid->base + CSID_IRQ_CMD); + + reinit_completion(&csid->reset_complete); + + /* Reset with registers preserved */ + writel(CSID_RST_IRQ | CSID_RST_IFE_CLK | CSID_RST_PHY_CLK | CSID_RST_CSID_CLK, + csid->base + CSID_RST_STROBES); + + time = wait_for_completion_timeout(&csid->reset_complete, + msecs_to_jiffies(CSID_RESET_TIMEOUT_MS)); + if (!time) { + dev_err(csid->camss->dev, "CSID%u: reset timeout\n", csid->id); + return -EIO; + } + + dev_dbg(csid->camss->dev, "CSID%u: reset done\n", csid->id); + + return 0; +} + +static irqreturn_t csid_isr(int irq, void *dev) +{ + struct csid_device *csid = dev; + u32 val; + + val = readl_relaxed(csid->base + CSID_IRQ_STATUS); + writel_relaxed(val, csid->base + CSID_IRQ_CLEAR); + writel_relaxed(CSID_IRQ_CMD_CLEAR, csid->base + CSID_IRQ_CMD); + + if (val & CSID_IRQ_MASK_RST_DONE) + complete(&csid->reset_complete); + else + dev_warn_ratelimited(csid->camss->dev, "Spurious CSID interrupt\n"); + + return IRQ_HANDLED; +} + +static int csid_configure_testgen_pattern(struct csid_device *csid, s32 val) +{ + return -EOPNOTSUPP; /* Not part of CSID */ +} + +static void csid_subdev_init(struct csid_device *csid) {} + +const struct csid_hw_ops csid_ops_340 = { + .configure_testgen_pattern = csid_configure_testgen_pattern, + .configure_stream = csid_configure_stream, + .hw_version = csid_hw_version, + .isr = csid_isr, + .reset = csid_reset, + .src_pad_code = csid_src_pad_code, + .subdev_init = csid_subdev_init, +}; diff --git a/drivers/media/platform/qcom/camss/camss-csid-780.c b/drivers/media/platform/qcom/camss/camss-csid-gen3.c index 4c720d177731..664245cf6eb0 100644 --- a/drivers/media/platform/qcom/camss/camss-csid-780.c +++ b/drivers/media/platform/qcom/camss/camss-csid-gen3.c @@ -13,7 +13,7 @@ #include "camss.h" #include "camss-csid.h" -#include "camss-csid-780.h" +#include "camss-csid-gen3.h" #define CSID_IO_PATH_CFG0(csid) (0x4 * (csid)) #define OUTPUT_IFE_EN 0x100 @@ -45,8 +45,12 @@ #define CSID_CSI2_RX_IRQ_CLEAR 0xA4 #define CSID_CSI2_RX_IRQ_SET 0xA8 +#define IS_CSID_690(csid) ((csid->camss->res->version == CAMSS_8775P) \ + || (csid->camss->res->version == CAMSS_8300)) #define CSID_BUF_DONE_IRQ_STATUS 0x8C -#define BUF_DONE_IRQ_STATUS_RDI_OFFSET (csid_is_lite(csid) ? 1 : 14) +#define BUF_DONE_IRQ_STATUS_RDI_OFFSET (csid_is_lite(csid) ?\ + 1 : (IS_CSID_690(csid) ?\ + 13 : 14)) #define CSID_BUF_DONE_IRQ_MASK 0x90 #define CSID_BUF_DONE_IRQ_CLEAR 0x94 #define CSID_BUF_DONE_IRQ_SET 0x98 @@ -59,6 +63,7 @@ #define CSID_CSI2_RX_CFG0 0x200 #define CSI2_RX_CFG0_NUM_ACTIVE_LANES 0 +#define CSI2_RX_CFG0_VC_MODE 3 #define CSI2_RX_CFG0_DL0_INPUT_SEL 4 #define CSI2_RX_CFG0_PHY_NUM_SEL 20 @@ -66,7 +71,9 @@ #define CSI2_RX_CFG1_ECC_CORRECTION_EN BIT(0) #define CSI2_RX_CFG1_VC_MODE BIT(2) -#define CSID_RDI_CFG0(rdi) (0x500 + 0x100 * (rdi)) +#define CSID_RDI_CFG0(rdi) (csid_is_lite(csid) && IS_CSID_690(csid) ?\ + (0x300 + 0x100 * (rdi)) :\ + (0x500 + 0x100 * (rdi))) #define RDI_CFG0_TIMESTAMP_EN BIT(6) #define RDI_CFG0_TIMESTAMP_STB_SEL BIT(8) #define RDI_CFG0_DECODE_FORMAT 12 @@ -75,10 +82,14 @@ #define RDI_CFG0_DT_ID 27 #define RDI_CFG0_EN BIT(31) -#define CSID_RDI_CTRL(rdi) (0x504 + 0x100 * (rdi)) +#define CSID_RDI_CTRL(rdi) (csid_is_lite(csid) && IS_CSID_690(csid) ?\ + (0x304 + 0x100 * (rdi)) :\ + (0x504 + 0x100 * (rdi))) #define RDI_CTRL_START_CMD BIT(0) -#define CSID_RDI_CFG1(rdi) (0x510 + 0x100 * (rdi)) +#define CSID_RDI_CFG1(rdi) (csid_is_lite(csid) && IS_CSID_690(csid) ?\ + (0x310 + 0x100 * (rdi)) :\ + (0x510 + 0x100 * (rdi))) #define RDI_CFG1_DROP_H_EN BIT(5) #define RDI_CFG1_DROP_V_EN BIT(6) #define RDI_CFG1_CROP_H_EN BIT(7) @@ -86,9 +97,12 @@ #define RDI_CFG1_PIX_STORE BIT(10) #define RDI_CFG1_PACKING_FORMAT_MIPI BIT(15) -#define CSID_RDI_IRQ_SUBSAMPLE_PATTERN(rdi) (0x548 + 0x100 * (rdi)) -#define CSID_RDI_IRQ_SUBSAMPLE_PERIOD(rdi) (0x54C + 0x100 * (rdi)) - +#define CSID_RDI_IRQ_SUBSAMPLE_PATTERN(rdi) (csid_is_lite(csid) && IS_CSID_690(csid) ?\ + (0x348 + 0x100 * (rdi)) :\ + (0x548 + 0x100 * (rdi))) +#define CSID_RDI_IRQ_SUBSAMPLE_PERIOD(rdi) (csid_is_lite(csid) && IS_CSID_690(csid) ?\ + (0x34C + 0x100 * (rdi)) :\ + (0x54C + 0x100 * (rdi))) #define CSI2_RX_CFG0_PHY_SEL_BASE_IDX 1 static void __csid_configure_rx(struct csid_device *csid, @@ -259,7 +273,7 @@ static irqreturn_t csid_isr(int irq, void *dev) if (buf_done_val & BIT(BUF_DONE_IRQ_STATUS_RDI_OFFSET + i)) { /* - * For Titan 780, bus done and RUP IRQ have been moved to + * For Titan Gen3, bus done and RUP IRQ have been moved to * CSID from VFE. Once CSID received bus done, need notify * VFE of this event. Trigger VFE to handle bus done process. */ @@ -325,7 +339,7 @@ static void csid_subdev_init(struct csid_device *csid) csid->testgen.nmodes = CSID_PAYLOAD_MODE_DISABLED; } -const struct csid_hw_ops csid_ops_780 = { +const struct csid_hw_ops csid_ops_gen3 = { .configure_stream = csid_configure_stream, .configure_testgen_pattern = csid_configure_testgen_pattern, .hw_version = csid_hw_version, diff --git a/drivers/media/platform/qcom/camss/camss-csid-780.h b/drivers/media/platform/qcom/camss/camss-csid-gen3.h index a990c66a60ff..6ee62da770c1 100644 --- a/drivers/media/platform/qcom/camss/camss-csid-780.h +++ b/drivers/media/platform/qcom/camss/camss-csid-gen3.h @@ -1,13 +1,13 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* - * camss-csid-780.h + * camss-csid-gen3.h * * Qualcomm MSM Camera Subsystem - CSID (CSI Decoder) Module Generation 3 * * Copyright (c) 2024 Qualcomm Technologies, Inc. */ -#ifndef __QC_MSM_CAMSS_CSID_780_H__ -#define __QC_MSM_CAMSS_CSID_780_H__ +#ifndef __QC_MSM_CAMSS_CSID_GEN3_H__ +#define __QC_MSM_CAMSS_CSID_GEN3_H__ #define DECODE_FORMAT_UNCOMPRESSED_8_BIT 0x1 #define DECODE_FORMAT_UNCOMPRESSED_10_BIT 0x2 @@ -22,4 +22,4 @@ #define PLAIN_FORMAT_PLAIN16 0x1 /* supports DPCM, UNCOMPRESSED_10/16_BIT */ #define PLAIN_FORMAT_PLAIN32 0x2 /* supports UNCOMPRESSED_20_BIT */ -#endif /* __QC_MSM_CAMSS_CSID_780_H__ */ +#endif /* __QC_MSM_CAMSS_CSID_GEN3_H__ */ diff --git a/drivers/media/platform/qcom/camss/camss-csid.h b/drivers/media/platform/qcom/camss/camss-csid.h index 9dc826d8c8f6..aedc96ed84b2 100644 --- a/drivers/media/platform/qcom/camss/camss-csid.h +++ b/drivers/media/platform/qcom/camss/camss-csid.h @@ -213,9 +213,10 @@ extern const struct csid_formats csid_formats_gen2; extern const struct csid_hw_ops csid_ops_4_1; extern const struct csid_hw_ops csid_ops_4_7; +extern const struct csid_hw_ops csid_ops_340; extern const struct csid_hw_ops csid_ops_680; extern const struct csid_hw_ops csid_ops_gen2; -extern const struct csid_hw_ops csid_ops_780; +extern const struct csid_hw_ops csid_ops_gen3; /* * csid_is_lite - Check if CSID is CSID lite. diff --git a/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c b/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c index 88c0ba495c32..a229ba04b158 100644 --- a/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c +++ b/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c @@ -64,6 +64,85 @@ struct csiphy_lane_regs { u32 csiphy_param_type; }; +/* 5nm 2PH v 1.3.0 2p5Gbps 4 lane DPHY mode */ +static const struct +csiphy_lane_regs lane_regs_sa8775p[] = { + {0x0724, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0728, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0700, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x070C, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0738, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x072C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0734, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0710, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x071C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0714, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x073C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0704, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0720, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0708, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0024, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0000, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x002C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0034, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0010, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x001C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0014, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x003C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0004, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0020, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0008, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0224, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0200, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x022C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0234, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0210, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x021C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0214, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x023C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0204, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0220, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0208, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0424, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0400, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x042C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0434, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0410, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x041C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0414, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x043C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0404, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0420, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0408, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0624, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0600, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0638, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x062C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0634, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0610, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x061C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0614, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x063C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0604, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0620, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0608, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x005C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0060, 0xFD, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0064, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x025C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0260, 0xFD, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0264, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x045C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0460, 0xFD, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0464, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x065C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0660, 0xFD, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0664, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, +}; + /* GEN2 1.0 2PH */ static const struct csiphy_lane_regs lane_regs_sdm845[] = { @@ -319,6 +398,90 @@ csiphy_lane_regs lane_regs_sm8250[] = { {0x0884, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, }; +/* 14nm 2PH v 2.0.1 2p5Gbps 4 lane DPHY mode */ +static const struct +csiphy_lane_regs lane_regs_qcm2290[] = { + {0x0030, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x002c, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0034, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0028, 0x04, 0x00, CSIPHY_DNP_PARAMS}, + {0x003c, 0xb8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x001c, 0x0a, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0000, 0xd7, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0004, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0020, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0008, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x000c, 0xff, 0x00, CSIPHY_DNP_PARAMS}, + {0x0010, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0038, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0060, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0064, 0x3f, 0x00, CSIPHY_DEFAULT_PARAMS}, + + {0x0730, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x072c, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0734, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0728, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x073c, 0xb8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x071c, 0x0a, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0700, 0xc0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0704, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0720, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0708, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x070c, 0xff, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0710, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0738, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0760, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0764, 0x3f, 0x00, CSIPHY_DEFAULT_PARAMS}, + + {0x0230, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x022c, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0234, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0228, 0x04, 0x00, CSIPHY_DNP_PARAMS}, + {0x023c, 0xb8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x021c, 0x0a, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0200, 0xd7, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0204, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0220, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0208, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x020c, 0xff, 0x00, CSIPHY_DNP_PARAMS}, + {0x0210, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0238, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0260, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0264, 0x3f, 0x00, CSIPHY_DEFAULT_PARAMS}, + + {0x0430, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x042c, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0434, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0428, 0x04, 0x00, CSIPHY_DNP_PARAMS}, + {0x043c, 0xb8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x041c, 0x0a, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0400, 0xd7, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0404, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0420, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0408, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x040C, 0xff, 0x00, CSIPHY_DNP_PARAMS}, + {0x0410, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0438, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0460, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0464, 0x3f, 0x00, CSIPHY_DEFAULT_PARAMS}, + + {0x0630, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x062c, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0634, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0628, 0x04, 0x00, CSIPHY_DNP_PARAMS}, + {0x063c, 0xb8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x061c, 0x0a, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0600, 0xd7, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0604, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0620, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0608, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x060C, 0xff, 0x00, CSIPHY_DNP_PARAMS}, + {0x0610, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0638, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0660, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0664, 0x3f, 0x00, CSIPHY_DEFAULT_PARAMS}, +}; + /* GEN2 2.1.2 2PH DPHY mode */ static const struct csiphy_lane_regs lane_regs_sm8550[] = { @@ -744,11 +907,14 @@ static bool csiphy_is_gen2(u32 version) bool ret = false; switch (version) { + case CAMSS_2290: case CAMSS_7280: case CAMSS_8250: case CAMSS_8280XP: + case CAMSS_8300: case CAMSS_845: case CAMSS_8550: + case CAMSS_8775P: case CAMSS_X1E80100: ret = true; break; @@ -829,6 +995,10 @@ static int csiphy_init(struct csiphy_device *csiphy) regs->lane_regs = &lane_regs_sdm845[0]; regs->lane_array_size = ARRAY_SIZE(lane_regs_sdm845); break; + case CAMSS_2290: + regs->lane_regs = &lane_regs_qcm2290[0]; + regs->lane_array_size = ARRAY_SIZE(lane_regs_qcm2290); + break; case CAMSS_7280: case CAMSS_8250: regs->lane_regs = &lane_regs_sm8250[0]; @@ -848,6 +1018,11 @@ static int csiphy_init(struct csiphy_device *csiphy) regs->lane_array_size = ARRAY_SIZE(lane_regs_sm8550); regs->offset = 0x1000; break; + case CAMSS_8300: + case CAMSS_8775P: + regs->lane_regs = &lane_regs_sa8775p[0]; + regs->lane_array_size = ARRAY_SIZE(lane_regs_sa8775p); + break; default: break; } diff --git a/drivers/media/platform/qcom/camss/camss-vfe-340.c b/drivers/media/platform/qcom/camss/camss-vfe-340.c new file mode 100644 index 000000000000..30d7630b3e8b --- /dev/null +++ b/drivers/media/platform/qcom/camss/camss-vfe-340.c @@ -0,0 +1,320 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Qualcomm MSM Camera Subsystem - VFE (Video Front End) Module 340 (TFE) + * + * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include <linux/delay.h> +#include <linux/bitfield.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/iopoll.h> + +#include "camss.h" +#include "camss-vfe.h" + +#define TFE_GLOBAL_RESET_CMD (0x014) +#define TFE_GLOBAL_RESET_CMD_CORE BIT(0) + +#define TFE_REG_UPDATE_CMD (0x02c) + +#define TFE_IRQ_CMD (0x030) +#define TFE_IRQ_CMD_CLEAR BIT(0) +#define TFE_IRQ_MASK_0 (0x034) +#define TFE_IRQ_MASK_0_RST_DONE BIT(0) +#define TFE_IRQ_MASK_0_BUS_WR BIT(1) +#define TFE_IRQ_MASK_1 (0x038) +#define TFE_IRQ_MASK_2 (0x03c) +#define TFE_IRQ_CLEAR_0 (0x040) + +#define TFE_IRQ_STATUS_0 (0x04c) + +#define BUS_REG(a) (0xa00 + (a)) + +#define TFE_BUS_IRQ_MASK_0 BUS_REG(0x18) +#define TFE_BUS_IRQ_MASK_RUP_DONE_MASK GENMASK(3, 0) +#define TFE_BUS_IRQ_MASK_RUP_DONE(sc) FIELD_PREP(TFE_BUS_IRQ_MASK_RUP_DONE_MASK, BIT(sc)) +#define TFE_BUS_IRQ_MASK_BUF_DONE_MASK GENMASK(15, 8) +#define TFE_BUS_IRQ_MASK_BUF_DONE(sg) FIELD_PREP(TFE_BUS_IRQ_MASK_BUF_DONE_MASK, BIT(sg)) +#define TFE_BUS_IRQ_MASK_0_CONS_VIOL BIT(28) +#define TFE_BUS_IRQ_MASK_0_VIOL BIT(30) +#define TFE_BUS_IRQ_MASK_0_IMG_VIOL BIT(31) + +#define TFE_BUS_IRQ_MASK_1 BUS_REG(0x1c) +#define TFE_BUS_IRQ_CLEAR_0 BUS_REG(0x20) +#define TFE_BUS_IRQ_STATUS_0 BUS_REG(0x28) +#define TFE_BUS_IRQ_CMD BUS_REG(0x30) +#define TFE_BUS_IRQ_CMD_CLEAR BIT(0) + +#define TFE_BUS_STATUS_CLEAR BUS_REG(0x60) +#define TFE_BUS_VIOLATION_STATUS BUS_REG(0x64) +#define TFE_BUS_OVERFLOW_STATUS BUS_REG(0x68) +#define TFE_BUS_IMAGE_SZ_VIOLATION_STATUS BUS_REG(0x70) + +#define TFE_BUS_CLIENT_CFG(c) BUS_REG(0x200 + (c) * 0x100) +#define TFE_BUS_CLIENT_CFG_EN BIT(0) +#define TFE_BUS_CLIENT_CFG_MODE_FRAME BIT(16) +#define TFE_BUS_IMAGE_ADDR(c) BUS_REG(0x204 + (c) * 0x100) +#define TFE_BUS_FRAME_INCR(c) BUS_REG(0x208 + (c) * 0x100) +#define TFE_BUS_IMAGE_CFG_0(c) BUS_REG(0x20c + (c) * 0x100) +#define TFE_BUS_IMAGE_CFG_0_DEFAULT 0xffff +#define TFE_BUS_IMAGE_CFG_1(c) BUS_REG(0x210 + (c) * 0x100) +#define TFE_BUS_IMAGE_CFG_2(c) BUS_REG(0x214 + (c) * 0x100) +#define TFE_BUS_IMAGE_CFG_2_DEFAULT 0xffff +#define TFE_BUS_PACKER_CFG(c) BUS_REG(0x218 + (c) * 0x100) +#define TFE_BUS_PACKER_CFG_FMT_PLAIN64 0xa +#define TFE_BUS_IRQ_SUBSAMPLE_CFG_0(c) BUS_REG(0x230 + (c) * 0x100) +#define TFE_BUS_IRQ_SUBSAMPLE_CFG_1(c) BUS_REG(0x234 + (c) * 0x100) +#define TFE_BUS_FRAMEDROP_CFG_0(c) BUS_REG(0x238 + (c) * 0x100) +#define TFE_BUS_FRAMEDROP_CFG_1(c) BUS_REG(0x23c + (c) * 0x100) + +/* + * TODO: differentiate the port id based on requested type of RDI, BHIST etc + * + * TFE write master IDs (clients) + * + * BAYER 0 + * IDEAL_RAW 1 + * STATS_TINTLESS_BG 2 + * STATS_BHIST 3 + * STATS_AWB_BG 4 + * STATS_AEC_BG 5 + * STATS_BAF 6 + * RDI0 7 + * RDI1 8 + * RDI2 9 + */ +#define RDI_WM(n) (7 + (n)) +#define TFE_WM_NUM 10 + +enum tfe_iface { + TFE_IFACE_PIX, + TFE_IFACE_RDI0, + TFE_IFACE_RDI1, + TFE_IFACE_RDI2, + TFE_IFACE_NUM +}; + +enum tfe_subgroups { + TFE_SUBGROUP_BAYER, + TFE_SUBGROUP_IDEAL_RAW, + TFE_SUBGROUP_HDR, + TFE_SUBGROUP_BG, + TFE_SUBGROUP_BAF, + TFE_SUBGROUP_RDI0, + TFE_SUBGROUP_RDI1, + TFE_SUBGROUP_RDI2, + TFE_SUBGROUP_NUM +}; + +static enum tfe_iface tfe_line_iface_map[VFE_LINE_NUM_MAX] = { + [VFE_LINE_RDI0] = TFE_IFACE_RDI0, + [VFE_LINE_RDI1] = TFE_IFACE_RDI1, + [VFE_LINE_RDI2] = TFE_IFACE_RDI2, + [VFE_LINE_PIX] = TFE_IFACE_PIX, +}; + +static enum vfe_line_id tfe_subgroup_line_map[TFE_SUBGROUP_NUM] = { + [TFE_SUBGROUP_BAYER] = VFE_LINE_PIX, + [TFE_SUBGROUP_IDEAL_RAW] = VFE_LINE_PIX, + [TFE_SUBGROUP_HDR] = VFE_LINE_PIX, + [TFE_SUBGROUP_BG] = VFE_LINE_PIX, + [TFE_SUBGROUP_BAF] = VFE_LINE_PIX, + [TFE_SUBGROUP_RDI0] = VFE_LINE_RDI0, + [TFE_SUBGROUP_RDI1] = VFE_LINE_RDI1, + [TFE_SUBGROUP_RDI2] = VFE_LINE_RDI2, +}; + +static inline enum tfe_iface __line_to_iface(enum vfe_line_id line_id) +{ + if (line_id <= VFE_LINE_NONE || line_id >= VFE_LINE_NUM_MAX) { + pr_warn("VFE: Invalid line %d\n", line_id); + return TFE_IFACE_RDI0; + } + + return tfe_line_iface_map[line_id]; +} + +static inline enum vfe_line_id __iface_to_line(unsigned int iface) +{ + int i; + + for (i = 0; i < VFE_LINE_NUM_MAX; i++) { + if (tfe_line_iface_map[i] == iface) + return i; + } + + return VFE_LINE_NONE; +} + +static inline enum vfe_line_id __subgroup_to_line(enum tfe_subgroups sg) +{ + if (sg >= TFE_SUBGROUP_NUM) + return VFE_LINE_NONE; + + return tfe_subgroup_line_map[sg]; +} + +static void vfe_global_reset(struct vfe_device *vfe) +{ + writel(TFE_IRQ_MASK_0_RST_DONE, vfe->base + TFE_IRQ_MASK_0); + writel(TFE_GLOBAL_RESET_CMD_CORE, vfe->base + TFE_GLOBAL_RESET_CMD); +} + +static irqreturn_t vfe_isr(int irq, void *dev) +{ + struct vfe_device *vfe = dev; + u32 status; + int i; + + status = readl_relaxed(vfe->base + TFE_IRQ_STATUS_0); + writel_relaxed(status, vfe->base + TFE_IRQ_CLEAR_0); + writel_relaxed(TFE_IRQ_CMD_CLEAR, vfe->base + TFE_IRQ_CMD); + + if (status & TFE_IRQ_MASK_0_RST_DONE) { + dev_dbg(vfe->camss->dev, "VFE%u: Reset done!", vfe->id); + vfe_isr_reset_ack(vfe); + } + + if (status & TFE_IRQ_MASK_0_BUS_WR) { + u32 bus_status = readl_relaxed(vfe->base + TFE_BUS_IRQ_STATUS_0); + + writel_relaxed(bus_status, vfe->base + TFE_BUS_IRQ_CLEAR_0); + writel_relaxed(TFE_BUS_IRQ_CMD_CLEAR, vfe->base + TFE_BUS_IRQ_CMD); + + for (i = 0; i < TFE_IFACE_NUM; i++) { + if (bus_status & TFE_BUS_IRQ_MASK_RUP_DONE(i)) + vfe->res->hw_ops->reg_update_clear(vfe, __iface_to_line(i)); + } + + for (i = 0; i < TFE_SUBGROUP_NUM; i++) { + if (bus_status & TFE_BUS_IRQ_MASK_BUF_DONE(i)) + vfe_buf_done(vfe, __subgroup_to_line(i)); + } + + if (bus_status & TFE_BUS_IRQ_MASK_0_CONS_VIOL) + dev_err_ratelimited(vfe->camss->dev, "VFE%u: Bad config violation", + vfe->id); + + if (bus_status & TFE_BUS_IRQ_MASK_0_VIOL) + dev_err_ratelimited(vfe->camss->dev, "VFE%u: Input data violation", + vfe->id); + + if (bus_status & TFE_BUS_IRQ_MASK_0_IMG_VIOL) + dev_err_ratelimited(vfe->camss->dev, "VFE%u: Image size violation", + vfe->id); + } + + status = readl_relaxed(vfe->base + TFE_BUS_OVERFLOW_STATUS); + if (status) { + writel_relaxed(status, vfe->base + TFE_BUS_STATUS_CLEAR); + for (i = 0; i < TFE_WM_NUM; i++) { + if (status & BIT(i)) + dev_err_ratelimited(vfe->camss->dev, + "VFE%u: bus overflow for wm %u\n", + vfe->id, i); + } + } + + return IRQ_HANDLED; +} + +static int vfe_halt(struct vfe_device *vfe) +{ + /* rely on vfe_disable_output() to stop the VFE */ + return 0; +} + +static void vfe_enable_irq(struct vfe_device *vfe) +{ + writel(TFE_IRQ_MASK_0_RST_DONE | TFE_IRQ_MASK_0_BUS_WR, + vfe->base + TFE_IRQ_MASK_0); + writel(TFE_BUS_IRQ_MASK_RUP_DONE_MASK | TFE_BUS_IRQ_MASK_BUF_DONE_MASK | + TFE_BUS_IRQ_MASK_0_CONS_VIOL | TFE_BUS_IRQ_MASK_0_VIOL | + TFE_BUS_IRQ_MASK_0_IMG_VIOL, vfe->base + TFE_BUS_IRQ_MASK_0); +} + +static void vfe_wm_update(struct vfe_device *vfe, u8 rdi, u32 addr, + struct vfe_line *line) +{ + u8 wm = RDI_WM(rdi); + + writel_relaxed(addr, vfe->base + TFE_BUS_IMAGE_ADDR(wm)); +} + +static void vfe_wm_start(struct vfe_device *vfe, u8 rdi, struct vfe_line *line) +{ + struct v4l2_pix_format_mplane *pix = &line->video_out.active_fmt.fmt.pix_mp; + u32 stride = pix->plane_fmt[0].bytesperline; + u8 wm = RDI_WM(rdi); + + /* Configuration for plain RDI frames */ + writel_relaxed(TFE_BUS_IMAGE_CFG_0_DEFAULT, vfe->base + TFE_BUS_IMAGE_CFG_0(wm)); + writel_relaxed(0u, vfe->base + TFE_BUS_IMAGE_CFG_1(wm)); + writel_relaxed(TFE_BUS_IMAGE_CFG_2_DEFAULT, vfe->base + TFE_BUS_IMAGE_CFG_2(wm)); + writel_relaxed(stride * pix->height, vfe->base + TFE_BUS_FRAME_INCR(wm)); + writel_relaxed(TFE_BUS_PACKER_CFG_FMT_PLAIN64, vfe->base + TFE_BUS_PACKER_CFG(wm)); + + /* No dropped frames, one irq per frame */ + writel_relaxed(0, vfe->base + TFE_BUS_FRAMEDROP_CFG_0(wm)); + writel_relaxed(1, vfe->base + TFE_BUS_FRAMEDROP_CFG_1(wm)); + writel_relaxed(0, vfe->base + TFE_BUS_IRQ_SUBSAMPLE_CFG_0(wm)); + writel_relaxed(1, vfe->base + TFE_BUS_IRQ_SUBSAMPLE_CFG_1(wm)); + + vfe_enable_irq(vfe); + + writel(TFE_BUS_CLIENT_CFG_EN | TFE_BUS_CLIENT_CFG_MODE_FRAME, + vfe->base + TFE_BUS_CLIENT_CFG(wm)); + + dev_dbg(vfe->camss->dev, "VFE%u: Started RDI%u width %u height %u stride %u\n", + vfe->id, rdi, pix->width, pix->height, stride); +} + +static void vfe_wm_stop(struct vfe_device *vfe, u8 rdi) +{ + u8 wm = RDI_WM(rdi); + + writel(0, vfe->base + TFE_BUS_CLIENT_CFG(wm)); + + dev_dbg(vfe->camss->dev, "VFE%u: Stopped RDI%u\n", vfe->id, rdi); +} + +static const struct camss_video_ops vfe_video_ops_520 = { + .queue_buffer = vfe_queue_buffer_v2, + .flush_buffers = vfe_flush_buffers, +}; + +static void vfe_subdev_init(struct device *dev, struct vfe_device *vfe) +{ + vfe->video_ops = vfe_video_ops_520; +} + +static void vfe_reg_update(struct vfe_device *vfe, enum vfe_line_id line_id) +{ + vfe->reg_update |= BIT(__line_to_iface(line_id)); + writel_relaxed(vfe->reg_update, vfe->base + TFE_REG_UPDATE_CMD); +} + +static void vfe_reg_update_clear(struct vfe_device *vfe, enum vfe_line_id line_id) +{ + vfe->reg_update &= ~BIT(__line_to_iface(line_id)); +} + +const struct vfe_hw_ops vfe_ops_340 = { + .global_reset = vfe_global_reset, + .hw_version = vfe_hw_version, + .isr = vfe_isr, + .pm_domain_off = vfe_pm_domain_off, + .pm_domain_on = vfe_pm_domain_on, + .subdev_init = vfe_subdev_init, + .vfe_disable = vfe_disable, + .vfe_enable = vfe_enable_v2, + .vfe_halt = vfe_halt, + .vfe_wm_start = vfe_wm_start, + .vfe_wm_stop = vfe_wm_stop, + .vfe_buf_done = vfe_buf_done, + .vfe_wm_update = vfe_wm_update, + .reg_update = vfe_reg_update, + .reg_update_clear = vfe_reg_update_clear, +}; diff --git a/drivers/media/platform/qcom/camss/camss-vfe-780.c b/drivers/media/platform/qcom/camss/camss-vfe-gen3.c index b9812d70f91b..22579617def7 100644 --- a/drivers/media/platform/qcom/camss/camss-vfe-780.c +++ b/drivers/media/platform/qcom/camss/camss-vfe-gen3.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Qualcomm MSM Camera Subsystem - VFE (Video Front End) Module v780 (SM8550) + * Qualcomm MSM Camera Subsystem - VFE (Video Front End) Module gen3 * * Copyright (c) 2024 Qualcomm Technologies, Inc. */ @@ -12,13 +12,44 @@ #include "camss.h" #include "camss-vfe.h" -#define BUS_REG_BASE (vfe_is_lite(vfe) ? 0x200 : 0xC00) +#define IS_VFE_690(vfe) \ + ((vfe->camss->res->version == CAMSS_8775P) \ + || (vfe->camss->res->version == CAMSS_8300)) + +#define BUS_REG_BASE_690 \ + (vfe_is_lite(vfe) ? 0x480 : 0x400) +#define BUS_REG_BASE_780 \ + (vfe_is_lite(vfe) ? 0x200 : 0xC00) +#define BUS_REG_BASE \ + (IS_VFE_690(vfe) ? BUS_REG_BASE_690 : BUS_REG_BASE_780) + +#define VFE_TOP_CORE_CFG (0x24) +#define VFE_DISABLE_DSCALING_DS4 BIT(21) +#define VFE_DISABLE_DSCALING_DS16 BIT(22) + +#define VFE_BUS_WM_TEST_BUS_CTRL_690 (BUS_REG_BASE + 0xFC) +#define VFE_BUS_WM_TEST_BUS_CTRL_780 (BUS_REG_BASE + 0xDC) +#define VFE_BUS_WM_TEST_BUS_CTRL \ + (IS_VFE_690(vfe) ? VFE_BUS_WM_TEST_BUS_CTRL_690 \ + : VFE_BUS_WM_TEST_BUS_CTRL_780) +/* + * Bus client mapping: + * + * Full VFE: + * VFE_690: 16 = RDI0, 17 = RDI1, 18 = RDI2 + * VFE_780: 23 = RDI0, 24 = RDI1, 25 = RDI2 + * + * VFE LITE: + * VFE_690 : 0 = RDI0, 1 = RDI1, 2 = RDI2, 3 = RDI3, 4 = RDI4, 5 = RDI5 + * VFE_780 : 0 = RDI0, 1 = RDI1, 2 = RDI2, 3 = RDI3, 4 = RDI4 + */ +#define RDI_WM_690(n) ((vfe_is_lite(vfe) ? 0x0 : 0x10) + (n)) +#define RDI_WM_780(n) ((vfe_is_lite(vfe) ? 0x0 : 0x17) + (n)) +#define RDI_WM(n) (IS_VFE_690(vfe) ? RDI_WM_690(n) : RDI_WM_780(n)) #define VFE_BUS_WM_CGC_OVERRIDE (BUS_REG_BASE + 0x08) #define WM_CGC_OVERRIDE_ALL (0x7FFFFFF) -#define VFE_BUS_WM_TEST_BUS_CTRL (BUS_REG_BASE + 0xDC) - #define VFE_BUS_WM_CFG(n) (BUS_REG_BASE + 0x200 + (n) * 0x100) #define WM_CFG_EN BIT(0) #define WM_VIR_FRM_EN BIT(1) @@ -39,17 +70,6 @@ #define VFE_BUS_WM_MMU_PREFETCH_CFG(n) (BUS_REG_BASE + 0x260 + (n) * 0x100) #define VFE_BUS_WM_MMU_PREFETCH_MAX_OFFSET(n) (BUS_REG_BASE + 0x264 + (n) * 0x100) -/* - * Bus client mapping: - * - * Full VFE: - * 23 = RDI0, 24 = RDI1, 25 = RDI2 - * - * VFE LITE: - * 0 = RDI0, 1 = RDI1, 2 = RDI3, 4 = RDI4 - */ -#define RDI_WM(n) ((vfe_is_lite(vfe) ? 0x0 : 0x17) + (n)) - static void vfe_wm_start(struct vfe_device *vfe, u8 wm, struct vfe_line *line) { struct v4l2_pix_format_mplane *pix = @@ -62,14 +82,24 @@ static void vfe_wm_start(struct vfe_device *vfe, u8 wm, struct vfe_line *line) writel(0x0, vfe->base + VFE_BUS_WM_TEST_BUS_CTRL); - writel(ALIGN(pix->plane_fmt[0].bytesperline, 16) * pix->height >> 8, - vfe->base + VFE_BUS_WM_FRAME_INCR(wm)); + if (IS_VFE_690(vfe)) + writel(ALIGN(pix->plane_fmt[0].bytesperline, 16) * pix->height, + vfe->base + VFE_BUS_WM_FRAME_INCR(wm)); + else + writel(ALIGN(pix->plane_fmt[0].bytesperline, 16) * pix->height >> 8, + vfe->base + VFE_BUS_WM_FRAME_INCR(wm)); + writel((WM_IMAGE_CFG_0_DEFAULT_WIDTH & 0xFFFF), vfe->base + VFE_BUS_WM_IMAGE_CFG_0(wm)); writel(WM_IMAGE_CFG_2_DEFAULT_STRIDE, vfe->base + VFE_BUS_WM_IMAGE_CFG_2(wm)); writel(0, vfe->base + VFE_BUS_WM_PACKER_CFG(wm)); + /* TOP CORE CFG */ + if (IS_VFE_690(vfe)) + writel(VFE_DISABLE_DSCALING_DS4 | VFE_DISABLE_DSCALING_DS16, + vfe->base + VFE_TOP_CORE_CFG); + /* no dropped frames, one irq per frame */ writel(0, vfe->base + VFE_BUS_WM_FRAMEDROP_PERIOD(wm)); writel(1, vfe->base + VFE_BUS_WM_FRAMEDROP_PATTERN(wm)); @@ -92,7 +122,11 @@ static void vfe_wm_update(struct vfe_device *vfe, u8 wm, u32 addr, struct vfe_line *line) { wm = RDI_WM(wm); - writel((addr >> 8) & 0xFFFFFFFF, vfe->base + VFE_BUS_WM_IMAGE_ADDR(wm)); + + if (IS_VFE_690(vfe)) + writel(addr, vfe->base + VFE_BUS_WM_IMAGE_ADDR(wm)); + else + writel((addr >> 8), vfe->base + VFE_BUS_WM_IMAGE_ADDR(wm)); dev_dbg(vfe->camss->dev, "wm:%d, image buf addr:0x%x\n", wm, addr); @@ -113,14 +147,14 @@ static inline void vfe_reg_update_clear(struct vfe_device *vfe, camss_reg_update(vfe->camss, vfe->id, port_id, true); } -static const struct camss_video_ops vfe_video_ops_780 = { +static const struct camss_video_ops vfe_video_ops_gen3 = { .queue_buffer = vfe_queue_buffer_v2, .flush_buffers = vfe_flush_buffers, }; static void vfe_subdev_init(struct device *dev, struct vfe_device *vfe) { - vfe->video_ops = vfe_video_ops_780; + vfe->video_ops = vfe_video_ops_gen3; } static void vfe_global_reset(struct vfe_device *vfe) @@ -140,7 +174,7 @@ static int vfe_halt(struct vfe_device *vfe) return 0; } -const struct vfe_hw_ops vfe_ops_780 = { +const struct vfe_hw_ops vfe_ops_gen3 = { .global_reset = vfe_global_reset, .hw_version = vfe_hw_version, .isr = vfe_isr, diff --git a/drivers/media/platform/qcom/camss/camss-vfe.c b/drivers/media/platform/qcom/camss/camss-vfe.c index 4bca6c3abaff..dff8d0a1e8c2 100644 --- a/drivers/media/platform/qcom/camss/camss-vfe.c +++ b/drivers/media/platform/qcom/camss/camss-vfe.c @@ -340,12 +340,15 @@ static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code, } break; case CAMSS_660: + case CAMSS_2290: case CAMSS_7280: case CAMSS_8x96: case CAMSS_8250: case CAMSS_8280XP: + case CAMSS_8300: case CAMSS_845: case CAMSS_8550: + case CAMSS_8775P: case CAMSS_X1E80100: switch (sink_code) { case MEDIA_BUS_FMT_YUYV8_1X16: @@ -910,7 +913,24 @@ static int vfe_match_clock_names(struct vfe_device *vfe, return (!strcmp(clock->name, vfe_name) || !strcmp(clock->name, vfe_lite_name) || - !strcmp(clock->name, "vfe_lite")); + !strcmp(clock->name, "vfe_lite") || + !strcmp(clock->name, "camnoc_axi")); +} + +/* + * vfe_check_clock_levels - Calculate and set clock rates on VFE module + * @clock: clocks data + * + * Return false if there is no non-zero clock level and true otherwise. + */ +static bool vfe_check_clock_levels(struct camss_clock *clock) +{ + int i; + + for (i = 0; i < clock->nfreqs; i++) + if (clock->freq[i]) + return true; + return false; } /* @@ -936,7 +956,7 @@ static int vfe_set_clock_rates(struct vfe_device *vfe) for (i = 0; i < vfe->nclocks; i++) { struct camss_clock *clock = &vfe->clock[i]; - if (vfe_match_clock_names(vfe, clock)) { + if (vfe_match_clock_names(vfe, clock) && vfe_check_clock_levels(clock)) { u64 min_rate = 0; long rate; @@ -1017,7 +1037,7 @@ static int vfe_check_clock_rates(struct vfe_device *vfe) for (i = 0; i < vfe->nclocks; i++) { struct camss_clock *clock = &vfe->clock[i]; - if (vfe_match_clock_names(vfe, clock)) { + if (vfe_match_clock_names(vfe, clock) && vfe_check_clock_levels(clock)) { u64 min_rate = 0; unsigned long rate; @@ -1972,8 +1992,10 @@ static int vfe_bpl_align(struct vfe_device *vfe) case CAMSS_7280: case CAMSS_8250: case CAMSS_8280XP: + case CAMSS_8300: case CAMSS_845: case CAMSS_8550: + case CAMSS_8775P: case CAMSS_X1E80100: ret = 16; break; diff --git a/drivers/media/platform/qcom/camss/camss-vfe.h b/drivers/media/platform/qcom/camss/camss-vfe.h index a23f666be753..0300efdb1c46 100644 --- a/drivers/media/platform/qcom/camss/camss-vfe.h +++ b/drivers/media/platform/qcom/camss/camss-vfe.h @@ -242,9 +242,10 @@ extern const struct vfe_hw_ops vfe_ops_4_1; extern const struct vfe_hw_ops vfe_ops_4_7; extern const struct vfe_hw_ops vfe_ops_4_8; extern const struct vfe_hw_ops vfe_ops_170; +extern const struct vfe_hw_ops vfe_ops_340; extern const struct vfe_hw_ops vfe_ops_480; extern const struct vfe_hw_ops vfe_ops_680; -extern const struct vfe_hw_ops vfe_ops_780; +extern const struct vfe_hw_ops vfe_ops_gen3; int vfe_get(struct vfe_device *vfe); void vfe_put(struct vfe_device *vfe); diff --git a/drivers/media/platform/qcom/camss/camss-video.c b/drivers/media/platform/qcom/camss/camss-video.c index 8d05802d1735..831486e14754 100644 --- a/drivers/media/platform/qcom/camss/camss-video.c +++ b/drivers/media/platform/qcom/camss/camss-video.c @@ -604,50 +604,11 @@ static const struct v4l2_ioctl_ops msm_vid_ioctl_ops = { * V4L2 file operations */ -static int video_open(struct file *file) -{ - struct video_device *vdev = video_devdata(file); - struct camss_video *video = video_drvdata(file); - struct v4l2_fh *vfh; - int ret; - - mutex_lock(&video->lock); - - vfh = kzalloc(sizeof(*vfh), GFP_KERNEL); - if (vfh == NULL) { - ret = -ENOMEM; - goto error_alloc; - } - - v4l2_fh_init(vfh, vdev); - v4l2_fh_add(vfh); - - file->private_data = vfh; - - mutex_unlock(&video->lock); - - return 0; - -error_alloc: - mutex_unlock(&video->lock); - - return ret; -} - -static int video_release(struct file *file) -{ - vb2_fop_release(file); - - file->private_data = NULL; - - return 0; -} - static const struct v4l2_file_operations msm_vid_fops = { .owner = THIS_MODULE, .unlocked_ioctl = video_ioctl2, - .open = video_open, - .release = video_release, + .open = v4l2_fh_open, + .release = vb2_fop_release, .poll = vb2_fop_poll, .mmap = vb2_fop_mmap, .read = vb2_fop_read, diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index e08e70b93824..2fbcd0e343aa 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -515,6 +515,140 @@ static const struct camss_subdev_resources vfe_res_8x96[] = { } }; +static const struct camss_subdev_resources csiphy_res_2290[] = { + /* CSIPHY0 */ + { + .regulators = { "vdd-csiphy-1p2", "vdd-csiphy-1p8" }, + .clock = { "top_ahb", "ahb", "csiphy0", "csiphy0_timer" }, + .clock_rate = { { 0 }, + { 0 }, + { 240000000, 341330000, 384000000 }, + { 100000000, 200000000, 268800000 } }, + .reg = { "csiphy0" }, + .interrupt = { "csiphy0" }, + .csiphy = { + .id = 0, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, + + /* CSIPHY1 */ + { + .regulators = { "vdd-csiphy-1p2", "vdd-csiphy-1p8" }, + .clock = { "top_ahb", "ahb", "csiphy1", "csiphy1_timer" }, + .clock_rate = { { 0 }, + { 0 }, + { 240000000, 341330000, 384000000 }, + { 100000000, 200000000, 268800000 } }, + .reg = { "csiphy1" }, + .interrupt = { "csiphy1" }, + .csiphy = { + .id = 1, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + } +}; + +static const struct camss_subdev_resources csid_res_2290[] = { + /* CSID0 */ + { + .regulators = {}, + .clock = { "top_ahb", "ahb", "csi0", "vfe0_cphy_rx", "vfe0" }, + .clock_rate = { { 0 }, + { 0 }, + { 192000000, 240000000, 384000000, 426400000 }, + { 0 }, + { 0 } }, + .reg = { "csid0" }, + .interrupt = { "csid0" }, + .csid = { + .hw_ops = &csid_ops_340, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_gen2 + } + }, + + /* CSID1 */ + { + .regulators = {}, + .clock = { "top_ahb", "ahb", "csi1", "vfe1_cphy_rx", "vfe1" }, + .clock_rate = { { 0 }, + { 0 }, + { 192000000, 240000000, 384000000, 426400000 }, + { 0 }, + { 0 } }, + .reg = { "csid1" }, + .interrupt = { "csid1" }, + .csid = { + .hw_ops = &csid_ops_340, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_gen2 + } + } +}; + +static const struct camss_subdev_resources vfe_res_2290[] = { + /* VFE0 */ + { + .regulators = {}, + .clock = { "top_ahb", "ahb", "axi", "vfe0", "camnoc_rt_axi", "camnoc_nrt_axi" }, + .clock_rate = { { 0 }, + { 0 }, + { 0 }, + { 19200000, 153600000, 192000000, 256000000, 384000000, 460800000 }, + { 0 }, + { 0 }, }, + .reg = { "vfe0" }, + .interrupt = { "vfe0" }, + .vfe = { + .line_num = 4, + .hw_ops = &vfe_ops_340, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + + /* VFE1 */ + { + .regulators = {}, + .clock = { "top_ahb", "ahb", "axi", "vfe1", "camnoc_rt_axi", "camnoc_nrt_axi" }, + .clock_rate = { { 0 }, + { 0 }, + { 0 }, + { 19200000, 153600000, 192000000, 256000000, 384000000, 460800000 }, + { 0 }, + { 0 }, }, + .reg = { "vfe1" }, + .interrupt = { "vfe1" }, + .vfe = { + .line_num = 4, + .hw_ops = &vfe_ops_340, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, +}; + +static const struct resources_icc icc_res_2290[] = { + { + .name = "ahb", + .icc_bw_tbl.avg = 150000, + .icc_bw_tbl.peak = 300000, + }, + { + .name = "hf_mnoc", + .icc_bw_tbl.avg = 2097152, + .icc_bw_tbl.peak = 3000000, + }, + { + .name = "sf_mnoc", + .icc_bw_tbl.avg = 2097152, + .icc_bw_tbl.peak = 3000000, + }, +}; + static const struct camss_subdev_resources csiphy_res_660[] = { /* CSIPHY0 */ { @@ -2285,7 +2419,7 @@ static const struct camss_subdev_resources csid_res_8550[] = { .csid = { .is_lite = false, .parent_dev_ops = &vfe_parent_dev_ops, - .hw_ops = &csid_ops_780, + .hw_ops = &csid_ops_gen3, .formats = &csid_formats_gen2 } }, @@ -2300,7 +2434,7 @@ static const struct camss_subdev_resources csid_res_8550[] = { .csid = { .is_lite = false, .parent_dev_ops = &vfe_parent_dev_ops, - .hw_ops = &csid_ops_780, + .hw_ops = &csid_ops_gen3, .formats = &csid_formats_gen2 } }, @@ -2315,7 +2449,7 @@ static const struct camss_subdev_resources csid_res_8550[] = { .csid = { .is_lite = false, .parent_dev_ops = &vfe_parent_dev_ops, - .hw_ops = &csid_ops_780, + .hw_ops = &csid_ops_gen3, .formats = &csid_formats_gen2 } }, @@ -2330,7 +2464,7 @@ static const struct camss_subdev_resources csid_res_8550[] = { .csid = { .is_lite = true, .parent_dev_ops = &vfe_parent_dev_ops, - .hw_ops = &csid_ops_780, + .hw_ops = &csid_ops_gen3, .formats = &csid_formats_gen2 } }, @@ -2345,7 +2479,7 @@ static const struct camss_subdev_resources csid_res_8550[] = { .csid = { .is_lite = true, .parent_dev_ops = &vfe_parent_dev_ops, - .hw_ops = &csid_ops_780, + .hw_ops = &csid_ops_gen3, .formats = &csid_formats_gen2 } } @@ -2371,7 +2505,7 @@ static const struct camss_subdev_resources vfe_res_8550[] = { .is_lite = false, .has_pd = true, .pd_name = "ife0", - .hw_ops = &vfe_ops_780, + .hw_ops = &vfe_ops_gen3, .formats_rdi = &vfe_formats_rdi_845, .formats_pix = &vfe_formats_pix_845 } @@ -2395,7 +2529,7 @@ static const struct camss_subdev_resources vfe_res_8550[] = { .is_lite = false, .has_pd = true, .pd_name = "ife1", - .hw_ops = &vfe_ops_780, + .hw_ops = &vfe_ops_gen3, .formats_rdi = &vfe_formats_rdi_845, .formats_pix = &vfe_formats_pix_845 } @@ -2419,7 +2553,7 @@ static const struct camss_subdev_resources vfe_res_8550[] = { .is_lite = false, .has_pd = true, .pd_name = "ife2", - .hw_ops = &vfe_ops_780, + .hw_ops = &vfe_ops_gen3, .formats_rdi = &vfe_formats_rdi_845, .formats_pix = &vfe_formats_pix_845 } @@ -2441,7 +2575,7 @@ static const struct camss_subdev_resources vfe_res_8550[] = { .vfe = { .line_num = 4, .is_lite = true, - .hw_ops = &vfe_ops_780, + .hw_ops = &vfe_ops_gen3, .formats_rdi = &vfe_formats_rdi_845, .formats_pix = &vfe_formats_pix_845 } @@ -2463,7 +2597,7 @@ static const struct camss_subdev_resources vfe_res_8550[] = { .vfe = { .line_num = 4, .is_lite = true, - .hw_ops = &vfe_ops_780, + .hw_ops = &vfe_ops_gen3, .formats_rdi = &vfe_formats_rdi_845, .formats_pix = &vfe_formats_pix_845 } @@ -2483,6 +2617,467 @@ static const struct resources_icc icc_res_sm8550[] = { }, }; +static const struct camss_subdev_resources csiphy_res_8300[] = { + /* CSIPHY0 */ + { + .regulators = { "vdda-phy", "vdda-pll" }, + + .clock = { "csiphy_rx", "csiphy0", "csiphy0_timer" }, + .clock_rate = { + { 400000000 }, + { 0 }, + { 400000000 }, + }, + .reg = { "csiphy0" }, + .interrupt = { "csiphy0" }, + .csiphy = { + .id = 0, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845, + } + }, + /* CSIPHY1 */ + { + .regulators = { "vdda-phy", "vdda-pll" }, + + .clock = { "csiphy_rx", "csiphy1", "csiphy1_timer" }, + .clock_rate = { + { 400000000 }, + { 0 }, + { 400000000 }, + }, + .reg = { "csiphy1" }, + .interrupt = { "csiphy1" }, + .csiphy = { + .id = 1, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845, + } + }, + /* CSIPHY2 */ + { + .regulators = { "vdda-phy", "vdda-pll" }, + + .clock = { "csiphy_rx", "csiphy2", "csiphy2_timer" }, + .clock_rate = { + { 400000000 }, + { 0 }, + { 400000000 }, + }, + .reg = { "csiphy2" }, + .interrupt = { "csiphy2" }, + .csiphy = { + .id = 2, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845, + } + }, +}; + +static const struct camss_subdev_resources csiphy_res_8775p[] = { + /* CSIPHY0 */ + { + .regulators = { "vdda-phy", "vdda-pll" }, + .clock = { "csiphy_rx", "csiphy0", "csiphy0_timer"}, + .clock_rate = { + { 400000000 }, + { 0 }, + { 400000000 }, + }, + .reg = { "csiphy0" }, + .interrupt = { "csiphy0" }, + .csiphy = { + .id = 0, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, + /* CSIPHY1 */ + { + .regulators = { "vdda-phy", "vdda-pll" }, + .clock = { "csiphy_rx", "csiphy1", "csiphy1_timer"}, + .clock_rate = { + { 400000000 }, + { 0 }, + { 400000000 }, + }, + .reg = { "csiphy1" }, + .interrupt = { "csiphy1" }, + .csiphy = { + .id = 1, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, + /* CSIPHY2 */ + { + .regulators = { "vdda-phy", "vdda-pll" }, + .clock = { "csiphy_rx", "csiphy2", "csiphy2_timer"}, + .clock_rate = { + { 400000000 }, + { 0 }, + { 400000000 }, + }, + .reg = { "csiphy2" }, + .interrupt = { "csiphy2" }, + .csiphy = { + .id = 2, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, + /* CSIPHY3 */ + { + .regulators = { "vdda-phy", "vdda-pll" }, + .clock = { "csiphy_rx", "csiphy3", "csiphy3_timer"}, + .clock_rate = { + { 400000000 }, + { 0 }, + { 400000000 }, + }, + .reg = { "csiphy3" }, + .interrupt = { "csiphy3" }, + .csiphy = { + .id = 3, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, +}; + +static const struct camss_subdev_resources csid_res_8775p[] = { + /* CSID0 */ + { + .regulators = {}, + .clock = { "csid", "csiphy_rx"}, + .clock_rate = { + { 400000000, 400000000}, + { 400000000, 400000000} + }, + .reg = { "csid0" }, + .interrupt = { "csid0" }, + .csid = { + .is_lite = false, + .hw_ops = &csid_ops_gen3, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_gen2 + } + }, + /* CSID1 */ + { + .regulators = {}, + .clock = { "csid", "csiphy_rx"}, + .clock_rate = { + { 400000000, 400000000}, + { 400000000, 400000000} + }, + .reg = { "csid1" }, + .interrupt = { "csid1" }, + .csid = { + .is_lite = false, + .hw_ops = &csid_ops_gen3, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_gen2 + } + }, + + /* CSID2 (lite) */ + { + .regulators = {}, + .clock = { "cpas_vfe_lite", "vfe_lite_ahb", + "vfe_lite_csid", "vfe_lite_cphy_rx", + "vfe_lite"}, + .clock_rate = { + { 0, 0, 400000000, 400000000, 0}, + { 0, 0, 400000000, 480000000, 0} + }, + .reg = { "csid_lite0" }, + .interrupt = { "csid_lite0" }, + .csid = { + .is_lite = true, + .hw_ops = &csid_ops_gen3, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_gen2 + } + }, + /* CSID3 (lite) */ + { + .regulators = {}, + .clock = { "cpas_vfe_lite", "vfe_lite_ahb", + "vfe_lite_csid", "vfe_lite_cphy_rx", + "vfe_lite"}, + .clock_rate = { + { 0, 0, 400000000, 400000000, 0}, + { 0, 0, 400000000, 480000000, 0} + }, + .reg = { "csid_lite1" }, + .interrupt = { "csid_lite1" }, + .csid = { + .is_lite = true, + .hw_ops = &csid_ops_gen3, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_gen2 + } + }, + /* CSID4 (lite) */ + { + .regulators = {}, + .clock = { "cpas_vfe_lite", "vfe_lite_ahb", + "vfe_lite_csid", "vfe_lite_cphy_rx", + "vfe_lite"}, + .clock_rate = { + { 0, 0, 400000000, 400000000, 0}, + { 0, 0, 400000000, 480000000, 0} + }, + .reg = { "csid_lite2" }, + .interrupt = { "csid_lite2" }, + .csid = { + .is_lite = true, + .hw_ops = &csid_ops_gen3, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_gen2 + } + }, + /* CSID5 (lite) */ + { + .regulators = {}, + .clock = { "cpas_vfe_lite", "vfe_lite_ahb", + "vfe_lite_csid", "vfe_lite_cphy_rx", + "vfe_lite"}, + .clock_rate = { + { 0, 0, 400000000, 400000000, 0}, + { 0, 0, 400000000, 480000000, 0} + }, + .reg = { "csid_lite3" }, + .interrupt = { "csid_lite3" }, + .csid = { + .is_lite = true, + .hw_ops = &csid_ops_gen3, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_gen2 + } + }, + /* CSID6 (lite) */ + { + .regulators = {}, + .clock = { "cpas_vfe_lite", "vfe_lite_ahb", + "vfe_lite_csid", "vfe_lite_cphy_rx", + "vfe_lite"}, + .clock_rate = { + { 0, 0, 400000000, 400000000, 0}, + { 0, 0, 400000000, 480000000, 0} + }, + .reg = { "csid_lite4" }, + .interrupt = { "csid_lite4" }, + .csid = { + .is_lite = true, + .hw_ops = &csid_ops_gen3, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_gen2 + } + }, +}; + +static const struct camss_subdev_resources vfe_res_8775p[] = { + /* VFE0 */ + { + .regulators = {}, + .clock = { "cpas_vfe0", "vfe0", "vfe0_fast_ahb", + "cpas_ahb", "gcc_axi_hf", + "cpas_fast_ahb_clk", + "camnoc_axi"}, + .clock_rate = { + { 0 }, + { 480000000 }, + { 300000000, 400000000 }, + { 300000000, 400000000 }, + { 0 }, + { 300000000, 400000000 }, + { 400000000 }, + }, + .reg = { "vfe0" }, + .interrupt = { "vfe0" }, + .vfe = { + .line_num = 3, + .is_lite = false, + .has_pd = false, + .pd_name = NULL, + .hw_ops = &vfe_ops_gen3, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE1 */ + { + .regulators = {}, + .clock = { "cpas_vfe1", "vfe1", "vfe1_fast_ahb", + "cpas_ahb", "gcc_axi_hf", + "cpas_fast_ahb_clk", + "camnoc_axi"}, + .clock_rate = { + { 0 }, + { 480000000 }, + { 300000000, 400000000 }, + { 300000000, 400000000 }, + { 0 }, + { 300000000, 400000000 }, + { 400000000 }, + }, + .reg = { "vfe1" }, + .interrupt = { "vfe1" }, + .vfe = { + .line_num = 3, + .is_lite = false, + .has_pd = false, + .pd_name = NULL, + .hw_ops = &vfe_ops_gen3, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE2 (lite) */ + { + .regulators = {}, + .clock = { "cpas_vfe_lite", "vfe_lite_ahb", + "vfe_lite_csid", "vfe_lite_cphy_rx", + "vfe_lite"}, + .clock_rate = { + { 0, 0, 0, 0 }, + { 300000000, 400000000, 400000000, 400000000 }, + { 400000000, 400000000, 400000000, 400000000 }, + { 400000000, 400000000, 400000000, 400000000 }, + { 480000000, 600000000, 600000000, 600000000 }, + }, + .reg = { "vfe_lite0" }, + .interrupt = { "vfe_lite0" }, + .vfe = { + .line_num = 4, + .is_lite = true, + .hw_ops = &vfe_ops_gen3, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE3 (lite) */ + { + .regulators = {}, + .clock = { "cpas_vfe_lite", "vfe_lite_ahb", + "vfe_lite_csid", "vfe_lite_cphy_rx", + "vfe_lite"}, + .clock_rate = { + { 0, 0, 0, 0 }, + { 300000000, 400000000, 400000000, 400000000 }, + { 400000000, 400000000, 400000000, 400000000 }, + { 400000000, 400000000, 400000000, 400000000 }, + { 480000000, 600000000, 600000000, 600000000 }, + }, + .reg = { "vfe_lite1" }, + .interrupt = { "vfe_lite1" }, + .vfe = { + .line_num = 4, + .is_lite = true, + .hw_ops = &vfe_ops_gen3, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE4 (lite) */ + { + .regulators = {}, + .clock = { "cpas_vfe_lite", "vfe_lite_ahb", + "vfe_lite_csid", "vfe_lite_cphy_rx", + "vfe_lite"}, + .clock_rate = { + { 0, 0, 0, 0 }, + { 300000000, 400000000, 400000000, 400000000 }, + { 400000000, 400000000, 400000000, 400000000 }, + { 400000000, 400000000, 400000000, 400000000 }, + { 480000000, 600000000, 600000000, 600000000 }, + }, + .reg = { "vfe_lite2" }, + .interrupt = { "vfe_lite2" }, + .vfe = { + .line_num = 4, + .is_lite = true, + .hw_ops = &vfe_ops_gen3, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE5 (lite) */ + { + .regulators = {}, + .clock = { "cpas_vfe_lite", "vfe_lite_ahb", + "vfe_lite_csid", "vfe_lite_cphy_rx", + "vfe_lite"}, + .clock_rate = { + { 0, 0, 0, 0 }, + { 300000000, 400000000, 400000000, 400000000 }, + { 400000000, 400000000, 400000000, 400000000 }, + { 400000000, 400000000, 400000000, 400000000 }, + { 480000000, 600000000, 600000000, 600000000 }, + }, + .reg = { "vfe_lite3" }, + .interrupt = { "vfe_lite3" }, + .vfe = { + .line_num = 4, + .is_lite = true, + .hw_ops = &vfe_ops_gen3, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE6 (lite) */ + { + .regulators = {}, + .clock = { "cpas_vfe_lite", "vfe_lite_ahb", + "vfe_lite_csid", "vfe_lite_cphy_rx", + "vfe_lite"}, + .clock_rate = { + { 0, 0, 0, 0 }, + { 300000000, 400000000, 400000000, 400000000 }, + { 400000000, 400000000, 400000000, 400000000 }, + { 400000000, 400000000, 400000000, 400000000 }, + { 480000000, 600000000, 600000000, 600000000 }, + }, + .reg = { "vfe_lite4" }, + .interrupt = { "vfe_lite4" }, + .vfe = { + .line_num = 4, + .is_lite = true, + .hw_ops = &vfe_ops_gen3, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, +}; + +static const struct resources_icc icc_res_qcs8300[] = { + { + .name = "ahb", + .icc_bw_tbl.avg = 38400, + .icc_bw_tbl.peak = 76800, + }, + { + .name = "hf_0", + .icc_bw_tbl.avg = 2097152, + .icc_bw_tbl.peak = 2097152, + }, +}; + +static const struct resources_icc icc_res_sa8775p[] = { + { + .name = "ahb", + .icc_bw_tbl.avg = 38400, + .icc_bw_tbl.peak = 76800, + }, + { + .name = "hf_0", + .icc_bw_tbl.avg = 2097152, + .icc_bw_tbl.peak = 2097152, + }, +}; + static const struct camss_subdev_resources csiphy_res_x1e80100[] = { /* CSIPHY0 */ { @@ -3041,9 +3636,6 @@ static int camss_of_parse_ports(struct camss *camss) for_each_endpoint_of_node(dev->of_node, node) { struct camss_async_subdev *csd; - if (!of_device_is_available(node)) - continue; - remote = of_graph_get_remote_port_parent(node); if (!remote) { dev_err(dev, "Cannot get remote parent\n"); @@ -3143,7 +3735,6 @@ static int camss_init_subdevices(struct camss *camss) } /* - * camss_link_entities - Register subdev nodes and create links * camss_link_err - print error in case link creation fails * @src_name: name for source of the link * @sink_name: name for sink of the link @@ -3557,7 +4148,6 @@ static int camss_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct camss *camss; - int num_subdevs; int ret; camss = devm_kzalloc(dev, sizeof(*camss), GFP_KERNEL); @@ -3628,17 +4218,15 @@ static int camss_probe(struct platform_device *pdev) pm_runtime_enable(dev); - num_subdevs = camss_of_parse_ports(camss); - if (num_subdevs < 0) { - ret = num_subdevs; + ret = camss_of_parse_ports(camss); + if (ret < 0) goto err_v4l2_device_unregister; - } ret = camss_register_entities(camss); if (ret < 0) goto err_v4l2_device_unregister; - ret = camss->res->link_entities(camss); + ret = camss_link_entities(camss); if (ret < 0) goto err_register_subdevs; @@ -3648,23 +4236,12 @@ static int camss_probe(struct platform_device *pdev) goto err_register_subdevs; } - if (num_subdevs) { - camss->notifier.ops = &camss_subdev_notifier_ops; - - ret = v4l2_async_nf_register(&camss->notifier); - if (ret) { - dev_err(dev, - "Failed to register async subdev nodes: %d\n", - ret); - goto err_media_device_unregister; - } - } else { - ret = v4l2_device_register_subdev_nodes(&camss->v4l2_dev); - if (ret < 0) { - dev_err(dev, "Failed to register subdev nodes: %d\n", - ret); - goto err_media_device_unregister; - } + camss->notifier.ops = &camss_subdev_notifier_ops; + ret = v4l2_async_nf_register(&camss->notifier); + if (ret) { + dev_err(dev, + "Failed to register async subdev nodes: %d\n", ret); + goto err_media_device_unregister; } return 0; @@ -3723,7 +4300,6 @@ static const struct camss_resources msm8916_resources = { .csiphy_num = ARRAY_SIZE(csiphy_res_8x16), .csid_num = ARRAY_SIZE(csid_res_8x16), .vfe_num = ARRAY_SIZE(vfe_res_8x16), - .link_entities = camss_link_entities }; static const struct camss_resources msm8953_resources = { @@ -3737,7 +4313,6 @@ static const struct camss_resources msm8953_resources = { .csiphy_num = ARRAY_SIZE(csiphy_res_8x96), .csid_num = ARRAY_SIZE(csid_res_8x53), .vfe_num = ARRAY_SIZE(vfe_res_8x53), - .link_entities = camss_link_entities }; static const struct camss_resources msm8996_resources = { @@ -3749,7 +4324,46 @@ static const struct camss_resources msm8996_resources = { .csiphy_num = ARRAY_SIZE(csiphy_res_8x96), .csid_num = ARRAY_SIZE(csid_res_8x96), .vfe_num = ARRAY_SIZE(vfe_res_8x96), - .link_entities = camss_link_entities +}; + +static const struct camss_resources qcm2290_resources = { + .version = CAMSS_2290, + .csiphy_res = csiphy_res_2290, + .csid_res = csid_res_2290, + .vfe_res = vfe_res_2290, + .icc_res = icc_res_2290, + .icc_path_num = ARRAY_SIZE(icc_res_2290), + .csiphy_num = ARRAY_SIZE(csiphy_res_2290), + .csid_num = ARRAY_SIZE(csid_res_2290), + .vfe_num = ARRAY_SIZE(vfe_res_2290), +}; + +static const struct camss_resources qcs8300_resources = { + .version = CAMSS_8300, + .pd_name = "top", + .csiphy_res = csiphy_res_8300, + .csid_res = csid_res_8775p, + .csid_wrapper_res = &csid_wrapper_res_sm8550, + .vfe_res = vfe_res_8775p, + .icc_res = icc_res_qcs8300, + .csiphy_num = ARRAY_SIZE(csiphy_res_8300), + .csid_num = ARRAY_SIZE(csid_res_8775p), + .vfe_num = ARRAY_SIZE(vfe_res_8775p), + .icc_path_num = ARRAY_SIZE(icc_res_qcs8300), +}; + +static const struct camss_resources sa8775p_resources = { + .version = CAMSS_8775P, + .pd_name = "top", + .csiphy_res = csiphy_res_8775p, + .csid_res = csid_res_8775p, + .csid_wrapper_res = &csid_wrapper_res_sm8550, + .vfe_res = vfe_res_8775p, + .icc_res = icc_res_sa8775p, + .csiphy_num = ARRAY_SIZE(csiphy_res_8775p), + .csid_num = ARRAY_SIZE(csid_res_8775p), + .vfe_num = ARRAY_SIZE(vfe_res_8775p), + .icc_path_num = ARRAY_SIZE(icc_res_sa8775p), }; static const struct camss_resources sdm660_resources = { @@ -3761,7 +4375,6 @@ static const struct camss_resources sdm660_resources = { .csiphy_num = ARRAY_SIZE(csiphy_res_660), .csid_num = ARRAY_SIZE(csid_res_660), .vfe_num = ARRAY_SIZE(vfe_res_660), - .link_entities = camss_link_entities }; static const struct camss_resources sdm670_resources = { @@ -3772,7 +4385,6 @@ static const struct camss_resources sdm670_resources = { .csiphy_num = ARRAY_SIZE(csiphy_res_670), .csid_num = ARRAY_SIZE(csid_res_670), .vfe_num = ARRAY_SIZE(vfe_res_670), - .link_entities = camss_link_entities }; static const struct camss_resources sdm845_resources = { @@ -3784,7 +4396,6 @@ static const struct camss_resources sdm845_resources = { .csiphy_num = ARRAY_SIZE(csiphy_res_845), .csid_num = ARRAY_SIZE(csid_res_845), .vfe_num = ARRAY_SIZE(vfe_res_845), - .link_entities = camss_link_entities }; static const struct camss_resources sm8250_resources = { @@ -3798,7 +4409,6 @@ static const struct camss_resources sm8250_resources = { .csiphy_num = ARRAY_SIZE(csiphy_res_8250), .csid_num = ARRAY_SIZE(csid_res_8250), .vfe_num = ARRAY_SIZE(vfe_res_8250), - .link_entities = camss_link_entities }; static const struct camss_resources sc8280xp_resources = { @@ -3813,7 +4423,6 @@ static const struct camss_resources sc8280xp_resources = { .csiphy_num = ARRAY_SIZE(csiphy_res_sc8280xp), .csid_num = ARRAY_SIZE(csid_res_sc8280xp), .vfe_num = ARRAY_SIZE(vfe_res_sc8280xp), - .link_entities = camss_link_entities }; static const struct camss_resources sc7280_resources = { @@ -3827,7 +4436,6 @@ static const struct camss_resources sc7280_resources = { .csiphy_num = ARRAY_SIZE(csiphy_res_7280), .csid_num = ARRAY_SIZE(csid_res_7280), .vfe_num = ARRAY_SIZE(vfe_res_7280), - .link_entities = camss_link_entities }; static const struct camss_resources sm8550_resources = { @@ -3842,7 +4450,6 @@ static const struct camss_resources sm8550_resources = { .csiphy_num = ARRAY_SIZE(csiphy_res_8550), .csid_num = ARRAY_SIZE(csid_res_8550), .vfe_num = ARRAY_SIZE(vfe_res_8550), - .link_entities = camss_link_entities }; static const struct camss_resources x1e80100_resources = { @@ -3857,13 +4464,15 @@ static const struct camss_resources x1e80100_resources = { .csiphy_num = ARRAY_SIZE(csiphy_res_x1e80100), .csid_num = ARRAY_SIZE(csid_res_x1e80100), .vfe_num = ARRAY_SIZE(vfe_res_x1e80100), - .link_entities = camss_link_entities }; static const struct of_device_id camss_dt_match[] = { { .compatible = "qcom,msm8916-camss", .data = &msm8916_resources }, { .compatible = "qcom,msm8953-camss", .data = &msm8953_resources }, { .compatible = "qcom,msm8996-camss", .data = &msm8996_resources }, + { .compatible = "qcom,qcm2290-camss", .data = &qcm2290_resources }, + { .compatible = "qcom,qcs8300-camss", .data = &qcs8300_resources }, + { .compatible = "qcom,sa8775p-camss", .data = &sa8775p_resources }, { .compatible = "qcom,sc7280-camss", .data = &sc7280_resources }, { .compatible = "qcom,sc8280xp-camss", .data = &sc8280xp_resources }, { .compatible = "qcom,sdm660-camss", .data = &sdm660_resources }, diff --git a/drivers/media/platform/qcom/camss/camss.h b/drivers/media/platform/qcom/camss/camss.h index 63c0afee154a..a70fbc78ccc3 100644 --- a/drivers/media/platform/qcom/camss/camss.h +++ b/drivers/media/platform/qcom/camss/camss.h @@ -78,14 +78,17 @@ enum pm_domain { enum camss_version { CAMSS_660, + CAMSS_2290, CAMSS_7280, CAMSS_8x16, CAMSS_8x53, CAMSS_8x96, CAMSS_8250, CAMSS_8280XP, + CAMSS_8300, CAMSS_845, CAMSS_8550, + CAMSS_8775P, CAMSS_X1E80100, }; @@ -107,7 +110,6 @@ struct camss_resources { const unsigned int csiphy_num; const unsigned int csid_num; const unsigned int vfe_num; - int (*link_entities)(struct camss *camss); }; struct camss { diff --git a/drivers/media/platform/qcom/iris/Makefile b/drivers/media/platform/qcom/iris/Makefile index e86d00ee6f15..13270cd6d899 100644 --- a/drivers/media/platform/qcom/iris/Makefile +++ b/drivers/media/platform/qcom/iris/Makefile @@ -1,5 +1,5 @@ -qcom-iris-objs += \ - iris_buffer.o \ +qcom-iris-objs += iris_buffer.o \ + iris_common.o \ iris_core.o \ iris_ctrls.o \ iris_firmware.o \ @@ -19,6 +19,7 @@ qcom-iris-objs += \ iris_vidc.o \ iris_vb2.o \ iris_vdec.o \ + iris_venc.o \ iris_vpu2.o \ iris_vpu3x.o \ iris_vpu_buffer.o \ diff --git a/drivers/media/platform/qcom/iris/iris_buffer.c b/drivers/media/platform/qcom/iris/iris_buffer.c index 6425e4919e3b..c0900038e7de 100644 --- a/drivers/media/platform/qcom/iris/iris_buffer.c +++ b/drivers/media/platform/qcom/iris/iris_buffer.c @@ -63,7 +63,12 @@ static u32 iris_yuv_buffer_size_nv12(struct iris_inst *inst) { u32 y_plane, uv_plane, y_stride, uv_stride, y_scanlines, uv_scanlines; - struct v4l2_format *f = inst->fmt_dst; + struct v4l2_format *f; + + if (inst->domain == DECODER) + f = inst->fmt_dst; + else + f = inst->fmt_src; y_stride = ALIGN(f->fmt.pix_mp.width, Y_STRIDE_ALIGN); uv_stride = ALIGN(f->fmt.pix_mp.width, UV_STRIDE_ALIGN); @@ -194,7 +199,7 @@ static u32 iris_yuv_buffer_size_qc08c(struct iris_inst *inst) return ALIGN(y_meta_plane + y_plane + uv_meta_plane + uv_plane, PIXELS_4K); } -static u32 iris_bitstream_buffer_size(struct iris_inst *inst) +static u32 iris_dec_bitstream_buffer_size(struct iris_inst *inst) { struct platform_inst_caps *caps = inst->core->iris_platform_data->inst_caps; u32 base_res_mbs = NUM_MBS_4K; @@ -219,18 +224,58 @@ static u32 iris_bitstream_buffer_size(struct iris_inst *inst) return ALIGN(frame_size, PIXELS_4K); } +static u32 iris_enc_bitstream_buffer_size(struct iris_inst *inst) +{ + u32 aligned_width, aligned_height, bitstream_size, yuv_size; + int bitrate_mode, frame_rc; + struct v4l2_format *f; + + f = inst->fmt_dst; + + bitrate_mode = inst->fw_caps[BITRATE_MODE].value; + frame_rc = inst->fw_caps[FRAME_RC_ENABLE].value; + + aligned_width = ALIGN(f->fmt.pix_mp.width, 32); + aligned_height = ALIGN(f->fmt.pix_mp.height, 32); + bitstream_size = aligned_width * aligned_height * 3; + yuv_size = (aligned_width * aligned_height * 3) >> 1; + if (aligned_width * aligned_height > (4096 * 2176)) + /* bitstream_size = 0.25 * yuv_size; */ + bitstream_size = (bitstream_size >> 3); + else if (aligned_width * aligned_height > (1280 * 720)) + /* bitstream_size = 0.5 * yuv_size; */ + bitstream_size = (bitstream_size >> 2); + + if ((!frame_rc || bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ) && + bitstream_size < yuv_size) + bitstream_size = (bitstream_size << 1); + + return ALIGN(bitstream_size, 4096); +} + int iris_get_buffer_size(struct iris_inst *inst, enum iris_buffer_type buffer_type) { - switch (buffer_type) { - case BUF_INPUT: - return iris_bitstream_buffer_size(inst); - case BUF_OUTPUT: - return iris_yuv_buffer_size_nv12(inst); - case BUF_DPB: - return iris_yuv_buffer_size_qc08c(inst); - default: - return 0; + if (inst->domain == DECODER) { + switch (buffer_type) { + case BUF_INPUT: + return iris_dec_bitstream_buffer_size(inst); + case BUF_OUTPUT: + return iris_yuv_buffer_size_nv12(inst); + case BUF_DPB: + return iris_yuv_buffer_size_qc08c(inst); + default: + return 0; + } + } else { + switch (buffer_type) { + case BUF_INPUT: + return iris_yuv_buffer_size_nv12(inst); + case BUF_OUTPUT: + return iris_enc_bitstream_buffer_size(inst); + default: + return 0; + } } } @@ -239,7 +284,7 @@ static void iris_fill_internal_buf_info(struct iris_inst *inst, { struct iris_buffers *buffers = &inst->buffers[buffer_type]; - buffers->size = iris_vpu_buf_size(inst, buffer_type); + buffers->size = inst->core->iris_platform_data->get_vpu_buffer_size(inst, buffer_type); buffers->min_count = iris_vpu_buf_count(inst, buffer_type); } @@ -249,16 +294,30 @@ void iris_get_internal_buffers(struct iris_inst *inst, u32 plane) const u32 *internal_buf_type; u32 internal_buffer_count, i; - if (V4L2_TYPE_IS_OUTPUT(plane)) { - internal_buf_type = platform_data->dec_ip_int_buf_tbl; - internal_buffer_count = platform_data->dec_ip_int_buf_tbl_size; - for (i = 0; i < internal_buffer_count; i++) - iris_fill_internal_buf_info(inst, internal_buf_type[i]); + if (inst->domain == DECODER) { + if (V4L2_TYPE_IS_OUTPUT(plane)) { + internal_buf_type = platform_data->dec_ip_int_buf_tbl; + internal_buffer_count = platform_data->dec_ip_int_buf_tbl_size; + for (i = 0; i < internal_buffer_count; i++) + iris_fill_internal_buf_info(inst, internal_buf_type[i]); + } else { + internal_buf_type = platform_data->dec_op_int_buf_tbl; + internal_buffer_count = platform_data->dec_op_int_buf_tbl_size; + for (i = 0; i < internal_buffer_count; i++) + iris_fill_internal_buf_info(inst, internal_buf_type[i]); + } } else { - internal_buf_type = platform_data->dec_op_int_buf_tbl; - internal_buffer_count = platform_data->dec_op_int_buf_tbl_size; - for (i = 0; i < internal_buffer_count; i++) - iris_fill_internal_buf_info(inst, internal_buf_type[i]); + if (V4L2_TYPE_IS_OUTPUT(plane)) { + internal_buf_type = platform_data->enc_ip_int_buf_tbl; + internal_buffer_count = platform_data->enc_ip_int_buf_tbl_size; + for (i = 0; i < internal_buffer_count; i++) + iris_fill_internal_buf_info(inst, internal_buf_type[i]); + } else { + internal_buf_type = platform_data->enc_op_int_buf_tbl; + internal_buffer_count = platform_data->enc_op_int_buf_tbl_size; + for (i = 0; i < internal_buffer_count; i++) + iris_fill_internal_buf_info(inst, internal_buf_type[i]); + } } } @@ -299,12 +358,22 @@ int iris_create_internal_buffers(struct iris_inst *inst, u32 plane) const u32 *internal_buf_type; int ret; - if (V4L2_TYPE_IS_OUTPUT(plane)) { - internal_buf_type = platform_data->dec_ip_int_buf_tbl; - internal_buffer_count = platform_data->dec_ip_int_buf_tbl_size; + if (inst->domain == DECODER) { + if (V4L2_TYPE_IS_OUTPUT(plane)) { + internal_buf_type = platform_data->dec_ip_int_buf_tbl; + internal_buffer_count = platform_data->dec_ip_int_buf_tbl_size; + } else { + internal_buf_type = platform_data->dec_op_int_buf_tbl; + internal_buffer_count = platform_data->dec_op_int_buf_tbl_size; + } } else { - internal_buf_type = platform_data->dec_op_int_buf_tbl; - internal_buffer_count = platform_data->dec_op_int_buf_tbl_size; + if (V4L2_TYPE_IS_OUTPUT(plane)) { + internal_buf_type = platform_data->enc_ip_int_buf_tbl; + internal_buffer_count = platform_data->enc_ip_int_buf_tbl_size; + } else { + internal_buf_type = platform_data->enc_op_int_buf_tbl; + internal_buffer_count = platform_data->enc_op_int_buf_tbl_size; + } } for (i = 0; i < internal_buffer_count; i++) { @@ -334,6 +403,29 @@ int iris_queue_buffer(struct iris_inst *inst, struct iris_buffer *buf) return 0; } +int iris_queue_internal_deferred_buffers(struct iris_inst *inst, enum iris_buffer_type buffer_type) +{ + struct iris_buffer *buffer, *next; + struct iris_buffers *buffers; + int ret = 0; + + buffers = &inst->buffers[buffer_type]; + list_for_each_entry_safe(buffer, next, &buffers->list, list) { + if (buffer->attr & BUF_ATTR_PENDING_RELEASE) + continue; + if (buffer->attr & BUF_ATTR_QUEUED) + continue; + + if (buffer->attr & BUF_ATTR_DEFERRED) { + ret = iris_queue_buffer(inst, buffer); + if (ret) + return ret; + } + } + + return ret; +} + int iris_queue_internal_buffers(struct iris_inst *inst, u32 plane) { const struct iris_platform_data *platform_data = inst->core->iris_platform_data; @@ -343,12 +435,22 @@ int iris_queue_internal_buffers(struct iris_inst *inst, u32 plane) u32 internal_buffer_count, i; int ret; - if (V4L2_TYPE_IS_OUTPUT(plane)) { - internal_buf_type = platform_data->dec_ip_int_buf_tbl; - internal_buffer_count = platform_data->dec_ip_int_buf_tbl_size; + if (inst->domain == DECODER) { + if (V4L2_TYPE_IS_OUTPUT(plane)) { + internal_buf_type = platform_data->dec_ip_int_buf_tbl; + internal_buffer_count = platform_data->dec_ip_int_buf_tbl_size; + } else { + internal_buf_type = platform_data->dec_op_int_buf_tbl; + internal_buffer_count = platform_data->dec_op_int_buf_tbl_size; + } } else { - internal_buf_type = platform_data->dec_op_int_buf_tbl; - internal_buffer_count = platform_data->dec_op_int_buf_tbl_size; + if (V4L2_TYPE_IS_OUTPUT(plane)) { + internal_buf_type = platform_data->enc_ip_int_buf_tbl; + internal_buffer_count = platform_data->enc_ip_int_buf_tbl_size; + } else { + internal_buf_type = platform_data->enc_op_int_buf_tbl; + internal_buffer_count = platform_data->enc_op_int_buf_tbl_size; + } } for (i = 0; i < internal_buffer_count; i++) { @@ -358,6 +460,10 @@ int iris_queue_internal_buffers(struct iris_inst *inst, u32 plane) continue; if (buffer->attr & BUF_ATTR_QUEUED) continue; + if (buffer->type == BUF_DPB && inst->state != IRIS_INST_STREAMING) { + buffer->attr |= BUF_ATTR_DEFERRED; + continue; + } ret = iris_queue_buffer(inst, buffer); if (ret) return ret; @@ -388,12 +494,22 @@ static int iris_destroy_internal_buffers(struct iris_inst *inst, u32 plane, bool u32 i, len; int ret; - if (V4L2_TYPE_IS_OUTPUT(plane)) { - internal_buf_type = platform_data->dec_ip_int_buf_tbl; - len = platform_data->dec_ip_int_buf_tbl_size; + if (inst->domain == DECODER) { + if (V4L2_TYPE_IS_OUTPUT(plane)) { + internal_buf_type = platform_data->dec_ip_int_buf_tbl; + len = platform_data->dec_ip_int_buf_tbl_size; + } else { + internal_buf_type = platform_data->dec_op_int_buf_tbl; + len = platform_data->dec_op_int_buf_tbl_size; + } } else { - internal_buf_type = platform_data->dec_op_int_buf_tbl; - len = platform_data->dec_op_int_buf_tbl_size; + if (V4L2_TYPE_IS_OUTPUT(plane)) { + internal_buf_type = platform_data->enc_ip_int_buf_tbl; + len = platform_data->enc_ip_int_buf_tbl_size; + } else { + internal_buf_type = platform_data->enc_op_int_buf_tbl; + len = platform_data->enc_op_int_buf_tbl_size; + } } for (i = 0; i < len; i++) { @@ -413,6 +529,19 @@ static int iris_destroy_internal_buffers(struct iris_inst *inst, u32 plane, bool } } + if (force) { + if (inst->domain == DECODER) + buffers = &inst->buffers[BUF_PERSIST]; + else + buffers = &inst->buffers[BUF_ARP]; + + list_for_each_entry_safe(buf, next, &buffers->list, list) { + ret = iris_destroy_internal_buffer(inst, buf); + if (ret) + return ret; + } + } + return 0; } @@ -455,8 +584,13 @@ static int iris_release_input_internal_buffers(struct iris_inst *inst) u32 internal_buffer_count, i; int ret; - internal_buf_type = platform_data->dec_ip_int_buf_tbl; - internal_buffer_count = platform_data->dec_ip_int_buf_tbl_size; + if (inst->domain == DECODER) { + internal_buf_type = platform_data->dec_ip_int_buf_tbl; + internal_buffer_count = platform_data->dec_ip_int_buf_tbl_size; + } else { + internal_buf_type = platform_data->enc_ip_int_buf_tbl; + internal_buffer_count = platform_data->enc_ip_int_buf_tbl_size; + } for (i = 0; i < internal_buffer_count; i++) { ret = iris_release_internal_buffers(inst, internal_buf_type[i]); @@ -467,9 +601,9 @@ static int iris_release_input_internal_buffers(struct iris_inst *inst) return 0; } -int iris_alloc_and_queue_persist_bufs(struct iris_inst *inst) +int iris_alloc_and_queue_persist_bufs(struct iris_inst *inst, enum iris_buffer_type buffer_type) { - struct iris_buffers *buffers = &inst->buffers[BUF_PERSIST]; + struct iris_buffers *buffers = &inst->buffers[buffer_type]; struct iris_buffer *buffer, *next; int ret; u32 i; @@ -477,10 +611,10 @@ int iris_alloc_and_queue_persist_bufs(struct iris_inst *inst) if (!list_empty(&buffers->list)) return 0; - iris_fill_internal_buf_info(inst, BUF_PERSIST); + iris_fill_internal_buf_info(inst, buffer_type); for (i = 0; i < buffers->min_count; i++) { - ret = iris_create_internal_buffer(inst, BUF_PERSIST, i); + ret = iris_create_internal_buffer(inst, buffer_type, i); if (ret) return ret; } @@ -614,6 +748,8 @@ int iris_vb2_buffer_done(struct iris_inst *inst, struct iris_buffer *buf) vb2 = &vbuf->vb2_buf; + vbuf->flags |= buf->flags; + if (buf->flags & V4L2_BUF_FLAG_ERROR) { state = VB2_BUF_STATE_ERROR; vb2_set_plane_payload(vb2, 0, 0); @@ -622,8 +758,6 @@ int iris_vb2_buffer_done(struct iris_inst *inst, struct iris_buffer *buf) return 0; } - vbuf->flags |= buf->flags; - if (V4L2_TYPE_IS_CAPTURE(type)) { vb2_set_plane_payload(vb2, 0, buf->data_size); vbuf->sequence = inst->sequence_cap++; diff --git a/drivers/media/platform/qcom/iris/iris_buffer.h b/drivers/media/platform/qcom/iris/iris_buffer.h index 00825ad2dc3a..325d30fce5c9 100644 --- a/drivers/media/platform/qcom/iris/iris_buffer.h +++ b/drivers/media/platform/qcom/iris/iris_buffer.h @@ -25,6 +25,8 @@ struct iris_inst; * @BUF_DPB: buffer to store display picture buffers for reference * @BUF_PERSIST: buffer to store session context data * @BUF_SCRATCH_1: buffer to store decoding/encoding context data for HW + * @BUF_SCRATCH_2: buffer to store encoding context data for HW + * @BUF_VPSS: buffer to store VPSS context data for HW * @BUF_TYPE_MAX: max buffer types */ enum iris_buffer_type { @@ -38,6 +40,8 @@ enum iris_buffer_type { BUF_DPB, BUF_PERSIST, BUF_SCRATCH_1, + BUF_SCRATCH_2, + BUF_VPSS, BUF_TYPE_MAX, }; @@ -105,10 +109,11 @@ int iris_get_buffer_size(struct iris_inst *inst, enum iris_buffer_type buffer_ty void iris_get_internal_buffers(struct iris_inst *inst, u32 plane); int iris_create_internal_buffers(struct iris_inst *inst, u32 plane); int iris_queue_internal_buffers(struct iris_inst *inst, u32 plane); +int iris_queue_internal_deferred_buffers(struct iris_inst *inst, enum iris_buffer_type buffer_type); int iris_destroy_internal_buffer(struct iris_inst *inst, struct iris_buffer *buffer); int iris_destroy_all_internal_buffers(struct iris_inst *inst, u32 plane); int iris_destroy_dequeued_internal_buffers(struct iris_inst *inst, u32 plane); -int iris_alloc_and_queue_persist_bufs(struct iris_inst *inst); +int iris_alloc_and_queue_persist_bufs(struct iris_inst *inst, enum iris_buffer_type buf_type); int iris_alloc_and_queue_input_int_bufs(struct iris_inst *inst); int iris_queue_buffer(struct iris_inst *inst, struct iris_buffer *buf); int iris_queue_deferred_buffers(struct iris_inst *inst, enum iris_buffer_type buf_type); diff --git a/drivers/media/platform/qcom/iris/iris_common.c b/drivers/media/platform/qcom/iris/iris_common.c new file mode 100644 index 000000000000..9fc663bdaf3f --- /dev/null +++ b/drivers/media/platform/qcom/iris/iris_common.c @@ -0,0 +1,232 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include <media/v4l2-mem2mem.h> + +#include "iris_common.h" +#include "iris_ctrls.h" +#include "iris_instance.h" +#include "iris_power.h" + +int iris_vb2_buffer_to_driver(struct vb2_buffer *vb2, struct iris_buffer *buf) +{ + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2); + + buf->type = iris_v4l2_type_to_driver(vb2->type); + buf->index = vb2->index; + buf->fd = vb2->planes[0].m.fd; + buf->buffer_size = vb2->planes[0].length; + buf->data_offset = vb2->planes[0].data_offset; + buf->data_size = vb2->planes[0].bytesused - vb2->planes[0].data_offset; + buf->flags = vbuf->flags; + buf->timestamp = vb2->timestamp; + buf->attr = 0; + + return 0; +} + +void iris_set_ts_metadata(struct iris_inst *inst, struct vb2_v4l2_buffer *vbuf) +{ + u32 mask = V4L2_BUF_FLAG_TIMECODE | V4L2_BUF_FLAG_TSTAMP_SRC_MASK; + struct vb2_buffer *vb = &vbuf->vb2_buf; + u64 ts_us = vb->timestamp; + + if (inst->metadata_idx >= ARRAY_SIZE(inst->tss)) + inst->metadata_idx = 0; + + do_div(ts_us, NSEC_PER_USEC); + + inst->tss[inst->metadata_idx].flags = vbuf->flags & mask; + inst->tss[inst->metadata_idx].tc = vbuf->timecode; + inst->tss[inst->metadata_idx].ts_us = ts_us; + inst->tss[inst->metadata_idx].ts_ns = vb->timestamp; + + inst->metadata_idx++; +} + +int iris_process_streamon_input(struct iris_inst *inst) +{ + const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; + enum iris_inst_sub_state set_sub_state = 0; + int ret; + + iris_scale_power(inst); + + ret = hfi_ops->session_start(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + if (ret) + return ret; + + if (inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) { + ret = iris_inst_change_sub_state(inst, IRIS_INST_SUB_INPUT_PAUSE, 0); + if (ret) + return ret; + } + + if (inst->domain == DECODER && + (inst->sub_state & IRIS_INST_SUB_DRC || + inst->sub_state & IRIS_INST_SUB_DRAIN || + inst->sub_state & IRIS_INST_SUB_FIRST_IPSC)) { + if (!(inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE)) { + if (hfi_ops->session_pause) { + ret = hfi_ops->session_pause(inst, + V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + if (ret) + return ret; + } + set_sub_state = IRIS_INST_SUB_INPUT_PAUSE; + } + } + + ret = iris_inst_state_change_streamon(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + if (ret) + return ret; + + inst->last_buffer_dequeued = false; + + return iris_inst_change_sub_state(inst, 0, set_sub_state); +} + +int iris_process_streamon_output(struct iris_inst *inst) +{ + const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; + bool drain_active = false, drc_active = false; + enum iris_inst_sub_state clear_sub_state = 0; + int ret = 0; + + iris_scale_power(inst); + + drain_active = inst->sub_state & IRIS_INST_SUB_DRAIN && + inst->sub_state & IRIS_INST_SUB_DRAIN_LAST; + + drc_active = inst->sub_state & IRIS_INST_SUB_DRC && + inst->sub_state & IRIS_INST_SUB_DRC_LAST; + + if (drc_active) + clear_sub_state = IRIS_INST_SUB_DRC | IRIS_INST_SUB_DRC_LAST; + else if (drain_active) + clear_sub_state = IRIS_INST_SUB_DRAIN | IRIS_INST_SUB_DRAIN_LAST; + + if (inst->domain == DECODER && inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) { + ret = iris_alloc_and_queue_input_int_bufs(inst); + if (ret) + return ret; + ret = iris_set_stage(inst, STAGE); + if (ret) + return ret; + ret = iris_set_pipe(inst, PIPE); + if (ret) + return ret; + } + + if (inst->state == IRIS_INST_INPUT_STREAMING && + inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) { + if (!drain_active) + ret = hfi_ops->session_resume_drc(inst, + V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + else if (hfi_ops->session_resume_drain) + ret = hfi_ops->session_resume_drain(inst, + V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + if (ret) + return ret; + clear_sub_state |= IRIS_INST_SUB_INPUT_PAUSE; + } + + if (inst->sub_state & IRIS_INST_SUB_FIRST_IPSC) + clear_sub_state |= IRIS_INST_SUB_FIRST_IPSC; + + ret = hfi_ops->session_start(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + if (ret) + return ret; + + if (inst->sub_state & IRIS_INST_SUB_OUTPUT_PAUSE) + clear_sub_state |= IRIS_INST_SUB_OUTPUT_PAUSE; + + ret = iris_inst_state_change_streamon(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + if (ret) + return ret; + + inst->last_buffer_dequeued = false; + + return iris_inst_change_sub_state(inst, clear_sub_state, 0); +} + +static void iris_flush_deferred_buffers(struct iris_inst *inst, + enum iris_buffer_type type) +{ + struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; + struct v4l2_m2m_buffer *buffer, *n; + struct iris_buffer *buf; + + if (type == BUF_INPUT) { + v4l2_m2m_for_each_src_buf_safe(m2m_ctx, buffer, n) { + buf = to_iris_buffer(&buffer->vb); + if (buf->attr & BUF_ATTR_DEFERRED) { + if (!(buf->attr & BUF_ATTR_BUFFER_DONE)) { + buf->attr |= BUF_ATTR_BUFFER_DONE; + buf->data_size = 0; + iris_vb2_buffer_done(inst, buf); + } + } + } + } else { + v4l2_m2m_for_each_dst_buf_safe(m2m_ctx, buffer, n) { + buf = to_iris_buffer(&buffer->vb); + if (buf->attr & BUF_ATTR_DEFERRED) { + if (!(buf->attr & BUF_ATTR_BUFFER_DONE)) { + buf->attr |= BUF_ATTR_BUFFER_DONE; + buf->data_size = 0; + iris_vb2_buffer_done(inst, buf); + } + } + } + } +} + +static void iris_kill_session(struct iris_inst *inst) +{ + const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; + + if (!inst->session_id) + return; + + hfi_ops->session_close(inst); + iris_inst_change_state(inst, IRIS_INST_ERROR); +} + +int iris_session_streamoff(struct iris_inst *inst, u32 plane) +{ + const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; + enum iris_buffer_type buffer_type; + int ret; + + switch (plane) { + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + buffer_type = BUF_INPUT; + break; + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + buffer_type = BUF_OUTPUT; + break; + default: + return -EINVAL; + } + + ret = hfi_ops->session_stop(inst, plane); + if (ret) + goto error; + + ret = iris_inst_state_change_streamoff(inst, plane); + if (ret) + goto error; + + iris_flush_deferred_buffers(inst, buffer_type); + + return 0; + +error: + iris_kill_session(inst); + iris_flush_deferred_buffers(inst, buffer_type); + + return ret; +} diff --git a/drivers/media/platform/qcom/iris/iris_common.h b/drivers/media/platform/qcom/iris/iris_common.h new file mode 100644 index 000000000000..b2a27b781c9a --- /dev/null +++ b/drivers/media/platform/qcom/iris/iris_common.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#ifndef __IRIS_COMMON_H__ +#define __IRIS_COMMON_H__ + +struct iris_inst; +struct iris_buffer; + +int iris_vb2_buffer_to_driver(struct vb2_buffer *vb2, struct iris_buffer *buf); +void iris_set_ts_metadata(struct iris_inst *inst, struct vb2_v4l2_buffer *vbuf); +int iris_process_streamon_input(struct iris_inst *inst); +int iris_process_streamon_output(struct iris_inst *inst); +int iris_session_streamoff(struct iris_inst *inst, u32 plane); + +#endif diff --git a/drivers/media/platform/qcom/iris/iris_core.c b/drivers/media/platform/qcom/iris/iris_core.c index 0fa0a3b549a2..8406c48d635b 100644 --- a/drivers/media/platform/qcom/iris/iris_core.c +++ b/drivers/media/platform/qcom/iris/iris_core.c @@ -15,10 +15,12 @@ void iris_core_deinit(struct iris_core *core) pm_runtime_resume_and_get(core->dev); mutex_lock(&core->lock); - iris_fw_unload(core); - iris_vpu_power_off(core); - iris_hfi_queues_deinit(core); - core->state = IRIS_CORE_DEINIT; + if (core->state != IRIS_CORE_DEINIT) { + iris_fw_unload(core); + iris_vpu_power_off(core); + iris_hfi_queues_deinit(core); + core->state = IRIS_CORE_DEINIT; + } mutex_unlock(&core->lock); pm_runtime_put_sync(core->dev); diff --git a/drivers/media/platform/qcom/iris/iris_core.h b/drivers/media/platform/qcom/iris/iris_core.h index aeeac32a1f6d..fb194c967ad4 100644 --- a/drivers/media/platform/qcom/iris/iris_core.h +++ b/drivers/media/platform/qcom/iris/iris_core.h @@ -25,6 +25,11 @@ struct icc_info { #define IRIS_FW_VERSION_LENGTH 128 #define IFACEQ_CORE_PKT_SIZE (1024 * 4) +enum domain_type { + ENCODER = BIT(0), + DECODER = BIT(1), +}; + /** * struct iris_core - holds core parameters valid for all instances * @@ -33,8 +38,10 @@ struct icc_info { * @irq: iris irq * @v4l2_dev: a holder for v4l2 device structure * @vdev_dec: iris video device structure for decoder + * @vdev_enc: iris video device structure for encoder * @iris_v4l2_file_ops: iris v4l2 file ops - * @iris_v4l2_ioctl_ops: iris v4l2 ioctl ops + * @iris_v4l2_ioctl_ops_dec: iris v4l2 ioctl ops for decoder + * @iris_v4l2_ioctl_ops_enc: iris v4l2 ioctl ops for encoder * @iris_vb2_ops: iris vb2 ops * @icc_tbl: table of iris interconnects * @icc_count: count of iris interconnects @@ -64,7 +71,8 @@ struct icc_info { * @intr_status: interrupt status * @sys_error_handler: a delayed work for handling system fatal error * @instances: a list_head of all instances - * @inst_fw_caps: an array of supported instance capabilities + * @inst_fw_caps_dec: an array of supported instance capabilities by decoder + * @inst_fw_caps_enc: an array of supported instance capabilities by encoder */ struct iris_core { @@ -73,8 +81,10 @@ struct iris_core { int irq; struct v4l2_device v4l2_dev; struct video_device *vdev_dec; + struct video_device *vdev_enc; const struct v4l2_file_operations *iris_v4l2_file_ops; - const struct v4l2_ioctl_ops *iris_v4l2_ioctl_ops; + const struct v4l2_ioctl_ops *iris_v4l2_ioctl_ops_dec; + const struct v4l2_ioctl_ops *iris_v4l2_ioctl_ops_enc; const struct vb2_ops *iris_vb2_ops; struct icc_bulk_data *icc_tbl; u32 icc_count; @@ -104,7 +114,9 @@ struct iris_core { u32 intr_status; struct delayed_work sys_error_handler; struct list_head instances; - struct platform_inst_fw_cap inst_fw_caps[INST_FW_CAP_MAX]; + /* encoder and decoder have overlapping caps, so two different arrays are required */ + struct platform_inst_fw_cap inst_fw_caps_dec[INST_FW_CAP_MAX]; + struct platform_inst_fw_cap inst_fw_caps_enc[INST_FW_CAP_MAX]; }; int iris_core_init(struct iris_core *core); diff --git a/drivers/media/platform/qcom/iris/iris_ctrls.c b/drivers/media/platform/qcom/iris/iris_ctrls.c index 9136b723c0f2..754a5ad718bc 100644 --- a/drivers/media/platform/qcom/iris/iris_ctrls.c +++ b/drivers/media/platform/qcom/iris/iris_ctrls.c @@ -7,8 +7,13 @@ #include <media/v4l2-mem2mem.h> #include "iris_ctrls.h" +#include "iris_hfi_gen1_defines.h" +#include "iris_hfi_gen2_defines.h" #include "iris_instance.h" +#define CABAC_MAX_BITRATE 160000000 +#define CAVLC_MAX_BITRATE 220000000 + static inline bool iris_valid_cap_id(enum platform_inst_fw_cap_type cap_id) { return cap_id >= 1 && cap_id < INST_FW_CAP_MAX; @@ -31,6 +36,68 @@ static enum platform_inst_fw_cap_type iris_get_cap_id(u32 id) return LEVEL_VP9; case V4L2_CID_MPEG_VIDEO_HEVC_TIER: return TIER; + case V4L2_CID_MPEG_VIDEO_HEADER_MODE: + return HEADER_MODE; + case V4L2_CID_MPEG_VIDEO_PREPEND_SPSPPS_TO_IDR: + return PREPEND_SPSPPS_TO_IDR; + case V4L2_CID_MPEG_VIDEO_BITRATE: + return BITRATE; + case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: + return BITRATE_PEAK; + case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: + return BITRATE_MODE; + case V4L2_CID_MPEG_VIDEO_FRAME_SKIP_MODE: + return FRAME_SKIP_MODE; + case V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE: + return FRAME_RC_ENABLE; + case V4L2_CID_MPEG_VIDEO_GOP_SIZE: + return GOP_SIZE; + case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE: + return ENTROPY_MODE; + case V4L2_CID_MPEG_VIDEO_H264_MIN_QP: + return MIN_FRAME_QP_H264; + case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP: + return MIN_FRAME_QP_HEVC; + case V4L2_CID_MPEG_VIDEO_H264_MAX_QP: + return MAX_FRAME_QP_H264; + case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP: + return MAX_FRAME_QP_HEVC; + case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_MIN_QP: + return I_FRAME_MIN_QP_H264; + case V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_MIN_QP: + return I_FRAME_MIN_QP_HEVC; + case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_MIN_QP: + return P_FRAME_MIN_QP_H264; + case V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_MIN_QP: + return P_FRAME_MIN_QP_HEVC; + case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_MIN_QP: + return B_FRAME_MIN_QP_H264; + case V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_MIN_QP: + return B_FRAME_MIN_QP_HEVC; + case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_MAX_QP: + return I_FRAME_MAX_QP_H264; + case V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_MAX_QP: + return I_FRAME_MAX_QP_HEVC; + case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_MAX_QP: + return P_FRAME_MAX_QP_H264; + case V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_MAX_QP: + return P_FRAME_MAX_QP_HEVC; + case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_MAX_QP: + return B_FRAME_MAX_QP_H264; + case V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_MAX_QP: + return B_FRAME_MAX_QP_HEVC; + case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP: + return I_FRAME_QP_H264; + case V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP: + return I_FRAME_QP_HEVC; + case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP: + return P_FRAME_QP_H264; + case V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_QP: + return P_FRAME_QP_HEVC; + case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP: + return B_FRAME_QP_H264; + case V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_QP: + return B_FRAME_QP_HEVC; default: return INST_FW_CAP_MAX; } @@ -56,12 +123,74 @@ static u32 iris_get_v4l2_id(enum platform_inst_fw_cap_type cap_id) return V4L2_CID_MPEG_VIDEO_VP9_LEVEL; case TIER: return V4L2_CID_MPEG_VIDEO_HEVC_TIER; + case HEADER_MODE: + return V4L2_CID_MPEG_VIDEO_HEADER_MODE; + case PREPEND_SPSPPS_TO_IDR: + return V4L2_CID_MPEG_VIDEO_PREPEND_SPSPPS_TO_IDR; + case BITRATE: + return V4L2_CID_MPEG_VIDEO_BITRATE; + case BITRATE_PEAK: + return V4L2_CID_MPEG_VIDEO_BITRATE_PEAK; + case BITRATE_MODE: + return V4L2_CID_MPEG_VIDEO_BITRATE_MODE; + case FRAME_SKIP_MODE: + return V4L2_CID_MPEG_VIDEO_FRAME_SKIP_MODE; + case FRAME_RC_ENABLE: + return V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE; + case GOP_SIZE: + return V4L2_CID_MPEG_VIDEO_GOP_SIZE; + case ENTROPY_MODE: + return V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE; + case MIN_FRAME_QP_H264: + return V4L2_CID_MPEG_VIDEO_H264_MIN_QP; + case MIN_FRAME_QP_HEVC: + return V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP; + case MAX_FRAME_QP_H264: + return V4L2_CID_MPEG_VIDEO_H264_MAX_QP; + case MAX_FRAME_QP_HEVC: + return V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP; + case I_FRAME_MIN_QP_H264: + return V4L2_CID_MPEG_VIDEO_H264_I_FRAME_MIN_QP; + case I_FRAME_MIN_QP_HEVC: + return V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_MIN_QP; + case P_FRAME_MIN_QP_H264: + return V4L2_CID_MPEG_VIDEO_H264_P_FRAME_MIN_QP; + case P_FRAME_MIN_QP_HEVC: + return V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_MIN_QP; + case B_FRAME_MIN_QP_H264: + return V4L2_CID_MPEG_VIDEO_H264_B_FRAME_MIN_QP; + case B_FRAME_MIN_QP_HEVC: + return V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_MIN_QP; + case I_FRAME_MAX_QP_H264: + return V4L2_CID_MPEG_VIDEO_H264_I_FRAME_MAX_QP; + case I_FRAME_MAX_QP_HEVC: + return V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_MAX_QP; + case P_FRAME_MAX_QP_H264: + return V4L2_CID_MPEG_VIDEO_H264_P_FRAME_MAX_QP; + case P_FRAME_MAX_QP_HEVC: + return V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_MAX_QP; + case B_FRAME_MAX_QP_H264: + return V4L2_CID_MPEG_VIDEO_H264_B_FRAME_MAX_QP; + case B_FRAME_MAX_QP_HEVC: + return V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_MAX_QP; + case I_FRAME_QP_H264: + return V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP; + case I_FRAME_QP_HEVC: + return V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP; + case P_FRAME_QP_H264: + return V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP; + case P_FRAME_QP_HEVC: + return V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_QP; + case B_FRAME_QP_H264: + return V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP; + case B_FRAME_QP_HEVC: + return V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_QP; default: return 0; } } -static int iris_vdec_op_s_ctrl(struct v4l2_ctrl *ctrl) +static int iris_op_s_ctrl(struct v4l2_ctrl *ctrl) { struct iris_inst *inst = container_of(ctrl->handler, struct iris_inst, ctrl_handler); enum platform_inst_fw_cap_type cap_id; @@ -82,11 +211,16 @@ static int iris_vdec_op_s_ctrl(struct v4l2_ctrl *ctrl) inst->fw_caps[cap_id].value = ctrl->val; + if (vb2_is_streaming(q)) { + if (cap[cap_id].set) + cap[cap_id].set(inst, cap_id); + } + return 0; } static const struct v4l2_ctrl_ops iris_ctrl_ops = { - .s_ctrl = iris_vdec_op_s_ctrl, + .s_ctrl = iris_op_s_ctrl, }; int iris_ctrls_init(struct iris_inst *inst) @@ -101,7 +235,10 @@ int iris_ctrls_init(struct iris_inst *inst) num_ctrls++; } - /* Adding 1 to num_ctrls to include V4L2_CID_MIN_BUFFERS_FOR_CAPTURE */ + /* Adding 1 to num_ctrls to include + * V4L2_CID_MIN_BUFFERS_FOR_CAPTURE for decoder and + * V4L2_CID_MIN_BUFFERS_FOR_OUTPUT for encoder + */ ret = v4l2_ctrl_handler_init(&inst->ctrl_handler, num_ctrls + 1); if (ret) @@ -143,8 +280,13 @@ int iris_ctrls_init(struct iris_inst *inst) ctrl_idx++; } - v4l2_ctrl_new_std(&inst->ctrl_handler, NULL, - V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, 1, 32, 1, 4); + if (inst->domain == DECODER) { + v4l2_ctrl_new_std(&inst->ctrl_handler, NULL, + V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, 1, 32, 1, 4); + } else { + v4l2_ctrl_new_std(&inst->ctrl_handler, NULL, + V4L2_CID_MIN_BUFFERS_FOR_OUTPUT, 1, 32, 1, 4); + } ret = inst->ctrl_handler.error; if (ret) @@ -162,32 +304,57 @@ void iris_session_init_caps(struct iris_core *core) struct platform_inst_fw_cap *caps; u32 i, num_cap, cap_id; - caps = core->iris_platform_data->inst_fw_caps; - num_cap = core->iris_platform_data->inst_fw_caps_size; + caps = core->iris_platform_data->inst_fw_caps_dec; + num_cap = core->iris_platform_data->inst_fw_caps_dec_size; + + for (i = 0; i < num_cap; i++) { + cap_id = caps[i].cap_id; + if (!iris_valid_cap_id(cap_id)) + continue; + + core->inst_fw_caps_dec[cap_id].cap_id = caps[i].cap_id; + core->inst_fw_caps_dec[cap_id].min = caps[i].min; + core->inst_fw_caps_dec[cap_id].max = caps[i].max; + core->inst_fw_caps_dec[cap_id].step_or_mask = caps[i].step_or_mask; + core->inst_fw_caps_dec[cap_id].value = caps[i].value; + core->inst_fw_caps_dec[cap_id].flags = caps[i].flags; + core->inst_fw_caps_dec[cap_id].hfi_id = caps[i].hfi_id; + core->inst_fw_caps_dec[cap_id].set = caps[i].set; + } + + caps = core->iris_platform_data->inst_fw_caps_enc; + num_cap = core->iris_platform_data->inst_fw_caps_enc_size; for (i = 0; i < num_cap; i++) { cap_id = caps[i].cap_id; if (!iris_valid_cap_id(cap_id)) continue; - core->inst_fw_caps[cap_id].cap_id = caps[i].cap_id; - core->inst_fw_caps[cap_id].min = caps[i].min; - core->inst_fw_caps[cap_id].max = caps[i].max; - core->inst_fw_caps[cap_id].step_or_mask = caps[i].step_or_mask; - core->inst_fw_caps[cap_id].value = caps[i].value; - core->inst_fw_caps[cap_id].flags = caps[i].flags; - core->inst_fw_caps[cap_id].hfi_id = caps[i].hfi_id; - core->inst_fw_caps[cap_id].set = caps[i].set; + core->inst_fw_caps_enc[cap_id].cap_id = caps[i].cap_id; + core->inst_fw_caps_enc[cap_id].min = caps[i].min; + core->inst_fw_caps_enc[cap_id].max = caps[i].max; + core->inst_fw_caps_enc[cap_id].step_or_mask = caps[i].step_or_mask; + core->inst_fw_caps_enc[cap_id].value = caps[i].value; + core->inst_fw_caps_enc[cap_id].flags = caps[i].flags; + core->inst_fw_caps_enc[cap_id].hfi_id = caps[i].hfi_id; + core->inst_fw_caps_enc[cap_id].set = caps[i].set; } } static u32 iris_get_port_info(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id) { - if (inst->fw_caps[cap_id].flags & CAP_FLAG_INPUT_PORT) - return HFI_PORT_BITSTREAM; - else if (inst->fw_caps[cap_id].flags & CAP_FLAG_OUTPUT_PORT) - return HFI_PORT_RAW; + if (inst->domain == DECODER) { + if (inst->fw_caps[cap_id].flags & CAP_FLAG_INPUT_PORT) + return HFI_PORT_BITSTREAM; + else if (inst->fw_caps[cap_id].flags & CAP_FLAG_OUTPUT_PORT) + return HFI_PORT_RAW; + } else { + if (inst->fw_caps[cap_id].flags & CAP_FLAG_INPUT_PORT) + return HFI_PORT_RAW; + else if (inst->fw_caps[cap_id].flags & CAP_FLAG_OUTPUT_PORT) + return HFI_PORT_BITSTREAM; + } return HFI_PORT_NONE; } @@ -227,8 +394,10 @@ int iris_set_stage(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id u32 width = inp_f->fmt.pix_mp.width; u32 work_mode = STAGE_2; - if (iris_res_is_less_than(width, height, 1280, 720)) - work_mode = STAGE_1; + if (inst->domain == DECODER) { + if (iris_res_is_less_than(width, height, 1280, 720)) + work_mode = STAGE_1; + } return hfi_ops->session_set_property(inst, hfi_id, HFI_HOST_FLAGS_NONE, @@ -250,6 +419,470 @@ int iris_set_pipe(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id) &work_route, sizeof(u32)); } +int iris_set_profile(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id) +{ + const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; + u32 hfi_id, hfi_value; + + if (inst->codec == V4L2_PIX_FMT_H264) { + hfi_id = inst->fw_caps[PROFILE_H264].hfi_id; + hfi_value = inst->fw_caps[PROFILE_H264].value; + } else { + hfi_id = inst->fw_caps[PROFILE_HEVC].hfi_id; + hfi_value = inst->fw_caps[PROFILE_HEVC].value; + } + + return hfi_ops->session_set_property(inst, hfi_id, + HFI_HOST_FLAGS_NONE, + iris_get_port_info(inst, cap_id), + HFI_PAYLOAD_U32_ENUM, + &hfi_value, sizeof(u32)); +} + +int iris_set_level(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id) +{ + const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; + u32 hfi_id, hfi_value; + + if (inst->codec == V4L2_PIX_FMT_H264) { + hfi_id = inst->fw_caps[LEVEL_H264].hfi_id; + hfi_value = inst->fw_caps[LEVEL_H264].value; + } else { + hfi_id = inst->fw_caps[LEVEL_HEVC].hfi_id; + hfi_value = inst->fw_caps[LEVEL_HEVC].value; + } + + return hfi_ops->session_set_property(inst, hfi_id, + HFI_HOST_FLAGS_NONE, + iris_get_port_info(inst, cap_id), + HFI_PAYLOAD_U32_ENUM, + &hfi_value, sizeof(u32)); +} + +int iris_set_profile_level_gen1(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id) +{ + const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; + u32 hfi_id = inst->fw_caps[cap_id].hfi_id; + struct hfi_profile_level pl; + + if (inst->codec == V4L2_PIX_FMT_H264) { + pl.profile = inst->fw_caps[PROFILE_H264].value; + pl.level = inst->fw_caps[LEVEL_H264].value; + } else { + pl.profile = inst->fw_caps[PROFILE_HEVC].value; + pl.level = inst->fw_caps[LEVEL_HEVC].value; + } + + return hfi_ops->session_set_property(inst, hfi_id, + HFI_HOST_FLAGS_NONE, + iris_get_port_info(inst, cap_id), + HFI_PAYLOAD_U32_ENUM, + &pl, sizeof(u32)); +} + +int iris_set_header_mode_gen1(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id) +{ + const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; + u32 header_mode = inst->fw_caps[cap_id].value; + u32 hfi_id = inst->fw_caps[cap_id].hfi_id; + u32 hfi_val; + + if (header_mode == V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE) + hfi_val = 0; + else + hfi_val = 1; + + return hfi_ops->session_set_property(inst, hfi_id, + HFI_HOST_FLAGS_NONE, + iris_get_port_info(inst, cap_id), + HFI_PAYLOAD_U32, + &hfi_val, sizeof(u32)); +} + +int iris_set_header_mode_gen2(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id) +{ + const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; + u32 prepend_sps_pps = inst->fw_caps[PREPEND_SPSPPS_TO_IDR].value; + u32 header_mode = inst->fw_caps[cap_id].value; + u32 hfi_id = inst->fw_caps[cap_id].hfi_id; + u32 hfi_val; + + if (prepend_sps_pps) + hfi_val = HFI_SEQ_HEADER_PREFIX_WITH_SYNC_FRAME; + else if (header_mode == V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME) + hfi_val = HFI_SEQ_HEADER_JOINED_WITH_1ST_FRAME; + else + hfi_val = HFI_SEQ_HEADER_SEPERATE_FRAME; + + return hfi_ops->session_set_property(inst, hfi_id, + HFI_HOST_FLAGS_NONE, + iris_get_port_info(inst, cap_id), + HFI_PAYLOAD_U32_ENUM, + &hfi_val, sizeof(u32)); +} + +int iris_set_bitrate(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id) +{ + const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; + u32 entropy_mode = inst->fw_caps[ENTROPY_MODE].value; + u32 bitrate = inst->fw_caps[cap_id].value; + u32 hfi_id = inst->fw_caps[cap_id].hfi_id; + u32 max_bitrate; + + if (inst->codec == V4L2_PIX_FMT_HEVC) + max_bitrate = CABAC_MAX_BITRATE; + + if (entropy_mode == V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC) + max_bitrate = CABAC_MAX_BITRATE; + else + max_bitrate = CAVLC_MAX_BITRATE; + + bitrate = min(bitrate, max_bitrate); + + return hfi_ops->session_set_property(inst, hfi_id, + HFI_HOST_FLAGS_NONE, + iris_get_port_info(inst, cap_id), + HFI_PAYLOAD_U32, + &bitrate, sizeof(u32)); +} + +int iris_set_peak_bitrate(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id) +{ + const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; + u32 rc_mode = inst->fw_caps[BITRATE_MODE].value; + u32 peak_bitrate = inst->fw_caps[cap_id].value; + u32 bitrate = inst->fw_caps[BITRATE].value; + u32 hfi_id = inst->fw_caps[cap_id].hfi_id; + + if (rc_mode != V4L2_MPEG_VIDEO_BITRATE_MODE_CBR) + return 0; + + if (inst->fw_caps[cap_id].flags & CAP_FLAG_CLIENT_SET) { + if (peak_bitrate < bitrate) + peak_bitrate = bitrate; + } else { + peak_bitrate = bitrate; + } + + inst->fw_caps[cap_id].value = peak_bitrate; + + return hfi_ops->session_set_property(inst, hfi_id, + HFI_HOST_FLAGS_NONE, + iris_get_port_info(inst, cap_id), + HFI_PAYLOAD_U32, + &peak_bitrate, sizeof(u32)); +} + +int iris_set_bitrate_mode_gen1(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id) +{ + const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; + u32 bitrate_mode = inst->fw_caps[BITRATE_MODE].value; + u32 frame_rc = inst->fw_caps[FRAME_RC_ENABLE].value; + u32 frame_skip = inst->fw_caps[FRAME_SKIP_MODE].value; + u32 hfi_id = inst->fw_caps[cap_id].hfi_id; + u32 rc_mode = 0; + + if (!frame_rc) + rc_mode = HFI_RATE_CONTROL_OFF; + else if (bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) + rc_mode = frame_skip ? HFI_RATE_CONTROL_VBR_VFR : HFI_RATE_CONTROL_VBR_CFR; + else if (bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR) + rc_mode = frame_skip ? HFI_RATE_CONTROL_CBR_VFR : HFI_RATE_CONTROL_CBR_CFR; + else if (bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ) + rc_mode = HFI_RATE_CONTROL_CQ; + + inst->hfi_rc_type = rc_mode; + + return hfi_ops->session_set_property(inst, hfi_id, + HFI_HOST_FLAGS_NONE, + iris_get_port_info(inst, cap_id), + HFI_PAYLOAD_U32_ENUM, + &rc_mode, sizeof(u32)); +} + +int iris_set_bitrate_mode_gen2(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id) +{ + const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; + u32 bitrate_mode = inst->fw_caps[BITRATE_MODE].value; + u32 frame_rc = inst->fw_caps[FRAME_RC_ENABLE].value; + u32 frame_skip = inst->fw_caps[FRAME_SKIP_MODE].value; + u32 hfi_id = inst->fw_caps[cap_id].hfi_id; + u32 rc_mode = 0; + + if (!frame_rc) + rc_mode = HFI_RC_OFF; + else if (bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) + rc_mode = HFI_RC_VBR_CFR; + else if (bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR) + rc_mode = frame_skip ? HFI_RC_CBR_VFR : HFI_RC_CBR_CFR; + else if (bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ) + rc_mode = HFI_RC_CQ; + + inst->hfi_rc_type = rc_mode; + + return hfi_ops->session_set_property(inst, hfi_id, + HFI_HOST_FLAGS_NONE, + iris_get_port_info(inst, cap_id), + HFI_PAYLOAD_U32_ENUM, + &rc_mode, sizeof(u32)); +} + +int iris_set_entropy_mode_gen1(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id) +{ + const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; + u32 entropy_mode = inst->fw_caps[cap_id].value; + u32 hfi_id = inst->fw_caps[cap_id].hfi_id; + u32 hfi_val; + + if (inst->codec != V4L2_PIX_FMT_H264) + return 0; + + hfi_val = (entropy_mode == V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC) ? + HFI_H264_ENTROPY_CAVLC : HFI_H264_ENTROPY_CABAC; + + return hfi_ops->session_set_property(inst, hfi_id, + HFI_HOST_FLAGS_NONE, + iris_get_port_info(inst, cap_id), + HFI_PAYLOAD_U32, + &hfi_val, sizeof(u32)); +} + +int iris_set_entropy_mode_gen2(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id) +{ + const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; + u32 entropy_mode = inst->fw_caps[cap_id].value; + u32 hfi_id = inst->fw_caps[cap_id].hfi_id; + u32 profile; + + if (inst->codec != V4L2_PIX_FMT_H264) + return 0; + + profile = inst->fw_caps[PROFILE_H264].value; + + if (profile == V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE || + profile == V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) + entropy_mode = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC; + + inst->fw_caps[cap_id].value = entropy_mode; + + return hfi_ops->session_set_property(inst, hfi_id, + HFI_HOST_FLAGS_NONE, + iris_get_port_info(inst, cap_id), + HFI_PAYLOAD_U32, + &entropy_mode, sizeof(u32)); +} + +int iris_set_min_qp(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id) +{ + const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; + u32 i_qp_enable = 0, p_qp_enable = 0, b_qp_enable = 0; + u32 i_frame_qp = 0, p_frame_qp = 0, b_frame_qp = 0; + u32 min_qp_enable = 0, client_qp_enable = 0; + u32 hfi_id = inst->fw_caps[cap_id].hfi_id; + u32 hfi_val; + + if (inst->codec == V4L2_PIX_FMT_H264) { + if (inst->fw_caps[MIN_FRAME_QP_H264].flags & CAP_FLAG_CLIENT_SET) + min_qp_enable = 1; + if (min_qp_enable || + (inst->fw_caps[I_FRAME_MIN_QP_H264].flags & CAP_FLAG_CLIENT_SET)) + i_qp_enable = 1; + if (min_qp_enable || + (inst->fw_caps[P_FRAME_MIN_QP_H264].flags & CAP_FLAG_CLIENT_SET)) + p_qp_enable = 1; + if (min_qp_enable || + (inst->fw_caps[B_FRAME_MIN_QP_H264].flags & CAP_FLAG_CLIENT_SET)) + b_qp_enable = 1; + } else { + if (inst->fw_caps[MIN_FRAME_QP_HEVC].flags & CAP_FLAG_CLIENT_SET) + min_qp_enable = 1; + if (min_qp_enable || + (inst->fw_caps[I_FRAME_MIN_QP_HEVC].flags & CAP_FLAG_CLIENT_SET)) + i_qp_enable = 1; + if (min_qp_enable || + (inst->fw_caps[P_FRAME_MIN_QP_HEVC].flags & CAP_FLAG_CLIENT_SET)) + p_qp_enable = 1; + if (min_qp_enable || + (inst->fw_caps[B_FRAME_MIN_QP_HEVC].flags & CAP_FLAG_CLIENT_SET)) + b_qp_enable = 1; + } + + client_qp_enable = i_qp_enable | p_qp_enable << 1 | b_qp_enable << 2; + if (!client_qp_enable) + return 0; + + if (inst->codec == V4L2_PIX_FMT_H264) { + i_frame_qp = max(inst->fw_caps[I_FRAME_MIN_QP_H264].value, + inst->fw_caps[MIN_FRAME_QP_H264].value); + p_frame_qp = max(inst->fw_caps[P_FRAME_MIN_QP_H264].value, + inst->fw_caps[MIN_FRAME_QP_H264].value); + b_frame_qp = max(inst->fw_caps[B_FRAME_MIN_QP_H264].value, + inst->fw_caps[MIN_FRAME_QP_H264].value); + } else { + i_frame_qp = max(inst->fw_caps[I_FRAME_MIN_QP_HEVC].value, + inst->fw_caps[MIN_FRAME_QP_HEVC].value); + p_frame_qp = max(inst->fw_caps[P_FRAME_MIN_QP_HEVC].value, + inst->fw_caps[MIN_FRAME_QP_HEVC].value); + b_frame_qp = max(inst->fw_caps[B_FRAME_MIN_QP_HEVC].value, + inst->fw_caps[MIN_FRAME_QP_HEVC].value); + } + + hfi_val = i_frame_qp | p_frame_qp << 8 | b_frame_qp << 16 | client_qp_enable << 24; + + return hfi_ops->session_set_property(inst, hfi_id, + HFI_HOST_FLAGS_NONE, + iris_get_port_info(inst, cap_id), + HFI_PAYLOAD_32_PACKED, + &hfi_val, sizeof(u32)); +} + +int iris_set_max_qp(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id) +{ + const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; + u32 i_qp_enable = 0, p_qp_enable = 0, b_qp_enable = 0; + u32 max_qp_enable = 0, client_qp_enable; + u32 i_frame_qp, p_frame_qp, b_frame_qp; + u32 hfi_id = inst->fw_caps[cap_id].hfi_id; + u32 hfi_val; + + if (inst->codec == V4L2_PIX_FMT_H264) { + if (inst->fw_caps[MAX_FRAME_QP_H264].flags & CAP_FLAG_CLIENT_SET) + max_qp_enable = 1; + if (max_qp_enable || + (inst->fw_caps[I_FRAME_MAX_QP_H264].flags & CAP_FLAG_CLIENT_SET)) + i_qp_enable = 1; + if (max_qp_enable || + (inst->fw_caps[P_FRAME_MAX_QP_H264].flags & CAP_FLAG_CLIENT_SET)) + p_qp_enable = 1; + if (max_qp_enable || + (inst->fw_caps[B_FRAME_MAX_QP_H264].flags & CAP_FLAG_CLIENT_SET)) + b_qp_enable = 1; + } else { + if (inst->fw_caps[MAX_FRAME_QP_HEVC].flags & CAP_FLAG_CLIENT_SET) + max_qp_enable = 1; + if (max_qp_enable || + (inst->fw_caps[I_FRAME_MAX_QP_HEVC].flags & CAP_FLAG_CLIENT_SET)) + i_qp_enable = 1; + if (max_qp_enable || + (inst->fw_caps[P_FRAME_MAX_QP_HEVC].flags & CAP_FLAG_CLIENT_SET)) + p_qp_enable = 1; + if (max_qp_enable || + (inst->fw_caps[B_FRAME_MAX_QP_HEVC].flags & CAP_FLAG_CLIENT_SET)) + b_qp_enable = 1; + } + + client_qp_enable = i_qp_enable | p_qp_enable << 1 | b_qp_enable << 2; + if (!client_qp_enable) + return 0; + + if (inst->codec == V4L2_PIX_FMT_H264) { + i_frame_qp = min(inst->fw_caps[I_FRAME_MAX_QP_H264].value, + inst->fw_caps[MAX_FRAME_QP_H264].value); + p_frame_qp = min(inst->fw_caps[P_FRAME_MAX_QP_H264].value, + inst->fw_caps[MAX_FRAME_QP_H264].value); + b_frame_qp = min(inst->fw_caps[B_FRAME_MAX_QP_H264].value, + inst->fw_caps[MAX_FRAME_QP_H264].value); + } else { + i_frame_qp = min(inst->fw_caps[I_FRAME_MAX_QP_HEVC].value, + inst->fw_caps[MAX_FRAME_QP_HEVC].value); + p_frame_qp = min(inst->fw_caps[P_FRAME_MAX_QP_HEVC].value, + inst->fw_caps[MAX_FRAME_QP_HEVC].value); + b_frame_qp = min(inst->fw_caps[B_FRAME_MAX_QP_HEVC].value, + inst->fw_caps[MAX_FRAME_QP_HEVC].value); + } + + hfi_val = i_frame_qp | p_frame_qp << 8 | b_frame_qp << 16 | + client_qp_enable << 24; + + return hfi_ops->session_set_property(inst, hfi_id, + HFI_HOST_FLAGS_NONE, + iris_get_port_info(inst, cap_id), + HFI_PAYLOAD_32_PACKED, + &hfi_val, sizeof(u32)); +} + +int iris_set_frame_qp(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id) +{ + const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; + u32 i_qp_enable = 0, p_qp_enable = 0, b_qp_enable = 0, client_qp_enable; + u32 i_frame_qp, p_frame_qp, b_frame_qp; + u32 hfi_id = inst->fw_caps[cap_id].hfi_id; + struct vb2_queue *q; + u32 hfi_val; + + q = v4l2_m2m_get_dst_vq(inst->m2m_ctx); + if (vb2_is_streaming(q)) { + if (inst->hfi_rc_type != HFI_RC_OFF) + return 0; + } + + if (inst->hfi_rc_type == HFI_RC_OFF) { + i_qp_enable = 1; + p_qp_enable = 1; + b_qp_enable = 1; + } else { + if (inst->codec == V4L2_PIX_FMT_H264) { + if (inst->fw_caps[I_FRAME_QP_H264].flags & CAP_FLAG_CLIENT_SET) + i_qp_enable = 1; + if (inst->fw_caps[P_FRAME_QP_H264].flags & CAP_FLAG_CLIENT_SET) + p_qp_enable = 1; + if (inst->fw_caps[B_FRAME_QP_H264].flags & CAP_FLAG_CLIENT_SET) + b_qp_enable = 1; + } else { + if (inst->fw_caps[I_FRAME_QP_HEVC].flags & CAP_FLAG_CLIENT_SET) + i_qp_enable = 1; + if (inst->fw_caps[P_FRAME_QP_HEVC].flags & CAP_FLAG_CLIENT_SET) + p_qp_enable = 1; + if (inst->fw_caps[B_FRAME_QP_HEVC].flags & CAP_FLAG_CLIENT_SET) + b_qp_enable = 1; + } + } + + client_qp_enable = i_qp_enable | p_qp_enable << 1 | b_qp_enable << 2; + if (!client_qp_enable) + return 0; + + if (inst->codec == V4L2_PIX_FMT_H264) { + i_frame_qp = inst->fw_caps[I_FRAME_QP_H264].value; + p_frame_qp = inst->fw_caps[P_FRAME_QP_H264].value; + b_frame_qp = inst->fw_caps[B_FRAME_QP_H264].value; + } else { + i_frame_qp = inst->fw_caps[I_FRAME_QP_HEVC].value; + p_frame_qp = inst->fw_caps[P_FRAME_QP_HEVC].value; + b_frame_qp = inst->fw_caps[B_FRAME_QP_HEVC].value; + } + + hfi_val = i_frame_qp | p_frame_qp << 8 | b_frame_qp << 16 | + client_qp_enable << 24; + + return hfi_ops->session_set_property(inst, hfi_id, + HFI_HOST_FLAGS_NONE, + iris_get_port_info(inst, cap_id), + HFI_PAYLOAD_32_PACKED, + &hfi_val, sizeof(u32)); +} + +int iris_set_qp_range(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id) +{ + const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; + struct hfi_quantization_range_v2 range; + u32 hfi_id = inst->fw_caps[cap_id].hfi_id; + + if (inst->codec == V4L2_PIX_FMT_HEVC) { + range.min_qp.qp_packed = inst->fw_caps[MIN_FRAME_QP_HEVC].value; + range.max_qp.qp_packed = inst->fw_caps[MAX_FRAME_QP_HEVC].value; + } else { + range.min_qp.qp_packed = inst->fw_caps[MIN_FRAME_QP_H264].value; + range.max_qp.qp_packed = inst->fw_caps[MAX_FRAME_QP_H264].value; + } + + return hfi_ops->session_set_property(inst, hfi_id, + HFI_HOST_FLAGS_NONE, + iris_get_port_info(inst, cap_id), + HFI_PAYLOAD_32_PACKED, + &range, sizeof(range)); +} + int iris_set_properties(struct iris_inst *inst, u32 plane) { const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; diff --git a/drivers/media/platform/qcom/iris/iris_ctrls.h b/drivers/media/platform/qcom/iris/iris_ctrls.h index 9b5741868933..30af333cc494 100644 --- a/drivers/media/platform/qcom/iris/iris_ctrls.h +++ b/drivers/media/platform/qcom/iris/iris_ctrls.h @@ -17,6 +17,21 @@ int iris_set_u32_enum(struct iris_inst *inst, enum platform_inst_fw_cap_type cap int iris_set_stage(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id); int iris_set_pipe(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id); int iris_set_u32(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id); +int iris_set_profile(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id); +int iris_set_level(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id); +int iris_set_profile_level_gen1(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id); +int iris_set_header_mode_gen1(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id); +int iris_set_header_mode_gen2(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id); +int iris_set_bitrate(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id); +int iris_set_peak_bitrate(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id); +int iris_set_bitrate_mode_gen1(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id); +int iris_set_bitrate_mode_gen2(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id); +int iris_set_entropy_mode_gen1(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id); +int iris_set_entropy_mode_gen2(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id); +int iris_set_min_qp(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id); +int iris_set_max_qp(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id); +int iris_set_frame_qp(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id); +int iris_set_qp_range(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id); int iris_set_properties(struct iris_inst *inst, u32 plane); #endif diff --git a/drivers/media/platform/qcom/iris/iris_firmware.c b/drivers/media/platform/qcom/iris/iris_firmware.c index f1b5cd56db32..9ab499fad946 100644 --- a/drivers/media/platform/qcom/iris/iris_firmware.c +++ b/drivers/media/platform/qcom/iris/iris_firmware.c @@ -60,16 +60,7 @@ static int iris_load_fw_to_memory(struct iris_core *core, const char *fw_name) ret = qcom_mdt_load(dev, firmware, fw_name, pas_id, mem_virt, mem_phys, res_size, NULL); - if (ret) - goto err_mem_unmap; - - ret = qcom_scm_pas_auth_and_reset(pas_id); - if (ret) - goto err_mem_unmap; - - return ret; -err_mem_unmap: memunmap(mem_virt); err_release_fw: release_firmware(firmware); @@ -94,6 +85,12 @@ int iris_fw_load(struct iris_core *core) return -ENOMEM; } + ret = qcom_scm_pas_auth_and_reset(core->iris_platform_data->pas_id); + if (ret) { + dev_err(core->dev, "auth and reset failed: %d\n", ret); + return ret; + } + ret = qcom_scm_mem_protect_video_var(cp_config->cp_start, cp_config->cp_size, cp_config->cp_nonpixel_start, diff --git a/drivers/media/platform/qcom/iris/iris_hfi_common.h b/drivers/media/platform/qcom/iris/iris_hfi_common.h index 9e6aadb83783..b51471fb32c7 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_common.h +++ b/drivers/media/platform/qcom/iris/iris_hfi_common.h @@ -102,7 +102,7 @@ enum hfi_matrix_coefficients { struct iris_hfi_prop_type_handle { u32 type; - int (*handle)(struct iris_inst *inst); + int (*handle)(struct iris_inst *inst, u32 plane); }; struct iris_hfi_command_ops { diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c index 5fc30d54af4d..e1788c266bb1 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c @@ -21,6 +21,10 @@ static u32 iris_hfi_gen1_buf_type_from_driver(enum iris_buffer_type buffer_type) return HFI_BUFFER_INTERNAL_SCRATCH; case BUF_SCRATCH_1: return HFI_BUFFER_INTERNAL_SCRATCH_1; + case BUF_SCRATCH_2: + return HFI_BUFFER_INTERNAL_SCRATCH_2; + case BUF_ARP: + return HFI_BUFFER_INTERNAL_PERSIST; default: return -EINVAL; } @@ -109,7 +113,12 @@ static int iris_hfi_gen1_session_open(struct iris_inst *inst) packet.shdr.hdr.size = sizeof(struct hfi_session_open_pkt); packet.shdr.hdr.pkt_type = HFI_CMD_SYS_SESSION_INIT; packet.shdr.session_id = inst->session_id; - packet.session_domain = HFI_SESSION_TYPE_DEC; + + if (inst->domain == DECODER) + packet.session_domain = HFI_SESSION_TYPE_DEC; + else + packet.session_domain = HFI_SESSION_TYPE_ENC; + packet.session_codec = codec; reinit_completion(&inst->completion); @@ -184,47 +193,70 @@ static int iris_hfi_gen1_session_stop(struct iris_inst *inst, u32 plane) u32 flush_type = 0; int ret = 0; - if ((V4L2_TYPE_IS_OUTPUT(plane) && - inst->state == IRIS_INST_INPUT_STREAMING) || - (V4L2_TYPE_IS_CAPTURE(plane) && - inst->state == IRIS_INST_OUTPUT_STREAMING) || - inst->state == IRIS_INST_ERROR) { - reinit_completion(&inst->completion); - iris_hfi_gen1_packet_session_cmd(inst, &pkt, HFI_CMD_SESSION_STOP); - ret = iris_hfi_queue_cmd_write(core, &pkt, pkt.shdr.hdr.size); - if (!ret) - ret = iris_wait_for_session_response(inst, false); - - reinit_completion(&inst->completion); - iris_hfi_gen1_packet_session_cmd(inst, &pkt, HFI_CMD_SESSION_RELEASE_RESOURCES); - ret = iris_hfi_queue_cmd_write(core, &pkt, pkt.shdr.hdr.size); - if (!ret) - ret = iris_wait_for_session_response(inst, false); - - iris_inst_change_sub_state(inst, IRIS_INST_SUB_LOAD_RESOURCES, 0); + if (inst->domain == DECODER) { + if (inst->state == IRIS_INST_STREAMING) { + if (V4L2_TYPE_IS_OUTPUT(plane)) + flush_type = HFI_FLUSH_ALL; + else if (V4L2_TYPE_IS_CAPTURE(plane)) + flush_type = HFI_FLUSH_OUTPUT; + + reinit_completion(&inst->flush_completion); + + flush_pkt.shdr.hdr.size = sizeof(struct hfi_session_flush_pkt); + flush_pkt.shdr.hdr.pkt_type = HFI_CMD_SESSION_FLUSH; + flush_pkt.shdr.session_id = inst->session_id; + flush_pkt.flush_type = flush_type; + + ret = iris_hfi_queue_cmd_write(core, &flush_pkt, flush_pkt.shdr.hdr.size); + if (!ret) { + inst->flush_responses_pending++; + ret = iris_wait_for_session_response(inst, true); + } + } else if (inst->sub_state & IRIS_INST_SUB_LOAD_RESOURCES) { + reinit_completion(&inst->completion); + iris_hfi_gen1_packet_session_cmd(inst, &pkt, HFI_CMD_SESSION_STOP); + ret = iris_hfi_queue_cmd_write(core, &pkt, pkt.shdr.hdr.size); + if (!ret) + ret = iris_wait_for_session_response(inst, false); + + reinit_completion(&inst->completion); + iris_hfi_gen1_packet_session_cmd(inst, &pkt, + HFI_CMD_SESSION_RELEASE_RESOURCES); + ret = iris_hfi_queue_cmd_write(core, &pkt, pkt.shdr.hdr.size); + if (!ret) + ret = iris_wait_for_session_response(inst, false); + + iris_inst_change_sub_state(inst, IRIS_INST_SUB_LOAD_RESOURCES, 0); + + iris_helper_buffers_done(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, + VB2_BUF_STATE_ERROR); + iris_helper_buffers_done(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, + VB2_BUF_STATE_ERROR); + } + } else { + if (inst->state == IRIS_INST_STREAMING || + inst->state == IRIS_INST_INPUT_STREAMING || + inst->state == IRIS_INST_ERROR) { + reinit_completion(&inst->completion); + iris_hfi_gen1_packet_session_cmd(inst, &pkt, HFI_CMD_SESSION_STOP); + ret = iris_hfi_queue_cmd_write(core, &pkt, pkt.shdr.hdr.size); + if (!ret) + ret = iris_wait_for_session_response(inst, false); + + reinit_completion(&inst->completion); + iris_hfi_gen1_packet_session_cmd(inst, &pkt, + HFI_CMD_SESSION_RELEASE_RESOURCES); + ret = iris_hfi_queue_cmd_write(core, &pkt, pkt.shdr.hdr.size); + if (!ret) + ret = iris_wait_for_session_response(inst, false); + + iris_inst_change_sub_state(inst, IRIS_INST_SUB_LOAD_RESOURCES, 0); + } iris_helper_buffers_done(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, VB2_BUF_STATE_ERROR); iris_helper_buffers_done(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, VB2_BUF_STATE_ERROR); - } else if (inst->state == IRIS_INST_STREAMING) { - if (V4L2_TYPE_IS_OUTPUT(plane)) - flush_type = HFI_FLUSH_ALL; - else if (V4L2_TYPE_IS_CAPTURE(plane)) - flush_type = HFI_FLUSH_OUTPUT; - - reinit_completion(&inst->flush_completion); - - flush_pkt.shdr.hdr.size = sizeof(struct hfi_session_flush_pkt); - flush_pkt.shdr.hdr.pkt_type = HFI_CMD_SESSION_FLUSH; - flush_pkt.shdr.session_id = inst->session_id; - flush_pkt.flush_type = flush_type; - - ret = iris_hfi_queue_cmd_write(core, &flush_pkt, flush_pkt.shdr.hdr.size); - if (!ret) { - inst->flush_responses_pending++; - ret = iris_wait_for_session_response(inst, true); - } } return ret; @@ -241,23 +273,44 @@ static int iris_hfi_gen1_session_continue(struct iris_inst *inst, u32 plane) static int iris_hfi_gen1_queue_input_buffer(struct iris_inst *inst, struct iris_buffer *buf) { - struct hfi_session_empty_buffer_compressed_pkt ip_pkt; - - ip_pkt.shdr.hdr.size = sizeof(struct hfi_session_empty_buffer_compressed_pkt); - ip_pkt.shdr.hdr.pkt_type = HFI_CMD_SESSION_EMPTY_BUFFER; - ip_pkt.shdr.session_id = inst->session_id; - ip_pkt.time_stamp_hi = upper_32_bits(buf->timestamp); - ip_pkt.time_stamp_lo = lower_32_bits(buf->timestamp); - ip_pkt.flags = buf->flags; - ip_pkt.mark_target = 0; - ip_pkt.mark_data = 0; - ip_pkt.offset = buf->data_offset; - ip_pkt.alloc_len = buf->buffer_size; - ip_pkt.filled_len = buf->data_size; - ip_pkt.input_tag = buf->index; - ip_pkt.packet_buffer = buf->device_addr; - - return iris_hfi_queue_cmd_write(inst->core, &ip_pkt, ip_pkt.shdr.hdr.size); + struct hfi_session_empty_buffer_compressed_pkt com_ip_pkt; + struct hfi_session_empty_buffer_uncompressed_pkt uncom_ip_pkt; + + if (inst->domain == DECODER) { + com_ip_pkt.shdr.hdr.size = sizeof(struct hfi_session_empty_buffer_compressed_pkt); + com_ip_pkt.shdr.hdr.pkt_type = HFI_CMD_SESSION_EMPTY_BUFFER; + com_ip_pkt.shdr.session_id = inst->session_id; + com_ip_pkt.time_stamp_hi = upper_32_bits(buf->timestamp); + com_ip_pkt.time_stamp_lo = lower_32_bits(buf->timestamp); + com_ip_pkt.flags = buf->flags; + com_ip_pkt.mark_target = 0; + com_ip_pkt.mark_data = 0; + com_ip_pkt.offset = buf->data_offset; + com_ip_pkt.alloc_len = buf->buffer_size; + com_ip_pkt.filled_len = buf->data_size; + com_ip_pkt.input_tag = buf->index; + com_ip_pkt.packet_buffer = buf->device_addr; + return iris_hfi_queue_cmd_write(inst->core, &com_ip_pkt, + com_ip_pkt.shdr.hdr.size); + } else { + uncom_ip_pkt.shdr.hdr.size = + sizeof(struct hfi_session_empty_buffer_uncompressed_pkt); + uncom_ip_pkt.shdr.hdr.pkt_type = HFI_CMD_SESSION_EMPTY_BUFFER; + uncom_ip_pkt.shdr.session_id = inst->session_id; + uncom_ip_pkt.time_stamp_hi = upper_32_bits(buf->timestamp); + uncom_ip_pkt.time_stamp_lo = lower_32_bits(buf->timestamp); + uncom_ip_pkt.view_id = 0; + uncom_ip_pkt.flags = buf->flags; + uncom_ip_pkt.mark_target = 0; + uncom_ip_pkt.mark_data = 0; + uncom_ip_pkt.offset = buf->data_offset; + uncom_ip_pkt.alloc_len = buf->buffer_size; + uncom_ip_pkt.filled_len = buf->data_size; + uncom_ip_pkt.input_tag = buf->index; + uncom_ip_pkt.packet_buffer = buf->device_addr; + return iris_hfi_queue_cmd_write(inst->core, &uncom_ip_pkt, + uncom_ip_pkt.shdr.hdr.size); + } } static int iris_hfi_gen1_queue_output_buffer(struct iris_inst *inst, struct iris_buffer *buf) @@ -330,6 +383,8 @@ static int iris_hfi_gen1_session_queue_buffer(struct iris_inst *inst, struct iri case BUF_PERSIST: case BUF_BIN: case BUF_SCRATCH_1: + case BUF_SCRATCH_2: + case BUF_ARP: return iris_hfi_gen1_queue_internal_buffer(inst, buf); default: return -EINVAL; @@ -395,16 +450,31 @@ exit: static int iris_hfi_gen1_session_drain(struct iris_inst *inst, u32 plane) { - struct hfi_session_empty_buffer_compressed_pkt ip_pkt = {0}; + if (inst->domain == DECODER) { + struct hfi_session_empty_buffer_compressed_pkt ip_pkt = {0}; + + ip_pkt.shdr.hdr.size = sizeof(struct hfi_session_empty_buffer_compressed_pkt); + ip_pkt.shdr.hdr.pkt_type = HFI_CMD_SESSION_EMPTY_BUFFER; + ip_pkt.shdr.session_id = inst->session_id; + ip_pkt.flags = HFI_BUFFERFLAG_EOS; + ip_pkt.packet_buffer = 0xdeadb000; + + return iris_hfi_queue_cmd_write(inst->core, &ip_pkt, ip_pkt.shdr.hdr.size); + } + + if (inst->domain == ENCODER) { + struct hfi_session_empty_buffer_uncompressed_pkt ip_pkt = {0}; - ip_pkt.shdr.hdr.size = sizeof(struct hfi_session_empty_buffer_compressed_pkt); - ip_pkt.shdr.hdr.pkt_type = HFI_CMD_SESSION_EMPTY_BUFFER; - ip_pkt.shdr.session_id = inst->session_id; - ip_pkt.flags = HFI_BUFFERFLAG_EOS; - if (inst->codec == V4L2_PIX_FMT_VP9) + ip_pkt.shdr.hdr.size = sizeof(struct hfi_session_empty_buffer_uncompressed_pkt); + ip_pkt.shdr.hdr.pkt_type = HFI_CMD_SESSION_EMPTY_BUFFER; + ip_pkt.shdr.session_id = inst->session_id; + ip_pkt.flags = HFI_BUFFERFLAG_EOS; ip_pkt.packet_buffer = 0xdeadb000; - return iris_hfi_queue_cmd_write(inst->core, &ip_pkt, ip_pkt.shdr.hdr.size); + return iris_hfi_queue_cmd_write(inst->core, &ip_pkt, ip_pkt.shdr.hdr.size); + } + + return -EINVAL; } static int @@ -507,6 +577,114 @@ iris_hfi_gen1_packet_session_set_property(struct hfi_session_set_property_pkt *p packet->shdr.hdr.size += sizeof(u32) + sizeof(*wm); break; } + case HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT: { + struct hfi_profile_level *in = pdata, *pl = prop_data; + + pl->level = in->level; + pl->profile = in->profile; + if (pl->profile <= 0) + /* Profile not supported, falling back to high */ + pl->profile = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH; + + if (!pl->level) + /* Level not supported, falling back to 1 */ + pl->level = 1; + + packet->shdr.hdr.size += sizeof(u32) + sizeof(*pl); + break; + } + case HFI_PROPERTY_CONFIG_VENC_SYNC_FRAME_SEQUENCE_HEADER: { + struct hfi_enable *en = prop_data; + u32 *in = pdata; + + en->enable = *in; + packet->shdr.hdr.size += sizeof(u32) + sizeof(*en); + break; + } + case HFI_PROPERTY_CONFIG_VENC_TARGET_BITRATE: { + struct hfi_bitrate *brate = prop_data; + u32 *in = pdata; + + brate->bitrate = *in; + brate->layer_id = 0; + packet->shdr.hdr.size += sizeof(u32) + sizeof(*brate); + break; + } + case HFI_PROPERTY_PARAM_VENC_RATE_CONTROL: { + u32 *in = pdata; + + switch (*in) { + case HFI_RATE_CONTROL_OFF: + case HFI_RATE_CONTROL_CBR_CFR: + case HFI_RATE_CONTROL_CBR_VFR: + case HFI_RATE_CONTROL_VBR_CFR: + case HFI_RATE_CONTROL_VBR_VFR: + case HFI_RATE_CONTROL_CQ: + break; + default: + return -EINVAL; + } + + packet->data[1] = *in; + packet->shdr.hdr.size += sizeof(u32) * 2; + break; + } + case HFI_PROPERTY_PARAM_VENC_H264_ENTROPY_CONTROL: { + struct hfi_h264_entropy_control *entropy = prop_data; + u32 *in = pdata; + + entropy->entropy_mode = *in; + if (entropy->entropy_mode == HFI_H264_ENTROPY_CABAC) + entropy->cabac_model = HFI_H264_CABAC_MODEL_0; + packet->shdr.hdr.size += sizeof(u32) + sizeof(*entropy); + break; + } + case HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE_V2: { + struct hfi_quantization_range_v2 *range = prop_data; + struct hfi_quantization_range_v2 *in = pdata; + u32 min_qp, max_qp; + + min_qp = in->min_qp.qp_packed; + max_qp = in->max_qp.qp_packed; + + /* We'll be packing in the qp, so make sure we + * won't be losing data when masking + */ + if (min_qp > 0xff || max_qp > 0xff) + return -ERANGE; + + range->min_qp.layer_id = 0xFF; + range->max_qp.layer_id = 0xFF; + range->min_qp.qp_packed = (min_qp & 0xFF) | ((min_qp & 0xFF) << 8) | + ((min_qp & 0xFF) << 16); + range->max_qp.qp_packed = (max_qp & 0xFF) | ((max_qp & 0xFF) << 8) | + ((max_qp & 0xFF) << 16); + range->min_qp.enable = 7; + range->max_qp.enable = 7; + packet->shdr.hdr.size += sizeof(u32) + sizeof(*range); + break; + } + case HFI_PROPERTY_CONFIG_FRAME_RATE: { + struct hfi_framerate *frate = prop_data; + struct hfi_framerate *in = pdata; + + frate->buffer_type = in->buffer_type; + frate->framerate = in->framerate; + packet->shdr.hdr.size += sizeof(u32) + sizeof(*frate); + break; + } + case HFI_PROPERTY_PARAM_UNCOMPRESSED_PLANE_ACTUAL_INFO: { + struct hfi_uncompressed_plane_actual_info *plane_actual_info = prop_data; + struct hfi_uncompressed_plane_actual_info *in = pdata; + + plane_actual_info->buffer_type = in->buffer_type; + plane_actual_info->num_planes = in->num_planes; + plane_actual_info->plane_format[0] = in->plane_format[0]; + if (in->num_planes > 1) + plane_actual_info->plane_format[1] = in->plane_format[1]; + packet->shdr.hdr.size += sizeof(u32) + sizeof(*plane_actual_info); + break; + } default: return -EINVAL; } @@ -549,7 +727,7 @@ static int iris_hfi_gen1_session_set_property(struct iris_inst *inst, u32 packet return hfi_gen1_set_property(inst, packet_type, payload, payload_size); } -static int iris_hfi_gen1_set_resolution(struct iris_inst *inst) +static int iris_hfi_gen1_set_resolution(struct iris_inst *inst, u32 plane) { u32 ptype = HFI_PROPERTY_PARAM_FRAME_SIZE; struct hfi_framesize fs; @@ -564,14 +742,18 @@ static int iris_hfi_gen1_set_resolution(struct iris_inst *inst) if (ret) return ret; } - fs.buffer_type = HFI_BUFFER_OUTPUT2; + if (inst->domain == DECODER) + fs.buffer_type = HFI_BUFFER_OUTPUT2; + else + fs.buffer_type = HFI_BUFFER_OUTPUT; + fs.width = inst->fmt_dst->fmt.pix_mp.width; fs.height = inst->fmt_dst->fmt.pix_mp.height; return hfi_gen1_set_property(inst, ptype, &fs, sizeof(fs)); } -static int iris_hfi_gen1_decide_core(struct iris_inst *inst) +static int iris_hfi_gen1_decide_core(struct iris_inst *inst, u32 plane) { const u32 ptype = HFI_PROPERTY_CONFIG_VIDEOCORES_USAGE; struct hfi_videocores_usage_type cu; @@ -581,36 +763,45 @@ static int iris_hfi_gen1_decide_core(struct iris_inst *inst) return hfi_gen1_set_property(inst, ptype, &cu, sizeof(cu)); } -static int iris_hfi_gen1_set_raw_format(struct iris_inst *inst) +static int iris_hfi_gen1_set_raw_format(struct iris_inst *inst, u32 plane) { const u32 ptype = HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SELECT; - u32 pixelformat = inst->fmt_dst->fmt.pix_mp.pixelformat; struct hfi_uncompressed_format_select fmt; + u32 pixelformat; int ret; - if (iris_split_mode_enabled(inst)) { - fmt.buffer_type = HFI_BUFFER_OUTPUT; - fmt.format = pixelformat == V4L2_PIX_FMT_NV12 ? HFI_COLOR_FORMAT_NV12_UBWC : 0; + if (inst->domain == DECODER) { + pixelformat = inst->fmt_dst->fmt.pix_mp.pixelformat; + if (iris_split_mode_enabled(inst)) { + fmt.buffer_type = HFI_BUFFER_OUTPUT; + fmt.format = pixelformat == V4L2_PIX_FMT_NV12 ? + HFI_COLOR_FORMAT_NV12_UBWC : 0; - ret = hfi_gen1_set_property(inst, ptype, &fmt, sizeof(fmt)); - if (ret) - return ret; + ret = hfi_gen1_set_property(inst, ptype, &fmt, sizeof(fmt)); + if (ret) + return ret; - fmt.buffer_type = HFI_BUFFER_OUTPUT2; - fmt.format = pixelformat == V4L2_PIX_FMT_NV12 ? HFI_COLOR_FORMAT_NV12 : 0; + fmt.buffer_type = HFI_BUFFER_OUTPUT2; + fmt.format = pixelformat == V4L2_PIX_FMT_NV12 ? HFI_COLOR_FORMAT_NV12 : 0; - ret = hfi_gen1_set_property(inst, ptype, &fmt, sizeof(fmt)); + ret = hfi_gen1_set_property(inst, ptype, &fmt, sizeof(fmt)); + } else { + fmt.buffer_type = HFI_BUFFER_OUTPUT; + fmt.format = pixelformat == V4L2_PIX_FMT_NV12 ? HFI_COLOR_FORMAT_NV12 : 0; + + ret = hfi_gen1_set_property(inst, ptype, &fmt, sizeof(fmt)); + } } else { - fmt.buffer_type = HFI_BUFFER_OUTPUT; + pixelformat = inst->fmt_src->fmt.pix_mp.pixelformat; + fmt.buffer_type = HFI_BUFFER_INPUT; fmt.format = pixelformat == V4L2_PIX_FMT_NV12 ? HFI_COLOR_FORMAT_NV12 : 0; - ret = hfi_gen1_set_property(inst, ptype, &fmt, sizeof(fmt)); } return ret; } -static int iris_hfi_gen1_set_format_constraints(struct iris_inst *inst) +static int iris_hfi_gen1_set_format_constraints(struct iris_inst *inst, u32 plane) { const u32 ptype = HFI_PROPERTY_PARAM_UNCOMPRESSED_PLANE_ACTUAL_CONSTRAINTS_INFO; struct hfi_uncompressed_plane_actual_constraints_info pconstraint; @@ -630,7 +821,7 @@ static int iris_hfi_gen1_set_format_constraints(struct iris_inst *inst) return hfi_gen1_set_property(inst, ptype, &pconstraint, sizeof(pconstraint)); } -static int iris_hfi_gen1_set_num_bufs(struct iris_inst *inst) +static int iris_hfi_gen1_set_num_bufs(struct iris_inst *inst, u32 plane) { u32 ptype = HFI_PROPERTY_PARAM_BUFFER_COUNT_ACTUAL; struct hfi_buffer_count_actual buf_count; @@ -644,20 +835,28 @@ static int iris_hfi_gen1_set_num_bufs(struct iris_inst *inst) if (ret) return ret; - if (iris_split_mode_enabled(inst)) { - buf_count.type = HFI_BUFFER_OUTPUT; - buf_count.count_actual = VIDEO_MAX_FRAME; - buf_count.count_min_host = VIDEO_MAX_FRAME; + if (inst->domain == DECODER) { + if (iris_split_mode_enabled(inst)) { + buf_count.type = HFI_BUFFER_OUTPUT; + buf_count.count_actual = VIDEO_MAX_FRAME; + buf_count.count_min_host = VIDEO_MAX_FRAME; - ret = hfi_gen1_set_property(inst, ptype, &buf_count, sizeof(buf_count)); - if (ret) - return ret; + ret = hfi_gen1_set_property(inst, ptype, &buf_count, sizeof(buf_count)); + if (ret) + return ret; - buf_count.type = HFI_BUFFER_OUTPUT2; - buf_count.count_actual = iris_vpu_buf_count(inst, BUF_DPB); - buf_count.count_min_host = iris_vpu_buf_count(inst, BUF_DPB); + buf_count.type = HFI_BUFFER_OUTPUT2; + buf_count.count_actual = iris_vpu_buf_count(inst, BUF_DPB); + buf_count.count_min_host = iris_vpu_buf_count(inst, BUF_DPB); - ret = hfi_gen1_set_property(inst, ptype, &buf_count, sizeof(buf_count)); + ret = hfi_gen1_set_property(inst, ptype, &buf_count, sizeof(buf_count)); + } else { + buf_count.type = HFI_BUFFER_OUTPUT; + buf_count.count_actual = VIDEO_MAX_FRAME; + buf_count.count_min_host = VIDEO_MAX_FRAME; + + ret = hfi_gen1_set_property(inst, ptype, &buf_count, sizeof(buf_count)); + } } else { buf_count.type = HFI_BUFFER_OUTPUT; buf_count.count_actual = VIDEO_MAX_FRAME; @@ -669,7 +868,7 @@ static int iris_hfi_gen1_set_num_bufs(struct iris_inst *inst) return ret; } -static int iris_hfi_gen1_set_multistream(struct iris_inst *inst) +static int iris_hfi_gen1_set_multistream(struct iris_inst *inst, u32 plane) { u32 ptype = HFI_PROPERTY_PARAM_VDEC_MULTI_STREAM; struct hfi_multi_stream multi = {0}; @@ -704,7 +903,7 @@ static int iris_hfi_gen1_set_multistream(struct iris_inst *inst) return ret; } -static int iris_hfi_gen1_set_bufsize(struct iris_inst *inst) +static int iris_hfi_gen1_set_bufsize(struct iris_inst *inst, u32 plane) { const u32 ptype = HFI_PROPERTY_PARAM_BUFFER_SIZE_ACTUAL; struct hfi_buffer_size_actual bufsz; @@ -712,7 +911,7 @@ static int iris_hfi_gen1_set_bufsize(struct iris_inst *inst) if (iris_split_mode_enabled(inst)) { bufsz.type = HFI_BUFFER_OUTPUT; - bufsz.size = iris_vpu_buf_size(inst, BUF_DPB); + bufsz.size = inst->core->iris_platform_data->get_vpu_buffer_size(inst, BUF_DPB); ret = hfi_gen1_set_property(inst, ptype, &bufsz, sizeof(bufsz)); if (ret) @@ -739,14 +938,49 @@ static int iris_hfi_gen1_set_bufsize(struct iris_inst *inst) return ret; } +static int iris_hfi_gen1_set_frame_rate(struct iris_inst *inst, u32 plane) +{ + const u32 ptype = HFI_PROPERTY_CONFIG_FRAME_RATE; + struct hfi_framerate frate; + + if (V4L2_TYPE_IS_OUTPUT(plane)) + return 0; + + frate.buffer_type = HFI_BUFFER_OUTPUT; + frate.framerate = inst->frame_rate << 16; + + return hfi_gen1_set_property(inst, ptype, &frate, sizeof(frate)); +} + +static int iris_hfi_gen1_set_stride(struct iris_inst *inst, u32 plane) +{ + const u32 ptype = HFI_PROPERTY_PARAM_UNCOMPRESSED_PLANE_ACTUAL_INFO; + struct hfi_uncompressed_plane_actual_info plane_actual_info; + + plane_actual_info.buffer_type = HFI_BUFFER_INPUT; + plane_actual_info.num_planes = 2; + plane_actual_info.plane_format[0].actual_stride = + ALIGN(inst->fmt_src->fmt.pix_mp.width, 128); + plane_actual_info.plane_format[0].actual_plane_buffer_height = + ALIGN(inst->fmt_src->fmt.pix_mp.height, 32); + plane_actual_info.plane_format[1].actual_stride = + ALIGN(inst->fmt_src->fmt.pix_mp.width, 128); + plane_actual_info.plane_format[1].actual_plane_buffer_height = + (ALIGN(inst->fmt_src->fmt.pix_mp.height, 32)) / 2; + + return hfi_gen1_set_property(inst, ptype, &plane_actual_info, sizeof(plane_actual_info)); +} + static int iris_hfi_gen1_session_set_config_params(struct iris_inst *inst, u32 plane) { + struct iris_hfi_prop_type_handle const *handler = NULL; + u32 handler_size = 0; struct iris_core *core = inst->core; u32 config_params_size, i, j; const u32 *config_params; int ret; - static const struct iris_hfi_prop_type_handle prop_type_handle_inp_arr[] = { + static const struct iris_hfi_prop_type_handle vdec_prop_type_handle_inp_arr[] = { {HFI_PROPERTY_PARAM_FRAME_SIZE, iris_hfi_gen1_set_resolution}, {HFI_PROPERTY_CONFIG_VIDEOCORES_USAGE, @@ -763,7 +997,7 @@ static int iris_hfi_gen1_session_set_config_params(struct iris_inst *inst, u32 p iris_hfi_gen1_set_bufsize}, }; - static const struct iris_hfi_prop_type_handle prop_type_handle_out_arr[] = { + static const struct iris_hfi_prop_type_handle vdec_prop_type_handle_out_arr[] = { {HFI_PROPERTY_PARAM_FRAME_SIZE, iris_hfi_gen1_set_resolution}, {HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SELECT, @@ -778,29 +1012,43 @@ static int iris_hfi_gen1_session_set_config_params(struct iris_inst *inst, u32 p iris_hfi_gen1_set_bufsize}, }; - config_params = core->iris_platform_data->input_config_params_default; - config_params_size = core->iris_platform_data->input_config_params_default_size; - - if (V4L2_TYPE_IS_OUTPUT(plane)) { - for (i = 0; i < config_params_size; i++) { - for (j = 0; j < ARRAY_SIZE(prop_type_handle_inp_arr); j++) { - if (prop_type_handle_inp_arr[j].type == config_params[i]) { - ret = prop_type_handle_inp_arr[j].handle(inst); - if (ret) - return ret; - break; - } - } + static const struct iris_hfi_prop_type_handle venc_prop_type_handle_inp_arr[] = { + {HFI_PROPERTY_CONFIG_FRAME_RATE, + iris_hfi_gen1_set_frame_rate}, + {HFI_PROPERTY_PARAM_UNCOMPRESSED_PLANE_ACTUAL_INFO, + iris_hfi_gen1_set_stride}, + {HFI_PROPERTY_PARAM_FRAME_SIZE, + iris_hfi_gen1_set_resolution}, + {HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SELECT, + iris_hfi_gen1_set_raw_format}, + {HFI_PROPERTY_PARAM_BUFFER_COUNT_ACTUAL, + iris_hfi_gen1_set_num_bufs}, + }; + + if (inst->domain == DECODER) { + config_params = core->iris_platform_data->dec_input_config_params_default; + config_params_size = core->iris_platform_data->dec_input_config_params_default_size; + if (V4L2_TYPE_IS_OUTPUT(plane)) { + handler = vdec_prop_type_handle_inp_arr; + handler_size = ARRAY_SIZE(vdec_prop_type_handle_inp_arr); + } else if (V4L2_TYPE_IS_CAPTURE(plane)) { + handler = vdec_prop_type_handle_out_arr; + handler_size = ARRAY_SIZE(vdec_prop_type_handle_out_arr); } - } else if (V4L2_TYPE_IS_CAPTURE(plane)) { - for (i = 0; i < config_params_size; i++) { - for (j = 0; j < ARRAY_SIZE(prop_type_handle_out_arr); j++) { - if (prop_type_handle_out_arr[j].type == config_params[i]) { - ret = prop_type_handle_out_arr[j].handle(inst); - if (ret) - return ret; - break; - } + } else { + config_params = core->iris_platform_data->enc_input_config_params; + config_params_size = core->iris_platform_data->enc_input_config_params_size; + handler = venc_prop_type_handle_inp_arr; + handler_size = ARRAY_SIZE(venc_prop_type_handle_inp_arr); + } + + for (i = 0; i < config_params_size; i++) { + for (j = 0; j < handler_size; j++) { + if (handler[j].type == config_params[i]) { + ret = handler[j].handle(inst, plane); + if (ret) + return ret; + break; } } } diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h index d4d119ca98b0..42226ccee3d9 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h @@ -10,6 +10,7 @@ #define HFI_VIDEO_ARCH_OX 0x1 +#define HFI_SESSION_TYPE_ENC 1 #define HFI_SESSION_TYPE_DEC 2 #define HFI_VIDEO_CODEC_H264 0x00000002 @@ -73,18 +74,22 @@ #define HFI_BUFFER_INPUT 0x1 #define HFI_BUFFER_OUTPUT 0x2 #define HFI_BUFFER_OUTPUT2 0x3 +#define HFI_BUFFER_INTERNAL_PERSIST 0x4 #define HFI_BUFFER_INTERNAL_PERSIST_1 0x5 #define HFI_BUFFER_INTERNAL_SCRATCH 0x6 #define HFI_BUFFER_INTERNAL_SCRATCH_1 0x7 +#define HFI_BUFFER_INTERNAL_SCRATCH_2 0x8 #define HFI_PROPERTY_SYS_CODEC_POWER_PLANE_CTRL 0x5 #define HFI_PROPERTY_SYS_IMAGE_VERSION 0x6 #define HFI_PROPERTY_PARAM_FRAME_SIZE 0x1001 +#define HFI_PROPERTY_PARAM_UNCOMPRESSED_PLANE_ACTUAL_INFO 0x1002 #define HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SELECT 0x1003 #define HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT 0x1005 #define HFI_PROPERTY_PARAM_WORK_MODE 0x1015 #define HFI_PROPERTY_PARAM_WORK_ROUTE 0x1017 +#define HFI_PROPERTY_CONFIG_FRAME_RATE 0x2001 #define HFI_PROPERTY_CONFIG_VIDEOCORES_USAGE 0x2002 #define HFI_PROPERTY_PARAM_VDEC_MULTI_STREAM 0x1003001 @@ -111,15 +116,32 @@ #define HFI_MSG_SESSION_RELEASE_RESOURCES 0x22100a #define HFI_MSG_SESSION_RELEASE_BUFFERS 0x22100c -#define HFI_PICTURE_I 0x00000001 -#define HFI_PICTURE_P 0x00000002 -#define HFI_PICTURE_B 0x00000004 -#define HFI_PICTURE_IDR 0x00000008 +#define HFI_GEN1_PICTURE_I 0x00000001 +#define HFI_GEN1_PICTURE_P 0x00000002 +#define HFI_GEN1_PICTURE_B 0x00000004 +#define HFI_GEN1_PICTURE_IDR 0x00000008 #define HFI_FRAME_NOTCODED 0x7f002000 #define HFI_FRAME_YUV 0x7f004000 #define HFI_UNUSED_PICT 0x10000000 -#define HFI_BUFFERFLAG_DATACORRUPT 0x00000008 -#define HFI_BUFFERFLAG_DROP_FRAME 0x20000000 +#define HFI_BUFFERFLAG_DATACORRUPT 0x00000008 +#define HFI_BUFFERFLAG_DROP_FRAME 0x20000000 +#define HFI_RATE_CONTROL_OFF 0x1000001 +#define HFI_RATE_CONTROL_VBR_VFR 0x1000002 +#define HFI_RATE_CONTROL_VBR_CFR 0x1000003 +#define HFI_RATE_CONTROL_CBR_VFR 0x1000004 +#define HFI_RATE_CONTROL_CBR_CFR 0x1000005 +#define HFI_RATE_CONTROL_CQ 0x1000008 + +#define HFI_H264_ENTROPY_CAVLC 0x1 +#define HFI_H264_ENTROPY_CABAC 0x2 + +#define HFI_PROPERTY_PARAM_VENC_H264_ENTROPY_CONTROL 0x2005002 +#define HFI_PROPERTY_PARAM_VENC_H264_DEBLOCK_CONTROL 0x2005003 +#define HFI_PROPERTY_PARAM_VENC_RATE_CONTROL 0x2005004 +#define HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE_V2 0x2005009 +#define HFI_PROPERTY_PARAM_VENC_MAX_NUM_B_FRAMES 0x2005020 +#define HFI_PROPERTY_CONFIG_VENC_TARGET_BITRATE 0x2006001 +#define HFI_PROPERTY_CONFIG_VENC_SYNC_FRAME_SEQUENCE_HEADER 0x2006008 struct hfi_pkt_hdr { u32 size; @@ -194,6 +216,23 @@ struct hfi_session_empty_buffer_compressed_pkt { u32 data; }; +struct hfi_session_empty_buffer_uncompressed_pkt { + struct hfi_session_hdr_pkt shdr; + u32 view_id; + u32 time_stamp_hi; + u32 time_stamp_lo; + u32 flags; + u32 mark_target; + u32 mark_data; + u32 alloc_len; + u32 filled_len; + u32 offset; + u32 input_tag; + u32 packet_buffer; + u32 extradata_buffer; + u32 data; +}; + struct hfi_session_fill_buffer_pkt { struct hfi_session_hdr_pkt shdr; u32 stream_id; @@ -340,6 +379,17 @@ struct hfi_uncompressed_plane_actual_constraints_info { struct hfi_uncompressed_plane_constraints plane_format[2]; }; +struct hfi_uncompressed_plane_actual { + int actual_stride; + u32 actual_plane_buffer_height; +}; + +struct hfi_uncompressed_plane_actual_info { + u32 buffer_type; + u32 num_planes; + struct hfi_uncompressed_plane_actual plane_format[2]; +}; + struct hfi_buffer_count_actual { u32 type; u32 count_actual; @@ -367,6 +417,36 @@ struct hfi_buffer_requirements { u32 alignment; }; +struct hfi_bitrate { + u32 bitrate; + u32 layer_id; +}; + +#define HFI_H264_CABAC_MODEL_0 0x1 + +struct hfi_h264_entropy_control { + u32 entropy_mode; + u32 cabac_model; +}; + +struct hfi_quantization_v2 { + u32 qp_packed; + u32 layer_id; + u32 enable; + u32 reserved[3]; +}; + +struct hfi_quantization_range_v2 { + struct hfi_quantization_v2 min_qp; + struct hfi_quantization_v2 max_qp; + u32 reserved[4]; +}; + +struct hfi_framerate { + u32 buffer_type; + u32 framerate; +}; + struct hfi_event_data { u32 error; u32 height; @@ -398,6 +478,26 @@ struct hfi_msg_session_empty_buffer_done_pkt { u32 data[]; }; +struct hfi_msg_session_fbd_compressed_pkt { + struct hfi_session_hdr_pkt shdr; + u32 time_stamp_hi; + u32 time_stamp_lo; + u32 error_type; + u32 flags; + u32 mark_target; + u32 mark_data; + u32 stats; + u32 offset; + u32 alloc_len; + u32 filled_len; + u32 input_tag; + u32 output_tag; + u32 picture_type; + u32 packet_buffer; + u32 extradata_buffer; + u32 data[]; +}; + struct hfi_msg_session_fbd_uncompressed_plane0_pkt { struct hfi_session_hdr_pkt shdr; u32 stream_id; diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c index 8d1ce8a19a45..8e864c239e29 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c @@ -387,24 +387,43 @@ error: static void iris_hfi_gen1_session_ftb_done(struct iris_inst *inst, void *packet) { - struct hfi_msg_session_fbd_uncompressed_plane0_pkt *pkt = packet; + struct hfi_msg_session_fbd_uncompressed_plane0_pkt *uncom_pkt = packet; + struct hfi_msg_session_fbd_compressed_pkt *com_pkt = packet; struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; struct v4l2_m2m_buffer *m2m_buffer, *n; struct hfi_session_flush_pkt flush_pkt; - u32 timestamp_hi = pkt->time_stamp_hi; - u32 timestamp_lo = pkt->time_stamp_lo; + u32 timestamp_hi; + u32 timestamp_lo; struct iris_core *core = inst->core; - u32 filled_len = pkt->filled_len; - u32 pic_type = pkt->picture_type; - u32 output_tag = pkt->output_tag; + u32 filled_len; + u32 pic_type; + u32 output_tag; struct iris_buffer *buf, *iter; struct iris_buffers *buffers; - u32 hfi_flags = pkt->flags; - u32 offset = pkt->offset; + u32 hfi_flags; + u32 offset; u64 timestamp_us = 0; bool found = false; u32 flags = 0; + if (inst->domain == DECODER) { + timestamp_hi = uncom_pkt->time_stamp_hi; + timestamp_lo = uncom_pkt->time_stamp_lo; + filled_len = uncom_pkt->filled_len; + pic_type = uncom_pkt->picture_type; + output_tag = uncom_pkt->output_tag; + hfi_flags = uncom_pkt->flags; + offset = uncom_pkt->offset; + } else { + timestamp_hi = com_pkt->time_stamp_hi; + timestamp_lo = com_pkt->time_stamp_lo; + filled_len = com_pkt->filled_len; + pic_type = com_pkt->picture_type; + output_tag = com_pkt->output_tag; + hfi_flags = com_pkt->flags; + offset = com_pkt->offset; + } + if ((hfi_flags & HFI_BUFFERFLAG_EOS) && !filled_len) { reinit_completion(&inst->flush_completion); @@ -416,11 +435,10 @@ static void iris_hfi_gen1_session_ftb_done(struct iris_inst *inst, void *packet) inst->flush_responses_pending++; iris_inst_sub_state_change_drain_last(inst); - - return; } - if (iris_split_mode_enabled(inst) && pkt->stream_id == 0) { + if (iris_split_mode_enabled(inst) && inst->domain == DECODER && + uncom_pkt->stream_id == 0) { buffers = &inst->buffers[BUF_DPB]; if (!buffers) goto error; @@ -461,8 +479,14 @@ static void iris_hfi_gen1_session_ftb_done(struct iris_inst *inst, void *packet) timestamp_us = timestamp_hi; timestamp_us = (timestamp_us << 32) | timestamp_lo; } else { - if (pkt->stream_id == 1 && !inst->last_buffer_dequeued) { - if (iris_drc_pending(inst)) { + if (inst->domain == DECODER && uncom_pkt->stream_id == 1 && + !inst->last_buffer_dequeued) { + if (iris_drc_pending(inst) || iris_drain_pending(inst)) { + flags |= V4L2_BUF_FLAG_LAST; + inst->last_buffer_dequeued = true; + } + } else if (inst->domain == ENCODER) { + if (!inst->last_buffer_dequeued && iris_drain_pending(inst)) { flags |= V4L2_BUF_FLAG_LAST; inst->last_buffer_dequeued = true; } @@ -471,14 +495,14 @@ static void iris_hfi_gen1_session_ftb_done(struct iris_inst *inst, void *packet) buf->timestamp = timestamp_us; switch (pic_type) { - case HFI_PICTURE_IDR: - case HFI_PICTURE_I: + case HFI_GEN1_PICTURE_IDR: + case HFI_GEN1_PICTURE_I: flags |= V4L2_BUF_FLAG_KEYFRAME; break; - case HFI_PICTURE_P: + case HFI_GEN1_PICTURE_P: flags |= V4L2_BUF_FLAG_PFRAME; break; - case HFI_PICTURE_B: + case HFI_GEN1_PICTURE_B: flags |= V4L2_BUF_FLAG_BFRAME; break; case HFI_FRAME_NOTCODED: @@ -553,7 +577,7 @@ static const struct iris_hfi_gen1_response_pkt_info pkt_infos[] = { }, { .pkt = HFI_MSG_SESSION_FILL_BUFFER, - .pkt_sz = sizeof(struct hfi_msg_session_fbd_uncompressed_plane0_pkt), + .pkt_sz = sizeof(struct hfi_msg_session_fbd_compressed_pkt), }, { .pkt = HFI_MSG_SESSION_FLUSH, diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c index 7ca5ae13d62b..4ce71a142508 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c @@ -88,33 +88,63 @@ static int iris_hfi_gen2_sys_pc_prep(struct iris_core *core) return ret; } -static u32 iris_hfi_gen2_get_port(u32 plane) +static u32 iris_hfi_gen2_get_port(struct iris_inst *inst, u32 plane) { - switch (plane) { - case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: - return HFI_PORT_BITSTREAM; - case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: - return HFI_PORT_RAW; - default: - return HFI_PORT_NONE; + if (inst->domain == DECODER) { + switch (plane) { + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + return HFI_PORT_BITSTREAM; + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + return HFI_PORT_RAW; + default: + return HFI_PORT_NONE; + } + } else { + switch (plane) { + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + return HFI_PORT_RAW; + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + return HFI_PORT_BITSTREAM; + default: + return HFI_PORT_NONE; + } } } -static u32 iris_hfi_gen2_get_port_from_buf_type(enum iris_buffer_type buffer_type) +static u32 iris_hfi_gen2_get_port_from_buf_type(struct iris_inst *inst, + enum iris_buffer_type buffer_type) { - switch (buffer_type) { - case BUF_INPUT: - case BUF_BIN: - case BUF_COMV: - case BUF_NON_COMV: - case BUF_LINE: - return HFI_PORT_BITSTREAM; - case BUF_OUTPUT: - case BUF_DPB: - return HFI_PORT_RAW; - case BUF_PERSIST: - default: - return HFI_PORT_NONE; + if (inst->domain == DECODER) { + switch (buffer_type) { + case BUF_INPUT: + case BUF_BIN: + case BUF_COMV: + case BUF_NON_COMV: + case BUF_LINE: + return HFI_PORT_BITSTREAM; + case BUF_OUTPUT: + case BUF_DPB: + return HFI_PORT_RAW; + case BUF_PERSIST: + default: + return HFI_PORT_NONE; + } + } else { + switch (buffer_type) { + case BUF_INPUT: + case BUF_VPSS: + return HFI_PORT_RAW; + case BUF_OUTPUT: + case BUF_BIN: + case BUF_COMV: + case BUF_NON_COMV: + case BUF_LINE: + case BUF_SCRATCH_2: + return HFI_PORT_BITSTREAM; + case BUF_ARP: + default: + return HFI_PORT_NONE; + } } } @@ -136,34 +166,77 @@ static int iris_hfi_gen2_session_set_property(struct iris_inst *inst, u32 packet inst_hfi_gen2->packet->size); } -static int iris_hfi_gen2_set_bitstream_resolution(struct iris_inst *inst) +static int iris_hfi_gen2_set_raw_resolution(struct iris_inst *inst, u32 plane) { - struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); - u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); u32 resolution = inst->fmt_src->fmt.pix_mp.width << 16 | inst->fmt_src->fmt.pix_mp.height; + u32 port = iris_hfi_gen2_get_port(inst, plane); - inst_hfi_gen2->src_subcr_params.bitstream_resolution = resolution; + return iris_hfi_gen2_session_set_property(inst, + HFI_PROP_RAW_RESOLUTION, + HFI_HOST_FLAGS_NONE, + port, + HFI_PAYLOAD_32_PACKED, + &resolution, + sizeof(u32)); +} + +static int iris_hfi_gen2_set_bitstream_resolution(struct iris_inst *inst, u32 plane) +{ + struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); + u32 port = iris_hfi_gen2_get_port(inst, plane); + enum hfi_packet_payload_info payload_type; + u32 resolution, codec_align; + + if (inst->domain == DECODER) { + resolution = inst->fmt_src->fmt.pix_mp.width << 16 | + inst->fmt_src->fmt.pix_mp.height; + inst_hfi_gen2->src_subcr_params.bitstream_resolution = resolution; + payload_type = HFI_PAYLOAD_U32; + } else { + codec_align = inst->codec == V4L2_PIX_FMT_HEVC ? 32 : 16; + resolution = ALIGN(inst->fmt_dst->fmt.pix_mp.width, codec_align) << 16 | + ALIGN(inst->fmt_dst->fmt.pix_mp.height, codec_align); + inst_hfi_gen2->dst_subcr_params.bitstream_resolution = resolution; + payload_type = HFI_PAYLOAD_32_PACKED; + } return iris_hfi_gen2_session_set_property(inst, HFI_PROP_BITSTREAM_RESOLUTION, HFI_HOST_FLAGS_NONE, port, - HFI_PAYLOAD_U32, + payload_type, &resolution, sizeof(u32)); } -static int iris_hfi_gen2_set_crop_offsets(struct iris_inst *inst) +static int iris_hfi_gen2_set_crop_offsets(struct iris_inst *inst, u32 plane) { - u32 bottom_offset = (inst->fmt_src->fmt.pix_mp.height - inst->crop.height); - u32 right_offset = (inst->fmt_src->fmt.pix_mp.width - inst->crop.width); struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); - u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); - u32 left_offset = inst->crop.left; - u32 top_offset = inst->crop.top; + u32 port = iris_hfi_gen2_get_port(inst, plane); + u32 bottom_offset, right_offset; + u32 left_offset, top_offset; u32 payload[2]; + if (inst->domain == DECODER) { + if (V4L2_TYPE_IS_OUTPUT(plane)) { + bottom_offset = (inst->fmt_src->fmt.pix_mp.height - inst->crop.height); + right_offset = (inst->fmt_src->fmt.pix_mp.width - inst->crop.width); + left_offset = inst->crop.left; + top_offset = inst->crop.top; + } else { + bottom_offset = (inst->fmt_dst->fmt.pix_mp.height - inst->compose.height); + right_offset = (inst->fmt_dst->fmt.pix_mp.width - inst->compose.width); + left_offset = inst->compose.left; + top_offset = inst->compose.top; + } + } else { + bottom_offset = (inst->fmt_src->fmt.pix_mp.height - inst->crop.height); + right_offset = (inst->fmt_src->fmt.pix_mp.width - inst->crop.width); + left_offset = inst->crop.left; + top_offset = inst->crop.top; + } + payload[0] = FIELD_PREP(GENMASK(31, 16), left_offset) | top_offset; payload[1] = FIELD_PREP(GENMASK(31, 16), right_offset) | bottom_offset; inst_hfi_gen2->src_subcr_params.crop_offsets[0] = payload[0]; @@ -178,10 +251,10 @@ static int iris_hfi_gen2_set_crop_offsets(struct iris_inst *inst) sizeof(u64)); } -static int iris_hfi_gen2_set_bit_depth(struct iris_inst *inst) +static int iris_hfi_gen2_set_bit_depth(struct iris_inst *inst, u32 plane) { struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); - u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + u32 port = iris_hfi_gen2_get_port(inst, plane); u32 bitdepth = BIT_DEPTH_8; inst_hfi_gen2->src_subcr_params.bit_depth = bitdepth; @@ -195,10 +268,10 @@ static int iris_hfi_gen2_set_bit_depth(struct iris_inst *inst) sizeof(u32)); } -static int iris_hfi_gen2_set_coded_frames(struct iris_inst *inst) +static int iris_hfi_gen2_set_coded_frames(struct iris_inst *inst, u32 plane) { struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); - u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + u32 port = iris_hfi_gen2_get_port(inst, plane); u32 coded_frames = 0; if (inst->fw_caps[CODED_FRAMES].value == CODED_FRAMES_PROGRESSIVE) @@ -214,11 +287,11 @@ static int iris_hfi_gen2_set_coded_frames(struct iris_inst *inst) sizeof(u32)); } -static int iris_hfi_gen2_set_min_output_count(struct iris_inst *inst) +static int iris_hfi_gen2_set_min_output_count(struct iris_inst *inst, u32 plane) { struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); - u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); u32 min_output = inst->buffers[BUF_OUTPUT].min_count; + u32 port = iris_hfi_gen2_get_port(inst, plane); inst_hfi_gen2->src_subcr_params.fw_min_count = min_output; @@ -231,10 +304,10 @@ static int iris_hfi_gen2_set_min_output_count(struct iris_inst *inst) sizeof(u32)); } -static int iris_hfi_gen2_set_picture_order_count(struct iris_inst *inst) +static int iris_hfi_gen2_set_picture_order_count(struct iris_inst *inst, u32 plane) { struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); - u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + u32 port = iris_hfi_gen2_get_port(inst, plane); u32 poc = 0; inst_hfi_gen2->src_subcr_params.pic_order_cnt = poc; @@ -248,16 +321,16 @@ static int iris_hfi_gen2_set_picture_order_count(struct iris_inst *inst) sizeof(u32)); } -static int iris_hfi_gen2_set_colorspace(struct iris_inst *inst) +static int iris_hfi_gen2_set_colorspace(struct iris_inst *inst, u32 plane) { struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); - u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); struct v4l2_pix_format_mplane *pixmp = &inst->fmt_src->fmt.pix_mp; u32 video_signal_type_present_flag = 0, color_info; u32 matrix_coeff = HFI_MATRIX_COEFF_RESERVED; u32 video_format = UNSPECIFIED_COLOR_FORMAT; u32 full_range = V4L2_QUANTIZATION_DEFAULT; u32 transfer_char = HFI_TRANSFER_RESERVED; + u32 port = iris_hfi_gen2_get_port(inst, plane); u32 colour_description_present_flag = 0; u32 primaries = HFI_PRIMARIES_RESERVED; @@ -291,10 +364,10 @@ static int iris_hfi_gen2_set_colorspace(struct iris_inst *inst) sizeof(u32)); } -static int iris_hfi_gen2_set_profile(struct iris_inst *inst) +static int iris_hfi_gen2_set_profile(struct iris_inst *inst, u32 plane) { struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); - u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + u32 port = iris_hfi_gen2_get_port(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); u32 profile = 0; switch (inst->codec) { @@ -320,10 +393,10 @@ static int iris_hfi_gen2_set_profile(struct iris_inst *inst) sizeof(u32)); } -static int iris_hfi_gen2_set_level(struct iris_inst *inst) +static int iris_hfi_gen2_set_level(struct iris_inst *inst, u32 plane) { struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); - u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + u32 port = iris_hfi_gen2_get_port(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); u32 level = 0; switch (inst->codec) { @@ -349,33 +422,47 @@ static int iris_hfi_gen2_set_level(struct iris_inst *inst) sizeof(u32)); } -static int iris_hfi_gen2_set_colorformat(struct iris_inst *inst) +static int iris_hfi_gen2_set_colorformat(struct iris_inst *inst, u32 plane) { - u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + u32 port = iris_hfi_gen2_get_port(inst, plane); u32 hfi_colorformat, pixelformat; - pixelformat = inst->fmt_dst->fmt.pix_mp.pixelformat; - hfi_colorformat = pixelformat == V4L2_PIX_FMT_NV12 ? HFI_COLOR_FMT_NV12 : 0; + if (inst->domain == DECODER) { + pixelformat = inst->fmt_dst->fmt.pix_mp.pixelformat; + hfi_colorformat = pixelformat == V4L2_PIX_FMT_NV12 ? HFI_COLOR_FMT_NV12 : 0; + } else { + pixelformat = inst->fmt_src->fmt.pix_mp.pixelformat; + hfi_colorformat = pixelformat == V4L2_PIX_FMT_NV12 ? HFI_COLOR_FMT_NV12 : 0; + } return iris_hfi_gen2_session_set_property(inst, HFI_PROP_COLOR_FORMAT, HFI_HOST_FLAGS_NONE, port, - HFI_PAYLOAD_U32, + HFI_PAYLOAD_U32_ENUM, &hfi_colorformat, sizeof(u32)); } -static int iris_hfi_gen2_set_linear_stride_scanline(struct iris_inst *inst) +static int iris_hfi_gen2_set_linear_stride_scanline(struct iris_inst *inst, u32 plane) { - u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); - u32 pixelformat = inst->fmt_dst->fmt.pix_mp.pixelformat; - u32 scanline_y = inst->fmt_dst->fmt.pix_mp.height; - u32 stride_y = inst->fmt_dst->fmt.pix_mp.width; - u32 scanline_uv = scanline_y / 2; - u32 stride_uv = stride_y; + u32 pixelformat, stride_y, stride_uv, scanline_y, scanline_uv; + u32 port = iris_hfi_gen2_get_port(inst, plane); u32 payload[2]; + if (inst->domain == DECODER) { + pixelformat = inst->fmt_dst->fmt.pix_mp.pixelformat; + stride_y = inst->fmt_dst->fmt.pix_mp.width; + scanline_y = inst->fmt_dst->fmt.pix_mp.height; + } else { + pixelformat = inst->fmt_src->fmt.pix_mp.pixelformat; + stride_y = ALIGN(inst->fmt_src->fmt.pix_mp.width, 128); + scanline_y = ALIGN(inst->fmt_src->fmt.pix_mp.height, 32); + } + + stride_uv = stride_y; + scanline_uv = scanline_y / 2; + if (pixelformat != V4L2_PIX_FMT_NV12) return 0; @@ -386,15 +473,15 @@ static int iris_hfi_gen2_set_linear_stride_scanline(struct iris_inst *inst) HFI_PROP_LINEAR_STRIDE_SCANLINE, HFI_HOST_FLAGS_NONE, port, - HFI_PAYLOAD_U64, + HFI_PAYLOAD_64_PACKED, &payload, sizeof(u64)); } -static int iris_hfi_gen2_set_tier(struct iris_inst *inst) +static int iris_hfi_gen2_set_tier(struct iris_inst *inst, u32 plane) { struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); - u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + u32 port = iris_hfi_gen2_get_port(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); u32 tier = inst->fw_caps[TIER].value; inst_hfi_gen2->src_subcr_params.tier = tier; @@ -408,14 +495,29 @@ static int iris_hfi_gen2_set_tier(struct iris_inst *inst) sizeof(u32)); } +static int iris_hfi_gen2_set_frame_rate(struct iris_inst *inst, u32 plane) +{ + u32 port = iris_hfi_gen2_get_port(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + u32 frame_rate = inst->frame_rate << 16; + + return iris_hfi_gen2_session_set_property(inst, + HFI_PROP_FRAME_RATE, + HFI_HOST_FLAGS_NONE, + port, + HFI_PAYLOAD_Q16, + &frame_rate, + sizeof(u32)); +} + static int iris_hfi_gen2_session_set_config_params(struct iris_inst *inst, u32 plane) { - struct iris_core *core = inst->core; + const struct iris_platform_data *pdata = inst->core->iris_platform_data; u32 config_params_size = 0, i, j; const u32 *config_params = NULL; int ret; static const struct iris_hfi_prop_type_handle prop_type_handle_arr[] = { + {HFI_PROP_RAW_RESOLUTION, iris_hfi_gen2_set_raw_resolution }, {HFI_PROP_BITSTREAM_RESOLUTION, iris_hfi_gen2_set_bitstream_resolution }, {HFI_PROP_CROP_OFFSETS, iris_hfi_gen2_set_crop_offsets }, {HFI_PROP_CODED_FRAMES, iris_hfi_gen2_set_coded_frames }, @@ -428,29 +530,35 @@ static int iris_hfi_gen2_session_set_config_params(struct iris_inst *inst, u32 p {HFI_PROP_COLOR_FORMAT, iris_hfi_gen2_set_colorformat }, {HFI_PROP_LINEAR_STRIDE_SCANLINE, iris_hfi_gen2_set_linear_stride_scanline }, {HFI_PROP_TIER, iris_hfi_gen2_set_tier }, + {HFI_PROP_FRAME_RATE, iris_hfi_gen2_set_frame_rate }, }; - if (V4L2_TYPE_IS_OUTPUT(plane)) { - switch (inst->codec) { - case V4L2_PIX_FMT_H264: - config_params = core->iris_platform_data->input_config_params_default; - config_params_size = - core->iris_platform_data->input_config_params_default_size; - break; - case V4L2_PIX_FMT_HEVC: - config_params = core->iris_platform_data->input_config_params_hevc; - config_params_size = - core->iris_platform_data->input_config_params_hevc_size; - break; - case V4L2_PIX_FMT_VP9: - config_params = core->iris_platform_data->input_config_params_vp9; - config_params_size = - core->iris_platform_data->input_config_params_vp9_size; - break; + if (inst->domain == DECODER) { + if (V4L2_TYPE_IS_OUTPUT(plane)) { + if (inst->codec == V4L2_PIX_FMT_H264) { + config_params = pdata->dec_input_config_params_default; + config_params_size = pdata->dec_input_config_params_default_size; + } else if (inst->codec == V4L2_PIX_FMT_HEVC) { + config_params = pdata->dec_input_config_params_hevc; + config_params_size = pdata->dec_input_config_params_hevc_size; + } else if (inst->codec == V4L2_PIX_FMT_VP9) { + config_params = pdata->dec_input_config_params_vp9; + config_params_size = pdata->dec_input_config_params_vp9_size; + } else { + return -EINVAL; + } + } else { + config_params = pdata->dec_output_config_params; + config_params_size = pdata->dec_output_config_params_size; } } else { - config_params = core->iris_platform_data->output_config_params; - config_params_size = core->iris_platform_data->output_config_params_size; + if (V4L2_TYPE_IS_OUTPUT(plane)) { + config_params = pdata->enc_input_config_params; + config_params_size = pdata->enc_input_config_params_size; + } else { + config_params = pdata->enc_output_config_params; + config_params_size = pdata->enc_output_config_params_size; + } } if (!config_params || !config_params_size) @@ -459,7 +567,7 @@ static int iris_hfi_gen2_session_set_config_params(struct iris_inst *inst, u32 p for (i = 0; i < config_params_size; i++) { for (j = 0; j < ARRAY_SIZE(prop_type_handle_arr); j++) { if (prop_type_handle_arr[j].type == config_params[i]) { - ret = prop_type_handle_arr[j].handle(inst); + ret = prop_type_handle_arr[j].handle(inst, plane); if (ret) return ret; break; @@ -477,14 +585,19 @@ static int iris_hfi_gen2_session_set_codec(struct iris_inst *inst) switch (inst->codec) { case V4L2_PIX_FMT_H264: - codec = HFI_CODEC_DECODE_AVC; + if (inst->domain == ENCODER) + codec = HFI_CODEC_ENCODE_AVC; + else + codec = HFI_CODEC_DECODE_AVC; break; case V4L2_PIX_FMT_HEVC: - codec = HFI_CODEC_DECODE_HEVC; + if (inst->domain == ENCODER) + codec = HFI_CODEC_ENCODE_HEVC; + else + codec = HFI_CODEC_DECODE_HEVC; break; case V4L2_PIX_FMT_VP9: codec = HFI_CODEC_DECODE_VP9; - break; } iris_hfi_gen2_packet_session_property(inst, @@ -550,9 +663,11 @@ static int iris_hfi_gen2_session_open(struct iris_inst *inst) if (ret) goto fail_free_packet; - ret = iris_hfi_gen2_session_set_default_header(inst); - if (ret) - goto fail_free_packet; + if (inst->domain == DECODER) { + ret = iris_hfi_gen2_session_set_default_header(inst); + if (ret) + goto fail_free_packet; + } return 0; @@ -601,7 +716,7 @@ static int iris_hfi_gen2_session_subscribe_mode(struct iris_inst *inst, cmd, (HFI_HOST_FLAGS_RESPONSE_REQUIRED | HFI_HOST_FLAGS_INTR_REQUIRED), - iris_hfi_gen2_get_port(plane), + iris_hfi_gen2_get_port(inst, plane), inst->session_id, payload_type, payload, @@ -623,6 +738,9 @@ static int iris_hfi_gen2_subscribe_change_param(struct iris_inst *inst, u32 plan u32 hfi_port = 0, i; int ret; + if (inst->domain == ENCODER) + return 0; + if ((V4L2_TYPE_IS_OUTPUT(plane) && inst_hfi_gen2->ipsc_properties_set) || (V4L2_TYPE_IS_CAPTURE(plane) && inst_hfi_gen2->opsc_properties_set)) { dev_err(core->dev, "invalid plane\n"); @@ -631,19 +749,19 @@ static int iris_hfi_gen2_subscribe_change_param(struct iris_inst *inst, u32 plan switch (inst->codec) { case V4L2_PIX_FMT_H264: - change_param = core->iris_platform_data->input_config_params_default; + change_param = core->iris_platform_data->dec_input_config_params_default; change_param_size = - core->iris_platform_data->input_config_params_default_size; + core->iris_platform_data->dec_input_config_params_default_size; break; case V4L2_PIX_FMT_HEVC: - change_param = core->iris_platform_data->input_config_params_hevc; + change_param = core->iris_platform_data->dec_input_config_params_hevc; change_param_size = - core->iris_platform_data->input_config_params_hevc_size; + core->iris_platform_data->dec_input_config_params_hevc_size; break; case V4L2_PIX_FMT_VP9: - change_param = core->iris_platform_data->input_config_params_vp9; + change_param = core->iris_platform_data->dec_input_config_params_vp9; change_param_size = - core->iris_platform_data->input_config_params_vp9_size; + core->iris_platform_data->dec_input_config_params_vp9_size; break; } @@ -664,7 +782,7 @@ static int iris_hfi_gen2_subscribe_change_param(struct iris_inst *inst, u32 plan if (V4L2_TYPE_IS_OUTPUT(plane)) { inst_hfi_gen2->ipsc_properties_set = true; } else { - hfi_port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + hfi_port = iris_hfi_gen2_get_port(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); memcpy(&inst_hfi_gen2->dst_subcr_params, &inst_hfi_gen2->src_subcr_params, sizeof(inst_hfi_gen2->src_subcr_params)); @@ -759,6 +877,9 @@ static int iris_hfi_gen2_subscribe_property(struct iris_inst *inst, u32 plane) payload[0] = HFI_MODE_PROPERTY; + if (inst->domain == ENCODER) + return 0; + if (V4L2_TYPE_IS_OUTPUT(plane)) { subscribe_prop_size = core->iris_platform_data->dec_input_prop_size; subcribe_prop = core->iris_platform_data->dec_input_prop; @@ -810,7 +931,7 @@ static int iris_hfi_gen2_session_start(struct iris_inst *inst, u32 plane) HFI_CMD_START, (HFI_HOST_FLAGS_RESPONSE_REQUIRED | HFI_HOST_FLAGS_INTR_REQUIRED), - iris_hfi_gen2_get_port(plane), + iris_hfi_gen2_get_port(inst, plane), inst->session_id, HFI_PAYLOAD_NONE, NULL, @@ -832,7 +953,7 @@ static int iris_hfi_gen2_session_stop(struct iris_inst *inst, u32 plane) (HFI_HOST_FLAGS_RESPONSE_REQUIRED | HFI_HOST_FLAGS_INTR_REQUIRED | HFI_HOST_FLAGS_NON_DISCARDABLE), - iris_hfi_gen2_get_port(plane), + iris_hfi_gen2_get_port(inst, plane), inst->session_id, HFI_PAYLOAD_NONE, NULL, @@ -854,7 +975,7 @@ static int iris_hfi_gen2_session_pause(struct iris_inst *inst, u32 plane) HFI_CMD_PAUSE, (HFI_HOST_FLAGS_RESPONSE_REQUIRED | HFI_HOST_FLAGS_INTR_REQUIRED), - iris_hfi_gen2_get_port(plane), + iris_hfi_gen2_get_port(inst, plane), inst->session_id, HFI_PAYLOAD_NONE, NULL, @@ -873,7 +994,7 @@ static int iris_hfi_gen2_session_resume_drc(struct iris_inst *inst, u32 plane) HFI_CMD_RESUME, (HFI_HOST_FLAGS_RESPONSE_REQUIRED | HFI_HOST_FLAGS_INTR_REQUIRED), - iris_hfi_gen2_get_port(plane), + iris_hfi_gen2_get_port(inst, plane), inst->session_id, HFI_PAYLOAD_U32, &payload, @@ -892,7 +1013,7 @@ static int iris_hfi_gen2_session_resume_drain(struct iris_inst *inst, u32 plane) HFI_CMD_RESUME, (HFI_HOST_FLAGS_RESPONSE_REQUIRED | HFI_HOST_FLAGS_INTR_REQUIRED), - iris_hfi_gen2_get_port(plane), + iris_hfi_gen2_get_port(inst, plane), inst->session_id, HFI_PAYLOAD_U32, &payload, @@ -914,7 +1035,7 @@ static int iris_hfi_gen2_session_drain(struct iris_inst *inst, u32 plane) (HFI_HOST_FLAGS_RESPONSE_REQUIRED | HFI_HOST_FLAGS_INTR_REQUIRED | HFI_HOST_FLAGS_NON_DISCARDABLE), - iris_hfi_gen2_get_port(plane), + iris_hfi_gen2_get_port(inst, plane), inst->session_id, HFI_PAYLOAD_NONE, NULL, @@ -924,13 +1045,19 @@ static int iris_hfi_gen2_session_drain(struct iris_inst *inst, u32 plane) inst_hfi_gen2->packet->size); } -static u32 iris_hfi_gen2_buf_type_from_driver(enum iris_buffer_type buffer_type) +static u32 iris_hfi_gen2_buf_type_from_driver(u32 domain, enum iris_buffer_type buffer_type) { switch (buffer_type) { case BUF_INPUT: - return HFI_BUFFER_BITSTREAM; + if (domain == DECODER) + return HFI_BUFFER_BITSTREAM; + else + return HFI_BUFFER_RAW; case BUF_OUTPUT: - return HFI_BUFFER_RAW; + if (domain == DECODER) + return HFI_BUFFER_RAW; + else + return HFI_BUFFER_BITSTREAM; case BUF_BIN: return HFI_BUFFER_BIN; case BUF_COMV: @@ -940,9 +1067,14 @@ static u32 iris_hfi_gen2_buf_type_from_driver(enum iris_buffer_type buffer_type) case BUF_LINE: return HFI_BUFFER_LINE; case BUF_DPB: + case BUF_SCRATCH_2: return HFI_BUFFER_DPB; case BUF_PERSIST: return HFI_BUFFER_PERSIST; + case BUF_ARP: + return HFI_BUFFER_ARP; + case BUF_VPSS: + return HFI_BUFFER_VPSS; default: return 0; } @@ -965,16 +1097,17 @@ static int iris_set_num_comv(struct iris_inst *inst) &num_comv, sizeof(u32)); } -static void iris_hfi_gen2_get_buffer(struct iris_buffer *buffer, struct iris_hfi_buffer *buf) +static void iris_hfi_gen2_get_buffer(u32 domain, struct iris_buffer *buffer, + struct iris_hfi_buffer *buf) { memset(buf, 0, sizeof(*buf)); - buf->type = iris_hfi_gen2_buf_type_from_driver(buffer->type); + buf->type = iris_hfi_gen2_buf_type_from_driver(domain, buffer->type); buf->index = buffer->index; buf->base_address = buffer->device_addr; buf->addr_offset = 0; buf->buffer_size = buffer->buffer_size; - if (buffer->type == BUF_INPUT) + if (domain == DECODER && buffer->type == BUF_INPUT) buf->buffer_size = ALIGN(buffer->buffer_size, 256); buf->data_offset = buffer->data_offset; buf->data_size = buffer->data_size; @@ -991,14 +1124,14 @@ static int iris_hfi_gen2_session_queue_buffer(struct iris_inst *inst, struct iri u32 port; int ret; - iris_hfi_gen2_get_buffer(buffer, &hfi_buffer); + iris_hfi_gen2_get_buffer(inst->domain, buffer, &hfi_buffer); if (buffer->type == BUF_COMV) { ret = iris_set_num_comv(inst); if (ret) return ret; } - port = iris_hfi_gen2_get_port_from_buf_type(buffer->type); + port = iris_hfi_gen2_get_port_from_buf_type(inst, buffer->type); iris_hfi_gen2_packet_session_command(inst, HFI_CMD_BUFFER, HFI_HOST_FLAGS_INTR_REQUIRED, @@ -1018,9 +1151,9 @@ static int iris_hfi_gen2_session_release_buffer(struct iris_inst *inst, struct i struct iris_hfi_buffer hfi_buffer; u32 port; - iris_hfi_gen2_get_buffer(buffer, &hfi_buffer); + iris_hfi_gen2_get_buffer(inst->domain, buffer, &hfi_buffer); hfi_buffer.flags |= HFI_BUF_HOST_FLAG_RELEASE; - port = iris_hfi_gen2_get_port_from_buf_type(buffer->type); + port = iris_hfi_gen2_get_port_from_buf_type(inst, buffer->type); iris_hfi_gen2_packet_session_command(inst, HFI_CMD_BUFFER, diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h index 5f13dc11bea5..aa1f795f5626 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h @@ -49,18 +49,48 @@ #define HFI_PROP_TIER 0x03000109 #define HFI_PROP_STAGE 0x0300010a #define HFI_PROP_PIPE 0x0300010b +#define HFI_PROP_FRAME_RATE 0x0300010c #define HFI_PROP_LUMA_CHROMA_BIT_DEPTH 0x0300010f #define HFI_PROP_CODED_FRAMES 0x03000120 #define HFI_PROP_CABAC_SESSION 0x03000121 #define HFI_PROP_BUFFER_HOST_MAX_COUNT 0x03000123 #define HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT 0x03000124 #define HFI_PROP_PIC_ORDER_CNT_TYPE 0x03000128 + +enum hfi_rate_control { + HFI_RC_VBR_CFR = 0x00000000, + HFI_RC_CBR_CFR = 0x00000001, + HFI_RC_CQ = 0x00000002, + HFI_RC_OFF = 0x00000003, + HFI_RC_CBR_VFR = 0x00000004, + HFI_RC_LOSSLESS = 0x00000005, +}; + +#define HFI_PROP_RATE_CONTROL 0x0300012a +#define HFI_PROP_QP_PACKED 0x0300012e +#define HFI_PROP_MIN_QP_PACKED 0x0300012f +#define HFI_PROP_MAX_QP_PACKED 0x03000130 +#define HFI_PROP_TOTAL_BITRATE 0x0300013b +#define HFI_PROP_MAX_GOP_FRAMES 0x03000146 +#define HFI_PROP_MAX_B_FRAMES 0x03000147 #define HFI_PROP_QUALITY_MODE 0x03000148 + +enum hfi_seq_header_mode { + HFI_SEQ_HEADER_SEPERATE_FRAME = 0x00000001, + HFI_SEQ_HEADER_JOINED_WITH_1ST_FRAME = 0x00000002, + HFI_SEQ_HEADER_PREFIX_WITH_SYNC_FRAME = 0x00000004, + HFI_SEQ_HEADER_METADATA = 0x00000008, +}; + +#define HFI_PROP_SEQ_HEADER_MODE 0x03000149 #define HFI_PROP_SIGNAL_COLOR_INFO 0x03000155 #define HFI_PROP_PICTURE_TYPE 0x03000162 #define HFI_PROP_DEC_DEFAULT_HEADER 0x03000168 #define HFI_PROP_DEC_START_FROM_RAP_FRAME 0x03000169 #define HFI_PROP_NO_OUTPUT 0x0300016a +#define HFI_PROP_BUFFER_MARK 0x0300016c +#define HFI_PROP_RAW_RESOLUTION 0x03000178 +#define HFI_PROP_TOTAL_PEAK_BITRATE 0x0300017C #define HFI_PROP_COMV_BUFFER_COUNT 0x03000193 #define HFI_PROP_END 0x03FFFFFF @@ -111,13 +141,13 @@ enum hfi_codec_type { }; enum hfi_picture_type { - HFI_PICTURE_IDR = 0x00000001, - HFI_PICTURE_P = 0x00000002, - HFI_PICTURE_B = 0x00000004, - HFI_PICTURE_I = 0x00000008, - HFI_PICTURE_CRA = 0x00000010, - HFI_PICTURE_BLA = 0x00000020, - HFI_PICTURE_NOSHOW = 0x00000040, + HFI_GEN2_PICTURE_IDR = 0x00000001, + HFI_GEN2_PICTURE_P = 0x00000002, + HFI_GEN2_PICTURE_B = 0x00000004, + HFI_GEN2_PICTURE_I = 0x00000008, + HFI_GEN2_PICTURE_CRA = 0x00000010, + HFI_GEN2_PICTURE_BLA = 0x00000020, + HFI_GEN2_PICTURE_NOSHOW = 0x00000040, }; enum hfi_buffer_type { diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c index a8c30fc5c0d0..2f1f118eae4f 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c @@ -29,7 +29,8 @@ struct iris_hfi_gen2_packet_handle { int (*handle)(struct iris_inst *inst, struct iris_hfi_packet *pkt); }; -static u32 iris_hfi_gen2_buf_type_to_driver(enum hfi_buffer_type buf_type) +static u32 iris_hfi_gen2_buf_type_to_driver(struct iris_inst *inst, + enum hfi_buffer_type buf_type) { switch (buf_type) { case HFI_BUFFER_BITSTREAM: @@ -47,7 +48,10 @@ static u32 iris_hfi_gen2_buf_type_to_driver(enum hfi_buffer_type buf_type) case HFI_BUFFER_LINE: return BUF_LINE; case HFI_BUFFER_DPB: - return BUF_DPB; + if (inst->domain == DECODER) + return BUF_DPB; + else + return BUF_SCRATCH_2; case HFI_BUFFER_PERSIST: return BUF_PERSIST; default: @@ -87,17 +91,18 @@ static bool iris_hfi_gen2_is_valid_hfi_port(u32 port, u32 buffer_type) static int iris_hfi_gen2_get_driver_buffer_flags(struct iris_inst *inst, u32 hfi_flags) { - u32 keyframe = HFI_PICTURE_IDR | HFI_PICTURE_I | HFI_PICTURE_CRA | HFI_PICTURE_BLA; struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); + u32 keyframe = HFI_GEN2_PICTURE_IDR | HFI_GEN2_PICTURE_I | + HFI_GEN2_PICTURE_CRA | HFI_GEN2_PICTURE_BLA; u32 driver_flags = 0; - if (inst_hfi_gen2->hfi_frame_info.picture_type & HFI_PICTURE_NOSHOW) + if (inst_hfi_gen2->hfi_frame_info.picture_type & HFI_GEN2_PICTURE_NOSHOW) driver_flags |= V4L2_BUF_FLAG_ERROR; else if (inst_hfi_gen2->hfi_frame_info.picture_type & keyframe) driver_flags |= V4L2_BUF_FLAG_KEYFRAME; - else if (inst_hfi_gen2->hfi_frame_info.picture_type & HFI_PICTURE_P) + else if (inst_hfi_gen2->hfi_frame_info.picture_type & HFI_GEN2_PICTURE_P) driver_flags |= V4L2_BUF_FLAG_PFRAME; - else if (inst_hfi_gen2->hfi_frame_info.picture_type & HFI_PICTURE_B) + else if (inst_hfi_gen2->hfi_frame_info.picture_type & HFI_GEN2_PICTURE_B) driver_flags |= V4L2_BUF_FLAG_BFRAME; if (inst_hfi_gen2->hfi_frame_info.data_corrupt || inst_hfi_gen2->hfi_frame_info.overflow) @@ -420,11 +425,10 @@ static void iris_hfi_gen2_handle_dequeue_buffers(struct iris_inst *inst) static int iris_hfi_gen2_handle_release_internal_buffer(struct iris_inst *inst, struct iris_hfi_buffer *buffer) { - u32 buf_type = iris_hfi_gen2_buf_type_to_driver(buffer->type); + u32 buf_type = iris_hfi_gen2_buf_type_to_driver(inst, buffer->type); struct iris_buffers *buffers = &inst->buffers[buf_type]; struct iris_buffer *buf, *iter; bool found = false; - int ret = 0; list_for_each_entry(iter, &buffers->list, list) { if (iter->device_addr == buffer->base_address) { @@ -437,10 +441,8 @@ static int iris_hfi_gen2_handle_release_internal_buffer(struct iris_inst *inst, return -EINVAL; buf->attr &= ~BUF_ATTR_QUEUED; - if (buf->attr & BUF_ATTR_PENDING_RELEASE) - ret = iris_destroy_internal_buffer(inst, buf); - return ret; + return iris_destroy_internal_buffer(inst, buf); } static int iris_hfi_gen2_handle_session_stop(struct iris_inst *inst, @@ -478,12 +480,22 @@ static int iris_hfi_gen2_handle_session_buffer(struct iris_inst *inst, if (!iris_hfi_gen2_is_valid_hfi_port(pkt->port, buffer->type)) return 0; - if (buffer->type == HFI_BUFFER_BITSTREAM) - return iris_hfi_gen2_handle_input_buffer(inst, buffer); - else if (buffer->type == HFI_BUFFER_RAW) - return iris_hfi_gen2_handle_output_buffer(inst, buffer); - else - return iris_hfi_gen2_handle_release_internal_buffer(inst, buffer); + if (inst->domain == DECODER) { + if (buffer->type == HFI_BUFFER_BITSTREAM) + return iris_hfi_gen2_handle_input_buffer(inst, buffer); + else if (buffer->type == HFI_BUFFER_RAW) + return iris_hfi_gen2_handle_output_buffer(inst, buffer); + else + return iris_hfi_gen2_handle_release_internal_buffer(inst, buffer); + } else { + if (buffer->type == HFI_BUFFER_RAW) + return iris_hfi_gen2_handle_input_buffer(inst, buffer); + else if (buffer->type == HFI_BUFFER_BITSTREAM) + return iris_hfi_gen2_handle_output_buffer(inst, buffer); + else + return iris_hfi_gen2_handle_release_internal_buffer(inst, buffer); + } + return 0; } static int iris_hfi_gen2_handle_session_drain(struct iris_inst *inst, diff --git a/drivers/media/platform/qcom/iris/iris_instance.h b/drivers/media/platform/qcom/iris/iris_instance.h index 0e1f5799b72d..5982d7adefea 100644 --- a/drivers/media/platform/qcom/iris/iris_instance.h +++ b/drivers/media/platform/qcom/iris/iris_instance.h @@ -12,6 +12,20 @@ #include "iris_core.h" #include "iris_utils.h" +#define DEFAULT_WIDTH 320 +#define DEFAULT_HEIGHT 240 + +enum iris_fmt_type { + IRIS_FMT_H264, + IRIS_FMT_HEVC, + IRIS_FMT_VP9, +}; + +struct iris_fmt { + u32 pixfmt; + u32 type; +}; + /** * struct iris_inst - holds per video instance parameters * @@ -24,7 +38,9 @@ * @fmt_src: structure of v4l2_format for source * @fmt_dst: structure of v4l2_format for destination * @ctrl_handler: reference of v4l2 ctrl handler + * @domain: domain type: encoder or decoder * @crop: structure of crop info + * @compose: structure of compose info * @completion: structure of signal completions * @flush_completion: structure of signal completions for flush cmd * @flush_responses_pending: counter to track number of pending flush responses @@ -45,6 +61,9 @@ * @metadata_idx: index for metadata buffer * @codec: codec type * @last_buffer_dequeued: a flag to indicate that last buffer is sent by driver + * @frame_rate: frame rate of current instance + * @operating_rate: operating rate of current instance + * @hfi_rc_type: rate control type */ struct iris_inst { @@ -57,7 +76,9 @@ struct iris_inst { struct v4l2_format *fmt_src; struct v4l2_format *fmt_dst; struct v4l2_ctrl_handler ctrl_handler; + enum domain_type domain; struct iris_hfi_rect_desc crop; + struct iris_hfi_rect_desc compose; struct completion completion; struct completion flush_completion; u32 flush_responses_pending; @@ -78,6 +99,9 @@ struct iris_inst { u32 metadata_idx; u32 codec; bool last_buffer_dequeued; + u32 frame_rate; + u32 operating_rate; + u32 hfi_rc_type; }; #endif diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h index adafdce8a856..58d05e0a112e 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_common.h +++ b/drivers/media/platform/qcom/iris/iris_platform_common.h @@ -7,6 +7,7 @@ #define __IRIS_PLATFORM_COMMON_H__ #include <linux/bits.h> +#include "iris_buffer.h" struct iris_core; struct iris_inst; @@ -21,7 +22,13 @@ struct iris_inst; #define DEFAULT_MAX_HOST_BUF_COUNT 64 #define DEFAULT_MAX_HOST_BURST_BUF_COUNT 256 #define DEFAULT_FPS 30 -#define NUM_MBS_8K ((8192 * 4352) / 256) +#define MAXIMUM_FPS 480 +#define NUM_MBS_8K ((8192 * 4352) / 256) +#define MIN_QP_8BIT 1 +#define MAX_QP 51 +#define MAX_QP_HEVC 63 +#define DEFAULT_QP 20 +#define BITRATE_DEFAULT 20000000 enum stage_type { STAGE_1 = 1, @@ -38,11 +45,15 @@ extern struct iris_platform_data qcs8300_data; extern struct iris_platform_data sm8250_data; extern struct iris_platform_data sm8550_data; extern struct iris_platform_data sm8650_data; +extern struct iris_platform_data sm8750_data; enum platform_clk_type { - IRIS_AXI_CLK, + IRIS_AXI_CLK, /* AXI0 in case of platforms with multiple AXI clocks */ IRIS_CTRL_CLK, IRIS_HW_CLK, + IRIS_AXI1_CLK, + IRIS_CTRL_FREERUN_CLK, + IRIS_HW_FREERUN_CLK, }; struct platform_clk_data { @@ -78,6 +89,8 @@ struct platform_inst_caps { u32 mb_cycles_fw; u32 mb_cycles_fw_vpp; u32 num_comv; + u32 max_frame_rate; + u32 max_operating_rate; }; enum platform_inst_fw_cap_type { @@ -88,6 +101,7 @@ enum platform_inst_fw_cap_type { LEVEL_HEVC, LEVEL_VP9, INPUT_BUF_HOST_MAX_COUNT, + OUTPUT_BUF_HOST_MAX_COUNT, STAGE, PIPE, POC, @@ -95,6 +109,37 @@ enum platform_inst_fw_cap_type { BIT_DEPTH, RAP_FRAME, TIER, + HEADER_MODE, + PREPEND_SPSPPS_TO_IDR, + BITRATE, + BITRATE_PEAK, + BITRATE_MODE, + FRAME_SKIP_MODE, + FRAME_RC_ENABLE, + GOP_SIZE, + ENTROPY_MODE, + MIN_FRAME_QP_H264, + MIN_FRAME_QP_HEVC, + MAX_FRAME_QP_H264, + MAX_FRAME_QP_HEVC, + I_FRAME_MIN_QP_H264, + I_FRAME_MIN_QP_HEVC, + P_FRAME_MIN_QP_H264, + P_FRAME_MIN_QP_HEVC, + B_FRAME_MIN_QP_H264, + B_FRAME_MIN_QP_HEVC, + I_FRAME_MAX_QP_H264, + I_FRAME_MAX_QP_HEVC, + P_FRAME_MAX_QP_H264, + P_FRAME_MAX_QP_HEVC, + B_FRAME_MAX_QP_H264, + B_FRAME_MAX_QP_HEVC, + I_FRAME_QP_H264, + I_FRAME_QP_HEVC, + P_FRAME_QP_H264, + P_FRAME_QP_HEVC, + B_FRAME_QP_H264, + B_FRAME_QP_HEVC, INST_FW_CAP_MAX, }; @@ -149,6 +194,7 @@ struct iris_platform_data { void (*init_hfi_command_ops)(struct iris_core *core); void (*init_hfi_response_ops)(struct iris_core *core); struct iris_inst *(*get_instance)(void); + u32 (*get_vpu_buffer_size)(struct iris_inst *inst, enum iris_buffer_type buffer_type); const struct vpu_ops *vpu_ops; void (*set_preset_registers)(struct iris_core *core); const struct icc_info *icc_tbl; @@ -169,8 +215,10 @@ struct iris_platform_data { const char *fwname; u32 pas_id; struct platform_inst_caps *inst_caps; - struct platform_inst_fw_cap *inst_fw_caps; - u32 inst_fw_caps_size; + struct platform_inst_fw_cap *inst_fw_caps_dec; + u32 inst_fw_caps_dec_size; + struct platform_inst_fw_cap *inst_fw_caps_enc; + u32 inst_fw_caps_enc_size; struct tz_cp_config *tz_cp_config_data; u32 core_arch; u32 hw_response_timeout; @@ -179,14 +227,20 @@ struct iris_platform_data { u32 max_session_count; /* max number of macroblocks per frame supported */ u32 max_core_mbpf; - const u32 *input_config_params_default; - unsigned int input_config_params_default_size; - const u32 *input_config_params_hevc; - unsigned int input_config_params_hevc_size; - const u32 *input_config_params_vp9; - unsigned int input_config_params_vp9_size; - const u32 *output_config_params; - unsigned int output_config_params_size; + /* max number of macroblocks per second supported */ + u32 max_core_mbps; + const u32 *dec_input_config_params_default; + unsigned int dec_input_config_params_default_size; + const u32 *dec_input_config_params_hevc; + unsigned int dec_input_config_params_hevc_size; + const u32 *dec_input_config_params_vp9; + unsigned int dec_input_config_params_vp9_size; + const u32 *dec_output_config_params; + unsigned int dec_output_config_params_size; + const u32 *enc_input_config_params; + unsigned int enc_input_config_params_size; + const u32 *enc_output_config_params; + unsigned int enc_output_config_params_size; const u32 *dec_input_prop; unsigned int dec_input_prop_size; const u32 *dec_output_prop_avc; @@ -199,6 +253,10 @@ struct iris_platform_data { unsigned int dec_ip_int_buf_tbl_size; const u32 *dec_op_int_buf_tbl; unsigned int dec_op_int_buf_tbl_size; + const u32 *enc_ip_int_buf_tbl; + unsigned int enc_ip_int_buf_tbl_size; + const u32 *enc_op_int_buf_tbl; + unsigned int enc_op_int_buf_tbl_size; }; #endif diff --git a/drivers/media/platform/qcom/iris/iris_platform_gen2.c b/drivers/media/platform/qcom/iris/iris_platform_gen2.c index d3026b2bcb70..36d69cc73986 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_gen2.c +++ b/drivers/media/platform/qcom/iris/iris_platform_gen2.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2025 Linaro Ltd */ #include "iris_core.h" @@ -8,14 +9,17 @@ #include "iris_hfi_gen2.h" #include "iris_hfi_gen2_defines.h" #include "iris_platform_common.h" +#include "iris_vpu_buffer.h" #include "iris_vpu_common.h" #include "iris_platform_qcs8300.h" #include "iris_platform_sm8650.h" +#include "iris_platform_sm8750.h" #define VIDEO_ARCH_LX 1 +#define BITRATE_MAX 245000000 -static struct platform_inst_fw_cap inst_fw_cap_sm8550[] = { +static struct platform_inst_fw_cap inst_fw_cap_sm8550_dec[] = { { .cap_id = PROFILE_H264, .min = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE, @@ -199,6 +203,393 @@ static struct platform_inst_fw_cap inst_fw_cap_sm8550[] = { }, }; +static struct platform_inst_fw_cap inst_fw_cap_sm8550_enc[] = { + { + .cap_id = PROFILE_H264, + .min = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE, + .max = V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_HIGH), + .value = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH, + .hfi_id = HFI_PROP_PROFILE, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_profile, + }, + { + .cap_id = PROFILE_HEVC, + .min = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN, + .max = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN) | + BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE) | + BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10), + .value = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN, + .hfi_id = HFI_PROP_PROFILE, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_profile, + }, + { + .cap_id = LEVEL_H264, + .min = V4L2_MPEG_VIDEO_H264_LEVEL_1_0, + .max = V4L2_MPEG_VIDEO_H264_LEVEL_6_0, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1B) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_3) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_6_0), + .value = V4L2_MPEG_VIDEO_H264_LEVEL_5_0, + .hfi_id = HFI_PROP_LEVEL, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_level, + }, + { + .cap_id = LEVEL_HEVC, + .min = V4L2_MPEG_VIDEO_HEVC_LEVEL_1, + .max = V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5_2) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2), + .value = V4L2_MPEG_VIDEO_HEVC_LEVEL_5, + .hfi_id = HFI_PROP_LEVEL, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_level, + }, + { + .cap_id = STAGE, + .min = STAGE_1, + .max = STAGE_2, + .step_or_mask = 1, + .value = STAGE_2, + .hfi_id = HFI_PROP_STAGE, + .set = iris_set_stage, + }, + { + .cap_id = HEADER_MODE, + .min = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE, + .max = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE) | + BIT(V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME), + .value = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME, + .hfi_id = HFI_PROP_SEQ_HEADER_MODE, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_header_mode_gen2, + }, + { + .cap_id = PREPEND_SPSPPS_TO_IDR, + .min = 0, + .max = 1, + .step_or_mask = 1, + .value = 0, + }, + { + .cap_id = BITRATE, + .min = 1, + .max = BITRATE_MAX, + .step_or_mask = 1, + .value = BITRATE_DEFAULT, + .hfi_id = HFI_PROP_TOTAL_BITRATE, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + .set = iris_set_bitrate, + }, + { + .cap_id = BITRATE_PEAK, + .min = 1, + .max = BITRATE_MAX, + .step_or_mask = 1, + .value = BITRATE_DEFAULT, + .hfi_id = HFI_PROP_TOTAL_PEAK_BITRATE, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + .set = iris_set_peak_bitrate, + }, + { + .cap_id = BITRATE_MODE, + .min = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, + .max = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) | + BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_CBR), + .value = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, + .hfi_id = HFI_PROP_RATE_CONTROL, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_bitrate_mode_gen2, + }, + { + .cap_id = FRAME_SKIP_MODE, + .min = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED, + .max = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED) | + BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT) | + BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT), + .value = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + }, + { + .cap_id = FRAME_RC_ENABLE, + .min = 0, + .max = 1, + .step_or_mask = 1, + .value = 1, + }, + { + .cap_id = GOP_SIZE, + .min = 0, + .max = INT_MAX, + .step_or_mask = 1, + .value = 2 * DEFAULT_FPS - 1, + .hfi_id = HFI_PROP_MAX_GOP_FRAMES, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + .set = iris_set_u32, + }, + { + .cap_id = ENTROPY_MODE, + .min = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC, + .max = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC) | + BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC), + .value = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC, + .hfi_id = HFI_PROP_CABAC_SESSION, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_entropy_mode_gen2, + }, + { + .cap_id = MIN_FRAME_QP_H264, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MIN_QP_8BIT, + .hfi_id = HFI_PROP_MIN_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT, + .set = iris_set_min_qp, + }, + { + .cap_id = MIN_FRAME_QP_HEVC, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MIN_QP_8BIT, + .hfi_id = HFI_PROP_MIN_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT, + .set = iris_set_min_qp, + }, + { + .cap_id = MAX_FRAME_QP_H264, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MAX_QP, + .hfi_id = HFI_PROP_MAX_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT, + .set = iris_set_max_qp, + }, + { + .cap_id = MAX_FRAME_QP_HEVC, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MAX_QP, + .hfi_id = HFI_PROP_MAX_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT, + .set = iris_set_max_qp, + }, + { + .cap_id = I_FRAME_MIN_QP_H264, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MIN_QP_8BIT, + }, + { + .cap_id = I_FRAME_MIN_QP_HEVC, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MIN_QP_8BIT, + }, + { + .cap_id = P_FRAME_MIN_QP_H264, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MIN_QP_8BIT, + }, + { + .cap_id = P_FRAME_MIN_QP_HEVC, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MIN_QP_8BIT, + }, + { + .cap_id = B_FRAME_MIN_QP_H264, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MIN_QP_8BIT, + }, + { + .cap_id = B_FRAME_MIN_QP_HEVC, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MIN_QP_8BIT, + }, + { + .cap_id = I_FRAME_MAX_QP_H264, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MAX_QP, + }, + { + .cap_id = I_FRAME_MAX_QP_HEVC, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MAX_QP, + }, + { + .cap_id = P_FRAME_MAX_QP_H264, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MAX_QP, + }, + { + .cap_id = P_FRAME_MAX_QP_HEVC, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MAX_QP, + }, + { + .cap_id = B_FRAME_MAX_QP_H264, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MAX_QP, + }, + { + .cap_id = B_FRAME_MAX_QP_HEVC, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MAX_QP, + }, + { + .cap_id = I_FRAME_QP_H264, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = DEFAULT_QP, + .hfi_id = HFI_PROP_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + .set = iris_set_frame_qp, + }, + { + .cap_id = I_FRAME_QP_HEVC, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = DEFAULT_QP, + .hfi_id = HFI_PROP_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + .set = iris_set_frame_qp, + }, + { + .cap_id = P_FRAME_QP_H264, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = DEFAULT_QP, + .hfi_id = HFI_PROP_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + .set = iris_set_frame_qp, + }, + { + .cap_id = P_FRAME_QP_HEVC, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = DEFAULT_QP, + .hfi_id = HFI_PROP_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + .set = iris_set_frame_qp, + }, + { + .cap_id = B_FRAME_QP_H264, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = DEFAULT_QP, + .hfi_id = HFI_PROP_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + .set = iris_set_frame_qp, + }, + { + .cap_id = B_FRAME_QP_HEVC, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = DEFAULT_QP, + .hfi_id = HFI_PROP_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + .set = iris_set_frame_qp, + }, + { + .cap_id = INPUT_BUF_HOST_MAX_COUNT, + .min = DEFAULT_MAX_HOST_BUF_COUNT, + .max = DEFAULT_MAX_HOST_BURST_BUF_COUNT, + .step_or_mask = 1, + .value = DEFAULT_MAX_HOST_BUF_COUNT, + .hfi_id = HFI_PROP_BUFFER_HOST_MAX_COUNT, + .flags = CAP_FLAG_INPUT_PORT, + .set = iris_set_u32, + }, + { + .cap_id = OUTPUT_BUF_HOST_MAX_COUNT, + .min = DEFAULT_MAX_HOST_BUF_COUNT, + .max = DEFAULT_MAX_HOST_BURST_BUF_COUNT, + .step_or_mask = 1, + .value = DEFAULT_MAX_HOST_BUF_COUNT, + .hfi_id = HFI_PROP_BUFFER_HOST_MAX_COUNT, + .flags = CAP_FLAG_OUTPUT_PORT, + .set = iris_set_u32, + }, +}; + static struct platform_inst_caps platform_inst_cap_sm8550 = { .min_frame_width = 96, .max_frame_width = 8192, @@ -209,6 +600,8 @@ static struct platform_inst_caps platform_inst_cap_sm8550 = { .mb_cycles_fw = 489583, .mb_cycles_fw_vpp = 66234, .num_comv = 0, + .max_frame_rate = MAXIMUM_FPS, + .max_operating_rate = MAXIMUM_FPS, }; static void iris_set_sm8550_preset_registers(struct iris_core *core) @@ -289,11 +682,25 @@ static const u32 sm8550_vdec_input_config_param_vp9[] = { HFI_PROP_LEVEL, }; +static const u32 sm8550_venc_input_config_params[] = { + HFI_PROP_COLOR_FORMAT, + HFI_PROP_RAW_RESOLUTION, + HFI_PROP_CROP_OFFSETS, + HFI_PROP_LINEAR_STRIDE_SCANLINE, + HFI_PROP_SIGNAL_COLOR_INFO, +}; + static const u32 sm8550_vdec_output_config_params[] = { HFI_PROP_COLOR_FORMAT, HFI_PROP_LINEAR_STRIDE_SCANLINE, }; +static const u32 sm8550_venc_output_config_params[] = { + HFI_PROP_BITSTREAM_RESOLUTION, + HFI_PROP_CROP_OFFSETS, + HFI_PROP_FRAME_RATE, +}; + static const u32 sm8550_vdec_subscribe_input_properties[] = { HFI_PROP_NO_OUTPUT, }; @@ -322,10 +729,19 @@ static const u32 sm8550_dec_op_int_buf_tbl[] = { BUF_DPB, }; +static const u32 sm8550_enc_op_int_buf_tbl[] = { + BUF_BIN, + BUF_COMV, + BUF_NON_COMV, + BUF_LINE, + BUF_SCRATCH_2, +}; + struct iris_platform_data sm8550_data = { .get_instance = iris_hfi_gen2_get_instance, .init_hfi_command_ops = iris_hfi_gen2_command_ops_init, .init_hfi_response_ops = iris_hfi_gen2_response_ops_init, + .get_vpu_buffer_size = iris_vpu_buf_size, .vpu_ops = &iris_vpu3_ops, .set_preset_registers = iris_set_sm8550_preset_registers, .icc_tbl = sm8550_icc_table, @@ -345,8 +761,10 @@ struct iris_platform_data sm8550_data = { .fwname = "qcom/vpu/vpu30_p4.mbn", .pas_id = IRIS_PAS_ID, .inst_caps = &platform_inst_cap_sm8550, - .inst_fw_caps = inst_fw_cap_sm8550, - .inst_fw_caps_size = ARRAY_SIZE(inst_fw_cap_sm8550), + .inst_fw_caps_dec = inst_fw_cap_sm8550_dec, + .inst_fw_caps_dec_size = ARRAY_SIZE(inst_fw_cap_sm8550_dec), + .inst_fw_caps_enc = inst_fw_cap_sm8550_enc, + .inst_fw_caps_enc_size = ARRAY_SIZE(inst_fw_cap_sm8550_enc), .tz_cp_config_data = &tz_cp_config_sm8550, .core_arch = VIDEO_ARCH_LX, .hw_response_timeout = HW_RESPONSE_TIMEOUT_VALUE, @@ -354,22 +772,33 @@ struct iris_platform_data sm8550_data = { .num_vpp_pipe = 4, .max_session_count = 16, .max_core_mbpf = NUM_MBS_8K * 2, - .input_config_params_default = + .max_core_mbps = ((7680 * 4320) / 256) * 60, + .dec_input_config_params_default = sm8550_vdec_input_config_params_default, - .input_config_params_default_size = + .dec_input_config_params_default_size = ARRAY_SIZE(sm8550_vdec_input_config_params_default), - .input_config_params_hevc = + .dec_input_config_params_hevc = sm8550_vdec_input_config_param_hevc, - .input_config_params_hevc_size = + .dec_input_config_params_hevc_size = ARRAY_SIZE(sm8550_vdec_input_config_param_hevc), - .input_config_params_vp9 = + .dec_input_config_params_vp9 = sm8550_vdec_input_config_param_vp9, - .input_config_params_vp9_size = + .dec_input_config_params_vp9_size = ARRAY_SIZE(sm8550_vdec_input_config_param_vp9), - .output_config_params = + .dec_output_config_params = sm8550_vdec_output_config_params, - .output_config_params_size = + .dec_output_config_params_size = ARRAY_SIZE(sm8550_vdec_output_config_params), + + .enc_input_config_params = + sm8550_venc_input_config_params, + .enc_input_config_params_size = + ARRAY_SIZE(sm8550_venc_input_config_params), + .enc_output_config_params = + sm8550_venc_output_config_params, + .enc_output_config_params_size = + ARRAY_SIZE(sm8550_venc_output_config_params), + .dec_input_prop = sm8550_vdec_subscribe_input_properties, .dec_input_prop_size = ARRAY_SIZE(sm8550_vdec_subscribe_input_properties), .dec_output_prop_avc = sm8550_vdec_subscribe_output_properties_avc, @@ -386,6 +815,9 @@ struct iris_platform_data sm8550_data = { .dec_ip_int_buf_tbl_size = ARRAY_SIZE(sm8550_dec_ip_int_buf_tbl), .dec_op_int_buf_tbl = sm8550_dec_op_int_buf_tbl, .dec_op_int_buf_tbl_size = ARRAY_SIZE(sm8550_dec_op_int_buf_tbl), + + .enc_op_int_buf_tbl = sm8550_enc_op_int_buf_tbl, + .enc_op_int_buf_tbl_size = ARRAY_SIZE(sm8550_enc_op_int_buf_tbl), }; /* @@ -399,6 +831,7 @@ struct iris_platform_data sm8650_data = { .get_instance = iris_hfi_gen2_get_instance, .init_hfi_command_ops = iris_hfi_gen2_command_ops_init, .init_hfi_response_ops = iris_hfi_gen2_response_ops_init, + .get_vpu_buffer_size = iris_vpu33_buf_size, .vpu_ops = &iris_vpu33_ops, .set_preset_registers = iris_set_sm8550_preset_registers, .icc_tbl = sm8550_icc_table, @@ -420,8 +853,10 @@ struct iris_platform_data sm8650_data = { .fwname = "qcom/vpu/vpu33_p4.mbn", .pas_id = IRIS_PAS_ID, .inst_caps = &platform_inst_cap_sm8550, - .inst_fw_caps = inst_fw_cap_sm8550, - .inst_fw_caps_size = ARRAY_SIZE(inst_fw_cap_sm8550), + .inst_fw_caps_dec = inst_fw_cap_sm8550_dec, + .inst_fw_caps_dec_size = ARRAY_SIZE(inst_fw_cap_sm8550_dec), + .inst_fw_caps_enc = inst_fw_cap_sm8550_enc, + .inst_fw_caps_enc_size = ARRAY_SIZE(inst_fw_cap_sm8550_enc), .tz_cp_config_data = &tz_cp_config_sm8550, .core_arch = VIDEO_ARCH_LX, .hw_response_timeout = HW_RESPONSE_TIMEOUT_VALUE, @@ -429,22 +864,33 @@ struct iris_platform_data sm8650_data = { .num_vpp_pipe = 4, .max_session_count = 16, .max_core_mbpf = NUM_MBS_8K * 2, - .input_config_params_default = + .max_core_mbps = ((7680 * 4320) / 256) * 60, + .dec_input_config_params_default = sm8550_vdec_input_config_params_default, - .input_config_params_default_size = + .dec_input_config_params_default_size = ARRAY_SIZE(sm8550_vdec_input_config_params_default), - .input_config_params_hevc = + .dec_input_config_params_hevc = sm8550_vdec_input_config_param_hevc, - .input_config_params_hevc_size = + .dec_input_config_params_hevc_size = ARRAY_SIZE(sm8550_vdec_input_config_param_hevc), - .input_config_params_vp9 = + .dec_input_config_params_vp9 = sm8550_vdec_input_config_param_vp9, - .input_config_params_vp9_size = + .dec_input_config_params_vp9_size = ARRAY_SIZE(sm8550_vdec_input_config_param_vp9), - .output_config_params = + .dec_output_config_params = sm8550_vdec_output_config_params, - .output_config_params_size = + .dec_output_config_params_size = ARRAY_SIZE(sm8550_vdec_output_config_params), + + .enc_input_config_params = + sm8550_venc_input_config_params, + .enc_input_config_params_size = + ARRAY_SIZE(sm8550_venc_input_config_params), + .enc_output_config_params = + sm8550_venc_output_config_params, + .enc_output_config_params_size = + ARRAY_SIZE(sm8550_venc_output_config_params), + .dec_input_prop = sm8550_vdec_subscribe_input_properties, .dec_input_prop_size = ARRAY_SIZE(sm8550_vdec_subscribe_input_properties), .dec_output_prop_avc = sm8550_vdec_subscribe_output_properties_avc, @@ -461,6 +907,90 @@ struct iris_platform_data sm8650_data = { .dec_ip_int_buf_tbl_size = ARRAY_SIZE(sm8550_dec_ip_int_buf_tbl), .dec_op_int_buf_tbl = sm8550_dec_op_int_buf_tbl, .dec_op_int_buf_tbl_size = ARRAY_SIZE(sm8550_dec_op_int_buf_tbl), + + .enc_op_int_buf_tbl = sm8550_enc_op_int_buf_tbl, + .enc_op_int_buf_tbl_size = ARRAY_SIZE(sm8550_enc_op_int_buf_tbl), +}; + +struct iris_platform_data sm8750_data = { + .get_instance = iris_hfi_gen2_get_instance, + .init_hfi_command_ops = iris_hfi_gen2_command_ops_init, + .init_hfi_response_ops = iris_hfi_gen2_response_ops_init, + .vpu_ops = &iris_vpu35_ops, + .set_preset_registers = iris_set_sm8550_preset_registers, + .icc_tbl = sm8550_icc_table, + .icc_tbl_size = ARRAY_SIZE(sm8550_icc_table), + .clk_rst_tbl = sm8750_clk_reset_table, + .clk_rst_tbl_size = ARRAY_SIZE(sm8750_clk_reset_table), + .bw_tbl_dec = sm8550_bw_table_dec, + .bw_tbl_dec_size = ARRAY_SIZE(sm8550_bw_table_dec), + .pmdomain_tbl = sm8550_pmdomain_table, + .pmdomain_tbl_size = ARRAY_SIZE(sm8550_pmdomain_table), + .opp_pd_tbl = sm8550_opp_pd_table, + .opp_pd_tbl_size = ARRAY_SIZE(sm8550_opp_pd_table), + .clk_tbl = sm8750_clk_table, + .clk_tbl_size = ARRAY_SIZE(sm8750_clk_table), + /* Upper bound of DMA address range */ + .dma_mask = 0xe0000000 - 1, + .fwname = "qcom/vpu/vpu35_p4.mbn", + .pas_id = IRIS_PAS_ID, + .inst_caps = &platform_inst_cap_sm8550, + .inst_fw_caps_dec = inst_fw_cap_sm8550_dec, + .inst_fw_caps_dec_size = ARRAY_SIZE(inst_fw_cap_sm8550_dec), + .inst_fw_caps_enc = inst_fw_cap_sm8550_enc, + .inst_fw_caps_enc_size = ARRAY_SIZE(inst_fw_cap_sm8550_enc), + .tz_cp_config_data = &tz_cp_config_sm8550, + .core_arch = VIDEO_ARCH_LX, + .hw_response_timeout = HW_RESPONSE_TIMEOUT_VALUE, + .ubwc_config = &ubwc_config_sm8550, + .num_vpp_pipe = 4, + .max_session_count = 16, + .max_core_mbpf = NUM_MBS_8K * 2, + .dec_input_config_params_default = + sm8550_vdec_input_config_params_default, + .dec_input_config_params_default_size = + ARRAY_SIZE(sm8550_vdec_input_config_params_default), + .dec_input_config_params_hevc = + sm8550_vdec_input_config_param_hevc, + .dec_input_config_params_hevc_size = + ARRAY_SIZE(sm8550_vdec_input_config_param_hevc), + .dec_input_config_params_vp9 = + sm8550_vdec_input_config_param_vp9, + .dec_input_config_params_vp9_size = + ARRAY_SIZE(sm8550_vdec_input_config_param_vp9), + .dec_output_config_params = + sm8550_vdec_output_config_params, + .dec_output_config_params_size = + ARRAY_SIZE(sm8550_vdec_output_config_params), + + .enc_input_config_params = + sm8550_venc_input_config_params, + .enc_input_config_params_size = + ARRAY_SIZE(sm8550_venc_input_config_params), + .enc_output_config_params = + sm8550_venc_output_config_params, + .enc_output_config_params_size = + ARRAY_SIZE(sm8550_venc_output_config_params), + + .dec_input_prop = sm8550_vdec_subscribe_input_properties, + .dec_input_prop_size = ARRAY_SIZE(sm8550_vdec_subscribe_input_properties), + .dec_output_prop_avc = sm8550_vdec_subscribe_output_properties_avc, + .dec_output_prop_avc_size = + ARRAY_SIZE(sm8550_vdec_subscribe_output_properties_avc), + .dec_output_prop_hevc = sm8550_vdec_subscribe_output_properties_hevc, + .dec_output_prop_hevc_size = + ARRAY_SIZE(sm8550_vdec_subscribe_output_properties_hevc), + .dec_output_prop_vp9 = sm8550_vdec_subscribe_output_properties_vp9, + .dec_output_prop_vp9_size = + ARRAY_SIZE(sm8550_vdec_subscribe_output_properties_vp9), + + .dec_ip_int_buf_tbl = sm8550_dec_ip_int_buf_tbl, + .dec_ip_int_buf_tbl_size = ARRAY_SIZE(sm8550_dec_ip_int_buf_tbl), + .dec_op_int_buf_tbl = sm8550_dec_op_int_buf_tbl, + .dec_op_int_buf_tbl_size = ARRAY_SIZE(sm8550_dec_op_int_buf_tbl), + + .enc_op_int_buf_tbl = sm8550_enc_op_int_buf_tbl, + .enc_op_int_buf_tbl_size = ARRAY_SIZE(sm8550_enc_op_int_buf_tbl), }; /* @@ -472,6 +1002,7 @@ struct iris_platform_data qcs8300_data = { .get_instance = iris_hfi_gen2_get_instance, .init_hfi_command_ops = iris_hfi_gen2_command_ops_init, .init_hfi_response_ops = iris_hfi_gen2_response_ops_init, + .get_vpu_buffer_size = iris_vpu_buf_size, .vpu_ops = &iris_vpu3_ops, .set_preset_registers = iris_set_sm8550_preset_registers, .icc_tbl = sm8550_icc_table, @@ -491,8 +1022,10 @@ struct iris_platform_data qcs8300_data = { .fwname = "qcom/vpu/vpu30_p4_s6.mbn", .pas_id = IRIS_PAS_ID, .inst_caps = &platform_inst_cap_qcs8300, - .inst_fw_caps = inst_fw_cap_qcs8300, - .inst_fw_caps_size = ARRAY_SIZE(inst_fw_cap_qcs8300), + .inst_fw_caps_dec = inst_fw_cap_qcs8300_dec, + .inst_fw_caps_dec_size = ARRAY_SIZE(inst_fw_cap_qcs8300_dec), + .inst_fw_caps_enc = inst_fw_cap_qcs8300_enc, + .inst_fw_caps_enc_size = ARRAY_SIZE(inst_fw_cap_qcs8300_enc), .tz_cp_config_data = &tz_cp_config_sm8550, .core_arch = VIDEO_ARCH_LX, .hw_response_timeout = HW_RESPONSE_TIMEOUT_VALUE, @@ -500,22 +1033,33 @@ struct iris_platform_data qcs8300_data = { .num_vpp_pipe = 2, .max_session_count = 16, .max_core_mbpf = ((4096 * 2176) / 256) * 4, - .input_config_params_default = + .max_core_mbps = (((3840 * 2176) / 256) * 120), + .dec_input_config_params_default = sm8550_vdec_input_config_params_default, - .input_config_params_default_size = + .dec_input_config_params_default_size = ARRAY_SIZE(sm8550_vdec_input_config_params_default), - .input_config_params_hevc = + .dec_input_config_params_hevc = sm8550_vdec_input_config_param_hevc, - .input_config_params_hevc_size = + .dec_input_config_params_hevc_size = ARRAY_SIZE(sm8550_vdec_input_config_param_hevc), - .input_config_params_vp9 = + .dec_input_config_params_vp9 = sm8550_vdec_input_config_param_vp9, - .input_config_params_vp9_size = + .dec_input_config_params_vp9_size = ARRAY_SIZE(sm8550_vdec_input_config_param_vp9), - .output_config_params = + .dec_output_config_params = sm8550_vdec_output_config_params, - .output_config_params_size = + .dec_output_config_params_size = ARRAY_SIZE(sm8550_vdec_output_config_params), + + .enc_input_config_params = + sm8550_venc_input_config_params, + .enc_input_config_params_size = + ARRAY_SIZE(sm8550_venc_input_config_params), + .enc_output_config_params = + sm8550_venc_output_config_params, + .enc_output_config_params_size = + ARRAY_SIZE(sm8550_venc_output_config_params), + .dec_input_prop = sm8550_vdec_subscribe_input_properties, .dec_input_prop_size = ARRAY_SIZE(sm8550_vdec_subscribe_input_properties), .dec_output_prop_avc = sm8550_vdec_subscribe_output_properties_avc, @@ -532,4 +1076,7 @@ struct iris_platform_data qcs8300_data = { .dec_ip_int_buf_tbl_size = ARRAY_SIZE(sm8550_dec_ip_int_buf_tbl), .dec_op_int_buf_tbl = sm8550_dec_op_int_buf_tbl, .dec_op_int_buf_tbl_size = ARRAY_SIZE(sm8550_dec_op_int_buf_tbl), + + .enc_op_int_buf_tbl = sm8550_enc_op_int_buf_tbl, + .enc_op_int_buf_tbl_size = ARRAY_SIZE(sm8550_enc_op_int_buf_tbl), }; diff --git a/drivers/media/platform/qcom/iris/iris_platform_qcs8300.h b/drivers/media/platform/qcom/iris/iris_platform_qcs8300.h index a8d66ed388a3..35ea0efade73 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_qcs8300.h +++ b/drivers/media/platform/qcom/iris/iris_platform_qcs8300.h @@ -3,7 +3,9 @@ * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved. */ -static struct platform_inst_fw_cap inst_fw_cap_qcs8300[] = { +#define BITRATE_MAX 245000000 + +static struct platform_inst_fw_cap inst_fw_cap_qcs8300_dec[] = { { .cap_id = PROFILE_H264, .min = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE, @@ -187,6 +189,352 @@ static struct platform_inst_fw_cap inst_fw_cap_qcs8300[] = { }, }; +static struct platform_inst_fw_cap inst_fw_cap_qcs8300_enc[] = { + { + .cap_id = PROFILE_H264, + .min = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE, + .max = V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_HIGH), + .value = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH, + .hfi_id = HFI_PROP_PROFILE, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + }, + { + .cap_id = PROFILE_HEVC, + .min = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN, + .max = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN) | + BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE) | + BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10), + .value = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN, + .hfi_id = HFI_PROP_PROFILE, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + }, + { + .cap_id = LEVEL_H264, + .min = V4L2_MPEG_VIDEO_H264_LEVEL_1_0, + .max = V4L2_MPEG_VIDEO_H264_LEVEL_6_0, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1B) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_3) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_6_0), + .value = V4L2_MPEG_VIDEO_H264_LEVEL_5_0, + .hfi_id = HFI_PROP_LEVEL, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + }, + { + .cap_id = LEVEL_HEVC, + .min = V4L2_MPEG_VIDEO_HEVC_LEVEL_1, + .max = V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5_2) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2), + .value = V4L2_MPEG_VIDEO_HEVC_LEVEL_5, + .hfi_id = HFI_PROP_LEVEL, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + }, + { + .cap_id = STAGE, + .min = STAGE_1, + .max = STAGE_2, + .step_or_mask = 1, + .value = STAGE_2, + .hfi_id = HFI_PROP_STAGE, + }, + { + .cap_id = HEADER_MODE, + .min = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE, + .max = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE) | + BIT(V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME), + .value = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME, + .hfi_id = HFI_PROP_SEQ_HEADER_MODE, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + }, + { + .cap_id = PREPEND_SPSPPS_TO_IDR, + .min = 0, + .max = 1, + .step_or_mask = 1, + .value = 0, + }, + { + .cap_id = BITRATE, + .min = 1, + .max = BITRATE_MAX, + .step_or_mask = 1, + .value = BITRATE_DEFAULT, + .hfi_id = HFI_PROP_TOTAL_BITRATE, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + }, + { + .cap_id = BITRATE_PEAK, + .min = 1, + .max = BITRATE_MAX, + .step_or_mask = 1, + .value = BITRATE_DEFAULT, + .hfi_id = HFI_PROP_TOTAL_PEAK_BITRATE, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + }, + { + .cap_id = BITRATE_MODE, + .min = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, + .max = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) | + BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_CBR), + .value = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, + .hfi_id = HFI_PROP_RATE_CONTROL, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + }, + { + .cap_id = FRAME_SKIP_MODE, + .min = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED, + .max = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED) | + BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT) | + BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT), + .value = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + }, + { + .cap_id = FRAME_RC_ENABLE, + .min = 0, + .max = 1, + .step_or_mask = 1, + .value = 1, + }, + { + .cap_id = GOP_SIZE, + .min = 0, + .max = INT_MAX, + .step_or_mask = 1, + .value = 2 * DEFAULT_FPS - 1, + .hfi_id = HFI_PROP_MAX_GOP_FRAMES, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + }, + { + .cap_id = ENTROPY_MODE, + .min = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC, + .max = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC) | + BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC), + .value = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC, + .hfi_id = HFI_PROP_CABAC_SESSION, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + }, + { + .cap_id = MIN_FRAME_QP_H264, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MIN_QP_8BIT, + .hfi_id = HFI_PROP_MIN_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT, + }, + { + .cap_id = MIN_FRAME_QP_HEVC, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MIN_QP_8BIT, + .hfi_id = HFI_PROP_MIN_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT, + }, + { + .cap_id = MAX_FRAME_QP_H264, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MAX_QP, + .hfi_id = HFI_PROP_MAX_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT, + }, + { + .cap_id = MAX_FRAME_QP_HEVC, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MAX_QP, + .hfi_id = HFI_PROP_MAX_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT, + }, + { + .cap_id = I_FRAME_MIN_QP_H264, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MIN_QP_8BIT, + }, + { + .cap_id = I_FRAME_MIN_QP_HEVC, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MIN_QP_8BIT, + }, + { + .cap_id = P_FRAME_MIN_QP_H264, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MIN_QP_8BIT, + }, + { + .cap_id = P_FRAME_MIN_QP_HEVC, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MIN_QP_8BIT, + }, + { + .cap_id = B_FRAME_MIN_QP_H264, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MIN_QP_8BIT, + }, + { + .cap_id = B_FRAME_MIN_QP_HEVC, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MIN_QP_8BIT, + }, + { + .cap_id = I_FRAME_MAX_QP_H264, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MAX_QP, + }, + { + .cap_id = I_FRAME_MAX_QP_HEVC, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MAX_QP, + }, + { + .cap_id = P_FRAME_MAX_QP_H264, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MAX_QP, + }, + { + .cap_id = P_FRAME_MAX_QP_HEVC, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MAX_QP, + }, + { + .cap_id = B_FRAME_MAX_QP_H264, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MAX_QP, + }, + { + .cap_id = B_FRAME_MAX_QP_HEVC, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MAX_QP, + }, + { + .cap_id = I_FRAME_QP_H264, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = DEFAULT_QP, + .hfi_id = HFI_PROP_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + }, + { + .cap_id = I_FRAME_QP_HEVC, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = DEFAULT_QP, + .hfi_id = HFI_PROP_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + }, + { + .cap_id = P_FRAME_QP_H264, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = DEFAULT_QP, + .hfi_id = HFI_PROP_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + }, + { + .cap_id = P_FRAME_QP_HEVC, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = DEFAULT_QP, + .hfi_id = HFI_PROP_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + }, + { + .cap_id = B_FRAME_QP_H264, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = DEFAULT_QP, + .hfi_id = HFI_PROP_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + }, + { + .cap_id = B_FRAME_QP_HEVC, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = DEFAULT_QP, + .hfi_id = HFI_PROP_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + }, +}; + static struct platform_inst_caps platform_inst_cap_qcs8300 = { .min_frame_width = 96, .max_frame_width = 4096, @@ -197,4 +545,6 @@ static struct platform_inst_caps platform_inst_cap_qcs8300 = { .mb_cycles_fw = 326389, .mb_cycles_fw_vpp = 44156, .num_comv = 0, + .max_frame_rate = MAXIMUM_FPS, + .max_operating_rate = MAXIMUM_FPS, }; diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8250.c b/drivers/media/platform/qcom/iris/iris_platform_sm8250.c index 8d0816a67ae0..16486284f8ac 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_sm8250.c +++ b/drivers/media/platform/qcom/iris/iris_platform_sm8250.c @@ -9,9 +9,15 @@ #include "iris_resources.h" #include "iris_hfi_gen1.h" #include "iris_hfi_gen1_defines.h" +#include "iris_vpu_buffer.h" #include "iris_vpu_common.h" -static struct platform_inst_fw_cap inst_fw_cap_sm8250[] = { +#define BITRATE_MIN 32000 +#define BITRATE_MAX 160000000 +#define BITRATE_PEAK_DEFAULT (BITRATE_DEFAULT * 2) +#define BITRATE_STEP 100 + +static struct platform_inst_fw_cap inst_fw_cap_sm8250_dec[] = { { .cap_id = PIPE, .min = PIPE_1, @@ -32,6 +38,200 @@ static struct platform_inst_fw_cap inst_fw_cap_sm8250[] = { }, }; +static struct platform_inst_fw_cap inst_fw_cap_sm8250_enc[] = { + { + .cap_id = STAGE, + .min = STAGE_1, + .max = STAGE_2, + .step_or_mask = 1, + .value = STAGE_2, + .hfi_id = HFI_PROPERTY_PARAM_WORK_MODE, + .set = iris_set_stage, + }, + { + .cap_id = PROFILE_H264, + .min = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE, + .max = V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_HIGH) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH), + .value = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH, + .hfi_id = HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_profile_level_gen1, + }, + { + .cap_id = PROFILE_HEVC, + .min = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN, + .max = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN) | + BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE) | + BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10), + .value = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN, + .hfi_id = HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_profile_level_gen1, + }, + { + .cap_id = LEVEL_H264, + .min = V4L2_MPEG_VIDEO_H264_LEVEL_1_0, + .max = V4L2_MPEG_VIDEO_H264_LEVEL_5_1, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1B) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_3) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_1), + .value = V4L2_MPEG_VIDEO_H264_LEVEL_1_0, + .hfi_id = HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_profile_level_gen1, + }, + { + .cap_id = LEVEL_HEVC, + .min = V4L2_MPEG_VIDEO_HEVC_LEVEL_1, + .max = V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5_2) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2), + .value = V4L2_MPEG_VIDEO_HEVC_LEVEL_1, + .hfi_id = HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_profile_level_gen1, + }, + { + .cap_id = HEADER_MODE, + .min = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE, + .max = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE) | + BIT(V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME), + .value = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME, + .hfi_id = HFI_PROPERTY_CONFIG_VENC_SYNC_FRAME_SEQUENCE_HEADER, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_header_mode_gen1, + }, + { + .cap_id = BITRATE, + .min = BITRATE_MIN, + .max = BITRATE_MAX, + .step_or_mask = BITRATE_STEP, + .value = BITRATE_DEFAULT, + .hfi_id = HFI_PROPERTY_CONFIG_VENC_TARGET_BITRATE, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + .set = iris_set_bitrate, + }, + { + .cap_id = BITRATE_MODE, + .min = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, + .max = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) | + BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_CBR), + .value = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, + .hfi_id = HFI_PROPERTY_PARAM_VENC_RATE_CONTROL, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_bitrate_mode_gen1, + }, + { + .cap_id = FRAME_SKIP_MODE, + .min = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED, + .max = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED) | + BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT), + .value = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + }, + { + .cap_id = FRAME_RC_ENABLE, + .min = 0, + .max = 1, + .step_or_mask = 1, + .value = 1, + }, + { + .cap_id = GOP_SIZE, + .min = 0, + .max = (1 << 16) - 1, + .step_or_mask = 1, + .value = 30, + .set = iris_set_u32 + }, + { + .cap_id = ENTROPY_MODE, + .min = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC, + .max = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC) | + BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC), + .value = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC, + .hfi_id = HFI_PROPERTY_PARAM_VENC_H264_ENTROPY_CONTROL, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_entropy_mode_gen1, + }, + { + .cap_id = MIN_FRAME_QP_H264, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MIN_QP_8BIT, + .hfi_id = HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE_V2, + .flags = CAP_FLAG_OUTPUT_PORT, + .set = iris_set_qp_range, + }, + { + .cap_id = MIN_FRAME_QP_HEVC, + .min = MIN_QP_8BIT, + .max = MAX_QP_HEVC, + .step_or_mask = 1, + .value = MIN_QP_8BIT, + .hfi_id = HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE_V2, + .flags = CAP_FLAG_OUTPUT_PORT, + .set = iris_set_qp_range, + }, + { + .cap_id = MAX_FRAME_QP_H264, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MAX_QP, + .hfi_id = HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE_V2, + .flags = CAP_FLAG_OUTPUT_PORT, + .set = iris_set_qp_range, + }, + { + .cap_id = MAX_FRAME_QP_HEVC, + .min = MIN_QP_8BIT, + .max = MAX_QP_HEVC, + .step_or_mask = 1, + .value = MAX_QP_HEVC, + .hfi_id = HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE_V2, + .flags = CAP_FLAG_OUTPUT_PORT, + .set = iris_set_qp_range, + }, +}; + static struct platform_inst_caps platform_inst_cap_sm8250 = { .min_frame_width = 128, .max_frame_width = 8192, @@ -40,6 +240,8 @@ static struct platform_inst_caps platform_inst_cap_sm8250 = { .max_mbpf = 138240, .mb_cycles_vsp = 25, .mb_cycles_vpp = 200, + .max_frame_rate = MAXIMUM_FPS, + .max_operating_rate = MAXIMUM_FPS, }; static void iris_set_sm8250_preset_registers(struct iris_core *core) @@ -89,6 +291,14 @@ static const u32 sm8250_vdec_input_config_param_default[] = { HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE, }; +static const u32 sm8250_venc_input_config_param[] = { + HFI_PROPERTY_CONFIG_FRAME_RATE, + HFI_PROPERTY_PARAM_UNCOMPRESSED_PLANE_ACTUAL_INFO, + HFI_PROPERTY_PARAM_FRAME_SIZE, + HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SELECT, + HFI_PROPERTY_PARAM_BUFFER_COUNT_ACTUAL, +}; + static const u32 sm8250_dec_ip_int_buf_tbl[] = { BUF_BIN, BUF_SCRATCH_1, @@ -98,10 +308,17 @@ static const u32 sm8250_dec_op_int_buf_tbl[] = { BUF_DPB, }; +static const u32 sm8250_enc_ip_int_buf_tbl[] = { + BUF_BIN, + BUF_SCRATCH_1, + BUF_SCRATCH_2, +}; + struct iris_platform_data sm8250_data = { .get_instance = iris_hfi_gen1_get_instance, .init_hfi_command_ops = &iris_hfi_gen1_command_ops_init, .init_hfi_response_ops = iris_hfi_gen1_response_ops_init, + .get_vpu_buffer_size = iris_vpu_buf_size, .vpu_ops = &iris_vpu2_ops, .set_preset_registers = iris_set_sm8250_preset_registers, .icc_tbl = sm8250_icc_table, @@ -121,20 +338,29 @@ struct iris_platform_data sm8250_data = { .fwname = "qcom/vpu-1.0/venus.mbn", .pas_id = IRIS_PAS_ID, .inst_caps = &platform_inst_cap_sm8250, - .inst_fw_caps = inst_fw_cap_sm8250, - .inst_fw_caps_size = ARRAY_SIZE(inst_fw_cap_sm8250), + .inst_fw_caps_dec = inst_fw_cap_sm8250_dec, + .inst_fw_caps_dec_size = ARRAY_SIZE(inst_fw_cap_sm8250_dec), + .inst_fw_caps_enc = inst_fw_cap_sm8250_enc, + .inst_fw_caps_enc_size = ARRAY_SIZE(inst_fw_cap_sm8250_enc), .tz_cp_config_data = &tz_cp_config_sm8250, .hw_response_timeout = HW_RESPONSE_TIMEOUT_VALUE, .num_vpp_pipe = 4, .max_session_count = 16, .max_core_mbpf = NUM_MBS_8K, - .input_config_params_default = + .max_core_mbps = ((7680 * 4320) / 256) * 60, + .dec_input_config_params_default = sm8250_vdec_input_config_param_default, - .input_config_params_default_size = + .dec_input_config_params_default_size = ARRAY_SIZE(sm8250_vdec_input_config_param_default), + .enc_input_config_params = sm8250_venc_input_config_param, + .enc_input_config_params_size = + ARRAY_SIZE(sm8250_venc_input_config_param), .dec_ip_int_buf_tbl = sm8250_dec_ip_int_buf_tbl, .dec_ip_int_buf_tbl_size = ARRAY_SIZE(sm8250_dec_ip_int_buf_tbl), .dec_op_int_buf_tbl = sm8250_dec_op_int_buf_tbl, .dec_op_int_buf_tbl_size = ARRAY_SIZE(sm8250_dec_op_int_buf_tbl), + + .enc_ip_int_buf_tbl = sm8250_enc_ip_int_buf_tbl, + .enc_ip_int_buf_tbl_size = ARRAY_SIZE(sm8250_enc_ip_int_buf_tbl), }; diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8750.h b/drivers/media/platform/qcom/iris/iris_platform_sm8750.h new file mode 100644 index 000000000000..719056656a5b --- /dev/null +++ b/drivers/media/platform/qcom/iris/iris_platform_sm8750.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2025 Linaro Ltd + */ + +#ifndef __MEDIA_IRIS_PLATFORM_SM8750_H__ +#define __MEDIA_IRIS_PLATFORM_SM8750_H__ + +static const char * const sm8750_clk_reset_table[] = { + "bus0", "bus1", "core", "vcodec0_core" +}; + +static const struct platform_clk_data sm8750_clk_table[] = { + {IRIS_AXI_CLK, "iface" }, + {IRIS_CTRL_CLK, "core" }, + {IRIS_HW_CLK, "vcodec0_core" }, + {IRIS_AXI1_CLK, "iface1" }, + {IRIS_CTRL_FREERUN_CLK, "core_freerun" }, + {IRIS_HW_FREERUN_CLK, "vcodec0_core_freerun" }, +}; + +#endif diff --git a/drivers/media/platform/qcom/iris/iris_probe.c b/drivers/media/platform/qcom/iris/iris_probe.c index 4e6e92357968..00e99be16e08 100644 --- a/drivers/media/platform/qcom/iris/iris_probe.c +++ b/drivers/media/platform/qcom/iris/iris_probe.c @@ -146,7 +146,7 @@ static int iris_init_resources(struct iris_core *core) return iris_init_resets(core); } -static int iris_register_video_device(struct iris_core *core) +static int iris_register_video_device(struct iris_core *core, enum domain_type type) { struct video_device *vdev; int ret; @@ -155,19 +155,29 @@ static int iris_register_video_device(struct iris_core *core) if (!vdev) return -ENOMEM; - strscpy(vdev->name, "qcom-iris-decoder", sizeof(vdev->name)); vdev->release = video_device_release; vdev->fops = core->iris_v4l2_file_ops; - vdev->ioctl_ops = core->iris_v4l2_ioctl_ops; vdev->vfl_dir = VFL_DIR_M2M; vdev->v4l2_dev = &core->v4l2_dev; vdev->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING; + if (type == DECODER) { + strscpy(vdev->name, "qcom-iris-decoder", sizeof(vdev->name)); + vdev->ioctl_ops = core->iris_v4l2_ioctl_ops_dec; + core->vdev_dec = vdev; + } else if (type == ENCODER) { + strscpy(vdev->name, "qcom-iris-encoder", sizeof(vdev->name)); + vdev->ioctl_ops = core->iris_v4l2_ioctl_ops_enc; + core->vdev_enc = vdev; + } else { + ret = -EINVAL; + goto err_vdev_release; + } + ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1); if (ret) goto err_vdev_release; - core->vdev_dec = vdev; video_set_drvdata(vdev, core); return 0; @@ -189,6 +199,7 @@ static void iris_remove(struct platform_device *pdev) iris_core_deinit(core); video_unregister_device(core->vdev_dec); + video_unregister_device(core->vdev_enc); v4l2_device_unregister(&core->v4l2_dev); @@ -258,17 +269,21 @@ static int iris_probe(struct platform_device *pdev) if (ret) return ret; - ret = iris_register_video_device(core); + ret = iris_register_video_device(core, DECODER); if (ret) goto err_v4l2_unreg; + ret = iris_register_video_device(core, ENCODER); + if (ret) + goto err_vdev_unreg_dec; + platform_set_drvdata(pdev, core); dma_mask = core->iris_platform_data->dma_mask; ret = dma_set_mask_and_coherent(dev, dma_mask); if (ret) - goto err_vdev_unreg; + goto err_vdev_unreg_enc; dma_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32)); dma_set_seg_boundary(&pdev->dev, DMA_BIT_MASK(32)); @@ -277,11 +292,13 @@ static int iris_probe(struct platform_device *pdev) pm_runtime_use_autosuspend(core->dev); ret = devm_pm_runtime_enable(core->dev); if (ret) - goto err_vdev_unreg; + goto err_vdev_unreg_enc; return 0; -err_vdev_unreg: +err_vdev_unreg_enc: + video_unregister_device(core->vdev_enc); +err_vdev_unreg_dec: video_unregister_device(core->vdev_dec); err_v4l2_unreg: v4l2_device_unregister(&core->v4l2_dev); @@ -353,6 +370,10 @@ static const struct of_device_id iris_dt_match[] = { .compatible = "qcom,sm8650-iris", .data = &sm8650_data, }, + { + .compatible = "qcom,sm8750-iris", + .data = &sm8750_data, + }, { }, }; MODULE_DEVICE_TABLE(of, iris_dt_match); diff --git a/drivers/media/platform/qcom/iris/iris_state.c b/drivers/media/platform/qcom/iris/iris_state.c index 104e1687ad39..d14472414750 100644 --- a/drivers/media/platform/qcom/iris/iris_state.c +++ b/drivers/media/platform/qcom/iris/iris_state.c @@ -122,7 +122,8 @@ static bool iris_inst_allow_sub_state(struct iris_inst *inst, enum iris_inst_sub return false; case IRIS_INST_OUTPUT_STREAMING: if (sub_state & (IRIS_INST_SUB_DRC_LAST | - IRIS_INST_SUB_DRAIN_LAST | IRIS_INST_SUB_OUTPUT_PAUSE)) + IRIS_INST_SUB_DRAIN_LAST | IRIS_INST_SUB_OUTPUT_PAUSE | + IRIS_INST_SUB_LOAD_RESOURCES)) return true; return false; case IRIS_INST_STREAMING: @@ -251,7 +252,7 @@ bool iris_drc_pending(struct iris_inst *inst) inst->sub_state & IRIS_INST_SUB_DRC_LAST; } -static inline bool iris_drain_pending(struct iris_inst *inst) +bool iris_drain_pending(struct iris_inst *inst) { return inst->sub_state & IRIS_INST_SUB_DRAIN && inst->sub_state & IRIS_INST_SUB_DRAIN_LAST; @@ -262,11 +263,11 @@ bool iris_allow_cmd(struct iris_inst *inst, u32 cmd) struct vb2_queue *src_q = v4l2_m2m_get_src_vq(inst->m2m_ctx); struct vb2_queue *dst_q = v4l2_m2m_get_dst_vq(inst->m2m_ctx); - if (cmd == V4L2_DEC_CMD_START) { + if (cmd == V4L2_DEC_CMD_START || cmd == V4L2_ENC_CMD_START) { if (vb2_is_streaming(src_q) || vb2_is_streaming(dst_q)) if (iris_drc_pending(inst) || iris_drain_pending(inst)) return true; - } else if (cmd == V4L2_DEC_CMD_STOP) { + } else if (cmd == V4L2_DEC_CMD_STOP || cmd == V4L2_ENC_CMD_STOP) { if (vb2_is_streaming(src_q)) if (inst->sub_state != IRIS_INST_SUB_DRAIN) return true; diff --git a/drivers/media/platform/qcom/iris/iris_state.h b/drivers/media/platform/qcom/iris/iris_state.h index e718386dbe04..b09fa54cf17e 100644 --- a/drivers/media/platform/qcom/iris/iris_state.h +++ b/drivers/media/platform/qcom/iris/iris_state.h @@ -141,5 +141,6 @@ int iris_inst_sub_state_change_drc_last(struct iris_inst *inst); int iris_inst_sub_state_change_pause(struct iris_inst *inst, u32 plane); bool iris_allow_cmd(struct iris_inst *inst, u32 cmd); bool iris_drc_pending(struct iris_inst *inst); +bool iris_drain_pending(struct iris_inst *inst); #endif diff --git a/drivers/media/platform/qcom/iris/iris_utils.c b/drivers/media/platform/qcom/iris/iris_utils.c index 83c70d6a2d90..85c70a62b1fd 100644 --- a/drivers/media/platform/qcom/iris/iris_utils.c +++ b/drivers/media/platform/qcom/iris/iris_utils.c @@ -88,3 +88,39 @@ struct iris_inst *iris_get_instance(struct iris_core *core, u32 session_id) mutex_unlock(&core->lock); return NULL; } + +int iris_check_core_mbpf(struct iris_inst *inst) +{ + struct iris_core *core = inst->core; + struct iris_inst *instance; + u32 total_mbpf = 0; + + mutex_lock(&core->lock); + list_for_each_entry(instance, &core->instances, list) + total_mbpf += iris_get_mbpf(instance); + mutex_unlock(&core->lock); + + if (total_mbpf > core->iris_platform_data->max_core_mbpf) + return -ENOMEM; + + return 0; +} + +int iris_check_core_mbps(struct iris_inst *inst) +{ + struct iris_core *core = inst->core; + struct iris_inst *instance; + u32 total_mbps = 0, fps = 0; + + mutex_lock(&core->lock); + list_for_each_entry(instance, &core->instances, list) { + fps = max(instance->frame_rate, instance->operating_rate); + total_mbps += iris_get_mbpf(instance) * fps; + } + mutex_unlock(&core->lock); + + if (total_mbps > core->iris_platform_data->max_core_mbps) + return -ENOMEM; + + return 0; +} diff --git a/drivers/media/platform/qcom/iris/iris_utils.h b/drivers/media/platform/qcom/iris/iris_utils.h index 49869cf7a376..75740181122f 100644 --- a/drivers/media/platform/qcom/iris/iris_utils.h +++ b/drivers/media/platform/qcom/iris/iris_utils.h @@ -49,5 +49,7 @@ struct iris_inst *iris_get_instance(struct iris_core *core, u32 session_id); void iris_helper_buffers_done(struct iris_inst *inst, unsigned int type, enum vb2_buffer_state state); int iris_wait_for_session_response(struct iris_inst *inst, bool is_flush); +int iris_check_core_mbpf(struct iris_inst *inst); +int iris_check_core_mbps(struct iris_inst *inst); #endif diff --git a/drivers/media/platform/qcom/iris/iris_vb2.c b/drivers/media/platform/qcom/iris/iris_vb2.c index 8b17c7c39487..139b821f7952 100644 --- a/drivers/media/platform/qcom/iris/iris_vb2.c +++ b/drivers/media/platform/qcom/iris/iris_vb2.c @@ -7,28 +7,13 @@ #include <media/v4l2-event.h> #include <media/v4l2-mem2mem.h> +#include "iris_common.h" #include "iris_instance.h" #include "iris_vb2.h" #include "iris_vdec.h" +#include "iris_venc.h" #include "iris_power.h" -static int iris_check_core_mbpf(struct iris_inst *inst) -{ - struct iris_core *core = inst->core; - struct iris_inst *instance; - u32 total_mbpf = 0; - - mutex_lock(&core->lock); - list_for_each_entry(instance, &core->instances, list) - total_mbpf += iris_get_mbpf(instance); - mutex_unlock(&core->lock); - - if (total_mbpf > core->iris_platform_data->max_core_mbpf) - return -ENOMEM; - - return 0; -} - static int iris_check_inst_mbpf(struct iris_inst *inst) { struct platform_inst_caps *caps; @@ -173,9 +158,6 @@ int iris_vb2_start_streaming(struct vb2_queue *q, unsigned int count) inst = vb2_get_drv_priv(q); - if (V4L2_TYPE_IS_CAPTURE(q->type) && inst->state == IRIS_INST_INIT) - return 0; - mutex_lock(&inst->lock); if (inst->state == IRIS_INST_ERROR) { ret = -EBUSY; @@ -194,16 +176,35 @@ int iris_vb2_start_streaming(struct vb2_queue *q, unsigned int count) if (ret) goto error; - if (V4L2_TYPE_IS_OUTPUT(q->type)) - ret = iris_vdec_streamon_input(inst); - else if (V4L2_TYPE_IS_CAPTURE(q->type)) - ret = iris_vdec_streamon_output(inst); + if (V4L2_TYPE_IS_OUTPUT(q->type)) { + if (inst->domain == DECODER) + ret = iris_vdec_streamon_input(inst); + else + ret = iris_venc_streamon_input(inst); + } else if (V4L2_TYPE_IS_CAPTURE(q->type)) { + if (inst->domain == DECODER) + ret = iris_vdec_streamon_output(inst); + else + ret = iris_venc_streamon_output(inst); + } if (ret) goto error; buf_type = iris_v4l2_type_to_driver(q->type); - ret = iris_queue_deferred_buffers(inst, buf_type); + if (inst->domain == DECODER) { + if (inst->state == IRIS_INST_STREAMING) + ret = iris_queue_internal_deferred_buffers(inst, BUF_DPB); + if (!ret) + ret = iris_queue_deferred_buffers(inst, buf_type); + } else { + if (inst->state == IRIS_INST_STREAMING) { + ret = iris_queue_deferred_buffers(inst, BUF_INPUT); + if (!ret) + ret = iris_queue_deferred_buffers(inst, BUF_OUTPUT); + } + } + if (ret) goto error; @@ -235,7 +236,7 @@ void iris_vb2_stop_streaming(struct vb2_queue *q) !V4L2_TYPE_IS_CAPTURE(q->type)) goto exit; - ret = iris_vdec_session_streamoff(inst, q->type); + ret = iris_session_streamoff(inst, q->type); if (ret) goto exit; @@ -326,7 +327,10 @@ void iris_vb2_buf_queue(struct vb2_buffer *vb2) v4l2_m2m_buf_queue(m2m_ctx, vbuf); - ret = iris_vdec_qbuf(inst, vbuf); + if (inst->domain == DECODER) + ret = iris_vdec_qbuf(inst, vbuf); + else + ret = iris_venc_qbuf(inst, vbuf); exit: if (ret) { diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/media/platform/qcom/iris/iris_vdec.c index d670b51c5839..ae13c3e1b426 100644 --- a/drivers/media/platform/qcom/iris/iris_vdec.c +++ b/drivers/media/platform/qcom/iris/iris_vdec.c @@ -7,14 +7,13 @@ #include <media/v4l2-mem2mem.h> #include "iris_buffer.h" +#include "iris_common.h" #include "iris_ctrls.h" #include "iris_instance.h" #include "iris_power.h" #include "iris_vdec.h" #include "iris_vpu_buffer.h" -#define DEFAULT_WIDTH 320 -#define DEFAULT_HEIGHT 240 #define DEFAULT_CODEC_ALIGNMENT 16 int iris_vdec_inst_init(struct iris_inst *inst) @@ -56,7 +55,7 @@ int iris_vdec_inst_init(struct iris_inst *inst) inst->buffers[BUF_OUTPUT].min_count = iris_vpu_buf_count(inst, BUF_OUTPUT); inst->buffers[BUF_OUTPUT].size = f->fmt.pix_mp.plane_fmt[0].sizeimage; - memcpy(&inst->fw_caps[0], &core->inst_fw_caps[0], + memcpy(&inst->fw_caps[0], &core->inst_fw_caps_dec[0], INST_FW_CAP_MAX * sizeof(struct platform_inst_fw_cap)); return iris_ctrls_init(inst); @@ -158,7 +157,7 @@ int iris_vdec_try_fmt(struct iris_inst *inst, struct v4l2_format *f) } break; case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: - if (!fmt) { + if (f->fmt.pix_mp.pixelformat != V4L2_PIX_FMT_NV12) { f_inst = inst->fmt_dst; f->fmt.pix_mp.pixelformat = f_inst->fmt.pix_mp.pixelformat; f->fmt.pix_mp.width = f_inst->fmt.pix_mp.width; @@ -265,6 +264,19 @@ int iris_vdec_s_fmt(struct iris_inst *inst, struct v4l2_format *f) return 0; } +int iris_vdec_validate_format(struct iris_inst *inst, u32 pixelformat) +{ + const struct iris_fmt *fmt = NULL; + + if (pixelformat != V4L2_PIX_FMT_NV12) { + fmt = find_format(inst, pixelformat, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + if (!fmt) + return -EINVAL; + } + + return 0; +} + int iris_vdec_subscribe_event(struct iris_inst *inst, const struct v4l2_event_subscription *sub) { int ret = 0; @@ -301,125 +313,6 @@ void iris_vdec_src_change(struct iris_inst *inst) v4l2_event_queue_fh(&inst->fh, &event); } - -static void iris_vdec_flush_deferred_buffers(struct iris_inst *inst, - enum iris_buffer_type type) -{ - struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; - struct v4l2_m2m_buffer *buffer, *n; - struct iris_buffer *buf; - - if (type == BUF_INPUT) { - v4l2_m2m_for_each_src_buf_safe(m2m_ctx, buffer, n) { - buf = to_iris_buffer(&buffer->vb); - if (buf->attr & BUF_ATTR_DEFERRED) { - if (!(buf->attr & BUF_ATTR_BUFFER_DONE)) { - buf->attr |= BUF_ATTR_BUFFER_DONE; - buf->data_size = 0; - iris_vb2_buffer_done(inst, buf); - } - } - } - } else { - v4l2_m2m_for_each_dst_buf_safe(m2m_ctx, buffer, n) { - buf = to_iris_buffer(&buffer->vb); - if (buf->attr & BUF_ATTR_DEFERRED) { - if (!(buf->attr & BUF_ATTR_BUFFER_DONE)) { - buf->attr |= BUF_ATTR_BUFFER_DONE; - buf->data_size = 0; - iris_vb2_buffer_done(inst, buf); - } - } - } - } -} - -static void iris_vdec_kill_session(struct iris_inst *inst) -{ - const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; - - if (!inst->session_id) - return; - - hfi_ops->session_close(inst); - iris_inst_change_state(inst, IRIS_INST_ERROR); -} - -int iris_vdec_session_streamoff(struct iris_inst *inst, u32 plane) -{ - const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; - enum iris_buffer_type buffer_type; - int ret; - - switch (plane) { - case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: - buffer_type = BUF_INPUT; - break; - case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: - buffer_type = BUF_OUTPUT; - break; - default: - return -EINVAL; - } - - ret = hfi_ops->session_stop(inst, plane); - if (ret) - goto error; - - ret = iris_inst_state_change_streamoff(inst, plane); - if (ret) - goto error; - - iris_vdec_flush_deferred_buffers(inst, buffer_type); - - return 0; - -error: - iris_vdec_kill_session(inst); - iris_vdec_flush_deferred_buffers(inst, buffer_type); - - return ret; -} - -static int iris_vdec_process_streamon_input(struct iris_inst *inst) -{ - const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; - enum iris_inst_sub_state set_sub_state = 0; - int ret; - - iris_scale_power(inst); - - ret = hfi_ops->session_start(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); - if (ret) - return ret; - - if (inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) { - ret = iris_inst_change_sub_state(inst, IRIS_INST_SUB_INPUT_PAUSE, 0); - if (ret) - return ret; - } - - if (inst->sub_state & IRIS_INST_SUB_DRC || - inst->sub_state & IRIS_INST_SUB_DRAIN || - inst->sub_state & IRIS_INST_SUB_FIRST_IPSC) { - if (!(inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE)) { - if (hfi_ops->session_pause) { - ret = hfi_ops->session_pause(inst, - V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); - if (ret) - return ret; - } - set_sub_state = IRIS_INST_SUB_INPUT_PAUSE; - } - } - - ret = iris_inst_state_change_streamon(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); - if (ret) - return ret; - - return iris_inst_change_sub_state(inst, 0, set_sub_state); -} - int iris_vdec_streamon_input(struct iris_inst *inst) { int ret; @@ -428,7 +321,7 @@ int iris_vdec_streamon_input(struct iris_inst *inst) if (ret) return ret; - ret = iris_alloc_and_queue_persist_bufs(inst); + ret = iris_alloc_and_queue_persist_bufs(inst, BUF_PERSIST); if (ret) return ret; @@ -446,71 +339,7 @@ int iris_vdec_streamon_input(struct iris_inst *inst) if (ret) return ret; - return iris_vdec_process_streamon_input(inst); -} - -static int iris_vdec_process_streamon_output(struct iris_inst *inst) -{ - const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; - bool drain_active = false, drc_active = false; - enum iris_inst_sub_state clear_sub_state = 0; - int ret = 0; - - iris_scale_power(inst); - - drain_active = inst->sub_state & IRIS_INST_SUB_DRAIN && - inst->sub_state & IRIS_INST_SUB_DRAIN_LAST; - - drc_active = inst->sub_state & IRIS_INST_SUB_DRC && - inst->sub_state & IRIS_INST_SUB_DRC_LAST; - - if (drc_active) - clear_sub_state = IRIS_INST_SUB_DRC | IRIS_INST_SUB_DRC_LAST; - else if (drain_active) - clear_sub_state = IRIS_INST_SUB_DRAIN | IRIS_INST_SUB_DRAIN_LAST; - - if (inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) { - ret = iris_alloc_and_queue_input_int_bufs(inst); - if (ret) - return ret; - ret = iris_set_stage(inst, STAGE); - if (ret) - return ret; - ret = iris_set_pipe(inst, PIPE); - if (ret) - return ret; - } - - if (inst->state == IRIS_INST_INPUT_STREAMING && - inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) { - if (!drain_active) - ret = hfi_ops->session_resume_drc(inst, - V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); - else if (hfi_ops->session_resume_drain) - ret = hfi_ops->session_resume_drain(inst, - V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); - if (ret) - return ret; - clear_sub_state |= IRIS_INST_SUB_INPUT_PAUSE; - } - - if (inst->sub_state & IRIS_INST_SUB_FIRST_IPSC) - clear_sub_state |= IRIS_INST_SUB_FIRST_IPSC; - - ret = hfi_ops->session_start(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); - if (ret) - return ret; - - if (inst->sub_state & IRIS_INST_SUB_OUTPUT_PAUSE) - clear_sub_state |= IRIS_INST_SUB_OUTPUT_PAUSE; - - ret = iris_inst_state_change_streamon(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); - if (ret) - return ret; - - inst->last_buffer_dequeued = false; - - return iris_inst_change_sub_state(inst, clear_sub_state, 0); + return iris_process_streamon_input(inst); } int iris_vdec_streamon_output(struct iris_inst *inst) @@ -532,7 +361,7 @@ int iris_vdec_streamon_output(struct iris_inst *inst) if (ret) return ret; - ret = iris_vdec_process_streamon_output(inst); + ret = iris_process_streamon_output(inst); if (ret) goto error; @@ -543,49 +372,11 @@ int iris_vdec_streamon_output(struct iris_inst *inst) return ret; error: - iris_vdec_session_streamoff(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + iris_session_streamoff(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); return ret; } -static int -iris_vdec_vb2_buffer_to_driver(struct vb2_buffer *vb2, struct iris_buffer *buf) -{ - struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2); - - buf->type = iris_v4l2_type_to_driver(vb2->type); - buf->index = vb2->index; - buf->fd = vb2->planes[0].m.fd; - buf->buffer_size = vb2->planes[0].length; - buf->data_offset = vb2->planes[0].data_offset; - buf->data_size = vb2->planes[0].bytesused - vb2->planes[0].data_offset; - buf->flags = vbuf->flags; - buf->timestamp = vb2->timestamp; - buf->attr = 0; - - return 0; -} - -static void -iris_set_ts_metadata(struct iris_inst *inst, struct vb2_v4l2_buffer *vbuf) -{ - u32 mask = V4L2_BUF_FLAG_TIMECODE | V4L2_BUF_FLAG_TSTAMP_SRC_MASK; - struct vb2_buffer *vb = &vbuf->vb2_buf; - u64 ts_us = vb->timestamp; - - if (inst->metadata_idx >= ARRAY_SIZE(inst->tss)) - inst->metadata_idx = 0; - - do_div(ts_us, NSEC_PER_USEC); - - inst->tss[inst->metadata_idx].flags = vbuf->flags & mask; - inst->tss[inst->metadata_idx].tc = vbuf->timecode; - inst->tss[inst->metadata_idx].ts_us = ts_us; - inst->tss[inst->metadata_idx].ts_ns = vb->timestamp; - - inst->metadata_idx++; -} - int iris_vdec_qbuf(struct iris_inst *inst, struct vb2_v4l2_buffer *vbuf) { struct iris_buffer *buf = to_iris_buffer(vbuf); @@ -593,7 +384,7 @@ int iris_vdec_qbuf(struct iris_inst *inst, struct vb2_v4l2_buffer *vbuf) struct vb2_queue *q; int ret; - ret = iris_vdec_vb2_buffer_to_driver(vb2, buf); + ret = iris_vb2_buffer_to_driver(vb2, buf); if (ret) return ret; diff --git a/drivers/media/platform/qcom/iris/iris_vdec.h b/drivers/media/platform/qcom/iris/iris_vdec.h index cd7aab66dc7c..ec1ce55d1375 100644 --- a/drivers/media/platform/qcom/iris/iris_vdec.h +++ b/drivers/media/platform/qcom/iris/iris_vdec.h @@ -8,22 +8,12 @@ struct iris_inst; -enum iris_fmt_type { - IRIS_FMT_H264, - IRIS_FMT_HEVC, - IRIS_FMT_VP9, -}; - -struct iris_fmt { - u32 pixfmt; - u32 type; -}; - int iris_vdec_inst_init(struct iris_inst *inst); void iris_vdec_inst_deinit(struct iris_inst *inst); int iris_vdec_enum_fmt(struct iris_inst *inst, struct v4l2_fmtdesc *f); int iris_vdec_try_fmt(struct iris_inst *inst, struct v4l2_format *f); int iris_vdec_s_fmt(struct iris_inst *inst, struct v4l2_format *f); +int iris_vdec_validate_format(struct iris_inst *inst, u32 pixelformat); int iris_vdec_subscribe_event(struct iris_inst *inst, const struct v4l2_event_subscription *sub); void iris_vdec_src_change(struct iris_inst *inst); int iris_vdec_streamon_input(struct iris_inst *inst); @@ -31,6 +21,5 @@ int iris_vdec_streamon_output(struct iris_inst *inst); int iris_vdec_qbuf(struct iris_inst *inst, struct vb2_v4l2_buffer *vbuf); int iris_vdec_start_cmd(struct iris_inst *inst); int iris_vdec_stop_cmd(struct iris_inst *inst); -int iris_vdec_session_streamoff(struct iris_inst *inst, u32 plane); #endif diff --git a/drivers/media/platform/qcom/iris/iris_venc.c b/drivers/media/platform/qcom/iris/iris_venc.c new file mode 100644 index 000000000000..099bd5ed4ae0 --- /dev/null +++ b/drivers/media/platform/qcom/iris/iris_venc.c @@ -0,0 +1,579 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include <media/v4l2-event.h> +#include <media/v4l2-mem2mem.h> + +#include "iris_buffer.h" +#include "iris_common.h" +#include "iris_ctrls.h" +#include "iris_instance.h" +#include "iris_power.h" +#include "iris_venc.h" +#include "iris_vpu_buffer.h" + +int iris_venc_inst_init(struct iris_inst *inst) +{ + struct iris_core *core = inst->core; + struct v4l2_format *f; + + inst->fmt_src = kzalloc(sizeof(*inst->fmt_src), GFP_KERNEL); + inst->fmt_dst = kzalloc(sizeof(*inst->fmt_dst), GFP_KERNEL); + if (!inst->fmt_src || !inst->fmt_dst) { + kfree(inst->fmt_src); + kfree(inst->fmt_dst); + return -ENOMEM; + } + + f = inst->fmt_dst; + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + f->fmt.pix_mp.width = DEFAULT_WIDTH; + f->fmt.pix_mp.height = DEFAULT_HEIGHT; + f->fmt.pix_mp.pixelformat = V4L2_PIX_FMT_H264; + inst->codec = f->fmt.pix_mp.pixelformat; + f->fmt.pix_mp.num_planes = 1; + f->fmt.pix_mp.plane_fmt[0].bytesperline = 0; + f->fmt.pix_mp.plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_OUTPUT); + f->fmt.pix_mp.field = V4L2_FIELD_NONE; + f->fmt.pix_mp.colorspace = V4L2_COLORSPACE_DEFAULT; + f->fmt.pix_mp.xfer_func = V4L2_XFER_FUNC_DEFAULT; + f->fmt.pix_mp.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; + f->fmt.pix_mp.quantization = V4L2_QUANTIZATION_DEFAULT; + inst->buffers[BUF_OUTPUT].min_count = iris_vpu_buf_count(inst, BUF_OUTPUT); + inst->buffers[BUF_OUTPUT].size = f->fmt.pix_mp.plane_fmt[0].sizeimage; + + f = inst->fmt_src; + f->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + f->fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12; + f->fmt.pix_mp.width = ALIGN(DEFAULT_WIDTH, 128); + f->fmt.pix_mp.height = ALIGN(DEFAULT_HEIGHT, 32); + f->fmt.pix_mp.num_planes = 1; + f->fmt.pix_mp.plane_fmt[0].bytesperline = ALIGN(DEFAULT_WIDTH, 128); + f->fmt.pix_mp.plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_INPUT); + f->fmt.pix_mp.field = V4L2_FIELD_NONE; + f->fmt.pix_mp.colorspace = V4L2_COLORSPACE_DEFAULT; + f->fmt.pix_mp.xfer_func = V4L2_XFER_FUNC_DEFAULT; + f->fmt.pix_mp.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; + f->fmt.pix_mp.quantization = V4L2_QUANTIZATION_DEFAULT; + inst->buffers[BUF_INPUT].min_count = iris_vpu_buf_count(inst, BUF_INPUT); + inst->buffers[BUF_INPUT].size = f->fmt.pix_mp.plane_fmt[0].sizeimage; + + inst->crop.left = 0; + inst->crop.top = 0; + inst->crop.width = f->fmt.pix_mp.width; + inst->crop.height = f->fmt.pix_mp.height; + + inst->operating_rate = DEFAULT_FPS; + inst->frame_rate = DEFAULT_FPS; + + memcpy(&inst->fw_caps[0], &core->inst_fw_caps_enc[0], + INST_FW_CAP_MAX * sizeof(struct platform_inst_fw_cap)); + + return iris_ctrls_init(inst); +} + +void iris_venc_inst_deinit(struct iris_inst *inst) +{ + kfree(inst->fmt_dst); + kfree(inst->fmt_src); +} + +static const struct iris_fmt iris_venc_formats[] = { + [IRIS_FMT_H264] = { + .pixfmt = V4L2_PIX_FMT_H264, + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, + }, + [IRIS_FMT_HEVC] = { + .pixfmt = V4L2_PIX_FMT_HEVC, + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, + }, +}; + +static const struct iris_fmt * +find_format(struct iris_inst *inst, u32 pixfmt, u32 type) +{ + const struct iris_fmt *fmt = iris_venc_formats; + unsigned int size = ARRAY_SIZE(iris_venc_formats); + unsigned int i; + + for (i = 0; i < size; i++) { + if (fmt[i].pixfmt == pixfmt) + break; + } + + if (i == size || fmt[i].type != type) + return NULL; + + return &fmt[i]; +} + +static const struct iris_fmt * +find_format_by_index(struct iris_inst *inst, u32 index, u32 type) +{ + const struct iris_fmt *fmt = iris_venc_formats; + unsigned int size = ARRAY_SIZE(iris_venc_formats); + + if (index >= size || fmt[index].type != type) + return NULL; + + return &fmt[index]; +} + +int iris_venc_enum_fmt(struct iris_inst *inst, struct v4l2_fmtdesc *f) +{ + const struct iris_fmt *fmt; + + switch (f->type) { + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + if (f->index) + return -EINVAL; + f->pixelformat = V4L2_PIX_FMT_NV12; + break; + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + fmt = find_format_by_index(inst, f->index, f->type); + if (!fmt) + return -EINVAL; + + f->pixelformat = fmt->pixfmt; + f->flags = V4L2_FMT_FLAG_COMPRESSED | V4L2_FMT_FLAG_ENC_CAP_FRAME_INTERVAL; + break; + default: + return -EINVAL; + } + + return 0; +} + +int iris_venc_try_fmt(struct iris_inst *inst, struct v4l2_format *f) +{ + struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp; + const struct iris_fmt *fmt; + struct v4l2_format *f_inst; + + memset(pixmp->reserved, 0, sizeof(pixmp->reserved)); + fmt = find_format(inst, pixmp->pixelformat, f->type); + switch (f->type) { + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + if (f->fmt.pix_mp.pixelformat != V4L2_PIX_FMT_NV12) { + f_inst = inst->fmt_src; + f->fmt.pix_mp.width = f_inst->fmt.pix_mp.width; + f->fmt.pix_mp.height = f_inst->fmt.pix_mp.height; + f->fmt.pix_mp.pixelformat = f_inst->fmt.pix_mp.pixelformat; + } + break; + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + if (!fmt) { + f_inst = inst->fmt_dst; + f->fmt.pix_mp.width = f_inst->fmt.pix_mp.width; + f->fmt.pix_mp.height = f_inst->fmt.pix_mp.height; + f->fmt.pix_mp.pixelformat = f_inst->fmt.pix_mp.pixelformat; + } + break; + default: + return -EINVAL; + } + + if (pixmp->field == V4L2_FIELD_ANY) + pixmp->field = V4L2_FIELD_NONE; + + pixmp->num_planes = 1; + + return 0; +} + +static int iris_venc_s_fmt_output(struct iris_inst *inst, struct v4l2_format *f) +{ + struct v4l2_format *fmt; + + iris_venc_try_fmt(inst, f); + + if (!(find_format(inst, f->fmt.pix_mp.pixelformat, f->type))) + return -EINVAL; + + fmt = inst->fmt_dst; + fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + fmt->fmt.pix_mp.num_planes = 1; + fmt->fmt.pix_mp.plane_fmt[0].bytesperline = 0; + fmt->fmt.pix_mp.plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_OUTPUT); + + if (f->fmt.pix_mp.colorspace != V4L2_COLORSPACE_DEFAULT && + f->fmt.pix_mp.colorspace != V4L2_COLORSPACE_REC709) + f->fmt.pix_mp.colorspace = V4L2_COLORSPACE_DEFAULT; + fmt->fmt.pix_mp.colorspace = f->fmt.pix_mp.colorspace; + fmt->fmt.pix_mp.xfer_func = f->fmt.pix_mp.xfer_func; + fmt->fmt.pix_mp.ycbcr_enc = f->fmt.pix_mp.ycbcr_enc; + fmt->fmt.pix_mp.quantization = f->fmt.pix_mp.quantization; + + inst->buffers[BUF_OUTPUT].min_count = iris_vpu_buf_count(inst, BUF_OUTPUT); + inst->buffers[BUF_OUTPUT].size = fmt->fmt.pix_mp.plane_fmt[0].sizeimage; + fmt->fmt.pix_mp.pixelformat = f->fmt.pix_mp.pixelformat; + inst->codec = f->fmt.pix_mp.pixelformat; + memcpy(f, fmt, sizeof(struct v4l2_format)); + + return 0; +} + +static int iris_venc_s_fmt_input(struct iris_inst *inst, struct v4l2_format *f) +{ + struct v4l2_format *fmt, *output_fmt; + + iris_venc_try_fmt(inst, f); + + if (f->fmt.pix_mp.pixelformat != V4L2_PIX_FMT_NV12) + return -EINVAL; + + fmt = inst->fmt_src; + fmt->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + fmt->fmt.pix_mp.width = ALIGN(f->fmt.pix_mp.width, 128); + fmt->fmt.pix_mp.height = ALIGN(f->fmt.pix_mp.height, 32); + fmt->fmt.pix_mp.num_planes = 1; + fmt->fmt.pix_mp.pixelformat = f->fmt.pix_mp.pixelformat; + fmt->fmt.pix_mp.plane_fmt[0].bytesperline = ALIGN(f->fmt.pix_mp.width, 128); + fmt->fmt.pix_mp.plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_INPUT); + + fmt->fmt.pix_mp.colorspace = f->fmt.pix_mp.colorspace; + fmt->fmt.pix_mp.xfer_func = f->fmt.pix_mp.xfer_func; + fmt->fmt.pix_mp.ycbcr_enc = f->fmt.pix_mp.ycbcr_enc; + fmt->fmt.pix_mp.quantization = f->fmt.pix_mp.quantization; + + output_fmt = inst->fmt_dst; + output_fmt->fmt.pix_mp.width = fmt->fmt.pix_mp.width; + output_fmt->fmt.pix_mp.height = fmt->fmt.pix_mp.height; + output_fmt->fmt.pix_mp.colorspace = fmt->fmt.pix_mp.colorspace; + output_fmt->fmt.pix_mp.xfer_func = fmt->fmt.pix_mp.xfer_func; + output_fmt->fmt.pix_mp.ycbcr_enc = fmt->fmt.pix_mp.ycbcr_enc; + output_fmt->fmt.pix_mp.quantization = fmt->fmt.pix_mp.quantization; + + inst->buffers[BUF_INPUT].min_count = iris_vpu_buf_count(inst, BUF_INPUT); + inst->buffers[BUF_INPUT].size = fmt->fmt.pix_mp.plane_fmt[0].sizeimage; + + if (f->fmt.pix_mp.width != inst->crop.width || + f->fmt.pix_mp.height != inst->crop.height) { + inst->crop.top = 0; + inst->crop.left = 0; + inst->crop.width = fmt->fmt.pix_mp.width; + inst->crop.height = fmt->fmt.pix_mp.height; + + iris_venc_s_fmt_output(inst, output_fmt); + } + + memcpy(f, fmt, sizeof(struct v4l2_format)); + + return 0; +} + +int iris_venc_s_fmt(struct iris_inst *inst, struct v4l2_format *f) +{ + struct vb2_queue *q; + + q = v4l2_m2m_get_vq(inst->m2m_ctx, f->type); + if (!q) + return -EINVAL; + + if (vb2_is_busy(q)) + return -EBUSY; + + switch (f->type) { + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + return iris_venc_s_fmt_input(inst, f); + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + return iris_venc_s_fmt_output(inst, f); + default: + return -EINVAL; + } +} + +int iris_venc_validate_format(struct iris_inst *inst, u32 pixelformat) +{ + const struct iris_fmt *fmt = NULL; + + if (pixelformat != V4L2_PIX_FMT_NV12) { + fmt = find_format(inst, pixelformat, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + if (!fmt) + return -EINVAL; + } + + return 0; +} + +int iris_venc_subscribe_event(struct iris_inst *inst, + const struct v4l2_event_subscription *sub) +{ + switch (sub->type) { + case V4L2_EVENT_EOS: + return v4l2_event_subscribe(&inst->fh, sub, 0, NULL); + case V4L2_EVENT_CTRL: + return v4l2_ctrl_subscribe_event(&inst->fh, sub); + default: + return -EINVAL; + } +} + +int iris_venc_s_selection(struct iris_inst *inst, struct v4l2_selection *s) +{ + if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) + return -EINVAL; + + switch (s->target) { + case V4L2_SEL_TGT_CROP: + s->r.left = 0; + s->r.top = 0; + + if (s->r.width > inst->fmt_src->fmt.pix_mp.width || + s->r.height > inst->fmt_src->fmt.pix_mp.height) + return -EINVAL; + + inst->crop.left = s->r.left; + inst->crop.top = s->r.top; + inst->crop.width = s->r.width; + inst->crop.height = s->r.height; + inst->fmt_dst->fmt.pix_mp.width = inst->crop.width; + inst->fmt_dst->fmt.pix_mp.height = inst->crop.height; + return iris_venc_s_fmt_output(inst, inst->fmt_dst); + default: + return -EINVAL; + } +} + +int iris_venc_s_param(struct iris_inst *inst, struct v4l2_streamparm *s_parm) +{ + struct platform_inst_caps *caps = inst->core->iris_platform_data->inst_caps; + struct vb2_queue *src_q = v4l2_m2m_get_src_vq(inst->m2m_ctx); + struct vb2_queue *dst_q = v4l2_m2m_get_dst_vq(inst->m2m_ctx); + struct v4l2_fract *timeperframe = NULL; + u32 default_rate = DEFAULT_FPS; + bool is_frame_rate = false; + u64 us_per_frame, fps; + u32 max_rate; + + int ret = 0; + + if (s_parm->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { + timeperframe = &s_parm->parm.output.timeperframe; + max_rate = caps->max_operating_rate; + s_parm->parm.output.capability = V4L2_CAP_TIMEPERFRAME; + } else { + timeperframe = &s_parm->parm.capture.timeperframe; + is_frame_rate = true; + max_rate = caps->max_frame_rate; + s_parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; + } + + if (!timeperframe->denominator || !timeperframe->numerator) { + if (!timeperframe->numerator) + timeperframe->numerator = 1; + if (!timeperframe->denominator) + timeperframe->denominator = default_rate; + } + + us_per_frame = timeperframe->numerator * (u64)USEC_PER_SEC; + do_div(us_per_frame, timeperframe->denominator); + + if (!us_per_frame) + return -EINVAL; + + fps = (u64)USEC_PER_SEC; + do_div(fps, us_per_frame); + if (fps > max_rate) { + ret = -ENOMEM; + goto reset_rate; + } + + if (is_frame_rate) + inst->frame_rate = (u32)fps; + else + inst->operating_rate = (u32)fps; + + if ((s_parm->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE && vb2_is_streaming(src_q)) || + (s_parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && vb2_is_streaming(dst_q))) { + ret = iris_check_core_mbpf(inst); + if (ret) + goto reset_rate; + ret = iris_check_core_mbps(inst); + if (ret) + goto reset_rate; + } + + return 0; + +reset_rate: + if (ret) { + if (is_frame_rate) + inst->frame_rate = default_rate; + else + inst->operating_rate = default_rate; + } + + return ret; +} + +int iris_venc_g_param(struct iris_inst *inst, struct v4l2_streamparm *s_parm) +{ + struct v4l2_fract *timeperframe = NULL; + + if (s_parm->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { + timeperframe = &s_parm->parm.output.timeperframe; + timeperframe->numerator = 1; + timeperframe->denominator = inst->operating_rate; + s_parm->parm.output.capability = V4L2_CAP_TIMEPERFRAME; + } else { + timeperframe = &s_parm->parm.capture.timeperframe; + timeperframe->numerator = 1; + timeperframe->denominator = inst->frame_rate; + s_parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; + } + + return 0; +} + +int iris_venc_streamon_input(struct iris_inst *inst) +{ + int ret; + + ret = iris_set_properties(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + if (ret) + return ret; + + ret = iris_alloc_and_queue_persist_bufs(inst, BUF_ARP); + if (ret) + return ret; + + iris_get_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + + ret = iris_destroy_dequeued_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + if (ret) + return ret; + + ret = iris_create_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + if (ret) + return ret; + + ret = iris_queue_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + if (ret) + return ret; + + return iris_process_streamon_input(inst); +} + +int iris_venc_streamon_output(struct iris_inst *inst) +{ + int ret; + + ret = iris_set_properties(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + if (ret) + goto error; + + ret = iris_alloc_and_queue_persist_bufs(inst, BUF_ARP); + if (ret) + return ret; + + iris_get_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + + ret = iris_destroy_dequeued_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + if (ret) + goto error; + + ret = iris_create_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + if (ret) + goto error; + + ret = iris_queue_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + if (ret) + goto error; + + ret = iris_process_streamon_output(inst); + if (ret) + goto error; + + return ret; + +error: + iris_session_streamoff(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + + return ret; +} + +int iris_venc_qbuf(struct iris_inst *inst, struct vb2_v4l2_buffer *vbuf) +{ + struct iris_buffer *buf = to_iris_buffer(vbuf); + struct vb2_buffer *vb2 = &vbuf->vb2_buf; + struct vb2_queue *q; + int ret; + + ret = iris_vb2_buffer_to_driver(vb2, buf); + if (ret) + return ret; + + if (buf->type == BUF_INPUT) + iris_set_ts_metadata(inst, vbuf); + + q = v4l2_m2m_get_vq(inst->m2m_ctx, vb2->type); + if (!vb2_is_streaming(q)) { + buf->attr |= BUF_ATTR_DEFERRED; + return 0; + } + + iris_scale_power(inst); + + return iris_queue_buffer(inst, buf); +} + +int iris_venc_start_cmd(struct iris_inst *inst) +{ + const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; + enum iris_inst_sub_state clear_sub_state = 0; + struct vb2_queue *dst_vq; + int ret; + + dst_vq = v4l2_m2m_get_dst_vq(inst->m2m_ctx); + + if (inst->sub_state & IRIS_INST_SUB_DRAIN && + inst->sub_state & IRIS_INST_SUB_DRAIN_LAST) { + vb2_clear_last_buffer_dequeued(dst_vq); + clear_sub_state = IRIS_INST_SUB_DRAIN | IRIS_INST_SUB_DRAIN_LAST; + if (inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) { + if (hfi_ops->session_resume_drain) { + ret = hfi_ops->session_resume_drain(inst, + V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + if (ret) + return ret; + } + clear_sub_state |= IRIS_INST_SUB_INPUT_PAUSE; + } + if (inst->sub_state & IRIS_INST_SUB_OUTPUT_PAUSE) { + if (hfi_ops->session_resume_drain) { + ret = hfi_ops->session_resume_drain(inst, + V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + if (ret) + return ret; + } + clear_sub_state |= IRIS_INST_SUB_OUTPUT_PAUSE; + } + } else { + dev_err(inst->core->dev, "start called before receiving last_flag\n"); + iris_inst_change_state(inst, IRIS_INST_ERROR); + return -EBUSY; + } + + inst->last_buffer_dequeued = false; + + return iris_inst_change_sub_state(inst, clear_sub_state, 0); +} + +int iris_venc_stop_cmd(struct iris_inst *inst) +{ + const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; + int ret; + + ret = hfi_ops->session_drain(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + if (ret) + return ret; + + ret = iris_inst_change_sub_state(inst, 0, IRIS_INST_SUB_DRAIN); + + iris_scale_power(inst); + + return ret; +} diff --git a/drivers/media/platform/qcom/iris/iris_venc.h b/drivers/media/platform/qcom/iris/iris_venc.h new file mode 100644 index 000000000000..c4db7433da53 --- /dev/null +++ b/drivers/media/platform/qcom/iris/iris_venc.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#ifndef _IRIS_VENC_H_ +#define _IRIS_VENC_H_ + +struct iris_inst; + +int iris_venc_inst_init(struct iris_inst *inst); +void iris_venc_inst_deinit(struct iris_inst *inst); +int iris_venc_enum_fmt(struct iris_inst *inst, struct v4l2_fmtdesc *f); +int iris_venc_try_fmt(struct iris_inst *inst, struct v4l2_format *f); +int iris_venc_s_fmt(struct iris_inst *inst, struct v4l2_format *f); +int iris_venc_validate_format(struct iris_inst *inst, u32 pixelformat); +int iris_venc_subscribe_event(struct iris_inst *inst, const struct v4l2_event_subscription *sub); +int iris_venc_s_selection(struct iris_inst *inst, struct v4l2_selection *s); +int iris_venc_g_param(struct iris_inst *inst, struct v4l2_streamparm *s_parm); +int iris_venc_s_param(struct iris_inst *inst, struct v4l2_streamparm *s_parm); +int iris_venc_streamon_input(struct iris_inst *inst); +int iris_venc_streamon_output(struct iris_inst *inst); +int iris_venc_qbuf(struct iris_inst *inst, struct vb2_v4l2_buffer *vbuf); +int iris_venc_start_cmd(struct iris_inst *inst); +int iris_venc_stop_cmd(struct iris_inst *inst); + +#endif diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c index c417e8c31f80..d38d0f6961cd 100644 --- a/drivers/media/platform/qcom/iris/iris_vidc.c +++ b/drivers/media/platform/qcom/iris/iris_vidc.c @@ -12,6 +12,7 @@ #include "iris_vidc.h" #include "iris_instance.h" #include "iris_vdec.h" +#include "iris_venc.h" #include "iris_vb2.h" #include "iris_vpu_buffer.h" #include "iris_platform_common.h" @@ -21,16 +22,19 @@ #define STEP_WIDTH 1 #define STEP_HEIGHT 1 -static void iris_v4l2_fh_init(struct iris_inst *inst) +static void iris_v4l2_fh_init(struct iris_inst *inst, struct file *filp) { - v4l2_fh_init(&inst->fh, inst->core->vdev_dec); + if (inst->domain == ENCODER) + v4l2_fh_init(&inst->fh, inst->core->vdev_enc); + else if (inst->domain == DECODER) + v4l2_fh_init(&inst->fh, inst->core->vdev_dec); inst->fh.ctrl_handler = &inst->ctrl_handler; - v4l2_fh_add(&inst->fh); + v4l2_fh_add(&inst->fh, filp); } -static void iris_v4l2_fh_deinit(struct iris_inst *inst) +static void iris_v4l2_fh_deinit(struct iris_inst *inst, struct file *filp) { - v4l2_fh_del(&inst->fh); + v4l2_fh_del(&inst->fh, filp); inst->fh.ctrl_handler = NULL; v4l2_fh_exit(&inst->fh); } @@ -67,9 +71,9 @@ static void iris_remove_session(struct iris_inst *inst) mutex_unlock(&core->lock); } -static inline struct iris_inst *iris_get_inst(struct file *filp, void *fh) +static inline struct iris_inst *iris_get_inst(struct file *filp) { - return container_of(filp->private_data, struct iris_inst, fh); + return container_of(file_to_v4l2_fh(filp), struct iris_inst, fh); } static void iris_m2m_device_run(void *priv) @@ -126,9 +130,19 @@ iris_m2m_queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_ int iris_open(struct file *filp) { struct iris_core *core = video_drvdata(filp); + struct video_device *vdev; struct iris_inst *inst; + u32 session_type; int ret; + vdev = video_devdata(filp); + if (strcmp(vdev->name, "qcom-iris-decoder") == 0) + session_type = DECODER; + else if (strcmp(vdev->name, "qcom-iris-encoder") == 0) + session_type = ENCODER; + else + return -EINVAL; + ret = pm_runtime_resume_and_get(core->dev); if (ret < 0) return ret; @@ -147,6 +161,7 @@ int iris_open(struct file *filp) return -ENOMEM; inst->core = core; + inst->domain = session_type; inst->session_id = hash32_ptr(inst); inst->state = IRIS_INST_DEINIT; @@ -161,10 +176,12 @@ int iris_open(struct file *filp) INIT_LIST_HEAD(&inst->buffers[BUF_DPB].list); INIT_LIST_HEAD(&inst->buffers[BUF_PERSIST].list); INIT_LIST_HEAD(&inst->buffers[BUF_SCRATCH_1].list); + INIT_LIST_HEAD(&inst->buffers[BUF_SCRATCH_2].list); + INIT_LIST_HEAD(&inst->buffers[BUF_VPSS].list); init_completion(&inst->completion); init_completion(&inst->flush_completion); - iris_v4l2_fh_init(inst); + iris_v4l2_fh_init(inst, filp); inst->m2m_dev = v4l2_m2m_init(&iris_m2m_ops); if (IS_ERR_OR_NULL(inst->m2m_dev)) { @@ -178,14 +195,16 @@ int iris_open(struct file *filp) goto fail_m2m_release; } - ret = iris_vdec_inst_init(inst); + if (inst->domain == DECODER) + ret = iris_vdec_inst_init(inst); + else if (inst->domain == ENCODER) + ret = iris_venc_inst_init(inst); if (ret) goto fail_m2m_ctx_release; iris_add_session(inst); inst->fh.m2m_ctx = inst->m2m_ctx; - filp->private_data = &inst->fh; return 0; @@ -194,7 +213,7 @@ fail_m2m_ctx_release: fail_m2m_release: v4l2_m2m_release(inst->m2m_dev); fail_v4l2_fh_deinit: - iris_v4l2_fh_deinit(inst); + iris_v4l2_fh_deinit(inst, filp); mutex_destroy(&inst->ctx_q_lock); mutex_destroy(&inst->lock); kfree(inst); @@ -240,26 +259,42 @@ static void iris_check_num_queued_internal_buffers(struct iris_inst *inst, u32 p for (i = 0; i < internal_buffer_count; i++) { buffers = &inst->buffers[internal_buf_type[i]]; + count = 0; list_for_each_entry_safe(buf, next, &buffers->list, list) count++; if (count) dev_err(inst->core->dev, "%d buffer of type %d not released", count, internal_buf_type[i]); } + + if (inst->domain == DECODER) + buffers = &inst->buffers[BUF_PERSIST]; + else + buffers = &inst->buffers[BUF_ARP]; + + count = 0; + list_for_each_entry_safe(buf, next, &buffers->list, list) + count++; + if (count) + dev_err(inst->core->dev, "%d buffer of type %d not released", + count, inst->domain == DECODER ? BUF_PERSIST : BUF_ARP); } int iris_close(struct file *filp) { - struct iris_inst *inst = iris_get_inst(filp, NULL); + struct iris_inst *inst = iris_get_inst(filp); v4l2_ctrl_handler_free(&inst->ctrl_handler); v4l2_m2m_ctx_release(inst->m2m_ctx); v4l2_m2m_release(inst->m2m_dev); mutex_lock(&inst->lock); - iris_vdec_inst_deinit(inst); + if (inst->domain == DECODER) + iris_vdec_inst_deinit(inst); + else if (inst->domain == ENCODER) + iris_venc_inst_deinit(inst); iris_session_close(inst); iris_inst_change_state(inst, IRIS_INST_DEINIT); - iris_v4l2_fh_deinit(inst); + iris_v4l2_fh_deinit(inst, filp); iris_destroy_all_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); iris_destroy_all_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); iris_check_num_queued_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); @@ -269,25 +304,34 @@ int iris_close(struct file *filp) mutex_destroy(&inst->ctx_q_lock); mutex_destroy(&inst->lock); kfree(inst); - filp->private_data = NULL; return 0; } static int iris_enum_fmt(struct file *filp, void *fh, struct v4l2_fmtdesc *f) { - struct iris_inst *inst = iris_get_inst(filp, NULL); + struct iris_inst *inst = iris_get_inst(filp); - return iris_vdec_enum_fmt(inst, f); + if (inst->domain == DECODER) + return iris_vdec_enum_fmt(inst, f); + else if (inst->domain == ENCODER) + return iris_venc_enum_fmt(inst, f); + else + return -EINVAL; } static int iris_try_fmt_vid_mplane(struct file *filp, void *fh, struct v4l2_format *f) { - struct iris_inst *inst = iris_get_inst(filp, NULL); - int ret; + struct iris_inst *inst = iris_get_inst(filp); + int ret = 0; mutex_lock(&inst->lock); - ret = iris_vdec_try_fmt(inst, f); + + if (inst->domain == DECODER) + ret = iris_vdec_try_fmt(inst, f); + else if (inst->domain == ENCODER) + ret = iris_venc_try_fmt(inst, f); + mutex_unlock(&inst->lock); return ret; @@ -295,11 +339,16 @@ static int iris_try_fmt_vid_mplane(struct file *filp, void *fh, struct v4l2_form static int iris_s_fmt_vid_mplane(struct file *filp, void *fh, struct v4l2_format *f) { - struct iris_inst *inst = iris_get_inst(filp, NULL); - int ret; + struct iris_inst *inst = iris_get_inst(filp); + int ret = 0; mutex_lock(&inst->lock); - ret = iris_vdec_s_fmt(inst, f); + + if (inst->domain == DECODER) + ret = iris_vdec_s_fmt(inst, f); + else if (inst->domain == ENCODER) + ret = iris_venc_s_fmt(inst, f); + mutex_unlock(&inst->lock); return ret; @@ -307,7 +356,7 @@ static int iris_s_fmt_vid_mplane(struct file *filp, void *fh, struct v4l2_format static int iris_g_fmt_vid_mplane(struct file *filp, void *fh, struct v4l2_format *f) { - struct iris_inst *inst = iris_get_inst(filp, NULL); + struct iris_inst *inst = iris_get_inst(filp); int ret = 0; mutex_lock(&inst->lock); @@ -326,15 +375,20 @@ static int iris_g_fmt_vid_mplane(struct file *filp, void *fh, struct v4l2_format static int iris_enum_framesizes(struct file *filp, void *fh, struct v4l2_frmsizeenum *fsize) { - struct iris_inst *inst = iris_get_inst(filp, NULL); + struct iris_inst *inst = iris_get_inst(filp); struct platform_inst_caps *caps; + int ret = 0; if (fsize->index) return -EINVAL; - if (fsize->pixel_format != V4L2_PIX_FMT_H264 && - fsize->pixel_format != V4L2_PIX_FMT_NV12) - return -EINVAL; + if (inst->domain == DECODER) + ret = iris_vdec_validate_format(inst, fsize->pixel_format); + else + ret = iris_venc_validate_format(inst, fsize->pixel_format); + + if (ret) + return ret; caps = inst->core->iris_platform_data->inst_caps; @@ -346,55 +400,174 @@ static int iris_enum_framesizes(struct file *filp, void *fh, fsize->stepwise.max_height = caps->max_frame_height; fsize->stepwise.step_height = STEP_HEIGHT; + return ret; +} + +static int iris_enum_frameintervals(struct file *filp, void *fh, + struct v4l2_frmivalenum *fival) + +{ + struct iris_inst *inst = iris_get_inst(filp); + struct iris_core *core = inst->core; + struct platform_inst_caps *caps; + u32 fps, mbpf; + int ret = 0; + + if (inst->domain == DECODER) + return -ENOTTY; + + if (fival->index) + return -EINVAL; + + ret = iris_venc_validate_format(inst, fival->pixel_format); + if (ret) + return ret; + + if (!fival->width || !fival->height) + return -EINVAL; + + caps = inst->core->iris_platform_data->inst_caps; + if (fival->width > caps->max_frame_width || + fival->width < caps->min_frame_width || + fival->height > caps->max_frame_height || + fival->height < caps->min_frame_height) + return -EINVAL; + + mbpf = NUM_MBS_PER_FRAME(fival->height, fival->width); + fps = DIV_ROUND_UP(core->iris_platform_data->max_core_mbps, mbpf); + + fival->type = V4L2_FRMIVAL_TYPE_STEPWISE; + fival->stepwise.min.numerator = 1; + fival->stepwise.min.denominator = + min_t(u32, fps, MAXIMUM_FPS); + fival->stepwise.max.numerator = 1; + fival->stepwise.max.denominator = 1; + fival->stepwise.step.numerator = 1; + fival->stepwise.step.denominator = MAXIMUM_FPS; + return 0; } static int iris_querycap(struct file *filp, void *fh, struct v4l2_capability *cap) { + struct iris_inst *inst = iris_get_inst(filp); + strscpy(cap->driver, IRIS_DRV_NAME, sizeof(cap->driver)); - strscpy(cap->card, "Iris Decoder", sizeof(cap->card)); + + if (inst->domain == DECODER) + strscpy(cap->card, "Iris Decoder", sizeof(cap->card)); + else + strscpy(cap->card, "Iris Encoder", sizeof(cap->card)); return 0; } static int iris_g_selection(struct file *filp, void *fh, struct v4l2_selection *s) { - struct iris_inst *inst = iris_get_inst(filp, NULL); + struct iris_inst *inst = iris_get_inst(filp); - if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && + inst->domain == DECODER) return -EINVAL; - switch (s->target) { - case V4L2_SEL_TGT_CROP_BOUNDS: - case V4L2_SEL_TGT_CROP_DEFAULT: - case V4L2_SEL_TGT_CROP: - case V4L2_SEL_TGT_COMPOSE_BOUNDS: - case V4L2_SEL_TGT_COMPOSE_PADDED: - case V4L2_SEL_TGT_COMPOSE_DEFAULT: - case V4L2_SEL_TGT_COMPOSE: + if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && + inst->domain == ENCODER) + return -EINVAL; + + if (inst->domain == DECODER) { + switch (s->target) { + case V4L2_SEL_TGT_CROP_BOUNDS: + case V4L2_SEL_TGT_CROP_DEFAULT: + case V4L2_SEL_TGT_CROP: + case V4L2_SEL_TGT_COMPOSE_BOUNDS: + case V4L2_SEL_TGT_COMPOSE_PADDED: + case V4L2_SEL_TGT_COMPOSE_DEFAULT: + case V4L2_SEL_TGT_COMPOSE: + s->r.left = inst->crop.left; + s->r.top = inst->crop.top; + s->r.width = inst->crop.width; + s->r.height = inst->crop.height; + break; + default: + return -EINVAL; + } + } else if (inst->domain == ENCODER) { + switch (s->target) { + case V4L2_SEL_TGT_CROP_BOUNDS: + case V4L2_SEL_TGT_CROP_DEFAULT: + s->r.width = inst->fmt_src->fmt.pix_mp.width; + s->r.height = inst->fmt_src->fmt.pix_mp.height; + break; + case V4L2_SEL_TGT_CROP: + s->r.width = inst->crop.width; + s->r.height = inst->crop.height; + break; + default: + return -EINVAL; + } s->r.left = inst->crop.left; s->r.top = inst->crop.top; - s->r.width = inst->crop.width; - s->r.height = inst->crop.height; - break; - default: - return -EINVAL; } return 0; } +static int iris_s_selection(struct file *filp, void *fh, struct v4l2_selection *s) +{ + struct iris_inst *inst = iris_get_inst(filp); + + if (inst->domain == DECODER) + return -EINVAL; + else if (inst->domain == ENCODER) + return iris_venc_s_selection(inst, s); + + return -EINVAL; +} + static int iris_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subscription *sub) { struct iris_inst *inst = container_of(fh, struct iris_inst, fh); - return iris_vdec_subscribe_event(inst, sub); + if (inst->domain == DECODER) + return iris_vdec_subscribe_event(inst, sub); + else if (inst->domain == ENCODER) + return iris_venc_subscribe_event(inst, sub); + + return -EINVAL; +} + +static int iris_s_parm(struct file *filp, void *fh, struct v4l2_streamparm *a) +{ + struct iris_inst *inst = iris_get_inst(filp); + + if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && + a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) + return -EINVAL; + + if (inst->domain == ENCODER) + return iris_venc_s_param(inst, a); + else + return -EINVAL; +} + +static int iris_g_parm(struct file *filp, void *fh, struct v4l2_streamparm *a) +{ + struct iris_inst *inst = iris_get_inst(filp); + + if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && + a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) + return -EINVAL; + + if (inst->domain == ENCODER) + return iris_venc_g_param(inst, a); + else + return -EINVAL; } static int iris_dec_cmd(struct file *filp, void *fh, struct v4l2_decoder_cmd *dec) { - struct iris_inst *inst = iris_get_inst(filp, NULL); + struct iris_inst *inst = iris_get_inst(filp); int ret = 0; mutex_lock(&inst->lock); @@ -424,6 +597,39 @@ unlock: return ret; } +static int iris_enc_cmd(struct file *filp, void *fh, + struct v4l2_encoder_cmd *enc) +{ + struct iris_inst *inst = iris_get_inst(filp); + int ret = 0; + + mutex_lock(&inst->lock); + + ret = v4l2_m2m_ioctl_encoder_cmd(filp, fh, enc); + if (ret) + goto unlock; + + if (inst->state == IRIS_INST_DEINIT) + goto unlock; + + if (!iris_allow_cmd(inst, enc->cmd)) { + ret = -EBUSY; + goto unlock; + } + + if (enc->cmd == V4L2_ENC_CMD_START) + ret = iris_venc_start_cmd(inst); + else if (enc->cmd == V4L2_ENC_CMD_STOP) + ret = iris_venc_stop_cmd(inst); + else + ret = -EINVAL; + +unlock: + mutex_unlock(&inst->lock); + + return ret; +} + static struct v4l2_file_operations iris_v4l2_file_ops = { .owner = THIS_MODULE, .open = iris_open, @@ -443,7 +649,7 @@ static const struct vb2_ops iris_vb2_ops = { .buf_queue = iris_vb2_buf_queue, }; -static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops = { +static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops_dec = { .vidioc_enum_fmt_vid_cap = iris_enum_fmt, .vidioc_enum_fmt_vid_out = iris_enum_fmt, .vidioc_try_fmt_vid_cap_mplane = iris_try_fmt_vid_mplane, @@ -471,9 +677,42 @@ static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops = { .vidioc_decoder_cmd = iris_dec_cmd, }; +static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops_enc = { + .vidioc_enum_fmt_vid_cap = iris_enum_fmt, + .vidioc_enum_fmt_vid_out = iris_enum_fmt, + .vidioc_try_fmt_vid_cap_mplane = iris_try_fmt_vid_mplane, + .vidioc_try_fmt_vid_out_mplane = iris_try_fmt_vid_mplane, + .vidioc_s_fmt_vid_cap_mplane = iris_s_fmt_vid_mplane, + .vidioc_s_fmt_vid_out_mplane = iris_s_fmt_vid_mplane, + .vidioc_g_fmt_vid_cap_mplane = iris_g_fmt_vid_mplane, + .vidioc_g_fmt_vid_out_mplane = iris_g_fmt_vid_mplane, + .vidioc_enum_framesizes = iris_enum_framesizes, + .vidioc_enum_frameintervals = iris_enum_frameintervals, + .vidioc_querycap = iris_querycap, + .vidioc_subscribe_event = iris_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, + .vidioc_g_selection = iris_g_selection, + .vidioc_s_selection = iris_s_selection, + .vidioc_s_parm = iris_s_parm, + .vidioc_g_parm = iris_g_parm, + .vidioc_streamon = v4l2_m2m_ioctl_streamon, + .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, + .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, + .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, + .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs, + .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf, + .vidioc_expbuf = v4l2_m2m_ioctl_expbuf, + .vidioc_qbuf = v4l2_m2m_ioctl_qbuf, + .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf, + .vidioc_remove_bufs = v4l2_m2m_ioctl_remove_bufs, + .vidioc_try_encoder_cmd = v4l2_m2m_ioctl_try_encoder_cmd, + .vidioc_encoder_cmd = iris_enc_cmd, +}; + void iris_init_ops(struct iris_core *core) { core->iris_v4l2_file_ops = &iris_v4l2_file_ops; core->iris_vb2_ops = &iris_vb2_ops; - core->iris_v4l2_ioctl_ops = &iris_v4l2_ioctl_ops; + core->iris_v4l2_ioctl_ops_dec = &iris_v4l2_ioctl_ops_dec; + core->iris_v4l2_ioctl_ops_enc = &iris_v4l2_ioctl_ops_enc; } diff --git a/drivers/media/platform/qcom/iris/iris_vpu2.c b/drivers/media/platform/qcom/iris/iris_vpu2.c index 7cf1bfc352d3..de7d142316d2 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu2.c +++ b/drivers/media/platform/qcom/iris/iris_vpu2.c @@ -34,6 +34,8 @@ static u64 iris_vpu2_calc_freq(struct iris_inst *inst, size_t data_size) const struct vpu_ops iris_vpu2_ops = { .power_off_hw = iris_vpu_power_off_hw, + .power_on_hw = iris_vpu_power_on_hw, .power_off_controller = iris_vpu_power_off_controller, + .power_on_controller = iris_vpu_power_on_controller, .calc_freq = iris_vpu2_calc_freq, }; diff --git a/drivers/media/platform/qcom/iris/iris_vpu3x.c b/drivers/media/platform/qcom/iris/iris_vpu3x.c index 9b7c9a1495ee..339776a0b467 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu3x.c +++ b/drivers/media/platform/qcom/iris/iris_vpu3x.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2025 Linaro Ltd */ #include <linux/iopoll.h> @@ -19,8 +20,13 @@ #define WRAPPER_IRIS_CPU_NOC_LPI_CONTROL (WRAPPER_BASE_OFFS + 0x5C) #define REQ_POWER_DOWN_PREP BIT(0) #define WRAPPER_IRIS_CPU_NOC_LPI_STATUS (WRAPPER_BASE_OFFS + 0x60) +#define NOC_LPI_STATUS_DONE BIT(0) /* Indicates the NOC handshake is complete */ +#define NOC_LPI_STATUS_DENY BIT(1) /* Indicates the NOC handshake is denied */ +#define NOC_LPI_STATUS_ACTIVE BIT(2) /* Indicates the NOC is active */ #define WRAPPER_CORE_CLOCK_CONFIG (WRAPPER_BASE_OFFS + 0x88) #define CORE_CLK_RUN 0x0 +/* VPU v3.5 */ +#define WRAPPER_IRIS_VCODEC_VPU_WRAPPER_SPARE_0 (WRAPPER_BASE_OFFS + 0x78) #define WRAPPER_TZ_CTL_AXI_CLOCK_CONFIG (WRAPPER_TZ_BASE_OFFS + 0x14) #define CTL_AXI_CLK_HALT BIT(0) @@ -52,6 +58,8 @@ #define AON_WRAPPER_MVP_NOC_CORE_CLK_CONTROL (AON_BASE_OFFS + 0x20) #define NOC_HALT BIT(0) #define AON_WRAPPER_SPARE (AON_BASE_OFFS + 0x28) +#define AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_CONTROL (AON_BASE_OFFS + 0x2C) +#define AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_STATUS (AON_BASE_OFFS + 0x30) static bool iris_vpu3x_hw_power_collapsed(struct iris_core *core) { @@ -109,7 +117,9 @@ disable_power: static void iris_vpu33_power_off_hardware(struct iris_core *core) { + bool handshake_done = false, handshake_busy = false; u32 reg_val = 0, value, i; + u32 count = 0; int ret; if (iris_vpu3x_hw_power_collapsed(core)) @@ -128,13 +138,36 @@ static void iris_vpu33_power_off_hardware(struct iris_core *core) goto disable_power; } + /* Retry up to 1000 times as recommended by hardware documentation */ + do { + /* set MNoC to low power */ + writel(REQ_POWER_DOWN_PREP, core->reg_base + AON_WRAPPER_MVP_NOC_LPI_CONTROL); + + udelay(15); + + value = readl(core->reg_base + AON_WRAPPER_MVP_NOC_LPI_STATUS); + + handshake_done = value & NOC_LPI_STATUS_DONE; + handshake_busy = value & (NOC_LPI_STATUS_DENY | NOC_LPI_STATUS_ACTIVE); + + if (handshake_done || !handshake_busy) + break; + + writel(0, core->reg_base + AON_WRAPPER_MVP_NOC_LPI_CONTROL); + + udelay(15); + + } while (++count < 1000); + + if (!handshake_done && handshake_busy) + dev_err(core->dev, "LPI handshake timeout\n"); + ret = readl_poll_timeout(core->reg_base + AON_WRAPPER_MVP_NOC_LPI_STATUS, reg_val, reg_val & BIT(0), 200, 2000); if (ret) goto disable_power; - /* set MNoC to low power, set PD_NOC_QREQ (bit 0) */ - writel(BIT(0), core->reg_base + AON_WRAPPER_MVP_NOC_LPI_CONTROL); + writel(0, core->reg_base + AON_WRAPPER_MVP_NOC_LPI_CONTROL); writel(CORE_BRIDGE_SW_RESET | CORE_BRIDGE_HW_RESET_DISABLE, core->reg_base + CPU_CS_AHB_BRIDGE_SYNC_RESET); @@ -225,6 +258,158 @@ disable_power: return 0; } +static int iris_vpu35_power_on_hw(struct iris_core *core) +{ + int ret; + + ret = iris_enable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN]); + if (ret) + return ret; + + ret = iris_prepare_enable_clock(core, IRIS_AXI_CLK); + if (ret) + goto err_disable_power; + + ret = iris_prepare_enable_clock(core, IRIS_HW_FREERUN_CLK); + if (ret) + goto err_disable_axi_clk; + + ret = iris_prepare_enable_clock(core, IRIS_HW_CLK); + if (ret) + goto err_disable_hw_free_clk; + + ret = dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN], true); + if (ret) + goto err_disable_hw_clk; + + return 0; + +err_disable_hw_clk: + iris_disable_unprepare_clock(core, IRIS_HW_CLK); +err_disable_hw_free_clk: + iris_disable_unprepare_clock(core, IRIS_HW_FREERUN_CLK); +err_disable_axi_clk: + iris_disable_unprepare_clock(core, IRIS_AXI_CLK); +err_disable_power: + iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN]); + + return ret; +} + +static void iris_vpu35_power_off_hw(struct iris_core *core) +{ + iris_vpu33_power_off_hardware(core); + + iris_disable_unprepare_clock(core, IRIS_HW_FREERUN_CLK); + iris_disable_unprepare_clock(core, IRIS_AXI_CLK); +} + +static int iris_vpu35_power_off_controller(struct iris_core *core) +{ + u32 clk_rst_tbl_size = core->iris_platform_data->clk_rst_tbl_size; + unsigned int count = 0; + u32 val = 0; + bool handshake_done, handshake_busy; + int ret; + + writel(MSK_SIGNAL_FROM_TENSILICA | MSK_CORE_POWER_ON, core->reg_base + CPU_CS_X2RPMH); + + writel(REQ_POWER_DOWN_PREP, core->reg_base + WRAPPER_IRIS_CPU_NOC_LPI_CONTROL); + + ret = readl_poll_timeout(core->reg_base + WRAPPER_IRIS_CPU_NOC_LPI_STATUS, + val, val & BIT(0), 200, 2000); + if (ret) + goto disable_power; + + writel(0, core->reg_base + WRAPPER_IRIS_CPU_NOC_LPI_CONTROL); + + /* Retry up to 1000 times as recommended by hardware documentation */ + do { + /* set MNoC to low power */ + writel(REQ_POWER_DOWN_PREP, core->reg_base + AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_CONTROL); + + udelay(15); + + val = readl(core->reg_base + AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_STATUS); + + handshake_done = val & NOC_LPI_STATUS_DONE; + handshake_busy = val & (NOC_LPI_STATUS_DENY | NOC_LPI_STATUS_ACTIVE); + + if (handshake_done || !handshake_busy) + break; + + writel(0, core->reg_base + AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_CONTROL); + + udelay(15); + + } while (++count < 1000); + + if (!handshake_done && handshake_busy) + dev_err(core->dev, "LPI handshake timeout\n"); + + ret = readl_poll_timeout(core->reg_base + AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_STATUS, + val, val & BIT(0), 200, 2000); + if (ret) + goto disable_power; + + writel(0, core->reg_base + AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_CONTROL); + + writel(0, core->reg_base + WRAPPER_DEBUG_BRIDGE_LPI_CONTROL); + + ret = readl_poll_timeout(core->reg_base + WRAPPER_DEBUG_BRIDGE_LPI_STATUS, + val, val == 0, 200, 2000); + if (ret) + goto disable_power; + +disable_power: + iris_disable_unprepare_clock(core, IRIS_CTRL_CLK); + iris_disable_unprepare_clock(core, IRIS_CTRL_FREERUN_CLK); + iris_disable_unprepare_clock(core, IRIS_AXI1_CLK); + + iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); + + reset_control_bulk_reset(clk_rst_tbl_size, core->resets); + + return 0; +} + +static int iris_vpu35_power_on_controller(struct iris_core *core) +{ + int ret; + + ret = iris_enable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); + if (ret) + return ret; + + ret = iris_prepare_enable_clock(core, IRIS_AXI1_CLK); + if (ret) + goto err_disable_power; + + ret = iris_prepare_enable_clock(core, IRIS_CTRL_FREERUN_CLK); + if (ret) + goto err_disable_axi1_clk; + + ret = iris_prepare_enable_clock(core, IRIS_CTRL_CLK); + if (ret) + goto err_disable_ctrl_free_clk; + + return 0; + +err_disable_ctrl_free_clk: + iris_disable_unprepare_clock(core, IRIS_CTRL_FREERUN_CLK); +err_disable_axi1_clk: + iris_disable_unprepare_clock(core, IRIS_AXI1_CLK); +err_disable_power: + iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); + + return ret; +} + +static void iris_vpu35_program_bootup_registers(struct iris_core *core) +{ + writel(0x1, core->reg_base + WRAPPER_IRIS_VCODEC_VPU_WRAPPER_SPARE_0); +} + static u64 iris_vpu3x_calculate_frequency(struct iris_inst *inst, size_t data_size) { struct platform_inst_caps *caps = inst->core->iris_platform_data->inst_caps; @@ -264,12 +449,25 @@ static u64 iris_vpu3x_calculate_frequency(struct iris_inst *inst, size_t data_si const struct vpu_ops iris_vpu3_ops = { .power_off_hw = iris_vpu3_power_off_hardware, + .power_on_hw = iris_vpu_power_on_hw, .power_off_controller = iris_vpu_power_off_controller, + .power_on_controller = iris_vpu_power_on_controller, .calc_freq = iris_vpu3x_calculate_frequency, }; const struct vpu_ops iris_vpu33_ops = { .power_off_hw = iris_vpu33_power_off_hardware, + .power_on_hw = iris_vpu_power_on_hw, .power_off_controller = iris_vpu33_power_off_controller, + .power_on_controller = iris_vpu_power_on_controller, + .calc_freq = iris_vpu3x_calculate_frequency, +}; + +const struct vpu_ops iris_vpu35_ops = { + .power_off_hw = iris_vpu35_power_off_hw, + .power_on_hw = iris_vpu35_power_on_hw, + .power_off_controller = iris_vpu35_power_off_controller, + .power_on_controller = iris_vpu35_power_on_controller, + .program_bootup_registers = iris_vpu35_program_bootup_registers, .calc_freq = iris_vpu3x_calculate_frequency, }; diff --git a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c index f92fd39fe310..4463be05ce16 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c +++ b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c @@ -5,6 +5,14 @@ #include "iris_instance.h" #include "iris_vpu_buffer.h" +#include "iris_hfi_gen1_defines.h" +#include "iris_hfi_gen2_defines.h" + +#define HFI_MAX_COL_FRAME 6 + +#ifndef SYSTEM_LAL_TILE10 +#define SYSTEM_LAL_TILE10 192 +#endif static u32 size_h264d_hw_bin_buffer(u32 frame_width, u32 frame_height, u32 num_vpp_pipes) { @@ -548,6 +556,858 @@ static u32 iris_vpu_dec_scratch1_size(struct iris_inst *inst) iris_vpu_dec_line_size(inst); } +static inline u32 size_bin_bitstream_enc(u32 width, u32 height, + u32 rc_type) +{ + u32 aligned_height = ALIGN(height, 32); + u32 aligned_width = ALIGN(width, 32); + u32 frame_size = width * height * 3; + u32 mbs_per_frame; + + /* + * Encoder output size calculation: 32 Align width/height + * For resolution < 720p : YUVsize * 4 + * For resolution > 720p & <= 4K : YUVsize / 2 + * For resolution > 4k : YUVsize / 4 + * Initially frame_size = YUVsize * 2; + */ + + mbs_per_frame = (ALIGN(aligned_height, 16) * ALIGN(aligned_width, 16)) / 256; + + if (mbs_per_frame < NUM_MBS_720P) + frame_size = frame_size << 1; + else if (mbs_per_frame <= NUM_MBS_4K) + frame_size = frame_size >> 2; + else + frame_size = frame_size >> 3; + + if (rc_type == HFI_RATE_CONTROL_OFF || rc_type == HFI_RATE_CONTROL_CQ || + rc_type == HFI_RC_OFF || rc_type == HFI_RC_CQ) + frame_size = frame_size << 1; + + /* + * In case of opaque color format bitdepth will be known + * with first ETB, buffers allocated already with 8 bit + * won't be sufficient for 10 bit + * calculate size considering 10-bit by default + * For 10-bit cases size = size * 1.25 + */ + frame_size *= 5; + frame_size /= 4; + + return ALIGN(frame_size, SZ_4K); +} + +static inline u32 hfi_buffer_bin_enc(u32 width, u32 height, + u32 work_mode, u32 lcu_size, + u32 num_vpp_pipes, u32 rc_type) +{ + u32 sao_bin_buffer_size, padded_bin_size, bitstream_size; + u32 total_bitbin_buffers, size_single_pipe, bitbin_size; + u32 aligned_height = ALIGN(height, lcu_size); + u32 aligned_width = ALIGN(width, lcu_size); + + bitstream_size = size_bin_bitstream_enc(width, height, rc_type); + bitstream_size = ALIGN(bitstream_size, 256); + + if (work_mode == STAGE_2) { + total_bitbin_buffers = 3; + bitbin_size = bitstream_size * 17 / 10; + bitbin_size = ALIGN(bitbin_size, 256); + } else { + total_bitbin_buffers = 1; + bitstream_size = aligned_width * aligned_height * 3; + bitbin_size = ALIGN(bitstream_size, 256); + } + + if (num_vpp_pipes > 2) + size_single_pipe = bitbin_size / 2; + else + size_single_pipe = bitbin_size; + + size_single_pipe = ALIGN(size_single_pipe, 256); + sao_bin_buffer_size = (64 * (((width + 32) * (height + 32)) >> 10)) + 384; + padded_bin_size = ALIGN(size_single_pipe, 256); + size_single_pipe = sao_bin_buffer_size + padded_bin_size; + size_single_pipe = ALIGN(size_single_pipe, 256); + bitbin_size = size_single_pipe * num_vpp_pipes; + + return ALIGN(bitbin_size, 256) * total_bitbin_buffers + 512; +} + +static u32 iris_vpu_enc_bin_size(struct iris_inst *inst) +{ + u32 num_vpp_pipes = inst->core->iris_platform_data->num_vpp_pipe; + u32 stage = inst->fw_caps[STAGE].value; + struct v4l2_format *f = inst->fmt_dst; + u32 height = f->fmt.pix_mp.height; + u32 width = f->fmt.pix_mp.width; + u32 lcu_size; + + if (inst->codec == V4L2_PIX_FMT_HEVC) + lcu_size = 32; + else + lcu_size = 16; + + return hfi_buffer_bin_enc(width, height, stage, lcu_size, + num_vpp_pipes, inst->hfi_rc_type); +} + +static inline +u32 hfi_buffer_comv_enc(u32 frame_width, u32 frame_height, u32 lcu_size, + u32 num_recon, u32 standard) +{ + u32 height_in_lcus = ((frame_height) + (lcu_size) - 1) / (lcu_size); + u32 width_in_lcus = ((frame_width) + (lcu_size) - 1) / (lcu_size); + u32 num_lcu_in_frame = width_in_lcus * height_in_lcus; + u32 mb_height = ((frame_height) + 15) >> 4; + u32 mb_width = ((frame_width) + 15) >> 4; + u32 size_colloc_mv, size_colloc_rc; + + size_colloc_mv = (standard == HFI_CODEC_ENCODE_HEVC) ? + (16 * ((num_lcu_in_frame << 2) + 32)) : + (3 * 16 * (width_in_lcus * height_in_lcus + 32)); + size_colloc_mv = ALIGN(size_colloc_mv, 256) * num_recon; + size_colloc_rc = (((mb_width + 7) >> 3) * 16 * 2 * mb_height); + size_colloc_rc = ALIGN(size_colloc_rc, 256) * HFI_MAX_COL_FRAME; + + return size_colloc_mv + size_colloc_rc; +} + +static u32 iris_vpu_enc_comv_size(struct iris_inst *inst) +{ + struct v4l2_format *f = inst->fmt_dst; + u32 height = f->fmt.pix_mp.height; + u32 width = f->fmt.pix_mp.width; + u32 num_recon = 1; + u32 lcu_size = 16; + + if (inst->codec == V4L2_PIX_FMT_HEVC) { + lcu_size = 32; + return hfi_buffer_comv_enc(width, height, lcu_size, + num_recon + 1, HFI_CODEC_ENCODE_HEVC); + } + + return hfi_buffer_comv_enc(width, height, lcu_size, + num_recon + 1, HFI_CODEC_ENCODE_AVC); +} + +static inline +u32 size_frame_rc_buf_size(u32 standard, u32 frame_height_coded, + u32 num_vpp_pipes_enc) +{ + u32 size = 0; + + size = (standard == HFI_CODEC_ENCODE_HEVC) ? + (256 + 16 * (14 + ((((frame_height_coded) >> 5) + 7) >> 3))) : + (256 + 16 * (14 + ((((frame_height_coded) >> 4) + 7) >> 3))); + size *= 11; + + if (num_vpp_pipes_enc > 1) + size = ALIGN(size, 256) * num_vpp_pipes_enc; + + return ALIGN(size, 512) * HFI_MAX_COL_FRAME; +} + +static inline +u32 size_enc_slice_info_buf(u32 num_lcu_in_frame) +{ + return ALIGN((256 + (num_lcu_in_frame << 4)), 256); +} + +static inline u32 enc_bitcnt_buf_size(u32 num_lcu_in_frame) +{ + return ALIGN((256 + (4 * (num_lcu_in_frame))), 256); +} + +static inline u32 enc_bitmap_buf_size(u32 num_lcu_in_frame) +{ + return ALIGN((256 + ((num_lcu_in_frame) >> 3)), 256); +} + +static inline u32 size_override_buf(u32 num_lcumb) +{ + return ALIGN(((16 * (((num_lcumb) + 7) >> 3))), 256) * 2; +} + +static inline u32 size_ir_buf(u32 num_lcu_in_frame) +{ + return ALIGN((((((num_lcu_in_frame) << 1) + 7) & (~7)) * 3), 256); +} + +static inline +u32 size_linebuff_data(bool is_ten_bit, u32 frame_width_coded) +{ + return is_ten_bit ? + (((((10 * (frame_width_coded) + 1024) + (256 - 1)) & + (~(256 - 1))) * 1) + + (((((10 * (frame_width_coded) + 1024) >> 1) + (256 - 1)) & + (~(256 - 1))) * 2)) : + (((((8 * (frame_width_coded) + 1024) + (256 - 1)) & + (~(256 - 1))) * 1) + + (((((8 * (frame_width_coded) + 1024) >> 1) + (256 - 1)) & + (~(256 - 1))) * 2)); +} + +static inline +u32 size_left_linebuff_ctrl(u32 standard, u32 frame_height_coded, + u32 num_vpp_pipes_enc) +{ + u32 size = 0; + + size = standard == HFI_CODEC_ENCODE_HEVC ? + (((frame_height_coded) + + (32)) / 32 * 4 * 16) : + (((frame_height_coded) + 15) / 16 * 5 * 16); + + if ((num_vpp_pipes_enc) > 1) { + size += 512; + size = ALIGN(size, 512) * + num_vpp_pipes_enc; + } + + return ALIGN(size, 256); +} + +static inline +u32 size_left_linebuff_recon_pix(bool is_ten_bit, u32 frame_height_coded, + u32 num_vpp_pipes_enc) +{ + return (((is_ten_bit + 1) * 2 * (frame_height_coded) + 256) + + (256 << (num_vpp_pipes_enc - 1)) - 1) & + (~((256 << (num_vpp_pipes_enc - 1)) - 1)) * 1; +} + +static inline +u32 size_top_linebuff_ctrl_fe(u32 frame_width_coded, u32 standard) +{ + return standard == HFI_CODEC_ENCODE_HEVC ? + ALIGN((64 * ((frame_width_coded) >> 5)), 256) : + ALIGN((256 + 16 * ((frame_width_coded) >> 4)), 256); +} + +static inline +u32 size_left_linebuff_ctrl_fe(u32 frame_height_coded, u32 num_vpp_pipes_enc) +{ + return (((256 + 64 * ((frame_height_coded) >> 4)) + + (256 << (num_vpp_pipes_enc - 1)) - 1) & + (~((256 << (num_vpp_pipes_enc - 1)) - 1)) * 1) * + num_vpp_pipes_enc; +} + +static inline +u32 size_left_linebuff_metadata_recon_y(u32 frame_height_coded, + bool is_ten_bit, + u32 num_vpp_pipes_enc) +{ + return ALIGN(((256 + 64 * ((frame_height_coded) / + (8 * (is_ten_bit ? 4 : 8))))), 256) * num_vpp_pipes_enc; +} + +static inline +u32 size_left_linebuff_metadata_recon_uv(u32 frame_height_coded, + bool is_ten_bit, + u32 num_vpp_pipes_enc) +{ + return ALIGN(((256 + 64 * ((frame_height_coded) / + (4 * (is_ten_bit ? 4 : 8))))), 256) * num_vpp_pipes_enc; +} + +static inline +u32 size_linebuff_recon_pix(bool is_ten_bit, u32 frame_width_coded) +{ + return ALIGN(((is_ten_bit ? 3 : 2) * (frame_width_coded)), 256); +} + +static inline +u32 size_line_buf_ctrl(u32 frame_width_coded) +{ + return ALIGN(frame_width_coded, 256); +} + +static inline +u32 size_line_buf_ctrl_id2(u32 frame_width_coded) +{ + return ALIGN(frame_width_coded, 256); +} + +static inline u32 size_line_buf_sde(u32 frame_width_coded) +{ + return ALIGN((256 + (16 * ((frame_width_coded) >> 4))), 256); +} + +static inline +u32 size_vpss_line_buf(u32 num_vpp_pipes_enc, u32 frame_height_coded, + u32 frame_width_coded) +{ + return ALIGN(((((((8192) >> 2) << 5) * (num_vpp_pipes_enc)) + 64) + + (((((max_t(u32, (frame_width_coded), + (frame_height_coded)) + 3) >> 2) << 5) + 256) * 16)), 256); +} +static inline +u32 size_vpss_line_buf_vpu33(u32 num_vpp_pipes_enc, u32 frame_height_coded, + u32 frame_width_coded) +{ + u32 vpss_4tap_top, vpss_4tap_left, vpss_div2_top; + u32 vpss_div2_left, vpss_top_lb, vpss_left_lb; + u32 size_left, size_top; + u32 max_width_height; + + max_width_height = max_t(u32, frame_width_coded, frame_height_coded); + vpss_4tap_top = ((((max_width_height * 2) + 3) >> 2) << 4) + 256; + vpss_4tap_left = (((8192 + 3) >> 2) << 5) + 64; + vpss_div2_top = (((max_width_height + 3) >> 2) << 4) + 256; + vpss_div2_left = ((((max_width_height * 2) + 3) >> 2) << 5) + 64; + vpss_top_lb = (frame_width_coded + 1) << 3; + vpss_left_lb = (frame_height_coded << 3) * num_vpp_pipes_enc; + size_left = (vpss_4tap_left + vpss_div2_left) * 2 * num_vpp_pipes_enc; + size_top = (vpss_4tap_top + vpss_div2_top) * 2; + + return ALIGN(size_left + size_top + vpss_top_lb + vpss_left_lb, DMA_ALIGNMENT); +} + +static inline +u32 size_top_line_buf_first_stg_sao(u32 frame_width_coded) +{ + return ALIGN((16 * ((frame_width_coded) >> 5)), 256); +} + +static inline +u32 size_enc_ref_buffer(u32 frame_width, u32 frame_height) +{ + u32 u_chroma_buffer_height = ALIGN(frame_height >> 1, 32); + u32 u_buffer_height = ALIGN(frame_height, 32); + u32 u_buffer_width = ALIGN(frame_width, 32); + + return (u_buffer_height + u_chroma_buffer_height) * u_buffer_width; +} + +static inline +u32 size_enc_ten_bit_ref_buffer(u32 frame_width, u32 frame_height) +{ + u32 ref_luma_stride_in_bytes = ((frame_width + SYSTEM_LAL_TILE10 - 1) / SYSTEM_LAL_TILE10) * + SYSTEM_LAL_TILE10; + u32 ref_buf_height = (frame_height + (32 - 1)) & (~(32 - 1)); + u32 u_ref_stride, luma_size; + u32 ref_chrm_height_in_bytes; + u32 chroma_size; + + u_ref_stride = 4 * (ref_luma_stride_in_bytes / 3); + u_ref_stride = (u_ref_stride + (128 - 1)) & (~(128 - 1)); + luma_size = ref_buf_height * u_ref_stride; + luma_size = (luma_size + (4096 - 1)) & (~(4096 - 1)); + + ref_chrm_height_in_bytes = (((frame_height + 1) >> 1) + (32 - 1)) & (~(32 - 1)); + chroma_size = u_ref_stride * ref_chrm_height_in_bytes; + chroma_size = (chroma_size + (4096 - 1)) & (~(4096 - 1)); + + return luma_size + chroma_size; +} + +static inline +u32 hfi_ubwc_calc_metadata_plane_stride(u32 frame_width, + u32 metadata_stride_multiple, + u32 tile_width_in_pels) +{ + return ALIGN(((frame_width + (tile_width_in_pels - 1)) / tile_width_in_pels), + metadata_stride_multiple); +} + +static inline +u32 hfi_ubwc_metadata_plane_bufheight(u32 frame_height, + u32 metadata_height_multiple, + u32 tile_height_in_pels) +{ + return ALIGN(((frame_height + (tile_height_in_pels - 1)) / tile_height_in_pels), + metadata_height_multiple); +} + +static inline +u32 hfi_ubwc_metadata_plane_buffer_size(u32 _metadata_tride, u32 _metadata_buf_height) +{ + return ALIGN(_metadata_tride * _metadata_buf_height, 4096); +} + +static inline +u32 hfi_buffer_non_comv_enc(u32 frame_width, u32 frame_height, + u32 num_vpp_pipes_enc, u32 lcu_size, u32 standard) +{ + u32 height_in_lcus = ((frame_height) + (lcu_size) - 1) / (lcu_size); + u32 width_in_lcus = ((frame_width) + (lcu_size) - 1) / (lcu_size); + u32 num_lcu_in_frame = width_in_lcus * height_in_lcus; + u32 frame_height_coded = height_in_lcus * (lcu_size); + u32 frame_width_coded = width_in_lcus * (lcu_size); + u32 num_lcumb, frame_rc_buf_size; + + num_lcumb = (frame_height_coded / lcu_size) * + ((frame_width_coded + lcu_size * 8) / lcu_size); + frame_rc_buf_size = size_frame_rc_buf_size(standard, frame_height_coded, + num_vpp_pipes_enc); + return size_enc_slice_info_buf(num_lcu_in_frame) + + SIZE_SLICE_CMD_BUFFER + + SIZE_SPS_PPS_SLICE_HDR + + frame_rc_buf_size + + enc_bitcnt_buf_size(num_lcu_in_frame) + + enc_bitmap_buf_size(num_lcu_in_frame) + + SIZE_BSE_SLICE_CMD_BUF + + SIZE_LAMBDA_LUT + + size_override_buf(num_lcumb) + + size_ir_buf(num_lcu_in_frame); +} + +static u32 iris_vpu_enc_non_comv_size(struct iris_inst *inst) +{ + u32 num_vpp_pipes = inst->core->iris_platform_data->num_vpp_pipe; + struct v4l2_format *f = inst->fmt_dst; + u32 height = f->fmt.pix_mp.height; + u32 width = f->fmt.pix_mp.width; + u32 lcu_size = 16; + + if (inst->codec == V4L2_PIX_FMT_HEVC) { + lcu_size = 32; + return hfi_buffer_non_comv_enc(width, height, num_vpp_pipes, + lcu_size, HFI_CODEC_ENCODE_HEVC) + + SIZE_ONE_SLICE_BUF; + } + + return hfi_buffer_non_comv_enc(width, height, num_vpp_pipes, + lcu_size, HFI_CODEC_ENCODE_AVC); +} + +static inline +u32 hfi_buffer_line_enc_base(u32 frame_width, u32 frame_height, bool is_ten_bit, + u32 num_vpp_pipes_enc, u32 lcu_size, u32 standard) +{ + u32 width_in_lcus = ((frame_width) + (lcu_size) - 1) / (lcu_size); + u32 height_in_lcus = ((frame_height) + (lcu_size) - 1) / (lcu_size); + u32 frame_height_coded = height_in_lcus * (lcu_size); + u32 frame_width_coded = width_in_lcus * (lcu_size); + u32 line_buff_data_size, left_line_buff_ctrl_size; + u32 left_line_buff_metadata_recon__uv__size; + u32 left_line_buff_metadata_recon__y__size; + u32 left_line_buff_recon_pix_size; + u32 top_line_buff_ctrl_fe_size; + u32 line_buff_recon_pix_size; + + line_buff_data_size = size_linebuff_data(is_ten_bit, frame_width_coded); + left_line_buff_ctrl_size = + size_left_linebuff_ctrl(standard, frame_height_coded, num_vpp_pipes_enc); + left_line_buff_recon_pix_size = + size_left_linebuff_recon_pix(is_ten_bit, frame_height_coded, + num_vpp_pipes_enc); + top_line_buff_ctrl_fe_size = + size_top_linebuff_ctrl_fe(frame_width_coded, standard); + left_line_buff_metadata_recon__y__size = + size_left_linebuff_metadata_recon_y(frame_height_coded, is_ten_bit, + num_vpp_pipes_enc); + left_line_buff_metadata_recon__uv__size = + size_left_linebuff_metadata_recon_uv(frame_height_coded, is_ten_bit, + num_vpp_pipes_enc); + line_buff_recon_pix_size = size_linebuff_recon_pix(is_ten_bit, frame_width_coded); + + return size_line_buf_ctrl(frame_width_coded) + + size_line_buf_ctrl_id2(frame_width_coded) + + line_buff_data_size + + left_line_buff_ctrl_size + + left_line_buff_recon_pix_size + + top_line_buff_ctrl_fe_size + + left_line_buff_metadata_recon__y__size + + left_line_buff_metadata_recon__uv__size + + line_buff_recon_pix_size + + size_left_linebuff_ctrl_fe(frame_height_coded, num_vpp_pipes_enc) + + size_line_buf_sde(frame_width_coded) + + size_top_line_buf_first_stg_sao(frame_width_coded); +} + +static inline +u32 hfi_buffer_line_enc(u32 frame_width, u32 frame_height, bool is_ten_bit, + u32 num_vpp_pipes_enc, u32 lcu_size, u32 standard) +{ + u32 width_in_lcus = ((frame_width) + (lcu_size) - 1) / (lcu_size); + u32 height_in_lcus = ((frame_height) + (lcu_size) - 1) / (lcu_size); + u32 frame_height_coded = height_in_lcus * (lcu_size); + u32 frame_width_coded = width_in_lcus * (lcu_size); + + return hfi_buffer_line_enc_base(frame_width, frame_height, is_ten_bit, + num_vpp_pipes_enc, lcu_size, standard) + + size_vpss_line_buf(num_vpp_pipes_enc, frame_height_coded, frame_width_coded); +} + +static inline +u32 hfi_buffer_line_enc_vpu33(u32 frame_width, u32 frame_height, bool is_ten_bit, + u32 num_vpp_pipes_enc, u32 lcu_size, u32 standard) +{ + u32 width_in_lcus = ((frame_width) + (lcu_size) - 1) / (lcu_size); + u32 height_in_lcus = ((frame_height) + (lcu_size) - 1) / (lcu_size); + u32 frame_height_coded = height_in_lcus * (lcu_size); + u32 frame_width_coded = width_in_lcus * (lcu_size); + + return hfi_buffer_line_enc_base(frame_width, frame_height, is_ten_bit, + num_vpp_pipes_enc, lcu_size, standard) + + size_vpss_line_buf_vpu33(num_vpp_pipes_enc, frame_height_coded, + frame_width_coded); +} + +static u32 iris_vpu_enc_line_size(struct iris_inst *inst) +{ + u32 num_vpp_pipes = inst->core->iris_platform_data->num_vpp_pipe; + struct v4l2_format *f = inst->fmt_dst; + u32 height = f->fmt.pix_mp.height; + u32 width = f->fmt.pix_mp.width; + u32 lcu_size = 16; + + if (inst->codec == V4L2_PIX_FMT_HEVC) { + lcu_size = 32; + return hfi_buffer_line_enc(width, height, 0, num_vpp_pipes, + lcu_size, HFI_CODEC_ENCODE_HEVC); + } + + return hfi_buffer_line_enc(width, height, 0, num_vpp_pipes, + lcu_size, HFI_CODEC_ENCODE_AVC); +} + +static u32 iris_vpu33_enc_line_size(struct iris_inst *inst) +{ + u32 num_vpp_pipes = inst->core->iris_platform_data->num_vpp_pipe; + struct v4l2_format *f = inst->fmt_dst; + u32 height = f->fmt.pix_mp.height; + u32 width = f->fmt.pix_mp.width; + u32 lcu_size = 16; + + if (inst->codec == V4L2_PIX_FMT_HEVC) { + lcu_size = 32; + return hfi_buffer_line_enc_vpu33(width, height, 0, num_vpp_pipes, + lcu_size, HFI_CODEC_ENCODE_HEVC); + } + + return hfi_buffer_line_enc_vpu33(width, height, 0, num_vpp_pipes, + lcu_size, HFI_CODEC_ENCODE_AVC); +} + +static inline +u32 hfi_buffer_dpb_enc(u32 frame_width, u32 frame_height, bool is_ten_bit) +{ + u32 metadata_stride, metadata_buf_height, meta_size_y, meta_size_c; + u32 ten_bit_ref_buf_size = 0, ref_buf_size = 0; + u32 size; + + if (!is_ten_bit) { + ref_buf_size = size_enc_ref_buffer(frame_width, frame_height); + metadata_stride = + hfi_ubwc_calc_metadata_plane_stride(frame_width, 64, + HFI_COL_FMT_NV12C_Y_TILE_WIDTH); + metadata_buf_height = + hfi_ubwc_metadata_plane_bufheight(frame_height, 16, + HFI_COL_FMT_NV12C_Y_TILE_HEIGHT); + meta_size_y = + hfi_ubwc_metadata_plane_buffer_size(metadata_stride, metadata_buf_height); + meta_size_c = + hfi_ubwc_metadata_plane_buffer_size(metadata_stride, metadata_buf_height); + size = ref_buf_size + meta_size_y + meta_size_c; + } else { + ten_bit_ref_buf_size = size_enc_ten_bit_ref_buffer(frame_width, frame_height); + metadata_stride = + hfi_ubwc_calc_metadata_plane_stride(frame_width, + IRIS_METADATA_STRIDE_MULTIPLE, + HFI_COL_FMT_TP10C_Y_TILE_WIDTH); + metadata_buf_height = + hfi_ubwc_metadata_plane_bufheight(frame_height, + IRIS_METADATA_HEIGHT_MULTIPLE, + HFI_COL_FMT_TP10C_Y_TILE_HEIGHT); + meta_size_y = + hfi_ubwc_metadata_plane_buffer_size(metadata_stride, metadata_buf_height); + meta_size_c = + hfi_ubwc_metadata_plane_buffer_size(metadata_stride, metadata_buf_height); + size = ten_bit_ref_buf_size + meta_size_y + meta_size_c; + } + + return size; +} + +static u32 iris_vpu_enc_arp_size(struct iris_inst *inst) +{ + return HFI_BUFFER_ARP_ENC; +} + +inline bool is_scaling_enabled(struct iris_inst *inst) +{ + return inst->crop.left != inst->compose.left || + inst->crop.top != inst->compose.top || + inst->crop.width != inst->compose.width || + inst->crop.height != inst->compose.height; +} + +static inline +u32 hfi_buffer_vpss_enc(u32 dswidth, u32 dsheight, bool ds_enable, + u32 blur, bool is_ten_bit) +{ + if (ds_enable || blur) + return hfi_buffer_dpb_enc(dswidth, dsheight, is_ten_bit); + + return 0; +} + +static inline u32 hfi_buffer_scratch1_enc(u32 frame_width, u32 frame_height, + u32 lcu_size, u32 num_ref, + bool ten_bit, u32 num_vpp_pipes, + bool is_h265) +{ + u32 line_buf_ctrl_size, line_buf_data_size, leftline_buf_ctrl_size; + u32 line_buf_sde_size, sps_pps_slice_hdr, topline_buf_ctrl_size_FE; + u32 leftline_buf_ctrl_size_FE, line_buf_recon_pix_size; + u32 leftline_buf_recon_pix_size, lambda_lut_size, override_buffer_size; + u32 col_mv_buf_size, vpp_reg_buffer_size, ir_buffer_size; + u32 vpss_line_buf, leftline_buf_meta_recony, h265e_colrcbuf_size; + u32 h265e_framerc_bufsize, h265e_lcubitcnt_bufsize; + u32 h265e_lcubitmap_bufsize, se_stats_bufsize; + u32 bse_reg_buffer_size, bse_slice_cmd_buffer_size, slice_info_bufsize; + u32 line_buf_ctrl_size_buffid2, slice_cmd_buffer_size; + u32 width_lcu_num, height_lcu_num, width_coded, height_coded; + u32 frame_num_lcu, linebuf_meta_recon_uv, topline_bufsize_fe_1stg_sao; + u32 vpss_line_buffer_size_1; + u32 bit_depth, num_lcu_mb; + + width_lcu_num = (frame_width + lcu_size - 1) / lcu_size; + height_lcu_num = (frame_height + lcu_size - 1) / lcu_size; + frame_num_lcu = width_lcu_num * height_lcu_num; + width_coded = width_lcu_num * lcu_size; + height_coded = height_lcu_num * lcu_size; + num_lcu_mb = (height_coded / lcu_size) * + ((width_coded + lcu_size * 8) / lcu_size); + slice_info_bufsize = 256 + (frame_num_lcu << 4); + slice_info_bufsize = ALIGN(slice_info_bufsize, 256); + line_buf_ctrl_size = ALIGN(width_coded, 256); + line_buf_ctrl_size_buffid2 = ALIGN(width_coded, 256); + + bit_depth = ten_bit ? 10 : 8; + line_buf_data_size = + (((((bit_depth * width_coded + 1024) + (256 - 1)) & + (~(256 - 1))) * 1) + + (((((bit_depth * width_coded + 1024) >> 1) + (256 - 1)) & + (~(256 - 1))) * 2)); + + leftline_buf_ctrl_size = is_h265 ? ((height_coded + 32) / 32 * 4 * 16) : + ((height_coded + 15) / 16 * 5 * 16); + + if (num_vpp_pipes > 1) { + leftline_buf_ctrl_size += 512; + leftline_buf_ctrl_size = + ALIGN(leftline_buf_ctrl_size, 512) * num_vpp_pipes; + } + + leftline_buf_ctrl_size = ALIGN(leftline_buf_ctrl_size, 256); + leftline_buf_recon_pix_size = + (((ten_bit + 1) * 2 * (height_coded) + 256) + + (256 << (num_vpp_pipes - 1)) - 1) & + (~((256 << (num_vpp_pipes - 1)) - 1)) * 1; + + topline_buf_ctrl_size_FE = is_h265 ? (64 * (width_coded >> 5)) : + (256 + 16 * (width_coded >> 4)); + topline_buf_ctrl_size_FE = ALIGN(topline_buf_ctrl_size_FE, 256); + leftline_buf_ctrl_size_FE = + (((256 + 64 * (height_coded >> 4)) + + (256 << (num_vpp_pipes - 1)) - 1) & + (~((256 << (num_vpp_pipes - 1)) - 1)) * 1) * + num_vpp_pipes; + leftline_buf_meta_recony = + (256 + 64 * ((height_coded) / (8 * (ten_bit ? 4 : 8)))); + leftline_buf_meta_recony = ALIGN(leftline_buf_meta_recony, 256); + leftline_buf_meta_recony = leftline_buf_meta_recony * num_vpp_pipes; + linebuf_meta_recon_uv = + (256 + 64 * ((height_coded) / (4 * (ten_bit ? 4 : 8)))); + linebuf_meta_recon_uv = ALIGN(linebuf_meta_recon_uv, 256); + linebuf_meta_recon_uv = linebuf_meta_recon_uv * num_vpp_pipes; + line_buf_recon_pix_size = ((ten_bit ? 3 : 2) * width_coded); + line_buf_recon_pix_size = ALIGN(line_buf_recon_pix_size, 256); + slice_cmd_buffer_size = ALIGN(20480, 256); + sps_pps_slice_hdr = 2048 + 4096; + col_mv_buf_size = + is_h265 ? (16 * ((frame_num_lcu << 2) + 32)) : + (3 * 16 * (width_lcu_num * height_lcu_num + 32)); + col_mv_buf_size = ALIGN(col_mv_buf_size, 256) * (num_ref + 1); + h265e_colrcbuf_size = + (((width_lcu_num + 7) >> 3) * 16 * 2 * height_lcu_num); + if (num_vpp_pipes > 1) + h265e_colrcbuf_size = + ALIGN(h265e_colrcbuf_size, 256) * num_vpp_pipes; + + h265e_colrcbuf_size = + ALIGN(h265e_colrcbuf_size, 256) * HFI_MAX_COL_FRAME; + h265e_framerc_bufsize = + (is_h265) ? + (256 + 16 * (14 + (((height_coded >> 5) + 7) >> 3))) : + (256 + 16 * (14 + (((height_coded >> 4) + 7) >> 3))); + h265e_framerc_bufsize *= 6; + if (num_vpp_pipes > 1) + h265e_framerc_bufsize = + ALIGN(h265e_framerc_bufsize, 256) * num_vpp_pipes; + + h265e_framerc_bufsize = + ALIGN(h265e_framerc_bufsize, 512) * HFI_MAX_COL_FRAME; + h265e_lcubitcnt_bufsize = 256 + 4 * frame_num_lcu; + h265e_lcubitcnt_bufsize = ALIGN(h265e_lcubitcnt_bufsize, 256); + h265e_lcubitmap_bufsize = 256 + (frame_num_lcu >> 3); + h265e_lcubitmap_bufsize = ALIGN(h265e_lcubitmap_bufsize, 256); + line_buf_sde_size = 256 + 16 * (width_coded >> 4); + line_buf_sde_size = ALIGN(line_buf_sde_size, 256); + if ((width_coded * height_coded) > (4096 * 2160)) + se_stats_bufsize = 0; + else if ((width_coded * height_coded) > (1920 * 1088)) + se_stats_bufsize = (40 * 4 * frame_num_lcu + 256 + 256); + else + se_stats_bufsize = (1024 * frame_num_lcu + 256 + 256); + + se_stats_bufsize = ALIGN(se_stats_bufsize, 256) * 2; + bse_slice_cmd_buffer_size = (((8192 << 2) + 7) & (~7)) * 6; + bse_reg_buffer_size = (((512 << 3) + 7) & (~7)) * 4; + vpp_reg_buffer_size = (((2048 << 3) + 31) & (~31)) * 10; + lambda_lut_size = 256 * 11; + override_buffer_size = 16 * ((num_lcu_mb + 7) >> 3); + override_buffer_size = ALIGN(override_buffer_size, 256) * 2; + ir_buffer_size = (((frame_num_lcu << 1) + 7) & (~7)) * 3; + vpss_line_buffer_size_1 = (((8192 >> 2) << 5) * num_vpp_pipes) + 64; + vpss_line_buf = + (((((max(width_coded, height_coded) + 3) >> 2) << 5) + 256) * + 16) + + vpss_line_buffer_size_1; + topline_bufsize_fe_1stg_sao = 16 * (width_coded >> 5); + topline_bufsize_fe_1stg_sao = ALIGN(topline_bufsize_fe_1stg_sao, 256); + + return line_buf_ctrl_size + line_buf_data_size + + line_buf_ctrl_size_buffid2 + leftline_buf_ctrl_size + + vpss_line_buf + col_mv_buf_size + topline_buf_ctrl_size_FE + + leftline_buf_ctrl_size_FE + line_buf_recon_pix_size + + leftline_buf_recon_pix_size + leftline_buf_meta_recony + + linebuf_meta_recon_uv + h265e_colrcbuf_size + + h265e_framerc_bufsize + h265e_lcubitcnt_bufsize + + h265e_lcubitmap_bufsize + line_buf_sde_size + + topline_bufsize_fe_1stg_sao + override_buffer_size + + bse_reg_buffer_size + vpp_reg_buffer_size + sps_pps_slice_hdr + + slice_cmd_buffer_size + bse_slice_cmd_buffer_size + + ir_buffer_size + slice_info_bufsize + lambda_lut_size + + se_stats_bufsize + 1024; +} + +static u32 iris_vpu_enc_scratch1_size(struct iris_inst *inst) +{ + u32 num_vpp_pipes = inst->core->iris_platform_data->num_vpp_pipe; + struct v4l2_format *f = inst->fmt_dst; + u32 frame_height = f->fmt.pix_mp.height; + u32 frame_width = f->fmt.pix_mp.width; + u32 num_ref = 1; + u32 lcu_size; + bool is_h265; + + if (inst->codec == V4L2_PIX_FMT_H264) { + lcu_size = 16; + is_h265 = false; + } else if (inst->codec == V4L2_PIX_FMT_HEVC) { + lcu_size = 32; + is_h265 = true; + } else { + return 0; + } + + return hfi_buffer_scratch1_enc(frame_width, frame_height, lcu_size, + num_ref, false, num_vpp_pipes, is_h265); +} + +static inline u32 ubwc_metadata_plane_stride(u32 width, + u32 metadata_stride_multi, + u32 tile_width_pels) +{ + return ALIGN(((width + (tile_width_pels - 1)) / tile_width_pels), + metadata_stride_multi); +} + +static inline u32 ubwc_metadata_plane_bufheight(u32 height, + u32 metadata_height_multi, + u32 tile_height_pels) +{ + return ALIGN(((height + (tile_height_pels - 1)) / tile_height_pels), + metadata_height_multi); +} + +static inline u32 ubwc_metadata_plane_buffer_size(u32 metadata_stride, + u32 metadata_buf_height) +{ + return ALIGN(metadata_stride * metadata_buf_height, SZ_4K); +} + +static inline u32 hfi_buffer_scratch2_enc(u32 frame_width, u32 frame_height, + u32 num_ref, bool ten_bit) +{ + u32 aligned_width, aligned_height, chroma_height, ref_buf_height; + u32 metadata_stride, meta_buf_height, meta_size_y, meta_size_c; + u32 ref_luma_stride_bytes, ref_chroma_height_bytes; + u32 ref_buf_size, ref_stride; + u32 luma_size, chroma_size; + u32 size; + + if (!ten_bit) { + aligned_height = ALIGN(frame_height, 32); + chroma_height = frame_height >> 1; + chroma_height = ALIGN(chroma_height, 32); + aligned_width = ALIGN(frame_width, 128); + metadata_stride = + ubwc_metadata_plane_stride(frame_width, 64, 32); + meta_buf_height = + ubwc_metadata_plane_bufheight(frame_height, 16, 8); + meta_size_y = ubwc_metadata_plane_buffer_size(metadata_stride, + meta_buf_height); + meta_size_c = ubwc_metadata_plane_buffer_size(metadata_stride, + meta_buf_height); + size = (aligned_height + chroma_height) * aligned_width + + meta_size_y + meta_size_c; + size = (size * (num_ref + 3)) + 4096; + } else { + ref_buf_height = (frame_height + (32 - 1)) & (~(32 - 1)); + ref_luma_stride_bytes = ((frame_width + 192 - 1) / 192) * 192; + ref_stride = 4 * (ref_luma_stride_bytes / 3); + ref_stride = (ref_stride + (128 - 1)) & (~(128 - 1)); + luma_size = ref_buf_height * ref_stride; + ref_chroma_height_bytes = + (((frame_height + 1) >> 1) + (32 - 1)) & (~(32 - 1)); + chroma_size = ref_stride * ref_chroma_height_bytes; + luma_size = (luma_size + (SZ_4K - 1)) & (~(SZ_4K - 1)); + chroma_size = (chroma_size + (SZ_4K - 1)) & (~(SZ_4K - 1)); + ref_buf_size = luma_size + chroma_size; + metadata_stride = + ubwc_metadata_plane_stride(frame_width, 64, 48); + meta_buf_height = + ubwc_metadata_plane_bufheight(frame_height, 16, 4); + meta_size_y = ubwc_metadata_plane_buffer_size(metadata_stride, + meta_buf_height); + meta_size_c = ubwc_metadata_plane_buffer_size(metadata_stride, + meta_buf_height); + size = ref_buf_size + meta_size_y + meta_size_c; + size = (size * (num_ref + 3)) + 4096; + } + + return size; +} + +static u32 iris_vpu_enc_scratch2_size(struct iris_inst *inst) +{ + struct v4l2_format *f = inst->fmt_dst; + u32 frame_width = f->fmt.pix_mp.width; + u32 frame_height = f->fmt.pix_mp.height; + u32 num_ref = 1; + + return hfi_buffer_scratch2_enc(frame_width, frame_height, num_ref, + false); +} + +static u32 iris_vpu_enc_vpss_size(struct iris_inst *inst) +{ + u32 ds_enable = is_scaling_enabled(inst); + struct v4l2_format *f = inst->fmt_dst; + u32 height = f->fmt.pix_mp.height; + u32 width = f->fmt.pix_mp.width; + + return hfi_buffer_vpss_enc(width, height, ds_enable, 0, 0); +} + static int output_min_count(struct iris_inst *inst) { int output_min_count = 4; @@ -571,10 +1431,10 @@ struct iris_vpu_buf_type_handle { u32 (*handle)(struct iris_inst *inst); }; -int iris_vpu_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type) +u32 iris_vpu_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type) { - const struct iris_vpu_buf_type_handle *buf_type_handle_arr; - u32 size = 0, buf_type_handle_size, i; + const struct iris_vpu_buf_type_handle *buf_type_handle_arr = NULL; + u32 size = 0, buf_type_handle_size = 0, i; static const struct iris_vpu_buf_type_handle dec_internal_buf_type_handle[] = { {BUF_BIN, iris_vpu_dec_bin_size }, @@ -586,8 +1446,24 @@ int iris_vpu_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type) {BUF_SCRATCH_1, iris_vpu_dec_scratch1_size }, }; - buf_type_handle_size = ARRAY_SIZE(dec_internal_buf_type_handle); - buf_type_handle_arr = dec_internal_buf_type_handle; + static const struct iris_vpu_buf_type_handle enc_internal_buf_type_handle[] = { + {BUF_BIN, iris_vpu_enc_bin_size }, + {BUF_COMV, iris_vpu_enc_comv_size }, + {BUF_NON_COMV, iris_vpu_enc_non_comv_size }, + {BUF_LINE, iris_vpu_enc_line_size }, + {BUF_ARP, iris_vpu_enc_arp_size }, + {BUF_VPSS, iris_vpu_enc_vpss_size }, + {BUF_SCRATCH_1, iris_vpu_enc_scratch1_size }, + {BUF_SCRATCH_2, iris_vpu_enc_scratch2_size }, + }; + + if (inst->domain == DECODER) { + buf_type_handle_size = ARRAY_SIZE(dec_internal_buf_type_handle); + buf_type_handle_arr = dec_internal_buf_type_handle; + } else if (inst->domain == ENCODER) { + buf_type_handle_size = ARRAY_SIZE(enc_internal_buf_type_handle); + buf_type_handle_arr = enc_internal_buf_type_handle; + } for (i = 0; i < buf_type_handle_size; i++) { if (buf_type_handle_arr[i].type == buffer_type) { @@ -599,6 +1475,34 @@ int iris_vpu_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type) return size; } +u32 iris_vpu33_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type) +{ + u32 size = 0, i; + + static const struct iris_vpu_buf_type_handle enc_internal_buf_type_handle[] = { + {BUF_BIN, iris_vpu_enc_bin_size }, + {BUF_COMV, iris_vpu_enc_comv_size }, + {BUF_NON_COMV, iris_vpu_enc_non_comv_size }, + {BUF_LINE, iris_vpu33_enc_line_size }, + {BUF_ARP, iris_vpu_enc_arp_size }, + {BUF_VPSS, iris_vpu_enc_vpss_size }, + {BUF_SCRATCH_1, iris_vpu_enc_scratch1_size }, + {BUF_SCRATCH_2, iris_vpu_enc_scratch2_size }, + }; + + if (inst->domain == DECODER) + return iris_vpu_buf_size(inst, buffer_type); + + for (i = 0; i < ARRAY_SIZE(enc_internal_buf_type_handle); i++) { + if (enc_internal_buf_type_handle[i].type == buffer_type) { + size = enc_internal_buf_type_handle[i].handle(inst); + break; + } + } + + return size; +} + static u32 internal_buffer_count(struct iris_inst *inst, enum iris_buffer_type buffer_type) { @@ -628,7 +1532,10 @@ int iris_vpu_buf_count(struct iris_inst *inst, enum iris_buffer_type buffer_type case BUF_INPUT: return MIN_BUFFERS; case BUF_OUTPUT: - return output_min_count(inst); + if (inst->domain == ENCODER) + return MIN_BUFFERS; + else + return output_min_count(inst); case BUF_BIN: case BUF_COMV: case BUF_NON_COMV: @@ -636,6 +1543,9 @@ int iris_vpu_buf_count(struct iris_inst *inst, enum iris_buffer_type buffer_type case BUF_PERSIST: return internal_buffer_count(inst, buffer_type); case BUF_SCRATCH_1: + case BUF_SCRATCH_2: + case BUF_VPSS: + case BUF_ARP: return 1; /* internal buffer count needed by firmware is 1 */ case BUF_DPB: return iris_vpu_dpb_count(inst); diff --git a/drivers/media/platform/qcom/iris/iris_vpu_buffer.h b/drivers/media/platform/qcom/iris/iris_vpu_buffer.h index ee95fd20b794..04f0b7400a1e 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_buffer.h +++ b/drivers/media/platform/qcom/iris/iris_vpu_buffer.h @@ -41,6 +41,7 @@ struct iris_inst; #define SIZE_SLIST_BUF_H265 (BIT(10)) #define H265_DISPLAY_BUF_SIZE (3072) #define H265_NUM_FRM_INFO (48) +#define SIZE_ONE_SLICE_BUF 256 #define VP9_NUM_FRAME_INFO_BUF 32 #define VP9_NUM_PROBABILITY_TABLE_BUF (VP9_NUM_FRAME_INFO_BUF + 4) @@ -80,6 +81,26 @@ struct iris_inst; #define MAX_PE_NBR_DATA_LCU64_LINE_BUFFER_SIZE 384 #define MAX_FE_NBR_DATA_LUMA_LINE_BUFFER_SIZE 640 +#define SIZE_SLICE_CMD_BUFFER (ALIGN(20480, 256)) +#define SIZE_SPS_PPS_SLICE_HDR (2048 + 4096) +#define SIZE_BSE_SLICE_CMD_BUF ((((8192 << 2) + 7) & (~7)) * 3) +#define SIZE_LAMBDA_LUT (256 * 11) + +#define HFI_COL_FMT_NV12C_Y_TILE_HEIGHT (8) +#define HFI_COL_FMT_NV12C_Y_TILE_WIDTH (32) +#define HFI_COL_FMT_TP10C_Y_TILE_HEIGHT (4) +#define HFI_COL_FMT_TP10C_Y_TILE_WIDTH (48) + +#define IRIS_METADATA_STRIDE_MULTIPLE 64 +#define IRIS_METADATA_HEIGHT_MULTIPLE 16 + +#define HFI_BUFFER_ARP_ENC 204800 + +#define MAX_WIDTH 4096 +#define MAX_HEIGHT 2304 +#define NUM_MBS_4K (DIV_ROUND_UP(MAX_WIDTH, 16) * DIV_ROUND_UP(MAX_HEIGHT, 16)) +#define NUM_MBS_720P (((ALIGN(1280, 16)) >> 4) * ((ALIGN(736, 16)) >> 4)) + static inline u32 size_h264d_lb_fe_top_data(u32 frame_width) { return MAX_FE_NBR_DATA_LUMA_LINE_BUFFER_SIZE * ALIGN(frame_width, 16) * 3; @@ -125,7 +146,8 @@ static inline u32 size_h264d_qp(u32 frame_width, u32 frame_height) return DIV_ROUND_UP(frame_width, 64) * DIV_ROUND_UP(frame_height, 64) * 128; } -int iris_vpu_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type); +u32 iris_vpu_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type); +u32 iris_vpu33_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type); int iris_vpu_buf_count(struct iris_inst *inst, enum iris_buffer_type buffer_type); #endif diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.c b/drivers/media/platform/qcom/iris/iris_vpu_common.c index 268e45acaa7c..bb98950e018f 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_common.c +++ b/drivers/media/platform/qcom/iris/iris_vpu_common.c @@ -84,6 +84,7 @@ static void iris_vpu_interrupt_init(struct iris_core *core) static void iris_vpu_setup_ucregion_memory_map(struct iris_core *core) { u32 queue_size, value; + const struct vpu_ops *vpu_ops = core->iris_platform_data->vpu_ops; /* Iris hardware requires 4K queue alignment */ queue_size = ALIGN(sizeof(struct iris_hfi_queue_table_header) + @@ -105,6 +106,9 @@ static void iris_vpu_setup_ucregion_memory_map(struct iris_core *core) value = (u32)core->sfr_daddr + core->iris_platform_data->core_arch; writel(value, core->reg_base + SFR_ADDR); } + + if (vpu_ops->program_bootup_registers) + vpu_ops->program_bootup_registers(core); } int iris_vpu_boot_firmware(struct iris_core *core) @@ -271,7 +275,7 @@ void iris_vpu_power_off(struct iris_core *core) disable_irq_nosync(core->irq); } -static int iris_vpu_power_on_controller(struct iris_core *core) +int iris_vpu_power_on_controller(struct iris_core *core) { u32 rst_tbl_size = core->iris_platform_data->clk_rst_tbl_size; int ret; @@ -302,7 +306,7 @@ err_disable_power: return ret; } -static int iris_vpu_power_on_hw(struct iris_core *core) +int iris_vpu_power_on_hw(struct iris_core *core) { int ret; @@ -337,11 +341,11 @@ int iris_vpu_power_on(struct iris_core *core) if (ret) goto err; - ret = iris_vpu_power_on_controller(core); + ret = core->iris_platform_data->vpu_ops->power_on_controller(core); if (ret) goto err_unvote_icc; - ret = iris_vpu_power_on_hw(core); + ret = core->iris_platform_data->vpu_ops->power_on_hw(core); if (ret) goto err_power_off_ctrl; @@ -359,7 +363,7 @@ int iris_vpu_power_on(struct iris_core *core) return 0; err_power_off_ctrl: - iris_vpu_power_off_controller(core); + core->iris_platform_data->vpu_ops->power_off_controller(core); err_unvote_icc: iris_unset_icc_bw(core); err: diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.h b/drivers/media/platform/qcom/iris/iris_vpu_common.h index 93b7fa27be3b..d636e287457a 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_common.h +++ b/drivers/media/platform/qcom/iris/iris_vpu_common.h @@ -11,10 +11,14 @@ struct iris_core; extern const struct vpu_ops iris_vpu2_ops; extern const struct vpu_ops iris_vpu3_ops; extern const struct vpu_ops iris_vpu33_ops; +extern const struct vpu_ops iris_vpu35_ops; struct vpu_ops { void (*power_off_hw)(struct iris_core *core); + int (*power_on_hw)(struct iris_core *core); int (*power_off_controller)(struct iris_core *core); + int (*power_on_controller)(struct iris_core *core); + void (*program_bootup_registers)(struct iris_core *core); u64 (*calc_freq)(struct iris_inst *inst, size_t data_size); }; @@ -23,6 +27,8 @@ void iris_vpu_raise_interrupt(struct iris_core *core); void iris_vpu_clear_interrupt(struct iris_core *core); int iris_vpu_watchdog(struct iris_core *core, u32 intr_status); int iris_vpu_prepare_pc(struct iris_core *core); +int iris_vpu_power_on_controller(struct iris_core *core); +int iris_vpu_power_on_hw(struct iris_core *core); int iris_vpu_power_on(struct iris_core *core); int iris_vpu_power_off_controller(struct iris_core *core); void iris_vpu_power_off_hw(struct iris_core *core); diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c index 4c049c694d9c..abf959b8f3a6 100644 --- a/drivers/media/platform/qcom/venus/core.c +++ b/drivers/media/platform/qcom/venus/core.c @@ -254,14 +254,19 @@ err: static void venus_assign_register_offsets(struct venus_core *core) { - if (IS_IRIS2(core) || IS_IRIS2_1(core)) { - core->vbif_base = core->base + VBIF_BASE; + if (IS_IRIS2(core) || IS_IRIS2_1(core) || IS_AR50_LITE(core)) { core->cpu_base = core->base + CPU_BASE_V6; core->cpu_cs_base = core->base + CPU_CS_BASE_V6; core->cpu_ic_base = core->base + CPU_IC_BASE_V6; core->wrapper_base = core->base + WRAPPER_BASE_V6; core->wrapper_tz_base = core->base + WRAPPER_TZ_BASE_V6; - core->aon_base = core->base + AON_BASE_V6; + if (IS_AR50_LITE(core)) { + core->vbif_base = NULL; + core->aon_base = NULL; + } else { + core->vbif_base = core->base + VBIF_BASE; + core->aon_base = core->base + AON_BASE_V6; + } } else { core->vbif_base = core->base + VBIF_BASE; core->cpu_base = core->base + CPU_BASE; @@ -448,24 +453,18 @@ static int venus_probe(struct platform_device *pdev) if (ret < 0) goto err_runtime_disable; - if (core->res->dec_nodename || core->res->enc_nodename) { - ret = venus_add_dynamic_nodes(core); - if (ret) - goto err_runtime_disable; - } - - ret = of_platform_populate(dev->of_node, NULL, NULL, dev); - if (ret) - goto err_remove_dynamic_nodes; - ret = venus_firmware_init(core); if (ret) - goto err_of_depopulate; + goto err_runtime_disable; ret = venus_boot(core); if (ret) goto err_firmware_deinit; + ret = venus_firmware_cfg(core); + if (ret) + goto err_venus_shutdown; + ret = hfi_core_resume(core, true); if (ret) goto err_venus_shutdown; @@ -474,34 +473,48 @@ static int venus_probe(struct platform_device *pdev) if (ret) goto err_venus_shutdown; - ret = venus_enumerate_codecs(core, VIDC_SESSION_TYPE_DEC); + ret = venus_firmware_check(core); if (ret) goto err_core_deinit; + if (core->res->dec_nodename || core->res->enc_nodename) { + ret = venus_add_dynamic_nodes(core); + if (ret) + goto err_core_deinit; + } + + ret = of_platform_populate(dev->of_node, NULL, NULL, dev); + if (ret) + goto err_remove_dynamic_nodes; + + ret = venus_enumerate_codecs(core, VIDC_SESSION_TYPE_DEC); + if (ret) + goto err_of_depopulate; + ret = venus_enumerate_codecs(core, VIDC_SESSION_TYPE_ENC); if (ret) - goto err_core_deinit; + goto err_of_depopulate; ret = pm_runtime_put_sync(dev); if (ret) { pm_runtime_get_noresume(dev); - goto err_core_deinit; + goto err_of_depopulate; } venus_dbgfs_init(core); return 0; +err_of_depopulate: + of_platform_depopulate(dev); +err_remove_dynamic_nodes: + venus_remove_dynamic_nodes(core); err_core_deinit: hfi_core_deinit(core, false); err_venus_shutdown: venus_shutdown(core); err_firmware_deinit: venus_firmware_deinit(core); -err_of_depopulate: - of_platform_depopulate(dev); -err_remove_dynamic_nodes: - venus_remove_dynamic_nodes(core); err_runtime_disable: pm_runtime_put_noidle(dev); pm_runtime_disable(dev); @@ -596,7 +609,7 @@ err_cpucfg_path: return ret; } -void venus_close_common(struct venus_inst *inst) +void venus_close_common(struct venus_inst *inst, struct file *filp) { /* * Make sure we don't have IRQ/IRQ-thread currently running @@ -607,7 +620,7 @@ void venus_close_common(struct venus_inst *inst) v4l2_m2m_ctx_release(inst->m2m_ctx); v4l2_m2m_release(inst->m2m_dev); hfi_session_destroy(inst); - v4l2_fh_del(&inst->fh); + v4l2_fh_del(&inst->fh, filp); v4l2_fh_exit(&inst->fh); v4l2_ctrl_handler_free(&inst->ctrl_handler); @@ -1057,15 +1070,65 @@ static const struct venus_resources sc7280_res = { .enc_nodename = "video-encoder", }; +static const struct bw_tbl qcm2290_bw_table_dec[] = { + { 352800, 597000, 0, 746000, 0 }, /* 1080p@30 + 720p@30 */ + { 244800, 413000, 0, 516000, 0 }, /* 1080p@30 */ + { 216000, 364000, 0, 454000, 0 }, /* 720p@60 */ + { 108000, 182000, 0, 227000, 0 }, /* 720p@30 */ +}; + +static const struct bw_tbl qcm2290_bw_table_enc[] = { + { 352800, 396000, 0, 0, 0 }, /* 1080p@30 + 720p@30 */ + { 244800, 275000, 0, 0, 0 }, /* 1080p@30 */ + { 216000, 242000, 0, 0, 0 }, /* 720p@60 */ + { 108000, 121000, 0, 0, 0 }, /* 720p@30 */ +}; + +static const struct firmware_version min_fw = { + .major = 6, .minor = 0, .rev = 55, +}; + +static const struct venus_resources qcm2290_res = { + .bw_tbl_dec = qcm2290_bw_table_dec, + .bw_tbl_dec_size = ARRAY_SIZE(qcm2290_bw_table_dec), + .bw_tbl_enc = qcm2290_bw_table_enc, + .bw_tbl_enc_size = ARRAY_SIZE(qcm2290_bw_table_enc), + .clks = { "core", "iface", "bus", "throttle" }, + .clks_num = 4, + .vcodec0_clks = { "vcodec0_core", "vcodec0_bus" }, + .vcodec_clks_num = 2, + .vcodec_pmdomains = (const char *[]) { "venus", "vcodec0" }, + .vcodec_pmdomains_num = 2, + .opp_pmdomain = (const char *[]) { "cx" }, + .vcodec_num = 1, + .hfi_version = HFI_VERSION_4XX, + .vpu_version = VPU_VERSION_AR50_LITE, + .max_load = 352800, + .num_vpp_pipes = 1, + .vmem_id = VIDC_RESOURCE_NONE, + .vmem_size = 0, + .vmem_addr = 0, + .cp_start = 0, + .cp_size = 0x70800000, + .cp_nonpixel_start = 0x1000000, + .cp_nonpixel_size = 0x24800000, + .dma_mask = 0xe0000000 - 1, + .fwname = "qcom/venus-6.0/venus.mbn", + .dec_nodename = "video-decoder", + .enc_nodename = "video-encoder", + .min_fw = &min_fw, +}; + static const struct of_device_id venus_dt_match[] = { { .compatible = "qcom,msm8916-venus", .data = &msm8916_res, }, { .compatible = "qcom,msm8996-venus", .data = &msm8996_res, }, { .compatible = "qcom,msm8998-venus", .data = &msm8998_res, }, + { .compatible = "qcom,qcm2290-venus", .data = &qcm2290_res, }, + { .compatible = "qcom,sc7180-venus", .data = &sc7180_res, }, + { .compatible = "qcom,sc7280-venus", .data = &sc7280_res, }, { .compatible = "qcom,sdm660-venus", .data = &sdm660_res, }, { .compatible = "qcom,sdm845-venus", .data = &sdm845_res, }, { .compatible = "qcom,sdm845-venus-v2", .data = &sdm845_res_v2, }, - { .compatible = "qcom,sc7180-venus", .data = &sc7180_res, }, - { .compatible = "qcom,sc7280-venus", .data = &sc7280_res, }, { .compatible = "qcom,sm8250-venus", .data = &sm8250_res, }, { } }; diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h index 5b1ba1c69adb..7506f5d0f609 100644 --- a/drivers/media/platform/qcom/venus/core.h +++ b/drivers/media/platform/qcom/venus/core.h @@ -58,6 +58,12 @@ enum vpu_version { VPU_VERSION_IRIS2_1, }; +struct firmware_version { + u32 major; + u32 minor; + u32 rev; +}; + struct venus_resources { u64 dma_mask; const struct freq_tbl *freq_tbl; @@ -94,6 +100,7 @@ struct venus_resources { const char *fwname; const char *enc_nodename; const char *dec_nodename; + const struct firmware_version *min_fw; }; enum venus_fmt { @@ -231,11 +238,7 @@ struct venus_core { unsigned int core0_usage_count; unsigned int core1_usage_count; struct dentry *root; - struct venus_img_version { - u32 major; - u32 minor; - u32 rev; - } venus_ver; + struct firmware_version venus_ver; unsigned long dump_core; struct of_changeset *ocs; bool hwmode_dev; @@ -530,12 +533,17 @@ struct venus_inst { #define IS_IRIS2(core) ((core)->res->vpu_version == VPU_VERSION_IRIS2) #define IS_IRIS2_1(core) ((core)->res->vpu_version == VPU_VERSION_IRIS2_1) +static inline bool is_lite(struct venus_core *core) +{ + return IS_AR50_LITE(core); +} + #define ctrl_to_inst(ctrl) \ container_of((ctrl)->handler, struct venus_inst, ctrl_handler) static inline struct venus_inst *to_inst(struct file *filp) { - return container_of(filp->private_data, struct venus_inst, fh); + return container_of(file_to_v4l2_fh(filp), struct venus_inst, fh); } static inline void *to_hfi_priv(struct venus_core *core) @@ -573,5 +581,5 @@ is_fw_rev_or_older(struct venus_core *core, u32 vmajor, u32 vminor, u32 vrev) (core)->venus_ver.rev <= vrev); } -void venus_close_common(struct venus_inst *inst); +void venus_close_common(struct venus_inst *inst, struct file *filp); #endif diff --git a/drivers/media/platform/qcom/venus/firmware.c b/drivers/media/platform/qcom/venus/firmware.c index 862d0718f694..af0ac40bec9b 100644 --- a/drivers/media/platform/qcom/venus/firmware.c +++ b/drivers/media/platform/qcom/venus/firmware.c @@ -30,7 +30,7 @@ static void venus_reset_cpu(struct venus_core *core) u32 fw_size = core->fw.mapped_mem_size; void __iomem *wrapper_base; - if (IS_IRIS2_1(core)) + if (IS_IRIS2(core) || IS_IRIS2_1(core)) wrapper_base = core->wrapper_tz_base; else wrapper_base = core->wrapper_base; @@ -42,7 +42,7 @@ static void venus_reset_cpu(struct venus_core *core) writel(fw_size, wrapper_base + WRAPPER_NONPIX_START_ADDR); writel(fw_size, wrapper_base + WRAPPER_NONPIX_END_ADDR); - if (IS_IRIS2_1(core)) { + if (IS_IRIS2(core) || IS_IRIS2_1(core)) { /* Bring XTSS out of reset */ writel(0, wrapper_base + WRAPPER_TZ_XTSS_SW_RESET); } else { @@ -68,7 +68,7 @@ int venus_set_hw_state(struct venus_core *core, bool resume) if (resume) { venus_reset_cpu(core); } else { - if (IS_IRIS2_1(core)) + if (IS_IRIS2(core) || IS_IRIS2_1(core)) writel(WRAPPER_XTSS_SW_RESET_BIT, core->wrapper_tz_base + WRAPPER_TZ_XTSS_SW_RESET); else @@ -181,7 +181,7 @@ static int venus_shutdown_no_tz(struct venus_core *core) void __iomem *wrapper_base = core->wrapper_base; void __iomem *wrapper_tz_base = core->wrapper_tz_base; - if (IS_IRIS2_1(core)) { + if (IS_IRIS2(core) || IS_IRIS2_1(core)) { /* Assert the reset to XTSS */ reg = readl(wrapper_tz_base + WRAPPER_TZ_XTSS_SW_RESET); reg |= WRAPPER_XTSS_SW_RESET_BIT; @@ -207,6 +207,16 @@ static int venus_shutdown_no_tz(struct venus_core *core) return 0; } +int venus_firmware_cfg(struct venus_core *core) +{ + void __iomem *cpu_cs_base = core->cpu_cs_base; + + if (IS_AR50_LITE(core)) + writel(CPU_CS_VCICMD_ARP_OFF, cpu_cs_base + CPU_CS_VCICMD); + + return 0; +} + int venus_boot(struct venus_core *core) { struct device *dev = core->dev; @@ -280,6 +290,26 @@ int venus_shutdown(struct venus_core *core) return ret; } +int venus_firmware_check(struct venus_core *core) +{ + const struct firmware_version *req = core->res->min_fw; + const struct firmware_version *run = &core->venus_ver; + + if (!req) + return 0; + + if (!is_fw_rev_or_newer(core, req->major, req->minor, req->rev)) + goto error; + + return 0; +error: + dev_err(core->dev, "Firmware v%d.%d.%d < v%d.%d.%d\n", + run->major, run->minor, run->rev, + req->major, req->minor, req->rev); + + return -EINVAL; +} + int venus_firmware_init(struct venus_core *core) { struct platform_device_info info; diff --git a/drivers/media/platform/qcom/venus/firmware.h b/drivers/media/platform/qcom/venus/firmware.h index aaccd847fa30..87e1d922b369 100644 --- a/drivers/media/platform/qcom/venus/firmware.h +++ b/drivers/media/platform/qcom/venus/firmware.h @@ -9,6 +9,8 @@ struct device; int venus_firmware_init(struct venus_core *core); void venus_firmware_deinit(struct venus_core *core); +int venus_firmware_check(struct venus_core *core); +int venus_firmware_cfg(struct venus_core *core); int venus_boot(struct venus_core *core); int venus_shutdown(struct venus_core *core); int venus_set_hw_state(struct venus_core *core, bool suspend); diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index 8295542e1a7c..2e4363f82231 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -1715,11 +1715,17 @@ int venus_helper_session_init(struct venus_inst *inst) if (ret) return ret; - inst->clk_data.vpp_freq = hfi_platform_get_codec_vpp_freq(version, codec, + inst->clk_data.vpp_freq = hfi_platform_get_codec_vpp_freq(inst->core, + version, + codec, session_type); - inst->clk_data.vsp_freq = hfi_platform_get_codec_vsp_freq(version, codec, + inst->clk_data.vsp_freq = hfi_platform_get_codec_vsp_freq(inst->core, + version, + codec, session_type); - inst->clk_data.low_power_freq = hfi_platform_get_codec_lp_freq(version, codec, + inst->clk_data.low_power_freq = hfi_platform_get_codec_lp_freq(inst->core, + version, + codec, session_type); return 0; diff --git a/drivers/media/platform/qcom/venus/hfi_msgs.c b/drivers/media/platform/qcom/venus/hfi_msgs.c index cf0d97cbc463..47b99d5b5af7 100644 --- a/drivers/media/platform/qcom/venus/hfi_msgs.c +++ b/drivers/media/platform/qcom/venus/hfi_msgs.c @@ -277,7 +277,12 @@ static void hfi_sys_init_done(struct venus_core *core, struct venus_inst *inst, done: core->error = error; - complete(&core->done); + /* + * Since core_init could ask for the firmware version to be validated, + * completion might have to wait until the version is retrieved. + */ + if (!core->res->min_fw) + complete(&core->done); } static void @@ -328,6 +333,10 @@ done: 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); + + /* core_init could have had to wait for a version check */ + if (core->res->min_fw) + complete(&core->done); } static void hfi_sys_property_info(struct venus_core *core, diff --git a/drivers/media/platform/qcom/venus/hfi_parser.c b/drivers/media/platform/qcom/venus/hfi_parser.c index 1b3db2caa99f..92765f9c8873 100644 --- a/drivers/media/platform/qcom/venus/hfi_parser.c +++ b/drivers/media/platform/qcom/venus/hfi_parser.c @@ -282,7 +282,7 @@ static int hfi_platform_parser(struct venus_core *core, struct venus_inst *inst) return ret; if (plat->capabilities) - caps = plat->capabilities(&entries); + caps = plat->capabilities(core, &entries); if (!caps || !entries || !count) return -EINVAL; diff --git a/drivers/media/platform/qcom/venus/hfi_platform.c b/drivers/media/platform/qcom/venus/hfi_platform.c index 643e5aa138f5..cde7f93045ac 100644 --- a/drivers/media/platform/qcom/venus/hfi_platform.c +++ b/drivers/media/platform/qcom/venus/hfi_platform.c @@ -21,7 +21,9 @@ const struct hfi_platform *hfi_platform_get(enum hfi_version version) } unsigned long -hfi_platform_get_codec_vpp_freq(enum hfi_version version, u32 codec, u32 session_type) +hfi_platform_get_codec_vpp_freq(struct venus_core *core, + enum hfi_version version, u32 codec, + u32 session_type) { const struct hfi_platform *plat; unsigned long freq = 0; @@ -31,13 +33,15 @@ hfi_platform_get_codec_vpp_freq(enum hfi_version version, u32 codec, u32 session return 0; if (plat->codec_vpp_freq) - freq = plat->codec_vpp_freq(session_type, codec); + freq = plat->codec_vpp_freq(core, session_type, codec); return freq; } unsigned long -hfi_platform_get_codec_vsp_freq(enum hfi_version version, u32 codec, u32 session_type) +hfi_platform_get_codec_vsp_freq(struct venus_core *core, + enum hfi_version version, u32 codec, + u32 session_type) { const struct hfi_platform *plat; unsigned long freq = 0; @@ -47,13 +51,15 @@ hfi_platform_get_codec_vsp_freq(enum hfi_version version, u32 codec, u32 session return 0; if (plat->codec_vpp_freq) - freq = plat->codec_vsp_freq(session_type, codec); + freq = plat->codec_vsp_freq(core, session_type, codec); return freq; } unsigned long -hfi_platform_get_codec_lp_freq(enum hfi_version version, u32 codec, u32 session_type) +hfi_platform_get_codec_lp_freq(struct venus_core *core, + enum hfi_version version, u32 codec, + u32 session_type) { const struct hfi_platform *plat; unsigned long freq = 0; @@ -63,13 +69,14 @@ hfi_platform_get_codec_lp_freq(enum hfi_version version, u32 codec, u32 session_ return 0; if (plat->codec_lp_freq) - freq = plat->codec_lp_freq(session_type, codec); + freq = plat->codec_lp_freq(core, session_type, codec); return freq; } int -hfi_platform_get_codecs(struct venus_core *core, u32 *enc_codecs, u32 *dec_codecs, u32 *count) +hfi_platform_get_codecs(struct venus_core *core, u32 *enc_codecs, + u32 *dec_codecs, u32 *count) { const struct hfi_platform *plat; @@ -78,7 +85,7 @@ hfi_platform_get_codecs(struct venus_core *core, u32 *enc_codecs, u32 *dec_codec return -EINVAL; if (plat->codecs) - plat->codecs(enc_codecs, dec_codecs, count); + plat->codecs(core, enc_codecs, dec_codecs, count); if (IS_IRIS2_1(core)) { *enc_codecs &= ~HFI_VIDEO_CODEC_VP8; diff --git a/drivers/media/platform/qcom/venus/hfi_platform.h b/drivers/media/platform/qcom/venus/hfi_platform.h index ec89a90a8129..5e4f8013a6b1 100644 --- a/drivers/media/platform/qcom/venus/hfi_platform.h +++ b/drivers/media/platform/qcom/venus/hfi_platform.h @@ -47,11 +47,16 @@ struct hfi_platform_codec_freq_data { }; struct hfi_platform { - unsigned long (*codec_vpp_freq)(u32 session_type, u32 codec); - unsigned long (*codec_vsp_freq)(u32 session_type, u32 codec); - unsigned long (*codec_lp_freq)(u32 session_type, u32 codec); - void (*codecs)(u32 *enc_codecs, u32 *dec_codecs, u32 *count); - const struct hfi_plat_caps *(*capabilities)(unsigned int *entries); + unsigned long (*codec_vpp_freq)(struct venus_core *core, + u32 session_type, u32 codec); + unsigned long (*codec_vsp_freq)(struct venus_core *core, + u32 session_type, u32 codec); + unsigned long (*codec_lp_freq)(struct venus_core *core, + u32 session_type, u32 codec); + void (*codecs)(struct venus_core *core, u32 *enc_codecs, + u32 *dec_codecs, u32 *count); + const struct hfi_plat_caps *(*capabilities)(struct venus_core *core, + unsigned int *entries); int (*bufreq)(struct hfi_plat_buffers_params *params, u32 session_type, u32 buftype, struct hfi_buffer_requirements *bufreq); }; @@ -60,12 +65,15 @@ extern const struct hfi_platform hfi_plat_v4; extern const struct hfi_platform hfi_plat_v6; const struct hfi_platform *hfi_platform_get(enum hfi_version version); -unsigned long hfi_platform_get_codec_vpp_freq(enum hfi_version version, u32 codec, - u32 session_type); -unsigned long hfi_platform_get_codec_vsp_freq(enum hfi_version version, u32 codec, - u32 session_type); -unsigned long hfi_platform_get_codec_lp_freq(enum hfi_version version, u32 codec, - u32 session_type); -int hfi_platform_get_codecs(struct venus_core *core, u32 *enc_codecs, u32 *dec_codecs, - u32 *count); +unsigned long hfi_platform_get_codec_vpp_freq(struct venus_core *core, + enum hfi_version version, + u32 codec, u32 session_type); +unsigned long hfi_platform_get_codec_vsp_freq(struct venus_core *core, + enum hfi_version version, + u32 codec, u32 session_type); +unsigned long hfi_platform_get_codec_lp_freq(struct venus_core *core, + enum hfi_version version, + u32 codec, u32 session_type); +int hfi_platform_get_codecs(struct venus_core *core, u32 *enc_codecs, + u32 *dec_codecs, u32 *count); #endif diff --git a/drivers/media/platform/qcom/venus/hfi_platform_v4.c b/drivers/media/platform/qcom/venus/hfi_platform_v4.c index e3f0a90a567b..cda888b56b5d 100644 --- a/drivers/media/platform/qcom/venus/hfi_platform_v4.c +++ b/drivers/media/platform/qcom/venus/hfi_platform_v4.c @@ -2,6 +2,7 @@ /* * Copyright (c) 2020, The Linux Foundation. All rights reserved. */ +#include "core.h" #include "hfi_platform.h" static const struct hfi_plat_caps caps[] = { @@ -245,20 +246,150 @@ static const struct hfi_plat_caps caps[] = { .num_fmts = 4, } }; -static const struct hfi_plat_caps *get_capabilities(unsigned int *entries) +static const struct hfi_plat_caps caps_lite[] = { { - *entries = ARRAY_SIZE(caps); - return caps; + .codec = HFI_VIDEO_CODEC_H264, + .domain = VIDC_SESSION_TYPE_DEC, + .caps[0] = {HFI_CAPABILITY_FRAME_WIDTH, 128, 1920, 1}, + .caps[1] = {HFI_CAPABILITY_FRAME_HEIGHT, 128, 1920, 1}, + .caps[2] = {HFI_CAPABILITY_MBS_PER_FRAME, 64, 8160, 1}, + .caps[3] = {HFI_CAPABILITY_BITRATE, 1, 60000000, 1 }, + .caps[4] = {HFI_CAPABILITY_MBS_PER_SECOND, 64, 244800, 1}, + .caps[5] = {HFI_CAPABILITY_FRAMERATE, 1, 120, 1}, + .caps[6] = {HFI_CAPABILITY_MAX_VIDEOCORES, 0, 1, 1}, + .num_caps = 7, + .pl[0] = { HFI_H264_PROFILE_BASELINE, HFI_H264_LEVEL_5}, + .pl[1] = {HFI_H264_PROFILE_MAIN, HFI_H264_LEVEL_5}, + .pl[2] = {HFI_H264_PROFILE_HIGH, HFI_H264_LEVEL_5}, + .pl[3] = {HFI_H264_PROFILE_CONSTRAINED_BASE, HFI_H264_LEVEL_5}, + .pl[4] = {HFI_H264_PROFILE_CONSTRAINED_HIGH, HFI_H264_LEVEL_5}, + .num_pl = 5, + .fmts[0] = {HFI_BUFFER_OUTPUT, HFI_COLOR_FORMAT_NV12_UBWC}, + .fmts[1] = {HFI_BUFFER_OUTPUT2, HFI_COLOR_FORMAT_NV12_UBWC}, + .fmts[2] = {HFI_BUFFER_OUTPUT2, HFI_COLOR_FORMAT_NV12}, + .fmts[3] = {HFI_BUFFER_OUTPUT2, HFI_COLOR_FORMAT_NV21}, + .num_fmts = 4, +}, { + .codec = HFI_VIDEO_CODEC_HEVC, + .domain = VIDC_SESSION_TYPE_DEC, + .caps[0] = {HFI_CAPABILITY_FRAME_WIDTH, 128, 1920, 1}, + .caps[1] = {HFI_CAPABILITY_FRAME_HEIGHT, 128, 1920, 1}, + .caps[2] = {HFI_CAPABILITY_MBS_PER_FRAME, 64, 8160, 1}, + .caps[3] = {HFI_CAPABILITY_BITRATE, 1, 60000000, 1 }, + .caps[4] = {HFI_CAPABILITY_MBS_PER_SECOND, 64, 244800, 1}, + .caps[5] = {HFI_CAPABILITY_FRAMERATE, 1, 120, 1}, + .caps[6] = {HFI_CAPABILITY_MAX_VIDEOCORES, 0, 1, 1}, + .num_caps = 7, + .pl[0] = {HFI_HEVC_PROFILE_MAIN, HFI_HEVC_LEVEL_5 | HFI_HEVC_TIER_HIGH0 << 28 }, + .pl[1] = {HFI_HEVC_PROFILE_MAIN10, HFI_HEVC_LEVEL_5 | HFI_HEVC_TIER_HIGH0 << 28 }, + .num_pl = 2, + .fmts[0] = {HFI_BUFFER_OUTPUT, HFI_COLOR_FORMAT_NV12_UBWC}, + .fmts[1] = {HFI_BUFFER_OUTPUT2, HFI_COLOR_FORMAT_NV12_UBWC}, + .fmts[2] = {HFI_BUFFER_OUTPUT2, HFI_COLOR_FORMAT_NV12}, + .fmts[3] = {HFI_BUFFER_OUTPUT2, HFI_COLOR_FORMAT_NV21}, + .num_fmts = 4, +}, { + .codec = HFI_VIDEO_CODEC_VP9, + .domain = VIDC_SESSION_TYPE_DEC, + .caps[0] = {HFI_CAPABILITY_FRAME_WIDTH, 128, 1920, 1}, + .caps[1] = {HFI_CAPABILITY_FRAME_HEIGHT, 128, 1920, 1}, + .caps[2] = {HFI_CAPABILITY_MBS_PER_FRAME, 64, 8160, 1}, + .caps[3] = {HFI_CAPABILITY_BITRATE, 1, 60000000, 1 }, + .caps[4] = {HFI_CAPABILITY_MBS_PER_SECOND, 64, 244800, 1}, + .caps[5] = {HFI_CAPABILITY_FRAMERATE, 1, 120, 1}, + .caps[6] = {HFI_CAPABILITY_MAX_VIDEOCORES, 0, 1, 1}, + .num_caps = 7, + .pl[0] = {HFI_VP9_PROFILE_P0, 200}, + .pl[1] = {HFI_VP9_PROFILE_P2_10B, 200}, + .num_pl = 2, + .fmts[0] = {HFI_BUFFER_OUTPUT, HFI_COLOR_FORMAT_NV12_UBWC}, + .fmts[1] = {HFI_BUFFER_OUTPUT2, HFI_COLOR_FORMAT_NV12_UBWC}, + .fmts[2] = {HFI_BUFFER_OUTPUT2, HFI_COLOR_FORMAT_NV12}, + .fmts[3] = {HFI_BUFFER_OUTPUT2, HFI_COLOR_FORMAT_NV21}, + .num_fmts = 4, +}, { + .codec = HFI_VIDEO_CODEC_H264, + .domain = VIDC_SESSION_TYPE_ENC, + .caps[0] = {HFI_CAPABILITY_FRAME_WIDTH, 128, 1920, 1}, + .caps[1] = {HFI_CAPABILITY_FRAME_HEIGHT, 128, 1920, 1}, + .caps[2] = {HFI_CAPABILITY_MBS_PER_FRAME, 64, 8160, 1}, + .caps[3] = {HFI_CAPABILITY_BITRATE, 1, 60000000, 1 }, + .caps[4] = {HFI_CAPABILITY_MBS_PER_SECOND, 64, 244800, 1}, + .caps[5] = {HFI_CAPABILITY_FRAMERATE, 1, 120, 1}, + .caps[6] = {HFI_CAPABILITY_MAX_VIDEOCORES, 0, 1, 1}, + .caps[7] = {HFI_CAPABILITY_HIER_P_NUM_ENH_LAYERS, 0, 6, 1}, + .caps[8] = {HFI_CAPABILITY_ENC_LTR_COUNT, 0, 4, 1}, + .caps[9] = {HFI_CAPABILITY_MBS_PER_SECOND_POWERSAVE, 0, 244800, 1}, + .caps[10] = {HFI_CAPABILITY_I_FRAME_QP, 0, 51, 1}, + .caps[11] = {HFI_CAPABILITY_P_FRAME_QP, 0, 51, 1}, + .caps[12] = {HFI_CAPABILITY_B_FRAME_QP, 0, 51, 1}, + .caps[13] = {HFI_CAPABILITY_SLICE_BYTE, 1, 10, 1}, + .caps[14] = {HFI_CAPABILITY_SLICE_MB, 1, 10, 1}, + .num_caps = 15, + .pl[0] = {HFI_H264_PROFILE_BASELINE, HFI_H264_LEVEL_5}, + .pl[1] = {HFI_H264_PROFILE_MAIN, HFI_H264_LEVEL_5}, + .pl[2] = {HFI_H264_PROFILE_HIGH, HFI_H264_LEVEL_5}, + .pl[3] = {HFI_H264_PROFILE_CONSTRAINED_BASE, HFI_H264_LEVEL_5}, + .pl[4] = {HFI_H264_PROFILE_CONSTRAINED_HIGH, HFI_H264_LEVEL_5}, + .num_pl = 5, + .fmts[0] = {HFI_BUFFER_INPUT, HFI_COLOR_FORMAT_NV12}, + .fmts[1] = {HFI_BUFFER_INPUT, HFI_COLOR_FORMAT_NV12_UBWC}, + .num_fmts = 2, +}, { + .codec = HFI_VIDEO_CODEC_HEVC, + .domain = VIDC_SESSION_TYPE_ENC, + .caps[0] = {HFI_CAPABILITY_FRAME_WIDTH, 128, 1920, 1}, + .caps[1] = {HFI_CAPABILITY_FRAME_HEIGHT, 128, 1920, 1}, + .caps[2] = {HFI_CAPABILITY_MBS_PER_FRAME, 64, 8160, 1}, + .caps[3] = {HFI_CAPABILITY_BITRATE, 1, 60000000, 1 }, + .caps[4] = {HFI_CAPABILITY_MBS_PER_SECOND, 64, 244800, 1}, + .caps[5] = {HFI_CAPABILITY_FRAMERATE, 1, 120, 1}, + .caps[6] = {HFI_CAPABILITY_MAX_VIDEOCORES, 0, 1, 1}, + .caps[7] = {HFI_CAPABILITY_HIER_P_NUM_ENH_LAYERS, 0, 6, 1}, + .caps[8] = {HFI_CAPABILITY_ENC_LTR_COUNT, 0, 4, 1}, + .caps[9] = {HFI_CAPABILITY_MBS_PER_SECOND_POWERSAVE, 0, 244800, 1}, + .caps[10] = {HFI_CAPABILITY_I_FRAME_QP, 0, 51, 1}, + .caps[11] = {HFI_CAPABILITY_P_FRAME_QP, 0, 51, 1}, + .caps[12] = {HFI_CAPABILITY_B_FRAME_QP, 0, 51, 1}, + .caps[13] = {HFI_CAPABILITY_SLICE_BYTE, 1, 10, 1}, + .caps[14] = {HFI_CAPABILITY_SLICE_MB, 1, 10, 1}, + .num_caps = 15, + .pl[0] = {HFI_HEVC_PROFILE_MAIN, HFI_HEVC_LEVEL_5 | HFI_HEVC_TIER_HIGH0}, + .pl[1] = {HFI_HEVC_PROFILE_MAIN10, HFI_HEVC_LEVEL_5 | HFI_HEVC_TIER_HIGH0}, + .num_pl = 2, + .fmts[0] = {HFI_BUFFER_INPUT, HFI_COLOR_FORMAT_NV12}, + .fmts[1] = {HFI_BUFFER_INPUT, HFI_COLOR_FORMAT_NV12_UBWC}, + .num_fmts = 2, +} }; + +static const struct hfi_plat_caps *get_capabilities(struct venus_core *core, + unsigned int *entries) +{ + *entries = is_lite(core) ? ARRAY_SIZE(caps_lite) : ARRAY_SIZE(caps); + + return is_lite(core) ? caps_lite : caps; } -static void get_codecs(u32 *enc_codecs, u32 *dec_codecs, u32 *count) +static void get_codecs(struct venus_core *core, + u32 *enc_codecs, u32 *dec_codecs, u32 *count) { - *enc_codecs = HFI_VIDEO_CODEC_H264 | HFI_VIDEO_CODEC_HEVC | - HFI_VIDEO_CODEC_VP8; - *dec_codecs = HFI_VIDEO_CODEC_H264 | HFI_VIDEO_CODEC_HEVC | - HFI_VIDEO_CODEC_VP8 | HFI_VIDEO_CODEC_VP9 | - HFI_VIDEO_CODEC_MPEG2; - *count = 8; + const struct hfi_plat_caps *caps; + unsigned int num; + size_t i; + + *enc_codecs = 0; + *dec_codecs = 0; + + caps = get_capabilities(core, &num); + + for (i = 0; i < num; caps++, i++) { + if (caps->domain == VIDC_SESSION_TYPE_ENC) + *enc_codecs |= caps->codec; + else + *dec_codecs |= caps->codec; + } + + *count = num; } static const struct hfi_platform_codec_freq_data codec_freq_data[] = { @@ -272,13 +403,29 @@ static const struct hfi_platform_codec_freq_data codec_freq_data[] = { { V4L2_PIX_FMT_VP9, VIDC_SESSION_TYPE_DEC, 200, 10, 200 }, }; +static const struct hfi_platform_codec_freq_data codec_freq_data_lite[] = { + { V4L2_PIX_FMT_H264, VIDC_SESSION_TYPE_DEC, 440, 0, 440 }, + { V4L2_PIX_FMT_HEVC, VIDC_SESSION_TYPE_DEC, 440, 0, 440 }, + { V4L2_PIX_FMT_VP9, VIDC_SESSION_TYPE_DEC, 440, 0, 440 }, + { V4L2_PIX_FMT_H264, VIDC_SESSION_TYPE_ENC, 675, 0, 675 }, + { V4L2_PIX_FMT_HEVC, VIDC_SESSION_TYPE_ENC, 675, 0, 675 }, +}; + static const struct hfi_platform_codec_freq_data * -get_codec_freq_data(u32 session_type, u32 pixfmt) +get_codec_freq_data(struct venus_core *core, u32 session_type, u32 pixfmt) { - const struct hfi_platform_codec_freq_data *data = codec_freq_data; - unsigned int i, data_size = ARRAY_SIZE(codec_freq_data); + const struct hfi_platform_codec_freq_data *data; + unsigned int i, data_size; const struct hfi_platform_codec_freq_data *found = NULL; + if (is_lite(core)) { + data = codec_freq_data_lite; + data_size = ARRAY_SIZE(codec_freq_data_lite); + } else { + data = codec_freq_data; + data_size = ARRAY_SIZE(codec_freq_data); + } + for (i = 0; i < data_size; i++) { if (data[i].pixfmt == pixfmt && data[i].session_type == session_type) { found = &data[i]; @@ -289,33 +436,36 @@ get_codec_freq_data(u32 session_type, u32 pixfmt) return found; } -static unsigned long codec_vpp_freq(u32 session_type, u32 codec) +static unsigned long codec_vpp_freq(struct venus_core *core, + u32 session_type, u32 codec) { const struct hfi_platform_codec_freq_data *data; - data = get_codec_freq_data(session_type, codec); + data = get_codec_freq_data(core, session_type, codec); if (data) return data->vpp_freq; return 0; } -static unsigned long codec_vsp_freq(u32 session_type, u32 codec) +static unsigned long codec_vsp_freq(struct venus_core *core, + u32 session_type, u32 codec) { const struct hfi_platform_codec_freq_data *data; - data = get_codec_freq_data(session_type, codec); + data = get_codec_freq_data(core, session_type, codec); if (data) return data->vsp_freq; return 0; } -static unsigned long codec_lp_freq(u32 session_type, u32 codec) +static unsigned long codec_lp_freq(struct venus_core *core, + u32 session_type, u32 codec) { const struct hfi_platform_codec_freq_data *data; - data = get_codec_freq_data(session_type, codec); + data = get_codec_freq_data(core, session_type, codec); if (data) return data->low_power_freq; diff --git a/drivers/media/platform/qcom/venus/hfi_platform_v6.c b/drivers/media/platform/qcom/venus/hfi_platform_v6.c index 4e8af645f8b9..d8568c08cc36 100644 --- a/drivers/media/platform/qcom/venus/hfi_platform_v6.c +++ b/drivers/media/platform/qcom/venus/hfi_platform_v6.c @@ -2,6 +2,7 @@ /* * Copyright (c) 2020, The Linux Foundation. All rights reserved. */ +#include "core.h" #include "hfi_platform.h" static const struct hfi_plat_caps caps[] = { @@ -245,14 +246,22 @@ static const struct hfi_plat_caps caps[] = { .num_fmts = 4, } }; -static const struct hfi_plat_caps *get_capabilities(unsigned int *entries) +static const struct hfi_plat_caps *get_capabilities(struct venus_core *core, + unsigned int *entries) { + if (is_lite(core)) + return NULL; + *entries = ARRAY_SIZE(caps); return caps; } -static void get_codecs(u32 *enc_codecs, u32 *dec_codecs, u32 *count) +static void get_codecs(struct venus_core *core, u32 *enc_codecs, + u32 *dec_codecs, u32 *count) { + if (is_lite(core)) + return; + *enc_codecs = HFI_VIDEO_CODEC_H264 | HFI_VIDEO_CODEC_HEVC | HFI_VIDEO_CODEC_VP8; *dec_codecs = HFI_VIDEO_CODEC_H264 | HFI_VIDEO_CODEC_HEVC | @@ -273,12 +282,15 @@ static const struct hfi_platform_codec_freq_data codec_freq_data[] = { }; static const struct hfi_platform_codec_freq_data * -get_codec_freq_data(u32 session_type, u32 pixfmt) +get_codec_freq_data(struct venus_core *core, u32 session_type, u32 pixfmt) { const struct hfi_platform_codec_freq_data *data = codec_freq_data; unsigned int i, data_size = ARRAY_SIZE(codec_freq_data); const struct hfi_platform_codec_freq_data *found = NULL; + if (is_lite(core)) + return NULL; + for (i = 0; i < data_size; i++) { if (data[i].pixfmt == pixfmt && data[i].session_type == session_type) { found = &data[i]; @@ -289,33 +301,36 @@ get_codec_freq_data(u32 session_type, u32 pixfmt) return found; } -static unsigned long codec_vpp_freq(u32 session_type, u32 codec) +static unsigned long codec_vpp_freq(struct venus_core *core, u32 session_type, + u32 codec) { const struct hfi_platform_codec_freq_data *data; - data = get_codec_freq_data(session_type, codec); + data = get_codec_freq_data(core, session_type, codec); if (data) return data->vpp_freq; return 0; } -static unsigned long codec_vsp_freq(u32 session_type, u32 codec) +static unsigned long codec_vsp_freq(struct venus_core *core, u32 session_type, + u32 codec) { const struct hfi_platform_codec_freq_data *data; - data = get_codec_freq_data(session_type, codec); + data = get_codec_freq_data(core, session_type, codec); if (data) return data->vsp_freq; return 0; } -static unsigned long codec_lp_freq(u32 session_type, u32 codec) +static unsigned long codec_lp_freq(struct venus_core *core, u32 session_type, + u32 codec) { const struct hfi_platform_codec_freq_data *data; - data = get_codec_freq_data(session_type, codec); + data = get_codec_freq_data(core, session_type, codec); if (data) return data->low_power_freq; diff --git a/drivers/media/platform/qcom/venus/hfi_venus.c b/drivers/media/platform/qcom/venus/hfi_venus.c index cec7f5964d3d..d3da35f67fd5 100644 --- a/drivers/media/platform/qcom/venus/hfi_venus.c +++ b/drivers/media/platform/qcom/venus/hfi_venus.c @@ -380,7 +380,7 @@ static void venus_soft_int(struct venus_hfi_device *hdev) void __iomem *cpu_ic_base = hdev->core->cpu_ic_base; u32 clear_bit; - if (IS_V6(hdev->core)) + if (IS_V6(hdev->core) || (IS_V4(hdev->core) && is_lite(hdev->core))) clear_bit = BIT(CPU_IC_SOFTINT_H2A_SHIFT_V6); else clear_bit = BIT(CPU_IC_SOFTINT_H2A_SHIFT); @@ -501,9 +501,11 @@ static int venus_boot_core(struct venus_hfi_device *hdev) if (count >= max_tries) ret = -ETIMEDOUT; - if (IS_IRIS2(hdev->core) || IS_IRIS2_1(hdev->core)) { + if (IS_IRIS2(hdev->core) || IS_IRIS2_1(hdev->core) || IS_AR50_LITE(hdev->core)) { writel(0x1, cpu_cs_base + CPU_CS_H2XSOFTINTEN_V6); - writel(0x0, cpu_cs_base + CPU_CS_X2RPMH_V6); + + if (!IS_AR50_LITE(hdev->core)) + writel(0x0, cpu_cs_base + CPU_CS_X2RPMH_V6); } return ret; @@ -569,6 +571,9 @@ static int venus_halt_axi(struct venus_hfi_device *hdev) u32 mask_val; int ret; + if (IS_AR50_LITE(hdev->core)) + return 0; + if (IS_IRIS2(hdev->core) || IS_IRIS2_1(hdev->core)) { writel(0x3, cpu_cs_base + CPU_CS_X2RPMH_V6); @@ -1138,7 +1143,13 @@ static irqreturn_t venus_isr(struct venus_core *core) wrapper_base = hdev->core->wrapper_base; status = readl(wrapper_base + WRAPPER_INTR_STATUS); - if (IS_IRIS2(core) || IS_IRIS2_1(core)) { + + if (IS_AR50_LITE(core)) { + if (status & WRAPPER_INTR_STATUS_A2H_MASK || + status & WRAPPER_INTR_STATUS_A2HWD_MASK_V4_LITE || + status & CPU_CS_SCIACMDARG0_INIT_IDLE_MSG_MASK) + hdev->irq_status = status; + } else if (IS_IRIS2(core) || IS_IRIS2_1(core)) { if (status & WRAPPER_INTR_STATUS_A2H_MASK || status & WRAPPER_INTR_STATUS_A2HWD_MASK_V6 || status & CPU_CS_SCIACMDARG0_INIT_IDLE_MSG_MASK) @@ -1150,7 +1161,7 @@ static irqreturn_t venus_isr(struct venus_core *core) hdev->irq_status = status; } writel(1, cpu_cs_base + CPU_CS_A2HSOFTINTCLR); - if (!(IS_IRIS2(core) || IS_IRIS2_1(core))) + if (!(IS_IRIS2(core) || IS_IRIS2_1(core) || IS_AR50_LITE(core))) writel(status, wrapper_base + WRAPPER_INTR_CLEAR); return IRQ_WAKE_THREAD; @@ -1535,7 +1546,7 @@ static bool venus_cpu_and_video_core_idle(struct venus_hfi_device *hdev) void __iomem *cpu_cs_base = hdev->core->cpu_cs_base; u32 ctrl_status, cpu_status; - if (IS_IRIS2(hdev->core) || IS_IRIS2_1(hdev->core)) + if (IS_IRIS2(hdev->core) || IS_IRIS2_1(hdev->core) || IS_AR50_LITE(hdev->core)) cpu_status = readl(wrapper_tz_base + WRAPPER_TZ_CPU_STATUS_V6); else cpu_status = readl(wrapper_base + WRAPPER_CPU_STATUS); @@ -1555,7 +1566,7 @@ static bool venus_cpu_idle_and_pc_ready(struct venus_hfi_device *hdev) void __iomem *cpu_cs_base = hdev->core->cpu_cs_base; u32 ctrl_status, cpu_status; - if (IS_IRIS2(hdev->core) || IS_IRIS2_1(hdev->core)) + if (IS_IRIS2(hdev->core) || IS_IRIS2_1(hdev->core) || IS_AR50_LITE(hdev->core)) cpu_status = readl(wrapper_tz_base + WRAPPER_TZ_CPU_STATUS_V6); else cpu_status = readl(wrapper_base + WRAPPER_CPU_STATUS); diff --git a/drivers/media/platform/qcom/venus/hfi_venus_io.h b/drivers/media/platform/qcom/venus/hfi_venus_io.h index 9735a246ce36..f2c3064c44ae 100644 --- a/drivers/media/platform/qcom/venus/hfi_venus_io.h +++ b/drivers/media/platform/qcom/venus/hfi_venus_io.h @@ -51,6 +51,9 @@ /* Venus cpu */ #define CPU_CS_SCIACMDARG3 0x58 +#define CPU_CS_VCICMD 0x20 +#define CPU_CS_VCICMD_ARP_OFF BIT(0) + #define SFR_ADDR 0x5c #define MMAP_ADDR 0x60 #define UC_REGION_ADDR 0x64 @@ -100,6 +103,7 @@ #define WRAPPER_INTR_MASK_A2HCPU_MASK 0x4 #define WRAPPER_INTR_MASK_A2HCPU_SHIFT 0x2 +#define WRAPPER_INTR_STATUS_A2HWD_MASK_V4_LITE 0x10 #define WRAPPER_INTR_STATUS_A2HWD_MASK_V6 0x8 #define WRAPPER_INTR_MASK_A2HWD_BASK_V6 0x8 diff --git a/drivers/media/platform/qcom/venus/pm_helpers.c b/drivers/media/platform/qcom/venus/pm_helpers.c index e32f8862a9f9..f0269524ac70 100644 --- a/drivers/media/platform/qcom/venus/pm_helpers.c +++ b/drivers/media/platform/qcom/venus/pm_helpers.c @@ -40,6 +40,8 @@ static int core_clks_get(struct venus_core *core) static int core_clks_enable(struct venus_core *core) { + const struct freq_tbl *freq_tbl = core->res->freq_tbl; + unsigned int freq_tbl_size = core->res->freq_tbl_size; const struct venus_resources *res = core->res; struct device *dev = core->dev; unsigned long freq = 0; @@ -48,11 +50,16 @@ static int core_clks_enable(struct venus_core *core) int ret; opp = dev_pm_opp_find_freq_ceil(dev, &freq); - if (!IS_ERR(opp)) + if (IS_ERR(opp)) { + if (!freq_tbl) + return -ENODEV; + freq = freq_tbl[freq_tbl_size - 1].freq; + } else { dev_pm_opp_put(opp); + } for (i = 0; i < res->clks_num; i++) { - if (IS_V6(core)) { + if (IS_V6(core) || (IS_V4(core) && is_lite(core))) { ret = clk_set_rate(core->clks[i], freq); if (ret) goto err; diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c index 29b0d6a5303d..55c27345b7d8 100644 --- a/drivers/media/platform/qcom/venus/vdec.c +++ b/drivers/media/platform/qcom/venus/vdec.c @@ -1732,9 +1732,8 @@ static int vdec_open(struct file *file) v4l2_fh_init(&inst->fh, core->vdev_dec); inst->fh.ctrl_handler = &inst->ctrl_handler; - v4l2_fh_add(&inst->fh); + v4l2_fh_add(&inst->fh, file); inst->fh.m2m_ctx = inst->m2m_ctx; - file->private_data = &inst->fh; return 0; @@ -1755,7 +1754,7 @@ static int vdec_close(struct file *file) vdec_pm_get(inst); cancel_work_sync(&inst->delayed_process_work); - venus_close_common(inst); + venus_close_common(inst, file); ida_destroy(&inst->dpb_ids); vdec_pm_put(inst, false); diff --git a/drivers/media/platform/qcom/venus/venc.c b/drivers/media/platform/qcom/venus/venc.c index c0a0ccdded80..fba07557a399 100644 --- a/drivers/media/platform/qcom/venus/venc.c +++ b/drivers/media/platform/qcom/venus/venc.c @@ -1515,9 +1515,8 @@ static int venc_open(struct file *file) v4l2_fh_init(&inst->fh, core->vdev_enc); inst->fh.ctrl_handler = &inst->ctrl_handler; - v4l2_fh_add(&inst->fh); + v4l2_fh_add(&inst->fh, file); inst->fh.m2m_ctx = inst->m2m_ctx; - file->private_data = &inst->fh; return 0; @@ -1537,7 +1536,7 @@ static int venc_close(struct file *file) struct venus_inst *inst = to_inst(file); venc_pm_get(inst); - venus_close_common(inst); + venus_close_common(inst, file); inst->enc_state = VENUS_ENC_STATE_DEINIT; venc_pm_put(inst, false); diff --git a/drivers/media/platform/raspberrypi/rp1-cfe/csi2.c b/drivers/media/platform/raspberrypi/rp1-cfe/csi2.c index 35c2ab1e2cd4..2c5b4d24b4e6 100644 --- a/drivers/media/platform/raspberrypi/rp1-cfe/csi2.c +++ b/drivers/media/platform/raspberrypi/rp1-cfe/csi2.c @@ -525,7 +525,7 @@ static const struct v4l2_subdev_internal_ops csi2_internal_ops = { int csi2_init(struct csi2_device *csi2, struct dentry *debugfs) { - unsigned int ret; + int ret; spin_lock_init(&csi2->errors_lock); diff --git a/drivers/media/platform/renesas/rcar-vin/rcar-core.c b/drivers/media/platform/renesas/rcar-vin/rcar-core.c index f73729f59671..100105b620e3 100644 --- a/drivers/media/platform/renesas/rcar-vin/rcar-core.c +++ b/drivers/media/platform/renesas/rcar-vin/rcar-core.c @@ -849,7 +849,7 @@ static int rvin_isp_init(struct rvin_dev *vin) * Suspend / Resume */ -static int __maybe_unused rvin_suspend(struct device *dev) +static int rvin_suspend(struct device *dev) { struct rvin_dev *vin = dev_get_drvdata(dev); @@ -861,7 +861,7 @@ static int __maybe_unused rvin_suspend(struct device *dev) return 0; } -static int __maybe_unused rvin_resume(struct device *dev) +static int rvin_resume(struct device *dev) { struct rvin_dev *vin = dev_get_drvdata(dev); @@ -1276,13 +1276,13 @@ static void rcar_vin_remove(struct platform_device *pdev) rvin_dma_unregister(vin); } -static SIMPLE_DEV_PM_OPS(rvin_pm_ops, rvin_suspend, rvin_resume); +static DEFINE_SIMPLE_DEV_PM_OPS(rvin_pm_ops, rvin_suspend, rvin_resume); static struct platform_driver rcar_vin_driver = { .driver = { .name = "rcar-vin", .suppress_bind_attrs = true, - .pm = &rvin_pm_ops, + .pm = pm_sleep_ptr(&rvin_pm_ops), .of_match_table = rvin_of_id_table, }, .probe = rcar_vin_probe, diff --git a/drivers/media/platform/renesas/rcar-vin/rcar-v4l2.c b/drivers/media/platform/renesas/rcar-vin/rcar-v4l2.c index 62eddf3a35fc..079dbaf016c2 100644 --- a/drivers/media/platform/renesas/rcar-vin/rcar-v4l2.c +++ b/drivers/media/platform/renesas/rcar-vin/rcar-v4l2.c @@ -588,8 +588,6 @@ static int rvin_open(struct file *file) if (ret) goto err_pm; - file->private_data = vin; - ret = v4l2_fh_open(file); if (ret) goto err_unlock; diff --git a/drivers/media/platform/renesas/rcar_drif.c b/drivers/media/platform/renesas/rcar_drif.c index fc8b6bbef793..11bf47fb8266 100644 --- a/drivers/media/platform/renesas/rcar_drif.c +++ b/drivers/media/platform/renesas/rcar_drif.c @@ -1446,18 +1446,18 @@ static void rcar_drif_remove(struct platform_device *pdev) } /* FIXME: Implement suspend/resume support */ -static int __maybe_unused rcar_drif_suspend(struct device *dev) +static int rcar_drif_suspend(struct device *dev) { return 0; } -static int __maybe_unused rcar_drif_resume(struct device *dev) +static int rcar_drif_resume(struct device *dev) { return 0; } -static SIMPLE_DEV_PM_OPS(rcar_drif_pm_ops, rcar_drif_suspend, - rcar_drif_resume); +static DEFINE_SIMPLE_DEV_PM_OPS(rcar_drif_pm_ops, rcar_drif_suspend, + rcar_drif_resume); static const struct of_device_id rcar_drif_of_table[] = { { .compatible = "renesas,rcar-gen3-drif" }, @@ -1470,8 +1470,8 @@ static struct platform_driver rcar_drif_driver = { .driver = { .name = RCAR_DRIF_DRV_NAME, .of_match_table = rcar_drif_of_table, - .pm = &rcar_drif_pm_ops, - }, + .pm = pm_sleep_ptr(&rcar_drif_pm_ops), + }, .probe = rcar_drif_probe, .remove = rcar_drif_remove, }; diff --git a/drivers/media/platform/renesas/rcar_fdp1.c b/drivers/media/platform/renesas/rcar_fdp1.c index 5d453a7a8988..e615c56083f1 100644 --- a/drivers/media/platform/renesas/rcar_fdp1.c +++ b/drivers/media/platform/renesas/rcar_fdp1.c @@ -630,9 +630,9 @@ struct fdp1_ctx { struct fdp1_field_buffer *previous; }; -static inline struct fdp1_ctx *fh_to_ctx(struct v4l2_fh *fh) +static inline struct fdp1_ctx *file_to_ctx(struct file *filp) { - return container_of(fh, struct fdp1_ctx, fh); + return container_of(file_to_v4l2_fh(filp), struct fdp1_ctx, fh); } static struct fdp1_q_data *get_q_data(struct fdp1_ctx *ctx, @@ -1406,8 +1406,8 @@ static int fdp1_enum_fmt_vid_out(struct file *file, void *priv, static int fdp1_g_fmt(struct file *file, void *priv, struct v4l2_format *f) { + struct fdp1_ctx *ctx = file_to_ctx(file); struct fdp1_q_data *q_data; - struct fdp1_ctx *ctx = fh_to_ctx(priv); if (!v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type)) return -EINVAL; @@ -1584,7 +1584,7 @@ static void fdp1_try_fmt_capture(struct fdp1_ctx *ctx, static int fdp1_try_fmt(struct file *file, void *priv, struct v4l2_format *f) { - struct fdp1_ctx *ctx = fh_to_ctx(priv); + struct fdp1_ctx *ctx = file_to_ctx(file); if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) fdp1_try_fmt_output(ctx, NULL, &f->fmt.pix_mp); @@ -1655,7 +1655,7 @@ static void fdp1_set_format(struct fdp1_ctx *ctx, static int fdp1_s_fmt(struct file *file, void *priv, struct v4l2_format *f) { - struct fdp1_ctx *ctx = fh_to_ctx(priv); + struct fdp1_ctx *ctx = file_to_ctx(file); struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx; struct vb2_queue *vq = v4l2_m2m_get_vq(m2m_ctx, f->type); @@ -2088,7 +2088,6 @@ static int fdp1_open(struct file *file) } v4l2_fh_init(&ctx->fh, video_devdata(file)); - file->private_data = &ctx->fh; ctx->fdp1 = fdp1; /* Initialise Queues */ @@ -2137,7 +2136,7 @@ static int fdp1_open(struct file *file) if (ret < 0) goto error_pm; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); dprintk(fdp1, "Created instance: %p, m2m_ctx: %p\n", ctx, ctx->fh.m2m_ctx); @@ -2158,11 +2157,11 @@ done: static int fdp1_release(struct file *file) { struct fdp1_dev *fdp1 = video_drvdata(file); - struct fdp1_ctx *ctx = fh_to_ctx(file->private_data); + struct fdp1_ctx *ctx = file_to_ctx(file); dprintk(fdp1, "Releasing instance %p\n", ctx); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); v4l2_ctrl_handler_free(&ctx->hdl); mutex_lock(&fdp1->dev_mutex); @@ -2409,7 +2408,7 @@ static void fdp1_remove(struct platform_device *pdev) rcar_fcp_put(fdp1->fcp); } -static int __maybe_unused fdp1_pm_runtime_suspend(struct device *dev) +static int fdp1_pm_runtime_suspend(struct device *dev) { struct fdp1_dev *fdp1 = dev_get_drvdata(dev); @@ -2418,7 +2417,7 @@ static int __maybe_unused fdp1_pm_runtime_suspend(struct device *dev) return 0; } -static int __maybe_unused fdp1_pm_runtime_resume(struct device *dev) +static int fdp1_pm_runtime_resume(struct device *dev) { struct fdp1_dev *fdp1 = dev_get_drvdata(dev); @@ -2429,9 +2428,7 @@ static int __maybe_unused fdp1_pm_runtime_resume(struct device *dev) } static const struct dev_pm_ops fdp1_pm_ops = { - SET_RUNTIME_PM_OPS(fdp1_pm_runtime_suspend, - fdp1_pm_runtime_resume, - NULL) + RUNTIME_PM_OPS(fdp1_pm_runtime_suspend, fdp1_pm_runtime_resume, NULL) }; static const struct of_device_id fdp1_dt_ids[] = { @@ -2446,7 +2443,7 @@ static struct platform_driver fdp1_pdrv = { .driver = { .name = DRIVER_NAME, .of_match_table = fdp1_dt_ids, - .pm = &fdp1_pm_ops, + .pm = pm_ptr(&fdp1_pm_ops), }, }; diff --git a/drivers/media/platform/renesas/rcar_jpu.c b/drivers/media/platform/renesas/rcar_jpu.c index 81038df71bb5..46ea259a2bb9 100644 --- a/drivers/media/platform/renesas/rcar_jpu.c +++ b/drivers/media/platform/renesas/rcar_jpu.c @@ -480,9 +480,9 @@ static struct jpu_ctx *ctrl_to_ctx(struct v4l2_ctrl *c) return container_of(c->handler, struct jpu_ctx, ctrl_handler); } -static struct jpu_ctx *fh_to_ctx(struct v4l2_fh *fh) +static struct jpu_ctx *file_to_ctx(struct file *filp) { - return container_of(fh, struct jpu_ctx, fh); + return container_of(file_to_v4l2_fh(filp), struct jpu_ctx, fh); } static void jpu_set_tbl(struct jpu *jpu, u32 reg, const unsigned int *tbl, @@ -656,7 +656,7 @@ static u8 jpu_parse_hdr(void *buffer, unsigned long size, unsigned int *width, static int jpu_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { - struct jpu_ctx *ctx = fh_to_ctx(priv); + struct jpu_ctx *ctx = file_to_ctx(file); if (ctx->encoder) strscpy(cap->card, DRV_NAME " encoder", sizeof(cap->card)); @@ -714,7 +714,7 @@ static int jpu_enum_fmt(struct v4l2_fmtdesc *f, u32 type) static int jpu_enum_fmt_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - struct jpu_ctx *ctx = fh_to_ctx(priv); + struct jpu_ctx *ctx = file_to_ctx(file); return jpu_enum_fmt(f, ctx->encoder ? JPU_ENC_CAPTURE : JPU_DEC_CAPTURE); @@ -723,7 +723,7 @@ static int jpu_enum_fmt_cap(struct file *file, void *priv, static int jpu_enum_fmt_out(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - struct jpu_ctx *ctx = fh_to_ctx(priv); + struct jpu_ctx *ctx = file_to_ctx(file); return jpu_enum_fmt(f, ctx->encoder ? JPU_ENC_OUTPUT : JPU_DEC_OUTPUT); } @@ -823,7 +823,7 @@ static int __jpu_try_fmt(struct jpu_ctx *ctx, struct jpu_fmt **fmtinfo, static int jpu_try_fmt(struct file *file, void *priv, struct v4l2_format *f) { - struct jpu_ctx *ctx = fh_to_ctx(priv); + struct jpu_ctx *ctx = file_to_ctx(file); if (!v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type)) return -EINVAL; @@ -834,7 +834,7 @@ static int jpu_try_fmt(struct file *file, void *priv, struct v4l2_format *f) static int jpu_s_fmt(struct file *file, void *priv, struct v4l2_format *f) { struct vb2_queue *vq; - struct jpu_ctx *ctx = fh_to_ctx(priv); + struct jpu_ctx *ctx = file_to_ctx(file); struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx; struct jpu_fmt *fmtinfo; struct jpu_q_data *q_data; @@ -863,8 +863,8 @@ static int jpu_s_fmt(struct file *file, void *priv, struct v4l2_format *f) static int jpu_g_fmt(struct file *file, void *priv, struct v4l2_format *f) { + struct jpu_ctx *ctx = file_to_ctx(file); struct jpu_q_data *q_data; - struct jpu_ctx *ctx = fh_to_ctx(priv); if (!v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type)) return -EINVAL; @@ -897,8 +897,8 @@ static const struct v4l2_ctrl_ops jpu_ctrl_ops = { static int jpu_streamon(struct file *file, void *priv, enum v4l2_buf_type type) { - struct jpu_ctx *ctx = fh_to_ctx(priv); struct jpu_q_data *src_q_data, *dst_q_data, *orig, adj, *ref; + struct jpu_ctx *ctx = file_to_ctx(file); enum v4l2_buf_type adj_type; src_q_data = jpu_get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); @@ -1226,8 +1226,7 @@ static int jpu_open(struct file *file) v4l2_fh_init(&ctx->fh, vfd); ctx->fh.ctrl_handler = &ctx->ctrl_handler; - file->private_data = &ctx->fh; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); ctx->jpu = jpu; ctx->encoder = vfd == &jpu->vfd_encoder; @@ -1272,7 +1271,7 @@ jpu_reset_rollback: device_prepare_rollback: mutex_unlock(&jpu->mutex); v4l_prepare_rollback: - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); kfree(ctx); return ret; @@ -1280,12 +1279,12 @@ v4l_prepare_rollback: static int jpu_release(struct file *file) { + struct jpu_ctx *ctx = file_to_ctx(file); struct jpu *jpu = video_drvdata(file); - struct jpu_ctx *ctx = fh_to_ctx(file->private_data); v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); v4l2_ctrl_handler_free(&ctx->ctrl_handler); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); kfree(ctx); @@ -1745,6 +1744,6 @@ static struct platform_driver jpu_driver = { module_platform_driver(jpu_driver); MODULE_ALIAS("platform:" DRV_NAME); -MODULE_AUTHOR("Mikhail Ulianov <mikhail.ulyanov@cogentembedded.com>"); +MODULE_AUTHOR("Mikhail Ulianov"); MODULE_DESCRIPTION("Renesas R-Car JPEG processing unit driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/media/platform/renesas/renesas-ceu.c b/drivers/media/platform/renesas/renesas-ceu.c index 8cceafe491b1..deed49d0fb10 100644 --- a/drivers/media/platform/renesas/renesas-ceu.c +++ b/drivers/media/platform/renesas/renesas-ceu.c @@ -1048,7 +1048,7 @@ static int ceu_init_mbus_fmt(struct ceu_device *ceudev) /* * ceu_runtime_resume() - soft-reset the interface and turn sensor power on. */ -static int __maybe_unused ceu_runtime_resume(struct device *dev) +static int ceu_runtime_resume(struct device *dev) { struct ceu_device *ceudev = dev_get_drvdata(dev); struct v4l2_subdev *v4l2_sd = ceudev->sd->v4l2_sd; @@ -1064,7 +1064,7 @@ static int __maybe_unused ceu_runtime_resume(struct device *dev) * ceu_runtime_suspend() - disable capture and interrupts and soft-reset. * Turn sensor power off. */ -static int __maybe_unused ceu_runtime_suspend(struct device *dev) +static int ceu_runtime_suspend(struct device *dev) { struct ceu_device *ceudev = dev_get_drvdata(dev); struct v4l2_subdev *v4l2_sd = ceudev->sd->v4l2_sd; @@ -1709,15 +1709,13 @@ static void ceu_remove(struct platform_device *pdev) } static const struct dev_pm_ops ceu_pm_ops = { - SET_RUNTIME_PM_OPS(ceu_runtime_suspend, - ceu_runtime_resume, - NULL) + RUNTIME_PM_OPS(ceu_runtime_suspend, ceu_runtime_resume, NULL) }; static struct platform_driver ceu_driver = { .driver = { .name = DRIVER_NAME, - .pm = &ceu_pm_ops, + .pm = pm_ptr(&ceu_pm_ops), .of_match_table = of_match_ptr(ceu_of_match), }, .probe = ceu_probe, diff --git a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-core.c b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-core.c index 806acc8f9728..3c5fbd857371 100644 --- a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-core.c +++ b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-core.c @@ -367,7 +367,6 @@ static const struct rzg2l_cru_info rzg3e_cru_info = { .enable_interrupts = rzg3e_cru_enable_interrupts, .disable_interrupts = rzg3e_cru_disable_interrupts, .fifo_empty = rzg3e_fifo_empty, - .csi_setup = rzg3e_cru_csi2_setup, }; static const u16 rzg2l_cru_regs[] = { @@ -412,7 +411,6 @@ static const struct rzg2l_cru_info rzg2l_cru_info = { .enable_interrupts = rzg2l_cru_enable_interrupts, .disable_interrupts = rzg2l_cru_disable_interrupts, .fifo_empty = rzg2l_fifo_empty, - .csi_setup = rzg2l_cru_csi2_setup, }; static const struct of_device_id rzg2l_cru_of_id_table[] = { diff --git a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-cru.h b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-cru.h index be95b41c37df..3a200db15730 100644 --- a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-cru.h +++ b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-cru.h @@ -92,9 +92,6 @@ struct rzg2l_cru_info { void (*enable_interrupts)(struct rzg2l_cru_dev *cru); void (*disable_interrupts)(struct rzg2l_cru_dev *cru); bool (*fifo_empty)(struct rzg2l_cru_dev *cru); - void (*csi_setup)(struct rzg2l_cru_dev *cru, - const struct rzg2l_cru_ip_format *ip_fmt, - u8 csi_vc); }; /** @@ -204,11 +201,5 @@ void rzg3e_cru_disable_interrupts(struct rzg2l_cru_dev *cru); bool rzg2l_fifo_empty(struct rzg2l_cru_dev *cru); bool rzg3e_fifo_empty(struct rzg2l_cru_dev *cru); -void rzg2l_cru_csi2_setup(struct rzg2l_cru_dev *cru, - const struct rzg2l_cru_ip_format *ip_fmt, - u8 csi_vc); -void rzg3e_cru_csi2_setup(struct rzg2l_cru_dev *cru, - const struct rzg2l_cru_ip_format *ip_fmt, - u8 csi_vc); #endif diff --git a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-video.c b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-video.c index a8817a7066b2..162e2ace6931 100644 --- a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-video.c +++ b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-video.c @@ -257,30 +257,18 @@ static void rzg2l_cru_initialize_axi(struct rzg2l_cru_dev *cru) rzg2l_cru_write(cru, AMnAXIATTR, amnaxiattr); } -void rzg3e_cru_csi2_setup(struct rzg2l_cru_dev *cru, - const struct rzg2l_cru_ip_format *ip_fmt, - u8 csi_vc) +static void rzg2l_cru_csi2_setup(struct rzg2l_cru_dev *cru, + const struct rzg2l_cru_ip_format *ip_fmt, + u8 csi_vc) { const struct rzg2l_cru_info *info = cru->info; u32 icnmc = ICnMC_INF(ip_fmt->datatype); - icnmc |= rzg2l_cru_read(cru, info->image_conv) & ~ICnMC_INF_MASK; - - /* Set virtual channel CSI2 */ - icnmc |= ICnMC_VCSEL(csi_vc); - - rzg2l_cru_write(cru, ICnSVCNUM, csi_vc); - rzg2l_cru_write(cru, ICnSVC, ICnSVC_SVC0(0) | ICnSVC_SVC1(1) | - ICnSVC_SVC2(2) | ICnSVC_SVC3(3)); - rzg2l_cru_write(cru, info->image_conv, icnmc); -} - -void rzg2l_cru_csi2_setup(struct rzg2l_cru_dev *cru, - const struct rzg2l_cru_ip_format *ip_fmt, - u8 csi_vc) -{ - const struct rzg2l_cru_info *info = cru->info; - u32 icnmc = ICnMC_INF(ip_fmt->datatype); + if (cru->info->regs[ICnSVC]) { + rzg2l_cru_write(cru, ICnSVCNUM, csi_vc); + rzg2l_cru_write(cru, ICnSVC, ICnSVC_SVC0(0) | ICnSVC_SVC1(1) | + ICnSVC_SVC2(2) | ICnSVC_SVC3(3)); + } icnmc |= rzg2l_cru_read(cru, info->image_conv) & ~ICnMC_INF_MASK; @@ -299,7 +287,7 @@ static int rzg2l_cru_initialize_image_conv(struct rzg2l_cru_dev *cru, const struct rzg2l_cru_ip_format *cru_ip_fmt; cru_ip_fmt = rzg2l_cru_ip_code_to_fmt(ip_sd_fmt->code); - info->csi_setup(cru, cru_ip_fmt, csi_vc); + rzg2l_cru_csi2_setup(cru, cru_ip_fmt, csi_vc); /* Output format */ cru_video_fmt = rzg2l_cru_ip_format_to_fmt(cru->format.pixelformat); @@ -1078,7 +1066,6 @@ static int rzg2l_cru_open(struct file *file) if (ret) return ret; - file->private_data = cru; ret = v4l2_fh_open(file); if (ret) goto err_unlock; diff --git a/drivers/media/platform/renesas/vsp1/vsp1_drv.c b/drivers/media/platform/renesas/vsp1/vsp1_drv.c index b8d06e88c475..6c64657fc4f3 100644 --- a/drivers/media/platform/renesas/vsp1/vsp1_drv.c +++ b/drivers/media/platform/renesas/vsp1/vsp1_drv.c @@ -618,7 +618,7 @@ void vsp1_device_put(struct vsp1_device *vsp1) * Power Management */ -static int __maybe_unused vsp1_pm_suspend(struct device *dev) +static int vsp1_pm_suspend(struct device *dev) { struct vsp1_device *vsp1 = dev_get_drvdata(dev); @@ -634,7 +634,7 @@ static int __maybe_unused vsp1_pm_suspend(struct device *dev) return 0; } -static int __maybe_unused vsp1_pm_resume(struct device *dev) +static int vsp1_pm_resume(struct device *dev) { struct vsp1_device *vsp1 = dev_get_drvdata(dev); @@ -650,7 +650,7 @@ static int __maybe_unused vsp1_pm_resume(struct device *dev) return 0; } -static int __maybe_unused vsp1_pm_runtime_suspend(struct device *dev) +static int vsp1_pm_runtime_suspend(struct device *dev) { struct vsp1_device *vsp1 = dev_get_drvdata(dev); @@ -660,7 +660,7 @@ static int __maybe_unused vsp1_pm_runtime_suspend(struct device *dev) return 0; } -static int __maybe_unused vsp1_pm_runtime_resume(struct device *dev) +static int vsp1_pm_runtime_resume(struct device *dev) { struct vsp1_device *vsp1 = dev_get_drvdata(dev); int ret; @@ -693,8 +693,8 @@ done: } static const struct dev_pm_ops vsp1_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(vsp1_pm_suspend, vsp1_pm_resume) - SET_RUNTIME_PM_OPS(vsp1_pm_runtime_suspend, vsp1_pm_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(vsp1_pm_suspend, vsp1_pm_resume) + RUNTIME_PM_OPS(vsp1_pm_runtime_suspend, vsp1_pm_runtime_resume, NULL) }; /* ----------------------------------------------------------------------------- @@ -1042,7 +1042,7 @@ static struct platform_driver vsp1_platform_driver = { .remove = vsp1_remove, .driver = { .name = "vsp1", - .pm = &vsp1_pm_ops, + .pm = pm_ptr(&vsp1_pm_ops), .of_match_table = vsp1_of_match, }, }; diff --git a/drivers/media/platform/renesas/vsp1/vsp1_histo.c b/drivers/media/platform/renesas/vsp1/vsp1_histo.c index c762202877ba..390ea50f1595 100644 --- a/drivers/media/platform/renesas/vsp1/vsp1_histo.c +++ b/drivers/media/platform/renesas/vsp1/vsp1_histo.c @@ -392,7 +392,7 @@ static const struct v4l2_subdev_ops histo_ops = { static int histo_v4l2_querycap(struct file *file, void *fh, struct v4l2_capability *cap) { - struct v4l2_fh *vfh = file->private_data; + struct v4l2_fh *vfh = file_to_v4l2_fh(file); struct vsp1_histogram *histo = vdev_to_histo(vfh->vdev); cap->capabilities = V4L2_CAP_DEVICE_CAPS | V4L2_CAP_STREAMING @@ -409,7 +409,7 @@ static int histo_v4l2_querycap(struct file *file, void *fh, static int histo_v4l2_enum_format(struct file *file, void *fh, struct v4l2_fmtdesc *f) { - struct v4l2_fh *vfh = file->private_data; + struct v4l2_fh *vfh = file_to_v4l2_fh(file); struct vsp1_histogram *histo = vdev_to_histo(vfh->vdev); if (f->index > 0 || f->type != histo->queue.type) @@ -423,7 +423,7 @@ static int histo_v4l2_enum_format(struct file *file, void *fh, static int histo_v4l2_get_format(struct file *file, void *fh, struct v4l2_format *format) { - struct v4l2_fh *vfh = file->private_data; + struct v4l2_fh *vfh = file_to_v4l2_fh(file); struct vsp1_histogram *histo = vdev_to_histo(vfh->vdev); struct v4l2_meta_format *meta = &format->fmt.meta; diff --git a/drivers/media/platform/renesas/vsp1/vsp1_video.c b/drivers/media/platform/renesas/vsp1/vsp1_video.c index bc66fbdde3cc..75f9a1a85d55 100644 --- a/drivers/media/platform/renesas/vsp1/vsp1_video.c +++ b/drivers/media/platform/renesas/vsp1/vsp1_video.c @@ -896,7 +896,7 @@ static const struct vb2_ops vsp1_video_queue_qops = { static int vsp1_video_querycap(struct file *file, void *fh, struct v4l2_capability *cap) { - struct v4l2_fh *vfh = file->private_data; + struct v4l2_fh *vfh = file_to_v4l2_fh(file); struct vsp1_video *video = to_vsp1_video(vfh->vdev); cap->capabilities = V4L2_CAP_DEVICE_CAPS | V4L2_CAP_STREAMING @@ -912,7 +912,7 @@ vsp1_video_querycap(struct file *file, void *fh, struct v4l2_capability *cap) static int vsp1_video_enum_format(struct file *file, void *fh, struct v4l2_fmtdesc *f) { - struct v4l2_fh *vfh = file->private_data; + struct v4l2_fh *vfh = file_to_v4l2_fh(file); struct vsp1_video *video = to_vsp1_video(vfh->vdev); const struct vsp1_format_info *info; @@ -933,7 +933,7 @@ static int vsp1_video_enum_format(struct file *file, void *fh, static int vsp1_video_get_format(struct file *file, void *fh, struct v4l2_format *format) { - struct v4l2_fh *vfh = file->private_data; + struct v4l2_fh *vfh = file_to_v4l2_fh(file); struct vsp1_video *video = to_vsp1_video(vfh->vdev); if (format->type != video->queue.type) @@ -949,7 +949,7 @@ vsp1_video_get_format(struct file *file, void *fh, struct v4l2_format *format) static int vsp1_video_try_format(struct file *file, void *fh, struct v4l2_format *format) { - struct v4l2_fh *vfh = file->private_data; + struct v4l2_fh *vfh = file_to_v4l2_fh(file); struct vsp1_video *video = to_vsp1_video(vfh->vdev); if (format->type != video->queue.type) @@ -961,7 +961,7 @@ vsp1_video_try_format(struct file *file, void *fh, struct v4l2_format *format) static int vsp1_video_set_format(struct file *file, void *fh, struct v4l2_format *format) { - struct v4l2_fh *vfh = file->private_data; + struct v4l2_fh *vfh = file_to_v4l2_fh(file); struct vsp1_video *video = to_vsp1_video(vfh->vdev); const struct vsp1_format_info *info; int ret; @@ -991,7 +991,7 @@ done: static int vsp1_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type) { - struct v4l2_fh *vfh = file->private_data; + struct v4l2_fh *vfh = file_to_v4l2_fh(file); struct vsp1_video *video = to_vsp1_video(vfh->vdev); struct media_device *mdev = &video->vsp1->media_dev; struct vsp1_pipeline *pipe; @@ -1079,13 +1079,11 @@ static int vsp1_video_open(struct file *file) return -ENOMEM; v4l2_fh_init(vfh, &video->video); - v4l2_fh_add(vfh); - - file->private_data = vfh; + v4l2_fh_add(vfh, file); ret = vsp1_device_get(video->vsp1); if (ret < 0) { - v4l2_fh_del(vfh); + v4l2_fh_del(vfh, file); v4l2_fh_exit(vfh); kfree(vfh); } diff --git a/drivers/media/platform/renesas/vsp1/vsp1_vspx.c b/drivers/media/platform/renesas/vsp1/vsp1_vspx.c index a754b92232bd..1673479be0ff 100644 --- a/drivers/media/platform/renesas/vsp1/vsp1_vspx.c +++ b/drivers/media/platform/renesas/vsp1/vsp1_vspx.c @@ -286,6 +286,7 @@ void vsp1_isp_free_buffer(struct device *dev, dma_free_coherent(bus_master, buffer_desc->size, buffer_desc->cpu_addr, buffer_desc->dma_addr); } +EXPORT_SYMBOL_GPL(vsp1_isp_free_buffer); /** * vsp1_isp_start_streaming - Start processing VSPX jobs diff --git a/drivers/media/platform/rockchip/rga/rga.c b/drivers/media/platform/rockchip/rga/rga.c index 3dccab5fa4a1..776046de979a 100644 --- a/drivers/media/platform/rockchip/rga/rga.c +++ b/drivers/media/platform/rockchip/rga/rga.c @@ -395,8 +395,7 @@ static int rga_open(struct file *file) return ret; } v4l2_fh_init(&ctx->fh, video_devdata(file)); - file->private_data = &ctx->fh; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); rga_setup_ctrls(ctx); @@ -411,8 +410,7 @@ static int rga_open(struct file *file) static int rga_release(struct file *file) { - struct rga_ctx *ctx = - container_of(file->private_data, struct rga_ctx, fh); + struct rga_ctx *ctx = file_to_rga_ctx(file); struct rockchip_rga *rga = ctx->rga; mutex_lock(&rga->mutex); @@ -420,7 +418,7 @@ static int rga_release(struct file *file) v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); v4l2_ctrl_handler_free(&ctx->ctrl_handler); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); kfree(ctx); @@ -448,7 +446,7 @@ vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) return 0; } -static int vidioc_enum_fmt(struct file *file, void *prv, struct v4l2_fmtdesc *f) +static int vidioc_enum_fmt(struct file *file, void *priv, struct v4l2_fmtdesc *f) { struct rga_fmt *fmt; @@ -461,10 +459,10 @@ static int vidioc_enum_fmt(struct file *file, void *prv, struct v4l2_fmtdesc *f) return 0; } -static int vidioc_g_fmt(struct file *file, void *prv, struct v4l2_format *f) +static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f) { struct v4l2_pix_format_mplane *pix_fmt = &f->fmt.pix_mp; - struct rga_ctx *ctx = prv; + struct rga_ctx *ctx = file_to_rga_ctx(file); struct vb2_queue *vq; struct rga_frame *frm; @@ -483,7 +481,7 @@ static int vidioc_g_fmt(struct file *file, void *prv, struct v4l2_format *f) return 0; } -static int vidioc_try_fmt(struct file *file, void *prv, struct v4l2_format *f) +static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f) { struct v4l2_pix_format_mplane *pix_fmt = &f->fmt.pix_mp; struct rga_fmt *fmt; @@ -503,10 +501,10 @@ static int vidioc_try_fmt(struct file *file, void *prv, struct v4l2_format *f) return 0; } -static int vidioc_s_fmt(struct file *file, void *prv, struct v4l2_format *f) +static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f) { struct v4l2_pix_format_mplane *pix_fmt = &f->fmt.pix_mp; - struct rga_ctx *ctx = prv; + struct rga_ctx *ctx = file_to_rga_ctx(file); struct rockchip_rga *rga = ctx->rga; struct vb2_queue *vq; struct rga_frame *frm; @@ -516,7 +514,7 @@ static int vidioc_s_fmt(struct file *file, void *prv, struct v4l2_format *f) /* Adjust all values accordingly to the hardware capabilities * and chosen format. */ - ret = vidioc_try_fmt(file, prv, f); + ret = vidioc_try_fmt(file, priv, f); if (ret) return ret; vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); @@ -560,10 +558,10 @@ static int vidioc_s_fmt(struct file *file, void *prv, struct v4l2_format *f) return 0; } -static int vidioc_g_selection(struct file *file, void *prv, +static int vidioc_g_selection(struct file *file, void *priv, struct v4l2_selection *s) { - struct rga_ctx *ctx = prv; + struct rga_ctx *ctx = file_to_rga_ctx(file); struct rga_frame *f; bool use_frame = false; @@ -608,10 +606,10 @@ static int vidioc_g_selection(struct file *file, void *prv, return 0; } -static int vidioc_s_selection(struct file *file, void *prv, +static int vidioc_s_selection(struct file *file, void *priv, struct v4l2_selection *s) { - struct rga_ctx *ctx = prv; + struct rga_ctx *ctx = file_to_rga_ctx(file); struct rockchip_rga *rga = ctx->rga; struct rga_frame *f; int ret = 0; diff --git a/drivers/media/platform/rockchip/rga/rga.h b/drivers/media/platform/rockchip/rga/rga.h index 530e12de73c4..72a28b120fab 100644 --- a/drivers/media/platform/rockchip/rga/rga.h +++ b/drivers/media/platform/rockchip/rga/rga.h @@ -68,6 +68,11 @@ struct rga_ctx { u32 fill_color; }; +static inline struct rga_ctx *file_to_rga_ctx(struct file *filp) +{ + return container_of(file_to_v4l2_fh(filp), struct rga_ctx, fh); +} + struct rockchip_rga { struct v4l2_device v4l2_dev; struct v4l2_m2m_dev *m2m_dev; diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h index 5f187f9efc7b..6028ecdd23de 100644 --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h @@ -24,6 +24,7 @@ #include "rkisp1-regs.h" struct dentry; +struct dev_pm_domain_list; struct regmap; /* @@ -55,7 +56,7 @@ struct regmap; #define RKISP1_BUS_INFO "platform:" RKISP1_DRIVER_NAME /* maximum number of clocks */ -#define RKISP1_MAX_BUS_CLK 8 +#define RKISP1_MAX_BUS_CLK 4 /* a bitmask of the ready stats */ #define RKISP1_STATS_MEAS_MASK (RKISP1_CIF_ISP_AWB_DONE | \ @@ -139,27 +140,31 @@ enum rkisp1_feature { /* * struct rkisp1_info - Model-specific ISP Information * - * @clks: array of ISP clock names - * @clk_size: number of entries in the @clks array + * @num_clocks: number of clocks * @isrs: array of ISP interrupt descriptors * @isr_size: number of entries in the @isrs array * @isp_ver: ISP version * @features: bitmask of rkisp1_feature features implemented by the ISP * @max_width: maximum input frame width * @max_height: maximum input frame height + * @pm_domains.names: name of the power domains + * @pm_domains.count: number of power domains * * This structure contains information about the ISP specific to a particular * ISP model, version, or integration in a particular SoC. */ struct rkisp1_info { - const char * const *clks; - unsigned int clk_size; + unsigned int num_clocks; const struct rkisp1_isr_data *isrs; unsigned int isr_size; enum rkisp1_cif_isp_version isp_ver; unsigned int features; unsigned int max_width; unsigned int max_height; + struct { + const char * const *names; + unsigned int count; + } pm_domains; }; /* @@ -483,6 +488,7 @@ struct rkisp1_debug { * @dev: a pointer to the struct device * @clk_size: number of clocks * @clks: array of clocks + * @pm_domains: power domains * @gasket: the gasket - i.MX8MP only * @gasket_id: the gasket ID (0 or 1) - i.MX8MP only * @v4l2_dev: v4l2_device variable @@ -507,6 +513,7 @@ struct rkisp1_device { struct device *dev; unsigned int clk_size; struct clk_bulk_data clks[RKISP1_MAX_BUS_CLK]; + struct dev_pm_domain_list *pm_domains; struct regmap *gasket; unsigned int gasket_id; struct v4l2_device v4l2_dev; diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c index dc65a7924f8a..1791c02a40ae 100644 --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c @@ -8,6 +8,7 @@ * Copyright (C) 2017 Rockchip Electronics Co., Ltd. */ +#include <linux/build_bug.h> #include <linux/clk.h> #include <linux/interrupt.h> #include <linux/mfd/syscon.h> @@ -16,6 +17,7 @@ #include <linux/of_graph.h> #include <linux/platform_device.h> #include <linux/pinctrl/consumer.h> +#include <linux/pm_domain.h> #include <linux/pm_runtime.h> #include <media/v4l2-fwnode.h> #include <media/v4l2-mc.h> @@ -491,13 +493,6 @@ static irqreturn_t rkisp1_isr(int irq, void *ctx) return ret; } -static const char * const px30_isp_clks[] = { - "isp", - "aclk", - "hclk", - "pclk", -}; - static const struct rkisp1_isr_data px30_isp_isrs[] = { { "isp", rkisp1_isp_isr, BIT(RKISP1_IRQ_ISP) }, { "mi", rkisp1_capture_isr, BIT(RKISP1_IRQ_MI) }, @@ -505,8 +500,7 @@ static const struct rkisp1_isr_data px30_isp_isrs[] = { }; static const struct rkisp1_info px30_isp_info = { - .clks = px30_isp_clks, - .clk_size = ARRAY_SIZE(px30_isp_clks), + .num_clocks = 4, .isrs = px30_isp_isrs, .isr_size = ARRAY_SIZE(px30_isp_isrs), .isp_ver = RKISP1_V12, @@ -518,19 +512,12 @@ static const struct rkisp1_info px30_isp_info = { .max_height = 2448, }; -static const char * const rk3399_isp_clks[] = { - "isp", - "aclk", - "hclk", -}; - static const struct rkisp1_isr_data rk3399_isp_isrs[] = { { NULL, rkisp1_isr, BIT(RKISP1_IRQ_ISP) | BIT(RKISP1_IRQ_MI) | BIT(RKISP1_IRQ_MIPI) }, }; static const struct rkisp1_info rk3399_isp_info = { - .clks = rk3399_isp_clks, - .clk_size = ARRAY_SIZE(rk3399_isp_clks), + .num_clocks = 3, .isrs = rk3399_isp_isrs, .isr_size = ARRAY_SIZE(rk3399_isp_isrs), .isp_ver = RKISP1_V10, @@ -542,19 +529,17 @@ static const struct rkisp1_info rk3399_isp_info = { .max_height = 3312, }; -static const char * const imx8mp_isp_clks[] = { - "isp", - "hclk", - "aclk", -}; - static const struct rkisp1_isr_data imx8mp_isp_isrs[] = { { NULL, rkisp1_isr, BIT(RKISP1_IRQ_ISP) | BIT(RKISP1_IRQ_MI) }, }; +static const char * const imx8mp_isp_pm_domains[] = { + "isp", + "csi2", +}; + static const struct rkisp1_info imx8mp_isp_info = { - .clks = imx8mp_isp_clks, - .clk_size = ARRAY_SIZE(imx8mp_isp_clks), + .num_clocks = 3, .isrs = imx8mp_isp_isrs, .isr_size = ARRAY_SIZE(imx8mp_isp_isrs), .isp_ver = RKISP1_V_IMX8MP, @@ -563,6 +548,10 @@ static const struct rkisp1_info imx8mp_isp_info = { | RKISP1_FEATURE_COMPAND, .max_width = 4096, .max_height = 3072, + .pm_domains = { + .names = imx8mp_isp_pm_domains, + .count = ARRAY_SIZE(imx8mp_isp_pm_domains), + }, }; static const struct of_device_id rkisp1_of_match[] = { @@ -582,6 +571,81 @@ static const struct of_device_id rkisp1_of_match[] = { }; MODULE_DEVICE_TABLE(of, rkisp1_of_match); +static const char * const rkisp1_clk_names[] = { + "isp", + "aclk", + "hclk", + "pclk", +}; + +static int rkisp1_init_clocks(struct rkisp1_device *rkisp1) +{ + const struct rkisp1_info *info = rkisp1->info; + unsigned int i; + int ret; + + static_assert(ARRAY_SIZE(rkisp1_clk_names) == ARRAY_SIZE(rkisp1->clks)); + + for (i = 0; i < info->num_clocks; i++) + rkisp1->clks[i].id = rkisp1_clk_names[i]; + + ret = devm_clk_bulk_get(rkisp1->dev, info->num_clocks, rkisp1->clks); + if (ret) + return ret; + + rkisp1->clk_size = info->num_clocks; + + /* + * On i.MX8MP the pclk clock is needed to access the HDR stitching + * registers, but wasn't required by DT bindings. Try to acquire it as + * an optional clock to avoid breaking backward compatibility. + */ + if (info->isp_ver == RKISP1_V_IMX8MP) { + struct clk *clk; + + clk = devm_clk_get_optional(rkisp1->dev, "pclk"); + if (IS_ERR(clk)) + return dev_err_probe(rkisp1->dev, PTR_ERR(clk), + "Failed to acquire pclk clock\n"); + + if (clk) + rkisp1->clks[rkisp1->clk_size++].clk = clk; + } + + return 0; +} + +static int rkisp1_init_pm_domains(struct rkisp1_device *rkisp1) +{ + const struct rkisp1_info *info = rkisp1->info; + struct dev_pm_domain_attach_data pm_domain_data = { + .pd_names = info->pm_domains.names, + .num_pd_names = info->pm_domains.count, + }; + int ret; + + /* + * Most platforms have a single power domain, which the PM domain core + * automatically attaches at probe time. When that's the case there's + * nothing to do here. + */ + if (rkisp1->dev->pm_domain) + return 0; + + if (!pm_domain_data.num_pd_names) + return 0; + + ret = devm_pm_domain_attach_list(rkisp1->dev, &pm_domain_data, + &rkisp1->pm_domains); + if (ret < 0) { + dev_err_probe(rkisp1->dev, ret, + "Failed to attach power domains\n"); + return ret; + } + + return 0; +} + static int rkisp1_probe(struct platform_device *pdev) { const struct rkisp1_info *info; @@ -639,12 +703,13 @@ static int rkisp1_probe(struct platform_device *pdev) } } - for (i = 0; i < info->clk_size; i++) - rkisp1->clks[i].id = info->clks[i]; - ret = devm_clk_bulk_get(dev, info->clk_size, rkisp1->clks); + ret = rkisp1_init_clocks(rkisp1); + if (ret) + return ret; + + ret = rkisp1_init_pm_domains(rkisp1); if (ret) return ret; - rkisp1->clk_size = info->clk_size; if (info->isp_ver == RKISP1_V_IMX8MP) { unsigned int id; diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec.c b/drivers/media/platform/rockchip/rkvdec/rkvdec.c index d3b31f461194..6e606d73ff51 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec.c +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec.c @@ -354,7 +354,7 @@ static int rkvdec_try_capture_fmt(struct file *file, void *priv, struct v4l2_format *f) { struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; - struct rkvdec_ctx *ctx = fh_to_rkvdec_ctx(priv); + struct rkvdec_ctx *ctx = file_to_rkvdec_ctx(file); const struct rkvdec_coded_fmt_desc *coded_desc; /* @@ -387,7 +387,7 @@ static int rkvdec_try_output_fmt(struct file *file, void *priv, struct v4l2_format *f) { struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; - struct rkvdec_ctx *ctx = fh_to_rkvdec_ctx(priv); + struct rkvdec_ctx *ctx = file_to_rkvdec_ctx(file); const struct rkvdec_coded_fmt_desc *desc; desc = rkvdec_find_coded_fmt_desc(pix_mp->pixelformat); @@ -418,7 +418,7 @@ static int rkvdec_try_output_fmt(struct file *file, void *priv, 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 rkvdec_ctx *ctx = file_to_rkvdec_ctx(file); struct vb2_queue *vq; int ret; @@ -439,7 +439,7 @@ static int rkvdec_s_capture_fmt(struct file *file, void *priv, static int rkvdec_s_output_fmt(struct file *file, void *priv, struct v4l2_format *f) { - struct rkvdec_ctx *ctx = fh_to_rkvdec_ctx(priv); + struct rkvdec_ctx *ctx = file_to_rkvdec_ctx(file); struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx; const struct rkvdec_coded_fmt_desc *desc; struct v4l2_format *cap_fmt; @@ -504,7 +504,7 @@ static int rkvdec_s_output_fmt(struct file *file, void *priv, static int rkvdec_g_output_fmt(struct file *file, void *priv, struct v4l2_format *f) { - struct rkvdec_ctx *ctx = fh_to_rkvdec_ctx(priv); + struct rkvdec_ctx *ctx = file_to_rkvdec_ctx(file); *f = ctx->coded_fmt; return 0; @@ -513,7 +513,7 @@ static int rkvdec_g_output_fmt(struct file *file, void *priv, static int rkvdec_g_capture_fmt(struct file *file, void *priv, struct v4l2_format *f) { - struct rkvdec_ctx *ctx = fh_to_rkvdec_ctx(priv); + struct rkvdec_ctx *ctx = file_to_rkvdec_ctx(file); *f = ctx->decoded_fmt; return 0; @@ -532,7 +532,7 @@ static int rkvdec_enum_output_fmt(struct file *file, void *priv, static int rkvdec_enum_capture_fmt(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - struct rkvdec_ctx *ctx = fh_to_rkvdec_ctx(priv); + struct rkvdec_ctx *ctx = file_to_rkvdec_ctx(file); u32 fourcc; fourcc = rkvdec_enum_decoded_fmt(ctx, f->index, ctx->image_fmt); @@ -937,8 +937,7 @@ static int rkvdec_open(struct file *filp) if (ret) goto err_cleanup_m2m_ctx; - filp->private_data = &ctx->fh; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, filp); return 0; @@ -952,9 +951,9 @@ err_free_ctx: static int rkvdec_release(struct file *filp) { - struct rkvdec_ctx *ctx = fh_to_rkvdec_ctx(filp->private_data); + struct rkvdec_ctx *ctx = file_to_rkvdec_ctx(filp); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, filp); v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); v4l2_ctrl_handler_free(&ctx->ctrl_hdl); v4l2_fh_exit(&ctx->fh); diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec.h b/drivers/media/platform/rockchip/rkvdec/rkvdec.h index f6e8bf38add3..481aaa4bffe9 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec.h +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec.h @@ -124,9 +124,9 @@ struct rkvdec_ctx { void *priv; }; -static inline struct rkvdec_ctx *fh_to_rkvdec_ctx(struct v4l2_fh *fh) +static inline struct rkvdec_ctx *file_to_rkvdec_ctx(struct file *filp) { - return container_of(fh, struct rkvdec_ctx, fh); + return container_of(file_to_v4l2_fh(filp), struct rkvdec_ctx, fh); } struct rkvdec_aux_buf { diff --git a/drivers/media/platform/samsung/exynos-gsc/gsc-core.h b/drivers/media/platform/samsung/exynos-gsc/gsc-core.h index b9777e07fb6d..265221abf4dc 100644 --- a/drivers/media/platform/samsung/exynos-gsc/gsc-core.h +++ b/drivers/media/platform/samsung/exynos-gsc/gsc-core.h @@ -85,7 +85,6 @@ enum gsc_yuv_fmt { GSC_CRCB, }; -#define fh_to_ctx(__fh) container_of(__fh, struct gsc_ctx, fh) #define is_rgb(x) (!!((x) & 0x1)) #define is_yuv420(x) (!!((x) & 0x2)) #define is_yuv422(x) (!!((x) & 0x4)) @@ -381,6 +380,11 @@ struct gsc_ctx { enum v4l2_colorspace out_colorspace; }; +static inline struct gsc_ctx *file_to_ctx(struct file *filp) +{ + return container_of(file_to_v4l2_fh(filp), struct gsc_ctx, fh); +} + void gsc_set_prefbuf(struct gsc_dev *gsc, struct gsc_frame *frm); int gsc_register_m2m_device(struct gsc_dev *gsc); void gsc_unregister_m2m_device(struct gsc_dev *gsc); diff --git a/drivers/media/platform/samsung/exynos-gsc/gsc-m2m.c b/drivers/media/platform/samsung/exynos-gsc/gsc-m2m.c index 4bda1c369c44..722e2531e23f 100644 --- a/drivers/media/platform/samsung/exynos-gsc/gsc-m2m.c +++ b/drivers/media/platform/samsung/exynos-gsc/gsc-m2m.c @@ -297,7 +297,7 @@ static int gsc_m2m_enum_fmt(struct file *file, void *priv, static int gsc_m2m_g_fmt_mplane(struct file *file, void *fh, struct v4l2_format *f) { - struct gsc_ctx *ctx = fh_to_ctx(fh); + struct gsc_ctx *ctx = file_to_ctx(file); return gsc_g_fmt_mplane(ctx, f); } @@ -305,7 +305,7 @@ static int gsc_m2m_g_fmt_mplane(struct file *file, void *fh, static int gsc_m2m_try_fmt_mplane(struct file *file, void *fh, struct v4l2_format *f) { - struct gsc_ctx *ctx = fh_to_ctx(fh); + struct gsc_ctx *ctx = file_to_ctx(file); return gsc_try_fmt_mplane(ctx, f); } @@ -313,7 +313,7 @@ static int gsc_m2m_try_fmt_mplane(struct file *file, void *fh, static int gsc_m2m_s_fmt_mplane(struct file *file, void *fh, struct v4l2_format *f) { - struct gsc_ctx *ctx = fh_to_ctx(fh); + struct gsc_ctx *ctx = file_to_ctx(file); struct vb2_queue *vq; struct gsc_frame *frame; struct v4l2_pix_format_mplane *pix; @@ -359,7 +359,7 @@ static int gsc_m2m_s_fmt_mplane(struct file *file, void *fh, static int gsc_m2m_reqbufs(struct file *file, void *fh, struct v4l2_requestbuffers *reqbufs) { - struct gsc_ctx *ctx = fh_to_ctx(fh); + struct gsc_ctx *ctx = file_to_ctx(file); struct gsc_dev *gsc = ctx->gsc_dev; u32 max_cnt; @@ -374,35 +374,35 @@ static int gsc_m2m_reqbufs(struct file *file, void *fh, static int gsc_m2m_expbuf(struct file *file, void *fh, struct v4l2_exportbuffer *eb) { - struct gsc_ctx *ctx = fh_to_ctx(fh); + struct gsc_ctx *ctx = file_to_ctx(file); return v4l2_m2m_expbuf(file, ctx->m2m_ctx, eb); } static int gsc_m2m_querybuf(struct file *file, void *fh, struct v4l2_buffer *buf) { - struct gsc_ctx *ctx = fh_to_ctx(fh); + struct gsc_ctx *ctx = file_to_ctx(file); return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf); } static int gsc_m2m_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf) { - struct gsc_ctx *ctx = fh_to_ctx(fh); + struct gsc_ctx *ctx = file_to_ctx(file); return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf); } static int gsc_m2m_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf) { - struct gsc_ctx *ctx = fh_to_ctx(fh); + struct gsc_ctx *ctx = file_to_ctx(file); return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf); } static int gsc_m2m_streamon(struct file *file, void *fh, enum v4l2_buf_type type) { - struct gsc_ctx *ctx = fh_to_ctx(fh); + struct gsc_ctx *ctx = file_to_ctx(file); /* The source and target color format need to be set */ if (V4L2_TYPE_IS_OUTPUT(type)) { @@ -418,7 +418,7 @@ static int gsc_m2m_streamon(struct file *file, void *fh, static int gsc_m2m_streamoff(struct file *file, void *fh, enum v4l2_buf_type type) { - struct gsc_ctx *ctx = fh_to_ctx(fh); + struct gsc_ctx *ctx = file_to_ctx(file); return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type); } @@ -440,8 +440,8 @@ static int is_rectangle_enclosed(struct v4l2_rect *a, struct v4l2_rect *b) static int gsc_m2m_g_selection(struct file *file, void *fh, struct v4l2_selection *s) { + struct gsc_ctx *ctx = file_to_ctx(file); struct gsc_frame *frame; - struct gsc_ctx *ctx = fh_to_ctx(fh); if ((s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) && (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)) @@ -478,7 +478,7 @@ static int gsc_m2m_s_selection(struct file *file, void *fh, struct v4l2_selection *s) { struct gsc_frame *frame; - struct gsc_ctx *ctx = fh_to_ctx(fh); + struct gsc_ctx *ctx = file_to_ctx(file); struct gsc_variant *variant = ctx->gsc_dev->variant; struct v4l2_selection sel = *s; int ret; @@ -625,8 +625,7 @@ static int gsc_m2m_open(struct file *file) /* Use separate control handler per file handle */ ctx->fh.ctrl_handler = &ctx->ctrl_handler; - file->private_data = &ctx->fh; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); ctx->gsc_dev = gsc; /* Default color format */ @@ -655,7 +654,7 @@ static int gsc_m2m_open(struct file *file) error_ctrls: gsc_ctrls_delete(ctx); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); error_fh: v4l2_fh_exit(&ctx->fh); kfree(ctx); @@ -666,7 +665,7 @@ unlock: static int gsc_m2m_release(struct file *file) { - struct gsc_ctx *ctx = fh_to_ctx(file->private_data); + struct gsc_ctx *ctx = file_to_ctx(file); struct gsc_dev *gsc = ctx->gsc_dev; pr_debug("pid: %d, state: 0x%lx, refcnt= %d", @@ -676,7 +675,7 @@ static int gsc_m2m_release(struct file *file) v4l2_m2m_ctx_release(ctx->m2m_ctx); gsc_ctrls_delete(ctx); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); if (--gsc->m2m.refcnt <= 0) @@ -690,7 +689,7 @@ static int gsc_m2m_release(struct file *file) static __poll_t gsc_m2m_poll(struct file *file, struct poll_table_struct *wait) { - struct gsc_ctx *ctx = fh_to_ctx(file->private_data); + struct gsc_ctx *ctx = file_to_ctx(file); struct gsc_dev *gsc = ctx->gsc_dev; __poll_t ret; @@ -705,7 +704,7 @@ static __poll_t gsc_m2m_poll(struct file *file, static int gsc_m2m_mmap(struct file *file, struct vm_area_struct *vma) { - struct gsc_ctx *ctx = fh_to_ctx(file->private_data); + struct gsc_ctx *ctx = file_to_ctx(file); struct gsc_dev *gsc = ctx->gsc_dev; int ret; diff --git a/drivers/media/platform/samsung/exynos4-is/fimc-core.h b/drivers/media/platform/samsung/exynos4-is/fimc-core.h index 63385152a2ff..c23cbdee7afc 100644 --- a/drivers/media/platform/samsung/exynos4-is/fimc-core.h +++ b/drivers/media/platform/samsung/exynos4-is/fimc-core.h @@ -496,7 +496,10 @@ struct fimc_ctx { struct fimc_ctrls ctrls; }; -#define fh_to_ctx(__fh) container_of(__fh, struct fimc_ctx, fh) +static inline struct fimc_ctx *file_to_ctx(struct file *filp) +{ + return container_of(file_to_v4l2_fh(filp), struct fimc_ctx, fh); +} static inline void set_frame_bounds(struct fimc_frame *f, u32 width, u32 height) { diff --git a/drivers/media/platform/samsung/exynos4-is/fimc-m2m.c b/drivers/media/platform/samsung/exynos4-is/fimc-m2m.c index 951433c8e92a..562c57f186c6 100644 --- a/drivers/media/platform/samsung/exynos4-is/fimc-m2m.c +++ b/drivers/media/platform/samsung/exynos4-is/fimc-m2m.c @@ -249,7 +249,7 @@ static int fimc_m2m_enum_fmt(struct file *file, void *priv, static int fimc_m2m_g_fmt_mplane(struct file *file, void *fh, struct v4l2_format *f) { - struct fimc_ctx *ctx = fh_to_ctx(fh); + struct fimc_ctx *ctx = file_to_ctx(file); const struct fimc_frame *frame = ctx_get_frame(ctx, f->type); if (IS_ERR(frame)) @@ -308,7 +308,7 @@ static int fimc_try_fmt_mplane(struct fimc_ctx *ctx, struct v4l2_format *f) static int fimc_m2m_try_fmt_mplane(struct file *file, void *fh, struct v4l2_format *f) { - struct fimc_ctx *ctx = fh_to_ctx(fh); + struct fimc_ctx *ctx = file_to_ctx(file); return fimc_try_fmt_mplane(ctx, f); } @@ -337,7 +337,7 @@ static void __set_frame_format(struct fimc_frame *frame, static int fimc_m2m_s_fmt_mplane(struct file *file, void *fh, struct v4l2_format *f) { - struct fimc_ctx *ctx = fh_to_ctx(fh); + struct fimc_ctx *ctx = file_to_ctx(file); struct fimc_dev *fimc = ctx->fimc_dev; const struct fimc_fmt *fmt; struct vb2_queue *vq; @@ -376,7 +376,7 @@ static int fimc_m2m_s_fmt_mplane(struct file *file, void *fh, static int fimc_m2m_g_selection(struct file *file, void *fh, struct v4l2_selection *s) { - struct fimc_ctx *ctx = fh_to_ctx(fh); + struct fimc_ctx *ctx = file_to_ctx(file); const struct fimc_frame *frame; frame = ctx_get_frame(ctx, s->type); @@ -484,7 +484,7 @@ static int fimc_m2m_try_selection(struct fimc_ctx *ctx, static int fimc_m2m_s_selection(struct file *file, void *fh, struct v4l2_selection *s) { - struct fimc_ctx *ctx = fh_to_ctx(fh); + struct fimc_ctx *ctx = file_to_ctx(file); struct fimc_dev *fimc = ctx->fimc_dev; struct fimc_frame *f; int ret; @@ -634,8 +634,7 @@ static int fimc_m2m_open(struct file *file) /* Use separate control handler per file handle */ ctx->fh.ctrl_handler = &ctx->ctrls.handler; - file->private_data = &ctx->fh; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); /* Setup the device context for memory-to-memory mode */ ctx->state = FIMC_CTX_M2M; @@ -664,7 +663,7 @@ error_m2m_ctx: v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); error_c: fimc_ctrls_delete(ctx); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); error_fh: v4l2_fh_exit(&ctx->fh); kfree(ctx); @@ -675,7 +674,7 @@ unlock: static int fimc_m2m_release(struct file *file) { - struct fimc_ctx *ctx = fh_to_ctx(file->private_data); + struct fimc_ctx *ctx = file_to_ctx(file); struct fimc_dev *fimc = ctx->fimc_dev; dbg("pid: %d, state: 0x%lx, refcnt= %d", @@ -685,7 +684,7 @@ static int fimc_m2m_release(struct file *file) v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); fimc_ctrls_delete(ctx); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); if (--fimc->m2m.refcnt <= 0) diff --git a/drivers/media/platform/samsung/s3c-camif/camif-capture.c b/drivers/media/platform/samsung/s3c-camif/camif-capture.c index 3e566b65f417..ed1a1d693293 100644 --- a/drivers/media/platform/samsung/s3c-camif/camif-capture.c +++ b/drivers/media/platform/samsung/s3c-camif/camif-capture.c @@ -572,7 +572,7 @@ static int s3c_camif_close(struct file *file) mutex_lock(&camif->lock); - if (vp->owner == file->private_data) { + if (vp->owner == file_to_v4l2_fh(file)) { camif_stop_capture(vp); vb2_queue_release(&vp->vb_queue); vp->owner = NULL; @@ -595,7 +595,7 @@ static __poll_t s3c_camif_poll(struct file *file, __poll_t ret; mutex_lock(&camif->lock); - if (vp->owner && vp->owner != file->private_data) + if (vp->owner && vp->owner != file_to_v4l2_fh(file)) ret = EPOLLERR; else ret = vb2_poll(&vp->vb_queue, file, wait); @@ -609,7 +609,7 @@ static int s3c_camif_mmap(struct file *file, struct vm_area_struct *vma) struct camif_vp *vp = video_drvdata(file); int ret; - if (vp->owner && vp->owner != file->private_data) + if (vp->owner && vp->owner != file_to_v4l2_fh(file)) ret = -EBUSY; else ret = vb2_mmap(&vp->vb_queue, vma); @@ -791,7 +791,7 @@ static int s3c_camif_vidioc_s_fmt(struct file *file, void *priv, out_frame->rect.top = 0; if (vp->owner == NULL) - vp->owner = priv; + vp->owner = file_to_v4l2_fh(file); pr_debug("%ux%u. payload: %u. fmt: 0x%08x. %d %d. sizeimage: %d. bpl: %d\n", out_frame->f_width, out_frame->f_height, vp->payload, @@ -841,7 +841,7 @@ static int s3c_camif_streamon(struct file *file, void *priv, if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - if (vp->owner && vp->owner != priv) + if (vp->owner && vp->owner != file_to_v4l2_fh(file)) return -EBUSY; if (s3c_vp_active(vp)) @@ -872,7 +872,7 @@ static int s3c_camif_streamoff(struct file *file, void *priv, if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - if (vp->owner && vp->owner != priv) + if (vp->owner && vp->owner != file_to_v4l2_fh(file)) return -EBUSY; ret = vb2_streamoff(&vp->vb_queue, type); @@ -888,9 +888,9 @@ static int s3c_camif_reqbufs(struct file *file, void *priv, int ret; pr_debug("[vp%d] rb count: %d, owner: %p, priv: %p\n", - vp->id, rb->count, vp->owner, priv); + vp->id, rb->count, vp->owner, file_to_v4l2_fh(file)); - if (vp->owner && vp->owner != priv) + if (vp->owner && vp->owner != file_to_v4l2_fh(file)) return -EBUSY; if (rb->count) @@ -910,7 +910,7 @@ static int s3c_camif_reqbufs(struct file *file, void *priv, vp->reqbufs_count = rb->count; if (vp->owner == NULL && rb->count > 0) - vp->owner = priv; + vp->owner = file_to_v4l2_fh(file); return ret; } @@ -929,7 +929,7 @@ static int s3c_camif_qbuf(struct file *file, void *priv, pr_debug("[vp%d]\n", vp->id); - if (vp->owner && vp->owner != priv) + if (vp->owner && vp->owner != file_to_v4l2_fh(file)) return -EBUSY; return vb2_qbuf(&vp->vb_queue, vp->vdev.v4l2_dev->mdev, buf); @@ -942,7 +942,7 @@ static int s3c_camif_dqbuf(struct file *file, void *priv, pr_debug("[vp%d] sequence: %d\n", vp->id, vp->frame_sequence); - if (vp->owner && vp->owner != priv) + if (vp->owner && vp->owner != file_to_v4l2_fh(file)) return -EBUSY; return vb2_dqbuf(&vp->vb_queue, buf, file->f_flags & O_NONBLOCK); @@ -954,14 +954,14 @@ static int s3c_camif_create_bufs(struct file *file, void *priv, struct camif_vp *vp = video_drvdata(file); int ret; - if (vp->owner && vp->owner != priv) + if (vp->owner && vp->owner != file_to_v4l2_fh(file)) return -EBUSY; create->count = max_t(u32, 1, create->count); ret = vb2_create_bufs(&vp->vb_queue, create); if (!ret && vp->owner == NULL) - vp->owner = priv; + vp->owner = file_to_v4l2_fh(file); return ret; } diff --git a/drivers/media/platform/samsung/s5p-g2d/g2d.c b/drivers/media/platform/samsung/s5p-g2d/g2d.c index ffed16a34493..ffb9bee6cb9d 100644 --- a/drivers/media/platform/samsung/s5p-g2d/g2d.c +++ b/drivers/media/platform/samsung/s5p-g2d/g2d.c @@ -25,7 +25,10 @@ #include "g2d.h" #include "g2d-regs.h" -#define fh2ctx(__fh) container_of(__fh, struct g2d_ctx, fh) +static inline struct g2d_ctx *file2ctx(struct file *filp) +{ + return container_of(file_to_v4l2_fh(filp), struct g2d_ctx, fh); +} static struct g2d_fmt formats[] = { { @@ -254,8 +257,7 @@ static int g2d_open(struct file *file) return ret; } v4l2_fh_init(&ctx->fh, video_devdata(file)); - file->private_data = &ctx->fh; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); g2d_setup_ctrls(ctx); @@ -272,13 +274,13 @@ static int g2d_open(struct file *file) static int g2d_release(struct file *file) { struct g2d_dev *dev = video_drvdata(file); - struct g2d_ctx *ctx = fh2ctx(file->private_data); + struct g2d_ctx *ctx = file2ctx(file); mutex_lock(&dev->mutex); v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); mutex_unlock(&dev->mutex); v4l2_ctrl_handler_free(&ctx->ctrl_handler); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); kfree(ctx); v4l2_info(&dev->v4l2_dev, "instance closed\n"); @@ -295,7 +297,7 @@ static int vidioc_querycap(struct file *file, void *priv, return 0; } -static int vidioc_enum_fmt(struct file *file, void *prv, struct v4l2_fmtdesc *f) +static int vidioc_enum_fmt(struct file *file, void *priv, struct v4l2_fmtdesc *f) { if (f->index >= NUM_FORMATS) return -EINVAL; @@ -303,9 +305,9 @@ static int vidioc_enum_fmt(struct file *file, void *prv, struct v4l2_fmtdesc *f) return 0; } -static int vidioc_g_fmt(struct file *file, void *prv, struct v4l2_format *f) +static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f) { - struct g2d_ctx *ctx = prv; + struct g2d_ctx *ctx = file2ctx(file); struct vb2_queue *vq; struct g2d_frame *frm; @@ -325,7 +327,7 @@ static int vidioc_g_fmt(struct file *file, void *prv, struct v4l2_format *f) return 0; } -static int vidioc_try_fmt(struct file *file, void *prv, struct v4l2_format *f) +static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f) { struct g2d_fmt *fmt; enum v4l2_field *field; @@ -355,9 +357,9 @@ static int vidioc_try_fmt(struct file *file, void *prv, struct v4l2_format *f) return 0; } -static int vidioc_s_fmt(struct file *file, void *prv, struct v4l2_format *f) +static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f) { - struct g2d_ctx *ctx = prv; + struct g2d_ctx *ctx = file2ctx(file); struct g2d_dev *dev = ctx->dev; struct vb2_queue *vq; struct g2d_frame *frm; @@ -366,7 +368,7 @@ static int vidioc_s_fmt(struct file *file, void *prv, struct v4l2_format *f) /* Adjust all values accordingly to the hardware capabilities * and chosen format. */ - ret = vidioc_try_fmt(file, prv, f); + ret = vidioc_try_fmt(file, priv, f); if (ret) return ret; vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); @@ -395,10 +397,10 @@ static int vidioc_s_fmt(struct file *file, void *prv, struct v4l2_format *f) return 0; } -static int vidioc_g_selection(struct file *file, void *prv, +static int vidioc_g_selection(struct file *file, void *priv, struct v4l2_selection *s) { - struct g2d_ctx *ctx = prv; + struct g2d_ctx *ctx = file2ctx(file); struct g2d_frame *f; f = get_frame(ctx, s->type); @@ -445,10 +447,10 @@ static int vidioc_g_selection(struct file *file, void *prv, return 0; } -static int vidioc_try_selection(struct file *file, void *prv, +static int vidioc_try_selection(struct file *file, void *priv, const struct v4l2_selection *s) { - struct g2d_ctx *ctx = prv; + struct g2d_ctx *ctx = file2ctx(file); struct g2d_dev *dev = ctx->dev; struct g2d_frame *f; @@ -473,14 +475,14 @@ static int vidioc_try_selection(struct file *file, void *prv, return 0; } -static int vidioc_s_selection(struct file *file, void *prv, +static int vidioc_s_selection(struct file *file, void *priv, struct v4l2_selection *s) { - struct g2d_ctx *ctx = prv; + struct g2d_ctx *ctx = file2ctx(file); struct g2d_frame *f; int ret; - ret = vidioc_try_selection(file, prv, s); + ret = vidioc_try_selection(file, priv, s); if (ret) return ret; f = get_frame(ctx, s->type); diff --git a/drivers/media/platform/samsung/s5p-jpeg/jpeg-core.c b/drivers/media/platform/samsung/s5p-jpeg/jpeg-core.c index ac4cf269456a..81792f7f8b16 100644 --- a/drivers/media/platform/samsung/s5p-jpeg/jpeg-core.c +++ b/drivers/media/platform/samsung/s5p-jpeg/jpeg-core.c @@ -580,9 +580,9 @@ static inline struct s5p_jpeg_ctx *ctrl_to_ctx(struct v4l2_ctrl *c) return container_of(c->handler, struct s5p_jpeg_ctx, ctrl_handler); } -static inline struct s5p_jpeg_ctx *fh_to_ctx(struct v4l2_fh *fh) +static inline struct s5p_jpeg_ctx *file_to_ctx(struct file *filp) { - return container_of(fh, struct s5p_jpeg_ctx, fh); + return container_of(file_to_v4l2_fh(filp), struct s5p_jpeg_ctx, fh); } static int s5p_jpeg_to_user_subsampling(struct s5p_jpeg_ctx *ctx) @@ -965,8 +965,7 @@ static int s5p_jpeg_open(struct file *file) v4l2_fh_init(&ctx->fh, vfd); /* Use separate control handler per file handle */ ctx->fh.ctrl_handler = &ctx->ctrl_handler; - file->private_data = &ctx->fh; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); ctx->jpeg = jpeg; if (vfd == jpeg->vfd_encoder) { @@ -1001,7 +1000,7 @@ static int s5p_jpeg_open(struct file *file) return 0; error: - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); mutex_unlock(&jpeg->lock); free: @@ -1011,13 +1010,13 @@ free: static int s5p_jpeg_release(struct file *file) { + struct s5p_jpeg_ctx *ctx = file_to_ctx(file); struct s5p_jpeg *jpeg = video_drvdata(file); - struct s5p_jpeg_ctx *ctx = fh_to_ctx(file->private_data); mutex_lock(&jpeg->lock); v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); v4l2_ctrl_handler_free(&ctx->ctrl_handler); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); kfree(ctx); mutex_unlock(&jpeg->lock); @@ -1249,7 +1248,7 @@ static bool s5p_jpeg_parse_hdr(struct s5p_jpeg_q_data *result, static int s5p_jpeg_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { - struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); + struct s5p_jpeg_ctx *ctx = file_to_ctx(file); if (ctx->mode == S5P_JPEG_ENCODE) { strscpy(cap->driver, S5P_JPEG_M2M_NAME, @@ -1297,7 +1296,7 @@ static int enum_fmt(struct s5p_jpeg_ctx *ctx, static int s5p_jpeg_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); + struct s5p_jpeg_ctx *ctx = file_to_ctx(file); if (ctx->mode == S5P_JPEG_ENCODE) return enum_fmt(ctx, sjpeg_formats, SJPEG_NUM_FORMATS, f, @@ -1310,7 +1309,7 @@ static int s5p_jpeg_enum_fmt_vid_cap(struct file *file, void *priv, static int s5p_jpeg_enum_fmt_vid_out(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); + struct s5p_jpeg_ctx *ctx = file_to_ctx(file); if (ctx->mode == S5P_JPEG_ENCODE) return enum_fmt(ctx, sjpeg_formats, SJPEG_NUM_FORMATS, f, @@ -1336,7 +1335,7 @@ static int s5p_jpeg_g_fmt(struct file *file, void *priv, struct v4l2_format *f) struct vb2_queue *vq; struct s5p_jpeg_q_data *q_data = NULL; struct v4l2_pix_format *pix = &f->fmt.pix; - struct s5p_jpeg_ctx *ct = fh_to_ctx(priv); + struct s5p_jpeg_ctx *ct = file_to_ctx(file); vq = v4l2_m2m_get_vq(ct->fh.m2m_ctx, f->type); if (!vq) @@ -1476,7 +1475,7 @@ static int vidioc_try_fmt(struct v4l2_format *f, struct s5p_jpeg_fmt *fmt, static int s5p_jpeg_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); + struct s5p_jpeg_ctx *ctx = file_to_ctx(file); struct v4l2_pix_format *pix = &f->fmt.pix; struct s5p_jpeg_fmt *fmt; int ret; @@ -1535,7 +1534,7 @@ exit: static int s5p_jpeg_try_fmt_vid_out(struct file *file, void *priv, struct v4l2_format *f) { - struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); + struct s5p_jpeg_ctx *ctx = file_to_ctx(file); struct s5p_jpeg_fmt *fmt; fmt = s5p_jpeg_find_format(ctx, f->fmt.pix.pixelformat, @@ -1682,7 +1681,7 @@ static int s5p_jpeg_s_fmt_vid_cap(struct file *file, void *priv, if (ret) return ret; - return s5p_jpeg_s_fmt(fh_to_ctx(priv), f); + return s5p_jpeg_s_fmt(file_to_ctx(file), f); } static int s5p_jpeg_s_fmt_vid_out(struct file *file, void *priv, @@ -1694,7 +1693,7 @@ static int s5p_jpeg_s_fmt_vid_out(struct file *file, void *priv, if (ret) return ret; - return s5p_jpeg_s_fmt(fh_to_ctx(priv), f); + return s5p_jpeg_s_fmt(file_to_ctx(file), f); } static int s5p_jpeg_subscribe_event(struct v4l2_fh *fh, @@ -1791,7 +1790,7 @@ static int exynos3250_jpeg_try_crop(struct s5p_jpeg_ctx *ctx, static int s5p_jpeg_g_selection(struct file *file, void *priv, struct v4l2_selection *s) { - struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); + struct s5p_jpeg_ctx *ctx = file_to_ctx(file); if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) @@ -1828,7 +1827,7 @@ static int s5p_jpeg_g_selection(struct file *file, void *priv, static int s5p_jpeg_s_selection(struct file *file, void *fh, struct v4l2_selection *s) { - struct s5p_jpeg_ctx *ctx = fh_to_ctx(file->private_data); + struct s5p_jpeg_ctx *ctx = file_to_ctx(file); struct v4l2_rect *rect = &s->r; int ret = -EINVAL; diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c index 73fdcd362265..4948d734eb02 100644 --- a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c @@ -801,8 +801,7 @@ static int s5p_mfc_open(struct file *file) } init_waitqueue_head(&ctx->queue); v4l2_fh_init(&ctx->fh, vdev); - file->private_data = &ctx->fh; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); ctx->dev = dev; INIT_LIST_HEAD(&ctx->src_queue); INIT_LIST_HEAD(&ctx->dst_queue); @@ -877,7 +876,7 @@ static int s5p_mfc_open(struct file *file) /* Init videobuf2 queue for CAPTURE */ q = &ctx->vq_dst; q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - q->drv_priv = &ctx->fh; + q->drv_priv = ctx; q->lock = &dev->mfc_mutex; if (vdev == dev->vfd_dec) { q->io_modes = VB2_MMAP; @@ -904,7 +903,7 @@ static int s5p_mfc_open(struct file *file) /* Init videobuf2 queue for OUTPUT */ q = &ctx->vq_src; q->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; - q->drv_priv = &ctx->fh; + q->drv_priv = ctx; q->lock = &dev->mfc_mutex; if (vdev == dev->vfd_dec) { q->io_modes = VB2_MMAP; @@ -956,7 +955,7 @@ err_ctrls_setup: err_bad_node: dev->ctx[ctx->num] = NULL; err_no_ctx: - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); kfree(ctx); err_alloc: @@ -970,7 +969,7 @@ err_enter: /* Release MFC context */ static int s5p_mfc_release(struct file *file) { - struct s5p_mfc_ctx *ctx = fh_to_ctx(file->private_data); + struct s5p_mfc_ctx *ctx = file_to_ctx(file); struct s5p_mfc_dev *dev = ctx->dev; /* if dev is null, do cleanup that doesn't need dev */ @@ -1011,7 +1010,7 @@ static int s5p_mfc_release(struct file *file) if (dev) dev->ctx[ctx->num] = NULL; s5p_mfc_dec_ctrls_delete(ctx); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); /* vdev is gone if dev is null */ if (dev) v4l2_fh_exit(&ctx->fh); @@ -1027,7 +1026,7 @@ static int s5p_mfc_release(struct file *file) static __poll_t s5p_mfc_poll(struct file *file, struct poll_table_struct *wait) { - struct s5p_mfc_ctx *ctx = fh_to_ctx(file->private_data); + struct s5p_mfc_ctx *ctx = file_to_ctx(file); struct s5p_mfc_dev *dev = ctx->dev; struct vb2_queue *src_q, *dst_q; struct vb2_buffer *src_vb = NULL, *dst_vb = NULL; @@ -1078,7 +1077,7 @@ end: /* Mmap */ static int s5p_mfc_mmap(struct file *file, struct vm_area_struct *vma) { - struct s5p_mfc_ctx *ctx = fh_to_ctx(file->private_data); + struct s5p_mfc_ctx *ctx = file_to_ctx(file); unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; int ret; diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_cmd_v6.c b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_cmd_v6.c index 47bc3014b5d8..f7c682fca645 100644 --- a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_cmd_v6.c +++ b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_cmd_v6.c @@ -14,8 +14,7 @@ #include "s5p_mfc_opr.h" #include "s5p_mfc_cmd_v6.h" -static int s5p_mfc_cmd_host2risc_v6(struct s5p_mfc_dev *dev, int cmd, - const struct s5p_mfc_cmd_args *args) +static int s5p_mfc_cmd_host2risc_v6(struct s5p_mfc_dev *dev, int cmd) { mfc_debug(2, "Issue the command: %d\n", cmd); @@ -31,7 +30,6 @@ static int s5p_mfc_cmd_host2risc_v6(struct s5p_mfc_dev *dev, int cmd, static int s5p_mfc_sys_init_cmd_v6(struct s5p_mfc_dev *dev) { - struct s5p_mfc_cmd_args h2r_args; const struct s5p_mfc_buf_size_v6 *buf_size = dev->variant->buf_size->priv; int ret; @@ -41,33 +39,23 @@ static int s5p_mfc_sys_init_cmd_v6(struct s5p_mfc_dev *dev) mfc_write(dev, dev->ctx_buf.dma, S5P_FIMV_CONTEXT_MEM_ADDR_V6); mfc_write(dev, buf_size->dev_ctx, S5P_FIMV_CONTEXT_MEM_SIZE_V6); - return s5p_mfc_cmd_host2risc_v6(dev, S5P_FIMV_H2R_CMD_SYS_INIT_V6, - &h2r_args); + return s5p_mfc_cmd_host2risc_v6(dev, S5P_FIMV_H2R_CMD_SYS_INIT_V6); } static int s5p_mfc_sleep_cmd_v6(struct s5p_mfc_dev *dev) { - struct s5p_mfc_cmd_args h2r_args; - - memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args)); - return s5p_mfc_cmd_host2risc_v6(dev, S5P_FIMV_H2R_CMD_SLEEP_V6, - &h2r_args); + return s5p_mfc_cmd_host2risc_v6(dev, S5P_FIMV_H2R_CMD_SLEEP_V6); } static int s5p_mfc_wakeup_cmd_v6(struct s5p_mfc_dev *dev) { - struct s5p_mfc_cmd_args h2r_args; - - memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args)); - return s5p_mfc_cmd_host2risc_v6(dev, S5P_FIMV_H2R_CMD_WAKEUP_V6, - &h2r_args); + return s5p_mfc_cmd_host2risc_v6(dev, S5P_FIMV_H2R_CMD_WAKEUP_V6); } /* Open a new instance and get its number */ static int s5p_mfc_open_inst_cmd_v6(struct s5p_mfc_ctx *ctx) { struct s5p_mfc_dev *dev = ctx->dev; - struct s5p_mfc_cmd_args h2r_args; int codec_type; mfc_debug(2, "Requested codec mode: %d\n", ctx->codec_mode); @@ -129,23 +117,20 @@ static int s5p_mfc_open_inst_cmd_v6(struct s5p_mfc_ctx *ctx) mfc_write(dev, ctx->ctx.size, S5P_FIMV_CONTEXT_MEM_SIZE_V6); mfc_write(dev, 0, S5P_FIMV_D_CRC_CTRL_V6); /* no crc */ - return s5p_mfc_cmd_host2risc_v6(dev, S5P_FIMV_H2R_CMD_OPEN_INSTANCE_V6, - &h2r_args); + return s5p_mfc_cmd_host2risc_v6(dev, S5P_FIMV_H2R_CMD_OPEN_INSTANCE_V6); } /* Close instance */ static int s5p_mfc_close_inst_cmd_v6(struct s5p_mfc_ctx *ctx) { struct s5p_mfc_dev *dev = ctx->dev; - struct s5p_mfc_cmd_args h2r_args; int ret = 0; dev->curr_ctx = ctx->num; if (ctx->state != MFCINST_FREE) { mfc_write(dev, ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6); ret = s5p_mfc_cmd_host2risc_v6(dev, - S5P_FIMV_H2R_CMD_CLOSE_INSTANCE_V6, - &h2r_args); + S5P_FIMV_H2R_CMD_CLOSE_INSTANCE_V6); } else { ret = -EINVAL; } @@ -153,9 +138,15 @@ static int s5p_mfc_close_inst_cmd_v6(struct s5p_mfc_ctx *ctx) return ret; } +static int s5p_mfc_cmd_host2risc_v6_args(struct s5p_mfc_dev *dev, int cmd, + const struct s5p_mfc_cmd_args *ignored) +{ + return s5p_mfc_cmd_host2risc_v6(dev, cmd); +} + /* Initialize cmd function pointers for MFC v6 */ static const struct s5p_mfc_hw_cmds s5p_mfc_cmds_v6 = { - .cmd_host2risc = s5p_mfc_cmd_host2risc_v6, + .cmd_host2risc = s5p_mfc_cmd_host2risc_v6_args, .sys_init_cmd = s5p_mfc_sys_init_cmd_v6, .sleep_cmd = s5p_mfc_sleep_cmd_v6, .wakeup_cmd = s5p_mfc_wakeup_cmd_v6, diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_common.h index 86c316c1ff8f..58dc1768082c 100644 --- a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_common.h +++ b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_common.h @@ -767,7 +767,11 @@ struct mfc_control { #define s5p_mfc_hw_call(f, op, args...) \ ((f && f->op) ? f->op(args) : (typeof(f->op(args)))(-ENODEV)) -#define fh_to_ctx(__fh) container_of(__fh, struct s5p_mfc_ctx, fh) +static inline struct s5p_mfc_ctx *file_to_ctx(struct file *filp) +{ + return container_of(file_to_v4l2_fh(filp), struct s5p_mfc_ctx, fh); +} + #define ctrl_to_ctx(__ctrl) \ container_of((__ctrl)->handler, struct s5p_mfc_ctx, ctrl_handler) diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_dec.c index 3efbc3367906..afd28beabfde 100644 --- a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_dec.c +++ b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_dec.c @@ -330,7 +330,7 @@ static int vidioc_enum_fmt(struct file *file, struct v4l2_fmtdesc *f, return 0; } -static int vidioc_enum_fmt_vid_cap(struct file *file, void *pirv, +static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f) { return vidioc_enum_fmt(file, f, false); @@ -345,7 +345,7 @@ static int vidioc_enum_fmt_vid_out(struct file *file, void *priv, /* Get format */ static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f) { - struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); + struct s5p_mfc_ctx *ctx = file_to_ctx(file); struct v4l2_pix_format_mplane *pix_mp; mfc_debug_enter(); @@ -442,7 +442,7 @@ static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f) static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f) { struct s5p_mfc_dev *dev = video_drvdata(file); - struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); + struct s5p_mfc_ctx *ctx = file_to_ctx(file); int ret = 0; struct v4l2_pix_format_mplane *pix_mp; const struct s5p_mfc_buf_size *buf_size = dev->variant->buf_size; @@ -598,7 +598,7 @@ static int vidioc_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *reqbufs) { struct s5p_mfc_dev *dev = video_drvdata(file); - struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); + struct s5p_mfc_ctx *ctx = file_to_ctx(file); if (reqbufs->memory != V4L2_MEMORY_MMAP) { mfc_debug(2, "Only V4L2_MEMORY_MMAP is supported\n"); @@ -619,7 +619,7 @@ static int vidioc_reqbufs(struct file *file, void *priv, static int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *buf) { - struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); + struct s5p_mfc_ctx *ctx = file_to_ctx(file); int ret; int i; @@ -647,7 +647,7 @@ static int vidioc_querybuf(struct file *file, void *priv, /* Queue a buffer */ static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) { - struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); + struct s5p_mfc_ctx *ctx = file_to_ctx(file); if (ctx->state == MFCINST_ERROR) { mfc_err("Call on QBUF after unrecoverable error\n"); @@ -666,7 +666,7 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) const struct v4l2_event ev = { .type = V4L2_EVENT_EOS }; - struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); + struct s5p_mfc_ctx *ctx = file_to_ctx(file); int ret; if (ctx->state == MFCINST_ERROR) { @@ -695,7 +695,7 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) static int vidioc_expbuf(struct file *file, void *priv, struct v4l2_exportbuffer *eb) { - struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); + struct s5p_mfc_ctx *ctx = file_to_ctx(file); if (eb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) return vb2_expbuf(&ctx->vq_src, eb); @@ -708,7 +708,7 @@ static int vidioc_expbuf(struct file *file, void *priv, static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type type) { - struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); + struct s5p_mfc_ctx *ctx = file_to_ctx(file); int ret = -EINVAL; mfc_debug_enter(); @@ -724,7 +724,7 @@ static int vidioc_streamon(struct file *file, void *priv, static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type type) { - struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); + struct s5p_mfc_ctx *ctx = file_to_ctx(file); if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) return vb2_streamoff(&ctx->vq_src, type); @@ -801,7 +801,7 @@ static const struct v4l2_ctrl_ops s5p_mfc_dec_ctrl_ops = { static int vidioc_g_selection(struct file *file, void *priv, struct v4l2_selection *s) { - struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); + struct s5p_mfc_ctx *ctx = file_to_ctx(file); struct s5p_mfc_dev *dev = ctx->dev; u32 left, right, top, bottom; u32 width, height; @@ -856,7 +856,7 @@ static int vidioc_g_selection(struct file *file, void *priv, static int vidioc_decoder_cmd(struct file *file, void *priv, struct v4l2_decoder_cmd *cmd) { - struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); + struct s5p_mfc_ctx *ctx = file_to_ctx(file); struct s5p_mfc_dev *dev = ctx->dev; struct s5p_mfc_buf *buf; unsigned long flags; @@ -937,7 +937,7 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq, unsigned int *plane_count, unsigned int psize[], struct device *alloc_devs[]) { - struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv); + struct s5p_mfc_ctx *ctx = vb2_get_drv_priv(vq); struct s5p_mfc_dev *dev = ctx->dev; const struct v4l2_format_info *format; @@ -1006,7 +1006,7 @@ static int s5p_mfc_buf_init(struct vb2_buffer *vb) { struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct vb2_queue *vq = vb->vb2_queue; - struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv); + struct s5p_mfc_ctx *ctx = vb2_get_drv_priv(vq); unsigned int i; if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { @@ -1068,7 +1068,7 @@ static int s5p_mfc_buf_init(struct vb2_buffer *vb) static int s5p_mfc_start_streaming(struct vb2_queue *q, unsigned int count) { - struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv); + struct s5p_mfc_ctx *ctx = vb2_get_drv_priv(q); struct s5p_mfc_dev *dev = ctx->dev; v4l2_ctrl_handler_setup(&ctx->ctrl_handler); @@ -1085,7 +1085,7 @@ static int s5p_mfc_start_streaming(struct vb2_queue *q, unsigned int count) static void s5p_mfc_stop_streaming(struct vb2_queue *q) { unsigned long flags; - struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv); + struct s5p_mfc_ctx *ctx = vb2_get_drv_priv(q); struct s5p_mfc_dev *dev = ctx->dev; int aborted = 0; @@ -1130,7 +1130,7 @@ static void s5p_mfc_stop_streaming(struct vb2_queue *q) static void s5p_mfc_buf_queue(struct vb2_buffer *vb) { struct vb2_queue *vq = vb->vb2_queue; - struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv); + struct s5p_mfc_ctx *ctx = vb2_get_drv_priv(vq); struct s5p_mfc_dev *dev = ctx->dev; unsigned long flags; struct s5p_mfc_buf *mfc_buf; diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_enc.c b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_enc.c index 6c603dcd5664..3f8701e5614f 100644 --- a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_enc.c +++ b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_enc.c @@ -1375,7 +1375,7 @@ static int vidioc_enum_fmt(struct file *file, struct v4l2_fmtdesc *f, return -EINVAL; } -static int vidioc_enum_fmt_vid_cap(struct file *file, void *pirv, +static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f) { return vidioc_enum_fmt(file, f, false); @@ -1389,8 +1389,8 @@ static int vidioc_enum_fmt_vid_out(struct file *file, void *priv, static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f) { - struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp; + struct s5p_mfc_ctx *ctx = file_to_ctx(file); mfc_debug(2, "f->type = %d ctx->state = %d\n", f->type, ctx->state); if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { @@ -1472,8 +1472,8 @@ static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f) static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f) { + struct s5p_mfc_ctx *ctx = file_to_ctx(file); struct s5p_mfc_dev *dev = video_drvdata(file); - struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp; int ret = 0; @@ -1531,7 +1531,7 @@ static int vidioc_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *reqbufs) { struct s5p_mfc_dev *dev = video_drvdata(file); - struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); + struct s5p_mfc_ctx *ctx = file_to_ctx(file); int ret = 0; /* if memory is not mmp or userptr or dmabuf return error */ @@ -1601,7 +1601,7 @@ static int vidioc_reqbufs(struct file *file, void *priv, static int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *buf) { - struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); + struct s5p_mfc_ctx *ctx = file_to_ctx(file); int ret = 0; /* if memory is not mmp or userptr or dmabuf return error */ @@ -1636,7 +1636,7 @@ static int vidioc_querybuf(struct file *file, void *priv, /* Queue a buffer */ static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) { - struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); + struct s5p_mfc_ctx *ctx = file_to_ctx(file); if (ctx->state == MFCINST_ERROR) { mfc_err("Call on QBUF after unrecoverable error\n"); @@ -1657,10 +1657,10 @@ static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) /* Dequeue a buffer */ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) { + struct s5p_mfc_ctx *ctx = file_to_ctx(file); const struct v4l2_event ev = { .type = V4L2_EVENT_EOS }; - struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); int ret; if (ctx->state == MFCINST_ERROR) { @@ -1685,7 +1685,7 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) static int vidioc_expbuf(struct file *file, void *priv, struct v4l2_exportbuffer *eb) { - struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); + struct s5p_mfc_ctx *ctx = file_to_ctx(file); if (eb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) return vb2_expbuf(&ctx->vq_src, eb); @@ -1698,7 +1698,7 @@ static int vidioc_expbuf(struct file *file, void *priv, static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type type) { - struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); + struct s5p_mfc_ctx *ctx = file_to_ctx(file); if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) return vb2_streamon(&ctx->vq_src, type); @@ -1711,7 +1711,7 @@ static int vidioc_streamon(struct file *file, void *priv, static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type type) { - struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); + struct s5p_mfc_ctx *ctx = file_to_ctx(file); if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) return vb2_streamoff(&ctx->vq_src, type); @@ -2284,7 +2284,7 @@ static const struct v4l2_ctrl_ops s5p_mfc_enc_ctrl_ops = { static int vidioc_s_parm(struct file *file, void *priv, struct v4l2_streamparm *a) { - struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); + struct s5p_mfc_ctx *ctx = file_to_ctx(file); if (a->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { ctx->enc_params.rc_framerate_num = @@ -2301,7 +2301,7 @@ static int vidioc_s_parm(struct file *file, void *priv, static int vidioc_g_parm(struct file *file, void *priv, struct v4l2_streamparm *a) { - struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); + struct s5p_mfc_ctx *ctx = file_to_ctx(file); if (a->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { a->parm.output.timeperframe.denominator = @@ -2318,7 +2318,7 @@ static int vidioc_g_parm(struct file *file, void *priv, static int vidioc_encoder_cmd(struct file *file, void *priv, struct v4l2_encoder_cmd *cmd) { - struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); + struct s5p_mfc_ctx *ctx = file_to_ctx(file); struct s5p_mfc_dev *dev = ctx->dev; struct s5p_mfc_buf *buf; unsigned long flags; @@ -2418,7 +2418,7 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq, unsigned int *buf_count, unsigned int *plane_count, unsigned int psize[], struct device *alloc_devs[]) { - struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv); + struct s5p_mfc_ctx *ctx = vb2_get_drv_priv(vq); struct s5p_mfc_dev *dev = ctx->dev; if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { @@ -2477,7 +2477,7 @@ static int s5p_mfc_buf_init(struct vb2_buffer *vb) { struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct vb2_queue *vq = vb->vb2_queue; - struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv); + struct s5p_mfc_ctx *ctx = vb2_get_drv_priv(vq); unsigned int i; int ret; @@ -2516,7 +2516,7 @@ static int s5p_mfc_buf_init(struct vb2_buffer *vb) static int s5p_mfc_buf_prepare(struct vb2_buffer *vb) { struct vb2_queue *vq = vb->vb2_queue; - struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv); + struct s5p_mfc_ctx *ctx = vb2_get_drv_priv(vq); int ret; if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { @@ -2557,7 +2557,7 @@ static int s5p_mfc_buf_prepare(struct vb2_buffer *vb) static int s5p_mfc_start_streaming(struct vb2_queue *q, unsigned int count) { - struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv); + struct s5p_mfc_ctx *ctx = vb2_get_drv_priv(q); struct s5p_mfc_dev *dev = ctx->dev; if (IS_MFCV6_PLUS(dev) && @@ -2588,7 +2588,7 @@ static int s5p_mfc_start_streaming(struct vb2_queue *q, unsigned int count) static void s5p_mfc_stop_streaming(struct vb2_queue *q) { unsigned long flags; - struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv); + struct s5p_mfc_ctx *ctx = vb2_get_drv_priv(q); struct s5p_mfc_dev *dev = ctx->dev; if ((ctx->state == MFCINST_FINISHING || @@ -2617,7 +2617,7 @@ static void s5p_mfc_stop_streaming(struct vb2_queue *q) static void s5p_mfc_buf_queue(struct vb2_buffer *vb) { struct vb2_queue *vq = vb->vb2_queue; - struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv); + struct s5p_mfc_ctx *ctx = vb2_get_drv_priv(vq); struct s5p_mfc_dev *dev = ctx->dev; unsigned long flags; struct s5p_mfc_buf *mfc_buf; diff --git a/drivers/media/platform/st/sti/bdisp/bdisp-v4l2.c b/drivers/media/platform/st/sti/bdisp/bdisp-v4l2.c index 1eb934490c0b..56169b70652d 100644 --- a/drivers/media/platform/st/sti/bdisp/bdisp-v4l2.c +++ b/drivers/media/platform/st/sti/bdisp/bdisp-v4l2.c @@ -33,7 +33,10 @@ #define BDISP_MIN_H 1 #define BDISP_MAX_H 8191 -#define fh_to_ctx(__fh) container_of(__fh, struct bdisp_ctx, fh) +static inline struct bdisp_ctx *file_to_ctx(struct file *filp) +{ + return container_of(file_to_v4l2_fh(filp), struct bdisp_ctx, fh); +} enum bdisp_dev_flags { ST_M2M_OPEN, /* Driver opened */ @@ -603,8 +606,7 @@ static int bdisp_open(struct file *file) /* Use separate control handler per file handle */ ctx->fh.ctrl_handler = &ctx->ctrl_handler; - file->private_data = &ctx->fh; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); /* Default format */ ctx->src = bdisp_dflt_fmt; @@ -630,7 +632,7 @@ static int bdisp_open(struct file *file) error_ctrls: bdisp_ctrls_delete(ctx); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); error_fh: v4l2_fh_exit(&ctx->fh); bdisp_hw_free_nodes(ctx); @@ -644,7 +646,7 @@ unlock: static int bdisp_release(struct file *file) { - struct bdisp_ctx *ctx = fh_to_ctx(file->private_data); + struct bdisp_ctx *ctx = file_to_ctx(file); struct bdisp_dev *bdisp = ctx->bdisp_dev; dev_dbg(bdisp->dev, "%s\n", __func__); @@ -655,7 +657,7 @@ static int bdisp_release(struct file *file) bdisp_ctrls_delete(ctx); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); if (--bdisp->m2m.refcnt <= 0) @@ -682,7 +684,7 @@ static const struct v4l2_file_operations bdisp_fops = { static int bdisp_querycap(struct file *file, void *fh, struct v4l2_capability *cap) { - struct bdisp_ctx *ctx = fh_to_ctx(fh); + struct bdisp_ctx *ctx = file_to_ctx(file); struct bdisp_dev *bdisp = ctx->bdisp_dev; strscpy(cap->driver, bdisp->pdev->name, sizeof(cap->driver)); @@ -694,7 +696,7 @@ static int bdisp_querycap(struct file *file, void *fh, static int bdisp_enum_fmt(struct file *file, void *fh, struct v4l2_fmtdesc *f) { - struct bdisp_ctx *ctx = fh_to_ctx(fh); + struct bdisp_ctx *ctx = file_to_ctx(file); const struct bdisp_fmt *fmt; if (f->index >= ARRAY_SIZE(bdisp_formats)) @@ -714,7 +716,7 @@ static int bdisp_enum_fmt(struct file *file, void *fh, struct v4l2_fmtdesc *f) static int bdisp_g_fmt(struct file *file, void *fh, struct v4l2_format *f) { - struct bdisp_ctx *ctx = fh_to_ctx(fh); + struct bdisp_ctx *ctx = file_to_ctx(file); struct v4l2_pix_format *pix; struct bdisp_frame *frame = ctx_get_frame(ctx, f->type); @@ -738,7 +740,7 @@ static int bdisp_g_fmt(struct file *file, void *fh, struct v4l2_format *f) static int bdisp_try_fmt(struct file *file, void *fh, struct v4l2_format *f) { - struct bdisp_ctx *ctx = fh_to_ctx(fh); + struct bdisp_ctx *ctx = file_to_ctx(file); struct v4l2_pix_format *pix = &f->fmt.pix; const struct bdisp_fmt *format; u32 in_w, in_h; @@ -788,7 +790,7 @@ static int bdisp_try_fmt(struct file *file, void *fh, struct v4l2_format *f) static int bdisp_s_fmt(struct file *file, void *fh, struct v4l2_format *f) { - struct bdisp_ctx *ctx = fh_to_ctx(fh); + struct bdisp_ctx *ctx = file_to_ctx(file); struct vb2_queue *vq; struct bdisp_frame *frame; struct v4l2_pix_format *pix; @@ -841,8 +843,8 @@ static int bdisp_s_fmt(struct file *file, void *fh, struct v4l2_format *f) static int bdisp_g_selection(struct file *file, void *fh, struct v4l2_selection *s) { + struct bdisp_ctx *ctx = file_to_ctx(file); struct bdisp_frame *frame; - struct bdisp_ctx *ctx = fh_to_ctx(fh); frame = ctx_get_frame(ctx, s->type); if (IS_ERR(frame)) { @@ -919,8 +921,8 @@ static int is_rect_enclosed(struct v4l2_rect *a, struct v4l2_rect *b) static int bdisp_s_selection(struct file *file, void *fh, struct v4l2_selection *s) { + struct bdisp_ctx *ctx = file_to_ctx(file); struct bdisp_frame *frame; - struct bdisp_ctx *ctx = fh_to_ctx(fh); struct v4l2_rect *in, out; bool valid = false; @@ -997,7 +999,7 @@ static int bdisp_s_selection(struct file *file, void *fh, static int bdisp_streamon(struct file *file, void *fh, enum v4l2_buf_type type) { - struct bdisp_ctx *ctx = fh_to_ctx(fh); + struct bdisp_ctx *ctx = file_to_ctx(file); if ((type == V4L2_BUF_TYPE_VIDEO_OUTPUT) && !bdisp_ctx_state_is_set(BDISP_SRC_FMT, ctx)) { diff --git a/drivers/media/platform/st/sti/delta/delta-mjpeg-dec.c b/drivers/media/platform/st/sti/delta/delta-mjpeg-dec.c index 0533d4a083d2..a078f1107300 100644 --- a/drivers/media/platform/st/sti/delta/delta-mjpeg-dec.c +++ b/drivers/media/platform/st/sti/delta/delta-mjpeg-dec.c @@ -239,7 +239,7 @@ static int delta_mjpeg_ipc_open(struct delta_ctx *pctx) return 0; } -static int delta_mjpeg_ipc_decode(struct delta_ctx *pctx, struct delta_au *au) +static int delta_mjpeg_ipc_decode(struct delta_ctx *pctx, dma_addr_t pstart, dma_addr_t pend) { struct delta_dev *delta = pctx->dev; struct delta_mjpeg_ctx *ctx = to_ctx(pctx); @@ -256,8 +256,8 @@ static int delta_mjpeg_ipc_decode(struct delta_ctx *pctx, struct delta_au *au) memset(params, 0, sizeof(*params)); - params->picture_start_addr_p = (u32)(au->paddr); - params->picture_end_addr_p = (u32)(au->paddr + au->size - 1); + params->picture_start_addr_p = pstart; + params->picture_end_addr_p = pend; /* * !WARNING! @@ -374,12 +374,14 @@ static int delta_mjpeg_decode(struct delta_ctx *pctx, struct delta_au *pau) struct delta_dev *delta = pctx->dev; struct delta_mjpeg_ctx *ctx = to_ctx(pctx); int ret; - struct delta_au au = *pau; + void *au_vaddr = pau->vaddr; + dma_addr_t au_dma = pau->paddr; + size_t au_size = pau->size; unsigned int data_offset = 0; struct mjpeg_header *header = &ctx->header_struct; if (!ctx->header) { - ret = delta_mjpeg_read_header(pctx, au.vaddr, au.size, + ret = delta_mjpeg_read_header(pctx, au_vaddr, au_size, header, &data_offset); if (ret) { pctx->stream_errors++; @@ -405,17 +407,17 @@ static int delta_mjpeg_decode(struct delta_ctx *pctx, struct delta_au *pau) goto err; } - ret = delta_mjpeg_read_header(pctx, au.vaddr, au.size, + ret = delta_mjpeg_read_header(pctx, au_vaddr, au_size, ctx->header, &data_offset); if (ret) { pctx->stream_errors++; goto err; } - au.paddr += data_offset; - au.vaddr += data_offset; + au_dma += data_offset; + au_vaddr += data_offset; - ret = delta_mjpeg_ipc_decode(pctx, &au); + ret = delta_mjpeg_ipc_decode(pctx, au_dma, au_dma + au_size - 1); if (ret) goto err; diff --git a/drivers/media/platform/st/sti/delta/delta-v4l2.c b/drivers/media/platform/st/sti/delta/delta-v4l2.c index 196e6a40335d..6c1a53c771f7 100644 --- a/drivers/media/platform/st/sti/delta/delta-v4l2.c +++ b/drivers/media/platform/st/sti/delta/delta-v4l2.c @@ -24,7 +24,11 @@ #define DELTA_PREFIX "[---:----]" -#define to_ctx(__fh) container_of(__fh, struct delta_ctx, fh) +static inline struct delta_ctx *file_to_ctx(struct file *filp) +{ + return container_of(file_to_v4l2_fh(filp), struct delta_ctx, fh); +} + #define to_au(__vbuf) container_of(__vbuf, struct delta_au, vbuf) #define to_frame(__vbuf) container_of(__vbuf, struct delta_frame, vbuf) @@ -382,7 +386,7 @@ static int delta_open_decoder(struct delta_ctx *ctx, u32 streamformat, static int delta_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { - struct delta_ctx *ctx = to_ctx(file->private_data); + struct delta_ctx *ctx = file_to_ctx(file); struct delta_dev *delta = ctx->dev; strscpy(cap->driver, DELTA_NAME, sizeof(cap->driver)); @@ -396,7 +400,7 @@ static int delta_querycap(struct file *file, void *priv, static int delta_enum_fmt_stream(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - struct delta_ctx *ctx = to_ctx(file->private_data); + struct delta_ctx *ctx = file_to_ctx(file); struct delta_dev *delta = ctx->dev; if (unlikely(f->index >= delta->nb_of_streamformats)) @@ -410,7 +414,7 @@ static int delta_enum_fmt_stream(struct file *file, void *priv, static int delta_enum_fmt_frame(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - struct delta_ctx *ctx = to_ctx(file->private_data); + struct delta_ctx *ctx = file_to_ctx(file); struct delta_dev *delta = ctx->dev; if (unlikely(f->index >= delta->nb_of_pixelformats)) @@ -424,7 +428,7 @@ static int delta_enum_fmt_frame(struct file *file, void *priv, static int delta_g_fmt_stream(struct file *file, void *fh, struct v4l2_format *f) { - struct delta_ctx *ctx = to_ctx(file->private_data); + struct delta_ctx *ctx = file_to_ctx(file); struct delta_dev *delta = ctx->dev; struct v4l2_pix_format *pix = &f->fmt.pix; struct delta_streaminfo *streaminfo = &ctx->streaminfo; @@ -452,7 +456,7 @@ static int delta_g_fmt_stream(struct file *file, void *fh, static int delta_g_fmt_frame(struct file *file, void *fh, struct v4l2_format *f) { - struct delta_ctx *ctx = to_ctx(file->private_data); + struct delta_ctx *ctx = file_to_ctx(file); struct delta_dev *delta = ctx->dev; struct v4l2_pix_format *pix = &f->fmt.pix; struct delta_frameinfo *frameinfo = &ctx->frameinfo; @@ -491,7 +495,7 @@ static int delta_g_fmt_frame(struct file *file, void *fh, struct v4l2_format *f) static int delta_try_fmt_stream(struct file *file, void *priv, struct v4l2_format *f) { - struct delta_ctx *ctx = to_ctx(file->private_data); + struct delta_ctx *ctx = file_to_ctx(file); struct delta_dev *delta = ctx->dev; struct v4l2_pix_format *pix = &f->fmt.pix; u32 streamformat = pix->pixelformat; @@ -545,7 +549,7 @@ static int delta_try_fmt_stream(struct file *file, void *priv, static int delta_try_fmt_frame(struct file *file, void *priv, struct v4l2_format *f) { - struct delta_ctx *ctx = to_ctx(file->private_data); + struct delta_ctx *ctx = file_to_ctx(file); struct delta_dev *delta = ctx->dev; struct v4l2_pix_format *pix = &f->fmt.pix; u32 pixelformat = pix->pixelformat; @@ -605,7 +609,7 @@ static int delta_try_fmt_frame(struct file *file, void *priv, static int delta_s_fmt_stream(struct file *file, void *fh, struct v4l2_format *f) { - struct delta_ctx *ctx = to_ctx(file->private_data); + struct delta_ctx *ctx = file_to_ctx(file); struct delta_dev *delta = ctx->dev; struct vb2_queue *vq; struct v4l2_pix_format *pix = &f->fmt.pix; @@ -641,7 +645,7 @@ static int delta_s_fmt_stream(struct file *file, void *fh, static int delta_s_fmt_frame(struct file *file, void *fh, struct v4l2_format *f) { - struct delta_ctx *ctx = to_ctx(file->private_data); + struct delta_ctx *ctx = file_to_ctx(file); struct delta_dev *delta = ctx->dev; const struct delta_dec *dec = ctx->dec; struct v4l2_pix_format *pix = &f->fmt.pix; @@ -721,7 +725,7 @@ static int delta_s_fmt_frame(struct file *file, void *fh, struct v4l2_format *f) static int delta_g_selection(struct file *file, void *fh, struct v4l2_selection *s) { - struct delta_ctx *ctx = to_ctx(fh); + struct delta_ctx *ctx = file_to_ctx(file); struct delta_frameinfo *frameinfo = &ctx->frameinfo; struct v4l2_rect crop; @@ -803,7 +807,7 @@ static int delta_try_decoder_cmd(struct file *file, void *fh, return 0; } -static int delta_decoder_stop_cmd(struct delta_ctx *ctx, void *fh) +static int delta_decoder_stop_cmd(struct delta_ctx *ctx) { const struct delta_dec *dec = ctx->dec; struct delta_dev *delta = ctx->dev; @@ -866,14 +870,14 @@ delay_eos: static int delta_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *cmd) { - struct delta_ctx *ctx = to_ctx(fh); + struct delta_ctx *ctx = file_to_ctx(file); int ret = 0; ret = delta_try_decoder_cmd(file, fh, cmd); if (ret) return ret; - return delta_decoder_stop_cmd(ctx, fh); + return delta_decoder_stop_cmd(ctx); } static int delta_subscribe_event(struct v4l2_fh *fh, @@ -1633,8 +1637,7 @@ static int delta_open(struct file *file) ctx->dev = delta; v4l2_fh_init(&ctx->fh, video_devdata(file)); - file->private_data = &ctx->fh; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); INIT_WORK(&ctx->run_work, delta_run_work); mutex_init(&ctx->lock); @@ -1679,7 +1682,7 @@ static int delta_open(struct file *file) return 0; err_fh_del: - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); kfree(ctx); err: @@ -1690,7 +1693,7 @@ err: static int delta_release(struct file *file) { - struct delta_ctx *ctx = to_ctx(file->private_data); + struct delta_ctx *ctx = file_to_ctx(file); struct delta_dev *delta = ctx->dev; const struct delta_dec *dec = ctx->dec; @@ -1707,7 +1710,7 @@ static int delta_release(struct file *file) v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); /* disable ST231 clocks */ diff --git a/drivers/media/platform/st/sti/hva/hva-v4l2.c b/drivers/media/platform/st/sti/hva/hva-v4l2.c index 5366c0f92549..3581b73a99b8 100644 --- a/drivers/media/platform/st/sti/hva/hva-v4l2.c +++ b/drivers/media/platform/st/sti/hva/hva-v4l2.c @@ -36,7 +36,10 @@ #define to_type_str(type) (type == V4L2_BUF_TYPE_VIDEO_OUTPUT ? \ "frame" : "stream") -#define fh_to_ctx(f) (container_of(f, struct hva_ctx, fh)) +static inline struct hva_ctx *file_to_ctx(struct file *filp) +{ + return container_of(file_to_v4l2_fh(filp), struct hva_ctx, fh); +} /* registry of available encoders */ static const struct hva_enc *hva_encoders[] = { @@ -254,7 +257,7 @@ static void hva_dbg_summary(struct hva_ctx *ctx) static int hva_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { - struct hva_ctx *ctx = fh_to_ctx(file->private_data); + struct hva_ctx *ctx = file_to_ctx(file); struct hva_dev *hva = ctx_to_hdev(ctx); strscpy(cap->driver, HVA_NAME, sizeof(cap->driver)); @@ -268,7 +271,7 @@ static int hva_querycap(struct file *file, void *priv, static int hva_enum_fmt_stream(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - struct hva_ctx *ctx = fh_to_ctx(file->private_data); + struct hva_ctx *ctx = file_to_ctx(file); struct hva_dev *hva = ctx_to_hdev(ctx); if (unlikely(f->index >= hva->nb_of_streamformats)) @@ -282,7 +285,7 @@ static int hva_enum_fmt_stream(struct file *file, void *priv, static int hva_enum_fmt_frame(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - struct hva_ctx *ctx = fh_to_ctx(file->private_data); + struct hva_ctx *ctx = file_to_ctx(file); struct hva_dev *hva = ctx_to_hdev(ctx); if (unlikely(f->index >= hva->nb_of_pixelformats)) @@ -295,7 +298,7 @@ static int hva_enum_fmt_frame(struct file *file, void *priv, static int hva_g_fmt_stream(struct file *file, void *fh, struct v4l2_format *f) { - struct hva_ctx *ctx = fh_to_ctx(file->private_data); + struct hva_ctx *ctx = file_to_ctx(file); struct hva_streaminfo *streaminfo = &ctx->streaminfo; f->fmt.pix.width = streaminfo->width; @@ -314,7 +317,7 @@ static int hva_g_fmt_stream(struct file *file, void *fh, struct v4l2_format *f) static int hva_g_fmt_frame(struct file *file, void *fh, struct v4l2_format *f) { - struct hva_ctx *ctx = fh_to_ctx(file->private_data); + struct hva_ctx *ctx = file_to_ctx(file); struct hva_frameinfo *frameinfo = &ctx->frameinfo; f->fmt.pix.width = frameinfo->width; @@ -335,7 +338,7 @@ static int hva_g_fmt_frame(struct file *file, void *fh, struct v4l2_format *f) static int hva_try_fmt_stream(struct file *file, void *priv, struct v4l2_format *f) { - struct hva_ctx *ctx = fh_to_ctx(file->private_data); + struct hva_ctx *ctx = file_to_ctx(file); struct device *dev = ctx_to_dev(ctx); struct v4l2_pix_format *pix = &f->fmt.pix; u32 streamformat = pix->pixelformat; @@ -399,7 +402,7 @@ static int hva_try_fmt_stream(struct file *file, void *priv, static int hva_try_fmt_frame(struct file *file, void *priv, struct v4l2_format *f) { - struct hva_ctx *ctx = fh_to_ctx(file->private_data); + struct hva_ctx *ctx = file_to_ctx(file); struct device *dev = ctx_to_dev(ctx); struct v4l2_pix_format *pix = &f->fmt.pix; u32 pixelformat = pix->pixelformat; @@ -449,7 +452,7 @@ static int hva_try_fmt_frame(struct file *file, void *priv, static int hva_s_fmt_stream(struct file *file, void *fh, struct v4l2_format *f) { - struct hva_ctx *ctx = fh_to_ctx(file->private_data); + struct hva_ctx *ctx = file_to_ctx(file); struct device *dev = ctx_to_dev(ctx); struct vb2_queue *vq; int ret; @@ -479,7 +482,7 @@ static int hva_s_fmt_stream(struct file *file, void *fh, struct v4l2_format *f) static int hva_s_fmt_frame(struct file *file, void *fh, struct v4l2_format *f) { - struct hva_ctx *ctx = fh_to_ctx(file->private_data); + struct hva_ctx *ctx = file_to_ctx(file); struct device *dev = ctx_to_dev(ctx); struct v4l2_pix_format *pix = &f->fmt.pix; struct vb2_queue *vq; @@ -517,7 +520,7 @@ static int hva_s_fmt_frame(struct file *file, void *fh, struct v4l2_format *f) static int hva_g_parm(struct file *file, void *fh, struct v4l2_streamparm *sp) { - struct hva_ctx *ctx = fh_to_ctx(file->private_data); + struct hva_ctx *ctx = file_to_ctx(file); struct v4l2_fract *time_per_frame = &ctx->ctrls.time_per_frame; if (sp->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) @@ -533,7 +536,7 @@ static int hva_g_parm(struct file *file, void *fh, struct v4l2_streamparm *sp) static int hva_s_parm(struct file *file, void *fh, struct v4l2_streamparm *sp) { - struct hva_ctx *ctx = fh_to_ctx(file->private_data); + struct hva_ctx *ctx = file_to_ctx(file); struct v4l2_fract *time_per_frame = &ctx->ctrls.time_per_frame; if (sp->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) @@ -553,7 +556,7 @@ static int hva_s_parm(struct file *file, void *fh, struct v4l2_streamparm *sp) static int hva_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) { - struct hva_ctx *ctx = fh_to_ctx(file->private_data); + struct hva_ctx *ctx = file_to_ctx(file); struct device *dev = ctx_to_dev(ctx); if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { @@ -1171,8 +1174,7 @@ static int hva_open(struct file *file) INIT_WORK(&ctx->run_work, hva_run_work); v4l2_fh_init(&ctx->fh, video_devdata(file)); - file->private_data = &ctx->fh; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); ret = hva_ctrls_setup(ctx); if (ret) { @@ -1216,7 +1218,7 @@ static int hva_open(struct file *file) err_ctrls: v4l2_ctrl_handler_free(&ctx->ctrl_handler); err_fh: - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); kfree(ctx); out: @@ -1225,7 +1227,7 @@ out: static int hva_release(struct file *file) { - struct hva_ctx *ctx = fh_to_ctx(file->private_data); + struct hva_ctx *ctx = file_to_ctx(file); struct hva_dev *hva = ctx_to_hdev(ctx); struct device *dev = ctx_to_dev(ctx); const struct hva_enc *enc = ctx->enc; @@ -1247,7 +1249,7 @@ static int hva_release(struct file *file) v4l2_ctrl_handler_free(&ctx->ctrl_handler); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); #ifdef CONFIG_VIDEO_STI_HVA_DEBUGFS diff --git a/drivers/media/platform/st/sti/hva/hva.h b/drivers/media/platform/st/sti/hva/hva.h index ba6b893416ec..1fe561082a74 100644 --- a/drivers/media/platform/st/sti/hva/hva.h +++ b/drivers/media/platform/st/sti/hva/hva.h @@ -13,8 +13,6 @@ #include <media/videobuf2-v4l2.h> #include <media/v4l2-mem2mem.h> -#define fh_to_ctx(f) (container_of(f, struct hva_ctx, fh)) - #define hva_to_dev(h) (h->dev) #define ctx_to_dev(c) (c->hva_dev->dev) diff --git a/drivers/media/platform/st/stm32/dma2d/dma2d.c b/drivers/media/platform/st/stm32/dma2d/dma2d.c index 48fa781aab06..468c247ba328 100644 --- a/drivers/media/platform/st/stm32/dma2d/dma2d.c +++ b/drivers/media/platform/st/stm32/dma2d/dma2d.c @@ -45,7 +45,10 @@ * whole of a destination image with a pixel format conversion. */ -#define fh2ctx(__fh) container_of(__fh, struct dma2d_ctx, fh) +static inline struct dma2d_ctx *file2ctx(struct file *filp) +{ + return container_of(file_to_v4l2_fh(filp), struct dma2d_ctx, fh); +} static const struct dma2d_fmt formats[] = { { @@ -301,8 +304,7 @@ static int dma2d_open(struct file *file) } v4l2_fh_init(&ctx->fh, video_devdata(file)); - file->private_data = &ctx->fh; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); dma2d_setup_ctrls(ctx); @@ -318,13 +320,13 @@ static int dma2d_open(struct file *file) static int dma2d_release(struct file *file) { struct dma2d_dev *dev = video_drvdata(file); - struct dma2d_ctx *ctx = fh2ctx(file->private_data); + struct dma2d_ctx *ctx = file2ctx(file); mutex_lock(&dev->mutex); v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); mutex_unlock(&dev->mutex); v4l2_ctrl_handler_free(&ctx->ctrl_handler); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); kfree(ctx); @@ -341,7 +343,7 @@ static int vidioc_querycap(struct file *file, void *priv, return 0; } -static int vidioc_enum_fmt(struct file *file, void *prv, struct v4l2_fmtdesc *f) +static int vidioc_enum_fmt(struct file *file, void *priv, struct v4l2_fmtdesc *f) { if (f->index >= NUM_FORMATS) return -EINVAL; @@ -350,9 +352,9 @@ static int vidioc_enum_fmt(struct file *file, void *prv, struct v4l2_fmtdesc *f) return 0; } -static int vidioc_g_fmt(struct file *file, void *prv, struct v4l2_format *f) +static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f) { - struct dma2d_ctx *ctx = prv; + struct dma2d_ctx *ctx = file2ctx(file); struct vb2_queue *vq; struct dma2d_frame *frm; @@ -375,9 +377,9 @@ static int vidioc_g_fmt(struct file *file, void *prv, struct v4l2_format *f) return 0; } -static int vidioc_try_fmt(struct file *file, void *prv, struct v4l2_format *f) +static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f) { - struct dma2d_ctx *ctx = prv; + struct dma2d_ctx *ctx = file2ctx(file); struct dma2d_fmt *fmt; enum v4l2_field *field; u32 fourcc = f->fmt.pix.pixelformat; @@ -418,9 +420,9 @@ static int vidioc_try_fmt(struct file *file, void *prv, struct v4l2_format *f) return 0; } -static int vidioc_s_fmt(struct file *file, void *prv, struct v4l2_format *f) +static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f) { - struct dma2d_ctx *ctx = prv; + struct dma2d_ctx *ctx = file2ctx(file); struct vb2_queue *vq; struct dma2d_frame *frm; struct dma2d_fmt *fmt; @@ -429,7 +431,7 @@ static int vidioc_s_fmt(struct file *file, void *prv, struct v4l2_format *f) /* Adjust all values accordingly to the hardware capabilities * and chosen format. */ - ret = vidioc_try_fmt(file, prv, f); + ret = vidioc_try_fmt(file, priv, f); if (ret) return ret; diff --git a/drivers/media/platform/st/stm32/stm32-csi.c b/drivers/media/platform/st/stm32/stm32-csi.c index b69048144cc1..fd2b6dfbd44c 100644 --- a/drivers/media/platform/st/stm32/stm32-csi.c +++ b/drivers/media/platform/st/stm32/stm32-csi.c @@ -443,8 +443,7 @@ static void stm32_csi_phy_reg_write(struct stm32_csi_dev *csidev, static int stm32_csi_start(struct stm32_csi_dev *csidev, struct v4l2_subdev_state *state) { - struct media_pad *src_pad = - &csidev->s_subdev->entity.pads[csidev->s_subdev_pad_nb]; + struct media_pad *src_pad; const struct stm32_csi_mbps_phy_reg *phy_regs = NULL; struct v4l2_mbus_framefmt *sink_fmt; const struct stm32_csi_fmts *fmt; @@ -466,6 +465,7 @@ static int stm32_csi_start(struct stm32_csi_dev *csidev, if (!csidev->s_subdev) return -EIO; + src_pad = &csidev->s_subdev->entity.pads[csidev->s_subdev_pad_nb]; link_freq = v4l2_get_link_freq(src_pad, fmt->bpp, 2 * csidev->num_lanes); if (link_freq < 0) diff --git a/drivers/media/platform/st/stm32/stm32-dcmi.c b/drivers/media/platform/st/stm32/stm32-dcmi.c index d94c61b8569d..13762861b769 100644 --- a/drivers/media/platform/st/stm32/stm32-dcmi.c +++ b/drivers/media/platform/st/stm32/stm32-dcmi.c @@ -1701,8 +1701,8 @@ static int dcmi_framesizes_init(struct stm32_dcmi *dcmi) .which = V4L2_SUBDEV_FORMAT_ACTIVE, .code = dcmi->sd_format->mbus_code, }; - unsigned int ret; unsigned int i; + int ret; /* Allocate discrete framesizes array */ while (!v4l2_subdev_call(subdev, pad, enum_frame_size, @@ -1808,8 +1808,8 @@ static int dcmi_graph_notify_bound(struct v4l2_async_notifier *notifier, struct v4l2_async_connection *asd) { struct stm32_dcmi *dcmi = notifier_to_dcmi(notifier); - unsigned int ret; int src_pad; + int ret; dev_dbg(dcmi->dev, "Subdev \"%s\" bound\n", subdev->name); diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c index 76356bc7f10e..65879f4802c0 100644 --- a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c +++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c @@ -711,7 +711,7 @@ static void sun6i_csi_capture_format_prepare(struct v4l2_format *format) pix_format->xfer_func = V4L2_XFER_FUNC_DEFAULT; } -static int sun6i_csi_capture_querycap(struct file *file, void *private, +static int sun6i_csi_capture_querycap(struct file *file, void *priv, struct v4l2_capability *capability) { struct sun6i_csi_device *csi_dev = video_drvdata(file); @@ -725,7 +725,7 @@ static int sun6i_csi_capture_querycap(struct file *file, void *private, return 0; } -static int sun6i_csi_capture_enum_fmt(struct file *file, void *private, +static int sun6i_csi_capture_enum_fmt(struct file *file, void *priv, struct v4l2_fmtdesc *fmtdesc) { u32 index = fmtdesc->index; @@ -738,7 +738,7 @@ static int sun6i_csi_capture_enum_fmt(struct file *file, void *private, return 0; } -static int sun6i_csi_capture_g_fmt(struct file *file, void *private, +static int sun6i_csi_capture_g_fmt(struct file *file, void *priv, struct v4l2_format *format) { struct sun6i_csi_device *csi_dev = video_drvdata(file); @@ -748,7 +748,7 @@ static int sun6i_csi_capture_g_fmt(struct file *file, void *private, return 0; } -static int sun6i_csi_capture_s_fmt(struct file *file, void *private, +static int sun6i_csi_capture_s_fmt(struct file *file, void *priv, struct v4l2_format *format) { struct sun6i_csi_device *csi_dev = video_drvdata(file); @@ -764,7 +764,7 @@ static int sun6i_csi_capture_s_fmt(struct file *file, void *private, return 0; } -static int sun6i_csi_capture_try_fmt(struct file *file, void *private, +static int sun6i_csi_capture_try_fmt(struct file *file, void *priv, struct v4l2_format *format) { sun6i_csi_capture_format_prepare(format); @@ -772,7 +772,7 @@ static int sun6i_csi_capture_try_fmt(struct file *file, void *private, return 0; } -static int sun6i_csi_capture_enum_input(struct file *file, void *private, +static int sun6i_csi_capture_enum_input(struct file *file, void *priv, struct v4l2_input *input) { if (input->index != 0) @@ -784,7 +784,7 @@ static int sun6i_csi_capture_enum_input(struct file *file, void *private, return 0; } -static int sun6i_csi_capture_g_input(struct file *file, void *private, +static int sun6i_csi_capture_g_input(struct file *file, void *priv, unsigned int *index) { *index = 0; @@ -792,7 +792,7 @@ static int sun6i_csi_capture_g_input(struct file *file, void *private, return 0; } -static int sun6i_csi_capture_s_input(struct file *file, void *private, +static int sun6i_csi_capture_s_input(struct file *file, void *priv, unsigned int index) { if (index != 0) diff --git a/drivers/media/platform/sunxi/sun8i-di/sun8i-di.c b/drivers/media/platform/sunxi/sun8i-di/sun8i-di.c index 3e7f2df70408..eb519afb30ca 100644 --- a/drivers/media/platform/sunxi/sun8i-di/sun8i-di.c +++ b/drivers/media/platform/sunxi/sun8i-di/sun8i-di.c @@ -309,7 +309,7 @@ static void deinterlace_init(struct deinterlace_dev *dev) static inline struct deinterlace_ctx *deinterlace_file2ctx(struct file *file) { - return container_of(file->private_data, struct deinterlace_ctx, fh); + return container_of(file_to_v4l2_fh(file), struct deinterlace_ctx, fh); } static bool deinterlace_check_format(u32 pixelformat) @@ -730,7 +730,6 @@ static int deinterlace_open(struct file *file) deinterlace_prepare_format(&ctx->dst_fmt); v4l2_fh_init(&ctx->fh, video_devdata(file)); - file->private_data = &ctx->fh; ctx->dev = dev; ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, @@ -740,7 +739,7 @@ static int deinterlace_open(struct file *file) goto err_free; } - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); mutex_unlock(&dev->dev_mutex); @@ -756,12 +755,11 @@ err_free: static int deinterlace_release(struct file *file) { struct deinterlace_dev *dev = video_drvdata(file); - struct deinterlace_ctx *ctx = container_of(file->private_data, - struct deinterlace_ctx, fh); + struct deinterlace_ctx *ctx = deinterlace_file2ctx(file); mutex_lock(&dev->dev_mutex); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); diff --git a/drivers/media/platform/sunxi/sun8i-rotate/sun8i_rotate.c b/drivers/media/platform/sunxi/sun8i-rotate/sun8i_rotate.c index abd10b218aa1..89992feaab60 100644 --- a/drivers/media/platform/sunxi/sun8i-rotate/sun8i_rotate.c +++ b/drivers/media/platform/sunxi/sun8i-rotate/sun8i_rotate.c @@ -170,7 +170,7 @@ static irqreturn_t rotate_irq(int irq, void *data) static inline struct rotate_ctx *rotate_file2ctx(struct file *file) { - return container_of(file->private_data, struct rotate_ctx, fh); + return container_of(file_to_v4l2_fh(file), struct rotate_ctx, fh); } static void rotate_prepare_format(struct v4l2_pix_format *pix_fmt) @@ -659,7 +659,6 @@ static int rotate_open(struct file *file) rotate_set_cap_format(ctx, &ctx->dst_fmt, ctx->rotate); v4l2_fh_init(&ctx->fh, video_devdata(file)); - file->private_data = &ctx->fh; ctx->dev = dev; ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, @@ -669,7 +668,7 @@ static int rotate_open(struct file *file) goto err_free; } - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); ret = rotate_setup_ctrls(ctx); if (ret) @@ -691,13 +690,12 @@ err_free: static int rotate_release(struct file *file) { struct rotate_dev *dev = video_drvdata(file); - struct rotate_ctx *ctx = container_of(file->private_data, - struct rotate_ctx, fh); + struct rotate_ctx *ctx = rotate_file2ctx(file); mutex_lock(&dev->dev_mutex); v4l2_ctrl_handler_free(&ctx->ctrl_handler); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); diff --git a/drivers/media/platform/synopsys/hdmirx/snps_hdmirx.c b/drivers/media/platform/synopsys/hdmirx/snps_hdmirx.c index 7af6765532e3..b7d278b3889f 100644 --- a/drivers/media/platform/synopsys/hdmirx/snps_hdmirx.c +++ b/drivers/media/platform/synopsys/hdmirx/snps_hdmirx.c @@ -459,7 +459,7 @@ static bool port_no_link(struct snps_hdmirx_dev *hdmirx_dev) return !tx_5v_power_present(hdmirx_dev); } -static int hdmirx_query_dv_timings(struct file *file, void *_fh, +static int hdmirx_query_dv_timings(struct file *file, void *priv, struct v4l2_dv_timings *timings) { struct hdmirx_stream *stream = video_drvdata(file); @@ -751,7 +751,7 @@ static int hdmirx_dv_timings_cap(struct file *file, void *fh, return 0; } -static int hdmirx_enum_dv_timings(struct file *file, void *_fh, +static int hdmirx_enum_dv_timings(struct file *file, void *priv, struct v4l2_enum_dv_timings *timings) { return v4l2_enum_dv_timings_cap(timings, &hdmirx_timings_cap, NULL, NULL); @@ -1323,7 +1323,7 @@ static int hdmirx_g_fmt_vid_cap_mplane(struct file *file, void *fh, return 0; } -static int hdmirx_g_dv_timings(struct file *file, void *_fh, +static int hdmirx_g_dv_timings(struct file *file, void *priv, struct v4l2_dv_timings *timings) { struct hdmirx_stream *stream = video_drvdata(file); @@ -1339,7 +1339,7 @@ static int hdmirx_g_dv_timings(struct file *file, void *_fh, return 0; } -static int hdmirx_s_dv_timings(struct file *file, void *_fh, +static int hdmirx_s_dv_timings(struct file *file, void *priv, struct v4l2_dv_timings *timings) { struct hdmirx_stream *stream = video_drvdata(file); diff --git a/drivers/media/platform/synopsys/hdmirx/snps_hdmirx.h b/drivers/media/platform/synopsys/hdmirx/snps_hdmirx.h index 220ab99ca611..b13f58e31944 100644 --- a/drivers/media/platform/synopsys/hdmirx/snps_hdmirx.h +++ b/drivers/media/platform/synopsys/hdmirx/snps_hdmirx.h @@ -8,10 +8,12 @@ #ifndef DW_HDMIRX_H #define DW_HDMIRX_H +#include <linux/bitfield.h> #include <linux/bitops.h> +#include <linux/hw_bitfield.h> -#define UPDATE(x, h, l) (((x) << (l)) & GENMASK((h), (l))) -#define HIWORD_UPDATE(v, h, l) (((v) << (l)) | (GENMASK((h), (l)) << 16)) +#define UPDATE(x, h, l) FIELD_PREP(GENMASK((h), (l)), (x)) +#define HIWORD_UPDATE(v, h, l) FIELD_PREP_WM16(GENMASK((h), (l)), (v)) /* SYS_GRF */ #define SYS_GRF_SOC_CON1 0x0304 diff --git a/drivers/media/platform/ti/Kconfig b/drivers/media/platform/ti/Kconfig index bab998c4179a..3bc4aa35887e 100644 --- a/drivers/media/platform/ti/Kconfig +++ b/drivers/media/platform/ti/Kconfig @@ -67,7 +67,8 @@ config VIDEO_TI_J721E_CSI2RX tristate "TI J721E CSI2RX wrapper layer driver" depends on VIDEO_DEV && VIDEO_V4L2_SUBDEV_API depends on MEDIA_SUPPORT && MEDIA_CONTROLLER - depends on (PHY_CADENCE_DPHY_RX && VIDEO_CADENCE_CSI2RX) || COMPILE_TEST + depends on VIDEO_CADENCE_CSI2RX + depends on PHY_CADENCE_DPHY_RX || COMPILE_TEST depends on ARCH_K3 || COMPILE_TEST select VIDEOBUF2_DMA_CONTIG select V4L2_FWNODE diff --git a/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c b/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c index b628d6e081db..b75aa363d1bf 100644 --- a/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c +++ b/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c @@ -13,7 +13,9 @@ #include <linux/module.h> #include <linux/of_platform.h> #include <linux/platform_device.h> +#include <linux/property.h> +#include <media/cadence/cdns-csi2rx.h> #include <media/mipi-csi2.h> #include <media/v4l2-device.h> #include <media/v4l2-ioctl.h> @@ -28,6 +30,7 @@ #define SHIM_DMACNTX 0x20 #define SHIM_DMACNTX_EN BIT(31) #define SHIM_DMACNTX_YUV422 GENMASK(27, 26) +#define SHIM_DMACNTX_DUAL_PCK_CFG BIT(24) #define SHIM_DMACNTX_SIZE GENMASK(21, 20) #define SHIM_DMACNTX_FMT GENMASK(5, 0) #define SHIM_DMACNTX_YUV422_MODE_11 3 @@ -39,6 +42,7 @@ #define SHIM_PSI_CFG0_SRC_TAG GENMASK(15, 0) #define SHIM_PSI_CFG0_DST_TAG GENMASK(31, 16) +#define TI_CSI2RX_MAX_PIX_PER_CLK 4 #define PSIL_WORD_SIZE_BYTES 16 /* * There are no hard limits on the width or height. The DMA engine can handle @@ -52,6 +56,8 @@ #define DRAIN_TIMEOUT_MS 50 #define DRAIN_BUFFER_SIZE SZ_32K +#define CSI2RX_BRIDGE_SOURCE_PAD 1 + struct ti_csi2rx_fmt { u32 fourcc; /* Four character code. */ u32 code; /* Mbus code. */ @@ -107,6 +113,7 @@ struct ti_csi2rx_dev { struct v4l2_format v_fmt; struct ti_csi2rx_dma dma; u32 sequence; + u8 pix_per_clk; }; static const struct ti_csi2rx_fmt ti_csi2rx_formats[] = { @@ -299,7 +306,7 @@ static int ti_csi2rx_enum_fmt_vid_cap(struct file *file, void *priv, return 0; } -static int ti_csi2rx_g_fmt_vid_cap(struct file *file, void *prov, +static int ti_csi2rx_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { struct ti_csi2rx_dev *csi = video_drvdata(file); @@ -426,8 +433,9 @@ static int csi_async_notifier_complete(struct v4l2_async_notifier *notifier) if (ret) return ret; - ret = v4l2_create_fwnode_links_to_pad(csi->source, &csi->pad, - MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED); + ret = media_create_pad_link(&csi->source->entity, CSI2RX_BRIDGE_SOURCE_PAD, + &vdev->entity, csi->pad.index, + MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED); if (ret) { video_unregister_device(vdev); @@ -450,25 +458,23 @@ static int ti_csi2rx_notifier_register(struct ti_csi2rx_dev *csi) { struct fwnode_handle *fwnode; struct v4l2_async_connection *asc; - struct device_node *node; int ret; - node = of_get_child_by_name(csi->dev->of_node, "csi-bridge"); - if (!node) + fwnode = fwnode_get_named_child_node(csi->dev->fwnode, "csi-bridge"); + if (!fwnode) return -EINVAL; - fwnode = of_fwnode_handle(node); - if (!fwnode) { - of_node_put(node); - return -EINVAL; - } - v4l2_async_nf_init(&csi->notifier, &csi->v4l2_dev); csi->notifier.ops = &csi_async_notifier_ops; asc = v4l2_async_nf_add_fwnode(&csi->notifier, fwnode, struct v4l2_async_connection); - of_node_put(node); + /* + * Calling v4l2_async_nf_add_fwnode grabs a refcount, + * so drop the one we got in fwnode_get_named_child_node + */ + fwnode_handle_put(fwnode); + if (IS_ERR(asc)) { v4l2_async_nf_cleanup(&csi->notifier); return PTR_ERR(asc); @@ -483,6 +489,26 @@ static int ti_csi2rx_notifier_register(struct ti_csi2rx_dev *csi) return 0; } +/* Request maximum possible pixels per clock from the bridge */ +static void ti_csi2rx_request_max_ppc(struct ti_csi2rx_dev *csi) +{ + u8 ppc = TI_CSI2RX_MAX_PIX_PER_CLK; + struct media_pad *pad; + int ret; + + pad = media_entity_remote_source_pad_unique(&csi->vdev.entity); + if (IS_ERR(pad)) + return; + + ret = cdns_csi2rx_negotiate_ppc(csi->source, pad->index, &ppc); + if (ret) { + dev_warn(csi->dev, "NUM_PIXELS negotiation failed: %d\n", ret); + csi->pix_per_clk = 1; + } else { + csi->pix_per_clk = ppc; + } +} + static void ti_csi2rx_setup_shim(struct ti_csi2rx_dev *csi) { const struct ti_csi2rx_fmt *fmt; @@ -494,6 +520,9 @@ static void ti_csi2rx_setup_shim(struct ti_csi2rx_dev *csi) reg = SHIM_CNTL_PIX_RST; writel(reg, csi->shim + SHIM_CNTL); + /* Negotiate pixel count from the source */ + ti_csi2rx_request_max_ppc(csi); + reg = SHIM_DMACNTX_EN; reg |= FIELD_PREP(SHIM_DMACNTX_FMT, fmt->csi_dt); @@ -522,14 +551,18 @@ static void ti_csi2rx_setup_shim(struct ti_csi2rx_dev *csi) case V4L2_PIX_FMT_YVYU: reg |= FIELD_PREP(SHIM_DMACNTX_YUV422, SHIM_DMACNTX_YUV422_MODE_11); + /* Multiple pixels are handled differently for packed YUV */ + if (csi->pix_per_clk == 2) + reg |= SHIM_DMACNTX_DUAL_PCK_CFG; + reg |= FIELD_PREP(SHIM_DMACNTX_SIZE, fmt->size); break; default: - /* Ignore if not YUV 4:2:2 */ + /* By default we change the shift size for multiple pixels */ + reg |= FIELD_PREP(SHIM_DMACNTX_SIZE, + fmt->size + (csi->pix_per_clk >> 1)); break; } - reg |= FIELD_PREP(SHIM_DMACNTX_SIZE, fmt->size); - writel(reg, csi->shim + SHIM_DMACNTX); reg = FIELD_PREP(SHIM_PSI_CFG0_SRC_TAG, 0) | @@ -1120,7 +1153,7 @@ static int ti_csi2rx_probe(struct platform_device *pdev) if (ret) goto err_vb2q; - ret = of_platform_populate(csi->dev->of_node, NULL, NULL, csi->dev); + ret = devm_of_platform_populate(csi->dev); if (ret) { dev_err(csi->dev, "Failed to create children: %d\n", ret); goto err_subdev; diff --git a/drivers/media/platform/ti/omap/omap_vout.c b/drivers/media/platform/ti/omap/omap_vout.c index a87d5030ac35..22782e9f1f4e 100644 --- a/drivers/media/platform/ti/omap/omap_vout.c +++ b/drivers/media/platform/ti/omap/omap_vout.c @@ -1236,7 +1236,7 @@ static int vidioc_g_fbuf(struct file *file, void *fh, return 0; } -static int vidioc_enum_output(struct file *file, void *priv_fh, +static int vidioc_enum_output(struct file *file, void *priv, struct v4l2_output *out) { if (out->index) @@ -1246,13 +1246,13 @@ static int vidioc_enum_output(struct file *file, void *priv_fh, return 0; } -static int vidioc_g_output(struct file *file, void *priv_fh, unsigned int *i) +static int vidioc_g_output(struct file *file, void *priv, unsigned int *i) { *i = 0; return 0; } -static int vidioc_s_output(struct file *file, void *priv_fh, unsigned int i) +static int vidioc_s_output(struct file *file, void *priv, unsigned int i) { return i ? -EINVAL : 0; } diff --git a/drivers/media/platform/ti/omap3isp/ispccdc.c b/drivers/media/platform/ti/omap3isp/ispccdc.c index 7d0c723dcd11..55ee14e8b449 100644 --- a/drivers/media/platform/ti/omap3isp/ispccdc.c +++ b/drivers/media/platform/ti/omap3isp/ispccdc.c @@ -1873,12 +1873,6 @@ static int ccdc_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh, return v4l2_event_subscribe(fh, sub, OMAP3ISP_CCDC_NEVENTS, NULL); } -static int ccdc_unsubscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh, - struct v4l2_event_subscription *sub) -{ - return v4l2_event_unsubscribe(fh, sub); -} - /* * ccdc_set_stream - Enable/Disable streaming on the CCDC module * @sd: ISP CCDC V4L2 subdevice @@ -2487,7 +2481,7 @@ static int ccdc_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) static const struct v4l2_subdev_core_ops ccdc_v4l2_core_ops = { .ioctl = ccdc_ioctl, .subscribe_event = ccdc_subscribe_event, - .unsubscribe_event = ccdc_unsubscribe_event, + .unsubscribe_event = v4l2_event_subdev_unsubscribe, }; /* V4L2 subdev video operations */ diff --git a/drivers/media/platform/ti/omap3isp/isph3a_aewb.c b/drivers/media/platform/ti/omap3isp/isph3a_aewb.c index e6c54c4bbfca..ae93da9c4542 100644 --- a/drivers/media/platform/ti/omap3isp/isph3a_aewb.c +++ b/drivers/media/platform/ti/omap3isp/isph3a_aewb.c @@ -269,7 +269,7 @@ static const struct ispstat_ops h3a_aewb_ops = { static const struct v4l2_subdev_core_ops h3a_aewb_subdev_core_ops = { .ioctl = h3a_aewb_ioctl, .subscribe_event = omap3isp_stat_subscribe_event, - .unsubscribe_event = omap3isp_stat_unsubscribe_event, + .unsubscribe_event = v4l2_event_subdev_unsubscribe, }; static const struct v4l2_subdev_video_ops h3a_aewb_subdev_video_ops = { diff --git a/drivers/media/platform/ti/omap3isp/isph3a_af.c b/drivers/media/platform/ti/omap3isp/isph3a_af.c index de7b116d0122..ca478da4ad34 100644 --- a/drivers/media/platform/ti/omap3isp/isph3a_af.c +++ b/drivers/media/platform/ti/omap3isp/isph3a_af.c @@ -334,7 +334,7 @@ static const struct ispstat_ops h3a_af_ops = { static const struct v4l2_subdev_core_ops h3a_af_subdev_core_ops = { .ioctl = h3a_af_ioctl, .subscribe_event = omap3isp_stat_subscribe_event, - .unsubscribe_event = omap3isp_stat_unsubscribe_event, + .unsubscribe_event = v4l2_event_subdev_unsubscribe, }; static const struct v4l2_subdev_video_ops h3a_af_subdev_video_ops = { diff --git a/drivers/media/platform/ti/omap3isp/isphist.c b/drivers/media/platform/ti/omap3isp/isphist.c index 0ef78aace6da..7851ad13d84f 100644 --- a/drivers/media/platform/ti/omap3isp/isphist.c +++ b/drivers/media/platform/ti/omap3isp/isphist.c @@ -456,7 +456,7 @@ static const struct ispstat_ops hist_ops = { static const struct v4l2_subdev_core_ops hist_subdev_core_ops = { .ioctl = hist_ioctl, .subscribe_event = omap3isp_stat_subscribe_event, - .unsubscribe_event = omap3isp_stat_unsubscribe_event, + .unsubscribe_event = v4l2_event_subdev_unsubscribe, }; static const struct v4l2_subdev_video_ops hist_subdev_video_ops = { diff --git a/drivers/media/platform/ti/omap3isp/ispstat.c b/drivers/media/platform/ti/omap3isp/ispstat.c index d3da68408ecb..07bd62a93d99 100644 --- a/drivers/media/platform/ti/omap3isp/ispstat.c +++ b/drivers/media/platform/ti/omap3isp/ispstat.c @@ -1010,13 +1010,6 @@ int omap3isp_stat_subscribe_event(struct v4l2_subdev *subdev, return v4l2_event_subscribe(fh, sub, STAT_NEVENTS, NULL); } -int omap3isp_stat_unsubscribe_event(struct v4l2_subdev *subdev, - struct v4l2_fh *fh, - struct v4l2_event_subscription *sub) -{ - return v4l2_event_unsubscribe(fh, sub); -} - void omap3isp_stat_unregister_entities(struct ispstat *stat) { v4l2_device_unregister_subdev(&stat->subdev); diff --git a/drivers/media/platform/ti/omap3isp/ispstat.h b/drivers/media/platform/ti/omap3isp/ispstat.h index b548e617cf62..59842c4a9c33 100644 --- a/drivers/media/platform/ti/omap3isp/ispstat.h +++ b/drivers/media/platform/ti/omap3isp/ispstat.h @@ -135,9 +135,6 @@ void omap3isp_stat_cleanup(struct ispstat *stat); int omap3isp_stat_subscribe_event(struct v4l2_subdev *subdev, struct v4l2_fh *fh, struct v4l2_event_subscription *sub); -int omap3isp_stat_unsubscribe_event(struct v4l2_subdev *subdev, - struct v4l2_fh *fh, - struct v4l2_event_subscription *sub); int omap3isp_stat_s_stream(struct v4l2_subdev *subdev, int enable); int omap3isp_stat_busy(struct ispstat *stat); diff --git a/drivers/media/platform/ti/omap3isp/ispvideo.c b/drivers/media/platform/ti/omap3isp/ispvideo.c index 78e30298c7ad..0e7f0bf2b346 100644 --- a/drivers/media/platform/ti/omap3isp/ispvideo.c +++ b/drivers/media/platform/ti/omap3isp/ispvideo.c @@ -657,7 +657,7 @@ isp_video_querycap(struct file *file, void *fh, struct v4l2_capability *cap) static int isp_video_get_format(struct file *file, void *fh, struct v4l2_format *format) { - struct isp_video_fh *vfh = to_isp_video_fh(fh); + struct isp_video_fh *vfh = file_to_isp_video_fh(file); struct isp_video *video = video_drvdata(file); if (format->type != video->type) @@ -673,7 +673,7 @@ isp_video_get_format(struct file *file, void *fh, struct v4l2_format *format) static int isp_video_set_format(struct file *file, void *fh, struct v4l2_format *format) { - struct isp_video_fh *vfh = to_isp_video_fh(fh); + struct isp_video_fh *vfh = file_to_isp_video_fh(file); struct isp_video *video = video_drvdata(file); struct v4l2_mbus_framefmt fmt; @@ -858,7 +858,7 @@ isp_video_set_selection(struct file *file, void *fh, struct v4l2_selection *sel) static int isp_video_get_param(struct file *file, void *fh, struct v4l2_streamparm *a) { - struct isp_video_fh *vfh = to_isp_video_fh(fh); + struct isp_video_fh *vfh = file_to_isp_video_fh(file); struct isp_video *video = video_drvdata(file); if (video->type != V4L2_BUF_TYPE_VIDEO_OUTPUT || @@ -876,7 +876,7 @@ isp_video_get_param(struct file *file, void *fh, struct v4l2_streamparm *a) static int isp_video_set_param(struct file *file, void *fh, struct v4l2_streamparm *a) { - struct isp_video_fh *vfh = to_isp_video_fh(fh); + struct isp_video_fh *vfh = file_to_isp_video_fh(file); struct isp_video *video = video_drvdata(file); if (video->type != V4L2_BUF_TYPE_VIDEO_OUTPUT || @@ -894,7 +894,7 @@ isp_video_set_param(struct file *file, void *fh, struct v4l2_streamparm *a) static int isp_video_reqbufs(struct file *file, void *fh, struct v4l2_requestbuffers *rb) { - struct isp_video_fh *vfh = to_isp_video_fh(fh); + struct isp_video_fh *vfh = file_to_isp_video_fh(file); struct isp_video *video = video_drvdata(file); int ret; @@ -908,7 +908,7 @@ isp_video_reqbufs(struct file *file, void *fh, struct v4l2_requestbuffers *rb) static int isp_video_querybuf(struct file *file, void *fh, struct v4l2_buffer *b) { - struct isp_video_fh *vfh = to_isp_video_fh(fh); + struct isp_video_fh *vfh = file_to_isp_video_fh(file); struct isp_video *video = video_drvdata(file); int ret; @@ -922,7 +922,7 @@ isp_video_querybuf(struct file *file, void *fh, struct v4l2_buffer *b) static int isp_video_qbuf(struct file *file, void *fh, struct v4l2_buffer *b) { - struct isp_video_fh *vfh = to_isp_video_fh(fh); + struct isp_video_fh *vfh = file_to_isp_video_fh(file); struct isp_video *video = video_drvdata(file); int ret; @@ -936,7 +936,7 @@ isp_video_qbuf(struct file *file, void *fh, struct v4l2_buffer *b) static int isp_video_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b) { - struct isp_video_fh *vfh = to_isp_video_fh(fh); + struct isp_video_fh *vfh = file_to_isp_video_fh(file); struct isp_video *video = video_drvdata(file); int ret; @@ -1074,7 +1074,7 @@ static int isp_video_check_external_subdevs(struct isp_video *video, static int isp_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type) { - struct isp_video_fh *vfh = to_isp_video_fh(fh); + struct isp_video_fh *vfh = file_to_isp_video_fh(file); struct isp_video *video = video_drvdata(file); enum isp_pipeline_state state; struct isp_pipeline *pipe; @@ -1180,7 +1180,7 @@ err_enum_init: static int isp_video_streamoff(struct file *file, void *fh, enum v4l2_buf_type type) { - struct isp_video_fh *vfh = to_isp_video_fh(fh); + struct isp_video_fh *vfh = file_to_isp_video_fh(file); struct isp_video *video = video_drvdata(file); struct isp_pipeline *pipe = to_isp_pipeline(&video->video.entity); enum isp_pipeline_state state; @@ -1297,7 +1297,7 @@ static int isp_video_open(struct file *file) return -ENOMEM; v4l2_fh_init(&handle->vfh, &video->video); - v4l2_fh_add(&handle->vfh); + v4l2_fh_add(&handle->vfh, file); /* If this is the first user, initialise the pipeline. */ if (omap3isp_get(video->isp) == NULL) { @@ -1333,11 +1333,10 @@ static int isp_video_open(struct file *file) handle->timeperframe.denominator = 1; handle->video = video; - file->private_data = &handle->vfh; done: if (ret < 0) { - v4l2_fh_del(&handle->vfh); + v4l2_fh_del(&handle->vfh, file); v4l2_fh_exit(&handle->vfh); kfree(handle); } @@ -1348,8 +1347,8 @@ done: static int isp_video_release(struct file *file) { struct isp_video *video = video_drvdata(file); - struct v4l2_fh *vfh = file->private_data; - struct isp_video_fh *handle = to_isp_video_fh(vfh); + struct v4l2_fh *vfh = file_to_v4l2_fh(file); + struct isp_video_fh *handle = file_to_isp_video_fh(file); /* Disable streaming and free the buffers queue resources. */ isp_video_streamoff(file, vfh, video->type); @@ -1361,10 +1360,9 @@ static int isp_video_release(struct file *file) v4l2_pipeline_pm_put(&video->video.entity); /* Release the file handle. */ - v4l2_fh_del(vfh); + v4l2_fh_del(vfh, file); v4l2_fh_exit(vfh); kfree(handle); - file->private_data = NULL; omap3isp_put(video->isp); @@ -1373,7 +1371,7 @@ static int isp_video_release(struct file *file) static __poll_t isp_video_poll(struct file *file, poll_table *wait) { - struct isp_video_fh *vfh = to_isp_video_fh(file->private_data); + struct isp_video_fh *vfh = file_to_isp_video_fh(file); struct isp_video *video = video_drvdata(file); __poll_t ret; @@ -1386,7 +1384,7 @@ static __poll_t isp_video_poll(struct file *file, poll_table *wait) static int isp_video_mmap(struct file *file, struct vm_area_struct *vma) { - struct isp_video_fh *vfh = to_isp_video_fh(file->private_data); + struct isp_video_fh *vfh = file_to_isp_video_fh(file); return vb2_mmap(&vfh->queue, vma); } diff --git a/drivers/media/platform/ti/omap3isp/ispvideo.h b/drivers/media/platform/ti/omap3isp/ispvideo.h index 1d23df576e6b..537da59cff62 100644 --- a/drivers/media/platform/ti/omap3isp/ispvideo.h +++ b/drivers/media/platform/ti/omap3isp/ispvideo.h @@ -194,7 +194,11 @@ struct isp_video_fh { struct v4l2_fract timeperframe; }; -#define to_isp_video_fh(fh) container_of(fh, struct isp_video_fh, vfh) +static inline struct isp_video_fh *file_to_isp_video_fh(struct file *filp) +{ + return container_of(file_to_v4l2_fh(filp), struct isp_video_fh, vfh); +} + #define isp_video_queue_to_isp_video_fh(q) \ container_of(q, struct isp_video_fh, queue) diff --git a/drivers/media/platform/ti/vpe/vpe.c b/drivers/media/platform/ti/vpe/vpe.c index 636d76ecebcd..6029d4e8e0bd 100644 --- a/drivers/media/platform/ti/vpe/vpe.c +++ b/drivers/media/platform/ti/vpe/vpe.c @@ -422,6 +422,10 @@ struct vpe_ctx { unsigned int src_mv_buf_selector; }; +static inline struct vpe_ctx *to_vpe_ctx(struct file *filp) +{ + return container_of(file_to_v4l2_fh(filp), struct vpe_ctx, fh); +} /* * M2M devices get 2 queues. @@ -1562,7 +1566,7 @@ static int vpe_enum_fmt(struct file *file, void *priv, static int vpe_g_fmt(struct file *file, void *priv, struct v4l2_format *f) { struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp; - struct vpe_ctx *ctx = file->private_data; + struct vpe_ctx *ctx = to_vpe_ctx(file); struct vb2_queue *vq; struct vpe_q_data *q_data; @@ -1719,7 +1723,7 @@ static int __vpe_try_fmt(struct vpe_ctx *ctx, struct v4l2_format *f, static int vpe_try_fmt(struct file *file, void *priv, struct v4l2_format *f) { - struct vpe_ctx *ctx = file->private_data; + struct vpe_ctx *ctx = to_vpe_ctx(file); struct vpe_fmt *fmt = find_format(f); if (V4L2_TYPE_IS_OUTPUT(f->type)) @@ -1783,7 +1787,7 @@ static int __vpe_s_fmt(struct vpe_ctx *ctx, struct v4l2_format *f) static int vpe_s_fmt(struct file *file, void *priv, struct v4l2_format *f) { int ret; - struct vpe_ctx *ctx = file->private_data; + struct vpe_ctx *ctx = to_vpe_ctx(file); ret = vpe_try_fmt(file, priv, f); if (ret) @@ -1871,7 +1875,7 @@ static int __vpe_try_selection(struct vpe_ctx *ctx, struct v4l2_selection *s) static int vpe_g_selection(struct file *file, void *fh, struct v4l2_selection *s) { - struct vpe_ctx *ctx = file->private_data; + struct vpe_ctx *ctx = to_vpe_ctx(file); struct vpe_q_data *q_data; struct v4l2_pix_format_mplane *pix; bool use_c_rect = false; @@ -1935,7 +1939,7 @@ static int vpe_g_selection(struct file *file, void *fh, static int vpe_s_selection(struct file *file, void *fh, struct v4l2_selection *s) { - struct vpe_ctx *ctx = file->private_data; + struct vpe_ctx *ctx = to_vpe_ctx(file); struct vpe_q_data *q_data; struct v4l2_selection sel = *s; int ret; @@ -2306,7 +2310,6 @@ static int vpe_open(struct file *file) init_adb_hdrs(ctx); v4l2_fh_init(&ctx->fh, video_devdata(file)); - file->private_data = ctx; hdl = &ctx->hdl; v4l2_ctrl_handler_init(hdl, 1); @@ -2360,7 +2363,7 @@ static int vpe_open(struct file *file) goto exit_fh; } - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); /* * for now, just report the creation of the first instance, we can later @@ -2400,7 +2403,7 @@ free_ctx: static int vpe_release(struct file *file) { struct vpe_dev *dev = video_drvdata(file); - struct vpe_ctx *ctx = file->private_data; + struct vpe_ctx *ctx = to_vpe_ctx(file); vpe_dbg(dev, "releasing instance %p\n", ctx); @@ -2418,7 +2421,7 @@ static int vpe_release(struct file *file) vpdma_free_desc_buf(&ctx->sc_coeff_v); vpdma_free_desc_buf(&ctx->sc_coeff_h); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); v4l2_ctrl_handler_free(&ctx->hdl); v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); diff --git a/drivers/media/platform/verisilicon/hantro.h b/drivers/media/platform/verisilicon/hantro.h index 81328c63b796..e0fdc4535b2d 100644 --- a/drivers/media/platform/verisilicon/hantro.h +++ b/drivers/media/platform/verisilicon/hantro.h @@ -382,9 +382,9 @@ extern int hantro_debug; pr_err("%s:%d: " fmt, __func__, __LINE__, ##args) /* Structure access helpers. */ -static __always_inline struct hantro_ctx *fh_to_ctx(struct v4l2_fh *fh) +static __always_inline struct hantro_ctx *file_to_ctx(struct file *filp) { - return container_of(fh, struct hantro_ctx, fh); + return container_of(file_to_v4l2_fh(filp), struct hantro_ctx, fh); } /* Register accessors. */ diff --git a/drivers/media/platform/verisilicon/hantro_drv.c b/drivers/media/platform/verisilicon/hantro_drv.c index fa972effd4a2..e0c11fe8b55c 100644 --- a/drivers/media/platform/verisilicon/hantro_drv.c +++ b/drivers/media/platform/verisilicon/hantro_drv.c @@ -662,8 +662,7 @@ static int hantro_open(struct file *filp) } v4l2_fh_init(&ctx->fh, vdev); - filp->private_data = &ctx->fh; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, filp); hantro_reset_fmts(ctx); @@ -677,7 +676,7 @@ static int hantro_open(struct file *filp) return 0; err_fh_free: - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, filp); v4l2_fh_exit(&ctx->fh); err_ctx_free: kfree(ctx); @@ -686,15 +685,14 @@ err_ctx_free: static int hantro_release(struct file *filp) { - struct hantro_ctx *ctx = - container_of(filp->private_data, struct hantro_ctx, fh); + struct hantro_ctx *ctx = file_to_ctx(filp); /* * No need for extra locking because this was the last reference * to this file. */ v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, filp); v4l2_fh_exit(&ctx->fh); v4l2_ctrl_handler_free(&ctx->ctrl_handler); kfree(ctx); @@ -917,6 +915,8 @@ static int hantro_add_func(struct hantro_dev *vpu, unsigned int funcid) vpu->decoder = func; v4l2_disable_ioctl(vfd, VIDIOC_TRY_ENCODER_CMD); v4l2_disable_ioctl(vfd, VIDIOC_ENCODER_CMD); + v4l2_disable_ioctl(vfd, VIDIOC_G_SELECTION); + v4l2_disable_ioctl(vfd, VIDIOC_S_SELECTION); } video_set_drvdata(vfd, vpu); diff --git a/drivers/media/platform/verisilicon/hantro_v4l2.c b/drivers/media/platform/verisilicon/hantro_v4l2.c index 7c3515cf7d64..fcf3bd9bcda2 100644 --- a/drivers/media/platform/verisilicon/hantro_v4l2.c +++ b/drivers/media/platform/verisilicon/hantro_v4l2.c @@ -185,7 +185,7 @@ static int vidioc_querycap(struct file *file, void *priv, static int vidioc_enum_framesizes(struct file *file, void *priv, struct v4l2_frmsizeenum *fsize) { - struct hantro_ctx *ctx = fh_to_ctx(priv); + struct hantro_ctx *ctx = file_to_ctx(file); const struct hantro_fmt *fmt; fmt = hantro_find_format(ctx, fsize->pixel_format); @@ -217,7 +217,7 @@ static int vidioc_enum_fmt(struct file *file, void *priv, struct v4l2_fmtdesc *f, bool capture) { - struct hantro_ctx *ctx = fh_to_ctx(priv); + struct hantro_ctx *ctx = file_to_ctx(file); const struct hantro_fmt *fmt, *formats; unsigned int num_fmts, i, j = 0; bool skip_mode_none, enum_all_formats; @@ -297,7 +297,7 @@ static int vidioc_g_fmt_out_mplane(struct file *file, void *priv, struct v4l2_format *f) { struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; - struct hantro_ctx *ctx = fh_to_ctx(priv); + struct hantro_ctx *ctx = file_to_ctx(file); vpu_debug(4, "f->type = %d\n", f->type); @@ -310,7 +310,7 @@ static int vidioc_g_fmt_cap_mplane(struct file *file, void *priv, struct v4l2_format *f) { struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; - struct hantro_ctx *ctx = fh_to_ctx(priv); + struct hantro_ctx *ctx = file_to_ctx(file); vpu_debug(4, "f->type = %d\n", f->type); @@ -398,13 +398,13 @@ static int hantro_try_fmt(const struct hantro_ctx *ctx, static int vidioc_try_fmt_cap_mplane(struct file *file, void *priv, struct v4l2_format *f) { - return hantro_try_fmt(fh_to_ctx(priv), &f->fmt.pix_mp, f->type); + return hantro_try_fmt(file_to_ctx(file), &f->fmt.pix_mp, f->type); } static int vidioc_try_fmt_out_mplane(struct file *file, void *priv, struct v4l2_format *f) { - return hantro_try_fmt(fh_to_ctx(priv), &f->fmt.pix_mp, f->type); + return hantro_try_fmt(file_to_ctx(file), &f->fmt.pix_mp, f->type); } static void @@ -648,23 +648,22 @@ static int hantro_set_fmt_cap(struct hantro_ctx *ctx, static int vidioc_s_fmt_out_mplane(struct file *file, void *priv, struct v4l2_format *f) { - return hantro_set_fmt_out(fh_to_ctx(priv), &f->fmt.pix_mp, HANTRO_AUTO_POSTPROC); + return hantro_set_fmt_out(file_to_ctx(file), &f->fmt.pix_mp, HANTRO_AUTO_POSTPROC); } static int vidioc_s_fmt_cap_mplane(struct file *file, void *priv, struct v4l2_format *f) { - return hantro_set_fmt_cap(fh_to_ctx(priv), &f->fmt.pix_mp); + return hantro_set_fmt_cap(file_to_ctx(file), &f->fmt.pix_mp); } static int vidioc_g_selection(struct file *file, void *priv, struct v4l2_selection *sel) { - struct hantro_ctx *ctx = fh_to_ctx(priv); + struct hantro_ctx *ctx = file_to_ctx(file); /* Crop only supported on source. */ - if (!ctx->is_encoder || - sel->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) + if (sel->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) return -EINVAL; switch (sel->target) { @@ -691,13 +690,12 @@ static int vidioc_g_selection(struct file *file, void *priv, static int vidioc_s_selection(struct file *file, void *priv, struct v4l2_selection *sel) { - struct hantro_ctx *ctx = fh_to_ctx(priv); + struct hantro_ctx *ctx = file_to_ctx(file); struct v4l2_rect *rect = &sel->r; struct vb2_queue *vq; /* Crop only supported on source. */ - if (!ctx->is_encoder || - sel->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) + if (sel->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) return -EINVAL; /* Change not allowed if the queue is streaming. */ @@ -738,7 +736,7 @@ static const struct v4l2_event hantro_eos_event = { static int vidioc_encoder_cmd(struct file *file, void *priv, struct v4l2_encoder_cmd *ec) { - struct hantro_ctx *ctx = fh_to_ctx(priv); + struct hantro_ctx *ctx = file_to_ctx(file); int ret; ret = v4l2_m2m_ioctl_try_encoder_cmd(file, priv, ec); diff --git a/drivers/media/platform/verisilicon/imx8m_vpu_hw.c b/drivers/media/platform/verisilicon/imx8m_vpu_hw.c index 35799da534ed..f9f276385c11 100644 --- a/drivers/media/platform/verisilicon/imx8m_vpu_hw.c +++ b/drivers/media/platform/verisilicon/imx8m_vpu_hw.c @@ -234,24 +234,6 @@ static const struct hantro_fmt imx8m_vpu_g2_dec_fmts[] = { }, }; -static irqreturn_t imx8m_vpu_g1_irq(int irq, void *dev_id) -{ - struct hantro_dev *vpu = dev_id; - enum vb2_buffer_state state; - u32 status; - - status = vdpu_read(vpu, G1_REG_INTERRUPT); - state = (status & G1_REG_INTERRUPT_DEC_RDY_INT) ? - VB2_BUF_STATE_DONE : VB2_BUF_STATE_ERROR; - - vdpu_write(vpu, 0, G1_REG_INTERRUPT); - vdpu_write(vpu, G1_REG_CONFIG_DEC_CLK_GATE_E, G1_REG_CONFIG); - - hantro_irq_done(vpu, state); - - return IRQ_HANDLED; -} - static int imx8mq_vpu_hw_init(struct hantro_dev *vpu) { vpu->ctrl_base = vpu->reg_bases[vpu->variant->num_regs - 1]; @@ -328,7 +310,7 @@ static const struct hantro_codec_ops imx8mq_vpu_g2_codec_ops[] = { */ static const struct hantro_irq imx8mq_irqs[] = { - { "g1", imx8m_vpu_g1_irq }, + { "g1", hantro_g1_irq }, }; static const struct hantro_irq imx8mq_g2_irqs[] = { diff --git a/drivers/media/platform/xilinx/xilinx-dma.c b/drivers/media/platform/xilinx/xilinx-dma.c index 18bfa6001909..fcfe0883aba5 100644 --- a/drivers/media/platform/xilinx/xilinx-dma.c +++ b/drivers/media/platform/xilinx/xilinx-dma.c @@ -469,7 +469,7 @@ static const struct vb2_ops xvip_dma_queue_qops = { static int xvip_dma_querycap(struct file *file, void *fh, struct v4l2_capability *cap) { - struct v4l2_fh *vfh = file->private_data; + struct v4l2_fh *vfh = file_to_v4l2_fh(file); struct xvip_dma *dma = to_xvip_dma(vfh->vdev); cap->capabilities = dma->xdev->v4l2_caps | V4L2_CAP_STREAMING | @@ -491,7 +491,7 @@ xvip_dma_querycap(struct file *file, void *fh, struct v4l2_capability *cap) static int xvip_dma_enum_format(struct file *file, void *fh, struct v4l2_fmtdesc *f) { - struct v4l2_fh *vfh = file->private_data; + struct v4l2_fh *vfh = file_to_v4l2_fh(file); struct xvip_dma *dma = to_xvip_dma(vfh->vdev); if (f->index > 0) @@ -505,7 +505,7 @@ xvip_dma_enum_format(struct file *file, void *fh, struct v4l2_fmtdesc *f) static int xvip_dma_get_format(struct file *file, void *fh, struct v4l2_format *format) { - struct v4l2_fh *vfh = file->private_data; + struct v4l2_fh *vfh = file_to_v4l2_fh(file); struct xvip_dma *dma = to_xvip_dma(vfh->vdev); format->fmt.pix = dma->format; @@ -565,7 +565,7 @@ __xvip_dma_try_format(struct xvip_dma *dma, struct v4l2_pix_format *pix, static int xvip_dma_try_format(struct file *file, void *fh, struct v4l2_format *format) { - struct v4l2_fh *vfh = file->private_data; + struct v4l2_fh *vfh = file_to_v4l2_fh(file); struct xvip_dma *dma = to_xvip_dma(vfh->vdev); __xvip_dma_try_format(dma, &format->fmt.pix, NULL); @@ -575,7 +575,7 @@ xvip_dma_try_format(struct file *file, void *fh, struct v4l2_format *format) static int xvip_dma_set_format(struct file *file, void *fh, struct v4l2_format *format) { - struct v4l2_fh *vfh = file->private_data; + struct v4l2_fh *vfh = file_to_v4l2_fh(file); struct xvip_dma *dma = to_xvip_dma(vfh->vdev); const struct xvip_video_format *info; |