• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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