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