1df0566a6SJani Nikula /*
2df0566a6SJani Nikula * Copyright © 2016 Intel Corporation
3df0566a6SJani Nikula *
4df0566a6SJani Nikula * Permission is hereby granted, free of charge, to any person obtaining a
5df0566a6SJani Nikula * copy of this software and associated documentation files (the "Software"),
6df0566a6SJani Nikula * to deal in the Software without restriction, including without limitation
7df0566a6SJani Nikula * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8df0566a6SJani Nikula * and/or sell copies of the Software, and to permit persons to whom the
9df0566a6SJani Nikula * Software is furnished to do so, subject to the following conditions:
10df0566a6SJani Nikula *
11df0566a6SJani Nikula * The above copyright notice and this permission notice (including the next
12df0566a6SJani Nikula * paragraph) shall be included in all copies or substantial portions of the
13df0566a6SJani Nikula * Software.
14df0566a6SJani Nikula *
15df0566a6SJani Nikula * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16df0566a6SJani Nikula * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17df0566a6SJani Nikula * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18df0566a6SJani Nikula * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19df0566a6SJani Nikula * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20df0566a6SJani Nikula * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21df0566a6SJani Nikula * IN THE SOFTWARE.
22df0566a6SJani Nikula *
23df0566a6SJani Nikula * Authors:
24df0566a6SJani Nikula * Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
25df0566a6SJani Nikula * Jerome Anand <jerome.anand@intel.com>
26df0566a6SJani Nikula * based on VED patches
27df0566a6SJani Nikula *
28df0566a6SJani Nikula */
29df0566a6SJani Nikula
30df0566a6SJani Nikula /**
31df0566a6SJani Nikula * DOC: LPE Audio integration for HDMI or DP playback
32df0566a6SJani Nikula *
33df0566a6SJani Nikula * Motivation:
34df0566a6SJani Nikula * Atom platforms (e.g. valleyview and cherryTrail) integrates a DMA-based
35df0566a6SJani Nikula * interface as an alternative to the traditional HDaudio path. While this
36df0566a6SJani Nikula * mode is unrelated to the LPE aka SST audio engine, the documentation refers
37df0566a6SJani Nikula * to this mode as LPE so we keep this notation for the sake of consistency.
38df0566a6SJani Nikula *
39df0566a6SJani Nikula * The interface is handled by a separate standalone driver maintained in the
40df0566a6SJani Nikula * ALSA subsystem for simplicity. To minimize the interaction between the two
41df0566a6SJani Nikula * subsystems, a bridge is setup between the hdmi-lpe-audio and i915:
42df0566a6SJani Nikula * 1. Create a platform device to share MMIO/IRQ resources
43df0566a6SJani Nikula * 2. Make the platform device child of i915 device for runtime PM.
44df0566a6SJani Nikula * 3. Create IRQ chip to forward the LPE audio irqs.
45df0566a6SJani Nikula * the hdmi-lpe-audio driver probes the lpe audio device and creates a new
46df0566a6SJani Nikula * sound card
47df0566a6SJani Nikula *
48df0566a6SJani Nikula * Threats:
49df0566a6SJani Nikula * Due to the restriction in Linux platform device model, user need manually
50df0566a6SJani Nikula * uninstall the hdmi-lpe-audio driver before uninstalling i915 module,
51df0566a6SJani Nikula * otherwise we might run into use-after-free issues after i915 removes the
52df0566a6SJani Nikula * platform device: even though hdmi-lpe-audio driver is released, the modules
53df0566a6SJani Nikula * is still in "installed" status.
54df0566a6SJani Nikula *
55df0566a6SJani Nikula * Implementation:
56df0566a6SJani Nikula * The MMIO/REG platform resources are created according to the registers
57df0566a6SJani Nikula * specification.
58df0566a6SJani Nikula * When forwarding LPE audio irqs, the flow control handler selection depends
59df0566a6SJani Nikula * on the platform, for example on valleyview handle_simple_irq is enough.
60df0566a6SJani Nikula *
61df0566a6SJani Nikula */
62df0566a6SJani Nikula
63df0566a6SJani Nikula #include <linux/acpi.h>
64df0566a6SJani Nikula #include <linux/delay.h>
65df0566a6SJani Nikula #include <linux/device.h>
66df0566a6SJani Nikula #include <linux/irq.h>
67df0566a6SJani Nikula #include <linux/pci.h>
68df0566a6SJani Nikula #include <linux/platform_device.h>
69df0566a6SJani Nikula #include <linux/pm_runtime.h>
70df0566a6SJani Nikula
71df0566a6SJani Nikula #include <drm/intel_lpe_audio.h>
72df0566a6SJani Nikula
73df0566a6SJani Nikula #include "i915_drv.h"
74801543b2SJani Nikula #include "i915_irq.h"
75801543b2SJani Nikula #include "i915_reg.h"
76ef589022SJani Nikula #include "intel_de.h"
77df0566a6SJani Nikula #include "intel_lpe_audio.h"
786bba2b30SPiotr Piórkowski #include "intel_pci_config.h"
79df0566a6SJani Nikula
804be1c12cSJani Nikula #define HAS_LPE_AUDIO(dev_priv) ((dev_priv)->display.audio.lpe.platdev != NULL)
81df0566a6SJani Nikula
82df0566a6SJani Nikula static struct platform_device *
lpe_audio_platdev_create(struct drm_i915_private * dev_priv)83df0566a6SJani Nikula lpe_audio_platdev_create(struct drm_i915_private *dev_priv)
84df0566a6SJani Nikula {
853703060dSAndrzej Hajda struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
86df0566a6SJani Nikula struct platform_device_info pinfo = {};
87df0566a6SJani Nikula struct resource *rsc;
88df0566a6SJani Nikula struct platform_device *platdev;
89df0566a6SJani Nikula struct intel_hdmi_lpe_audio_pdata *pdata;
90df0566a6SJani Nikula
91df0566a6SJani Nikula pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
92df0566a6SJani Nikula if (!pdata)
93df0566a6SJani Nikula return ERR_PTR(-ENOMEM);
94df0566a6SJani Nikula
95df0566a6SJani Nikula rsc = kcalloc(2, sizeof(*rsc), GFP_KERNEL);
96df0566a6SJani Nikula if (!rsc) {
97df0566a6SJani Nikula kfree(pdata);
98df0566a6SJani Nikula return ERR_PTR(-ENOMEM);
99df0566a6SJani Nikula }
100df0566a6SJani Nikula
1014be1c12cSJani Nikula rsc[0].start = rsc[0].end = dev_priv->display.audio.lpe.irq;
102df0566a6SJani Nikula rsc[0].flags = IORESOURCE_IRQ;
103df0566a6SJani Nikula rsc[0].name = "hdmi-lpe-audio-irq";
104df0566a6SJani Nikula
1050492a34cSVille Syrjälä rsc[1].start = pci_resource_start(pdev, GEN4_GTTMMADR_BAR) +
106df0566a6SJani Nikula I915_HDMI_LPE_AUDIO_BASE;
1070492a34cSVille Syrjälä rsc[1].end = pci_resource_start(pdev, GEN4_GTTMMADR_BAR) +
108df0566a6SJani Nikula I915_HDMI_LPE_AUDIO_BASE + I915_HDMI_LPE_AUDIO_SIZE - 1;
109df0566a6SJani Nikula rsc[1].flags = IORESOURCE_MEM;
110df0566a6SJani Nikula rsc[1].name = "hdmi-lpe-audio-mmio";
111df0566a6SJani Nikula
1123703060dSAndrzej Hajda pinfo.parent = dev_priv->drm.dev;
113df0566a6SJani Nikula pinfo.name = "hdmi-lpe-audio";
114df0566a6SJani Nikula pinfo.id = -1;
115df0566a6SJani Nikula pinfo.res = rsc;
116df0566a6SJani Nikula pinfo.num_res = 2;
117df0566a6SJani Nikula pinfo.data = pdata;
118df0566a6SJani Nikula pinfo.size_data = sizeof(*pdata);
119df0566a6SJani Nikula pinfo.dma_mask = DMA_BIT_MASK(32);
120df0566a6SJani Nikula
12124977870SJani Nikula pdata->num_pipes = INTEL_NUM_PIPES(dev_priv);
122df0566a6SJani Nikula pdata->num_ports = IS_CHERRYVIEW(dev_priv) ? 3 : 2; /* B,C,D or B,C */
123df0566a6SJani Nikula pdata->port[0].pipe = -1;
124df0566a6SJani Nikula pdata->port[1].pipe = -1;
125df0566a6SJani Nikula pdata->port[2].pipe = -1;
126df0566a6SJani Nikula spin_lock_init(&pdata->lpe_audio_slock);
127df0566a6SJani Nikula
128df0566a6SJani Nikula platdev = platform_device_register_full(&pinfo);
129df0566a6SJani Nikula kfree(rsc);
130df0566a6SJani Nikula kfree(pdata);
131df0566a6SJani Nikula
132df0566a6SJani Nikula if (IS_ERR(platdev)) {
13344294724SWambui Karuga drm_err(&dev_priv->drm,
13444294724SWambui Karuga "Failed to allocate LPE audio platform device\n");
135df0566a6SJani Nikula return platdev;
136df0566a6SJani Nikula }
137df0566a6SJani Nikula
138df0566a6SJani Nikula pm_runtime_no_callbacks(&platdev->dev);
139df0566a6SJani Nikula
140df0566a6SJani Nikula return platdev;
141df0566a6SJani Nikula }
142df0566a6SJani Nikula
lpe_audio_platdev_destroy(struct drm_i915_private * dev_priv)143df0566a6SJani Nikula static void lpe_audio_platdev_destroy(struct drm_i915_private *dev_priv)
144df0566a6SJani Nikula {
145df0566a6SJani Nikula /* XXX Note that platform_device_register_full() allocates a dma_mask
146df0566a6SJani Nikula * and never frees it. We can't free it here as we cannot guarantee
147df0566a6SJani Nikula * this is the last reference (i.e. that the dma_mask will not be
148df0566a6SJani Nikula * used after our unregister). So ee choose to leak the sizeof(u64)
149df0566a6SJani Nikula * allocation here - it should be fixed in the platform_device rather
150df0566a6SJani Nikula * than us fiddle with its internals.
151df0566a6SJani Nikula */
152df0566a6SJani Nikula
1534be1c12cSJani Nikula platform_device_unregister(dev_priv->display.audio.lpe.platdev);
154df0566a6SJani Nikula }
155df0566a6SJani Nikula
lpe_audio_irq_unmask(struct irq_data * d)156df0566a6SJani Nikula static void lpe_audio_irq_unmask(struct irq_data *d)
157df0566a6SJani Nikula {
158df0566a6SJani Nikula }
159df0566a6SJani Nikula
lpe_audio_irq_mask(struct irq_data * d)160df0566a6SJani Nikula static void lpe_audio_irq_mask(struct irq_data *d)
161df0566a6SJani Nikula {
162df0566a6SJani Nikula }
163df0566a6SJani Nikula
164df0566a6SJani Nikula static struct irq_chip lpe_audio_irqchip = {
165df0566a6SJani Nikula .name = "hdmi_lpe_audio_irqchip",
166df0566a6SJani Nikula .irq_mask = lpe_audio_irq_mask,
167df0566a6SJani Nikula .irq_unmask = lpe_audio_irq_unmask,
168df0566a6SJani Nikula };
169df0566a6SJani Nikula
lpe_audio_irq_init(struct drm_i915_private * dev_priv)170df0566a6SJani Nikula static int lpe_audio_irq_init(struct drm_i915_private *dev_priv)
171df0566a6SJani Nikula {
1724be1c12cSJani Nikula int irq = dev_priv->display.audio.lpe.irq;
173df0566a6SJani Nikula
174f4224a4cSPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv));
175df0566a6SJani Nikula irq_set_chip_and_handler_name(irq,
176df0566a6SJani Nikula &lpe_audio_irqchip,
177df0566a6SJani Nikula handle_simple_irq,
178df0566a6SJani Nikula "hdmi_lpe_audio_irq_handler");
179df0566a6SJani Nikula
180df0566a6SJani Nikula return irq_set_chip_data(irq, dev_priv);
181df0566a6SJani Nikula }
182df0566a6SJani Nikula
lpe_audio_detect(struct drm_i915_private * dev_priv)183df0566a6SJani Nikula static bool lpe_audio_detect(struct drm_i915_private *dev_priv)
184df0566a6SJani Nikula {
185df0566a6SJani Nikula int lpe_present = false;
186df0566a6SJani Nikula
187df0566a6SJani Nikula if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
188df0566a6SJani Nikula static const struct pci_device_id atom_hdaudio_ids[] = {
189df0566a6SJani Nikula /* Baytrail */
190df0566a6SJani Nikula {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0f04)},
191df0566a6SJani Nikula /* Braswell */
192df0566a6SJani Nikula {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2284)},
193df0566a6SJani Nikula {}
194df0566a6SJani Nikula };
195df0566a6SJani Nikula
196df0566a6SJani Nikula if (!pci_dev_present(atom_hdaudio_ids)) {
19744294724SWambui Karuga drm_info(&dev_priv->drm,
19844294724SWambui Karuga "HDaudio controller not detected, using LPE audio instead\n");
199df0566a6SJani Nikula lpe_present = true;
200df0566a6SJani Nikula }
201df0566a6SJani Nikula }
202df0566a6SJani Nikula return lpe_present;
203df0566a6SJani Nikula }
204df0566a6SJani Nikula
lpe_audio_setup(struct drm_i915_private * dev_priv)205df0566a6SJani Nikula static int lpe_audio_setup(struct drm_i915_private *dev_priv)
206df0566a6SJani Nikula {
207df0566a6SJani Nikula int ret;
208df0566a6SJani Nikula
2094be1c12cSJani Nikula dev_priv->display.audio.lpe.irq = irq_alloc_desc(0);
2104be1c12cSJani Nikula if (dev_priv->display.audio.lpe.irq < 0) {
21144294724SWambui Karuga drm_err(&dev_priv->drm, "Failed to allocate IRQ desc: %d\n",
2124be1c12cSJani Nikula dev_priv->display.audio.lpe.irq);
2134be1c12cSJani Nikula ret = dev_priv->display.audio.lpe.irq;
214df0566a6SJani Nikula goto err;
215df0566a6SJani Nikula }
216df0566a6SJani Nikula
2174be1c12cSJani Nikula drm_dbg(&dev_priv->drm, "irq = %d\n", dev_priv->display.audio.lpe.irq);
218df0566a6SJani Nikula
219df0566a6SJani Nikula ret = lpe_audio_irq_init(dev_priv);
220df0566a6SJani Nikula
221df0566a6SJani Nikula if (ret) {
22244294724SWambui Karuga drm_err(&dev_priv->drm,
22344294724SWambui Karuga "Failed to initialize irqchip for lpe audio: %d\n",
224df0566a6SJani Nikula ret);
225df0566a6SJani Nikula goto err_free_irq;
226df0566a6SJani Nikula }
227df0566a6SJani Nikula
2284be1c12cSJani Nikula dev_priv->display.audio.lpe.platdev = lpe_audio_platdev_create(dev_priv);
229df0566a6SJani Nikula
2304be1c12cSJani Nikula if (IS_ERR(dev_priv->display.audio.lpe.platdev)) {
2314be1c12cSJani Nikula ret = PTR_ERR(dev_priv->display.audio.lpe.platdev);
23244294724SWambui Karuga drm_err(&dev_priv->drm,
23344294724SWambui Karuga "Failed to create lpe audio platform device: %d\n",
234df0566a6SJani Nikula ret);
235df0566a6SJani Nikula goto err_free_irq;
236df0566a6SJani Nikula }
237df0566a6SJani Nikula
238df0566a6SJani Nikula /* enable chicken bit; at least this is required for Dell Wyse 3040
239df0566a6SJani Nikula * with DP outputs (but only sometimes by some reason!)
240df0566a6SJani Nikula */
241ef589022SJani Nikula intel_de_write(dev_priv, VLV_AUD_CHICKEN_BIT_REG,
242ef589022SJani Nikula VLV_CHICKEN_BIT_DBG_ENABLE);
243df0566a6SJani Nikula
244df0566a6SJani Nikula return 0;
245df0566a6SJani Nikula err_free_irq:
2464be1c12cSJani Nikula irq_free_desc(dev_priv->display.audio.lpe.irq);
247df0566a6SJani Nikula err:
2484be1c12cSJani Nikula dev_priv->display.audio.lpe.irq = -1;
2494be1c12cSJani Nikula dev_priv->display.audio.lpe.platdev = NULL;
250df0566a6SJani Nikula return ret;
251df0566a6SJani Nikula }
252df0566a6SJani Nikula
253df0566a6SJani Nikula /**
254df0566a6SJani Nikula * intel_lpe_audio_irq_handler() - forwards the LPE audio irq
255df0566a6SJani Nikula * @dev_priv: the i915 drm device private data
256df0566a6SJani Nikula *
257df0566a6SJani Nikula * the LPE Audio irq is forwarded to the irq handler registered by LPE audio
258df0566a6SJani Nikula * driver.
259df0566a6SJani Nikula */
intel_lpe_audio_irq_handler(struct drm_i915_private * dev_priv)260df0566a6SJani Nikula void intel_lpe_audio_irq_handler(struct drm_i915_private *dev_priv)
261df0566a6SJani Nikula {
262df0566a6SJani Nikula int ret;
263df0566a6SJani Nikula
264df0566a6SJani Nikula if (!HAS_LPE_AUDIO(dev_priv))
265df0566a6SJani Nikula return;
266df0566a6SJani Nikula
2674be1c12cSJani Nikula ret = generic_handle_irq(dev_priv->display.audio.lpe.irq);
268df0566a6SJani Nikula if (ret)
26944294724SWambui Karuga drm_err_ratelimited(&dev_priv->drm,
27044294724SWambui Karuga "error handling LPE audio irq: %d\n", ret);
271df0566a6SJani Nikula }
272df0566a6SJani Nikula
273df0566a6SJani Nikula /**
274df0566a6SJani Nikula * intel_lpe_audio_init() - detect and setup the bridge between HDMI LPE Audio
275df0566a6SJani Nikula * driver and i915
276df0566a6SJani Nikula * @dev_priv: the i915 drm device private data
277df0566a6SJani Nikula *
278df0566a6SJani Nikula * Return: 0 if successful. non-zero if detection or
279df0566a6SJani Nikula * llocation/initialization fails
280df0566a6SJani Nikula */
intel_lpe_audio_init(struct drm_i915_private * dev_priv)281df0566a6SJani Nikula int intel_lpe_audio_init(struct drm_i915_private *dev_priv)
282df0566a6SJani Nikula {
283df0566a6SJani Nikula int ret = -ENODEV;
284df0566a6SJani Nikula
285df0566a6SJani Nikula if (lpe_audio_detect(dev_priv)) {
286df0566a6SJani Nikula ret = lpe_audio_setup(dev_priv);
287df0566a6SJani Nikula if (ret < 0)
28844294724SWambui Karuga drm_err(&dev_priv->drm,
28944294724SWambui Karuga "failed to setup LPE Audio bridge\n");
290df0566a6SJani Nikula }
291df0566a6SJani Nikula return ret;
292df0566a6SJani Nikula }
293df0566a6SJani Nikula
294df0566a6SJani Nikula /**
295df0566a6SJani Nikula * intel_lpe_audio_teardown() - destroy the bridge between HDMI LPE
296df0566a6SJani Nikula * audio driver and i915
297df0566a6SJani Nikula * @dev_priv: the i915 drm device private data
298df0566a6SJani Nikula *
299df0566a6SJani Nikula * release all the resources for LPE audio <-> i915 bridge.
300df0566a6SJani Nikula */
intel_lpe_audio_teardown(struct drm_i915_private * dev_priv)301df0566a6SJani Nikula void intel_lpe_audio_teardown(struct drm_i915_private *dev_priv)
302df0566a6SJani Nikula {
303df0566a6SJani Nikula if (!HAS_LPE_AUDIO(dev_priv))
304df0566a6SJani Nikula return;
305df0566a6SJani Nikula
306df0566a6SJani Nikula lpe_audio_platdev_destroy(dev_priv);
307df0566a6SJani Nikula
3084be1c12cSJani Nikula irq_free_desc(dev_priv->display.audio.lpe.irq);
309df0566a6SJani Nikula
3104be1c12cSJani Nikula dev_priv->display.audio.lpe.irq = -1;
3114be1c12cSJani Nikula dev_priv->display.audio.lpe.platdev = NULL;
312df0566a6SJani Nikula }
313df0566a6SJani Nikula
314df0566a6SJani Nikula /**
315df0566a6SJani Nikula * intel_lpe_audio_notify() - notify lpe audio event
316df0566a6SJani Nikula * audio driver and i915
317df0566a6SJani Nikula * @dev_priv: the i915 drm device private data
318*5eba7426SVille Syrjälä * @cpu_transcoder: CPU transcoder
319df0566a6SJani Nikula * @port: port
320df0566a6SJani Nikula * @eld : ELD data
321df0566a6SJani Nikula * @ls_clock: Link symbol clock in kHz
322df0566a6SJani Nikula * @dp_output: Driving a DP output?
323df0566a6SJani Nikula *
324df0566a6SJani Nikula * Notify lpe audio driver of eld change.
325df0566a6SJani Nikula */
intel_lpe_audio_notify(struct drm_i915_private * dev_priv,enum transcoder cpu_transcoder,enum port port,const void * eld,int ls_clock,bool dp_output)326df0566a6SJani Nikula void intel_lpe_audio_notify(struct drm_i915_private *dev_priv,
327*5eba7426SVille Syrjälä enum transcoder cpu_transcoder, enum port port,
328df0566a6SJani Nikula const void *eld, int ls_clock, bool dp_output)
329df0566a6SJani Nikula {
330df0566a6SJani Nikula unsigned long irqflags;
331df0566a6SJani Nikula struct intel_hdmi_lpe_audio_pdata *pdata;
332df0566a6SJani Nikula struct intel_hdmi_lpe_audio_port_pdata *ppdata;
333df0566a6SJani Nikula u32 audio_enable;
334df0566a6SJani Nikula
335df0566a6SJani Nikula if (!HAS_LPE_AUDIO(dev_priv))
336df0566a6SJani Nikula return;
337df0566a6SJani Nikula
3384be1c12cSJani Nikula pdata = dev_get_platdata(&dev_priv->display.audio.lpe.platdev->dev);
339df0566a6SJani Nikula ppdata = &pdata->port[port - PORT_B];
340df0566a6SJani Nikula
341df0566a6SJani Nikula spin_lock_irqsave(&pdata->lpe_audio_slock, irqflags);
342df0566a6SJani Nikula
343ef589022SJani Nikula audio_enable = intel_de_read(dev_priv, VLV_AUD_PORT_EN_DBG(port));
344df0566a6SJani Nikula
345df0566a6SJani Nikula if (eld != NULL) {
346df0566a6SJani Nikula memcpy(ppdata->eld, eld, HDMI_MAX_ELD_BYTES);
347*5eba7426SVille Syrjälä ppdata->pipe = cpu_transcoder;
348df0566a6SJani Nikula ppdata->ls_clock = ls_clock;
349df0566a6SJani Nikula ppdata->dp_output = dp_output;
350df0566a6SJani Nikula
351df0566a6SJani Nikula /* Unmute the amp for both DP and HDMI */
352ef589022SJani Nikula intel_de_write(dev_priv, VLV_AUD_PORT_EN_DBG(port),
353df0566a6SJani Nikula audio_enable & ~VLV_AMP_MUTE);
354df0566a6SJani Nikula } else {
355df0566a6SJani Nikula memset(ppdata->eld, 0, HDMI_MAX_ELD_BYTES);
356df0566a6SJani Nikula ppdata->pipe = -1;
357df0566a6SJani Nikula ppdata->ls_clock = 0;
358df0566a6SJani Nikula ppdata->dp_output = false;
359df0566a6SJani Nikula
360df0566a6SJani Nikula /* Mute the amp for both DP and HDMI */
361ef589022SJani Nikula intel_de_write(dev_priv, VLV_AUD_PORT_EN_DBG(port),
362df0566a6SJani Nikula audio_enable | VLV_AMP_MUTE);
363df0566a6SJani Nikula }
364df0566a6SJani Nikula
365df0566a6SJani Nikula if (pdata->notify_audio_lpe)
3664be1c12cSJani Nikula pdata->notify_audio_lpe(dev_priv->display.audio.lpe.platdev, port - PORT_B);
367df0566a6SJani Nikula
368df0566a6SJani Nikula spin_unlock_irqrestore(&pdata->lpe_audio_slock, irqflags);
369df0566a6SJani Nikula }
370