Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 //
0003 // em28xx-camera.c - driver for Empia EM25xx/27xx/28xx USB video capture devices
0004 //
0005 // Copyright (C) 2009 Mauro Carvalho Chehab <mchehab@kernel.org>
0006 // Copyright (C) 2013 Frank Schäfer <fschaefer.oss@googlemail.com>
0007 
0008 #include "em28xx.h"
0009 
0010 #include <linux/i2c.h>
0011 #include <linux/usb.h>
0012 #include <media/i2c/mt9v011.h>
0013 #include <media/v4l2-common.h>
0014 
0015 /* Possible i2c addresses of Micron sensors */
0016 static unsigned short micron_sensor_addrs[] = {
0017     0xb8 >> 1,   /* MT9V111, MT9V403 */
0018     0xba >> 1,   /* MT9M001/011/111/112, MT9V011/012/112, MT9D011 */
0019     0x90 >> 1,   /* MT9V012/112, MT9D011 (alternative address) */
0020     I2C_CLIENT_END
0021 };
0022 
0023 /* Possible i2c addresses of Omnivision sensors */
0024 static unsigned short omnivision_sensor_addrs[] = {
0025     0x42 >> 1,   /* OV7725, OV7670/60/48 */
0026     0x60 >> 1,   /* OV2640, OV9650/53/55 */
0027     I2C_CLIENT_END
0028 };
0029 
0030 /* FIXME: Should be replaced by a proper mt9m111 driver */
0031 static int em28xx_initialize_mt9m111(struct em28xx *dev)
0032 {
0033     int i;
0034     unsigned char regs[][3] = {
0035         { 0x0d, 0x00, 0x01, },  /* reset and use defaults */
0036         { 0x0d, 0x00, 0x00, },
0037         { 0x0a, 0x00, 0x21, },
0038         { 0x21, 0x04, 0x00, },  /* full readout spd, no row/col skip */
0039     };
0040 
0041     for (i = 0; i < ARRAY_SIZE(regs); i++)
0042         i2c_master_send(&dev->i2c_client[dev->def_i2c_bus],
0043                 &regs[i][0], 3);
0044 
0045     /* FIXME: This won't be creating a sensor at the media graph */
0046 
0047     return 0;
0048 }
0049 
0050 /* FIXME: Should be replaced by a proper mt9m001 driver */
0051 static int em28xx_initialize_mt9m001(struct em28xx *dev)
0052 {
0053     int i;
0054     unsigned char regs[][3] = {
0055         { 0x0d, 0x00, 0x01, },
0056         { 0x0d, 0x00, 0x00, },
0057         { 0x04, 0x05, 0x00, },  /* hres = 1280 */
0058         { 0x03, 0x04, 0x00, },  /* vres = 1024 */
0059         { 0x20, 0x11, 0x00, },
0060         { 0x06, 0x00, 0x10, },
0061         { 0x2b, 0x00, 0x24, },
0062         { 0x2e, 0x00, 0x24, },
0063         { 0x35, 0x00, 0x24, },
0064         { 0x2d, 0x00, 0x20, },
0065         { 0x2c, 0x00, 0x20, },
0066         { 0x09, 0x0a, 0xd4, },
0067         { 0x35, 0x00, 0x57, },
0068     };
0069 
0070     for (i = 0; i < ARRAY_SIZE(regs); i++)
0071         i2c_master_send(&dev->i2c_client[dev->def_i2c_bus],
0072                 &regs[i][0], 3);
0073 
0074     /* FIXME: This won't be creating a sensor at the media graph */
0075 
0076     return 0;
0077 }
0078 
0079 /*
0080  * Probes Micron sensors with 8 bit address and 16 bit register width
0081  */
0082 static int em28xx_probe_sensor_micron(struct em28xx *dev)
0083 {
0084     int ret, i;
0085     char *name;
0086     u16 id;
0087 
0088     struct i2c_client *client = &dev->i2c_client[dev->def_i2c_bus];
0089 
0090     dev->em28xx_sensor = EM28XX_NOSENSOR;
0091     for (i = 0; micron_sensor_addrs[i] != I2C_CLIENT_END; i++) {
0092         client->addr = micron_sensor_addrs[i];
0093         /* Read chip ID from register 0x00 */
0094         ret = i2c_smbus_read_word_data(client, 0x00); /* assumes LE */
0095         if (ret < 0) {
0096             if (ret != -ENXIO)
0097                 dev_err(&dev->intf->dev,
0098                     "couldn't read from i2c device 0x%02x: error %i\n",
0099                        client->addr << 1, ret);
0100             continue;
0101         }
0102         id = swab16(ret); /* LE -> BE */
0103         /* Read chip ID from register 0xff */
0104         ret = i2c_smbus_read_word_data(client, 0xff);
0105         if (ret < 0) {
0106             dev_err(&dev->intf->dev,
0107                 "couldn't read from i2c device 0x%02x: error %i\n",
0108                 client->addr << 1, ret);
0109             continue;
0110         }
0111         /* Validate chip ID to be sure we have a Micron device */
0112         if (id != swab16(ret))
0113             continue;
0114         /* Check chip ID */
0115         switch (id) {
0116         case 0x1222:
0117             name = "MT9V012"; /* MI370 */ /* 640x480 */
0118             break;
0119         case 0x1229:
0120             name = "MT9V112"; /* 640x480 */
0121             break;
0122         case 0x1433:
0123             name = "MT9M011"; /* 1280x1024 */
0124             break;
0125         case 0x143a:    /* found in the ECS G200 */
0126             name = "MT9M111"; /* MI1310 */ /* 1280x1024 */
0127             dev->em28xx_sensor = EM28XX_MT9M111;
0128             break;
0129         case 0x148c:
0130             name = "MT9M112"; /* MI1320 */ /* 1280x1024 */
0131             break;
0132         case 0x1511:
0133             name = "MT9D011"; /* MI2010 */ /* 1600x1200 */
0134             break;
0135         case 0x8232:
0136         case 0x8243:    /* rev B */
0137             name = "MT9V011"; /* MI360 */ /* 640x480 */
0138             dev->em28xx_sensor = EM28XX_MT9V011;
0139             break;
0140         case 0x8431:
0141             name = "MT9M001"; /* 1280x1024 */
0142             dev->em28xx_sensor = EM28XX_MT9M001;
0143             break;
0144         default:
0145             dev_info(&dev->intf->dev,
0146                  "unknown Micron sensor detected: 0x%04x\n",
0147                  id);
0148             return 0;
0149         }
0150 
0151         if (dev->em28xx_sensor == EM28XX_NOSENSOR)
0152             dev_info(&dev->intf->dev,
0153                  "unsupported sensor detected: %s\n", name);
0154         else
0155             dev_info(&dev->intf->dev,
0156                  "sensor %s detected\n", name);
0157 
0158         return 0;
0159     }
0160 
0161     return -ENODEV;
0162 }
0163 
0164 /*
0165  * Probes Omnivision sensors with 8 bit address and register width
0166  */
0167 static int em28xx_probe_sensor_omnivision(struct em28xx *dev)
0168 {
0169     int ret, i;
0170     char *name;
0171     u8 reg;
0172     u16 id;
0173     struct i2c_client *client = &dev->i2c_client[dev->def_i2c_bus];
0174 
0175     dev->em28xx_sensor = EM28XX_NOSENSOR;
0176     /*
0177      * NOTE: these devices have the register auto incrementation disabled
0178      * by default, so we have to use single byte reads !
0179      */
0180     for (i = 0; omnivision_sensor_addrs[i] != I2C_CLIENT_END; i++) {
0181         client->addr = omnivision_sensor_addrs[i];
0182         /* Read manufacturer ID from registers 0x1c-0x1d (BE) */
0183         reg = 0x1c;
0184         ret = i2c_smbus_read_byte_data(client, reg);
0185         if (ret < 0) {
0186             if (ret != -ENXIO)
0187                 dev_err(&dev->intf->dev,
0188                     "couldn't read from i2c device 0x%02x: error %i\n",
0189                     client->addr << 1, ret);
0190             continue;
0191         }
0192         id = ret << 8;
0193         reg = 0x1d;
0194         ret = i2c_smbus_read_byte_data(client, reg);
0195         if (ret < 0) {
0196             dev_err(&dev->intf->dev,
0197                 "couldn't read from i2c device 0x%02x: error %i\n",
0198                 client->addr << 1, ret);
0199             continue;
0200         }
0201         id += ret;
0202         /* Check manufacturer ID */
0203         if (id != 0x7fa2)
0204             continue;
0205         /* Read product ID from registers 0x0a-0x0b (BE) */
0206         reg = 0x0a;
0207         ret = i2c_smbus_read_byte_data(client, reg);
0208         if (ret < 0) {
0209             dev_err(&dev->intf->dev,
0210                 "couldn't read from i2c device 0x%02x: error %i\n",
0211                 client->addr << 1, ret);
0212             continue;
0213         }
0214         id = ret << 8;
0215         reg = 0x0b;
0216         ret = i2c_smbus_read_byte_data(client, reg);
0217         if (ret < 0) {
0218             dev_err(&dev->intf->dev,
0219                 "couldn't read from i2c device 0x%02x: error %i\n",
0220                 client->addr << 1, ret);
0221             continue;
0222         }
0223         id += ret;
0224         /* Check product ID */
0225         switch (id) {
0226         case 0x2642:
0227             name = "OV2640";
0228             dev->em28xx_sensor = EM28XX_OV2640;
0229             break;
0230         case 0x7648:
0231             name = "OV7648";
0232             break;
0233         case 0x7660:
0234             name = "OV7660";
0235             break;
0236         case 0x7673:
0237             name = "OV7670";
0238             break;
0239         case 0x7720:
0240             name = "OV7720";
0241             break;
0242         case 0x7721:
0243             name = "OV7725";
0244             break;
0245         case 0x9648: /* Rev 2 */
0246         case 0x9649: /* Rev 3 */
0247             name = "OV9640";
0248             break;
0249         case 0x9650:
0250         case 0x9652: /* OV9653 */
0251             name = "OV9650";
0252             break;
0253         case 0x9656: /* Rev 4 */
0254         case 0x9657: /* Rev 5 */
0255             name = "OV9655";
0256             break;
0257         default:
0258             dev_info(&dev->intf->dev,
0259                  "unknown OmniVision sensor detected: 0x%04x\n",
0260                 id);
0261             return 0;
0262         }
0263 
0264         if (dev->em28xx_sensor == EM28XX_NOSENSOR)
0265             dev_info(&dev->intf->dev,
0266                  "unsupported sensor detected: %s\n", name);
0267         else
0268             dev_info(&dev->intf->dev,
0269                  "sensor %s detected\n", name);
0270 
0271         return 0;
0272     }
0273 
0274     return -ENODEV;
0275 }
0276 
0277 int em28xx_detect_sensor(struct em28xx *dev)
0278 {
0279     int ret;
0280 
0281     ret = em28xx_probe_sensor_micron(dev);
0282 
0283     if (dev->em28xx_sensor == EM28XX_NOSENSOR && ret < 0)
0284         ret = em28xx_probe_sensor_omnivision(dev);
0285 
0286     /*
0287      * NOTE: the Windows driver also probes i2c addresses
0288      *       0x22 (Samsung ?) and 0x66 (Kodak ?)
0289      */
0290 
0291     if (dev->em28xx_sensor == EM28XX_NOSENSOR && ret < 0) {
0292         dev_info(&dev->intf->dev,
0293              "No sensor detected\n");
0294         return -ENODEV;
0295     }
0296 
0297     return 0;
0298 }
0299 
0300 int em28xx_init_camera(struct em28xx *dev)
0301 {
0302     struct i2c_client *client = &dev->i2c_client[dev->def_i2c_bus];
0303     struct i2c_adapter *adap = &dev->i2c_adap[dev->def_i2c_bus];
0304     struct em28xx_v4l2 *v4l2 = dev->v4l2;
0305 
0306     switch (dev->em28xx_sensor) {
0307     case EM28XX_MT9V011:
0308     {
0309         struct mt9v011_platform_data pdata;
0310         struct i2c_board_info mt9v011_info = {
0311             .type = "mt9v011",
0312             .addr = client->addr,
0313             .platform_data = &pdata,
0314         };
0315 
0316         v4l2->sensor_xres = 640;
0317         v4l2->sensor_yres = 480;
0318 
0319         /*
0320          * FIXME: mt9v011 uses I2S speed as xtal clk - at least with
0321          * the Silvercrest cam I have here for testing - for higher
0322          * resolutions, a high clock cause horizontal artifacts, so we
0323          * need to use a lower xclk frequency.
0324          * Yet, it would be possible to adjust xclk depending on the
0325          * desired resolution, since this affects directly the
0326          * frame rate.
0327          */
0328         dev->board.xclk = EM28XX_XCLK_FREQUENCY_4_3MHZ;
0329         em28xx_write_reg(dev, EM28XX_R0F_XCLK, dev->board.xclk);
0330         v4l2->sensor_xtal = 4300000;
0331         pdata.xtal = v4l2->sensor_xtal;
0332         if (NULL ==
0333             v4l2_i2c_new_subdev_board(&v4l2->v4l2_dev, adap,
0334                           &mt9v011_info, NULL))
0335             return -ENODEV;
0336         v4l2->vinmode = EM28XX_VINMODE_RGB8_GRBG;
0337         v4l2->vinctl = 0x00;
0338 
0339         break;
0340     }
0341     case EM28XX_MT9M001:
0342         v4l2->sensor_xres = 1280;
0343         v4l2->sensor_yres = 1024;
0344 
0345         em28xx_initialize_mt9m001(dev);
0346 
0347         v4l2->vinmode = EM28XX_VINMODE_RGB8_BGGR;
0348         v4l2->vinctl = 0x00;
0349 
0350         break;
0351     case EM28XX_MT9M111:
0352         v4l2->sensor_xres = 640;
0353         v4l2->sensor_yres = 512;
0354 
0355         dev->board.xclk = EM28XX_XCLK_FREQUENCY_48MHZ;
0356         em28xx_write_reg(dev, EM28XX_R0F_XCLK, dev->board.xclk);
0357         em28xx_initialize_mt9m111(dev);
0358 
0359         v4l2->vinmode = EM28XX_VINMODE_YUV422_UYVY;
0360         v4l2->vinctl = 0x00;
0361 
0362         break;
0363     case EM28XX_OV2640:
0364     {
0365         struct v4l2_subdev *subdev;
0366         struct i2c_board_info ov2640_info = {
0367             .type = "ov2640",
0368             .flags = I2C_CLIENT_SCCB,
0369             .addr = client->addr,
0370         };
0371         struct v4l2_subdev_format format = {
0372             .which = V4L2_SUBDEV_FORMAT_ACTIVE,
0373         };
0374 
0375         /*
0376          * FIXME: sensor supports resolutions up to 1600x1200, but
0377          * resolution setting/switching needs to be modified to
0378          * - switch sensor output resolution (including further
0379          *   configuration changes)
0380          * - adjust bridge xclk
0381          * - disable 16 bit (12 bit) output formats on high resolutions
0382          */
0383         v4l2->sensor_xres = 640;
0384         v4l2->sensor_yres = 480;
0385 
0386         subdev =
0387              v4l2_i2c_new_subdev_board(&v4l2->v4l2_dev, adap,
0388                            &ov2640_info, NULL);
0389         if (!subdev)
0390             return -ENODEV;
0391 
0392         format.format.code = MEDIA_BUS_FMT_YUYV8_2X8;
0393         format.format.width = 640;
0394         format.format.height = 480;
0395         v4l2_subdev_call(subdev, pad, set_fmt, NULL, &format);
0396 
0397         /* NOTE: for UXGA=1600x1200 switch to 12MHz */
0398         dev->board.xclk = EM28XX_XCLK_FREQUENCY_24MHZ;
0399         em28xx_write_reg(dev, EM28XX_R0F_XCLK, dev->board.xclk);
0400         v4l2->vinmode = EM28XX_VINMODE_YUV422_YUYV;
0401         v4l2->vinctl = 0x00;
0402 
0403         break;
0404     }
0405     case EM28XX_NOSENSOR:
0406     default:
0407         return -EINVAL;
0408     }
0409 
0410     return 0;
0411 }
0412 EXPORT_SYMBOL_GPL(em28xx_init_camera);