xref: /openbmc/linux/drivers/gpu/drm/i915/display/intel_lpe_audio.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
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