All of lore.kernel.org
 help / color / mirror / Atom feed
From: Sylwester Nawrocki <s.nawrocki@samsung.com>
To: Shaik Ameer Basha <shaik.ameer@samsung.com>,
	linux-media@vger.kernel.org, linux-samsung-soc@vger.kernel.org,
	'Arun Kumar K' <arun.kk@samsung.com>
Cc: posciak@google.com, inki.dae@samsung.com, hverkuil@xs4all.nl
Subject: Re: [PATCH v4 2/4] [media] exynos-scaler: Add core functionality for the SCALER driver
Date: Fri, 18 Oct 2013 11:07:54 +0200	[thread overview]
Message-ID: <5260FA6A.3000303@samsung.com> (raw)
In-Reply-To: <1380889594-10448-3-git-send-email-shaik.ameer@samsung.com>

On 04/10/13 14:26, Shaik Ameer Basha wrote:
> This patch adds the core functionality for the SCALER driver.
> 
> Signed-off-by: Shaik Ameer Basha <shaik.ameer@samsung.com>

Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>

Just couple minor comment below...

> ---
>  drivers/media/platform/exynos-scaler/scaler.c | 1238 +++++++++++++++++++++++++
>  drivers/media/platform/exynos-scaler/scaler.h |  375 ++++++++
>  2 files changed, 1613 insertions(+)
>  create mode 100644 drivers/media/platform/exynos-scaler/scaler.c
>  create mode 100644 drivers/media/platform/exynos-scaler/scaler.h
 [...]
> +static int __scaler_try_ctrl(struct scaler_ctx *ctx, struct v4l2_ctrl *ctrl)
> +{
> +	struct scaler_dev *scaler = ctx->scaler_dev;
> +	struct scaler_variant *variant = scaler->variant;
> +
> +	switch (ctrl->id) {
> +	case V4L2_CID_ROTATE:
> +		return scaler_check_scaler_ratio(variant,
> +			ctx->s_frame.selection.width,
> +			ctx->s_frame.selection.height,
> +			ctx->d_frame.selection.width,
> +			ctx->d_frame.selection.height,
> +			ctx->ctrls_scaler.rotate->val);
> +	}
> +
> +	return 0;
> +}
> +
> +static int scaler_try_ctrl(struct v4l2_ctrl *ctrl)
> +{
> +	struct scaler_ctx *ctx = ctrl_to_ctx(ctrl);
> +	unsigned long flags;
> +	int ret;
> +
> +	spin_lock_irqsave(&ctx->scaler_dev->slock, flags);
> +	ret = __scaler_try_ctrl(ctx, ctrl);
> +	spin_unlock_irqrestore(&ctx->scaler_dev->slock, flags);
> +
> +	return ret;
> +}
> +
> +static int __scaler_s_ctrl(struct scaler_ctx *ctx, struct v4l2_ctrl *ctrl)
> +{
> +	struct scaler_dev *scaler = ctx->scaler_dev;
> +	struct scaler_variant *variant = scaler->variant;
> +	int ret = 0;
> +
> +	switch (ctrl->id) {
> +	case V4L2_CID_HFLIP:
> +		ctx->hflip = ctrl->val;
> +		break;
> +
> +	case V4L2_CID_VFLIP:
> +		ctx->vflip = ctrl->val;
> +		break;
> +
> +	case V4L2_CID_ROTATE:
> +		ret = scaler_check_scaler_ratio(variant,
> +			ctx->s_frame.selection.width,
> +			ctx->s_frame.selection.height,
> +			ctx->d_frame.selection.width,
> +			ctx->d_frame.selection.height,
> +			ctx->ctrls_scaler.rotate->val);

I think this check is not needed, since it is already done in
__scaler_try_ctrl() ?

> +		if (ret < 0)
> +			return -EINVAL;
> +
> +		ctx->rotation = ctrl->val;
> +		break;
> +
> +	case V4L2_CID_ALPHA_COMPONENT:
> +		ctx->d_frame.alpha = ctrl->val;
> +		break;
> +	}
> +
> +	ctx->state |= SCALER_PARAMS;
> +	return 0;
> +}
> +
> +static int scaler_s_ctrl(struct v4l2_ctrl *ctrl)
> +{
> +	struct scaler_ctx *ctx = ctrl_to_ctx(ctrl);
> +	unsigned long flags;
> +	int ret;
> +
> +	spin_lock_irqsave(&ctx->scaler_dev->slock, flags);
> +	ret = __scaler_s_ctrl(ctx, ctrl);
> +	spin_unlock_irqrestore(&ctx->scaler_dev->slock, flags);
> +
> +	return ret;
> +}
> +
> +static const struct v4l2_ctrl_ops scaler_ctrl_ops = {
> +	.try_ctrl = scaler_try_ctrl,
> +	.s_ctrl = scaler_s_ctrl,
> +};
> +
> +int scaler_ctrls_create(struct scaler_ctx *ctx)
> +{
> +	if (ctx->ctrls_rdy) {
> +		scaler_dbg(ctx->scaler_dev,
> +			"Control handler of this ctx was created already");
> +		return 0;
> +	}
> +
> +	v4l2_ctrl_handler_init(&ctx->ctrl_handler, SCALER_MAX_CTRL_NUM);
> +
> +	ctx->ctrls_scaler.rotate = v4l2_ctrl_new_std(&ctx->ctrl_handler,
> +		&scaler_ctrl_ops, V4L2_CID_ROTATE, 0, 270, 90, 0);
> +	ctx->ctrls_scaler.hflip = v4l2_ctrl_new_std(&ctx->ctrl_handler,
> +		&scaler_ctrl_ops, V4L2_CID_HFLIP, 0, 1, 1, 0);
> +	ctx->ctrls_scaler.vflip = v4l2_ctrl_new_std(&ctx->ctrl_handler,
> +		&scaler_ctrl_ops, V4L2_CID_VFLIP, 0, 1, 1, 0);
> +	ctx->ctrls_scaler.global_alpha = v4l2_ctrl_new_std(&ctx->ctrl_handler,
> +		&scaler_ctrl_ops, V4L2_CID_ALPHA_COMPONENT, 0, 255, 1, 0);
> +
> +	ctx->ctrls_rdy = ctx->ctrl_handler.error == 0;
> +
> +	if (ctx->ctrl_handler.error) {
> +		int err = ctx->ctrl_handler.error;
> +		v4l2_ctrl_handler_free(&ctx->ctrl_handler);
> +		scaler_dbg(ctx->scaler_dev,

This should probably be dev_err().

> +			"Failed to create SCALER control handlers");
> +		return err;
> +	}
> +
> +	return 0;
> +}
> +
> +void scaler_ctrls_delete(struct scaler_ctx *ctx)
> +{
> +	if (ctx->ctrls_rdy) {
> +		v4l2_ctrl_handler_free(&ctx->ctrl_handler);
> +		ctx->ctrls_rdy = false;
> +	}
> +}
> +
> +/* The color format (num_comp, num_planes) must be already configured. */
> +int scaler_prepare_addr(struct scaler_ctx *ctx, struct vb2_buffer *vb,
> +			struct scaler_frame *frame, struct scaler_addr *addr)
> +{
> +	int ret = 0;
> +	u32 pix_size;
> +	const struct scaler_fmt *fmt;
> +
> +	if (vb == NULL || frame == NULL)
> +		return -EINVAL;
> +
> +	pix_size = frame->f_width * frame->f_height;
> +	fmt = frame->fmt;
> +
> +	scaler_dbg(ctx->scaler_dev,
> +			"planes= %d, comp= %d, pix_size= %d, fmt = %d\n",
> +			fmt->num_planes, fmt->num_comp,
> +			pix_size, fmt->scaler_color);

Alignment seems wrong here.

> +	addr->y = vb2_dma_contig_plane_dma_addr(vb, 0);
> +
> +	if (fmt->num_planes == 1) {
> +		switch (fmt->num_comp) {
> +		case 1:
> +			addr->cb = 0;
> +			addr->cr = 0;
> +			break;
> +		case 2:
> +			/* Decompose Y into Y/Cb */
> +			addr->cb = (dma_addr_t)(addr->y + pix_size);
> +			addr->cr = 0;
> +			break;
> +		case 3:
> +			/* Decompose Y into Y/Cb/Cr */
> +			addr->cb = (dma_addr_t)(addr->y + pix_size);
> +			if (SCALER_YUV420 == fmt->color)
> +				addr->cr = (dma_addr_t)(addr->cb
> +						+ (pix_size >> 2));
> +			else if (SCALER_YUV422 == fmt->color)
> +				addr->cr = (dma_addr_t)(addr->cb
> +						+ (pix_size >> 1));
> +			else /* 444 */
> +				addr->cr = (dma_addr_t)(addr->cb + pix_size);
> +			break;
> +		default:
> +			scaler_dbg(ctx->scaler_dev,
> +				"Invalid number of color planes\n");
> +			return -EINVAL;
> +		}
> +	} else {
> +		if (fmt->num_planes >= 2)
> +			addr->cb = vb2_dma_contig_plane_dma_addr(vb, 1);
> +
> +		if (fmt->num_planes == 3)
> +			addr->cr = vb2_dma_contig_plane_dma_addr(vb, 2);
> +	}
> +
> +	if ((fmt->color_order == SCALER_CRCB) && (fmt->num_planes == 3))
> +		swap(addr->cb, addr->cr);
> +
> +	if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type))
> +		scaler_dbg(ctx->scaler_dev,
> +			 "\nIN:ADDR: y= 0x%X  cb= 0x%X cr= 0x%X ret= %d\n",
> +			 addr->y, addr->cb, addr->cr, ret);
> +	else
> +		scaler_dbg(ctx->scaler_dev,
> +			 "\nOUT:ADDR: y= 0x%X  cb= 0x%X cr= 0x%X ret= %d\n",
> +			 addr->y, addr->cb, addr->cr, ret);
> +
> +	return ret;
> +}
> +
> +static void scaler_sw_reset(struct scaler_dev *scaler)
> +{
> +	scaler_hw_set_sw_reset(scaler);
> +	scaler_wait_reset(scaler);
> +
> +	scaler->coeff_type = SCALER_CSC_COEFF_NONE;
> +}
> +
> +static void scaler_check_for_illegal_status(struct device *dev,
> +					  unsigned int irq_status)
> +{
> +	int i;
> +
> +	for (i = 0; i < SCALER_NUM_ERRORS; i++)
> +		if ((1 << scaler_errors[i].irq_num) & irq_status)
> +			dev_err(dev, "ERROR:: %s\n", scaler_errors[i].name);
> +}
> +
> +static irqreturn_t scaler_irq_handler(int irq, void *priv)
> +{
> +	struct scaler_dev *scaler = priv;
> +	struct scaler_ctx *ctx;
> +	unsigned int scaler_irq;
> +	struct device *dev = &scaler->pdev->dev;
> +
> +	scaler_irq = scaler_hw_get_irq_status(scaler);
> +	scaler_dbg(scaler, "irq_status: 0x%x\n", scaler_irq);
> +	scaler_hw_clear_irq(scaler, scaler_irq);
> +
> +	if (scaler_irq & SCALER_INT_STATUS_ERROR)
> +		scaler_check_for_illegal_status(dev, scaler_irq);
> +
> +	if (!(scaler_irq & (1 << SCALER_INT_FRAME_END)))
> +		return IRQ_HANDLED;
> +
> +	spin_lock(&scaler->slock);
> +
> +	if (test_and_clear_bit(ST_M2M_PEND, &scaler->state)) {
> +
> +		scaler_hw_enable_control(scaler, false);
> +
> +		if (test_and_clear_bit(ST_M2M_SUSPENDING, &scaler->state)) {
> +			set_bit(ST_M2M_SUSPENDED, &scaler->state);
> +			wake_up(&scaler->irq_queue);
> +			goto isr_unlock;
> +		}
> +		ctx = v4l2_m2m_get_curr_priv(scaler->m2m.m2m_dev);
> +
> +		if (!ctx || !ctx->m2m_ctx)
> +			goto isr_unlock;
> +
> +		spin_unlock(&scaler->slock);
> +		scaler_m2m_job_finish(ctx, VB2_BUF_STATE_DONE);
> +
> +		/* wake_up job_abort, stop_streaming */
> +		if (ctx->state & SCALER_CTX_STOP_REQ) {
> +			ctx->state &= ~SCALER_CTX_STOP_REQ;
> +			wake_up(&scaler->irq_queue);
> +		}
> +		return IRQ_HANDLED;
> +	}
> +
> +isr_unlock:
> +	spin_unlock(&scaler->slock);
> +	return IRQ_HANDLED;
> +}
> +
> +static struct scaler_frm_limit scaler_frm_limit_5410 = {
> +	.min_w = 4,
> +	.min_h = 4,
> +	.max_w = 4096,
> +	.max_h = 4096,
> +};
> +
> +static struct scaler_frm_limit scaler_inp_frm_limit_5420 = {
> +	.min_w = 16,
> +	.min_h = 16,
> +	.max_w = 8192,
> +	.max_h = 8192,
> +};
> +
> +static struct scaler_frm_limit scaler_out_frm_limit_5420 = {
> +	.min_w = 4,
> +	.min_h = 4,
> +	.max_w = 8192,
> +	.max_h = 8192,
> +};
> +
> +static struct scaler_pix_align scaler_align_info = {
> +	.src_w_420 = 2,
> +	.src_w_422 = 2,
> +	.src_h_420 = 2,
> +	.dst_w_420 = 2,
> +	.dst_w_422 = 2,
> +	.dst_h_420 = 2,
> +};
> +
> +
> +static struct scaler_variant scaler_variant_info_5410 = {
> +	.pix_in		= &scaler_frm_limit_5410,
> +	.pix_out	= &scaler_frm_limit_5410,
> +	.pix_align	= &scaler_align_info,
> +	.scl_up_max	= 16,
> +	.scl_down_max	= 4,
> +	.in_buf_cnt	= 32,
> +	.out_buf_cnt	= 32,
> +};
> +
> +static struct scaler_variant scaler_variant_info_5420 = {
> +	.pix_in		= &scaler_inp_frm_limit_5420,
> +	.pix_out	= &scaler_out_frm_limit_5420,
> +	.pix_align	= &scaler_align_info,
> +	.scl_up_max	= 16,
> +	.scl_down_max	= 4,
> +	.in_buf_cnt	= 32,
> +	.out_buf_cnt	= 32,
> +};
> +
> +static const struct of_device_id exynos_scaler_match[] = {
> +	{
> +		.compatible = "samsung,exynos5410-scaler",
> +		.data = &scaler_variant_info_5410,
> +	},
> +	{
> +		.compatible = "samsung,exynos5420-scaler",
> +		.data = &scaler_variant_info_5420,
> +	},
> +	{},
> +};
> +MODULE_DEVICE_TABLE(of, exynos_scaler_match);
> +
> +static void *scaler_get_variant_data(struct platform_device *pdev)
> +{
> +	if (pdev->dev.of_node) {
> +		const struct of_device_id *match;
> +		match = of_match_node(exynos_scaler_match, pdev->dev.of_node);
> +		if (match)
> +			return (void *)match->data;
> +	}
> +
> +	return NULL;
> +}
> +
> +static void scaler_clk_put(struct scaler_dev *scaler)
> +{
> +	if (!IS_ERR(scaler->clock))
> +		clk_unprepare(scaler->clock);
> +}
> +
> +static int scaler_clk_get(struct scaler_dev *scaler)
> +{
> +	int ret;
> +
> +	scaler_dbg(scaler, "scaler_clk_get Called\n");
> +
> +	scaler->clock = devm_clk_get(&scaler->pdev->dev,
> +					SCALER_CLOCK_GATE_NAME);
> +	if (IS_ERR(scaler->clock)) {
> +		dev_err(&scaler->pdev->dev, "failed to get clock~~~: %s\n",
> +			SCALER_CLOCK_GATE_NAME);

Perhaps remove "~~~" ?

> +		return PTR_ERR(scaler->clock);
> +	}
> +
> +	ret = clk_prepare(scaler->clock);
> +	if (ret < 0) {
> +		dev_err(&scaler->pdev->dev,
> +			"clock prepare fail for clock: %s\n",
> +			SCALER_CLOCK_GATE_NAME);
> +		scaler->clock = ERR_PTR(-EINVAL);
> +		return ret;
> +	}
> +
> +	return 0;
> +}

Thanks,
Sylwester

  reply	other threads:[~2013-10-18  9:07 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-10-04 12:26 [PATCH v4 0/4] Exynos5 Series SCALER Driver Shaik Ameer Basha
2013-10-04 12:26 ` [PATCH v4 1/4] [media] exynos-scaler: Add new driver for Exynos5 SCALER Shaik Ameer Basha
2013-10-18  8:57   ` Sylwester Nawrocki
2013-10-20 12:33     ` Shaik Ameer Basha
2013-10-20 18:25       ` Sylwester Nawrocki
2014-01-02 20:18   ` Mauro Carvalho Chehab
2014-01-07  3:52     ` Shaik Ameer Basha
2013-10-04 12:26 ` [PATCH v4 2/4] [media] exynos-scaler: Add core functionality for the SCALER driver Shaik Ameer Basha
2013-10-18  9:07   ` Sylwester Nawrocki [this message]
2014-01-02 20:25   ` Mauro Carvalho Chehab
2014-01-07  3:59     ` Shaik Ameer Basha
2013-10-04 12:26 ` [PATCH v4 3/4] [media] exynos-scaler: Add m2m " Shaik Ameer Basha
2013-10-16  9:56   ` Kamil Debski
2013-10-18  5:41     ` Arun Kumar K
2013-10-18  9:11   ` Sylwester Nawrocki
2013-10-04 12:26 ` [PATCH v4 4/4] [media] exynos-scaler: Add DT bindings for " Shaik Ameer Basha
2013-10-18  9:14   ` Sylwester Nawrocki

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=5260FA6A.3000303@samsung.com \
    --to=s.nawrocki@samsung.com \
    --cc=arun.kk@samsung.com \
    --cc=hverkuil@xs4all.nl \
    --cc=inki.dae@samsung.com \
    --cc=linux-media@vger.kernel.org \
    --cc=linux-samsung-soc@vger.kernel.org \
    --cc=posciak@google.com \
    --cc=shaik.ameer@samsung.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.