]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - drivers/media/platform/mtk-jpeg/mtk_jpeg_parse.c
Merge tag 'v4.11-rc1' into patchwork
[mirror_ubuntu-artful-kernel.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 }