diff options
-rw-r--r-- | Documentation/devicetree/bindings/sound/nuvoton,nau8821.yaml | 7 | ||||
-rw-r--r-- | include/sound/l3.h | 28 | ||||
-rw-r--r-- | include/sound/uda134x.h | 24 | ||||
-rw-r--r-- | sound/soc/codecs/Kconfig | 8 | ||||
-rw-r--r-- | sound/soc/codecs/Makefile | 4 | ||||
-rw-r--r-- | sound/soc/codecs/l3.c | 132 | ||||
-rw-r--r-- | sound/soc/codecs/nau8821.c | 42 | ||||
-rw-r--r-- | sound/soc/codecs/nau8821.h | 25 | ||||
-rw-r--r-- | sound/soc/codecs/uda134x.c | 587 | ||||
-rw-r--r-- | sound/soc/codecs/uda134x.h | 33 | ||||
-rw-r--r-- | sound/soc/generic/audio-graph-card2-custom-sample.dtsi | 7 | ||||
-rw-r--r-- | sound/soc/generic/audio-graph-card2.c | 12 | ||||
-rw-r--r-- | sound/soc/sh/rcar/adg.c | 68 | ||||
-rw-r--r-- | sound/soc/sof/amd/acp-ipc.c | 4 | ||||
-rw-r--r-- | sound/soc/sof/amd/acp-loader.c | 3 | ||||
-rw-r--r-- | sound/soc/sof/amd/acp.c | 35 | ||||
-rw-r--r-- | sound/soc/sof/amd/acp.h | 2 |
17 files changed, 171 insertions, 850 deletions
diff --git a/Documentation/devicetree/bindings/sound/nuvoton,nau8821.yaml b/Documentation/devicetree/bindings/sound/nuvoton,nau8821.yaml index fc2f4ce4db88..3e54abd4ca74 100644 --- a/Documentation/devicetree/bindings/sound/nuvoton,nau8821.yaml +++ b/Documentation/devicetree/bindings/sound/nuvoton,nau8821.yaml @@ -89,6 +89,12 @@ properties: $ref: /schemas/types.yaml#/definitions/uint32 default: 3072000 + nuvoton,left-input-single-end: + description: Enable left input with single-ended settings if set. + For the headset mic application, the single-ended control is + just limited to the left adc for design demand. + type: boolean + '#sound-dai-cells': const: 0 @@ -114,6 +120,7 @@ examples: nuvoton,jkdet-pull-enable; nuvoton,jkdet-pull-up; nuvoton,key-enable; + nuvoton,left-input-single-end; nuvoton,jkdet-polarity = <GPIO_ACTIVE_LOW>; nuvoton,micbias-voltage = <6>; nuvoton,vref-impedance = <2>; diff --git a/include/sound/l3.h b/include/sound/l3.h deleted file mode 100644 index b6f58072237a..000000000000 --- a/include/sound/l3.h +++ /dev/null @@ -1,28 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _L3_H_ -#define _L3_H_ 1 - -struct l3_pins { - void (*setdat)(struct l3_pins *, int); - void (*setclk)(struct l3_pins *, int); - void (*setmode)(struct l3_pins *, int); - - int gpio_data; - int gpio_clk; - int gpio_mode; - int use_gpios; - - int data_hold; - int data_setup; - int clock_high; - int mode_hold; - int mode; - int mode_setup; -}; - -struct device; - -int l3_write(struct l3_pins *adap, u8 addr, u8 *data, int len); -int l3_set_gpio_ops(struct device *dev, struct l3_pins *adap); - -#endif diff --git a/include/sound/uda134x.h b/include/sound/uda134x.h deleted file mode 100644 index db82516da162..000000000000 --- a/include/sound/uda134x.h +++ /dev/null @@ -1,24 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * uda134x.h -- UDA134x ALSA SoC Codec driver - * - * Copyright 2007 Dension Audio Systems Ltd. - * Author: Zoltan Devai - */ - -#ifndef _UDA134X_H -#define _UDA134X_H - -#include <sound/l3.h> - -struct uda134x_platform_data { - struct l3_pins l3; - void (*power) (int); - int model; -#define UDA134X_UDA1340 1 -#define UDA134X_UDA1341 2 -#define UDA134X_UDA1344 3 -#define UDA134X_UDA1345 4 -}; - -#endif /* _UDA134X_H */ diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 9ddebd135892..95b5bd883215 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -15,7 +15,6 @@ config SND_SOC_ALL_CODECS tristate "Build all ASoC CODEC drivers" depends on COMPILE_TEST imply SND_SOC_88PM860X - imply SND_SOC_L3 imply SND_SOC_AB8500_CODEC imply SND_SOC_AC97_CODEC imply SND_SOC_AD1836 @@ -270,7 +269,6 @@ config SND_SOC_ALL_CODECS imply SND_SOC_TWL4030 imply SND_SOC_TWL6040 imply SND_SOC_UDA1334 - imply SND_SOC_UDA134X imply SND_SOC_UDA1380 imply SND_SOC_WCD9335 imply SND_SOC_WCD934X @@ -1010,9 +1008,6 @@ config SND_SOC_JZ4770_CODEC This driver can also be built as a module. If so, the module will be called snd-soc-jz4770-codec. -config SND_SOC_L3 - tristate - config SND_SOC_DA7210 tristate depends on SND_SOC_I2C_AND_SPI @@ -1969,9 +1964,6 @@ config SND_SOC_UDA1334 and has basic features such as de-emphasis (at 44.1 kHz sampling rate) and mute. -config SND_SOC_UDA134X - tristate - config SND_SOC_UDA1380 tristate depends on I2C diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 95cbb42253e2..c8502a49b40a 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -131,7 +131,6 @@ snd-soc-jz4740-codec-objs := jz4740.o snd-soc-jz4725b-codec-objs := jz4725b.o snd-soc-jz4760-codec-objs := jz4760.o snd-soc-jz4770-codec-objs := jz4770.o -snd-soc-l3-objs := l3.o snd-soc-lm4857-objs := lm4857.o snd-soc-lm49453-objs := lm49453.o snd-soc-lochnagar-sc-objs := lochnagar-sc.o @@ -303,7 +302,6 @@ snd-soc-ts3a227e-objs := ts3a227e.o snd-soc-twl4030-objs := twl4030.o snd-soc-twl6040-objs := twl6040.o snd-soc-uda1334-objs := uda1334.o -snd-soc-uda134x-objs := uda134x.o snd-soc-uda1380-objs := uda1380.o snd-soc-wcd-mbhc-objs := wcd-mbhc-v2.o snd-soc-wcd9335-objs := wcd-clsh-v2.o wcd9335.o @@ -518,7 +516,6 @@ obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o obj-$(CONFIG_SND_SOC_JZ4725B_CODEC) += snd-soc-jz4725b-codec.o obj-$(CONFIG_SND_SOC_JZ4760_CODEC) += snd-soc-jz4760-codec.o obj-$(CONFIG_SND_SOC_JZ4770_CODEC) += snd-soc-jz4770-codec.o -obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o obj-$(CONFIG_SND_SOC_LM4857) += snd-soc-lm4857.o obj-$(CONFIG_SND_SOC_LM49453) += snd-soc-lm49453.o obj-$(CONFIG_SND_SOC_LOCHNAGAR_SC) += snd-soc-lochnagar-sc.o @@ -687,7 +684,6 @@ obj-$(CONFIG_SND_SOC_TS3A227E) += snd-soc-ts3a227e.o obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o obj-$(CONFIG_SND_SOC_TWL6040) += snd-soc-twl6040.o obj-$(CONFIG_SND_SOC_UDA1334) += snd-soc-uda1334.o -obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o obj-$(CONFIG_SND_SOC_WCD_MBHC) += snd-soc-wcd-mbhc.o obj-$(CONFIG_SND_SOC_WCD9335) += snd-soc-wcd9335.o diff --git a/sound/soc/codecs/l3.c b/sound/soc/codecs/l3.c deleted file mode 100644 index b84f6f1f6800..000000000000 --- a/sound/soc/codecs/l3.c +++ /dev/null @@ -1,132 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * L3 code - * - * Copyright (C) 2008, Christian Pellegrin <chripell@evolware.org> - * - * based on: - * - * L3 bus algorithm module. - * - * Copyright (C) 2001 Russell King, All Rights Reserved. - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/delay.h> -#include <linux/device.h> -#include <linux/gpio.h> - -#include <sound/l3.h> - -/* - * Send one byte of data to the chip. Data is latched into the chip on - * the rising edge of the clock. - */ -static void sendbyte(struct l3_pins *adap, unsigned int byte) -{ - int i; - - for (i = 0; i < 8; i++) { - adap->setclk(adap, 0); - udelay(adap->data_hold); - adap->setdat(adap, byte & 1); - udelay(adap->data_setup); - adap->setclk(adap, 1); - udelay(adap->clock_high); - byte >>= 1; - } -} - -/* - * Send a set of bytes to the chip. We need to pulse the MODE line - * between each byte, but never at the start nor at the end of the - * transfer. - */ -static void sendbytes(struct l3_pins *adap, const u8 *buf, - int len) -{ - int i; - - for (i = 0; i < len; i++) { - if (i) { - udelay(adap->mode_hold); - adap->setmode(adap, 0); - udelay(adap->mode); - } - adap->setmode(adap, 1); - udelay(adap->mode_setup); - sendbyte(adap, buf[i]); - } -} - -int l3_write(struct l3_pins *adap, u8 addr, u8 *data, int len) -{ - adap->setclk(adap, 1); - adap->setdat(adap, 1); - adap->setmode(adap, 1); - udelay(adap->mode); - - adap->setmode(adap, 0); - udelay(adap->mode_setup); - sendbyte(adap, addr); - udelay(adap->mode_hold); - - sendbytes(adap, data, len); - - adap->setclk(adap, 1); - adap->setdat(adap, 1); - adap->setmode(adap, 0); - - return len; -} -EXPORT_SYMBOL_GPL(l3_write); - - -static void l3_set_clk(struct l3_pins *adap, int val) -{ - gpio_set_value(adap->gpio_clk, val); -} - -static void l3_set_data(struct l3_pins *adap, int val) -{ - gpio_set_value(adap->gpio_data, val); -} - -static void l3_set_mode(struct l3_pins *adap, int val) -{ - gpio_set_value(adap->gpio_mode, val); -} - -int l3_set_gpio_ops(struct device *dev, struct l3_pins *adap) -{ - int ret; - - if (!adap->use_gpios) - return -EINVAL; - - ret = devm_gpio_request_one(dev, adap->gpio_data, - GPIOF_OUT_INIT_LOW, "l3_data"); - if (ret < 0) - return ret; - adap->setdat = l3_set_data; - - ret = devm_gpio_request_one(dev, adap->gpio_clk, - GPIOF_OUT_INIT_LOW, "l3_clk"); - if (ret < 0) - return ret; - adap->setclk = l3_set_clk; - - ret = devm_gpio_request_one(dev, adap->gpio_mode, - GPIOF_OUT_INIT_LOW, "l3_mode"); - if (ret < 0) - return ret; - adap->setmode = l3_set_mode; - - return 0; -} -EXPORT_SYMBOL_GPL(l3_set_gpio_ops); - -MODULE_DESCRIPTION("L3 bit-banging driver"); -MODULE_AUTHOR("Christian Pellegrin <chripell@evolware.org>"); -MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/nau8821.c b/sound/soc/codecs/nau8821.c index ca6beb2d2649..f307374834b5 100644 --- a/sound/soc/codecs/nau8821.c +++ b/sound/soc/codecs/nau8821.c @@ -624,6 +624,36 @@ static int system_clock_control(struct snd_soc_dapm_widget *w, return 0; } +static int nau8821_left_fepga_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 nau8821 *nau8821 = snd_soc_component_get_drvdata(component); + + if (!nau8821->left_input_single_end) + return 0; + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + regmap_update_bits(nau8821->regmap, NAU8821_R77_FEPGA, + NAU8821_ACDC_CTRL_MASK | NAU8821_FEPGA_MODEL_MASK, + NAU8821_ACDC_VREF_MICN | NAU8821_FEPGA_MODEL_AAF); + regmap_update_bits(nau8821->regmap, NAU8821_R76_BOOST, + NAU8821_HP_BOOST_DISCHRG_EN, NAU8821_HP_BOOST_DISCHRG_EN); + break; + case SND_SOC_DAPM_POST_PMD: + regmap_update_bits(nau8821->regmap, NAU8821_R77_FEPGA, + NAU8821_ACDC_CTRL_MASK | NAU8821_FEPGA_MODEL_MASK, 0); + regmap_update_bits(nau8821->regmap, NAU8821_R76_BOOST, + NAU8821_HP_BOOST_DISCHRG_EN, 0); + break; + default: + break; + } + + return 0; +} + static const struct snd_soc_dapm_widget nau8821_dapm_widgets[] = { SND_SOC_DAPM_SUPPLY("System Clock", SND_SOC_NOPM, 0, 0, system_clock_control, SND_SOC_DAPM_POST_PMD), @@ -635,8 +665,10 @@ static const struct snd_soc_dapm_widget nau8821_dapm_widgets[] = { NAU8821_POWERUP_ADCL_SFT, 0), SND_SOC_DAPM_ADC("ADCR Power", NULL, NAU8821_R72_ANALOG_ADC_2, NAU8821_POWERUP_ADCR_SFT, 0), + /* single-ended design only on the left */ SND_SOC_DAPM_PGA_S("Frontend PGA L", 1, NAU8821_R7F_POWER_UP_CONTROL, - NAU8821_PUP_PGA_L_SFT, 0, NULL, 0), + NAU8821_PUP_PGA_L_SFT, 0, nau8821_left_fepga_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_PGA_S("Frontend PGA R", 1, NAU8821_R7F_POWER_UP_CONTROL, NAU8821_PUP_PGA_R_SFT, 0, NULL, 0), SND_SOC_DAPM_PGA_S("ADCL Digital path", 0, NAU8821_R01_ENA_CTRL, @@ -1677,6 +1709,8 @@ static int nau8821_read_device_properties(struct device *dev, "nuvoton,jkdet-pull-up"); nau8821->key_enable = device_property_read_bool(dev, "nuvoton,key-enable"); + nau8821->left_input_single_end = device_property_read_bool(dev, + "nuvoton,left-input-single-end"); ret = device_property_read_u32(dev, "nuvoton,jkdet-polarity", &nau8821->jkdet_polarity); if (ret) @@ -1760,6 +1794,12 @@ static void nau8821_init_regs(struct nau8821 *nau8821) NAU8821_ADC_SYNC_DOWN_MASK, NAU8821_ADC_SYNC_DOWN_64); regmap_update_bits(regmap, NAU8821_R2C_DAC_CTRL1, NAU8821_DAC_OVERSAMPLE_MASK, NAU8821_DAC_OVERSAMPLE_64); + if (nau8821->left_input_single_end) { + regmap_update_bits(regmap, NAU8821_R6B_PGA_MUTE, + NAU8821_MUTE_MICNL_EN, NAU8821_MUTE_MICNL_EN); + regmap_update_bits(regmap, NAU8821_R74_MIC_BIAS, + NAU8821_MICBIAS_LOWNOISE_EN, NAU8821_MICBIAS_LOWNOISE_EN); + } } static int nau8821_setup_irq(struct nau8821 *nau8821) diff --git a/sound/soc/codecs/nau8821.h b/sound/soc/codecs/nau8821.h index d962293c218e..00a888ed07ce 100644 --- a/sound/soc/codecs/nau8821.h +++ b/sound/soc/codecs/nau8821.h @@ -433,6 +433,14 @@ #define NAU8821_DAC_CAPACITOR_MSB (0x1 << 1) #define NAU8821_DAC_CAPACITOR_LSB 0x1 +/* MUTE_MIC_L_N (0x6b) */ +#define NAU8821_MUTE_MICNL_SFT 5 +#define NAU8821_MUTE_MICNL_EN (0x1 << NAU8821_MUTE_MICNL_SFT) +#define NAU8821_MUTE_MICNR_SFT 4 +#define NAU8821_MUTE_MICNR_EN (0x1 << NAU8821_MUTE_MICNR_SFT) +#define NAU8821_MUTE_MICRP_SFT 2 +#define NAU8821_MUTE_MICRP_EN (0x1 << NAU8821_MUTE_MICRP_SFT) + /* ANALOG_ADC_1 (0x71) */ #define NAU8821_MICDET_EN_SFT 0 #define NAU8821_MICDET_MASK 0x1 @@ -463,23 +471,39 @@ /* MIC_BIAS (0x74) */ #define NAU8821_MICBIAS_JKR2 (0x1 << 12) +#define NAU8821_MICBIAS_LOWNOISE_SFT 10 +#define NAU8821_MICBIAS_LOWNOISE_EN (0x1 << NAU8821_MICBIAS_LOWNOISE_SFT) #define NAU8821_MICBIAS_POWERUP_SFT 8 +#define NAU8821_MICBIAS_POWERUP_EN (0x1 << NAU8821_MICBIAS_POWERUP_SFT) #define NAU8821_MICBIAS_VOLTAGE_SFT 0 #define NAU8821_MICBIAS_VOLTAGE_MASK 0x7 /* BOOST (0x76) */ #define NAU8821_PRECHARGE_DIS (0x1 << 13) #define NAU8821_GLOBAL_BIAS_EN (0x1 << 12) +#define NAU8821_HP_BOOST_DISCHRG_SFT 11 +#define NAU8821_HP_BOOST_DISCHRG_EN (0x1 << NAU8821_HP_BOOST_DISCHRG_SFT) #define NAU8821_HP_BOOST_DIS_SFT 9 #define NAU8821_HP_BOOST_DIS (0x1 << NAU8821_HP_BOOST_DIS_SFT) #define NAU8821_HP_BOOST_G_DIS (0x1 << 8) #define NAU8821_SHORT_SHUTDOWN_EN (0x1 << 6) /* FEPGA (0x77) */ +#define NAU8821_ACDC_CTRL_SFT 14 +#define NAU8821_ACDC_CTRL_MASK (0x3 << NAU8821_ACDC_CTRL_SFT) +#define NAU8821_ACDC_VREF_MICP (0x1 << NAU8821_ACDC_CTRL_SFT) +#define NAU8821_ACDC_VREF_MICN (0x2 << NAU8821_ACDC_CTRL_SFT) #define NAU8821_FEPGA_MODEL_SFT 4 #define NAU8821_FEPGA_MODEL_MASK (0xf << NAU8821_FEPGA_MODEL_SFT) +#define NAU8821_FEPGA_MODEL_AAF (0x1 << NAU8821_FEPGA_MODEL_SFT) +#define NAU8821_FEPGA_MODEL_DIS (0x2 << NAU8821_FEPGA_MODEL_SFT) +#define NAU8821_FEPGA_MODEL_IMP12K (0x8 << NAU8821_FEPGA_MODEL_SFT) #define NAU8821_FEPGA_MODER_SFT 0 #define NAU8821_FEPGA_MODER_MASK 0xf +#define NAU8821_FEPGA_MODER_AAF 0x1 +#define NAU8821_FEPGA_MODER_DIS 0x2 +#define NAU8821_FEPGA_MODER_IMP12K 0x8 + /* PGA_GAIN (0x7e) */ #define NAU8821_PGA_GAIN_L_SFT 8 @@ -543,6 +567,7 @@ struct nau8821 { bool jkdet_enable; bool jkdet_pull_enable; bool jkdet_pull_up; + bool left_input_single_end; int jkdet_polarity; int jack_insert_debounce; int jack_eject_debounce; diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c deleted file mode 100644 index 1a62bec94005..000000000000 --- a/sound/soc/codecs/uda134x.c +++ /dev/null @@ -1,587 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * uda134x.c -- UDA134X ALSA SoC Codec driver - * - * Modifications by Christian Pellegrin <chripell@evolware.org> - * - * Copyright 2007 Dension Audio Systems Ltd. - * Author: Zoltan Devai - * - * Based on the WM87xx drivers by Liam Girdwood and Richard Purdie - */ - -#include <linux/module.h> -#include <linux/delay.h> -#include <linux/slab.h> -#include <sound/pcm.h> -#include <sound/pcm_params.h> -#include <sound/soc.h> -#include <sound/initval.h> - -#include <sound/uda134x.h> -#include <sound/l3.h> - -#include "uda134x.h" - - -#define UDA134X_RATES SNDRV_PCM_RATE_8000_48000 -#define UDA134X_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | \ - SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S20_3LE) - -struct uda134x_priv { - int sysclk; - int dai_fmt; - - struct snd_pcm_substream *master_substream; - struct snd_pcm_substream *slave_substream; - - struct regmap *regmap; - struct uda134x_platform_data *pd; -}; - -static const struct reg_default uda134x_reg_defaults[] = { - { UDA134X_EA000, 0x04 }, - { UDA134X_EA001, 0x04 }, - { UDA134X_EA010, 0x04 }, - { UDA134X_EA011, 0x00 }, - { UDA134X_EA100, 0x00 }, - { UDA134X_EA101, 0x00 }, - { UDA134X_EA110, 0x00 }, - { UDA134X_EA111, 0x00 }, - { UDA134X_STATUS0, 0x00 }, - { UDA134X_STATUS1, 0x03 }, - { UDA134X_DATA000, 0x00 }, - { UDA134X_DATA001, 0x00 }, - { UDA134X_DATA010, 0x00 }, - { UDA134X_DATA011, 0x00 }, - { UDA134X_DATA1, 0x00 }, -}; - -/* - * Write to the uda134x registers - * - */ -static int uda134x_regmap_write(void *context, unsigned int reg, - unsigned int value) -{ - struct uda134x_platform_data *pd = context; - int ret; - u8 addr; - u8 data = value; - - switch (reg) { - case UDA134X_STATUS0: - case UDA134X_STATUS1: - addr = UDA134X_STATUS_ADDR; - data |= (reg - UDA134X_STATUS0) << 7; - break; - case UDA134X_DATA000: - case UDA134X_DATA001: - case UDA134X_DATA010: - case UDA134X_DATA011: - addr = UDA134X_DATA0_ADDR; - data |= (reg - UDA134X_DATA000) << 6; - break; - case UDA134X_DATA1: - addr = UDA134X_DATA1_ADDR; - break; - default: - /* It's an extended address register */ - addr = (reg | UDA134X_EXTADDR_PREFIX); - - ret = l3_write(&pd->l3, - UDA134X_DATA0_ADDR, &addr, 1); - if (ret != 1) - return -EIO; - - addr = UDA134X_DATA0_ADDR; - data = (value | UDA134X_EXTDATA_PREFIX); - break; - } - - ret = l3_write(&pd->l3, - addr, &data, 1); - if (ret != 1) - return -EIO; - - return 0; -} - -static inline void uda134x_reset(struct snd_soc_component *component) -{ - struct uda134x_priv *uda134x = snd_soc_component_get_drvdata(component); - unsigned int mask = 1<<6; - - regmap_update_bits(uda134x->regmap, UDA134X_STATUS0, mask, mask); - msleep(1); - regmap_update_bits(uda134x->regmap, UDA134X_STATUS0, mask, 0); -} - -static int uda134x_mute(struct snd_soc_dai *dai, int mute, int direction) -{ - struct uda134x_priv *uda134x = snd_soc_component_get_drvdata(dai->component); - unsigned int mask = 1<<2; - unsigned int val; - - pr_debug("%s mute: %d\n", __func__, mute); - - if (mute) - val = mask; - else - val = 0; - - return regmap_update_bits(uda134x->regmap, UDA134X_DATA010, mask, val); -} - -static int uda134x_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_soc_component *component = dai->component; - struct uda134x_priv *uda134x = snd_soc_component_get_drvdata(component); - struct snd_pcm_runtime *master_runtime; - - if (uda134x->master_substream) { - master_runtime = uda134x->master_substream->runtime; - - pr_debug("%s constraining to %d bits at %d\n", __func__, - master_runtime->sample_bits, - master_runtime->rate); - - snd_pcm_hw_constraint_single(substream->runtime, - SNDRV_PCM_HW_PARAM_RATE, - master_runtime->rate); - - snd_pcm_hw_constraint_single(substream->runtime, - SNDRV_PCM_HW_PARAM_SAMPLE_BITS, - master_runtime->sample_bits); - - uda134x->slave_substream = substream; - } else - uda134x->master_substream = substream; - - return 0; -} - -static void uda134x_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_soc_component *component = dai->component; - struct uda134x_priv *uda134x = snd_soc_component_get_drvdata(component); - - if (uda134x->master_substream == substream) - uda134x->master_substream = uda134x->slave_substream; - - uda134x->slave_substream = NULL; -} - -static int uda134x_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_component *component = dai->component; - struct uda134x_priv *uda134x = snd_soc_component_get_drvdata(component); - unsigned int hw_params = 0; - - if (substream == uda134x->slave_substream) { - pr_debug("%s ignoring hw_params for slave substream\n", - __func__); - return 0; - } - - pr_debug("%s sysclk: %d, rate:%d\n", __func__, - uda134x->sysclk, params_rate(params)); - - /* set SYSCLK / fs ratio */ - switch (uda134x->sysclk / params_rate(params)) { - case 512: - break; - case 384: - hw_params |= (1<<4); - break; - case 256: - hw_params |= (1<<5); - break; - default: - printk(KERN_ERR "%s unsupported fs\n", __func__); - return -EINVAL; - } - - pr_debug("%s dai_fmt: %d, params_format:%d\n", __func__, - uda134x->dai_fmt, params_format(params)); - - /* set DAI format and word length */ - switch (uda134x->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - break; - case SND_SOC_DAIFMT_RIGHT_J: - switch (params_width(params)) { - case 16: - hw_params |= (1<<1); - break; - case 18: - hw_params |= (1<<2); - break; - case 20: - hw_params |= ((1<<2) | (1<<1)); - break; - default: - printk(KERN_ERR "%s unsupported format (right)\n", - __func__); - return -EINVAL; - } - break; - case SND_SOC_DAIFMT_LEFT_J: - hw_params |= (1<<3); - break; - default: - printk(KERN_ERR "%s unsupported format\n", __func__); - return -EINVAL; - } - - return regmap_update_bits(uda134x->regmap, UDA134X_STATUS0, - STATUS0_SYSCLK_MASK | STATUS0_DAIFMT_MASK, hw_params); -} - -static int uda134x_set_dai_sysclk(struct snd_soc_dai *codec_dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_component *component = codec_dai->component; - struct uda134x_priv *uda134x = snd_soc_component_get_drvdata(component); - - pr_debug("%s clk_id: %d, freq: %u, dir: %d\n", __func__, - clk_id, freq, dir); - - /* Anything between 256fs*8Khz and 512fs*48Khz should be acceptable - because the codec is slave. Of course limitations of the clock - master (the IIS controller) apply. - We'll error out on set_hw_params if it's not OK */ - if ((freq >= (256 * 8000)) && (freq <= (512 * 48000))) { - uda134x->sysclk = freq; - return 0; - } - - printk(KERN_ERR "%s unsupported sysclk\n", __func__); - return -EINVAL; -} - -static int uda134x_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_component *component = codec_dai->component; - struct uda134x_priv *uda134x = snd_soc_component_get_drvdata(component); - - pr_debug("%s fmt: %08X\n", __func__, fmt); - - /* codec supports only full consumer mode */ - if ((fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) != SND_SOC_DAIFMT_CBC_CFC) { - printk(KERN_ERR "%s unsupported clocking mode\n", __func__); - return -EINVAL; - } - - /* no support for clock inversion */ - if ((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_NB_NF) { - printk(KERN_ERR "%s unsupported clock inversion\n", __func__); - return -EINVAL; - } - - /* We can't setup DAI format here as it depends on the word bit num */ - /* so let's just store the value for later */ - uda134x->dai_fmt = fmt; - - return 0; -} - -static int uda134x_set_bias_level(struct snd_soc_component *component, - enum snd_soc_bias_level level) -{ - struct uda134x_priv *uda134x = snd_soc_component_get_drvdata(component); - struct uda134x_platform_data *pd = uda134x->pd; - pr_debug("%s bias level %d\n", __func__, level); - - switch (level) { - case SND_SOC_BIAS_ON: - break; - case SND_SOC_BIAS_PREPARE: - /* power on */ - if (pd->power) { - pd->power(1); - regcache_sync(uda134x->regmap); - } - break; - case SND_SOC_BIAS_STANDBY: - break; - case SND_SOC_BIAS_OFF: - /* power off */ - if (pd->power) { - pd->power(0); - regcache_mark_dirty(uda134x->regmap); - } - break; - } - return 0; -} - -static const char *uda134x_dsp_setting[] = {"Flat", "Minimum1", - "Minimum2", "Maximum"}; -static const char *uda134x_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"}; -static const char *uda134x_mixmode[] = {"Differential", "Analog1", - "Analog2", "Both"}; - -static const struct soc_enum uda134x_mixer_enum[] = { -SOC_ENUM_SINGLE(UDA134X_DATA010, 0, 0x04, uda134x_dsp_setting), -SOC_ENUM_SINGLE(UDA134X_DATA010, 3, 0x04, uda134x_deemph), -SOC_ENUM_SINGLE(UDA134X_EA010, 0, 0x04, uda134x_mixmode), -}; - -static const struct snd_kcontrol_new uda1341_snd_controls[] = { -SOC_SINGLE("Master Playback Volume", UDA134X_DATA000, 0, 0x3F, 1), -SOC_SINGLE("Capture Volume", UDA134X_EA010, 2, 0x07, 0), -SOC_SINGLE("Analog1 Volume", UDA134X_EA000, 0, 0x1F, 1), -SOC_SINGLE("Analog2 Volume", UDA134X_EA001, 0, 0x1F, 1), - -SOC_SINGLE("Mic Sensitivity", UDA134X_EA010, 2, 7, 0), -SOC_SINGLE("Mic Volume", UDA134X_EA101, 0, 0x1F, 0), - -SOC_SINGLE("Tone Control - Bass", UDA134X_DATA001, 2, 0xF, 0), -SOC_SINGLE("Tone Control - Treble", UDA134X_DATA001, 0, 3, 0), - -SOC_ENUM("Sound Processing Filter", uda134x_mixer_enum[0]), -SOC_ENUM("PCM Playback De-emphasis", uda134x_mixer_enum[1]), -SOC_ENUM("Input Mux", uda134x_mixer_enum[2]), - -SOC_SINGLE("AGC Switch", UDA134X_EA100, 4, 1, 0), -SOC_SINGLE("AGC Target Volume", UDA134X_EA110, 0, 0x03, 1), -SOC_SINGLE("AGC Timing", UDA134X_EA110, 2, 0x07, 0), - -SOC_SINGLE("DAC +6dB Switch", UDA134X_STATUS1, 6, 1, 0), -SOC_SINGLE("ADC +6dB Switch", UDA134X_STATUS1, 5, 1, 0), -SOC_SINGLE("ADC Polarity Switch", UDA134X_STATUS1, 4, 1, 0), -SOC_SINGLE("DAC Polarity Switch", UDA134X_STATUS1, 3, 1, 0), -SOC_SINGLE("Double Speed Playback Switch", UDA134X_STATUS1, 2, 1, 0), -SOC_SINGLE("DC Filter Enable Switch", UDA134X_STATUS0, 0, 1, 0), -}; - -static const struct snd_kcontrol_new uda1340_snd_controls[] = { -SOC_SINGLE("Master Playback Volume", UDA134X_DATA000, 0, 0x3F, 1), - -SOC_SINGLE("Tone Control - Bass", UDA134X_DATA001, 2, 0xF, 0), -SOC_SINGLE("Tone Control - Treble", UDA134X_DATA001, 0, 3, 0), - -SOC_ENUM("Sound Processing Filter", uda134x_mixer_enum[0]), -SOC_ENUM("PCM Playback De-emphasis", uda134x_mixer_enum[1]), - -SOC_SINGLE("DC Filter Enable Switch", UDA134X_STATUS0, 0, 1, 0), -}; - -static const struct snd_kcontrol_new uda1345_snd_controls[] = { -SOC_SINGLE("Master Playback Volume", UDA134X_DATA000, 0, 0x3F, 1), - -SOC_ENUM("PCM Playback De-emphasis", uda134x_mixer_enum[1]), - -SOC_SINGLE("DC Filter Enable Switch", UDA134X_STATUS0, 0, 1, 0), -}; - -/* UDA1341 has the DAC/ADC power down in STATUS1 */ -static const struct snd_soc_dapm_widget uda1341_dapm_widgets[] = { - SND_SOC_DAPM_DAC("DAC", "Playback", UDA134X_STATUS1, 0, 0), - SND_SOC_DAPM_ADC("ADC", "Capture", UDA134X_STATUS1, 1, 0), -}; - -/* UDA1340/4/5 has the DAC/ADC pwoer down in DATA0 11 */ -static const struct snd_soc_dapm_widget uda1340_dapm_widgets[] = { - SND_SOC_DAPM_DAC("DAC", "Playback", UDA134X_DATA011, 0, 0), - SND_SOC_DAPM_ADC("ADC", "Capture", UDA134X_DATA011, 1, 0), -}; - -/* Common DAPM widgets */ -static const struct snd_soc_dapm_widget uda134x_dapm_widgets[] = { - SND_SOC_DAPM_INPUT("VINL1"), - SND_SOC_DAPM_INPUT("VINR1"), - SND_SOC_DAPM_INPUT("VINL2"), - SND_SOC_DAPM_INPUT("VINR2"), - SND_SOC_DAPM_OUTPUT("VOUTL"), - SND_SOC_DAPM_OUTPUT("VOUTR"), -}; - -static const struct snd_soc_dapm_route uda134x_dapm_routes[] = { - { "ADC", NULL, "VINL1" }, - { "ADC", NULL, "VINR1" }, - { "ADC", NULL, "VINL2" }, - { "ADC", NULL, "VINR2" }, - { "VOUTL", NULL, "DAC" }, - { "VOUTR", NULL, "DAC" }, -}; - -static const struct snd_soc_dai_ops uda134x_dai_ops = { - .startup = uda134x_startup, - .shutdown = uda134x_shutdown, - .hw_params = uda134x_hw_params, - .mute_stream = uda134x_mute, - .set_sysclk = uda134x_set_dai_sysclk, - .set_fmt = uda134x_set_dai_fmt, - .no_capture_mute = 1, -}; - -static struct snd_soc_dai_driver uda134x_dai = { - .name = "uda134x-hifi", - /* playback capabilities */ - .playback = { - .stream_name = "Playback", - .channels_min = 1, - .channels_max = 2, - .rates = UDA134X_RATES, - .formats = UDA134X_FORMATS, - }, - /* capture capabilities */ - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 2, - .rates = UDA134X_RATES, - .formats = UDA134X_FORMATS, - }, - /* pcm operations */ - .ops = &uda134x_dai_ops, -}; - -static int uda134x_soc_probe(struct snd_soc_component *component) -{ - struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); - struct uda134x_priv *uda134x = snd_soc_component_get_drvdata(component); - struct uda134x_platform_data *pd = uda134x->pd; - const struct snd_soc_dapm_widget *widgets; - unsigned int num_widgets; - int ret; - - printk(KERN_INFO "UDA134X SoC Audio Codec\n"); - - switch (pd->model) { - case UDA134X_UDA1340: - case UDA134X_UDA1341: - case UDA134X_UDA1344: - case UDA134X_UDA1345: - break; - default: - printk(KERN_ERR "UDA134X SoC codec: " - "unsupported model %d\n", - pd->model); - return -EINVAL; - } - - if (pd->power) - pd->power(1); - - uda134x_reset(component); - - if (pd->model == UDA134X_UDA1341) { - widgets = uda1341_dapm_widgets; - num_widgets = ARRAY_SIZE(uda1341_dapm_widgets); - } else { - widgets = uda1340_dapm_widgets; - num_widgets = ARRAY_SIZE(uda1340_dapm_widgets); - } - - ret = snd_soc_dapm_new_controls(dapm, widgets, num_widgets); - if (ret) { - printk(KERN_ERR "%s failed to register dapm controls: %d", - __func__, ret); - return ret; - } - - switch (pd->model) { - case UDA134X_UDA1340: - case UDA134X_UDA1344: - ret = snd_soc_add_component_controls(component, uda1340_snd_controls, - ARRAY_SIZE(uda1340_snd_controls)); - break; - case UDA134X_UDA1341: - ret = snd_soc_add_component_controls(component, uda1341_snd_controls, - ARRAY_SIZE(uda1341_snd_controls)); - break; - case UDA134X_UDA1345: - ret = snd_soc_add_component_controls(component, uda1345_snd_controls, - ARRAY_SIZE(uda1345_snd_controls)); - break; - default: - printk(KERN_ERR "%s unknown codec type: %d", - __func__, pd->model); - return -EINVAL; - } - - if (ret < 0) { - printk(KERN_ERR "UDA134X: failed to register controls\n"); - return ret; - } - - return 0; -} - -static const struct snd_soc_component_driver soc_component_dev_uda134x = { - .probe = uda134x_soc_probe, - .set_bias_level = uda134x_set_bias_level, - .dapm_widgets = uda134x_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(uda134x_dapm_widgets), - .dapm_routes = uda134x_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(uda134x_dapm_routes), - .suspend_bias_off = 1, - .idle_bias_on = 1, - .use_pmdown_time = 1, - .endianness = 1, -}; - -static const struct regmap_config uda134x_regmap_config = { - .reg_bits = 8, - .val_bits = 8, - .max_register = UDA134X_DATA1, - .reg_defaults = uda134x_reg_defaults, - .num_reg_defaults = ARRAY_SIZE(uda134x_reg_defaults), - .cache_type = REGCACHE_RBTREE, - - .reg_write = uda134x_regmap_write, -}; - -static int uda134x_codec_probe(struct platform_device *pdev) -{ - struct uda134x_platform_data *pd = pdev->dev.platform_data; - struct uda134x_priv *uda134x; - int ret; - - if (!pd) { - dev_err(&pdev->dev, "Missing L3 bitbang function\n"); - return -ENODEV; - } - - uda134x = devm_kzalloc(&pdev->dev, sizeof(*uda134x), GFP_KERNEL); - if (!uda134x) - return -ENOMEM; - - uda134x->pd = pd; - platform_set_drvdata(pdev, uda134x); - - if (pd->l3.use_gpios) { - ret = l3_set_gpio_ops(&pdev->dev, &uda134x->pd->l3); - if (ret < 0) - return ret; - } - - uda134x->regmap = devm_regmap_init(&pdev->dev, NULL, pd, - &uda134x_regmap_config); - if (IS_ERR(uda134x->regmap)) - return PTR_ERR(uda134x->regmap); - - return devm_snd_soc_register_component(&pdev->dev, - &soc_component_dev_uda134x, &uda134x_dai, 1); -} - -static struct platform_driver uda134x_codec_driver = { - .driver = { - .name = "uda134x-codec", - }, - .probe = uda134x_codec_probe, -}; - -module_platform_driver(uda134x_codec_driver); - -MODULE_DESCRIPTION("UDA134X ALSA soc codec driver"); -MODULE_AUTHOR("Zoltan Devai, Christian Pellegrin <chripell@evolware.org>"); -MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/uda134x.h b/sound/soc/codecs/uda134x.h deleted file mode 100644 index 664618c2571c..000000000000 --- a/sound/soc/codecs/uda134x.h +++ /dev/null @@ -1,33 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _UDA134X_CODEC_H -#define _UDA134X_CODEC_H - -#define UDA134X_L3ADDR 5 -#define UDA134X_DATA0_ADDR ((UDA134X_L3ADDR << 2) | 0) -#define UDA134X_DATA1_ADDR ((UDA134X_L3ADDR << 2) | 1) -#define UDA134X_STATUS_ADDR ((UDA134X_L3ADDR << 2) | 2) - -#define UDA134X_EXTADDR_PREFIX 0xC0 -#define UDA134X_EXTDATA_PREFIX 0xE0 - -/* UDA134X registers */ -#define UDA134X_EA000 0 -#define UDA134X_EA001 1 -#define UDA134X_EA010 2 -#define UDA134X_EA011 3 -#define UDA134X_EA100 4 -#define UDA134X_EA101 5 -#define UDA134X_EA110 6 -#define UDA134X_EA111 7 -#define UDA134X_STATUS0 8 -#define UDA134X_STATUS1 9 -#define UDA134X_DATA000 10 -#define UDA134X_DATA001 11 -#define UDA134X_DATA010 12 -#define UDA134X_DATA011 13 -#define UDA134X_DATA1 14 - -#define STATUS0_DAIFMT_MASK (~(7<<1)) -#define STATUS0_SYSCLK_MASK (~(3<<4)) - -#endif diff --git a/sound/soc/generic/audio-graph-card2-custom-sample.dtsi b/sound/soc/generic/audio-graph-card2-custom-sample.dtsi index 2ac0de3c21da..8acaa2ddb335 100644 --- a/sound/soc/generic/audio-graph-card2-custom-sample.dtsi +++ b/sound/soc/generic/audio-graph-card2-custom-sample.dtsi @@ -34,6 +34,13 @@ * ... * }; * + * + * Below sample doesn't use "format" property, + * because test-component driver (test-cpu/test-codec) is supporting + * snd_soc_dai_ops :: .auto_selectable_formats. + * see + * snd_soc_runtime_get_dai_fmt() + * linux/sound/soc/generic/test-component.c :: test_dai_formats */ / { /* diff --git a/sound/soc/generic/audio-graph-card2.c b/sound/soc/generic/audio-graph-card2.c index 98732468a992..b1c675c6b6db 100644 --- a/sound/soc/generic/audio-graph-card2.c +++ b/sound/soc/generic/audio-graph-card2.c @@ -47,6 +47,18 @@ see graph_parse_daifmt(). + "format" property is no longer needed on DT if both CPU/Codec drivers are + supporting snd_soc_dai_ops :: .auto_selectable_formats. + see + snd_soc_runtime_get_dai_fmt() + + sample driver + linux/sound/soc/sh/rcar/core.c + linux/sound/soc/codecs/ak4613.c + linux/sound/soc/codecs/pcm3168a.c + linux/sound/soc/soc-utils.c + linux/sound/soc/generic/test-component.c + ************************************ Normal Audio-Graph ************************************ diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index 0b8926600d90..230c48648af3 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -358,8 +358,6 @@ int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *ssi_mod, unsigned int rate) ckr = 0x80000000; /* BRGB output = 48kHz */ rsnd_mod_bset(adg_mod, BRGCKR, 0x80770000, adg->ckr | ckr); - rsnd_mod_write(adg_mod, BRRA, adg->brga); - rsnd_mod_write(adg_mod, BRRB, adg->brgb); dev_dbg(dev, "CLKOUT is based on BRG%c (= %dHz)\n", (ckr) ? 'B' : 'A', @@ -372,9 +370,16 @@ int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *ssi_mod, unsigned int rate) void rsnd_adg_clk_control(struct rsnd_priv *priv, int enable) { struct rsnd_adg *adg = rsnd_priv_to_adg(priv); + struct rsnd_mod *adg_mod = rsnd_mod_get(adg); struct clk *clk; int i; + if (enable) { + rsnd_mod_bset(adg_mod, BRGCKR, 0x80770000, adg->ckr); + rsnd_mod_write(adg_mod, BRRA, adg->brga); + rsnd_mod_write(adg_mod, BRRB, adg->brgb); + } + for_each_rsnd_clkin(clk, adg, i) { if (enable) { clk_prepare_enable(clk); @@ -485,12 +490,12 @@ static int rsnd_adg_get_clkout(struct rsnd_priv *priv) struct device_node *np = dev->of_node; struct property *prop; u32 ckr, brgx, brga, brgb; - u32 rate, div; u32 req_rate[ADG_HZ_SIZE] = {}; uint32_t count = 0; unsigned long req_Hz[ADG_HZ_SIZE]; int clkout_size; int i, req_size; + int approximate = 0; const char *parent_clk_name = NULL; const char * const *clkout_name; int brg_table[] = { @@ -501,8 +506,8 @@ static int rsnd_adg_get_clkout(struct rsnd_priv *priv) }; ckr = 0; - brga = 2; /* default 1/6 */ - brgb = 2; /* default 1/6 */ + brga = 0xff; /* default */ + brgb = 0xff; /* default */ /* * ADG supports BRRA/BRRB output only @@ -537,17 +542,41 @@ static int rsnd_adg_get_clkout(struct rsnd_priv *priv) * rsnd_adg_ssi_clk_try_start() * rsnd_ssi_master_clk_start() */ + + /* + * [APPROXIMATE] + * + * clk_i (internal clock) can't create accurate rate, it will be approximate rate. + * + * <Note> + * + * clk_i needs x2 of required maximum rate. + * see + * - Minimum division of BRRA/BRRB + * - rsnd_ssi_clk_query() + * + * Sample Settings for TDM 8ch, 32bit width + * + * 8(ch) x 32(bit) x 44100(Hz) x 2<Note> = 22579200 + * 8(ch) x 32(bit) x 48000(Hz) x 2<Note> = 24576000 + * + * clock-frequency = <22579200 24576000>; + */ for_each_rsnd_clkin(clk, adg, i) { + u32 rate, div; + rate = clk_get_rate(clk); if (0 == rate) /* not used */ continue; /* BRGA */ - if (!adg->brg_rate[ADG_HZ_441] && (0 == rate % 44100)) { - div = 6; - if (req_Hz[ADG_HZ_441]) - div = rate / req_Hz[ADG_HZ_441]; + + if (i == CLKI) + /* see [APPROXIMATE] */ + rate = (clk_get_rate(clk) / req_Hz[ADG_HZ_441]) * req_Hz[ADG_HZ_441]; + if (!adg->brg_rate[ADG_HZ_441] && req_Hz[ADG_HZ_441] && (0 == rate % 44100)) { + div = rate / req_Hz[ADG_HZ_441]; brgx = rsnd_adg_calculate_brgx(div); if (BRRx_MASK(brgx) == brgx) { brga = brgx; @@ -555,14 +584,18 @@ static int rsnd_adg_get_clkout(struct rsnd_priv *priv) ckr |= brg_table[i] << 20; if (req_Hz[ADG_HZ_441]) parent_clk_name = __clk_get_name(clk); + if (i == CLKI) + approximate = 1; } } /* BRGB */ - if (!adg->brg_rate[ADG_HZ_48] && (0 == rate % 48000)) { - div = 6; - if (req_Hz[ADG_HZ_48]) - div = rate / req_Hz[ADG_HZ_48]; + + if (i == CLKI) + /* see [APPROXIMATE] */ + rate = (clk_get_rate(clk) / req_Hz[ADG_HZ_48]) * req_Hz[ADG_HZ_48]; + if (!adg->brg_rate[ADG_HZ_48] && req_Hz[ADG_HZ_48] && (0 == rate % 48000)) { + div = rate / req_Hz[ADG_HZ_48]; brgx = rsnd_adg_calculate_brgx(div); if (BRRx_MASK(brgx) == brgx) { brgb = brgx; @@ -570,10 +603,19 @@ static int rsnd_adg_get_clkout(struct rsnd_priv *priv) ckr |= brg_table[i] << 16; if (req_Hz[ADG_HZ_48]) parent_clk_name = __clk_get_name(clk); + if (i == CLKI) + approximate = 1; } } } + if (!(adg->brg_rate[ADG_HZ_48] && req_Hz[ADG_HZ_48]) && + !(adg->brg_rate[ADG_HZ_441] && req_Hz[ADG_HZ_441])) + goto rsnd_adg_get_clkout_end; + + if (approximate) + dev_info(dev, "It uses CLK_I as approximate rate"); + clkout_name = clkout_name_gen2; clkout_size = ARRAY_SIZE(clkout_name_gen2); if (rsnd_is_gen4(priv)) diff --git a/sound/soc/sof/amd/acp-ipc.c b/sound/soc/sof/amd/acp-ipc.c index 81a2c096a185..fcb54f545fea 100644 --- a/sound/soc/sof/amd/acp-ipc.c +++ b/sound/soc/sof/amd/acp-ipc.c @@ -170,6 +170,8 @@ irqreturn_t acp_sof_ipc_irq_thread(int irq, void *context) if ((status & SOF_IPC_PANIC_MAGIC_MASK) == SOF_IPC_PANIC_MAGIC) { snd_sof_dsp_panic(sdev, sdev->dsp_box.offset + sizeof(status), true); + status = 0; + acp_mailbox_write(sdev, sdev->dsp_box.offset, &status, sizeof(status)); return IRQ_HANDLED; } snd_sof_ipc_msgs_rx(sdev); @@ -199,6 +201,8 @@ irqreturn_t acp_sof_ipc_irq_thread(int irq, void *context) acp_mailbox_read(sdev, sdev->debug_box.offset, &status, sizeof(u32)); if ((status & SOF_IPC_PANIC_MAGIC_MASK) == SOF_IPC_PANIC_MAGIC) { snd_sof_dsp_panic(sdev, sdev->dsp_oops_offset, true); + status = 0; + acp_mailbox_write(sdev, sdev->debug_box.offset, &status, sizeof(status)); return IRQ_HANDLED; } diff --git a/sound/soc/sof/amd/acp-loader.c b/sound/soc/sof/amd/acp-loader.c index a63c00b53a5e..a427673cfb03 100644 --- a/sound/soc/sof/amd/acp-loader.c +++ b/sound/soc/sof/amd/acp-loader.c @@ -207,6 +207,7 @@ EXPORT_SYMBOL_NS(acp_dsp_pre_fw_run, SND_SOC_SOF_AMD_COMMON); int acp_sof_dsp_run(struct snd_sof_dev *sdev) { + struct acp_dev_data *adata = sdev->pdata->hw_pdata; const struct sof_amd_acp_desc *desc = get_chip_info(sdev->pdata); int val; @@ -215,7 +216,7 @@ int acp_sof_dsp_run(struct snd_sof_dev *sdev) dev_dbg(sdev->dev, "ACP_DSP0_RUNSTALL : 0x%0x\n", val); /* Some platforms won't support fusion DSP,keep offset zero for no support */ - if (desc->fusion_dsp_offset) { + if (desc->fusion_dsp_offset && adata->enable_fw_debug) { snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->fusion_dsp_offset, ACP_DSP_RUN); val = snd_sof_dsp_read(sdev, ACP_DSP_BAR, desc->fusion_dsp_offset); dev_dbg(sdev->dev, "ACP_DSP0_FUSION_RUNSTALL : 0x%0x\n", val); diff --git a/sound/soc/sof/amd/acp.c b/sound/soc/sof/amd/acp.c index b2e00a10a03e..19a801908b56 100644 --- a/sound/soc/sof/amd/acp.c +++ b/sound/soc/sof/amd/acp.c @@ -22,6 +22,10 @@ #define SECURED_FIRMWARE 1 +static bool enable_fw_debug; +module_param(enable_fw_debug, bool, 0444); +MODULE_PARM_DESC(enable_fw_debug, "Enable Firmware debug"); + const struct dmi_system_id acp_sof_quirk_table[] = { { /* Valve Jupiter device */ @@ -337,14 +341,7 @@ static irqreturn_t acp_irq_thread(int irq, void *context) { struct snd_sof_dev *sdev = context; const struct sof_amd_acp_desc *desc = get_chip_info(sdev->pdata); - unsigned int val, count = ACP_HW_SEM_RETRY_COUNT; - - val = snd_sof_dsp_read(sdev, ACP_DSP_BAR, desc->ext_intr_stat); - if (val & ACP_SHA_STAT) { - /* Clear SHA interrupt raised by PSP */ - snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->ext_intr_stat, val); - return IRQ_HANDLED; - } + unsigned int count = ACP_HW_SEM_RETRY_COUNT; while (snd_sof_dsp_read(sdev, ACP_DSP_BAR, desc->hw_semaphore_offset)) { /* Wait until acquired HW Semaphore lock or timeout */ @@ -370,9 +367,9 @@ static irqreturn_t acp_irq_handler(int irq, void *dev_id) unsigned int val; val = snd_sof_dsp_read(sdev, ACP_DSP_BAR, base + DSP_SW_INTR_STAT_OFFSET); - if (val) { - val |= ACP_DSP_TO_HOST_IRQ; - snd_sof_dsp_write(sdev, ACP_DSP_BAR, base + DSP_SW_INTR_STAT_OFFSET, val); + if (val & ACP_DSP_TO_HOST_IRQ) { + snd_sof_dsp_write(sdev, ACP_DSP_BAR, base + DSP_SW_INTR_STAT_OFFSET, + ACP_DSP_TO_HOST_IRQ); return IRQ_WAKE_THREAD; } @@ -426,7 +423,12 @@ static int acp_reset(struct snd_sof_dev *sdev) if (ret < 0) dev_err(sdev->dev, "timeout in releasing reset\n"); - snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->acp_clkmux_sel, ACP_CLOCK_ACLK); + if (desc->acp_clkmux_sel) + snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->acp_clkmux_sel, ACP_CLOCK_ACLK); + + if (desc->ext_intr_enb) + snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->ext_intr_enb, 0x01); + return ret; } @@ -464,7 +466,6 @@ EXPORT_SYMBOL_NS(amd_sof_acp_suspend, SND_SOC_SOF_AMD_COMMON); int amd_sof_acp_resume(struct snd_sof_dev *sdev) { - const struct sof_amd_acp_desc *desc = get_chip_info(sdev->pdata); int ret; ret = acp_init(sdev); @@ -472,12 +473,7 @@ int amd_sof_acp_resume(struct snd_sof_dev *sdev) dev_err(sdev->dev, "ACP Init failed\n"); return ret; } - - snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->acp_clkmux_sel, ACP_CLOCK_ACLK); - - ret = acp_memory_init(sdev); - - return ret; + return acp_memory_init(sdev); } EXPORT_SYMBOL_NS(amd_sof_acp_resume, SND_SOC_SOF_AMD_COMMON); @@ -562,6 +558,7 @@ int amd_sof_acp_probe(struct snd_sof_dev *sdev) dev_dbg(sdev->dev, "fw_code_bin:%s, fw_data_bin:%s\n", adata->fw_code_bin, adata->fw_data_bin); } + adata->enable_fw_debug = enable_fw_debug; acp_memory_init(sdev); acp_dsp_stream_init(sdev); diff --git a/sound/soc/sof/amd/acp.h b/sound/soc/sof/amd/acp.h index 19cad4fcf99a..4dcceb764769 100644 --- a/sound/soc/sof/amd/acp.h +++ b/sound/soc/sof/amd/acp.h @@ -174,6 +174,7 @@ struct sof_amd_acp_desc { const char *name; unsigned int host_bridge_id; u32 pgfsm_base; + u32 ext_intr_enb; u32 ext_intr_stat; u32 dsp_intr_base; u32 sram_pte_offset; @@ -204,6 +205,7 @@ struct acp_dev_data { struct acp_dsp_stream *dtrace_stream; struct pci_dev *smn_dev; struct acp_dsp_stream *probe_stream; + bool enable_fw_debug; }; void memcpy_to_scratch(struct snd_sof_dev *sdev, u32 offset, unsigned int *src, size_t bytes); |