1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (C) Collabora, Ltd.
5 * Based on GSPCA and CODA drivers:
6 * Copyright (C) Jean-Francois Moine (http://moinejf.free.fr)
7 * Copyright (C) 2014 Philipp Zabel, Pengutronix
9 #include <linux/dma-mapping.h>
10 #include <linux/kernel.h>
11 #include <linux/string.h>
12 #include "hantro_jpeg.h"
15 #define LUMA_QUANT_OFF 7
16 #define CHROMA_QUANT_OFF 72
17 #define HEIGHT_OFF 141
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
25 /* Default tables from JPEG ITU-T.81
26 * (ISO/IEC 10918-1) Annex K, tables K.1 and K.2
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
39 static unsigned char luma_q_table_reordered[ARRAY_SIZE(luma_q_table)];
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
52 static unsigned char chroma_q_table_reordered[ARRAY_SIZE(chroma_q_table)];
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
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
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,
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,
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,
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,
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.
147 static const unsigned char hantro_jpeg_header[JPEG_HEADER_SIZE] = {
152 0xff, 0xdb, 0x00, 0x84,
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,
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,
175 0xff, 0xc0, 0x00, 0x11, 0x08, 0x00, 0xf0, 0x01,
176 0x40, 0x03, 0x01, 0x22, 0x00, 0x02, 0x11, 0x01,
180 0xff, 0xc4, 0x00, 0x1f, 0x00,
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,
188 0xff, 0xc4, 0x00, 0xb5, 0x10,
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,
215 0xff, 0xc4, 0x00, 0x1f, 0x01,
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,
223 0xff, 0xc4, 0x00, 0xb5, 0x11,
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,
250 0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02,
251 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00,
254 static unsigned char jpeg_scale_qp(const unsigned char qp, int scale)
258 temp = DIV_ROUND_CLOSEST((unsigned int)qp * scale, 100);
264 return (unsigned char)temp;
268 jpeg_scale_quant_table(unsigned char *file_q_tab,
269 unsigned char *reordered_q_tab,
270 const unsigned char *tab, int scale)
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);
280 static void jpeg_set_quality(unsigned char *buffer, int quality)
285 * Non-linear scaling factor:
286 * [5,50] -> [1000..100], [51,100] -> [98..0]
289 scale = 5000 / quality;
291 scale = 200 - 2 * quality;
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);
301 unsigned char *hantro_jpeg_get_qtable(int index)
304 return luma_q_table_reordered;
305 return chroma_q_table_reordered;
308 void hantro_jpeg_header_assemble(struct hantro_jpeg_ctx *ctx)
310 char *buf = ctx->buffer;
312 memcpy(buf, hantro_jpeg_header,
313 sizeof(hantro_jpeg_header));
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;
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));
327 jpeg_set_quality(buf, ctx->quality);
330 int hantro_jpeg_enc_init(struct hantro_ctx *ctx)
332 ctx->jpeg_enc.bounce_buffer.size =
333 ctx->dst_fmt.plane_fmt[0].sizeimage -
334 ctx->vpu_dst_fmt->header_size;
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,
341 DMA_ATTR_ALLOC_SINGLE_PAGES);
342 if (!ctx->jpeg_enc.bounce_buffer.cpu)
348 void hantro_jpeg_enc_exit(struct hantro_ctx *ctx)
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);