[media] s5p-fimc: Add color effect control

Add support for V4L2_CID_COLORFX control at the mem-to-mem and capture
video nodes.

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>
This commit is contained in:
Sylwester Nawrocki 2012-04-02 06:41:22 -03:00 committed by Mauro Carvalho Chehab
parent 0c9204d342
commit 9448ab7dec
6 changed files with 136 additions and 50 deletions

View file

@ -62,7 +62,7 @@ static int fimc_capture_hw_init(struct fimc_dev *fimc)
fimc_hw_set_mainscaler(ctx);
fimc_hw_set_target_format(ctx);
fimc_hw_set_rotation(ctx);
fimc_hw_set_effect(ctx, false);
fimc_hw_set_effect(ctx);
fimc_hw_set_output_path(ctx);
fimc_hw_set_out_dma(ctx);
if (fimc->variant->has_alpha)
@ -164,6 +164,7 @@ static int fimc_capture_config_update(struct fimc_ctx *ctx)
fimc_hw_set_mainscaler(ctx);
fimc_hw_set_target_format(ctx);
fimc_hw_set_rotation(ctx);
fimc_hw_set_effect(ctx);
fimc_prepare_dma_offset(ctx, &ctx->d_frame);
fimc_hw_set_out_dma(ctx);
if (fimc->variant->has_alpha)
@ -462,14 +463,14 @@ int fimc_capture_ctrls_create(struct fimc_dev *fimc)
if (WARN_ON(vid_cap->ctx == NULL))
return -ENXIO;
if (vid_cap->ctx->ctrls_rdy)
if (vid_cap->ctx->ctrls.ready)
return 0;
ret = fimc_ctrls_create(vid_cap->ctx);
if (ret || vid_cap->user_subdev_api)
if (ret || vid_cap->user_subdev_api || !vid_cap->ctx->ctrls.ready)
return ret;
return v4l2_ctrl_add_handler(&vid_cap->ctx->ctrl_handler,
return v4l2_ctrl_add_handler(&vid_cap->ctx->ctrls.handler,
fimc->pipeline.subdevs[IDX_SENSOR]->ctrl_handler);
}
@ -1588,7 +1589,7 @@ static int fimc_register_capture_device(struct fimc_dev *fimc,
v4l2_info(v4l2_dev, "Registered %s as /dev/%s\n",
vfd->name, video_device_node_name(vfd));
vfd->ctrl_handler = &ctx->ctrl_handler;
vfd->ctrl_handler = &ctx->ctrls.handler;
return 0;
err_vd:

View 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;
ctx->ctrls_rdy = ctx->ctrl_handler.error == 0;
ctrls->colorfx = v4l2_ctrl_new_std_menu(handler, &fimc_ctrl_ops,
V4L2_CID_COLORFX, V4L2_COLORFX_SET_CBCR,
~0x983f, V4L2_COLORFX_NONE);
return ctx->ctrl_handler.error;
ctrls->colorfx_cbcr = v4l2_ctrl_new_std(handler, &fimc_ctrl_ops,
V4L2_CID_COLORFX_CBCR, 0, 0xffff, 1, 0);
ctx->effect.type = FIMC_REG_CIIMGEFF_FIN_BYPASS;
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;

View file

@ -445,6 +445,30 @@ struct fimc_dev {
struct fimc_pipeline pipeline;
};
/**
* struct fimc_ctrls - v4l2 controls structure
* @handler: the control handler
* @colorfx: image effect control
* @colorfx_cbcr: Cb/Cr coefficients control
* @rotate: image rotation control
* @hflip: horizontal flip control
* @vflip: vertical flip control
* @alpha: RGB alpha control
* @ready: true if @handler is initialized
*/
struct fimc_ctrls {
struct v4l2_ctrl_handler handler;
struct {
struct v4l2_ctrl *colorfx;
struct v4l2_ctrl *colorfx_cbcr;
};
struct v4l2_ctrl *rotate;
struct v4l2_ctrl *hflip;
struct v4l2_ctrl *vflip;
struct v4l2_ctrl *alpha;
bool ready;
};
/**
* fimc_ctx - the device context data
* @s_frame: source frame properties
@ -465,12 +489,7 @@ struct fimc_dev {
* @fimc_dev: the FIMC device this context applies to
* @m2m_ctx: memory-to-memory device context
* @fh: v4l2 file handle
* @ctrl_handler: v4l2 controls handler
* @ctrl_rotate image rotation control
* @ctrl_hflip horizontal flip control
* @ctrl_vflip vertical flip control
* @ctrl_alpha RGB alpha control
* @ctrls_rdy: true if the control handler is initialized
* @ctrls: v4l2 controls structure
*/
struct fimc_ctx {
struct fimc_frame s_frame;
@ -491,12 +510,7 @@ struct fimc_ctx {
struct fimc_dev *fimc_dev;
struct v4l2_m2m_ctx *m2m_ctx;
struct v4l2_fh fh;
struct v4l2_ctrl_handler ctrl_handler;
struct v4l2_ctrl *ctrl_rotate;
struct v4l2_ctrl *ctrl_hflip;
struct v4l2_ctrl *ctrl_vflip;
struct v4l2_ctrl *ctrl_alpha;
bool ctrls_rdy;
struct fimc_ctrls ctrls;
};
#define fh_to_ctx(__fh) container_of(__fh, struct fimc_ctx, fh)

View file

@ -150,7 +150,7 @@ static void fimc_device_run(void *priv)
fimc_hw_set_mainscaler(ctx);
fimc_hw_set_target_format(ctx);
fimc_hw_set_rotation(ctx);
fimc_hw_set_effect(ctx, false);
fimc_hw_set_effect(ctx);
fimc_hw_set_out_dma(ctx);
if (fimc->variant->has_alpha)
fimc_hw_set_rgb_alpha(ctx);
@ -669,7 +669,7 @@ static int fimc_m2m_open(struct file *file)
goto error_fh;
/* Use separate control handler per file handle */
ctx->fh.ctrl_handler = &ctx->ctrl_handler;
ctx->fh.ctrl_handler = &ctx->ctrls.handler;
file->private_data = &ctx->fh;
v4l2_fh_add(&ctx->fh);

View file

@ -368,13 +368,13 @@ void fimc_hw_en_capture(struct fimc_ctx *ctx)
writel(cfg, dev->regs + FIMC_REG_CIIMGCPT);
}
void fimc_hw_set_effect(struct fimc_ctx *ctx, bool active)
void fimc_hw_set_effect(struct fimc_ctx *ctx)
{
struct fimc_dev *dev = ctx->fimc_dev;
struct fimc_effect *effect = &ctx->effect;
u32 cfg = 0;
if (active) {
if (effect->type != FIMC_REG_CIIMGEFF_FIN_BYPASS) {
cfg |= FIMC_REG_CIIMGEFF_IE_SC_AFTER |
FIMC_REG_CIIMGEFF_IE_ENABLE;
cfg |= effect->type;

View file

@ -288,7 +288,7 @@ void fimc_hw_en_irq(struct fimc_dev *fimc, int enable);
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_effect(struct fimc_ctx *ctx);
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);