[media] s5p-fimc: Add color effect control
[deliverable/linux.git] / drivers / media / video / s5p-fimc / fimc-core.c
index bad9ad018baa08b25664bebb2a3745736f5cea14..fedcd561ba27f37122caa01adf2da1199c3db536 100644 (file)
@@ -463,11 +463,53 @@ void fimc_prepare_dma_offset(struct fimc_ctx *ctx, struct fimc_frame *f)
            f->fmt->color, f->dma_offset.y_h, f->dma_offset.y_v);
 }
 
+int fimc_set_color_effect(struct fimc_ctx *ctx, enum v4l2_colorfx colorfx)
+{
+       struct fimc_effect *effect = &ctx->effect;
+
+       switch (colorfx) {
+       case V4L2_COLORFX_NONE:
+               effect->type = FIMC_REG_CIIMGEFF_FIN_BYPASS;
+               break;
+       case V4L2_COLORFX_BW:
+               effect->type = FIMC_REG_CIIMGEFF_FIN_ARBITRARY;
+               effect->pat_cb = 128;
+               effect->pat_cr = 128;
+               break;
+       case V4L2_COLORFX_SEPIA:
+               effect->type = FIMC_REG_CIIMGEFF_FIN_ARBITRARY;
+               effect->pat_cb = 115;
+               effect->pat_cr = 145;
+               break;
+       case V4L2_COLORFX_NEGATIVE:
+               effect->type = FIMC_REG_CIIMGEFF_FIN_NEGATIVE;
+               break;
+       case V4L2_COLORFX_EMBOSS:
+               effect->type = FIMC_REG_CIIMGEFF_FIN_EMBOSSING;
+               break;
+       case V4L2_COLORFX_ART_FREEZE:
+               effect->type = FIMC_REG_CIIMGEFF_FIN_ARTFREEZE;
+               break;
+       case V4L2_COLORFX_SILHOUETTE:
+               effect->type = FIMC_REG_CIIMGEFF_FIN_SILHOUETTE;
+               break;
+       case V4L2_COLORFX_SET_CBCR:
+               effect->type = FIMC_REG_CIIMGEFF_FIN_ARBITRARY;
+               effect->pat_cb = ctx->ctrls.colorfx_cbcr->val >> 8;
+               effect->pat_cr = ctx->ctrls.colorfx_cbcr->val & 0xff;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 /*
  * V4L2 controls handling
  */
 #define ctrl_to_ctx(__ctrl) \
-       container_of((__ctrl)->handler, struct fimc_ctx, ctrl_handler)
+       container_of((__ctrl)->handler, struct fimc_ctx, ctrls.handler)
 
 static int __fimc_s_ctrl(struct fimc_ctx *ctx, struct v4l2_ctrl *ctrl)
 {
@@ -507,7 +549,14 @@ static int __fimc_s_ctrl(struct fimc_ctx *ctx, struct v4l2_ctrl *ctrl)
        case V4L2_CID_ALPHA_COMPONENT:
                ctx->d_frame.alpha = ctrl->val;
                break;
+
+       case V4L2_CID_COLORFX:
+               ret = fimc_set_color_effect(ctx, ctrl->val);
+               if (ret)
+                       return ret;
+               break;
        }
+
        ctx->state |= FIMC_PARAMS;
        set_bit(ST_CAPT_APPLY_CFG, &fimc->state);
        return 0;
@@ -534,69 +583,91 @@ int fimc_ctrls_create(struct fimc_ctx *ctx)
 {
        struct fimc_variant *variant = ctx->fimc_dev->variant;
        unsigned int max_alpha = fimc_get_alpha_mask(ctx->d_frame.fmt);
+       struct fimc_ctrls *ctrls = &ctx->ctrls;
+       struct v4l2_ctrl_handler *handler = &ctrls->handler;
 
-       if (ctx->ctrls_rdy)
+       if (ctx->ctrls.ready)
                return 0;
-       v4l2_ctrl_handler_init(&ctx->ctrl_handler, 4);
 
-       ctx->ctrl_rotate = v4l2_ctrl_new_std(&ctx->ctrl_handler, &fimc_ctrl_ops,
+       v4l2_ctrl_handler_init(handler, 6);
+
+       ctrls->rotate = v4l2_ctrl_new_std(handler, &fimc_ctrl_ops,
                                        V4L2_CID_ROTATE, 0, 270, 90, 0);
-       ctx->ctrl_hflip = v4l2_ctrl_new_std(&ctx->ctrl_handler, &fimc_ctrl_ops,
+       ctrls->hflip = v4l2_ctrl_new_std(handler, &fimc_ctrl_ops,
                                        V4L2_CID_HFLIP, 0, 1, 1, 0);
-       ctx->ctrl_vflip = v4l2_ctrl_new_std(&ctx->ctrl_handler, &fimc_ctrl_ops,
+       ctrls->vflip = v4l2_ctrl_new_std(handler, &fimc_ctrl_ops,
                                        V4L2_CID_VFLIP, 0, 1, 1, 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);
+               ctrls->alpha = v4l2_ctrl_new_std(handler, &fimc_ctrl_ops,
+                                       V4L2_CID_ALPHA_COMPONENT,
+                                       0, max_alpha, 1, 0);
        else
-               ctx->ctrl_alpha = NULL;
+               ctrls->alpha = NULL;
+
+       ctrls->colorfx = v4l2_ctrl_new_std_menu(handler, &fimc_ctrl_ops,
+                               V4L2_CID_COLORFX, V4L2_COLORFX_SET_CBCR,
+                               ~0x983f, V4L2_COLORFX_NONE);
+
+       ctrls->colorfx_cbcr = v4l2_ctrl_new_std(handler, &fimc_ctrl_ops,
+                               V4L2_CID_COLORFX_CBCR, 0, 0xffff, 1, 0);
 
-       ctx->ctrls_rdy = ctx->ctrl_handler.error == 0;
+       ctx->effect.type = FIMC_REG_CIIMGEFF_FIN_BYPASS;
 
-       return ctx->ctrl_handler.error;
+       if (!handler->error) {
+               v4l2_ctrl_cluster(3, &ctrls->colorfx);
+               ctrls->ready = true;
+       }
+
+       return handler->error;
 }
 
 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;
+       struct fimc_ctrls *ctrls = &ctx->ctrls;
+
+       if (ctrls->ready) {
+               v4l2_ctrl_handler_free(&ctrls->handler);
+               ctrls->ready = false;
+               ctrls->alpha = NULL;
        }
 }
 
 void fimc_ctrls_activate(struct fimc_ctx *ctx, bool active)
 {
        unsigned int has_alpha = ctx->d_frame.fmt->flags & FMT_HAS_ALPHA;
+       struct fimc_ctrls *ctrls = &ctx->ctrls;
 
-       if (!ctx->ctrls_rdy)
+       if (!ctrls->ready)
                return;
 
-       mutex_lock(&ctx->ctrl_handler.lock);
-       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);
+       mutex_lock(&ctrls->handler.lock);
+       v4l2_ctrl_activate(ctrls->rotate, active);
+       v4l2_ctrl_activate(ctrls->hflip, active);
+       v4l2_ctrl_activate(ctrls->vflip, active);
+       v4l2_ctrl_activate(ctrls->colorfx, active);
+       if (ctrls->alpha)
+               v4l2_ctrl_activate(ctrls->alpha, active && has_alpha);
 
        if (active) {
-               ctx->rotation = ctx->ctrl_rotate->val;
-               ctx->hflip    = ctx->ctrl_hflip->val;
-               ctx->vflip    = ctx->ctrl_vflip->val;
+               fimc_set_color_effect(ctx, ctrls->colorfx->cur.val);
+               ctx->rotation = ctrls->rotate->val;
+               ctx->hflip    = ctrls->hflip->val;
+               ctx->vflip    = ctrls->vflip->val;
        } else {
+               ctx->effect.type = FIMC_REG_CIIMGEFF_FIN_BYPASS;
                ctx->rotation = 0;
                ctx->hflip    = 0;
                ctx->vflip    = 0;
        }
-       mutex_unlock(&ctx->ctrl_handler.lock);
+       mutex_unlock(&ctrls->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;
+       struct v4l2_ctrl *ctrl = ctx->ctrls.alpha;
 
        if (ctrl == NULL || !fimc->variant->has_alpha)
                return;
This page took 0.036354 seconds and 5 git commands to generate.