From 146c9aff275c5f075a29641e2d6d38153e96696e Mon Sep 17 00:00:00 2001 From: John Crispin Date: Wed, 11 Feb 2015 13:05:23 +0000 Subject: brcm2708: remove 3.14 support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Álvaro Fernández Rojas SVN-Revision: 44402 --- ...audIO-Sound-Card-support-for-Raspberry-Pi.patch | 1070 -------------------- 1 file changed, 1070 deletions(-) delete mode 100644 target/linux/brcm2708/patches-3.14/0049-Add-IQaudIO-Sound-Card-support-for-Raspberry-Pi.patch (limited to 'target/linux/brcm2708/patches-3.14/0049-Add-IQaudIO-Sound-Card-support-for-Raspberry-Pi.patch') diff --git a/target/linux/brcm2708/patches-3.14/0049-Add-IQaudIO-Sound-Card-support-for-Raspberry-Pi.patch b/target/linux/brcm2708/patches-3.14/0049-Add-IQaudIO-Sound-Card-support-for-Raspberry-Pi.patch deleted file mode 100644 index 72538714cf..0000000000 --- a/target/linux/brcm2708/patches-3.14/0049-Add-IQaudIO-Sound-Card-support-for-Raspberry-Pi.patch +++ /dev/null @@ -1,1070 +0,0 @@ -From deaa651db204a6add9cb0189350922625fd1a311 Mon Sep 17 00:00:00 2001 -From: Gordon Garrity -Date: Sat, 8 Mar 2014 16:56:57 +0000 -Subject: [PATCH 49/54] Add IQaudIO Sound Card support for Raspberry Pi - ---- - arch/arm/configs/bcmrpi_defconfig | 1 + - arch/arm/mach-bcm2708/bcm2708.c | 22 ++ - sound/soc/bcm/Kconfig | 7 + - sound/soc/bcm/Makefile | 2 + - sound/soc/bcm/iqaudio-dac.c | 111 +++++++ - sound/soc/codecs/Kconfig | 4 + - sound/soc/codecs/Makefile | 2 + - sound/soc/codecs/pcm512x.c | 677 ++++++++++++++++++++++++++++++++++++++ - sound/soc/codecs/pcm512x.h | 142 ++++++++ - 9 files changed, 968 insertions(+) - create mode 100644 sound/soc/bcm/iqaudio-dac.c - create mode 100644 sound/soc/codecs/pcm512x.c - create mode 100644 sound/soc/codecs/pcm512x.h - ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -750,6 +750,7 @@ CONFIG_SND_BCM2708_SOC_RPI_DAC=m - CONFIG_SND_SOC_I2C_AND_SPI=m - CONFIG_SND_SOC_PCM5102A=m - CONFIG_SND_SOC_PCM1794A=m -+CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m - CONFIG_SOUND_PRIME=m - CONFIG_HIDRAW=y - CONFIG_HID_A4TECH=m ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -680,6 +680,22 @@ static struct platform_device snd_pcm179 - }; - #endif - -+ -+#if defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) || defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC_MODULE) -+static struct platform_device snd_rpi_iqaudio_dac_device = { -+ .name = "snd-rpi-iqaudio-dac", -+ .id = 0, -+ .num_resources = 0, -+}; -+ -+// Use the actual device name rather than generic driver name -+static struct i2c_board_info __initdata snd_pcm512x_i2c_devices[] = { -+ { -+ I2C_BOARD_INFO("pcm5122", 0x4c) -+ }, -+}; -+#endif -+ - int __init bcm_register_device(struct platform_device *pdev) - { - int ret; -@@ -822,6 +838,12 @@ void __init bcm2708_init(void) - bcm_register_device(&snd_pcm1794a_codec_device); - #endif - -+#if defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) || defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC_MODULE) -+ bcm_register_device(&snd_rpi_iqaudio_dac_device); -+ i2c_register_board_info(1, snd_pcm512x_i2c_devices, ARRAY_SIZE(snd_pcm512x_i2c_devices)); -+#endif -+ -+ - for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { - struct amba_device *d = amba_devs[i]; - amba_device_register(d, &iomem_resource); ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -39,3 +39,10 @@ config SND_BCM2708_SOC_RPI_DAC - select SND_SOC_PCM1794A - help - Say Y or M if you want to add support for RPi-DAC. -+ -+config SND_BCM2708_SOC_IQAUDIO_DAC -+ tristate "Support for IQaudIO-DAC" -+ depends on SND_BCM2708_SOC_I2S -+ select SND_SOC_PCM512x -+ help -+ Say Y or M if you want to add support for IQaudIO-DAC. ---- a/sound/soc/bcm/Makefile -+++ b/sound/soc/bcm/Makefile -@@ -12,7 +12,9 @@ obj-$(CONFIG_SND_BCM2708_SOC_I2S) += snd - snd-soc-hifiberry-dac-objs := hifiberry_dac.o - snd-soc-hifiberry-digi-objs := hifiberry_digi.o - snd-soc-rpi-dac-objs := rpi-dac.o -+snd-soc-iqaudio-dac-objs := iqaudio-dac.o - - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) += snd-soc-hifiberry-digi.o - obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o -+obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o ---- /dev/null -+++ b/sound/soc/bcm/iqaudio-dac.c -@@ -0,0 +1,111 @@ -+/* -+ * ASoC Driver for IQaudIO DAC -+ * -+ * Author: Florian Meier -+ * Copyright 2013 -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ */ -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+static int snd_rpi_iqaudio_dac_init(struct snd_soc_pcm_runtime *rtd) -+{ -+// NOT USED struct snd_soc_codec *codec = rtd->codec; -+ -+ return 0; -+} -+ -+static int snd_rpi_iqaudio_dac_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+// NOT USED struct snd_soc_dai *codec_dai = rtd->codec_dai; -+// NOT USED struct snd_soc_codec *codec = rtd->codec; -+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; -+ -+ unsigned int sample_bits = -+ snd_pcm_format_physical_width(params_format(params)); -+ -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, sample_bits * 2); -+} -+ -+/* machine stream operations */ -+static struct snd_soc_ops snd_rpi_iqaudio_dac_ops = { -+ .hw_params = snd_rpi_iqaudio_dac_hw_params, -+}; -+ -+static struct snd_soc_dai_link snd_rpi_iqaudio_dac_dai[] = { -+{ -+ .name = "IQaudIO DAC", -+ .stream_name = "IQaudIO DAC HiFi", -+ .cpu_dai_name = "bcm2708-i2s.0", -+ .codec_dai_name = "pcm512x-hifi", -+ .platform_name = "bcm2708-i2s.0", -+ .codec_name = "pcm512x.1-004c", -+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | -+ SND_SOC_DAIFMT_CBS_CFS, -+ .ops = &snd_rpi_iqaudio_dac_ops, -+ .init = snd_rpi_iqaudio_dac_init, -+}, -+}; -+ -+/* audio machine driver */ -+static struct snd_soc_card snd_rpi_iqaudio_dac = { -+ .name = "snd_rpi_iqaudio_dac", -+ .dai_link = snd_rpi_iqaudio_dac_dai, -+ .num_links = ARRAY_SIZE(snd_rpi_iqaudio_dac_dai), -+}; -+ -+static int snd_rpi_iqaudio_dac_probe(struct platform_device *pdev) -+{ -+ int ret = 0; -+ -+ snd_rpi_iqaudio_dac.dev = &pdev->dev; -+ ret = snd_soc_register_card(&snd_rpi_iqaudio_dac); -+ if (ret) -+ dev_err(&pdev->dev, -+ "snd_soc_register_card() failed: %d\n", ret); -+ -+ return ret; -+} -+ -+static int snd_rpi_iqaudio_dac_remove(struct platform_device *pdev) -+{ -+ return snd_soc_unregister_card(&snd_rpi_iqaudio_dac); -+} -+ -+static const struct of_device_id iqaudio_of_match[] = { -+ { .compatible = "iqaudio,iqaudio-dac", }, -+ {}, -+}; -+ -+static struct platform_driver snd_rpi_iqaudio_dac_driver = { -+ .driver = { -+ .name = "snd-rpi-iqaudio-dac", -+ .owner = THIS_MODULE, -+ .of_match_table = iqaudio_of_match, -+ }, -+ .probe = snd_rpi_iqaudio_dac_probe, -+ .remove = snd_rpi_iqaudio_dac_remove, -+}; -+ -+module_platform_driver(snd_rpi_iqaudio_dac_driver); -+ -+MODULE_AUTHOR("Florian Meier "); -+MODULE_DESCRIPTION("ASoC Driver for IQAudio DAC"); -+MODULE_LICENSE("GPL v2"); ---- a/sound/soc/codecs/Kconfig -+++ b/sound/soc/codecs/Kconfig -@@ -61,6 +61,7 @@ config SND_SOC_ALL_CODECS - select SND_SOC_PCM3008 - select SND_SOC_PCM1794A - select SND_SOC_PCM5102A -+ select SND_SOC_PCM512x if SND_SOC_I2C_AND_SPI - select SND_SOC_RT5631 if I2C - select SND_SOC_RT5640 if I2C - select SND_SOC_SGTL5000 if I2C -@@ -321,6 +322,9 @@ config SND_SOC_PCM1794A - config SND_SOC_PCM5102A - tristate - -+config SND_SOC_PCM512x -+ tristate -+ - config SND_SOC_RT5631 - tristate - ---- a/sound/soc/codecs/Makefile -+++ b/sound/soc/codecs/Makefile -@@ -48,6 +48,7 @@ snd-soc-pcm1792a-codec-objs := pcm1792a. - snd-soc-pcm3008-objs := pcm3008.o - snd-soc-pcm1794a-objs := pcm1794a.o - snd-soc-pcm5102a-objs := pcm5102a.o -+snd-soc-pcm512x-objs := pcm512x.o - snd-soc-rt5631-objs := rt5631.o - snd-soc-rt5640-objs := rt5640.o - snd-soc-sgtl5000-objs := sgtl5000.o -@@ -183,6 +184,7 @@ obj-$(CONFIG_SND_SOC_PCM1792A) += snd-so - obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o - obj-$(CONFIG_SND_SOC_PCM1794A) += snd-soc-pcm1794a.o - obj-$(CONFIG_SND_SOC_PCM5102A) += snd-soc-pcm5102a.o -+obj-$(CONFIG_SND_SOC_PCM512x) += snd-soc-pcm512x.o - obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o - obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o - obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o ---- /dev/null -+++ b/sound/soc/codecs/pcm512x.c -@@ -0,0 +1,677 @@ -+/* -+ * Driver for the PCM512x CODECs -+ * -+ * Author: Mark Brown -+ * Copyright 2014 Linaro Ltd -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ */ -+ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "pcm512x.h" -+ -+#define PCM512x_NUM_SUPPLIES 3 -+static const char *pcm512x_supply_names[PCM512x_NUM_SUPPLIES] = { -+ "AVDD", -+ "DVDD", -+ "CPVDD", -+}; -+ -+struct pcm512x_priv { -+ struct regmap *regmap; -+ struct clk *sclk; -+ struct regulator_bulk_data supplies[PCM512x_NUM_SUPPLIES]; -+ struct notifier_block supply_nb[PCM512x_NUM_SUPPLIES]; -+}; -+ -+/* -+ * We can't use the same notifier block for more than one supply and -+ * there's no way I can see to get from a callback to the caller -+ * except container_of(). -+ */ -+#define PCM512x_REGULATOR_EVENT(n) \ -+static int pcm512x_regulator_event_##n(struct notifier_block *nb, \ -+ unsigned long event, void *data) \ -+{ \ -+ struct pcm512x_priv *pcm512x = container_of(nb, struct pcm512x_priv, \ -+ supply_nb[n]); \ -+ if (event & REGULATOR_EVENT_DISABLE) { \ -+ regcache_mark_dirty(pcm512x->regmap); \ -+ regcache_cache_only(pcm512x->regmap, true); \ -+ } \ -+ return 0; \ -+} -+ -+PCM512x_REGULATOR_EVENT(0) -+PCM512x_REGULATOR_EVENT(1) -+PCM512x_REGULATOR_EVENT(2) -+ -+static const struct reg_default pcm512x_reg_defaults[] = { -+ { PCM512x_RESET, 0x00 }, -+ { PCM512x_POWER, 0x00 }, -+ { PCM512x_MUTE, 0x00 }, -+ { PCM512x_DSP, 0x00 }, -+ { PCM512x_PLL_REF, 0x00 }, -+ { PCM512x_DAC_ROUTING, 0x11 }, -+ { PCM512x_DSP_PROGRAM, 0x01 }, -+ { PCM512x_CLKDET, 0x00 }, -+ { PCM512x_AUTO_MUTE, 0x00 }, -+ { PCM512x_ERROR_DETECT, 0x00 }, -+ { PCM512x_DIGITAL_VOLUME_1, 0x00 }, -+ { PCM512x_DIGITAL_VOLUME_2, 0x30 }, -+ { PCM512x_DIGITAL_VOLUME_3, 0x30 }, -+ { PCM512x_DIGITAL_MUTE_1, 0x22 }, -+ { PCM512x_DIGITAL_MUTE_2, 0x00 }, -+ { PCM512x_DIGITAL_MUTE_3, 0x07 }, -+}; -+ -+static bool pcm512x_readable(struct device *dev, unsigned int reg) -+{ -+ switch (reg) { -+ case PCM512x_RESET: -+ case PCM512x_POWER: -+ case PCM512x_MUTE: -+ case PCM512x_PLL_EN: -+ case PCM512x_SPI_MISO_FUNCTION: -+ case PCM512x_DSP: -+ case PCM512x_GPIO_EN: -+ case PCM512x_BCLK_LRCLK_CFG: -+ case PCM512x_DSP_GPIO_INPUT: -+ case PCM512x_MASTER_MODE: -+ case PCM512x_PLL_REF: -+ case PCM512x_PLL_COEFF_0: -+ case PCM512x_PLL_COEFF_1: -+ case PCM512x_PLL_COEFF_2: -+ case PCM512x_PLL_COEFF_3: -+ case PCM512x_PLL_COEFF_4: -+ case PCM512x_DSP_CLKDIV: -+ case PCM512x_DAC_CLKDIV: -+ case PCM512x_NCP_CLKDIV: -+ case PCM512x_OSR_CLKDIV: -+ case PCM512x_MASTER_CLKDIV_1: -+ case PCM512x_MASTER_CLKDIV_2: -+ case PCM512x_FS_SPEED_MODE: -+ case PCM512x_IDAC_1: -+ case PCM512x_IDAC_2: -+ case PCM512x_ERROR_DETECT: -+ case PCM512x_I2S_1: -+ case PCM512x_I2S_2: -+ case PCM512x_DAC_ROUTING: -+ case PCM512x_DSP_PROGRAM: -+ case PCM512x_CLKDET: -+ case PCM512x_AUTO_MUTE: -+ case PCM512x_DIGITAL_VOLUME_1: -+ case PCM512x_DIGITAL_VOLUME_2: -+ case PCM512x_DIGITAL_VOLUME_3: -+ case PCM512x_DIGITAL_MUTE_1: -+ case PCM512x_DIGITAL_MUTE_2: -+ case PCM512x_DIGITAL_MUTE_3: -+ case PCM512x_GPIO_OUTPUT_1: -+ case PCM512x_GPIO_OUTPUT_2: -+ case PCM512x_GPIO_OUTPUT_3: -+ case PCM512x_GPIO_OUTPUT_4: -+ case PCM512x_GPIO_OUTPUT_5: -+ case PCM512x_GPIO_OUTPUT_6: -+ case PCM512x_GPIO_CONTROL_1: -+ case PCM512x_GPIO_CONTROL_2: -+ case PCM512x_OVERFLOW: -+ case PCM512x_RATE_DET_1: -+ case PCM512x_RATE_DET_2: -+ case PCM512x_RATE_DET_3: -+ case PCM512x_RATE_DET_4: -+ case PCM512x_ANALOG_MUTE_DET: -+ case PCM512x_GPIN: -+ case PCM512x_DIGITAL_MUTE_DET: -+ return true; -+ default: -+ return false; -+ } -+} -+ -+static bool pcm512x_volatile(struct device *dev, unsigned int reg) -+{ -+ switch (reg) { -+ case PCM512x_PLL_EN: -+ case PCM512x_OVERFLOW: -+ case PCM512x_RATE_DET_1: -+ case PCM512x_RATE_DET_2: -+ case PCM512x_RATE_DET_3: -+ case PCM512x_RATE_DET_4: -+ case PCM512x_ANALOG_MUTE_DET: -+ case PCM512x_GPIN: -+ case PCM512x_DIGITAL_MUTE_DET: -+ return true; -+ default: -+ return false; -+ } -+} -+ -+static const DECLARE_TLV_DB_SCALE(digital_tlv, -10350, 50, 1); -+ -+static const char *pcm512x_dsp_program_texts[] = { -+ "FIR interpolation with de-emphasis", -+ "Low latency IIR with de-emphasis", -+ "High attenuation with de-emphasis", -+ "Ringing-less low latency FIR", -+}; -+ -+static const unsigned int pcm512x_dsp_program_values[] = { -+ 1, -+ 2, -+ 3, -+ 5, -+ 7, -+}; -+ -+static const SOC_VALUE_ENUM_SINGLE_DECL(pcm512x_dsp_program, -+ PCM512x_DSP_PROGRAM, 0, 0x1f, -+ pcm512x_dsp_program_texts, -+ pcm512x_dsp_program_values); -+ -+static const char *pcm512x_clk_missing_text[] = { -+ "1s", "2s", "3s", "4s", "5s", "6s", "7s", "8s" -+}; -+ -+static const struct soc_enum pcm512x_clk_missing = -+ SOC_ENUM_SINGLE(PCM512x_CLKDET, 0, 7, pcm512x_clk_missing_text); -+ -+static const char *pcm512x_autom_text[] = { -+ "21ms", "106ms", "213ms", "533ms", "1.07s", "2.13s", "5.33s", "10.66s" -+}; -+ -+static const struct soc_enum pcm512x_autom_l = -+ SOC_ENUM_SINGLE(PCM512x_AUTO_MUTE, PCM512x_ATML_SHIFT, 7, -+ pcm512x_autom_text); -+ -+static const struct soc_enum pcm512x_autom_r = -+ SOC_ENUM_SINGLE(PCM512x_AUTO_MUTE, PCM512x_ATMR_SHIFT, 7, -+ pcm512x_autom_text); -+ -+static const char *pcm512x_ramp_rate_text[] = { -+ "1 sample/update", "2 samples/update", "4 samples/update", -+ "Immediate" -+}; -+ -+static const struct soc_enum pcm512x_vndf = -+ SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNDF_SHIFT, 4, -+ pcm512x_ramp_rate_text); -+ -+static const struct soc_enum pcm512x_vnuf = -+ SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNUF_SHIFT, 4, -+ pcm512x_ramp_rate_text); -+ -+static const struct soc_enum pcm512x_vedf = -+ SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_2, PCM512x_VEDF_SHIFT, 4, -+ pcm512x_ramp_rate_text); -+ -+static const char *pcm512x_ramp_step_text[] = { -+ "4dB/step", "2dB/step", "1dB/step", "0.5dB/step" -+}; -+ -+static const struct soc_enum pcm512x_vnds = -+ SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNDS_SHIFT, 4, -+ pcm512x_ramp_step_text); -+ -+static const struct soc_enum pcm512x_vnus = -+ SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNUS_SHIFT, 4, -+ pcm512x_ramp_step_text); -+ -+static const struct soc_enum pcm512x_veds = -+ SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_2, PCM512x_VEDS_SHIFT, 4, -+ pcm512x_ramp_step_text); -+ -+static const struct snd_kcontrol_new pcm512x_controls[] = { -+SOC_DOUBLE_R_TLV("Playback Digital Volume", PCM512x_DIGITAL_VOLUME_2, -+ PCM512x_DIGITAL_VOLUME_3, 0, 255, 1, digital_tlv), -+SOC_DOUBLE("Playback Digital Switch", PCM512x_MUTE, PCM512x_RQML_SHIFT, -+ PCM512x_RQMR_SHIFT, 1, 1), -+ -+SOC_SINGLE("Deemphasis Switch", PCM512x_DSP, PCM512x_DEMP_SHIFT, 1, 1), -+SOC_VALUE_ENUM("DSP Program", pcm512x_dsp_program), -+ -+SOC_ENUM("Clock Missing Period", pcm512x_clk_missing), -+SOC_ENUM("Auto Mute Time Left", pcm512x_autom_l), -+SOC_ENUM("Auto Mute Time Right", pcm512x_autom_r), -+SOC_SINGLE("Auto Mute Mono Switch", PCM512x_DIGITAL_MUTE_3, -+ PCM512x_ACTL_SHIFT, 1, 0), -+SOC_DOUBLE("Auto Mute Switch", PCM512x_DIGITAL_MUTE_3, PCM512x_AMLE_SHIFT, -+ PCM512x_AMLR_SHIFT, 1, 0), -+ -+SOC_ENUM("Volume Ramp Down Rate", pcm512x_vndf), -+SOC_ENUM("Volume Ramp Down Step", pcm512x_vnds), -+SOC_ENUM("Volume Ramp Up Rate", pcm512x_vnuf), -+SOC_ENUM("Volume Ramp Up Step", pcm512x_vnus), -+SOC_ENUM("Volume Ramp Down Emergency Rate", pcm512x_vedf), -+SOC_ENUM("Volume Ramp Down Emergency Step", pcm512x_veds), -+}; -+ -+static const struct snd_soc_dapm_widget pcm512x_dapm_widgets[] = { -+SND_SOC_DAPM_DAC("DACL", NULL, SND_SOC_NOPM, 0, 0), -+SND_SOC_DAPM_DAC("DACR", NULL, SND_SOC_NOPM, 0, 0), -+ -+SND_SOC_DAPM_OUTPUT("OUTL"), -+SND_SOC_DAPM_OUTPUT("OUTR"), -+}; -+ -+static const struct snd_soc_dapm_route pcm512x_dapm_routes[] = { -+ { "DACL", NULL, "Playback" }, -+ { "DACR", NULL, "Playback" }, -+ -+ { "OUTL", NULL, "DACL" }, -+ { "OUTR", NULL, "DACR" }, -+}; -+ -+static int pcm512x_set_bias_level(struct snd_soc_codec *codec, -+ enum snd_soc_bias_level level) -+{ -+ struct pcm512x_priv *pcm512x = dev_get_drvdata(codec->dev); -+ int ret; -+ -+ switch (level) { -+ case SND_SOC_BIAS_ON: -+ case SND_SOC_BIAS_PREPARE: -+ break; -+ -+ case SND_SOC_BIAS_STANDBY: -+ ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER, -+ PCM512x_RQST, 0); -+ if (ret != 0) { -+ dev_err(codec->dev, "Failed to remove standby: %d\n", -+ ret); -+ return ret; -+ } -+ break; -+ -+ case SND_SOC_BIAS_OFF: -+ ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER, -+ PCM512x_RQST, PCM512x_RQST); -+ if (ret != 0) { -+ dev_err(codec->dev, "Failed to request standby: %d\n", -+ ret); -+ return ret; -+ } -+ break; -+ } -+ -+ codec->dapm.bias_level = level; -+ -+ return 0; -+} -+ -+static struct snd_soc_dai_driver pcm512x_dai = { -+ .name = "pcm512x-hifi", -+ .playback = { -+ .stream_name = "Playback", -+ .channels_min = 2, -+ .channels_max = 2, -+ .rates = SNDRV_PCM_RATE_8000_192000, -+ .formats = SNDRV_PCM_FMTBIT_S16_LE | -+ SNDRV_PCM_FMTBIT_S24_LE | -+ SNDRV_PCM_FMTBIT_S32_LE -+ }, -+}; -+ -+static struct snd_soc_codec_driver pcm512x_codec_driver = { -+ .set_bias_level = pcm512x_set_bias_level, -+ .idle_bias_off = true, -+ -+ .controls = pcm512x_controls, -+ .num_controls = ARRAY_SIZE(pcm512x_controls), -+ .dapm_widgets = pcm512x_dapm_widgets, -+ .num_dapm_widgets = ARRAY_SIZE(pcm512x_dapm_widgets), -+ .dapm_routes = pcm512x_dapm_routes, -+ .num_dapm_routes = ARRAY_SIZE(pcm512x_dapm_routes), -+}; -+ -+static const struct regmap_config pcm512x_regmap = { -+ .reg_bits = 8, -+ .val_bits = 8, -+ -+ .readable_reg = pcm512x_readable, -+ .volatile_reg = pcm512x_volatile, -+ -+ .max_register = PCM512x_MAX_REGISTER, -+ .reg_defaults = pcm512x_reg_defaults, -+ .num_reg_defaults = ARRAY_SIZE(pcm512x_reg_defaults), -+ .cache_type = REGCACHE_RBTREE, -+}; -+ -+static const struct of_device_id pcm512x_of_match[] = { -+ { .compatible = "ti,pcm5121", }, -+ { .compatible = "ti,pcm5122", }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, pcm512x_of_match); -+ -+static int pcm512x_probe(struct device *dev, struct regmap *regmap) -+{ -+ struct pcm512x_priv *pcm512x; -+ int i, ret; -+ -+ pcm512x = devm_kzalloc(dev, sizeof(struct pcm512x_priv), GFP_KERNEL); -+ if (!pcm512x) -+ return -ENOMEM; -+ -+ dev_set_drvdata(dev, pcm512x); -+ pcm512x->regmap = regmap; -+ -+ for (i = 0; i < ARRAY_SIZE(pcm512x->supplies); i++) -+ pcm512x->supplies[i].supply = pcm512x_supply_names[i]; -+ -+ ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(pcm512x->supplies), -+ pcm512x->supplies); -+ if (ret != 0) { -+ dev_err(dev, "Failed to get supplies: %d\n", ret); -+ return ret; -+ } -+ -+ pcm512x->supply_nb[0].notifier_call = pcm512x_regulator_event_0; -+ pcm512x->supply_nb[1].notifier_call = pcm512x_regulator_event_1; -+ pcm512x->supply_nb[2].notifier_call = pcm512x_regulator_event_2; -+ -+ for (i = 0; i < ARRAY_SIZE(pcm512x->supplies); i++) { -+ ret = regulator_register_notifier(pcm512x->supplies[i].consumer, -+ &pcm512x->supply_nb[i]); -+ if (ret != 0) { -+ dev_err(dev, -+ "Failed to register regulator notifier: %d\n", -+ ret); -+ } -+ } -+ -+ ret = regulator_bulk_enable(ARRAY_SIZE(pcm512x->supplies), -+ pcm512x->supplies); -+ if (ret != 0) { -+ dev_err(dev, "Failed to enable supplies: %d\n", ret); -+ return ret; -+ } -+ -+ /* Reset the device, verifying I/O in the process for I2C */ -+ ret = regmap_write(regmap, PCM512x_RESET, -+ PCM512x_RSTM | PCM512x_RSTR); -+ if (ret != 0) { -+ dev_err(dev, "Failed to reset device: %d\n", ret); -+ goto err; -+ } -+ -+ ret = regmap_write(regmap, PCM512x_RESET, 0); -+ if (ret != 0) { -+ dev_err(dev, "Failed to reset device: %d\n", ret); -+ goto err; -+ } -+ -+ pcm512x->sclk = devm_clk_get(dev, NULL); -+ if (IS_ERR(pcm512x->sclk)) { -+ if (PTR_ERR(pcm512x->sclk) == -EPROBE_DEFER) -+ return -EPROBE_DEFER; -+ -+ dev_info(dev, "No SCLK, using BCLK: %ld\n", -+ PTR_ERR(pcm512x->sclk)); -+ -+ /* Disable reporting of missing SCLK as an error */ -+ regmap_update_bits(regmap, PCM512x_ERROR_DETECT, -+ PCM512x_IDCH, PCM512x_IDCH); -+ -+ /* Switch PLL input to BCLK */ -+ regmap_update_bits(regmap, PCM512x_PLL_REF, -+ PCM512x_SREF, PCM512x_SREF); -+ } else { -+ ret = clk_prepare_enable(pcm512x->sclk); -+ if (ret != 0) { -+ dev_err(dev, "Failed to enable SCLK: %d\n", ret); -+ return ret; -+ } -+ } -+ -+ /* Default to standby mode */ -+ ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER, -+ PCM512x_RQST, PCM512x_RQST); -+ if (ret != 0) { -+ dev_err(dev, "Failed to request standby: %d\n", -+ ret); -+ goto err_clk; -+ } -+ -+ pm_runtime_set_active(dev); -+ pm_runtime_enable(dev); -+ pm_runtime_idle(dev); -+ -+ ret = snd_soc_register_codec(dev, &pcm512x_codec_driver, -+ &pcm512x_dai, 1); -+ if (ret != 0) { -+ dev_err(dev, "Failed to register CODEC: %d\n", ret); -+ goto err_pm; -+ } -+ -+ dev_info(dev, "Completed initialisation - pcm512x_probe"); -+ -+ return 0; -+ -+err_pm: -+ pm_runtime_disable(dev); -+err_clk: -+ if (!IS_ERR(pcm512x->sclk)) -+ clk_disable_unprepare(pcm512x->sclk); -+err: -+ regulator_bulk_disable(ARRAY_SIZE(pcm512x->supplies), -+ pcm512x->supplies); -+ return ret; -+} -+ -+static void pcm512x_remove(struct device *dev) -+{ -+ struct pcm512x_priv *pcm512x = dev_get_drvdata(dev); -+ -+ snd_soc_unregister_codec(dev); -+ pm_runtime_disable(dev); -+ if (!IS_ERR(pcm512x->sclk)) -+ clk_disable_unprepare(pcm512x->sclk); -+ regulator_bulk_disable(ARRAY_SIZE(pcm512x->supplies), -+ pcm512x->supplies); -+} -+ -+/* TODO -+static int pcm512x_suspend(struct device *dev) -+{ -+ struct pcm512x_priv *pcm512x = dev_get_drvdata(dev); -+ int ret; -+ -+ ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER, -+ PCM512x_RQPD, PCM512x_RQPD); -+ if (ret != 0) { -+ dev_err(dev, "Failed to request power down: %d\n", ret); -+ return ret; -+ } -+ -+ ret = regulator_bulk_disable(ARRAY_SIZE(pcm512x->supplies), -+ pcm512x->supplies); -+ if (ret != 0) { -+ dev_err(dev, "Failed to disable supplies: %d\n", ret); -+ return ret; -+ } -+ -+ if (!IS_ERR(pcm512x->sclk)) -+ clk_disable_unprepare(pcm512x->sclk); -+ -+ return 0; -+} -+ -+static int pcm512x_resume(struct device *dev) -+{ -+ struct pcm512x_priv *pcm512x = dev_get_drvdata(dev); -+ int ret; -+ -+ if (!IS_ERR(pcm512x->sclk)) { -+ ret = clk_prepare_enable(pcm512x->sclk); -+ if (ret != 0) { -+ dev_err(dev, "Failed to enable SCLK: %d\n", ret); -+ return ret; -+ } -+ } -+ -+ ret = regulator_bulk_enable(ARRAY_SIZE(pcm512x->supplies), -+ pcm512x->supplies); -+ if (ret != 0) { -+ dev_err(dev, "Failed to enable supplies: %d\n", ret); -+ return ret; -+ } -+ -+ regcache_cache_only(pcm512x->regmap, false); -+ ret = regcache_sync(pcm512x->regmap); -+ if (ret != 0) { -+ dev_err(dev, "Failed to sync cache: %d\n", ret); -+ return ret; -+ } -+ -+ ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER, -+ PCM512x_RQPD, 0); -+ if (ret != 0) { -+ dev_err(dev, "Failed to remove power down: %d\n", ret); -+ return ret; -+ } -+ -+ return 0; -+} -+ -+// END OF PCM512x_suspend and resume calls TODO -+*/ -+ -+static const struct dev_pm_ops pcm512x_pm_ops = { -+ SET_RUNTIME_PM_OPS(pcm512x_suspend, pcm512x_resume, NULL) -+}; -+ -+#if IS_ENABLED(CONFIG_I2C) -+static int pcm512x_i2c_probe(struct i2c_client *i2c, -+ const struct i2c_device_id *id) -+{ -+ struct regmap *regmap; -+ -+ regmap = devm_regmap_init_i2c(i2c, &pcm512x_regmap); -+ if (IS_ERR(regmap)) -+ return PTR_ERR(regmap); -+ -+ return pcm512x_probe(&i2c->dev, regmap); -+} -+ -+static int pcm512x_i2c_remove(struct i2c_client *i2c) -+{ -+ pcm512x_remove(&i2c->dev); -+ return 0; -+} -+ -+static const struct i2c_device_id pcm512x_i2c_id[] = { -+ { "pcm5121", }, -+ { "pcm5122", }, -+ { } -+}; -+MODULE_DEVICE_TABLE(i2c, pcm512x_i2c_id); -+ -+static struct i2c_driver pcm512x_i2c_driver = { -+ .probe = pcm512x_i2c_probe, -+ .remove = pcm512x_i2c_remove, -+ .id_table = pcm512x_i2c_id, -+ .driver = { -+ .name = "pcm512x", -+ .owner = THIS_MODULE, -+ .of_match_table = pcm512x_of_match, -+ .pm = &pcm512x_pm_ops, -+ }, -+}; -+#endif -+ -+#if defined(CONFIG_SPI_MASTER) -+static int pcm512x_spi_probe(struct spi_device *spi) -+{ -+ struct regmap *regmap; -+ int ret; -+ -+ regmap = devm_regmap_init_spi(spi, &pcm512x_regmap); -+ if (IS_ERR(regmap)) { -+ ret = PTR_ERR(regmap); -+ return ret; -+ } -+ -+ return pcm512x_probe(&spi->dev, regmap); -+} -+ -+static int pcm512x_spi_remove(struct spi_device *spi) -+{ -+ pcm512x_remove(&spi->dev); -+ return 0; -+} -+ -+static const struct spi_device_id pcm512x_spi_id[] = { -+ { "pcm5121", }, -+ { "pcm5122", }, -+ { }, -+}; -+MODULE_DEVICE_TABLE(spi, pcm512x_spi_id); -+ -+static struct spi_driver pcm512x_spi_driver = { -+ .probe = pcm512x_spi_probe, -+ .remove = pcm512x_spi_remove, -+ .id_table = pcm512x_spi_id, -+ .driver = { -+ .name = "pcm512x", -+ .owner = THIS_MODULE, -+ .of_match_table = pcm512x_of_match, -+ .pm = &pcm512x_pm_ops, -+ }, -+}; -+#endif -+ -+static int __init pcm512x_modinit(void) -+{ -+ int ret = 0; -+ -+#if IS_ENABLED(CONFIG_I2C) -+ ret = i2c_add_driver(&pcm512x_i2c_driver); -+ if (ret) { -+ printk(KERN_ERR "Failed to register pcm512x I2C driver: %d\n", -+ ret); -+ } -+#endif -+#if defined(CONFIG_SPI_MASTER) -+ ret = spi_register_driver(&pcm512x_spi_driver); -+ if (ret != 0) { -+ printk(KERN_ERR "Failed to register pcm512x SPI driver: %d\n", -+ ret); -+ } -+#endif -+ return ret; -+} -+module_init(pcm512x_modinit); -+ -+static void __exit pcm512x_exit(void) -+{ -+#if IS_ENABLED(CONFIG_I2C) -+ i2c_del_driver(&pcm512x_i2c_driver); -+#endif -+#if defined(CONFIG_SPI_MASTER) -+ spi_unregister_driver(&pcm512x_spi_driver); -+#endif -+} -+module_exit(pcm512x_exit); -+ -+MODULE_DESCRIPTION("ASoC PCM512x codec driver"); -+MODULE_AUTHOR("Mark Brown "); -+MODULE_LICENSE("GPL v2"); ---- /dev/null -+++ b/sound/soc/codecs/pcm512x.h -@@ -0,0 +1,142 @@ -+/* -+ * Driver for the PCM512x CODECs -+ * -+ * Author: Mark Brown -+ * Copyright 2014 Linaro Ltd -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ */ -+ -+#ifndef _SND_SOC_PCM512X -+#define _SND_SOC_PCM512X -+ -+#define PCM512x_PAGE_0_BASE 0 -+ -+#define PCM512x_PAGE 0 -+ -+#define PCM512x_RESET (PCM512x_PAGE_0_BASE + 1) -+#define PCM512x_POWER (PCM512x_PAGE_0_BASE + 2) -+#define PCM512x_MUTE (PCM512x_PAGE_0_BASE + 3) -+#define PCM512x_PLL_EN (PCM512x_PAGE_0_BASE + 4) -+#define PCM512x_SPI_MISO_FUNCTION (PCM512x_PAGE_0_BASE + 6) -+#define PCM512x_DSP (PCM512x_PAGE_0_BASE + 7) -+#define PCM512x_GPIO_EN (PCM512x_PAGE_0_BASE + 8) -+#define PCM512x_BCLK_LRCLK_CFG (PCM512x_PAGE_0_BASE + 9) -+#define PCM512x_DSP_GPIO_INPUT (PCM512x_PAGE_0_BASE + 10) -+#define PCM512x_MASTER_MODE (PCM512x_PAGE_0_BASE + 12) -+#define PCM512x_PLL_REF (PCM512x_PAGE_0_BASE + 13) -+#define PCM512x_PLL_COEFF_0 (PCM512x_PAGE_0_BASE + 20) -+#define PCM512x_PLL_COEFF_1 (PCM512x_PAGE_0_BASE + 21) -+#define PCM512x_PLL_COEFF_2 (PCM512x_PAGE_0_BASE + 22) -+#define PCM512x_PLL_COEFF_3 (PCM512x_PAGE_0_BASE + 23) -+#define PCM512x_PLL_COEFF_4 (PCM512x_PAGE_0_BASE + 24) -+#define PCM512x_DSP_CLKDIV (PCM512x_PAGE_0_BASE + 27) -+#define PCM512x_DAC_CLKDIV (PCM512x_PAGE_0_BASE + 28) -+#define PCM512x_NCP_CLKDIV (PCM512x_PAGE_0_BASE + 29) -+#define PCM512x_OSR_CLKDIV (PCM512x_PAGE_0_BASE + 30) -+#define PCM512x_MASTER_CLKDIV_1 (PCM512x_PAGE_0_BASE + 32) -+#define PCM512x_MASTER_CLKDIV_2 (PCM512x_PAGE_0_BASE + 33) -+#define PCM512x_FS_SPEED_MODE (PCM512x_PAGE_0_BASE + 34) -+#define PCM512x_IDAC_1 (PCM512x_PAGE_0_BASE + 35) -+#define PCM512x_IDAC_2 (PCM512x_PAGE_0_BASE + 36) -+#define PCM512x_ERROR_DETECT (PCM512x_PAGE_0_BASE + 37) -+#define PCM512x_I2S_1 (PCM512x_PAGE_0_BASE + 40) -+#define PCM512x_I2S_2 (PCM512x_PAGE_0_BASE + 41) -+#define PCM512x_DAC_ROUTING (PCM512x_PAGE_0_BASE + 42) -+#define PCM512x_DSP_PROGRAM (PCM512x_PAGE_0_BASE + 43) -+#define PCM512x_CLKDET (PCM512x_PAGE_0_BASE + 44) -+#define PCM512x_AUTO_MUTE (PCM512x_PAGE_0_BASE + 59) -+#define PCM512x_DIGITAL_VOLUME_1 (PCM512x_PAGE_0_BASE + 60) -+#define PCM512x_DIGITAL_VOLUME_2 (PCM512x_PAGE_0_BASE + 61) -+#define PCM512x_DIGITAL_VOLUME_3 (PCM512x_PAGE_0_BASE + 62) -+#define PCM512x_DIGITAL_MUTE_1 (PCM512x_PAGE_0_BASE + 63) -+#define PCM512x_DIGITAL_MUTE_2 (PCM512x_PAGE_0_BASE + 64) -+#define PCM512x_DIGITAL_MUTE_3 (PCM512x_PAGE_0_BASE + 65) -+#define PCM512x_GPIO_OUTPUT_1 (PCM512x_PAGE_0_BASE + 80) -+#define PCM512x_GPIO_OUTPUT_2 (PCM512x_PAGE_0_BASE + 81) -+#define PCM512x_GPIO_OUTPUT_3 (PCM512x_PAGE_0_BASE + 82) -+#define PCM512x_GPIO_OUTPUT_4 (PCM512x_PAGE_0_BASE + 83) -+#define PCM512x_GPIO_OUTPUT_5 (PCM512x_PAGE_0_BASE + 84) -+#define PCM512x_GPIO_OUTPUT_6 (PCM512x_PAGE_0_BASE + 85) -+#define PCM512x_GPIO_CONTROL_1 (PCM512x_PAGE_0_BASE + 86) -+#define PCM512x_GPIO_CONTROL_2 (PCM512x_PAGE_0_BASE + 87) -+#define PCM512x_OVERFLOW (PCM512x_PAGE_0_BASE + 90) -+#define PCM512x_RATE_DET_1 (PCM512x_PAGE_0_BASE + 91) -+#define PCM512x_RATE_DET_2 (PCM512x_PAGE_0_BASE + 92) -+#define PCM512x_RATE_DET_3 (PCM512x_PAGE_0_BASE + 93) -+#define PCM512x_RATE_DET_4 (PCM512x_PAGE_0_BASE + 94) -+#define PCM512x_ANALOG_MUTE_DET (PCM512x_PAGE_0_BASE + 108) -+#define PCM512x_GPIN (PCM512x_PAGE_0_BASE + 119) -+#define PCM512x_DIGITAL_MUTE_DET (PCM512x_PAGE_0_BASE + 120) -+ -+#define PCM512x_MAX_REGISTER (PCM512x_PAGE_0_BASE + 120) -+ -+/* Page 0, Register 1 - reset */ -+#define PCM512x_RSTR (1 << 0) -+#define PCM512x_RSTM (1 << 4) -+ -+/* Page 0, Register 2 - power */ -+#define PCM512x_RQPD (1 << 0) -+#define PCM512x_RQPD_SHIFT 0 -+#define PCM512x_RQST (1 << 4) -+#define PCM512x_RQST_SHIFT 4 -+ -+/* Page 0, Register 3 - mute */ -+#define PCM512x_RQMR_SHIFT 0 -+#define PCM512x_RQML_SHIFT 4 -+ -+/* Page 0, Register 4 - PLL */ -+#define PCM512x_PLCE (1 << 0) -+#define PCM512x_RLCE_SHIFT 0 -+#define PCM512x_PLCK (1 << 4) -+#define PCM512x_PLCK_SHIFT 4 -+ -+/* Page 0, Register 7 - DSP */ -+#define PCM512x_SDSL (1 << 0) -+#define PCM512x_SDSL_SHIFT 0 -+#define PCM512x_DEMP (1 << 4) -+#define PCM512x_DEMP_SHIFT 4 -+ -+/* Page 0, Register 13 - PLL reference */ -+#define PCM512x_SREF (1 << 4) -+ -+/* Page 0, Register 37 - Error detection */ -+#define PCM512x_IPLK (1 << 0) -+#define PCM512x_DCAS (1 << 1) -+#define PCM512x_IDCM (1 << 2) -+#define PCM512x_IDCH (1 << 3) -+#define PCM512x_IDSK (1 << 4) -+#define PCM512x_IDBK (1 << 5) -+#define PCM512x_IDFS (1 << 6) -+ -+/* Page 0, Register 42 - DAC routing */ -+#define PCM512x_AUPR_SHIFT 0 -+#define PCM512x_AUPL_SHIFT 4 -+ -+/* Page 0, Register 59 - auto mute */ -+#define PCM512x_ATMR_SHIFT 0 -+#define PCM512x_ATML_SHIFT 4 -+ -+/* Page 0, Register 63 - ramp rates */ -+#define PCM512x_VNDF_SHIFT 6 -+#define PCM512x_VNDS_SHIFT 4 -+#define PCM512x_VNUF_SHIFT 2 -+#define PCM512x_VNUS_SHIFT 0 -+ -+/* Page 0, Register 64 - emergency ramp rates */ -+#define PCM512x_VEDF_SHIFT 6 -+#define PCM512x_VEDS_SHIFT 4 -+ -+/* Page 0, Register 65 - Digital mute enables */ -+#define PCM512x_ACTL_SHIFT 2 -+#define PCM512x_AMLE_SHIFT 1 -+#define PCM512x_AMLR_SHIFT 0 -+ -+#endif -- cgit v1.2.3