summaryrefslogtreecommitdiff
path: root/isp/controls.c
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2012-10-20 20:49:07 +0200
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2012-10-20 21:05:46 +0200
commit1922132a4facf53e71855fb3624ab29da99a6fe3 (patch)
tree918d8e20962db8a811108db6f0be8d81e783b1a7 /isp/controls.c
parent7e62380de5584b9edbd61048f5b16e521e893eeb (diff)
isp: Emulate global gain for sensors that only expose color gains
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Diffstat (limited to 'isp/controls.c')
-rw-r--r--isp/controls.c70
1 files changed, 70 insertions, 0 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;