linux/drivers/media/platform/coda/coda-jpeg.c
<<
>>
Prefs
   1/*
   2 * Coda multi-standard codec IP - JPEG support functions
   3 *
   4 * Copyright (C) 2014 Philipp Zabel, Pengutronix
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License as published by
   8 * the Free Software Foundation; either version 2 of the License, or
   9 * (at your option) any later version.
  10 */
  11
  12#include <linux/kernel.h>
  13#include <linux/swab.h>
  14
  15#include "coda.h"
  16#include "trace.h"
  17
  18#define SOI_MARKER      0xffd8
  19#define EOI_MARKER      0xffd9
  20
  21/*
  22 * Typical Huffman tables for 8-bit precision luminance and
  23 * chrominance from JPEG ITU-T.81 (ISO/IEC 10918-1) Annex K.3
  24 */
  25
  26static const unsigned char luma_dc_bits[16] = {
  27        0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01,
  28        0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  29};
  30
  31static const unsigned char luma_dc_value[12] = {
  32        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
  33        0x08, 0x09, 0x0a, 0x0b,
  34};
  35
  36static const unsigned char chroma_dc_bits[16] = {
  37        0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  38        0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
  39};
  40
  41static const unsigned char chroma_dc_value[12] = {
  42        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
  43        0x08, 0x09, 0x0a, 0x0b,
  44};
  45
  46static const unsigned char luma_ac_bits[16] = {
  47        0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03,
  48        0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d,
  49};
  50
  51static const unsigned char luma_ac_value[162 + 2] = {
  52        0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
  53        0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
  54        0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
  55        0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
  56        0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
  57        0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
  58        0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
  59        0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
  60        0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
  61        0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
  62        0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
  63        0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
  64        0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
  65        0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
  66        0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
  67        0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
  68        0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
  69        0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
  70        0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
  71        0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
  72        0xf9, 0xfa, /* padded to 32-bit */
  73};
  74
  75static const unsigned char chroma_ac_bits[16] = {
  76        0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
  77        0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77,
  78};
  79
  80static const unsigned char chroma_ac_value[162 + 2] = {
  81        0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
  82        0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
  83        0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
  84        0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
  85        0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
  86        0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
  87        0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
  88        0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
  89        0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
  90        0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
  91        0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
  92        0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
  93        0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
  94        0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
  95        0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
  96        0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
  97        0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
  98        0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
  99        0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
 100        0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
 101        0xf9, 0xfa, /* padded to 32-bit */
 102};
 103
 104/*
 105 * Quantization tables for luminance and chrominance components in
 106 * zig-zag scan order from the Freescale i.MX VPU libaries
 107 */
 108
 109static unsigned char luma_q[64] = {
 110        0x06, 0x04, 0x04, 0x04, 0x05, 0x04, 0x06, 0x05,
 111        0x05, 0x06, 0x09, 0x06, 0x05, 0x06, 0x09, 0x0b,
 112        0x08, 0x06, 0x06, 0x08, 0x0b, 0x0c, 0x0a, 0x0a,
 113        0x0b, 0x0a, 0x0a, 0x0c, 0x10, 0x0c, 0x0c, 0x0c,
 114        0x0c, 0x0c, 0x0c, 0x10, 0x0c, 0x0c, 0x0c, 0x0c,
 115        0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
 116        0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
 117        0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
 118};
 119
 120static unsigned char chroma_q[64] = {
 121        0x07, 0x07, 0x07, 0x0d, 0x0c, 0x0d, 0x18, 0x10,
 122        0x10, 0x18, 0x14, 0x0e, 0x0e, 0x0e, 0x14, 0x14,
 123        0x0e, 0x0e, 0x0e, 0x0e, 0x14, 0x11, 0x0c, 0x0c,
 124        0x0c, 0x0c, 0x0c, 0x11, 0x11, 0x0c, 0x0c, 0x0c,
 125        0x0c, 0x0c, 0x0c, 0x11, 0x0c, 0x0c, 0x0c, 0x0c,
 126        0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
 127        0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
 128        0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
 129};
 130
 131struct coda_memcpy_desc {
 132        int offset;
 133        const void *src;
 134        size_t len;
 135};
 136
 137static void coda_memcpy_parabuf(void *parabuf,
 138                                const struct coda_memcpy_desc *desc)
 139{
 140        u32 *dst = parabuf + desc->offset;
 141        const u32 *src = desc->src;
 142        int len = desc->len / 4;
 143        int i;
 144
 145        for (i = 0; i < len; i += 2) {
 146                dst[i + 1] = swab32(src[i]);
 147                dst[i] = swab32(src[i + 1]);
 148        }
 149}
 150
 151int coda_jpeg_write_tables(struct coda_ctx *ctx)
 152{
 153        int i;
 154        static const struct coda_memcpy_desc huff[8] = {
 155                { 0,   luma_dc_bits,    sizeof(luma_dc_bits)    },
 156                { 16,  luma_dc_value,   sizeof(luma_dc_value)   },
 157                { 32,  luma_ac_bits,    sizeof(luma_ac_bits)    },
 158                { 48,  luma_ac_value,   sizeof(luma_ac_value)   },
 159                { 216, chroma_dc_bits,  sizeof(chroma_dc_bits)  },
 160                { 232, chroma_dc_value, sizeof(chroma_dc_value) },
 161                { 248, chroma_ac_bits,  sizeof(chroma_ac_bits)  },
 162                { 264, chroma_ac_value, sizeof(chroma_ac_value) },
 163        };
 164        struct coda_memcpy_desc qmat[3] = {
 165                { 512, ctx->params.jpeg_qmat_tab[0], 64 },
 166                { 576, ctx->params.jpeg_qmat_tab[1], 64 },
 167                { 640, ctx->params.jpeg_qmat_tab[1], 64 },
 168        };
 169
 170        /* Write huffman tables to parameter memory */
 171        for (i = 0; i < ARRAY_SIZE(huff); i++)
 172                coda_memcpy_parabuf(ctx->parabuf.vaddr, huff + i);
 173
 174        /* Write Q-matrix to parameter memory */
 175        for (i = 0; i < ARRAY_SIZE(qmat); i++)
 176                coda_memcpy_parabuf(ctx->parabuf.vaddr, qmat + i);
 177
 178        return 0;
 179}
 180
 181bool coda_jpeg_check_buffer(struct coda_ctx *ctx, struct vb2_buffer *vb)
 182{
 183        void *vaddr = vb2_plane_vaddr(vb, 0);
 184        u16 soi, eoi;
 185        int len, i;
 186
 187        soi = be16_to_cpup((__be16 *)vaddr);
 188        if (soi != SOI_MARKER)
 189                return false;
 190
 191        len = vb2_get_plane_payload(vb, 0);
 192        vaddr += len - 2;
 193        for (i = 0; i < 32; i++) {
 194                eoi = be16_to_cpup((__be16 *)(vaddr - i));
 195                if (eoi == EOI_MARKER) {
 196                        if (i > 0)
 197                                vb2_set_plane_payload(vb, 0, len - i);
 198                        return true;
 199                }
 200        }
 201
 202        return false;
 203}
 204
 205/*
 206 * Scale quantization table using nonlinear scaling factor
 207 * u8 qtab[64], scale [50,190]
 208 */
 209static void coda_scale_quant_table(u8 *q_tab, int scale)
 210{
 211        unsigned int temp;
 212        int i;
 213
 214        for (i = 0; i < 64; i++) {
 215                temp = DIV_ROUND_CLOSEST((unsigned int)q_tab[i] * scale, 100);
 216                if (temp <= 0)
 217                        temp = 1;
 218                if (temp > 255)
 219                        temp = 255;
 220                q_tab[i] = (unsigned char)temp;
 221        }
 222}
 223
 224void coda_set_jpeg_compression_quality(struct coda_ctx *ctx, int quality)
 225{
 226        unsigned int scale;
 227
 228        ctx->params.jpeg_quality = quality;
 229
 230        /* Clip quality setting to [5,100] interval */
 231        if (quality > 100)
 232                quality = 100;
 233        if (quality < 5)
 234                quality = 5;
 235
 236        /*
 237         * Non-linear scaling factor:
 238         * [5,50] -> [1000..100], [51,100] -> [98..0]
 239         */
 240        if (quality < 50)
 241                scale = 5000 / quality;
 242        else
 243                scale = 200 - 2 * quality;
 244
 245        if (ctx->params.jpeg_qmat_tab[0]) {
 246                memcpy(ctx->params.jpeg_qmat_tab[0], luma_q, 64);
 247                coda_scale_quant_table(ctx->params.jpeg_qmat_tab[0], scale);
 248        }
 249        if (ctx->params.jpeg_qmat_tab[1]) {
 250                memcpy(ctx->params.jpeg_qmat_tab[1], chroma_q, 64);
 251                coda_scale_quant_table(ctx->params.jpeg_qmat_tab[1], scale);
 252        }
 253}
 254