Alsa-devel
Threads by month
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
August 2013
- 112 participants
- 278 discussions
[alsa-devel] [PATCH 1/5] ASoC: Add ADAU1X61 and ADAU1X81 CODECs common code
by Lars-Peter Clausen 29 Aug '13
by Lars-Peter Clausen 29 Aug '13
29 Aug '13
The ADAU1X61 and ADAU1X81 are very similar in the digital domain, but are quite
different in the analog domain. This patch adds support for the common parts of
the ADAU1X61 and ADAU1X81 CODECs.
Signed-off-by: Lars-Peter Clausen <lars(a)metafoo.de>
---
include/linux/platform_data/adau17x1.h | 23 +
sound/soc/codecs/Kconfig | 4 +
sound/soc/codecs/Makefile | 2 +
sound/soc/codecs/adau17x1.c | 895 +++++++++++++++++++++++++++++++++
sound/soc/codecs/adau17x1.h | 148 ++++++
5 files changed, 1072 insertions(+)
create mode 100644 include/linux/platform_data/adau17x1.h
create mode 100644 sound/soc/codecs/adau17x1.c
create mode 100644 sound/soc/codecs/adau17x1.h
diff --git a/include/linux/platform_data/adau17x1.h b/include/linux/platform_data/adau17x1.h
new file mode 100644
index 0000000..fdf419a
--- /dev/null
+++ b/include/linux/platform_data/adau17x1.h
@@ -0,0 +1,23 @@
+/*
+ * Driver for ADAU1761/ADAU1461/ADAU1761/ADAU1961/ADAU1781/ADAU1781 codecs
+ *
+ * Copyright 2011-2013 Analog Devices Inc.
+ * Author: Lars-Peter Clausen <lars(a)metafoo.de>
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef __LINUX_PLATFORM_DATA_ADAU17X1_H__
+#define __LINUX_PLATFORM_DATA_ADAU17X1_H__
+
+/**
+ * enum adau17x1_micbias_voltage - Microphone bias voltage
+ * @ADAU17X1_MICBIAS_0_90_AVDD: 0.9 * AVDD
+ * @ADAU17X1_MICBIAS_0_65_AVDD: 0.65 * AVDD
+ */
+enum adau17x1_micbias_voltage {
+ ADAU17X1_MICBIAS_0_90_AVDD = 0,
+ ADAU17X1_MICBIAS_0_65_AVDD = 1,
+};
+
+#endif
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 15106c0..56137d4 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -193,6 +193,10 @@ config SND_SOC_ADAU1701
config SND_SOC_ADAU1373
tristate
+config SND_SOC_ADAU17X1
+ select SND_SOC_SIGMADSP
+ tristate
+
config SND_SOC_ADAV80X
tristate
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index bc12676..b4ecf6c 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -7,6 +7,7 @@ snd-soc-ad1980-objs := ad1980.o
snd-soc-ad73311-objs := ad73311.o
snd-soc-adau1701-objs := adau1701.o
snd-soc-adau1373-objs := adau1373.o
+snd-soc-adau17x1-objs := adau17x1.o
snd-soc-adav80x-objs := adav80x.o
snd-soc-ads117x-objs := ads117x.o
snd-soc-ak4104-objs := ak4104.o
@@ -138,6 +139,7 @@ obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o
obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.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
obj-$(CONFIG_SND_SOC_ADAV80X) += snd-soc-adav80x.o
obj-$(CONFIG_SND_SOC_ADS117X) += snd-soc-ads117x.o
obj-$(CONFIG_SND_SOC_AK4104) += snd-soc-ak4104.o
diff --git a/sound/soc/codecs/adau17x1.c b/sound/soc/codecs/adau17x1.c
new file mode 100644
index 0000000..b7d678d
--- /dev/null
+++ b/sound/soc/codecs/adau17x1.c
@@ -0,0 +1,895 @@
+/*
+ * Common code for ADAU1X61 and ADAU1X81 codecs
+ *
+ * Copyright 2011-2013 Analog Devices Inc.
+ * Author: Lars-Peter Clausen <lars(a)metafoo.de>
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/tlv.h>
+#include <linux/gcd.h>
+#include <linux/i2c.h>
+#include <linux/spi/spi.h>
+#include <linux/regmap.h>
+
+#include "sigmadsp.h"
+#include "adau17x1.h"
+
+static const char * const adau17x1_capture_mixer_boost_text[] = {
+ "Normal operation", "Boost Level 1", "Boost Level 2", "Boost Level 3",
+};
+
+static const SOC_ENUM_SINGLE_DECL(adau17x1_capture_boost_enum,
+ ADAU17X1_REC_POWER_MGMT, 5, adau17x1_capture_mixer_boost_text);
+
+static const char * const adau17x1_mic_bias_mode_text[] = {
+ "Normal operation", "High performance",
+};
+
+static SOC_ENUM_SINGLE_DECL(adau17x1_mic_bias_mode_enum,
+ ADAU17X1_MICBIAS, 3, adau17x1_mic_bias_mode_text);
+
+static const char * const adau17x1_mono_stereo_text[] = {
+ "Stereo",
+ "Mono Left Channel (L+R)",
+ "Mono Right Channel (L+R)",
+ "Mono (L+R)",
+};
+
+static const SOC_ENUM_SINGLE_DECL(adau17x1_dac_mode_enum,
+ ADAU17X1_DAC_CONTROL0, 6, adau17x1_mono_stereo_text);
+
+static const DECLARE_TLV_DB_MINMAX(adau17x1_digital_tlv, -9563, 0);
+
+static const struct snd_kcontrol_new adau17x1_controls[] = {
+ SOC_DOUBLE_R_TLV("Digital Capture Volume",
+ ADAU17X1_LEFT_INPUT_DIGITAL_VOL,
+ ADAU17X1_RIGHT_INPUT_DIGITAL_VOL,
+ 0, 0xff, 1, adau17x1_digital_tlv),
+ SOC_DOUBLE_R_TLV("Digital Playback Volume", ADAU17X1_DAC_CONTROL1,
+ ADAU17X1_DAC_CONTROL2, 0, 0xff, 1, adau17x1_digital_tlv),
+
+ SOC_SINGLE("ADC High Pass Filter Switch", ADAU17X1_ADC_CONTROL,
+ 5, 1, 0),
+ SOC_SINGLE("Playback De-emphasis Switch", ADAU17X1_DAC_CONTROL0,
+ 2, 1, 0),
+
+ SOC_ENUM("Capture Boost", adau17x1_capture_boost_enum),
+
+ SOC_ENUM("Mic Bias Mode", adau17x1_mic_bias_mode_enum),
+
+ SOC_ENUM("DAC Mono Stereo", adau17x1_dac_mode_enum),
+};
+
+static int adau17x1_pll_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct adau *adau = snd_soc_codec_get_drvdata(w->codec);
+ int ret;
+
+ if (SND_SOC_DAPM_EVENT_ON(event)) {
+ adau->pll_regs[5] = 1;
+ } else {
+ adau->pll_regs[5] = 0;
+ /* Bypass the PLL when disabled, otherwise registers will become
+ * inaccessible. */
+ regmap_update_bits(adau->regmap, ADAU17X1_CLOCK_CONTROL,
+ ADAU17X1_CLOCK_CONTROL_CORECLK_SRC_PLL, 0);
+ }
+
+ /* 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 (SND_SOC_DAPM_EVENT_ON(event)) {
+ mdelay(5);
+ regmap_update_bits(adau->regmap, ADAU17X1_CLOCK_CONTROL,
+ ADAU17X1_CLOCK_CONTROL_CORECLK_SRC_PLL,
+ ADAU17X1_CLOCK_CONTROL_CORECLK_SRC_PLL);
+ }
+
+ return 0;
+}
+
+static const struct snd_soc_dapm_widget adau17x1_dapm_widgets[] = {
+ SND_SOC_DAPM_SUPPLY_S("PLL", 3, SND_SOC_NOPM, 0, 0, adau17x1_pll_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_SUPPLY("AIFCLK", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_SUPPLY("MICBIAS", ADAU17X1_MICBIAS, 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_SUPPLY("Left Playback Enable", ADAU17X1_PLAY_POWER_MGMT,
+ 0, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("Right Playback Enable", ADAU17X1_PLAY_POWER_MGMT,
+ 1, 0, NULL, 0),
+
+ SND_SOC_DAPM_SUPPLY("Left Dec Filter Enable", ADAU17X1_ADC_CONTROL,
+ 0, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("Right Dec Filter Enable", ADAU17X1_ADC_CONTROL,
+ 1, 0, NULL, 0),
+
+ SND_SOC_DAPM_DAC("Left DAC", NULL, ADAU17X1_DAC_CONTROL0, 0, 0),
+ SND_SOC_DAPM_DAC("Right DAC", NULL, ADAU17X1_DAC_CONTROL0, 1, 0),
+ SND_SOC_DAPM_ADC("Left ADC", NULL, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_ADC("Right ADC", NULL, SND_SOC_NOPM, 0, 0),
+
+ SND_SOC_DAPM_AIF_OUT("AIFOUT", "Capture", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_IN("AIFIN", "Playback", 0, SND_SOC_NOPM, 0, 0),
+};
+
+static const struct snd_soc_dapm_route adau17x1_dapm_routes[] = {
+ { "Left ADC", NULL, "SYSCLK" },
+ { "Right ADC", NULL, "SYSCLK" },
+ { "Left DAC", NULL, "SYSCLK" },
+ { "Right DAC", NULL, "SYSCLK" },
+ { "AIFOUT", NULL, "SYSCLK" },
+ { "AIFIN", NULL, "SYSCLK" },
+
+ { "Left ADC", NULL, "Left Dec Filter Enable" },
+ { "Right ADC", NULL, "Right Dec Filter Enable" },
+
+ { "AIFOUT", NULL, "AIFCLK" },
+ { "AIFIN", NULL, "AIFCLK" },
+};
+
+static const struct snd_soc_dapm_route adau17x1_dapm_pll_route = {
+ "SYSCLK", NULL, "PLL",
+};
+
+static const char * const adau17x1_dac_mux_text[] = {
+ "AIFIN",
+ "DSP",
+};
+
+int adau17x1_dsp_mux_enum_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
+ struct adau *adau = snd_soc_codec_get_drvdata(codec);
+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+ struct snd_soc_dapm_update update;
+ unsigned int val, change;
+
+ if (ucontrol->value.enumerated.item[0] >= e->max)
+ return -EINVAL;
+
+ switch (ucontrol->value.enumerated.item[0]) {
+ case 0:
+ switch (e->reg) {
+ case ADAU17X1_SERIAL_INPUT_ROUTE:
+ val = (adau->tdm_dac_slot * 2) + 1;
+ adau->dsp_playback_bypass = true;
+ break;
+ case ADAU17X1_SERIAL_OUTPUT_ROUTE:
+ val = (adau->tdm_adc_slot * 2) + 1;
+ adau->dsp_capture_bypass = true;
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ default:
+ val = 0;
+
+ switch (e->reg) {
+ case ADAU17X1_SERIAL_INPUT_ROUTE:
+ adau->dsp_playback_bypass = false;
+ break;
+ case ADAU17X1_SERIAL_OUTPUT_ROUTE:
+ adau->dsp_capture_bypass = false;
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ }
+
+ change = snd_soc_test_bits(codec, e->reg, 0xff, val);
+ if (change) {
+ update.kcontrol = kcontrol;
+ update.reg = e->reg;
+ update.mask = 0xff;
+ update.val = val;
+
+ snd_soc_dapm_mux_update_power(&codec->dapm, kcontrol,
+ ucontrol->value.enumerated.item[0], e, &update);
+ }
+
+ return change;
+}
+EXPORT_SYMBOL_GPL(adau17x1_dsp_mux_enum_put);
+
+int adau17x1_dsp_mux_enum_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+ unsigned int val;
+
+ val = snd_soc_read(codec, e->reg);
+ ucontrol->value.enumerated.item[0] = val == 0;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(adau17x1_dsp_mux_enum_get);
+
+static const SOC_ENUM_SINGLE_DECL(adau17x1_dac_mux_enum,
+ ADAU17X1_SERIAL_INPUT_ROUTE, 0,
+ adau17x1_dac_mux_text);
+
+static const struct snd_kcontrol_new adau17x1_dac_mux =
+ ADAU17X1_DSP_MUX_ENUM("DAC Playback Mux", adau17x1_dac_mux_enum);
+
+static const struct snd_soc_dapm_widget adau17x1_dsp_dapm_widgets[] = {
+ SND_SOC_DAPM_PGA("DSP", ADAU17X1_DSP_RUN, 0, 0, NULL, 0),
+ SND_SOC_DAPM_SIGGEN("DSP Siggen"),
+
+ SND_SOC_DAPM_VIRT_MUX("DAC Playback Mux", SND_SOC_NOPM, 0, 0,
+ &adau17x1_dac_mux),
+
+};
+
+static const struct snd_soc_dapm_route adau17x1_dsp_dapm_routes[] = {
+ { "DAC Playback Mux", "DSP", "DSP" },
+ { "DAC Playback Mux", "AIFIN", "AIFIN" },
+
+ { "Left DAC", NULL, "DAC Playback Mux" },
+ { "Right DAC", NULL, "DAC Playback Mux" },
+
+ { "AIFOUT Capture Mux", "DSP", "DSP" },
+
+ { "AIFOUT", NULL, "AIFOUT Capture Mux" },
+
+ { "DSP", NULL, "DSP Siggen" },
+};
+
+static const struct snd_soc_dapm_route adau17x1_no_dsp_dapm_routes[] = {
+ { "Left DAC", NULL, "AIFIN" },
+ { "Right DAC", NULL, "AIFIN" },
+};
+
+static void adau17x1_check_aifclk(struct snd_soc_codec *codec)
+{
+ struct adau *adau = snd_soc_codec_get_drvdata(codec);
+
+ /* If we are in master mode we need to generate bit- and frameclock,
+ * regardless of whether there is an active path or not */
+ if (codec->active && adau->master)
+ snd_soc_dapm_force_enable_pin(&codec->dapm, "AIFCLK");
+ else
+ snd_soc_dapm_disable_pin(&codec->dapm, "AIFCLK");
+ snd_soc_dapm_sync(&codec->dapm);
+}
+
+bool adau17x1_has_dsp(struct adau *adau)
+{
+ switch (adau->type) {
+ case ADAU1761:
+ case ADAU1381:
+ case ADAU1781:
+ return true;
+ default:
+ return false;
+ }
+}
+EXPORT_SYMBOL_GPL(adau17x1_has_dsp);
+
+static int adau17x1_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct adau *adau = snd_soc_codec_get_drvdata(codec);
+ unsigned int val, div, dsp_div;
+ unsigned int freq;
+
+ if (adau->clk_src == ADAU17X1_CLK_SRC_PLL)
+ freq = adau->pll_freq;
+ else
+ freq = adau->sysclk / adau->sysclk_div;
+
+ if (freq % params_rate(params) != 0)
+ return -EINVAL;
+
+ switch (freq / params_rate(params)) {
+ case 1024: /* fs */
+ div = 0;
+ dsp_div = 1;
+ break;
+ case 6144: /* fs / 6 */
+ div = 1;
+ dsp_div = 6;
+ break;
+ case 4096: /* fs / 4 */
+ div = 2;
+ dsp_div = 5;
+ break;
+ case 3072: /* fs / 3 */
+ div = 3;
+ dsp_div = 4;
+ break;
+ case 2048: /* fs / 2 */
+ div = 4;
+ dsp_div = 3;
+ break;
+ case 1536: /* fs / 1.5 */
+ div = 5;
+ dsp_div = 2;
+ break;
+ case 512: /* fs / 0.5 */
+ div = 6;
+ dsp_div = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ regmap_update_bits(adau->regmap, ADAU17X1_CONVERTER0, 7, div);
+ if (adau17x1_has_dsp(adau)) {
+ regmap_write(adau->regmap, ADAU17X1_SERIAL_SAMPLING_RATE, div);
+ regmap_write(adau->regmap, ADAU17X1_DSP_SAMPLING_RATE, dsp_div);
+ }
+
+ adau17x1_check_aifclk(codec);
+
+ if (adau->dai_fmt != SND_SOC_DAIFMT_RIGHT_J)
+ return 0;
+
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ val = ADAU17X1_SERIAL_PORT1_DELAY16;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ val = ADAU17X1_SERIAL_PORT1_DELAY8;
+ break;
+ case SNDRV_PCM_FORMAT_S32_LE:
+ val = ADAU17X1_SERIAL_PORT1_DELAY0;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return regmap_update_bits(adau->regmap, ADAU17X1_SERIAL_PORT1,
+ ADAU17X1_SERIAL_PORT1_DELAY_MASK, val);
+}
+
+static int adau17x1_dai_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ adau17x1_check_aifclk(dai->codec);
+
+ return 0;
+}
+
+static void adau17x1_dai_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ adau17x1_check_aifclk(dai->codec);
+}
+
+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 div;
+ unsigned int r, n, m, i, j;
+
+ 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 > 0xffff || m > 0xffff || div > 3 || r > 8 || r < 2)
+ return -EINVAL;
+ }
+
+ adau->pll_regs[0] = m >> 8;
+ adau->pll_regs[1] = m & 0xff;
+ adau->pll_regs[2] = n >> 8;
+ adau->pll_regs[3] = n & 0xff;
+ adau->pll_regs[4] = (r << 3) | (div << 1);
+ if (m != 0)
+ adau->pll_regs[4] |= 1; /* Fractional mode */
+ adau->pll_regs[5] = 0;
+
+ 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 adau *adau = snd_soc_codec_get_drvdata(dai->codec);
+ struct snd_soc_dapm_context *dapm = &dai->codec->dapm;
+
+ switch (clk_id) {
+ case ADAU17X1_CLK_SRC_MCLK:
+ case ADAU17X1_CLK_SRC_PLL:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ adau->sysclk = freq;
+
+ if (adau->clk_src != clk_id) {
+ if (clk_id == ADAU17X1_CLK_SRC_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_set_dai_clkdiv(struct snd_soc_dai *dai, int div_id, int div)
+{
+ struct adau *adau = snd_soc_codec_get_drvdata(dai->codec);
+
+ if (div < 0 || div > 4)
+ return -EINVAL;
+
+ adau->sysclk_div = div;
+
+ return regmap_update_bits(adau->regmap, ADAU17X1_CLOCK_CONTROL,
+ ADAU17X1_CLOCK_CONTROL_INFREQ_MASK, (div - 1) << 1);
+}
+
+static int adau17x1_set_dai_fmt(struct snd_soc_dai *dai,
+ unsigned int fmt)
+{
+ struct adau *adau = snd_soc_codec_get_drvdata(dai->codec);
+ unsigned int ctrl0, ctrl1;
+ int lrclk_pol;
+
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM:
+ ctrl0 = ADAU17X1_SERIAL_PORT0_MASTER;
+ adau->master = true;
+ break;
+ case SND_SOC_DAIFMT_CBS_CFS:
+ ctrl0 = 0;
+ adau->master = false;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ lrclk_pol = 0;
+ ctrl1 = ADAU17X1_SERIAL_PORT1_DELAY1;
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ case SND_SOC_DAIFMT_RIGHT_J:
+ lrclk_pol = 1;
+ ctrl1 = ADAU17X1_SERIAL_PORT1_DELAY0;
+ break;
+ case SND_SOC_DAIFMT_DSP_A:
+ lrclk_pol = 1;
+ ctrl0 |= ADAU17X1_SERIAL_PORT0_PULSE_MODE;
+ ctrl1 = ADAU17X1_SERIAL_PORT1_DELAY1;
+ break;
+ case SND_SOC_DAIFMT_DSP_B:
+ lrclk_pol = 1;
+ ctrl0 |= ADAU17X1_SERIAL_PORT0_PULSE_MODE;
+ ctrl1 = ADAU17X1_SERIAL_PORT1_DELAY0;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ ctrl0 |= ADAU17X1_SERIAL_PORT0_BCLK_POL;
+ break;
+ case SND_SOC_DAIFMT_NB_IF:
+ lrclk_pol = !lrclk_pol;
+ break;
+ case SND_SOC_DAIFMT_IB_IF:
+ ctrl0 |= ADAU17X1_SERIAL_PORT0_BCLK_POL;
+ lrclk_pol = !lrclk_pol;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (lrclk_pol)
+ ctrl0 |= ADAU17X1_SERIAL_PORT0_LRCLK_POL;
+
+ regmap_write(adau->regmap, ADAU17X1_SERIAL_PORT0, ctrl0);
+ regmap_write(adau->regmap, ADAU17X1_SERIAL_PORT1, ctrl1);
+
+ adau->dai_fmt = fmt & SND_SOC_DAIFMT_FORMAT_MASK;
+
+ return 0;
+}
+
+static int adau17x1_set_dai_tdm_slot(struct snd_soc_dai *dai,
+ unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width)
+{
+ struct adau *adau = snd_soc_codec_get_drvdata(dai->codec);
+ unsigned int ser_ctrl0, ser_ctrl1;
+ unsigned int conv_ctrl0, conv_ctrl1;
+
+ /* I2S mode */
+ if (slots == 0) {
+ slots = 2;
+ rx_mask = 3;
+ tx_mask = 3;
+ slot_width = 32;
+ }
+
+ switch (slots) {
+ case 2:
+ ser_ctrl0 = ADUA_SERIAL_PORT0_STEREO;
+ break;
+ case 4:
+ ser_ctrl0 = ADUA_SERIAL_PORT0_TDM4;
+ break;
+ case 8:
+ if (adau->type == ADAU1361)
+ return -EINVAL;
+
+ ser_ctrl0 = ADUA_SERIAL_PORT0_TDM8;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (slot_width * slots) {
+ case 32:
+ if (adau->type == ADAU1761)
+ return -EINVAL;
+
+ ser_ctrl1 = ADUA_SERIAL_PORT1_BCLK32;
+ break;
+ case 64:
+ ser_ctrl1 = ADUA_SERIAL_PORT1_BCLK64;
+ break;
+ case 48:
+ ser_ctrl1 = ADUA_SERIAL_PORT1_BCLK48;
+ break;
+ case 128:
+ ser_ctrl1 = ADUA_SERIAL_PORT1_BCLK128;
+ break;
+ case 256:
+ if (adau->type == ADAU1361)
+ return -EINVAL;
+
+ ser_ctrl1 = ADUA_SERIAL_PORT1_BCLK256;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (rx_mask) {
+ case 0x03:
+ conv_ctrl1 = ADAU17X1_CONVERTER1_ADC_PAIR(1);
+ adau->tdm_adc_slot = 0;
+ break;
+ case 0x0c:
+ conv_ctrl1 = ADAU17X1_CONVERTER1_ADC_PAIR(2);
+ adau->tdm_adc_slot = 1;
+ break;
+ case 0x30:
+ conv_ctrl1 = ADAU17X1_CONVERTER1_ADC_PAIR(3);
+ adau->tdm_adc_slot = 2;
+ break;
+ case 0xc0:
+ conv_ctrl1 = ADAU17X1_CONVERTER1_ADC_PAIR(4);
+ adau->tdm_adc_slot = 3;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (tx_mask) {
+ case 0x03:
+ conv_ctrl0 = ADAU17X1_CONVERTER0_DAC_PAIR(1);
+ adau->tdm_dac_slot = 0;
+ break;
+ case 0x0c:
+ conv_ctrl0 = ADAU17X1_CONVERTER0_DAC_PAIR(2);
+ adau->tdm_dac_slot = 1;
+ break;
+ case 0x30:
+ conv_ctrl0 = ADAU17X1_CONVERTER0_DAC_PAIR(3);
+ adau->tdm_dac_slot = 2;
+ break;
+ case 0xc0:
+ conv_ctrl0 = ADAU17X1_CONVERTER0_DAC_PAIR(4);
+ adau->tdm_dac_slot = 3;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ regmap_update_bits(adau->regmap, ADAU17X1_CONVERTER0,
+ ADAU17X1_CONVERTER0_DAC_PAIR_MASK, conv_ctrl0);
+ regmap_update_bits(adau->regmap, ADAU17X1_CONVERTER1,
+ ADAU17X1_CONVERTER1_ADC_PAIR_MASK, conv_ctrl1);
+ regmap_update_bits(adau->regmap, ADAU17X1_SERIAL_PORT0,
+ ADAU17X1_SERIAL_PORT0_TDM_MASK, ser_ctrl0);
+ regmap_update_bits(adau->regmap, ADAU17X1_SERIAL_PORT1,
+ ADAU17X1_SERIAL_PORT1_BCLK_MASK, ser_ctrl1);
+
+ if (adau17x1_has_dsp(adau)) {
+ if (adau->dsp_playback_bypass) {
+ regmap_write(adau->regmap, ADAU17X1_SERIAL_INPUT_ROUTE,
+ (adau->tdm_dac_slot * 2) + 1);
+ }
+ if (adau->dsp_capture_bypass) {
+ regmap_write(adau->regmap, ADAU17X1_SERIAL_OUTPUT_ROUTE,
+ (adau->tdm_adc_slot * 2) + 1);
+ }
+ }
+
+ return 0;
+}
+
+const struct snd_soc_dai_ops adau17x1_dai_ops = {
+ .hw_params = adau17x1_hw_params,
+ .set_sysclk = adau17x1_set_dai_sysclk,
+ .set_fmt = adau17x1_set_dai_fmt,
+ .set_pll = adau17x1_set_dai_pll,
+ .set_clkdiv = adau17x1_set_dai_clkdiv,
+ .set_tdm_slot = adau17x1_set_dai_tdm_slot,
+ .startup = adau17x1_dai_startup,
+ .shutdown = adau17x1_dai_shutdown,
+};
+EXPORT_SYMBOL_GPL(adau17x1_dai_ops);
+
+int adau17x1_set_micbias_voltage(struct snd_soc_codec *codec,
+ enum adau17x1_micbias_voltage micbias)
+{
+ struct adau *adau = snd_soc_codec_get_drvdata(codec);
+
+ switch (micbias) {
+ case ADAU17X1_MICBIAS_0_90_AVDD:
+ case ADAU17X1_MICBIAS_0_65_AVDD:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ regmap_write(adau->regmap, ADAU17X1_MICBIAS, micbias << 2);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(adau17x1_set_micbias_voltage);
+
+bool adau17x1_readable_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case ADAU17X1_CLOCK_CONTROL:
+ case ADAU17X1_PLL_CONTROL:
+ case ADAU17X1_REC_POWER_MGMT:
+ case ADAU17X1_MICBIAS:
+ case ADAU17X1_SERIAL_PORT0:
+ case ADAU17X1_SERIAL_PORT1:
+ case ADAU17X1_CONVERTER0:
+ case ADAU17X1_CONVERTER1:
+ case ADAU17X1_LEFT_INPUT_DIGITAL_VOL:
+ case ADAU17X1_RIGHT_INPUT_DIGITAL_VOL:
+ case ADAU17X1_ADC_CONTROL:
+ case ADAU17X1_PLAY_POWER_MGMT:
+ case ADAU17X1_DAC_CONTROL0:
+ case ADAU17X1_DAC_CONTROL1:
+ case ADAU17X1_DAC_CONTROL2:
+ case ADAU17X1_SERIAL_PORT_PAD:
+ case ADAU17X1_CONTROL_PORT_PAD0:
+ case ADAU17X1_CONTROL_PORT_PAD1:
+ case ADAU17X1_DSP_SAMPLING_RATE:
+ case ADAU17X1_SERIAL_INPUT_ROUTE:
+ case ADAU17X1_SERIAL_OUTPUT_ROUTE:
+ case ADAU17X1_DSP_ENABLE:
+ case ADAU17X1_DSP_RUN:
+ case ADAU17X1_SERIAL_SAMPLING_RATE:
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
+EXPORT_SYMBOL_GPL(adau17x1_readable_register);
+
+bool adau17x1_volatile_register(struct device *dev, unsigned int reg)
+{
+ /* SigmaDSP parameter and program memory */
+ if (reg < 0x4000)
+ return true;
+
+ switch (reg) {
+ /* The PLL register is 6 bytes long */
+ case ADAU17X1_PLL_CONTROL:
+ case ADAU17X1_PLL_CONTROL + 1:
+ case ADAU17X1_PLL_CONTROL + 2:
+ case ADAU17X1_PLL_CONTROL + 3:
+ case ADAU17X1_PLL_CONTROL + 4:
+ case ADAU17X1_PLL_CONTROL + 5:
+ return true;
+ default:
+ break;
+ }
+
+ return false;
+}
+EXPORT_SYMBOL_GPL(adau17x1_volatile_register);
+
+int adau17x1_load_firmware(struct adau *adau, struct device *dev,
+ const char *firmware)
+{
+ int ret;
+ int dspsr;
+
+ ret = regmap_read(adau->regmap, ADAU17X1_DSP_SAMPLING_RATE, &dspsr);
+ if (ret)
+ return ret;
+
+ regmap_write(adau->regmap, ADAU17X1_DSP_ENABLE, 1);
+ regmap_write(adau->regmap, ADAU17X1_DSP_SAMPLING_RATE, 0xf);
+
+ ret = process_sigma_firmware_regmap(dev, adau->regmap, firmware);
+ if (ret) {
+ regmap_write(adau->regmap, ADAU17X1_DSP_ENABLE, 0);
+ return ret;
+ }
+ regmap_write(adau->regmap, ADAU17X1_DSP_SAMPLING_RATE, dspsr);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(adau17x1_load_firmware);
+
+int adau17x1_probe(struct snd_soc_codec *codec)
+{
+ struct adau *adau = snd_soc_codec_get_drvdata(codec);
+ int ret;
+
+ ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP);
+ if (ret)
+ return ret;
+
+ codec->driver->set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+ ret = snd_soc_add_codec_controls(codec, adau17x1_controls,
+ ARRAY_SIZE(adau17x1_controls));
+ if (ret)
+ return ret;
+ ret = snd_soc_dapm_new_controls(&codec->dapm, adau17x1_dapm_widgets,
+ ARRAY_SIZE(adau17x1_dapm_widgets));
+ if (ret)
+ return ret;
+
+ if (adau17x1_has_dsp(adau)) {
+ ret = snd_soc_dapm_new_controls(&codec->dapm,
+ adau17x1_dsp_dapm_widgets,
+ ARRAY_SIZE(adau17x1_dsp_dapm_widgets));
+ }
+ return ret;
+}
+EXPORT_SYMBOL_GPL(adau17x1_probe);
+
+int adau17x1_add_routes(struct snd_soc_codec *codec)
+{
+ struct adau *adau = snd_soc_codec_get_drvdata(codec);
+ int ret;
+
+ ret = snd_soc_dapm_add_routes(&codec->dapm, adau17x1_dapm_routes,
+ ARRAY_SIZE(adau17x1_dapm_routes));
+ if (ret)
+ return ret;
+
+ if (adau17x1_has_dsp(adau)) {
+ ret = snd_soc_dapm_add_routes(&codec->dapm,
+ adau17x1_dsp_dapm_routes,
+ ARRAY_SIZE(adau17x1_dsp_dapm_routes));
+ } else {
+ ret = snd_soc_dapm_add_routes(&codec->dapm,
+ adau17x1_no_dsp_dapm_routes,
+ ARRAY_SIZE(adau17x1_no_dsp_dapm_routes));
+ }
+ return ret;
+}
+EXPORT_SYMBOL_GPL(adau17x1_add_routes);
+
+#if IS_ENABLED(CONFIG_SPI_MASTER)
+static void adau17x1_spi_mode(struct device *dev)
+{
+ /* To get the device into SPI mode CLATCH has to be pulled low three
+ * times. Do this by issuing three dummy reads. */
+ spi_w8r8(to_spi_device(dev), 0x00);
+ spi_w8r8(to_spi_device(dev), 0x00);
+ spi_w8r8(to_spi_device(dev), 0x00);
+}
+#else
+static inline void adau17x1_spi_mode(struct device *dev) {}
+#endif
+
+int adau17x1_suspend(struct snd_soc_codec *codec)
+{
+ codec->driver->set_bias_level(codec, SND_SOC_BIAS_OFF);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(adau17x1_suspend);
+
+int adau17x1_resume(struct snd_soc_codec *codec)
+{
+ struct adau *adau = snd_soc_codec_get_drvdata(codec);
+
+ if (adau->spi_mode)
+ adau17x1_spi_mode(codec->dev);
+
+ codec->driver->set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+ regcache_sync(adau->regmap);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(adau17x1_resume);
+
+int adau17x1_bus_probe(struct device *dev, struct regmap *regmap,
+ enum adau17x1_type type, bool spi_mode)
+{
+ struct adau *adau;
+
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ adau = devm_kzalloc(dev, sizeof(*adau), GFP_KERNEL);
+ if (!adau)
+ return -ENOMEM;
+
+ adau->regmap = regmap;
+ adau->spi_mode = spi_mode;
+ adau->type = type;
+ adau->sysclk_div = 1;
+
+ dev_set_drvdata(dev, adau);
+
+ if (spi_mode)
+ adau17x1_spi_mode(dev);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(adau17x1_bus_probe);
+
+MODULE_DESCRIPTION("ASoC ADAU1X61/ADAU1X81 common code");
+MODULE_AUTHOR("Lars-Peter Clausen <lars(a)metafoo.de>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/adau17x1.h b/sound/soc/codecs/adau17x1.h
new file mode 100644
index 0000000..d49442e
--- /dev/null
+++ b/sound/soc/codecs/adau17x1.h
@@ -0,0 +1,148 @@
+#ifndef __ADAU17X1_H__
+#define __ADAU17X1_H__
+
+#include <linux/regmap.h>
+#include <linux/platform_data/adau17x1.h>
+
+enum adau17x1_type {
+ ADAU1361,
+ ADAU1761,
+ ADAU1381,
+ ADAU1781,
+};
+
+enum adau17x1_pll {
+ ADAU17X1_PLL,
+};
+
+enum adau17x1_pll_src {
+ ADAU17X1_PLL_SRC_MCLK,
+};
+
+enum adau17x1_clk_src {
+ ADAU17X1_CLK_SRC_MCLK,
+ ADAU17X1_CLK_SRC_PLL,
+};
+
+struct adau {
+ unsigned int sysclk;
+ unsigned int sysclk_div;
+ unsigned int pll_freq;
+
+ enum adau17x1_clk_src clk_src;
+ enum adau17x1_type type;
+ bool spi_mode;
+
+ unsigned int dai_fmt;
+
+ uint8_t pll_regs[6];
+
+ bool master;
+
+ unsigned int tdm_dac_slot;
+ unsigned int tdm_adc_slot;
+
+ bool dsp_playback_bypass;
+ bool dsp_capture_bypass;
+
+ struct regmap *regmap;
+};
+
+int adau17x1_probe(struct snd_soc_codec *codec);
+int adau17x1_add_routes(struct snd_soc_codec *codec);
+int adau17x1_bus_probe(struct device *dev,
+ struct regmap *regmap, enum adau17x1_type type,
+ bool spi_mode);
+int adau17x1_set_micbias_voltage(struct snd_soc_codec *codec,
+ enum adau17x1_micbias_voltage micbias);
+bool adau17x1_readable_register(struct device *dev, unsigned int reg);
+bool adau17x1_volatile_register(struct device *dev, unsigned int reg);
+int adau17x1_suspend(struct snd_soc_codec *codec);
+int adau17x1_resume(struct snd_soc_codec *codec);
+
+extern const struct snd_soc_dai_ops adau17x1_dai_ops;
+
+int adau17x1_load_firmware(struct adau *adau, struct device *dev,
+ const char *firmware);
+bool adau17x1_has_dsp(struct adau *adau);
+int adau17x1_dsp_mux_enum_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol);
+int adau17x1_dsp_mux_enum_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol);
+
+#define ADAU17X1_DSP_MUX_ENUM(xname, xenum) \
+ SOC_DAPM_ENUM_EXT(xname, xenum, \
+ adau17x1_dsp_mux_enum_get, adau17x1_dsp_mux_enum_put)
+
+#define DECLARE_ADAU17X1_AIFOUT_MUX(name, text) \
+static const char * const adau17x1_ ## name ## _aifout_text[] = { \
+ text, \
+ "DSP", \
+}; \
+static const SOC_ENUM_SINGLE_DECL(adau17x1_ ## name ## _aifout_mux_enum, \
+ ADAU17X1_SERIAL_OUTPUT_ROUTE, 0, adau17x1_ ## name ## _aifout_text); \
+static const struct snd_kcontrol_new adau17x1_ ## name ## _aifout_mux = \
+ ADAU17X1_DSP_MUX_ENUM("AIFOUT Capture Mux", \
+ adau17x1_ ## name ## _aifout_mux_enum); \
+static const struct snd_soc_dapm_widget adau17x1_ ## name ## _dsp_widget = \
+ SND_SOC_DAPM_VIRT_MUX("AIFOUT Capture Mux", SND_SOC_NOPM, 0, 0, \
+ &adau17x1_ ## name ## _aifout_mux) \
+
+#define ADAU17X1_CLOCK_CONTROL 0x4000
+#define ADAU17X1_PLL_CONTROL 0x4002
+#define ADAU17X1_REC_POWER_MGMT 0x4009
+#define ADAU17X1_MICBIAS 0x4010
+#define ADAU17X1_SERIAL_PORT0 0x4015
+#define ADAU17X1_SERIAL_PORT1 0x4016
+#define ADAU17X1_CONVERTER0 0x4017
+#define ADAU17X1_CONVERTER1 0x4018
+#define ADAU17X1_LEFT_INPUT_DIGITAL_VOL 0x401a
+#define ADAU17X1_RIGHT_INPUT_DIGITAL_VOL 0x401b
+#define ADAU17X1_ADC_CONTROL 0x4019
+#define ADAU17X1_PLAY_POWER_MGMT 0x4029
+#define ADAU17X1_DAC_CONTROL0 0x402a
+#define ADAU17X1_DAC_CONTROL1 0x402b
+#define ADAU17X1_DAC_CONTROL2 0x402c
+#define ADAU17X1_SERIAL_PORT_PAD 0x402d
+#define ADAU17X1_CONTROL_PORT_PAD0 0x402f
+#define ADAU17X1_CONTROL_PORT_PAD1 0x4030
+#define ADAU17X1_DSP_SAMPLING_RATE 0x40eb
+#define ADAU17X1_SERIAL_INPUT_ROUTE 0x40f2
+#define ADAU17X1_SERIAL_OUTPUT_ROUTE 0x40f3
+#define ADAU17X1_DSP_ENABLE 0x40f5
+#define ADAU17X1_DSP_RUN 0x40f6
+#define ADAU17X1_SERIAL_SAMPLING_RATE 0x40f8
+
+#define ADAU17X1_SERIAL_PORT0_BCLK_POL BIT(4)
+#define ADAU17X1_SERIAL_PORT0_LRCLK_POL BIT(3)
+#define ADAU17X1_SERIAL_PORT0_MASTER BIT(0)
+
+#define ADAU17X1_SERIAL_PORT1_DELAY1 0x00
+#define ADAU17X1_SERIAL_PORT1_DELAY0 0x01
+#define ADAU17X1_SERIAL_PORT1_DELAY8 0x02
+#define ADAU17X1_SERIAL_PORT1_DELAY16 0x03
+#define ADAU17X1_SERIAL_PORT1_DELAY_MASK 0x03
+
+#define ADAU17X1_CLOCK_CONTROL_INFREQ_MASK 0x6
+#define ADAU17X1_CLOCK_CONTROL_CORECLK_SRC_PLL BIT(3)
+#define ADAU17X1_CLOCK_CONTROL_SYSCLK_EN BIT(0)
+
+#define ADUA_SERIAL_PORT1_BCLK32 (0x0 << 5)
+#define ADUA_SERIAL_PORT1_BCLK48 (0x1 << 5)
+#define ADUA_SERIAL_PORT1_BCLK64 (0x2 << 5)
+#define ADUA_SERIAL_PORT1_BCLK128 (0x3 << 5)
+#define ADUA_SERIAL_PORT1_BCLK256 (0x4 << 5)
+#define ADAU17X1_SERIAL_PORT1_BCLK_MASK (0x7 << 5)
+
+#define ADUA_SERIAL_PORT0_STEREO (0x0 << 1)
+#define ADUA_SERIAL_PORT0_TDM4 (0x1 << 1)
+#define ADUA_SERIAL_PORT0_TDM8 (0x2 << 1)
+#define ADAU17X1_SERIAL_PORT0_TDM_MASK (0x3 << 1)
+#define ADAU17X1_SERIAL_PORT0_PULSE_MODE BIT(5)
+
+#define ADAU17X1_CONVERTER0_DAC_PAIR(x) (((x) - 1) << 5)
+#define ADAU17X1_CONVERTER0_DAC_PAIR_MASK (0x3 << 5)
+#define ADAU17X1_CONVERTER1_ADC_PAIR(x) ((x) - 1)
+#define ADAU17X1_CONVERTER1_ADC_PAIR_MASK 0x3
+
+#endif
--
1.8.0
2
11
[alsa-devel] 32337ea "ASoC: warn if we will overwrite the DAI stream widgets"
by Stephen Warren 29 Aug '13
by Stephen Warren 29 Aug '13
29 Aug '13
Russell, if the warning in commit 32337ea "ASoC: warn if we will
overwrite the DAI stream widgets" fires, what do I need to do to the
ASoC driver to fix it? (I'm deliberately ignoring any other issues with
this patch, and looking only to discover what is apparently wrong with
my driver that's triggering this...).
Steev Klimaszewski reported this warning to me, and I've repro'd it
running next-20130827 on a couple of Tegra systems (TrimSlice and
Seaboard at least), using sound/soc/tegra/tegra_{trimslice,wm8903}.c,
and associated ASoC components.
For the record, the commit description is:
> ASoC: warn if we will overwrite the DAI stream widgets
>
> The DAI stream widgets can end up being created multiple times if the
> CPU DAI and DMA/platform components share the same struct device. This
> bug has been reported in various forms to the ASoC maintainer(s) several
> times, yet they refuse to acknowledge this:
>
> > Essentially all the dmaengine based platforms in mainline use a shared
> > device for DMA and DAI; I'm fairly sure someone would have mentioned if
> > there were problems.
> >
> > As you have been repeatedly told the Kirkwood drivers are the first
> > drivers submitted to mainline which use DPCM and therefore it is not
> > surprising that there are a few issues which need to be worked through,
> > there were a few revisions to the framework which went in as a result of
> > review during the mainline merge. The problem you are seeing here is
> > due to this being the first platform with a *shared* device to use DPCM.
>
> This is inspite of stating multiple times that this has nothing to do
> with DPCM what so ever. So, having tried to convince them over the
> last month that this is the case, and them being obstructive and/or
> obtuse, this is the only way left open to convince them that there is
> a problem here.
>
> It is only through complete frustration over their inability to recognise
> that there could be a problem that I am putting this into linux-next;
> this is not something I want to do, but they leave me no other choice.
>
> If they are correct, then this patch will have no effect what so ever.
> If I am correct, there will be warnings produced where a CPU DAI and
> DMA/platform component shares the same struct device.
>
> Signed-off-by: Russell King <rmk+kernel(a)arm.linux.org.uk>
2
1
28 Aug '13
On Thu, 22 Aug 2013 18:00:14 +0200, Wolfram Sang <wsa(a)the-dreams.de> wrote:
> I2C of helpers used to live in of_i2c.c but experience (from SPI) shows
> that it is much cleaner to have this in the core. This also removes a
> circular dependency between the helpers and the core, and so we can
> finally register child nodes in the core instead of doing this manually
> in each driver. So, fix the drivers and documentation, too.
>
> Acked-by: Rob Herring <rob.herring(a)calxeda.com>
> Reviewed-by: Felipe Balbi <balbi(a)ti.com>
> Acked-by: Rafael J. Wysocki <rafael.j.wysocki(a)intel.com>
> Tested-by: Sylwester Nawrocki <s.nawrocki(a)samsung.com>
> Signed-off-by: Wolfram Sang <wsa(a)the-dreams.de>
Acked-by: Grant Likely <grant.likely(a)linaro.org>
> ---
>
> V2->V3: Was trying to be too smart by only fixing includes needed.
> Took a more general approach this time, converting of_i2c.h
> to i2c.h in case i2c.h was not already there. Otherwise
> remove it. Improved my build scripts and no build failures,
> no complaints from buildbot as well.
>
>
> Documentation/acpi/enumeration.txt | 1 -
> arch/powerpc/platforms/44x/warp.c | 1 -
> drivers/gpu/drm/tilcdc/tilcdc_slave.c | 1 -
> drivers/gpu/drm/tilcdc/tilcdc_tfp410.c | 1 -
> drivers/gpu/host1x/drm/output.c | 2 +-
> drivers/i2c/busses/i2c-at91.c | 3 -
> drivers/i2c/busses/i2c-cpm.c | 6 --
> drivers/i2c/busses/i2c-davinci.c | 2 -
> drivers/i2c/busses/i2c-designware-platdrv.c | 2 -
> drivers/i2c/busses/i2c-gpio.c | 3 -
> drivers/i2c/busses/i2c-i801.c | 2 -
> drivers/i2c/busses/i2c-ibm_iic.c | 4 -
> drivers/i2c/busses/i2c-imx.c | 3 -
> drivers/i2c/busses/i2c-mpc.c | 2 -
> drivers/i2c/busses/i2c-mv64xxx.c | 3 -
> drivers/i2c/busses/i2c-mxs.c | 3 -
> drivers/i2c/busses/i2c-nomadik.c | 3 -
> drivers/i2c/busses/i2c-ocores.c | 3 -
> drivers/i2c/busses/i2c-octeon.c | 3 -
> drivers/i2c/busses/i2c-omap.c | 3 -
> drivers/i2c/busses/i2c-pnx.c | 3 -
> drivers/i2c/busses/i2c-powermac.c | 9 +-
> drivers/i2c/busses/i2c-pxa.c | 2 -
> drivers/i2c/busses/i2c-s3c2410.c | 2 -
> drivers/i2c/busses/i2c-sh_mobile.c | 2 -
> drivers/i2c/busses/i2c-sirf.c | 3 -
> drivers/i2c/busses/i2c-stu300.c | 2 -
> drivers/i2c/busses/i2c-tegra.c | 3 -
> drivers/i2c/busses/i2c-versatile.c | 2 -
> drivers/i2c/busses/i2c-wmt.c | 3 -
> drivers/i2c/busses/i2c-xiic.c | 3 -
> drivers/i2c/i2c-core.c | 109 +++++++++++++++++++++-
> drivers/i2c/i2c-mux.c | 3 -
> drivers/i2c/muxes/i2c-arb-gpio-challenge.c | 1 -
> drivers/i2c/muxes/i2c-mux-gpio.c | 1 -
> drivers/i2c/muxes/i2c-mux-pinctrl.c | 1 -
> drivers/media/platform/exynos4-is/fimc-is-i2c.c | 4 +-
> drivers/media/platform/exynos4-is/fimc-is.c | 2 +-
> drivers/media/platform/exynos4-is/media-dev.c | 1 -
> drivers/of/Kconfig | 6 --
> drivers/of/Makefile | 1 -
> drivers/of/of_i2c.c | 114 -----------------------
> drivers/staging/imx-drm/imx-tve.c | 2 +-
> include/linux/i2c.h | 20 ++++
> include/linux/of_i2c.h | 46 ---------
> sound/soc/fsl/imx-sgtl5000.c | 2 +-
> sound/soc/fsl/imx-wm8962.c | 2 +-
> 47 files changed, 138 insertions(+), 262 deletions(-)
> delete mode 100644 drivers/of/of_i2c.c
> delete mode 100644 include/linux/of_i2c.h
>
> diff --git a/Documentation/acpi/enumeration.txt b/Documentation/acpi/enumeration.txt
> index d9be7a9..958266e 100644
> --- a/Documentation/acpi/enumeration.txt
> +++ b/Documentation/acpi/enumeration.txt
> @@ -238,7 +238,6 @@ An I2C bus (controller) driver does:
> if (ret)
> /* handle error */
>
> - of_i2c_register_devices(adapter);
> /* Enumerate the slave devices behind this bus via ACPI */
> acpi_i2c_register_devices(adapter);
>
> diff --git a/arch/powerpc/platforms/44x/warp.c b/arch/powerpc/platforms/44x/warp.c
> index 4cfa499..534574a 100644
> --- a/arch/powerpc/platforms/44x/warp.c
> +++ b/arch/powerpc/platforms/44x/warp.c
> @@ -16,7 +16,6 @@
> #include <linux/interrupt.h>
> #include <linux/delay.h>
> #include <linux/of_gpio.h>
> -#include <linux/of_i2c.h>
> #include <linux/slab.h>
> #include <linux/export.h>
>
> diff --git a/drivers/gpu/drm/tilcdc/tilcdc_slave.c b/drivers/gpu/drm/tilcdc/tilcdc_slave.c
> index dfffaf0..a19f657 100644
> --- a/drivers/gpu/drm/tilcdc/tilcdc_slave.c
> +++ b/drivers/gpu/drm/tilcdc/tilcdc_slave.c
> @@ -16,7 +16,6 @@
> */
>
> #include <linux/i2c.h>
> -#include <linux/of_i2c.h>
> #include <linux/pinctrl/pinmux.h>
> #include <linux/pinctrl/consumer.h>
> #include <drm/drm_encoder_slave.h>
> diff --git a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
> index 925c7cd..c38b56b 100644
> --- a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
> +++ b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
> @@ -16,7 +16,6 @@
> */
>
> #include <linux/i2c.h>
> -#include <linux/of_i2c.h>
> #include <linux/gpio.h>
> #include <linux/of_gpio.h>
> #include <linux/pinctrl/pinmux.h>
> diff --git a/drivers/gpu/host1x/drm/output.c b/drivers/gpu/host1x/drm/output.c
> index 8140fc6..137ae81 100644
> --- a/drivers/gpu/host1x/drm/output.c
> +++ b/drivers/gpu/host1x/drm/output.c
> @@ -9,7 +9,7 @@
>
> #include <linux/module.h>
> #include <linux/of_gpio.h>
> -#include <linux/of_i2c.h>
> +#include <linux/i2c.h>
>
> #include "drm.h"
>
> diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c
> index 6bb839b..fd05930 100644
> --- a/drivers/i2c/busses/i2c-at91.c
> +++ b/drivers/i2c/busses/i2c-at91.c
> @@ -28,7 +28,6 @@
> #include <linux/module.h>
> #include <linux/of.h>
> #include <linux/of_device.h>
> -#include <linux/of_i2c.h>
> #include <linux/platform_device.h>
> #include <linux/slab.h>
> #include <linux/platform_data/dma-atmel.h>
> @@ -775,8 +774,6 @@ static int at91_twi_probe(struct platform_device *pdev)
> return rc;
> }
>
> - of_i2c_register_devices(&dev->adapter);
> -
> dev_info(dev->dev, "AT91 i2c bus driver.\n");
> return 0;
> }
> diff --git a/drivers/i2c/busses/i2c-cpm.c b/drivers/i2c/busses/i2c-cpm.c
> index 2e1f7eb..b2b8aa9 100644
> --- a/drivers/i2c/busses/i2c-cpm.c
> +++ b/drivers/i2c/busses/i2c-cpm.c
> @@ -42,7 +42,6 @@
> #include <linux/dma-mapping.h>
> #include <linux/of_device.h>
> #include <linux/of_platform.h>
> -#include <linux/of_i2c.h>
> #include <sysdev/fsl_soc.h>
> #include <asm/cpm.h>
>
> @@ -681,11 +680,6 @@ static int cpm_i2c_probe(struct platform_device *ofdev)
> dev_dbg(&ofdev->dev, "hw routines for %s registered.\n",
> cpm->adap.name);
>
> - /*
> - * register OF I2C devices
> - */
> - of_i2c_register_devices(&cpm->adap);
> -
> return 0;
> out_shut:
> cpm_i2c_shutdown(cpm);
> diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c
> index fa55605..62be3b3 100644
> --- a/drivers/i2c/busses/i2c-davinci.c
> +++ b/drivers/i2c/busses/i2c-davinci.c
> @@ -38,7 +38,6 @@
> #include <linux/slab.h>
> #include <linux/cpufreq.h>
> #include <linux/gpio.h>
> -#include <linux/of_i2c.h>
> #include <linux/of_device.h>
>
> #include <mach/hardware.h>
> @@ -728,7 +727,6 @@ static int davinci_i2c_probe(struct platform_device *pdev)
> dev_err(&pdev->dev, "failure adding adapter\n");
> goto err_unuse_clocks;
> }
> - of_i2c_register_devices(adap);
>
> return 0;
>
> diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c
> index 4c5fada..27ea436 100644
> --- a/drivers/i2c/busses/i2c-designware-platdrv.c
> +++ b/drivers/i2c/busses/i2c-designware-platdrv.c
> @@ -35,7 +35,6 @@
> #include <linux/err.h>
> #include <linux/interrupt.h>
> #include <linux/of.h>
> -#include <linux/of_i2c.h>
> #include <linux/platform_device.h>
> #include <linux/pm.h>
> #include <linux/pm_runtime.h>
> @@ -172,7 +171,6 @@ static int dw_i2c_probe(struct platform_device *pdev)
> dev_err(&pdev->dev, "failure adding adapter\n");
> return r;
> }
> - of_i2c_register_devices(adap);
> acpi_i2c_register_devices(adap);
>
> pm_runtime_set_autosuspend_delay(&pdev->dev, 1000);
> diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c
> index bc6e139..e5da9fe 100644
> --- a/drivers/i2c/busses/i2c-gpio.c
> +++ b/drivers/i2c/busses/i2c-gpio.c
> @@ -16,7 +16,6 @@
> #include <linux/platform_device.h>
> #include <linux/gpio.h>
> #include <linux/of_gpio.h>
> -#include <linux/of_i2c.h>
>
> struct i2c_gpio_private_data {
> struct i2c_adapter adap;
> @@ -224,8 +223,6 @@ static int i2c_gpio_probe(struct platform_device *pdev)
> if (ret)
> goto err_add_bus;
>
> - of_i2c_register_devices(adap);
> -
> platform_set_drvdata(pdev, priv);
>
> dev_info(&pdev->dev, "using pins %u (SDA) and %u (SCL%s)\n",
> diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
> index 4ebceed..4296d17 100644
> --- a/drivers/i2c/busses/i2c-i801.c
> +++ b/drivers/i2c/busses/i2c-i801.c
> @@ -87,7 +87,6 @@
> #include <linux/slab.h>
> #include <linux/wait.h>
> #include <linux/err.h>
> -#include <linux/of_i2c.h>
>
> #if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \
> defined CONFIG_DMI
> @@ -1230,7 +1229,6 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
> goto exit_free_irq;
> }
>
> - of_i2c_register_devices(&priv->adapter);
> i801_probe_optional_slaves(priv);
> /* We ignore errors - multiplexing is optional */
> i801_add_mux(priv);
> diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c
> index 973f516..ff3caa0 100644
> --- a/drivers/i2c/busses/i2c-ibm_iic.c
> +++ b/drivers/i2c/busses/i2c-ibm_iic.c
> @@ -42,7 +42,6 @@
> #include <linux/io.h>
> #include <linux/i2c.h>
> #include <linux/of_platform.h>
> -#include <linux/of_i2c.h>
>
> #include "i2c-ibm_iic.h"
>
> @@ -759,9 +758,6 @@ static int iic_probe(struct platform_device *ofdev)
> dev_info(&ofdev->dev, "using %s mode\n",
> dev->fast_mode ? "fast (400 kHz)" : "standard (100 kHz)");
>
> - /* Now register all the child nodes */
> - of_i2c_register_devices(adap);
> -
> return 0;
>
> error_cleanup:
> diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
> index e242797..bbbea6b 100644
> --- a/drivers/i2c/busses/i2c-imx.c
> +++ b/drivers/i2c/busses/i2c-imx.c
> @@ -50,7 +50,6 @@
> #include <linux/slab.h>
> #include <linux/of.h>
> #include <linux/of_device.h>
> -#include <linux/of_i2c.h>
> #include <linux/platform_data/i2c-imx.h>
>
> /** Defines ********************************************************************
> @@ -570,8 +569,6 @@ static int __init i2c_imx_probe(struct platform_device *pdev)
> return ret;
> }
>
> - of_i2c_register_devices(&i2c_imx->adapter);
> -
> /* Set up platform driver data */
> platform_set_drvdata(pdev, i2c_imx);
>
> diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
> index 7607dc0..9f2513d 100644
> --- a/drivers/i2c/busses/i2c-mpc.c
> +++ b/drivers/i2c/busses/i2c-mpc.c
> @@ -18,7 +18,6 @@
> #include <linux/sched.h>
> #include <linux/init.h>
> #include <linux/of_platform.h>
> -#include <linux/of_i2c.h>
> #include <linux/slab.h>
>
> #include <linux/io.h>
> @@ -691,7 +690,6 @@ static int fsl_i2c_probe(struct platform_device *op)
> dev_err(i2c->dev, "failed to add adapter\n");
> goto fail_add;
> }
> - of_i2c_register_devices(&i2c->adap);
>
> return result;
>
> diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
> index b1f42bf..8220322 100644
> --- a/drivers/i2c/busses/i2c-mv64xxx.c
> +++ b/drivers/i2c/busses/i2c-mv64xxx.c
> @@ -21,7 +21,6 @@
> #include <linux/of.h>
> #include <linux/of_device.h>
> #include <linux/of_irq.h>
> -#include <linux/of_i2c.h>
> #include <linux/clk.h>
> #include <linux/err.h>
>
> @@ -689,8 +688,6 @@ mv64xxx_i2c_probe(struct platform_device *pd)
> goto exit_free_irq;
> }
>
> - of_i2c_register_devices(&drv_data->adapter);
> -
> return 0;
>
> exit_free_irq:
> diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c
> index df8ff5a..62ed07d 100644
> --- a/drivers/i2c/busses/i2c-mxs.c
> +++ b/drivers/i2c/busses/i2c-mxs.c
> @@ -27,7 +27,6 @@
> #include <linux/stmp_device.h>
> #include <linux/of.h>
> #include <linux/of_device.h>
> -#include <linux/of_i2c.h>
> #include <linux/dma-mapping.h>
> #include <linux/dmaengine.h>
>
> @@ -701,8 +700,6 @@ static int mxs_i2c_probe(struct platform_device *pdev)
> return err;
> }
>
> - of_i2c_register_devices(adap);
> -
> return 0;
> }
>
> diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c
> index 512dfe6..519df17 100644
> --- a/drivers/i2c/busses/i2c-nomadik.c
> +++ b/drivers/i2c/busses/i2c-nomadik.c
> @@ -24,7 +24,6 @@
> #include <linux/pm_runtime.h>
> #include <linux/platform_data/i2c-nomadik.h>
> #include <linux/of.h>
> -#include <linux/of_i2c.h>
> #include <linux/pinctrl/consumer.h>
>
> #define DRIVER_NAME "nmk-i2c"
> @@ -1045,8 +1044,6 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id)
> goto err_add_adap;
> }
>
> - of_i2c_register_devices(adap);
> -
> pm_runtime_put(&adev->dev);
>
> return 0;
> diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c
> index 0e1f824..0a52b78 100644
> --- a/drivers/i2c/busses/i2c-ocores.c
> +++ b/drivers/i2c/busses/i2c-ocores.c
> @@ -24,7 +24,6 @@
> #include <linux/i2c-ocores.h>
> #include <linux/slab.h>
> #include <linux/io.h>
> -#include <linux/of_i2c.h>
> #include <linux/log2.h>
>
> struct ocores_i2c {
> @@ -435,8 +434,6 @@ static int ocores_i2c_probe(struct platform_device *pdev)
> if (pdata) {
> for (i = 0; i < pdata->num_devices; i++)
> i2c_new_device(&i2c->adap, pdata->devices + i);
> - } else {
> - of_i2c_register_devices(&i2c->adap);
> }
>
> return 0;
> diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon.c
> index 956fe32..b929ba2 100644
> --- a/drivers/i2c/busses/i2c-octeon.c
> +++ b/drivers/i2c/busses/i2c-octeon.c
> @@ -15,7 +15,6 @@
> #include <linux/interrupt.h>
> #include <linux/kernel.h>
> #include <linux/module.h>
> -#include <linux/of_i2c.h>
> #include <linux/delay.h>
> #include <linux/sched.h>
> #include <linux/slab.h>
> @@ -599,8 +598,6 @@ static int octeon_i2c_probe(struct platform_device *pdev)
> }
> dev_info(i2c->dev, "version %s\n", DRV_VERSION);
>
> - of_i2c_register_devices(&i2c->adap);
> -
> return 0;
>
> out:
> diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
> index 142b694d..a9f0f80 100644
> --- a/drivers/i2c/busses/i2c-omap.c
> +++ b/drivers/i2c/busses/i2c-omap.c
> @@ -38,7 +38,6 @@
> #include <linux/clk.h>
> #include <linux/io.h>
> #include <linux/of.h>
> -#include <linux/of_i2c.h>
> #include <linux/of_device.h>
> #include <linux/slab.h>
> #include <linux/i2c-omap.h>
> @@ -1245,8 +1244,6 @@ omap_i2c_probe(struct platform_device *pdev)
> dev_info(dev->dev, "bus %d rev%d.%d at %d kHz\n", adap->nr,
> major, minor, dev->speed);
>
> - of_i2c_register_devices(adap);
> -
> pm_runtime_mark_last_busy(dev->dev);
> pm_runtime_put_autosuspend(dev->dev);
>
> diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c
> index 5f39c6d..7b57d67 100644
> --- a/drivers/i2c/busses/i2c-pnx.c
> +++ b/drivers/i2c/busses/i2c-pnx.c
> @@ -23,7 +23,6 @@
> #include <linux/err.h>
> #include <linux/clk.h>
> #include <linux/slab.h>
> -#include <linux/of_i2c.h>
>
> #define I2C_PNX_TIMEOUT_DEFAULT 10 /* msec */
> #define I2C_PNX_SPEED_KHZ_DEFAULT 100
> @@ -741,8 +740,6 @@ static int i2c_pnx_probe(struct platform_device *pdev)
> goto out_irq;
> }
>
> - of_i2c_register_devices(&alg_data->adapter);
> -
> dev_dbg(&pdev->dev, "%s: Master at %#8x, irq %d.\n",
> alg_data->adapter.name, res->start, alg_data->irq);
>
> diff --git a/drivers/i2c/busses/i2c-powermac.c b/drivers/i2c/busses/i2c-powermac.c
> index 8dc90da..1010f2e 100644
> --- a/drivers/i2c/busses/i2c-powermac.c
> +++ b/drivers/i2c/busses/i2c-powermac.c
> @@ -440,7 +440,9 @@ static int i2c_powermac_probe(struct platform_device *dev)
> adapter->algo = &i2c_powermac_algorithm;
> i2c_set_adapdata(adapter, bus);
> adapter->dev.parent = &dev->dev;
> - adapter->dev.of_node = dev->dev.of_node;
> +
> + /* Clear of_node to skip automatic registration of i2c child nodes */
> + adapter->dev.of_node = NULL;
> rc = i2c_add_adapter(adapter);
> if (rc) {
> printk(KERN_ERR "i2c-powermac: Adapter %s registration "
> @@ -450,9 +452,8 @@ static int i2c_powermac_probe(struct platform_device *dev)
>
> printk(KERN_INFO "PowerMac i2c bus %s registered\n", adapter->name);
>
> - /* Cannot use of_i2c_register_devices() due to Apple device-tree
> - * funkyness
> - */
> + /* Use custom child registration due to Apple device-tree funkyness */
> + adapter->dev.of_node = dev->dev.of_node;
> i2c_powermac_register_devices(adapter, bus);
>
> return rc;
> diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
> index fbafed2..bc65014 100644
> --- a/drivers/i2c/busses/i2c-pxa.c
> +++ b/drivers/i2c/busses/i2c-pxa.c
> @@ -31,7 +31,6 @@
> #include <linux/i2c-pxa.h>
> #include <linux/of.h>
> #include <linux/of_device.h>
> -#include <linux/of_i2c.h>
> #include <linux/platform_device.h>
> #include <linux/err.h>
> #include <linux/clk.h>
> @@ -1185,7 +1184,6 @@ static int i2c_pxa_probe(struct platform_device *dev)
> printk(KERN_INFO "I2C: Failed to add bus\n");
> goto eadapt;
> }
> - of_i2c_register_devices(&i2c->adap);
>
> platform_set_drvdata(dev, i2c);
>
> diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
> index cab1c91..643426e 100644
> --- a/drivers/i2c/busses/i2c-s3c2410.c
> +++ b/drivers/i2c/busses/i2c-s3c2410.c
> @@ -36,7 +36,6 @@
> #include <linux/cpufreq.h>
> #include <linux/slab.h>
> #include <linux/io.h>
> -#include <linux/of_i2c.h>
> #include <linux/of_gpio.h>
> #include <linux/pinctrl/consumer.h>
>
> @@ -1154,7 +1153,6 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
> return ret;
> }
>
> - of_i2c_register_devices(&i2c->adap);
> platform_set_drvdata(pdev, i2c);
>
> pm_runtime_enable(&pdev->dev);
> diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c
> index debf745..aa1268f 100644
> --- a/drivers/i2c/busses/i2c-sh_mobile.c
> +++ b/drivers/i2c/busses/i2c-sh_mobile.c
> @@ -27,7 +27,6 @@
> #include <linux/platform_device.h>
> #include <linux/interrupt.h>
> #include <linux/i2c.h>
> -#include <linux/of_i2c.h>
> #include <linux/err.h>
> #include <linux/pm_runtime.h>
> #include <linux/clk.h>
> @@ -758,7 +757,6 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
> "I2C adapter %d with bus speed %lu Hz (L/H=%x/%x)\n",
> adap->nr, pd->bus_speed, pd->iccl, pd->icch);
>
> - of_i2c_register_devices(adap);
> return 0;
>
> err_all:
> diff --git a/drivers/i2c/busses/i2c-sirf.c b/drivers/i2c/busses/i2c-sirf.c
> index a63c7d5..0ff22e2 100644
> --- a/drivers/i2c/busses/i2c-sirf.c
> +++ b/drivers/i2c/busses/i2c-sirf.c
> @@ -12,7 +12,6 @@
> #include <linux/slab.h>
> #include <linux/platform_device.h>
> #include <linux/i2c.h>
> -#include <linux/of_i2c.h>
> #include <linux/clk.h>
> #include <linux/err.h>
> #include <linux/io.h>
> @@ -366,8 +365,6 @@ static int i2c_sirfsoc_probe(struct platform_device *pdev)
>
> clk_disable(clk);
>
> - of_i2c_register_devices(adap);
> -
> dev_info(&pdev->dev, " I2C adapter ready to operate\n");
>
> return 0;
> diff --git a/drivers/i2c/busses/i2c-stu300.c b/drivers/i2c/busses/i2c-stu300.c
> index d1a6b20..047546c 100644
> --- a/drivers/i2c/busses/i2c-stu300.c
> +++ b/drivers/i2c/busses/i2c-stu300.c
> @@ -17,7 +17,6 @@
> #include <linux/clk.h>
> #include <linux/io.h>
> #include <linux/slab.h>
> -#include <linux/of_i2c.h>
>
> /* the name of this kernel module */
> #define NAME "stu300"
> @@ -936,7 +935,6 @@ stu300_probe(struct platform_device *pdev)
> platform_set_drvdata(pdev, dev);
> dev_info(&pdev->dev, "ST DDC I2C @ %p, irq %d\n",
> dev->virtbase, dev->irq);
> - of_i2c_register_devices(adap);
>
> return 0;
> }
> diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
> index 9aa1b60..c457cb4 100644
> --- a/drivers/i2c/busses/i2c-tegra.c
> +++ b/drivers/i2c/busses/i2c-tegra.c
> @@ -25,7 +25,6 @@
> #include <linux/interrupt.h>
> #include <linux/delay.h>
> #include <linux/slab.h>
> -#include <linux/of_i2c.h>
> #include <linux/of_device.h>
> #include <linux/module.h>
> #include <linux/clk/tegra.h>
> @@ -802,8 +801,6 @@ static int tegra_i2c_probe(struct platform_device *pdev)
> return ret;
> }
>
> - of_i2c_register_devices(&i2c_dev->adapter);
> -
> return 0;
> }
>
> diff --git a/drivers/i2c/busses/i2c-versatile.c b/drivers/i2c/busses/i2c-versatile.c
> index f3a8790..6bb3a89 100644
> --- a/drivers/i2c/busses/i2c-versatile.c
> +++ b/drivers/i2c/busses/i2c-versatile.c
> @@ -16,7 +16,6 @@
> #include <linux/platform_device.h>
> #include <linux/slab.h>
> #include <linux/io.h>
> -#include <linux/of_i2c.h>
>
> #define I2C_CONTROL 0x00
> #define I2C_CONTROLS 0x00
> @@ -108,7 +107,6 @@ static int i2c_versatile_probe(struct platform_device *dev)
> ret = i2c_bit_add_numbered_bus(&i2c->adap);
> if (ret >= 0) {
> platform_set_drvdata(dev, i2c);
> - of_i2c_register_devices(&i2c->adap);
> return 0;
> }
>
> diff --git a/drivers/i2c/busses/i2c-wmt.c b/drivers/i2c/busses/i2c-wmt.c
> index baaa7d1..c65da3d 100644
> --- a/drivers/i2c/busses/i2c-wmt.c
> +++ b/drivers/i2c/busses/i2c-wmt.c
> @@ -21,7 +21,6 @@
> #include <linux/module.h>
> #include <linux/of.h>
> #include <linux/of_address.h>
> -#include <linux/of_i2c.h>
> #include <linux/of_irq.h>
> #include <linux/platform_device.h>
>
> @@ -439,8 +438,6 @@ static int wmt_i2c_probe(struct platform_device *pdev)
>
> platform_set_drvdata(pdev, i2c_dev);
>
> - of_i2c_register_devices(adap);
> -
> return 0;
> }
>
> diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c
> index 3d0f052..8823db7 100644
> --- a/drivers/i2c/busses/i2c-xiic.c
> +++ b/drivers/i2c/busses/i2c-xiic.c
> @@ -40,7 +40,6 @@
> #include <linux/i2c-xiic.h>
> #include <linux/io.h>
> #include <linux/slab.h>
> -#include <linux/of_i2c.h>
>
> #define DRIVER_NAME "xiic-i2c"
>
> @@ -752,8 +751,6 @@ static int xiic_i2c_probe(struct platform_device *pdev)
> i2c_new_device(&i2c->adap, pdata->devices + i);
> }
>
> - of_i2c_register_devices(&i2c->adap);
> -
> return 0;
>
> add_adapter_failed:
> diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
> index f32ca29..08ebd78 100644
> --- a/drivers/i2c/i2c-core.c
> +++ b/drivers/i2c/i2c-core.c
> @@ -23,7 +23,11 @@
> SMBus 2.0 support by Mark Studebaker <mdsxyz123(a)yahoo.com> and
> Jean Delvare <khali(a)linux-fr.org>
> Mux support by Rodolfo Giometti <giometti(a)enneenne.com> and
> - Michael Lawnick <michael.lawnick.ext(a)nsn.com> */
> + Michael Lawnick <michael.lawnick.ext(a)nsn.com>
> + OF support is copyright (c) 2008 Jochen Friedrich <jochen(a)scram.de>
> + (based on a previous patch from Jon Smirl <jonsmirl(a)gmail.com>) and
> + (c) 2013 Wolfram Sang <wsa(a)the-dreams.de>
> + */
>
> #include <linux/module.h>
> #include <linux/kernel.h>
> @@ -35,7 +39,9 @@
> #include <linux/init.h>
> #include <linux/idr.h>
> #include <linux/mutex.h>
> +#include <linux/of.h>
> #include <linux/of_device.h>
> +#include <linux/of_irq.h>
> #include <linux/completion.h>
> #include <linux/hardirq.h>
> #include <linux/irqflags.h>
> @@ -954,6 +960,104 @@ static void i2c_scan_static_board_info(struct i2c_adapter *adapter)
> up_read(&__i2c_board_lock);
> }
>
> +/* OF support code */
> +
> +#if IS_ENABLED(CONFIG_OF)
> +static void of_i2c_register_devices(struct i2c_adapter *adap)
> +{
> + void *result;
> + struct device_node *node;
> +
> + /* Only register child devices if the adapter has a node pointer set */
> + if (!adap->dev.of_node)
> + return;
> +
> + dev_dbg(&adap->dev, "of_i2c: walking child nodes\n");
> +
> + for_each_available_child_of_node(adap->dev.of_node, node) {
> + struct i2c_board_info info = {};
> + struct dev_archdata dev_ad = {};
> + const __be32 *addr;
> + int len;
> +
> + dev_dbg(&adap->dev, "of_i2c: register %s\n", node->full_name);
> +
> + if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) {
> + dev_err(&adap->dev, "of_i2c: modalias failure on %s\n",
> + node->full_name);
> + continue;
> + }
> +
> + addr = of_get_property(node, "reg", &len);
> + if (!addr || (len < sizeof(int))) {
> + dev_err(&adap->dev, "of_i2c: invalid reg on %s\n",
> + node->full_name);
> + continue;
> + }
> +
> + info.addr = be32_to_cpup(addr);
> + if (info.addr > (1 << 10) - 1) {
> + dev_err(&adap->dev, "of_i2c: invalid addr=%x on %s\n",
> + info.addr, node->full_name);
> + continue;
> + }
> +
> + info.irq = irq_of_parse_and_map(node, 0);
> + info.of_node = of_node_get(node);
> + info.archdata = &dev_ad;
> +
> + if (of_get_property(node, "wakeup-source", NULL))
> + info.flags |= I2C_CLIENT_WAKE;
> +
> + request_module("%s%s", I2C_MODULE_PREFIX, info.type);
> +
> + result = i2c_new_device(adap, &info);
> + if (result == NULL) {
> + dev_err(&adap->dev, "of_i2c: Failure registering %s\n",
> + node->full_name);
> + of_node_put(node);
> + irq_dispose_mapping(info.irq);
> + continue;
> + }
> + }
> +}
> +
> +static int of_dev_node_match(struct device *dev, void *data)
> +{
> + return dev->of_node == data;
> +}
> +
> +/* must call put_device() when done with returned i2c_client device */
> +struct i2c_client *of_find_i2c_device_by_node(struct device_node *node)
> +{
> + struct device *dev;
> +
> + dev = bus_find_device(&i2c_bus_type, NULL, node,
> + of_dev_node_match);
> + if (!dev)
> + return NULL;
> +
> + return i2c_verify_client(dev);
> +}
> +EXPORT_SYMBOL(of_find_i2c_device_by_node);
> +
> +/* must call put_device() when done with returned i2c_adapter device */
> +struct i2c_adapter *of_find_i2c_adapter_by_node(struct device_node *node)
> +{
> + struct device *dev;
> +
> + dev = bus_find_device(&i2c_bus_type, NULL, node,
> + of_dev_node_match);
> + if (!dev)
> + return NULL;
> +
> + return i2c_verify_adapter(dev);
> +}
> +EXPORT_SYMBOL(of_find_i2c_adapter_by_node);
> +#else
> +static void of_i2c_register_devices(struct i2c_adapter *adap) { }
> +#endif /* CONFIG_OF */
> +
> static int i2c_do_add_adapter(struct i2c_driver *driver,
> struct i2c_adapter *adap)
> {
> @@ -1058,6 +1162,8 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
>
> exit_recovery:
> /* create pre-declared device nodes */
> + of_i2c_register_devices(adap);
> +
> if (adap->nr < __i2c_first_dynamic_bus_num)
> i2c_scan_static_board_info(adap);
>
> @@ -1282,7 +1388,6 @@ void i2c_del_adapter(struct i2c_adapter *adap)
> }
> EXPORT_SYMBOL(i2c_del_adapter);
>
> -
> /* ------------------------------------------------------------------------- */
>
> int i2c_for_each_dev(void *data, int (*fn)(struct device *, void *))
> diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c
> index 7409ebb..797e311 100644
> --- a/drivers/i2c/i2c-mux.c
> +++ b/drivers/i2c/i2c-mux.c
> @@ -25,7 +25,6 @@
> #include <linux/i2c.h>
> #include <linux/i2c-mux.h>
> #include <linux/of.h>
> -#include <linux/of_i2c.h>
>
> /* multiplexer per channel data */
> struct i2c_mux_priv {
> @@ -185,8 +184,6 @@ struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent,
> dev_info(&parent->dev, "Added multiplexed i2c bus %d\n",
> i2c_adapter_id(&priv->adap));
>
> - of_i2c_register_devices(&priv->adap);
> -
> return &priv->adap;
> }
> EXPORT_SYMBOL_GPL(i2c_add_mux_adapter);
> diff --git a/drivers/i2c/muxes/i2c-arb-gpio-challenge.c b/drivers/i2c/muxes/i2c-arb-gpio-challenge.c
> index 210b6f7..b901638 100644
> --- a/drivers/i2c/muxes/i2c-arb-gpio-challenge.c
> +++ b/drivers/i2c/muxes/i2c-arb-gpio-challenge.c
> @@ -21,7 +21,6 @@
> #include <linux/i2c-mux.h>
> #include <linux/init.h>
> #include <linux/module.h>
> -#include <linux/of_i2c.h>
> #include <linux/of_gpio.h>
> #include <linux/platform_device.h>
> #include <linux/slab.h>
> diff --git a/drivers/i2c/muxes/i2c-mux-gpio.c b/drivers/i2c/muxes/i2c-mux-gpio.c
> index 5a0ce00..128a981 100644
> --- a/drivers/i2c/muxes/i2c-mux-gpio.c
> +++ b/drivers/i2c/muxes/i2c-mux-gpio.c
> @@ -16,7 +16,6 @@
> #include <linux/module.h>
> #include <linux/slab.h>
> #include <linux/gpio.h>
> -#include <linux/of_i2c.h>
> #include <linux/of_gpio.h>
>
> struct gpiomux {
> diff --git a/drivers/i2c/muxes/i2c-mux-pinctrl.c b/drivers/i2c/muxes/i2c-mux-pinctrl.c
> index a43c0ce..859a6d2 100644
> --- a/drivers/i2c/muxes/i2c-mux-pinctrl.c
> +++ b/drivers/i2c/muxes/i2c-mux-pinctrl.c
> @@ -20,7 +20,6 @@
> #include <linux/i2c-mux.h>
> #include <linux/init.h>
> #include <linux/module.h>
> -#include <linux/of_i2c.h>
> #include <linux/pinctrl/consumer.h>
> #include <linux/i2c-mux-pinctrl.h>
> #include <linux/platform_device.h>
> diff --git a/drivers/media/platform/exynos4-is/fimc-is-i2c.c b/drivers/media/platform/exynos4-is/fimc-is-i2c.c
> index 617a798..9930556 100644
> --- a/drivers/media/platform/exynos4-is/fimc-is-i2c.c
> +++ b/drivers/media/platform/exynos4-is/fimc-is-i2c.c
> @@ -12,7 +12,7 @@
>
> #include <linux/clk.h>
> #include <linux/module.h>
> -#include <linux/of_i2c.h>
> +#include <linux/i2c.h>
> #include <linux/platform_device.h>
> #include <linux/pm_runtime.h>
> #include <linux/slab.h>
> @@ -67,8 +67,6 @@ static int fimc_is_i2c_probe(struct platform_device *pdev)
> pm_runtime_enable(&pdev->dev);
> pm_runtime_enable(&i2c_adap->dev);
>
> - of_i2c_register_devices(i2c_adap);
> -
> return 0;
> }
>
> diff --git a/drivers/media/platform/exynos4-is/fimc-is.c b/drivers/media/platform/exynos4-is/fimc-is.c
> index 967f6a9..2276fdc 100644
> --- a/drivers/media/platform/exynos4-is/fimc-is.c
> +++ b/drivers/media/platform/exynos4-is/fimc-is.c
> @@ -21,7 +21,7 @@
> #include <linux/interrupt.h>
> #include <linux/kernel.h>
> #include <linux/module.h>
> -#include <linux/of_i2c.h>
> +#include <linux/i2c.h>
> #include <linux/of_irq.h>
> #include <linux/of_address.h>
> #include <linux/of_platform.h>
> diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c
> index 19f556c..f8c66b4 100644
> --- a/drivers/media/platform/exynos4-is/media-dev.c
> +++ b/drivers/media/platform/exynos4-is/media-dev.c
> @@ -20,7 +20,6 @@
> #include <linux/of.h>
> #include <linux/of_platform.h>
> #include <linux/of_device.h>
> -#include <linux/of_i2c.h>
> #include <linux/platform_device.h>
> #include <linux/pm_runtime.h>
> #include <linux/types.h>
> diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
> index 80e5c13..78cc760 100644
> --- a/drivers/of/Kconfig
> +++ b/drivers/of/Kconfig
> @@ -48,12 +48,6 @@ config OF_IRQ
> def_bool y
> depends on !SPARC
>
> -config OF_I2C
> - def_tristate I2C
> - depends on I2C
> - help
> - OpenFirmware I2C accessors
> -
> config OF_NET
> depends on NETDEVICES
> def_bool y
> diff --git a/drivers/of/Makefile b/drivers/of/Makefile
> index 1f9c0c4..efd0510 100644
> --- a/drivers/of/Makefile
> +++ b/drivers/of/Makefile
> @@ -3,7 +3,6 @@ obj-$(CONFIG_OF_FLATTREE) += fdt.o
> obj-$(CONFIG_OF_PROMTREE) += pdt.o
> obj-$(CONFIG_OF_ADDRESS) += address.o
> obj-$(CONFIG_OF_IRQ) += irq.o
> -obj-$(CONFIG_OF_I2C) += of_i2c.o
> obj-$(CONFIG_OF_NET) += of_net.o
> obj-$(CONFIG_OF_SELFTEST) += selftest.o
> obj-$(CONFIG_OF_MDIO) += of_mdio.o
> diff --git a/drivers/of/of_i2c.c b/drivers/of/of_i2c.c
> deleted file mode 100644
> index b667264..0000000
> --- a/drivers/of/of_i2c.c
> +++ /dev/null
> @@ -1,114 +0,0 @@
> -/*
> - * OF helpers for the I2C API
> - *
> - * Copyright (c) 2008 Jochen Friedrich <jochen(a)scram.de>
> - *
> - * Based on a previous patch from Jon Smirl <jonsmirl(a)gmail.com>
> - *
> - * This program is free software; you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License as published by
> - * the Free Software Foundation; either version 2 of the License, or
> - * (at your option) any later version.
> - */
> -
> -#include <linux/i2c.h>
> -#include <linux/irq.h>
> -#include <linux/of.h>
> -#include <linux/of_i2c.h>
> -#include <linux/of_irq.h>
> -#include <linux/module.h>
> -
> -void of_i2c_register_devices(struct i2c_adapter *adap)
> -{
> - void *result;
> - struct device_node *node;
> -
> - /* Only register child devices if the adapter has a node pointer set */
> - if (!adap->dev.of_node)
> - return;
> -
> - dev_dbg(&adap->dev, "of_i2c: walking child nodes\n");
> -
> - for_each_available_child_of_node(adap->dev.of_node, node) {
> - struct i2c_board_info info = {};
> - struct dev_archdata dev_ad = {};
> - const __be32 *addr;
> - int len;
> -
> - dev_dbg(&adap->dev, "of_i2c: register %s\n", node->full_name);
> -
> - if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) {
> - dev_err(&adap->dev, "of_i2c: modalias failure on %s\n",
> - node->full_name);
> - continue;
> - }
> -
> - addr = of_get_property(node, "reg", &len);
> - if (!addr || (len < sizeof(int))) {
> - dev_err(&adap->dev, "of_i2c: invalid reg on %s\n",
> - node->full_name);
> - continue;
> - }
> -
> - info.addr = be32_to_cpup(addr);
> - if (info.addr > (1 << 10) - 1) {
> - dev_err(&adap->dev, "of_i2c: invalid addr=%x on %s\n",
> - info.addr, node->full_name);
> - continue;
> - }
> -
> - info.irq = irq_of_parse_and_map(node, 0);
> - info.of_node = of_node_get(node);
> - info.archdata = &dev_ad;
> -
> - if (of_get_property(node, "wakeup-source", NULL))
> - info.flags |= I2C_CLIENT_WAKE;
> -
> - request_module("%s%s", I2C_MODULE_PREFIX, info.type);
> -
> - result = i2c_new_device(adap, &info);
> - if (result == NULL) {
> - dev_err(&adap->dev, "of_i2c: Failure registering %s\n",
> - node->full_name);
> - of_node_put(node);
> - irq_dispose_mapping(info.irq);
> - continue;
> - }
> - }
> -}
> -EXPORT_SYMBOL(of_i2c_register_devices);
> -
> -static int of_dev_node_match(struct device *dev, void *data)
> -{
> - return dev->of_node == data;
> -}
> -
> -/* must call put_device() when done with returned i2c_client device */
> -struct i2c_client *of_find_i2c_device_by_node(struct device_node *node)
> -{
> - struct device *dev;
> -
> - dev = bus_find_device(&i2c_bus_type, NULL, node,
> - of_dev_node_match);
> - if (!dev)
> - return NULL;
> -
> - return i2c_verify_client(dev);
> -}
> -EXPORT_SYMBOL(of_find_i2c_device_by_node);
> -
> -/* must call put_device() when done with returned i2c_adapter device */
> -struct i2c_adapter *of_find_i2c_adapter_by_node(struct device_node *node)
> -{
> - struct device *dev;
> -
> - dev = bus_find_device(&i2c_bus_type, NULL, node,
> - of_dev_node_match);
> - if (!dev)
> - return NULL;
> -
> - return i2c_verify_adapter(dev);
> -}
> -EXPORT_SYMBOL(of_find_i2c_adapter_by_node);
> -
> -MODULE_LICENSE("GPL");
> diff --git a/drivers/staging/imx-drm/imx-tve.c b/drivers/staging/imx-drm/imx-tve.c
> index a56797d..2d76fd4 100644
> --- a/drivers/staging/imx-drm/imx-tve.c
> +++ b/drivers/staging/imx-drm/imx-tve.c
> @@ -21,7 +21,7 @@
> #include <linux/clk.h>
> #include <linux/clk-provider.h>
> #include <linux/module.h>
> -#include <linux/of_i2c.h>
> +#include <linux/i2c.h>
> #include <linux/regmap.h>
> #include <linux/regulator/consumer.h>
> #include <linux/spinlock.h>
> diff --git a/include/linux/i2c.h b/include/linux/i2c.h
> index e988fa9..2189189 100644
> --- a/include/linux/i2c.h
> +++ b/include/linux/i2c.h
> @@ -542,6 +542,26 @@ static inline int i2c_adapter_id(struct i2c_adapter *adap)
>
> #endif /* I2C */
>
> +#if IS_ENABLED(CONFIG_OF)
> +/* must call put_device() when done with returned i2c_client device */
> +extern struct i2c_client *of_find_i2c_device_by_node(struct device_node *node);
> +
> +/* must call put_device() when done with returned i2c_adapter device */
> +extern struct i2c_adapter *of_find_i2c_adapter_by_node(struct device_node *node);
> +
> +#else
> +
> +static inline struct i2c_client *of_find_i2c_device_by_node(struct device_node *node)
> +{
> + return NULL;
> +}
> +
> +static inline struct i2c_adapter *of_find_i2c_adapter_by_node(struct device_node *node)
> +{
> + return NULL;
> +}
> +#endif /* CONFIG_OF */
> +
> #if IS_ENABLED(CONFIG_ACPI_I2C)
> extern void acpi_i2c_register_devices(struct i2c_adapter *adap);
> #else
> diff --git a/include/linux/of_i2c.h b/include/linux/of_i2c.h
> deleted file mode 100644
> index cfb545c..0000000
> --- a/include/linux/of_i2c.h
> +++ /dev/null
> @@ -1,46 +0,0 @@
> -/*
> - * Generic I2C API implementation for PowerPC.
> - *
> - * Copyright (c) 2008 Jochen Friedrich <jochen(a)scram.de>
> - *
> - * This program is free software; you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License as published by
> - * the Free Software Foundation; either version 2 of the License, or
> - * (at your option) any later version.
> - */
> -
> -#ifndef __LINUX_OF_I2C_H
> -#define __LINUX_OF_I2C_H
> -
> -#if defined(CONFIG_OF_I2C) || defined(CONFIG_OF_I2C_MODULE)
> -#include <linux/i2c.h>
> -
> -extern void of_i2c_register_devices(struct i2c_adapter *adap);
> -
> -/* must call put_device() when done with returned i2c_client device */
> -extern struct i2c_client *of_find_i2c_device_by_node(struct device_node *node);
> -
> -/* must call put_device() when done with returned i2c_adapter device */
> -extern struct i2c_adapter *of_find_i2c_adapter_by_node(
> - struct device_node *node);
> -
> -#else
> -static inline void of_i2c_register_devices(struct i2c_adapter *adap)
> -{
> - return;
> -}
> -
> -static inline struct i2c_client *of_find_i2c_device_by_node(struct device_node *node)
> -{
> - return NULL;
> -}
> -
> -/* must call put_device() when done with returned i2c_adapter device */
> -static inline struct i2c_adapter *of_find_i2c_adapter_by_node(
> - struct device_node *node)
> -{
> - return NULL;
> -}
> -#endif /* CONFIG_OF_I2C */
> -
> -#endif /* __LINUX_OF_I2C_H */
> diff --git a/sound/soc/fsl/imx-sgtl5000.c b/sound/soc/fsl/imx-sgtl5000.c
> index 3f726e4..f2fbde9 100644
> --- a/sound/soc/fsl/imx-sgtl5000.c
> +++ b/sound/soc/fsl/imx-sgtl5000.c
> @@ -13,7 +13,7 @@
> #include <linux/module.h>
> #include <linux/of.h>
> #include <linux/of_platform.h>
> -#include <linux/of_i2c.h>
> +#include <linux/i2c.h>
> #include <linux/clk.h>
> #include <sound/soc.h>
>
> diff --git a/sound/soc/fsl/imx-wm8962.c b/sound/soc/fsl/imx-wm8962.c
> index 52a36a9..9fd7a65 100644
> --- a/sound/soc/fsl/imx-wm8962.c
> +++ b/sound/soc/fsl/imx-wm8962.c
> @@ -15,7 +15,7 @@
>
> #include <linux/module.h>
> #include <linux/of_platform.h>
> -#include <linux/of_i2c.h>
> +#include <linux/i2c.h>
> #include <linux/slab.h>
> #include <linux/clk.h>
> #include <sound/soc.h>
> --
> 1.7.10.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo(a)vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
1
0
[alsa-devel] [PATCH] ASoc: kirkwood: Use the Kirkwood audio driver in Dove boards
by Jean-Francois Moine 28 Aug '13
by Jean-Francois Moine 28 Aug '13
28 Aug '13
This patch permits the generation of the Kirkwood audio driver which
may be used in the Dove boards.
Signed-off-by: Jean-Francois Moine <moinejf(a)free.fr>
---
sound/soc/kirkwood/Kconfig | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/sound/soc/kirkwood/Kconfig b/sound/soc/kirkwood/Kconfig
index 9e1970c..78ed4a4 100644
--- a/sound/soc/kirkwood/Kconfig
+++ b/sound/soc/kirkwood/Kconfig
@@ -1,6 +1,6 @@
config SND_KIRKWOOD_SOC
- tristate "SoC Audio for the Marvell Kirkwood chip"
- depends on ARCH_KIRKWOOD || COMPILE_TEST
+ tristate "SoC Audio for the Marvell Kirkwood and Dove chips"
+ depends on ARCH_KIRKWOOD || ARCH_DOVE || COMPILE_TEST
help
Say Y or M if you want to add support for codecs attached to
the Kirkwood I2S interface. You will also need to select the
--
Ken ar c'hentaƱ | ** Breizh ha Linux atav! **
Jef | http://moinejf.free.fr/
2
1
On Tue, 27 Aug 2013, James Stone wrote:
> This does not help at all with running jackd at lower latencies.
>
> With this patch, I get xruns at 128 frames/period or less with jackd
> (accompanied by iso underrun messages), whereas with vanilla 3.10.9
> (which now has both yours and Clemen's patches applied), performance
> is extremely good (64 frames per period possible).
Was this was both recording and playback, or playback only? If you
were doing both, what happens with just playback?
Assuming you see the same problem with just playback, please collect a
usbmon trace showing one or two of those underruns at say 64
frames/period. And for comparison, it would be nice to have a usbmon
trace showing a couple of seconds of normal operation under
vanilla 3.10.9.
Alan Stern
1
0
Re: [alsa-devel] [PATCH] ASoC: codecs/sgtl5000.c: specify correct reg_stride in regmap_config.
by David Jander 27 Aug '13
by David Jander 27 Aug '13
27 Aug '13
On Sun, 25 Aug 2013 16:44:26 +0800
zengzhaoming <zengzm.kernel(a)gmail.com> wrote:
> On 08-22/08:23, David Jander wrote:
> > This makes the RB-Tree more compact and efficient.
> >
> > Signed-off-by: David Jander <david(a)protonic.nl>
> > ---
> > sound/soc/codecs/sgtl5000.c | 1 +
> > 1 file changed, 1 insertion(+)
> >
> > diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c
> > index 760e8bf..ba5ca67 100644
> > --- a/sound/soc/codecs/sgtl5000.c
> > +++ b/sound/soc/codecs/sgtl5000.c
> > @@ -1480,6 +1480,7 @@ static struct snd_soc_codec_driver sgtl5000_driver =
> > { static const struct regmap_config sgtl5000_regmap = {
> > .reg_bits = 16,
> > .val_bits = 16,
> > + .reg_stride = 2,
> >
> > .max_register = SGTL5000_MAX_REG_OFFSET,
> > .volatile_reg = sgtl5000_volatile,
> > --
> > 1.8.1.2
>
> Fabio has post same patch for this.
> http://comments.gmane.org/gmane.linux.alsa.devel/109903
Oh. I didn't see that one, sorry.
Fabio's patch is from July, 5th. It takes quite some time for this to hit
mainline then....
Best regards,
--
David Jander
Protonic Holland.
2
1
This patch implements a device-tree-only machine driver for Freescale
i.MX series Soc. It works with spdif_transmitter/spdif_receiver and
fsl_spdif.c drivers.
Signed-off-by: Nicolin Chen <b42378(a)freescale.com>
---
Changelog
v10->v11:
* Use boolean properties for spdif-out/in switch instead of codec phandles.
* Accordingly create dummy codec driver in probe() instead of DT nodes.
.../devicetree/bindings/sound/imx-audio-spdif.txt | 34 +++++
sound/soc/fsl/Kconfig | 11 ++
sound/soc/fsl/Makefile | 2 +
sound/soc/fsl/imx-spdif.c | 152 ++++++++++++++++++++
4 files changed, 199 insertions(+), 0 deletions(-)
create mode 100644 Documentation/devicetree/bindings/sound/imx-audio-spdif.txt
create mode 100644 sound/soc/fsl/imx-spdif.c
diff --git a/Documentation/devicetree/bindings/sound/imx-audio-spdif.txt b/Documentation/devicetree/bindings/sound/imx-audio-spdif.txt
new file mode 100644
index 0000000..7d13479
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/imx-audio-spdif.txt
@@ -0,0 +1,34 @@
+Freescale i.MX audio complex with S/PDIF transceiver
+
+Required properties:
+
+ - compatible : "fsl,imx-audio-spdif"
+
+ - model : The user-visible name of this sound complex
+
+ - spdif-controller : The phandle of the i.MX S/PDIF controller
+
+
+Optional properties:
+
+ - spdif-out : This is a boolean property. If present, the transmitting
+ function of S/PDIF will be enabled, indicating there's a physical
+ S/PDIF out connector/jack on the board or it's connecting to some
+ other IP block, such as an HDMI encoder/display-controller.
+
+ - spdif-in : This is a boolean property. If present, the receiving
+ function of S/PDIF will be enabled, indicating there's a physical
+ S/PDIF in connector/jack on the board.
+
+* Note: At least one of these two properties should be set in the DT binding.
+
+
+Example:
+
+sound-spdif {
+ compatible = "fsl,imx-audio-spdif";
+ model = "imx-spdif";
+ spdif-controller = <&spdif>;
+ spdif-out;
+ spdif-in;
+};
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index cd088cc..a708380 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -193,6 +193,17 @@ config SND_SOC_IMX_SGTL5000
Say Y if you want to add support for SoC audio on an i.MX board with
a sgtl5000 codec.
+config SND_SOC_IMX_SPDIF
+ tristate "SoC Audio support for i.MX boards with S/PDIF"
+ select SND_SOC_IMX_PCM_DMA
+ select SND_SOC_FSL_SPDIF
+ select SND_SOC_FSL_UTILS
+ select SND_SOC_SPDIF
+ help
+ SoC Audio support for i.MX boards with S/PDIF
+ Say Y if you want to add support for SoC audio on an i.MX board with
+ a S/DPDIF.
+
config SND_SOC_IMX_MC13783
tristate "SoC Audio support for I.MX boards with mc13783"
depends on MFD_MC13783 && ARM
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile
index 4b5970e..e2aaff7 100644
--- a/sound/soc/fsl/Makefile
+++ b/sound/soc/fsl/Makefile
@@ -45,6 +45,7 @@ snd-soc-mx27vis-aic32x4-objs := mx27vis-aic32x4.o
snd-soc-wm1133-ev1-objs := wm1133-ev1.o
snd-soc-imx-sgtl5000-objs := imx-sgtl5000.o
snd-soc-imx-wm8962-objs := imx-wm8962.o
+snd-soc-imx-spdif-objs :=imx-spdif.o
snd-soc-imx-mc13783-objs := imx-mc13783.o
obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o
@@ -53,4 +54,5 @@ obj-$(CONFIG_SND_SOC_MX27VIS_AIC32X4) += snd-soc-mx27vis-aic32x4.o
obj-$(CONFIG_SND_MXC_SOC_WM1133_EV1) += snd-soc-wm1133-ev1.o
obj-$(CONFIG_SND_SOC_IMX_SGTL5000) += snd-soc-imx-sgtl5000.o
obj-$(CONFIG_SND_SOC_IMX_WM8962) += snd-soc-imx-wm8962.o
+obj-$(CONFIG_SND_SOC_IMX_SPDIF) += snd-soc-imx-spdif.o
obj-$(CONFIG_SND_SOC_IMX_MC13783) += snd-soc-imx-mc13783.o
diff --git a/sound/soc/fsl/imx-spdif.c b/sound/soc/fsl/imx-spdif.c
new file mode 100644
index 0000000..af5b553
--- /dev/null
+++ b/sound/soc/fsl/imx-spdif.c
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2013 Freescale Semiconductor, Inc.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <sound/soc.h>
+
+struct imx_spdif_data {
+ struct snd_soc_dai_link dai[2];
+ struct snd_soc_card card;
+ struct platform_device *txdev;
+ struct platform_device *rxdev;
+};
+
+static int imx_spdif_audio_probe(struct platform_device *pdev)
+{
+ struct device_node *spdif_np, *np = pdev->dev.of_node;
+ struct platform_device *spdif_pdev;
+ struct imx_spdif_data *data;
+ int ret = 0, num_links = 0;
+
+ spdif_np = of_parse_phandle(np, "spdif-controller", 0);
+ if (!spdif_np) {
+ dev_err(&pdev->dev, "failed to find spdif-controller\n");
+ ret = -EINVAL;
+ goto end;
+ }
+
+ spdif_pdev = of_find_device_by_node(spdif_np);
+ if (!spdif_pdev) {
+ dev_err(&pdev->dev, "failed to find S/PDIF device\n");
+ ret = -EINVAL;
+ goto end;
+ }
+
+ data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+ if (!data) {
+ dev_err(&pdev->dev, "failed to allocate memory\n");
+ ret = -ENOMEM;
+ goto end;
+ }
+
+ if (of_property_read_bool(np, "spdif-out")) {
+ data->dai[num_links].name = "S/PDIF TX";
+ data->dai[num_links].stream_name = "S/PDIF PCM Playback";
+ data->dai[num_links].codec_dai_name = "dit-hifi";
+ data->dai[num_links].codec_name = "spdif-dit";
+ data->dai[num_links].cpu_of_node = spdif_np;
+ data->dai[num_links].platform_of_node = spdif_np;
+ num_links++;
+ }
+
+ if (of_property_read_bool(np, "spdif-in")) {
+ data->dai[num_links].name = "S/PDIF RX";
+ data->dai[num_links].stream_name = "S/PDIF PCM Capture";
+ data->dai[num_links].codec_dai_name = "dir-hifi";
+ data->dai[num_links].codec_name = "spdif-dir";
+ data->dai[num_links].cpu_of_node = spdif_np;
+ data->dai[num_links].platform_of_node = spdif_np;
+ num_links++;
+ }
+
+ if (!num_links) {
+ dev_err(&pdev->dev, "no enabled S/PDIF DAI link\n");
+ goto end;
+ }
+
+ data->card.dev = &pdev->dev;
+ data->card.num_links = num_links;
+ data->card.dai_link = data->dai;
+
+ ret = snd_soc_of_parse_card_name(&data->card, "model");
+ if (ret)
+ goto end;
+
+ data->txdev = platform_device_register_simple("spdif-dit", -1, NULL, 0);
+ if (IS_ERR(data->txdev)) {
+ ret = PTR_ERR(data->txdev);
+ dev_err(&pdev->dev, "register spdif-dit failed (%d)\n", ret);
+ goto end;
+ }
+
+ data->rxdev = platform_device_register_simple("spdif-dir", -1, NULL, 0);
+ if (IS_ERR(data->rxdev)) {
+ ret = PTR_ERR(data->rxdev);
+ dev_err(&pdev->dev, "register spdif-dir failed (%d)\n", ret);
+ goto error_dit;
+ }
+
+ ret = snd_soc_register_card(&data->card);
+ if (ret) {
+ dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
+ goto error_dir;
+ }
+
+ platform_set_drvdata(pdev, data);
+
+ goto end;
+
+error_dir:
+ platform_device_unregister(data->rxdev);
+error_dit:
+ platform_device_unregister(data->txdev);
+end:
+ if (spdif_np)
+ of_node_put(spdif_np);
+
+ return ret;
+}
+
+static int imx_spdif_audio_remove(struct platform_device *pdev)
+{
+ struct imx_spdif_data *data = platform_get_drvdata(pdev);
+
+ platform_device_unregister(data->rxdev);
+ platform_device_unregister(data->txdev);
+
+ snd_soc_unregister_card(&data->card);
+
+ return 0;
+}
+
+static const struct of_device_id imx_spdif_dt_ids[] = {
+ { .compatible = "fsl,imx-audio-spdif", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, imx_spdif_dt_ids);
+
+static struct platform_driver imx_spdif_driver = {
+ .driver = {
+ .name = "imx-spdif",
+ .owner = THIS_MODULE,
+ .of_match_table = imx_spdif_dt_ids,
+ },
+ .probe = imx_spdif_audio_probe,
+ .remove = imx_spdif_audio_remove,
+};
+
+module_platform_driver(imx_spdif_driver);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("Freescale i.MX S/PDIF machine driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:imx-spdif");
--
1.7.1
4
6
[alsa-devel] [PATCH 1/8] ASoC: dapm: Fix marking widgets dirty when a route is added
by Lars-Peter Clausen 27 Aug '13
by Lars-Peter Clausen 27 Aug '13
27 Aug '13
The current calls to dapm_mark_dirty() in snd_soc_dapm_add_path() are on a path
that is only reached if the sink widget is either a mixer or a mux. Move the
calls further up so they are called for all widget types.
Signed-off-by: Lars-Peter Clausen <lars(a)metafoo.de>
---
sound/soc/soc-dapm.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index d84bd0f..7e9afbc4 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -2374,6 +2374,9 @@ static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm,
wsource->ext = 1;
}
+ dapm_mark_dirty(wsource, "Route added");
+ dapm_mark_dirty(wsink, "Route added");
+
/* connect static paths */
if (control == NULL) {
list_add(&path->list, &dapm->card->paths);
@@ -2436,9 +2439,6 @@ static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm,
return 0;
}
- dapm_mark_dirty(wsource, "Route added");
- dapm_mark_dirty(wsink, "Route added");
-
return 0;
err:
kfree(path);
--
1.8.0
2
17
Hi Takashi,
Here is the patch series which fixes various issues being reported by users (out
of tree sadly)
The first three and and last one are marked to stable as would like these to be
fixed in older kernels as well. It would be good if you can send them as fixes
to linus for 3.11.
Rest can go in the merge window
Fixes:
- using lock for all operation was a very bad idead. This is bad as some of the
ioctls like drain, partial drain can be time consuming and thus prevent any
other operation while these are ongoing like Pause, Stop or timestamp query, so
fix this be removing bunch of ioctls not to use device lock.
- Now we dont have lock for pointer updates so this maybe racy, so use lock
for doing lowest level calculation.
- As disscused on our sample rate problem, lets move to use rate values and I
will fix the lib too. Since the driver are not upstream the impact of this
change wont be huge.
- Plus few fix like use snprintf, state chacks for pause, write etc..
Vinod Koul (9):
ALSA: Compress - dont use lock for all ioctls
ALSA: compress: use mutex in drain
ASoC: compress: dont aquire lock for draining states
ALSA: compress: use snprint instread of sprintf
ALSA: compres: wakeup the poll thread on pause
ALSA: compress: dont write when stream is paused
ALSA: compress: allow write when stream is setup
ALSA: compress: call pointer callback and updates under a lock
ALSA: compress: use rate values for passing sampling rates
include/sound/compress_driver.h | 2 +
include/uapi/sound/compress_offload.h | 2 +-
sound/core/compress_offload.c | 140 +++++++++++++++++++++++++-------
sound/soc/soc-compress.c | 10 +++
4 files changed, 122 insertions(+), 32 deletions(-)
Thanks
~Vinod
3
39
[alsa-devel] hda: Is it ok to enable SND_HDA_I915 to support Haswell Gfx power well by default?
by Lin, Mengdong 27 Aug '13
by Lin, Mengdong 27 Aug '13
27 Aug '13
Hi Takashi and David,
Is it okay to enable SND_HDA_I915 by default?
This would make it easy to upgrade kernel on Haswell. A user only needs to apply default configurations for the new kernel, and display audio can work automatically. The user need not have any idea about the display power well.
Now the user needs to manually enable SND_HDA_I915, otherwise display audio won't work since Gfx driver may turn off the power well which make both the controller and codec lose power.
Thanks
Mengdong
3
4