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