Skip to content

Commit 700dadf

Browse files
rjarzmikbroonie
authored andcommitted
ASoC: wm9713: convert to regmap
Convert the Wolfson WM9713 to regmap API. This will leverage all the regmap functions (debug, registers update, etc ...). As a bonus, this will pave the path to gpio chip introduction, and devicetree support. This was tested on the mioa701 board, pxa27x based, in PCM playback, and through suspend/resume. Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr> Reviewed-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com> Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent 8005c49 commit 700dadf

File tree

2 files changed

+108
-67
lines changed

2 files changed

+108
-67
lines changed

sound/soc/codecs/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -891,6 +891,7 @@ config SND_SOC_WM9712
891891

892892
config SND_SOC_WM9713
893893
tristate
894+
select REGMAP_AC97
894895

895896
# Amp
896897
config SND_SOC_LM4857

sound/soc/codecs/wm9713.c

Lines changed: 107 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <linux/slab.h>
2020
#include <linux/module.h>
2121
#include <linux/device.h>
22+
#include <linux/regmap.h>
2223
#include <sound/core.h>
2324
#include <sound/pcm.h>
2425
#include <sound/ac97_codec.h>
@@ -39,33 +40,15 @@ struct wm9713_priv {
3940
struct mutex lock;
4041
};
4142

42-
static unsigned int ac97_read(struct snd_soc_codec *codec,
43-
unsigned int reg);
44-
static int ac97_write(struct snd_soc_codec *codec,
45-
unsigned int reg, unsigned int val);
46-
47-
/*
48-
* WM9713 register cache
49-
* Reg 0x3c bit 15 is used by touch driver.
50-
*/
51-
static const u16 wm9713_reg[] = {
52-
0x6174, 0x8080, 0x8080, 0x8080,
53-
0xc880, 0xe808, 0xe808, 0x0808,
54-
0x00da, 0x8000, 0xd600, 0xaaa0,
55-
0xaaa0, 0xaaa0, 0x0000, 0x0000,
56-
0x0f0f, 0x0040, 0x0000, 0x7f00,
57-
0x0405, 0x0410, 0xbb80, 0xbb80,
58-
0x0000, 0xbb80, 0x0000, 0x4523,
59-
0x0000, 0x2000, 0x7eff, 0xffff,
60-
0x0000, 0x0000, 0x0080, 0x0000,
61-
0x0000, 0x0000, 0xfffe, 0xffff,
62-
0x0000, 0x0000, 0x0000, 0xfffe,
63-
0x4000, 0x0000, 0x0000, 0x0000,
64-
0xb032, 0x3e00, 0x0000, 0x0000,
65-
0x0000, 0x0000, 0x0000, 0x0000,
66-
0x0000, 0x0000, 0x0000, 0x0006,
67-
0x0001, 0x0000, 0x574d, 0x4c13,
68-
};
43+
static unsigned int ac97_read(struct snd_soc_codec *codec, unsigned int reg)
44+
{
45+
return snd_soc_read(codec, reg);
46+
}
47+
static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,
48+
unsigned int val)
49+
{
50+
return snd_soc_write(codec, reg, val);
51+
}
6952

7053
#define HPL_MIXER 0
7154
#define HPR_MIXER 1
@@ -674,39 +657,97 @@ static const struct snd_soc_dapm_route wm9713_audio_map[] = {
674657
{"Capture Mono Mux", "Right", "Right Capture Source"},
675658
};
676659

677-
static unsigned int ac97_read(struct snd_soc_codec *codec,
678-
unsigned int reg)
660+
static bool wm9713_readable_reg(struct device *dev, unsigned int reg)
679661
{
680-
struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec);
681-
u16 *cache = codec->reg_cache;
682-
683-
if (reg == AC97_RESET || reg == AC97_GPIO_STATUS ||
684-
reg == AC97_VENDOR_ID1 || reg == AC97_VENDOR_ID2 ||
685-
reg == AC97_CD)
686-
return soc_ac97_ops->read(wm9713->ac97, reg);
687-
else {
688-
reg = reg >> 1;
689-
690-
if (reg >= (ARRAY_SIZE(wm9713_reg)))
691-
return -EIO;
692-
693-
return cache[reg];
662+
switch (reg) {
663+
case AC97_RESET ... AC97_PCM_SURR_DAC_RATE:
664+
case AC97_PCM_LR_ADC_RATE:
665+
case AC97_CENTER_LFE_MASTER:
666+
case AC97_SPDIF ... AC97_LINE1_LEVEL:
667+
case AC97_GPIO_CFG ... 0x5c:
668+
case AC97_CODEC_CLASS_REV ... AC97_PCI_SID:
669+
case 0x74 ... AC97_VENDOR_ID2:
670+
return true;
671+
default:
672+
return false;
694673
}
695674
}
696675

697-
static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,
698-
unsigned int val)
676+
static bool wm9713_writeable_reg(struct device *dev, unsigned int reg)
699677
{
700-
struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec);
678+
switch (reg) {
679+
case AC97_VENDOR_ID1:
680+
case AC97_VENDOR_ID2:
681+
return false;
682+
default:
683+
return wm9713_readable_reg(dev, reg);
684+
}
685+
}
701686

702-
u16 *cache = codec->reg_cache;
703-
soc_ac97_ops->write(wm9713->ac97, reg, val);
704-
reg = reg >> 1;
705-
if (reg < (ARRAY_SIZE(wm9713_reg)))
706-
cache[reg] = val;
687+
static const struct reg_default wm9713_reg_defaults[] = {
688+
{ 0x02, 0x8080 }, /* Speaker Output Volume */
689+
{ 0x04, 0x8080 }, /* Headphone Output Volume */
690+
{ 0x06, 0x8080 }, /* Out3/OUT4 Volume */
691+
{ 0x08, 0xc880 }, /* Mono Volume */
692+
{ 0x0a, 0xe808 }, /* LINEIN Volume */
693+
{ 0x0c, 0xe808 }, /* DAC PGA Volume */
694+
{ 0x0e, 0x0808 }, /* MIC PGA Volume */
695+
{ 0x10, 0x00da }, /* MIC Routing Control */
696+
{ 0x12, 0x8000 }, /* Record PGA Volume */
697+
{ 0x14, 0xd600 }, /* Record Routing */
698+
{ 0x16, 0xaaa0 }, /* PCBEEP Volume */
699+
{ 0x18, 0xaaa0 }, /* VxDAC Volume */
700+
{ 0x1a, 0xaaa0 }, /* AUXDAC Volume */
701+
{ 0x1c, 0x0000 }, /* Output PGA Mux */
702+
{ 0x1e, 0x0000 }, /* DAC 3D control */
703+
{ 0x20, 0x0f0f }, /* DAC Tone Control*/
704+
{ 0x22, 0x0040 }, /* MIC Input Select & Bias */
705+
{ 0x24, 0x0000 }, /* Output Volume Mapping & Jack */
706+
{ 0x26, 0x7f00 }, /* Powerdown Ctrl/Stat*/
707+
{ 0x28, 0x0405 }, /* Extended Audio ID */
708+
{ 0x2a, 0x0410 }, /* Extended Audio Start/Ctrl */
709+
{ 0x2c, 0xbb80 }, /* Audio DACs Sample Rate */
710+
{ 0x2e, 0xbb80 }, /* AUXDAC Sample Rate */
711+
{ 0x32, 0xbb80 }, /* Audio ADCs Sample Rate */
712+
{ 0x36, 0x4523 }, /* PCM codec control */
713+
{ 0x3a, 0x2000 }, /* SPDIF control */
714+
{ 0x3c, 0xfdff }, /* Powerdown 1 */
715+
{ 0x3e, 0xffff }, /* Powerdown 2 */
716+
{ 0x40, 0x0000 }, /* General Purpose */
717+
{ 0x42, 0x0000 }, /* Fast Power-Up Control */
718+
{ 0x44, 0x0080 }, /* MCLK/PLL Control */
719+
{ 0x46, 0x0000 }, /* MCLK/PLL Control */
720+
{ 0x4c, 0xfffe }, /* GPIO Pin Configuration */
721+
{ 0x4e, 0xffff }, /* GPIO Pin Polarity / Type */
722+
{ 0x50, 0x0000 }, /* GPIO Pin Sticky */
723+
{ 0x52, 0x0000 }, /* GPIO Pin Wake-Up */
724+
/* GPIO Pin Status */
725+
{ 0x56, 0xfffe }, /* GPIO Pin Sharing */
726+
{ 0x58, 0x4000 }, /* GPIO PullUp/PullDown */
727+
{ 0x5a, 0x0000 }, /* Additional Functions 1 */
728+
{ 0x5c, 0x0000 }, /* Additional Functions 2 */
729+
{ 0x60, 0xb032 }, /* ALC Control */
730+
{ 0x62, 0x3e00 }, /* ALC / Noise Gate Control */
731+
{ 0x64, 0x0000 }, /* AUXDAC input control */
732+
{ 0x74, 0x0000 }, /* Digitiser Reg 1 */
733+
{ 0x76, 0x0006 }, /* Digitiser Reg 2 */
734+
{ 0x78, 0x0001 }, /* Digitiser Reg 3 */
735+
{ 0x7a, 0x0000 }, /* Digitiser Read Back */
736+
};
707737

708-
return 0;
709-
}
738+
static const struct regmap_config wm9713_regmap_config = {
739+
.reg_bits = 16,
740+
.reg_stride = 2,
741+
.val_bits = 16,
742+
.max_register = 0x7e,
743+
.cache_type = REGCACHE_RBTREE,
744+
745+
.reg_defaults = wm9713_reg_defaults,
746+
.num_reg_defaults = ARRAY_SIZE(wm9713_reg_defaults),
747+
.volatile_reg = regmap_ac97_default_volatile,
748+
.readable_reg = wm9713_readable_reg,
749+
.writeable_reg = wm9713_writeable_reg,
750+
};
710751

711752
/* PLL divisors */
712753
struct _pll_div {
@@ -1173,8 +1214,7 @@ static int wm9713_soc_suspend(struct snd_soc_codec *codec)
11731214
static int wm9713_soc_resume(struct snd_soc_codec *codec)
11741215
{
11751216
struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec);
1176-
int i, ret;
1177-
u16 *cache = codec->reg_cache;
1217+
int ret;
11781218

11791219
ret = snd_ac97_reset(wm9713->ac97, true, WM9713_VENDOR_ID,
11801220
WM9713_VENDOR_ID_MASK);
@@ -1189,12 +1229,8 @@ static int wm9713_soc_resume(struct snd_soc_codec *codec)
11891229

11901230
/* only synchronise the codec if warm reset failed */
11911231
if (ret == 0) {
1192-
for (i = 2; i < ARRAY_SIZE(wm9713_reg) << 1; i += 2) {
1193-
if (i == AC97_POWERDOWN || i == AC97_EXTENDED_MID ||
1194-
i == AC97_EXTENDED_MSTATUS || i > 0x66)
1195-
continue;
1196-
soc_ac97_ops->write(wm9713->ac97, i, cache[i>>1]);
1197-
}
1232+
regcache_mark_dirty(codec->component.regmap);
1233+
snd_soc_cache_sync(codec);
11981234
}
11991235

12001236
return ret;
@@ -1203,13 +1239,22 @@ static int wm9713_soc_resume(struct snd_soc_codec *codec)
12031239
static int wm9713_soc_probe(struct snd_soc_codec *codec)
12041240
{
12051241
struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec);
1242+
struct regmap *regmap;
12061243
int reg;
12071244

12081245
wm9713->ac97 = snd_soc_new_ac97_codec(codec, WM9713_VENDOR_ID,
12091246
WM9713_VENDOR_ID_MASK);
12101247
if (IS_ERR(wm9713->ac97))
12111248
return PTR_ERR(wm9713->ac97);
12121249

1250+
regmap = devm_regmap_init_ac97(wm9713->ac97, &wm9713_regmap_config);
1251+
if (IS_ERR(regmap)) {
1252+
snd_soc_free_ac97_codec(wm9713->ac97);
1253+
return PTR_ERR(regmap);
1254+
}
1255+
1256+
snd_soc_codec_init_regmap(codec, regmap);
1257+
12131258
/* unmute the adc - move to kcontrol */
12141259
reg = ac97_read(codec, AC97_CD) & 0x7fff;
12151260
ac97_write(codec, AC97_CD, reg);
@@ -1221,6 +1266,7 @@ static int wm9713_soc_remove(struct snd_soc_codec *codec)
12211266
{
12221267
struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec);
12231268

1269+
snd_soc_codec_exit_regmap(codec);
12241270
snd_soc_free_ac97_codec(wm9713->ac97);
12251271
return 0;
12261272
}
@@ -1230,13 +1276,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9713 = {
12301276
.remove = wm9713_soc_remove,
12311277
.suspend = wm9713_soc_suspend,
12321278
.resume = wm9713_soc_resume,
1233-
.read = ac97_read,
1234-
.write = ac97_write,
12351279
.set_bias_level = wm9713_set_bias_level,
1236-
.reg_cache_size = ARRAY_SIZE(wm9713_reg),
1237-
.reg_word_size = sizeof(u16),
1238-
.reg_cache_step = 2,
1239-
.reg_cache_default = wm9713_reg,
12401280

12411281
.controls = wm9713_snd_ac97_controls,
12421282
.num_controls = ARRAY_SIZE(wm9713_snd_ac97_controls),

0 commit comments

Comments
 (0)