linux/drivers/media/usb/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_s_ctrl(struct v4l2_ctrl *ctrl);
  25
  26static const struct v4l2_ctrl_ops s5k83a_ctrl_ops = {
  27        .s_ctrl = s5k83a_s_ctrl,
  28};
  29
  30static struct v4l2_pix_format s5k83a_modes[] = {
  31        {
  32                640,
  33                480,
  34                V4L2_PIX_FMT_SBGGR8,
  35                V4L2_FIELD_NONE,
  36                .sizeimage =
  37                        640 * 480,
  38                .bytesperline = 640,
  39                .colorspace = V4L2_COLORSPACE_SRGB,
  40                .priv = 0
  41        }
  42};
  43
  44static void s5k83a_dump_registers(struct sd *sd);
  45static int s5k83a_get_rotation(struct sd *sd, u8 *reg_data);
  46static int s5k83a_set_led_indication(struct sd *sd, u8 val);
  47static int s5k83a_set_flip_real(struct gspca_dev *gspca_dev,
  48                                __s32 vflip, __s32 hflip);
  49
  50int s5k83a_probe(struct sd *sd)
  51{
  52        u8 prod_id = 0, ver_id = 0;
  53        int i, err = 0;
  54        struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
  55
  56        if (force_sensor) {
  57                if (force_sensor == S5K83A_SENSOR) {
  58                        pr_info("Forcing a %s sensor\n", s5k83a.name);
  59                        goto sensor_found;
  60                }
  61                /* If we want to force another sensor, don't try to probe this
  62                 * one */
  63                return -ENODEV;
  64        }
  65
  66        PDEBUG(D_PROBE, "Probing for a s5k83a sensor");
  67
  68        /* Preinit the sensor */
  69        for (i = 0; i < ARRAY_SIZE(preinit_s5k83a) && !err; i++) {
  70                u8 data[2] = {preinit_s5k83a[i][2], preinit_s5k83a[i][3]};
  71                if (preinit_s5k83a[i][0] == SENSOR)
  72                        err = m5602_write_sensor(sd, preinit_s5k83a[i][1],
  73                                data, 2);
  74                else
  75                        err = m5602_write_bridge(sd, preinit_s5k83a[i][1],
  76                                data[0]);
  77        }
  78
  79        /* We don't know what register (if any) that contain the product id
  80         * Just pick the first addresses that seem to produce the same results
  81         * on multiple machines */
  82        if (m5602_read_sensor(sd, 0x00, &prod_id, 1))
  83                return -ENODEV;
  84
  85        if (m5602_read_sensor(sd, 0x01, &ver_id, 1))
  86                return -ENODEV;
  87
  88        if ((prod_id == 0xff) || (ver_id == 0xff))
  89                return -ENODEV;
  90        else
  91                pr_info("Detected a s5k83a sensor\n");
  92
  93sensor_found:
  94        sd->gspca_dev.cam.cam_mode = s5k83a_modes;
  95        sd->gspca_dev.cam.nmodes = ARRAY_SIZE(s5k83a_modes);
  96
  97        /* null the pointer! thread is't running now */
  98        sd->rotation_thread = NULL;
  99
 100        return 0;
 101}
 102
 103int s5k83a_init(struct sd *sd)
 104{
 105        int i, err = 0;
 106
 107        for (i = 0; i < ARRAY_SIZE(init_s5k83a) && !err; i++) {
 108                u8 data[2] = {0x00, 0x00};
 109
 110                switch (init_s5k83a[i][0]) {
 111                case BRIDGE:
 112                        err = m5602_write_bridge(sd,
 113                                        init_s5k83a[i][1],
 114                                        init_s5k83a[i][2]);
 115                        break;
 116
 117                case SENSOR:
 118                        data[0] = init_s5k83a[i][2];
 119                        err = m5602_write_sensor(sd,
 120                                init_s5k83a[i][1], data, 1);
 121                        break;
 122
 123                case SENSOR_LONG:
 124                        data[0] = init_s5k83a[i][2];
 125                        data[1] = init_s5k83a[i][3];
 126                        err = m5602_write_sensor(sd,
 127                                init_s5k83a[i][1], data, 2);
 128                        break;
 129                default:
 130                        pr_info("Invalid stream command, exiting init\n");
 131                        return -EINVAL;
 132                }
 133        }
 134
 135        if (dump_sensor)
 136                s5k83a_dump_registers(sd);
 137
 138        return err;
 139}
 140
 141int s5k83a_init_controls(struct sd *sd)
 142{
 143        struct v4l2_ctrl_handler *hdl = &sd->gspca_dev.ctrl_handler;
 144
 145        sd->gspca_dev.vdev.ctrl_handler = hdl;
 146        v4l2_ctrl_handler_init(hdl, 6);
 147
 148        v4l2_ctrl_new_std(hdl, &s5k83a_ctrl_ops, V4L2_CID_BRIGHTNESS,
 149                          0, 255, 1, S5K83A_DEFAULT_BRIGHTNESS);
 150
 151        v4l2_ctrl_new_std(hdl, &s5k83a_ctrl_ops, V4L2_CID_EXPOSURE,
 152                          0, S5K83A_MAXIMUM_EXPOSURE, 1,
 153                          S5K83A_DEFAULT_EXPOSURE);
 154
 155        v4l2_ctrl_new_std(hdl, &s5k83a_ctrl_ops, V4L2_CID_GAIN,
 156                          0, 255, 1, S5K83A_DEFAULT_GAIN);
 157
 158        sd->hflip = v4l2_ctrl_new_std(hdl, &s5k83a_ctrl_ops, V4L2_CID_HFLIP,
 159                                      0, 1, 1, 0);
 160        sd->vflip = v4l2_ctrl_new_std(hdl, &s5k83a_ctrl_ops, V4L2_CID_VFLIP,
 161                                      0, 1, 1, 0);
 162
 163        if (hdl->error) {
 164                pr_err("Could not initialize controls\n");
 165                return hdl->error;
 166        }
 167
 168        v4l2_ctrl_cluster(2, &sd->hflip);
 169
 170        return 0;
 171}
 172
 173static int rotation_thread_function(void *data)
 174{
 175        struct sd *sd = (struct sd *) data;
 176        u8 reg, previous_rotation = 0;
 177        __s32 vflip, hflip;
 178
 179        set_current_state(TASK_INTERRUPTIBLE);
 180        while (!schedule_timeout(100)) {
 181                if (mutex_lock_interruptible(&sd->gspca_dev.usb_lock))
 182                        break;
 183
 184                s5k83a_get_rotation(sd, &reg);
 185                if (previous_rotation != reg) {
 186                        previous_rotation = reg;
 187                        pr_info("Camera was flipped\n");
 188
 189                        hflip = sd->hflip->val;
 190                        vflip = sd->vflip->val;
 191
 192                        if (reg) {
 193                                vflip = !vflip;
 194                                hflip = !hflip;
 195                        }
 196                        s5k83a_set_flip_real((struct gspca_dev *) sd,
 197                                              vflip, hflip);
 198                }
 199
 200                mutex_unlock(&sd->gspca_dev.usb_lock);
 201                set_current_state(TASK_INTERRUPTIBLE);
 202        }
 203
 204        /* return to "front" flip */
 205        if (previous_rotation) {
 206                hflip = sd->hflip->val;
 207                vflip = sd->vflip->val;
 208                s5k83a_set_flip_real((struct gspca_dev *) sd, vflip, hflip);
 209        }
 210
 211        sd->rotation_thread = NULL;
 212        return 0;
 213}
 214
 215int s5k83a_start(struct sd *sd)
 216{
 217        int i, err = 0;
 218
 219        /* Create another thread, polling the GPIO ports of the camera to check
 220           if it got rotated. This is how the windows driver does it so we have
 221           to assume that there is no better way of accomplishing this */
 222        sd->rotation_thread = kthread_create(rotation_thread_function,
 223                                             sd, "rotation thread");
 224        wake_up_process(sd->rotation_thread);
 225
 226        /* Preinit the sensor */
 227        for (i = 0; i < ARRAY_SIZE(start_s5k83a) && !err; i++) {
 228                u8 data[2] = {start_s5k83a[i][2], start_s5k83a[i][3]};
 229                if (start_s5k83a[i][0] == SENSOR)
 230                        err = m5602_write_sensor(sd, start_s5k83a[i][1],
 231                                data, 2);
 232                else
 233                        err = m5602_write_bridge(sd, start_s5k83a[i][1],
 234                                data[0]);
 235        }
 236        if (err < 0)
 237                return err;
 238
 239        return s5k83a_set_led_indication(sd, 1);
 240}
 241
 242int s5k83a_stop(struct sd *sd)
 243{
 244        if (sd->rotation_thread)
 245                kthread_stop(sd->rotation_thread);
 246
 247        return s5k83a_set_led_indication(sd, 0);
 248}
 249
 250void s5k83a_disconnect(struct sd *sd)
 251{
 252        s5k83a_stop(sd);
 253
 254        sd->sensor = NULL;
 255}
 256
 257static int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val)
 258{
 259        int err;
 260        u8 data[2];
 261        struct sd *sd = (struct sd *) gspca_dev;
 262
 263        data[0] = 0x00;
 264        data[1] = 0x20;
 265        err = m5602_write_sensor(sd, 0x14, data, 2);
 266        if (err < 0)
 267                return err;
 268
 269        data[0] = 0x01;
 270        data[1] = 0x00;
 271        err = m5602_write_sensor(sd, 0x0d, data, 2);
 272        if (err < 0)
 273                return err;
 274
 275        /* FIXME: This is not sane, we need to figure out the composition
 276                  of these registers */
 277        data[0] = val >> 3; /* gain, high 5 bits */
 278        data[1] = val >> 1; /* gain, high 7 bits */
 279        err = m5602_write_sensor(sd, S5K83A_GAIN, data, 2);
 280
 281        return err;
 282}
 283
 284static int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
 285{
 286        int err;
 287        u8 data[1];
 288        struct sd *sd = (struct sd *) gspca_dev;
 289
 290        data[0] = val;
 291        err = m5602_write_sensor(sd, S5K83A_BRIGHTNESS, data, 1);
 292        return err;
 293}
 294
 295static int s5k83a_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
 296{
 297        int err;
 298        u8 data[2];
 299        struct sd *sd = (struct sd *) gspca_dev;
 300
 301        data[0] = 0;
 302        data[1] = val;
 303        err = m5602_write_sensor(sd, S5K83A_EXPOSURE, data, 2);
 304        return err;
 305}
 306
 307static int s5k83a_set_flip_real(struct gspca_dev *gspca_dev,
 308                                __s32 vflip, __s32 hflip)
 309{
 310        int err;
 311        u8 data[1];
 312        struct sd *sd = (struct sd *) gspca_dev;
 313
 314        data[0] = 0x05;
 315        err = m5602_write_sensor(sd, S5K83A_PAGE_MAP, data, 1);
 316        if (err < 0)
 317                return err;
 318
 319        /* six bit is vflip, seven is hflip */
 320        data[0] = S5K83A_FLIP_MASK;
 321        data[0] = (vflip) ? data[0] | 0x40 : data[0];
 322        data[0] = (hflip) ? data[0] | 0x80 : data[0];
 323
 324        err = m5602_write_sensor(sd, S5K83A_FLIP, data, 1);
 325        if (err < 0)
 326                return err;
 327
 328        data[0] = (vflip) ? 0x0b : 0x0a;
 329        err = m5602_write_sensor(sd, S5K83A_VFLIP_TUNE, data, 1);
 330        if (err < 0)
 331                return err;
 332
 333        data[0] = (hflip) ? 0x0a : 0x0b;
 334        err = m5602_write_sensor(sd, S5K83A_HFLIP_TUNE, data, 1);
 335        return err;
 336}
 337
 338static int s5k83a_set_hvflip(struct gspca_dev *gspca_dev)
 339{
 340        int err;
 341        u8 reg;
 342        struct sd *sd = (struct sd *) gspca_dev;
 343        int hflip = sd->hflip->val;
 344        int vflip = sd->vflip->val;
 345
 346        err = s5k83a_get_rotation(sd, &reg);
 347        if (err < 0)
 348                return err;
 349        if (reg) {
 350                hflip = !hflip;
 351                vflip = !vflip;
 352        }
 353
 354        err = s5k83a_set_flip_real(gspca_dev, vflip, hflip);
 355        return err;
 356}
 357
 358static int s5k83a_s_ctrl(struct v4l2_ctrl *ctrl)
 359{
 360        struct gspca_dev *gspca_dev =
 361                container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
 362        int err;
 363
 364        if (!gspca_dev->streaming)
 365                return 0;
 366
 367        switch (ctrl->id) {
 368        case V4L2_CID_BRIGHTNESS:
 369                err = s5k83a_set_brightness(gspca_dev, ctrl->val);
 370                break;
 371        case V4L2_CID_EXPOSURE:
 372                err = s5k83a_set_exposure(gspca_dev, ctrl->val);
 373                break;
 374        case V4L2_CID_GAIN:
 375                err = s5k83a_set_gain(gspca_dev, ctrl->val);
 376                break;
 377        case V4L2_CID_HFLIP:
 378                err = s5k83a_set_hvflip(gspca_dev);
 379                break;
 380        default:
 381                return -EINVAL;
 382        }
 383
 384        return err;
 385}
 386
 387static int s5k83a_set_led_indication(struct sd *sd, u8 val)
 388{
 389        int err = 0;
 390        u8 data[1];
 391
 392        err = m5602_read_bridge(sd, M5602_XB_GPIO_DAT, data);
 393        if (err < 0)
 394                return err;
 395
 396        if (val)
 397                data[0] = data[0] | S5K83A_GPIO_LED_MASK;
 398        else
 399                data[0] = data[0] & ~S5K83A_GPIO_LED_MASK;
 400
 401        err = m5602_write_bridge(sd, M5602_XB_GPIO_DAT, data[0]);
 402
 403        return err;
 404}
 405
 406/* Get camera rotation on Acer notebooks */
 407static int s5k83a_get_rotation(struct sd *sd, u8 *reg_data)
 408{
 409        int err = m5602_read_bridge(sd, M5602_XB_GPIO_DAT, reg_data);
 410        *reg_data = (*reg_data & S5K83A_GPIO_ROTATION_MASK) ? 0 : 1;
 411        return err;
 412}
 413
 414static void s5k83a_dump_registers(struct sd *sd)
 415{
 416        int address;
 417        u8 page, old_page;
 418        m5602_read_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1);
 419
 420        for (page = 0; page < 16; page++) {
 421                m5602_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1);
 422                pr_info("Dumping the s5k83a register state for page 0x%x\n",
 423                        page);
 424                for (address = 0; address <= 0xff; address++) {
 425                        u8 val = 0;
 426                        m5602_read_sensor(sd, address, &val, 1);
 427                        pr_info("register 0x%x contains 0x%x\n", address, val);
 428                }
 429        }
 430        pr_info("s5k83a register state dump complete\n");
 431
 432        for (page = 0; page < 16; page++) {
 433                m5602_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1);
 434                pr_info("Probing for which registers that are read/write for page 0x%x\n",
 435                        page);
 436                for (address = 0; address <= 0xff; address++) {
 437                        u8 old_val, ctrl_val, test_val = 0xff;
 438
 439                        m5602_read_sensor(sd, address, &old_val, 1);
 440                        m5602_write_sensor(sd, address, &test_val, 1);
 441                        m5602_read_sensor(sd, address, &ctrl_val, 1);
 442
 443                        if (ctrl_val == test_val)
 444                                pr_info("register 0x%x is writeable\n",
 445                                        address);
 446                        else
 447                                pr_info("register 0x%x is read only\n",
 448                                        address);
 449
 450                        /* Restore original val */
 451                        m5602_write_sensor(sd, address, &old_val, 1);
 452                }
 453        }
 454        pr_info("Read/write register probing complete\n");
 455        m5602_write_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1);
 456}
 457