root/drivers/media/platform/coda/coda-jpeg.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. coda_memcpy_parabuf
  2. coda_jpeg_write_tables
  3. coda_jpeg_check_buffer
  4. coda_scale_quant_table
  5. coda_set_jpeg_compression_quality

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

/* [<][>][^][v][top][bottom][index][help] */