Commit 89a88dd3 authored by Mark Brown's avatar Mark Brown

Merge tag 'asoc-v4.1' into asoc-next

ASoC: Changes for v4.1

A selection of changes for v4.1 so far.  The main things are:

 - Move of jack registration to the card where it belongs.
 - Support for DAPM routes specified by both the machine driver and DT.

# gpg: Signature made Thu 05 Mar 2015 01:10:27 GMT using RSA key ID 5D5487D0
# gpg: WARNING: digest algorithm MD5 is deprecated
# gpg: please see https://gnupg.org/faq/weak-digest-algos.html for more information
# gpg: Oops: keyid_from_fingerprint: no pubkey
# gpg: Good signature from "Mark Brown <broonie@sirena.org.uk>"
# gpg:                 aka "Mark Brown <broonie@debian.org>"
# gpg:                 aka "Mark Brown <broonie@kernel.org>"
# gpg:                 aka "Mark Brown <broonie@tardis.ed.ac.uk>"
# gpg:                 aka "Mark Brown <broonie@linaro.org>"
# gpg:                 aka "Mark Brown <Mark.Brown@linaro.org>"
parents 3eaecb4b d7e3281b
...@@ -18,6 +18,7 @@ Required properties: ...@@ -18,6 +18,7 @@ Required properties:
* Headphones * Headphones
* Speakers * Speakers
* Mic Jack * Mic Jack
* Int Mic
- nvidia,i2s-controller : The phandle of the Tegra I2S controller that's - nvidia,i2s-controller : The phandle of the Tegra I2S controller that's
connected to the CODEC. connected to the CODEC.
......
...@@ -366,4 +366,11 @@ static inline int params_physical_width(const struct snd_pcm_hw_params *p) ...@@ -366,4 +366,11 @@ static inline int params_physical_width(const struct snd_pcm_hw_params *p)
return snd_pcm_format_physical_width(params_format(p)); return snd_pcm_format_physical_width(params_format(p));
} }
static inline void
params_set_format(struct snd_pcm_hw_params *p, snd_pcm_format_t fmt)
{
snd_mask_set(hw_param_mask(p, SNDRV_PCM_HW_PARAM_FORMAT),
(__force int)fmt);
}
#endif /* __SOUND_PCM_PARAMS_H */ #endif /* __SOUND_PCM_PARAMS_H */
...@@ -450,8 +450,10 @@ int soc_dai_hw_params(struct snd_pcm_substream *substream, ...@@ -450,8 +450,10 @@ int soc_dai_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai); struct snd_soc_dai *dai);
/* Jack reporting */ /* Jack reporting */
int snd_soc_jack_new(struct snd_soc_codec *codec, const char *id, int type, int snd_soc_card_jack_new(struct snd_soc_card *card, const char *id, int type,
struct snd_soc_jack *jack); struct snd_soc_jack *jack, struct snd_soc_jack_pin *pins,
unsigned int num_pins);
void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask); void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask);
int snd_soc_jack_add_pins(struct snd_soc_jack *jack, int count, int snd_soc_jack_add_pins(struct snd_soc_jack *jack, int count,
struct snd_soc_jack_pin *pins); struct snd_soc_jack_pin *pins);
...@@ -659,7 +661,7 @@ struct snd_soc_jack_gpio { ...@@ -659,7 +661,7 @@ struct snd_soc_jack_gpio {
struct snd_soc_jack { struct snd_soc_jack {
struct mutex mutex; struct mutex mutex;
struct snd_jack *jack; struct snd_jack *jack;
struct snd_soc_codec *codec; struct snd_soc_card *card;
struct list_head pins; struct list_head pins;
int status; int status;
struct blocking_notifier_head notifier; struct blocking_notifier_head notifier;
...@@ -954,6 +956,9 @@ struct snd_soc_dai_link { ...@@ -954,6 +956,9 @@ struct snd_soc_dai_link {
unsigned int symmetric_channels:1; unsigned int symmetric_channels:1;
unsigned int symmetric_samplebits:1; unsigned int symmetric_samplebits:1;
/* Mark this pcm with non atomic ops */
bool nonatomic;
/* Do not create a PCM for this DAI link (Backend link) */ /* Do not create a PCM for this DAI link (Backend link) */
unsigned int no_pcm:1; unsigned int no_pcm:1;
...@@ -1071,11 +1076,16 @@ struct snd_soc_card { ...@@ -1071,11 +1076,16 @@ struct snd_soc_card {
/* /*
* Card-specific routes and widgets. * Card-specific routes and widgets.
* Note: of_dapm_xxx for Device Tree; Otherwise for driver build-in.
*/ */
const struct snd_soc_dapm_widget *dapm_widgets; const struct snd_soc_dapm_widget *dapm_widgets;
int num_dapm_widgets; int num_dapm_widgets;
const struct snd_soc_dapm_route *dapm_routes; const struct snd_soc_dapm_route *dapm_routes;
int num_dapm_routes; int num_dapm_routes;
const struct snd_soc_dapm_widget *of_dapm_widgets;
int num_of_dapm_widgets;
const struct snd_soc_dapm_route *of_dapm_routes;
int num_of_dapm_routes;
bool fully_routed; bool fully_routed;
struct work_struct deferred_resume_work; struct work_struct deferred_resume_work;
......
...@@ -187,6 +187,94 @@ static irqreturn_t atmel_ssc_interrupt(int irq, void *dev_id) ...@@ -187,6 +187,94 @@ static irqreturn_t atmel_ssc_interrupt(int irq, void *dev_id)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
/*
* When the bit clock is input, limit the maximum rate according to the
* Serial Clock Ratio Considerations section from the SSC documentation:
*
* The Transmitter and the Receiver can be programmed to operate
* with the clock signals provided on either the TK or RK pins.
* This allows the SSC to support many slave-mode data transfers.
* In this case, the maximum clock speed allowed on the RK pin is:
* - Peripheral clock divided by 2 if Receiver Frame Synchro is input
* - Peripheral clock divided by 3 if Receiver Frame Synchro is output
* In addition, the maximum clock speed allowed on the TK pin is:
* - Peripheral clock divided by 6 if Transmit Frame Synchro is input
* - Peripheral clock divided by 2 if Transmit Frame Synchro is output
*
* When the bit clock is output, limit the rate according to the
* SSC divider restrictions.
*/
static int atmel_ssc_hw_rule_rate(struct snd_pcm_hw_params *params,
struct snd_pcm_hw_rule *rule)
{
struct atmel_ssc_info *ssc_p = rule->private;
struct ssc_device *ssc = ssc_p->ssc;
struct snd_interval *i = hw_param_interval(params, rule->var);
struct snd_interval t;
struct snd_ratnum r = {
.den_min = 1,
.den_max = 4095,
.den_step = 1,
};
unsigned int num = 0, den = 0;
int frame_size;
int mck_div = 2;
int ret;
frame_size = snd_soc_params_to_frame_size(params);
if (frame_size < 0)
return frame_size;
switch (ssc_p->daifmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBM_CFS:
if ((ssc_p->dir_mask & SSC_DIR_MASK_CAPTURE)
&& ssc->clk_from_rk_pin)
/* Receiver Frame Synchro (i.e. capture)
* is output (format is _CFS) and the RK pin
* is used for input (format is _CBM_).
*/
mck_div = 3;
break;
case SND_SOC_DAIFMT_CBM_CFM:
if ((ssc_p->dir_mask & SSC_DIR_MASK_PLAYBACK)
&& !ssc->clk_from_rk_pin)
/* Transmit Frame Synchro (i.e. playback)
* is input (format is _CFM) and the TK pin
* is used for input (format _CBM_ but not
* using the RK pin).
*/
mck_div = 6;
break;
}
switch (ssc_p->daifmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBS_CFS:
r.num = ssc_p->mck_rate / mck_div / frame_size;
ret = snd_interval_ratnum(i, 1, &r, &num, &den);
if (ret >= 0 && den && rule->var == SNDRV_PCM_HW_PARAM_RATE) {
params->rate_num = num;
params->rate_den = den;
}
break;
case SND_SOC_DAIFMT_CBM_CFS:
case SND_SOC_DAIFMT_CBM_CFM:
t.min = 8000;
t.max = ssc_p->mck_rate / mck_div / frame_size;
t.openmin = t.openmax = 0;
t.integer = 0;
ret = snd_interval_refine(i, &t);
break;
default:
ret = -EINVAL;
break;
}
return ret;
}
/*-------------------------------------------------------------------------*\ /*-------------------------------------------------------------------------*\
* DAI functions * DAI functions
...@@ -200,6 +288,7 @@ static int atmel_ssc_startup(struct snd_pcm_substream *substream, ...@@ -200,6 +288,7 @@ static int atmel_ssc_startup(struct snd_pcm_substream *substream,
struct atmel_ssc_info *ssc_p = &ssc_info[dai->id]; struct atmel_ssc_info *ssc_p = &ssc_info[dai->id];
struct atmel_pcm_dma_params *dma_params; struct atmel_pcm_dma_params *dma_params;
int dir, dir_mask; int dir, dir_mask;
int ret;
pr_debug("atmel_ssc_startup: SSC_SR=0x%u\n", pr_debug("atmel_ssc_startup: SSC_SR=0x%u\n",
ssc_readl(ssc_p->ssc->regs, SR)); ssc_readl(ssc_p->ssc->regs, SR));
...@@ -207,6 +296,7 @@ static int atmel_ssc_startup(struct snd_pcm_substream *substream, ...@@ -207,6 +296,7 @@ static int atmel_ssc_startup(struct snd_pcm_substream *substream,
/* Enable PMC peripheral clock for this SSC */ /* Enable PMC peripheral clock for this SSC */
pr_debug("atmel_ssc_dai: Starting clock\n"); pr_debug("atmel_ssc_dai: Starting clock\n");
clk_enable(ssc_p->ssc->clk); clk_enable(ssc_p->ssc->clk);
ssc_p->mck_rate = clk_get_rate(ssc_p->ssc->clk);
/* Reset the SSC to keep it at a clean status */ /* Reset the SSC to keep it at a clean status */
ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_SWRST)); ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_SWRST));
...@@ -219,6 +309,17 @@ static int atmel_ssc_startup(struct snd_pcm_substream *substream, ...@@ -219,6 +309,17 @@ static int atmel_ssc_startup(struct snd_pcm_substream *substream,
dir_mask = SSC_DIR_MASK_CAPTURE; dir_mask = SSC_DIR_MASK_CAPTURE;
} }
ret = snd_pcm_hw_rule_add(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_RATE,
atmel_ssc_hw_rule_rate,
ssc_p,
SNDRV_PCM_HW_PARAM_FRAME_BITS,
SNDRV_PCM_HW_PARAM_CHANNELS, -1);
if (ret < 0) {
dev_err(dai->dev, "Failed to specify rate rule: %d\n", ret);
return ret;
}
dma_params = &ssc_dma_params[dai->id][dir]; dma_params = &ssc_dma_params[dai->id][dir];
dma_params->ssc = ssc_p->ssc; dma_params->ssc = ssc_p->ssc;
dma_params->substream = substream; dma_params->substream = substream;
...@@ -783,8 +884,6 @@ static int atmel_ssc_resume(struct snd_soc_dai *cpu_dai) ...@@ -783,8 +884,6 @@ static int atmel_ssc_resume(struct snd_soc_dai *cpu_dai)
# define atmel_ssc_resume NULL # define atmel_ssc_resume NULL
#endif /* CONFIG_PM */ #endif /* CONFIG_PM */
#define ATMEL_SSC_RATES (SNDRV_PCM_RATE_8000_96000)
#define ATMEL_SSC_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\ #define ATMEL_SSC_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
...@@ -804,12 +903,16 @@ static struct snd_soc_dai_driver atmel_ssc_dai = { ...@@ -804,12 +903,16 @@ static struct snd_soc_dai_driver atmel_ssc_dai = {
.playback = { .playback = {
.channels_min = 1, .channels_min = 1,
.channels_max = 2, .channels_max = 2,
.rates = ATMEL_SSC_RATES, .rates = SNDRV_PCM_RATE_CONTINUOUS,
.rate_min = 8000,
.rate_max = 384000,
.formats = ATMEL_SSC_FORMATS,}, .formats = ATMEL_SSC_FORMATS,},
.capture = { .capture = {
.channels_min = 1, .channels_min = 1,
.channels_max = 2, .channels_max = 2,
.rates = ATMEL_SSC_RATES, .rates = SNDRV_PCM_RATE_CONTINUOUS,
.rate_min = 8000,
.rate_max = 384000,
.formats = ATMEL_SSC_FORMATS,}, .formats = ATMEL_SSC_FORMATS,},
.ops = &atmel_ssc_dai_ops, .ops = &atmel_ssc_dai_ops,
}; };
......
...@@ -115,6 +115,7 @@ struct atmel_ssc_info { ...@@ -115,6 +115,7 @@ struct atmel_ssc_info {
unsigned short rcmr_period; unsigned short rcmr_period;
struct atmel_pcm_dma_params *dma_params[2]; struct atmel_pcm_dma_params *dma_params[2];
struct atmel_ssc_state ssc_state; struct atmel_ssc_state ssc_state;
unsigned long mck_rate;
}; };
int atmel_ssc_set_audio(int ssc_id); int atmel_ssc_set_audio(int ssc_id);
......
...@@ -141,7 +141,8 @@ config SND_SOC_ALL_CODECS ...@@ -141,7 +141,8 @@ config SND_SOC_ALL_CODECS
select SND_SOC_WM8770 if SPI_MASTER select SND_SOC_WM8770 if SPI_MASTER
select SND_SOC_WM8776 if SND_SOC_I2C_AND_SPI select SND_SOC_WM8776 if SND_SOC_I2C_AND_SPI
select SND_SOC_WM8782 select SND_SOC_WM8782
select SND_SOC_WM8804 if SND_SOC_I2C_AND_SPI select SND_SOC_WM8804_I2C if I2C
select SND_SOC_WM8804_SPI if SPI_MASTER
select SND_SOC_WM8900 if I2C select SND_SOC_WM8900 if I2C
select SND_SOC_WM8903 if I2C select SND_SOC_WM8903 if I2C
select SND_SOC_WM8904 if I2C select SND_SOC_WM8904 if I2C
...@@ -744,8 +745,19 @@ config SND_SOC_WM8782 ...@@ -744,8 +745,19 @@ config SND_SOC_WM8782
tristate tristate
config SND_SOC_WM8804 config SND_SOC_WM8804
tristate "Wolfson Microelectronics WM8804 S/PDIF transceiver" tristate
depends on SND_SOC_I2C_AND_SPI
config SND_SOC_WM8804_I2C
tristate "Wolfson Microelectronics WM8804 S/PDIF transceiver I2C"
depends on I2C
select SND_SOC_WM8804
select REGMAP_I2C
config SND_SOC_WM8804_SPI
tristate "Wolfson Microelectronics WM8804 S/PDIF transceiver SPI"
depends on SPI_MASTER
select SND_SOC_WM8804
select REGMAP_SPI
config SND_SOC_WM8900 config SND_SOC_WM8900
tristate tristate
......
...@@ -145,6 +145,8 @@ snd-soc-wm8770-objs := wm8770.o ...@@ -145,6 +145,8 @@ snd-soc-wm8770-objs := wm8770.o
snd-soc-wm8776-objs := wm8776.o snd-soc-wm8776-objs := wm8776.o
snd-soc-wm8782-objs := wm8782.o snd-soc-wm8782-objs := wm8782.o
snd-soc-wm8804-objs := wm8804.o snd-soc-wm8804-objs := wm8804.o
snd-soc-wm8804-i2c-objs := wm8804-i2c.o
snd-soc-wm8804-spi-objs := wm8804-spi.o
snd-soc-wm8900-objs := wm8900.o snd-soc-wm8900-objs := wm8900.o
snd-soc-wm8903-objs := wm8903.o snd-soc-wm8903-objs := wm8903.o
snd-soc-wm8904-objs := wm8904.o snd-soc-wm8904-objs := wm8904.o
...@@ -323,6 +325,8 @@ obj-$(CONFIG_SND_SOC_WM8770) += snd-soc-wm8770.o ...@@ -323,6 +325,8 @@ obj-$(CONFIG_SND_SOC_WM8770) += snd-soc-wm8770.o
obj-$(CONFIG_SND_SOC_WM8776) += snd-soc-wm8776.o obj-$(CONFIG_SND_SOC_WM8776) += snd-soc-wm8776.o
obj-$(CONFIG_SND_SOC_WM8782) += snd-soc-wm8782.o obj-$(CONFIG_SND_SOC_WM8782) += snd-soc-wm8782.o
obj-$(CONFIG_SND_SOC_WM8804) += snd-soc-wm8804.o obj-$(CONFIG_SND_SOC_WM8804) += snd-soc-wm8804.o
obj-$(CONFIG_SND_SOC_WM8804_I2C) += snd-soc-wm8804-i2c.o
obj-$(CONFIG_SND_SOC_WM8804_SPI) += snd-soc-wm8804-spi.o
obj-$(CONFIG_SND_SOC_WM8900) += snd-soc-wm8900.o obj-$(CONFIG_SND_SOC_WM8900) += snd-soc-wm8900.o
obj-$(CONFIG_SND_SOC_WM8903) += snd-soc-wm8903.o obj-$(CONFIG_SND_SOC_WM8903) += snd-soc-wm8903.o
obj-$(CONFIG_SND_SOC_WM8904) += snd-soc-wm8904.o obj-$(CONFIG_SND_SOC_WM8904) += snd-soc-wm8904.o
......
...@@ -938,22 +938,15 @@ int adau1977_probe(struct device *dev, struct regmap *regmap, ...@@ -938,22 +938,15 @@ int adau1977_probe(struct device *dev, struct regmap *regmap,
adau1977->dvdd_reg = NULL; adau1977->dvdd_reg = NULL;
} }
adau1977->reset_gpio = devm_gpiod_get(dev, "reset"); adau1977->reset_gpio = devm_gpiod_get_optional(dev, "reset",
if (IS_ERR(adau1977->reset_gpio)) { GPIOD_OUT_LOW);
ret = PTR_ERR(adau1977->reset_gpio); if (IS_ERR(adau1977->reset_gpio))
if (ret != -ENOENT && ret != -ENOSYS) return PTR_ERR(adau1977->reset_gpio);
return PTR_ERR(adau1977->reset_gpio);
adau1977->reset_gpio = NULL;
}
dev_set_drvdata(dev, adau1977); dev_set_drvdata(dev, adau1977);
if (adau1977->reset_gpio) { if (adau1977->reset_gpio)
ret = gpiod_direction_output(adau1977->reset_gpio, 0);
if (ret)
return ret;
ndelay(100); ndelay(100);
}
ret = adau1977_power_enable(adau1977); ret = adau1977_power_enable(adau1977);
if (ret) if (ret)
......
...@@ -437,20 +437,13 @@ static int cs35l32_i2c_probe(struct i2c_client *i2c_client, ...@@ -437,20 +437,13 @@ static int cs35l32_i2c_probe(struct i2c_client *i2c_client,
} }
/* Reset the Device */ /* Reset the Device */
cs35l32->reset_gpio = devm_gpiod_get(&i2c_client->dev, cs35l32->reset_gpio = devm_gpiod_get_optional(&i2c_client->dev,
"reset-gpios"); "reset", GPIOD_OUT_LOW);
if (IS_ERR(cs35l32->reset_gpio)) { if (IS_ERR(cs35l32->reset_gpio))
ret = PTR_ERR(cs35l32->reset_gpio); return PTR_ERR(cs35l32->reset_gpio);
if (ret != -ENOENT && ret != -ENOSYS)
return ret; if (cs35l32->reset_gpio)
cs35l32->reset_gpio = NULL;
} else {
ret = gpiod_direction_output(cs35l32->reset_gpio, 0);
if (ret)
return ret;
gpiod_set_value_cansleep(cs35l32->reset_gpio, 1); gpiod_set_value_cansleep(cs35l32->reset_gpio, 1);
}
/* initialize codec */ /* initialize codec */
ret = regmap_read(cs35l32->regmap, CS35L32_DEVID_AB, &reg); ret = regmap_read(cs35l32->regmap, CS35L32_DEVID_AB, &reg);
......
...@@ -605,21 +605,14 @@ static int cs4265_i2c_probe(struct i2c_client *i2c_client, ...@@ -605,21 +605,14 @@ static int cs4265_i2c_probe(struct i2c_client *i2c_client,
return ret; return ret;
} }
cs4265->reset_gpio = devm_gpiod_get(&i2c_client->dev, cs4265->reset_gpio = devm_gpiod_get_optional(&i2c_client->dev,
"reset-gpios"); "reset", GPIOD_OUT_LOW);
if (IS_ERR(cs4265->reset_gpio)) { if (IS_ERR(cs4265->reset_gpio))
ret = PTR_ERR(cs4265->reset_gpio); return PTR_ERR(cs4265->reset_gpio);
if (ret != -ENOENT && ret != -ENOSYS)
return ret; if (cs4265->reset_gpio) {
cs4265->reset_gpio = NULL;
} else {
ret = gpiod_direction_output(cs4265->reset_gpio, 0);
if (ret)
return ret;
mdelay(1); mdelay(1);
gpiod_set_value_cansleep(cs4265->reset_gpio, 1); gpiod_set_value_cansleep(cs4265->reset_gpio, 1);
} }
i2c_set_clientdata(i2c_client, cs4265); i2c_set_clientdata(i2c_client, cs4265);
......
...@@ -26,8 +26,6 @@ ...@@ -26,8 +26,6 @@
#include <sound/soc-dai.h> #include <sound/soc-dai.h>
#include <sound/soc-dapm.h> #include <sound/soc-dapm.h>
#define DRV_NAME "max98357a"
static int max98357a_daiops_trigger(struct snd_pcm_substream *substream, static int max98357a_daiops_trigger(struct snd_pcm_substream *substream,
int cmd, struct snd_soc_dai *dai) int cmd, struct snd_soc_dai *dai)
{ {
...@@ -87,9 +85,9 @@ static struct snd_soc_dai_ops max98357a_dai_ops = { ...@@ -87,9 +85,9 @@ static struct snd_soc_dai_ops max98357a_dai_ops = {
}; };
static struct snd_soc_dai_driver max98357a_dai_driver = { static struct snd_soc_dai_driver max98357a_dai_driver = {
.name = DRV_NAME, .name = "HiFi",
.playback = { .playback = {
.stream_name = DRV_NAME "-playback", .stream_name = "HiFi Playback",
.formats = SNDRV_PCM_FMTBIT_S16 | .formats = SNDRV_PCM_FMTBIT_S16 |
SNDRV_PCM_FMTBIT_S24 | SNDRV_PCM_FMTBIT_S24 |
SNDRV_PCM_FMTBIT_S32, SNDRV_PCM_FMTBIT_S32,
...@@ -127,7 +125,7 @@ static int max98357a_platform_remove(struct platform_device *pdev) ...@@ -127,7 +125,7 @@ static int max98357a_platform_remove(struct platform_device *pdev)
#ifdef CONFIG_OF #ifdef CONFIG_OF
static const struct of_device_id max98357a_device_id[] = { static const struct of_device_id max98357a_device_id[] = {
{ .compatible = "maxim," DRV_NAME, }, { .compatible = "maxim,max98357a" },
{} {}
}; };
MODULE_DEVICE_TABLE(of, max98357a_device_id); MODULE_DEVICE_TABLE(of, max98357a_device_id);
...@@ -135,7 +133,7 @@ MODULE_DEVICE_TABLE(of, max98357a_device_id); ...@@ -135,7 +133,7 @@ MODULE_DEVICE_TABLE(of, max98357a_device_id);
static struct platform_driver max98357a_platform_driver = { static struct platform_driver max98357a_platform_driver = {
.driver = { .driver = {
.name = DRV_NAME, .name = "max98357a",
.of_match_table = of_match_ptr(max98357a_device_id), .of_match_table = of_match_ptr(max98357a_device_id),
}, },
.probe = max98357a_platform_probe, .probe = max98357a_platform_probe,
...@@ -145,4 +143,3 @@ module_platform_driver(max98357a_platform_driver); ...@@ -145,4 +143,3 @@ module_platform_driver(max98357a_platform_driver);
MODULE_DESCRIPTION("Maxim MAX98357A Codec Driver"); MODULE_DESCRIPTION("Maxim MAX98357A Codec Driver");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:" DRV_NAME);
...@@ -54,6 +54,9 @@ struct pcm512x_priv { ...@@ -54,6 +54,9 @@ struct pcm512x_priv {
int pll_d; int pll_d;
int pll_p; int pll_p;
unsigned long real_pll; unsigned long real_pll;
unsigned long overclock_pll;
unsigned long overclock_dac;
unsigned long overclock_dsp;
}; };
/* /*
...@@ -224,6 +227,90 @@ static bool pcm512x_volatile(struct device *dev, unsigned int reg) ...@@ -224,6 +227,90 @@ static bool pcm512x_volatile(struct device *dev, unsigned int reg)
} }
} }
static int pcm512x_overclock_pll_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec);
ucontrol->value.integer.value[0] = pcm512x->overclock_pll;
return 0;
}
static int pcm512x_overclock_pll_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec);
switch (codec->dapm.bias_level) {
case SND_SOC_BIAS_OFF:
case SND_SOC_BIAS_STANDBY:
break;
default:
return -EBUSY;
}
pcm512x->overclock_pll = ucontrol->value.integer.value[0];
return 0;
}
static int pcm512x_overclock_dsp_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec);
ucontrol->value.integer.value[0] = pcm512x->overclock_dsp;
return 0;
}
static int pcm512x_overclock_dsp_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec);
switch (codec->dapm.bias_level) {
case SND_SOC_BIAS_OFF:
case SND_SOC_BIAS_STANDBY:
break;
default:
return -EBUSY;
}
pcm512x->overclock_dsp = ucontrol->value.integer.value[0];
return 0;
}
static int pcm512x_overclock_dac_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec);
ucontrol->value.integer.value[0] = pcm512x->overclock_dac;
return 0;
}
static int pcm512x_overclock_dac_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec);
switch (codec->dapm.bias_level) {
case SND_SOC_BIAS_OFF:
case SND_SOC_BIAS_STANDBY:
break;
default:
return -EBUSY;
}
pcm512x->overclock_dac = ucontrol->value.integer.value[0];
return 0;
}
static const DECLARE_TLV_DB_SCALE(digital_tlv, -10350, 50, 1); static const DECLARE_TLV_DB_SCALE(digital_tlv, -10350, 50, 1);
static const DECLARE_TLV_DB_SCALE(analog_tlv, -600, 600, 0); static const DECLARE_TLV_DB_SCALE(analog_tlv, -600, 600, 0);
static const DECLARE_TLV_DB_SCALE(boost_tlv, 0, 80, 0); static const DECLARE_TLV_DB_SCALE(boost_tlv, 0, 80, 0);
...@@ -328,6 +415,13 @@ SOC_ENUM("Volume Ramp Up Rate", pcm512x_vnuf), ...@@ -328,6 +415,13 @@ SOC_ENUM("Volume Ramp Up Rate", pcm512x_vnuf),
SOC_ENUM("Volume Ramp Up Step", pcm512x_vnus), SOC_ENUM("Volume Ramp Up Step", pcm512x_vnus),
SOC_ENUM("Volume Ramp Down Emergency Rate", pcm512x_vedf), SOC_ENUM("Volume Ramp Down Emergency Rate", pcm512x_vedf),
SOC_ENUM("Volume Ramp Down Emergency Step", pcm512x_veds), SOC_ENUM("Volume Ramp Down Emergency Step", pcm512x_veds),
SOC_SINGLE_EXT("Max Overclock PLL", SND_SOC_NOPM, 0, 20, 0,
pcm512x_overclock_pll_get, pcm512x_overclock_pll_put),
SOC_SINGLE_EXT("Max Overclock DSP", SND_SOC_NOPM, 0, 40, 0,
pcm512x_overclock_dsp_get, pcm512x_overclock_dsp_put),
SOC_SINGLE_EXT("Max Overclock DAC", SND_SOC_NOPM, 0, 40, 0,
pcm512x_overclock_dac_get, pcm512x_overclock_dac_put),
}; };
static const struct snd_soc_dapm_widget pcm512x_dapm_widgets[] = { static const struct snd_soc_dapm_widget pcm512x_dapm_widgets[] = {
...@@ -346,6 +440,45 @@ static const struct snd_soc_dapm_route pcm512x_dapm_routes[] = { ...@@ -346,6 +440,45 @@ static const struct snd_soc_dapm_route pcm512x_dapm_routes[] = {
{ "OUTR", NULL, "DACR" }, { "OUTR", NULL, "DACR" },
}; };
static unsigned long pcm512x_pll_max(struct pcm512x_priv *pcm512x)
{
return 25000000 + 25000000 * pcm512x->overclock_pll / 100;
}
static unsigned long pcm512x_dsp_max(struct pcm512x_priv *pcm512x)
{
return 50000000 + 50000000 * pcm512x->overclock_dsp / 100;
}
static unsigned long pcm512x_dac_max(struct pcm512x_priv *pcm512x,
unsigned long rate)
{
return rate + rate * pcm512x->overclock_dac / 100;
}
static unsigned long pcm512x_sck_max(struct pcm512x_priv *pcm512x)
{
if (!pcm512x->pll_out)
return 25000000;
return pcm512x_pll_max(pcm512x);
}
static unsigned long pcm512x_ncp_target(struct pcm512x_priv *pcm512x,
unsigned long dac_rate)
{
/*
* If the DAC is not actually overclocked, use the good old
* NCP target rate...
*/
if (dac_rate <= 6144000)
return 1536000;
/*
* ...but if the DAC is in fact overclocked, bump the NCP target
* rate to get the recommended dividers even when overclocking.
*/
return pcm512x_dac_max(pcm512x, 1536000);
}
static const u32 pcm512x_dai_rates[] = { static const u32 pcm512x_dai_rates[] = {
8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000, 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000,
88200, 96000, 176400, 192000, 384000, 88200, 96000, 176400, 192000, 384000,
...@@ -359,6 +492,7 @@ static const struct snd_pcm_hw_constraint_list constraints_slave = { ...@@ -359,6 +492,7 @@ static const struct snd_pcm_hw_constraint_list constraints_slave = {
static int pcm512x_hw_rule_rate(struct snd_pcm_hw_params *params, static int pcm512x_hw_rule_rate(struct snd_pcm_hw_params *params,
struct snd_pcm_hw_rule *rule) struct snd_pcm_hw_rule *rule)
{ {
struct pcm512x_priv *pcm512x = rule->private;
struct snd_interval ranges[2]; struct snd_interval ranges[2];
int frame_size; int frame_size;
...@@ -377,7 +511,7 @@ static int pcm512x_hw_rule_rate(struct snd_pcm_hw_params *params, ...@@ -377,7 +511,7 @@ static int pcm512x_hw_rule_rate(struct snd_pcm_hw_params *params,
*/ */
memset(ranges, 0, sizeof(ranges)); memset(ranges, 0, sizeof(ranges));
ranges[0].min = 8000; ranges[0].min = 8000;
ranges[0].max = 25000000 / frame_size / 2; ranges[0].max = pcm512x_sck_max(pcm512x) / frame_size / 2;
ranges[1].min = DIV_ROUND_UP(16000000, frame_size); ranges[1].min = DIV_ROUND_UP(16000000, frame_size);
ranges[1].max = 384000; ranges[1].max = 384000;
break; break;
...@@ -408,7 +542,7 @@ static int pcm512x_dai_startup_master(struct snd_pcm_substream *substream, ...@@ -408,7 +542,7 @@ static int pcm512x_dai_startup_master(struct snd_pcm_substream *substream,
return snd_pcm_hw_rule_add(substream->runtime, 0, return snd_pcm_hw_rule_add(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_RATE, SNDRV_PCM_HW_PARAM_RATE,
pcm512x_hw_rule_rate, pcm512x_hw_rule_rate,
NULL, pcm512x,
SNDRV_PCM_HW_PARAM_FRAME_BITS, SNDRV_PCM_HW_PARAM_FRAME_BITS,
SNDRV_PCM_HW_PARAM_CHANNELS, -1); SNDRV_PCM_HW_PARAM_CHANNELS, -1);
...@@ -517,6 +651,8 @@ static unsigned long pcm512x_find_sck(struct snd_soc_dai *dai, ...@@ -517,6 +651,8 @@ static unsigned long pcm512x_find_sck(struct snd_soc_dai *dai,
unsigned long bclk_rate) unsigned long bclk_rate)
{ {
struct device *dev = dai->dev; struct device *dev = dai->dev;
struct snd_soc_codec *codec = dai->codec;
struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec);
unsigned long sck_rate; unsigned long sck_rate;
int pow2; int pow2;
...@@ -527,9 +663,10 @@ static unsigned long pcm512x_find_sck(struct snd_soc_dai *dai, ...@@ -527,9 +663,10 @@ static unsigned long pcm512x_find_sck(struct snd_soc_dai *dai,
* as many factors of 2 as possible, as that makes it easier * as many factors of 2 as possible, as that makes it easier
* to find a fast DAC rate * to find a fast DAC rate
*/ */
pow2 = 1 << fls((25000000 - 16000000) / bclk_rate); pow2 = 1 << fls((pcm512x_pll_max(pcm512x) - 16000000) / bclk_rate);
for (; pow2; pow2 >>= 1) { for (; pow2; pow2 >>= 1) {
sck_rate = rounddown(25000000, bclk_rate * pow2); sck_rate = rounddown(pcm512x_pll_max(pcm512x),
bclk_rate * pow2);
if (sck_rate >= 16000000) if (sck_rate >= 16000000)
break; break;
} }
...@@ -678,7 +815,7 @@ static unsigned long pcm512x_pllin_dac_rate(struct snd_soc_dai *dai, ...@@ -678,7 +815,7 @@ static unsigned long pcm512x_pllin_dac_rate(struct snd_soc_dai *dai,
return 0; /* futile, quit early */ return 0; /* futile, quit early */
/* run DAC no faster than 6144000 Hz */ /* run DAC no faster than 6144000 Hz */
for (dac_rate = rounddown(6144000, osr_rate); for (dac_rate = rounddown(pcm512x_dac_max(pcm512x, 6144000), osr_rate);
dac_rate; dac_rate;
dac_rate -= osr_rate) { dac_rate -= osr_rate) {
...@@ -805,7 +942,7 @@ static int pcm512x_set_dividers(struct snd_soc_dai *dai, ...@@ -805,7 +942,7 @@ static int pcm512x_set_dividers(struct snd_soc_dai *dai,
osr_rate = 16 * sample_rate; osr_rate = 16 * sample_rate;
/* run DSP no faster than 50 MHz */ /* run DSP no faster than 50 MHz */
dsp_div = mck_rate > 50000000 ? 2 : 1; dsp_div = mck_rate > pcm512x_dsp_max(pcm512x) ? 2 : 1;
dac_rate = pcm512x_pllin_dac_rate(dai, osr_rate, pllin_rate); dac_rate = pcm512x_pllin_dac_rate(dai, osr_rate, pllin_rate);
if (dac_rate) { if (dac_rate) {
...@@ -836,7 +973,8 @@ static int pcm512x_set_dividers(struct snd_soc_dai *dai, ...@@ -836,7 +973,8 @@ static int pcm512x_set_dividers(struct snd_soc_dai *dai,
dacsrc_rate = pllin_rate; dacsrc_rate = pllin_rate;
} else { } else {
/* run DAC no faster than 6144000 Hz */ /* run DAC no faster than 6144000 Hz */
unsigned long dac_mul = 6144000 / osr_rate; unsigned long dac_mul = pcm512x_dac_max(pcm512x, 6144000)
/ osr_rate;
unsigned long sck_mul = sck_rate / osr_rate; unsigned long sck_mul = sck_rate / osr_rate;
for (; dac_mul; dac_mul--) { for (; dac_mul; dac_mul--) {
...@@ -863,28 +1001,30 @@ static int pcm512x_set_dividers(struct snd_soc_dai *dai, ...@@ -863,28 +1001,30 @@ static int pcm512x_set_dividers(struct snd_soc_dai *dai,
dacsrc_rate = sck_rate; dacsrc_rate = sck_rate;
} }
osr_div = DIV_ROUND_CLOSEST(dac_rate, osr_rate);
if (osr_div > 128) {
dev_err(dev, "Failed to find OSR divider\n");
return -EINVAL;
}
dac_div = DIV_ROUND_CLOSEST(dacsrc_rate, dac_rate); dac_div = DIV_ROUND_CLOSEST(dacsrc_rate, dac_rate);
if (dac_div > 128) { if (dac_div > 128) {
dev_err(dev, "Failed to find DAC divider\n"); dev_err(dev, "Failed to find DAC divider\n");
return -EINVAL; return -EINVAL;
} }
dac_rate = dacsrc_rate / dac_div;
ncp_div = DIV_ROUND_CLOSEST(dacsrc_rate / dac_div, 1536000); ncp_div = DIV_ROUND_CLOSEST(dac_rate,
if (ncp_div > 128 || dacsrc_rate / dac_div / ncp_div > 2048000) { pcm512x_ncp_target(pcm512x, dac_rate));
if (ncp_div > 128 || dac_rate / ncp_div > 2048000) {
/* run NCP no faster than 2048000 Hz, but why? */ /* run NCP no faster than 2048000 Hz, but why? */
ncp_div = DIV_ROUND_UP(dacsrc_rate / dac_div, 2048000); ncp_div = DIV_ROUND_UP(dac_rate, 2048000);
if (ncp_div > 128) { if (ncp_div > 128) {
dev_err(dev, "Failed to find NCP divider\n"); dev_err(dev, "Failed to find NCP divider\n");
return -EINVAL; return -EINVAL;
} }
} }
osr_div = DIV_ROUND_CLOSEST(dac_rate, osr_rate);
if (osr_div > 128) {
dev_err(dev, "Failed to find OSR divider\n");
return -EINVAL;
}
idac = mck_rate / (dsp_div * sample_rate); idac = mck_rate / (dsp_div * sample_rate);
ret = regmap_write(pcm512x->regmap, PCM512x_DSP_CLKDIV, dsp_div - 1); ret = regmap_write(pcm512x->regmap, PCM512x_DSP_CLKDIV, dsp_div - 1);
...@@ -937,11 +1077,11 @@ static int pcm512x_set_dividers(struct snd_soc_dai *dai, ...@@ -937,11 +1077,11 @@ static int pcm512x_set_dividers(struct snd_soc_dai *dai,
return ret; return ret;
} }
if (sample_rate <= 48000) if (sample_rate <= pcm512x_dac_max(pcm512x, 48000))
fssp = PCM512x_FSSP_48KHZ; fssp = PCM512x_FSSP_48KHZ;
else if (sample_rate <= 96000) else if (sample_rate <= pcm512x_dac_max(pcm512x, 96000))
fssp = PCM512x_FSSP_96KHZ; fssp = PCM512x_FSSP_96KHZ;
else if (sample_rate <= 192000) else if (sample_rate <= pcm512x_dac_max(pcm512x, 192000))
fssp = PCM512x_FSSP_192KHZ; fssp = PCM512x_FSSP_192KHZ;
else else
fssp = PCM512x_FSSP_384KHZ; fssp = PCM512x_FSSP_384KHZ;
......
...@@ -395,9 +395,20 @@ int rt286_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack) ...@@ -395,9 +395,20 @@ int rt286_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack)
rt286->jack = jack; rt286->jack = jack;
/* Send an initial empty report */ if (jack) {
snd_soc_jack_report(rt286->jack, 0, /* enable IRQ */
SND_JACK_MICROPHONE | SND_JACK_HEADPHONE); if (rt286->jack->status | SND_JACK_HEADPHONE)
snd_soc_dapm_force_enable_pin(&codec->dapm, "LDO1");
regmap_update_bits(rt286->regmap, RT286_IRQ_CTRL, 0x2, 0x2);
/* Send an initial empty report */
snd_soc_jack_report(rt286->jack, rt286->jack->status,
SND_JACK_MICROPHONE | SND_JACK_HEADPHONE);
} else {
/* disable IRQ */
regmap_update_bits(rt286->regmap, RT286_IRQ_CTRL, 0x2, 0x0);
snd_soc_dapm_disable_pin(&codec->dapm, "LDO1");
}
snd_soc_dapm_sync(&codec->dapm);
return 0; return 0;
} }
......
...@@ -1950,17 +1950,20 @@ enum { ...@@ -1950,17 +1950,20 @@ enum {
}; };
enum { enum {
RT5670_DMIC1_DISABLED,
RT5670_DMIC_DATA_GPIO6, RT5670_DMIC_DATA_GPIO6,
RT5670_DMIC_DATA_IN2P, RT5670_DMIC_DATA_IN2P,
RT5670_DMIC_DATA_GPIO7, RT5670_DMIC_DATA_GPIO7,
}; };
enum { enum {
RT5670_DMIC2_DISABLED,
RT5670_DMIC_DATA_GPIO8, RT5670_DMIC_DATA_GPIO8,
RT5670_DMIC_DATA_IN3N, RT5670_DMIC_DATA_IN3N,
}; };
enum { enum {
RT5670_DMIC3_DISABLED,
RT5670_DMIC_DATA_GPIO9, RT5670_DMIC_DATA_GPIO9,
RT5670_DMIC_DATA_GPIO10, RT5670_DMIC_DATA_GPIO10,
RT5670_DMIC_DATA_GPIO5, RT5670_DMIC_DATA_GPIO5,
......
...@@ -718,11 +718,24 @@ static int rt5677_set_dsp_vad(struct snd_soc_codec *codec, bool on) ...@@ -718,11 +718,24 @@ static int rt5677_set_dsp_vad(struct snd_soc_codec *codec, bool on)
RT5677_LDO1_SEL_MASK, 0x0); RT5677_LDO1_SEL_MASK, 0x0);
regmap_update_bits(rt5677->regmap, RT5677_PWR_ANLG2, regmap_update_bits(rt5677->regmap, RT5677_PWR_ANLG2,
RT5677_PWR_LDO1, RT5677_PWR_LDO1); RT5677_PWR_LDO1, RT5677_PWR_LDO1);
regmap_update_bits(rt5677->regmap, RT5677_GLB_CLK1, switch (rt5677->type) {
RT5677_MCLK_SRC_MASK, RT5677_MCLK2_SRC); case RT5677:
regmap_update_bits(rt5677->regmap, RT5677_GLB_CLK2, regmap_update_bits(rt5677->regmap, RT5677_GLB_CLK1,
RT5677_PLL2_PR_SRC_MASK | RT5677_DSP_CLK_SRC_MASK, RT5677_MCLK_SRC_MASK, RT5677_MCLK2_SRC);
RT5677_PLL2_PR_SRC_MCLK2 | RT5677_DSP_CLK_SRC_BYPASS); regmap_update_bits(rt5677->regmap, RT5677_GLB_CLK2,
RT5677_PLL2_PR_SRC_MASK |
RT5677_DSP_CLK_SRC_MASK,
RT5677_PLL2_PR_SRC_MCLK2 |
RT5677_DSP_CLK_SRC_BYPASS);
break;
case RT5676:
regmap_update_bits(rt5677->regmap, RT5677_GLB_CLK2,
RT5677_DSP_CLK_SRC_MASK,
RT5677_DSP_CLK_SRC_BYPASS);
break;
default:
break;
}
regmap_write(rt5677->regmap, RT5677_PWR_DSP2, 0x07ff); regmap_write(rt5677->regmap, RT5677_PWR_DSP2, 0x07ff);
regmap_write(rt5677->regmap, RT5677_PWR_DSP1, 0x07fd); regmap_write(rt5677->regmap, RT5677_PWR_DSP1, 0x07fd);
rt5677_set_dsp_mode(codec, true); rt5677_set_dsp_mode(codec, true);
...@@ -4500,10 +4513,10 @@ static int rt5677_suspend(struct snd_soc_codec *codec) ...@@ -4500,10 +4513,10 @@ static int rt5677_suspend(struct snd_soc_codec *codec)
if (!rt5677->dsp_vad_en) { if (!rt5677->dsp_vad_en) {
regcache_cache_only(rt5677->regmap, true); regcache_cache_only(rt5677->regmap, true);
regcache_mark_dirty(rt5677->regmap); regcache_mark_dirty(rt5677->regmap);
}
if (gpio_is_valid(rt5677->pow_ldo2)) if (gpio_is_valid(rt5677->pow_ldo2))
gpio_set_value_cansleep(rt5677->pow_ldo2, 0); gpio_set_value_cansleep(rt5677->pow_ldo2, 0);
}
return 0; return 0;
} }
...@@ -4512,12 +4525,12 @@ static int rt5677_resume(struct snd_soc_codec *codec) ...@@ -4512,12 +4525,12 @@ static int rt5677_resume(struct snd_soc_codec *codec)
{ {
struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);
if (gpio_is_valid(rt5677->pow_ldo2)) {
gpio_set_value_cansleep(rt5677->pow_ldo2, 1);
msleep(10);
}
if (!rt5677->dsp_vad_en) { if (!rt5677->dsp_vad_en) {
if (gpio_is_valid(rt5677->pow_ldo2)) {
gpio_set_value_cansleep(rt5677->pow_ldo2, 1);
msleep(10);
}
regcache_cache_only(rt5677->regmap, false); regcache_cache_only(rt5677->regmap, false);
regcache_sync(rt5677->regmap); regcache_sync(rt5677->regmap);
} }
...@@ -4733,7 +4746,8 @@ static const struct regmap_config rt5677_regmap = { ...@@ -4733,7 +4746,8 @@ static const struct regmap_config rt5677_regmap = {
}; };
static const struct i2c_device_id rt5677_i2c_id[] = { static const struct i2c_device_id rt5677_i2c_id[] = {
{ "rt5677", 0 }, { "rt5677", RT5677 },
{ "rt5676", RT5676 },
{ } { }
}; };
MODULE_DEVICE_TABLE(i2c, rt5677_i2c_id); MODULE_DEVICE_TABLE(i2c, rt5677_i2c_id);
...@@ -4850,6 +4864,8 @@ static int rt5677_i2c_probe(struct i2c_client *i2c, ...@@ -4850,6 +4864,8 @@ static int rt5677_i2c_probe(struct i2c_client *i2c,
i2c_set_clientdata(i2c, rt5677); i2c_set_clientdata(i2c, rt5677);
rt5677->type = id->driver_data;
if (pdata) if (pdata)
rt5677->pdata = *pdata; rt5677->pdata = *pdata;
......
...@@ -1665,6 +1665,11 @@ enum { ...@@ -1665,6 +1665,11 @@ enum {
RT5677_IRQ_JD3, RT5677_IRQ_JD3,
}; };
enum rt5677_type {
RT5677,
RT5676,
};
struct rt5677_priv { struct rt5677_priv {
struct snd_soc_codec *codec; struct snd_soc_codec *codec;
struct rt5677_platform_data pdata; struct rt5677_platform_data pdata;
...@@ -1681,6 +1686,7 @@ struct rt5677_priv { ...@@ -1681,6 +1686,7 @@ struct rt5677_priv {
int pll_in; int pll_in;
int pll_out; int pll_out;
int pow_ldo2; /* POW_LDO2 pin */ int pow_ldo2; /* POW_LDO2 pin */
enum rt5677_type type;
#ifdef CONFIG_GPIOLIB #ifdef CONFIG_GPIOLIB
struct gpio_chip gpio_chip; struct gpio_chip gpio_chip;
#endif #endif
......
...@@ -783,19 +783,21 @@ static inline void sn95031_enable_jack_btn(struct snd_soc_codec *codec) ...@@ -783,19 +783,21 @@ static inline void sn95031_enable_jack_btn(struct snd_soc_codec *codec)
snd_soc_write(codec, SN95031_BTNCTRL2, 0x01); snd_soc_write(codec, SN95031_BTNCTRL2, 0x01);
} }
static int sn95031_get_headset_state(struct snd_soc_jack *mfld_jack) static int sn95031_get_headset_state(struct snd_soc_codec *codec,
struct snd_soc_jack *mfld_jack)
{ {
int micbias = sn95031_get_mic_bias(mfld_jack->codec); int micbias = sn95031_get_mic_bias(codec);
int jack_type = snd_soc_jack_get_type(mfld_jack, micbias); int jack_type = snd_soc_jack_get_type(mfld_jack, micbias);
pr_debug("jack type detected = %d\n", jack_type); pr_debug("jack type detected = %d\n", jack_type);
if (jack_type == SND_JACK_HEADSET) if (jack_type == SND_JACK_HEADSET)
sn95031_enable_jack_btn(mfld_jack->codec); sn95031_enable_jack_btn(codec);
return jack_type; return jack_type;
} }
void sn95031_jack_detection(struct mfld_jack_data *jack_data) void sn95031_jack_detection(struct snd_soc_codec *codec,
struct mfld_jack_data *jack_data)
{ {
unsigned int status; unsigned int status;
unsigned int mask = SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_HEADSET; unsigned int mask = SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_HEADSET;
...@@ -809,11 +811,11 @@ void sn95031_jack_detection(struct mfld_jack_data *jack_data) ...@@ -809,11 +811,11 @@ void sn95031_jack_detection(struct mfld_jack_data *jack_data)
status = SND_JACK_HEADSET | SND_JACK_BTN_1; status = SND_JACK_HEADSET | SND_JACK_BTN_1;
} else if (jack_data->intr_id & 0x4) { } else if (jack_data->intr_id & 0x4) {
pr_debug("headset or headphones inserted\n"); pr_debug("headset or headphones inserted\n");
status = sn95031_get_headset_state(jack_data->mfld_jack); status = sn95031_get_headset_state(codec, jack_data->mfld_jack);
} else if (jack_data->intr_id & 0x8) { } else if (jack_data->intr_id & 0x8) {
pr_debug("headset or headphones removed\n"); pr_debug("headset or headphones removed\n");
status = 0; status = 0;
sn95031_disable_jack_btn(jack_data->mfld_jack->codec); sn95031_disable_jack_btn(codec);
} else { } else {
pr_err("unidentified interrupt\n"); pr_err("unidentified interrupt\n");
return; return;
......
...@@ -127,6 +127,7 @@ struct mfld_jack_data { ...@@ -127,6 +127,7 @@ struct mfld_jack_data {
struct snd_soc_jack *mfld_jack; struct snd_soc_jack *mfld_jack;
}; };
extern void sn95031_jack_detection(struct mfld_jack_data *jack_data); extern void sn95031_jack_detection(struct snd_soc_codec *codec,
struct mfld_jack_data *jack_data);
#endif #endif
...@@ -1213,27 +1213,15 @@ static int sta350_i2c_probe(struct i2c_client *i2c, ...@@ -1213,27 +1213,15 @@ static int sta350_i2c_probe(struct i2c_client *i2c,
#endif #endif
/* GPIOs */ /* GPIOs */
sta350->gpiod_nreset = devm_gpiod_get(dev, "reset"); sta350->gpiod_nreset = devm_gpiod_get_optional(dev, "reset",
if (IS_ERR(sta350->gpiod_nreset)) { GPIOD_OUT_LOW);
ret = PTR_ERR(sta350->gpiod_nreset); if (IS_ERR(sta350->gpiod_nreset))
if (ret != -ENOENT && ret != -ENOSYS) return PTR_ERR(sta350->gpiod_nreset);
return ret;
sta350->gpiod_power_down = devm_gpiod_get(dev, "power-down",
sta350->gpiod_nreset = NULL; GPIOD_OUT_LOW);
} else { if (IS_ERR(sta350->gpiod_power_down))
gpiod_direction_output(sta350->gpiod_nreset, 0); return PTR_ERR(sta350->gpiod_power_down);
}
sta350->gpiod_power_down = devm_gpiod_get(dev, "power-down");
if (IS_ERR(sta350->gpiod_power_down)) {
ret = PTR_ERR(sta350->gpiod_power_down);
if (ret != -ENOENT && ret != -ENOSYS)
return ret;
sta350->gpiod_power_down = NULL;
} else {
gpiod_direction_output(sta350->gpiod_power_down, 0);
}
/* regulators */ /* regulators */
for (i = 0; i < ARRAY_SIZE(sta350->supplies); i++) for (i = 0; i < ARRAY_SIZE(sta350->supplies); i++)
......
...@@ -485,16 +485,9 @@ static int tas2552_probe(struct i2c_client *client, ...@@ -485,16 +485,9 @@ static int tas2552_probe(struct i2c_client *client,
if (data == NULL) if (data == NULL)
return -ENOMEM; return -ENOMEM;
data->enable_gpio = devm_gpiod_get(dev, "enable"); data->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW);
if (IS_ERR(data->enable_gpio)) { if (IS_ERR(data->enable_gpio))
ret = PTR_ERR(data->enable_gpio); return PTR_ERR(data->enable_gpio);
if (ret != -ENOENT && ret != -ENOSYS)
return ret;
data->enable_gpio = NULL;
} else {
gpiod_direction_output(data->enable_gpio, 0);
}
data->tas2552_client = client; data->tas2552_client = client;
data->regmap = devm_regmap_init_i2c(client, &tas2552_regmap_config); data->regmap = devm_regmap_init_i2c(client, &tas2552_regmap_config);
......
/*
* wm8804-i2c.c -- WM8804 S/PDIF transceiver driver - I2C
*
* Copyright 2015 Cirrus Logic Inc
*
* Author: Charles Keepax <ckeepax@opensource.wolfsonmicro.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 as
* published by the Free Software Foundation.
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include "wm8804.h"
static int wm8804_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct regmap *regmap;
regmap = devm_regmap_init_i2c(i2c, &wm8804_regmap_config);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
return wm8804_probe(&i2c->dev, regmap);
}
static int wm8804_i2c_remove(struct i2c_client *i2c)
{
wm8804_remove(&i2c->dev);
return 0;
}
static const struct i2c_device_id wm8804_i2c_id[] = {
{ "wm8804", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, wm8804_i2c_id);
static const struct of_device_id wm8804_of_match[] = {
{ .compatible = "wlf,wm8804", },
{ }
};
MODULE_DEVICE_TABLE(of, wm8804_of_match);
static struct i2c_driver wm8804_i2c_driver = {
.driver = {
.name = "wm8804",
.owner = THIS_MODULE,
.of_match_table = wm8804_of_match,
},
.probe = wm8804_i2c_probe,
.remove = wm8804_i2c_remove,
.id_table = wm8804_i2c_id
};
module_i2c_driver(wm8804_i2c_driver);
MODULE_DESCRIPTION("ASoC WM8804 driver - I2C");
MODULE_AUTHOR("Charles Keepax <ckeepax@opensource.wolfsonmicro.com>");
MODULE_LICENSE("GPL");
/*
* wm8804-spi.c -- WM8804 S/PDIF transceiver driver - SPI
*
* Copyright 2015 Cirrus Logic Inc
*
* Author: Charles Keepax <ckeepax@opensource.wolfsonmicro.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 as
* published by the Free Software Foundation.
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/spi/spi.h>
#include "wm8804.h"
static int wm8804_spi_probe(struct spi_device *spi)
{
struct regmap *regmap;
regmap = devm_regmap_init_spi(spi, &wm8804_regmap_config);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
return wm8804_probe(&spi->dev, regmap);
}
static int wm8804_spi_remove(struct spi_device *spi)
{
wm8804_remove(&spi->dev);
return 0;
}
static const struct of_device_id wm8804_of_match[] = {
{ .compatible = "wlf,wm8804", },
{ }
};
MODULE_DEVICE_TABLE(of, wm8804_of_match);
static struct spi_driver wm8804_spi_driver = {
.driver = {
.name = "wm8804",
.owner = THIS_MODULE,
.of_match_table = wm8804_of_match,
},
.probe = wm8804_spi_probe,
.remove = wm8804_spi_remove
};
module_spi_driver(wm8804_spi_driver);
MODULE_DESCRIPTION("ASoC WM8804 driver - SPI");
MODULE_AUTHOR("Charles Keepax <ckeepax@opensource.wolfsonmicro.com>");
MODULE_LICENSE("GPL");
...@@ -15,10 +15,7 @@ ...@@ -15,10 +15,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/i2c.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/spi/spi.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <sound/core.h> #include <sound/core.h>
...@@ -185,9 +182,9 @@ static bool wm8804_volatile(struct device *dev, unsigned int reg) ...@@ -185,9 +182,9 @@ static bool wm8804_volatile(struct device *dev, unsigned int reg)
} }
} }
static int wm8804_reset(struct snd_soc_codec *codec) static int wm8804_reset(struct wm8804_priv *wm8804)
{ {
return snd_soc_write(codec, WM8804_RST_DEVID1, 0x0); return regmap_write(wm8804->regmap, WM8804_RST_DEVID1, 0x0);
} }
static int wm8804_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) static int wm8804_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
...@@ -518,100 +515,6 @@ static int wm8804_set_bias_level(struct snd_soc_codec *codec, ...@@ -518,100 +515,6 @@ static int wm8804_set_bias_level(struct snd_soc_codec *codec,
return 0; return 0;
} }
static int wm8804_remove(struct snd_soc_codec *codec)
{
struct wm8804_priv *wm8804;
int i;
wm8804 = snd_soc_codec_get_drvdata(codec);
for (i = 0; i < ARRAY_SIZE(wm8804->supplies); ++i)
regulator_unregister_notifier(wm8804->supplies[i].consumer,
&wm8804->disable_nb[i]);
return 0;
}
static int wm8804_probe(struct snd_soc_codec *codec)
{
struct wm8804_priv *wm8804;
int i, id1, id2, ret;
wm8804 = snd_soc_codec_get_drvdata(codec);
for (i = 0; i < ARRAY_SIZE(wm8804->supplies); i++)
wm8804->supplies[i].supply = wm8804_supply_names[i];
ret = devm_regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8804->supplies),
wm8804->supplies);
if (ret) {
dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
return ret;
}
wm8804->disable_nb[0].notifier_call = wm8804_regulator_event_0;
wm8804->disable_nb[1].notifier_call = wm8804_regulator_event_1;
/* This should really be moved into the regulator core */
for (i = 0; i < ARRAY_SIZE(wm8804->supplies); i++) {
ret = regulator_register_notifier(wm8804->supplies[i].consumer,
&wm8804->disable_nb[i]);
if (ret != 0) {
dev_err(codec->dev,
"Failed to register regulator notifier: %d\n",
ret);
}
}
ret = regulator_bulk_enable(ARRAY_SIZE(wm8804->supplies),
wm8804->supplies);
if (ret) {
dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
return ret;
}
id1 = snd_soc_read(codec, WM8804_RST_DEVID1);
if (id1 < 0) {
dev_err(codec->dev, "Failed to read device ID: %d\n", id1);
ret = id1;
goto err_reg_enable;
}
id2 = snd_soc_read(codec, WM8804_DEVID2);
if (id2 < 0) {
dev_err(codec->dev, "Failed to read device ID: %d\n", id2);
ret = id2;
goto err_reg_enable;
}
id2 = (id2 << 8) | id1;
if (id2 != 0x8805) {
dev_err(codec->dev, "Invalid device ID: %#x\n", id2);
ret = -EINVAL;
goto err_reg_enable;
}
ret = snd_soc_read(codec, WM8804_DEVREV);
if (ret < 0) {
dev_err(codec->dev, "Failed to read device revision: %d\n",
ret);
goto err_reg_enable;
}
dev_info(codec->dev, "revision %c\n", ret + 'A');
ret = wm8804_reset(codec);
if (ret < 0) {
dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
goto err_reg_enable;
}
return 0;
err_reg_enable:
regulator_bulk_disable(ARRAY_SIZE(wm8804->supplies), wm8804->supplies);
return ret;
}
static const struct snd_soc_dai_ops wm8804_dai_ops = { static const struct snd_soc_dai_ops wm8804_dai_ops = {
.hw_params = wm8804_hw_params, .hw_params = wm8804_hw_params,
.set_fmt = wm8804_set_fmt, .set_fmt = wm8804_set_fmt,
...@@ -649,8 +552,6 @@ static struct snd_soc_dai_driver wm8804_dai = { ...@@ -649,8 +552,6 @@ static struct snd_soc_dai_driver wm8804_dai = {
}; };
static const struct snd_soc_codec_driver soc_codec_dev_wm8804 = { static const struct snd_soc_codec_driver soc_codec_dev_wm8804 = {
.probe = wm8804_probe,
.remove = wm8804_remove,
.set_bias_level = wm8804_set_bias_level, .set_bias_level = wm8804_set_bias_level,
.idle_bias_off = true, .idle_bias_off = true,
...@@ -658,13 +559,7 @@ static const struct snd_soc_codec_driver soc_codec_dev_wm8804 = { ...@@ -658,13 +559,7 @@ static const struct snd_soc_codec_driver soc_codec_dev_wm8804 = {
.num_controls = ARRAY_SIZE(wm8804_snd_controls), .num_controls = ARRAY_SIZE(wm8804_snd_controls),
}; };
static const struct of_device_id wm8804_of_match[] = { const struct regmap_config wm8804_regmap_config = {
{ .compatible = "wlf,wm8804", },
{ }
};
MODULE_DEVICE_TABLE(of, wm8804_of_match);
static const struct regmap_config wm8804_regmap_config = {
.reg_bits = 8, .reg_bits = 8,
.val_bits = 8, .val_bits = 8,
...@@ -675,128 +570,110 @@ static const struct regmap_config wm8804_regmap_config = { ...@@ -675,128 +570,110 @@ static const struct regmap_config wm8804_regmap_config = {
.reg_defaults = wm8804_reg_defaults, .reg_defaults = wm8804_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(wm8804_reg_defaults), .num_reg_defaults = ARRAY_SIZE(wm8804_reg_defaults),
}; };
EXPORT_SYMBOL_GPL(wm8804_regmap_config);
#if defined(CONFIG_SPI_MASTER) int wm8804_probe(struct device *dev, struct regmap *regmap)
static int wm8804_spi_probe(struct spi_device *spi)
{ {
struct wm8804_priv *wm8804; struct wm8804_priv *wm8804;
int ret; unsigned int id1, id2;
int i, ret;
wm8804 = devm_kzalloc(&spi->dev, sizeof *wm8804, GFP_KERNEL); wm8804 = devm_kzalloc(dev, sizeof(*wm8804), GFP_KERNEL);
if (!wm8804) if (!wm8804)
return -ENOMEM; return -ENOMEM;
wm8804->regmap = devm_regmap_init_spi(spi, &wm8804_regmap_config); dev_set_drvdata(dev, wm8804);
if (IS_ERR(wm8804->regmap)) {
ret = PTR_ERR(wm8804->regmap); wm8804->regmap = regmap;
for (i = 0; i < ARRAY_SIZE(wm8804->supplies); i++)
wm8804->supplies[i].supply = wm8804_supply_names[i];
ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(wm8804->supplies),
wm8804->supplies);
if (ret) {
dev_err(dev, "Failed to request supplies: %d\n", ret);
return ret; return ret;
} }
spi_set_drvdata(spi, wm8804); wm8804->disable_nb[0].notifier_call = wm8804_regulator_event_0;
wm8804->disable_nb[1].notifier_call = wm8804_regulator_event_1;
ret = snd_soc_register_codec(&spi->dev, /* This should really be moved into the regulator core */
&soc_codec_dev_wm8804, &wm8804_dai, 1); for (i = 0; i < ARRAY_SIZE(wm8804->supplies); i++) {
ret = regulator_register_notifier(wm8804->supplies[i].consumer,
&wm8804->disable_nb[i]);
if (ret != 0) {
dev_err(dev,
"Failed to register regulator notifier: %d\n",
ret);
}
}
return ret; ret = regulator_bulk_enable(ARRAY_SIZE(wm8804->supplies),
} wm8804->supplies);
if (ret) {
dev_err(dev, "Failed to enable supplies: %d\n", ret);
goto err_reg_enable;
}
static int wm8804_spi_remove(struct spi_device *spi) ret = regmap_read(regmap, WM8804_RST_DEVID1, &id1);
{ if (ret < 0) {
snd_soc_unregister_codec(&spi->dev); dev_err(dev, "Failed to read device ID: %d\n", ret);
return 0; goto err_reg_enable;
} }
static struct spi_driver wm8804_spi_driver = { ret = regmap_read(regmap, WM8804_DEVID2, &id2);
.driver = { if (ret < 0) {
.name = "wm8804", dev_err(dev, "Failed to read device ID: %d\n", ret);
.owner = THIS_MODULE, goto err_reg_enable;
.of_match_table = wm8804_of_match, }
},
.probe = wm8804_spi_probe,
.remove = wm8804_spi_remove
};
#endif
#if IS_ENABLED(CONFIG_I2C) id2 = (id2 << 8) | id1;
static int wm8804_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct wm8804_priv *wm8804;
int ret;
wm8804 = devm_kzalloc(&i2c->dev, sizeof *wm8804, GFP_KERNEL); if (id2 != 0x8805) {
if (!wm8804) dev_err(dev, "Invalid device ID: %#x\n", id2);
return -ENOMEM; ret = -EINVAL;
goto err_reg_enable;
}
wm8804->regmap = devm_regmap_init_i2c(i2c, &wm8804_regmap_config); ret = regmap_read(regmap, WM8804_DEVREV, &id1);
if (IS_ERR(wm8804->regmap)) { if (ret < 0) {
ret = PTR_ERR(wm8804->regmap); dev_err(dev, "Failed to read device revision: %d\n",
return ret; ret);
goto err_reg_enable;
} }
dev_info(dev, "revision %c\n", id1 + 'A');
i2c_set_clientdata(i2c, wm8804); ret = wm8804_reset(wm8804);
if (ret < 0) {
dev_err(dev, "Failed to issue reset: %d\n", ret);
goto err_reg_enable;
}
ret = snd_soc_register_codec(&i2c->dev, return snd_soc_register_codec(dev, &soc_codec_dev_wm8804,
&soc_codec_dev_wm8804, &wm8804_dai, 1); &wm8804_dai, 1);
err_reg_enable:
regulator_bulk_disable(ARRAY_SIZE(wm8804->supplies), wm8804->supplies);
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(wm8804_probe);
static int wm8804_i2c_remove(struct i2c_client *i2c) void wm8804_remove(struct device *dev)
{ {
snd_soc_unregister_codec(&i2c->dev); struct wm8804_priv *wm8804;
return 0; int i;
}
static const struct i2c_device_id wm8804_i2c_id[] = {
{ "wm8804", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, wm8804_i2c_id);
static struct i2c_driver wm8804_i2c_driver = {
.driver = {
.name = "wm8804",
.owner = THIS_MODULE,
.of_match_table = wm8804_of_match,
},
.probe = wm8804_i2c_probe,
.remove = wm8804_i2c_remove,
.id_table = wm8804_i2c_id
};
#endif
static int __init wm8804_modinit(void) wm8804 = dev_get_drvdata(dev);
{
int ret = 0;
#if IS_ENABLED(CONFIG_I2C) for (i = 0; i < ARRAY_SIZE(wm8804->supplies); ++i)
ret = i2c_add_driver(&wm8804_i2c_driver); regulator_unregister_notifier(wm8804->supplies[i].consumer,
if (ret) { &wm8804->disable_nb[i]);
printk(KERN_ERR "Failed to register wm8804 I2C driver: %d\n",
ret);
}
#endif
#if defined(CONFIG_SPI_MASTER)
ret = spi_register_driver(&wm8804_spi_driver);
if (ret != 0) {
printk(KERN_ERR "Failed to register wm8804 SPI driver: %d\n",
ret);
}
#endif
return ret;
}
module_init(wm8804_modinit);
static void __exit wm8804_exit(void) snd_soc_unregister_codec(dev);
{
#if IS_ENABLED(CONFIG_I2C)
i2c_del_driver(&wm8804_i2c_driver);
#endif
#if defined(CONFIG_SPI_MASTER)
spi_unregister_driver(&wm8804_spi_driver);
#endif
} }
module_exit(wm8804_exit); EXPORT_SYMBOL_GPL(wm8804_remove);
MODULE_DESCRIPTION("ASoC WM8804 driver"); MODULE_DESCRIPTION("ASoC WM8804 driver");
MODULE_AUTHOR("Dimitris Papastamos <dp@opensource.wolfsonmicro.com>"); MODULE_AUTHOR("Dimitris Papastamos <dp@opensource.wolfsonmicro.com>");
......
...@@ -13,6 +13,8 @@ ...@@ -13,6 +13,8 @@
#ifndef _WM8804_H #ifndef _WM8804_H
#define _WM8804_H #define _WM8804_H
#include <linux/regmap.h>
/* /*
* Register values. * Register values.
*/ */
...@@ -62,4 +64,9 @@ ...@@ -62,4 +64,9 @@
#define WM8804_MCLKDIV_256FS 0 #define WM8804_MCLKDIV_256FS 0
#define WM8804_MCLKDIV_128FS 1 #define WM8804_MCLKDIV_128FS 1
extern const struct regmap_config wm8804_regmap_config;
int wm8804_probe(struct device *dev, struct regmap *regmap);
void wm8804_remove(struct device *dev);
#endif /* _WM8804_H */ #endif /* _WM8804_H */
...@@ -420,10 +420,9 @@ static int wm_coeff_put(struct snd_kcontrol *kcontrol, ...@@ -420,10 +420,9 @@ static int wm_coeff_put(struct snd_kcontrol *kcontrol,
memcpy(ctl->cache, p, ctl->len); memcpy(ctl->cache, p, ctl->len);
if (!ctl->enabled) { ctl->set = 1;
ctl->set = 1; if (!ctl->enabled)
return 0; return 0;
}
return wm_coeff_write_control(kcontrol, p, ctl->len); return wm_coeff_write_control(kcontrol, p, ctl->len);
} }
...@@ -1185,7 +1184,6 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp) ...@@ -1185,7 +1184,6 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp)
int ret, pos, blocks, type, offset, reg; int ret, pos, blocks, type, offset, reg;
char *file; char *file;
struct wm_adsp_buf *buf; struct wm_adsp_buf *buf;
int tmp;
file = kzalloc(PAGE_SIZE, GFP_KERNEL); file = kzalloc(PAGE_SIZE, GFP_KERNEL);
if (file == NULL) if (file == NULL)
...@@ -1335,12 +1333,7 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp) ...@@ -1335,12 +1333,7 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp)
} }
} }
tmp = le32_to_cpu(blk->len) % 4; pos += (le32_to_cpu(blk->len) + sizeof(*blk) + 3) & ~0x03;
if (tmp)
pos += le32_to_cpu(blk->len) + (4 - tmp) + sizeof(*blk);
else
pos += le32_to_cpu(blk->len) + sizeof(*blk);
blocks++; blocks++;
} }
......
config SND_DAVINCI_SOC config SND_DAVINCI_SOC
tristate "SoC Audio for TI DAVINCI" tristate
depends on ARCH_DAVINCI depends on ARCH_DAVINCI
select SND_EDMA_SOC
config SND_EDMA_SOC config SND_EDMA_SOC
tristate "SoC Audio for Texas Instruments chips using eDMA (AM33XX/43XX)" tristate "SoC Audio for Texas Instruments chips using eDMA"
depends on SOC_AM33XX || SOC_AM43XX depends on SOC_AM33XX || SOC_AM43XX || ARCH_DAVINCI
select SND_SOC_GENERIC_DMAENGINE_PCM select SND_SOC_GENERIC_DMAENGINE_PCM
help help
Say Y or M here if you want audio support for TI SoC which uses eDMA. Say Y or M here if you want audio support for TI SoC which uses eDMA.
The following line of SoCs are supported by this platform driver: The following line of SoCs are supported by this platform driver:
- daVinci devices
- AM335x - AM335x
- AM437x/AM438x - AM437x/AM438x
...@@ -17,7 +19,7 @@ config SND_DAVINCI_SOC_I2S ...@@ -17,7 +19,7 @@ config SND_DAVINCI_SOC_I2S
config SND_DAVINCI_SOC_MCASP config SND_DAVINCI_SOC_MCASP
tristate "Multichannel Audio Serial Port (McASP) support" tristate "Multichannel Audio Serial Port (McASP) support"
depends on SND_DAVINCI_SOC || SND_OMAP_SOC || SND_EDMA_SOC depends on SND_OMAP_SOC || SND_EDMA_SOC
help help
Say Y or M here if you want to have support for McASP IP found in Say Y or M here if you want to have support for McASP IP found in
various Texas Instruments SoCs like: various Texas Instruments SoCs like:
...@@ -45,7 +47,7 @@ config SND_AM33XX_SOC_EVM ...@@ -45,7 +47,7 @@ config SND_AM33XX_SOC_EVM
config SND_DAVINCI_SOC_EVM config SND_DAVINCI_SOC_EVM
tristate "SoC Audio support for DaVinci DM6446, DM355 or DM365 EVM" tristate "SoC Audio support for DaVinci DM6446, DM355 or DM365 EVM"
depends on SND_DAVINCI_SOC && I2C depends on SND_EDMA_SOC && I2C
depends on MACH_DAVINCI_EVM || MACH_DAVINCI_DM355_EVM || MACH_DAVINCI_DM365_EVM depends on MACH_DAVINCI_EVM || MACH_DAVINCI_DM355_EVM || MACH_DAVINCI_DM365_EVM
select SND_DAVINCI_SOC_GENERIC_EVM select SND_DAVINCI_SOC_GENERIC_EVM
help help
...@@ -73,7 +75,7 @@ endchoice ...@@ -73,7 +75,7 @@ endchoice
config SND_DM6467_SOC_EVM config SND_DM6467_SOC_EVM
tristate "SoC Audio support for DaVinci DM6467 EVM" tristate "SoC Audio support for DaVinci DM6467 EVM"
depends on SND_DAVINCI_SOC && MACH_DAVINCI_DM6467_EVM && I2C depends on SND_EDMA_SOC && MACH_DAVINCI_DM6467_EVM && I2C
select SND_DAVINCI_SOC_GENERIC_EVM select SND_DAVINCI_SOC_GENERIC_EVM
select SND_SOC_SPDIF select SND_SOC_SPDIF
...@@ -82,7 +84,7 @@ config SND_DM6467_SOC_EVM ...@@ -82,7 +84,7 @@ config SND_DM6467_SOC_EVM
config SND_DA830_SOC_EVM config SND_DA830_SOC_EVM
tristate "SoC Audio support for DA830/OMAP-L137 EVM" tristate "SoC Audio support for DA830/OMAP-L137 EVM"
depends on SND_DAVINCI_SOC && MACH_DAVINCI_DA830_EVM && I2C depends on SND_EDMA_SOC && MACH_DAVINCI_DA830_EVM && I2C
select SND_DAVINCI_SOC_GENERIC_EVM select SND_DAVINCI_SOC_GENERIC_EVM
help help
...@@ -91,7 +93,7 @@ config SND_DA830_SOC_EVM ...@@ -91,7 +93,7 @@ config SND_DA830_SOC_EVM
config SND_DA850_SOC_EVM config SND_DA850_SOC_EVM
tristate "SoC Audio support for DA850/OMAP-L138 EVM" tristate "SoC Audio support for DA850/OMAP-L138 EVM"
depends on SND_DAVINCI_SOC && MACH_DAVINCI_DA850_EVM && I2C depends on SND_EDMA_SOC && MACH_DAVINCI_DA850_EVM && I2C
select SND_DAVINCI_SOC_GENERIC_EVM select SND_DAVINCI_SOC_GENERIC_EVM
help help
Say Y if you want to add support for SoC audio on TI Say Y if you want to add support for SoC audio on TI
......
# DAVINCI Platform Support # DAVINCI Platform Support
snd-soc-davinci-objs := davinci-pcm.o
snd-soc-edma-objs := edma-pcm.o snd-soc-edma-objs := edma-pcm.o
snd-soc-davinci-i2s-objs := davinci-i2s.o snd-soc-davinci-i2s-objs := davinci-i2s.o
snd-soc-davinci-mcasp-objs:= davinci-mcasp.o snd-soc-davinci-mcasp-objs:= davinci-mcasp.o
snd-soc-davinci-vcif-objs:= davinci-vcif.o snd-soc-davinci-vcif-objs:= davinci-vcif.o
obj-$(CONFIG_SND_DAVINCI_SOC) += snd-soc-davinci.o
obj-$(CONFIG_SND_EDMA_SOC) += snd-soc-edma.o obj-$(CONFIG_SND_EDMA_SOC) += snd-soc-edma.o
obj-$(CONFIG_SND_DAVINCI_SOC_I2S) += snd-soc-davinci-i2s.o obj-$(CONFIG_SND_DAVINCI_SOC_I2S) += snd-soc-davinci-i2s.o
obj-$(CONFIG_SND_DAVINCI_SOC_MCASP) += snd-soc-davinci-mcasp.o obj-$(CONFIG_SND_DAVINCI_SOC_MCASP) += snd-soc-davinci-mcasp.o
......
...@@ -23,8 +23,9 @@ ...@@ -23,8 +23,9 @@
#include <sound/pcm_params.h> #include <sound/pcm_params.h>
#include <sound/initval.h> #include <sound/initval.h>
#include <sound/soc.h> #include <sound/soc.h>
#include <sound/dmaengine_pcm.h>
#include "davinci-pcm.h" #include "edma-pcm.h"
#include "davinci-i2s.h" #include "davinci-i2s.h"
...@@ -122,7 +123,8 @@ static const unsigned char double_fmt[SNDRV_PCM_FORMAT_S32_LE + 1] = { ...@@ -122,7 +123,8 @@ static const unsigned char double_fmt[SNDRV_PCM_FORMAT_S32_LE + 1] = {
struct davinci_mcbsp_dev { struct davinci_mcbsp_dev {
struct device *dev; struct device *dev;
struct davinci_pcm_dma_params dma_params[2]; struct snd_dmaengine_dai_dma_data dma_data[2];
int dma_request[2];
void __iomem *base; void __iomem *base;
#define MOD_DSP_A 0 #define MOD_DSP_A 0
#define MOD_DSP_B 1 #define MOD_DSP_B 1
...@@ -419,8 +421,6 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream, ...@@ -419,8 +421,6 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai) struct snd_soc_dai *dai)
{ {
struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai); struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai);
struct davinci_pcm_dma_params *dma_params =
&dev->dma_params[substream->stream];
struct snd_interval *i = NULL; struct snd_interval *i = NULL;
int mcbsp_word_length, master; int mcbsp_word_length, master;
unsigned int rcr, xcr, srgr, clk_div, freq, framesize; unsigned int rcr, xcr, srgr, clk_div, freq, framesize;
...@@ -532,8 +532,6 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream, ...@@ -532,8 +532,6 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
return -EINVAL; return -EINVAL;
} }
} }
dma_params->acnt = dma_params->data_type = data_type[fmt];
dma_params->fifo_level = 0;
mcbsp_word_length = asp_word_length[fmt]; mcbsp_word_length = asp_word_length[fmt];
switch (master) { switch (master) {
...@@ -600,15 +598,6 @@ static int davinci_i2s_trigger(struct snd_pcm_substream *substream, int cmd, ...@@ -600,15 +598,6 @@ static int davinci_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
return ret; return ret;
} }
static int davinci_i2s_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai);
snd_soc_dai_set_dma_data(dai, substream, dev->dma_params);
return 0;
}
static void davinci_i2s_shutdown(struct snd_pcm_substream *substream, static void davinci_i2s_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai) struct snd_soc_dai *dai)
{ {
...@@ -620,7 +609,6 @@ static void davinci_i2s_shutdown(struct snd_pcm_substream *substream, ...@@ -620,7 +609,6 @@ static void davinci_i2s_shutdown(struct snd_pcm_substream *substream,
#define DAVINCI_I2S_RATES SNDRV_PCM_RATE_8000_96000 #define DAVINCI_I2S_RATES SNDRV_PCM_RATE_8000_96000
static const struct snd_soc_dai_ops davinci_i2s_dai_ops = { static const struct snd_soc_dai_ops davinci_i2s_dai_ops = {
.startup = davinci_i2s_startup,
.shutdown = davinci_i2s_shutdown, .shutdown = davinci_i2s_shutdown,
.prepare = davinci_i2s_prepare, .prepare = davinci_i2s_prepare,
.trigger = davinci_i2s_trigger, .trigger = davinci_i2s_trigger,
...@@ -630,7 +618,18 @@ static const struct snd_soc_dai_ops davinci_i2s_dai_ops = { ...@@ -630,7 +618,18 @@ static const struct snd_soc_dai_ops davinci_i2s_dai_ops = {
}; };
static int davinci_i2s_dai_probe(struct snd_soc_dai *dai)
{
struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai);
dai->playback_dma_data = &dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK];
dai->capture_dma_data = &dev->dma_data[SNDRV_PCM_STREAM_CAPTURE];
return 0;
}
static struct snd_soc_dai_driver davinci_i2s_dai = { static struct snd_soc_dai_driver davinci_i2s_dai = {
.probe = davinci_i2s_dai_probe,
.playback = { .playback = {
.channels_min = 2, .channels_min = 2,
.channels_max = 2, .channels_max = 2,
...@@ -651,11 +650,9 @@ static const struct snd_soc_component_driver davinci_i2s_component = { ...@@ -651,11 +650,9 @@ static const struct snd_soc_component_driver davinci_i2s_component = {
static int davinci_i2s_probe(struct platform_device *pdev) static int davinci_i2s_probe(struct platform_device *pdev)
{ {
struct snd_platform_data *pdata = pdev->dev.platform_data;
struct davinci_mcbsp_dev *dev; struct davinci_mcbsp_dev *dev;
struct resource *mem, *ioarea, *res; struct resource *mem, *ioarea, *res;
enum dma_event_q asp_chan_q = EVENTQ_0; int *dma;
enum dma_event_q ram_chan_q = EVENTQ_1;
int ret; int ret;
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
...@@ -676,22 +673,6 @@ static int davinci_i2s_probe(struct platform_device *pdev) ...@@ -676,22 +673,6 @@ static int davinci_i2s_probe(struct platform_device *pdev)
GFP_KERNEL); GFP_KERNEL);
if (!dev) if (!dev)
return -ENOMEM; return -ENOMEM;
if (pdata) {
dev->enable_channel_combine = pdata->enable_channel_combine;
dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK].sram_size =
pdata->sram_size_playback;
dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].sram_size =
pdata->sram_size_capture;
dev->clk_input_pin = pdata->clk_input_pin;
dev->i2s_accurate_sck = pdata->i2s_accurate_sck;
asp_chan_q = pdata->asp_chan_q;
ram_chan_q = pdata->ram_chan_q;
}
dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK].asp_chan_q = asp_chan_q;
dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK].ram_chan_q = ram_chan_q;
dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].asp_chan_q = asp_chan_q;
dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].ram_chan_q = ram_chan_q;
dev->clk = clk_get(&pdev->dev, NULL); dev->clk = clk_get(&pdev->dev, NULL);
if (IS_ERR(dev->clk)) if (IS_ERR(dev->clk))
...@@ -705,10 +686,10 @@ static int davinci_i2s_probe(struct platform_device *pdev) ...@@ -705,10 +686,10 @@ static int davinci_i2s_probe(struct platform_device *pdev)
goto err_release_clk; goto err_release_clk;
} }
dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK].dma_addr = dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr =
(dma_addr_t)(mem->start + DAVINCI_MCBSP_DXR_REG); (dma_addr_t)(mem->start + DAVINCI_MCBSP_DXR_REG);
dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].dma_addr = dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].addr =
(dma_addr_t)(mem->start + DAVINCI_MCBSP_DRR_REG); (dma_addr_t)(mem->start + DAVINCI_MCBSP_DRR_REG);
/* first TX, then RX */ /* first TX, then RX */
...@@ -718,7 +699,9 @@ static int davinci_i2s_probe(struct platform_device *pdev) ...@@ -718,7 +699,9 @@ static int davinci_i2s_probe(struct platform_device *pdev)
ret = -ENXIO; ret = -ENXIO;
goto err_release_clk; goto err_release_clk;
} }
dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK].channel = res->start; dma = &dev->dma_request[SNDRV_PCM_STREAM_PLAYBACK];
*dma = res->start;
dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].filter_data = dma;
res = platform_get_resource(pdev, IORESOURCE_DMA, 1); res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
if (!res) { if (!res) {
...@@ -726,9 +709,11 @@ static int davinci_i2s_probe(struct platform_device *pdev) ...@@ -726,9 +709,11 @@ static int davinci_i2s_probe(struct platform_device *pdev)
ret = -ENXIO; ret = -ENXIO;
goto err_release_clk; goto err_release_clk;
} }
dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].channel = res->start; dma = &dev->dma_request[SNDRV_PCM_STREAM_CAPTURE];
dev->dev = &pdev->dev; *dma = res->start;
dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].filter_data = dma;
dev->dev = &pdev->dev;
dev_set_drvdata(&pdev->dev, dev); dev_set_drvdata(&pdev->dev, dev);
ret = snd_soc_register_component(&pdev->dev, &davinci_i2s_component, ret = snd_soc_register_component(&pdev->dev, &davinci_i2s_component,
...@@ -736,7 +721,7 @@ static int davinci_i2s_probe(struct platform_device *pdev) ...@@ -736,7 +721,7 @@ static int davinci_i2s_probe(struct platform_device *pdev)
if (ret != 0) if (ret != 0)
goto err_release_clk; goto err_release_clk;
ret = davinci_soc_platform_register(&pdev->dev); ret = edma_pcm_platform_register(&pdev->dev);
if (ret) { if (ret) {
dev_err(&pdev->dev, "register PCM failed: %d\n", ret); dev_err(&pdev->dev, "register PCM failed: %d\n", ret);
goto err_unregister_component; goto err_unregister_component;
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/platform_data/davinci_asp.h>
#include <sound/asoundef.h> #include <sound/asoundef.h>
#include <sound/core.h> #include <sound/core.h>
...@@ -36,7 +37,6 @@ ...@@ -36,7 +37,6 @@
#include <sound/dmaengine_pcm.h> #include <sound/dmaengine_pcm.h>
#include <sound/omap-pcm.h> #include <sound/omap-pcm.h>
#include "davinci-pcm.h"
#include "edma-pcm.h" #include "edma-pcm.h"
#include "davinci-mcasp.h" #include "davinci-mcasp.h"
...@@ -65,7 +65,6 @@ struct davinci_mcasp_context { ...@@ -65,7 +65,6 @@ struct davinci_mcasp_context {
}; };
struct davinci_mcasp { struct davinci_mcasp {
struct davinci_pcm_dma_params dma_params[2];
struct snd_dmaengine_dai_dma_data dma_data[2]; struct snd_dmaengine_dai_dma_data dma_data[2];
void __iomem *base; void __iomem *base;
u32 fifo_base; u32 fifo_base;
...@@ -82,6 +81,7 @@ struct davinci_mcasp { ...@@ -82,6 +81,7 @@ struct davinci_mcasp {
u16 bclk_lrclk_ratio; u16 bclk_lrclk_ratio;
int streams; int streams;
u32 irq_request[2]; u32 irq_request[2];
int dma_request[2];
int sysclk_freq; int sysclk_freq;
bool bclk_master; bool bclk_master;
...@@ -441,6 +441,18 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, ...@@ -441,6 +441,18 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AFSX | AFSR); mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AFSX | AFSR);
mcasp->bclk_master = 1; mcasp->bclk_master = 1;
break; break;
case SND_SOC_DAIFMT_CBS_CFM:
/* codec is clock slave and frame master */
mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE);
mcasp_clr_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, AFSXE);
mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
mcasp_clr_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, AFSRE);
mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, ACLKX | ACLKR);
mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AFSX | AFSR);
mcasp->bclk_master = 1;
break;
case SND_SOC_DAIFMT_CBM_CFS: case SND_SOC_DAIFMT_CBM_CFS:
/* codec is clock master and frame slave */ /* codec is clock master and frame slave */
mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE); mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE);
...@@ -631,7 +643,6 @@ static int davinci_config_channel_size(struct davinci_mcasp *mcasp, ...@@ -631,7 +643,6 @@ static int davinci_config_channel_size(struct davinci_mcasp *mcasp,
static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream, static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream,
int period_words, int channels) int period_words, int channels)
{ {
struct davinci_pcm_dma_params *dma_params = &mcasp->dma_params[stream];
struct snd_dmaengine_dai_dma_data *dma_data = &mcasp->dma_data[stream]; struct snd_dmaengine_dai_dma_data *dma_data = &mcasp->dma_data[stream];
int i; int i;
u8 tx_ser = 0; u8 tx_ser = 0;
...@@ -699,10 +710,8 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream, ...@@ -699,10 +710,8 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream,
* For example if three serializers are enabled the DMA * For example if three serializers are enabled the DMA
* need to transfer three words per DMA request. * need to transfer three words per DMA request.
*/ */
dma_params->fifo_level = active_serializers;
dma_data->maxburst = active_serializers; dma_data->maxburst = active_serializers;
} else { } else {
dma_params->fifo_level = 0;
dma_data->maxburst = 0; dma_data->maxburst = 0;
} }
return 0; return 0;
...@@ -734,7 +743,6 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream, ...@@ -734,7 +743,6 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream,
/* Configure the burst size for platform drivers */ /* Configure the burst size for platform drivers */
if (numevt == 1) if (numevt == 1)
numevt = 0; numevt = 0;
dma_params->fifo_level = numevt;
dma_data->maxburst = numevt; dma_data->maxburst = numevt;
return 0; return 0;
...@@ -860,8 +868,6 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, ...@@ -860,8 +868,6 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *cpu_dai) struct snd_soc_dai *cpu_dai)
{ {
struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai); struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai);
struct davinci_pcm_dma_params *dma_params =
&mcasp->dma_params[substream->stream];
int word_length; int word_length;
int channels = params_channels(params); int channels = params_channels(params);
int period_size = params_period_size(params); int period_size = params_period_size(params);
...@@ -902,31 +908,26 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, ...@@ -902,31 +908,26 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
switch (params_format(params)) { switch (params_format(params)) {
case SNDRV_PCM_FORMAT_U8: case SNDRV_PCM_FORMAT_U8:
case SNDRV_PCM_FORMAT_S8: case SNDRV_PCM_FORMAT_S8:
dma_params->data_type = 1;
word_length = 8; word_length = 8;
break; break;
case SNDRV_PCM_FORMAT_U16_LE: case SNDRV_PCM_FORMAT_U16_LE:
case SNDRV_PCM_FORMAT_S16_LE: case SNDRV_PCM_FORMAT_S16_LE:
dma_params->data_type = 2;
word_length = 16; word_length = 16;
break; break;
case SNDRV_PCM_FORMAT_U24_3LE: case SNDRV_PCM_FORMAT_U24_3LE:
case SNDRV_PCM_FORMAT_S24_3LE: case SNDRV_PCM_FORMAT_S24_3LE:
dma_params->data_type = 3;
word_length = 24; word_length = 24;
break; break;
case SNDRV_PCM_FORMAT_U24_LE: case SNDRV_PCM_FORMAT_U24_LE:
case SNDRV_PCM_FORMAT_S24_LE: case SNDRV_PCM_FORMAT_S24_LE:
dma_params->data_type = 4;
word_length = 24; word_length = 24;
break; break;
case SNDRV_PCM_FORMAT_U32_LE: case SNDRV_PCM_FORMAT_U32_LE:
case SNDRV_PCM_FORMAT_S32_LE: case SNDRV_PCM_FORMAT_S32_LE:
dma_params->data_type = 4;
word_length = 32; word_length = 32;
break; break;
...@@ -935,11 +936,6 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, ...@@ -935,11 +936,6 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
return -EINVAL; return -EINVAL;
} }
if (mcasp->version == MCASP_VERSION_2 && !dma_params->fifo_level)
dma_params->acnt = 4;
else
dma_params->acnt = dma_params->data_type;
davinci_config_channel_size(mcasp, word_length); davinci_config_channel_size(mcasp, word_length);
if (mcasp->op_mode == DAVINCI_MCASP_IIS_MODE) if (mcasp->op_mode == DAVINCI_MCASP_IIS_MODE)
...@@ -1043,17 +1039,8 @@ static int davinci_mcasp_dai_probe(struct snd_soc_dai *dai) ...@@ -1043,17 +1039,8 @@ static int davinci_mcasp_dai_probe(struct snd_soc_dai *dai)
{ {
struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai); struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai);
if (mcasp->version >= MCASP_VERSION_3) { dai->playback_dma_data = &mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK];
/* Using dmaengine PCM */ dai->capture_dma_data = &mcasp->dma_data[SNDRV_PCM_STREAM_CAPTURE];
dai->playback_dma_data =
&mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK];
dai->capture_dma_data =
&mcasp->dma_data[SNDRV_PCM_STREAM_CAPTURE];
} else {
/* Using davinci-pcm */
dai->playback_dma_data = mcasp->dma_params;
dai->capture_dma_data = mcasp->dma_params;
}
return 0; return 0;
} }
...@@ -1172,28 +1159,24 @@ static const struct snd_soc_component_driver davinci_mcasp_component = { ...@@ -1172,28 +1159,24 @@ static const struct snd_soc_component_driver davinci_mcasp_component = {
static struct davinci_mcasp_pdata dm646x_mcasp_pdata = { static struct davinci_mcasp_pdata dm646x_mcasp_pdata = {
.tx_dma_offset = 0x400, .tx_dma_offset = 0x400,
.rx_dma_offset = 0x400, .rx_dma_offset = 0x400,
.asp_chan_q = EVENTQ_0,
.version = MCASP_VERSION_1, .version = MCASP_VERSION_1,
}; };
static struct davinci_mcasp_pdata da830_mcasp_pdata = { static struct davinci_mcasp_pdata da830_mcasp_pdata = {
.tx_dma_offset = 0x2000, .tx_dma_offset = 0x2000,
.rx_dma_offset = 0x2000, .rx_dma_offset = 0x2000,
.asp_chan_q = EVENTQ_0,
.version = MCASP_VERSION_2, .version = MCASP_VERSION_2,
}; };
static struct davinci_mcasp_pdata am33xx_mcasp_pdata = { static struct davinci_mcasp_pdata am33xx_mcasp_pdata = {
.tx_dma_offset = 0, .tx_dma_offset = 0,
.rx_dma_offset = 0, .rx_dma_offset = 0,
.asp_chan_q = EVENTQ_0,
.version = MCASP_VERSION_3, .version = MCASP_VERSION_3,
}; };
static struct davinci_mcasp_pdata dra7_mcasp_pdata = { static struct davinci_mcasp_pdata dra7_mcasp_pdata = {
.tx_dma_offset = 0x200, .tx_dma_offset = 0x200,
.rx_dma_offset = 0x284, .rx_dma_offset = 0x284,
.asp_chan_q = EVENTQ_0,
.version = MCASP_VERSION_4, .version = MCASP_VERSION_4,
}; };
...@@ -1370,12 +1353,12 @@ static struct davinci_mcasp_pdata *davinci_mcasp_set_pdata_from_of( ...@@ -1370,12 +1353,12 @@ static struct davinci_mcasp_pdata *davinci_mcasp_set_pdata_from_of(
static int davinci_mcasp_probe(struct platform_device *pdev) static int davinci_mcasp_probe(struct platform_device *pdev)
{ {
struct davinci_pcm_dma_params *dma_params;
struct snd_dmaengine_dai_dma_data *dma_data; struct snd_dmaengine_dai_dma_data *dma_data;
struct resource *mem, *ioarea, *res, *dat; struct resource *mem, *ioarea, *res, *dat;
struct davinci_mcasp_pdata *pdata; struct davinci_mcasp_pdata *pdata;
struct davinci_mcasp *mcasp; struct davinci_mcasp *mcasp;
char *irq_name; char *irq_name;
int *dma;
int irq; int irq;
int ret; int ret;
...@@ -1509,59 +1492,45 @@ static int davinci_mcasp_probe(struct platform_device *pdev) ...@@ -1509,59 +1492,45 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
if (dat) if (dat)
mcasp->dat_port = true; mcasp->dat_port = true;
dma_params = &mcasp->dma_params[SNDRV_PCM_STREAM_PLAYBACK];
dma_data = &mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK]; dma_data = &mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK];
dma_params->asp_chan_q = pdata->asp_chan_q;
dma_params->ram_chan_q = pdata->ram_chan_q;
dma_params->sram_pool = pdata->sram_pool;
dma_params->sram_size = pdata->sram_size_playback;
if (dat) if (dat)
dma_params->dma_addr = dat->start; dma_data->addr = dat->start;
else else
dma_params->dma_addr = mem->start + pdata->tx_dma_offset; dma_data->addr = mem->start + pdata->tx_dma_offset;
/* Unconditional dmaengine stuff */
dma_data->addr = dma_params->dma_addr;
dma = &mcasp->dma_request[SNDRV_PCM_STREAM_PLAYBACK];
res = platform_get_resource(pdev, IORESOURCE_DMA, 0); res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
if (res) if (res)
dma_params->channel = res->start; *dma = res->start;
else else
dma_params->channel = pdata->tx_dma_channel; *dma = pdata->tx_dma_channel;
/* dmaengine filter data for DT and non-DT boot */ /* dmaengine filter data for DT and non-DT boot */
if (pdev->dev.of_node) if (pdev->dev.of_node)
dma_data->filter_data = "tx"; dma_data->filter_data = "tx";
else else
dma_data->filter_data = &dma_params->channel; dma_data->filter_data = dma;
/* RX is not valid in DIT mode */ /* RX is not valid in DIT mode */
if (mcasp->op_mode != DAVINCI_MCASP_DIT_MODE) { if (mcasp->op_mode != DAVINCI_MCASP_DIT_MODE) {
dma_params = &mcasp->dma_params[SNDRV_PCM_STREAM_CAPTURE];
dma_data = &mcasp->dma_data[SNDRV_PCM_STREAM_CAPTURE]; dma_data = &mcasp->dma_data[SNDRV_PCM_STREAM_CAPTURE];
dma_params->asp_chan_q = pdata->asp_chan_q;
dma_params->ram_chan_q = pdata->ram_chan_q;
dma_params->sram_pool = pdata->sram_pool;
dma_params->sram_size = pdata->sram_size_capture;
if (dat) if (dat)
dma_params->dma_addr = dat->start; dma_data->addr = dat->start;
else else
dma_params->dma_addr = mem->start + pdata->rx_dma_offset; dma_data->addr = mem->start + pdata->rx_dma_offset;
/* Unconditional dmaengine stuff */
dma_data->addr = dma_params->dma_addr;
dma = &mcasp->dma_request[SNDRV_PCM_STREAM_CAPTURE];
res = platform_get_resource(pdev, IORESOURCE_DMA, 1); res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
if (res) if (res)
dma_params->channel = res->start; *dma = res->start;
else else
dma_params->channel = pdata->rx_dma_channel; *dma = pdata->rx_dma_channel;
/* dmaengine filter data for DT and non-DT boot */ /* dmaengine filter data for DT and non-DT boot */
if (pdev->dev.of_node) if (pdev->dev.of_node)
dma_data->filter_data = "rx"; dma_data->filter_data = "rx";
else else
dma_data->filter_data = &dma_params->channel; dma_data->filter_data = dma;
} }
if (mcasp->version < MCASP_VERSION_3) { if (mcasp->version < MCASP_VERSION_3) {
...@@ -1584,17 +1553,11 @@ static int davinci_mcasp_probe(struct platform_device *pdev) ...@@ -1584,17 +1553,11 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
goto err; goto err;
switch (mcasp->version) { switch (mcasp->version) {
#if IS_BUILTIN(CONFIG_SND_DAVINCI_SOC) || \
(IS_MODULE(CONFIG_SND_DAVINCI_SOC_MCASP) && \
IS_MODULE(CONFIG_SND_DAVINCI_SOC))
case MCASP_VERSION_1:
case MCASP_VERSION_2:
ret = davinci_soc_platform_register(&pdev->dev);
break;
#endif
#if IS_BUILTIN(CONFIG_SND_EDMA_SOC) || \ #if IS_BUILTIN(CONFIG_SND_EDMA_SOC) || \
(IS_MODULE(CONFIG_SND_DAVINCI_SOC_MCASP) && \ (IS_MODULE(CONFIG_SND_DAVINCI_SOC_MCASP) && \
IS_MODULE(CONFIG_SND_EDMA_SOC)) IS_MODULE(CONFIG_SND_EDMA_SOC))
case MCASP_VERSION_1:
case MCASP_VERSION_2:
case MCASP_VERSION_3: case MCASP_VERSION_3:
ret = edma_pcm_platform_register(&pdev->dev); ret = edma_pcm_platform_register(&pdev->dev);
break; break;
......
This diff is collapsed.
/*
* ALSA PCM interface for the TI DAVINCI processor
*
* Author: Vladimir Barinov, <vbarinov@embeddedalley.com>
* Copyright: (C) 2007 MontaVista Software, Inc., <source@mvista.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 as
* published by the Free Software Foundation.
*/
#ifndef _DAVINCI_PCM_H
#define _DAVINCI_PCM_H
#include <linux/genalloc.h>
#include <linux/platform_data/davinci_asp.h>
#include <linux/platform_data/edma.h>
struct davinci_pcm_dma_params {
int channel; /* sync dma channel ID */
unsigned short acnt;
dma_addr_t dma_addr; /* device physical address for DMA */
unsigned sram_size;
struct gen_pool *sram_pool; /* SRAM gen_pool for ping pong */
enum dma_event_q asp_chan_q; /* event queue number for ASP channel */
enum dma_event_q ram_chan_q; /* event queue number for RAM channel */
unsigned char data_type; /* xfer data type */
unsigned char convert_mono_stereo;
unsigned int fifo_level;
};
#if IS_ENABLED(CONFIG_SND_DAVINCI_SOC)
int davinci_soc_platform_register(struct device *dev);
#else
static inline int davinci_soc_platform_register(struct device *dev)
{
return 0;
}
#endif /* CONFIG_SND_DAVINCI_SOC */
#endif
...@@ -33,8 +33,9 @@ ...@@ -33,8 +33,9 @@
#include <sound/pcm_params.h> #include <sound/pcm_params.h>
#include <sound/initval.h> #include <sound/initval.h>
#include <sound/soc.h> #include <sound/soc.h>
#include <sound/dmaengine_pcm.h>
#include "davinci-pcm.h" #include "edma-pcm.h"
#include "davinci-i2s.h" #include "davinci-i2s.h"
#define MOD_REG_BIT(val, mask, set) do { \ #define MOD_REG_BIT(val, mask, set) do { \
...@@ -47,7 +48,8 @@ ...@@ -47,7 +48,8 @@
struct davinci_vcif_dev { struct davinci_vcif_dev {
struct davinci_vc *davinci_vc; struct davinci_vc *davinci_vc;
struct davinci_pcm_dma_params dma_params[2]; struct snd_dmaengine_dai_dma_data dma_data[2];
int dma_request[2];
}; };
static void davinci_vcif_start(struct snd_pcm_substream *substream) static void davinci_vcif_start(struct snd_pcm_substream *substream)
...@@ -93,8 +95,6 @@ static int davinci_vcif_hw_params(struct snd_pcm_substream *substream, ...@@ -93,8 +95,6 @@ static int davinci_vcif_hw_params(struct snd_pcm_substream *substream,
{ {
struct davinci_vcif_dev *davinci_vcif_dev = snd_soc_dai_get_drvdata(dai); struct davinci_vcif_dev *davinci_vcif_dev = snd_soc_dai_get_drvdata(dai);
struct davinci_vc *davinci_vc = davinci_vcif_dev->davinci_vc; struct davinci_vc *davinci_vc = davinci_vcif_dev->davinci_vc;
struct davinci_pcm_dma_params *dma_params =
&davinci_vcif_dev->dma_params[substream->stream];
u32 w; u32 w;
/* Restart the codec before setup */ /* Restart the codec before setup */
...@@ -113,16 +113,12 @@ static int davinci_vcif_hw_params(struct snd_pcm_substream *substream, ...@@ -113,16 +113,12 @@ static int davinci_vcif_hw_params(struct snd_pcm_substream *substream,
/* Determine xfer data type */ /* Determine xfer data type */
switch (params_format(params)) { switch (params_format(params)) {
case SNDRV_PCM_FORMAT_U8: case SNDRV_PCM_FORMAT_U8:
dma_params->data_type = 0;
MOD_REG_BIT(w, DAVINCI_VC_CTRL_RD_BITS_8 | MOD_REG_BIT(w, DAVINCI_VC_CTRL_RD_BITS_8 |
DAVINCI_VC_CTRL_RD_UNSIGNED | DAVINCI_VC_CTRL_RD_UNSIGNED |
DAVINCI_VC_CTRL_WD_BITS_8 | DAVINCI_VC_CTRL_WD_BITS_8 |
DAVINCI_VC_CTRL_WD_UNSIGNED, 1); DAVINCI_VC_CTRL_WD_UNSIGNED, 1);
break; break;
case SNDRV_PCM_FORMAT_S8: case SNDRV_PCM_FORMAT_S8:
dma_params->data_type = 1;
MOD_REG_BIT(w, DAVINCI_VC_CTRL_RD_BITS_8 | MOD_REG_BIT(w, DAVINCI_VC_CTRL_RD_BITS_8 |
DAVINCI_VC_CTRL_WD_BITS_8, 1); DAVINCI_VC_CTRL_WD_BITS_8, 1);
...@@ -130,8 +126,6 @@ static int davinci_vcif_hw_params(struct snd_pcm_substream *substream, ...@@ -130,8 +126,6 @@ static int davinci_vcif_hw_params(struct snd_pcm_substream *substream,
DAVINCI_VC_CTRL_WD_UNSIGNED, 0); DAVINCI_VC_CTRL_WD_UNSIGNED, 0);
break; break;
case SNDRV_PCM_FORMAT_S16_LE: case SNDRV_PCM_FORMAT_S16_LE:
dma_params->data_type = 2;
MOD_REG_BIT(w, DAVINCI_VC_CTRL_RD_BITS_8 | MOD_REG_BIT(w, DAVINCI_VC_CTRL_RD_BITS_8 |
DAVINCI_VC_CTRL_RD_UNSIGNED | DAVINCI_VC_CTRL_RD_UNSIGNED |
DAVINCI_VC_CTRL_WD_BITS_8 | DAVINCI_VC_CTRL_WD_BITS_8 |
...@@ -142,8 +136,6 @@ static int davinci_vcif_hw_params(struct snd_pcm_substream *substream, ...@@ -142,8 +136,6 @@ static int davinci_vcif_hw_params(struct snd_pcm_substream *substream,
return -EINVAL; return -EINVAL;
} }
dma_params->acnt = dma_params->data_type;
writel(w, davinci_vc->base + DAVINCI_VC_CTRL); writel(w, davinci_vc->base + DAVINCI_VC_CTRL);
return 0; return 0;
...@@ -172,24 +164,25 @@ static int davinci_vcif_trigger(struct snd_pcm_substream *substream, int cmd, ...@@ -172,24 +164,25 @@ static int davinci_vcif_trigger(struct snd_pcm_substream *substream, int cmd,
return ret; return ret;
} }
static int davinci_vcif_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct davinci_vcif_dev *dev = snd_soc_dai_get_drvdata(dai);
snd_soc_dai_set_dma_data(dai, substream, dev->dma_params);
return 0;
}
#define DAVINCI_VCIF_RATES SNDRV_PCM_RATE_8000_48000 #define DAVINCI_VCIF_RATES SNDRV_PCM_RATE_8000_48000
static const struct snd_soc_dai_ops davinci_vcif_dai_ops = { static const struct snd_soc_dai_ops davinci_vcif_dai_ops = {
.startup = davinci_vcif_startup,
.trigger = davinci_vcif_trigger, .trigger = davinci_vcif_trigger,
.hw_params = davinci_vcif_hw_params, .hw_params = davinci_vcif_hw_params,
}; };
static int davinci_vcif_dai_probe(struct snd_soc_dai *dai)
{
struct davinci_vcif_dev *dev = snd_soc_dai_get_drvdata(dai);
dai->playback_dma_data = &dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK];
dai->capture_dma_data = &dev->dma_data[SNDRV_PCM_STREAM_CAPTURE];
return 0;
}
static struct snd_soc_dai_driver davinci_vcif_dai = { static struct snd_soc_dai_driver davinci_vcif_dai = {
.probe = davinci_vcif_dai_probe,
.playback = { .playback = {
.channels_min = 1, .channels_min = 1,
.channels_max = 2, .channels_max = 2,
...@@ -225,16 +218,16 @@ static int davinci_vcif_probe(struct platform_device *pdev) ...@@ -225,16 +218,16 @@ static int davinci_vcif_probe(struct platform_device *pdev)
/* DMA tx params */ /* DMA tx params */
davinci_vcif_dev->davinci_vc = davinci_vc; davinci_vcif_dev->davinci_vc = davinci_vc;
davinci_vcif_dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK].channel = davinci_vcif_dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].filter_data =
davinci_vc->davinci_vcif.dma_tx_channel; &davinci_vc->davinci_vcif.dma_tx_channel;
davinci_vcif_dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK].dma_addr = davinci_vcif_dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr =
davinci_vc->davinci_vcif.dma_tx_addr; davinci_vc->davinci_vcif.dma_tx_addr;
/* DMA rx params */ /* DMA rx params */
davinci_vcif_dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].channel = davinci_vcif_dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].filter_data =
davinci_vc->davinci_vcif.dma_rx_channel; &davinci_vc->davinci_vcif.dma_rx_channel;
davinci_vcif_dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].dma_addr = davinci_vcif_dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].addr =
davinci_vc->davinci_vcif.dma_rx_addr; davinci_vc->davinci_vcif.dma_rx_addr;
dev_set_drvdata(&pdev->dev, davinci_vcif_dev); dev_set_drvdata(&pdev->dev, davinci_vcif_dev);
...@@ -245,7 +238,7 @@ static int davinci_vcif_probe(struct platform_device *pdev) ...@@ -245,7 +238,7 @@ static int davinci_vcif_probe(struct platform_device *pdev)
return ret; return ret;
} }
ret = davinci_soc_platform_register(&pdev->dev); ret = edma_pcm_platform_register(&pdev->dev);
if (ret) { if (ret) {
dev_err(&pdev->dev, "register PCM failed: %d\n", ret); dev_err(&pdev->dev, "register PCM failed: %d\n", ret);
snd_soc_unregister_component(&pdev->dev); snd_soc_unregister_component(&pdev->dev);
......
...@@ -512,6 +512,12 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) ...@@ -512,6 +512,12 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
memcpy(priv->dai_link, fsl_asoc_card_dai, memcpy(priv->dai_link, fsl_asoc_card_dai,
sizeof(struct snd_soc_dai_link) * ARRAY_SIZE(priv->dai_link)); sizeof(struct snd_soc_dai_link) * ARRAY_SIZE(priv->dai_link));
ret = snd_soc_of_parse_audio_routing(&priv->card, "audio-routing");
if (ret) {
dev_err(&pdev->dev, "failed to parse audio-routing: %d\n", ret);
goto asrc_fail;
}
/* Normal DAI Link */ /* Normal DAI Link */
priv->dai_link[0].cpu_of_node = cpu_np; priv->dai_link[0].cpu_of_node = cpu_np;
priv->dai_link[0].codec_of_node = codec_np; priv->dai_link[0].codec_of_node = codec_np;
......
...@@ -53,9 +53,9 @@ static int imx_es8328_dai_init(struct snd_soc_pcm_runtime *rtd) ...@@ -53,9 +53,9 @@ static int imx_es8328_dai_init(struct snd_soc_pcm_runtime *rtd)
/* Headphone jack detection */ /* Headphone jack detection */
if (gpio_is_valid(data->jack_gpio)) { if (gpio_is_valid(data->jack_gpio)) {
ret = snd_soc_jack_new(rtd->codec, "Headphone", ret = snd_soc_card_jack_new(rtd->card, "Headphone",
SND_JACK_HEADPHONE | SND_JACK_BTN_0, SND_JACK_HEADPHONE | SND_JACK_BTN_0,
&headset_jack); &headset_jack, NULL, 0);
if (ret) if (ret)
return ret; return ret;
......
...@@ -205,16 +205,14 @@ static int wm1133_ev1_init(struct snd_soc_pcm_runtime *rtd) ...@@ -205,16 +205,14 @@ static int wm1133_ev1_init(struct snd_soc_pcm_runtime *rtd)
struct snd_soc_dapm_context *dapm = &codec->dapm; struct snd_soc_dapm_context *dapm = &codec->dapm;
/* Headphone jack detection */ /* Headphone jack detection */
snd_soc_jack_new(codec, "Headphone", SND_JACK_HEADPHONE, &hp_jack); snd_soc_card_jack_new(rtd->card, "Headphone", SND_JACK_HEADPHONE,
snd_soc_jack_add_pins(&hp_jack, ARRAY_SIZE(hp_jack_pins), &hp_jack, hp_jack_pins, ARRAY_SIZE(hp_jack_pins));
hp_jack_pins);
wm8350_hp_jack_detect(codec, WM8350_JDR, &hp_jack, SND_JACK_HEADPHONE); wm8350_hp_jack_detect(codec, WM8350_JDR, &hp_jack, SND_JACK_HEADPHONE);
/* Microphone jack detection */ /* Microphone jack detection */
snd_soc_jack_new(codec, "Microphone", snd_soc_card_jack_new(rtd->card, "Microphone",
SND_JACK_MICROPHONE | SND_JACK_BTN_0, &mic_jack); SND_JACK_MICROPHONE | SND_JACK_BTN_0, &mic_jack,
snd_soc_jack_add_pins(&mic_jack, ARRAY_SIZE(mic_jack_pins), mic_jack_pins, ARRAY_SIZE(mic_jack_pins));
mic_jack_pins);
wm8350_mic_jack_detect(codec, &mic_jack, SND_JACK_MICROPHONE, wm8350_mic_jack_detect(codec, &mic_jack, SND_JACK_MICROPHONE,
SND_JACK_BTN_0); SND_JACK_BTN_0);
......
...@@ -176,11 +176,11 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) ...@@ -176,11 +176,11 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd)
return ret; return ret;
if (gpio_is_valid(priv->gpio_hp_det)) { if (gpio_is_valid(priv->gpio_hp_det)) {
snd_soc_jack_new(codec->codec, "Headphones", SND_JACK_HEADPHONE, snd_soc_card_jack_new(rtd->card, "Headphones",
&simple_card_hp_jack); SND_JACK_HEADPHONE,
snd_soc_jack_add_pins(&simple_card_hp_jack, &simple_card_hp_jack,
ARRAY_SIZE(simple_card_hp_jack_pins), simple_card_hp_jack_pins,
simple_card_hp_jack_pins); ARRAY_SIZE(simple_card_hp_jack_pins));
simple_card_hp_jack_gpio.gpio = priv->gpio_hp_det; simple_card_hp_jack_gpio.gpio = priv->gpio_hp_det;
simple_card_hp_jack_gpio.invert = priv->gpio_hp_det_invert; simple_card_hp_jack_gpio.invert = priv->gpio_hp_det_invert;
...@@ -189,11 +189,11 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) ...@@ -189,11 +189,11 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd)
} }
if (gpio_is_valid(priv->gpio_mic_det)) { if (gpio_is_valid(priv->gpio_mic_det)) {
snd_soc_jack_new(codec->codec, "Mic Jack", SND_JACK_MICROPHONE, snd_soc_card_jack_new(rtd->card, "Mic Jack",
&simple_card_mic_jack); SND_JACK_MICROPHONE,
snd_soc_jack_add_pins(&simple_card_mic_jack, &simple_card_mic_jack,
ARRAY_SIZE(simple_card_mic_jack_pins), simple_card_mic_jack_pins,
simple_card_mic_jack_pins); ARRAY_SIZE(simple_card_mic_jack_pins));
simple_card_mic_jack_gpio.gpio = priv->gpio_mic_det; simple_card_mic_jack_gpio.gpio = priv->gpio_mic_det;
simple_card_mic_jack_gpio.invert = priv->gpio_mic_det_invert; simple_card_mic_jack_gpio.invert = priv->gpio_mic_det_invert;
snd_soc_jack_add_gpios(&simple_card_mic_jack, 1, snd_soc_jack_add_gpios(&simple_card_mic_jack, 1,
......
...@@ -80,15 +80,9 @@ static int broadwell_rt286_codec_init(struct snd_soc_pcm_runtime *rtd) ...@@ -80,15 +80,9 @@ static int broadwell_rt286_codec_init(struct snd_soc_pcm_runtime *rtd)
{ {
struct snd_soc_codec *codec = rtd->codec; struct snd_soc_codec *codec = rtd->codec;
int ret = 0; int ret = 0;
ret = snd_soc_jack_new(codec, "Headset", ret = snd_soc_card_jack_new(rtd->card, "Headset",
SND_JACK_HEADSET | SND_JACK_BTN_0, &broadwell_headset); SND_JACK_HEADSET | SND_JACK_BTN_0, &broadwell_headset,
broadwell_headset_pins, ARRAY_SIZE(broadwell_headset_pins));
if (ret)
return ret;
ret = snd_soc_jack_add_pins(&broadwell_headset,
ARRAY_SIZE(broadwell_headset_pins),
broadwell_headset_pins);
if (ret) if (ret)
return ret; return ret;
...@@ -110,9 +104,7 @@ static int broadwell_ssp0_fixup(struct snd_soc_pcm_runtime *rtd, ...@@ -110,9 +104,7 @@ static int broadwell_ssp0_fixup(struct snd_soc_pcm_runtime *rtd,
channels->min = channels->max = 2; channels->min = channels->max = 2;
/* set SSP0 to 16 bit */ /* set SSP0 to 16 bit */
snd_mask_set(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT - params_set_format(params, SNDRV_PCM_FORMAT_S16_LE);
SNDRV_PCM_HW_PARAM_FIRST_MASK],
SNDRV_PCM_FORMAT_S16_LE);
return 0; return 0;
} }
......
...@@ -84,7 +84,6 @@ static struct snd_soc_jack_gpio hs_jack_gpios[] = { ...@@ -84,7 +84,6 @@ static struct snd_soc_jack_gpio hs_jack_gpios[] = {
static int byt_max98090_init(struct snd_soc_pcm_runtime *runtime) static int byt_max98090_init(struct snd_soc_pcm_runtime *runtime)
{ {
int ret; int ret;
struct snd_soc_codec *codec = runtime->codec;
struct snd_soc_card *card = runtime->card; struct snd_soc_card *card = runtime->card;
struct byt_max98090_private *drv = snd_soc_card_get_drvdata(card); struct byt_max98090_private *drv = snd_soc_card_get_drvdata(card);
struct snd_soc_jack *jack = &drv->jack; struct snd_soc_jack *jack = &drv->jack;
...@@ -100,13 +99,9 @@ static int byt_max98090_init(struct snd_soc_pcm_runtime *runtime) ...@@ -100,13 +99,9 @@ static int byt_max98090_init(struct snd_soc_pcm_runtime *runtime)
} }
/* Enable jack detection */ /* Enable jack detection */
ret = snd_soc_jack_new(codec, "Headset", ret = snd_soc_card_jack_new(runtime->card, "Headset",
SND_JACK_LINEOUT | SND_JACK_HEADSET, jack); SND_JACK_LINEOUT | SND_JACK_HEADSET, jack,
if (ret) hs_jack_pins, ARRAY_SIZE(hs_jack_pins));
return ret;
ret = snd_soc_jack_add_pins(jack, ARRAY_SIZE(hs_jack_pins),
hs_jack_pins);
if (ret) if (ret)
return ret; return ret;
......
...@@ -113,9 +113,7 @@ static int byt_codec_fixup(struct snd_soc_pcm_runtime *rtd, ...@@ -113,9 +113,7 @@ static int byt_codec_fixup(struct snd_soc_pcm_runtime *rtd,
channels->min = channels->max = 2; channels->min = channels->max = 2;
/* set SSP2 to 24-bit */ /* set SSP2 to 24-bit */
snd_mask_set(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT - params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
SNDRV_PCM_HW_PARAM_FIRST_MASK],
SNDRV_PCM_FORMAT_S24_LE);
return 0; return 0;
} }
......
...@@ -169,17 +169,17 @@ static int cht_codec_init(struct snd_soc_pcm_runtime *runtime) ...@@ -169,17 +169,17 @@ static int cht_codec_init(struct snd_soc_pcm_runtime *runtime)
return ret; return ret;
} }
ret = snd_soc_jack_new(codec, "Headphone Jack", ret = snd_soc_card_jack_new(runtime->card, "Headphone Jack",
SND_JACK_HEADPHONE, SND_JACK_HEADPHONE, &ctx->hp_jack,
&ctx->hp_jack); NULL, 0);
if (ret) { if (ret) {
dev_err(runtime->dev, "HP jack creation failed %d\n", ret); dev_err(runtime->dev, "HP jack creation failed %d\n", ret);
return ret; return ret;
} }
ret = snd_soc_jack_new(codec, "Mic Jack", ret = snd_soc_card_jack_new(runtime->card, "Mic Jack",
SND_JACK_MICROPHONE, SND_JACK_MICROPHONE, &ctx->mic_jack,
&ctx->mic_jack); NULL, 0);
if (ret) { if (ret) {
dev_err(runtime->dev, "Mic jack creation failed %d\n", ret); dev_err(runtime->dev, "Mic jack creation failed %d\n", ret);
return ret; return ret;
...@@ -203,9 +203,7 @@ static int cht_codec_fixup(struct snd_soc_pcm_runtime *rtd, ...@@ -203,9 +203,7 @@ static int cht_codec_fixup(struct snd_soc_pcm_runtime *rtd,
channels->min = channels->max = 2; channels->min = channels->max = 2;
/* set SSP2 to 24-bit */ /* set SSP2 to 24-bit */
snd_mask_set(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT - params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
SNDRV_PCM_HW_PARAM_FIRST_MASK],
SNDRV_PCM_FORMAT_S24_LE);
return 0; return 0;
} }
......
...@@ -178,9 +178,7 @@ static int cht_codec_fixup(struct snd_soc_pcm_runtime *rtd, ...@@ -178,9 +178,7 @@ static int cht_codec_fixup(struct snd_soc_pcm_runtime *rtd,
channels->min = channels->max = 2; channels->min = channels->max = 2;
/* set SSP2 to 24-bit */ /* set SSP2 to 24-bit */
snd_mask_set(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT - params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
SNDRV_PCM_HW_PARAM_FIRST_MASK],
SNDRV_PCM_FORMAT_S24_LE);
return 0; return 0;
} }
...@@ -217,7 +215,7 @@ static struct snd_soc_dai_link cht_dailink[] = { ...@@ -217,7 +215,7 @@ static struct snd_soc_dai_link cht_dailink[] = {
.codec_dai_name = "snd-soc-dummy-dai", .codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy", .codec_name = "snd-soc-dummy",
.platform_name = "sst-mfld-platform", .platform_name = "sst-mfld-platform",
.ignore_suspend = 1, .nonatomic = true,
.dynamic = 1, .dynamic = 1,
.dpcm_playback = 1, .dpcm_playback = 1,
.dpcm_capture = 1, .dpcm_capture = 1,
...@@ -240,13 +238,13 @@ static struct snd_soc_dai_link cht_dailink[] = { ...@@ -240,13 +238,13 @@ static struct snd_soc_dai_link cht_dailink[] = {
.cpu_dai_name = "ssp2-port", .cpu_dai_name = "ssp2-port",
.platform_name = "sst-mfld-platform", .platform_name = "sst-mfld-platform",
.no_pcm = 1, .no_pcm = 1,
.nonatomic = true,
.codec_dai_name = "rt5670-aif1", .codec_dai_name = "rt5670-aif1",
.codec_name = "i2c-10EC5670:00", .codec_name = "i2c-10EC5670:00",
.dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_IB_NF .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_IB_NF
| SND_SOC_DAIFMT_CBS_CFS, | SND_SOC_DAIFMT_CBS_CFS,
.init = cht_codec_init, .init = cht_codec_init,
.be_hw_params_fixup = cht_codec_fixup, .be_hw_params_fixup = cht_codec_fixup,
.ignore_suspend = 1,
.dpcm_playback = 1, .dpcm_playback = 1,
.dpcm_capture = 1, .dpcm_capture = 1,
.ops = &cht_be_ssp2_ops, .ops = &cht_be_ssp2_ops,
...@@ -285,7 +283,6 @@ static int snd_cht_mc_probe(struct platform_device *pdev) ...@@ -285,7 +283,6 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
static struct platform_driver snd_cht_mc_driver = { static struct platform_driver snd_cht_mc_driver = {
.driver = { .driver = {
.name = "cht-bsw-rt5672", .name = "cht-bsw-rt5672",
.pm = &snd_soc_pm_ops,
}, },
.probe = snd_cht_mc_probe, .probe = snd_cht_mc_probe,
}; };
......
...@@ -56,9 +56,7 @@ static int haswell_ssp0_fixup(struct snd_soc_pcm_runtime *rtd, ...@@ -56,9 +56,7 @@ static int haswell_ssp0_fixup(struct snd_soc_pcm_runtime *rtd,
channels->min = channels->max = 2; channels->min = channels->max = 2;
/* set SSP0 to 16 bit */ /* set SSP0 to 16 bit */
snd_mask_set(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT - params_set_format(params, SNDRV_PCM_FORMAT_S16_LE);
SNDRV_PCM_HW_PARAM_FIRST_MASK],
SNDRV_PCM_FORMAT_S16_LE);
return 0; return 0;
} }
......
...@@ -228,10 +228,13 @@ static void mfld_jack_check(unsigned int intr_status) ...@@ -228,10 +228,13 @@ static void mfld_jack_check(unsigned int intr_status)
{ {
struct mfld_jack_data jack_data; struct mfld_jack_data jack_data;
if (!mfld_codec)
return;
jack_data.mfld_jack = &mfld_jack; jack_data.mfld_jack = &mfld_jack;
jack_data.intr_id = intr_status; jack_data.intr_id = intr_status;
sn95031_jack_detection(&jack_data); sn95031_jack_detection(mfld_codec, &jack_data);
/* TODO: add american headset detection post gpiolib support */ /* TODO: add american headset detection post gpiolib support */
} }
...@@ -240,8 +243,6 @@ static int mfld_init(struct snd_soc_pcm_runtime *runtime) ...@@ -240,8 +243,6 @@ static int mfld_init(struct snd_soc_pcm_runtime *runtime)
struct snd_soc_dapm_context *dapm = &runtime->card->dapm; struct snd_soc_dapm_context *dapm = &runtime->card->dapm;
int ret_val; int ret_val;
mfld_codec = runtime->codec;
/* default is earpiece pin, userspace sets it explcitly */ /* default is earpiece pin, userspace sets it explcitly */
snd_soc_dapm_disable_pin(dapm, "Headphones"); snd_soc_dapm_disable_pin(dapm, "Headphones");
/* default is lineout NC, userspace sets it explcitly */ /* default is lineout NC, userspace sets it explcitly */
...@@ -254,20 +255,15 @@ static int mfld_init(struct snd_soc_pcm_runtime *runtime) ...@@ -254,20 +255,15 @@ static int mfld_init(struct snd_soc_pcm_runtime *runtime)
snd_soc_dapm_disable_pin(dapm, "LINEINR"); snd_soc_dapm_disable_pin(dapm, "LINEINR");
/* Headset and button jack detection */ /* Headset and button jack detection */
ret_val = snd_soc_jack_new(mfld_codec, "Intel(R) MID Audio Jack", ret_val = snd_soc_card_jack_new(runtime->card,
SND_JACK_HEADSET | SND_JACK_BTN_0 | "Intel(R) MID Audio Jack", SND_JACK_HEADSET |
SND_JACK_BTN_1, &mfld_jack); SND_JACK_BTN_0 | SND_JACK_BTN_1, &mfld_jack,
mfld_jack_pins, ARRAY_SIZE(mfld_jack_pins));
if (ret_val) { if (ret_val) {
pr_err("jack creation failed\n"); pr_err("jack creation failed\n");
return ret_val; return ret_val;
} }
ret_val = snd_soc_jack_add_pins(&mfld_jack,
ARRAY_SIZE(mfld_jack_pins), mfld_jack_pins);
if (ret_val) {
pr_err("adding jack pins failed\n");
return ret_val;
}
ret_val = snd_soc_jack_add_zones(&mfld_jack, ret_val = snd_soc_jack_add_zones(&mfld_jack,
ARRAY_SIZE(mfld_zones), mfld_zones); ARRAY_SIZE(mfld_zones), mfld_zones);
if (ret_val) { if (ret_val) {
...@@ -275,6 +271,8 @@ static int mfld_init(struct snd_soc_pcm_runtime *runtime) ...@@ -275,6 +271,8 @@ static int mfld_init(struct snd_soc_pcm_runtime *runtime)
return ret_val; return ret_val;
} }
mfld_codec = runtime->codec;
/* we want to check if anything is inserted at boot, /* we want to check if anything is inserted at boot,
* so send a fake event to codec and it will read adc * so send a fake event to codec and it will read adc
* to find if anything is there or not */ * to find if anything is there or not */
...@@ -359,8 +357,6 @@ static irqreturn_t snd_mfld_jack_detection(int irq, void *data) ...@@ -359,8 +357,6 @@ static irqreturn_t snd_mfld_jack_detection(int irq, void *data)
{ {
struct mfld_mc_private *mc_drv_ctx = (struct mfld_mc_private *) data; struct mfld_mc_private *mc_drv_ctx = (struct mfld_mc_private *) data;
if (mfld_jack.codec == NULL)
return IRQ_HANDLED;
mfld_jack_check(mc_drv_ctx->interrupt_status); mfld_jack_check(mc_drv_ctx->interrupt_status);
return IRQ_HANDLED; return IRQ_HANDLED;
......
...@@ -594,11 +594,13 @@ static int sst_platform_pcm_trigger(struct snd_pcm_substream *substream, ...@@ -594,11 +594,13 @@ static int sst_platform_pcm_trigger(struct snd_pcm_substream *substream,
ret_val = stream->ops->stream_drop(sst->dev, str_id); ret_val = stream->ops->stream_drop(sst->dev, str_id);
break; break;
case SNDRV_PCM_TRIGGER_PAUSE_PUSH: case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
case SNDRV_PCM_TRIGGER_SUSPEND:
dev_dbg(rtd->dev, "sst: in pause\n"); dev_dbg(rtd->dev, "sst: in pause\n");
status = SST_PLATFORM_PAUSED; status = SST_PLATFORM_PAUSED;
ret_val = stream->ops->stream_pause(sst->dev, str_id); ret_val = stream->ops->stream_pause(sst->dev, str_id);
break; break;
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
case SNDRV_PCM_TRIGGER_RESUME:
dev_dbg(rtd->dev, "sst: in pause release\n"); dev_dbg(rtd->dev, "sst: in pause release\n");
status = SST_PLATFORM_RUNNING; status = SST_PLATFORM_RUNNING;
ret_val = stream->ops->stream_pause_release(sst->dev, str_id); ret_val = stream->ops->stream_pause_release(sst->dev, str_id);
...@@ -665,6 +667,9 @@ static int sst_pcm_new(struct snd_soc_pcm_runtime *rtd) ...@@ -665,6 +667,9 @@ static int sst_pcm_new(struct snd_soc_pcm_runtime *rtd)
static int sst_soc_probe(struct snd_soc_platform *platform) static int sst_soc_probe(struct snd_soc_platform *platform)
{ {
struct sst_data *drv = dev_get_drvdata(platform->dev);
drv->soc_card = platform->component.card;
return sst_dsp_init_v2_dpcm(platform); return sst_dsp_init_v2_dpcm(platform);
} }
...@@ -727,9 +732,64 @@ static int sst_platform_remove(struct platform_device *pdev) ...@@ -727,9 +732,64 @@ static int sst_platform_remove(struct platform_device *pdev)
return 0; return 0;
} }
#ifdef CONFIG_PM_SLEEP
static int sst_soc_prepare(struct device *dev)
{
struct sst_data *drv = dev_get_drvdata(dev);
int i;
/* suspend all pcms first */
snd_soc_suspend(drv->soc_card->dev);
snd_soc_poweroff(drv->soc_card->dev);
/* set the SSPs to idle */
for (i = 0; i < drv->soc_card->num_rtd; i++) {
struct snd_soc_dai *dai = drv->soc_card->rtd[i].cpu_dai;
if (dai->active) {
send_ssp_cmd(dai, dai->name, 0);
sst_handle_vb_timer(dai, false);
}
}
return 0;
}
static void sst_soc_complete(struct device *dev)
{
struct sst_data *drv = dev_get_drvdata(dev);
int i;
/* restart SSPs */
for (i = 0; i < drv->soc_card->num_rtd; i++) {
struct snd_soc_dai *dai = drv->soc_card->rtd[i].cpu_dai;
if (dai->active) {
sst_handle_vb_timer(dai, true);
send_ssp_cmd(dai, dai->name, 1);
}
}
snd_soc_resume(drv->soc_card->dev);
}
#else
#define sst_soc_prepare NULL
#define sst_soc_complete NULL
#endif
static const struct dev_pm_ops sst_platform_pm = {
.prepare = sst_soc_prepare,
.complete = sst_soc_complete,
};
static struct platform_driver sst_platform_driver = { static struct platform_driver sst_platform_driver = {
.driver = { .driver = {
.name = "sst-mfld-platform", .name = "sst-mfld-platform",
.pm = &sst_platform_pm,
}, },
.probe = sst_platform_probe, .probe = sst_platform_probe,
.remove = sst_platform_remove, .remove = sst_platform_remove,
......
...@@ -174,6 +174,7 @@ struct sst_data { ...@@ -174,6 +174,7 @@ struct sst_data {
struct sst_platform_data *pdata; struct sst_platform_data *pdata;
struct snd_sst_bytes_v2 *byte_stream; struct snd_sst_bytes_v2 *byte_stream;
struct mutex lock; struct mutex lock;
struct snd_soc_card *soc_card;
}; };
int sst_register_dsp(struct sst_device *sst); int sst_register_dsp(struct sst_device *sst);
int sst_unregister_dsp(struct sst_device *sst); int sst_unregister_dsp(struct sst_device *sst);
......
...@@ -423,23 +423,135 @@ static int intel_sst_runtime_suspend(struct device *dev) ...@@ -423,23 +423,135 @@ static int intel_sst_runtime_suspend(struct device *dev)
return ret; return ret;
} }
static int intel_sst_runtime_resume(struct device *dev) static int intel_sst_suspend(struct device *dev)
{ {
int ret = 0;
struct intel_sst_drv *ctx = dev_get_drvdata(dev); struct intel_sst_drv *ctx = dev_get_drvdata(dev);
struct sst_fw_save *fw_save;
int i, ret = 0;
if (ctx->sst_state == SST_RESET) { /* check first if we are already in SW reset */
ret = sst_load_fw(ctx); if (ctx->sst_state == SST_RESET)
if (ret) { return 0;
dev_err(dev, "FW download fail %d\n", ret);
sst_set_fw_state_locked(ctx, SST_RESET); /*
* check if any stream is active and running
* they should already by suspend by soc_suspend
*/
for (i = 1; i <= ctx->info.max_streams; i++) {
struct stream_info *stream = &ctx->streams[i];
if (stream->status == STREAM_RUNNING) {
dev_err(dev, "stream %d is running, cant susupend, abort\n", i);
return -EBUSY;
} }
} }
synchronize_irq(ctx->irq_num);
flush_workqueue(ctx->post_msg_wq);
/* Move the SST state to Reset */
sst_set_fw_state_locked(ctx, SST_RESET);
/* tell DSP we are suspending */
if (ctx->ops->save_dsp_context(ctx))
return -EBUSY;
/* save the memories */
fw_save = kzalloc(sizeof(*fw_save), GFP_KERNEL);
if (!fw_save)
return -ENOMEM;
fw_save->iram = kzalloc(ctx->iram_end - ctx->iram_base, GFP_KERNEL);
if (!fw_save->iram) {
ret = -ENOMEM;
goto iram;
}
fw_save->dram = kzalloc(ctx->dram_end - ctx->dram_base, GFP_KERNEL);
if (!fw_save->dram) {
ret = -ENOMEM;
goto dram;
}
fw_save->sram = kzalloc(SST_MAILBOX_SIZE, GFP_KERNEL);
if (!fw_save->sram) {
ret = -ENOMEM;
goto sram;
}
fw_save->ddr = kzalloc(ctx->ddr_end - ctx->ddr_base, GFP_KERNEL);
if (!fw_save->ddr) {
ret = -ENOMEM;
goto ddr;
}
memcpy32_fromio(fw_save->iram, ctx->iram, ctx->iram_end - ctx->iram_base);
memcpy32_fromio(fw_save->dram, ctx->dram, ctx->dram_end - ctx->dram_base);
memcpy32_fromio(fw_save->sram, ctx->mailbox, SST_MAILBOX_SIZE);
memcpy32_fromio(fw_save->ddr, ctx->ddr, ctx->ddr_end - ctx->ddr_base);
ctx->fw_save = fw_save;
ctx->ops->reset(ctx);
return 0;
ddr:
kfree(fw_save->sram);
sram:
kfree(fw_save->dram);
dram:
kfree(fw_save->iram);
iram:
kfree(fw_save);
return ret;
}
static int intel_sst_resume(struct device *dev)
{
struct intel_sst_drv *ctx = dev_get_drvdata(dev);
struct sst_fw_save *fw_save = ctx->fw_save;
int ret = 0;
struct sst_block *block;
if (!fw_save)
return 0;
sst_set_fw_state_locked(ctx, SST_FW_LOADING);
/* we have to restore the memory saved */
ctx->ops->reset(ctx);
ctx->fw_save = NULL;
memcpy32_toio(ctx->iram, fw_save->iram, ctx->iram_end - ctx->iram_base);
memcpy32_toio(ctx->dram, fw_save->dram, ctx->dram_end - ctx->dram_base);
memcpy32_toio(ctx->mailbox, fw_save->sram, SST_MAILBOX_SIZE);
memcpy32_toio(ctx->ddr, fw_save->ddr, ctx->ddr_end - ctx->ddr_base);
kfree(fw_save->sram);
kfree(fw_save->dram);
kfree(fw_save->iram);
kfree(fw_save->ddr);
kfree(fw_save);
block = sst_create_block(ctx, 0, FW_DWNL_ID);
if (block == NULL)
return -ENOMEM;
/* start and wait for ack */
ctx->ops->start(ctx);
ret = sst_wait_timeout(ctx, block);
if (ret) {
dev_err(ctx->dev, "fw download failed %d\n", ret);
/* FW download failed due to timeout */
ret = -EBUSY;
} else {
sst_set_fw_state_locked(ctx, SST_FW_RUNNING);
}
sst_free_block(ctx, block);
return ret; return ret;
} }
const struct dev_pm_ops intel_sst_pm = { const struct dev_pm_ops intel_sst_pm = {
.suspend = intel_sst_suspend,
.resume = intel_sst_resume,
.runtime_suspend = intel_sst_runtime_suspend, .runtime_suspend = intel_sst_runtime_suspend,
.runtime_resume = intel_sst_runtime_resume,
}; };
EXPORT_SYMBOL_GPL(intel_sst_pm); EXPORT_SYMBOL_GPL(intel_sst_pm);
...@@ -337,6 +337,13 @@ struct sst_shim_regs64 { ...@@ -337,6 +337,13 @@ struct sst_shim_regs64 {
u64 csr2; u64 csr2;
}; };
struct sst_fw_save {
void *iram;
void *dram;
void *sram;
void *ddr;
};
/** /**
* struct intel_sst_drv - driver ops * struct intel_sst_drv - driver ops
* *
...@@ -428,6 +435,8 @@ struct intel_sst_drv { ...@@ -428,6 +435,8 @@ struct intel_sst_drv {
* persistent till worker thread gets called * persistent till worker thread gets called
*/ */
char firmware_name[FW_NAME_SIZE]; char firmware_name[FW_NAME_SIZE];
struct sst_fw_save *fw_save;
}; };
/* misc definitions */ /* misc definitions */
...@@ -544,4 +553,7 @@ int sst_alloc_drv_context(struct intel_sst_drv **ctx, ...@@ -544,4 +553,7 @@ int sst_alloc_drv_context(struct intel_sst_drv **ctx,
int sst_context_init(struct intel_sst_drv *ctx); int sst_context_init(struct intel_sst_drv *ctx);
void sst_context_cleanup(struct intel_sst_drv *ctx); void sst_context_cleanup(struct intel_sst_drv *ctx);
void sst_configure_runtime_pm(struct intel_sst_drv *ctx); void sst_configure_runtime_pm(struct intel_sst_drv *ctx);
void memcpy32_toio(void __iomem *dst, const void *src, int count);
void memcpy32_fromio(void *dst, const void __iomem *src, int count);
#endif #endif
...@@ -138,12 +138,36 @@ int sst_get_stream(struct intel_sst_drv *ctx, ...@@ -138,12 +138,36 @@ int sst_get_stream(struct intel_sst_drv *ctx,
static int sst_power_control(struct device *dev, bool state) static int sst_power_control(struct device *dev, bool state)
{ {
struct intel_sst_drv *ctx = dev_get_drvdata(dev); struct intel_sst_drv *ctx = dev_get_drvdata(dev);
int ret = 0;
dev_dbg(ctx->dev, "state:%d", state); int usage_count = 0;
if (state == true)
return pm_runtime_get_sync(dev); #ifdef CONFIG_PM
else usage_count = atomic_read(&dev->power.usage_count);
#else
usage_count = 1;
#endif
if (state == true) {
ret = pm_runtime_get_sync(dev);
dev_dbg(ctx->dev, "Enable: pm usage count: %d\n", usage_count);
if (ret < 0) {
dev_err(ctx->dev, "Runtime get failed with err: %d\n", ret);
return ret;
}
if ((ctx->sst_state == SST_RESET) && (usage_count == 1)) {
ret = sst_load_fw(ctx);
if (ret) {
dev_err(dev, "FW download fail %d\n", ret);
sst_set_fw_state_locked(ctx, SST_RESET);
ret = sst_pm_runtime_put(ctx);
}
}
} else {
dev_dbg(ctx->dev, "Disable: pm usage count: %d\n", usage_count);
return sst_pm_runtime_put(ctx); return sst_pm_runtime_put(ctx);
}
return ret;
} }
/* /*
...@@ -572,6 +596,35 @@ static int sst_stream_drop(struct device *dev, int str_id) ...@@ -572,6 +596,35 @@ static int sst_stream_drop(struct device *dev, int str_id)
return sst_drop_stream(ctx, str_id); return sst_drop_stream(ctx, str_id);
} }
static int sst_stream_pause(struct device *dev, int str_id)
{
struct stream_info *str_info;
struct intel_sst_drv *ctx = dev_get_drvdata(dev);
if (ctx->sst_state != SST_FW_RUNNING)
return 0;
str_info = get_stream_info(ctx, str_id);
if (!str_info)
return -EINVAL;
return sst_pause_stream(ctx, str_id);
}
static int sst_stream_resume(struct device *dev, int str_id)
{
struct stream_info *str_info;
struct intel_sst_drv *ctx = dev_get_drvdata(dev);
if (ctx->sst_state != SST_FW_RUNNING)
return 0;
str_info = get_stream_info(ctx, str_id);
if (!str_info)
return -EINVAL;
return sst_resume_stream(ctx, str_id);
}
static int sst_stream_init(struct device *dev, struct pcm_stream_info *str_info) static int sst_stream_init(struct device *dev, struct pcm_stream_info *str_info)
{ {
int str_id = 0; int str_id = 0;
...@@ -633,6 +686,8 @@ static struct sst_ops pcm_ops = { ...@@ -633,6 +686,8 @@ static struct sst_ops pcm_ops = {
.stream_init = sst_stream_init, .stream_init = sst_stream_init,
.stream_start = sst_stream_start, .stream_start = sst_stream_start,
.stream_drop = sst_stream_drop, .stream_drop = sst_stream_drop,
.stream_pause = sst_stream_pause,
.stream_pause_release = sst_stream_resume,
.stream_read_tstamp = sst_read_timestamp, .stream_read_tstamp = sst_read_timestamp,
.send_byte_stream = sst_send_byte_stream, .send_byte_stream = sst_send_byte_stream,
.close = sst_close_pcm_stream, .close = sst_close_pcm_stream,
......
...@@ -39,7 +39,15 @@ ...@@ -39,7 +39,15 @@
#include "sst.h" #include "sst.h"
#include "../sst-dsp.h" #include "../sst-dsp.h"
static inline void memcpy32_toio(void __iomem *dst, const void *src, int count) void memcpy32_toio(void __iomem *dst, const void *src, int count)
{
/* __iowrite32_copy uses 32-bit count values so divide by 4 for
* right count in words
*/
__iowrite32_copy(dst, src, count/4);
}
void memcpy32_fromio(void *dst, const void __iomem *src, int count)
{ {
/* __iowrite32_copy uses 32-bit count values so divide by 4 for /* __iowrite32_copy uses 32-bit count values so divide by 4 for
* right count in words * right count in words
......
...@@ -100,17 +100,19 @@ config SND_OMAP_SOC_OMAP_TWL4030 ...@@ -100,17 +100,19 @@ config SND_OMAP_SOC_OMAP_TWL4030
config SND_OMAP_SOC_OMAP_ABE_TWL6040 config SND_OMAP_SOC_OMAP_ABE_TWL6040
tristate "SoC Audio support for OMAP boards using ABE and twl6040 codec" tristate "SoC Audio support for OMAP boards using ABE and twl6040 codec"
depends on TWL6040_CORE && SND_OMAP_SOC && (ARCH_OMAP4 || COMPILE_TEST) depends on TWL6040_CORE && SND_OMAP_SOC && (ARCH_OMAP4 || SOC_OMAP5 || COMPILE_TEST)
select SND_OMAP_SOC_DMIC select SND_OMAP_SOC_DMIC
select SND_OMAP_SOC_MCPDM select SND_OMAP_SOC_MCPDM
select SND_SOC_TWL6040 select SND_SOC_TWL6040
select SND_SOC_DMIC select SND_SOC_DMIC
select COMMON_CLK_PALMAS if SOC_OMAP5
help help
Say Y if you want to add support for SoC audio on OMAP boards using Say Y if you want to add support for SoC audio on OMAP boards using
ABE and twl6040 codec. This driver currently supports: ABE and twl6040 codec. This driver currently supports:
- SDP4430/Blaze boards - SDP4430/Blaze boards
- PandaBoard (4430) - PandaBoard (4430)
- PandaBoardES (4460) - PandaBoardES (4460)
- omap5-uevm (5432)
config SND_OMAP_SOC_OMAP3_PANDORA config SND_OMAP_SOC_OMAP3_PANDORA
tristate "SoC Audio support for OMAP3 Pandora" tristate "SoC Audio support for OMAP3 Pandora"
......
...@@ -479,8 +479,8 @@ static int ams_delta_cx20442_init(struct snd_soc_pcm_runtime *rtd) ...@@ -479,8 +479,8 @@ static int ams_delta_cx20442_init(struct snd_soc_pcm_runtime *rtd)
/* Add hook switch - can be used to control the codec from userspace /* Add hook switch - can be used to control the codec from userspace
* even if line discipline fails */ * even if line discipline fails */
ret = snd_soc_jack_new(rtd->codec, "hook_switch", ret = snd_soc_card_jack_new(card, "hook_switch", SND_JACK_HEADSET,
SND_JACK_HEADSET, &ams_delta_hook_switch); &ams_delta_hook_switch, NULL, 0);
if (ret) if (ret)
dev_warn(card->dev, dev_warn(card->dev,
"Failed to allocate resources for hook switch, " "Failed to allocate resources for hook switch, "
......
...@@ -182,17 +182,17 @@ static int omap_abe_twl6040_init(struct snd_soc_pcm_runtime *rtd) ...@@ -182,17 +182,17 @@ static int omap_abe_twl6040_init(struct snd_soc_pcm_runtime *rtd)
/* Headset jack detection only if it is supported */ /* Headset jack detection only if it is supported */
if (priv->jack_detection) { if (priv->jack_detection) {
ret = snd_soc_jack_new(codec, "Headset Jack", ret = snd_soc_card_jack_new(rtd->card, "Headset Jack",
SND_JACK_HEADSET, &hs_jack); SND_JACK_HEADSET, &hs_jack,
hs_jack_pins,
ARRAY_SIZE(hs_jack_pins));
if (ret) if (ret)
return ret; return ret;
ret = snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins),
hs_jack_pins);
twl6040_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADSET); twl6040_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADSET);
} }
return ret; return 0;
} }
static const struct snd_soc_dapm_route dmic_audio_map[] = { static const struct snd_soc_dapm_route dmic_audio_map[] = {
......
...@@ -39,7 +39,7 @@ ...@@ -39,7 +39,7 @@
#define pcm_omap1510() 0 #define pcm_omap1510() 0
#endif #endif
static const struct snd_pcm_hardware omap_pcm_hardware = { static struct snd_pcm_hardware omap_pcm_hardware = {
.info = SNDRV_PCM_INFO_MMAP | .info = SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_MMAP_VALID |
SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_INTERLEAVED |
...@@ -53,6 +53,24 @@ static const struct snd_pcm_hardware omap_pcm_hardware = { ...@@ -53,6 +53,24 @@ static const struct snd_pcm_hardware omap_pcm_hardware = {
.buffer_bytes_max = 128 * 1024, .buffer_bytes_max = 128 * 1024,
}; };
/* sDMA supports only 1, 2, and 4 byte transfer elements. */
static void omap_pcm_limit_supported_formats(void)
{
int i;
for (i = 0; i < SNDRV_PCM_FORMAT_LAST; i++) {
switch (snd_pcm_format_physical_width(i)) {
case 8:
case 16:
case 32:
omap_pcm_hardware.formats |= (1LL << i);
break;
default:
break;
}
}
}
/* this may get called several times by oss emulation */ /* this may get called several times by oss emulation */
static int omap_pcm_hw_params(struct snd_pcm_substream *substream, static int omap_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params) struct snd_pcm_hw_params *params)
...@@ -235,6 +253,7 @@ static struct snd_soc_platform_driver omap_soc_platform = { ...@@ -235,6 +253,7 @@ static struct snd_soc_platform_driver omap_soc_platform = {
int omap_pcm_platform_register(struct device *dev) int omap_pcm_platform_register(struct device *dev)
{ {
omap_pcm_limit_supported_formats();
return devm_snd_soc_register_platform(dev, &omap_soc_platform); return devm_snd_soc_register_platform(dev, &omap_soc_platform);
} }
EXPORT_SYMBOL_GPL(omap_pcm_platform_register); EXPORT_SYMBOL_GPL(omap_pcm_platform_register);
......
...@@ -170,14 +170,10 @@ static int omap_twl4030_init(struct snd_soc_pcm_runtime *rtd) ...@@ -170,14 +170,10 @@ static int omap_twl4030_init(struct snd_soc_pcm_runtime *rtd)
if (priv->jack_detect > 0) { if (priv->jack_detect > 0) {
hs_jack_gpios[0].gpio = priv->jack_detect; hs_jack_gpios[0].gpio = priv->jack_detect;
ret = snd_soc_jack_new(codec, "Headset Jack", SND_JACK_HEADSET, ret = snd_soc_card_jack_new(rtd->card, "Headset Jack",
&priv->hs_jack); SND_JACK_HEADSET, &priv->hs_jack,
if (ret) hs_jack_pins,
return ret; ARRAY_SIZE(hs_jack_pins));
ret = snd_soc_jack_add_pins(&priv->hs_jack,
ARRAY_SIZE(hs_jack_pins),
hs_jack_pins);
if (ret) if (ret)
return ret; return ret;
......
...@@ -311,9 +311,9 @@ static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd) ...@@ -311,9 +311,9 @@ static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd)
} }
/* AV jack detection */ /* AV jack detection */
err = snd_soc_jack_new(codec, "AV Jack", err = snd_soc_card_jack_new(rtd->card, "AV Jack",
SND_JACK_HEADSET | SND_JACK_VIDEOOUT, SND_JACK_HEADSET | SND_JACK_VIDEOOUT,
&rx51_av_jack); &rx51_av_jack, NULL, 0);
if (err) { if (err) {
dev_err(card->dev, "Failed to add AV Jack\n"); dev_err(card->dev, "Failed to add AV Jack\n");
return err; return err;
......
...@@ -126,17 +126,12 @@ static const struct snd_soc_dapm_route hx4700_audio_map[] = { ...@@ -126,17 +126,12 @@ static const struct snd_soc_dapm_route hx4700_audio_map[] = {
*/ */
static int hx4700_ak4641_init(struct snd_soc_pcm_runtime *rtd) static int hx4700_ak4641_init(struct snd_soc_pcm_runtime *rtd)
{ {
struct snd_soc_codec *codec = rtd->codec;
int err; int err;
/* Jack detection API stuff */ /* Jack detection API stuff */
err = snd_soc_jack_new(codec, "Headphone Jack", err = snd_soc_card_jack_new(rtd->card, "Headphone Jack",
SND_JACK_HEADPHONE, &hs_jack); SND_JACK_HEADPHONE, &hs_jack, hs_jack_pin,
if (err) ARRAY_SIZE(hs_jack_pin));
return err;
err = snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pin),
hs_jack_pin);
if (err) if (err)
return err; return err;
......
...@@ -75,17 +75,12 @@ static struct snd_soc_card palm27x_asoc; ...@@ -75,17 +75,12 @@ static struct snd_soc_card palm27x_asoc;
static int palm27x_ac97_init(struct snd_soc_pcm_runtime *rtd) static int palm27x_ac97_init(struct snd_soc_pcm_runtime *rtd)
{ {
struct snd_soc_codec *codec = rtd->codec;
int err; int err;
/* Jack detection API stuff */ /* Jack detection API stuff */
err = snd_soc_jack_new(codec, "Headphone Jack", err = snd_soc_card_jack_new(rtd->card, "Headphone Jack",
SND_JACK_HEADPHONE, &hs_jack); SND_JACK_HEADPHONE, &hs_jack, hs_jack_pins,
if (err) ARRAY_SIZE(hs_jack_pins));
return err;
err = snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins),
hs_jack_pins);
if (err) if (err)
return err; return err;
......
...@@ -78,15 +78,12 @@ static int ttc_pm860x_init(struct snd_soc_pcm_runtime *rtd) ...@@ -78,15 +78,12 @@ static int ttc_pm860x_init(struct snd_soc_pcm_runtime *rtd)
struct snd_soc_codec *codec = rtd->codec; struct snd_soc_codec *codec = rtd->codec;
/* Headset jack detection */ /* Headset jack detection */
snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE snd_soc_card_jack_new(rtd->card, "Headphone Jack", SND_JACK_HEADPHONE |
| SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2, SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2,
&hs_jack); &hs_jack, hs_jack_pins, ARRAY_SIZE(hs_jack_pins));
snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins), snd_soc_card_jack_new(rtd->card, "Microphone Jack", SND_JACK_MICROPHONE,
hs_jack_pins); &mic_jack, mic_jack_pins,
snd_soc_jack_new(codec, "Microphone Jack", SND_JACK_MICROPHONE, ARRAY_SIZE(mic_jack_pins));
&mic_jack);
snd_soc_jack_add_pins(&mic_jack, ARRAY_SIZE(mic_jack_pins),
mic_jack_pins);
/* headphone, microphone detection & headset short detection */ /* headphone, microphone detection & headset short detection */
pm860x_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADPHONE, pm860x_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADPHONE,
......
...@@ -143,13 +143,9 @@ static int z2_wm8750_init(struct snd_soc_pcm_runtime *rtd) ...@@ -143,13 +143,9 @@ static int z2_wm8750_init(struct snd_soc_pcm_runtime *rtd)
snd_soc_dapm_disable_pin(dapm, "MONO1"); snd_soc_dapm_disable_pin(dapm, "MONO1");
/* Jack detection API stuff */ /* Jack detection API stuff */
ret = snd_soc_jack_new(codec, "Headset Jack", SND_JACK_HEADSET, ret = snd_soc_card_jack_new(rtd->card, "Headset Jack", SND_JACK_HEADSET,
&hs_jack); &hs_jack, hs_jack_pins,
if (ret) ARRAY_SIZE(hs_jack_pins));
goto err;
ret = snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins),
hs_jack_pins);
if (ret) if (ret)
goto err; goto err;
......
...@@ -162,13 +162,8 @@ static struct platform_device *s3c24xx_snd_device; ...@@ -162,13 +162,8 @@ static struct platform_device *s3c24xx_snd_device;
static int h1940_uda1380_init(struct snd_soc_pcm_runtime *rtd) static int h1940_uda1380_init(struct snd_soc_pcm_runtime *rtd)
{ {
struct snd_soc_codec *codec = rtd->codec; snd_soc_card_jack_new(rtd->card, "Headphone Jack", SND_JACK_HEADPHONE,
&hp_jack, hp_jack_pins, ARRAY_SIZE(hp_jack_pins));
snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE,
&hp_jack);
snd_soc_jack_add_pins(&hp_jack, ARRAY_SIZE(hp_jack_pins),
hp_jack_pins);
snd_soc_jack_add_gpios(&hp_jack, ARRAY_SIZE(hp_jack_gpios), snd_soc_jack_add_gpios(&hp_jack, ARRAY_SIZE(hp_jack_gpios),
hp_jack_gpios); hp_jack_gpios);
......
...@@ -260,12 +260,12 @@ static int littlemill_late_probe(struct snd_soc_card *card) ...@@ -260,12 +260,12 @@ static int littlemill_late_probe(struct snd_soc_card *card)
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = snd_soc_jack_new(codec, "Headset", ret = snd_soc_card_jack_new(card, "Headset",
SND_JACK_HEADSET | SND_JACK_MECHANICAL | SND_JACK_HEADSET | SND_JACK_MECHANICAL |
SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_0 | SND_JACK_BTN_1 |
SND_JACK_BTN_2 | SND_JACK_BTN_3 | SND_JACK_BTN_2 | SND_JACK_BTN_3 |
SND_JACK_BTN_4 | SND_JACK_BTN_5, SND_JACK_BTN_4 | SND_JACK_BTN_5,
&littlemill_headset); &littlemill_headset, NULL, 0);
if (ret) if (ret)
return ret; return ret;
......
...@@ -56,16 +56,10 @@ static int lowland_wm5100_init(struct snd_soc_pcm_runtime *rtd) ...@@ -56,16 +56,10 @@ static int lowland_wm5100_init(struct snd_soc_pcm_runtime *rtd)
return ret; return ret;
} }
ret = snd_soc_jack_new(codec, "Headset", ret = snd_soc_card_jack_new(rtd->card, "Headset", SND_JACK_LINEOUT |
SND_JACK_LINEOUT | SND_JACK_HEADSET | SND_JACK_HEADSET | SND_JACK_BTN_0,
SND_JACK_BTN_0, &lowland_headset, lowland_headset_pins,
&lowland_headset); ARRAY_SIZE(lowland_headset_pins));
if (ret)
return ret;
ret = snd_soc_jack_add_pins(&lowland_headset,
ARRAY_SIZE(lowland_headset_pins),
lowland_headset_pins);
if (ret) if (ret)
return ret; return ret;
......
...@@ -211,13 +211,8 @@ static int rx1950_hw_params(struct snd_pcm_substream *substream, ...@@ -211,13 +211,8 @@ static int rx1950_hw_params(struct snd_pcm_substream *substream,
static int rx1950_uda1380_init(struct snd_soc_pcm_runtime *rtd) static int rx1950_uda1380_init(struct snd_soc_pcm_runtime *rtd)
{ {
struct snd_soc_codec *codec = rtd->codec; snd_soc_card_jack_new(rtd->card, "Headphone Jack", SND_JACK_HEADPHONE,
&hp_jack, hp_jack_pins, ARRAY_SIZE(hp_jack_pins));
snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE,
&hp_jack);
snd_soc_jack_add_pins(&hp_jack, ARRAY_SIZE(hp_jack_pins),
hp_jack_pins);
snd_soc_jack_add_gpios(&hp_jack, ARRAY_SIZE(hp_jack_gpios), snd_soc_jack_add_gpios(&hp_jack, ARRAY_SIZE(hp_jack_gpios),
hp_jack_gpios); hp_jack_gpios);
......
...@@ -151,13 +151,10 @@ static int smartq_wm8987_init(struct snd_soc_pcm_runtime *rtd) ...@@ -151,13 +151,10 @@ static int smartq_wm8987_init(struct snd_soc_pcm_runtime *rtd)
snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); snd_soc_dapm_disable_pin(dapm, "Headphone Jack");
/* Headphone jack detection */ /* Headphone jack detection */
err = snd_soc_jack_new(codec, "Headphone Jack", err = snd_soc_card_jack_new(rtd->card, "Headphone Jack",
SND_JACK_HEADPHONE, &smartq_jack); SND_JACK_HEADPHONE, &smartq_jack,
if (err) smartq_jack_pins,
return err; ARRAY_SIZE(smartq_jack_pins));
err = snd_soc_jack_add_pins(&smartq_jack, ARRAY_SIZE(smartq_jack_pins),
smartq_jack_pins);
if (err) if (err)
return err; return err;
......
...@@ -153,16 +153,10 @@ static int speyside_wm8996_init(struct snd_soc_pcm_runtime *rtd) ...@@ -153,16 +153,10 @@ static int speyside_wm8996_init(struct snd_soc_pcm_runtime *rtd)
pr_err("Failed to request HP_SEL GPIO: %d\n", ret); pr_err("Failed to request HP_SEL GPIO: %d\n", ret);
gpio_direction_output(WM8996_HPSEL_GPIO, speyside_jack_polarity); gpio_direction_output(WM8996_HPSEL_GPIO, speyside_jack_polarity);
ret = snd_soc_jack_new(codec, "Headset", ret = snd_soc_card_jack_new(rtd->card, "Headset", SND_JACK_LINEOUT |
SND_JACK_LINEOUT | SND_JACK_HEADSET | SND_JACK_HEADSET | SND_JACK_BTN_0,
SND_JACK_BTN_0, &speyside_headset, speyside_headset_pins,
&speyside_headset); ARRAY_SIZE(speyside_headset_pins));
if (ret)
return ret;
ret = snd_soc_jack_add_pins(&speyside_headset,
ARRAY_SIZE(speyside_headset_pins),
speyside_headset_pins);
if (ret) if (ret)
return ret; return ret;
......
...@@ -179,15 +179,10 @@ static int tobermory_late_probe(struct snd_soc_card *card) ...@@ -179,15 +179,10 @@ static int tobermory_late_probe(struct snd_soc_card *card)
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = snd_soc_jack_new(codec, "Headset", ret = snd_soc_card_jack_new(card, "Headset", SND_JACK_HEADSET |
SND_JACK_HEADSET | SND_JACK_BTN_0, SND_JACK_BTN_0, &tobermory_headset,
&tobermory_headset); tobermory_headset_pins,
if (ret) ARRAY_SIZE(tobermory_headset_pins));
return ret;
ret = snd_soc_jack_add_pins(&tobermory_headset,
ARRAY_SIZE(tobermory_headset_pins),
tobermory_headset_pins);
if (ret) if (ret)
return ret; return ret;
......
...@@ -1578,6 +1578,10 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) ...@@ -1578,6 +1578,10 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
snd_soc_dapm_new_controls(&card->dapm, card->dapm_widgets, snd_soc_dapm_new_controls(&card->dapm, card->dapm_widgets,
card->num_dapm_widgets); card->num_dapm_widgets);
if (card->of_dapm_widgets)
snd_soc_dapm_new_controls(&card->dapm, card->of_dapm_widgets,
card->num_of_dapm_widgets);
/* initialise the sound card only once */ /* initialise the sound card only once */
if (card->probe) { if (card->probe) {
ret = card->probe(card); ret = card->probe(card);
...@@ -1633,6 +1637,10 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) ...@@ -1633,6 +1637,10 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
snd_soc_dapm_add_routes(&card->dapm, card->dapm_routes, snd_soc_dapm_add_routes(&card->dapm, card->dapm_routes,
card->num_dapm_routes); card->num_dapm_routes);
if (card->of_dapm_routes)
snd_soc_dapm_add_routes(&card->dapm, card->of_dapm_routes,
card->num_of_dapm_routes);
for (i = 0; i < card->num_links; i++) { for (i = 0; i < card->num_links; i++) {
if (card->dai_link[i].dai_fmt) if (card->dai_link[i].dai_fmt)
snd_soc_runtime_set_dai_fmt(&card->rtd[i], snd_soc_runtime_set_dai_fmt(&card->rtd[i],
...@@ -3242,8 +3250,8 @@ int snd_soc_of_parse_audio_simple_widgets(struct snd_soc_card *card, ...@@ -3242,8 +3250,8 @@ int snd_soc_of_parse_audio_simple_widgets(struct snd_soc_card *card,
widgets[i].name = wname; widgets[i].name = wname;
} }
card->dapm_widgets = widgets; card->of_dapm_widgets = widgets;
card->num_dapm_widgets = num_widgets; card->num_of_dapm_widgets = num_widgets;
return 0; return 0;
} }
...@@ -3327,8 +3335,8 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, ...@@ -3327,8 +3335,8 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card,
} }
} }
card->num_dapm_routes = num_routes; card->num_of_dapm_routes = num_routes;
card->dapm_routes = routes; card->of_dapm_routes = routes;
return 0; return 0;
} }
......
...@@ -22,30 +22,42 @@ ...@@ -22,30 +22,42 @@
#include <trace/events/asoc.h> #include <trace/events/asoc.h>
/** /**
* snd_soc_jack_new - Create a new jack * snd_soc_card_jack_new - Create a new jack
* @codec: ASoC codec * @card: ASoC card
* @id: an identifying string for this jack * @id: an identifying string for this jack
* @type: a bitmask of enum snd_jack_type values that can be detected by * @type: a bitmask of enum snd_jack_type values that can be detected by
* this jack * this jack
* @jack: structure to use for the jack * @jack: structure to use for the jack
* @pins: Array of jack pins to be added to the jack or NULL
* @num_pins: Number of elements in the @pins array
* *
* Creates a new jack object. * Creates a new jack object.
* *
* Returns zero if successful, or a negative error code on failure. * Returns zero if successful, or a negative error code on failure.
* On success jack will be initialised. * On success jack will be initialised.
*/ */
int snd_soc_jack_new(struct snd_soc_codec *codec, const char *id, int type, int snd_soc_card_jack_new(struct snd_soc_card *card, const char *id, int type,
struct snd_soc_jack *jack) struct snd_soc_jack *jack, struct snd_soc_jack_pin *pins,
unsigned int num_pins)
{ {
int ret;
mutex_init(&jack->mutex); mutex_init(&jack->mutex);
jack->codec = codec; jack->card = card;
INIT_LIST_HEAD(&jack->pins); INIT_LIST_HEAD(&jack->pins);
INIT_LIST_HEAD(&jack->jack_zones); INIT_LIST_HEAD(&jack->jack_zones);
BLOCKING_INIT_NOTIFIER_HEAD(&jack->notifier); BLOCKING_INIT_NOTIFIER_HEAD(&jack->notifier);
return snd_jack_new(codec->component.card->snd_card, id, type, &jack->jack); ret = snd_jack_new(card->snd_card, id, type, &jack->jack);
if (ret)
return ret;
if (num_pins)
return snd_soc_jack_add_pins(jack, num_pins, pins);
return 0;
} }
EXPORT_SYMBOL_GPL(snd_soc_jack_new); EXPORT_SYMBOL_GPL(snd_soc_card_jack_new);
/** /**
* snd_soc_jack_report - Report the current status for a jack * snd_soc_jack_report - Report the current status for a jack
...@@ -63,7 +75,6 @@ EXPORT_SYMBOL_GPL(snd_soc_jack_new); ...@@ -63,7 +75,6 @@ EXPORT_SYMBOL_GPL(snd_soc_jack_new);
*/ */
void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask) void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask)
{ {
struct snd_soc_codec *codec;
struct snd_soc_dapm_context *dapm; struct snd_soc_dapm_context *dapm;
struct snd_soc_jack_pin *pin; struct snd_soc_jack_pin *pin;
unsigned int sync = 0; unsigned int sync = 0;
...@@ -74,8 +85,7 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask) ...@@ -74,8 +85,7 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask)
if (!jack) if (!jack)
return; return;
codec = jack->codec; dapm = &jack->card->dapm;
dapm = &codec->dapm;
mutex_lock(&jack->mutex); mutex_lock(&jack->mutex);
...@@ -175,12 +185,12 @@ int snd_soc_jack_add_pins(struct snd_soc_jack *jack, int count, ...@@ -175,12 +185,12 @@ int snd_soc_jack_add_pins(struct snd_soc_jack *jack, int count,
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
if (!pins[i].pin) { if (!pins[i].pin) {
dev_err(jack->codec->dev, "ASoC: No name for pin %d\n", dev_err(jack->card->dev, "ASoC: No name for pin %d\n",
i); i);
return -EINVAL; return -EINVAL;
} }
if (!pins[i].mask) { if (!pins[i].mask) {
dev_err(jack->codec->dev, "ASoC: No mask for pin %d" dev_err(jack->card->dev, "ASoC: No mask for pin %d"
" (%s)\n", i, pins[i].pin); " (%s)\n", i, pins[i].pin);
return -EINVAL; return -EINVAL;
} }
...@@ -260,7 +270,7 @@ static void snd_soc_jack_gpio_detect(struct snd_soc_jack_gpio *gpio) ...@@ -260,7 +270,7 @@ static void snd_soc_jack_gpio_detect(struct snd_soc_jack_gpio *gpio)
static irqreturn_t gpio_handler(int irq, void *data) static irqreturn_t gpio_handler(int irq, void *data)
{ {
struct snd_soc_jack_gpio *gpio = data; struct snd_soc_jack_gpio *gpio = data;
struct device *dev = gpio->jack->codec->component.card->dev; struct device *dev = gpio->jack->card->dev;
trace_snd_soc_jack_irq(gpio->name); trace_snd_soc_jack_irq(gpio->name);
...@@ -299,7 +309,7 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count, ...@@ -299,7 +309,7 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
if (!gpios[i].name) { if (!gpios[i].name) {
dev_err(jack->codec->dev, dev_err(jack->card->dev,
"ASoC: No name for gpio at index %d\n", i); "ASoC: No name for gpio at index %d\n", i);
ret = -EINVAL; ret = -EINVAL;
goto undo; goto undo;
...@@ -320,7 +330,7 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count, ...@@ -320,7 +330,7 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
} else { } else {
/* legacy GPIO number */ /* legacy GPIO number */
if (!gpio_is_valid(gpios[i].gpio)) { if (!gpio_is_valid(gpios[i].gpio)) {
dev_err(jack->codec->dev, dev_err(jack->card->dev,
"ASoC: Invalid gpio %d\n", "ASoC: Invalid gpio %d\n",
gpios[i].gpio); gpios[i].gpio);
ret = -EINVAL; ret = -EINVAL;
...@@ -350,7 +360,7 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count, ...@@ -350,7 +360,7 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
if (gpios[i].wake) { if (gpios[i].wake) {
ret = irq_set_irq_wake(gpiod_to_irq(gpios[i].desc), 1); ret = irq_set_irq_wake(gpiod_to_irq(gpios[i].desc), 1);
if (ret != 0) if (ret != 0)
dev_err(jack->codec->dev, dev_err(jack->card->dev,
"ASoC: Failed to mark GPIO at index %d as wake source: %d\n", "ASoC: Failed to mark GPIO at index %d as wake source: %d\n",
i, ret); i, ret);
} }
......
...@@ -2511,6 +2511,7 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) ...@@ -2511,6 +2511,7 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
/* DAPM dai link stream work */ /* DAPM dai link stream work */
INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work); INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work);
pcm->nonatomic = rtd->dai_link->nonatomic;
rtd->pcm = pcm; rtd->pcm = pcm;
pcm->private_data = rtd; pcm->private_data = rtd;
......
...@@ -106,11 +106,10 @@ static int tegra_alc5632_asoc_init(struct snd_soc_pcm_runtime *rtd) ...@@ -106,11 +106,10 @@ static int tegra_alc5632_asoc_init(struct snd_soc_pcm_runtime *rtd)
struct snd_soc_dapm_context *dapm = &codec->dapm; struct snd_soc_dapm_context *dapm = &codec->dapm;
struct tegra_alc5632 *machine = snd_soc_card_get_drvdata(rtd->card); struct tegra_alc5632 *machine = snd_soc_card_get_drvdata(rtd->card);
snd_soc_jack_new(codec, "Headset Jack", SND_JACK_HEADSET, snd_soc_card_jack_new(rtd->card, "Headset Jack", SND_JACK_HEADSET,
&tegra_alc5632_hs_jack); &tegra_alc5632_hs_jack,
snd_soc_jack_add_pins(&tegra_alc5632_hs_jack, tegra_alc5632_hs_jack_pins,
ARRAY_SIZE(tegra_alc5632_hs_jack_pins), ARRAY_SIZE(tegra_alc5632_hs_jack_pins));
tegra_alc5632_hs_jack_pins);
if (gpio_is_valid(machine->gpio_hp_det)) { if (gpio_is_valid(machine->gpio_hp_det)) {
tegra_alc5632_hp_jack_gpio.gpio = machine->gpio_hp_det; tegra_alc5632_hp_jack_gpio.gpio = machine->gpio_hp_det;
......
...@@ -133,24 +133,26 @@ static const struct snd_soc_dapm_widget tegra_max98090_dapm_widgets[] = { ...@@ -133,24 +133,26 @@ static const struct snd_soc_dapm_widget tegra_max98090_dapm_widgets[] = {
SND_SOC_DAPM_HP("Headphones", NULL), SND_SOC_DAPM_HP("Headphones", NULL),
SND_SOC_DAPM_SPK("Speakers", NULL), SND_SOC_DAPM_SPK("Speakers", NULL),
SND_SOC_DAPM_MIC("Mic Jack", NULL), SND_SOC_DAPM_MIC("Mic Jack", NULL),
SND_SOC_DAPM_MIC("Int Mic", NULL),
}; };
static const struct snd_kcontrol_new tegra_max98090_controls[] = { static const struct snd_kcontrol_new tegra_max98090_controls[] = {
SOC_DAPM_PIN_SWITCH("Headphones"),
SOC_DAPM_PIN_SWITCH("Speakers"), SOC_DAPM_PIN_SWITCH("Speakers"),
SOC_DAPM_PIN_SWITCH("Mic Jack"),
SOC_DAPM_PIN_SWITCH("Int Mic"),
}; };
static int tegra_max98090_asoc_init(struct snd_soc_pcm_runtime *rtd) static int tegra_max98090_asoc_init(struct snd_soc_pcm_runtime *rtd)
{ {
struct snd_soc_dai *codec_dai = rtd->codec_dai;
struct snd_soc_codec *codec = codec_dai->codec;
struct tegra_max98090 *machine = snd_soc_card_get_drvdata(rtd->card); struct tegra_max98090 *machine = snd_soc_card_get_drvdata(rtd->card);
if (gpio_is_valid(machine->gpio_hp_det)) { if (gpio_is_valid(machine->gpio_hp_det)) {
snd_soc_jack_new(codec, "Headphones", SND_JACK_HEADPHONE, snd_soc_card_jack_new(rtd->card, "Headphones",
&tegra_max98090_hp_jack); SND_JACK_HEADPHONE,
snd_soc_jack_add_pins(&tegra_max98090_hp_jack, &tegra_max98090_hp_jack,
ARRAY_SIZE(tegra_max98090_hp_jack_pins), tegra_max98090_hp_jack_pins,
tegra_max98090_hp_jack_pins); ARRAY_SIZE(tegra_max98090_hp_jack_pins));
tegra_max98090_hp_jack_gpio.gpio = machine->gpio_hp_det; tegra_max98090_hp_jack_gpio.gpio = machine->gpio_hp_det;
snd_soc_jack_add_gpios(&tegra_max98090_hp_jack, snd_soc_jack_add_gpios(&tegra_max98090_hp_jack,
...@@ -159,11 +161,11 @@ static int tegra_max98090_asoc_init(struct snd_soc_pcm_runtime *rtd) ...@@ -159,11 +161,11 @@ static int tegra_max98090_asoc_init(struct snd_soc_pcm_runtime *rtd)
} }
if (gpio_is_valid(machine->gpio_mic_det)) { if (gpio_is_valid(machine->gpio_mic_det)) {
snd_soc_jack_new(codec, "Mic Jack", SND_JACK_MICROPHONE, snd_soc_card_jack_new(rtd->card, "Mic Jack",
&tegra_max98090_mic_jack); SND_JACK_MICROPHONE,
snd_soc_jack_add_pins(&tegra_max98090_mic_jack, &tegra_max98090_mic_jack,
ARRAY_SIZE(tegra_max98090_mic_jack_pins), tegra_max98090_mic_jack_pins,
tegra_max98090_mic_jack_pins); ARRAY_SIZE(tegra_max98090_mic_jack_pins));
tegra_max98090_mic_jack_gpio.gpio = machine->gpio_mic_det; tegra_max98090_mic_jack_gpio.gpio = machine->gpio_mic_det;
snd_soc_jack_add_gpios(&tegra_max98090_mic_jack, snd_soc_jack_add_gpios(&tegra_max98090_mic_jack,
......
...@@ -108,15 +108,11 @@ static const struct snd_kcontrol_new tegra_rt5640_controls[] = { ...@@ -108,15 +108,11 @@ static const struct snd_kcontrol_new tegra_rt5640_controls[] = {
static int tegra_rt5640_asoc_init(struct snd_soc_pcm_runtime *rtd) static int tegra_rt5640_asoc_init(struct snd_soc_pcm_runtime *rtd)
{ {
struct snd_soc_dai *codec_dai = rtd->codec_dai;
struct snd_soc_codec *codec = codec_dai->codec;
struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(rtd->card); struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(rtd->card);
snd_soc_jack_new(codec, "Headphones", SND_JACK_HEADPHONE, snd_soc_card_jack_new(rtd->card, "Headphones", SND_JACK_HEADPHONE,
&tegra_rt5640_hp_jack); &tegra_rt5640_hp_jack, tegra_rt5640_hp_jack_pins,
snd_soc_jack_add_pins(&tegra_rt5640_hp_jack, ARRAY_SIZE(tegra_rt5640_hp_jack_pins));
ARRAY_SIZE(tegra_rt5640_hp_jack_pins),
tegra_rt5640_hp_jack_pins);
if (gpio_is_valid(machine->gpio_hp_det)) { if (gpio_is_valid(machine->gpio_hp_det)) {
tegra_rt5640_hp_jack_gpio.gpio = machine->gpio_hp_det; tegra_rt5640_hp_jack_gpio.gpio = machine->gpio_hp_det;
......
...@@ -146,10 +146,9 @@ static int tegra_rt5677_asoc_init(struct snd_soc_pcm_runtime *rtd) ...@@ -146,10 +146,9 @@ static int tegra_rt5677_asoc_init(struct snd_soc_pcm_runtime *rtd)
struct snd_soc_dapm_context *dapm = &codec->dapm; struct snd_soc_dapm_context *dapm = &codec->dapm;
struct tegra_rt5677 *machine = snd_soc_card_get_drvdata(rtd->card); struct tegra_rt5677 *machine = snd_soc_card_get_drvdata(rtd->card);
snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE, snd_soc_card_jack_new(rtd->card, "Headphone Jack", SND_JACK_HEADPHONE,
&tegra_rt5677_hp_jack); &tegra_rt5677_hp_jack,
snd_soc_jack_add_pins(&tegra_rt5677_hp_jack, 1, &tegra_rt5677_hp_jack_pins, 1);
&tegra_rt5677_hp_jack_pins);
if (gpio_is_valid(machine->gpio_hp_det)) { if (gpio_is_valid(machine->gpio_hp_det)) {
tegra_rt5677_hp_jack_gpio.gpio = machine->gpio_hp_det; tegra_rt5677_hp_jack_gpio.gpio = machine->gpio_hp_det;
...@@ -158,10 +157,9 @@ static int tegra_rt5677_asoc_init(struct snd_soc_pcm_runtime *rtd) ...@@ -158,10 +157,9 @@ static int tegra_rt5677_asoc_init(struct snd_soc_pcm_runtime *rtd)
} }
snd_soc_jack_new(codec, "Mic Jack", SND_JACK_MICROPHONE, snd_soc_card_jack_new(rtd->card, "Mic Jack", SND_JACK_MICROPHONE,
&tegra_rt5677_mic_jack); &tegra_rt5677_mic_jack,
snd_soc_jack_add_pins(&tegra_rt5677_mic_jack, 1, &tegra_rt5677_mic_jack_pins, 1);
&tegra_rt5677_mic_jack_pins);
if (gpio_is_valid(machine->gpio_mic_present)) { if (gpio_is_valid(machine->gpio_mic_present)) {
tegra_rt5677_mic_jack_gpio.gpio = machine->gpio_mic_present; tegra_rt5677_mic_jack_gpio.gpio = machine->gpio_mic_present;
......
...@@ -177,21 +177,19 @@ static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd) ...@@ -177,21 +177,19 @@ static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd)
if (gpio_is_valid(machine->gpio_hp_det)) { if (gpio_is_valid(machine->gpio_hp_det)) {
tegra_wm8903_hp_jack_gpio.gpio = machine->gpio_hp_det; tegra_wm8903_hp_jack_gpio.gpio = machine->gpio_hp_det;
snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE, snd_soc_card_jack_new(rtd->card, "Headphone Jack",
&tegra_wm8903_hp_jack); SND_JACK_HEADPHONE, &tegra_wm8903_hp_jack,
snd_soc_jack_add_pins(&tegra_wm8903_hp_jack, tegra_wm8903_hp_jack_pins,
ARRAY_SIZE(tegra_wm8903_hp_jack_pins), ARRAY_SIZE(tegra_wm8903_hp_jack_pins));
tegra_wm8903_hp_jack_pins);
snd_soc_jack_add_gpios(&tegra_wm8903_hp_jack, snd_soc_jack_add_gpios(&tegra_wm8903_hp_jack,
1, 1,
&tegra_wm8903_hp_jack_gpio); &tegra_wm8903_hp_jack_gpio);
} }
snd_soc_jack_new(codec, "Mic Jack", SND_JACK_MICROPHONE, snd_soc_card_jack_new(rtd->card, "Mic Jack", SND_JACK_MICROPHONE,
&tegra_wm8903_mic_jack); &tegra_wm8903_mic_jack,
snd_soc_jack_add_pins(&tegra_wm8903_mic_jack, tegra_wm8903_mic_jack_pins,
ARRAY_SIZE(tegra_wm8903_mic_jack_pins), ARRAY_SIZE(tegra_wm8903_mic_jack_pins));
tegra_wm8903_mic_jack_pins);
wm8903_mic_detect(codec, &tegra_wm8903_mic_jack, SND_JACK_MICROPHONE, wm8903_mic_detect(codec, &tegra_wm8903_mic_jack, SND_JACK_MICROPHONE,
0); 0);
......
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