0001
0002
0003
0004
0005
0006
0007
0008 #include <asm/unaligned.h>
0009 #include <linux/irqreturn.h>
0010 #include <linux/kernel.h>
0011 #include <linux/ktime.h>
0012 #include <linux/slab.h>
0013 #include <linux/swab.h>
0014 #include <linux/videodev2.h>
0015
0016 #include <media/v4l2-common.h>
0017 #include <media/v4l2-fh.h>
0018 #include <media/v4l2-jpeg.h>
0019 #include <media/v4l2-mem2mem.h>
0020 #include <media/videobuf2-core.h>
0021 #include <media/videobuf2-dma-contig.h>
0022
0023 #include "coda.h"
0024 #include "trace.h"
0025
0026 #define SOI_MARKER 0xffd8
0027 #define APP9_MARKER 0xffe9
0028 #define DRI_MARKER 0xffdd
0029 #define DQT_MARKER 0xffdb
0030 #define DHT_MARKER 0xffc4
0031 #define SOF_MARKER 0xffc0
0032 #define SOS_MARKER 0xffda
0033 #define EOI_MARKER 0xffd9
0034
0035 enum {
0036 CODA9_JPEG_FORMAT_420,
0037 CODA9_JPEG_FORMAT_422,
0038 CODA9_JPEG_FORMAT_224,
0039 CODA9_JPEG_FORMAT_444,
0040 CODA9_JPEG_FORMAT_400,
0041 };
0042
0043 struct coda_huff_tab {
0044 u8 luma_dc[16 + 12];
0045 u8 chroma_dc[16 + 12];
0046 u8 luma_ac[16 + 162];
0047 u8 chroma_ac[16 + 162];
0048
0049
0050 s16 min[4 * 16];
0051 s16 max[4 * 16];
0052 s8 ptr[4 * 16];
0053 };
0054
0055 #define CODA9_JPEG_ENC_HUFF_DATA_SIZE (256 + 256 + 16 + 16)
0056
0057
0058
0059
0060
0061
0062 static const unsigned char luma_dc[16 + 12] = {
0063
0064 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01,
0065 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0066
0067 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0068 0x08, 0x09, 0x0a, 0x0b,
0069 };
0070
0071 static const unsigned char chroma_dc[16 + 12] = {
0072
0073 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0074 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
0075
0076 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0077 0x08, 0x09, 0x0a, 0x0b,
0078 };
0079
0080 static const unsigned char luma_ac[16 + 162 + 2] = {
0081
0082 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03,
0083 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d,
0084
0085 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
0086 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
0087 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
0088 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
0089 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
0090 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
0091 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
0092 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
0093 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
0094 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
0095 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
0096 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
0097 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
0098 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0099 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
0100 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
0101 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
0102 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
0103 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
0104 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
0105 0xf9, 0xfa,
0106 };
0107
0108 static const unsigned char chroma_ac[16 + 162 + 2] = {
0109
0110 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
0111 0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77,
0112
0113 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
0114 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
0115 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
0116 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
0117 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
0118 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
0119 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
0120 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
0121 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
0122 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
0123 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
0124 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0125 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
0126 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
0127 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
0128 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
0129 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
0130 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
0131 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
0132 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
0133 0xf9, 0xfa,
0134 };
0135
0136
0137
0138
0139
0140
0141 static unsigned char luma_q[64] = {
0142 0x06, 0x04, 0x04, 0x04, 0x05, 0x04, 0x06, 0x05,
0143 0x05, 0x06, 0x09, 0x06, 0x05, 0x06, 0x09, 0x0b,
0144 0x08, 0x06, 0x06, 0x08, 0x0b, 0x0c, 0x0a, 0x0a,
0145 0x0b, 0x0a, 0x0a, 0x0c, 0x10, 0x0c, 0x0c, 0x0c,
0146 0x0c, 0x0c, 0x0c, 0x10, 0x0c, 0x0c, 0x0c, 0x0c,
0147 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
0148 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
0149 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
0150 };
0151
0152 static unsigned char chroma_q[64] = {
0153 0x07, 0x07, 0x07, 0x0d, 0x0c, 0x0d, 0x18, 0x10,
0154 0x10, 0x18, 0x14, 0x0e, 0x0e, 0x0e, 0x14, 0x14,
0155 0x0e, 0x0e, 0x0e, 0x0e, 0x14, 0x11, 0x0c, 0x0c,
0156 0x0c, 0x0c, 0x0c, 0x11, 0x11, 0x0c, 0x0c, 0x0c,
0157 0x0c, 0x0c, 0x0c, 0x11, 0x0c, 0x0c, 0x0c, 0x0c,
0158 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
0159 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
0160 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
0161 };
0162
0163 static const unsigned char width_align[] = {
0164 [CODA9_JPEG_FORMAT_420] = 16,
0165 [CODA9_JPEG_FORMAT_422] = 16,
0166 [CODA9_JPEG_FORMAT_224] = 8,
0167 [CODA9_JPEG_FORMAT_444] = 8,
0168 [CODA9_JPEG_FORMAT_400] = 8,
0169 };
0170
0171 static const unsigned char height_align[] = {
0172 [CODA9_JPEG_FORMAT_420] = 16,
0173 [CODA9_JPEG_FORMAT_422] = 8,
0174 [CODA9_JPEG_FORMAT_224] = 16,
0175 [CODA9_JPEG_FORMAT_444] = 8,
0176 [CODA9_JPEG_FORMAT_400] = 8,
0177 };
0178
0179 static int coda9_jpeg_chroma_format(u32 pixfmt)
0180 {
0181 switch (pixfmt) {
0182 case V4L2_PIX_FMT_YUV420:
0183 case V4L2_PIX_FMT_NV12:
0184 return CODA9_JPEG_FORMAT_420;
0185 case V4L2_PIX_FMT_YUV422P:
0186 return CODA9_JPEG_FORMAT_422;
0187 case V4L2_PIX_FMT_YUV444:
0188 return CODA9_JPEG_FORMAT_444;
0189 case V4L2_PIX_FMT_GREY:
0190 return CODA9_JPEG_FORMAT_400;
0191 }
0192 return -EINVAL;
0193 }
0194
0195 struct coda_memcpy_desc {
0196 int offset;
0197 const void *src;
0198 size_t len;
0199 };
0200
0201 static void coda_memcpy_parabuf(void *parabuf,
0202 const struct coda_memcpy_desc *desc)
0203 {
0204 u32 *dst = parabuf + desc->offset;
0205 const u32 *src = desc->src;
0206 int len = desc->len / 4;
0207 int i;
0208
0209 for (i = 0; i < len; i += 2) {
0210 dst[i + 1] = swab32(src[i]);
0211 dst[i] = swab32(src[i + 1]);
0212 }
0213 }
0214
0215 int coda_jpeg_write_tables(struct coda_ctx *ctx)
0216 {
0217 int i;
0218 static const struct coda_memcpy_desc huff[8] = {
0219 { 0, luma_dc, sizeof(luma_dc) },
0220 { 32, luma_ac, sizeof(luma_ac) },
0221 { 216, chroma_dc, sizeof(chroma_dc) },
0222 { 248, chroma_ac, sizeof(chroma_ac) },
0223 };
0224 struct coda_memcpy_desc qmat[3] = {
0225 { 512, ctx->params.jpeg_qmat_tab[0], 64 },
0226 { 576, ctx->params.jpeg_qmat_tab[1], 64 },
0227 { 640, ctx->params.jpeg_qmat_tab[1], 64 },
0228 };
0229
0230
0231 for (i = 0; i < ARRAY_SIZE(huff); i++)
0232 coda_memcpy_parabuf(ctx->parabuf.vaddr, huff + i);
0233
0234
0235 for (i = 0; i < ARRAY_SIZE(qmat); i++)
0236 coda_memcpy_parabuf(ctx->parabuf.vaddr, qmat + i);
0237
0238 return 0;
0239 }
0240
0241 bool coda_jpeg_check_buffer(struct coda_ctx *ctx, struct vb2_buffer *vb)
0242 {
0243 void *vaddr = vb2_plane_vaddr(vb, 0);
0244 u16 soi, eoi;
0245 int len, i;
0246
0247 soi = be16_to_cpup((__be16 *)vaddr);
0248 if (soi != SOI_MARKER)
0249 return false;
0250
0251 len = vb2_get_plane_payload(vb, 0);
0252 vaddr += len - 2;
0253 for (i = 0; i < 32; i++) {
0254 eoi = be16_to_cpup((__be16 *)(vaddr - i));
0255 if (eoi == EOI_MARKER) {
0256 if (i > 0)
0257 vb2_set_plane_payload(vb, 0, len - i);
0258 return true;
0259 }
0260 }
0261
0262 return false;
0263 }
0264
0265 static int coda9_jpeg_gen_dec_huff_tab(struct coda_ctx *ctx, int tab_num);
0266
0267 int coda_jpeg_decode_header(struct coda_ctx *ctx, struct vb2_buffer *vb)
0268 {
0269 struct coda_dev *dev = ctx->dev;
0270 u8 *buf = vb2_plane_vaddr(vb, 0);
0271 size_t len = vb2_get_plane_payload(vb, 0);
0272 struct v4l2_jpeg_scan_header scan_header;
0273 struct v4l2_jpeg_reference quantization_tables[4] = { };
0274 struct v4l2_jpeg_reference huffman_tables[4] = { };
0275 struct v4l2_jpeg_header header = {
0276 .scan = &scan_header,
0277 .quantization_tables = quantization_tables,
0278 .huffman_tables = huffman_tables,
0279 };
0280 struct coda_q_data *q_data_src;
0281 struct coda_huff_tab *huff_tab;
0282 int i, j, ret;
0283
0284 ret = v4l2_jpeg_parse_header(buf, len, &header);
0285 if (ret < 0) {
0286 v4l2_err(&dev->v4l2_dev, "failed to parse JPEG header: %pe\n",
0287 ERR_PTR(ret));
0288 return ret;
0289 }
0290
0291 ctx->params.jpeg_restart_interval = header.restart_interval;
0292
0293
0294 if (header.frame.height > ctx->codec->max_h ||
0295 header.frame.width > ctx->codec->max_w) {
0296 v4l2_err(&dev->v4l2_dev, "invalid dimensions: %dx%d\n",
0297 header.frame.width, header.frame.height);
0298 return -EINVAL;
0299 }
0300
0301 q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
0302 if (header.frame.height != q_data_src->height ||
0303 header.frame.width != q_data_src->width) {
0304 v4l2_err(&dev->v4l2_dev,
0305 "dimensions don't match format: %dx%d\n",
0306 header.frame.width, header.frame.height);
0307 return -EINVAL;
0308 }
0309
0310 if (header.frame.num_components != 3) {
0311 v4l2_err(&dev->v4l2_dev,
0312 "unsupported number of components: %d\n",
0313 header.frame.num_components);
0314 return -EINVAL;
0315 }
0316
0317
0318 if (quantization_tables[3].start) {
0319 v4l2_err(&dev->v4l2_dev,
0320 "only 3 quantization tables supported\n");
0321 return -EINVAL;
0322 }
0323 for (i = 0; i < 3; i++) {
0324 if (!quantization_tables[i].start)
0325 continue;
0326 if (quantization_tables[i].length != 64) {
0327 v4l2_err(&dev->v4l2_dev,
0328 "only 8-bit quantization tables supported\n");
0329 continue;
0330 }
0331 if (!ctx->params.jpeg_qmat_tab[i]) {
0332 ctx->params.jpeg_qmat_tab[i] = kmalloc(64, GFP_KERNEL);
0333 if (!ctx->params.jpeg_qmat_tab[i])
0334 return -ENOMEM;
0335 }
0336 memcpy(ctx->params.jpeg_qmat_tab[i],
0337 quantization_tables[i].start, 64);
0338 }
0339
0340
0341 for (i = 0; i < 4; i++) {
0342 if (!huffman_tables[i].start) {
0343 v4l2_err(&dev->v4l2_dev, "missing Huffman table\n");
0344 return -EINVAL;
0345 }
0346
0347 if (huffman_tables[i].length < 17 ||
0348 huffman_tables[i].length > 178 ||
0349 ((i & 2) == 0 && huffman_tables[i].length > 28)) {
0350 v4l2_err(&dev->v4l2_dev,
0351 "invalid Huffman table %d length: %zu\n",
0352 i, huffman_tables[i].length);
0353 return -EINVAL;
0354 }
0355 }
0356 huff_tab = ctx->params.jpeg_huff_tab;
0357 if (!huff_tab) {
0358 huff_tab = kzalloc(sizeof(struct coda_huff_tab), GFP_KERNEL);
0359 if (!huff_tab)
0360 return -ENOMEM;
0361 ctx->params.jpeg_huff_tab = huff_tab;
0362 }
0363
0364 memset(huff_tab, 0, sizeof(*huff_tab));
0365 memcpy(huff_tab->luma_dc, huffman_tables[0].start, huffman_tables[0].length);
0366 memcpy(huff_tab->chroma_dc, huffman_tables[1].start, huffman_tables[1].length);
0367 memcpy(huff_tab->luma_ac, huffman_tables[2].start, huffman_tables[2].length);
0368 memcpy(huff_tab->chroma_ac, huffman_tables[3].start, huffman_tables[3].length);
0369
0370
0371 for (i = 0; i < scan_header.num_components; i++) {
0372 struct v4l2_jpeg_scan_component_spec *scan_component;
0373
0374 scan_component = &scan_header.component[i];
0375 for (j = 0; j < header.frame.num_components; j++) {
0376 if (header.frame.component[j].component_identifier ==
0377 scan_component->component_selector)
0378 break;
0379 }
0380 if (j == header.frame.num_components)
0381 continue;
0382
0383 ctx->params.jpeg_huff_dc_index[j] =
0384 scan_component->dc_entropy_coding_table_selector;
0385 ctx->params.jpeg_huff_ac_index[j] =
0386 scan_component->ac_entropy_coding_table_selector;
0387 }
0388
0389
0390 for (i = 0; i < 4; i++)
0391 coda9_jpeg_gen_dec_huff_tab(ctx, i);
0392
0393
0394 ctx->jpeg_ecs_offset = header.ecs_offset;
0395
0396 switch (header.frame.subsampling) {
0397 case V4L2_JPEG_CHROMA_SUBSAMPLING_420:
0398 case V4L2_JPEG_CHROMA_SUBSAMPLING_422:
0399 ctx->params.jpeg_chroma_subsampling = header.frame.subsampling;
0400 break;
0401 default:
0402 v4l2_err(&dev->v4l2_dev, "chroma subsampling not supported: %d",
0403 header.frame.subsampling);
0404 return -EINVAL;
0405 }
0406
0407 return 0;
0408 }
0409
0410 static inline void coda9_jpeg_write_huff_values(struct coda_dev *dev, u8 *bits,
0411 int num_values)
0412 {
0413 s8 *values = (s8 *)(bits + 16);
0414 int huff_length, i;
0415
0416 for (huff_length = 0, i = 0; i < 16; i++)
0417 huff_length += bits[i];
0418 for (i = huff_length; i < num_values; i++)
0419 values[i] = -1;
0420 for (i = 0; i < num_values; i++)
0421 coda_write(dev, (s32)values[i], CODA9_REG_JPEG_HUFF_DATA);
0422 }
0423
0424 static int coda9_jpeg_dec_huff_setup(struct coda_ctx *ctx)
0425 {
0426 struct coda_huff_tab *huff_tab = ctx->params.jpeg_huff_tab;
0427 struct coda_dev *dev = ctx->dev;
0428 s16 *huff_min = huff_tab->min;
0429 s16 *huff_max = huff_tab->max;
0430 s8 *huff_ptr = huff_tab->ptr;
0431 int i;
0432
0433
0434 coda_write(dev, 0x003, CODA9_REG_JPEG_HUFF_CTRL);
0435 coda_write(dev, 0x000, CODA9_REG_JPEG_HUFF_ADDR);
0436 for (i = 0; i < 4 * 16; i++)
0437 coda_write(dev, (s32)huff_min[i], CODA9_REG_JPEG_HUFF_DATA);
0438
0439
0440 coda_write(dev, 0x403, CODA9_REG_JPEG_HUFF_CTRL);
0441 coda_write(dev, 0x440, CODA9_REG_JPEG_HUFF_ADDR);
0442 for (i = 0; i < 4 * 16; i++)
0443 coda_write(dev, (s32)huff_max[i], CODA9_REG_JPEG_HUFF_DATA);
0444
0445
0446 coda_write(dev, 0x803, CODA9_REG_JPEG_HUFF_CTRL);
0447 coda_write(dev, 0x880, CODA9_REG_JPEG_HUFF_ADDR);
0448 for (i = 0; i < 4 * 16; i++)
0449 coda_write(dev, (s32)huff_ptr[i], CODA9_REG_JPEG_HUFF_DATA);
0450
0451
0452 coda_write(dev, 0xc03, CODA9_REG_JPEG_HUFF_CTRL);
0453 coda9_jpeg_write_huff_values(dev, huff_tab->luma_dc, 12);
0454 coda9_jpeg_write_huff_values(dev, huff_tab->chroma_dc, 12);
0455 coda9_jpeg_write_huff_values(dev, huff_tab->luma_ac, 162);
0456 coda9_jpeg_write_huff_values(dev, huff_tab->chroma_ac, 162);
0457 coda_write(dev, 0x000, CODA9_REG_JPEG_HUFF_CTRL);
0458 return 0;
0459 }
0460
0461 static inline void coda9_jpeg_write_qmat_tab(struct coda_dev *dev,
0462 u8 *qmat, int index)
0463 {
0464 int i;
0465
0466 coda_write(dev, index | 0x3, CODA9_REG_JPEG_QMAT_CTRL);
0467 for (i = 0; i < 64; i++)
0468 coda_write(dev, qmat[i], CODA9_REG_JPEG_QMAT_DATA);
0469 coda_write(dev, 0, CODA9_REG_JPEG_QMAT_CTRL);
0470 }
0471
0472 static void coda9_jpeg_qmat_setup(struct coda_ctx *ctx)
0473 {
0474 struct coda_dev *dev = ctx->dev;
0475 int *qmat_index = ctx->params.jpeg_qmat_index;
0476 u8 **qmat_tab = ctx->params.jpeg_qmat_tab;
0477
0478 coda9_jpeg_write_qmat_tab(dev, qmat_tab[qmat_index[0]], 0x00);
0479 coda9_jpeg_write_qmat_tab(dev, qmat_tab[qmat_index[1]], 0x40);
0480 coda9_jpeg_write_qmat_tab(dev, qmat_tab[qmat_index[2]], 0x80);
0481 }
0482
0483 static void coda9_jpeg_dec_bbc_gbu_setup(struct coda_ctx *ctx,
0484 struct vb2_buffer *buf, u32 ecs_offset)
0485 {
0486 struct coda_dev *dev = ctx->dev;
0487 int page_ptr, word_ptr, bit_ptr;
0488 u32 bbc_base_addr, end_addr;
0489 int bbc_cur_pos;
0490 int ret, val;
0491
0492 bbc_base_addr = vb2_dma_contig_plane_dma_addr(buf, 0);
0493 end_addr = bbc_base_addr + vb2_get_plane_payload(buf, 0);
0494
0495 page_ptr = ecs_offset / 256;
0496 word_ptr = (ecs_offset % 256) / 4;
0497 if (page_ptr & 1)
0498 word_ptr += 64;
0499 bit_ptr = (ecs_offset % 4) * 8;
0500 if (word_ptr & 1)
0501 bit_ptr += 32;
0502 word_ptr &= ~0x1;
0503
0504 coda_write(dev, end_addr, CODA9_REG_JPEG_BBC_WR_PTR);
0505 coda_write(dev, bbc_base_addr, CODA9_REG_JPEG_BBC_BAS_ADDR);
0506
0507
0508 coda_write(dev, end_addr + 256 * 3 + 256, CODA9_REG_JPEG_BBC_END_ADDR);
0509 val = DIV_ROUND_UP(vb2_plane_size(buf, 0), 256) + 3;
0510 coda_write(dev, BIT(31) | val, CODA9_REG_JPEG_BBC_STRM_CTRL);
0511
0512 bbc_cur_pos = page_ptr;
0513 coda_write(dev, bbc_cur_pos, CODA9_REG_JPEG_BBC_CUR_POS);
0514 coda_write(dev, bbc_base_addr + (bbc_cur_pos << 8),
0515 CODA9_REG_JPEG_BBC_EXT_ADDR);
0516 coda_write(dev, (bbc_cur_pos & 1) << 6, CODA9_REG_JPEG_BBC_INT_ADDR);
0517 coda_write(dev, 64, CODA9_REG_JPEG_BBC_DATA_CNT);
0518 coda_write(dev, 0, CODA9_REG_JPEG_BBC_COMMAND);
0519 do {
0520 ret = coda_read(dev, CODA9_REG_JPEG_BBC_BUSY);
0521 } while (ret == 1);
0522
0523 bbc_cur_pos++;
0524 coda_write(dev, bbc_cur_pos, CODA9_REG_JPEG_BBC_CUR_POS);
0525 coda_write(dev, bbc_base_addr + (bbc_cur_pos << 8),
0526 CODA9_REG_JPEG_BBC_EXT_ADDR);
0527 coda_write(dev, (bbc_cur_pos & 1) << 6, CODA9_REG_JPEG_BBC_INT_ADDR);
0528 coda_write(dev, 64, CODA9_REG_JPEG_BBC_DATA_CNT);
0529 coda_write(dev, 0, CODA9_REG_JPEG_BBC_COMMAND);
0530 do {
0531 ret = coda_read(dev, CODA9_REG_JPEG_BBC_BUSY);
0532 } while (ret == 1);
0533
0534 bbc_cur_pos++;
0535 coda_write(dev, bbc_cur_pos, CODA9_REG_JPEG_BBC_CUR_POS);
0536 coda_write(dev, 1, CODA9_REG_JPEG_BBC_CTRL);
0537
0538 coda_write(dev, 0, CODA9_REG_JPEG_GBU_TT_CNT);
0539 coda_write(dev, word_ptr, CODA9_REG_JPEG_GBU_WD_PTR);
0540 coda_write(dev, 0, CODA9_REG_JPEG_GBU_BBSR);
0541 coda_write(dev, 127, CODA9_REG_JPEG_GBU_BBER);
0542 if (page_ptr & 1) {
0543 coda_write(dev, 0, CODA9_REG_JPEG_GBU_BBIR);
0544 coda_write(dev, 0, CODA9_REG_JPEG_GBU_BBHR);
0545 } else {
0546 coda_write(dev, 64, CODA9_REG_JPEG_GBU_BBIR);
0547 coda_write(dev, 64, CODA9_REG_JPEG_GBU_BBHR);
0548 }
0549 coda_write(dev, 4, CODA9_REG_JPEG_GBU_CTRL);
0550 coda_write(dev, bit_ptr, CODA9_REG_JPEG_GBU_FF_RPTR);
0551 coda_write(dev, 3, CODA9_REG_JPEG_GBU_CTRL);
0552 }
0553
0554 static const int bus_req_num[] = {
0555 [CODA9_JPEG_FORMAT_420] = 2,
0556 [CODA9_JPEG_FORMAT_422] = 3,
0557 [CODA9_JPEG_FORMAT_224] = 3,
0558 [CODA9_JPEG_FORMAT_444] = 4,
0559 [CODA9_JPEG_FORMAT_400] = 4,
0560 };
0561
0562 #define MCU_INFO(mcu_block_num, comp_num, comp0_info, comp1_info, comp2_info) \
0563 (((mcu_block_num) << CODA9_JPEG_MCU_BLOCK_NUM_OFFSET) | \
0564 ((comp_num) << CODA9_JPEG_COMP_NUM_OFFSET) | \
0565 ((comp0_info) << CODA9_JPEG_COMP0_INFO_OFFSET) | \
0566 ((comp1_info) << CODA9_JPEG_COMP1_INFO_OFFSET) | \
0567 ((comp2_info) << CODA9_JPEG_COMP2_INFO_OFFSET))
0568
0569 static const u32 mcu_info[] = {
0570 [CODA9_JPEG_FORMAT_420] = MCU_INFO(6, 3, 10, 5, 5),
0571 [CODA9_JPEG_FORMAT_422] = MCU_INFO(4, 3, 9, 5, 5),
0572 [CODA9_JPEG_FORMAT_224] = MCU_INFO(4, 3, 6, 5, 5),
0573 [CODA9_JPEG_FORMAT_444] = MCU_INFO(3, 3, 5, 5, 5),
0574 [CODA9_JPEG_FORMAT_400] = MCU_INFO(1, 1, 5, 0, 0),
0575 };
0576
0577
0578
0579
0580
0581
0582
0583 static int coda9_jpeg_gen_enc_huff_tab(struct coda_ctx *ctx, int tab_num,
0584 int *ehufsi, int *ehufco)
0585 {
0586 int i, j, k, lastk, si, code, maxsymbol;
0587 const u8 *bits, *huffval;
0588 struct {
0589 int size[256];
0590 int code[256];
0591 } *huff;
0592 static const unsigned char *huff_tabs[4] = {
0593 luma_dc, luma_ac, chroma_dc, chroma_ac,
0594 };
0595 int ret = -EINVAL;
0596
0597 huff = kzalloc(sizeof(*huff), GFP_KERNEL);
0598 if (!huff)
0599 return -ENOMEM;
0600
0601 bits = huff_tabs[tab_num];
0602 huffval = huff_tabs[tab_num] + 16;
0603
0604 maxsymbol = tab_num & 1 ? 256 : 16;
0605
0606
0607 k = 0;
0608 for (i = 1; i <= 16; i++) {
0609 j = bits[i - 1];
0610 if (k + j > maxsymbol)
0611 goto out;
0612 while (j--)
0613 huff->size[k++] = i;
0614 }
0615 lastk = k;
0616
0617
0618 k = 0;
0619 code = 0;
0620 si = huff->size[0];
0621 while (k < lastk) {
0622 while (huff->size[k] == si) {
0623 huff->code[k++] = code;
0624 code++;
0625 }
0626 if (code >= (1 << si))
0627 goto out;
0628 code <<= 1;
0629 si++;
0630 }
0631
0632
0633 for (k = 0; k < lastk; k++) {
0634 i = huffval[k];
0635 if (i >= maxsymbol || ehufsi[i])
0636 goto out;
0637 ehufco[i] = huff->code[k];
0638 ehufsi[i] = huff->size[k];
0639 }
0640
0641 ret = 0;
0642 out:
0643 kfree(huff);
0644 return ret;
0645 }
0646
0647 #define DC_TABLE_INDEX0 0
0648 #define AC_TABLE_INDEX0 1
0649 #define DC_TABLE_INDEX1 2
0650 #define AC_TABLE_INDEX1 3
0651
0652 static u8 *coda9_jpeg_get_huff_bits(struct coda_ctx *ctx, int tab_num)
0653 {
0654 struct coda_huff_tab *huff_tab = ctx->params.jpeg_huff_tab;
0655
0656 if (!huff_tab)
0657 return NULL;
0658
0659 switch (tab_num) {
0660 case DC_TABLE_INDEX0: return huff_tab->luma_dc;
0661 case AC_TABLE_INDEX0: return huff_tab->luma_ac;
0662 case DC_TABLE_INDEX1: return huff_tab->chroma_dc;
0663 case AC_TABLE_INDEX1: return huff_tab->chroma_ac;
0664 }
0665
0666 return NULL;
0667 }
0668
0669 static int coda9_jpeg_gen_dec_huff_tab(struct coda_ctx *ctx, int tab_num)
0670 {
0671 int ptr_cnt = 0, huff_code = 0, zero_flag = 0, data_flag = 0;
0672 u8 *huff_bits;
0673 s16 *huff_max;
0674 s16 *huff_min;
0675 s8 *huff_ptr;
0676 int ofs;
0677 int i;
0678
0679 huff_bits = coda9_jpeg_get_huff_bits(ctx, tab_num);
0680 if (!huff_bits)
0681 return -EINVAL;
0682
0683
0684 ofs = ((tab_num & 1) << 1) | ((tab_num >> 1) & 1);
0685 ofs *= 16;
0686
0687 huff_ptr = ctx->params.jpeg_huff_tab->ptr + ofs;
0688 huff_max = ctx->params.jpeg_huff_tab->max + ofs;
0689 huff_min = ctx->params.jpeg_huff_tab->min + ofs;
0690
0691 for (i = 0; i < 16; i++) {
0692 if (huff_bits[i]) {
0693 huff_ptr[i] = ptr_cnt;
0694 ptr_cnt += huff_bits[i];
0695 huff_min[i] = huff_code;
0696 huff_max[i] = huff_code + (huff_bits[i] - 1);
0697 data_flag = 1;
0698 zero_flag = 0;
0699 } else {
0700 huff_ptr[i] = -1;
0701 huff_min[i] = -1;
0702 huff_max[i] = -1;
0703 zero_flag = 1;
0704 }
0705
0706 if (data_flag == 1) {
0707 if (zero_flag == 1)
0708 huff_code <<= 1;
0709 else
0710 huff_code = (huff_max[i] + 1) << 1;
0711 }
0712 }
0713
0714 return 0;
0715 }
0716
0717 static int coda9_jpeg_load_huff_tab(struct coda_ctx *ctx)
0718 {
0719 struct {
0720 int size[4][256];
0721 int code[4][256];
0722 } *huff;
0723 u32 *huff_data;
0724 int i, j;
0725 int ret;
0726
0727 huff = kzalloc(sizeof(*huff), GFP_KERNEL);
0728 if (!huff)
0729 return -ENOMEM;
0730
0731
0732 for (i = 0; i < 4; i++) {
0733 ret = coda9_jpeg_gen_enc_huff_tab(ctx, i, huff->size[i],
0734 huff->code[i]);
0735 if (ret)
0736 goto out;
0737 }
0738
0739 if (!ctx->params.jpeg_huff_data) {
0740 ctx->params.jpeg_huff_data =
0741 kzalloc(sizeof(u32) * CODA9_JPEG_ENC_HUFF_DATA_SIZE,
0742 GFP_KERNEL);
0743 if (!ctx->params.jpeg_huff_data) {
0744 ret = -ENOMEM;
0745 goto out;
0746 }
0747 }
0748 huff_data = ctx->params.jpeg_huff_data;
0749
0750 for (j = 0; j < 4; j++) {
0751
0752 int t = (j == 0) ? AC_TABLE_INDEX0 :
0753 (j == 1) ? AC_TABLE_INDEX1 :
0754 (j == 2) ? DC_TABLE_INDEX0 :
0755 DC_TABLE_INDEX1;
0756
0757 int len = (j < 2) ? 256 : 16;
0758
0759 for (i = 0; i < len; i++) {
0760 if (huff->size[t][i] == 0 && huff->code[t][i] == 0)
0761 *(huff_data++) = 0;
0762 else
0763 *(huff_data++) =
0764 ((huff->size[t][i] - 1) << 16) |
0765 huff->code[t][i];
0766 }
0767 }
0768
0769 ret = 0;
0770 out:
0771 kfree(huff);
0772 return ret;
0773 }
0774
0775 static void coda9_jpeg_write_huff_tab(struct coda_ctx *ctx)
0776 {
0777 struct coda_dev *dev = ctx->dev;
0778 u32 *huff_data = ctx->params.jpeg_huff_data;
0779 int i;
0780
0781
0782 coda_write(dev, 0x3, CODA9_REG_JPEG_HUFF_CTRL);
0783 for (i = 0; i < CODA9_JPEG_ENC_HUFF_DATA_SIZE; i++)
0784 coda_write(dev, *(huff_data++), CODA9_REG_JPEG_HUFF_DATA);
0785 coda_write(dev, 0x0, CODA9_REG_JPEG_HUFF_CTRL);
0786 }
0787
0788 static inline void coda9_jpeg_write_qmat_quotients(struct coda_dev *dev,
0789 u8 *qmat, int index)
0790 {
0791 int i;
0792
0793 coda_write(dev, index | 0x3, CODA9_REG_JPEG_QMAT_CTRL);
0794 for (i = 0; i < 64; i++)
0795 coda_write(dev, 0x80000 / qmat[i], CODA9_REG_JPEG_QMAT_DATA);
0796 coda_write(dev, index, CODA9_REG_JPEG_QMAT_CTRL);
0797 }
0798
0799 static void coda9_jpeg_load_qmat_tab(struct coda_ctx *ctx)
0800 {
0801 struct coda_dev *dev = ctx->dev;
0802 u8 *luma_tab;
0803 u8 *chroma_tab;
0804
0805 luma_tab = ctx->params.jpeg_qmat_tab[0];
0806 if (!luma_tab)
0807 luma_tab = luma_q;
0808
0809 chroma_tab = ctx->params.jpeg_qmat_tab[1];
0810 if (!chroma_tab)
0811 chroma_tab = chroma_q;
0812
0813 coda9_jpeg_write_qmat_quotients(dev, luma_tab, 0x00);
0814 coda9_jpeg_write_qmat_quotients(dev, chroma_tab, 0x40);
0815 coda9_jpeg_write_qmat_quotients(dev, chroma_tab, 0x80);
0816 }
0817
0818 struct coda_jpeg_stream {
0819 u8 *curr;
0820 u8 *end;
0821 };
0822
0823 static inline int coda_jpeg_put_byte(u8 byte, struct coda_jpeg_stream *stream)
0824 {
0825 if (stream->curr >= stream->end)
0826 return -EINVAL;
0827
0828 *stream->curr++ = byte;
0829
0830 return 0;
0831 }
0832
0833 static inline int coda_jpeg_put_word(u16 word, struct coda_jpeg_stream *stream)
0834 {
0835 if (stream->curr + sizeof(__be16) > stream->end)
0836 return -EINVAL;
0837
0838 put_unaligned_be16(word, stream->curr);
0839 stream->curr += sizeof(__be16);
0840
0841 return 0;
0842 }
0843
0844 static int coda_jpeg_put_table(u16 marker, u8 index, const u8 *table,
0845 size_t len, struct coda_jpeg_stream *stream)
0846 {
0847 int i, ret;
0848
0849 ret = coda_jpeg_put_word(marker, stream);
0850 if (ret < 0)
0851 return ret;
0852 ret = coda_jpeg_put_word(3 + len, stream);
0853 if (ret < 0)
0854 return ret;
0855 ret = coda_jpeg_put_byte(index, stream);
0856 for (i = 0; i < len && ret == 0; i++)
0857 ret = coda_jpeg_put_byte(table[i], stream);
0858
0859 return ret;
0860 }
0861
0862 static int coda_jpeg_define_quantization_table(struct coda_ctx *ctx, u8 index,
0863 struct coda_jpeg_stream *stream)
0864 {
0865 return coda_jpeg_put_table(DQT_MARKER, index,
0866 ctx->params.jpeg_qmat_tab[index], 64,
0867 stream);
0868 }
0869
0870 static int coda_jpeg_define_huffman_table(u8 index, const u8 *table, size_t len,
0871 struct coda_jpeg_stream *stream)
0872 {
0873 return coda_jpeg_put_table(DHT_MARKER, index, table, len, stream);
0874 }
0875
0876 static int coda9_jpeg_encode_header(struct coda_ctx *ctx, int len, u8 *buf)
0877 {
0878 struct coda_jpeg_stream stream = { buf, buf + len };
0879 struct coda_q_data *q_data_src;
0880 int chroma_format, comp_num;
0881 int i, ret, pad;
0882
0883 q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
0884 chroma_format = coda9_jpeg_chroma_format(q_data_src->fourcc);
0885 if (chroma_format < 0)
0886 return 0;
0887
0888
0889 ret = coda_jpeg_put_word(SOI_MARKER, &stream);
0890 if (ret < 0)
0891 return ret;
0892
0893
0894 if (ctx->params.jpeg_restart_interval) {
0895 ret = coda_jpeg_put_word(DRI_MARKER, &stream);
0896 if (ret < 0)
0897 return ret;
0898 ret = coda_jpeg_put_word(4, &stream);
0899 if (ret < 0)
0900 return ret;
0901 ret = coda_jpeg_put_word(ctx->params.jpeg_restart_interval,
0902 &stream);
0903 if (ret < 0)
0904 return ret;
0905 }
0906
0907
0908 ret = coda_jpeg_define_quantization_table(ctx, 0x00, &stream);
0909 if (ret < 0)
0910 return ret;
0911 if (chroma_format != CODA9_JPEG_FORMAT_400) {
0912 ret = coda_jpeg_define_quantization_table(ctx, 0x01, &stream);
0913 if (ret < 0)
0914 return ret;
0915 }
0916
0917
0918 ret = coda_jpeg_define_huffman_table(0x00, luma_dc, 16 + 12, &stream);
0919 if (ret < 0)
0920 return ret;
0921 ret = coda_jpeg_define_huffman_table(0x10, luma_ac, 16 + 162, &stream);
0922 if (ret < 0)
0923 return ret;
0924 if (chroma_format != CODA9_JPEG_FORMAT_400) {
0925 ret = coda_jpeg_define_huffman_table(0x01, chroma_dc, 16 + 12,
0926 &stream);
0927 if (ret < 0)
0928 return ret;
0929 ret = coda_jpeg_define_huffman_table(0x11, chroma_ac, 16 + 162,
0930 &stream);
0931 if (ret < 0)
0932 return ret;
0933 }
0934
0935
0936 ret = coda_jpeg_put_word(SOF_MARKER, &stream);
0937 if (ret < 0)
0938 return ret;
0939 comp_num = (chroma_format == CODA9_JPEG_FORMAT_400) ? 1 : 3;
0940 ret = coda_jpeg_put_word(8 + comp_num * 3, &stream);
0941 if (ret < 0)
0942 return ret;
0943 ret = coda_jpeg_put_byte(0x08, &stream);
0944 if (ret < 0)
0945 return ret;
0946 ret = coda_jpeg_put_word(q_data_src->height, &stream);
0947 if (ret < 0)
0948 return ret;
0949 ret = coda_jpeg_put_word(q_data_src->width, &stream);
0950 if (ret < 0)
0951 return ret;
0952 ret = coda_jpeg_put_byte(comp_num, &stream);
0953 if (ret < 0)
0954 return ret;
0955 for (i = 0; i < comp_num; i++) {
0956 static unsigned char subsampling[5][3] = {
0957 [CODA9_JPEG_FORMAT_420] = { 0x22, 0x11, 0x11 },
0958 [CODA9_JPEG_FORMAT_422] = { 0x21, 0x11, 0x11 },
0959 [CODA9_JPEG_FORMAT_224] = { 0x12, 0x11, 0x11 },
0960 [CODA9_JPEG_FORMAT_444] = { 0x11, 0x11, 0x11 },
0961 [CODA9_JPEG_FORMAT_400] = { 0x11 },
0962 };
0963
0964
0965 ret = coda_jpeg_put_byte(i + 1, &stream);
0966 if (ret < 0)
0967 return ret;
0968 ret = coda_jpeg_put_byte(subsampling[chroma_format][i],
0969 &stream);
0970 if (ret < 0)
0971 return ret;
0972
0973 ret = coda_jpeg_put_byte((i == 0) ? 0 : 1, &stream);
0974 if (ret < 0)
0975 return ret;
0976 }
0977
0978
0979 pad = (stream.curr - buf) % 8;
0980 if (pad) {
0981 pad = 8 - pad;
0982 while (pad--) {
0983 ret = coda_jpeg_put_byte(0x00, &stream);
0984 if (ret < 0)
0985 return ret;
0986 }
0987 }
0988
0989 return stream.curr - buf;
0990 }
0991
0992
0993
0994
0995
0996 static void coda_scale_quant_table(u8 *q_tab, int scale)
0997 {
0998 unsigned int temp;
0999 int i;
1000
1001 for (i = 0; i < 64; i++) {
1002 temp = DIV_ROUND_CLOSEST((unsigned int)q_tab[i] * scale, 100);
1003 if (temp <= 0)
1004 temp = 1;
1005 if (temp > 255)
1006 temp = 255;
1007 q_tab[i] = (unsigned char)temp;
1008 }
1009 }
1010
1011 void coda_set_jpeg_compression_quality(struct coda_ctx *ctx, int quality)
1012 {
1013 unsigned int scale;
1014
1015 ctx->params.jpeg_quality = quality;
1016
1017
1018 if (quality > 100)
1019 quality = 100;
1020 if (quality < 5)
1021 quality = 5;
1022
1023
1024
1025
1026
1027 if (quality < 50)
1028 scale = 5000 / quality;
1029 else
1030 scale = 200 - 2 * quality;
1031
1032 if (ctx->params.jpeg_qmat_tab[0]) {
1033 memcpy(ctx->params.jpeg_qmat_tab[0], luma_q, 64);
1034 coda_scale_quant_table(ctx->params.jpeg_qmat_tab[0], scale);
1035 }
1036 if (ctx->params.jpeg_qmat_tab[1]) {
1037 memcpy(ctx->params.jpeg_qmat_tab[1], chroma_q, 64);
1038 coda_scale_quant_table(ctx->params.jpeg_qmat_tab[1], scale);
1039 }
1040 }
1041
1042
1043
1044
1045
1046 static int coda9_jpeg_start_encoding(struct coda_ctx *ctx)
1047 {
1048 struct coda_dev *dev = ctx->dev;
1049 int ret;
1050
1051 ret = coda9_jpeg_load_huff_tab(ctx);
1052 if (ret < 0) {
1053 v4l2_err(&dev->v4l2_dev, "error loading Huffman tables\n");
1054 return ret;
1055 }
1056 if (!ctx->params.jpeg_qmat_tab[0])
1057 ctx->params.jpeg_qmat_tab[0] = kmalloc(64, GFP_KERNEL);
1058 if (!ctx->params.jpeg_qmat_tab[1])
1059 ctx->params.jpeg_qmat_tab[1] = kmalloc(64, GFP_KERNEL);
1060 coda_set_jpeg_compression_quality(ctx, ctx->params.jpeg_quality);
1061
1062 return 0;
1063 }
1064
1065 static int coda9_jpeg_prepare_encode(struct coda_ctx *ctx)
1066 {
1067 struct coda_q_data *q_data_src;
1068 struct vb2_v4l2_buffer *src_buf, *dst_buf;
1069 struct coda_dev *dev = ctx->dev;
1070 u32 start_addr, end_addr;
1071 u16 aligned_width, aligned_height;
1072 bool chroma_interleave;
1073 int chroma_format;
1074 int header_len;
1075 int ret;
1076 ktime_t timeout;
1077
1078 src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
1079 dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
1080 q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
1081
1082 if (vb2_get_plane_payload(&src_buf->vb2_buf, 0) == 0)
1083 vb2_set_plane_payload(&src_buf->vb2_buf, 0,
1084 vb2_plane_size(&src_buf->vb2_buf, 0));
1085
1086 src_buf->sequence = ctx->osequence;
1087 dst_buf->sequence = ctx->osequence;
1088 ctx->osequence++;
1089
1090 src_buf->flags |= V4L2_BUF_FLAG_KEYFRAME;
1091 src_buf->flags &= ~V4L2_BUF_FLAG_PFRAME;
1092
1093 coda_set_gdi_regs(ctx);
1094
1095 start_addr = vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0);
1096 end_addr = start_addr + vb2_plane_size(&dst_buf->vb2_buf, 0);
1097
1098 chroma_format = coda9_jpeg_chroma_format(q_data_src->fourcc);
1099 if (chroma_format < 0)
1100 return chroma_format;
1101
1102
1103 aligned_width = round_up(q_data_src->width, width_align[chroma_format]);
1104 aligned_height = round_up(q_data_src->height,
1105 height_align[chroma_format]);
1106 if (aligned_width != q_data_src->bytesperline) {
1107 v4l2_err(&dev->v4l2_dev, "wrong stride: %d instead of %d\n",
1108 aligned_width, q_data_src->bytesperline);
1109 }
1110
1111 header_len =
1112 coda9_jpeg_encode_header(ctx,
1113 vb2_plane_size(&dst_buf->vb2_buf, 0),
1114 vb2_plane_vaddr(&dst_buf->vb2_buf, 0));
1115 if (header_len < 0)
1116 return header_len;
1117
1118 coda_write(dev, start_addr + header_len, CODA9_REG_JPEG_BBC_BAS_ADDR);
1119 coda_write(dev, end_addr, CODA9_REG_JPEG_BBC_END_ADDR);
1120 coda_write(dev, start_addr + header_len, CODA9_REG_JPEG_BBC_WR_PTR);
1121 coda_write(dev, start_addr + header_len, CODA9_REG_JPEG_BBC_RD_PTR);
1122 coda_write(dev, 0, CODA9_REG_JPEG_BBC_CUR_POS);
1123
1124 coda_write(dev, 64, CODA9_REG_JPEG_BBC_DATA_CNT);
1125 coda_write(dev, start_addr, CODA9_REG_JPEG_BBC_EXT_ADDR);
1126 coda_write(dev, 0, CODA9_REG_JPEG_BBC_INT_ADDR);
1127
1128 coda_write(dev, 0, CODA9_REG_JPEG_GBU_BT_PTR);
1129 coda_write(dev, 0, CODA9_REG_JPEG_GBU_WD_PTR);
1130 coda_write(dev, 0, CODA9_REG_JPEG_GBU_BBSR);
1131 coda_write(dev, BIT(31) | ((end_addr - start_addr - header_len) / 256),
1132 CODA9_REG_JPEG_BBC_STRM_CTRL);
1133 coda_write(dev, 0, CODA9_REG_JPEG_GBU_CTRL);
1134 coda_write(dev, 0, CODA9_REG_JPEG_GBU_FF_RPTR);
1135 coda_write(dev, 127, CODA9_REG_JPEG_GBU_BBER);
1136 coda_write(dev, 64, CODA9_REG_JPEG_GBU_BBIR);
1137 coda_write(dev, 64, CODA9_REG_JPEG_GBU_BBHR);
1138
1139 chroma_interleave = (q_data_src->fourcc == V4L2_PIX_FMT_NV12);
1140 coda_write(dev, CODA9_JPEG_PIC_CTRL_TC_DIRECTION |
1141 CODA9_JPEG_PIC_CTRL_ENCODER_EN, CODA9_REG_JPEG_PIC_CTRL);
1142 coda_write(dev, 0, CODA9_REG_JPEG_SCL_INFO);
1143 coda_write(dev, chroma_interleave, CODA9_REG_JPEG_DPB_CONFIG);
1144 coda_write(dev, ctx->params.jpeg_restart_interval,
1145 CODA9_REG_JPEG_RST_INTVAL);
1146 coda_write(dev, 1, CODA9_REG_JPEG_BBC_CTRL);
1147
1148 coda_write(dev, bus_req_num[chroma_format], CODA9_REG_JPEG_OP_INFO);
1149
1150 coda9_jpeg_write_huff_tab(ctx);
1151 coda9_jpeg_load_qmat_tab(ctx);
1152
1153 if (ctx->params.rot_mode & CODA_ROT_90) {
1154 aligned_width = aligned_height;
1155 aligned_height = q_data_src->bytesperline;
1156 if (chroma_format == CODA9_JPEG_FORMAT_422)
1157 chroma_format = CODA9_JPEG_FORMAT_224;
1158 else if (chroma_format == CODA9_JPEG_FORMAT_224)
1159 chroma_format = CODA9_JPEG_FORMAT_422;
1160 }
1161
1162 coda_write(dev, aligned_width << 16 | aligned_height,
1163 CODA9_REG_JPEG_PIC_SIZE);
1164 coda_write(dev, ctx->params.rot_mode ?
1165 (CODA_ROT_MIR_ENABLE | ctx->params.rot_mode) : 0,
1166 CODA9_REG_JPEG_ROT_INFO);
1167
1168 coda_write(dev, mcu_info[chroma_format], CODA9_REG_JPEG_MCU_INFO);
1169
1170 coda_write(dev, 1, CODA9_GDI_CONTROL);
1171 timeout = ktime_add_us(ktime_get(), 100000);
1172 do {
1173 ret = coda_read(dev, CODA9_GDI_STATUS);
1174 if (ktime_compare(ktime_get(), timeout) > 0) {
1175 v4l2_err(&dev->v4l2_dev, "timeout waiting for GDI\n");
1176 return -ETIMEDOUT;
1177 }
1178 } while (!ret);
1179
1180 coda_write(dev, (chroma_format << 17) | (chroma_interleave << 16) |
1181 q_data_src->bytesperline, CODA9_GDI_INFO_CONTROL);
1182
1183 coda_write(dev, aligned_width << 16 | aligned_height,
1184 CODA9_GDI_INFO_PIC_SIZE);
1185
1186 coda_write_base(ctx, q_data_src, src_buf, CODA9_GDI_INFO_BASE_Y);
1187
1188 coda_write(dev, 0, CODA9_REG_JPEG_DPB_BASE00);
1189 coda_write(dev, 0, CODA9_GDI_CONTROL);
1190 coda_write(dev, 1, CODA9_GDI_PIC_INIT_HOST);
1191
1192 coda_write(dev, 1, CODA9_GDI_WPROT_ERR_CLR);
1193 coda_write(dev, 0, CODA9_GDI_WPROT_RGN_EN);
1194
1195 trace_coda_jpeg_run(ctx, src_buf);
1196
1197 coda_write(dev, 1, CODA9_REG_JPEG_PIC_START);
1198
1199 return 0;
1200 }
1201
1202 static void coda9_jpeg_finish_encode(struct coda_ctx *ctx)
1203 {
1204 struct vb2_v4l2_buffer *src_buf, *dst_buf;
1205 struct coda_dev *dev = ctx->dev;
1206 u32 wr_ptr, start_ptr;
1207 u32 err_mb;
1208
1209 if (ctx->aborting) {
1210 coda_write(ctx->dev, 0, CODA9_REG_JPEG_BBC_FLUSH_CMD);
1211 return;
1212 }
1213
1214
1215
1216
1217
1218
1219 mutex_lock(&ctx->wakeup_mutex);
1220 src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
1221 dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
1222
1223 trace_coda_jpeg_done(ctx, dst_buf);
1224
1225
1226
1227
1228
1229 start_ptr = vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0);
1230 wr_ptr = coda_read(dev, CODA9_REG_JPEG_BBC_WR_PTR);
1231 vb2_set_plane_payload(&dst_buf->vb2_buf, 0, wr_ptr - start_ptr);
1232
1233 err_mb = coda_read(dev, CODA9_REG_JPEG_PIC_ERRMB);
1234 if (err_mb)
1235 coda_dbg(1, ctx, "ERRMB: 0x%x\n", err_mb);
1236
1237 coda_write(dev, 0, CODA9_REG_JPEG_BBC_FLUSH_CMD);
1238
1239 dst_buf->flags &= ~(V4L2_BUF_FLAG_PFRAME | V4L2_BUF_FLAG_LAST);
1240 dst_buf->flags |= V4L2_BUF_FLAG_KEYFRAME;
1241 dst_buf->flags |= src_buf->flags & V4L2_BUF_FLAG_LAST;
1242
1243 v4l2_m2m_buf_copy_metadata(src_buf, dst_buf, false);
1244
1245 v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);
1246 coda_m2m_buf_done(ctx, dst_buf, err_mb ? VB2_BUF_STATE_ERROR :
1247 VB2_BUF_STATE_DONE);
1248 mutex_unlock(&ctx->wakeup_mutex);
1249
1250 coda_dbg(1, ctx, "job finished: encoded frame (%u)%s\n",
1251 dst_buf->sequence,
1252 (dst_buf->flags & V4L2_BUF_FLAG_LAST) ? " (last)" : "");
1253
1254
1255
1256
1257
1258
1259 coda_hw_reset(ctx);
1260 }
1261
1262 static void coda9_jpeg_encode_timeout(struct coda_ctx *ctx)
1263 {
1264 struct coda_dev *dev = ctx->dev;
1265 u32 end_addr, wr_ptr;
1266
1267
1268 end_addr = coda_read(dev, CODA9_REG_JPEG_BBC_END_ADDR);
1269 wr_ptr = coda_read(dev, CODA9_REG_JPEG_BBC_WR_PTR);
1270 if (wr_ptr >= end_addr - 256) {
1271 v4l2_err(&dev->v4l2_dev, "JPEG too large for capture buffer\n");
1272 coda9_jpeg_finish_encode(ctx);
1273 return;
1274 }
1275
1276 coda_hw_reset(ctx);
1277 }
1278
1279 static void coda9_jpeg_release(struct coda_ctx *ctx)
1280 {
1281 int i;
1282
1283 if (ctx->params.jpeg_qmat_tab[0] == luma_q)
1284 ctx->params.jpeg_qmat_tab[0] = NULL;
1285 if (ctx->params.jpeg_qmat_tab[1] == chroma_q)
1286 ctx->params.jpeg_qmat_tab[1] = NULL;
1287 for (i = 0; i < 3; i++)
1288 kfree(ctx->params.jpeg_qmat_tab[i]);
1289 kfree(ctx->params.jpeg_huff_data);
1290 kfree(ctx->params.jpeg_huff_tab);
1291 }
1292
1293 const struct coda_context_ops coda9_jpeg_encode_ops = {
1294 .queue_init = coda_encoder_queue_init,
1295 .start_streaming = coda9_jpeg_start_encoding,
1296 .prepare_run = coda9_jpeg_prepare_encode,
1297 .finish_run = coda9_jpeg_finish_encode,
1298 .run_timeout = coda9_jpeg_encode_timeout,
1299 .release = coda9_jpeg_release,
1300 };
1301
1302
1303
1304
1305
1306 static int coda9_jpeg_start_decoding(struct coda_ctx *ctx)
1307 {
1308 ctx->params.jpeg_qmat_index[0] = 0;
1309 ctx->params.jpeg_qmat_index[1] = 1;
1310 ctx->params.jpeg_qmat_index[2] = 1;
1311 ctx->params.jpeg_qmat_tab[0] = luma_q;
1312 ctx->params.jpeg_qmat_tab[1] = chroma_q;
1313
1314
1315
1316
1317
1318
1319 return 0;
1320 }
1321
1322 static int coda9_jpeg_prepare_decode(struct coda_ctx *ctx)
1323 {
1324 struct coda_dev *dev = ctx->dev;
1325 int aligned_width, aligned_height;
1326 int chroma_format;
1327 int ret;
1328 u32 val, dst_fourcc;
1329 struct coda_q_data *q_data_src, *q_data_dst;
1330 struct vb2_v4l2_buffer *src_buf, *dst_buf;
1331 int chroma_interleave;
1332 int scl_hor_mode, scl_ver_mode;
1333
1334 src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
1335 dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
1336 q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
1337 q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
1338 dst_fourcc = q_data_dst->fourcc;
1339
1340 scl_hor_mode = coda_jpeg_scale(q_data_src->width, q_data_dst->width);
1341 scl_ver_mode = coda_jpeg_scale(q_data_src->height, q_data_dst->height);
1342
1343 if (vb2_get_plane_payload(&src_buf->vb2_buf, 0) == 0)
1344 vb2_set_plane_payload(&src_buf->vb2_buf, 0,
1345 vb2_plane_size(&src_buf->vb2_buf, 0));
1346
1347 chroma_format = coda9_jpeg_chroma_format(q_data_dst->fourcc);
1348 if (chroma_format < 0)
1349 return chroma_format;
1350
1351 ret = coda_jpeg_decode_header(ctx, &src_buf->vb2_buf);
1352 if (ret < 0) {
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_ERROR);
1357
1358 return ret;
1359 }
1360
1361
1362 aligned_width = round_up(q_data_src->width, width_align[chroma_format]);
1363 aligned_height = round_up(q_data_src->height, height_align[chroma_format]);
1364 if (aligned_width != q_data_dst->bytesperline) {
1365 v4l2_err(&dev->v4l2_dev, "stride mismatch: %d != %d\n",
1366 aligned_width, q_data_dst->bytesperline);
1367 }
1368
1369 coda_set_gdi_regs(ctx);
1370
1371 val = ctx->params.jpeg_huff_ac_index[0] << 12 |
1372 ctx->params.jpeg_huff_ac_index[1] << 11 |
1373 ctx->params.jpeg_huff_ac_index[2] << 10 |
1374 ctx->params.jpeg_huff_dc_index[0] << 9 |
1375 ctx->params.jpeg_huff_dc_index[1] << 8 |
1376 ctx->params.jpeg_huff_dc_index[2] << 7;
1377 if (ctx->params.jpeg_huff_tab)
1378 val |= CODA9_JPEG_PIC_CTRL_USER_HUFFMAN_EN;
1379 coda_write(dev, val, CODA9_REG_JPEG_PIC_CTRL);
1380
1381 coda_write(dev, aligned_width << 16 | aligned_height,
1382 CODA9_REG_JPEG_PIC_SIZE);
1383
1384 chroma_interleave = (dst_fourcc == V4L2_PIX_FMT_NV12);
1385 coda_write(dev, 0, CODA9_REG_JPEG_ROT_INFO);
1386 coda_write(dev, bus_req_num[chroma_format], CODA9_REG_JPEG_OP_INFO);
1387 coda_write(dev, mcu_info[chroma_format], CODA9_REG_JPEG_MCU_INFO);
1388 if (scl_hor_mode || scl_ver_mode)
1389 val = CODA9_JPEG_SCL_ENABLE | (scl_hor_mode << 2) | scl_ver_mode;
1390 else
1391 val = 0;
1392 coda_write(dev, val, CODA9_REG_JPEG_SCL_INFO);
1393 coda_write(dev, chroma_interleave, CODA9_REG_JPEG_DPB_CONFIG);
1394 coda_write(dev, ctx->params.jpeg_restart_interval,
1395 CODA9_REG_JPEG_RST_INTVAL);
1396
1397 if (ctx->params.jpeg_huff_tab) {
1398 ret = coda9_jpeg_dec_huff_setup(ctx);
1399 if (ret < 0) {
1400 v4l2_err(&dev->v4l2_dev,
1401 "failed to set up Huffman tables: %d\n", ret);
1402 return ret;
1403 }
1404 }
1405
1406 coda9_jpeg_qmat_setup(ctx);
1407
1408 coda9_jpeg_dec_bbc_gbu_setup(ctx, &src_buf->vb2_buf,
1409 ctx->jpeg_ecs_offset);
1410
1411 coda_write(dev, 0, CODA9_REG_JPEG_RST_INDEX);
1412 coda_write(dev, 0, CODA9_REG_JPEG_RST_COUNT);
1413
1414 coda_write(dev, 0, CODA9_REG_JPEG_DPCM_DIFF_Y);
1415 coda_write(dev, 0, CODA9_REG_JPEG_DPCM_DIFF_CB);
1416 coda_write(dev, 0, CODA9_REG_JPEG_DPCM_DIFF_CR);
1417
1418 coda_write(dev, 0, CODA9_REG_JPEG_ROT_INFO);
1419
1420 coda_write(dev, 1, CODA9_GDI_CONTROL);
1421 do {
1422 ret = coda_read(dev, CODA9_GDI_STATUS);
1423 } while (!ret);
1424
1425 val = (chroma_format << 17) | (chroma_interleave << 16) |
1426 q_data_dst->bytesperline;
1427 if (ctx->tiled_map_type == GDI_TILED_FRAME_MB_RASTER_MAP)
1428 val |= 3 << 20;
1429 coda_write(dev, val, CODA9_GDI_INFO_CONTROL);
1430
1431 coda_write(dev, aligned_width << 16 | aligned_height,
1432 CODA9_GDI_INFO_PIC_SIZE);
1433
1434 coda_write_base(ctx, q_data_dst, dst_buf, CODA9_GDI_INFO_BASE_Y);
1435
1436 coda_write(dev, 0, CODA9_REG_JPEG_DPB_BASE00);
1437 coda_write(dev, 0, CODA9_GDI_CONTROL);
1438 coda_write(dev, 1, CODA9_GDI_PIC_INIT_HOST);
1439
1440 trace_coda_jpeg_run(ctx, src_buf);
1441
1442 coda_write(dev, 1, CODA9_REG_JPEG_PIC_START);
1443
1444 return 0;
1445 }
1446
1447 static void coda9_jpeg_finish_decode(struct coda_ctx *ctx)
1448 {
1449 struct coda_dev *dev = ctx->dev;
1450 struct vb2_v4l2_buffer *dst_buf, *src_buf;
1451 struct coda_q_data *q_data_dst;
1452 u32 err_mb;
1453
1454 err_mb = coda_read(dev, CODA9_REG_JPEG_PIC_ERRMB);
1455 if (err_mb)
1456 v4l2_err(&dev->v4l2_dev, "ERRMB: 0x%x\n", err_mb);
1457
1458 coda_write(dev, 0, CODA9_REG_JPEG_BBC_FLUSH_CMD);
1459
1460
1461
1462
1463
1464
1465 mutex_lock(&ctx->wakeup_mutex);
1466 src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
1467 dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
1468 dst_buf->sequence = ctx->osequence++;
1469
1470 trace_coda_jpeg_done(ctx, dst_buf);
1471
1472 dst_buf->flags &= ~(V4L2_BUF_FLAG_PFRAME | V4L2_BUF_FLAG_LAST);
1473 dst_buf->flags |= V4L2_BUF_FLAG_KEYFRAME;
1474 dst_buf->flags |= src_buf->flags & V4L2_BUF_FLAG_LAST;
1475
1476 v4l2_m2m_buf_copy_metadata(src_buf, dst_buf, false);
1477
1478 q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
1479 vb2_set_plane_payload(&dst_buf->vb2_buf, 0, q_data_dst->sizeimage);
1480
1481 v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);
1482 coda_m2m_buf_done(ctx, dst_buf, err_mb ? VB2_BUF_STATE_ERROR :
1483 VB2_BUF_STATE_DONE);
1484
1485 mutex_unlock(&ctx->wakeup_mutex);
1486
1487 coda_dbg(1, ctx, "job finished: decoded frame (%u)%s\n",
1488 dst_buf->sequence,
1489 (dst_buf->flags & V4L2_BUF_FLAG_LAST) ? " (last)" : "");
1490
1491
1492
1493
1494
1495
1496 coda_hw_reset(ctx);
1497 }
1498
1499 const struct coda_context_ops coda9_jpeg_decode_ops = {
1500 .queue_init = coda_encoder_queue_init,
1501 .start_streaming = coda9_jpeg_start_decoding,
1502 .prepare_run = coda9_jpeg_prepare_decode,
1503 .finish_run = coda9_jpeg_finish_decode,
1504 .release = coda9_jpeg_release,
1505 };
1506
1507 irqreturn_t coda9_jpeg_irq_handler(int irq, void *data)
1508 {
1509 struct coda_dev *dev = data;
1510 struct coda_ctx *ctx;
1511 int status;
1512 int err_mb;
1513
1514 status = coda_read(dev, CODA9_REG_JPEG_PIC_STATUS);
1515 if (status == 0)
1516 return IRQ_HANDLED;
1517 coda_write(dev, status, CODA9_REG_JPEG_PIC_STATUS);
1518
1519 if (status & CODA9_JPEG_STATUS_OVERFLOW)
1520 v4l2_err(&dev->v4l2_dev, "JPEG overflow\n");
1521
1522 if (status & CODA9_JPEG_STATUS_BBC_INT)
1523 v4l2_err(&dev->v4l2_dev, "JPEG BBC interrupt\n");
1524
1525 if (status & CODA9_JPEG_STATUS_ERROR) {
1526 v4l2_err(&dev->v4l2_dev, "JPEG error\n");
1527
1528 err_mb = coda_read(dev, CODA9_REG_JPEG_PIC_ERRMB);
1529 if (err_mb) {
1530 v4l2_err(&dev->v4l2_dev,
1531 "ERRMB: 0x%x: rst idx %d, mcu pos (%d,%d)\n",
1532 err_mb, err_mb >> 24, (err_mb >> 12) & 0xfff,
1533 err_mb & 0xfff);
1534 }
1535 }
1536
1537 ctx = v4l2_m2m_get_curr_priv(dev->m2m_dev);
1538 if (!ctx) {
1539 v4l2_err(&dev->v4l2_dev,
1540 "Instance released before the end of transaction\n");
1541 mutex_unlock(&dev->coda_mutex);
1542 return IRQ_HANDLED;
1543 }
1544
1545 complete(&ctx->completion);
1546
1547 return IRQ_HANDLED;
1548 }