linux/drivers/media/platform/mtk-jpeg/mtk_jpeg_dec_parse.c
<<
>>
Prefs
   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}
 153