xref: /linux/drivers/media/platform/chips-media/wave5/wave5-helper.c (revision 90d32e92011eaae8e70a9169b4e7acf4ca8f9d3a)
1 // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
2 /*
3  * Wave5 series multi-standard codec IP - decoder interface
4  *
5  * Copyright (C) 2021-2023 CHIPS&MEDIA INC
6  */
7 
8 #include "wave5-helper.h"
9 
10 const char *state_to_str(enum vpu_instance_state state)
11 {
12 	switch (state) {
13 	case VPU_INST_STATE_NONE:
14 		return "NONE";
15 	case VPU_INST_STATE_OPEN:
16 		return "OPEN";
17 	case VPU_INST_STATE_INIT_SEQ:
18 		return "INIT_SEQ";
19 	case VPU_INST_STATE_PIC_RUN:
20 		return "PIC_RUN";
21 	case VPU_INST_STATE_STOP:
22 		return "STOP";
23 	default:
24 		return "UNKNOWN";
25 	}
26 }
27 
28 void wave5_cleanup_instance(struct vpu_instance *inst)
29 {
30 	int i;
31 
32 	if (list_is_singular(&inst->list))
33 		wave5_vdi_free_sram(inst->dev);
34 
35 	for (i = 0; i < inst->fbc_buf_count; i++)
36 		wave5_vpu_dec_reset_framebuffer(inst, i);
37 
38 	wave5_vdi_free_dma_memory(inst->dev, &inst->bitstream_vbuf);
39 	v4l2_ctrl_handler_free(&inst->v4l2_ctrl_hdl);
40 	if (inst->v4l2_fh.vdev) {
41 		v4l2_fh_del(&inst->v4l2_fh);
42 		v4l2_fh_exit(&inst->v4l2_fh);
43 	}
44 	list_del_init(&inst->list);
45 	ida_free(&inst->dev->inst_ida, inst->id);
46 	kfree(inst->codec_info);
47 	kfree(inst);
48 }
49 
50 int wave5_vpu_release_device(struct file *filp,
51 			     int (*close_func)(struct vpu_instance *inst, u32 *fail_res),
52 			     char *name)
53 {
54 	struct vpu_instance *inst = wave5_to_vpu_inst(filp->private_data);
55 	struct vpu_device *dev = inst->dev;
56 	int ret = 0;
57 
58 	v4l2_m2m_ctx_release(inst->v4l2_fh.m2m_ctx);
59 	if (inst->state != VPU_INST_STATE_NONE) {
60 		u32 fail_res;
61 
62 		ret = close_func(inst, &fail_res);
63 		if (fail_res == WAVE5_SYSERR_VPU_STILL_RUNNING) {
64 			dev_err(inst->dev->dev, "%s close failed, device is still running\n",
65 				name);
66 			return -EBUSY;
67 		}
68 		if (ret && ret != -EIO) {
69 			dev_err(inst->dev->dev, "%s close, fail: %d\n", name, ret);
70 			return ret;
71 		}
72 	}
73 
74 	wave5_cleanup_instance(inst);
75 	if (dev->irq < 0) {
76 		ret = mutex_lock_interruptible(&dev->dev_lock);
77 		if (ret)
78 			return ret;
79 
80 		if (list_empty(&dev->instances)) {
81 			dev_dbg(dev->dev, "Disabling the hrtimer\n");
82 			hrtimer_cancel(&dev->hrtimer);
83 		}
84 
85 		mutex_unlock(&dev->dev_lock);
86 	}
87 
88 	return ret;
89 }
90 
91 int wave5_vpu_queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq,
92 			 const struct vb2_ops *ops)
93 {
94 	struct vpu_instance *inst = priv;
95 	int ret;
96 
97 	src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
98 	src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
99 	src_vq->mem_ops = &vb2_dma_contig_memops;
100 	src_vq->ops = ops;
101 	src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
102 	src_vq->buf_struct_size = sizeof(struct vpu_src_buffer);
103 	src_vq->drv_priv = inst;
104 	src_vq->lock = &inst->dev->dev_lock;
105 	src_vq->dev = inst->dev->v4l2_dev.dev;
106 	ret = vb2_queue_init(src_vq);
107 	if (ret)
108 		return ret;
109 
110 	dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
111 	dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
112 	dst_vq->mem_ops = &vb2_dma_contig_memops;
113 	dst_vq->ops = ops;
114 	dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
115 	dst_vq->buf_struct_size = sizeof(struct vpu_src_buffer);
116 	dst_vq->drv_priv = inst;
117 	dst_vq->lock = &inst->dev->dev_lock;
118 	dst_vq->dev = inst->dev->v4l2_dev.dev;
119 	ret = vb2_queue_init(dst_vq);
120 	if (ret)
121 		return ret;
122 
123 	return 0;
124 }
125 
126 int wave5_vpu_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subscription *sub)
127 {
128 	struct vpu_instance *inst = wave5_to_vpu_inst(fh);
129 	bool is_decoder = inst->type == VPU_INST_TYPE_DEC;
130 
131 	dev_dbg(inst->dev->dev, "%s: [%s] type: %u id: %u | flags: %u\n", __func__,
132 		is_decoder ? "decoder" : "encoder", sub->type, sub->id, sub->flags);
133 
134 	switch (sub->type) {
135 	case V4L2_EVENT_EOS:
136 		return v4l2_event_subscribe(fh, sub, 0, NULL);
137 	case V4L2_EVENT_SOURCE_CHANGE:
138 		if (is_decoder)
139 			return v4l2_src_change_event_subscribe(fh, sub);
140 		return -EINVAL;
141 	case V4L2_EVENT_CTRL:
142 		return v4l2_ctrl_subscribe_event(fh, sub);
143 	default:
144 		return -EINVAL;
145 	}
146 }
147 
148 int wave5_vpu_g_fmt_out(struct file *file, void *fh, struct v4l2_format *f)
149 {
150 	struct vpu_instance *inst = wave5_to_vpu_inst(fh);
151 	int i;
152 
153 	f->fmt.pix_mp.width = inst->src_fmt.width;
154 	f->fmt.pix_mp.height = inst->src_fmt.height;
155 	f->fmt.pix_mp.pixelformat = inst->src_fmt.pixelformat;
156 	f->fmt.pix_mp.field = inst->src_fmt.field;
157 	f->fmt.pix_mp.flags = inst->src_fmt.flags;
158 	f->fmt.pix_mp.num_planes = inst->src_fmt.num_planes;
159 	for (i = 0; i < f->fmt.pix_mp.num_planes; i++) {
160 		f->fmt.pix_mp.plane_fmt[i].bytesperline = inst->src_fmt.plane_fmt[i].bytesperline;
161 		f->fmt.pix_mp.plane_fmt[i].sizeimage = inst->src_fmt.plane_fmt[i].sizeimage;
162 	}
163 
164 	f->fmt.pix_mp.colorspace = inst->colorspace;
165 	f->fmt.pix_mp.ycbcr_enc = inst->ycbcr_enc;
166 	f->fmt.pix_mp.quantization = inst->quantization;
167 	f->fmt.pix_mp.xfer_func = inst->xfer_func;
168 
169 	return 0;
170 }
171 
172 const struct vpu_format *wave5_find_vpu_fmt(unsigned int v4l2_pix_fmt,
173 					    const struct vpu_format fmt_list[MAX_FMTS])
174 {
175 	unsigned int index;
176 
177 	for (index = 0; index < MAX_FMTS; index++) {
178 		if (fmt_list[index].v4l2_pix_fmt == v4l2_pix_fmt)
179 			return &fmt_list[index];
180 	}
181 
182 	return NULL;
183 }
184 
185 const struct vpu_format *wave5_find_vpu_fmt_by_idx(unsigned int idx,
186 						   const struct vpu_format fmt_list[MAX_FMTS])
187 {
188 	if (idx >= MAX_FMTS)
189 		return NULL;
190 
191 	if (!fmt_list[idx].v4l2_pix_fmt)
192 		return NULL;
193 
194 	return &fmt_list[idx];
195 }
196 
197 enum wave_std wave5_to_vpu_std(unsigned int v4l2_pix_fmt, enum vpu_instance_type type)
198 {
199 	switch (v4l2_pix_fmt) {
200 	case V4L2_PIX_FMT_H264:
201 		return type == VPU_INST_TYPE_DEC ? W_AVC_DEC : W_AVC_ENC;
202 	case V4L2_PIX_FMT_HEVC:
203 		return type == VPU_INST_TYPE_DEC ? W_HEVC_DEC : W_HEVC_ENC;
204 	default:
205 		return STD_UNKNOWN;
206 	}
207 }
208 
209 void wave5_return_bufs(struct vb2_queue *q, u32 state)
210 {
211 	struct vpu_instance *inst = vb2_get_drv_priv(q);
212 	struct v4l2_m2m_ctx *m2m_ctx = inst->v4l2_fh.m2m_ctx;
213 	struct v4l2_ctrl_handler v4l2_ctrl_hdl = inst->v4l2_ctrl_hdl;
214 	struct vb2_v4l2_buffer *vbuf;
215 
216 	for (;;) {
217 		if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
218 			vbuf = v4l2_m2m_src_buf_remove(m2m_ctx);
219 		else
220 			vbuf = v4l2_m2m_dst_buf_remove(m2m_ctx);
221 		if (!vbuf)
222 			return;
223 		v4l2_ctrl_request_complete(vbuf->vb2_buf.req_obj.req, &v4l2_ctrl_hdl);
224 		v4l2_m2m_buf_done(vbuf, state);
225 	}
226 }
227