1 /*
2  * Coda multi-standard codec IP - JPEG support functions
3  *
4  * Copyright (C) 2014 Philipp Zabel, Pengutronix
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  */
11 
12 #include <linux/kernel.h>
13 #include <linux/swab.h>
14 
15 #include "coda.h"
16 #include "trace.h"
17 
18 #define SOI_MARKER	0xffd8
19 #define EOI_MARKER	0xffd9
20 
21 /*
22  * Typical Huffman tables for 8-bit precision luminance and
23  * chrominance from JPEG ITU-T.81 (ISO/IEC 10918-1) Annex K.3
24  */
25 
26 static const unsigned char luma_dc_bits[16] = {
27 	0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01,
28 	0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29 };
30 
31 static const unsigned char luma_dc_value[12] = {
32 	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
33 	0x08, 0x09, 0x0a, 0x0b,
34 };
35 
36 static const unsigned char chroma_dc_bits[16] = {
37 	0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
38 	0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
39 };
40 
41 static const unsigned char chroma_dc_value[12] = {
42 	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
43 	0x08, 0x09, 0x0a, 0x0b,
44 };
45 
46 static const unsigned char luma_ac_bits[16] = {
47 	0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03,
48 	0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d,
49 };
50 
51 static const unsigned char luma_ac_value[162 + 2] = {
52 	0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
53 	0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
54 	0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
55 	0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
56 	0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
57 	0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
58 	0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
59 	0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
60 	0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
61 	0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
62 	0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
63 	0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
64 	0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
65 	0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
66 	0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
67 	0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
68 	0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
69 	0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
70 	0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
71 	0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
72 	0xf9, 0xfa, /* padded to 32-bit */
73 };
74 
75 static const unsigned char chroma_ac_bits[16] = {
76 	0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
77 	0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77,
78 };
79 
80 static const unsigned char chroma_ac_value[162 + 2] = {
81 	0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
82 	0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
83 	0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
84 	0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
85 	0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
86 	0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
87 	0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
88 	0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
89 	0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
90 	0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
91 	0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
92 	0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
93 	0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
94 	0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
95 	0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
96 	0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
97 	0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
98 	0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
99 	0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
100 	0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
101 	0xf9, 0xfa, /* padded to 32-bit */
102 };
103 
104 /*
105  * Quantization tables for luminance and chrominance components in
106  * zig-zag scan order from the Freescale i.MX VPU libaries
107  */
108 
109 static unsigned char luma_q[64] = {
110 	0x06, 0x04, 0x04, 0x04, 0x05, 0x04, 0x06, 0x05,
111 	0x05, 0x06, 0x09, 0x06, 0x05, 0x06, 0x09, 0x0b,
112 	0x08, 0x06, 0x06, 0x08, 0x0b, 0x0c, 0x0a, 0x0a,
113 	0x0b, 0x0a, 0x0a, 0x0c, 0x10, 0x0c, 0x0c, 0x0c,
114 	0x0c, 0x0c, 0x0c, 0x10, 0x0c, 0x0c, 0x0c, 0x0c,
115 	0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
116 	0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
117 	0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
118 };
119 
120 static unsigned char chroma_q[64] = {
121 	0x07, 0x07, 0x07, 0x0d, 0x0c, 0x0d, 0x18, 0x10,
122 	0x10, 0x18, 0x14, 0x0e, 0x0e, 0x0e, 0x14, 0x14,
123 	0x0e, 0x0e, 0x0e, 0x0e, 0x14, 0x11, 0x0c, 0x0c,
124 	0x0c, 0x0c, 0x0c, 0x11, 0x11, 0x0c, 0x0c, 0x0c,
125 	0x0c, 0x0c, 0x0c, 0x11, 0x0c, 0x0c, 0x0c, 0x0c,
126 	0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
127 	0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
128 	0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
129 };
130 
131 struct coda_memcpy_desc {
132 	int offset;
133 	const void *src;
134 	size_t len;
135 };
136 
coda_memcpy_parabuf(void * parabuf,const struct coda_memcpy_desc * desc)137 static void coda_memcpy_parabuf(void *parabuf,
138 				const struct coda_memcpy_desc *desc)
139 {
140 	u32 *dst = parabuf + desc->offset;
141 	const u32 *src = desc->src;
142 	int len = desc->len / 4;
143 	int i;
144 
145 	for (i = 0; i < len; i += 2) {
146 		dst[i + 1] = swab32(src[i]);
147 		dst[i] = swab32(src[i + 1]);
148 	}
149 }
150 
coda_jpeg_write_tables(struct coda_ctx * ctx)151 int coda_jpeg_write_tables(struct coda_ctx *ctx)
152 {
153 	int i;
154 	static const struct coda_memcpy_desc huff[8] = {
155 		{ 0,   luma_dc_bits,    sizeof(luma_dc_bits)    },
156 		{ 16,  luma_dc_value,   sizeof(luma_dc_value)   },
157 		{ 32,  luma_ac_bits,    sizeof(luma_ac_bits)    },
158 		{ 48,  luma_ac_value,   sizeof(luma_ac_value)   },
159 		{ 216, chroma_dc_bits,  sizeof(chroma_dc_bits)  },
160 		{ 232, chroma_dc_value, sizeof(chroma_dc_value) },
161 		{ 248, chroma_ac_bits,  sizeof(chroma_ac_bits)  },
162 		{ 264, chroma_ac_value, sizeof(chroma_ac_value) },
163 	};
164 	struct coda_memcpy_desc qmat[3] = {
165 		{ 512, ctx->params.jpeg_qmat_tab[0], 64 },
166 		{ 576, ctx->params.jpeg_qmat_tab[1], 64 },
167 		{ 640, ctx->params.jpeg_qmat_tab[1], 64 },
168 	};
169 
170 	/* Write huffman tables to parameter memory */
171 	for (i = 0; i < ARRAY_SIZE(huff); i++)
172 		coda_memcpy_parabuf(ctx->parabuf.vaddr, huff + i);
173 
174 	/* Write Q-matrix to parameter memory */
175 	for (i = 0; i < ARRAY_SIZE(qmat); i++)
176 		coda_memcpy_parabuf(ctx->parabuf.vaddr, qmat + i);
177 
178 	return 0;
179 }
180 
coda_jpeg_check_buffer(struct coda_ctx * ctx,struct vb2_buffer * vb)181 bool coda_jpeg_check_buffer(struct coda_ctx *ctx, struct vb2_buffer *vb)
182 {
183 	void *vaddr = vb2_plane_vaddr(vb, 0);
184 	u16 soi, eoi;
185 	int len, i;
186 
187 	soi = be16_to_cpup((__be16 *)vaddr);
188 	if (soi != SOI_MARKER)
189 		return false;
190 
191 	len = vb2_get_plane_payload(vb, 0);
192 	vaddr += len - 2;
193 	for (i = 0; i < 32; i++) {
194 		eoi = be16_to_cpup((__be16 *)(vaddr - i));
195 		if (eoi == EOI_MARKER) {
196 			if (i > 0)
197 				vb2_set_plane_payload(vb, 0, len - i);
198 			return true;
199 		}
200 	}
201 
202 	return false;
203 }
204 
205 /*
206  * Scale quantization table using nonlinear scaling factor
207  * u8 qtab[64], scale [50,190]
208  */
coda_scale_quant_table(u8 * q_tab,int scale)209 static void coda_scale_quant_table(u8 *q_tab, int scale)
210 {
211 	unsigned int temp;
212 	int i;
213 
214 	for (i = 0; i < 64; i++) {
215 		temp = DIV_ROUND_CLOSEST((unsigned int)q_tab[i] * scale, 100);
216 		if (temp <= 0)
217 			temp = 1;
218 		if (temp > 255)
219 			temp = 255;
220 		q_tab[i] = (unsigned char)temp;
221 	}
222 }
223 
coda_set_jpeg_compression_quality(struct coda_ctx * ctx,int quality)224 void coda_set_jpeg_compression_quality(struct coda_ctx *ctx, int quality)
225 {
226 	unsigned int scale;
227 
228 	ctx->params.jpeg_quality = quality;
229 
230 	/* Clip quality setting to [5,100] interval */
231 	if (quality > 100)
232 		quality = 100;
233 	if (quality < 5)
234 		quality = 5;
235 
236 	/*
237 	 * Non-linear scaling factor:
238 	 * [5,50] -> [1000..100], [51,100] -> [98..0]
239 	 */
240 	if (quality < 50)
241 		scale = 5000 / quality;
242 	else
243 		scale = 200 - 2 * quality;
244 
245 	if (ctx->params.jpeg_qmat_tab[0]) {
246 		memcpy(ctx->params.jpeg_qmat_tab[0], luma_q, 64);
247 		coda_scale_quant_table(ctx->params.jpeg_qmat_tab[0], scale);
248 	}
249 	if (ctx->params.jpeg_qmat_tab[1]) {
250 		memcpy(ctx->params.jpeg_qmat_tab[1], chroma_q, 64);
251 		coda_scale_quant_table(ctx->params.jpeg_qmat_tab[1], scale);
252 	}
253 }
254