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
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, /* padded to 32-bit */
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, /* 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
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	/* 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
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 = be16_to_cpup((__be16 *)vaddr);
185	u16 eoi = be16_to_cpup((__be16 *)(vaddr +
186					  vb2_get_plane_payload(vb, 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 */
195static 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
210void 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}
240