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.nawro...@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.p...@samsung.com>
> ---
>  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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to