Commit 65fd5252 authored by Mark Brown's avatar Mark Brown

Merge remote-tracking branches 'asoc/topic/sta529', 'asoc/topic/sti',...

Merge remote-tracking branches 'asoc/topic/sta529', 'asoc/topic/sti', 'asoc/topic/stm', 'asoc/topic/sunxi' and 'asoc/topic/tas2552' into asoc-next
STMicroelectronics STM32 Serial Audio Interface (SAI).
The SAI interface (Serial Audio Interface) offers a wide set of audio protocols
as I2S standards, LSB or MSB-justified, PCM/DSP, TDM, and AC'97.
The SAI contains two independent audio sub-blocks. Each sub-block has
its own clock generator and I/O lines controller.
Required properties:
- compatible: Should be "st,stm32f4-sai"
- reg: Base address and size of SAI common register set.
- clocks: Must contain phandle and clock specifier pairs for each entry
in clock-names.
- clock-names: Must contain "x8k" and "x11k"
"x8k": SAI parent clock for sampling rates multiple of 8kHz.
"x11k": SAI parent clock for sampling rates multiple of 11.025kHz.
- interrupts: cpu DAI interrupt line shared by SAI sub-blocks
Optional properties:
- resets: Reference to a reset controller asserting the SAI
SAI subnodes:
Two subnodes corresponding to SAI sub-block instances A et B can be defined.
Subnode can be omitted for unsused sub-block.
SAI subnodes required properties:
- compatible: Should be "st,stm32-sai-sub-a" or "st,stm32-sai-sub-b"
for SAI sub-block A or B respectively.
- reg: Base address and size of SAI sub-block register set.
- clocks: Must contain one phandle and clock specifier pair
for sai_ck which feeds the internal clock generator.
- clock-names: Must contain "sai_ck".
- dmas: see Documentation/devicetree/bindings/dma/stm32-dma.txt
- dma-names: identifier string for each DMA request line
"tx": if sai sub-block is configured as playback DAI
"rx": if sai sub-block is configured as capture DAI
- pinctrl-names: should contain only value "default"
- pinctrl-0: see Documentation/devicetree/bindings/pinctrl/pinctrl-stm32.txt
Example:
sound_card {
compatible = "audio-graph-card";
dais = <&sai1b_port>;
};
sai1: sai1@40015800 {
compatible = "st,stm32f4-sai";
#address-cells = <1>;
#size-cells = <1>;
ranges;
reg = <0x40015800 0x4>;
clocks = <&rcc 1 CLK_SAIQ_PDIV>, <&rcc 1 CLK_I2SQ_PDIV>;
clock-names = "x8k", "x11k";
interrupts = <87>;
sai1b: audio-controller@40015824 {
#sound-dai-cells = <0>;
compatible = "st,stm32-sai-sub-b";
reg = <0x40015824 0x1C>;
clocks = <&rcc 1 CLK_SAI2>;
clock-names = "sai_ck";
dmas = <&dma2 5 0 0x400 0x0>;
dma-names = "tx";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_sai1b>;
ports {
#address-cells = <1>;
#size-cells = <0>;
sai1b_port: port@0 {
reg = <0>;
cpu_endpoint: endpoint {
remote-endpoint = <&codec_endpoint>;
audio-graph-card,format = "i2s";
audio-graph-card,bitclock-master = <&codec_endpoint>;
audio-graph-card,frame-master = <&codec_endpoint>;
};
};
};
};
};
audio-codec {
codec_port: port {
codec_endpoint: endpoint {
remote-endpoint = <&cpu_endpoint>;
};
};
};
......@@ -5,7 +5,8 @@ The tas2552 serial control bus communicates through I2C protocols
Required properties:
- compatible - One of:
"ti,tas2552" - TAS2552
- reg - I2C slave address
- reg - I2C slave address: it can be 0x40 if ADDR pin is 0
or 0x41 if ADDR pin is 1.
- supply-*: Required supply regulators are:
"vbat" battery voltage
"iovdd" I/O Voltage
......@@ -14,17 +15,20 @@ Required properties:
Optional properties:
- enable-gpio - gpio pin to enable/disable the device
tas2552 can receive it's reference clock via MCLK, BCLK, IVCLKIN pin or use the
tas2552 can receive its reference clock via MCLK, BCLK, IVCLKIN pin or use the
internal 1.8MHz. This CLKIN is used by the PLL. In addition to PLL, the PDM
reference clock is also selectable: PLL, IVCLKIN, BCLK or MCLK.
For system integration the dt-bindings/sound/tas2552.h header file provides
defined values to selct and configure the PLL and PDM reference clocks.
defined values to select and configure the PLL and PDM reference clocks.
Example:
tas2552: tas2552@41 {
compatible = "ti,tas2552";
reg = <0x41>;
vbat-supply = <&reg_vbat>;
iovdd-supply = <&reg_iovdd>;
avdd-supply = <&reg_avdd>;
enable-gpio = <&gpio4 2 GPIO_ACTIVE_HIGH>;
};
......
......@@ -64,6 +64,7 @@ source "sound/soc/sh/Kconfig"
source "sound/soc/sirf/Kconfig"
source "sound/soc/spear/Kconfig"
source "sound/soc/sti/Kconfig"
source "sound/soc/stm/Kconfig"
source "sound/soc/sunxi/Kconfig"
source "sound/soc/tegra/Kconfig"
source "sound/soc/txx9/Kconfig"
......
......@@ -44,6 +44,7 @@ obj-$(CONFIG_SND_SOC) += sh/
obj-$(CONFIG_SND_SOC) += sirf/
obj-$(CONFIG_SND_SOC) += spear/
obj-$(CONFIG_SND_SOC) += sti/
obj-$(CONFIG_SND_SOC) += stm/
obj-$(CONFIG_SND_SOC) += sunxi/
obj-$(CONFIG_SND_SOC) += tegra/
obj-$(CONFIG_SND_SOC) += txx9/
......
......@@ -375,9 +375,16 @@ static const struct i2c_device_id sta529_i2c_id[] = {
};
MODULE_DEVICE_TABLE(i2c, sta529_i2c_id);
static const struct of_device_id sta529_of_match[] = {
{ .compatible = "st,sta529", },
{ }
};
MODULE_DEVICE_TABLE(of, sta529_of_match);
static struct i2c_driver sta529_i2c_driver = {
.driver = {
.name = "sta529",
.of_match_table = sta529_of_match,
},
.probe = sta529_i2c_probe,
.remove = sta529_i2c_remove,
......
......@@ -611,7 +611,7 @@ static int tas2552_codec_probe(struct snd_soc_codec *codec)
regulator_bulk_disable(ARRAY_SIZE(tas2552->supplies),
tas2552->supplies);
return -EIO;
return ret;
}
static int tas2552_codec_remove(struct snd_soc_codec *codec)
......@@ -637,7 +637,7 @@ static int tas2552_suspend(struct snd_soc_codec *codec)
if (ret != 0)
dev_err(codec->dev, "Failed to disable supplies: %d\n",
ret);
return 0;
return ret;
}
static int tas2552_resume(struct snd_soc_codec *codec)
......@@ -653,7 +653,7 @@ static int tas2552_resume(struct snd_soc_codec *codec)
ret);
}
return 0;
return ret;
}
#else
#define tas2552_suspend NULL
......
......@@ -1074,7 +1074,7 @@ int uni_player_init(struct platform_device *pdev,
player->clk = of_clk_get(pdev->dev.of_node, 0);
if (IS_ERR(player->clk)) {
dev_err(player->dev, "Failed to get clock\n");
ret = PTR_ERR(player->clk);
return PTR_ERR(player->clk);
}
/* Select the frequency synthesizer clock */
......
menuconfig SND_SOC_STM32
tristate "STMicroelectronics STM32 SOC audio support"
depends on ARCH_STM32 || COMPILE_TEST
depends on SND_SOC
select SND_SOC_GENERIC_DMAENGINE_PCM
select REGMAP_MMIO
help
Say Y if you want to enable ASoC-support for STM32
# SAI
snd-soc-stm32-sai-sub-objs := stm32_sai_sub.o
obj-$(CONFIG_SND_SOC_STM32) += snd-soc-stm32-sai-sub.o
snd-soc-stm32-sai-objs := stm32_sai.o
obj-$(CONFIG_SND_SOC_STM32) += snd-soc-stm32-sai.o
/*
* STM32 ALSA SoC Digital Audio Interface (SAI) driver.
*
* Copyright (C) 2016, STMicroelectronics - All Rights Reserved
* Author(s): Olivier Moysan <olivier.moysan@st.com> for STMicroelectronics.
*
* License terms: GPL V2.0.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*/
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/of_platform.h>
#include <linux/reset.h>
#include <sound/dmaengine_pcm.h>
#include <sound/core.h>
#include "stm32_sai.h"
static const struct of_device_id stm32_sai_ids[] = {
{ .compatible = "st,stm32f4-sai", .data = (void *)SAI_STM32F4 },
{}
};
static int stm32_sai_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct stm32_sai_data *sai;
struct reset_control *rst;
struct resource *res;
void __iomem *base;
const struct of_device_id *of_id;
sai = devm_kzalloc(&pdev->dev, sizeof(*sai), GFP_KERNEL);
if (!sai)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(base))
return PTR_ERR(base);
of_id = of_match_device(stm32_sai_ids, &pdev->dev);
if (of_id)
sai->version = (enum stm32_sai_version)of_id->data;
else
return -EINVAL;
sai->clk_x8k = devm_clk_get(&pdev->dev, "x8k");
if (IS_ERR(sai->clk_x8k)) {
dev_err(&pdev->dev, "missing x8k parent clock\n");
return PTR_ERR(sai->clk_x8k);
}
sai->clk_x11k = devm_clk_get(&pdev->dev, "x11k");
if (IS_ERR(sai->clk_x11k)) {
dev_err(&pdev->dev, "missing x11k parent clock\n");
return PTR_ERR(sai->clk_x11k);
}
/* init irqs */
sai->irq = platform_get_irq(pdev, 0);
if (sai->irq < 0) {
dev_err(&pdev->dev, "no irq for node %s\n", pdev->name);
return sai->irq;
}
/* reset */
rst = reset_control_get(&pdev->dev, NULL);
if (!IS_ERR(rst)) {
reset_control_assert(rst);
udelay(2);
reset_control_deassert(rst);
}
sai->pdev = pdev;
platform_set_drvdata(pdev, sai);
return of_platform_populate(np, NULL, NULL, &pdev->dev);
}
static int stm32_sai_remove(struct platform_device *pdev)
{
of_platform_depopulate(&pdev->dev);
return 0;
}
MODULE_DEVICE_TABLE(of, stm32_sai_ids);
static struct platform_driver stm32_sai_driver = {
.driver = {
.name = "st,stm32-sai",
.of_match_table = stm32_sai_ids,
},
.probe = stm32_sai_probe,
.remove = stm32_sai_remove,
};
module_platform_driver(stm32_sai_driver);
MODULE_DESCRIPTION("STM32 Soc SAI Interface");
MODULE_AUTHOR("Olivier Moysan, <olivier.moysan@st.com>");
MODULE_ALIAS("platform:st,stm32-sai");
MODULE_LICENSE("GPL v2");
/*
* STM32 ALSA SoC Digital Audio Interface (SAI) driver.
*
* Copyright (C) 2016, STMicroelectronics - All Rights Reserved
* Author(s): Olivier Moysan <olivier.moysan@st.com> for STMicroelectronics.
*
* License terms: GPL V2.0.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*/
/******************** SAI Register Map **************************************/
/* common register */
#define STM_SAI_GCR 0x00
/* Sub-block A&B registers offsets, relative to A&B sub-block addresses */
#define STM_SAI_CR1_REGX 0x00 /* A offset: 0x04. B offset: 0x24 */
#define STM_SAI_CR2_REGX 0x04
#define STM_SAI_FRCR_REGX 0x08
#define STM_SAI_SLOTR_REGX 0x0C
#define STM_SAI_IMR_REGX 0x10
#define STM_SAI_SR_REGX 0x14
#define STM_SAI_CLRFR_REGX 0x18
#define STM_SAI_DR_REGX 0x1C
/******************** Bit definition for SAI_GCR register *******************/
#define SAI_GCR_SYNCIN_SHIFT 0
#define SAI_GCR_SYNCIN_MASK GENMASK(1, SAI_GCR_SYNCIN_SHIFT)
#define SAI_GCR_SYNCIN_SET(x) ((x) << SAI_GCR_SYNCIN_SHIFT)
#define SAI_GCR_SYNCOUT_SHIFT 4
#define SAI_GCR_SYNCOUT_MASK GENMASK(5, SAI_GCR_SYNCOUT_SHIFT)
#define SAI_GCR_SYNCOUT_SET(x) ((x) << SAI_GCR_SYNCOUT_SHIFT)
/******************* Bit definition for SAI_XCR1 register *******************/
#define SAI_XCR1_RX_TX_SHIFT 0
#define SAI_XCR1_RX_TX BIT(SAI_XCR1_RX_TX_SHIFT)
#define SAI_XCR1_SLAVE_SHIFT 1
#define SAI_XCR1_SLAVE BIT(SAI_XCR1_SLAVE_SHIFT)
#define SAI_XCR1_PRTCFG_SHIFT 2
#define SAI_XCR1_PRTCFG_MASK GENMASK(3, SAI_XCR1_PRTCFG_SHIFT)
#define SAI_XCR1_PRTCFG_SET(x) ((x) << SAI_XCR1_PRTCFG_SHIFT)
#define SAI_XCR1_DS_SHIFT 5
#define SAI_XCR1_DS_MASK GENMASK(7, SAI_XCR1_DS_SHIFT)
#define SAI_XCR1_DS_SET(x) ((x) << SAI_XCR1_DS_SHIFT)
#define SAI_XCR1_LSBFIRST_SHIFT 8
#define SAI_XCR1_LSBFIRST BIT(SAI_XCR1_LSBFIRST_SHIFT)
#define SAI_XCR1_CKSTR_SHIFT 9
#define SAI_XCR1_CKSTR BIT(SAI_XCR1_CKSTR_SHIFT)
#define SAI_XCR1_SYNCEN_SHIFT 10
#define SAI_XCR1_SYNCEN_MASK GENMASK(11, SAI_XCR1_SYNCEN_SHIFT)
#define SAI_XCR1_SYNCEN_SET(x) ((x) << SAI_XCR1_SYNCEN_SHIFT)
#define SAI_XCR1_MONO_SHIFT 12
#define SAI_XCR1_MONO BIT(SAI_XCR1_MONO_SHIFT)
#define SAI_XCR1_OUTDRIV_SHIFT 13
#define SAI_XCR1_OUTDRIV BIT(SAI_XCR1_OUTDRIV_SHIFT)
#define SAI_XCR1_SAIEN_SHIFT 16
#define SAI_XCR1_SAIEN BIT(SAI_XCR1_SAIEN_SHIFT)
#define SAI_XCR1_DMAEN_SHIFT 17
#define SAI_XCR1_DMAEN BIT(SAI_XCR1_DMAEN_SHIFT)
#define SAI_XCR1_NODIV_SHIFT 19
#define SAI_XCR1_NODIV BIT(SAI_XCR1_NODIV_SHIFT)
#define SAI_XCR1_MCKDIV_SHIFT 20
#define SAI_XCR1_MCKDIV_WIDTH 4
#define SAI_XCR1_MCKDIV_MASK GENMASK(24, SAI_XCR1_MCKDIV_SHIFT)
#define SAI_XCR1_MCKDIV_SET(x) ((x) << SAI_XCR1_MCKDIV_SHIFT)
#define SAI_XCR1_MCKDIV_MAX ((1 << SAI_XCR1_MCKDIV_WIDTH) - 1)
#define SAI_XCR1_OSR_SHIFT 26
#define SAI_XCR1_OSR BIT(SAI_XCR1_OSR_SHIFT)
/******************* Bit definition for SAI_XCR2 register *******************/
#define SAI_XCR2_FTH_SHIFT 0
#define SAI_XCR2_FTH_MASK GENMASK(2, SAI_XCR2_FTH_SHIFT)
#define SAI_XCR2_FTH_SET(x) ((x) << SAI_XCR2_FTH_SHIFT)
#define SAI_XCR2_FFLUSH_SHIFT 3
#define SAI_XCR2_FFLUSH BIT(SAI_XCR2_FFLUSH_SHIFT)
#define SAI_XCR2_TRIS_SHIFT 4
#define SAI_XCR2_TRIS BIT(SAI_XCR2_TRIS_SHIFT)
#define SAI_XCR2_MUTE_SHIFT 5
#define SAI_XCR2_MUTE BIT(SAI_XCR2_MUTE_SHIFT)
#define SAI_XCR2_MUTEVAL_SHIFT 6
#define SAI_XCR2_MUTEVAL BIT(SAI_XCR2_MUTEVAL_SHIFT)
#define SAI_XCR2_MUTECNT_SHIFT 7
#define SAI_XCR2_MUTECNT_MASK GENMASK(12, SAI_XCR2_MUTECNT_SHIFT)
#define SAI_XCR2_MUTECNT_SET(x) ((x) << SAI_XCR2_MUTECNT_SHIFT)
#define SAI_XCR2_CPL_SHIFT 13
#define SAI_XCR2_CPL BIT(SAI_XCR2_CPL_SHIFT)
#define SAI_XCR2_COMP_SHIFT 14
#define SAI_XCR2_COMP_MASK GENMASK(15, SAI_XCR2_COMP_SHIFT)
#define SAI_XCR2_COMP_SET(x) ((x) << SAI_XCR2_COMP_SHIFT)
/****************** Bit definition for SAI_XFRCR register *******************/
#define SAI_XFRCR_FRL_SHIFT 0
#define SAI_XFRCR_FRL_MASK GENMASK(7, SAI_XFRCR_FRL_SHIFT)
#define SAI_XFRCR_FRL_SET(x) ((x) << SAI_XFRCR_FRL_SHIFT)
#define SAI_XFRCR_FSALL_SHIFT 8
#define SAI_XFRCR_FSALL_MASK GENMASK(14, SAI_XFRCR_FSALL_SHIFT)
#define SAI_XFRCR_FSALL_SET(x) ((x) << SAI_XFRCR_FSALL_SHIFT)
#define SAI_XFRCR_FSDEF_SHIFT 16
#define SAI_XFRCR_FSDEF BIT(SAI_XFRCR_FSDEF_SHIFT)
#define SAI_XFRCR_FSPOL_SHIFT 17
#define SAI_XFRCR_FSPOL BIT(SAI_XFRCR_FSPOL_SHIFT)
#define SAI_XFRCR_FSOFF_SHIFT 18
#define SAI_XFRCR_FSOFF BIT(SAI_XFRCR_FSOFF_SHIFT)
/****************** Bit definition for SAI_XSLOTR register ******************/
#define SAI_XSLOTR_FBOFF_SHIFT 0
#define SAI_XSLOTR_FBOFF_MASK GENMASK(4, SAI_XSLOTR_FBOFF_SHIFT)
#define SAI_XSLOTR_FBOFF_SET(x) ((x) << SAI_XSLOTR_FBOFF_SHIFT)
#define SAI_XSLOTR_SLOTSZ_SHIFT 6
#define SAI_XSLOTR_SLOTSZ_MASK GENMASK(7, SAI_XSLOTR_SLOTSZ_SHIFT)
#define SAI_XSLOTR_SLOTSZ_SET(x) ((x) << SAI_XSLOTR_SLOTSZ_SHIFT)
#define SAI_XSLOTR_NBSLOT_SHIFT 8
#define SAI_XSLOTR_NBSLOT_MASK GENMASK(11, SAI_XSLOTR_NBSLOT_SHIFT)
#define SAI_XSLOTR_NBSLOT_SET(x) ((x) << SAI_XSLOTR_NBSLOT_SHIFT)
#define SAI_XSLOTR_SLOTEN_SHIFT 16
#define SAI_XSLOTR_SLOTEN_WIDTH 16
#define SAI_XSLOTR_SLOTEN_MASK GENMASK(31, SAI_XSLOTR_SLOTEN_SHIFT)
#define SAI_XSLOTR_SLOTEN_SET(x) ((x) << SAI_XSLOTR_SLOTEN_SHIFT)
/******************* Bit definition for SAI_XIMR register *******************/
#define SAI_XIMR_OVRUDRIE BIT(0)
#define SAI_XIMR_MUTEDETIE BIT(1)
#define SAI_XIMR_WCKCFGIE BIT(2)
#define SAI_XIMR_FREQIE BIT(3)
#define SAI_XIMR_CNRDYIE BIT(4)
#define SAI_XIMR_AFSDETIE BIT(5)
#define SAI_XIMR_LFSDETIE BIT(6)
#define SAI_XIMR_SHIFT 0
#define SAI_XIMR_MASK GENMASK(6, SAI_XIMR_SHIFT)
/******************** Bit definition for SAI_XSR register *******************/
#define SAI_XSR_OVRUDR BIT(0)
#define SAI_XSR_MUTEDET BIT(1)
#define SAI_XSR_WCKCFG BIT(2)
#define SAI_XSR_FREQ BIT(3)
#define SAI_XSR_CNRDY BIT(4)
#define SAI_XSR_AFSDET BIT(5)
#define SAI_XSR_LFSDET BIT(6)
#define SAI_XSR_SHIFT 0
#define SAI_XSR_MASK GENMASK(6, SAI_XSR_SHIFT)
/****************** Bit definition for SAI_XCLRFR register ******************/
#define SAI_XCLRFR_COVRUDR BIT(0)
#define SAI_XCLRFR_CMUTEDET BIT(1)
#define SAI_XCLRFR_CWCKCFG BIT(2)
#define SAI_XCLRFR_CFREQ BIT(3)
#define SAI_XCLRFR_CCNRDY BIT(4)
#define SAI_XCLRFR_CAFSDET BIT(5)
#define SAI_XCLRFR_CLFSDET BIT(6)
#define SAI_XCLRFR_SHIFT 0
#define SAI_XCLRFR_MASK GENMASK(6, SAI_XCLRFR_SHIFT)
enum stm32_sai_version {
SAI_STM32F4
};
/**
* struct stm32_sai_data - private data of SAI instance driver
* @pdev: device data pointer
* @clk_x8k: SAI parent clock for sampling frequencies multiple of 8kHz
* @clk_x11k: SAI parent clock for sampling frequencies multiple of 11kHz
* @version: SOC version
* @irq: SAI interrupt line
*/
struct stm32_sai_data {
struct platform_device *pdev;
struct clk *clk_x8k;
struct clk *clk_x11k;
int version;
int irq;
};
This diff is collapsed.
......@@ -252,24 +252,15 @@ static const DECLARE_TLV_DB_RANGE(sun8i_codec_mic_gain_scale,
);
static const struct snd_kcontrol_new sun8i_codec_common_controls[] = {
/* Mixer pre-gains */
SOC_SINGLE_TLV("Line In Playback Volume", SUN8I_ADDA_LINEIN_GCTRL,
SUN8I_ADDA_LINEIN_GCTRL_LINEING,
0x7, 0, sun8i_codec_out_mixer_pregain_scale),
/* Mixer pre-gain */
SOC_SINGLE_TLV("Mic1 Playback Volume", SUN8I_ADDA_MICIN_GCTRL,
SUN8I_ADDA_MICIN_GCTRL_MIC1G,
0x7, 0, sun8i_codec_out_mixer_pregain_scale),
SOC_SINGLE_TLV("Mic2 Playback Volume",
SUN8I_ADDA_MICIN_GCTRL, SUN8I_ADDA_MICIN_GCTRL_MIC2G,
0x7, 0, sun8i_codec_out_mixer_pregain_scale),
/* Microphone Amp boost gains */
/* Microphone Amp boost gain */
SOC_SINGLE_TLV("Mic1 Boost Volume", SUN8I_ADDA_MIC1G_MICBIAS_CTRL,
SUN8I_ADDA_MIC1G_MICBIAS_CTRL_MIC1BOOST, 0x7, 0,
sun8i_codec_mic_gain_scale),
SOC_SINGLE_TLV("Mic2 Boost Volume", SUN8I_ADDA_MIC2G_CTRL,
SUN8I_ADDA_MIC2G_CTRL_MIC2BOOST, 0x7, 0,
sun8i_codec_mic_gain_scale),
/* ADC */
SOC_SINGLE_TLV("ADC Gain Capture Volume", SUN8I_ADDA_ADC_AP_EN,
......@@ -295,12 +286,8 @@ static const struct snd_soc_dapm_widget sun8i_codec_common_widgets[] = {
* stream widgets at the card level.
*/
/* Line In */
SND_SOC_DAPM_INPUT("LINEIN"),
/* Microphone inputs */
/* Microphone input */
SND_SOC_DAPM_INPUT("MIC1"),
SND_SOC_DAPM_INPUT("MIC2"),
/* Microphone Bias */
SND_SOC_DAPM_SUPPLY("MBIAS", SUN8I_ADDA_MIC1G_MICBIAS_CTRL,
......@@ -310,8 +297,6 @@ static const struct snd_soc_dapm_widget sun8i_codec_common_widgets[] = {
/* Mic input path */
SND_SOC_DAPM_PGA("Mic1 Amplifier", SUN8I_ADDA_MIC1G_MICBIAS_CTRL,
SUN8I_ADDA_MIC1G_MICBIAS_CTRL_MIC1AMPEN, 0, NULL, 0),
SND_SOC_DAPM_PGA("Mic2 Amplifier", SUN8I_ADDA_MIC2G_CTRL,
SUN8I_ADDA_MIC2G_CTRL_MIC2AMPEN, 0, NULL, 0),
/* Mixers */
SND_SOC_DAPM_MIXER("Left Mixer", SUN8I_ADDA_DAC_PA_SRC,
......@@ -335,35 +320,26 @@ static const struct snd_soc_dapm_widget sun8i_codec_common_widgets[] = {
static const struct snd_soc_dapm_route sun8i_codec_common_routes[] = {
/* Microphone Routes */
{ "Mic1 Amplifier", NULL, "MIC1"},
{ "Mic2 Amplifier", NULL, "MIC2"},
/* Left Mixer Routes */
{ "Left Mixer", "DAC Playback Switch", "Left DAC" },
{ "Left Mixer", "DAC Reversed Playback Switch", "Right DAC" },
{ "Left Mixer", "Line In Playback Switch", "LINEIN" },
{ "Left Mixer", "Mic1 Playback Switch", "Mic1 Amplifier" },
{ "Left Mixer", "Mic2 Playback Switch", "Mic2 Amplifier" },
/* Right Mixer Routes */
{ "Right Mixer", "DAC Playback Switch", "Right DAC" },
{ "Right Mixer", "DAC Reversed Playback Switch", "Left DAC" },
{ "Right Mixer", "Line In Playback Switch", "LINEIN" },
{ "Right Mixer", "Mic1 Playback Switch", "Mic1 Amplifier" },
{ "Right Mixer", "Mic2 Playback Switch", "Mic2 Amplifier" },
/* Left ADC Mixer Routes */
{ "Left ADC Mixer", "Mixer Capture Switch", "Left Mixer" },
{ "Left ADC Mixer", "Mixer Reversed Capture Switch", "Right Mixer" },
{ "Left ADC Mixer", "Line In Capture Switch", "LINEIN" },
{ "Left ADC Mixer", "Mic1 Capture Switch", "Mic1 Amplifier" },
{ "Left ADC Mixer", "Mic2 Capture Switch", "Mic2 Amplifier" },
/* Right ADC Mixer Routes */
{ "Right ADC Mixer", "Mixer Capture Switch", "Right Mixer" },
{ "Right ADC Mixer", "Mixer Reversed Capture Switch", "Left Mixer" },
{ "Right ADC Mixer", "Line In Capture Switch", "LINEIN" },
{ "Right ADC Mixer", "Mic1 Capture Switch", "Mic1 Amplifier" },
{ "Right ADC Mixer", "Mic2 Capture Switch", "Mic2 Amplifier" },
/* ADC Routes */
{ "Left ADC", NULL, "Left ADC Mixer" },
......@@ -498,6 +474,61 @@ static int sun8i_codec_add_hmic(struct snd_soc_component *cmpnt)
return ret;
}
/* line in specific controls, widgets and rines */
static const struct snd_kcontrol_new sun8i_codec_linein_controls[] = {
/* Mixer pre-gain */
SOC_SINGLE_TLV("Line In Playback Volume", SUN8I_ADDA_LINEIN_GCTRL,
SUN8I_ADDA_LINEIN_GCTRL_LINEING,
0x7, 0, sun8i_codec_out_mixer_pregain_scale),
};
static const struct snd_soc_dapm_widget sun8i_codec_linein_widgets[] = {
/* Line input */
SND_SOC_DAPM_INPUT("LINEIN"),
};
static const struct snd_soc_dapm_route sun8i_codec_linein_routes[] = {
{ "Left Mixer", "Line In Playback Switch", "LINEIN" },
{ "Right Mixer", "Line In Playback Switch", "LINEIN" },
{ "Left ADC Mixer", "Line In Capture Switch", "LINEIN" },
{ "Right ADC Mixer", "Line In Capture Switch", "LINEIN" },
};
static int sun8i_codec_add_linein(struct snd_soc_component *cmpnt)
{
struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(cmpnt);
struct device *dev = cmpnt->dev;
int ret;
ret = snd_soc_add_component_controls(cmpnt,
sun8i_codec_linein_controls,
ARRAY_SIZE(sun8i_codec_linein_controls));
if (ret) {
dev_err(dev, "Failed to add Line In controls: %d\n", ret);
return ret;
}
ret = snd_soc_dapm_new_controls(dapm, sun8i_codec_linein_widgets,
ARRAY_SIZE(sun8i_codec_linein_widgets));
if (ret) {
dev_err(dev, "Failed to add Line In DAPM widgets: %d\n", ret);
return ret;
}
ret = snd_soc_dapm_add_routes(dapm, sun8i_codec_linein_routes,
ARRAY_SIZE(sun8i_codec_linein_routes));
if (ret) {
dev_err(dev, "Failed to add Line In DAPM routes: %d\n", ret);
return ret;
}
return 0;
}
/* line out specific controls, widgets and routes */
static const DECLARE_TLV_DB_RANGE(sun8i_codec_lineout_vol_scale,
0, 1, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1),
......@@ -578,19 +609,90 @@ static int sun8i_codec_add_lineout(struct snd_soc_component *cmpnt)
return 0;
}
/* mic2 specific controls, widgets and routes */
static const struct snd_kcontrol_new sun8i_codec_mic2_controls[] = {
/* Mixer pre-gain */
SOC_SINGLE_TLV("Mic2 Playback Volume",
SUN8I_ADDA_MICIN_GCTRL, SUN8I_ADDA_MICIN_GCTRL_MIC2G,
0x7, 0, sun8i_codec_out_mixer_pregain_scale),
/* Microphone Amp boost gain */
SOC_SINGLE_TLV("Mic2 Boost Volume", SUN8I_ADDA_MIC2G_CTRL,
SUN8I_ADDA_MIC2G_CTRL_MIC2BOOST, 0x7, 0,
sun8i_codec_mic_gain_scale),
};
static const struct snd_soc_dapm_widget sun8i_codec_mic2_widgets[] = {
/* Microphone input */
SND_SOC_DAPM_INPUT("MIC2"),
/* Mic input path */
SND_SOC_DAPM_PGA("Mic2 Amplifier", SUN8I_ADDA_MIC2G_CTRL,
SUN8I_ADDA_MIC2G_CTRL_MIC2AMPEN, 0, NULL, 0),
};
static const struct snd_soc_dapm_route sun8i_codec_mic2_routes[] = {
{ "Mic2 Amplifier", NULL, "MIC2"},
{ "Left Mixer", "Mic2 Playback Switch", "Mic2 Amplifier" },
{ "Right Mixer", "Mic2 Playback Switch", "Mic2 Amplifier" },
{ "Left ADC Mixer", "Mic2 Capture Switch", "Mic2 Amplifier" },
{ "Right ADC Mixer", "Mic2 Capture Switch", "Mic2 Amplifier" },
};
static int sun8i_codec_add_mic2(struct snd_soc_component *cmpnt)
{
struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(cmpnt);
struct device *dev = cmpnt->dev;
int ret;
ret = snd_soc_add_component_controls(cmpnt,
sun8i_codec_mic2_controls,
ARRAY_SIZE(sun8i_codec_mic2_controls));
if (ret) {
dev_err(dev, "Failed to add MIC2 controls: %d\n", ret);
return ret;
}
ret = snd_soc_dapm_new_controls(dapm, sun8i_codec_mic2_widgets,
ARRAY_SIZE(sun8i_codec_mic2_widgets));
if (ret) {
dev_err(dev, "Failed to add MIC2 DAPM widgets: %d\n", ret);
return ret;
}
ret = snd_soc_dapm_add_routes(dapm, sun8i_codec_mic2_routes,
ARRAY_SIZE(sun8i_codec_mic2_routes));
if (ret) {
dev_err(dev, "Failed to add MIC2 DAPM routes: %d\n", ret);
return ret;
}
return 0;
}
struct sun8i_codec_analog_quirks {
bool has_headphone;
bool has_hmic;
bool has_linein;
bool has_lineout;
bool has_mic2;
};
static const struct sun8i_codec_analog_quirks sun8i_a23_quirks = {
.has_headphone = true,
.has_hmic = true,
.has_linein = true,
.has_mic2 = true,
};
static const struct sun8i_codec_analog_quirks sun8i_h3_quirks = {
.has_linein = true,
.has_lineout = true,
.has_mic2 = true,
};
static int sun8i_codec_analog_cmpnt_probe(struct snd_soc_component *cmpnt)
......@@ -620,12 +722,24 @@ static int sun8i_codec_analog_cmpnt_probe(struct snd_soc_component *cmpnt)
return ret;
}
if (quirks->has_linein) {
ret = sun8i_codec_add_linein(cmpnt);
if (ret)
return ret;
}
if (quirks->has_lineout) {
ret = sun8i_codec_add_lineout(cmpnt);
if (ret)
return ret;
}
if (quirks->has_mic2) {
ret = sun8i_codec_add_mic2(cmpnt);
if (ret)
return ret;
}
return 0;
}
......
......@@ -290,12 +290,10 @@ static const struct snd_soc_dapm_widget sun8i_codec_dapm_widgets[] = {
SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0R_ENA, 0),
/* DAC Mixers */
SND_SOC_DAPM_MIXER("Left Digital DAC Mixer", SND_SOC_NOPM, 0, 0,
sun8i_dac_mixer_controls,
ARRAY_SIZE(sun8i_dac_mixer_controls)),
SND_SOC_DAPM_MIXER("Right Digital DAC Mixer", SND_SOC_NOPM, 0, 0,
sun8i_dac_mixer_controls,
ARRAY_SIZE(sun8i_dac_mixer_controls)),
SOC_MIXER_ARRAY("Left Digital DAC Mixer", SND_SOC_NOPM, 0, 0,
sun8i_dac_mixer_controls),
SOC_MIXER_ARRAY("Right Digital DAC Mixer", SND_SOC_NOPM, 0, 0,
sun8i_dac_mixer_controls),
/* Clocks */
SND_SOC_DAPM_SUPPLY("MODCLK AFI1", SUN8I_MOD_CLK_ENA,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment