1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
4 */
5
6 #include <linux/pm_runtime.h>
7 #include <media/v4l2-event.h>
8 #include <media/v4l2-ioctl.h>
9 #include <media/v4l2-mem2mem.h>
10 #include <media/videobuf2-dma-contig.h>
11
12 #include "iris_vidc.h"
13 #include "iris_instance.h"
14 #include "iris_vdec.h"
15 #include "iris_vb2.h"
16 #include "iris_vpu_buffer.h"
17 #include "iris_platform_common.h"
18
19 #define IRIS_DRV_NAME "iris_driver"
20 #define IRIS_BUS_NAME "platform:iris_icc"
21 #define STEP_WIDTH 1
22 #define STEP_HEIGHT 1
23
iris_v4l2_fh_init(struct iris_inst * inst)24 static void iris_v4l2_fh_init(struct iris_inst *inst)
25 {
26 v4l2_fh_init(&inst->fh, inst->core->vdev_dec);
27 inst->fh.ctrl_handler = &inst->ctrl_handler;
28 v4l2_fh_add(&inst->fh);
29 }
30
iris_v4l2_fh_deinit(struct iris_inst * inst)31 static void iris_v4l2_fh_deinit(struct iris_inst *inst)
32 {
33 v4l2_fh_del(&inst->fh);
34 inst->fh.ctrl_handler = NULL;
35 v4l2_fh_exit(&inst->fh);
36 }
37
iris_add_session(struct iris_inst * inst)38 static void iris_add_session(struct iris_inst *inst)
39 {
40 struct iris_core *core = inst->core;
41 struct iris_inst *iter;
42 u32 count = 0;
43
44 mutex_lock(&core->lock);
45
46 list_for_each_entry(iter, &core->instances, list)
47 count++;
48
49 if (count < core->iris_platform_data->max_session_count)
50 list_add_tail(&inst->list, &core->instances);
51
52 mutex_unlock(&core->lock);
53 }
54
iris_remove_session(struct iris_inst * inst)55 static void iris_remove_session(struct iris_inst *inst)
56 {
57 struct iris_core *core = inst->core;
58 struct iris_inst *iter, *temp;
59
60 mutex_lock(&core->lock);
61 list_for_each_entry_safe(iter, temp, &core->instances, list) {
62 if (iter->session_id == inst->session_id) {
63 list_del_init(&iter->list);
64 break;
65 }
66 }
67 mutex_unlock(&core->lock);
68 }
69
iris_get_inst(struct file * filp,void * fh)70 static inline struct iris_inst *iris_get_inst(struct file *filp, void *fh)
71 {
72 return container_of(filp->private_data, struct iris_inst, fh);
73 }
74
iris_m2m_device_run(void * priv)75 static void iris_m2m_device_run(void *priv)
76 {
77 }
78
iris_m2m_job_abort(void * priv)79 static void iris_m2m_job_abort(void *priv)
80 {
81 struct iris_inst *inst = priv;
82 struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx;
83
84 v4l2_m2m_job_finish(inst->m2m_dev, m2m_ctx);
85 }
86
87 static const struct v4l2_m2m_ops iris_m2m_ops = {
88 .device_run = iris_m2m_device_run,
89 .job_abort = iris_m2m_job_abort,
90 };
91
92 static int
iris_m2m_queue_init(void * priv,struct vb2_queue * src_vq,struct vb2_queue * dst_vq)93 iris_m2m_queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq)
94 {
95 struct iris_inst *inst = priv;
96 int ret;
97
98 src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
99 src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
100 src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
101 src_vq->ops = inst->core->iris_vb2_ops;
102 src_vq->mem_ops = &vb2_dma_contig_memops;
103 src_vq->drv_priv = inst;
104 src_vq->buf_struct_size = sizeof(struct iris_buffer);
105 src_vq->min_reqbufs_allocation = MIN_BUFFERS;
106 src_vq->dev = inst->core->dev;
107 src_vq->lock = &inst->ctx_q_lock;
108 ret = vb2_queue_init(src_vq);
109 if (ret)
110 return ret;
111
112 dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
113 dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
114 dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
115 dst_vq->ops = inst->core->iris_vb2_ops;
116 dst_vq->mem_ops = &vb2_dma_contig_memops;
117 dst_vq->drv_priv = inst;
118 dst_vq->buf_struct_size = sizeof(struct iris_buffer);
119 dst_vq->min_reqbufs_allocation = MIN_BUFFERS;
120 dst_vq->dev = inst->core->dev;
121 dst_vq->lock = &inst->ctx_q_lock;
122
123 return vb2_queue_init(dst_vq);
124 }
125
iris_open(struct file * filp)126 int iris_open(struct file *filp)
127 {
128 struct iris_core *core = video_drvdata(filp);
129 struct iris_inst *inst;
130 int ret;
131
132 ret = pm_runtime_resume_and_get(core->dev);
133 if (ret < 0)
134 return ret;
135
136 ret = iris_core_init(core);
137 if (ret) {
138 dev_err(core->dev, "core init failed\n");
139 pm_runtime_put_sync(core->dev);
140 return ret;
141 }
142
143 pm_runtime_put_sync(core->dev);
144
145 inst = core->iris_platform_data->get_instance();
146 if (!inst)
147 return -ENOMEM;
148
149 inst->core = core;
150 inst->session_id = hash32_ptr(inst);
151 inst->state = IRIS_INST_DEINIT;
152
153 mutex_init(&inst->lock);
154 mutex_init(&inst->ctx_q_lock);
155
156 INIT_LIST_HEAD(&inst->buffers[BUF_BIN].list);
157 INIT_LIST_HEAD(&inst->buffers[BUF_ARP].list);
158 INIT_LIST_HEAD(&inst->buffers[BUF_COMV].list);
159 INIT_LIST_HEAD(&inst->buffers[BUF_NON_COMV].list);
160 INIT_LIST_HEAD(&inst->buffers[BUF_LINE].list);
161 INIT_LIST_HEAD(&inst->buffers[BUF_DPB].list);
162 INIT_LIST_HEAD(&inst->buffers[BUF_PERSIST].list);
163 INIT_LIST_HEAD(&inst->buffers[BUF_SCRATCH_1].list);
164 init_completion(&inst->completion);
165 init_completion(&inst->flush_completion);
166
167 iris_v4l2_fh_init(inst);
168
169 inst->m2m_dev = v4l2_m2m_init(&iris_m2m_ops);
170 if (IS_ERR_OR_NULL(inst->m2m_dev)) {
171 ret = -EINVAL;
172 goto fail_v4l2_fh_deinit;
173 }
174
175 inst->m2m_ctx = v4l2_m2m_ctx_init(inst->m2m_dev, inst, iris_m2m_queue_init);
176 if (IS_ERR_OR_NULL(inst->m2m_ctx)) {
177 ret = -EINVAL;
178 goto fail_m2m_release;
179 }
180
181 ret = iris_vdec_inst_init(inst);
182 if (ret)
183 goto fail_m2m_ctx_release;
184
185 iris_add_session(inst);
186
187 inst->fh.m2m_ctx = inst->m2m_ctx;
188 filp->private_data = &inst->fh;
189
190 return 0;
191
192 fail_m2m_ctx_release:
193 v4l2_m2m_ctx_release(inst->m2m_ctx);
194 fail_m2m_release:
195 v4l2_m2m_release(inst->m2m_dev);
196 fail_v4l2_fh_deinit:
197 iris_v4l2_fh_deinit(inst);
198 mutex_destroy(&inst->ctx_q_lock);
199 mutex_destroy(&inst->lock);
200 kfree(inst);
201
202 return ret;
203 }
204
iris_session_close(struct iris_inst * inst)205 static void iris_session_close(struct iris_inst *inst)
206 {
207 const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops;
208 bool wait_for_response = true;
209 int ret;
210
211 if (inst->state == IRIS_INST_DEINIT)
212 return;
213
214 reinit_completion(&inst->completion);
215
216 ret = hfi_ops->session_close(inst);
217 if (ret)
218 wait_for_response = false;
219
220 if (wait_for_response)
221 iris_wait_for_session_response(inst, false);
222 }
223
iris_close(struct file * filp)224 int iris_close(struct file *filp)
225 {
226 struct iris_inst *inst = iris_get_inst(filp, NULL);
227
228 v4l2_ctrl_handler_free(&inst->ctrl_handler);
229 v4l2_m2m_ctx_release(inst->m2m_ctx);
230 v4l2_m2m_release(inst->m2m_dev);
231 mutex_lock(&inst->lock);
232 iris_vdec_inst_deinit(inst);
233 iris_session_close(inst);
234 iris_inst_change_state(inst, IRIS_INST_DEINIT);
235 iris_v4l2_fh_deinit(inst);
236 iris_destroy_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
237 iris_destroy_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
238 iris_remove_session(inst);
239 mutex_unlock(&inst->lock);
240 mutex_destroy(&inst->ctx_q_lock);
241 mutex_destroy(&inst->lock);
242 kfree(inst);
243 filp->private_data = NULL;
244
245 return 0;
246 }
247
iris_enum_fmt(struct file * filp,void * fh,struct v4l2_fmtdesc * f)248 static int iris_enum_fmt(struct file *filp, void *fh, struct v4l2_fmtdesc *f)
249 {
250 struct iris_inst *inst = iris_get_inst(filp, NULL);
251
252 if (f->index)
253 return -EINVAL;
254
255 return iris_vdec_enum_fmt(inst, f);
256 }
257
iris_try_fmt_vid_mplane(struct file * filp,void * fh,struct v4l2_format * f)258 static int iris_try_fmt_vid_mplane(struct file *filp, void *fh, struct v4l2_format *f)
259 {
260 struct iris_inst *inst = iris_get_inst(filp, NULL);
261 int ret;
262
263 mutex_lock(&inst->lock);
264 ret = iris_vdec_try_fmt(inst, f);
265 mutex_unlock(&inst->lock);
266
267 return ret;
268 }
269
iris_s_fmt_vid_mplane(struct file * filp,void * fh,struct v4l2_format * f)270 static int iris_s_fmt_vid_mplane(struct file *filp, void *fh, struct v4l2_format *f)
271 {
272 struct iris_inst *inst = iris_get_inst(filp, NULL);
273 int ret;
274
275 mutex_lock(&inst->lock);
276 ret = iris_vdec_s_fmt(inst, f);
277 mutex_unlock(&inst->lock);
278
279 return ret;
280 }
281
iris_g_fmt_vid_mplane(struct file * filp,void * fh,struct v4l2_format * f)282 static int iris_g_fmt_vid_mplane(struct file *filp, void *fh, struct v4l2_format *f)
283 {
284 struct iris_inst *inst = iris_get_inst(filp, NULL);
285 int ret = 0;
286
287 mutex_lock(&inst->lock);
288 if (V4L2_TYPE_IS_OUTPUT(f->type))
289 *f = *inst->fmt_src;
290 else if (V4L2_TYPE_IS_CAPTURE(f->type))
291 *f = *inst->fmt_dst;
292 else
293 ret = -EINVAL;
294
295 mutex_unlock(&inst->lock);
296
297 return ret;
298 }
299
iris_enum_framesizes(struct file * filp,void * fh,struct v4l2_frmsizeenum * fsize)300 static int iris_enum_framesizes(struct file *filp, void *fh,
301 struct v4l2_frmsizeenum *fsize)
302 {
303 struct iris_inst *inst = iris_get_inst(filp, NULL);
304 struct platform_inst_caps *caps;
305
306 if (fsize->index)
307 return -EINVAL;
308
309 if (fsize->pixel_format != V4L2_PIX_FMT_H264 &&
310 fsize->pixel_format != V4L2_PIX_FMT_NV12)
311 return -EINVAL;
312
313 caps = inst->core->iris_platform_data->inst_caps;
314
315 fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
316 fsize->stepwise.min_width = caps->min_frame_width;
317 fsize->stepwise.max_width = caps->max_frame_width;
318 fsize->stepwise.step_width = STEP_WIDTH;
319 fsize->stepwise.min_height = caps->min_frame_height;
320 fsize->stepwise.max_height = caps->max_frame_height;
321 fsize->stepwise.step_height = STEP_HEIGHT;
322
323 return 0;
324 }
325
iris_querycap(struct file * filp,void * fh,struct v4l2_capability * cap)326 static int iris_querycap(struct file *filp, void *fh, struct v4l2_capability *cap)
327 {
328 strscpy(cap->driver, IRIS_DRV_NAME, sizeof(cap->driver));
329 strscpy(cap->card, "Iris Decoder", sizeof(cap->card));
330
331 return 0;
332 }
333
iris_g_selection(struct file * filp,void * fh,struct v4l2_selection * s)334 static int iris_g_selection(struct file *filp, void *fh, struct v4l2_selection *s)
335 {
336 struct iris_inst *inst = iris_get_inst(filp, NULL);
337
338 if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
339 return -EINVAL;
340
341 switch (s->target) {
342 case V4L2_SEL_TGT_CROP_BOUNDS:
343 case V4L2_SEL_TGT_CROP_DEFAULT:
344 case V4L2_SEL_TGT_CROP:
345 case V4L2_SEL_TGT_COMPOSE_BOUNDS:
346 case V4L2_SEL_TGT_COMPOSE_PADDED:
347 case V4L2_SEL_TGT_COMPOSE_DEFAULT:
348 case V4L2_SEL_TGT_COMPOSE:
349 s->r.left = inst->crop.left;
350 s->r.top = inst->crop.top;
351 s->r.width = inst->crop.width;
352 s->r.height = inst->crop.height;
353 break;
354 default:
355 return -EINVAL;
356 }
357
358 return 0;
359 }
360
iris_subscribe_event(struct v4l2_fh * fh,const struct v4l2_event_subscription * sub)361 static int iris_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subscription *sub)
362 {
363 struct iris_inst *inst = container_of(fh, struct iris_inst, fh);
364
365 return iris_vdec_subscribe_event(inst, sub);
366 }
367
iris_dec_cmd(struct file * filp,void * fh,struct v4l2_decoder_cmd * dec)368 static int iris_dec_cmd(struct file *filp, void *fh,
369 struct v4l2_decoder_cmd *dec)
370 {
371 struct iris_inst *inst = iris_get_inst(filp, NULL);
372 int ret = 0;
373
374 mutex_lock(&inst->lock);
375
376 ret = v4l2_m2m_ioctl_decoder_cmd(filp, fh, dec);
377 if (ret)
378 goto unlock;
379
380 if (inst->state == IRIS_INST_DEINIT)
381 goto unlock;
382
383 if (!iris_allow_cmd(inst, dec->cmd)) {
384 ret = -EBUSY;
385 goto unlock;
386 }
387
388 if (dec->cmd == V4L2_DEC_CMD_START)
389 ret = iris_vdec_start_cmd(inst);
390 else if (dec->cmd == V4L2_DEC_CMD_STOP)
391 ret = iris_vdec_stop_cmd(inst);
392 else
393 ret = -EINVAL;
394
395 unlock:
396 mutex_unlock(&inst->lock);
397
398 return ret;
399 }
400
401 static struct v4l2_file_operations iris_v4l2_file_ops = {
402 .owner = THIS_MODULE,
403 .open = iris_open,
404 .release = iris_close,
405 .unlocked_ioctl = video_ioctl2,
406 .poll = v4l2_m2m_fop_poll,
407 .mmap = v4l2_m2m_fop_mmap,
408 };
409
410 static const struct vb2_ops iris_vb2_ops = {
411 .buf_init = iris_vb2_buf_init,
412 .queue_setup = iris_vb2_queue_setup,
413 .start_streaming = iris_vb2_start_streaming,
414 .stop_streaming = iris_vb2_stop_streaming,
415 .buf_prepare = iris_vb2_buf_prepare,
416 .buf_out_validate = iris_vb2_buf_out_validate,
417 .buf_queue = iris_vb2_buf_queue,
418 };
419
420 static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops = {
421 .vidioc_enum_fmt_vid_cap = iris_enum_fmt,
422 .vidioc_enum_fmt_vid_out = iris_enum_fmt,
423 .vidioc_try_fmt_vid_cap_mplane = iris_try_fmt_vid_mplane,
424 .vidioc_try_fmt_vid_out_mplane = iris_try_fmt_vid_mplane,
425 .vidioc_s_fmt_vid_cap_mplane = iris_s_fmt_vid_mplane,
426 .vidioc_s_fmt_vid_out_mplane = iris_s_fmt_vid_mplane,
427 .vidioc_g_fmt_vid_cap_mplane = iris_g_fmt_vid_mplane,
428 .vidioc_g_fmt_vid_out_mplane = iris_g_fmt_vid_mplane,
429 .vidioc_enum_framesizes = iris_enum_framesizes,
430 .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs,
431 .vidioc_querybuf = v4l2_m2m_ioctl_querybuf,
432 .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs,
433 .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf,
434 .vidioc_expbuf = v4l2_m2m_ioctl_expbuf,
435 .vidioc_qbuf = v4l2_m2m_ioctl_qbuf,
436 .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf,
437 .vidioc_remove_bufs = v4l2_m2m_ioctl_remove_bufs,
438 .vidioc_querycap = iris_querycap,
439 .vidioc_g_selection = iris_g_selection,
440 .vidioc_subscribe_event = iris_subscribe_event,
441 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
442 .vidioc_streamon = v4l2_m2m_ioctl_streamon,
443 .vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
444 .vidioc_try_decoder_cmd = v4l2_m2m_ioctl_try_decoder_cmd,
445 .vidioc_decoder_cmd = iris_dec_cmd,
446 };
447
iris_init_ops(struct iris_core * core)448 void iris_init_ops(struct iris_core *core)
449 {
450 core->iris_v4l2_file_ops = &iris_v4l2_file_ops;
451 core->iris_vb2_ops = &iris_vb2_ops;
452 core->iris_v4l2_ioctl_ops = &iris_v4l2_ioctl_ops;
453 }
454