| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * wm8961.c -- WM8961 ALSA SoC Audio driver |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Copyright 2009-10 Wolfson Microelectronics, plc |
|---|
| 5 | 6 | * |
|---|
| 6 | 7 | * Author: Mark Brown |
|---|
| 7 | | - * |
|---|
| 8 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 9 | | - * it under the terms of the GNU General Public License version 2 as |
|---|
| 10 | | - * published by the Free Software Foundation. |
|---|
| 11 | 8 | * |
|---|
| 12 | 9 | * Currently unimplemented features: |
|---|
| 13 | 10 | * - ALC |
|---|
| .. | .. |
|---|
| 195 | 192 | struct snd_kcontrol *kcontrol, int event) |
|---|
| 196 | 193 | { |
|---|
| 197 | 194 | struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); |
|---|
| 198 | | - u16 hp_reg = snd_soc_component_read32(component, WM8961_ANALOGUE_HP_0); |
|---|
| 199 | | - u16 cp_reg = snd_soc_component_read32(component, WM8961_CHARGE_PUMP_1); |
|---|
| 200 | | - u16 pwr_reg = snd_soc_component_read32(component, WM8961_PWR_MGMT_2); |
|---|
| 201 | | - u16 dcs_reg = snd_soc_component_read32(component, WM8961_DC_SERVO_1); |
|---|
| 195 | + u16 hp_reg = snd_soc_component_read(component, WM8961_ANALOGUE_HP_0); |
|---|
| 196 | + u16 cp_reg = snd_soc_component_read(component, WM8961_CHARGE_PUMP_1); |
|---|
| 197 | + u16 pwr_reg = snd_soc_component_read(component, WM8961_PWR_MGMT_2); |
|---|
| 198 | + u16 dcs_reg = snd_soc_component_read(component, WM8961_DC_SERVO_1); |
|---|
| 202 | 199 | int timeout = 500; |
|---|
| 203 | 200 | |
|---|
| 204 | 201 | if (event & SND_SOC_DAPM_POST_PMU) { |
|---|
| .. | .. |
|---|
| 232 | 229 | snd_soc_component_write(component, WM8961_DC_SERVO_1, dcs_reg); |
|---|
| 233 | 230 | do { |
|---|
| 234 | 231 | msleep(1); |
|---|
| 235 | | - dcs_reg = snd_soc_component_read32(component, WM8961_DC_SERVO_1); |
|---|
| 232 | + dcs_reg = snd_soc_component_read(component, WM8961_DC_SERVO_1); |
|---|
| 236 | 233 | } while (--timeout && |
|---|
| 237 | 234 | dcs_reg & (WM8961_DCS_TRIG_STARTUP_HPR | |
|---|
| 238 | 235 | WM8961_DCS_TRIG_STARTUP_HPL)); |
|---|
| .. | .. |
|---|
| 287 | 284 | struct snd_kcontrol *kcontrol, int event) |
|---|
| 288 | 285 | { |
|---|
| 289 | 286 | struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); |
|---|
| 290 | | - u16 pwr_reg = snd_soc_component_read32(component, WM8961_PWR_MGMT_2); |
|---|
| 291 | | - u16 spk_reg = snd_soc_component_read32(component, WM8961_CLASS_D_CONTROL_1); |
|---|
| 287 | + u16 pwr_reg = snd_soc_component_read(component, WM8961_PWR_MGMT_2); |
|---|
| 288 | + u16 spk_reg = snd_soc_component_read(component, WM8961_CLASS_D_CONTROL_1); |
|---|
| 292 | 289 | |
|---|
| 293 | 290 | if (event & SND_SOC_DAPM_POST_PMU) { |
|---|
| 294 | 291 | /* Enable the PGA */ |
|---|
| .. | .. |
|---|
| 524 | 521 | abs(wm8961_srate[best].rate - fs)) |
|---|
| 525 | 522 | best = i; |
|---|
| 526 | 523 | } |
|---|
| 527 | | - reg = snd_soc_component_read32(component, WM8961_ADDITIONAL_CONTROL_3); |
|---|
| 524 | + reg = snd_soc_component_read(component, WM8961_ADDITIONAL_CONTROL_3); |
|---|
| 528 | 525 | reg &= ~WM8961_SAMPLE_RATE_MASK; |
|---|
| 529 | 526 | reg |= wm8961_srate[best].val; |
|---|
| 530 | 527 | snd_soc_component_write(component, WM8961_ADDITIONAL_CONTROL_3, reg); |
|---|
| .. | .. |
|---|
| 557 | 554 | wm8961_clk_sys_ratio[i].ratio, wm8961->sysclk, fs, |
|---|
| 558 | 555 | wm8961->sysclk / fs); |
|---|
| 559 | 556 | |
|---|
| 560 | | - reg = snd_soc_component_read32(component, WM8961_CLOCKING_4); |
|---|
| 557 | + reg = snd_soc_component_read(component, WM8961_CLOCKING_4); |
|---|
| 561 | 558 | reg &= ~WM8961_CLK_SYS_RATE_MASK; |
|---|
| 562 | 559 | reg |= wm8961_clk_sys_ratio[i].val << WM8961_CLK_SYS_RATE_SHIFT; |
|---|
| 563 | 560 | snd_soc_component_write(component, WM8961_CLOCKING_4, reg); |
|---|
| 564 | 561 | |
|---|
| 565 | | - reg = snd_soc_component_read32(component, WM8961_AUDIO_INTERFACE_0); |
|---|
| 562 | + reg = snd_soc_component_read(component, WM8961_AUDIO_INTERFACE_0); |
|---|
| 566 | 563 | reg &= ~WM8961_WL_MASK; |
|---|
| 567 | 564 | switch (params_width(params)) { |
|---|
| 568 | 565 | case 16: |
|---|
| .. | .. |
|---|
| 582 | 579 | snd_soc_component_write(component, WM8961_AUDIO_INTERFACE_0, reg); |
|---|
| 583 | 580 | |
|---|
| 584 | 581 | /* Sloping stop-band filter is recommended for <= 24kHz */ |
|---|
| 585 | | - reg = snd_soc_component_read32(component, WM8961_ADC_DAC_CONTROL_2); |
|---|
| 582 | + reg = snd_soc_component_read(component, WM8961_ADC_DAC_CONTROL_2); |
|---|
| 586 | 583 | if (fs <= 24000) |
|---|
| 587 | 584 | reg |= WM8961_DACSLOPE; |
|---|
| 588 | 585 | else |
|---|
| .. | .. |
|---|
| 598 | 595 | { |
|---|
| 599 | 596 | struct snd_soc_component *component = dai->component; |
|---|
| 600 | 597 | struct wm8961_priv *wm8961 = snd_soc_component_get_drvdata(component); |
|---|
| 601 | | - u16 reg = snd_soc_component_read32(component, WM8961_CLOCKING1); |
|---|
| 598 | + u16 reg = snd_soc_component_read(component, WM8961_CLOCKING1); |
|---|
| 602 | 599 | |
|---|
| 603 | 600 | if (freq > 33000000) { |
|---|
| 604 | 601 | dev_err(component->dev, "MCLK must be <33MHz\n"); |
|---|
| .. | .. |
|---|
| 624 | 621 | static int wm8961_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) |
|---|
| 625 | 622 | { |
|---|
| 626 | 623 | struct snd_soc_component *component = dai->component; |
|---|
| 627 | | - u16 aif = snd_soc_component_read32(component, WM8961_AUDIO_INTERFACE_0); |
|---|
| 624 | + u16 aif = snd_soc_component_read(component, WM8961_AUDIO_INTERFACE_0); |
|---|
| 628 | 625 | |
|---|
| 629 | 626 | aif &= ~(WM8961_BCLKINV | WM8961_LRP | |
|---|
| 630 | 627 | WM8961_MS | WM8961_FORMAT_MASK); |
|---|
| .. | .. |
|---|
| 653 | 650 | |
|---|
| 654 | 651 | case SND_SOC_DAIFMT_DSP_B: |
|---|
| 655 | 652 | aif |= WM8961_LRP; |
|---|
| 656 | | - /* fall through */ |
|---|
| 653 | + fallthrough; |
|---|
| 657 | 654 | case SND_SOC_DAIFMT_DSP_A: |
|---|
| 658 | 655 | aif |= 3; |
|---|
| 659 | 656 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { |
|---|
| .. | .. |
|---|
| 691 | 688 | static int wm8961_set_tristate(struct snd_soc_dai *dai, int tristate) |
|---|
| 692 | 689 | { |
|---|
| 693 | 690 | struct snd_soc_component *component = dai->component; |
|---|
| 694 | | - u16 reg = snd_soc_component_read32(component, WM8961_ADDITIONAL_CONTROL_2); |
|---|
| 691 | + u16 reg = snd_soc_component_read(component, WM8961_ADDITIONAL_CONTROL_2); |
|---|
| 695 | 692 | |
|---|
| 696 | 693 | if (tristate) |
|---|
| 697 | 694 | reg |= WM8961_TRIS; |
|---|
| .. | .. |
|---|
| 701 | 698 | return snd_soc_component_write(component, WM8961_ADDITIONAL_CONTROL_2, reg); |
|---|
| 702 | 699 | } |
|---|
| 703 | 700 | |
|---|
| 704 | | -static int wm8961_digital_mute(struct snd_soc_dai *dai, int mute) |
|---|
| 701 | +static int wm8961_mute(struct snd_soc_dai *dai, int mute, int direction) |
|---|
| 705 | 702 | { |
|---|
| 706 | 703 | struct snd_soc_component *component = dai->component; |
|---|
| 707 | | - u16 reg = snd_soc_component_read32(component, WM8961_ADC_DAC_CONTROL_1); |
|---|
| 704 | + u16 reg = snd_soc_component_read(component, WM8961_ADC_DAC_CONTROL_1); |
|---|
| 708 | 705 | |
|---|
| 709 | 706 | if (mute) |
|---|
| 710 | 707 | reg |= WM8961_DACMU; |
|---|
| .. | .. |
|---|
| 723 | 720 | |
|---|
| 724 | 721 | switch (div_id) { |
|---|
| 725 | 722 | case WM8961_BCLK: |
|---|
| 726 | | - reg = snd_soc_component_read32(component, WM8961_CLOCKING2); |
|---|
| 723 | + reg = snd_soc_component_read(component, WM8961_CLOCKING2); |
|---|
| 727 | 724 | reg &= ~WM8961_BCLKDIV_MASK; |
|---|
| 728 | 725 | reg |= div; |
|---|
| 729 | 726 | snd_soc_component_write(component, WM8961_CLOCKING2, reg); |
|---|
| 730 | 727 | break; |
|---|
| 731 | 728 | |
|---|
| 732 | 729 | case WM8961_LRCLK: |
|---|
| 733 | | - reg = snd_soc_component_read32(component, WM8961_AUDIO_INTERFACE_2); |
|---|
| 730 | + reg = snd_soc_component_read(component, WM8961_AUDIO_INTERFACE_2); |
|---|
| 734 | 731 | reg &= ~WM8961_LRCLK_RATE_MASK; |
|---|
| 735 | 732 | reg |= div; |
|---|
| 736 | 733 | snd_soc_component_write(component, WM8961_AUDIO_INTERFACE_2, reg); |
|---|
| .. | .. |
|---|
| 760 | 757 | case SND_SOC_BIAS_PREPARE: |
|---|
| 761 | 758 | if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_STANDBY) { |
|---|
| 762 | 759 | /* Enable bias generation */ |
|---|
| 763 | | - reg = snd_soc_component_read32(component, WM8961_ANTI_POP); |
|---|
| 760 | + reg = snd_soc_component_read(component, WM8961_ANTI_POP); |
|---|
| 764 | 761 | reg |= WM8961_BUFIOEN | WM8961_BUFDCOPEN; |
|---|
| 765 | 762 | snd_soc_component_write(component, WM8961_ANTI_POP, reg); |
|---|
| 766 | 763 | |
|---|
| 767 | 764 | /* VMID=2*50k, VREF */ |
|---|
| 768 | | - reg = snd_soc_component_read32(component, WM8961_PWR_MGMT_1); |
|---|
| 765 | + reg = snd_soc_component_read(component, WM8961_PWR_MGMT_1); |
|---|
| 769 | 766 | reg &= ~WM8961_VMIDSEL_MASK; |
|---|
| 770 | 767 | reg |= (1 << WM8961_VMIDSEL_SHIFT) | WM8961_VREF; |
|---|
| 771 | 768 | snd_soc_component_write(component, WM8961_PWR_MGMT_1, reg); |
|---|
| .. | .. |
|---|
| 775 | 772 | case SND_SOC_BIAS_STANDBY: |
|---|
| 776 | 773 | if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_PREPARE) { |
|---|
| 777 | 774 | /* VREF off */ |
|---|
| 778 | | - reg = snd_soc_component_read32(component, WM8961_PWR_MGMT_1); |
|---|
| 775 | + reg = snd_soc_component_read(component, WM8961_PWR_MGMT_1); |
|---|
| 779 | 776 | reg &= ~WM8961_VREF; |
|---|
| 780 | 777 | snd_soc_component_write(component, WM8961_PWR_MGMT_1, reg); |
|---|
| 781 | 778 | |
|---|
| 782 | 779 | /* Bias generation off */ |
|---|
| 783 | | - reg = snd_soc_component_read32(component, WM8961_ANTI_POP); |
|---|
| 780 | + reg = snd_soc_component_read(component, WM8961_ANTI_POP); |
|---|
| 784 | 781 | reg &= ~(WM8961_BUFIOEN | WM8961_BUFDCOPEN); |
|---|
| 785 | 782 | snd_soc_component_write(component, WM8961_ANTI_POP, reg); |
|---|
| 786 | 783 | |
|---|
| 787 | 784 | /* VMID off */ |
|---|
| 788 | | - reg = snd_soc_component_read32(component, WM8961_PWR_MGMT_1); |
|---|
| 785 | + reg = snd_soc_component_read(component, WM8961_PWR_MGMT_1); |
|---|
| 789 | 786 | reg &= ~WM8961_VMIDSEL_MASK; |
|---|
| 790 | 787 | snd_soc_component_write(component, WM8961_PWR_MGMT_1, reg); |
|---|
| 791 | 788 | } |
|---|
| .. | .. |
|---|
| 809 | 806 | .hw_params = wm8961_hw_params, |
|---|
| 810 | 807 | .set_sysclk = wm8961_set_sysclk, |
|---|
| 811 | 808 | .set_fmt = wm8961_set_fmt, |
|---|
| 812 | | - .digital_mute = wm8961_digital_mute, |
|---|
| 809 | + .mute_stream = wm8961_mute, |
|---|
| 813 | 810 | .set_tristate = wm8961_set_tristate, |
|---|
| 814 | 811 | .set_clkdiv = wm8961_set_clkdiv, |
|---|
| 812 | + .no_capture_mute = 1, |
|---|
| 815 | 813 | }; |
|---|
| 816 | 814 | |
|---|
| 817 | 815 | static struct snd_soc_dai_driver wm8961_dai = { |
|---|
| .. | .. |
|---|
| 836 | 834 | u16 reg; |
|---|
| 837 | 835 | |
|---|
| 838 | 836 | /* Enable class W */ |
|---|
| 839 | | - reg = snd_soc_component_read32(component, WM8961_CHARGE_PUMP_B); |
|---|
| 837 | + reg = snd_soc_component_read(component, WM8961_CHARGE_PUMP_B); |
|---|
| 840 | 838 | reg |= WM8961_CP_DYN_PWR_MASK; |
|---|
| 841 | 839 | snd_soc_component_write(component, WM8961_CHARGE_PUMP_B, reg); |
|---|
| 842 | 840 | |
|---|
| 843 | 841 | /* Latch volume update bits (right channel only, we always |
|---|
| 844 | 842 | * write both out) and default ZC on. */ |
|---|
| 845 | | - reg = snd_soc_component_read32(component, WM8961_ROUT1_VOLUME); |
|---|
| 843 | + reg = snd_soc_component_read(component, WM8961_ROUT1_VOLUME); |
|---|
| 846 | 844 | snd_soc_component_write(component, WM8961_ROUT1_VOLUME, |
|---|
| 847 | 845 | reg | WM8961_LO1ZC | WM8961_OUT1VU); |
|---|
| 848 | 846 | snd_soc_component_write(component, WM8961_LOUT1_VOLUME, reg | WM8961_LO1ZC); |
|---|
| 849 | | - reg = snd_soc_component_read32(component, WM8961_ROUT2_VOLUME); |
|---|
| 847 | + reg = snd_soc_component_read(component, WM8961_ROUT2_VOLUME); |
|---|
| 850 | 848 | snd_soc_component_write(component, WM8961_ROUT2_VOLUME, |
|---|
| 851 | 849 | reg | WM8961_SPKRZC | WM8961_SPKVU); |
|---|
| 852 | 850 | snd_soc_component_write(component, WM8961_LOUT2_VOLUME, reg | WM8961_SPKLZC); |
|---|
| 853 | 851 | |
|---|
| 854 | | - reg = snd_soc_component_read32(component, WM8961_RIGHT_ADC_VOLUME); |
|---|
| 852 | + reg = snd_soc_component_read(component, WM8961_RIGHT_ADC_VOLUME); |
|---|
| 855 | 853 | snd_soc_component_write(component, WM8961_RIGHT_ADC_VOLUME, reg | WM8961_ADCVU); |
|---|
| 856 | | - reg = snd_soc_component_read32(component, WM8961_RIGHT_INPUT_VOLUME); |
|---|
| 854 | + reg = snd_soc_component_read(component, WM8961_RIGHT_INPUT_VOLUME); |
|---|
| 857 | 855 | snd_soc_component_write(component, WM8961_RIGHT_INPUT_VOLUME, reg | WM8961_IPVU); |
|---|
| 858 | 856 | |
|---|
| 859 | 857 | /* Use soft mute by default */ |
|---|
| 860 | | - reg = snd_soc_component_read32(component, WM8961_ADC_DAC_CONTROL_2); |
|---|
| 858 | + reg = snd_soc_component_read(component, WM8961_ADC_DAC_CONTROL_2); |
|---|
| 861 | 859 | reg |= WM8961_DACSMM; |
|---|
| 862 | 860 | snd_soc_component_write(component, WM8961_ADC_DAC_CONTROL_2, reg); |
|---|
| 863 | 861 | |
|---|
| 864 | 862 | /* Use automatic clocking mode by default; for now this is all |
|---|
| 865 | 863 | * we support. |
|---|
| 866 | 864 | */ |
|---|
| 867 | | - reg = snd_soc_component_read32(component, WM8961_CLOCKING_3); |
|---|
| 865 | + reg = snd_soc_component_read(component, WM8961_CLOCKING_3); |
|---|
| 868 | 866 | reg &= ~WM8961_MANUAL_MODE; |
|---|
| 869 | 867 | snd_soc_component_write(component, WM8961_CLOCKING_3, reg); |
|---|
| 870 | 868 | |
|---|