[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:
parent
0c9204d342
commit
9448ab7dec
6 changed files with 136 additions and 50 deletions
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue