diff options
Diffstat (limited to 'drivers/media/i2c/saa7191.c')
-rw-r--r-- | drivers/media/i2c/saa7191.c | 659 |
1 files changed, 659 insertions, 0 deletions
diff --git a/drivers/media/i2c/saa7191.c b/drivers/media/i2c/saa7191.c new file mode 100644 index 000000000000..d7d1670e0ca3 --- /dev/null +++ b/drivers/media/i2c/saa7191.c | |||
@@ -0,0 +1,659 @@ | |||
1 | /* | ||
2 | * saa7191.c - Philips SAA7191 video decoder driver | ||
3 | * | ||
4 | * Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org> | ||
5 | * Copyright (C) 2004,2005 Mikael Nousiainen <tmnousia@cc.hut.fi> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/delay.h> | ||
13 | #include <linux/errno.h> | ||
14 | #include <linux/fs.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/major.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/mm.h> | ||
20 | #include <linux/slab.h> | ||
21 | |||
22 | #include <linux/videodev2.h> | ||
23 | #include <linux/i2c.h> | ||
24 | #include <media/v4l2-device.h> | ||
25 | #include <media/v4l2-chip-ident.h> | ||
26 | |||
27 | #include "saa7191.h" | ||
28 | |||
29 | #define SAA7191_MODULE_VERSION "0.0.5" | ||
30 | |||
31 | MODULE_DESCRIPTION("Philips SAA7191 video decoder driver"); | ||
32 | MODULE_VERSION(SAA7191_MODULE_VERSION); | ||
33 | MODULE_AUTHOR("Mikael Nousiainen <tmnousia@cc.hut.fi>"); | ||
34 | MODULE_LICENSE("GPL"); | ||
35 | |||
36 | |||
37 | // #define SAA7191_DEBUG | ||
38 | |||
39 | #ifdef SAA7191_DEBUG | ||
40 | #define dprintk(x...) printk("SAA7191: " x); | ||
41 | #else | ||
42 | #define dprintk(x...) | ||
43 | #endif | ||
44 | |||
45 | #define SAA7191_SYNC_COUNT 30 | ||
46 | #define SAA7191_SYNC_DELAY 100 /* milliseconds */ | ||
47 | |||
48 | struct saa7191 { | ||
49 | struct v4l2_subdev sd; | ||
50 | |||
51 | /* the register values are stored here as the actual | ||
52 | * I2C-registers are write-only */ | ||
53 | u8 reg[25]; | ||
54 | |||
55 | int input; | ||
56 | v4l2_std_id norm; | ||
57 | }; | ||
58 | |||
59 | static inline struct saa7191 *to_saa7191(struct v4l2_subdev *sd) | ||
60 | { | ||
61 | return container_of(sd, struct saa7191, sd); | ||
62 | } | ||
63 | |||
64 | static const u8 initseq[] = { | ||
65 | 0, /* Subaddress */ | ||
66 | |||
67 | 0x50, /* (0x50) SAA7191_REG_IDEL */ | ||
68 | |||
69 | /* 50 Hz signal timing */ | ||
70 | 0x30, /* (0x30) SAA7191_REG_HSYB */ | ||
71 | 0x00, /* (0x00) SAA7191_REG_HSYS */ | ||
72 | 0xe8, /* (0xe8) SAA7191_REG_HCLB */ | ||
73 | 0xb6, /* (0xb6) SAA7191_REG_HCLS */ | ||
74 | 0xf4, /* (0xf4) SAA7191_REG_HPHI */ | ||
75 | |||
76 | /* control */ | ||
77 | SAA7191_LUMA_APER_1, /* (0x01) SAA7191_REG_LUMA - CVBS mode */ | ||
78 | 0x00, /* (0x00) SAA7191_REG_HUEC */ | ||
79 | 0xf8, /* (0xf8) SAA7191_REG_CKTQ */ | ||
80 | 0xf8, /* (0xf8) SAA7191_REG_CKTS */ | ||
81 | 0x90, /* (0x90) SAA7191_REG_PLSE */ | ||
82 | 0x90, /* (0x90) SAA7191_REG_SESE */ | ||
83 | 0x00, /* (0x00) SAA7191_REG_GAIN */ | ||
84 | SAA7191_STDC_NFEN | SAA7191_STDC_HRMV, /* (0x0c) SAA7191_REG_STDC | ||
85 | * - not SECAM, | ||
86 | * slow time constant */ | ||
87 | SAA7191_IOCK_OEDC | SAA7191_IOCK_OEHS | SAA7191_IOCK_OEVS | ||
88 | | SAA7191_IOCK_OEDY, /* (0x78) SAA7191_REG_IOCK | ||
89 | * - chroma from CVBS, GPSW1 & 2 off */ | ||
90 | SAA7191_CTL3_AUFD | SAA7191_CTL3_SCEN | SAA7191_CTL3_OFTS | ||
91 | | SAA7191_CTL3_YDEL0, /* (0x99) SAA7191_REG_CTL3 | ||
92 | * - automatic field detection */ | ||
93 | 0x00, /* (0x00) SAA7191_REG_CTL4 */ | ||
94 | 0x2c, /* (0x2c) SAA7191_REG_CHCV - PAL nominal value */ | ||
95 | 0x00, /* unused */ | ||
96 | 0x00, /* unused */ | ||
97 | |||
98 | /* 60 Hz signal timing */ | ||
99 | 0x34, /* (0x34) SAA7191_REG_HS6B */ | ||
100 | 0x0a, /* (0x0a) SAA7191_REG_HS6S */ | ||
101 | 0xf4, /* (0xf4) SAA7191_REG_HC6B */ | ||
102 | 0xce, /* (0xce) SAA7191_REG_HC6S */ | ||
103 | 0xf4, /* (0xf4) SAA7191_REG_HP6I */ | ||
104 | }; | ||
105 | |||
106 | /* SAA7191 register handling */ | ||
107 | |||
108 | static u8 saa7191_read_reg(struct v4l2_subdev *sd, u8 reg) | ||
109 | { | ||
110 | return to_saa7191(sd)->reg[reg]; | ||
111 | } | ||
112 | |||
113 | static int saa7191_read_status(struct v4l2_subdev *sd, u8 *value) | ||
114 | { | ||
115 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
116 | int ret; | ||
117 | |||
118 | ret = i2c_master_recv(client, value, 1); | ||
119 | if (ret < 0) { | ||
120 | printk(KERN_ERR "SAA7191: saa7191_read_status(): read failed\n"); | ||
121 | return ret; | ||
122 | } | ||
123 | |||
124 | return 0; | ||
125 | } | ||
126 | |||
127 | |||
128 | static int saa7191_write_reg(struct v4l2_subdev *sd, u8 reg, u8 value) | ||
129 | { | ||
130 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
131 | |||
132 | to_saa7191(sd)->reg[reg] = value; | ||
133 | return i2c_smbus_write_byte_data(client, reg, value); | ||
134 | } | ||
135 | |||
136 | /* the first byte of data must be the first subaddress number (register) */ | ||
137 | static int saa7191_write_block(struct v4l2_subdev *sd, | ||
138 | u8 length, const u8 *data) | ||
139 | { | ||
140 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
141 | struct saa7191 *decoder = to_saa7191(sd); | ||
142 | int i; | ||
143 | int ret; | ||
144 | |||
145 | for (i = 0; i < (length - 1); i++) { | ||
146 | decoder->reg[data[0] + i] = data[i + 1]; | ||
147 | } | ||
148 | |||
149 | ret = i2c_master_send(client, data, length); | ||
150 | if (ret < 0) { | ||
151 | printk(KERN_ERR "SAA7191: saa7191_write_block(): " | ||
152 | "write failed\n"); | ||
153 | return ret; | ||
154 | } | ||
155 | |||
156 | return 0; | ||
157 | } | ||
158 | |||
159 | /* Helper functions */ | ||
160 | |||
161 | static int saa7191_s_routing(struct v4l2_subdev *sd, | ||
162 | u32 input, u32 output, u32 config) | ||
163 | { | ||
164 | struct saa7191 *decoder = to_saa7191(sd); | ||
165 | u8 luma = saa7191_read_reg(sd, SAA7191_REG_LUMA); | ||
166 | u8 iock = saa7191_read_reg(sd, SAA7191_REG_IOCK); | ||
167 | int err; | ||
168 | |||
169 | switch (input) { | ||
170 | case SAA7191_INPUT_COMPOSITE: /* Set Composite input */ | ||
171 | iock &= ~(SAA7191_IOCK_CHRS | SAA7191_IOCK_GPSW1 | ||
172 | | SAA7191_IOCK_GPSW2); | ||
173 | /* Chrominance trap active */ | ||
174 | luma &= ~SAA7191_LUMA_BYPS; | ||
175 | break; | ||
176 | case SAA7191_INPUT_SVIDEO: /* Set S-Video input */ | ||
177 | iock |= SAA7191_IOCK_CHRS | SAA7191_IOCK_GPSW2; | ||
178 | /* Chrominance trap bypassed */ | ||
179 | luma |= SAA7191_LUMA_BYPS; | ||
180 | break; | ||
181 | default: | ||
182 | return -EINVAL; | ||
183 | } | ||
184 | |||
185 | err = saa7191_write_reg(sd, SAA7191_REG_LUMA, luma); | ||
186 | if (err) | ||
187 | return -EIO; | ||
188 | err = saa7191_write_reg(sd, SAA7191_REG_IOCK, iock); | ||
189 | if (err) | ||
190 | return -EIO; | ||
191 | |||
192 | decoder->input = input; | ||
193 | |||
194 | return 0; | ||
195 | } | ||
196 | |||
197 | static int saa7191_s_std(struct v4l2_subdev *sd, v4l2_std_id norm) | ||
198 | { | ||
199 | struct saa7191 *decoder = to_saa7191(sd); | ||
200 | u8 stdc = saa7191_read_reg(sd, SAA7191_REG_STDC); | ||
201 | u8 ctl3 = saa7191_read_reg(sd, SAA7191_REG_CTL3); | ||
202 | u8 chcv = saa7191_read_reg(sd, SAA7191_REG_CHCV); | ||
203 | int err; | ||
204 | |||
205 | if (norm & V4L2_STD_PAL) { | ||
206 | stdc &= ~SAA7191_STDC_SECS; | ||
207 | ctl3 &= ~(SAA7191_CTL3_AUFD | SAA7191_CTL3_FSEL); | ||
208 | chcv = SAA7191_CHCV_PAL; | ||
209 | } else if (norm & V4L2_STD_NTSC) { | ||
210 | stdc &= ~SAA7191_STDC_SECS; | ||
211 | ctl3 &= ~SAA7191_CTL3_AUFD; | ||
212 | ctl3 |= SAA7191_CTL3_FSEL; | ||
213 | chcv = SAA7191_CHCV_NTSC; | ||
214 | } else if (norm & V4L2_STD_SECAM) { | ||
215 | stdc |= SAA7191_STDC_SECS; | ||
216 | ctl3 &= ~(SAA7191_CTL3_AUFD | SAA7191_CTL3_FSEL); | ||
217 | chcv = SAA7191_CHCV_PAL; | ||
218 | } else { | ||
219 | return -EINVAL; | ||
220 | } | ||
221 | |||
222 | err = saa7191_write_reg(sd, SAA7191_REG_CTL3, ctl3); | ||
223 | if (err) | ||
224 | return -EIO; | ||
225 | err = saa7191_write_reg(sd, SAA7191_REG_STDC, stdc); | ||
226 | if (err) | ||
227 | return -EIO; | ||
228 | err = saa7191_write_reg(sd, SAA7191_REG_CHCV, chcv); | ||
229 | if (err) | ||
230 | return -EIO; | ||
231 | |||
232 | decoder->norm = norm; | ||
233 | |||
234 | dprintk("ctl3: %02x stdc: %02x chcv: %02x\n", ctl3, | ||
235 | stdc, chcv); | ||
236 | dprintk("norm: %llx\n", norm); | ||
237 | |||
238 | return 0; | ||
239 | } | ||
240 | |||
241 | static int saa7191_wait_for_signal(struct v4l2_subdev *sd, u8 *status) | ||
242 | { | ||
243 | int i = 0; | ||
244 | |||
245 | dprintk("Checking for signal...\n"); | ||
246 | |||
247 | for (i = 0; i < SAA7191_SYNC_COUNT; i++) { | ||
248 | if (saa7191_read_status(sd, status)) | ||
249 | return -EIO; | ||
250 | |||
251 | if (((*status) & SAA7191_STATUS_HLCK) == 0) { | ||
252 | dprintk("Signal found\n"); | ||
253 | return 0; | ||
254 | } | ||
255 | |||
256 | msleep(SAA7191_SYNC_DELAY); | ||
257 | } | ||
258 | |||
259 | dprintk("No signal\n"); | ||
260 | |||
261 | return -EBUSY; | ||
262 | } | ||
263 | |||
264 | static int saa7191_querystd(struct v4l2_subdev *sd, v4l2_std_id *norm) | ||
265 | { | ||
266 | struct saa7191 *decoder = to_saa7191(sd); | ||
267 | u8 stdc = saa7191_read_reg(sd, SAA7191_REG_STDC); | ||
268 | u8 ctl3 = saa7191_read_reg(sd, SAA7191_REG_CTL3); | ||
269 | u8 status; | ||
270 | v4l2_std_id old_norm = decoder->norm; | ||
271 | int err = 0; | ||
272 | |||
273 | dprintk("SAA7191 extended signal auto-detection...\n"); | ||
274 | |||
275 | *norm = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM; | ||
276 | stdc &= ~SAA7191_STDC_SECS; | ||
277 | ctl3 &= ~(SAA7191_CTL3_FSEL); | ||
278 | |||
279 | err = saa7191_write_reg(sd, SAA7191_REG_STDC, stdc); | ||
280 | if (err) { | ||
281 | err = -EIO; | ||
282 | goto out; | ||
283 | } | ||
284 | err = saa7191_write_reg(sd, SAA7191_REG_CTL3, ctl3); | ||
285 | if (err) { | ||
286 | err = -EIO; | ||
287 | goto out; | ||
288 | } | ||
289 | |||
290 | ctl3 |= SAA7191_CTL3_AUFD; | ||
291 | err = saa7191_write_reg(sd, SAA7191_REG_CTL3, ctl3); | ||
292 | if (err) { | ||
293 | err = -EIO; | ||
294 | goto out; | ||
295 | } | ||
296 | |||
297 | msleep(SAA7191_SYNC_DELAY); | ||
298 | |||
299 | err = saa7191_wait_for_signal(sd, &status); | ||
300 | if (err) | ||
301 | goto out; | ||
302 | |||
303 | if (status & SAA7191_STATUS_FIDT) { | ||
304 | /* 60Hz signal -> NTSC */ | ||
305 | dprintk("60Hz signal: NTSC\n"); | ||
306 | *norm = V4L2_STD_NTSC; | ||
307 | return 0; | ||
308 | } | ||
309 | |||
310 | /* 50Hz signal */ | ||
311 | dprintk("50Hz signal: Trying PAL...\n"); | ||
312 | |||
313 | /* try PAL first */ | ||
314 | err = saa7191_s_std(sd, V4L2_STD_PAL); | ||
315 | if (err) | ||
316 | goto out; | ||
317 | |||
318 | msleep(SAA7191_SYNC_DELAY); | ||
319 | |||
320 | err = saa7191_wait_for_signal(sd, &status); | ||
321 | if (err) | ||
322 | goto out; | ||
323 | |||
324 | /* not 50Hz ? */ | ||
325 | if (status & SAA7191_STATUS_FIDT) { | ||
326 | dprintk("No 50Hz signal\n"); | ||
327 | saa7191_s_std(sd, old_norm); | ||
328 | return -EAGAIN; | ||
329 | } | ||
330 | |||
331 | if (status & SAA7191_STATUS_CODE) { | ||
332 | dprintk("PAL\n"); | ||
333 | *norm = V4L2_STD_PAL; | ||
334 | return saa7191_s_std(sd, old_norm); | ||
335 | } | ||
336 | |||
337 | dprintk("No color detected with PAL - Trying SECAM...\n"); | ||
338 | |||
339 | /* no color detected ? -> try SECAM */ | ||
340 | err = saa7191_s_std(sd, V4L2_STD_SECAM); | ||
341 | if (err) | ||
342 | goto out; | ||
343 | |||
344 | msleep(SAA7191_SYNC_DELAY); | ||
345 | |||
346 | err = saa7191_wait_for_signal(sd, &status); | ||
347 | if (err) | ||
348 | goto out; | ||
349 | |||
350 | /* not 50Hz ? */ | ||
351 | if (status & SAA7191_STATUS_FIDT) { | ||
352 | dprintk("No 50Hz signal\n"); | ||
353 | err = -EAGAIN; | ||
354 | goto out; | ||
355 | } | ||
356 | |||
357 | if (status & SAA7191_STATUS_CODE) { | ||
358 | /* Color detected -> SECAM */ | ||
359 | dprintk("SECAM\n"); | ||
360 | *norm = V4L2_STD_SECAM; | ||
361 | return saa7191_s_std(sd, old_norm); | ||
362 | } | ||
363 | |||
364 | dprintk("No color detected with SECAM - Going back to PAL.\n"); | ||
365 | |||
366 | out: | ||
367 | return saa7191_s_std(sd, old_norm); | ||
368 | } | ||
369 | |||
370 | static int saa7191_autodetect_norm(struct v4l2_subdev *sd) | ||
371 | { | ||
372 | u8 status; | ||
373 | |||
374 | dprintk("SAA7191 signal auto-detection...\n"); | ||
375 | |||
376 | dprintk("Reading status...\n"); | ||
377 | |||
378 | if (saa7191_read_status(sd, &status)) | ||
379 | return -EIO; | ||
380 | |||
381 | dprintk("Checking for signal...\n"); | ||
382 | |||
383 | /* no signal ? */ | ||
384 | if (status & SAA7191_STATUS_HLCK) { | ||
385 | dprintk("No signal\n"); | ||
386 | return -EBUSY; | ||
387 | } | ||
388 | |||
389 | dprintk("Signal found\n"); | ||
390 | |||
391 | if (status & SAA7191_STATUS_FIDT) { | ||
392 | /* 60hz signal -> NTSC */ | ||
393 | dprintk("NTSC\n"); | ||
394 | return saa7191_s_std(sd, V4L2_STD_NTSC); | ||
395 | } else { | ||
396 | /* 50hz signal -> PAL */ | ||
397 | dprintk("PAL\n"); | ||
398 | return saa7191_s_std(sd, V4L2_STD_PAL); | ||
399 | } | ||
400 | } | ||
401 | |||
402 | static int saa7191_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | ||
403 | { | ||
404 | u8 reg; | ||
405 | int ret = 0; | ||
406 | |||
407 | switch (ctrl->id) { | ||
408 | case SAA7191_CONTROL_BANDPASS: | ||
409 | case SAA7191_CONTROL_BANDPASS_WEIGHT: | ||
410 | case SAA7191_CONTROL_CORING: | ||
411 | reg = saa7191_read_reg(sd, SAA7191_REG_LUMA); | ||
412 | switch (ctrl->id) { | ||
413 | case SAA7191_CONTROL_BANDPASS: | ||
414 | ctrl->value = ((s32)reg & SAA7191_LUMA_BPSS_MASK) | ||
415 | >> SAA7191_LUMA_BPSS_SHIFT; | ||
416 | break; | ||
417 | case SAA7191_CONTROL_BANDPASS_WEIGHT: | ||
418 | ctrl->value = ((s32)reg & SAA7191_LUMA_APER_MASK) | ||
419 | >> SAA7191_LUMA_APER_SHIFT; | ||
420 | break; | ||
421 | case SAA7191_CONTROL_CORING: | ||
422 | ctrl->value = ((s32)reg & SAA7191_LUMA_CORI_MASK) | ||
423 | >> SAA7191_LUMA_CORI_SHIFT; | ||
424 | break; | ||
425 | } | ||
426 | break; | ||
427 | case SAA7191_CONTROL_FORCE_COLOUR: | ||
428 | case SAA7191_CONTROL_CHROMA_GAIN: | ||
429 | reg = saa7191_read_reg(sd, SAA7191_REG_GAIN); | ||
430 | if (ctrl->id == SAA7191_CONTROL_FORCE_COLOUR) | ||
431 | ctrl->value = ((s32)reg & SAA7191_GAIN_COLO) ? 1 : 0; | ||
432 | else | ||
433 | ctrl->value = ((s32)reg & SAA7191_GAIN_LFIS_MASK) | ||
434 | >> SAA7191_GAIN_LFIS_SHIFT; | ||
435 | break; | ||
436 | case V4L2_CID_HUE: | ||
437 | reg = saa7191_read_reg(sd, SAA7191_REG_HUEC); | ||
438 | if (reg < 0x80) | ||
439 | reg += 0x80; | ||
440 | else | ||
441 | reg -= 0x80; | ||
442 | ctrl->value = (s32)reg; | ||
443 | break; | ||
444 | case SAA7191_CONTROL_VTRC: | ||
445 | reg = saa7191_read_reg(sd, SAA7191_REG_STDC); | ||
446 | ctrl->value = ((s32)reg & SAA7191_STDC_VTRC) ? 1 : 0; | ||
447 | break; | ||
448 | case SAA7191_CONTROL_LUMA_DELAY: | ||
449 | reg = saa7191_read_reg(sd, SAA7191_REG_CTL3); | ||
450 | ctrl->value = ((s32)reg & SAA7191_CTL3_YDEL_MASK) | ||
451 | >> SAA7191_CTL3_YDEL_SHIFT; | ||
452 | if (ctrl->value >= 4) | ||
453 | ctrl->value -= 8; | ||
454 | break; | ||
455 | case SAA7191_CONTROL_VNR: | ||
456 | reg = saa7191_read_reg(sd, SAA7191_REG_CTL4); | ||
457 | ctrl->value = ((s32)reg & SAA7191_CTL4_VNOI_MASK) | ||
458 | >> SAA7191_CTL4_VNOI_SHIFT; | ||
459 | break; | ||
460 | default: | ||
461 | ret = -EINVAL; | ||
462 | } | ||
463 | |||
464 | return ret; | ||
465 | } | ||
466 | |||
467 | static int saa7191_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | ||
468 | { | ||
469 | u8 reg; | ||
470 | int ret = 0; | ||
471 | |||
472 | switch (ctrl->id) { | ||
473 | case SAA7191_CONTROL_BANDPASS: | ||
474 | case SAA7191_CONTROL_BANDPASS_WEIGHT: | ||
475 | case SAA7191_CONTROL_CORING: | ||
476 | reg = saa7191_read_reg(sd, SAA7191_REG_LUMA); | ||
477 | switch (ctrl->id) { | ||
478 | case SAA7191_CONTROL_BANDPASS: | ||
479 | reg &= ~SAA7191_LUMA_BPSS_MASK; | ||
480 | reg |= (ctrl->value << SAA7191_LUMA_BPSS_SHIFT) | ||
481 | & SAA7191_LUMA_BPSS_MASK; | ||
482 | break; | ||
483 | case SAA7191_CONTROL_BANDPASS_WEIGHT: | ||
484 | reg &= ~SAA7191_LUMA_APER_MASK; | ||
485 | reg |= (ctrl->value << SAA7191_LUMA_APER_SHIFT) | ||
486 | & SAA7191_LUMA_APER_MASK; | ||
487 | break; | ||
488 | case SAA7191_CONTROL_CORING: | ||
489 | reg &= ~SAA7191_LUMA_CORI_MASK; | ||
490 | reg |= (ctrl->value << SAA7191_LUMA_CORI_SHIFT) | ||
491 | & SAA7191_LUMA_CORI_MASK; | ||
492 | break; | ||
493 | } | ||
494 | ret = saa7191_write_reg(sd, SAA7191_REG_LUMA, reg); | ||
495 | break; | ||
496 | case SAA7191_CONTROL_FORCE_COLOUR: | ||
497 | case SAA7191_CONTROL_CHROMA_GAIN: | ||
498 | reg = saa7191_read_reg(sd, SAA7191_REG_GAIN); | ||
499 | if (ctrl->id == SAA7191_CONTROL_FORCE_COLOUR) { | ||
500 | if (ctrl->value) | ||
501 | reg |= SAA7191_GAIN_COLO; | ||
502 | else | ||
503 | reg &= ~SAA7191_GAIN_COLO; | ||
504 | } else { | ||
505 | reg &= ~SAA7191_GAIN_LFIS_MASK; | ||
506 | reg |= (ctrl->value << SAA7191_GAIN_LFIS_SHIFT) | ||
507 | & SAA7191_GAIN_LFIS_MASK; | ||
508 | } | ||
509 | ret = saa7191_write_reg(sd, SAA7191_REG_GAIN, reg); | ||
510 | break; | ||
511 | case V4L2_CID_HUE: | ||
512 | reg = ctrl->value & 0xff; | ||
513 | if (reg < 0x80) | ||
514 | reg += 0x80; | ||
515 | else | ||
516 | reg -= 0x80; | ||
517 | ret = saa7191_write_reg(sd, SAA7191_REG_HUEC, reg); | ||
518 | break; | ||
519 | case SAA7191_CONTROL_VTRC: | ||
520 | reg = saa7191_read_reg(sd, SAA7191_REG_STDC); | ||
521 | if (ctrl->value) | ||
522 | reg |= SAA7191_STDC_VTRC; | ||
523 | else | ||
524 | reg &= ~SAA7191_STDC_VTRC; | ||
525 | ret = saa7191_write_reg(sd, SAA7191_REG_STDC, reg); | ||
526 | break; | ||
527 | case SAA7191_CONTROL_LUMA_DELAY: { | ||
528 | s32 value = ctrl->value; | ||
529 | if (value < 0) | ||
530 | value += 8; | ||
531 | reg = saa7191_read_reg(sd, SAA7191_REG_CTL3); | ||
532 | reg &= ~SAA7191_CTL3_YDEL_MASK; | ||
533 | reg |= (value << SAA7191_CTL3_YDEL_SHIFT) | ||
534 | & SAA7191_CTL3_YDEL_MASK; | ||
535 | ret = saa7191_write_reg(sd, SAA7191_REG_CTL3, reg); | ||
536 | break; | ||
537 | } | ||
538 | case SAA7191_CONTROL_VNR: | ||
539 | reg = saa7191_read_reg(sd, SAA7191_REG_CTL4); | ||
540 | reg &= ~SAA7191_CTL4_VNOI_MASK; | ||
541 | reg |= (ctrl->value << SAA7191_CTL4_VNOI_SHIFT) | ||
542 | & SAA7191_CTL4_VNOI_MASK; | ||
543 | ret = saa7191_write_reg(sd, SAA7191_REG_CTL4, reg); | ||
544 | break; | ||
545 | default: | ||
546 | ret = -EINVAL; | ||
547 | } | ||
548 | |||
549 | return ret; | ||
550 | } | ||
551 | |||
552 | /* I2C-interface */ | ||
553 | |||
554 | static int saa7191_g_input_status(struct v4l2_subdev *sd, u32 *status) | ||
555 | { | ||
556 | u8 status_reg; | ||
557 | int res = V4L2_IN_ST_NO_SIGNAL; | ||
558 | |||
559 | if (saa7191_read_status(sd, &status_reg)) | ||
560 | return -EIO; | ||
561 | if ((status_reg & SAA7191_STATUS_HLCK) == 0) | ||
562 | res = 0; | ||
563 | if (!(status_reg & SAA7191_STATUS_CODE)) | ||
564 | res |= V4L2_IN_ST_NO_COLOR; | ||
565 | *status = res; | ||
566 | return 0; | ||
567 | } | ||
568 | |||
569 | |||
570 | static int saa7191_g_chip_ident(struct v4l2_subdev *sd, | ||
571 | struct v4l2_dbg_chip_ident *chip) | ||
572 | { | ||
573 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
574 | |||
575 | return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SAA7191, 0); | ||
576 | } | ||
577 | |||
578 | /* ----------------------------------------------------------------------- */ | ||
579 | |||
580 | static const struct v4l2_subdev_core_ops saa7191_core_ops = { | ||
581 | .g_chip_ident = saa7191_g_chip_ident, | ||
582 | .g_ctrl = saa7191_g_ctrl, | ||
583 | .s_ctrl = saa7191_s_ctrl, | ||
584 | .s_std = saa7191_s_std, | ||
585 | }; | ||
586 | |||
587 | static const struct v4l2_subdev_video_ops saa7191_video_ops = { | ||
588 | .s_routing = saa7191_s_routing, | ||
589 | .querystd = saa7191_querystd, | ||
590 | .g_input_status = saa7191_g_input_status, | ||
591 | }; | ||
592 | |||
593 | static const struct v4l2_subdev_ops saa7191_ops = { | ||
594 | .core = &saa7191_core_ops, | ||
595 | .video = &saa7191_video_ops, | ||
596 | }; | ||
597 | |||
598 | static int saa7191_probe(struct i2c_client *client, | ||
599 | const struct i2c_device_id *id) | ||
600 | { | ||
601 | int err = 0; | ||
602 | struct saa7191 *decoder; | ||
603 | struct v4l2_subdev *sd; | ||
604 | |||
605 | v4l_info(client, "chip found @ 0x%x (%s)\n", | ||
606 | client->addr << 1, client->adapter->name); | ||
607 | |||
608 | decoder = kzalloc(sizeof(*decoder), GFP_KERNEL); | ||
609 | if (!decoder) | ||
610 | return -ENOMEM; | ||
611 | |||
612 | sd = &decoder->sd; | ||
613 | v4l2_i2c_subdev_init(sd, client, &saa7191_ops); | ||
614 | |||
615 | err = saa7191_write_block(sd, sizeof(initseq), initseq); | ||
616 | if (err) { | ||
617 | printk(KERN_ERR "SAA7191 initialization failed\n"); | ||
618 | kfree(decoder); | ||
619 | return err; | ||
620 | } | ||
621 | |||
622 | printk(KERN_INFO "SAA7191 initialized\n"); | ||
623 | |||
624 | decoder->input = SAA7191_INPUT_COMPOSITE; | ||
625 | decoder->norm = V4L2_STD_PAL; | ||
626 | |||
627 | err = saa7191_autodetect_norm(sd); | ||
628 | if (err && (err != -EBUSY)) | ||
629 | printk(KERN_ERR "SAA7191: Signal auto-detection failed\n"); | ||
630 | |||
631 | return 0; | ||
632 | } | ||
633 | |||
634 | static int saa7191_remove(struct i2c_client *client) | ||
635 | { | ||
636 | struct v4l2_subdev *sd = i2c_get_clientdata(client); | ||
637 | |||
638 | v4l2_device_unregister_subdev(sd); | ||
639 | kfree(to_saa7191(sd)); | ||
640 | return 0; | ||
641 | } | ||
642 | |||
643 | static const struct i2c_device_id saa7191_id[] = { | ||
644 | { "saa7191", 0 }, | ||
645 | { } | ||
646 | }; | ||
647 | MODULE_DEVICE_TABLE(i2c, saa7191_id); | ||
648 | |||
649 | static struct i2c_driver saa7191_driver = { | ||
650 | .driver = { | ||
651 | .owner = THIS_MODULE, | ||
652 | .name = "saa7191", | ||
653 | }, | ||
654 | .probe = saa7191_probe, | ||
655 | .remove = saa7191_remove, | ||
656 | .id_table = saa7191_id, | ||
657 | }; | ||
658 | |||
659 | module_i2c_driver(saa7191_driver); | ||