1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2016 MediaTek Inc.
4  * Author: PoChun Lin <pochun.lin@mediatek.com>
5  */
6 
7 #include "mtk_vcodec_enc_drv.h"
8 #include "venc_ipi_msg.h"
9 #include "venc_vpu_if.h"
10 
11 static void handle_enc_init_msg(struct venc_vpu_inst *vpu, const void *data)
12 {
13 	const struct venc_vpu_ipi_msg_init *msg = data;
14 
15 	vpu->inst_addr = msg->vpu_inst_addr;
16 	vpu->vsi = mtk_vcodec_fw_map_dm_addr(vpu->ctx->dev->fw_handler,
17 					     msg->vpu_inst_addr);
18 
19 	/* Firmware version field value is unspecified on MT8173. */
20 	if (mtk_vcodec_fw_get_type(vpu->ctx->dev->fw_handler) == VPU)
21 		return;
22 
23 	/* Check firmware version. */
24 	mtk_venc_debug(vpu->ctx, "firmware version: 0x%x\n", msg->venc_abi_version);
25 	switch (msg->venc_abi_version) {
26 	case 1:
27 		break;
28 	default:
29 		mtk_venc_err(vpu->ctx, "unhandled firmware version 0x%x\n",
30 			     msg->venc_abi_version);
31 		vpu->failure = 1;
32 		break;
33 	}
34 }
35 
36 static void handle_enc_encode_msg(struct venc_vpu_inst *vpu, const void *data)
37 {
38 	const struct venc_vpu_ipi_msg_enc *msg = data;
39 
40 	vpu->state = msg->state;
41 	vpu->bs_size = msg->bs_size;
42 	vpu->is_key_frm = msg->is_key_frm;
43 }
44 
45 static bool vpu_enc_check_ap_inst(struct mtk_vcodec_enc_dev *enc_dev, struct venc_vpu_inst *vpu)
46 {
47 	struct mtk_vcodec_enc_ctx *ctx;
48 	int ret = false;
49 
50 	mutex_lock(&enc_dev->dev_ctx_lock);
51 	list_for_each_entry(ctx, &enc_dev->ctx_list, list) {
52 		if (!IS_ERR_OR_NULL(ctx) && ctx->vpu_inst == vpu) {
53 			ret = true;
54 			break;
55 		}
56 	}
57 	mutex_unlock(&enc_dev->dev_ctx_lock);
58 
59 	return ret;
60 }
61 
62 static void vpu_enc_ipi_handler(void *data, unsigned int len, void *priv)
63 {
64 	struct mtk_vcodec_enc_dev *enc_dev;
65 	const struct venc_vpu_ipi_msg_common *msg = data;
66 	struct venc_vpu_inst *vpu;
67 
68 	enc_dev = (struct mtk_vcodec_enc_dev *)priv;
69 	vpu = (struct venc_vpu_inst *)(unsigned long)msg->venc_inst;
70 	if (!priv || !vpu) {
71 		pr_err(MTK_DBG_V4L2_STR "venc_inst is NULL, did the SCP hang or crash?");
72 		return;
73 	}
74 
75 	mtk_venc_debug(vpu->ctx, "msg_id %x inst %p status %d", msg->msg_id, vpu, msg->status);
76 	if (!vpu_enc_check_ap_inst(enc_dev, vpu) || msg->msg_id < VPU_IPIMSG_ENC_INIT_DONE ||
77 	    msg->msg_id > VPU_IPIMSG_ENC_DEINIT_DONE) {
78 		mtk_v4l2_venc_err(vpu->ctx, "venc msg id not correctly => 0x%x", msg->msg_id);
79 		vpu->failure = -EINVAL;
80 		goto error;
81 	}
82 
83 	vpu->failure = (msg->status != VENC_IPI_MSG_STATUS_OK);
84 	if (vpu->failure) {
85 		mtk_venc_err(vpu->ctx, "vpu enc status failure %d", vpu->failure);
86 		goto error;
87 	}
88 
89 	switch (msg->msg_id) {
90 	case VPU_IPIMSG_ENC_INIT_DONE:
91 		handle_enc_init_msg(vpu, data);
92 		break;
93 	case VPU_IPIMSG_ENC_SET_PARAM_DONE:
94 		break;
95 	case VPU_IPIMSG_ENC_ENCODE_DONE:
96 		handle_enc_encode_msg(vpu, data);
97 		break;
98 	case VPU_IPIMSG_ENC_DEINIT_DONE:
99 		break;
100 	default:
101 		mtk_venc_err(vpu->ctx, "unknown msg id %x", msg->msg_id);
102 		break;
103 	}
104 
105 error:
106 	vpu->signaled = 1;
107 }
108 
109 static int vpu_enc_send_msg(struct venc_vpu_inst *vpu, void *msg,
110 			    int len)
111 {
112 	int status;
113 
114 	if (!vpu->ctx->dev->fw_handler) {
115 		mtk_venc_err(vpu->ctx, "inst dev is NULL");
116 		return -EINVAL;
117 	}
118 
119 	status = mtk_vcodec_fw_ipi_send(vpu->ctx->dev->fw_handler, vpu->id, msg,
120 					len, 2000);
121 	if (status) {
122 		mtk_venc_err(vpu->ctx, "vpu_ipi_send msg_id %x len %d fail %d",
123 			     *(uint32_t *)msg, len, status);
124 		return -EINVAL;
125 	}
126 	if (vpu->failure)
127 		return -EINVAL;
128 
129 	return 0;
130 }
131 
132 int vpu_enc_init(struct venc_vpu_inst *vpu)
133 {
134 	int status;
135 	struct venc_ap_ipi_msg_init out;
136 
137 	init_waitqueue_head(&vpu->wq_hd);
138 	vpu->signaled = 0;
139 	vpu->failure = 0;
140 	vpu->ctx->vpu_inst = vpu;
141 
142 	status = mtk_vcodec_fw_ipi_register(vpu->ctx->dev->fw_handler, vpu->id,
143 					    vpu_enc_ipi_handler, "venc",
144 					    vpu->ctx->dev);
145 
146 	if (status) {
147 		mtk_venc_err(vpu->ctx, "vpu_ipi_register fail %d", status);
148 		return -EINVAL;
149 	}
150 
151 	memset(&out, 0, sizeof(out));
152 	out.msg_id = AP_IPIMSG_ENC_INIT;
153 	out.venc_inst = (unsigned long)vpu;
154 	if (vpu_enc_send_msg(vpu, &out, sizeof(out))) {
155 		mtk_venc_err(vpu->ctx, "AP_IPIMSG_ENC_INIT fail");
156 		return -EINVAL;
157 	}
158 
159 	if (IS_ERR_OR_NULL(vpu->vsi)) {
160 		mtk_venc_err(vpu->ctx, "invalid venc vsi");
161 		return -EINVAL;
162 	}
163 
164 	return 0;
165 }
166 
167 static unsigned int venc_enc_param_crop_right(struct venc_vpu_inst *vpu,
168 					      struct venc_enc_param *enc_prm)
169 {
170 	unsigned int img_crop_right = enc_prm->buf_width - enc_prm->width;
171 
172 	return img_crop_right % 16;
173 }
174 
175 static unsigned int venc_enc_param_crop_bottom(struct venc_enc_param *enc_prm)
176 {
177 	return round_up(enc_prm->height, 16) - enc_prm->height;
178 }
179 
180 static unsigned int venc_enc_param_num_mb(struct venc_enc_param *enc_prm)
181 {
182 	return DIV_ROUND_UP(enc_prm->width, 16) *
183 	       DIV_ROUND_UP(enc_prm->height, 16);
184 }
185 
186 int vpu_enc_set_param(struct venc_vpu_inst *vpu,
187 		      enum venc_set_param_type id,
188 		      struct venc_enc_param *enc_param)
189 {
190 	const bool is_ext = MTK_ENC_CTX_IS_EXT(vpu->ctx);
191 	size_t msg_size = is_ext ?
192 		sizeof(struct venc_ap_ipi_msg_set_param_ext) :
193 		sizeof(struct venc_ap_ipi_msg_set_param);
194 	struct venc_ap_ipi_msg_set_param_ext out;
195 
196 	mtk_venc_debug(vpu->ctx, "id %d ->", id);
197 
198 	memset(&out, 0, sizeof(out));
199 	out.base.msg_id = AP_IPIMSG_ENC_SET_PARAM;
200 	out.base.vpu_inst_addr = vpu->inst_addr;
201 	out.base.param_id = id;
202 	switch (id) {
203 	case VENC_SET_PARAM_ENC:
204 		if (is_ext) {
205 			out.base.data_item = 3;
206 			out.base.data[0] =
207 				venc_enc_param_crop_right(vpu, enc_param);
208 			out.base.data[1] =
209 				venc_enc_param_crop_bottom(enc_param);
210 			out.base.data[2] = venc_enc_param_num_mb(enc_param);
211 		} else {
212 			out.base.data_item = 0;
213 		}
214 		break;
215 	case VENC_SET_PARAM_FORCE_INTRA:
216 		out.base.data_item = 0;
217 		break;
218 	case VENC_SET_PARAM_ADJUST_BITRATE:
219 		out.base.data_item = 1;
220 		out.base.data[0] = enc_param->bitrate;
221 		break;
222 	case VENC_SET_PARAM_ADJUST_FRAMERATE:
223 		out.base.data_item = 1;
224 		out.base.data[0] = enc_param->frm_rate;
225 		break;
226 	case VENC_SET_PARAM_GOP_SIZE:
227 		out.base.data_item = 1;
228 		out.base.data[0] = enc_param->gop_size;
229 		break;
230 	case VENC_SET_PARAM_INTRA_PERIOD:
231 		out.base.data_item = 1;
232 		out.base.data[0] = enc_param->intra_period;
233 		break;
234 	case VENC_SET_PARAM_SKIP_FRAME:
235 		out.base.data_item = 0;
236 		break;
237 	default:
238 		mtk_venc_err(vpu->ctx, "id %d not supported", id);
239 		return -EINVAL;
240 	}
241 	if (vpu_enc_send_msg(vpu, &out, msg_size)) {
242 		mtk_venc_err(vpu->ctx, "AP_IPIMSG_ENC_SET_PARAM %d fail", id);
243 		return -EINVAL;
244 	}
245 
246 	mtk_venc_debug(vpu->ctx, "id %d <-", id);
247 
248 	return 0;
249 }
250 
251 static int vpu_enc_encode_32bits(struct venc_vpu_inst *vpu,
252 				 unsigned int bs_mode,
253 				 struct venc_frm_buf *frm_buf,
254 				 struct mtk_vcodec_mem *bs_buf,
255 				 struct venc_frame_info *frame_info)
256 {
257 	const bool is_ext = MTK_ENC_CTX_IS_EXT(vpu->ctx);
258 	size_t msg_size = is_ext ?
259 		sizeof(struct venc_ap_ipi_msg_enc_ext) :
260 		sizeof(struct venc_ap_ipi_msg_enc);
261 	struct venc_ap_ipi_msg_enc_ext out;
262 
263 	mtk_venc_debug(vpu->ctx, "bs_mode %d ->", bs_mode);
264 
265 	memset(&out, 0, sizeof(out));
266 	out.base.msg_id = AP_IPIMSG_ENC_ENCODE;
267 	out.base.vpu_inst_addr = vpu->inst_addr;
268 	out.base.bs_mode = bs_mode;
269 	if (frm_buf) {
270 		if ((frm_buf->fb_addr[0].dma_addr % 16 == 0) &&
271 		    (frm_buf->fb_addr[1].dma_addr % 16 == 0) &&
272 		    (frm_buf->fb_addr[2].dma_addr % 16 == 0)) {
273 			out.base.input_addr[0] = frm_buf->fb_addr[0].dma_addr;
274 			out.base.input_addr[1] = frm_buf->fb_addr[1].dma_addr;
275 			out.base.input_addr[2] = frm_buf->fb_addr[2].dma_addr;
276 		} else {
277 			mtk_venc_err(vpu->ctx, "dma_addr not align to 16");
278 			return -EINVAL;
279 		}
280 	}
281 	if (bs_buf) {
282 		out.base.bs_addr = bs_buf->dma_addr;
283 		out.base.bs_size = bs_buf->size;
284 	}
285 	if (is_ext && frame_info) {
286 		out.data_item = 3;
287 		out.data[0] = frame_info->frm_count;
288 		out.data[1] = frame_info->skip_frm_count;
289 		out.data[2] = frame_info->frm_type;
290 	}
291 	if (vpu_enc_send_msg(vpu, &out, msg_size)) {
292 		mtk_venc_err(vpu->ctx, "AP_IPIMSG_ENC_ENCODE %d fail", bs_mode);
293 		return -EINVAL;
294 	}
295 
296 	return 0;
297 }
298 
299 static int vpu_enc_encode_34bits(struct venc_vpu_inst *vpu,
300 				 unsigned int bs_mode,
301 				 struct venc_frm_buf *frm_buf,
302 				 struct mtk_vcodec_mem *bs_buf,
303 				 struct venc_frame_info *frame_info)
304 {
305 	struct venc_ap_ipi_msg_enc_ext_34 out;
306 	size_t msg_size = sizeof(struct venc_ap_ipi_msg_enc_ext_34);
307 
308 	mtk_venc_debug(vpu->ctx, "bs_mode %d ->", bs_mode);
309 
310 	memset(&out, 0, sizeof(out));
311 	out.msg_id = AP_IPIMSG_ENC_ENCODE;
312 	out.vpu_inst_addr = vpu->inst_addr;
313 	out.bs_mode = bs_mode;
314 
315 	if (frm_buf) {
316 		if ((frm_buf->fb_addr[0].dma_addr % 16 == 0) &&
317 		    (frm_buf->fb_addr[1].dma_addr % 16 == 0) &&
318 		    (frm_buf->fb_addr[2].dma_addr % 16 == 0)) {
319 			out.input_addr[0] = frm_buf->fb_addr[0].dma_addr;
320 			out.input_addr[1] = frm_buf->fb_addr[1].dma_addr;
321 			out.input_addr[2] = frm_buf->fb_addr[2].dma_addr;
322 		} else {
323 			mtk_venc_err(vpu->ctx, "dma_addr not align to 16");
324 			return -EINVAL;
325 		}
326 	}
327 	if (bs_buf) {
328 		out.bs_addr = bs_buf->dma_addr;
329 		out.bs_size = bs_buf->size;
330 	}
331 	if (frame_info) {
332 		out.data_item = 3;
333 		out.data[0] = frame_info->frm_count;
334 		out.data[1] = frame_info->skip_frm_count;
335 		out.data[2] = frame_info->frm_type;
336 	}
337 	if (vpu_enc_send_msg(vpu, &out, msg_size)) {
338 		mtk_venc_err(vpu->ctx, "AP_IPIMSG_ENC_ENCODE %d fail", bs_mode);
339 		return -EINVAL;
340 	}
341 
342 	return 0;
343 }
344 
345 int vpu_enc_encode(struct venc_vpu_inst *vpu, unsigned int bs_mode,
346 		   struct venc_frm_buf *frm_buf,
347 		   struct mtk_vcodec_mem *bs_buf,
348 		   struct venc_frame_info *frame_info)
349 {
350 	int ret;
351 
352 	if (MTK_ENC_IOVA_IS_34BIT(vpu->ctx))
353 		ret = vpu_enc_encode_34bits(vpu, bs_mode,
354 					    frm_buf, bs_buf, frame_info);
355 	else
356 		ret = vpu_enc_encode_32bits(vpu, bs_mode,
357 					    frm_buf, bs_buf, frame_info);
358 
359 	if (ret)
360 		return ret;
361 
362 	mtk_venc_debug(vpu->ctx, "bs_mode %d state %d size %d key_frm %d <-",
363 		       bs_mode, vpu->state, vpu->bs_size, vpu->is_key_frm);
364 
365 	return 0;
366 }
367 
368 int vpu_enc_deinit(struct venc_vpu_inst *vpu)
369 {
370 	struct venc_ap_ipi_msg_deinit out;
371 
372 	memset(&out, 0, sizeof(out));
373 	out.msg_id = AP_IPIMSG_ENC_DEINIT;
374 	out.vpu_inst_addr = vpu->inst_addr;
375 	if (vpu_enc_send_msg(vpu, &out, sizeof(out))) {
376 		mtk_venc_err(vpu->ctx, "AP_IPIMSG_ENC_DEINIT fail");
377 		return -EINVAL;
378 	}
379 
380 	return 0;
381 }
382