1515#include <linux/module.h>
1616#include <linux/kernel.h>
1717#include <linux/device.h>
18+ #include <linux/regmap.h>
1819#include <sound/core.h>
1920#include <sound/pcm.h>
2021#include <sound/ac97_codec.h>
2122#include <sound/initval.h>
2223#include <sound/soc.h>
2324#include <sound/tlv.h>
24- #include "wm9712.h"
2525
2626#define WM9712_VENDOR_ID 0x574d4c12
2727#define WM9712_VENDOR_ID_MASK 0xffffffff
@@ -32,31 +32,66 @@ struct wm9712_priv {
3232 struct mutex lock ;
3333};
3434
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+ };
3973
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 ),
6095};
6196
6297#define HPL_MIXER 0x0
@@ -485,75 +520,36 @@ static const struct snd_soc_dapm_route wm9712_audio_map[] = {
485520 {"ROUT2" , NULL , "Speaker PGA" },
486521};
487522
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-
522523static int ac97_prepare (struct snd_pcm_substream * substream ,
523524 struct snd_soc_dai * dai )
524525{
525526 struct snd_soc_codec * codec = dai -> codec ;
526527 int reg ;
527- u16 vra ;
528528 struct snd_pcm_runtime * runtime = substream -> runtime ;
529529
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 );
532531
533532 if (substream -> stream == SNDRV_PCM_STREAM_PLAYBACK )
534533 reg = AC97_PCM_FRONT_DAC_RATE ;
535534 else
536535 reg = AC97_PCM_LR_ADC_RATE ;
537536
538- return ac97_write (codec , reg , runtime -> rate );
537+ return snd_soc_write (codec , reg , runtime -> rate );
539538}
540539
541540static int ac97_aux_prepare (struct snd_pcm_substream * substream ,
542541 struct snd_soc_dai * dai )
543542{
544543 struct snd_soc_codec * codec = dai -> codec ;
545- u16 vra , xsle ;
546544 struct snd_pcm_runtime * runtime = substream -> runtime ;
547545
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 );
552548
553549 if (substream -> stream != SNDRV_PCM_STREAM_PLAYBACK )
554550 return - ENODEV ;
555551
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 );
557553}
558554
559555#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,
605601 case SND_SOC_BIAS_PREPARE :
606602 break ;
607603 case SND_SOC_BIAS_STANDBY :
608- ac97_write (codec , AC97_POWERDOWN , 0x0000 );
604+ snd_soc_write (codec , AC97_POWERDOWN , 0x0000 );
609605 break ;
610606 case SND_SOC_BIAS_OFF :
611607 /* 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 );
614610 break ;
615611 }
616612 return 0 ;
@@ -619,8 +615,7 @@ static int wm9712_set_bias_level(struct snd_soc_codec *codec,
619615static int wm9712_soc_resume (struct snd_soc_codec * codec )
620616{
621617 struct wm9712_priv * wm9712 = snd_soc_codec_get_drvdata (codec );
622- int i , ret ;
623- u16 * cache = codec -> reg_cache ;
618+ int ret ;
624619
625620 ret = snd_ac97_reset (wm9712 -> ac97 , true, WM9712_VENDOR_ID ,
626621 WM9712_VENDOR_ID_MASK );
@@ -629,22 +624,16 @@ static int wm9712_soc_resume(struct snd_soc_codec *codec)
629624
630625 snd_soc_codec_force_bias_level (codec , SND_SOC_BIAS_STANDBY );
631626
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 );
641629
642630 return ret ;
643631}
644632
645633static int wm9712_soc_probe (struct snd_soc_codec * codec )
646634{
647635 struct wm9712_priv * wm9712 = snd_soc_codec_get_drvdata (codec );
636+ struct regmap * regmap ;
648637 int ret ;
649638
650639 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)
655644 return ret ;
656645 }
657646
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+
658655 /* 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 );
660657
661658 return 0 ;
659+ err_free_ac97_codec :
660+ snd_soc_free_ac97_codec (wm9712 -> ac97 );
661+ return ret ;
662662}
663663
664664static int wm9712_soc_remove (struct snd_soc_codec * codec )
665665{
666666 struct wm9712_priv * wm9712 = snd_soc_codec_get_drvdata (codec );
667667
668+ snd_soc_codec_exit_regmap (codec );
668669 snd_soc_free_ac97_codec (wm9712 -> ac97 );
669670 return 0 ;
670671}
@@ -673,14 +674,8 @@ static const struct snd_soc_codec_driver soc_codec_dev_wm9712 = {
673674 .probe = wm9712_soc_probe ,
674675 .remove = wm9712_soc_remove ,
675676 .resume = wm9712_soc_resume ,
676- .read = ac97_read ,
677- .write = ac97_write ,
678677 .set_bias_level = wm9712_set_bias_level ,
679678 .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 ,
684679
685680 .component_driver = {
686681 .controls = wm9712_snd_ac97_controls ,
0 commit comments