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