]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - drivers/media/platform/coda/coda-jpeg.c
Merge branch 'timers-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[mirror_ubuntu-jammy-kernel.git] / drivers / media / platform / coda / coda-jpeg.c
CommitLineData
2874c5fd 1// SPDX-License-Identifier: GPL-2.0-or-later
cb1d3a33
PZ
2/*
3 * Coda multi-standard codec IP - JPEG support functions
4 *
5 * Copyright (C) 2014 Philipp Zabel, Pengutronix
cb1d3a33
PZ
6 */
7
8#include <linux/kernel.h>
9#include <linux/swab.h>
10
11#include "coda.h"
9a1a8f99 12#include "trace.h"
cb1d3a33 13
edc16cb1
PZ
14#define SOI_MARKER 0xffd8
15#define EOI_MARKER 0xffd9
16
cb1d3a33
PZ
17/*
18 * Typical Huffman tables for 8-bit precision luminance and
19 * chrominance from JPEG ITU-T.81 (ISO/IEC 10918-1) Annex K.3
20 */
21
22static 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
27static const unsigned char luma_dc_value[12] = {
28 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
29 0x08, 0x09, 0x0a, 0x0b,
30};
31
32static 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
37static const unsigned char chroma_dc_value[12] = {
38 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
39 0x08, 0x09, 0x0a, 0x0b,
40};
41
42static 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
47static 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, /* padded to 32-bit */
69};
70
71static 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
76static 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, /* padded to 32-bit */
98};
99
100/*
101 * Quantization tables for luminance and chrominance components in
8b72c18d 102 * zig-zag scan order from the Freescale i.MX VPU libraries
cb1d3a33
PZ
103 */
104
105static 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
116static 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
127struct coda_memcpy_desc {
128 int offset;
129 const void *src;
130 size_t len;
131};
132
133static 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
147int 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 /* Write huffman tables to parameter memory */
167 for (i = 0; i < ARRAY_SIZE(huff); i++)
168 coda_memcpy_parabuf(ctx->parabuf.vaddr, huff + i);
169
170 /* Write Q-matrix to parameter memory */
171 for (i = 0; i < ARRAY_SIZE(qmat); i++)
172 coda_memcpy_parabuf(ctx->parabuf.vaddr, qmat + i);
173
174 return 0;
175}
176
d4de047b 177bool coda_jpeg_check_buffer(struct coda_ctx *ctx, struct vb2_buffer *vb)
edc16cb1 178{
d4de047b
PZ
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 }
edc16cb1 197
d4de047b 198 return false;
edc16cb1
PZ
199}
200
cb1d3a33
PZ
201/*
202 * Scale quantization table using nonlinear scaling factor
203 * u8 qtab[64], scale [50,190]
204 */
205static 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
220void 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 /* Clip quality setting to [5,100] interval */
227 if (quality > 100)
228 quality = 100;
229 if (quality < 5)
230 quality = 5;
231
232 /*
233 * Non-linear scaling factor:
234 * [5,50] -> [1000..100], [51,100] -> [98..0]
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}