]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/media/platform/coda/coda-jpeg.c
Merge remote-tracking branch 'v4l-dvb/master'
[karo-tx-linux.git] / drivers / media / platform / coda / coda-jpeg.c
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
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
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
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  */
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
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 }