15
15
#include <linux/module.h>
16
16
#include <linux/kernel.h>
17
17
#include <linux/device.h>
18
+ #include <linux/regmap.h>
18
19
#include <sound/core.h>
19
20
#include <sound/pcm.h>
20
21
#include <sound/ac97_codec.h>
21
22
#include <sound/initval.h>
22
23
#include <sound/soc.h>
23
24
#include <sound/tlv.h>
24
- #include "wm9712.h"
25
25
26
26
#define WM9712_VENDOR_ID 0x574d4c12
27
27
#define WM9712_VENDOR_ID_MASK 0xffffffff
@@ -32,31 +32,66 @@ struct wm9712_priv {
32
32
struct mutex lock ;
33
33
};
34
34
35
- static unsigned int ac97_read (struct snd_soc_codec * codec ,
36
- unsigned int reg );
37
- static int ac97_write (struct snd_soc_codec * codec ,
38
- unsigned int reg , unsigned int val );
35
+ static const struct reg_default wm9712_reg_defaults [] = {
36
+ { 0x02 , 0x8000 },
37
+ { 0x04 , 0x8000 },
38
+ { 0x06 , 0x8000 },
39
+ { 0x08 , 0x0f0f },
40
+ { 0x0a , 0xaaa0 },
41
+ { 0x0c , 0xc008 },
42
+ { 0x0e , 0x6808 },
43
+ { 0x10 , 0xe808 },
44
+ { 0x12 , 0xaaa0 },
45
+ { 0x14 , 0xad00 },
46
+ { 0x16 , 0x8000 },
47
+ { 0x18 , 0xe808 },
48
+ { 0x1a , 0x3000 },
49
+ { 0x1c , 0x8000 },
50
+ { 0x20 , 0x0000 },
51
+ { 0x22 , 0x0000 },
52
+ { 0x26 , 0x000f },
53
+ { 0x28 , 0x0605 },
54
+ { 0x2a , 0x0410 },
55
+ { 0x2c , 0xbb80 },
56
+ { 0x2e , 0xbb80 },
57
+ { 0x32 , 0xbb80 },
58
+ { 0x34 , 0x2000 },
59
+ { 0x4c , 0xf83e },
60
+ { 0x4e , 0xffff },
61
+ { 0x50 , 0x0000 },
62
+ { 0x52 , 0x0000 },
63
+ { 0x56 , 0xf83e },
64
+ { 0x58 , 0x0008 },
65
+ { 0x5c , 0x0000 },
66
+ { 0x60 , 0xb032 },
67
+ { 0x62 , 0x3e00 },
68
+ { 0x64 , 0x0000 },
69
+ { 0x76 , 0x0006 },
70
+ { 0x78 , 0x0001 },
71
+ { 0x7a , 0x0000 },
72
+ };
39
73
40
- /*
41
- * WM9712 register cache
42
- */
43
- static const u16 wm9712_reg [] = {
44
- 0x6174 , 0x8000 , 0x8000 , 0x8000 , /* 6 */
45
- 0x0f0f , 0xaaa0 , 0xc008 , 0x6808 , /* e */
46
- 0xe808 , 0xaaa0 , 0xad00 , 0x8000 , /* 16 */
47
- 0xe808 , 0x3000 , 0x8000 , 0x0000 , /* 1e */
48
- 0x0000 , 0x0000 , 0x0000 , 0x000f , /* 26 */
49
- 0x0405 , 0x0410 , 0xbb80 , 0xbb80 , /* 2e */
50
- 0x0000 , 0xbb80 , 0x0000 , 0x0000 , /* 36 */
51
- 0x0000 , 0x2000 , 0x0000 , 0x0000 , /* 3e */
52
- 0x0000 , 0x0000 , 0x0000 , 0x0000 , /* 46 */
53
- 0x0000 , 0x0000 , 0xf83e , 0xffff , /* 4e */
54
- 0x0000 , 0x0000 , 0x0000 , 0xf83e , /* 56 */
55
- 0x0008 , 0x0000 , 0x0000 , 0x0000 , /* 5e */
56
- 0xb032 , 0x3e00 , 0x0000 , 0x0000 , /* 66 */
57
- 0x0000 , 0x0000 , 0x0000 , 0x0000 , /* 6e */
58
- 0x0000 , 0x0000 , 0x0000 , 0x0006 , /* 76 */
59
- 0x0001 , 0x0000 , 0x574d , 0x4c12 , /* 7e */
74
+ static bool wm9712_volatile_reg (struct device * dev , unsigned int reg )
75
+ {
76
+ switch (reg ) {
77
+ case AC97_REC_GAIN :
78
+ return true;
79
+ default :
80
+ return regmap_ac97_default_volatile (dev , reg );
81
+ }
82
+ }
83
+
84
+ static const struct regmap_config wm9712_regmap_config = {
85
+ .reg_bits = 16 ,
86
+ .reg_stride = 2 ,
87
+ .val_bits = 16 ,
88
+ .max_register = 0x7e ,
89
+ .cache_type = REGCACHE_RBTREE ,
90
+
91
+ .volatile_reg = wm9712_volatile_reg ,
92
+
93
+ .reg_defaults = wm9712_reg_defaults ,
94
+ .num_reg_defaults = ARRAY_SIZE (wm9712_reg_defaults ),
60
95
};
61
96
62
97
#define HPL_MIXER 0x0
@@ -485,75 +520,36 @@ static const struct snd_soc_dapm_route wm9712_audio_map[] = {
485
520
{"ROUT2" , NULL , "Speaker PGA" },
486
521
};
487
522
488
- static unsigned int ac97_read (struct snd_soc_codec * codec ,
489
- unsigned int reg )
490
- {
491
- struct wm9712_priv * wm9712 = snd_soc_codec_get_drvdata (codec );
492
- u16 * cache = codec -> reg_cache ;
493
-
494
- if (reg == AC97_RESET || reg == AC97_GPIO_STATUS ||
495
- reg == AC97_VENDOR_ID1 || reg == AC97_VENDOR_ID2 ||
496
- reg == AC97_REC_GAIN )
497
- return soc_ac97_ops -> read (wm9712 -> ac97 , reg );
498
- else {
499
- reg = reg >> 1 ;
500
-
501
- if (reg >= (ARRAY_SIZE (wm9712_reg )))
502
- return - EIO ;
503
-
504
- return cache [reg ];
505
- }
506
- }
507
-
508
- static int ac97_write (struct snd_soc_codec * codec , unsigned int reg ,
509
- unsigned int val )
510
- {
511
- struct wm9712_priv * wm9712 = snd_soc_codec_get_drvdata (codec );
512
- u16 * cache = codec -> reg_cache ;
513
-
514
- soc_ac97_ops -> write (wm9712 -> ac97 , reg , val );
515
- reg = reg >> 1 ;
516
- if (reg < (ARRAY_SIZE (wm9712_reg )))
517
- cache [reg ] = val ;
518
-
519
- return 0 ;
520
- }
521
-
522
523
static int ac97_prepare (struct snd_pcm_substream * substream ,
523
524
struct snd_soc_dai * dai )
524
525
{
525
526
struct snd_soc_codec * codec = dai -> codec ;
526
527
int reg ;
527
- u16 vra ;
528
528
struct snd_pcm_runtime * runtime = substream -> runtime ;
529
529
530
- vra = ac97_read (codec , AC97_EXTENDED_STATUS );
531
- ac97_write (codec , AC97_EXTENDED_STATUS , vra | 0x1 );
530
+ snd_soc_update_bits (codec , AC97_EXTENDED_STATUS , 0x1 , 0x1 );
532
531
533
532
if (substream -> stream == SNDRV_PCM_STREAM_PLAYBACK )
534
533
reg = AC97_PCM_FRONT_DAC_RATE ;
535
534
else
536
535
reg = AC97_PCM_LR_ADC_RATE ;
537
536
538
- return ac97_write (codec , reg , runtime -> rate );
537
+ return snd_soc_write (codec , reg , runtime -> rate );
539
538
}
540
539
541
540
static int ac97_aux_prepare (struct snd_pcm_substream * substream ,
542
541
struct snd_soc_dai * dai )
543
542
{
544
543
struct snd_soc_codec * codec = dai -> codec ;
545
- u16 vra , xsle ;
546
544
struct snd_pcm_runtime * runtime = substream -> runtime ;
547
545
548
- vra = ac97_read (codec , AC97_EXTENDED_STATUS );
549
- ac97_write (codec , AC97_EXTENDED_STATUS , vra | 0x1 );
550
- xsle = ac97_read (codec , AC97_PCI_SID );
551
- ac97_write (codec , AC97_PCI_SID , xsle | 0x8000 );
546
+ snd_soc_update_bits (codec , AC97_EXTENDED_STATUS , 0x1 , 0x1 );
547
+ snd_soc_update_bits (codec , AC97_PCI_SID , 0x8000 , 0x8000 );
552
548
553
549
if (substream -> stream != SNDRV_PCM_STREAM_PLAYBACK )
554
550
return - ENODEV ;
555
551
556
- return ac97_write (codec , AC97_PCM_SURR_DAC_RATE , runtime -> rate );
552
+ return snd_soc_write (codec , AC97_PCM_SURR_DAC_RATE , runtime -> rate );
557
553
}
558
554
559
555
#define WM9712_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
@@ -605,12 +601,12 @@ static int wm9712_set_bias_level(struct snd_soc_codec *codec,
605
601
case SND_SOC_BIAS_PREPARE :
606
602
break ;
607
603
case SND_SOC_BIAS_STANDBY :
608
- ac97_write (codec , AC97_POWERDOWN , 0x0000 );
604
+ snd_soc_write (codec , AC97_POWERDOWN , 0x0000 );
609
605
break ;
610
606
case SND_SOC_BIAS_OFF :
611
607
/* disable everything including AC link */
612
- ac97_write (codec , AC97_EXTENDED_MSTATUS , 0xffff );
613
- ac97_write (codec , AC97_POWERDOWN , 0xffff );
608
+ snd_soc_write (codec , AC97_EXTENDED_MSTATUS , 0xffff );
609
+ snd_soc_write (codec , AC97_POWERDOWN , 0xffff );
614
610
break ;
615
611
}
616
612
return 0 ;
@@ -619,8 +615,7 @@ static int wm9712_set_bias_level(struct snd_soc_codec *codec,
619
615
static int wm9712_soc_resume (struct snd_soc_codec * codec )
620
616
{
621
617
struct wm9712_priv * wm9712 = snd_soc_codec_get_drvdata (codec );
622
- int i , ret ;
623
- u16 * cache = codec -> reg_cache ;
618
+ int ret ;
624
619
625
620
ret = snd_ac97_reset (wm9712 -> ac97 , true, WM9712_VENDOR_ID ,
626
621
WM9712_VENDOR_ID_MASK );
@@ -629,22 +624,16 @@ static int wm9712_soc_resume(struct snd_soc_codec *codec)
629
624
630
625
snd_soc_codec_force_bias_level (codec , SND_SOC_BIAS_STANDBY );
631
626
632
- if (ret == 0 ) {
633
- /* Sync reg_cache with the hardware after cold reset */
634
- for (i = 2 ; i < ARRAY_SIZE (wm9712_reg ) << 1 ; i += 2 ) {
635
- if (i == AC97_INT_PAGING || i == AC97_POWERDOWN ||
636
- (i > 0x58 && i != 0x5c ))
637
- continue ;
638
- soc_ac97_ops -> write (wm9712 -> ac97 , i , cache [i >>1 ]);
639
- }
640
- }
627
+ if (ret == 0 )
628
+ regcache_sync (codec -> component .regmap );
641
629
642
630
return ret ;
643
631
}
644
632
645
633
static int wm9712_soc_probe (struct snd_soc_codec * codec )
646
634
{
647
635
struct wm9712_priv * wm9712 = snd_soc_codec_get_drvdata (codec );
636
+ struct regmap * regmap ;
648
637
int ret ;
649
638
650
639
wm9712 -> ac97 = snd_soc_new_ac97_codec (codec , WM9712_VENDOR_ID ,
@@ -655,16 +644,28 @@ static int wm9712_soc_probe(struct snd_soc_codec *codec)
655
644
return ret ;
656
645
}
657
646
647
+ regmap = regmap_init_ac97 (wm9712 -> ac97 , & wm9712_regmap_config );
648
+ if (IS_ERR (regmap )) {
649
+ ret = PTR_ERR (regmap );
650
+ goto err_free_ac97_codec ;
651
+ }
652
+
653
+ snd_soc_codec_init_regmap (codec , regmap );
654
+
658
655
/* set alc mux to none */
659
- ac97_write (codec , AC97_VIDEO , ac97_read ( codec , AC97_VIDEO ) | 0x3000 );
656
+ snd_soc_update_bits (codec , AC97_VIDEO , 0x3000 , 0x3000 );
660
657
661
658
return 0 ;
659
+ err_free_ac97_codec :
660
+ snd_soc_free_ac97_codec (wm9712 -> ac97 );
661
+ return ret ;
662
662
}
663
663
664
664
static int wm9712_soc_remove (struct snd_soc_codec * codec )
665
665
{
666
666
struct wm9712_priv * wm9712 = snd_soc_codec_get_drvdata (codec );
667
667
668
+ snd_soc_codec_exit_regmap (codec );
668
669
snd_soc_free_ac97_codec (wm9712 -> ac97 );
669
670
return 0 ;
670
671
}
@@ -673,14 +674,8 @@ static const struct snd_soc_codec_driver soc_codec_dev_wm9712 = {
673
674
.probe = wm9712_soc_probe ,
674
675
.remove = wm9712_soc_remove ,
675
676
.resume = wm9712_soc_resume ,
676
- .read = ac97_read ,
677
- .write = ac97_write ,
678
677
.set_bias_level = wm9712_set_bias_level ,
679
678
.suspend_bias_off = true,
680
- .reg_cache_size = ARRAY_SIZE (wm9712_reg ),
681
- .reg_word_size = sizeof (u16 ),
682
- .reg_cache_step = 2 ,
683
- .reg_cache_default = wm9712_reg ,
684
679
685
680
.component_driver = {
686
681
.controls = wm9712_snd_ac97_controls ,
0 commit comments