Re: [PATCH v4 1/4] [media] exynos-scaler: Add new driver for Exynos5 SCALER

2014-01-06 Thread Shaik Ameer Basha
Hi Mauro,

Thanks for the review comments.

On Fri, Jan 3, 2014 at 1:48 AM, Mauro Carvalho Chehab
 wrote:
> Em Fri,  4 Oct 2013 17:56:31 +0530
> Shaik Ameer Basha  escreveu:
>
>> This patch adds support for SCALER device which is a new device
>> for scaling, blending, color fill  and color space conversion
>> on EXYNOS5410 and EXYNOS5420 SoCs.
>>
>> This device supports the followings as key feature.
>> input image format
>> - YCbCr420 2P(UV/VU), 3P
>> - YCbCr422 1P(YUYV/UYVY/YVYU), 2P(UV,VU), 3P
>> - YCbCr444 2P(UV,VU), 3P
>> - RGB565, ARGB1555, ARGB, ARGB, RGBA
>> - Pre-multiplexed ARGB, L8A8 and L8
>> output image format
>> - YCbCr420 2P(UV/VU), 3P
>> - YCbCr422 1P(YUYV/UYVY/YVYU), 2P(UV,VU), 3P
>> - YCbCr444 2P(UV,VU), 3P
>> - RGB565, ARGB1555, ARGB, ARGB, RGBA
>> - Pre-multiplexed ARGB
>> input rotation
>> - 0/90/180/270 degree, X/Y/XY Flip
>> scale ratio
>> - 1/4 scale down to 16 scale up
>> color space conversion
>> - RGB to YUV / YUV to RGB
>> Size - Exynos5420
>> - Input : 16x16 to 8192x8192
>> - Output:   4x4 to 8192x8192
>> Size - Exynos5410
>> - Input/Output: 4x4 to 4096x4096
>> alpha blending, color fill
>>
>> Signed-off-by: Shaik Ameer Basha 
>> ---
>>  drivers/media/platform/exynos-scaler/scaler-regs.c |  336 
>> 
>>  drivers/media/platform/exynos-scaler/scaler-regs.h |  331 
>> +++
>>  2 files changed, 667 insertions(+)
>>  create mode 100644 drivers/media/platform/exynos-scaler/scaler-regs.c
>>  create mode 100644 drivers/media/platform/exynos-scaler/scaler-regs.h
>>
>> diff --git a/drivers/media/platform/exynos-scaler/scaler-regs.c 
>> b/drivers/media/platform/exynos-scaler/scaler-regs.c
>> new file mode 100644
>> index 000..ae4a548
>> --- /dev/null
>> +++ b/drivers/media/platform/exynos-scaler/scaler-regs.c
>> @@ -0,0 +1,336 @@
>> +/*
>> + * Copyright (c) 2013 Samsung Electronics Co., Ltd.
>> + *   http://www.samsung.com
>> + *
>> + * Samsung EXYNOS5 SoC series SCALER driver
>> + *
>> + * 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 
>> +#include 
>> +
>> +#include "scaler-regs.h"
>> +
>> +/* Scaler reset timeout in milliseconds */
>> +#define SCALER_RESET_TIMEOUT 50
>> +
>> +void scaler_hw_set_sw_reset(struct scaler_dev *dev)
>> +{
>> + u32 cfg;
>> +
>> + cfg = scaler_read(dev, SCALER_CFG);
>> + cfg |= SCALER_CFG_SOFT_RESET;
>> +
>> + scaler_write(dev, SCALER_CFG, cfg);
>> +}
>> +
>> +int scaler_wait_reset(struct scaler_dev *dev)
>> +{
>> + unsigned long end = jiffies + msecs_to_jiffies(SCALER_RESET_TIMEOUT);
>> + u32 cfg, reset_done = 0;
>> +
>> + while (time_before(jiffies, end)) {
>> + cfg = scaler_read(dev, SCALER_CFG);
>> + if (!(cfg & SCALER_CFG_SOFT_RESET)) {
>> + reset_done = 1;
>> + break;
>> + }
>> + usleep_range(10, 20);
>
> Hmm... that doesn't seem right... the timeout can take up to 50,000 us, and
> you're sleeping from 10 to 20us... that means that this loop can have up to
> 5000 interactions... It seems that you're wasting power here without need.
>
> I suspect that you should consider sleeping for a longer time here.

I will check what is the average time taken for the reset process.
If it is much more than 20us then i will increase this sleeping time.

>
> Btw, instead of using time_before(jiffies, end), you could do:
> time_is_after_jiffies(end)
>

Ok. I will modify.

> As, from jiffies.h:
> /* time_is_after_jiffies(a) return true if a is after jiffies */
> #define time_is_after_jiffies(a) time_before(jiffies, a)
>
>> + }
>> +
>> + /*
>> +  * Write any value to read/write register and read it back.
>> +  * If the written and read value matches, then the reset process is
>> +  * succeeded.
>> +  */
>> + while (reset_done) {
>
> This is tricky. If the reset fail, it will return busy. Otherwise, it
> can loop forever here. Worse than that, you're don't even sleeping
> before retries, again wasting power.
>
> Why don't you just change it to something similar to:
>
> if (!reset_done)
> return -EBUSY;
>
> end = jiffies + msecs_to_jiffies(SCALER_RESET_TIMEOUT);
> while (time_is_after_jiffies(end)) {
> scaler_write(dev, SCALER_CFG_SOFT_RESET_CHECK_REG,
> SCALER_CFG_SOFT_RESET_CHECK_VAL);
> if (SCALER_CFG_SOFT_RESET_CHECK_VAL ==
> scaler_read(dev, SCALER_CFG_SOFT_RESET_CHECK_REG))
> return 0;
> msleep(10);
> }


My Intention is to comp

Re: [PATCH v4 1/4] [media] exynos-scaler: Add new driver for Exynos5 SCALER

2014-01-02 Thread Mauro Carvalho Chehab
Em Fri,  4 Oct 2013 17:56:31 +0530
Shaik Ameer Basha  escreveu:

> This patch adds support for SCALER device which is a new device
> for scaling, blending, color fill  and color space conversion
> on EXYNOS5410 and EXYNOS5420 SoCs.
> 
> This device supports the followings as key feature.
> input image format
> - YCbCr420 2P(UV/VU), 3P
> - YCbCr422 1P(YUYV/UYVY/YVYU), 2P(UV,VU), 3P
> - YCbCr444 2P(UV,VU), 3P
> - RGB565, ARGB1555, ARGB, ARGB, RGBA
> - Pre-multiplexed ARGB, L8A8 and L8
> output image format
> - YCbCr420 2P(UV/VU), 3P
> - YCbCr422 1P(YUYV/UYVY/YVYU), 2P(UV,VU), 3P
> - YCbCr444 2P(UV,VU), 3P
> - RGB565, ARGB1555, ARGB, ARGB, RGBA
> - Pre-multiplexed ARGB
> input rotation
> - 0/90/180/270 degree, X/Y/XY Flip
> scale ratio
> - 1/4 scale down to 16 scale up
> color space conversion
> - RGB to YUV / YUV to RGB
> Size - Exynos5420
> - Input : 16x16 to 8192x8192
> - Output:   4x4 to 8192x8192
> Size - Exynos5410
> - Input/Output: 4x4 to 4096x4096
> alpha blending, color fill
> 
> Signed-off-by: Shaik Ameer Basha 
> ---
>  drivers/media/platform/exynos-scaler/scaler-regs.c |  336 
> 
>  drivers/media/platform/exynos-scaler/scaler-regs.h |  331 +++
>  2 files changed, 667 insertions(+)
>  create mode 100644 drivers/media/platform/exynos-scaler/scaler-regs.c
>  create mode 100644 drivers/media/platform/exynos-scaler/scaler-regs.h
> 
> diff --git a/drivers/media/platform/exynos-scaler/scaler-regs.c 
> b/drivers/media/platform/exynos-scaler/scaler-regs.c
> new file mode 100644
> index 000..ae4a548
> --- /dev/null
> +++ b/drivers/media/platform/exynos-scaler/scaler-regs.c
> @@ -0,0 +1,336 @@
> +/*
> + * Copyright (c) 2013 Samsung Electronics Co., Ltd.
> + *   http://www.samsung.com
> + *
> + * Samsung EXYNOS5 SoC series SCALER driver
> + *
> + * 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 
> +#include 
> +
> +#include "scaler-regs.h"
> +
> +/* Scaler reset timeout in milliseconds */
> +#define SCALER_RESET_TIMEOUT 50
> +
> +void scaler_hw_set_sw_reset(struct scaler_dev *dev)
> +{
> + u32 cfg;
> +
> + cfg = scaler_read(dev, SCALER_CFG);
> + cfg |= SCALER_CFG_SOFT_RESET;
> +
> + scaler_write(dev, SCALER_CFG, cfg);
> +}
> +
> +int scaler_wait_reset(struct scaler_dev *dev)
> +{
> + unsigned long end = jiffies + msecs_to_jiffies(SCALER_RESET_TIMEOUT);
> + u32 cfg, reset_done = 0;
> +
> + while (time_before(jiffies, end)) {
> + cfg = scaler_read(dev, SCALER_CFG);
> + if (!(cfg & SCALER_CFG_SOFT_RESET)) {
> + reset_done = 1;
> + break;
> + }
> + usleep_range(10, 20);

Hmm... that doesn't seem right... the timeout can take up to 50,000 us, and
you're sleeping from 10 to 20us... that means that this loop can have up to
5000 interactions... It seems that you're wasting power here without need.

I suspect that you should consider sleeping for a longer time here.

Btw, instead of using time_before(jiffies, end), you could do:
time_is_after_jiffies(end)

As, from jiffies.h:
/* time_is_after_jiffies(a) return true if a is after jiffies */
#define time_is_after_jiffies(a) time_before(jiffies, a)

> + }
> +
> + /*
> +  * Write any value to read/write register and read it back.
> +  * If the written and read value matches, then the reset process is
> +  * succeeded.
> +  */
> + while (reset_done) {

This is tricky. If the reset fail, it will return busy. Otherwise, it
can loop forever here. Worse than that, you're don't even sleeping
before retries, again wasting power.

Why don't you just change it to something similar to:

if (!reset_done)
return -EBUSY;

end = jiffies + msecs_to_jiffies(SCALER_RESET_TIMEOUT);
while (time_is_after_jiffies(end)) {
scaler_write(dev, SCALER_CFG_SOFT_RESET_CHECK_REG,
SCALER_CFG_SOFT_RESET_CHECK_VAL);
if (SCALER_CFG_SOFT_RESET_CHECK_VAL ==
scaler_read(dev, SCALER_CFG_SOFT_RESET_CHECK_REG))
return 0;
msleep(10);
}

> +
> + /*
> +  * TODO: need to define number of tries before returning
> +  * -EBUSY to the caller
> +  */
> +
> + scaler_write(dev, SCALER_CFG_SOFT_RESET_CHECK_REG,
> + SCALER_CFG_SOFT_RESET_CHECK_VAL);
> + if (SCALER_CFG_SOFT_RESET_CHECK_VAL ==
> + scaler_read(dev, SCALER_CFG_SOFT_RESET_CHECK_REG))
> + r

Re: [PATCH v4 1/4] [media] exynos-scaler: Add new driver for Exynos5 SCALER

2013-10-20 Thread Sylwester Nawrocki

Hi Shaik,

On 10/20/2013 02:33 PM, Shaik Ameer Basha wrote:

On Fri, Oct 18, 2013 at 5:57 PM, Sylwester Nawrocki
  wrote:

>  Hi,
>
>  I have couple minor comments. These could be addressed in follow up
>  patches, it you won't manage to do it today. Sorry for being late with
>  this.


Sorry for the late reply.

Currently I am on travel and I don't have the environment to rebase
and test this driver.
I will address your comments in follow up patches.

Can you please queue this driver to your branch and send a pull
request for 3.13 ?


The driver seems to be in quite a good shape now and I think it would
have been bad not to merge it in this release. I'll let Kamil handle
it as he's a sub-maintainer of the v4l2 mem-to-mem drivers.

Regards,
Sylwester
--
To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v4 1/4] [media] exynos-scaler: Add new driver for Exynos5 SCALER

2013-10-20 Thread Shaik Ameer Basha
Hi Sylwester,

On Fri, Oct 18, 2013 at 5:57 PM, Sylwester Nawrocki
 wrote:
> Hi,
>
> I have couple minor comments. These could be addressed in follow up
> patches, it you won't manage to do it today. Sorry for being late with
> this.

Sorry for the late reply.

Currently I am on travel and I don't have the environment to rebase
and test this driver.
I will address your comments in follow up patches.

Can you please queue this driver to your branch and send a pull
request for 3.13 ?

Regards,
Shaik Ameer Basha

>
> On 04/10/13 14:26, Shaik Ameer Basha wrote:
>> This patch adds support for SCALER device which is a new device
>> for scaling, blending, color fill  and color space conversion
>> on EXYNOS5410 and EXYNOS5420 SoCs.
>>
>> This device supports the followings as key feature.
>> input image format
>> - YCbCr420 2P(UV/VU), 3P
>> - YCbCr422 1P(YUYV/UYVY/YVYU), 2P(UV,VU), 3P
>> - YCbCr444 2P(UV,VU), 3P
>> - RGB565, ARGB1555, ARGB, ARGB, RGBA
>> - Pre-multiplexed ARGB, L8A8 and L8
>> output image format
>> - YCbCr420 2P(UV/VU), 3P
>> - YCbCr422 1P(YUYV/UYVY/YVYU), 2P(UV,VU), 3P
>> - YCbCr444 2P(UV,VU), 3P
>> - RGB565, ARGB1555, ARGB, ARGB, RGBA
>> - Pre-multiplexed ARGB
>> input rotation
>> - 0/90/180/270 degree, X/Y/XY Flip
>> scale ratio
>> - 1/4 scale down to 16 scale up
>> color space conversion
>> - RGB to YUV / YUV to RGB
>> Size - Exynos5420
>> - Input : 16x16 to 8192x8192
>> - Output:   4x4 to 8192x8192
>> Size - Exynos5410
>> - Input/Output: 4x4 to 4096x4096
>> alpha blending, color fill
>>
>> Signed-off-by: Shaik Ameer Basha 
>
> Reviewed-by: Sylwester Nawrocki 
>
>> +void scaler_hw_set_in_size(struct scaler_ctx *ctx)
>> +{
>> + struct scaler_dev *dev = ctx->scaler_dev;
>> + struct scaler_frame *frame = &ctx->s_frame;
>> + u32 cfg;
>> +
>> + /* set input pixel offset */
>> + cfg = (frame->selection.left & SCALER_SRC_YH_POS_MASK) <<
>> +   SCALER_SRC_YH_POS_SHIFT;
>> + cfg |= ((frame->selection.top & SCALER_SRC_YV_POS_MASK) <<
>> +SCALER_SRC_YV_POS_SHIFT);
>> + scaler_write(dev, SCALER_SRC_Y_POS, cfg);
>> +
>> + /* TODO: calculate 'C' plane h/v offset using 'Y' plane h/v offset */
>> +
>> + /* Set input span */
>> + cfg = (frame->f_width & SCALER_SRC_Y_SPAN_MASK) <<
>> + SCALER_SRC_Y_SPAN_SHIFT;
>> + if (is_yuv420_2p(frame->fmt))
>> + cfg |= ((frame->f_width & SCALER_SRC_C_SPAN_MASK) <<
>> +   SCALER_SRC_C_SPAN_SHIFT);
>> + else /* TODO: Verify */
>> + cfg |= ((frame->f_width & SCALER_SRC_C_SPAN_MASK) <<
>> +   SCALER_SRC_C_SPAN_SHIFT);
>> +
>> + scaler_write(dev, SCALER_SRC_SPAN, cfg);
>> +
>> + /* Set input cropped size */
>> + cfg = (frame->selection.width & SCALER_SRC_WIDTH_MASK) <<
>> +SCALER_SRC_WIDTH_SHIFT;
>> + cfg |= ((frame->selection.height & SCALER_SRC_HEIGHT_MASK) <<
>> +   SCALER_SRC_HEIGHT_SHIFT);
>> + scaler_write(dev, SCALER_SRC_WH, cfg);
>> +
>> + scaler_dbg(dev, "src: posx: %d, posY: %d, spanY: %d, spanC: %d, cropX: 
>> %d, cropY: %d\n",
>
> This could be broken into two lines, it's just a debug print.
>
>> + frame->selection.left, frame->selection.top,
>> + frame->f_width, frame->f_width, frame->selection.width,
>> + frame->selection.height);
>> +}
>> +
>> +void scaler_hw_set_in_image_format(struct scaler_ctx *ctx)
>> +{
>> + struct scaler_dev *dev = ctx->scaler_dev;
>> + struct scaler_frame *frame = &ctx->s_frame;
>> + u32 cfg;
>> +
>> + cfg = scaler_read(dev, SCALER_SRC_CFG);
>> + cfg &= ~(SCALER_SRC_COLOR_FORMAT_MASK << 
>> SCALER_SRC_COLOR_FORMAT_SHIFT);
>> + cfg |= ((frame->fmt->scaler_color & SCALER_SRC_COLOR_FORMAT_MASK) <<
>> +SCALER_SRC_COLOR_FORMAT_SHIFT);
>> +
>> + /* Setting tiled/linear format */
>> + if (is_tiled_fmt(frame->fmt))
>> + cfg |= SCALER_SRC_TILE_EN;
>> + else
>> + cfg &= ~SCALER_SRC_TILE_EN;
>> +
>> + scaler_write(dev, SCALER_SRC_CFG, cfg);
>> +}
>> +
>> +void scaler_hw_set_out_size(struct scaler_ctx *ctx)
>> +{
>> + struct scaler_dev *dev = ctx->scaler_dev;
>> + struct scaler_frame *frame = &ctx->d_frame;
>> + u32 cfg;
>> +
>> + /* Set output pixel offset */
>> + cfg = (frame->selection.left & SCALER_DST_H_POS_MASK) <<
>> +   SCALER_DST_H_POS_SHIFT;
>> + cfg |= (frame->selection.top & SCALER_DST_V_POS_MASK) <<
>> +   SCALER_DST_V_POS_SHIFT;
>> + scaler_write(dev, SCALER_DST_POS, cfg);
>> +
>> + /* Set output span */
>> +

Re: [PATCH v4 1/4] [media] exynos-scaler: Add new driver for Exynos5 SCALER

2013-10-18 Thread Sylwester Nawrocki
Hi,

I have couple minor comments. These could be addressed in follow up
patches, it you won't manage to do it today. Sorry for being late with
this.

On 04/10/13 14:26, Shaik Ameer Basha wrote:
> This patch adds support for SCALER device which is a new device
> for scaling, blending, color fill  and color space conversion
> on EXYNOS5410 and EXYNOS5420 SoCs.
> 
> This device supports the followings as key feature.
> input image format
> - YCbCr420 2P(UV/VU), 3P
> - YCbCr422 1P(YUYV/UYVY/YVYU), 2P(UV,VU), 3P
> - YCbCr444 2P(UV,VU), 3P
> - RGB565, ARGB1555, ARGB, ARGB, RGBA
> - Pre-multiplexed ARGB, L8A8 and L8
> output image format
> - YCbCr420 2P(UV/VU), 3P
> - YCbCr422 1P(YUYV/UYVY/YVYU), 2P(UV,VU), 3P
> - YCbCr444 2P(UV,VU), 3P
> - RGB565, ARGB1555, ARGB, ARGB, RGBA
> - Pre-multiplexed ARGB
> input rotation
> - 0/90/180/270 degree, X/Y/XY Flip
> scale ratio
> - 1/4 scale down to 16 scale up
> color space conversion
> - RGB to YUV / YUV to RGB
> Size - Exynos5420
> - Input : 16x16 to 8192x8192
> - Output:   4x4 to 8192x8192
> Size - Exynos5410
> - Input/Output: 4x4 to 4096x4096
> alpha blending, color fill
> 
> Signed-off-by: Shaik Ameer Basha 

Reviewed-by: Sylwester Nawrocki 

> +void scaler_hw_set_in_size(struct scaler_ctx *ctx)
> +{
> + struct scaler_dev *dev = ctx->scaler_dev;
> + struct scaler_frame *frame = &ctx->s_frame;
> + u32 cfg;
> +
> + /* set input pixel offset */
> + cfg = (frame->selection.left & SCALER_SRC_YH_POS_MASK) <<
> +   SCALER_SRC_YH_POS_SHIFT;
> + cfg |= ((frame->selection.top & SCALER_SRC_YV_POS_MASK) <<
> +SCALER_SRC_YV_POS_SHIFT);
> + scaler_write(dev, SCALER_SRC_Y_POS, cfg);
> +
> + /* TODO: calculate 'C' plane h/v offset using 'Y' plane h/v offset */
> +
> + /* Set input span */
> + cfg = (frame->f_width & SCALER_SRC_Y_SPAN_MASK) <<
> + SCALER_SRC_Y_SPAN_SHIFT;
> + if (is_yuv420_2p(frame->fmt))
> + cfg |= ((frame->f_width & SCALER_SRC_C_SPAN_MASK) <<
> +   SCALER_SRC_C_SPAN_SHIFT);
> + else /* TODO: Verify */
> + cfg |= ((frame->f_width & SCALER_SRC_C_SPAN_MASK) <<
> +   SCALER_SRC_C_SPAN_SHIFT);
> +
> + scaler_write(dev, SCALER_SRC_SPAN, cfg);
> +
> + /* Set input cropped size */
> + cfg = (frame->selection.width & SCALER_SRC_WIDTH_MASK) <<
> +SCALER_SRC_WIDTH_SHIFT;
> + cfg |= ((frame->selection.height & SCALER_SRC_HEIGHT_MASK) <<
> +   SCALER_SRC_HEIGHT_SHIFT);
> + scaler_write(dev, SCALER_SRC_WH, cfg);
> +
> + scaler_dbg(dev, "src: posx: %d, posY: %d, spanY: %d, spanC: %d, cropX: 
> %d, cropY: %d\n",

This could be broken into two lines, it's just a debug print.

> + frame->selection.left, frame->selection.top,
> + frame->f_width, frame->f_width, frame->selection.width,
> + frame->selection.height);
> +}
> +
> +void scaler_hw_set_in_image_format(struct scaler_ctx *ctx)
> +{
> + struct scaler_dev *dev = ctx->scaler_dev;
> + struct scaler_frame *frame = &ctx->s_frame;
> + u32 cfg;
> +
> + cfg = scaler_read(dev, SCALER_SRC_CFG);
> + cfg &= ~(SCALER_SRC_COLOR_FORMAT_MASK << SCALER_SRC_COLOR_FORMAT_SHIFT);
> + cfg |= ((frame->fmt->scaler_color & SCALER_SRC_COLOR_FORMAT_MASK) <<
> +SCALER_SRC_COLOR_FORMAT_SHIFT);
> +
> + /* Setting tiled/linear format */
> + if (is_tiled_fmt(frame->fmt))
> + cfg |= SCALER_SRC_TILE_EN;
> + else
> + cfg &= ~SCALER_SRC_TILE_EN;
> +
> + scaler_write(dev, SCALER_SRC_CFG, cfg);
> +}
> +
> +void scaler_hw_set_out_size(struct scaler_ctx *ctx)
> +{
> + struct scaler_dev *dev = ctx->scaler_dev;
> + struct scaler_frame *frame = &ctx->d_frame;
> + u32 cfg;
> +
> + /* Set output pixel offset */
> + cfg = (frame->selection.left & SCALER_DST_H_POS_MASK) <<
> +   SCALER_DST_H_POS_SHIFT;
> + cfg |= (frame->selection.top & SCALER_DST_V_POS_MASK) <<
> +   SCALER_DST_V_POS_SHIFT;
> + scaler_write(dev, SCALER_DST_POS, cfg);
> +
> + /* Set output span */
> + cfg = (frame->f_width & SCALER_DST_Y_SPAN_MASK) <<
> + SCALER_DST_Y_SPAN_SHIFT;
> + if (is_yuv420_2p(frame->fmt))
> + cfg |= (((frame->f_width / 2) & SCALER_DST_C_SPAN_MASK) <<
> +  SCALER_DST_C_SPAN_SHIFT);
> + else
> + cfg |= (((frame->f_width) & SCALER_DST_C_SPAN_MASK) <<
> +  SCALER_DST_C_SPAN_SHIFT);
> + scaler_write(dev, SCALER_DST_S

[PATCH v4 1/4] [media] exynos-scaler: Add new driver for Exynos5 SCALER

2013-10-04 Thread Shaik Ameer Basha
This patch adds support for SCALER device which is a new device
for scaling, blending, color fill  and color space conversion
on EXYNOS5410 and EXYNOS5420 SoCs.

This device supports the followings as key feature.
input image format
- YCbCr420 2P(UV/VU), 3P
- YCbCr422 1P(YUYV/UYVY/YVYU), 2P(UV,VU), 3P
- YCbCr444 2P(UV,VU), 3P
- RGB565, ARGB1555, ARGB, ARGB, RGBA
- Pre-multiplexed ARGB, L8A8 and L8
output image format
- YCbCr420 2P(UV/VU), 3P
- YCbCr422 1P(YUYV/UYVY/YVYU), 2P(UV,VU), 3P
- YCbCr444 2P(UV,VU), 3P
- RGB565, ARGB1555, ARGB, ARGB, RGBA
- Pre-multiplexed ARGB
input rotation
- 0/90/180/270 degree, X/Y/XY Flip
scale ratio
- 1/4 scale down to 16 scale up
color space conversion
- RGB to YUV / YUV to RGB
Size - Exynos5420
- Input : 16x16 to 8192x8192
- Output:   4x4 to 8192x8192
Size - Exynos5410
- Input/Output: 4x4 to 4096x4096
alpha blending, color fill

Signed-off-by: Shaik Ameer Basha 
---
 drivers/media/platform/exynos-scaler/scaler-regs.c |  336 
 drivers/media/platform/exynos-scaler/scaler-regs.h |  331 +++
 2 files changed, 667 insertions(+)
 create mode 100644 drivers/media/platform/exynos-scaler/scaler-regs.c
 create mode 100644 drivers/media/platform/exynos-scaler/scaler-regs.h

diff --git a/drivers/media/platform/exynos-scaler/scaler-regs.c 
b/drivers/media/platform/exynos-scaler/scaler-regs.c
new file mode 100644
index 000..ae4a548
--- /dev/null
+++ b/drivers/media/platform/exynos-scaler/scaler-regs.c
@@ -0,0 +1,336 @@
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Samsung EXYNOS5 SoC series SCALER driver
+ *
+ * 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 
+#include 
+
+#include "scaler-regs.h"
+
+/* Scaler reset timeout in milliseconds */
+#define SCALER_RESET_TIMEOUT   50
+
+void scaler_hw_set_sw_reset(struct scaler_dev *dev)
+{
+   u32 cfg;
+
+   cfg = scaler_read(dev, SCALER_CFG);
+   cfg |= SCALER_CFG_SOFT_RESET;
+
+   scaler_write(dev, SCALER_CFG, cfg);
+}
+
+int scaler_wait_reset(struct scaler_dev *dev)
+{
+   unsigned long end = jiffies + msecs_to_jiffies(SCALER_RESET_TIMEOUT);
+   u32 cfg, reset_done = 0;
+
+   while (time_before(jiffies, end)) {
+   cfg = scaler_read(dev, SCALER_CFG);
+   if (!(cfg & SCALER_CFG_SOFT_RESET)) {
+   reset_done = 1;
+   break;
+   }
+   usleep_range(10, 20);
+   }
+
+   /*
+* Write any value to read/write register and read it back.
+* If the written and read value matches, then the reset process is
+* succeeded.
+*/
+   while (reset_done) {
+
+   /*
+* TODO: need to define number of tries before returning
+* -EBUSY to the caller
+*/
+
+   scaler_write(dev, SCALER_CFG_SOFT_RESET_CHECK_REG,
+   SCALER_CFG_SOFT_RESET_CHECK_VAL);
+   if (SCALER_CFG_SOFT_RESET_CHECK_VAL ==
+   scaler_read(dev, SCALER_CFG_SOFT_RESET_CHECK_REG))
+   return 0;
+   }
+
+   return -EBUSY;
+}
+
+void scaler_hw_set_irq(struct scaler_dev *dev, int irq_num, bool enable)
+{
+   u32 cfg;
+
+   if ((irq_num < SCALER_INT_FRAME_END) ||
+   (irq_num > SCALER_INT_TIMEOUT))
+   return;
+
+   cfg = scaler_read(dev, SCALER_INT_EN);
+   if (enable)
+   cfg |= (1 << irq_num);
+   else
+   cfg &= ~(1 << irq_num);
+   scaler_write(dev, SCALER_INT_EN, cfg);
+}
+
+void scaler_hw_set_input_addr(struct scaler_dev *dev, struct scaler_addr *addr)
+{
+   scaler_dbg(dev, "src_buf: 0x%x, cb: 0x%x, cr: 0x%x",
+   addr->y, addr->cb, addr->cr);
+   scaler_write(dev, SCALER_SRC_Y_BASE, addr->y);
+   scaler_write(dev, SCALER_SRC_CB_BASE, addr->cb);
+   scaler_write(dev, SCALER_SRC_CR_BASE, addr->cr);
+}
+
+void scaler_hw_set_output_addr(struct scaler_dev *dev,
+struct scaler_addr *addr)
+{
+   scaler_dbg(dev, "dst_buf: 0x%x, cb: 0x%x, cr: 0x%x",
+   addr->y, addr->cb, addr->cr);
+   scaler_write(dev, SCALER_DST_Y_BASE, addr->y);
+   scaler_write(dev, SCALER_DST_CB_BASE, addr->cb);
+   scaler_write(dev, SCALER_DST_CR_BASE, addr->cr);
+}
+
+void scaler_hw_set_in_size(struct scaler_ctx *ctx)
+{
+   struct scaler_dev *dev = ctx->scaler_dev;
+   struct scaler_frame *frame = &ctx->s_frame;
+   u32 cfg;
+
+   /* set input pixel offset */
+   cfg = (frame->selection.le