2
0
mirror of https://github.com/edk2-porting/linux-next.git synced 2024-12-23 12:43:55 +08:00

Merge remote-tracking branch 'asoc/fix/fsl' into asoc-linus

This commit is contained in:
Mark Brown 2013-11-20 15:20:31 +00:00
commit cde4d7596c
20 changed files with 209 additions and 124 deletions

View File

@ -31,6 +31,8 @@ struct cs42l52_platform_data {
/* Charge Pump Freq. Check datasheet Pg73 */ /* Charge Pump Freq. Check datasheet Pg73 */
unsigned int chgfreq; unsigned int chgfreq;
/* Reset GPIO */
unsigned int reset_gpio;
}; };
#endif /* __CS42L52_H */ #endif /* __CS42L52_H */

View File

@ -2312,17 +2312,17 @@ static int ab8500_codec_set_dai_tdm_slot(struct snd_soc_dai *dai,
case 0: case 0:
break; break;
case 1: case 1:
slot = find_first_bit((unsigned long *)&tx_mask, 32); slot = ffs(tx_mask);
snd_soc_update_bits(codec, AB8500_DASLOTCONF1, mask, slot); snd_soc_update_bits(codec, AB8500_DASLOTCONF1, mask, slot);
snd_soc_update_bits(codec, AB8500_DASLOTCONF3, mask, slot); snd_soc_update_bits(codec, AB8500_DASLOTCONF3, mask, slot);
snd_soc_update_bits(codec, AB8500_DASLOTCONF2, mask, slot); snd_soc_update_bits(codec, AB8500_DASLOTCONF2, mask, slot);
snd_soc_update_bits(codec, AB8500_DASLOTCONF4, mask, slot); snd_soc_update_bits(codec, AB8500_DASLOTCONF4, mask, slot);
break; break;
case 2: case 2:
slot = find_first_bit((unsigned long *)&tx_mask, 32); slot = ffs(tx_mask);
snd_soc_update_bits(codec, AB8500_DASLOTCONF1, mask, slot); snd_soc_update_bits(codec, AB8500_DASLOTCONF1, mask, slot);
snd_soc_update_bits(codec, AB8500_DASLOTCONF3, mask, slot); snd_soc_update_bits(codec, AB8500_DASLOTCONF3, mask, slot);
slot = find_next_bit((unsigned long *)&tx_mask, 32, slot + 1); slot = fls(tx_mask);
snd_soc_update_bits(codec, AB8500_DASLOTCONF2, mask, slot); snd_soc_update_bits(codec, AB8500_DASLOTCONF2, mask, slot);
snd_soc_update_bits(codec, AB8500_DASLOTCONF4, mask, slot); snd_soc_update_bits(codec, AB8500_DASLOTCONF4, mask, slot);
break; break;
@ -2353,18 +2353,18 @@ static int ab8500_codec_set_dai_tdm_slot(struct snd_soc_dai *dai,
case 0: case 0:
break; break;
case 1: case 1:
slot = find_first_bit((unsigned long *)&rx_mask, 32); slot = ffs(rx_mask);
snd_soc_update_bits(codec, AB8500_ADSLOTSEL(slot), snd_soc_update_bits(codec, AB8500_ADSLOTSEL(slot),
AB8500_MASK_SLOT(slot), AB8500_MASK_SLOT(slot),
AB8500_ADSLOTSELX_AD_OUT_TO_SLOT(AB8500_AD_OUT3, slot)); AB8500_ADSLOTSELX_AD_OUT_TO_SLOT(AB8500_AD_OUT3, slot));
break; break;
case 2: case 2:
slot = find_first_bit((unsigned long *)&rx_mask, 32); slot = ffs(rx_mask);
snd_soc_update_bits(codec, snd_soc_update_bits(codec,
AB8500_ADSLOTSEL(slot), AB8500_ADSLOTSEL(slot),
AB8500_MASK_SLOT(slot), AB8500_MASK_SLOT(slot),
AB8500_ADSLOTSELX_AD_OUT_TO_SLOT(AB8500_AD_OUT3, slot)); AB8500_ADSLOTSELX_AD_OUT_TO_SLOT(AB8500_AD_OUT3, slot));
slot = find_next_bit((unsigned long *)&rx_mask, 32, slot + 1); slot = fls(rx_mask);
snd_soc_update_bits(codec, snd_soc_update_bits(codec,
AB8500_ADSLOTSEL(slot), AB8500_ADSLOTSEL(slot),
AB8500_MASK_SLOT(slot), AB8500_MASK_SLOT(slot),
@ -2586,6 +2586,8 @@ static int ab8500_codec_driver_probe(struct platform_device *pdev)
/* Create driver private-data struct */ /* Create driver private-data struct */
drvdata = devm_kzalloc(&pdev->dev, sizeof(struct ab8500_codec_drvdata), drvdata = devm_kzalloc(&pdev->dev, sizeof(struct ab8500_codec_drvdata),
GFP_KERNEL); GFP_KERNEL);
if (!drvdata)
return -ENOMEM;
drvdata->sid_status = SID_UNCONFIGURED; drvdata->sid_status = SID_UNCONFIGURED;
drvdata->anc_status = ANC_UNCONFIGURED; drvdata->anc_status = ANC_UNCONFIGURED;
dev_set_drvdata(&pdev->dev, drvdata); dev_set_drvdata(&pdev->dev, drvdata);

View File

@ -257,7 +257,7 @@ static int ak4642_dai_startup(struct snd_pcm_substream *substream,
* This operation came from example code of * This operation came from example code of
* "ASAHI KASEI AK4642" (japanese) manual p94. * "ASAHI KASEI AK4642" (japanese) manual p94.
*/ */
snd_soc_write(codec, SG_SL1, PMMP | MGAIN0); snd_soc_update_bits(codec, SG_SL1, PMMP | MGAIN0, PMMP | MGAIN0);
snd_soc_write(codec, TIMER, ZTM(0x3) | WTM(0x3)); snd_soc_write(codec, TIMER, ZTM(0x3) | WTM(0x3));
snd_soc_write(codec, ALC_CTL1, ALC | LMTH0); snd_soc_write(codec, ALC_CTL1, ALC | LMTH0);
snd_soc_update_bits(codec, PW_MGMT1, PMADL, PMADL); snd_soc_update_bits(codec, PW_MGMT1, PMADL, PMADL);

View File

@ -17,6 +17,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/input.h> #include <linux/input.h>
@ -1116,40 +1117,6 @@ static int cs42l52_probe(struct snd_soc_codec *codec)
cs42l52->sysclk = CS42L52_DEFAULT_CLK; cs42l52->sysclk = CS42L52_DEFAULT_CLK;
cs42l52->config.format = CS42L52_DEFAULT_FORMAT; cs42l52->config.format = CS42L52_DEFAULT_FORMAT;
/* Set Platform MICx CFG */
snd_soc_update_bits(codec, CS42L52_MICA_CTL,
CS42L52_MIC_CTL_TYPE_MASK,
cs42l52->pdata.mica_cfg <<
CS42L52_MIC_CTL_TYPE_SHIFT);
snd_soc_update_bits(codec, CS42L52_MICB_CTL,
CS42L52_MIC_CTL_TYPE_MASK,
cs42l52->pdata.micb_cfg <<
CS42L52_MIC_CTL_TYPE_SHIFT);
/* if Single Ended, Get Mic_Select */
if (cs42l52->pdata.mica_cfg)
snd_soc_update_bits(codec, CS42L52_MICA_CTL,
CS42L52_MIC_CTL_MIC_SEL_MASK,
cs42l52->pdata.mica_sel <<
CS42L52_MIC_CTL_MIC_SEL_SHIFT);
if (cs42l52->pdata.micb_cfg)
snd_soc_update_bits(codec, CS42L52_MICB_CTL,
CS42L52_MIC_CTL_MIC_SEL_MASK,
cs42l52->pdata.micb_sel <<
CS42L52_MIC_CTL_MIC_SEL_SHIFT);
/* Set Platform Charge Pump Freq */
snd_soc_update_bits(codec, CS42L52_CHARGE_PUMP,
CS42L52_CHARGE_PUMP_MASK,
cs42l52->pdata.chgfreq <<
CS42L52_CHARGE_PUMP_SHIFT);
/* Set Platform Bias Level */
snd_soc_update_bits(codec, CS42L52_IFACE_CTL2,
CS42L52_IFACE_CTL2_BIAS_LVL,
cs42l52->pdata.micbias_lvl);
return ret; return ret;
} }
@ -1205,6 +1172,7 @@ static int cs42l52_i2c_probe(struct i2c_client *i2c_client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
struct cs42l52_private *cs42l52; struct cs42l52_private *cs42l52;
struct cs42l52_platform_data *pdata = dev_get_platdata(&i2c_client->dev);
int ret; int ret;
unsigned int devid = 0; unsigned int devid = 0;
unsigned int reg; unsigned int reg;
@ -1222,11 +1190,22 @@ static int cs42l52_i2c_probe(struct i2c_client *i2c_client,
return ret; return ret;
} }
i2c_set_clientdata(i2c_client, cs42l52); if (pdata)
cs42l52->pdata = *pdata;
if (dev_get_platdata(&i2c_client->dev)) if (cs42l52->pdata.reset_gpio) {
memcpy(&cs42l52->pdata, dev_get_platdata(&i2c_client->dev), ret = gpio_request_one(cs42l52->pdata.reset_gpio,
sizeof(cs42l52->pdata)); GPIOF_OUT_INIT_HIGH, "CS42L52 /RST");
if (ret < 0) {
dev_err(&i2c_client->dev, "Failed to request /RST %d: %d\n",
cs42l52->pdata.reset_gpio, ret);
return ret;
}
gpio_set_value_cansleep(cs42l52->pdata.reset_gpio, 0);
gpio_set_value_cansleep(cs42l52->pdata.reset_gpio, 1);
}
i2c_set_clientdata(i2c_client, cs42l52);
ret = regmap_register_patch(cs42l52->regmap, cs42l52_threshold_patch, ret = regmap_register_patch(cs42l52->regmap, cs42l52_threshold_patch,
ARRAY_SIZE(cs42l52_threshold_patch)); ARRAY_SIZE(cs42l52_threshold_patch));
@ -1244,7 +1223,43 @@ static int cs42l52_i2c_probe(struct i2c_client *i2c_client,
return ret; return ret;
} }
regcache_cache_only(cs42l52->regmap, true); dev_info(&i2c_client->dev, "Cirrus Logic CS42L52, Revision: %02X\n",
reg & 0xFF);
/* Set Platform Data */
if (cs42l52->pdata.mica_cfg)
regmap_update_bits(cs42l52->regmap, CS42L52_MICA_CTL,
CS42L52_MIC_CTL_TYPE_MASK,
cs42l52->pdata.mica_cfg <<
CS42L52_MIC_CTL_TYPE_SHIFT);
if (cs42l52->pdata.micb_cfg)
regmap_update_bits(cs42l52->regmap, CS42L52_MICB_CTL,
CS42L52_MIC_CTL_TYPE_MASK,
cs42l52->pdata.micb_cfg <<
CS42L52_MIC_CTL_TYPE_SHIFT);
if (cs42l52->pdata.mica_sel)
regmap_update_bits(cs42l52->regmap, CS42L52_MICA_CTL,
CS42L52_MIC_CTL_MIC_SEL_MASK,
cs42l52->pdata.mica_sel <<
CS42L52_MIC_CTL_MIC_SEL_SHIFT);
if (cs42l52->pdata.micb_sel)
regmap_update_bits(cs42l52->regmap, CS42L52_MICB_CTL,
CS42L52_MIC_CTL_MIC_SEL_MASK,
cs42l52->pdata.micb_sel <<
CS42L52_MIC_CTL_MIC_SEL_SHIFT);
if (cs42l52->pdata.chgfreq)
regmap_update_bits(cs42l52->regmap, CS42L52_CHARGE_PUMP,
CS42L52_CHARGE_PUMP_MASK,
cs42l52->pdata.chgfreq <<
CS42L52_CHARGE_PUMP_SHIFT);
if (cs42l52->pdata.micbias_lvl)
regmap_update_bits(cs42l52->regmap, CS42L52_IFACE_CTL2,
CS42L52_IFACE_CTL2_BIAS_LVL,
cs42l52->pdata.micbias_lvl);
ret = snd_soc_register_codec(&i2c_client->dev, ret = snd_soc_register_codec(&i2c_client->dev,
&soc_codec_dev_cs42l52, &cs42l52_dai, 1); &soc_codec_dev_cs42l52, &cs42l52_dai, 1);

View File

@ -269,6 +269,6 @@
#define CS42L52_FIX_BITS1 0x3E #define CS42L52_FIX_BITS1 0x3E
#define CS42L52_FIX_BITS2 0x47 #define CS42L52_FIX_BITS2 0x47
#define CS42L52_MAX_REGISTER 0x34 #define CS42L52_MAX_REGISTER 0x47
#endif #endif

View File

@ -342,6 +342,8 @@ static int ml26124_hw_params(struct snd_pcm_substream *substream,
struct ml26124_priv *priv = snd_soc_codec_get_drvdata(codec); struct ml26124_priv *priv = snd_soc_codec_get_drvdata(codec);
int i = get_coeff(priv->mclk, params_rate(hw_params)); int i = get_coeff(priv->mclk, params_rate(hw_params));
if (i < 0)
return i;
priv->substream = substream; priv->substream = substream;
priv->rate = params_rate(hw_params); priv->rate = params_rate(hw_params);

View File

@ -1604,8 +1604,8 @@ static int rt5640_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_codec *codec = rtd->codec; struct snd_soc_codec *codec = rtd->codec;
struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec); struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
unsigned int val_len = 0, val_clk, mask_clk, dai_sel; unsigned int val_len = 0, val_clk, mask_clk;
int pre_div, bclk_ms, frame_size; int dai_sel, pre_div, bclk_ms, frame_size;
rt5640->lrck[dai->id] = params_rate(params); rt5640->lrck[dai->id] = params_rate(params);
pre_div = get_clk_info(rt5640->sysclk, rt5640->lrck[dai->id]); pre_div = get_clk_info(rt5640->sysclk, rt5640->lrck[dai->id]);
@ -1675,7 +1675,8 @@ static int rt5640_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{ {
struct snd_soc_codec *codec = dai->codec; struct snd_soc_codec *codec = dai->codec;
struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec); struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
unsigned int reg_val = 0, dai_sel; unsigned int reg_val = 0;
int dai_sel;
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBM_CFM: case SND_SOC_DAIFMT_CBM_CFM:

View File

@ -793,11 +793,11 @@ static int wm0010_set_sysclk(struct snd_soc_codec *codec, int source,
wm0010->max_spi_freq = 0; wm0010->max_spi_freq = 0;
} else { } else {
for (i = 0; i < ARRAY_SIZE(pll_clock_map); i++) for (i = 0; i < ARRAY_SIZE(pll_clock_map); i++)
if (freq >= pll_clock_map[i].max_sysclk) if (freq >= pll_clock_map[i].max_sysclk) {
wm0010->max_spi_freq = pll_clock_map[i].max_pll_spi_speed;
wm0010->pll_clkctrl1 = pll_clock_map[i].pll_clkctrl1;
break; break;
}
wm0010->max_spi_freq = pll_clock_map[i].max_pll_spi_speed;
wm0010->pll_clkctrl1 = pll_clock_map[i].pll_clkctrl1;
} }
return 0; return 0;

View File

@ -1024,24 +1024,36 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = {
ARIZONA_MUX_ROUTES("ASRC2L", "ASRC2L"), ARIZONA_MUX_ROUTES("ASRC2L", "ASRC2L"),
ARIZONA_MUX_ROUTES("ASRC2R", "ASRC2R"), ARIZONA_MUX_ROUTES("ASRC2R", "ASRC2R"),
{ "AEC Loopback", "HPOUT1L", "OUT1L" },
{ "AEC Loopback", "HPOUT1R", "OUT1R" },
{ "HPOUT1L", NULL, "OUT1L" }, { "HPOUT1L", NULL, "OUT1L" },
{ "HPOUT1R", NULL, "OUT1R" }, { "HPOUT1R", NULL, "OUT1R" },
{ "AEC Loopback", "HPOUT2L", "OUT2L" },
{ "AEC Loopback", "HPOUT2R", "OUT2R" },
{ "HPOUT2L", NULL, "OUT2L" }, { "HPOUT2L", NULL, "OUT2L" },
{ "HPOUT2R", NULL, "OUT2R" }, { "HPOUT2R", NULL, "OUT2R" },
{ "AEC Loopback", "HPOUT3L", "OUT3L" },
{ "AEC Loopback", "HPOUT3R", "OUT3R" },
{ "HPOUT3L", NULL, "OUT3L" }, { "HPOUT3L", NULL, "OUT3L" },
{ "HPOUT3R", NULL, "OUT3L" }, { "HPOUT3R", NULL, "OUT3L" },
{ "AEC Loopback", "SPKOUTL", "OUT4L" },
{ "SPKOUTLN", NULL, "OUT4L" }, { "SPKOUTLN", NULL, "OUT4L" },
{ "SPKOUTLP", NULL, "OUT4L" }, { "SPKOUTLP", NULL, "OUT4L" },
{ "AEC Loopback", "SPKOUTR", "OUT4R" },
{ "SPKOUTRN", NULL, "OUT4R" }, { "SPKOUTRN", NULL, "OUT4R" },
{ "SPKOUTRP", NULL, "OUT4R" }, { "SPKOUTRP", NULL, "OUT4R" },
{ "AEC Loopback", "SPKDAT1L", "OUT5L" },
{ "AEC Loopback", "SPKDAT1R", "OUT5R" },
{ "SPKDAT1L", NULL, "OUT5L" }, { "SPKDAT1L", NULL, "OUT5L" },
{ "SPKDAT1R", NULL, "OUT5R" }, { "SPKDAT1R", NULL, "OUT5R" },
{ "AEC Loopback", "SPKDAT2L", "OUT6L" },
{ "AEC Loopback", "SPKDAT2R", "OUT6R" },
{ "SPKDAT2L", NULL, "OUT6L" }, { "SPKDAT2L", NULL, "OUT6L" },
{ "SPKDAT2R", NULL, "OUT6R" }, { "SPKDAT2R", NULL, "OUT6R" },

View File

@ -1758,6 +1758,9 @@ SOC_DOUBLE_R_TLV("EQ4 Volume", WM8962_EQ3, WM8962_EQ23,
WM8962_EQL_B4_GAIN_SHIFT, 31, 0, eq_tlv), WM8962_EQL_B4_GAIN_SHIFT, 31, 0, eq_tlv),
SOC_DOUBLE_R_TLV("EQ5 Volume", WM8962_EQ3, WM8962_EQ23, SOC_DOUBLE_R_TLV("EQ5 Volume", WM8962_EQ3, WM8962_EQ23,
WM8962_EQL_B5_GAIN_SHIFT, 31, 0, eq_tlv), WM8962_EQL_B5_GAIN_SHIFT, 31, 0, eq_tlv),
SND_SOC_BYTES("EQL Coefficients", WM8962_EQ4, 18),
SND_SOC_BYTES("EQR Coefficients", WM8962_EQ24, 18),
SOC_SINGLE("3D Switch", WM8962_THREED1, 0, 1, 0), SOC_SINGLE("3D Switch", WM8962_THREED1, 0, 1, 0),
SND_SOC_BYTES_MASK("3D Coefficients", WM8962_THREED1, 4, WM8962_THREED_ENA), SND_SOC_BYTES_MASK("3D Coefficients", WM8962_THREED1, 4, WM8962_THREED_ENA),
@ -1775,6 +1778,11 @@ WM8962_DSP2_ENABLE("HPF2 Switch", WM8962_HPF2_ENA_SHIFT),
SND_SOC_BYTES("HPF Coefficients", WM8962_LHPF2, 1), SND_SOC_BYTES("HPF Coefficients", WM8962_LHPF2, 1),
WM8962_DSP2_ENABLE("HD Bass Switch", WM8962_HDBASS_ENA_SHIFT), WM8962_DSP2_ENABLE("HD Bass Switch", WM8962_HDBASS_ENA_SHIFT),
SND_SOC_BYTES("HD Bass Coefficients", WM8962_HDBASS_AI_1, 30), SND_SOC_BYTES("HD Bass Coefficients", WM8962_HDBASS_AI_1, 30),
SOC_DOUBLE("ALC Switch", WM8962_ALC1, WM8962_ALCL_ENA_SHIFT,
WM8962_ALCR_ENA_SHIFT, 1, 0),
SND_SOC_BYTES_MASK("ALC Coefficients", WM8962_ALC1, 4,
WM8962_ALCL_ENA_MASK | WM8962_ALCR_ENA_MASK),
}; };
static const struct snd_kcontrol_new wm8962_spk_mono_controls[] = { static const struct snd_kcontrol_new wm8962_spk_mono_controls[] = {
@ -3616,28 +3624,28 @@ static int wm8962_i2c_probe(struct i2c_client *i2c,
0); 0);
/* Apply static configuration for GPIOs */ /* Apply static configuration for GPIOs */
for (i = 0; i < ARRAY_SIZE(pdata->gpio_init); i++) for (i = 0; i < ARRAY_SIZE(wm8962->pdata.gpio_init); i++)
if (pdata->gpio_init[i]) { if (wm8962->pdata.gpio_init[i]) {
wm8962_set_gpio_mode(wm8962, i + 1); wm8962_set_gpio_mode(wm8962, i + 1);
regmap_write(wm8962->regmap, 0x200 + i, regmap_write(wm8962->regmap, 0x200 + i,
pdata->gpio_init[i] & 0xffff); wm8962->pdata.gpio_init[i] & 0xffff);
} }
/* Put the speakers into mono mode? */ /* Put the speakers into mono mode? */
if (pdata->spk_mono) if (wm8962->pdata.spk_mono)
regmap_update_bits(wm8962->regmap, WM8962_CLASS_D_CONTROL_2, regmap_update_bits(wm8962->regmap, WM8962_CLASS_D_CONTROL_2,
WM8962_SPK_MONO_MASK, WM8962_SPK_MONO); WM8962_SPK_MONO_MASK, WM8962_SPK_MONO);
/* Micbias setup, detection enable and detection /* Micbias setup, detection enable and detection
* threasholds. */ * threasholds. */
if (pdata->mic_cfg) if (wm8962->pdata.mic_cfg)
regmap_update_bits(wm8962->regmap, WM8962_ADDITIONAL_CONTROL_4, regmap_update_bits(wm8962->regmap, WM8962_ADDITIONAL_CONTROL_4,
WM8962_MICDET_ENA | WM8962_MICDET_ENA |
WM8962_MICDET_THR_MASK | WM8962_MICDET_THR_MASK |
WM8962_MICSHORT_THR_MASK | WM8962_MICSHORT_THR_MASK |
WM8962_MICBIAS_LVL, WM8962_MICBIAS_LVL,
pdata->mic_cfg); wm8962->pdata.mic_cfg);
/* Latch volume update bits */ /* Latch volume update bits */
regmap_update_bits(wm8962->regmap, WM8962_LEFT_INPUT_VOLUME, regmap_update_bits(wm8962->regmap, WM8962_LEFT_INPUT_VOLUME,
@ -3682,7 +3690,7 @@ static int wm8962_i2c_probe(struct i2c_client *i2c,
} }
if (wm8962->irq) { if (wm8962->irq) {
if (pdata->irq_active_low) { if (wm8962->pdata.irq_active_low) {
trigger = IRQF_TRIGGER_LOW; trigger = IRQF_TRIGGER_LOW;
irq_pol = WM8962_IRQ_POL; irq_pol = WM8962_IRQ_POL;
} else { } else {

View File

@ -438,6 +438,8 @@ static int wm8996_get_retune_mobile_enum(struct snd_kcontrol *kcontrol,
struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
int block = wm8996_get_retune_mobile_block(kcontrol->id.name); int block = wm8996_get_retune_mobile_block(kcontrol->id.name);
if (block < 0)
return block;
ucontrol->value.enumerated.item[0] = wm8996->retune_mobile_cfg[block]; ucontrol->value.enumerated.item[0] = wm8996->retune_mobile_cfg[block];
return 0; return 0;

View File

@ -396,11 +396,12 @@ static int wm_coeff_write_control(struct snd_kcontrol *kcontrol,
ret = regmap_raw_write(adsp->regmap, reg, scratch, ret = regmap_raw_write(adsp->regmap, reg, scratch,
ctl->len); ctl->len);
if (ret) { if (ret) {
adsp_err(adsp, "Failed to write %zu bytes to %x\n", adsp_err(adsp, "Failed to write %zu bytes to %x: %d\n",
ctl->len, reg); ctl->len, reg, ret);
kfree(scratch); kfree(scratch);
return ret; return ret;
} }
adsp_dbg(adsp, "Wrote %zu bytes to %x\n", ctl->len, reg);
kfree(scratch); kfree(scratch);
@ -450,11 +451,12 @@ static int wm_coeff_read_control(struct snd_kcontrol *kcontrol,
ret = regmap_raw_read(adsp->regmap, reg, scratch, ctl->len); ret = regmap_raw_read(adsp->regmap, reg, scratch, ctl->len);
if (ret) { if (ret) {
adsp_err(adsp, "Failed to read %zu bytes from %x\n", adsp_err(adsp, "Failed to read %zu bytes from %x: %d\n",
ctl->len, reg); ctl->len, reg, ret);
kfree(scratch); kfree(scratch);
return ret; return ret;
} }
adsp_dbg(adsp, "Read %zu bytes from %x\n", ctl->len, reg);
memcpy(buf, scratch, ctl->len); memcpy(buf, scratch, ctl->len);
kfree(scratch); kfree(scratch);
@ -568,6 +570,7 @@ static int wm_adsp_load(struct wm_adsp *dsp)
file, header->ver); file, header->ver);
goto out_fw; goto out_fw;
} }
adsp_info(dsp, "Firmware version: %d\n", header->ver);
if (header->core != dsp->type) { if (header->core != dsp->type) {
adsp_err(dsp, "%s: invalid core %d != %d\n", adsp_err(dsp, "%s: invalid core %d != %d\n",
@ -689,7 +692,8 @@ static int wm_adsp_load(struct wm_adsp *dsp)
&buf_list); &buf_list);
if (!buf) { if (!buf) {
adsp_err(dsp, "Out of memory\n"); adsp_err(dsp, "Out of memory\n");
return -ENOMEM; ret = -ENOMEM;
goto out_fw;
} }
ret = regmap_raw_write_async(regmap, reg, buf->buf, ret = regmap_raw_write_async(regmap, reg, buf->buf,
@ -1313,8 +1317,8 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp)
le32_to_cpu(blk->len)); le32_to_cpu(blk->len));
if (ret != 0) { if (ret != 0) {
adsp_err(dsp, adsp_err(dsp,
"%s.%d: Failed to write to %x in %s\n", "%s.%d: Failed to write to %x in %s: %d\n",
file, blocks, reg, region_name); file, blocks, reg, region_name, ret);
} }
} }
@ -1358,6 +1362,7 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w,
struct snd_soc_codec *codec = w->codec; struct snd_soc_codec *codec = w->codec;
struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec); struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec);
struct wm_adsp *dsp = &dsps[w->shift]; struct wm_adsp *dsp = &dsps[w->shift];
struct wm_adsp_alg_region *alg_region;
struct wm_coeff_ctl *ctl; struct wm_coeff_ctl *ctl;
int ret; int ret;
int val; int val;
@ -1435,6 +1440,14 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w,
list_for_each_entry(ctl, &dsp->ctl_list, list) list_for_each_entry(ctl, &dsp->ctl_list, list)
ctl->enabled = 0; ctl->enabled = 0;
while (!list_empty(&dsp->alg_regions)) {
alg_region = list_first_entry(&dsp->alg_regions,
struct wm_adsp_alg_region,
list);
list_del(&alg_region->list);
kfree(alg_region);
}
break; break;
default: default:

View File

@ -42,7 +42,8 @@ static int eukrea_tlv320_hw_params(struct snd_pcm_substream *substream,
SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBM_CFM); SND_SOC_DAIFMT_CBM_CFM);
if (ret) { if (ret) {
pr_err("%s: failed set cpu dai format\n", __func__); dev_err(cpu_dai->dev,
"Failed to set the cpu dai format.\n");
return ret; return ret;
} }
@ -50,14 +51,16 @@ static int eukrea_tlv320_hw_params(struct snd_pcm_substream *substream,
SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBM_CFM); SND_SOC_DAIFMT_CBM_CFM);
if (ret) { if (ret) {
pr_err("%s: failed set codec dai format\n", __func__); dev_err(cpu_dai->dev,
"Failed to set the codec format.\n");
return ret; return ret;
} }
ret = snd_soc_dai_set_sysclk(codec_dai, 0, ret = snd_soc_dai_set_sysclk(codec_dai, 0,
CODEC_CLOCK, SND_SOC_CLOCK_OUT); CODEC_CLOCK, SND_SOC_CLOCK_OUT);
if (ret) { if (ret) {
pr_err("%s: failed setting codec sysclk\n", __func__); dev_err(cpu_dai->dev,
"Failed to set the codec sysclk.\n");
return ret; return ret;
} }
snd_soc_dai_set_tdm_slot(cpu_dai, 0xffffffc, 0xffffffc, 2, 0); snd_soc_dai_set_tdm_slot(cpu_dai, 0xffffffc, 0xffffffc, 2, 0);
@ -65,7 +68,8 @@ static int eukrea_tlv320_hw_params(struct snd_pcm_substream *substream,
ret = snd_soc_dai_set_sysclk(cpu_dai, IMX_SSP_SYS_CLK, 0, ret = snd_soc_dai_set_sysclk(cpu_dai, IMX_SSP_SYS_CLK, 0,
SND_SOC_CLOCK_IN); SND_SOC_CLOCK_IN);
if (ret) { if (ret) {
pr_err("can't set CPU system clock IMX_SSP_SYS_CLK\n"); dev_err(cpu_dai->dev,
"Can't set the IMX_SSP_SYS_CLK CPU system clock.\n");
return ret; return ret;
} }
@ -155,7 +159,8 @@ static struct platform_driver eukrea_tlv320_driver = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
}, },
.probe = eukrea_tlv320_probe, .probe = eukrea_tlv320_probe,
.remove = eukrea_tlv320_remove,}; .remove = eukrea_tlv320_remove,
};
module_platform_driver(eukrea_tlv320_driver); module_platform_driver(eukrea_tlv320_driver);

View File

@ -1107,9 +1107,9 @@ static int fsl_spdif_probe(struct platform_device *pdev)
/* Get the addresses and IRQ */ /* Get the addresses and IRQ */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (IS_ERR(res)) { if (!res) {
dev_err(&pdev->dev, "could not determine device resources\n"); dev_err(&pdev->dev, "could not determine device resources\n");
return PTR_ERR(res); return -ENXIO;
} }
regs = devm_ioremap_resource(&pdev->dev, res); regs = devm_ioremap_resource(&pdev->dev, res);

View File

@ -44,7 +44,8 @@ struct imx_pcm_runtime_data {
struct hrtimer hrt; struct hrtimer hrt;
int poll_time_ns; int poll_time_ns;
struct snd_pcm_substream *substream; struct snd_pcm_substream *substream;
atomic_t running; atomic_t playing;
atomic_t capturing;
}; };
static enum hrtimer_restart snd_hrtimer_callback(struct hrtimer *hrt) static enum hrtimer_restart snd_hrtimer_callback(struct hrtimer *hrt)
@ -56,7 +57,7 @@ static enum hrtimer_restart snd_hrtimer_callback(struct hrtimer *hrt)
struct pt_regs regs; struct pt_regs regs;
unsigned long delta; unsigned long delta;
if (!atomic_read(&iprtd->running)) if (!atomic_read(&iprtd->playing) && !atomic_read(&iprtd->capturing))
return HRTIMER_NORESTART; return HRTIMER_NORESTART;
get_fiq_regs(&regs); get_fiq_regs(&regs);
@ -124,7 +125,6 @@ static int snd_imx_pcm_prepare(struct snd_pcm_substream *substream)
return 0; return 0;
} }
static int fiq_enable;
static int imx_pcm_fiq; static int imx_pcm_fiq;
static int snd_imx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) static int snd_imx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
@ -136,23 +136,27 @@ static int snd_imx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
atomic_set(&iprtd->running, 1); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
atomic_set(&iprtd->playing, 1);
else
atomic_set(&iprtd->capturing, 1);
hrtimer_start(&iprtd->hrt, ns_to_ktime(iprtd->poll_time_ns), hrtimer_start(&iprtd->hrt, ns_to_ktime(iprtd->poll_time_ns),
HRTIMER_MODE_REL); HRTIMER_MODE_REL);
if (++fiq_enable == 1) enable_fiq(imx_pcm_fiq);
enable_fiq(imx_pcm_fiq);
break; break;
case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH: case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
atomic_set(&iprtd->running, 0); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
atomic_set(&iprtd->playing, 0);
if (--fiq_enable == 0) else
atomic_set(&iprtd->capturing, 0);
if (!atomic_read(&iprtd->playing) &&
!atomic_read(&iprtd->capturing))
disable_fiq(imx_pcm_fiq); disable_fiq(imx_pcm_fiq);
break; break;
default: default:
return -EINVAL; return -EINVAL;
} }
@ -200,7 +204,8 @@ static int snd_imx_open(struct snd_pcm_substream *substream)
iprtd->substream = substream; iprtd->substream = substream;
atomic_set(&iprtd->running, 0); atomic_set(&iprtd->playing, 0);
atomic_set(&iprtd->capturing, 0);
hrtimer_init(&iprtd->hrt, CLOCK_MONOTONIC, HRTIMER_MODE_REL); hrtimer_init(&iprtd->hrt, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
iprtd->hrt.function = snd_hrtimer_callback; iprtd->hrt.function = snd_hrtimer_callback;

View File

@ -568,7 +568,7 @@ static int kirkwood_i2s_dev_probe(struct platform_device *pdev)
} else { } else {
dev_info(&pdev->dev, "found external clock\n"); dev_info(&pdev->dev, "found external clock\n");
clk_prepare_enable(priv->extclk); clk_prepare_enable(priv->extclk);
soc_dai = &kirkwood_i2s_dai_extclk; soc_dai = kirkwood_i2s_dai_extclk;
} }
} }

View File

@ -1068,7 +1068,7 @@ static struct i2s_dai *i2s_alloc_dai(struct platform_device *pdev, bool sec)
dev_set_drvdata(&i2s->pdev->dev, i2s); dev_set_drvdata(&i2s->pdev->dev, i2s);
} else { /* Create a new platform_device for Secondary */ } else { /* Create a new platform_device for Secondary */
i2s->pdev = platform_device_alloc("samsung-i2s-sec", -1); i2s->pdev = platform_device_alloc("samsung-i2s-sec", -1);
if (IS_ERR(i2s->pdev)) if (!i2s->pdev)
return NULL; return NULL;
i2s->pdev->dev.parent = &pdev->dev; i2s->pdev->dev.parent = &pdev->dev;

View File

@ -94,6 +94,7 @@
* *
*/ */
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/shdma-base.h>
#include "rsnd.h" #include "rsnd.h"
#define RSND_RATES SNDRV_PCM_RATE_8000_96000 #define RSND_RATES SNDRV_PCM_RATE_8000_96000
@ -209,13 +210,6 @@ int rsnd_dma_available(struct rsnd_dma *dma)
return !!dma->chan; return !!dma->chan;
} }
static bool rsnd_dma_filter(struct dma_chan *chan, void *param)
{
chan->private = param;
return true;
}
int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma,
int is_play, int id, int is_play, int id,
int (*inquiry)(struct rsnd_dma *dma, int (*inquiry)(struct rsnd_dma *dma,
@ -223,7 +217,9 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma,
int (*complete)(struct rsnd_dma *dma)) int (*complete)(struct rsnd_dma *dma))
{ {
struct device *dev = rsnd_priv_to_dev(priv); struct device *dev = rsnd_priv_to_dev(priv);
struct dma_slave_config cfg;
dma_cap_mask_t mask; dma_cap_mask_t mask;
int ret;
if (dma->chan) { if (dma->chan) {
dev_err(dev, "it already has dma channel\n"); dev_err(dev, "it already has dma channel\n");
@ -233,15 +229,23 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma,
dma_cap_zero(mask); dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask); dma_cap_set(DMA_SLAVE, mask);
dma->slave.shdma_slave.slave_id = id; dma->chan = dma_request_slave_channel_compat(mask, shdma_chan_filter,
(void *)id, dev,
dma->chan = dma_request_channel(mask, rsnd_dma_filter, is_play ? "tx" : "rx");
&dma->slave.shdma_slave);
if (!dma->chan) { if (!dma->chan) {
dev_err(dev, "can't get dma channel\n"); dev_err(dev, "can't get dma channel\n");
return -EIO; return -EIO;
} }
cfg.slave_id = id;
cfg.dst_addr = 0; /* use default addr when playback */
cfg.src_addr = 0; /* use default addr when capture */
cfg.direction = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM;
ret = dmaengine_slave_config(dma->chan, &cfg);
if (ret < 0)
goto rsnd_dma_init_err;
dma->dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE; dma->dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
dma->priv = priv; dma->priv = priv;
dma->inquiry = inquiry; dma->inquiry = inquiry;
@ -249,6 +253,11 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma,
INIT_WORK(&dma->work, rsnd_dma_do_work); INIT_WORK(&dma->work, rsnd_dma_do_work);
return 0; return 0;
rsnd_dma_init_err:
rsnd_dma_quit(priv, dma);
return ret;
} }
void rsnd_dma_quit(struct rsnd_priv *priv, void rsnd_dma_quit(struct rsnd_priv *priv,

View File

@ -2551,8 +2551,9 @@ int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol,
if (uinfo->value.enumerated.item > e->max - 1) if (uinfo->value.enumerated.item > e->max - 1)
uinfo->value.enumerated.item = e->max - 1; uinfo->value.enumerated.item = e->max - 1;
strcpy(uinfo->value.enumerated.name, strlcpy(uinfo->value.enumerated.name,
e->texts[uinfo->value.enumerated.item]); e->texts[uinfo->value.enumerated.item],
sizeof(uinfo->value.enumerated.name));
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(snd_soc_info_enum_double); EXPORT_SYMBOL_GPL(snd_soc_info_enum_double);

View File

@ -190,7 +190,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
/* startup the audio subsystem */ /* startup the audio subsystem */
if (cpu_dai->driver->ops->startup) { if (cpu_dai->driver->ops && cpu_dai->driver->ops->startup) {
ret = cpu_dai->driver->ops->startup(substream, cpu_dai); ret = cpu_dai->driver->ops->startup(substream, cpu_dai);
if (ret < 0) { if (ret < 0) {
dev_err(cpu_dai->dev, "ASoC: can't open interface" dev_err(cpu_dai->dev, "ASoC: can't open interface"
@ -208,7 +208,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
} }
} }
if (codec_dai->driver->ops->startup) { if (codec_dai->driver->ops && codec_dai->driver->ops->startup) {
ret = codec_dai->driver->ops->startup(substream, codec_dai); ret = codec_dai->driver->ops->startup(substream, codec_dai);
if (ret < 0) { if (ret < 0) {
dev_err(codec_dai->dev, "ASoC: can't open codec" dev_err(codec_dai->dev, "ASoC: can't open codec"
@ -463,7 +463,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
} }
} }
if (codec_dai->driver->ops->prepare) { if (codec_dai->driver->ops && codec_dai->driver->ops->prepare) {
ret = codec_dai->driver->ops->prepare(substream, codec_dai); ret = codec_dai->driver->ops->prepare(substream, codec_dai);
if (ret < 0) { if (ret < 0) {
dev_err(codec_dai->dev, "ASoC: DAI prepare error: %d\n", dev_err(codec_dai->dev, "ASoC: DAI prepare error: %d\n",
@ -472,7 +472,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
} }
} }
if (cpu_dai->driver->ops->prepare) { if (cpu_dai->driver->ops && cpu_dai->driver->ops->prepare) {
ret = cpu_dai->driver->ops->prepare(substream, cpu_dai); ret = cpu_dai->driver->ops->prepare(substream, cpu_dai);
if (ret < 0) { if (ret < 0) {
dev_err(cpu_dai->dev, "ASoC: DAI prepare error: %d\n", dev_err(cpu_dai->dev, "ASoC: DAI prepare error: %d\n",
@ -523,7 +523,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
} }
} }
if (codec_dai->driver->ops->hw_params) { if (codec_dai->driver->ops && codec_dai->driver->ops->hw_params) {
ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai); ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai);
if (ret < 0) { if (ret < 0) {
dev_err(codec_dai->dev, "ASoC: can't set %s hw params:" dev_err(codec_dai->dev, "ASoC: can't set %s hw params:"
@ -532,7 +532,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
} }
} }
if (cpu_dai->driver->ops->hw_params) { if (cpu_dai->driver->ops && cpu_dai->driver->ops->hw_params) {
ret = cpu_dai->driver->ops->hw_params(substream, params, cpu_dai); ret = cpu_dai->driver->ops->hw_params(substream, params, cpu_dai);
if (ret < 0) { if (ret < 0) {
dev_err(cpu_dai->dev, "ASoC: %s hw params failed: %d\n", dev_err(cpu_dai->dev, "ASoC: %s hw params failed: %d\n",
@ -559,11 +559,11 @@ out:
return ret; return ret;
platform_err: platform_err:
if (cpu_dai->driver->ops->hw_free) if (cpu_dai->driver->ops && cpu_dai->driver->ops->hw_free)
cpu_dai->driver->ops->hw_free(substream, cpu_dai); cpu_dai->driver->ops->hw_free(substream, cpu_dai);
interface_err: interface_err:
if (codec_dai->driver->ops->hw_free) if (codec_dai->driver->ops && codec_dai->driver->ops->hw_free)
codec_dai->driver->ops->hw_free(substream, codec_dai); codec_dai->driver->ops->hw_free(substream, codec_dai);
codec_err: codec_err:
@ -600,10 +600,10 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
platform->driver->ops->hw_free(substream); platform->driver->ops->hw_free(substream);
/* now free hw params for the DAIs */ /* now free hw params for the DAIs */
if (codec_dai->driver->ops->hw_free) if (codec_dai->driver->ops && codec_dai->driver->ops->hw_free)
codec_dai->driver->ops->hw_free(substream, codec_dai); codec_dai->driver->ops->hw_free(substream, codec_dai);
if (cpu_dai->driver->ops->hw_free) if (cpu_dai->driver->ops && cpu_dai->driver->ops->hw_free)
cpu_dai->driver->ops->hw_free(substream, cpu_dai); cpu_dai->driver->ops->hw_free(substream, cpu_dai);
mutex_unlock(&rtd->pcm_mutex); mutex_unlock(&rtd->pcm_mutex);
@ -618,7 +618,7 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
struct snd_soc_dai *codec_dai = rtd->codec_dai; struct snd_soc_dai *codec_dai = rtd->codec_dai;
int ret; int ret;
if (codec_dai->driver->ops->trigger) { if (codec_dai->driver->ops && codec_dai->driver->ops->trigger) {
ret = codec_dai->driver->ops->trigger(substream, cmd, codec_dai); ret = codec_dai->driver->ops->trigger(substream, cmd, codec_dai);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -630,7 +630,7 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
return ret; return ret;
} }
if (cpu_dai->driver->ops->trigger) { if (cpu_dai->driver->ops && cpu_dai->driver->ops->trigger) {
ret = cpu_dai->driver->ops->trigger(substream, cmd, cpu_dai); ret = cpu_dai->driver->ops->trigger(substream, cmd, cpu_dai);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -647,19 +647,20 @@ static int soc_pcm_bespoke_trigger(struct snd_pcm_substream *substream,
struct snd_soc_dai *codec_dai = rtd->codec_dai; struct snd_soc_dai *codec_dai = rtd->codec_dai;
int ret; int ret;
if (codec_dai->driver->ops->bespoke_trigger) { if (codec_dai->driver->ops &&
codec_dai->driver->ops->bespoke_trigger) {
ret = codec_dai->driver->ops->bespoke_trigger(substream, cmd, codec_dai); ret = codec_dai->driver->ops->bespoke_trigger(substream, cmd, codec_dai);
if (ret < 0) if (ret < 0)
return ret; return ret;
} }
if (platform->driver->bespoke_trigger) { if (platform->driver->ops && platform->driver->bespoke_trigger) {
ret = platform->driver->bespoke_trigger(substream, cmd); ret = platform->driver->bespoke_trigger(substream, cmd);
if (ret < 0) if (ret < 0)
return ret; return ret;
} }
if (cpu_dai->driver->ops->bespoke_trigger) { if (cpu_dai->driver->ops && cpu_dai->driver->ops->bespoke_trigger) {
ret = cpu_dai->driver->ops->bespoke_trigger(substream, cmd, cpu_dai); ret = cpu_dai->driver->ops->bespoke_trigger(substream, cmd, cpu_dai);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -684,10 +685,10 @@ static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream)
if (platform->driver->ops && platform->driver->ops->pointer) if (platform->driver->ops && platform->driver->ops->pointer)
offset = platform->driver->ops->pointer(substream); offset = platform->driver->ops->pointer(substream);
if (cpu_dai->driver->ops->delay) if (cpu_dai->driver->ops && cpu_dai->driver->ops->delay)
delay += cpu_dai->driver->ops->delay(substream, cpu_dai); delay += cpu_dai->driver->ops->delay(substream, cpu_dai);
if (codec_dai->driver->ops->delay) if (codec_dai->driver->ops && codec_dai->driver->ops->delay)
delay += codec_dai->driver->ops->delay(substream, codec_dai); delay += codec_dai->driver->ops->delay(substream, codec_dai);
if (platform->driver->delay) if (platform->driver->delay)
@ -1037,6 +1038,12 @@ static int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream)
struct snd_pcm_substream *be_substream = struct snd_pcm_substream *be_substream =
snd_soc_dpcm_get_substream(be, stream); snd_soc_dpcm_get_substream(be, stream);
if (!be_substream) {
dev_err(be->dev, "ASoC: no backend %s stream\n",
stream ? "capture" : "playback");
continue;
}
/* is this op for this BE ? */ /* is this op for this BE ? */
if (!snd_soc_dpcm_be_can_update(fe, be, stream)) if (!snd_soc_dpcm_be_can_update(fe, be, stream))
continue; continue;
@ -1054,7 +1061,8 @@ static int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream)
(be->dpcm[stream].state != SND_SOC_DPCM_STATE_CLOSE)) (be->dpcm[stream].state != SND_SOC_DPCM_STATE_CLOSE))
continue; continue;
dev_dbg(be->dev, "ASoC: open BE %s\n", be->dai_link->name); dev_dbg(be->dev, "ASoC: open %s BE %s\n",
stream ? "capture" : "playback", be->dai_link->name);
be_substream->runtime = be->dpcm[stream].runtime; be_substream->runtime = be->dpcm[stream].runtime;
err = soc_pcm_open(be_substream); err = soc_pcm_open(be_substream);
@ -1673,7 +1681,7 @@ static int soc_pcm_ioctl(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_platform *platform = rtd->platform; struct snd_soc_platform *platform = rtd->platform;
if (platform->driver->ops->ioctl) if (platform->driver->ops && platform->driver->ops->ioctl)
return platform->driver->ops->ioctl(substream, cmd, arg); return platform->driver->ops->ioctl(substream, cmd, arg);
return snd_pcm_lib_ioctl(substream, cmd, arg); return snd_pcm_lib_ioctl(substream, cmd, arg);
} }
@ -1934,8 +1942,8 @@ int soc_dpcm_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute)
dev_dbg(be->dev, "ASoC: BE digital mute %s\n", be->dai_link->name); dev_dbg(be->dev, "ASoC: BE digital mute %s\n", be->dai_link->name);
if (drv->ops->digital_mute && dai->playback_active) if (drv->ops && drv->ops->digital_mute && dai->playback_active)
drv->ops->digital_mute(dai, mute); drv->ops->digital_mute(dai, mute);
} }
return 0; return 0;
@ -2224,7 +2232,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dpcm_can_be_params);
int snd_soc_platform_trigger(struct snd_pcm_substream *substream, int snd_soc_platform_trigger(struct snd_pcm_substream *substream,
int cmd, struct snd_soc_platform *platform) int cmd, struct snd_soc_platform *platform)
{ {
if (platform->driver->ops->trigger) if (platform->driver->ops && platform->driver->ops->trigger)
return platform->driver->ops->trigger(substream, cmd); return platform->driver->ops->trigger(substream, cmd);
return 0; return 0;
} }