1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * saa7110 - Philips SAA7110(A) video decoder driver 4 * 5 * Copyright (C) 1998 Pauline Middelink <middelin@polyware.nl> 6 * 7 * Copyright (C) 1999 Wolfgang Scherr <scherr@net4you.net> 8 * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx> 9 * - some corrections for Pinnacle Systems Inc. DC10plus card. 10 * 11 * Changes by Ronald Bultje <rbultje@ronald.bitfreak.net> 12 * - moved over to linux>=2.4.x i2c protocol (1/1/2003) 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 /* 6 CVBS, 3 SVHS */ 37 #define SAA7110_MAX_OUTPUT 1 /* 1 YUV */ 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 /* I2C support functions */ 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; /* first register to write to */ 82 83 /* Sanity check */ 84 if (reg + (len - 1) > SAA7110_NR_REG) 85 return ret; 86 87 /* the saa7110 has an autoincrement function, use it if 88 * the adapter understands raw I2C */ 89 if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { 90 ret = i2c_master_send(client, data, len); 91 92 /* Cache the written data */ 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 /* SAA7110 functions */ 114 /* ----------------------------------------------------------------------- */ 115 116 #define FRESP_06H_COMPST 0x03 /*0x13*/ 117 #define FRESP_06H_SVIDEO 0x83 /*0xC0*/ 118 119 120 static int saa7110_selmux(struct v4l2_subdev *sd, int chan) 121 { 122 static const unsigned char modes[9][8] = { 123 /* mode 0 */ 124 {FRESP_06H_COMPST, 0xD9, 0x17, 0x40, 0x03, 125 0x44, 0x75, 0x16}, 126 /* mode 1 */ 127 {FRESP_06H_COMPST, 0xD8, 0x17, 0x40, 0x03, 128 0x44, 0x75, 0x16}, 129 /* mode 2 */ 130 {FRESP_06H_COMPST, 0xBA, 0x07, 0x91, 0x03, 131 0x60, 0xB5, 0x05}, 132 /* mode 3 */ 133 {FRESP_06H_COMPST, 0xB8, 0x07, 0x91, 0x03, 134 0x60, 0xB5, 0x05}, 135 /* mode 4 */ 136 {FRESP_06H_COMPST, 0x7C, 0x07, 0xD2, 0x83, 137 0x60, 0xB5, 0x03}, 138 /* mode 5 */ 139 {FRESP_06H_COMPST, 0x78, 0x07, 0xD2, 0x83, 140 0x60, 0xB5, 0x03}, 141 /* mode 6 */ 142 {FRESP_06H_SVIDEO, 0x59, 0x17, 0x42, 0xA3, 143 0x44, 0x75, 0x12}, 144 /* mode 7 */ 145 {FRESP_06H_SVIDEO, 0x9A, 0x17, 0xB1, 0x13, 146 0x60, 0xB5, 0x14}, 147 /* mode 8 */ 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]); /* Luminance control */ 155 saa7110_write(sd, 0x20, ptr[1]); /* Analog Control #1 */ 156 saa7110_write(sd, 0x21, ptr[2]); /* Analog Control #2 */ 157 saa7110_write(sd, 0x22, ptr[3]); /* Mixer Control #1 */ 158 saa7110_write(sd, 0x2C, ptr[4]); /* Mixer Control #2 */ 159 saa7110_write(sd, 0x30, ptr[5]); /* ADCs gain control */ 160 saa7110_write(sd, 0x31, ptr[6]); /* Mixer Control #3 */ 161 saa7110_write(sd, 0x21, ptr[7]); /* Analog Control #2 */ 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 /* 0x08 */ 0xF8, 0xF8, 0x60, 0x60, 0x00, 0x86, 0x18, 0x90, 170 /* 0x10 */ 0x00, 0x59, 0x40, 0x46, 0x42, 0x1A, 0xFF, 0xDA, 171 /* 0x18 */ 0xF2, 0x8B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 172 /* 0x20 */ 0xD9, 0x16, 0x40, 0x41, 0x80, 0x41, 0x80, 0x4F, 173 /* 0x28 */ 0xFE, 0x01, 0xCF, 0x0F, 0x03, 0x01, 0x03, 0x0C, 174 /* 0x30 */ 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 /* mode changed, start automatic detection */ 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 /*saa7110_write(sd,0x2E,0x81);*/ 199 return V4L2_STD_NTSC; 200 } 201 v4l2_dbg(1, debug, sd, "status=0x%02x (PAL/no color)\n", status); 202 /*saa7110_write(sd,0x2E,0x9A);*/ 203 return V4L2_STD_PAL; 204 } 205 /*saa7110_write(sd,0x06,0x03);*/ 206 if (status & 0x20) { /* 60Hz */ 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 /*saa7110_write(sd,0x2E,0x81);*/ 212 return V4L2_STD_NTSC; 213 } 214 215 /* 50Hz -> PAL/SECAM */ 216 saa7110_write(sd, 0x0D, 0x86); 217 saa7110_write(sd, 0x0F, 0x10); 218 saa7110_write(sd, 0x11, 0x59); 219 /*saa7110_write(sd,0x2E,0x9A);*/ 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 /*saa7110_write(sd, 0x06, 0x03);*/ 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 /*saa7110_write(sd, 0x2E, 0x81);*/ 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 /*saa7110_write(sd, 0x2E, 0x9A);*/ 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 /*saa7110_write(sd, 0x2E, 0x9A);*/ 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 { 363 struct saa7110 *decoder; 364 struct v4l2_subdev *sd; 365 int rv; 366 367 /* Check if the adapter supports the needed features */ 368 if (!i2c_check_functionality(client->adapter, 369 I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) 370 return -ENODEV; 371 372 v4l_info(client, "chip found @ 0x%x (%s)\n", 373 client->addr << 1, client->adapter->name); 374 375 decoder = devm_kzalloc(&client->dev, sizeof(*decoder), GFP_KERNEL); 376 if (!decoder) 377 return -ENOMEM; 378 sd = &decoder->sd; 379 v4l2_i2c_subdev_init(sd, client, &saa7110_ops); 380 decoder->norm = V4L2_STD_PAL; 381 decoder->input = 0; 382 decoder->enable = 1; 383 v4l2_ctrl_handler_init(&decoder->hdl, 2); 384 v4l2_ctrl_new_std(&decoder->hdl, &saa7110_ctrl_ops, 385 V4L2_CID_BRIGHTNESS, 0, 255, 1, 128); 386 v4l2_ctrl_new_std(&decoder->hdl, &saa7110_ctrl_ops, 387 V4L2_CID_CONTRAST, 0, 127, 1, 64); 388 v4l2_ctrl_new_std(&decoder->hdl, &saa7110_ctrl_ops, 389 V4L2_CID_SATURATION, 0, 127, 1, 64); 390 v4l2_ctrl_new_std(&decoder->hdl, &saa7110_ctrl_ops, 391 V4L2_CID_HUE, -128, 127, 1, 0); 392 sd->ctrl_handler = &decoder->hdl; 393 if (decoder->hdl.error) { 394 int err = decoder->hdl.error; 395 396 v4l2_ctrl_handler_free(&decoder->hdl); 397 return err; 398 } 399 v4l2_ctrl_handler_setup(&decoder->hdl); 400 401 init_waitqueue_head(&decoder->wq); 402 403 rv = saa7110_write_block(sd, initseq, sizeof(initseq)); 404 if (rv < 0) { 405 v4l2_dbg(1, debug, sd, "init status %d\n", rv); 406 } else { 407 int ver, status; 408 saa7110_write(sd, 0x21, 0x10); 409 saa7110_write(sd, 0x0e, 0x18); 410 saa7110_write(sd, 0x0D, 0x04); 411 ver = saa7110_read(sd); 412 saa7110_write(sd, 0x0D, 0x06); 413 /*mdelay(150);*/ 414 status = saa7110_read(sd); 415 v4l2_dbg(1, debug, sd, "version %x, status=0x%02x\n", 416 ver, status); 417 saa7110_write(sd, 0x0D, 0x86); 418 saa7110_write(sd, 0x0F, 0x10); 419 saa7110_write(sd, 0x11, 0x59); 420 /*saa7110_write(sd, 0x2E, 0x9A);*/ 421 } 422 423 /*saa7110_selmux(sd,0);*/ 424 /*determine_norm(sd);*/ 425 /* setup and implicit mode 0 select has been performed */ 426 427 return 0; 428 } 429 430 static void saa7110_remove(struct i2c_client *client) 431 { 432 struct v4l2_subdev *sd = i2c_get_clientdata(client); 433 struct saa7110 *decoder = to_saa7110(sd); 434 435 v4l2_device_unregister_subdev(sd); 436 v4l2_ctrl_handler_free(&decoder->hdl); 437 } 438 439 /* ----------------------------------------------------------------------- */ 440 441 static const struct i2c_device_id saa7110_id[] = { 442 { "saa7110" }, 443 { } 444 }; 445 MODULE_DEVICE_TABLE(i2c, saa7110_id); 446 447 static struct i2c_driver saa7110_driver = { 448 .driver = { 449 .name = "saa7110", 450 }, 451 .probe = saa7110_probe, 452 .remove = saa7110_remove, 453 .id_table = saa7110_id, 454 }; 455 456 module_i2c_driver(saa7110_driver); 457