mtk_jpeg_dec_parse.c (2816B)
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 11#include "mtk_jpeg_dec_parse.h" 12 13#define TEM 0x01 14#define SOF0 0xc0 15#define RST 0xd0 16#define SOI 0xd8 17#define EOI 0xd9 18 19struct mtk_jpeg_stream { 20 u8 *addr; 21 u32 size; 22 u32 curr; 23}; 24 25static int read_byte(struct mtk_jpeg_stream *stream) 26{ 27 if (stream->curr >= stream->size) 28 return -1; 29 return stream->addr[stream->curr++]; 30} 31 32static int read_word_be(struct mtk_jpeg_stream *stream, u32 *word) 33{ 34 u32 temp; 35 int byte; 36 37 byte = read_byte(stream); 38 if (byte == -1) 39 return -1; 40 temp = byte << 8; 41 byte = read_byte(stream); 42 if (byte == -1) 43 return -1; 44 *word = (u32)byte | temp; 45 46 return 0; 47} 48 49static void read_skip(struct mtk_jpeg_stream *stream, long len) 50{ 51 if (len <= 0) 52 return; 53 while (len--) 54 read_byte(stream); 55} 56 57static bool mtk_jpeg_do_parse(struct mtk_jpeg_dec_param *param, u8 *src_addr_va, 58 u32 src_size) 59{ 60 bool notfound = true; 61 struct mtk_jpeg_stream stream; 62 63 stream.addr = src_addr_va; 64 stream.size = src_size; 65 stream.curr = 0; 66 67 while (notfound) { 68 int i, length, byte; 69 u32 word; 70 71 byte = read_byte(&stream); 72 if (byte == -1) 73 return false; 74 if (byte != 0xff) 75 continue; 76 do 77 byte = read_byte(&stream); 78 while (byte == 0xff); 79 if (byte == -1) 80 return false; 81 if (byte == 0) 82 continue; 83 84 length = 0; 85 switch (byte) { 86 case SOF0: 87 /* length */ 88 if (read_word_be(&stream, &word)) 89 break; 90 91 /* precision */ 92 if (read_byte(&stream) == -1) 93 break; 94 95 if (read_word_be(&stream, &word)) 96 break; 97 param->pic_h = word; 98 99 if (read_word_be(&stream, &word)) 100 break; 101 param->pic_w = word; 102 103 param->comp_num = read_byte(&stream); 104 if (param->comp_num != 1 && param->comp_num != 3) 105 break; 106 107 for (i = 0; i < param->comp_num; i++) { 108 param->comp_id[i] = read_byte(&stream); 109 if (param->comp_id[i] == -1) 110 break; 111 112 /* sampling */ 113 byte = read_byte(&stream); 114 if (byte == -1) 115 break; 116 param->sampling_w[i] = (byte >> 4) & 0x0F; 117 param->sampling_h[i] = byte & 0x0F; 118 119 param->qtbl_num[i] = read_byte(&stream); 120 if (param->qtbl_num[i] == -1) 121 break; 122 } 123 124 notfound = !(i == param->comp_num); 125 break; 126 case RST ... RST + 7: 127 case SOI: 128 case EOI: 129 case TEM: 130 break; 131 default: 132 if (read_word_be(&stream, &word)) 133 break; 134 length = (long)word - 2; 135 read_skip(&stream, length); 136 break; 137 } 138 } 139 140 return !notfound; 141} 142 143bool mtk_jpeg_parse(struct mtk_jpeg_dec_param *param, u8 *src_addr_va, 144 u32 src_size) 145{ 146 if (!mtk_jpeg_do_parse(param, src_addr_va, src_size)) 147 return false; 148 if (mtk_jpeg_dec_fill_param(param)) 149 return false; 150 151 return true; 152}