Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.5.6.
  1// SPDX-License-Identifier: GPL-2.0-only
  2//
  3// Copyright(c) 2018 Intel Corporation. All rights reserved.
  4//
  5// Authors: Keyon Jie <yang.jie@linux.intel.com>
  6//
  7
  8#include <linux/module.h>
  9#include <sound/hdaudio_ext.h>
 10#include <sound/hda_register.h>
 11#include <sound/hda_codec.h>
 12#include <sound/hda_i915.h>
 13#include <sound/sof.h>
 14#include "../ops.h"
 15#include "hda.h"
 16
 17#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC)
 18#include "../../codecs/hdac_hda.h"
 19
 20#define CODEC_PROBE_RETRIES	3
 21
 22#define IDISP_VID_INTEL	0x80860000
 23
 24static int hda_codec_mask = -1;
 25module_param_named(codec_mask, hda_codec_mask, int, 0444);
 26MODULE_PARM_DESC(codec_mask, "SOF HDA codec mask for probing");
 27
 28/* load the legacy HDA codec driver */
 29static int request_codec_module(struct hda_codec *codec)
 30{
 31#ifdef MODULE
 32	char alias[MODULE_NAME_LEN];
 33	const char *mod = NULL;
 34
 35	switch (codec->probe_id) {
 36	case HDA_CODEC_ID_GENERIC:
 37#if IS_MODULE(CONFIG_SND_HDA_GENERIC)
 38		mod = "snd-hda-codec-generic";
 39#endif
 40		break;
 41	default:
 42		snd_hdac_codec_modalias(&codec->core, alias, sizeof(alias));
 43		mod = alias;
 44		break;
 45	}
 46
 47	if (mod) {
 48		dev_dbg(&codec->core.dev, "loading codec module: %s\n", mod);
 49		request_module(mod);
 50	}
 51#endif /* MODULE */
 52	return device_attach(hda_codec_dev(codec));
 53}
 54
 55static int hda_codec_load_module(struct hda_codec *codec)
 56{
 57	int ret = request_codec_module(codec);
 58
 59	if (ret <= 0) {
 60		codec->probe_id = HDA_CODEC_ID_GENERIC;
 61		ret = request_codec_module(codec);
 62	}
 63
 64	return ret;
 65}
 66
 67/* enable controller wake up event for all codecs with jack connectors */
 68void hda_codec_jack_wake_enable(struct snd_sof_dev *sdev, bool enable)
 69{
 70	struct hda_bus *hbus = sof_to_hbus(sdev);
 71	struct hdac_bus *bus = sof_to_bus(sdev);
 72	struct hda_codec *codec;
 73	unsigned int mask = 0;
 74
 75	if (IS_ENABLED(CONFIG_SND_SOC_SOF_NOCODEC_DEBUG_SUPPORT) &&
 76	    sof_debug_check_flag(SOF_DBG_FORCE_NOCODEC))
 77		return;
 78
 79	if (enable) {
 80		list_for_each_codec(codec, hbus)
 81			if (codec->jacktbl.used)
 82				mask |= BIT(codec->core.addr);
 83	}
 84
 85	snd_hdac_chip_updatew(bus, WAKEEN, STATESTS_INT_MASK, mask);
 86}
 87EXPORT_SYMBOL_NS_GPL(hda_codec_jack_wake_enable, SND_SOC_SOF_HDA_AUDIO_CODEC);
 88
 89/* check jack status after resuming from suspend mode */
 90void hda_codec_jack_check(struct snd_sof_dev *sdev)
 91{
 92	struct hda_bus *hbus = sof_to_hbus(sdev);
 93	struct hda_codec *codec;
 94
 95	if (IS_ENABLED(CONFIG_SND_SOC_SOF_NOCODEC_DEBUG_SUPPORT) &&
 96	    sof_debug_check_flag(SOF_DBG_FORCE_NOCODEC))
 97		return;
 98
 99	list_for_each_codec(codec, hbus)
100		/*
101		 * Wake up all jack-detecting codecs regardless whether an event
102		 * has been recorded in STATESTS
103		 */
104		if (codec->jacktbl.used)
105			pm_request_resume(&codec->core.dev);
106}
107EXPORT_SYMBOL_NS_GPL(hda_codec_jack_check, SND_SOC_SOF_HDA_AUDIO_CODEC);
108
109#if IS_ENABLED(CONFIG_SND_HDA_GENERIC)
110#define is_generic_config(bus) \
111	((bus)->modelname && !strcmp((bus)->modelname, "generic"))
112#else
113#define is_generic_config(x)	0
114#endif
115
116static struct hda_codec *hda_codec_device_init(struct hdac_bus *bus, int addr, int type)
117{
118	struct hda_codec *codec;
119	int ret;
120
121	codec = snd_hda_codec_device_init(to_hda_bus(bus), addr, "ehdaudio%dD%d", bus->idx, addr);
122	if (IS_ERR(codec)) {
123		dev_err(bus->dev, "device init failed for hdac device\n");
124		return codec;
125	}
126
127	codec->core.type = type;
128
129	ret = snd_hdac_device_register(&codec->core);
130	if (ret) {
131		dev_err(bus->dev, "failed to register hdac device\n");
132		put_device(&codec->core.dev);
133		return ERR_PTR(ret);
134	}
135
136	return codec;
137}
138
139/* probe individual codec */
140static int hda_codec_probe(struct snd_sof_dev *sdev, int address)
141{
142	struct hdac_hda_priv *hda_priv;
143	struct hda_bus *hbus = sof_to_hbus(sdev);
144	struct hda_codec *codec;
145	u32 hda_cmd = (address << 28) | (AC_NODE_ROOT << 20) |
146		(AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID;
147	u32 resp = -1;
148	int ret, retry = 0;
149
150	do {
151		mutex_lock(&hbus->core.cmd_mutex);
152		snd_hdac_bus_send_cmd(&hbus->core, hda_cmd);
153		snd_hdac_bus_get_response(&hbus->core, address, &resp);
154		mutex_unlock(&hbus->core.cmd_mutex);
155	} while (resp == -1 && retry++ < CODEC_PROBE_RETRIES);
156
157	if (resp == -1)
158		return -EIO;
159	dev_dbg(sdev->dev, "HDA codec #%d probed OK: response: %x\n",
160		address, resp);
161
162	hda_priv = devm_kzalloc(sdev->dev, sizeof(*hda_priv), GFP_KERNEL);
163	if (!hda_priv)
164		return -ENOMEM;
165
166	codec = hda_codec_device_init(&hbus->core, address, HDA_DEV_LEGACY);
167	ret = PTR_ERR_OR_ZERO(codec);
168	if (ret < 0)
169		return ret;
170
171	hda_priv->codec = codec;
172	dev_set_drvdata(&codec->core.dev, hda_priv);
173
174	if ((resp & 0xFFFF0000) == IDISP_VID_INTEL) {
175		if (!hbus->core.audio_component) {
176			dev_dbg(sdev->dev,
177				"iDisp hw present but no driver\n");
178			ret = -ENOENT;
179			goto out;
180		}
181		hda_priv->need_display_power = true;
182	}
183
184	if (is_generic_config(hbus))
185		codec->probe_id = HDA_CODEC_ID_GENERIC;
186	else
187		codec->probe_id = 0;
188
189	ret = hda_codec_load_module(codec);
190	/*
191	 * handle ret==0 (no driver bound) as an error, but pass
192	 * other return codes without modification
193	 */
194	if (ret == 0)
195		ret = -ENOENT;
196
197out:
198	if (ret < 0) {
199		snd_hdac_device_unregister(&codec->core);
200		put_device(&codec->core.dev);
201	}
202
203	return ret;
204}
205
206/* Codec initialization */
207void hda_codec_probe_bus(struct snd_sof_dev *sdev)
208{
209	struct hdac_bus *bus = sof_to_bus(sdev);
210	int i, ret;
211
212	if (IS_ENABLED(CONFIG_SND_SOC_SOF_NOCODEC_DEBUG_SUPPORT) &&
213	    sof_debug_check_flag(SOF_DBG_FORCE_NOCODEC))
214		return;
215
216	/* probe codecs in avail slots */
217	for (i = 0; i < HDA_MAX_CODECS; i++) {
218
219		if (!(bus->codec_mask & (1 << i)))
220			continue;
221
222		ret = hda_codec_probe(sdev, i);
223		if (ret < 0) {
224			dev_warn(bus->dev, "codec #%d probe error, ret: %d\n",
225				 i, ret);
226			bus->codec_mask &= ~BIT(i);
227		}
228	}
229}
230EXPORT_SYMBOL_NS_GPL(hda_codec_probe_bus, SND_SOC_SOF_HDA_AUDIO_CODEC);
231
232void hda_codec_check_for_state_change(struct snd_sof_dev *sdev)
233{
234	struct hdac_bus *bus = sof_to_bus(sdev);
235	unsigned int codec_mask;
236
237	codec_mask = snd_hdac_chip_readw(bus, STATESTS);
238	if (codec_mask) {
239		hda_codec_jack_check(sdev);
240		snd_hdac_chip_writew(bus, STATESTS, codec_mask);
241	}
242}
243EXPORT_SYMBOL_NS_GPL(hda_codec_check_for_state_change, SND_SOC_SOF_HDA_AUDIO_CODEC);
244
245void hda_codec_detect_mask(struct snd_sof_dev *sdev)
246{
247	struct hdac_bus *bus = sof_to_bus(sdev);
248
249	if (IS_ENABLED(CONFIG_SND_SOC_SOF_NOCODEC_DEBUG_SUPPORT) &&
250	    sof_debug_check_flag(SOF_DBG_FORCE_NOCODEC))
251		return;
252
253	/* Accept unsolicited responses */
254	snd_hdac_chip_updatel(bus, GCTL, AZX_GCTL_UNSOL, AZX_GCTL_UNSOL);
255
256	/* detect codecs */
257	if (!bus->codec_mask) {
258		bus->codec_mask = snd_hdac_chip_readw(bus, STATESTS);
259		dev_dbg(bus->dev, "codec_mask = 0x%lx\n", bus->codec_mask);
260	}
261
262	if (hda_codec_mask != -1) {
263		bus->codec_mask &= hda_codec_mask;
264		dev_dbg(bus->dev, "filtered codec_mask = 0x%lx\n",
265			bus->codec_mask);
266	}
267}
268EXPORT_SYMBOL_NS_GPL(hda_codec_detect_mask, SND_SOC_SOF_HDA_AUDIO_CODEC);
269
270void hda_codec_init_cmd_io(struct snd_sof_dev *sdev)
271{
272	struct hdac_bus *bus = sof_to_bus(sdev);
273
274	if (IS_ENABLED(CONFIG_SND_SOC_SOF_NOCODEC_DEBUG_SUPPORT) &&
275	    sof_debug_check_flag(SOF_DBG_FORCE_NOCODEC))
276		return;
277
278	/* initialize the codec command I/O */
279	snd_hdac_bus_init_cmd_io(bus);
280}
281EXPORT_SYMBOL_NS_GPL(hda_codec_init_cmd_io, SND_SOC_SOF_HDA_AUDIO_CODEC);
282
283void hda_codec_resume_cmd_io(struct snd_sof_dev *sdev)
284{
285	struct hdac_bus *bus = sof_to_bus(sdev);
286
287	if (IS_ENABLED(CONFIG_SND_SOC_SOF_NOCODEC_DEBUG_SUPPORT) &&
288	    sof_debug_check_flag(SOF_DBG_FORCE_NOCODEC))
289		return;
290
291	/* set up CORB/RIRB buffers if was on before suspend */
292	if (bus->cmd_dma_state)
293		snd_hdac_bus_init_cmd_io(bus);
294}
295EXPORT_SYMBOL_NS_GPL(hda_codec_resume_cmd_io, SND_SOC_SOF_HDA_AUDIO_CODEC);
296
297void hda_codec_stop_cmd_io(struct snd_sof_dev *sdev)
298{
299	struct hdac_bus *bus = sof_to_bus(sdev);
300
301	if (IS_ENABLED(CONFIG_SND_SOC_SOF_NOCODEC_DEBUG_SUPPORT) &&
302	    sof_debug_check_flag(SOF_DBG_FORCE_NOCODEC))
303		return;
304
305	/* initialize the codec command I/O */
306	snd_hdac_bus_stop_cmd_io(bus);
307}
308EXPORT_SYMBOL_NS_GPL(hda_codec_stop_cmd_io, SND_SOC_SOF_HDA_AUDIO_CODEC);
309
310void hda_codec_suspend_cmd_io(struct snd_sof_dev *sdev)
311{
312	struct hdac_bus *bus = sof_to_bus(sdev);
313
314	if (IS_ENABLED(CONFIG_SND_SOC_SOF_NOCODEC_DEBUG_SUPPORT) &&
315	    sof_debug_check_flag(SOF_DBG_FORCE_NOCODEC))
316		return;
317
318	/* stop the CORB/RIRB DMA if it is On */
319	if (bus->cmd_dma_state)
320		snd_hdac_bus_stop_cmd_io(bus);
321
322}
323EXPORT_SYMBOL_NS_GPL(hda_codec_suspend_cmd_io, SND_SOC_SOF_HDA_AUDIO_CODEC);
324
325void hda_codec_rirb_status_clear(struct snd_sof_dev *sdev)
326{
327	struct hdac_bus *bus = sof_to_bus(sdev);
328
329	if (IS_ENABLED(CONFIG_SND_SOC_SOF_NOCODEC_DEBUG_SUPPORT) &&
330	    sof_debug_check_flag(SOF_DBG_FORCE_NOCODEC))
331		return;
332
333	/* clear rirb status */
334	snd_hdac_chip_writeb(bus, RIRBSTS, RIRB_INT_MASK);
335}
336EXPORT_SYMBOL_NS_GPL(hda_codec_rirb_status_clear, SND_SOC_SOF_HDA_AUDIO_CODEC);
337
338void hda_codec_set_codec_wakeup(struct snd_sof_dev *sdev, bool status)
339{
340	struct hdac_bus *bus = sof_to_bus(sdev);
341
342	if (sof_debug_check_flag(SOF_DBG_FORCE_NOCODEC))
343		return;
344
345	snd_hdac_set_codec_wakeup(bus, status);
346}
347EXPORT_SYMBOL_NS_GPL(hda_codec_set_codec_wakeup, SND_SOC_SOF_HDA_AUDIO_CODEC);
348
349bool hda_codec_check_rirb_status(struct snd_sof_dev *sdev)
350{
351	struct hdac_bus *bus = sof_to_bus(sdev);
352	bool active = false;
353	u32 rirb_status;
354
355	if (IS_ENABLED(CONFIG_SND_SOC_SOF_NOCODEC_DEBUG_SUPPORT) &&
356	    sof_debug_check_flag(SOF_DBG_FORCE_NOCODEC))
357		return false;
358
359	rirb_status = snd_hdac_chip_readb(bus, RIRBSTS);
360	if (rirb_status & RIRB_INT_MASK) {
361		/*
362		 * Clearing the interrupt status here ensures
363		 * that no interrupt gets masked after the RIRB
364		 * wp is read in snd_hdac_bus_update_rirb.
365		 */
366		snd_hdac_chip_writeb(bus, RIRBSTS,
367				     RIRB_INT_MASK);
368		active = true;
369		if (rirb_status & RIRB_INT_RESPONSE)
370			snd_hdac_bus_update_rirb(bus);
371	}
372	return active;
373}
374EXPORT_SYMBOL_NS_GPL(hda_codec_check_rirb_status, SND_SOC_SOF_HDA_AUDIO_CODEC);
375
376void hda_codec_device_remove(struct snd_sof_dev *sdev)
377{
378	struct hdac_bus *bus = sof_to_bus(sdev);
379
380	if (IS_ENABLED(CONFIG_SND_SOC_SOF_NOCODEC_DEBUG_SUPPORT) &&
381	    sof_debug_check_flag(SOF_DBG_FORCE_NOCODEC))
382		return;
383
384	/* codec removal, invoke bus_device_remove */
385	snd_hdac_ext_bus_device_remove(bus);
386}
387EXPORT_SYMBOL_NS_GPL(hda_codec_device_remove, SND_SOC_SOF_HDA_AUDIO_CODEC);
388
389#endif /* CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC */
390
391#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) && IS_ENABLED(CONFIG_SND_HDA_CODEC_HDMI)
392
393void hda_codec_i915_display_power(struct snd_sof_dev *sdev, bool enable)
394{
395	struct hdac_bus *bus = sof_to_bus(sdev);
396
397	if (IS_ENABLED(CONFIG_SND_SOC_SOF_NOCODEC_DEBUG_SUPPORT) &&
398	    sof_debug_check_flag(SOF_DBG_FORCE_NOCODEC))
399		return;
400
401	if (HDA_IDISP_CODEC(bus->codec_mask)) {
402		dev_dbg(bus->dev, "Turning i915 HDAC power %d\n", enable);
403		snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, enable);
404	}
405}
406EXPORT_SYMBOL_NS_GPL(hda_codec_i915_display_power, SND_SOC_SOF_HDA_AUDIO_CODEC_I915);
407
408int hda_codec_i915_init(struct snd_sof_dev *sdev)
409{
410	struct hdac_bus *bus = sof_to_bus(sdev);
411	int ret;
412
413	if (IS_ENABLED(CONFIG_SND_SOC_SOF_NOCODEC_DEBUG_SUPPORT) &&
414	    sof_debug_check_flag(SOF_DBG_FORCE_NOCODEC))
415		return 0;
416
417	/* i915 exposes a HDA codec for HDMI audio */
418	ret = snd_hdac_i915_init(bus);
419	if (ret < 0)
420		return ret;
421
422	/* codec_mask not yet known, power up for probe */
423	snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, true);
424
425	return 0;
426}
427EXPORT_SYMBOL_NS_GPL(hda_codec_i915_init, SND_SOC_SOF_HDA_AUDIO_CODEC_I915);
428
429int hda_codec_i915_exit(struct snd_sof_dev *sdev)
430{
431	struct hdac_bus *bus = sof_to_bus(sdev);
432
433	if (IS_ENABLED(CONFIG_SND_SOC_SOF_NOCODEC_DEBUG_SUPPORT) &&
434	    sof_debug_check_flag(SOF_DBG_FORCE_NOCODEC))
435		return 0;
436
437	if (!bus->audio_component)
438		return 0;
439
440	/* power down unconditionally */
441	snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false);
442
443	return snd_hdac_i915_exit(bus);
444}
445EXPORT_SYMBOL_NS_GPL(hda_codec_i915_exit, SND_SOC_SOF_HDA_AUDIO_CODEC_I915);
446
447#endif
448
449MODULE_LICENSE("Dual BSD/GPL");