Commit | Line | Data |
---|---|---|
1802d0be | 1 | // SPDX-License-Identifier: GPL-2.0-only |
27a274db TL |
2 | /* |
3 | * Copyright (c) 2016 MediaTek Inc. | |
4 | * Author: PoChun Lin <pochun.lin@mediatek.com> | |
27a274db TL |
5 | */ |
6 | ||
7 | #include "mtk_vpu.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, 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 | ||
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 | ||
28 | static void vpu_enc_ipi_handler(void *data, unsigned int len, void *priv) | |
29 | { | |
30 | struct venc_vpu_ipi_msg_common *msg = data; | |
65ad26cd HV |
31 | struct venc_vpu_inst *vpu = |
32 | (struct venc_vpu_inst *)(unsigned long)msg->venc_inst; | |
27a274db TL |
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 | ||
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) { | |
27a274db | 73 | mtk_vcodec_err(vpu, "vpu_ipi_send msg_id %x len %d fail %d", |
9eeb0ed0 | 74 | *(uint32_t *)msg, len, status); |
27a274db TL |
75 | return -EINVAL; |
76 | } | |
77 | if (vpu->failure) | |
78 | return -EINVAL; | |
79 | ||
80 | mtk_vcodec_debug_leave(vpu); | |
81 | ||
82 | return 0; | |
83 | } | |
84 | ||
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 | ||
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 | ||
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 | ||
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 | } |