Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *  adv7175 - adv7175a video encoder driver version 0.0.3
0004  *
0005  * Copyright (C) 1998 Dave Perks <dperks@ibm.net>
0006  * Copyright (C) 1999 Wolfgang Scherr <scherr@net4you.net>
0007  * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
0008  *    - some corrections for Pinnacle Systems Inc. DC10plus card.
0009  *
0010  * Changes by Ronald Bultje <rbultje@ronald.bitfreak.net>
0011  *    - moved over to linux>=2.4.x i2c protocol (9/9/2002)
0012  */
0013 
0014 #include <linux/module.h>
0015 #include <linux/types.h>
0016 #include <linux/slab.h>
0017 #include <linux/ioctl.h>
0018 #include <linux/uaccess.h>
0019 #include <linux/i2c.h>
0020 #include <linux/videodev2.h>
0021 #include <media/v4l2-device.h>
0022 
0023 MODULE_DESCRIPTION("Analog Devices ADV7175 video encoder driver");
0024 MODULE_AUTHOR("Dave Perks");
0025 MODULE_LICENSE("GPL");
0026 
0027 #define   I2C_ADV7175        0xd4
0028 #define   I2C_ADV7176        0x54
0029 
0030 
0031 static int debug;
0032 module_param(debug, int, 0);
0033 MODULE_PARM_DESC(debug, "Debug level (0-1)");
0034 
0035 /* ----------------------------------------------------------------------- */
0036 
0037 struct adv7175 {
0038     struct v4l2_subdev sd;
0039     v4l2_std_id norm;
0040     int input;
0041 };
0042 
0043 static inline struct adv7175 *to_adv7175(struct v4l2_subdev *sd)
0044 {
0045     return container_of(sd, struct adv7175, sd);
0046 }
0047 
0048 static char *inputs[] = { "pass_through", "play_back", "color_bar" };
0049 
0050 static u32 adv7175_codes[] = {
0051     MEDIA_BUS_FMT_UYVY8_2X8,
0052     MEDIA_BUS_FMT_UYVY8_1X16,
0053 };
0054 
0055 /* ----------------------------------------------------------------------- */
0056 
0057 static inline int adv7175_write(struct v4l2_subdev *sd, u8 reg, u8 value)
0058 {
0059     struct i2c_client *client = v4l2_get_subdevdata(sd);
0060 
0061     return i2c_smbus_write_byte_data(client, reg, value);
0062 }
0063 
0064 static inline int adv7175_read(struct v4l2_subdev *sd, u8 reg)
0065 {
0066     struct i2c_client *client = v4l2_get_subdevdata(sd);
0067 
0068     return i2c_smbus_read_byte_data(client, reg);
0069 }
0070 
0071 static int adv7175_write_block(struct v4l2_subdev *sd,
0072              const u8 *data, unsigned int len)
0073 {
0074     struct i2c_client *client = v4l2_get_subdevdata(sd);
0075     int ret = -1;
0076     u8 reg;
0077 
0078     /* the adv7175 has an autoincrement function, use it if
0079      * the adapter understands raw I2C */
0080     if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
0081         /* do raw I2C, not smbus compatible */
0082         u8 block_data[32];
0083         int block_len;
0084 
0085         while (len >= 2) {
0086             block_len = 0;
0087             block_data[block_len++] = reg = data[0];
0088             do {
0089                 block_data[block_len++] = data[1];
0090                 reg++;
0091                 len -= 2;
0092                 data += 2;
0093             } while (len >= 2 && data[0] == reg && block_len < 32);
0094             ret = i2c_master_send(client, block_data, block_len);
0095             if (ret < 0)
0096                 break;
0097         }
0098     } else {
0099         /* do some slow I2C emulation kind of thing */
0100         while (len >= 2) {
0101             reg = *data++;
0102             ret = adv7175_write(sd, reg, *data++);
0103             if (ret < 0)
0104                 break;
0105             len -= 2;
0106         }
0107     }
0108 
0109     return ret;
0110 }
0111 
0112 static void set_subcarrier_freq(struct v4l2_subdev *sd, int pass_through)
0113 {
0114     /* for some reason pass_through NTSC needs
0115      * a different sub-carrier freq to remain stable. */
0116     if (pass_through)
0117         adv7175_write(sd, 0x02, 0x00);
0118     else
0119         adv7175_write(sd, 0x02, 0x55);
0120 
0121     adv7175_write(sd, 0x03, 0x55);
0122     adv7175_write(sd, 0x04, 0x55);
0123     adv7175_write(sd, 0x05, 0x25);
0124 }
0125 
0126 /* ----------------------------------------------------------------------- */
0127 /* Output filter:  S-Video  Composite */
0128 
0129 #define MR050       0x11    /* 0x09 */
0130 #define MR060       0x14    /* 0x0c */
0131 
0132 /* ----------------------------------------------------------------------- */
0133 
0134 #define TR0MODE     0x46
0135 #define TR0RST      0x80
0136 
0137 #define TR1CAPT     0x80
0138 #define TR1PLAY     0x00
0139 
0140 static const unsigned char init_common[] = {
0141 
0142     0x00, MR050,        /* MR0, PAL enabled */
0143     0x01, 0x00,     /* MR1 */
0144     0x02, 0x0c,     /* subc. freq. */
0145     0x03, 0x8c,     /* subc. freq. */
0146     0x04, 0x79,     /* subc. freq. */
0147     0x05, 0x26,     /* subc. freq. */
0148     0x06, 0x40,     /* subc. phase */
0149 
0150     0x07, TR0MODE,      /* TR0, 16bit */
0151     0x08, 0x21,     /*  */
0152     0x09, 0x00,     /*  */
0153     0x0a, 0x00,     /*  */
0154     0x0b, 0x00,     /*  */
0155     0x0c, TR1CAPT,      /* TR1 */
0156     0x0d, 0x4f,     /* MR2 */
0157     0x0e, 0x00,     /*  */
0158     0x0f, 0x00,     /*  */
0159     0x10, 0x00,     /*  */
0160     0x11, 0x00,     /*  */
0161 };
0162 
0163 static const unsigned char init_pal[] = {
0164     0x00, MR050,        /* MR0, PAL enabled */
0165     0x01, 0x00,     /* MR1 */
0166     0x02, 0x0c,     /* subc. freq. */
0167     0x03, 0x8c,     /* subc. freq. */
0168     0x04, 0x79,     /* subc. freq. */
0169     0x05, 0x26,     /* subc. freq. */
0170     0x06, 0x40,     /* subc. phase */
0171 };
0172 
0173 static const unsigned char init_ntsc[] = {
0174     0x00, MR060,        /* MR0, NTSC enabled */
0175     0x01, 0x00,     /* MR1 */
0176     0x02, 0x55,     /* subc. freq. */
0177     0x03, 0x55,     /* subc. freq. */
0178     0x04, 0x55,     /* subc. freq. */
0179     0x05, 0x25,     /* subc. freq. */
0180     0x06, 0x1a,     /* subc. phase */
0181 };
0182 
0183 static int adv7175_init(struct v4l2_subdev *sd, u32 val)
0184 {
0185     /* This is just for testing!!! */
0186     adv7175_write_block(sd, init_common, sizeof(init_common));
0187     adv7175_write(sd, 0x07, TR0MODE | TR0RST);
0188     adv7175_write(sd, 0x07, TR0MODE);
0189     return 0;
0190 }
0191 
0192 static int adv7175_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std)
0193 {
0194     struct adv7175 *encoder = to_adv7175(sd);
0195 
0196     if (std & V4L2_STD_NTSC) {
0197         adv7175_write_block(sd, init_ntsc, sizeof(init_ntsc));
0198         if (encoder->input == 0)
0199             adv7175_write(sd, 0x0d, 0x4f);  /* Enable genlock */
0200         adv7175_write(sd, 0x07, TR0MODE | TR0RST);
0201         adv7175_write(sd, 0x07, TR0MODE);
0202     } else if (std & V4L2_STD_PAL) {
0203         adv7175_write_block(sd, init_pal, sizeof(init_pal));
0204         if (encoder->input == 0)
0205             adv7175_write(sd, 0x0d, 0x4f);  /* Enable genlock */
0206         adv7175_write(sd, 0x07, TR0MODE | TR0RST);
0207         adv7175_write(sd, 0x07, TR0MODE);
0208     } else if (std & V4L2_STD_SECAM) {
0209         /* This is an attempt to convert
0210          * SECAM->PAL (typically it does not work
0211          * due to genlock: when decoder is in SECAM
0212          * and encoder in in PAL the subcarrier can
0213          * not be synchronized with horizontal
0214          * quency) */
0215         adv7175_write_block(sd, init_pal, sizeof(init_pal));
0216         if (encoder->input == 0)
0217             adv7175_write(sd, 0x0d, 0x49);  /* Disable genlock */
0218         adv7175_write(sd, 0x07, TR0MODE | TR0RST);
0219         adv7175_write(sd, 0x07, TR0MODE);
0220     } else {
0221         v4l2_dbg(1, debug, sd, "illegal norm: %llx\n",
0222                 (unsigned long long)std);
0223         return -EINVAL;
0224     }
0225     v4l2_dbg(1, debug, sd, "switched to %llx\n", (unsigned long long)std);
0226     encoder->norm = std;
0227     return 0;
0228 }
0229 
0230 static int adv7175_s_routing(struct v4l2_subdev *sd,
0231                  u32 input, u32 output, u32 config)
0232 {
0233     struct adv7175 *encoder = to_adv7175(sd);
0234 
0235     /* RJ: input = 0: input is from decoder
0236        input = 1: input is from ZR36060
0237        input = 2: color bar */
0238 
0239     switch (input) {
0240     case 0:
0241         adv7175_write(sd, 0x01, 0x00);
0242 
0243         if (encoder->norm & V4L2_STD_NTSC)
0244             set_subcarrier_freq(sd, 1);
0245 
0246         adv7175_write(sd, 0x0c, TR1CAPT);   /* TR1 */
0247         if (encoder->norm & V4L2_STD_SECAM)
0248             adv7175_write(sd, 0x0d, 0x49);  /* Disable genlock */
0249         else
0250             adv7175_write(sd, 0x0d, 0x4f);  /* Enable genlock */
0251         adv7175_write(sd, 0x07, TR0MODE | TR0RST);
0252         adv7175_write(sd, 0x07, TR0MODE);
0253         /*udelay(10);*/
0254         break;
0255 
0256     case 1:
0257         adv7175_write(sd, 0x01, 0x00);
0258 
0259         if (encoder->norm & V4L2_STD_NTSC)
0260             set_subcarrier_freq(sd, 0);
0261 
0262         adv7175_write(sd, 0x0c, TR1PLAY);   /* TR1 */
0263         adv7175_write(sd, 0x0d, 0x49);
0264         adv7175_write(sd, 0x07, TR0MODE | TR0RST);
0265         adv7175_write(sd, 0x07, TR0MODE);
0266         /* udelay(10); */
0267         break;
0268 
0269     case 2:
0270         adv7175_write(sd, 0x01, 0x80);
0271 
0272         if (encoder->norm & V4L2_STD_NTSC)
0273             set_subcarrier_freq(sd, 0);
0274 
0275         adv7175_write(sd, 0x0d, 0x49);
0276         adv7175_write(sd, 0x07, TR0MODE | TR0RST);
0277         adv7175_write(sd, 0x07, TR0MODE);
0278         /* udelay(10); */
0279         break;
0280 
0281     default:
0282         v4l2_dbg(1, debug, sd, "illegal input: %d\n", input);
0283         return -EINVAL;
0284     }
0285     v4l2_dbg(1, debug, sd, "switched to %s\n", inputs[input]);
0286     encoder->input = input;
0287     return 0;
0288 }
0289 
0290 static int adv7175_enum_mbus_code(struct v4l2_subdev *sd,
0291         struct v4l2_subdev_state *sd_state,
0292         struct v4l2_subdev_mbus_code_enum *code)
0293 {
0294     if (code->pad || code->index >= ARRAY_SIZE(adv7175_codes))
0295         return -EINVAL;
0296 
0297     code->code = adv7175_codes[code->index];
0298     return 0;
0299 }
0300 
0301 static int adv7175_get_fmt(struct v4l2_subdev *sd,
0302         struct v4l2_subdev_state *sd_state,
0303         struct v4l2_subdev_format *format)
0304 {
0305     struct v4l2_mbus_framefmt *mf = &format->format;
0306     u8 val = adv7175_read(sd, 0x7);
0307 
0308     if (format->pad)
0309         return -EINVAL;
0310 
0311     if ((val & 0x40) == (1 << 6))
0312         mf->code = MEDIA_BUS_FMT_UYVY8_1X16;
0313     else
0314         mf->code = MEDIA_BUS_FMT_UYVY8_2X8;
0315 
0316     mf->colorspace  = V4L2_COLORSPACE_SMPTE170M;
0317     mf->width       = 0;
0318     mf->height      = 0;
0319     mf->field       = V4L2_FIELD_ANY;
0320 
0321     return 0;
0322 }
0323 
0324 static int adv7175_set_fmt(struct v4l2_subdev *sd,
0325         struct v4l2_subdev_state *sd_state,
0326         struct v4l2_subdev_format *format)
0327 {
0328     struct v4l2_mbus_framefmt *mf = &format->format;
0329     u8 val = adv7175_read(sd, 0x7);
0330     int ret = 0;
0331 
0332     if (format->pad)
0333         return -EINVAL;
0334 
0335     switch (mf->code) {
0336     case MEDIA_BUS_FMT_UYVY8_2X8:
0337         val &= ~0x40;
0338         break;
0339 
0340     case MEDIA_BUS_FMT_UYVY8_1X16:
0341         val |= 0x40;
0342         break;
0343 
0344     default:
0345         v4l2_dbg(1, debug, sd,
0346             "illegal v4l2_mbus_framefmt code: %d\n", mf->code);
0347         return -EINVAL;
0348     }
0349 
0350     if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
0351         ret = adv7175_write(sd, 0x7, val);
0352 
0353     return ret;
0354 }
0355 
0356 static int adv7175_s_power(struct v4l2_subdev *sd, int on)
0357 {
0358     if (on)
0359         adv7175_write(sd, 0x01, 0x00);
0360     else
0361         adv7175_write(sd, 0x01, 0x78);
0362 
0363     return 0;
0364 }
0365 
0366 /* ----------------------------------------------------------------------- */
0367 
0368 static const struct v4l2_subdev_core_ops adv7175_core_ops = {
0369     .init = adv7175_init,
0370     .s_power = adv7175_s_power,
0371 };
0372 
0373 static const struct v4l2_subdev_video_ops adv7175_video_ops = {
0374     .s_std_output = adv7175_s_std_output,
0375     .s_routing = adv7175_s_routing,
0376 };
0377 
0378 static const struct v4l2_subdev_pad_ops adv7175_pad_ops = {
0379     .enum_mbus_code = adv7175_enum_mbus_code,
0380     .get_fmt = adv7175_get_fmt,
0381     .set_fmt = adv7175_set_fmt,
0382 };
0383 
0384 static const struct v4l2_subdev_ops adv7175_ops = {
0385     .core = &adv7175_core_ops,
0386     .video = &adv7175_video_ops,
0387     .pad = &adv7175_pad_ops,
0388 };
0389 
0390 /* ----------------------------------------------------------------------- */
0391 
0392 static int adv7175_probe(struct i2c_client *client,
0393             const struct i2c_device_id *id)
0394 {
0395     int i;
0396     struct adv7175 *encoder;
0397     struct v4l2_subdev *sd;
0398 
0399     /* Check if the adapter supports the needed features */
0400     if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
0401         return -ENODEV;
0402 
0403     v4l_info(client, "chip found @ 0x%x (%s)\n",
0404             client->addr << 1, client->adapter->name);
0405 
0406     encoder = devm_kzalloc(&client->dev, sizeof(*encoder), GFP_KERNEL);
0407     if (encoder == NULL)
0408         return -ENOMEM;
0409     sd = &encoder->sd;
0410     v4l2_i2c_subdev_init(sd, client, &adv7175_ops);
0411     encoder->norm = V4L2_STD_NTSC;
0412     encoder->input = 0;
0413 
0414     i = adv7175_write_block(sd, init_common, sizeof(init_common));
0415     if (i >= 0) {
0416         i = adv7175_write(sd, 0x07, TR0MODE | TR0RST);
0417         i = adv7175_write(sd, 0x07, TR0MODE);
0418         i = adv7175_read(sd, 0x12);
0419         v4l2_dbg(1, debug, sd, "revision %d\n", i & 1);
0420     }
0421     if (i < 0)
0422         v4l2_dbg(1, debug, sd, "init error 0x%x\n", i);
0423     return 0;
0424 }
0425 
0426 static int adv7175_remove(struct i2c_client *client)
0427 {
0428     struct v4l2_subdev *sd = i2c_get_clientdata(client);
0429 
0430     v4l2_device_unregister_subdev(sd);
0431     return 0;
0432 }
0433 
0434 /* ----------------------------------------------------------------------- */
0435 
0436 static const struct i2c_device_id adv7175_id[] = {
0437     { "adv7175", 0 },
0438     { "adv7176", 0 },
0439     { }
0440 };
0441 MODULE_DEVICE_TABLE(i2c, adv7175_id);
0442 
0443 static struct i2c_driver adv7175_driver = {
0444     .driver = {
0445         .name   = "adv7175",
0446     },
0447     .probe      = adv7175_probe,
0448     .remove     = adv7175_remove,
0449     .id_table   = adv7175_id,
0450 };
0451 
0452 module_i2c_driver(adv7175_driver);