148 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*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 14struct mtk_jpeg_stream {15 u8 *addr;16 u32 size;17 u32 curr;18};19 20static 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 27static 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 44static 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 52static 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 do72 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 138bool 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