1/* 2 * saa7110 - Philips SAA7110(A) video decoder driver 3 * 4 * Copyright (C) 1998 Pauline Middelink <middelin@polyware.nl> 5 * 6 * Copyright (C) 1999 Wolfgang Scherr <scherr@net4you.net> 7 * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx> 8 * - some corrections for Pinnacle Systems Inc. DC10plus card. 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 * This program is free software; you can redistribute it and/or modify 14 * it under the terms of the GNU General Public License as published by 15 * the Free Software Foundation; either version 2 of the License, or 16 * (at your option) any later version. 17 * 18 * This program is distributed in the hope that it will be useful, 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 * GNU General Public License for more details. 22 * 23 * You should have received a copy of the GNU General Public License 24 * along with this program; if not, write to the Free Software 25 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 26 */ 27 28#include <linux/module.h> 29#include <linux/init.h> 30#include <linux/types.h> 31#include <linux/delay.h> 32#include <linux/slab.h> 33#include <linux/wait.h> 34#include <asm/uaccess.h> 35#include <linux/i2c.h> 36#include <linux/videodev2.h> 37#include <media/v4l2-device.h> 38#include <media/v4l2-chip-ident.h> 39#include <media/v4l2-ctrls.h> 40 41MODULE_DESCRIPTION("Philips SAA7110 video decoder driver"); 42MODULE_AUTHOR("Pauline Middelink"); 43MODULE_LICENSE("GPL"); 44 45 46static int debug; 47module_param(debug, int, 0); 48MODULE_PARM_DESC(debug, "Debug level (0-1)"); 49 50#define SAA7110_MAX_INPUT 9 /* 6 CVBS, 3 SVHS */ 51#define SAA7110_MAX_OUTPUT 1 /* 1 YUV */ 52 53#define SAA7110_NR_REG 0x35 54 55struct saa7110 { 56 struct v4l2_subdev sd; 57 struct v4l2_ctrl_handler hdl; 58 u8 reg[SAA7110_NR_REG]; 59 60 v4l2_std_id norm; 61 int input; 62 int enable; 63 64 wait_queue_head_t wq; 65}; 66 67static inline struct saa7110 *to_saa7110(struct v4l2_subdev *sd) 68{ 69 return container_of(sd, struct saa7110, sd); 70} 71 72static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) 73{ 74 return &container_of(ctrl->handler, struct saa7110, hdl)->sd; 75} 76 77/* ----------------------------------------------------------------------- */ 78/* I2C support functions */ 79/* ----------------------------------------------------------------------- */ 80 81static int saa7110_write(struct v4l2_subdev *sd, u8 reg, u8 value) 82{ 83 struct i2c_client *client = v4l2_get_subdevdata(sd); 84 struct saa7110 *decoder = to_saa7110(sd); 85 86 decoder->reg[reg] = value; 87 return i2c_smbus_write_byte_data(client, reg, value); 88} 89 90static int saa7110_write_block(struct v4l2_subdev *sd, const u8 *data, unsigned int len) 91{ 92 struct i2c_client *client = v4l2_get_subdevdata(sd); 93 struct saa7110 *decoder = to_saa7110(sd); 94 int ret = -1; 95 u8 reg = *data; /* first register to write to */ 96 97 /* Sanity check */ 98 if (reg + (len - 1) > SAA7110_NR_REG) 99 return ret; 100 101 /* the saa7110 has an autoincrement function, use it if 102 * the adapter understands raw I2C */ 103 if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { 104 ret = i2c_master_send(client, data, len); 105 106 /* Cache the written data */ 107 memcpy(decoder->reg + reg, data + 1, len - 1); 108 } else { 109 for (++data, --len; len; len--) { 110 ret = saa7110_write(sd, reg++, *data++); 111 if (ret < 0) 112 break; 113 } 114 } 115 116 return ret; 117} 118 119static inline int saa7110_read(struct v4l2_subdev *sd) 120{ 121 struct i2c_client *client = v4l2_get_subdevdata(sd); 122 123 return i2c_smbus_read_byte(client); 124} 125 126/* ----------------------------------------------------------------------- */ 127/* SAA7110 functions */ 128/* ----------------------------------------------------------------------- */ 129 130#define FRESP_06H_COMPST 0x03 /*0x13*/ 131#define FRESP_06H_SVIDEO 0x83 /*0xC0*/ 132 133 134static int saa7110_selmux(struct v4l2_subdev *sd, int chan) 135{ 136 static const unsigned char modes[9][8] = { 137 /* mode 0 */ 138 {FRESP_06H_COMPST, 0xD9, 0x17, 0x40, 0x03, 139 0x44, 0x75, 0x16}, 140 /* mode 1 */ 141 {FRESP_06H_COMPST, 0xD8, 0x17, 0x40, 0x03, 142 0x44, 0x75, 0x16}, 143 /* mode 2 */ 144 {FRESP_06H_COMPST, 0xBA, 0x07, 0x91, 0x03, 145 0x60, 0xB5, 0x05}, 146 /* mode 3 */ 147 {FRESP_06H_COMPST, 0xB8, 0x07, 0x91, 0x03, 148 0x60, 0xB5, 0x05}, 149 /* mode 4 */ 150 {FRESP_06H_COMPST, 0x7C, 0x07, 0xD2, 0x83, 151 0x60, 0xB5, 0x03}, 152 /* mode 5 */ 153 {FRESP_06H_COMPST, 0x78, 0x07, 0xD2, 0x83, 154 0x60, 0xB5, 0x03}, 155 /* mode 6 */ 156 {FRESP_06H_SVIDEO, 0x59, 0x17, 0x42, 0xA3, 157 0x44, 0x75, 0x12}, 158 /* mode 7 */ 159 {FRESP_06H_SVIDEO, 0x9A, 0x17, 0xB1, 0x13, 160 0x60, 0xB5, 0x14}, 161 /* mode 8 */ 162 {FRESP_06H_SVIDEO, 0x3C, 0x27, 0xC1, 0x23, 163 0x44, 0x75, 0x21} 164 }; 165 struct saa7110 *decoder = to_saa7110(sd); 166 const unsigned char *ptr = modes[chan]; 167 168 saa7110_write(sd, 0x06, ptr[0]); /* Luminance control */ 169 saa7110_write(sd, 0x20, ptr[1]); /* Analog Control #1 */ 170 saa7110_write(sd, 0x21, ptr[2]); /* Analog Control #2 */ 171 saa7110_write(sd, 0x22, ptr[3]); /* Mixer Control #1 */ 172 saa7110_write(sd, 0x2C, ptr[4]); /* Mixer Control #2 */ 173 saa7110_write(sd, 0x30, ptr[5]); /* ADCs gain control */ 174 saa7110_write(sd, 0x31, ptr[6]); /* Mixer Control #3 */ 175 saa7110_write(sd, 0x21, ptr[7]); /* Analog Control #2 */ 176 decoder->input = chan; 177 178 return 0; 179} 180 181static const unsigned char initseq[1 + SAA7110_NR_REG] = { 182 0, 0x4C, 0x3C, 0x0D, 0xEF, 0xBD, 0xF2, 0x03, 0x00, 183 /* 0x08 */ 0xF8, 0xF8, 0x60, 0x60, 0x00, 0x86, 0x18, 0x90, 184 /* 0x10 */ 0x00, 0x59, 0x40, 0x46, 0x42, 0x1A, 0xFF, 0xDA, 185 /* 0x18 */ 0xF2, 0x8B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 186 /* 0x20 */ 0xD9, 0x16, 0x40, 0x41, 0x80, 0x41, 0x80, 0x4F, 187 /* 0x28 */ 0xFE, 0x01, 0xCF, 0x0F, 0x03, 0x01, 0x03, 0x0C, 188 /* 0x30 */ 0x44, 0x71, 0x02, 0x8C, 0x02 189}; 190 191static v4l2_std_id determine_norm(struct v4l2_subdev *sd) 192{ 193 DEFINE_WAIT(wait); 194 struct saa7110 *decoder = to_saa7110(sd); 195 int status; 196 197 /* mode changed, start automatic detection */ 198 saa7110_write_block(sd, initseq, sizeof(initseq)); 199 saa7110_selmux(sd, decoder->input); 200 prepare_to_wait(&decoder->wq, &wait, TASK_UNINTERRUPTIBLE); 201 schedule_timeout(msecs_to_jiffies(250)); 202 finish_wait(&decoder->wq, &wait); 203 status = saa7110_read(sd); 204 if (status & 0x40) { 205 v4l2_dbg(1, debug, sd, "status=0x%02x (no signal)\n", status); 206 return decoder->norm; /* no change*/ 207 } 208 if ((status & 3) == 0) { 209 saa7110_write(sd, 0x06, 0x83); 210 if (status & 0x20) { 211 v4l2_dbg(1, debug, sd, "status=0x%02x (NTSC/no color)\n", status); 212 /*saa7110_write(sd,0x2E,0x81);*/ 213 return V4L2_STD_NTSC; 214 } 215 v4l2_dbg(1, debug, sd, "status=0x%02x (PAL/no color)\n", status); 216 /*saa7110_write(sd,0x2E,0x9A);*/ 217 return V4L2_STD_PAL; 218 } 219 /*saa7110_write(sd,0x06,0x03);*/ 220 if (status & 0x20) { /* 60Hz */ 221 v4l2_dbg(1, debug, sd, "status=0x%02x (NTSC)\n", status); 222 saa7110_write(sd, 0x0D, 0x86); 223 saa7110_write(sd, 0x0F, 0x50); 224 saa7110_write(sd, 0x11, 0x2C); 225 /*saa7110_write(sd,0x2E,0x81);*/ 226 return V4L2_STD_NTSC; 227 } 228 229 /* 50Hz -> PAL/SECAM */ 230 saa7110_write(sd, 0x0D, 0x86); 231 saa7110_write(sd, 0x0F, 0x10); 232 saa7110_write(sd, 0x11, 0x59); 233 /*saa7110_write(sd,0x2E,0x9A);*/ 234 235 prepare_to_wait(&decoder->wq, &wait, TASK_UNINTERRUPTIBLE); 236 schedule_timeout(msecs_to_jiffies(250)); 237 finish_wait(&decoder->wq, &wait); 238 239 status = saa7110_read(sd); 240 if ((status & 0x03) == 0x01) { 241 v4l2_dbg(1, debug, sd, "status=0x%02x (SECAM)\n", status); 242 saa7110_write(sd, 0x0D, 0x87); 243 return V4L2_STD_SECAM; 244 } 245 v4l2_dbg(1, debug, sd, "status=0x%02x (PAL)\n", status); 246 return V4L2_STD_PAL; 247} 248 249static int saa7110_g_input_status(struct v4l2_subdev *sd, u32 *pstatus) 250{ 251 struct saa7110 *decoder = to_saa7110(sd); 252 int res = V4L2_IN_ST_NO_SIGNAL; 253 int status = saa7110_read(sd); 254 255 v4l2_dbg(1, debug, sd, "status=0x%02x norm=%llx\n", 256 status, (unsigned long long)decoder->norm); 257 if (!(status & 0x40)) 258 res = 0; 259 if (!(status & 0x03)) 260 res |= V4L2_IN_ST_NO_COLOR; 261 262 *pstatus = res; 263 return 0; 264} 265 266static int saa7110_querystd(struct v4l2_subdev *sd, v4l2_std_id *std) 267{ 268 *(v4l2_std_id *)std = determine_norm(sd); 269 return 0; 270} 271 272static int saa7110_s_std(struct v4l2_subdev *sd, v4l2_std_id std) 273{ 274 struct saa7110 *decoder = to_saa7110(sd); 275 276 if (decoder->norm != std) { 277 decoder->norm = std; 278 /*saa7110_write(sd, 0x06, 0x03);*/ 279 if (std & V4L2_STD_NTSC) { 280 saa7110_write(sd, 0x0D, 0x86); 281 saa7110_write(sd, 0x0F, 0x50); 282 saa7110_write(sd, 0x11, 0x2C); 283 /*saa7110_write(sd, 0x2E, 0x81);*/ 284 v4l2_dbg(1, debug, sd, "switched to NTSC\n"); 285 } else if (std & V4L2_STD_PAL) { 286 saa7110_write(sd, 0x0D, 0x86); 287 saa7110_write(sd, 0x0F, 0x10); 288 saa7110_write(sd, 0x11, 0x59); 289 /*saa7110_write(sd, 0x2E, 0x9A);*/ 290 v4l2_dbg(1, debug, sd, "switched to PAL\n"); 291 } else if (std & V4L2_STD_SECAM) { 292 saa7110_write(sd, 0x0D, 0x87); 293 saa7110_write(sd, 0x0F, 0x10); 294 saa7110_write(sd, 0x11, 0x59); 295 /*saa7110_write(sd, 0x2E, 0x9A);*/ 296 v4l2_dbg(1, debug, sd, "switched to SECAM\n"); 297 } else { 298 return -EINVAL; 299 } 300 } 301 return 0; 302} 303 304static int saa7110_s_routing(struct v4l2_subdev *sd, 305 u32 input, u32 output, u32 config) 306{ 307 struct saa7110 *decoder = to_saa7110(sd); 308 309 if (input >= SAA7110_MAX_INPUT) { 310 v4l2_dbg(1, debug, sd, "input=%d not available\n", input); 311 return -EINVAL; 312 } 313 if (decoder->input != input) { 314 saa7110_selmux(sd, input); 315 v4l2_dbg(1, debug, sd, "switched to input=%d\n", input); 316 } 317 return 0; 318} 319 320static int saa7110_s_stream(struct v4l2_subdev *sd, int enable) 321{ 322 struct saa7110 *decoder = to_saa7110(sd); 323 324 if (decoder->enable != enable) { 325 decoder->enable = enable; 326 saa7110_write(sd, 0x0E, enable ? 0x18 : 0x80); 327 v4l2_dbg(1, debug, sd, "YUV %s\n", enable ? "on" : "off"); 328 } 329 return 0; 330} 331 332static int saa7110_s_ctrl(struct v4l2_ctrl *ctrl) 333{ 334 struct v4l2_subdev *sd = to_sd(ctrl); 335 336 switch (ctrl->id) { 337 case V4L2_CID_BRIGHTNESS: 338 saa7110_write(sd, 0x19, ctrl->val); 339 break; 340 case V4L2_CID_CONTRAST: 341 saa7110_write(sd, 0x13, ctrl->val); 342 break; 343 case V4L2_CID_SATURATION: 344 saa7110_write(sd, 0x12, ctrl->val); 345 break; 346 case V4L2_CID_HUE: 347 saa7110_write(sd, 0x07, ctrl->val); 348 break; 349 default: 350 return -EINVAL; 351 } 352 return 0; 353} 354 355static int saa7110_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) 356{ 357 struct i2c_client *client = v4l2_get_subdevdata(sd); 358 359 return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SAA7110, 0); 360} 361 362/* ----------------------------------------------------------------------- */ 363 364static const struct v4l2_ctrl_ops saa7110_ctrl_ops = { 365 .s_ctrl = saa7110_s_ctrl, 366}; 367 368static const struct v4l2_subdev_core_ops saa7110_core_ops = { 369 .g_chip_ident = saa7110_g_chip_ident, 370 .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, 371 .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, 372 .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, 373 .g_ctrl = v4l2_subdev_g_ctrl, 374 .s_ctrl = v4l2_subdev_s_ctrl, 375 .queryctrl = v4l2_subdev_queryctrl, 376 .querymenu = v4l2_subdev_querymenu, 377 .s_std = saa7110_s_std, 378}; 379 380static const struct v4l2_subdev_video_ops saa7110_video_ops = { 381 .s_routing = saa7110_s_routing, 382 .s_stream = saa7110_s_stream, 383 .querystd = saa7110_querystd, 384 .g_input_status = saa7110_g_input_status, 385}; 386 387static const struct v4l2_subdev_ops saa7110_ops = { 388 .core = &saa7110_core_ops, 389 .video = &saa7110_video_ops, 390}; 391 392/* ----------------------------------------------------------------------- */ 393 394static int saa7110_probe(struct i2c_client *client, 395 const struct i2c_device_id *id) 396{ 397 struct saa7110 *decoder; 398 struct v4l2_subdev *sd; 399 int rv; 400 401 /* Check if the adapter supports the needed features */ 402 if (!i2c_check_functionality(client->adapter, 403 I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) 404 return -ENODEV; 405 406 v4l_info(client, "chip found @ 0x%x (%s)\n", 407 client->addr << 1, client->adapter->name); 408 409 decoder = kzalloc(sizeof(struct saa7110), GFP_KERNEL); 410 if (!decoder) 411 return -ENOMEM; 412 sd = &decoder->sd; 413 v4l2_i2c_subdev_init(sd, client, &saa7110_ops); 414 decoder->norm = V4L2_STD_PAL; 415 decoder->input = 0; 416 decoder->enable = 1; 417 v4l2_ctrl_handler_init(&decoder->hdl, 2); 418 v4l2_ctrl_new_std(&decoder->hdl, &saa7110_ctrl_ops, 419 V4L2_CID_BRIGHTNESS, 0, 255, 1, 128); 420 v4l2_ctrl_new_std(&decoder->hdl, &saa7110_ctrl_ops, 421 V4L2_CID_CONTRAST, 0, 127, 1, 64); 422 v4l2_ctrl_new_std(&decoder->hdl, &saa7110_ctrl_ops, 423 V4L2_CID_SATURATION, 0, 127, 1, 64); 424 v4l2_ctrl_new_std(&decoder->hdl, &saa7110_ctrl_ops, 425 V4L2_CID_HUE, -128, 127, 1, 0); 426 sd->ctrl_handler = &decoder->hdl; 427 if (decoder->hdl.error) { 428 int err = decoder->hdl.error; 429 430 v4l2_ctrl_handler_free(&decoder->hdl); 431 kfree(decoder); 432 return err; 433 } 434 v4l2_ctrl_handler_setup(&decoder->hdl); 435 436 init_waitqueue_head(&decoder->wq); 437 438 rv = saa7110_write_block(sd, initseq, sizeof(initseq)); 439 if (rv < 0) { 440 v4l2_dbg(1, debug, sd, "init status %d\n", rv); 441 } else { 442 int ver, status; 443 saa7110_write(sd, 0x21, 0x10); 444 saa7110_write(sd, 0x0e, 0x18); 445 saa7110_write(sd, 0x0D, 0x04); 446 ver = saa7110_read(sd); 447 saa7110_write(sd, 0x0D, 0x06); 448 /*mdelay(150);*/ 449 status = saa7110_read(sd); 450 v4l2_dbg(1, debug, sd, "version %x, status=0x%02x\n", 451 ver, status); 452 saa7110_write(sd, 0x0D, 0x86); 453 saa7110_write(sd, 0x0F, 0x10); 454 saa7110_write(sd, 0x11, 0x59); 455 /*saa7110_write(sd, 0x2E, 0x9A);*/ 456 } 457 458 /*saa7110_selmux(sd,0);*/ 459 /*determine_norm(sd);*/ 460 /* setup and implicit mode 0 select has been performed */ 461 462 return 0; 463} 464 465static int saa7110_remove(struct i2c_client *client) 466{ 467 struct v4l2_subdev *sd = i2c_get_clientdata(client); 468 struct saa7110 *decoder = to_saa7110(sd); 469 470 v4l2_device_unregister_subdev(sd); 471 v4l2_ctrl_handler_free(&decoder->hdl); 472 kfree(decoder); 473 return 0; 474} 475 476/* ----------------------------------------------------------------------- */ 477 478static const struct i2c_device_id saa7110_id[] = { 479 { "saa7110", 0 }, 480 { } 481}; 482MODULE_DEVICE_TABLE(i2c, saa7110_id); 483 484static struct i2c_driver saa7110_driver = { 485 .driver = { 486 .owner = THIS_MODULE, 487 .name = "saa7110", 488 }, 489 .probe = saa7110_probe, 490 .remove = saa7110_remove, 491 .id_table = saa7110_id, 492}; 493 494static __init int init_saa7110(void) 495{ 496 return i2c_add_driver(&saa7110_driver); 497} 498 499static __exit void exit_saa7110(void) 500{ 501 i2c_del_driver(&saa7110_driver); 502} 503 504module_init(init_saa7110); 505module_exit(exit_saa7110); 506