forked from Minki/linux
sound fixes for 4.9-rc5
this became a largish pull-request, as we've got a bunch of pending ASoC fixes at this time. One noticeable change is the removal of error directive in uapi/sound/asoc.h. We found that the API has been already used on Chromebooks, so we need to support it even now. A slight big LOC is found in Qualcomm lpass driver, but the rest are all small and easy fixes for ASoC drivers (sti, sun4i, Realtek codecs, Intel, tas571x, etc) in addition to the patches to harden the ALSA core proc file accesses. -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAABAgAGBQJYI3I4AAoJEGwxgFQ9KSmkgEMP/iGW/7T2AqD39pKtmfXH60gt hU9ccBt+gSrKqyMZHjrqp69o2//9JSsx6ezJXAWm5OeDwPJCxwSBIy2fGzxBZDwW 0nhYbeoZFQbQucCTDLRO33n0xe7YIMtjp9H55PBBoaWKDdDoRiOdsKIRSFWToV2Q IOPY3pvYUP8RzYA2GC9Ud5xDb0U/J3je7PGhwM880sBlOxykTJJwrq95tG8EGIF8 CAj/B/IJw0SuA79RDjBSziT9xAfHjiky4wYTw7HcjgBStLv3R2txM3775Cvhsnwr ISdXmh2ImibCh5ADIivXoNTkptq0mTurWi/6W1fENqZVxaAh7/MsWjlVKfAmgUKT kTRgLJLZIQ/P0ejKnbRI2+K4z0iLcF4w4GURi3iwEOKuvX1jDN/F9pte/ZCB3BIw IKxRZ2ClWAdlpPt/reNNH3fKICguLlktoZWUkZm1rVZ2ACieQVMmodYjIMP0egXr EHus0Pp+B9U3prvncGKSIG9+/8XFBdYh++811cVkT78W2nBmy9VjvbA2iBTo1Yzj mWzpU/Zp+wC44TyMHP+AtZj+XsAM0l0gQRMUKoMe1RTdOmBleGsiGaN/V9kTuX0S bHbPV1CKnfw/4mQDc9BGuVC6xz/kS3xgqqUscdIf0flN7/kYJbzOJlz2fM/svP7z w0yH9d7pvEGKJTqLlyOm =jmAA -----END PGP SIGNATURE----- Merge tag 'sound-4.9-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound Pull sound fixes from Takashi Iwai: "This became a largish pull-request, as we've got a bunch of pending ASoC fixes at this time. One noticeable change is the removal of error directive in uapi/sound/asoc.h. We found that the API has been already used on Chromebooks, so we need to support it even now. A slight big LOC is found in Qualcomm lpass driver, but the rest are all small and easy fixes for ASoC drivers (sti, sun4i, Realtek codecs, Intel, tas571x, etc) in addition to the patches to harden the ALSA core proc file accesses" * tag 'sound-4.9-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (26 commits) ALSA: info: Return error for invalid read/write ALSA: info: Limit the proc text input size ASoC: samsung: spdif: Fix DMA filter initialization ASoC: sun4i-codec: Enable bus clock after getting GPIO ASoC: lpass-cpu: add module licence and description ASoC: lpass-platform: Fix broken pcm data usage ASoC: sun4i-codec: return error code instead of NULL when create_card fails ASoC: hdmi-codec: Fix hdmi_of_xlate_dai_name when #sound-dai-cells = <0> ASoC: samsung: get access to DMA engine early to defer probe properly ASoC: da7219: Connect output enable register to DAIOUT ASoC: Intel: Skylake: Fix to turn off hdmi power on probe failure ASoC: sti-sas: enable fast io for regmap ASoC: sti: fix channel status update after playback start ASoC: PXA: Brownstone needs I2C ASoC: Intel: Skylake: Always acquire runtime pm ref on unload ASoC: Intel: Atom: add terminate entry for dmi_system_id tables ASoC: rt298: fix jack type detect error ASoC: rt5663: fix a debug statement ASoC: cs4270: fix DAPM stream name mismatch ASoC: Intel: haswell depends on sst-firmware ...
This commit is contained in:
commit
27bcd37e02
@ -18,12 +18,6 @@
|
||||
#include <linux/types.h>
|
||||
#include <sound/asound.h>
|
||||
|
||||
#ifndef __KERNEL__
|
||||
#error This API is an early revision and not enabled in the current
|
||||
#error kernel release, it will be enabled in a future kernel version
|
||||
#error with incompatible changes to what is here.
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Maximum number of channels topology kcontrol can represent.
|
||||
*/
|
||||
|
@ -325,10 +325,15 @@ static ssize_t snd_info_text_entry_write(struct file *file,
|
||||
size_t next;
|
||||
int err = 0;
|
||||
|
||||
if (!entry->c.text.write)
|
||||
return -EIO;
|
||||
pos = *offset;
|
||||
if (!valid_pos(pos, count))
|
||||
return -EIO;
|
||||
next = pos + count;
|
||||
/* don't handle too large text inputs */
|
||||
if (next > 16 * 1024)
|
||||
return -EIO;
|
||||
mutex_lock(&entry->access);
|
||||
buf = data->wbuffer;
|
||||
if (!buf) {
|
||||
@ -366,7 +371,9 @@ static int snd_info_seq_show(struct seq_file *seq, void *p)
|
||||
struct snd_info_private_data *data = seq->private;
|
||||
struct snd_info_entry *entry = data->entry;
|
||||
|
||||
if (entry->c.text.read) {
|
||||
if (!entry->c.text.read) {
|
||||
return -EIO;
|
||||
} else {
|
||||
data->rbuffer->buffer = (char *)seq; /* XXX hack! */
|
||||
entry->c.text.read(entry, data->rbuffer);
|
||||
}
|
||||
|
@ -148,11 +148,11 @@ SND_SOC_DAPM_OUTPUT("AOUTR"),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route cs4270_dapm_routes[] = {
|
||||
{ "Capture", NULL, "AINA" },
|
||||
{ "Capture", NULL, "AINB" },
|
||||
{ "Capture", NULL, "AINL" },
|
||||
{ "Capture", NULL, "AINR" },
|
||||
|
||||
{ "AOUTA", NULL, "Playback" },
|
||||
{ "AOUTB", NULL, "Playback" },
|
||||
{ "AOUTL", NULL, "Playback" },
|
||||
{ "AOUTR", NULL, "Playback" },
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -880,7 +880,8 @@ static const struct snd_soc_dapm_widget da7219_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
|
||||
|
||||
/* DAI */
|
||||
SND_SOC_DAPM_AIF_OUT("DAIOUT", "Capture", 0, SND_SOC_NOPM, 0, 0),
|
||||
SND_SOC_DAPM_AIF_OUT("DAIOUT", "Capture", 0, DA7219_DAI_TDM_CTRL,
|
||||
DA7219_DAI_OE_SHIFT, DA7219_NO_INVERT),
|
||||
SND_SOC_DAPM_AIF_IN("DAIIN", "Playback", 0, SND_SOC_NOPM, 0, 0),
|
||||
|
||||
/* Output Muxes */
|
||||
|
@ -364,7 +364,12 @@ static int hdmi_of_xlate_dai_name(struct snd_soc_component *component,
|
||||
struct of_phandle_args *args,
|
||||
const char **dai_name)
|
||||
{
|
||||
int id = args->args[0];
|
||||
int id;
|
||||
|
||||
if (args->args_count)
|
||||
id = args->args[0];
|
||||
else
|
||||
id = 0;
|
||||
|
||||
if (id < ARRAY_SIZE(hdmi_dai_name)) {
|
||||
*dai_name = hdmi_dai_name[id];
|
||||
|
@ -249,6 +249,11 @@ static int rt298_jack_detect(struct rt298_priv *rt298, bool *hp, bool *mic)
|
||||
snd_soc_dapm_force_enable_pin(dapm, "LDO1");
|
||||
snd_soc_dapm_sync(dapm);
|
||||
|
||||
regmap_update_bits(rt298->regmap,
|
||||
RT298_POWER_CTRL1, 0x1001, 0);
|
||||
regmap_update_bits(rt298->regmap,
|
||||
RT298_POWER_CTRL2, 0x4, 0x4);
|
||||
|
||||
regmap_write(rt298->regmap, RT298_SET_MIC1, 0x24);
|
||||
msleep(50);
|
||||
|
||||
|
@ -1547,11 +1547,11 @@ static int rt5663_jack_detect(struct snd_soc_codec *codec, int jack_insert)
|
||||
msleep(sleep_time[i]);
|
||||
val = snd_soc_read(codec, RT5663_EM_JACK_TYPE_2) &
|
||||
0x0003;
|
||||
dev_dbg(codec->dev, "%s: MX-00e7 val=%x sleep %d\n",
|
||||
__func__, val, sleep_time[i]);
|
||||
i++;
|
||||
if (val == 0x1 || val == 0x2 || val == 0x3)
|
||||
break;
|
||||
dev_dbg(codec->dev, "%s: MX-00e7 val=%x sleep %d\n",
|
||||
__func__, val, sleep_time[i]);
|
||||
}
|
||||
dev_dbg(codec->dev, "%s val = %d\n", __func__, val);
|
||||
switch (val) {
|
||||
|
@ -424,7 +424,7 @@ static const struct snd_soc_dai_ops stih407_dac_ops = {
|
||||
static const struct regmap_config stih407_sas_regmap = {
|
||||
.reg_bits = 32,
|
||||
.val_bits = 32,
|
||||
|
||||
.fast_io = true,
|
||||
.max_register = STIH407_AUDIO_DAC_CTRL,
|
||||
.reg_defaults = stih407_sas_reg_defaults,
|
||||
.num_reg_defaults = ARRAY_SIZE(stih407_sas_reg_defaults),
|
||||
|
@ -341,20 +341,9 @@ static int tas571x_set_bias_level(struct snd_soc_codec *codec,
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
gpiod_set_value(priv->pdn_gpio, 0);
|
||||
usleep_range(5000, 6000);
|
||||
|
||||
regcache_cache_only(priv->regmap, false);
|
||||
ret = regcache_sync(priv->regmap);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
case SND_SOC_BIAS_OFF:
|
||||
regcache_cache_only(priv->regmap, true);
|
||||
gpiod_set_value(priv->pdn_gpio, 1);
|
||||
|
||||
if (!IS_ERR(priv->mclk))
|
||||
clk_disable_unprepare(priv->mclk);
|
||||
break;
|
||||
@ -401,16 +390,6 @@ static const struct snd_kcontrol_new tas5711_controls[] = {
|
||||
TAS571X_SOFT_MUTE_REG,
|
||||
TAS571X_SOFT_MUTE_CH1_SHIFT, TAS571X_SOFT_MUTE_CH2_SHIFT,
|
||||
1, 1),
|
||||
|
||||
SOC_DOUBLE_R_RANGE("CH1 Mixer Volume",
|
||||
TAS5717_CH1_LEFT_CH_MIX_REG,
|
||||
TAS5717_CH1_RIGHT_CH_MIX_REG,
|
||||
16, 0, 0x80, 0),
|
||||
|
||||
SOC_DOUBLE_R_RANGE("CH2 Mixer Volume",
|
||||
TAS5717_CH2_LEFT_CH_MIX_REG,
|
||||
TAS5717_CH2_RIGHT_CH_MIX_REG,
|
||||
16, 0, 0x80, 0),
|
||||
};
|
||||
|
||||
static const struct regmap_range tas571x_readonly_regs_range[] = {
|
||||
@ -488,6 +467,16 @@ static const struct snd_kcontrol_new tas5717_controls[] = {
|
||||
TAS571X_SOFT_MUTE_CH1_SHIFT, TAS571X_SOFT_MUTE_CH2_SHIFT,
|
||||
1, 1),
|
||||
|
||||
SOC_DOUBLE_R_RANGE("CH1 Mixer Volume",
|
||||
TAS5717_CH1_LEFT_CH_MIX_REG,
|
||||
TAS5717_CH1_RIGHT_CH_MIX_REG,
|
||||
16, 0, 0x80, 0),
|
||||
|
||||
SOC_DOUBLE_R_RANGE("CH2 Mixer Volume",
|
||||
TAS5717_CH2_LEFT_CH_MIX_REG,
|
||||
TAS5717_CH2_RIGHT_CH_MIX_REG,
|
||||
16, 0, 0x80, 0),
|
||||
|
||||
/*
|
||||
* The biquads are named according to the register names.
|
||||
* Please note that TI's TAS57xx Graphical Development Environment
|
||||
@ -747,13 +736,14 @@ static int tas571x_i2c_probe(struct i2c_client *client,
|
||||
/* pulse the active low reset line for ~100us */
|
||||
usleep_range(100, 200);
|
||||
gpiod_set_value(priv->reset_gpio, 0);
|
||||
usleep_range(12000, 20000);
|
||||
usleep_range(13500, 20000);
|
||||
}
|
||||
|
||||
ret = regmap_write(priv->regmap, TAS571X_OSC_TRIM_REG, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
usleep_range(50000, 60000);
|
||||
|
||||
memcpy(&priv->codec_driver, &tas571x_codec, sizeof(priv->codec_driver));
|
||||
priv->codec_driver.component_driver.controls = priv->chip->controls;
|
||||
@ -770,9 +760,6 @@ static int tas571x_i2c_probe(struct i2c_client *client,
|
||||
return ret;
|
||||
}
|
||||
|
||||
regcache_cache_only(priv->regmap, true);
|
||||
gpiod_set_value(priv->pdn_gpio, 1);
|
||||
|
||||
return snd_soc_register_codec(&client->dev, &priv->codec_driver,
|
||||
&tas571x_dai, 1);
|
||||
}
|
||||
|
@ -47,6 +47,7 @@ config SND_SOC_INTEL_SST_MATCH
|
||||
|
||||
config SND_SOC_INTEL_HASWELL
|
||||
tristate
|
||||
select SND_SOC_INTEL_SST_FIRMWARE
|
||||
|
||||
config SND_SOC_INTEL_BAYTRAIL
|
||||
tristate
|
||||
@ -56,7 +57,6 @@ config SND_SOC_INTEL_HASWELL_MACH
|
||||
depends on X86_INTEL_LPSS && I2C && I2C_DESIGNWARE_PLATFORM
|
||||
depends on DW_DMAC_CORE
|
||||
select SND_SOC_INTEL_SST
|
||||
select SND_SOC_INTEL_SST_FIRMWARE
|
||||
select SND_SOC_INTEL_HASWELL
|
||||
select SND_SOC_RT5640
|
||||
help
|
||||
@ -138,7 +138,6 @@ config SND_SOC_INTEL_BROADWELL_MACH
|
||||
I2C_DESIGNWARE_PLATFORM
|
||||
depends on DW_DMAC_CORE
|
||||
select SND_SOC_INTEL_SST
|
||||
select SND_SOC_INTEL_SST_FIRMWARE
|
||||
select SND_SOC_INTEL_HASWELL
|
||||
select SND_SOC_RT286
|
||||
help
|
||||
|
@ -416,6 +416,7 @@ static const struct dmi_system_id cht_table[] = {
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Surface 3"),
|
||||
},
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
|
@ -130,8 +130,8 @@ static int broxton_da7219_codec_init(struct snd_soc_pcm_runtime *rtd)
|
||||
*/
|
||||
ret = snd_soc_card_jack_new(rtd->card, "Headset Jack",
|
||||
SND_JACK_HEADSET | SND_JACK_BTN_0 | SND_JACK_BTN_1 |
|
||||
SND_JACK_BTN_2 | SND_JACK_BTN_3, &broxton_headset,
|
||||
NULL, 0);
|
||||
SND_JACK_BTN_2 | SND_JACK_BTN_3 | SND_JACK_LINEOUT,
|
||||
&broxton_headset, NULL, 0);
|
||||
if (ret) {
|
||||
dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret);
|
||||
return ret;
|
||||
|
@ -674,7 +674,7 @@ static int skl_probe(struct pci_dev *pci,
|
||||
|
||||
if (skl->nhlt == NULL) {
|
||||
err = -ENODEV;
|
||||
goto out_free;
|
||||
goto out_display_power_off;
|
||||
}
|
||||
|
||||
skl_nhlt_update_topology_bin(skl);
|
||||
@ -746,6 +746,9 @@ out_mach_free:
|
||||
skl_machine_device_unregister(skl);
|
||||
out_nhlt_free:
|
||||
skl_nhlt_free(skl->nhlt);
|
||||
out_display_power_off:
|
||||
if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI))
|
||||
snd_hdac_display_power(bus, false);
|
||||
out_free:
|
||||
skl->init_failed = 1;
|
||||
skl_free(ebus);
|
||||
@ -785,8 +788,7 @@ static void skl_remove(struct pci_dev *pci)
|
||||
|
||||
release_firmware(skl->tplg);
|
||||
|
||||
if (pci_dev_run_wake(pci))
|
||||
pm_runtime_get_noresume(&pci->dev);
|
||||
pm_runtime_get_noresume(&pci->dev);
|
||||
|
||||
/* codec removal, invoke bus_device_remove */
|
||||
snd_hdac_ext_bus_device_remove(ebus);
|
||||
|
@ -208,7 +208,7 @@ config SND_PXA2XX_SOC_IMOTE2
|
||||
|
||||
config SND_MMP_SOC_BROWNSTONE
|
||||
tristate "SoC Audio support for Marvell Brownstone"
|
||||
depends on SND_MMP_SOC && MACH_BROWNSTONE
|
||||
depends on SND_MMP_SOC && MACH_BROWNSTONE && I2C
|
||||
select SND_MMP_SOC_SSPA
|
||||
select MFD_WM8994
|
||||
select SND_SOC_WM8994
|
||||
|
@ -586,3 +586,6 @@ int asoc_qcom_lpass_cpu_platform_remove(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(asoc_qcom_lpass_cpu_platform_remove);
|
||||
|
||||
MODULE_DESCRIPTION("QTi LPASS CPU Driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
@ -61,7 +61,40 @@ static int lpass_platform_pcmops_open(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
|
||||
int ret;
|
||||
struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai;
|
||||
struct lpass_data *drvdata =
|
||||
snd_soc_platform_get_drvdata(soc_runtime->platform);
|
||||
struct lpass_variant *v = drvdata->variant;
|
||||
int ret, dma_ch, dir = substream->stream;
|
||||
struct lpass_pcm_data *data;
|
||||
|
||||
data = devm_kzalloc(soc_runtime->dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
data->i2s_port = cpu_dai->driver->id;
|
||||
runtime->private_data = data;
|
||||
|
||||
if (v->alloc_dma_channel)
|
||||
dma_ch = v->alloc_dma_channel(drvdata, dir);
|
||||
if (dma_ch < 0)
|
||||
return dma_ch;
|
||||
|
||||
drvdata->substream[dma_ch] = substream;
|
||||
|
||||
ret = regmap_write(drvdata->lpaif_map,
|
||||
LPAIF_DMACTL_REG(v, dma_ch, dir), 0);
|
||||
if (ret) {
|
||||
dev_err(soc_runtime->dev,
|
||||
"%s() error writing to rdmactl reg: %d\n",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (dir == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
data->rdma_ch = dma_ch;
|
||||
else
|
||||
data->wrdma_ch = dma_ch;
|
||||
|
||||
snd_soc_set_runtime_hwparams(substream, &lpass_platform_pcm_hardware);
|
||||
|
||||
@ -80,13 +113,40 @@ static int lpass_platform_pcmops_open(struct snd_pcm_substream *substream)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lpass_platform_pcmops_close(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
|
||||
struct lpass_data *drvdata =
|
||||
snd_soc_platform_get_drvdata(soc_runtime->platform);
|
||||
struct lpass_variant *v = drvdata->variant;
|
||||
struct lpass_pcm_data *data;
|
||||
int dma_ch, dir = substream->stream;
|
||||
|
||||
data = runtime->private_data;
|
||||
v = drvdata->variant;
|
||||
|
||||
if (dir == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
dma_ch = data->rdma_ch;
|
||||
else
|
||||
dma_ch = data->wrdma_ch;
|
||||
|
||||
drvdata->substream[dma_ch] = NULL;
|
||||
|
||||
if (v->free_dma_channel)
|
||||
v->free_dma_channel(drvdata, dma_ch);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lpass_platform_pcmops_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
|
||||
struct lpass_data *drvdata =
|
||||
snd_soc_platform_get_drvdata(soc_runtime->platform);
|
||||
struct lpass_pcm_data *pcm_data = drvdata->private_data;
|
||||
struct snd_pcm_runtime *rt = substream->runtime;
|
||||
struct lpass_pcm_data *pcm_data = rt->private_data;
|
||||
struct lpass_variant *v = drvdata->variant;
|
||||
snd_pcm_format_t format = params_format(params);
|
||||
unsigned int channels = params_channels(params);
|
||||
@ -179,7 +239,8 @@ static int lpass_platform_pcmops_hw_free(struct snd_pcm_substream *substream)
|
||||
struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
|
||||
struct lpass_data *drvdata =
|
||||
snd_soc_platform_get_drvdata(soc_runtime->platform);
|
||||
struct lpass_pcm_data *pcm_data = drvdata->private_data;
|
||||
struct snd_pcm_runtime *rt = substream->runtime;
|
||||
struct lpass_pcm_data *pcm_data = rt->private_data;
|
||||
struct lpass_variant *v = drvdata->variant;
|
||||
unsigned int reg;
|
||||
int ret;
|
||||
@ -203,7 +264,8 @@ static int lpass_platform_pcmops_prepare(struct snd_pcm_substream *substream)
|
||||
struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
|
||||
struct lpass_data *drvdata =
|
||||
snd_soc_platform_get_drvdata(soc_runtime->platform);
|
||||
struct lpass_pcm_data *pcm_data = drvdata->private_data;
|
||||
struct snd_pcm_runtime *rt = substream->runtime;
|
||||
struct lpass_pcm_data *pcm_data = rt->private_data;
|
||||
struct lpass_variant *v = drvdata->variant;
|
||||
int ret, ch, dir = substream->stream;
|
||||
|
||||
@ -257,7 +319,8 @@ static int lpass_platform_pcmops_trigger(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
|
||||
struct lpass_data *drvdata =
|
||||
snd_soc_platform_get_drvdata(soc_runtime->platform);
|
||||
struct lpass_pcm_data *pcm_data = drvdata->private_data;
|
||||
struct snd_pcm_runtime *rt = substream->runtime;
|
||||
struct lpass_pcm_data *pcm_data = rt->private_data;
|
||||
struct lpass_variant *v = drvdata->variant;
|
||||
int ret, ch, dir = substream->stream;
|
||||
|
||||
@ -333,7 +396,8 @@ static snd_pcm_uframes_t lpass_platform_pcmops_pointer(
|
||||
struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
|
||||
struct lpass_data *drvdata =
|
||||
snd_soc_platform_get_drvdata(soc_runtime->platform);
|
||||
struct lpass_pcm_data *pcm_data = drvdata->private_data;
|
||||
struct snd_pcm_runtime *rt = substream->runtime;
|
||||
struct lpass_pcm_data *pcm_data = rt->private_data;
|
||||
struct lpass_variant *v = drvdata->variant;
|
||||
unsigned int base_addr, curr_addr;
|
||||
int ret, ch, dir = substream->stream;
|
||||
@ -374,6 +438,7 @@ static int lpass_platform_pcmops_mmap(struct snd_pcm_substream *substream,
|
||||
|
||||
static const struct snd_pcm_ops lpass_platform_pcm_ops = {
|
||||
.open = lpass_platform_pcmops_open,
|
||||
.close = lpass_platform_pcmops_close,
|
||||
.ioctl = snd_pcm_lib_ioctl,
|
||||
.hw_params = lpass_platform_pcmops_hw_params,
|
||||
.hw_free = lpass_platform_pcmops_hw_free,
|
||||
@ -470,117 +535,45 @@ static int lpass_platform_pcm_new(struct snd_soc_pcm_runtime *soc_runtime)
|
||||
{
|
||||
struct snd_pcm *pcm = soc_runtime->pcm;
|
||||
struct snd_pcm_substream *psubstream, *csubstream;
|
||||
struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai;
|
||||
struct lpass_data *drvdata =
|
||||
snd_soc_platform_get_drvdata(soc_runtime->platform);
|
||||
struct lpass_variant *v = drvdata->variant;
|
||||
int ret = -EINVAL;
|
||||
struct lpass_pcm_data *data;
|
||||
size_t size = lpass_platform_pcm_hardware.buffer_bytes_max;
|
||||
|
||||
data = devm_kzalloc(soc_runtime->dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
data->i2s_port = cpu_dai->driver->id;
|
||||
drvdata->private_data = data;
|
||||
|
||||
psubstream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
|
||||
if (psubstream) {
|
||||
if (v->alloc_dma_channel)
|
||||
data->rdma_ch = v->alloc_dma_channel(drvdata,
|
||||
SNDRV_PCM_STREAM_PLAYBACK);
|
||||
|
||||
if (data->rdma_ch < 0)
|
||||
return data->rdma_ch;
|
||||
|
||||
drvdata->substream[data->rdma_ch] = psubstream;
|
||||
|
||||
ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
|
||||
soc_runtime->platform->dev,
|
||||
size, &psubstream->dma_buffer);
|
||||
if (ret)
|
||||
goto playback_alloc_err;
|
||||
|
||||
ret = regmap_write(drvdata->lpaif_map,
|
||||
LPAIF_RDMACTL_REG(v, data->rdma_ch), 0);
|
||||
if (ret) {
|
||||
dev_err(soc_runtime->dev,
|
||||
"%s() error writing to rdmactl reg: %d\n",
|
||||
__func__, ret);
|
||||
goto capture_alloc_err;
|
||||
dev_err(soc_runtime->dev, "Cannot allocate buffer(s)\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
csubstream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
|
||||
if (csubstream) {
|
||||
if (v->alloc_dma_channel)
|
||||
data->wrdma_ch = v->alloc_dma_channel(drvdata,
|
||||
SNDRV_PCM_STREAM_CAPTURE);
|
||||
|
||||
if (data->wrdma_ch < 0) {
|
||||
ret = data->wrdma_ch;
|
||||
goto capture_alloc_err;
|
||||
}
|
||||
|
||||
drvdata->substream[data->wrdma_ch] = csubstream;
|
||||
|
||||
ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
|
||||
soc_runtime->platform->dev,
|
||||
size, &csubstream->dma_buffer);
|
||||
if (ret)
|
||||
goto capture_alloc_err;
|
||||
|
||||
ret = regmap_write(drvdata->lpaif_map,
|
||||
LPAIF_WRDMACTL_REG(v, data->wrdma_ch), 0);
|
||||
if (ret) {
|
||||
dev_err(soc_runtime->dev,
|
||||
"%s() error writing to wrdmactl reg: %d\n",
|
||||
__func__, ret);
|
||||
goto capture_reg_err;
|
||||
dev_err(soc_runtime->dev, "Cannot allocate buffer(s)\n");
|
||||
if (psubstream)
|
||||
snd_dma_free_pages(&psubstream->dma_buffer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
capture_reg_err:
|
||||
if (csubstream)
|
||||
snd_dma_free_pages(&csubstream->dma_buffer);
|
||||
|
||||
capture_alloc_err:
|
||||
if (psubstream)
|
||||
snd_dma_free_pages(&psubstream->dma_buffer);
|
||||
|
||||
playback_alloc_err:
|
||||
dev_err(soc_runtime->dev, "Cannot allocate buffer(s)\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void lpass_platform_pcm_free(struct snd_pcm *pcm)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rt;
|
||||
struct lpass_data *drvdata;
|
||||
struct lpass_pcm_data *data;
|
||||
struct lpass_variant *v;
|
||||
struct snd_pcm_substream *substream;
|
||||
int ch, i;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(pcm->streams); i++) {
|
||||
substream = pcm->streams[i].substream;
|
||||
if (substream) {
|
||||
rt = substream->private_data;
|
||||
drvdata = snd_soc_platform_get_drvdata(rt->platform);
|
||||
data = drvdata->private_data;
|
||||
|
||||
ch = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
? data->rdma_ch
|
||||
: data->wrdma_ch;
|
||||
v = drvdata->variant;
|
||||
drvdata->substream[ch] = NULL;
|
||||
if (v->free_dma_channel)
|
||||
v->free_dma_channel(drvdata, ch);
|
||||
|
||||
snd_dma_free_pages(&substream->dma_buffer);
|
||||
substream->dma_buffer.area = NULL;
|
||||
substream->dma_buffer.addr = 0;
|
||||
|
@ -59,7 +59,6 @@ struct lpass_data {
|
||||
struct clk *pcnoc_mport_clk;
|
||||
struct clk *pcnoc_sway_clk;
|
||||
|
||||
void *private_data;
|
||||
};
|
||||
|
||||
/* Vairant data per each SOC */
|
||||
|
@ -383,11 +383,6 @@ static int s3c_ac97_probe(struct platform_device *pdev)
|
||||
goto err4;
|
||||
}
|
||||
|
||||
ret = devm_snd_soc_register_component(&pdev->dev, &s3c_ac97_component,
|
||||
s3c_ac97_dai, ARRAY_SIZE(s3c_ac97_dai));
|
||||
if (ret)
|
||||
goto err5;
|
||||
|
||||
ret = samsung_asoc_dma_platform_register(&pdev->dev,
|
||||
ac97_pdata->dma_filter,
|
||||
NULL, NULL);
|
||||
@ -396,6 +391,11 @@ static int s3c_ac97_probe(struct platform_device *pdev)
|
||||
goto err5;
|
||||
}
|
||||
|
||||
ret = devm_snd_soc_register_component(&pdev->dev, &s3c_ac97_component,
|
||||
s3c_ac97_dai, ARRAY_SIZE(s3c_ac97_dai));
|
||||
if (ret)
|
||||
goto err5;
|
||||
|
||||
return 0;
|
||||
err5:
|
||||
free_irq(irq_res->start, NULL);
|
||||
|
@ -1237,14 +1237,14 @@ static int samsung_i2s_probe(struct platform_device *pdev)
|
||||
dev_err(&pdev->dev, "Unable to get drvdata\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
ret = devm_snd_soc_register_component(&sec_dai->pdev->dev,
|
||||
&samsung_i2s_component,
|
||||
&sec_dai->i2s_dai_drv, 1);
|
||||
ret = samsung_asoc_dma_platform_register(&pdev->dev,
|
||||
sec_dai->filter, "tx-sec", NULL);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
return samsung_asoc_dma_platform_register(&pdev->dev,
|
||||
sec_dai->filter, "tx-sec", NULL);
|
||||
return devm_snd_soc_register_component(&sec_dai->pdev->dev,
|
||||
&samsung_i2s_component,
|
||||
&sec_dai->i2s_dai_drv, 1);
|
||||
}
|
||||
|
||||
pri_dai = i2s_alloc_dai(pdev, false);
|
||||
@ -1314,6 +1314,11 @@ static int samsung_i2s_probe(struct platform_device *pdev)
|
||||
if (quirks & QUIRK_PRI_6CHAN)
|
||||
pri_dai->i2s_dai_drv.playback.channels_max = 6;
|
||||
|
||||
ret = samsung_asoc_dma_platform_register(&pdev->dev, pri_dai->filter,
|
||||
NULL, NULL);
|
||||
if (ret < 0)
|
||||
goto err_disable_clk;
|
||||
|
||||
if (quirks & QUIRK_SEC_DAI) {
|
||||
sec_dai = i2s_alloc_dai(pdev, true);
|
||||
if (!sec_dai) {
|
||||
@ -1353,10 +1358,6 @@ static int samsung_i2s_probe(struct platform_device *pdev)
|
||||
if (ret < 0)
|
||||
goto err_free_dai;
|
||||
|
||||
ret = samsung_asoc_dma_platform_register(&pdev->dev, pri_dai->filter,
|
||||
NULL, NULL);
|
||||
if (ret < 0)
|
||||
goto err_free_dai;
|
||||
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
|
||||
|
@ -565,15 +565,6 @@ static int s3c_pcm_dev_probe(struct platform_device *pdev)
|
||||
pcm->dma_capture = &s3c_pcm_stereo_in[pdev->id];
|
||||
pcm->dma_playback = &s3c_pcm_stereo_out[pdev->id];
|
||||
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
|
||||
ret = devm_snd_soc_register_component(&pdev->dev, &s3c_pcm_component,
|
||||
&s3c_pcm_dai[pdev->id], 1);
|
||||
if (ret != 0) {
|
||||
dev_err(&pdev->dev, "failed to get register DAI: %d\n", ret);
|
||||
goto err5;
|
||||
}
|
||||
|
||||
ret = samsung_asoc_dma_platform_register(&pdev->dev, filter,
|
||||
NULL, NULL);
|
||||
if (ret) {
|
||||
@ -581,8 +572,18 @@ static int s3c_pcm_dev_probe(struct platform_device *pdev)
|
||||
goto err5;
|
||||
}
|
||||
|
||||
return 0;
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
|
||||
ret = devm_snd_soc_register_component(&pdev->dev, &s3c_pcm_component,
|
||||
&s3c_pcm_dai[pdev->id], 1);
|
||||
if (ret != 0) {
|
||||
dev_err(&pdev->dev, "failed to get register DAI: %d\n", ret);
|
||||
goto err6;
|
||||
}
|
||||
|
||||
return 0;
|
||||
err6:
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
err5:
|
||||
clk_disable_unprepare(pcm->pclk);
|
||||
err4:
|
||||
|
@ -168,19 +168,19 @@ static int s3c2412_iis_dev_probe(struct platform_device *pdev)
|
||||
s3c2412_i2s_pcm_stereo_in.addr = res->start + S3C2412_IISRXD;
|
||||
s3c2412_i2s_pcm_stereo_in.filter_data = pdata->dma_capture;
|
||||
|
||||
ret = s3c_i2sv2_register_component(&pdev->dev, -1,
|
||||
&s3c2412_i2s_component,
|
||||
&s3c2412_i2s_dai);
|
||||
if (ret) {
|
||||
pr_err("failed to register the dai\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = samsung_asoc_dma_platform_register(&pdev->dev,
|
||||
pdata->dma_filter,
|
||||
NULL, NULL);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
pr_err("failed to register the DMA: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = s3c_i2sv2_register_component(&pdev->dev, -1,
|
||||
&s3c2412_i2s_component,
|
||||
&s3c2412_i2s_dai);
|
||||
if (ret)
|
||||
pr_err("failed to register the dai\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -474,18 +474,18 @@ static int s3c24xx_iis_dev_probe(struct platform_device *pdev)
|
||||
s3c24xx_i2s_pcm_stereo_in.addr = res->start + S3C2410_IISFIFO;
|
||||
s3c24xx_i2s_pcm_stereo_in.filter_data = pdata->dma_capture;
|
||||
|
||||
ret = devm_snd_soc_register_component(&pdev->dev,
|
||||
&s3c24xx_i2s_component, &s3c24xx_i2s_dai, 1);
|
||||
if (ret) {
|
||||
pr_err("failed to register the dai\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = samsung_asoc_dma_platform_register(&pdev->dev,
|
||||
pdata->dma_filter,
|
||||
NULL, NULL);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
pr_err("failed to register the dma: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = devm_snd_soc_register_component(&pdev->dev,
|
||||
&s3c24xx_i2s_component, &s3c24xx_i2s_dai, 1);
|
||||
if (ret)
|
||||
pr_err("failed to register the dai\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -416,15 +416,6 @@ static int spdif_probe(struct platform_device *pdev)
|
||||
goto err3;
|
||||
}
|
||||
|
||||
dev_set_drvdata(&pdev->dev, spdif);
|
||||
|
||||
ret = devm_snd_soc_register_component(&pdev->dev,
|
||||
&samsung_spdif_component, &samsung_spdif_dai, 1);
|
||||
if (ret != 0) {
|
||||
dev_err(&pdev->dev, "fail to register dai\n");
|
||||
goto err4;
|
||||
}
|
||||
|
||||
spdif_stereo_out.addr_width = 2;
|
||||
spdif_stereo_out.addr = mem_res->start + DATA_OUTBUF;
|
||||
filter = NULL;
|
||||
@ -432,7 +423,6 @@ static int spdif_probe(struct platform_device *pdev)
|
||||
spdif_stereo_out.filter_data = spdif_pdata->dma_playback;
|
||||
filter = spdif_pdata->dma_filter;
|
||||
}
|
||||
|
||||
spdif->dma_playback = &spdif_stereo_out;
|
||||
|
||||
ret = samsung_asoc_dma_platform_register(&pdev->dev, filter,
|
||||
@ -442,6 +432,15 @@ static int spdif_probe(struct platform_device *pdev)
|
||||
goto err4;
|
||||
}
|
||||
|
||||
dev_set_drvdata(&pdev->dev, spdif);
|
||||
|
||||
ret = devm_snd_soc_register_component(&pdev->dev,
|
||||
&samsung_spdif_component, &samsung_spdif_dai, 1);
|
||||
if (ret != 0) {
|
||||
dev_err(&pdev->dev, "fail to register dai\n");
|
||||
goto err4;
|
||||
}
|
||||
|
||||
return 0;
|
||||
err4:
|
||||
iounmap(spdif->regs);
|
||||
|
@ -614,7 +614,11 @@ static int uni_player_ctl_iec958_put(struct snd_kcontrol *kcontrol,
|
||||
iec958->status[3] = ucontrol->value.iec958.status[3];
|
||||
mutex_unlock(&player->ctrl_lock);
|
||||
|
||||
uni_player_set_channel_status(player, NULL);
|
||||
if (player->substream && player->substream->runtime)
|
||||
uni_player_set_channel_status(player,
|
||||
player->substream->runtime);
|
||||
else
|
||||
uni_player_set_channel_status(player, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -765,11 +765,11 @@ static struct snd_soc_card *sun4i_codec_create_card(struct device *dev)
|
||||
|
||||
card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL);
|
||||
if (!card)
|
||||
return NULL;
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
card->dai_link = sun4i_codec_create_link(dev, &card->num_links);
|
||||
if (!card->dai_link)
|
||||
return NULL;
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
card->dev = dev;
|
||||
card->name = "sun4i-codec";
|
||||
@ -829,12 +829,6 @@ static int sun4i_codec_probe(struct platform_device *pdev)
|
||||
return PTR_ERR(scodec->clk_module);
|
||||
}
|
||||
|
||||
/* Enable the bus clock */
|
||||
if (clk_prepare_enable(scodec->clk_apb)) {
|
||||
dev_err(&pdev->dev, "Failed to enable the APB clock\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
scodec->gpio_pa = devm_gpiod_get_optional(&pdev->dev, "allwinner,pa",
|
||||
GPIOD_OUT_LOW);
|
||||
if (IS_ERR(scodec->gpio_pa)) {
|
||||
@ -844,6 +838,12 @@ static int sun4i_codec_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Enable the bus clock */
|
||||
if (clk_prepare_enable(scodec->clk_apb)) {
|
||||
dev_err(&pdev->dev, "Failed to enable the APB clock\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* DMA configuration for TX FIFO */
|
||||
scodec->playback_dma_data.addr = res->start + SUN4I_CODEC_DAC_TXDATA;
|
||||
scodec->playback_dma_data.maxburst = 4;
|
||||
@ -876,7 +876,8 @@ static int sun4i_codec_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
card = sun4i_codec_create_card(&pdev->dev);
|
||||
if (!card) {
|
||||
if (IS_ERR(card)) {
|
||||
ret = PTR_ERR(card);
|
||||
dev_err(&pdev->dev, "Failed to create our card\n");
|
||||
goto err_unregister_codec;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user