]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/media/platform/coda/coda-jpeg.c
Merge branch 'linux-4.13' of git://github.com/skeggsb/linux into drm-fixes
[karo-tx-linux.git] / drivers / media / platform / coda / coda-jpeg.c
1 /*
2  * Coda multi-standard codec IP - JPEG support functions
3  *
4  * Copyright (C) 2014 Philipp Zabel, Pengutronix
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  */
11
12 #include <linux/kernel.h>
13 #include <linux/swab.h>
14
15 #include "coda.h"
16 #include "trace.h"
17
18 #define SOI_MARKER      0xffd8
19 #define EOI_MARKER      0xffd9
20
21 /*
22  * Typical Huffman tables for 8-bit precision luminance and
23  * chrominance from JPEG ITU-T.81 (ISO/IEC 10918-1) Annex K.3
24  */
25
26 static const unsigned char luma_dc_bits[16] = {
27         0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01,
28         0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29 };
30
31 static const unsigned char luma_dc_value[12] = {
32         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
33         0x08, 0x09, 0x0a, 0x0b,
34 };
35
36 static const unsigned char chroma_dc_bits[16] = {
37         0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
38         0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
39 };
40
41 static const unsigned char chroma_dc_value[12] = {
42         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
43         0x08, 0x09, 0x0a, 0x0b,
44 };
45
46 static const unsigned char luma_ac_bits[16] = {
47         0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03,
48         0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d,
49 };
50
51 static const unsigned char luma_ac_value[162 + 2] = {
52         0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
53         0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
54         0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
55         0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
56         0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
57         0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
58         0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
59         0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
60         0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
61         0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
62         0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
63         0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
64         0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
65         0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
66         0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
67         0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
68         0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
69         0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
70         0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
71         0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
72         0xf9, 0xfa, /* padded to 32-bit */
73 };
74
75 static const unsigned char chroma_ac_bits[16] = {
76         0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
77         0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77,
78 };
79
80 static const unsigned char chroma_ac_value[162 + 2] = {
81         0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
82         0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
83         0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
84         0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
85         0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
86         0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
87         0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
88         0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
89         0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
90         0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
91         0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
92         0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
93         0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
94         0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
95         0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
96         0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
97         0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
98         0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
99         0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
100         0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
101         0xf9, 0xfa, /* padded to 32-bit */
102 };
103
104 /*
105  * Quantization tables for luminance and chrominance components in
106  * zig-zag scan order from the Freescale i.MX VPU libaries
107  */
108
109 static unsigned char luma_q[64] = {
110         0x06, 0x04, 0x04, 0x04, 0x05, 0x04, 0x06, 0x05,
111         0x05, 0x06, 0x09, 0x06, 0x05, 0x06, 0x09, 0x0b,
112         0x08, 0x06, 0x06, 0x08, 0x0b, 0x0c, 0x0a, 0x0a,
113         0x0b, 0x0a, 0x0a, 0x0c, 0x10, 0x0c, 0x0c, 0x0c,
114         0x0c, 0x0c, 0x0c, 0x10, 0x0c, 0x0c, 0x0c, 0x0c,
115         0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
116         0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
117         0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
118 };
119
120 static unsigned char chroma_q[64] = {
121         0x07, 0x07, 0x07, 0x0d, 0x0c, 0x0d, 0x18, 0x10,
122         0x10, 0x18, 0x14, 0x0e, 0x0e, 0x0e, 0x14, 0x14,
123         0x0e, 0x0e, 0x0e, 0x0e, 0x14, 0x11, 0x0c, 0x0c,
124         0x0c, 0x0c, 0x0c, 0x11, 0x11, 0x0c, 0x0c, 0x0c,
125         0x0c, 0x0c, 0x0c, 0x11, 0x0c, 0x0c, 0x0c, 0x0c,
126         0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
127         0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
128         0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
129 };
130
131 struct coda_memcpy_desc {
132         int offset;
133         const void *src;
134         size_t len;
135 };
136
137 static void coda_memcpy_parabuf(void *parabuf,
138                                 const struct coda_memcpy_desc *desc)
139 {
140         u32 *dst = parabuf + desc->offset;
141         const u32 *src = desc->src;
142         int len = desc->len / 4;
143         int i;
144
145         for (i = 0; i < len; i += 2) {
146                 dst[i + 1] = swab32(src[i]);
147                 dst[i] = swab32(src[i + 1]);
148         }
149 }
150
151 int coda_jpeg_write_tables(struct coda_ctx *ctx)
152 {
153         int i;
154         static const struct coda_memcpy_desc huff[8] = {
155                 { 0,   luma_dc_bits,    sizeof(luma_dc_bits)    },
156                 { 16,  luma_dc_value,   sizeof(luma_dc_value)   },
157                 { 32,  luma_ac_bits,    sizeof(luma_ac_bits)    },
158                 { 48,  luma_ac_value,   sizeof(luma_ac_value)   },
159                 { 216, chroma_dc_bits,  sizeof(chroma_dc_bits)  },
160                 { 232, chroma_dc_value, sizeof(chroma_dc_value) },
161                 { 248, chroma_ac_bits,  sizeof(chroma_ac_bits)  },
162                 { 264, chroma_ac_value, sizeof(chroma_ac_value) },
163         };
164         struct coda_memcpy_desc qmat[3] = {
165                 { 512, ctx->params.jpeg_qmat_tab[0], 64 },
166                 { 576, ctx->params.jpeg_qmat_tab[1], 64 },
167                 { 640, ctx->params.jpeg_qmat_tab[1], 64 },
168         };
169
170         /* Write huffman tables to parameter memory */
171         for (i = 0; i < ARRAY_SIZE(huff); i++)
172                 coda_memcpy_parabuf(ctx->parabuf.vaddr, huff + i);
173
174         /* Write Q-matrix to parameter memory */
175         for (i = 0; i < ARRAY_SIZE(qmat); i++)
176                 coda_memcpy_parabuf(ctx->parabuf.vaddr, qmat + i);
177
178         return 0;
179 }
180
181 bool coda_jpeg_check_buffer(struct coda_ctx *ctx, struct vb2_buffer *vb)
182 {
183         void *vaddr = vb2_plane_vaddr(vb, 0);
184         u16 soi, eoi;
185         int len, i;
186
187         soi = be16_to_cpup((__be16 *)vaddr);
188         if (soi != SOI_MARKER)
189                 return false;
190
191         len = vb2_get_plane_payload(vb, 0);
192         vaddr += len - 2;
193         for (i = 0; i < 32; i++) {
194                 eoi = be16_to_cpup((__be16 *)(vaddr - i));
195                 if (eoi == EOI_MARKER) {
196                         if (i > 0)
197                                 vb2_set_plane_payload(vb, 0, len - i);
198                         return true;
199                 }
200         }
201
202         return false;
203 }
204
205 /*
206  * Scale quantization table using nonlinear scaling factor
207  * u8 qtab[64], scale [50,190]
208  */
209 static void coda_scale_quant_table(u8 *q_tab, int scale)
210 {
211         unsigned int temp;
212         int i;
213
214         for (i = 0; i < 64; i++) {
215                 temp = DIV_ROUND_CLOSEST((unsigned int)q_tab[i] * scale, 100);
216                 if (temp <= 0)
217                         temp = 1;
218                 if (temp > 255)
219                         temp = 255;
220                 q_tab[i] = (unsigned char)temp;
221         }
222 }
223
224 void coda_set_jpeg_compression_quality(struct coda_ctx *ctx, int quality)
225 {
226         unsigned int scale;
227
228         ctx->params.jpeg_quality = quality;
229
230         /* Clip quality setting to [5,100] interval */
231         if (quality > 100)
232                 quality = 100;
233         if (quality < 5)
234                 quality = 5;
235
236         /*
237          * Non-linear scaling factor:
238          * [5,50] -> [1000..100], [51,100] -> [98..0]
239          */
240         if (quality < 50)
241                 scale = 5000 / quality;
242         else
243                 scale = 200 - 2 * quality;
244
245         if (ctx->params.jpeg_qmat_tab[0]) {
246                 memcpy(ctx->params.jpeg_qmat_tab[0], luma_q, 64);
247                 coda_scale_quant_table(ctx->params.jpeg_qmat_tab[0], scale);
248         }
249         if (ctx->params.jpeg_qmat_tab[1]) {
250                 memcpy(ctx->params.jpeg_qmat_tab[1], chroma_q, 64);
251                 coda_scale_quant_table(ctx->params.jpeg_qmat_tab[1], scale);
252         }
253 }