aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/soc/codecs/stac9766.c108
1 files changed, 59 insertions, 49 deletions
diff --git a/sound/soc/codecs/stac9766.c b/sound/soc/codecs/stac9766.c
index f675d343b529..62cbeedf93b9 100644
--- a/sound/soc/codecs/stac9766.c
+++ b/sound/soc/codecs/stac9766.c
@@ -18,6 +18,7 @@
18#include <linux/slab.h> 18#include <linux/slab.h>
19#include <linux/module.h> 19#include <linux/module.h>
20#include <linux/device.h> 20#include <linux/device.h>
21#include <linux/regmap.h>
21#include <sound/core.h> 22#include <sound/core.h>
22#include <sound/pcm.h> 23#include <sound/pcm.h>
23#include <sound/ac97_codec.h> 24#include <sound/ac97_codec.h>
@@ -33,26 +34,49 @@
33#define AC97_STAC_ANALOG_SPECIAL 0x6E 34#define AC97_STAC_ANALOG_SPECIAL 0x6E
34#define AC97_STAC_STEREO_MIC 0x78 35#define AC97_STAC_STEREO_MIC 0x78
35 36
36/* 37static const struct reg_default stac9766_reg_defaults[] = {
37 * STAC9766 register cache 38 { 0x02, 0x8000 },
38 */ 39 { 0x04, 0x8000 },
39static const u16 stac9766_reg[] = { 40 { 0x06, 0x8000 },
40 0x6A90, 0x8000, 0x8000, 0x8000, /* 6 */ 41 { 0x0a, 0x0000 },
41 0x0000, 0x0000, 0x8008, 0x8008, /* e */ 42 { 0x0c, 0x8008 },
42 0x8808, 0x8808, 0x8808, 0x8808, /* 16 */ 43 { 0x0e, 0x8008 },
43 0x8808, 0x0000, 0x8000, 0x0000, /* 1e */ 44 { 0x10, 0x8808 },
44 0x0000, 0x0000, 0x0000, 0x000f, /* 26 */ 45 { 0x12, 0x8808 },
45 0x0a05, 0x0400, 0xbb80, 0x0000, /* 2e */ 46 { 0x14, 0x8808 },
46 0x0000, 0xbb80, 0x0000, 0x0000, /* 36 */ 47 { 0x16, 0x8808 },
47 0x0000, 0x2000, 0x0000, 0x0100, /* 3e */ 48 { 0x18, 0x8808 },
48 0x0000, 0x0000, 0x0080, 0x0000, /* 46 */ 49 { 0x1a, 0x0000 },
49 0x0000, 0x0000, 0x0003, 0xffff, /* 4e */ 50 { 0x1c, 0x8000 },
50 0x0000, 0x0000, 0x0000, 0x0000, /* 56 */ 51 { 0x20, 0x0000 },
51 0x4000, 0x0000, 0x0000, 0x0000, /* 5e */ 52 { 0x22, 0x0000 },
52 0x1201, 0x0000, 0x0000, 0x0000, /* 66 */ 53 { 0x28, 0x0a05 },
53 0x0000, 0x0000, 0x0000, 0x1000, /* 6e */ 54 { 0x2c, 0xbb80 },
54 0x0000, 0x0000, 0x0000, 0x0006, /* 76 */ 55 { 0x32, 0xbb80 },
55 0x0000, 0x0000, 0x0000, 0x0000, /* 7e */ 56 { 0x3a, 0x2000 },
57 { 0x3e, 0x0100 },
58 { 0x4c, 0x0300 },
59 { 0x4e, 0xffff },
60 { 0x50, 0x0000 },
61 { 0x52, 0x0000 },
62 { 0x54, 0x0000 },
63 { 0x6a, 0x0000 },
64 { 0x6e, 0x1000 },
65 { 0x72, 0x0000 },
66 { 0x78, 0x0000 },
67};
68
69static const struct regmap_config stac9766_regmap_config = {
70 .reg_bits = 16,
71 .reg_stride = 2,
72 .val_bits = 16,
73 .max_register = 0x78,
74 .cache_type = REGCACHE_RBTREE,
75
76 .volatile_reg = regmap_ac97_default_volatile,
77
78 .reg_defaults = stac9766_reg_defaults,
79 .num_reg_defaults = ARRAY_SIZE(stac9766_reg_defaults),
56}; 80};
57 81
58static const char *stac9766_record_mux[] = {"Mic", "CD", "Video", "AUX", 82static const char *stac9766_record_mux[] = {"Mic", "CD", "Video", "AUX",
@@ -144,34 +168,13 @@ static const struct snd_kcontrol_new stac9766_snd_ac97_controls[] = {
144static int stac9766_ac97_write(struct snd_soc_codec *codec, unsigned int reg, 168static int stac9766_ac97_write(struct snd_soc_codec *codec, unsigned int reg,
145 unsigned int val) 169 unsigned int val)
146{ 170{
147 struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); 171 return snd_soc_write(codec, reg, val);
148 u16 *cache = codec->reg_cache;
149
150 if (reg / 2 >= ARRAY_SIZE(stac9766_reg))
151 return -EIO;
152
153 soc_ac97_ops->write(ac97, reg, val);
154 cache[reg / 2] = val;
155 return 0;
156} 172}
157 173
158static unsigned int stac9766_ac97_read(struct snd_soc_codec *codec, 174static unsigned int stac9766_ac97_read(struct snd_soc_codec *codec,
159 unsigned int reg) 175 unsigned int reg)
160{ 176{
161 struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); 177 return snd_soc_read(codec, reg);
162 u16 val = 0, *cache = codec->reg_cache;
163
164 if (reg / 2 >= ARRAY_SIZE(stac9766_reg))
165 return -EIO;
166
167 if (reg == AC97_RESET || reg == AC97_GPIO_STATUS ||
168 reg == AC97_INT_PAGING || reg == AC97_VENDOR_ID1 ||
169 reg == AC97_VENDOR_ID2) {
170
171 val = soc_ac97_ops->read(ac97, reg);
172 return val;
173 }
174 return cache[reg / 2];
175} 178}
176 179
177static int ac97_analog_prepare(struct snd_pcm_substream *substream, 180static int ac97_analog_prepare(struct snd_pcm_substream *substream,
@@ -290,21 +293,34 @@ static struct snd_soc_dai_driver stac9766_dai[] = {
290static int stac9766_codec_probe(struct snd_soc_codec *codec) 293static int stac9766_codec_probe(struct snd_soc_codec *codec)
291{ 294{
292 struct snd_ac97 *ac97; 295 struct snd_ac97 *ac97;
296 struct regmap *regmap;
297 int ret;
293 298
294 ac97 = snd_soc_new_ac97_codec(codec, STAC9766_VENDOR_ID, 299 ac97 = snd_soc_new_ac97_codec(codec, STAC9766_VENDOR_ID,
295 STAC9766_VENDOR_ID_MASK); 300 STAC9766_VENDOR_ID_MASK);
296 if (IS_ERR(ac97)) 301 if (IS_ERR(ac97))
297 return PTR_ERR(ac97); 302 return PTR_ERR(ac97);
298 303
304 regmap = regmap_init_ac97(ac97, &stac9766_regmap_config);
305 if (IS_ERR(regmap)) {
306 ret = PTR_ERR(regmap);
307 goto err_free_ac97;
308 }
309
310 snd_soc_codec_init_regmap(codec, regmap);
299 snd_soc_codec_set_drvdata(codec, ac97); 311 snd_soc_codec_set_drvdata(codec, ac97);
300 312
301 return 0; 313 return 0;
314err_free_ac97:
315 snd_soc_free_ac97_codec(ac97);
316 return ret;
302} 317}
303 318
304static int stac9766_codec_remove(struct snd_soc_codec *codec) 319static int stac9766_codec_remove(struct snd_soc_codec *codec)
305{ 320{
306 struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); 321 struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec);
307 322
323 snd_soc_codec_exit_regmap(codec);
308 snd_soc_free_ac97_codec(ac97); 324 snd_soc_free_ac97_codec(ac97);
309 return 0; 325 return 0;
310} 326}
@@ -314,17 +330,11 @@ static struct snd_soc_codec_driver soc_codec_dev_stac9766 = {
314 .controls = stac9766_snd_ac97_controls, 330 .controls = stac9766_snd_ac97_controls,
315 .num_controls = ARRAY_SIZE(stac9766_snd_ac97_controls), 331 .num_controls = ARRAY_SIZE(stac9766_snd_ac97_controls),
316 }, 332 },
317 .write = stac9766_ac97_write,
318 .read = stac9766_ac97_read,
319 .set_bias_level = stac9766_set_bias_level, 333 .set_bias_level = stac9766_set_bias_level,
320 .suspend_bias_off = true, 334 .suspend_bias_off = true,
321 .probe = stac9766_codec_probe, 335 .probe = stac9766_codec_probe,
322 .remove = stac9766_codec_remove, 336 .remove = stac9766_codec_remove,
323 .resume = stac9766_codec_resume, 337 .resume = stac9766_codec_resume,
324 .reg_cache_size = ARRAY_SIZE(stac9766_reg),
325 .reg_word_size = sizeof(u16),
326 .reg_cache_step = 2,
327 .reg_cache_default = stac9766_reg,
328}; 338};
329 339
330static int stac9766_probe(struct platform_device *pdev) 340static int stac9766_probe(struct platform_device *pdev)