From 1922132a4facf53e71855fb3624ab29da99a6fe3 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sat, 20 Oct 2012 20:49:07 +0200 Subject: isp: Emulate global gain for sensors that only expose color gains Signed-off-by: Laurent Pinchart --- isp/controls.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++ isp/controls.h | 1 + isp/omap3isp-priv.h | 5 ++-- isp/omap3isp.c | 8 +++--- 4 files changed, 77 insertions(+), 7 deletions(-) diff --git a/isp/controls.c b/isp/controls.c index cce4265..05ab20b 100644 --- a/isp/controls.c +++ b/isp/controls.c @@ -343,6 +343,70 @@ int omap3_isp_preview_setup(struct omap3_isp_device *isp) #define V4L2_CID_GAIN_GREEN2 (V4L2_CTRL_CLASS_CAMERA | 0x1003) #define V4L2_CID_GAIN_BLUE (V4L2_CTRL_CLASS_CAMERA | 0x1004) +#define SENSOR_GAIN_GLOBAL (1 << 0) +#define SENSOR_GAIN_RED (1 << 1) +#define SENSOR_GAIN_GREEN1 (1 << 2) +#define SENSOR_GAIN_GREEN2 (1 << 3) +#define SENSOR_GAIN_BLUE (1 << 4) +#define SENSOR_GAIN_COLORS (SENSOR_GAIN_RED | \ + SENSOR_GAIN_GREEN1 | \ + SENSOR_GAIN_GREEN2 | \ + SENSOR_GAIN_BLUE) + +int omap3_isp_sensor_init(struct omap3_isp_device *isp) +{ + struct v4l2_queryctrl query; + unsigned int gains = 0; + __u32 id; + int ret; + + /* Retrieve the sensor default format. */ + ret = v4l2_subdev_get_format(isp->sensor.entity, &isp->sensor.format, 0, + V4L2_SUBDEV_FORMAT_TRY); + if (ret < 0) { + printf("error: unable to get sensor default format.\n"); + return ret; + } + + for (id = 0; ; id = query.id) { + memset(&query, 0, sizeof query); + query.id = id | V4L2_CTRL_FLAG_NEXT_CTRL; + ret = ioctl(isp->sensor.entity->fd, VIDIOC_QUERYCTRL, &query); + if (ret < 0) { + if (errno == EINVAL) + break; + + printf("error: unable to get sensor default format.\n"); + return -errno; + } + + switch (query.id) { + case V4L2_CID_GAIN: + gains |= SENSOR_GAIN_GLOBAL; + break; + case V4L2_CID_GAIN_RED: + gains |= SENSOR_GAIN_RED; + break; + case V4L2_CID_GAIN_GREEN1: + gains |= SENSOR_GAIN_GREEN1; + break; + case V4L2_CID_GAIN_GREEN2: + gains |= SENSOR_GAIN_GREEN2; + break; + case V4L2_CID_GAIN_BLUE: + gains |= SENSOR_GAIN_BLUE; + break; + } + } + + if ((gains & SENSOR_GAIN_COLORS) == SENSOR_GAIN_COLORS) + isp->sensor.has_color_gains = true; + if (gains & SENSOR_GAIN_GLOBAL) + isp->sensor.has_global_gain = true; + + return 0; +} + int omap3_isp_sensor_get_exposure(struct omap3_isp_device *isp, unsigned int *exposure) { @@ -374,6 +438,9 @@ int omap3_isp_sensor_set_gain(struct omap3_isp_device *isp, unsigned int gain) { struct v4l2_ext_control ctrls[1]; + if (!isp->sensor.has_global_gain) + return omap3_isp_sensor_set_gains(isp, gain, gain, gain); + ctrls[0].id = V4L2_CID_GAIN; ctrls[0].value = gain; @@ -386,6 +453,9 @@ int omap3_isp_sensor_set_gains(struct omap3_isp_device *isp, struct v4l2_ext_control ctrls[4]; unsigned int i = 0; + if (!isp->sensor.has_color_gains) + return -EINVAL; + if (red != OMAP3_ISP_SENSOR_GAIN_KEEP) { ctrls[i].id = V4L2_CID_GAIN_RED; ctrls[i++].value = red; diff --git a/isp/controls.h b/isp/controls.h index 6c7f74e..29bdd48 100644 --- a/isp/controls.h +++ b/isp/controls.h @@ -25,5 +25,6 @@ struct omap3_isp_device; int omap3_isp_preview_setup(struct omap3_isp_device *isp); +int omap3_isp_sensor_init(struct omap3_isp_device *isp); #endif /* __OMAP3ISP_CONTROLS_H */ diff --git a/isp/omap3isp-priv.h b/isp/omap3isp-priv.h index 2f3dbb9..c71ed40 100644 --- a/isp/omap3isp-priv.h +++ b/isp/omap3isp-priv.h @@ -139,6 +139,9 @@ struct omap3_isp_device { struct { struct media_entity *entity; + struct v4l2_mbus_framefmt format; + bool has_color_gains; + bool has_global_gain; } sensor; struct { struct media_entity *entity; @@ -149,8 +152,6 @@ struct omap3_isp_device { } preview; struct omap3_isp_aewb aewb; - struct v4l2_mbus_framefmt sensor_format; - struct omap3_isp_pipeline viewfinder; struct omap3_isp_pipeline snapshot; diff --git a/isp/omap3isp.c b/isp/omap3isp.c index ac9cc4a..7ff2d7e 100644 --- a/isp/omap3isp.c +++ b/isp/omap3isp.c @@ -637,7 +637,7 @@ static int omap3_isp_pipeline_try_format(struct omap3_isp_device *isp, * Otherwise scale as much as possible on the sensor. */ if (scaler == OMAP3_ISP_SCALER_ISP) - format = isp->sensor_format; + format = isp->sensor.format; else format = *ofmt; @@ -939,11 +939,9 @@ struct omap3_isp_device *omap3_isp_open(const char *devname, isp->sensor.entity = entity; - /* Retrieve the sensor default format. */ - ret = v4l2_subdev_get_format(isp->sensor.entity, &isp->sensor_format, 0, - V4L2_SUBDEV_FORMAT_TRY); + ret = omap3_isp_sensor_init(isp); if (ret < 0) { - printf("error: unable to get sensor default format.\n"); + printf("error: unable to initialize sensor.\n"); goto error; } -- cgit v1.2.3