• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_vpu.h"
8 #include "venc_ipi_msg.h"
9 #include "venc_vpu_if.h"
10 
handle_enc_init_msg(struct venc_vpu_inst * vpu,void * data)11 static void handle_enc_init_msg(struct venc_vpu_inst *vpu, void *data)
12 {
13 	struct venc_vpu_ipi_msg_init *msg = data;
14 
15 	vpu->inst_addr = msg->vpu_inst_addr;
16 	vpu->vsi = vpu_mapping_dm_addr(vpu->dev, msg->vpu_inst_addr);
17 }
18 
handle_enc_encode_msg(struct venc_vpu_inst * vpu,void * data)19 static void handle_enc_encode_msg(struct venc_vpu_inst *vpu, void *data)
20 {
21 	struct venc_vpu_ipi_msg_enc *msg = data;
22 
23 	vpu->state = msg->state;
24 	vpu->bs_size = msg->bs_size;
25 	vpu->is_key_frm = msg->is_key_frm;
26 }
27 
vpu_enc_ipi_handler(void * data,unsigned int len,void * priv)28 static void vpu_enc_ipi_handler(void *data, unsigned int len, void *priv)
29 {
30 	struct venc_vpu_ipi_msg_common *msg = data;
31 	struct venc_vpu_inst *vpu =
32 		(struct venc_vpu_inst *)(unsigned long)msg->venc_inst;
33 
34 	mtk_vcodec_debug(vpu, "msg_id %x inst %p status %d",
35 			 msg->msg_id, vpu, msg->status);
36 
37 	switch (msg->msg_id) {
38 	case VPU_IPIMSG_ENC_INIT_DONE:
39 		handle_enc_init_msg(vpu, data);
40 		break;
41 	case VPU_IPIMSG_ENC_SET_PARAM_DONE:
42 		break;
43 	case VPU_IPIMSG_ENC_ENCODE_DONE:
44 		handle_enc_encode_msg(vpu, data);
45 		break;
46 	case VPU_IPIMSG_ENC_DEINIT_DONE:
47 		break;
48 	default:
49 		mtk_vcodec_err(vpu, "unknown msg id %x", msg->msg_id);
50 		break;
51 	}
52 
53 	vpu->signaled = 1;
54 	vpu->failure = (msg->status != VENC_IPI_MSG_STATUS_OK);
55 
56 	mtk_vcodec_debug_leave(vpu);
57 }
58 
vpu_enc_send_msg(struct venc_vpu_inst * vpu,void * msg,int len)59 static int vpu_enc_send_msg(struct venc_vpu_inst *vpu, void *msg,
60 			    int len)
61 {
62 	int status;
63 
64 	mtk_vcodec_debug_enter(vpu);
65 
66 	if (!vpu->dev) {
67 		mtk_vcodec_err(vpu, "inst dev is NULL");
68 		return -EINVAL;
69 	}
70 
71 	status = vpu_ipi_send(vpu->dev, vpu->id, msg, len);
72 	if (status) {
73 		mtk_vcodec_err(vpu, "vpu_ipi_send msg_id %x len %d fail %d",
74 			       *(uint32_t *)msg, len, status);
75 		return -EINVAL;
76 	}
77 	if (vpu->failure)
78 		return -EINVAL;
79 
80 	mtk_vcodec_debug_leave(vpu);
81 
82 	return 0;
83 }
84 
vpu_enc_init(struct venc_vpu_inst * vpu)85 int vpu_enc_init(struct venc_vpu_inst *vpu)
86 {
87 	int status;
88 	struct venc_ap_ipi_msg_init out;
89 
90 	mtk_vcodec_debug_enter(vpu);
91 
92 	init_waitqueue_head(&vpu->wq_hd);
93 	vpu->signaled = 0;
94 	vpu->failure = 0;
95 
96 	status = vpu_ipi_register(vpu->dev, vpu->id, vpu_enc_ipi_handler,
97 				  NULL, NULL);
98 	if (status) {
99 		mtk_vcodec_err(vpu, "vpu_ipi_register fail %d", status);
100 		return -EINVAL;
101 	}
102 
103 	memset(&out, 0, sizeof(out));
104 	out.msg_id = AP_IPIMSG_ENC_INIT;
105 	out.venc_inst = (unsigned long)vpu;
106 	if (vpu_enc_send_msg(vpu, &out, sizeof(out))) {
107 		mtk_vcodec_err(vpu, "AP_IPIMSG_ENC_INIT fail");
108 		return -EINVAL;
109 	}
110 
111 	mtk_vcodec_debug_leave(vpu);
112 
113 	return 0;
114 }
115 
vpu_enc_set_param(struct venc_vpu_inst * vpu,enum venc_set_param_type id,struct venc_enc_param * enc_param)116 int vpu_enc_set_param(struct venc_vpu_inst *vpu,
117 		      enum venc_set_param_type id,
118 		      struct venc_enc_param *enc_param)
119 {
120 	struct venc_ap_ipi_msg_set_param out;
121 
122 	mtk_vcodec_debug(vpu, "id %d ->", id);
123 
124 	memset(&out, 0, sizeof(out));
125 	out.msg_id = AP_IPIMSG_ENC_SET_PARAM;
126 	out.vpu_inst_addr = vpu->inst_addr;
127 	out.param_id = id;
128 	switch (id) {
129 	case VENC_SET_PARAM_ENC:
130 		out.data_item = 0;
131 		break;
132 	case VENC_SET_PARAM_FORCE_INTRA:
133 		out.data_item = 0;
134 		break;
135 	case VENC_SET_PARAM_ADJUST_BITRATE:
136 		out.data_item = 1;
137 		out.data[0] = enc_param->bitrate;
138 		break;
139 	case VENC_SET_PARAM_ADJUST_FRAMERATE:
140 		out.data_item = 1;
141 		out.data[0] = enc_param->frm_rate;
142 		break;
143 	case VENC_SET_PARAM_GOP_SIZE:
144 		out.data_item = 1;
145 		out.data[0] = enc_param->gop_size;
146 		break;
147 	case VENC_SET_PARAM_INTRA_PERIOD:
148 		out.data_item = 1;
149 		out.data[0] = enc_param->intra_period;
150 		break;
151 	case VENC_SET_PARAM_SKIP_FRAME:
152 		out.data_item = 0;
153 		break;
154 	default:
155 		mtk_vcodec_err(vpu, "id %d not supported", id);
156 		return -EINVAL;
157 	}
158 	if (vpu_enc_send_msg(vpu, &out, sizeof(out))) {
159 		mtk_vcodec_err(vpu,
160 			       "AP_IPIMSG_ENC_SET_PARAM %d fail", id);
161 		return -EINVAL;
162 	}
163 
164 	mtk_vcodec_debug(vpu, "id %d <-", id);
165 
166 	return 0;
167 }
168 
vpu_enc_encode(struct venc_vpu_inst * vpu,unsigned int bs_mode,struct venc_frm_buf * frm_buf,struct mtk_vcodec_mem * bs_buf,unsigned int * bs_size)169 int vpu_enc_encode(struct venc_vpu_inst *vpu, unsigned int bs_mode,
170 		   struct venc_frm_buf *frm_buf,
171 		   struct mtk_vcodec_mem *bs_buf,
172 		   unsigned int *bs_size)
173 {
174 	struct venc_ap_ipi_msg_enc out;
175 
176 	mtk_vcodec_debug(vpu, "bs_mode %d ->", bs_mode);
177 
178 	memset(&out, 0, sizeof(out));
179 	out.msg_id = AP_IPIMSG_ENC_ENCODE;
180 	out.vpu_inst_addr = vpu->inst_addr;
181 	out.bs_mode = bs_mode;
182 	if (frm_buf) {
183 		if ((frm_buf->fb_addr[0].dma_addr % 16 == 0) &&
184 		    (frm_buf->fb_addr[1].dma_addr % 16 == 0) &&
185 		    (frm_buf->fb_addr[2].dma_addr % 16 == 0)) {
186 			out.input_addr[0] = frm_buf->fb_addr[0].dma_addr;
187 			out.input_addr[1] = frm_buf->fb_addr[1].dma_addr;
188 			out.input_addr[2] = frm_buf->fb_addr[2].dma_addr;
189 		} else {
190 			mtk_vcodec_err(vpu, "dma_addr not align to 16");
191 			return -EINVAL;
192 		}
193 	}
194 	if (bs_buf) {
195 		out.bs_addr = bs_buf->dma_addr;
196 		out.bs_size = bs_buf->size;
197 	}
198 	if (vpu_enc_send_msg(vpu, &out, sizeof(out))) {
199 		mtk_vcodec_err(vpu, "AP_IPIMSG_ENC_ENCODE %d fail",
200 			       bs_mode);
201 		return -EINVAL;
202 	}
203 
204 	mtk_vcodec_debug(vpu, "bs_mode %d state %d size %d key_frm %d <-",
205 			 bs_mode, vpu->state, vpu->bs_size, vpu->is_key_frm);
206 
207 	return 0;
208 }
209 
vpu_enc_deinit(struct venc_vpu_inst * vpu)210 int vpu_enc_deinit(struct venc_vpu_inst *vpu)
211 {
212 	struct venc_ap_ipi_msg_deinit out;
213 
214 	mtk_vcodec_debug_enter(vpu);
215 
216 	memset(&out, 0, sizeof(out));
217 	out.msg_id = AP_IPIMSG_ENC_DEINIT;
218 	out.vpu_inst_addr = vpu->inst_addr;
219 	if (vpu_enc_send_msg(vpu, &out, sizeof(out))) {
220 		mtk_vcodec_err(vpu, "AP_IPIMSG_ENC_DEINIT fail");
221 		return -EINVAL;
222 	}
223 
224 	mtk_vcodec_debug_leave(vpu);
225 
226 	return 0;
227 }
228