diff options
Diffstat (limited to 'sound/soc/codecs')
62 files changed, 7770 insertions, 1122 deletions
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index f3fb98f0a995..1cd6ab344d67 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -32,6 +32,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_ADAU1977_SPI if SPI_MASTER select SND_SOC_ADAU1977_I2C if I2C select SND_SOC_ADAU1701 if I2C + select SND_SOC_ADAU7002 select SND_SOC_ADS117X select SND_SOC_AK4104 if SPI_MASTER select SND_SOC_AK4535 if I2C @@ -46,6 +47,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_BT_SCO select SND_SOC_CQ0093VC if MFD_DAVINCI_VOICECODEC select SND_SOC_CS35L32 if I2C + select SND_SOC_CS35L33 if I2C select SND_SOC_CS42L51_I2C if I2C select SND_SOC_CS42L52 if I2C && INPUT select SND_SOC_CS42L56 if I2C && INPUT @@ -57,6 +59,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_CS42XX8_I2C if I2C select SND_SOC_CS4349 if I2C select SND_SOC_CS47L24 if MFD_CS47L24 + select SND_SOC_CS53L30 if I2C select SND_SOC_CX20442 if TTY select SND_SOC_DA7210 if SND_SOC_I2C_AND_SPI select SND_SOC_DA7213 if I2C @@ -84,6 +87,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_MAX98925 if I2C select SND_SOC_MAX98926 if I2C select SND_SOC_MAX9850 if I2C + select SND_SOC_MAX9860 if I2C select SND_SOC_MAX9768 if I2C select SND_SOC_MAX9877 if I2C select SND_SOC_MC13783 if MFD_MC13XXX @@ -269,8 +273,12 @@ config SND_SOC_AD1980 config SND_SOC_AD73311 tristate +config SND_SOC_ADAU_UTILS + tristate + config SND_SOC_ADAU1373 tristate + select SND_SOC_ADAU_UTILS config SND_SOC_ADAU1701 tristate "Analog Devices ADAU1701 CODEC" @@ -280,6 +288,7 @@ config SND_SOC_ADAU1701 config SND_SOC_ADAU17X1 tristate select SND_SOC_SIGMADSP_REGMAP + select SND_SOC_ADAU_UTILS config SND_SOC_ADAU1761 tristate @@ -322,6 +331,9 @@ config SND_SOC_ADAU1977_I2C select SND_SOC_ADAU1977 select REGMAP_I2C +config SND_SOC_ADAU7002 + tristate "Analog Devices ADAU7002 Stereo PDM-to-I2S/TDM Converter" + config SND_SOC_ADAV80X tristate @@ -371,7 +383,7 @@ config SND_SOC_ALC5632 tristate config SND_SOC_BT_SCO - tristate + tristate "Dummy BT SCO codec driver" config SND_SOC_CQ0093VC tristate @@ -380,6 +392,10 @@ config SND_SOC_CS35L32 tristate "Cirrus Logic CS35L32 CODEC" depends on I2C +config SND_SOC_CS35L33 + tristate "Cirrus Logic CS35L33 CODEC" + depends on I2C + config SND_SOC_CS42L51 tristate @@ -450,6 +466,11 @@ config SND_SOC_CS4349 config SND_SOC_CS47L24 tristate +# Cirrus Logic Quad-Channel ADC +config SND_SOC_CS53L30 + tristate "Cirrus Logic CS53L30 CODEC" + depends on I2C + config SND_SOC_CX20442 tristate depends on TTY @@ -536,6 +557,10 @@ config SND_SOC_MAX98357A config SND_SOC_MAX98371 tristate +config SND_SOC_MAX98504 + tristate "Maxim MAX98504 speaker amplifier" + depends on I2C + config SND_SOC_MAX9867 tristate @@ -548,6 +573,11 @@ config SND_SOC_MAX98926 config SND_SOC_MAX9850 tristate +config SND_SOC_MAX9860 + tristate "Maxim MAX9860 Mono Audio Voice Codec" + depends on I2C + select REGMAP_I2C + config SND_SOC_PCM1681 tristate "Texas Instruments PCM1681 CODEC" depends on I2C @@ -644,6 +674,9 @@ config SND_SOC_RT298 config SND_SOC_RT5514 tristate +config SND_SOC_RT5514_SPI + tristate + config SND_SOC_RT5616 tristate "Realtek RT5616 CODEC" depends on I2C @@ -969,7 +1002,8 @@ config SND_SOC_WM8983 tristate config SND_SOC_WM8985 - tristate + tristate "Wolfson Microelectronics WM8985 and WM8758 codec driver" + depends on SND_SOC_I2C_AND_SPI config SND_SOC_WM8988 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 0f548fd34ca3..58036af2c7d9 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -7,6 +7,7 @@ snd-soc-ad193x-spi-objs := ad193x-spi.o snd-soc-ad193x-i2c-objs := ad193x-i2c.o snd-soc-ad1980-objs := ad1980.o snd-soc-ad73311-objs := ad73311.o +snd-soc-adau-utils-objs := adau-utils.o snd-soc-adau1373-objs := adau1373.o snd-soc-adau1701-objs := adau1701.o snd-soc-adau17x1-objs := adau17x1.o @@ -19,6 +20,7 @@ snd-soc-adau1781-spi-objs := adau1781-spi.o snd-soc-adau1977-objs := adau1977.o snd-soc-adau1977-spi-objs := adau1977-spi.o snd-soc-adau1977-i2c-objs := adau1977-i2c.o +snd-soc-adau7002-objs := adau7002.o snd-soc-adav80x-objs := adav80x.o snd-soc-adav801-objs := adav801.o snd-soc-adav803-objs := adav803.o @@ -35,6 +37,7 @@ snd-soc-arizona-objs := arizona.o snd-soc-bt-sco-objs := bt-sco.o snd-soc-cq93vc-objs := cq93vc.o snd-soc-cs35l32-objs := cs35l32.o +snd-soc-cs35l33-objs := cs35l33.o snd-soc-cs42l51-objs := cs42l51.o snd-soc-cs42l51-i2c-objs := cs42l51-i2c.o snd-soc-cs42l52-objs := cs42l52.o @@ -49,6 +52,7 @@ snd-soc-cs42xx8-objs := cs42xx8.o snd-soc-cs42xx8-i2c-objs := cs42xx8-i2c.o snd-soc-cs4349-objs := cs4349.o snd-soc-cs47l24-objs := cs47l24.o +snd-soc-cs53l30-objs := cs53l30.o snd-soc-cx20442-objs := cx20442.o snd-soc-da7210-objs := da7210.o snd-soc-da7213-objs := da7213.o @@ -79,6 +83,7 @@ snd-soc-max9867-objs := max9867.o snd-soc-max98925-objs := max98925.o snd-soc-max98926-objs := max98926.o snd-soc-max9850-objs := max9850.o +snd-soc-max9860-objs := max9860.o snd-soc-mc13783-objs := mc13783.o snd-soc-ml26124-objs := ml26124.o snd-soc-nau8825-objs := nau8825.o @@ -100,6 +105,7 @@ snd-soc-rl6347a-objs := rl6347a.o snd-soc-rt286-objs := rt286.o snd-soc-rt298-objs := rt298.o snd-soc-rt5514-objs := rt5514.o +snd-soc-rt5514-spi-objs := rt5514-spi.o snd-soc-rt5616-objs := rt5616.o snd-soc-rt5631-objs := rt5631.o snd-soc-rt5640-objs := rt5640.o @@ -208,6 +214,7 @@ snd-soc-wm-hubs-objs := wm_hubs.o # Amp snd-soc-max9877-objs := max9877.o +snd-soc-max98504-objs := max98504.o snd-soc-tpa6130a2-objs := tpa6130a2.o snd-soc-tas2552-objs := tas2552.o @@ -220,6 +227,7 @@ obj-$(CONFIG_SND_SOC_AD193X_SPI) += snd-soc-ad193x-spi.o obj-$(CONFIG_SND_SOC_AD193X_I2C) += snd-soc-ad193x-i2c.o obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o +obj-$(CONFIG_SND_SOC_ADAU_UTILS) += snd-soc-adau-utils.o obj-$(CONFIG_SND_SOC_ADAU1373) += snd-soc-adau1373.o obj-$(CONFIG_SND_SOC_ADAU1701) += snd-soc-adau1701.o obj-$(CONFIG_SND_SOC_ADAU17X1) += snd-soc-adau17x1.o @@ -232,6 +240,7 @@ obj-$(CONFIG_SND_SOC_ADAU1781_SPI) += snd-soc-adau1781-spi.o obj-$(CONFIG_SND_SOC_ADAU1977) += snd-soc-adau1977.o obj-$(CONFIG_SND_SOC_ADAU1977_SPI) += snd-soc-adau1977-spi.o obj-$(CONFIG_SND_SOC_ADAU1977_I2C) += snd-soc-adau1977-i2c.o +obj-$(CONFIG_SND_SOC_ADAU7002) += snd-soc-adau7002.o obj-$(CONFIG_SND_SOC_ADAV80X) += snd-soc-adav80x.o obj-$(CONFIG_SND_SOC_ADAV801) += snd-soc-adav801.o obj-$(CONFIG_SND_SOC_ADAV803) += snd-soc-adav803.o @@ -250,6 +259,7 @@ obj-$(CONFIG_SND_SOC_ARIZONA) += snd-soc-arizona.o obj-$(CONFIG_SND_SOC_BT_SCO) += snd-soc-bt-sco.o obj-$(CONFIG_SND_SOC_CQ0093VC) += snd-soc-cq93vc.o obj-$(CONFIG_SND_SOC_CS35L32) += snd-soc-cs35l32.o +obj-$(CONFIG_SND_SOC_CS35L33) += snd-soc-cs35l33.o obj-$(CONFIG_SND_SOC_CS42L51) += snd-soc-cs42l51.o obj-$(CONFIG_SND_SOC_CS42L51_I2C) += snd-soc-cs42l51-i2c.o obj-$(CONFIG_SND_SOC_CS42L52) += snd-soc-cs42l52.o @@ -264,6 +274,7 @@ obj-$(CONFIG_SND_SOC_CS42XX8) += snd-soc-cs42xx8.o obj-$(CONFIG_SND_SOC_CS42XX8_I2C) += snd-soc-cs42xx8-i2c.o obj-$(CONFIG_SND_SOC_CS4349) += snd-soc-cs4349.o obj-$(CONFIG_SND_SOC_CS47L24) += snd-soc-cs47l24.o +obj-$(CONFIG_SND_SOC_CS53L30) += snd-soc-cs53l30.o obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o obj-$(CONFIG_SND_SOC_DA7213) += snd-soc-da7213.o @@ -293,6 +304,7 @@ obj-$(CONFIG_SND_SOC_MAX9867) += snd-soc-max9867.o obj-$(CONFIG_SND_SOC_MAX98925) += snd-soc-max98925.o obj-$(CONFIG_SND_SOC_MAX98926) += snd-soc-max98926.o obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o +obj-$(CONFIG_SND_SOC_MAX9860) += snd-soc-max9860.o obj-$(CONFIG_SND_SOC_MC13783) += snd-soc-mc13783.o obj-$(CONFIG_SND_SOC_ML26124) += snd-soc-ml26124.o obj-$(CONFIG_SND_SOC_NAU8825) += snd-soc-nau8825.o @@ -314,6 +326,7 @@ obj-$(CONFIG_SND_SOC_RL6347A) += snd-soc-rl6347a.o obj-$(CONFIG_SND_SOC_RT286) += snd-soc-rt286.o obj-$(CONFIG_SND_SOC_RT298) += snd-soc-rt298.o obj-$(CONFIG_SND_SOC_RT5514) += snd-soc-rt5514.o +obj-$(CONFIG_SND_SOC_RT5514_SPI) += snd-soc-rt5514-spi.o obj-$(CONFIG_SND_SOC_RT5616) += snd-soc-rt5616.o obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o @@ -419,4 +432,5 @@ obj-$(CONFIG_SND_SOC_WM_HUBS) += snd-soc-wm-hubs.o # Amp obj-$(CONFIG_SND_SOC_MAX9877) += snd-soc-max9877.o +obj-$(CONFIG_SND_SOC_MAX98504) += snd-soc-max98504.o obj-$(CONFIG_SND_SOC_TPA6130A2) += snd-soc-tpa6130a2.o diff --git a/sound/soc/codecs/adau-utils.c b/sound/soc/codecs/adau-utils.c new file mode 100644 index 000000000000..19d6a6f41b12 --- /dev/null +++ b/sound/soc/codecs/adau-utils.c @@ -0,0 +1,61 @@ +/* + * Shared helper functions for devices from the ADAU family + * + * Copyright 2011-2016 Analog Devices Inc. + * Author: Lars-Peter Clausen <lars@metafoo.de> + * + * Licensed under the GPL-2 or later. + */ + +#include <linux/gcd.h> +#include <linux/kernel.h> +#include <linux/module.h> + +#include "adau-utils.h" + +int adau_calc_pll_cfg(unsigned int freq_in, unsigned int freq_out, + uint8_t regs[5]) +{ + unsigned int r, n, m, i, j; + unsigned int div; + + if (!freq_out) { + r = 0; + n = 0; + m = 0; + div = 0; + } else { + if (freq_out % freq_in != 0) { + div = DIV_ROUND_UP(freq_in, 13500000); + freq_in /= div; + r = freq_out / freq_in; + i = freq_out % freq_in; + j = gcd(i, freq_in); + n = i / j; + m = freq_in / j; + div--; + } else { + r = freq_out / freq_in; + n = 0; + m = 0; + div = 0; + } + if (n > 0xffff || m > 0xffff || div > 3 || r > 8 || r < 2) + return -EINVAL; + } + + regs[0] = m >> 8; + regs[1] = m & 0xff; + regs[2] = n >> 8; + regs[3] = n & 0xff; + regs[4] = (r << 3) | (div << 1); + if (m != 0) + regs[4] |= 1; /* Fractional mode */ + + return 0; +} +EXPORT_SYMBOL_GPL(adau_calc_pll_cfg); + +MODULE_DESCRIPTION("ASoC ADAU audio CODECs shared helper functions"); +MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/adau-utils.h b/sound/soc/codecs/adau-utils.h new file mode 100644 index 000000000000..939b5f37762f --- /dev/null +++ b/sound/soc/codecs/adau-utils.h @@ -0,0 +1,7 @@ +#ifndef SOUND_SOC_CODECS_ADAU_PLL_H +#define SOUND_SOC_CODECS_ADAU_PLL_H + +int adau_calc_pll_cfg(unsigned int freq_in, unsigned int freq_out, + uint8_t regs[5]); + +#endif diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c index fe1353a797b9..1556b360fa15 100644 --- a/sound/soc/codecs/adau1373.c +++ b/sound/soc/codecs/adau1373.c @@ -23,6 +23,7 @@ #include <sound/adau1373.h> #include "adau1373.h" +#include "adau-utils.h" struct adau1373_dai { unsigned int clk_src; @@ -1254,7 +1255,8 @@ static int adau1373_set_pll(struct snd_soc_codec *codec, int pll_id, { struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec); unsigned int dpll_div = 0; - unsigned int x, r, n, m, i, j, mode; + uint8_t pll_regs[5]; + int ret; switch (pll_id) { case ADAU1373_PLL1: @@ -1295,27 +1297,8 @@ static int adau1373_set_pll(struct snd_soc_codec *codec, int pll_id, dpll_div++; } - if (freq_out % freq_in != 0) { - /* fout = fin * (r + (n/m)) / x */ - x = DIV_ROUND_UP(freq_in, 13500000); - freq_in /= x; - r = freq_out / freq_in; - i = freq_out % freq_in; - j = gcd(i, freq_in); - n = i / j; - m = freq_in / j; - x--; - mode = 1; - } else { - /* fout = fin / r */ - r = freq_out / freq_in; - n = 0; - m = 0; - x = 0; - mode = 0; - } - - if (r < 2 || r > 8 || x > 3 || m > 0xffff || n > 0xffff) + ret = adau_calc_pll_cfg(freq_in, freq_out, pll_regs); + if (ret) return -EINVAL; if (dpll_div) { @@ -1330,12 +1313,11 @@ static int adau1373_set_pll(struct snd_soc_codec *codec, int pll_id, regmap_write(adau1373->regmap, ADAU1373_DPLL_CTRL(pll_id), (source << 4) | dpll_div); - regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL1(pll_id), (m >> 8) & 0xff); - regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL2(pll_id), m & 0xff); - regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL3(pll_id), (n >> 8) & 0xff); - regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL4(pll_id), n & 0xff); - regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL5(pll_id), - (r << 3) | (x << 1) | mode); + regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL1(pll_id), pll_regs[0]); + regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL2(pll_id), pll_regs[1]); + regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL3(pll_id), pll_regs[2]); + regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL4(pll_id), pll_regs[3]); + regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL5(pll_id), pll_regs[4]); /* Set sysclk to pll_rate / 4 */ regmap_update_bits(adau1373->regmap, ADAU1373_CLK_SRC_DIV(pll_id), 0x3f, 0x09); diff --git a/sound/soc/codecs/adau1761-i2c.c b/sound/soc/codecs/adau1761-i2c.c index 8de010f758cd..9e7f257f17f8 100644 --- a/sound/soc/codecs/adau1761-i2c.c +++ b/sound/soc/codecs/adau1761-i2c.c @@ -31,7 +31,7 @@ static int adau1761_i2c_probe(struct i2c_client *client, static int adau1761_i2c_remove(struct i2c_client *client) { - snd_soc_unregister_codec(&client->dev); + adau17x1_remove(&client->dev); return 0; } diff --git a/sound/soc/codecs/adau1761-spi.c b/sound/soc/codecs/adau1761-spi.c index d9171245bd9f..a0b214be759a 100644 --- a/sound/soc/codecs/adau1761-spi.c +++ b/sound/soc/codecs/adau1761-spi.c @@ -48,7 +48,7 @@ static int adau1761_spi_probe(struct spi_device *spi) static int adau1761_spi_remove(struct spi_device *spi) { - snd_soc_unregister_codec(&spi->dev); + adau17x1_remove(&spi->dev); return 0; } diff --git a/sound/soc/codecs/adau1781-i2c.c b/sound/soc/codecs/adau1781-i2c.c index 06cbca84cf02..7b9d1802d159 100644 --- a/sound/soc/codecs/adau1781-i2c.c +++ b/sound/soc/codecs/adau1781-i2c.c @@ -31,7 +31,7 @@ static int adau1781_i2c_probe(struct i2c_client *client, static int adau1781_i2c_remove(struct i2c_client *client) { - snd_soc_unregister_codec(&client->dev); + adau17x1_remove(&client->dev); return 0; } diff --git a/sound/soc/codecs/adau1781-spi.c b/sound/soc/codecs/adau1781-spi.c index 3d965a01b99c..9b233544d2e8 100644 --- a/sound/soc/codecs/adau1781-spi.c +++ b/sound/soc/codecs/adau1781-spi.c @@ -48,7 +48,7 @@ static int adau1781_spi_probe(struct spi_device *spi) static int adau1781_spi_remove(struct spi_device *spi) { - snd_soc_unregister_codec(&spi->dev); + adau17x1_remove(&spi->dev); return 0; } diff --git a/sound/soc/codecs/adau17x1.c b/sound/soc/codecs/adau17x1.c index fcf05b254ecd..439aa3ff1f99 100644 --- a/sound/soc/codecs/adau17x1.c +++ b/sound/soc/codecs/adau17x1.c @@ -9,6 +9,7 @@ #include <linux/module.h> #include <linux/init.h> +#include <linux/clk.h> #include <linux/delay.h> #include <linux/slab.h> #include <sound/core.h> @@ -23,6 +24,7 @@ #include "sigmadsp.h" #include "adau17x1.h" +#include "adau-utils.h" static const char * const adau17x1_capture_mixer_boost_text[] = { "Normal operation", "Boost Level 1", "Boost Level 2", "Boost Level 3", @@ -302,6 +304,116 @@ bool adau17x1_has_dsp(struct adau *adau) } EXPORT_SYMBOL_GPL(adau17x1_has_dsp); +static int adau17x1_set_dai_pll(struct snd_soc_dai *dai, int pll_id, + int source, unsigned int freq_in, unsigned int freq_out) +{ + struct snd_soc_codec *codec = dai->codec; + struct adau *adau = snd_soc_codec_get_drvdata(codec); + int ret; + + if (freq_in < 8000000 || freq_in > 27000000) + return -EINVAL; + + ret = adau_calc_pll_cfg(freq_in, freq_out, adau->pll_regs); + if (ret < 0) + return ret; + + /* The PLL register is 6 bytes long and can only be written at once. */ + ret = regmap_raw_write(adau->regmap, ADAU17X1_PLL_CONTROL, + adau->pll_regs, ARRAY_SIZE(adau->pll_regs)); + if (ret) + return ret; + + adau->pll_freq = freq_out; + + return 0; +} + +static int adau17x1_set_dai_sysclk(struct snd_soc_dai *dai, + int clk_id, unsigned int freq, int dir) +{ + struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(dai->codec); + struct adau *adau = snd_soc_codec_get_drvdata(dai->codec); + bool is_pll; + bool was_pll; + + switch (clk_id) { + case ADAU17X1_CLK_SRC_MCLK: + is_pll = false; + break; + case ADAU17X1_CLK_SRC_PLL_AUTO: + if (!adau->mclk) + return -EINVAL; + /* Fall-through */ + case ADAU17X1_CLK_SRC_PLL: + is_pll = true; + break; + default: + return -EINVAL; + } + + switch (adau->clk_src) { + case ADAU17X1_CLK_SRC_MCLK: + was_pll = false; + break; + case ADAU17X1_CLK_SRC_PLL: + case ADAU17X1_CLK_SRC_PLL_AUTO: + was_pll = true; + break; + default: + return -EINVAL; + } + + adau->sysclk = freq; + + if (is_pll != was_pll) { + if (is_pll) { + snd_soc_dapm_add_routes(dapm, + &adau17x1_dapm_pll_route, 1); + } else { + snd_soc_dapm_del_routes(dapm, + &adau17x1_dapm_pll_route, 1); + } + } + + adau->clk_src = clk_id; + + return 0; +} + +static int adau17x1_auto_pll(struct snd_soc_dai *dai, + struct snd_pcm_hw_params *params) +{ + struct adau *adau = snd_soc_dai_get_drvdata(dai); + unsigned int pll_rate; + + switch (params_rate(params)) { + case 48000: + case 8000: + case 12000: + case 16000: + case 24000: + case 32000: + case 96000: + pll_rate = 48000 * 1024; + break; + case 44100: + case 7350: + case 11025: + case 14700: + case 22050: + case 29400: + case 88200: + pll_rate = 44100 * 1024; + break; + default: + return -EINVAL; + } + + return adau17x1_set_dai_pll(dai, ADAU17X1_PLL, ADAU17X1_PLL_SRC_MCLK, + clk_get_rate(adau->mclk), pll_rate); +} + static int adau17x1_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { @@ -311,10 +423,19 @@ static int adau17x1_hw_params(struct snd_pcm_substream *substream, unsigned int freq; int ret; - if (adau->clk_src == ADAU17X1_CLK_SRC_PLL) + switch (adau->clk_src) { + case ADAU17X1_CLK_SRC_PLL_AUTO: + ret = adau17x1_auto_pll(dai, params); + if (ret) + return ret; + /* Fall-through */ + case ADAU17X1_CLK_SRC_PLL: freq = adau->pll_freq; - else + break; + default: freq = adau->sysclk; + break; + } if (freq % params_rate(params) != 0) return -EINVAL; @@ -386,93 +507,6 @@ static int adau17x1_hw_params(struct snd_pcm_substream *substream, ADAU17X1_SERIAL_PORT1_DELAY_MASK, val); } -static int adau17x1_set_dai_pll(struct snd_soc_dai *dai, int pll_id, - int source, unsigned int freq_in, unsigned int freq_out) -{ - struct snd_soc_codec *codec = dai->codec; - struct adau *adau = snd_soc_codec_get_drvdata(codec); - unsigned int r, n, m, i, j; - unsigned int div; - int ret; - - if (freq_in < 8000000 || freq_in > 27000000) - return -EINVAL; - - if (!freq_out) { - r = 0; - n = 0; - m = 0; - div = 0; - } else { - if (freq_out % freq_in != 0) { - div = DIV_ROUND_UP(freq_in, 13500000); - freq_in /= div; - r = freq_out / freq_in; - i = freq_out % freq_in; - j = gcd(i, freq_in); - n = i / j; - m = freq_in / j; - div--; - } else { - r = freq_out / freq_in; - n = 0; - m = 0; - div = 0; - } - if (n |