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