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