linux/drivers/media/usb/em28xx/em28xx-camera.c
<<
>>
Prefs
   1/*
   2   em28xx-camera.c - driver for Empia EM25xx/27xx/28xx USB video capture devices
   3
   4   Copyright (C) 2009 Mauro Carvalho Chehab <mchehab@infradead.org>
   5   Copyright (C) 2013 Frank Schäfer <fschaefer.oss@googlemail.com>
   6
   7   This program is free software; you can redistribute it and/or modify
   8   it under the terms of the GNU General Public License as published by
   9   the Free Software Foundation; either version 2 of the License, or
  10   (at your option) any later version.
  11
  12   This program is distributed in the hope that it will be useful,
  13   but WITHOUT ANY WARRANTY; without even the implied warranty of
  14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15   GNU General Public License for more details.
  16
  17   You should have received a copy of the GNU General Public License
  18   along with this program; if not, write to the Free Software
  19   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20*/
  21
  22#include <linux/i2c.h>
  23#include <media/soc_camera.h>
  24#include <media/mt9v011.h>
  25#include <media/v4l2-common.h>
  26
  27#include "em28xx.h"
  28
  29
  30/* Possible i2c addresses of Micron sensors */
  31static unsigned short micron_sensor_addrs[] = {
  32        0xb8 >> 1,   /* MT9V111, MT9V403 */
  33        0xba >> 1,   /* MT9M001/011/111/112, MT9V011/012/112, MT9D011 */
  34        0x90 >> 1,   /* MT9V012/112, MT9D011 (alternative address) */
  35        I2C_CLIENT_END
  36};
  37
  38/* Possible i2c addresses of Omnivision sensors */
  39static unsigned short omnivision_sensor_addrs[] = {
  40        0x42 >> 1,   /* OV7725, OV7670/60/48 */
  41        0x60 >> 1,   /* OV2640, OV9650/53/55 */
  42        I2C_CLIENT_END
  43};
  44
  45
  46static struct soc_camera_link camlink = {
  47        .bus_id = 0,
  48        .flags = 0,
  49        .module_name = "em28xx",
  50};
  51
  52
  53/* FIXME: Should be replaced by a proper mt9m111 driver */
  54static int em28xx_initialize_mt9m111(struct em28xx *dev)
  55{
  56        int i;
  57        unsigned char regs[][3] = {
  58                { 0x0d, 0x00, 0x01, },  /* reset and use defaults */
  59                { 0x0d, 0x00, 0x00, },
  60                { 0x0a, 0x00, 0x21, },
  61                { 0x21, 0x04, 0x00, },  /* full readout speed, no row/col skipping */
  62        };
  63
  64        for (i = 0; i < ARRAY_SIZE(regs); i++)
  65                i2c_master_send(&dev->i2c_client[dev->def_i2c_bus],
  66                                &regs[i][0], 3);
  67
  68        return 0;
  69}
  70
  71
  72/* FIXME: Should be replaced by a proper mt9m001 driver */
  73static int em28xx_initialize_mt9m001(struct em28xx *dev)
  74{
  75        int i;
  76        unsigned char regs[][3] = {
  77                { 0x0d, 0x00, 0x01, },
  78                { 0x0d, 0x00, 0x00, },
  79                { 0x04, 0x05, 0x00, },  /* hres = 1280 */
  80                { 0x03, 0x04, 0x00, },  /* vres = 1024 */
  81                { 0x20, 0x11, 0x00, },
  82                { 0x06, 0x00, 0x10, },
  83                { 0x2b, 0x00, 0x24, },
  84                { 0x2e, 0x00, 0x24, },
  85                { 0x35, 0x00, 0x24, },
  86                { 0x2d, 0x00, 0x20, },
  87                { 0x2c, 0x00, 0x20, },
  88                { 0x09, 0x0a, 0xd4, },
  89                { 0x35, 0x00, 0x57, },
  90        };
  91
  92        for (i = 0; i < ARRAY_SIZE(regs); i++)
  93                i2c_master_send(&dev->i2c_client[dev->def_i2c_bus],
  94                                &regs[i][0], 3);
  95
  96        return 0;
  97}
  98
  99
 100/*
 101 * Probes Micron sensors with 8 bit address and 16 bit register width
 102 */
 103static int em28xx_probe_sensor_micron(struct em28xx *dev)
 104{
 105        int ret, i;
 106        char *name;
 107        u8 reg;
 108        __be16 id_be;
 109        u16 id;
 110
 111        struct i2c_client client = dev->i2c_client[dev->def_i2c_bus];
 112
 113        dev->em28xx_sensor = EM28XX_NOSENSOR;
 114        for (i = 0; micron_sensor_addrs[i] != I2C_CLIENT_END; i++) {
 115                client.addr = micron_sensor_addrs[i];
 116                /* NOTE: i2c_smbus_read_word_data() doesn't work with BE data */
 117                /* Read chip ID from register 0x00 */
 118                reg = 0x00;
 119                ret = i2c_master_send(&client, &reg, 1);
 120                if (ret < 0) {
 121                        if (ret != -ENODEV)
 122                                em28xx_errdev("couldn't read from i2c device 0x%02x: error %i\n",
 123                                              client.addr << 1, ret);
 124                        continue;
 125                }
 126                ret = i2c_master_recv(&client, (u8 *)&id_be, 2);
 127                if (ret < 0) {
 128                        em28xx_errdev("couldn't read from i2c device 0x%02x: error %i\n",
 129                                      client.addr << 1, ret);
 130                        continue;
 131                }
 132                id = be16_to_cpu(id_be);
 133                /* Read chip ID from register 0xff */
 134                reg = 0xff;
 135                ret = i2c_master_send(&client, &reg, 1);
 136                if (ret < 0) {
 137                        em28xx_errdev("couldn't read from i2c device 0x%02x: error %i\n",
 138                                      client.addr << 1, ret);
 139                        continue;
 140                }
 141                ret = i2c_master_recv(&client, (u8 *)&id_be, 2);
 142                if (ret < 0) {
 143                        em28xx_errdev("couldn't read from i2c device 0x%02x: error %i\n",
 144                                      client.addr << 1, ret);
 145                        continue;
 146                }
 147                /* Validate chip ID to be sure we have a Micron device */
 148                if (id != be16_to_cpu(id_be))
 149                        continue;
 150                /* Check chip ID */
 151                id = be16_to_cpu(id_be);
 152                switch (id) {
 153                case 0x1222:
 154                        name = "MT9V012"; /* MI370 */ /* 640x480 */
 155                        break;
 156                case 0x1229:
 157                        name = "MT9V112"; /* 640x480 */
 158                        break;
 159                case 0x1433:
 160                        name = "MT9M011"; /* 1280x1024 */
 161                        break;
 162                case 0x143a:    /* found in the ECS G200 */
 163                        name = "MT9M111"; /* MI1310 */ /* 1280x1024 */
 164                        dev->em28xx_sensor = EM28XX_MT9M111;
 165                        break;
 166                case 0x148c:
 167                        name = "MT9M112"; /* MI1320 */ /* 1280x1024 */
 168                        break;
 169                case 0x1511:
 170                        name = "MT9D011"; /* MI2010 */ /* 1600x1200 */
 171                        break;
 172                case 0x8232:
 173                case 0x8243:    /* rev B */
 174                        name = "MT9V011"; /* MI360 */ /* 640x480 */
 175                        dev->em28xx_sensor = EM28XX_MT9V011;
 176                        break;
 177                case 0x8431:
 178                        name = "MT9M001"; /* 1280x1024 */
 179                        dev->em28xx_sensor = EM28XX_MT9M001;
 180                        break;
 181                default:
 182                        em28xx_info("unknown Micron sensor detected: 0x%04x\n",
 183                                    id);
 184                        return 0;
 185                }
 186
 187                if (dev->em28xx_sensor == EM28XX_NOSENSOR)
 188                        em28xx_info("unsupported sensor detected: %s\n", name);
 189                else
 190                        em28xx_info("sensor %s detected\n", name);
 191
 192                dev->i2c_client[dev->def_i2c_bus].addr = client.addr;
 193                return 0;
 194        }
 195
 196        return -ENODEV;
 197}
 198
 199/*
 200 * Probes Omnivision sensors with 8 bit address and register width
 201 */
 202static int em28xx_probe_sensor_omnivision(struct em28xx *dev)
 203{
 204        int ret, i;
 205        char *name;
 206        u8 reg;
 207        u16 id;
 208        struct i2c_client client = dev->i2c_client[dev->def_i2c_bus];
 209
 210        dev->em28xx_sensor = EM28XX_NOSENSOR;
 211        /* NOTE: these devices have the register auto incrementation disabled
 212         * by default, so we have to use single byte reads !              */
 213        for (i = 0; omnivision_sensor_addrs[i] != I2C_CLIENT_END; i++) {
 214                client.addr = omnivision_sensor_addrs[i];
 215                /* Read manufacturer ID from registers 0x1c-0x1d (BE) */
 216                reg = 0x1c;
 217                ret = i2c_smbus_read_byte_data(&client, reg);
 218                if (ret < 0) {
 219                        if (ret != -ENODEV)
 220                                em28xx_errdev("couldn't read from i2c device 0x%02x: error %i\n",
 221                                              client.addr << 1, ret);
 222                        continue;
 223                }
 224                id = ret << 8;
 225                reg = 0x1d;
 226                ret = i2c_smbus_read_byte_data(&client, reg);
 227                if (ret < 0) {
 228                        em28xx_errdev("couldn't read from i2c device 0x%02x: error %i\n",
 229                                      client.addr << 1, ret);
 230                        continue;
 231                }
 232                id += ret;
 233                /* Check manufacturer ID */
 234                if (id != 0x7fa2)
 235                        continue;
 236                /* Read product ID from registers 0x0a-0x0b (BE) */
 237                reg = 0x0a;
 238                ret = i2c_smbus_read_byte_data(&client, reg);
 239                if (ret < 0) {
 240                        em28xx_errdev("couldn't read from i2c device 0x%02x: error %i\n",
 241                                      client.addr << 1, ret);
 242                        continue;
 243                }
 244                id = ret << 8;
 245                reg = 0x0b;
 246                ret = i2c_smbus_read_byte_data(&client, reg);
 247                if (ret < 0) {
 248                        em28xx_errdev("couldn't read from i2c device 0x%02x: error %i\n",
 249                                      client.addr << 1, ret);
 250                        continue;
 251                }
 252                id += ret;
 253                /* Check product ID */
 254                switch (id) {
 255                case 0x2642:
 256                        name = "OV2640";
 257                        dev->em28xx_sensor = EM28XX_OV2640;
 258                        break;
 259                case 0x7648:
 260                        name = "OV7648";
 261                        break;
 262                case 0x7660:
 263                        name = "OV7660";
 264                        break;
 265                case 0x7673:
 266                        name = "OV7670";
 267                        break;
 268                case 0x7720:
 269                        name = "OV7720";
 270                        break;
 271                case 0x7721:
 272                        name = "OV7725";
 273                        break;
 274                case 0x9648: /* Rev 2 */
 275                case 0x9649: /* Rev 3 */
 276                        name = "OV9640";
 277                        break;
 278                case 0x9650:
 279                case 0x9652: /* OV9653 */
 280                        name = "OV9650";
 281                        break;
 282                case 0x9656: /* Rev 4 */
 283                case 0x9657: /* Rev 5 */
 284                        name = "OV9655";
 285                        break;
 286                default:
 287                        em28xx_info("unknown OmniVision sensor detected: 0x%04x\n",
 288                                    id);
 289                        return 0;
 290                }
 291
 292                if (dev->em28xx_sensor == EM28XX_NOSENSOR)
 293                        em28xx_info("unsupported sensor detected: %s\n", name);
 294                else
 295                        em28xx_info("sensor %s detected\n", name);
 296
 297                dev->i2c_client[dev->def_i2c_bus].addr = client.addr;
 298                return 0;
 299        }
 300
 301        return -ENODEV;
 302}
 303
 304int em28xx_detect_sensor(struct em28xx *dev)
 305{
 306        int ret;
 307
 308        ret = em28xx_probe_sensor_micron(dev);
 309
 310        if (dev->em28xx_sensor == EM28XX_NOSENSOR && ret < 0)
 311                ret = em28xx_probe_sensor_omnivision(dev);
 312
 313        /*
 314         * NOTE: the Windows driver also probes i2c addresses
 315         *       0x22 (Samsung ?) and 0x66 (Kodak ?)
 316         */
 317
 318        if (dev->em28xx_sensor == EM28XX_NOSENSOR && ret < 0) {
 319                em28xx_info("No sensor detected\n");
 320                return -ENODEV;
 321        }
 322
 323        return 0;
 324}
 325
 326int em28xx_init_camera(struct em28xx *dev)
 327{
 328        switch (dev->em28xx_sensor) {
 329        case EM28XX_MT9V011:
 330        {
 331                struct mt9v011_platform_data pdata;
 332                struct i2c_board_info mt9v011_info = {
 333                        .type = "mt9v011",
 334                        .addr = dev->i2c_client[dev->def_i2c_bus].addr,
 335                        .platform_data = &pdata,
 336                };
 337
 338                dev->sensor_xres = 640;
 339                dev->sensor_yres = 480;
 340
 341                /*
 342                 * FIXME: mt9v011 uses I2S speed as xtal clk - at least with
 343                 * the Silvercrest cam I have here for testing - for higher
 344                 * resolutions, a high clock cause horizontal artifacts, so we
 345                 * need to use a lower xclk frequency.
 346                 * Yet, it would be possible to adjust xclk depending on the
 347                 * desired resolution, since this affects directly the
 348                 * frame rate.
 349                 */
 350                dev->board.xclk = EM28XX_XCLK_FREQUENCY_4_3MHZ;
 351                em28xx_write_reg(dev, EM28XX_R0F_XCLK, dev->board.xclk);
 352                dev->sensor_xtal = 4300000;
 353                pdata.xtal = dev->sensor_xtal;
 354                if (NULL ==
 355                    v4l2_i2c_new_subdev_board(&dev->v4l2_dev,
 356                                              &dev->i2c_adap[dev->def_i2c_bus],
 357                                              &mt9v011_info, NULL))
 358                        return -ENODEV;
 359                /* probably means GRGB 16 bit bayer */
 360                dev->vinmode = 0x0d;
 361                dev->vinctl = 0x00;
 362
 363                break;
 364        }
 365        case EM28XX_MT9M001:
 366                dev->sensor_xres = 1280;
 367                dev->sensor_yres = 1024;
 368
 369                em28xx_initialize_mt9m001(dev);
 370
 371                /* probably means BGGR 16 bit bayer */
 372                dev->vinmode = 0x0c;
 373                dev->vinctl = 0x00;
 374
 375                break;
 376        case EM28XX_MT9M111:
 377                dev->sensor_xres = 640;
 378                dev->sensor_yres = 512;
 379
 380                dev->board.xclk = EM28XX_XCLK_FREQUENCY_48MHZ;
 381                em28xx_write_reg(dev, EM28XX_R0F_XCLK, dev->board.xclk);
 382                em28xx_initialize_mt9m111(dev);
 383
 384                dev->vinmode = 0x0a;
 385                dev->vinctl = 0x00;
 386
 387                break;
 388        case EM28XX_OV2640:
 389        {
 390                struct v4l2_subdev *subdev;
 391                struct i2c_board_info ov2640_info = {
 392                        .type = "ov2640",
 393                        .flags = I2C_CLIENT_SCCB,
 394                        .addr = dev->i2c_client[dev->def_i2c_bus].addr,
 395                        .platform_data = &camlink,
 396                };
 397                struct v4l2_mbus_framefmt fmt;
 398
 399                /*
 400                 * FIXME: sensor supports resolutions up to 1600x1200, but
 401                 * resolution setting/switching needs to be modified to
 402                 * - switch sensor output resolution (including further
 403                 *   configuration changes)
 404                 * - adjust bridge xclk
 405                 * - disable 16 bit (12 bit) output formats on high resolutions
 406                 */
 407                dev->sensor_xres = 640;
 408                dev->sensor_yres = 480;
 409
 410                subdev =
 411                     v4l2_i2c_new_subdev_board(&dev->v4l2_dev,
 412                                               &dev->i2c_adap[dev->def_i2c_bus],
 413                                               &ov2640_info, NULL);
 414
 415                fmt.code = V4L2_MBUS_FMT_YUYV8_2X8;
 416                fmt.width = 640;
 417                fmt.height = 480;
 418                v4l2_subdev_call(subdev, video, s_mbus_fmt, &fmt);
 419
 420                /* NOTE: for UXGA=1600x1200 switch to 12MHz */
 421                dev->board.xclk = EM28XX_XCLK_FREQUENCY_24MHZ;
 422                em28xx_write_reg(dev, EM28XX_R0F_XCLK, dev->board.xclk);
 423                dev->vinmode = 0x08;
 424                dev->vinctl = 0x00;
 425
 426                break;
 427        }
 428        case EM28XX_NOSENSOR:
 429        default:
 430                return -EINVAL;
 431        }
 432
 433        return 0;
 434}
 435