diff options
Diffstat (limited to 'drivers/media/video/tda7432.c')
-rw-r--r-- | drivers/media/video/tda7432.c | 252 |
1 files changed, 111 insertions, 141 deletions
diff --git a/drivers/media/video/tda7432.c b/drivers/media/video/tda7432.c index 4963d426488..0c020585fff 100644 --- a/drivers/media/video/tda7432.c +++ b/drivers/media/video/tda7432.c | |||
@@ -47,9 +47,10 @@ | |||
47 | #include <linux/videodev2.h> | 47 | #include <linux/videodev2.h> |
48 | #include <linux/i2c.h> | 48 | #include <linux/i2c.h> |
49 | 49 | ||
50 | #include <media/v4l2-common.h> | 50 | #include <media/v4l2-device.h> |
51 | #include <media/v4l2-ioctl.h> | 51 | #include <media/v4l2-ioctl.h> |
52 | #include <media/i2c-addr.h> | 52 | #include <media/i2c-addr.h> |
53 | #include <media/v4l2-i2c-drv-legacy.h> | ||
53 | 54 | ||
54 | #ifndef VIDEO_AUDIO_BALANCE | 55 | #ifndef VIDEO_AUDIO_BALANCE |
55 | # define VIDEO_AUDIO_BALANCE 32 | 56 | # define VIDEO_AUDIO_BALANCE 32 |
@@ -79,6 +80,7 @@ I2C_CLIENT_INSMOD; | |||
79 | /* Structure of address and subaddresses for the tda7432 */ | 80 | /* Structure of address and subaddresses for the tda7432 */ |
80 | 81 | ||
81 | struct tda7432 { | 82 | struct tda7432 { |
83 | struct v4l2_subdev sd; | ||
82 | int addr; | 84 | int addr; |
83 | int input; | 85 | int input; |
84 | int volume; | 86 | int volume; |
@@ -86,10 +88,12 @@ struct tda7432 { | |||
86 | int bass, treble; | 88 | int bass, treble; |
87 | int lf, lr, rf, rr; | 89 | int lf, lr, rf, rr; |
88 | int loud; | 90 | int loud; |
89 | struct i2c_client c; | ||
90 | }; | 91 | }; |
91 | static struct i2c_driver driver; | 92 | |
92 | static struct i2c_client client_template; | 93 | static inline struct tda7432 *to_state(struct v4l2_subdev *sd) |
94 | { | ||
95 | return container_of(sd, struct tda7432, sd); | ||
96 | } | ||
93 | 97 | ||
94 | /* The TDA7432 is made by STS-Thompson | 98 | /* The TDA7432 is made by STS-Thompson |
95 | * http://www.st.com | 99 | * http://www.st.com |
@@ -224,32 +228,33 @@ static struct i2c_client client_template; | |||
224 | 228 | ||
225 | /* Begin code */ | 229 | /* Begin code */ |
226 | 230 | ||
227 | static int tda7432_write(struct i2c_client *client, int subaddr, int val) | 231 | static int tda7432_write(struct v4l2_subdev *sd, int subaddr, int val) |
228 | { | 232 | { |
233 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
229 | unsigned char buffer[2]; | 234 | unsigned char buffer[2]; |
230 | v4l_dbg(2, debug,client,"In tda7432_write\n"); | 235 | |
231 | v4l_dbg(1, debug,client,"Writing %d 0x%x\n", subaddr, val); | 236 | v4l2_dbg(2, debug, sd, "In tda7432_write\n"); |
237 | v4l2_dbg(1, debug, sd, "Writing %d 0x%x\n", subaddr, val); | ||
232 | buffer[0] = subaddr; | 238 | buffer[0] = subaddr; |
233 | buffer[1] = val; | 239 | buffer[1] = val; |
234 | if (2 != i2c_master_send(client,buffer,2)) { | 240 | if (2 != i2c_master_send(client, buffer, 2)) { |
235 | v4l_err(client,"I/O error, trying (write %d 0x%x)\n", | 241 | v4l2_err(sd, "I/O error, trying (write %d 0x%x)\n", |
236 | subaddr, val); | 242 | subaddr, val); |
237 | return -1; | 243 | return -1; |
238 | } | 244 | } |
239 | return 0; | 245 | return 0; |
240 | } | 246 | } |
241 | 247 | ||
242 | /* I don't think we ever actually _read_ the chip... */ | 248 | static int tda7432_set(struct v4l2_subdev *sd) |
243 | |||
244 | static int tda7432_set(struct i2c_client *client) | ||
245 | { | 249 | { |
246 | struct tda7432 *t = i2c_get_clientdata(client); | 250 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
251 | struct tda7432 *t = to_state(sd); | ||
247 | unsigned char buf[16]; | 252 | unsigned char buf[16]; |
248 | v4l_dbg(2, debug,client,"In tda7432_set\n"); | ||
249 | 253 | ||
250 | v4l_dbg(1, debug,client, | 254 | v4l2_dbg(1, debug, sd, |
251 | "tda7432: 7432_set(0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x)\n", | 255 | "tda7432: 7432_set(0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x)\n", |
252 | t->input,t->volume,t->bass,t->treble,t->lf,t->lr,t->rf,t->rr,t->loud); | 256 | t->input, t->volume, t->bass, t->treble, t->lf, t->lr, |
257 | t->rf, t->rr, t->loud); | ||
253 | buf[0] = TDA7432_IN; | 258 | buf[0] = TDA7432_IN; |
254 | buf[1] = t->input; | 259 | buf[1] = t->input; |
255 | buf[2] = t->volume; | 260 | buf[2] = t->volume; |
@@ -260,18 +265,19 @@ static int tda7432_set(struct i2c_client *client) | |||
260 | buf[7] = t->rf; | 265 | buf[7] = t->rf; |
261 | buf[8] = t->rr; | 266 | buf[8] = t->rr; |
262 | buf[9] = t->loud; | 267 | buf[9] = t->loud; |
263 | if (10 != i2c_master_send(client,buf,10)) { | 268 | if (10 != i2c_master_send(client, buf, 10)) { |
264 | v4l_err(client,"I/O error, trying tda7432_set\n"); | 269 | v4l2_err(sd, "I/O error, trying tda7432_set\n"); |
265 | return -1; | 270 | return -1; |
266 | } | 271 | } |
267 | 272 | ||
268 | return 0; | 273 | return 0; |
269 | } | 274 | } |
270 | 275 | ||
271 | static void do_tda7432_init(struct i2c_client *client) | 276 | static void do_tda7432_init(struct v4l2_subdev *sd) |
272 | { | 277 | { |
273 | struct tda7432 *t = i2c_get_clientdata(client); | 278 | struct tda7432 *t = to_state(sd); |
274 | v4l_dbg(2, debug,client,"In tda7432_init\n"); | 279 | |
280 | v4l2_dbg(2, debug, sd, "In tda7432_init\n"); | ||
275 | 281 | ||
276 | t->input = TDA7432_STEREO_IN | /* Main (stereo) input */ | 282 | t->input = TDA7432_STEREO_IN | /* Main (stereo) input */ |
277 | TDA7432_BASS_SYM | /* Symmetric bass cut */ | 283 | TDA7432_BASS_SYM | /* Symmetric bass cut */ |
@@ -288,57 +294,12 @@ static void do_tda7432_init(struct i2c_client *client) | |||
288 | t->rr = TDA7432_ATTEN_0DB; /* 0dB attenuation */ | 294 | t->rr = TDA7432_ATTEN_0DB; /* 0dB attenuation */ |
289 | t->loud = loudness; /* insmod parameter */ | 295 | t->loud = loudness; /* insmod parameter */ |
290 | 296 | ||
291 | tda7432_set(client); | 297 | tda7432_set(sd); |
292 | } | 298 | } |
293 | 299 | ||
294 | /* *********************** * | 300 | static int tda7432_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) |
295 | * i2c interface functions * | ||
296 | * *********************** */ | ||
297 | |||
298 | static int tda7432_attach(struct i2c_adapter *adap, int addr, int kind) | ||
299 | { | 301 | { |
300 | struct tda7432 *t; | 302 | struct tda7432 *t = to_state(sd); |
301 | struct i2c_client *client; | ||
302 | |||
303 | t = kzalloc(sizeof *t,GFP_KERNEL); | ||
304 | if (!t) | ||
305 | return -ENOMEM; | ||
306 | |||
307 | client = &t->c; | ||
308 | memcpy(client,&client_template,sizeof(struct i2c_client)); | ||
309 | client->adapter = adap; | ||
310 | client->addr = addr; | ||
311 | i2c_set_clientdata(client, t); | ||
312 | |||
313 | do_tda7432_init(client); | ||
314 | i2c_attach_client(client); | ||
315 | |||
316 | v4l_info(client, "chip found @ 0x%x (%s)\n", addr << 1, adap->name); | ||
317 | return 0; | ||
318 | } | ||
319 | |||
320 | static int tda7432_probe(struct i2c_adapter *adap) | ||
321 | { | ||
322 | if (adap->class & I2C_CLASS_TV_ANALOG) | ||
323 | return i2c_probe(adap, &addr_data, tda7432_attach); | ||
324 | return 0; | ||
325 | } | ||
326 | |||
327 | static int tda7432_detach(struct i2c_client *client) | ||
328 | { | ||
329 | struct tda7432 *t = i2c_get_clientdata(client); | ||
330 | |||
331 | do_tda7432_init(client); | ||
332 | i2c_detach_client(client); | ||
333 | |||
334 | kfree(t); | ||
335 | return 0; | ||
336 | } | ||
337 | |||
338 | static int tda7432_get_ctrl(struct i2c_client *client, | ||
339 | struct v4l2_control *ctrl) | ||
340 | { | ||
341 | struct tda7432 *t = i2c_get_clientdata(client); | ||
342 | 303 | ||
343 | switch (ctrl->id) { | 304 | switch (ctrl->id) { |
344 | case V4L2_CID_AUDIO_MUTE: | 305 | case V4L2_CID_AUDIO_MUTE: |
@@ -382,10 +343,9 @@ static int tda7432_get_ctrl(struct i2c_client *client, | |||
382 | return -EINVAL; | 343 | return -EINVAL; |
383 | } | 344 | } |
384 | 345 | ||
385 | static int tda7432_set_ctrl(struct i2c_client *client, | 346 | static int tda7432_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) |
386 | struct v4l2_control *ctrl) | ||
387 | { | 347 | { |
388 | struct tda7432 *t = i2c_get_clientdata(client); | 348 | struct tda7432 *t = to_state(sd); |
389 | 349 | ||
390 | switch (ctrl->id) { | 350 | switch (ctrl->id) { |
391 | case V4L2_CID_AUDIO_MUTE: | 351 | case V4L2_CID_AUDIO_MUTE: |
@@ -400,7 +360,7 @@ static int tda7432_set_ctrl(struct i2c_client *client, | |||
400 | if (loudness) /* Turn on the loudness bit */ | 360 | if (loudness) /* Turn on the loudness bit */ |
401 | t->volume |= TDA7432_LD_ON; | 361 | t->volume |= TDA7432_LD_ON; |
402 | 362 | ||
403 | tda7432_write(client,TDA7432_VL, t->volume); | 363 | tda7432_write(sd, TDA7432_VL, t->volume); |
404 | return 0; | 364 | return 0; |
405 | case V4L2_CID_AUDIO_BALANCE: | 365 | case V4L2_CID_AUDIO_BALANCE: |
406 | if (ctrl->value < 32768) { | 366 | if (ctrl->value < 32768) { |
@@ -428,14 +388,14 @@ static int tda7432_set_ctrl(struct i2c_client *client, | |||
428 | if(t->bass>= 0x8) | 388 | if(t->bass>= 0x8) |
429 | t->bass = (~t->bass & 0xf) + 0x8 ; | 389 | t->bass = (~t->bass & 0xf) + 0x8 ; |
430 | 390 | ||
431 | tda7432_write(client,TDA7432_TN, 0x10 | (t->bass << 4) | t->treble ); | 391 | tda7432_write(sd, TDA7432_TN, 0x10 | (t->bass << 4) | t->treble); |
432 | return 0; | 392 | return 0; |
433 | case V4L2_CID_AUDIO_TREBLE: | 393 | case V4L2_CID_AUDIO_TREBLE: |
434 | t->treble= ctrl->value >> 12; | 394 | t->treble= ctrl->value >> 12; |
435 | if(t->treble>= 0x8) | 395 | if(t->treble>= 0x8) |
436 | t->treble = (~t->treble & 0xf) + 0x8 ; | 396 | t->treble = (~t->treble & 0xf) + 0x8 ; |
437 | 397 | ||
438 | tda7432_write(client,TDA7432_TN, 0x10 | (t->bass << 4) | t->treble ); | 398 | tda7432_write(sd, TDA7432_TN, 0x10 | (t->bass << 4) | t->treble); |
439 | return 0; | 399 | return 0; |
440 | default: | 400 | default: |
441 | return -EINVAL; | 401 | return -EINVAL; |
@@ -445,92 +405,102 @@ static int tda7432_set_ctrl(struct i2c_client *client, | |||
445 | if (t->muted) | 405 | if (t->muted) |
446 | { | 406 | { |
447 | /* Mute & update balance*/ | 407 | /* Mute & update balance*/ |
448 | tda7432_write(client,TDA7432_LF, t->lf | TDA7432_MUTE); | 408 | tda7432_write(sd, TDA7432_LF, t->lf | TDA7432_MUTE); |
449 | tda7432_write(client,TDA7432_LR, t->lr | TDA7432_MUTE); | 409 | tda7432_write(sd, TDA7432_LR, t->lr | TDA7432_MUTE); |
450 | tda7432_write(client,TDA7432_RF, t->rf | TDA7432_MUTE); | 410 | tda7432_write(sd, TDA7432_RF, t->rf | TDA7432_MUTE); |
451 | tda7432_write(client,TDA7432_RR, t->rr | TDA7432_MUTE); | 411 | tda7432_write(sd, TDA7432_RR, t->rr | TDA7432_MUTE); |
452 | } else { | 412 | } else { |
453 | tda7432_write(client,TDA7432_LF, t->lf); | 413 | tda7432_write(sd, TDA7432_LF, t->lf); |
454 | tda7432_write(client,TDA7432_LR, t->lr); | 414 | tda7432_write(sd, TDA7432_LR, t->lr); |
455 | tda7432_write(client,TDA7432_RF, t->rf); | 415 | tda7432_write(sd, TDA7432_RF, t->rf); |
456 | tda7432_write(client,TDA7432_RR, t->rr); | 416 | tda7432_write(sd, TDA7432_RR, t->rr); |
457 | } | 417 | } |
458 | return 0; | 418 | return 0; |
459 | } | 419 | } |
460 | 420 | ||
461 | static int tda7432_command(struct i2c_client *client, | 421 | static int tda7432_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) |
462 | unsigned int cmd, void *arg) | ||
463 | { | 422 | { |
464 | v4l_dbg(2, debug,client,"In tda7432_command\n"); | 423 | switch (qc->id) { |
465 | if (debug>1) | 424 | case V4L2_CID_AUDIO_MUTE: |
466 | v4l_i2c_print_ioctl(client,cmd); | 425 | case V4L2_CID_AUDIO_VOLUME: |
467 | 426 | case V4L2_CID_AUDIO_BALANCE: | |
468 | switch (cmd) { | 427 | case V4L2_CID_AUDIO_BASS: |
469 | /* --- v4l ioctls --- */ | 428 | case V4L2_CID_AUDIO_TREBLE: |
470 | /* take care: bttv does userspace copying, we'll get a | ||
471 | kernel pointer here... */ | ||
472 | case VIDIOC_QUERYCTRL: | ||
473 | { | ||
474 | struct v4l2_queryctrl *qc = arg; | ||
475 | |||
476 | switch (qc->id) { | ||
477 | case V4L2_CID_AUDIO_MUTE: | ||
478 | case V4L2_CID_AUDIO_VOLUME: | ||
479 | case V4L2_CID_AUDIO_BALANCE: | ||
480 | case V4L2_CID_AUDIO_BASS: | ||
481 | case V4L2_CID_AUDIO_TREBLE: | ||
482 | default: | ||
483 | return -EINVAL; | ||
484 | } | ||
485 | return v4l2_ctrl_query_fill_std(qc); | 429 | return v4l2_ctrl_query_fill_std(qc); |
486 | } | 430 | } |
487 | case VIDIOC_S_CTRL: | 431 | return -EINVAL; |
488 | return tda7432_set_ctrl(client, arg); | 432 | } |
489 | |||
490 | case VIDIOC_G_CTRL: | ||
491 | return tda7432_get_ctrl(client, arg); | ||
492 | |||
493 | } /* end of (cmd) switch */ | ||
494 | 433 | ||
495 | return 0; | 434 | static int tda7432_command(struct i2c_client *client, unsigned cmd, void *arg) |
435 | { | ||
436 | return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); | ||
496 | } | 437 | } |
497 | 438 | ||
498 | static struct i2c_driver driver = { | 439 | /* ----------------------------------------------------------------------- */ |
499 | .driver = { | 440 | |
500 | .name = "tda7432", | 441 | static const struct v4l2_subdev_core_ops tda7432_core_ops = { |
501 | }, | 442 | .queryctrl = tda7432_queryctrl, |
502 | .id = I2C_DRIVERID_TDA7432, | 443 | .g_ctrl = tda7432_g_ctrl, |
503 | .attach_adapter = tda7432_probe, | 444 | .s_ctrl = tda7432_s_ctrl, |
504 | .detach_client = tda7432_detach, | ||
505 | .command = tda7432_command, | ||
506 | }; | 445 | }; |
507 | 446 | ||
508 | static struct i2c_client client_template = | 447 | static const struct v4l2_subdev_ops tda7432_ops = { |
509 | { | 448 | .core = &tda7432_core_ops, |
510 | .name = "tda7432", | ||
511 | .driver = &driver, | ||
512 | }; | 449 | }; |
513 | 450 | ||
514 | static int __init tda7432_init(void) | 451 | /* ----------------------------------------------------------------------- */ |
452 | |||
453 | /* *********************** * | ||
454 | * i2c interface functions * | ||
455 | * *********************** */ | ||
456 | |||
457 | static int tda7432_probe(struct i2c_client *client, | ||
458 | const struct i2c_device_id *id) | ||
515 | { | 459 | { |
516 | if ( (loudness < 0) || (loudness > 15) ) { | 460 | struct tda7432 *t; |
517 | printk(KERN_ERR "loudness parameter must be between 0 and 15\n"); | 461 | struct v4l2_subdev *sd; |
518 | return -EINVAL; | 462 | |
463 | v4l_info(client, "chip found @ 0x%02x (%s)\n", | ||
464 | client->addr << 1, client->adapter->name); | ||
465 | |||
466 | t = kzalloc(sizeof(*t), GFP_KERNEL); | ||
467 | if (!t) | ||
468 | return -ENOMEM; | ||
469 | sd = &t->sd; | ||
470 | v4l2_i2c_subdev_init(sd, client, &tda7432_ops); | ||
471 | if (loudness < 0 || loudness > 15) { | ||
472 | v4l2_warn(sd, "loudness parameter must be between 0 and 15\n"); | ||
473 | if (loudness < 0) | ||
474 | loudness = 0; | ||
475 | if (loudness > 15) | ||
476 | loudness = 15; | ||
519 | } | 477 | } |
520 | 478 | ||
521 | return i2c_add_driver(&driver); | 479 | do_tda7432_init(sd); |
480 | return 0; | ||
522 | } | 481 | } |
523 | 482 | ||
524 | static void __exit tda7432_fini(void) | 483 | static int tda7432_remove(struct i2c_client *client) |
525 | { | 484 | { |
526 | i2c_del_driver(&driver); | 485 | struct v4l2_subdev *sd = i2c_get_clientdata(client); |
527 | } | ||
528 | 486 | ||
529 | module_init(tda7432_init); | 487 | do_tda7432_init(sd); |
530 | module_exit(tda7432_fini); | 488 | v4l2_device_unregister_subdev(sd); |
489 | kfree(to_state(sd)); | ||
490 | return 0; | ||
491 | } | ||
531 | 492 | ||
532 | /* | 493 | static const struct i2c_device_id tda7432_id[] = { |
533 | * Local variables: | 494 | { "tda7432", 0 }, |
534 | * c-basic-offset: 8 | 495 | { } |
535 | * End: | 496 | }; |
536 | */ | 497 | MODULE_DEVICE_TABLE(i2c, tda7432_id); |
498 | |||
499 | static struct v4l2_i2c_driver_data v4l2_i2c_data = { | ||
500 | .name = "tda7432", | ||
501 | .driverid = I2C_DRIVERID_TDA7432, | ||
502 | .command = tda7432_command, | ||
503 | .probe = tda7432_probe, | ||
504 | .remove = tda7432_remove, | ||
505 | .id_table = tda7432_id, | ||
506 | }; | ||