GNU Linux-libre 4.14.251-gnu1
[releases.git] / drivers / media / platform / mtk-jpeg / mtk_jpeg_parse.c
1 /*
2  * Copyright (c) 2016 MediaTek Inc.
3  * Author: Ming Hsiu Tsai <minghsiu.tsai@mediatek.com>
4  *         Rick Chang <rick.chang@mediatek.com>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  */
15
16 #include <linux/kernel.h>
17 #include <linux/videodev2.h>
18
19 #include "mtk_jpeg_parse.h"
20
21 #define TEM     0x01
22 #define SOF0    0xc0
23 #define RST     0xd0
24 #define SOI     0xd8
25 #define EOI     0xd9
26
27 struct mtk_jpeg_stream {
28         u8 *addr;
29         u32 size;
30         u32 curr;
31 };
32
33 static int read_byte(struct mtk_jpeg_stream *stream)
34 {
35         if (stream->curr >= stream->size)
36                 return -1;
37         return stream->addr[stream->curr++];
38 }
39
40 static int read_word_be(struct mtk_jpeg_stream *stream, u32 *word)
41 {
42         u32 temp;
43         int byte;
44
45         byte = read_byte(stream);
46         if (byte == -1)
47                 return -1;
48         temp = byte << 8;
49         byte = read_byte(stream);
50         if (byte == -1)
51                 return -1;
52         *word = (u32)byte | temp;
53
54         return 0;
55 }
56
57 static void read_skip(struct mtk_jpeg_stream *stream, long len)
58 {
59         if (len <= 0)
60                 return;
61         while (len--)
62                 read_byte(stream);
63 }
64
65 static bool mtk_jpeg_do_parse(struct mtk_jpeg_dec_param *param, u8 *src_addr_va,
66                               u32 src_size)
67 {
68         bool notfound = true;
69         struct mtk_jpeg_stream stream;
70
71         stream.addr = src_addr_va;
72         stream.size = src_size;
73         stream.curr = 0;
74
75         while (notfound) {
76                 int i, length, byte;
77                 u32 word;
78
79                 byte = read_byte(&stream);
80                 if (byte == -1)
81                         return false;
82                 if (byte != 0xff)
83                         continue;
84                 do
85                         byte = read_byte(&stream);
86                 while (byte == 0xff);
87                 if (byte == -1)
88                         return false;
89                 if (byte == 0)
90                         continue;
91
92                 length = 0;
93                 switch (byte) {
94                 case SOF0:
95                         /* length */
96                         if (read_word_be(&stream, &word))
97                                 break;
98
99                         /* precision */
100                         if (read_byte(&stream) == -1)
101                                 break;
102
103                         if (read_word_be(&stream, &word))
104                                 break;
105                         param->pic_h = word;
106
107                         if (read_word_be(&stream, &word))
108                                 break;
109                         param->pic_w = word;
110
111                         param->comp_num = read_byte(&stream);
112                         if (param->comp_num != 1 && param->comp_num != 3)
113                                 break;
114
115                         for (i = 0; i < param->comp_num; i++) {
116                                 param->comp_id[i] = read_byte(&stream);
117                                 if (param->comp_id[i] == -1)
118                                         break;
119
120                                 /* sampling */
121                                 byte = read_byte(&stream);
122                                 if (byte == -1)
123                                         break;
124                                 param->sampling_w[i] = (byte >> 4) & 0x0F;
125                                 param->sampling_h[i] = byte & 0x0F;
126
127                                 param->qtbl_num[i] = read_byte(&stream);
128                                 if (param->qtbl_num[i] == -1)
129                                         break;
130                         }
131
132                         notfound = !(i == param->comp_num);
133                         break;
134                 case RST ... RST + 7:
135                 case SOI:
136                 case EOI:
137                 case TEM:
138                         break;
139                 default:
140                         if (read_word_be(&stream, &word))
141                                 break;
142                         length = (long)word - 2;
143                         read_skip(&stream, length);
144                         break;
145                 }
146         }
147
148         return !notfound;
149 }
150
151 bool mtk_jpeg_parse(struct mtk_jpeg_dec_param *param, u8 *src_addr_va,
152                     u32 src_size)
153 {
154         if (!mtk_jpeg_do_parse(param, src_addr_va, src_size))
155                 return false;
156         if (mtk_jpeg_dec_fill_param(param))
157                 return false;
158
159         return true;
160 }