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.3, I
27 */
28 static const unsigned char luma_q_table[] = {
29 0x10, 0x0b, 0x0a, 0x10, 0x7c, 0x8c, 0x97, 0xa1,
30 0x0c, 0x0c, 0x0e, 0x13, 0x7e, 0x9e, 0xa0, 0x9b,
31 0x0e, 0x0d, 0x10, 0x18, 0x8c, 0x9d, 0xa9, 0x9c,
32 0x0e, 0x11, 0x16, 0x1d, 0x97, 0xbb, 0xb4, 0xa2,
33 0x12, 0x16, 0x25, 0x38, 0xa8, 0x6d, 0x67, 0xb1,
34 0x18, 0x23, 0x37, 0x40, 0xb5, 0x68, 0x71, 0xc0,
35 0x31, 0x40, 0x4e, 0x57, 0x67, 0x79, 0x78, 0x65,
36 0x48, 0x5c, 0x5f, 0x62, 0x70, 0x64, 0x67, 0xc7,
37 };
38
39 static const unsigned char chroma_q_table[] = {
40 0x11, 0x12, 0x18, 0x2f, 0x63, 0x63, 0x63, 0x63,
41 0x12, 0x15, 0x1a, 0x42, 0x63, 0x63, 0x63, 0x63,
42 0x18, 0x1a, 0x38, 0x63, 0x63, 0x63, 0x63, 0x63,
43 0x2f, 0x42, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
44 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
45 0x63, 0x63, 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 };
49
50 /* Huffman tables are shared with CODA */
51 static const unsigned char luma_dc_table[] = {
52 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01,
53 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
54 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
55 0x08, 0x09, 0x0a, 0x0b,
56 };
57
58 static const unsigned char chroma_dc_table[] = {
59 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
60 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
61 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
62 0x08, 0x09, 0x0a, 0x0b,
63 };
64
65 static const unsigned char luma_ac_table[] = {
66 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03,
67 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d,
68 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
69 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
70 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
71 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
72 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
73 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
74 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
75 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
76 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
77 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
78 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
79 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
80 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
81 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
82 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
83 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
84 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
85 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
86 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
87 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
88 0xf9, 0xfa,
89 };
90
91 static const unsigned char chroma_ac_table[] = {
92 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
93 0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77,
94 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
95 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
96 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
97 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
98 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
99 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
100 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
101 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
102 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
103 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
104 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
105 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
106 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
107 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
108 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
109 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
110 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
111 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
112 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
113 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
114 0xf9, 0xfa,
115 };
116
117 /* For simplicity, we keep a pre-formatted JPEG header,
118 * and we'll use fixed offsets to change the width, height
119 * quantization tables, etc.
120 */
121 static const unsigned char hantro_jpeg_header[JPEG_HEADER_SIZE] = {
122 /* SOI */
123 0xff, 0xd8,
124
125 /* DQT */
126 0xff, 0xdb, 0x00, 0x84,
127
128 0x00,
129 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
130 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
131 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
132 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
133 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
134 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
135 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
136 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
137
138 0x01,
139 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
140 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
141 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
142 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
143 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
144 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
145 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
146 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
147
148 /* SOF */
149 0xff, 0xc0, 0x00, 0x11, 0x08, 0x00, 0xf0, 0x01,
150 0x40, 0x03, 0x01, 0x22, 0x00, 0x02, 0x11, 0x01,
151 0x03, 0x11, 0x01,
152
153 /* DHT */
154 0xff, 0xc4, 0x00, 0x1f, 0x00,
155
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,
160
161 /* DHT */
162 0xff, 0xc4, 0x00, 0xb5, 0x10,
163
164 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,
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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
177 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
178 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
179 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
180 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
181 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x00, 0x00, 0x00, 0x00,
186 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
187
188 /* DHT */
189 0xff, 0xc4, 0x00, 0x1f, 0x01,
190
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,
195
196 /* DHT */
197 0xff, 0xc4, 0x00, 0xb5, 0x11,
198
199 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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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, 0x00, 0x00, 0x00, 0x00,
221 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
222
223 /* SOS */
224 0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02,
225 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00,
226 };
227
228 static void
jpeg_scale_quant_table(unsigned char * q_tab,const unsigned char * tab,int scale)229 jpeg_scale_quant_table(unsigned char *q_tab,
230 const unsigned char *tab, int scale)
231 {
232 unsigned int temp;
233 int i;
234
235 for (i = 0; i < 64; i++) {
236 temp = DIV_ROUND_CLOSEST((unsigned int)tab[i] * scale, 100);
237 if (temp <= 0)
238 temp = 1;
239 if (temp > 255)
240 temp = 255;
241 q_tab[i] = (unsigned char)temp;
242 }
243 }
244
jpeg_set_quality(unsigned char * buffer,int quality)245 static void jpeg_set_quality(unsigned char *buffer, int quality)
246 {
247 int scale;
248
249 /*
250 * Non-linear scaling factor:
251 * [5,50] -> [1000..100], [51,100] -> [98..0]
252 */
253 if (quality < 50)
254 scale = 5000 / quality;
255 else
256 scale = 200 - 2 * quality;
257
258 jpeg_scale_quant_table(buffer + LUMA_QUANT_OFF,
259 luma_q_table, scale);
260 jpeg_scale_quant_table(buffer + CHROMA_QUANT_OFF,
261 chroma_q_table, scale);
262 }
263
264 unsigned char *
hantro_jpeg_get_qtable(struct hantro_jpeg_ctx * ctx,int index)265 hantro_jpeg_get_qtable(struct hantro_jpeg_ctx *ctx, int index)
266 {
267 if (index == 0)
268 return ctx->buffer + LUMA_QUANT_OFF;
269 return ctx->buffer + CHROMA_QUANT_OFF;
270 }
271
hantro_jpeg_header_assemble(struct hantro_jpeg_ctx * ctx)272 void hantro_jpeg_header_assemble(struct hantro_jpeg_ctx *ctx)
273 {
274 char *buf = ctx->buffer;
275
276 memcpy(buf, hantro_jpeg_header,
277 sizeof(hantro_jpeg_header));
278
279 buf[HEIGHT_OFF + 0] = ctx->height >> 8;
280 buf[HEIGHT_OFF + 1] = ctx->height;
281 buf[WIDTH_OFF + 0] = ctx->width >> 8;
282 buf[WIDTH_OFF + 1] = ctx->width;
283
284 memcpy(buf + HUFF_LUMA_DC_OFF, luma_dc_table, sizeof(luma_dc_table));
285 memcpy(buf + HUFF_LUMA_AC_OFF, luma_ac_table, sizeof(luma_ac_table));
286 memcpy(buf + HUFF_CHROMA_DC_OFF, chroma_dc_table,
287 sizeof(chroma_dc_table));
288 memcpy(buf + HUFF_CHROMA_AC_OFF, chroma_ac_table,
289 sizeof(chroma_ac_table));
290
291 jpeg_set_quality(buf, ctx->quality);
292 }
293
hantro_jpeg_enc_init(struct hantro_ctx * ctx)294 int hantro_jpeg_enc_init(struct hantro_ctx *ctx)
295 {
296 ctx->jpeg_enc.bounce_buffer.size =
297 ctx->dst_fmt.plane_fmt[0].sizeimage -
298 ctx->vpu_dst_fmt->header_size;
299
300 ctx->jpeg_enc.bounce_buffer.cpu =
301 dma_alloc_attrs(ctx->dev->dev,
302 ctx->jpeg_enc.bounce_buffer.size,
303 &ctx->jpeg_enc.bounce_buffer.dma,
304 GFP_KERNEL,
305 DMA_ATTR_ALLOC_SINGLE_PAGES);
306 if (!ctx->jpeg_enc.bounce_buffer.cpu)
307 return -ENOMEM;
308
309 return 0;
310 }
311
hantro_jpeg_enc_exit(struct hantro_ctx * ctx)312 void hantro_jpeg_enc_exit(struct hantro_ctx *ctx)
313 {
314 dma_free_attrs(ctx->dev->dev,
315 ctx->jpeg_enc.bounce_buffer.size,
316 ctx->jpeg_enc.bounce_buffer.cpu,
317 ctx->jpeg_enc.bounce_buffer.dma,
318 DMA_ATTR_ALLOC_SINGLE_PAGES);
319 }
320