forked from Minki/linux
b2f0d2724b
Add v4l2 driver for Mediatek JPEG Decoder Signed-off-by: Rick Chang <rick.chang@mediatek.com> Signed-off-by: Minghsiu Tsai <minghsiu.tsai@mediatek.com> Reviewed-by: Ricky Liang <jcliang@chromium.org> Tested-by: Ricky Liang <jcliang@chromium.org> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
161 lines
3.1 KiB
C
161 lines
3.1 KiB
C
/*
|
|
* Copyright (c) 2016 MediaTek Inc.
|
|
* Author: Ming Hsiu Tsai <minghsiu.tsai@mediatek.com>
|
|
* Rick Chang <rick.chang@mediatek.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*/
|
|
|
|
#include <linux/kernel.h>
|
|
#include <linux/videodev2.h>
|
|
|
|
#include "mtk_jpeg_parse.h"
|
|
|
|
#define TEM 0x01
|
|
#define SOF0 0xc0
|
|
#define RST 0xd0
|
|
#define SOI 0xd8
|
|
#define EOI 0xd9
|
|
|
|
struct mtk_jpeg_stream {
|
|
u8 *addr;
|
|
u32 size;
|
|
u32 curr;
|
|
};
|
|
|
|
static int read_byte(struct mtk_jpeg_stream *stream)
|
|
{
|
|
if (stream->curr >= stream->size)
|
|
return -1;
|
|
return stream->addr[stream->curr++];
|
|
}
|
|
|
|
static int read_word_be(struct mtk_jpeg_stream *stream, u32 *word)
|
|
{
|
|
u32 temp;
|
|
int byte;
|
|
|
|
byte = read_byte(stream);
|
|
if (byte == -1)
|
|
return -1;
|
|
temp = byte << 8;
|
|
byte = read_byte(stream);
|
|
if (byte == -1)
|
|
return -1;
|
|
*word = (u32)byte | temp;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void read_skip(struct mtk_jpeg_stream *stream, long len)
|
|
{
|
|
if (len <= 0)
|
|
return;
|
|
while (len--)
|
|
read_byte(stream);
|
|
}
|
|
|
|
static bool mtk_jpeg_do_parse(struct mtk_jpeg_dec_param *param, u8 *src_addr_va,
|
|
u32 src_size)
|
|
{
|
|
bool notfound = true;
|
|
struct mtk_jpeg_stream stream;
|
|
|
|
stream.addr = src_addr_va;
|
|
stream.size = src_size;
|
|
stream.curr = 0;
|
|
|
|
while (notfound) {
|
|
int i, length, byte;
|
|
u32 word;
|
|
|
|
byte = read_byte(&stream);
|
|
if (byte == -1)
|
|
return false;
|
|
if (byte != 0xff)
|
|
continue;
|
|
do
|
|
byte = read_byte(&stream);
|
|
while (byte == 0xff);
|
|
if (byte == -1)
|
|
return false;
|
|
if (byte == 0)
|
|
continue;
|
|
|
|
length = 0;
|
|
switch (byte) {
|
|
case SOF0:
|
|
/* length */
|
|
if (read_word_be(&stream, &word))
|
|
break;
|
|
|
|
/* precision */
|
|
if (read_byte(&stream) == -1)
|
|
break;
|
|
|
|
if (read_word_be(&stream, &word))
|
|
break;
|
|
param->pic_h = word;
|
|
|
|
if (read_word_be(&stream, &word))
|
|
break;
|
|
param->pic_w = word;
|
|
|
|
param->comp_num = read_byte(&stream);
|
|
if (param->comp_num != 1 && param->comp_num != 3)
|
|
break;
|
|
|
|
for (i = 0; i < param->comp_num; i++) {
|
|
param->comp_id[i] = read_byte(&stream);
|
|
if (param->comp_id[i] == -1)
|
|
break;
|
|
|
|
/* sampling */
|
|
byte = read_byte(&stream);
|
|
if (byte == -1)
|
|
break;
|
|
param->sampling_w[i] = (byte >> 4) & 0x0F;
|
|
param->sampling_h[i] = byte & 0x0F;
|
|
|
|
param->qtbl_num[i] = read_byte(&stream);
|
|
if (param->qtbl_num[i] == -1)
|
|
break;
|
|
}
|
|
|
|
notfound = !(i == param->comp_num);
|
|
break;
|
|
case RST ... RST + 7:
|
|
case SOI:
|
|
case EOI:
|
|
case TEM:
|
|
break;
|
|
default:
|
|
if (read_word_be(&stream, &word))
|
|
break;
|
|
length = (long)word - 2;
|
|
read_skip(&stream, length);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return !notfound;
|
|
}
|
|
|
|
bool mtk_jpeg_parse(struct mtk_jpeg_dec_param *param, u8 *src_addr_va,
|
|
u32 src_size)
|
|
{
|
|
if (!mtk_jpeg_do_parse(param, src_addr_va, src_size))
|
|
return false;
|
|
if (mtk_jpeg_dec_fill_param(param))
|
|
return false;
|
|
|
|
return true;
|
|
}
|