.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * Coda multi-standard codec IP - JPEG support functions |
---|
3 | 4 | * |
---|
4 | 5 | * 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 | 6 | */ |
---|
11 | 7 | |
---|
| 8 | +#include <asm/unaligned.h> |
---|
| 9 | +#include <linux/irqreturn.h> |
---|
12 | 10 | #include <linux/kernel.h> |
---|
| 11 | +#include <linux/ktime.h> |
---|
| 12 | +#include <linux/slab.h> |
---|
13 | 13 | #include <linux/swab.h> |
---|
| 14 | +#include <linux/videodev2.h> |
---|
| 15 | + |
---|
| 16 | +#include <media/v4l2-common.h> |
---|
| 17 | +#include <media/v4l2-fh.h> |
---|
| 18 | +#include <media/v4l2-jpeg.h> |
---|
| 19 | +#include <media/v4l2-mem2mem.h> |
---|
| 20 | +#include <media/videobuf2-core.h> |
---|
| 21 | +#include <media/videobuf2-dma-contig.h> |
---|
14 | 22 | |
---|
15 | 23 | #include "coda.h" |
---|
16 | 24 | #include "trace.h" |
---|
17 | 25 | |
---|
18 | 26 | #define SOI_MARKER 0xffd8 |
---|
| 27 | +#define APP9_MARKER 0xffe9 |
---|
| 28 | +#define DRI_MARKER 0xffdd |
---|
| 29 | +#define DQT_MARKER 0xffdb |
---|
| 30 | +#define DHT_MARKER 0xffc4 |
---|
| 31 | +#define SOF_MARKER 0xffc0 |
---|
| 32 | +#define SOS_MARKER 0xffda |
---|
19 | 33 | #define EOI_MARKER 0xffd9 |
---|
| 34 | + |
---|
| 35 | +enum { |
---|
| 36 | + CODA9_JPEG_FORMAT_420, |
---|
| 37 | + CODA9_JPEG_FORMAT_422, |
---|
| 38 | + CODA9_JPEG_FORMAT_224, |
---|
| 39 | + CODA9_JPEG_FORMAT_444, |
---|
| 40 | + CODA9_JPEG_FORMAT_400, |
---|
| 41 | +}; |
---|
| 42 | + |
---|
| 43 | +struct coda_huff_tab { |
---|
| 44 | + u8 luma_dc[16 + 12]; |
---|
| 45 | + u8 chroma_dc[16 + 12]; |
---|
| 46 | + u8 luma_ac[16 + 162]; |
---|
| 47 | + u8 chroma_ac[16 + 162]; |
---|
| 48 | + |
---|
| 49 | + /* DC Luma, DC Chroma, AC Luma, AC Chroma */ |
---|
| 50 | + s16 min[4 * 16]; |
---|
| 51 | + s16 max[4 * 16]; |
---|
| 52 | + s8 ptr[4 * 16]; |
---|
| 53 | +}; |
---|
| 54 | + |
---|
| 55 | +#define CODA9_JPEG_ENC_HUFF_DATA_SIZE (256 + 256 + 16 + 16) |
---|
20 | 56 | |
---|
21 | 57 | /* |
---|
22 | 58 | * Typical Huffman tables for 8-bit precision luminance and |
---|
23 | 59 | * chrominance from JPEG ITU-T.81 (ISO/IEC 10918-1) Annex K.3 |
---|
24 | 60 | */ |
---|
25 | 61 | |
---|
26 | | -static const unsigned char luma_dc_bits[16] = { |
---|
| 62 | +static const unsigned char luma_dc[16 + 12] = { |
---|
| 63 | + /* bits */ |
---|
27 | 64 | 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, |
---|
28 | 65 | 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
---|
29 | | -}; |
---|
30 | | - |
---|
31 | | -static const unsigned char luma_dc_value[12] = { |
---|
| 66 | + /* values */ |
---|
32 | 67 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, |
---|
33 | 68 | 0x08, 0x09, 0x0a, 0x0b, |
---|
34 | 69 | }; |
---|
35 | 70 | |
---|
36 | | -static const unsigned char chroma_dc_bits[16] = { |
---|
| 71 | +static const unsigned char chroma_dc[16 + 12] = { |
---|
| 72 | + /* bits */ |
---|
37 | 73 | 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, |
---|
38 | 74 | 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, |
---|
39 | | -}; |
---|
40 | | - |
---|
41 | | -static const unsigned char chroma_dc_value[12] = { |
---|
| 75 | + /* values */ |
---|
42 | 76 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, |
---|
43 | 77 | 0x08, 0x09, 0x0a, 0x0b, |
---|
44 | 78 | }; |
---|
45 | 79 | |
---|
46 | | -static const unsigned char luma_ac_bits[16] = { |
---|
| 80 | +static const unsigned char luma_ac[16 + 162 + 2] = { |
---|
| 81 | + /* bits */ |
---|
47 | 82 | 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, |
---|
48 | 83 | 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d, |
---|
49 | | -}; |
---|
50 | | - |
---|
51 | | -static const unsigned char luma_ac_value[162 + 2] = { |
---|
| 84 | + /* values */ |
---|
52 | 85 | 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, |
---|
53 | 86 | 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, |
---|
54 | 87 | 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, |
---|
.. | .. |
---|
72 | 105 | 0xf9, 0xfa, /* padded to 32-bit */ |
---|
73 | 106 | }; |
---|
74 | 107 | |
---|
75 | | -static const unsigned char chroma_ac_bits[16] = { |
---|
| 108 | +static const unsigned char chroma_ac[16 + 162 + 2] = { |
---|
| 109 | + /* bits */ |
---|
76 | 110 | 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, |
---|
77 | 111 | 0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, |
---|
78 | | -}; |
---|
79 | | - |
---|
80 | | -static const unsigned char chroma_ac_value[162 + 2] = { |
---|
| 112 | + /* values */ |
---|
81 | 113 | 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, |
---|
82 | 114 | 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, |
---|
83 | 115 | 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, |
---|
.. | .. |
---|
103 | 135 | |
---|
104 | 136 | /* |
---|
105 | 137 | * Quantization tables for luminance and chrominance components in |
---|
106 | | - * zig-zag scan order from the Freescale i.MX VPU libaries |
---|
| 138 | + * zig-zag scan order from the Freescale i.MX VPU libraries |
---|
107 | 139 | */ |
---|
108 | 140 | |
---|
109 | 141 | static unsigned char luma_q[64] = { |
---|
.. | .. |
---|
127 | 159 | 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, |
---|
128 | 160 | 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, |
---|
129 | 161 | }; |
---|
| 162 | + |
---|
| 163 | +static const unsigned char width_align[] = { |
---|
| 164 | + [CODA9_JPEG_FORMAT_420] = 16, |
---|
| 165 | + [CODA9_JPEG_FORMAT_422] = 16, |
---|
| 166 | + [CODA9_JPEG_FORMAT_224] = 8, |
---|
| 167 | + [CODA9_JPEG_FORMAT_444] = 8, |
---|
| 168 | + [CODA9_JPEG_FORMAT_400] = 8, |
---|
| 169 | +}; |
---|
| 170 | + |
---|
| 171 | +static const unsigned char height_align[] = { |
---|
| 172 | + [CODA9_JPEG_FORMAT_420] = 16, |
---|
| 173 | + [CODA9_JPEG_FORMAT_422] = 8, |
---|
| 174 | + [CODA9_JPEG_FORMAT_224] = 16, |
---|
| 175 | + [CODA9_JPEG_FORMAT_444] = 8, |
---|
| 176 | + [CODA9_JPEG_FORMAT_400] = 8, |
---|
| 177 | +}; |
---|
| 178 | + |
---|
| 179 | +static int coda9_jpeg_chroma_format(u32 pixfmt) |
---|
| 180 | +{ |
---|
| 181 | + switch (pixfmt) { |
---|
| 182 | + case V4L2_PIX_FMT_YUV420: |
---|
| 183 | + case V4L2_PIX_FMT_NV12: |
---|
| 184 | + return CODA9_JPEG_FORMAT_420; |
---|
| 185 | + case V4L2_PIX_FMT_YUV422P: |
---|
| 186 | + return CODA9_JPEG_FORMAT_422; |
---|
| 187 | + case V4L2_PIX_FMT_YUV444: |
---|
| 188 | + return CODA9_JPEG_FORMAT_444; |
---|
| 189 | + case V4L2_PIX_FMT_GREY: |
---|
| 190 | + return CODA9_JPEG_FORMAT_400; |
---|
| 191 | + } |
---|
| 192 | + return -EINVAL; |
---|
| 193 | +} |
---|
130 | 194 | |
---|
131 | 195 | struct coda_memcpy_desc { |
---|
132 | 196 | int offset; |
---|
.. | .. |
---|
152 | 216 | { |
---|
153 | 217 | int i; |
---|
154 | 218 | 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) }, |
---|
| 219 | + { 0, luma_dc, sizeof(luma_dc) }, |
---|
| 220 | + { 32, luma_ac, sizeof(luma_ac) }, |
---|
| 221 | + { 216, chroma_dc, sizeof(chroma_dc) }, |
---|
| 222 | + { 248, chroma_ac, sizeof(chroma_ac) }, |
---|
163 | 223 | }; |
---|
164 | 224 | struct coda_memcpy_desc qmat[3] = { |
---|
165 | 225 | { 512, ctx->params.jpeg_qmat_tab[0], 64 }, |
---|
.. | .. |
---|
200 | 260 | } |
---|
201 | 261 | |
---|
202 | 262 | return false; |
---|
| 263 | +} |
---|
| 264 | + |
---|
| 265 | +static int coda9_jpeg_gen_dec_huff_tab(struct coda_ctx *ctx, int tab_num); |
---|
| 266 | + |
---|
| 267 | +int coda_jpeg_decode_header(struct coda_ctx *ctx, struct vb2_buffer *vb) |
---|
| 268 | +{ |
---|
| 269 | + struct coda_dev *dev = ctx->dev; |
---|
| 270 | + u8 *buf = vb2_plane_vaddr(vb, 0); |
---|
| 271 | + size_t len = vb2_get_plane_payload(vb, 0); |
---|
| 272 | + struct v4l2_jpeg_scan_header scan_header; |
---|
| 273 | + struct v4l2_jpeg_reference quantization_tables[4] = { }; |
---|
| 274 | + struct v4l2_jpeg_reference huffman_tables[4] = { }; |
---|
| 275 | + struct v4l2_jpeg_header header = { |
---|
| 276 | + .scan = &scan_header, |
---|
| 277 | + .quantization_tables = quantization_tables, |
---|
| 278 | + .huffman_tables = huffman_tables, |
---|
| 279 | + }; |
---|
| 280 | + struct coda_q_data *q_data_src; |
---|
| 281 | + struct coda_huff_tab *huff_tab; |
---|
| 282 | + int i, j, ret; |
---|
| 283 | + |
---|
| 284 | + ret = v4l2_jpeg_parse_header(buf, len, &header); |
---|
| 285 | + if (ret < 0) { |
---|
| 286 | + v4l2_err(&dev->v4l2_dev, "failed to parse header\n"); |
---|
| 287 | + return ret; |
---|
| 288 | + } |
---|
| 289 | + |
---|
| 290 | + ctx->params.jpeg_restart_interval = header.restart_interval; |
---|
| 291 | + |
---|
| 292 | + /* check frame header */ |
---|
| 293 | + if (header.frame.height > ctx->codec->max_h || |
---|
| 294 | + header.frame.width > ctx->codec->max_w) { |
---|
| 295 | + v4l2_err(&dev->v4l2_dev, "invalid dimensions: %dx%d\n", |
---|
| 296 | + header.frame.width, header.frame.height); |
---|
| 297 | + return -EINVAL; |
---|
| 298 | + } |
---|
| 299 | + |
---|
| 300 | + q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); |
---|
| 301 | + if (header.frame.height != q_data_src->height || |
---|
| 302 | + header.frame.width != q_data_src->width) { |
---|
| 303 | + v4l2_err(&dev->v4l2_dev, |
---|
| 304 | + "dimensions don't match format: %dx%d\n", |
---|
| 305 | + header.frame.width, header.frame.height); |
---|
| 306 | + return -EINVAL; |
---|
| 307 | + } |
---|
| 308 | + |
---|
| 309 | + if (header.frame.num_components != 3) { |
---|
| 310 | + v4l2_err(&dev->v4l2_dev, |
---|
| 311 | + "unsupported number of components: %d\n", |
---|
| 312 | + header.frame.num_components); |
---|
| 313 | + return -EINVAL; |
---|
| 314 | + } |
---|
| 315 | + |
---|
| 316 | + /* install quantization tables */ |
---|
| 317 | + if (quantization_tables[3].start) { |
---|
| 318 | + v4l2_err(&dev->v4l2_dev, |
---|
| 319 | + "only 3 quantization tables supported\n"); |
---|
| 320 | + return -EINVAL; |
---|
| 321 | + } |
---|
| 322 | + for (i = 0; i < 3; i++) { |
---|
| 323 | + if (!quantization_tables[i].start) |
---|
| 324 | + continue; |
---|
| 325 | + if (quantization_tables[i].length != 64) { |
---|
| 326 | + v4l2_err(&dev->v4l2_dev, |
---|
| 327 | + "only 8-bit quantization tables supported\n"); |
---|
| 328 | + continue; |
---|
| 329 | + } |
---|
| 330 | + if (!ctx->params.jpeg_qmat_tab[i]) { |
---|
| 331 | + ctx->params.jpeg_qmat_tab[i] = kmalloc(64, GFP_KERNEL); |
---|
| 332 | + if (!ctx->params.jpeg_qmat_tab[i]) |
---|
| 333 | + return -ENOMEM; |
---|
| 334 | + } |
---|
| 335 | + memcpy(ctx->params.jpeg_qmat_tab[i], |
---|
| 336 | + quantization_tables[i].start, 64); |
---|
| 337 | + } |
---|
| 338 | + |
---|
| 339 | + /* install Huffman tables */ |
---|
| 340 | + for (i = 0; i < 4; i++) { |
---|
| 341 | + if (!huffman_tables[i].start) { |
---|
| 342 | + v4l2_err(&dev->v4l2_dev, "missing Huffman table\n"); |
---|
| 343 | + return -EINVAL; |
---|
| 344 | + } |
---|
| 345 | + /* AC tables should be between 17 -> 178, DC between 17 -> 28 */ |
---|
| 346 | + if (huffman_tables[i].length < 17 || |
---|
| 347 | + huffman_tables[i].length > 178 || |
---|
| 348 | + ((i & 2) == 0 && huffman_tables[i].length > 28)) { |
---|
| 349 | + v4l2_err(&dev->v4l2_dev, |
---|
| 350 | + "invalid Huffman table %d length: %zu\n", |
---|
| 351 | + i, huffman_tables[i].length); |
---|
| 352 | + return -EINVAL; |
---|
| 353 | + } |
---|
| 354 | + } |
---|
| 355 | + huff_tab = ctx->params.jpeg_huff_tab; |
---|
| 356 | + if (!huff_tab) { |
---|
| 357 | + huff_tab = kzalloc(sizeof(struct coda_huff_tab), GFP_KERNEL); |
---|
| 358 | + if (!huff_tab) |
---|
| 359 | + return -ENOMEM; |
---|
| 360 | + ctx->params.jpeg_huff_tab = huff_tab; |
---|
| 361 | + } |
---|
| 362 | + |
---|
| 363 | + memset(huff_tab, 0, sizeof(*huff_tab)); |
---|
| 364 | + memcpy(huff_tab->luma_dc, huffman_tables[0].start, huffman_tables[0].length); |
---|
| 365 | + memcpy(huff_tab->chroma_dc, huffman_tables[1].start, huffman_tables[1].length); |
---|
| 366 | + memcpy(huff_tab->luma_ac, huffman_tables[2].start, huffman_tables[2].length); |
---|
| 367 | + memcpy(huff_tab->chroma_ac, huffman_tables[3].start, huffman_tables[3].length); |
---|
| 368 | + |
---|
| 369 | + /* check scan header */ |
---|
| 370 | + for (i = 0; i < scan_header.num_components; i++) { |
---|
| 371 | + struct v4l2_jpeg_scan_component_spec *scan_component; |
---|
| 372 | + |
---|
| 373 | + scan_component = &scan_header.component[i]; |
---|
| 374 | + for (j = 0; j < header.frame.num_components; j++) { |
---|
| 375 | + if (header.frame.component[j].component_identifier == |
---|
| 376 | + scan_component->component_selector) |
---|
| 377 | + break; |
---|
| 378 | + } |
---|
| 379 | + if (j == header.frame.num_components) |
---|
| 380 | + continue; |
---|
| 381 | + |
---|
| 382 | + ctx->params.jpeg_huff_dc_index[j] = |
---|
| 383 | + scan_component->dc_entropy_coding_table_selector; |
---|
| 384 | + ctx->params.jpeg_huff_ac_index[j] = |
---|
| 385 | + scan_component->ac_entropy_coding_table_selector; |
---|
| 386 | + } |
---|
| 387 | + |
---|
| 388 | + /* Generate Huffman table information */ |
---|
| 389 | + for (i = 0; i < 4; i++) |
---|
| 390 | + coda9_jpeg_gen_dec_huff_tab(ctx, i); |
---|
| 391 | + |
---|
| 392 | + /* start of entropy coded segment */ |
---|
| 393 | + ctx->jpeg_ecs_offset = header.ecs_offset; |
---|
| 394 | + |
---|
| 395 | + switch (header.frame.subsampling) { |
---|
| 396 | + case V4L2_JPEG_CHROMA_SUBSAMPLING_420: |
---|
| 397 | + case V4L2_JPEG_CHROMA_SUBSAMPLING_422: |
---|
| 398 | + ctx->params.jpeg_chroma_subsampling = header.frame.subsampling; |
---|
| 399 | + break; |
---|
| 400 | + default: |
---|
| 401 | + v4l2_err(&dev->v4l2_dev, "chroma subsampling not supported: %d", |
---|
| 402 | + header.frame.subsampling); |
---|
| 403 | + return -EINVAL; |
---|
| 404 | + } |
---|
| 405 | + |
---|
| 406 | + return 0; |
---|
| 407 | +} |
---|
| 408 | + |
---|
| 409 | +static inline void coda9_jpeg_write_huff_values(struct coda_dev *dev, u8 *bits, |
---|
| 410 | + int num_values) |
---|
| 411 | +{ |
---|
| 412 | + s8 *values = (s8 *)(bits + 16); |
---|
| 413 | + int huff_length, i; |
---|
| 414 | + |
---|
| 415 | + for (huff_length = 0, i = 0; i < 16; i++) |
---|
| 416 | + huff_length += bits[i]; |
---|
| 417 | + for (i = huff_length; i < num_values; i++) |
---|
| 418 | + values[i] = -1; |
---|
| 419 | + for (i = 0; i < num_values; i++) |
---|
| 420 | + coda_write(dev, (s32)values[i], CODA9_REG_JPEG_HUFF_DATA); |
---|
| 421 | +} |
---|
| 422 | + |
---|
| 423 | +static int coda9_jpeg_dec_huff_setup(struct coda_ctx *ctx) |
---|
| 424 | +{ |
---|
| 425 | + struct coda_huff_tab *huff_tab = ctx->params.jpeg_huff_tab; |
---|
| 426 | + struct coda_dev *dev = ctx->dev; |
---|
| 427 | + s16 *huff_min = huff_tab->min; |
---|
| 428 | + s16 *huff_max = huff_tab->max; |
---|
| 429 | + s8 *huff_ptr = huff_tab->ptr; |
---|
| 430 | + int i; |
---|
| 431 | + |
---|
| 432 | + /* MIN Tables */ |
---|
| 433 | + coda_write(dev, 0x003, CODA9_REG_JPEG_HUFF_CTRL); |
---|
| 434 | + coda_write(dev, 0x000, CODA9_REG_JPEG_HUFF_ADDR); |
---|
| 435 | + for (i = 0; i < 4 * 16; i++) |
---|
| 436 | + coda_write(dev, (s32)huff_min[i], CODA9_REG_JPEG_HUFF_DATA); |
---|
| 437 | + |
---|
| 438 | + /* MAX Tables */ |
---|
| 439 | + coda_write(dev, 0x403, CODA9_REG_JPEG_HUFF_CTRL); |
---|
| 440 | + coda_write(dev, 0x440, CODA9_REG_JPEG_HUFF_ADDR); |
---|
| 441 | + for (i = 0; i < 4 * 16; i++) |
---|
| 442 | + coda_write(dev, (s32)huff_max[i], CODA9_REG_JPEG_HUFF_DATA); |
---|
| 443 | + |
---|
| 444 | + /* PTR Tables */ |
---|
| 445 | + coda_write(dev, 0x803, CODA9_REG_JPEG_HUFF_CTRL); |
---|
| 446 | + coda_write(dev, 0x880, CODA9_REG_JPEG_HUFF_ADDR); |
---|
| 447 | + for (i = 0; i < 4 * 16; i++) |
---|
| 448 | + coda_write(dev, (s32)huff_ptr[i], CODA9_REG_JPEG_HUFF_DATA); |
---|
| 449 | + |
---|
| 450 | + /* VAL Tables: DC Luma, DC Chroma, AC Luma, AC Chroma */ |
---|
| 451 | + coda_write(dev, 0xc03, CODA9_REG_JPEG_HUFF_CTRL); |
---|
| 452 | + coda9_jpeg_write_huff_values(dev, huff_tab->luma_dc, 12); |
---|
| 453 | + coda9_jpeg_write_huff_values(dev, huff_tab->chroma_dc, 12); |
---|
| 454 | + coda9_jpeg_write_huff_values(dev, huff_tab->luma_ac, 162); |
---|
| 455 | + coda9_jpeg_write_huff_values(dev, huff_tab->chroma_ac, 162); |
---|
| 456 | + coda_write(dev, 0x000, CODA9_REG_JPEG_HUFF_CTRL); |
---|
| 457 | + return 0; |
---|
| 458 | +} |
---|
| 459 | + |
---|
| 460 | +static inline void coda9_jpeg_write_qmat_tab(struct coda_dev *dev, |
---|
| 461 | + u8 *qmat, int index) |
---|
| 462 | +{ |
---|
| 463 | + int i; |
---|
| 464 | + |
---|
| 465 | + coda_write(dev, index | 0x3, CODA9_REG_JPEG_QMAT_CTRL); |
---|
| 466 | + for (i = 0; i < 64; i++) |
---|
| 467 | + coda_write(dev, qmat[i], CODA9_REG_JPEG_QMAT_DATA); |
---|
| 468 | + coda_write(dev, 0, CODA9_REG_JPEG_QMAT_CTRL); |
---|
| 469 | +} |
---|
| 470 | + |
---|
| 471 | +static void coda9_jpeg_qmat_setup(struct coda_ctx *ctx) |
---|
| 472 | +{ |
---|
| 473 | + struct coda_dev *dev = ctx->dev; |
---|
| 474 | + int *qmat_index = ctx->params.jpeg_qmat_index; |
---|
| 475 | + u8 **qmat_tab = ctx->params.jpeg_qmat_tab; |
---|
| 476 | + |
---|
| 477 | + coda9_jpeg_write_qmat_tab(dev, qmat_tab[qmat_index[0]], 0x00); |
---|
| 478 | + coda9_jpeg_write_qmat_tab(dev, qmat_tab[qmat_index[1]], 0x40); |
---|
| 479 | + coda9_jpeg_write_qmat_tab(dev, qmat_tab[qmat_index[2]], 0x80); |
---|
| 480 | +} |
---|
| 481 | + |
---|
| 482 | +static void coda9_jpeg_dec_bbc_gbu_setup(struct coda_ctx *ctx, |
---|
| 483 | + struct vb2_buffer *buf, u32 ecs_offset) |
---|
| 484 | +{ |
---|
| 485 | + struct coda_dev *dev = ctx->dev; |
---|
| 486 | + int page_ptr, word_ptr, bit_ptr; |
---|
| 487 | + u32 bbc_base_addr, end_addr; |
---|
| 488 | + int bbc_cur_pos; |
---|
| 489 | + int ret, val; |
---|
| 490 | + |
---|
| 491 | + bbc_base_addr = vb2_dma_contig_plane_dma_addr(buf, 0); |
---|
| 492 | + end_addr = bbc_base_addr + vb2_get_plane_payload(buf, 0); |
---|
| 493 | + |
---|
| 494 | + page_ptr = ecs_offset / 256; |
---|
| 495 | + word_ptr = (ecs_offset % 256) / 4; |
---|
| 496 | + if (page_ptr & 1) |
---|
| 497 | + word_ptr += 64; |
---|
| 498 | + bit_ptr = (ecs_offset % 4) * 8; |
---|
| 499 | + if (word_ptr & 1) |
---|
| 500 | + bit_ptr += 32; |
---|
| 501 | + word_ptr &= ~0x1; |
---|
| 502 | + |
---|
| 503 | + coda_write(dev, end_addr, CODA9_REG_JPEG_BBC_WR_PTR); |
---|
| 504 | + coda_write(dev, bbc_base_addr, CODA9_REG_JPEG_BBC_BAS_ADDR); |
---|
| 505 | + |
---|
| 506 | + /* Leave 3 256-byte page margin to avoid a BBC interrupt */ |
---|
| 507 | + coda_write(dev, end_addr + 256 * 3 + 256, CODA9_REG_JPEG_BBC_END_ADDR); |
---|
| 508 | + val = DIV_ROUND_UP(vb2_plane_size(buf, 0), 256) + 3; |
---|
| 509 | + coda_write(dev, BIT(31) | val, CODA9_REG_JPEG_BBC_STRM_CTRL); |
---|
| 510 | + |
---|
| 511 | + bbc_cur_pos = page_ptr; |
---|
| 512 | + coda_write(dev, bbc_cur_pos, CODA9_REG_JPEG_BBC_CUR_POS); |
---|
| 513 | + coda_write(dev, bbc_base_addr + (bbc_cur_pos << 8), |
---|
| 514 | + CODA9_REG_JPEG_BBC_EXT_ADDR); |
---|
| 515 | + coda_write(dev, (bbc_cur_pos & 1) << 6, CODA9_REG_JPEG_BBC_INT_ADDR); |
---|
| 516 | + coda_write(dev, 64, CODA9_REG_JPEG_BBC_DATA_CNT); |
---|
| 517 | + coda_write(dev, 0, CODA9_REG_JPEG_BBC_COMMAND); |
---|
| 518 | + do { |
---|
| 519 | + ret = coda_read(dev, CODA9_REG_JPEG_BBC_BUSY); |
---|
| 520 | + } while (ret == 1); |
---|
| 521 | + |
---|
| 522 | + bbc_cur_pos++; |
---|
| 523 | + coda_write(dev, bbc_cur_pos, CODA9_REG_JPEG_BBC_CUR_POS); |
---|
| 524 | + coda_write(dev, bbc_base_addr + (bbc_cur_pos << 8), |
---|
| 525 | + CODA9_REG_JPEG_BBC_EXT_ADDR); |
---|
| 526 | + coda_write(dev, (bbc_cur_pos & 1) << 6, CODA9_REG_JPEG_BBC_INT_ADDR); |
---|
| 527 | + coda_write(dev, 64, CODA9_REG_JPEG_BBC_DATA_CNT); |
---|
| 528 | + coda_write(dev, 0, CODA9_REG_JPEG_BBC_COMMAND); |
---|
| 529 | + do { |
---|
| 530 | + ret = coda_read(dev, CODA9_REG_JPEG_BBC_BUSY); |
---|
| 531 | + } while (ret == 1); |
---|
| 532 | + |
---|
| 533 | + bbc_cur_pos++; |
---|
| 534 | + coda_write(dev, bbc_cur_pos, CODA9_REG_JPEG_BBC_CUR_POS); |
---|
| 535 | + coda_write(dev, 1, CODA9_REG_JPEG_BBC_CTRL); |
---|
| 536 | + |
---|
| 537 | + coda_write(dev, 0, CODA9_REG_JPEG_GBU_TT_CNT); |
---|
| 538 | + coda_write(dev, word_ptr, CODA9_REG_JPEG_GBU_WD_PTR); |
---|
| 539 | + coda_write(dev, 0, CODA9_REG_JPEG_GBU_BBSR); |
---|
| 540 | + coda_write(dev, 127, CODA9_REG_JPEG_GBU_BBER); |
---|
| 541 | + if (page_ptr & 1) { |
---|
| 542 | + coda_write(dev, 0, CODA9_REG_JPEG_GBU_BBIR); |
---|
| 543 | + coda_write(dev, 0, CODA9_REG_JPEG_GBU_BBHR); |
---|
| 544 | + } else { |
---|
| 545 | + coda_write(dev, 64, CODA9_REG_JPEG_GBU_BBIR); |
---|
| 546 | + coda_write(dev, 64, CODA9_REG_JPEG_GBU_BBHR); |
---|
| 547 | + } |
---|
| 548 | + coda_write(dev, 4, CODA9_REG_JPEG_GBU_CTRL); |
---|
| 549 | + coda_write(dev, bit_ptr, CODA9_REG_JPEG_GBU_FF_RPTR); |
---|
| 550 | + coda_write(dev, 3, CODA9_REG_JPEG_GBU_CTRL); |
---|
| 551 | +} |
---|
| 552 | + |
---|
| 553 | +static const int bus_req_num[] = { |
---|
| 554 | + [CODA9_JPEG_FORMAT_420] = 2, |
---|
| 555 | + [CODA9_JPEG_FORMAT_422] = 3, |
---|
| 556 | + [CODA9_JPEG_FORMAT_224] = 3, |
---|
| 557 | + [CODA9_JPEG_FORMAT_444] = 4, |
---|
| 558 | + [CODA9_JPEG_FORMAT_400] = 4, |
---|
| 559 | +}; |
---|
| 560 | + |
---|
| 561 | +#define MCU_INFO(mcu_block_num, comp_num, comp0_info, comp1_info, comp2_info) \ |
---|
| 562 | + (((mcu_block_num) << CODA9_JPEG_MCU_BLOCK_NUM_OFFSET) | \ |
---|
| 563 | + ((comp_num) << CODA9_JPEG_COMP_NUM_OFFSET) | \ |
---|
| 564 | + ((comp0_info) << CODA9_JPEG_COMP0_INFO_OFFSET) | \ |
---|
| 565 | + ((comp1_info) << CODA9_JPEG_COMP1_INFO_OFFSET) | \ |
---|
| 566 | + ((comp2_info) << CODA9_JPEG_COMP2_INFO_OFFSET)) |
---|
| 567 | + |
---|
| 568 | +static const u32 mcu_info[] = { |
---|
| 569 | + [CODA9_JPEG_FORMAT_420] = MCU_INFO(6, 3, 10, 5, 5), |
---|
| 570 | + [CODA9_JPEG_FORMAT_422] = MCU_INFO(4, 3, 9, 5, 5), |
---|
| 571 | + [CODA9_JPEG_FORMAT_224] = MCU_INFO(4, 3, 6, 5, 5), |
---|
| 572 | + [CODA9_JPEG_FORMAT_444] = MCU_INFO(3, 3, 5, 5, 5), |
---|
| 573 | + [CODA9_JPEG_FORMAT_400] = MCU_INFO(1, 1, 5, 0, 0), |
---|
| 574 | +}; |
---|
| 575 | + |
---|
| 576 | +/* |
---|
| 577 | + * Convert Huffman table specifcations to tables of codes and code lengths. |
---|
| 578 | + * For reference, see JPEG ITU-T.81 (ISO/IEC 10918-1) [1] |
---|
| 579 | + * |
---|
| 580 | + * [1] https://www.w3.org/Graphics/JPEG/itu-t81.pdf |
---|
| 581 | + */ |
---|
| 582 | +static int coda9_jpeg_gen_enc_huff_tab(struct coda_ctx *ctx, int tab_num, |
---|
| 583 | + int *ehufsi, int *ehufco) |
---|
| 584 | +{ |
---|
| 585 | + int i, j, k, lastk, si, code, maxsymbol; |
---|
| 586 | + const u8 *bits, *huffval; |
---|
| 587 | + struct { |
---|
| 588 | + int size[256]; |
---|
| 589 | + int code[256]; |
---|
| 590 | + } *huff; |
---|
| 591 | + static const unsigned char *huff_tabs[4] = { |
---|
| 592 | + luma_dc, luma_ac, chroma_dc, chroma_ac, |
---|
| 593 | + }; |
---|
| 594 | + int ret = -EINVAL; |
---|
| 595 | + |
---|
| 596 | + huff = kzalloc(sizeof(*huff), GFP_KERNEL); |
---|
| 597 | + if (!huff) |
---|
| 598 | + return -ENOMEM; |
---|
| 599 | + |
---|
| 600 | + bits = huff_tabs[tab_num]; |
---|
| 601 | + huffval = huff_tabs[tab_num] + 16; |
---|
| 602 | + |
---|
| 603 | + maxsymbol = tab_num & 1 ? 256 : 16; |
---|
| 604 | + |
---|
| 605 | + /* Figure C.1 - Generation of table of Huffman code sizes */ |
---|
| 606 | + k = 0; |
---|
| 607 | + for (i = 1; i <= 16; i++) { |
---|
| 608 | + j = bits[i - 1]; |
---|
| 609 | + if (k + j > maxsymbol) |
---|
| 610 | + goto out; |
---|
| 611 | + while (j--) |
---|
| 612 | + huff->size[k++] = i; |
---|
| 613 | + } |
---|
| 614 | + lastk = k; |
---|
| 615 | + |
---|
| 616 | + /* Figure C.2 - Generation of table of Huffman codes */ |
---|
| 617 | + k = 0; |
---|
| 618 | + code = 0; |
---|
| 619 | + si = huff->size[0]; |
---|
| 620 | + while (k < lastk) { |
---|
| 621 | + while (huff->size[k] == si) { |
---|
| 622 | + huff->code[k++] = code; |
---|
| 623 | + code++; |
---|
| 624 | + } |
---|
| 625 | + if (code >= (1 << si)) |
---|
| 626 | + goto out; |
---|
| 627 | + code <<= 1; |
---|
| 628 | + si++; |
---|
| 629 | + } |
---|
| 630 | + |
---|
| 631 | + /* Figure C.3 - Ordering procedure for encoding procedure code tables */ |
---|
| 632 | + for (k = 0; k < lastk; k++) { |
---|
| 633 | + i = huffval[k]; |
---|
| 634 | + if (i >= maxsymbol || ehufsi[i]) |
---|
| 635 | + goto out; |
---|
| 636 | + ehufco[i] = huff->code[k]; |
---|
| 637 | + ehufsi[i] = huff->size[k]; |
---|
| 638 | + } |
---|
| 639 | + |
---|
| 640 | + ret = 0; |
---|
| 641 | +out: |
---|
| 642 | + kfree(huff); |
---|
| 643 | + return ret; |
---|
| 644 | +} |
---|
| 645 | + |
---|
| 646 | +#define DC_TABLE_INDEX0 0 |
---|
| 647 | +#define AC_TABLE_INDEX0 1 |
---|
| 648 | +#define DC_TABLE_INDEX1 2 |
---|
| 649 | +#define AC_TABLE_INDEX1 3 |
---|
| 650 | + |
---|
| 651 | +static u8 *coda9_jpeg_get_huff_bits(struct coda_ctx *ctx, int tab_num) |
---|
| 652 | +{ |
---|
| 653 | + struct coda_huff_tab *huff_tab = ctx->params.jpeg_huff_tab; |
---|
| 654 | + |
---|
| 655 | + if (!huff_tab) |
---|
| 656 | + return NULL; |
---|
| 657 | + |
---|
| 658 | + switch (tab_num) { |
---|
| 659 | + case DC_TABLE_INDEX0: return huff_tab->luma_dc; |
---|
| 660 | + case AC_TABLE_INDEX0: return huff_tab->luma_ac; |
---|
| 661 | + case DC_TABLE_INDEX1: return huff_tab->chroma_dc; |
---|
| 662 | + case AC_TABLE_INDEX1: return huff_tab->chroma_ac; |
---|
| 663 | + } |
---|
| 664 | + |
---|
| 665 | + return NULL; |
---|
| 666 | +} |
---|
| 667 | + |
---|
| 668 | +static int coda9_jpeg_gen_dec_huff_tab(struct coda_ctx *ctx, int tab_num) |
---|
| 669 | +{ |
---|
| 670 | + int ptr_cnt = 0, huff_code = 0, zero_flag = 0, data_flag = 0; |
---|
| 671 | + u8 *huff_bits; |
---|
| 672 | + s16 *huff_max; |
---|
| 673 | + s16 *huff_min; |
---|
| 674 | + s8 *huff_ptr; |
---|
| 675 | + int ofs; |
---|
| 676 | + int i; |
---|
| 677 | + |
---|
| 678 | + huff_bits = coda9_jpeg_get_huff_bits(ctx, tab_num); |
---|
| 679 | + if (!huff_bits) |
---|
| 680 | + return -EINVAL; |
---|
| 681 | + |
---|
| 682 | + /* DC/AC Luma, DC/AC Chroma -> DC Luma/Chroma, AC Luma/Chroma */ |
---|
| 683 | + ofs = ((tab_num & 1) << 1) | ((tab_num >> 1) & 1); |
---|
| 684 | + ofs *= 16; |
---|
| 685 | + |
---|
| 686 | + huff_ptr = ctx->params.jpeg_huff_tab->ptr + ofs; |
---|
| 687 | + huff_max = ctx->params.jpeg_huff_tab->max + ofs; |
---|
| 688 | + huff_min = ctx->params.jpeg_huff_tab->min + ofs; |
---|
| 689 | + |
---|
| 690 | + for (i = 0; i < 16; i++) { |
---|
| 691 | + if (huff_bits[i]) { |
---|
| 692 | + huff_ptr[i] = ptr_cnt; |
---|
| 693 | + ptr_cnt += huff_bits[i]; |
---|
| 694 | + huff_min[i] = huff_code; |
---|
| 695 | + huff_max[i] = huff_code + (huff_bits[i] - 1); |
---|
| 696 | + data_flag = 1; |
---|
| 697 | + zero_flag = 0; |
---|
| 698 | + } else { |
---|
| 699 | + huff_ptr[i] = -1; |
---|
| 700 | + huff_min[i] = -1; |
---|
| 701 | + huff_max[i] = -1; |
---|
| 702 | + zero_flag = 1; |
---|
| 703 | + } |
---|
| 704 | + |
---|
| 705 | + if (data_flag == 1) { |
---|
| 706 | + if (zero_flag == 1) |
---|
| 707 | + huff_code <<= 1; |
---|
| 708 | + else |
---|
| 709 | + huff_code = (huff_max[i] + 1) << 1; |
---|
| 710 | + } |
---|
| 711 | + } |
---|
| 712 | + |
---|
| 713 | + return 0; |
---|
| 714 | +} |
---|
| 715 | + |
---|
| 716 | +static int coda9_jpeg_load_huff_tab(struct coda_ctx *ctx) |
---|
| 717 | +{ |
---|
| 718 | + struct { |
---|
| 719 | + int size[4][256]; |
---|
| 720 | + int code[4][256]; |
---|
| 721 | + } *huff; |
---|
| 722 | + u32 *huff_data; |
---|
| 723 | + int i, j; |
---|
| 724 | + int ret; |
---|
| 725 | + |
---|
| 726 | + huff = kzalloc(sizeof(*huff), GFP_KERNEL); |
---|
| 727 | + if (!huff) |
---|
| 728 | + return -ENOMEM; |
---|
| 729 | + |
---|
| 730 | + /* Generate all four (luma/chroma DC/AC) code/size lookup tables */ |
---|
| 731 | + for (i = 0; i < 4; i++) { |
---|
| 732 | + ret = coda9_jpeg_gen_enc_huff_tab(ctx, i, huff->size[i], |
---|
| 733 | + huff->code[i]); |
---|
| 734 | + if (ret) |
---|
| 735 | + goto out; |
---|
| 736 | + } |
---|
| 737 | + |
---|
| 738 | + if (!ctx->params.jpeg_huff_data) { |
---|
| 739 | + ctx->params.jpeg_huff_data = |
---|
| 740 | + kzalloc(sizeof(u32) * CODA9_JPEG_ENC_HUFF_DATA_SIZE, |
---|
| 741 | + GFP_KERNEL); |
---|
| 742 | + if (!ctx->params.jpeg_huff_data) { |
---|
| 743 | + ret = -ENOMEM; |
---|
| 744 | + goto out; |
---|
| 745 | + } |
---|
| 746 | + } |
---|
| 747 | + huff_data = ctx->params.jpeg_huff_data; |
---|
| 748 | + |
---|
| 749 | + for (j = 0; j < 4; j++) { |
---|
| 750 | + /* Store Huffman lookup tables in AC0, AC1, DC0, DC1 order */ |
---|
| 751 | + int t = (j == 0) ? AC_TABLE_INDEX0 : |
---|
| 752 | + (j == 1) ? AC_TABLE_INDEX1 : |
---|
| 753 | + (j == 2) ? DC_TABLE_INDEX0 : |
---|
| 754 | + DC_TABLE_INDEX1; |
---|
| 755 | + /* DC tables only have 16 entries */ |
---|
| 756 | + int len = (j < 2) ? 256 : 16; |
---|
| 757 | + |
---|
| 758 | + for (i = 0; i < len; i++) { |
---|
| 759 | + if (huff->size[t][i] == 0 && huff->code[t][i] == 0) |
---|
| 760 | + *(huff_data++) = 0; |
---|
| 761 | + else |
---|
| 762 | + *(huff_data++) = |
---|
| 763 | + ((huff->size[t][i] - 1) << 16) | |
---|
| 764 | + huff->code[t][i]; |
---|
| 765 | + } |
---|
| 766 | + } |
---|
| 767 | + |
---|
| 768 | + ret = 0; |
---|
| 769 | +out: |
---|
| 770 | + kfree(huff); |
---|
| 771 | + return ret; |
---|
| 772 | +} |
---|
| 773 | + |
---|
| 774 | +static void coda9_jpeg_write_huff_tab(struct coda_ctx *ctx) |
---|
| 775 | +{ |
---|
| 776 | + struct coda_dev *dev = ctx->dev; |
---|
| 777 | + u32 *huff_data = ctx->params.jpeg_huff_data; |
---|
| 778 | + int i; |
---|
| 779 | + |
---|
| 780 | + /* Write Huffman size/code lookup tables in AC0, AC1, DC0, DC1 order */ |
---|
| 781 | + coda_write(dev, 0x3, CODA9_REG_JPEG_HUFF_CTRL); |
---|
| 782 | + for (i = 0; i < CODA9_JPEG_ENC_HUFF_DATA_SIZE; i++) |
---|
| 783 | + coda_write(dev, *(huff_data++), CODA9_REG_JPEG_HUFF_DATA); |
---|
| 784 | + coda_write(dev, 0x0, CODA9_REG_JPEG_HUFF_CTRL); |
---|
| 785 | +} |
---|
| 786 | + |
---|
| 787 | +static inline void coda9_jpeg_write_qmat_quotients(struct coda_dev *dev, |
---|
| 788 | + u8 *qmat, int index) |
---|
| 789 | +{ |
---|
| 790 | + int i; |
---|
| 791 | + |
---|
| 792 | + coda_write(dev, index | 0x3, CODA9_REG_JPEG_QMAT_CTRL); |
---|
| 793 | + for (i = 0; i < 64; i++) |
---|
| 794 | + coda_write(dev, 0x80000 / qmat[i], CODA9_REG_JPEG_QMAT_DATA); |
---|
| 795 | + coda_write(dev, index, CODA9_REG_JPEG_QMAT_CTRL); |
---|
| 796 | +} |
---|
| 797 | + |
---|
| 798 | +static void coda9_jpeg_load_qmat_tab(struct coda_ctx *ctx) |
---|
| 799 | +{ |
---|
| 800 | + struct coda_dev *dev = ctx->dev; |
---|
| 801 | + u8 *luma_tab; |
---|
| 802 | + u8 *chroma_tab; |
---|
| 803 | + |
---|
| 804 | + luma_tab = ctx->params.jpeg_qmat_tab[0]; |
---|
| 805 | + if (!luma_tab) |
---|
| 806 | + luma_tab = luma_q; |
---|
| 807 | + |
---|
| 808 | + chroma_tab = ctx->params.jpeg_qmat_tab[1]; |
---|
| 809 | + if (!chroma_tab) |
---|
| 810 | + chroma_tab = chroma_q; |
---|
| 811 | + |
---|
| 812 | + coda9_jpeg_write_qmat_quotients(dev, luma_tab, 0x00); |
---|
| 813 | + coda9_jpeg_write_qmat_quotients(dev, chroma_tab, 0x40); |
---|
| 814 | + coda9_jpeg_write_qmat_quotients(dev, chroma_tab, 0x80); |
---|
| 815 | +} |
---|
| 816 | + |
---|
| 817 | +struct coda_jpeg_stream { |
---|
| 818 | + u8 *curr; |
---|
| 819 | + u8 *end; |
---|
| 820 | +}; |
---|
| 821 | + |
---|
| 822 | +static inline int coda_jpeg_put_byte(u8 byte, struct coda_jpeg_stream *stream) |
---|
| 823 | +{ |
---|
| 824 | + if (stream->curr >= stream->end) |
---|
| 825 | + return -EINVAL; |
---|
| 826 | + |
---|
| 827 | + *stream->curr++ = byte; |
---|
| 828 | + |
---|
| 829 | + return 0; |
---|
| 830 | +} |
---|
| 831 | + |
---|
| 832 | +static inline int coda_jpeg_put_word(u16 word, struct coda_jpeg_stream *stream) |
---|
| 833 | +{ |
---|
| 834 | + if (stream->curr + sizeof(__be16) > stream->end) |
---|
| 835 | + return -EINVAL; |
---|
| 836 | + |
---|
| 837 | + put_unaligned_be16(word, stream->curr); |
---|
| 838 | + stream->curr += sizeof(__be16); |
---|
| 839 | + |
---|
| 840 | + return 0; |
---|
| 841 | +} |
---|
| 842 | + |
---|
| 843 | +static int coda_jpeg_put_table(u16 marker, u8 index, const u8 *table, |
---|
| 844 | + size_t len, struct coda_jpeg_stream *stream) |
---|
| 845 | +{ |
---|
| 846 | + int i, ret; |
---|
| 847 | + |
---|
| 848 | + ret = coda_jpeg_put_word(marker, stream); |
---|
| 849 | + if (ret < 0) |
---|
| 850 | + return ret; |
---|
| 851 | + ret = coda_jpeg_put_word(3 + len, stream); |
---|
| 852 | + if (ret < 0) |
---|
| 853 | + return ret; |
---|
| 854 | + ret = coda_jpeg_put_byte(index, stream); |
---|
| 855 | + for (i = 0; i < len && ret == 0; i++) |
---|
| 856 | + ret = coda_jpeg_put_byte(table[i], stream); |
---|
| 857 | + |
---|
| 858 | + return ret; |
---|
| 859 | +} |
---|
| 860 | + |
---|
| 861 | +static int coda_jpeg_define_quantization_table(struct coda_ctx *ctx, u8 index, |
---|
| 862 | + struct coda_jpeg_stream *stream) |
---|
| 863 | +{ |
---|
| 864 | + return coda_jpeg_put_table(DQT_MARKER, index, |
---|
| 865 | + ctx->params.jpeg_qmat_tab[index], 64, |
---|
| 866 | + stream); |
---|
| 867 | +} |
---|
| 868 | + |
---|
| 869 | +static int coda_jpeg_define_huffman_table(u8 index, const u8 *table, size_t len, |
---|
| 870 | + struct coda_jpeg_stream *stream) |
---|
| 871 | +{ |
---|
| 872 | + return coda_jpeg_put_table(DHT_MARKER, index, table, len, stream); |
---|
| 873 | +} |
---|
| 874 | + |
---|
| 875 | +static int coda9_jpeg_encode_header(struct coda_ctx *ctx, int len, u8 *buf) |
---|
| 876 | +{ |
---|
| 877 | + struct coda_jpeg_stream stream = { buf, buf + len }; |
---|
| 878 | + struct coda_q_data *q_data_src; |
---|
| 879 | + int chroma_format, comp_num; |
---|
| 880 | + int i, ret, pad; |
---|
| 881 | + |
---|
| 882 | + q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); |
---|
| 883 | + chroma_format = coda9_jpeg_chroma_format(q_data_src->fourcc); |
---|
| 884 | + if (chroma_format < 0) |
---|
| 885 | + return 0; |
---|
| 886 | + |
---|
| 887 | + /* Start Of Image */ |
---|
| 888 | + ret = coda_jpeg_put_word(SOI_MARKER, &stream); |
---|
| 889 | + if (ret < 0) |
---|
| 890 | + return ret; |
---|
| 891 | + |
---|
| 892 | + /* Define Restart Interval */ |
---|
| 893 | + if (ctx->params.jpeg_restart_interval) { |
---|
| 894 | + ret = coda_jpeg_put_word(DRI_MARKER, &stream); |
---|
| 895 | + if (ret < 0) |
---|
| 896 | + return ret; |
---|
| 897 | + ret = coda_jpeg_put_word(4, &stream); |
---|
| 898 | + if (ret < 0) |
---|
| 899 | + return ret; |
---|
| 900 | + ret = coda_jpeg_put_word(ctx->params.jpeg_restart_interval, |
---|
| 901 | + &stream); |
---|
| 902 | + if (ret < 0) |
---|
| 903 | + return ret; |
---|
| 904 | + } |
---|
| 905 | + |
---|
| 906 | + /* Define Quantization Tables */ |
---|
| 907 | + ret = coda_jpeg_define_quantization_table(ctx, 0x00, &stream); |
---|
| 908 | + if (ret < 0) |
---|
| 909 | + return ret; |
---|
| 910 | + if (chroma_format != CODA9_JPEG_FORMAT_400) { |
---|
| 911 | + ret = coda_jpeg_define_quantization_table(ctx, 0x01, &stream); |
---|
| 912 | + if (ret < 0) |
---|
| 913 | + return ret; |
---|
| 914 | + } |
---|
| 915 | + |
---|
| 916 | + /* Define Huffman Tables */ |
---|
| 917 | + ret = coda_jpeg_define_huffman_table(0x00, luma_dc, 16 + 12, &stream); |
---|
| 918 | + if (ret < 0) |
---|
| 919 | + return ret; |
---|
| 920 | + ret = coda_jpeg_define_huffman_table(0x10, luma_ac, 16 + 162, &stream); |
---|
| 921 | + if (ret < 0) |
---|
| 922 | + return ret; |
---|
| 923 | + if (chroma_format != CODA9_JPEG_FORMAT_400) { |
---|
| 924 | + ret = coda_jpeg_define_huffman_table(0x01, chroma_dc, 16 + 12, |
---|
| 925 | + &stream); |
---|
| 926 | + if (ret < 0) |
---|
| 927 | + return ret; |
---|
| 928 | + ret = coda_jpeg_define_huffman_table(0x11, chroma_ac, 16 + 162, |
---|
| 929 | + &stream); |
---|
| 930 | + if (ret < 0) |
---|
| 931 | + return ret; |
---|
| 932 | + } |
---|
| 933 | + |
---|
| 934 | + /* Start Of Frame */ |
---|
| 935 | + ret = coda_jpeg_put_word(SOF_MARKER, &stream); |
---|
| 936 | + if (ret < 0) |
---|
| 937 | + return ret; |
---|
| 938 | + comp_num = (chroma_format == CODA9_JPEG_FORMAT_400) ? 1 : 3; |
---|
| 939 | + ret = coda_jpeg_put_word(8 + comp_num * 3, &stream); |
---|
| 940 | + if (ret < 0) |
---|
| 941 | + return ret; |
---|
| 942 | + ret = coda_jpeg_put_byte(0x08, &stream); |
---|
| 943 | + if (ret < 0) |
---|
| 944 | + return ret; |
---|
| 945 | + ret = coda_jpeg_put_word(q_data_src->height, &stream); |
---|
| 946 | + if (ret < 0) |
---|
| 947 | + return ret; |
---|
| 948 | + ret = coda_jpeg_put_word(q_data_src->width, &stream); |
---|
| 949 | + if (ret < 0) |
---|
| 950 | + return ret; |
---|
| 951 | + ret = coda_jpeg_put_byte(comp_num, &stream); |
---|
| 952 | + if (ret < 0) |
---|
| 953 | + return ret; |
---|
| 954 | + for (i = 0; i < comp_num; i++) { |
---|
| 955 | + static unsigned char subsampling[5][3] = { |
---|
| 956 | + [CODA9_JPEG_FORMAT_420] = { 0x22, 0x11, 0x11 }, |
---|
| 957 | + [CODA9_JPEG_FORMAT_422] = { 0x21, 0x11, 0x11 }, |
---|
| 958 | + [CODA9_JPEG_FORMAT_224] = { 0x12, 0x11, 0x11 }, |
---|
| 959 | + [CODA9_JPEG_FORMAT_444] = { 0x11, 0x11, 0x11 }, |
---|
| 960 | + [CODA9_JPEG_FORMAT_400] = { 0x11 }, |
---|
| 961 | + }; |
---|
| 962 | + |
---|
| 963 | + /* Component identifier, matches SOS */ |
---|
| 964 | + ret = coda_jpeg_put_byte(i + 1, &stream); |
---|
| 965 | + if (ret < 0) |
---|
| 966 | + return ret; |
---|
| 967 | + ret = coda_jpeg_put_byte(subsampling[chroma_format][i], |
---|
| 968 | + &stream); |
---|
| 969 | + if (ret < 0) |
---|
| 970 | + return ret; |
---|
| 971 | + /* Chroma table index */ |
---|
| 972 | + ret = coda_jpeg_put_byte((i == 0) ? 0 : 1, &stream); |
---|
| 973 | + if (ret < 0) |
---|
| 974 | + return ret; |
---|
| 975 | + } |
---|
| 976 | + |
---|
| 977 | + /* Pad to multiple of 8 bytes */ |
---|
| 978 | + pad = (stream.curr - buf) % 8; |
---|
| 979 | + if (pad) { |
---|
| 980 | + pad = 8 - pad; |
---|
| 981 | + while (pad--) { |
---|
| 982 | + ret = coda_jpeg_put_byte(0x00, &stream); |
---|
| 983 | + if (ret < 0) |
---|
| 984 | + return ret; |
---|
| 985 | + } |
---|
| 986 | + } |
---|
| 987 | + |
---|
| 988 | + return stream.curr - buf; |
---|
203 | 989 | } |
---|
204 | 990 | |
---|
205 | 991 | /* |
---|
.. | .. |
---|
251 | 1037 | coda_scale_quant_table(ctx->params.jpeg_qmat_tab[1], scale); |
---|
252 | 1038 | } |
---|
253 | 1039 | } |
---|
| 1040 | + |
---|
| 1041 | +/* |
---|
| 1042 | + * Encoder context operations |
---|
| 1043 | + */ |
---|
| 1044 | + |
---|
| 1045 | +static int coda9_jpeg_start_encoding(struct coda_ctx *ctx) |
---|
| 1046 | +{ |
---|
| 1047 | + struct coda_dev *dev = ctx->dev; |
---|
| 1048 | + int ret; |
---|
| 1049 | + |
---|
| 1050 | + ret = coda9_jpeg_load_huff_tab(ctx); |
---|
| 1051 | + if (ret < 0) { |
---|
| 1052 | + v4l2_err(&dev->v4l2_dev, "error loading Huffman tables\n"); |
---|
| 1053 | + return ret; |
---|
| 1054 | + } |
---|
| 1055 | + if (!ctx->params.jpeg_qmat_tab[0]) |
---|
| 1056 | + ctx->params.jpeg_qmat_tab[0] = kmalloc(64, GFP_KERNEL); |
---|
| 1057 | + if (!ctx->params.jpeg_qmat_tab[1]) |
---|
| 1058 | + ctx->params.jpeg_qmat_tab[1] = kmalloc(64, GFP_KERNEL); |
---|
| 1059 | + coda_set_jpeg_compression_quality(ctx, ctx->params.jpeg_quality); |
---|
| 1060 | + |
---|
| 1061 | + return 0; |
---|
| 1062 | +} |
---|
| 1063 | + |
---|
| 1064 | +static int coda9_jpeg_prepare_encode(struct coda_ctx *ctx) |
---|
| 1065 | +{ |
---|
| 1066 | + struct coda_q_data *q_data_src; |
---|
| 1067 | + struct vb2_v4l2_buffer *src_buf, *dst_buf; |
---|
| 1068 | + struct coda_dev *dev = ctx->dev; |
---|
| 1069 | + u32 start_addr, end_addr; |
---|
| 1070 | + u16 aligned_width, aligned_height; |
---|
| 1071 | + bool chroma_interleave; |
---|
| 1072 | + int chroma_format; |
---|
| 1073 | + int header_len; |
---|
| 1074 | + int ret; |
---|
| 1075 | + ktime_t timeout; |
---|
| 1076 | + |
---|
| 1077 | + src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); |
---|
| 1078 | + dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); |
---|
| 1079 | + q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); |
---|
| 1080 | + |
---|
| 1081 | + if (vb2_get_plane_payload(&src_buf->vb2_buf, 0) == 0) |
---|
| 1082 | + vb2_set_plane_payload(&src_buf->vb2_buf, 0, |
---|
| 1083 | + vb2_plane_size(&src_buf->vb2_buf, 0)); |
---|
| 1084 | + |
---|
| 1085 | + src_buf->sequence = ctx->osequence; |
---|
| 1086 | + dst_buf->sequence = ctx->osequence; |
---|
| 1087 | + ctx->osequence++; |
---|
| 1088 | + |
---|
| 1089 | + src_buf->flags |= V4L2_BUF_FLAG_KEYFRAME; |
---|
| 1090 | + src_buf->flags &= ~V4L2_BUF_FLAG_PFRAME; |
---|
| 1091 | + |
---|
| 1092 | + coda_set_gdi_regs(ctx); |
---|
| 1093 | + |
---|
| 1094 | + start_addr = vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0); |
---|
| 1095 | + end_addr = start_addr + vb2_plane_size(&dst_buf->vb2_buf, 0); |
---|
| 1096 | + |
---|
| 1097 | + chroma_format = coda9_jpeg_chroma_format(q_data_src->fourcc); |
---|
| 1098 | + if (chroma_format < 0) |
---|
| 1099 | + return chroma_format; |
---|
| 1100 | + |
---|
| 1101 | + /* Round image dimensions to multiple of MCU size */ |
---|
| 1102 | + aligned_width = round_up(q_data_src->width, width_align[chroma_format]); |
---|
| 1103 | + aligned_height = round_up(q_data_src->height, |
---|
| 1104 | + height_align[chroma_format]); |
---|
| 1105 | + if (aligned_width != q_data_src->bytesperline) { |
---|
| 1106 | + v4l2_err(&dev->v4l2_dev, "wrong stride: %d instead of %d\n", |
---|
| 1107 | + aligned_width, q_data_src->bytesperline); |
---|
| 1108 | + } |
---|
| 1109 | + |
---|
| 1110 | + header_len = |
---|
| 1111 | + coda9_jpeg_encode_header(ctx, |
---|
| 1112 | + vb2_plane_size(&dst_buf->vb2_buf, 0), |
---|
| 1113 | + vb2_plane_vaddr(&dst_buf->vb2_buf, 0)); |
---|
| 1114 | + if (header_len < 0) |
---|
| 1115 | + return header_len; |
---|
| 1116 | + |
---|
| 1117 | + coda_write(dev, start_addr + header_len, CODA9_REG_JPEG_BBC_BAS_ADDR); |
---|
| 1118 | + coda_write(dev, end_addr, CODA9_REG_JPEG_BBC_END_ADDR); |
---|
| 1119 | + coda_write(dev, start_addr + header_len, CODA9_REG_JPEG_BBC_WR_PTR); |
---|
| 1120 | + coda_write(dev, start_addr + header_len, CODA9_REG_JPEG_BBC_RD_PTR); |
---|
| 1121 | + coda_write(dev, 0, CODA9_REG_JPEG_BBC_CUR_POS); |
---|
| 1122 | + /* 64 words per 256-byte page */ |
---|
| 1123 | + coda_write(dev, 64, CODA9_REG_JPEG_BBC_DATA_CNT); |
---|
| 1124 | + coda_write(dev, start_addr, CODA9_REG_JPEG_BBC_EXT_ADDR); |
---|
| 1125 | + coda_write(dev, 0, CODA9_REG_JPEG_BBC_INT_ADDR); |
---|
| 1126 | + |
---|
| 1127 | + coda_write(dev, 0, CODA9_REG_JPEG_GBU_BT_PTR); |
---|
| 1128 | + coda_write(dev, 0, CODA9_REG_JPEG_GBU_WD_PTR); |
---|
| 1129 | + coda_write(dev, 0, CODA9_REG_JPEG_GBU_BBSR); |
---|
| 1130 | + coda_write(dev, BIT(31) | ((end_addr - start_addr - header_len) / 256), |
---|
| 1131 | + CODA9_REG_JPEG_BBC_STRM_CTRL); |
---|
| 1132 | + coda_write(dev, 0, CODA9_REG_JPEG_GBU_CTRL); |
---|
| 1133 | + coda_write(dev, 0, CODA9_REG_JPEG_GBU_FF_RPTR); |
---|
| 1134 | + coda_write(dev, 127, CODA9_REG_JPEG_GBU_BBER); |
---|
| 1135 | + coda_write(dev, 64, CODA9_REG_JPEG_GBU_BBIR); |
---|
| 1136 | + coda_write(dev, 64, CODA9_REG_JPEG_GBU_BBHR); |
---|
| 1137 | + |
---|
| 1138 | + chroma_interleave = (q_data_src->fourcc == V4L2_PIX_FMT_NV12); |
---|
| 1139 | + coda_write(dev, CODA9_JPEG_PIC_CTRL_TC_DIRECTION | |
---|
| 1140 | + CODA9_JPEG_PIC_CTRL_ENCODER_EN, CODA9_REG_JPEG_PIC_CTRL); |
---|
| 1141 | + coda_write(dev, 0, CODA9_REG_JPEG_SCL_INFO); |
---|
| 1142 | + coda_write(dev, chroma_interleave, CODA9_REG_JPEG_DPB_CONFIG); |
---|
| 1143 | + coda_write(dev, ctx->params.jpeg_restart_interval, |
---|
| 1144 | + CODA9_REG_JPEG_RST_INTVAL); |
---|
| 1145 | + coda_write(dev, 1, CODA9_REG_JPEG_BBC_CTRL); |
---|
| 1146 | + |
---|
| 1147 | + coda_write(dev, bus_req_num[chroma_format], CODA9_REG_JPEG_OP_INFO); |
---|
| 1148 | + |
---|
| 1149 | + coda9_jpeg_write_huff_tab(ctx); |
---|
| 1150 | + coda9_jpeg_load_qmat_tab(ctx); |
---|
| 1151 | + |
---|
| 1152 | + if (ctx->params.rot_mode & CODA_ROT_90) { |
---|
| 1153 | + aligned_width = aligned_height; |
---|
| 1154 | + aligned_height = q_data_src->bytesperline; |
---|
| 1155 | + if (chroma_format == CODA9_JPEG_FORMAT_422) |
---|
| 1156 | + chroma_format = CODA9_JPEG_FORMAT_224; |
---|
| 1157 | + else if (chroma_format == CODA9_JPEG_FORMAT_224) |
---|
| 1158 | + chroma_format = CODA9_JPEG_FORMAT_422; |
---|
| 1159 | + } |
---|
| 1160 | + /* These need to be multiples of MCU size */ |
---|
| 1161 | + coda_write(dev, aligned_width << 16 | aligned_height, |
---|
| 1162 | + CODA9_REG_JPEG_PIC_SIZE); |
---|
| 1163 | + coda_write(dev, ctx->params.rot_mode ? |
---|
| 1164 | + (CODA_ROT_MIR_ENABLE | ctx->params.rot_mode) : 0, |
---|
| 1165 | + CODA9_REG_JPEG_ROT_INFO); |
---|
| 1166 | + |
---|
| 1167 | + coda_write(dev, mcu_info[chroma_format], CODA9_REG_JPEG_MCU_INFO); |
---|
| 1168 | + |
---|
| 1169 | + coda_write(dev, 1, CODA9_GDI_CONTROL); |
---|
| 1170 | + timeout = ktime_add_us(ktime_get(), 100000); |
---|
| 1171 | + do { |
---|
| 1172 | + ret = coda_read(dev, CODA9_GDI_STATUS); |
---|
| 1173 | + if (ktime_compare(ktime_get(), timeout) > 0) { |
---|
| 1174 | + v4l2_err(&dev->v4l2_dev, "timeout waiting for GDI\n"); |
---|
| 1175 | + return -ETIMEDOUT; |
---|
| 1176 | + } |
---|
| 1177 | + } while (!ret); |
---|
| 1178 | + |
---|
| 1179 | + coda_write(dev, (chroma_format << 17) | (chroma_interleave << 16) | |
---|
| 1180 | + q_data_src->bytesperline, CODA9_GDI_INFO_CONTROL); |
---|
| 1181 | + /* The content of this register seems to be irrelevant: */ |
---|
| 1182 | + coda_write(dev, aligned_width << 16 | aligned_height, |
---|
| 1183 | + CODA9_GDI_INFO_PIC_SIZE); |
---|
| 1184 | + |
---|
| 1185 | + coda_write_base(ctx, q_data_src, src_buf, CODA9_GDI_INFO_BASE_Y); |
---|
| 1186 | + |
---|
| 1187 | + coda_write(dev, 0, CODA9_REG_JPEG_DPB_BASE00); |
---|
| 1188 | + coda_write(dev, 0, CODA9_GDI_CONTROL); |
---|
| 1189 | + coda_write(dev, 1, CODA9_GDI_PIC_INIT_HOST); |
---|
| 1190 | + |
---|
| 1191 | + coda_write(dev, 1, CODA9_GDI_WPROT_ERR_CLR); |
---|
| 1192 | + coda_write(dev, 0, CODA9_GDI_WPROT_RGN_EN); |
---|
| 1193 | + |
---|
| 1194 | + trace_coda_jpeg_run(ctx, src_buf); |
---|
| 1195 | + |
---|
| 1196 | + coda_write(dev, 1, CODA9_REG_JPEG_PIC_START); |
---|
| 1197 | + |
---|
| 1198 | + return 0; |
---|
| 1199 | +} |
---|
| 1200 | + |
---|
| 1201 | +static void coda9_jpeg_finish_encode(struct coda_ctx *ctx) |
---|
| 1202 | +{ |
---|
| 1203 | + struct vb2_v4l2_buffer *src_buf, *dst_buf; |
---|
| 1204 | + struct coda_dev *dev = ctx->dev; |
---|
| 1205 | + u32 wr_ptr, start_ptr; |
---|
| 1206 | + u32 err_mb; |
---|
| 1207 | + |
---|
| 1208 | + if (ctx->aborting) { |
---|
| 1209 | + coda_write(ctx->dev, 0, CODA9_REG_JPEG_BBC_FLUSH_CMD); |
---|
| 1210 | + return; |
---|
| 1211 | + } |
---|
| 1212 | + |
---|
| 1213 | + /* |
---|
| 1214 | + * Lock to make sure that an encoder stop command running in parallel |
---|
| 1215 | + * will either already have marked src_buf as last, or it will wake up |
---|
| 1216 | + * the capture queue after the buffers are returned. |
---|
| 1217 | + */ |
---|
| 1218 | + mutex_lock(&ctx->wakeup_mutex); |
---|
| 1219 | + src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); |
---|
| 1220 | + dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); |
---|
| 1221 | + |
---|
| 1222 | + trace_coda_jpeg_done(ctx, dst_buf); |
---|
| 1223 | + |
---|
| 1224 | + /* |
---|
| 1225 | + * Set plane payload to the number of bytes written out |
---|
| 1226 | + * by the JPEG processing unit |
---|
| 1227 | + */ |
---|
| 1228 | + start_ptr = vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0); |
---|
| 1229 | + wr_ptr = coda_read(dev, CODA9_REG_JPEG_BBC_WR_PTR); |
---|
| 1230 | + vb2_set_plane_payload(&dst_buf->vb2_buf, 0, wr_ptr - start_ptr); |
---|
| 1231 | + |
---|
| 1232 | + err_mb = coda_read(dev, CODA9_REG_JPEG_PIC_ERRMB); |
---|
| 1233 | + if (err_mb) |
---|
| 1234 | + coda_dbg(1, ctx, "ERRMB: 0x%x\n", err_mb); |
---|
| 1235 | + |
---|
| 1236 | + coda_write(dev, 0, CODA9_REG_JPEG_BBC_FLUSH_CMD); |
---|
| 1237 | + |
---|
| 1238 | + dst_buf->flags &= ~(V4L2_BUF_FLAG_PFRAME | V4L2_BUF_FLAG_LAST); |
---|
| 1239 | + dst_buf->flags |= V4L2_BUF_FLAG_KEYFRAME; |
---|
| 1240 | + dst_buf->flags |= src_buf->flags & V4L2_BUF_FLAG_LAST; |
---|
| 1241 | + |
---|
| 1242 | + v4l2_m2m_buf_copy_metadata(src_buf, dst_buf, false); |
---|
| 1243 | + |
---|
| 1244 | + v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE); |
---|
| 1245 | + coda_m2m_buf_done(ctx, dst_buf, err_mb ? VB2_BUF_STATE_ERROR : |
---|
| 1246 | + VB2_BUF_STATE_DONE); |
---|
| 1247 | + mutex_unlock(&ctx->wakeup_mutex); |
---|
| 1248 | + |
---|
| 1249 | + coda_dbg(1, ctx, "job finished: encoded frame (%u)%s\n", |
---|
| 1250 | + dst_buf->sequence, |
---|
| 1251 | + (dst_buf->flags & V4L2_BUF_FLAG_LAST) ? " (last)" : ""); |
---|
| 1252 | + |
---|
| 1253 | + /* |
---|
| 1254 | + * Reset JPEG processing unit after each encode run to work |
---|
| 1255 | + * around hangups when switching context between encoder and |
---|
| 1256 | + * decoder. |
---|
| 1257 | + */ |
---|
| 1258 | + coda_hw_reset(ctx); |
---|
| 1259 | +} |
---|
| 1260 | + |
---|
| 1261 | +static void coda9_jpeg_encode_timeout(struct coda_ctx *ctx) |
---|
| 1262 | +{ |
---|
| 1263 | + struct coda_dev *dev = ctx->dev; |
---|
| 1264 | + u32 end_addr, wr_ptr; |
---|
| 1265 | + |
---|
| 1266 | + /* Handle missing BBC overflow interrupt via timeout */ |
---|
| 1267 | + end_addr = coda_read(dev, CODA9_REG_JPEG_BBC_END_ADDR); |
---|
| 1268 | + wr_ptr = coda_read(dev, CODA9_REG_JPEG_BBC_WR_PTR); |
---|
| 1269 | + if (wr_ptr >= end_addr - 256) { |
---|
| 1270 | + v4l2_err(&dev->v4l2_dev, "JPEG too large for capture buffer\n"); |
---|
| 1271 | + coda9_jpeg_finish_encode(ctx); |
---|
| 1272 | + return; |
---|
| 1273 | + } |
---|
| 1274 | + |
---|
| 1275 | + coda_hw_reset(ctx); |
---|
| 1276 | +} |
---|
| 1277 | + |
---|
| 1278 | +static void coda9_jpeg_release(struct coda_ctx *ctx) |
---|
| 1279 | +{ |
---|
| 1280 | + int i; |
---|
| 1281 | + |
---|
| 1282 | + if (ctx->params.jpeg_qmat_tab[0] == luma_q) |
---|
| 1283 | + ctx->params.jpeg_qmat_tab[0] = NULL; |
---|
| 1284 | + if (ctx->params.jpeg_qmat_tab[1] == chroma_q) |
---|
| 1285 | + ctx->params.jpeg_qmat_tab[1] = NULL; |
---|
| 1286 | + for (i = 0; i < 3; i++) |
---|
| 1287 | + kfree(ctx->params.jpeg_qmat_tab[i]); |
---|
| 1288 | + kfree(ctx->params.jpeg_huff_data); |
---|
| 1289 | + kfree(ctx->params.jpeg_huff_tab); |
---|
| 1290 | +} |
---|
| 1291 | + |
---|
| 1292 | +const struct coda_context_ops coda9_jpeg_encode_ops = { |
---|
| 1293 | + .queue_init = coda_encoder_queue_init, |
---|
| 1294 | + .start_streaming = coda9_jpeg_start_encoding, |
---|
| 1295 | + .prepare_run = coda9_jpeg_prepare_encode, |
---|
| 1296 | + .finish_run = coda9_jpeg_finish_encode, |
---|
| 1297 | + .run_timeout = coda9_jpeg_encode_timeout, |
---|
| 1298 | + .release = coda9_jpeg_release, |
---|
| 1299 | +}; |
---|
| 1300 | + |
---|
| 1301 | +/* |
---|
| 1302 | + * Decoder context operations |
---|
| 1303 | + */ |
---|
| 1304 | + |
---|
| 1305 | +static int coda9_jpeg_start_decoding(struct coda_ctx *ctx) |
---|
| 1306 | +{ |
---|
| 1307 | + ctx->params.jpeg_qmat_index[0] = 0; |
---|
| 1308 | + ctx->params.jpeg_qmat_index[1] = 1; |
---|
| 1309 | + ctx->params.jpeg_qmat_index[2] = 1; |
---|
| 1310 | + ctx->params.jpeg_qmat_tab[0] = luma_q; |
---|
| 1311 | + ctx->params.jpeg_qmat_tab[1] = chroma_q; |
---|
| 1312 | + /* nothing more to do here */ |
---|
| 1313 | + |
---|
| 1314 | + /* TODO: we could already scan the first header to get the chroma |
---|
| 1315 | + * format. |
---|
| 1316 | + */ |
---|
| 1317 | + |
---|
| 1318 | + return 0; |
---|
| 1319 | +} |
---|
| 1320 | + |
---|
| 1321 | +static int coda9_jpeg_prepare_decode(struct coda_ctx *ctx) |
---|
| 1322 | +{ |
---|
| 1323 | + struct coda_dev *dev = ctx->dev; |
---|
| 1324 | + int aligned_width, aligned_height; |
---|
| 1325 | + int chroma_format; |
---|
| 1326 | + int ret; |
---|
| 1327 | + u32 val, dst_fourcc; |
---|
| 1328 | + struct coda_q_data *q_data_src, *q_data_dst; |
---|
| 1329 | + struct vb2_v4l2_buffer *src_buf, *dst_buf; |
---|
| 1330 | + int chroma_interleave; |
---|
| 1331 | + |
---|
| 1332 | + src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); |
---|
| 1333 | + dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); |
---|
| 1334 | + q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); |
---|
| 1335 | + q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); |
---|
| 1336 | + dst_fourcc = q_data_dst->fourcc; |
---|
| 1337 | + |
---|
| 1338 | + if (vb2_get_plane_payload(&src_buf->vb2_buf, 0) == 0) |
---|
| 1339 | + vb2_set_plane_payload(&src_buf->vb2_buf, 0, |
---|
| 1340 | + vb2_plane_size(&src_buf->vb2_buf, 0)); |
---|
| 1341 | + |
---|
| 1342 | + chroma_format = coda9_jpeg_chroma_format(q_data_dst->fourcc); |
---|
| 1343 | + if (chroma_format < 0) { |
---|
| 1344 | + v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx); |
---|
| 1345 | + return chroma_format; |
---|
| 1346 | + } |
---|
| 1347 | + |
---|
| 1348 | + ret = coda_jpeg_decode_header(ctx, &src_buf->vb2_buf); |
---|
| 1349 | + if (ret < 0) { |
---|
| 1350 | + v4l2_err(&dev->v4l2_dev, "failed to decode JPEG header: %d\n", |
---|
| 1351 | + ret); |
---|
| 1352 | + |
---|
| 1353 | + src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); |
---|
| 1354 | + dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); |
---|
| 1355 | + v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE); |
---|
| 1356 | + v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE); |
---|
| 1357 | + |
---|
| 1358 | + v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx); |
---|
| 1359 | + return ret; |
---|
| 1360 | + } |
---|
| 1361 | + |
---|
| 1362 | + /* Round image dimensions to multiple of MCU size */ |
---|
| 1363 | + aligned_width = round_up(q_data_src->width, width_align[chroma_format]); |
---|
| 1364 | + aligned_height = round_up(q_data_src->height, height_align[chroma_format]); |
---|
| 1365 | + if (aligned_width != q_data_dst->bytesperline) { |
---|
| 1366 | + v4l2_err(&dev->v4l2_dev, "stride mismatch: %d != %d\n", |
---|
| 1367 | + aligned_width, q_data_dst->bytesperline); |
---|
| 1368 | + } |
---|
| 1369 | + |
---|
| 1370 | + coda_set_gdi_regs(ctx); |
---|
| 1371 | + |
---|
| 1372 | + val = ctx->params.jpeg_huff_ac_index[0] << 12 | |
---|
| 1373 | + ctx->params.jpeg_huff_ac_index[1] << 11 | |
---|
| 1374 | + ctx->params.jpeg_huff_ac_index[2] << 10 | |
---|
| 1375 | + ctx->params.jpeg_huff_dc_index[0] << 9 | |
---|
| 1376 | + ctx->params.jpeg_huff_dc_index[1] << 8 | |
---|
| 1377 | + ctx->params.jpeg_huff_dc_index[2] << 7; |
---|
| 1378 | + if (ctx->params.jpeg_huff_tab) |
---|
| 1379 | + val |= CODA9_JPEG_PIC_CTRL_USER_HUFFMAN_EN; |
---|
| 1380 | + coda_write(dev, val, CODA9_REG_JPEG_PIC_CTRL); |
---|
| 1381 | + |
---|
| 1382 | + coda_write(dev, aligned_width << 16 | aligned_height, |
---|
| 1383 | + CODA9_REG_JPEG_PIC_SIZE); |
---|
| 1384 | + |
---|
| 1385 | + chroma_interleave = (dst_fourcc == V4L2_PIX_FMT_NV12); |
---|
| 1386 | + coda_write(dev, 0, CODA9_REG_JPEG_ROT_INFO); |
---|
| 1387 | + coda_write(dev, bus_req_num[chroma_format], CODA9_REG_JPEG_OP_INFO); |
---|
| 1388 | + coda_write(dev, mcu_info[chroma_format], CODA9_REG_JPEG_MCU_INFO); |
---|
| 1389 | + coda_write(dev, 0, CODA9_REG_JPEG_SCL_INFO); |
---|
| 1390 | + coda_write(dev, chroma_interleave, CODA9_REG_JPEG_DPB_CONFIG); |
---|
| 1391 | + coda_write(dev, ctx->params.jpeg_restart_interval, |
---|
| 1392 | + CODA9_REG_JPEG_RST_INTVAL); |
---|
| 1393 | + |
---|
| 1394 | + if (ctx->params.jpeg_huff_tab) { |
---|
| 1395 | + ret = coda9_jpeg_dec_huff_setup(ctx); |
---|
| 1396 | + if (ret < 0) { |
---|
| 1397 | + v4l2_err(&dev->v4l2_dev, |
---|
| 1398 | + "failed to set up Huffman tables: %d\n", ret); |
---|
| 1399 | + v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx); |
---|
| 1400 | + return ret; |
---|
| 1401 | + } |
---|
| 1402 | + } |
---|
| 1403 | + |
---|
| 1404 | + coda9_jpeg_qmat_setup(ctx); |
---|
| 1405 | + |
---|
| 1406 | + coda9_jpeg_dec_bbc_gbu_setup(ctx, &src_buf->vb2_buf, |
---|
| 1407 | + ctx->jpeg_ecs_offset); |
---|
| 1408 | + |
---|
| 1409 | + coda_write(dev, 0, CODA9_REG_JPEG_RST_INDEX); |
---|
| 1410 | + coda_write(dev, 0, CODA9_REG_JPEG_RST_COUNT); |
---|
| 1411 | + |
---|
| 1412 | + coda_write(dev, 0, CODA9_REG_JPEG_DPCM_DIFF_Y); |
---|
| 1413 | + coda_write(dev, 0, CODA9_REG_JPEG_DPCM_DIFF_CB); |
---|
| 1414 | + coda_write(dev, 0, CODA9_REG_JPEG_DPCM_DIFF_CR); |
---|
| 1415 | + |
---|
| 1416 | + coda_write(dev, 0, CODA9_REG_JPEG_ROT_INFO); |
---|
| 1417 | + |
---|
| 1418 | + coda_write(dev, 1, CODA9_GDI_CONTROL); |
---|
| 1419 | + do { |
---|
| 1420 | + ret = coda_read(dev, CODA9_GDI_STATUS); |
---|
| 1421 | + } while (!ret); |
---|
| 1422 | + |
---|
| 1423 | + val = (chroma_format << 17) | (chroma_interleave << 16) | |
---|
| 1424 | + q_data_dst->bytesperline; |
---|
| 1425 | + if (ctx->tiled_map_type == GDI_TILED_FRAME_MB_RASTER_MAP) |
---|
| 1426 | + val |= 3 << 20; |
---|
| 1427 | + coda_write(dev, val, CODA9_GDI_INFO_CONTROL); |
---|
| 1428 | + |
---|
| 1429 | + coda_write(dev, aligned_width << 16 | aligned_height, |
---|
| 1430 | + CODA9_GDI_INFO_PIC_SIZE); |
---|
| 1431 | + |
---|
| 1432 | + coda_write_base(ctx, q_data_dst, dst_buf, CODA9_GDI_INFO_BASE_Y); |
---|
| 1433 | + |
---|
| 1434 | + coda_write(dev, 0, CODA9_REG_JPEG_DPB_BASE00); |
---|
| 1435 | + coda_write(dev, 0, CODA9_GDI_CONTROL); |
---|
| 1436 | + coda_write(dev, 1, CODA9_GDI_PIC_INIT_HOST); |
---|
| 1437 | + |
---|
| 1438 | + trace_coda_jpeg_run(ctx, src_buf); |
---|
| 1439 | + |
---|
| 1440 | + coda_write(dev, 1, CODA9_REG_JPEG_PIC_START); |
---|
| 1441 | + |
---|
| 1442 | + return 0; |
---|
| 1443 | +} |
---|
| 1444 | + |
---|
| 1445 | +static void coda9_jpeg_finish_decode(struct coda_ctx *ctx) |
---|
| 1446 | +{ |
---|
| 1447 | + struct coda_dev *dev = ctx->dev; |
---|
| 1448 | + struct vb2_v4l2_buffer *dst_buf, *src_buf; |
---|
| 1449 | + struct coda_q_data *q_data_dst; |
---|
| 1450 | + u32 err_mb; |
---|
| 1451 | + |
---|
| 1452 | + err_mb = coda_read(dev, CODA9_REG_JPEG_PIC_ERRMB); |
---|
| 1453 | + if (err_mb) |
---|
| 1454 | + v4l2_err(&dev->v4l2_dev, "ERRMB: 0x%x\n", err_mb); |
---|
| 1455 | + |
---|
| 1456 | + coda_write(dev, 0, CODA9_REG_JPEG_BBC_FLUSH_CMD); |
---|
| 1457 | + |
---|
| 1458 | + /* |
---|
| 1459 | + * Lock to make sure that a decoder stop command running in parallel |
---|
| 1460 | + * will either already have marked src_buf as last, or it will wake up |
---|
| 1461 | + * the capture queue after the buffers are returned. |
---|
| 1462 | + */ |
---|
| 1463 | + mutex_lock(&ctx->wakeup_mutex); |
---|
| 1464 | + src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); |
---|
| 1465 | + dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); |
---|
| 1466 | + dst_buf->sequence = ctx->osequence++; |
---|
| 1467 | + |
---|
| 1468 | + trace_coda_jpeg_done(ctx, dst_buf); |
---|
| 1469 | + |
---|
| 1470 | + dst_buf->flags &= ~(V4L2_BUF_FLAG_PFRAME | V4L2_BUF_FLAG_LAST); |
---|
| 1471 | + dst_buf->flags |= V4L2_BUF_FLAG_KEYFRAME; |
---|
| 1472 | + dst_buf->flags |= src_buf->flags & V4L2_BUF_FLAG_LAST; |
---|
| 1473 | + |
---|
| 1474 | + v4l2_m2m_buf_copy_metadata(src_buf, dst_buf, false); |
---|
| 1475 | + |
---|
| 1476 | + q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); |
---|
| 1477 | + vb2_set_plane_payload(&dst_buf->vb2_buf, 0, q_data_dst->sizeimage); |
---|
| 1478 | + |
---|
| 1479 | + v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE); |
---|
| 1480 | + coda_m2m_buf_done(ctx, dst_buf, err_mb ? VB2_BUF_STATE_ERROR : |
---|
| 1481 | + VB2_BUF_STATE_DONE); |
---|
| 1482 | + |
---|
| 1483 | + mutex_unlock(&ctx->wakeup_mutex); |
---|
| 1484 | + |
---|
| 1485 | + coda_dbg(1, ctx, "job finished: decoded frame (%u)%s\n", |
---|
| 1486 | + dst_buf->sequence, |
---|
| 1487 | + (dst_buf->flags & V4L2_BUF_FLAG_LAST) ? " (last)" : ""); |
---|
| 1488 | + |
---|
| 1489 | + /* |
---|
| 1490 | + * Reset JPEG processing unit after each decode run to work |
---|
| 1491 | + * around hangups when switching context between encoder and |
---|
| 1492 | + * decoder. |
---|
| 1493 | + */ |
---|
| 1494 | + coda_hw_reset(ctx); |
---|
| 1495 | +} |
---|
| 1496 | + |
---|
| 1497 | +const struct coda_context_ops coda9_jpeg_decode_ops = { |
---|
| 1498 | + .queue_init = coda_encoder_queue_init, /* non-bitstream operation */ |
---|
| 1499 | + .start_streaming = coda9_jpeg_start_decoding, |
---|
| 1500 | + .prepare_run = coda9_jpeg_prepare_decode, |
---|
| 1501 | + .finish_run = coda9_jpeg_finish_decode, |
---|
| 1502 | + .release = coda9_jpeg_release, |
---|
| 1503 | +}; |
---|
| 1504 | + |
---|
| 1505 | +irqreturn_t coda9_jpeg_irq_handler(int irq, void *data) |
---|
| 1506 | +{ |
---|
| 1507 | + struct coda_dev *dev = data; |
---|
| 1508 | + struct coda_ctx *ctx; |
---|
| 1509 | + int status; |
---|
| 1510 | + int err_mb; |
---|
| 1511 | + |
---|
| 1512 | + status = coda_read(dev, CODA9_REG_JPEG_PIC_STATUS); |
---|
| 1513 | + if (status == 0) |
---|
| 1514 | + return IRQ_HANDLED; |
---|
| 1515 | + coda_write(dev, status, CODA9_REG_JPEG_PIC_STATUS); |
---|
| 1516 | + |
---|
| 1517 | + if (status & CODA9_JPEG_STATUS_OVERFLOW) |
---|
| 1518 | + v4l2_err(&dev->v4l2_dev, "JPEG overflow\n"); |
---|
| 1519 | + |
---|
| 1520 | + if (status & CODA9_JPEG_STATUS_BBC_INT) |
---|
| 1521 | + v4l2_err(&dev->v4l2_dev, "JPEG BBC interrupt\n"); |
---|
| 1522 | + |
---|
| 1523 | + if (status & CODA9_JPEG_STATUS_ERROR) { |
---|
| 1524 | + v4l2_err(&dev->v4l2_dev, "JPEG error\n"); |
---|
| 1525 | + |
---|
| 1526 | + err_mb = coda_read(dev, CODA9_REG_JPEG_PIC_ERRMB); |
---|
| 1527 | + if (err_mb) { |
---|
| 1528 | + v4l2_err(&dev->v4l2_dev, |
---|
| 1529 | + "ERRMB: 0x%x: rst idx %d, mcu pos (%d,%d)\n", |
---|
| 1530 | + err_mb, err_mb >> 24, (err_mb >> 12) & 0xfff, |
---|
| 1531 | + err_mb & 0xfff); |
---|
| 1532 | + } |
---|
| 1533 | + } |
---|
| 1534 | + |
---|
| 1535 | + ctx = v4l2_m2m_get_curr_priv(dev->m2m_dev); |
---|
| 1536 | + if (!ctx) { |
---|
| 1537 | + v4l2_err(&dev->v4l2_dev, |
---|
| 1538 | + "Instance released before the end of transaction\n"); |
---|
| 1539 | + mutex_unlock(&dev->coda_mutex); |
---|
| 1540 | + return IRQ_HANDLED; |
---|
| 1541 | + } |
---|
| 1542 | + |
---|
| 1543 | + complete(&ctx->completion); |
---|
| 1544 | + |
---|
| 1545 | + return IRQ_HANDLED; |
---|
| 1546 | +} |
---|