Commit 88f18348 authored by Mark Brown's avatar Mark Brown

Merge remote-tracking branches 'asoc/topic/max98926', 'asoc/topic/mtk',...

Merge remote-tracking branches 'asoc/topic/max98926', 'asoc/topic/mtk', 'asoc/topic/mxs-saif', 'asoc/topic/nau8825' and 'asoc/topic/omap' into asoc-next
MT8173 with RT5650 RT5514 CODECS
Required properties:
- compatible : "mediatek,mt8173-rt5650-rt5514"
- mediatek,audio-codec: the phandles of rt5650 and rt5514 codecs
- mediatek,platform: the phandle of MT8173 ASoC platform
Example:
sound {
compatible = "mediatek,mt8173-rt5650-rt5514";
mediatek,audio-codec = <&rt5650 &rt5514>;
mediatek,platform = <&afe>;
};
MT8173 with RT5650 CODECS
Required properties:
- compatible : "mediatek,mt8173-rt5650"
- mediatek,audio-codec: the phandles of rt5650 codecs
- mediatek,platform: the phandle of MT8173 ASoC platform
Example:
sound {
compatible = "mediatek,mt8173-rt5650";
mediatek,audio-codec = <&rt5650>;
mediatek,platform = <&afe>;
};
......@@ -40,7 +40,7 @@ static const char *const max98926_hpf_cutoff_txt[] = {
"200Hz", "400Hz", "800Hz",
};
static struct reg_default max98926_reg[] = {
static const struct reg_default max98926_reg[] = {
{ 0x0B, 0x00 }, /* IRQ Enable0 */
{ 0x0C, 0x00 }, /* IRQ Enable1 */
{ 0x0D, 0x00 }, /* IRQ Enable2 */
......@@ -506,7 +506,7 @@ static struct snd_soc_codec_driver soc_codec_dev_max98926 = {
.num_dapm_widgets = ARRAY_SIZE(max98926_dapm_widgets),
};
static struct regmap_config max98926_regmap = {
static const struct regmap_config max98926_regmap = {
.reg_bits = 8,
.val_bits = 8,
.max_register = MAX98926_VERSION,
......
......@@ -84,6 +84,7 @@ static const struct nau8825_fll_attr fll_pre_scalar[] = {
static const struct reg_default nau8825_reg_defaults[] = {
{ NAU8825_REG_ENA_CTRL, 0x00ff },
{ NAU8825_REG_IIC_ADDR_SET, 0x0 },
{ NAU8825_REG_CLK_DIVIDER, 0x0050 },
{ NAU8825_REG_FLL1, 0x0 },
{ NAU8825_REG_FLL2, 0x3126 },
......@@ -158,8 +159,7 @@ static const struct reg_default nau8825_reg_defaults[] = {
static bool nau8825_readable_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
case NAU8825_REG_ENA_CTRL:
case NAU8825_REG_CLK_DIVIDER ... NAU8825_REG_FLL_VCO_RSV:
case NAU8825_REG_ENA_CTRL ... NAU8825_REG_FLL_VCO_RSV:
case NAU8825_REG_HSD_CTRL ... NAU8825_REG_JACK_DET_CTRL:
case NAU8825_REG_INTERRUPT_MASK ... NAU8825_REG_KEYDET_CTRL:
case NAU8825_REG_VDET_THRESHOLD_1 ... NAU8825_REG_DACR_CTRL:
......@@ -184,8 +184,7 @@ static bool nau8825_readable_reg(struct device *dev, unsigned int reg)
static bool nau8825_writeable_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
case NAU8825_REG_RESET ... NAU8825_REG_ENA_CTRL:
case NAU8825_REG_CLK_DIVIDER ... NAU8825_REG_FLL_VCO_RSV:
case NAU8825_REG_RESET ... NAU8825_REG_FLL_VCO_RSV:
case NAU8825_REG_HSD_CTRL ... NAU8825_REG_JACK_DET_CTRL:
case NAU8825_REG_INTERRUPT_MASK:
case NAU8825_REG_INT_CLR_KEY_STATUS ... NAU8825_REG_KEYDET_CTRL:
......@@ -227,10 +226,42 @@ static bool nau8825_volatile_reg(struct device *dev, unsigned int reg)
static int nau8825_pump_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct nau8825 *nau8825 = snd_soc_codec_get_drvdata(codec);
switch (event) {
case SND_SOC_DAPM_POST_PMU:
/* Prevent startup click by letting charge pump to ramp up */
msleep(10);
regmap_update_bits(nau8825->regmap, NAU8825_REG_CHARGE_PUMP,
NAU8825_JAMNODCLOW, NAU8825_JAMNODCLOW);
break;
case SND_SOC_DAPM_PRE_PMD:
regmap_update_bits(nau8825->regmap, NAU8825_REG_CHARGE_PUMP,
NAU8825_JAMNODCLOW, 0);
break;
default:
return -EINVAL;
}
return 0;
}
static int nau8825_output_dac_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct nau8825 *nau8825 = snd_soc_codec_get_drvdata(codec);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
/* Disables the TESTDAC to let DAC signal pass through. */
regmap_update_bits(nau8825->regmap, NAU8825_REG_BIAS_ADJ,
NAU8825_BIAS_TESTDAC_EN, 0);
break;
case SND_SOC_DAPM_POST_PMD:
regmap_update_bits(nau8825->regmap, NAU8825_REG_BIAS_ADJ,
NAU8825_BIAS_TESTDAC_EN, NAU8825_BIAS_TESTDAC_EN);
break;
default:
return -EINVAL;
......@@ -316,10 +347,10 @@ static const struct snd_soc_dapm_widget nau8825_dapm_widgets[] = {
SND_SOC_DAPM_ADC("SAR", NULL, NAU8825_REG_SAR_CTRL,
NAU8825_SAR_ADC_EN_SFT, 0),
SND_SOC_DAPM_DAC("ADACL", NULL, NAU8825_REG_RDAC, 12, 0),
SND_SOC_DAPM_DAC("ADACR", NULL, NAU8825_REG_RDAC, 13, 0),
SND_SOC_DAPM_SUPPLY("ADACL Clock", NAU8825_REG_RDAC, 8, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("ADACR Clock", NAU8825_REG_RDAC, 9, 0, NULL, 0),
SND_SOC_DAPM_PGA_S("ADACL", 2, NAU8825_REG_RDAC, 12, 0, NULL, 0),
SND_SOC_DAPM_PGA_S("ADACR", 2, NAU8825_REG_RDAC, 13, 0, NULL, 0),
SND_SOC_DAPM_PGA_S("ADACL Clock", 3, NAU8825_REG_RDAC, 8, 0, NULL, 0),
SND_SOC_DAPM_PGA_S("ADACR Clock", 3, NAU8825_REG_RDAC, 9, 0, NULL, 0),
SND_SOC_DAPM_DAC("DDACR", NULL, NAU8825_REG_ENA_CTRL,
NAU8825_ENABLE_DACR_SFT, 0),
......@@ -330,29 +361,48 @@ static const struct snd_soc_dapm_widget nau8825_dapm_widgets[] = {
SND_SOC_DAPM_MUX("DACL Mux", SND_SOC_NOPM, 0, 0, &nau8825_dacl_mux),
SND_SOC_DAPM_MUX("DACR Mux", SND_SOC_NOPM, 0, 0, &nau8825_dacr_mux),
SND_SOC_DAPM_PGA("HP amp L", NAU8825_REG_CLASSG_CTRL, 1, 0, NULL, 0),
SND_SOC_DAPM_PGA("HP amp R", NAU8825_REG_CLASSG_CTRL, 2, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("HP amp power", NAU8825_REG_CLASSG_CTRL, 0, 0, NULL,
0),
SND_SOC_DAPM_PGA_S("HP amp L", 0,
NAU8825_REG_CLASSG_CTRL, 1, 0, NULL, 0),
SND_SOC_DAPM_PGA_S("HP amp R", 0,
NAU8825_REG_CLASSG_CTRL, 2, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("Charge Pump", NAU8825_REG_CHARGE_PUMP, 5, 0,
nau8825_pump_event, SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PGA_S("Charge Pump", 1, NAU8825_REG_CHARGE_PUMP, 5, 0,
nau8825_pump_event, SND_SOC_DAPM_POST_PMU |
SND_SOC_DAPM_PRE_PMD),
SND_SOC_DAPM_PGA("Output Driver R Stage 1",
SND_SOC_DAPM_PGA_S("Output Driver R Stage 1", 4,
NAU8825_REG_POWER_UP_CONTROL, 5, 0, NULL, 0),
SND_SOC_DAPM_PGA("Output Driver L Stage 1",
SND_SOC_DAPM_PGA_S("Output Driver L Stage 1", 4,
NAU8825_REG_POWER_UP_CONTROL, 4, 0, NULL, 0),
SND_SOC_DAPM_PGA("Output Driver R Stage 2",
SND_SOC_DAPM_PGA_S("Output Driver R Stage 2", 5,
NAU8825_REG_POWER_UP_CONTROL, 3, 0, NULL, 0),
SND_SOC_DAPM_PGA("Output Driver L Stage 2",
SND_SOC_DAPM_PGA_S("Output Driver L Stage 2", 5,
NAU8825_REG_POWER_UP_CONTROL, 2, 0, NULL, 0),
SND_SOC_DAPM_PGA_S("Output Driver R Stage 3", 1,
SND_SOC_DAPM_PGA_S("Output Driver R Stage 3", 6,
NAU8825_REG_POWER_UP_CONTROL, 1, 0, NULL, 0),
SND_SOC_DAPM_PGA_S("Output Driver L Stage 3", 1,
SND_SOC_DAPM_PGA_S("Output Driver L Stage 3", 6,
NAU8825_REG_POWER_UP_CONTROL, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA_S("Output DACL", 2, NAU8825_REG_CHARGE_PUMP, 8, 1, NULL, 0),
SND_SOC_DAPM_PGA_S("Output DACR", 2, NAU8825_REG_CHARGE_PUMP, 9, 1, NULL, 0),
SND_SOC_DAPM_PGA_S("Output DACL", 7,
NAU8825_REG_CHARGE_PUMP, 8, 1, nau8825_output_dac_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_PGA_S("Output DACR", 7,
NAU8825_REG_CHARGE_PUMP, 9, 1, nau8825_output_dac_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
/* HPOL/R are ungrounded by disabling 16 Ohm pull-downs on playback */
SND_SOC_DAPM_PGA_S("HPOL Pulldown", 8,
NAU8825_REG_HSD_CTRL, 0, 1, NULL, 0),
SND_SOC_DAPM_PGA_S("HPOR Pulldown", 8,
NAU8825_REG_HSD_CTRL, 1, 1, NULL, 0),
/* High current HPOL/R boost driver */
SND_SOC_DAPM_PGA_S("HP Boost Driver", 9,
NAU8825_REG_BOOST, 9, 1, NULL, 0),
/* Class G operation control*/
SND_SOC_DAPM_PGA_S("Class G", 10,
NAU8825_REG_CLASSG_CTRL, 0, 0, NULL, 0),
SND_SOC_DAPM_OUTPUT("HPOL"),
SND_SOC_DAPM_OUTPUT("HPOR"),
......@@ -375,24 +425,27 @@ static const struct snd_soc_dapm_route nau8825_dapm_routes[] = {
{"DACR Mux", "DACR", "DDACR"},
{"HP amp L", NULL, "DACL Mux"},
{"HP amp R", NULL, "DACR Mux"},
{"HP amp L", NULL, "HP amp power"},
{"HP amp R", NULL, "HP amp power"},
{"ADACL", NULL, "HP amp L"},
{"ADACR", NULL, "HP amp R"},
{"ADACL", NULL, "ADACL Clock"},
{"ADACR", NULL, "ADACR Clock"},
{"Output Driver L Stage 1", NULL, "ADACL"},
{"Output Driver R Stage 1", NULL, "ADACR"},
{"Charge Pump", NULL, "HP amp L"},
{"Charge Pump", NULL, "HP amp R"},
{"ADACL", NULL, "Charge Pump"},
{"ADACR", NULL, "Charge Pump"},
{"ADACL Clock", NULL, "ADACL"},
{"ADACR Clock", NULL, "ADACR"},
{"Output Driver L Stage 1", NULL, "ADACL Clock"},
{"Output Driver R Stage 1", NULL, "ADACR Clock"},
{"Output Driver L Stage 2", NULL, "Output Driver L Stage 1"},
{"Output Driver R Stage 2", NULL, "Output Driver R Stage 1"},
{"Output Driver L Stage 3", NULL, "Output Driver L Stage 2"},
{"Output Driver R Stage 3", NULL, "Output Driver R Stage 2"},
{"Output DACL", NULL, "Output Driver L Stage 3"},
{"Output DACR", NULL, "Output Driver R Stage 3"},
{"HPOL", NULL, "Output DACL"},
{"HPOR", NULL, "Output DACR"},
{"HPOL", NULL, "Charge Pump"},
{"HPOR", NULL, "Charge Pump"},
{"HPOL Pulldown", NULL, "Output DACL"},
{"HPOR Pulldown", NULL, "Output DACR"},
{"HP Boost Driver", NULL, "HPOL Pulldown"},
{"HP Boost Driver", NULL, "HPOR Pulldown"},
{"Class G", NULL, "HP Boost Driver"},
{"HPOL", NULL, "Class G"},
{"HPOR", NULL, "Class G"},
};
static int nau8825_hw_params(struct snd_pcm_substream *substream,
......@@ -659,11 +712,10 @@ static int nau8825_jack_insert(struct nau8825 *nau8825)
break;
}
if (type & SND_JACK_HEADPHONE) {
/* Unground HPL/R */
regmap_update_bits(regmap, NAU8825_REG_HSD_CTRL, 0x3, 0);
}
/* Leaving HPOL/R grounded after jack insert by default. They will be
* ungrounded as part of the widget power up sequence at the beginning
* of playback to reduce pop.
*/
return type;
}
......@@ -768,6 +820,8 @@ static void nau8825_init_regs(struct nau8825 *nau8825)
{
struct regmap *regmap = nau8825->regmap;
/* Latch IIC LSB value */
regmap_write(regmap, NAU8825_REG_IIC_ADDR_SET, 0x0001);
/* Enable Bias/Vmid */
regmap_update_bits(nau8825->regmap, NAU8825_REG_BIAS_ADJ,
NAU8825_BIAS_VMID, NAU8825_BIAS_VMID);
......@@ -780,10 +834,10 @@ static void nau8825_init_regs(struct nau8825 *nau8825)
nau8825->vref_impedance << NAU8825_BIAS_VMID_SEL_SFT);
/* Disable Boost Driver, Automatic Short circuit protection enable */
regmap_update_bits(regmap, NAU8825_REG_BOOST,
NAU8825_PRECHARGE_DIS | NAU8825_HP_BOOST_G_DIS |
NAU8825_SHORT_SHUTDOWN_EN,
NAU8825_PRECHARGE_DIS | NAU8825_HP_BOOST_G_DIS |
NAU8825_SHORT_SHUTDOWN_EN);
NAU8825_PRECHARGE_DIS | NAU8825_HP_BOOST_DIS |
NAU8825_HP_BOOST_G_DIS | NAU8825_SHORT_SHUTDOWN_EN,
NAU8825_PRECHARGE_DIS | NAU8825_HP_BOOST_DIS |
NAU8825_HP_BOOST_G_DIS | NAU8825_SHORT_SHUTDOWN_EN);
regmap_update_bits(regmap, NAU8825_REG_GPIO12_CTRL,
NAU8825_JKDET_OUTPUT_EN,
......@@ -822,6 +876,35 @@ static void nau8825_init_regs(struct nau8825 *nau8825)
NAU8825_ADC_SYNC_DOWN_MASK, NAU8825_ADC_SYNC_DOWN_128);
regmap_update_bits(regmap, NAU8825_REG_DAC_CTRL1,
NAU8825_DAC_OVERSAMPLE_MASK, NAU8825_DAC_OVERSAMPLE_128);
/* Disable DACR/L power */
regmap_update_bits(regmap, NAU8825_REG_CHARGE_PUMP,
NAU8825_POWER_DOWN_DACR | NAU8825_POWER_DOWN_DACL,
NAU8825_POWER_DOWN_DACR | NAU8825_POWER_DOWN_DACL);
/* Enable TESTDAC. This sets the analog DAC inputs to a '0' input
* signal to avoid any glitches due to power up transients in both
* the analog and digital DAC circuit.
*/
regmap_update_bits(nau8825->regmap, NAU8825_REG_BIAS_ADJ,
NAU8825_BIAS_TESTDAC_EN, NAU8825_BIAS_TESTDAC_EN);
/* CICCLP off */
regmap_update_bits(regmap, NAU8825_REG_DAC_CTRL1,
NAU8825_DAC_CLIP_OFF, NAU8825_DAC_CLIP_OFF);
/* Class AB bias current to 2x, DAC Capacitor enable MSB/LSB */
regmap_update_bits(regmap, NAU8825_REG_ANALOG_CONTROL_2,
NAU8825_HP_NON_CLASSG_CURRENT_2xADJ |
NAU8825_DAC_CAPACITOR_MSB | NAU8825_DAC_CAPACITOR_LSB,
NAU8825_HP_NON_CLASSG_CURRENT_2xADJ |
NAU8825_DAC_CAPACITOR_MSB | NAU8825_DAC_CAPACITOR_LSB);
/* Class G timer 64ms */
regmap_update_bits(regmap, NAU8825_REG_CLASSG_CTRL,
NAU8825_CLASSG_TIMER_MASK,
0x20 << NAU8825_CLASSG_TIMER_SFT);
/* DAC clock delay 2ns, VREF */
regmap_update_bits(regmap, NAU8825_REG_RDAC,
NAU8825_RDAC_CLK_DELAY_MASK | NAU8825_RDAC_VREF_MASK,
(0x2 << NAU8825_RDAC_CLK_DELAY_SFT) |
(0x3 << NAU8825_RDAC_VREF_SFT));
}
static const struct regmap_config nau8825_regmap_config = {
......
......@@ -14,6 +14,7 @@
#define NAU8825_REG_RESET 0x00
#define NAU8825_REG_ENA_CTRL 0x01
#define NAU8825_REG_IIC_ADDR_SET 0x02
#define NAU8825_REG_CLK_DIVIDER 0x03
#define NAU8825_REG_FLL1 0x04
#define NAU8825_REG_FLL2 0x05
......@@ -129,7 +130,7 @@
/* HSD_CTRL (0xc) */
#define NAU8825_HSD_AUTO_MODE (1 << 6)
/* 0 - short to GND, 1 - open */
/* 0 - open, 1 - short to GND */
#define NAU8825_SPKR_DWN1R (1 << 1)
#define NAU8825_SPKR_DWN1L (1 << 0)
......@@ -251,12 +252,18 @@
/* DACR_CTRL (0x34) */
#define NAU8825_DACR_CH_SEL_SFT 9
/* CLASSG_CTRL (0x50) */
#define NAU8825_CLASSG_TIMER_SFT 8
#define NAU8825_CLASSG_TIMER_MASK (0x3f << NAU8825_CLASSG_TIMER_SFT)
#define NAU8825_CLASSG_EN (1 << 0)
/* I2C_DEVICE_ID (0x58) */
#define NAU8825_GPIO2JD1 (1 << 7)
#define NAU8825_SOFTWARE_ID_MASK 0x3
#define NAU8825_SOFTWARE_ID_NAU8825 0x0
/* BIAS_ADJ (0x66) */
#define NAU8825_BIAS_TESTDAC_EN (0x3 << 8)
#define NAU8825_BIAS_VMID (1 << 6)
#define NAU8825_BIAS_VMID_SEL_SFT 4
#define NAU8825_BIAS_VMID_SEL_MASK (3 << NAU8825_BIAS_VMID_SEL_SFT)
......@@ -274,6 +281,12 @@
#define NAU8825_ADC_VREFSEL_VMID_PLUS_1DB (3 << 8)
#define NAU8825_POWERUP_ADCL (1 << 6)
/* RDAC (0x73) */
#define NAU8825_RDAC_CLK_DELAY_SFT 4
#define NAU8825_RDAC_CLK_DELAY_MASK (0x7 << NAU8825_RDAC_CLK_DELAY_SFT)
#define NAU8825_RDAC_VREF_SFT 2
#define NAU8825_RDAC_VREF_MASK (0x3 << NAU8825_RDAC_VREF_SFT)
/* MIC_BIAS (0x74) */
#define NAU8825_MICBIAS_JKSLV (1 << 14)
#define NAU8825_MICBIAS_JKR2 (1 << 12)
......@@ -284,6 +297,7 @@
/* BOOST (0x76) */
#define NAU8825_PRECHARGE_DIS (1 << 13)
#define NAU8825_GLOBAL_BIAS_EN (1 << 12)
#define NAU8825_HP_BOOST_DIS (1 << 9)
#define NAU8825_HP_BOOST_G_DIS (1 << 8)
#define NAU8825_SHORT_SHUTDOWN_EN (1 << 6)
......
......@@ -17,6 +17,27 @@ config SND_SOC_MT8173_MAX98090
Select Y if you have such device.
If unsure select "N".
config SND_SOC_MT8173_RT5650
tristate "ASoC Audio driver for MT8173 with RT5650 codec"
depends on SND_SOC_MEDIATEK && I2C
select SND_SOC_RT5645
help
This adds ASoC driver for Mediatek MT8173 boards
with the RT5650 audio codec.
Select Y if you have such device.
If unsure select "N".
config SND_SOC_MT8173_RT5650_RT5514
tristate "ASoC Audio driver for MT8173 with RT5650 RT5514 codecs"
depends on SND_SOC_MEDIATEK && I2C
select SND_SOC_RT5645
select SND_SOC_RT5514
help
This adds ASoC driver for Mediatek MT8173 boards
with the RT5650 and RT5514 codecs.
Select Y if you have such device.
If unsure select "N".
config SND_SOC_MT8173_RT5650_RT5676
tristate "ASoC Audio driver for MT8173 with RT5650 RT5676 codecs"
depends on SND_SOC_MEDIATEK && I2C
......@@ -27,4 +48,3 @@ config SND_SOC_MT8173_RT5650_RT5676
with the RT5650 and RT5676 codecs.
Select Y if you have such device.
If unsure select "N".
......@@ -2,4 +2,6 @@
obj-$(CONFIG_SND_SOC_MEDIATEK) += mtk-afe-pcm.o
# Machine support
obj-$(CONFIG_SND_SOC_MT8173_MAX98090) += mt8173-max98090.o
obj-$(CONFIG_SND_SOC_MT8173_RT5650) += mt8173-rt5650.o
obj-$(CONFIG_SND_SOC_MT8173_RT5650_RT5514) += mt8173-rt5650-rt5514.o
obj-$(CONFIG_SND_SOC_MT8173_RT5650_RT5676) += mt8173-rt5650-rt5676.o
/*
* mt8173-rt5650-rt5514.c -- MT8173 machine driver with RT5650/5514 codecs
*
* Copyright (c) 2016 MediaTek Inc.
* Author: Koro Chen <koro.chen@mediatek.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only 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/module.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <sound/soc.h>
#include <sound/jack.h>
#include "../codecs/rt5645.h"
#define MCLK_FOR_CODECS 12288000
static const struct snd_soc_dapm_widget mt8173_rt5650_rt5514_widgets[] = {
SND_SOC_DAPM_SPK("Speaker", NULL),
SND_SOC_DAPM_MIC("Int Mic", NULL),
SND_SOC_DAPM_HP("Headphone", NULL),
SND_SOC_DAPM_MIC("Headset Mic", NULL),
};
static const struct snd_soc_dapm_route mt8173_rt5650_rt5514_routes[] = {
{"Speaker", NULL, "SPOL"},
{"Speaker", NULL, "SPOR"},
{"Sub DMIC1L", NULL, "Int Mic"},
{"Sub DMIC1R", NULL, "Int Mic"},
{"Headphone", NULL, "HPOL"},
{"Headphone", NULL, "HPOR"},
{"Headset Mic", NULL, "micbias1"},
{"Headset Mic", NULL, "micbias2"},
{"IN1P", NULL, "Headset Mic"},
{"IN1N", NULL, "Headset Mic"},
};
static const struct snd_kcontrol_new mt8173_rt5650_rt5514_controls[] = {
SOC_DAPM_PIN_SWITCH("Speaker"),
SOC_DAPM_PIN_SWITCH("Int Mic"),
SOC_DAPM_PIN_SWITCH("Headphone"),
SOC_DAPM_PIN_SWITCH("Headset Mic"),
};
static int mt8173_rt5650_rt5514_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
int i, ret;
for (i = 0; i < rtd->num_codecs; i++) {
struct snd_soc_dai *codec_dai = rtd->codec_dais[i];
/* pll from mclk 12.288M */
ret = snd_soc_dai_set_pll(codec_dai, 0, 0, MCLK_FOR_CODECS,
params_rate(params) * 512);
if (ret)
return ret;
/* sysclk from pll */
ret = snd_soc_dai_set_sysclk(codec_dai, 1,
params_rate(params) * 512,
SND_SOC_CLOCK_IN);
if (ret)
return ret;
}
return 0;
}
static struct snd_soc_ops mt8173_rt5650_rt5514_ops = {
.hw_params = mt8173_rt5650_rt5514_hw_params,
};
static struct snd_soc_jack mt8173_rt5650_rt5514_jack;
static int mt8173_rt5650_rt5514_init(struct snd_soc_pcm_runtime *runtime)
{
struct snd_soc_card *card = runtime->card;
struct snd_soc_codec *codec = runtime->codec_dais[0]->codec;
int ret;
rt5645_sel_asrc_clk_src(codec,
RT5645_DA_STEREO_FILTER |
RT5645_AD_STEREO_FILTER,
RT5645_CLK_SEL_I2S1_ASRC);
/* enable jack detection */
ret = snd_soc_card_jack_new(card, "Headset Jack",
SND_JACK_HEADPHONE | SND_JACK_MICROPHONE |
SND_JACK_BTN_0 | SND_JACK_BTN_1 |
SND_JACK_BTN_2 | SND_JACK_BTN_3,
&mt8173_rt5650_rt5514_jack, NULL, 0);
if (ret) {
dev_err(card->dev, "Can't new Headset Jack %d\n", ret);
return ret;
}
return rt5645_set_jack_detect(codec,
&mt8173_rt5650_rt5514_jack,
&mt8173_rt5650_rt5514_jack,
&mt8173_rt5650_rt5514_jack);
}
static struct snd_soc_dai_link_component mt8173_rt5650_rt5514_codecs[] = {
{
.dai_name = "rt5645-aif1",
},
{
.dai_name = "rt5514-aif1",
},
};
enum {
DAI_LINK_PLAYBACK,
DAI_LINK_CAPTURE,
DAI_LINK_CODEC_I2S,
};
/* Digital audio interface glue - connects codec <---> CPU */
static struct snd_soc_dai_link mt8173_rt5650_rt5514_dais[] = {
/* Front End DAI links */
[DAI_LINK_PLAYBACK] = {
.name = "rt5650_rt5514 Playback",
.stream_name = "rt5650_rt5514 Playback",
.cpu_dai_name = "DL1",
.codec_name = "snd-soc-dummy",
.codec_dai_name = "snd-soc-dummy-dai",
.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
.dynamic = 1,
.dpcm_playback = 1,
},
[DAI_LINK_CAPTURE] = {
.name = "rt5650_rt5514 Capture",
.stream_name = "rt5650_rt5514 Capture",
.cpu_dai_name = "VUL",
.codec_name = "snd-soc-dummy",
.codec_dai_name = "snd-soc-dummy-dai",
.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
.dynamic = 1,
.dpcm_capture = 1,
},
/* Back End DAI links */
[DAI_LINK_CODEC_I2S] = {
.name = "Codec",
.cpu_dai_name = "I2S",
.no_pcm = 1,
.codecs = mt8173_rt5650_rt5514_codecs,
.num_codecs = 2,
.init = mt8173_rt5650_rt5514_init,
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBS_CFS,
.ops = &mt8173_rt5650_rt5514_ops,
.ignore_pmdown_time = 1,
.dpcm_playback = 1,
.dpcm_capture = 1,
},
};
static struct snd_soc_codec_conf mt8173_rt5650_rt5514_codec_conf[] = {
{
.name_prefix = "Sub",
},
};
static struct snd_soc_card mt8173_rt5650_rt5514_card = {
.name = "mtk-rt5650-rt5514",
.owner = THIS_MODULE,
.dai_link = mt8173_rt5650_rt5514_dais,
.num_links = ARRAY_SIZE(mt8173_rt5650_rt5514_dais),
.codec_conf = mt8173_rt5650_rt5514_codec_conf,
.num_configs = ARRAY_SIZE(mt8173_rt5650_rt5514_codec_conf),
.controls = mt8173_rt5650_rt5514_controls,
.num_controls = ARRAY_SIZE(mt8173_rt5650_rt5514_controls),
.dapm_widgets = mt8173_rt5650_rt5514_widgets,
.num_dapm_widgets = ARRAY_SIZE(mt8173_rt5650_rt5514_widgets),
.dapm_routes = mt8173_rt5650_rt5514_routes,
.num_dapm_routes = ARRAY_SIZE(mt8173_rt5650_rt5514_routes),
};
static int mt8173_rt5650_rt5514_dev_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = &mt8173_rt5650_rt5514_card;
struct device_node *platform_node;
int i, ret;
platform_node = of_parse_phandle(pdev->dev.of_node,
"mediatek,platform", 0);
if (!platform_node) {
dev_err(&pdev->dev, "Property 'platform' missing or invalid\n");
return -EINVAL;
}
for (i = 0; i < card->num_links; i++) {
if (mt8173_rt5650_rt5514_dais[i].platform_name)
continue;
mt8173_rt5650_rt5514_dais[i].platform_of_node = platform_node;
}
mt8173_rt5650_rt5514_codecs[0].of_node =
of_parse_phandle(pdev->dev.of_node, "mediatek,audio-codec", 0);
if (!mt8173_rt5650_rt5514_codecs[0].of_node) {
dev_err(&pdev->dev,
"Property 'audio-codec' missing or invalid\n");
return -EINVAL;
}
mt8173_rt5650_rt5514_codecs[1].of_node =
of_parse_phandle(pdev->dev.of_node, "mediatek,audio-codec", 1);
if (!mt8173_rt5650_rt5514_codecs[1].of_node) {
dev_err(&pdev->dev,
"Property 'audio-codec' missing or invalid\n");
return -EINVAL;
}
mt8173_rt5650_rt5514_codec_conf[0].of_node =
mt8173_rt5650_rt5514_codecs[1].of_node;
card->dev = &pdev->dev;
platform_set_drvdata(pdev, card);
ret = devm_snd_soc_register_card(&pdev->dev, card);
if (ret)
dev_err(&pdev->dev, "%s snd_soc_register_card fail %d\n",
__func__, ret);
return ret;
}
static const struct of_device_id mt8173_rt5650_rt5514_dt_match[] = {
{ .compatible = "mediatek,mt8173-rt5650-rt5514", },
{ }
};
MODULE_DEVICE_TABLE(of, mt8173_rt5650_rt5514_dt_match);
static struct platform_driver mt8173_rt5650_rt5514_driver = {
.driver = {
.name = "mtk-rt5650-rt5514",
.of_match_table = mt8173_rt5650_rt5514_dt_match,
#ifdef CONFIG_PM
.pm = &snd_soc_pm_ops,
#endif
},
.probe = mt8173_rt5650_rt5514_dev_probe,
};
module_platform_driver(mt8173_rt5650_rt5514_driver);
/* Module information */
MODULE_DESCRIPTION("MT8173 RT5650 and RT5514 SoC machine driver");
MODULE_AUTHOR("Koro Chen <koro.chen@mediatek.com>");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:mtk-rt5650-rt5514");
......@@ -131,10 +131,17 @@ static struct snd_soc_dai_link_component mt8173_rt5650_rt5676_codecs[] = {
},
};
enum {
DAI_LINK_PLAYBACK,
DAI_LINK_CAPTURE,
DAI_LINK_CODEC_I2S,
DAI_LINK_INTERCODEC
};
/* Digital audio interface glue - connects codec <---> CPU */
static struct snd_soc_dai_link mt8173_rt5650_rt5676_dais[] = {
/* Front End DAI links */
{
[DAI_LINK_PLAYBACK] = {
.name = "rt5650_rt5676 Playback",
.stream_name = "rt5650_rt5676 Playback",
.cpu_dai_name = "DL1",
......@@ -144,7 +151,7 @@ static struct snd_soc_dai_link mt8173_rt5650_rt5676_dais[] = {
.dynamic = 1,
.dpcm_playback = 1,
},
{
[DAI_LINK_CAPTURE] = {
.name = "rt5650_rt5676 Capture",
.stream_name = "rt5650_rt5676 Capture",
.cpu_dai_name = "VUL",
......@@ -156,7 +163,7 @@ static struct snd_soc_dai_link mt8173_rt5650_rt5676_dais[] = {
},
/* Back End DAI links */
{
[DAI_LINK_CODEC_I2S] = {
.name = "Codec",
.cpu_dai_name = "I2S",
.no_pcm = 1,
......@@ -170,7 +177,8 @@ static struct snd_soc_dai_link mt8173_rt5650_rt5676_dais[] = {
.dpcm_playback = 1,
.dpcm_capture = 1,
},
{ /* rt5676 <-> rt5650 intercodec link: Sets rt5676 I2S2 as master */
/* rt5676 <-> rt5650 intercodec link: Sets rt5676 I2S2 as master */
[DAI_LINK_INTERCODEC] = {
.name = "rt5650_rt5676 intercodec",
.stream_name = "rt5650_rt5676 intercodec",
.cpu_dai_name = "snd-soc-dummy-dai",
......@@ -240,7 +248,7 @@ static int mt8173_rt5650_rt5676_dev_probe(struct platform_device *pdev)
mt8173_rt5650_rt5676_codec_conf[0].of_node =
mt8173_rt5650_rt5676_codecs[1].of_node;
mt8173_rt5650_rt5676_dais[3].codec_of_node =
mt8173_rt5650_rt5676_dais[DAI_LINK_INTERCODEC].codec_of_node =
mt8173_rt5650_rt5676_codecs[1].of_node;
card->dev = &pdev->dev;
......
/*
* mt8173-rt5650.c -- MT8173 machine driver with RT5650 codecs
*
* Copyright (c) 2016 MediaTek Inc.
* Author: Koro Chen <koro.chen@mediatek.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only 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/module.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <sound/soc.h>
#include <sound/jack.h>
#include "../codecs/rt5645.h"
#define MCLK_FOR_CODECS 12288000
static const struct snd_soc_dapm_widget mt8173_rt5650_widgets[] = {
SND_SOC_DAPM_SPK("Speaker", NULL),
SND_SOC_DAPM_MIC("Int Mic", NULL),
SND_SOC_DAPM_HP("Headphone", NULL),
SND_SOC_DAPM_MIC("Headset Mic", NULL),
};
static const struct snd_soc_dapm_route mt8173_rt5650_routes[] = {
{"Speaker", NULL, "SPOL"},
{"Speaker", NULL, "SPOR"},
{"DMIC L1", NULL, "Int Mic"},
{"DMIC R1", NULL, "Int Mic"},
{"Headphone", NULL, "HPOL"},
{"Headphone", NULL, "HPOR"},
{"Headset Mic", NULL, "micbias1"},
{"Headset Mic", NULL, "micbias2"},
{"IN1P", NULL, "Headset Mic"},
{"IN1N", NULL, "Headset Mic"},
};
static const struct snd_kcontrol_new mt8173_rt5650_controls[] = {
SOC_DAPM_PIN_SWITCH("Speaker"),
SOC_DAPM_PIN_SWITCH("Int Mic"),
SOC_DAPM_PIN_SWITCH("Headphone"),
SOC_DAPM_PIN_SWITCH("Headset Mic"),
};
static int mt8173_rt5650_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
int i, ret;
for (i = 0; i < rtd->num_codecs; i++) {
struct snd_soc_dai *codec_dai = rtd->codec_dais[i];
/* pll from mclk 12.288M */
ret = snd_soc_dai_set_pll(codec_dai, 0, 0, MCLK_FOR_CODECS,
params_rate(params) * 512);
if (ret)
return ret;
/* sysclk from pll */
ret = snd_soc_dai_set_sysclk(codec_dai, 1,
params_rate(params) * 512,
SND_SOC_CLOCK_IN);
if (ret)
return ret;
}
return 0;
}
static struct snd_soc_ops mt8173_rt5650_ops = {
.hw_params = mt8173_rt5650_hw_params,
};
static struct snd_soc_jack mt8173_rt5650_jack;
static int mt8173_rt5650_init(struct snd_soc_pcm_runtime *runtime)
{
struct snd_soc_card *card = runtime->card;
struct snd_soc_codec *codec = runtime->codec_dais[0]->codec;
int ret;
rt5645_sel_asrc_clk_src(codec,
RT5645_DA_STEREO_FILTER |
RT5645_AD_STEREO_FILTER,
RT5645_CLK_SEL_I2S1_ASRC);
/* enable jack detection */
ret = snd_soc_card_jack_new(card, "Headset Jack",
SND_JACK_HEADPHONE | SND_JACK_MICROPHONE |
SND_JACK_BTN_0 | SND_JACK_BTN_1 |
SND_JACK_BTN_2 | SND_JACK_BTN_3,
&mt8173_rt5650_jack, NULL, 0);
if (ret) {
dev_err(card->dev, "Can't new Headset Jack %d\n", ret);
return ret;
}
return rt5645_set_jack_detect(codec,
&mt8173_rt5650_jack,
&mt8173_rt5650_jack,
&mt8173_rt5650_jack);
}
static struct snd_soc_dai_link_component mt8173_rt5650_codecs[] = {
{
.dai_name = "rt5645-aif1",
},
};
enum {
DAI_LINK_PLAYBACK,
DAI_LINK_CAPTURE,
DAI_LINK_CODEC_I2S,
};
/* Digital audio interface glue - connects codec <---> CPU */
static struct snd_soc_dai_link mt8173_rt5650_dais[] = {
/* Front End DAI links */
[DAI_LINK_PLAYBACK] = {
.name = "rt5650 Playback",
.stream_name = "rt5650 Playback",
.cpu_dai_name = "DL1",
.codec_name = "snd-soc-dummy",
.codec_dai_name = "snd-soc-dummy-dai",
.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
.dynamic = 1,
.dpcm_playback = 1,
},
[DAI_LINK_CAPTURE] = {
.name = "rt5650 Capture",
.stream_name = "rt5650 Capture",
.cpu_dai_name = "VUL",
.codec_name = "snd-soc-dummy",
.codec_dai_name = "snd-soc-dummy-dai",
.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
.dynamic = 1,
.dpcm_capture = 1,
},
/* Back End DAI links */
[DAI_LINK_CODEC_I2S] = {
.name = "Codec",
.cpu_dai_name = "I2S",
.no_pcm = 1,
.codecs = mt8173_rt5650_codecs,
.num_codecs = 1,
.init = mt8173_rt5650_init,
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBS_CFS,
.ops = &mt8173_rt5650_ops,
.ignore_pmdown_time = 1,
.dpcm_playback = 1,
.dpcm_capture = 1,
},
};
static struct snd_soc_card mt8173_rt5650_card = {
.name = "mtk-rt5650",
.owner = THIS_MODULE,
.dai_link = mt8173_rt5650_dais,
.num_links = ARRAY_SIZE(mt8173_rt5650_dais),
.controls = mt8173_rt5650_controls,
.num_controls = ARRAY_SIZE(mt8173_rt5650_controls),
.dapm_widgets = mt8173_rt5650_widgets,
.num_dapm_widgets = ARRAY_SIZE(mt8173_rt5650_widgets),
.dapm_routes = mt8173_rt5650_routes,
.num_dapm_routes = ARRAY_SIZE(mt8173_rt5650_routes),
};
static int mt8173_rt5650_dev_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = &mt8173_rt5650_card;
struct device_node *platform_node;
int i, ret;
platform_node = of_parse_phandle(pdev->dev.of_node,
"mediatek,platform", 0);
if (!platform_node) {
dev_err(&pdev->dev, "Property 'platform' missing or invalid\n");
return -EINVAL;
}
for (i = 0; i < card->num_links; i++) {
if (mt8173_rt5650_dais[i].platform_name)
continue;
mt8173_rt5650_dais[i].platform_of_node = platform_node;
}
mt8173_rt5650_codecs[0].of_node =
of_parse_phandle(pdev->dev.of_node, "mediatek,audio-codec", 0);
if (!mt8173_rt5650_codecs[0].of_node) {
dev_err(&pdev->dev,
"Property 'audio-codec' missing or invalid\n");
return -EINVAL;
}
card->dev = &pdev->dev;
platform_set_drvdata(pdev, card);
ret = devm_snd_soc_register_card(&pdev->dev, card);
if (ret)
dev_err(&pdev->dev, "%s snd_soc_register_card fail %d\n",
__func__, ret);
return ret;
}
static const struct of_device_id mt8173_rt5650_dt_match[] = {
{ .compatible = "mediatek,mt8173-rt5650", },
{ }
};
MODULE_DEVICE_TABLE(of, mt8173_rt5650_dt_match);
static struct platform_driver mt8173_rt5650_driver = {
.driver = {
.name = "mtk-rt5650",
.of_match_table = mt8173_rt5650_dt_match,
#ifdef CONFIG_PM
.pm = &snd_soc_pm_ops,
#endif
},
.probe = mt8173_rt5650_dev_probe,
};
module_platform_driver(mt8173_rt5650_driver);
/* Module information */
MODULE_DESCRIPTION("MT8173 RT5650 SoC machine driver");
MODULE_AUTHOR("Koro Chen <koro.chen@mediatek.com>");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:mtk-rt5650");
......@@ -87,6 +87,7 @@ struct mtk_afe_memif_data {
int irq_en_shift;
int irq_fs_shift;
int irq_clr_shift;
int msb_shift;
};
struct mtk_afe_memif {
......
......@@ -21,6 +21,7 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/dma-mapping.h>
#include <linux/pm_runtime.h>
#include <sound/soc.h>
#include "mtk-afe-common.h"
......@@ -35,9 +36,11 @@
#define AFE_I2S_CON1 0x0034
#define AFE_I2S_CON2 0x0038
#define AFE_CONN_24BIT 0x006c
#define AFE_MEMIF_MSB 0x00cc
#define AFE_CONN1 0x0024
#define AFE_CONN2 0x0028
#define AFE_CONN3 0x002c
#define AFE_CONN7 0x0460
#define AFE_CONN8 0x0464
#define AFE_HDMI_CONN0 0x0390
......@@ -61,6 +64,7 @@
#define AFE_HDMI_OUT_CUR 0x0378
#define AFE_HDMI_OUT_END 0x037c
#define AFE_ADDA_TOP_CON0 0x0120
#define AFE_ADDA2_TOP_CON0 0x0600
#define AFE_HDMI_OUT_CON0 0x0370
......@@ -257,6 +261,7 @@ static int mtk_afe_set_i2s(struct mtk_afe *afe, unsigned int rate)
return -EINVAL;
/* from external ADC */
regmap_update_bits(afe->regmap, AFE_ADDA_TOP_CON0, 0x1, 0x1);
regmap_update_bits(afe->regmap, AFE_ADDA2_TOP_CON0, 0x1, 0x1);
/* set input */
......@@ -281,20 +286,13 @@ static void mtk_afe_set_i2s_enable(struct mtk_afe *afe, bool enable)
regmap_read(afe->regmap, AFE_I2S_CON2, &val);
if (!!(val & AFE_I2S_CON2_EN) == enable)
return; /* must skip soft reset */
/* I2S soft reset begin */
regmap_update_bits(afe->regmap, AUDIO_TOP_CON1, 0x4, 0x4);
return;
/* input */
regmap_update_bits(afe->regmap, AFE_I2S_CON2, 0x1, enable);
/* output */
regmap_update_bits(afe->regmap, AFE_I2S_CON1, 0x1, enable);
/* I2S soft reset end */
udelay(1);
regmap_update_bits(afe->regmap, AUDIO_TOP_CON1, 0x4, 0);
}
static int mtk_afe_dais_enable_clks(struct mtk_afe *afe,
......@@ -363,6 +361,7 @@ static int mtk_afe_i2s_startup(struct snd_pcm_substream *substream,
return 0;
mtk_afe_dais_enable_clks(afe, afe->clocks[MTK_CLK_I2S1_M], NULL);
mtk_afe_dais_enable_clks(afe, afe->clocks[MTK_CLK_I2S2_M], NULL);
regmap_update_bits(afe->regmap, AUDIO_TOP_CON0,
AUD_TCON0_PDN_22M | AUD_TCON0_PDN_24M, 0);
return 0;
......@@ -382,6 +381,7 @@ static void mtk_afe_i2s_shutdown(struct snd_pcm_substream *substream,
AUD_TCON0_PDN_22M | AUD_TCON0_PDN_24M,
AUD_TCON0_PDN_22M | AUD_TCON0_PDN_24M);
mtk_afe_dais_disable_clks(afe, afe->clocks[MTK_CLK_I2S1_M], NULL);
mtk_afe_dais_disable_clks(afe, afe->clocks[MTK_CLK_I2S2_M], NULL);
}
static int mtk_afe_i2s_prepare(struct snd_pcm_substream *substream,
......@@ -395,6 +395,9 @@ static int mtk_afe_i2s_prepare(struct snd_pcm_substream *substream,
mtk_afe_dais_set_clks(afe,
afe->clocks[MTK_CLK_I2S1_M], runtime->rate * 256,
NULL, 0);
mtk_afe_dais_set_clks(afe,
afe->clocks[MTK_CLK_I2S2_M], runtime->rate * 256,
NULL, 0);
/* config I2S */
ret = mtk_afe_set_i2s(afe, substream->runtime->rate);
if (ret)
......@@ -592,6 +595,7 @@ static int mtk_afe_dais_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct mtk_afe *afe = snd_soc_platform_get_drvdata(rtd->platform);
struct mtk_afe_memif *memif = &afe->memif[rtd->cpu_dai->id];
int msb_at_bit33 = 0;
int ret;
dev_dbg(afe->dev,
......@@ -603,7 +607,8 @@ static int mtk_afe_dais_hw_params(struct snd_pcm_substream *substream,
if (ret < 0)
return ret;
memif->phys_buf_addr = substream->runtime->dma_addr;
msb_at_bit33 = upper_32_bits(substream->runtime->dma_addr) ? 1 : 0;
memif->phys_buf_addr = lower_32_bits(substream->runtime->dma_addr);
memif->buffer_size = substream->runtime->dma_bytes;
/* start */
......@@ -614,6 +619,11 @@ static int mtk_afe_dais_hw_params(struct snd_pcm_substream *substream,
memif->data->reg_ofs_base + AFE_BASE_END_OFFSET,
memif->phys_buf_addr + memif->buffer_size - 1);
/* set MSB to 33-bit */
regmap_update_bits(afe->regmap, AFE_MEMIF_MSB,
1 << memif->data->msb_shift,
msb_at_bit33 << memif->data->msb_shift);
/* set channel */
if (memif->data->mono_shift >= 0) {
unsigned int mono = (params_channels(params) == 1) ? 1 : 0;
......@@ -894,15 +904,19 @@ static const struct snd_kcontrol_new mtk_afe_o04_mix[] = {
};
static const struct snd_kcontrol_new mtk_afe_o09_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("I03 Switch", AFE_CONN3, 0, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I17 Switch", AFE_CONN7, 30, 1, 0),
};
static const struct snd_kcontrol_new mtk_afe_o10_mix[] = {
SOC_DAPM_SINGLE_AUTODISABLE("I04 Switch", AFE_CONN3, 3, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("I18 Switch", AFE_CONN8, 0, 1, 0),
};
static const struct snd_soc_dapm_widget mtk_afe_pcm_widgets[] = {
/* inter-connections */
SND_SOC_DAPM_MIXER("I03", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("I04", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("I05", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("I06", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("I17", SND_SOC_NOPM, 0, 0, NULL, 0),
......@@ -925,12 +939,16 @@ static const struct snd_soc_dapm_route mtk_afe_pcm_routes[] = {
{"I2S Playback", NULL, "O04"},
{"VUL", NULL, "O09"},
{"VUL", NULL, "O10"},
{"I03", NULL, "I2S Capture"},
{"I04", NULL, "I2S Capture"},
{"I17", NULL, "I2S Capture"},
{"I18", NULL, "I2S Capture"},
{ "O03", "I05 Switch", "I05" },
{ "O04", "I06 Switch", "I06" },
{ "O09", "I17 Switch", "I17" },
{ "O09", "I03 Switch", "I03" },
{ "O10", "I18 Switch", "I18" },
{ "O10", "I04 Switch", "I04" },
};
static const struct snd_soc_dapm_route mtk_afe_hdmi_routes[] = {
......@@ -978,6 +996,7 @@ static const struct mtk_afe_memif_data memif_data[MTK_AFE_MEMIF_NUM] = {
.irq_en_shift = 0,
.irq_fs_shift = 4,
.irq_clr_shift = 0,
.msb_shift = 0,
}, {
.name = "DL2",
.id = MTK_AFE_MEMIF_DL2,
......@@ -991,6 +1010,7 @@ static const struct mtk_afe_memif_data memif_data[MTK_AFE_MEMIF_NUM] = {
.irq_en_shift = 2,
.irq_fs_shift = 16,
.irq_clr_shift = 2,
.msb_shift = 1,
}, {
.name = "VUL",
.id = MTK_AFE_MEMIF_VUL,
......@@ -1004,6 +1024,7 @@ static const struct mtk_afe_memif_data memif_data[MTK_AFE_MEMIF_NUM] = {
.irq_en_shift = 1,
.irq_fs_shift = 8,
.irq_clr_shift = 1,
.msb_shift = 6,
}, {
.name = "DAI",
.id = MTK_AFE_MEMIF_DAI,
......@@ -1017,6 +1038,7 @@ static const struct mtk_afe_memif_data memif_data[MTK_AFE_MEMIF_NUM] = {
.irq_en_shift = 3,
.irq_fs_shift = 20,
.irq_clr_shift = 3,
.msb_shift = 5,
}, {
.name = "AWB",
.id = MTK_AFE_MEMIF_AWB,
......@@ -1030,6 +1052,7 @@ static const struct mtk_afe_memif_data memif_data[MTK_AFE_MEMIF_NUM] = {
.irq_en_shift = 14,
.irq_fs_shift = 24,
.irq_clr_shift = 6,
.msb_shift = 3,
}, {
.name = "MOD_DAI",
.id = MTK_AFE_MEMIF_MOD_DAI,
......@@ -1043,6 +1066,7 @@ static const struct mtk_afe_memif_data memif_data[MTK_AFE_MEMIF_NUM] = {
.irq_en_shift = 3,
.irq_fs_shift = 20,
.irq_clr_shift = 3,
.msb_shift = 4,
}, {
.name = "HDMI",
.id = MTK_AFE_MEMIF_HDMI,
......@@ -1056,6 +1080,7 @@ static const struct mtk_afe_memif_data memif_data[MTK_AFE_MEMIF_NUM] = {
.irq_en_shift = 12,
.irq_fs_shift = -1,
.irq_clr_shift = 4,
.msb_shift = 8,
},
};
......@@ -1189,6 +1214,10 @@ static int mtk_afe_pcm_dev_probe(struct platform_device *pdev)
struct mtk_afe *afe;
struct resource *res;
ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(33));
if (ret)
return ret;
afe = devm_kzalloc(&pdev->dev, sizeof(*afe), GFP_KERNEL);
if (!afe)
return -ENOMEM;
......
......@@ -418,7 +418,7 @@ static int mxs_saif_hw_params(struct snd_pcm_substream *substream,
}
stat = __raw_readl(saif->base + SAIF_STAT);
if (stat & BM_SAIF_STAT_BUSY) {
if (!saif->mclk_in_use && (stat & BM_SAIF_STAT_BUSY)) {
dev_err(cpu_dai->dev, "error: busy\n");
return -EBUSY;
}
......
......@@ -345,6 +345,7 @@ static int omap_hdmi_audio_probe(struct platform_device *pdev)
dai_drv = &omap4_hdmi_dai;
break;
case OMAPDSS_VER_OMAP5:
case OMAPDSS_VER_DRA7xx:
dai_drv = &omap5_hdmi_dai;
break;
default:
......
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