This source file includes following definitions.
- to_saa7110
- to_sd
- saa7110_write
- saa7110_write_block
- saa7110_read
- saa7110_selmux
- determine_norm
- saa7110_g_input_status
- saa7110_querystd
- saa7110_s_std
- saa7110_s_routing
- saa7110_s_stream
- saa7110_s_ctrl
- saa7110_probe
- saa7110_remove
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 
  15 #include <linux/module.h>
  16 #include <linux/init.h>
  17 #include <linux/types.h>
  18 #include <linux/delay.h>
  19 #include <linux/slab.h>
  20 #include <linux/wait.h>
  21 #include <linux/uaccess.h>
  22 #include <linux/i2c.h>
  23 #include <linux/videodev2.h>
  24 #include <media/v4l2-device.h>
  25 #include <media/v4l2-ctrls.h>
  26 
  27 MODULE_DESCRIPTION("Philips SAA7110 video decoder driver");
  28 MODULE_AUTHOR("Pauline Middelink");
  29 MODULE_LICENSE("GPL");
  30 
  31 
  32 static int debug;
  33 module_param(debug, int, 0);
  34 MODULE_PARM_DESC(debug, "Debug level (0-1)");
  35 
  36 #define SAA7110_MAX_INPUT       9       
  37 #define SAA7110_MAX_OUTPUT      1       
  38 
  39 #define SAA7110_NR_REG          0x35
  40 
  41 struct saa7110 {
  42         struct v4l2_subdev sd;
  43         struct v4l2_ctrl_handler hdl;
  44         u8 reg[SAA7110_NR_REG];
  45 
  46         v4l2_std_id norm;
  47         int input;
  48         int enable;
  49 
  50         wait_queue_head_t wq;
  51 };
  52 
  53 static inline struct saa7110 *to_saa7110(struct v4l2_subdev *sd)
  54 {
  55         return container_of(sd, struct saa7110, sd);
  56 }
  57 
  58 static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
  59 {
  60         return &container_of(ctrl->handler, struct saa7110, hdl)->sd;
  61 }
  62 
  63 
  64 
  65 
  66 
  67 static int saa7110_write(struct v4l2_subdev *sd, u8 reg, u8 value)
  68 {
  69         struct i2c_client *client = v4l2_get_subdevdata(sd);
  70         struct saa7110 *decoder = to_saa7110(sd);
  71 
  72         decoder->reg[reg] = value;
  73         return i2c_smbus_write_byte_data(client, reg, value);
  74 }
  75 
  76 static int saa7110_write_block(struct v4l2_subdev *sd, const u8 *data, unsigned int len)
  77 {
  78         struct i2c_client *client = v4l2_get_subdevdata(sd);
  79         struct saa7110 *decoder = to_saa7110(sd);
  80         int ret = -1;
  81         u8 reg = *data;         
  82 
  83         
  84         if (reg + (len - 1) > SAA7110_NR_REG)
  85                 return ret;
  86 
  87         
  88 
  89         if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
  90                 ret = i2c_master_send(client, data, len);
  91 
  92                 
  93                 memcpy(decoder->reg + reg, data + 1, len - 1);
  94         } else {
  95                 for (++data, --len; len; len--) {
  96                         ret = saa7110_write(sd, reg++, *data++);
  97                         if (ret < 0)
  98                                 break;
  99                 }
 100         }
 101 
 102         return ret;
 103 }
 104 
 105 static inline int saa7110_read(struct v4l2_subdev *sd)
 106 {
 107         struct i2c_client *client = v4l2_get_subdevdata(sd);
 108 
 109         return i2c_smbus_read_byte(client);
 110 }
 111 
 112 
 113 
 114 
 115 
 116 #define FRESP_06H_COMPST 0x03   
 117 #define FRESP_06H_SVIDEO 0x83   
 118 
 119 
 120 static int saa7110_selmux(struct v4l2_subdev *sd, int chan)
 121 {
 122         static const unsigned char modes[9][8] = {
 123                 
 124                 {FRESP_06H_COMPST, 0xD9, 0x17, 0x40, 0x03,
 125                               0x44, 0x75, 0x16},
 126                 
 127                 {FRESP_06H_COMPST, 0xD8, 0x17, 0x40, 0x03,
 128                               0x44, 0x75, 0x16},
 129                 
 130                 {FRESP_06H_COMPST, 0xBA, 0x07, 0x91, 0x03,
 131                               0x60, 0xB5, 0x05},
 132                 
 133                 {FRESP_06H_COMPST, 0xB8, 0x07, 0x91, 0x03,
 134                               0x60, 0xB5, 0x05},
 135                 
 136                 {FRESP_06H_COMPST, 0x7C, 0x07, 0xD2, 0x83,
 137                               0x60, 0xB5, 0x03},
 138                 
 139                 {FRESP_06H_COMPST, 0x78, 0x07, 0xD2, 0x83,
 140                               0x60, 0xB5, 0x03},
 141                 
 142                 {FRESP_06H_SVIDEO, 0x59, 0x17, 0x42, 0xA3,
 143                               0x44, 0x75, 0x12},
 144                 
 145                 {FRESP_06H_SVIDEO, 0x9A, 0x17, 0xB1, 0x13,
 146                               0x60, 0xB5, 0x14},
 147                 
 148                 {FRESP_06H_SVIDEO, 0x3C, 0x27, 0xC1, 0x23,
 149                               0x44, 0x75, 0x21}
 150         };
 151         struct saa7110 *decoder = to_saa7110(sd);
 152         const unsigned char *ptr = modes[chan];
 153 
 154         saa7110_write(sd, 0x06, ptr[0]);        
 155         saa7110_write(sd, 0x20, ptr[1]);        
 156         saa7110_write(sd, 0x21, ptr[2]);        
 157         saa7110_write(sd, 0x22, ptr[3]);        
 158         saa7110_write(sd, 0x2C, ptr[4]);        
 159         saa7110_write(sd, 0x30, ptr[5]);        
 160         saa7110_write(sd, 0x31, ptr[6]);        
 161         saa7110_write(sd, 0x21, ptr[7]);        
 162         decoder->input = chan;
 163 
 164         return 0;
 165 }
 166 
 167 static const unsigned char initseq[1 + SAA7110_NR_REG] = {
 168         0, 0x4C, 0x3C, 0x0D, 0xEF, 0xBD, 0xF2, 0x03, 0x00,
 169          0xF8, 0xF8, 0x60, 0x60, 0x00, 0x86, 0x18, 0x90,
 170          0x00, 0x59, 0x40, 0x46, 0x42, 0x1A, 0xFF, 0xDA,
 171          0xF2, 0x8B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 172          0xD9, 0x16, 0x40, 0x41, 0x80, 0x41, 0x80, 0x4F,
 173          0xFE, 0x01, 0xCF, 0x0F, 0x03, 0x01, 0x03, 0x0C,
 174          0x44, 0x71, 0x02, 0x8C, 0x02
 175 };
 176 
 177 static v4l2_std_id determine_norm(struct v4l2_subdev *sd)
 178 {
 179         DEFINE_WAIT(wait);
 180         struct saa7110 *decoder = to_saa7110(sd);
 181         int status;
 182 
 183         
 184         saa7110_write_block(sd, initseq, sizeof(initseq));
 185         saa7110_selmux(sd, decoder->input);
 186         prepare_to_wait(&decoder->wq, &wait, TASK_UNINTERRUPTIBLE);
 187         schedule_timeout(msecs_to_jiffies(250));
 188         finish_wait(&decoder->wq, &wait);
 189         status = saa7110_read(sd);
 190         if (status & 0x40) {
 191                 v4l2_dbg(1, debug, sd, "status=0x%02x (no signal)\n", status);
 192                 return V4L2_STD_UNKNOWN;
 193         }
 194         if ((status & 3) == 0) {
 195                 saa7110_write(sd, 0x06, 0x83);
 196                 if (status & 0x20) {
 197                         v4l2_dbg(1, debug, sd, "status=0x%02x (NTSC/no color)\n", status);
 198                         
 199                         return V4L2_STD_NTSC;
 200                 }
 201                 v4l2_dbg(1, debug, sd, "status=0x%02x (PAL/no color)\n", status);
 202                 
 203                 return V4L2_STD_PAL;
 204         }
 205         
 206         if (status & 0x20) {    
 207                 v4l2_dbg(1, debug, sd, "status=0x%02x (NTSC)\n", status);
 208                 saa7110_write(sd, 0x0D, 0x86);
 209                 saa7110_write(sd, 0x0F, 0x50);
 210                 saa7110_write(sd, 0x11, 0x2C);
 211                 
 212                 return V4L2_STD_NTSC;
 213         }
 214 
 215         
 216         saa7110_write(sd, 0x0D, 0x86);
 217         saa7110_write(sd, 0x0F, 0x10);
 218         saa7110_write(sd, 0x11, 0x59);
 219         
 220 
 221         prepare_to_wait(&decoder->wq, &wait, TASK_UNINTERRUPTIBLE);
 222         schedule_timeout(msecs_to_jiffies(250));
 223         finish_wait(&decoder->wq, &wait);
 224 
 225         status = saa7110_read(sd);
 226         if ((status & 0x03) == 0x01) {
 227                 v4l2_dbg(1, debug, sd, "status=0x%02x (SECAM)\n", status);
 228                 saa7110_write(sd, 0x0D, 0x87);
 229                 return V4L2_STD_SECAM;
 230         }
 231         v4l2_dbg(1, debug, sd, "status=0x%02x (PAL)\n", status);
 232         return V4L2_STD_PAL;
 233 }
 234 
 235 static int saa7110_g_input_status(struct v4l2_subdev *sd, u32 *pstatus)
 236 {
 237         struct saa7110 *decoder = to_saa7110(sd);
 238         int res = V4L2_IN_ST_NO_SIGNAL;
 239         int status = saa7110_read(sd);
 240 
 241         v4l2_dbg(1, debug, sd, "status=0x%02x norm=%llx\n",
 242                        status, (unsigned long long)decoder->norm);
 243         if (!(status & 0x40))
 244                 res = 0;
 245         if (!(status & 0x03))
 246                 res |= V4L2_IN_ST_NO_COLOR;
 247 
 248         *pstatus = res;
 249         return 0;
 250 }
 251 
 252 static int saa7110_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
 253 {
 254         *std &= determine_norm(sd);
 255         return 0;
 256 }
 257 
 258 static int saa7110_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
 259 {
 260         struct saa7110 *decoder = to_saa7110(sd);
 261 
 262         if (decoder->norm != std) {
 263                 decoder->norm = std;
 264                 
 265                 if (std & V4L2_STD_NTSC) {
 266                         saa7110_write(sd, 0x0D, 0x86);
 267                         saa7110_write(sd, 0x0F, 0x50);
 268                         saa7110_write(sd, 0x11, 0x2C);
 269                         
 270                         v4l2_dbg(1, debug, sd, "switched to NTSC\n");
 271                 } else if (std & V4L2_STD_PAL) {
 272                         saa7110_write(sd, 0x0D, 0x86);
 273                         saa7110_write(sd, 0x0F, 0x10);
 274                         saa7110_write(sd, 0x11, 0x59);
 275                         
 276                         v4l2_dbg(1, debug, sd, "switched to PAL\n");
 277                 } else if (std & V4L2_STD_SECAM) {
 278                         saa7110_write(sd, 0x0D, 0x87);
 279                         saa7110_write(sd, 0x0F, 0x10);
 280                         saa7110_write(sd, 0x11, 0x59);
 281                         
 282                         v4l2_dbg(1, debug, sd, "switched to SECAM\n");
 283                 } else {
 284                         return -EINVAL;
 285                 }
 286         }
 287         return 0;
 288 }
 289 
 290 static int saa7110_s_routing(struct v4l2_subdev *sd,
 291                              u32 input, u32 output, u32 config)
 292 {
 293         struct saa7110 *decoder = to_saa7110(sd);
 294 
 295         if (input >= SAA7110_MAX_INPUT) {
 296                 v4l2_dbg(1, debug, sd, "input=%d not available\n", input);
 297                 return -EINVAL;
 298         }
 299         if (decoder->input != input) {
 300                 saa7110_selmux(sd, input);
 301                 v4l2_dbg(1, debug, sd, "switched to input=%d\n", input);
 302         }
 303         return 0;
 304 }
 305 
 306 static int saa7110_s_stream(struct v4l2_subdev *sd, int enable)
 307 {
 308         struct saa7110 *decoder = to_saa7110(sd);
 309 
 310         if (decoder->enable != enable) {
 311                 decoder->enable = enable;
 312                 saa7110_write(sd, 0x0E, enable ? 0x18 : 0x80);
 313                 v4l2_dbg(1, debug, sd, "YUV %s\n", enable ? "on" : "off");
 314         }
 315         return 0;
 316 }
 317 
 318 static int saa7110_s_ctrl(struct v4l2_ctrl *ctrl)
 319 {
 320         struct v4l2_subdev *sd = to_sd(ctrl);
 321 
 322         switch (ctrl->id) {
 323         case V4L2_CID_BRIGHTNESS:
 324                 saa7110_write(sd, 0x19, ctrl->val);
 325                 break;
 326         case V4L2_CID_CONTRAST:
 327                 saa7110_write(sd, 0x13, ctrl->val);
 328                 break;
 329         case V4L2_CID_SATURATION:
 330                 saa7110_write(sd, 0x12, ctrl->val);
 331                 break;
 332         case V4L2_CID_HUE:
 333                 saa7110_write(sd, 0x07, ctrl->val);
 334                 break;
 335         default:
 336                 return -EINVAL;
 337         }
 338         return 0;
 339 }
 340 
 341 
 342 
 343 static const struct v4l2_ctrl_ops saa7110_ctrl_ops = {
 344         .s_ctrl = saa7110_s_ctrl,
 345 };
 346 
 347 static const struct v4l2_subdev_video_ops saa7110_video_ops = {
 348         .s_std = saa7110_s_std,
 349         .s_routing = saa7110_s_routing,
 350         .s_stream = saa7110_s_stream,
 351         .querystd = saa7110_querystd,
 352         .g_input_status = saa7110_g_input_status,
 353 };
 354 
 355 static const struct v4l2_subdev_ops saa7110_ops = {
 356         .video = &saa7110_video_ops,
 357 };
 358 
 359 
 360 
 361 static int saa7110_probe(struct i2c_client *client,
 362                         const struct i2c_device_id *id)
 363 {
 364         struct saa7110 *decoder;
 365         struct v4l2_subdev *sd;
 366         int rv;
 367 
 368         
 369         if (!i2c_check_functionality(client->adapter,
 370                 I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
 371                 return -ENODEV;
 372 
 373         v4l_info(client, "chip found @ 0x%x (%s)\n",
 374                         client->addr << 1, client->adapter->name);
 375 
 376         decoder = devm_kzalloc(&client->dev, sizeof(*decoder), GFP_KERNEL);
 377         if (!decoder)
 378                 return -ENOMEM;
 379         sd = &decoder->sd;
 380         v4l2_i2c_subdev_init(sd, client, &saa7110_ops);
 381         decoder->norm = V4L2_STD_PAL;
 382         decoder->input = 0;
 383         decoder->enable = 1;
 384         v4l2_ctrl_handler_init(&decoder->hdl, 2);
 385         v4l2_ctrl_new_std(&decoder->hdl, &saa7110_ctrl_ops,
 386                 V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
 387         v4l2_ctrl_new_std(&decoder->hdl, &saa7110_ctrl_ops,
 388                 V4L2_CID_CONTRAST, 0, 127, 1, 64);
 389         v4l2_ctrl_new_std(&decoder->hdl, &saa7110_ctrl_ops,
 390                 V4L2_CID_SATURATION, 0, 127, 1, 64);
 391         v4l2_ctrl_new_std(&decoder->hdl, &saa7110_ctrl_ops,
 392                 V4L2_CID_HUE, -128, 127, 1, 0);
 393         sd->ctrl_handler = &decoder->hdl;
 394         if (decoder->hdl.error) {
 395                 int err = decoder->hdl.error;
 396 
 397                 v4l2_ctrl_handler_free(&decoder->hdl);
 398                 return err;
 399         }
 400         v4l2_ctrl_handler_setup(&decoder->hdl);
 401 
 402         init_waitqueue_head(&decoder->wq);
 403 
 404         rv = saa7110_write_block(sd, initseq, sizeof(initseq));
 405         if (rv < 0) {
 406                 v4l2_dbg(1, debug, sd, "init status %d\n", rv);
 407         } else {
 408                 int ver, status;
 409                 saa7110_write(sd, 0x21, 0x10);
 410                 saa7110_write(sd, 0x0e, 0x18);
 411                 saa7110_write(sd, 0x0D, 0x04);
 412                 ver = saa7110_read(sd);
 413                 saa7110_write(sd, 0x0D, 0x06);
 414                 
 415                 status = saa7110_read(sd);
 416                 v4l2_dbg(1, debug, sd, "version %x, status=0x%02x\n",
 417                                ver, status);
 418                 saa7110_write(sd, 0x0D, 0x86);
 419                 saa7110_write(sd, 0x0F, 0x10);
 420                 saa7110_write(sd, 0x11, 0x59);
 421                 
 422         }
 423 
 424         
 425         
 426         
 427 
 428         return 0;
 429 }
 430 
 431 static int saa7110_remove(struct i2c_client *client)
 432 {
 433         struct v4l2_subdev *sd = i2c_get_clientdata(client);
 434         struct saa7110 *decoder = to_saa7110(sd);
 435 
 436         v4l2_device_unregister_subdev(sd);
 437         v4l2_ctrl_handler_free(&decoder->hdl);
 438         return 0;
 439 }
 440 
 441 
 442 
 443 static const struct i2c_device_id saa7110_id[] = {
 444         { "saa7110", 0 },
 445         { }
 446 };
 447 MODULE_DEVICE_TABLE(i2c, saa7110_id);
 448 
 449 static struct i2c_driver saa7110_driver = {
 450         .driver = {
 451                 .name   = "saa7110",
 452         },
 453         .probe          = saa7110_probe,
 454         .remove         = saa7110_remove,
 455         .id_table       = saa7110_id,
 456 };
 457 
 458 module_i2c_driver(saa7110_driver);