1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (C) Collabora, Ltd. 4 * 5 * Based on GSPCA and CODA drivers: 6 * Copyright (C) Jean-Francois Moine (http://moinejf.free.fr) 7 * Copyright (C) 2014 Philipp Zabel, Pengutronix 8 */ 9 10 #include <linux/align.h> 11 #include <linux/build_bug.h> 12 #include <linux/kernel.h> 13 #include <linux/string.h> 14 #include "hantro_jpeg.h" 15 #include "hantro.h" 16 17 #define LUMA_QUANT_OFF 25 18 #define CHROMA_QUANT_OFF 90 19 #define HEIGHT_OFF 159 20 #define WIDTH_OFF 161 21 22 #define HUFF_LUMA_DC_OFF 178 23 #define HUFF_LUMA_AC_OFF 211 24 #define HUFF_CHROMA_DC_OFF 394 25 #define HUFF_CHROMA_AC_OFF 427 26 27 /* Default tables from JPEG ITU-T.81 28 * (ISO/IEC 10918-1) Annex K, tables K.1 and K.2 29 */ 30 static const unsigned char luma_q_table[] = { 31 0x10, 0x0b, 0x0a, 0x10, 0x18, 0x28, 0x33, 0x3d, 32 0x0c, 0x0c, 0x0e, 0x13, 0x1a, 0x3a, 0x3c, 0x37, 33 0x0e, 0x0d, 0x10, 0x18, 0x28, 0x39, 0x45, 0x38, 34 0x0e, 0x11, 0x16, 0x1d, 0x33, 0x57, 0x50, 0x3e, 35 0x12, 0x16, 0x25, 0x38, 0x44, 0x6d, 0x67, 0x4d, 36 0x18, 0x23, 0x37, 0x40, 0x51, 0x68, 0x71, 0x5c, 37 0x31, 0x40, 0x4e, 0x57, 0x67, 0x79, 0x78, 0x65, 38 0x48, 0x5c, 0x5f, 0x62, 0x70, 0x64, 0x67, 0x63 39 }; 40 41 static const unsigned char chroma_q_table[] = { 42 0x11, 0x12, 0x18, 0x2f, 0x63, 0x63, 0x63, 0x63, 43 0x12, 0x15, 0x1a, 0x42, 0x63, 0x63, 0x63, 0x63, 44 0x18, 0x1a, 0x38, 0x63, 0x63, 0x63, 0x63, 0x63, 45 0x2f, 0x42, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 46 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 47 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 48 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 49 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63 50 }; 51 52 static const unsigned char zigzag[] = { 53 0, 1, 8, 16, 9, 2, 3, 10, 54 17, 24, 32, 25, 18, 11, 4, 5, 55 12, 19, 26, 33, 40, 48, 41, 34, 56 27, 20, 13, 6, 7, 14, 21, 28, 57 35, 42, 49, 56, 57, 50, 43, 36, 58 29, 22, 15, 23, 30, 37, 44, 51, 59 58, 59, 52, 45, 38, 31, 39, 46, 60 53, 60, 61, 54, 47, 55, 62, 63 61 }; 62 63 static const u32 hw_reorder[] = { 64 0, 8, 16, 24, 1, 9, 17, 25, 65 32, 40, 48, 56, 33, 41, 49, 57, 66 2, 10, 18, 26, 3, 11, 19, 27, 67 34, 42, 50, 58, 35, 43, 51, 59, 68 4, 12, 20, 28, 5, 13, 21, 29, 69 36, 44, 52, 60, 37, 45, 53, 61, 70 6, 14, 22, 30, 7, 15, 23, 31, 71 38, 46, 54, 62, 39, 47, 55, 63 72 }; 73 74 /* Huffman tables are shared with CODA */ 75 static const unsigned char luma_dc_table[] = { 76 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 77 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 78 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 79 0x08, 0x09, 0x0a, 0x0b, 80 }; 81 82 static const unsigned char chroma_dc_table[] = { 83 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 84 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 85 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 86 0x08, 0x09, 0x0a, 0x0b, 87 }; 88 89 static const unsigned char luma_ac_table[] = { 90 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 91 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d, 92 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 93 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 94 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, 95 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, 96 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, 97 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, 98 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 99 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 100 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 101 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 102 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 103 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 104 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 105 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 106 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 107 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 108 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 109 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, 110 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 111 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 112 0xf9, 0xfa, 113 }; 114 115 static const unsigned char chroma_ac_table[] = { 116 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 117 0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, 118 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 119 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, 120 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 121 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, 122 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 123 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, 124 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, 125 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 126 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 127 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 128 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 129 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 130 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 131 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 132 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 133 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 134 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 135 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 136 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 137 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 138 0xf9, 0xfa, 139 }; 140 141 /* For simplicity, we keep a pre-formatted JPEG header, 142 * and we'll use fixed offsets to change the width, height 143 * quantization tables, etc. 144 */ 145 static const unsigned char hantro_jpeg_header[] = { 146 /* SOI */ 147 0xff, 0xd8, 148 149 /* JFIF-APP0 */ 150 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46, 151 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 152 0x00, 0x00, 153 154 /* DQT */ 155 0xff, 0xdb, 0x00, 0x84, 156 157 0x00, 158 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 159 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 160 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 161 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 162 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 163 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 164 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 165 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 166 167 0x01, 168 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 169 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 170 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 171 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 172 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 173 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 174 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 175 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 176 177 /* SOF */ 178 0xff, 0xc0, 0x00, 0x11, 0x08, 0x00, 0xf0, 0x01, 179 0x40, 0x03, 0x01, 0x22, 0x00, 0x02, 0x11, 0x01, 180 0x03, 0x11, 0x01, 181 182 /* DHT */ 183 0xff, 0xc4, 0x00, 0x1f, 0x00, 184 185 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 186 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 187 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 188 0x00, 0x00, 0x00, 0x00, 189 190 /* DHT */ 191 0xff, 0xc4, 0x00, 0xb5, 0x10, 192 193 0x00, 0x00, 194 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 195 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 196 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 197 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 198 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 199 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 200 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 201 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 202 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 203 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 204 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 205 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 206 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 207 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 208 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 209 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 210 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 211 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 212 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 213 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 214 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 215 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 216 217 /* DHT */ 218 0xff, 0xc4, 0x00, 0x1f, 0x01, 219 220 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 221 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 222 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 223 0x00, 0x00, 0x00, 0x00, 224 225 /* DHT */ 226 0xff, 0xc4, 0x00, 0xb5, 0x11, 227 228 0x00, 0x00, 229 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 230 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 231 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 232 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 233 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 234 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 235 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 236 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 237 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 238 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 239 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 240 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 241 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 242 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 243 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 244 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 245 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 246 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 247 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 248 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 249 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 250 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 251 252 /* COM */ 253 0xff, 0xfe, 0x00, 0x03, 0x00, 254 255 /* SOS */ 256 0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 257 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00, 258 }; 259 260 /* 261 * JPEG_HEADER_SIZE is used in other parts of the driver in lieu of 262 * "sizeof(hantro_jpeg_header)". The two must be equal. 263 */ 264 static_assert(sizeof(hantro_jpeg_header) == JPEG_HEADER_SIZE); 265 266 /* 267 * hantro_jpeg_header is padded with a COM segment, so that the payload 268 * of the SOS segment (the entropy-encoded image scan), which should 269 * trail the whole header, is 8-byte aligned for the hardware to write 270 * to directly. 271 */ 272 static_assert(IS_ALIGNED(sizeof(hantro_jpeg_header), 8), 273 "Hantro JPEG header size needs to be 8-byte aligned."); 274 275 static unsigned char jpeg_scale_qp(const unsigned char qp, int scale) 276 { 277 unsigned int temp; 278 279 temp = DIV_ROUND_CLOSEST((unsigned int)qp * scale, 100); 280 if (temp <= 0) 281 temp = 1; 282 if (temp > 255) 283 temp = 255; 284 285 return (unsigned char)temp; 286 } 287 288 static void 289 jpeg_scale_quant_table(unsigned char *file_q_tab, 290 unsigned char *reordered_q_tab, 291 const unsigned char *tab, int scale) 292 { 293 int i; 294 295 BUILD_BUG_ON(ARRAY_SIZE(zigzag) != JPEG_QUANT_SIZE); 296 BUILD_BUG_ON(ARRAY_SIZE(hw_reorder) != JPEG_QUANT_SIZE); 297 298 for (i = 0; i < JPEG_QUANT_SIZE; i++) { 299 file_q_tab[i] = jpeg_scale_qp(tab[zigzag[i]], scale); 300 reordered_q_tab[i] = jpeg_scale_qp(tab[hw_reorder[i]], scale); 301 } 302 } 303 304 static void jpeg_set_quality(struct hantro_jpeg_ctx *ctx) 305 { 306 int scale; 307 308 /* 309 * Non-linear scaling factor: 310 * [5,50] -> [1000..100], [51,100] -> [98..0] 311 */ 312 if (ctx->quality < 50) 313 scale = 5000 / ctx->quality; 314 else 315 scale = 200 - 2 * ctx->quality; 316 317 BUILD_BUG_ON(ARRAY_SIZE(luma_q_table) != JPEG_QUANT_SIZE); 318 BUILD_BUG_ON(ARRAY_SIZE(chroma_q_table) != JPEG_QUANT_SIZE); 319 BUILD_BUG_ON(ARRAY_SIZE(ctx->hw_luma_qtable) != JPEG_QUANT_SIZE); 320 BUILD_BUG_ON(ARRAY_SIZE(ctx->hw_chroma_qtable) != JPEG_QUANT_SIZE); 321 322 jpeg_scale_quant_table(ctx->buffer + LUMA_QUANT_OFF, 323 ctx->hw_luma_qtable, luma_q_table, scale); 324 jpeg_scale_quant_table(ctx->buffer + CHROMA_QUANT_OFF, 325 ctx->hw_chroma_qtable, chroma_q_table, scale); 326 } 327 328 void hantro_jpeg_header_assemble(struct hantro_jpeg_ctx *ctx) 329 { 330 char *buf = ctx->buffer; 331 332 memcpy(buf, hantro_jpeg_header, 333 sizeof(hantro_jpeg_header)); 334 335 buf[HEIGHT_OFF + 0] = ctx->height >> 8; 336 buf[HEIGHT_OFF + 1] = ctx->height; 337 buf[WIDTH_OFF + 0] = ctx->width >> 8; 338 buf[WIDTH_OFF + 1] = ctx->width; 339 340 memcpy(buf + HUFF_LUMA_DC_OFF, luma_dc_table, sizeof(luma_dc_table)); 341 memcpy(buf + HUFF_LUMA_AC_OFF, luma_ac_table, sizeof(luma_ac_table)); 342 memcpy(buf + HUFF_CHROMA_DC_OFF, chroma_dc_table, 343 sizeof(chroma_dc_table)); 344 memcpy(buf + HUFF_CHROMA_AC_OFF, chroma_ac_table, 345 sizeof(chroma_ac_table)); 346 347 jpeg_set_quality(ctx); 348 } 349