xref: /linux/drivers/media/platform/verisilicon/hantro_jpeg.c (revision ae22a94997b8a03dcb3c922857c203246711f9d4)
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 
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"
15 #include "hantro.h"
16 
17 #define LUMA_QUANT_OFF		25
18 #define CHROMA_QUANT_OFF	90
19 #define HEIGHT_OFF		159
20 #define WIDTH_OFF		161
21 
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
26 
27 /* Default tables from JPEG ITU-T.81
28  * (ISO/IEC 10918-1) Annex K, tables K.1 and K.2
29  */
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
39 };
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 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
61 };
62 
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
72 };
73 
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,
80 };
81 
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,
87 };
88 
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,
112 	0xf9, 0xfa,
113 };
114 
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,
138 	0xf9, 0xfa,
139 };
140 
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.
144  */
145 static const unsigned char hantro_jpeg_header[] = {
146 	/* SOI */
147 	0xff, 0xd8,
148 
149 	/* JFIF-APP0 */
150 	0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46,
151 	0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01,
152 	0x00, 0x00,
153 
154 	/* DQT */
155 	0xff, 0xdb, 0x00, 0x84,
156 
157 	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 	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,
166 
167 	0x01,
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,
176 
177 	/* SOF */
178 	0xff, 0xc0, 0x00, 0x11, 0x08, 0x00, 0xf0, 0x01,
179 	0x40, 0x03, 0x01, 0x22, 0x00, 0x02, 0x11, 0x01,
180 	0x03, 0x11, 0x01,
181 
182 	/* DHT */
183 	0xff, 0xc4, 0x00, 0x1f, 0x00,
184 
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,
189 
190 	/* DHT */
191 	0xff, 0xc4, 0x00, 0xb5, 0x10,
192 
193 	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 	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,
216 
217 	/* DHT */
218 	0xff, 0xc4, 0x00, 0x1f, 0x01,
219 
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,
224 
225 	/* DHT */
226 	0xff, 0xc4, 0x00, 0xb5, 0x11,
227 
228 	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 	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,
251 
252 	/* COM */
253 	0xff, 0xfe, 0x00, 0x03, 0x00,
254 
255 	/* SOS */
256 	0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02,
257 	0x11, 0x03, 0x11, 0x00, 0x3f, 0x00,
258 };
259 
260 /*
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.
263  */
264 static_assert(sizeof(hantro_jpeg_header) == JPEG_HEADER_SIZE);
265 
266 /*
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
270  * to directly.
271  */
272 static_assert(IS_ALIGNED(sizeof(hantro_jpeg_header), 8),
273 	      "Hantro JPEG header size needs to be 8-byte aligned.");
274 
275 static unsigned char jpeg_scale_qp(const unsigned char qp, int scale)
276 {
277 	unsigned int temp;
278 
279 	temp = DIV_ROUND_CLOSEST((unsigned int)qp * scale, 100);
280 	if (temp <= 0)
281 		temp = 1;
282 	if (temp > 255)
283 		temp = 255;
284 
285 	return (unsigned char)temp;
286 }
287 
288 static void
289 jpeg_scale_quant_table(unsigned char *file_q_tab,
290 		       unsigned char *reordered_q_tab,
291 		       const unsigned char *tab, int scale)
292 {
293 	int i;
294 
295 	BUILD_BUG_ON(ARRAY_SIZE(zigzag) != JPEG_QUANT_SIZE);
296 	BUILD_BUG_ON(ARRAY_SIZE(hw_reorder) != JPEG_QUANT_SIZE);
297 
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);
301 	}
302 }
303 
304 static void jpeg_set_quality(struct hantro_jpeg_ctx *ctx)
305 {
306 	int scale;
307 
308 	/*
309 	 * Non-linear scaling factor:
310 	 * [5,50] -> [1000..100], [51,100] -> [98..0]
311 	 */
312 	if (ctx->quality < 50)
313 		scale = 5000 / ctx->quality;
314 	else
315 		scale = 200 - 2 * ctx->quality;
316 
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);
321 
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);
326 }
327 
328 void hantro_jpeg_header_assemble(struct hantro_jpeg_ctx *ctx)
329 {
330 	char *buf = ctx->buffer;
331 
332 	memcpy(buf, hantro_jpeg_header,
333 	       sizeof(hantro_jpeg_header));
334 
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;
339 
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));
346 
347 	jpeg_set_quality(ctx);
348 }
349