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