diff options
Diffstat (limited to 'sound/soc/codecs/tlv320aic26.c')
-rw-r--r-- | sound/soc/codecs/tlv320aic26.c | 139 |
1 files changed, 27 insertions, 112 deletions
diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c index 7b8f3d965f43..94a658fa6d97 100644 --- a/sound/soc/codecs/tlv320aic26.c +++ b/sound/soc/codecs/tlv320aic26.c | |||
@@ -29,6 +29,7 @@ MODULE_LICENSE("GPL"); | |||
29 | /* AIC26 driver private data */ | 29 | /* AIC26 driver private data */ |
30 | struct aic26 { | 30 | struct aic26 { |
31 | struct spi_device *spi; | 31 | struct spi_device *spi; |
32 | struct regmap *regmap; | ||
32 | struct snd_soc_codec *codec; | 33 | struct snd_soc_codec *codec; |
33 | int master; | 34 | int master; |
34 | int datfm; | 35 | int datfm; |
@@ -40,85 +41,6 @@ struct aic26 { | |||
40 | int keyclick_len; | 41 | int keyclick_len; |
41 | }; | 42 | }; |
42 | 43 | ||
43 | /* --------------------------------------------------------------------- | ||
44 | * Register access routines | ||
45 | */ | ||
46 | static unsigned int aic26_reg_read(struct snd_soc_codec *codec, | ||
47 | unsigned int reg) | ||
48 | { | ||
49 | struct aic26 *aic26 = snd_soc_codec_get_drvdata(codec); | ||
50 | u16 *cache = codec->reg_cache; | ||
51 | u16 cmd, value; | ||
52 | u8 buffer[2]; | ||
53 | int rc; | ||
54 | |||
55 | if (reg >= AIC26_NUM_REGS) { | ||
56 | WARN_ON_ONCE(1); | ||
57 | return 0; | ||
58 | } | ||
59 | |||
60 | /* Do SPI transfer; first 16bits are command; remaining is | ||
61 | * register contents */ | ||
62 | cmd = AIC26_READ_COMMAND_WORD(reg); | ||
63 | buffer[0] = (cmd >> 8) & 0xff; | ||
64 | buffer[1] = cmd & 0xff; | ||
65 | rc = spi_write_then_read(aic26->spi, buffer, 2, buffer, 2); | ||
66 | if (rc) { | ||
67 | dev_err(&aic26->spi->dev, "AIC26 reg read error\n"); | ||
68 | return -EIO; | ||
69 | } | ||
70 | value = (buffer[0] << 8) | buffer[1]; | ||
71 | |||
72 | /* Update the cache before returning with the value */ | ||
73 | cache[reg] = value; | ||
74 | return value; | ||
75 | } | ||
76 | |||
77 | static unsigned int aic26_reg_read_cache(struct snd_soc_codec *codec, | ||
78 | unsigned int reg) | ||
79 | { | ||
80 | u16 *cache = codec->reg_cache; | ||
81 | |||
82 | if (reg >= AIC26_NUM_REGS) { | ||
83 | WARN_ON_ONCE(1); | ||
84 | return 0; | ||
85 | } | ||
86 | |||
87 | return cache[reg]; | ||
88 | } | ||
89 | |||
90 | static int aic26_reg_write(struct snd_soc_codec *codec, unsigned int reg, | ||
91 | unsigned int value) | ||
92 | { | ||
93 | struct aic26 *aic26 = snd_soc_codec_get_drvdata(codec); | ||
94 | u16 *cache = codec->reg_cache; | ||
95 | u16 cmd; | ||
96 | u8 buffer[4]; | ||
97 | int rc; | ||
98 | |||
99 | if (reg >= AIC26_NUM_REGS) { | ||
100 | WARN_ON_ONCE(1); | ||
101 | return -EINVAL; | ||
102 | } | ||
103 | |||
104 | /* Do SPI transfer; first 16bits are command; remaining is data | ||
105 | * to write into register */ | ||
106 | cmd = AIC26_WRITE_COMMAND_WORD(reg); | ||
107 | buffer[0] = (cmd >> 8) & 0xff; | ||
108 | buffer[1] = cmd & 0xff; | ||
109 | buffer[2] = value >> 8; | ||
110 | buffer[3] = value; | ||
111 | rc = spi_write(aic26->spi, buffer, 4); | ||
112 | if (rc) { | ||
113 | dev_err(&aic26->spi->dev, "AIC26 reg read error\n"); | ||
114 | return -EIO; | ||
115 | } | ||
116 | |||
117 | /* update cache before returning */ | ||
118 | cache[reg] = value; | ||
119 | return 0; | ||
120 | } | ||
121 | |||
122 | static const struct snd_soc_dapm_widget tlv320aic26_dapm_widgets[] = { | 44 | static const struct snd_soc_dapm_widget tlv320aic26_dapm_widgets[] = { |
123 | SND_SOC_DAPM_INPUT("MICIN"), | 45 | SND_SOC_DAPM_INPUT("MICIN"), |
124 | SND_SOC_DAPM_INPUT("AUX"), | 46 | SND_SOC_DAPM_INPUT("AUX"), |
@@ -195,19 +117,15 @@ static int aic26_hw_params(struct snd_pcm_substream *substream, | |||
195 | snd_soc_write(codec, AIC26_REG_PLL_PROG2, reg); | 117 | snd_soc_write(codec, AIC26_REG_PLL_PROG2, reg); |
196 | 118 | ||
197 | /* Audio Control 3 (master mode, fsref rate) */ | 119 | /* Audio Control 3 (master mode, fsref rate) */ |
198 | reg = aic26_reg_read_cache(codec, AIC26_REG_AUDIO_CTRL3); | ||
199 | reg &= ~0xf800; | ||
200 | if (aic26->master) | 120 | if (aic26->master) |
201 | reg |= 0x0800; | 121 | reg = 0x0800; |
202 | if (fsref == 48000) | 122 | if (fsref == 48000) |
203 | reg |= 0x2000; | 123 | reg = 0x2000; |
204 | snd_soc_write(codec, AIC26_REG_AUDIO_CTRL3, reg); | 124 | snd_soc_update_bits(codec, AIC26_REG_AUDIO_CTRL3, 0xf800, reg); |
205 | 125 | ||
206 | /* Audio Control 1 (FSref divisor) */ | 126 | /* Audio Control 1 (FSref divisor) */ |
207 | reg = aic26_reg_read_cache(codec, AIC26_REG_AUDIO_CTRL1); | 127 | reg = wlen | aic26->datfm | (divisor << 3) | divisor; |
208 | reg &= ~0x0fff; | 128 | snd_soc_update_bits(codec, AIC26_REG_AUDIO_CTRL1, 0xfff, reg); |
209 | reg |= wlen | aic26->datfm | (divisor << 3) | divisor; | ||
210 | snd_soc_write(codec, AIC26_REG_AUDIO_CTRL1, reg); | ||
211 | 129 | ||
212 | return 0; | 130 | return 0; |
213 | } | 131 | } |
@@ -219,16 +137,16 @@ static int aic26_mute(struct snd_soc_dai *dai, int mute) | |||
219 | { | 137 | { |
220 | struct snd_soc_codec *codec = dai->codec; | 138 | struct snd_soc_codec *codec = dai->codec; |
221 | struct aic26 *aic26 = snd_soc_codec_get_drvdata(codec); | 139 | struct aic26 *aic26 = snd_soc_codec_get_drvdata(codec); |
222 | u16 reg = aic26_reg_read_cache(codec, AIC26_REG_DAC_GAIN); | 140 | u16 reg; |
223 | 141 | ||
224 | dev_dbg(&aic26->spi->dev, "aic26_mute(dai=%p, mute=%i)\n", | 142 | dev_dbg(&aic26->spi->dev, "aic26_mute(dai=%p, mute=%i)\n", |
225 | dai, mute); | 143 | dai, mute); |
226 | 144 | ||
227 | if (mute) | 145 | if (mute) |
228 | reg |= 0x8080; | 146 | reg = 0x8080; |
229 | else | 147 | else |
230 | reg &= ~0x8080; | 148 | reg = 0; |
231 | snd_soc_write(codec, AIC26_REG_DAC_GAIN, reg); | 149 | snd_soc_update_bits(codec, AIC26_REG_DAC_GAIN, 0x8000, reg); |
232 | 150 | ||
233 | return 0; | 151 | return 0; |
234 | } | 152 | } |
@@ -346,7 +264,7 @@ static ssize_t aic26_keyclick_show(struct device *dev, | |||
346 | struct aic26 *aic26 = dev_get_drvdata(dev); | 264 | struct aic26 *aic26 = dev_get_drvdata(dev); |
347 | int val, amp, freq, len; | 265 | int val, amp, freq, len; |
348 | 266 | ||
349 | val = aic26_reg_read_cache(aic26->codec, AIC26_REG_AUDIO_CTRL2); | 267 | val = snd_soc_read(aic26->codec, AIC26_REG_AUDIO_CTRL2); |
350 | amp = (val >> 12) & 0x7; | 268 | amp = (val >> 12) & 0x7; |
351 | freq = (125 << ((val >> 8) & 0x7)) >> 1; | 269 | freq = (125 << ((val >> 8) & 0x7)) >> 1; |
352 | len = 2 * (1 + ((val >> 4) & 0xf)); | 270 | len = 2 * (1 + ((val >> 4) & 0xf)); |
@@ -360,11 +278,9 @@ static ssize_t aic26_keyclick_set(struct device *dev, | |||
360 | const char *buf, size_t count) | 278 | const char *buf, size_t count) |
361 | { | 279 | { |
362 | struct aic26 *aic26 = dev_get_drvdata(dev); | 280 | struct aic26 *aic26 = dev_get_drvdata(dev); |
363 | int val; | ||
364 | 281 | ||
365 | val = aic26_reg_read_cache(aic26->codec, AIC26_REG_AUDIO_CTRL2); | 282 | snd_soc_update_bits(aic26->codec, AIC26_REG_AUDIO_CTRL2, |
366 | val |= 0x8000; | 283 | 0x8000, 0x800); |
367 | snd_soc_write(aic26->codec, AIC26_REG_AUDIO_CTRL2, val); | ||
368 | 284 | ||
369 | return count; | 285 | return count; |
370 | } | 286 | } |
@@ -377,7 +293,9 @@ static DEVICE_ATTR(keyclick, 0644, aic26_keyclick_show, aic26_keyclick_set); | |||
377 | static int aic26_probe(struct snd_soc_codec *codec) | 293 | static int aic26_probe(struct snd_soc_codec *codec) |
378 | { | 294 | { |
379 | struct aic26 *aic26 = dev_get_drvdata(codec->dev); | 295 | struct aic26 *aic26 = dev_get_drvdata(codec->dev); |
380 | int ret, err, i, reg; | 296 | int ret, reg; |
297 | |||
298 | snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP); | ||
381 | 299 | ||
382 | aic26->codec = codec; | 300 | aic26->codec = codec; |
383 | 301 | ||
@@ -393,37 +311,30 @@ static int aic26_probe(struct snd_soc_codec *codec) | |||
393 | reg |= 0x0800; /* set master mode */ | 311 | reg |= 0x0800; /* set master mode */ |
394 | snd_soc_write(codec, AIC26_REG_AUDIO_CTRL3, reg); | 312 | snd_soc_write(codec, AIC26_REG_AUDIO_CTRL3, reg); |
395 | 313 | ||
396 | /* Fill register cache */ | ||
397 | for (i = 0; i < codec->driver->reg_cache_size; i++) | ||
398 | snd_soc_read(codec, i); | ||
399 | |||
400 | /* Register the sysfs files for debugging */ | 314 | /* Register the sysfs files for debugging */ |
401 | /* Create SysFS files */ | 315 | /* Create SysFS files */ |
402 | ret = device_create_file(codec->dev, &dev_attr_keyclick); | 316 | ret = device_create_file(codec->dev, &dev_attr_keyclick); |
403 | if (ret) | 317 | if (ret) |
404 | dev_info(codec->dev, "error creating sysfs files\n"); | 318 | dev_info(codec->dev, "error creating sysfs files\n"); |
405 | 319 | ||
406 | /* register controls */ | ||
407 | dev_dbg(codec->dev, "Registering controls\n"); | ||
408 | err = snd_soc_add_codec_controls(codec, aic26_snd_controls, | ||
409 | ARRAY_SIZE(aic26_snd_controls)); | ||
410 | WARN_ON(err < 0); | ||
411 | |||
412 | return 0; | 320 | return 0; |
413 | } | 321 | } |
414 | 322 | ||
415 | static struct snd_soc_codec_driver aic26_soc_codec_dev = { | 323 | static struct snd_soc_codec_driver aic26_soc_codec_dev = { |
416 | .probe = aic26_probe, | 324 | .probe = aic26_probe, |
417 | .read = aic26_reg_read, | 325 | .controls = aic26_snd_controls, |
418 | .write = aic26_reg_write, | 326 | .num_controls = ARRAY_SIZE(aic26_snd_controls), |
419 | .reg_cache_size = AIC26_NUM_REGS, | ||
420 | .reg_word_size = sizeof(u16), | ||
421 | .dapm_widgets = tlv320aic26_dapm_widgets, | 327 | .dapm_widgets = tlv320aic26_dapm_widgets, |
422 | .num_dapm_widgets = ARRAY_SIZE(tlv320aic26_dapm_widgets), | 328 | .num_dapm_widgets = ARRAY_SIZE(tlv320aic26_dapm_widgets), |
423 | .dapm_routes = tlv320aic26_dapm_routes, | 329 | .dapm_routes = tlv320aic26_dapm_routes, |
424 | .num_dapm_routes = ARRAY_SIZE(tlv320aic26_dapm_routes), | 330 | .num_dapm_routes = ARRAY_SIZE(tlv320aic26_dapm_routes), |
425 | }; | 331 | }; |
426 | 332 | ||
333 | static const struct regmap_config aic26_regmap = { | ||
334 | .reg_bits = 16, | ||
335 | .val_bits = 16, | ||
336 | }; | ||
337 | |||
427 | /* --------------------------------------------------------------------- | 338 | /* --------------------------------------------------------------------- |
428 | * SPI device portion of driver: probe and release routines and SPI | 339 | * SPI device portion of driver: probe and release routines and SPI |
429 | * driver registration. | 340 | * driver registration. |
@@ -440,6 +351,10 @@ static int aic26_spi_probe(struct spi_device *spi) | |||
440 | if (!aic26) | 351 | if (!aic26) |
441 | return -ENOMEM; | 352 | return -ENOMEM; |
442 | 353 | ||
354 | aic26->regmap = devm_regmap_init_spi(spi, &aic26_regmap); | ||
355 | if (IS_ERR(aic26->regmap)) | ||
356 | return PTR_ERR(aic26->regmap); | ||
357 | |||
443 | /* Initialize the driver data */ | 358 | /* Initialize the driver data */ |
444 | aic26->spi = spi; | 359 | aic26->spi = spi; |
445 | dev_set_drvdata(&spi->dev, aic26); | 360 | dev_set_drvdata(&spi->dev, aic26); |