[media] s5p-fimc: Add support for alpha component configuration
authorSylwester Nawrocki <s.nawrocki@samsung.com>
Thu, 1 Dec 2011 17:02:24 +0000 (14:02 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Fri, 30 Dec 2011 16:06:14 +0000 (14:06 -0200)
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 value range and the pixel format
since the driver will clamp the alpha component. Depending on
fourcc the valid alpha bits are:

 - V4L2_PIX_FMT_RGB555  [0]
 - V4L2_PIX_FMT_RGB444  [3:0]
 - V4L2_PIX_FMT_RGB32   [7:0]

When switching to a pixel format with smaller alpha component width
the currently set alpha value will be clamped to maximum value valid
for current format. When switching to a format with wider alpha the
alpha value remains unchanged.

The variant description data structure is extended with a new entry
so an additional control is created only where really supported by
the hardware.

V4L2_PIX_FMT_RGB555 and V4L2_PIX_FMT_RGB444 formats are only valid
for V4L2_BUF_TYPE_VIDEO_CAPTURE buffer queue.

Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/video/s5p-fimc/fimc-capture.c
drivers/media/video/s5p-fimc/fimc-core.c
drivers/media/video/s5p-fimc/fimc-core.h
drivers/media/video/s5p-fimc/fimc-reg.c
drivers/media/video/s5p-fimc/regs-fimc.h

index 2cc3b9166724f2eaf47ea1c05f5a12e5e7208ea7..510cfab477fff48c57ddd2d9151b53ec144f91ea 100644 (file)
@@ -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);
@@ -812,6 +816,10 @@ static int fimc_capture_set_format(struct fimc_dev *fimc, struct v4l2_format *f)
                                          FIMC_SD_PAD_SOURCE);
        if (!ff->fmt)
                return -EINVAL;
+
+       /* Update RGB Alpha control state and value range */
+       fimc_alpha_ctrl_update(ctx);
+
        /* Try to match format at the host and the sensor */
        if (!fimc->vid_cap.user_subdev_api) {
                mf->code   = ff->fmt->mbus_code;
@@ -1235,6 +1243,9 @@ static int fimc_subdev_set_fmt(struct v4l2_subdev *sd,
                *mf = fmt->format;
                return 0;
        }
+       /* Update RGB Alpha control state and value range */
+       fimc_alpha_ctrl_update(ctx);
+
        fimc_capture_mark_jpeg_xfer(ctx, fimc_fmt_is_jpeg(ffmt->color));
 
        ff = fmt->pad == FIMC_SD_PAD_SINK ?
index 07c6254faee32b1ef3ee75964faa2b63b1f7615d..4aaaf1de3a174c4e257ba8e88e69d0b6405d4266 100644 (file)
@@ -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_OUT | FMT_HAS_ALPHA,
+       }, {
+               .name           = "ARGB4444",
+               .fourcc         = V4L2_PIX_FMT_RGB444,
+               .depth          = { 16 },
+               .color          = S5P_FIMC_RGB444,
+               .memplanes      = 1,
+               .colplanes      = 1,
+               .flags          = FMT_FLAGS_M2M_OUT | FMT_HAS_ALPHA,
        }, {
                .name           = "YUV 4:2:2 packed, YCbYCr",
                .fourcc         = V4L2_PIX_FMT_YUYV,
@@ -171,6 +187,14 @@ static struct fimc_fmt fimc_formats[] = {
        },
 };
 
+static unsigned int get_m2m_fmt_flags(unsigned int stream_type)
+{
+       if (stream_type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+               return FMT_FLAGS_M2M_IN;
+       else
+               return FMT_FLAGS_M2M_OUT;
+}
+
 int fimc_check_scaler_ratio(struct fimc_ctx *ctx, int sw, int sh,
                            int dw, int dh, int rotation)
 {
@@ -652,8 +676,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);
 
@@ -750,12 +777,11 @@ static struct vb2_ops fimc_qops = {
 #define ctrl_to_ctx(__ctrl) \
        container_of((__ctrl)->handler, struct fimc_ctx, ctrl_handler)
 
-static int fimc_s_ctrl(struct v4l2_ctrl *ctrl)
+static int __fimc_s_ctrl(struct fimc_ctx *ctx, struct v4l2_ctrl *ctrl)
 {
-       struct fimc_ctx *ctx = ctrl_to_ctx(ctrl);
        struct fimc_dev *fimc = ctx->fimc_dev;
        struct samsung_fimc_variant *variant = fimc->variant;
-       unsigned long flags;
+       unsigned int flags = FIMC_DST_FMT | FIMC_SRC_FMT;
        int ret = 0;
 
        if (ctrl->flags & V4L2_CTRL_FLAG_INACTIVE)
@@ -763,52 +789,63 @@ static int fimc_s_ctrl(struct v4l2_ctrl *ctrl)
 
        switch (ctrl->id) {
        case V4L2_CID_HFLIP:
-               spin_lock_irqsave(&ctx->slock, flags);
                ctx->hflip = ctrl->val;
                break;
 
        case V4L2_CID_VFLIP:
-               spin_lock_irqsave(&ctx->slock, flags);
                ctx->vflip = ctrl->val;
                break;
 
        case V4L2_CID_ROTATE:
                if (fimc_capture_pending(fimc) ||
-                   fimc_ctx_state_is_set(FIMC_DST_FMT | FIMC_SRC_FMT, ctx)) {
+                   (ctx->state & flags) == flags) {
                        ret = fimc_check_scaler_ratio(ctx, ctx->s_frame.width,
                                        ctx->s_frame.height, ctx->d_frame.width,
                                        ctx->d_frame.height, ctrl->val);
-               }
-               if (ret) {
-                       v4l2_err(fimc->m2m.vfd, "Out of scaler range\n");
-                       return -EINVAL;
+                       if (ret)
+                               return -EINVAL;
                }
                if ((ctrl->val == 90 || ctrl->val == 270) &&
                    !variant->has_out_rot)
                        return -EINVAL;
-               spin_lock_irqsave(&ctx->slock, flags);
+
                ctx->rotation = ctrl->val;
                break;
 
-       default:
-               v4l2_err(fimc->v4l2_dev, "Invalid control: 0x%X\n", ctrl->id);
-               return -EINVAL;
+       case V4L2_CID_ALPHA_COMPONENT:
+               ctx->d_frame.alpha = ctrl->val;
+               break;
        }
        ctx->state |= FIMC_PARAMS;
        set_bit(ST_CAPT_APPLY_CFG, &fimc->state);
-       spin_unlock_irqrestore(&ctx->slock, flags);
        return 0;
 }
 
+static int fimc_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct fimc_ctx *ctx = ctrl_to_ctx(ctrl);
+       unsigned long flags;
+       int ret;
+
+       spin_lock_irqsave(&ctx->slock, flags);
+       ret = __fimc_s_ctrl(ctx, ctrl);
+       spin_unlock_irqrestore(&ctx->slock, flags);
+
+       return ret;
+}
+
 static const struct v4l2_ctrl_ops fimc_ctrl_ops = {
        .s_ctrl = fimc_s_ctrl,
 };
 
 int fimc_ctrls_create(struct fimc_ctx *ctx)
 {
+       struct samsung_fimc_variant *variant = ctx->fimc_dev->variant;
+       unsigned int max_alpha = fimc_get_alpha_mask(ctx->d_frame.fmt);
+
        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 +853,13 @@ 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, max_alpha, 1, 0);
+       else
+               ctx->ctrl_alpha = NULL;
+
        ctx->ctrls_rdy = ctx->ctrl_handler.error == 0;
 
        return ctx->ctrl_handler.error;
@@ -826,11 +870,14 @@ void fimc_ctrls_delete(struct fimc_ctx *ctx)
        if (ctx->ctrls_rdy) {
                v4l2_ctrl_handler_free(&ctx->ctrl_handler);
                ctx->ctrls_rdy = false;
+               ctx->ctrl_alpha = NULL;
        }
 }
 
 void fimc_ctrls_activate(struct fimc_ctx *ctx, bool active)
 {
+       unsigned int has_alpha = ctx->d_frame.fmt->flags & FMT_HAS_ALPHA;
+
        if (!ctx->ctrls_rdy)
                return;
 
@@ -838,6 +885,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 && has_alpha);
 
        if (active) {
                ctx->rotation = ctx->ctrl_rotate->val;
@@ -851,6 +900,24 @@ void fimc_ctrls_activate(struct fimc_ctx *ctx, bool active)
        mutex_unlock(&ctx->ctrl_handler.lock);
 }
 
+/* Update maximum value of the alpha color control */
+void fimc_alpha_ctrl_update(struct fimc_ctx *ctx)
+{
+       struct fimc_dev *fimc = ctx->fimc_dev;
+       struct v4l2_ctrl *ctrl = ctx->ctrl_alpha;
+
+       if (ctrl == NULL || !fimc->variant->has_alpha)
+               return;
+
+       v4l2_ctrl_lock(ctrl);
+       ctrl->maximum = fimc_get_alpha_mask(ctx->d_frame.fmt);
+
+       if (ctrl->cur.val > ctrl->maximum)
+               ctrl->cur.val = ctrl->maximum;
+
+       v4l2_ctrl_unlock(ctrl);
+}
+
 /*
  * V4L2 ioctl handlers
  */
@@ -874,7 +941,8 @@ static int fimc_m2m_enum_fmt_mplane(struct file *file, void *priv,
 {
        struct fimc_fmt *fmt;
 
-       fmt = fimc_find_format(NULL, NULL, FMT_FLAGS_M2M, f->index);
+       fmt = fimc_find_format(NULL, NULL, get_m2m_fmt_flags(f->type),
+                              f->index);
        if (!fmt)
                return -EINVAL;
 
@@ -938,6 +1006,7 @@ void fimc_adjust_mplane_format(struct fimc_fmt *fmt, u32 width, u32 height,
        pix->colorspace = V4L2_COLORSPACE_JPEG;
        pix->field = V4L2_FIELD_NONE;
        pix->num_planes = fmt->memplanes;
+       pix->pixelformat = fmt->fourcc;
        pix->height = height;
        pix->width = width;
 
@@ -1017,7 +1086,8 @@ static int fimc_try_fmt_mplane(struct fimc_ctx *ctx, struct v4l2_format *f)
 
        dbg("w: %d, h: %d", pix->width, pix->height);
 
-       fmt = fimc_find_format(&pix->pixelformat, NULL, FMT_FLAGS_M2M, 0);
+       fmt = fimc_find_format(&pix->pixelformat, NULL,
+                              get_m2m_fmt_flags(f->type), 0);
        if (WARN(fmt == NULL, "Pixel format lookup failed"))
                return -EINVAL;
 
@@ -1087,10 +1157,13 @@ static int fimc_m2m_s_fmt_mplane(struct file *file, void *fh,
 
        pix = &f->fmt.pix_mp;
        frame->fmt = fimc_find_format(&pix->pixelformat, NULL,
-                                     FMT_FLAGS_M2M, 0);
+                                     get_m2m_fmt_flags(f->type), 0);
        if (!frame->fmt)
                return -EINVAL;
 
+       /* Update RGB Alpha control state and value range */
+       fimc_alpha_ctrl_update(ctx);
+
        for (i = 0; i < frame->fmt->colplanes; i++) {
                frame->payload[i] =
                        (pix->width * pix->height * frame->fmt->depth[i]) / 8;
@@ -1374,6 +1447,12 @@ static int fimc_m2m_open(struct file *file)
        if (!ctx)
                return -ENOMEM;
        v4l2_fh_init(&ctx->fh, fimc->m2m.vfd);
+       ctx->fimc_dev = fimc;
+
+       /* Default color format */
+       ctx->s_frame.fmt = &fimc_formats[0];
+       ctx->d_frame.fmt = &fimc_formats[0];
+
        ret = fimc_ctrls_create(ctx);
        if (ret)
                goto error_fh;
@@ -1383,10 +1462,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];
        /* Setup the device context for memory-to-memory mode */
        ctx->state = FIMC_CTX_M2M;
        ctx->flags = 0;
@@ -1893,6 +1968,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,
@@ -1906,6 +1982,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,
index c7f01c47b20fe354e101bbf4ab904cab18e3ec55..4e20560c73d4d5ed6e74e81c324cd5ca7cc062ca 100644 (file)
@@ -85,7 +85,9 @@ 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,
@@ -160,8 +162,11 @@ struct fimc_fmt {
        u16     colplanes;
        u8      depth[VIDEO_MAX_PLANES];
        u16     flags;
-#define FMT_FLAGS_CAM  (1 << 0)
-#define FMT_FLAGS_M2M  (1 << 1)
+#define FMT_FLAGS_CAM          (1 << 0)
+#define FMT_FLAGS_M2M_IN       (1 << 1)
+#define FMT_FLAGS_M2M_OUT      (1 << 2)
+#define FMT_FLAGS_M2M          (1 << 1 | 1 << 2)
+#define FMT_HAS_ALPHA          (1 << 3)
 };
 
 /**
@@ -283,6 +288,7 @@ struct fimc_frame {
        struct fimc_addr        paddr;
        struct fimc_dma_offset  dma_offset;
        struct fimc_fmt         *fmt;
+       u8                      alpha;
 };
 
 /**
@@ -387,6 +393,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 +489,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 +517,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;
 };
 
@@ -578,6 +587,17 @@ static inline int tiled_fmt(struct fimc_fmt *fmt)
        return fmt->fourcc == V4L2_PIX_FMT_NV12MT;
 }
 
+/* Return the alpha component bit mask */
+static inline int fimc_get_alpha_mask(struct fimc_fmt *fmt)
+{
+       switch (fmt->color) {
+       case S5P_FIMC_RGB444:   return 0x0f;
+       case S5P_FIMC_RGB555:   return 0x01;
+       case S5P_FIMC_RGB888:   return 0xff;
+       default:                return 0;
+       };
+}
+
 static inline void fimc_hw_clear_irq(struct fimc_dev *dev)
 {
        u32 cfg = readl(dev->regs + S5P_CIGCTRL);
@@ -674,6 +694,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);
@@ -695,6 +716,7 @@ int fimc_vidioc_enum_fmt_mplane(struct file *file, void *priv,
 int fimc_ctrls_create(struct fimc_ctx *ctx);
 void fimc_ctrls_delete(struct fimc_ctx *ctx);
 void fimc_ctrls_activate(struct fimc_ctx *ctx, bool active);
+void fimc_alpha_ctrl_update(struct fimc_ctx *ctx);
 int fimc_fill_format(struct fimc_frame *frame, struct v4l2_format *f);
 void fimc_adjust_mplane_format(struct fimc_fmt *fmt, u32 width, u32 height,
                               struct v4l2_pix_format_mplane *pix);
index 44f5c2d1920bb50dd0dfe8e436eec1df32aa8c3f..15466d0529c14907e2cf2716cd49b1f1da03e8f5 100644 (file)
@@ -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;
index c8e3b94bd91d2ca7cf16c66886a33c9afbe1c290..c7a5bc51d571d860d6daee44a0076b99216d388f 100644 (file)
 #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)