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
January 2020
- 133 participants
- 383 discussions
[alsa-devel] [PATCH v2] ASoC: max98090: save and restore SHDN when changing sensitive registers
by Tzung-Bi Shih 09 Jan '20
by Tzung-Bi Shih 09 Jan '20
09 Jan '20
According to the datasheet, there are some registers can only be changed
when SHDN is 0. Changing these settings during SHDN = 1 can compromise
device stability and performance specifications.
Saves SHDN before writing to these sensitive registers and restores SHDN
afterward.
Here is the register list codec driver of max98090 wants to change:
M98090_REG_QUICK_SYSTEM_CLOCK 0x04
M98090_REG_QUICK_SAMPLE_RATE 0x05
M98090_REG_DAI_INTERFACE 0x06
M98090_REG_DAC_PATH 0x07
M98090_REG_MIC_DIRECT_TO_ADC 0x08
M98090_REG_LINE_TO_ADC 0x09
M98090_REG_ANALOG_MIC_LOOP 0x0A
M98090_REG_ANALOG_LINE_LOOP 0x0B
M98090_REG_SYSTEM_CLOCK 0x1B
M98090_REG_CLOCK_MODE 0x1C
M98090_REG_CLOCK_RATIO_NI_MSB 0x1D
M98090_REG_CLOCK_RATIO_NI_LSB 0x1E
M98090_REG_CLOCK_RATIO_MI_MSB 0x1F
M98090_REG_CLOCK_RATIO_MI_LSB 0x20
M98090_REG_MASTER_MODE 0x21
M98090_REG_INTERFACE_FORMAT 0x22
M98090_REG_TDM_CONTROL 0x23
M98090_REG_TDM_FORMAT 0x24
M98090_REG_IO_CONFIGURATION 0x25
M98090_REG_FILTER_CONFIG 0x26
M98090_REG_INPUT_ENABLE 0x3E
M98090_REG_OUTPUT_ENABLE 0x3F
M98090_REG_BIAS_CONTROL 0x42
M98090_REG_DAC_CONTROL 0x43
M98090_REG_ADC_CONTROL 0x44
M98090_REG_DRC_TIMING 0x33
M98090_REG_DRC_COMPRESSOR 0x34
M98090_REG_DRC_EXPANDER 0x35
M98090_REG_DSP_FILTER_ENABLE 0x41
M98090_REG_EQUALIZER_BASE 0x46
M98090_REG_RECORD_BIQUAD_BASE 0xAF
M98090_REG_DIGITAL_MIC_ENABLE 0x13
M98090_REG_DIGITAL_MIC_CONFIG 0x14
Signed-off-by: Tzung-Bi Shih <tzungbi(a)google.com>
---
This patch is a follow up fix for the question:
https://mailman.alsa-project.org/pipermail/alsa-devel/2019-October/157364.h…
Changes from v1:
https://mailman.alsa-project.org/pipermail/alsa-devel/2019-November/158855.…
- fix a typo in commit message
- rebase to the latest for-next (a few line numbers changed)
sound/soc/codecs/max98090.c | 433 ++++++++++++++++++++++++++----------
sound/soc/codecs/max98090.h | 3 +-
2 files changed, 312 insertions(+), 124 deletions(-)
diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c
index e46b6ada13b1..da23810f958e 100644
--- a/sound/soc/codecs/max98090.c
+++ b/sound/soc/codecs/max98090.c
@@ -5,24 +5,149 @@
* Copyright 2011-2012 Maxim Integrated Products
*/
+#include <linux/acpi.h>
+#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/module.h>
+#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/slab.h>
-#include <linux/acpi.h>
-#include <linux/clk.h>
#include <sound/jack.h>
+#include <sound/max98090.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/tlv.h>
-#include <sound/max98090.h>
#include "max98090.h"
+static void max98090_shdn_save_locked(struct max98090_priv *max98090)
+{
+ int shdn = 0;
+
+ /* saved_shdn, saved_count, SHDN are protected by card->dapm_mutex */
+ regmap_read(max98090->regmap, M98090_REG_DEVICE_SHUTDOWN, &shdn);
+ max98090->saved_shdn |= shdn;
+ ++max98090->saved_count;
+
+ if (shdn)
+ regmap_write(max98090->regmap, M98090_REG_DEVICE_SHUTDOWN, 0x0);
+}
+
+static void max98090_shdn_restore_locked(struct max98090_priv *max98090)
+{
+ /* saved_shdn, saved_count, SHDN are protected by card->dapm_mutex */
+ if (--max98090->saved_count == 0) {
+ if (max98090->saved_shdn) {
+ regmap_write(max98090->regmap,
+ M98090_REG_DEVICE_SHUTDOWN,
+ M98090_SHDNN_MASK);
+ max98090->saved_shdn = 0;
+ }
+ }
+}
+
+static void max98090_shdn_save(struct max98090_priv *max98090)
+{
+ mutex_lock(&max98090->component->card->dapm_mutex);
+ max98090_shdn_save_locked(max98090);
+}
+
+static void max98090_shdn_restore(struct max98090_priv *max98090)
+{
+ max98090_shdn_restore_locked(max98090);
+ mutex_unlock(&max98090->component->card->dapm_mutex);
+}
+
+static int max98090_put_volsw(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component =
+ snd_soc_kcontrol_component(kcontrol);
+ struct max98090_priv *max98090 =
+ snd_soc_component_get_drvdata(component);
+ int ret;
+
+ max98090_shdn_save(max98090);
+ ret = snd_soc_put_volsw(kcontrol, ucontrol);
+ max98090_shdn_restore(max98090);
+
+ return ret;
+}
+
+static int max98090_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component =
+ snd_soc_kcontrol_component(kcontrol);
+ struct max98090_priv *max98090 =
+ snd_soc_component_get_drvdata(component);
+ int ret;
+
+ max98090_shdn_save(max98090);
+ ret = snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
+ max98090_shdn_restore(max98090);
+
+ return ret;
+}
+
+static int max98090_put_enum_double(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component =
+ snd_soc_kcontrol_component(kcontrol);
+ struct max98090_priv *max98090 =
+ snd_soc_component_get_drvdata(component);
+ int ret;
+
+ max98090_shdn_save(max98090);
+ ret = snd_soc_put_enum_double(kcontrol, ucontrol);
+ max98090_shdn_restore(max98090);
+
+ return ret;
+}
+
+static int max98090_bytes_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component =
+ snd_soc_kcontrol_component(kcontrol);
+ struct max98090_priv *max98090 =
+ snd_soc_component_get_drvdata(component);
+ int ret;
+
+ max98090_shdn_save(max98090);
+ ret = snd_soc_bytes_put(kcontrol, ucontrol);
+ max98090_shdn_restore(max98090);
+
+ return ret;
+}
+
+static int max98090_dapm_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_component *component =
+ snd_soc_dapm_to_component(w->dapm);
+ struct max98090_priv *max98090 =
+ snd_soc_component_get_drvdata(component);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ case SND_SOC_DAPM_PRE_PMD:
+ max98090_shdn_save_locked(max98090);
+ break;
+ case SND_SOC_DAPM_POST_PMU:
+ case SND_SOC_DAPM_POST_PMD:
+ max98090_shdn_restore_locked(max98090);
+ break;
+ }
+
+ return 0;
+}
+
/* Allows for sparsely populated register maps */
static const struct reg_default max98090_reg[] = {
{ 0x00, 0x00 }, /* 00 Software Reset */
@@ -506,10 +631,13 @@ static SOC_ENUM_SINGLE_DECL(max98090_adchp_enum,
max98090_pwr_perf_text);
static const struct snd_kcontrol_new max98090_snd_controls[] = {
- SOC_ENUM("MIC Bias VCM Bandgap", max98090_vcmbandgap_enum),
+ SOC_ENUM_EXT("MIC Bias VCM Bandgap", max98090_vcmbandgap_enum,
+ snd_soc_get_enum_double, max98090_put_enum_double),
- SOC_SINGLE("DMIC MIC Comp Filter Config", M98090_REG_DIGITAL_MIC_CONFIG,
- M98090_DMIC_COMP_SHIFT, M98090_DMIC_COMP_NUM - 1, 0),
+ SOC_SINGLE_EXT("DMIC MIC Comp Filter Config",
+ M98090_REG_DIGITAL_MIC_CONFIG,
+ M98090_DMIC_COMP_SHIFT, M98090_DMIC_COMP_NUM - 1, 0,
+ snd_soc_get_volsw, max98090_put_volsw),
SOC_SINGLE_EXT_TLV("MIC1 Boost Volume",
M98090_REG_MIC1_INPUT_LEVEL, M98090_MIC_PA1EN_SHIFT,
@@ -564,24 +692,34 @@ static const struct snd_kcontrol_new max98090_snd_controls[] = {
M98090_AVR_SHIFT, M98090_AVR_NUM - 1, 1,
max98090_av_tlv),
- SOC_ENUM("ADC Oversampling Rate", max98090_osr128_enum),
- SOC_SINGLE("ADC Quantizer Dither", M98090_REG_ADC_CONTROL,
- M98090_ADCDITHER_SHIFT, M98090_ADCDITHER_NUM - 1, 0),
- SOC_ENUM("ADC High Performance Mode", max98090_adchp_enum),
-
- SOC_SINGLE("DAC Mono Mode", M98090_REG_IO_CONFIGURATION,
- M98090_DMONO_SHIFT, M98090_DMONO_NUM - 1, 0),
- SOC_SINGLE("SDIN Mode", M98090_REG_IO_CONFIGURATION,
- M98090_SDIEN_SHIFT, M98090_SDIEN_NUM - 1, 0),
- SOC_SINGLE("SDOUT Mode", M98090_REG_IO_CONFIGURATION,
- M98090_SDOEN_SHIFT, M98090_SDOEN_NUM - 1, 0),
- SOC_SINGLE("SDOUT Hi-Z Mode", M98090_REG_IO_CONFIGURATION,
- M98090_HIZOFF_SHIFT, M98090_HIZOFF_NUM - 1, 1),
- SOC_ENUM("Filter Mode", max98090_mode_enum),
- SOC_SINGLE("Record Path DC Blocking", M98090_REG_FILTER_CONFIG,
- M98090_AHPF_SHIFT, M98090_AHPF_NUM - 1, 0),
- SOC_SINGLE("Playback Path DC Blocking", M98090_REG_FILTER_CONFIG,
- M98090_DHPF_SHIFT, M98090_DHPF_NUM - 1, 0),
+ SOC_ENUM_EXT("ADC Oversampling Rate", max98090_osr128_enum,
+ snd_soc_get_enum_double, max98090_put_enum_double),
+ SOC_SINGLE_EXT("ADC Quantizer Dither", M98090_REG_ADC_CONTROL,
+ M98090_ADCDITHER_SHIFT, M98090_ADCDITHER_NUM - 1, 0,
+ snd_soc_get_volsw, max98090_put_volsw),
+ SOC_ENUM_EXT("ADC High Performance Mode", max98090_adchp_enum,
+ snd_soc_get_enum_double, max98090_put_enum_double),
+
+ SOC_SINGLE_EXT("DAC Mono Mode", M98090_REG_IO_CONFIGURATION,
+ M98090_DMONO_SHIFT, M98090_DMONO_NUM - 1, 0,
+ snd_soc_get_volsw, max98090_put_volsw),
+ SOC_SINGLE_EXT("SDIN Mode", M98090_REG_IO_CONFIGURATION,
+ M98090_SDIEN_SHIFT, M98090_SDIEN_NUM - 1, 0,
+ snd_soc_get_volsw, max98090_put_volsw),
+ SOC_SINGLE_EXT("SDOUT Mode", M98090_REG_IO_CONFIGURATION,
+ M98090_SDOEN_SHIFT, M98090_SDOEN_NUM - 1, 0,
+ snd_soc_get_volsw, max98090_put_volsw),
+ SOC_SINGLE_EXT("SDOUT Hi-Z Mode", M98090_REG_IO_CONFIGURATION,
+ M98090_HIZOFF_SHIFT, M98090_HIZOFF_NUM - 1, 1,
+ snd_soc_get_volsw, max98090_put_volsw),
+ SOC_ENUM_EXT("Filter Mode", max98090_mode_enum,
+ snd_soc_get_enum_double, max98090_put_enum_double),
+ SOC_SINGLE_EXT("Record Path DC Blocking", M98090_REG_FILTER_CONFIG,
+ M98090_AHPF_SHIFT, M98090_AHPF_NUM - 1, 0,
+ snd_soc_get_volsw, max98090_put_volsw),
+ SOC_SINGLE_EXT("Playback Path DC Blocking", M98090_REG_FILTER_CONFIG,
+ M98090_DHPF_SHIFT, M98090_DHPF_NUM - 1, 0,
+ snd_soc_get_volsw, max98090_put_volsw),
SOC_SINGLE_TLV("Digital BQ Volume", M98090_REG_ADC_BIQUAD_LEVEL,
M98090_AVBQ_SHIFT, M98090_AVBQ_NUM - 1, 1, max98090_dv_tlv),
SOC_SINGLE_EXT_TLV("Digital Sidetone Volume",
@@ -594,13 +732,17 @@ static const struct snd_kcontrol_new max98090_snd_controls[] = {
SOC_SINGLE_TLV("Digital Volume", M98090_REG_DAI_PLAYBACK_LEVEL,
M98090_DV_SHIFT, M98090_DV_NUM - 1, 1,
max98090_dv_tlv),
- SND_SOC_BYTES("EQ Coefficients", M98090_REG_EQUALIZER_BASE, 105),
- SOC_SINGLE("Digital EQ 3 Band Switch", M98090_REG_DSP_FILTER_ENABLE,
- M98090_EQ3BANDEN_SHIFT, M98090_EQ3BANDEN_NUM - 1, 0),
- SOC_SINGLE("Digital EQ 5 Band Switch", M98090_REG_DSP_FILTER_ENABLE,
- M98090_EQ5BANDEN_SHIFT, M98090_EQ5BANDEN_NUM - 1, 0),
- SOC_SINGLE("Digital EQ 7 Band Switch", M98090_REG_DSP_FILTER_ENABLE,
- M98090_EQ7BANDEN_SHIFT, M98090_EQ7BANDEN_NUM - 1, 0),
+ SND_SOC_BYTES_E("EQ Coefficients", M98090_REG_EQUALIZER_BASE, 105,
+ snd_soc_bytes_get, max98090_bytes_put),
+ SOC_SINGLE_EXT("Digital EQ 3 Band Switch", M98090_REG_DSP_FILTER_ENABLE,
+ M98090_EQ3BANDEN_SHIFT, M98090_EQ3BANDEN_NUM - 1, 0,
+ snd_soc_get_volsw, max98090_put_volsw),
+ SOC_SINGLE_EXT("Digital EQ 5 Band Switch", M98090_REG_DSP_FILTER_ENABLE,
+ M98090_EQ5BANDEN_SHIFT, M98090_EQ5BANDEN_NUM - 1, 0,
+ snd_soc_get_volsw, max98090_put_volsw),
+ SOC_SINGLE_EXT("Digital EQ 7 Band Switch", M98090_REG_DSP_FILTER_ENABLE,
+ M98090_EQ7BANDEN_SHIFT, M98090_EQ7BANDEN_NUM - 1, 0,
+ snd_soc_get_volsw, max98090_put_volsw),
SOC_SINGLE("Digital EQ Clipping Detection", M98090_REG_DAI_PLAYBACK_LEVEL_EQ,
M98090_EQCLPN_SHIFT, M98090_EQCLPN_NUM - 1,
1),
@@ -608,25 +750,34 @@ static const struct snd_kcontrol_new max98090_snd_controls[] = {
M98090_DVEQ_SHIFT, M98090_DVEQ_NUM - 1, 1,
max98090_dv_tlv),
- SOC_SINGLE("ALC Enable", M98090_REG_DRC_TIMING,
- M98090_DRCEN_SHIFT, M98090_DRCEN_NUM - 1, 0),
- SOC_ENUM("ALC Attack Time", max98090_drcatk_enum),
- SOC_ENUM("ALC Release Time", max98090_drcrls_enum),
+ SOC_SINGLE_EXT("ALC Enable", M98090_REG_DRC_TIMING,
+ M98090_DRCEN_SHIFT, M98090_DRCEN_NUM - 1, 0,
+ snd_soc_get_volsw, max98090_put_volsw),
+ SOC_ENUM_EXT("ALC Attack Time", max98090_drcatk_enum,
+ snd_soc_get_enum_double, max98090_put_enum_double),
+ SOC_ENUM_EXT("ALC Release Time", max98090_drcrls_enum,
+ snd_soc_get_enum_double, max98090_put_enum_double),
SOC_SINGLE_TLV("ALC Make Up Volume", M98090_REG_DRC_GAIN,
M98090_DRCG_SHIFT, M98090_DRCG_NUM - 1, 0,
max98090_alcmakeup_tlv),
- SOC_ENUM("ALC Compression Ratio", max98090_alccmp_enum),
- SOC_ENUM("ALC Expansion Ratio", max98090_drcexp_enum),
- SOC_SINGLE_TLV("ALC Compression Threshold Volume",
+ SOC_ENUM_EXT("ALC Compression Ratio", max98090_alccmp_enum,
+ snd_soc_get_enum_double, max98090_put_enum_double),
+ SOC_ENUM_EXT("ALC Expansion Ratio", max98090_drcexp_enum,
+ snd_soc_get_enum_double, max98090_put_enum_double),
+ SOC_SINGLE_EXT_TLV("ALC Compression Threshold Volume",
M98090_REG_DRC_COMPRESSOR, M98090_DRCTHC_SHIFT,
- M98090_DRCTHC_NUM - 1, 1, max98090_alccomp_tlv),
- SOC_SINGLE_TLV("ALC Expansion Threshold Volume",
+ M98090_DRCTHC_NUM - 1, 1,
+ snd_soc_get_volsw, max98090_put_volsw, max98090_alccomp_tlv),
+ SOC_SINGLE_EXT_TLV("ALC Expansion Threshold Volume",
M98090_REG_DRC_EXPANDER, M98090_DRCTHE_SHIFT,
- M98090_DRCTHE_NUM - 1, 1, max98090_drcexp_tlv),
+ M98090_DRCTHE_NUM - 1, 1,
+ snd_soc_get_volsw, max98090_put_volsw, max98090_drcexp_tlv),
- SOC_ENUM("DAC HP Playback Performance Mode",
- max98090_dac_perfmode_enum),
- SOC_ENUM("DAC High Performance Mode", max98090_dachp_enum),
+ SOC_ENUM_EXT("DAC HP Playback Performance Mode",
+ max98090_dac_perfmode_enum,
+ snd_soc_get_enum_double, max98090_put_enum_double),
+ SOC_ENUM_EXT("DAC High Performance Mode", max98090_dachp_enum,
+ snd_soc_get_enum_double, max98090_put_enum_double),
SOC_SINGLE_TLV("Headphone Left Mixer Volume",
M98090_REG_HP_CONTROL, M98090_MIXHPLG_SHIFT,
@@ -684,9 +835,12 @@ static const struct snd_kcontrol_new max98090_snd_controls[] = {
SOC_SINGLE("Volume Adjustment Smoothing", M98090_REG_LEVEL_CONTROL,
M98090_VSENN_SHIFT, M98090_VSENN_NUM - 1, 1),
- SND_SOC_BYTES("Biquad Coefficients", M98090_REG_RECORD_BIQUAD_BASE, 15),
- SOC_SINGLE("Biquad Switch", M98090_REG_DSP_FILTER_ENABLE,
- M98090_ADCBQEN_SHIFT, M98090_ADCBQEN_NUM - 1, 0),
+ SND_SOC_BYTES_E("Biquad Coefficients",
+ M98090_REG_RECORD_BIQUAD_BASE, 15,
+ snd_soc_bytes_get, max98090_bytes_put),
+ SOC_SINGLE_EXT("Biquad Switch", M98090_REG_DSP_FILTER_ENABLE,
+ M98090_ADCBQEN_SHIFT, M98090_ADCBQEN_NUM - 1, 0,
+ snd_soc_get_volsw, max98090_put_volsw),
};
static const struct snd_kcontrol_new max98091_snd_controls[] = {
@@ -695,10 +849,12 @@ static const struct snd_kcontrol_new max98091_snd_controls[] = {
M98090_DMIC34_ZEROPAD_SHIFT,
M98090_DMIC34_ZEROPAD_NUM - 1, 0),
- SOC_ENUM("Filter DMIC34 Mode", max98090_filter_dmic34mode_enum),
- SOC_SINGLE("DMIC34 DC Blocking", M98090_REG_FILTER_CONFIG,
+ SOC_ENUM_EXT("Filter DMIC34 Mode", max98090_filter_dmic34mode_enum,
+ snd_soc_get_enum_double, max98090_put_enum_double),
+ SOC_SINGLE_EXT("DMIC34 DC Blocking", M98090_REG_FILTER_CONFIG,
M98090_FLT_DMIC34HPF_SHIFT,
- M98090_FLT_DMIC34HPF_NUM - 1, 0),
+ M98090_FLT_DMIC34HPF_NUM - 1, 0,
+ snd_soc_get_volsw, max98090_put_volsw),
SOC_SINGLE_TLV("DMIC3 Boost Volume", M98090_REG_DMIC3_VOLUME,
M98090_DMIC_AV3G_SHIFT, M98090_DMIC_AV3G_NUM - 1, 0,
@@ -716,8 +872,9 @@ static const struct snd_kcontrol_new max98091_snd_controls[] = {
SND_SOC_BYTES("DMIC34 Biquad Coefficients",
M98090_REG_DMIC34_BIQUAD_BASE, 15),
- SOC_SINGLE("DMIC34 Biquad Switch", M98090_REG_DSP_FILTER_ENABLE,
- M98090_DMIC34BQEN_SHIFT, M98090_DMIC34BQEN_NUM - 1, 0),
+ SOC_SINGLE_EXT("DMIC34 Biquad Switch", M98090_REG_DSP_FILTER_ENABLE,
+ M98090_DMIC34BQEN_SHIFT, M98090_DMIC34BQEN_NUM - 1, 0,
+ snd_soc_get_volsw, max98090_put_volsw),
SOC_SINGLE_TLV("DMIC34 BQ PreAttenuation Volume",
M98090_REG_DMIC34_BQ_PREATTEN, M98090_AV34BQ_SHIFT,
@@ -771,19 +928,6 @@ static int max98090_micinput_event(struct snd_soc_dapm_widget *w,
return 0;
}
-static int max98090_shdn_event(struct snd_soc_dapm_widget *w,
- struct snd_kcontrol *kcontrol, int event)
-{
- struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
- struct max98090_priv *max98090 = snd_soc_component_get_drvdata(component);
-
- if (event & SND_SOC_DAPM_POST_PMU)
- max98090->shdn_pending = true;
-
- return 0;
-
-}
-
static const char *mic1_mux_text[] = { "IN12", "IN56" };
static SOC_ENUM_SINGLE_DECL(mic1_mux_enum,
@@ -884,10 +1028,14 @@ static SOC_ENUM_SINGLE_DECL(ltenr_mux_enum,
lten_mux_text);
static const struct snd_kcontrol_new max98090_ltenl_mux =
- SOC_DAPM_ENUM("LTENL Mux", ltenl_mux_enum);
+ SOC_DAPM_ENUM_EXT("LTENL Mux", ltenl_mux_enum,
+ snd_soc_dapm_get_enum_double,
+ max98090_dapm_put_enum_double);
static const struct snd_kcontrol_new max98090_ltenr_mux =
- SOC_DAPM_ENUM("LTENR Mux", ltenr_mux_enum);
+ SOC_DAPM_ENUM_EXT("LTENR Mux", ltenr_mux_enum,
+ snd_soc_dapm_get_enum_double,
+ max98090_dapm_put_enum_double);
static const char *lben_mux_text[] = { "Normal", "Loopback" };
@@ -902,10 +1050,14 @@ static SOC_ENUM_SINGLE_DECL(lbenr_mux_enum,
lben_mux_text);
static const struct snd_kcontrol_new max98090_lbenl_mux =
- SOC_DAPM_ENUM("LBENL Mux", lbenl_mux_enum);
+ SOC_DAPM_ENUM_EXT("LBENL Mux", lbenl_mux_enum,
+ snd_soc_dapm_get_enum_double,
+ max98090_dapm_put_enum_double);
static const struct snd_kcontrol_new max98090_lbenr_mux =
- SOC_DAPM_ENUM("LBENR Mux", lbenr_mux_enum);
+ SOC_DAPM_ENUM_EXT("LBENR Mux", lbenr_mux_enum,
+ snd_soc_dapm_get_enum_double,
+ max98090_dapm_put_enum_double);
static const char *stenl_mux_text[] = { "Normal", "Sidetone Left" };
@@ -1072,21 +1224,25 @@ static const struct snd_soc_dapm_widget max98090_dapm_widgets[] = {
SND_SOC_DAPM_INPUT("IN56"),
SND_SOC_DAPM_SUPPLY("MICBIAS", M98090_REG_INPUT_ENABLE,
- M98090_MBEN_SHIFT, 0, NULL, 0),
+ M98090_MBEN_SHIFT, 0, max98090_dapm_event,
+ SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
SND_SOC_DAPM_SUPPLY("SHDN", M98090_REG_DEVICE_SHUTDOWN,
M98090_SHDNN_SHIFT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("SDIEN", M98090_REG_IO_CONFIGURATION,
- M98090_SDIEN_SHIFT, 0, NULL, 0),
+ M98090_SDIEN_SHIFT, 0, max98090_dapm_event,
+ SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
SND_SOC_DAPM_SUPPLY("SDOEN", M98090_REG_IO_CONFIGURATION,
- M98090_SDOEN_SHIFT, 0, NULL, 0),
+ M98090_SDOEN_SHIFT, 0, max98090_dapm_event,
+ SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
SND_SOC_DAPM_SUPPLY("DMICL_ENA", M98090_REG_DIGITAL_MIC_ENABLE,
- M98090_DIGMICL_SHIFT, 0, max98090_shdn_event,
- SND_SOC_DAPM_POST_PMU),
+ M98090_DIGMICL_SHIFT, 0, max98090_dapm_event,
+ SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
SND_SOC_DAPM_SUPPLY("DMICR_ENA", M98090_REG_DIGITAL_MIC_ENABLE,
- M98090_DIGMICR_SHIFT, 0, max98090_shdn_event,
- SND_SOC_DAPM_POST_PMU),
+ M98090_DIGMICR_SHIFT, 0, max98090_dapm_event,
+ SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
SND_SOC_DAPM_SUPPLY("AHPF", M98090_REG_FILTER_CONFIG,
- M98090_AHPF_SHIFT, 0, NULL, 0),
+ M98090_AHPF_SHIFT, 0, max98090_dapm_event,
+ SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
/*
* Note: Sysclk and misc power supplies are taken care of by SHDN
@@ -1116,10 +1272,12 @@ static const struct snd_soc_dapm_widget max98090_dapm_widgets[] = {
&max98090_lineb_mixer_controls[0],
ARRAY_SIZE(max98090_lineb_mixer_controls)),
- SND_SOC_DAPM_PGA("LINEA Input", M98090_REG_INPUT_ENABLE,
- M98090_LINEAEN_SHIFT, 0, NULL, 0),
- SND_SOC_DAPM_PGA("LINEB Input", M98090_REG_INPUT_ENABLE,
- M98090_LINEBEN_SHIFT, 0, NULL, 0),
+ SND_SOC_DAPM_PGA_E("LINEA Input", M98090_REG_INPUT_ENABLE,
+ M98090_LINEAEN_SHIFT, 0, NULL, 0, max98090_dapm_event,
+ SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
+ SND_SOC_DAPM_PGA_E("LINEB Input", M98090_REG_INPUT_ENABLE,
+ M98090_LINEBEN_SHIFT, 0, NULL, 0, max98090_dapm_event,
+ SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
SND_SOC_DAPM_MIXER("Left ADC Mixer", SND_SOC_NOPM, 0, 0,
&max98090_left_adc_mixer_controls[0],
@@ -1130,11 +1288,11 @@ static const struct snd_soc_dapm_widget max98090_dapm_widgets[] = {
ARRAY_SIZE(max98090_right_adc_mixer_controls)),
SND_SOC_DAPM_ADC_E("ADCL", NULL, M98090_REG_INPUT_ENABLE,
- M98090_ADLEN_SHIFT, 0, max98090_shdn_event,
- SND_SOC_DAPM_POST_PMU),
+ M98090_ADLEN_SHIFT, 0, max98090_dapm_event,
+ SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
SND_SOC_DAPM_ADC_E("ADCR", NULL, M98090_REG_INPUT_ENABLE,
- M98090_ADREN_SHIFT, 0, max98090_shdn_event,
- SND_SOC_DAPM_POST_PMU),
+ M98090_ADREN_SHIFT, 0, max98090_dapm_event,
+ SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
SND_SOC_DAPM_AIF_OUT("AIFOUTL", "HiFi Capture", 0,
SND_SOC_NOPM, 0, 0),
@@ -1162,10 +1320,12 @@ static const struct snd_soc_dapm_widget max98090_dapm_widgets[] = {
SND_SOC_DAPM_AIF_IN("AIFINL", "HiFi Playback", 0, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_AIF_IN("AIFINR", "HiFi Playback", 1, SND_SOC_NOPM, 0, 0),
- SND_SOC_DAPM_DAC("DACL", NULL, M98090_REG_OUTPUT_ENABLE,
- M98090_DALEN_SHIFT, 0),
- SND_SOC_DAPM_DAC("DACR", NULL, M98090_REG_OUTPUT_ENABLE,
- M98090_DAREN_SHIFT, 0),
+ SND_SOC_DAPM_DAC_E("DACL", NULL, M98090_REG_OUTPUT_ENABLE,
+ M98090_DALEN_SHIFT, 0, max98090_dapm_event,
+ SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
+ SND_SOC_DAPM_DAC_E("DACR", NULL, M98090_REG_OUTPUT_ENABLE,
+ M98090_DAREN_SHIFT, 0, max98090_dapm_event,
+ SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
SND_SOC_DAPM_MIXER("Left Headphone Mixer", SND_SOC_NOPM, 0, 0,
&max98090_left_hp_mixer_controls[0],
@@ -1200,20 +1360,26 @@ static const struct snd_soc_dapm_widget max98090_dapm_widgets[] = {
SND_SOC_DAPM_MUX("MIXHPRSEL Mux", SND_SOC_NOPM, 0, 0,
&max98090_mixhprsel_mux),
- SND_SOC_DAPM_PGA("HP Left Out", M98090_REG_OUTPUT_ENABLE,
- M98090_HPLEN_SHIFT, 0, NULL, 0),
- SND_SOC_DAPM_PGA("HP Right Out", M98090_REG_OUTPUT_ENABLE,
- M98090_HPREN_SHIFT, 0, NULL, 0),
-
- SND_SOC_DAPM_PGA("SPK Left Out", M98090_REG_OUTPUT_ENABLE,
- M98090_SPLEN_SHIFT, 0, NULL, 0),
- SND_SOC_DAPM_PGA("SPK Right Out", M98090_REG_OUTPUT_ENABLE,
- M98090_SPREN_SHIFT, 0, NULL, 0),
-
- SND_SOC_DAPM_PGA("RCV Left Out", M98090_REG_OUTPUT_ENABLE,
- M98090_RCVLEN_SHIFT, 0, NULL, 0),
- SND_SOC_DAPM_PGA("RCV Right Out", M98090_REG_OUTPUT_ENABLE,
- M98090_RCVREN_SHIFT, 0, NULL, 0),
+ SND_SOC_DAPM_PGA_E("HP Left Out", M98090_REG_OUTPUT_ENABLE,
+ M98090_HPLEN_SHIFT, 0, NULL, 0, max98090_dapm_event,
+ SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
+ SND_SOC_DAPM_PGA_E("HP Right Out", M98090_REG_OUTPUT_ENABLE,
+ M98090_HPREN_SHIFT, 0, NULL, 0, max98090_dapm_event,
+ SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
+
+ SND_SOC_DAPM_PGA_E("SPK Left Out", M98090_REG_OUTPUT_ENABLE,
+ M98090_SPLEN_SHIFT, 0, NULL, 0, max98090_dapm_event,
+ SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
+ SND_SOC_DAPM_PGA_E("SPK Right Out", M98090_REG_OUTPUT_ENABLE,
+ M98090_SPREN_SHIFT, 0, NULL, 0, max98090_dapm_event,
+ SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
+
+ SND_SOC_DAPM_PGA_E("RCV Left Out", M98090_REG_OUTPUT_ENABLE,
+ M98090_RCVLEN_SHIFT, 0, NULL, 0, max98090_dapm_event,
+ SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
+ SND_SOC_DAPM_PGA_E("RCV Right Out", M98090_REG_OUTPUT_ENABLE,
+ M98090_RCVREN_SHIFT, 0, NULL, 0, max98090_dapm_event,
+ SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
SND_SOC_DAPM_OUTPUT("HPL"),
SND_SOC_DAPM_OUTPUT("HPR"),
@@ -1228,9 +1394,11 @@ static const struct snd_soc_dapm_widget max98091_dapm_widgets[] = {
SND_SOC_DAPM_INPUT("DMIC4"),
SND_SOC_DAPM_SUPPLY("DMIC3_ENA", M98090_REG_DIGITAL_MIC_ENABLE,
- M98090_DIGMIC3_SHIFT, 0, NULL, 0),
+ M98090_DIGMIC3_SHIFT, 0, max98090_dapm_event,
+ SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
SND_SOC_DAPM_SUPPLY("DMIC4_ENA", M98090_REG_DIGITAL_MIC_ENABLE,
- M98090_DIGMIC4_SHIFT, 0, NULL, 0),
+ M98090_DIGMIC4_SHIFT, 0, max98090_dapm_event,
+ SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
};
static const struct snd_soc_dapm_route max98090_dapm_routes[] = {
@@ -1501,6 +1669,11 @@ static void max98090_configure_bclk(struct snd_soc_component *component)
return;
}
+ /*
+ * Master mode: no need to save and restore SHDN for the following
+ * sensitive registers.
+ */
+
/* Check for supported PCLK to LRCLK ratios */
for (i = 0; i < ARRAY_SIZE(pclk_rates); i++) {
if ((pclk_rates[i] == max98090->sysclk) &&
@@ -1587,12 +1760,14 @@ static int max98090_dai_set_fmt(struct snd_soc_dai *codec_dai,
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBS_CFS:
/* Set to slave mode PLL - MAS mode off */
+ max98090_shdn_save(max98090);
snd_soc_component_write(component,
M98090_REG_CLOCK_RATIO_NI_MSB, 0x00);
snd_soc_component_write(component,
M98090_REG_CLOCK_RATIO_NI_LSB, 0x00);
snd_soc_component_update_bits(component, M98090_REG_CLOCK_MODE,
M98090_USE_M1_MASK, 0);
+ max98090_shdn_restore(max98090);
max98090->master = false;
break;
case SND_SOC_DAIFMT_CBM_CFM:
@@ -1618,7 +1793,9 @@ static int max98090_dai_set_fmt(struct snd_soc_dai *codec_dai,
dev_err(component->dev, "DAI clock mode unsupported");
return -EINVAL;
}
+ max98090_shdn_save(max98090);
snd_soc_component_write(component, M98090_REG_MASTER_MODE, regval);
+ max98090_shdn_restore(max98090);
regval = 0;
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
@@ -1663,8 +1840,10 @@ static int max98090_dai_set_fmt(struct snd_soc_dai *codec_dai,
if (max98090->tdm_slots > 1)
regval ^= M98090_BCI_MASK;
+ max98090_shdn_save(max98090);
snd_soc_component_write(component,
M98090_REG_INTERFACE_FORMAT, regval);
+ max98090_shdn_restore(max98090);
}
return 0;
@@ -1676,6 +1855,7 @@ static int max98090_set_tdm_slot(struct snd_soc_dai *codec_dai,
struct snd_soc_component *component = codec_dai->component;
struct max98090_priv *max98090 = snd_soc_component_get_drvdata(component);
struct max98090_cdata *cdata;
+
cdata = &max98090->dai[0];
if (slots < 0 || slots > 4)
@@ -1685,6 +1865,7 @@ static int max98090_set_tdm_slot(struct snd_soc_dai *codec_dai,
max98090->tdm_width = slot_width;
if (max98090->tdm_slots > 1) {
+ max98090_shdn_save(max98090);
/* SLOTL SLOTR SLOTDLY */
snd_soc_component_write(component, M98090_REG_TDM_FORMAT,
0 << M98090_TDM_SLOTL_SHIFT |
@@ -1695,6 +1876,7 @@ static int max98090_set_tdm_slot(struct snd_soc_dai *codec_dai,
snd_soc_component_update_bits(component, M98090_REG_TDM_CONTROL,
M98090_TDM_MASK,
M98090_TDM_MASK);
+ max98090_shdn_restore(max98090);
}
/*
@@ -1894,6 +2076,7 @@ static int max98090_configure_dmic(struct max98090_priv *max98090,
dmic_freq = dmic_table[pclk_index].settings[micclk_index].freq;
dmic_comp = dmic_table[pclk_index].settings[micclk_index].comp[i];
+ max98090_shdn_save(max98090);
regmap_update_bits(max98090->regmap, M98090_REG_DIGITAL_MIC_ENABLE,
M98090_MICCLK_MASK,
micclk_index << M98090_MICCLK_SHIFT);
@@ -1902,6 +2085,7 @@ static int max98090_configure_dmic(struct max98090_priv *max98090,
M98090_DMIC_COMP_MASK | M98090_DMIC_FREQ_MASK,
dmic_comp << M98090_DMIC_COMP_SHIFT |
dmic_freq << M98090_DMIC_FREQ_SHIFT);
+ max98090_shdn_restore(max98090);
return 0;
}
@@ -1938,8 +2122,10 @@ static int max98090_dai_hw_params(struct snd_pcm_substream *substream,
switch (params_width(params)) {
case 16:
+ max98090_shdn_save(max98090);
snd_soc_component_update_bits(component, M98090_REG_INTERFACE_FORMAT,
M98090_WS_MASK, 0);
+ max98090_shdn_restore(max98090);
break;
default:
return -EINVAL;
@@ -1950,6 +2136,7 @@ static int max98090_dai_hw_params(struct snd_pcm_substream *substream,
cdata->rate = max98090->lrclk;
+ max98090_shdn_save(max98090);
/* Update filter mode */
if (max98090->lrclk < 24000)
snd_soc_component_update_bits(component, M98090_REG_FILTER_CONFIG,
@@ -1965,6 +2152,7 @@ static int max98090_dai_hw_params(struct snd_pcm_substream *substream,
else
snd_soc_component_update_bits(component, M98090_REG_FILTER_CONFIG,
M98090_DHF_MASK, M98090_DHF_MASK);
+ max98090_shdn_restore(max98090);
max98090_configure_dmic(max98090, max98090->dmic_freq, max98090->pclk,
max98090->lrclk);
@@ -1995,6 +2183,7 @@ static int max98090_dai_set_sysclk(struct snd_soc_dai *dai,
* 0x02 (when master clk is 20MHz to 40MHz)..
* 0x03 (when master clk is 40MHz to 60MHz)..
*/
+ max98090_shdn_save(max98090);
if ((freq >= 10000000) && (freq <= 20000000)) {
snd_soc_component_write(component, M98090_REG_SYSTEM_CLOCK,
M98090_PSCLK_DIV1);
@@ -2009,8 +2198,10 @@ static int max98090_dai_set_sysclk(struct snd_soc_dai *dai,
max98090->pclk = freq >> 2;
} else {
dev_err(component->dev, "Invalid master clock frequency\n");
+ max98090_shdn_restore(max98090);
return -EINVAL;
}
+ max98090_shdn_restore(max98090);
max98090->sysclk = freq;
@@ -2122,10 +2313,12 @@ static void max98090_pll_work(struct max98090_priv *max98090)
*/
/* Toggle shutdown OFF then ON */
+ mutex_lock(&component->card->dapm_mutex);
snd_soc_component_update_bits(component, M98090_REG_DEVICE_SHUTDOWN,
M98090_SHDNN_MASK, 0);
snd_soc_component_update_bits(component, M98090_REG_DEVICE_SHUTDOWN,
M98090_SHDNN_MASK, M98090_SHDNN_MASK);
+ mutex_unlock(&component->card->dapm_mutex);
for (i = 0; i < 10; ++i) {
/* Give PLL time to lock */
@@ -2448,7 +2641,12 @@ static int max98090_probe(struct snd_soc_component *component)
*/
snd_soc_component_read32(component, M98090_REG_DEVICE_STATUS);
- /* High Performance is default */
+ /*
+ * SHDN should be 0 at the point, no need to save/restore for the
+ * following registers.
+ *
+ * High Performance is default
+ */
snd_soc_component_update_bits(component, M98090_REG_DAC_CONTROL,
M98090_DACHP_MASK,
1 << M98090_DACHP_SHIFT);
@@ -2459,7 +2657,12 @@ static int max98090_probe(struct snd_soc_component *component)
M98090_ADCHP_MASK,
1 << M98090_ADCHP_SHIFT);
- /* Turn on VCM bandgap reference */
+ /*
+ * SHDN should be 0 at the point, no need to save/restore for the
+ * following registers.
+ *
+ * Turn on VCM bandgap reference
+ */
snd_soc_component_write(component, M98090_REG_BIAS_CONTROL,
M98090_VCM_MODE_MASK);
@@ -2491,25 +2694,9 @@ static void max98090_remove(struct snd_soc_component *component)
max98090->component = NULL;
}
-static void max98090_seq_notifier(struct snd_soc_component *component,
- enum snd_soc_dapm_type event, int subseq)
-{
- struct max98090_priv *max98090 = snd_soc_component_get_drvdata(component);
-
- if (max98090->shdn_pending) {
- snd_soc_component_update_bits(component, M98090_REG_DEVICE_SHUTDOWN,
- M98090_SHDNN_MASK, 0);
- msleep(40);
- snd_soc_component_update_bits(component, M98090_REG_DEVICE_SHUTDOWN,
- M98090_SHDNN_MASK, M98090_SHDNN_MASK);
- max98090->shdn_pending = false;
- }
-}
-
static const struct snd_soc_component_driver soc_component_dev_max98090 = {
.probe = max98090_probe,
.remove = max98090_remove,
- .seq_notifier = max98090_seq_notifier,
.set_bias_level = max98090_set_bias_level,
.idle_bias_on = 1,
.use_pmdown_time = 1,
diff --git a/sound/soc/codecs/max98090.h b/sound/soc/codecs/max98090.h
index a197114b0dad..0a31708b7df7 100644
--- a/sound/soc/codecs/max98090.h
+++ b/sound/soc/codecs/max98090.h
@@ -1539,7 +1539,8 @@ struct max98090_priv {
unsigned int pa2en;
unsigned int sidetone;
bool master;
- bool shdn_pending;
+ int saved_count;
+ int saved_shdn;
};
int max98090_mic_detect(struct snd_soc_component *component,
--
2.24.0.432.g9d3f5f5b63-goog
3
20
alsa-project/alsa-lib pull request #21 was opened from cujomalainey:
v2 changes
Dropped Jack* as it looks like we may need to do some renaming internally.
Dropped Gain controls as we are adjusting our definitions.
Dropped disable software volume per comments and will look at removing internally
Notes:
Per request regarding CaptureChannelMap, is it work changing the format if the current format transfers directly to alsa plugin inputs?
Apologies for the multi month delay between versions
Request URL : https://github.com/alsa-project/alsa-lib/pull/21
Patch URL : https://github.com/alsa-project/alsa-lib/pull/21.patch
Repository URL: https://github.com/alsa-project/alsa-lib
1
0
09 Jan '20
From: Jeff Chang <jeff_chang(a)richtek.com>
The MT6660 is a boosted BTL class-D amplifier with V/I sensing.
A built-in DC-DC step-up converter is used to provide efficient
power for class-D amplifier with multi-level class-G operation.
The digital audio interface supports I2S, left-justified,
right-justified, TDM and DSP A/B format for audio in with a data
out used for chip information like voltage sense and current
sense, which are able to be monitored via DATAO through proper
Signed-off-by: Jeff Chang <jeff_chang(a)richtek.com>
---
Documentation/devicetree/bindings/sound/mt6660.txt | 53 ++
sound/soc/codecs/Kconfig | 11 +
sound/soc/codecs/Makefile | 2 +
sound/soc/codecs/mt6660.c | 628 +++++++++++++++++++++
sound/soc/codecs/mt6660.h | 75 +++
5 files changed, 769 insertions(+)
create mode 100644 Documentation/devicetree/bindings/sound/mt6660.txt
create mode 100644 sound/soc/codecs/mt6660.c
create mode 100644 sound/soc/codecs/mt6660.h
changelogs between v4 & v3
- remove unnecessary kcontrols.
- modify copy right header.
- use dev_dbg instead of dev_info.
- add necessary debug message.
- add DT binding documentation.
- add space before } at every table.
changelogs between v3 & v2
- modify MT6660 Kconfig, remove unnecessary selection.
- remove my own debug io interface. use standard regmap for debugging.
- remove regmap volatile ops, we do not use cache.
- remove component io read/write function, use snd_soc_component_init_regmap.
- remove init setting write code. Using parsing dts to set them.
- remove unnecessary pr_info log message.
- remove mt6660_component_put_volsw. Using snd_soc_get_volsw
diff --git a/Documentation/devicetree/bindings/sound/mt6660.txt b/Documentation/devicetree/bindings/sound/mt6660.txt
new file mode 100644
index 0000000..2a1736b
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/mt6660.txt
@@ -0,0 +1,53 @@
+MT6660 MediaTek Speaker Amplifier
+
+This device supports I2C mode only.
+
+Required properties:
+
+ - compatible : "mediatek,mt6660"
+
+ - reg : The I2C slave address
+
+Optional properties:
+
+ - rt,init_setting_num : The initial register setting element number.
+
+ - rt,init_setting_addr : the addreses array for INIT Setting table.
+
+ - rt,init_setting_mask : the mask array for INIT Setting table.
+
+ - rt,init_setting_val : the value array for INIT Setting table.
+
+Example:
+
+ mt6660@34 {
+ status = "ok";
+ compatible = "mediatek,mt6660";
+ reg = <0x34>;
+ rt,init_setting_num = <26>;
+ rt,init_setting_addr =
+ <0x20 0x30 0x50 0xB1
+ 0xD3 0xE0 0x98 0xB9
+ 0xB7 0xB6 0x6B 0x07
+ 0xBB 0x69 0xBD 0x70
+ 0x7C 0x46 0x1A 0x1B
+ 0x51 0xA2 0x33 0x4C
+ 0x15 0x68>;
+ rt,init_setting_mask =
+ <0x80 0x01 0x1c 0x0c
+ 0x03 0x01 0x44 0xff
+ 0x7777 0x07 0xe0 0xff
+ 0xff 0xff 0xffff 0xff
+ 0xff 0xff 0xffffffff 0xffffffff
+ 0xff 0xff 0xffff 0xffff
+ 0x1800 0x1f>;
+ rt,init_setting_val =
+ <0x00 0x00 0x04 0x00
+ 0x03 0x00 0x04 0x82
+ 0x7273 0x03 0x20 0x70
+ 0x20 0x40 0x17f8 0x15
+ 0x00 0x1d 0x7fdb7ffe 0x7fdb7ffe
+ 0x58 0xce 0x7fff 0x0116
+ 0x0800 0x07>;
+ };
+
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 229cc89..f135fbb 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -122,6 +122,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_ML26124 if I2C
select SND_SOC_MT6351 if MTK_PMIC_WRAP
select SND_SOC_MT6358 if MTK_PMIC_WRAP
+ select SND_SOC_MT6660 if I2C
select SND_SOC_NAU8540 if I2C
select SND_SOC_NAU8810 if I2C
select SND_SOC_NAU8822 if I2C
@@ -1465,6 +1466,16 @@ config SND_SOC_MT6358
Enable support for the platform which uses MT6358 as
external codec device.
+config SND_SOC_MT6660
+ tristate "Mediatek MT6660 Speaker Amplifier"
+ depends on I2C
+ help
+ MediaTek MT6660 is a smart power amplifier which contain
+ speaker protection, multi-band DRC, equalizer functions.
+ Select N if you don't have MT6660 on board.
+ Select M to build this as module.
+
+
config SND_SOC_NAU8540
tristate "Nuvoton Technology Corporation NAU85L40 CODEC"
depends on I2C
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index c498373..2b6814c 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -119,6 +119,7 @@ snd-soc-msm8916-analog-objs := msm8916-wcd-analog.o
snd-soc-msm8916-digital-objs := msm8916-wcd-digital.o
snd-soc-mt6351-objs := mt6351.o
snd-soc-mt6358-objs := mt6358.o
+snd-soc-mt6660-objs := mt6660.o
snd-soc-nau8540-objs := nau8540.o
snd-soc-nau8810-objs := nau8810.o
snd-soc-nau8822-objs := nau8822.o
@@ -403,6 +404,7 @@ obj-$(CONFIG_SND_SOC_MSM8916_WCD_ANALOG) +=snd-soc-msm8916-analog.o
obj-$(CONFIG_SND_SOC_MSM8916_WCD_DIGITAL) +=snd-soc-msm8916-digital.o
obj-$(CONFIG_SND_SOC_MT6351) += snd-soc-mt6351.o
obj-$(CONFIG_SND_SOC_MT6358) += snd-soc-mt6358.o
+obj-$(CONFIG_SND_SOC_MT6660) += snd-soc-mt6660.o
obj-$(CONFIG_SND_SOC_NAU8540) += snd-soc-nau8540.o
obj-$(CONFIG_SND_SOC_NAU8810) += snd-soc-nau8810.o
obj-$(CONFIG_SND_SOC_NAU8822) += snd-soc-nau8822.o
diff --git a/sound/soc/codecs/mt6660.c b/sound/soc/codecs/mt6660.c
new file mode 100644
index 0000000..b8fc53b
--- /dev/null
+++ b/sound/soc/codecs/mt6660.c
@@ -0,0 +1,628 @@
+// SPDX-License-Identifier: GPL-2.0 //
+
+// Copyright (c) 2019 MediaTek Inc.
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/pm_runtime.h>
+#include <linux/delay.h>
+#include <sound/soc.h>
+#include <sound/tlv.h>
+#include <sound/pcm_params.h>
+#include <linux/debugfs.h>
+
+#include "mt6660.h"
+
+struct codec_reg_val {
+ u32 addr;
+ u32 mask;
+ u32 data;
+};
+
+struct reg_size_table {
+ u32 addr;
+ u8 size;
+};
+
+static const struct reg_size_table mt6660_reg_size_table[] = {
+ { MT6660_REG_HPF1_COEF, 4 },
+ { MT6660_REG_HPF2_COEF, 4 },
+ { MT6660_REG_TDM_CFG3, 2 },
+ { MT6660_REG_RESV17, 2 },
+ { MT6660_REG_RESV23, 2 },
+ { MT6660_REG_SIGMAX, 2 },
+ { MT6660_REG_DEVID, 2 },
+ { MT6660_REG_HCLIP_CTRL, 2 },
+ { MT6660_REG_DA_GAIN, 2 },
+};
+
+static int mt6660_get_reg_size(uint32_t addr)
+{
+ int i = 0;
+
+ for (i = 0; i < ARRAY_SIZE(mt6660_reg_size_table); i++) {
+ if (mt6660_reg_size_table[i].addr == addr)
+ return mt6660_reg_size_table[i].size;
+ }
+ return 1;
+}
+
+static int mt6660_reg_write(void *context, unsigned int reg, unsigned int val)
+{
+ struct mt6660_chip *chip = context;
+ int size = mt6660_get_reg_size(reg);
+ u8 reg_data[4] = {0};
+ int i = 0, ret = 0;
+
+ for (i = 0; i < size; i++)
+ reg_data[size - i - 1] = (val >> (8 * i)) & 0xff;
+
+ ret = i2c_smbus_write_i2c_block_data(chip->i2c, reg, size, reg_data);
+ if (ret < 0)
+ return ret;
+ return 0;
+}
+
+static int mt6660_reg_read(void *context, unsigned int reg, unsigned int *val)
+{
+ struct mt6660_chip *chip = context;
+ int size = mt6660_get_reg_size(reg);
+ int i = 0, ret = 0;
+ u8 data[4] = {0};
+ u32 reg_data = 0;
+
+ ret = i2c_smbus_read_i2c_block_data(chip->i2c, reg, size, data);
+ if (ret < 0)
+ return ret;
+ for (i = 0; i < size; i++) {
+ reg_data <<= 8;
+ reg_data |= data[i];
+ }
+ *val = reg_data;
+ return 0;
+}
+
+static struct regmap_config mt6660_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 32,
+ .reg_write = mt6660_reg_write,
+ .reg_read = mt6660_reg_read,
+};
+
+static int mt6660_codec_dac_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ usleep_range(1000, 1100);
+ break;
+ }
+ return 0;
+}
+
+static int mt6660_codec_classd_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_component *component =
+ snd_soc_dapm_to_component(w->dapm);
+ int ret = 0;
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ dev_dbg(component->dev,
+ "%s: before classd turn on\n", __func__);
+ /* config to adaptive mode */
+ ret = snd_soc_component_update_bits(component,
+ MT6660_REG_BST_CTRL, 0x03, 0x03);
+ if (ret < 0) {
+ dev_err(component->dev, "config mode adaptive fail\n");
+ return ret;
+ }
+ break;
+ case SND_SOC_DAPM_POST_PMU:
+ /* voltage sensing enable */
+ ret = snd_soc_component_update_bits(component,
+ MT6660_REG_RESV7, 0x04, 0x04);
+ if (ret < 0) {
+ dev_err(component->dev,
+ "enable voltage sensing fail\n");
+ return ret;
+ }
+ dev_dbg(component->dev, "Amp on\n");
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ dev_dbg(component->dev, "Amp off\n");
+ /* voltage sensing disable */
+ ret = snd_soc_component_update_bits(component,
+ MT6660_REG_RESV7, 0x04, 0x00);
+ if (ret < 0) {
+ dev_err(component->dev,
+ "disable voltage sensing fail\n");
+ return ret;
+ }
+ /* pop-noise improvement 1 */
+ ret = snd_soc_component_update_bits(component,
+ MT6660_REG_RESV10, 0x10, 0x10);
+ if (ret < 0) {
+ dev_err(component->dev,
+ "pop-noise improvement 1 fail\n");
+ return ret;
+ }
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ dev_dbg(component->dev,
+ "%s: after classd turn off\n", __func__);
+ /* pop-noise improvement 2 */
+ ret = snd_soc_component_update_bits(component,
+ MT6660_REG_RESV10, 0x10, 0x00);
+ if (ret < 0) {
+ dev_err(component->dev,
+ "pop-noise improvement 2 fail\n");
+ return ret;
+ }
+ /* config to off mode */
+ ret = snd_soc_component_update_bits(component,
+ MT6660_REG_BST_CTRL, 0x03, 0x00);
+ if (ret < 0) {
+ dev_err(component->dev, "config mode off fail\n");
+ return ret;
+ }
+ break;
+ }
+ return 0;
+}
+
+static const struct snd_soc_dapm_widget mt6660_component_dapm_widgets[] = {
+ SND_SOC_DAPM_DAC_E("DAC", NULL, MT6660_REG_PLL_CFG1,
+ 0, 1, mt6660_codec_dac_event, SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_ADC("VI ADC", NULL, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_PGA("PGA", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_OUT_DRV_E("ClassD", MT6660_REG_SYSTEM_CTRL, 2, 0,
+ NULL, 0, mt6660_codec_classd_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_OUTPUT("OUTP"),
+ SND_SOC_DAPM_OUTPUT("OUTN"),
+};
+
+static const struct snd_soc_dapm_route mt6660_component_dapm_routes[] = {
+ { "DAC", NULL, "aif_playback" },
+ { "PGA", NULL, "DAC" },
+ { "ClassD", NULL, "PGA" },
+ { "OUTP", NULL, "ClassD" },
+ { "OUTN", NULL, "ClassD" },
+ { "VI ADC", NULL, "ClassD" },
+ { "aif_capture", NULL, "VI ADC" },
+};
+
+static int mt6660_component_get_volsw(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component =
+ snd_soc_kcontrol_component(kcontrol);
+ struct mt6660_chip *chip = (struct mt6660_chip *)
+ snd_soc_component_get_drvdata(component);
+ int ret = -EINVAL;
+
+ if (!strcmp(kcontrol->id.name, "Chip Rev")) {
+ ucontrol->value.integer.value[0] = chip->chip_rev & 0x0f;
+ ret = 0;
+ }
+ return ret;
+}
+
+static const DECLARE_TLV_DB_SCALE(vol_ctl_tlv, -1155, 5, 0);
+
+static const struct snd_kcontrol_new mt6660_component_snd_controls[] = {
+ SOC_SINGLE_TLV("Digital Volume", MT6660_REG_VOL_CTRL, 0, 255,
+ 1, vol_ctl_tlv),
+ SOC_SINGLE("Hard Clip Switch", MT6660_REG_HCLIP_CTRL, 8, 1, 0),
+ SOC_SINGLE("Clip Switch", MT6660_REG_SPS_CTRL, 0, 1, 0),
+ SOC_SINGLE("Boost Mode", MT6660_REG_BST_CTRL, 0, 3, 0),
+ SOC_SINGLE("DRE Switch", MT6660_REG_DRE_CTRL, 0, 1, 0),
+ SOC_SINGLE("DC Protect Switch", MT6660_REG_DC_PROTECT_CTRL, 3, 1, 0),
+ SOC_SINGLE("Data Output Left Channel Selection",
+ MT6660_REG_DATAO_SEL, 3, 7, 0),
+ SOC_SINGLE("Data Output Right Channel Selection",
+ MT6660_REG_DATAO_SEL, 0, 7, 0),
+ SOC_SINGLE_EXT("T0 SEL", MT6660_REG_CALI_T0, 0, 7, 0,
+ snd_soc_get_volsw, NULL),
+ SOC_SINGLE_EXT("Chip Rev", MT6660_REG_DEVID, 8, 15, 0,
+ mt6660_component_get_volsw, NULL),
+};
+
+static inline int _mt6660_chip_power_on(struct mt6660_chip *chip, int on_off)
+{
+ u8 reg_data = 0;
+ int ret = 0;
+
+ ret = i2c_smbus_read_byte_data(chip->i2c, MT6660_REG_SYSTEM_CTRL);
+ if (ret < 0)
+ return ret;
+ reg_data = (u8)ret;
+ if (on_off)
+ reg_data &= (~0x01);
+ else
+ reg_data |= 0x01;
+ return regmap_write(chip->regmap, MT6660_REG_SYSTEM_CTRL, reg_data);
+}
+
+static int mt6660_apply_plat_data(struct mt6660_chip *chip,
+ struct snd_soc_component *component)
+{
+ size_t i = 0;
+ int num = chip->plat_data.init_setting_num;
+ int ret = 0;
+
+ ret = _mt6660_chip_power_on(chip, 1);
+ if (ret < 0) {
+ dev_err(chip->dev, "%s power on failed\n", __func__);
+ return ret;
+ }
+
+ for (i = 0; i < num; i++) {
+ ret = snd_soc_component_update_bits(component,
+ chip->plat_data.init_setting_addr[i],
+ chip->plat_data.init_setting_mask[i],
+ chip->plat_data.init_setting_val[i]);
+ if (ret < 0)
+ return ret;
+ }
+ ret = _mt6660_chip_power_on(chip, 0);
+ if (ret < 0) {
+ dev_err(chip->dev, "%s power on failed\n", __func__);
+ return ret;
+ }
+ return 0;
+}
+
+static int mt6660_component_probe(struct snd_soc_component *component)
+{
+ struct mt6660_chip *chip = snd_soc_component_get_drvdata(component);
+ int ret = 0;
+
+ dev_dbg(component->dev, "%s\n", __func__);
+ snd_soc_component_init_regmap(component, chip->regmap);
+
+ ret = mt6660_apply_plat_data(chip, component);
+ if (ret < 0)
+ dev_err(chip->dev, "mt6660 apply plat data failed\n");
+
+ return ret;
+}
+
+static void mt6660_component_remove(struct snd_soc_component *component)
+{
+ dev_dbg(component->dev, "%s\n", __func__);
+ snd_soc_component_exit_regmap(component);
+}
+
+static const struct snd_soc_component_driver mt6660_component_driver = {
+ .probe = mt6660_component_probe,
+ .remove = mt6660_component_remove,
+
+ .controls = mt6660_component_snd_controls,
+ .num_controls = ARRAY_SIZE(mt6660_component_snd_controls),
+ .dapm_widgets = mt6660_component_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(mt6660_component_dapm_widgets),
+ .dapm_routes = mt6660_component_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(mt6660_component_dapm_routes),
+
+ .idle_bias_on = false, /* idle_bias_off = true */
+};
+
+static int mt6660_component_aif_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params, struct snd_soc_dai *dai)
+{
+ int word_len = params_physical_width(hw_params);
+ int aud_bit = params_width(hw_params);
+ u16 reg_data = 0;
+ int ret = 0;
+
+ dev_dbg(dai->dev, "%s: ++\n", __func__);
+ dev_dbg(dai->dev, "format: 0x%08x\n", params_format(hw_params));
+ dev_dbg(dai->dev, "rate: 0x%08x\n", params_rate(hw_params));
+ dev_dbg(dai->dev, "word_len: %d, aud_bit: %d\n", word_len, aud_bit);
+ if (word_len > 32 || word_len < 16) {
+ dev_err(dai->dev, "not supported word length\n");
+ return -ENOTSUPP;
+ }
+ switch (aud_bit) {
+ case 16:
+ reg_data = 3;
+ break;
+ case 18:
+ reg_data = 2;
+ break;
+ case 20:
+ reg_data = 1;
+ break;
+ case 24:
+ case 32:
+ reg_data = 0;
+ break;
+ default:
+ return -ENOTSUPP;
+ }
+ ret = snd_soc_component_update_bits(dai->component,
+ MT6660_REG_SERIAL_CFG1, 0xc0, (reg_data << 6));
+ if (ret < 0) {
+ dev_err(dai->dev, "config aud bit fail\n");
+ return ret;
+ }
+ ret = snd_soc_component_update_bits(dai->component,
+ MT6660_REG_TDM_CFG3, 0x3f0, word_len << 4);
+ if (ret < 0) {
+ dev_err(dai->dev, "config word len fail\n");
+ return ret;
+ }
+ dev_dbg(dai->dev, "%s: --\n", __func__);
+ return 0;
+}
+
+static const struct snd_soc_dai_ops mt6660_component_aif_ops = {
+ .hw_params = mt6660_component_aif_hw_params,
+};
+
+#define STUB_RATES SNDRV_PCM_RATE_8000_192000
+#define STUB_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_U16_LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | \
+ SNDRV_PCM_FMTBIT_U24_LE | \
+ SNDRV_PCM_FMTBIT_S32_LE | \
+ SNDRV_PCM_FMTBIT_U32_LE)
+
+static struct snd_soc_dai_driver mt6660_codec_dai = {
+ .name = "mt6660-aif",
+ .playback = {
+ .stream_name = "aif_playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = STUB_RATES,
+ .formats = STUB_FORMATS,
+ },
+ .capture = {
+ .stream_name = "aif_capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = STUB_RATES,
+ .formats = STUB_FORMATS,
+ },
+ /* dai properties */
+ .symmetric_rates = 1,
+ .symmetric_channels = 1,
+ .symmetric_samplebits = 1,
+ /* dai operations */
+ .ops = &mt6660_component_aif_ops,
+};
+
+static inline int _mt6660_chip_id_check(struct mt6660_chip *chip)
+{
+ u8 id[2] = {0};
+ int ret = 0;
+
+ ret = i2c_smbus_read_i2c_block_data(chip->i2c, MT6660_REG_DEVID, 2, id);
+ if (ret < 0)
+ return ret;
+ ret = (id[0] << 8) + id[1];
+ ret &= 0x0ff0;
+ if (ret != 0x00e0 && ret != 0x01e0) {
+ dev_err(chip->dev, "%s id(%x) not match\n", __func__, ret);
+ return -ENODEV;
+ }
+ return ret;
+}
+
+static inline int _mt6660_chip_sw_reset(struct mt6660_chip *chip)
+{
+ int ret;
+
+ /* turn on main pll first, then trigger reset */
+ ret = regmap_write(chip->regmap, 0x03, 0x00);
+ if (ret < 0)
+ return ret;
+ ret = regmap_write(chip->regmap, MT6660_REG_SYSTEM_CTRL, 0x80);
+ msleep(30);
+ return 0;
+}
+
+static inline int _mt6660_read_chip_revision(struct mt6660_chip *chip)
+{
+ u8 reg_data[2] = {0};
+ int ret = 0;
+
+ ret = i2c_smbus_read_i2c_block_data(
+ chip->i2c, MT6660_REG_DEVID, 2, reg_data);
+ if (ret < 0) {
+ dev_err(chip->dev, "get chip revision fail\n");
+ return ret;
+ }
+ chip->chip_rev = reg_data[1];
+ return 0;
+}
+
+static int mt6660_parse_dt(struct mt6660_chip *chip, struct device *dev)
+{
+ struct device_node *np = dev->of_node;
+ u32 val;
+ size_t i = 0;
+
+ if (!np) {
+ dev_err(dev, "no device node\n");
+ return -EINVAL;
+ }
+
+ if (of_property_read_u32(np, "rt,init_setting_num", &val)) {
+ dev_err(dev, "no init setting\n");
+ chip->plat_data.init_setting_num = 0;
+ } else {
+ chip->plat_data.init_setting_num = val;
+ }
+
+ chip->plat_data.init_setting_addr =
+ devm_kzalloc(dev, sizeof(u32) *
+ chip->plat_data.init_setting_num, GFP_KERNEL);
+ chip->plat_data.init_setting_mask =
+ devm_kzalloc(dev, sizeof(u32) *
+ chip->plat_data.init_setting_num, GFP_KERNEL);
+ chip->plat_data.init_setting_val =
+ devm_kzalloc(dev, sizeof(u32) *
+ chip->plat_data.init_setting_num, GFP_KERNEL);
+
+ if (of_property_read_u32_array(np, "rt,init_setting_addr",
+ chip->plat_data.init_setting_addr,
+ chip->plat_data.init_setting_num)) {
+ dev_err(dev, "no init setting addr\n");
+ }
+ if (of_property_read_u32_array(np, "rt,init_setting_mask",
+ chip->plat_data.init_setting_mask,
+ chip->plat_data.init_setting_num)) {
+ dev_err(dev, "no init setting addr\n");
+ }
+ if (of_property_read_u32_array(np, "rt,init_setting_val",
+ chip->plat_data.init_setting_val,
+ chip->plat_data.init_setting_num)) {
+ dev_err(dev, "no init setting addr\n");
+ }
+
+ dev_dbg(dev, "%s, init stting table, num = %d\n", __func__,
+ chip->plat_data.init_setting_num);
+ for (i = 0; i < chip->plat_data.init_setting_num; i++) {
+ dev_dbg(dev, "0x%02x, 0x%08x, 0x%08x\n",
+ chip->plat_data.init_setting_addr[i],
+ chip->plat_data.init_setting_mask[i],
+ chip->plat_data.init_setting_val[i]);
+ }
+ return 0;
+}
+
+static int mt6660_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct mt6660_chip *chip = NULL;
+ int ret = 0;
+
+ dev_dbg(&client->dev, "%s\n", __func__);
+ chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
+ if (!chip)
+ return -ENOMEM;
+ chip->i2c = client;
+ chip->dev = &client->dev;
+ mutex_init(&chip->io_lock);
+ i2c_set_clientdata(client, chip);
+
+ ret = mt6660_parse_dt(chip, &client->dev);
+ if (ret < 0) {
+ dev_err(&client->dev, "parsing dts failed\n");
+ return ret;
+ }
+
+ chip->regmap = devm_regmap_init(&client->dev,
+ NULL, chip, &mt6660_regmap_config);
+ if (IS_ERR(chip->regmap)) {
+ ret = PTR_ERR(chip->regmap);
+ dev_err(&client->dev, "failed to initialise regmap: %d\n", ret);
+ return ret;
+ }
+
+ /* chip reset first */
+ ret = _mt6660_chip_sw_reset(chip);
+ if (ret < 0) {
+ dev_err(chip->dev, "chip reset fail\n");
+ goto probe_fail;
+ }
+ /* chip power on */
+ ret = _mt6660_chip_power_on(chip, 1);
+ if (ret < 0) {
+ dev_err(chip->dev, "chip power on 2 fail\n");
+ goto probe_fail;
+ }
+ /* chip devid check */
+ ret = _mt6660_chip_id_check(chip);
+ if (ret < 0) {
+ dev_err(chip->dev, "chip id check fail\n");
+ goto probe_fail;
+ }
+ /* chip revision get */
+ ret = _mt6660_read_chip_revision(chip);
+ if (ret < 0) {
+ dev_err(chip->dev, "read chip revision fail\n");
+ goto probe_fail;
+ }
+ pm_runtime_set_active(chip->dev);
+ pm_runtime_enable(chip->dev);
+
+ ret = devm_snd_soc_register_component(chip->dev,
+ &mt6660_component_driver,
+ &mt6660_codec_dai, 1);
+ return ret;
+probe_fail:
+ _mt6660_chip_power_on(chip, 0);
+ mutex_destroy(&chip->io_lock);
+ return ret;
+}
+
+static int mt6660_i2c_remove(struct i2c_client *client)
+{
+ struct mt6660_chip *chip = i2c_get_clientdata(client);
+
+ pm_runtime_disable(chip->dev);
+ pm_runtime_set_suspended(chip->dev);
+ mutex_destroy(&chip->io_lock);
+ return 0;
+}
+
+static int __maybe_unused mt6660_i2c_runtime_suspend(struct device *dev)
+{
+ struct mt6660_chip *chip = dev_get_drvdata(dev);
+
+ dev_dbg(dev, "enter low power mode\n");
+ return regmap_update_bits(chip->regmap,
+ MT6660_REG_SYSTEM_CTRL, 0x01, 0x01);
+}
+
+static int __maybe_unused mt6660_i2c_runtime_resume(struct device *dev)
+{
+ struct mt6660_chip *chip = dev_get_drvdata(dev);
+
+ dev_dbg(dev, "exit low power mode\n");
+ return regmap_update_bits(chip->regmap,
+ MT6660_REG_SYSTEM_CTRL, 0x01, 0x00);
+}
+
+static const struct dev_pm_ops mt6660_dev_pm_ops = {
+ SET_RUNTIME_PM_OPS(mt6660_i2c_runtime_suspend,
+ mt6660_i2c_runtime_resume, NULL)
+};
+
+static const struct of_device_id __maybe_unused mt6660_of_id[] = {
+ { .compatible = "mediatek,mt6660",},
+ {},
+};
+MODULE_DEVICE_TABLE(of, mt6660_of_id);
+
+static const struct i2c_device_id mt6660_i2c_id[] = {
+ {"mt6660", 0 },
+ {},
+};
+MODULE_DEVICE_TABLE(i2c, mt6660_i2c_id);
+
+static struct i2c_driver mt6660_i2c_driver = {
+ .driver = {
+ .name = "mt6660",
+ .of_match_table = of_match_ptr(mt6660_of_id),
+ .pm = &mt6660_dev_pm_ops,
+ },
+ .probe = mt6660_i2c_probe,
+ .remove = mt6660_i2c_remove,
+ .id_table = mt6660_i2c_id,
+};
+module_i2c_driver(mt6660_i2c_driver);
+
+MODULE_AUTHOR("Jeff Chang <jeff_chang(a)richtek.com>");
+MODULE_DESCRIPTION("MT6660 SPKAMP Driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("1.0.7_G");
diff --git a/sound/soc/codecs/mt6660.h b/sound/soc/codecs/mt6660.h
new file mode 100644
index 0000000..6c40b40
--- /dev/null
+++ b/sound/soc/codecs/mt6660.h
@@ -0,0 +1,75 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef __SND_SOC_MT6660_H
+#define __SND_SOC_MT6660_H
+
+#include <linux/mutex.h>
+#include <linux/regmap.h>
+
+struct mt6660_platform_data {
+ u8 init_setting_num;
+ u32 *init_setting_addr;
+ u32 *init_setting_mask;
+ u32 *init_setting_val;
+};
+
+struct mt6660_chip {
+ struct i2c_client *i2c;
+ struct device *dev;
+ struct platform_device *param_dev;
+ struct mt6660_platform_data plat_data;
+ struct mutex io_lock;
+ struct regmap *regmap;
+ u16 chip_rev;
+};
+
+#define MT6660_REG_DEVID (0x00)
+#define MT6660_REG_SYSTEM_CTRL (0x03)
+#define MT6660_REG_IRQ_STATUS1 (0x05)
+#define MT6660_REG_ADDA_CLOCK (0x07)
+#define MT6660_REG_SERIAL_CFG1 (0x10)
+#define MT6660_REG_DATAO_SEL (0x12)
+#define MT6660_REG_TDM_CFG3 (0x15)
+#define MT6660_REG_HPF_CTRL (0x18)
+#define MT6660_REG_HPF1_COEF (0x1A)
+#define MT6660_REG_HPF2_COEF (0x1B)
+#define MT6660_REG_PATH_BYPASS (0x1E)
+#define MT6660_REG_WDT_CTRL (0x20)
+#define MT6660_REG_HCLIP_CTRL (0x24)
+#define MT6660_REG_VOL_CTRL (0x29)
+#define MT6660_REG_SPS_CTRL (0x30)
+#define MT6660_REG_SIGMAX (0x33)
+#define MT6660_REG_CALI_T0 (0x3F)
+#define MT6660_REG_BST_CTRL (0x40)
+#define MT6660_REG_PROTECTION_CFG (0x46)
+#define MT6660_REG_DA_GAIN (0x4c)
+#define MT6660_REG_AUDIO_IN2_SEL (0x50)
+#define MT6660_REG_SIG_GAIN (0x51)
+#define MT6660_REG_PLL_CFG1 (0x60)
+#define MT6660_REG_DRE_CTRL (0x68)
+#define MT6660_REG_DRE_THDMODE (0x69)
+#define MT6660_REG_DRE_CORASE (0x6B)
+#define MT6660_REG_PWM_CTRL (0x70)
+#define MT6660_REG_DC_PROTECT_CTRL (0x74)
+#define MT6660_REG_ADC_USB_MODE (0x7c)
+#define MT6660_REG_INTERNAL_CFG (0x88)
+#define MT6660_REG_RESV0 (0x98)
+#define MT6660_REG_RESV1 (0x99)
+#define MT6660_REG_RESV2 (0x9A)
+#define MT6660_REG_RESV3 (0x9B)
+#define MT6660_REG_RESV6 (0xA2)
+#define MT6660_REG_RESV7 (0xA3)
+#define MT6660_REG_RESV10 (0xB0)
+#define MT6660_REG_RESV11 (0xB1)
+#define MT6660_REG_RESV16 (0xB6)
+#define MT6660_REG_RESV17 (0xB7)
+#define MT6660_REG_RESV19 (0xB9)
+#define MT6660_REG_RESV21 (0xBB)
+#define MT6660_REG_RESV23 (0xBD)
+#define MT6660_REG_RESV31 (0xD3)
+#define MT6660_REG_RESV40 (0xE0)
+
+#endif /* __SND_SOC_MT6660_H */
--
2.7.4
3
2
09 Jan '20
Hi,
this is a patch set for updating ALSA PCM API usages in dw-hdmi
driver. I already tried to "fix" the driver some time ago but it was
utterly wrong. So this is a combination of the revised patch and
another cleanup patch.
The first one is to change the buffer allocation mechanism in the
driver to the manual allocation of the h/w buffer and the automatic
allocation of PCM stream buffers via the new standard API. The
significant change is that size of the h/w buffer isn't no longer
controlled via ALSA preallocation proc file but rather via the new
module option (if any).
The second one is a oneliner patch just to remove the superfluous PCM
ops.
Both need the ALSA PCM core changes in 5.5-rc1, so please apply them
on top of 5.5-rc1 or later. Or, just let me know if I should apply
them through sound git tree.
thanks,
Takashi
===
Takashi Iwai (2):
drm/bridge: dw-hdmi: Follow the standard ALSA memalloc way
drm/bridge: dw-hdmi: Drop superfluous ioctl PCM ops
.../gpu/drm/bridge/synopsys/dw-hdmi-ahb-audio.c | 49 ++++++++++++----------
1 file changed, 26 insertions(+), 23 deletions(-)
--
2.16.4
3
5
Dear all,
I'm working on a board that is equipped with a Bluetooth chip and a gsm
phone, both connected to the CPU (AM3352) on 2 different pcm. I wrote the
codecs and they are working (read as: I can play/record on both devices).
What I want to achieve now is to route those pcm together and still being
able to (at least) play audio on both. I tried alsaloop, but it eats too
much CPU (80% +) even in half duplex loop (BT capture => GSM playback), and
it was the only application running. In [1] I saw that I should be able to
route the codec together in kernel space (to avoid data copy between user
and kernel spaces). I did not tried that solution yet because it's not
really clear to me how to implement it, any suggestions/examples? If I
follow that solution, can I still use those PCM to playback my audio file
(I see that I can disconnect that link through a mixer control, so this
should be possible)?
Again any suggestion is really appreciated.
Best regards,
Gabriele
[1]:
https://www.kernel.org/doc/html/latest/sound/soc/dpcm.html#hostless-pcm-str…
1
0
09 Jan '20
We've got quite a few bug reports showing the SOF driver being loaded
unintentionally recently, and the reason seems to be that users didn't
know the module option change: with the recent kernel, a new option
dsp_driver=1 has to be passed to a new module snd-intel-dspcfg
instead of snd_hda_intel.dmic_detect=0 option.
That is, actually there are two tricky things here:
- We changed the whole detection in another module and another
option semantics.
- The existing option for skipping the DSP probe was also renamed.
For avoiding the confusion and giving user more hint, this patch
reverts the renamed option dsp_driver back to dmic_detect for
snd-hda-intel module, and show the warning about the module option
change when the non-default value is passed.
Fixes: 82d9d54a6c0e ("ALSA: hda: add Intel DSP configuration / probe code")
Signed-off-by: Takashi Iwai <tiwai(a)suse.de>
---
sound/pci/hda/hda_intel.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 5b92f290cbb0..8ef223aa1e37 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -125,7 +125,7 @@ static char *patch[SNDRV_CARDS];
static bool beep_mode[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] =
CONFIG_SND_HDA_INPUT_BEEP_MODE};
#endif
-static bool dsp_driver = 1;
+static bool dmic_detect = 1;
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for Intel HD audio interface.");
@@ -160,9 +160,10 @@ module_param_array(beep_mode, bool, NULL, 0444);
MODULE_PARM_DESC(beep_mode, "Select HDA Beep registration mode "
"(0=off, 1=on) (default=1).");
#endif
-module_param(dsp_driver, bool, 0444);
-MODULE_PARM_DESC(dsp_driver, "Allow DSP driver selection (bypass this driver) "
- "(0=off, 1=on) (default=1)");
+module_param(dmic_detect, bool, 0444);
+MODULE_PARM_DESC(dmic_detect, "Allow DSP driver selection (bypass this driver) "
+ "(0=off, 1=on) (default=1); "
+ "deprecated, use snd-intel-dspcfg.dsp_driver option instead");
#ifdef CONFIG_PM
static int param_set_xint(const char *val, const struct kernel_param *kp);
@@ -2099,11 +2100,13 @@ static int azx_probe(struct pci_dev *pci,
/*
* stop probe if another Intel's DSP driver should be activated
*/
- if (dsp_driver) {
+ if (dmic_detect) {
err = snd_intel_dsp_driver_probe(pci);
if (err != SND_INTEL_DSP_DRIVER_ANY &&
err != SND_INTEL_DSP_DRIVER_LEGACY)
return -ENODEV;
+ } else {
+ dev_warn(&pci->dev, "dmic_detect option is deprecated, pass snd-intel-dspcfg.dsp_driver=1 option instead\n");
}
err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
--
2.16.4
1
0
[alsa-devel] [PATCH][resend] ASoC: simple-card: switch to yaml base Documentation
by Kuninori Morimoto 09 Jan '20
by Kuninori Morimoto 09 Jan '20
09 Jan '20
From: Kuninori Morimoto <kuninori.morimoto.gx(a)renesas.com>
This patch switches from .txt base to .yaml base Document.
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx(a)renesas.com>
---
.../devicetree/bindings/sound/simple-card.txt | 351 ---------------
.../devicetree/bindings/sound/simple-card.yaml | 472 +++++++++++++++++++++
2 files changed, 472 insertions(+), 351 deletions(-)
delete mode 100644 Documentation/devicetree/bindings/sound/simple-card.txt
create mode 100644 Documentation/devicetree/bindings/sound/simple-card.yaml
diff --git a/Documentation/devicetree/bindings/sound/simple-card.txt b/Documentation/devicetree/bindings/sound/simple-card.txt
deleted file mode 100644
index 79954cd6..0000000
--- a/Documentation/devicetree/bindings/sound/simple-card.txt
+++ /dev/null
@@ -1,351 +0,0 @@
-Simple-Card:
-
-Simple-Card specifies audio DAI connections of SoC <-> codec.
-
-Required properties:
-
-- compatible : "simple-audio-card"
-
-Optional properties:
-
-- simple-audio-card,name : User specified audio sound card name, one string
- property.
-- simple-audio-card,widgets : Please refer to widgets.txt.
-- simple-audio-card,routing : A list of the connections between audio components.
- Each entry is a pair of strings, the first being the
- connection's sink, the second being the connection's
- source.
-- simple-audio-card,mclk-fs : Multiplication factor between stream rate and codec
- mclk. When defined, mclk-fs property defined in
- dai-link sub nodes are ignored.
-- simple-audio-card,hp-det-gpio : Reference to GPIO that signals when
- headphones are attached.
-- simple-audio-card,mic-det-gpio : Reference to GPIO that signals when
- a microphone is attached.
-- simple-audio-card,aux-devs : List of phandles pointing to auxiliary devices, such
- as amplifiers, to be added to the sound card.
-- simple-audio-card,pin-switches : List of strings containing the widget names for
- which pin switches must be created.
-
-Optional subnodes:
-
-- simple-audio-card,dai-link : Container for dai-link level
- properties and the CPU and CODEC
- sub-nodes. This container may be
- omitted when the card has only one
- DAI link. See the examples and the
- section below.
-
-Dai-link subnode properties and subnodes:
-
-If dai-link subnode is omitted and the subnode properties are directly
-under "sound"-node the subnode property and subnode names have to be
-prefixed with "simple-audio-card,"-prefix.
-
-Required dai-link subnodes:
-
-- cpu : CPU sub-node
-- codec : CODEC sub-node
-
-Optional dai-link subnode properties:
-
-- format : CPU/CODEC common audio format.
- "i2s", "right_j", "left_j" , "dsp_a"
- "dsp_b", "ac97", "pdm", "msb", "lsb"
-- frame-master : Indicates dai-link frame master.
- phandle to a cpu or codec subnode.
-- bitclock-master : Indicates dai-link bit clock master.
- phandle to a cpu or codec subnode.
-- bitclock-inversion : bool property. Add this if the
- dai-link uses bit clock inversion.
-- frame-inversion : bool property. Add this if the
- dai-link uses frame clock inversion.
-- mclk-fs : Multiplication factor between stream
- rate and codec mclk, applied only for
- the dai-link.
-
-For backward compatibility the frame-master and bitclock-master
-properties can be used as booleans in codec subnode to indicate if the
-codec is the dai-link frame or bit clock master. In this case there
-should be no dai-link node, the same properties should not be present
-at sound-node level, and the bitclock-inversion and frame-inversion
-properties should also be placed in the codec node if needed.
-
-Required CPU/CODEC subnodes properties:
-
-- sound-dai : phandle and port of CPU/CODEC
-
-Optional CPU/CODEC subnodes properties:
-
-- dai-tdm-slot-num : Please refer to tdm-slot.txt.
-- dai-tdm-slot-width : Please refer to tdm-slot.txt.
-- clocks / system-clock-frequency : specify subnode's clock if needed.
- it can be specified via "clocks" if system has
- clock node (= common clock), or "system-clock-frequency"
- (if system doens't support common clock)
- If a clock is specified, it is
- enabled with clk_prepare_enable()
- in dai startup() and disabled with
- clk_disable_unprepare() in dai
- shutdown().
- If a clock is specified and a
- multiplication factor is given with
- mclk-fs, the clock will be set to the
- calculated mclk frequency when the
- stream starts.
-- system-clock-direction-out : specifies clock direction as 'out' on
- initialization. It is useful for some aCPUs with
- fixed clocks.
-
--------------------------------------------
-Example 1 - single DAI link:
--------------------------------------------
-
-sound {
- compatible = "simple-audio-card";
- simple-audio-card,name = "VF610-Tower-Sound-Card";
- simple-audio-card,format = "left_j";
- simple-audio-card,bitclock-master = <&dailink0_master>;
- simple-audio-card,frame-master = <&dailink0_master>;
- simple-audio-card,widgets =
- "Microphone", "Microphone Jack",
- "Headphone", "Headphone Jack",
- "Speaker", "External Speaker";
- simple-audio-card,routing =
- "MIC_IN", "Microphone Jack",
- "Headphone Jack", "HP_OUT",
- "External Speaker", "LINE_OUT";
-
- simple-audio-card,cpu {
- sound-dai = <&sh_fsi2 0>;
- };
-
- dailink0_master: simple-audio-card,codec {
- sound-dai = <&ak4648>;
- clocks = <&osc>;
- };
-};
-
-&i2c0 {
- ak4648: ak4648@12 {
- #sound-dai-cells = <0>;
- compatible = "asahi-kasei,ak4648";
- reg = <0x12>;
- };
-};
-
-sh_fsi2: sh_fsi2@ec230000 {
- #sound-dai-cells = <1>;
- compatible = "renesas,sh_fsi2";
- reg = <0xec230000 0x400>;
- interrupt-parent = <&gic>;
- interrupts = <0 146 0x4>;
-};
-
--------------------------------------------
-Example 2 - many DAI links:
--------------------------------------------
-
-sound {
- compatible = "simple-audio-card";
- simple-audio-card,name = "Cubox Audio";
-
- simple-audio-card,dai-link@0 { /* I2S - HDMI */
- reg = <0>;
- format = "i2s";
- cpu {
- sound-dai = <&audio1 0>;
- };
- codec {
- sound-dai = <&tda998x 0>;
- };
- };
-
- simple-audio-card,dai-link@1 { /* S/PDIF - HDMI */
- reg = <1>;
- cpu {
- sound-dai = <&audio1 1>;
- };
- codec {
- sound-dai = <&tda998x 1>;
- };
- };
-
- simple-audio-card,dai-link@2 { /* S/PDIF - S/PDIF */
- reg = <2>;
- cpu {
- sound-dai = <&audio1 1>;
- };
- codec {
- sound-dai = <&spdif_codec>;
- };
- };
-};
-
--------------------------------------------
-Example 3 - route audio from IMX6 SSI2 through TLV320DAC3100 codec
-through TPA6130A2 amplifier to headphones:
--------------------------------------------
-
-&i2c0 {
- codec: tlv320dac3100@18 {
- compatible = "ti,tlv320dac3100";
- ...
- }
-
- amp: tpa6130a2@60 {
- compatible = "ti,tpa6130a2";
- ...
- }
-}
-
-sound {
- compatible = "simple-audio-card";
- ...
- simple-audio-card,widgets =
- "Headphone", "Headphone Jack";
- simple-audio-card,routing =
- "Headphone Jack", "HPLEFT",
- "Headphone Jack", "HPRIGHT",
- "LEFTIN", "HPL",
- "RIGHTIN", "HPR";
- simple-audio-card,aux-devs = <&>;
- simple-audio-card,cpu {
- sound-dai = <&ssi2>;
- };
- simple-audio-card,codec {
- sound-dai = <&codec>;
- clocks = ...
- };
-};
-
--------------------------------------------
-Example 4. Sampling Rate Conversion
--------------------------------------------
-
-sound {
- compatible = "simple-audio-card";
-
- simple-audio-card,name = "rsnd-ak4643";
- simple-audio-card,format = "left_j";
- simple-audio-card,bitclock-master = <&sndcodec>;
- simple-audio-card,frame-master = <&sndcodec>;
-
- simple-audio-card,convert-rate = <48000>;
-
- simple-audio-card,prefix = "ak4642";
- simple-audio-card,routing = "ak4642 Playback", "DAI0 Playback",
- "DAI0 Capture", "ak4642 Capture";
-
- sndcpu: simple-audio-card,cpu {
- sound-dai = <&rcar_sound>;
- };
-
- sndcodec: simple-audio-card,codec {
- sound-dai = <&ak4643>;
- system-clock-frequency = <11289600>;
- };
-};
-
--------------------------------------------
-Example 5. 2 CPU 1 Codec (Mixing)
--------------------------------------------
-sound {
- compatible = "simple-audio-card";
-
- simple-audio-card,name = "rsnd-ak4643";
- simple-audio-card,format = "left_j";
- simple-audio-card,bitclock-master = <&dpcmcpu>;
- simple-audio-card,frame-master = <&dpcmcpu>;
-
- simple-audio-card,routing = "ak4642 Playback", "DAI0 Playback",
- "ak4642 Playback", "DAI1 Playback";
-
- dpcmcpu: cpu@0 {
- sound-dai = <&rcar_sound 0>;
- };
-
- cpu@1 {
- sound-dai = <&rcar_sound 1>;
- };
-
- codec {
- prefix = "ak4642";
- sound-dai = <&ak4643>;
- clocks = <&audio_clock>;
- };
-};
-
--------------------------------------------
-Example 6 - many DAI links with DPCM:
--------------------------------------------
-
-CPU0 ------ ak4613
-CPU1 ------ PCM3168A-p /* DPCM 1ch/2ch */
-CPU2 --/ /* DPCM 3ch/4ch */
-CPU3 --/ /* DPCM 5ch/6ch */
-CPU4 --/ /* DPCM 7ch/8ch */
-CPU5 ------ PCM3168A-c
-
-sound {
- compatible = "simple-audio-card";
-
- simple-audio-card,routing =
- "pcm3168a Playback", "DAI1 Playback",
- "pcm3168a Playback", "DAI2 Playback",
- "pcm3168a Playback", "DAI3 Playback",
- "pcm3168a Playback", "DAI4 Playback";
-
- simple-audio-card,dai-link@0 {
- format = "left_j";
- bitclock-master = <&sndcpu0>;
- frame-master = <&sndcpu0>;
-
- sndcpu0: cpu {
- sound-dai = <&rcar_sound 0>;
- };
- codec {
- sound-dai = <&ak4613>;
- };
- };
- simple-audio-card,dai-link@1 {
- format = "i2s";
- bitclock-master = <&sndcpu1>;
- frame-master = <&sndcpu1>;
-
- convert-channels = <8>; /* TDM Split */
-
- sndcpu1: cpu@0 {
- sound-dai = <&rcar_sound 1>;
- };
- cpu@1 {
- sound-dai = <&rcar_sound 2>;
- };
- cpu@2 {
- sound-dai = <&rcar_sound 3>;
- };
- cpu@3 {
- sound-dai = <&rcar_sound 4>;
- };
- codec {
- mclk-fs = <512>;
- prefix = "pcm3168a";
- dai-tdm-slot-num = <8>;
- sound-dai = <&pcm3168a 0>;
- };
- };
- simple-audio-card,dai-link@2 {
- format = "i2s";
- bitclock-master = <&sndcpu2>;
- frame-master = <&sndcpu2>;
-
- sndcpu2: cpu {
- sound-dai = <&rcar_sound 5>;
- };
- codec {
- mclk-fs = <512>;
- prefix = "pcm3168a";
- sound-dai = <&pcm3168a 1>;
- };
- };
-};
diff --git a/Documentation/devicetree/bindings/sound/simple-card.yaml b/Documentation/devicetree/bindings/sound/simple-card.yaml
new file mode 100644
index 0000000..ac3975f
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/simple-card.yaml
@@ -0,0 +1,472 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/simple-card.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Simple Audio Card Driver Device Tree Bindings
+
+maintainers:
+ - Kuninori Morimoto <kuninori.morimoto.gx(a)renesas.com>
+
+definitions:
+
+ frame-master:
+ description: Indicates dai-link frame master.
+ $ref: /schemas/types.yaml#/definitions/phandle-array
+
+ bitclock-master:
+ description: Indicates dai-link bit clock master
+ $ref: /schemas/types.yaml#/definitions/phandle-array
+
+ frame-inversion:
+ description: dai-link uses frame clock inversion
+ $ref: /schemas/types.yaml#/definitions/flag
+
+ bitclock-inversion:
+ description: dai-link uses bit clock inversion
+ $ref: /schemas/types.yaml#/definitions/flag
+
+ mclk-fs:
+ description: |
+ Multiplication factor between stream rate and codec mclk.
+ When defined, mclk-fs property defined in dai-link sub nodes are ignored.
+ $ref: /schemas/types.yaml#/definitions/uint32
+
+ hp-det-gpio:
+ description: |
+ Reference to GPIO that signals when headphones are attached.
+ $ref: /schemas/types.yaml#/definitions/phandle
+
+ aux-devs:
+ description: |
+ List of phandles pointing to auxiliary devices, such
+ as amplifiers, to be added to the sound card.
+ $ref: /schemas/types.yaml#/definitions/phandle-array
+
+ mic-det-gpio:
+ description: |
+ Reference to GPIO that signals when a microphone is attached.
+ $ref: /schemas/types.yaml#/definitions/phandle
+
+ convert-rate:
+ description: CPU to Codec rate convert.
+ $ref: /schemas/types.yaml#/definitions/uint32
+
+ convert-channels:
+ description: CPU to Codec rate channels.
+ $ref: /schemas/types.yaml#/definitions/uint32
+
+ prefix:
+ description: "device name prefix"
+ $ref: /schemas/types.yaml#/definitions/string
+
+ pin-switches:
+ description: the widget names for which pin switches must be created.
+ $ref: /schemas/types.yaml#/definitions/string-array
+
+ format:
+ description: audio format.
+ oneOf:
+ - items:
+ enum:
+ - i2s
+ - right_j
+ - left_j
+ - dsp_a
+ - dsp_b
+ - ac97
+ - pdm
+ - msb
+ - lsb
+
+ dai:
+ type: object
+ properties:
+ sound-dai:
+ $ref: /schemas/types.yaml#/definitions/phandle-array
+
+ # common properties
+ mclk-fs:
+ $ref: "#/definitions/mclk-fs"
+ prefix:
+ $ref: "#/definitions/prefix"
+ frame-inversion:
+ $ref: "#/definitions/frame-inversion"
+ bitclock-inversion:
+ $ref: "#/definitions/bitclock-inversion"
+ frame-master:
+ $ref: /schemas/types.yaml#/definitions/flag
+ bitclock-master:
+ $ref: /schemas/types.yaml#/definitions/flag
+
+ dai-tdm-slot-num:
+ description: see tdm-slot.txt.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ dai-tdm-slot-width:
+ description: see tdm-slot.txt.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ clocks:
+ description: |
+ If a clock is specified and a multiplication factor is given with
+ mclk-fs, the clock will be set to the calculated mclk frequency
+ when the stream starts.
+ $ref: /schemas/types.yaml#/definitions/phandle-array
+ system-clock-frequency:
+ description: |
+ If a clock is specified and a multiplication factor is given with
+ mclk-fs, the clock will be set to the calculated mclk frequency
+ when the stream starts.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ system-clock-direction-out:
+ description: |
+ specifies clock direction as 'out' on initialization.
+ It is useful for some aCPUs with fixed clocks.
+ $ref: /schemas/types.yaml#/definitions/flag
+ required:
+ - sound-dai
+
+properties:
+ compatible:
+ contains:
+ enum:
+ - simple-audio-card
+ - simple-scu-audio-card
+
+ "#address-cells": true
+ "#size-cells": true
+
+ simple-audio-card,name:
+ description: User specified audio sound card name.
+ $ref: /schemas/types.yaml#/definitions/string
+
+ simple-audio-card,widgets:
+ description: User specified audio sound card name.
+ $ref: /schemas/types.yaml#/definitions/non-unique-string-array
+
+ simple-audio-card,routing:
+ description: |
+ A list of the connections between audio components.
+ Each entry is a pair of strings, the first being the
+ connection's sink, the second being the connection's source.
+ $ref: /schemas/types.yaml#/definitions/non-unique-string-array
+
+patternProperties:
+ "^simple-audio-card,cpu.*":
+ description: CPU node
+ $ref: "#/definitions/dai"
+ "^simple-audio-card,codec.*":
+ description: CPU node
+ $ref: "#/definitions/dai"
+
+ # common properties
+ "^simple-audio-card,frame-master$":
+ $ref: "#/definitions/frame-master"
+ "^simple-audio-card,bitclock-master$":
+ $ref: "#/definitions/bitclock-master"
+ "^simple-audio-card,frame-inversion$":
+ $ref: "#/definitions/frame-inversion"
+ "^simple-audio-card,bitclock-inversion$":
+ $ref: "#/definitions/bitclock-inversion"
+ "^simple-audio-card,format$":
+ $ref: "#/definitions/format"
+ "^simple-audio-card,mclk-fs$":
+ $ref: "#/definitions/mclk-fs"
+ "^simple-audio-card,hp-det-gpio$":
+ $ref: "#/definitions/hp-det-gpio"
+ "^simple-audio-card,mic-det-gpio$":
+ $ref: "#/definitions/mic-det-gpio"
+ "^simple-audio-card,aux-devs$":
+ $ref: "#/definitions/aux-devs"
+ "^simple-audio-card,convert-rate$":
+ $ref: "#/definitions/convert-rate"
+ "^simple-audio-card,convert-channels$":
+ $ref: "#/definitions/convert-channels"
+ "^simple-audio-card,prefix$":
+ $ref: "#/definitions/prefix"
+ "^simple-audio-card,pin-switches$":
+ $ref: "#/definitions/pin-switches"
+
+ "^simple-audio-card,dai-link":
+ description: |
+ Container for dai-link level properties and the CPU and CODEC sub-nodes.
+ This container may be omitted when the card has only one DAI link.
+ type: object
+ properties:
+ reg:
+ $ref: /schemas/types.yaml#/definitions/uint32
+
+ # common properties
+ frame-master:
+ $ref: "#/definitions/frame-master"
+ bitclock-master:
+ $ref: "#/definitions/bitclock-master"
+ frame-inversion:
+ $ref: "#/definitions/frame-inversion"
+ bitclock-inversion:
+ $ref: "#/definitions/bitclock-inversion"
+ format:
+ $ref: "#/definitions/format"
+ mclk-fs:
+ $ref: "#/definitions/mclk-fs"
+ hp-det-gpio:
+ $ref: "#/definitions/hp-det-gpio"
+ mic-det-gpio:
+ $ref: "#/definitions/mic-det-gpio"
+ aux-devs:
+ $ref: "#/definitions/aux-devs"
+ convert-rate:
+ $ref: "#/definitions/convert-rate"
+ convert-channels:
+ $ref: "#/definitions/convert-channels"
+ prefix:
+ $ref: "#/definitions/prefix"
+ pin-switches:
+ $ref: "#/definitions/pin-switches"
+
+ patternProperties:
+ "^cpu.*":
+ $ref: "#/definitions/dai"
+ "^codec.*":
+ $ref: "#/definitions/dai"
+ additionalProperties: false
+
+required:
+ - compatible
+
+additionalProperties: false
+
+examples:
+#--------------------
+# single DAI link
+#--------------------
+ - |
+ sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "VF610-Tower-Sound-Card";
+ simple-audio-card,format = "left_j";
+ simple-audio-card,bitclock-master = <&dailink0_master>;
+ simple-audio-card,frame-master = <&dailink0_master>;
+ simple-audio-card,widgets =
+ "Microphone", "Microphone Jack",
+ "Headphone", "Headphone Jack",
+ "Speaker", "External Speaker";
+ simple-audio-card,routing =
+ "MIC_IN", "Microphone Jack",
+ "Headphone Jack", "HP_OUT",
+ "External Speaker", "LINE_OUT";
+
+ simple-audio-card,cpu {
+ sound-dai = <&sh_fsi2 0>;
+ };
+
+ dailink0_master: simple-audio-card,codec {
+ sound-dai = <&ak4648>;
+ clocks = <&osc>;
+ };
+ };
+
+#--------------------
+# Multi DAI links
+#--------------------
+ - |
+ sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "Cubox Audio";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ simple-audio-card,dai-link@0 { /* I2S - HDMI */
+ reg = <0>;
+ format = "i2s";
+ cpu {
+ sound-dai = <&audio0>;
+ };
+ codec {
+ sound-dai = <&tda998x0>;
+ };
+ };
+
+ simple-audio-card,dai-link@1 { /* S/PDIF - HDMI */
+ reg = <1>;
+ cpu {
+ sound-dai = <&audio1>;
+ };
+ codec {
+ sound-dai = <&tda998x1>;
+ };
+ };
+
+ simple-audio-card,dai-link@2 { /* S/PDIF - S/PDIF */
+ reg = <2>;
+ cpu {
+ sound-dai = <&audio2>;
+ };
+ codec {
+ sound-dai = <&spdif_codec>;
+ };
+ };
+ };
+
+#--------------------
+# route audio from IMX6 SSI2 through TLV320DAC3100 codec
+# through TPA6130A2 amplifier to headphones:
+#--------------------
+ - |
+ sound {
+ compatible = "simple-audio-card";
+
+ simple-audio-card,widgets =
+ "Headphone", "Headphone Jack";
+ simple-audio-card,routing =
+ "Headphone Jack", "HPLEFT",
+ "Headphone Jack", "HPRIGHT",
+ "LEFTIN", "HPL",
+ "RIGHTIN", "HPR";
+ simple-audio-card,aux-devs = <&>;
+ simple-audio-card,cpu {
+ sound-dai = <&ssi2>;
+ };
+ simple-audio-card,codec {
+ sound-dai = <&codec>;
+ clocks = <&clocks>;
+ };
+ };
+
+#--------------------
+# Sampling Rate Conversion
+#--------------------
+ - |
+ sound {
+ compatible = "simple-audio-card";
+
+ simple-audio-card,name = "rsnd-ak4643";
+ simple-audio-card,format = "left_j";
+ simple-audio-card,bitclock-master = <&sndcodec>;
+ simple-audio-card,frame-master = <&sndcodec>;
+
+ simple-audio-card,convert-rate = <48000>;
+
+ simple-audio-card,prefix = "ak4642";
+ simple-audio-card,routing = "ak4642 Playback", "DAI0 Playback",
+ "DAI0 Capture", "ak4642 Capture";
+
+ sndcpu: simple-audio-card,cpu {
+ sound-dai = <&rcar_sound>;
+ };
+
+ sndcodec: simple-audio-card,codec {
+ sound-dai = <&ak4643>;
+ system-clock-frequency = <11289600>;
+ };
+ };
+
+#--------------------
+# 2 CPU 1 Codec (Mixing)
+#--------------------
+ - |
+ sound {
+ compatible = "simple-audio-card";
+
+ simple-audio-card,name = "rsnd-ak4643";
+ simple-audio-card,format = "left_j";
+ simple-audio-card,bitclock-master = <&dpcmcpu>;
+ simple-audio-card,frame-master = <&dpcmcpu>;
+
+ simple-audio-card,convert-rate = <48000>;
+ simple-audio-card,convert-channels = <2>;
+
+ simple-audio-card,routing = "ak4642 Playback", "DAI0 Playback",
+ "ak4642 Playback", "DAI1 Playback";
+
+ dpcmcpu: simple-audio-card,cpu@0 {
+ sound-dai = <&rcar_sound 0>;
+ };
+
+ simple-audio-card,cpu@1 {
+ sound-dai = <&rcar_sound 1>;
+ };
+
+ simple-audio-card,codec {
+ prefix = "ak4642";
+ sound-dai = <&ak4643>;
+ clocks = <&audio_clock>;
+ };
+ };
+
+#--------------------
+# Multi DAI links with DPCM:
+#
+# CPU0 ------ ak4613
+# CPU1 ------ PCM3168A-p /* DPCM 1ch/2ch */
+# CPU2 --/ /* DPCM 3ch/4ch */
+# CPU3 --/ /* DPCM 5ch/6ch */
+# CPU4 --/ /* DPCM 7ch/8ch */
+# CPU5 ------ PCM3168A-c
+#--------------------
+ - |
+ sound {
+ compatible = "simple-audio-card";
+
+ simple-audio-card,routing =
+ "pcm3168a Playback", "DAI1 Playback",
+ "pcm3168a Playback", "DAI2 Playback",
+ "pcm3168a Playback", "DAI3 Playback",
+ "pcm3168a Playback", "DAI4 Playback";
+
+ simple-audio-card,dai-link@0 {
+ format = "left_j";
+ bitclock-master = <&sndcpu0>;
+ frame-master = <&sndcpu0>;
+
+ sndcpu0: cpu {
+ sound-dai = <&rcar_sound 0>;
+ };
+ codec {
+ sound-dai = <&ak4613>;
+ };
+ };
+
+ simple-audio-card,dai-link@1 {
+ format = "i2s";
+ bitclock-master = <&sndcpu1>;
+ frame-master = <&sndcpu1>;
+
+ convert-channels = <8>; /* TDM Split */
+
+ sndcpu1: cpu@0 {
+ sound-dai = <&rcar_sound 1>;
+ };
+ cpu@1 {
+ sound-dai = <&rcar_sound 2>;
+ };
+ cpu@2 {
+ sound-dai = <&rcar_sound 3>;
+ };
+ cpu@3 {
+ sound-dai = <&rcar_sound 4>;
+ };
+ codec {
+ mclk-fs = <512>;
+ prefix = "pcm3168a";
+ dai-tdm-slot-num = <8>;
+ sound-dai = <&pcm3168a 0>;
+ };
+ };
+
+ simple-audio-card,dai-link@2 {
+ format = "i2s";
+ bitclock-master = <&sndcpu2>;
+ frame-master = <&sndcpu2>;
+
+ sndcpu2: cpu {
+ sound-dai = <&rcar_sound 5>;
+ };
+ codec {
+ mclk-fs = <512>;
+ prefix = "pcm3168a";
+ sound-dai = <&pcm3168a 1>;
+ };
+ };
+ };
--
2.7.4
2
2
09 Jan '20
What is the impact assessment so far done for MIDI 2.0 for ALSA & Linux ?
Will a kernel change be needed for (USB) MIDI to support the MIDI 2.0
packet interface ?
How about the ALSA sequencer API ? Any activities around this ?
MIDI application based on Jack MIDI impact ?
https://www.midi.org/articles-old/details-about-midi-2-0-midi-ci-profiles-a…
https://www.midi.org/articles-old/midi-2-0-scope
https://thefeaturestory.com/2019/12/05/artlogic-give-exclusive-preview-of-m…
https://www.namm.org/thenammshow/2020/events/a3e-workshop-art-logic-midi-20…
https://juce.com/discover/stories/introducing-midi-2-0
https://www.musictech.net/features/midi-2-0-what-mean-for-you/
1
0
[alsa-devel] [PATCH][resend] ASoC: renesas, rsnd: switch to yaml base Documentation
by Kuninori Morimoto 09 Jan '20
by Kuninori Morimoto 09 Jan '20
09 Jan '20
From: Kuninori Morimoto <kuninori.morimoto.gx(a)renesas.com>
This patch switches from .txt base to .yaml base Document.
It is still keeping detail explanations at .txt
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx(a)renesas.com>
---
.../devicetree/bindings/sound/renesas,rsnd.txt | 518 --------------------
.../devicetree/bindings/sound/renesas,rsnd.yaml | 527 +++++++++++++++++++++
2 files changed, 527 insertions(+), 518 deletions(-)
create mode 100644 Documentation/devicetree/bindings/sound/renesas,rsnd.yaml
diff --git a/Documentation/devicetree/bindings/sound/renesas,rsnd.txt b/Documentation/devicetree/bindings/sound/renesas,rsnd.txt
index 797fd03..b731f16 100644
--- a/Documentation/devicetree/bindings/sound/renesas,rsnd.txt
+++ b/Documentation/devicetree/bindings/sound/renesas,rsnd.txt
@@ -253,521 +253,3 @@ This is example of TDM 6ch.
Driver can automatically switches TDM <-> stereo mode in this case.
see "Example: simple sound card for TDM"
-
-=============================================
-Required properties:
-=============================================
-
-- compatible : "renesas,rcar_sound-<soctype>", fallbacks
- "renesas,rcar_sound-gen1" if generation1, and
- "renesas,rcar_sound-gen2" if generation2 (or RZ/G1)
- "renesas,rcar_sound-gen3" if generation3 (or RZ/G2)
- Examples with soctypes are:
- - "renesas,rcar_sound-r8a7743" (RZ/G1M)
- - "renesas,rcar_sound-r8a7744" (RZ/G1N)
- - "renesas,rcar_sound-r8a7745" (RZ/G1E)
- - "renesas,rcar_sound-r8a77470" (RZ/G1C)
- - "renesas,rcar_sound-r8a774a1" (RZ/G2M)
- - "renesas,rcar_sound-r8a774b1" (RZ/G2N)
- - "renesas,rcar_sound-r8a774c0" (RZ/G2E)
- - "renesas,rcar_sound-r8a7778" (R-Car M1A)
- - "renesas,rcar_sound-r8a7779" (R-Car H1)
- - "renesas,rcar_sound-r8a7790" (R-Car H2)
- - "renesas,rcar_sound-r8a7791" (R-Car M2-W)
- - "renesas,rcar_sound-r8a7793" (R-Car M2-N)
- - "renesas,rcar_sound-r8a7794" (R-Car E2)
- - "renesas,rcar_sound-r8a7795" (R-Car H3)
- - "renesas,rcar_sound-r8a7796" (R-Car M3-W)
- - "renesas,rcar_sound-r8a77965" (R-Car M3-N)
- - "renesas,rcar_sound-r8a77990" (R-Car E3)
- - "renesas,rcar_sound-r8a77995" (R-Car D3)
-- reg : Should contain the register physical address.
- required register is
- SRU/ADG/SSI if generation1
- SRU/ADG/SSIU/SSI/AUDIO-DMAC-periperi if generation2/generation3
- Select extended AUDIO-DMAC-periperi address if SoC has it,
- otherwise select normal AUDIO-DMAC-periperi address.
-- reg-names : Should contain the register names.
- scu/adg/ssi if generation1
- scu/adg/ssiu/ssi/audmapp if generation2/generation3
-- rcar_sound,ssi : Should contain SSI feature.
- The number of SSI subnode should be same as HW.
- see below for detail.
-- rcar_sound,ssiu : Should contain SSIU feature.
- The number of SSIU subnode should be same as HW.
- see below for detail.
-- rcar_sound,src : Should contain SRC feature.
- The number of SRC subnode should be same as HW.
- see below for detail.
-- rcar_sound,ctu : Should contain CTU feature.
- The number of CTU subnode should be same as HW.
- see below for detail.
-- rcar_sound,mix : Should contain MIX feature.
- The number of MIX subnode should be same as HW.
- see below for detail.
-- rcar_sound,dvc : Should contain DVC feature.
- The number of DVC subnode should be same as HW.
- see below for detail.
-- rcar_sound,dai : DAI contents.
- The number of DAI subnode should be same as HW.
- see below for detail.
-- #sound-dai-cells : it must be 0 if your system is using single DAI
- it must be 1 if your system is using multi DAI
-- clocks : References to SSI/SRC/MIX/CTU/DVC/AUDIO_CLK clocks.
-- clock-names : List of necessary clock names.
- "ssi-all", "ssi.X", "src.X", "mix.X", "ctu.X",
- "dvc.X", "clk_a", "clk_b", "clk_c", "clk_i"
-
-Optional properties:
-- #clock-cells : it must be 0 if your system has audio_clkout
- it must be 1 if your system has audio_clkout0/1/2/3
-- clock-frequency : for all audio_clkout0/1/2/3
-- clkout-lr-asynchronous : boolean property. it indicates that audio_clkoutn
- is asynchronizes with lr-clock.
-- resets : References to SSI resets.
-- reset-names : List of valid reset names.
- "ssi-all", "ssi.X"
-
-SSI subnode properties:
-- interrupts : Should contain SSI interrupt for PIO transfer
-- shared-pin : if shared clock pin
-- pio-transfer : use PIO transfer mode
-- no-busif : BUSIF is not ussed when [mem -> SSI] via DMA case
-- dma : Should contain Audio DMAC entry
-- dma-names : SSI case "rx" (=playback), "tx" (=capture)
- Deprecated: see SSIU subnode properties
- SSIU case "rxu" (=playback), "txu" (=capture)
-
-SSIU subnode properties:
-- dma : Should contain Audio DMAC entry
-- dma-names : "rx" (=playback), "tx" (=capture)
-
-SRC subnode properties:
-- dma : Should contain Audio DMAC entry
-- dma-names : "rx" (=playback), "tx" (=capture)
-
-DVC subnode properties:
-- dma : Should contain Audio DMAC entry
-- dma-names : "tx" (=playback/capture)
-
-DAI subnode properties:
-- playback : list of playback modules
-- capture : list of capture modules
-
-
-=============================================
-Example:
-=============================================
-
-rcar_sound: sound@ec500000 {
- #sound-dai-cells = <1>;
- compatible = "renesas,rcar_sound-r8a7791", "renesas,rcar_sound-gen2";
- reg = <0 0xec500000 0 0x1000>, /* SCU */
- <0 0xec5a0000 0 0x100>, /* ADG */
- <0 0xec540000 0 0x1000>, /* SSIU */
- <0 0xec541000 0 0x1280>, /* SSI */
- <0 0xec740000 0 0x200>; /* Audio DMAC peri peri*/
- reg-names = "scu", "adg", "ssiu", "ssi", "audmapp";
-
- clocks = <&mstp10_clks R8A7790_CLK_SSI_ALL>,
- <&mstp10_clks R8A7790_CLK_SSI9>, <&mstp10_clks R8A7790_CLK_SSI8>,
- <&mstp10_clks R8A7790_CLK_SSI7>, <&mstp10_clks R8A7790_CLK_SSI6>,
- <&mstp10_clks R8A7790_CLK_SSI5>, <&mstp10_clks R8A7790_CLK_SSI4>,
- <&mstp10_clks R8A7790_CLK_SSI3>, <&mstp10_clks R8A7790_CLK_SSI2>,
- <&mstp10_clks R8A7790_CLK_SSI1>, <&mstp10_clks R8A7790_CLK_SSI0>,
- <&mstp10_clks R8A7790_CLK_SCU_SRC9>, <&mstp10_clks R8A7790_CLK_SCU_SRC8>,
- <&mstp10_clks R8A7790_CLK_SCU_SRC7>, <&mstp10_clks R8A7790_CLK_SCU_SRC6>,
- <&mstp10_clks R8A7790_CLK_SCU_SRC5>, <&mstp10_clks R8A7790_CLK_SCU_SRC4>,
- <&mstp10_clks R8A7790_CLK_SCU_SRC3>, <&mstp10_clks R8A7790_CLK_SCU_SRC2>,
- <&mstp10_clks R8A7790_CLK_SCU_SRC1>, <&mstp10_clks R8A7790_CLK_SCU_SRC0>,
- <&mstp10_clks R8A7790_CLK_SCU_DVC0>, <&mstp10_clks R8A7790_CLK_SCU_DVC1>,
- <&audio_clk_a>, <&audio_clk_b>, <&audio_clk_c>, <&m2_clk>;
- clock-names = "ssi-all",
- "ssi.9", "ssi.8", "ssi.7", "ssi.6", "ssi.5",
- "ssi.4", "ssi.3", "ssi.2", "ssi.1", "ssi.0",
- "src.9", "src.8", "src.7", "src.6", "src.5",
- "src.4", "src.3", "src.2", "src.1", "src.0",
- "dvc.0", "dvc.1",
- "clk_a", "clk_b", "clk_c", "clk_i";
-
- rcar_sound,dvc {
- dvc0: dvc-0 {
- dmas = <&audma0 0xbc>;
- dma-names = "tx";
- };
- dvc1: dvc-1 {
- dmas = <&audma0 0xbe>;
- dma-names = "tx";
- };
- };
-
- rcar_sound,mix {
- mix0: mix-0 { };
- mix1: mix-1 { };
- };
-
- rcar_sound,ctu {
- ctu00: ctu-0 { };
- ctu01: ctu-1 { };
- ctu02: ctu-2 { };
- ctu03: ctu-3 { };
- ctu10: ctu-4 { };
- ctu11: ctu-5 { };
- ctu12: ctu-6 { };
- ctu13: ctu-7 { };
- };
-
- rcar_sound,src {
- src0: src-0 {
- interrupts = <0 352 IRQ_TYPE_LEVEL_HIGH>;
- dmas = <&audma0 0x85>, <&audma1 0x9a>;
- dma-names = "rx", "tx";
- };
- src1: src-1 {
- interrupts = <0 353 IRQ_TYPE_LEVEL_HIGH>;
- dmas = <&audma0 0x87>, <&audma1 0x9c>;
- dma-names = "rx", "tx";
- };
- src2: src-2 {
- interrupts = <0 354 IRQ_TYPE_LEVEL_HIGH>;
- dmas = <&audma0 0x89>, <&audma1 0x9e>;
- dma-names = "rx", "tx";
- };
- src3: src-3 {
- interrupts = <0 355 IRQ_TYPE_LEVEL_HIGH>;
- dmas = <&audma0 0x8b>, <&audma1 0xa0>;
- dma-names = "rx", "tx";
- };
- src4: src-4 {
- interrupts = <0 356 IRQ_TYPE_LEVEL_HIGH>;
- dmas = <&audma0 0x8d>, <&audma1 0xb0>;
- dma-names = "rx", "tx";
- };
- src5: src-5 {
- interrupts = <0 357 IRQ_TYPE_LEVEL_HIGH>;
- dmas = <&audma0 0x8f>, <&audma1 0xb2>;
- dma-names = "rx", "tx";
- };
- src6: src-6 {
- interrupts = <0 358 IRQ_TYPE_LEVEL_HIGH>;
- dmas = <&audma0 0x91>, <&audma1 0xb4>;
- dma-names = "rx", "tx";
- };
- src7: src-7 {
- interrupts = <0 359 IRQ_TYPE_LEVEL_HIGH>;
- dmas = <&audma0 0x93>, <&audma1 0xb6>;
- dma-names = "rx", "tx";
- };
- src8: src-8 {
- interrupts = <0 360 IRQ_TYPE_LEVEL_HIGH>;
- dmas = <&audma0 0x95>, <&audma1 0xb8>;
- dma-names = "rx", "tx";
- };
- src9: src-9 {
- interrupts = <0 361 IRQ_TYPE_LEVEL_HIGH>;
- dmas = <&audma0 0x97>, <&audma1 0xba>;
- dma-names = "rx", "tx";
- };
- };
-
- rcar_sound,ssiu {
- ssiu00: ssiu-0 {
- dmas = <&audma0 0x15>, <&audma1 0x16>;
- dma-names = "rx", "tx";
- };
- ssiu01: ssiu-1 {
- dmas = <&audma0 0x35>, <&audma1 0x36>;
- dma-names = "rx", "tx";
- };
-
- ...
-
- ssiu95: ssiu-49 {
- dmas = <&audma0 0xA5>, <&audma1 0xA6>;
- dma-names = "rx", "tx";
- };
- ssiu96: ssiu-50 {
- dmas = <&audma0 0xA7>, <&audma1 0xA8>;
- dma-names = "rx", "tx";
- };
- ssiu97: ssiu-51 {
- dmas = <&audma0 0xA9>, <&audma1 0xAA>;
- dma-names = "rx", "tx";
- };
- };
-
- rcar_sound,ssi {
- ssi0: ssi-0 {
- interrupts = <0 370 IRQ_TYPE_LEVEL_HIGH>;
- dmas = <&audma0 0x01>, <&audma1 0x02>;
- dma-names = "rx", "tx";
- };
- ssi1: ssi-1 {
- interrupts = <0 371 IRQ_TYPE_LEVEL_HIGH>;
- dmas = <&audma0 0x03>, <&audma1 0x04>;
- dma-names = "rx", "tx";
- };
-
- ...
-
- ssi8: ssi-8 {
- interrupts = <0 378 IRQ_TYPE_LEVEL_HIGH>;
- dmas = <&audma0 0x11>, <&audma1 0x12>;
- dma-names = "rx", "tx";
- };
- ssi9: ssi-9 {
- interrupts = <0 379 IRQ_TYPE_LEVEL_HIGH>;
- dmas = <&audma0 0x13>, <&audma1 0x14>;
- dma-names = "rx", "tx";
- };
- };
-
- rcar_sound,dai {
- dai0 {
- playback = <&ssi5 &src5>;
- capture = <&ssi6>;
- };
- dai1 {
- playback = <&ssi3>;
- };
- dai2 {
- capture = <&ssi4>;
- };
- dai3 {
- playback = <&ssi7>;
- };
- dai4 {
- capture = <&ssi8>;
- };
- };
-};
-
-=============================================
-Example: simple sound card
-=============================================
-
- rsnd_ak4643: sound {
- compatible = "simple-audio-card";
-
- simple-audio-card,format = "left_j";
- simple-audio-card,bitclock-master = <&sndcodec>;
- simple-audio-card,frame-master = <&sndcodec>;
-
- sndcpu: simple-audio-card,cpu {
- sound-dai = <&rcar_sound>;
- };
-
- sndcodec: simple-audio-card,codec {
- sound-dai = <&ak4643>;
- clocks = <&audio_clock>;
- };
- };
-
-&rcar_sound {
- pinctrl-0 = <&sound_pins &sound_clk_pins>;
- pinctrl-names = "default";
-
- /* Single DAI */
- #sound-dai-cells = <0>;
-
-
- rcar_sound,dai {
- dai0 {
- playback = <&ssi0 &src2 &dvc0>;
- capture = <&ssi1 &src3 &dvc1>;
- };
- };
-};
-
-&ssi1 {
- shared-pin;
-};
-
-=============================================
-Example: simple sound card for Asynchronous mode
-=============================================
-
-sound {
- compatible = "simple-scu-audio-card";
- ...
- /*
- * SRC Asynchronous mode setting
- * Playback:
- * All input data will be converted to 48kHz
- * Capture:
- * Inputed 48kHz data will be converted to
- * system specified Hz
- */
- simple-audio-card,convert-rate = <48000>;
- ...
- simple-audio-card,cpu {
- sound-dai = <&rcar_sound>;
- };
- simple-audio-card,codec {
- ...
- };
-};
-
-=============================================
-Example: simple sound card for channel convert
-=============================================
-
-sound {
- compatible = "simple-scu-audio-card";
- ...
- /*
- * CTU setting
- * All input data will be converted to 2ch
- * as output data
- */
- simple-audio-card,convert-channels = <2>;
- ...
- simple-audio-card,cpu {
- sound-dai = <&rcar_sound>;
- };
- simple-audio-card,codec {
- ...
- };
-};
-
-=============================================
-Example: simple sound card for MIXer
-=============================================
-
-sound {
- compatible = "simple-scu-audio-card";
- ...
- simple-audio-card,cpu@0 {
- sound-dai = <&rcar_sound 0>;
- };
- simple-audio-card,cpu@1 {
- sound-dai = <&rcar_sound 1>;
- };
- simple-audio-card,codec {
- ...
- };
-};
-
-&rcar_sound {
- ...
- rcar_sound,dai {
- dai0 {
- playback = <&src1 &ctu02 &mix0 &dvc0 &ssi0>;
- };
- dai1 {
- playback = <&src2 &ctu03 &mix0 &dvc0 &ssi0>;
- };
- };
-};
-
-=============================================
-Example: simple sound card for TDM
-=============================================
-
-rsnd_tdm: sound {
- compatible = "simple-audio-card";
-
- simple-audio-card,format = "left_j";
- simple-audio-card,bitclock-master = <&sndcodec>;
- simple-audio-card,frame-master = <&sndcodec>;
-
- sndcpu: simple-audio-card,cpu {
- sound-dai = <&rcar_sound>;
- dai-tdm-slot-num = <6>;
- };
-
- sndcodec: simple-audio-card,codec {
- sound-dai = <&xxx>;
- };
-};
-
-=============================================
-Example: simple sound card for TDM Split
-=============================================
-
-sound_card: sound {
- compatible = "audio-graph-scu-card";
- prefix = "xxxx";
- routing = "xxxx Playback", "DAI0 Playback",
- "xxxx Playback", "DAI1 Playback",
- "xxxx Playback", "DAI2 Playback",
- "xxxx Playback", "DAI3 Playback";
- convert-channels = <8>; /* TDM Split */
-
- dais = <&rsnd_port0 /* playback ch1/ch2 */
- &rsnd_port1 /* playback ch3/ch4 */
- &rsnd_port2 /* playback ch5/ch6 */
- &rsnd_port3 /* playback ch7/ch8 */
- >;
-};
-
-audio-codec {
- ...
- port {
- codec_0: endpoint@1 {
- remote-endpoint = <&rsnd_ep0>;
- };
- codec_1: endpoint@2 {
- remote-endpoint = <&rsnd_ep1>;
- };
- codec_2: endpoint@3 {
- remote-endpoint = <&rsnd_ep2>;
- };
- codec_3: endpoint@4 {
- remote-endpoint = <&rsnd_ep3>;
- };
- };
-};
-
-&rcar_sound {
- ...
- ports {
- rsnd_port0: port@0 {
- rsnd_ep0: endpoint {
- remote-endpoint = <&codec_0>;
- ...
- playback = <&ssiu30 &ssi3>;
- };
- };
- rsnd_port1: port@1 {
- rsnd_ep1: endpoint {
- remote-endpoint = <&codec_1>;
- ...
- playback = <&ssiu31 &ssi3>;
- };
- };
- rsnd_port2: port@2 {
- rsnd_ep2: endpoint {
- remote-endpoint = <&codec_2>;
- ...
- playback = <&ssiu32 &ssi3>;
- };
- };
- rsnd_port3: port@3 {
- rsnd_ep3: endpoint {
- remote-endpoint = <&codec_3>;
- ...
- playback = <&ssiu33 &ssi3>;
- };
- };
- };
-};
-
-=============================================
-Example: simple sound card for Multi channel
-=============================================
-
-&rcar_sound {
- pinctrl-0 = <&sound_pins &sound_clk_pins>;
- pinctrl-names = "default";
-
- /* Single DAI */
- #sound-dai-cells = <0>;
-
-
- rcar_sound,dai {
- dai0 {
- playback = <&ssi0 &ssi1 &ssi2 &src0 &dvc0>;
- };
- };
-};
diff --git a/Documentation/devicetree/bindings/sound/renesas,rsnd.yaml b/Documentation/devicetree/bindings/sound/renesas,rsnd.yaml
new file mode 100644
index 0000000..5fb036c
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/renesas,rsnd.yaml
@@ -0,0 +1,527 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/renesas,rsnd.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Renesas R-Car Sound Driver Device Tree Bindings
+
+maintainers:
+ - Kuninori Morimoto <kuninori.morimoto.gx(a)renesas.com>
+
+properties:
+ $nodename:
+ pattern: "^sound@.*"
+
+ compatible:
+ oneOf:
+ # for Gen1 SoC
+ - items:
+ - enum:
+ - renesas,rcar_sound-r8a7778 # R-Car M1A
+ - renesas,rcar_sound-r8a7779 # R-Car H1
+ - enum:
+ - renesas,rcar_sound-gen1
+ # for Gen2 SoC
+ - items:
+ - enum:
+ - renesas,rcar_sound-r8a7743 # RZ/G1M
+ - renesas,rcar_sound-r8a7744 # RZ/G1N
+ - renesas,rcar_sound-r8a7745 # RZ/G1E
+ - renesas,rcar_sound-r8a77470 # RZ/G1C
+ - renesas,rcar_sound-r8a7790 # R-Car H2
+ - renesas,rcar_sound-r8a7791 # R-Car M2-W
+ - renesas,rcar_sound-r8a7793 # R-Car M2-N
+ - renesas,rcar_sound-r8a7794 # R-Car E2
+ - enum:
+ - renesas,rcar_sound-gen2
+ # for Gen3 SoC
+ - items:
+ - enum:
+ - renesas,rcar_sound-r8a774a1 # RZ/G2M
+ - renesas,rcar_sound-r8a774b1 # RZ/G2N
+ - renesas,rcar_sound-r8a774c0 # RZ/G2E
+ - renesas,rcar_sound-r8a7795 # R-Car H3
+ - renesas,rcar_sound-r8a7796 # R-Car M3-W
+ - renesas,rcar_sound-r8a77965 # R-Car M3-N
+ - renesas,rcar_sound-r8a77990 # R-Car E3
+ - renesas,rcar_sound-r8a77995 # R-Car D3
+ - enum:
+ - renesas,rcar_sound-gen3
+ # for Generic
+ - items:
+ - enum:
+ - renesas,rcar_sound-gen1
+ - renesas,rcar_sound-gen2
+ - renesas,rcar_sound-gen3
+
+ reg:
+ minItems: 3 # Gen1
+ maxItems: 5 # Gen2/Gen3
+
+ reg-names:
+ description: |
+ Should contain the register names.
+ scu/adg/ssi if generation1
+ scu/adg/ssiu/ssi/audmapp if generation2/generation3
+ minItems: 3 # Gen1
+ maxItems: 5 # Gen2/Gen3
+ allOf:
+ - items:
+ enum:
+ - scu
+ - adg
+ - ssiu
+ - ssi
+ - audmapp
+
+ "#sound-dai-cells":
+ description: |
+ it must be 0 if your system is using single DAI
+ it must be 1 if your system is using multi DAIs
+ enum: [0, 1]
+
+ "#clock-cells":
+ description: |
+ it must be 0 if your system has audio_clkout
+ it must be 1 if your system has audio_clkout0/1/2/3
+ enum: [0, 1]
+
+ clock-frequency:
+ description: for audio_clkout0/1/2/3
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+
+ clkout-lr-asynchronous:
+ description: audio_clkoutn is asynchronizes with lr-clock.
+ $ref: /schemas/types.yaml#/definitions/flag
+
+ power-domains: true
+
+ resets:
+ description: References to SSI resets
+ $ref: /schemas/types.yaml#/definitions/phandle-array
+
+ reset-names:
+ description: List of valid reset names.
+ allOf:
+ - items:
+ enum:
+ - ssi-all
+ - ssi.9
+ - ssi.8
+ - ssi.7
+ - ssi.6
+ - ssi.5
+ - ssi.4
+ - ssi.3
+ - ssi.2
+ - ssi.1
+ - ssi.0
+
+ clocks:
+ $ref: /schemas/types.yaml#/definitions/phandle-array
+ description: References to SSI/SRC/MIX/CTU/DVC/AUDIO_CLK clocks.
+
+ clock-names:
+ description: List of necessary clock names.
+ allOf:
+ - items:
+ enum:
+ - ssi-all
+ - ssi.9
+ - ssi.8
+ - ssi.7
+ - ssi.6
+ - ssi.5
+ - ssi.4
+ - ssi.3
+ - ssi.2
+ - ssi.1
+ - ssi.0
+ - src.9
+ - src.8
+ - src.7
+ - src.6
+ - src.5
+ - src.4
+ - src.3
+ - src.2
+ - src.1
+ - src.0
+ - mix.1
+ - mix.0
+ - ctu.1
+ - ctu.0
+ - dvc.1
+ - dvc.0
+ - clk_a
+ - clk_b
+ - clk_c
+ - clk_i
+
+ # For OF-graph
+ port:
+ description: OF-Graph subnode
+ type: object
+ properties:
+ reg:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ endpoint:
+ type: object
+ properties:
+ remote-endpoint:
+ $ref: /schemas/types.yaml#/definitions/phandle-array
+ dai-format:
+ $ref: "simple-card.yaml#/definitions/format"
+ playback:
+ $ref: /schemas/types.yaml#/definitions/phandle-array
+ capture:
+ $ref: /schemas/types.yaml#/definitions/phandle-array
+ required:
+ - remote-endpoint
+
+ # For multi OF-graph
+ ports:
+ description: multi OF-Graph subnode
+ type: object
+ patternProperties:
+ "port.*":
+ $ref: "#properties/port"
+
+patternProperties:
+ "^rcar_sound,dvc$":
+ description: DVC subnode.
+ type: object
+ patternProperties:
+ "dvc.*":
+ type: object
+ properties:
+ dmas:
+ $ref: /schemas/types.yaml#/definitions/phandle-array
+ dma-names:
+ const: "tx"
+ required:
+ - dmas
+ - dma-names
+ additionalProperties: false
+
+ "^rcar_sound,mix$":
+ description: MIX subnode.
+ type: object
+ patternProperties:
+ "mix.*":
+ type: object
+ additionalProperties: false
+
+ "^rcar_sound,ctu$":
+ description: CTU subnode.
+ type: object
+ patternProperties:
+ "ctu.*":
+ type: object
+ additionalProperties: false
+
+ "^rcar_sound,src$":
+ description: SRC subnode.
+ type: object
+ patternProperties:
+ "src.*":
+ type: object
+ properties:
+ interrupts:
+ maxItems: 1
+ dmas:
+ $ref: /schemas/types.yaml#/definitions/phandle-array
+ dma-names:
+ allOf:
+ - items:
+ enum:
+ - tx
+ - rx
+ if:
+ properties:
+ status:
+ const: "ok"
+ then:
+ required:
+ - interrupts
+ - dmas
+ - dma-names
+ additionalProperties: false
+
+ "^rcar_sound,ssiu$":
+ description: SSIU subnode.
+ type: object
+ patternProperties:
+ "ssiu.*":
+ type: object
+ properties:
+ dmas:
+ $ref: /schemas/types.yaml#/definitions/phandle-array
+ dma-names:
+ allOf:
+ - items:
+ enum:
+ - tx
+ - rx
+ required:
+ - dmas
+ - dma-names
+ additionalProperties: false
+
+ "^rcar_sound,ssi$":
+ description: SSI subnode.
+ type: object
+ patternProperties:
+ "ssi.*":
+ type: object
+ properties:
+ interrupts:
+ maxItems: 1
+ dmas:
+ $ref: /schemas/types.yaml#/definitions/phandle-array
+ dma-names:
+ allOf:
+ - items:
+ enum:
+ - tx
+ - rx
+ - txu # if no ssiu node
+ - rxu # if no ssiu node
+
+ shared-pin:
+ description: shared clock pin
+ $ref: /schemas/types.yaml#/definitions/flag
+ pio-transfer:
+ description: PIO transfer mode
+ $ref: /schemas/types.yaml#/definitions/flag
+ no-busif:
+ description: BUSIF is not used when [mem -> SSI] via DMA case
+ $ref: /schemas/types.yaml#/definitions/flag
+ required:
+ - interrupts
+ - dmas
+ - dma-names
+ additionalProperties: false
+
+ # For DAI base
+ "^rcar_sound,dai$":
+ description: DAI subnode.
+ type: object
+ patternProperties:
+ "dai.*":
+ type: object
+ properties:
+ playback:
+ $ref: /schemas/types.yaml#/definitions/phandle-array
+ capture:
+ $ref: /schemas/types.yaml#/definitions/phandle-array
+ anyOf:
+ - required:
+ - playback
+ - required:
+ - capture
+ additionalProperties: false
+
+required:
+ - compatible
+ - reg
+ - reg-names
+ - clocks
+ - clock-names
+ - "#sound-dai-cells"
+
+additionalProperties: false
+
+examples:
+ - |
+ rcar_sound: sound@ec500000 {
+ #sound-dai-cells = <1>;
+ compatible = "renesas,rcar_sound-r8a7790", "renesas,rcar_sound-gen2";
+ reg = <0 0xec500000 0 0x1000>, /* SCU */
+ <0 0xec5a0000 0 0x100>, /* ADG */
+ <0 0xec540000 0 0x1000>, /* SSIU */
+ <0 0xec541000 0 0x1280>, /* SSI */
+ <0 0xec740000 0 0x200>; /* Audio DMAC peri peri*/
+ reg-names = "scu", "adg", "ssiu", "ssi", "audmapp";
+
+ clocks = <&mstp10_clks 1005>, /* SSI-ALL */
+ <&mstp10_clks 1006>, <&mstp10_clks 1007>, /* SSI9, SSI8 */
+ <&mstp10_clks 1008>, <&mstp10_clks 1009>, /* SSI7, SSI6 */
+ <&mstp10_clks 1010>, <&mstp10_clks 1011>, /* SSI5, SSI4 */
+ <&mstp10_clks 1012>, <&mstp10_clks 1013>, /* SSI3, SSI2 */
+ <&mstp10_clks 1014>, <&mstp10_clks 1015>, /* SSI1, SSI0 */
+ <&mstp10_clks 1022>, <&mstp10_clks 1023>, /* SRC9, SRC8 */
+ <&mstp10_clks 1024>, <&mstp10_clks 1025>, /* SRC7, SRC6 */
+ <&mstp10_clks 1026>, <&mstp10_clks 1027>, /* SRC5, SRC4 */
+ <&mstp10_clks 1028>, <&mstp10_clks 1029>, /* SRC3, SRC2 */
+ <&mstp10_clks 1030>, <&mstp10_clks 1031>, /* SRC1, SRC0 */
+ <&mstp10_clks 1020>, <&mstp10_clks 1021>, /* DVC0, DVC1 */
+ <&mstp10_clks 1020>, <&mstp10_clks 1021>, /* CLKA, CLKB */
+ <&mstp10_clks 1019>, <&mstp10_clks 1018>; /* CLKC, CLKI */
+
+ clock-names = "ssi-all",
+ "ssi.9", "ssi.8",
+ "ssi.7", "ssi.6",
+ "ssi.5", "ssi.4",
+ "ssi.3", "ssi.2",
+ "ssi.1", "ssi.0",
+ "src.9", "src.8",
+ "src.7", "src.6",
+ "src.5", "src.4",
+ "src.3", "src.2",
+ "src.1", "src.0",
+ "dvc.0", "dvc.1",
+ "clk_a", "clk_b",
+ "clk_c", "clk_i";
+
+ rcar_sound,dvc {
+ dvc0: dvc-0 {
+ dmas = <&audma0 0xbc>;
+ dma-names = "tx";
+ };
+ dvc1: dvc-1 {
+ dmas = <&audma0 0xbe>;
+ dma-names = "tx";
+ };
+ };
+
+
+ rcar_sound,mix {
+ mix0: mix-0 { };
+ mix1: mix-1 { };
+ };
+
+ rcar_sound,ctu {
+ ctu00: ctu-0 { };
+ ctu01: ctu-1 { };
+ ctu02: ctu-2 { };
+ ctu03: ctu-3 { };
+ ctu10: ctu-4 { };
+ ctu11: ctu-5 { };
+ ctu12: ctu-6 { };
+ ctu13: ctu-7 { };
+ };
+
+ rcar_sound,src {
+ src0: src-0 {
+ status = "disabled";
+ };
+ src1: src-1 {
+ interrupts = <0 353 0>;
+ dmas = <&audma0 0x87>, <&audma1 0x9c>;
+ dma-names = "rx", "tx";
+ };
+ /* skip after src-2 */
+ };
+
+ rcar_sound,ssiu {
+ ssiu00: ssiu-0 {
+ dmas = <&audma0 0x15>, <&audma1 0x16>;
+ dma-names = "rx", "tx";
+ };
+ ssiu01: ssiu-1 {
+ dmas = <&audma0 0x35>, <&audma1 0x36>;
+ dma-names = "rx", "tx";
+ };
+ /* skip after ssiu-2 */
+ };
+
+ rcar_sound,ssi {
+ ssi0: ssi-0 {
+ interrupts = <0 370 1>;
+ dmas = <&audma0 0x01>, <&audma1 0x02>;
+ dma-names = "rx", "tx";
+ };
+ ssi1: ssi-1 {
+ interrupts = <0 371 1>;
+ dmas = <&audma0 0x03>, <&audma1 0x04>;
+ dma-names = "rx", "tx";
+ };
+ /* skip other ssi-2 */
+ };
+
+ /* DAI base */
+ rcar_sound,dai {
+ dai0 {
+ playback = <&ssi5 &src5>;
+ capture = <&ssi6>;
+ };
+ dai1 {
+ playback = <&ssi3>;
+ };
+ dai2 {
+ capture = <&ssi4>;
+ };
+ dai3 {
+ playback = <&ssi7>;
+ };
+ dai4 {
+ capture = <&ssi8>;
+ };
+ };
+
+ /* OF-Graph */
+ port {
+ rsnd_endpoint: endpoint {
+ remote-endpoint = <&codec_endpoint>;
+
+ dai-format = "left_j";
+ bitclock-master = <&rsnd_endpoint0>;
+ frame-master = <&rsnd_endpoint0>;
+
+ playback = <&ssi0 &src0 &dvc0>;
+ capture = <&ssi1 &src1 &dvc1>;
+ };
+ };
+
+ /* Multi OF-Graph */
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ rsnd_port0: port@0 {
+ reg = <0>;
+ rsnd_endpoint0: endpoint {
+ remote-endpoint = <&codec_endpoint1>;
+
+ dai-format = "left_j";
+ bitclock-master = <&rsnd_endpoint0>;
+ frame-master = <&rsnd_endpoint0>;
+
+ playback = <&ssi0 &src0 &dvc0>;
+ capture = <&ssi1 &src1 &dvc1>;
+ };
+ };
+ rsnd_port1: port@1 {
+ reg = <1>;
+ rsnd_endpoint1: endpoint {
+ remote-endpoint = <&codec_endpoint2>;
+
+ dai-format = "i2s";
+ playback = <&ssi0 &src0 &dvc0>;
+ capture = <&ssi1 &src1 &dvc1>;
+ };
+ };
+ };
+ };
+
+
+ codec {
+ ports {
+ port@0 {
+ codec_endpoint: endpoint {
+ remote-endpoint = <&rsnd_endpoint>;
+ };
+ };
+ port@1 {
+ codec_endpoint1: endpoint {
+ remote-endpoint = <&rsnd_endpoint0>;
+ };
+ };
+ port@2 {
+ codec_endpoint2: endpoint {
+ remote-endpoint = <&rsnd_endpoint1>;
+ };
+ };
+ };
+ };
--
2.7.4
1
0
[alsa-devel] [PATCH] treewide: remove redundent IS_ERR() before error code check
by Masahiro Yamada 08 Jan '20
by Masahiro Yamada 08 Jan '20
08 Jan '20
'PTR_ERR(p) == -E*' is a stronger condition than IS_ERR(p).
Hence, IS_ERR(p) is unneeded.
The semantic patch that generates this commit is as follows:
// <smpl>
@@
expression ptr;
constant error_code;
@@
-IS_ERR(ptr) && (PTR_ERR(ptr) == - error_code)
+PTR_ERR(ptr) == - error_code
// </smpl>
Signed-off-by: Masahiro Yamada <masahiroy(a)kernel.org>
---
crypto/af_alg.c | 2 +-
drivers/acpi/scan.c | 2 +-
drivers/char/hw_random/bcm2835-rng.c | 2 +-
drivers/char/hw_random/omap-rng.c | 4 ++--
drivers/clk/clk.c | 2 +-
drivers/dma/mv_xor_v2.c | 2 +-
drivers/gpio/gpiolib-devres.c | 2 +-
drivers/gpio/gpiolib-of.c | 8 ++++----
drivers/gpio/gpiolib.c | 2 +-
drivers/i2c/busses/i2c-mv64xxx.c | 5 ++---
drivers/i2c/busses/i2c-synquacer.c | 2 +-
drivers/mtd/ubi/build.c | 2 +-
drivers/of/device.c | 2 +-
drivers/pci/controller/pci-tegra.c | 2 +-
drivers/phy/phy-core.c | 4 ++--
drivers/spi/spi-orion.c | 3 +--
drivers/video/fbdev/imxfb.c | 2 +-
fs/ext4/super.c | 2 +-
fs/f2fs/node.c | 2 +-
fs/ocfs2/suballoc.c | 2 +-
fs/sysfs/group.c | 2 +-
net/core/dev.c | 2 +-
net/core/filter.c | 2 +-
net/xfrm/xfrm_policy.c | 2 +-
sound/soc/codecs/ak4104.c | 3 +--
sound/soc/codecs/cs4270.c | 3 +--
sound/soc/codecs/tlv320aic32x4.c | 6 ++----
sound/soc/sunxi/sun4i-spdif.c | 2 +-
28 files changed, 35 insertions(+), 41 deletions(-)
diff --git a/crypto/af_alg.c b/crypto/af_alg.c
index 0dceaabc6321..0cc82bec0657 100644
--- a/crypto/af_alg.c
+++ b/crypto/af_alg.c
@@ -169,7 +169,7 @@ static int alg_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
sa->salg_name[sizeof(sa->salg_name) + addr_len - sizeof(*sa) - 1] = 0;
type = alg_get_type(sa->salg_type);
- if (IS_ERR(type) && PTR_ERR(type) == -ENOENT) {
+ if (PTR_ERR(type) == -ENOENT) {
request_module("algif-%s", sa->salg_type);
type = alg_get_type(sa->salg_type);
}
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 915650bf519f..6d3448895382 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -1462,7 +1462,7 @@ int acpi_dma_configure(struct device *dev, enum dev_dma_attr attr)
iort_dma_setup(dev, &dma_addr, &size);
iommu = iort_iommu_configure(dev);
- if (IS_ERR(iommu) && PTR_ERR(iommu) == -EPROBE_DEFER)
+ if (PTR_ERR(iommu) == -EPROBE_DEFER)
return -EPROBE_DEFER;
arch_setup_dma_ops(dev, dma_addr, size,
diff --git a/drivers/char/hw_random/bcm2835-rng.c b/drivers/char/hw_random/bcm2835-rng.c
index d2a5791eb49f..cbf5eaea662c 100644
--- a/drivers/char/hw_random/bcm2835-rng.c
+++ b/drivers/char/hw_random/bcm2835-rng.c
@@ -157,7 +157,7 @@ static int bcm2835_rng_probe(struct platform_device *pdev)
/* Clock is optional on most platforms */
priv->clk = devm_clk_get(dev, NULL);
- if (IS_ERR(priv->clk) && PTR_ERR(priv->clk) == -EPROBE_DEFER)
+ if (PTR_ERR(priv->clk) == -EPROBE_DEFER)
return -EPROBE_DEFER;
priv->rng.name = pdev->name;
diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c
index 0ed07d16ec8e..65952393e1bb 100644
--- a/drivers/char/hw_random/omap-rng.c
+++ b/drivers/char/hw_random/omap-rng.c
@@ -476,7 +476,7 @@ static int omap_rng_probe(struct platform_device *pdev)
}
priv->clk = devm_clk_get(&pdev->dev, NULL);
- if (IS_ERR(priv->clk) && PTR_ERR(priv->clk) == -EPROBE_DEFER)
+ if (PTR_ERR(priv->clk) == -EPROBE_DEFER)
return -EPROBE_DEFER;
if (!IS_ERR(priv->clk)) {
ret = clk_prepare_enable(priv->clk);
@@ -488,7 +488,7 @@ static int omap_rng_probe(struct platform_device *pdev)
}
priv->clk_reg = devm_clk_get(&pdev->dev, "reg");
- if (IS_ERR(priv->clk_reg) && PTR_ERR(priv->clk_reg) == -EPROBE_DEFER)
+ if (PTR_ERR(priv->clk_reg) == -EPROBE_DEFER)
return -EPROBE_DEFER;
if (!IS_ERR(priv->clk_reg)) {
ret = clk_prepare_enable(priv->clk_reg);
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 6a11239ccde3..3c27699487c1 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -429,7 +429,7 @@ static void clk_core_fill_parent_index(struct clk_core *core, u8 index)
parent = ERR_PTR(-EPROBE_DEFER);
} else {
parent = clk_core_get(core, index);
- if (IS_ERR(parent) && PTR_ERR(parent) == -ENOENT && entry->name)
+ if (PTR_ERR(parent) == -ENOENT && entry->name)
parent = clk_core_lookup(entry->name);
}
diff --git a/drivers/dma/mv_xor_v2.c b/drivers/dma/mv_xor_v2.c
index e3850f04f676..157c959311ea 100644
--- a/drivers/dma/mv_xor_v2.c
+++ b/drivers/dma/mv_xor_v2.c
@@ -750,7 +750,7 @@ static int mv_xor_v2_probe(struct platform_device *pdev)
}
xor_dev->clk = devm_clk_get(&pdev->dev, NULL);
- if (IS_ERR(xor_dev->clk) && PTR_ERR(xor_dev->clk) == -EPROBE_DEFER) {
+ if (PTR_ERR(xor_dev->clk) == -EPROBE_DEFER) {
ret = EPROBE_DEFER;
goto disable_reg_clk;
}
diff --git a/drivers/gpio/gpiolib-devres.c b/drivers/gpio/gpiolib-devres.c
index 4421be09b960..72b6001c56ef 100644
--- a/drivers/gpio/gpiolib-devres.c
+++ b/drivers/gpio/gpiolib-devres.c
@@ -308,7 +308,7 @@ devm_gpiod_get_array_optional(struct device *dev, const char *con_id,
struct gpio_descs *descs;
descs = devm_gpiod_get_array(dev, con_id, flags);
- if (IS_ERR(descs) && (PTR_ERR(descs) == -ENOENT))
+ if (PTR_ERR(descs) == -ENOENT)
return NULL;
return descs;
diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c
index b696e4598a24..3d3659cd72ef 100644
--- a/drivers/gpio/gpiolib-of.c
+++ b/drivers/gpio/gpiolib-of.c
@@ -505,24 +505,24 @@ struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
break;
}
- if (IS_ERR(desc) && PTR_ERR(desc) == -ENOENT) {
+ if (PTR_ERR(desc) == -ENOENT) {
/* Special handling for SPI GPIOs if used */
desc = of_find_spi_gpio(dev, con_id, &of_flags);
}
- if (IS_ERR(desc) && PTR_ERR(desc) == -ENOENT) {
+ if (PTR_ERR(desc) == -ENOENT) {
/* This quirk looks up flags and all */
desc = of_find_spi_cs_gpio(dev, con_id, idx, flags);
if (!IS_ERR(desc))
return desc;
}
- if (IS_ERR(desc) && PTR_ERR(desc) == -ENOENT) {
+ if (PTR_ERR(desc) == -ENOENT) {
/* Special handling for regulator GPIOs if used */
desc = of_find_regulator_gpio(dev, con_id, &of_flags);
}
- if (IS_ERR(desc) && PTR_ERR(desc) == -ENOENT)
+ if (PTR_ERR(desc) == -ENOENT)
desc = of_find_arizona_gpio(dev, con_id, &of_flags);
if (IS_ERR(desc))
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 78a16e42f222..20a6adf2128f 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -5067,7 +5067,7 @@ struct gpio_descs *__must_check gpiod_get_array_optional(struct device *dev,
struct gpio_descs *descs;
descs = gpiod_get_array(dev, con_id, flags);
- if (IS_ERR(descs) && (PTR_ERR(descs) == -ENOENT))
+ if (PTR_ERR(descs) == -ENOENT)
return NULL;
return descs;
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
index a5a95ea5b81a..febb7c7ea72b 100644
--- a/drivers/i2c/busses/i2c-mv64xxx.c
+++ b/drivers/i2c/busses/i2c-mv64xxx.c
@@ -901,14 +901,13 @@ mv64xxx_i2c_probe(struct platform_device *pd)
/* Not all platforms have clocks */
drv_data->clk = devm_clk_get(&pd->dev, NULL);
- if (IS_ERR(drv_data->clk) && PTR_ERR(drv_data->clk) == -EPROBE_DEFER)
+ if (PTR_ERR(drv_data->clk) == -EPROBE_DEFER)
return -EPROBE_DEFER;
if (!IS_ERR(drv_data->clk))
clk_prepare_enable(drv_data->clk);
drv_data->reg_clk = devm_clk_get(&pd->dev, "reg");
- if (IS_ERR(drv_data->reg_clk) &&
- PTR_ERR(drv_data->reg_clk) == -EPROBE_DEFER)
+ if (PTR_ERR(drv_data->reg_clk) == -EPROBE_DEFER)
return -EPROBE_DEFER;
if (!IS_ERR(drv_data->reg_clk))
clk_prepare_enable(drv_data->reg_clk);
diff --git a/drivers/i2c/busses/i2c-synquacer.c b/drivers/i2c/busses/i2c-synquacer.c
index 39762f0611b1..86026798b4f7 100644
--- a/drivers/i2c/busses/i2c-synquacer.c
+++ b/drivers/i2c/busses/i2c-synquacer.c
@@ -553,7 +553,7 @@ static int synquacer_i2c_probe(struct platform_device *pdev)
&i2c->pclkrate);
i2c->pclk = devm_clk_get(&pdev->dev, "pclk");
- if (IS_ERR(i2c->pclk) && PTR_ERR(i2c->pclk) == -EPROBE_DEFER)
+ if (PTR_ERR(i2c->pclk) == -EPROBE_DEFER)
return -EPROBE_DEFER;
if (!IS_ERR_OR_NULL(i2c->pclk)) {
dev_dbg(&pdev->dev, "clock source %p\n", i2c->pclk);
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index d636bbe214cb..e58dda6c7075 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -1159,7 +1159,7 @@ static struct mtd_info * __init open_mtd_device(const char *mtd_dev)
* MTD device name.
*/
mtd = get_mtd_device_nm(mtd_dev);
- if (IS_ERR(mtd) && PTR_ERR(mtd) == -ENODEV)
+ if (PTR_ERR(mtd) == -ENODEV)
/* Probably this is an MTD character device node path */
mtd = open_mtd_by_chdev(mtd_dev);
} else
diff --git a/drivers/of/device.c b/drivers/of/device.c
index e9127db7b067..27203bfd0b22 100644
--- a/drivers/of/device.c
+++ b/drivers/of/device.c
@@ -161,7 +161,7 @@ int of_dma_configure(struct device *dev, struct device_node *np, bool force_dma)
coherent ? " " : " not ");
iommu = of_iommu_configure(dev, np);
- if (IS_ERR(iommu) && PTR_ERR(iommu) == -EPROBE_DEFER)
+ if (PTR_ERR(iommu) == -EPROBE_DEFER)
return -EPROBE_DEFER;
dev_dbg(dev, "device is%sbehind an iommu\n",
diff --git a/drivers/pci/controller/pci-tegra.c b/drivers/pci/controller/pci-tegra.c
index 673a1725ef38..40928c4d261d 100644
--- a/drivers/pci/controller/pci-tegra.c
+++ b/drivers/pci/controller/pci-tegra.c
@@ -1406,7 +1406,7 @@ static struct phy *devm_of_phy_optional_get_index(struct device *dev,
phy = devm_of_phy_get(dev, np, name);
kfree(name);
- if (IS_ERR(phy) && PTR_ERR(phy) == -ENODEV)
+ if (PTR_ERR(phy) == -ENODEV)
phy = NULL;
return phy;
diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c
index b04f4fe85ac2..48d355cf0210 100644
--- a/drivers/phy/phy-core.c
+++ b/drivers/phy/phy-core.c
@@ -690,7 +690,7 @@ struct phy *phy_optional_get(struct device *dev, const char *string)
{
struct phy *phy = phy_get(dev, string);
- if (IS_ERR(phy) && (PTR_ERR(phy) == -ENODEV))
+ if (PTR_ERR(phy) == -ENODEV)
phy = NULL;
return phy;
@@ -744,7 +744,7 @@ struct phy *devm_phy_optional_get(struct device *dev, const char *string)
{
struct phy *phy = devm_phy_get(dev, string);
- if (IS_ERR(phy) && (PTR_ERR(phy) == -ENODEV))
+ if (PTR_ERR(phy) == -ENODEV)
phy = NULL;
return phy;
diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c
index c7266ef295fd..1f59beb7d27e 100644
--- a/drivers/spi/spi-orion.c
+++ b/drivers/spi/spi-orion.c
@@ -646,8 +646,7 @@ static int orion_spi_probe(struct platform_device *pdev)
/* The following clock is only used by some SoCs */
spi->axi_clk = devm_clk_get(&pdev->dev, "axi");
- if (IS_ERR(spi->axi_clk) &&
- PTR_ERR(spi->axi_clk) == -EPROBE_DEFER) {
+ if (PTR_ERR(spi->axi_clk) == -EPROBE_DEFER) {
status = -EPROBE_DEFER;
goto out_rel_clk;
}
diff --git a/drivers/video/fbdev/imxfb.c b/drivers/video/fbdev/imxfb.c
index b3286d1fa543..5fad6bf16322 100644
--- a/drivers/video/fbdev/imxfb.c
+++ b/drivers/video/fbdev/imxfb.c
@@ -1017,7 +1017,7 @@ static int imxfb_probe(struct platform_device *pdev)
}
fbi->lcd_pwr = devm_regulator_get(&pdev->dev, "lcd");
- if (IS_ERR(fbi->lcd_pwr) && (PTR_ERR(fbi->lcd_pwr) == -EPROBE_DEFER)) {
+ if (PTR_ERR(fbi->lcd_pwr) == -EPROBE_DEFER) {
ret = -EPROBE_DEFER;
goto failed_lcd;
}
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 2937a8873fe1..b20ac7a47425 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -5987,7 +5987,7 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type,
bh = ext4_bread(handle, inode, blk,
EXT4_GET_BLOCKS_CREATE |
EXT4_GET_BLOCKS_METADATA_NOFAIL);
- } while (IS_ERR(bh) && (PTR_ERR(bh) == -ENOSPC) &&
+ } while (PTR_ERR(bh) == -ENOSPC &&
ext4_should_retry_alloc(inode->i_sb, &retries));
if (IS_ERR(bh))
return PTR_ERR(bh);
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index 3314a0f3405e..9d02cdcdbb07 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -875,7 +875,7 @@ static int truncate_dnode(struct dnode_of_data *dn)
/* get direct node */
page = f2fs_get_node_page(F2FS_I_SB(dn->inode), dn->nid);
- if (IS_ERR(page) && PTR_ERR(page) == -ENOENT)
+ if (PTR_ERR(page) == -ENOENT)
return 1;
else if (IS_ERR(page))
return PTR_ERR(page);
diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c
index 4180c3ef0a68..939df99d2dec 100644
--- a/fs/ocfs2/suballoc.c
+++ b/fs/ocfs2/suballoc.c
@@ -696,7 +696,7 @@ static int ocfs2_block_group_alloc(struct ocfs2_super *osb,
bg_bh = ocfs2_block_group_alloc_contig(osb, handle, alloc_inode,
ac, cl);
- if (IS_ERR(bg_bh) && (PTR_ERR(bg_bh) == -ENOSPC))
+ if (PTR_ERR(bg_bh) == -ENOSPC)
bg_bh = ocfs2_block_group_alloc_discontig(handle,
alloc_inode,
ac, cl);
diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c
index d41c21fef138..c4ab045926b7 100644
--- a/fs/sysfs/group.c
+++ b/fs/sysfs/group.c
@@ -449,7 +449,7 @@ int __compat_only_sysfs_link_entry_to_kobj(struct kobject *kobj,
}
link = kernfs_create_link(kobj->sd, target_name, entry);
- if (IS_ERR(link) && PTR_ERR(link) == -EEXIST)
+ if (PTR_ERR(link) == -EEXIST)
sysfs_warn_dup(kobj->sd, target_name);
kernfs_put(entry);
diff --git a/net/core/dev.c b/net/core/dev.c
index 0ad39c87b7fd..6d849b6f5724 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -5723,7 +5723,7 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff
if (&ptype->list == head)
goto normal;
- if (IS_ERR(pp) && PTR_ERR(pp) == -EINPROGRESS) {
+ if (PTR_ERR(pp) == -EINPROGRESS) {
ret = GRO_CONSUMED;
goto ok;
}
diff --git a/net/core/filter.c b/net/core/filter.c
index 28b3c258188c..687934f3aad7 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -1573,7 +1573,7 @@ int sk_reuseport_attach_bpf(u32 ufd, struct sock *sk)
return -EPERM;
prog = bpf_prog_get_type(ufd, BPF_PROG_TYPE_SOCKET_FILTER);
- if (IS_ERR(prog) && PTR_ERR(prog) == -EINVAL)
+ if (PTR_ERR(prog) == -EINVAL)
prog = bpf_prog_get_type(ufd, BPF_PROG_TYPE_SK_REUSEPORT);
if (IS_ERR(prog))
return PTR_ERR(prog);
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index f2d1e573ea55..93b9e00cca33 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -3186,7 +3186,7 @@ struct dst_entry *xfrm_lookup_route(struct net *net, struct dst_entry *dst_orig,
flags | XFRM_LOOKUP_QUEUE |
XFRM_LOOKUP_KEEP_DST_REF);
- if (IS_ERR(dst) && PTR_ERR(dst) == -EREMOTE)
+ if (PTR_ERR(dst) == -EREMOTE)
return make_blackhole(net, dst_orig->ops->family, dst_orig);
if (IS_ERR(dst))
diff --git a/sound/soc/codecs/ak4104.c b/sound/soc/codecs/ak4104.c
index e8c5fda82e08..979cfb165eed 100644
--- a/sound/soc/codecs/ak4104.c
+++ b/sound/soc/codecs/ak4104.c
@@ -295,8 +295,7 @@ static int ak4104_spi_probe(struct spi_device *spi)
reset_gpiod = devm_gpiod_get_optional(&spi->dev, "reset",
GPIOD_OUT_HIGH);
- if (IS_ERR(reset_gpiod) &&
- PTR_ERR(reset_gpiod) == -EPROBE_DEFER)
+ if (PTR_ERR(reset_gpiod) == -EPROBE_DEFER)
return -EPROBE_DEFER;
/* read the 'reserved' register - according to the datasheet, it
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c
index 793a14d58667..5f25b9f872bd 100644
--- a/sound/soc/codecs/cs4270.c
+++ b/sound/soc/codecs/cs4270.c
@@ -681,8 +681,7 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client,
reset_gpiod = devm_gpiod_get_optional(&i2c_client->dev, "reset",
GPIOD_OUT_HIGH);
- if (IS_ERR(reset_gpiod) &&
- PTR_ERR(reset_gpiod) == -EPROBE_DEFER)
+ if (PTR_ERR(reset_gpiod) == -EPROBE_DEFER)
return -EPROBE_DEFER;
cs4270->regmap = devm_regmap_init_i2c(i2c_client, &cs4270_regmap);
diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c
index b4e9a6c73f90..d087f3b20b1d 100644
--- a/sound/soc/codecs/tlv320aic32x4.c
+++ b/sound/soc/codecs/tlv320aic32x4.c
@@ -1098,11 +1098,9 @@ static int aic32x4_setup_regulators(struct device *dev,
return PTR_ERR(aic32x4->supply_av);
}
} else {
- if (IS_ERR(aic32x4->supply_dv) &&
- PTR_ERR(aic32x4->supply_dv) == -EPROBE_DEFER)
+ if (PTR_ERR(aic32x4->supply_dv) == -EPROBE_DEFER)
return -EPROBE_DEFER;
- if (IS_ERR(aic32x4->supply_av) &&
- PTR_ERR(aic32x4->supply_av) == -EPROBE_DEFER)
+ if (PTR_ERR(aic32x4->supply_av) == -EPROBE_DEFER)
return -EPROBE_DEFER;
}
diff --git a/sound/soc/sunxi/sun4i-spdif.c b/sound/soc/sunxi/sun4i-spdif.c
index cbe598b0fb10..98a9fe645521 100644
--- a/sound/soc/sunxi/sun4i-spdif.c
+++ b/sound/soc/sunxi/sun4i-spdif.c
@@ -555,7 +555,7 @@ static int sun4i_spdif_probe(struct platform_device *pdev)
if (quirks->has_reset) {
host->rst = devm_reset_control_get_optional_exclusive(&pdev->dev,
NULL);
- if (IS_ERR(host->rst) && PTR_ERR(host->rst) == -EPROBE_DEFER) {
+ if (PTR_ERR(host->rst) == -EPROBE_DEFER) {
ret = -EPROBE_DEFER;
dev_err(&pdev->dev, "Failed to get reset: %d\n", ret);
return ret;
--
2.17.1
7
7