diff options
27 files changed, 1647 insertions, 649 deletions
diff --git a/Documentation/devicetree/bindings/sound/max98357a.txt b/Documentation/devicetree/bindings/sound/max98357a.txt index 4bce14ce806f..75db84d06240 100644 --- a/Documentation/devicetree/bindings/sound/max98357a.txt +++ b/Documentation/devicetree/bindings/sound/max98357a.txt @@ -1,9 +1,10 @@ -Maxim MAX98357A audio DAC +Maxim MAX98357A/MAX98360A audio DAC -This node models the Maxim MAX98357A DAC. +This node models the Maxim MAX98357A/MAX98360A DAC. Required properties: -- compatible : "maxim,max98357a" +- compatible : "maxim,max98357a" for MAX98357A. + "maxim,max98360a" for MAX98360A. Optional properties: - sdmode-gpios : GPIO specifier for the chip's SD_MODE pin. @@ -20,3 +21,8 @@ max98357a { compatible = "maxim,max98357a"; sdmode-gpios = <&qcom_pinmux 25 0>; }; + +max98360a { + compatible = "maxim,max98360a"; + sdmode-gpios = <&qcom_pinmux 25 0>; +}; diff --git a/Documentation/devicetree/bindings/sound/maxim,max98390.yaml b/Documentation/devicetree/bindings/sound/maxim,max98390.yaml new file mode 100644 index 000000000000..e5ac35280da3 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/maxim,max98390.yaml @@ -0,0 +1,51 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/maxim,max98390.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Maxim Integrated MAX98390 Speaker Amplifier with Integrated Dynamic Speaker Management + +maintainers: + - Steve Lee <steves.lee@maximintegrated.com> + +properties: + compatible: + const: maxim,max98390 + + reg: + maxItems: 1 + description: I2C address of the device. + + maxim,temperature_calib: + allOf: + - $ref: /schemas/types.yaml#/definitions/uint32 + description: The calculated temperature data was measured while doing the calibration. + minimum: 0 + maximum: 65535 + + maxim,r0_calib: + allOf: + - $ref: /schemas/types.yaml#/definitions/uint32 + description: This is r0 calibration data which was measured in factory mode. + minimum: 1 + maximum: 8388607 + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + max98390: amplifier@38 { + compatible = "maxim,max98390"; + reg = <0x38>; + maxim,temperature_calib = <1024>; + maxim,r0_calib = <100232>; + }; + }; diff --git a/Documentation/devicetree/bindings/sound/mt6358.txt b/Documentation/devicetree/bindings/sound/mt6358.txt index 5465730013a1..59a73ffdf1d3 100644 --- a/Documentation/devicetree/bindings/sound/mt6358.txt +++ b/Documentation/devicetree/bindings/sound/mt6358.txt @@ -10,9 +10,15 @@ Required properties: - compatible : "mediatek,mt6358-sound". - Avdd-supply : power source of AVDD +Optional properties: +- mediatek,dmic-mode : Indicates how many data pins are used to transmit two + channels of PDM signal. 0 means two wires, 1 means one wire. Default + value is 0. + Example: mt6358_snd { compatible = "mediatek,mt6358-sound"; Avdd-supply = <&mt6358_vaud28_reg>; + mediatek,dmic-mode = <0>; }; diff --git a/Documentation/devicetree/bindings/sound/samsung,aries-wm8994.yaml b/Documentation/devicetree/bindings/sound/samsung,aries-wm8994.yaml new file mode 100644 index 000000000000..902a0b66628e --- /dev/null +++ b/Documentation/devicetree/bindings/sound/samsung,aries-wm8994.yaml @@ -0,0 +1,147 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/samsung,aries-wm8994.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Samsung Aries audio complex with WM8994 codec + +maintainers: + - Jonathan Bakker <xc-racer2@live.ca> + +properties: + compatible: + oneOf: + - const: samsung,aries-wm8994 + description: With FM radio and modem master + + - const: samsung,fascinate4g-wm8994 + description: Without FM radio and modem slave + + model: + $ref: /schemas/types.yaml#/definitions/string + description: The user-visible name of this sound complex. + + cpu: + type: object + properties: + sound-dai: + minItems: 2 + maxItems: 2 + $ref: /schemas/types.yaml#/definitions/phandle-array + description: | + phandles to the I2S controller and bluetooth codec, + in that order + + codec: + type: object + properties: + sound-dai: + $ref: /schemas/types.yaml#/definitions/phandle-array + description: phandle to the WM8994 CODEC + + samsung,audio-routing: + $ref: /schemas/types.yaml#/definitions/non-unique-string-array + description: | + 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; + valid names for sources and sinks are the WM8994's pins (as + documented in its binding), and the jacks on the board - + For samsung,aries-wm8994: HP, SPK, RCV, LINE, Main Mic, Headset Mic, + or FM In + For samsung,fascinate4g-wm8994: HP, SPK, RCV, LINE, Main Mic, + or HeadsetMic + + extcon: + description: Extcon phandle for dock detection + + main-micbias-supply: + description: Supply for the micbias on the main mic + + headset-micbias-supply: + description: Supply for the micbias on the headset mic + + earpath-sel-gpios: + description: GPIO for switching between tv-out and mic paths + + headset-detect-gpios: + description: GPIO for detection of headset insertion + + headset-key-gpios: + description: GPIO for detection of headset key press + + io-channels: + maxItems: 1 + description: IO channel to read micbias voltage for headset detection + + io-channel-names: + const: headset-detect + +required: + - compatible + - model + - cpu + - codec + - samsung,audio-routing + - extcon + - main-micbias-supply + - headset-micbias-supply + - earpath-sel-gpios + - headset-detect-gpios + - headset-key-gpios + +additionalProperties: false + +examples: + - | + #include <dt-bindings/gpio/gpio.h> + + sound { + compatible = "samsung,fascinate4g-wm8994"; + + model = "Fascinate4G"; + + extcon = <&fsa9480>; + + main-micbias-supply = <&main_micbias_reg>; + headset-micbias-supply = <&headset_micbias_reg>; + + earpath-sel-gpios = <&gpj2 6 GPIO_ACTIVE_HIGH>; + + io-channels = <&adc 3>; + io-channel-names = "headset-detect"; + headset-detect-gpios = <&gph0 6 GPIO_ACTIVE_HIGH>; + headset-key-gpios = <&gph3 6 GPIO_ACTIVE_HIGH>; + + samsung,audio-routing = + "HP", "HPOUT1L", + "HP", "HPOUT1R", + + "SPK", "SPKOUTLN", + "SPK", "SPKOUTLP", + + "RCV", "HPOUT2N", + "RCV", "HPOUT2P", + + "LINE", "LINEOUT2N", + "LINE", "LINEOUT2P", + + "IN1LP", "Main Mic", + "IN1LN", "Main Mic", + + "IN1RP", "Headset Mic", + "IN1RN", "Headset Mic"; + + pinctrl-names = "default"; + pinctrl-0 = <&headset_det &earpath_sel>; + + cpu { + sound-dai = <&i2s0>, <&bt_codec>; + }; + + codec { + sound-dai = <&wm8994>; + }; + }; + diff --git a/Documentation/devicetree/bindings/sound/wm8960.txt b/Documentation/devicetree/bindings/sound/wm8960.txt index 6d29ac3750ee..85d3b287108c 100644 --- a/Documentation/devicetree/bindings/sound/wm8960.txt +++ b/Documentation/devicetree/bindings/sound/wm8960.txt @@ -21,6 +21,17 @@ Optional properties: enabled and disabled together with HP_L and HP_R pins in response to jack detect events. + - wlf,hp-cfg: A list of headphone jack detect configuration register values. + The list must be 3 entries long. + hp-cfg[0]: HPSEL[1:0] of R48 (Additional Control 4). + hp-cfg[1]: {HPSWEN:HPSWPOL} of R24 (Additional Control 2). + hp-cfg[2]: {TOCLKSEL:TOEN} of R23 (Additional Control 1). + + - wlf,gpio-cfg: A list of GPIO configuration register values. + The list must be 2 entries long. + gpio-cfg[0]: ALRCGPIO of R9 (Audio interface) + gpio-cfg[1]: {GPIOPOL:GPIOSEL[2:0]} of R48 (Additional Control 4). + Example: wm8960: codec@1a { diff --git a/Documentation/devicetree/bindings/sound/wm8994.txt b/Documentation/devicetree/bindings/sound/wm8994.txt index 367b58ce1bb9..8fa947509c10 100644 --- a/Documentation/devicetree/bindings/sound/wm8994.txt +++ b/Documentation/devicetree/bindings/sound/wm8994.txt @@ -68,6 +68,29 @@ Optional properties: - wlf,csnaddr-pd : If present enable the internal pull-down resistor on the CS/ADDR pin. +Pins on the device (for linking into audio routes): + + * IN1LN + * IN1LP + * IN2LN + * IN2LP:VXRN + * IN1RN + * IN1RP + * IN2RN + * IN2RP:VXRP + * SPKOUTLP + * SPKOUTLN + * SPKOUTRP + * SPKOUTRN + * HPOUT1L + * HPOUT1R + * HPOUT2P + * HPOUT2N + * LINEOUT1P + * LINEOUT1N + * LINEOUT2P + * LINEOUT2N + Example: wm8994: codec@1a { diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index 5663891148e3..4a4bb723ca9f 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -2,7 +2,8 @@ * * soc-component.h * - * Copyright (c) 2019 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> + * Copyright (C) 2019 Renesas Electronics Corp. + * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> */ #ifndef __SOC_COMPONENT_H #define __SOC_COMPONENT_H @@ -324,6 +325,13 @@ static inline int snd_soc_component_cache_sync( return regcache_sync(component->regmap); } +int snd_soc_component_initialize(struct snd_soc_component *component, + const struct snd_soc_component_driver *driver, + struct device *dev, const char *name); +void snd_soc_component_set_aux(struct snd_soc_component *component, + struct snd_soc_aux_dev *aux); +int snd_soc_component_init(struct snd_soc_component *component); + /* component IO */ int snd_soc_component_read(struct snd_soc_component *component, unsigned int reg, unsigned int *val); @@ -359,6 +367,7 @@ int snd_soc_component_stream_event(struct snd_soc_component *component, int snd_soc_component_set_bias_level(struct snd_soc_component *component, enum snd_soc_bias_level level); +void snd_soc_component_setup_regmap(struct snd_soc_component *component); #ifdef CONFIG_REGMAP void snd_soc_component_init_regmap(struct snd_soc_component *component, struct regmap *regmap); @@ -421,16 +430,6 @@ int snd_soc_component_open(struct snd_soc_component *component, struct snd_pcm_substream *substream); int snd_soc_component_close(struct snd_soc_component *component, struct snd_pcm_substream *substream); -int snd_soc_component_prepare(struct snd_soc_component *component, - struct snd_pcm_substream *substream); -int snd_soc_component_hw_params(struct snd_soc_component *component, - struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params); -int snd_soc_component_hw_free(struct snd_soc_component *component, - struct snd_pcm_substream *substream); -int snd_soc_component_trigger(struct snd_soc_component *component, - struct snd_pcm_substream *substream, - int cmd); void snd_soc_component_suspend(struct snd_soc_component *component); void snd_soc_component_resume(struct snd_soc_component *component); int snd_soc_component_is_suspended(struct snd_soc_component *component); @@ -455,5 +454,13 @@ int snd_soc_pcm_component_mmap(struct snd_pcm_substream *substream, struct vm_area_struct *vma); int snd_soc_pcm_component_new(struct snd_soc_pcm_runtime *rtd); void snd_soc_pcm_component_free(struct snd_soc_pcm_runtime *rtd); +int snd_soc_pcm_component_prepare(struct snd_pcm_substream *substream); +int snd_soc_pcm_component_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_component **last); +void snd_soc_pcm_component_hw_free(struct snd_pcm_substream *substream, + struct snd_soc_component *last); +int snd_soc_pcm_component_trigger(struct snd_pcm_substream *substream, + int cmd); #endif /* __SOC_COMPONENT_H */ diff --git a/include/sound/wm8960.h b/include/sound/wm8960.h index d22e84805025..275fd5b201ce 100644 --- a/include/sound/wm8960.h +++ b/include/sound/wm8960.h @@ -16,6 +16,23 @@ struct wm8960_data { bool capless; /* Headphone outputs configured in capless mode */ bool shared_lrclk; /* DAC and ADC LRCLKs are wired together */ + + /* + * Setup for headphone detection + * + * hp_cfg[0]: HPSEL[1:0] of R48 (Additional Control 4) + * hp_cfg[1]: {HPSWEN:HPSWPOL} of R24 (Additional Control 2). + * hp_cfg[2]: {TOCLKSEL:TOEN} of R23 (Additional Control 1). + */ + u32 hp_cfg[3]; + + /* + * Setup for gpio configuration + * + * gpio_cfg[0]: ALRCGPIO of R9 (Audio interface) + * gpio_cfg[1]: {GPIOPOL:GPIOSEL[2:0]} of R48 (Additional Control 4). + */ + u32 gpio_cfg[2]; }; #endif diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 7f1747518e79..ddbac3a2169f 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-utils.o soc-dai.o soc-component.o -snd-soc-core-objs += soc-pcm.o soc-io.o soc-devres.o soc-ops.o soc-link.o soc-card.o +snd-soc-core-objs += soc-pcm.o soc-devres.o soc-ops.o soc-link.o soc-card.o snd-soc-core-$(CONFIG_SND_SOC_COMPRESS) += soc-compress.o ifneq ($(CONFIG_SND_SOC_TOPOLOGY),) diff --git a/sound/soc/amd/acp3x-rt5682-max9836.c b/sound/soc/amd/acp3x-rt5682-max9836.c index e499c00e0c66..f745b42dfd23 100644 --- a/sound/soc/amd/acp3x-rt5682-max9836.c +++ b/sound/soc/amd/acp3x-rt5682-max9836.c @@ -188,25 +188,27 @@ static int acp3x_ec_dmic0_startup(struct snd_pcm_substream *substream) machine->cap_i2s_instance = I2S_BT_INSTANCE; snd_soc_dai_set_bclk_ratio(codec_dai, 64); - if (dmic_sel) - gpiod_set_value(dmic_sel, 0); return rt5682_clk_enable(substream); } -static int acp3x_ec_dmic1_startup(struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_card *card = rtd->card; - struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); - struct acp3x_platform_info *machine = snd_soc_card_get_drvdata(card); +static int dmic_switch; - machine->cap_i2s_instance = I2S_BT_INSTANCE; - snd_soc_dai_set_bclk_ratio(codec_dai, 64); - if (dmic_sel) - gpiod_set_value(dmic_sel, 1); +static int dmic_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + ucontrol->value.integer.value[0] = dmic_switch; + return 0; +} - return rt5682_clk_enable(substream); +static int dmic_set(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + if (dmic_sel) { + dmic_switch = ucontrol->value.integer.value[0]; + gpiod_set_value(dmic_sel, dmic_switch); + } + return 0; } static void rt5682_shutdown(struct snd_pcm_substream *substream) @@ -229,11 +231,6 @@ static const struct snd_soc_ops acp3x_ec_cap0_ops = { .shutdown = rt5682_shutdown, }; -static const struct snd_soc_ops acp3x_ec_cap1_ops = { - .startup = acp3x_ec_dmic1_startup, - .shutdown = rt5682_shutdown, -}; - SND_SOC_DAILINK_DEF(acp3x_i2s, DAILINK_COMP_ARRAY(COMP_CPU("acp3x_i2s_playcap.0"))); SND_SOC_DAILINK_DEF(acp3x_bt, @@ -279,21 +276,26 @@ static struct snd_soc_dai_link acp3x_dai_5682_98357[] = { .ops = &acp3x_ec_cap0_ops, SND_SOC_DAILINK_REG(acp3x_bt, cros_ec, platform), }, - { - .name = "acp3x-ec-dmic1-capture", - .stream_name = "Capture DMIC1", - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF - | SND_SOC_DAIFMT_CBS_CFS, - .dpcm_capture = 1, - .ops = &acp3x_ec_cap1_ops, - SND_SOC_DAILINK_REG(acp3x_bt, cros_ec, platform), - }, }; +static const char * const dmic_mux_text[] = { + "Front Mic", + "Rear Mic", +}; + +static SOC_ENUM_SINGLE_DECL( + acp3x_dmic_enum, SND_SOC_NOPM, 0, dmic_mux_text); + +static const struct snd_kcontrol_new acp3x_dmic_mux_control = + SOC_DAPM_ENUM_EXT("DMIC Select Mux", acp3x_dmic_enum, + dmic_get, dmic_set); + static const struct snd_soc_dapm_widget acp3x_widgets[] = { SND_SOC_DAPM_HP("Headphone Jack", NULL), SND_SOC_DAPM_SPK("Spk", NULL), SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_MUX("Dmic Mux", SND_SOC_NOPM, 0, 0, + &acp3x_dmic_mux_control), }; static const struct snd_soc_dapm_route acp3x_audio_route[] = { @@ -301,6 +303,8 @@ static const struct snd_soc_dapm_route acp3x_audio_route[] = { {"Headphone Jack", NULL, "HPOR"}, {"IN1P", NULL, "Headset Mic"}, {"Spk", NULL, "Speaker"}, + {"Dmic Mux", "Front Mic", "DMIC"}, + {"Dmic Mux", "Rear Mic", "DMIC"}, }; static const struct snd_kcontrol_new acp3x_mc_controls[] = { diff --git a/sound/soc/codecs/max98357a.c b/sound/soc/codecs/max98357a.c index a8bd793a7867..4f431133d0bb 100644 --- a/sound/soc/codecs/max98357a.c +++ b/sound/soc/codecs/max98357a.c @@ -125,6 +125,7 @@ static int max98357a_platform_probe(struct platform_device *pdev) #ifdef CONFIG_OF static const struct of_device_id max98357a_device_id[] = { { .compatible = "maxim,max98357a" }, + { .compatible = "maxim,max98360a" }, {} }; MODULE_DEVICE_TABLE(of, max98357a_device_id); diff --git a/sound/soc/codecs/max98390.c b/sound/soc/codecs/max98390.c index e6613b52bd78..b345e626956d 100644 --- a/sound/soc/codecs/max98390.c +++ b/sound/soc/codecs/max98390.c @@ -842,6 +842,20 @@ static int max98390_dsm_calibrate(struct snd_soc_component *component) return 0; } +static void max98390_init_regs(struct snd_soc_component *component) +{ + struct max98390_priv *max98390 = + snd_soc_component_get_drvdata(component); + + regmap_write(max98390->regmap, MAX98390_CLK_MON, 0x6f); + regmap_write(max98390->regmap, MAX98390_DAT_MON, 0x00); + regmap_write(max98390->regmap, MAX98390_PWR_GATE_CTL, 0x00); + regmap_write(max98390->regmap, MAX98390_PCM_RX_EN_A, 0x03); + regmap_write(max98390->regmap, MAX98390_ENV_TRACK_VOUT_HEADROOM, 0x0e); + regmap_write(max98390->regmap, MAX98390_BOOST_BYPASS1, 0x46); + regmap_write(max98390->regmap, MAX98390_FET_SCALING3, 0x03); +} + static int max98390_probe(struct snd_soc_component *component) { struct max98390_priv *max98390 = @@ -853,18 +867,10 @@ static int max98390_probe(struct snd_soc_component *component) /* Update dsm bin param */ max98390_dsm_init(component); - /* Amp Setting */ - regmap_write(max98390->regmap, MAX98390_CLK_MON, 0x6f); - regmap_write(max98390->regmap, MAX98390_PCM_RX_EN_A, 0x03); - regmap_write(max98390->regmap, MAX98390_PWR_GATE_CTL, 0x2d); - regmap_write(max98390->regmap, MAX98390_ENV_TRACK_VOUT_HEADROOM, 0x0e); - regmap_write(max98390->regmap, MAX98390_BOOST_BYPASS1, 0x46); - regmap_write(max98390->regmap, MAX98390_FET_SCALING3, 0x03); + /* Amp init setting */ + max98390_init_regs(component); /* Dsm Setting */ - regmap_write(max98390->regmap, DSM_VOL_CTRL, 0x94); - regmap_write(max98390->regmap, DSMIG_EN, 0x19); - regmap_write(max98390->regmap, MAX98390_R203A_AMP_EN, 0x80); if (max98390->ref_rdc_value) { regmap_write(max98390->regmap, DSM_TPROT_RECIP_RDC_ROOM_BYTE0, max98390->ref_rdc_value & 0x000000ff); diff --git a/sound/soc/codecs/mt6358.c b/sound/soc/codecs/mt6358.c index 1b830ea4f6ed..1f39d5998cf6 100644 --- a/sound/soc/codecs/mt6358.c +++ b/sound/soc/codecs/mt6358.c @@ -95,6 +95,8 @@ struct mt6358_priv { struct regulator *avdd_reg; int wov_enabled; + + unsigned int dmic_one_wire_mode; }; int mt6358_set_mtkaif_protocol(struct snd_soc_component *cmpnt, @@ -1831,7 +1833,10 @@ static int mt6358_dmic_enable(struct mt6358_priv *priv) mt6358_mtkaif_tx_enable(priv); /* UL dmic setting */ - regmap_write(priv->regmap, MT6358_AFE_UL_SRC_CON0_H, 0x0080); + if (priv->dmic_one_wire_mode) + regmap_write(priv->regmap, MT6358_AFE_UL_SRC_CON0_H, 0x0400); + else + regmap_write(priv->regmap, MT6358_AFE_UL_SRC_CON0_H, 0x0080); /* UL turn on */ regmap_write(priv->regmap, MT6358_AFE_UL_SRC_CON0_L, 0x0003); @@ -2426,6 +2431,20 @@ static const struct snd_soc_component_driver mt6358_soc_component_driver = { .num_dapm_routes = ARRAY_SIZE(mt6358_dapm_routes), }; +static void mt6358_parse_dt(struct mt6358_priv *priv) +{ + int ret; + struct device *dev = priv->dev; + + ret = of_property_read_u32(dev->of_node, "mediatek,dmic-mode", + &priv->dmic_one_wire_mode); + if (ret) { + dev_warn(priv->dev, "%s() failed to read dmic-mode\n", + __func__); + priv->dmic_one_wire_mode = 0; + } +} + static int mt6358_platform_driver_probe(struct platform_device *pdev) { struct mt6358_priv *priv; @@ -2445,6 +2464,8 @@ static int mt6358_platform_driver_probe(struct platform_device *pdev) if (IS_ERR(priv->regmap)) return PTR_ERR(priv->regmap); + mt6358_parse_dt(priv); + dev_info(priv->dev, "%s(), dev name %s\n", __func__, dev_name(&pdev->dev)); diff --git a/sound/soc/codecs/rl6231.c b/sound/soc/codecs/rl6231.c index 8c9daf32bab8..d1fc1706422f 100644 --- a/sound/soc/codecs/rl6231.c +++ b/sound/soc/codecs/rl6231.c @@ -103,7 +103,9 @@ struct pll_calc_map { static const struct pll_calc_map pll_preset_table[] = { {19200000, 4096000, 23, 14, 1, false, false}, {19200000, 24576000, 3, 30, 3, false, false}, + {48000000, 3840000, 23, 2, 0, false, false}, {3840000, 24576000, 3, 30, 0, true, false}, + {3840000, 22579200, 3, 5, 0, true, false}, }; static unsigned int find_best_div(unsigned int in, diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c index 3e9d2c6c51f9..36cfd10f8b04 100644 --- a/sound/soc/codecs/rt5682.c +++ b/sound/soc/codecs/rt5682.c @@ -2248,7 +2248,7 @@ static int rt5682_set_component_pll(struct snd_soc_component *component, { struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); struct rl6231_pll_code pll_code, pll2f_code, pll2b_code; - unsigned int pll2_fout1; + unsigned int pll2_fout1, pll2_ps_val; int ret; if (source == rt5682->pll_src[pll_id] && @@ -2317,8 +2317,15 @@ static int rt5682_set_component_pll(struct snd_soc_component *component, pll2b_code.n_code); snd_soc_component_write(component, RT5682_PLL2_CTRL_3, pll2f_code.n_code << RT5682_PLL2F_N_SFT); + + if (freq_out == 22579200) + pll2_ps_val = 1 << RT5682_PLL2B_SEL_PS_SFT; + else + pll2_ps_val = 1 << RT5682_PLL2B_PS_BYP_SFT; snd_soc_component_update_bits(component, RT5682_PLL2_CTRL_4, + RT5682_PLL2B_SEL_PS_MASK | RT5682_PLL2B_PS_BYP_MASK | RT5682_PLL2B_M_BP_MASK | RT5682_PLL2F_M_BP_MASK | 0xf, + pll2_ps_val | (pll2b_code.m_bp ? 1 : 0) << RT5682_PLL2B_M_BP_SFT | (pll2f_code.m_bp ? 1 : 0) << RT5682_PLL2F_M_BP_SFT | 0xf); @@ -2456,8 +2463,8 @@ static int rt5682_set_bias_level(struct snd_soc_component *component, #ifdef CONFIG_COMMON_CLK #define CLK_PLL2_FIN 48000000 -#define CLK_PLL2_FOUT 24576000 #define CLK_48 48000 +#define CLK_44 44100 static bool rt5682_clk_check(struct rt5682_priv *rt5682) { @@ -2527,13 +2534,22 @@ static unsigned long rt5682_wclk_recalc_rate(struct clk_hw *hw, struct rt5682_priv *rt5682 = container_of(hw, struct rt5682_priv, dai_clks_hw[RT5682_DAI_WCLK_IDX]); + struct snd_soc_component *component = rt5682->component; + const char * const clk_name = __clk_get_name(hw->clk); if (!rt5682_clk_check(rt5682)) return 0; /* - * Only accept to set wclk rate to 48kHz temporarily. + * Only accept to set wclk rate to 44.1k or 48kHz. */ - return CLK_48; + if (rt5682->lrck[RT5682_AIF1] != CLK_48 && + rt5682->lrck[RT5682_AIF1] != CLK_44) { + dev_warn(component->dev, "%s: clk %s only support %d or %d Hz output\n", + __func__, clk_name, CLK_44, CLK_48); + return 0; + } + + return rt5682->lrck[RT5682_AIF1]; } static long rt5682_wclk_round_rate(struct clk_hw *hw, unsigned long rate, @@ -2542,13 +2558,22 @@ static long rt5682_wclk_round_rate(struct clk_hw *hw, unsigned long rate, struct rt5682_priv *rt5682 = container_of(hw, struct rt5682_priv, dai_clks_hw[RT5682_DAI_WCLK_IDX]); + struct snd_soc_component *component = rt5682->component; + const char * const clk_name = __clk_get_name(hw->clk); if (!rt5682_clk_check(rt5682)) return -EINVAL; /* - * Only accept to set wclk rate to 48kHz temporarily. + * Only accept to set wclk rate to 44.1k or 48kHz. + * It will force to 48kHz if not both. */ - return CLK_48; + if (rate != CLK_48 && rate != CLK_44) { + dev_warn(component->dev, "%s: clk %s only support %d or %d Hz output\n", + __func__, clk_name, CLK_44, CLK_48); + rate = CLK_48; + } + + return rate; } static int rt5682_wclk_set_rate(struct clk_hw *hw, unsigned long rate, @@ -2561,6 +2586,7 @@ static int rt5682_wclk_set_rate(struct clk_hw *hw, unsigned long rate, struct clk *parent_clk; const char * const clk_name = __clk_get_name(hw->clk); int pre_div; + unsigned int clk_pll2_out; if (!rt5682_clk_check(rt5682)) return -EINVAL; @@ -2583,23 +2609,17 @@ static int rt5682_wclk_set_rate(struct clk_hw *hw, unsigned long rate, clk_name, CLK_PLL2_FIN); /* - * It's a temporary limitation. Only accept to set wclk rate to 48kHz. - * It will force wclk to 48kHz even it's not. - */ - if (rate != CLK_48) { - dev_warn(component->dev, "clk %s only support %d Hz output\n", - clk_name, CLK_48); - rate = CLK_48; - } - - /* - * To achieve the rate conversion from 48MHz to 48kHz, PLL2 is needed. + * To achieve the rate conversion from 48MHz to 44.1k or 48kHz, + * PLL2 is needed. */ + clk_pll2_out = rate * 512; rt5682_set_component_pll(component, RT5682_PLL2, RT5682_PLL2_S_MCLK, - CLK_PLL2_FIN, CLK_PLL2_FOUT); + CLK_PLL2_FIN, clk_pll2_out); rt5682_set_component_sysclk(component, RT5682_SCLK_S_PLL2, 0, - CLK_PLL2_FOUT, SND_SOC_CLOCK_IN); + clk_pll2_out, SND_SOC_CLOCK_IN); + + rt5682->lrck[RT5682_AIF1] = rate; pre_div = rl6231_get_clk_info(rt5682->sysclk, rate); diff --git a/sound/soc/codecs/rt5682.h b/sound/soc/codecs/rt5682.h index f172c9ebd227..6d94327beae5 100644 --- a/sound/soc/codecs/rt5682.h +++ b/sound/soc/codecs/rt5682.h @@ -1080,6 +1080,10 @@ #define RT5682_PLL2F_N_SFT 8 /* PLL2 M/N/K Code Control 2 (0x009e) */ +#define RT5682_PLL2B_SEL_PS_MASK (0x1 << 13) +#define RT5682_PLL2B_SEL_PS_SFT 13 +#define RT5682_PLL2B_PS_BYP_MASK (0x1 << 12) +#define RT5682_PLL2B_PS_BYP_SFT 12 #define RT5682_PLL2B_M_BP_MASK (0x1 << 11) #define RT5682_PLL2B_M_BP_SFT 11 #define RT5682_PLL2F_M_BP_MASK (0x1 << 7) diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c index fbcee21736e8..2f2b2f5d55e4 100644 --- a/sound/soc/codecs/wm0010.c +++ b/sound/soc/codecs/wm0010.c @@ -515,7 +515,7 @@ static int wm0010_stage2_load(struct snd_soc_component *component) dev_dbg(component->dev, "Downloading %zu byte stage 2 loader\n", fw->size); /* Copy to local buffer first as vmalloc causes problems for dma */ - img = kzalloc(fw->size, GFP_KERNEL | GFP_DMA); + img = kmemdup(&fw->data[0], fw->size, GFP_KERNEL | GFP_DMA); if (!img) { ret = -ENOMEM; goto abort2; @@ -527,8 +527,6 @@ static int wm0010_stage2_load(struct snd_soc_component *component) goto abort1; } - memcpy(img, &fw->data[0], fw->size); - spi_message_init(&m); memset(&t, 0, sizeof(t)); t.rx_buf = out; |