1
2
3
4
5
6
7
8
9
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
23
24
25
26static 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
31static const unsigned char luma_dc_value[12] = {
32 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
33 0x08, 0x09, 0x0a, 0x0b,
34};
35
36static 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
41static const unsigned char chroma_dc_value[12] = {
42 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
43 0x08, 0x09, 0x0a, 0x0b,
44};
45
46static 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
51static 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,
73};
74
75static 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
80static 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,
102};
103
104
105
106
107
108
109static 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
120static 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
131struct coda_memcpy_desc {
132 int offset;
133 const void *src;
134 size_t len;
135};
136
137static 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
151int 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
171 for (i = 0; i < ARRAY_SIZE(huff); i++)
172 coda_memcpy_parabuf(ctx->parabuf.vaddr, huff + i);
173
174
175 for (i = 0; i < ARRAY_SIZE(qmat); i++)
176 coda_memcpy_parabuf(ctx->parabuf.vaddr, qmat + i);
177
178 return 0;
179}
180
181bool 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
207
208
209static 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
224void 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
231 if (quality > 100)
232 quality = 100;
233 if (quality < 5)
234 quality = 5;
235
236
237
238
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