PageRenderTime 81ms CodeModel.GetById 15ms app.highlight 54ms RepoModel.GetById 0ms app.codeStats 1ms

/drivers/media/video/saa717x.c

https://bitbucket.org/slukk/jb-tsm-kernel-4.2
C | 1389 lines | 1081 code | 186 blank | 122 comment | 87 complexity | c7dddac82cc1525066795b95115498cd MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
   1/*
   2 * saa717x - Philips SAA717xHL video decoder driver
   3 *
   4 * Based on the saa7115 driver
   5 *
   6 * Changes by Ohta Kyuma <alpha292@bremen.or.jp>
   7 *    - Apply to SAA717x,NEC uPD64031,uPD64083. (1/31/2004)
   8 *
   9 * Changes by T.Adachi (tadachi@tadachi-net.com)
  10 *    - support audio, video scaler etc, and checked the initialize sequence.
  11 *
  12 * Cleaned up by Hans Verkuil <hverkuil@xs4all.nl>
  13 *
  14 * Note: this is a reversed engineered driver based on captures from
  15 * the I2C bus under Windows. This chip is very similar to the saa7134,
  16 * though. Unfortunately, this driver is currently only working for NTSC.
  17 *
  18 * This program is free software; you can redistribute it and/or modify
  19 * it under the terms of the GNU General Public License as published by
  20 * the Free Software Foundation; either version 2 of the License, or
  21 * (at your option) any later version.
  22 *
  23 * This program is distributed in the hope that it will be useful,
  24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  26 * GNU General Public License for more details.
  27 *
  28 * You should have received a copy of the GNU General Public License
  29 * along with this program; if not, write to the Free Software
  30 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  31 */
  32
  33#include <linux/module.h>
  34#include <linux/kernel.h>
  35#include <linux/slab.h>
  36#include <linux/sched.h>
  37
  38#include <linux/videodev2.h>
  39#include <linux/i2c.h>
  40#include <media/v4l2-device.h>
  41#include <media/v4l2-ctrls.h>
  42
  43MODULE_DESCRIPTION("Philips SAA717x audio/video decoder driver");
  44MODULE_AUTHOR("K. Ohta, T. Adachi, Hans Verkuil");
  45MODULE_LICENSE("GPL");
  46
  47static int debug;
  48module_param(debug, int, 0644);
  49MODULE_PARM_DESC(debug, "Debug level (0-1)");
  50
  51/*
  52 * Generic i2c probe
  53 * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
  54 */
  55
  56struct saa717x_state {
  57	struct v4l2_subdev sd;
  58	struct v4l2_ctrl_handler hdl;
  59	v4l2_std_id std;
  60	int input;
  61	int enable;
  62	int radio;
  63	int playback;
  64	int audio;
  65	int tuner_audio_mode;
  66	int audio_main_mute;
  67	int audio_main_vol_r;
  68	int audio_main_vol_l;
  69	u16 audio_main_bass;
  70	u16 audio_main_treble;
  71	u16 audio_main_volume;
  72	u16 audio_main_balance;
  73	int audio_input;
  74};
  75
  76static inline struct saa717x_state *to_state(struct v4l2_subdev *sd)
  77{
  78	return container_of(sd, struct saa717x_state, sd);
  79}
  80
  81static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
  82{
  83	return &container_of(ctrl->handler, struct saa717x_state, hdl)->sd;
  84}
  85
  86/* ----------------------------------------------------------------------- */
  87
  88/* for audio mode */
  89#define TUNER_AUDIO_MONO   	0  /* LL */
  90#define TUNER_AUDIO_STEREO 	1  /* LR */
  91#define TUNER_AUDIO_LANG1  	2  /* LL */
  92#define TUNER_AUDIO_LANG2  	3  /* RR */
  93
  94#define SAA717X_NTSC_WIDTH   	(704)
  95#define SAA717X_NTSC_HEIGHT  	(480)
  96
  97/* ----------------------------------------------------------------------- */
  98
  99static int saa717x_write(struct v4l2_subdev *sd, u32 reg, u32 value)
 100{
 101	struct i2c_client *client = v4l2_get_subdevdata(sd);
 102	struct i2c_adapter *adap = client->adapter;
 103	int fw_addr = reg == 0x454 || (reg >= 0x464 && reg <= 0x478) || reg == 0x480 || reg == 0x488;
 104	unsigned char mm1[6];
 105	struct i2c_msg msg;
 106
 107	msg.flags = 0;
 108	msg.addr = client->addr;
 109	mm1[0] = (reg >> 8) & 0xff;
 110	mm1[1] = reg & 0xff;
 111
 112	if (fw_addr) {
 113		mm1[4] = (value >> 16) & 0xff;
 114		mm1[3] = (value >> 8) & 0xff;
 115		mm1[2] = value & 0xff;
 116	} else {
 117		mm1[2] = value & 0xff;
 118	}
 119	msg.len = fw_addr ? 5 : 3; /* Long Registers have *only* three bytes! */
 120	msg.buf = mm1;
 121	v4l2_dbg(2, debug, sd, "wrote:  reg 0x%03x=%08x\n", reg, value);
 122	return i2c_transfer(adap, &msg, 1) == 1;
 123}
 124
 125static void saa717x_write_regs(struct v4l2_subdev *sd, u32 *data)
 126{
 127	while (data[0] || data[1]) {
 128		saa717x_write(sd, data[0], data[1]);
 129		data += 2;
 130	}
 131}
 132
 133static u32 saa717x_read(struct v4l2_subdev *sd, u32 reg)
 134{
 135	struct i2c_client *client = v4l2_get_subdevdata(sd);
 136	struct i2c_adapter *adap = client->adapter;
 137	int fw_addr = (reg >= 0x404 && reg <= 0x4b8) || reg == 0x528;
 138	unsigned char mm1[2];
 139	unsigned char mm2[4] = { 0, 0, 0, 0 };
 140	struct i2c_msg msgs[2];
 141	u32 value;
 142
 143	msgs[0].flags = 0;
 144	msgs[1].flags = I2C_M_RD;
 145	msgs[0].addr = msgs[1].addr = client->addr;
 146	mm1[0] = (reg >> 8) & 0xff;
 147	mm1[1] = reg & 0xff;
 148	msgs[0].len = 2;
 149	msgs[0].buf = mm1;
 150	msgs[1].len = fw_addr ? 3 : 1; /* Multibyte Registers contains *only* 3 bytes */
 151	msgs[1].buf = mm2;
 152	i2c_transfer(adap, msgs, 2);
 153
 154	if (fw_addr)
 155		value = (mm2[2] & 0xff)  | ((mm2[1] & 0xff) >> 8) | ((mm2[0] & 0xff) >> 16);
 156	else
 157		value = mm2[0] & 0xff;
 158
 159	v4l2_dbg(2, debug, sd, "read:  reg 0x%03x=0x%08x\n", reg, value);
 160	return value;
 161}
 162
 163/* ----------------------------------------------------------------------- */
 164
 165static u32 reg_init_initialize[] =
 166{
 167	/* from linux driver */
 168	0x101, 0x008, /* Increment delay */
 169
 170	0x103, 0x000, /* Analog input control 2 */
 171	0x104, 0x090, /* Analog input control 3 */
 172	0x105, 0x090, /* Analog input control 4 */
 173	0x106, 0x0eb, /* Horizontal sync start */
 174	0x107, 0x0e0, /* Horizontal sync stop */
 175	0x109, 0x055, /* Luminance control */
 176
 177	0x10f, 0x02a, /* Chroma gain control */
 178	0x110, 0x000, /* Chroma control 2 */
 179
 180	0x114, 0x045, /* analog/ADC */
 181
 182	0x118, 0x040, /* RAW data gain */
 183	0x119, 0x080, /* RAW data offset */
 184
 185	0x044, 0x000, /* VBI horizontal input window start (L) TASK A */
 186	0x045, 0x000, /* VBI horizontal input window start (H) TASK A */
 187	0x046, 0x0cf, /* VBI horizontal input window stop (L) TASK A */
 188	0x047, 0x002, /* VBI horizontal input window stop (H) TASK A */
 189
 190	0x049, 0x000, /* VBI vertical input window start (H) TASK A */
 191
 192	0x04c, 0x0d0, /* VBI horizontal output length (L) TASK A */
 193	0x04d, 0x002, /* VBI horizontal output length (H) TASK A */
 194
 195	0x064, 0x080, /* Lumina brightness TASK A */
 196	0x065, 0x040, /* Luminance contrast TASK A */
 197	0x066, 0x040, /* Chroma saturation TASK A */
 198	/* 067H: Reserved */
 199	0x068, 0x000, /* VBI horizontal scaling increment (L) TASK A */
 200	0x069, 0x004, /* VBI horizontal scaling increment (H) TASK A */
 201	0x06a, 0x000, /* VBI phase offset TASK A */
 202
 203	0x06e, 0x000, /* Horizontal phase offset Luma TASK A */
 204	0x06f, 0x000, /* Horizontal phase offset Chroma TASK A */
 205
 206	0x072, 0x000, /* Vertical filter mode TASK A */
 207
 208	0x084, 0x000, /* VBI horizontal input window start (L) TAKS B */
 209	0x085, 0x000, /* VBI horizontal input window start (H) TAKS B */
 210	0x086, 0x0cf, /* VBI horizontal input window stop (L) TAKS B */
 211	0x087, 0x002, /* VBI horizontal input window stop (H) TAKS B */
 212
 213	0x089, 0x000, /* VBI vertical input window start (H) TAKS B */
 214
 215	0x08c, 0x0d0, /* VBI horizontal output length (L) TASK B */
 216	0x08d, 0x002, /* VBI horizontal output length (H) TASK B */
 217
 218	0x0a4, 0x080, /* Lumina brightness TASK B */
 219	0x0a5, 0x040, /* Luminance contrast TASK B */
 220	0x0a6, 0x040, /* Chroma saturation TASK B */
 221	/* 0A7H reserved */
 222	0x0a8, 0x000, /* VBI horizontal scaling increment (L) TASK B */
 223	0x0a9, 0x004, /* VBI horizontal scaling increment (H) TASK B */
 224	0x0aa, 0x000, /* VBI phase offset TASK B */
 225
 226	0x0ae, 0x000, /* Horizontal phase offset Luma TASK B */
 227	0x0af, 0x000, /*Horizontal phase offset Chroma TASK B */
 228
 229	0x0b2, 0x000, /* Vertical filter mode TASK B */
 230
 231	0x00c, 0x000, /* Start point GREEN path */
 232	0x00d, 0x000, /* Start point BLUE path */
 233	0x00e, 0x000, /* Start point RED path */
 234
 235	0x010, 0x010, /* GREEN path gamma curve --- */
 236	0x011, 0x020,
 237	0x012, 0x030,
 238	0x013, 0x040,
 239	0x014, 0x050,
 240	0x015, 0x060,
 241	0x016, 0x070,
 242	0x017, 0x080,
 243	0x018, 0x090,
 244	0x019, 0x0a0,
 245	0x01a, 0x0b0,
 246	0x01b, 0x0c0,
 247	0x01c, 0x0d0,
 248	0x01d, 0x0e0,
 249	0x01e, 0x0f0,
 250	0x01f, 0x0ff, /* --- GREEN path gamma curve */
 251
 252	0x020, 0x010, /* BLUE path gamma curve --- */
 253	0x021, 0x020,
 254	0x022, 0x030,
 255	0x023, 0x040,
 256	0x024, 0x050,
 257	0x025, 0x060,
 258	0x026, 0x070,
 259	0x027, 0x080,
 260	0x028, 0x090,
 261	0x029, 0x0a0,
 262	0x02a, 0x0b0,
 263	0x02b, 0x0c0,
 264	0x02c, 0x0d0,
 265	0x02d, 0x0e0,
 266	0x02e, 0x0f0,
 267	0x02f, 0x0ff, /* --- BLUE path gamma curve */
 268
 269	0x030, 0x010, /* RED path gamma curve --- */
 270	0x031, 0x020,
 271	0x032, 0x030,
 272	0x033, 0x040,
 273	0x034, 0x050,
 274	0x035, 0x060,
 275	0x036, 0x070,
 276	0x037, 0x080,
 277	0x038, 0x090,
 278	0x039, 0x0a0,
 279	0x03a, 0x0b0,
 280	0x03b, 0x0c0,
 281	0x03c, 0x0d0,
 282	0x03d, 0x0e0,
 283	0x03e, 0x0f0,
 284	0x03f, 0x0ff, /* --- RED path gamma curve */
 285
 286	0x109, 0x085, /* Luminance control  */
 287
 288	/**** from app start ****/
 289	0x584, 0x000, /* AGC gain control */
 290	0x585, 0x000, /* Program count */
 291	0x586, 0x003, /* Status reset */
 292	0x588, 0x0ff, /* Number of audio samples (L) */
 293	0x589, 0x00f, /* Number of audio samples (M) */
 294	0x58a, 0x000, /* Number of audio samples (H) */
 295	0x58b, 0x000, /* Audio select */
 296	0x58c, 0x010, /* Audio channel assign1 */
 297	0x58d, 0x032, /* Audio channel assign2 */
 298	0x58e, 0x054, /* Audio channel assign3 */
 299	0x58f, 0x023, /* Audio format */
 300	0x590, 0x000, /* SIF control */
 301
 302	0x595, 0x000, /* ?? */
 303	0x596, 0x000, /* ?? */
 304	0x597, 0x000, /* ?? */
 305
 306	0x464, 0x00, /* Digital input crossbar1 */
 307
 308	0x46c, 0xbbbb10, /* Digital output selection1-3 */
 309	0x470, 0x101010, /* Digital output selection4-6 */
 310
 311	0x478, 0x00, /* Sound feature control */
 312
 313	0x474, 0x18, /* Softmute control */
 314
 315	0x454, 0x0425b9, /* Sound Easy programming(reset) */
 316	0x454, 0x042539, /* Sound Easy programming(reset) */
 317
 318
 319	/**** common setting( of DVD play, including scaler commands) ****/
 320	0x042, 0x003, /* Data path configuration for VBI (TASK A) */
 321
 322	0x082, 0x003, /* Data path configuration for VBI (TASK B) */
 323
 324	0x108, 0x0f8, /* Sync control */
 325	0x2a9, 0x0fd, /* ??? */
 326	0x102, 0x089, /* select video input "mode 9" */
 327	0x111, 0x000, /* Mode/delay control */
 328
 329	0x10e, 0x00a, /* Chroma control 1 */
 330
 331	0x594, 0x002, /* SIF, analog I/O select */
 332
 333	0x454, 0x0425b9, /* Sound  */
 334	0x454, 0x042539,
 335
 336	0x111, 0x000,
 337	0x10e, 0x00a,
 338	0x464, 0x000,
 339	0x300, 0x000,
 340	0x301, 0x006,
 341	0x302, 0x000,
 342	0x303, 0x006,
 343	0x308, 0x040,
 344	0x309, 0x000,
 345	0x30a, 0x000,
 346	0x30b, 0x000,
 347	0x000, 0x002,
 348	0x001, 0x000,
 349	0x002, 0x000,
 350	0x003, 0x000,
 351	0x004, 0x033,
 352	0x040, 0x01d,
 353	0x041, 0x001,
 354	0x042, 0x004,
 355	0x043, 0x000,
 356	0x080, 0x01e,
 357	0x081, 0x001,
 358	0x082, 0x004,
 359	0x083, 0x000,
 360	0x190, 0x018,
 361	0x115, 0x000,
 362	0x116, 0x012,
 363	0x117, 0x018,
 364	0x04a, 0x011,
 365	0x08a, 0x011,
 366	0x04b, 0x000,
 367	0x08b, 0x000,
 368	0x048, 0x000,
 369	0x088, 0x000,
 370	0x04e, 0x012,
 371	0x08e, 0x012,
 372	0x058, 0x012,
 373	0x098, 0x012,
 374	0x059, 0x000,
 375	0x099, 0x000,
 376	0x05a, 0x003,
 377	0x09a, 0x003,
 378	0x05b, 0x001,
 379	0x09b, 0x001,
 380	0x054, 0x008,
 381	0x094, 0x008,
 382	0x055, 0x000,
 383	0x095, 0x000,
 384	0x056, 0x0c7,
 385	0x096, 0x0c7,
 386	0x057, 0x002,
 387	0x097, 0x002,
 388	0x0ff, 0x0ff,
 389	0x060, 0x001,
 390	0x0a0, 0x001,
 391	0x061, 0x000,
 392	0x0a1, 0x000,
 393	0x062, 0x000,
 394	0x0a2, 0x000,
 395	0x063, 0x000,
 396	0x0a3, 0x000,
 397	0x070, 0x000,
 398	0x0b0, 0x000,
 399	0x071, 0x004,
 400	0x0b1, 0x004,
 401	0x06c, 0x0e9,
 402	0x0ac, 0x0e9,
 403	0x06d, 0x003,
 404	0x0ad, 0x003,
 405	0x05c, 0x0d0,
 406	0x09c, 0x0d0,
 407	0x05d, 0x002,
 408	0x09d, 0x002,
 409	0x05e, 0x0f2,
 410	0x09e, 0x0f2,
 411	0x05f, 0x000,
 412	0x09f, 0x000,
 413	0x074, 0x000,
 414	0x0b4, 0x000,
 415	0x075, 0x000,
 416	0x0b5, 0x000,
 417	0x076, 0x000,
 418	0x0b6, 0x000,
 419	0x077, 0x000,
 420	0x0b7, 0x000,
 421	0x195, 0x008,
 422	0x0ff, 0x0ff,
 423	0x108, 0x0f8,
 424	0x111, 0x000,
 425	0x10e, 0x00a,
 426	0x2a9, 0x0fd,
 427	0x464, 0x001,
 428	0x454, 0x042135,
 429	0x598, 0x0e7,
 430	0x599, 0x07d,
 431	0x59a, 0x018,
 432	0x59c, 0x066,
 433	0x59d, 0x090,
 434	0x59e, 0x001,
 435	0x584, 0x000,
 436	0x585, 0x000,
 437	0x586, 0x003,
 438	0x588, 0x0ff,
 439	0x589, 0x00f,
 440	0x58a, 0x000,
 441	0x58b, 0x000,
 442	0x58c, 0x010,
 443	0x58d, 0x032,
 444	0x58e, 0x054,
 445	0x58f, 0x023,
 446	0x590, 0x000,
 447	0x595, 0x000,
 448	0x596, 0x000,
 449	0x597, 0x000,
 450	0x464, 0x000,
 451	0x46c, 0xbbbb10,
 452	0x470, 0x101010,
 453
 454
 455	0x478, 0x000,
 456	0x474, 0x018,
 457	0x454, 0x042135,
 458	0x598, 0x0e7,
 459	0x599, 0x07d,
 460	0x59a, 0x018,
 461	0x59c, 0x066,
 462	0x59d, 0x090,
 463	0x59e, 0x001,
 464	0x584, 0x000,
 465	0x585, 0x000,
 466	0x586, 0x003,
 467	0x588, 0x0ff,
 468	0x589, 0x00f,
 469	0x58a, 0x000,
 470	0x58b, 0x000,
 471	0x58c, 0x010,
 472	0x58d, 0x032,
 473	0x58e, 0x054,
 474	0x58f, 0x023,
 475	0x590, 0x000,
 476	0x595, 0x000,
 477	0x596, 0x000,
 478	0x597, 0x000,
 479	0x464, 0x000,
 480	0x46c, 0xbbbb10,
 481	0x470, 0x101010,
 482
 483	0x478, 0x000,
 484	0x474, 0x018,
 485	0x454, 0x042135,
 486	0x598, 0x0e7,
 487	0x599, 0x07d,
 488	0x59a, 0x018,
 489	0x59c, 0x066,
 490	0x59d, 0x090,
 491	0x59e, 0x001,
 492	0x584, 0x000,
 493	0x585, 0x000,
 494	0x586, 0x003,
 495	0x588, 0x0ff,
 496	0x589, 0x00f,
 497	0x58a, 0x000,
 498	0x58b, 0x000,
 499	0x58c, 0x010,
 500	0x58d, 0x032,
 501	0x58e, 0x054,
 502	0x58f, 0x023,
 503	0x590, 0x000,
 504	0x595, 0x000,
 505	0x596, 0x000,
 506	0x597, 0x000,
 507	0x464, 0x000,
 508	0x46c, 0xbbbb10,
 509	0x470, 0x101010,
 510	0x478, 0x000,
 511	0x474, 0x018,
 512	0x454, 0x042135,
 513	0x193, 0x000,
 514	0x300, 0x000,
 515	0x301, 0x006,
 516	0x302, 0x000,
 517	0x303, 0x006,
 518	0x308, 0x040,
 519	0x309, 0x000,
 520	0x30a, 0x000,
 521	0x30b, 0x000,
 522	0x000, 0x002,
 523	0x001, 0x000,
 524	0x002, 0x000,
 525	0x003, 0x000,
 526	0x004, 0x033,
 527	0x040, 0x01d,
 528	0x041, 0x001,
 529	0x042, 0x004,
 530	0x043, 0x000,
 531	0x080, 0x01e,
 532	0x081, 0x001,
 533	0x082, 0x004,
 534	0x083, 0x000,
 535	0x190, 0x018,
 536	0x115, 0x000,
 537	0x116, 0x012,
 538	0x117, 0x018,
 539	0x04a, 0x011,
 540	0x08a, 0x011,
 541	0x04b, 0x000,
 542	0x08b, 0x000,
 543	0x048, 0x000,
 544	0x088, 0x000,
 545	0x04e, 0x012,
 546	0x08e, 0x012,
 547	0x058, 0x012,
 548	0x098, 0x012,
 549	0x059, 0x000,
 550	0x099, 0x000,
 551	0x05a, 0x003,
 552	0x09a, 0x003,
 553	0x05b, 0x001,
 554	0x09b, 0x001,
 555	0x054, 0x008,
 556	0x094, 0x008,
 557	0x055, 0x000,
 558	0x095, 0x000,
 559	0x056, 0x0c7,
 560	0x096, 0x0c7,
 561	0x057, 0x002,
 562	0x097, 0x002,
 563	0x060, 0x001,
 564	0x0a0, 0x001,
 565	0x061, 0x000,
 566	0x0a1, 0x000,
 567	0x062, 0x000,
 568	0x0a2, 0x000,
 569	0x063, 0x000,
 570	0x0a3, 0x000,
 571	0x070, 0x000,
 572	0x0b0, 0x000,
 573	0x071, 0x004,
 574	0x0b1, 0x004,
 575	0x06c, 0x0e9,
 576	0x0ac, 0x0e9,
 577	0x06d, 0x003,
 578	0x0ad, 0x003,
 579	0x05c, 0x0d0,
 580	0x09c, 0x0d0,
 581	0x05d, 0x002,
 582	0x09d, 0x002,
 583	0x05e, 0x0f2,
 584	0x09e, 0x0f2,
 585	0x05f, 0x000,
 586	0x09f, 0x000,
 587	0x074, 0x000,
 588	0x0b4, 0x000,
 589	0x075, 0x000,
 590	0x0b5, 0x000,
 591	0x076, 0x000,
 592	0x0b6, 0x000,
 593	0x077, 0x000,
 594	0x0b7, 0x000,
 595	0x195, 0x008,
 596	0x598, 0x0e7,
 597	0x599, 0x07d,
 598	0x59a, 0x018,
 599	0x59c, 0x066,
 600	0x59d, 0x090,
 601	0x59e, 0x001,
 602	0x584, 0x000,
 603	0x585, 0x000,
 604	0x586, 0x003,
 605	0x588, 0x0ff,
 606	0x589, 0x00f,
 607	0x58a, 0x000,
 608	0x58b, 0x000,
 609	0x58c, 0x010,
 610	0x58d, 0x032,
 611	0x58e, 0x054,
 612	0x58f, 0x023,
 613	0x590, 0x000,
 614	0x595, 0x000,
 615	0x596, 0x000,
 616	0x597, 0x000,
 617	0x464, 0x000,
 618	0x46c, 0xbbbb10,
 619	0x470, 0x101010,
 620	0x478, 0x000,
 621	0x474, 0x018,
 622	0x454, 0x042135,
 623	0x193, 0x0a6,
 624	0x108, 0x0f8,
 625	0x042, 0x003,
 626	0x082, 0x003,
 627	0x454, 0x0425b9,
 628	0x454, 0x042539,
 629	0x193, 0x000,
 630	0x193, 0x0a6,
 631	0x464, 0x000,
 632
 633	0, 0
 634};
 635
 636/* Tuner */
 637static u32 reg_init_tuner_input[] = {
 638	0x108, 0x0f8, /* Sync control */
 639	0x111, 0x000, /* Mode/delay control */
 640	0x10e, 0x00a, /* Chroma control 1 */
 641	0, 0
 642};
 643
 644/* Composite */
 645static u32 reg_init_composite_input[] = {
 646	0x108, 0x0e8, /* Sync control */
 647	0x111, 0x000, /* Mode/delay control */
 648	0x10e, 0x04a, /* Chroma control 1 */
 649	0, 0
 650};
 651
 652/* S-Video */
 653static u32 reg_init_svideo_input[] = {
 654	0x108, 0x0e8, /* Sync control */
 655	0x111, 0x000, /* Mode/delay control */
 656	0x10e, 0x04a, /* Chroma control 1 */
 657	0, 0
 658};
 659
 660static u32 reg_set_audio_template[4][2] =
 661{
 662	{ /* for MONO
 663		tadachi 6/29 DMA audio output select?
 664		Register 0x46c
 665		7-4: DMA2, 3-0: DMA1 ch. DMA4, DMA3 DMA2, DMA1
 666		0: MAIN left,  1: MAIN right
 667		2: AUX1 left,  3: AUX1 right
 668		4: AUX2 left,  5: AUX2 right
 669		6: DPL left,   7: DPL  right
 670		8: DPL center, 9: DPL surround
 671		A: monitor output, B: digital sense */
 672		0xbbbb00,
 673
 674		/* tadachi 6/29 DAC and I2S output select?
 675		   Register 0x470
 676		   7-4:DAC right ch. 3-0:DAC left ch.
 677		   I2S1 right,left  I2S2 right,left */
 678		0x00,
 679	},
 680	{ /* for STEREO */
 681		0xbbbb10, 0x101010,
 682	},
 683	{ /* for LANG1 */
 684		0xbbbb00, 0x00,
 685	},
 686	{ /* for LANG2/SAP */
 687		0xbbbb11, 0x111111,
 688	}
 689};
 690
 691
 692/* Get detected audio flags (from saa7134 driver) */
 693static void get_inf_dev_status(struct v4l2_subdev *sd,
 694		int *dual_flag, int *stereo_flag)
 695{
 696	u32 reg_data3;
 697
 698	static char *stdres[0x20] = {
 699		[0x00] = "no standard detected",
 700		[0x01] = "B/G (in progress)",
 701		[0x02] = "D/K (in progress)",
 702		[0x03] = "M (in progress)",
 703
 704		[0x04] = "B/G A2",
 705		[0x05] = "B/G NICAM",
 706		[0x06] = "D/K A2 (1)",
 707		[0x07] = "D/K A2 (2)",
 708		[0x08] = "D/K A2 (3)",
 709		[0x09] = "D/K NICAM",
 710		[0x0a] = "L NICAM",
 711		[0x0b] = "I NICAM",
 712
 713		[0x0c] = "M Korea",
 714		[0x0d] = "M BTSC ",
 715		[0x0e] = "M EIAJ",
 716
 717		[0x0f] = "FM radio / IF 10.7 / 50 deemp",
 718		[0x10] = "FM radio / IF 10.7 / 75 deemp",
 719		[0x11] = "FM radio / IF sel / 50 deemp",
 720		[0x12] = "FM radio / IF sel / 75 deemp",
 721
 722		[0x13 ... 0x1e] = "unknown",
 723		[0x1f] = "??? [in progress]",
 724	};
 725
 726
 727	*dual_flag = *stereo_flag = 0;
 728
 729	/* (demdec status: 0x528) */
 730
 731	/* read current status */
 732	reg_data3 = saa717x_read(sd, 0x0528);
 733
 734	v4l2_dbg(1, debug, sd, "tvaudio thread status: 0x%x [%s%s%s]\n",
 735		reg_data3, stdres[reg_data3 & 0x1f],
 736		(reg_data3 & 0x000020) ? ",stereo" : "",
 737		(reg_data3 & 0x000040) ? ",dual"   : "");
 738	v4l2_dbg(1, debug, sd, "detailed status: "
 739		"%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s\n",
 740		(reg_data3 & 0x000080) ? " A2/EIAJ pilot tone "     : "",
 741		(reg_data3 & 0x000100) ? " A2/EIAJ dual "           : "",
 742		(reg_data3 & 0x000200) ? " A2/EIAJ stereo "         : "",
 743		(reg_data3 & 0x000400) ? " A2/EIAJ noise mute "     : "",
 744
 745		(reg_data3 & 0x000800) ? " BTSC/FM radio pilot "    : "",
 746		(reg_data3 & 0x001000) ? " SAP carrier "            : "",
 747		(reg_data3 & 0x002000) ? " BTSC stereo noise mute " : "",
 748		(reg_data3 & 0x004000) ? " SAP noise mute "         : "",
 749		(reg_data3 & 0x008000) ? " VDSP "                   : "",
 750
 751		(reg_data3 & 0x010000) ? " NICST "                  : "",
 752		(reg_data3 & 0x020000) ? " NICDU "                  : "",
 753		(reg_data3 & 0x040000) ? " NICAM muted "            : "",
 754		(reg_data3 & 0x080000) ? " NICAM reserve sound "    : "",
 755
 756		(reg_data3 & 0x100000) ? " init done "              : "");
 757
 758	if (reg_data3 & 0x000220) {
 759		v4l2_dbg(1, debug, sd, "ST!!!\n");
 760		*stereo_flag = 1;
 761	}
 762
 763	if (reg_data3 & 0x000140) {
 764		v4l2_dbg(1, debug, sd, "DUAL!!!\n");
 765		*dual_flag = 1;
 766	}
 767}
 768
 769/* regs write to set audio mode */
 770static void set_audio_mode(struct v4l2_subdev *sd, int audio_mode)
 771{
 772	v4l2_dbg(1, debug, sd, "writing registers to set audio mode by set %d\n",
 773			audio_mode);
 774
 775	saa717x_write(sd, 0x46c, reg_set_audio_template[audio_mode][0]);
 776	saa717x_write(sd, 0x470, reg_set_audio_template[audio_mode][1]);
 777}
 778
 779/* write regs to set audio volume, bass and treble */
 780static int set_audio_regs(struct v4l2_subdev *sd,
 781		struct saa717x_state *decoder)
 782{
 783	u8 mute = 0xac; /* -84 dB */
 784	u32 val;
 785	unsigned int work_l, work_r;
 786
 787	/* set SIF analog I/O select */
 788	saa717x_write(sd, 0x0594, decoder->audio_input);
 789	v4l2_dbg(1, debug, sd, "set audio input %d\n",
 790			decoder->audio_input);
 791
 792	/* normalize ( 65535 to 0 -> 24 to -40 (not -84)) */
 793	work_l = (min(65536 - decoder->audio_main_balance, 32768) * decoder->audio_main_volume) / 32768;
 794	work_r = (min(decoder->audio_main_balance, (u16)32768) * decoder->audio_main_volume) / 32768;
 795	decoder->audio_main_vol_l = (long)work_l * (24 - (-40)) / 65535 - 40;
 796	decoder->audio_main_vol_r = (long)work_r * (24 - (-40)) / 65535 - 40;
 797
 798	/* set main volume */
 799	/* main volume L[7-0],R[7-0],0x00  24=24dB,-83dB, -84(mute) */
 800	/*    def:0dB->6dB(MPG600GR) */
 801	/* if mute is on, set mute */
 802	if (decoder->audio_main_mute) {
 803		val = mute | (mute << 8);
 804	} else {
 805		val = (u8)decoder->audio_main_vol_l |
 806			((u8)decoder->audio_main_vol_r << 8);
 807	}
 808
 809	saa717x_write(sd, 0x480, val);
 810
 811	/* set bass and treble */
 812	val = decoder->audio_main_bass & 0x1f;
 813	val |= (decoder->audio_main_treble & 0x1f) << 5;
 814	saa717x_write(sd, 0x488, val);
 815	return 0;
 816}
 817
 818/********** scaling staff ***********/
 819static void set_h_prescale(struct v4l2_subdev *sd,
 820		int task, int prescale)
 821{
 822	static const struct {
 823		int xpsc;
 824		int xacl;
 825		int xc2_1;
 826		int xdcg;
 827		int vpfy;
 828	} vals[] = {
 829		/* XPSC XACL XC2_1 XDCG VPFY */
 830		{    1,   0,    0,    0,   0 },
 831		{    2,   2,    1,    2,   2 },
 832		{    3,   4,    1,    3,   2 },
 833		{    4,   8,    1,    4,   2 },
 834		{    5,   8,    1,    4,   2 },
 835		{    6,   8,    1,    4,   3 },
 836		{    7,   8,    1,    4,   3 },
 837		{    8,  15,    0,    4,   3 },
 838		{    9,  15,    0,    4,   3 },
 839		{   10,  16,    1,    5,   3 },
 840	};
 841	static const int count = ARRAY_SIZE(vals);
 842	int i, task_shift;
 843
 844	task_shift = task * 0x40;
 845	for (i = 0; i < count; i++)
 846		if (vals[i].xpsc == prescale)
 847			break;
 848	if (i == count)
 849		return;
 850
 851	/* horizonal prescaling */
 852	saa717x_write(sd, 0x60 + task_shift, vals[i].xpsc);
 853	/* accumulation length */
 854	saa717x_write(sd, 0x61 + task_shift, vals[i].xacl);
 855	/* level control */
 856	saa717x_write(sd, 0x62 + task_shift,
 857			(vals[i].xc2_1 << 3) | vals[i].xdcg);
 858	/*FIR prefilter control */
 859	saa717x_write(sd, 0x63 + task_shift,
 860			(vals[i].vpfy << 2) | vals[i].vpfy);
 861}
 862
 863/********** scaling staff ***********/
 864static void set_v_scale(struct v4l2_subdev *sd, int task, int yscale)
 865{
 866	int task_shift;
 867
 868	task_shift = task * 0x40;
 869	/* Vertical scaling ratio (LOW) */
 870	saa717x_write(sd, 0x70 + task_shift, yscale & 0xff);
 871	/* Vertical scaling ratio (HI) */
 872	saa717x_write(sd, 0x71 + task_shift, yscale >> 8);
 873}
 874
 875static int saa717x_s_ctrl(struct v4l2_ctrl *ctrl)
 876{
 877	struct v4l2_subdev *sd = to_sd(ctrl);
 878	struct saa717x_state *state = to_state(sd);
 879
 880	switch (ctrl->id) {
 881	case V4L2_CID_BRIGHTNESS:
 882		saa717x_write(sd, 0x10a, ctrl->val);
 883		return 0;
 884
 885	case V4L2_CID_CONTRAST:
 886		saa717x_write(sd, 0x10b, ctrl->val);
 887		return 0;
 888
 889	case V4L2_CID_SATURATION:
 890		saa717x_write(sd, 0x10c, ctrl->val);
 891		return 0;
 892
 893	case V4L2_CID_HUE:
 894		saa717x_write(sd, 0x10d, ctrl->val);
 895		return 0;
 896
 897	case V4L2_CID_AUDIO_MUTE:
 898		state->audio_main_mute = ctrl->val;
 899		break;
 900
 901	case V4L2_CID_AUDIO_VOLUME:
 902		state->audio_main_volume = ctrl->val;
 903		break;
 904
 905	case V4L2_CID_AUDIO_BALANCE:
 906		state->audio_main_balance = ctrl->val;
 907		break;
 908
 909	case V4L2_CID_AUDIO_TREBLE:
 910		state->audio_main_treble = ctrl->val;
 911		break;
 912
 913	case V4L2_CID_AUDIO_BASS:
 914		state->audio_main_bass = ctrl->val;
 915		break;
 916
 917	default:
 918		return 0;
 919	}
 920	set_audio_regs(sd, state);
 921	return 0;
 922}
 923
 924static int saa717x_s_video_routing(struct v4l2_subdev *sd,
 925				   u32 input, u32 output, u32 config)
 926{
 927	struct saa717x_state *decoder = to_state(sd);
 928	int is_tuner = input & 0x80;  /* tuner input flag */
 929
 930	input &= 0x7f;
 931
 932	v4l2_dbg(1, debug, sd, "decoder set input (%d)\n", input);
 933	/* inputs from 0-9 are available*/
 934	/* saa717x have mode0-mode9 but mode5 is reserved. */
 935	if (input > 9 || input == 5)
 936		return -EINVAL;
 937
 938	if (decoder->input != input) {
 939		int input_line = input;
 940
 941		decoder->input = input_line;
 942		v4l2_dbg(1, debug, sd,  "now setting %s input %d\n",
 943				input_line >= 6 ? "S-Video" : "Composite",
 944				input_line);
 945
 946		/* select mode */
 947		saa717x_write(sd, 0x102,
 948				(saa717x_read(sd, 0x102) & 0xf0) |
 949				input_line);
 950
 951		/* bypass chrominance trap for modes 6..9 */
 952		saa717x_write(sd, 0x109,
 953				(saa717x_read(sd, 0x109) & 0x7f) |
 954				(input_line < 6 ? 0x0 : 0x80));
 955
 956		/* change audio_mode */
 957		if (is_tuner) {
 958			/* tuner */
 959			set_audio_mode(sd, decoder->tuner_audio_mode);
 960		} else {
 961			/* Force to STEREO mode if Composite or
 962			 * S-Video were chosen */
 963			set_audio_mode(sd, TUNER_AUDIO_STEREO);
 964		}
 965		/* change initialize procedure (Composite/S-Video) */
 966		if (is_tuner)
 967			saa717x_write_regs(sd, reg_init_tuner_input);
 968		else if (input_line >= 6)
 969			saa717x_write_regs(sd, reg_init_svideo_input);
 970		else
 971			saa717x_write_regs(sd, reg_init_composite_input);
 972	}
 973
 974	return 0;
 975}
 976
 977#ifdef CONFIG_VIDEO_ADV_DEBUG
 978static int saa717x_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
 979{
 980	struct i2c_client *client = v4l2_get_subdevdata(sd);
 981
 982	if (!v4l2_chip_match_i2c_client(client, &reg->match))
 983		return -EINVAL;
 984	if (!capable(CAP_SYS_ADMIN))
 985		return -EPERM;
 986	reg->val = saa717x_read(sd, reg->reg);
 987	reg->size = 1;
 988	return 0;
 989}
 990
 991static int saa717x_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
 992{
 993	struct i2c_client *client = v4l2_get_subdevdata(sd);
 994	u16 addr = reg->reg & 0xffff;
 995	u8 val = reg->val & 0xff;
 996
 997	if (!v4l2_chip_match_i2c_client(client, &reg->match))
 998		return -EINVAL;
 999	if (!capable(CAP_SYS_ADMIN))
1000		return -EPERM;
1001	saa717x_write(sd, addr, val);
1002	return 0;
1003}
1004#endif
1005
1006static int saa717x_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
1007{
1008	int prescale, h_scale, v_scale;
1009
1010	v4l2_dbg(1, debug, sd, "decoder set size\n");
1011
1012	if (fmt->code != V4L2_MBUS_FMT_FIXED)
1013		return -EINVAL;
1014
1015	/* FIXME need better bounds checking here */
1016	if (fmt->width < 1 || fmt->width > 1440)
1017		return -EINVAL;
1018	if (fmt->height < 1 || fmt->height > 960)
1019		return -EINVAL;
1020
1021	fmt->field = V4L2_FIELD_INTERLACED;
1022	fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
1023
1024	/* scaling setting */
1025	/* NTSC and interlace only */
1026	prescale = SAA717X_NTSC_WIDTH / fmt->width;
1027	if (prescale == 0)
1028		prescale = 1;
1029	h_scale = 1024 * SAA717X_NTSC_WIDTH / prescale / fmt->width;
1030	/* interlace */
1031	v_scale = 512 * 2 * SAA717X_NTSC_HEIGHT / fmt->height;
1032
1033	/* Horizontal prescaling etc */
1034	set_h_prescale(sd, 0, prescale);
1035	set_h_prescale(sd, 1, prescale);
1036
1037	/* Horizontal scaling increment */
1038	/* TASK A */
1039	saa717x_write(sd, 0x6C, (u8)(h_scale & 0xFF));
1040	saa717x_write(sd, 0x6D, (u8)((h_scale >> 8) & 0xFF));
1041	/* TASK B */
1042	saa717x_write(sd, 0xAC, (u8)(h_scale & 0xFF));
1043	saa717x_write(sd, 0xAD, (u8)((h_scale >> 8) & 0xFF));
1044
1045	/* Vertical prescaling etc */
1046	set_v_scale(sd, 0, v_scale);
1047	set_v_scale(sd, 1, v_scale);
1048
1049	/* set video output size */
1050	/* video number of pixels at output */
1051	/* TASK A */
1052	saa717x_write(sd, 0x5C, (u8)(fmt->width & 0xFF));
1053	saa717x_write(sd, 0x5D, (u8)((fmt->width >> 8) & 0xFF));
1054	/* TASK B */
1055	saa717x_write(sd, 0x9C, (u8)(fmt->width & 0xFF));
1056	saa717x_write(sd, 0x9D, (u8)((fmt->width >> 8) & 0xFF));
1057
1058	/* video number of lines at output */
1059	/* TASK A */
1060	saa717x_write(sd, 0x5E, (u8)(fmt->height & 0xFF));
1061	saa717x_write(sd, 0x5F, (u8)((fmt->height >> 8) & 0xFF));
1062	/* TASK B */
1063	saa717x_write(sd, 0x9E, (u8)(fmt->height & 0xFF));
1064	saa717x_write(sd, 0x9F, (u8)((fmt->height >> 8) & 0xFF));
1065	return 0;
1066}
1067
1068static int saa717x_s_radio(struct v4l2_subdev *sd)
1069{
1070	struct saa717x_state *decoder = to_state(sd);
1071
1072	decoder->radio = 1;
1073	return 0;
1074}
1075
1076static int saa717x_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
1077{
1078	struct saa717x_state *decoder = to_state(sd);
1079
1080	v4l2_dbg(1, debug, sd, "decoder set norm ");
1081	v4l2_dbg(1, debug, sd, "(not yet implementd)\n");
1082
1083	decoder->radio = 0;
1084	decoder->std = std;
1085	return 0;
1086}
1087
1088static int saa717x_s_audio_routing(struct v4l2_subdev *sd,
1089				   u32 input, u32 output, u32 config)
1090{
1091	struct saa717x_state *decoder = to_state(sd);
1092
1093	if (input < 3) { /* FIXME! --tadachi */
1094		decoder->audio_input = input;
1095		v4l2_dbg(1, debug, sd,
1096				"set decoder audio input to %d\n",
1097				decoder->audio_input);
1098		set_audio_regs(sd, decoder);
1099		return 0;
1100	}
1101	return -ERANGE;
1102}
1103
1104static int saa717x_s_stream(struct v4l2_subdev *sd, int enable)
1105{
1106	struct saa717x_state *decoder = to_state(sd);
1107
1108	v4l2_dbg(1, debug, sd, "decoder %s output\n",
1109			enable ? "enable" : "disable");
1110	decoder->enable = enable;
1111	saa717x_write(sd, 0x193, enable ? 0xa6 : 0x26);
1112	return 0;
1113}
1114
1115/* change audio mode */
1116static int saa717x_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
1117{
1118	struct saa717x_state *decoder = to_state(sd);
1119	int audio_mode;
1120	char *mes[4] = {
1121		"MONO", "STEREO", "LANG1", "LANG2/SAP"
1122	};
1123
1124	audio_mode = TUNER_AUDIO_STEREO;
1125
1126	switch (vt->audmode) {
1127		case V4L2_TUNER_MODE_MONO:
1128			audio_mode = TUNER_AUDIO_MONO;
1129			break;
1130		case V4L2_TUNER_MODE_STEREO:
1131			audio_mode = TUNER_AUDIO_STEREO;
1132			break;
1133		case V4L2_TUNER_MODE_LANG2:
1134			audio_mode = TUNER_AUDIO_LANG2;
1135			break;
1136		case V4L2_TUNER_MODE_LANG1:
1137			audio_mode = TUNER_AUDIO_LANG1;
1138			break;
1139	}
1140
1141	v4l2_dbg(1, debug, sd, "change audio mode to %s\n",
1142			mes[audio_mode]);
1143	decoder->tuner_audio_mode = audio_mode;
1144	/* The registers are not changed here. */
1145	/* See DECODER_ENABLE_OUTPUT section. */
1146	set_audio_mode(sd, decoder->tuner_audio_mode);
1147	return 0;
1148}
1149
1150static int saa717x_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
1151{
1152	struct saa717x_state *decoder = to_state(sd);
1153	int dual_f, stereo_f;
1154
1155	if (decoder->radio)
1156		return 0;
1157	get_inf_dev_status(sd, &dual_f, &stereo_f);
1158
1159	v4l2_dbg(1, debug, sd, "DETECT==st:%d dual:%d\n",
1160			stereo_f, dual_f);
1161
1162	/* mono */
1163	if ((dual_f == 0) && (stereo_f == 0)) {
1164		vt->rxsubchans = V4L2_TUNER_SUB_MONO;
1165		v4l2_dbg(1, debug, sd, "DETECT==MONO\n");
1166	}
1167
1168	/* stereo */
1169	if (stereo_f == 1) {
1170		if (vt->audmode == V4L2_TUNER_MODE_STEREO ||
1171				vt->audmode == V4L2_TUNER_MODE_LANG1) {
1172			vt->rxsubchans = V4L2_TUNER_SUB_STEREO;
1173			v4l2_dbg(1, debug, sd, "DETECT==ST(ST)\n");
1174		} else {
1175			vt->rxsubchans = V4L2_TUNER_SUB_MONO;
1176			v4l2_dbg(1, debug, sd, "DETECT==ST(MONO)\n");
1177		}
1178	}
1179
1180	/* dual */
1181	if (dual_f == 1) {
1182		if (vt->audmode == V4L2_TUNER_MODE_LANG2) {
1183			vt->rxsubchans = V4L2_TUNER_SUB_LANG2 | V4L2_TUNER_SUB_MONO;
1184			v4l2_dbg(1, debug, sd, "DETECT==DUAL1\n");
1185		} else {
1186			vt->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_MONO;
1187			v4l2_dbg(1, debug, sd, "DETECT==DUAL2\n");
1188		}
1189	}
1190	return 0;
1191}
1192
1193static int saa717x_log_status(struct v4l2_subdev *sd)
1194{
1195	struct saa717x_state *state = to_state(sd);
1196
1197	v4l2_ctrl_handler_log_status(&state->hdl, sd->name);
1198	return 0;
1199}
1200
1201/* ----------------------------------------------------------------------- */
1202
1203static const struct v4l2_ctrl_ops saa717x_ctrl_ops = {
1204	.s_ctrl = saa717x_s_ctrl,
1205};
1206
1207static const struct v4l2_subdev_core_ops saa717x_core_ops = {
1208#ifdef CONFIG_VIDEO_ADV_DEBUG
1209	.g_register = saa717x_g_register,
1210	.s_register = saa717x_s_register,
1211#endif
1212	.s_std = saa717x_s_std,
1213	.g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
1214	.try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
1215	.s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
1216	.g_ctrl = v4l2_subdev_g_ctrl,
1217	.s_ctrl = v4l2_subdev_s_ctrl,
1218	.queryctrl = v4l2_subdev_queryctrl,
1219	.querymenu = v4l2_subdev_querymenu,
1220	.log_status = saa717x_log_status,
1221};
1222
1223static const struct v4l2_subdev_tuner_ops saa717x_tuner_ops = {
1224	.g_tuner = saa717x_g_tuner,
1225	.s_tuner = saa717x_s_tuner,
1226	.s_radio = saa717x_s_radio,
1227};
1228
1229static const struct v4l2_subdev_video_ops saa717x_video_ops = {
1230	.s_routing = saa717x_s_video_routing,
1231	.s_mbus_fmt = saa717x_s_mbus_fmt,
1232	.s_stream = saa717x_s_stream,
1233};
1234
1235static const struct v4l2_subdev_audio_ops saa717x_audio_ops = {
1236	.s_routing = saa717x_s_audio_routing,
1237};
1238
1239static const struct v4l2_subdev_ops saa717x_ops = {
1240	.core = &saa717x_core_ops,
1241	.tuner = &saa717x_tuner_ops,
1242	.audio = &saa717x_audio_ops,
1243	.video = &saa717x_video_ops,
1244};
1245
1246/* ----------------------------------------------------------------------- */
1247
1248
1249/* i2c implementation */
1250
1251/* ----------------------------------------------------------------------- */
1252static int saa717x_probe(struct i2c_client *client,
1253			 const struct i2c_device_id *did)
1254{
1255	struct saa717x_state *decoder;
1256	struct v4l2_ctrl_handler *hdl;
1257	struct v4l2_subdev *sd;
1258	u8 id = 0;
1259	char *p = "";
1260
1261	/* Check if the adapter supports the needed features */
1262	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
1263		return -EIO;
1264
1265	decoder = kzalloc(sizeof(struct saa717x_state), GFP_KERNEL);
1266	if (decoder == NULL)
1267		return -ENOMEM;
1268
1269	sd = &decoder->sd;
1270	v4l2_i2c_subdev_init(sd, client, &saa717x_ops);
1271
1272	if (saa717x_write(sd, 0x5a4, 0xfe) &&
1273			saa717x_write(sd, 0x5a5, 0x0f) &&
1274			saa717x_write(sd, 0x5a6, 0x00) &&
1275			saa717x_write(sd, 0x5a7, 0x01))
1276		id = saa717x_read(sd, 0x5a0);
1277	if (id != 0xc2 && id != 0x32 && id != 0xf2 && id != 0x6c) {
1278		v4l2_dbg(1, debug, sd, "saa717x not found (id=%02x)\n", id);
1279		kfree(decoder);
1280		return -ENODEV;
1281	}
1282	if (id == 0xc2)
1283		p = "saa7173";
1284	else if (id == 0x32)
1285		p = "saa7174A";
1286	else if (id == 0x6c)
1287		p = "saa7174HL";
1288	else
1289		p = "saa7171";
1290	v4l2_info(sd, "%s found @ 0x%x (%s)\n", p,
1291			client->addr << 1, client->adapter->name);
1292
1293	hdl = &decoder->hdl;
1294	v4l2_ctrl_handler_init(hdl, 9);
1295	/* add in ascending ID order */
1296	v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops,
1297			V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
1298	v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops,
1299			V4L2_CID_CONTRAST, 0, 255, 1, 68);
1300	v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops,
1301			V4L2_CID_SATURATION, 0, 255, 1, 64);
1302	v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops,
1303			V4L2_CID_HUE, -128, 127, 1, 0);
1304	v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops,
1305			V4L2_CID_AUDIO_VOLUME, 0, 65535, 65535 / 100, 42000);
1306	v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops,
1307			V4L2_CID_AUDIO_BALANCE, 0, 65535, 65535 / 100, 32768);
1308	v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops,
1309			V4L2_CID_AUDIO_BASS, -16, 15, 1, 0);
1310	v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops,
1311			V4L2_CID_AUDIO_TREBLE, -16, 15, 1, 0);
1312	v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops,
1313			V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
1314	sd->ctrl_handler = hdl;
1315	if (hdl->error) {
1316		int err = hdl->error;
1317
1318		v4l2_ctrl_handler_free(hdl);
1319		kfree(decoder);
1320		return err;
1321	}
1322
1323	decoder->std = V4L2_STD_NTSC;
1324	decoder->input = -1;
1325	decoder->enable = 1;
1326
1327	/* FIXME!! */
1328	decoder->playback = 0;	/* initially capture mode used */
1329	decoder->audio = 1; /* DECODER_AUDIO_48_KHZ */
1330
1331	decoder->audio_input = 2; /* FIXME!! */
1332
1333	decoder->tuner_audio_mode = TUNER_AUDIO_STEREO;
1334	/* set volume, bass and treble */
1335	decoder->audio_main_vol_l = 6;
1336	decoder->audio_main_vol_r = 6;
1337
1338	v4l2_dbg(1, debug, sd, "writing init values\n");
1339
1340	/* FIXME!! */
1341	saa717x_write_regs(sd, reg_init_initialize);
1342
1343	v4l2_ctrl_handler_setup(hdl);
1344
1345	set_current_state(TASK_INTERRUPTIBLE);
1346	schedule_timeout(2*HZ);
1347	return 0;
1348}
1349
1350static int saa717x_remove(struct i2c_client *client)
1351{
1352	struct v4l2_subdev *sd = i2c_get_clientdata(client);
1353
1354	v4l2_device_unregister_subdev(sd);
1355	v4l2_ctrl_handler_free(sd->ctrl_handler);
1356	kfree(to_state(sd));
1357	return 0;
1358}
1359
1360/* ----------------------------------------------------------------------- */
1361
1362static const struct i2c_device_id saa717x_id[] = {
1363	{ "saa717x", 0 },
1364	{ }
1365};
1366MODULE_DEVICE_TABLE(i2c, saa717x_id);
1367
1368static struct i2c_driver saa717x_driver = {
1369	.driver = {
1370		.owner	= THIS_MODULE,
1371		.name	= "saa717x",
1372	},
1373	.probe		= saa717x_probe,
1374	.remove		= saa717x_remove,
1375	.id_table	= saa717x_id,
1376};
1377
1378static __init int init_saa717x(void)
1379{
1380	return i2c_add_driver(&saa717x_driver);
1381}
1382
1383static __exit void exit_saa717x(void)
1384{
1385	i2c_del_driver(&saa717x_driver);
1386}
1387
1388module_init(init_saa717x);
1389module_exit(exit_saa717x);