Commit b95a24d6 authored by Marek Szyprowski's avatar Marek Szyprowski Committed by Mauro Carvalho Chehab

[media] s5p-jpeg: generalize clocks handling

Allow jpeg codec variants declare clocks they need.
Before this patch is applied jpeg-core gets jpeg->sclk
"speculatively": if it is not there, we assume no problem.

This patch eliminates this by explicitly declaring
what clocks are needed for each variant.

This is a preparation for adding Exynos 5433 variant support, which
needs 4 clocks of names not compatible with any previous version of
jpeg hw module.

[Rebase and commit message]
Signed-off-by: default avatarMarek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: default avatarAndrzej Pietrasiewicz <andrzej.p@samsung.com>
Reviewed-by: default avatarJacek Anaszewski <j.anaszewski@samsung.com>
Signed-off-by: default avatarHans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@osg.samsung.com>
parent 5bcc0dd7
...@@ -2455,7 +2455,7 @@ static int s5p_jpeg_probe(struct platform_device *pdev) ...@@ -2455,7 +2455,7 @@ static int s5p_jpeg_probe(struct platform_device *pdev)
{ {
struct s5p_jpeg *jpeg; struct s5p_jpeg *jpeg;
struct resource *res; struct resource *res;
int ret; int i, ret;
/* JPEG IP abstraction struct */ /* JPEG IP abstraction struct */
jpeg = devm_kzalloc(&pdev->dev, sizeof(struct s5p_jpeg), GFP_KERNEL); jpeg = devm_kzalloc(&pdev->dev, sizeof(struct s5p_jpeg), GFP_KERNEL);
...@@ -2490,23 +2490,21 @@ static int s5p_jpeg_probe(struct platform_device *pdev) ...@@ -2490,23 +2490,21 @@ static int s5p_jpeg_probe(struct platform_device *pdev)
} }
/* clocks */ /* clocks */
jpeg->clk = clk_get(&pdev->dev, "jpeg"); for (i = 0; i < jpeg->variant->num_clocks; i++) {
if (IS_ERR(jpeg->clk)) { jpeg->clocks[i] = devm_clk_get(&pdev->dev,
dev_err(&pdev->dev, "cannot get clock\n"); jpeg->variant->clk_names[i]);
ret = PTR_ERR(jpeg->clk); if (IS_ERR(jpeg->clocks[i])) {
return ret; dev_err(&pdev->dev, "failed to get clock: %s\n",
jpeg->variant->clk_names[i]);
return PTR_ERR(jpeg->clocks[i]);
}
} }
dev_dbg(&pdev->dev, "clock source %p\n", jpeg->clk);
jpeg->sclk = clk_get(&pdev->dev, "sclk");
if (IS_ERR(jpeg->sclk))
dev_info(&pdev->dev, "sclk clock not available\n");
/* v4l2 device */ /* v4l2 device */
ret = v4l2_device_register(&pdev->dev, &jpeg->v4l2_dev); ret = v4l2_device_register(&pdev->dev, &jpeg->v4l2_dev);
if (ret) { if (ret) {
dev_err(&pdev->dev, "Failed to register v4l2 device\n"); dev_err(&pdev->dev, "Failed to register v4l2 device\n");
goto clk_get_rollback; return ret;
} }
/* mem2mem device */ /* mem2mem device */
...@@ -2603,17 +2601,13 @@ static int s5p_jpeg_probe(struct platform_device *pdev) ...@@ -2603,17 +2601,13 @@ static int s5p_jpeg_probe(struct platform_device *pdev)
device_register_rollback: device_register_rollback:
v4l2_device_unregister(&jpeg->v4l2_dev); v4l2_device_unregister(&jpeg->v4l2_dev);
clk_get_rollback:
clk_put(jpeg->clk);
if (!IS_ERR(jpeg->sclk))
clk_put(jpeg->sclk);
return ret; return ret;
} }
static int s5p_jpeg_remove(struct platform_device *pdev) static int s5p_jpeg_remove(struct platform_device *pdev)
{ {
struct s5p_jpeg *jpeg = platform_get_drvdata(pdev); struct s5p_jpeg *jpeg = platform_get_drvdata(pdev);
int i;
pm_runtime_disable(jpeg->dev); pm_runtime_disable(jpeg->dev);
...@@ -2624,15 +2618,10 @@ static int s5p_jpeg_remove(struct platform_device *pdev) ...@@ -2624,15 +2618,10 @@ static int s5p_jpeg_remove(struct platform_device *pdev)
v4l2_device_unregister(&jpeg->v4l2_dev); v4l2_device_unregister(&jpeg->v4l2_dev);
if (!pm_runtime_status_suspended(&pdev->dev)) { if (!pm_runtime_status_suspended(&pdev->dev)) {
clk_disable_unprepare(jpeg->clk); for (i = jpeg->variant->num_clocks - 1; i >= 0; i--)
if (!IS_ERR(jpeg->sclk)) clk_disable_unprepare(jpeg->clocks[i]);
clk_disable_unprepare(jpeg->sclk);
} }
clk_put(jpeg->clk);
if (!IS_ERR(jpeg->sclk))
clk_put(jpeg->sclk);
return 0; return 0;
} }
...@@ -2640,10 +2629,10 @@ static int s5p_jpeg_remove(struct platform_device *pdev) ...@@ -2640,10 +2629,10 @@ static int s5p_jpeg_remove(struct platform_device *pdev)
static int s5p_jpeg_runtime_suspend(struct device *dev) static int s5p_jpeg_runtime_suspend(struct device *dev)
{ {
struct s5p_jpeg *jpeg = dev_get_drvdata(dev); struct s5p_jpeg *jpeg = dev_get_drvdata(dev);
int i;
clk_disable_unprepare(jpeg->clk); for (i = jpeg->variant->num_clocks - 1; i >= 0; i--)
if (!IS_ERR(jpeg->sclk)) clk_disable_unprepare(jpeg->clocks[i]);
clk_disable_unprepare(jpeg->sclk);
return 0; return 0;
} }
...@@ -2652,16 +2641,15 @@ static int s5p_jpeg_runtime_resume(struct device *dev) ...@@ -2652,16 +2641,15 @@ static int s5p_jpeg_runtime_resume(struct device *dev)
{ {
struct s5p_jpeg *jpeg = dev_get_drvdata(dev); struct s5p_jpeg *jpeg = dev_get_drvdata(dev);
unsigned long flags; unsigned long flags;
int ret; int i, ret;
ret = clk_prepare_enable(jpeg->clk); for (i = 0; i < jpeg->variant->num_clocks; i++) {
if (ret < 0) ret = clk_prepare_enable(jpeg->clocks[i]);
return ret; if (ret) {
while (--i > 0)
if (!IS_ERR(jpeg->sclk)) { clk_disable_unprepare(jpeg->clocks[i]);
ret = clk_prepare_enable(jpeg->sclk);
if (ret < 0)
return ret; return ret;
}
} }
spin_lock_irqsave(&jpeg->slock, flags); spin_lock_irqsave(&jpeg->slock, flags);
...@@ -2715,6 +2703,8 @@ static struct s5p_jpeg_variant s5p_jpeg_drvdata = { ...@@ -2715,6 +2703,8 @@ static struct s5p_jpeg_variant s5p_jpeg_drvdata = {
.jpeg_irq = s5p_jpeg_irq, .jpeg_irq = s5p_jpeg_irq,
.m2m_ops = &s5p_jpeg_m2m_ops, .m2m_ops = &s5p_jpeg_m2m_ops,
.fmt_ver_flag = SJPEG_FMT_FLAG_S5P, .fmt_ver_flag = SJPEG_FMT_FLAG_S5P,
.clk_names = {"jpeg"},
.num_clocks = 1,
}; };
static struct s5p_jpeg_variant exynos3250_jpeg_drvdata = { static struct s5p_jpeg_variant exynos3250_jpeg_drvdata = {
...@@ -2723,6 +2713,8 @@ static struct s5p_jpeg_variant exynos3250_jpeg_drvdata = { ...@@ -2723,6 +2713,8 @@ static struct s5p_jpeg_variant exynos3250_jpeg_drvdata = {
.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, .hw3250_compat = 1,
.clk_names = {"jpeg", "sclk"},
.num_clocks = 2,
}; };
static struct s5p_jpeg_variant exynos4_jpeg_drvdata = { static struct s5p_jpeg_variant exynos4_jpeg_drvdata = {
...@@ -2731,6 +2723,8 @@ static struct s5p_jpeg_variant exynos4_jpeg_drvdata = { ...@@ -2731,6 +2723,8 @@ static struct s5p_jpeg_variant exynos4_jpeg_drvdata = {
.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, .htbl_reinit = 1,
.clk_names = {"jpeg"},
.num_clocks = 1,
}; };
static struct s5p_jpeg_variant exynos5420_jpeg_drvdata = { static struct s5p_jpeg_variant exynos5420_jpeg_drvdata = {
...@@ -2740,6 +2734,8 @@ static struct s5p_jpeg_variant exynos5420_jpeg_drvdata = { ...@@ -2740,6 +2734,8 @@ static struct s5p_jpeg_variant exynos5420_jpeg_drvdata = {
.fmt_ver_flag = SJPEG_FMT_FLAG_EXYNOS3250, /* intentionally 3250 */ .fmt_ver_flag = SJPEG_FMT_FLAG_EXYNOS3250, /* intentionally 3250 */
.hw3250_compat = 1, .hw3250_compat = 1,
.htbl_reinit = 1, .htbl_reinit = 1,
.clk_names = {"jpeg"},
.num_clocks = 1,
}; };
static const struct of_device_id samsung_jpeg_match[] = { static const struct of_device_id samsung_jpeg_match[] = {
......
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
#define S5P_JPEG_M2M_NAME "s5p-jpeg" #define S5P_JPEG_M2M_NAME "s5p-jpeg"
#define JPEG_MAX_CLOCKS 4
/* JPEG compression quality setting */ /* JPEG compression quality setting */
#define S5P_JPEG_COMPR_QUAL_BEST 0 #define S5P_JPEG_COMPR_QUAL_BEST 0
#define S5P_JPEG_COMPR_QUAL_WORST 3 #define S5P_JPEG_COMPR_QUAL_WORST 3
...@@ -100,8 +102,7 @@ enum exynos4_jpeg_img_quality_level { ...@@ -100,8 +102,7 @@ enum exynos4_jpeg_img_quality_level {
* @m2m_dev: v4l2 mem2mem device data * @m2m_dev: v4l2 mem2mem device data
* @regs: JPEG IP registers mapping * @regs: JPEG IP registers mapping
* @irq: JPEG IP irq * @irq: JPEG IP irq
* @clk: JPEG IP clock * @clocks: JPEG IP clock(s)
* @sclk: Exynos3250 JPEG IP special clock
* @dev: JPEG IP struct device * @dev: JPEG IP struct device
* @alloc_ctx: videobuf2 memory allocator's context * @alloc_ctx: videobuf2 memory allocator's context
* @variant: driver variant to be used * @variant: driver variant to be used
...@@ -121,8 +122,7 @@ struct s5p_jpeg { ...@@ -121,8 +122,7 @@ struct s5p_jpeg {
void __iomem *regs; void __iomem *regs;
unsigned int irq; unsigned int irq;
enum exynos4_jpeg_result irq_ret; enum exynos4_jpeg_result irq_ret;
struct clk *clk; struct clk *clocks[JPEG_MAX_CLOCKS];
struct clk *sclk;
struct device *dev; struct device *dev;
void *alloc_ctx; void *alloc_ctx;
struct s5p_jpeg_variant *variant; struct s5p_jpeg_variant *variant;
...@@ -136,6 +136,8 @@ struct s5p_jpeg_variant { ...@@ -136,6 +136,8 @@ struct s5p_jpeg_variant {
unsigned int htbl_reinit: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);
const char *clk_names[JPEG_MAX_CLOCKS];
int num_clocks;
}; };
/** /**
......
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