1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2016 MediaTek Inc. 4 * Author: Ming Hsiu Tsai <minghsiu.tsai@mediatek.com> 5 * Rick Chang <rick.chang@mediatek.com> 6 */ 7 8 #include <linux/kernel.h> 9 #include <linux/videodev2.h> 10 #include <media/jpeg.h> 11 12 #include "mtk_jpeg_dec_parse.h" 13 14 struct mtk_jpeg_stream { 15 u8 *addr; 16 u32 size; 17 u32 curr; 18 }; 19 20 static int read_byte(struct mtk_jpeg_stream *stream) 21 { 22 if (stream->curr >= stream->size) 23 return -1; 24 return stream->addr[stream->curr++]; 25 } 26 27 static int read_word_be(struct mtk_jpeg_stream *stream, u32 *word) 28 { 29 u32 temp; 30 int byte; 31 32 byte = read_byte(stream); 33 if (byte == -1) 34 return -1; 35 temp = byte << 8; 36 byte = read_byte(stream); 37 if (byte == -1) 38 return -1; 39 *word = (u32)byte | temp; 40 41 return 0; 42 } 43 44 static void read_skip(struct mtk_jpeg_stream *stream, long len) 45 { 46 if (len <= 0) 47 return; 48 while (len--) 49 read_byte(stream); 50 } 51 52 static bool mtk_jpeg_do_parse(struct mtk_jpeg_dec_param *param, u8 *src_addr_va, 53 u32 src_size) 54 { 55 bool notfound = true; 56 struct mtk_jpeg_stream stream; 57 58 stream.addr = src_addr_va; 59 stream.size = src_size; 60 stream.curr = 0; 61 62 while (notfound) { 63 int i, length, byte; 64 u32 word; 65 66 byte = read_byte(&stream); 67 if (byte == -1) 68 return false; 69 if (byte != 0xff) 70 continue; 71 do 72 byte = read_byte(&stream); 73 while (byte == 0xff); 74 if (byte == -1) 75 return false; 76 if (byte == 0) 77 continue; 78 79 length = 0; 80 switch (byte) { 81 case JPEG_MARKER_SOF0: 82 /* length */ 83 if (read_word_be(&stream, &word)) 84 break; 85 86 /* precision */ 87 if (read_byte(&stream) == -1) 88 break; 89 90 if (read_word_be(&stream, &word)) 91 break; 92 param->pic_h = word; 93 94 if (read_word_be(&stream, &word)) 95 break; 96 param->pic_w = word; 97 98 param->comp_num = read_byte(&stream); 99 if (param->comp_num != 1 && param->comp_num != 3) 100 break; 101 102 for (i = 0; i < param->comp_num; i++) { 103 param->comp_id[i] = read_byte(&stream); 104 if (param->comp_id[i] == -1) 105 break; 106 107 /* sampling */ 108 byte = read_byte(&stream); 109 if (byte == -1) 110 break; 111 param->sampling_w[i] = (byte >> 4) & 0x0F; 112 param->sampling_h[i] = byte & 0x0F; 113 114 param->qtbl_num[i] = read_byte(&stream); 115 if (param->qtbl_num[i] == -1) 116 break; 117 } 118 119 notfound = !(i == param->comp_num); 120 break; 121 case JPEG_MARKER_RST ... JPEG_MARKER_RST + 7: 122 case JPEG_MARKER_SOI: 123 case JPEG_MARKER_EOI: 124 case JPEG_MARKER_TEM: 125 break; 126 default: 127 if (read_word_be(&stream, &word)) 128 break; 129 length = (long)word - 2; 130 read_skip(&stream, length); 131 break; 132 } 133 } 134 135 return !notfound; 136 } 137 138 bool mtk_jpeg_parse(struct mtk_jpeg_dec_param *param, u8 *src_addr_va, 139 u32 src_size) 140 { 141 if (!mtk_jpeg_do_parse(param, src_addr_va, src_size)) 142 return false; 143 if (mtk_jpeg_dec_fill_param(param)) 144 return false; 145 146 return true; 147 } 148