Commit | Line | Data |
---|---|---|
27a274db TL |
1 | /* |
2 | * Copyright (c) 2016 MediaTek Inc. | |
3 | * Author: PoChun Lin <pochun.lin@mediatek.com> | |
4 | * | |
5 | * This program is free software; you can redistribute it and/or | |
6 | * modify | |
7 | * it under the terms of the GNU General Public License version 2 as | |
8 | * published by the Free Software Foundation. | |
9 | * | |
10 | * This program is distributed in the hope that it will be useful, | |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | * GNU General Public License for more details. | |
14 | */ | |
15 | ||
16 | #include "mtk_vpu.h" | |
17 | #include "venc_ipi_msg.h" | |
18 | #include "venc_vpu_if.h" | |
19 | ||
20 | static void handle_enc_init_msg(struct venc_vpu_inst *vpu, void *data) | |
21 | { | |
22 | struct venc_vpu_ipi_msg_init *msg = data; | |
23 | ||
24 | vpu->inst_addr = msg->vpu_inst_addr; | |
25 | vpu->vsi = vpu_mapping_dm_addr(vpu->dev, msg->vpu_inst_addr); | |
26 | } | |
27 | ||
28 | static void handle_enc_encode_msg(struct venc_vpu_inst *vpu, void *data) | |
29 | { | |
30 | struct venc_vpu_ipi_msg_enc *msg = data; | |
31 | ||
32 | vpu->state = msg->state; | |
33 | vpu->bs_size = msg->bs_size; | |
34 | vpu->is_key_frm = msg->is_key_frm; | |
35 | } | |
36 | ||
37 | static void vpu_enc_ipi_handler(void *data, unsigned int len, void *priv) | |
38 | { | |
39 | struct venc_vpu_ipi_msg_common *msg = data; | |
65ad26cd HV |
40 | struct venc_vpu_inst *vpu = |
41 | (struct venc_vpu_inst *)(unsigned long)msg->venc_inst; | |
27a274db TL |
42 | |
43 | mtk_vcodec_debug(vpu, "msg_id %x inst %p status %d", | |
44 | msg->msg_id, vpu, msg->status); | |
45 | ||
46 | switch (msg->msg_id) { | |
47 | case VPU_IPIMSG_ENC_INIT_DONE: | |
48 | handle_enc_init_msg(vpu, data); | |
49 | break; | |
50 | case VPU_IPIMSG_ENC_SET_PARAM_DONE: | |
51 | break; | |
52 | case VPU_IPIMSG_ENC_ENCODE_DONE: | |
53 | handle_enc_encode_msg(vpu, data); | |
54 | break; | |
55 | case VPU_IPIMSG_ENC_DEINIT_DONE: | |
56 | break; | |
57 | default: | |
58 | mtk_vcodec_err(vpu, "unknown msg id %x", msg->msg_id); | |
59 | break; | |
60 | } | |
61 | ||
62 | vpu->signaled = 1; | |
63 | vpu->failure = (msg->status != VENC_IPI_MSG_STATUS_OK); | |
64 | ||
65 | mtk_vcodec_debug_leave(vpu); | |
66 | } | |
67 | ||
68 | static int vpu_enc_send_msg(struct venc_vpu_inst *vpu, void *msg, | |
69 | int len) | |
70 | { | |
71 | int status; | |
72 | ||
73 | mtk_vcodec_debug_enter(vpu); | |
74 | ||
75 | if (!vpu->dev) { | |
76 | mtk_vcodec_err(vpu, "inst dev is NULL"); | |
77 | return -EINVAL; | |
78 | } | |
79 | ||
80 | status = vpu_ipi_send(vpu->dev, vpu->id, msg, len); | |
81 | if (status) { | |
82 | uint32_t msg_id = *(uint32_t *)msg; | |
83 | ||
84 | mtk_vcodec_err(vpu, "vpu_ipi_send msg_id %x len %d fail %d", | |
85 | msg_id, len, status); | |
86 | return -EINVAL; | |
87 | } | |
88 | if (vpu->failure) | |
89 | return -EINVAL; | |
90 | ||
91 | mtk_vcodec_debug_leave(vpu); | |
92 | ||
93 | return 0; | |
94 | } | |
95 | ||
96 | int vpu_enc_init(struct venc_vpu_inst *vpu) | |
97 | { | |
98 | int status; | |
99 | struct venc_ap_ipi_msg_init out; | |
100 | ||
101 | mtk_vcodec_debug_enter(vpu); | |
102 | ||
103 | init_waitqueue_head(&vpu->wq_hd); | |
104 | vpu->signaled = 0; | |
105 | vpu->failure = 0; | |
106 | ||
107 | status = vpu_ipi_register(vpu->dev, vpu->id, vpu_enc_ipi_handler, | |
108 | NULL, NULL); | |
109 | if (status) { | |
110 | mtk_vcodec_err(vpu, "vpu_ipi_register fail %d", status); | |
111 | return -EINVAL; | |
112 | } | |
113 | ||
114 | memset(&out, 0, sizeof(out)); | |
115 | out.msg_id = AP_IPIMSG_ENC_INIT; | |
116 | out.venc_inst = (unsigned long)vpu; | |
117 | if (vpu_enc_send_msg(vpu, &out, sizeof(out))) { | |
118 | mtk_vcodec_err(vpu, "AP_IPIMSG_ENC_INIT fail"); | |
119 | return -EINVAL; | |
120 | } | |
121 | ||
122 | mtk_vcodec_debug_leave(vpu); | |
123 | ||
124 | return 0; | |
125 | } | |
126 | ||
127 | int vpu_enc_set_param(struct venc_vpu_inst *vpu, | |
128 | enum venc_set_param_type id, | |
129 | struct venc_enc_param *enc_param) | |
130 | { | |
131 | struct venc_ap_ipi_msg_set_param out; | |
132 | ||
133 | mtk_vcodec_debug(vpu, "id %d ->", id); | |
134 | ||
135 | memset(&out, 0, sizeof(out)); | |
136 | out.msg_id = AP_IPIMSG_ENC_SET_PARAM; | |
137 | out.vpu_inst_addr = vpu->inst_addr; | |
138 | out.param_id = id; | |
139 | switch (id) { | |
140 | case VENC_SET_PARAM_ENC: | |
141 | out.data_item = 0; | |
142 | break; | |
143 | case VENC_SET_PARAM_FORCE_INTRA: | |
144 | out.data_item = 0; | |
145 | break; | |
146 | case VENC_SET_PARAM_ADJUST_BITRATE: | |
147 | out.data_item = 1; | |
148 | out.data[0] = enc_param->bitrate; | |
149 | break; | |
150 | case VENC_SET_PARAM_ADJUST_FRAMERATE: | |
151 | out.data_item = 1; | |
152 | out.data[0] = enc_param->frm_rate; | |
153 | break; | |
154 | case VENC_SET_PARAM_GOP_SIZE: | |
155 | out.data_item = 1; | |
156 | out.data[0] = enc_param->gop_size; | |
157 | break; | |
158 | case VENC_SET_PARAM_INTRA_PERIOD: | |
159 | out.data_item = 1; | |
160 | out.data[0] = enc_param->intra_period; | |
161 | break; | |
162 | case VENC_SET_PARAM_SKIP_FRAME: | |
163 | out.data_item = 0; | |
164 | break; | |
165 | default: | |
166 | mtk_vcodec_err(vpu, "id %d not supported", id); | |
167 | return -EINVAL; | |
168 | } | |
169 | if (vpu_enc_send_msg(vpu, &out, sizeof(out))) { | |
170 | mtk_vcodec_err(vpu, | |
171 | "AP_IPIMSG_ENC_SET_PARAM %d fail", id); | |
172 | return -EINVAL; | |
173 | } | |
174 | ||
175 | mtk_vcodec_debug(vpu, "id %d <-", id); | |
176 | ||
177 | return 0; | |
178 | } | |
179 | ||
180 | int vpu_enc_encode(struct venc_vpu_inst *vpu, unsigned int bs_mode, | |
181 | struct venc_frm_buf *frm_buf, | |
182 | struct mtk_vcodec_mem *bs_buf, | |
183 | unsigned int *bs_size) | |
184 | { | |
185 | struct venc_ap_ipi_msg_enc out; | |
186 | ||
187 | mtk_vcodec_debug(vpu, "bs_mode %d ->", bs_mode); | |
188 | ||
189 | memset(&out, 0, sizeof(out)); | |
190 | out.msg_id = AP_IPIMSG_ENC_ENCODE; | |
191 | out.vpu_inst_addr = vpu->inst_addr; | |
192 | out.bs_mode = bs_mode; | |
193 | if (frm_buf) { | |
194 | if ((frm_buf->fb_addr[0].dma_addr % 16 == 0) && | |
195 | (frm_buf->fb_addr[1].dma_addr % 16 == 0) && | |
196 | (frm_buf->fb_addr[2].dma_addr % 16 == 0)) { | |
197 | out.input_addr[0] = frm_buf->fb_addr[0].dma_addr; | |
198 | out.input_addr[1] = frm_buf->fb_addr[1].dma_addr; | |
199 | out.input_addr[2] = frm_buf->fb_addr[2].dma_addr; | |
200 | } else { | |
201 | mtk_vcodec_err(vpu, "dma_addr not align to 16"); | |
202 | return -EINVAL; | |
203 | } | |
204 | } | |
205 | if (bs_buf) { | |
206 | out.bs_addr = bs_buf->dma_addr; | |
207 | out.bs_size = bs_buf->size; | |
208 | } | |
209 | if (vpu_enc_send_msg(vpu, &out, sizeof(out))) { | |
210 | mtk_vcodec_err(vpu, "AP_IPIMSG_ENC_ENCODE %d fail", | |
211 | bs_mode); | |
212 | return -EINVAL; | |
213 | } | |
214 | ||
215 | mtk_vcodec_debug(vpu, "bs_mode %d state %d size %d key_frm %d <-", | |
216 | bs_mode, vpu->state, vpu->bs_size, vpu->is_key_frm); | |
217 | ||
218 | return 0; | |
219 | } | |
220 | ||
221 | int vpu_enc_deinit(struct venc_vpu_inst *vpu) | |
222 | { | |
223 | struct venc_ap_ipi_msg_deinit out; | |
224 | ||
225 | mtk_vcodec_debug_enter(vpu); | |
226 | ||
227 | memset(&out, 0, sizeof(out)); | |
228 | out.msg_id = AP_IPIMSG_ENC_DEINIT; | |
229 | out.vpu_inst_addr = vpu->inst_addr; | |
230 | if (vpu_enc_send_msg(vpu, &out, sizeof(out))) { | |
231 | mtk_vcodec_err(vpu, "AP_IPIMSG_ENC_DEINIT fail"); | |
232 | return -EINVAL; | |
233 | } | |
234 | ||
235 | mtk_vcodec_debug_leave(vpu); | |
236 | ||
237 | return 0; | |
238 | } |