Commit 39e4edfd authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'sound-4.12-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound

Pull sound fixes from Takashi Iwai:
 "This update contains a slightly hight amount of changes due to the
  pending ASoC fixes:

   - ALSA timer core got a couple of fixes for races between read and
     ioctl, leading to potential read of uninitialized kmalloced memory

   - ASoC core fixed the de-registration pattern for use-after-free bug

   - The rewrite of probe code in ASoC Intel Skylake for i915 component

   - ASoC R-snd got a series of fixes for SSI

   - ASoC simple-card, atmel, da7213, and rt286 trivial fixes

   - HD-audio ALC269 quirk and rearrangement of quirk table"

* tag 'sound-4.12-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound:
  ALSA: timer: Fix missing queue indices reset at SNDRV_TIMER_IOCTL_SELECT
  ALSA: timer: Fix race between read and ioctl
  ALSA: hda/realtek - Reorder ALC269 ASUS quirk entries
  ALSA: hda/realtek: Fix mic and headset jack sense on Asus X705UD
  ASoC: rsnd: fixup parent_clk_name of AUDIO_CLKOUTx
  ASoC: Intel: Skylake: Fix to parse consecutive string tkns in manifest
  ASoC: Intel: Skylake: Fix IPC rx_list corruption
  ASoC: rsnd: SSI PIO adjust to 24bit mode
  MAINTAINERS: Update email address for patches to Wolfson parts
  ASoC: Fix use-after-free at card unregistration
  ASoC: simple-card: fix mic jack initialization
  ASoC: rsnd: don't call free_irq() on Parent SSI
  ASoC: atmel-classd: sync regcache when resuming
  ASoC: rsnd: don't use PDTA bit for 24bit on SSI
  ASoC: da7213: Fix incorrect usage of bitwise '&' operator for SRM check
  rt286: add Thinkpad Helix 2 to force_combo_jack_table
  ASoC: Intel: Skylake: Move i915 registration to worker thread
parents 6107cc58 ba3021b2
...@@ -13861,7 +13861,7 @@ S: Odd fixes ...@@ -13861,7 +13861,7 @@ S: Odd fixes
F: drivers/net/wireless/wl3501* F: drivers/net/wireless/wl3501*
WOLFSON MICROELECTRONICS DRIVERS WOLFSON MICROELECTRONICS DRIVERS
L: patches@opensource.wolfsonmicro.com L: patches@opensource.cirrus.com
T: git https://github.com/CirrusLogic/linux-drivers.git T: git https://github.com/CirrusLogic/linux-drivers.git
W: https://github.com/CirrusLogic/linux-drivers/wiki W: https://github.com/CirrusLogic/linux-drivers/wiki
S: Supported S: Supported
......
...@@ -1618,6 +1618,7 @@ static int snd_timer_user_tselect(struct file *file, ...@@ -1618,6 +1618,7 @@ static int snd_timer_user_tselect(struct file *file,
if (err < 0) if (err < 0)
goto __err; goto __err;
tu->qhead = tu->qtail = tu->qused = 0;
kfree(tu->queue); kfree(tu->queue);
tu->queue = NULL; tu->queue = NULL;
kfree(tu->tqueue); kfree(tu->tqueue);
...@@ -1959,6 +1960,7 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, ...@@ -1959,6 +1960,7 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer,
tu = file->private_data; tu = file->private_data;
unit = tu->tread ? sizeof(struct snd_timer_tread) : sizeof(struct snd_timer_read); unit = tu->tread ? sizeof(struct snd_timer_tread) : sizeof(struct snd_timer_read);
mutex_lock(&tu->ioctl_lock);
spin_lock_irq(&tu->qlock); spin_lock_irq(&tu->qlock);
while ((long)count - result >= unit) { while ((long)count - result >= unit) {
while (!tu->qused) { while (!tu->qused) {
...@@ -1974,7 +1976,9 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, ...@@ -1974,7 +1976,9 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer,
add_wait_queue(&tu->qchange_sleep, &wait); add_wait_queue(&tu->qchange_sleep, &wait);
spin_unlock_irq(&tu->qlock); spin_unlock_irq(&tu->qlock);
mutex_unlock(&tu->ioctl_lock);
schedule(); schedule();
mutex_lock(&tu->ioctl_lock);
spin_lock_irq(&tu->qlock); spin_lock_irq(&tu->qlock);
remove_wait_queue(&tu->qchange_sleep, &wait); remove_wait_queue(&tu->qchange_sleep, &wait);
...@@ -1994,7 +1998,6 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, ...@@ -1994,7 +1998,6 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer,
tu->qused--; tu->qused--;
spin_unlock_irq(&tu->qlock); spin_unlock_irq(&tu->qlock);
mutex_lock(&tu->ioctl_lock);
if (tu->tread) { if (tu->tread) {
if (copy_to_user(buffer, &tu->tqueue[qhead], if (copy_to_user(buffer, &tu->tqueue[qhead],
sizeof(struct snd_timer_tread))) sizeof(struct snd_timer_tread)))
...@@ -2004,7 +2007,6 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, ...@@ -2004,7 +2007,6 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer,
sizeof(struct snd_timer_read))) sizeof(struct snd_timer_read)))
err = -EFAULT; err = -EFAULT;
} }
mutex_unlock(&tu->ioctl_lock);
spin_lock_irq(&tu->qlock); spin_lock_irq(&tu->qlock);
if (err < 0) if (err < 0)
...@@ -2014,6 +2016,7 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, ...@@ -2014,6 +2016,7 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer,
} }
_error: _error:
spin_unlock_irq(&tu->qlock); spin_unlock_irq(&tu->qlock);
mutex_unlock(&tu->ioctl_lock);
return result > 0 ? result : err; return result > 0 ? result : err;
} }
......
...@@ -5854,7 +5854,11 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { ...@@ -5854,7 +5854,11 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300), SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300),
SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
SND_PCI_QUIRK(0x1043, 0x10c0, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC), SND_PCI_QUIRK(0x1043, 0x10c0, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC),
SND_PCI_QUIRK(0x1043, 0x10d0, "ASUS X540LA/X540LJ", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1043, 0x115d, "Asus 1015E", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), SND_PCI_QUIRK(0x1043, 0x115d, "Asus 1015E", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
SND_PCI_QUIRK(0x1043, 0x11c0, "ASUS X556UR", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1043, 0x1290, "ASUS X441SA", ALC233_FIXUP_EAPD_COEF_AND_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1043, 0x12a0, "ASUS X441UV", ALC233_FIXUP_EAPD_COEF_AND_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1043, 0x12f0, "ASUS X541UV", ALC256_FIXUP_ASUS_MIC), SND_PCI_QUIRK(0x1043, 0x12f0, "ASUS X541UV", ALC256_FIXUP_ASUS_MIC),
SND_PCI_QUIRK(0x1043, 0x12e0, "ASUS X541SA", ALC256_FIXUP_ASUS_MIC), SND_PCI_QUIRK(0x1043, 0x12e0, "ASUS X541SA", ALC256_FIXUP_ASUS_MIC),
SND_PCI_QUIRK(0x1043, 0x13b0, "ASUS Z550SA", ALC256_FIXUP_ASUS_MIC), SND_PCI_QUIRK(0x1043, 0x13b0, "ASUS Z550SA", ALC256_FIXUP_ASUS_MIC),
...@@ -5862,13 +5866,10 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { ...@@ -5862,13 +5866,10 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x1517, "Asus Zenbook UX31A", ALC269VB_FIXUP_ASUS_ZENBOOK_UX31A), SND_PCI_QUIRK(0x1043, 0x1517, "Asus Zenbook UX31A", ALC269VB_FIXUP_ASUS_ZENBOOK_UX31A),
SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC), SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC),
SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW), SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
SND_PCI_QUIRK(0x1043, 0x1a30, "ASUS X705UD", ALC256_FIXUP_ASUS_MIC),
SND_PCI_QUIRK(0x1043, 0x1b13, "Asus U41SV", ALC269_FIXUP_INV_DMIC), SND_PCI_QUIRK(0x1043, 0x1b13, "Asus U41SV", ALC269_FIXUP_INV_DMIC),
SND_PCI_QUIRK(0x1043, 0x1c23, "Asus X55U", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
SND_PCI_QUIRK(0x1043, 0x1bbd, "ASUS Z550MA", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1043, 0x1bbd, "ASUS Z550MA", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1043, 0x10d0, "ASUS X540LA/X540LJ", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1043, 0x1c23, "Asus X55U", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
SND_PCI_QUIRK(0x1043, 0x11c0, "ASUS X556UR", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1043, 0x1290, "ASUS X441SA", ALC233_FIXUP_EAPD_COEF_AND_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1043, 0x12a0, "ASUS X441UV", ALC233_FIXUP_EAPD_COEF_AND_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1043, 0x1ccd, "ASUS X555UB", ALC256_FIXUP_ASUS_MIC), SND_PCI_QUIRK(0x1043, 0x1ccd, "ASUS X555UB", ALC256_FIXUP_ASUS_MIC),
SND_PCI_QUIRK(0x1043, 0x3030, "ASUS ZN270IE", ALC256_FIXUP_ASUS_AIO_GPIO2), SND_PCI_QUIRK(0x1043, 0x3030, "ASUS ZN270IE", ALC256_FIXUP_ASUS_AIO_GPIO2),
SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC), SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC),
......
...@@ -301,6 +301,14 @@ static int atmel_classd_codec_probe(struct snd_soc_codec *codec) ...@@ -301,6 +301,14 @@ static int atmel_classd_codec_probe(struct snd_soc_codec *codec)
return 0; return 0;
} }
static int atmel_classd_codec_resume(struct snd_soc_codec *codec)
{
struct snd_soc_card *card = snd_soc_codec_get_drvdata(codec);
struct atmel_classd *dd = snd_soc_card_get_drvdata(card);
return regcache_sync(dd->regmap);
}
static struct regmap *atmel_classd_codec_get_remap(struct device *dev) static struct regmap *atmel_classd_codec_get_remap(struct device *dev)
{ {
return dev_get_regmap(dev, NULL); return dev_get_regmap(dev, NULL);
...@@ -308,6 +316,7 @@ static struct regmap *atmel_classd_codec_get_remap(struct device *dev) ...@@ -308,6 +316,7 @@ static struct regmap *atmel_classd_codec_get_remap(struct device *dev)
static struct snd_soc_codec_driver soc_codec_dev_classd = { static struct snd_soc_codec_driver soc_codec_dev_classd = {
.probe = atmel_classd_codec_probe, .probe = atmel_classd_codec_probe,
.resume = atmel_classd_codec_resume,
.get_regmap = atmel_classd_codec_get_remap, .get_regmap = atmel_classd_codec_get_remap,
.component_driver = { .component_driver = {
.controls = atmel_classd_snd_controls, .controls = atmel_classd_snd_controls,
......
...@@ -772,7 +772,7 @@ static int da7213_dai_event(struct snd_soc_dapm_widget *w, ...@@ -772,7 +772,7 @@ static int da7213_dai_event(struct snd_soc_dapm_widget *w,
++i; ++i;
msleep(50); msleep(50);
} }
} while ((i < DA7213_SRM_CHECK_RETRIES) & (!srm_lock)); } while ((i < DA7213_SRM_CHECK_RETRIES) && (!srm_lock));
if (!srm_lock) if (!srm_lock)
dev_warn(codec->dev, "SRM failed to lock\n"); dev_warn(codec->dev, "SRM failed to lock\n");
......
...@@ -1108,6 +1108,13 @@ static const struct dmi_system_id force_combo_jack_table[] = { ...@@ -1108,6 +1108,13 @@ static const struct dmi_system_id force_combo_jack_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "Kabylake Client platform") DMI_MATCH(DMI_PRODUCT_NAME, "Kabylake Client platform")
} }
}, },
{
.ident = "Thinkpad Helix 2nd",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad Helix 2nd")
}
},
{ } { }
}; };
......
...@@ -202,7 +202,7 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) ...@@ -202,7 +202,7 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd)
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = asoc_simple_card_init_mic(rtd->card, &priv->hp_jack, PREFIX); ret = asoc_simple_card_init_mic(rtd->card, &priv->mic_jack, PREFIX);
if (ret < 0) if (ret < 0)
return ret; return ret;
......
...@@ -413,8 +413,11 @@ static void skl_ipc_process_reply(struct sst_generic_ipc *ipc, ...@@ -413,8 +413,11 @@ static void skl_ipc_process_reply(struct sst_generic_ipc *ipc,
u32 reply = header.primary & IPC_GLB_REPLY_STATUS_MASK; u32 reply = header.primary & IPC_GLB_REPLY_STATUS_MASK;
u64 *ipc_header = (u64 *)(&header); u64 *ipc_header = (u64 *)(&header);
struct skl_sst *skl = container_of(ipc, struct skl_sst, ipc); struct skl_sst *skl = container_of(ipc, struct skl_sst, ipc);
unsigned long flags;
spin_lock_irqsave(&ipc->dsp->spinlock, flags);
msg = skl_ipc_reply_get_msg(ipc, *ipc_header); msg = skl_ipc_reply_get_msg(ipc, *ipc_header);
spin_unlock_irqrestore(&ipc->dsp->spinlock, flags);
if (msg == NULL) { if (msg == NULL) {
dev_dbg(ipc->dev, "ipc: rx list is empty\n"); dev_dbg(ipc->dev, "ipc: rx list is empty\n");
return; return;
...@@ -456,8 +459,10 @@ static void skl_ipc_process_reply(struct sst_generic_ipc *ipc, ...@@ -456,8 +459,10 @@ static void skl_ipc_process_reply(struct sst_generic_ipc *ipc,
} }
} }
spin_lock_irqsave(&ipc->dsp->spinlock, flags);
list_del(&msg->list); list_del(&msg->list);
sst_ipc_tx_msg_reply_complete(ipc, msg); sst_ipc_tx_msg_reply_complete(ipc, msg);
spin_unlock_irqrestore(&ipc->dsp->spinlock, flags);
} }
irqreturn_t skl_dsp_irq_thread_handler(int irq, void *context) irqreturn_t skl_dsp_irq_thread_handler(int irq, void *context)
......
...@@ -2502,7 +2502,7 @@ static int skl_tplg_get_manifest_tkn(struct device *dev, ...@@ -2502,7 +2502,7 @@ static int skl_tplg_get_manifest_tkn(struct device *dev,
if (ret < 0) if (ret < 0)
return ret; return ret;
tkn_count += ret; tkn_count = ret;
tuple_size += tkn_count * tuple_size += tkn_count *
sizeof(struct snd_soc_tplg_vendor_string_elem); sizeof(struct snd_soc_tplg_vendor_string_elem);
......
...@@ -410,7 +410,7 @@ static int skl_free(struct hdac_ext_bus *ebus) ...@@ -410,7 +410,7 @@ static int skl_free(struct hdac_ext_bus *ebus)
struct skl *skl = ebus_to_skl(ebus); struct skl *skl = ebus_to_skl(ebus);
struct hdac_bus *bus = ebus_to_hbus(ebus); struct hdac_bus *bus = ebus_to_hbus(ebus);
skl->init_failed = 1; /* to be sure */ skl->init_done = 0; /* to be sure */
snd_hdac_ext_stop_streams(ebus); snd_hdac_ext_stop_streams(ebus);
...@@ -428,8 +428,10 @@ static int skl_free(struct hdac_ext_bus *ebus) ...@@ -428,8 +428,10 @@ static int skl_free(struct hdac_ext_bus *ebus)
snd_hdac_ext_bus_exit(ebus); snd_hdac_ext_bus_exit(ebus);
cancel_work_sync(&skl->probe_work);
if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI))
snd_hdac_i915_exit(&ebus->bus); snd_hdac_i915_exit(&ebus->bus);
return 0; return 0;
} }
...@@ -566,6 +568,84 @@ static const struct hdac_bus_ops bus_core_ops = { ...@@ -566,6 +568,84 @@ static const struct hdac_bus_ops bus_core_ops = {
.get_response = snd_hdac_bus_get_response, .get_response = snd_hdac_bus_get_response,
}; };
static int skl_i915_init(struct hdac_bus *bus)
{
int err;
/*
* The HDMI codec is in GPU so we need to ensure that it is powered
* up and ready for probe
*/
err = snd_hdac_i915_init(bus);
if (err < 0)
return err;
err = snd_hdac_display_power(bus, true);
if (err < 0)
dev_err(bus->dev, "Cannot turn on display power on i915\n");
return err;
}
static void skl_probe_work(struct work_struct *work)
{
struct skl *skl = container_of(work, struct skl, probe_work);
struct hdac_ext_bus *ebus = &skl->ebus;
struct hdac_bus *bus = ebus_to_hbus(ebus);
struct hdac_ext_link *hlink = NULL;
int err;
if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) {
err = skl_i915_init(bus);
if (err < 0)
return;
}
err = skl_init_chip(bus, true);
if (err < 0) {
dev_err(bus->dev, "Init chip failed with err: %d\n", err);
goto out_err;
}
/* codec detection */
if (!bus->codec_mask)
dev_info(bus->dev, "no hda codecs found!\n");
/* create codec instances */
err = skl_codec_create(ebus);
if (err < 0)
goto out_err;
if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) {
err = snd_hdac_display_power(bus, false);
if (err < 0) {
dev_err(bus->dev, "Cannot turn off display power on i915\n");
return;
}
}
/* register platform dai and controls */
err = skl_platform_register(bus->dev);
if (err < 0)
return;
/*
* we are done probing so decrement link counts
*/
list_for_each_entry(hlink, &ebus->hlink_list, list)
snd_hdac_ext_bus_link_put(ebus, hlink);
/* configure PM */
pm_runtime_put_noidle(bus->dev);
pm_runtime_allow(bus->dev);
skl->init_done = 1;
return;
out_err:
if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI))
err = snd_hdac_display_power(bus, false);
}
/* /*
* constructor * constructor
*/ */
...@@ -593,6 +673,7 @@ static int skl_create(struct pci_dev *pci, ...@@ -593,6 +673,7 @@ static int skl_create(struct pci_dev *pci,
snd_hdac_ext_bus_init(ebus, &pci->dev, &bus_core_ops, io_ops); snd_hdac_ext_bus_init(ebus, &pci->dev, &bus_core_ops, io_ops);
ebus->bus.use_posbuf = 1; ebus->bus.use_posbuf = 1;
skl->pci = pci; skl->pci = pci;
INIT_WORK(&skl->probe_work, skl_probe_work);
ebus->bus.bdl_pos_adj = 0; ebus->bus.bdl_pos_adj = 0;
...@@ -601,27 +682,6 @@ static int skl_create(struct pci_dev *pci, ...@@ -601,27 +682,6 @@ static int skl_create(struct pci_dev *pci,
return 0; return 0;
} }
static int skl_i915_init(struct hdac_bus *bus)
{
int err;
/*
* The HDMI codec is in GPU so we need to ensure that it is powered
* up and ready for probe
*/
err = snd_hdac_i915_init(bus);
if (err < 0)
return err;
err = snd_hdac_display_power(bus, true);
if (err < 0) {
dev_err(bus->dev, "Cannot turn on display power on i915\n");
return err;
}
return err;
}
static int skl_first_init(struct hdac_ext_bus *ebus) static int skl_first_init(struct hdac_ext_bus *ebus)
{ {
struct skl *skl = ebus_to_skl(ebus); struct skl *skl = ebus_to_skl(ebus);
...@@ -684,20 +744,7 @@ static int skl_first_init(struct hdac_ext_bus *ebus) ...@@ -684,20 +744,7 @@ static int skl_first_init(struct hdac_ext_bus *ebus)
/* initialize chip */ /* initialize chip */
skl_init_pci(skl); skl_init_pci(skl);
if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) { return skl_init_chip(bus, true);
err = skl_i915_init(bus);
if (err < 0)
return err;
}
skl_init_chip(bus, true);
/* codec detection */
if (!bus->codec_mask) {
dev_info(bus->dev, "no hda codecs found!\n");
}
return 0;
} }
static int skl_probe(struct pci_dev *pci, static int skl_probe(struct pci_dev *pci,
...@@ -706,7 +753,6 @@ static int skl_probe(struct pci_dev *pci, ...@@ -706,7 +753,6 @@ static int skl_probe(struct pci_dev *pci,
struct skl *skl; struct skl *skl;
struct hdac_ext_bus *ebus = NULL; struct hdac_ext_bus *ebus = NULL;
struct hdac_bus *bus = NULL; struct hdac_bus *bus = NULL;
struct hdac_ext_link *hlink = NULL;
int err; int err;
/* we use ext core ops, so provide NULL for ops here */ /* we use ext core ops, so provide NULL for ops here */
...@@ -729,7 +775,7 @@ static int skl_probe(struct pci_dev *pci, ...@@ -729,7 +775,7 @@ static int skl_probe(struct pci_dev *pci,
if (skl->nhlt == NULL) { if (skl->nhlt == NULL) {
err = -ENODEV; err = -ENODEV;
goto out_display_power_off; goto out_free;
} }
err = skl_nhlt_create_sysfs(skl); err = skl_nhlt_create_sysfs(skl);
...@@ -760,56 +806,24 @@ static int skl_probe(struct pci_dev *pci, ...@@ -760,56 +806,24 @@ static int skl_probe(struct pci_dev *pci,
if (bus->mlcap) if (bus->mlcap)
snd_hdac_ext_bus_get_ml_capabilities(ebus); snd_hdac_ext_bus_get_ml_capabilities(ebus);
snd_hdac_bus_stop_chip(bus);
/* create device for soc dmic */ /* create device for soc dmic */
err = skl_dmic_device_register(skl); err = skl_dmic_device_register(skl);
if (err < 0) if (err < 0)
goto out_dsp_free; goto out_dsp_free;
/* register platform dai and controls */ schedule_work(&skl->probe_work);
err = skl_platform_register(bus->dev);
if (err < 0)
goto out_dmic_free;
/* create codec instances */
err = skl_codec_create(ebus);
if (err < 0)
goto out_unregister;
if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) {
err = snd_hdac_display_power(bus, false);
if (err < 0) {
dev_err(bus->dev, "Cannot turn off display power on i915\n");
return err;
}
}
/*
* we are done probling so decrement link counts
*/
list_for_each_entry(hlink, &ebus->hlink_list, list)
snd_hdac_ext_bus_link_put(ebus, hlink);
/* configure PM */
pm_runtime_put_noidle(bus->dev);
pm_runtime_allow(bus->dev);
return 0; return 0;
out_unregister:
skl_platform_unregister(bus->dev);
out_dmic_free:
skl_dmic_device_unregister(skl);
out_dsp_free: out_dsp_free:
skl_free_dsp(skl); skl_free_dsp(skl);
out_mach_free: out_mach_free:
skl_machine_device_unregister(skl); skl_machine_device_unregister(skl);
out_nhlt_free: out_nhlt_free:
skl_nhlt_free(skl->nhlt); skl_nhlt_free(skl->nhlt);
out_display_power_off:
if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI))
snd_hdac_display_power(bus, false);
out_free: out_free:
skl->init_failed = 1;
skl_free(ebus); skl_free(ebus);
return err; return err;
...@@ -828,7 +842,7 @@ static void skl_shutdown(struct pci_dev *pci) ...@@ -828,7 +842,7 @@ static void skl_shutdown(struct pci_dev *pci)
skl = ebus_to_skl(ebus); skl = ebus_to_skl(ebus);
if (skl->init_failed) if (!skl->init_done)
return; return;
snd_hdac_ext_stop_streams(ebus); snd_hdac_ext_stop_streams(ebus);
......
...@@ -46,7 +46,7 @@ struct skl { ...@@ -46,7 +46,7 @@ struct skl {
struct hdac_ext_bus ebus; struct hdac_ext_bus ebus;
struct pci_dev *pci; struct pci_dev *pci;
unsigned int init_failed:1; /* delayed init failed */ unsigned int init_done:1; /* delayed init status */
struct platform_device *dmic_dev; struct platform_device *dmic_dev;
struct platform_device *i2s_dev; struct platform_device *i2s_dev;
struct snd_soc_platform *platform; struct snd_soc_platform *platform;
...@@ -64,6 +64,8 @@ struct skl { ...@@ -64,6 +64,8 @@ struct skl {
const struct firmware *tplg; const struct firmware *tplg;
int supend_active; int supend_active;
struct work_struct probe_work;
}; };
#define skl_to_ebus(s) (&(s)->ebus) #define skl_to_ebus(s) (&(s)->ebus)
......
...@@ -507,7 +507,8 @@ static void rsnd_adg_get_clkout(struct rsnd_priv *priv, ...@@ -507,7 +507,8 @@ static void rsnd_adg_get_clkout(struct rsnd_priv *priv,
rbga = rbgx; rbga = rbgx;
adg->rbga_rate_for_441khz = rate / div; adg->rbga_rate_for_441khz = rate / div;
ckr |= brg_table[i] << 20; ckr |= brg_table[i] << 20;
if (req_441kHz_rate) if (req_441kHz_rate &&
!(adg_mode_flags(adg) & AUDIO_OUT_48))
parent_clk_name = __clk_get_name(clk); parent_clk_name = __clk_get_name(clk);
} }
} }
...@@ -522,7 +523,8 @@ static void rsnd_adg_get_clkout(struct rsnd_priv *priv, ...@@ -522,7 +523,8 @@ static void rsnd_adg_get_clkout(struct rsnd_priv *priv,
rbgb = rbgx; rbgb = rbgx;
adg->rbgb_rate_for_48khz = rate / div; adg->rbgb_rate_for_48khz = rate / div;
ckr |= brg_table[i] << 16; ckr |= brg_table[i] << 16;
if (req_48kHz_rate) if (req_48kHz_rate &&
(adg_mode_flags(adg) & AUDIO_OUT_48))
parent_clk_name = __clk_get_name(clk); parent_clk_name = __clk_get_name(clk);
} }
} }
......
...@@ -89,6 +89,7 @@ static int rsnd_cmd_init(struct rsnd_mod *mod, ...@@ -89,6 +89,7 @@ static int rsnd_cmd_init(struct rsnd_mod *mod,
dev_dbg(dev, "ctu/mix path = 0x%08x", data); dev_dbg(dev, "ctu/mix path = 0x%08x", data);
rsnd_mod_write(mod, CMD_ROUTE_SLCT, data); rsnd_mod_write(mod, CMD_ROUTE_SLCT, data);
rsnd_mod_write(mod, CMD_BUSIF_MODE, rsnd_get_busif_shift(io, mod) | 1);
rsnd_mod_write(mod, CMD_BUSIF_DALIGN, rsnd_get_dalign(mod, io)); rsnd_mod_write(mod, CMD_BUSIF_DALIGN, rsnd_get_dalign(mod, io));
rsnd_adg_set_cmd_timsel_gen2(mod, io); rsnd_adg_set_cmd_timsel_gen2(mod, io);
......
...@@ -343,6 +343,57 @@ u32 rsnd_get_dalign(struct rsnd_mod *mod, struct rsnd_dai_stream *io) ...@@ -343,6 +343,57 @@ u32 rsnd_get_dalign(struct rsnd_mod *mod, struct rsnd_dai_stream *io)
return 0x76543210; return 0x76543210;
} }
u32 rsnd_get_busif_shift(struct rsnd_dai_stream *io, struct rsnd_mod *mod)
{
enum rsnd_mod_type playback_mods[] = {
RSND_MOD_SRC,
RSND_MOD_CMD,
RSND_MOD_SSIU,
};
enum rsnd_mod_type capture_mods[] = {
RSND_MOD_CMD,
RSND_MOD_SRC,
RSND_MOD_SSIU,
};
struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
struct rsnd_mod *tmod = NULL;
enum rsnd_mod_type *mods =
rsnd_io_is_play(io) ?
playback_mods : capture_mods;
int i;
/*
* This is needed for 24bit data
* We need to shift 8bit
*
* Linux 24bit data is located as 0x00******
* HW 24bit data is located as 0x******00
*
*/
switch (runtime->sample_bits) {
case 16:
return 0;
case 32:
break;
}
for (i = 0; i < ARRAY_SIZE(playback_mods); i++) {