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
10 #include <linux/align.h>
11 #include <linux/build_bug.h>
12 #include <linux/kernel.h>
13 #include <linux/string.h>
14 #include "hantro_jpeg.h"
17 #define LUMA_QUANT_OFF 25
18 #define CHROMA_QUANT_OFF 90
19 #define HEIGHT_OFF 159
22 #define HUFF_LUMA_DC_OFF 178
23 #define HUFF_LUMA_AC_OFF 211
24 #define HUFF_CHROMA_DC_OFF 394
25 #define HUFF_CHROMA_AC_OFF 427
27 /* Default tables from JPEG ITU-T.81
28 * (ISO/IEC 10918-1) Annex K, tables K.1 and K.2
30 static const unsigned char luma_q_table[] = {
31 0x10, 0x0b, 0x0a, 0x10, 0x18, 0x28, 0x33, 0x3d,
32 0x0c, 0x0c, 0x0e, 0x13, 0x1a, 0x3a, 0x3c, 0x37,
33 0x0e, 0x0d, 0x10, 0x18, 0x28, 0x39, 0x45, 0x38,
34 0x0e, 0x11, 0x16, 0x1d, 0x33, 0x57, 0x50, 0x3e,
35 0x12, 0x16, 0x25, 0x38, 0x44, 0x6d, 0x67, 0x4d,
36 0x18, 0x23, 0x37, 0x40, 0x51, 0x68, 0x71, 0x5c,
37 0x31, 0x40, 0x4e, 0x57, 0x67, 0x79, 0x78, 0x65,
38 0x48, 0x5c, 0x5f, 0x62, 0x70, 0x64, 0x67, 0x63
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 const unsigned char zigzag[] = {
53 0, 1, 8, 16, 9, 2, 3, 10,
54 17, 24, 32, 25, 18, 11, 4, 5,
55 12, 19, 26, 33, 40, 48, 41, 34,
56 27, 20, 13, 6, 7, 14, 21, 28,
57 35, 42, 49, 56, 57, 50, 43, 36,
58 29, 22, 15, 23, 30, 37, 44, 51,
59 58, 59, 52, 45, 38, 31, 39, 46,
60 53, 60, 61, 54, 47, 55, 62, 63
63 static const u32 hw_reorder[] = {
64 0, 8, 16, 24, 1, 9, 17, 25,
65 32, 40, 48, 56, 33, 41, 49, 57,
66 2, 10, 18, 26, 3, 11, 19, 27,
67 34, 42, 50, 58, 35, 43, 51, 59,
68 4, 12, 20, 28, 5, 13, 21, 29,
69 36, 44, 52, 60, 37, 45, 53, 61,
70 6, 14, 22, 30, 7, 15, 23, 31,
71 38, 46, 54, 62, 39, 47, 55, 63
74 /* Huffman tables are shared with CODA */
75 static const unsigned char luma_dc_table[] = {
76 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01,
77 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
78 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
79 0x08, 0x09, 0x0a, 0x0b,
82 static const unsigned char chroma_dc_table[] = {
83 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
84 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
85 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
86 0x08, 0x09, 0x0a, 0x0b,
89 static const unsigned char luma_ac_table[] = {
90 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03,
91 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d,
92 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
93 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
94 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
95 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
96 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
97 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
98 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
99 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
100 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
101 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
102 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
103 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
104 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
105 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
106 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
107 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
108 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
109 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
110 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
111 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
115 static const unsigned char chroma_ac_table[] = {
116 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
117 0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77,
118 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
119 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
120 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
121 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
122 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
123 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
124 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
125 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
126 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
127 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
128 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
129 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
130 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
131 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
132 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
133 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
134 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
135 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
136 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
137 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
141 /* For simplicity, we keep a pre-formatted JPEG header,
142 * and we'll use fixed offsets to change the width, height
143 * quantization tables, etc.
145 static const unsigned char hantro_jpeg_header[] = {
150 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46,
151 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01,
155 0xff, 0xdb, 0x00, 0x84,
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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
164 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
165 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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
174 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
175 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
178 0xff, 0xc0, 0x00, 0x11, 0x08, 0x00, 0xf0, 0x01,
179 0x40, 0x03, 0x01, 0x22, 0x00, 0x02, 0x11, 0x01,
183 0xff, 0xc4, 0x00, 0x1f, 0x00,
185 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
186 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
187 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
188 0x00, 0x00, 0x00, 0x00,
191 0xff, 0xc4, 0x00, 0xb5, 0x10,
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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
214 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
215 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
218 0xff, 0xc4, 0x00, 0x1f, 0x01,
220 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
221 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
222 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
223 0x00, 0x00, 0x00, 0x00,
226 0xff, 0xc4, 0x00, 0xb5, 0x11,
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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
249 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
250 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
253 0xff, 0xfe, 0x00, 0x03, 0x00,
256 0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02,
257 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00,
261 * JPEG_HEADER_SIZE is used in other parts of the driver in lieu of
262 * "sizeof(hantro_jpeg_header)". The two must be equal.
264 static_assert(sizeof(hantro_jpeg_header) == JPEG_HEADER_SIZE);
267 * hantro_jpeg_header is padded with a COM segment, so that the payload
268 * of the SOS segment (the entropy-encoded image scan), which should
269 * trail the whole header, is 8-byte aligned for the hardware to write
272 static_assert(IS_ALIGNED(sizeof(hantro_jpeg_header), 8),
273 "Hantro JPEG header size needs to be 8-byte aligned.");
275 static unsigned char jpeg_scale_qp(const unsigned char qp, int scale)
279 temp = DIV_ROUND_CLOSEST((unsigned int)qp * scale, 100);
285 return (unsigned char)temp;
289 jpeg_scale_quant_table(unsigned char *file_q_tab,
290 unsigned char *reordered_q_tab,
291 const unsigned char *tab, int scale)
295 BUILD_BUG_ON(ARRAY_SIZE(zigzag) != JPEG_QUANT_SIZE);
296 BUILD_BUG_ON(ARRAY_SIZE(hw_reorder) != JPEG_QUANT_SIZE);
298 for (i = 0; i < JPEG_QUANT_SIZE; i++) {
299 file_q_tab[i] = jpeg_scale_qp(tab[zigzag[i]], scale);
300 reordered_q_tab[i] = jpeg_scale_qp(tab[hw_reorder[i]], scale);
304 static void jpeg_set_quality(struct hantro_jpeg_ctx *ctx)
309 * Non-linear scaling factor:
310 * [5,50] -> [1000..100], [51,100] -> [98..0]
312 if (ctx->quality < 50)
313 scale = 5000 / ctx->quality;
315 scale = 200 - 2 * ctx->quality;
317 BUILD_BUG_ON(ARRAY_SIZE(luma_q_table) != JPEG_QUANT_SIZE);
318 BUILD_BUG_ON(ARRAY_SIZE(chroma_q_table) != JPEG_QUANT_SIZE);
319 BUILD_BUG_ON(ARRAY_SIZE(ctx->hw_luma_qtable) != JPEG_QUANT_SIZE);
320 BUILD_BUG_ON(ARRAY_SIZE(ctx->hw_chroma_qtable) != JPEG_QUANT_SIZE);
322 jpeg_scale_quant_table(ctx->buffer + LUMA_QUANT_OFF,
323 ctx->hw_luma_qtable, luma_q_table, scale);
324 jpeg_scale_quant_table(ctx->buffer + CHROMA_QUANT_OFF,
325 ctx->hw_chroma_qtable, chroma_q_table, scale);
328 void hantro_jpeg_header_assemble(struct hantro_jpeg_ctx *ctx)
330 char *buf = ctx->buffer;
332 memcpy(buf, hantro_jpeg_header,
333 sizeof(hantro_jpeg_header));
335 buf[HEIGHT_OFF + 0] = ctx->height >> 8;
336 buf[HEIGHT_OFF + 1] = ctx->height;
337 buf[WIDTH_OFF + 0] = ctx->width >> 8;
338 buf[WIDTH_OFF + 1] = ctx->width;
340 memcpy(buf + HUFF_LUMA_DC_OFF, luma_dc_table, sizeof(luma_dc_table));
341 memcpy(buf + HUFF_LUMA_AC_OFF, luma_ac_table, sizeof(luma_ac_table));
342 memcpy(buf + HUFF_CHROMA_DC_OFF, chroma_dc_table,
343 sizeof(chroma_dc_table));
344 memcpy(buf + HUFF_CHROMA_AC_OFF, chroma_ac_table,
345 sizeof(chroma_ac_table));
347 jpeg_set_quality(ctx);