diff options
| author | Mark Brown <broonie@linaro.org> | 2013-10-24 06:24:15 -0400 |
|---|---|---|
| committer | Mark Brown <broonie@linaro.org> | 2013-10-24 06:24:15 -0400 |
| commit | 3cabd442d7c8f9428c231faa92755fceab4dd8d6 (patch) | |
| tree | 943b8ce8a73410e68a826483b3f433e169443a6d | |
| parent | 2b48f86b5b643274087396cc157b5a2a76711526 (diff) | |
| parent | 7fbdeb809050cb958f3baa83dcc643f9a2f287f2 (diff) | |
Merge remote-tracking branch 'asoc/topic/tlv320aic26' into asoc-next
| -rw-r--r-- | sound/soc/codecs/tlv320aic26.c | 139 | ||||
| -rw-r--r-- | sound/soc/codecs/tlv320aic26.h | 5 |
2 files changed, 28 insertions, 116 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); |
diff --git a/sound/soc/codecs/tlv320aic26.h b/sound/soc/codecs/tlv320aic26.h index 67f19c3bebe6..629b85e75409 100644 --- a/sound/soc/codecs/tlv320aic26.h +++ b/sound/soc/codecs/tlv320aic26.h | |||
| @@ -9,10 +9,7 @@ | |||
| 9 | #define _TLV320AIC16_H_ | 9 | #define _TLV320AIC16_H_ |
| 10 | 10 | ||
| 11 | /* AIC26 Registers */ | 11 | /* AIC26 Registers */ |
| 12 | #define AIC26_READ_COMMAND_WORD(addr) ((1 << 15) | (addr << 5)) | 12 | #define AIC26_PAGE_ADDR(page, offset) ((page << 11) | offset << 5) |
| 13 | #define AIC26_WRITE_COMMAND_WORD(addr) ((0 << 15) | (addr << 5)) | ||
| 14 | #define AIC26_PAGE_ADDR(page, offset) ((page << 6) | offset) | ||
| 15 | #define AIC26_NUM_REGS AIC26_PAGE_ADDR(3, 0) | ||
| 16 | 13 | ||
| 17 | /* Page 0: Auxiliary data registers */ | 14 | /* Page 0: Auxiliary data registers */ |
| 18 | #define AIC26_REG_BAT1 AIC26_PAGE_ADDR(0, 0x05) | 15 | #define AIC26_REG_BAT1 AIC26_PAGE_ADDR(0, 0x05) |
