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