Commit 2fa4a285 authored by Mark Brown's avatar Mark Brown

Merge tag 'asoc-v3.16-rc5' into asoc-linus

ASoC: Fixes for v3.16

A bigger batch of changes than I would like as I didn't send any for a
few weeks without noticing how many had built up.  They are almost all
driver specific though, larger changes are:

 - Fixes to the newly added Baytrail/MAX98090 which look like some QA
   was missed on the microphone detection.
 - Deletion of some erroniously listed audio formats for Haswell.
 - Fix debugfs creation in the core so that we don't try to generate
   multiple directories with the same name, relatively large textually
   but simple to inspect by eye and test.
 - A couple of bugfixes for the rcar driver one of which which involves
   a bit of code motion to move initailisation of some hardware out of
   common paths into device specific ones.
 - Ensure both channels are powered up for mono outputs on Arizona
   devices, involving some simple data tables listing the outputs and a
   loop over them.
 - A couple of fixes to save and restore information on suspended and
   idle Samsung I2S controllers.

# gpg: Signature made Tue 22 Jul 2014 00:52:53 BST using RSA key ID 7EA229BD
# 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 9c1810f9 d0ab92d6
...@@ -290,19 +290,19 @@ static int bf5xx_pcm_silence(struct snd_pcm_substream *substream, ...@@ -290,19 +290,19 @@ static int bf5xx_pcm_silence(struct snd_pcm_substream *substream,
unsigned int sample_size = runtime->sample_bits / 8; unsigned int sample_size = runtime->sample_bits / 8;
void *buf = runtime->dma_area; void *buf = runtime->dma_area;
struct bf5xx_i2s_pcm_data *dma_data; struct bf5xx_i2s_pcm_data *dma_data;
unsigned int offset, size; unsigned int offset, samples;
dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
if (dma_data->tdm_mode) { if (dma_data->tdm_mode) {
offset = pos * 8 * sample_size; offset = pos * 8 * sample_size;
size = count * 8 * sample_size; samples = count * 8;
} else { } else {
offset = frames_to_bytes(runtime, pos); offset = frames_to_bytes(runtime, pos);
size = frames_to_bytes(runtime, count); samples = count * runtime->channels;
} }
snd_pcm_format_set_silence(runtime->format, buf + offset, size); snd_pcm_format_set_silence(runtime->format, buf + offset, samples);
return 0; return 0;
} }
......
...@@ -230,8 +230,10 @@ static int adau1701_reg_read(void *context, unsigned int reg, ...@@ -230,8 +230,10 @@ static int adau1701_reg_read(void *context, unsigned int reg,
*value = 0; *value = 0;
for (i = 0; i < size; i++) for (i = 0; i < size; i++) {
*value |= recv_buf[i] << (i * 8); *value <<= 8;
*value |= recv_buf[i];
}
return 0; return 0;
} }
......
...@@ -243,6 +243,31 @@ int arizona_init_spk(struct snd_soc_codec *codec) ...@@ -243,6 +243,31 @@ int arizona_init_spk(struct snd_soc_codec *codec)
} }
EXPORT_SYMBOL_GPL(arizona_init_spk); EXPORT_SYMBOL_GPL(arizona_init_spk);
static const struct snd_soc_dapm_route arizona_mono_routes[] = {
{ "OUT1R", NULL, "OUT1L" },
{ "OUT2R", NULL, "OUT2L" },
{ "OUT3R", NULL, "OUT3L" },
{ "OUT4R", NULL, "OUT4L" },
{ "OUT5R", NULL, "OUT5L" },
{ "OUT6R", NULL, "OUT6L" },
};
int arizona_init_mono(struct snd_soc_codec *codec)
{
struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
struct arizona *arizona = priv->arizona;
int i;
for (i = 0; i < ARIZONA_MAX_OUTPUT; ++i) {
if (arizona->pdata.out_mono[i])
snd_soc_dapm_add_routes(&codec->dapm,
&arizona_mono_routes[i], 1);
}
return 0;
}
EXPORT_SYMBOL_GPL(arizona_init_mono);
int arizona_init_gpio(struct snd_soc_codec *codec) int arizona_init_gpio(struct snd_soc_codec *codec)
{ {
struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
......
...@@ -249,6 +249,7 @@ extern int arizona_set_fll(struct arizona_fll *fll, int source, ...@@ -249,6 +249,7 @@ extern int arizona_set_fll(struct arizona_fll *fll, int source,
extern int arizona_init_spk(struct snd_soc_codec *codec); extern int arizona_init_spk(struct snd_soc_codec *codec);
extern int arizona_init_gpio(struct snd_soc_codec *codec); extern int arizona_init_gpio(struct snd_soc_codec *codec);
extern int arizona_init_mono(struct snd_soc_codec *codec);
extern int arizona_init_dai(struct arizona_priv *priv, int dai); extern int arizona_init_dai(struct arizona_priv *priv, int dai);
......
...@@ -445,9 +445,9 @@ static const struct snd_kcontrol_new cs42l56_snd_controls[] = { ...@@ -445,9 +445,9 @@ static const struct snd_kcontrol_new cs42l56_snd_controls[] = {
SOC_DOUBLE("ADC Boost Switch", CS42L56_GAIN_BIAS_CTL, 3, 2, 1, 1), SOC_DOUBLE("ADC Boost Switch", CS42L56_GAIN_BIAS_CTL, 3, 2, 1, 1),
SOC_DOUBLE_R_SX_TLV("Headphone Volume", CS42L56_HPA_VOLUME, SOC_DOUBLE_R_SX_TLV("Headphone Volume", CS42L56_HPA_VOLUME,
CS42L56_HPA_VOLUME, 0, 0x44, 0x55, hl_tlv), CS42L56_HPB_VOLUME, 0, 0x44, 0x55, hl_tlv),
SOC_DOUBLE_R_SX_TLV("LineOut Volume", CS42L56_LOA_VOLUME, SOC_DOUBLE_R_SX_TLV("LineOut Volume", CS42L56_LOA_VOLUME,
CS42L56_LOA_VOLUME, 0, 0x44, 0x55, hl_tlv), CS42L56_LOB_VOLUME, 0, 0x44, 0x55, hl_tlv),
SOC_SINGLE_TLV("Bass Shelving Volume", CS42L56_TONE_CTL, SOC_SINGLE_TLV("Bass Shelving Volume", CS42L56_TONE_CTL,
0, 0x00, 1, tone_tlv), 0, 0x00, 1, tone_tlv),
......
...@@ -2284,7 +2284,7 @@ static int max98090_probe(struct snd_soc_codec *codec) ...@@ -2284,7 +2284,7 @@ static int max98090_probe(struct snd_soc_codec *codec)
/* Register for interrupts */ /* Register for interrupts */
dev_dbg(codec->dev, "irq = %d\n", max98090->irq); dev_dbg(codec->dev, "irq = %d\n", max98090->irq);
ret = request_threaded_irq(max98090->irq, NULL, ret = devm_request_threaded_irq(codec->dev, max98090->irq, NULL,
max98090_interrupt, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, max98090_interrupt, IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
"max98090_interrupt", codec); "max98090_interrupt", codec);
if (ret < 0) { if (ret < 0) {
......
...@@ -1277,7 +1277,7 @@ static int sgtl5000_enable_regulators(struct snd_soc_codec *codec) ...@@ -1277,7 +1277,7 @@ static int sgtl5000_enable_regulators(struct snd_soc_codec *codec)
return ret; return ret;
} }
ret = devm_regulator_bulk_get(codec->dev, ARRAY_SIZE(sgtl5000->supplies), ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(sgtl5000->supplies),
sgtl5000->supplies); sgtl5000->supplies);
if (ret) if (ret)
goto err_ldo_remove; goto err_ldo_remove;
...@@ -1285,13 +1285,16 @@ static int sgtl5000_enable_regulators(struct snd_soc_codec *codec) ...@@ -1285,13 +1285,16 @@ static int sgtl5000_enable_regulators(struct snd_soc_codec *codec)
ret = regulator_bulk_enable(ARRAY_SIZE(sgtl5000->supplies), ret = regulator_bulk_enable(ARRAY_SIZE(sgtl5000->supplies),
sgtl5000->supplies); sgtl5000->supplies);
if (ret) if (ret)
goto err_ldo_remove; goto err_regulator_free;
/* wait for all power rails bring up */ /* wait for all power rails bring up */
udelay(10); udelay(10);
return 0; return 0;
err_regulator_free:
regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies),
sgtl5000->supplies);
err_ldo_remove: err_ldo_remove:
if (!external_vddd) if (!external_vddd)
ldo_regulator_remove(codec); ldo_regulator_remove(codec);
...@@ -1361,6 +1364,8 @@ static int sgtl5000_probe(struct snd_soc_codec *codec) ...@@ -1361,6 +1364,8 @@ static int sgtl5000_probe(struct snd_soc_codec *codec)
err: err:
regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies), regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies),
sgtl5000->supplies); sgtl5000->supplies);
regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies),
sgtl5000->supplies);
ldo_regulator_remove(codec); ldo_regulator_remove(codec);
return ret; return ret;
...@@ -1374,6 +1379,8 @@ static int sgtl5000_remove(struct snd_soc_codec *codec) ...@@ -1374,6 +1379,8 @@ static int sgtl5000_remove(struct snd_soc_codec *codec)
regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies), regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies),
sgtl5000->supplies); sgtl5000->supplies);
regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies),
sgtl5000->supplies);
ldo_regulator_remove(codec); ldo_regulator_remove(codec);
return 0; return 0;
......
...@@ -879,7 +879,7 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream, ...@@ -879,7 +879,7 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream,
case SNDRV_PCM_FORMAT_S20_3LE: case SNDRV_PCM_FORMAT_S20_3LE:
data |= (0x01 << 4); data |= (0x01 << 4);
break; break;
case SNDRV_PCM_FORMAT_S24_LE: case SNDRV_PCM_FORMAT_S24_3LE:
data |= (0x02 << 4); data |= (0x02 << 4);
break; break;
case SNDRV_PCM_FORMAT_S32_LE: case SNDRV_PCM_FORMAT_S32_LE:
......
...@@ -1596,6 +1596,7 @@ static int wm5110_codec_probe(struct snd_soc_codec *codec) ...@@ -1596,6 +1596,7 @@ static int wm5110_codec_probe(struct snd_soc_codec *codec)
arizona_init_spk(codec); arizona_init_spk(codec);
arizona_init_gpio(codec); arizona_init_gpio(codec);
arizona_init_mono(codec);
ret = snd_soc_add_codec_controls(codec, wm_adsp2_fw_controls, 8); ret = snd_soc_add_codec_controls(codec, wm_adsp2_fw_controls, 8);
if (ret != 0) if (ret != 0)
......
...@@ -1758,3 +1758,5 @@ int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs) ...@@ -1758,3 +1758,5 @@ int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs)
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(wm_adsp2_init); EXPORT_SYMBOL_GPL(wm_adsp2_init);
MODULE_LICENSE("GPL v2");
...@@ -6,6 +6,7 @@ config SND_DAVINCI_SOC_I2S ...@@ -6,6 +6,7 @@ config SND_DAVINCI_SOC_I2S
tristate tristate
config SND_DAVINCI_SOC_MCASP config SND_DAVINCI_SOC_MCASP
depends on SND_DAVINCI_SOC || SND_OMAP_SOC
tristate tristate
config SND_DAVINCI_SOC_VCIF config SND_DAVINCI_SOC_VCIF
......
...@@ -720,6 +720,10 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, ...@@ -720,6 +720,10 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
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;
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; dma_params->data_type = 4;
...@@ -1223,14 +1227,22 @@ static int davinci_mcasp_probe(struct platform_device *pdev) ...@@ -1223,14 +1227,22 @@ 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_1:
case MCASP_VERSION_2: case MCASP_VERSION_2:
case MCASP_VERSION_3: case MCASP_VERSION_3:
ret = davinci_soc_platform_register(&pdev->dev); ret = davinci_soc_platform_register(&pdev->dev);
break; break;
#endif
#if IS_BUILTIN(CONFIG_SND_OMAP_SOC) || \
(IS_MODULE(CONFIG_SND_DAVINCI_SOC_MCASP) && \
IS_MODULE(CONFIG_SND_OMAP_SOC))
case MCASP_VERSION_4: case MCASP_VERSION_4:
ret = omap_pcm_platform_register(&pdev->dev); ret = omap_pcm_platform_register(&pdev->dev);
break; break;
#endif
default: default:
dev_err(&pdev->dev, "Invalid McASP version: %d\n", dev_err(&pdev->dev, "Invalid McASP version: %d\n",
mcasp->version); mcasp->version);
......
...@@ -106,7 +106,7 @@ static irqreturn_t fsl_sai_isr(int irq, void *devid) ...@@ -106,7 +106,7 @@ static irqreturn_t fsl_sai_isr(int irq, void *devid)
xcsr &= ~FSL_SAI_CSR_xF_MASK; xcsr &= ~FSL_SAI_CSR_xF_MASK;
if (flags) if (flags)
regmap_write(sai->regmap, FSL_SAI_TCSR, flags | xcsr); regmap_write(sai->regmap, FSL_SAI_RCSR, flags | xcsr);
out: out:
if (irq_none) if (irq_none)
...@@ -371,10 +371,13 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd, ...@@ -371,10 +371,13 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd,
/* Check if the opposite FRDE is also disabled */ /* Check if the opposite FRDE is also disabled */
if (!(tx ? rcsr & FSL_SAI_CSR_FRDE : tcsr & FSL_SAI_CSR_FRDE)) { if (!(tx ? rcsr & FSL_SAI_CSR_FRDE : tcsr & FSL_SAI_CSR_FRDE)) {
/* Disable both directions and reset their FIFOs */
regmap_update_bits(sai->regmap, FSL_SAI_TCSR, regmap_update_bits(sai->regmap, FSL_SAI_TCSR,
FSL_SAI_CSR_TERE, 0); FSL_SAI_CSR_TERE | FSL_SAI_CSR_FR,
FSL_SAI_CSR_FR);
regmap_update_bits(sai->regmap, FSL_SAI_RCSR, regmap_update_bits(sai->regmap, FSL_SAI_RCSR,
FSL_SAI_CSR_TERE, 0); FSL_SAI_CSR_TERE | FSL_SAI_CSR_FR,
FSL_SAI_CSR_FR);
} }
break; break;
default: default:
......
...@@ -116,6 +116,7 @@ asoc_simple_card_sub_parse_of(struct device_node *np, ...@@ -116,6 +116,7 @@ asoc_simple_card_sub_parse_of(struct device_node *np,
{ {
struct device_node *node; struct device_node *node;
struct clk *clk; struct clk *clk;
u32 val;
int ret; int ret;
/* /*
...@@ -151,10 +152,8 @@ asoc_simple_card_sub_parse_of(struct device_node *np, ...@@ -151,10 +152,8 @@ asoc_simple_card_sub_parse_of(struct device_node *np,
} }
dai->sysclk = clk_get_rate(clk); dai->sysclk = clk_get_rate(clk);
} else if (of_property_read_bool(np, "system-clock-frequency")) { } else if (!of_property_read_u32(np, "system-clock-frequency", &val)) {
of_property_read_u32(np, dai->sysclk = val;
"system-clock-frequency",
&dai->sysclk);
} else { } else {
clk = of_clk_get(node, 0); clk = of_clk_get(node, 0);
if (!IS_ERR(clk)) if (!IS_ERR(clk))
...@@ -303,6 +302,7 @@ static int asoc_simple_card_parse_of(struct device_node *node, ...@@ -303,6 +302,7 @@ static int asoc_simple_card_parse_of(struct device_node *node,
{ {
struct snd_soc_dai_link *dai_link = priv->snd_card.dai_link; struct snd_soc_dai_link *dai_link = priv->snd_card.dai_link;
struct simple_dai_props *dai_props = priv->dai_props; struct simple_dai_props *dai_props = priv->dai_props;
u32 val;
int ret; int ret;
/* parsing the card name from DT */ /* parsing the card name from DT */
...@@ -325,8 +325,9 @@ static int asoc_simple_card_parse_of(struct device_node *node, ...@@ -325,8 +325,9 @@ static int asoc_simple_card_parse_of(struct device_node *node,
} }
/* Factor to mclk, used in hw_params() */ /* Factor to mclk, used in hw_params() */
of_property_read_u32(node, "simple-audio-card,mclk-fs", ret = of_property_read_u32(node, "simple-audio-card,mclk-fs", &val);
&priv->mclk_fs); if (ret == 0)
priv->mclk_fs = val;
dev_dbg(dev, "New simple-card: %s\n", priv->snd_card.name ? dev_dbg(dev, "New simple-card: %s\n", priv->snd_card.name ?
priv->snd_card.name : ""); priv->snd_card.name : "");
......
...@@ -39,8 +39,7 @@ static const struct snd_soc_dapm_widget byt_max98090_widgets[] = { ...@@ -39,8 +39,7 @@ static const struct snd_soc_dapm_widget byt_max98090_widgets[] = {
static const struct snd_soc_dapm_route byt_max98090_audio_map[] = { static const struct snd_soc_dapm_route byt_max98090_audio_map[] = {
{"IN34", NULL, "Headset Mic"}, {"IN34", NULL, "Headset Mic"},
{"IN34", NULL, "MICBIAS"}, {"Headset Mic", NULL, "MICBIAS"},
{"MICBIAS", NULL, "Headset Mic"},
{"DMICL", NULL, "Int Mic"}, {"DMICL", NULL, "Int Mic"},
{"Headphone", NULL, "HPL"}, {"Headphone", NULL, "HPL"},
{"Headphone", NULL, "HPR"}, {"Headphone", NULL, "HPR"},
...@@ -84,7 +83,8 @@ static struct snd_soc_jack_gpio hs_jack_gpios[] = { ...@@ -84,7 +83,8 @@ static struct snd_soc_jack_gpio hs_jack_gpios[] = {
{ {
.name = "mic-gpio", .name = "mic-gpio",
.idx = 1, .idx = 1,
.report = SND_JACK_MICROPHONE | SND_JACK_LINEIN, .invert = 1,
.report = SND_JACK_MICROPHONE,
.debounce_time = 200, .debounce_time = 200,
}, },
}; };
...@@ -108,7 +108,8 @@ static int byt_max98090_init(struct snd_soc_pcm_runtime *runtime) ...@@ -108,7 +108,8 @@ static int byt_max98090_init(struct snd_soc_pcm_runtime *runtime)
} }
/* Enable jack detection */ /* Enable jack detection */
ret = snd_soc_jack_new(codec, "Headphone", SND_JACK_HEADPHONE, jack); ret = snd_soc_jack_new(codec, "Headset",
SND_JACK_LINEOUT | SND_JACK_HEADSET, jack);
if (ret) if (ret)
return ret; return ret;
...@@ -117,13 +118,9 @@ static int byt_max98090_init(struct snd_soc_pcm_runtime *runtime) ...@@ -117,13 +118,9 @@ static int byt_max98090_init(struct snd_soc_pcm_runtime *runtime)
if (ret) if (ret)
return ret; return ret;
ret = snd_soc_jack_add_gpiods(card->dev->parent, jack, return snd_soc_jack_add_gpiods(card->dev->parent, jack,
ARRAY_SIZE(hs_jack_gpios), ARRAY_SIZE(hs_jack_gpios),
hs_jack_gpios); hs_jack_gpios);
if (ret)
return ret;
return max98090_mic_detect(codec, jack);
} }
static struct snd_soc_dai_link byt_max98090_dais[] = { static struct snd_soc_dai_link byt_max98090_dais[] = {
......
...@@ -32,7 +32,7 @@ static const struct snd_pcm_hardware sst_byt_pcm_hardware = { ...@@ -32,7 +32,7 @@ static const struct snd_pcm_hardware sst_byt_pcm_hardware = {
SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_PAUSE |
SNDRV_PCM_INFO_RESUME, SNDRV_PCM_INFO_RESUME,
.formats = SNDRV_PCM_FMTBIT_S16_LE | .formats = SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FORMAT_S24_LE, SNDRV_PCM_FMTBIT_S24_LE,
.period_bytes_min = 384, .period_bytes_min = 384,
.period_bytes_max = 48000, .period_bytes_max = 48000,
.periods_min = 2, .periods_min = 2,
......
...@@ -359,6 +359,17 @@ static u32 hsw_block_get_bit(struct sst_mem_block *block) ...@@ -359,6 +359,17 @@ static u32 hsw_block_get_bit(struct sst_mem_block *block)
return bit; return bit;
} }
/*dummy read a SRAM block.*/
static void sst_mem_block_dummy_read(struct sst_mem_block *block)
{
u32 size;
u8 tmp_buf[4];
struct sst_dsp *sst = block->dsp;
size = block->size > 4 ? 4 : block->size;
memcpy_fromio(tmp_buf, sst->addr.lpe + block->offset, size);
}
/* enable 32kB memory block - locks held by caller */ /* enable 32kB memory block - locks held by caller */
static int hsw_block_enable(struct sst_mem_block *block) static int hsw_block_enable(struct sst_mem_block *block)
{ {
...@@ -378,6 +389,8 @@ static int hsw_block_enable(struct sst_mem_block *block) ...@@ -378,6 +389,8 @@ static int hsw_block_enable(struct sst_mem_block *block)
/* wait 18 DSP clock ticks */ /* wait 18 DSP clock ticks */
udelay(10); udelay(10);
/*add a dummy read before the SRAM block is written, otherwise the writing may miss bytes sometimes.*/
sst_mem_block_dummy_read(block);
return 0; return 0;
} }
......
...@@ -80,7 +80,7 @@ static const struct snd_pcm_hardware hsw_pcm_hardware = { ...@@ -80,7 +80,7 @@ static const struct snd_pcm_hardware hsw_pcm_hardware = {
SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_PAUSE |
SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_RESUME |
SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, SNDRV_PCM_INFO_NO_PERIOD_WAKEUP,
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE | .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE, SNDRV_PCM_FMTBIT_S32_LE,
.period_bytes_min = PAGE_SIZE, .period_bytes_min = PAGE_SIZE,
.period_bytes_max = (HSW_PCM_PERIODS_MAX / HSW_PCM_PERIODS_MIN) * PAGE_SIZE, .period_bytes_max = (HSW_PCM_PERIODS_MAX / HSW_PCM_PERIODS_MIN) * PAGE_SIZE,
...@@ -400,7 +400,15 @@ static int hsw_pcm_hw_params(struct snd_pcm_substream *substream, ...@@ -400,7 +400,15 @@ static int hsw_pcm_hw_params(struct snd_pcm_substream *substream,
sst_hsw_stream_set_valid(hsw, pcm_data->stream, 16); sst_hsw_stream_set_valid(hsw, pcm_data->stream, 16);
break; break;
case SNDRV_PCM_FORMAT_S24_LE: case SNDRV_PCM_FORMAT_S24_LE:
bits = SST_HSW_DEPTH_24BIT; bits = SST_HSW_DEPTH_32BIT;
sst_hsw_stream_set_valid(hsw, pcm_data->stream, 24);
break;
case SNDRV_PCM_FORMAT_S8:
bits = SST_HSW_DEPTH_8BIT;
sst_hsw_stream_set_valid(hsw, pcm_data->stream, 8);
break;
case SNDRV_PCM_FORMAT_S32_LE:
bits = SST_HSW_DEPTH_32BIT;
sst_hsw_stream_set_valid(hsw, pcm_data->stream, 32); sst_hsw_stream_set_valid(hsw, pcm_data->stream, 32);
break; break;
default: default:
...@@ -685,8 +693,9 @@ static int hsw_pcm_new(struct snd_soc_pcm_runtime *rtd) ...@@ -685,8 +693,9 @@ static int hsw_pcm_new(struct snd_soc_pcm_runtime *rtd)
} }
#define HSW_FORMATS \ #define HSW_FORMATS \
(SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S16_LE |\ (SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S24_LE | \
SNDRV_PCM_FMTBIT_S32_LE) SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S16_LE |\
SNDRV_PCM_FMTBIT_S8)
static struct snd_soc_dai_driver hsw_dais[] = { static struct snd_soc_dai_driver hsw_dais[] = {
{ {
...@@ -696,7 +705,7 @@ static struct snd_soc_dai_driver hsw_dais[] = { ...@@ -696,7 +705,7 @@ static struct snd_soc_dai_driver hsw_dais[] = {
.channels_min = 2, .channels_min = 2,
.channels_max = 2, .channels_max = 2,
.rates = SNDRV_PCM_RATE_48000, .rates = SNDRV_PCM_RATE_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE, .formats = SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE,
}, },
}, },
{ {
...@@ -727,8 +736,8 @@ static struct snd_soc_dai_driver hsw_dais[] = { ...@@ -727,8 +736,8 @@ static struct snd_soc_dai_driver hsw_dais[] = {
.stream_name = "Loopback Capture", .stream_name = "Loopback Capture",
.channels_min = 2, .channels_min = 2,
.channels_max = 2, .channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_192000, .rates = SNDRV_PCM_RATE_48000,
.formats = HSW_FORMATS, .formats = SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE,
}, },
}, },
{ {
...@@ -737,8 +746,8 @@ static struct snd_soc_dai_driver hsw_dais[] = { ...@@ -737,8 +746,8 @@ static struct snd_soc_dai_driver hsw_dais[] = {
.stream_name = "Analog Capture", .stream_name = "Analog Capture",
.channels_min = 2, .channels_min = 2,
.channels_max = 2, .channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_192000, .rates = SNDRV_PCM_RATE_48000,
.formats = HSW_FORMATS, .formats = SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE,
}, },
}, },
}; };
......
...@@ -570,7 +570,7 @@ static int s6000_i2s_probe(struct platform_device *pdev) ...@@ -570,7 +570,7 @@ static int s6000_i2s_probe(struct platform_device *pdev)
return ret; return ret;
} }
static void s6000_i2s_remove(struct platform_device *pdev) static int s6000_i2s_remove(struct platform_device *pdev)
{ {
struct s6000_i2s_dev *dev = dev_get_drvdata(&pdev->dev); struct s6000_i2s_dev *dev = dev_get_drvdata(&pdev->dev);
struct resource *region; struct resource *region;
...@@ -597,6 +597,8 @@ static void s6000_i2s_remove(struct platform_device *pdev) ...@@ -597,6 +597,8 @@ static void s6000_i2s_remove(struct platform_device *pdev)
iounmap(mmio); iounmap(mmio);
region = platform_get_resource(pdev, IORESOURCE_IO, 0); region = platform_get_resource(pdev, IORESOURCE_IO, 0);
release_mem_region(region->start, resource_size(region)); release_mem_region(region->start, resource_size(region));
return 0;
} }
static struct platform_driver s6000_i2s_driver = { static struct platform_driver s6000_i2s_driver = {
......
...@@ -68,6 +68,8 @@ struct i2s_dai { ...@@ -68,6 +68,8 @@ struct i2s_dai {
#define DAI_OPENED (1 << 0) /* Dai is opened */ #define DAI_OPENED (1 << 0) /* Dai is opened */
#define DAI_MANAGER (1 << 1) /* Dai is the manager */ #define DAI_MANAGER (1 << 1) /* Dai is the manager */
unsigned mode; unsigned mode;
/* CDCLK pin direction: 0 - input, 1 - output */
unsigned int cdclk_out:1;
/* Driver for this DAI */ /* Driver for this DAI */
struct snd_soc_dai_driver i2s_dai_drv; struct snd_soc_dai_driver i2s_dai_drv;
/* DMA parameters */ /* DMA parameters */
...@@ -737,6 +739,9 @@ static int i2s_startup(struct snd_pcm_substream *substream, ...@@ -737,6 +739,9 @@ static int i2s_startup(struct snd_pcm_substream *substream,
spin_unlock_irqrestore(&lock, flags); spin_unlock_irqrestore(&lock, flags);
if (!is_opened(other) && i2s->cdclk_out)
i2s_set_sysclk(dai, SAMSUNG_I2S_CDCLK,
0, SND_SOC_CLOCK_OUT);
return 0; return 0;
} }
...@@ -752,9 +757,13 @@ static void i2s_shutdown(struct snd_pcm_substream *substream, ...@@ -752,9 +757,13 @@ static void i2s_shutdown(struct snd_pcm_substream *substream,
i2s->mode &= ~DAI_OPENED; i2s->mode &= ~DAI_OPENED;
i2s->mode &= ~DAI_MANAGER; i2s->mode &= ~DAI_MANAGER;
if (is_opened(other)) if (is_opened(other)) {
other->mode |= DAI_MANAGER; other->mode |= DAI_MANAGER;
} else {
u32 mod = readl(i2s->addr + I2SMOD);
i2s->cdclk_out = !(mod & MOD_CDCLKCON);
other->cdclk_out = i2s->cdclk_out;
}
/* Reset any constraint on RFS and BFS */ /* Reset any constraint on RFS and BFS */
i2s->rfs = 0; i2s->rfs = 0;
i2s->bfs = 0; i2s->bfs = 0;
...@@ -920,11 +929,9 @@ static int i2s_suspend(struct snd_soc_dai *dai) ...@@ -920,11 +929,9 @@ static int i2s_suspend(struct snd_soc_dai *dai)
{ {
struct i2s_dai *i2s = to_info(dai); struct i2s_dai *i2s = to_info(dai);
if (dai->active) { i2s->suspend_i2smod = readl(i2s->addr + I2SMOD);
i2s->suspend_i2smod = readl(i2s->addr + I2SMOD); i2s->suspend_i2scon = readl(i2s->addr + I2SCON);
i2s->suspend_i2scon = readl(i2s->addr + I2SCON); i2s->suspend_i2spsr = readl(i2s->addr + I2SPSR);
i2s->suspend_i2spsr = readl(i2s->addr + I2SPSR);
}
return 0; return 0;
} }
...@@ -933,11 +940,9 @@ static int i2s_resume(struct snd_soc_dai *dai) ...@@ -933,11 +940,9 @@ static int i2s_resume(struct snd_soc_dai *dai)
{ {
struct i2s_dai *i2s = to_info(dai); struct i2s_dai *i2s = to_info(dai);
if (dai->active) { writel(i2s->suspend_i2scon, i2s->addr + I2SCON);
writel(i2s->suspend_i2scon, i2s->addr + I2SCON); writel(i2s->suspend_i2smod, i2s->addr + I2SMOD);
writel(i2s->suspend_i2smod, i2s->addr + I2SMOD); writel(i2s->suspend_i2spsr, i2s->addr + I2SPSR);
writel(i2s->suspend_i2spsr, i2s->addr + I2SPSR);
}
return 0; return 0;
} }
......
...@@ -297,7 +297,6 @@ static void rsnd_dma_of_name(struct rsnd_dma *dma, ...@@ -297,7 +297,6 @@ static void rsnd_dma_of_name(struct rsnd_dma *dma,
for (i = 1; i < MOD_MAX; i++) { for (i = 1; i < MOD_MAX; i++) {
if (!src) { if (!src) {
mod[i] = ssi; mod[i] = ssi;
break;
} else if (!dvc) { } else if (!dvc) {
mod[i] = src; mod[i] = src;
src = NULL; src = NULL;
...@@ -308,6 +307,9 @@ static void rsnd_dma_of_name(struct rsnd_dma *dma, ...@@ -308,6 +307,9 @@ static void rsnd_dma_of_name(struct rsnd_dma *dma,
if (mod[i] == this) if (mod[i] == this)
index = i; index = i;
if (mod[i] == ssi)
break;
} }
if (is_play) { if (is_play) {
......
...@@ -184,7 +184,7 @@ static int rsnd_gen_regmap_init(struct rsnd_priv *priv, ...@@ -184,7 +184,7 @@ static int rsnd_gen_regmap_init(struct rsnd_priv *priv,
#define RDMA_CMD_O_N(addr, i) (addr ##_reg - 0x004f8000 + (0x400 * i)) #define RDMA_CMD_O_N(addr, i) (addr ##_reg - 0x004f8000 + (0x400 * i))
#define RDMA_CMD_O_P(addr, i) (addr ##_reg - 0x001f8000 + (0x400 * i)) #define RDMA_CMD_O_P(addr, i) (addr ##_reg - 0x001f8000 + (0x400 * i))
void rsnd_gen_dma_addr(struct rsnd_priv *priv, static void rsnd_gen2_dma_addr(struct rsnd_priv *priv,
struct rsnd_dma *dma, struct rsnd_dma *dma,
struct dma_slave_config *cfg, struct dma_slave_config *cfg,
int is_play, int slave_id) int is_play, int slave_id)
...@@ -226,17 +226,6 @@ void rsnd_gen_dma_addr(struct rsnd_priv *priv, ...@@ -226,17 +226,6 @@ void rsnd_gen_dma_addr(struct rsnd_priv *priv,
} }
}; };
cfg->slave_id = slave_id;
cfg->src_addr = 0;
cfg->dst_addr = 0;
cfg->direction = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM;
/*
* gen1 uses default DMA addr
*/
if (rsnd_is_gen1(priv))
return;
/* it shouldn't happen */ /* it shouldn't happen */
if (use_dvc & !use_src) { if (use_dvc & !use_src) {
dev_err(dev, "DVC is selected without SRC\n"); dev_err(dev, "DVC is selected without SRC\n");
...@@ -250,6 +239,26 @@ void rsnd_gen_dma_addr(struct rsnd_priv *priv, ...@@ -250,6 +239,26 @@ void rsnd_gen_dma_addr(struct rsnd_priv *priv,
id, cfg->src_addr, cfg->dst_addr); id, cfg->src_addr, cfg->dst_addr);
} }
void rsnd_gen_dma_addr(struct rsnd_priv *priv,
struct rsnd_dma *dma,
struct dma_slave_config *cfg,
int is_play, int slave_id)
{
cfg->slave_id = slave_id;
cfg->src_addr = 0;
cfg->dst_addr = 0;
cfg->direction = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM;
/*
* gen1 uses default DMA addr
*/
if (rsnd_is_gen1(priv))
return;
rsnd_gen2_dma_addr(priv, dma, cfg, is_play, slave_id);
}
/* /*
* Gen2 * Gen2
*/ */
......
...@@ -270,12 +270,32 @@ static const struct file_operations codec_reg_fops = { ...@@ -270,12 +270,32 @@ static const struct file_operations codec_reg_fops = {
.llseek = default_llseek, .llseek = default_llseek,
}; };
static struct dentry *soc_debugfs_create_dir(struct dentry *parent,
const char *fmt, ...)
{
struct dentry *de;
va_list ap;
char *s;
va_start(ap, fmt);
s = kvasprintf(GFP_KERNEL, fmt, ap);
va_end(ap);
if (!s)
return NULL;
de = debugfs_create_dir(s, parent);
kfree(s);
return de;
}
static void soc_init_codec_debugfs(struct snd_soc_codec *codec) static void soc_init_codec_debugfs(struct snd_soc_codec *codec)
{ {
struct dentry *debugfs_card_root = codec->card->debugfs_card_root; struct dentry *debugfs_card_root = codec->card->debugfs_card_root;
codec->debugfs_codec_root = debugfs_create_dir(codec->name, codec->debugfs_codec_root = soc_debugfs_create_dir(debugfs_card_root,
debugfs_card_root); "codec:%s", codec->name);
if (!codec->debugfs_codec_root) { if (!codec->debugfs_codec_root) {
dev_warn(codec->dev, dev_warn(codec->dev,
"ASoC: Failed to create codec debugfs directory\n"); "ASoC: Failed to create codec debugfs directory\n");
...@@ -306,8 +326,8 @@ static void soc_init_platform_debugfs(struct snd_soc_platform *platform) ...@@ -306,8 +326,8 @@ static void soc_init_platform_debugfs(struct snd_soc_platform *platform)
{ {
struct dentry *debugfs_card_root = platform->card->debugfs_card_root; struct dentry *debugfs_card_root = platform->card->debugfs_card_root;
platform->debugfs_platform_root = debugfs_create_dir(platform->name, platform->debugfs_platform_root = soc_debugfs_create_dir(debugfs_card_root,
debugfs_card_root); "platform:%s", platform->name);
if (!platform->debugfs_platform_root) { if (!platform->debugfs_platform_root) {
dev_warn(platform->dev, dev_warn(platform->dev,
"ASoC: Failed to create platform debugfs directory\n"); "ASoC: Failed to create platform debugfs directory\n");
......
...@@ -2069,6 +2069,7 @@ int soc_dpcm_runtime_update(struct snd_soc_card *card) ...@@ -2069,6 +2069,7 @@ int soc_dpcm_runtime_update(struct snd_soc_card *card)
dpcm_be_disconnect(fe, SNDRV_PCM_STREAM_PLAYBACK); dpcm_be_disconnect(fe, SNDRV_PCM_STREAM_PLAYBACK);
} }
dpcm_path_put(&list);
capture: capture:
/* skip if FE doesn't have capture capability */ /* skip if FE doesn't have capture capability */
if (!fe->cpu_dai->driver->capture.channels_min) if (!fe->cpu_dai->driver->capture.channels_min)
......
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