From 71e84ea7f082eb02df6ef40f55d2c4a998f6e1df Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Moine?= <moinejf@free.fr>
Date: Tue, 28 Dec 2010 07:35:27 -0300
Subject: [PATCH] [media] gspca - stv06xx/st6422: Use the new video control
 mechanism
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Jean-François Moine <moinejf@free.fr>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
---
 .../video/gspca/stv06xx/stv06xx_st6422.c      | 272 ++++++++----------
 .../video/gspca/stv06xx/stv06xx_st6422.h      |  10 -
 2 files changed, 118 insertions(+), 164 deletions(-)

diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c
index 42f3a1e41188..8a456de4970a 100644
--- a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c
+++ b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c
@@ -28,6 +28,20 @@
 
 #include "stv06xx_st6422.h"
 
+/* controls */
+enum e_ctrl {
+	BRIGHTNESS,
+	CONTRAST,
+	GAIN,
+	EXPOSURE,
+	NCTRLS		/* number of controls */
+};
+
+/* sensor settings */
+struct st6422_settings {
+	struct gspca_ctrl ctrls[NCTRLS];
+};
+
 static struct v4l2_pix_format st6422_mode[] = {
 	/* Note we actually get 124 lines of data, of which we skip the 4st
 	   4 as they are garbage */
@@ -57,9 +71,14 @@ static struct v4l2_pix_format st6422_mode[] = {
 	},
 };
 
-static const struct ctrl st6422_ctrl[] = {
-#define BRIGHTNESS_IDX 0
-	{
+/* V4L2 controls supported by the driver */
+static void st6422_set_brightness(struct gspca_dev *gspca_dev);
+static void st6422_set_contrast(struct gspca_dev *gspca_dev);
+static void st6422_set_gain(struct gspca_dev *gspca_dev);
+static void st6422_set_exposure(struct gspca_dev *gspca_dev);
+
+static const struct ctrl st6422_ctrl[NCTRLS] = {
+[BRIGHTNESS] = {
 		{
 			.id		= V4L2_CID_BRIGHTNESS,
 			.type		= V4L2_CTRL_TYPE_INTEGER,
@@ -69,11 +88,9 @@ static const struct ctrl st6422_ctrl[] = {
 			.step		= 1,
 			.default_value  = 3
 		},
-		.set = st6422_set_brightness,
-		.get = st6422_get_brightness
+		.set_control = st6422_set_brightness
 	},
-#define CONTRAST_IDX 1
-	{
+[CONTRAST] = {
 		{
 			.id		= V4L2_CID_CONTRAST,
 			.type		= V4L2_CTRL_TYPE_INTEGER,
@@ -83,11 +100,9 @@ static const struct ctrl st6422_ctrl[] = {
 			.step		= 1,
 			.default_value  = 11
 		},
-		.set = st6422_set_contrast,
-		.get = st6422_get_contrast
+		.set_control = st6422_set_contrast
 	},
-#define GAIN_IDX 2
-	{
+[GAIN] = {
 		{
 			.id		= V4L2_CID_GAIN,
 			.type		= V4L2_CTRL_TYPE_INTEGER,
@@ -97,49 +112,43 @@ static const struct ctrl st6422_ctrl[] = {
 			.step		= 1,
 			.default_value  = 64
 		},
-		.set = st6422_set_gain,
-		.get = st6422_get_gain
+		.set_control = st6422_set_gain
 	},
-#define EXPOSURE_IDX 3
-	{
+[EXPOSURE] = {
 		{
 			.id		= V4L2_CID_EXPOSURE,
 			.type		= V4L2_CTRL_TYPE_INTEGER,
 			.name		= "Exposure",
 			.minimum	= 0,
-			.maximum	= 1023,
+#define EXPOSURE_MAX 1023
+			.maximum	= EXPOSURE_MAX,
 			.step		= 1,
 			.default_value  = 256
 		},
-		.set = st6422_set_exposure,
-		.get = st6422_get_exposure
+		.set_control = st6422_set_exposure
 	},
 };
 
 static int st6422_probe(struct sd *sd)
 {
-	int i;
-	s32 *sensor_settings;
+	struct st6422_settings *sensor_settings;
 
 	if (sd->bridge != BRIDGE_ST6422)
 		return -ENODEV;
 
 	info("st6422 sensor detected");
 
-	sensor_settings = kmalloc(ARRAY_SIZE(st6422_ctrl) * sizeof(s32),
-				  GFP_KERNEL);
+	sensor_settings = kmalloc(sizeof *sensor_settings, GFP_KERNEL);
 	if (!sensor_settings)
 		return -ENOMEM;
 
 	sd->gspca_dev.cam.cam_mode = st6422_mode;
 	sd->gspca_dev.cam.nmodes = ARRAY_SIZE(st6422_mode);
+	sd->gspca_dev.cam.ctrls = sensor_settings->ctrls;
 	sd->desc.ctrls = st6422_ctrl;
 	sd->desc.nctrls = ARRAY_SIZE(st6422_ctrl);
 	sd->sensor_priv = sensor_settings;
 
-	for (i = 0; i < sd->desc.nctrls; i++)
-		sensor_settings[i] = st6422_ctrl[i].qctrl.default_value;
-
 	return 0;
 }
 
@@ -234,77 +243,92 @@ static void st6422_disconnect(struct sd *sd)
 	kfree(sd->sensor_priv);
 }
 
-static int st6422_start(struct sd *sd)
+static int setbrightness(struct sd *sd)
+{
+	struct st6422_settings *sensor_settings = sd->sensor_priv;
+
+	/* val goes from 0 -> 31 */
+	return stv06xx_write_bridge(sd, 0x1432,
+			sensor_settings->ctrls[BRIGHTNESS].val);
+}
+
+static int setcontrast(struct sd *sd)
+{
+	struct st6422_settings *sensor_settings = sd->sensor_priv;
+
+	/* Val goes from 0 -> 15 */
+	return stv06xx_write_bridge(sd, 0x143a,
+			sensor_settings->ctrls[CONTRAST].val | 0xf0);
+}
+
+static int setgain(struct sd *sd)
 {
+	struct st6422_settings *sensor_settings = sd->sensor_priv;
+	u8 gain;
 	int err;
-	struct cam *cam = &sd->gspca_dev.cam;
-	s32 *sensor_settings = sd->sensor_priv;
 
-	if (cam->cam_mode[sd->gspca_dev.curr_mode].priv)
-		err = stv06xx_write_bridge(sd, 0x1505, 0x0f);
-	else
-		err = stv06xx_write_bridge(sd, 0x1505, 0x02);
-	if (err < 0)
-		return err;
+	gain = sensor_settings->ctrls[GAIN].val;
 
-	err = st6422_set_brightness(&sd->gspca_dev,
-				    sensor_settings[BRIGHTNESS_IDX]);
+	/* Set red, green, blue, gain */
+	err = stv06xx_write_bridge(sd, 0x0509, gain);
 	if (err < 0)
 		return err;
 
-	err = st6422_set_contrast(&sd->gspca_dev,
-				  sensor_settings[CONTRAST_IDX]);
+	err = stv06xx_write_bridge(sd, 0x050a, gain);
 	if (err < 0)
 		return err;
 
-	err = st6422_set_exposure(&sd->gspca_dev,
-				  sensor_settings[EXPOSURE_IDX]);
+	err = stv06xx_write_bridge(sd, 0x050b, gain);
 	if (err < 0)
 		return err;
 
-	err = st6422_set_gain(&sd->gspca_dev,
-			      sensor_settings[GAIN_IDX]);
+	/* 2 mystery writes */
+	err = stv06xx_write_bridge(sd, 0x050c, 0x2a);
 	if (err < 0)
 		return err;
 
-	PDEBUG(D_STREAM, "Starting stream");
-
-	return 0;
+	return stv06xx_write_bridge(sd, 0x050d, 0x01);
 }
 
-static int st6422_stop(struct sd *sd)
+static int setexposure(struct sd *sd)
 {
-	PDEBUG(D_STREAM, "Halting stream");
-
-	return 0;
-}
-
-static int st6422_get_brightness(struct gspca_dev *gspca_dev, __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
-
-	*val = sensor_settings[BRIGHTNESS_IDX];
+	struct st6422_settings *sensor_settings = sd->sensor_priv;
+	u16 expo;
+	int err;
 
-	PDEBUG(D_V4L2, "Read brightness %d", *val);
+	expo = sensor_settings->ctrls[EXPOSURE].val;
+	err = stv06xx_write_bridge(sd, 0x143d, expo & 0xff);
+	if (err < 0)
+		return err;
 
-	return 0;
+	return stv06xx_write_bridge(sd, 0x143e, expo >> 8);
 }
 
-static int st6422_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
+static int st6422_start(struct sd *sd)
 {
 	int err;
-	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
+	struct cam *cam = &sd->gspca_dev.cam;
 
-	sensor_settings[BRIGHTNESS_IDX] = val;
+	if (cam->cam_mode[sd->gspca_dev.curr_mode].priv)
+		err = stv06xx_write_bridge(sd, 0x1505, 0x0f);
+	else
+		err = stv06xx_write_bridge(sd, 0x1505, 0x02);
+	if (err < 0)
+		return err;
 
-	if (!gspca_dev->streaming)
-		return 0;
+	err = setbrightness(sd);
+	if (err < 0)
+		return err;
 
-	/* val goes from 0 -> 31 */
-	PDEBUG(D_V4L2, "Set brightness to %d", val);
-	err = stv06xx_write_bridge(sd, 0x1432, val);
+	err = setcontrast(sd);
+	if (err < 0)
+		return err;
+
+	err = setexposure(sd);
+	if (err < 0)
+		return err;
+
+	err = setgain(sd);
 	if (err < 0)
 		return err;
 
@@ -313,125 +337,65 @@ static int st6422_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
 	return (err < 0) ? err : 0;
 }
 
-static int st6422_get_contrast(struct gspca_dev *gspca_dev, __s32 *val)
+static int st6422_stop(struct sd *sd)
 {
-	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
-
-	*val = sensor_settings[CONTRAST_IDX];
-
-	PDEBUG(D_V4L2, "Read contrast %d", *val);
+	PDEBUG(D_STREAM, "Halting stream");
 
 	return 0;
 }
 
-static int st6422_set_contrast(struct gspca_dev *gspca_dev, __s32 val)
+static void st6422_set_brightness(struct gspca_dev *gspca_dev)
 {
 	int err;
 	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
-
-	sensor_settings[CONTRAST_IDX] = val;
 
-	if (!gspca_dev->streaming)
-		return 0;
-
-	/* Val goes from 0 -> 15 */
-	PDEBUG(D_V4L2, "Set contrast to %d\n", val);
-	err = stv06xx_write_bridge(sd, 0x143a, 0xf0 | val);
-	if (err < 0)
-		return err;
+	err = setbrightness(sd);
 
 	/* commit settings */
-	err = stv06xx_write_bridge(sd, 0x143f, 0x01);
-	return (err < 0) ? err : 0;
-}
-
-static int st6422_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
-
-	*val = sensor_settings[GAIN_IDX];
+	if (err >= 0)
+		err = stv06xx_write_bridge(sd, 0x143f, 0x01);
 
-	PDEBUG(D_V4L2, "Read gain %d", *val);
-
-	return 0;
+	gspca_dev->usb_err = err;
 }
 
-static int st6422_set_gain(struct gspca_dev *gspca_dev, __s32 val)
+static void st6422_set_contrast(struct gspca_dev *gspca_dev)
 {
 	int err;
 	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
 
-	sensor_settings[GAIN_IDX] = val;
-
-	if (!gspca_dev->streaming)
-		return 0;
-
-	PDEBUG(D_V4L2, "Set gain to %d", val);
-
-	/* Set red, green, blue, gain */
-	err = stv06xx_write_bridge(sd, 0x0509, val);
-	if (err < 0)
-		return err;
-
-	err = stv06xx_write_bridge(sd, 0x050a, val);
-	if (err < 0)
-		return err;
-
-	err = stv06xx_write_bridge(sd, 0x050b, val);
-	if (err < 0)
-		return err;
-
-	/* 2 mystery writes */
-	err = stv06xx_write_bridge(sd, 0x050c, 0x2a);
-	if (err < 0)
-		return err;
-
-	err = stv06xx_write_bridge(sd, 0x050d, 0x01);
-	if (err < 0)
-		return err;
+	err = setcontrast(sd);
 
 	/* commit settings */
-	err = stv06xx_write_bridge(sd, 0x143f, 0x01);
-	return (err < 0) ? err : 0;
+	if (err >= 0)
+		err = stv06xx_write_bridge(sd, 0x143f, 0x01);
+
+	gspca_dev->usb_err = err;
 }
 
-static int st6422_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
+static void st6422_set_gain(struct gspca_dev *gspca_dev)
 {
+	int err;
 	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
 
-	*val = sensor_settings[EXPOSURE_IDX];
+	err = setgain(sd);
 
-	PDEBUG(D_V4L2, "Read exposure %d", *val);
+	/* commit settings */
+	if (err >= 0)
+		err = stv06xx_write_bridge(sd, 0x143f, 0x01);
 
-	return 0;
+	gspca_dev->usb_err = err;
 }
 
-static int st6422_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
+static void st6422_set_exposure(struct gspca_dev *gspca_dev)
 {
 	int err;
 	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
-
-	sensor_settings[EXPOSURE_IDX] = val;
-
-	if (!gspca_dev->streaming)
-		return 0;
-
-	PDEBUG(D_V4L2, "Set exposure to %d\n", val);
-	err = stv06xx_write_bridge(sd, 0x143d, val & 0xff);
-	if (err < 0)
-		return err;
 
-	err = stv06xx_write_bridge(sd, 0x143e, val >> 8);
-	if (err < 0)
-		return err;
+	err = setexposure(sd);
 
 	/* commit settings */
-	err = stv06xx_write_bridge(sd, 0x143f, 0x01);
-	return (err < 0) ? err : 0;
+	if (err >= 0)
+		err = stv06xx_write_bridge(sd, 0x143f, 0x01);
+
+	gspca_dev->usb_err = err;
 }
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h
index 12608aebe50b..d7498e06432b 100644
--- a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h
+++ b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h
@@ -37,16 +37,6 @@ static int st6422_init(struct sd *sd);
 static int st6422_stop(struct sd *sd);
 static void st6422_disconnect(struct sd *sd);
 
-/* V4L2 controls supported by the driver */
-static int st6422_get_brightness(struct gspca_dev *gspca_dev, __s32 *val);
-static int st6422_set_brightness(struct gspca_dev *gspca_dev, __s32 val);
-static int st6422_get_contrast(struct gspca_dev *gspca_dev, __s32 *val);
-static int st6422_set_contrast(struct gspca_dev *gspca_dev, __s32 val);
-static int st6422_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
-static int st6422_set_gain(struct gspca_dev *gspca_dev, __s32 val);
-static int st6422_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
-static int st6422_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
-
 const struct stv06xx_sensor stv06xx_sensor_st6422 = {
 	.name = "ST6422",
 	/* No known way to lower framerate in case of less bandwidth */
-- 
GitLab