aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/saa7110.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/saa7110.c')
-rw-r--r--drivers/media/video/saa7110.c472
1 files changed, 249 insertions, 223 deletions
diff --git a/drivers/media/video/saa7110.c b/drivers/media/video/saa7110.c
index 37860698f782..df4e08d2dceb 100644
--- a/drivers/media/video/saa7110.c
+++ b/drivers/media/video/saa7110.c
@@ -33,15 +33,16 @@
33#include <linux/wait.h> 33#include <linux/wait.h>
34#include <asm/uaccess.h> 34#include <asm/uaccess.h>
35#include <linux/i2c.h> 35#include <linux/i2c.h>
36#include <linux/videodev.h> 36#include <linux/videodev2.h>
37#include <linux/video_decoder.h> 37#include <media/v4l2-device.h>
38#include <media/v4l2-common.h> 38#include <media/v4l2-chip-ident.h>
39#include <media/v4l2-i2c-drv-legacy.h> 39#include <media/v4l2-i2c-drv.h>
40 40
41MODULE_DESCRIPTION("Philips SAA7110 video decoder driver"); 41MODULE_DESCRIPTION("Philips SAA7110 video decoder driver");
42MODULE_AUTHOR("Pauline Middelink"); 42MODULE_AUTHOR("Pauline Middelink");
43MODULE_LICENSE("GPL"); 43MODULE_LICENSE("GPL");
44 44
45
45static int debug; 46static int debug;
46module_param(debug, int, 0); 47module_param(debug, int, 0);
47MODULE_PARM_DESC(debug, "Debug level (0-1)"); 48MODULE_PARM_DESC(debug, "Debug level (0-1)");
@@ -52,9 +53,10 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)");
52#define SAA7110_NR_REG 0x35 53#define SAA7110_NR_REG 0x35
53 54
54struct saa7110 { 55struct saa7110 {
56 struct v4l2_subdev sd;
55 u8 reg[SAA7110_NR_REG]; 57 u8 reg[SAA7110_NR_REG];
56 58
57 int norm; 59 v4l2_std_id norm;
58 int input; 60 int input;
59 int enable; 61 int enable;
60 int bright; 62 int bright;
@@ -65,20 +67,28 @@ struct saa7110 {
65 wait_queue_head_t wq; 67 wait_queue_head_t wq;
66}; 68};
67 69
70static inline struct saa7110 *to_saa7110(struct v4l2_subdev *sd)
71{
72 return container_of(sd, struct saa7110, sd);
73}
74
68/* ----------------------------------------------------------------------- */ 75/* ----------------------------------------------------------------------- */
69/* I2C support functions */ 76/* I2C support functions */
70/* ----------------------------------------------------------------------- */ 77/* ----------------------------------------------------------------------- */
71 78
72static int saa7110_write(struct i2c_client *client, u8 reg, u8 value) 79static int saa7110_write(struct v4l2_subdev *sd, u8 reg, u8 value)
73{ 80{
74 struct saa7110 *decoder = i2c_get_clientdata(client); 81 struct i2c_client *client = v4l2_get_subdevdata(sd);
82 struct saa7110 *decoder = to_saa7110(sd);
75 83
76 decoder->reg[reg] = value; 84 decoder->reg[reg] = value;
77 return i2c_smbus_write_byte_data(client, reg, value); 85 return i2c_smbus_write_byte_data(client, reg, value);
78} 86}
79 87
80static int saa7110_write_block(struct i2c_client *client, const u8 *data, unsigned int len) 88static int saa7110_write_block(struct v4l2_subdev *sd, const u8 *data, unsigned int len)
81{ 89{
90 struct i2c_client *client = v4l2_get_subdevdata(sd);
91 struct saa7110 *decoder = to_saa7110(sd);
82 int ret = -1; 92 int ret = -1;
83 u8 reg = *data; /* first register to write to */ 93 u8 reg = *data; /* first register to write to */
84 94
@@ -89,15 +99,13 @@ static int saa7110_write_block(struct i2c_client *client, const u8 *data, unsign
89 /* the saa7110 has an autoincrement function, use it if 99 /* the saa7110 has an autoincrement function, use it if
90 * the adapter understands raw I2C */ 100 * the adapter understands raw I2C */
91 if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { 101 if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
92 struct saa7110 *decoder = i2c_get_clientdata(client);
93
94 ret = i2c_master_send(client, data, len); 102 ret = i2c_master_send(client, data, len);
95 103
96 /* Cache the written data */ 104 /* Cache the written data */
97 memcpy(decoder->reg + reg, data + 1, len - 1); 105 memcpy(decoder->reg + reg, data + 1, len - 1);
98 } else { 106 } else {
99 for (++data, --len; len; len--) { 107 for (++data, --len; len; len--) {
100 ret = saa7110_write(client, reg++, *data++); 108 ret = saa7110_write(sd, reg++, *data++);
101 if (ret < 0) 109 if (ret < 0)
102 break; 110 break;
103 } 111 }
@@ -106,8 +114,10 @@ static int saa7110_write_block(struct i2c_client *client, const u8 *data, unsign
106 return ret; 114 return ret;
107} 115}
108 116
109static inline int saa7110_read(struct i2c_client *client) 117static inline int saa7110_read(struct v4l2_subdev *sd)
110{ 118{
119 struct i2c_client *client = v4l2_get_subdevdata(sd);
120
111 return i2c_smbus_read_byte(client); 121 return i2c_smbus_read_byte(client);
112} 122}
113 123
@@ -115,11 +125,11 @@ static inline int saa7110_read(struct i2c_client *client)
115/* SAA7110 functions */ 125/* SAA7110 functions */
116/* ----------------------------------------------------------------------- */ 126/* ----------------------------------------------------------------------- */
117 127
118#define FRESP_06H_COMPST 0x03 //0x13 128#define FRESP_06H_COMPST 0x03 /*0x13*/
119#define FRESP_06H_SVIDEO 0x83 //0xC0 129#define FRESP_06H_SVIDEO 0x83 /*0xC0*/
120 130
121 131
122static int saa7110_selmux(struct i2c_client *client, int chan) 132static int saa7110_selmux(struct v4l2_subdev *sd, int chan)
123{ 133{
124 static const unsigned char modes[9][8] = { 134 static const unsigned char modes[9][8] = {
125 /* mode 0 */ 135 /* mode 0 */
@@ -150,17 +160,17 @@ static int saa7110_selmux(struct i2c_client *client, int chan)
150 {FRESP_06H_SVIDEO, 0x3C, 0x27, 0xC1, 0x23, 160 {FRESP_06H_SVIDEO, 0x3C, 0x27, 0xC1, 0x23,
151 0x44, 0x75, 0x21} 161 0x44, 0x75, 0x21}
152 }; 162 };
153 struct saa7110 *decoder = i2c_get_clientdata(client); 163 struct saa7110 *decoder = to_saa7110(sd);
154 const unsigned char *ptr = modes[chan]; 164 const unsigned char *ptr = modes[chan];
155 165
156 saa7110_write(client, 0x06, ptr[0]); /* Luminance control */ 166 saa7110_write(sd, 0x06, ptr[0]); /* Luminance control */
157 saa7110_write(client, 0x20, ptr[1]); /* Analog Control #1 */ 167 saa7110_write(sd, 0x20, ptr[1]); /* Analog Control #1 */
158 saa7110_write(client, 0x21, ptr[2]); /* Analog Control #2 */ 168 saa7110_write(sd, 0x21, ptr[2]); /* Analog Control #2 */
159 saa7110_write(client, 0x22, ptr[3]); /* Mixer Control #1 */ 169 saa7110_write(sd, 0x22, ptr[3]); /* Mixer Control #1 */
160 saa7110_write(client, 0x2C, ptr[4]); /* Mixer Control #2 */ 170 saa7110_write(sd, 0x2C, ptr[4]); /* Mixer Control #2 */
161 saa7110_write(client, 0x30, ptr[5]); /* ADCs gain control */ 171 saa7110_write(sd, 0x30, ptr[5]); /* ADCs gain control */
162 saa7110_write(client, 0x31, ptr[6]); /* Mixer Control #3 */ 172 saa7110_write(sd, 0x31, ptr[6]); /* Mixer Control #3 */
163 saa7110_write(client, 0x21, ptr[7]); /* Analog Control #2 */ 173 saa7110_write(sd, 0x21, ptr[7]); /* Analog Control #2 */
164 decoder->input = chan; 174 decoder->input = chan;
165 175
166 return 0; 176 return 0;
@@ -176,246 +186,260 @@ static const unsigned char initseq[1 + SAA7110_NR_REG] = {
176 /* 0x30 */ 0x44, 0x71, 0x02, 0x8C, 0x02 186 /* 0x30 */ 0x44, 0x71, 0x02, 0x8C, 0x02
177}; 187};
178 188
179static int determine_norm(struct i2c_client *client) 189static v4l2_std_id determine_norm(struct v4l2_subdev *sd)
180{ 190{
181 DEFINE_WAIT(wait); 191 DEFINE_WAIT(wait);
182 struct saa7110 *decoder = i2c_get_clientdata(client); 192 struct saa7110 *decoder = to_saa7110(sd);
183 int status; 193 int status;
184 194
185 /* mode changed, start automatic detection */ 195 /* mode changed, start automatic detection */
186 saa7110_write_block(client, initseq, sizeof(initseq)); 196 saa7110_write_block(sd, initseq, sizeof(initseq));
187 saa7110_selmux(client, decoder->input); 197 saa7110_selmux(sd, decoder->input);
188 prepare_to_wait(&decoder->wq, &wait, TASK_UNINTERRUPTIBLE); 198 prepare_to_wait(&decoder->wq, &wait, TASK_UNINTERRUPTIBLE);
189 schedule_timeout(msecs_to_jiffies(250)); 199 schedule_timeout(msecs_to_jiffies(250));
190 finish_wait(&decoder->wq, &wait); 200 finish_wait(&decoder->wq, &wait);
191 status = saa7110_read(client); 201 status = saa7110_read(sd);
192 if (status & 0x40) { 202 if (status & 0x40) {
193 v4l_dbg(1, debug, client, "status=0x%02x (no signal)\n", status); 203 v4l2_dbg(1, debug, sd, "status=0x%02x (no signal)\n", status);
194 return decoder->norm; // no change 204 return decoder->norm; /* no change*/
195 } 205 }
196 if ((status & 3) == 0) { 206 if ((status & 3) == 0) {
197 saa7110_write(client, 0x06, 0x83); 207 saa7110_write(sd, 0x06, 0x83);
198 if (status & 0x20) { 208 if (status & 0x20) {
199 v4l_dbg(1, debug, client, "status=0x%02x (NTSC/no color)\n", status); 209 v4l2_dbg(1, debug, sd, "status=0x%02x (NTSC/no color)\n", status);
200 //saa7110_write(client,0x2E,0x81); 210 /*saa7110_write(sd,0x2E,0x81);*/
201 return VIDEO_MODE_NTSC; 211 return V4L2_STD_NTSC;
202 } 212 }
203 v4l_dbg(1, debug, client, "status=0x%02x (PAL/no color)\n", status); 213 v4l2_dbg(1, debug, sd, "status=0x%02x (PAL/no color)\n", status);
204 //saa7110_write(client,0x2E,0x9A); 214 /*saa7110_write(sd,0x2E,0x9A);*/
205 return VIDEO_MODE_PAL; 215 return V4L2_STD_PAL;
206 } 216 }
207 //saa7110_write(client,0x06,0x03); 217 /*saa7110_write(sd,0x06,0x03);*/
208 if (status & 0x20) { /* 60Hz */ 218 if (status & 0x20) { /* 60Hz */
209 v4l_dbg(1, debug, client, "status=0x%02x (NTSC)\n", status); 219 v4l2_dbg(1, debug, sd, "status=0x%02x (NTSC)\n", status);
210 saa7110_write(client, 0x0D, 0x86); 220 saa7110_write(sd, 0x0D, 0x86);
211 saa7110_write(client, 0x0F, 0x50); 221 saa7110_write(sd, 0x0F, 0x50);
212 saa7110_write(client, 0x11, 0x2C); 222 saa7110_write(sd, 0x11, 0x2C);
213 //saa7110_write(client,0x2E,0x81); 223 /*saa7110_write(sd,0x2E,0x81);*/
214 return VIDEO_MODE_NTSC; 224 return V4L2_STD_NTSC;
215 } 225 }
216 226
217 /* 50Hz -> PAL/SECAM */ 227 /* 50Hz -> PAL/SECAM */
218 saa7110_write(client, 0x0D, 0x86); 228 saa7110_write(sd, 0x0D, 0x86);
219 saa7110_write(client, 0x0F, 0x10); 229 saa7110_write(sd, 0x0F, 0x10);
220 saa7110_write(client, 0x11, 0x59); 230 saa7110_write(sd, 0x11, 0x59);
221 //saa7110_write(client,0x2E,0x9A); 231 /*saa7110_write(sd,0x2E,0x9A);*/
222 232
223 prepare_to_wait(&decoder->wq, &wait, TASK_UNINTERRUPTIBLE); 233 prepare_to_wait(&decoder->wq, &wait, TASK_UNINTERRUPTIBLE);
224 schedule_timeout(msecs_to_jiffies(250)); 234 schedule_timeout(msecs_to_jiffies(250));
225 finish_wait(&decoder->wq, &wait); 235 finish_wait(&decoder->wq, &wait);
226 236
227 status = saa7110_read(client); 237 status = saa7110_read(sd);
228 if ((status & 0x03) == 0x01) { 238 if ((status & 0x03) == 0x01) {
229 v4l_dbg(1, debug, client, "status=0x%02x (SECAM)\n", status); 239 v4l2_dbg(1, debug, sd, "status=0x%02x (SECAM)\n", status);
230 saa7110_write(client, 0x0D, 0x87); 240 saa7110_write(sd, 0x0D, 0x87);
231 return VIDEO_MODE_SECAM; 241 return V4L2_STD_SECAM;
232 } 242 }
233 v4l_dbg(1, debug, client, "status=0x%02x (PAL)\n", status); 243 v4l2_dbg(1, debug, sd, "status=0x%02x (PAL)\n", status);
234 return VIDEO_MODE_PAL; 244 return V4L2_STD_PAL;
235} 245}
236 246
237static int 247static int saa7110_g_input_status(struct v4l2_subdev *sd, u32 *pstatus)
238saa7110_command (struct i2c_client *client,
239 unsigned int cmd,
240 void *arg)
241{ 248{
242 struct saa7110 *decoder = i2c_get_clientdata(client); 249 struct saa7110 *decoder = to_saa7110(sd);
243 int v; 250 int res = V4L2_IN_ST_NO_SIGNAL;
251 int status = saa7110_read(sd);
252
253 v4l2_dbg(1, debug, sd, "status=0x%02x norm=%llx\n",
254 status, (unsigned long long)decoder->norm);
255 if (!(status & 0x40))
256 res = 0;
257 if (!(status & 0x03))
258 res |= V4L2_IN_ST_NO_COLOR;
259
260 *pstatus = res;
261 return 0;
262}
244 263
245 switch (cmd) { 264static int saa7110_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
246 case 0: 265{
247 //saa7110_write_block(client, initseq, sizeof(initseq)); 266 *(v4l2_std_id *)std = determine_norm(sd);
248 break; 267 return 0;
268}
249 269
250 case DECODER_GET_CAPABILITIES: 270static int saa7110_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
251 { 271{
252 struct video_decoder_capability *dc = arg; 272 struct saa7110 *decoder = to_saa7110(sd);
273
274 if (decoder->norm != std) {
275 decoder->norm = std;
276 /*saa7110_write(sd, 0x06, 0x03);*/
277 if (std & V4L2_STD_NTSC) {
278 saa7110_write(sd, 0x0D, 0x86);
279 saa7110_write(sd, 0x0F, 0x50);
280 saa7110_write(sd, 0x11, 0x2C);
281 /*saa7110_write(sd, 0x2E, 0x81);*/
282 v4l2_dbg(1, debug, sd, "switched to NTSC\n");
283 } else if (std & V4L2_STD_PAL) {
284 saa7110_write(sd, 0x0D, 0x86);
285 saa7110_write(sd, 0x0F, 0x10);
286 saa7110_write(sd, 0x11, 0x59);
287 /*saa7110_write(sd, 0x2E, 0x9A);*/
288 v4l2_dbg(1, debug, sd, "switched to PAL\n");
289 } else if (std & V4L2_STD_SECAM) {
290 saa7110_write(sd, 0x0D, 0x87);
291 saa7110_write(sd, 0x0F, 0x10);
292 saa7110_write(sd, 0x11, 0x59);
293 /*saa7110_write(sd, 0x2E, 0x9A);*/
294 v4l2_dbg(1, debug, sd, "switched to SECAM\n");
295 } else {
296 return -EINVAL;
297 }
298 }
299 return 0;
300}
253 301
254 dc->flags = 302static int saa7110_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route)
255 VIDEO_DECODER_PAL | VIDEO_DECODER_NTSC | 303{
256 VIDEO_DECODER_SECAM | VIDEO_DECODER_AUTO; 304 struct saa7110 *decoder = to_saa7110(sd);
257 dc->inputs = SAA7110_MAX_INPUT; 305
258 dc->outputs = SAA7110_MAX_OUTPUT; 306 if (route->input < 0 || route->input >= SAA7110_MAX_INPUT) {
259 break; 307 v4l2_dbg(1, debug, sd, "input=%d not available\n", route->input);
308 return -EINVAL;
309 }
310 if (decoder->input != route->input) {
311 saa7110_selmux(sd, route->input);
312 v4l2_dbg(1, debug, sd, "switched to input=%d\n", route->input);
260 } 313 }
314 return 0;
315}
261 316
262 case DECODER_GET_STATUS: 317static int saa7110_s_stream(struct v4l2_subdev *sd, int enable)
263 { 318{
264 int status; 319 struct saa7110 *decoder = to_saa7110(sd);
265 int res = 0; 320
266 321 if (decoder->enable != enable) {
267 status = saa7110_read(client); 322 decoder->enable = enable;
268 v4l_dbg(1, debug, client, "status=0x%02x norm=%d\n", 323 saa7110_write(sd, 0x0E, enable ? 0x18 : 0x80);
269 status, decoder->norm); 324 v4l2_dbg(1, debug, sd, "YUV %s\n", enable ? "on" : "off");
270 if (!(status & 0x40))
271 res |= DECODER_STATUS_GOOD;
272 if (status & 0x03)
273 res |= DECODER_STATUS_COLOR;
274
275 switch (decoder->norm) {
276 case VIDEO_MODE_NTSC:
277 res |= DECODER_STATUS_NTSC;
278 break;
279 case VIDEO_MODE_PAL:
280 res |= DECODER_STATUS_PAL;
281 break;
282 case VIDEO_MODE_SECAM:
283 res |= DECODER_STATUS_SECAM;
284 break;
285 }
286 *(int *) arg = res;
287 break;
288 } 325 }
326 return 0;
327}
289 328
290 case DECODER_SET_NORM: 329static int saa7110_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
291 v = *(int *) arg; 330{
292 if (decoder->norm != v) { 331 switch (qc->id) {
293 decoder->norm = v; 332 case V4L2_CID_BRIGHTNESS:
294 //saa7110_write(client, 0x06, 0x03); 333 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128);
295 switch (v) { 334 case V4L2_CID_CONTRAST:
296 case VIDEO_MODE_NTSC: 335 case V4L2_CID_SATURATION:
297 saa7110_write(client, 0x0D, 0x86); 336 return v4l2_ctrl_query_fill(qc, 0, 127, 1, 64);
298 saa7110_write(client, 0x0F, 0x50); 337 case V4L2_CID_HUE:
299 saa7110_write(client, 0x11, 0x2C); 338 return v4l2_ctrl_query_fill(qc, -128, 127, 1, 0);
300 //saa7110_write(client, 0x2E, 0x81); 339 default:
301 v4l_dbg(1, debug, client, "switched to NTSC\n"); 340 return -EINVAL;
302 break; 341 }
303 case VIDEO_MODE_PAL: 342 return 0;
304 saa7110_write(client, 0x0D, 0x86); 343}
305 saa7110_write(client, 0x0F, 0x10);
306 saa7110_write(client, 0x11, 0x59);
307 //saa7110_write(client, 0x2E, 0x9A);
308 v4l_dbg(1, debug, client, "switched to PAL\n");
309 break;
310 case VIDEO_MODE_SECAM:
311 saa7110_write(client, 0x0D, 0x87);
312 saa7110_write(client, 0x0F, 0x10);
313 saa7110_write(client, 0x11, 0x59);
314 //saa7110_write(client, 0x2E, 0x9A);
315 v4l_dbg(1, debug, client, "switched to SECAM\n");
316 break;
317 case VIDEO_MODE_AUTO:
318 v4l_dbg(1, debug, client, "switched to AUTO\n");
319 decoder->norm = determine_norm(client);
320 *(int *) arg = decoder->norm;
321 break;
322 default:
323 return -EPERM;
324 }
325 }
326 break;
327 344
328 case DECODER_SET_INPUT: 345static int saa7110_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
329 v = *(int *) arg; 346{
330 if (v < 0 || v >= SAA7110_MAX_INPUT) { 347 struct saa7110 *decoder = to_saa7110(sd);
331 v4l_dbg(1, debug, client, "input=%d not available\n", v);
332 return -EINVAL;
333 }
334 if (decoder->input != v) {
335 saa7110_selmux(client, v);
336 v4l_dbg(1, debug, client, "switched to input=%d\n", v);
337 }
338 break;
339 348
340 case DECODER_SET_OUTPUT: 349 switch (ctrl->id) {
341 v = *(int *) arg; 350 case V4L2_CID_BRIGHTNESS:
342 /* not much choice of outputs */ 351 ctrl->value = decoder->bright;
343 if (v != 0)
344 return -EINVAL;
345 break; 352 break;
346 353 case V4L2_CID_CONTRAST:
347 case DECODER_ENABLE_OUTPUT: 354 ctrl->value = decoder->contrast;
348 v = *(int *) arg; 355 break;
349 if (decoder->enable != v) { 356 case V4L2_CID_SATURATION:
350 decoder->enable = v; 357 ctrl->value = decoder->sat;
351 saa7110_write(client, 0x0E, v ? 0x18 : 0x80); 358 break;
352 v4l_dbg(1, debug, client, "YUV %s\n", v ? "on" : "off"); 359 case V4L2_CID_HUE:
353 } 360 ctrl->value = decoder->hue;
354 break; 361 break;
362 default:
363 return -EINVAL;
364 }
365 return 0;
366}
355 367
356 case DECODER_SET_PICTURE: 368static int saa7110_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
357 { 369{
358 struct video_picture *pic = arg; 370 struct saa7110 *decoder = to_saa7110(sd);
359 371
360 if (decoder->bright != pic->brightness) { 372 switch (ctrl->id) {
361 /* We want 0 to 255 we get 0-65535 */ 373 case V4L2_CID_BRIGHTNESS:
362 decoder->bright = pic->brightness; 374 if (decoder->bright != ctrl->value) {
363 saa7110_write(client, 0x19, decoder->bright >> 8); 375 decoder->bright = ctrl->value;
364 } 376 saa7110_write(sd, 0x19, decoder->bright);
365 if (decoder->contrast != pic->contrast) {
366 /* We want 0 to 127 we get 0-65535 */
367 decoder->contrast = pic->contrast;
368 saa7110_write(client, 0x13,
369 decoder->contrast >> 9);
370 } 377 }
371 if (decoder->sat != pic->colour) { 378 break;
372 /* We want 0 to 127 we get 0-65535 */ 379 case V4L2_CID_CONTRAST:
373 decoder->sat = pic->colour; 380 if (decoder->contrast != ctrl->value) {
374 saa7110_write(client, 0x12, decoder->sat >> 9); 381 decoder->contrast = ctrl->value;
382 saa7110_write(sd, 0x13, decoder->contrast);
375 } 383 }
376 if (decoder->hue != pic->hue) { 384 break;
377 /* We want -128 to 127 we get 0-65535 */ 385 case V4L2_CID_SATURATION:
378 decoder->hue = pic->hue; 386 if (decoder->sat != ctrl->value) {
379 saa7110_write(client, 0x07, 387 decoder->sat = ctrl->value;
380 (decoder->hue >> 8) - 128); 388 saa7110_write(sd, 0x12, decoder->sat);
381 } 389 }
382 break; 390 break;
383 } 391 case V4L2_CID_HUE:
384 392 if (decoder->hue != ctrl->value) {
385 case DECODER_DUMP: 393 decoder->hue = ctrl->value;
386 if (!debug) 394 saa7110_write(sd, 0x07, decoder->hue);
387 break;
388 for (v = 0; v < SAA7110_NR_REG; v += 16) {
389 int j;
390 v4l_dbg(1, debug, client, "%02x:", v);
391 for (j = 0; j < 16 && v + j < SAA7110_NR_REG; j++)
392 printk(KERN_CONT " %02x", decoder->reg[v + j]);
393 printk(KERN_CONT "\n");
394 } 395 }
395 break; 396 break;
396
397 default: 397 default:
398 v4l_dbg(1, debug, client, "unknown command %08x\n", cmd);
399 return -EINVAL; 398 return -EINVAL;
400 } 399 }
401 return 0; 400 return 0;
402} 401}
403 402
403static int saa7110_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
404{
405 struct i2c_client *client = v4l2_get_subdevdata(sd);
406
407 return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SAA7110, 0);
408}
409
404/* ----------------------------------------------------------------------- */ 410/* ----------------------------------------------------------------------- */
405 411
406/* 412static const struct v4l2_subdev_core_ops saa7110_core_ops = {
407 * Generic i2c probe 413 .g_chip_ident = saa7110_g_chip_ident,
408 * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1' 414 .g_ctrl = saa7110_g_ctrl,
409 */ 415 .s_ctrl = saa7110_s_ctrl,
416 .queryctrl = saa7110_queryctrl,
417};
410 418
411static unsigned short normal_i2c[] = { 0x9c >> 1, 0x9e >> 1, I2C_CLIENT_END }; 419static const struct v4l2_subdev_tuner_ops saa7110_tuner_ops = {
420 .s_std = saa7110_s_std,
421};
412 422
413I2C_CLIENT_INSMOD; 423static const struct v4l2_subdev_video_ops saa7110_video_ops = {
424 .s_routing = saa7110_s_routing,
425 .s_stream = saa7110_s_stream,
426 .querystd = saa7110_querystd,
427 .g_input_status = saa7110_g_input_status,
428};
429
430static const struct v4l2_subdev_ops saa7110_ops = {
431 .core = &saa7110_core_ops,
432 .tuner = &saa7110_tuner_ops,
433 .video = &saa7110_video_ops,
434};
435
436/* ----------------------------------------------------------------------- */
414 437
415static int saa7110_probe(struct i2c_client *client, 438static int saa7110_probe(struct i2c_client *client,
416 const struct i2c_device_id *id) 439 const struct i2c_device_id *id)
417{ 440{
418 struct saa7110 *decoder; 441 struct saa7110 *decoder;
442 struct v4l2_subdev *sd;
419 int rv; 443 int rv;
420 444
421 /* Check if the adapter supports the needed features */ 445 /* Check if the adapter supports the needed features */
@@ -429,7 +453,9 @@ static int saa7110_probe(struct i2c_client *client,
429 decoder = kzalloc(sizeof(struct saa7110), GFP_KERNEL); 453 decoder = kzalloc(sizeof(struct saa7110), GFP_KERNEL);
430 if (!decoder) 454 if (!decoder)
431 return -ENOMEM; 455 return -ENOMEM;
432 decoder->norm = VIDEO_MODE_PAL; 456 sd = &decoder->sd;
457 v4l2_i2c_subdev_init(sd, client, &saa7110_ops);
458 decoder->norm = V4L2_STD_PAL;
433 decoder->input = 0; 459 decoder->input = 0;
434 decoder->enable = 1; 460 decoder->enable = 1;
435 decoder->bright = 32768; 461 decoder->bright = 32768;
@@ -437,30 +463,29 @@ static int saa7110_probe(struct i2c_client *client,
437 decoder->hue = 32768; 463 decoder->hue = 32768;
438 decoder->sat = 32768; 464 decoder->sat = 32768;
439 init_waitqueue_head(&decoder->wq); 465 init_waitqueue_head(&decoder->wq);
440 i2c_set_clientdata(client, decoder);
441 466
442 rv = saa7110_write_block(client, initseq, sizeof(initseq)); 467 rv = saa7110_write_block(sd, initseq, sizeof(initseq));
443 if (rv < 0) { 468 if (rv < 0) {
444 v4l_dbg(1, debug, client, "init status %d\n", rv); 469 v4l2_dbg(1, debug, sd, "init status %d\n", rv);
445 } else { 470 } else {
446 int ver, status; 471 int ver, status;
447 saa7110_write(client, 0x21, 0x10); 472 saa7110_write(sd, 0x21, 0x10);
448 saa7110_write(client, 0x0e, 0x18); 473 saa7110_write(sd, 0x0e, 0x18);
449 saa7110_write(client, 0x0D, 0x04); 474 saa7110_write(sd, 0x0D, 0x04);
450 ver = saa7110_read(client); 475 ver = saa7110_read(sd);
451 saa7110_write(client, 0x0D, 0x06); 476 saa7110_write(sd, 0x0D, 0x06);
452 //mdelay(150); 477 /*mdelay(150);*/
453 status = saa7110_read(client); 478 status = saa7110_read(sd);
454 v4l_dbg(1, debug, client, "version %x, status=0x%02x\n", 479 v4l2_dbg(1, debug, sd, "version %x, status=0x%02x\n",
455 ver, status); 480 ver, status);
456 saa7110_write(client, 0x0D, 0x86); 481 saa7110_write(sd, 0x0D, 0x86);
457 saa7110_write(client, 0x0F, 0x10); 482 saa7110_write(sd, 0x0F, 0x10);
458 saa7110_write(client, 0x11, 0x59); 483 saa7110_write(sd, 0x11, 0x59);
459 //saa7110_write(client, 0x2E, 0x9A); 484 /*saa7110_write(sd, 0x2E, 0x9A);*/
460 } 485 }
461 486
462 //saa7110_selmux(client,0); 487 /*saa7110_selmux(sd,0);*/
463 //determine_norm(client); 488 /*determine_norm(sd);*/
464 /* setup and implicit mode 0 select has been performed */ 489 /* setup and implicit mode 0 select has been performed */
465 490
466 return 0; 491 return 0;
@@ -468,7 +493,10 @@ static int saa7110_probe(struct i2c_client *client,
468 493
469static int saa7110_remove(struct i2c_client *client) 494static int saa7110_remove(struct i2c_client *client)
470{ 495{
471 kfree(i2c_get_clientdata(client)); 496 struct v4l2_subdev *sd = i2c_get_clientdata(client);
497
498 v4l2_device_unregister_subdev(sd);
499 kfree(to_saa7110(sd));
472 return 0; 500 return 0;
473} 501}
474 502
@@ -482,8 +510,6 @@ MODULE_DEVICE_TABLE(i2c, saa7110_id);
482 510
483static struct v4l2_i2c_driver_data v4l2_i2c_data = { 511static struct v4l2_i2c_driver_data v4l2_i2c_data = {
484 .name = "saa7110", 512 .name = "saa7110",
485 .driverid = I2C_DRIVERID_SAA7110,
486 .command = saa7110_command,
487 .probe = saa7110_probe, 513 .probe = saa7110_probe,
488 .remove = saa7110_remove, 514 .remove = saa7110_remove,
489 .id_table = saa7110_id, 515 .id_table = saa7110_id,