diff options
| -rw-r--r-- | sound/soc/codecs/cs4271.c | 166 |
1 files changed, 96 insertions, 70 deletions
diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c index 2415a4118dbd..03036b326732 100644 --- a/sound/soc/codecs/cs4271.c +++ b/sound/soc/codecs/cs4271.c | |||
| @@ -39,17 +39,15 @@ | |||
| 39 | 39 | ||
| 40 | /* | 40 | /* |
| 41 | * CS4271 registers | 41 | * CS4271 registers |
| 42 | * High byte represents SPI chip address (0x10) + write command (0) | ||
| 43 | * Low byte - codec register address | ||
| 44 | */ | 42 | */ |
| 45 | #define CS4271_MODE1 0x2001 /* Mode Control 1 */ | 43 | #define CS4271_MODE1 0x01 /* Mode Control 1 */ |
| 46 | #define CS4271_DACCTL 0x2002 /* DAC Control */ | 44 | #define CS4271_DACCTL 0x02 /* DAC Control */ |
| 47 | #define CS4271_DACVOL 0x2003 /* DAC Volume & Mixing Control */ | 45 | #define CS4271_DACVOL 0x03 /* DAC Volume & Mixing Control */ |
| 48 | #define CS4271_VOLA 0x2004 /* DAC Channel A Volume Control */ | 46 | #define CS4271_VOLA 0x04 /* DAC Channel A Volume Control */ |
| 49 | #define CS4271_VOLB 0x2005 /* DAC Channel B Volume Control */ | 47 | #define CS4271_VOLB 0x05 /* DAC Channel B Volume Control */ |
| 50 | #define CS4271_ADCCTL 0x2006 /* ADC Control */ | 48 | #define CS4271_ADCCTL 0x06 /* ADC Control */ |
| 51 | #define CS4271_MODE2 0x2007 /* Mode Control 2 */ | 49 | #define CS4271_MODE2 0x07 /* Mode Control 2 */ |
| 52 | #define CS4271_CHIPID 0x2008 /* Chip ID */ | 50 | #define CS4271_CHIPID 0x08 /* Chip ID */ |
| 53 | 51 | ||
| 54 | #define CS4271_FIRSTREG CS4271_MODE1 | 52 | #define CS4271_FIRSTREG CS4271_MODE1 |
| 55 | #define CS4271_LASTREG CS4271_MODE2 | 53 | #define CS4271_LASTREG CS4271_MODE2 |
| @@ -144,23 +142,27 @@ | |||
| 144 | * Array do not include Chip ID, as codec driver does not use | 142 | * Array do not include Chip ID, as codec driver does not use |
| 145 | * registers read operations at all | 143 | * registers read operations at all |
| 146 | */ | 144 | */ |
| 147 | static const u8 cs4271_dflt_reg[CS4271_NR_REGS] = { | 145 | static const struct reg_default cs4271_reg_defaults[] = { |
| 148 | 0, | 146 | { CS4271_MODE1, 0, }, |
| 149 | 0, | 147 | { CS4271_DACCTL, CS4271_DACCTL_AMUTE, }, |
| 150 | CS4271_DACCTL_AMUTE, | 148 | { CS4271_DACVOL, CS4271_DACVOL_SOFT | CS4271_DACVOL_ATAPI_AL_BR, }, |
| 151 | CS4271_DACVOL_SOFT | CS4271_DACVOL_ATAPI_AL_BR, | 149 | { CS4271_VOLA, 0, }, |
| 152 | 0, | 150 | { CS4271_VOLB, 0, }, |
| 153 | 0, | 151 | { CS4271_ADCCTL, 0, }, |
| 154 | 0, | 152 | { CS4271_MODE2, 0, }, |
| 155 | 0, | ||
| 156 | }; | 153 | }; |
| 157 | 154 | ||
| 155 | static bool cs4271_volatile_reg(struct device *dev, unsigned int reg) | ||
| 156 | { | ||
| 157 | return reg == CS4271_CHIPID; | ||
| 158 | } | ||
| 159 | |||
| 158 | struct cs4271_private { | 160 | struct cs4271_private { |
| 159 | /* SND_SOC_I2C or SND_SOC_SPI */ | 161 | /* SND_SOC_I2C or SND_SOC_SPI */ |
| 160 | enum snd_soc_control_type bus_type; | ||
| 161 | unsigned int mclk; | 162 | unsigned int mclk; |
| 162 | bool master; | 163 | bool master; |
| 163 | bool deemph; | 164 | bool deemph; |
| 165 | struct regmap *regmap; | ||
| 164 | /* Current sample rate for de-emphasis control */ | 166 | /* Current sample rate for de-emphasis control */ |
| 165 | int rate; | 167 | int rate; |
| 166 | /* GPIO driving Reset pin, if any */ | 168 | /* GPIO driving Reset pin, if any */ |
| @@ -210,14 +212,14 @@ static int cs4271_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
| 210 | switch (format & SND_SOC_DAIFMT_FORMAT_MASK) { | 212 | switch (format & SND_SOC_DAIFMT_FORMAT_MASK) { |
| 211 | case SND_SOC_DAIFMT_LEFT_J: | 213 | case SND_SOC_DAIFMT_LEFT_J: |
| 212 | val |= CS4271_MODE1_DAC_DIF_LJ; | 214 | val |= CS4271_MODE1_DAC_DIF_LJ; |
| 213 | ret = snd_soc_update_bits(codec, CS4271_ADCCTL, | 215 | ret = regmap_update_bits(cs4271->regmap, CS4271_ADCCTL, |
| 214 | CS4271_ADCCTL_ADC_DIF_MASK, CS4271_ADCCTL_ADC_DIF_LJ); | 216 | CS4271_ADCCTL_ADC_DIF_MASK, CS4271_ADCCTL_ADC_DIF_LJ); |
| 215 | if (ret < 0) | 217 | if (ret < 0) |
| 216 | return ret; | 218 | return ret; |
| 217 | break; | 219 | break; |
| 218 | case SND_SOC_DAIFMT_I2S: | 220 | case SND_SOC_DAIFMT_I2S: |
| 219 | val |= CS4271_MODE1_DAC_DIF_I2S; | 221 | val |= CS4271_MODE1_DAC_DIF_I2S; |
| 220 | ret = snd_soc_update_bits(codec, CS4271_ADCCTL, | 222 | ret = regmap_update_bits(cs4271->regmap, CS4271_ADCCTL, |
| 221 | CS4271_ADCCTL_ADC_DIF_MASK, CS4271_ADCCTL_ADC_DIF_I2S); | 223 | CS4271_ADCCTL_ADC_DIF_MASK, CS4271_ADCCTL_ADC_DIF_I2S); |
| 222 | if (ret < 0) | 224 | if (ret < 0) |
| 223 | return ret; | 225 | return ret; |
| @@ -227,7 +229,7 @@ static int cs4271_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
| 227 | return -EINVAL; | 229 | return -EINVAL; |
| 228 | } | 230 | } |
| 229 | 231 | ||
| 230 | ret = snd_soc_update_bits(codec, CS4271_MODE1, | 232 | ret = regmap_update_bits(cs4271->regmap, CS4271_MODE1, |
| 231 | CS4271_MODE1_DAC_DIF_MASK | CS4271_MODE1_MASTER, val); | 233 | CS4271_MODE1_DAC_DIF_MASK | CS4271_MODE1_MASTER, val); |
| 232 | if (ret < 0) | 234 | if (ret < 0) |
| 233 | return ret; | 235 | return ret; |
| @@ -252,7 +254,7 @@ static int cs4271_set_deemph(struct snd_soc_codec *codec) | |||
| 252 | val <<= 4; | 254 | val <<= 4; |
| 253 | } | 255 | } |
| 254 | 256 | ||
| 255 | ret = snd_soc_update_bits(codec, CS4271_DACCTL, | 257 | ret = regmap_update_bits(cs4271->regmap, CS4271_DACCTL, |
| 256 | CS4271_DACCTL_DEM_MASK, val); | 258 | CS4271_DACCTL_DEM_MASK, val); |
| 257 | if (ret < 0) | 259 | if (ret < 0) |
| 258 | return ret; | 260 | return ret; |
| @@ -341,14 +343,14 @@ static int cs4271_hw_params(struct snd_pcm_substream *substream, | |||
| 341 | !dai->capture_active) || | 343 | !dai->capture_active) || |
| 342 | (substream->stream == SNDRV_PCM_STREAM_CAPTURE && | 344 | (substream->stream == SNDRV_PCM_STREAM_CAPTURE && |
| 343 | !dai->playback_active)) { | 345 | !dai->playback_active)) { |
| 344 | ret = snd_soc_update_bits(codec, CS4271_MODE2, | 346 | ret = regmap_update_bits(cs4271->regmap, CS4271_MODE2, |
| 345 | CS4271_MODE2_PDN, | 347 | CS4271_MODE2_PDN, |
| 346 | CS4271_MODE2_PDN); | 348 | CS4271_MODE2_PDN); |
| 347 | if (ret < 0) | 349 | if (ret < 0) |
| 348 | return ret; | 350 | return ret; |
| 349 | 351 | ||
| 350 | ret = snd_soc_update_bits(codec, CS4271_MODE2, | 352 | ret = regmap_update_bits(cs4271->regmap, CS4271_MODE2, |
| 351 | CS4271_MODE2_PDN, 0); | 353 | CS4271_MODE2_PDN, 0); |
| 352 | if (ret < 0) | 354 | if (ret < 0) |
| 353 | return ret; | 355 | return ret; |
| 354 | } | 356 | } |
| @@ -378,7 +380,7 @@ static int cs4271_hw_params(struct snd_pcm_substream *substream, | |||
| 378 | 380 | ||
| 379 | val |= cs4271_clk_tab[i].ratio_mask; | 381 | val |= cs4271_clk_tab[i].ratio_mask; |
| 380 | 382 | ||
| 381 | ret = snd_soc_update_bits(codec, CS4271_MODE1, | 383 | ret = regmap_update_bits(cs4271->regmap, CS4271_MODE1, |
| 382 | CS4271_MODE1_MODE_MASK | CS4271_MODE1_DIV_MASK, val); | 384 | CS4271_MODE1_MODE_MASK | CS4271_MODE1_DIV_MASK, val); |
| 383 | if (ret < 0) | 385 | if (ret < 0) |
| 384 | return ret; | 386 | return ret; |
| @@ -386,22 +388,29 @@ static int cs4271_hw_params(struct snd_pcm_substream *substream, | |||
| 386 | return cs4271_set_deemph(codec); | 388 | return cs4271_set_deemph(codec); |
| 387 | } | 389 | } |
| 388 | 390 | ||
| 389 | static int cs4271_digital_mute(struct snd_soc_dai *dai, int mute) | 391 | static int cs4271_mute_stream(struct snd_soc_dai *dai, int mute, int stream) |
| 390 | { | 392 | { |
| 391 | struct snd_soc_codec *codec = dai->codec; | 393 | struct snd_soc_codec *codec = dai->codec; |
| 394 | struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec); | ||
| 392 | int ret; | 395 | int ret; |
| 393 | int val_a = 0; | 396 | int val_a = 0; |
| 394 | int val_b = 0; | 397 | int val_b = 0; |
| 395 | 398 | ||
| 399 | if (stream != SNDRV_PCM_STREAM_PLAYBACK) | ||
| 400 | return 0; | ||
| 401 | |||
| 396 | if (mute) { | 402 | if (mute) { |
| 397 | val_a = CS4271_VOLA_MUTE; | 403 | val_a = CS4271_VOLA_MUTE; |
| 398 | val_b = CS4271_VOLB_MUTE; | 404 | val_b = CS4271_VOLB_MUTE; |
| 399 | } | 405 | } |
| 400 | 406 | ||
| 401 | ret = snd_soc_update_bits(codec, CS4271_VOLA, CS4271_VOLA_MUTE, val_a); | 407 | ret = regmap_update_bits(cs4271->regmap, CS4271_VOLA, |
| 408 | CS4271_VOLA_MUTE, val_a); | ||
| 402 | if (ret < 0) | 409 | if (ret < 0) |
| 403 | return ret; | 410 | return ret; |
| 404 | ret = snd_soc_update_bits(codec, CS4271_VOLB, CS4271_VOLB_MUTE, val_b); | 411 | |
| 412 | ret = regmap_update_bits(cs4271->regmap, CS4271_VOLB, | ||
| 413 | CS4271_VOLB_MUTE, val_b); | ||
| 405 | if (ret < 0) | 414 | if (ret < 0) |
| 406 | return ret; | 415 | return ret; |
| 407 | 416 | ||
| @@ -436,7 +445,7 @@ static const struct snd_soc_dai_ops cs4271_dai_ops = { | |||
| 436 | .hw_params = cs4271_hw_params, | 445 | .hw_params = cs4271_hw_params, |
| 437 | .set_sysclk = cs4271_set_dai_sysclk, | 446 | .set_sysclk = cs4271_set_dai_sysclk, |
| 438 | .set_fmt = cs4271_set_dai_fmt, | 447 | .set_fmt = cs4271_set_dai_fmt, |
| 439 | .digital_mute = cs4271_digital_mute, | 448 | .mute_stream = cs4271_mute_stream, |
| 440 | }; | 449 | }; |
| 441 | 450 | ||
| 442 | static struct snd_soc_dai_driver cs4271_dai = { | 451 | static struct snd_soc_dai_driver cs4271_dai = { |
| @@ -463,25 +472,33 @@ static struct snd_soc_dai_driver cs4271_dai = { | |||
| 463 | static int cs4271_soc_suspend(struct snd_soc_codec *codec) | 472 | static int cs4271_soc_suspend(struct snd_soc_codec *codec) |
| 464 | { | 473 | { |
| 465 | int ret; | 474 | int ret; |
| 475 | struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec); | ||
| 476 | |||
| 466 | /* Set power-down bit */ | 477 | /* Set power-down bit */ |
| 467 | ret = snd_soc_update_bits(codec, CS4271_MODE2, CS4271_MODE2_PDN, | 478 | ret = regmap_update_bits(cs4271->regmap, CS4271_MODE2, |
| 468 | CS4271_MODE2_PDN); | 479 | CS4271_MODE2_PDN, CS4271_MODE2_PDN); |
| 469 | if (ret < 0) | 480 | if (ret < 0) |
| 470 | return ret; | 481 | return ret; |
| 482 | |||
| 471 | return 0; | 483 | return 0; |
| 472 | } | 484 | } |
| 473 | 485 | ||
| 474 | static int cs4271_soc_resume(struct snd_soc_codec *codec) | 486 | static int cs4271_soc_resume(struct snd_soc_codec *codec) |
| 475 | { | 487 | { |
| 476 | int ret; | 488 | int ret; |
| 489 | struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec); | ||
| 490 | |||
| 477 | /* Restore codec state */ | 491 | /* Restore codec state */ |
| 478 | ret = snd_soc_cache_sync(codec); | 492 | ret = regcache_sync(cs4271->regmap); |
| 479 | if (ret < 0) | 493 | if (ret < 0) |
| 480 | return ret; | 494 | return ret; |
| 495 | |||
| 481 | /* then disable the power-down bit */ | 496 | /* then disable the power-down bit */ |
| 482 | ret = snd_soc_update_bits(codec, CS4271_MODE2, CS4271_MODE2_PDN, 0); | 497 | ret = regmap_update_bits(cs4271->regmap, CS4271_MODE2, |
| 498 | CS4271_MODE2_PDN, 0); | ||
| 483 | if (ret < 0) | 499 | if (ret < 0) |
| 484 | return ret; | 500 | return ret; |
| 501 | |||
| 485 | return 0; | 502 | return 0; |
| 486 | } | 503 | } |
| 487 | #else | 504 | #else |
| @@ -542,40 +559,22 @@ static int cs4271_probe(struct snd_soc_codec *codec) | |||
| 542 | 559 | ||
| 543 | cs4271->gpio_nreset = gpio_nreset; | 560 | cs4271->gpio_nreset = gpio_nreset; |
| 544 | 561 | ||
| 545 | /* | 562 | ret = regmap_update_bits(cs4271->regmap, CS4271_MODE2, |
| 546 | * In case of I2C, chip address specified in board data. | 563 | CS4271_MODE2_PDN | CS4271_MODE2_CPEN, |
| 547 | * So cache IO operations use 8 bit codec register address. | 564 | CS4271_MODE2_PDN | CS4271_MODE2_CPEN); |
| 548 | * In case of SPI, chip address and register address | ||
| 549 | * passed together as 16 bit value. | ||
| 550 | * Anyway, register address is masked with 0xFF inside | ||
| 551 | * soc-cache code. | ||
| 552 | */ | ||
| 553 | if (cs4271->bus_type == SND_SOC_SPI) | ||
| 554 | ret = snd_soc_codec_set_cache_io(codec, 16, 8, | ||
| 555 | cs4271->bus_type); | ||
| 556 | else | ||
| 557 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, | ||
| 558 | cs4271->bus_type); | ||
| 559 | if (ret) { | ||
| 560 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
| 561 | return ret; | ||
| 562 | } | ||
| 563 | |||
| 564 | ret = snd_soc_update_bits(codec, CS4271_MODE2, | ||
| 565 | CS4271_MODE2_PDN | CS4271_MODE2_CPEN, | ||
| 566 | CS4271_MODE2_PDN | CS4271_MODE2_CPEN); | ||
| 567 | if (ret < 0) | 565 | if (ret < 0) |
| 568 | return ret; | 566 | return ret; |
| 569 | ret = snd_soc_update_bits(codec, CS4271_MODE2, CS4271_MODE2_PDN, 0); | 567 | ret = regmap_update_bits(cs4271->regmap, CS4271_MODE2, |
| 568 | CS4271_MODE2_PDN, 0); | ||
| 570 | if (ret < 0) | 569 | if (ret < 0) |
| 571 | return ret; | 570 | return ret; |
| 572 | /* Power-up sequence requires 85 uS */ | 571 | /* Power-up sequence requires 85 uS */ |
| 573 | udelay(85); | 572 | udelay(85); |
| 574 | 573 | ||
| 575 | if (amutec_eq_bmutec) | 574 | if (amutec_eq_bmutec) |
| 576 | snd_soc_update_bits(codec, CS4271_MODE2, | 575 | regmap_update_bits(cs4271->regmap, CS4271_MODE2, |
| 577 | CS4271_MODE2_MUTECAEQUB, | 576 | CS4271_MODE2_MUTECAEQUB, |
| 578 | CS4271_MODE2_MUTECAEQUB); | 577 | CS4271_MODE2_MUTECAEQUB); |
| 579 | 578 | ||
| 580 | return snd_soc_add_codec_controls(codec, cs4271_snd_controls, | 579 | return snd_soc_add_codec_controls(codec, cs4271_snd_controls, |
| 581 | ARRAY_SIZE(cs4271_snd_controls)); | 580 | ARRAY_SIZE(cs4271_snd_controls)); |
| @@ -597,13 +596,24 @@ static struct snd_soc_codec_driver soc_codec_dev_cs4271 = { | |||
| 597 | .remove = cs4271_remove, | 596 | .remove = cs4271_remove, |
| 598 | .suspend = cs4271_soc_suspend, | 597 | .suspend = cs4271_soc_suspend, |
| 599 | .resume = cs4271_soc_resume, | 598 | .resume = cs4271_soc_resume, |
| 600 | .reg_cache_default = cs4271_dflt_reg, | ||
| 601 | .reg_cache_size = ARRAY_SIZE(cs4271_dflt_reg), | ||
| 602 | .reg_word_size = sizeof(cs4271_dflt_reg[0]), | ||
| 603 | .compress_type = SND_SOC_FLAT_COMPRESSION, | ||
| 604 | }; | 599 | }; |
| 605 | 600 | ||
| 606 | #if defined(CONFIG_SPI_MASTER) | 601 | #if defined(CONFIG_SPI_MASTER) |
| 602 | |||
| 603 | static const struct regmap_config cs4271_spi_regmap = { | ||
| 604 | .reg_bits = 16, | ||
| 605 | .val_bits = 8, | ||
| 606 | .max_register = CS4271_LASTREG, | ||
| 607 | .read_flag_mask = 0x21, | ||
| 608 | .write_flag_mask = 0x20, | ||
| 609 | |||
| 610 | .reg_defaults = cs4271_reg_defaults, | ||
| 611 | .num_reg_defaults = ARRAY_SIZE(cs4271_reg_defaults), | ||
| 612 | .cache_type = REGCACHE_RBTREE, | ||
| 613 | |||
| 614 | .volatile_reg = cs4271_volatile_reg, | ||
| 615 | }; | ||
| 616 | |||
| 607 | static int cs4271_spi_probe(struct spi_device *spi) | 617 | static int cs4271_spi_probe(struct spi_device *spi) |
| 608 | { | 618 | { |
| 609 | struct cs4271_private *cs4271; | 619 | struct cs4271_private *cs4271; |
| @@ -613,7 +623,9 @@ static int cs4271_spi_probe(struct spi_device *spi) | |||
| 613 | return -ENOMEM; | 623 | return -ENOMEM; |
| 614 | 624 | ||
| 615 | spi_set_drvdata(spi, cs4271); | 625 | spi_set_drvdata(spi, cs4271); |
| 616 | cs4271->bus_type = SND_SOC_SPI; | 626 | cs4271->regmap = devm_regmap_init_spi(spi, &cs4271_spi_regmap); |
| 627 | if (IS_ERR(cs4271->regmap)) | ||
| 628 | return PTR_ERR(cs4271->regmap); | ||
| 617 | 629 | ||
| 618 | return snd_soc_register_codec(&spi->dev, &soc_codec_dev_cs4271, | 630 | return snd_soc_register_codec(&spi->dev, &soc_codec_dev_cs4271, |
| 619 | &cs4271_dai, 1); | 631 | &cs4271_dai, 1); |
| @@ -643,6 +655,18 @@ static const struct i2c_device_id cs4271_i2c_id[] = { | |||
| 643 | }; | 655 | }; |
| 644 | MODULE_DEVICE_TABLE(i2c, cs4271_i2c_id); | 656 | MODULE_DEVICE_TABLE(i2c, cs4271_i2c_id); |
| 645 | 657 | ||
| 658 | static const struct regmap_config cs4271_i2c_regmap = { | ||
| 659 | .reg_bits = 8, | ||
| 660 | .val_bits = 8, | ||
| 661 | .max_register = CS4271_LASTREG, | ||
| 662 | |||
| 663 | .reg_defaults = cs4271_reg_defaults, | ||
| 664 | .num_reg_defaults = ARRAY_SIZE(cs4271_reg_defaults), | ||
| 665 | .cache_type = REGCACHE_RBTREE, | ||
| 666 | |||
| 667 | .volatile_reg = cs4271_volatile_reg, | ||
| 668 | }; | ||
| 669 | |||
| 646 | static int cs4271_i2c_probe(struct i2c_client *client, | 670 | static int cs4271_i2c_probe(struct i2c_client *client, |
| 647 | const struct i2c_device_id *id) | 671 | const struct i2c_device_id *id) |
| 648 | { | 672 | { |
| @@ -653,7 +677,9 @@ static int cs4271_i2c_probe(struct i2c_client *client, | |||
| 653 | return -ENOMEM; | 677 | return -ENOMEM; |
| 654 | 678 | ||
| 655 | i2c_set_clientdata(client, cs4271); | 679 | i2c_set_clientdata(client, cs4271); |
| 656 | cs4271->bus_type = SND_SOC_I2C; | 680 | cs4271->regmap = devm_regmap_init_i2c(client, &cs4271_i2c_regmap); |
| 681 | if (IS_ERR(cs4271->regmap)) | ||
| 682 | return PTR_ERR(cs4271->regmap); | ||
| 657 | 683 | ||
| 658 | return snd_soc_register_codec(&client->dev, &soc_codec_dev_cs4271, | 684 | return snd_soc_register_codec(&client->dev, &soc_codec_dev_cs4271, |
| 659 | &cs4271_dai, 1); | 685 | &cs4271_dai, 1); |
