Skip to content

Commit

Permalink
[media] s5p-fimc: Add color effect control
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Sylwester Nawrocki authored and Mauro Carvalho Chehab committed May 20, 2012
1 parent 0c9204d commit 9448ab7
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 50 deletions.
11 changes: 6 additions & 5 deletions drivers/media/video/s5p-fimc/fimc-capture.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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:
Expand Down
127 changes: 99 additions & 28 deletions drivers/media/video/s5p-fimc/fimc-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down
38 changes: 26 additions & 12 deletions drivers/media/video/s5p-fimc/fimc-core.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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;
Expand All @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions drivers/media/video/s5p-fimc/fimc-m2m.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);

Expand Down
4 changes: 2 additions & 2 deletions drivers/media/video/s5p-fimc/fimc-reg.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion drivers/media/video/s5p-fimc/fimc-reg.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 9448ab7

Please sign in to comment.