Commit 6c96dbbc authored by Andrzej Pietrasiewicz's avatar Andrzej Pietrasiewicz Committed by Mauro Carvalho Chehab

[media] s5p-jpeg: add support for 5433

JPEG IP found in Exynos5433 is similar to what is in Exynos4, but
there are some subtle differences which this patch takes into account.

The most important difference is in what is processed by the JPEG IP and
what has to be provided to it. In case of 5433 the IP does not parse
Huffman and quantisation tables, so this has to be performed with the CPU
and the majority of the code in this patch does that.

A small but important difference is in what address is passed to the JPEG
IP. In case of 5433 it is the SOS (start of scan) position, which is
natural, because the headers must be parsed elsewhere.

There is also a difference in how the hardware is put to work in
device_run.

Data structures are extended as appropriate to accommodate the above
changes.
Signed-off-by: default avatarAndrzej Pietrasiewicz <andrzej.p@samsung.com>
Reviewed-by: default avatarJacek Anaszewski <j.anaszewski@samsung.com>
Signed-off-by: default avatarHans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@osg.samsung.com>
parent b95a24d6
......@@ -4,7 +4,8 @@ Required properties:
- compatible : should be one of:
"samsung,s5pv210-jpeg", "samsung,exynos4210-jpeg",
"samsung,exynos3250-jpeg", "samsung,exynos5420-jpeg";
"samsung,exynos3250-jpeg", "samsung,exynos5420-jpeg",
"samsung,exynos5433-jpeg";
- reg : address and length of the JPEG codec IP register set;
- interrupts : specifies the JPEG codec IP interrupt;
- clock-names : should contain:
......
This diff is collapsed.
......@@ -42,9 +42,12 @@
/* a selection of JPEG markers */
#define TEM 0x01
#define SOF0 0xc0
#define DHT 0xc4
#define RST 0xd0
#define SOI 0xd8
#define EOI 0xd9
#define SOS 0xda
#define DQT 0xdb
#define DHP 0xde
/* Flags that indicate a format can be used for capture/output */
......@@ -68,12 +71,15 @@
#define SJPEG_SUBSAMPLING_422 0x21
#define SJPEG_SUBSAMPLING_420 0x22
#define S5P_JPEG_MAX_MARKER 4
/* Version numbers */
enum sjpeg_version {
SJPEG_S5P,
SJPEG_EXYNOS3250,
SJPEG_EXYNOS4,
SJPEG_EXYNOS5420,
SJPEG_EXYNOS5433,
};
enum exynos4_jpeg_result {
......@@ -134,6 +140,7 @@ struct s5p_jpeg_variant {
unsigned int fmt_ver_flag;
unsigned int hw3250_compat:1;
unsigned int htbl_reinit:1;
unsigned int hw_ex4_compat:1;
struct v4l2_m2m_ops *m2m_ops;
irqreturn_t (*jpeg_irq)(int irq, void *priv);
const char *clk_names[JPEG_MAX_CLOCKS];
......@@ -162,17 +169,41 @@ struct s5p_jpeg_fmt {
u32 flags;
};
/**
* s5p_jpeg_marker - collection of markers from jpeg header
* @marker: markers' positions relative to the buffer beginning
* @len: markers' payload lengths (without length field)
* @n: number of markers in collection
*/
struct s5p_jpeg_marker {
u32 marker[S5P_JPEG_MAX_MARKER];
u32 len[S5P_JPEG_MAX_MARKER];
u32 n;
};
/**
* s5p_jpeg_q_data - parameters of one queue
* @fmt: driver-specific format of this queue
* @w: image width
* @h: image height
* @sos: SOS marker's position relative to the buffer beginning
* @dht: DHT markers' positions relative to the buffer beginning
* @dqt: DQT markers' positions relative to the buffer beginning
* @sof: SOF0 marker's postition relative to the buffer beginning
* @sof_len: SOF0 marker's payload length (without length field itself)
* @components: number of image components
* @size: image buffer size in bytes
*/
struct s5p_jpeg_q_data {
struct s5p_jpeg_fmt *fmt;
u32 w;
u32 h;
u32 sos;
struct s5p_jpeg_marker dht;
struct s5p_jpeg_marker dqt;
u32 sof;
u32 sof_len;
u32 components;
u32 size;
};
......
......@@ -45,9 +45,20 @@ void exynos4_jpeg_set_enc_dec_mode(void __iomem *base, unsigned int mode)
}
}
void exynos4_jpeg_set_img_fmt(void __iomem *base, unsigned int img_fmt)
void __exynos4_jpeg_set_img_fmt(void __iomem *base, unsigned int img_fmt,
unsigned int version)
{
unsigned int reg;
unsigned int exynos4_swap_chroma_cbcr;
unsigned int exynos4_swap_chroma_crcb;
if (version == SJPEG_EXYNOS4) {
exynos4_swap_chroma_cbcr = EXYNOS4_SWAP_CHROMA_CBCR;
exynos4_swap_chroma_crcb = EXYNOS4_SWAP_CHROMA_CRCB;
} else {
exynos4_swap_chroma_cbcr = EXYNOS5433_SWAP_CHROMA_CBCR;
exynos4_swap_chroma_crcb = EXYNOS5433_SWAP_CHROMA_CRCB;
}
reg = readl(base + EXYNOS4_IMG_FMT_REG) &
EXYNOS4_ENC_IN_FMT_MASK; /* clear except enc format */
......@@ -67,48 +78,48 @@ void exynos4_jpeg_set_img_fmt(void __iomem *base, unsigned int img_fmt)
case V4L2_PIX_FMT_NV24:
reg = reg | EXYNOS4_ENC_YUV_444_IMG |
EXYNOS4_YUV_444_IP_YUV_444_2P_IMG |
EXYNOS4_SWAP_CHROMA_CBCR;
exynos4_swap_chroma_cbcr;
break;
case V4L2_PIX_FMT_NV42:
reg = reg | EXYNOS4_ENC_YUV_444_IMG |
EXYNOS4_YUV_444_IP_YUV_444_2P_IMG |
EXYNOS4_SWAP_CHROMA_CRCB;
exynos4_swap_chroma_crcb;
break;
case V4L2_PIX_FMT_YUYV:
reg = reg | EXYNOS4_DEC_YUV_422_IMG |
EXYNOS4_YUV_422_IP_YUV_422_1P_IMG |
EXYNOS4_SWAP_CHROMA_CBCR;
exynos4_swap_chroma_cbcr;
break;
case V4L2_PIX_FMT_YVYU:
reg = reg | EXYNOS4_DEC_YUV_422_IMG |
EXYNOS4_YUV_422_IP_YUV_422_1P_IMG |
EXYNOS4_SWAP_CHROMA_CRCB;
exynos4_swap_chroma_crcb;
break;
case V4L2_PIX_FMT_NV16:
reg = reg | EXYNOS4_DEC_YUV_422_IMG |
EXYNOS4_YUV_422_IP_YUV_422_2P_IMG |
EXYNOS4_SWAP_CHROMA_CBCR;
exynos4_swap_chroma_cbcr;
break;
case V4L2_PIX_FMT_NV61:
reg = reg | EXYNOS4_DEC_YUV_422_IMG |
EXYNOS4_YUV_422_IP_YUV_422_2P_IMG |
EXYNOS4_SWAP_CHROMA_CRCB;
exynos4_swap_chroma_crcb;
break;
case V4L2_PIX_FMT_NV12:
reg = reg | EXYNOS4_DEC_YUV_420_IMG |
EXYNOS4_YUV_420_IP_YUV_420_2P_IMG |
EXYNOS4_SWAP_CHROMA_CBCR;
exynos4_swap_chroma_cbcr;
break;
case V4L2_PIX_FMT_NV21:
reg = reg | EXYNOS4_DEC_YUV_420_IMG |
EXYNOS4_YUV_420_IP_YUV_420_2P_IMG |
EXYNOS4_SWAP_CHROMA_CRCB;
exynos4_swap_chroma_crcb;
break;
case V4L2_PIX_FMT_YUV420:
reg = reg | EXYNOS4_DEC_YUV_420_IMG |
EXYNOS4_YUV_420_IP_YUV_420_3P_IMG |
EXYNOS4_SWAP_CHROMA_CBCR;
exynos4_swap_chroma_cbcr;
break;
default:
break;
......@@ -118,12 +129,14 @@ void exynos4_jpeg_set_img_fmt(void __iomem *base, unsigned int img_fmt)
writel(reg, base + EXYNOS4_IMG_FMT_REG);
}
void exynos4_jpeg_set_enc_out_fmt(void __iomem *base, unsigned int out_fmt)
void __exynos4_jpeg_set_enc_out_fmt(void __iomem *base, unsigned int out_fmt,
unsigned int version)
{
unsigned int reg;
reg = readl(base + EXYNOS4_IMG_FMT_REG) &
~EXYNOS4_ENC_FMT_MASK; /* clear enc format */
~(version == SJPEG_EXYNOS4 ? EXYNOS4_ENC_FMT_MASK :
EXYNOS5433_ENC_FMT_MASK); /* clear enc format */
switch (out_fmt) {
case V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY:
......@@ -149,9 +162,18 @@ void exynos4_jpeg_set_enc_out_fmt(void __iomem *base, unsigned int out_fmt)
writel(reg, base + EXYNOS4_IMG_FMT_REG);
}
void exynos4_jpeg_set_interrupt(void __iomem *base)
void exynos4_jpeg_set_interrupt(void __iomem *base, unsigned int version)
{
writel(EXYNOS4_INT_EN_ALL, base + EXYNOS4_INT_EN_REG);
unsigned int reg;
if (version == SJPEG_EXYNOS4) {
reg = readl(base + EXYNOS4_INT_EN_REG) & ~EXYNOS4_INT_EN_MASK;
writel(reg | EXYNOS4_INT_EN_ALL, base + EXYNOS4_INT_EN_REG);
} else {
reg = readl(base + EXYNOS4_INT_EN_REG) &
~EXYNOS5433_INT_EN_MASK;
writel(reg | EXYNOS5433_INT_EN_ALL, base + EXYNOS4_INT_EN_REG);
}
}
unsigned int exynos4_jpeg_get_int_status(void __iomem *base)
......@@ -234,6 +256,36 @@ void exynos4_jpeg_set_encode_tbl_select(void __iomem *base,
writel(reg, base + EXYNOS4_TBL_SEL_REG);
}
void exynos4_jpeg_set_dec_components(void __iomem *base, int n)
{
unsigned int reg;
reg = readl(base + EXYNOS4_TBL_SEL_REG);
reg |= EXYNOS4_NF(n);
writel(reg, base + EXYNOS4_TBL_SEL_REG);
}
void exynos4_jpeg_select_dec_q_tbl(void __iomem *base, char c, char x)
{
unsigned int reg;
reg = readl(base + EXYNOS4_TBL_SEL_REG);
reg |= EXYNOS4_Q_TBL_COMP(c, x);
writel(reg, base + EXYNOS4_TBL_SEL_REG);
}
void exynos4_jpeg_select_dec_h_tbl(void __iomem *base, char c, char x)
{
unsigned int reg;
reg = readl(base + EXYNOS4_TBL_SEL_REG);
reg |= EXYNOS4_HUFF_TBL_COMP(c, x);
writel(reg, base + EXYNOS4_TBL_SEL_REG);
}
void exynos4_jpeg_set_encode_hoff_cnt(void __iomem *base, unsigned int fmt)
{
if (fmt == V4L2_PIX_FMT_GREY)
......
......@@ -15,10 +15,12 @@
void exynos4_jpeg_sw_reset(void __iomem *base);
void exynos4_jpeg_set_enc_dec_mode(void __iomem *base, unsigned int mode);
void exynos4_jpeg_set_img_fmt(void __iomem *base, unsigned int img_fmt);
void exynos4_jpeg_set_enc_out_fmt(void __iomem *base, unsigned int out_fmt);
void __exynos4_jpeg_set_img_fmt(void __iomem *base, unsigned int img_fmt,
unsigned int version);
void __exynos4_jpeg_set_enc_out_fmt(void __iomem *base, unsigned int out_fmt,
unsigned int version);
void exynos4_jpeg_set_enc_tbl(void __iomem *base);
void exynos4_jpeg_set_interrupt(void __iomem *base);
void exynos4_jpeg_set_interrupt(void __iomem *base, unsigned int version);
unsigned int exynos4_jpeg_get_int_status(void __iomem *base);
void exynos4_jpeg_set_huf_table_enable(void __iomem *base, int value);
void exynos4_jpeg_set_sys_int_enable(void __iomem *base, int value);
......@@ -30,6 +32,9 @@ void exynos4_jpeg_set_frame_buf_address(void __iomem *base,
struct s5p_jpeg_addr *jpeg_addr);
void exynos4_jpeg_set_encode_tbl_select(void __iomem *base,
enum exynos4_jpeg_img_quality_level level);
void exynos4_jpeg_set_dec_components(void __iomem *base, int n);
void exynos4_jpeg_select_dec_q_tbl(void __iomem *base, char c, char x);
void exynos4_jpeg_select_dec_h_tbl(void __iomem *base, char c, char x);
void exynos4_jpeg_set_encode_hoff_cnt(void __iomem *base, unsigned int fmt);
void exynos4_jpeg_set_dec_bitstream_size(void __iomem *base, unsigned int size);
unsigned int exynos4_jpeg_get_stream_size(void __iomem *base);
......
......@@ -231,12 +231,14 @@
/* JPEG INT Register bit */
#define EXYNOS4_INT_EN_MASK (0x1f << 0)
#define EXYNOS5433_INT_EN_MASK (0x1ff << 0)
#define EXYNOS4_PROT_ERR_INT_EN (1 << 0)
#define EXYNOS4_IMG_COMPLETION_INT_EN (1 << 1)
#define EXYNOS4_DEC_INVALID_FORMAT_EN (1 << 2)
#define EXYNOS4_MULTI_SCAN_ERROR_EN (1 << 3)
#define EXYNOS4_FRAME_ERR_EN (1 << 4)
#define EXYNOS4_INT_EN_ALL (0x1f << 0)
#define EXYNOS5433_INT_EN_ALL (0x1b6 << 0)
#define EXYNOS4_MOD_REG_PROC_ENC (0 << 3)
#define EXYNOS4_MOD_REG_PROC_DEC (1 << 3)
......@@ -296,6 +298,8 @@
#define EXYNOS4_ENC_FMT_SHIFT 24
#define EXYNOS4_ENC_FMT_MASK (3 << EXYNOS4_ENC_FMT_SHIFT)
#define EXYNOS5433_ENC_FMT_MASK (7 << EXYNOS4_ENC_FMT_SHIFT)
#define EXYNOS4_ENC_FMT_GRAY (0 << EXYNOS4_ENC_FMT_SHIFT)
#define EXYNOS4_ENC_FMT_YUV_444 (1 << EXYNOS4_ENC_FMT_SHIFT)
#define EXYNOS4_ENC_FMT_YUV_422 (2 << EXYNOS4_ENC_FMT_SHIFT)
......@@ -305,6 +309,8 @@
#define EXYNOS4_SWAP_CHROMA_CRCB (1 << 26)
#define EXYNOS4_SWAP_CHROMA_CBCR (0 << 26)
#define EXYNOS5433_SWAP_CHROMA_CRCB (1 << 27)
#define EXYNOS5433_SWAP_CHROMA_CBCR (0 << 27)
/* JPEG HUFF count Register bit */
#define EXYNOS4_HUFF_COUNT_MASK 0xffff
......@@ -316,35 +322,56 @@
#define EXYNOS4_DECODED_IMG_FMT_MASK 0x3
/* JPEG TBL SEL Register bit */
#define EXYNOS4_Q_TBL_COMP1_0 (0 << 0)
#define EXYNOS4_Q_TBL_COMP1_1 (1 << 0)
#define EXYNOS4_Q_TBL_COMP1_2 (2 << 0)
#define EXYNOS4_Q_TBL_COMP1_3 (3 << 0)
#define EXYNOS4_Q_TBL_COMP2_0 (0 << 2)
#define EXYNOS4_Q_TBL_COMP2_1 (1 << 2)
#define EXYNOS4_Q_TBL_COMP2_2 (2 << 2)
#define EXYNOS4_Q_TBL_COMP2_3 (3 << 2)
#define EXYNOS4_Q_TBL_COMP3_0 (0 << 4)
#define EXYNOS4_Q_TBL_COMP3_1 (1 << 4)
#define EXYNOS4_Q_TBL_COMP3_2 (2 << 4)
#define EXYNOS4_Q_TBL_COMP3_3 (3 << 4)
#define EXYNOS4_HUFF_TBL_COMP1_AC_0_DC_0 (0 << 6)
#define EXYNOS4_HUFF_TBL_COMP1_AC_0_DC_1 (1 << 6)
#define EXYNOS4_HUFF_TBL_COMP1_AC_1_DC_0 (2 << 6)
#define EXYNOS4_HUFF_TBL_COMP1_AC_1_DC_1 (3 << 6)
#define EXYNOS4_HUFF_TBL_COMP2_AC_0_DC_0 (0 << 8)
#define EXYNOS4_HUFF_TBL_COMP2_AC_0_DC_1 (1 << 8)
#define EXYNOS4_HUFF_TBL_COMP2_AC_1_DC_0 (2 << 8)
#define EXYNOS4_HUFF_TBL_COMP2_AC_1_DC_1 (3 << 8)
#define EXYNOS4_HUFF_TBL_COMP3_AC_0_DC_0 (0 << 10)
#define EXYNOS4_HUFF_TBL_COMP3_AC_0_DC_1 (1 << 10)
#define EXYNOS4_HUFF_TBL_COMP3_AC_1_DC_0 (2 << 10)
#define EXYNOS4_HUFF_TBL_COMP3_AC_1_DC_1 (3 << 10)
#define EXYNOS4_Q_TBL_COMP(c, n) ((n) << (((c) - 1) << 1))
#define EXYNOS4_Q_TBL_COMP1_0 EXYNOS4_Q_TBL_COMP(1, 0)
#define EXYNOS4_Q_TBL_COMP1_1 EXYNOS4_Q_TBL_COMP(1, 1)
#define EXYNOS4_Q_TBL_COMP1_2 EXYNOS4_Q_TBL_COMP(1, 2)
#define EXYNOS4_Q_TBL_COMP1_3 EXYNOS4_Q_TBL_COMP(1, 3)
#define EXYNOS4_Q_TBL_COMP2_0 EXYNOS4_Q_TBL_COMP(2, 0)
#define EXYNOS4_Q_TBL_COMP2_1 EXYNOS4_Q_TBL_COMP(2, 1)
#define EXYNOS4_Q_TBL_COMP2_2 EXYNOS4_Q_TBL_COMP(2, 2)
#define EXYNOS4_Q_TBL_COMP2_3 EXYNOS4_Q_TBL_COMP(2, 3)
#define EXYNOS4_Q_TBL_COMP3_0 EXYNOS4_Q_TBL_COMP(3, 0)
#define EXYNOS4_Q_TBL_COMP3_1 EXYNOS4_Q_TBL_COMP(3, 1)
#define EXYNOS4_Q_TBL_COMP3_2 EXYNOS4_Q_TBL_COMP(3, 2)
#define EXYNOS4_Q_TBL_COMP3_3 EXYNOS4_Q_TBL_COMP(3, 3)
#define EXYNOS4_HUFF_TBL_COMP(c, n) ((n) << ((((c) - 1) << 1) + 6))
#define EXYNOS4_HUFF_TBL_COMP1_AC_0_DC_0 \
EXYNOS4_HUFF_TBL_COMP(1, 0)
#define EXYNOS4_HUFF_TBL_COMP1_AC_0_DC_1 \
EXYNOS4_HUFF_TBL_COMP(1, 1)
#define EXYNOS4_HUFF_TBL_COMP1_AC_1_DC_0 \
EXYNOS4_HUFF_TBL_COMP(1, 2)
#define EXYNOS4_HUFF_TBL_COMP1_AC_1_DC_1 \
EXYNOS4_HUFF_TBL_COMP(1, 3)
#define EXYNOS4_HUFF_TBL_COMP2_AC_0_DC_0 \
EXYNOS4_HUFF_TBL_COMP(2, 0)
#define EXYNOS4_HUFF_TBL_COMP2_AC_0_DC_1 \
EXYNOS4_HUFF_TBL_COMP(2, 1)
#define EXYNOS4_HUFF_TBL_COMP2_AC_1_DC_0 \
EXYNOS4_HUFF_TBL_COMP(2, 2)
#define EXYNOS4_HUFF_TBL_COMP2_AC_1_DC_1 \
EXYNOS4_HUFF_TBL_COMP(2, 3)
#define EXYNOS4_HUFF_TBL_COMP3_AC_0_DC_0 \
EXYNOS4_HUFF_TBL_COMP(3, 0)
#define EXYNOS4_HUFF_TBL_COMP3_AC_0_DC_1 \
EXYNOS4_HUFF_TBL_COMP(3, 1)
#define EXYNOS4_HUFF_TBL_COMP3_AC_1_DC_0 \
EXYNOS4_HUFF_TBL_COMP(3, 2)
#define EXYNOS4_HUFF_TBL_COMP3_AC_1_DC_1 \
EXYNOS4_HUFF_TBL_COMP(3, 3)
#define EXYNOS4_NF_SHIFT 16
#define EXYNOS4_NF_MASK 0xff
#define EXYNOS4_NF(x) \
(((x) << EXYNOS4_NF_SHIFT) & EXYNOS4_NF_MASK)
/* JPEG quantizer table register */
#define EXYNOS4_QTBL_CONTENT(n) (0x100 + (n) * 0x40)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment