diff --git a/sound/soc/sof/intel/hda-bus.c b/sound/soc/sof/intel/hda-bus.c index 759f1e61a0309c..e7fd07f1f80d5b 100644 --- a/sound/soc/sof/intel/hda-bus.c +++ b/sound/soc/sof/intel/hda-bus.c @@ -75,10 +75,9 @@ static const struct hdac_io_ops io_ops = { /* * This can be used for both with/without hda link support. - * Returns 0 if successful, or a negative error code. */ -int sof_hda_bus_init(struct hdac_bus *bus, struct device *dev, - const struct hdac_ext_bus_ops *ext_ops) +void sof_hda_bus_init(struct hdac_bus *bus, struct device *dev, + const struct hdac_ext_bus_ops *ext_ops) { static int idx; @@ -103,6 +102,4 @@ int sof_hda_bus_init(struct hdac_bus *bus, struct device *dev, mutex_init(&bus->lock); bus->cmd_dma_state = true; - - return 0; } diff --git a/sound/soc/sof/intel/hda-codec.c b/sound/soc/sof/intel/hda-codec.c index fbf64635b309e6..9701aac357b3ea 100644 --- a/sound/soc/sof/intel/hda-codec.c +++ b/sound/soc/sof/intel/hda-codec.c @@ -112,6 +112,34 @@ int hda_codec_probe_bus(struct snd_sof_dev *sdev) } EXPORT_SYMBOL(hda_codec_probe_bus); +int hda_codec_i915_get(struct snd_sof_dev *sdev) +{ + struct hdac_bus *bus = sof_to_bus(sdev); + int ret; + + dev_dbg(bus->dev, "Turning i915 HDAC power on\n"); + ret = snd_hdac_display_power(bus, true); + if (ret < 0) + dev_err(bus->dev, "i915 HDAC power on failed %d\n", ret); + + return ret; +} +EXPORT_SYMBOL(hda_codec_i915_get); + +int hda_codec_i915_put(struct snd_sof_dev *sdev) +{ + struct hdac_bus *bus = sof_to_bus(sdev); + int ret; + + dev_dbg(bus->dev, "Turning i915 HDAC power off\n"); + ret = snd_hdac_display_power(bus, false); + if (ret < 0) + dev_err(bus->dev, "i915 HDAC power off failed %d\n", ret); + + return ret; +} +EXPORT_SYMBOL(hda_codec_i915_put); + int hda_codec_i915_init(struct snd_sof_dev *sdev) { struct hdac_bus *bus = sof_to_bus(sdev); @@ -122,12 +150,27 @@ int hda_codec_i915_init(struct snd_sof_dev *sdev) if (ret < 0) return ret; - ret = snd_hdac_display_power(bus, true); - if (ret < 0) - dev_err(bus->dev, "i915 HDAC power on failed %d\n", ret); + ret = hda_codec_i915_get(sdev); return ret; } EXPORT_SYMBOL(hda_codec_i915_init); +int hda_codec_i915_exit(struct snd_sof_dev *sdev) +{ + struct hdac_bus *bus = sof_to_bus(sdev); + int ret; + + /* + * we don't need to decrease the refcount with + * hda_codec_i915_put() on exit since the device cannot be + * active + */ + + ret = snd_hdac_i915_exit(bus); + + return ret; +} +EXPORT_SYMBOL(hda_codec_i915_exit); + MODULE_LICENSE("Dual BSD/GPL"); diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index 4d7028ff7a9c09..9e1874f3f4d268 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -380,7 +380,7 @@ int hda_dsp_resume(struct snd_sof_dev *sdev) /* turn display power on */ if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) { - ret = snd_hdac_display_power(bus, true); + ret = hda_codec_i915_get(sdev); if (ret < 0) { dev_err(bus->dev, "Cannot turn on display power on i915 after resume\n"); return ret; @@ -417,7 +417,7 @@ int hda_dsp_suspend(struct snd_sof_dev *sdev, int state) /* turn display power off */ if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) { - ret = snd_hdac_display_power(bus, false); + ret = hda_codec_i915_put(sdev); if (ret < 0) { dev_err(bus->dev, "Cannot turn OFF display power on i915 during suspend\n"); return ret; diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 8ef9484ee0068d..a951de0edb4daf 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -459,8 +459,11 @@ static int hda_init_caps(struct snd_sof_dev *sdev) ret = hda_dsp_ctrl_init_chip(sdev, true); if (ret < 0) { dev_err(bus->dev, "Init chip failed with ret: %d\n", ret); - if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) - snd_hdac_display_power(bus, false); + if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) { + ret = hda_codec_i915_put(sdev); + if (ret < 0) + return ret; + } return ret; } @@ -477,11 +480,9 @@ static int hda_init_caps(struct snd_sof_dev *sdev) hda_codec_probe_bus(sdev); if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) { - ret = snd_hdac_display_power(bus, false); - if (ret < 0) { - dev_err(bus->dev, "Cannot turn off display power on i915\n"); + ret = hda_codec_i915_put(sdev); + if (ret < 0) return ret; - } } /* @@ -563,15 +564,17 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) #endif /* set up HDA base */ + bus = sof_to_bus(sdev); ret = hda_init(sdev); if (ret < 0) - return ret; + goto hdac_bus_unmap; /* DSP base */ sdev->bar[HDA_DSP_BAR] = pci_ioremap_bar(pci, HDA_DSP_BAR); if (!sdev->bar[HDA_DSP_BAR]) { dev_err(&pci->dev, "error: ioremap error\n"); - return -ENXIO; + ret = -ENXIO; + goto hdac_bus_unmap; } sdev->mmio_bar = HDA_DSP_BAR; @@ -595,7 +598,7 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) * not all errors are due to memory issues, but trying * to free everything does not harm */ - goto err; + goto free_streams; } /* @@ -619,7 +622,6 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) sdev->ipc_irq = sdev->hda->irq; } - bus = sof_to_bus(sdev); dev_dbg(sdev->dev, "using HDA IRQ %d\n", sdev->hda->irq); ret = request_threaded_irq(sdev->hda->irq, hda_dsp_stream_interrupt, hda_dsp_stream_threaded_handler, @@ -720,10 +722,11 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) pci_free_irq_vectors(pci); free_streams: hda_dsp_stream_free(sdev); +/* dsp_unmap: not currently used */ + iounmap(sdev->bar[HDA_DSP_BAR]); +hdac_bus_unmap: + iounmap(bus->remap_addr); err: - /* disable DSP */ - snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL, - SOF_HDA_PPCTL_GPROCEN, 0); return ret; } @@ -756,10 +759,17 @@ int hda_dsp_remove(struct snd_sof_dev *sdev) SOF_HDA_PPCTL_GPROCEN, 0); free_irq(sdev->ipc_irq, sdev); - free_irq(sdev->pci->irq, bus); + free_irq(sdev->hda->irq, bus); pci_free_irq_vectors(pci); hda_dsp_stream_free(sdev); + + iounmap(sdev->bar[HDA_DSP_BAR]); + iounmap(bus->remap_addr); + + if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) + hda_codec_i915_exit(sdev); + return 0; } diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index a1a525376d760f..875af5e287dfc9 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -504,17 +504,23 @@ int hda_dsp_ctrl_init_chip(struct snd_sof_dev *sdev, bool full_reset); /* * HDA bus operations. */ -int sof_hda_bus_init(struct hdac_bus *bus, struct device *dev, - const struct hdac_ext_bus_ops *ext_ops); +void sof_hda_bus_init(struct hdac_bus *bus, struct device *dev, + const struct hdac_ext_bus_ops *ext_ops); #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) /* * HDA Codec operations. */ int hda_codec_probe_bus(struct snd_sof_dev *sdev); + +#if IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI) +int hda_codec_i915_get(struct snd_sof_dev *sdev); +int hda_codec_i915_put(struct snd_sof_dev *sdev); int hda_codec_i915_init(struct snd_sof_dev *sdev); -#endif +int hda_codec_i915_exit(struct snd_sof_dev *sdev); +#endif /* CONFIG_SND_SOC_HDAC_HDMI */ +#endif /* CONFIG_SND_SOC_SOF_HDA */ /* * Trace Control. */