root/drivers/media/usb/gspca/m5602/m5602_s5k83a.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. s5k83a_probe
  2. s5k83a_init
  3. s5k83a_init_controls
  4. rotation_thread_function
  5. s5k83a_start
  6. s5k83a_stop
  7. s5k83a_disconnect
  8. s5k83a_set_gain
  9. s5k83a_set_brightness
  10. s5k83a_set_exposure
  11. s5k83a_set_flip_real
  12. s5k83a_set_hvflip
  13. s5k83a_s_ctrl
  14. s5k83a_set_led_indication
  15. s5k83a_get_rotation
  16. s5k83a_dump_registers

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Driver for the s5k83a sensor
   4  *
   5  * Copyright (C) 2008 Erik Andrén
   6  * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
   7  * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
   8  *
   9  * Portions of code to USB interface and ALi driver software,
  10  * Copyright (c) 2006 Willem Duinker
  11  * v4l2 interface modeled after the V4L2 driver
  12  * for SN9C10x PC Camera Controllers
  13  */
  14 
  15 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  16 
  17 #include <linux/kthread.h>
  18 #include "m5602_s5k83a.h"
  19 
  20 static int s5k83a_s_ctrl(struct v4l2_ctrl *ctrl);
  21 
  22 static const struct v4l2_ctrl_ops s5k83a_ctrl_ops = {
  23         .s_ctrl = s5k83a_s_ctrl,
  24 };
  25 
  26 static struct v4l2_pix_format s5k83a_modes[] = {
  27         {
  28                 640,
  29                 480,
  30                 V4L2_PIX_FMT_SBGGR8,
  31                 V4L2_FIELD_NONE,
  32                 .sizeimage =
  33                         640 * 480,
  34                 .bytesperline = 640,
  35                 .colorspace = V4L2_COLORSPACE_SRGB,
  36                 .priv = 0
  37         }
  38 };
  39 
  40 static const unsigned char preinit_s5k83a[][4] = {
  41         {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
  42         {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
  43         {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
  44         {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
  45         {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
  46         {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00},
  47         {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00},
  48 
  49         {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
  50         {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
  51         {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00},
  52         {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00},
  53         {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00},
  54         {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
  55         {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
  56         {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
  57         {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
  58         {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00},
  59         {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00},
  60         {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
  61         {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
  62         {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
  63         {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
  64         {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
  65         {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
  66         {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
  67         {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00},
  68         {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
  69         {BRIDGE, M5602_XB_GPIO_DAT, 0x1c, 0x00},
  70         {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
  71         {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00},
  72         {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
  73         {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
  74         {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00},
  75 };
  76 
  77 /* This could probably be considerably shortened.
  78    I don't have the hardware to experiment with it, patches welcome
  79 */
  80 static const unsigned char init_s5k83a[][4] = {
  81         /* The following sequence is useless after a clean boot
  82            but is necessary after resume from suspend */
  83         {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
  84         {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00},
  85         {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00},
  86         {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00},
  87         {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
  88         {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
  89         {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
  90         {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
  91         {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00},
  92         {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00},
  93         {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
  94         {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
  95         {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
  96         {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
  97         {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
  98         {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
  99         {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
 100         {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00},
 101         {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
 102         {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00},
 103         {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
 104         {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00},
 105         {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
 106         {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
 107         {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00},
 108 
 109         {SENSOR, S5K83A_PAGE_MAP, 0x04, 0x00},
 110         {SENSOR, 0xaf, 0x01, 0x00},
 111         {SENSOR, S5K83A_PAGE_MAP, 0x00, 0x00},
 112         {SENSOR, 0x7b, 0xff, 0x00},
 113         {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
 114         {SENSOR, 0x01, 0x50, 0x00},
 115         {SENSOR, 0x12, 0x20, 0x00},
 116         {SENSOR, 0x17, 0x40, 0x00},
 117         {SENSOR, 0x1c, 0x00, 0x00},
 118         {SENSOR, 0x02, 0x70, 0x00},
 119         {SENSOR, 0x03, 0x0b, 0x00},
 120         {SENSOR, 0x04, 0xf0, 0x00},
 121         {SENSOR, 0x05, 0x0b, 0x00},
 122         {SENSOR, 0x06, 0x71, 0x00},
 123         {SENSOR, 0x07, 0xe8, 0x00}, /* 488 */
 124         {SENSOR, 0x08, 0x02, 0x00},
 125         {SENSOR, 0x09, 0x88, 0x00}, /* 648 */
 126         {SENSOR, 0x14, 0x00, 0x00},
 127         {SENSOR, 0x15, 0x20, 0x00}, /* 32 */
 128         {SENSOR, 0x19, 0x00, 0x00},
 129         {SENSOR, 0x1a, 0x98, 0x00}, /* 152 */
 130         {SENSOR, 0x0f, 0x02, 0x00},
 131         {SENSOR, 0x10, 0xe5, 0x00}, /* 741 */
 132         /* normal colors
 133         (this is value after boot, but after tries can be different) */
 134         {SENSOR, 0x00, 0x06, 0x00},
 135 };
 136 
 137 static const unsigned char start_s5k83a[][4] = {
 138         {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
 139         {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
 140         {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
 141         {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
 142         {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
 143         {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
 144         {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
 145         {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
 146         {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
 147         {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
 148         {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
 149         {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00},
 150         {BRIDGE, M5602_XB_VSYNC_PARA, 0xe4, 0x00}, /* 484 */
 151         {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
 152         {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
 153         {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
 154         {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
 155         {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
 156         {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
 157         {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00},
 158         {BRIDGE, M5602_XB_HSYNC_PARA, 0x7f, 0x00}, /* 639 */
 159         {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
 160         {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
 161         {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
 162 };
 163 
 164 static void s5k83a_dump_registers(struct sd *sd);
 165 static int s5k83a_get_rotation(struct sd *sd, u8 *reg_data);
 166 static int s5k83a_set_led_indication(struct sd *sd, u8 val);
 167 static int s5k83a_set_flip_real(struct gspca_dev *gspca_dev,
 168                                 __s32 vflip, __s32 hflip);
 169 
 170 int s5k83a_probe(struct sd *sd)
 171 {
 172         u8 prod_id = 0, ver_id = 0;
 173         int i, err = 0;
 174         struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
 175 
 176         if (force_sensor) {
 177                 if (force_sensor == S5K83A_SENSOR) {
 178                         pr_info("Forcing a %s sensor\n", s5k83a.name);
 179                         goto sensor_found;
 180                 }
 181                 /* If we want to force another sensor, don't try to probe this
 182                  * one */
 183                 return -ENODEV;
 184         }
 185 
 186         gspca_dbg(gspca_dev, D_PROBE, "Probing for a s5k83a sensor\n");
 187 
 188         /* Preinit the sensor */
 189         for (i = 0; i < ARRAY_SIZE(preinit_s5k83a) && !err; i++) {
 190                 u8 data[2] = {preinit_s5k83a[i][2], preinit_s5k83a[i][3]};
 191                 if (preinit_s5k83a[i][0] == SENSOR)
 192                         err = m5602_write_sensor(sd, preinit_s5k83a[i][1],
 193                                 data, 2);
 194                 else
 195                         err = m5602_write_bridge(sd, preinit_s5k83a[i][1],
 196                                 data[0]);
 197         }
 198 
 199         /* We don't know what register (if any) that contain the product id
 200          * Just pick the first addresses that seem to produce the same results
 201          * on multiple machines */
 202         if (m5602_read_sensor(sd, 0x00, &prod_id, 1))
 203                 return -ENODEV;
 204 
 205         if (m5602_read_sensor(sd, 0x01, &ver_id, 1))
 206                 return -ENODEV;
 207 
 208         if ((prod_id == 0xff) || (ver_id == 0xff))
 209                 return -ENODEV;
 210         else
 211                 pr_info("Detected a s5k83a sensor\n");
 212 
 213 sensor_found:
 214         sd->gspca_dev.cam.cam_mode = s5k83a_modes;
 215         sd->gspca_dev.cam.nmodes = ARRAY_SIZE(s5k83a_modes);
 216 
 217         /* null the pointer! thread is't running now */
 218         sd->rotation_thread = NULL;
 219 
 220         return 0;
 221 }
 222 
 223 int s5k83a_init(struct sd *sd)
 224 {
 225         int i, err = 0;
 226 
 227         for (i = 0; i < ARRAY_SIZE(init_s5k83a) && !err; i++) {
 228                 u8 data[2] = {0x00, 0x00};
 229 
 230                 switch (init_s5k83a[i][0]) {
 231                 case BRIDGE:
 232                         err = m5602_write_bridge(sd,
 233                                         init_s5k83a[i][1],
 234                                         init_s5k83a[i][2]);
 235                         break;
 236 
 237                 case SENSOR:
 238                         data[0] = init_s5k83a[i][2];
 239                         err = m5602_write_sensor(sd,
 240                                 init_s5k83a[i][1], data, 1);
 241                         break;
 242 
 243                 case SENSOR_LONG:
 244                         data[0] = init_s5k83a[i][2];
 245                         data[1] = init_s5k83a[i][3];
 246                         err = m5602_write_sensor(sd,
 247                                 init_s5k83a[i][1], data, 2);
 248                         break;
 249                 default:
 250                         pr_info("Invalid stream command, exiting init\n");
 251                         return -EINVAL;
 252                 }
 253         }
 254 
 255         if (dump_sensor)
 256                 s5k83a_dump_registers(sd);
 257 
 258         return err;
 259 }
 260 
 261 int s5k83a_init_controls(struct sd *sd)
 262 {
 263         struct v4l2_ctrl_handler *hdl = &sd->gspca_dev.ctrl_handler;
 264 
 265         sd->gspca_dev.vdev.ctrl_handler = hdl;
 266         v4l2_ctrl_handler_init(hdl, 6);
 267 
 268         v4l2_ctrl_new_std(hdl, &s5k83a_ctrl_ops, V4L2_CID_BRIGHTNESS,
 269                           0, 255, 1, S5K83A_DEFAULT_BRIGHTNESS);
 270 
 271         v4l2_ctrl_new_std(hdl, &s5k83a_ctrl_ops, V4L2_CID_EXPOSURE,
 272                           0, S5K83A_MAXIMUM_EXPOSURE, 1,
 273                           S5K83A_DEFAULT_EXPOSURE);
 274 
 275         v4l2_ctrl_new_std(hdl, &s5k83a_ctrl_ops, V4L2_CID_GAIN,
 276                           0, 255, 1, S5K83A_DEFAULT_GAIN);
 277 
 278         sd->hflip = v4l2_ctrl_new_std(hdl, &s5k83a_ctrl_ops, V4L2_CID_HFLIP,
 279                                       0, 1, 1, 0);
 280         sd->vflip = v4l2_ctrl_new_std(hdl, &s5k83a_ctrl_ops, V4L2_CID_VFLIP,
 281                                       0, 1, 1, 0);
 282 
 283         if (hdl->error) {
 284                 pr_err("Could not initialize controls\n");
 285                 return hdl->error;
 286         }
 287 
 288         v4l2_ctrl_cluster(2, &sd->hflip);
 289 
 290         return 0;
 291 }
 292 
 293 static int rotation_thread_function(void *data)
 294 {
 295         struct sd *sd = (struct sd *) data;
 296         u8 reg, previous_rotation = 0;
 297         __s32 vflip, hflip;
 298 
 299         set_current_state(TASK_INTERRUPTIBLE);
 300         while (!schedule_timeout(msecs_to_jiffies(100))) {
 301                 if (mutex_lock_interruptible(&sd->gspca_dev.usb_lock))
 302                         break;
 303 
 304                 s5k83a_get_rotation(sd, &reg);
 305                 if (previous_rotation != reg) {
 306                         previous_rotation = reg;
 307                         pr_info("Camera was flipped\n");
 308 
 309                         hflip = sd->hflip->val;
 310                         vflip = sd->vflip->val;
 311 
 312                         if (reg) {
 313                                 vflip = !vflip;
 314                                 hflip = !hflip;
 315                         }
 316                         s5k83a_set_flip_real((struct gspca_dev *) sd,
 317                                               vflip, hflip);
 318                 }
 319 
 320                 mutex_unlock(&sd->gspca_dev.usb_lock);
 321                 set_current_state(TASK_INTERRUPTIBLE);
 322         }
 323 
 324         /* return to "front" flip */
 325         if (previous_rotation) {
 326                 hflip = sd->hflip->val;
 327                 vflip = sd->vflip->val;
 328                 s5k83a_set_flip_real((struct gspca_dev *) sd, vflip, hflip);
 329         }
 330 
 331         sd->rotation_thread = NULL;
 332         return 0;
 333 }
 334 
 335 int s5k83a_start(struct sd *sd)
 336 {
 337         int i, err = 0;
 338 
 339         /* Create another thread, polling the GPIO ports of the camera to check
 340            if it got rotated. This is how the windows driver does it so we have
 341            to assume that there is no better way of accomplishing this */
 342         sd->rotation_thread = kthread_create(rotation_thread_function,
 343                                              sd, "rotation thread");
 344         if (IS_ERR(sd->rotation_thread)) {
 345                 err = PTR_ERR(sd->rotation_thread);
 346                 sd->rotation_thread = NULL;
 347                 return err;
 348         }
 349         wake_up_process(sd->rotation_thread);
 350 
 351         /* Preinit the sensor */
 352         for (i = 0; i < ARRAY_SIZE(start_s5k83a) && !err; i++) {
 353                 u8 data[2] = {start_s5k83a[i][2], start_s5k83a[i][3]};
 354                 if (start_s5k83a[i][0] == SENSOR)
 355                         err = m5602_write_sensor(sd, start_s5k83a[i][1],
 356                                 data, 2);
 357                 else
 358                         err = m5602_write_bridge(sd, start_s5k83a[i][1],
 359                                 data[0]);
 360         }
 361         if (err < 0)
 362                 return err;
 363 
 364         return s5k83a_set_led_indication(sd, 1);
 365 }
 366 
 367 int s5k83a_stop(struct sd *sd)
 368 {
 369         if (sd->rotation_thread)
 370                 kthread_stop(sd->rotation_thread);
 371 
 372         return s5k83a_set_led_indication(sd, 0);
 373 }
 374 
 375 void s5k83a_disconnect(struct sd *sd)
 376 {
 377         s5k83a_stop(sd);
 378 
 379         sd->sensor = NULL;
 380 }
 381 
 382 static int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val)
 383 {
 384         int err;
 385         u8 data[2];
 386         struct sd *sd = (struct sd *) gspca_dev;
 387 
 388         data[0] = 0x00;
 389         data[1] = 0x20;
 390         err = m5602_write_sensor(sd, 0x14, data, 2);
 391         if (err < 0)
 392                 return err;
 393 
 394         data[0] = 0x01;
 395         data[1] = 0x00;
 396         err = m5602_write_sensor(sd, 0x0d, data, 2);
 397         if (err < 0)
 398                 return err;
 399 
 400         /* FIXME: This is not sane, we need to figure out the composition
 401                   of these registers */
 402         data[0] = val >> 3; /* gain, high 5 bits */
 403         data[1] = val >> 1; /* gain, high 7 bits */
 404         err = m5602_write_sensor(sd, S5K83A_GAIN, data, 2);
 405 
 406         return err;
 407 }
 408 
 409 static int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
 410 {
 411         int err;
 412         u8 data[1];
 413         struct sd *sd = (struct sd *) gspca_dev;
 414 
 415         data[0] = val;
 416         err = m5602_write_sensor(sd, S5K83A_BRIGHTNESS, data, 1);
 417         return err;
 418 }
 419 
 420 static int s5k83a_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
 421 {
 422         int err;
 423         u8 data[2];
 424         struct sd *sd = (struct sd *) gspca_dev;
 425 
 426         data[0] = 0;
 427         data[1] = val;
 428         err = m5602_write_sensor(sd, S5K83A_EXPOSURE, data, 2);
 429         return err;
 430 }
 431 
 432 static int s5k83a_set_flip_real(struct gspca_dev *gspca_dev,
 433                                 __s32 vflip, __s32 hflip)
 434 {
 435         int err;
 436         u8 data[1];
 437         struct sd *sd = (struct sd *) gspca_dev;
 438 
 439         data[0] = 0x05;
 440         err = m5602_write_sensor(sd, S5K83A_PAGE_MAP, data, 1);
 441         if (err < 0)
 442                 return err;
 443 
 444         /* six bit is vflip, seven is hflip */
 445         data[0] = S5K83A_FLIP_MASK;
 446         data[0] = (vflip) ? data[0] | 0x40 : data[0];
 447         data[0] = (hflip) ? data[0] | 0x80 : data[0];
 448 
 449         err = m5602_write_sensor(sd, S5K83A_FLIP, data, 1);
 450         if (err < 0)
 451                 return err;
 452 
 453         data[0] = (vflip) ? 0x0b : 0x0a;
 454         err = m5602_write_sensor(sd, S5K83A_VFLIP_TUNE, data, 1);
 455         if (err < 0)
 456                 return err;
 457 
 458         data[0] = (hflip) ? 0x0a : 0x0b;
 459         err = m5602_write_sensor(sd, S5K83A_HFLIP_TUNE, data, 1);
 460         return err;
 461 }
 462 
 463 static int s5k83a_set_hvflip(struct gspca_dev *gspca_dev)
 464 {
 465         int err;
 466         u8 reg;
 467         struct sd *sd = (struct sd *) gspca_dev;
 468         int hflip = sd->hflip->val;
 469         int vflip = sd->vflip->val;
 470 
 471         err = s5k83a_get_rotation(sd, &reg);
 472         if (err < 0)
 473                 return err;
 474         if (reg) {
 475                 hflip = !hflip;
 476                 vflip = !vflip;
 477         }
 478 
 479         err = s5k83a_set_flip_real(gspca_dev, vflip, hflip);
 480         return err;
 481 }
 482 
 483 static int s5k83a_s_ctrl(struct v4l2_ctrl *ctrl)
 484 {
 485         struct gspca_dev *gspca_dev =
 486                 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
 487         int err;
 488 
 489         if (!gspca_dev->streaming)
 490                 return 0;
 491 
 492         switch (ctrl->id) {
 493         case V4L2_CID_BRIGHTNESS:
 494                 err = s5k83a_set_brightness(gspca_dev, ctrl->val);
 495                 break;
 496         case V4L2_CID_EXPOSURE:
 497                 err = s5k83a_set_exposure(gspca_dev, ctrl->val);
 498                 break;
 499         case V4L2_CID_GAIN:
 500                 err = s5k83a_set_gain(gspca_dev, ctrl->val);
 501                 break;
 502         case V4L2_CID_HFLIP:
 503                 err = s5k83a_set_hvflip(gspca_dev);
 504                 break;
 505         default:
 506                 return -EINVAL;
 507         }
 508 
 509         return err;
 510 }
 511 
 512 static int s5k83a_set_led_indication(struct sd *sd, u8 val)
 513 {
 514         int err = 0;
 515         u8 data[1];
 516 
 517         err = m5602_read_bridge(sd, M5602_XB_GPIO_DAT, data);
 518         if (err < 0)
 519                 return err;
 520 
 521         if (val)
 522                 data[0] = data[0] | S5K83A_GPIO_LED_MASK;
 523         else
 524                 data[0] = data[0] & ~S5K83A_GPIO_LED_MASK;
 525 
 526         err = m5602_write_bridge(sd, M5602_XB_GPIO_DAT, data[0]);
 527 
 528         return err;
 529 }
 530 
 531 /* Get camera rotation on Acer notebooks */
 532 static int s5k83a_get_rotation(struct sd *sd, u8 *reg_data)
 533 {
 534         int err = m5602_read_bridge(sd, M5602_XB_GPIO_DAT, reg_data);
 535         *reg_data = (*reg_data & S5K83A_GPIO_ROTATION_MASK) ? 0 : 1;
 536         return err;
 537 }
 538 
 539 static void s5k83a_dump_registers(struct sd *sd)
 540 {
 541         int address;
 542         u8 page, old_page;
 543         m5602_read_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1);
 544 
 545         for (page = 0; page < 16; page++) {
 546                 m5602_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1);
 547                 pr_info("Dumping the s5k83a register state for page 0x%x\n",
 548                         page);
 549                 for (address = 0; address <= 0xff; address++) {
 550                         u8 val = 0;
 551                         m5602_read_sensor(sd, address, &val, 1);
 552                         pr_info("register 0x%x contains 0x%x\n", address, val);
 553                 }
 554         }
 555         pr_info("s5k83a register state dump complete\n");
 556 
 557         for (page = 0; page < 16; page++) {
 558                 m5602_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1);
 559                 pr_info("Probing for which registers that are read/write for page 0x%x\n",
 560                         page);
 561                 for (address = 0; address <= 0xff; address++) {
 562                         u8 old_val, ctrl_val, test_val = 0xff;
 563 
 564                         m5602_read_sensor(sd, address, &old_val, 1);
 565                         m5602_write_sensor(sd, address, &test_val, 1);
 566                         m5602_read_sensor(sd, address, &ctrl_val, 1);
 567 
 568                         if (ctrl_val == test_val)
 569                                 pr_info("register 0x%x is writeable\n",
 570                                         address);
 571                         else
 572                                 pr_info("register 0x%x is read only\n",
 573                                         address);
 574 
 575                         /* Restore original val */
 576                         m5602_write_sensor(sd, address, &old_val, 1);
 577                 }
 578         }
 579         pr_info("Read/write register probing complete\n");
 580         m5602_write_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1);
 581 }

/* [<][>][^][v][top][bottom][index][help] */