root/drivers/media/i2c/saa7185.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. to_saa7185
  2. saa7185_read
  3. saa7185_write
  4. saa7185_write_block
  5. saa7185_init
  6. saa7185_s_std_output
  7. saa7185_s_routing
  8. saa7185_probe
  9. saa7185_remove

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * saa7185 - Philips SAA7185B video encoder driver version 0.0.3
   4  *
   5  * Copyright (C) 1998 Dave Perks <dperks@ibm.net>
   6  *
   7  * Slight changes for video timing and attachment output by
   8  * Wolfgang Scherr <scherr@net4you.net>
   9  *
  10  * Changes by Ronald Bultje <rbultje@ronald.bitfreak.net>
  11  *    - moved over to linux>=2.4.x i2c protocol (1/1/2003)
  12  */
  13 
  14 #include <linux/module.h>
  15 #include <linux/types.h>
  16 #include <linux/slab.h>
  17 #include <linux/ioctl.h>
  18 #include <linux/uaccess.h>
  19 #include <linux/i2c.h>
  20 #include <linux/videodev2.h>
  21 #include <media/v4l2-device.h>
  22 
  23 MODULE_DESCRIPTION("Philips SAA7185 video encoder driver");
  24 MODULE_AUTHOR("Dave Perks");
  25 MODULE_LICENSE("GPL");
  26 
  27 static int debug;
  28 module_param(debug, int, 0);
  29 MODULE_PARM_DESC(debug, "Debug level (0-1)");
  30 
  31 
  32 /* ----------------------------------------------------------------------- */
  33 
  34 struct saa7185 {
  35         struct v4l2_subdev sd;
  36         unsigned char reg[128];
  37 
  38         v4l2_std_id norm;
  39 };
  40 
  41 static inline struct saa7185 *to_saa7185(struct v4l2_subdev *sd)
  42 {
  43         return container_of(sd, struct saa7185, sd);
  44 }
  45 
  46 /* ----------------------------------------------------------------------- */
  47 
  48 static inline int saa7185_read(struct v4l2_subdev *sd)
  49 {
  50         struct i2c_client *client = v4l2_get_subdevdata(sd);
  51 
  52         return i2c_smbus_read_byte(client);
  53 }
  54 
  55 static int saa7185_write(struct v4l2_subdev *sd, u8 reg, u8 value)
  56 {
  57         struct i2c_client *client = v4l2_get_subdevdata(sd);
  58         struct saa7185 *encoder = to_saa7185(sd);
  59 
  60         v4l2_dbg(1, debug, sd, "%02x set to %02x\n", reg, value);
  61         encoder->reg[reg] = value;
  62         return i2c_smbus_write_byte_data(client, reg, value);
  63 }
  64 
  65 static int saa7185_write_block(struct v4l2_subdev *sd,
  66                 const u8 *data, unsigned int len)
  67 {
  68         struct i2c_client *client = v4l2_get_subdevdata(sd);
  69         struct saa7185 *encoder = to_saa7185(sd);
  70         int ret = -1;
  71         u8 reg;
  72 
  73         /* the adv7175 has an autoincrement function, use it if
  74          * the adapter understands raw I2C */
  75         if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
  76                 /* do raw I2C, not smbus compatible */
  77                 u8 block_data[32];
  78                 int block_len;
  79 
  80                 while (len >= 2) {
  81                         block_len = 0;
  82                         block_data[block_len++] = reg = data[0];
  83                         do {
  84                                 block_data[block_len++] =
  85                                     encoder->reg[reg++] = data[1];
  86                                 len -= 2;
  87                                 data += 2;
  88                         } while (len >= 2 && data[0] == reg && block_len < 32);
  89                         ret = i2c_master_send(client, block_data, block_len);
  90                         if (ret < 0)
  91                                 break;
  92                 }
  93         } else {
  94                 /* do some slow I2C emulation kind of thing */
  95                 while (len >= 2) {
  96                         reg = *data++;
  97                         ret = saa7185_write(sd, reg, *data++);
  98                         if (ret < 0)
  99                                 break;
 100                         len -= 2;
 101                 }
 102         }
 103 
 104         return ret;
 105 }
 106 
 107 /* ----------------------------------------------------------------------- */
 108 
 109 static const unsigned char init_common[] = {
 110         0x3a, 0x0f,             /* CBENB=0, V656=0, VY2C=1,
 111                                  * YUV2C=1, MY2C=1, MUV2C=1 */
 112 
 113         0x42, 0x6b,             /* OVLY0=107 */
 114         0x43, 0x00,             /* OVLU0=0     white */
 115         0x44, 0x00,             /* OVLV0=0   */
 116         0x45, 0x22,             /* OVLY1=34  */
 117         0x46, 0xac,             /* OVLU1=172   yellow */
 118         0x47, 0x0e,             /* OVLV1=14  */
 119         0x48, 0x03,             /* OVLY2=3   */
 120         0x49, 0x1d,             /* OVLU2=29    cyan */
 121         0x4a, 0xac,             /* OVLV2=172 */
 122         0x4b, 0xf0,             /* OVLY3=240 */
 123         0x4c, 0xc8,             /* OVLU3=200   green */
 124         0x4d, 0xb9,             /* OVLV3=185 */
 125         0x4e, 0xd4,             /* OVLY4=212 */
 126         0x4f, 0x38,             /* OVLU4=56    magenta */
 127         0x50, 0x47,             /* OVLV4=71  */
 128         0x51, 0xc1,             /* OVLY5=193 */
 129         0x52, 0xe3,             /* OVLU5=227   red */
 130         0x53, 0x54,             /* OVLV5=84  */
 131         0x54, 0xa3,             /* OVLY6=163 */
 132         0x55, 0x54,             /* OVLU6=84    blue */
 133         0x56, 0xf2,             /* OVLV6=242 */
 134         0x57, 0x90,             /* OVLY7=144 */
 135         0x58, 0x00,             /* OVLU7=0     black */
 136         0x59, 0x00,             /* OVLV7=0   */
 137 
 138         0x5a, 0x00,             /* CHPS=0    */
 139         0x5b, 0x76,             /* GAINU=118 */
 140         0x5c, 0xa5,             /* GAINV=165 */
 141         0x5d, 0x3c,             /* BLCKL=60  */
 142         0x5e, 0x3a,             /* BLNNL=58  */
 143         0x5f, 0x3a,             /* CCRS=0, BLNVB=58 */
 144         0x60, 0x00,             /* NULL      */
 145 
 146         /* 0x61 - 0x66 set according to norm */
 147 
 148         0x67, 0x00,             /* 0 : caption 1st byte odd  field */
 149         0x68, 0x00,             /* 0 : caption 2nd byte odd  field */
 150         0x69, 0x00,             /* 0 : caption 1st byte even field */
 151         0x6a, 0x00,             /* 0 : caption 2nd byte even field */
 152 
 153         0x6b, 0x91,             /* MODIN=2, PCREF=0, SCCLN=17 */
 154         0x6c, 0x20,             /* SRCV1=0, TRCV2=1, ORCV1=0, PRCV1=0,
 155                                  * CBLF=0, ORCV2=0, PRCV2=0 */
 156         0x6d, 0x00,             /* SRCM1=0, CCEN=0 */
 157 
 158         0x6e, 0x0e,             /* HTRIG=0x005, approx. centered, at
 159                                  * least for PAL */
 160         0x6f, 0x00,             /* HTRIG upper bits */
 161         0x70, 0x20,             /* PHRES=0, SBLN=1, VTRIG=0 */
 162 
 163         /* The following should not be needed */
 164 
 165         0x71, 0x15,             /* BMRQ=0x115 */
 166         0x72, 0x90,             /* EMRQ=0x690 */
 167         0x73, 0x61,             /* EMRQ=0x690, BMRQ=0x115 */
 168         0x74, 0x00,             /* NULL       */
 169         0x75, 0x00,             /* NULL       */
 170         0x76, 0x00,             /* NULL       */
 171         0x77, 0x15,             /* BRCV=0x115 */
 172         0x78, 0x90,             /* ERCV=0x690 */
 173         0x79, 0x61,             /* ERCV=0x690, BRCV=0x115 */
 174 
 175         /* Field length controls */
 176 
 177         0x7a, 0x70,             /* FLC=0 */
 178 
 179         /* The following should not be needed if SBLN = 1 */
 180 
 181         0x7b, 0x16,             /* FAL=22 */
 182         0x7c, 0x35,             /* LAL=244 */
 183         0x7d, 0x20,             /* LAL=244, FAL=22 */
 184 };
 185 
 186 static const unsigned char init_pal[] = {
 187         0x61, 0x1e,             /* FISE=0, PAL=1, SCBW=1, RTCE=1,
 188                                  * YGS=1, INPI=0, DOWN=0 */
 189         0x62, 0xc8,             /* DECTYP=1, BSTA=72 */
 190         0x63, 0xcb,             /* FSC0 */
 191         0x64, 0x8a,             /* FSC1 */
 192         0x65, 0x09,             /* FSC2 */
 193         0x66, 0x2a,             /* FSC3 */
 194 };
 195 
 196 static const unsigned char init_ntsc[] = {
 197         0x61, 0x1d,             /* FISE=1, PAL=0, SCBW=1, RTCE=1,
 198                                  * YGS=1, INPI=0, DOWN=0 */
 199         0x62, 0xe6,             /* DECTYP=1, BSTA=102 */
 200         0x63, 0x1f,             /* FSC0 */
 201         0x64, 0x7c,             /* FSC1 */
 202         0x65, 0xf0,             /* FSC2 */
 203         0x66, 0x21,             /* FSC3 */
 204 };
 205 
 206 
 207 static int saa7185_init(struct v4l2_subdev *sd, u32 val)
 208 {
 209         struct saa7185 *encoder = to_saa7185(sd);
 210 
 211         saa7185_write_block(sd, init_common, sizeof(init_common));
 212         if (encoder->norm & V4L2_STD_NTSC)
 213                 saa7185_write_block(sd, init_ntsc, sizeof(init_ntsc));
 214         else
 215                 saa7185_write_block(sd, init_pal, sizeof(init_pal));
 216         return 0;
 217 }
 218 
 219 static int saa7185_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std)
 220 {
 221         struct saa7185 *encoder = to_saa7185(sd);
 222 
 223         if (std & V4L2_STD_NTSC)
 224                 saa7185_write_block(sd, init_ntsc, sizeof(init_ntsc));
 225         else if (std & V4L2_STD_PAL)
 226                 saa7185_write_block(sd, init_pal, sizeof(init_pal));
 227         else
 228                 return -EINVAL;
 229         encoder->norm = std;
 230         return 0;
 231 }
 232 
 233 static int saa7185_s_routing(struct v4l2_subdev *sd,
 234                              u32 input, u32 output, u32 config)
 235 {
 236         struct saa7185 *encoder = to_saa7185(sd);
 237 
 238         /* RJ: input = 0: input is from SA7111
 239          input = 1: input is from ZR36060 */
 240 
 241         switch (input) {
 242         case 0:
 243                 /* turn off colorbar */
 244                 saa7185_write(sd, 0x3a, 0x0f);
 245                 /* Switch RTCE to 1 */
 246                 saa7185_write(sd, 0x61, (encoder->reg[0x61] & 0xf7) | 0x08);
 247                 saa7185_write(sd, 0x6e, 0x01);
 248                 break;
 249 
 250         case 1:
 251                 /* turn off colorbar */
 252                 saa7185_write(sd, 0x3a, 0x0f);
 253                 /* Switch RTCE to 0 */
 254                 saa7185_write(sd, 0x61, (encoder->reg[0x61] & 0xf7) | 0x00);
 255                 /* SW: a slight sync problem... */
 256                 saa7185_write(sd, 0x6e, 0x00);
 257                 break;
 258 
 259         case 2:
 260                 /* turn on colorbar */
 261                 saa7185_write(sd, 0x3a, 0x8f);
 262                 /* Switch RTCE to 0 */
 263                 saa7185_write(sd, 0x61, (encoder->reg[0x61] & 0xf7) | 0x08);
 264                 /* SW: a slight sync problem... */
 265                 saa7185_write(sd, 0x6e, 0x01);
 266                 break;
 267 
 268         default:
 269                 return -EINVAL;
 270         }
 271         return 0;
 272 }
 273 
 274 /* ----------------------------------------------------------------------- */
 275 
 276 static const struct v4l2_subdev_core_ops saa7185_core_ops = {
 277         .init = saa7185_init,
 278 };
 279 
 280 static const struct v4l2_subdev_video_ops saa7185_video_ops = {
 281         .s_std_output = saa7185_s_std_output,
 282         .s_routing = saa7185_s_routing,
 283 };
 284 
 285 static const struct v4l2_subdev_ops saa7185_ops = {
 286         .core = &saa7185_core_ops,
 287         .video = &saa7185_video_ops,
 288 };
 289 
 290 
 291 /* ----------------------------------------------------------------------- */
 292 
 293 static int saa7185_probe(struct i2c_client *client,
 294                         const struct i2c_device_id *id)
 295 {
 296         int i;
 297         struct saa7185 *encoder;
 298         struct v4l2_subdev *sd;
 299 
 300         /* Check if the adapter supports the needed features */
 301         if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 302                 return -ENODEV;
 303 
 304         v4l_info(client, "chip found @ 0x%x (%s)\n",
 305                         client->addr << 1, client->adapter->name);
 306 
 307         encoder = devm_kzalloc(&client->dev, sizeof(*encoder), GFP_KERNEL);
 308         if (encoder == NULL)
 309                 return -ENOMEM;
 310         encoder->norm = V4L2_STD_NTSC;
 311         sd = &encoder->sd;
 312         v4l2_i2c_subdev_init(sd, client, &saa7185_ops);
 313 
 314         i = saa7185_write_block(sd, init_common, sizeof(init_common));
 315         if (i >= 0)
 316                 i = saa7185_write_block(sd, init_ntsc, sizeof(init_ntsc));
 317         if (i < 0)
 318                 v4l2_dbg(1, debug, sd, "init error %d\n", i);
 319         else
 320                 v4l2_dbg(1, debug, sd, "revision 0x%x\n",
 321                                 saa7185_read(sd) >> 5);
 322         return 0;
 323 }
 324 
 325 static int saa7185_remove(struct i2c_client *client)
 326 {
 327         struct v4l2_subdev *sd = i2c_get_clientdata(client);
 328         struct saa7185 *encoder = to_saa7185(sd);
 329 
 330         v4l2_device_unregister_subdev(sd);
 331         /* SW: output off is active */
 332         saa7185_write(sd, 0x61, (encoder->reg[0x61]) | 0x40);
 333         return 0;
 334 }
 335 
 336 /* ----------------------------------------------------------------------- */
 337 
 338 static const struct i2c_device_id saa7185_id[] = {
 339         { "saa7185", 0 },
 340         { }
 341 };
 342 MODULE_DEVICE_TABLE(i2c, saa7185_id);
 343 
 344 static struct i2c_driver saa7185_driver = {
 345         .driver = {
 346                 .name   = "saa7185",
 347         },
 348         .probe          = saa7185_probe,
 349         .remove         = saa7185_remove,
 350         .id_table       = saa7185_id,
 351 };
 352 
 353 module_i2c_driver(saa7185_driver);

/* [<][>][^][v][top][bottom][index][help] */