aboutsummaryrefslogtreecommitdiffstats
path: root/sound/aoa/codecs/snd-aoa-codec-tas.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2006-09-17 15:59:25 -0400
committerJaroslav Kysela <perex@suse.cz>2006-09-23 04:47:06 -0400
commit307192065c55dbc70159037c1e3006a9f761192b (patch)
tree462ed687281672986f54af5ac1d7abc2f2b8c999 /sound/aoa/codecs/snd-aoa-codec-tas.c
parent43001c9515cf87935c50e84b3e27b1f3b3776b5d (diff)
[ALSA] aoa: add locking to tas codec
Looks like I completely forgot to do this. This patch adds locking to the tas codec so two userspace programs can't hit the controls at the same time. Tested on my powerbook, but I obviously can't find any problems even without it since it doesn't do SMP. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Jaroslav Kysela <perex@suse.cz>
Diffstat (limited to 'sound/aoa/codecs/snd-aoa-codec-tas.c')
-rw-r--r--sound/aoa/codecs/snd-aoa-codec-tas.c96
1 files changed, 83 insertions, 13 deletions
diff --git a/sound/aoa/codecs/snd-aoa-codec-tas.c b/sound/aoa/codecs/snd-aoa-codec-tas.c
index 16c0b6b0a805..2ef55a17917c 100644
--- a/sound/aoa/codecs/snd-aoa-codec-tas.c
+++ b/sound/aoa/codecs/snd-aoa-codec-tas.c
@@ -66,6 +66,8 @@
66#include <asm/prom.h> 66#include <asm/prom.h>
67#include <linux/delay.h> 67#include <linux/delay.h>
68#include <linux/module.h> 68#include <linux/module.h>
69#include <linux/mutex.h>
70
69MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>"); 71MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
70MODULE_LICENSE("GPL"); 72MODULE_LICENSE("GPL");
71MODULE_DESCRIPTION("tas codec driver for snd-aoa"); 73MODULE_DESCRIPTION("tas codec driver for snd-aoa");
@@ -91,6 +93,10 @@ struct tas {
91 u8 bass, treble; 93 u8 bass, treble;
92 u8 acr; 94 u8 acr;
93 int drc_range; 95 int drc_range;
96 /* protects hardware access against concurrency from
97 * userspace when hitting controls and during
98 * codec init/suspend/resume */
99 struct mutex mtx;
94}; 100};
95 101
96static int tas_reset_init(struct tas *tas); 102static int tas_reset_init(struct tas *tas);
@@ -231,8 +237,10 @@ static int tas_snd_vol_get(struct snd_kcontrol *kcontrol,
231{ 237{
232 struct tas *tas = snd_kcontrol_chip(kcontrol); 238 struct tas *tas = snd_kcontrol_chip(kcontrol);
233 239
240 mutex_lock(&tas->mtx);
234 ucontrol->value.integer.value[0] = tas->cached_volume_l; 241 ucontrol->value.integer.value[0] = tas->cached_volume_l;
235 ucontrol->value.integer.value[1] = tas->cached_volume_r; 242 ucontrol->value.integer.value[1] = tas->cached_volume_r;
243 mutex_unlock(&tas->mtx);
236 return 0; 244 return 0;
237} 245}
238 246
@@ -241,14 +249,18 @@ static int tas_snd_vol_put(struct snd_kcontrol *kcontrol,
241{ 249{
242 struct tas *tas = snd_kcontrol_chip(kcontrol); 250 struct tas *tas = snd_kcontrol_chip(kcontrol);
243 251
252 mutex_lock(&tas->mtx);
244 if (tas->cached_volume_l == ucontrol->value.integer.value[0] 253 if (tas->cached_volume_l == ucontrol->value.integer.value[0]
245 && tas->cached_volume_r == ucontrol->value.integer.value[1]) 254 && tas->cached_volume_r == ucontrol->value.integer.value[1]) {
255 mutex_unlock(&tas->mtx);
246 return 0; 256 return 0;
257 }
247 258
248 tas->cached_volume_l = ucontrol->value.integer.value[0]; 259 tas->cached_volume_l = ucontrol->value.integer.value[0];
249 tas->cached_volume_r = ucontrol->value.integer.value[1]; 260 tas->cached_volume_r = ucontrol->value.integer.value[1];
250 if (tas->hw_enabled) 261 if (tas->hw_enabled)
251 tas_set_volume(tas); 262 tas_set_volume(tas);
263 mutex_unlock(&tas->mtx);
252 return 1; 264 return 1;
253} 265}
254 266
@@ -276,8 +288,10 @@ static int tas_snd_mute_get(struct snd_kcontrol *kcontrol,
276{ 288{
277 struct tas *tas = snd_kcontrol_chip(kcontrol); 289 struct tas *tas = snd_kcontrol_chip(kcontrol);
278 290
291 mutex_lock(&tas->mtx);
279 ucontrol->value.integer.value[0] = !tas->mute_l; 292 ucontrol->value.integer.value[0] = !tas->mute_l;
280 ucontrol->value.integer.value[1] = !tas->mute_r; 293 ucontrol->value.integer.value[1] = !tas->mute_r;
294 mutex_unlock(&tas->mtx);
281 return 0; 295 return 0;
282} 296}
283 297
@@ -286,14 +300,18 @@ static int tas_snd_mute_put(struct snd_kcontrol *kcontrol,
286{ 300{
287 struct tas *tas = snd_kcontrol_chip(kcontrol); 301 struct tas *tas = snd_kcontrol_chip(kcontrol);
288 302
303 mutex_lock(&tas->mtx);
289 if (tas->mute_l == !ucontrol->value.integer.value[0] 304 if (tas->mute_l == !ucontrol->value.integer.value[0]
290 && tas->mute_r == !ucontrol->value.integer.value[1]) 305 && tas->mute_r == !ucontrol->value.integer.value[1]) {
306 mutex_unlock(&tas->mtx);
291 return 0; 307 return 0;
308 }
292 309
293 tas->mute_l = !ucontrol->value.integer.value[0]; 310 tas->mute_l = !ucontrol->value.integer.value[0];
294 tas->mute_r = !ucontrol->value.integer.value[1]; 311 tas->mute_r = !ucontrol->value.integer.value[1];
295 if (tas->hw_enabled) 312 if (tas->hw_enabled)
296 tas_set_volume(tas); 313 tas_set_volume(tas);
314 mutex_unlock(&tas->mtx);
297 return 1; 315 return 1;
298} 316}
299 317
@@ -322,8 +340,10 @@ static int tas_snd_mixer_get(struct snd_kcontrol *kcontrol,
322 struct tas *tas = snd_kcontrol_chip(kcontrol); 340 struct tas *tas = snd_kcontrol_chip(kcontrol);
323 int idx = kcontrol->private_value; 341 int idx = kcontrol->private_value;
324 342
343 mutex_lock(&tas->mtx);
325 ucontrol->value.integer.value[0] = tas->mixer_l[idx]; 344 ucontrol->value.integer.value[0] = tas->mixer_l[idx];
326 ucontrol->value.integer.value[1] = tas->mixer_r[idx]; 345 ucontrol->value.integer.value[1] = tas->mixer_r[idx];
346 mutex_unlock(&tas->mtx);
327 347
328 return 0; 348 return 0;
329} 349}
@@ -334,15 +354,19 @@ static int tas_snd_mixer_put(struct snd_kcontrol *kcontrol,
334 struct tas *tas = snd_kcontrol_chip(kcontrol); 354 struct tas *tas = snd_kcontrol_chip(kcontrol);
335 int idx = kcontrol->private_value; 355 int idx = kcontrol->private_value;
336 356
357 mutex_lock(&tas->mtx);
337 if (tas->mixer_l[idx] == ucontrol->value.integer.value[0] 358 if (tas->mixer_l[idx] == ucontrol->value.integer.value[0]
338 && tas->mixer_r[idx] == ucontrol->value.integer.value[1]) 359 && tas->mixer_r[idx] == ucontrol->value.integer.value[1]) {
360 mutex_unlock(&tas->mtx);
339 return 0; 361 return 0;
362 }
340 363
341 tas->mixer_l[idx] = ucontrol->value.integer.value[0]; 364 tas->mixer_l[idx] = ucontrol->value.integer.value[0];
342 tas->mixer_r[idx] = ucontrol->value.integer.value[1]; 365 tas->mixer_r[idx] = ucontrol->value.integer.value[1];
343 366
344 if (tas->hw_enabled) 367 if (tas->hw_enabled)
345 tas_set_mixer(tas); 368 tas_set_mixer(tas);
369 mutex_unlock(&tas->mtx);
346 return 1; 370 return 1;
347} 371}
348 372
@@ -375,7 +399,9 @@ static int tas_snd_drc_range_get(struct snd_kcontrol *kcontrol,
375{ 399{
376 struct tas *tas = snd_kcontrol_chip(kcontrol); 400 struct tas *tas = snd_kcontrol_chip(kcontrol);
377 401
402 mutex_lock(&tas->mtx);
378 ucontrol->value.integer.value[0] = tas->drc_range; 403 ucontrol->value.integer.value[0] = tas->drc_range;
404 mutex_unlock(&tas->mtx);
379 return 0; 405 return 0;
380} 406}
381 407
@@ -384,12 +410,16 @@ static int tas_snd_drc_range_put(struct snd_kcontrol *kcontrol,
384{ 410{
385 struct tas *tas = snd_kcontrol_chip(kcontrol); 411 struct tas *tas = snd_kcontrol_chip(kcontrol);
386 412
387 if (tas->drc_range == ucontrol->value.integer.value[0]) 413 mutex_lock(&tas->mtx);
414 if (tas->drc_range == ucontrol->value.integer.value[0]) {
415 mutex_unlock(&tas->mtx);
388 return 0; 416 return 0;
417 }
389 418
390 tas->drc_range = ucontrol->value.integer.value[0]; 419 tas->drc_range = ucontrol->value.integer.value[0];
391 if (tas->hw_enabled) 420 if (tas->hw_enabled)
392 tas3004_set_drc(tas); 421 tas3004_set_drc(tas);
422 mutex_unlock(&tas->mtx);
393 return 1; 423 return 1;
394} 424}
395 425
@@ -417,7 +447,9 @@ static int tas_snd_drc_switch_get(struct snd_kcontrol *kcontrol,
417{ 447{
418 struct tas *tas = snd_kcontrol_chip(kcontrol); 448 struct tas *tas = snd_kcontrol_chip(kcontrol);
419 449
450 mutex_lock(&tas->mtx);
420 ucontrol->value.integer.value[0] = tas->drc_enabled; 451 ucontrol->value.integer.value[0] = tas->drc_enabled;
452 mutex_unlock(&tas->mtx);
421 return 0; 453 return 0;
422} 454}
423 455
@@ -426,12 +458,16 @@ static int tas_snd_drc_switch_put(struct snd_kcontrol *kcontrol,
426{ 458{
427 struct tas *tas = snd_kcontrol_chip(kcontrol); 459 struct tas *tas = snd_kcontrol_chip(kcontrol);
428 460
429 if (tas->drc_enabled == ucontrol->value.integer.value[0]) 461 mutex_lock(&tas->mtx);
462 if (tas->drc_enabled == ucontrol->value.integer.value[0]) {
463 mutex_unlock(&tas->mtx);
430 return 0; 464 return 0;
465 }
431 466
432 tas->drc_enabled = ucontrol->value.integer.value[0]; 467 tas->drc_enabled = ucontrol->value.integer.value[0];
433 if (tas->hw_enabled) 468 if (tas->hw_enabled)
434 tas3004_set_drc(tas); 469 tas3004_set_drc(tas);
470 mutex_unlock(&tas->mtx);
435 return 1; 471 return 1;
436} 472}
437 473
@@ -463,7 +499,9 @@ static int tas_snd_capture_source_get(struct snd_kcontrol *kcontrol,
463{ 499{
464 struct tas *tas = snd_kcontrol_chip(kcontrol); 500 struct tas *tas = snd_kcontrol_chip(kcontrol);
465 501
502 mutex_lock(&tas->mtx);
466 ucontrol->value.enumerated.item[0] = !!(tas->acr & TAS_ACR_INPUT_B); 503 ucontrol->value.enumerated.item[0] = !!(tas->acr & TAS_ACR_INPUT_B);
504 mutex_unlock(&tas->mtx);
467 return 0; 505 return 0;
468} 506}
469 507
@@ -471,15 +509,21 @@ static int tas_snd_capture_source_put(struct snd_kcontrol *kcontrol,
471 struct snd_ctl_elem_value *ucontrol) 509 struct snd_ctl_elem_value *ucontrol)
472{ 510{
473 struct tas *tas = snd_kcontrol_chip(kcontrol); 511 struct tas *tas = snd_kcontrol_chip(kcontrol);
474 int oldacr = tas->acr; 512 int oldacr;
513
514 mutex_lock(&tas->mtx);
515 oldacr = tas->acr;
475 516
476 tas->acr &= ~TAS_ACR_INPUT_B; 517 tas->acr &= ~TAS_ACR_INPUT_B;
477 if (ucontrol->value.enumerated.item[0]) 518 if (ucontrol->value.enumerated.item[0])
478 tas->acr |= TAS_ACR_INPUT_B; 519 tas->acr |= TAS_ACR_INPUT_B;
479 if (oldacr == tas->acr) 520 if (oldacr == tas->acr) {
521 mutex_unlock(&tas->mtx);
480 return 0; 522 return 0;
523 }
481 if (tas->hw_enabled) 524 if (tas->hw_enabled)
482 tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr); 525 tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr);
526 mutex_unlock(&tas->mtx);
483 return 1; 527 return 1;
484} 528}
485 529
@@ -518,7 +562,9 @@ static int tas_snd_treble_get(struct snd_kcontrol *kcontrol,
518{ 562{
519 struct tas *tas = snd_kcontrol_chip(kcontrol); 563 struct tas *tas = snd_kcontrol_chip(kcontrol);
520 564
565 mutex_lock(&tas->mtx);
521 ucontrol->value.integer.value[0] = tas->treble; 566 ucontrol->value.integer.value[0] = tas->treble;
567 mutex_unlock(&tas->mtx);
522 return 0; 568 return 0;
523} 569}
524 570
@@ -527,12 +573,16 @@ static int tas_snd_treble_put(struct snd_kcontrol *kcontrol,
527{ 573{
528 struct tas *tas = snd_kcontrol_chip(kcontrol); 574 struct tas *tas = snd_kcontrol_chip(kcontrol);
529 575
530 if (tas->treble == ucontrol->value.integer.value[0]) 576 mutex_lock(&tas->mtx);
577 if (tas->treble == ucontrol->value.integer.value[0]) {
578 mutex_unlock(&tas->mtx);
531 return 0; 579 return 0;
580 }
532 581
533 tas->treble = ucontrol->value.integer.value[0]; 582 tas->treble = ucontrol->value.integer.value[0];
534 if (tas->hw_enabled) 583 if (tas->hw_enabled)
535 tas_set_treble(tas); 584 tas_set_treble(tas);
585 mutex_unlock(&tas->mtx);
536 return 1; 586 return 1;
537} 587}
538 588
@@ -560,7 +610,9 @@ static int tas_snd_bass_get(struct snd_kcontrol *kcontrol,
560{ 610{
561 struct tas *tas = snd_kcontrol_chip(kcontrol); 611 struct tas *tas = snd_kcontrol_chip(kcontrol);
562 612
613 mutex_lock(&tas->mtx);
563 ucontrol->value.integer.value[0] = tas->bass; 614 ucontrol->value.integer.value[0] = tas->bass;
615 mutex_unlock(&tas->mtx);
564 return 0; 616 return 0;
565} 617}
566 618
@@ -569,12 +621,16 @@ static int tas_snd_bass_put(struct snd_kcontrol *kcontrol,
569{ 621{
570 struct tas *tas = snd_kcontrol_chip(kcontrol); 622 struct tas *tas = snd_kcontrol_chip(kcontrol);
571 623
572 if (tas->bass == ucontrol->value.integer.value[0]) 624 mutex_lock(&tas->mtx);
625 if (tas->bass == ucontrol->value.integer.value[0]) {
626 mutex_unlock(&tas->mtx);
573 return 0; 627 return 0;
628 }
574 629
575 tas->bass = ucontrol->value.integer.value[0]; 630 tas->bass = ucontrol->value.integer.value[0];
576 if (tas->hw_enabled) 631 if (tas->hw_enabled)
577 tas_set_bass(tas); 632 tas_set_bass(tas);
633 mutex_unlock(&tas->mtx);
578 return 1; 634 return 1;
579} 635}
580 636
@@ -628,16 +684,16 @@ static int tas_reset_init(struct tas *tas)
628 684
629 tmp = TAS_MCS_SCLK64 | TAS_MCS_SPORT_MODE_I2S | TAS_MCS_SPORT_WL_24BIT; 685 tmp = TAS_MCS_SCLK64 | TAS_MCS_SPORT_MODE_I2S | TAS_MCS_SPORT_WL_24BIT;
630 if (tas_write_reg(tas, TAS_REG_MCS, 1, &tmp)) 686 if (tas_write_reg(tas, TAS_REG_MCS, 1, &tmp))
631 return -ENODEV; 687 goto outerr;
632 688
633 tas->acr |= TAS_ACR_ANALOG_PDOWN | TAS_ACR_B_MONAUREAL | 689 tas->acr |= TAS_ACR_ANALOG_PDOWN | TAS_ACR_B_MONAUREAL |
634 TAS_ACR_B_MON_SEL_RIGHT; 690 TAS_ACR_B_MON_SEL_RIGHT;
635 if (tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr)) 691 if (tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr))
636 return -ENODEV; 692 goto outerr;
637 693
638 tmp = 0; 694 tmp = 0;
639 if (tas_write_reg(tas, TAS_REG_MCS2, 1, &tmp)) 695 if (tas_write_reg(tas, TAS_REG_MCS2, 1, &tmp))
640 return -ENODEV; 696 goto outerr;
641 697
642 tas3004_set_drc(tas); 698 tas3004_set_drc(tas);
643 699
@@ -649,9 +705,11 @@ static int tas_reset_init(struct tas *tas)
649 705
650 tas->acr &= ~TAS_ACR_ANALOG_PDOWN; 706 tas->acr &= ~TAS_ACR_ANALOG_PDOWN;
651 if (tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr)) 707 if (tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr))
652 return -ENODEV; 708 goto outerr;
653 709
654 return 0; 710 return 0;
711 outerr:
712 return -ENODEV;
655} 713}
656 714
657static int tas_switch_clock(struct codec_info_item *cii, enum clock_switch clock) 715static int tas_switch_clock(struct codec_info_item *cii, enum clock_switch clock)
@@ -666,11 +724,13 @@ static int tas_switch_clock(struct codec_info_item *cii, enum clock_switch clock
666 break; 724 break;
667 case CLOCK_SWITCH_SLAVE: 725 case CLOCK_SWITCH_SLAVE:
668 /* Clocks are back, re-init the codec */ 726 /* Clocks are back, re-init the codec */
727 mutex_lock(&tas->mtx);
669 tas_reset_init(tas); 728 tas_reset_init(tas);
670 tas_set_volume(tas); 729 tas_set_volume(tas);
671 tas_set_mixer(tas); 730 tas_set_mixer(tas);
672 tas->hw_enabled = 1; 731 tas->hw_enabled = 1;
673 tas->codec.gpio->methods->all_amps_restore(tas->codec.gpio); 732 tas->codec.gpio->methods->all_amps_restore(tas->codec.gpio);
733 mutex_unlock(&tas->mtx);
674 break; 734 break;
675 default: 735 default:
676 /* doesn't happen as of now */ 736 /* doesn't happen as of now */
@@ -684,19 +744,23 @@ static int tas_switch_clock(struct codec_info_item *cii, enum clock_switch clock
684 * our i2c device is suspended, and then take note of that! */ 744 * our i2c device is suspended, and then take note of that! */
685static int tas_suspend(struct tas *tas) 745static int tas_suspend(struct tas *tas)
686{ 746{
747 mutex_lock(&tas->mtx);
687 tas->hw_enabled = 0; 748 tas->hw_enabled = 0;
688 tas->acr |= TAS_ACR_ANALOG_PDOWN; 749 tas->acr |= TAS_ACR_ANALOG_PDOWN;
689 tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr); 750 tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr);
751 mutex_unlock(&tas->mtx);
690 return 0; 752 return 0;
691} 753}
692 754
693static int tas_resume(struct tas *tas) 755static int tas_resume(struct tas *tas)
694{ 756{
695 /* reset codec */ 757 /* reset codec */
758 mutex_lock(&tas->mtx);
696 tas_reset_init(tas); 759 tas_reset_init(tas);
697 tas_set_volume(tas); 760 tas_set_volume(tas);
698 tas_set_mixer(tas); 761 tas_set_mixer(tas);
699 tas->hw_enabled = 1; 762 tas->hw_enabled = 1;
763 mutex_unlock(&tas->mtx);
700 return 0; 764 return 0;
701} 765}
702 766
@@ -739,11 +803,14 @@ static int tas_init_codec(struct aoa_codec *codec)
739 return -EINVAL; 803 return -EINVAL;
740 } 804 }
741 805
806 mutex_lock(&tas->mtx);
742 if (tas_reset_init(tas)) { 807 if (tas_reset_init(tas)) {
743 printk(KERN_ERR PFX "tas failed to initialise\n"); 808 printk(KERN_ERR PFX "tas failed to initialise\n");
809 mutex_unlock(&tas->mtx);
744 return -ENXIO; 810 return -ENXIO;
745 } 811 }
746 tas->hw_enabled = 1; 812 tas->hw_enabled = 1;
813 mutex_unlock(&tas->mtx);
747 814
748 if (tas->codec.soundbus_dev->attach_codec(tas->codec.soundbus_dev, 815 if (tas->codec.soundbus_dev->attach_codec(tas->codec.soundbus_dev,
749 aoa_get_card(), 816 aoa_get_card(),
@@ -822,6 +889,7 @@ static int tas_create(struct i2c_adapter *adapter,
822 if (!tas) 889 if (!tas)
823 return -ENOMEM; 890 return -ENOMEM;
824 891
892 mutex_init(&tas->mtx);
825 tas->i2c.driver = &tas_driver; 893 tas->i2c.driver = &tas_driver;
826 tas->i2c.adapter = adapter; 894 tas->i2c.adapter = adapter;
827 tas->i2c.addr = addr; 895 tas->i2c.addr = addr;
@@ -850,6 +918,7 @@ static int tas_create(struct i2c_adapter *adapter,
850 detach: 918 detach:
851 i2c_detach_client(&tas->i2c); 919 i2c_detach_client(&tas->i2c);
852 fail: 920 fail:
921 mutex_destroy(&tas->mtx);
853 kfree(tas); 922 kfree(tas);
854 return -EINVAL; 923 return -EINVAL;
855} 924}
@@ -908,6 +977,7 @@ static int tas_i2c_detach(struct i2c_client *client)
908 /* power down codec chip */ 977 /* power down codec chip */
909 tas_write_reg(tas, TAS_REG_ACR, 1, &tmp); 978 tas_write_reg(tas, TAS_REG_ACR, 1, &tmp);
910 979
980 mutex_destroy(&tas->mtx);
911 kfree(tas); 981 kfree(tas);
912 return 0; 982 return 0;
913} 983}