Merge branch 'for-linus' into for-next

Back-merge for applying the more HD-audio quirks on top of the latest
code.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
Takashi Iwai 2018-12-07 11:40:00 +01:00
commit 2bff7e97eb
33 changed files with 485 additions and 267 deletions

View File

@ -13931,6 +13931,7 @@ S: Supported
F: Documentation/devicetree/bindings/sound/ F: Documentation/devicetree/bindings/sound/
F: Documentation/sound/soc/ F: Documentation/sound/soc/
F: sound/soc/ F: sound/soc/
F: include/dt-bindings/sound/
F: include/sound/soc* F: include/sound/soc*
SOUNDWIRE SUBSYSTEM SOUNDWIRE SUBSYSTEM

View File

@ -254,11 +254,13 @@ static inline int snd_interval_empty(const struct snd_interval *i)
static inline int snd_interval_single(const struct snd_interval *i) static inline int snd_interval_single(const struct snd_interval *i)
{ {
return (i->min == i->max || return (i->min == i->max ||
(i->min + 1 == i->max && i->openmax)); (i->min + 1 == i->max && (i->openmin || i->openmax)));
} }
static inline int snd_interval_value(const struct snd_interval *i) static inline int snd_interval_value(const struct snd_interval *i)
{ {
if (i->openmin && !i->openmax)
return i->max;
return i->min; return i->min;
} }

View File

@ -1192,7 +1192,7 @@ struct snd_soc_pcm_runtime {
((i) < rtd->num_codecs) && ((dai) = rtd->codec_dais[i]); \ ((i) < rtd->num_codecs) && ((dai) = rtd->codec_dais[i]); \
(i)++) (i)++)
#define for_each_rtd_codec_dai_rollback(rtd, i, dai) \ #define for_each_rtd_codec_dai_rollback(rtd, i, dai) \
for (; ((i--) >= 0) && ((dai) = rtd->codec_dais[i]);) for (; ((--i) >= 0) && ((dai) = rtd->codec_dais[i]);)
/* mixer control */ /* mixer control */

View File

@ -36,6 +36,7 @@
#include <sound/timer.h> #include <sound/timer.h>
#include <sound/minors.h> #include <sound/minors.h>
#include <linux/uio.h> #include <linux/uio.h>
#include <linux/delay.h>
#include "pcm_local.h" #include "pcm_local.h"
@ -91,12 +92,12 @@ static DECLARE_RWSEM(snd_pcm_link_rwsem);
* and this may lead to a deadlock when the code path takes read sem * and this may lead to a deadlock when the code path takes read sem
* twice (e.g. one in snd_pcm_action_nonatomic() and another in * twice (e.g. one in snd_pcm_action_nonatomic() and another in
* snd_pcm_stream_lock()). As a (suboptimal) workaround, let writer to * snd_pcm_stream_lock()). As a (suboptimal) workaround, let writer to
* spin until it gets the lock. * sleep until all the readers are completed without blocking by writer.
*/ */
static inline void down_write_nonblock(struct rw_semaphore *lock) static inline void down_write_nonfifo(struct rw_semaphore *lock)
{ {
while (!down_write_trylock(lock)) while (!down_write_trylock(lock))
cond_resched(); msleep(1);
} }
#define PCM_LOCK_DEFAULT 0 #define PCM_LOCK_DEFAULT 0
@ -1967,7 +1968,7 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
res = -ENOMEM; res = -ENOMEM;
goto _nolock; goto _nolock;
} }
down_write_nonblock(&snd_pcm_link_rwsem); down_write_nonfifo(&snd_pcm_link_rwsem);
write_lock_irq(&snd_pcm_link_rwlock); write_lock_irq(&snd_pcm_link_rwlock);
if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN || if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN ||
substream->runtime->status->state != substream1->runtime->status->state || substream->runtime->status->state != substream1->runtime->status->state ||
@ -2014,7 +2015,7 @@ static int snd_pcm_unlink(struct snd_pcm_substream *substream)
struct snd_pcm_substream *s; struct snd_pcm_substream *s;
int res = 0; int res = 0;
down_write_nonblock(&snd_pcm_link_rwsem); down_write_nonfifo(&snd_pcm_link_rwsem);
write_lock_irq(&snd_pcm_link_rwlock); write_lock_irq(&snd_pcm_link_rwlock);
if (!snd_pcm_stream_linked(substream)) { if (!snd_pcm_stream_linked(substream)) {
res = -EALREADY; res = -EALREADY;
@ -2369,7 +2370,8 @@ int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream)
static void pcm_release_private(struct snd_pcm_substream *substream) static void pcm_release_private(struct snd_pcm_substream *substream)
{ {
snd_pcm_unlink(substream); if (snd_pcm_stream_linked(substream))
snd_pcm_unlink(substream);
} }
void snd_pcm_release_substream(struct snd_pcm_substream *substream) void snd_pcm_release_substream(struct snd_pcm_substream *substream)

View File

@ -2498,6 +2498,10 @@ static const struct pci_device_id azx_ids[] = {
/* AMD Hudson */ /* AMD Hudson */
{ PCI_DEVICE(0x1022, 0x780d), { PCI_DEVICE(0x1022, 0x780d),
.driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_SB }, .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_SB },
/* AMD Stoney */
{ PCI_DEVICE(0x1022, 0x157a),
.driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_SB |
AZX_DCAPS_PM_RUNTIME },
/* AMD Raven */ /* AMD Raven */
{ PCI_DEVICE(0x1022, 0x15e3), { PCI_DEVICE(0x1022, 0x15e3),
.driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_SB | .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_SB |

View File

@ -388,6 +388,7 @@ static void alc_fill_eapd_coef(struct hda_codec *codec)
case 0x10ec0285: case 0x10ec0285:
case 0x10ec0298: case 0x10ec0298:
case 0x10ec0289: case 0x10ec0289:
case 0x10ec0300:
alc_update_coef_idx(codec, 0x10, 1<<9, 0); alc_update_coef_idx(codec, 0x10, 1<<9, 0);
break; break;
case 0x10ec0275: case 0x10ec0275:
@ -2830,6 +2831,7 @@ enum {
ALC269_TYPE_ALC215, ALC269_TYPE_ALC215,
ALC269_TYPE_ALC225, ALC269_TYPE_ALC225,
ALC269_TYPE_ALC294, ALC269_TYPE_ALC294,
ALC269_TYPE_ALC300,
ALC269_TYPE_ALC700, ALC269_TYPE_ALC700,
}; };
@ -2864,6 +2866,7 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
case ALC269_TYPE_ALC215: case ALC269_TYPE_ALC215:
case ALC269_TYPE_ALC225: case ALC269_TYPE_ALC225:
case ALC269_TYPE_ALC294: case ALC269_TYPE_ALC294:
case ALC269_TYPE_ALC300:
case ALC269_TYPE_ALC700: case ALC269_TYPE_ALC700:
ssids = alc269_ssids; ssids = alc269_ssids;
break; break;
@ -4985,9 +4988,18 @@ static void alc_fixup_tpt470_dock(struct hda_codec *codec,
{ 0x19, 0x21a11010 }, /* dock mic */ { 0x19, 0x21a11010 }, /* dock mic */
{ } { }
}; };
/* Assure the speaker pin to be coupled with DAC NID 0x03; otherwise
* the speaker output becomes too low by some reason on Thinkpads with
* ALC298 codec
*/
static hda_nid_t preferred_pairs[] = {
0x14, 0x03, 0x17, 0x02, 0x21, 0x02,
0
};
struct alc_spec *spec = codec->spec; struct alc_spec *spec = codec->spec;
if (action == HDA_FIXUP_ACT_PRE_PROBE) { if (action == HDA_FIXUP_ACT_PRE_PROBE) {
spec->gen.preferred_dacs = preferred_pairs;
spec->parse_flags = HDA_PINCFG_NO_HP_FIXUP; spec->parse_flags = HDA_PINCFG_NO_HP_FIXUP;
snd_hda_apply_pincfgs(codec, pincfgs); snd_hda_apply_pincfgs(codec, pincfgs);
} else if (action == HDA_FIXUP_ACT_INIT) { } else if (action == HDA_FIXUP_ACT_INIT) {
@ -5358,6 +5370,16 @@ static void alc274_fixup_bind_dacs(struct hda_codec *codec,
spec->gen.preferred_dacs = preferred_pairs; spec->gen.preferred_dacs = preferred_pairs;
} }
/* The DAC of NID 0x3 will introduce click/pop noise on headphones, so invalidate it */
static void alc285_fixup_invalidate_dacs(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
if (action != HDA_FIXUP_ACT_PRE_PROBE)
return;
snd_hda_override_wcaps(codec, 0x03, 0);
}
/* for hda_fixup_thinkpad_acpi() */ /* for hda_fixup_thinkpad_acpi() */
#include "thinkpad_helper.c" #include "thinkpad_helper.c"
@ -5492,6 +5514,9 @@ enum {
ALC255_FIXUP_DELL_HEADSET_MIC, ALC255_FIXUP_DELL_HEADSET_MIC,
ALC295_FIXUP_HP_X360, ALC295_FIXUP_HP_X360,
ALC221_FIXUP_HP_HEADSET_MIC, ALC221_FIXUP_HP_HEADSET_MIC,
ALC285_FIXUP_LENOVO_HEADPHONE_NOISE,
ALC295_FIXUP_HP_AUTO_MUTE,
ALC286_FIXUP_ACER_AIO_MIC_NO_PRESENCE,
}; };
static const struct hda_fixup alc269_fixups[] = { static const struct hda_fixup alc269_fixups[] = {
@ -5656,6 +5681,8 @@ static const struct hda_fixup alc269_fixups[] = {
[ALC269_FIXUP_HP_MUTE_LED_MIC3] = { [ALC269_FIXUP_HP_MUTE_LED_MIC3] = {
.type = HDA_FIXUP_FUNC, .type = HDA_FIXUP_FUNC,
.v.func = alc269_fixup_hp_mute_led_mic3, .v.func = alc269_fixup_hp_mute_led_mic3,
.chained = true,
.chain_id = ALC295_FIXUP_HP_AUTO_MUTE
}, },
[ALC269_FIXUP_HP_GPIO_LED] = { [ALC269_FIXUP_HP_GPIO_LED] = {
.type = HDA_FIXUP_FUNC, .type = HDA_FIXUP_FUNC,
@ -6359,6 +6386,23 @@ static const struct hda_fixup alc269_fixups[] = {
.chained = true, .chained = true,
.chain_id = ALC269_FIXUP_HEADSET_MIC .chain_id = ALC269_FIXUP_HEADSET_MIC
}, },
[ALC285_FIXUP_LENOVO_HEADPHONE_NOISE] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc285_fixup_invalidate_dacs,
},
[ALC295_FIXUP_HP_AUTO_MUTE] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc_fixup_auto_mute_via_amp,
},
[ALC286_FIXUP_ACER_AIO_MIC_NO_PRESENCE] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
{ 0x18, 0x01a1913c }, /* use as headset mic, without its own jack detect */
{ }
},
.chained = true,
.chain_id = ALC269_FIXUP_HEADSET_MIC
},
}; };
static const struct snd_pci_quirk alc269_fixup_tbl[] = { static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@ -6373,7 +6417,11 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1025, 0x0762, "Acer Aspire E1-472", ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572), SND_PCI_QUIRK(0x1025, 0x0762, "Acer Aspire E1-472", ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572),
SND_PCI_QUIRK(0x1025, 0x0775, "Acer Aspire E1-572", ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572), SND_PCI_QUIRK(0x1025, 0x0775, "Acer Aspire E1-572", ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572),
SND_PCI_QUIRK(0x1025, 0x079b, "Acer Aspire V5-573G", ALC282_FIXUP_ASPIRE_V5_PINS), SND_PCI_QUIRK(0x1025, 0x079b, "Acer Aspire V5-573G", ALC282_FIXUP_ASPIRE_V5_PINS),
SND_PCI_QUIRK(0x1025, 0x102b, "Acer Aspire C24-860", ALC286_FIXUP_ACER_AIO_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1025, 0x106d, "Acer Cloudbook 14", ALC283_FIXUP_CHROME_BOOK), SND_PCI_QUIRK(0x1025, 0x106d, "Acer Cloudbook 14", ALC283_FIXUP_CHROME_BOOK),
SND_PCI_QUIRK(0x1025, 0x128f, "Acer Veriton Z6860G", ALC286_FIXUP_ACER_AIO_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1025, 0x1290, "Acer Veriton Z4860G", ALC286_FIXUP_ACER_AIO_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1025, 0x1291, "Acer Veriton Z4660G", ALC286_FIXUP_ACER_AIO_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z), SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
SND_PCI_QUIRK(0x1028, 0x054b, "Dell XPS one 2710", ALC275_FIXUP_DELL_XPS), SND_PCI_QUIRK(0x1028, 0x054b, "Dell XPS one 2710", ALC275_FIXUP_DELL_XPS),
SND_PCI_QUIRK(0x1028, 0x05bd, "Dell Latitude E6440", ALC292_FIXUP_DELL_E7X), SND_PCI_QUIRK(0x1028, 0x05bd, "Dell Latitude E6440", ALC292_FIXUP_DELL_E7X),
@ -7032,6 +7080,15 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
{0x12, 0x90a60130}, {0x12, 0x90a60130},
{0x19, 0x03a11020}, {0x19, 0x03a11020},
{0x21, 0x0321101f}), {0x21, 0x0321101f}),
SND_HDA_PIN_QUIRK(0x10ec0285, 0x17aa, "Lenovo", ALC285_FIXUP_LENOVO_HEADPHONE_NOISE,
{0x12, 0x90a60130},
{0x14, 0x90170110},
{0x19, 0x04a11040},
{0x21, 0x04211020}),
SND_HDA_PIN_QUIRK(0x10ec0286, 0x1025, "Acer", ALC286_FIXUP_ACER_AIO_MIC_NO_PRESENCE,
{0x12, 0x90a60130},
{0x17, 0x90170110},
{0x21, 0x02211020}),
SND_HDA_PIN_QUIRK(0x10ec0288, 0x1028, "Dell", ALC288_FIXUP_DELL1_MIC_NO_PRESENCE, SND_HDA_PIN_QUIRK(0x10ec0288, 0x1028, "Dell", ALC288_FIXUP_DELL1_MIC_NO_PRESENCE,
{0x12, 0x90a60120}, {0x12, 0x90a60120},
{0x14, 0x90170110}, {0x14, 0x90170110},
@ -7167,6 +7224,37 @@ static void alc269_fill_coef(struct hda_codec *codec)
alc_update_coef_idx(codec, 0x4, 0, 1<<11); alc_update_coef_idx(codec, 0x4, 0, 1<<11);
} }
static void alc294_hp_init(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
int i, val;
if (!hp_pin)
return;
snd_hda_codec_write(codec, hp_pin, 0,
AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
msleep(100);
snd_hda_codec_write(codec, hp_pin, 0,
AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
alc_update_coef_idx(codec, 0x6f, 0x000f, 0);/* Set HP depop to manual mode */
alc_update_coefex_idx(codec, 0x58, 0x00, 0x8000, 0x8000); /* HP depop procedure start */
/* Wait for depop procedure finish */
val = alc_read_coefex_idx(codec, 0x58, 0x01);
for (i = 0; i < 20 && val & 0x0080; i++) {
msleep(50);
val = alc_read_coefex_idx(codec, 0x58, 0x01);
}
/* Set HP depop to auto mode */
alc_update_coef_idx(codec, 0x6f, 0x000f, 0x000b);
msleep(50);
}
/* /*
*/ */
static int patch_alc269(struct hda_codec *codec) static int patch_alc269(struct hda_codec *codec)
@ -7292,6 +7380,11 @@ static int patch_alc269(struct hda_codec *codec)
spec->codec_variant = ALC269_TYPE_ALC294; spec->codec_variant = ALC269_TYPE_ALC294;
spec->gen.mixer_nid = 0; /* ALC2x4 does not have any loopback mixer path */ spec->gen.mixer_nid = 0; /* ALC2x4 does not have any loopback mixer path */
alc_update_coef_idx(codec, 0x6b, 0x0018, (1<<4) | (1<<3)); /* UAJ MIC Vref control by verb */ alc_update_coef_idx(codec, 0x6b, 0x0018, (1<<4) | (1<<3)); /* UAJ MIC Vref control by verb */
alc294_hp_init(codec);
break;
case 0x10ec0300:
spec->codec_variant = ALC269_TYPE_ALC300;
spec->gen.mixer_nid = 0; /* no loopback on ALC300 */
break; break;
case 0x10ec0700: case 0x10ec0700:
case 0x10ec0701: case 0x10ec0701:
@ -7299,6 +7392,7 @@ static int patch_alc269(struct hda_codec *codec)
spec->codec_variant = ALC269_TYPE_ALC700; spec->codec_variant = ALC269_TYPE_ALC700;
spec->gen.mixer_nid = 0; /* ALC700 does not have any loopback mixer path */ spec->gen.mixer_nid = 0; /* ALC700 does not have any loopback mixer path */
alc_update_coef_idx(codec, 0x4a, 1 << 15, 0); /* Combo jack auto trigger control */ alc_update_coef_idx(codec, 0x4a, 1 << 15, 0); /* Combo jack auto trigger control */
alc294_hp_init(codec);
break; break;
} }
@ -8403,6 +8497,7 @@ static const struct hda_device_id snd_hda_id_realtek[] = {
HDA_CODEC_ENTRY(0x10ec0295, "ALC295", patch_alc269), HDA_CODEC_ENTRY(0x10ec0295, "ALC295", patch_alc269),
HDA_CODEC_ENTRY(0x10ec0298, "ALC298", patch_alc269), HDA_CODEC_ENTRY(0x10ec0298, "ALC298", patch_alc269),
HDA_CODEC_ENTRY(0x10ec0299, "ALC299", patch_alc269), HDA_CODEC_ENTRY(0x10ec0299, "ALC299", patch_alc269),
HDA_CODEC_ENTRY(0x10ec0300, "ALC300", patch_alc269),
HDA_CODEC_REV_ENTRY(0x10ec0861, 0x100340, "ALC660", patch_alc861), HDA_CODEC_REV_ENTRY(0x10ec0861, 0x100340, "ALC660", patch_alc861),
HDA_CODEC_ENTRY(0x10ec0660, "ALC660-VD", patch_alc861vd), HDA_CODEC_ENTRY(0x10ec0660, "ALC660-VD", patch_alc861vd),
HDA_CODEC_ENTRY(0x10ec0861, "ALC861", patch_alc861), HDA_CODEC_ENTRY(0x10ec0861, "ALC861", patch_alc861),

View File

@ -2187,11 +2187,6 @@ static int hdac_hdmi_runtime_suspend(struct device *dev)
*/ */
snd_hdac_codec_read(hdev, hdev->afg, 0, AC_VERB_SET_POWER_STATE, snd_hdac_codec_read(hdev, hdev->afg, 0, AC_VERB_SET_POWER_STATE,
AC_PWRST_D3); AC_PWRST_D3);
err = snd_hdac_display_power(bus, false);
if (err < 0) {
dev_err(dev, "Cannot turn on display power on i915\n");
return err;
}
hlink = snd_hdac_ext_bus_get_link(bus, dev_name(dev)); hlink = snd_hdac_ext_bus_get_link(bus, dev_name(dev));
if (!hlink) { if (!hlink) {
@ -2201,7 +2196,11 @@ static int hdac_hdmi_runtime_suspend(struct device *dev)
snd_hdac_ext_bus_link_put(bus, hlink); snd_hdac_ext_bus_link_put(bus, hlink);
return 0; err = snd_hdac_display_power(bus, false);
if (err < 0)
dev_err(dev, "Cannot turn off display power on i915\n");
return err;
} }
static int hdac_hdmi_runtime_resume(struct device *dev) static int hdac_hdmi_runtime_resume(struct device *dev)

View File

@ -139,7 +139,7 @@ enum pcm186x_type {
#define PCM186X_MAX_REGISTER PCM186X_CURR_TRIM_CTRL #define PCM186X_MAX_REGISTER PCM186X_CURR_TRIM_CTRL
/* PCM186X_PAGE */ /* PCM186X_PAGE */
#define PCM186X_RESET 0xff #define PCM186X_RESET 0xfe
/* PCM186X_ADCX_INPUT_SEL_X */ /* PCM186X_ADCX_INPUT_SEL_X */
#define PCM186X_ADC_INPUT_SEL_POL BIT(7) #define PCM186X_ADC_INPUT_SEL_POL BIT(7)

View File

@ -198,20 +198,16 @@ static const struct snd_kcontrol_new pcm3060_dapm_controls[] = {
}; };
static const struct snd_soc_dapm_widget pcm3060_dapm_widgets[] = { static const struct snd_soc_dapm_widget pcm3060_dapm_widgets[] = {
SND_SOC_DAPM_OUTPUT("OUTL+"), SND_SOC_DAPM_OUTPUT("OUTL"),
SND_SOC_DAPM_OUTPUT("OUTR+"), SND_SOC_DAPM_OUTPUT("OUTR"),
SND_SOC_DAPM_OUTPUT("OUTL-"),
SND_SOC_DAPM_OUTPUT("OUTR-"),
SND_SOC_DAPM_INPUT("INL"), SND_SOC_DAPM_INPUT("INL"),
SND_SOC_DAPM_INPUT("INR"), SND_SOC_DAPM_INPUT("INR"),
}; };
static const struct snd_soc_dapm_route pcm3060_dapm_map[] = { static const struct snd_soc_dapm_route pcm3060_dapm_map[] = {
{ "OUTL+", NULL, "Playback" }, { "OUTL", NULL, "Playback" },
{ "OUTR+", NULL, "Playback" }, { "OUTR", NULL, "Playback" },
{ "OUTL-", NULL, "Playback" },
{ "OUTR-", NULL, "Playback" },
{ "Capture", NULL, "INL" }, { "Capture", NULL, "INL" },
{ "Capture", NULL, "INR" }, { "Capture", NULL, "INR" },

View File

@ -765,38 +765,41 @@ static unsigned int wm_adsp_region_to_reg(struct wm_adsp_region const *mem,
static void wm_adsp2_show_fw_status(struct wm_adsp *dsp) static void wm_adsp2_show_fw_status(struct wm_adsp *dsp)
{ {
u16 scratch[4]; unsigned int scratch[4];
unsigned int addr = dsp->base + ADSP2_SCRATCH0;
unsigned int i;
int ret; int ret;
ret = regmap_raw_read(dsp->regmap, dsp->base + ADSP2_SCRATCH0, for (i = 0; i < ARRAY_SIZE(scratch); ++i) {
scratch, sizeof(scratch)); ret = regmap_read(dsp->regmap, addr + i, &scratch[i]);
if (ret) { if (ret) {
adsp_err(dsp, "Failed to read SCRATCH regs: %d\n", ret); adsp_err(dsp, "Failed to read SCRATCH%u: %d\n", i, ret);
return; return;
}
} }
adsp_dbg(dsp, "FW SCRATCH 0:0x%x 1:0x%x 2:0x%x 3:0x%x\n", adsp_dbg(dsp, "FW SCRATCH 0:0x%x 1:0x%x 2:0x%x 3:0x%x\n",
be16_to_cpu(scratch[0]), scratch[0], scratch[1], scratch[2], scratch[3]);
be16_to_cpu(scratch[1]),
be16_to_cpu(scratch[2]),
be16_to_cpu(scratch[3]));
} }
static void wm_adsp2v2_show_fw_status(struct wm_adsp *dsp) static void wm_adsp2v2_show_fw_status(struct wm_adsp *dsp)
{ {
u32 scratch[2]; unsigned int scratch[2];
int ret; int ret;
ret = regmap_raw_read(dsp->regmap, dsp->base + ADSP2V2_SCRATCH0_1, ret = regmap_read(dsp->regmap, dsp->base + ADSP2V2_SCRATCH0_1,
scratch, sizeof(scratch)); &scratch[0]);
if (ret) { if (ret) {
adsp_err(dsp, "Failed to read SCRATCH regs: %d\n", ret); adsp_err(dsp, "Failed to read SCRATCH0_1: %d\n", ret);
return; return;
} }
scratch[0] = be32_to_cpu(scratch[0]); ret = regmap_read(dsp->regmap, dsp->base + ADSP2V2_SCRATCH2_3,
scratch[1] = be32_to_cpu(scratch[1]); &scratch[1]);
if (ret) {
adsp_err(dsp, "Failed to read SCRATCH2_3: %d\n", ret);
return;
}
adsp_dbg(dsp, "FW SCRATCH 0:0x%x 1:0x%x 2:0x%x 3:0x%x\n", adsp_dbg(dsp, "FW SCRATCH 0:0x%x 1:0x%x 2:0x%x 3:0x%x\n",
scratch[0] & 0xFFFF, scratch[0] & 0xFFFF,

View File

@ -101,22 +101,42 @@ config SND_SST_ATOM_HIFI2_PLATFORM_ACPI
codec, then enable this option by saying Y or m. This is a codec, then enable this option by saying Y or m. This is a
recommended option recommended option
config SND_SOC_INTEL_SKYLAKE_SSP_CLK
tristate
config SND_SOC_INTEL_SKYLAKE config SND_SOC_INTEL_SKYLAKE
tristate "SKL/BXT/KBL/GLK/CNL... Platforms" tristate "SKL/BXT/KBL/GLK/CNL... Platforms"
depends on PCI && ACPI depends on PCI && ACPI
select SND_SOC_INTEL_SKYLAKE_COMMON
help
If you have a Intel Skylake/Broxton/ApolloLake/KabyLake/
GeminiLake or CannonLake platform with the DSP enabled in the BIOS
then enable this option by saying Y or m.
if SND_SOC_INTEL_SKYLAKE
config SND_SOC_INTEL_SKYLAKE_SSP_CLK
tristate
config SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC
bool "HDAudio codec support"
help
If you have a Intel Skylake/Broxton/ApolloLake/KabyLake/
GeminiLake or CannonLake platform with an HDaudio codec
then enable this option by saying Y
config SND_SOC_INTEL_SKYLAKE_COMMON
tristate
select SND_HDA_EXT_CORE select SND_HDA_EXT_CORE
select SND_HDA_DSP_LOADER select SND_HDA_DSP_LOADER
select SND_SOC_TOPOLOGY select SND_SOC_TOPOLOGY
select SND_SOC_INTEL_SST select SND_SOC_INTEL_SST
select SND_SOC_HDAC_HDA if SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC
select SND_SOC_ACPI_INTEL_MATCH select SND_SOC_ACPI_INTEL_MATCH
help help
If you have a Intel Skylake/Broxton/ApolloLake/KabyLake/ If you have a Intel Skylake/Broxton/ApolloLake/KabyLake/
GeminiLake or CannonLake platform with the DSP enabled in the BIOS GeminiLake or CannonLake platform with the DSP enabled in the BIOS
then enable this option by saying Y or m. then enable this option by saying Y or m.
endif ## SND_SOC_INTEL_SKYLAKE
config SND_SOC_ACPI_INTEL_MATCH config SND_SOC_ACPI_INTEL_MATCH
tristate tristate
select SND_SOC_ACPI if ACPI select SND_SOC_ACPI if ACPI

View File

@ -293,16 +293,6 @@ config SND_SOC_INTEL_KBL_DA7219_MAX98927_MACH
Say Y if you have such a device. Say Y if you have such a device.
If unsure select "N". If unsure select "N".
config SND_SOC_INTEL_SKL_HDA_DSP_GENERIC_MACH
tristate "SKL/KBL/BXT/APL with HDA Codecs"
select SND_SOC_HDAC_HDMI
select SND_SOC_HDAC_HDA
help
This adds support for ASoC machine driver for Intel platforms
SKL/KBL/BXT/APL with iDisp, HDA audio codecs.
Say Y or m if you have such a device. This is a recommended option.
If unsure select "N".
config SND_SOC_INTEL_GLK_RT5682_MAX98357A_MACH config SND_SOC_INTEL_GLK_RT5682_MAX98357A_MACH
tristate "GLK with RT5682 and MAX98357A in I2S Mode" tristate "GLK with RT5682 and MAX98357A in I2S Mode"
depends on MFD_INTEL_LPSS && I2C && ACPI depends on MFD_INTEL_LPSS && I2C && ACPI
@ -319,4 +309,18 @@ config SND_SOC_INTEL_GLK_RT5682_MAX98357A_MACH
endif ## SND_SOC_INTEL_SKYLAKE endif ## SND_SOC_INTEL_SKYLAKE
if SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC
config SND_SOC_INTEL_SKL_HDA_DSP_GENERIC_MACH
tristate "SKL/KBL/BXT/APL with HDA Codecs"
select SND_SOC_HDAC_HDMI
# SND_SOC_HDAC_HDA is already selected
help
This adds support for ASoC machine driver for Intel platforms
SKL/KBL/BXT/APL with iDisp, HDA audio codecs.
Say Y or m if you have such a device. This is a recommended option.
If unsure select "N".
endif ## SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC
endif ## SND_SOC_INTEL_MACH endif ## SND_SOC_INTEL_MACH

View File

@ -19,6 +19,7 @@
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/ */
#include <linux/dmi.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/slab.h> #include <linux/slab.h>
@ -35,6 +36,8 @@
#define CHT_PLAT_CLK_3_HZ 19200000 #define CHT_PLAT_CLK_3_HZ 19200000
#define CHT_CODEC_DAI "HiFi" #define CHT_CODEC_DAI "HiFi"
#define QUIRK_PMC_PLT_CLK_0 0x01
struct cht_mc_private { struct cht_mc_private {
struct clk *mclk; struct clk *mclk;
struct snd_soc_jack jack; struct snd_soc_jack jack;
@ -385,11 +388,29 @@ static struct snd_soc_card snd_soc_card_cht = {
.num_controls = ARRAY_SIZE(cht_mc_controls), .num_controls = ARRAY_SIZE(cht_mc_controls),
}; };
static const struct dmi_system_id cht_max98090_quirk_table[] = {
{
/* Swanky model Chromebook (Toshiba Chromebook 2) */
.matches = {
DMI_MATCH(DMI_PRODUCT_NAME, "Swanky"),
},
.driver_data = (void *)QUIRK_PMC_PLT_CLK_0,
},
{}
};
static int snd_cht_mc_probe(struct platform_device *pdev) static int snd_cht_mc_probe(struct platform_device *pdev)
{ {
const struct dmi_system_id *dmi_id;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
int ret_val = 0; int ret_val = 0;
struct cht_mc_private *drv; struct cht_mc_private *drv;
const char *mclk_name;
int quirks = 0;
dmi_id = dmi_first_match(cht_max98090_quirk_table);
if (dmi_id)
quirks = (unsigned long)dmi_id->driver_data;
drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL); drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
if (!drv) if (!drv)
@ -411,11 +432,16 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
snd_soc_card_cht.dev = &pdev->dev; snd_soc_card_cht.dev = &pdev->dev;
snd_soc_card_set_drvdata(&snd_soc_card_cht, drv); snd_soc_card_set_drvdata(&snd_soc_card_cht, drv);
drv->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3"); if (quirks & QUIRK_PMC_PLT_CLK_0)
mclk_name = "pmc_plt_clk_0";
else
mclk_name = "pmc_plt_clk_3";
drv->mclk = devm_clk_get(&pdev->dev, mclk_name);
if (IS_ERR(drv->mclk)) { if (IS_ERR(drv->mclk)) {
dev_err(&pdev->dev, dev_err(&pdev->dev,
"Failed to get MCLK from pmc_plt_clk_3: %ld\n", "Failed to get MCLK from %s: %ld\n",
PTR_ERR(drv->mclk)); mclk_name, PTR_ERR(drv->mclk));
return PTR_ERR(drv->mclk); return PTR_ERR(drv->mclk);
} }

View File

@ -37,7 +37,9 @@
#include "skl.h" #include "skl.h"
#include "skl-sst-dsp.h" #include "skl-sst-dsp.h"
#include "skl-sst-ipc.h" #include "skl-sst-ipc.h"
#if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC)
#include "../../../soc/codecs/hdac_hda.h" #include "../../../soc/codecs/hdac_hda.h"
#endif
/* /*
* initialize the PCI registers * initialize the PCI registers
@ -658,6 +660,8 @@ static void skl_clock_device_unregister(struct skl *skl)
platform_device_unregister(skl->clk_dev); platform_device_unregister(skl->clk_dev);
} }
#if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC)
#define IDISP_INTEL_VENDOR_ID 0x80860000 #define IDISP_INTEL_VENDOR_ID 0x80860000
/* /*
@ -676,6 +680,8 @@ static void load_codec_module(struct hda_codec *codec)
#endif #endif
} }
#endif /* CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC */
/* /*
* Probe the given codec address * Probe the given codec address
*/ */
@ -685,9 +691,11 @@ static int probe_codec(struct hdac_bus *bus, int addr)
(AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID; (AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID;
unsigned int res = -1; unsigned int res = -1;
struct skl *skl = bus_to_skl(bus); struct skl *skl = bus_to_skl(bus);
#if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC)
struct hdac_hda_priv *hda_codec; struct hdac_hda_priv *hda_codec;
struct hdac_device *hdev;
int err; int err;
#endif
struct hdac_device *hdev;
mutex_lock(&bus->cmd_mutex); mutex_lock(&bus->cmd_mutex);
snd_hdac_bus_send_cmd(bus, cmd); snd_hdac_bus_send_cmd(bus, cmd);
@ -697,6 +705,7 @@ static int probe_codec(struct hdac_bus *bus, int addr)
return -EIO; return -EIO;
dev_dbg(bus->dev, "codec #%d probed OK: %x\n", addr, res); dev_dbg(bus->dev, "codec #%d probed OK: %x\n", addr, res);
#if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC)
hda_codec = devm_kzalloc(&skl->pci->dev, sizeof(*hda_codec), hda_codec = devm_kzalloc(&skl->pci->dev, sizeof(*hda_codec),
GFP_KERNEL); GFP_KERNEL);
if (!hda_codec) if (!hda_codec)
@ -715,6 +724,13 @@ static int probe_codec(struct hdac_bus *bus, int addr)
load_codec_module(&hda_codec->codec); load_codec_module(&hda_codec->codec);
} }
return 0; return 0;
#else
hdev = devm_kzalloc(&skl->pci->dev, sizeof(*hdev), GFP_KERNEL);
if (!hdev)
return -ENOMEM;
return snd_hdac_ext_bus_device_init(bus, addr, hdev);
#endif /* CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC */
} }
/* Codec initialization */ /* Codec initialization */
@ -815,6 +831,12 @@ static void skl_probe_work(struct work_struct *work)
} }
} }
/*
* we are done probing so decrement link counts
*/
list_for_each_entry(hlink, &bus->hlink_list, list)
snd_hdac_ext_bus_link_put(bus, hlink);
if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) { if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) {
err = snd_hdac_display_power(bus, false); err = snd_hdac_display_power(bus, false);
if (err < 0) { if (err < 0) {
@ -824,12 +846,6 @@ static void skl_probe_work(struct work_struct *work)
} }
} }
/*
* we are done probing so decrement link counts
*/
list_for_each_entry(hlink, &bus->hlink_list, list)
snd_hdac_ext_bus_link_put(bus, hlink);
/* configure PM */ /* configure PM */
pm_runtime_put_noidle(bus->dev); pm_runtime_put_noidle(bus->dev);
pm_runtime_allow(bus->dev); pm_runtime_allow(bus->dev);
@ -870,7 +886,7 @@ static int skl_create(struct pci_dev *pci,
hbus = skl_to_hbus(skl); hbus = skl_to_hbus(skl);
bus = skl_to_bus(skl); bus = skl_to_bus(skl);
#if IS_ENABLED(CONFIG_SND_SOC_HDAC_HDA) #if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC)
ext_ops = snd_soc_hdac_hda_get_ops(); ext_ops = snd_soc_hdac_hda_get_ops();
#endif #endif
snd_hdac_ext_bus_init(bus, &pci->dev, &bus_core_ops, io_ops, ext_ops); snd_hdac_ext_bus_init(bus, &pci->dev, &bus_core_ops, io_ops, ext_ops);

View File

@ -36,6 +36,8 @@
#include "../codecs/twl6040.h" #include "../codecs/twl6040.h"
struct abe_twl6040 { struct abe_twl6040 {
struct snd_soc_card card;
struct snd_soc_dai_link dai_links[2];
int jack_detection; /* board can detect jack events */ int jack_detection; /* board can detect jack events */
int mclk_freq; /* MCLK frequency speed for twl6040 */ int mclk_freq; /* MCLK frequency speed for twl6040 */
}; };
@ -208,40 +210,10 @@ static int omap_abe_dmic_init(struct snd_soc_pcm_runtime *rtd)
ARRAY_SIZE(dmic_audio_map)); ARRAY_SIZE(dmic_audio_map));
} }
/* Digital audio interface glue - connects codec <--> CPU */
static struct snd_soc_dai_link abe_twl6040_dai_links[] = {
{
.name = "TWL6040",
.stream_name = "TWL6040",
.codec_dai_name = "twl6040-legacy",
.codec_name = "twl6040-codec",
.init = omap_abe_twl6040_init,
.ops = &omap_abe_ops,
},
{
.name = "DMIC",
.stream_name = "DMIC Capture",
.codec_dai_name = "dmic-hifi",
.codec_name = "dmic-codec",
.init = omap_abe_dmic_init,
.ops = &omap_abe_dmic_ops,
},
};
/* Audio machine driver */
static struct snd_soc_card omap_abe_card = {
.owner = THIS_MODULE,
.dapm_widgets = twl6040_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(twl6040_dapm_widgets),
.dapm_routes = audio_map,
.num_dapm_routes = ARRAY_SIZE(audio_map),
};
static int omap_abe_probe(struct platform_device *pdev) static int omap_abe_probe(struct platform_device *pdev)
{ {
struct device_node *node = pdev->dev.of_node; struct device_node *node = pdev->dev.of_node;
struct snd_soc_card *card = &omap_abe_card; struct snd_soc_card *card;
struct device_node *dai_node; struct device_node *dai_node;
struct abe_twl6040 *priv; struct abe_twl6040 *priv;
int num_links = 0; int num_links = 0;
@ -252,12 +224,18 @@ static int omap_abe_probe(struct platform_device *pdev)
return -ENODEV; return -ENODEV;
} }
card->dev = &pdev->dev;
priv = devm_kzalloc(&pdev->dev, sizeof(struct abe_twl6040), GFP_KERNEL); priv = devm_kzalloc(&pdev->dev, sizeof(struct abe_twl6040), GFP_KERNEL);
if (priv == NULL) if (priv == NULL)
return -ENOMEM; return -ENOMEM;
card = &priv->card;
card->dev = &pdev->dev;
card->owner = THIS_MODULE;
card->dapm_widgets = twl6040_dapm_widgets;
card->num_dapm_widgets = ARRAY_SIZE(twl6040_dapm_widgets);
card->dapm_routes = audio_map;
card->num_dapm_routes = ARRAY_SIZE(audio_map);
if (snd_soc_of_parse_card_name(card, "ti,model")) { if (snd_soc_of_parse_card_name(card, "ti,model")) {
dev_err(&pdev->dev, "Card name is not provided\n"); dev_err(&pdev->dev, "Card name is not provided\n");
return -ENODEV; return -ENODEV;
@ -274,14 +252,27 @@ static int omap_abe_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "McPDM node is not provided\n"); dev_err(&pdev->dev, "McPDM node is not provided\n");
return -EINVAL; return -EINVAL;
} }
abe_twl6040_dai_links[0].cpu_of_node = dai_node;
abe_twl6040_dai_links[0].platform_of_node = dai_node; priv->dai_links[0].name = "DMIC";
priv->dai_links[0].stream_name = "TWL6040";
priv->dai_links[0].cpu_of_node = dai_node;
priv->dai_links[0].platform_of_node = dai_node;
priv->dai_links[0].codec_dai_name = "twl6040-legacy";
priv->dai_links[0].codec_name = "twl6040-codec";
priv->dai_links[0].init = omap_abe_twl6040_init;
priv->dai_links[0].ops = &omap_abe_ops;
dai_node = of_parse_phandle(node, "ti,dmic", 0); dai_node = of_parse_phandle(node, "ti,dmic", 0);
if (dai_node) { if (dai_node) {
num_links = 2; num_links = 2;
abe_twl6040_dai_links[1].cpu_of_node = dai_node; priv->dai_links[1].name = "TWL6040";
abe_twl6040_dai_links[1].platform_of_node = dai_node; priv->dai_links[1].stream_name = "DMIC Capture";
priv->dai_links[1].cpu_of_node = dai_node;
priv->dai_links[1].platform_of_node = dai_node;
priv->dai_links[1].codec_dai_name = "dmic-hifi";
priv->dai_links[1].codec_name = "dmic-codec";
priv->dai_links[1].init = omap_abe_dmic_init;
priv->dai_links[1].ops = &omap_abe_dmic_ops;
} else { } else {
num_links = 1; num_links = 1;
} }
@ -300,7 +291,7 @@ static int omap_abe_probe(struct platform_device *pdev)
return -ENODEV; return -ENODEV;
} }
card->dai_link = abe_twl6040_dai_links; card->dai_link = priv->dai_links;
card->num_links = num_links; card->num_links = num_links;
snd_soc_card_set_drvdata(card, priv); snd_soc_card_set_drvdata(card, priv);

View File

@ -48,6 +48,8 @@ struct omap_dmic {
struct device *dev; struct device *dev;
void __iomem *io_base; void __iomem *io_base;
struct clk *fclk; struct clk *fclk;
struct pm_qos_request pm_qos_req;
int latency;
int fclk_freq; int fclk_freq;
int out_freq; int out_freq;
int clk_div; int clk_div;
@ -124,6 +126,8 @@ static void omap_dmic_dai_shutdown(struct snd_pcm_substream *substream,
mutex_lock(&dmic->mutex); mutex_lock(&dmic->mutex);
pm_qos_remove_request(&dmic->pm_qos_req);
if (!dai->active) if (!dai->active)
dmic->active = 0; dmic->active = 0;
@ -228,6 +232,8 @@ static int omap_dmic_dai_hw_params(struct snd_pcm_substream *substream,
/* packet size is threshold * channels */ /* packet size is threshold * channels */
dma_data = snd_soc_dai_get_dma_data(dai, substream); dma_data = snd_soc_dai_get_dma_data(dai, substream);
dma_data->maxburst = dmic->threshold * channels; dma_data->maxburst = dmic->threshold * channels;
dmic->latency = (OMAP_DMIC_THRES_MAX - dmic->threshold) * USEC_PER_SEC /
params_rate(params);
return 0; return 0;
} }
@ -238,6 +244,9 @@ static int omap_dmic_dai_prepare(struct snd_pcm_substream *substream,
struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai); struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
u32 ctrl; u32 ctrl;
if (pm_qos_request_active(&dmic->pm_qos_req))
pm_qos_update_request(&dmic->pm_qos_req, dmic->latency);
/* Configure uplink threshold */ /* Configure uplink threshold */
omap_dmic_write(dmic, OMAP_DMIC_FIFO_CTRL_REG, dmic->threshold); omap_dmic_write(dmic, OMAP_DMIC_FIFO_CTRL_REG, dmic->threshold);

View File

@ -308,9 +308,9 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
pkt_size = channels; pkt_size = channels;
} }
latency = ((((buffer_size - pkt_size) / channels) * 1000) latency = (buffer_size - pkt_size) / channels;
/ (params->rate_num / params->rate_den)); latency = latency * USEC_PER_SEC /
(params->rate_num / params->rate_den);
mcbsp->latency[substream->stream] = latency; mcbsp->latency[substream->stream] = latency;
omap_mcbsp_set_threshold(substream, pkt_size); omap_mcbsp_set_threshold(substream, pkt_size);

View File

@ -54,6 +54,8 @@ struct omap_mcpdm {
unsigned long phys_base; unsigned long phys_base;
void __iomem *io_base; void __iomem *io_base;
int irq; int irq;
struct pm_qos_request pm_qos_req;
int latency[2];
struct mutex mutex; struct mutex mutex;
@ -277,6 +279,9 @@ static void omap_mcpdm_dai_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai) struct snd_soc_dai *dai)
{ {
struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai); struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
int tx = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
int stream1 = tx ? SNDRV_PCM_STREAM_PLAYBACK : SNDRV_PCM_STREAM_CAPTURE;
int stream2 = tx ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
mutex_lock(&mcpdm->mutex); mutex_lock(&mcpdm->mutex);
@ -289,6 +294,14 @@ static void omap_mcpdm_dai_shutdown(struct snd_pcm_substream *substream,
} }
} }
if (mcpdm->latency[stream2])
pm_qos_update_request(&mcpdm->pm_qos_req,
mcpdm->latency[stream2]);
else if (mcpdm->latency[stream1])
pm_qos_remove_request(&mcpdm->pm_qos_req);
mcpdm->latency[stream1] = 0;
mutex_unlock(&mcpdm->mutex); mutex_unlock(&mcpdm->mutex);
} }
@ -300,7 +313,7 @@ static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream,
int stream = substream->stream; int stream = substream->stream;
struct snd_dmaengine_dai_dma_data *dma_data; struct snd_dmaengine_dai_dma_data *dma_data;
u32 threshold; u32 threshold;
int channels; int channels, latency;
int link_mask = 0; int link_mask = 0;
channels = params_channels(params); channels = params_channels(params);
@ -344,14 +357,25 @@ static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream,
dma_data->maxburst = dma_data->maxburst =
(MCPDM_DN_THRES_MAX - threshold) * channels; (MCPDM_DN_THRES_MAX - threshold) * channels;
latency = threshold;
} else { } else {
/* If playback is not running assume a stereo stream to come */ /* If playback is not running assume a stereo stream to come */
if (!mcpdm->config[!stream].link_mask) if (!mcpdm->config[!stream].link_mask)
mcpdm->config[!stream].link_mask = (0x3 << 3); mcpdm->config[!stream].link_mask = (0x3 << 3);
dma_data->maxburst = threshold * channels; dma_data->maxburst = threshold * channels;
latency = (MCPDM_DN_THRES_MAX - threshold);
} }
/*
* The DMA must act to a DMA request within latency time (usec) to avoid
* under/overflow
*/
mcpdm->latency[stream] = latency * USEC_PER_SEC / params_rate(params);
if (!mcpdm->latency[stream])
mcpdm->latency[stream] = 10;
/* Check if we need to restart McPDM with this stream */ /* Check if we need to restart McPDM with this stream */
if (mcpdm->config[stream].link_mask && if (mcpdm->config[stream].link_mask &&
mcpdm->config[stream].link_mask != link_mask) mcpdm->config[stream].link_mask != link_mask)
@ -366,6 +390,20 @@ static int omap_mcpdm_prepare(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai) struct snd_soc_dai *dai)
{ {
struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai); struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
struct pm_qos_request *pm_qos_req = &mcpdm->pm_qos_req;
int tx = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
int stream1 = tx ? SNDRV_PCM_STREAM_PLAYBACK : SNDRV_PCM_STREAM_CAPTURE;
int stream2 = tx ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
int latency = mcpdm->latency[stream2];
/* Prevent omap hardware from hitting off between FIFO fills */
if (!latency || mcpdm->latency[stream1] < latency)
latency = mcpdm->latency[stream1];
if (pm_qos_request_active(pm_qos_req))
pm_qos_update_request(pm_qos_req, latency);
else if (latency)
pm_qos_add_request(pm_qos_req, PM_QOS_CPU_DMA_LATENCY, latency);
if (!omap_mcpdm_active(mcpdm)) { if (!omap_mcpdm_active(mcpdm)) {
omap_mcpdm_start(mcpdm); omap_mcpdm_start(mcpdm);
@ -427,6 +465,9 @@ static int omap_mcpdm_remove(struct snd_soc_dai *dai)
free_irq(mcpdm->irq, (void *)mcpdm); free_irq(mcpdm->irq, (void *)mcpdm);
pm_runtime_disable(mcpdm->dev); pm_runtime_disable(mcpdm->dev);
if (pm_qos_request_active(&mcpdm->pm_qos_req))
pm_qos_remove_request(&mcpdm->pm_qos_req);
return 0; return 0;
} }

View File

@ -13,6 +13,7 @@ int qcom_snd_parse_of(struct snd_soc_card *card)
struct device_node *cpu = NULL; struct device_node *cpu = NULL;
struct device *dev = card->dev; struct device *dev = card->dev;
struct snd_soc_dai_link *link; struct snd_soc_dai_link *link;
struct of_phandle_args args;
int ret, num_links; int ret, num_links;
ret = snd_soc_of_parse_card_name(card, "model"); ret = snd_soc_of_parse_card_name(card, "model");
@ -47,12 +48,14 @@ int qcom_snd_parse_of(struct snd_soc_card *card)
goto err; goto err;
} }
link->cpu_of_node = of_parse_phandle(cpu, "sound-dai", 0); ret = of_parse_phandle_with_args(cpu, "sound-dai",
if (!link->cpu_of_node) { "#sound-dai-cells", 0, &args);
if (ret) {
dev_err(card->dev, "error getting cpu phandle\n"); dev_err(card->dev, "error getting cpu phandle\n");
ret = -EINVAL;
goto err; goto err;
} }
link->cpu_of_node = args.np;
link->id = args.args[0];
ret = snd_soc_of_get_dai_name(cpu, &link->cpu_dai_name); ret = snd_soc_of_get_dai_name(cpu, &link->cpu_dai_name);
if (ret) { if (ret) {

View File

@ -1112,204 +1112,204 @@ static int q6afe_of_xlate_dai_name(struct snd_soc_component *component,
} }
static const struct snd_soc_dapm_widget q6afe_dai_widgets[] = { static const struct snd_soc_dapm_widget q6afe_dai_widgets[] = {
SND_SOC_DAPM_AIF_OUT("HDMI_RX", "HDMI Playback", 0, 0, 0, 0), SND_SOC_DAPM_AIF_IN("HDMI_RX", NULL, 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("SLIMBUS_0_RX", "Slimbus Playback", 0, 0, 0, 0), SND_SOC_DAPM_AIF_IN("SLIMBUS_0_RX", NULL, 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("SLIMBUS_1_RX", "Slimbus1 Playback", 0, 0, 0, 0), SND_SOC_DAPM_AIF_IN("SLIMBUS_1_RX", NULL, 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("SLIMBUS_2_RX", "Slimbus2 Playback", 0, 0, 0, 0), SND_SOC_DAPM_AIF_IN("SLIMBUS_2_RX", NULL, 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("SLIMBUS_3_RX", "Slimbus3 Playback", 0, 0, 0, 0), SND_SOC_DAPM_AIF_IN("SLIMBUS_3_RX", NULL, 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("SLIMBUS_4_RX", "Slimbus4 Playback", 0, 0, 0, 0), SND_SOC_DAPM_AIF_IN("SLIMBUS_4_RX", NULL, 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("SLIMBUS_5_RX", "Slimbus5 Playback", 0, 0, 0, 0), SND_SOC_DAPM_AIF_IN("SLIMBUS_5_RX", NULL, 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("SLIMBUS_6_RX", "Slimbus6 Playback", 0, 0, 0, 0), SND_SOC_DAPM_AIF_IN("SLIMBUS_6_RX", NULL, 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("SLIMBUS_0_TX", "Slimbus Capture", 0, 0, 0, 0), SND_SOC_DAPM_AIF_OUT("SLIMBUS_0_TX", NULL, 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("SLIMBUS_1_TX", "Slimbus1 Capture", 0, 0, 0, 0), SND_SOC_DAPM_AIF_OUT("SLIMBUS_1_TX", NULL, 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("SLIMBUS_2_TX", "Slimbus2 Capture", 0, 0, 0, 0), SND_SOC_DAPM_AIF_OUT("SLIMBUS_2_TX", NULL, 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("SLIMBUS_3_TX", "Slimbus3 Capture", 0, 0, 0, 0), SND_SOC_DAPM_AIF_OUT("SLIMBUS_3_TX", NULL, 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("SLIMBUS_4_TX", "Slimbus4 Capture", 0, 0, 0, 0), SND_SOC_DAPM_AIF_OUT("SLIMBUS_4_TX", NULL, 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("SLIMBUS_5_TX", "Slimbus5 Capture", 0, 0, 0, 0), SND_SOC_DAPM_AIF_OUT("SLIMBUS_5_TX", NULL, 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("SLIMBUS_6_TX", "Slimbus6 Capture", 0, 0, 0, 0), SND_SOC_DAPM_AIF_OUT("SLIMBUS_6_TX", NULL, 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("QUAT_MI2S_RX", "Quaternary MI2S Playback", SND_SOC_DAPM_AIF_IN("QUAT_MI2S_RX", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("QUAT_MI2S_TX", "Quaternary MI2S Capture", SND_SOC_DAPM_AIF_OUT("QUAT_MI2S_TX", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("TERT_MI2S_RX", "Tertiary MI2S Playback", SND_SOC_DAPM_AIF_IN("TERT_MI2S_RX", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("TERT_MI2S_TX", "Tertiary MI2S Capture", SND_SOC_DAPM_AIF_OUT("TERT_MI2S_TX", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("SEC_MI2S_RX", "Secondary MI2S Playback", SND_SOC_DAPM_AIF_IN("SEC_MI2S_RX", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("SEC_MI2S_TX", "Secondary MI2S Capture", SND_SOC_DAPM_AIF_OUT("SEC_MI2S_TX", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("SEC_MI2S_RX_SD1", SND_SOC_DAPM_AIF_IN("SEC_MI2S_RX_SD1",
"Secondary MI2S Playback SD1", "Secondary MI2S Playback SD1",
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("PRI_MI2S_RX", "Primary MI2S Playback", SND_SOC_DAPM_AIF_IN("PRI_MI2S_RX", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("PRI_MI2S_TX", "Primary MI2S Capture", SND_SOC_DAPM_AIF_OUT("PRI_MI2S_TX", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_RX_0", "Primary TDM0 Playback", SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_0", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_RX_1", "Primary TDM1 Playback", SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_1", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_RX_2", "Primary TDM2 Playback", SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_2", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_RX_3", "Primary TDM3 Playback", SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_3", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_RX_4", "Primary TDM4 Playback", SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_4", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_RX_5", "Primary TDM5 Playback", SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_5", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_RX_6", "Primary TDM6 Playback", SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_6", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_RX_7", "Primary TDM7 Playback", SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_7", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_TX_0", "Primary TDM0 Capture", SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_0", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_TX_1", "Primary TDM1 Capture", SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_1", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_TX_2", "Primary TDM2 Capture", SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_2", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_TX_3", "Primary TDM3 Capture", SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_3", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_TX_4", "Primary TDM4 Capture", SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_4", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_TX_5", "Primary TDM5 Capture", SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_5", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_TX_6", "Primary TDM6 Capture", SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_6", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_TX_7", "Primary TDM7 Capture", SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_7", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("SEC_TDM_RX_0", "Secondary TDM0 Playback", SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_0", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("SEC_TDM_RX_1", "Secondary TDM1 Playback", SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_1", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("SEC_TDM_RX_2", "Secondary TDM2 Playback", SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_2", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("SEC_TDM_RX_3", "Secondary TDM3 Playback", SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_3", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("SEC_TDM_RX_4", "Secondary TDM4 Playback", SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_4", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("SEC_TDM_RX_5", "Secondary TDM5 Playback", SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_5", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("SEC_TDM_RX_6", "Secondary TDM6 Playback", SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_6", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("SEC_TDM_RX_7", "Secondary TDM7 Playback", SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_7", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("SEC_TDM_TX_0", "Secondary TDM0 Capture", SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_0", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("SEC_TDM_TX_1", "Secondary TDM1 Capture", SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_1", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("SEC_TDM_TX_2", "Secondary TDM2 Capture", SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_2", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("SEC_TDM_TX_3", "Secondary TDM3 Capture", SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_3", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("SEC_TDM_TX_4", "Secondary TDM4 Capture", SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_4", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("SEC_TDM_TX_5", "Secondary TDM5 Capture", SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_5", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("SEC_TDM_TX_6", "Secondary TDM6 Capture", SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_6", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("SEC_TDM_TX_7", "Secondary TDM7 Capture", SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_7", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("TERT_TDM_RX_0", "Tertiary TDM0 Playback", SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_0", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("TERT_TDM_RX_1", "Tertiary TDM1 Playback", SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_1", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("TERT_TDM_RX_2", "Tertiary TDM2 Playback", SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_2", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("TERT_TDM_RX_3", "Tertiary TDM3 Playback", SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_3", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("TERT_TDM_RX_4", "Tertiary TDM4 Playback", SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_4", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("TERT_TDM_RX_5", "Tertiary TDM5 Playback", SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_5", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("TERT_TDM_RX_6", "Tertiary TDM6 Playback", SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_6", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("TERT_TDM_RX_7", "Tertiary TDM7 Playback", SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_7", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("TERT_TDM_TX_0", "Tertiary TDM0 Capture", SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_0", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("TERT_TDM_TX_1", "Tertiary TDM1 Capture", SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_1", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("TERT_TDM_TX_2", "Tertiary TDM2 Capture", SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_2", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("TERT_TDM_TX_3", "Tertiary TDM3 Capture", SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_3", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("TERT_TDM_TX_4", "Tertiary TDM4 Capture", SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_4", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("TERT_TDM_TX_5", "Tertiary TDM5 Capture", SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_5", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("TERT_TDM_TX_6", "Tertiary TDM6 Capture", SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_6", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("TERT_TDM_TX_7", "Tertiary TDM7 Capture", SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_7", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("QUAT_TDM_RX_0", "Quaternary TDM0 Playback", SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_0", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("QUAT_TDM_RX_1", "Quaternary TDM1 Playback", SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_1", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("QUAT_TDM_RX_2", "Quaternary TDM2 Playback", SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_2", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("QUAT_TDM_RX_3", "Quaternary TDM3 Playback", SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_3", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("QUAT_TDM_RX_4", "Quaternary TDM4 Playback", SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_4", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("QUAT_TDM_RX_5", "Quaternary TDM5 Playback", SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_5", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("QUAT_TDM_RX_6", "Quaternary TDM6 Playback", SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_6", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("QUAT_TDM_RX_7", "Quaternary TDM7 Playback", SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_7", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("QUAT_TDM_TX_0", "Quaternary TDM0 Capture", SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_0", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("QUAT_TDM_TX_1", "Quaternary TDM1 Capture", SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_1", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("QUAT_TDM_TX_2", "Quaternary TDM2 Capture", SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_2", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("QUAT_TDM_TX_3", "Quaternary TDM3 Capture", SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_3", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("QUAT_TDM_TX_4", "Quaternary TDM4 Capture", SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_4", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("QUAT_TDM_TX_5", "Quaternary TDM5 Capture", SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_5", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("QUAT_TDM_TX_6", "Quaternary TDM6 Capture", SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_6", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("QUAT_TDM_TX_7", "Quaternary TDM7 Capture", SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_7", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("QUIN_TDM_RX_0", "Quinary TDM0 Playback", SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_0", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("QUIN_TDM_RX_1", "Quinary TDM1 Playback", SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_1", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("QUIN_TDM_RX_2", "Quinary TDM2 Playback", SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_2", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("QUIN_TDM_RX_3", "Quinary TDM3 Playback", SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_3", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("QUIN_TDM_RX_4", "Quinary TDM4 Playback", SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_4", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("QUIN_TDM_RX_5", "Quinary TDM5 Playback", SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_5", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("QUIN_TDM_RX_6", "Quinary TDM6 Playback", SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_6", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("QUIN_TDM_RX_7", "Quinary TDM7 Playback", SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_7", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("QUIN_TDM_TX_0", "Quinary TDM0 Capture", SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_0", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("QUIN_TDM_TX_1", "Quinary TDM1 Capture", SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_1", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("QUIN_TDM_TX_2", "Quinary TDM2 Capture", SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_2", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("QUIN_TDM_TX_3", "Quinary TDM3 Capture", SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_3", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("QUIN_TDM_TX_4", "Quinary TDM4 Capture", SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_4", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("QUIN_TDM_TX_5", "Quinary TDM5 Capture", SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_5", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("QUIN_TDM_TX_6", "Quinary TDM6 Capture", SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_6", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("QUIN_TDM_TX_7", "Quinary TDM7 Capture", SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_7", NULL,
0, 0, 0, 0), 0, 0, 0, 0),
}; };

View File

@ -49,14 +49,14 @@
#define AFE_PORT_I2S_SD1 0x2 #define AFE_PORT_I2S_SD1 0x2
#define AFE_PORT_I2S_SD2 0x3 #define AFE_PORT_I2S_SD2 0x3
#define AFE_PORT_I2S_SD3 0x4 #define AFE_PORT_I2S_SD3 0x4
#define AFE_PORT_I2S_SD0_MASK BIT(0x1) #define AFE_PORT_I2S_SD0_MASK BIT(0x0)
#define AFE_PORT_I2S_SD1_MASK BIT(0x2) #define AFE_PORT_I2S_SD1_MASK BIT(0x1)
#define AFE_PORT_I2S_SD2_MASK BIT(0x3) #define AFE_PORT_I2S_SD2_MASK BIT(0x2)
#define AFE_PORT_I2S_SD3_MASK BIT(0x4) #define AFE_PORT_I2S_SD3_MASK BIT(0x3)
#define AFE_PORT_I2S_SD0_1_MASK GENMASK(2, 1) #define AFE_PORT_I2S_SD0_1_MASK GENMASK(1, 0)
#define AFE_PORT_I2S_SD2_3_MASK GENMASK(4, 3) #define AFE_PORT_I2S_SD2_3_MASK GENMASK(3, 2)
#define AFE_PORT_I2S_SD0_1_2_MASK GENMASK(3, 1) #define AFE_PORT_I2S_SD0_1_2_MASK GENMASK(2, 0)
#define AFE_PORT_I2S_SD0_1_2_3_MASK GENMASK(4, 1) #define AFE_PORT_I2S_SD0_1_2_3_MASK GENMASK(3, 0)
#define AFE_PORT_I2S_QUAD01 0x5 #define AFE_PORT_I2S_QUAD01 0x5
#define AFE_PORT_I2S_QUAD23 0x6 #define AFE_PORT_I2S_QUAD23 0x6
#define AFE_PORT_I2S_6CHS 0x7 #define AFE_PORT_I2S_6CHS 0x7

View File

@ -122,7 +122,6 @@ static struct snd_pcm_hardware q6asm_dai_hardware_playback = {
.rate_max = 48000, \ .rate_max = 48000, \
}, \ }, \
.name = "MultiMedia"#num, \ .name = "MultiMedia"#num, \
.probe = fe_dai_probe, \
.id = MSM_FRONTEND_DAI_MULTIMEDIA##num, \ .id = MSM_FRONTEND_DAI_MULTIMEDIA##num, \
} }
@ -511,38 +510,6 @@ static void q6asm_dai_pcm_free(struct snd_pcm *pcm)
} }
} }
static const struct snd_soc_dapm_route afe_pcm_routes[] = {
{"MM_DL1", NULL, "MultiMedia1 Playback" },
{"MM_DL2", NULL, "MultiMedia2 Playback" },
{"MM_DL3", NULL, "MultiMedia3 Playback" },
{"MM_DL4", NULL, "MultiMedia4 Playback" },
{"MM_DL5", NULL, "MultiMedia5 Playback" },
{"MM_DL6", NULL, "MultiMedia6 Playback" },
{"MM_DL7", NULL, "MultiMedia7 Playback" },
{"MM_DL7", NULL, "MultiMedia8 Playback" },
{"MultiMedia1 Capture", NULL, "MM_UL1"},
{"MultiMedia2 Capture", NULL, "MM_UL2"},
{"MultiMedia3 Capture", NULL, "MM_UL3"},
{"MultiMedia4 Capture", NULL, "MM_UL4"},
{"MultiMedia5 Capture", NULL, "MM_UL5"},
{"MultiMedia6 Capture", NULL, "MM_UL6"},
{"MultiMedia7 Capture", NULL, "MM_UL7"},
{"MultiMedia8 Capture", NULL, "MM_UL8"},
};
static int fe_dai_probe(struct snd_soc_dai *dai)
{
struct snd_soc_dapm_context *dapm;
dapm = snd_soc_component_get_dapm(dai->component);
snd_soc_dapm_add_routes(dapm, afe_pcm_routes,
ARRAY_SIZE(afe_pcm_routes));
return 0;
}
static const struct snd_soc_component_driver q6asm_fe_dai_component = { static const struct snd_soc_component_driver q6asm_fe_dai_component = {
.name = DRV_NAME, .name = DRV_NAME,
.ops = &q6asm_dai_ops, .ops = &q6asm_dai_ops,

View File

@ -909,6 +909,25 @@ static const struct snd_soc_dapm_route intercon[] = {
{"MM_UL6", NULL, "MultiMedia6 Mixer"}, {"MM_UL6", NULL, "MultiMedia6 Mixer"},
{"MM_UL7", NULL, "MultiMedia7 Mixer"}, {"MM_UL7", NULL, "MultiMedia7 Mixer"},
{"MM_UL8", NULL, "MultiMedia8 Mixer"}, {"MM_UL8", NULL, "MultiMedia8 Mixer"},
{"MM_DL1", NULL, "MultiMedia1 Playback" },
{"MM_DL2", NULL, "MultiMedia2 Playback" },
{"MM_DL3", NULL, "MultiMedia3 Playback" },
{"MM_DL4", NULL, "MultiMedia4 Playback" },
{"MM_DL5", NULL, "MultiMedia5 Playback" },
{"MM_DL6", NULL, "MultiMedia6 Playback" },
{"MM_DL7", NULL, "MultiMedia7 Playback" },
{"MM_DL8", NULL, "MultiMedia8 Playback" },
{"MultiMedia1 Capture", NULL, "MM_UL1"},
{"MultiMedia2 Capture", NULL, "MM_UL2"},
{"MultiMedia3 Capture", NULL, "MM_UL3"},
{"MultiMedia4 Capture", NULL, "MM_UL4"},
{"MultiMedia5 Capture", NULL, "MM_UL5"},
{"MultiMedia6 Capture", NULL, "MM_UL6"},
{"MultiMedia7 Capture", NULL, "MM_UL7"},
{"MultiMedia8 Capture", NULL, "MM_UL8"},
}; };
static int routing_hw_params(struct snd_pcm_substream *substream, static int routing_hw_params(struct snd_pcm_substream *substream,

View File

@ -33,6 +33,7 @@ static const struct snd_pcm_hardware snd_rockchip_hardware = {
static const struct snd_dmaengine_pcm_config rk_dmaengine_pcm_config = { static const struct snd_dmaengine_pcm_config rk_dmaengine_pcm_config = {
.pcm_hardware = &snd_rockchip_hardware, .pcm_hardware = &snd_rockchip_hardware,
.prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
.prealloc_buffer_size = 32 * 1024, .prealloc_buffer_size = 32 * 1024,
}; };

View File

@ -306,7 +306,7 @@ static int rsnd_ssi_master_clk_start(struct rsnd_mod *mod,
if (rsnd_ssi_is_multi_slave(mod, io)) if (rsnd_ssi_is_multi_slave(mod, io))
return 0; return 0;
if (ssi->rate) { if (ssi->usrcnt > 1) {
if (ssi->rate != rate) { if (ssi->rate != rate) {
dev_err(dev, "SSI parent/child should use same rate\n"); dev_err(dev, "SSI parent/child should use same rate\n");
return -EINVAL; return -EINVAL;

View File

@ -10,11 +10,17 @@ struct snd_soc_acpi_mach *
snd_soc_acpi_find_machine(struct snd_soc_acpi_mach *machines) snd_soc_acpi_find_machine(struct snd_soc_acpi_mach *machines)
{ {
struct snd_soc_acpi_mach *mach; struct snd_soc_acpi_mach *mach;
struct snd_soc_acpi_mach *mach_alt;
for (mach = machines; mach->id[0]; mach++) { for (mach = machines; mach->id[0]; mach++) {
if (acpi_dev_present(mach->id, NULL, -1)) { if (acpi_dev_present(mach->id, NULL, -1)) {
if (mach->machine_quirk) if (mach->machine_quirk) {
mach = mach->machine_quirk(mach); mach_alt = mach->machine_quirk(mach);
if (!mach_alt)
continue; /* not full match, ignore */
mach = mach_alt;
}
return mach; return mach;
} }
} }

View File

@ -2131,6 +2131,7 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
} }
card->instantiated = 1; card->instantiated = 1;
dapm_mark_endpoints_dirty(card);
snd_soc_dapm_sync(&card->dapm); snd_soc_dapm_sync(&card->dapm);
mutex_unlock(&card->mutex); mutex_unlock(&card->mutex);
mutex_unlock(&client_mutex); mutex_unlock(&client_mutex);

View File

@ -390,7 +390,7 @@ static int stm32_sai_add_mclk_provider(struct stm32_sai_sub_data *sai)
char *mclk_name, *p, *s = (char *)pname; char *mclk_name, *p, *s = (char *)pname;
int ret, i = 0; int ret, i = 0;
mclk = devm_kzalloc(dev, sizeof(mclk), GFP_KERNEL); mclk = devm_kzalloc(dev, sizeof(*mclk), GFP_KERNEL);
if (!mclk) if (!mclk)
return -ENOMEM; return -ENOMEM;

View File

@ -31,7 +31,7 @@ config SND_SUN8I_CODEC_ANALOG
config SND_SUN50I_CODEC_ANALOG config SND_SUN50I_CODEC_ANALOG
tristate "Allwinner sun50i Codec Analog Controls Support" tristate "Allwinner sun50i Codec Analog Controls Support"
depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
select SND_SUNXI_ADDA_PR_REGMAP select SND_SUN8I_ADDA_PR_REGMAP
help help
Say Y or M if you want to add support for the analog controls for Say Y or M if you want to add support for the analog controls for
the codec embedded in Allwinner A64 SoC. the codec embedded in Allwinner A64 SoC.

View File

@ -481,7 +481,11 @@ static const struct snd_soc_dapm_route sun8i_codec_dapm_routes[] = {
{ "Right Digital DAC Mixer", "AIF1 Slot 0 Digital DAC Playback Switch", { "Right Digital DAC Mixer", "AIF1 Slot 0 Digital DAC Playback Switch",
"AIF1 Slot 0 Right"}, "AIF1 Slot 0 Right"},
/* ADC routes */ /* ADC Routes */
{ "AIF1 Slot 0 Right ADC", NULL, "ADC" },
{ "AIF1 Slot 0 Left ADC", NULL, "ADC" },
/* ADC Mixer Routes */
{ "Left Digital ADC Mixer", "AIF1 Data Digital ADC Capture Switch", { "Left Digital ADC Mixer", "AIF1 Data Digital ADC Capture Switch",
"AIF1 Slot 0 Left ADC" }, "AIF1 Slot 0 Left ADC" },
{ "Right Digital ADC Mixer", "AIF1 Data Digital ADC Capture Switch", { "Right Digital ADC Mixer", "AIF1 Data Digital ADC Capture Switch",
@ -605,16 +609,10 @@ err_pm_disable:
static int sun8i_codec_remove(struct platform_device *pdev) static int sun8i_codec_remove(struct platform_device *pdev)
{ {
struct snd_soc_card *card = platform_get_drvdata(pdev);
struct sun8i_codec *scodec = snd_soc_card_get_drvdata(card);
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
if (!pm_runtime_status_suspended(&pdev->dev)) if (!pm_runtime_status_suspended(&pdev->dev))
sun8i_codec_runtime_suspend(&pdev->dev); sun8i_codec_runtime_suspend(&pdev->dev);
clk_disable_unprepare(scodec->clk_module);
clk_disable_unprepare(scodec->clk_bus);
return 0; return 0;
} }

View File

@ -682,9 +682,12 @@ static int usb_audio_probe(struct usb_interface *intf,
__error: __error:
if (chip) { if (chip) {
/* chip->active is inside the chip->card object,
* decrement before memory is possibly returned.
*/
atomic_dec(&chip->active);
if (!chip->num_interfaces) if (!chip->num_interfaces)
snd_card_free(chip->card); snd_card_free(chip->card);
atomic_dec(&chip->active);
} }
mutex_unlock(&register_mutex); mutex_unlock(&register_mutex);
return err; return err;

View File

@ -3382,5 +3382,15 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"),
.ifnum = QUIRK_NO_INTERFACE .ifnum = QUIRK_NO_INTERFACE
} }
}, },
/* Dell WD19 Dock */
{
USB_DEVICE(0x0bda, 0x402e),
.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "Dell",
.product_name = "WD19 Dock",
.profile_name = "Dell-WD15-Dock",
.ifnum = QUIRK_NO_INTERFACE
}
},
#undef USB_DEVICE_VENDOR_SPEC #undef USB_DEVICE_VENDOR_SPEC

View File

@ -1492,6 +1492,7 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
return SNDRV_PCM_FMTBIT_DSD_U32_BE; return SNDRV_PCM_FMTBIT_DSD_U32_BE;
break; break;
case USB_ID(0x152a, 0x85de): /* SMSL D1 DAC */
case USB_ID(0x16d0, 0x09dd): /* Encore mDSD */ case USB_ID(0x16d0, 0x09dd): /* Encore mDSD */
case USB_ID(0x0d8c, 0x0316): /* Hegel HD12 DSD */ case USB_ID(0x0d8c, 0x0316): /* Hegel HD12 DSD */
case USB_ID(0x16b0, 0x06b2): /* NuPrime DAC-10 */ case USB_ID(0x16b0, 0x06b2): /* NuPrime DAC-10 */