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