]> git.proxmox.com Git - mirror_ubuntu-kernels.git/blob - drivers/media/platform/vicodec/codec-v4l2-fwht.c
HID: logitech-dj: fix spelling in printk
[mirror_ubuntu-kernels.git] / drivers / media / platform / vicodec / codec-v4l2-fwht.c
1 // SPDX-License-Identifier: LGPL-2.1
2 /*
3 * A V4L2 frontend for the FWHT codec
4 *
5 * Copyright 2018 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
6 */
7
8 #include <linux/errno.h>
9 #include <linux/string.h>
10 #include <linux/videodev2.h>
11 #include "codec-v4l2-fwht.h"
12
13 static const struct v4l2_fwht_pixfmt_info v4l2_fwht_pixfmts[] = {
14 { V4L2_PIX_FMT_YUV420, 1, 3, 2, 1, 1, 2, 2, 3},
15 { V4L2_PIX_FMT_YVU420, 1, 3, 2, 1, 1, 2, 2, 3},
16 { V4L2_PIX_FMT_YUV422P, 1, 2, 1, 1, 1, 2, 1, 3},
17 { V4L2_PIX_FMT_NV12, 1, 3, 2, 1, 2, 2, 2, 3},
18 { V4L2_PIX_FMT_NV21, 1, 3, 2, 1, 2, 2, 2, 3},
19 { V4L2_PIX_FMT_NV16, 1, 2, 1, 1, 2, 2, 1, 3},
20 { V4L2_PIX_FMT_NV61, 1, 2, 1, 1, 2, 2, 1, 3},
21 { V4L2_PIX_FMT_NV24, 1, 3, 1, 1, 2, 1, 1, 3},
22 { V4L2_PIX_FMT_NV42, 1, 3, 1, 1, 2, 1, 1, 3},
23 { V4L2_PIX_FMT_YUYV, 2, 2, 1, 2, 4, 2, 1, 3},
24 { V4L2_PIX_FMT_YVYU, 2, 2, 1, 2, 4, 2, 1, 3},
25 { V4L2_PIX_FMT_UYVY, 2, 2, 1, 2, 4, 2, 1, 3},
26 { V4L2_PIX_FMT_VYUY, 2, 2, 1, 2, 4, 2, 1, 3},
27 { V4L2_PIX_FMT_BGR24, 3, 3, 1, 3, 3, 1, 1, 3},
28 { V4L2_PIX_FMT_RGB24, 3, 3, 1, 3, 3, 1, 1, 3},
29 { V4L2_PIX_FMT_HSV24, 3, 3, 1, 3, 3, 1, 1, 3},
30 { V4L2_PIX_FMT_BGR32, 4, 4, 1, 4, 4, 1, 1, 3},
31 { V4L2_PIX_FMT_XBGR32, 4, 4, 1, 4, 4, 1, 1, 3},
32 { V4L2_PIX_FMT_RGB32, 4, 4, 1, 4, 4, 1, 1, 3},
33 { V4L2_PIX_FMT_XRGB32, 4, 4, 1, 4, 4, 1, 1, 3},
34 { V4L2_PIX_FMT_HSV32, 4, 4, 1, 4, 4, 1, 1, 3},
35 { V4L2_PIX_FMT_ARGB32, 4, 4, 1, 4, 4, 1, 1, 4},
36 { V4L2_PIX_FMT_ABGR32, 4, 4, 1, 4, 4, 1, 1, 4},
37 { V4L2_PIX_FMT_GREY, 1, 1, 1, 1, 0, 1, 1, 1},
38 };
39
40 const struct v4l2_fwht_pixfmt_info *v4l2_fwht_find_pixfmt(u32 pixelformat)
41 {
42 unsigned int i;
43
44 for (i = 0; i < ARRAY_SIZE(v4l2_fwht_pixfmts); i++)
45 if (v4l2_fwht_pixfmts[i].id == pixelformat)
46 return v4l2_fwht_pixfmts + i;
47 return NULL;
48 }
49
50 const struct v4l2_fwht_pixfmt_info *v4l2_fwht_get_pixfmt(u32 idx)
51 {
52 if (idx >= ARRAY_SIZE(v4l2_fwht_pixfmts))
53 return NULL;
54 return v4l2_fwht_pixfmts + idx;
55 }
56
57 int v4l2_fwht_encode(struct v4l2_fwht_state *state, u8 *p_in, u8 *p_out)
58 {
59 unsigned int size = state->width * state->height;
60 const struct v4l2_fwht_pixfmt_info *info = state->info;
61 struct fwht_cframe_hdr *p_hdr;
62 struct fwht_cframe cf;
63 struct fwht_raw_frame rf;
64 u32 encoding;
65 u32 flags = 0;
66
67 if (!info)
68 return -EINVAL;
69 rf.width = state->width;
70 rf.height = state->height;
71 rf.luma = p_in;
72 rf.width_div = info->width_div;
73 rf.height_div = info->height_div;
74 rf.luma_alpha_step = info->luma_alpha_step;
75 rf.chroma_step = info->chroma_step;
76 rf.alpha = NULL;
77 rf.components_num = info->components_num;
78
79 switch (info->id) {
80 case V4L2_PIX_FMT_GREY:
81 rf.cb = NULL;
82 rf.cr = NULL;
83 break;
84 case V4L2_PIX_FMT_YUV420:
85 rf.cb = rf.luma + size;
86 rf.cr = rf.cb + size / 4;
87 break;
88 case V4L2_PIX_FMT_YVU420:
89 rf.cr = rf.luma + size;
90 rf.cb = rf.cr + size / 4;
91 break;
92 case V4L2_PIX_FMT_YUV422P:
93 rf.cb = rf.luma + size;
94 rf.cr = rf.cb + size / 2;
95 break;
96 case V4L2_PIX_FMT_NV12:
97 case V4L2_PIX_FMT_NV16:
98 case V4L2_PIX_FMT_NV24:
99 rf.cb = rf.luma + size;
100 rf.cr = rf.cb + 1;
101 break;
102 case V4L2_PIX_FMT_NV21:
103 case V4L2_PIX_FMT_NV61:
104 case V4L2_PIX_FMT_NV42:
105 rf.cr = rf.luma + size;
106 rf.cb = rf.cr + 1;
107 break;
108 case V4L2_PIX_FMT_YUYV:
109 rf.cb = rf.luma + 1;
110 rf.cr = rf.cb + 2;
111 break;
112 case V4L2_PIX_FMT_YVYU:
113 rf.cr = rf.luma + 1;
114 rf.cb = rf.cr + 2;
115 break;
116 case V4L2_PIX_FMT_UYVY:
117 rf.cb = rf.luma;
118 rf.cr = rf.cb + 2;
119 rf.luma++;
120 break;
121 case V4L2_PIX_FMT_VYUY:
122 rf.cr = rf.luma;
123 rf.cb = rf.cr + 2;
124 rf.luma++;
125 break;
126 case V4L2_PIX_FMT_RGB24:
127 case V4L2_PIX_FMT_HSV24:
128 rf.cr = rf.luma;
129 rf.cb = rf.cr + 2;
130 rf.luma++;
131 break;
132 case V4L2_PIX_FMT_BGR24:
133 rf.cb = rf.luma;
134 rf.cr = rf.cb + 2;
135 rf.luma++;
136 break;
137 case V4L2_PIX_FMT_RGB32:
138 case V4L2_PIX_FMT_XRGB32:
139 case V4L2_PIX_FMT_HSV32:
140 rf.cr = rf.luma + 1;
141 rf.cb = rf.cr + 2;
142 rf.luma += 2;
143 break;
144 case V4L2_PIX_FMT_BGR32:
145 case V4L2_PIX_FMT_XBGR32:
146 rf.cb = rf.luma;
147 rf.cr = rf.cb + 2;
148 rf.luma++;
149 break;
150 case V4L2_PIX_FMT_ARGB32:
151 rf.alpha = rf.luma;
152 rf.cr = rf.luma + 1;
153 rf.cb = rf.cr + 2;
154 rf.luma += 2;
155 break;
156 case V4L2_PIX_FMT_ABGR32:
157 rf.cb = rf.luma;
158 rf.cr = rf.cb + 2;
159 rf.luma++;
160 rf.alpha = rf.cr + 1;
161 break;
162 default:
163 return -EINVAL;
164 }
165
166 cf.width = state->width;
167 cf.height = state->height;
168 cf.i_frame_qp = state->i_frame_qp;
169 cf.p_frame_qp = state->p_frame_qp;
170 cf.rlc_data = (__be16 *)(p_out + sizeof(*p_hdr));
171
172 encoding = fwht_encode_frame(&rf, &state->ref_frame, &cf,
173 !state->gop_cnt,
174 state->gop_cnt == state->gop_size - 1);
175 if (!(encoding & FWHT_FRAME_PCODED))
176 state->gop_cnt = 0;
177 if (++state->gop_cnt >= state->gop_size)
178 state->gop_cnt = 0;
179
180 p_hdr = (struct fwht_cframe_hdr *)p_out;
181 p_hdr->magic1 = FWHT_MAGIC1;
182 p_hdr->magic2 = FWHT_MAGIC2;
183 p_hdr->version = htonl(FWHT_VERSION);
184 p_hdr->width = htonl(cf.width);
185 p_hdr->height = htonl(cf.height);
186 flags |= (info->components_num - 1) << FWHT_FL_COMPONENTS_NUM_OFFSET;
187 if (encoding & FWHT_LUMA_UNENCODED)
188 flags |= FWHT_FL_LUMA_IS_UNCOMPRESSED;
189 if (encoding & FWHT_CB_UNENCODED)
190 flags |= FWHT_FL_CB_IS_UNCOMPRESSED;
191 if (encoding & FWHT_CR_UNENCODED)
192 flags |= FWHT_FL_CR_IS_UNCOMPRESSED;
193 if (encoding & FWHT_ALPHA_UNENCODED)
194 flags |= FWHT_FL_ALPHA_IS_UNCOMPRESSED;
195 if (rf.height_div == 1)
196 flags |= FWHT_FL_CHROMA_FULL_HEIGHT;
197 if (rf.width_div == 1)
198 flags |= FWHT_FL_CHROMA_FULL_WIDTH;
199 p_hdr->flags = htonl(flags);
200 p_hdr->colorspace = htonl(state->colorspace);
201 p_hdr->xfer_func = htonl(state->xfer_func);
202 p_hdr->ycbcr_enc = htonl(state->ycbcr_enc);
203 p_hdr->quantization = htonl(state->quantization);
204 p_hdr->size = htonl(cf.size);
205 state->ref_frame.width = cf.width;
206 state->ref_frame.height = cf.height;
207 return cf.size + sizeof(*p_hdr);
208 }
209
210 int v4l2_fwht_decode(struct v4l2_fwht_state *state, u8 *p_in, u8 *p_out)
211 {
212 unsigned int size = state->width * state->height;
213 unsigned int chroma_size = size;
214 unsigned int i;
215 u32 flags;
216 struct fwht_cframe_hdr *p_hdr;
217 struct fwht_cframe cf;
218 u8 *p;
219 unsigned int components_num = 3;
220 unsigned int version;
221
222 if (!state->info)
223 return -EINVAL;
224
225 p_hdr = (struct fwht_cframe_hdr *)p_in;
226 cf.width = ntohl(p_hdr->width);
227 cf.height = ntohl(p_hdr->height);
228
229 version = ntohl(p_hdr->version);
230 if (!version || version > FWHT_VERSION) {
231 pr_err("version %d is not supported, current version is %d\n",
232 version, FWHT_VERSION);
233 return -EINVAL;
234 }
235
236 if (p_hdr->magic1 != FWHT_MAGIC1 ||
237 p_hdr->magic2 != FWHT_MAGIC2 ||
238 (cf.width & 7) || (cf.height & 7))
239 return -EINVAL;
240
241 /* TODO: support resolution changes */
242 if (cf.width != state->width || cf.height != state->height)
243 return -EINVAL;
244
245 flags = ntohl(p_hdr->flags);
246
247 if (version == FWHT_VERSION) {
248 components_num = 1 + ((flags & FWHT_FL_COMPONENTS_NUM_MSK) >>
249 FWHT_FL_COMPONENTS_NUM_OFFSET);
250 }
251
252 state->colorspace = ntohl(p_hdr->colorspace);
253 state->xfer_func = ntohl(p_hdr->xfer_func);
254 state->ycbcr_enc = ntohl(p_hdr->ycbcr_enc);
255 state->quantization = ntohl(p_hdr->quantization);
256 cf.rlc_data = (__be16 *)(p_in + sizeof(*p_hdr));
257
258 if (!(flags & FWHT_FL_CHROMA_FULL_WIDTH))
259 chroma_size /= 2;
260 if (!(flags & FWHT_FL_CHROMA_FULL_HEIGHT))
261 chroma_size /= 2;
262
263 fwht_decode_frame(&cf, &state->ref_frame, flags, components_num);
264
265 /*
266 * TODO - handle the case where the compressed stream encodes a
267 * different format than the requested decoded format.
268 */
269 switch (state->info->id) {
270 case V4L2_PIX_FMT_GREY:
271 memcpy(p_out, state->ref_frame.luma, size);
272 break;
273 case V4L2_PIX_FMT_YUV420:
274 case V4L2_PIX_FMT_YUV422P:
275 memcpy(p_out, state->ref_frame.luma, size);
276 p_out += size;
277 memcpy(p_out, state->ref_frame.cb, chroma_size);
278 p_out += chroma_size;
279 memcpy(p_out, state->ref_frame.cr, chroma_size);
280 break;
281 case V4L2_PIX_FMT_YVU420:
282 memcpy(p_out, state->ref_frame.luma, size);
283 p_out += size;
284 memcpy(p_out, state->ref_frame.cr, chroma_size);
285 p_out += chroma_size;
286 memcpy(p_out, state->ref_frame.cb, chroma_size);
287 break;
288 case V4L2_PIX_FMT_NV12:
289 case V4L2_PIX_FMT_NV16:
290 case V4L2_PIX_FMT_NV24:
291 memcpy(p_out, state->ref_frame.luma, size);
292 p_out += size;
293 for (i = 0, p = p_out; i < chroma_size; i++) {
294 *p++ = state->ref_frame.cb[i];
295 *p++ = state->ref_frame.cr[i];
296 }
297 break;
298 case V4L2_PIX_FMT_NV21:
299 case V4L2_PIX_FMT_NV61:
300 case V4L2_PIX_FMT_NV42:
301 memcpy(p_out, state->ref_frame.luma, size);
302 p_out += size;
303 for (i = 0, p = p_out; i < chroma_size; i++) {
304 *p++ = state->ref_frame.cr[i];
305 *p++ = state->ref_frame.cb[i];
306 }
307 break;
308 case V4L2_PIX_FMT_YUYV:
309 for (i = 0, p = p_out; i < size; i += 2) {
310 *p++ = state->ref_frame.luma[i];
311 *p++ = state->ref_frame.cb[i / 2];
312 *p++ = state->ref_frame.luma[i + 1];
313 *p++ = state->ref_frame.cr[i / 2];
314 }
315 break;
316 case V4L2_PIX_FMT_YVYU:
317 for (i = 0, p = p_out; i < size; i += 2) {
318 *p++ = state->ref_frame.luma[i];
319 *p++ = state->ref_frame.cr[i / 2];
320 *p++ = state->ref_frame.luma[i + 1];
321 *p++ = state->ref_frame.cb[i / 2];
322 }
323 break;
324 case V4L2_PIX_FMT_UYVY:
325 for (i = 0, p = p_out; i < size; i += 2) {
326 *p++ = state->ref_frame.cb[i / 2];
327 *p++ = state->ref_frame.luma[i];
328 *p++ = state->ref_frame.cr[i / 2];
329 *p++ = state->ref_frame.luma[i + 1];
330 }
331 break;
332 case V4L2_PIX_FMT_VYUY:
333 for (i = 0, p = p_out; i < size; i += 2) {
334 *p++ = state->ref_frame.cr[i / 2];
335 *p++ = state->ref_frame.luma[i];
336 *p++ = state->ref_frame.cb[i / 2];
337 *p++ = state->ref_frame.luma[i + 1];
338 }
339 break;
340 case V4L2_PIX_FMT_RGB24:
341 case V4L2_PIX_FMT_HSV24:
342 for (i = 0, p = p_out; i < size; i++) {
343 *p++ = state->ref_frame.cr[i];
344 *p++ = state->ref_frame.luma[i];
345 *p++ = state->ref_frame.cb[i];
346 }
347 break;
348 case V4L2_PIX_FMT_BGR24:
349 for (i = 0, p = p_out; i < size; i++) {
350 *p++ = state->ref_frame.cb[i];
351 *p++ = state->ref_frame.luma[i];
352 *p++ = state->ref_frame.cr[i];
353 }
354 break;
355 case V4L2_PIX_FMT_RGB32:
356 case V4L2_PIX_FMT_XRGB32:
357 case V4L2_PIX_FMT_HSV32:
358 for (i = 0, p = p_out; i < size; i++) {
359 *p++ = 0;
360 *p++ = state->ref_frame.cr[i];
361 *p++ = state->ref_frame.luma[i];
362 *p++ = state->ref_frame.cb[i];
363 }
364 break;
365 case V4L2_PIX_FMT_BGR32:
366 case V4L2_PIX_FMT_XBGR32:
367 for (i = 0, p = p_out; i < size; i++) {
368 *p++ = state->ref_frame.cb[i];
369 *p++ = state->ref_frame.luma[i];
370 *p++ = state->ref_frame.cr[i];
371 *p++ = 0;
372 }
373 break;
374 case V4L2_PIX_FMT_ARGB32:
375 for (i = 0, p = p_out; i < size; i++) {
376 *p++ = state->ref_frame.alpha[i];
377 *p++ = state->ref_frame.cr[i];
378 *p++ = state->ref_frame.luma[i];
379 *p++ = state->ref_frame.cb[i];
380 }
381 break;
382 case V4L2_PIX_FMT_ABGR32:
383 for (i = 0, p = p_out; i < size; i++) {
384 *p++ = state->ref_frame.cb[i];
385 *p++ = state->ref_frame.luma[i];
386 *p++ = state->ref_frame.cr[i];
387 *p++ = state->ref_frame.alpha[i];
388 }
389 break;
390 default:
391 return -EINVAL;
392 }
393 return 0;
394 }