Commit 7c15fd4b authored by Andrzej Pietrasiewicz's avatar Andrzej Pietrasiewicz Committed by Mauro Carvalho Chehab

[media] s5p-jpeg: add 5420 family support

JPEG IP found in Exynos5420 is similar to what is in Exynos3250, but
there are some subtle differences which this patch takes into account.
Signed-off-by: default avatarAndrzej Pietrasiewicz <andrzej.p@samsung.com>
Signed-off-by: default avatarSylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@osg.samsung.com>
parent 4eb297e0
...@@ -4,7 +4,7 @@ Required properties: ...@@ -4,7 +4,7 @@ Required properties:
- compatible : should be one of: - compatible : should be one of:
"samsung,s5pv210-jpeg", "samsung,exynos4210-jpeg", "samsung,s5pv210-jpeg", "samsung,exynos4210-jpeg",
"samsung,exynos3250-jpeg"; "samsung,exynos3250-jpeg", "samsung,exynos5420-jpeg";
- reg : address and length of the JPEG codec IP register set; - reg : address and length of the JPEG codec IP register set;
- interrupts : specifies the JPEG codec IP interrupt; - interrupts : specifies the JPEG codec IP interrupt;
- clock-names : should contain: - clock-names : should contain:
......
...@@ -621,6 +621,7 @@ static int s5p_jpeg_to_user_subsampling(struct s5p_jpeg_ctx *ctx) ...@@ -621,6 +621,7 @@ static int s5p_jpeg_to_user_subsampling(struct s5p_jpeg_ctx *ctx)
return V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY; return V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY;
return ctx->subsampling; return ctx->subsampling;
case SJPEG_EXYNOS3250: case SJPEG_EXYNOS3250:
case SJPEG_EXYNOS5420:
if (ctx->subsampling > 3) if (ctx->subsampling > 3)
return V4L2_JPEG_CHROMA_SUBSAMPLING_411; return V4L2_JPEG_CHROMA_SUBSAMPLING_411;
return exynos3250_decoded_subsampling[ctx->subsampling]; return exynos3250_decoded_subsampling[ctx->subsampling];
...@@ -1142,13 +1143,13 @@ static void jpeg_bound_align_image(struct s5p_jpeg_ctx *ctx, ...@@ -1142,13 +1143,13 @@ static void jpeg_bound_align_image(struct s5p_jpeg_ctx *ctx,
w_step = 1 << walign; w_step = 1 << walign;
h_step = 1 << halign; h_step = 1 << halign;
if (ctx->jpeg->variant->version == SJPEG_EXYNOS3250) { if (ctx->jpeg->variant->hw3250_compat) {
/* /*
* Rightmost and bottommost pixels are cropped by the * Rightmost and bottommost pixels are cropped by the
* Exynos3250 JPEG IP for RGB formats, for the specific * Exynos3250/compatible JPEG IP for RGB formats, for the
* width and height values respectively. This assignment * specific width and height values respectively. This
* will result in v4l_bound_align_image returning dimensions * assignment will result in v4l_bound_align_image returning
* reduced by 1 for the aforementioned cases. * dimensions reduced by 1 for the aforementioned cases.
*/ */
if (w_step == 4 && ((width & 3) == 1)) { if (w_step == 4 && ((width & 3) == 1)) {
wmax = width; wmax = width;
...@@ -1384,12 +1385,12 @@ static int s5p_jpeg_s_fmt(struct s5p_jpeg_ctx *ct, struct v4l2_format *f) ...@@ -1384,12 +1385,12 @@ static int s5p_jpeg_s_fmt(struct s5p_jpeg_ctx *ct, struct v4l2_format *f)
/* /*
* Prevent downscaling to YUV420 format by more than 2 * Prevent downscaling to YUV420 format by more than 2
* for Exynos3250 SoC as it produces broken raw image * for Exynos3250/compatible SoC as it produces broken raw image
* in such cases. * in such cases.
*/ */
if (ct->mode == S5P_JPEG_DECODE && if (ct->mode == S5P_JPEG_DECODE &&
f_type == FMT_TYPE_CAPTURE && f_type == FMT_TYPE_CAPTURE &&
ct->jpeg->variant->version == SJPEG_EXYNOS3250 && ct->jpeg->variant->hw3250_compat &&
pix->pixelformat == V4L2_PIX_FMT_YUV420 && pix->pixelformat == V4L2_PIX_FMT_YUV420 &&
ct->scale_factor > 2) { ct->scale_factor > 2) {
scale_rect.width = ct->out_q.w / 2; scale_rect.width = ct->out_q.w / 2;
...@@ -1569,12 +1570,12 @@ static int s5p_jpeg_s_selection(struct file *file, void *fh, ...@@ -1569,12 +1570,12 @@ static int s5p_jpeg_s_selection(struct file *file, void *fh,
if (s->target == V4L2_SEL_TGT_COMPOSE) { if (s->target == V4L2_SEL_TGT_COMPOSE) {
if (ctx->mode != S5P_JPEG_DECODE) if (ctx->mode != S5P_JPEG_DECODE)
return -EINVAL; return -EINVAL;
if (ctx->jpeg->variant->version == SJPEG_EXYNOS3250) if (ctx->jpeg->variant->hw3250_compat)
ret = exynos3250_jpeg_try_downscale(ctx, rect); ret = exynos3250_jpeg_try_downscale(ctx, rect);
} else if (s->target == V4L2_SEL_TGT_CROP) { } else if (s->target == V4L2_SEL_TGT_CROP) {
if (ctx->mode != S5P_JPEG_ENCODE) if (ctx->mode != S5P_JPEG_ENCODE)
return -EINVAL; return -EINVAL;
if (ctx->jpeg->variant->version == SJPEG_EXYNOS3250) if (ctx->jpeg->variant->hw3250_compat)
ret = exynos3250_jpeg_try_crop(ctx, rect); ret = exynos3250_jpeg_try_crop(ctx, rect);
} }
...@@ -1604,8 +1605,9 @@ static int s5p_jpeg_adjust_subs_ctrl(struct s5p_jpeg_ctx *ctx, int *ctrl_val) ...@@ -1604,8 +1605,9 @@ static int s5p_jpeg_adjust_subs_ctrl(struct s5p_jpeg_ctx *ctx, int *ctrl_val)
case SJPEG_S5P: case SJPEG_S5P:
return 0; return 0;
case SJPEG_EXYNOS3250: case SJPEG_EXYNOS3250:
case SJPEG_EXYNOS5420:
/* /*
* The exynos3250 device can produce JPEG image only * The exynos3250/compatible device can produce JPEG image only
* of 4:4:4 subsampling when given RGB32 source image. * of 4:4:4 subsampling when given RGB32 source image.
*/ */
if (ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB32) if (ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB32)
...@@ -1624,7 +1626,7 @@ static int s5p_jpeg_adjust_subs_ctrl(struct s5p_jpeg_ctx *ctx, int *ctrl_val) ...@@ -1624,7 +1626,7 @@ static int s5p_jpeg_adjust_subs_ctrl(struct s5p_jpeg_ctx *ctx, int *ctrl_val)
} }
/* /*
* The exynos4x12 and exynos3250 devices require resulting * The exynos4x12 and exynos3250/compatible devices require resulting
* jpeg subsampling not to be lower than the input raw image * jpeg subsampling not to be lower than the input raw image
* subsampling. * subsampling.
*/ */
...@@ -2017,6 +2019,16 @@ static void exynos3250_jpeg_device_run(void *priv) ...@@ -2017,6 +2019,16 @@ static void exynos3250_jpeg_device_run(void *priv)
exynos3250_jpeg_qtbl(jpeg->regs, 2, 1); exynos3250_jpeg_qtbl(jpeg->regs, 2, 1);
exynos3250_jpeg_qtbl(jpeg->regs, 3, 1); exynos3250_jpeg_qtbl(jpeg->regs, 3, 1);
/*
* Some SoCs require setting Huffman tables before each run
*/
if (jpeg->variant->htbl_reinit) {
s5p_jpeg_set_hdctbl(jpeg->regs);
s5p_jpeg_set_hdctblg(jpeg->regs);
s5p_jpeg_set_hactbl(jpeg->regs);
s5p_jpeg_set_hactblg(jpeg->regs);
}
/* Y, Cb, Cr use Huffman table 0 */ /* Y, Cb, Cr use Huffman table 0 */
exynos3250_jpeg_htbl_ac(jpeg->regs, 1); exynos3250_jpeg_htbl_ac(jpeg->regs, 1);
exynos3250_jpeg_htbl_dc(jpeg->regs, 1); exynos3250_jpeg_htbl_dc(jpeg->regs, 1);
...@@ -2660,13 +2672,12 @@ static int s5p_jpeg_runtime_resume(struct device *dev) ...@@ -2660,13 +2672,12 @@ static int s5p_jpeg_runtime_resume(struct device *dev)
/* /*
* JPEG IP allows storing two Huffman tables for each component. * JPEG IP allows storing two Huffman tables for each component.
* We fill table 0 for each component and do this here only * We fill table 0 for each component and do this here only
* for S5PC210 and Exynos3250 SoCs. Exynos4x12 SoC requires * for S5PC210 and Exynos3250 SoCs. Exynos4x12 and Exynos542x SoC
* programming its Huffman tables each time the encoding process * require programming their Huffman tables each time the encoding
* is initialized, and thus it is accomplished in the device_run * process is initialized, and thus it is accomplished in the
* callback of m2m_ops. * device_run callback of m2m_ops.
*/ */
if (jpeg->variant->version == SJPEG_S5P || if (!jpeg->variant->htbl_reinit) {
jpeg->variant->version == SJPEG_EXYNOS3250) {
s5p_jpeg_set_hdctbl(jpeg->regs); s5p_jpeg_set_hdctbl(jpeg->regs);
s5p_jpeg_set_hdctblg(jpeg->regs); s5p_jpeg_set_hdctblg(jpeg->regs);
s5p_jpeg_set_hactbl(jpeg->regs); s5p_jpeg_set_hactbl(jpeg->regs);
...@@ -2714,6 +2725,7 @@ static struct s5p_jpeg_variant exynos3250_jpeg_drvdata = { ...@@ -2714,6 +2725,7 @@ static struct s5p_jpeg_variant exynos3250_jpeg_drvdata = {
.jpeg_irq = exynos3250_jpeg_irq, .jpeg_irq = exynos3250_jpeg_irq,
.m2m_ops = &exynos3250_jpeg_m2m_ops, .m2m_ops = &exynos3250_jpeg_m2m_ops,
.fmt_ver_flag = SJPEG_FMT_FLAG_EXYNOS3250, .fmt_ver_flag = SJPEG_FMT_FLAG_EXYNOS3250,
.hw3250_compat = 1,
}; };
static struct s5p_jpeg_variant exynos4_jpeg_drvdata = { static struct s5p_jpeg_variant exynos4_jpeg_drvdata = {
...@@ -2721,6 +2733,16 @@ static struct s5p_jpeg_variant exynos4_jpeg_drvdata = { ...@@ -2721,6 +2733,16 @@ static struct s5p_jpeg_variant exynos4_jpeg_drvdata = {
.jpeg_irq = exynos4_jpeg_irq, .jpeg_irq = exynos4_jpeg_irq,
.m2m_ops = &exynos4_jpeg_m2m_ops, .m2m_ops = &exynos4_jpeg_m2m_ops,
.fmt_ver_flag = SJPEG_FMT_FLAG_EXYNOS4, .fmt_ver_flag = SJPEG_FMT_FLAG_EXYNOS4,
.htbl_reinit = 1,
};
static struct s5p_jpeg_variant exynos5420_jpeg_drvdata = {
.version = SJPEG_EXYNOS5420,
.jpeg_irq = exynos3250_jpeg_irq, /* intentionally 3250 */
.m2m_ops = &exynos3250_jpeg_m2m_ops, /* intentionally 3250 */
.fmt_ver_flag = SJPEG_FMT_FLAG_EXYNOS3250, /* intentionally 3250 */
.hw3250_compat = 1,
.htbl_reinit = 1,
}; };
static const struct of_device_id samsung_jpeg_match[] = { static const struct of_device_id samsung_jpeg_match[] = {
...@@ -2736,6 +2758,9 @@ static const struct of_device_id samsung_jpeg_match[] = { ...@@ -2736,6 +2758,9 @@ static const struct of_device_id samsung_jpeg_match[] = {
}, { }, {
.compatible = "samsung,exynos4212-jpeg", .compatible = "samsung,exynos4212-jpeg",
.data = &exynos4_jpeg_drvdata, .data = &exynos4_jpeg_drvdata,
}, {
.compatible = "samsung,exynos5420-jpeg",
.data = &exynos5420_jpeg_drvdata,
}, },
{}, {},
}; };
......
...@@ -67,10 +67,12 @@ ...@@ -67,10 +67,12 @@
#define SJPEG_SUBSAMPLING_420 0x22 #define SJPEG_SUBSAMPLING_420 0x22
/* Version numbers */ /* Version numbers */
enum sjpeg_version {
#define SJPEG_S5P 1 SJPEG_S5P,
#define SJPEG_EXYNOS3250 2 SJPEG_EXYNOS3250,
#define SJPEG_EXYNOS4 3 SJPEG_EXYNOS4,
SJPEG_EXYNOS5420,
};
enum exynos4_jpeg_result { enum exynos4_jpeg_result {
OK_ENC_OR_DEC, OK_ENC_OR_DEC,
...@@ -130,6 +132,8 @@ struct s5p_jpeg { ...@@ -130,6 +132,8 @@ struct s5p_jpeg {
struct s5p_jpeg_variant { struct s5p_jpeg_variant {
unsigned int version; unsigned int version;
unsigned int fmt_ver_flag; unsigned int fmt_ver_flag;
unsigned int hw3250_compat:1;
unsigned int htbl_reinit:1;
struct v4l2_m2m_ops *m2m_ops; struct v4l2_m2m_ops *m2m_ops;
irqreturn_t (*jpeg_irq)(int irq, void *priv); irqreturn_t (*jpeg_irq)(int irq, void *priv);
}; };
......
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