diff options
| -rw-r--r-- | sound/soc/codecs/pcm512x.c | 441 | ||||
| -rw-r--r-- | sound/soc/codecs/pcm512x.h | 57 |
2 files changed, 481 insertions, 17 deletions
diff --git a/sound/soc/codecs/pcm512x.c b/sound/soc/codecs/pcm512x.c index 874723c36d65..526e6b30cdde 100644 --- a/sound/soc/codecs/pcm512x.c +++ b/sound/soc/codecs/pcm512x.c | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | #include <linux/regulator/consumer.h> | 23 | #include <linux/regulator/consumer.h> |
| 24 | #include <sound/soc.h> | 24 | #include <sound/soc.h> |
| 25 | #include <sound/soc-dapm.h> | 25 | #include <sound/soc-dapm.h> |
| 26 | #include <sound/pcm_params.h> | ||
| 26 | #include <sound/tlv.h> | 27 | #include <sound/tlv.h> |
| 27 | 28 | ||
| 28 | #include "pcm512x.h" | 29 | #include "pcm512x.h" |
| @@ -39,6 +40,7 @@ struct pcm512x_priv { | |||
| 39 | struct clk *sclk; | 40 | struct clk *sclk; |
| 40 | struct regulator_bulk_data supplies[PCM512x_NUM_SUPPLIES]; | 41 | struct regulator_bulk_data supplies[PCM512x_NUM_SUPPLIES]; |
| 41 | struct notifier_block supply_nb[PCM512x_NUM_SUPPLIES]; | 42 | struct notifier_block supply_nb[PCM512x_NUM_SUPPLIES]; |
| 43 | int fmt; | ||
| 42 | }; | 44 | }; |
| 43 | 45 | ||
| 44 | /* | 46 | /* |
| @@ -69,6 +71,7 @@ static const struct reg_default pcm512x_reg_defaults[] = { | |||
| 69 | { PCM512x_MUTE, 0x00 }, | 71 | { PCM512x_MUTE, 0x00 }, |
| 70 | { PCM512x_DSP, 0x00 }, | 72 | { PCM512x_DSP, 0x00 }, |
| 71 | { PCM512x_PLL_REF, 0x00 }, | 73 | { PCM512x_PLL_REF, 0x00 }, |
| 74 | { PCM512x_DAC_REF, 0x00 }, | ||
| 72 | { PCM512x_DAC_ROUTING, 0x11 }, | 75 | { PCM512x_DAC_ROUTING, 0x11 }, |
| 73 | { PCM512x_DSP_PROGRAM, 0x01 }, | 76 | { PCM512x_DSP_PROGRAM, 0x01 }, |
| 74 | { PCM512x_CLKDET, 0x00 }, | 77 | { PCM512x_CLKDET, 0x00 }, |
| @@ -87,6 +90,18 @@ static const struct reg_default pcm512x_reg_defaults[] = { | |||
| 87 | { PCM512x_ANALOG_GAIN_BOOST, 0x00 }, | 90 | { PCM512x_ANALOG_GAIN_BOOST, 0x00 }, |
| 88 | { PCM512x_VCOM_CTRL_1, 0x00 }, | 91 | { PCM512x_VCOM_CTRL_1, 0x00 }, |
| 89 | { PCM512x_VCOM_CTRL_2, 0x01 }, | 92 | { PCM512x_VCOM_CTRL_2, 0x01 }, |
| 93 | { PCM512x_BCLK_LRCLK_CFG, 0x00 }, | ||
| 94 | { PCM512x_MASTER_MODE, 0x7c }, | ||
| 95 | { PCM512x_SYNCHRONIZE, 0x10 }, | ||
| 96 | { PCM512x_DSP_CLKDIV, 0x00 }, | ||
| 97 | { PCM512x_DAC_CLKDIV, 0x00 }, | ||
| 98 | { PCM512x_NCP_CLKDIV, 0x00 }, | ||
| 99 | { PCM512x_OSR_CLKDIV, 0x00 }, | ||
| 100 | { PCM512x_MASTER_CLKDIV_1, 0x00 }, | ||
| 101 | { PCM512x_MASTER_CLKDIV_2, 0x00 }, | ||
| 102 | { PCM512x_FS_SPEED_MODE, 0x00 }, | ||
| 103 | { PCM512x_IDAC_1, 0x01 }, | ||
| 104 | { PCM512x_IDAC_2, 0x00 }, | ||
| 90 | }; | 105 | }; |
| 91 | 106 | ||
| 92 | static bool pcm512x_readable(struct device *dev, unsigned int reg) | 107 | static bool pcm512x_readable(struct device *dev, unsigned int reg) |
| @@ -103,6 +118,8 @@ static bool pcm512x_readable(struct device *dev, unsigned int reg) | |||
| 103 | case PCM512x_DSP_GPIO_INPUT: | 118 | case PCM512x_DSP_GPIO_INPUT: |
| 104 | case PCM512x_MASTER_MODE: | 119 | case PCM512x_MASTER_MODE: |
| 105 | case PCM512x_PLL_REF: | 120 | case PCM512x_PLL_REF: |
| 121 | case PCM512x_DAC_REF: | ||
| 122 | case PCM512x_SYNCHRONIZE: | ||
| 106 | case PCM512x_PLL_COEFF_0: | 123 | case PCM512x_PLL_COEFF_0: |
| 107 | case PCM512x_PLL_COEFF_1: | 124 | case PCM512x_PLL_COEFF_1: |
| 108 | case PCM512x_PLL_COEFF_2: | 125 | case PCM512x_PLL_COEFF_2: |
| @@ -303,6 +320,94 @@ static const struct snd_soc_dapm_route pcm512x_dapm_routes[] = { | |||
| 303 | { "OUTR", NULL, "DACR" }, | 320 | { "OUTR", NULL, "DACR" }, |
| 304 | }; | 321 | }; |
| 305 | 322 | ||
| 323 | static const u32 pcm512x_dai_rates[] = { | ||
| 324 | 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000, | ||
| 325 | 88200, 96000, 176400, 192000, 384000, | ||
| 326 | }; | ||
| 327 | |||
| 328 | static const struct snd_pcm_hw_constraint_list constraints_slave = { | ||
| 329 | .count = ARRAY_SIZE(pcm512x_dai_rates), | ||
| 330 | .list = pcm512x_dai_rates, | ||
| 331 | }; | ||
| 332 | |||
| 333 | static int pcm512x_dai_startup_master(struct snd_pcm_substream *substream, | ||
| 334 | struct snd_soc_dai *dai) | ||
| 335 | { | ||
| 336 | struct snd_soc_codec *codec = dai->codec; | ||
| 337 | struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec); | ||
| 338 | struct device *dev = dai->dev; | ||
| 339 | struct snd_pcm_hw_constraint_ratnums *constraints_no_pll; | ||
| 340 | struct snd_ratnum *rats_no_pll; | ||
| 341 | |||
| 342 | if (IS_ERR(pcm512x->sclk)) { | ||
| 343 | dev_err(dev, "Need SCLK for master mode: %ld\n", | ||
| 344 | PTR_ERR(pcm512x->sclk)); | ||
| 345 | return PTR_ERR(pcm512x->sclk); | ||
| 346 | } | ||
| 347 | |||
| 348 | constraints_no_pll = devm_kzalloc(dev, sizeof(*constraints_no_pll), | ||
| 349 | GFP_KERNEL); | ||
| 350 | if (!constraints_no_pll) | ||
| 351 | return -ENOMEM; | ||
| 352 | constraints_no_pll->nrats = 1; | ||
| 353 | rats_no_pll = devm_kzalloc(dev, sizeof(*rats_no_pll), GFP_KERNEL); | ||
| 354 | if (!rats_no_pll) | ||
| 355 | return -ENOMEM; | ||
| 356 | constraints_no_pll->rats = rats_no_pll; | ||
| 357 | rats_no_pll->num = clk_get_rate(pcm512x->sclk) / 64; | ||
| 358 | rats_no_pll->den_min = 1; | ||
| 359 | rats_no_pll->den_max = 128; | ||
| 360 | rats_no_pll->den_step = 1; | ||
| 361 | |||
| 362 | return snd_pcm_hw_constraint_ratnums(substream->runtime, 0, | ||
| 363 | SNDRV_PCM_HW_PARAM_RATE, | ||
| 364 | constraints_no_pll); | ||
| 365 | } | ||
| 366 | |||
| 367 | static int pcm512x_dai_startup_slave(struct snd_pcm_substream *substream, | ||
| 368 | struct snd_soc_dai *dai) | ||
| 369 | { | ||
| 370 | struct snd_soc_codec *codec = dai->codec; | ||
| 371 | struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec); | ||
| 372 | struct device *dev = dai->dev; | ||
| 373 | struct regmap *regmap = pcm512x->regmap; | ||
| 374 | |||
| 375 | if (IS_ERR(pcm512x->sclk)) { | ||
| 376 | dev_info(dev, "No SCLK, using BCLK: %ld\n", | ||
| 377 | PTR_ERR(pcm512x->sclk)); | ||
| 378 | |||
| 379 | /* Disable reporting of missing SCLK as an error */ | ||
| 380 | regmap_update_bits(regmap, PCM512x_ERROR_DETECT, | ||
| 381 | PCM512x_IDCH, PCM512x_IDCH); | ||
| 382 | |||
| 383 | /* Switch PLL input to BCLK */ | ||
| 384 | regmap_update_bits(regmap, PCM512x_PLL_REF, | ||
| 385 | PCM512x_SREF, PCM512x_SREF_BCK); | ||
| 386 | } | ||
| 387 | |||
| 388 | return snd_pcm_hw_constraint_list(substream->runtime, 0, | ||
| 389 | SNDRV_PCM_HW_PARAM_RATE, | ||
| 390 | &constraints_slave); | ||
| 391 | } | ||
| 392 | |||
| 393 | static int pcm512x_dai_startup(struct snd_pcm_substream *substream, | ||
| 394 | struct snd_soc_dai *dai) | ||
| 395 | { | ||
| 396 | struct snd_soc_codec *codec = dai->codec; | ||
| 397 | struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec); | ||
| 398 | |||
| 399 | switch (pcm512x->fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
| 400 | case SND_SOC_DAIFMT_CBM_CFM: | ||
| 401 | return pcm512x_dai_startup_master(substream, dai); | ||
| 402 | |||
| 403 | case SND_SOC_DAIFMT_CBS_CFS: | ||
| 404 | return pcm512x_dai_startup_slave(substream, dai); | ||
| 405 | |||
| 406 | default: | ||
| 407 | return -EINVAL; | ||
| 408 | } | ||
| 409 | } | ||
| 410 | |||
| 306 | static int pcm512x_set_bias_level(struct snd_soc_codec *codec, | 411 | static int pcm512x_set_bias_level(struct snd_soc_codec *codec, |
| 307 | enum snd_soc_bias_level level) | 412 | enum snd_soc_bias_level level) |
| 308 | { | 413 | { |
| @@ -340,17 +445,333 @@ static int pcm512x_set_bias_level(struct snd_soc_codec *codec, | |||
| 340 | return 0; | 445 | return 0; |
| 341 | } | 446 | } |
| 342 | 447 | ||
| 448 | static int pcm512x_set_dividers(struct snd_soc_dai *dai, | ||
| 449 | struct snd_pcm_hw_params *params) | ||
| 450 | { | ||
| 451 | struct device *dev = dai->dev; | ||
| 452 | struct snd_soc_codec *codec = dai->codec; | ||
| 453 | struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec); | ||
| 454 | unsigned long sck_rate; | ||
| 455 | unsigned long mck_rate; | ||
| 456 | unsigned long bclk_rate; | ||
| 457 | unsigned long sample_rate; | ||
| 458 | unsigned long osr_rate; | ||
| 459 | int bclk_div; | ||
| 460 | int lrclk_div; | ||
| 461 | int dsp_div; | ||
| 462 | int dac_div; | ||
| 463 | unsigned long dac_rate; | ||
| 464 | int ncp_div; | ||
| 465 | int osr_div; | ||
| 466 | unsigned long dac_mul; | ||
| 467 | unsigned long sck_mul; | ||
| 468 | int ret; | ||
| 469 | int idac; | ||
| 470 | int fssp; | ||
| 471 | |||
| 472 | lrclk_div = snd_soc_params_to_frame_size(params); | ||
| 473 | if (lrclk_div == 0) { | ||
| 474 | dev_err(dev, "No LRCLK?\n"); | ||
| 475 | return -EINVAL; | ||
| 476 | } | ||
| 477 | |||
| 478 | sck_rate = clk_get_rate(pcm512x->sclk); | ||
| 479 | bclk_div = params->rate_den * 64 / lrclk_div; | ||
| 480 | bclk_rate = DIV_ROUND_CLOSEST(sck_rate, bclk_div); | ||
| 481 | |||
| 482 | mck_rate = sck_rate; | ||
| 483 | |||
| 484 | if (bclk_div > 128) { | ||
| 485 | dev_err(dev, "Failed to find BCLK divider\n"); | ||
| 486 | return -EINVAL; | ||
| 487 | } | ||
| 488 | |||
| 489 | /* the actual rate */ | ||
| 490 | sample_rate = sck_rate / bclk_div / lrclk_div; | ||
| 491 | osr_rate = 16 * sample_rate; | ||
| 492 | |||
| 493 | /* run DSP no faster than 50 MHz */ | ||
| 494 | dsp_div = mck_rate > 50000000 ? 2 : 1; | ||
| 495 | |||
| 496 | /* run DAC no faster than 6144000 Hz */ | ||
| 497 | dac_mul = 6144000 / osr_rate; | ||
| 498 | sck_mul = sck_rate / osr_rate; | ||
| 499 | for (; dac_mul; dac_mul--) { | ||
| 500 | if (!(sck_mul % dac_mul)) | ||
| 501 | break; | ||
| 502 | } | ||
| 503 | if (!dac_mul) { | ||
| 504 | dev_err(dev, "Failed to find DAC rate\n"); | ||
| 505 | return -EINVAL; | ||
| 506 | } | ||
| 507 | |||
| 508 | dac_rate = dac_mul * osr_rate; | ||
| 509 | dev_dbg(dev, "dac_rate %lu sample_rate %lu\n", dac_rate, sample_rate); | ||
| 510 | |||
| 511 | dac_div = DIV_ROUND_CLOSEST(sck_rate, dac_rate); | ||
| 512 | if (dac_div > 128) { | ||
| 513 | dev_err(dev, "Failed to find DAC divider\n"); | ||
| 514 | return -EINVAL; | ||
| 515 | } | ||
| 516 | |||
| 517 | ncp_div = DIV_ROUND_CLOSEST(sck_rate / dac_div, 1536000); | ||
| 518 | if (ncp_div > 128 || sck_rate / dac_div / ncp_div > 2048000) { | ||
| 519 | /* run NCP no faster than 2048000 Hz, but why? */ | ||
| 520 | ncp_div = DIV_ROUND_UP(sck_rate / dac_div, 2048000); | ||
| 521 | if (ncp_div > 128) { | ||
| 522 | dev_err(dev, "Failed to find NCP divider\n"); | ||
| 523 | return -EINVAL; | ||
| 524 | } | ||
| 525 | } | ||
| 526 | |||
| 527 | osr_div = DIV_ROUND_CLOSEST(dac_rate, osr_rate); | ||
| 528 | if (osr_div > 128) { | ||
| 529 | dev_err(dev, "Failed to find OSR divider\n"); | ||
| 530 | return -EINVAL; | ||
| 531 | } | ||
| 532 | |||
| 533 | idac = mck_rate / (dsp_div * sample_rate); | ||
| 534 | |||
| 535 | ret = regmap_write(pcm512x->regmap, PCM512x_DSP_CLKDIV, dsp_div - 1); | ||
| 536 | if (ret != 0) { | ||
| 537 | dev_err(dev, "Failed to write DSP divider: %d\n", ret); | ||
| 538 | return ret; | ||
| 539 | } | ||
| 540 | |||
| 541 | ret = regmap_write(pcm512x->regmap, PCM512x_DAC_CLKDIV, dac_div - 1); | ||
| 542 | if (ret != 0) { | ||
| 543 | dev_err(dev, "Failed to write DAC divider: %d\n", ret); | ||
| 544 | return ret; | ||
| 545 | } | ||
| 546 | |||
| 547 | ret = regmap_write(pcm512x->regmap, PCM512x_NCP_CLKDIV, ncp_div - 1); | ||
| 548 | if (ret != 0) { | ||
| 549 | dev_err(dev, "Failed to write NCP divider: %d\n", ret); | ||
| 550 | return ret; | ||
| 551 | } | ||
| 552 | |||
| 553 | ret = regmap_write(pcm512x->regmap, PCM512x_OSR_CLKDIV, osr_div - 1); | ||
| 554 | if (ret != 0) { | ||
| 555 | dev_err(dev, "Failed to write OSR divider: %d\n", ret); | ||
| 556 | return ret; | ||
| 557 | } | ||
| 558 | |||
| 559 | ret = regmap_write(pcm512x->regmap, | ||
| 560 | PCM512x_MASTER_CLKDIV_1, bclk_div - 1); | ||
| 561 | if (ret != 0) { | ||
| 562 | dev_err(dev, "Failed to write BCLK divider: %d\n", ret); | ||
| 563 | return ret; | ||
| 564 | } | ||
| 565 | |||
| 566 | ret = regmap_write(pcm512x->regmap, | ||
| 567 | PCM512x_MASTER_CLKDIV_2, lrclk_div - 1); | ||
| 568 | if (ret != 0) { | ||
| 569 | dev_err(dev, "Failed to write LRCLK divider: %d\n", ret); | ||
| 570 | return ret; | ||
| 571 | } | ||
| 572 | |||
| 573 | ret = regmap_write(pcm512x->regmap, PCM512x_IDAC_1, idac >> 8); | ||
| 574 | if (ret != 0) { | ||
| 575 | dev_err(dev, "Failed to write IDAC msb divider: %d\n", ret); | ||
| 576 | return ret; | ||
| 577 | } | ||
| 578 | |||
| 579 | ret = regmap_write(pcm512x->regmap, PCM512x_IDAC_2, idac & 0xff); | ||
| 580 | if (ret != 0) { | ||
| 581 | dev_err(dev, "Failed to write IDAC lsb divider: %d\n", ret); | ||
| 582 | return ret; | ||
| 583 | } | ||
| 584 | |||
| 585 | if (sample_rate <= 48000) | ||
| 586 | fssp = PCM512x_FSSP_48KHZ; | ||
| 587 | else if (sample_rate <= 96000) | ||
| 588 | fssp = PCM512x_FSSP_96KHZ; | ||
| 589 | else if (sample_rate <= 192000) | ||
| 590 | fssp = PCM512x_FSSP_192KHZ; | ||
| 591 | else | ||
| 592 | fssp = PCM512x_FSSP_384KHZ; | ||
| 593 | ret = regmap_update_bits(pcm512x->regmap, PCM512x_FS_SPEED_MODE, | ||
| 594 | PCM512x_FSSP, fssp); | ||
| 595 | if (ret != 0) { | ||
| 596 | dev_err(codec->dev, "Failed to set fs speed: %d\n", ret); | ||
| 597 | return ret; | ||
| 598 | } | ||
| 599 | |||
| 600 | dev_dbg(codec->dev, "DSP divider %d\n", dsp_div); | ||
| 601 | dev_dbg(codec->dev, "DAC divider %d\n", dac_div); | ||
| 602 | dev_dbg(codec->dev, "NCP divider %d\n", ncp_div); | ||
| 603 | dev_dbg(codec->dev, "OSR divider %d\n", osr_div); | ||
| 604 | dev_dbg(codec->dev, "BCK divider %d\n", bclk_div); | ||
| 605 | dev_dbg(codec->dev, "LRCK divider %d\n", lrclk_div); | ||
| 606 | dev_dbg(codec->dev, "IDAC %d\n", idac); | ||
| 607 | dev_dbg(codec->dev, "1<<FSSP %d\n", 1 << fssp); | ||
| 608 | |||
| 609 | return 0; | ||
| 610 | } | ||
| 611 | |||
| 612 | static int pcm512x_hw_params(struct snd_pcm_substream *substream, | ||
| 613 | struct snd_pcm_hw_params *params, | ||
| 614 | struct snd_soc_dai *dai) | ||
| 615 | { | ||
| 616 | struct snd_soc_codec *codec = dai->codec; | ||
| 617 | struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec); | ||
| 618 | int alen; | ||
| 619 | int ret; | ||
| 620 | |||
| 621 | dev_dbg(codec->dev, "hw_params %u Hz, %u channels\n", | ||
| 622 | params_rate(params), | ||
| 623 | params_channels(params)); | ||
| 624 | |||
| 625 | switch (snd_pcm_format_width(params_format(params))) { | ||
| 626 | case 16: | ||
| 627 | alen = PCM512x_ALEN_16; | ||
| 628 | break; | ||
| 629 | case 20: | ||
| 630 | alen = PCM512x_ALEN_20; | ||
| 631 | break; | ||
| 632 | case 24: | ||
| 633 | alen = PCM512x_ALEN_24; | ||
| 634 | break; | ||
| 635 | case 32: | ||
| 636 | alen = PCM512x_ALEN_32; | ||
| 637 | break; | ||
| 638 | default: | ||
| 639 | dev_err(codec->dev, "Bad frame size: %d\n", | ||
| 640 | snd_pcm_format_width(params_format(params))); | ||
| 641 | return -EINVAL; | ||
| 642 | } | ||
| 643 | |||
| 644 | switch (pcm512x->fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
| 645 | case SND_SOC_DAIFMT_CBS_CFS: | ||
| 646 | ret = regmap_update_bits(pcm512x->regmap, | ||
| 647 | PCM512x_BCLK_LRCLK_CFG, | ||
| 648 | PCM512x_BCKP | ||
| 649 | | PCM512x_BCKO | PCM512x_LRKO, | ||
| 650 | 0); | ||
| 651 | if (ret != 0) { | ||
| 652 | dev_err(codec->dev, | ||
| 653 | "Failed to enable slave mode: %d\n", ret); | ||
| 654 | return ret; | ||
| 655 | } | ||
| 656 | |||
| 657 | ret = regmap_update_bits(pcm512x->regmap, PCM512x_ERROR_DETECT, | ||
| 658 | PCM512x_DCAS, 0); | ||
| 659 | if (ret != 0) { | ||
| 660 | dev_err(codec->dev, | ||
| 661 | "Failed to enable clock divider autoset: %d\n", | ||
| 662 | ret); | ||
| 663 | return ret; | ||
| 664 | } | ||
| 665 | return 0; | ||
| 666 | case SND_SOC_DAIFMT_CBM_CFM: | ||
| 667 | break; | ||
| 668 | default: | ||
| 669 | return -EINVAL; | ||
| 670 | } | ||
| 671 | |||
| 672 | ret = regmap_update_bits(pcm512x->regmap, PCM512x_I2S_1, | ||
| 673 | PCM512x_ALEN, alen); | ||
| 674 | if (ret != 0) { | ||
| 675 | dev_err(codec->dev, "Failed to set frame size: %d\n", ret); | ||
| 676 | return ret; | ||
| 677 | } | ||
| 678 | |||
| 679 | ret = regmap_update_bits(pcm512x->regmap, PCM512x_ERROR_DETECT, | ||
| 680 | PCM512x_IDFS | PCM512x_IDBK | ||
| 681 | | PCM512x_IDSK | PCM512x_IDCH | ||
| 682 | | PCM512x_IDCM | PCM512x_DCAS | ||
| 683 | | PCM512x_IPLK, | ||
| 684 | PCM512x_IDFS | PCM512x_IDBK | ||
| 685 | | PCM512x_IDSK | PCM512x_IDCH | ||
| 686 | | PCM512x_DCAS | PCM512x_IPLK); | ||
| 687 | if (ret != 0) { | ||
| 688 | dev_err(codec->dev, | ||
| 689 | "Failed to ignore auto-clock failures: %d\n", | ||
| 690 | ret); | ||
| 691 | return ret; | ||
| 692 | } | ||
| 693 | |||
| 694 | ret = regmap_update_bits(pcm512x->regmap, PCM512x_PLL_EN, | ||
| 695 | PCM512x_PLLE, 0); | ||
| 696 | if (ret != 0) { | ||
| 697 | dev_err(codec->dev, "Failed to disable pll: %d\n", ret); | ||
| 698 | return ret; | ||
| 699 | } | ||
| 700 | |||
| 701 | ret = pcm512x_set_dividers(dai, params); | ||
| 702 | if (ret != 0) | ||
| 703 | return ret; | ||
| 704 | |||
| 705 | ret = regmap_update_bits(pcm512x->regmap, PCM512x_DAC_REF, | ||
| 706 | PCM512x_SDAC, PCM512x_SDAC_SCK); | ||
| 707 | if (ret != 0) { | ||
| 708 | dev_err(codec->dev, "Failed to set sck as dacref: %d\n", ret); | ||
| 709 | return ret; | ||
| 710 | } | ||
| 711 | |||
| 712 | ret = regmap_update_bits(pcm512x->regmap, PCM512x_BCLK_LRCLK_CFG, | ||
| 713 | PCM512x_BCKP | PCM512x_BCKO | PCM512x_LRKO, | ||
| 714 | PCM512x_BCKO | PCM512x_LRKO); | ||
| 715 | if (ret != 0) { | ||
| 716 | dev_err(codec->dev, "Failed to enable clock output: %d\n", ret); | ||
| 717 | return ret; | ||
| 718 | } | ||
| 719 | |||
| 720 | ret = regmap_update_bits(pcm512x->regmap, PCM512x_MASTER_MODE, | ||
| 721 | PCM512x_RLRK | PCM512x_RBCK, | ||
| 722 | PCM512x_RLRK | PCM512x_RBCK); | ||
| 723 | if (ret != 0) { | ||
| 724 | dev_err(codec->dev, "Failed to enable master mode: %d\n", ret); | ||
| 725 | return ret; | ||
| 726 | } | ||
| 727 | |||
| 728 | ret = regmap_update_bits(pcm512x->regmap, PCM512x_SYNCHRONIZE, | ||
| 729 | PCM512x_RQSY, PCM512x_RQSY_HALT); | ||
| 730 | if (ret != 0) { | ||
| 731 | dev_err(codec->dev, "Failed to halt clocks: %d\n", ret); | ||
| 732 | return ret; | ||
| 733 | } | ||
| 734 | |||
| 735 | ret = regmap_update_bits(pcm512x->regmap, PCM512x_SYNCHRONIZE, | ||
| 736 | PCM512x_RQSY, PCM512x_RQSY_RESUME); | ||
| 737 | if (ret != 0) { | ||
| 738 | dev_err(codec->dev, "Failed to resume clocks: %d\n", ret); | ||
| 739 | return ret; | ||
| 740 | } | ||
| 741 | |||
| 742 | return 0; | ||
| 743 | } | ||
| 744 | |||
| 745 | static int pcm512x_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | ||
| 746 | { | ||
| 747 | struct snd_soc_codec *codec = dai->codec; | ||
| 748 | struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec); | ||
| 749 | |||
| 750 | pcm512x->fmt = fmt; | ||
| 751 | |||
| 752 | return 0; | ||
| 753 | } | ||
| 754 | |||
| 755 | static const struct snd_soc_dai_ops pcm512x_dai_ops = { | ||
| 756 | .startup = pcm512x_dai_startup, | ||
| 757 | .hw_params = pcm512x_hw_params, | ||
| 758 | .set_fmt = pcm512x_set_fmt, | ||
| 759 | }; | ||
| 760 | |||
| 343 | static struct snd_soc_dai_driver pcm512x_dai = { | 761 | static struct snd_soc_dai_driver pcm512x_dai = { |
| 344 | .name = "pcm512x-hifi", | 762 | .name = "pcm512x-hifi", |
| 345 | .playback = { | 763 | .playback = { |
| 346 | .stream_name = "Playback", | 764 | .stream_name = "Playback", |
| 347 | .channels_min = 2, | 765 | .channels_min = 2, |
| 348 | .channels_max = 2, | 766 | .channels_max = 2, |
| 349 | .rates = SNDRV_PCM_RATE_8000_192000, | 767 | .rates = SNDRV_PCM_RATE_CONTINUOUS, |
| 768 | .rate_min = 8000, | ||
| 769 | .rate_max = 384000, | ||
| 350 | .formats = SNDRV_PCM_FMTBIT_S16_LE | | 770 | .formats = SNDRV_PCM_FMTBIT_S16_LE | |
| 351 | SNDRV_PCM_FMTBIT_S24_LE | | 771 | SNDRV_PCM_FMTBIT_S24_LE | |
| 352 | SNDRV_PCM_FMTBIT_S32_LE | 772 | SNDRV_PCM_FMTBIT_S32_LE |
| 353 | }, | 773 | }, |
| 774 | .ops = &pcm512x_dai_ops, | ||
| 354 | }; | 775 | }; |
| 355 | 776 | ||
| 356 | static struct snd_soc_codec_driver pcm512x_codec_driver = { | 777 | static struct snd_soc_codec_driver pcm512x_codec_driver = { |
| @@ -448,21 +869,9 @@ int pcm512x_probe(struct device *dev, struct regmap *regmap) | |||
| 448 | } | 869 | } |
| 449 | 870 | ||
| 450 | pcm512x->sclk = devm_clk_get(dev, NULL); | 871 | pcm512x->sclk = devm_clk_get(dev, NULL); |
| 451 | if (IS_ERR(pcm512x->sclk)) { | 872 | if (PTR_ERR(pcm512x->sclk) == -EPROBE_DEFER) |
| 452 | if (PTR_ERR(pcm512x->sclk) == -EPROBE_DEFER) | 873 | return -EPROBE_DEFER; |
| 453 | return -EPROBE_DEFER; | 874 | if (!IS_ERR(pcm512x->sclk)) { |
| 454 | |||
| 455 | dev_info(dev, "No SCLK, using BCLK: %ld\n", | ||
| 456 | PTR_ERR(pcm512x->sclk)); | ||
| 457 | |||
| 458 | /* Disable reporting of missing SCLK as an error */ | ||
| 459 | regmap_update_bits(regmap, PCM512x_ERROR_DETECT, | ||
| 460 | PCM512x_IDCH, PCM512x_IDCH); | ||
| 461 | |||
| 462 | /* Switch PLL input to BCLK */ | ||
| 463 | regmap_update_bits(regmap, PCM512x_PLL_REF, | ||
| 464 | PCM512x_SREF, PCM512x_SREF); | ||
| 465 | } else { | ||
| 466 | ret = clk_prepare_enable(pcm512x->sclk); | 875 | ret = clk_prepare_enable(pcm512x->sclk); |
| 467 | if (ret != 0) { | 876 | if (ret != 0) { |
| 468 | dev_err(dev, "Failed to enable SCLK: %d\n", ret); | 877 | dev_err(dev, "Failed to enable SCLK: %d\n", ret); |
diff --git a/sound/soc/codecs/pcm512x.h b/sound/soc/codecs/pcm512x.h index 28b3dfd302bc..fa538d5aabf2 100644 --- a/sound/soc/codecs/pcm512x.h +++ b/sound/soc/codecs/pcm512x.h | |||
| @@ -37,6 +37,8 @@ | |||
| 37 | #define PCM512x_DSP_GPIO_INPUT (PCM512x_PAGE_BASE(0) + 10) | 37 | #define PCM512x_DSP_GPIO_INPUT (PCM512x_PAGE_BASE(0) + 10) |
| 38 | #define PCM512x_MASTER_MODE (PCM512x_PAGE_BASE(0) + 12) | 38 | #define PCM512x_MASTER_MODE (PCM512x_PAGE_BASE(0) + 12) |
| 39 | #define PCM512x_PLL_REF (PCM512x_PAGE_BASE(0) + 13) | 39 | #define PCM512x_PLL_REF (PCM512x_PAGE_BASE(0) + 13) |
| 40 | #define PCM512x_DAC_REF (PCM512x_PAGE_BASE(0) + 14) | ||
| 41 | #define PCM512x_SYNCHRONIZE (PCM512x_PAGE_BASE(0) + 19) | ||
| 40 | #define PCM512x_PLL_COEFF_0 (PCM512x_PAGE_BASE(0) + 20) | 42 | #define PCM512x_PLL_COEFF_0 (PCM512x_PAGE_BASE(0) + 20) |
| 41 | #define PCM512x_PLL_COEFF_1 (PCM512x_PAGE_BASE(0) + 21) | 43 | #define PCM512x_PLL_COEFF_1 (PCM512x_PAGE_BASE(0) + 21) |
| 42 | #define PCM512x_PLL_COEFF_2 (PCM512x_PAGE_BASE(0) + 22) | 44 | #define PCM512x_PLL_COEFF_2 (PCM512x_PAGE_BASE(0) + 22) |
| @@ -119,8 +121,47 @@ | |||
| 119 | #define PCM512x_DEMP (1 << 4) | 121 | #define PCM512x_DEMP (1 << 4) |
| 120 | #define PCM512x_DEMP_SHIFT 4 | 122 | #define PCM512x_DEMP_SHIFT 4 |
| 121 | 123 | ||
| 124 | /* Page 0, Register 9 - BCK, LRCLK configuration */ | ||
| 125 | #define PCM512x_LRKO (1 << 0) | ||
| 126 | #define PCM512x_LRKO_SHIFT 0 | ||
| 127 | #define PCM512x_BCKO (1 << 4) | ||
| 128 | #define PCM512x_BCKO_SHIFT 4 | ||
| 129 | #define PCM512x_BCKP (1 << 5) | ||
| 130 | #define PCM512x_BCKP_SHIFT 5 | ||
| 131 | |||
| 132 | /* Page 0, Register 12 - Master mode BCK, LRCLK reset */ | ||
| 133 | #define PCM512x_RLRK (1 << 0) | ||
| 134 | #define PCM512x_RLRK_SHIFT 0 | ||
| 135 | #define PCM512x_RBCK (1 << 1) | ||
| 136 | #define PCM512x_RBCK_SHIFT 1 | ||
| 137 | |||
| 122 | /* Page 0, Register 13 - PLL reference */ | 138 | /* Page 0, Register 13 - PLL reference */ |
| 123 | #define PCM512x_SREF (1 << 4) | 139 | #define PCM512x_SREF (7 << 4) |
| 140 | #define PCM512x_SREF_SHIFT 4 | ||
| 141 | #define PCM512x_SREF_SCK (0 << 4) | ||
| 142 | #define PCM512x_SREF_BCK (1 << 4) | ||
| 143 | #define PCM512x_SREF_GPIO (3 << 4) | ||
| 144 | |||
| 145 | /* Page 0, Register 14 - DAC reference */ | ||
| 146 | #define PCM512x_SDAC (7 << 4) | ||
| 147 | #define PCM512x_SDAC_SHIFT 4 | ||
| 148 | #define PCM512x_SDAC_MCK (0 << 4) | ||
| 149 | #define PCM512x_SDAC_PLL (1 << 4) | ||
| 150 | #define PCM512x_SDAC_SCK (3 << 4) | ||
| 151 | #define PCM512x_SDAC_BCK (4 << 4) | ||
| 152 | |||
| 153 | /* Page 0, Register 19 - synchronize */ | ||
| 154 | #define PCM512x_RQSY (1 << 0) | ||
| 155 | #define PCM512x_RQSY_RESUME (0 << 0) | ||
| 156 | #define PCM512x_RQSY_HALT (1 << 0) | ||
| 157 | |||
| 158 | /* Page 0, Register 34 - fs speed mode */ | ||
| 159 | #define PCM512x_FSSP (3 << 0) | ||
| 160 | #define PCM512x_FSSP_SHIFT 0 | ||
| 161 | #define PCM512x_FSSP_48KHZ (0 << 0) | ||
| 162 | #define PCM512x_FSSP_96KHZ (1 << 0) | ||
| 163 | #define PCM512x_FSSP_192KHZ (2 << 0) | ||
| 164 | #define PCM512x_FSSP_384KHZ (3 << 0) | ||
| 124 | 165 | ||
| 125 | /* Page 0, Register 37 - Error detection */ | 166 | /* Page 0, Register 37 - Error detection */ |
| 126 | #define PCM512x_IPLK (1 << 0) | 167 | #define PCM512x_IPLK (1 << 0) |
| @@ -131,6 +172,20 @@ | |||
| 131 | #define PCM512x_IDBK (1 << 5) | 172 | #define PCM512x_IDBK (1 << 5) |
| 132 | #define PCM512x_IDFS (1 << 6) | 173 | #define PCM512x_IDFS (1 << 6) |
| 133 | 174 | ||
| 175 | /* Page 0, Register 40 - I2S configuration */ | ||
| 176 | #define PCM512x_ALEN (3 << 0) | ||
| 177 | #define PCM512x_ALEN_SHIFT 0 | ||
| 178 | #define PCM512x_ALEN_16 (0 << 0) | ||
| 179 | #define PCM512x_ALEN_20 (1 << 0) | ||
| 180 | #define PCM512x_ALEN_24 (2 << 0) | ||
| 181 | #define PCM512x_ALEN_32 (3 << 0) | ||
| 182 | #define PCM512x_AFMT (3 << 4) | ||
| 183 | #define PCM512x_AFMT_SHIFT 4 | ||
| 184 | #define PCM512x_AFMT_I2S (0 << 4) | ||
| 185 | #define PCM512x_AFMT_DSP (1 << 4) | ||
| 186 | #define PCM512x_AFMT_RTJ (2 << 4) | ||
| 187 | #define PCM512x_AFMT_LTJ (3 << 4) | ||
| 188 | |||
| 134 | /* Page 0, Register 42 - DAC routing */ | 189 | /* Page 0, Register 42 - DAC routing */ |
| 135 | #define PCM512x_AUPR_SHIFT 0 | 190 | #define PCM512x_AUPR_SHIFT 0 |
| 136 | #define PCM512x_AUPL_SHIFT 4 | 191 | #define PCM512x_AUPL_SHIFT 4 |
