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_v4l2_buffer * vb)181 bool coda_jpeg_check_buffer(struct coda_ctx *ctx, struct vb2_v4l2_buffer *vb)
182 {
183 	void *vaddr = vb2_plane_vaddr(&vb->vb2_buf, 0);
184 	u16 soi = be16_to_cpup((__be16 *)vaddr);
185 	u16 eoi = be16_to_cpup((__be16 *)(vaddr +
186 			  vb2_get_plane_payload(&vb->vb2_buf, 0) - 2));
187 
188 	return soi == SOI_MARKER && eoi == EOI_MARKER;
189 }
190 
191 /*
192  * Scale quantization table using nonlinear scaling factor
193  * u8 qtab[64], scale [50,190]
194  */
coda_scale_quant_table(u8 * q_tab,int scale)195 static void coda_scale_quant_table(u8 *q_tab, int scale)
196 {
197 	unsigned int temp;
198 	int i;
199 
200 	for (i = 0; i < 64; i++) {
201 		temp = DIV_ROUND_CLOSEST((unsigned int)q_tab[i] * scale, 100);
202 		if (temp <= 0)
203 			temp = 1;
204 		if (temp > 255)
205 			temp = 255;
206 		q_tab[i] = (unsigned char)temp;
207 	}
208 }
209 
coda_set_jpeg_compression_quality(struct coda_ctx * ctx,int quality)210 void coda_set_jpeg_compression_quality(struct coda_ctx *ctx, int quality)
211 {
212 	unsigned int scale;
213 
214 	ctx->params.jpeg_quality = quality;
215 
216 	/* Clip quality setting to [5,100] interval */
217 	if (quality > 100)
218 		quality = 100;
219 	if (quality < 5)
220 		quality = 5;
221 
222 	/*
223 	 * Non-linear scaling factor:
224 	 * [5,50] -> [1000..100], [51,100] -> [98..0]
225 	 */
226 	if (quality < 50)
227 		scale = 5000 / quality;
228 	else
229 		scale = 200 - 2 * quality;
230 
231 	if (ctx->params.jpeg_qmat_tab[0]) {
232 		memcpy(ctx->params.jpeg_qmat_tab[0], luma_q, 64);
233 		coda_scale_quant_table(ctx->params.jpeg_qmat_tab[0], scale);
234 	}
235 	if (ctx->params.jpeg_qmat_tab[1]) {
236 		memcpy(ctx->params.jpeg_qmat_tab[1], chroma_q, 64);
237 		coda_scale_quant_table(ctx->params.jpeg_qmat_tab[1], scale);
238 	}
239 }
240