* [PATCH] media: jpeg: add driver for a version 2.x of jpeg H/W
@ 2012-03-01 23:46 송영목
2012-03-03 12:37 ` Sylwester Nawrocki
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: 송영목 @ 2012-03-01 23:46 UTC (permalink / raw)
To: linux-media; +Cc: mchehab, andrzej.p
This patch add a driver for a version 2.x of jpeg H/W
in ths Samsung Exynos5 Soc.
A jpeg H/W version of Exynos4 SoC is 3.0
1. Encoding
- input format : V4L2_PIX_FMT_RGB565X and V4L2_PIX_FMT_YUYV
2. Decoding
- output format : V4L2_PIX_FMT_YUYV and V4L2_PIX_FMT_YUV420
Signed-off-by: youngmok song <ym.song@samsung.com>
---
drivers/media/video/Kconfig | 17 +
drivers/media/video/s5p-jpeg/Makefile | 5 +-
drivers/media/video/s5p-jpeg/jpeg-core.c | 303 +-------------------
drivers/media/video/s5p-jpeg/jpeg-hw-common.h | 34 +++
drivers/media/video/s5p-jpeg/jpeg-hw-v2x.h | 387 +++++++++++++++++++++++++
drivers/media/video/s5p-jpeg/jpeg-regs-v2x.h | 150 ++++++++++
drivers/media/video/s5p-jpeg/jpeg-v2x.c | 129 ++++++++
drivers/media/video/s5p-jpeg/jpeg-v3.c | 340 ++++++++++++++++++++++
8 files changed, 1066 insertions(+), 299 deletions(-)
create mode 100644 drivers/media/video/s5p-jpeg/jpeg-hw-common.h
create mode 100644 drivers/media/video/s5p-jpeg/jpeg-hw-v2x.h
create mode 100644 drivers/media/video/s5p-jpeg/jpeg-regs-v2x.h
create mode 100644 drivers/media/video/s5p-jpeg/jpeg-v2x.c
create mode 100644 drivers/media/video/s5p-jpeg/jpeg-v3.c
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index 9adada0..551f925 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -1167,6 +1167,23 @@ config VIDEO_SAMSUNG_S5P_JPEG
select V4L2_MEM2MEM_DEV
---help---
This is a v4l2 driver for Samsung S5P and EXYNOS4 JPEG codec
+choice
+ prompt "JPEG V4L2 Driver"
+ default S5P_JPEG_V3
+ depends on VIDEO_SAMSUNG_S5P_JPEG
+ ---help---
+ Select version of MFC driver
+
+config S5P_JPEG_V3
+ bool "JPEG 3.x"
+ ---help---
+ Use JPEG 3.x V4L2 Driver
+
+config S5P_JPEG_V2
+ bool "JPEG 2.x"
+ ---help---
+ Use JPEG 2.x V4L2 Driver
+endchoice
config VIDEO_SAMSUNG_S5P_MFC
tristate "Samsung S5P MFC 5.1 Video Codec"
diff --git a/drivers/media/video/s5p-jpeg/Makefile b/drivers/media/video/s5p-jpeg/Makefile
index ddc2900..446d07f 100644
--- a/drivers/media/video/s5p-jpeg/Makefile
+++ b/drivers/media/video/s5p-jpeg/Makefile
@@ -1,2 +1,5 @@
-s5p-jpeg-objs := jpeg-core.o
obj-$(CONFIG_VIDEO_SAMSUNG_S5P_JPEG) := s5p-jpeg.o
+
+s5p-jpeg-objs := jpeg-core.o
+obj-$(CONFIG_S5P_JPEG_V3) += jpeg-v3.o
+obj-$(CONFIG_S5P_JPEG_V2) += jpeg-v2x.o
diff --git a/drivers/media/video/s5p-jpeg/jpeg-core.c b/drivers/media/video/s5p-jpeg/jpeg-core.c
index 1105a87..cf917cd 100644
--- a/drivers/media/video/s5p-jpeg/jpeg-core.c
+++ b/drivers/media/video/s5p-jpeg/jpeg-core.c
@@ -28,7 +28,7 @@
#include <media/videobuf2-dma-contig.h>
#include "jpeg-core.h"
-#include "jpeg-hw.h"
+#include "jpeg-hw-common.h"
static struct s5p_jpeg_fmt formats_enc[] = {
{
@@ -83,182 +83,6 @@ static struct s5p_jpeg_fmt formats_dec[] = {
};
#define NUM_FORMATS_DEC ARRAY_SIZE(formats_dec)
-static const unsigned char qtbl_luminance[4][64] = {
- {/* level 1 - high quality */
- 8, 6, 6, 8, 12, 14, 16, 17,
- 6, 6, 6, 8, 10, 13, 12, 15,
- 6, 6, 7, 8, 13, 14, 18, 24,
- 8, 8, 8, 14, 13, 19, 24, 35,
- 12, 10, 13, 13, 20, 26, 34, 39,
- 14, 13, 14, 19, 26, 34, 39, 39,
- 16, 12, 18, 24, 34, 39, 39, 39,
- 17, 15, 24, 35, 39, 39, 39, 39
- },
- {/* level 2 */
- 12, 8, 8, 12, 17, 21, 24, 23,
- 8, 9, 9, 11, 15, 19, 18, 23,
- 8, 9, 10, 12, 19, 20, 27, 36,
- 12, 11, 12, 21, 20, 28, 36, 53,
- 17, 15, 19, 20, 30, 39, 51, 59,
- 21, 19, 20, 28, 39, 51, 59, 59,
- 24, 18, 27, 36, 51, 59, 59, 59,
- 23, 23, 36, 53, 59, 59, 59, 59
- },
- {/* level 3 */
- 16, 11, 11, 16, 23, 27, 31, 30,
- 11, 12, 12, 15, 20, 23, 23, 30,
- 11, 12, 13, 16, 23, 26, 35, 47,
- 16, 15, 16, 23, 26, 37, 47, 64,
- 23, 20, 23, 26, 39, 51, 64, 64,
- 27, 23, 26, 37, 51, 64, 64, 64,
- 31, 23, 35, 47, 64, 64, 64, 64,
- 30, 30, 47, 64, 64, 64, 64, 64
- },
- {/*level 4 - low quality */
- 20, 16, 25, 39, 50, 46, 62, 68,
- 16, 18, 23, 38, 38, 53, 65, 68,
- 25, 23, 31, 38, 53, 65, 68, 68,
- 39, 38, 38, 53, 65, 68, 68, 68,
- 50, 38, 53, 65, 68, 68, 68, 68,
- 46, 53, 65, 68, 68, 68, 68, 68,
- 62, 65, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 68
- }
-};
-
-static const unsigned char qtbl_chrominance[4][64] = {
- {/* level 1 - high quality */
- 9, 8, 9, 11, 14, 17, 19, 24,
- 8, 10, 9, 11, 14, 13, 17, 22,
- 9, 9, 13, 14, 13, 15, 23, 26,
- 11, 11, 14, 14, 15, 20, 26, 33,
- 14, 14, 13, 15, 20, 24, 33, 39,
- 17, 13, 15, 20, 24, 32, 39, 39,
- 19, 17, 23, 26, 33, 39, 39, 39,
- 24, 22, 26, 33, 39, 39, 39, 39
- },
- {/* level 2 */
- 13, 11, 13, 16, 20, 20, 29, 37,
- 11, 14, 14, 14, 16, 20, 26, 32,
- 13, 14, 15, 17, 20, 23, 35, 40,
- 16, 14, 17, 21, 23, 30, 40, 50,
- 20, 16, 20, 23, 30, 37, 50, 59,
- 20, 20, 23, 30, 37, 48, 59, 59,
- 29, 26, 35, 40, 50, 59, 59, 59,
- 37, 32, 40, 50, 59, 59, 59, 59
- },
- {/* level 3 */
- 17, 15, 17, 21, 20, 26, 38, 48,
- 15, 19, 18, 17, 20, 26, 35, 43,
- 17, 18, 20, 22, 26, 30, 46, 53,
- 21, 17, 22, 28, 30, 39, 53, 64,
- 20, 20, 26, 30, 39, 48, 64, 64,
- 26, 26, 30, 39, 48, 63, 64, 64,
- 38, 35, 46, 53, 64, 64, 64, 64,
- 48, 43, 53, 64, 64, 64, 64, 64
- },
- {/*level 4 - low quality */
- 21, 25, 32, 38, 54, 68, 68, 68,
- 25, 28, 24, 38, 54, 68, 68, 68,
- 32, 24, 32, 43, 66, 68, 68, 68,
- 38, 38, 43, 53, 68, 68, 68, 68,
- 54, 54, 66, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 68
- }
-};
-
-static const unsigned char hdctbl0[16] = {
- 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0
-};
-
-static const unsigned char hdctblg0[12] = {
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb
-};
-static const unsigned char hactbl0[16] = {
- 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d
-};
-static const unsigned char hactblg0[162] = {
- 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
- 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
- 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
- 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
- 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
- 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
- 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
- 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
- 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
- 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
- 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
- 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
- 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
- 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
- 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
- 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
- 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
- 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
- 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
- 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
- 0xf9, 0xfa
-};
-
-static inline void jpeg_set_qtbl(void __iomem *regs, const unsigned char *qtbl,
- unsigned long tab, int len)
-{
- int i;
-
- for (i = 0; i < len; i++)
- writel((unsigned int)qtbl[i], regs + tab + (i * 0x04));
-}
-
-static inline void jpeg_set_qtbl_lum(void __iomem *regs, int quality)
-{
- /* this driver fills quantisation table 0 with data for luma */
- jpeg_set_qtbl(regs, qtbl_luminance[quality], S5P_JPG_QTBL_CONTENT(0),
- ARRAY_SIZE(qtbl_luminance[quality]));
-}
-
-static inline void jpeg_set_qtbl_chr(void __iomem *regs, int quality)
-{
- /* this driver fills quantisation table 1 with data for chroma */
- jpeg_set_qtbl(regs, qtbl_chrominance[quality], S5P_JPG_QTBL_CONTENT(1),
- ARRAY_SIZE(qtbl_chrominance[quality]));
-}
-
-static inline void jpeg_set_htbl(void __iomem *regs, const unsigned char *htbl,
- unsigned long tab, int len)
-{
- int i;
-
- for (i = 0; i < len; i++)
- writel((unsigned int)htbl[i], regs + tab + (i * 0x04));
-}
-
-static inline void jpeg_set_hdctbl(void __iomem *regs)
-{
- /* this driver fills table 0 for this component */
- jpeg_set_htbl(regs, hdctbl0, S5P_JPG_HDCTBL(0), ARRAY_SIZE(hdctbl0));
-}
-
-static inline void jpeg_set_hdctblg(void __iomem *regs)
-{
- /* this driver fills table 0 for this component */
- jpeg_set_htbl(regs, hdctblg0, S5P_JPG_HDCTBLG(0), ARRAY_SIZE(hdctblg0));
-}
-
-static inline void jpeg_set_hactbl(void __iomem *regs)
-{
- /* this driver fills table 0 for this component */
- jpeg_set_htbl(regs, hactbl0, S5P_JPG_HACTBL(0), ARRAY_SIZE(hactbl0));
-}
-
-static inline void jpeg_set_hactblg(void __iomem *regs)
-{
- /* this driver fills table 0 for this component */
- jpeg_set_htbl(regs, hactblg0, S5P_JPG_HACTBLG(0), ARRAY_SIZE(hactblg0));
-}
-
/*
* ============================================================================
* Device file operations
@@ -890,78 +714,7 @@ static const struct v4l2_ioctl_ops s5p_jpeg_ioctl_ops = {
static void s5p_jpeg_device_run(void *priv)
{
- struct s5p_jpeg_ctx *ctx = priv;
- struct s5p_jpeg *jpeg = ctx->jpeg;
- struct vb2_buffer *src_buf, *dst_buf;
- unsigned long src_addr, dst_addr;
-
- src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
- dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
- src_addr = vb2_dma_contig_plane_dma_addr(src_buf, 0);
- dst_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0);
-
- jpeg_reset(jpeg->regs);
- jpeg_poweron(jpeg->regs);
- jpeg_proc_mode(jpeg->regs, ctx->mode);
- if (ctx->mode == S5P_JPEG_ENCODE) {
- if (ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB565)
- jpeg_input_raw_mode(jpeg->regs, S5P_JPEG_RAW_IN_565);
- else
- jpeg_input_raw_mode(jpeg->regs, S5P_JPEG_RAW_IN_422);
- if (ctx->cap_q.fmt->fourcc == V4L2_PIX_FMT_YUYV)
- jpeg_subsampling_mode(jpeg->regs,
- S5P_JPEG_SUBSAMPLING_422);
- else
- jpeg_subsampling_mode(jpeg->regs,
- S5P_JPEG_SUBSAMPLING_420);
- jpeg_dri(jpeg->regs, 0);
- jpeg_x(jpeg->regs, ctx->out_q.w);
- jpeg_y(jpeg->regs, ctx->out_q.h);
- jpeg_imgadr(jpeg->regs, src_addr);
- jpeg_jpgadr(jpeg->regs, dst_addr);
-
- /* ultimately comes from sizeimage from userspace */
- jpeg_enc_stream_int(jpeg->regs, ctx->cap_q.size);
-
- /* JPEG RGB to YCbCr conversion matrix */
- jpeg_coef(jpeg->regs, 1, 1, S5P_JPEG_COEF11);
- jpeg_coef(jpeg->regs, 1, 2, S5P_JPEG_COEF12);
- jpeg_coef(jpeg->regs, 1, 3, S5P_JPEG_COEF13);
- jpeg_coef(jpeg->regs, 2, 1, S5P_JPEG_COEF21);
- jpeg_coef(jpeg->regs, 2, 2, S5P_JPEG_COEF22);
- jpeg_coef(jpeg->regs, 2, 3, S5P_JPEG_COEF23);
- jpeg_coef(jpeg->regs, 3, 1, S5P_JPEG_COEF31);
- jpeg_coef(jpeg->regs, 3, 2, S5P_JPEG_COEF32);
- jpeg_coef(jpeg->regs, 3, 3, S5P_JPEG_COEF33);
-
- /*
- * JPEG IP allows storing 4 quantization tables
- * We fill table 0 for luma and table 1 for chroma
- */
- jpeg_set_qtbl_lum(jpeg->regs, ctx->compr_quality);
- jpeg_set_qtbl_chr(jpeg->regs, ctx->compr_quality);
- /* use table 0 for Y */
- jpeg_qtbl(jpeg->regs, 1, 0);
- /* use table 1 for Cb and Cr*/
- jpeg_qtbl(jpeg->regs, 2, 1);
- jpeg_qtbl(jpeg->regs, 3, 1);
-
- /* Y, Cb, Cr use Huffman table 0 */
- jpeg_htbl_ac(jpeg->regs, 1);
- jpeg_htbl_dc(jpeg->regs, 1);
- jpeg_htbl_ac(jpeg->regs, 2);
- jpeg_htbl_dc(jpeg->regs, 2);
- jpeg_htbl_ac(jpeg->regs, 3);
- jpeg_htbl_dc(jpeg->regs, 3);
- } else {
- jpeg_rst_int_enable(jpeg->regs, true);
- jpeg_data_num_int_enable(jpeg->regs, true);
- jpeg_final_mcu_num_int_enable(jpeg->regs, true);
- jpeg_outform_raw(jpeg->regs, S5P_JPEG_RAW_OUT_422);
- jpeg_jpgadr(jpeg->regs, src_addr);
- jpeg_imgadr(jpeg->regs, dst_addr);
- }
- jpeg_start(jpeg->regs);
+ s5p_jpeg_execute(priv);
}
static int s5p_jpeg_job_ready(void *priv)
@@ -1153,46 +906,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq,
static irqreturn_t s5p_jpeg_irq(int irq, void *dev_id)
{
- struct s5p_jpeg *jpeg = dev_id;
- struct s5p_jpeg_ctx *curr_ctx;
- struct vb2_buffer *src_buf, *dst_buf;
- unsigned long payload_size = 0;
- enum vb2_buffer_state state = VB2_BUF_STATE_DONE;
- bool enc_jpeg_too_large = false;
- bool timer_elapsed = false;
- bool op_completed = false;
-
- curr_ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev);
-
- src_buf = v4l2_m2m_src_buf_remove(curr_ctx->m2m_ctx);
- dst_buf = v4l2_m2m_dst_buf_remove(curr_ctx->m2m_ctx);
-
- if (curr_ctx->mode == S5P_JPEG_ENCODE)
- enc_jpeg_too_large = jpeg_enc_stream_stat(jpeg->regs);
- timer_elapsed = jpeg_timer_stat(jpeg->regs);
- op_completed = jpeg_result_stat_ok(jpeg->regs);
- if (curr_ctx->mode == S5P_JPEG_DECODE)
- op_completed = op_completed && jpeg_stream_stat_ok(jpeg->regs);
-
- if (enc_jpeg_too_large) {
- state = VB2_BUF_STATE_ERROR;
- jpeg_clear_enc_stream_stat(jpeg->regs);
- } else if (timer_elapsed) {
- state = VB2_BUF_STATE_ERROR;
- jpeg_clear_timer_stat(jpeg->regs);
- } else if (!op_completed) {
- state = VB2_BUF_STATE_ERROR;
- } else {
- payload_size = jpeg_compressed_size(jpeg->regs);
- }
-
- v4l2_m2m_buf_done(src_buf, state);
- if (curr_ctx->mode == S5P_JPEG_ENCODE)
- vb2_set_plane_payload(dst_buf, 0, payload_size);
- v4l2_m2m_buf_done(dst_buf, state);
- v4l2_m2m_job_finish(jpeg->m2m_dev, curr_ctx->m2m_ctx);
-
- jpeg_clear_int(jpeg->regs);
+ s5p_jpeg_irq_execute(dev_id);
return IRQ_HANDLED;
}
@@ -1425,15 +1139,8 @@ static int s5p_jpeg_runtime_suspend(struct device *dev)
static int s5p_jpeg_runtime_resume(struct device *dev)
{
- struct s5p_jpeg *jpeg = dev_get_drvdata(dev);
- /*
- * JPEG IP allows storing two Huffman tables for each component
- * We fill table 0 for each component
- */
- jpeg_set_hdctbl(jpeg->regs);
- jpeg_set_hdctblg(jpeg->regs);
- jpeg_set_hactbl(jpeg->regs);
- jpeg_set_hactblg(jpeg->regs);
+ s5p_jpeg_runtime_resume_execute(dev);
+
return 0;
}
diff --git a/drivers/media/video/s5p-jpeg/jpeg-hw-common.h b/drivers/media/video/s5p-jpeg/jpeg-hw-common.h
new file mode 100644
index 0000000..c649598
--- /dev/null
+++ b/drivers/media/video/s5p-jpeg/jpeg-hw-common.h
@@ -0,0 +1,34 @@
+/* linux/drivers/media/video/s5p-jpeg/jpeg-hw.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.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.
+ */
+#ifndef JPEG_HW_COMMON_H_
+#define JPEG_HW_COMMON_H_
+
+#include <linux/io.h>
+#include <linux/delay.h>
+
+void s5p_jpeg_execute(void *priv);
+void s5p_jpeg_irq_execute(void *dev_id);
+void s5p_jpeg_runtime_resume_execute(struct device *dev);
+
+#define S5P_JPEG_MIN_WIDTH 32
+#define S5P_JPEG_MIN_HEIGHT 32
+#define S5P_JPEG_MAX_WIDTH 8192
+#define S5P_JPEG_MAX_HEIGHT 8192
+#define S5P_JPEG_ENCODE 0
+#define S5P_JPEG_DECODE 1
+#define S5P_JPEG_RAW_IN_565 0
+#define S5P_JPEG_RAW_IN_422 1
+#define S5P_JPEG_SUBSAMPLING_422 0
+#define S5P_JPEG_SUBSAMPLING_420 1
+#define S5P_JPEG_RAW_OUT_422 0
+#define S5P_JPEG_RAW_OUT_420 1
+#endif /* JPEG_HW_COMMON_H_ */
diff --git a/drivers/media/video/s5p-jpeg/jpeg-hw-v2x.h b/drivers/media/video/s5p-jpeg/jpeg-hw-v2x.h
new file mode 100644
index 0000000..90bd60b
--- /dev/null
+++ b/drivers/media/video/s5p-jpeg/jpeg-hw-v2x.h
@@ -0,0 +1,387 @@
+/* linux/drivers/media/video/s5p-jpeg/jpeg-hw-v2x.h
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ * http://www.samsung.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.
+ */
+#ifndef JPEG_HW_V2X_H_
+#define JPEG_HW_V2X_H_
+
+#include <linux/io.h>
+#include <linux/delay.h>
+
+#include "jpeg-regs-v2x.h"
+
+#define S5P_JPEG_MIN_WIDTH 32
+#define S5P_JPEG_MIN_HEIGHT 32
+#define S5P_JPEG_MAX_WIDTH 8192
+#define S5P_JPEG_MAX_HEIGHT 8192
+#define S5P_JPEG_ENCODE 0
+#define S5P_JPEG_DECODE 1
+#define S5P_JPEG_RAW_IN_565 0
+#define S5P_JPEG_RAW_IN_422 1
+#define S5P_JPEG_SUBSAMPLING_422 0
+#define S5P_JPEG_SUBSAMPLING_420 1
+#define S5P_JPEG_RAW_OUT_422 0
+#define S5P_JPEG_RAW_OUT_420 1
+
+/* Q-table for JPEG */
+/* ITU standard Q-table */
+static unsigned int ITU_Q_tbl[4][16] = {
+ {
+ 0x01010101, 0x01020303, 0x01010101, 0x01030303, /* Y */
+ 0x01010101, 0x02030303, 0x01010101, 0x03040403,
+ 0x01010203, 0x03050504, 0x01020303, 0x04050605,
+ 0x02030404, 0x05060605, 0x04050505, 0x06050505
+ } , {
+ 0x01010102, 0x05050505, 0x01010103, 0x05050505, /* CbCr */
+ 0x01010503, 0x05050505, 0x02030505, 0x05050505,
+ 0x05050505, 0x05050505, 0x05050505, 0x05050505,
+ 0x05050505, 0x05050505, 0x05050505, 0x05050505
+ } , {
+ 0x05020205, 0x0a161e25, 0x02020307, 0x0c232521, /* Y */
+ 0x0302050a, 0x16222b22, 0x0305090e, 0x1e393326,
+ 0x06091422, 0x2a384431, 0x0a122118, 0x34454b3c,
+ 0x1d283238, 0x44525142, 0x2d3c3e40, 0x4a424441
+ } , {
+ 0x05020205, 0x251e160a, 0x07030202, 0x2125230c, /* CbCr */
+ 0x0a050203, 0x222b2216, 0x0e090503, 0x2633391e,
+ 0x22140906, 0x3144382a, 0x1821120a, 0x3c4b4534,
+ 0x3832281d, 0x42515244, 0x403e3c2d, 0x4144424a
+ }
+};
+
+/* ITU Luminace Huffman Table */
+static unsigned int ITU_H_tbl_len_DC_luminance[4] = {
+ 0x01050100, 0x01010101, 0x00000001, 0x00000000
+};
+static unsigned int ITU_H_tbl_val_DC_luminance[3] = {
+ 0x03020100, 0x07060504, 0x0b0a0908
+};
+
+/* ITU Chrominace Huffman Table */
+static unsigned int ITU_H_tbl_len_DC_chrominance[4] = {
+ 0x01010300, 0x01010101, 0x00010101, 0x00000000
+};
+static unsigned int ITU_H_tbl_val_DC_chrominance[3] = {
+ 0x03020100, 0x07060504, 0x0b0a0908
+};
+
+static unsigned int ITU_H_tbl_len_AC_luminance[4] = {
+ 0x03010200, 0x03040203, 0x04040505, 0x7d010000
+};
+
+static unsigned int ITU_H_tbl_val_AC_luminance[41] = {
+ 0x00030201, 0x12051104, 0x06413121, 0x07615113,
+ 0x32147122, 0x08a19181, 0xc1b14223, 0xf0d15215,
+ 0x72623324, 0x160a0982, 0x1a191817, 0x28272625,
+ 0x35342a29, 0x39383736, 0x4544433a, 0x49484746,
+ 0x5554534a, 0x59585756, 0x6564635a, 0x69686766,
+ 0x7574736a, 0x79787776, 0x8584837a, 0x89888786,
+ 0x9493928a, 0x98979695, 0xa3a29a99, 0xa7a6a5a4,
+ 0xb2aaa9a8, 0xb6b5b4b3, 0xbab9b8b7, 0xc5c4c3c2,
+ 0xc9c8c7c6, 0xd4d3d2ca, 0xd8d7d6d5, 0xe2e1dad9,
+ 0xe6e5e4e3, 0xeae9e8e7, 0xf4f3f2f1, 0xf8f7f6f5,
+ 0x0000faf9
+};
+
+static u32 ITU_H_tbl_len_AC_chrominance[4] = {
+ 0x02010200, 0x04030404, 0x04040507, 0x77020100
+};
+static u32 ITU_H_tbl_val_AC_chrominance[41] = {
+ 0x03020100, 0x21050411, 0x41120631, 0x71610751,
+ 0x81322213, 0x91421408, 0x09c1b1a1, 0xf0523323,
+ 0xd1726215, 0x3424160a, 0x17f125e1, 0x261a1918,
+ 0x2a292827, 0x38373635, 0x44433a39, 0x48474645,
+ 0x54534a49, 0x58575655, 0x64635a59, 0x68676665,
+ 0x74736a69, 0x78777675, 0x83827a79, 0x87868584,
+ 0x928a8988, 0x96959493, 0x9a999897, 0xa5a4a3a2,
+ 0xa9a8a7a6, 0xb4b3b2aa, 0xb8b7b6b5, 0xc3c2bab9,
+ 0xc7c6c5c4, 0xd2cac9c8, 0xd6d5d4d3, 0xdad9d8d7,
+ 0xe5e4e3e2, 0xe9e8e7e6, 0xf4f3f2ea, 0xf8f7f6f5,
+ 0x0000faf9
+};
+
+static inline void jpeg_reset(void __iomem *regs)
+{
+ unsigned long reg;
+
+ reg = readl(regs + S5P_JPEG_CNTL_REG);
+ writel(reg & ~S5P_JPEG_SOFT_RESET_HI,
+ regs + S5P_JPEG_CNTL_REG);
+
+ ndelay(100000);
+
+ writel(reg | S5P_JPEG_SOFT_RESET_HI,
+ regs + S5P_JPEG_CNTL_REG);
+
+}
+
+static inline void jpeg_input_raw_mode(void __iomem *regs, unsigned long mode)
+{
+ unsigned long reg, m;
+
+ if (mode == S5P_JPEG_RAW_IN_565)
+ m = S5P_JPEG_ENC_RGB_IMG |
+ S5P_JPEG_RGB_IP_RGB_16BIT_IMG;
+ else if (mode == S5P_JPEG_RAW_IN_422)
+ m = S5P_JPEG_ENC_YUV_422_IMG |
+ S5P_JPEG_YUV_422_IP_YUV_422_1P_IMG;
+
+ reg = readl(regs + S5P_JPEG_IMG_FMT_REG) &
+ S5P_JPEG_ENC_IN_FMT_MASK; /* clear except enc format */
+ reg |= m;
+
+ writel(reg, regs + S5P_JPEG_IMG_FMT_REG);
+}
+
+static inline void jpeg_proc_mode(void __iomem *regs, unsigned long mode)
+{
+ unsigned int reg, m;
+
+ m = S5P_JPEG_DEC_MODE;
+ if (mode == S5P_JPEG_ENCODE)
+ m = S5P_JPEG_ENC_MODE;
+ else
+ m = S5P_JPEG_DEC_MODE;
+
+ reg = readl(regs + S5P_JPEG_CNTL_REG);
+ reg &= S5P_JPEG_ENC_DEC_MODE_MASK;
+ reg |= m;
+
+ writel(reg, regs + S5P_JPEG_CNTL_REG);
+}
+
+static inline void jpeg_set_dec_bitstream_size(void __iomem *regs, u32 size)
+{
+ writel(size, regs + S5P_JPEG_BITSTREAM_SIZE_REG);
+}
+
+static inline void jpeg_subsampling_mode(void __iomem *regs, unsigned long mode)
+{
+ unsigned long reg, m;
+
+ m = S5P_JPEG_ENC_FMT_YUV_422;
+ if (mode == S5P_JPEG_SUBSAMPLING_422)
+ m = S5P_JPEG_ENC_FMT_YUV_422;
+ else if (mode == S5P_JPEG_SUBSAMPLING_420)
+ m = S5P_JPEG_ENC_FMT_YUV_420;
+
+ reg = readl(regs + S5P_JPEG_IMG_FMT_REG);
+ reg &= ~S5P_JPEG_ENC_FMT_MASK;
+ reg |= m;
+
+ writel(reg, regs + S5P_JPEG_IMG_FMT_REG);
+}
+
+static void jpeg_set_encode_tbl_select(void __iomem *regs,
+ int quality)
+{
+ unsigned int reg;
+
+ switch (quality) {
+ case 0:
+ reg = S5P_JPEG_Q_TBL_COMP1_0 | S5P_JPEG_Q_TBL_COMP2_1 |
+ S5P_JPEG_Q_TBL_COMP3_1 |
+ S5P_JPEG_HUFF_TBL_COMP1_AC_0_DC_0 |
+ S5P_JPEG_HUFF_TBL_COMP2_AC_0_DC_0 |
+ S5P_JPEG_HUFF_TBL_COMP3_AC_1_DC_1;
+ break;
+ case 1:
+ reg = S5P_JPEG_Q_TBL_COMP1_0 | S5P_JPEG_Q_TBL_COMP2_3 |
+ S5P_JPEG_Q_TBL_COMP3_3 |
+ S5P_JPEG_HUFF_TBL_COMP1_AC_0_DC_0 |
+ S5P_JPEG_HUFF_TBL_COMP2_AC_0_DC_0 |
+ S5P_JPEG_HUFF_TBL_COMP3_AC_1_DC_1;
+ break;
+ case 2:
+ reg = S5P_JPEG_Q_TBL_COMP1_2 | S5P_JPEG_Q_TBL_COMP2_1 |
+ S5P_JPEG_Q_TBL_COMP3_1 |
+ S5P_JPEG_HUFF_TBL_COMP1_AC_0_DC_0 |
+ S5P_JPEG_HUFF_TBL_COMP2_AC_0_DC_0 |
+ S5P_JPEG_HUFF_TBL_COMP3_AC_1_DC_1;
+ break;
+ case 3:
+ reg = S5P_JPEG_Q_TBL_COMP1_2 | S5P_JPEG_Q_TBL_COMP2_3 |
+ S5P_JPEG_Q_TBL_COMP3_3 |
+ S5P_JPEG_HUFF_TBL_COMP1_AC_0_DC_0 |
+ S5P_JPEG_HUFF_TBL_COMP2_AC_0_DC_0 |
+ S5P_JPEG_HUFF_TBL_COMP3_AC_1_DC_1;
+ break;
+ default:
+ reg = S5P_JPEG_Q_TBL_COMP1_0 | S5P_JPEG_Q_TBL_COMP2_1 |
+ S5P_JPEG_Q_TBL_COMP3_1 |
+ S5P_JPEG_HUFF_TBL_COMP1_AC_0_DC_0 |
+ S5P_JPEG_HUFF_TBL_COMP2_AC_0_DC_0 |
+ S5P_JPEG_HUFF_TBL_COMP3_AC_1_DC_1;
+ break;
+ }
+ writel(reg, regs + S5P_JPEG_TBL_SEL_REG);
+}
+
+static inline void jpeg_x_y(void __iomem *regs, unsigned int x, unsigned int y)
+{
+ writel(0x0, regs + S5P_JPEG_IMG_SIZE_REG); /* clear */
+ writel(S5P_JPEG_X_SIZE(x) | S5P_JPEG_Y_SIZE(y),
+ regs + S5P_JPEG_IMG_SIZE_REG);
+}
+
+static inline void jpeg_set_dec_scaling(void __iomem *regs,
+ int x_value, int y_value)
+{
+ unsigned int reg;
+
+ reg = readl(regs + S5P_JPEG_CNTL_REG) &
+ ~(S5P_JPEG_HOR_SCALING_MASK |
+ S5P_JPEG_VER_SCALING_MASK);
+
+ writel(reg | S5P_JPEG_HOR_SCALING(x_value) |
+ S5P_JPEG_VER_SCALING(y_value),
+ regs + S5P_JPEG_CNTL_REG);
+}
+
+static inline void jpeg_outform_raw(void __iomem *regs, unsigned long format)
+{
+ unsigned long reg;
+
+ writel(0, regs + S5P_JPEG_IMG_FMT_REG); /* clear */
+
+ if (format == S5P_JPEG_RAW_OUT_422)
+ reg = S5P_JPEG_DEC_YUV_422_IMG |
+ S5P_JPEG_YUV_422_IP_YUV_422_1P_IMG;
+ else if (format == S5P_JPEG_RAW_OUT_420)
+ reg = S5P_JPEG_DEC_YUV_420_IMG |
+ S5P_JPEG_YUV_420_IP_YUV_420_3P_IMG;
+
+ writel(reg, regs + S5P_JPEG_IMG_FMT_REG);
+}
+
+static inline void jpeg_jpgadr(void __iomem *regs, unsigned long addr)
+{
+ writel(addr, regs + S5P_JPEG_OUT_MEM_BASE_REG);
+}
+
+static inline void jpeg_dec_imgadr(void __iomem *regs, unsigned long addr,
+ unsigned long format, u32 width, u32 height)
+{
+ if (format == S5P_JPEG_RAW_OUT_422) {
+ writel(addr, regs + S5P_JPEG_IMG_BA_PLANE_1_REG);
+ writel(0, regs + S5P_JPEG_IMG_BA_PLANE_2_REG);
+ writel(0, regs + S5P_JPEG_IMG_BA_PLANE_3_REG);
+ } else if (format == S5P_JPEG_RAW_OUT_420) {
+ writel(addr, regs + S5P_JPEG_IMG_BA_PLANE_1_REG);
+ writel(addr + width * height,
+ regs + S5P_JPEG_IMG_BA_PLANE_2_REG);
+ writel(addr + width * height + (width * height / 4),
+ regs + S5P_JPEG_IMG_BA_PLANE_3_REG);
+ }
+}
+
+static inline void jpeg_enc_imgadr(void __iomem *regs, unsigned long addr)
+{
+ writel(addr, regs + S5P_JPEG_IMG_BA_PLANE_1_REG);
+}
+
+static unsigned int jpeg_get_int_status(void __iomem *regs)
+{
+ return readl(regs + S5P_JPEG_INT_STATUS_REG);
+}
+
+static void jpeg_set_interrupt(void __iomem *regs)
+{
+ unsigned long reg;
+
+ reg = readl(regs + S5P_JPEG_INT_EN_REG) & ~S5P_JPEG_INT_EN_MASK;
+ writel(S5P_JPEG_INT_EN_ALL, regs + S5P_JPEG_INT_EN_REG);
+}
+
+static void jpeg_set_huf_table_enable(void __iomem *regs, int value)
+{
+ unsigned long reg;
+
+ reg = readl(regs + S5P_JPEG_CNTL_REG) & ~S5P_JPEG_HUF_TBL_EN;
+
+ if (value == 1)
+ writel(reg | S5P_JPEG_HUF_TBL_EN, regs + S5P_JPEG_CNTL_REG);
+ else
+ writel(reg | ~S5P_JPEG_HUF_TBL_EN, regs + S5P_JPEG_CNTL_REG);
+}
+
+static inline void jpeg_qtbl(void __iomem *regs)
+{
+ int i;
+
+ for (i = 0; i < 16; i++)
+ writel((unsigned int)ITU_Q_tbl[0][i],
+ regs + S5P_JPEG_QUAN_TBL_ENTRY_REG + (i*0x04));
+
+ for (i = 0; i < 16; i++)
+ writel((unsigned int)ITU_Q_tbl[1][i],
+ regs + S5P_JPEG_QUAN_TBL_ENTRY_REG + 0x40 + (i*0x04));
+
+ for (i = 0; i < 16; i++)
+ writel((unsigned int)ITU_Q_tbl[2][i],
+ regs + S5P_JPEG_QUAN_TBL_ENTRY_REG + 0x80 + (i*0x04));
+
+ for (i = 0; i < 16; i++)
+ writel((unsigned int)ITU_Q_tbl[3][i],
+ regs + S5P_JPEG_QUAN_TBL_ENTRY_REG + 0xc0 + (i*0x04));
+}
+
+static inline void jpeg_htbl_ac(void __iomem *regs)
+{
+ int i;
+
+ for (i = 0; i < 4; i++)
+ writel((unsigned int)ITU_H_tbl_len_AC_luminance[i],
+ regs + S5P_JPEG_HUFF_TBL_ENTRY_REG + 0x40 + (i*0x04));
+
+ for (i = 0; i < 41; i++)
+ writel((unsigned int)ITU_H_tbl_val_AC_luminance[i],
+ regs + S5P_JPEG_HUFF_TBL_ENTRY_REG + 0x50 + (i*0x04));
+
+ for (i = 0; i < 4; i++)
+ writel((unsigned int)ITU_H_tbl_len_AC_chrominance[i],
+ regs + S5P_JPEG_HUFF_TBL_ENTRY_REG + 0x100 + (i*0x04));
+
+ for (i = 0; i < 41; i++)
+ writel((unsigned int)ITU_H_tbl_val_AC_chrominance[i],
+ regs + S5P_JPEG_HUFF_TBL_ENTRY_REG + 0x110 + (i*0x04));
+}
+
+static inline void jpeg_htbl_dc(void __iomem *regs)
+{
+ int i;
+
+ for (i = 0; i < 4; i++)
+ writel((unsigned int)ITU_H_tbl_len_DC_luminance[i],
+ regs + S5P_JPEG_HUFF_TBL_ENTRY_REG + (i*0x04));
+
+ for (i = 0; i < 3; i++)
+ writel((unsigned int)ITU_H_tbl_val_DC_luminance[i],
+ regs + S5P_JPEG_HUFF_TBL_ENTRY_REG + 0x10 + (i*0x04));
+
+ for (i = 0; i < 4; i++)
+ writel((unsigned int)ITU_H_tbl_len_DC_chrominance[i],
+ regs + S5P_JPEG_HUFF_TBL_ENTRY_REG + 0x20 + (i*0x04));
+
+ for (i = 0; i < 3; i++)
+ writel((unsigned int)ITU_H_tbl_val_DC_chrominance[i],
+ regs + S5P_JPEG_HUFF_TBL_ENTRY_REG + 0x30 + (i*0x04));
+}
+
+static void jpeg_set_encode_hoff_cnt(void __iomem *regs)
+{
+ writel(0x1a2, regs + S5P_JPEG_HUFF_CNT_REG);
+}
+
+static unsigned int jpeg_compressed_size(void __iomem *regs)
+{
+ return readl(regs + S5P_JPEG_BITSTREAM_SIZE_REG);
+}
+
+#endif /* JPEG_HW_V2X_H_ */
diff --git a/drivers/media/video/s5p-jpeg/jpeg-regs-v2x.h b/drivers/media/video/s5p-jpeg/jpeg-regs-v2x.h
new file mode 100644
index 0000000..8305475
--- /dev/null
+++ b/drivers/media/video/s5p-jpeg/jpeg-regs-v2x.h
@@ -0,0 +1,150 @@
+/* linux/drivers/media/video/s5p-jpeg/jpeg-regs-v2x.h
+ *
+ * Register definition file for Samsung JPEG codec driver
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ * http:www.samsung.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.
+ */
+
+#ifndef JPEG_REGS_H_
+#define JPEG_REGS_H_
+
+/* JPEG Codec Control Registers */
+#define S5P_JPEG_CNTL_REG 0x00
+#define S5P_JPEG_INT_EN_REG 0x04
+#define S5P_JPEG_INT_STATUS_REG 0x0c
+#define S5P_JPEG_OUT_MEM_BASE_REG 0x10
+#define S5P_JPEG_IMG_SIZE_REG 0x14
+#define S5P_JPEG_IMG_BA_PLANE_1_REG 0x18
+#define S5P_JPEG_IMG_BA_PLANE_2_REG 0x24
+#define S5P_JPEG_IMG_BA_PLANE_3_REG 0x30
+
+#define S5P_JPEG_TBL_SEL_REG 0x3c
+
+#define S5P_JPEG_IMG_FMT_REG 0x40
+
+#define S5P_JPEG_BITSTREAM_SIZE_REG 0x44
+#define S5P_JPEG_HUFF_CNT_REG 0x4c
+
+#define S5P_JPEG_QUAN_TBL_ENTRY_REG 0x100
+#define S5P_JPEG_HUFF_TBL_ENTRY_REG 0x200
+
+
+/****************************************************************/
+/* Bit definition part */
+/****************************************************************/
+
+/* JPEG CNTL Register bit */
+#define S5P_JPEG_ENC_DEC_MODE_MASK (0xfffffffc << 0)
+#define S5P_JPEG_DEC_MODE (1 << 0)
+#define S5P_JPEG_ENC_MODE (1 << 1)
+#define S5P_JPEG_HUF_TBL_EN (1 << 19)
+#define S5P_JPEG_HOR_SCALING_SHIFT 20
+#define S5P_JPEG_HOR_SCALING_MASK \
+ (3 << S5P_JPEG_HOR_SCALING_SHIFT)
+#define S5P_JPEG_HOR_SCALING(x) \
+ (((x) & 0x3) << S5P_JPEG_HOR_SCALING_SHIFT)
+#define S5P_JPEG_VER_SCALING_SHIFT 22
+#define S5P_JPEG_VER_SCALING_MASK \
+ (3 << S5P_JPEG_VER_SCALING_SHIFT)
+#define S5P_JPEG_VER_SCALING(x) \
+ (((x) & 0x3) << S5P_JPEG_VER_SCALING_SHIFT)
+#define S5P_JPEG_SOFT_RESET_HI (1 << 29)
+
+/* JPEG INT Register bit */
+#define S5P_JPEG_INT_EN_MASK (0x1f << 0)
+#define S5P_JPEG_INT_EN_ALL (0x1f << 0)
+
+/* JPEG IMAGE SIZE Register bit */
+#define S5P_JPEG_X_SIZE_SHIFT 0
+#define S5P_JPEG_X_SIZE_MASK (0xffff << S5P_JPEG_X_SIZE_SHIFT)
+#define S5P_JPEG_X_SIZE(x) \
+ (((x) & 0xffff) << S5P_JPEG_X_SIZE_SHIFT)
+#define S5P_JPEG_Y_SIZE_SHIFT 16
+#define S5P_JPEG_Y_SIZE_MASK (0xffff << S5P_JPEG_Y_SIZE_SHIFT)
+#define S5P_JPEG_Y_SIZE(x) \
+ (((x) & 0xffff) << S5P_JPEG_Y_SIZE_SHIFT)
+
+/* JPEG IMAGE FORMAT Register bit */
+#define S5P_JPEG_ENC_IN_FMT_MASK 0xffff0000
+#define S5P_JPEG_ENC_RGB_IMG (1 << 0)
+#define S5P_JPEG_RGB_IP_SHIFT 6
+#define S5P_JPEG_RGB_IP_RGB_16BIT_IMG (4 << S5P_JPEG_RGB_IP_SHIFT)
+#define S5P_JPEG_ENC_YUV_422_IMG (3 << 0)
+
+/* JPEG IMAGE FORMAT Register bit */
+#define S5P_JPEG_ENC_IN_FMT_MASK 0xffff0000
+#define S5P_JPEG_DEC_YUV_422_IMG (3 << 0)
+#define S5P_JPEG_DEC_YUV_420_IMG (4 << 0)
+
+#define S5P_JPEG_YUV_422_IP_SHIFT 12
+#define S5P_JPEG_YUV_422_IP_MASK (7 << S5P_JPEG_YUV_422_IP_SHIFT)
+#define S5P_JPEG_YUV_422_IP_YUV_422_1P_IMG \
+ (4 << S5P_JPEG_YUV_422_IP_SHIFT)
+
+#define S5P_JPEG_YUV_420_IP_SHIFT 15
+#define S5P_JPEG_YUV_420_IP_MASK (7 << S5P_JPEG_YUV_420_IP_SHIFT)
+#define S5P_JPEG_YUV_420_IP_YUV_420_3P_IMG \
+ (5 << S5P_JPEG_YUV_420_IP_SHIFT)
+
+#define S5P_JPEG_ENC_FMT_SHIFT 24
+#define S5P_JPEG_ENC_FMT_MASK (3 << S5P_JPEG_ENC_FMT_SHIFT)
+#define S5P_JPEG_ENC_FMT_YUV_444 (1 << S5P_JPEG_ENC_FMT_SHIFT)
+#define S5P_JPEG_ENC_FMT_YUV_422 (2 << S5P_JPEG_ENC_FMT_SHIFT)
+#define S5P_JPEG_ENC_FMT_YUV_420 (3 << S5P_JPEG_ENC_FMT_SHIFT)
+
+/* JPEG TBL SEL Register bit */
+#define S5P_JPEG_Q_TBL_COMP1_SHIFT 0
+#define S5P_JPEG_Q_TBL_COMP1_0 (0 << S5P_JPEG_Q_TBL_COMP1_SHIFT)
+#define S5P_JPEG_Q_TBL_COMP1_1 (1 << S5P_JPEG_Q_TBL_COMP1_SHIFT)
+#define S5P_JPEG_Q_TBL_COMP1_2 (2 << S5P_JPEG_Q_TBL_COMP1_SHIFT)
+#define S5P_JPEG_Q_TBL_COMP1_3 (3 << S5P_JPEG_Q_TBL_COMP1_SHIFT)
+
+#define S5P_JPEG_Q_TBL_COMP2_SHIFT 2
+#define S5P_JPEG_Q_TBL_COMP2_0 (0 << S5P_JPEG_Q_TBL_COMP2_SHIFT)
+#define S5P_JPEG_Q_TBL_COMP2_1 (1 << S5P_JPEG_Q_TBL_COMP2_SHIFT)
+#define S5P_JPEG_Q_TBL_COMP2_2 (2 << S5P_JPEG_Q_TBL_COMP2_SHIFT)
+#define S5P_JPEG_Q_TBL_COMP2_3 (3 << S5P_JPEG_Q_TBL_COMP2_SHIFT)
+
+#define S5P_JPEG_Q_TBL_COMP3_SHIFT 4
+#define S5P_JPEG_Q_TBL_COMP3_0 (0 << S5P_JPEG_Q_TBL_COMP3_SHIFT)
+#define S5P_JPEG_Q_TBL_COMP3_1 (1 << S5P_JPEG_Q_TBL_COMP2_SHIFT)
+#define S5P_JPEG_Q_TBL_COMP3_2 (2 << S5P_JPEG_Q_TBL_COMP2_SHIFT)
+#define S5P_JPEG_Q_TBL_COMP3_3 (3 << S5P_JPEG_Q_TBL_COMP2_SHIFT)
+
+#define S5P_JPEG_HUFF_TBL_COMP1_SHIFT 6
+#define S5P_JPEG_HUFF_TBL_COMP1_AC_0_DC_0 \
+ (0 << S5P_JPEG_HUFF_TBL_COMP1_SHIFT)
+#define S5P_JPEG_HUFF_TBL_COMP1_AC_0_DC_1 \
+ (1 << S5P_JPEG_HUFF_TBL_COMP1_SHIFT)
+#define S5P_JPEG_HUFF_TBL_COMP1_AC_1_DC_0 \
+ (2 << S5P_JPEG_HUFF_TBL_COMP1_SHIFT)
+#define S5P_JPEG_HUFF_TBL_COMP1_AC_1_DC_1 \
+ (3 << S5P_JPEG_HUFF_TBL_COMP1_SHIFT)
+
+#define S5P_JPEG_HUFF_TBL_COMP2_SHIFT 8
+#define S5P_JPEG_HUFF_TBL_COMP2_AC_0_DC_0 \
+ (0 << S5P_JPEG_HUFF_TBL_COMP2_SHIFT)
+#define S5P_JPEG_HUFF_TBL_COMP2_AC_0_DC_1 \
+ (1 << S5P_JPEG_HUFF_TBL_COMP2_SHIFT)
+#define S5P_JPEG_HUFF_TBL_COMP2_AC_1_DC_0 \
+ (2 << S5P_JPEG_HUFF_TBL_COMP2_SHIFT)
+#define S5P_JPEG_HUFF_TBL_COMP2_AC_1_DC_1 \
+ (3 << S5P_JPEG_HUFF_TBL_COMP2_SHIFT)
+
+#define S5P_JPEG_HUFF_TBL_COMP3_SHIFT 10
+#define S5P_JPEG_HUFF_TBL_COMP3_AC_0_DC_0 \
+ (0 << S5P_JPEG_HUFF_TBL_COMP3_SHIFT)
+#define S5P_JPEG_HUFF_TBL_COMP3_AC_0_DC_1 \
+ (1 << S5P_JPEG_HUFF_TBL_COMP3_SHIFT)
+#define S5P_JPEG_HUFF_TBL_COMP3_AC_1_DC_0 \
+ (2 << S5P_JPEG_HUFF_TBL_COMP3_SHIFT)
+#define S5P_JPEG_HUFF_TBL_COMP3_AC_1_DC_1 \
+ (3 << S5P_JPEG_HUFF_TBL_COMP3_SHIFT)
+
+#endif /* JPEG_REGS_H_ */
diff --git a/drivers/media/video/s5p-jpeg/jpeg-v2x.c b/drivers/media/video/s5p-jpeg/jpeg-v2x.c
new file mode 100644
index 0000000..71bd38b
--- /dev/null
+++ b/drivers/media/video/s5p-jpeg/jpeg-v2x.c
@@ -0,0 +1,129 @@
+/* linux/drivers/media/video/s5p-jpeg/jpeg-v2x.c
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ * http://www.samsung.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.
+ */
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/gfp.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <media/v4l2-mem2mem.h>
+#include <media/v4l2-ioctl.h>
+#include <media/videobuf2-core.h>
+#include <media/videobuf2-dma-contig.h>
+
+#include "jpeg-core.h"
+#include "jpeg-hw-v2x.h"
+
+/*
+ * ============================================================================
+ * mem2mem callbacks
+ * ============================================================================
+ */
+
+void s5p_jpeg_irq_execute(void *dev_id)
+{
+ struct s5p_jpeg *jpeg = dev_id;
+ struct s5p_jpeg_ctx *curr_ctx;
+ struct vb2_buffer *src_buf, *dst_buf;
+ unsigned long payload_size = 0;
+ enum vb2_buffer_state state = VB2_BUF_STATE_DONE;
+
+ unsigned int int_status;
+
+ curr_ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev);
+
+ src_buf = v4l2_m2m_src_buf_remove(curr_ctx->m2m_ctx);
+ dst_buf = v4l2_m2m_dst_buf_remove(curr_ctx->m2m_ctx);
+
+ int_status = jpeg_get_int_status(jpeg->regs);
+
+ if (int_status != 0x2)
+ state = VB2_BUF_STATE_ERROR;
+
+ v4l2_m2m_buf_done(src_buf, state);
+ if (curr_ctx->mode == S5P_JPEG_ENCODE && int_status == 0x2) {
+ payload_size = jpeg_compressed_size(jpeg->regs);
+ vb2_set_plane_payload(dst_buf, 0, payload_size);
+ }
+ v4l2_m2m_buf_done(dst_buf, state);
+ v4l2_m2m_job_finish(jpeg->m2m_dev, curr_ctx->m2m_ctx);
+}
+
+void s5p_jpeg_execute(void *priv)
+{
+ struct s5p_jpeg_ctx *ctx = priv;
+ struct s5p_jpeg *jpeg = ctx->jpeg;
+ struct vb2_buffer *src_buf, *dst_buf;
+ unsigned long src_addr, dst_addr;
+
+ src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
+ dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
+
+ src_addr = vb2_dma_contig_plane_dma_addr(src_buf, 0);
+ dst_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0);
+
+ jpeg_reset(jpeg->regs);
+ jpeg_set_interrupt(jpeg->regs);
+
+ if (ctx->mode == S5P_JPEG_ENCODE) {
+ jpeg_set_huf_table_enable(jpeg->regs, 1);
+ jpeg_qtbl(jpeg->regs);
+ jpeg_htbl_ac(jpeg->regs);
+ jpeg_htbl_dc(jpeg->regs);
+ jpeg_set_encode_tbl_select(jpeg->regs, ctx->compr_quality);
+ jpeg_x_y(jpeg->regs, ctx->out_q.w, ctx->out_q.h);
+
+ if (ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB565)
+ jpeg_input_raw_mode(jpeg->regs, S5P_JPEG_RAW_IN_565);
+ else
+ jpeg_input_raw_mode(jpeg->regs, S5P_JPEG_RAW_IN_422);
+ if (ctx->cap_q.fmt->fourcc == V4L2_PIX_FMT_YUYV)
+ jpeg_subsampling_mode(jpeg->regs,
+ S5P_JPEG_SUBSAMPLING_422);
+ else
+ jpeg_subsampling_mode(jpeg->regs,
+ S5P_JPEG_SUBSAMPLING_420);
+
+ jpeg_enc_imgadr(jpeg->regs, src_addr);
+ jpeg_jpgadr(jpeg->regs, dst_addr);
+ jpeg_set_encode_hoff_cnt(jpeg->regs);
+ } else {
+ jpeg_set_encode_tbl_select(jpeg->regs, 0);
+ jpeg_set_dec_scaling(jpeg->regs, 0, 0);
+ jpeg_jpgadr(jpeg->regs, src_addr);
+ if (ctx->cap_q.fmt->fourcc == V4L2_PIX_FMT_YUYV) {
+ jpeg_dec_imgadr(jpeg->regs, dst_addr,
+ S5P_JPEG_RAW_OUT_422,
+ ctx->out_q.w, ctx->out_q.h);
+ jpeg_outform_raw(jpeg->regs, S5P_JPEG_RAW_OUT_422);
+ } else {
+ jpeg_dec_imgadr(jpeg->regs, dst_addr,
+ S5P_JPEG_RAW_OUT_420,
+ ctx->out_q.w, ctx->out_q.h);
+ jpeg_outform_raw(jpeg->regs, S5P_JPEG_RAW_OUT_420);
+ }
+ jpeg_set_dec_bitstream_size(jpeg->regs,
+ ctx->out_q.size / 32 + 1);
+ }
+ jpeg_proc_mode(jpeg->regs, ctx->mode);
+}
+
+void s5p_jpeg_runtime_resume_execute(struct device *dev)
+{
+
+}
diff --git a/drivers/media/video/s5p-jpeg/jpeg-v3.c b/drivers/media/video/s5p-jpeg/jpeg-v3.c
new file mode 100644
index 0000000..41a5038
--- /dev/null
+++ b/drivers/media/video/s5p-jpeg/jpeg-v3.c
@@ -0,0 +1,340 @@
+/* linux/drivers/media/video/s5p-jpeg/jpeg-v3.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.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.
+ */
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/gfp.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <media/v4l2-mem2mem.h>
+#include <media/v4l2-ioctl.h>
+#include <media/videobuf2-core.h>
+#include <media/videobuf2-dma-contig.h>
+
+#include "jpeg-core.h"
+#include "jpeg-hw.h"
+
+static const unsigned char qtbl_luminance[4][64] = {
+ {/* level 1 - high quality */
+ 8, 6, 6, 8, 12, 14, 16, 17,
+ 6, 6, 6, 8, 10, 13, 12, 15,
+ 6, 6, 7, 8, 13, 14, 18, 24,
+ 8, 8, 8, 14, 13, 19, 24, 35,
+ 12, 10, 13, 13, 20, 26, 34, 39,
+ 14, 13, 14, 19, 26, 34, 39, 39,
+ 16, 12, 18, 24, 34, 39, 39, 39,
+ 17, 15, 24, 35, 39, 39, 39, 39
+ },
+ {/* level 2 */
+ 12, 8, 8, 12, 17, 21, 24, 23,
+ 8, 9, 9, 11, 15, 19, 18, 23,
+ 8, 9, 10, 12, 19, 20, 27, 36,
+ 12, 11, 12, 21, 20, 28, 36, 53,
+ 17, 15, 19, 20, 30, 39, 51, 59,
+ 21, 19, 20, 28, 39, 51, 59, 59,
+ 24, 18, 27, 36, 51, 59, 59, 59,
+ 23, 23, 36, 53, 59, 59, 59, 59
+ },
+ {/* level 3 */
+ 16, 11, 11, 16, 23, 27, 31, 30,
+ 11, 12, 12, 15, 20, 23, 23, 30,
+ 11, 12, 13, 16, 23, 26, 35, 47,
+ 16, 15, 16, 23, 26, 37, 47, 64,
+ 23, 20, 23, 26, 39, 51, 64, 64,
+ 27, 23, 26, 37, 51, 64, 64, 64,
+ 31, 23, 35, 47, 64, 64, 64, 64,
+ 30, 30, 47, 64, 64, 64, 64, 64
+ },
+ {/*level 4 - low quality */
+ 20, 16, 25, 39, 50, 46, 62, 68,
+ 16, 18, 23, 38, 38, 53, 65, 68,
+ 25, 23, 31, 38, 53, 65, 68, 68,
+ 39, 38, 38, 53, 65, 68, 68, 68,
+ 50, 38, 53, 65, 68, 68, 68, 68,
+ 46, 53, 65, 68, 68, 68, 68, 68,
+ 62, 65, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68
+ }
+};
+
+static const unsigned char qtbl_chrominance[4][64] = {
+ {/* level 1 - high quality */
+ 9, 8, 9, 11, 14, 17, 19, 24,
+ 8, 10, 9, 11, 14, 13, 17, 22,
+ 9, 9, 13, 14, 13, 15, 23, 26,
+ 11, 11, 14, 14, 15, 20, 26, 33,
+ 14, 14, 13, 15, 20, 24, 33, 39,
+ 17, 13, 15, 20, 24, 32, 39, 39,
+ 19, 17, 23, 26, 33, 39, 39, 39,
+ 24, 22, 26, 33, 39, 39, 39, 39
+ },
+ {/* level 2 */
+ 13, 11, 13, 16, 20, 20, 29, 37,
+ 11, 14, 14, 14, 16, 20, 26, 32,
+ 13, 14, 15, 17, 20, 23, 35, 40,
+ 16, 14, 17, 21, 23, 30, 40, 50,
+ 20, 16, 20, 23, 30, 37, 50, 59,
+ 20, 20, 23, 30, 37, 48, 59, 59,
+ 29, 26, 35, 40, 50, 59, 59, 59,
+ 37, 32, 40, 50, 59, 59, 59, 59
+ },
+ {/* level 3 */
+ 17, 15, 17, 21, 20, 26, 38, 48,
+ 15, 19, 18, 17, 20, 26, 35, 43,
+ 17, 18, 20, 22, 26, 30, 46, 53,
+ 21, 17, 22, 28, 30, 39, 53, 64,
+ 20, 20, 26, 30, 39, 48, 64, 64,
+ 26, 26, 30, 39, 48, 63, 64, 64,
+ 38, 35, 46, 53, 64, 64, 64, 64,
+ 48, 43, 53, 64, 64, 64, 64, 64
+ },
+ {/*level 4 - low quality */
+ 21, 25, 32, 38, 54, 68, 68, 68,
+ 25, 28, 24, 38, 54, 68, 68, 68,
+ 32, 24, 32, 43, 66, 68, 68, 68,
+ 38, 38, 43, 53, 68, 68, 68, 68,
+ 54, 54, 66, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68
+ }
+};
+
+static const unsigned char hdctbl0[16] = {
+ 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0
+};
+
+static const unsigned char hdctblg0[12] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb
+};
+static const unsigned char hactbl0[16] = {
+ 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d
+};
+static const unsigned char hactblg0[162] = {
+ 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
+ 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
+ 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
+ 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
+ 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
+ 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
+ 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+ 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
+ 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
+ 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
+ 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
+ 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
+ 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
+ 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+ 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
+ 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
+ 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
+ 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
+ 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
+ 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+ 0xf9, 0xfa
+};
+
+static inline void jpeg_set_qtbl(void __iomem *regs, const unsigned char *qtbl,
+ unsigned long tab, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ writel((unsigned int)qtbl[i], regs + tab + (i * 0x04));
+}
+
+static inline void jpeg_set_qtbl_lum(void __iomem *regs, int quality)
+{
+ /* this driver fills quantisation table 0 with data for luma */
+ jpeg_set_qtbl(regs, qtbl_luminance[quality], S5P_JPG_QTBL_CONTENT(0),
+ ARRAY_SIZE(qtbl_luminance[quality]));
+}
+
+static inline void jpeg_set_qtbl_chr(void __iomem *regs, int quality)
+{
+ /* this driver fills quantisation table 1 with data for chroma */
+ jpeg_set_qtbl(regs, qtbl_chrominance[quality], S5P_JPG_QTBL_CONTENT(1),
+ ARRAY_SIZE(qtbl_chrominance[quality]));
+}
+
+static inline void jpeg_set_htbl(void __iomem *regs, const unsigned char *htbl,
+ unsigned long tab, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ writel((unsigned int)htbl[i], regs + tab + (i * 0x04));
+}
+
+static inline void jpeg_set_hdctbl(void __iomem *regs)
+{
+ /* this driver fills table 0 for this component */
+ jpeg_set_htbl(regs, hdctbl0, S5P_JPG_HDCTBL(0), ARRAY_SIZE(hdctbl0));
+}
+
+static inline void jpeg_set_hdctblg(void __iomem *regs)
+{
+ /* this driver fills table 0 for this component */
+ jpeg_set_htbl(regs, hdctblg0, S5P_JPG_HDCTBLG(0), ARRAY_SIZE(hdctblg0));
+}
+
+static inline void jpeg_set_hactbl(void __iomem *regs)
+{
+ /* this driver fills table 0 for this component */
+ jpeg_set_htbl(regs, hactbl0, S5P_JPG_HACTBL(0), ARRAY_SIZE(hactbl0));
+}
+
+static inline void jpeg_set_hactblg(void __iomem *regs)
+{
+ /* this driver fills table 0 for this component */
+ jpeg_set_htbl(regs, hactblg0, S5P_JPG_HACTBLG(0), ARRAY_SIZE(hactblg0));
+}
+
+void s5p_jpeg_irq_execute(void *dev_id)
+{
+ struct s5p_jpeg *jpeg = dev_id;
+ struct s5p_jpeg_ctx *curr_ctx;
+ struct vb2_buffer *src_buf, *dst_buf;
+ unsigned long payload_size = 0;
+ enum vb2_buffer_state state = VB2_BUF_STATE_DONE;
+ bool enc_jpeg_too_large = false;
+ bool timer_elapsed = false;
+ bool op_completed = false;
+
+ curr_ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev);
+
+ src_buf = v4l2_m2m_src_buf_remove(curr_ctx->m2m_ctx);
+ dst_buf = v4l2_m2m_dst_buf_remove(curr_ctx->m2m_ctx);
+
+ if (curr_ctx->mode == S5P_JPEG_ENCODE)
+ enc_jpeg_too_large = jpeg_enc_stream_stat(jpeg->regs);
+ timer_elapsed = jpeg_timer_stat(jpeg->regs);
+ op_completed = jpeg_result_stat_ok(jpeg->regs);
+ if (curr_ctx->mode == S5P_JPEG_DECODE)
+ op_completed = op_completed && jpeg_stream_stat_ok(jpeg->regs);
+
+ if (enc_jpeg_too_large) {
+ state = VB2_BUF_STATE_ERROR;
+ jpeg_clear_enc_stream_stat(jpeg->regs);
+ } else if (timer_elapsed) {
+ state = VB2_BUF_STATE_ERROR;
+ jpeg_clear_timer_stat(jpeg->regs);
+ } else if (!op_completed) {
+ state = VB2_BUF_STATE_ERROR;
+ } else {
+ payload_size = jpeg_compressed_size(jpeg->regs);
+ }
+
+ v4l2_m2m_buf_done(src_buf, state);
+ if (curr_ctx->mode == S5P_JPEG_ENCODE)
+ vb2_set_plane_payload(dst_buf, 0, payload_size);
+ v4l2_m2m_buf_done(dst_buf, state);
+ v4l2_m2m_job_finish(jpeg->m2m_dev, curr_ctx->m2m_ctx);
+
+ jpeg_clear_int(jpeg->regs);
+}
+
+void s5p_jpeg_execute(void *priv)
+{
+ struct s5p_jpeg_ctx *ctx = priv;
+ struct s5p_jpeg *jpeg = ctx->jpeg;
+ struct vb2_buffer *src_buf, *dst_buf;
+ unsigned long src_addr, dst_addr;
+
+ src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
+ dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
+ src_addr = vb2_dma_contig_plane_dma_addr(src_buf, 0);
+ dst_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0);
+
+ jpeg_reset(jpeg->regs);
+ jpeg_poweron(jpeg->regs);
+ jpeg_proc_mode(jpeg->regs, ctx->mode);
+ if (ctx->mode == S5P_JPEG_ENCODE) {
+ if (ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB565)
+ jpeg_input_raw_mode(jpeg->regs, S5P_JPEG_RAW_IN_565);
+ else
+ jpeg_input_raw_mode(jpeg->regs, S5P_JPEG_RAW_IN_422);
+ if (ctx->cap_q.fmt->fourcc == V4L2_PIX_FMT_YUYV)
+ jpeg_subsampling_mode(jpeg->regs,
+ S5P_JPEG_SUBSAMPLING_422);
+ else
+ jpeg_subsampling_mode(jpeg->regs,
+ S5P_JPEG_SUBSAMPLING_420);
+ jpeg_dri(jpeg->regs, 0);
+ jpeg_x(jpeg->regs, ctx->out_q.w);
+ jpeg_y(jpeg->regs, ctx->out_q.h);
+ jpeg_imgadr(jpeg->regs, src_addr);
+ jpeg_jpgadr(jpeg->regs, dst_addr);
+
+ /* ultimately comes from sizeimage from userspace */
+ jpeg_enc_stream_int(jpeg->regs, ctx->cap_q.size);
+
+ /* JPEG RGB to YCbCr conversion matrix */
+ jpeg_coef(jpeg->regs, 1, 1, S5P_JPEG_COEF11);
+ jpeg_coef(jpeg->regs, 1, 2, S5P_JPEG_COEF12);
+ jpeg_coef(jpeg->regs, 1, 3, S5P_JPEG_COEF13);
+ jpeg_coef(jpeg->regs, 2, 1, S5P_JPEG_COEF21);
+ jpeg_coef(jpeg->regs, 2, 2, S5P_JPEG_COEF22);
+ jpeg_coef(jpeg->regs, 2, 3, S5P_JPEG_COEF23);
+ jpeg_coef(jpeg->regs, 3, 1, S5P_JPEG_COEF31);
+ jpeg_coef(jpeg->regs, 3, 2, S5P_JPEG_COEF32);
+ jpeg_coef(jpeg->regs, 3, 3, S5P_JPEG_COEF33);
+
+ /*
+ * JPEG IP allows storing 4 quantization tables
+ * We fill table 0 for luma and table 1 for chroma
+ */
+ jpeg_set_qtbl_lum(jpeg->regs, ctx->compr_quality);
+ jpeg_set_qtbl_chr(jpeg->regs, ctx->compr_quality);
+ /* use table 0 for Y */
+ jpeg_qtbl(jpeg->regs, 1, 0);
+ /* use table 1 for Cb and Cr*/
+ jpeg_qtbl(jpeg->regs, 2, 1);
+ jpeg_qtbl(jpeg->regs, 3, 1);
+
+ /* Y, Cb, Cr use Huffman table 0 */
+ jpeg_htbl_ac(jpeg->regs, 1);
+ jpeg_htbl_dc(jpeg->regs, 1);
+ jpeg_htbl_ac(jpeg->regs, 2);
+ jpeg_htbl_dc(jpeg->regs, 2);
+ jpeg_htbl_ac(jpeg->regs, 3);
+ jpeg_htbl_dc(jpeg->regs, 3);
+ } else {
+ jpeg_rst_int_enable(jpeg->regs, true);
+ jpeg_data_num_int_enable(jpeg->regs, true);
+ jpeg_final_mcu_num_int_enable(jpeg->regs, true);
+ jpeg_outform_raw(jpeg->regs, S5P_JPEG_RAW_OUT_422);
+ jpeg_jpgadr(jpeg->regs, src_addr);
+ jpeg_imgadr(jpeg->regs, dst_addr);
+ }
+ jpeg_start(jpeg->regs);
+}
+
+void s5p_jpeg_runtime_resume_execute(struct device *dev)
+{
+ struct s5p_jpeg *jpeg = dev_get_drvdata(dev);
+ /*
+ * JPEG IP allows storing two Huffman tables for each component
+ * We fill table 0 for each component
+ */
+ jpeg_set_hdctbl(jpeg->regs);
+ jpeg_set_hdctblg(jpeg->regs);
+ jpeg_set_hactbl(jpeg->regs);
+ jpeg_set_hactblg(jpeg->regs);
+}
--
1.7.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH] media: jpeg: add driver for a version 2.x of jpeg H/W
2012-03-01 23:46 [PATCH] media: jpeg: add driver for a version 2.x of jpeg H/W 송영목
@ 2012-03-03 12:37 ` Sylwester Nawrocki
2012-03-05 13:59 ` Andrzej Pietrasiewicz
2012-03-06 6:31 ` Andrzej Pietrasiewicz
2 siblings, 0 replies; 4+ messages in thread
From: Sylwester Nawrocki @ 2012-03-03 12:37 UTC (permalink / raw)
To: 송영목; +Cc: linux-media, mchehab, andrzej.p
Hi 송영목,
On 03/02/2012 12:46 AM, 송영목 wrote:
> This patch add a driver for a version 2.x of jpeg H/W
s/add/adds
> in ths Samsung Exynos5 Soc.
s/ths/the
> A jpeg H/W version of Exynos4 SoC is 3.0
>
> 1. Encoding
> - input format : V4L2_PIX_FMT_RGB565X and V4L2_PIX_FMT_YUYV
>
> 2. Decoding
> - output format : V4L2_PIX_FMT_YUYV and V4L2_PIX_FMT_YUV420
Please consider reworking this patch so it can be applied on the latest s5p-jpeg driver
changes adding JPEG controls:
http://git.infradead.org/users/kmpark/linux-2.6-samsung/shortlog/refs/heads/media-for-next
> Signed-off-by: youngmok song<ym.song@samsung.com>
Normally the full name starts with capital letters.
> ---
> drivers/media/video/Kconfig | 17 +
> drivers/media/video/s5p-jpeg/Makefile | 5 +-
> drivers/media/video/s5p-jpeg/jpeg-core.c | 303 +-------------------
> drivers/media/video/s5p-jpeg/jpeg-hw-common.h | 34 +++
> drivers/media/video/s5p-jpeg/jpeg-hw-v2x.h | 387 +++++++++++++++++++++++++
> drivers/media/video/s5p-jpeg/jpeg-regs-v2x.h | 150 ++++++++++
> drivers/media/video/s5p-jpeg/jpeg-v2x.c | 129 ++++++++
> drivers/media/video/s5p-jpeg/jpeg-v3.c | 340 ++++++++++++++++++++++
> 8 files changed, 1066 insertions(+), 299 deletions(-)
> create mode 100644 drivers/media/video/s5p-jpeg/jpeg-hw-common.h
> create mode 100644 drivers/media/video/s5p-jpeg/jpeg-hw-v2x.h
> create mode 100644 drivers/media/video/s5p-jpeg/jpeg-regs-v2x.h
> create mode 100644 drivers/media/video/s5p-jpeg/jpeg-v2x.c
> create mode 100644 drivers/media/video/s5p-jpeg/jpeg-v3.c
>
> diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
> index 9adada0..551f925 100644
> --- a/drivers/media/video/Kconfig
> +++ b/drivers/media/video/Kconfig
> @@ -1167,6 +1167,23 @@ config VIDEO_SAMSUNG_S5P_JPEG
> select V4L2_MEM2MEM_DEV
> ---help---
> This is a v4l2 driver for Samsung S5P and EXYNOS4 JPEG codec
> +choice
> + prompt "JPEG V4L2 Driver"
> + default S5P_JPEG_V3
> + depends on VIDEO_SAMSUNG_S5P_JPEG
> + ---help---
> + Select version of MFC driver
MFC ?
> +config S5P_JPEG_V3
> + bool "JPEG 3.x"
> + ---help---
> + Use JPEG 3.x V4L2 Driver
> +
> +config S5P_JPEG_V2
> + bool "JPEG 2.x"
> + ---help---
> + Use JPEG 2.x V4L2 Driver
> +endchoice
How the user is supposed to know which JPEG IP version applies to which SoC ?
Generally, resolving the hardware differences at compile time is not something that
we would want. I suggest using struct platform_device_id for handling different H/W
variants, like it is done for example in drivers/dma/imx-sdma.c (see sdma_devtypes
table). It will ease the driver's adaptation to instantiation from the device tree, which
is important, since the exynos5 is supposed to be a DT only platform.
Probably even function pointers at the variant data structure wouldn't hurt, if there
is too many differences to handle them through single flags. From a quick review it
feels like the code could be consolidated more, but I'm going to leave commenting
on the details for Andrzej.
Please have a look at the JPEG controls:
http://git.infradead.org/users/kmpark/linux-samsung/commitdiff/e0122eabd2be3f0a3a9ff635df81e5c2509c4700
and feel free to propose anything you think is missing there (the Huffman and the
quantization tables will need their own ioctl(s)).
As a side note, please don't use Korean characters in the patch message. This implies
the character set other than ascii/utf-8 and and makes patches impossible to apply.
--
Regards,
Sylwester
^ permalink raw reply [flat|nested] 4+ messages in thread
* RE: [PATCH] media: jpeg: add driver for a version 2.x of jpeg H/W
2012-03-01 23:46 [PATCH] media: jpeg: add driver for a version 2.x of jpeg H/W 송영목
2012-03-03 12:37 ` Sylwester Nawrocki
@ 2012-03-05 13:59 ` Andrzej Pietrasiewicz
2012-03-06 6:31 ` Andrzej Pietrasiewicz
2 siblings, 0 replies; 4+ messages in thread
From: Andrzej Pietrasiewicz @ 2012-03-05 13:59 UTC (permalink / raw)
To: '송영목', linux-media; +Cc: mchehab
Hello송영목,
In general I think the v2x support should be designed to require
as little code changes as possible, and they should be related
to pure hardware differences only. Please see comments inline.
The tables (quantization, Huffman) logically contain mostly the
same data both in v3 and v2x and are defined by respective
standards. Only the arrangement of data is slightly different
(bytes vs 4-byte words). Please see comments inline.
On, March 02, 2012 12:47 AM 송영목 wrote:
<...>
> diff --git a/drivers/media/video/s5p-jpeg/jpeg-core.c
> b/drivers/media/video/s5p-jpeg/jpeg-core.c
> index 1105a87..cf917cd 100644
> --- a/drivers/media/video/s5p-jpeg/jpeg-core.c
> +++ b/drivers/media/video/s5p-jpeg/jpeg-core.c
<...>
> diff --git a/drivers/media/video/s5p-jpeg/jpeg-hw-v2x.h
<...>
> @@ -0,0 +1,387 @@
<...>
> +
> +#define S5P_JPEG_MIN_WIDTH 32
> +#define S5P_JPEG_MIN_HEIGHT 32
> +#define S5P_JPEG_MAX_WIDTH 8192
> +#define S5P_JPEG_MAX_HEIGHT 8192
> +#define S5P_JPEG_ENCODE 0
> +#define S5P_JPEG_DECODE 1
> +#define S5P_JPEG_RAW_IN_565 0
> +#define S5P_JPEG_RAW_IN_422 1
> +#define S5P_JPEG_SUBSAMPLING_422 0
> +#define S5P_JPEG_SUBSAMPLING_420 1
> +#define S5P_JPEG_RAW_OUT_422 0
> +#define S5P_JPEG_RAW_OUT_420 1
This is a verbatim copy of what is defined in jpeg-hw-common.h
and should not be repeated here. Use jpeg-hw-common.h.
> +/* Q-table for JPEG */
> +/* ITU standard Q-table */
> +static unsigned int ITU_Q_tbl[4][16] = {
> + {
> + 0x01010101, 0x01020303, 0x01010101, 0x01030303, /* Y */
> + 0x01010101, 0x02030303, 0x01010101, 0x03040403,
> + 0x01010203, 0x03050504, 0x01020303, 0x04050605,
> + 0x02030404, 0x05060605, 0x04050505, 0x06050505
> + } , {
> + 0x01010102, 0x05050505, 0x01010103, 0x05050505, /* CbCr */
> + 0x01010503, 0x05050505, 0x02030505, 0x05050505,
> + 0x05050505, 0x05050505, 0x05050505, 0x05050505,
> + 0x05050505, 0x05050505, 0x05050505, 0x05050505
> + } , {
> + 0x05020205, 0x0a161e25, 0x02020307, 0x0c232521, /* Y */
> + 0x0302050a, 0x16222b22, 0x0305090e, 0x1e393326,
> + 0x06091422, 0x2a384431, 0x0a122118, 0x34454b3c,
> + 0x1d283238, 0x44525142, 0x2d3c3e40, 0x4a424441
> + } , {
> + 0x05020205, 0x251e160a, 0x07030202, 0x2125230c, /* CbCr */
> + 0x0a050203, 0x222b2216, 0x0e090503, 0x2633391e,
> + 0x22140906, 0x3144382a, 0x1821120a, 0x3c4b4534,
> + 0x3832281d, 0x42515244, 0x403e3c2d, 0x4144424a
> + }
> +};
This array is static so this makes all users of this header file
allocate it. Why not put it into jpeg-v2x.c? (however, see
below for considerations about duplication)
This comment applies to all array definitions of this kind
in this file.
> +
> +/* ITU Luminace Huffman Table */
> +static unsigned int ITU_H_tbl_len_DC_luminance[4] = {
> + 0x01050100, 0x01010101, 0x00000001, 0x00000000
> +};
This is in fact the same thing as hdctbl0[16] in jpeg v3,
only arranged in 4-byte words. It would be nice if
the same definitions were used in both versions. This applies
to all tables defined here.
> +static unsigned int ITU_H_tbl_val_DC_luminance[3] = {
> + 0x03020100, 0x07060504, 0x0b0a0908
> +};
The same thing as hdctblg0[12] in jpeg v3.
<...>
> +static unsigned int ITU_H_tbl_val_DC_chrominance[3] = {
> + 0x03020100, 0x07060504, 0x0b0a0908
> +};
The same thing as as hdctblg0[12] in jpeg v3 and
ITU_H_tbl_val_DC_luminance[3] in your code.
> +
> +static unsigned int ITU_H_tbl_len_AC_luminance[4] = {
> + 0x03010200, 0x03040203, 0x04040505, 0x7d010000
> +};
> +
The same thing as hactbl0[16] in jpeg v3.
> +static unsigned int ITU_H_tbl_val_AC_luminance[41] = {
> + 0x00030201, 0x12051104, 0x06413121, 0x07615113,
> + 0x32147122, 0x08a19181, 0xc1b14223, 0xf0d15215,
> + 0x72623324, 0x160a0982, 0x1a191817, 0x28272625,
> + 0x35342a29, 0x39383736, 0x4544433a, 0x49484746,
> + 0x5554534a, 0x59585756, 0x6564635a, 0x69686766,
> + 0x7574736a, 0x79787776, 0x8584837a, 0x89888786,
> + 0x9493928a, 0x98979695, 0xa3a29a99, 0xa7a6a5a4,
> + 0xb2aaa9a8, 0xb6b5b4b3, 0xbab9b8b7, 0xc5c4c3c2,
> + 0xc9c8c7c6, 0xd4d3d2ca, 0xd8d7d6d5, 0xe2e1dad9,
> + 0xe6e5e4e3, 0xeae9e8e7, 0xf4f3f2f1, 0xf8f7f6f5,
> + 0x0000faf9
> +};
> +
The same thing as hactblg0[162] in jpeg v3.
<...>
> +
> +static inline void jpeg_reset(void __iomem *regs)
> +{
> + unsigned long reg;
> +
> + reg = readl(regs + S5P_JPEG_CNTL_REG);
> + writel(reg & ~S5P_JPEG_SOFT_RESET_HI,
> + regs + S5P_JPEG_CNTL_REG);
> +
> + ndelay(100000);
Why not use usleep_range?
<...>
> +static inline void jpeg_proc_mode(void __iomem *regs, unsigned long mode)
> +{
> + unsigned int reg, m;
> +
> + m = S5P_JPEG_DEC_MODE;
> + if (mode == S5P_JPEG_ENCODE)
> + m = S5P_JPEG_ENC_MODE;
> + else
> + m = S5P_JPEG_DEC_MODE;
> +
> + reg = readl(regs + S5P_JPEG_CNTL_REG);
> + reg &= S5P_JPEG_ENC_DEC_MODE_MASK;
> + reg |= m;
> +
> + writel(reg, regs + S5P_JPEG_CNTL_REG);
> +}
> +
This function is in fact an exact copy of its counterpart in v3.
The difference is in the name of the constant which names the
register (S5P_JPEG_CNTL_REG vs S5P_JPEGMOD), however,
the value of this constant is 0x00 in both cases. The
numeric values of ENC/COMPR and DEC/DECOMPR constants are different,
but I believe this could be mitigated some other way.
What is important is that the 2 functions serve the same purpose
and so should be factored out to some common code.
<...>
> +static inline void jpeg_subsampling_mode(void __iomem *regs, unsigned
long
> mode)
> +{
> + unsigned long reg, m;
> +
> + m = S5P_JPEG_ENC_FMT_YUV_422;
> + if (mode == S5P_JPEG_SUBSAMPLING_422)
> + m = S5P_JPEG_ENC_FMT_YUV_422;
> + else if (mode == S5P_JPEG_SUBSAMPLING_420)
> + m = S5P_JPEG_ENC_FMT_YUV_420;
> +
> + reg = readl(regs + S5P_JPEG_IMG_FMT_REG);
> + reg &= ~S5P_JPEG_ENC_FMT_MASK;
> + reg |= m;
> +
> + writel(reg, regs + S5P_JPEG_IMG_FMT_REG);
> +}
> +
The same here.
<...>
> +
> +static inline void jpeg_jpgadr(void __iomem *regs, unsigned long addr)
> +{
> + writel(addr, regs + S5P_JPEG_OUT_MEM_BASE_REG);
> +}
> +
The same here.
<...>
> +static inline void jpeg_enc_imgadr(void __iomem *regs, unsigned long
addr)
> +{
> + writel(addr, regs + S5P_JPEG_IMG_BA_PLANE_1_REG);
> +}
> +
This looks like jpeg_imgadr() from v3.
<...>
> diff --git a/drivers/media/video/s5p-jpeg/jpeg-regs-v2x.h
> b/drivers/media/video/s5p-jpeg/jpeg-regs-v2x.h
> new file mode 100644
> index 0000000..8305475
> --- /dev/null
> +++ b/drivers/media/video/s5p-jpeg/jpeg-regs-v2x.h
> @@ -0,0 +1,150 @@
> +/* linux/drivers/media/video/s5p-jpeg/jpeg-regs-v2x.h
> + *
> + * Register definition file for Samsung JPEG codec driver
> + *
> + * Copyright (c) 2012 Samsung Electronics Co., Ltd.
> + * http:www.samsung.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.
> + */
> +
> +#ifndef JPEG_REGS_H_
> +#define JPEG_REGS_H_
> +
> +/* JPEG Codec Control Registers */
> +#define S5P_JPEG_CNTL_REG 0x00
> +#define S5P_JPEG_INT_EN_REG 0x04
> +#define S5P_JPEG_INT_STATUS_REG 0x0c
> +#define S5P_JPEG_OUT_MEM_BASE_REG 0x10
> +#define S5P_JPEG_IMG_SIZE_REG 0x14
> +#define S5P_JPEG_IMG_BA_PLANE_1_REG 0x18
> +#define S5P_JPEG_IMG_BA_PLANE_2_REG 0x24
> +#define S5P_JPEG_IMG_BA_PLANE_3_REG 0x30
> +
> +#define S5P_JPEG_TBL_SEL_REG 0x3c
> +
> +#define S5P_JPEG_IMG_FMT_REG 0x40
> +
> +#define S5P_JPEG_BITSTREAM_SIZE_REG 0x44
> +#define S5P_JPEG_HUFF_CNT_REG 0x4c
> +
> +#define S5P_JPEG_QUAN_TBL_ENTRY_REG 0x100
> +#define S5P_JPEG_HUFF_TBL_ENTRY_REG 0x200
> +
> +
> +/****************************************************************/
> +/* Bit definition part
> */
> +/****************************************************************/
> +
> +/* JPEG CNTL Register bit */
> +#define S5P_JPEG_ENC_DEC_MODE_MASK (0xfffffffc << 0)
> +#define S5P_JPEG_DEC_MODE (1 << 0)
> +#define S5P_JPEG_ENC_MODE (1 << 1)
> +#define S5P_JPEG_HUF_TBL_EN (1 << 19)
> +#define S5P_JPEG_HOR_SCALING_SHIFT 20
> +#define S5P_JPEG_HOR_SCALING_MASK \
> + (3 << S5P_JPEG_HOR_SCALING_SHIFT)
> +#define S5P_JPEG_HOR_SCALING(x) \
> + (((x) & 0x3) << S5P_JPEG_HOR_SCALING_SHIFT)
> +#define S5P_JPEG_VER_SCALING_SHIFT 22
> +#define S5P_JPEG_VER_SCALING_MASK \
> + (3 << S5P_JPEG_VER_SCALING_SHIFT)
> +#define S5P_JPEG_VER_SCALING(x) \
> + (((x) & 0x3) << S5P_JPEG_VER_SCALING_SHIFT)
> +#define S5P_JPEG_SOFT_RESET_HI (1 << 29)
> +
> +/* JPEG INT Register bit */
> +#define S5P_JPEG_INT_EN_MASK (0x1f << 0)
> +#define S5P_JPEG_INT_EN_ALL (0x1f << 0)
> +
> +/* JPEG IMAGE SIZE Register bit */
> +#define S5P_JPEG_X_SIZE_SHIFT 0
> +#define S5P_JPEG_X_SIZE_MASK (0xffff << S5P_JPEG_X_SIZE_SHIFT)
> +#define S5P_JPEG_X_SIZE(x) \
> + (((x) & 0xffff) << S5P_JPEG_X_SIZE_SHIFT)
> +#define S5P_JPEG_Y_SIZE_SHIFT 16
> +#define S5P_JPEG_Y_SIZE_MASK (0xffff << S5P_JPEG_Y_SIZE_SHIFT)
> +#define S5P_JPEG_Y_SIZE(x) \
> + (((x) & 0xffff) << S5P_JPEG_Y_SIZE_SHIFT)
> +
> +/* JPEG IMAGE FORMAT Register bit */
> +#define S5P_JPEG_ENC_IN_FMT_MASK 0xffff0000
> +#define S5P_JPEG_ENC_RGB_IMG (1 << 0)
This is used only in one place in jpeg_input_raw_mode together with
<...>
this:
> +#define S5P_JPEG_RGB_IP_RGB_16BIT_IMG (4 <<
S5P_JPEG_RGB_IP_SHIFT)
To form one constant, while
> +#define S5P_JPEG_YUV_422_IP_YUV_422_1P_IMG \
> + (4 << S5P_JPEG_YUV_422_IP_SHIFT)
is only used in two places to form another constant.
If the constants were defined not combined from parts then
jpeg_input_raw_mode is effectively the same as in v3.
And a good candidate to factor out to some common code.
> +
> +#define S5P_JPEG_YUV_420_IP_SHIFT 15
> +#define S5P_JPEG_YUV_420_IP_MASK (7 <<
S5P_JPEG_YUV_420_IP_SHIFT)
> +#define S5P_JPEG_YUV_420_IP_YUV_420_3P_IMG \
> + (5 << S5P_JPEG_YUV_420_IP_SHIFT)
> +
> +#define S5P_JPEG_ENC_FMT_SHIFT 24
> +#define S5P_JPEG_ENC_FMT_MASK (3 <<
S5P_JPEG_ENC_FMT_SHIFT)
> +#define S5P_JPEG_ENC_FMT_YUV_444 (1 <<
S5P_JPEG_ENC_FMT_SHIFT)
> +#define S5P_JPEG_ENC_FMT_YUV_422 (2 <<
S5P_JPEG_ENC_FMT_SHIFT)
> +#define S5P_JPEG_ENC_FMT_YUV_420 (3 <<
S5P_JPEG_ENC_FMT_SHIFT)
> +
> +/* JPEG TBL SEL Register bit */
> +#define S5P_JPEG_Q_TBL_COMP1_SHIFT 0
> +#define S5P_JPEG_Q_TBL_COMP1_0 (0 <<
S5P_JPEG_Q_TBL_COMP1_SHIFT)
> +#define S5P_JPEG_Q_TBL_COMP1_1 (1 <<
S5P_JPEG_Q_TBL_COMP1_SHIFT)
> +#define S5P_JPEG_Q_TBL_COMP1_2 (2 <<
S5P_JPEG_Q_TBL_COMP1_SHIFT)
> +#define S5P_JPEG_Q_TBL_COMP1_3 (3 <<
S5P_JPEG_Q_TBL_COMP1_SHIFT)
> +
> +#define S5P_JPEG_Q_TBL_COMP2_SHIFT 2
> +#define S5P_JPEG_Q_TBL_COMP2_0 (0 <<
S5P_JPEG_Q_TBL_COMP2_SHIFT)
> +#define S5P_JPEG_Q_TBL_COMP2_1 (1 <<
S5P_JPEG_Q_TBL_COMP2_SHIFT)
> +#define S5P_JPEG_Q_TBL_COMP2_2 (2 <<
S5P_JPEG_Q_TBL_COMP2_SHIFT)
> +#define S5P_JPEG_Q_TBL_COMP2_3 (3 <<
S5P_JPEG_Q_TBL_COMP2_SHIFT)
> +
> +#define S5P_JPEG_Q_TBL_COMP3_SHIFT 4
> +#define S5P_JPEG_Q_TBL_COMP3_0 (0 <<
S5P_JPEG_Q_TBL_COMP3_SHIFT)
> +#define S5P_JPEG_Q_TBL_COMP3_1 (1 <<
S5P_JPEG_Q_TBL_COMP2_SHIFT)
> +#define S5P_JPEG_Q_TBL_COMP3_2 (2 <<
S5P_JPEG_Q_TBL_COMP2_SHIFT)
> +#define S5P_JPEG_Q_TBL_COMP3_3 (3 <<
S5P_JPEG_Q_TBL_COMP2_SHIFT)
> +
> +#define S5P_JPEG_HUFF_TBL_COMP1_SHIFT 6
> +#define S5P_JPEG_HUFF_TBL_COMP1_AC_0_DC_0 \
> + (0 << S5P_JPEG_HUFF_TBL_COMP1_SHIFT)
> +#define S5P_JPEG_HUFF_TBL_COMP1_AC_0_DC_1 \
> + (1 << S5P_JPEG_HUFF_TBL_COMP1_SHIFT)
> +#define S5P_JPEG_HUFF_TBL_COMP1_AC_1_DC_0 \
> + (2 << S5P_JPEG_HUFF_TBL_COMP1_SHIFT)
> +#define S5P_JPEG_HUFF_TBL_COMP1_AC_1_DC_1 \
> + (3 << S5P_JPEG_HUFF_TBL_COMP1_SHIFT)
> +
> +#define S5P_JPEG_HUFF_TBL_COMP2_SHIFT 8
> +#define S5P_JPEG_HUFF_TBL_COMP2_AC_0_DC_0 \
> + (0 << S5P_JPEG_HUFF_TBL_COMP2_SHIFT)
> +#define S5P_JPEG_HUFF_TBL_COMP2_AC_0_DC_1 \
> + (1 << S5P_JPEG_HUFF_TBL_COMP2_SHIFT)
> +#define S5P_JPEG_HUFF_TBL_COMP2_AC_1_DC_0 \
> + (2 << S5P_JPEG_HUFF_TBL_COMP2_SHIFT)
> +#define S5P_JPEG_HUFF_TBL_COMP2_AC_1_DC_1 \
> + (3 << S5P_JPEG_HUFF_TBL_COMP2_SHIFT)
> +
> +#define S5P_JPEG_HUFF_TBL_COMP3_SHIFT 10
> +#define S5P_JPEG_HUFF_TBL_COMP3_AC_0_DC_0 \
> + (0 << S5P_JPEG_HUFF_TBL_COMP3_SHIFT)
> +#define S5P_JPEG_HUFF_TBL_COMP3_AC_0_DC_1 \
> + (1 << S5P_JPEG_HUFF_TBL_COMP3_SHIFT)
> +#define S5P_JPEG_HUFF_TBL_COMP3_AC_1_DC_0 \
> + (2 << S5P_JPEG_HUFF_TBL_COMP3_SHIFT)
> +#define S5P_JPEG_HUFF_TBL_COMP3_AC_1_DC_1 \
> + (3 << S5P_JPEG_HUFF_TBL_COMP3_SHIFT)
> +
Perhaps you could use some smarter macros, e.g. with parameters?
> +#endif /* JPEG_REGS_H_ */
> diff --git a/drivers/media/video/s5p-jpeg/jpeg-v2x.c
> b/drivers/media/video/s5p-jpeg/jpeg-v2x.c
> new file mode 100644
> index 0000000..71bd38b
> --- /dev/null
> +++ b/drivers/media/video/s5p-jpeg/jpeg-v2x.c
> @@ -0,0 +1,129 @@
> +/* linux/drivers/media/video/s5p-jpeg/jpeg-v2x.c
> + *
> + * Copyright (c) 2012 Samsung Electronics Co., Ltd.
> + * http://www.samsung.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.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/err.h>
> +#include <linux/gfp.h>
> +#include <linux/interrupt.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/slab.h>
> +#include <linux/spinlock.h>
> +#include <linux/string.h>
> +#include <media/v4l2-mem2mem.h>
> +#include <media/v4l2-ioctl.h>
> +#include <media/videobuf2-core.h>
> +#include <media/videobuf2-dma-contig.h>
> +
> +#include "jpeg-core.h"
> +#include "jpeg-hw-v2x.h"
> +
> +/*
> + *
>
============================================================================
> + * mem2mem callbacks
> + *
>
============================================================================
> + */
> +
> +void s5p_jpeg_irq_execute(void *dev_id)
> +{
> + struct s5p_jpeg *jpeg = dev_id;
> + struct s5p_jpeg_ctx *curr_ctx;
> + struct vb2_buffer *src_buf, *dst_buf;
> + unsigned long payload_size = 0;
> + enum vb2_buffer_state state = VB2_BUF_STATE_DONE;
> +
> + unsigned int int_status;
> +
> + curr_ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev);
> +
> + src_buf = v4l2_m2m_src_buf_remove(curr_ctx->m2m_ctx);
> + dst_buf = v4l2_m2m_dst_buf_remove(curr_ctx->m2m_ctx);
> +
> + int_status = jpeg_get_int_status(jpeg->regs);
> +
> + if (int_status != 0x2)
> + state = VB2_BUF_STATE_ERROR;
> +
> + v4l2_m2m_buf_done(src_buf, state);
> + if (curr_ctx->mode == S5P_JPEG_ENCODE && int_status == 0x2) {
> + payload_size = jpeg_compressed_size(jpeg->regs);
> + vb2_set_plane_payload(dst_buf, 0, payload_size);
> + }
> + v4l2_m2m_buf_done(dst_buf, state);
> + v4l2_m2m_job_finish(jpeg->m2m_dev, curr_ctx->m2m_ctx);
> +}
> +
This function is almost the same as its counterpart in jpeg v3.
The difference is only in reading the interrupt cause, while
mem2mem operations are exacty the same. This makes maintenance
more difficult: whenever mem2mem usage changes, it needs to be
updated in 2 places. I think that wherever mem2mem operations are
the same in v2 and v3, they should be factored out to some common
code.
> +void s5p_jpeg_execute(void *priv)
> +{
> + struct s5p_jpeg_ctx *ctx = priv;
> + struct s5p_jpeg *jpeg = ctx->jpeg;
> + struct vb2_buffer *src_buf, *dst_buf;
> + unsigned long src_addr, dst_addr;
> +
> + src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
> + dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
> +
> + src_addr = vb2_dma_contig_plane_dma_addr(src_buf, 0);
> + dst_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0);
> +
> + jpeg_reset(jpeg->regs);
> + jpeg_set_interrupt(jpeg->regs);
> +
> + if (ctx->mode == S5P_JPEG_ENCODE) {
> + jpeg_set_huf_table_enable(jpeg->regs, 1);
> + jpeg_qtbl(jpeg->regs);
> + jpeg_htbl_ac(jpeg->regs);
> + jpeg_htbl_dc(jpeg->regs);
> + jpeg_set_encode_tbl_select(jpeg->regs, ctx->compr_quality);
> + jpeg_x_y(jpeg->regs, ctx->out_q.w, ctx->out_q.h);
> +
> + if (ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB565)
> + jpeg_input_raw_mode(jpeg->regs,
S5P_JPEG_RAW_IN_565);
> + else
> + jpeg_input_raw_mode(jpeg->regs,
S5P_JPEG_RAW_IN_422);
> + if (ctx->cap_q.fmt->fourcc == V4L2_PIX_FMT_YUYV)
> + jpeg_subsampling_mode(jpeg->regs,
> + S5P_JPEG_SUBSAMPLING_422);
> + else
> + jpeg_subsampling_mode(jpeg->regs,
> + S5P_JPEG_SUBSAMPLING_420);
> +
> + jpeg_enc_imgadr(jpeg->regs, src_addr);
> + jpeg_jpgadr(jpeg->regs, dst_addr);
> + jpeg_set_encode_hoff_cnt(jpeg->regs);
This part is almost a verbatim copy of its counterpart from v3,
only the sequence of operations is different and some calls are
grouped into separate functions (e.g. jpeg_htbl_ac, jpeg_htbl_dc,
jpeg_qtbl). Why not factor out into some common piece of code?
> + } else {
> + jpeg_set_encode_tbl_select(jpeg->regs, 0);
> + jpeg_set_dec_scaling(jpeg->regs, 0, 0);
> + jpeg_jpgadr(jpeg->regs, src_addr);
> + if (ctx->cap_q.fmt->fourcc == V4L2_PIX_FMT_YUYV) {
> + jpeg_dec_imgadr(jpeg->regs, dst_addr,
> + S5P_JPEG_RAW_OUT_422,
> + ctx->out_q.w, ctx->out_q.h);
> + jpeg_outform_raw(jpeg->regs, S5P_JPEG_RAW_OUT_422);
> + } else {
> + jpeg_dec_imgadr(jpeg->regs, dst_addr,
> + S5P_JPEG_RAW_OUT_420,
> + ctx->out_q.w, ctx->out_q.h);
> + jpeg_outform_raw(jpeg->regs, S5P_JPEG_RAW_OUT_420);
> + }
This looks like this patch: http://patchwork.linuxtv.org/patch/10004/
If you applied it to version 2x, it would be nice if you applied it
to version 3, too.
> + jpeg_set_dec_bitstream_size(jpeg->regs,
> + ctx->out_q.size / 32 + 1);
> + }
> + jpeg_proc_mode(jpeg->regs, ctx->mode);
> +}
> +
> +void s5p_jpeg_runtime_resume_execute(struct device *dev)
> +{
> +
> +}
<...>
^ permalink raw reply [flat|nested] 4+ messages in thread
* RE: [PATCH] media: jpeg: add driver for a version 2.x of jpeg H/W
2012-03-01 23:46 [PATCH] media: jpeg: add driver for a version 2.x of jpeg H/W 송영목
2012-03-03 12:37 ` Sylwester Nawrocki
2012-03-05 13:59 ` Andrzej Pietrasiewicz
@ 2012-03-06 6:31 ` Andrzej Pietrasiewicz
2 siblings, 0 replies; 4+ messages in thread
From: Andrzej Pietrasiewicz @ 2012-03-06 6:31 UTC (permalink / raw)
To: Andrzej Pietrasiewicz, '송영목',
linux-media
Cc: mchehab
On Monday, March 05, 2012 3:00 PM Andrzej Pietrasiewicz wrote:
I forgot to sign my last post. One might think I was being rude.
So I fix it below.
>
> Hello송영목,
>
>
> In general I think the v2x support should be designed to require
> as little code changes as possible, and they should be related
> to pure hardware differences only. Please see comments inline.
>
> The tables (quantization, Huffman) logically contain mostly the
> same data both in v3 and v2x and are defined by respective
> standards. Only the arrangement of data is slightly different
> (bytes vs 4-byte words). Please see comments inline.
>
> On, March 02, 2012 12:47 AM 송영목 wrote:
>
> <...>
>
> > diff --git a/drivers/media/video/s5p-jpeg/jpeg-core.c
> > b/drivers/media/video/s5p-jpeg/jpeg-core.c
> > index 1105a87..cf917cd 100644
> > --- a/drivers/media/video/s5p-jpeg/jpeg-core.c
> > +++ b/drivers/media/video/s5p-jpeg/jpeg-core.c
>
> <...>
> > diff --git a/drivers/media/video/s5p-jpeg/jpeg-hw-v2x.h
> <...>
> > @@ -0,0 +1,387 @@
> <...>
> > +
> > +#define S5P_JPEG_MIN_WIDTH 32
> > +#define S5P_JPEG_MIN_HEIGHT 32
> > +#define S5P_JPEG_MAX_WIDTH 8192
> > +#define S5P_JPEG_MAX_HEIGHT 8192
> > +#define S5P_JPEG_ENCODE 0
> > +#define S5P_JPEG_DECODE 1
> > +#define S5P_JPEG_RAW_IN_565 0
> > +#define S5P_JPEG_RAW_IN_422 1
> > +#define S5P_JPEG_SUBSAMPLING_422 0
> > +#define S5P_JPEG_SUBSAMPLING_420 1
> > +#define S5P_JPEG_RAW_OUT_422 0
> > +#define S5P_JPEG_RAW_OUT_420 1
>
> This is a verbatim copy of what is defined in jpeg-hw-common.h
> and should not be repeated here. Use jpeg-hw-common.h.
>
> > +/* Q-table for JPEG */
> > +/* ITU standard Q-table */
> > +static unsigned int ITU_Q_tbl[4][16] = {
> > + {
> > + 0x01010101, 0x01020303, 0x01010101, 0x01030303, /* Y */
> > + 0x01010101, 0x02030303, 0x01010101, 0x03040403,
> > + 0x01010203, 0x03050504, 0x01020303, 0x04050605,
> > + 0x02030404, 0x05060605, 0x04050505, 0x06050505
> > + } , {
> > + 0x01010102, 0x05050505, 0x01010103, 0x05050505, /* CbCr */
> > + 0x01010503, 0x05050505, 0x02030505, 0x05050505,
> > + 0x05050505, 0x05050505, 0x05050505, 0x05050505,
> > + 0x05050505, 0x05050505, 0x05050505, 0x05050505
> > + } , {
> > + 0x05020205, 0x0a161e25, 0x02020307, 0x0c232521, /* Y */
> > + 0x0302050a, 0x16222b22, 0x0305090e, 0x1e393326,
> > + 0x06091422, 0x2a384431, 0x0a122118, 0x34454b3c,
> > + 0x1d283238, 0x44525142, 0x2d3c3e40, 0x4a424441
> > + } , {
> > + 0x05020205, 0x251e160a, 0x07030202, 0x2125230c, /* CbCr */
> > + 0x0a050203, 0x222b2216, 0x0e090503, 0x2633391e,
> > + 0x22140906, 0x3144382a, 0x1821120a, 0x3c4b4534,
> > + 0x3832281d, 0x42515244, 0x403e3c2d, 0x4144424a
> > + }
> > +};
>
> This array is static so this makes all users of this header file
> allocate it. Why not put it into jpeg-v2x.c? (however, see
> below for considerations about duplication)
> This comment applies to all array definitions of this kind
> in this file.
>
> > +
> > +/* ITU Luminace Huffman Table */
> > +static unsigned int ITU_H_tbl_len_DC_luminance[4] = {
> > + 0x01050100, 0x01010101, 0x00000001, 0x00000000
> > +};
>
> This is in fact the same thing as hdctbl0[16] in jpeg v3,
> only arranged in 4-byte words. It would be nice if
> the same definitions were used in both versions. This applies
> to all tables defined here.
>
> > +static unsigned int ITU_H_tbl_val_DC_luminance[3] = {
> > + 0x03020100, 0x07060504, 0x0b0a0908
> > +};
>
> The same thing as hdctblg0[12] in jpeg v3.
>
> <...>
>
> > +static unsigned int ITU_H_tbl_val_DC_chrominance[3] = {
> > + 0x03020100, 0x07060504, 0x0b0a0908
> > +};
>
> The same thing as as hdctblg0[12] in jpeg v3 and
> ITU_H_tbl_val_DC_luminance[3] in your code.
>
> > +
> > +static unsigned int ITU_H_tbl_len_AC_luminance[4] = {
> > + 0x03010200, 0x03040203, 0x04040505, 0x7d010000
> > +};
> > +
>
> The same thing as hactbl0[16] in jpeg v3.
>
> > +static unsigned int ITU_H_tbl_val_AC_luminance[41] = {
> > + 0x00030201, 0x12051104, 0x06413121, 0x07615113,
> > + 0x32147122, 0x08a19181, 0xc1b14223, 0xf0d15215,
> > + 0x72623324, 0x160a0982, 0x1a191817, 0x28272625,
> > + 0x35342a29, 0x39383736, 0x4544433a, 0x49484746,
> > + 0x5554534a, 0x59585756, 0x6564635a, 0x69686766,
> > + 0x7574736a, 0x79787776, 0x8584837a, 0x89888786,
> > + 0x9493928a, 0x98979695, 0xa3a29a99, 0xa7a6a5a4,
> > + 0xb2aaa9a8, 0xb6b5b4b3, 0xbab9b8b7, 0xc5c4c3c2,
> > + 0xc9c8c7c6, 0xd4d3d2ca, 0xd8d7d6d5, 0xe2e1dad9,
> > + 0xe6e5e4e3, 0xeae9e8e7, 0xf4f3f2f1, 0xf8f7f6f5,
> > + 0x0000faf9
> > +};
> > +
>
> The same thing as hactblg0[162] in jpeg v3.
>
> <...>
>
> > +
> > +static inline void jpeg_reset(void __iomem *regs)
> > +{
> > + unsigned long reg;
> > +
> > + reg = readl(regs + S5P_JPEG_CNTL_REG);
> > + writel(reg & ~S5P_JPEG_SOFT_RESET_HI,
> > + regs + S5P_JPEG_CNTL_REG);
> > +
> > + ndelay(100000);
>
> Why not use usleep_range?
>
> <...>
>
> > +static inline void jpeg_proc_mode(void __iomem *regs, unsigned long
mode)
> > +{
> > + unsigned int reg, m;
> > +
> > + m = S5P_JPEG_DEC_MODE;
> > + if (mode == S5P_JPEG_ENCODE)
> > + m = S5P_JPEG_ENC_MODE;
> > + else
> > + m = S5P_JPEG_DEC_MODE;
> > +
> > + reg = readl(regs + S5P_JPEG_CNTL_REG);
> > + reg &= S5P_JPEG_ENC_DEC_MODE_MASK;
> > + reg |= m;
> > +
> > + writel(reg, regs + S5P_JPEG_CNTL_REG);
> > +}
> > +
>
> This function is in fact an exact copy of its counterpart in v3.
> The difference is in the name of the constant which names the
> register (S5P_JPEG_CNTL_REG vs S5P_JPEGMOD), however,
> the value of this constant is 0x00 in both cases. The
> numeric values of ENC/COMPR and DEC/DECOMPR constants are different,
> but I believe this could be mitigated some other way.
> What is important is that the 2 functions serve the same purpose
> and so should be factored out to some common code.
>
> <...>
>
> > +static inline void jpeg_subsampling_mode(void __iomem *regs, unsigned
long
> > mode)
> > +{
> > + unsigned long reg, m;
> > +
> > + m = S5P_JPEG_ENC_FMT_YUV_422;
> > + if (mode == S5P_JPEG_SUBSAMPLING_422)
> > + m = S5P_JPEG_ENC_FMT_YUV_422;
> > + else if (mode == S5P_JPEG_SUBSAMPLING_420)
> > + m = S5P_JPEG_ENC_FMT_YUV_420;
> > +
> > + reg = readl(regs + S5P_JPEG_IMG_FMT_REG);
> > + reg &= ~S5P_JPEG_ENC_FMT_MASK;
> > + reg |= m;
> > +
> > + writel(reg, regs + S5P_JPEG_IMG_FMT_REG);
> > +}
> > +
>
> The same here.
>
> <...>
>
> > +
> > +static inline void jpeg_jpgadr(void __iomem *regs, unsigned long addr)
> > +{
> > + writel(addr, regs + S5P_JPEG_OUT_MEM_BASE_REG);
> > +}
> > +
>
> The same here.
>
> <...>
>
> > +static inline void jpeg_enc_imgadr(void __iomem *regs, unsigned long
addr)
> > +{
> > + writel(addr, regs + S5P_JPEG_IMG_BA_PLANE_1_REG);
> > +}
> > +
>
> This looks like jpeg_imgadr() from v3.
>
>
> <...>
>
> > diff --git a/drivers/media/video/s5p-jpeg/jpeg-regs-v2x.h
> > b/drivers/media/video/s5p-jpeg/jpeg-regs-v2x.h
> > new file mode 100644
> > index 0000000..8305475
> > --- /dev/null
> > +++ b/drivers/media/video/s5p-jpeg/jpeg-regs-v2x.h
> > @@ -0,0 +1,150 @@
> > +/* linux/drivers/media/video/s5p-jpeg/jpeg-regs-v2x.h
> > + *
> > + * Register definition file for Samsung JPEG codec driver
> > + *
> > + * Copyright (c) 2012 Samsung Electronics Co., Ltd.
> > + * http:www.samsung.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.
> > + */
> > +
> > +#ifndef JPEG_REGS_H_
> > +#define JPEG_REGS_H_
> > +
> > +/* JPEG Codec Control Registers */
> > +#define S5P_JPEG_CNTL_REG 0x00
> > +#define S5P_JPEG_INT_EN_REG 0x04
> > +#define S5P_JPEG_INT_STATUS_REG 0x0c
> > +#define S5P_JPEG_OUT_MEM_BASE_REG 0x10
> > +#define S5P_JPEG_IMG_SIZE_REG 0x14
> > +#define S5P_JPEG_IMG_BA_PLANE_1_REG 0x18
> > +#define S5P_JPEG_IMG_BA_PLANE_2_REG 0x24
> > +#define S5P_JPEG_IMG_BA_PLANE_3_REG 0x30
> > +
> > +#define S5P_JPEG_TBL_SEL_REG 0x3c
> > +
> > +#define S5P_JPEG_IMG_FMT_REG 0x40
> > +
> > +#define S5P_JPEG_BITSTREAM_SIZE_REG 0x44
> > +#define S5P_JPEG_HUFF_CNT_REG 0x4c
> > +
> > +#define S5P_JPEG_QUAN_TBL_ENTRY_REG 0x100
> > +#define S5P_JPEG_HUFF_TBL_ENTRY_REG 0x200
> > +
> > +
> > +/****************************************************************/
> > +/* Bit definition part
> > */
> > +/****************************************************************/
> > +
> > +/* JPEG CNTL Register bit */
> > +#define S5P_JPEG_ENC_DEC_MODE_MASK (0xfffffffc << 0)
> > +#define S5P_JPEG_DEC_MODE (1 << 0)
> > +#define S5P_JPEG_ENC_MODE (1 << 1)
> > +#define S5P_JPEG_HUF_TBL_EN (1 << 19)
> > +#define S5P_JPEG_HOR_SCALING_SHIFT 20
> > +#define S5P_JPEG_HOR_SCALING_MASK \
> > + (3 << S5P_JPEG_HOR_SCALING_SHIFT)
> > +#define S5P_JPEG_HOR_SCALING(x) \
> > + (((x) & 0x3) << S5P_JPEG_HOR_SCALING_SHIFT)
> > +#define S5P_JPEG_VER_SCALING_SHIFT 22
> > +#define S5P_JPEG_VER_SCALING_MASK \
> > + (3 << S5P_JPEG_VER_SCALING_SHIFT)
> > +#define S5P_JPEG_VER_SCALING(x) \
> > + (((x) & 0x3) << S5P_JPEG_VER_SCALING_SHIFT)
> > +#define S5P_JPEG_SOFT_RESET_HI (1 << 29)
> > +
> > +/* JPEG INT Register bit */
> > +#define S5P_JPEG_INT_EN_MASK (0x1f << 0)
> > +#define S5P_JPEG_INT_EN_ALL (0x1f << 0)
> > +
> > +/* JPEG IMAGE SIZE Register bit */
> > +#define S5P_JPEG_X_SIZE_SHIFT 0
> > +#define S5P_JPEG_X_SIZE_MASK (0xffff <<
S5P_JPEG_X_SIZE_SHIFT)
> > +#define S5P_JPEG_X_SIZE(x) \
> > + (((x) & 0xffff) << S5P_JPEG_X_SIZE_SHIFT)
> > +#define S5P_JPEG_Y_SIZE_SHIFT 16
> > +#define S5P_JPEG_Y_SIZE_MASK (0xffff <<
S5P_JPEG_Y_SIZE_SHIFT)
> > +#define S5P_JPEG_Y_SIZE(x) \
> > + (((x) & 0xffff) << S5P_JPEG_Y_SIZE_SHIFT)
> > +
> > +/* JPEG IMAGE FORMAT Register bit */
> > +#define S5P_JPEG_ENC_IN_FMT_MASK 0xffff0000
> > +#define S5P_JPEG_ENC_RGB_IMG (1 << 0)
>
> This is used only in one place in jpeg_input_raw_mode together with
>
> <...>
>
> this:
> > +#define S5P_JPEG_RGB_IP_RGB_16BIT_IMG (4 <<
> S5P_JPEG_RGB_IP_SHIFT)
>
> To form one constant, while
>
>
> > +#define S5P_JPEG_YUV_422_IP_YUV_422_1P_IMG \
> > + (4 << S5P_JPEG_YUV_422_IP_SHIFT)
>
> is only used in two places to form another constant.
>
> If the constants were defined not combined from parts then
> jpeg_input_raw_mode is effectively the same as in v3.
> And a good candidate to factor out to some common code.
>
> > +
> > +#define S5P_JPEG_YUV_420_IP_SHIFT 15
> > +#define S5P_JPEG_YUV_420_IP_MASK (7 <<
S5P_JPEG_YUV_420_IP_SHIFT)
> > +#define S5P_JPEG_YUV_420_IP_YUV_420_3P_IMG \
> > + (5 << S5P_JPEG_YUV_420_IP_SHIFT)
> > +
> > +#define S5P_JPEG_ENC_FMT_SHIFT 24
> > +#define S5P_JPEG_ENC_FMT_MASK (3 <<
S5P_JPEG_ENC_FMT_SHIFT)
> > +#define S5P_JPEG_ENC_FMT_YUV_444 (1 <<
S5P_JPEG_ENC_FMT_SHIFT)
> > +#define S5P_JPEG_ENC_FMT_YUV_422 (2 <<
S5P_JPEG_ENC_FMT_SHIFT)
> > +#define S5P_JPEG_ENC_FMT_YUV_420 (3 <<
S5P_JPEG_ENC_FMT_SHIFT)
> > +
> > +/* JPEG TBL SEL Register bit */
> > +#define S5P_JPEG_Q_TBL_COMP1_SHIFT 0
> > +#define S5P_JPEG_Q_TBL_COMP1_0 (0 <<
S5P_JPEG_Q_TBL_COMP1_SHIFT)
> > +#define S5P_JPEG_Q_TBL_COMP1_1 (1 <<
S5P_JPEG_Q_TBL_COMP1_SHIFT)
> > +#define S5P_JPEG_Q_TBL_COMP1_2 (2 <<
S5P_JPEG_Q_TBL_COMP1_SHIFT)
> > +#define S5P_JPEG_Q_TBL_COMP1_3 (3 <<
S5P_JPEG_Q_TBL_COMP1_SHIFT)
> > +
> > +#define S5P_JPEG_Q_TBL_COMP2_SHIFT 2
> > +#define S5P_JPEG_Q_TBL_COMP2_0 (0 <<
S5P_JPEG_Q_TBL_COMP2_SHIFT)
> > +#define S5P_JPEG_Q_TBL_COMP2_1 (1 <<
S5P_JPEG_Q_TBL_COMP2_SHIFT)
> > +#define S5P_JPEG_Q_TBL_COMP2_2 (2 <<
S5P_JPEG_Q_TBL_COMP2_SHIFT)
> > +#define S5P_JPEG_Q_TBL_COMP2_3 (3 <<
S5P_JPEG_Q_TBL_COMP2_SHIFT)
> > +
> > +#define S5P_JPEG_Q_TBL_COMP3_SHIFT 4
> > +#define S5P_JPEG_Q_TBL_COMP3_0 (0 <<
S5P_JPEG_Q_TBL_COMP3_SHIFT)
> > +#define S5P_JPEG_Q_TBL_COMP3_1 (1 <<
S5P_JPEG_Q_TBL_COMP2_SHIFT)
> > +#define S5P_JPEG_Q_TBL_COMP3_2 (2 <<
S5P_JPEG_Q_TBL_COMP2_SHIFT)
> > +#define S5P_JPEG_Q_TBL_COMP3_3 (3 <<
S5P_JPEG_Q_TBL_COMP2_SHIFT)
> > +
> > +#define S5P_JPEG_HUFF_TBL_COMP1_SHIFT 6
> > +#define S5P_JPEG_HUFF_TBL_COMP1_AC_0_DC_0 \
> > + (0 << S5P_JPEG_HUFF_TBL_COMP1_SHIFT)
> > +#define S5P_JPEG_HUFF_TBL_COMP1_AC_0_DC_1 \
> > + (1 << S5P_JPEG_HUFF_TBL_COMP1_SHIFT)
> > +#define S5P_JPEG_HUFF_TBL_COMP1_AC_1_DC_0 \
> > + (2 << S5P_JPEG_HUFF_TBL_COMP1_SHIFT)
> > +#define S5P_JPEG_HUFF_TBL_COMP1_AC_1_DC_1 \
> > + (3 << S5P_JPEG_HUFF_TBL_COMP1_SHIFT)
> > +
> > +#define S5P_JPEG_HUFF_TBL_COMP2_SHIFT 8
> > +#define S5P_JPEG_HUFF_TBL_COMP2_AC_0_DC_0 \
> > + (0 << S5P_JPEG_HUFF_TBL_COMP2_SHIFT)
> > +#define S5P_JPEG_HUFF_TBL_COMP2_AC_0_DC_1 \
> > + (1 << S5P_JPEG_HUFF_TBL_COMP2_SHIFT)
> > +#define S5P_JPEG_HUFF_TBL_COMP2_AC_1_DC_0 \
> > + (2 << S5P_JPEG_HUFF_TBL_COMP2_SHIFT)
> > +#define S5P_JPEG_HUFF_TBL_COMP2_AC_1_DC_1 \
> > + (3 << S5P_JPEG_HUFF_TBL_COMP2_SHIFT)
> > +
> > +#define S5P_JPEG_HUFF_TBL_COMP3_SHIFT 10
> > +#define S5P_JPEG_HUFF_TBL_COMP3_AC_0_DC_0 \
> > + (0 << S5P_JPEG_HUFF_TBL_COMP3_SHIFT)
> > +#define S5P_JPEG_HUFF_TBL_COMP3_AC_0_DC_1 \
> > + (1 << S5P_JPEG_HUFF_TBL_COMP3_SHIFT)
> > +#define S5P_JPEG_HUFF_TBL_COMP3_AC_1_DC_0 \
> > + (2 << S5P_JPEG_HUFF_TBL_COMP3_SHIFT)
> > +#define S5P_JPEG_HUFF_TBL_COMP3_AC_1_DC_1 \
> > + (3 << S5P_JPEG_HUFF_TBL_COMP3_SHIFT)
> > +
>
> Perhaps you could use some smarter macros, e.g. with parameters?
>
>
> > +#endif /* JPEG_REGS_H_ */
> > diff --git a/drivers/media/video/s5p-jpeg/jpeg-v2x.c
> > b/drivers/media/video/s5p-jpeg/jpeg-v2x.c
> > new file mode 100644
> > index 0000000..71bd38b
> > --- /dev/null
> > +++ b/drivers/media/video/s5p-jpeg/jpeg-v2x.c
> > @@ -0,0 +1,129 @@
> > +/* linux/drivers/media/video/s5p-jpeg/jpeg-v2x.c
> > + *
> > + * Copyright (c) 2012 Samsung Electronics Co., Ltd.
> > + * http://www.samsung.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.
> > + */
> > +
> > +#include <linux/clk.h>
> > +#include <linux/err.h>
> > +#include <linux/gfp.h>
> > +#include <linux/interrupt.h>
> > +#include <linux/io.h>
> > +#include <linux/kernel.h>
> > +#include <linux/module.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/pm_runtime.h>
> > +#include <linux/slab.h>
> > +#include <linux/spinlock.h>
> > +#include <linux/string.h>
> > +#include <media/v4l2-mem2mem.h>
> > +#include <media/v4l2-ioctl.h>
> > +#include <media/videobuf2-core.h>
> > +#include <media/videobuf2-dma-contig.h>
> > +
> > +#include "jpeg-core.h"
> > +#include "jpeg-hw-v2x.h"
> > +
> > +/*
> > + *
> >
============================================================================
> > + * mem2mem callbacks
> > + *
> >
============================================================================
> > + */
> > +
> > +void s5p_jpeg_irq_execute(void *dev_id)
> > +{
> > + struct s5p_jpeg *jpeg = dev_id;
> > + struct s5p_jpeg_ctx *curr_ctx;
> > + struct vb2_buffer *src_buf, *dst_buf;
> > + unsigned long payload_size = 0;
> > + enum vb2_buffer_state state = VB2_BUF_STATE_DONE;
> > +
> > + unsigned int int_status;
> > +
> > + curr_ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev);
> > +
> > + src_buf = v4l2_m2m_src_buf_remove(curr_ctx->m2m_ctx);
> > + dst_buf = v4l2_m2m_dst_buf_remove(curr_ctx->m2m_ctx);
> > +
> > + int_status = jpeg_get_int_status(jpeg->regs);
> > +
> > + if (int_status != 0x2)
> > + state = VB2_BUF_STATE_ERROR;
> > +
> > + v4l2_m2m_buf_done(src_buf, state);
> > + if (curr_ctx->mode == S5P_JPEG_ENCODE && int_status == 0x2) {
> > + payload_size = jpeg_compressed_size(jpeg->regs);
> > + vb2_set_plane_payload(dst_buf, 0, payload_size);
> > + }
> > + v4l2_m2m_buf_done(dst_buf, state);
> > + v4l2_m2m_job_finish(jpeg->m2m_dev, curr_ctx->m2m_ctx);
> > +}
> > +
>
> This function is almost the same as its counterpart in jpeg v3.
> The difference is only in reading the interrupt cause, while
> mem2mem operations are exacty the same. This makes maintenance
> more difficult: whenever mem2mem usage changes, it needs to be
> updated in 2 places. I think that wherever mem2mem operations are
> the same in v2 and v3, they should be factored out to some common
> code.
>
> > +void s5p_jpeg_execute(void *priv)
> > +{
> > + struct s5p_jpeg_ctx *ctx = priv;
> > + struct s5p_jpeg *jpeg = ctx->jpeg;
> > + struct vb2_buffer *src_buf, *dst_buf;
> > + unsigned long src_addr, dst_addr;
> > +
> > + src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
> > + dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
> > +
> > + src_addr = vb2_dma_contig_plane_dma_addr(src_buf, 0);
> > + dst_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0);
> > +
> > + jpeg_reset(jpeg->regs);
> > + jpeg_set_interrupt(jpeg->regs);
> > +
> > + if (ctx->mode == S5P_JPEG_ENCODE) {
> > + jpeg_set_huf_table_enable(jpeg->regs, 1);
> > + jpeg_qtbl(jpeg->regs);
> > + jpeg_htbl_ac(jpeg->regs);
> > + jpeg_htbl_dc(jpeg->regs);
> > + jpeg_set_encode_tbl_select(jpeg->regs, ctx->compr_quality);
> > + jpeg_x_y(jpeg->regs, ctx->out_q.w, ctx->out_q.h);
> > +
> > + if (ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB565)
> > + jpeg_input_raw_mode(jpeg->regs,
S5P_JPEG_RAW_IN_565);
> > + else
> > + jpeg_input_raw_mode(jpeg->regs,
S5P_JPEG_RAW_IN_422);
> > + if (ctx->cap_q.fmt->fourcc == V4L2_PIX_FMT_YUYV)
> > + jpeg_subsampling_mode(jpeg->regs,
> > + S5P_JPEG_SUBSAMPLING_422);
> > + else
> > + jpeg_subsampling_mode(jpeg->regs,
> > + S5P_JPEG_SUBSAMPLING_420);
> > +
> > + jpeg_enc_imgadr(jpeg->regs, src_addr);
> > + jpeg_jpgadr(jpeg->regs, dst_addr);
> > + jpeg_set_encode_hoff_cnt(jpeg->regs);
>
> This part is almost a verbatim copy of its counterpart from v3,
> only the sequence of operations is different and some calls are
> grouped into separate functions (e.g. jpeg_htbl_ac, jpeg_htbl_dc,
> jpeg_qtbl). Why not factor out into some common piece of code?
>
> > + } else {
> > + jpeg_set_encode_tbl_select(jpeg->regs, 0);
> > + jpeg_set_dec_scaling(jpeg->regs, 0, 0);
> > + jpeg_jpgadr(jpeg->regs, src_addr);
> > + if (ctx->cap_q.fmt->fourcc == V4L2_PIX_FMT_YUYV) {
> > + jpeg_dec_imgadr(jpeg->regs, dst_addr,
> > + S5P_JPEG_RAW_OUT_422,
> > + ctx->out_q.w, ctx->out_q.h);
> > + jpeg_outform_raw(jpeg->regs, S5P_JPEG_RAW_OUT_422);
> > + } else {
> > + jpeg_dec_imgadr(jpeg->regs, dst_addr,
> > + S5P_JPEG_RAW_OUT_420,
> > + ctx->out_q.w, ctx->out_q.h);
> > + jpeg_outform_raw(jpeg->regs, S5P_JPEG_RAW_OUT_420);
> > + }
>
> This looks like this patch: http://patchwork.linuxtv.org/patch/10004/
> If you applied it to version 2x, it would be nice if you applied it
> to version 3, too.
>
>
> > + jpeg_set_dec_bitstream_size(jpeg->regs,
> > + ctx->out_q.size / 32 + 1);
> > + }
> > + jpeg_proc_mode(jpeg->regs, ctx->mode);
> > +}
> > +
> > +void s5p_jpeg_runtime_resume_execute(struct device *dev)
> > +{
> > +
> > +}
>
> <...>
>
Andrzej
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2012-03-06 6:32 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-03-01 23:46 [PATCH] media: jpeg: add driver for a version 2.x of jpeg H/W 송영목
2012-03-03 12:37 ` Sylwester Nawrocki
2012-03-05 13:59 ` Andrzej Pietrasiewicz
2012-03-06 6:31 ` Andrzej Pietrasiewicz
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox