| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * linux/sound/soc/codecs/tlv320aic32x4.c |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 6 | 7 | * Author: Javier Martin <javier.martin@vista-silicon.com> |
|---|
| 7 | 8 | * |
|---|
| 8 | 9 | * Based on sound/soc/codecs/wm8974 and TI driver for kernel 2.6.27. |
|---|
| 9 | | - * |
|---|
| 10 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 11 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 12 | | - * the Free Software Foundation; either version 2 of the License, or |
|---|
| 13 | | - * (at your option) any later version. |
|---|
| 14 | | - * |
|---|
| 15 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 16 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 17 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 18 | | - * GNU General Public License for more details. |
|---|
| 19 | | - * |
|---|
| 20 | | - * You should have received a copy of the GNU General Public License |
|---|
| 21 | | - * along with this program; if not, write to the Free Software |
|---|
| 22 | | - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, |
|---|
| 23 | | - * MA 02110-1301, USA. |
|---|
| 24 | 10 | */ |
|---|
| 25 | 11 | |
|---|
| 26 | 12 | #include <linux/module.h> |
|---|
| .. | .. |
|---|
| 33 | 19 | #include <linux/cdev.h> |
|---|
| 34 | 20 | #include <linux/slab.h> |
|---|
| 35 | 21 | #include <linux/clk.h> |
|---|
| 22 | +#include <linux/of_clk.h> |
|---|
| 36 | 23 | #include <linux/regulator/consumer.h> |
|---|
| 37 | 24 | |
|---|
| 38 | 25 | #include <sound/tlv320aic32x4.h> |
|---|
| .. | .. |
|---|
| 46 | 33 | |
|---|
| 47 | 34 | #include "tlv320aic32x4.h" |
|---|
| 48 | 35 | |
|---|
| 49 | | -struct aic32x4_rate_divs { |
|---|
| 50 | | - u32 mclk; |
|---|
| 51 | | - u32 rate; |
|---|
| 52 | | - u8 p_val; |
|---|
| 53 | | - u8 pll_j; |
|---|
| 54 | | - u16 pll_d; |
|---|
| 55 | | - u16 dosr; |
|---|
| 56 | | - u8 ndac; |
|---|
| 57 | | - u8 mdac; |
|---|
| 58 | | - u8 aosr; |
|---|
| 59 | | - u8 nadc; |
|---|
| 60 | | - u8 madc; |
|---|
| 61 | | - u8 blck_N; |
|---|
| 62 | | -}; |
|---|
| 63 | | - |
|---|
| 64 | 36 | struct aic32x4_priv { |
|---|
| 65 | 37 | struct regmap *regmap; |
|---|
| 66 | | - u32 sysclk; |
|---|
| 67 | 38 | u32 power_cfg; |
|---|
| 68 | 39 | u32 micpga_routing; |
|---|
| 69 | 40 | bool swapdacs; |
|---|
| 70 | 41 | int rstn_gpio; |
|---|
| 71 | | - struct clk *mclk; |
|---|
| 42 | + const char *mclk_name; |
|---|
| 72 | 43 | |
|---|
| 73 | 44 | struct regulator *supply_ldo; |
|---|
| 74 | 45 | struct regulator *supply_iov; |
|---|
| .. | .. |
|---|
| 79 | 50 | struct device *dev; |
|---|
| 80 | 51 | }; |
|---|
| 81 | 52 | |
|---|
| 53 | +static int aic32x4_reset_adc(struct snd_soc_dapm_widget *w, |
|---|
| 54 | + struct snd_kcontrol *kcontrol, int event) |
|---|
| 55 | +{ |
|---|
| 56 | + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); |
|---|
| 57 | + u32 adc_reg; |
|---|
| 58 | + |
|---|
| 59 | + /* |
|---|
| 60 | + * Workaround: the datasheet does not mention a required programming |
|---|
| 61 | + * sequence but experiments show the ADC needs to be reset after each |
|---|
| 62 | + * capture to avoid audible artifacts. |
|---|
| 63 | + */ |
|---|
| 64 | + switch (event) { |
|---|
| 65 | + case SND_SOC_DAPM_POST_PMD: |
|---|
| 66 | + adc_reg = snd_soc_component_read(component, AIC32X4_ADCSETUP); |
|---|
| 67 | + snd_soc_component_write(component, AIC32X4_ADCSETUP, adc_reg | |
|---|
| 68 | + AIC32X4_LADC_EN | AIC32X4_RADC_EN); |
|---|
| 69 | + snd_soc_component_write(component, AIC32X4_ADCSETUP, adc_reg); |
|---|
| 70 | + break; |
|---|
| 71 | + } |
|---|
| 72 | + return 0; |
|---|
| 73 | +}; |
|---|
| 74 | + |
|---|
| 75 | +static int mic_bias_event(struct snd_soc_dapm_widget *w, |
|---|
| 76 | + struct snd_kcontrol *kcontrol, int event) |
|---|
| 77 | +{ |
|---|
| 78 | + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); |
|---|
| 79 | + |
|---|
| 80 | + switch (event) { |
|---|
| 81 | + case SND_SOC_DAPM_POST_PMU: |
|---|
| 82 | + /* Change Mic Bias Registor */ |
|---|
| 83 | + snd_soc_component_update_bits(component, AIC32X4_MICBIAS, |
|---|
| 84 | + AIC32x4_MICBIAS_MASK, |
|---|
| 85 | + AIC32X4_MICBIAS_LDOIN | |
|---|
| 86 | + AIC32X4_MICBIAS_2075V); |
|---|
| 87 | + printk(KERN_DEBUG "%s: Mic Bias will be turned ON\n", __func__); |
|---|
| 88 | + break; |
|---|
| 89 | + case SND_SOC_DAPM_PRE_PMD: |
|---|
| 90 | + snd_soc_component_update_bits(component, AIC32X4_MICBIAS, |
|---|
| 91 | + AIC32x4_MICBIAS_MASK, 0); |
|---|
| 92 | + printk(KERN_DEBUG "%s: Mic Bias will be turned OFF\n", |
|---|
| 93 | + __func__); |
|---|
| 94 | + break; |
|---|
| 95 | + } |
|---|
| 96 | + |
|---|
| 97 | + return 0; |
|---|
| 98 | +} |
|---|
| 99 | + |
|---|
| 100 | + |
|---|
| 82 | 101 | static int aic32x4_get_mfp1_gpio(struct snd_kcontrol *kcontrol, |
|---|
| 83 | 102 | struct snd_ctl_elem_value *ucontrol) |
|---|
| 84 | 103 | { |
|---|
| 85 | 104 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); |
|---|
| 86 | 105 | u8 val; |
|---|
| 87 | 106 | |
|---|
| 88 | | - val = snd_soc_component_read32(component, AIC32X4_DINCTL); |
|---|
| 107 | + val = snd_soc_component_read(component, AIC32X4_DINCTL); |
|---|
| 89 | 108 | |
|---|
| 90 | 109 | ucontrol->value.integer.value[0] = (val & 0x01); |
|---|
| 91 | 110 | |
|---|
| .. | .. |
|---|
| 99 | 118 | u8 val; |
|---|
| 100 | 119 | u8 gpio_check; |
|---|
| 101 | 120 | |
|---|
| 102 | | - val = snd_soc_component_read32(component, AIC32X4_DOUTCTL); |
|---|
| 121 | + val = snd_soc_component_read(component, AIC32X4_DOUTCTL); |
|---|
| 103 | 122 | gpio_check = (val & AIC32X4_MFP_GPIO_ENABLED); |
|---|
| 104 | 123 | if (gpio_check != AIC32X4_MFP_GPIO_ENABLED) { |
|---|
| 105 | 124 | printk(KERN_ERR "%s: MFP2 is not configure as a GPIO output\n", |
|---|
| .. | .. |
|---|
| 126 | 145 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); |
|---|
| 127 | 146 | u8 val; |
|---|
| 128 | 147 | |
|---|
| 129 | | - val = snd_soc_component_read32(component, AIC32X4_SCLKCTL); |
|---|
| 148 | + val = snd_soc_component_read(component, AIC32X4_SCLKCTL); |
|---|
| 130 | 149 | |
|---|
| 131 | 150 | ucontrol->value.integer.value[0] = (val & 0x01); |
|---|
| 132 | 151 | |
|---|
| .. | .. |
|---|
| 140 | 159 | u8 val; |
|---|
| 141 | 160 | u8 gpio_check; |
|---|
| 142 | 161 | |
|---|
| 143 | | - val = snd_soc_component_read32(component, AIC32X4_MISOCTL); |
|---|
| 162 | + val = snd_soc_component_read(component, AIC32X4_MISOCTL); |
|---|
| 144 | 163 | gpio_check = (val & AIC32X4_MFP_GPIO_ENABLED); |
|---|
| 145 | 164 | if (gpio_check != AIC32X4_MFP_GPIO_ENABLED) { |
|---|
| 146 | 165 | printk(KERN_ERR "%s: MFP4 is not configure as a GPIO output\n", |
|---|
| .. | .. |
|---|
| 167 | 186 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); |
|---|
| 168 | 187 | u8 val; |
|---|
| 169 | 188 | |
|---|
| 170 | | - val = snd_soc_component_read32(component, AIC32X4_GPIOCTL); |
|---|
| 189 | + val = snd_soc_component_read(component, AIC32X4_GPIOCTL); |
|---|
| 171 | 190 | ucontrol->value.integer.value[0] = ((val & 0x2) >> 1); |
|---|
| 172 | 191 | |
|---|
| 173 | 192 | return 0; |
|---|
| .. | .. |
|---|
| 180 | 199 | u8 val; |
|---|
| 181 | 200 | u8 gpio_check; |
|---|
| 182 | 201 | |
|---|
| 183 | | - val = snd_soc_component_read32(component, AIC32X4_GPIOCTL); |
|---|
| 202 | + val = snd_soc_component_read(component, AIC32X4_GPIOCTL); |
|---|
| 184 | 203 | gpio_check = (val & AIC32X4_MFP5_GPIO_OUTPUT); |
|---|
| 185 | 204 | if (gpio_check != AIC32X4_MFP5_GPIO_OUTPUT) { |
|---|
| 186 | 205 | printk(KERN_ERR "%s: MFP5 is not configure as a GPIO output\n", |
|---|
| .. | .. |
|---|
| 231 | 250 | /* -12dB min, 0.5dB steps */ |
|---|
| 232 | 251 | static DECLARE_TLV_DB_SCALE(tlv_adc_vol, -1200, 50, 0); |
|---|
| 233 | 252 | |
|---|
| 253 | +static const char * const lo_cm_text[] = { |
|---|
| 254 | + "Full Chip", "1.65V", |
|---|
| 255 | +}; |
|---|
| 256 | + |
|---|
| 257 | +static SOC_ENUM_SINGLE_DECL(lo_cm_enum, AIC32X4_CMMODE, 3, lo_cm_text); |
|---|
| 258 | + |
|---|
| 259 | +static const char * const ptm_text[] = { |
|---|
| 260 | + "P3", "P2", "P1", |
|---|
| 261 | +}; |
|---|
| 262 | + |
|---|
| 263 | +static SOC_ENUM_SINGLE_DECL(l_ptm_enum, AIC32X4_LPLAYBACK, 2, ptm_text); |
|---|
| 264 | +static SOC_ENUM_SINGLE_DECL(r_ptm_enum, AIC32X4_RPLAYBACK, 2, ptm_text); |
|---|
| 265 | + |
|---|
| 234 | 266 | static const struct snd_kcontrol_new aic32x4_snd_controls[] = { |
|---|
| 235 | 267 | SOC_DOUBLE_R_S_TLV("PCM Playback Volume", AIC32X4_LDACVOL, |
|---|
| 236 | 268 | AIC32X4_RDACVOL, 0, -0x7f, 0x30, 7, 0, tlv_pcm), |
|---|
| 269 | + SOC_ENUM("DAC Left Playback PowerTune Switch", l_ptm_enum), |
|---|
| 270 | + SOC_ENUM("DAC Right Playback PowerTune Switch", r_ptm_enum), |
|---|
| 237 | 271 | SOC_DOUBLE_R_S_TLV("HP Driver Gain Volume", AIC32X4_HPLGAIN, |
|---|
| 238 | 272 | AIC32X4_HPRGAIN, 0, -0x6, 0x1d, 5, 0, |
|---|
| 239 | 273 | tlv_driver_gain), |
|---|
| .. | .. |
|---|
| 244 | 278 | AIC32X4_HPRGAIN, 6, 0x01, 1), |
|---|
| 245 | 279 | SOC_DOUBLE_R("LO DAC Playback Switch", AIC32X4_LOLGAIN, |
|---|
| 246 | 280 | AIC32X4_LORGAIN, 6, 0x01, 1), |
|---|
| 281 | + SOC_ENUM("LO Playback Common Mode Switch", lo_cm_enum), |
|---|
| 247 | 282 | SOC_DOUBLE_R("Mic PGA Switch", AIC32X4_LMICPGAVOL, |
|---|
| 248 | 283 | AIC32X4_RMICPGAVOL, 7, 0x01, 1), |
|---|
| 249 | 284 | |
|---|
| .. | .. |
|---|
| 277 | 312 | 0, 0x1F, 0), |
|---|
| 278 | 313 | SOC_DOUBLE_R("AGC Signal Debounce", AIC32X4_LAGC7, AIC32X4_RAGC7, |
|---|
| 279 | 314 | 0, 0x0F, 0), |
|---|
| 280 | | -}; |
|---|
| 281 | | - |
|---|
| 282 | | -static const struct aic32x4_rate_divs aic32x4_divs[] = { |
|---|
| 283 | | - /* 8k rate */ |
|---|
| 284 | | - {12000000, 8000, 1, 7, 6800, 768, 5, 3, 128, 5, 18, 24}, |
|---|
| 285 | | - {24000000, 8000, 2, 7, 6800, 768, 15, 1, 64, 45, 4, 24}, |
|---|
| 286 | | - {25000000, 8000, 2, 7, 3728, 768, 15, 1, 64, 45, 4, 24}, |
|---|
| 287 | | - /* 11.025k rate */ |
|---|
| 288 | | - {12000000, 11025, 1, 7, 5264, 512, 8, 2, 128, 8, 8, 16}, |
|---|
| 289 | | - {24000000, 11025, 2, 7, 5264, 512, 16, 1, 64, 32, 4, 16}, |
|---|
| 290 | | - /* 16k rate */ |
|---|
| 291 | | - {12000000, 16000, 1, 7, 6800, 384, 5, 3, 128, 5, 9, 12}, |
|---|
| 292 | | - {24000000, 16000, 2, 7, 6800, 384, 15, 1, 64, 18, 5, 12}, |
|---|
| 293 | | - {25000000, 16000, 2, 7, 3728, 384, 15, 1, 64, 18, 5, 12}, |
|---|
| 294 | | - /* 22.05k rate */ |
|---|
| 295 | | - {12000000, 22050, 1, 7, 5264, 256, 4, 4, 128, 4, 8, 8}, |
|---|
| 296 | | - {24000000, 22050, 2, 7, 5264, 256, 16, 1, 64, 16, 4, 8}, |
|---|
| 297 | | - {25000000, 22050, 2, 7, 2253, 256, 16, 1, 64, 16, 4, 8}, |
|---|
| 298 | | - /* 32k rate */ |
|---|
| 299 | | - {12000000, 32000, 1, 7, 1680, 192, 2, 7, 64, 2, 21, 6}, |
|---|
| 300 | | - {24000000, 32000, 2, 7, 1680, 192, 7, 2, 64, 7, 6, 6}, |
|---|
| 301 | | - /* 44.1k rate */ |
|---|
| 302 | | - {12000000, 44100, 1, 7, 5264, 128, 2, 8, 128, 2, 8, 4}, |
|---|
| 303 | | - {24000000, 44100, 2, 7, 5264, 128, 8, 2, 64, 8, 4, 4}, |
|---|
| 304 | | - {25000000, 44100, 2, 7, 2253, 128, 8, 2, 64, 8, 4, 4}, |
|---|
| 305 | | - /* 48k rate */ |
|---|
| 306 | | - {12000000, 48000, 1, 8, 1920, 128, 2, 8, 128, 2, 8, 4}, |
|---|
| 307 | | - {24000000, 48000, 2, 8, 1920, 128, 8, 2, 64, 8, 4, 4}, |
|---|
| 308 | | - {25000000, 48000, 2, 7, 8643, 128, 8, 2, 64, 8, 4, 4}, |
|---|
| 309 | | - |
|---|
| 310 | | - /* 96k rate */ |
|---|
| 311 | | - {25000000, 96000, 2, 7, 8643, 64, 4, 4, 64, 4, 4, 1}, |
|---|
| 312 | 315 | }; |
|---|
| 313 | 316 | |
|---|
| 314 | 317 | static const struct snd_kcontrol_new hpl_output_mixer_controls[] = { |
|---|
| .. | .. |
|---|
| 365 | 368 | SOC_DAPM_ENUM("IN3_R L- Switch", in3r_lpga_n_enum), |
|---|
| 366 | 369 | }; |
|---|
| 367 | 370 | |
|---|
| 368 | | -/* Right mixer pins */ |
|---|
| 371 | +/* Right mixer pins */ |
|---|
| 369 | 372 | static SOC_ENUM_SINGLE_DECL(in1r_rpga_p_enum, AIC32X4_RMICPGAPIN, 6, resistor_text); |
|---|
| 370 | 373 | static SOC_ENUM_SINGLE_DECL(in2r_rpga_p_enum, AIC32X4_RMICPGAPIN, 4, resistor_text); |
|---|
| 371 | 374 | static SOC_ENUM_SINGLE_DECL(in3r_rpga_p_enum, AIC32X4_RMICPGAPIN, 2, resistor_text); |
|---|
| .. | .. |
|---|
| 450 | 453 | SND_SOC_DAPM_MUX("IN3_R to Left Mixer Negative Resistor", SND_SOC_NOPM, 0, 0, |
|---|
| 451 | 454 | in3r_to_lmixer_controls), |
|---|
| 452 | 455 | |
|---|
| 453 | | - SND_SOC_DAPM_MICBIAS("Mic Bias", AIC32X4_MICBIAS, 6, 0), |
|---|
| 456 | + SND_SOC_DAPM_SUPPLY("Mic Bias", AIC32X4_MICBIAS, 6, 0, mic_bias_event, |
|---|
| 457 | + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), |
|---|
| 458 | + |
|---|
| 459 | + SND_SOC_DAPM_POST("ADC Reset", aic32x4_reset_adc), |
|---|
| 454 | 460 | |
|---|
| 455 | 461 | SND_SOC_DAPM_OUTPUT("HPL"), |
|---|
| 456 | 462 | SND_SOC_DAPM_OUTPUT("HPR"), |
|---|
| .. | .. |
|---|
| 567 | 573 | static const struct regmap_range_cfg aic32x4_regmap_pages[] = { |
|---|
| 568 | 574 | { |
|---|
| 569 | 575 | .selector_reg = 0, |
|---|
| 570 | | - .selector_mask = 0xff, |
|---|
| 576 | + .selector_mask = 0xff, |
|---|
| 571 | 577 | .window_start = 0, |
|---|
| 572 | 578 | .window_len = 128, |
|---|
| 573 | 579 | .range_min = 0, |
|---|
| 574 | | - .range_max = AIC32X4_RMICPGAVOL, |
|---|
| 580 | + .range_max = AIC32X4_REFPOWERUP, |
|---|
| 575 | 581 | }, |
|---|
| 576 | 582 | }; |
|---|
| 577 | 583 | |
|---|
| 578 | 584 | const struct regmap_config aic32x4_regmap_config = { |
|---|
| 579 | | - .max_register = AIC32X4_RMICPGAVOL, |
|---|
| 585 | + .max_register = AIC32X4_REFPOWERUP, |
|---|
| 580 | 586 | .ranges = aic32x4_regmap_pages, |
|---|
| 581 | 587 | .num_ranges = ARRAY_SIZE(aic32x4_regmap_pages), |
|---|
| 582 | 588 | }; |
|---|
| 583 | 589 | EXPORT_SYMBOL(aic32x4_regmap_config); |
|---|
| 584 | 590 | |
|---|
| 585 | | -static inline int aic32x4_get_divs(int mclk, int rate) |
|---|
| 586 | | -{ |
|---|
| 587 | | - int i; |
|---|
| 588 | | - |
|---|
| 589 | | - for (i = 0; i < ARRAY_SIZE(aic32x4_divs); i++) { |
|---|
| 590 | | - if ((aic32x4_divs[i].rate == rate) |
|---|
| 591 | | - && (aic32x4_divs[i].mclk == mclk)) { |
|---|
| 592 | | - return i; |
|---|
| 593 | | - } |
|---|
| 594 | | - } |
|---|
| 595 | | - printk(KERN_ERR "aic32x4: master clock and sample rate is not supported\n"); |
|---|
| 596 | | - return -EINVAL; |
|---|
| 597 | | -} |
|---|
| 598 | | - |
|---|
| 599 | 591 | static int aic32x4_set_dai_sysclk(struct snd_soc_dai *codec_dai, |
|---|
| 600 | 592 | int clk_id, unsigned int freq, int dir) |
|---|
| 601 | 593 | { |
|---|
| 602 | 594 | struct snd_soc_component *component = codec_dai->component; |
|---|
| 603 | | - struct aic32x4_priv *aic32x4 = snd_soc_component_get_drvdata(component); |
|---|
| 595 | + struct clk *mclk; |
|---|
| 596 | + struct clk *pll; |
|---|
| 604 | 597 | |
|---|
| 605 | | - switch (freq) { |
|---|
| 606 | | - case 12000000: |
|---|
| 607 | | - case 24000000: |
|---|
| 608 | | - case 25000000: |
|---|
| 609 | | - aic32x4->sysclk = freq; |
|---|
| 610 | | - return 0; |
|---|
| 611 | | - } |
|---|
| 612 | | - printk(KERN_ERR "aic32x4: invalid frequency to set DAI system clock\n"); |
|---|
| 613 | | - return -EINVAL; |
|---|
| 598 | + pll = devm_clk_get(component->dev, "pll"); |
|---|
| 599 | + if (IS_ERR(pll)) |
|---|
| 600 | + return PTR_ERR(pll); |
|---|
| 601 | + |
|---|
| 602 | + mclk = clk_get_parent(pll); |
|---|
| 603 | + |
|---|
| 604 | + return clk_set_rate(mclk, freq); |
|---|
| 614 | 605 | } |
|---|
| 615 | 606 | |
|---|
| 616 | 607 | static int aic32x4_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) |
|---|
| .. | .. |
|---|
| 660 | 651 | } |
|---|
| 661 | 652 | |
|---|
| 662 | 653 | snd_soc_component_update_bits(component, AIC32X4_IFACE1, |
|---|
| 663 | | - AIC32X4_IFACE1_DATATYPE_MASK | |
|---|
| 664 | | - AIC32X4_IFACE1_MASTER_MASK, iface_reg_1); |
|---|
| 654 | + AIC32X4_IFACE1_DATATYPE_MASK | |
|---|
| 655 | + AIC32X4_IFACE1_MASTER_MASK, iface_reg_1); |
|---|
| 665 | 656 | snd_soc_component_update_bits(component, AIC32X4_IFACE2, |
|---|
| 666 | | - AIC32X4_DATA_OFFSET_MASK, iface_reg_2); |
|---|
| 657 | + AIC32X4_DATA_OFFSET_MASK, iface_reg_2); |
|---|
| 667 | 658 | snd_soc_component_update_bits(component, AIC32X4_IFACE3, |
|---|
| 668 | | - AIC32X4_BCLKINV_MASK, iface_reg_3); |
|---|
| 659 | + AIC32X4_BCLKINV_MASK, iface_reg_3); |
|---|
| 669 | 660 | |
|---|
| 670 | 661 | return 0; |
|---|
| 671 | 662 | } |
|---|
| 672 | 663 | |
|---|
| 664 | +static int aic32x4_set_aosr(struct snd_soc_component *component, u8 aosr) |
|---|
| 665 | +{ |
|---|
| 666 | + return snd_soc_component_write(component, AIC32X4_AOSR, aosr); |
|---|
| 667 | +} |
|---|
| 668 | + |
|---|
| 669 | +static int aic32x4_set_dosr(struct snd_soc_component *component, u16 dosr) |
|---|
| 670 | +{ |
|---|
| 671 | + snd_soc_component_write(component, AIC32X4_DOSRMSB, dosr >> 8); |
|---|
| 672 | + snd_soc_component_write(component, AIC32X4_DOSRLSB, |
|---|
| 673 | + (dosr & 0xff)); |
|---|
| 674 | + |
|---|
| 675 | + return 0; |
|---|
| 676 | +} |
|---|
| 677 | + |
|---|
| 678 | +static int aic32x4_set_processing_blocks(struct snd_soc_component *component, |
|---|
| 679 | + u8 r_block, u8 p_block) |
|---|
| 680 | +{ |
|---|
| 681 | + if (r_block > 18 || p_block > 25) |
|---|
| 682 | + return -EINVAL; |
|---|
| 683 | + |
|---|
| 684 | + snd_soc_component_write(component, AIC32X4_ADCSPB, r_block); |
|---|
| 685 | + snd_soc_component_write(component, AIC32X4_DACSPB, p_block); |
|---|
| 686 | + |
|---|
| 687 | + return 0; |
|---|
| 688 | +} |
|---|
| 689 | + |
|---|
| 690 | +static int aic32x4_setup_clocks(struct snd_soc_component *component, |
|---|
| 691 | + unsigned int sample_rate, unsigned int channels, |
|---|
| 692 | + unsigned int bit_depth) |
|---|
| 693 | +{ |
|---|
| 694 | + u8 aosr; |
|---|
| 695 | + u16 dosr; |
|---|
| 696 | + u8 adc_resource_class, dac_resource_class; |
|---|
| 697 | + u8 madc, nadc, mdac, ndac, max_nadc, min_mdac, max_ndac; |
|---|
| 698 | + u8 dosr_increment; |
|---|
| 699 | + u16 max_dosr, min_dosr; |
|---|
| 700 | + unsigned long adc_clock_rate, dac_clock_rate; |
|---|
| 701 | + int ret; |
|---|
| 702 | + |
|---|
| 703 | + struct clk_bulk_data clocks[] = { |
|---|
| 704 | + { .id = "pll" }, |
|---|
| 705 | + { .id = "nadc" }, |
|---|
| 706 | + { .id = "madc" }, |
|---|
| 707 | + { .id = "ndac" }, |
|---|
| 708 | + { .id = "mdac" }, |
|---|
| 709 | + { .id = "bdiv" }, |
|---|
| 710 | + }; |
|---|
| 711 | + ret = devm_clk_bulk_get(component->dev, ARRAY_SIZE(clocks), clocks); |
|---|
| 712 | + if (ret) |
|---|
| 713 | + return ret; |
|---|
| 714 | + |
|---|
| 715 | + if (sample_rate <= 48000) { |
|---|
| 716 | + aosr = 128; |
|---|
| 717 | + adc_resource_class = 6; |
|---|
| 718 | + dac_resource_class = 8; |
|---|
| 719 | + dosr_increment = 8; |
|---|
| 720 | + aic32x4_set_processing_blocks(component, 1, 1); |
|---|
| 721 | + } else if (sample_rate <= 96000) { |
|---|
| 722 | + aosr = 64; |
|---|
| 723 | + adc_resource_class = 6; |
|---|
| 724 | + dac_resource_class = 8; |
|---|
| 725 | + dosr_increment = 4; |
|---|
| 726 | + aic32x4_set_processing_blocks(component, 1, 9); |
|---|
| 727 | + } else if (sample_rate == 192000) { |
|---|
| 728 | + aosr = 32; |
|---|
| 729 | + adc_resource_class = 3; |
|---|
| 730 | + dac_resource_class = 4; |
|---|
| 731 | + dosr_increment = 2; |
|---|
| 732 | + aic32x4_set_processing_blocks(component, 13, 19); |
|---|
| 733 | + } else { |
|---|
| 734 | + dev_err(component->dev, "Sampling rate not supported\n"); |
|---|
| 735 | + return -EINVAL; |
|---|
| 736 | + } |
|---|
| 737 | + |
|---|
| 738 | + madc = DIV_ROUND_UP((32 * adc_resource_class), aosr); |
|---|
| 739 | + max_dosr = (AIC32X4_MAX_DOSR_FREQ / sample_rate / dosr_increment) * |
|---|
| 740 | + dosr_increment; |
|---|
| 741 | + min_dosr = (AIC32X4_MIN_DOSR_FREQ / sample_rate / dosr_increment) * |
|---|
| 742 | + dosr_increment; |
|---|
| 743 | + max_nadc = AIC32X4_MAX_CODEC_CLKIN_FREQ / (madc * aosr * sample_rate); |
|---|
| 744 | + |
|---|
| 745 | + for (nadc = max_nadc; nadc > 0; --nadc) { |
|---|
| 746 | + adc_clock_rate = nadc * madc * aosr * sample_rate; |
|---|
| 747 | + for (dosr = max_dosr; dosr >= min_dosr; |
|---|
| 748 | + dosr -= dosr_increment) { |
|---|
| 749 | + min_mdac = DIV_ROUND_UP((32 * dac_resource_class), dosr); |
|---|
| 750 | + max_ndac = AIC32X4_MAX_CODEC_CLKIN_FREQ / |
|---|
| 751 | + (min_mdac * dosr * sample_rate); |
|---|
| 752 | + for (mdac = min_mdac; mdac <= 128; ++mdac) { |
|---|
| 753 | + for (ndac = max_ndac; ndac > 0; --ndac) { |
|---|
| 754 | + dac_clock_rate = ndac * mdac * dosr * |
|---|
| 755 | + sample_rate; |
|---|
| 756 | + if (dac_clock_rate == adc_clock_rate) { |
|---|
| 757 | + if (clk_round_rate(clocks[0].clk, dac_clock_rate) == 0) |
|---|
| 758 | + continue; |
|---|
| 759 | + |
|---|
| 760 | + clk_set_rate(clocks[0].clk, |
|---|
| 761 | + dac_clock_rate); |
|---|
| 762 | + |
|---|
| 763 | + clk_set_rate(clocks[1].clk, |
|---|
| 764 | + sample_rate * aosr * |
|---|
| 765 | + madc); |
|---|
| 766 | + clk_set_rate(clocks[2].clk, |
|---|
| 767 | + sample_rate * aosr); |
|---|
| 768 | + aic32x4_set_aosr(component, |
|---|
| 769 | + aosr); |
|---|
| 770 | + |
|---|
| 771 | + clk_set_rate(clocks[3].clk, |
|---|
| 772 | + sample_rate * dosr * |
|---|
| 773 | + mdac); |
|---|
| 774 | + clk_set_rate(clocks[4].clk, |
|---|
| 775 | + sample_rate * dosr); |
|---|
| 776 | + aic32x4_set_dosr(component, |
|---|
| 777 | + dosr); |
|---|
| 778 | + |
|---|
| 779 | + clk_set_rate(clocks[5].clk, |
|---|
| 780 | + sample_rate * channels * |
|---|
| 781 | + bit_depth); |
|---|
| 782 | + |
|---|
| 783 | + return 0; |
|---|
| 784 | + } |
|---|
| 785 | + } |
|---|
| 786 | + } |
|---|
| 787 | + } |
|---|
| 788 | + } |
|---|
| 789 | + |
|---|
| 790 | + dev_err(component->dev, |
|---|
| 791 | + "Could not set clocks to support sample rate.\n"); |
|---|
| 792 | + return -EINVAL; |
|---|
| 793 | +} |
|---|
| 794 | + |
|---|
| 673 | 795 | static int aic32x4_hw_params(struct snd_pcm_substream *substream, |
|---|
| 674 | | - struct snd_pcm_hw_params *params, |
|---|
| 675 | | - struct snd_soc_dai *dai) |
|---|
| 796 | + struct snd_pcm_hw_params *params, |
|---|
| 797 | + struct snd_soc_dai *dai) |
|---|
| 676 | 798 | { |
|---|
| 677 | 799 | struct snd_soc_component *component = dai->component; |
|---|
| 678 | 800 | struct aic32x4_priv *aic32x4 = snd_soc_component_get_drvdata(component); |
|---|
| 679 | 801 | u8 iface1_reg = 0; |
|---|
| 680 | 802 | u8 dacsetup_reg = 0; |
|---|
| 681 | | - int i; |
|---|
| 682 | 803 | |
|---|
| 683 | | - i = aic32x4_get_divs(aic32x4->sysclk, params_rate(params)); |
|---|
| 684 | | - if (i < 0) { |
|---|
| 685 | | - printk(KERN_ERR "aic32x4: sampling rate not supported\n"); |
|---|
| 686 | | - return i; |
|---|
| 687 | | - } |
|---|
| 804 | + aic32x4_setup_clocks(component, params_rate(params), |
|---|
| 805 | + params_channels(params), |
|---|
| 806 | + params_physical_width(params)); |
|---|
| 688 | 807 | |
|---|
| 689 | | - /* MCLK as PLL_CLKIN */ |
|---|
| 690 | | - snd_soc_component_update_bits(component, AIC32X4_CLKMUX, AIC32X4_PLL_CLKIN_MASK, |
|---|
| 691 | | - AIC32X4_PLL_CLKIN_MCLK << AIC32X4_PLL_CLKIN_SHIFT); |
|---|
| 692 | | - /* PLL as CODEC_CLKIN */ |
|---|
| 693 | | - snd_soc_component_update_bits(component, AIC32X4_CLKMUX, AIC32X4_CODEC_CLKIN_MASK, |
|---|
| 694 | | - AIC32X4_CODEC_CLKIN_PLL << AIC32X4_CODEC_CLKIN_SHIFT); |
|---|
| 695 | | - /* DAC_MOD_CLK as BDIV_CLKIN */ |
|---|
| 696 | | - snd_soc_component_update_bits(component, AIC32X4_IFACE3, AIC32X4_BDIVCLK_MASK, |
|---|
| 697 | | - AIC32X4_DACMOD2BCLK << AIC32X4_BDIVCLK_SHIFT); |
|---|
| 698 | | - |
|---|
| 699 | | - /* We will fix R value to 1 and will make P & J=K.D as variable */ |
|---|
| 700 | | - snd_soc_component_update_bits(component, AIC32X4_PLLPR, AIC32X4_PLL_R_MASK, 0x01); |
|---|
| 701 | | - |
|---|
| 702 | | - /* PLL P value */ |
|---|
| 703 | | - snd_soc_component_update_bits(component, AIC32X4_PLLPR, AIC32X4_PLL_P_MASK, |
|---|
| 704 | | - aic32x4_divs[i].p_val << AIC32X4_PLL_P_SHIFT); |
|---|
| 705 | | - |
|---|
| 706 | | - /* PLL J value */ |
|---|
| 707 | | - snd_soc_component_write(component, AIC32X4_PLLJ, aic32x4_divs[i].pll_j); |
|---|
| 708 | | - |
|---|
| 709 | | - /* PLL D value */ |
|---|
| 710 | | - snd_soc_component_write(component, AIC32X4_PLLDMSB, (aic32x4_divs[i].pll_d >> 8)); |
|---|
| 711 | | - snd_soc_component_write(component, AIC32X4_PLLDLSB, (aic32x4_divs[i].pll_d & 0xff)); |
|---|
| 712 | | - |
|---|
| 713 | | - /* NDAC divider value */ |
|---|
| 714 | | - snd_soc_component_update_bits(component, AIC32X4_NDAC, |
|---|
| 715 | | - AIC32X4_NDAC_MASK, aic32x4_divs[i].ndac); |
|---|
| 716 | | - |
|---|
| 717 | | - /* MDAC divider value */ |
|---|
| 718 | | - snd_soc_component_update_bits(component, AIC32X4_MDAC, |
|---|
| 719 | | - AIC32X4_MDAC_MASK, aic32x4_divs[i].mdac); |
|---|
| 720 | | - |
|---|
| 721 | | - /* DOSR MSB & LSB values */ |
|---|
| 722 | | - snd_soc_component_write(component, AIC32X4_DOSRMSB, aic32x4_divs[i].dosr >> 8); |
|---|
| 723 | | - snd_soc_component_write(component, AIC32X4_DOSRLSB, (aic32x4_divs[i].dosr & 0xff)); |
|---|
| 724 | | - |
|---|
| 725 | | - /* NADC divider value */ |
|---|
| 726 | | - snd_soc_component_update_bits(component, AIC32X4_NADC, |
|---|
| 727 | | - AIC32X4_NADC_MASK, aic32x4_divs[i].nadc); |
|---|
| 728 | | - |
|---|
| 729 | | - /* MADC divider value */ |
|---|
| 730 | | - snd_soc_component_update_bits(component, AIC32X4_MADC, |
|---|
| 731 | | - AIC32X4_MADC_MASK, aic32x4_divs[i].madc); |
|---|
| 732 | | - |
|---|
| 733 | | - /* AOSR value */ |
|---|
| 734 | | - snd_soc_component_write(component, AIC32X4_AOSR, aic32x4_divs[i].aosr); |
|---|
| 735 | | - |
|---|
| 736 | | - /* BCLK N divider */ |
|---|
| 737 | | - snd_soc_component_update_bits(component, AIC32X4_BCLKN, |
|---|
| 738 | | - AIC32X4_BCLK_MASK, aic32x4_divs[i].blck_N); |
|---|
| 739 | | - |
|---|
| 740 | | - switch (params_width(params)) { |
|---|
| 808 | + switch (params_physical_width(params)) { |
|---|
| 741 | 809 | case 16: |
|---|
| 742 | 810 | iface1_reg |= (AIC32X4_WORD_LEN_16BITS << |
|---|
| 743 | | - AIC32X4_IFACE1_DATALEN_SHIFT); |
|---|
| 811 | + AIC32X4_IFACE1_DATALEN_SHIFT); |
|---|
| 744 | 812 | break; |
|---|
| 745 | 813 | case 20: |
|---|
| 746 | 814 | iface1_reg |= (AIC32X4_WORD_LEN_20BITS << |
|---|
| 747 | | - AIC32X4_IFACE1_DATALEN_SHIFT); |
|---|
| 815 | + AIC32X4_IFACE1_DATALEN_SHIFT); |
|---|
| 748 | 816 | break; |
|---|
| 749 | 817 | case 24: |
|---|
| 750 | 818 | iface1_reg |= (AIC32X4_WORD_LEN_24BITS << |
|---|
| 751 | | - AIC32X4_IFACE1_DATALEN_SHIFT); |
|---|
| 819 | + AIC32X4_IFACE1_DATALEN_SHIFT); |
|---|
| 752 | 820 | break; |
|---|
| 753 | 821 | case 32: |
|---|
| 754 | 822 | iface1_reg |= (AIC32X4_WORD_LEN_32BITS << |
|---|
| 755 | | - AIC32X4_IFACE1_DATALEN_SHIFT); |
|---|
| 823 | + AIC32X4_IFACE1_DATALEN_SHIFT); |
|---|
| 756 | 824 | break; |
|---|
| 757 | 825 | } |
|---|
| 758 | 826 | snd_soc_component_update_bits(component, AIC32X4_IFACE1, |
|---|
| 759 | | - AIC32X4_IFACE1_DATALEN_MASK, iface1_reg); |
|---|
| 827 | + AIC32X4_IFACE1_DATALEN_MASK, iface1_reg); |
|---|
| 760 | 828 | |
|---|
| 761 | 829 | if (params_channels(params) == 1) { |
|---|
| 762 | 830 | dacsetup_reg = AIC32X4_RDAC2LCHN | AIC32X4_LDAC2LCHN; |
|---|
| .. | .. |
|---|
| 767 | 835 | dacsetup_reg = AIC32X4_LDAC2LCHN | AIC32X4_RDAC2RCHN; |
|---|
| 768 | 836 | } |
|---|
| 769 | 837 | snd_soc_component_update_bits(component, AIC32X4_DACSETUP, |
|---|
| 770 | | - AIC32X4_DAC_CHAN_MASK, dacsetup_reg); |
|---|
| 838 | + AIC32X4_DAC_CHAN_MASK, dacsetup_reg); |
|---|
| 771 | 839 | |
|---|
| 772 | 840 | return 0; |
|---|
| 773 | 841 | } |
|---|
| 774 | 842 | |
|---|
| 775 | | -static int aic32x4_mute(struct snd_soc_dai *dai, int mute) |
|---|
| 843 | +static int aic32x4_mute(struct snd_soc_dai *dai, int mute, int direction) |
|---|
| 776 | 844 | { |
|---|
| 777 | 845 | struct snd_soc_component *component = dai->component; |
|---|
| 778 | 846 | |
|---|
| 779 | 847 | snd_soc_component_update_bits(component, AIC32X4_DACMUTE, |
|---|
| 780 | | - AIC32X4_MUTEON, mute ? AIC32X4_MUTEON : 0); |
|---|
| 848 | + AIC32X4_MUTEON, mute ? AIC32X4_MUTEON : 0); |
|---|
| 781 | 849 | |
|---|
| 782 | 850 | return 0; |
|---|
| 783 | 851 | } |
|---|
| .. | .. |
|---|
| 785 | 853 | static int aic32x4_set_bias_level(struct snd_soc_component *component, |
|---|
| 786 | 854 | enum snd_soc_bias_level level) |
|---|
| 787 | 855 | { |
|---|
| 788 | | - struct aic32x4_priv *aic32x4 = snd_soc_component_get_drvdata(component); |
|---|
| 789 | 856 | int ret; |
|---|
| 857 | + |
|---|
| 858 | + struct clk_bulk_data clocks[] = { |
|---|
| 859 | + { .id = "madc" }, |
|---|
| 860 | + { .id = "mdac" }, |
|---|
| 861 | + { .id = "bdiv" }, |
|---|
| 862 | + }; |
|---|
| 863 | + |
|---|
| 864 | + ret = devm_clk_bulk_get(component->dev, ARRAY_SIZE(clocks), clocks); |
|---|
| 865 | + if (ret) |
|---|
| 866 | + return ret; |
|---|
| 790 | 867 | |
|---|
| 791 | 868 | switch (level) { |
|---|
| 792 | 869 | case SND_SOC_BIAS_ON: |
|---|
| 793 | | - /* Switch on master clock */ |
|---|
| 794 | | - ret = clk_prepare_enable(aic32x4->mclk); |
|---|
| 870 | + ret = clk_bulk_prepare_enable(ARRAY_SIZE(clocks), clocks); |
|---|
| 795 | 871 | if (ret) { |
|---|
| 796 | | - dev_err(component->dev, "Failed to enable master clock\n"); |
|---|
| 872 | + dev_err(component->dev, "Failed to enable clocks\n"); |
|---|
| 797 | 873 | return ret; |
|---|
| 798 | 874 | } |
|---|
| 799 | | - |
|---|
| 800 | | - /* Switch on PLL */ |
|---|
| 801 | | - snd_soc_component_update_bits(component, AIC32X4_PLLPR, |
|---|
| 802 | | - AIC32X4_PLLEN, AIC32X4_PLLEN); |
|---|
| 803 | | - |
|---|
| 804 | | - /* Switch on NDAC Divider */ |
|---|
| 805 | | - snd_soc_component_update_bits(component, AIC32X4_NDAC, |
|---|
| 806 | | - AIC32X4_NDACEN, AIC32X4_NDACEN); |
|---|
| 807 | | - |
|---|
| 808 | | - /* Switch on MDAC Divider */ |
|---|
| 809 | | - snd_soc_component_update_bits(component, AIC32X4_MDAC, |
|---|
| 810 | | - AIC32X4_MDACEN, AIC32X4_MDACEN); |
|---|
| 811 | | - |
|---|
| 812 | | - /* Switch on NADC Divider */ |
|---|
| 813 | | - snd_soc_component_update_bits(component, AIC32X4_NADC, |
|---|
| 814 | | - AIC32X4_NADCEN, AIC32X4_NADCEN); |
|---|
| 815 | | - |
|---|
| 816 | | - /* Switch on MADC Divider */ |
|---|
| 817 | | - snd_soc_component_update_bits(component, AIC32X4_MADC, |
|---|
| 818 | | - AIC32X4_MADCEN, AIC32X4_MADCEN); |
|---|
| 819 | | - |
|---|
| 820 | | - /* Switch on BCLK_N Divider */ |
|---|
| 821 | | - snd_soc_component_update_bits(component, AIC32X4_BCLKN, |
|---|
| 822 | | - AIC32X4_BCLKEN, AIC32X4_BCLKEN); |
|---|
| 823 | 875 | break; |
|---|
| 824 | 876 | case SND_SOC_BIAS_PREPARE: |
|---|
| 825 | 877 | break; |
|---|
| .. | .. |
|---|
| 828 | 880 | if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) |
|---|
| 829 | 881 | break; |
|---|
| 830 | 882 | |
|---|
| 831 | | - /* Switch off BCLK_N Divider */ |
|---|
| 832 | | - snd_soc_component_update_bits(component, AIC32X4_BCLKN, |
|---|
| 833 | | - AIC32X4_BCLKEN, 0); |
|---|
| 834 | | - |
|---|
| 835 | | - /* Switch off MADC Divider */ |
|---|
| 836 | | - snd_soc_component_update_bits(component, AIC32X4_MADC, |
|---|
| 837 | | - AIC32X4_MADCEN, 0); |
|---|
| 838 | | - |
|---|
| 839 | | - /* Switch off NADC Divider */ |
|---|
| 840 | | - snd_soc_component_update_bits(component, AIC32X4_NADC, |
|---|
| 841 | | - AIC32X4_NADCEN, 0); |
|---|
| 842 | | - |
|---|
| 843 | | - /* Switch off MDAC Divider */ |
|---|
| 844 | | - snd_soc_component_update_bits(component, AIC32X4_MDAC, |
|---|
| 845 | | - AIC32X4_MDACEN, 0); |
|---|
| 846 | | - |
|---|
| 847 | | - /* Switch off NDAC Divider */ |
|---|
| 848 | | - snd_soc_component_update_bits(component, AIC32X4_NDAC, |
|---|
| 849 | | - AIC32X4_NDACEN, 0); |
|---|
| 850 | | - |
|---|
| 851 | | - /* Switch off PLL */ |
|---|
| 852 | | - snd_soc_component_update_bits(component, AIC32X4_PLLPR, |
|---|
| 853 | | - AIC32X4_PLLEN, 0); |
|---|
| 854 | | - |
|---|
| 855 | | - /* Switch off master clock */ |
|---|
| 856 | | - clk_disable_unprepare(aic32x4->mclk); |
|---|
| 883 | + clk_bulk_disable_unprepare(ARRAY_SIZE(clocks), clocks); |
|---|
| 857 | 884 | break; |
|---|
| 858 | 885 | case SND_SOC_BIAS_OFF: |
|---|
| 859 | 886 | break; |
|---|
| .. | .. |
|---|
| 861 | 888 | return 0; |
|---|
| 862 | 889 | } |
|---|
| 863 | 890 | |
|---|
| 864 | | -#define AIC32X4_RATES SNDRV_PCM_RATE_8000_96000 |
|---|
| 865 | | -#define AIC32X4_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE \ |
|---|
| 866 | | - | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE) |
|---|
| 891 | +#define AIC32X4_RATES SNDRV_PCM_RATE_8000_192000 |
|---|
| 892 | +#define AIC32X4_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE \ |
|---|
| 893 | + | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_3LE \ |
|---|
| 894 | + | SNDRV_PCM_FMTBIT_S32_LE) |
|---|
| 867 | 895 | |
|---|
| 868 | 896 | static const struct snd_soc_dai_ops aic32x4_ops = { |
|---|
| 869 | 897 | .hw_params = aic32x4_hw_params, |
|---|
| 870 | | - .digital_mute = aic32x4_mute, |
|---|
| 898 | + .mute_stream = aic32x4_mute, |
|---|
| 871 | 899 | .set_fmt = aic32x4_set_dai_fmt, |
|---|
| 872 | 900 | .set_sysclk = aic32x4_set_dai_sysclk, |
|---|
| 901 | + .no_capture_mute = 1, |
|---|
| 873 | 902 | }; |
|---|
| 874 | 903 | |
|---|
| 875 | 904 | static struct snd_soc_dai_driver aic32x4_dai = { |
|---|
| 876 | 905 | .name = "tlv320aic32x4-hifi", |
|---|
| 877 | 906 | .playback = { |
|---|
| 878 | | - .stream_name = "Playback", |
|---|
| 879 | | - .channels_min = 1, |
|---|
| 880 | | - .channels_max = 2, |
|---|
| 881 | | - .rates = AIC32X4_RATES, |
|---|
| 882 | | - .formats = AIC32X4_FORMATS,}, |
|---|
| 907 | + .stream_name = "Playback", |
|---|
| 908 | + .channels_min = 1, |
|---|
| 909 | + .channels_max = 2, |
|---|
| 910 | + .rates = AIC32X4_RATES, |
|---|
| 911 | + .formats = AIC32X4_FORMATS,}, |
|---|
| 883 | 912 | .capture = { |
|---|
| 884 | | - .stream_name = "Capture", |
|---|
| 885 | | - .channels_min = 1, |
|---|
| 886 | | - .channels_max = 2, |
|---|
| 887 | | - .rates = AIC32X4_RATES, |
|---|
| 888 | | - .formats = AIC32X4_FORMATS,}, |
|---|
| 913 | + .stream_name = "Capture", |
|---|
| 914 | + .channels_min = 1, |
|---|
| 915 | + .channels_max = 8, |
|---|
| 916 | + .rates = AIC32X4_RATES, |
|---|
| 917 | + .formats = AIC32X4_FORMATS,}, |
|---|
| 889 | 918 | .ops = &aic32x4_ops, |
|---|
| 890 | 919 | .symmetric_rates = 1, |
|---|
| 891 | 920 | }; |
|---|
| .. | .. |
|---|
| 898 | 927 | /* MFP1 */ |
|---|
| 899 | 928 | if (aic32x4->setup->gpio_func[0] != AIC32X4_MFPX_DEFAULT_VALUE) { |
|---|
| 900 | 929 | snd_soc_component_write(component, AIC32X4_DINCTL, |
|---|
| 901 | | - aic32x4->setup->gpio_func[0]); |
|---|
| 930 | + aic32x4->setup->gpio_func[0]); |
|---|
| 902 | 931 | snd_soc_add_component_controls(component, aic32x4_mfp1, |
|---|
| 903 | 932 | ARRAY_SIZE(aic32x4_mfp1)); |
|---|
| 904 | 933 | } |
|---|
| .. | .. |
|---|
| 906 | 935 | /* MFP2 */ |
|---|
| 907 | 936 | if (aic32x4->setup->gpio_func[1] != AIC32X4_MFPX_DEFAULT_VALUE) { |
|---|
| 908 | 937 | snd_soc_component_write(component, AIC32X4_DOUTCTL, |
|---|
| 909 | | - aic32x4->setup->gpio_func[1]); |
|---|
| 938 | + aic32x4->setup->gpio_func[1]); |
|---|
| 910 | 939 | snd_soc_add_component_controls(component, aic32x4_mfp2, |
|---|
| 911 | 940 | ARRAY_SIZE(aic32x4_mfp2)); |
|---|
| 912 | 941 | } |
|---|
| .. | .. |
|---|
| 914 | 943 | /* MFP3 */ |
|---|
| 915 | 944 | if (aic32x4->setup->gpio_func[2] != AIC32X4_MFPX_DEFAULT_VALUE) { |
|---|
| 916 | 945 | snd_soc_component_write(component, AIC32X4_SCLKCTL, |
|---|
| 917 | | - aic32x4->setup->gpio_func[2]); |
|---|
| 946 | + aic32x4->setup->gpio_func[2]); |
|---|
| 918 | 947 | snd_soc_add_component_controls(component, aic32x4_mfp3, |
|---|
| 919 | 948 | ARRAY_SIZE(aic32x4_mfp3)); |
|---|
| 920 | 949 | } |
|---|
| .. | .. |
|---|
| 922 | 951 | /* MFP4 */ |
|---|
| 923 | 952 | if (aic32x4->setup->gpio_func[3] != AIC32X4_MFPX_DEFAULT_VALUE) { |
|---|
| 924 | 953 | snd_soc_component_write(component, AIC32X4_MISOCTL, |
|---|
| 925 | | - aic32x4->setup->gpio_func[3]); |
|---|
| 954 | + aic32x4->setup->gpio_func[3]); |
|---|
| 926 | 955 | snd_soc_add_component_controls(component, aic32x4_mfp4, |
|---|
| 927 | 956 | ARRAY_SIZE(aic32x4_mfp4)); |
|---|
| 928 | 957 | } |
|---|
| .. | .. |
|---|
| 930 | 959 | /* MFP5 */ |
|---|
| 931 | 960 | if (aic32x4->setup->gpio_func[4] != AIC32X4_MFPX_DEFAULT_VALUE) { |
|---|
| 932 | 961 | snd_soc_component_write(component, AIC32X4_GPIOCTL, |
|---|
| 933 | | - aic32x4->setup->gpio_func[4]); |
|---|
| 962 | + aic32x4->setup->gpio_func[4]); |
|---|
| 934 | 963 | snd_soc_add_component_controls(component, aic32x4_mfp5, |
|---|
| 935 | 964 | ARRAY_SIZE(aic32x4_mfp5)); |
|---|
| 936 | 965 | } |
|---|
| .. | .. |
|---|
| 940 | 969 | { |
|---|
| 941 | 970 | struct aic32x4_priv *aic32x4 = snd_soc_component_get_drvdata(component); |
|---|
| 942 | 971 | u32 tmp_reg; |
|---|
| 972 | + int ret; |
|---|
| 943 | 973 | |
|---|
| 944 | | - if (gpio_is_valid(aic32x4->rstn_gpio)) { |
|---|
| 945 | | - ndelay(10); |
|---|
| 946 | | - gpio_set_value(aic32x4->rstn_gpio, 1); |
|---|
| 947 | | - } |
|---|
| 974 | + struct clk_bulk_data clocks[] = { |
|---|
| 975 | + { .id = "codec_clkin" }, |
|---|
| 976 | + { .id = "pll" }, |
|---|
| 977 | + { .id = "bdiv" }, |
|---|
| 978 | + { .id = "mdac" }, |
|---|
| 979 | + }; |
|---|
| 948 | 980 | |
|---|
| 949 | | - snd_soc_component_write(component, AIC32X4_RESET, 0x01); |
|---|
| 981 | + ret = devm_clk_bulk_get(component->dev, ARRAY_SIZE(clocks), clocks); |
|---|
| 982 | + if (ret) |
|---|
| 983 | + return ret; |
|---|
| 950 | 984 | |
|---|
| 951 | 985 | if (aic32x4->setup) |
|---|
| 952 | 986 | aic32x4_setup_gpios(component); |
|---|
| 953 | 987 | |
|---|
| 988 | + clk_set_parent(clocks[0].clk, clocks[1].clk); |
|---|
| 989 | + clk_set_parent(clocks[2].clk, clocks[3].clk); |
|---|
| 990 | + |
|---|
| 954 | 991 | /* Power platform configuration */ |
|---|
| 955 | 992 | if (aic32x4->power_cfg & AIC32X4_PWR_MICBIAS_2075_LDOIN) { |
|---|
| 956 | | - snd_soc_component_write(component, AIC32X4_MICBIAS, AIC32X4_MICBIAS_LDOIN | |
|---|
| 957 | | - AIC32X4_MICBIAS_2075V); |
|---|
| 993 | + snd_soc_component_write(component, AIC32X4_MICBIAS, |
|---|
| 994 | + AIC32X4_MICBIAS_LDOIN | AIC32X4_MICBIAS_2075V); |
|---|
| 958 | 995 | } |
|---|
| 959 | 996 | if (aic32x4->power_cfg & AIC32X4_PWR_AVDD_DVDD_WEAK_DISABLE) |
|---|
| 960 | 997 | snd_soc_component_write(component, AIC32X4_PWRCFG, AIC32X4_AVDDWEAKDISABLE); |
|---|
| .. | .. |
|---|
| 963 | 1000 | AIC32X4_LDOCTLEN : 0; |
|---|
| 964 | 1001 | snd_soc_component_write(component, AIC32X4_LDOCTL, tmp_reg); |
|---|
| 965 | 1002 | |
|---|
| 966 | | - tmp_reg = snd_soc_component_read32(component, AIC32X4_CMMODE); |
|---|
| 1003 | + tmp_reg = snd_soc_component_read(component, AIC32X4_CMMODE); |
|---|
| 967 | 1004 | if (aic32x4->power_cfg & AIC32X4_PWR_CMMODE_LDOIN_RANGE_18_36) |
|---|
| 968 | 1005 | tmp_reg |= AIC32X4_LDOIN_18_36; |
|---|
| 969 | 1006 | if (aic32x4->power_cfg & AIC32X4_PWR_CMMODE_HP_LDOIN_POWERED) |
|---|
| .. | .. |
|---|
| 989 | 1026 | * and down for the first capture to work properly. It seems related to |
|---|
| 990 | 1027 | * a HW BUG or some kind of behavior not documented in the datasheet. |
|---|
| 991 | 1028 | */ |
|---|
| 992 | | - tmp_reg = snd_soc_component_read32(component, AIC32X4_ADCSETUP); |
|---|
| 1029 | + tmp_reg = snd_soc_component_read(component, AIC32X4_ADCSETUP); |
|---|
| 993 | 1030 | snd_soc_component_write(component, AIC32X4_ADCSETUP, tmp_reg | |
|---|
| 994 | 1031 | AIC32X4_LADC_EN | AIC32X4_RADC_EN); |
|---|
| 995 | 1032 | snd_soc_component_write(component, AIC32X4_ADCSETUP, tmp_reg); |
|---|
| 1033 | + |
|---|
| 1034 | + /* |
|---|
| 1035 | + * Enable the fast charging feature and ensure the needed 40ms ellapsed |
|---|
| 1036 | + * before using the analog circuits. |
|---|
| 1037 | + */ |
|---|
| 1038 | + snd_soc_component_write(component, AIC32X4_REFPOWERUP, |
|---|
| 1039 | + AIC32X4_REFPOWERUP_40MS); |
|---|
| 1040 | + msleep(40); |
|---|
| 996 | 1041 | |
|---|
| 997 | 1042 | return 0; |
|---|
| 998 | 1043 | } |
|---|
| .. | .. |
|---|
| 1017 | 1062 | struct device_node *np) |
|---|
| 1018 | 1063 | { |
|---|
| 1019 | 1064 | struct aic32x4_setup_data *aic32x4_setup; |
|---|
| 1065 | + int ret; |
|---|
| 1020 | 1066 | |
|---|
| 1021 | 1067 | aic32x4_setup = devm_kzalloc(aic32x4->dev, sizeof(*aic32x4_setup), |
|---|
| 1022 | 1068 | GFP_KERNEL); |
|---|
| 1023 | 1069 | if (!aic32x4_setup) |
|---|
| 1024 | 1070 | return -ENOMEM; |
|---|
| 1071 | + |
|---|
| 1072 | + ret = of_property_match_string(np, "clock-names", "mclk"); |
|---|
| 1073 | + if (ret < 0) |
|---|
| 1074 | + return -EINVAL; |
|---|
| 1075 | + aic32x4->mclk_name = of_clk_get_parent_name(np, ret); |
|---|
| 1025 | 1076 | |
|---|
| 1026 | 1077 | aic32x4->swapdacs = false; |
|---|
| 1027 | 1078 | aic32x4->micpga_routing = 0; |
|---|
| .. | .. |
|---|
| 1077 | 1128 | return PTR_ERR(aic32x4->supply_av); |
|---|
| 1078 | 1129 | } |
|---|
| 1079 | 1130 | } else { |
|---|
| 1080 | | - if (IS_ERR(aic32x4->supply_dv) && |
|---|
| 1081 | | - PTR_ERR(aic32x4->supply_dv) == -EPROBE_DEFER) |
|---|
| 1131 | + if (PTR_ERR(aic32x4->supply_dv) == -EPROBE_DEFER) |
|---|
| 1082 | 1132 | return -EPROBE_DEFER; |
|---|
| 1083 | | - if (IS_ERR(aic32x4->supply_av) && |
|---|
| 1084 | | - PTR_ERR(aic32x4->supply_av) == -EPROBE_DEFER) |
|---|
| 1133 | + if (PTR_ERR(aic32x4->supply_av) == -EPROBE_DEFER) |
|---|
| 1085 | 1134 | return -EPROBE_DEFER; |
|---|
| 1086 | 1135 | } |
|---|
| 1087 | 1136 | |
|---|
| .. | .. |
|---|
| 1144 | 1193 | return PTR_ERR(regmap); |
|---|
| 1145 | 1194 | |
|---|
| 1146 | 1195 | aic32x4 = devm_kzalloc(dev, sizeof(struct aic32x4_priv), |
|---|
| 1147 | | - GFP_KERNEL); |
|---|
| 1196 | + GFP_KERNEL); |
|---|
| 1148 | 1197 | if (aic32x4 == NULL) |
|---|
| 1149 | 1198 | return -ENOMEM; |
|---|
| 1150 | 1199 | |
|---|
| .. | .. |
|---|
| 1156 | 1205 | aic32x4->swapdacs = pdata->swapdacs; |
|---|
| 1157 | 1206 | aic32x4->micpga_routing = pdata->micpga_routing; |
|---|
| 1158 | 1207 | aic32x4->rstn_gpio = pdata->rstn_gpio; |
|---|
| 1208 | + aic32x4->mclk_name = "mclk"; |
|---|
| 1159 | 1209 | } else if (np) { |
|---|
| 1160 | 1210 | ret = aic32x4_parse_dt(aic32x4, np); |
|---|
| 1161 | 1211 | if (ret) { |
|---|
| .. | .. |
|---|
| 1167 | 1217 | aic32x4->swapdacs = false; |
|---|
| 1168 | 1218 | aic32x4->micpga_routing = 0; |
|---|
| 1169 | 1219 | aic32x4->rstn_gpio = -1; |
|---|
| 1170 | | - } |
|---|
| 1171 | | - |
|---|
| 1172 | | - aic32x4->mclk = devm_clk_get(dev, "mclk"); |
|---|
| 1173 | | - if (IS_ERR(aic32x4->mclk)) { |
|---|
| 1174 | | - dev_err(dev, "Failed getting the mclk. The current implementation does not support the usage of this codec without mclk\n"); |
|---|
| 1175 | | - return PTR_ERR(aic32x4->mclk); |
|---|
| 1220 | + aic32x4->mclk_name = "mclk"; |
|---|
| 1176 | 1221 | } |
|---|
| 1177 | 1222 | |
|---|
| 1178 | 1223 | if (gpio_is_valid(aic32x4->rstn_gpio)) { |
|---|
| .. | .. |
|---|
| 1188 | 1233 | return ret; |
|---|
| 1189 | 1234 | } |
|---|
| 1190 | 1235 | |
|---|
| 1236 | + if (gpio_is_valid(aic32x4->rstn_gpio)) { |
|---|
| 1237 | + ndelay(10); |
|---|
| 1238 | + gpio_set_value_cansleep(aic32x4->rstn_gpio, 1); |
|---|
| 1239 | + mdelay(1); |
|---|
| 1240 | + } |
|---|
| 1241 | + |
|---|
| 1242 | + ret = regmap_write(regmap, AIC32X4_RESET, 0x01); |
|---|
| 1243 | + if (ret) |
|---|
| 1244 | + goto err_disable_regulators; |
|---|
| 1245 | + |
|---|
| 1246 | + ret = aic32x4_register_clocks(dev, aic32x4->mclk_name); |
|---|
| 1247 | + if (ret) |
|---|
| 1248 | + goto err_disable_regulators; |
|---|
| 1249 | + |
|---|
| 1191 | 1250 | ret = devm_snd_soc_register_component(dev, |
|---|
| 1192 | 1251 | &soc_component_dev_aic32x4, &aic32x4_dai, 1); |
|---|
| 1193 | 1252 | if (ret) { |
|---|
| 1194 | 1253 | dev_err(dev, "Failed to register component\n"); |
|---|
| 1195 | | - aic32x4_disable_regulators(aic32x4); |
|---|
| 1196 | | - return ret; |
|---|
| 1254 | + goto err_disable_regulators; |
|---|
| 1197 | 1255 | } |
|---|
| 1198 | 1256 | |
|---|
| 1199 | 1257 | return 0; |
|---|
| 1258 | + |
|---|
| 1259 | +err_disable_regulators: |
|---|
| 1260 | + aic32x4_disable_regulators(aic32x4); |
|---|
| 1261 | + |
|---|
| 1262 | + return ret; |
|---|
| 1200 | 1263 | } |
|---|
| 1201 | 1264 | EXPORT_SYMBOL(aic32x4_probe); |
|---|
| 1202 | 1265 | |
|---|