Re: [PATCH v2 2/2] s5p-fimc: Add support for alpha component configuration

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Friday 25 November 2011 16:39:32 Sylwester Nawrocki wrote:
> On Exynos SoCs the FIMC IP allows to configure globally the alpha
> component of all pixels for V4L2_PIX_FMT_RGB32, V4L2_PIX_FMT_RGB555
> and V4L2_PIX_FMT_RGB444 image formats. This patch adds a v4l2 control
> in order to let the applications control the alpha component value.
> 
> The alpha value range depends on the pixel format, for RGB32 it's
> 0..255 (8-bits), for RGB555 - 0..1 (1-bit) and for RGB444 - 0..15
> (4-bits). The v4l2 control range is always 0..255 and the alpha
> component data width is determined by currently set format on the
> V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE buffer queue. The applications
> need to match the alpha channel data width and the pixel format
> since the driver will ignore the alpha component bits that are not
> applicable to the configured pixel format.

Will the driver ignore the least significant bits or the most significant 
bits?

Regards,

	Hans

> 
> A new entry is added in the variant description data structure
> so an additional control is created only where really supported
> by the hardware.
> 
> Signed-off-by: Sylwester Nawrocki <s.nawrocki@xxxxxxxxxxx>
> Signed-off-by: Kyungmin Park <kyungmin.park@xxxxxxxxxxx>
> ---
>  drivers/media/video/s5p-fimc/fimc-capture.c |    4 ++
>  drivers/media/video/s5p-fimc/fimc-core.c    |   49
> ++++++++++++++++++++++--- drivers/media/video/s5p-fimc/fimc-core.h    |  
> 13 ++++++-
>  drivers/media/video/s5p-fimc/fimc-reg.c     |   53
> +++++++++++++++++++++------ drivers/media/video/s5p-fimc/regs-fimc.h    | 
>   5 +++
>  5 files changed, 105 insertions(+), 19 deletions(-)
> 
> diff --git a/drivers/media/video/s5p-fimc/fimc-capture.c
> b/drivers/media/video/s5p-fimc/fimc-capture.c index 82d9ab6..70176e5
> 100644
> --- a/drivers/media/video/s5p-fimc/fimc-capture.c
> +++ b/drivers/media/video/s5p-fimc/fimc-capture.c
> @@ -63,6 +63,8 @@ static int fimc_init_capture(struct fimc_dev *fimc)
>  		fimc_hw_set_effect(ctx, false);
>  		fimc_hw_set_output_path(ctx);
>  		fimc_hw_set_out_dma(ctx);
> +		if (fimc->variant->has_alpha)
> +			fimc_hw_set_rgb_alpha(ctx);
>  		clear_bit(ST_CAPT_APPLY_CFG, &fimc->state);
>  	}
>  	spin_unlock_irqrestore(&fimc->slock, flags);
> @@ -154,6 +156,8 @@ int fimc_capture_config_update(struct fimc_ctx *ctx)
>  		fimc_hw_set_rotation(ctx);
>  		fimc_prepare_dma_offset(ctx, &ctx->d_frame);
>  		fimc_hw_set_out_dma(ctx);
> +		if (fimc->variant->has_alpha)
> +			fimc_hw_set_rgb_alpha(ctx);
>  		clear_bit(ST_CAPT_APPLY_CFG, &fimc->state);
>  	}
>  	spin_unlock(&ctx->slock);
> diff --git a/drivers/media/video/s5p-fimc/fimc-core.c
> b/drivers/media/video/s5p-fimc/fimc-core.c index 567e9ea..5fe9aeb 100644
> --- a/drivers/media/video/s5p-fimc/fimc-core.c
> +++ b/drivers/media/video/s5p-fimc/fimc-core.c
> @@ -52,13 +52,29 @@ static struct fimc_fmt fimc_formats[] = {
>  		.colplanes	= 1,
>  		.flags		= FMT_FLAGS_M2M,
>  	}, {
> -		.name		= "XRGB-8-8-8-8, 32 bpp",
> +		.name		= "ARGB8888, 32 bpp",
>  		.fourcc		= V4L2_PIX_FMT_RGB32,
>  		.depth		= { 32 },
>  		.color		= S5P_FIMC_RGB888,
>  		.memplanes	= 1,
>  		.colplanes	= 1,
> -		.flags		= FMT_FLAGS_M2M,
> +		.flags		= FMT_FLAGS_M2M | FMT_HAS_ALPHA,
> +	}, {
> +		.name		= "ARGB1555",
> +		.fourcc		= V4L2_PIX_FMT_RGB555,
> +		.depth		= { 16 },
> +		.color		= S5P_FIMC_RGB555,
> +		.memplanes	= 1,
> +		.colplanes	= 1,
> +		.flags		= FMT_FLAGS_M2M | FMT_HAS_ALPHA,
> +	}, {
> +		.name		= "ARGB4444",
> +		.fourcc		= V4L2_PIX_FMT_RGB444,
> +		.depth		= { 16 },
> +		.color		= S5P_FIMC_RGB444,
> +		.memplanes	= 1,
> +		.colplanes	= 1,
> +		.flags		= FMT_FLAGS_M2M | FMT_HAS_ALPHA,
>  	}, {
>  		.name		= "YUV 4:2:2 packed, YCbYCr",
>  		.fourcc		= V4L2_PIX_FMT_YUYV,
> @@ -652,8 +668,11 @@ static void fimc_dma_run(void *priv)
>  	if (ctx->state & (FIMC_DST_ADDR | FIMC_PARAMS))
>  		fimc_hw_set_output_addr(fimc, &ctx->d_frame.paddr, -1);
> 
> -	if (ctx->state & FIMC_PARAMS)
> +	if (ctx->state & FIMC_PARAMS) {
>  		fimc_hw_set_out_dma(ctx);
> +		if (fimc->variant->has_alpha)
> +			fimc_hw_set_rgb_alpha(ctx);
> +	}
> 
>  	fimc_activate_capture(ctx);
> 
> @@ -790,6 +809,11 @@ static int fimc_s_ctrl(struct v4l2_ctrl *ctrl)
>  		ctx->rotation = ctrl->val;
>  		break;
> 
> +	case V4L2_CID_ALPHA_COMPONENT:
> +		spin_lock_irqsave(&ctx->slock, flags);
> +		ctx->d_frame.alpha = ctrl->val;
> +		break;
> +
>  	default:
>  		v4l2_err(fimc->v4l2_dev, "Invalid control: 0x%X\n", ctrl->id);
>  		return -EINVAL;
> @@ -806,9 +830,11 @@ static const struct v4l2_ctrl_ops fimc_ctrl_ops = {
> 
>  int fimc_ctrls_create(struct fimc_ctx *ctx)
>  {
> +	struct samsung_fimc_variant *variant = ctx->fimc_dev->variant;
> +
>  	if (ctx->ctrls_rdy)
>  		return 0;
> -	v4l2_ctrl_handler_init(&ctx->ctrl_handler, 3);
> +	v4l2_ctrl_handler_init(&ctx->ctrl_handler, 4);
> 
>  	ctx->ctrl_rotate = v4l2_ctrl_new_std(&ctx->ctrl_handler, 
&fimc_ctrl_ops,
>  				     V4L2_CID_HFLIP, 0, 1, 1, 0);
> @@ -816,6 +842,14 @@ int fimc_ctrls_create(struct fimc_ctx *ctx)
>  				    V4L2_CID_VFLIP, 0, 1, 1, 0);
>  	ctx->ctrl_vflip = v4l2_ctrl_new_std(&ctx->ctrl_handler, 
&fimc_ctrl_ops,
>  				    V4L2_CID_ROTATE, 0, 270, 90, 0);
> +
> +	if (variant->has_alpha)
> +		ctx->ctrl_alpha = v4l2_ctrl_new_std(&ctx->ctrl_handler,
> +				    &fimc_ctrl_ops, V4L2_CID_ALPHA_COMPONENT,
> +				    0, 0xff, 1, 0);
> +	else
> +		ctx->ctrl_alpha = NULL;
> +
>  	ctx->ctrls_rdy = ctx->ctrl_handler.error == 0;
> 
>  	return ctx->ctrl_handler.error;
> @@ -838,6 +872,8 @@ void fimc_ctrls_activate(struct fimc_ctx *ctx, bool
> active) v4l2_ctrl_activate(ctx->ctrl_rotate, active);
>  	v4l2_ctrl_activate(ctx->ctrl_hflip, active);
>  	v4l2_ctrl_activate(ctx->ctrl_vflip, active);
> +	if (ctx->ctrl_alpha)
> +		v4l2_ctrl_activate(ctx->ctrl_alpha, active);
> 
>  	if (active) {
>  		ctx->rotation = ctx->ctrl_rotate->val;
> @@ -1374,6 +1410,8 @@ static int fimc_m2m_open(struct file *file)
>  	if (!ctx)
>  		return -ENOMEM;
>  	v4l2_fh_init(&ctx->fh, fimc->m2m.vfd);
> +	ctx->fimc_dev = fimc;
> +
>  	ret = fimc_ctrls_create(ctx);
>  	if (ret)
>  		goto error_fh;
> @@ -1383,7 +1421,6 @@ static int fimc_m2m_open(struct file *file)
>  	file->private_data = &ctx->fh;
>  	v4l2_fh_add(&ctx->fh);
> 
> -	ctx->fimc_dev = fimc;
>  	/* Default color format */
>  	ctx->s_frame.fmt = &fimc_formats[0];
>  	ctx->d_frame.fmt = &fimc_formats[0];
> @@ -1892,6 +1929,7 @@ static struct samsung_fimc_variant
> fimc0_variant_exynos4 = { .has_cam_if	 = 1,
>  	.has_cistatus2	 = 1,
>  	.has_mainscaler_ext = 1,
> +	.has_alpha	 = 1,
>  	.min_inp_pixsize = 16,
>  	.min_out_pixsize = 16,
>  	.hor_offs_align	 = 2,
> @@ -1905,6 +1943,7 @@ static struct samsung_fimc_variant
> fimc3_variant_exynos4 = { .has_cam_if	 = 1,
>  	.has_cistatus2	 = 1,
>  	.has_mainscaler_ext = 1,
> +	.has_alpha	 = 1,
>  	.min_inp_pixsize = 16,
>  	.min_out_pixsize = 16,
>  	.hor_offs_align	 = 2,
> diff --git a/drivers/media/video/s5p-fimc/fimc-core.h
> b/drivers/media/video/s5p-fimc/fimc-core.h index c7f01c4..9d1f669 100644
> --- a/drivers/media/video/s5p-fimc/fimc-core.h
> +++ b/drivers/media/video/s5p-fimc/fimc-core.h
> @@ -85,11 +85,14 @@ enum fimc_datapath {
>  };
> 
>  enum fimc_color_fmt {
> -	S5P_FIMC_RGB565 = 0x10,
> +	S5P_FIMC_RGB444 = 0x10,
> +	S5P_FIMC_RGB555,
> +	S5P_FIMC_RGB565,
>  	S5P_FIMC_RGB666,
>  	S5P_FIMC_RGB888,
>  	S5P_FIMC_RGB30_LOCAL,
>  	S5P_FIMC_YCBCR420 = 0x20,
> +	S5P_FIMC_YCBCR422,
>  	S5P_FIMC_YCBYCR422,
>  	S5P_FIMC_YCRYCB422,
>  	S5P_FIMC_CBYCRY422,
> @@ -162,6 +165,7 @@ struct fimc_fmt {
>  	u16	flags;
>  #define FMT_FLAGS_CAM	(1 << 0)
>  #define FMT_FLAGS_M2M	(1 << 1)
> +#define FMT_HAS_ALPHA	(1 << 2)
>  };
> 
>  /**
> @@ -283,6 +287,7 @@ struct fimc_frame {
>  	struct fimc_addr	paddr;
>  	struct fimc_dma_offset	dma_offset;
>  	struct fimc_fmt		*fmt;
> +	u8			alpha;
>  };
> 
>  /**
> @@ -387,6 +392,7 @@ struct samsung_fimc_variant {
>  	unsigned int	has_cistatus2:1;
>  	unsigned int	has_mainscaler_ext:1;
>  	unsigned int	has_cam_if:1;
> +	unsigned int	has_alpha:1;
>  	struct fimc_pix_limit *pix_limit;
>  	u16		min_inp_pixsize;
>  	u16		min_out_pixsize;
> @@ -482,7 +488,8 @@ struct fimc_dev {
>   * @ctrl_handler:	v4l2 controls handler
>   * @ctrl_rotate		image rotation control
>   * @ctrl_hflip		horizontal flip control
> - * @ctrl_vflip		vartical flip control
> + * @ctrl_vflip		vertical flip control
> + * @ctrl_alpha		RGB alpha control
>   * @ctrls_rdy:		true if the control handler is initialized
>   */
>  struct fimc_ctx {
> @@ -509,6 +516,7 @@ struct fimc_ctx {
>  	struct v4l2_ctrl	*ctrl_rotate;
>  	struct v4l2_ctrl	*ctrl_hflip;
>  	struct v4l2_ctrl	*ctrl_vflip;
> +	struct v4l2_ctrl	*ctrl_alpha;
>  	bool			ctrls_rdy;
>  };
> 
> @@ -674,6 +682,7 @@ void fimc_hw_set_prescaler(struct fimc_ctx *ctx);
>  void fimc_hw_set_mainscaler(struct fimc_ctx *ctx);
>  void fimc_hw_en_capture(struct fimc_ctx *ctx);
>  void fimc_hw_set_effect(struct fimc_ctx *ctx, bool active);
> +void fimc_hw_set_rgb_alpha(struct fimc_ctx *ctx);
>  void fimc_hw_set_in_dma(struct fimc_ctx *ctx);
>  void fimc_hw_set_input_path(struct fimc_ctx *ctx);
>  void fimc_hw_set_output_path(struct fimc_ctx *ctx);
> diff --git a/drivers/media/video/s5p-fimc/fimc-reg.c
> b/drivers/media/video/s5p-fimc/fimc-reg.c index 44f5c2d..15466d0 100644
> --- a/drivers/media/video/s5p-fimc/fimc-reg.c
> +++ b/drivers/media/video/s5p-fimc/fimc-reg.c
> @@ -117,7 +117,7 @@ void fimc_hw_set_target_format(struct fimc_ctx *ctx)
>  		  S5P_CITRGFMT_VSIZE_MASK);
> 
>  	switch (frame->fmt->color) {
> -	case S5P_FIMC_RGB565...S5P_FIMC_RGB888:
> +	case S5P_FIMC_RGB444...S5P_FIMC_RGB888:
>  		cfg |= S5P_CITRGFMT_RGB;
>  		break;
>  	case S5P_FIMC_YCBCR420:
> @@ -175,6 +175,7 @@ void fimc_hw_set_out_dma(struct fimc_ctx *ctx)
>  	struct fimc_dev *dev = ctx->fimc_dev;
>  	struct fimc_frame *frame = &ctx->d_frame;
>  	struct fimc_dma_offset *offset = &frame->dma_offset;
> +	struct fimc_fmt *fmt = frame->fmt;
> 
>  	/* Set the input dma offsets. */
>  	cfg = 0;
> @@ -198,15 +199,22 @@ void fimc_hw_set_out_dma(struct fimc_ctx *ctx)
>  	cfg = readl(dev->regs + S5P_CIOCTRL);
> 
>  	cfg &= ~(S5P_CIOCTRL_ORDER2P_MASK | S5P_CIOCTRL_ORDER422_MASK |
> -		 S5P_CIOCTRL_YCBCR_PLANE_MASK);
> +		 S5P_CIOCTRL_YCBCR_PLANE_MASK | S5P_CIOCTRL_RGB16FMT_MASK);
> 
> -	if (frame->fmt->colplanes == 1)
> +	if (fmt->colplanes == 1)
>  		cfg |= ctx->out_order_1p;
> -	else if (frame->fmt->colplanes == 2)
> +	else if (fmt->colplanes == 2)
>  		cfg |= ctx->out_order_2p | S5P_CIOCTRL_YCBCR_2PLANE;
> -	else if (frame->fmt->colplanes == 3)
> +	else if (fmt->colplanes == 3)
>  		cfg |= S5P_CIOCTRL_YCBCR_3PLANE;
> 
> +	if (fmt->color == S5P_FIMC_RGB565)
> +		cfg |= S5P_CIOCTRL_RGB565;
> +	else if (fmt->color == S5P_FIMC_RGB555)
> +		cfg |= S5P_CIOCTRL_ARGB1555;
> +	else if (fmt->color == S5P_FIMC_RGB444)
> +		cfg |= S5P_CIOCTRL_ARGB4444;
> +
>  	writel(cfg, dev->regs + S5P_CIOCTRL);
>  }
> 
> @@ -278,22 +286,28 @@ static void fimc_hw_set_scaler(struct fimc_ctx *ctx)
>  	if (sc->copy_mode)
>  		cfg |= S5P_CISCCTRL_ONE2ONE;
> 
> -
>  	if (ctx->in_path == FIMC_DMA) {
> -		if (src_frame->fmt->color == S5P_FIMC_RGB565)
> +		switch (src_frame->fmt->color) {
> +		case S5P_FIMC_RGB565:
>  			cfg |= S5P_CISCCTRL_INRGB_FMT_RGB565;
> -		else if (src_frame->fmt->color == S5P_FIMC_RGB666)
> +			break;
> +		case S5P_FIMC_RGB666:
>  			cfg |= S5P_CISCCTRL_INRGB_FMT_RGB666;
> -		else if (src_frame->fmt->color == S5P_FIMC_RGB888)
> +			break;
> +		case S5P_FIMC_RGB888:
>  			cfg |= S5P_CISCCTRL_INRGB_FMT_RGB888;
> +			break;
> +		}
>  	}
> 
>  	if (ctx->out_path == FIMC_DMA) {
> -		if (dst_frame->fmt->color == S5P_FIMC_RGB565)
> +		u32 color = dst_frame->fmt->color;
> +
> +		if (color >= S5P_FIMC_RGB444 && color <= S5P_FIMC_RGB565)
>  			cfg |= S5P_CISCCTRL_OUTRGB_FMT_RGB565;
> -		else if (dst_frame->fmt->color == S5P_FIMC_RGB666)
> +		else if (color == S5P_FIMC_RGB666)
>  			cfg |= S5P_CISCCTRL_OUTRGB_FMT_RGB666;
> -		else if (dst_frame->fmt->color == S5P_FIMC_RGB888)
> +		else if (color == S5P_FIMC_RGB888)
>  			cfg |= S5P_CISCCTRL_OUTRGB_FMT_RGB888;
>  	} else {
>  		cfg |= S5P_CISCCTRL_OUTRGB_FMT_RGB888;
> @@ -379,6 +393,21 @@ void fimc_hw_set_effect(struct fimc_ctx *ctx, bool
> active) writel(cfg, dev->regs + S5P_CIIMGEFF);
>  }
> 
> +void fimc_hw_set_rgb_alpha(struct fimc_ctx *ctx)
> +{
> +	struct fimc_dev *dev = ctx->fimc_dev;
> +	struct fimc_frame *frame = &ctx->d_frame;
> +	u32 cfg;
> +
> +	if (!(frame->fmt->flags & FMT_HAS_ALPHA))
> +		return;
> +
> +	cfg = readl(dev->regs + S5P_CIOCTRL);
> +	cfg &= ~S5P_CIOCTRL_ALPHA_OUT_MASK;
> +	cfg |= (frame->alpha << 4);
> +	writel(cfg, dev->regs + S5P_CIOCTRL);
> +}
> +
>  static void fimc_hw_set_in_dma_size(struct fimc_ctx *ctx)
>  {
>  	struct fimc_dev *dev = ctx->fimc_dev;
> diff --git a/drivers/media/video/s5p-fimc/regs-fimc.h
> b/drivers/media/video/s5p-fimc/regs-fimc.h index c8e3b94..c7a5bc5 100644
> --- a/drivers/media/video/s5p-fimc/regs-fimc.h
> +++ b/drivers/media/video/s5p-fimc/regs-fimc.h
> @@ -107,6 +107,11 @@
>  #define S5P_CIOCTRL_YCBCR_3PLANE	(0 << 3)
>  #define S5P_CIOCTRL_YCBCR_2PLANE	(1 << 3)
>  #define S5P_CIOCTRL_YCBCR_PLANE_MASK	(1 << 3)
> +#define S5P_CIOCTRL_ALPHA_OUT_MASK	(0xff << 4)
> +#define S5P_CIOCTRL_RGB16FMT_MASK	(3 << 16)
> +#define S5P_CIOCTRL_RGB565		(0 << 16)
> +#define S5P_CIOCTRL_ARGB1555		(1 << 16)
> +#define S5P_CIOCTRL_ARGB4444		(2 << 16)
>  #define S5P_CIOCTRL_ORDER2P_SHIFT	(24)
>  #define S5P_CIOCTRL_ORDER2P_MASK	(3 << 24)
>  #define S5P_CIOCTRL_ORDER422_2P_LSB_CRCB (0 << 24)
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux