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