aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/adv7175.c
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil@xs4all.nl>2009-02-19 12:56:37 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-03-30 11:42:58 -0400
commit35631dcc7f09522ff3119ba72d1252f80419779a (patch)
tree8bf5ad447503aaae167c71080945bccbb4c29d75 /drivers/media/video/adv7175.c
parent7d9ef21c2fd4d4d302cd2026c477c058f17d2ba8 (diff)
V4L/DVB (10728): adv7175: convert to v4l2-subdev.
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/adv7175.c')
-rw-r--r--drivers/media/video/adv7175.c307
1 files changed, 165 insertions, 142 deletions
diff --git a/drivers/media/video/adv7175.c b/drivers/media/video/adv7175.c
index 154dff03a7d8..318c3053633a 100644
--- a/drivers/media/video/adv7175.c
+++ b/drivers/media/video/adv7175.c
@@ -30,15 +30,26 @@
30#include <asm/uaccess.h> 30#include <asm/uaccess.h>
31#include <linux/i2c.h> 31#include <linux/i2c.h>
32#include <linux/i2c-id.h> 32#include <linux/i2c-id.h>
33#include <linux/videodev.h> 33#include <linux/videodev2.h>
34#include <linux/video_encoder.h> 34#include <media/v4l2-device.h>
35#include <media/v4l2-common.h> 35#include <media/v4l2-chip-ident.h>
36#include <media/v4l2-i2c-drv-legacy.h> 36#include <media/v4l2-i2c-drv-legacy.h>
37 37
38MODULE_DESCRIPTION("Analog Devices ADV7175 video encoder driver"); 38MODULE_DESCRIPTION("Analog Devices ADV7175 video encoder driver");
39MODULE_AUTHOR("Dave Perks"); 39MODULE_AUTHOR("Dave Perks");
40MODULE_LICENSE("GPL"); 40MODULE_LICENSE("GPL");
41 41
42#define I2C_ADV7175 0xd4
43#define I2C_ADV7176 0x54
44
45static unsigned short normal_i2c[] = {
46 I2C_ADV7175 >> 1, (I2C_ADV7175 >> 1) + 1,
47 I2C_ADV7176 >> 1, (I2C_ADV7176 >> 1) + 1,
48 I2C_CLIENT_END
49};
50
51I2C_CLIENT_INSMOD;
52
42static int debug; 53static int debug;
43module_param(debug, int, 0); 54module_param(debug, int, 0);
44MODULE_PARM_DESC(debug, "Debug level (0-1)"); 55MODULE_PARM_DESC(debug, "Debug level (0-1)");
@@ -46,34 +57,38 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)");
46/* ----------------------------------------------------------------------- */ 57/* ----------------------------------------------------------------------- */
47 58
48struct adv7175 { 59struct adv7175 {
60 struct v4l2_subdev sd;
49 v4l2_std_id norm; 61 v4l2_std_id norm;
50 int input; 62 int input;
51 int bright;
52 int contrast;
53 int hue;
54 int sat;
55}; 63};
56 64
57#define I2C_ADV7175 0xd4 65static inline struct adv7175 *to_adv7175(struct v4l2_subdev *sd)
58#define I2C_ADV7176 0x54 66{
67 return container_of(sd, struct adv7175, sd);
68}
59 69
60static char *inputs[] = { "pass_through", "play_back", "color_bar" }; 70static char *inputs[] = { "pass_through", "play_back", "color_bar" };
61 71
62/* ----------------------------------------------------------------------- */ 72/* ----------------------------------------------------------------------- */
63 73
64static inline int adv7175_write(struct i2c_client *client, u8 reg, u8 value) 74static inline int adv7175_write(struct v4l2_subdev *sd, u8 reg, u8 value)
65{ 75{
76 struct i2c_client *client = v4l2_get_subdevdata(sd);
77
66 return i2c_smbus_write_byte_data(client, reg, value); 78 return i2c_smbus_write_byte_data(client, reg, value);
67} 79}
68 80
69static inline int adv7175_read(struct i2c_client *client, u8 reg) 81static inline int adv7175_read(struct v4l2_subdev *sd, u8 reg)
70{ 82{
83 struct i2c_client *client = v4l2_get_subdevdata(sd);
84
71 return i2c_smbus_read_byte_data(client, reg); 85 return i2c_smbus_read_byte_data(client, reg);
72} 86}
73 87
74static int adv7175_write_block(struct i2c_client *client, 88static int adv7175_write_block(struct v4l2_subdev *sd,
75 const u8 *data, unsigned int len) 89 const u8 *data, unsigned int len)
76{ 90{
91 struct i2c_client *client = v4l2_get_subdevdata(sd);
77 int ret = -1; 92 int ret = -1;
78 u8 reg; 93 u8 reg;
79 94
@@ -101,7 +116,7 @@ static int adv7175_write_block(struct i2c_client *client,
101 /* do some slow I2C emulation kind of thing */ 116 /* do some slow I2C emulation kind of thing */
102 while (len >= 2) { 117 while (len >= 2) {
103 reg = *data++; 118 reg = *data++;
104 ret = adv7175_write(client, reg, *data++); 119 ret = adv7175_write(sd, reg, *data++);
105 if (ret < 0) 120 if (ret < 0)
106 break; 121 break;
107 len -= 2; 122 len -= 2;
@@ -111,18 +126,18 @@ static int adv7175_write_block(struct i2c_client *client,
111 return ret; 126 return ret;
112} 127}
113 128
114static void set_subcarrier_freq(struct i2c_client *client, int pass_through) 129static void set_subcarrier_freq(struct v4l2_subdev *sd, int pass_through)
115{ 130{
116 /* for some reason pass_through NTSC needs 131 /* for some reason pass_through NTSC needs
117 * a different sub-carrier freq to remain stable. */ 132 * a different sub-carrier freq to remain stable. */
118 if (pass_through) 133 if (pass_through)
119 adv7175_write(client, 0x02, 0x00); 134 adv7175_write(sd, 0x02, 0x00);
120 else 135 else
121 adv7175_write(client, 0x02, 0x55); 136 adv7175_write(sd, 0x02, 0x55);
122 137
123 adv7175_write(client, 0x03, 0x55); 138 adv7175_write(sd, 0x03, 0x55);
124 adv7175_write(client, 0x04, 0x55); 139 adv7175_write(sd, 0x04, 0x55);
125 adv7175_write(client, 0x05, 0x25); 140 adv7175_write(sd, 0x05, 0x25);
126} 141}
127 142
128/* ----------------------------------------------------------------------- */ 143/* ----------------------------------------------------------------------- */
@@ -182,144 +197,148 @@ static const unsigned char init_ntsc[] = {
182 0x06, 0x1a, /* subc. phase */ 197 0x06, 0x1a, /* subc. phase */
183}; 198};
184 199
185static int adv7175_command(struct i2c_client *client, unsigned cmd, void *arg) 200static int adv7175_init(struct v4l2_subdev *sd, u32 val)
201{
202 /* This is just for testing!!! */
203 adv7175_write_block(sd, init_common, sizeof(init_common));
204 adv7175_write(sd, 0x07, TR0MODE | TR0RST);
205 adv7175_write(sd, 0x07, TR0MODE);
206 return 0;
207}
208
209static int adv7175_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std)
186{ 210{
187 struct adv7175 *encoder = i2c_get_clientdata(client); 211 struct adv7175 *encoder = to_adv7175(sd);
188 212
189 switch (cmd) { 213 if (std & V4L2_STD_NTSC) {
190 case VIDIOC_INT_INIT: 214 adv7175_write_block(sd, init_ntsc, sizeof(init_ntsc));
191 /* This is just for testing!!! */ 215 if (encoder->input == 0)
192 adv7175_write_block(client, init_common, 216 adv7175_write(sd, 0x0d, 0x4f); /* Enable genlock */
193 sizeof(init_common)); 217 adv7175_write(sd, 0x07, TR0MODE | TR0RST);
194 adv7175_write(client, 0x07, TR0MODE | TR0RST); 218 adv7175_write(sd, 0x07, TR0MODE);
195 adv7175_write(client, 0x07, TR0MODE); 219 } else if (std & V4L2_STD_PAL) {
220 adv7175_write_block(sd, init_pal, sizeof(init_pal));
221 if (encoder->input == 0)
222 adv7175_write(sd, 0x0d, 0x4f); /* Enable genlock */
223 adv7175_write(sd, 0x07, TR0MODE | TR0RST);
224 adv7175_write(sd, 0x07, TR0MODE);
225 } else if (std & V4L2_STD_SECAM) {
226 /* This is an attempt to convert
227 * SECAM->PAL (typically it does not work
228 * due to genlock: when decoder is in SECAM
229 * and encoder in in PAL the subcarrier can
230 * not be syncronized with horizontal
231 * quency) */
232 adv7175_write_block(sd, init_pal, sizeof(init_pal));
233 if (encoder->input == 0)
234 adv7175_write(sd, 0x0d, 0x49); /* Disable genlock */
235 adv7175_write(sd, 0x07, TR0MODE | TR0RST);
236 adv7175_write(sd, 0x07, TR0MODE);
237 } else {
238 v4l2_dbg(1, debug, sd, "illegal norm: %llx\n", std);
239 return -EINVAL;
240 }
241 v4l2_dbg(1, debug, sd, "switched to %llx\n", std);
242 encoder->norm = std;
243 return 0;
244}
245
246static int adv7175_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route)
247{
248 struct adv7175 *encoder = to_adv7175(sd);
249
250 /* RJ: route->input = 0: input is from decoder
251 route->input = 1: input is from ZR36060
252 route->input = 2: color bar */
253
254 switch (route->input) {
255 case 0:
256 adv7175_write(sd, 0x01, 0x00);
257
258 if (encoder->norm & V4L2_STD_NTSC)
259 set_subcarrier_freq(sd, 1);
260
261 adv7175_write(sd, 0x0c, TR1CAPT); /* TR1 */
262 if (encoder->norm & V4L2_STD_SECAM)
263 adv7175_write(sd, 0x0d, 0x49); /* Disable genlock */
264 else
265 adv7175_write(sd, 0x0d, 0x4f); /* Enable genlock */
266 adv7175_write(sd, 0x07, TR0MODE | TR0RST);
267 adv7175_write(sd, 0x07, TR0MODE);
268 /*udelay(10);*/
196 break; 269 break;
197 270
198 case VIDIOC_INT_S_STD_OUTPUT: 271 case 1:
199 { 272 adv7175_write(sd, 0x01, 0x00);
200 v4l2_std_id iarg = *(v4l2_std_id *) arg; 273
201 274 if (encoder->norm & V4L2_STD_NTSC)
202 if (iarg & V4L2_STD_NTSC) { 275 set_subcarrier_freq(sd, 0);
203 adv7175_write_block(client, init_ntsc, 276
204 sizeof(init_ntsc)); 277 adv7175_write(sd, 0x0c, TR1PLAY); /* TR1 */
205 if (encoder->input == 0) 278 adv7175_write(sd, 0x0d, 0x49);
206 adv7175_write(client, 0x0d, 0x4f); // Enable genlock 279 adv7175_write(sd, 0x07, TR0MODE | TR0RST);
207 adv7175_write(client, 0x07, TR0MODE | TR0RST); 280 adv7175_write(sd, 0x07, TR0MODE);
208 adv7175_write(client, 0x07, TR0MODE); 281 /* udelay(10); */
209 } else if (iarg & V4L2_STD_PAL) {
210 adv7175_write_block(client, init_pal,
211 sizeof(init_pal));
212 if (encoder->input == 0)
213 adv7175_write(client, 0x0d, 0x4f); // Enable genlock
214 adv7175_write(client, 0x07, TR0MODE | TR0RST);
215 adv7175_write(client, 0x07, TR0MODE);
216 } else if (iarg & V4L2_STD_SECAM) {
217 /* This is an attempt to convert
218 * SECAM->PAL (typically it does not work
219 * due to genlock: when decoder is in SECAM
220 * and encoder in in PAL the subcarrier can
221 * not be syncronized with horizontal
222 * quency) */
223 adv7175_write_block(client, init_pal,
224 sizeof(init_pal));
225 if (encoder->input == 0)
226 adv7175_write(client, 0x0d, 0x49); // Disable genlock
227 adv7175_write(client, 0x07, TR0MODE | TR0RST);
228 adv7175_write(client, 0x07, TR0MODE);
229 } else {
230 v4l_dbg(1, debug, client, "illegal norm: %llx\n", iarg);
231 return -EINVAL;
232 }
233 v4l_dbg(1, debug, client, "switched to %llx\n", iarg);
234 encoder->norm = iarg;
235 break; 282 break;
236 }
237 283
238 case VIDIOC_INT_S_VIDEO_ROUTING: 284 case 2:
239 { 285 adv7175_write(sd, 0x01, 0x80);
240 struct v4l2_routing *route = arg; 286
241 287 if (encoder->norm & V4L2_STD_NTSC)
242 /* RJ: *iarg = 0: input is from SAA7110 288 set_subcarrier_freq(sd, 0);
243 *iarg = 1: input is from ZR36060 289
244 *iarg = 2: color bar */ 290 adv7175_write(sd, 0x0d, 0x49);
245 291 adv7175_write(sd, 0x07, TR0MODE | TR0RST);
246 switch (route->input) { 292 adv7175_write(sd, 0x07, TR0MODE);
247 case 0: 293 /* udelay(10); */
248 adv7175_write(client, 0x01, 0x00);
249
250 if (encoder->norm & V4L2_STD_NTSC)
251 set_subcarrier_freq(client, 1);
252
253 adv7175_write(client, 0x0c, TR1CAPT); /* TR1 */
254 if (encoder->norm & V4L2_STD_SECAM)
255 adv7175_write(client, 0x0d, 0x49); // Disable genlock
256 else
257 adv7175_write(client, 0x0d, 0x4f); // Enable genlock
258 adv7175_write(client, 0x07, TR0MODE | TR0RST);
259 adv7175_write(client, 0x07, TR0MODE);
260 //udelay(10);
261 break;
262
263 case 1:
264 adv7175_write(client, 0x01, 0x00);
265
266 if (encoder->norm & V4L2_STD_NTSC)
267 set_subcarrier_freq(client, 0);
268
269 adv7175_write(client, 0x0c, TR1PLAY); /* TR1 */
270 adv7175_write(client, 0x0d, 0x49);
271 adv7175_write(client, 0x07, TR0MODE | TR0RST);
272 adv7175_write(client, 0x07, TR0MODE);
273 /* udelay(10); */
274 break;
275
276 case 2:
277 adv7175_write(client, 0x01, 0x80);
278
279 if (encoder->norm & V4L2_STD_NTSC)
280 set_subcarrier_freq(client, 0);
281
282 adv7175_write(client, 0x0d, 0x49);
283 adv7175_write(client, 0x07, TR0MODE | TR0RST);
284 adv7175_write(client, 0x07, TR0MODE);
285 /* udelay(10); */
286 break;
287
288 default:
289 v4l_dbg(1, debug, client, "illegal input: %d\n", route->input);
290 return -EINVAL;
291 }
292 v4l_dbg(1, debug, client, "switched to %s\n", inputs[route->input]);
293 encoder->input = route->input;
294 break; 294 break;
295 }
296 295
297 default: 296 default:
297 v4l2_dbg(1, debug, sd, "illegal input: %d\n", route->input);
298 return -EINVAL; 298 return -EINVAL;
299 } 299 }
300 300 v4l2_dbg(1, debug, sd, "switched to %s\n", inputs[route->input]);
301 encoder->input = route->input;
301 return 0; 302 return 0;
302} 303}
303 304
305static int adv7175_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
306{
307 struct i2c_client *client = v4l2_get_subdevdata(sd);
308
309 return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_ADV7175, 0);
310}
311
312static int adv7175_command(struct i2c_client *client, unsigned cmd, void *arg)
313{
314 return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg);
315}
316
304/* ----------------------------------------------------------------------- */ 317/* ----------------------------------------------------------------------- */
305 318
306/* 319static const struct v4l2_subdev_core_ops adv7175_core_ops = {
307 * Generic i2c probe 320 .g_chip_ident = adv7175_g_chip_ident,
308 * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1' 321 .init = adv7175_init,
309 */
310static unsigned short normal_i2c[] = {
311 I2C_ADV7175 >> 1, (I2C_ADV7175 >> 1) + 1,
312 I2C_ADV7176 >> 1, (I2C_ADV7176 >> 1) + 1,
313 I2C_CLIENT_END
314}; 322};
315 323
316I2C_CLIENT_INSMOD; 324static const struct v4l2_subdev_video_ops adv7175_video_ops = {
325 .s_std_output = adv7175_s_std_output,
326 .s_routing = adv7175_s_routing,
327};
328
329static const struct v4l2_subdev_ops adv7175_ops = {
330 .core = &adv7175_core_ops,
331 .video = &adv7175_video_ops,
332};
333
334/* ----------------------------------------------------------------------- */
317 335
318static int adv7175_probe(struct i2c_client *client, 336static int adv7175_probe(struct i2c_client *client,
319 const struct i2c_device_id *id) 337 const struct i2c_device_id *id)
320{ 338{
321 int i; 339 int i;
322 struct adv7175 *encoder; 340 struct adv7175 *encoder;
341 struct v4l2_subdev *sd;
323 342
324 /* Check if the adapter supports the needed features */ 343 /* Check if the adapter supports the needed features */
325 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) 344 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
@@ -331,25 +350,29 @@ static int adv7175_probe(struct i2c_client *client,
331 encoder = kzalloc(sizeof(struct adv7175), GFP_KERNEL); 350 encoder = kzalloc(sizeof(struct adv7175), GFP_KERNEL);
332 if (encoder == NULL) 351 if (encoder == NULL)
333 return -ENOMEM; 352 return -ENOMEM;
353 sd = &encoder->sd;
354 v4l2_i2c_subdev_init(sd, client, &adv7175_ops);
334 encoder->norm = V4L2_STD_NTSC; 355 encoder->norm = V4L2_STD_NTSC;
335 encoder->input = 0; 356 encoder->input = 0;
336 i2c_set_clientdata(client, encoder);
337 357
338 i = adv7175_write_block(client, init_common, sizeof(init_common)); 358 i = adv7175_write_block(sd, init_common, sizeof(init_common));
339 if (i >= 0) { 359 if (i >= 0) {
340 i = adv7175_write(client, 0x07, TR0MODE | TR0RST); 360 i = adv7175_write(sd, 0x07, TR0MODE | TR0RST);
341 i = adv7175_write(client, 0x07, TR0MODE); 361 i = adv7175_write(sd, 0x07, TR0MODE);
342 i = adv7175_read(client, 0x12); 362 i = adv7175_read(sd, 0x12);
343 v4l_dbg(1, debug, client, "revision %d\n", i & 1); 363 v4l2_dbg(1, debug, sd, "revision %d\n", i & 1);
344 } 364 }
345 if (i < 0) 365 if (i < 0)
346 v4l_dbg(1, debug, client, "init error 0x%x\n", i); 366 v4l2_dbg(1, debug, sd, "init error 0x%x\n", i);
347 return 0; 367 return 0;
348} 368}
349 369
350static int adv7175_remove(struct i2c_client *client) 370static int adv7175_remove(struct i2c_client *client)
351{ 371{
352 kfree(i2c_get_clientdata(client)); 372 struct v4l2_subdev *sd = i2c_get_clientdata(client);
373
374 v4l2_device_unregister_subdev(sd);
375 kfree(to_adv7175(sd));
353 return 0; 376 return 0;
354} 377}
355 378