aboutsummaryrefslogtreecommitdiff
path: root/drivers/media/usb/gspca/m5602/m5602_s5k83a.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/usb/gspca/m5602/m5602_s5k83a.c')
-rw-r--r--drivers/media/usb/gspca/m5602/m5602_s5k83a.c291
1 files changed, 71 insertions, 220 deletions
diff --git a/drivers/media/usb/gspca/m5602/m5602_s5k83a.c b/drivers/media/usb/gspca/m5602/m5602_s5k83a.c
index 1de743a02b0..7cbc3a00bda 100644
--- a/drivers/media/usb/gspca/m5602/m5602_s5k83a.c
+++ b/drivers/media/usb/gspca/m5602/m5602_s5k83a.c
@@ -21,16 +21,11 @@
#include <linux/kthread.h>
#include "m5602_s5k83a.h"
-static int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val);
-static int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
-static int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val);
-static int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val);
-static int s5k83a_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
-static int s5k83a_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
-static int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
-static int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
-static int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
-static int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
+static int s5k83a_s_ctrl(struct v4l2_ctrl *ctrl);
+
+static const struct v4l2_ctrl_ops s5k83a_ctrl_ops = {
+ .s_ctrl = s5k83a_s_ctrl,
+};
static struct v4l2_pix_format s5k83a_modes[] = {
{
@@ -46,83 +41,6 @@ static struct v4l2_pix_format s5k83a_modes[] = {
}
};
-static const struct ctrl s5k83a_ctrls[] = {
-#define GAIN_IDX 0
- {
- {
- .id = V4L2_CID_GAIN,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "gain",
- .minimum = 0x00,
- .maximum = 0xff,
- .step = 0x01,
- .default_value = S5K83A_DEFAULT_GAIN,
- .flags = V4L2_CTRL_FLAG_SLIDER
- },
- .set = s5k83a_set_gain,
- .get = s5k83a_get_gain
-
- },
-#define BRIGHTNESS_IDX 1
- {
- {
- .id = V4L2_CID_BRIGHTNESS,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "brightness",
- .minimum = 0x00,
- .maximum = 0xff,
- .step = 0x01,
- .default_value = S5K83A_DEFAULT_BRIGHTNESS,
- .flags = V4L2_CTRL_FLAG_SLIDER
- },
- .set = s5k83a_set_brightness,
- .get = s5k83a_get_brightness,
- },
-#define EXPOSURE_IDX 2
- {
- {
- .id = V4L2_CID_EXPOSURE,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "exposure",
- .minimum = 0x00,
- .maximum = S5K83A_MAXIMUM_EXPOSURE,
- .step = 0x01,
- .default_value = S5K83A_DEFAULT_EXPOSURE,
- .flags = V4L2_CTRL_FLAG_SLIDER
- },
- .set = s5k83a_set_exposure,
- .get = s5k83a_get_exposure
- },
-#define HFLIP_IDX 3
- {
- {
- .id = V4L2_CID_HFLIP,
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .name = "horizontal flip",
- .minimum = 0,
- .maximum = 1,
- .step = 1,
- .default_value = 0
- },
- .set = s5k83a_set_hflip,
- .get = s5k83a_get_hflip
- },
-#define VFLIP_IDX 4
- {
- {
- .id = V4L2_CID_VFLIP,
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .name = "vertical flip",
- .minimum = 0,
- .maximum = 1,
- .step = 1,
- .default_value = 0
- },
- .set = s5k83a_set_vflip,
- .get = s5k83a_get_vflip
- }
-};
-
static void s5k83a_dump_registers(struct sd *sd);
static int s5k83a_get_rotation(struct sd *sd, u8 *reg_data);
static int s5k83a_set_led_indication(struct sd *sd, u8 val);
@@ -131,9 +49,9 @@ static int s5k83a_set_flip_real(struct gspca_dev *gspca_dev,
int s5k83a_probe(struct sd *sd)
{
- struct s5k83a_priv *sens_priv;
u8 prod_id = 0, ver_id = 0;
int i, err = 0;
+ struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
if (force_sensor) {
if (force_sensor == S5K83A_SENSOR) {
@@ -173,38 +91,18 @@ int s5k83a_probe(struct sd *sd)
pr_info("Detected a s5k83a sensor\n");
sensor_found:
- sens_priv = kmalloc(
- sizeof(struct s5k83a_priv), GFP_KERNEL);
- if (!sens_priv)
- return -ENOMEM;
-
- sens_priv->settings =
- kmalloc(sizeof(s32)*ARRAY_SIZE(s5k83a_ctrls), GFP_KERNEL);
- if (!sens_priv->settings) {
- kfree(sens_priv);
- return -ENOMEM;
- }
-
sd->gspca_dev.cam.cam_mode = s5k83a_modes;
sd->gspca_dev.cam.nmodes = ARRAY_SIZE(s5k83a_modes);
- sd->desc->ctrls = s5k83a_ctrls;
- sd->desc->nctrls = ARRAY_SIZE(s5k83a_ctrls);
/* null the pointer! thread is't running now */
- sens_priv->rotation_thread = NULL;
-
- for (i = 0; i < ARRAY_SIZE(s5k83a_ctrls); i++)
- sens_priv->settings[i] = s5k83a_ctrls[i].qctrl.default_value;
+ sd->rotation_thread = NULL;
- sd->sensor_priv = sens_priv;
return 0;
}
int s5k83a_init(struct sd *sd)
{
int i, err = 0;
- s32 *sensor_settings =
- ((struct s5k83a_priv *) sd->sensor_priv)->settings;
for (i = 0; i < ARRAY_SIZE(init_s5k83a) && !err; i++) {
u8 data[2] = {0x00, 0x00};
@@ -237,33 +135,44 @@ int s5k83a_init(struct sd *sd)
if (dump_sensor)
s5k83a_dump_registers(sd);
- err = s5k83a_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
- if (err < 0)
- return err;
+ return err;
+}
- err = s5k83a_set_brightness(&sd->gspca_dev,
- sensor_settings[BRIGHTNESS_IDX]);
- if (err < 0)
- return err;
+int s5k83a_init_controls(struct sd *sd)
+{
+ struct v4l2_ctrl_handler *hdl = &sd->gspca_dev.ctrl_handler;
- err = s5k83a_set_exposure(&sd->gspca_dev,
- sensor_settings[EXPOSURE_IDX]);
- if (err < 0)
- return err;
+ sd->gspca_dev.vdev.ctrl_handler = hdl;
+ v4l2_ctrl_handler_init(hdl, 6);
- err = s5k83a_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]);
- if (err < 0)
- return err;
+ v4l2_ctrl_new_std(hdl, &s5k83a_ctrl_ops, V4L2_CID_BRIGHTNESS,
+ 0, 255, 1, S5K83A_DEFAULT_BRIGHTNESS);
- err = s5k83a_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]);
+ v4l2_ctrl_new_std(hdl, &s5k83a_ctrl_ops, V4L2_CID_EXPOSURE,
+ 0, S5K83A_MAXIMUM_EXPOSURE, 1,
+ S5K83A_DEFAULT_EXPOSURE);
- return err;
+ v4l2_ctrl_new_std(hdl, &s5k83a_ctrl_ops, V4L2_CID_GAIN,
+ 0, 255, 1, S5K83A_DEFAULT_GAIN);
+
+ sd->hflip = v4l2_ctrl_new_std(hdl, &s5k83a_ctrl_ops, V4L2_CID_HFLIP,
+ 0, 1, 1, 0);
+ sd->vflip = v4l2_ctrl_new_std(hdl, &s5k83a_ctrl_ops, V4L2_CID_VFLIP,
+ 0, 1, 1, 0);
+
+ if (hdl->error) {
+ pr_err("Could not initialize controls\n");
+ return hdl->error;
+ }
+
+ v4l2_ctrl_cluster(2, &sd->hflip);
+
+ return 0;
}
static int rotation_thread_function(void *data)
{
struct sd *sd = (struct sd *) data;
- struct s5k83a_priv *sens_priv = sd->sensor_priv;
u8 reg, previous_rotation = 0;
__s32 vflip, hflip;
@@ -277,8 +186,8 @@ static int rotation_thread_function(void *data)
previous_rotation = reg;
pr_info("Camera was flipped\n");
- s5k83a_get_vflip((struct gspca_dev *) sd, &vflip);
- s5k83a_get_hflip((struct gspca_dev *) sd, &hflip);
+ hflip = sd->hflip->val;
+ vflip = sd->vflip->val;
if (reg) {
vflip = !vflip;
@@ -294,26 +203,25 @@ static int rotation_thread_function(void *data)
/* return to "front" flip */
if (previous_rotation) {
- s5k83a_get_vflip((struct gspca_dev *) sd, &vflip);
- s5k83a_get_hflip((struct gspca_dev *) sd, &hflip);
+ hflip = sd->hflip->val;
+ vflip = sd->vflip->val;
s5k83a_set_flip_real((struct gspca_dev *) sd, vflip, hflip);
}
- sens_priv->rotation_thread = NULL;
+ sd->rotation_thread = NULL;
return 0;
}
int s5k83a_start(struct sd *sd)
{
int i, err = 0;
- struct s5k83a_priv *sens_priv = sd->sensor_priv;
/* Create another thread, polling the GPIO ports of the camera to check
if it got rotated. This is how the windows driver does it so we have
to assume that there is no better way of accomplishing this */
- sens_priv->rotation_thread = kthread_create(rotation_thread_function,
- sd, "rotation thread");
- wake_up_process(sens_priv->rotation_thread);
+ sd->rotation_thread = kthread_create(rotation_thread_function,
+ sd, "rotation thread");
+ wake_up_process(sd->rotation_thread);
/* Preinit the sensor */
for (i = 0; i < ARRAY_SIZE(start_s5k83a) && !err; i++) {
@@ -333,32 +241,17 @@ int s5k83a_start(struct sd *sd)
int s5k83a_stop(struct sd *sd)
{
- struct s5k83a_priv *sens_priv = sd->sensor_priv;
-
- if (sens_priv->rotation_thread)
- kthread_stop(sens_priv->rotation_thread);
+ if (sd->rotation_thread)
+ kthread_stop(sd->rotation_thread);
return s5k83a_set_led_indication(sd, 0);
}
void s5k83a_disconnect(struct sd *sd)
{
- struct s5k83a_priv *sens_priv = sd->sensor_priv;
-
s5k83a_stop(sd);
sd->sensor = NULL;
- kfree(sens_priv->settings);
- kfree(sens_priv);
-}
-
-static int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
-{
- struct sd *sd = (struct sd *) gspca_dev;
- struct s5k83a_priv *sens_priv = sd->sensor_priv;
-
- *val = sens_priv->settings[GAIN_IDX];
- return 0;
}
static int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val)
@@ -366,9 +259,6 @@ static int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val)
int err;
u8 data[2];
struct sd *sd = (struct sd *) gspca_dev;
- struct s5k83a_priv *sens_priv = sd->sensor_priv;
-
- sens_priv->settings[GAIN_IDX] = val;
data[0] = 0x00;
data[1] = 0x20;
@@ -391,60 +281,29 @@ static int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val)
return err;
}
-static int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val)
-{
- struct sd *sd = (struct sd *) gspca_dev;
- struct s5k83a_priv *sens_priv = sd->sensor_priv;
-
- *val = sens_priv->settings[BRIGHTNESS_IDX];
- return 0;
-}
-
static int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
{
int err;
u8 data[1];
struct sd *sd = (struct sd *) gspca_dev;
- struct s5k83a_priv *sens_priv = sd->sensor_priv;
- sens_priv->settings[BRIGHTNESS_IDX] = val;
data[0] = val;
err = m5602_write_sensor(sd, S5K83A_BRIGHTNESS, data, 1);
return err;
}
-static int s5k83a_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
-{
- struct sd *sd = (struct sd *) gspca_dev;
- struct s5k83a_priv *sens_priv = sd->sensor_priv;
-
- *val = sens_priv->settings[EXPOSURE_IDX];
- return 0;
-}
-
static int s5k83a_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
{
int err;
u8 data[2];
struct sd *sd = (struct sd *) gspca_dev;
- struct s5k83a_priv *sens_priv = sd->sensor_priv;
- sens_priv->settings[EXPOSURE_IDX] = val;
data[0] = 0;
data[1] = val;
err = m5602_write_sensor(sd, S5K83A_EXPOSURE, data, 2);
return err;
}
-static int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
-{
- struct sd *sd = (struct sd *) gspca_dev;
- struct s5k83a_priv *sens_priv = sd->sensor_priv;
-
- *val = sens_priv->settings[VFLIP_IDX];
- return 0;
-}
-
static int s5k83a_set_flip_real(struct gspca_dev *gspca_dev,
__s32 vflip, __s32 hflip)
{
@@ -476,60 +335,52 @@ static int s5k83a_set_flip_real(struct gspca_dev *gspca_dev,
return err;
}
-static int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
+static int s5k83a_set_hvflip(struct gspca_dev *gspca_dev)
{
int err;
u8 reg;
- __s32 hflip;
struct sd *sd = (struct sd *) gspca_dev;
- struct s5k83a_priv *sens_priv = sd->sensor_priv;
-
- sens_priv->settings[VFLIP_IDX] = val;
-
- s5k83a_get_hflip(gspca_dev, &hflip);
+ int hflip = sd->hflip->val;
+ int vflip = sd->vflip->val;
err = s5k83a_get_rotation(sd, &reg);
if (err < 0)
return err;
if (reg) {
- val = !val;
hflip = !hflip;
+ vflip = !vflip;
}
- err = s5k83a_set_flip_real(gspca_dev, val, hflip);
+ err = s5k83a_set_flip_real(gspca_dev, vflip, hflip);
return err;
}
-static int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
-{
- struct sd *sd = (struct sd *) gspca_dev;
- struct s5k83a_priv *sens_priv = sd->sensor_priv;
-
- *val = sens_priv->settings[HFLIP_IDX];
- return 0;
-}
-
-static int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
+static int s5k83a_s_ctrl(struct v4l2_ctrl *ctrl)
{
+ struct gspca_dev *gspca_dev =
+ container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
int err;
- u8 reg;
- __s32 vflip;
- struct sd *sd = (struct sd *) gspca_dev;
- struct s5k83a_priv *sens_priv = sd->sensor_priv;
-
- sens_priv->settings[HFLIP_IDX] = val;
- s5k83a_get_vflip(gspca_dev, &vflip);
-
- err = s5k83a_get_rotation(sd, &reg);
- if (err < 0)
- return err;
- if (reg) {
- val = !val;
- vflip = !vflip;
+ if (!gspca_dev->streaming)
+ return 0;
+
+ switch (ctrl->id) {
+ case V4L2_CID_BRIGHTNESS:
+ err = s5k83a_set_brightness(gspca_dev, ctrl->val);
+ break;
+ case V4L2_CID_EXPOSURE:
+ err = s5k83a_set_exposure(gspca_dev, ctrl->val);
+ break;
+ case V4L2_CID_GAIN:
+ err = s5k83a_set_gain(gspca_dev, ctrl->val);
+ break;
+ case V4L2_CID_HFLIP:
+ err = s5k83a_set_hvflip(gspca_dev);
+ break;
+ default:
+ return -EINVAL;
}
- err = s5k83a_set_flip_real(gspca_dev, vflip, val);
return err;
}