1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Copyright (C) Collabora, Ltd.
4 *
5 * Based on GSPCA and CODA drivers:
6 * Copyright (C) Jean-Francois Moine (http://moinejf.free.fr)
7 * Copyright (C) 2014 Philipp Zabel, Pengutronix
8 */
9 #include <linux/dma-mapping.h>
10 #include <linux/kernel.h>
11 #include <linux/string.h>
12 #include "hantro_jpeg.h"
13 #include "hantro.h"
14
15 #define LUMA_QUANT_OFF 7
16 #define CHROMA_QUANT_OFF 72
17 #define HEIGHT_OFF 141
18 #define WIDTH_OFF 143
19
20 #define HUFF_LUMA_DC_OFF 160
21 #define HUFF_LUMA_AC_OFF 193
22 #define HUFF_CHROMA_DC_OFF 376
23 #define HUFF_CHROMA_AC_OFF 409
24
25 /* Default tables from JPEG ITU-T.81
26 * (ISO/IEC 10918-1) Annex K, tables K.1 and K.2
27 */
28 static const unsigned char luma_q_table[] = {
29 0x10, 0x0b, 0x0a, 0x10, 0x18, 0x28, 0x33, 0x3d,
30 0x0c, 0x0c, 0x0e, 0x13, 0x1a, 0x3a, 0x3c, 0x37,
31 0x0e, 0x0d, 0x10, 0x18, 0x28, 0x39, 0x45, 0x38,
32 0x0e, 0x11, 0x16, 0x1d, 0x33, 0x57, 0x50, 0x3e,
33 0x12, 0x16, 0x25, 0x38, 0x44, 0x6d, 0x67, 0x4d,
34 0x18, 0x23, 0x37, 0x40, 0x51, 0x68, 0x71, 0x5c,
35 0x31, 0x40, 0x4e, 0x57, 0x67, 0x79, 0x78, 0x65,
36 0x48, 0x5c, 0x5f, 0x62, 0x70, 0x64, 0x67, 0x63
37 };
38
39 static unsigned char luma_q_table_reordered[ARRAY_SIZE(luma_q_table)];
40
41 static const unsigned char chroma_q_table[] = {
42 0x11, 0x12, 0x18, 0x2f, 0x63, 0x63, 0x63, 0x63,
43 0x12, 0x15, 0x1a, 0x42, 0x63, 0x63, 0x63, 0x63,
44 0x18, 0x1a, 0x38, 0x63, 0x63, 0x63, 0x63, 0x63,
45 0x2f, 0x42, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
46 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
47 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
48 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
49 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63
50 };
51
52 static unsigned char chroma_q_table_reordered[ARRAY_SIZE(chroma_q_table)];
53
54 static const unsigned char zigzag[64] = {
55 0, 1, 8, 16, 9, 2, 3, 10,
56 17, 24, 32, 25, 18, 11, 4, 5,
57 12, 19, 26, 33, 40, 48, 41, 34,
58 27, 20, 13, 6, 7, 14, 21, 28,
59 35, 42, 49, 56, 57, 50, 43, 36,
60 29, 22, 15, 23, 30, 37, 44, 51,
61 58, 59, 52, 45, 38, 31, 39, 46,
62 53, 60, 61, 54, 47, 55, 62, 63
63 };
64
65 static const u32 hw_reorder[64] = {
66 0, 8, 16, 24, 1, 9, 17, 25,
67 32, 40, 48, 56, 33, 41, 49, 57,
68 2, 10, 18, 26, 3, 11, 19, 27,
69 34, 42, 50, 58, 35, 43, 51, 59,
70 4, 12, 20, 28, 5, 13, 21, 29,
71 36, 44, 52, 60, 37, 45, 53, 61,
72 6, 14, 22, 30, 7, 15, 23, 31,
73 38, 46, 54, 62, 39, 47, 55, 63
74 };
75
76 /* Huffman tables are shared with CODA */
77 static const unsigned char luma_dc_table[] = {
78 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01,
79 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
80 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
81 0x08, 0x09, 0x0a, 0x0b,
82 };
83
84 static const unsigned char chroma_dc_table[] = {
85 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
86 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
87 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
88 0x08, 0x09, 0x0a, 0x0b,
89 };
90
91 static const unsigned char luma_ac_table[] = {
92 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03,
93 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d,
94 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
95 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
96 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
97 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
98 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
99 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
100 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
101 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
102 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
103 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
104 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
105 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
106 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
107 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
108 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
109 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
110 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
111 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
112 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
113 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
114 0xf9, 0xfa,
115 };
116
117 static const unsigned char chroma_ac_table[] = {
118 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
119 0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77,
120 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
121 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
122 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
123 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
124 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
125 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
126 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
127 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
128 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
129 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
130 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
131 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
132 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
133 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
134 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
135 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
136 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
137 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
138 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
139 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
140 0xf9, 0xfa,
141 };
142
143 /* For simplicity, we keep a pre-formatted JPEG header,
144 * and we'll use fixed offsets to change the width, height
145 * quantization tables, etc.
146 */
147 static const unsigned char hantro_jpeg_header[JPEG_HEADER_SIZE] = {
148 /* SOI */
149 0xff, 0xd8,
150
151 /* DQT */
152 0xff, 0xdb, 0x00, 0x84,
153
154 0x00,
155 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
156 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
157 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
158 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
159 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
160 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
161 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
162 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
163
164 0x01,
165 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
166 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
167 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
168 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
169 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
170 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
171 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
172 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
173
174 /* SOF */
175 0xff, 0xc0, 0x00, 0x11, 0x08, 0x00, 0xf0, 0x01,
176 0x40, 0x03, 0x01, 0x22, 0x00, 0x02, 0x11, 0x01,
177 0x03, 0x11, 0x01,
178
179 /* DHT */
180 0xff, 0xc4, 0x00, 0x1f, 0x00,
181
182 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
183 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
184 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
185 0x00, 0x00, 0x00, 0x00,
186
187 /* DHT */
188 0xff, 0xc4, 0x00, 0xb5, 0x10,
189
190 0x00, 0x00,
191 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
192 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
193 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
194 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
195 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
196 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
197 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
198 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
199 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
200 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
201 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
202 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
203 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
204 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
205 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
206 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
207 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
208 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
209 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
210 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
211 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
212 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
213
214 /* DHT */
215 0xff, 0xc4, 0x00, 0x1f, 0x01,
216
217 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
218 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
219 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
220 0x00, 0x00, 0x00, 0x00,
221
222 /* DHT */
223 0xff, 0xc4, 0x00, 0xb5, 0x11,
224
225 0x00, 0x00,
226 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
227 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
228 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
229 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
230 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
231 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
232 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
233 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
234 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
235 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
236 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
237 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
238 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
239 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
240 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
241 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
242 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
243 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
244 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
245 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
246 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
247 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
248
249 /* SOS */
250 0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02,
251 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00,
252 };
253
jpeg_scale_qp(const unsigned char qp,int scale)254 static unsigned char jpeg_scale_qp(const unsigned char qp, int scale)
255 {
256 unsigned int temp;
257
258 temp = DIV_ROUND_CLOSEST((unsigned int)qp * scale, 100);
259 if (temp <= 0)
260 temp = 1;
261 if (temp > 255)
262 temp = 255;
263
264 return (unsigned char)temp;
265 }
266
267 static void
jpeg_scale_quant_table(unsigned char * file_q_tab,unsigned char * reordered_q_tab,const unsigned char * tab,int scale)268 jpeg_scale_quant_table(unsigned char *file_q_tab,
269 unsigned char *reordered_q_tab,
270 const unsigned char *tab, int scale)
271 {
272 int i;
273
274 for (i = 0; i < 64; i++) {
275 file_q_tab[i] = jpeg_scale_qp(tab[zigzag[i]], scale);
276 reordered_q_tab[i] = jpeg_scale_qp(tab[hw_reorder[i]], scale);
277 }
278 }
279
jpeg_set_quality(unsigned char * buffer,int quality)280 static void jpeg_set_quality(unsigned char *buffer, int quality)
281 {
282 int scale;
283
284 /*
285 * Non-linear scaling factor:
286 * [5,50] -> [1000..100], [51,100] -> [98..0]
287 */
288 if (quality < 50)
289 scale = 5000 / quality;
290 else
291 scale = 200 - 2 * quality;
292
293 jpeg_scale_quant_table(buffer + LUMA_QUANT_OFF,
294 luma_q_table_reordered,
295 luma_q_table, scale);
296 jpeg_scale_quant_table(buffer + CHROMA_QUANT_OFF,
297 chroma_q_table_reordered,
298 chroma_q_table, scale);
299 }
300
hantro_jpeg_get_qtable(int index)301 unsigned char *hantro_jpeg_get_qtable(int index)
302 {
303 if (index == 0)
304 return luma_q_table_reordered;
305 return chroma_q_table_reordered;
306 }
307
hantro_jpeg_header_assemble(struct hantro_jpeg_ctx * ctx)308 void hantro_jpeg_header_assemble(struct hantro_jpeg_ctx *ctx)
309 {
310 char *buf = ctx->buffer;
311
312 memcpy(buf, hantro_jpeg_header,
313 sizeof(hantro_jpeg_header));
314
315 buf[HEIGHT_OFF + 0] = ctx->height >> 8;
316 buf[HEIGHT_OFF + 1] = ctx->height;
317 buf[WIDTH_OFF + 0] = ctx->width >> 8;
318 buf[WIDTH_OFF + 1] = ctx->width;
319
320 memcpy(buf + HUFF_LUMA_DC_OFF, luma_dc_table, sizeof(luma_dc_table));
321 memcpy(buf + HUFF_LUMA_AC_OFF, luma_ac_table, sizeof(luma_ac_table));
322 memcpy(buf + HUFF_CHROMA_DC_OFF, chroma_dc_table,
323 sizeof(chroma_dc_table));
324 memcpy(buf + HUFF_CHROMA_AC_OFF, chroma_ac_table,
325 sizeof(chroma_ac_table));
326
327 jpeg_set_quality(buf, ctx->quality);
328 }
329
hantro_jpeg_enc_init(struct hantro_ctx * ctx)330 int hantro_jpeg_enc_init(struct hantro_ctx *ctx)
331 {
332 ctx->jpeg_enc.bounce_buffer.size =
333 ctx->dst_fmt.plane_fmt[0].sizeimage -
334 ctx->vpu_dst_fmt->header_size;
335
336 ctx->jpeg_enc.bounce_buffer.cpu =
337 dma_alloc_attrs(ctx->dev->dev,
338 ctx->jpeg_enc.bounce_buffer.size,
339 &ctx->jpeg_enc.bounce_buffer.dma,
340 GFP_KERNEL,
341 DMA_ATTR_ALLOC_SINGLE_PAGES);
342 if (!ctx->jpeg_enc.bounce_buffer.cpu)
343 return -ENOMEM;
344
345 return 0;
346 }
347
hantro_jpeg_enc_exit(struct hantro_ctx * ctx)348 void hantro_jpeg_enc_exit(struct hantro_ctx *ctx)
349 {
350 dma_free_attrs(ctx->dev->dev,
351 ctx->jpeg_enc.bounce_buffer.size,
352 ctx->jpeg_enc.bounce_buffer.cpu,
353 ctx->jpeg_enc.bounce_buffer.dma,
354 DMA_ATTR_ALLOC_SINGLE_PAGES);
355 }
356