Blame view

drivers/media/video/saa7110.c 13.9 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
  /*
   * saa7110 - Philips SAA7110(A) video decoder driver
   *
   * Copyright (C) 1998 Pauline Middelink <middelin@polyware.nl>
   *
   * Copyright (C) 1999 Wolfgang Scherr <scherr@net4you.net>
   * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
   *    - some corrections for Pinnacle Systems Inc. DC10plus card.
   *
   * Changes by Ronald Bultje <rbultje@ronald.bitfreak.net>
   *    - moved over to linux>=2.4.x i2c protocol (1/1/2003)
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; either version 2 of the License, or
   * (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   */
  
  #include <linux/module.h>
  #include <linux/init.h>
  #include <linux/types.h>
  #include <linux/delay.h>
  #include <linux/slab.h>
  #include <linux/wait.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34
  #include <asm/uaccess.h>
85ede69fe   Hans Verkuil   V4L/DVB (9204): s...
35
  #include <linux/i2c.h>
e7946844e   Hans Verkuil   V4L/DVB (10724): ...
36
37
38
  #include <linux/videodev2.h>
  #include <media/v4l2-device.h>
  #include <media/v4l2-chip-ident.h>
4744ebf63   Hans Verkuil   [media] saa7110: ...
39
  #include <media/v4l2-ctrls.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40
41
42
43
  
  MODULE_DESCRIPTION("Philips SAA7110 video decoder driver");
  MODULE_AUTHOR("Pauline Middelink");
  MODULE_LICENSE("GPL");
e7946844e   Hans Verkuil   V4L/DVB (10724): ...
44

ff699e6bd   Douglas Schilling Landgraf   V4L/DVB (7094): ...
45
  static int debug;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46
47
  module_param(debug, int, 0);
  MODULE_PARM_DESC(debug, "Debug level (0-1)");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
48
  #define SAA7110_MAX_INPUT	9	/* 6 CVBS, 3 SVHS */
8182ff69f   Jean Delvare   V4L/DVB (9372): M...
49
  #define SAA7110_MAX_OUTPUT	1	/* 1 YUV */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
50

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51
52
53
  #define SAA7110_NR_REG		0x35
  
  struct saa7110 {
e7946844e   Hans Verkuil   V4L/DVB (10724): ...
54
  	struct v4l2_subdev sd;
4744ebf63   Hans Verkuil   [media] saa7110: ...
55
  	struct v4l2_ctrl_handler hdl;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
56
  	u8 reg[SAA7110_NR_REG];
107063c61   Hans Verkuil   V4L/DVB (10714): ...
57
  	v4l2_std_id norm;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
58
59
  	int input;
  	int enable;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
60
61
62
  
  	wait_queue_head_t wq;
  };
e7946844e   Hans Verkuil   V4L/DVB (10724): ...
63
64
65
66
  static inline struct saa7110 *to_saa7110(struct v4l2_subdev *sd)
  {
  	return container_of(sd, struct saa7110, sd);
  }
4744ebf63   Hans Verkuil   [media] saa7110: ...
67
68
69
70
  static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
  {
  	return &container_of(ctrl->handler, struct saa7110, hdl)->sd;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
71
72
73
  /* ----------------------------------------------------------------------- */
  /* I2C support functions						   */
  /* ----------------------------------------------------------------------- */
e7946844e   Hans Verkuil   V4L/DVB (10724): ...
74
  static int saa7110_write(struct v4l2_subdev *sd, u8 reg, u8 value)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
75
  {
e7946844e   Hans Verkuil   V4L/DVB (10724): ...
76
77
  	struct i2c_client *client = v4l2_get_subdevdata(sd);
  	struct saa7110 *decoder = to_saa7110(sd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
78
79
80
81
  
  	decoder->reg[reg] = value;
  	return i2c_smbus_write_byte_data(client, reg, value);
  }
e7946844e   Hans Verkuil   V4L/DVB (10724): ...
82
  static int saa7110_write_block(struct v4l2_subdev *sd, const u8 *data, unsigned int len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
83
  {
e7946844e   Hans Verkuil   V4L/DVB (10724): ...
84
85
  	struct i2c_client *client = v4l2_get_subdevdata(sd);
  	struct saa7110 *decoder = to_saa7110(sd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
86
87
88
89
90
91
92
93
94
95
  	int ret = -1;
  	u8 reg = *data;		/* first register to write to */
  
  	/* Sanity check */
  	if (reg + (len - 1) > SAA7110_NR_REG)
  		return ret;
  
  	/* the saa7110 has an autoincrement function, use it if
  	 * the adapter understands raw I2C */
  	if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
9aa45e34d   Jean Delvare   V4L/DVB (3568k): ...
96
  		ret = i2c_master_send(client, data, len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
97
98
99
100
101
  
  		/* Cache the written data */
  		memcpy(decoder->reg + reg, data + 1, len - 1);
  	} else {
  		for (++data, --len; len; len--) {
e7946844e   Hans Verkuil   V4L/DVB (10724): ...
102
  			ret = saa7110_write(sd, reg++, *data++);
85ede69fe   Hans Verkuil   V4L/DVB (9204): s...
103
  			if (ret < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
104
105
106
107
108
109
  				break;
  		}
  	}
  
  	return ret;
  }
e7946844e   Hans Verkuil   V4L/DVB (10724): ...
110
  static inline int saa7110_read(struct v4l2_subdev *sd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
111
  {
e7946844e   Hans Verkuil   V4L/DVB (10724): ...
112
  	struct i2c_client *client = v4l2_get_subdevdata(sd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
113
114
115
116
117
118
  	return i2c_smbus_read_byte(client);
  }
  
  /* ----------------------------------------------------------------------- */
  /* SAA7110 functions							   */
  /* ----------------------------------------------------------------------- */
e7946844e   Hans Verkuil   V4L/DVB (10724): ...
119
120
  #define FRESP_06H_COMPST 0x03	/*0x13*/
  #define FRESP_06H_SVIDEO 0x83	/*0xC0*/
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
121

e7946844e   Hans Verkuil   V4L/DVB (10724): ...
122
  static int saa7110_selmux(struct v4l2_subdev *sd, int chan)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
  {
  	static const unsigned char modes[9][8] = {
  		/* mode 0 */
  		{FRESP_06H_COMPST, 0xD9, 0x17, 0x40, 0x03,
  			      0x44, 0x75, 0x16},
  		/* mode 1 */
  		{FRESP_06H_COMPST, 0xD8, 0x17, 0x40, 0x03,
  			      0x44, 0x75, 0x16},
  		/* mode 2 */
  		{FRESP_06H_COMPST, 0xBA, 0x07, 0x91, 0x03,
  			      0x60, 0xB5, 0x05},
  		/* mode 3 */
  		{FRESP_06H_COMPST, 0xB8, 0x07, 0x91, 0x03,
  			      0x60, 0xB5, 0x05},
  		/* mode 4 */
  		{FRESP_06H_COMPST, 0x7C, 0x07, 0xD2, 0x83,
  			      0x60, 0xB5, 0x03},
  		/* mode 5 */
  		{FRESP_06H_COMPST, 0x78, 0x07, 0xD2, 0x83,
  			      0x60, 0xB5, 0x03},
  		/* mode 6 */
  		{FRESP_06H_SVIDEO, 0x59, 0x17, 0x42, 0xA3,
  			      0x44, 0x75, 0x12},
  		/* mode 7 */
  		{FRESP_06H_SVIDEO, 0x9A, 0x17, 0xB1, 0x13,
  			      0x60, 0xB5, 0x14},
  		/* mode 8 */
  		{FRESP_06H_SVIDEO, 0x3C, 0x27, 0xC1, 0x23,
  			      0x44, 0x75, 0x21}
  	};
e7946844e   Hans Verkuil   V4L/DVB (10724): ...
153
  	struct saa7110 *decoder = to_saa7110(sd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
154
  	const unsigned char *ptr = modes[chan];
e7946844e   Hans Verkuil   V4L/DVB (10724): ...
155
156
157
158
159
160
161
162
  	saa7110_write(sd, 0x06, ptr[0]);	/* Luminance control    */
  	saa7110_write(sd, 0x20, ptr[1]);	/* Analog Control #1    */
  	saa7110_write(sd, 0x21, ptr[2]);	/* Analog Control #2    */
  	saa7110_write(sd, 0x22, ptr[3]);	/* Mixer Control #1     */
  	saa7110_write(sd, 0x2C, ptr[4]);	/* Mixer Control #2     */
  	saa7110_write(sd, 0x30, ptr[5]);	/* ADCs gain control    */
  	saa7110_write(sd, 0x31, ptr[6]);	/* Mixer Control #3     */
  	saa7110_write(sd, 0x21, ptr[7]);	/* Analog Control #2    */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
163
164
165
166
167
168
169
170
171
172
173
174
175
176
  	decoder->input = chan;
  
  	return 0;
  }
  
  static const unsigned char initseq[1 + SAA7110_NR_REG] = {
  	0, 0x4C, 0x3C, 0x0D, 0xEF, 0xBD, 0xF2, 0x03, 0x00,
  	/* 0x08 */ 0xF8, 0xF8, 0x60, 0x60, 0x00, 0x86, 0x18, 0x90,
  	/* 0x10 */ 0x00, 0x59, 0x40, 0x46, 0x42, 0x1A, 0xFF, 0xDA,
  	/* 0x18 */ 0xF2, 0x8B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  	/* 0x20 */ 0xD9, 0x16, 0x40, 0x41, 0x80, 0x41, 0x80, 0x4F,
  	/* 0x28 */ 0xFE, 0x01, 0xCF, 0x0F, 0x03, 0x01, 0x03, 0x0C,
  	/* 0x30 */ 0x44, 0x71, 0x02, 0x8C, 0x02
  };
e7946844e   Hans Verkuil   V4L/DVB (10724): ...
177
  static v4l2_std_id determine_norm(struct v4l2_subdev *sd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
178
179
  {
  	DEFINE_WAIT(wait);
e7946844e   Hans Verkuil   V4L/DVB (10724): ...
180
  	struct saa7110 *decoder = to_saa7110(sd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
181
182
183
  	int status;
  
  	/* mode changed, start automatic detection */
e7946844e   Hans Verkuil   V4L/DVB (10724): ...
184
185
  	saa7110_write_block(sd, initseq, sizeof(initseq));
  	saa7110_selmux(sd, decoder->input);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
186
  	prepare_to_wait(&decoder->wq, &wait, TASK_UNINTERRUPTIBLE);
09df5cbe4   Mauro Carvalho Chehab   V4L/DVB (5858): U...
187
  	schedule_timeout(msecs_to_jiffies(250));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
188
  	finish_wait(&decoder->wq, &wait);
e7946844e   Hans Verkuil   V4L/DVB (10724): ...
189
  	status = saa7110_read(sd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
190
  	if (status & 0x40) {
e7946844e   Hans Verkuil   V4L/DVB (10724): ...
191
192
193
  		v4l2_dbg(1, debug, sd, "status=0x%02x (no signal)
  ", status);
  		return decoder->norm;	/* no change*/
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
194
195
  	}
  	if ((status & 3) == 0) {
e7946844e   Hans Verkuil   V4L/DVB (10724): ...
196
  		saa7110_write(sd, 0x06, 0x83);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
197
  		if (status & 0x20) {
e7946844e   Hans Verkuil   V4L/DVB (10724): ...
198
199
200
  			v4l2_dbg(1, debug, sd, "status=0x%02x (NTSC/no color)
  ", status);
  			/*saa7110_write(sd,0x2E,0x81);*/
107063c61   Hans Verkuil   V4L/DVB (10714): ...
201
  			return V4L2_STD_NTSC;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
202
  		}
e7946844e   Hans Verkuil   V4L/DVB (10724): ...
203
204
205
  		v4l2_dbg(1, debug, sd, "status=0x%02x (PAL/no color)
  ", status);
  		/*saa7110_write(sd,0x2E,0x9A);*/
107063c61   Hans Verkuil   V4L/DVB (10714): ...
206
  		return V4L2_STD_PAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
207
  	}
e7946844e   Hans Verkuil   V4L/DVB (10724): ...
208
  	/*saa7110_write(sd,0x06,0x03);*/
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
209
  	if (status & 0x20) {	/* 60Hz */
e7946844e   Hans Verkuil   V4L/DVB (10724): ...
210
211
212
213
214
215
  		v4l2_dbg(1, debug, sd, "status=0x%02x (NTSC)
  ", status);
  		saa7110_write(sd, 0x0D, 0x86);
  		saa7110_write(sd, 0x0F, 0x50);
  		saa7110_write(sd, 0x11, 0x2C);
  		/*saa7110_write(sd,0x2E,0x81);*/
107063c61   Hans Verkuil   V4L/DVB (10714): ...
216
  		return V4L2_STD_NTSC;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
217
218
219
  	}
  
  	/* 50Hz -> PAL/SECAM */
e7946844e   Hans Verkuil   V4L/DVB (10724): ...
220
221
222
223
  	saa7110_write(sd, 0x0D, 0x86);
  	saa7110_write(sd, 0x0F, 0x10);
  	saa7110_write(sd, 0x11, 0x59);
  	/*saa7110_write(sd,0x2E,0x9A);*/
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
224
225
  
  	prepare_to_wait(&decoder->wq, &wait, TASK_UNINTERRUPTIBLE);
09df5cbe4   Mauro Carvalho Chehab   V4L/DVB (5858): U...
226
  	schedule_timeout(msecs_to_jiffies(250));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
227
  	finish_wait(&decoder->wq, &wait);
e7946844e   Hans Verkuil   V4L/DVB (10724): ...
228
  	status = saa7110_read(sd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
229
  	if ((status & 0x03) == 0x01) {
e7946844e   Hans Verkuil   V4L/DVB (10724): ...
230
231
232
  		v4l2_dbg(1, debug, sd, "status=0x%02x (SECAM)
  ", status);
  		saa7110_write(sd, 0x0D, 0x87);
107063c61   Hans Verkuil   V4L/DVB (10714): ...
233
  		return V4L2_STD_SECAM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
234
  	}
e7946844e   Hans Verkuil   V4L/DVB (10724): ...
235
236
  	v4l2_dbg(1, debug, sd, "status=0x%02x (PAL)
  ", status);
107063c61   Hans Verkuil   V4L/DVB (10714): ...
237
  	return V4L2_STD_PAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
238
  }
e7946844e   Hans Verkuil   V4L/DVB (10724): ...
239
  static int saa7110_g_input_status(struct v4l2_subdev *sd, u32 *pstatus)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
240
  {
e7946844e   Hans Verkuil   V4L/DVB (10724): ...
241
242
243
244
245
246
  	struct saa7110 *decoder = to_saa7110(sd);
  	int res = V4L2_IN_ST_NO_SIGNAL;
  	int status = saa7110_read(sd);
  
  	v4l2_dbg(1, debug, sd, "status=0x%02x norm=%llx
  ",
cc5cef8ea   Hans Verkuil   V4L/DVB (10914): ...
247
  		       status, (unsigned long long)decoder->norm);
e7946844e   Hans Verkuil   V4L/DVB (10724): ...
248
249
250
251
252
253
254
255
  	if (!(status & 0x40))
  		res = 0;
  	if (!(status & 0x03))
  		res |= V4L2_IN_ST_NO_COLOR;
  
  	*pstatus = res;
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
256

e7946844e   Hans Verkuil   V4L/DVB (10724): ...
257
258
259
260
261
  static int saa7110_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
  {
  	*(v4l2_std_id *)std = determine_norm(sd);
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
262

e7946844e   Hans Verkuil   V4L/DVB (10724): ...
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
  static int saa7110_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
  {
  	struct saa7110 *decoder = to_saa7110(sd);
  
  	if (decoder->norm != std) {
  		decoder->norm = std;
  		/*saa7110_write(sd, 0x06, 0x03);*/
  		if (std & V4L2_STD_NTSC) {
  			saa7110_write(sd, 0x0D, 0x86);
  			saa7110_write(sd, 0x0F, 0x50);
  			saa7110_write(sd, 0x11, 0x2C);
  			/*saa7110_write(sd, 0x2E, 0x81);*/
  			v4l2_dbg(1, debug, sd, "switched to NTSC
  ");
  		} else if (std & V4L2_STD_PAL) {
  			saa7110_write(sd, 0x0D, 0x86);
  			saa7110_write(sd, 0x0F, 0x10);
  			saa7110_write(sd, 0x11, 0x59);
  			/*saa7110_write(sd, 0x2E, 0x9A);*/
  			v4l2_dbg(1, debug, sd, "switched to PAL
  ");
  		} else if (std & V4L2_STD_SECAM) {
  			saa7110_write(sd, 0x0D, 0x87);
  			saa7110_write(sd, 0x0F, 0x10);
  			saa7110_write(sd, 0x11, 0x59);
  			/*saa7110_write(sd, 0x2E, 0x9A);*/
  			v4l2_dbg(1, debug, sd, "switched to SECAM
  ");
  		} else {
  			return -EINVAL;
  		}
  	}
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
297

5325b4272   Hans Verkuil   V4L/DVB (11380): ...
298
299
  static int saa7110_s_routing(struct v4l2_subdev *sd,
  			     u32 input, u32 output, u32 config)
e7946844e   Hans Verkuil   V4L/DVB (10724): ...
300
301
  {
  	struct saa7110 *decoder = to_saa7110(sd);
f14a2972e   Roel Kluin   V4L/DVB (13241): ...
302
  	if (input >= SAA7110_MAX_INPUT) {
5325b4272   Hans Verkuil   V4L/DVB (11380): ...
303
304
  		v4l2_dbg(1, debug, sd, "input=%d not available
  ", input);
e7946844e   Hans Verkuil   V4L/DVB (10724): ...
305
  		return -EINVAL;
85ede69fe   Hans Verkuil   V4L/DVB (9204): s...
306
  	}
5325b4272   Hans Verkuil   V4L/DVB (11380): ...
307
308
309
310
  	if (decoder->input != input) {
  		saa7110_selmux(sd, input);
  		v4l2_dbg(1, debug, sd, "switched to input=%d
  ", input);
e7946844e   Hans Verkuil   V4L/DVB (10724): ...
311
312
313
  	}
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
314

e7946844e   Hans Verkuil   V4L/DVB (10724): ...
315
316
317
318
319
320
321
322
323
  static int saa7110_s_stream(struct v4l2_subdev *sd, int enable)
  {
  	struct saa7110 *decoder = to_saa7110(sd);
  
  	if (decoder->enable != enable) {
  		decoder->enable = enable;
  		saa7110_write(sd, 0x0E, enable ? 0x18 : 0x80);
  		v4l2_dbg(1, debug, sd, "YUV %s
  ", enable ? "on" : "off");
107063c61   Hans Verkuil   V4L/DVB (10714): ...
324
  	}
e7946844e   Hans Verkuil   V4L/DVB (10724): ...
325
326
  	return 0;
  }
107063c61   Hans Verkuil   V4L/DVB (10714): ...
327

4744ebf63   Hans Verkuil   [media] saa7110: ...
328
  static int saa7110_s_ctrl(struct v4l2_ctrl *ctrl)
e7946844e   Hans Verkuil   V4L/DVB (10724): ...
329
  {
4744ebf63   Hans Verkuil   [media] saa7110: ...
330
  	struct v4l2_subdev *sd = to_sd(ctrl);
e7946844e   Hans Verkuil   V4L/DVB (10724): ...
331
332
333
  
  	switch (ctrl->id) {
  	case V4L2_CID_BRIGHTNESS:
4744ebf63   Hans Verkuil   [media] saa7110: ...
334
  		saa7110_write(sd, 0x19, ctrl->val);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
335
  		break;
e7946844e   Hans Verkuil   V4L/DVB (10724): ...
336
  	case V4L2_CID_CONTRAST:
4744ebf63   Hans Verkuil   [media] saa7110: ...
337
  		saa7110_write(sd, 0x13, ctrl->val);
107063c61   Hans Verkuil   V4L/DVB (10714): ...
338
  		break;
e7946844e   Hans Verkuil   V4L/DVB (10724): ...
339
  	case V4L2_CID_SATURATION:
4744ebf63   Hans Verkuil   [media] saa7110: ...
340
  		saa7110_write(sd, 0x12, ctrl->val);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
341
  		break;
e7946844e   Hans Verkuil   V4L/DVB (10724): ...
342
  	case V4L2_CID_HUE:
4744ebf63   Hans Verkuil   [media] saa7110: ...
343
  		saa7110_write(sd, 0x07, ctrl->val);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
344
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
345
  	default:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
346
347
348
349
  		return -EINVAL;
  	}
  	return 0;
  }
e7946844e   Hans Verkuil   V4L/DVB (10724): ...
350
351
352
353
354
355
  static int saa7110_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
  {
  	struct i2c_client *client = v4l2_get_subdevdata(sd);
  
  	return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SAA7110, 0);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
356
  /* ----------------------------------------------------------------------- */
4744ebf63   Hans Verkuil   [media] saa7110: ...
357
358
359
  static const struct v4l2_ctrl_ops saa7110_ctrl_ops = {
  	.s_ctrl = saa7110_s_ctrl,
  };
e7946844e   Hans Verkuil   V4L/DVB (10724): ...
360
361
  static const struct v4l2_subdev_core_ops saa7110_core_ops = {
  	.g_chip_ident = saa7110_g_chip_ident,
4744ebf63   Hans Verkuil   [media] saa7110: ...
362
363
364
365
366
367
368
  	.g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
  	.try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
  	.s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
  	.g_ctrl = v4l2_subdev_g_ctrl,
  	.s_ctrl = v4l2_subdev_s_ctrl,
  	.queryctrl = v4l2_subdev_queryctrl,
  	.querymenu = v4l2_subdev_querymenu,
e7946844e   Hans Verkuil   V4L/DVB (10724): ...
369
370
  	.s_std = saa7110_s_std,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
371

e7946844e   Hans Verkuil   V4L/DVB (10724): ...
372
373
374
375
376
377
378
379
380
  static const struct v4l2_subdev_video_ops saa7110_video_ops = {
  	.s_routing = saa7110_s_routing,
  	.s_stream = saa7110_s_stream,
  	.querystd = saa7110_querystd,
  	.g_input_status = saa7110_g_input_status,
  };
  
  static const struct v4l2_subdev_ops saa7110_ops = {
  	.core = &saa7110_core_ops,
e7946844e   Hans Verkuil   V4L/DVB (10724): ...
381
382
383
384
  	.video = &saa7110_video_ops,
  };
  
  /* ----------------------------------------------------------------------- */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
385

85ede69fe   Hans Verkuil   V4L/DVB (9204): s...
386
387
  static int saa7110_probe(struct i2c_client *client,
  			const struct i2c_device_id *id)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
388
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
389
  	struct saa7110 *decoder;
e7946844e   Hans Verkuil   V4L/DVB (10724): ...
390
  	struct v4l2_subdev *sd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
391
  	int rv;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
392
  	/* Check if the adapter supports the needed features */
85ede69fe   Hans Verkuil   V4L/DVB (9204): s...
393
394
395
  	if (!i2c_check_functionality(client->adapter,
  		I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
  		return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
396

85ede69fe   Hans Verkuil   V4L/DVB (9204): s...
397
398
399
  	v4l_info(client, "chip found @ 0x%x (%s)
  ",
  			client->addr << 1, client->adapter->name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
400

7408187d2   Panagiotis Issaris   (7408187d223f63d4...
401
  	decoder = kzalloc(sizeof(struct saa7110), GFP_KERNEL);
85ede69fe   Hans Verkuil   V4L/DVB (9204): s...
402
  	if (!decoder)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
403
  		return -ENOMEM;
e7946844e   Hans Verkuil   V4L/DVB (10724): ...
404
405
  	sd = &decoder->sd;
  	v4l2_i2c_subdev_init(sd, client, &saa7110_ops);
107063c61   Hans Verkuil   V4L/DVB (10714): ...
406
  	decoder->norm = V4L2_STD_PAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
407
408
  	decoder->input = 0;
  	decoder->enable = 1;
4744ebf63   Hans Verkuil   [media] saa7110: ...
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
  	v4l2_ctrl_handler_init(&decoder->hdl, 2);
  	v4l2_ctrl_new_std(&decoder->hdl, &saa7110_ctrl_ops,
  		V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
  	v4l2_ctrl_new_std(&decoder->hdl, &saa7110_ctrl_ops,
  		V4L2_CID_CONTRAST, 0, 127, 1, 64);
  	v4l2_ctrl_new_std(&decoder->hdl, &saa7110_ctrl_ops,
  		V4L2_CID_SATURATION, 0, 127, 1, 64);
  	v4l2_ctrl_new_std(&decoder->hdl, &saa7110_ctrl_ops,
  		V4L2_CID_HUE, -128, 127, 1, 0);
  	sd->ctrl_handler = &decoder->hdl;
  	if (decoder->hdl.error) {
  		int err = decoder->hdl.error;
  
  		v4l2_ctrl_handler_free(&decoder->hdl);
  		kfree(decoder);
  		return err;
  	}
  	v4l2_ctrl_handler_setup(&decoder->hdl);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
427
  	init_waitqueue_head(&decoder->wq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
428

e7946844e   Hans Verkuil   V4L/DVB (10724): ...
429
  	rv = saa7110_write_block(sd, initseq, sizeof(initseq));
85ede69fe   Hans Verkuil   V4L/DVB (9204): s...
430
  	if (rv < 0) {
e7946844e   Hans Verkuil   V4L/DVB (10724): ...
431
432
  		v4l2_dbg(1, debug, sd, "init status %d
  ", rv);
85ede69fe   Hans Verkuil   V4L/DVB (9204): s...
433
  	} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
434
  		int ver, status;
e7946844e   Hans Verkuil   V4L/DVB (10724): ...
435
436
437
438
439
440
441
442
443
  		saa7110_write(sd, 0x21, 0x10);
  		saa7110_write(sd, 0x0e, 0x18);
  		saa7110_write(sd, 0x0D, 0x04);
  		ver = saa7110_read(sd);
  		saa7110_write(sd, 0x0D, 0x06);
  		/*mdelay(150);*/
  		status = saa7110_read(sd);
  		v4l2_dbg(1, debug, sd, "version %x, status=0x%02x
  ",
85ede69fe   Hans Verkuil   V4L/DVB (9204): s...
444
  			       ver, status);
e7946844e   Hans Verkuil   V4L/DVB (10724): ...
445
446
447
448
  		saa7110_write(sd, 0x0D, 0x86);
  		saa7110_write(sd, 0x0F, 0x10);
  		saa7110_write(sd, 0x11, 0x59);
  		/*saa7110_write(sd, 0x2E, 0x9A);*/
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
449
  	}
e7946844e   Hans Verkuil   V4L/DVB (10724): ...
450
451
  	/*saa7110_selmux(sd,0);*/
  	/*determine_norm(sd);*/
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
452
453
454
455
  	/* setup and implicit mode 0 select has been performed */
  
  	return 0;
  }
85ede69fe   Hans Verkuil   V4L/DVB (9204): s...
456
  static int saa7110_remove(struct i2c_client *client)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
457
  {
e7946844e   Hans Verkuil   V4L/DVB (10724): ...
458
  	struct v4l2_subdev *sd = i2c_get_clientdata(client);
4744ebf63   Hans Verkuil   [media] saa7110: ...
459
  	struct saa7110 *decoder = to_saa7110(sd);
e7946844e   Hans Verkuil   V4L/DVB (10724): ...
460
461
  
  	v4l2_device_unregister_subdev(sd);
4744ebf63   Hans Verkuil   [media] saa7110: ...
462
463
  	v4l2_ctrl_handler_free(&decoder->hdl);
  	kfree(decoder);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
464
465
466
467
  	return 0;
  }
  
  /* ----------------------------------------------------------------------- */
85ede69fe   Hans Verkuil   V4L/DVB (9204): s...
468
469
470
471
472
  static const struct i2c_device_id saa7110_id[] = {
  	{ "saa7110", 0 },
  	{ }
  };
  MODULE_DEVICE_TABLE(i2c, saa7110_id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
473

ff6e5422e   Hans Verkuil   V4L/DVB: saa7110:...
474
475
476
477
478
479
480
481
  static struct i2c_driver saa7110_driver = {
  	.driver = {
  		.owner	= THIS_MODULE,
  		.name	= "saa7110",
  	},
  	.probe		= saa7110_probe,
  	.remove		= saa7110_remove,
  	.id_table	= saa7110_id,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
482
  };
ff6e5422e   Hans Verkuil   V4L/DVB: saa7110:...
483
484
485
486
487
488
489
490
491
492
493
494
495
  
  static __init int init_saa7110(void)
  {
  	return i2c_add_driver(&saa7110_driver);
  }
  
  static __exit void exit_saa7110(void)
  {
  	i2c_del_driver(&saa7110_driver);
  }
  
  module_init(init_saa7110);
  module_exit(exit_saa7110);