11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds *
4d01ce99fSTakashi Iwai * hda_intel.c - Implementation of primary alsa driver code base
5d01ce99fSTakashi Iwai * for Intel HD Audio.
61da177e4SLinus Torvalds *
71da177e4SLinus Torvalds * Copyright(c) 2004 Intel Corporation. All rights reserved.
81da177e4SLinus Torvalds *
91da177e4SLinus Torvalds * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
101da177e4SLinus Torvalds * PeiSen Hou <pshou@realtek.com.tw>
111da177e4SLinus Torvalds *
121da177e4SLinus Torvalds * CONTACTS:
131da177e4SLinus Torvalds *
141da177e4SLinus Torvalds * Matt Jared matt.jared@intel.com
151da177e4SLinus Torvalds * Andy Kopp andy.kopp@intel.com
161da177e4SLinus Torvalds * Dan Kogan dan.d.kogan@intel.com
171da177e4SLinus Torvalds *
181da177e4SLinus Torvalds * CHANGES:
191da177e4SLinus Torvalds *
201da177e4SLinus Torvalds * 2004.12.01 Major rewrite by tiwai, merged the work of pshou
211da177e4SLinus Torvalds */
221da177e4SLinus Torvalds
231da177e4SLinus Torvalds #include <linux/delay.h>
241da177e4SLinus Torvalds #include <linux/interrupt.h>
25362775e2SRandy Dunlap #include <linux/kernel.h>
261da177e4SLinus Torvalds #include <linux/module.h>
2724982c5fSAndrew Morton #include <linux/dma-mapping.h>
281da177e4SLinus Torvalds #include <linux/moduleparam.h>
291da177e4SLinus Torvalds #include <linux/init.h>
301da177e4SLinus Torvalds #include <linux/slab.h>
311da177e4SLinus Torvalds #include <linux/pci.h>
3262932df8SIngo Molnar #include <linux/mutex.h>
3327fe48d9STakashi Iwai #include <linux/io.h>
34b8dfc462SMengdong Lin #include <linux/pm_runtime.h>
355d890f59SPierre-Louis Bossart #include <linux/clocksource.h>
365d890f59SPierre-Louis Bossart #include <linux/time.h>
37f4c482a4STakashi Iwai #include <linux/completion.h>
38586bc4aaSAlex Deucher #include <linux/acpi.h>
3965fddcfcSMike Rapoport #include <linux/pgtable.h>
405d890f59SPierre-Louis Bossart
4127fe48d9STakashi Iwai #ifdef CONFIG_X86
4227fe48d9STakashi Iwai /* for snoop control */
437f80f513SLaura Abbott #include <asm/set_memory.h>
4450279d9bSGuneshwor Singh #include <asm/cpufeature.h>
4527fe48d9STakashi Iwai #endif
461da177e4SLinus Torvalds #include <sound/core.h>
471da177e4SLinus Torvalds #include <sound/initval.h>
4898d8fc6cSMengdong Lin #include <sound/hdaudio.h>
4998d8fc6cSMengdong Lin #include <sound/hda_i915.h>
5082d9d54aSJaroslav Kysela #include <sound/intel-dsp-config.h>
519121947dSTakashi Iwai #include <linux/vgaarb.h>
52a82d51edSTakashi Iwai #include <linux/vga_switcheroo.h>
535beb5627SOrlando Chamberlain #include <linux/apple-gmux.h>
544918cdabSTakashi Iwai #include <linux/firmware.h>
55be57bfffSPierre-Louis Bossart #include <sound/hda_codec.h>
5605e84878SDylan Reid #include "hda_controller.h"
57347de1f8SImre Deak #include "hda_intel.h"
581da177e4SLinus Torvalds
59785d8c4bSLibin Yang #define CREATE_TRACE_POINTS
60785d8c4bSLibin Yang #include "hda_intel_trace.h"
61785d8c4bSLibin Yang
62b6050ef6STakashi Iwai /* position fix mode */
63b6050ef6STakashi Iwai enum {
64b6050ef6STakashi Iwai POS_FIX_AUTO,
65b6050ef6STakashi Iwai POS_FIX_LPIB,
66b6050ef6STakashi Iwai POS_FIX_POSBUF,
67b6050ef6STakashi Iwai POS_FIX_VIACOMBO,
68b6050ef6STakashi Iwai POS_FIX_COMBO,
69f87e7f25STakashi Iwai POS_FIX_SKL,
70c02f77d3STakashi Iwai POS_FIX_FIFO,
71b6050ef6STakashi Iwai };
72b6050ef6STakashi Iwai
739a34af4aSTakashi Iwai /* Defines for ATI HD Audio support in SB450 south bridge */
749a34af4aSTakashi Iwai #define ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR 0x42
759a34af4aSTakashi Iwai #define ATI_SB450_HDAUDIO_ENABLE_SNOOP 0x02
769a34af4aSTakashi Iwai
779a34af4aSTakashi Iwai /* Defines for Nvidia HDA support */
789a34af4aSTakashi Iwai #define NVIDIA_HDA_TRANSREG_ADDR 0x4e
799a34af4aSTakashi Iwai #define NVIDIA_HDA_ENABLE_COHBITS 0x0f
809a34af4aSTakashi Iwai #define NVIDIA_HDA_ISTRM_COH 0x4d
819a34af4aSTakashi Iwai #define NVIDIA_HDA_OSTRM_COH 0x4c
829a34af4aSTakashi Iwai #define NVIDIA_HDA_ENABLE_COHBIT 0x01
839a34af4aSTakashi Iwai
849a34af4aSTakashi Iwai /* Defines for Intel SCH HDA snoop control */
856639484dSLibin Yang #define INTEL_HDA_CGCTL 0x48
866639484dSLibin Yang #define INTEL_HDA_CGCTL_MISCBDCGE (0x1 << 6)
879a34af4aSTakashi Iwai #define INTEL_SCH_HDA_DEVC 0x78
889a34af4aSTakashi Iwai #define INTEL_SCH_HDA_DEVC_NOSNOOP (0x1<<11)
899a34af4aSTakashi Iwai
9033124929STakashi Iwai /* max number of SDs */
9133124929STakashi Iwai /* ICH, ATI and VIA have 4 playback and 4 capture */
9233124929STakashi Iwai #define ICH6_NUM_CAPTURE 4
9333124929STakashi Iwai #define ICH6_NUM_PLAYBACK 4
9433124929STakashi Iwai
9533124929STakashi Iwai /* ULI has 6 playback and 5 capture */
9633124929STakashi Iwai #define ULI_NUM_CAPTURE 5
9733124929STakashi Iwai #define ULI_NUM_PLAYBACK 6
9833124929STakashi Iwai
9933124929STakashi Iwai /* ATI HDMI may have up to 8 playbacks and 0 capture */
10033124929STakashi Iwai #define ATIHDMI_NUM_CAPTURE 0
10133124929STakashi Iwai #define ATIHDMI_NUM_PLAYBACK 8
10233124929STakashi Iwai
1031da177e4SLinus Torvalds
1045aba4f8eSTakashi Iwai static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
1055aba4f8eSTakashi Iwai static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
106a67ff6a5SRusty Russell static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
1075aba4f8eSTakashi Iwai static char *model[SNDRV_CARDS];
1081dac6695STakashi Iwai static int position_fix[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = -1};
1095c0d7bc1STakashi Iwai static int bdl_pos_adj[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = -1};
1105aba4f8eSTakashi Iwai static int probe_mask[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = -1};
111d4d9cd03STakashi Iwai static int probe_only[SNDRV_CARDS];
11226a6cb6cSDavid Henningsson static int jackpoll_ms[SNDRV_CARDS];
11341438f13STakashi Iwai static int single_cmd = -1;
11471623855STakashi Iwai static int enable_msi = -1;
1154ea6fbc8STakashi Iwai #ifdef CONFIG_SND_HDA_PATCH_LOADER
1164ea6fbc8STakashi Iwai static char *patch[SNDRV_CARDS];
1174ea6fbc8STakashi Iwai #endif
1182dca0bbaSJaroslav Kysela #ifdef CONFIG_SND_HDA_INPUT_BEEP
1190920c9b4STakashi Iwai static bool beep_mode[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] =
1202dca0bbaSJaroslav Kysela CONFIG_SND_HDA_INPUT_BEEP_MODE};
1212dca0bbaSJaroslav Kysela #endif
1227fba6aeaSTakashi Iwai static bool dmic_detect = 1;
123d045bcefSJaroslav Kysela static bool ctl_dev_id = IS_ENABLED(CONFIG_SND_HDA_CTL_DEV_ID) ? 1 : 0;
1241da177e4SLinus Torvalds
1255aba4f8eSTakashi Iwai module_param_array(index, int, NULL, 0444);
1261da177e4SLinus Torvalds MODULE_PARM_DESC(index, "Index value for Intel HD audio interface.");
1275aba4f8eSTakashi Iwai module_param_array(id, charp, NULL, 0444);
1281da177e4SLinus Torvalds MODULE_PARM_DESC(id, "ID string for Intel HD audio interface.");
1295aba4f8eSTakashi Iwai module_param_array(enable, bool, NULL, 0444);
1305aba4f8eSTakashi Iwai MODULE_PARM_DESC(enable, "Enable Intel HD audio interface.");
1315aba4f8eSTakashi Iwai module_param_array(model, charp, NULL, 0444);
1321da177e4SLinus Torvalds MODULE_PARM_DESC(model, "Use the given board model.");
1335aba4f8eSTakashi Iwai module_param_array(position_fix, int, NULL, 0444);
1344cb36310SDavid Henningsson MODULE_PARM_DESC(position_fix, "DMA pointer read method."
135c02f77d3STakashi Iwai "(-1 = system default, 0 = auto, 1 = LPIB, 2 = POSBUF, 3 = VIACOMBO, 4 = COMBO, 5 = SKL+, 6 = FIFO).");
136555e219fSTakashi Iwai module_param_array(bdl_pos_adj, int, NULL, 0644);
137555e219fSTakashi Iwai MODULE_PARM_DESC(bdl_pos_adj, "BDL position adjustment offset.");
1385aba4f8eSTakashi Iwai module_param_array(probe_mask, int, NULL, 0444);
139606ad75fSTakashi Iwai MODULE_PARM_DESC(probe_mask, "Bitmask to probe codecs (default = -1).");
140079e683eSJaroslav Kysela module_param_array(probe_only, int, NULL, 0444);
141d4d9cd03STakashi Iwai MODULE_PARM_DESC(probe_only, "Only probing and no codec initialization.");
14226a6cb6cSDavid Henningsson module_param_array(jackpoll_ms, int, NULL, 0444);
14326a6cb6cSDavid Henningsson MODULE_PARM_DESC(jackpoll_ms, "Ms between polling for jack events (default = 0, using unsol events only)");
14441438f13STakashi Iwai module_param(single_cmd, bint, 0444);
145d01ce99fSTakashi Iwai MODULE_PARM_DESC(single_cmd, "Use single command to communicate with codecs "
146d01ce99fSTakashi Iwai "(for debugging only).");
147ac9ef6cfSTakashi Iwai module_param(enable_msi, bint, 0444);
148134a11f0STakashi Iwai MODULE_PARM_DESC(enable_msi, "Enable Message Signaled Interrupt (MSI)");
1494ea6fbc8STakashi Iwai #ifdef CONFIG_SND_HDA_PATCH_LOADER
1504ea6fbc8STakashi Iwai module_param_array(patch, charp, NULL, 0444);
1514ea6fbc8STakashi Iwai MODULE_PARM_DESC(patch, "Patch file for Intel HD audio interface.");
1524ea6fbc8STakashi Iwai #endif
1532dca0bbaSJaroslav Kysela #ifdef CONFIG_SND_HDA_INPUT_BEEP
1540920c9b4STakashi Iwai module_param_array(beep_mode, bool, NULL, 0444);
1552dca0bbaSJaroslav Kysela MODULE_PARM_DESC(beep_mode, "Select HDA Beep registration mode "
1560920c9b4STakashi Iwai "(0=off, 1=on) (default=1).");
1572dca0bbaSJaroslav Kysela #endif
1587fba6aeaSTakashi Iwai module_param(dmic_detect, bool, 0444);
1597fba6aeaSTakashi Iwai MODULE_PARM_DESC(dmic_detect, "Allow DSP driver selection (bypass this driver) "
1607fba6aeaSTakashi Iwai "(0=off, 1=on) (default=1); "
1617fba6aeaSTakashi Iwai "deprecated, use snd-intel-dspcfg.dsp_driver option instead");
162d045bcefSJaroslav Kysela module_param(ctl_dev_id, bool, 0444);
163d045bcefSJaroslav Kysela MODULE_PARM_DESC(ctl_dev_id, "Use control device identifier (based on codec address).");
164606ad75fSTakashi Iwai
16583012a7cSTakashi Iwai #ifdef CONFIG_PM
16665fcd41dSTakashi Iwai static int param_set_xint(const char *val, const struct kernel_param *kp);
1679c27847dSLuis R. Rodriguez static const struct kernel_param_ops param_ops_xint = {
16865fcd41dSTakashi Iwai .set = param_set_xint,
16965fcd41dSTakashi Iwai .get = param_get_int,
17065fcd41dSTakashi Iwai };
17165fcd41dSTakashi Iwai #define param_check_xint param_check_int
17265fcd41dSTakashi Iwai
173fee2fba3STakashi Iwai static int power_save = CONFIG_SND_HDA_POWER_SAVE_DEFAULT;
17465fcd41dSTakashi Iwai module_param(power_save, xint, 0644);
175fee2fba3STakashi Iwai MODULE_PARM_DESC(power_save, "Automatic power-saving timeout "
176fee2fba3STakashi Iwai "(in second, 0 = disable).");
1771da177e4SLinus Torvalds
17840088dc4STakashi Iwai static bool pm_blacklist = true;
17940088dc4STakashi Iwai module_param(pm_blacklist, bool, 0644);
1806317e5ebSTakashi Iwai MODULE_PARM_DESC(pm_blacklist, "Enable power-management denylist");
18140088dc4STakashi Iwai
182dee1b66cSTakashi Iwai /* reset the HD-audio controller in power save mode.
183dee1b66cSTakashi Iwai * this may give more power-saving, but will take longer time to
184dee1b66cSTakashi Iwai * wake up.
185dee1b66cSTakashi Iwai */
1868fc24426STakashi Iwai static bool power_save_controller = 1;
1878fc24426STakashi Iwai module_param(power_save_controller, bool, 0644);
188dee1b66cSTakashi Iwai MODULE_PARM_DESC(power_save_controller, "Reset controller in power save mode.");
189e62a42aeSDylan Reid #else
190bb573928STakashi Iwai #define power_save 0
19183012a7cSTakashi Iwai #endif /* CONFIG_PM */
192dee1b66cSTakashi Iwai
1937bfe059eSTakashi Iwai static int align_buffer_size = -1;
1947bfe059eSTakashi Iwai module_param(align_buffer_size, bint, 0644);
1952ae66c26SPierre-Louis Bossart MODULE_PARM_DESC(align_buffer_size,
1962ae66c26SPierre-Louis Bossart "Force buffer and period sizes to be multiple of 128 bytes.");
1972ae66c26SPierre-Louis Bossart
19827fe48d9STakashi Iwai #ifdef CONFIG_X86
1997c732015STakashi Iwai static int hda_snoop = -1;
2007c732015STakashi Iwai module_param_named(snoop, hda_snoop, bint, 0444);
20127fe48d9STakashi Iwai MODULE_PARM_DESC(snoop, "Enable/disable snooping");
20227fe48d9STakashi Iwai #else
20327fe48d9STakashi Iwai #define hda_snoop true
20427fe48d9STakashi Iwai #endif
20527fe48d9STakashi Iwai
20627fe48d9STakashi Iwai
2071da177e4SLinus Torvalds MODULE_LICENSE("GPL");
2081da177e4SLinus Torvalds MODULE_DESCRIPTION("Intel HDA driver");
2091da177e4SLinus Torvalds
210a82d51edSTakashi Iwai #if defined(CONFIG_PM) && defined(CONFIG_VGA_SWITCHEROO)
211f8f1becfSTakashi Iwai #if IS_ENABLED(CONFIG_SND_HDA_CODEC_HDMI)
212a82d51edSTakashi Iwai #define SUPPORT_VGA_SWITCHEROO
213a82d51edSTakashi Iwai #endif
214a82d51edSTakashi Iwai #endif
215a82d51edSTakashi Iwai
216a82d51edSTakashi Iwai
217cb53c626STakashi Iwai /*
2181da177e4SLinus Torvalds */
2191da177e4SLinus Torvalds
22007e4ca50STakashi Iwai /* driver types */
22107e4ca50STakashi Iwai enum {
22207e4ca50STakashi Iwai AZX_DRIVER_ICH,
22332679f95SSeth Heasley AZX_DRIVER_PCH,
2244979bca9STobin Davis AZX_DRIVER_SCH,
225a4b4793fSTakashi Iwai AZX_DRIVER_SKL,
226fab1285aSTakashi Iwai AZX_DRIVER_HDMI,
22707e4ca50STakashi Iwai AZX_DRIVER_ATI,
228778b6e1bSFelix Kuehling AZX_DRIVER_ATIHDMI,
2291815b34aSAndiry Xu AZX_DRIVER_ATIHDMI_NS,
230c51e4310Sjasontao AZX_DRIVER_GFHDMI,
23107e4ca50STakashi Iwai AZX_DRIVER_VIA,
23207e4ca50STakashi Iwai AZX_DRIVER_SIS,
23307e4ca50STakashi Iwai AZX_DRIVER_ULI,
234da3fca21SVinod G AZX_DRIVER_NVIDIA,
235f269002eSKailang Yang AZX_DRIVER_TERA,
23614d34f16STakashi Iwai AZX_DRIVER_CTX,
2375ae763b1STakashi Iwai AZX_DRIVER_CTHDA,
238c563f473STakashi Iwai AZX_DRIVER_CMEDIA,
239b6fcab14STony W Wang-oc AZX_DRIVER_ZHAOXIN,
24028bd137aSYanteng Si AZX_DRIVER_LOONGSON,
241c4da29caSYang, Libin AZX_DRIVER_GENERIC,
2422f5983f2STakashi Iwai AZX_NUM_DRIVERS, /* keep this as last entry */
24307e4ca50STakashi Iwai };
24407e4ca50STakashi Iwai
24537e661eeSTakashi Iwai #define azx_get_snoop_type(chip) \
24637e661eeSTakashi Iwai (((chip)->driver_caps & AZX_DCAPS_SNOOP_MASK) >> 10)
24737e661eeSTakashi Iwai #define AZX_DCAPS_SNOOP_TYPE(type) ((AZX_SNOOP_TYPE_ ## type) << 10)
24837e661eeSTakashi Iwai
249b42b4afbSTakashi Iwai /* quirks for old Intel chipsets */
250b42b4afbSTakashi Iwai #define AZX_DCAPS_INTEL_ICH \
251f34a4c9dSTakashi Iwai (AZX_DCAPS_OLD_SSYNC | AZX_DCAPS_NO_ALIGN_BUFSIZE)
252b42b4afbSTakashi Iwai
2532ea3c6a2STakashi Iwai /* quirks for Intel PCH */
2546603249dSTakashi Iwai #define AZX_DCAPS_INTEL_PCH_BASE \
255103884a3STakashi Iwai (AZX_DCAPS_NO_ALIGN_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY |\
256f34a4c9dSTakashi Iwai AZX_DCAPS_SNOOP_TYPE(SCH))
257d7dab4dbSTakashi Iwai
258dba9b7b6STakashi Iwai /* PCH up to IVB; no runtime PM; bind with i915 gfx */
2596603249dSTakashi Iwai #define AZX_DCAPS_INTEL_PCH_NOPM \
260dba9b7b6STakashi Iwai (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_I915_COMPONENT)
2619477c58eSTakashi Iwai
26255913110STakashi Iwai /* PCH for HSW/BDW; with runtime PM */
263dba9b7b6STakashi Iwai /* no i915 binding for this as HSW/BDW has another controller for HDMI */
2646603249dSTakashi Iwai #define AZX_DCAPS_INTEL_PCH \
265f5dac54dSKai-Heng Feng (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_PM_RUNTIME)
2666603249dSTakashi Iwai
2676603249dSTakashi Iwai /* HSW HDMI */
26833499a15STakashi Iwai #define AZX_DCAPS_INTEL_HASWELL \
269103884a3STakashi Iwai (/*AZX_DCAPS_ALIGN_BUFSIZE |*/ AZX_DCAPS_COUNT_LPIB_DELAY |\
270dba9b7b6STakashi Iwai AZX_DCAPS_PM_RUNTIME | AZX_DCAPS_I915_COMPONENT |\
271f34a4c9dSTakashi Iwai AZX_DCAPS_SNOOP_TYPE(SCH))
27233499a15STakashi Iwai
27354a0405dSLibin Yang /* Broadwell HDMI can't use position buffer reliably, force to use LPIB */
27454a0405dSLibin Yang #define AZX_DCAPS_INTEL_BROADWELL \
275103884a3STakashi Iwai (/*AZX_DCAPS_ALIGN_BUFSIZE |*/ AZX_DCAPS_POSFIX_LPIB |\
276dba9b7b6STakashi Iwai AZX_DCAPS_PM_RUNTIME | AZX_DCAPS_I915_COMPONENT |\
277f34a4c9dSTakashi Iwai AZX_DCAPS_SNOOP_TYPE(SCH))
27854a0405dSLibin Yang
27940cc2392SMengdong Lin #define AZX_DCAPS_INTEL_BAYTRAIL \
280e454ff8eSTakashi Iwai (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_I915_COMPONENT)
28140cc2392SMengdong Lin
2822d846c74SLibin Yang #define AZX_DCAPS_INTEL_BRASWELL \
283dba9b7b6STakashi Iwai (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_PM_RUNTIME |\
284e454ff8eSTakashi Iwai AZX_DCAPS_I915_COMPONENT)
2852d846c74SLibin Yang
286d6795827SLibin Yang #define AZX_DCAPS_INTEL_SKYLAKE \
287dba9b7b6STakashi Iwai (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_PM_RUNTIME |\
288e454ff8eSTakashi Iwai AZX_DCAPS_SEPARATE_STREAM_TAG | AZX_DCAPS_I915_COMPONENT)
289d6795827SLibin Yang
2902756d914STakashi Iwai #define AZX_DCAPS_INTEL_BROXTON AZX_DCAPS_INTEL_SKYLAKE
291c87693daSLu, Han
2929477c58eSTakashi Iwai /* quirks for ATI SB / AMD Hudson */
2939477c58eSTakashi Iwai #define AZX_DCAPS_PRESET_ATI_SB \
294f34a4c9dSTakashi Iwai (AZX_DCAPS_NO_TCSEL | AZX_DCAPS_POSFIX_LPIB |\
29537e661eeSTakashi Iwai AZX_DCAPS_SNOOP_TYPE(ATI))
2969477c58eSTakashi Iwai
2979477c58eSTakashi Iwai /* quirks for ATI/AMD HDMI */
2989477c58eSTakashi Iwai #define AZX_DCAPS_PRESET_ATI_HDMI \
299f34a4c9dSTakashi Iwai (AZX_DCAPS_NO_TCSEL | AZX_DCAPS_POSFIX_LPIB|\
300db79afa1SBenjamin Herrenschmidt AZX_DCAPS_NO_MSI64)
3019477c58eSTakashi Iwai
30237e661eeSTakashi Iwai /* quirks for ATI HDMI with snoop off */
30337e661eeSTakashi Iwai #define AZX_DCAPS_PRESET_ATI_HDMI_NS \
304b8c0aee7STakashi Iwai (AZX_DCAPS_PRESET_ATI_HDMI | AZX_DCAPS_SNOOP_OFF)
30537e661eeSTakashi Iwai
306c02f77d3STakashi Iwai /* quirks for AMD SB */
307c02f77d3STakashi Iwai #define AZX_DCAPS_PRESET_AMD_SB \
308f34a4c9dSTakashi Iwai (AZX_DCAPS_NO_TCSEL | AZX_DCAPS_AMD_WORKAROUND |\
309c0f1886dSTakashi Iwai AZX_DCAPS_SNOOP_TYPE(ATI) | AZX_DCAPS_PM_RUNTIME |\
310c0f1886dSTakashi Iwai AZX_DCAPS_RETRY_PROBE)
311c02f77d3STakashi Iwai
3129477c58eSTakashi Iwai /* quirks for Nvidia */
3139477c58eSTakashi Iwai #define AZX_DCAPS_PRESET_NVIDIA \
3143ab7511eSArd Biesheuvel (AZX_DCAPS_NO_MSI | AZX_DCAPS_CORBRP_SELF_CLEAR |\
31537e661eeSTakashi Iwai AZX_DCAPS_SNOOP_TYPE(NVIDIA))
3169477c58eSTakashi Iwai
3175ae763b1STakashi Iwai #define AZX_DCAPS_PRESET_CTHDA \
31837e661eeSTakashi Iwai (AZX_DCAPS_NO_MSI | AZX_DCAPS_POSFIX_LPIB |\
319cadd16eaSTakashi Iwai AZX_DCAPS_NO_64BIT |\
32037e661eeSTakashi Iwai AZX_DCAPS_4K_BDLE_BOUNDARY | AZX_DCAPS_SNOOP_OFF)
3215ae763b1STakashi Iwai
322a82d51edSTakashi Iwai /*
3232b760d88SLukas Wunner * vga_switcheroo support
324a82d51edSTakashi Iwai */
325a82d51edSTakashi Iwai #ifdef SUPPORT_VGA_SWITCHEROO
3265cb543dbSTakashi Iwai #define use_vga_switcheroo(chip) ((chip)->use_vga_switcheroo)
327dd23e1d5STakashi Iwai #define needs_eld_notify_link(chip) ((chip)->bus.keep_power)
3285cb543dbSTakashi Iwai #else
3295cb543dbSTakashi Iwai #define use_vga_switcheroo(chip) 0
33037a3a98eSTakashi Iwai #define needs_eld_notify_link(chip) false
3315cb543dbSTakashi Iwai #endif
3325cb543dbSTakashi Iwai
333bf82326fSTakashi Iwai static const char * const driver_short_names[] = {
33407e4ca50STakashi Iwai [AZX_DRIVER_ICH] = "HDA Intel",
33532679f95SSeth Heasley [AZX_DRIVER_PCH] = "HDA Intel PCH",
3364979bca9STobin Davis [AZX_DRIVER_SCH] = "HDA Intel MID",
337a4b4793fSTakashi Iwai [AZX_DRIVER_SKL] = "HDA Intel PCH", /* kept old name for compatibility */
338fab1285aSTakashi Iwai [AZX_DRIVER_HDMI] = "HDA Intel HDMI",
33907e4ca50STakashi Iwai [AZX_DRIVER_ATI] = "HDA ATI SB",
340778b6e1bSFelix Kuehling [AZX_DRIVER_ATIHDMI] = "HDA ATI HDMI",
3411815b34aSAndiry Xu [AZX_DRIVER_ATIHDMI_NS] = "HDA ATI HDMI",
342c51e4310Sjasontao [AZX_DRIVER_GFHDMI] = "HDA GF HDMI",
34307e4ca50STakashi Iwai [AZX_DRIVER_VIA] = "HDA VIA VT82xx",
34407e4ca50STakashi Iwai [AZX_DRIVER_SIS] = "HDA SIS966",
345da3fca21SVinod G [AZX_DRIVER_ULI] = "HDA ULI M5461",
346da3fca21SVinod G [AZX_DRIVER_NVIDIA] = "HDA NVidia",
347f269002eSKailang Yang [AZX_DRIVER_TERA] = "HDA Teradici",
34814d34f16STakashi Iwai [AZX_DRIVER_CTX] = "HDA Creative",
3495ae763b1STakashi Iwai [AZX_DRIVER_CTHDA] = "HDA Creative",
350c563f473STakashi Iwai [AZX_DRIVER_CMEDIA] = "HDA C-Media",
351b6fcab14STony W Wang-oc [AZX_DRIVER_ZHAOXIN] = "HDA Zhaoxin",
35228bd137aSYanteng Si [AZX_DRIVER_LOONGSON] = "HDA Loongson",
353c4da29caSYang, Libin [AZX_DRIVER_GENERIC] = "HD-Audio Generic",
35407e4ca50STakashi Iwai };
35507e4ca50STakashi Iwai
35668e7fffcSTakashi Iwai static int azx_acquire_irq(struct azx *chip, int do_disconnect);
35737a3a98eSTakashi Iwai static void set_default_power_save(struct azx *chip);
358111d3af5STakashi Iwai
359cb53c626STakashi Iwai /*
360cb53c626STakashi Iwai * initialize the PCI registers
361cb53c626STakashi Iwai */
362cb53c626STakashi Iwai /* update bits in a PCI register byte */
update_pci_byte(struct pci_dev * pci,unsigned int reg,unsigned char mask,unsigned char val)363cb53c626STakashi Iwai static void update_pci_byte(struct pci_dev *pci, unsigned int reg,
364cb53c626STakashi Iwai unsigned char mask, unsigned char val)
365cb53c626STakashi Iwai {
366cb53c626STakashi Iwai unsigned char data;
367cb53c626STakashi Iwai
368cb53c626STakashi Iwai pci_read_config_byte(pci, reg, &data);
369cb53c626STakashi Iwai data &= ~mask;
370cb53c626STakashi Iwai data |= (val & mask);
371cb53c626STakashi Iwai pci_write_config_byte(pci, reg, data);
372cb53c626STakashi Iwai }
373cb53c626STakashi Iwai
azx_init_pci(struct azx * chip)374cb53c626STakashi Iwai static void azx_init_pci(struct azx *chip)
375cb53c626STakashi Iwai {
37637e661eeSTakashi Iwai int snoop_type = azx_get_snoop_type(chip);
37737e661eeSTakashi Iwai
378cb53c626STakashi Iwai /* Clear bits 0-2 of PCI register TCSEL (at offset 0x44)
379cb53c626STakashi Iwai * TCSEL == Traffic Class Select Register, which sets PCI express QOS
380cb53c626STakashi Iwai * Ensuring these bits are 0 clears playback static on some HD Audio
381a09e89f6SAdam Lackorzynski * codecs.
382a09e89f6SAdam Lackorzynski * The PCI register TCSEL is defined in the Intel manuals.
383cb53c626STakashi Iwai */
38446f2cc80SLinus Torvalds if (!(chip->driver_caps & AZX_DCAPS_NO_TCSEL)) {
3854e76a883STakashi Iwai dev_dbg(chip->card->dev, "Clearing TCSEL\n");
386fb1d8ac2STakashi Iwai update_pci_byte(chip->pci, AZX_PCIREG_TCSEL, 0x07, 0);
3879477c58eSTakashi Iwai }
388cb53c626STakashi Iwai
3899477c58eSTakashi Iwai /* For ATI SB450/600/700/800/900 and AMD Hudson azalia HD audio,
3909477c58eSTakashi Iwai * we need to enable snoop.
3919477c58eSTakashi Iwai */
39237e661eeSTakashi Iwai if (snoop_type == AZX_SNOOP_TYPE_ATI) {
3934e76a883STakashi Iwai dev_dbg(chip->card->dev, "Setting ATI snoop: %d\n",
3944e76a883STakashi Iwai azx_snoop(chip));
395cb53c626STakashi Iwai update_pci_byte(chip->pci,
39627fe48d9STakashi Iwai ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR, 0x07,
39727fe48d9STakashi Iwai azx_snoop(chip) ? ATI_SB450_HDAUDIO_ENABLE_SNOOP : 0);
3989477c58eSTakashi Iwai }
3999477c58eSTakashi Iwai
400da3fca21SVinod G /* For NVIDIA HDA, enable snoop */
40137e661eeSTakashi Iwai if (snoop_type == AZX_SNOOP_TYPE_NVIDIA) {
4024e76a883STakashi Iwai dev_dbg(chip->card->dev, "Setting Nvidia snoop: %d\n",
4034e76a883STakashi Iwai azx_snoop(chip));
404cb53c626STakashi Iwai update_pci_byte(chip->pci,
405cb53c626STakashi Iwai NVIDIA_HDA_TRANSREG_ADDR,
406cb53c626STakashi Iwai 0x0f, NVIDIA_HDA_ENABLE_COHBITS);
407320dcc30SPeer Chen update_pci_byte(chip->pci,
408320dcc30SPeer Chen NVIDIA_HDA_ISTRM_COH,
409320dcc30SPeer Chen 0x01, NVIDIA_HDA_ENABLE_COHBIT);
410320dcc30SPeer Chen update_pci_byte(chip->pci,
411320dcc30SPeer Chen NVIDIA_HDA_OSTRM_COH,
412320dcc30SPeer Chen 0x01, NVIDIA_HDA_ENABLE_COHBIT);
4139477c58eSTakashi Iwai }
4149477c58eSTakashi Iwai
4159477c58eSTakashi Iwai /* Enable SCH/PCH snoop if needed */
41637e661eeSTakashi Iwai if (snoop_type == AZX_SNOOP_TYPE_SCH) {
41727fe48d9STakashi Iwai unsigned short snoop;
41890a5ad52STakashi Iwai pci_read_config_word(chip->pci, INTEL_SCH_HDA_DEVC, &snoop);
41927fe48d9STakashi Iwai if ((!azx_snoop(chip) && !(snoop & INTEL_SCH_HDA_DEVC_NOSNOOP)) ||
42027fe48d9STakashi Iwai (azx_snoop(chip) && (snoop & INTEL_SCH_HDA_DEVC_NOSNOOP))) {
42127fe48d9STakashi Iwai snoop &= ~INTEL_SCH_HDA_DEVC_NOSNOOP;
42227fe48d9STakashi Iwai if (!azx_snoop(chip))
42327fe48d9STakashi Iwai snoop |= INTEL_SCH_HDA_DEVC_NOSNOOP;
42427fe48d9STakashi Iwai pci_write_config_word(chip->pci, INTEL_SCH_HDA_DEVC, snoop);
42590a5ad52STakashi Iwai pci_read_config_word(chip->pci,
42690a5ad52STakashi Iwai INTEL_SCH_HDA_DEVC, &snoop);
42790a5ad52STakashi Iwai }
4284e76a883STakashi Iwai dev_dbg(chip->card->dev, "SCH snoop: %s\n",
4294e76a883STakashi Iwai (snoop & INTEL_SCH_HDA_DEVC_NOSNOOP) ?
4304e76a883STakashi Iwai "Disabled" : "Enabled");
431f5d40b30SFrederick Li }
4321da177e4SLinus Torvalds }
4331da177e4SLinus Torvalds
4347c23b7c1SLu, Han /*
4357c23b7c1SLu, Han * In BXT-P A0, HD-Audio DMA requests is later than expected,
4367c23b7c1SLu, Han * and makes an audio stream sensitive to system latencies when
4377c23b7c1SLu, Han * 24/32 bits are playing.
4387c23b7c1SLu, Han * Adjusting threshold of DMA fifo to force the DMA request
4397c23b7c1SLu, Han * sooner to improve latency tolerance at the expense of power.
4407c23b7c1SLu, Han */
bxt_reduce_dma_latency(struct azx * chip)4417c23b7c1SLu, Han static void bxt_reduce_dma_latency(struct azx *chip)
4427c23b7c1SLu, Han {
4437c23b7c1SLu, Han u32 val;
4447c23b7c1SLu, Han
44570eafad8STakashi Iwai val = azx_readl(chip, VS_EM4L);
4467c23b7c1SLu, Han val &= (0x3 << 20);
44770eafad8STakashi Iwai azx_writel(chip, VS_EM4L, val);
4487c23b7c1SLu, Han }
4497c23b7c1SLu, Han
4501f9d3d98SLibin Yang /*
4511f9d3d98SLibin Yang * ML_LCAP bits:
4521f9d3d98SLibin Yang * bit 0: 6 MHz Supported
4531f9d3d98SLibin Yang * bit 1: 12 MHz Supported
4541f9d3d98SLibin Yang * bit 2: 24 MHz Supported
4551f9d3d98SLibin Yang * bit 3: 48 MHz Supported
4561f9d3d98SLibin Yang * bit 4: 96 MHz Supported
4571f9d3d98SLibin Yang * bit 5: 192 MHz Supported
4581f9d3d98SLibin Yang */
intel_get_lctl_scf(struct azx * chip)4591f9d3d98SLibin Yang static int intel_get_lctl_scf(struct azx *chip)
4601f9d3d98SLibin Yang {
4611f9d3d98SLibin Yang struct hdac_bus *bus = azx_bus(chip);
462bf82326fSTakashi Iwai static const int preferred_bits[] = { 2, 3, 1, 4, 5 };
4631f9d3d98SLibin Yang u32 val, t;
4641f9d3d98SLibin Yang int i;
4651f9d3d98SLibin Yang
4661f9d3d98SLibin Yang val = readl(bus->mlcap + AZX_ML_BASE + AZX_REG_ML_LCAP);
4671f9d3d98SLibin Yang
4681f9d3d98SLibin Yang for (i = 0; i < ARRAY_SIZE(preferred_bits); i++) {
4691f9d3d98SLibin Yang t = preferred_bits[i];
4701f9d3d98SLibin Yang if (val & (1 << t))
4711f9d3d98SLibin Yang return t;
4721f9d3d98SLibin Yang }
4731f9d3d98SLibin Yang
4741f9d3d98SLibin Yang dev_warn(chip->card->dev, "set audio clock frequency to 6MHz");
4751f9d3d98SLibin Yang return 0;
4761f9d3d98SLibin Yang }
4771f9d3d98SLibin Yang
intel_ml_lctl_set_power(struct azx * chip,int state)4781f9d3d98SLibin Yang static int intel_ml_lctl_set_power(struct azx *chip, int state)
4791f9d3d98SLibin Yang {
4801f9d3d98SLibin Yang struct hdac_bus *bus = azx_bus(chip);
4811f9d3d98SLibin Yang u32 val;
4821f9d3d98SLibin Yang int timeout;
4831f9d3d98SLibin Yang
4841f9d3d98SLibin Yang /*
48510e794bdSPierre-Louis Bossart * Changes to LCTL.SCF are only needed for the first multi-link dealing
48610e794bdSPierre-Louis Bossart * with external codecs
4871f9d3d98SLibin Yang */
4881f9d3d98SLibin Yang val = readl(bus->mlcap + AZX_ML_BASE + AZX_REG_ML_LCTL);
48918afcf90SPierre-Louis Bossart val &= ~AZX_ML_LCTL_SPA;
49018afcf90SPierre-Louis Bossart val |= state << AZX_ML_LCTL_SPA_SHIFT;
4911f9d3d98SLibin Yang writel(val, bus->mlcap + AZX_ML_BASE + AZX_REG_ML_LCTL);
4921f9d3d98SLibin Yang /* wait for CPA */
4931f9d3d98SLibin Yang timeout = 50;
4941f9d3d98SLibin Yang while (timeout) {
4951f9d3d98SLibin Yang if (((readl(bus->mlcap + AZX_ML_BASE + AZX_REG_ML_LCTL)) &
49618afcf90SPierre-Louis Bossart AZX_ML_LCTL_CPA) == (state << AZX_ML_LCTL_CPA_SHIFT))
4971f9d3d98SLibin Yang return 0;
4981f9d3d98SLibin Yang timeout--;
4991f9d3d98SLibin Yang udelay(10);
5001f9d3d98SLibin Yang }
5011f9d3d98SLibin Yang
5021f9d3d98SLibin Yang return -1;
5031f9d3d98SLibin Yang }
5041f9d3d98SLibin Yang
intel_init_lctl(struct azx * chip)5051f9d3d98SLibin Yang static void intel_init_lctl(struct azx *chip)
5061f9d3d98SLibin Yang {
5071f9d3d98SLibin Yang struct hdac_bus *bus = azx_bus(chip);
5081f9d3d98SLibin Yang u32 val;
5091f9d3d98SLibin Yang int ret;
5101f9d3d98SLibin Yang
5111f9d3d98SLibin Yang /* 0. check lctl register value is correct or not */
5121f9d3d98SLibin Yang val = readl(bus->mlcap + AZX_ML_BASE + AZX_REG_ML_LCTL);
51310e794bdSPierre-Louis Bossart /* only perform additional configurations if the SCF is initially based on 6MHz */
51418afcf90SPierre-Louis Bossart if ((val & AZX_ML_LCTL_SCF) != 0)
5151f9d3d98SLibin Yang return;
5161f9d3d98SLibin Yang
5171f9d3d98SLibin Yang /*
5181f9d3d98SLibin Yang * Before operating on SPA, CPA must match SPA.
5191f9d3d98SLibin Yang * Any deviation may result in undefined behavior.
5201f9d3d98SLibin Yang */
52118afcf90SPierre-Louis Bossart if (((val & AZX_ML_LCTL_SPA) >> AZX_ML_LCTL_SPA_SHIFT) !=
52218afcf90SPierre-Louis Bossart ((val & AZX_ML_LCTL_CPA) >> AZX_ML_LCTL_CPA_SHIFT))
5231f9d3d98SLibin Yang return;
5241f9d3d98SLibin Yang
5251f9d3d98SLibin Yang /* 1. turn link down: set SPA to 0 and wait CPA to 0 */
5261f9d3d98SLibin Yang ret = intel_ml_lctl_set_power(chip, 0);
5271f9d3d98SLibin Yang udelay(100);
5281f9d3d98SLibin Yang if (ret)
5291f9d3d98SLibin Yang goto set_spa;
5301f9d3d98SLibin Yang
53110e794bdSPierre-Louis Bossart /* 2. update SCF to select an audio clock different from 6MHz */
53218afcf90SPierre-Louis Bossart val &= ~AZX_ML_LCTL_SCF;
5331f9d3d98SLibin Yang val |= intel_get_lctl_scf(chip);
5341f9d3d98SLibin Yang writel(val, bus->mlcap + AZX_ML_BASE + AZX_REG_ML_LCTL);
5351f9d3d98SLibin Yang
5361f9d3d98SLibin Yang set_spa:
5371f9d3d98SLibin Yang /* 4. turn link up: set SPA to 1 and wait CPA to 1 */
5381f9d3d98SLibin Yang intel_ml_lctl_set_power(chip, 1);
5391f9d3d98SLibin Yang udelay(100);
5401f9d3d98SLibin Yang }
5411f9d3d98SLibin Yang
hda_intel_init_chip(struct azx * chip,bool full_reset)5420a673521SLu, Han static void hda_intel_init_chip(struct azx *chip, bool full_reset)
5430a673521SLu, Han {
54498d8fc6cSMengdong Lin struct hdac_bus *bus = azx_bus(chip);
5457c23b7c1SLu, Han struct pci_dev *pci = chip->pci;
5466639484dSLibin Yang u32 val;
5470a673521SLu, Han
54898d8fc6cSMengdong Lin snd_hdac_set_codec_wakeup(bus, true);
549a4b4793fSTakashi Iwai if (chip->driver_type == AZX_DRIVER_SKL) {
5506639484dSLibin Yang pci_read_config_dword(pci, INTEL_HDA_CGCTL, &val);
5516639484dSLibin Yang val = val & ~INTEL_HDA_CGCTL_MISCBDCGE;
5526639484dSLibin Yang pci_write_config_dword(pci, INTEL_HDA_CGCTL, val);
5536639484dSLibin Yang }
5540a673521SLu, Han azx_init_chip(chip, full_reset);
555a4b4793fSTakashi Iwai if (chip->driver_type == AZX_DRIVER_SKL) {
5566639484dSLibin Yang pci_read_config_dword(pci, INTEL_HDA_CGCTL, &val);
5576639484dSLibin Yang val = val | INTEL_HDA_CGCTL_MISCBDCGE;
5586639484dSLibin Yang pci_write_config_dword(pci, INTEL_HDA_CGCTL, val);
5596639484dSLibin Yang }
560e454ff8eSTakashi Iwai
56198d8fc6cSMengdong Lin snd_hdac_set_codec_wakeup(bus, false);
5627c23b7c1SLu, Han
5637c23b7c1SLu, Han /* reduce dma latency to avoid noise */
5641b21bd7aSAmadeusz Sławiński if (HDA_CONTROLLER_IS_APL(pci))
5657c23b7c1SLu, Han bxt_reduce_dma_latency(chip);
5661f9d3d98SLibin Yang
5671f9d3d98SLibin Yang if (bus->mlcap != NULL)
5681f9d3d98SLibin Yang intel_init_lctl(chip);
5690a673521SLu, Han }
5700a673521SLu, Han
571b6050ef6STakashi Iwai /* calculate runtime delay from LPIB */
azx_get_delay_from_lpib(struct azx * chip,struct azx_dev * azx_dev,unsigned int pos)572b6050ef6STakashi Iwai static int azx_get_delay_from_lpib(struct azx *chip, struct azx_dev *azx_dev,
573b6050ef6STakashi Iwai unsigned int pos)
574b6050ef6STakashi Iwai {
5757833c3f8STakashi Iwai struct snd_pcm_substream *substream = azx_dev->core.substream;
576b6050ef6STakashi Iwai int stream = substream->stream;
577b6050ef6STakashi Iwai unsigned int lpib_pos = azx_get_pos_lpib(chip, azx_dev);
578b6050ef6STakashi Iwai int delay;
579b6050ef6STakashi Iwai
580b6050ef6STakashi Iwai if (stream == SNDRV_PCM_STREAM_PLAYBACK)
581b6050ef6STakashi Iwai delay = pos - lpib_pos;
582b6050ef6STakashi Iwai else
583b6050ef6STakashi Iwai delay = lpib_pos - pos;
584b6050ef6STakashi Iwai if (delay < 0) {
5857833c3f8STakashi Iwai if (delay >= azx_dev->core.delay_negative_threshold)
586b6050ef6STakashi Iwai delay = 0;
587b6050ef6STakashi Iwai else
5887833c3f8STakashi Iwai delay += azx_dev->core.bufsize;
589b6050ef6STakashi Iwai }
590b6050ef6STakashi Iwai
5917833c3f8STakashi Iwai if (delay >= azx_dev->core.period_bytes) {
592b6050ef6STakashi Iwai dev_info(chip->card->dev,
593b6050ef6STakashi Iwai "Unstable LPIB (%d >= %d); disabling LPIB delay counting\n",
5947833c3f8STakashi Iwai delay, azx_dev->core.period_bytes);
595b6050ef6STakashi Iwai delay = 0;
596b6050ef6STakashi Iwai chip->driver_caps &= ~AZX_DCAPS_COUNT_LPIB_DELAY;
597b6050ef6STakashi Iwai chip->get_delay[stream] = NULL;
598b6050ef6STakashi Iwai }
599b6050ef6STakashi Iwai
600b6050ef6STakashi Iwai return bytes_to_frames(substream->runtime, delay);
601b6050ef6STakashi Iwai }
602b6050ef6STakashi Iwai
6039ad593f6STakashi Iwai static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev);
6049ad593f6STakashi Iwai
6057ca954a8SDylan Reid /* called from IRQ */
azx_position_check(struct azx * chip,struct azx_dev * azx_dev)6067ca954a8SDylan Reid static int azx_position_check(struct azx *chip, struct azx_dev *azx_dev)
6077ca954a8SDylan Reid {
6089a34af4aSTakashi Iwai struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
6097ca954a8SDylan Reid int ok;
6107ca954a8SDylan Reid
6117ca954a8SDylan Reid ok = azx_position_ok(chip, azx_dev);
6127ca954a8SDylan Reid if (ok == 1) {
6137ca954a8SDylan Reid azx_dev->irq_pending = 0;
6147ca954a8SDylan Reid return ok;
6152f35c630STakashi Iwai } else if (ok == 0) {
6167ca954a8SDylan Reid /* bogus IRQ, process it later */
6177ca954a8SDylan Reid azx_dev->irq_pending = 1;
6182f35c630STakashi Iwai schedule_work(&hda->irq_pending_work);
6197ca954a8SDylan Reid }
6207ca954a8SDylan Reid return 0;
6217ca954a8SDylan Reid }
6227ca954a8SDylan Reid
623029d92c2STakashi Iwai #define display_power(chip, enable) \
624029d92c2STakashi Iwai snd_hdac_display_power(azx_bus(chip), HDA_CODEC_IDX_CONTROLLER, enable)
62517eccb27SMengdong Lin
6261da177e4SLinus Torvalds /*
6279ad593f6STakashi Iwai * Check whether the current DMA position is acceptable for updating
6289ad593f6STakashi Iwai * periods. Returns non-zero if it's OK.
6299ad593f6STakashi Iwai *
6309ad593f6STakashi Iwai * Many HD-audio controllers appear pretty inaccurate about
6319ad593f6STakashi Iwai * the update-IRQ timing. The IRQ is issued before actually the
6329ad593f6STakashi Iwai * data is processed. So, we need to process it afterwords in a
6339ad593f6STakashi Iwai * workqueue.
63446243b85STakashi Iwai *
63546243b85STakashi Iwai * Returns 1 if OK to proceed, 0 for delay handling, -1 for skipping update
6369ad593f6STakashi Iwai */
azx_position_ok(struct azx * chip,struct azx_dev * azx_dev)6379ad593f6STakashi Iwai static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev)
6389ad593f6STakashi Iwai {
6397833c3f8STakashi Iwai struct snd_pcm_substream *substream = azx_dev->core.substream;
64046243b85STakashi Iwai struct snd_pcm_runtime *runtime = substream->runtime;
641b6050ef6STakashi Iwai int stream = substream->stream;
642e5463720SJaroslav Kysela u32 wallclk;
6439ad593f6STakashi Iwai unsigned int pos;
64446243b85STakashi Iwai snd_pcm_uframes_t hwptr, target;
6459ad593f6STakashi Iwai
646a4d2b853SYanteng Si /*
647a4d2b853SYanteng Si * The value of the WALLCLK register is always 0
648a4d2b853SYanteng Si * on the Loongson controller, so we return directly.
649a4d2b853SYanteng Si */
650a4d2b853SYanteng Si if (chip->driver_type == AZX_DRIVER_LOONGSON)
651a4d2b853SYanteng Si return 1;
652a4d2b853SYanteng Si
6537833c3f8STakashi Iwai wallclk = azx_readl(chip, WALLCLK) - azx_dev->core.start_wallclk;
6547833c3f8STakashi Iwai if (wallclk < (azx_dev->core.period_wallclk * 2) / 3)
655fa00e046SJaroslav Kysela return -1; /* bogus (too early) interrupt */
656fa00e046SJaroslav Kysela
657b6050ef6STakashi Iwai if (chip->get_position[stream])
658b6050ef6STakashi Iwai pos = chip->get_position[stream](chip, azx_dev);
659b6050ef6STakashi Iwai else { /* use the position buffer as default */
660b6050ef6STakashi Iwai pos = azx_get_pos_posbuf(chip, azx_dev);
661b6050ef6STakashi Iwai if (!pos || pos == (u32)-1) {
662b6050ef6STakashi Iwai dev_info(chip->card->dev,
663b6050ef6STakashi Iwai "Invalid position buffer, using LPIB read method instead.\n");
664b6050ef6STakashi Iwai chip->get_position[stream] = azx_get_pos_lpib;
665ccc98865STakashi Iwai if (chip->get_position[0] == azx_get_pos_lpib &&
666ccc98865STakashi Iwai chip->get_position[1] == azx_get_pos_lpib)
667ccc98865STakashi Iwai azx_bus(chip)->use_posbuf = false;
668b6050ef6STakashi Iwai pos = azx_get_pos_lpib(chip, azx_dev);
669b6050ef6STakashi Iwai chip->get_delay[stream] = NULL;
670b6050ef6STakashi Iwai } else {
671b6050ef6STakashi Iwai chip->get_position[stream] = azx_get_pos_posbuf;
672b6050ef6STakashi Iwai if (chip->driver_caps & AZX_DCAPS_COUNT_LPIB_DELAY)
673b6050ef6STakashi Iwai chip->get_delay[stream] = azx_get_delay_from_lpib;
674b6050ef6STakashi Iwai }
675b6050ef6STakashi Iwai }
676b6050ef6STakashi Iwai
6777833c3f8STakashi Iwai if (pos >= azx_dev->core.bufsize)
678b6050ef6STakashi Iwai pos = 0;
6799ad593f6STakashi Iwai
6807833c3f8STakashi Iwai if (WARN_ONCE(!azx_dev->core.period_bytes,
681d6d8bf54STakashi Iwai "hda-intel: zero azx_dev->period_bytes"))
682f48f606dSJaroslav Kysela return -1; /* this shouldn't happen! */
6837833c3f8STakashi Iwai if (wallclk < (azx_dev->core.period_wallclk * 5) / 4 &&
6847833c3f8STakashi Iwai pos % azx_dev->core.period_bytes > azx_dev->core.period_bytes / 2)
685f48f606dSJaroslav Kysela /* NG - it's below the first next period boundary */
6864f0189beSTakashi Iwai return chip->bdl_pos_adj ? 0 : -1;
6877833c3f8STakashi Iwai azx_dev->core.start_wallclk += wallclk;
68846243b85STakashi Iwai
68946243b85STakashi Iwai if (azx_dev->core.no_period_wakeup)
69046243b85STakashi Iwai return 1; /* OK, no need to check period boundary */
69146243b85STakashi Iwai
69246243b85STakashi Iwai if (runtime->hw_ptr_base != runtime->hw_ptr_interrupt)
69346243b85STakashi Iwai return 1; /* OK, already in hwptr updating process */
69446243b85STakashi Iwai
69546243b85STakashi Iwai /* check whether the period gets really elapsed */
69646243b85STakashi Iwai pos = bytes_to_frames(runtime, pos);
69746243b85STakashi Iwai hwptr = runtime->hw_ptr_base + pos;
69846243b85STakashi Iwai if (hwptr < runtime->status->hw_ptr)
69946243b85STakashi Iwai hwptr += runtime->buffer_size;
70046243b85STakashi Iwai target = runtime->hw_ptr_interrupt + runtime->period_size;
70146243b85STakashi Iwai if (hwptr < target) {
70246243b85STakashi Iwai /* too early wakeup, process it later */
70346243b85STakashi Iwai return chip->bdl_pos_adj ? 0 : -1;
70446243b85STakashi Iwai }
70546243b85STakashi Iwai
7069ad593f6STakashi Iwai return 1; /* OK, it's fine */
7079ad593f6STakashi Iwai }
7089ad593f6STakashi Iwai
7099ad593f6STakashi Iwai /*
7109ad593f6STakashi Iwai * The work for pending PCM period updates.
7119ad593f6STakashi Iwai */
azx_irq_pending_work(struct work_struct * work)7129ad593f6STakashi Iwai static void azx_irq_pending_work(struct work_struct *work)
7139ad593f6STakashi Iwai {
7149a34af4aSTakashi Iwai struct hda_intel *hda = container_of(work, struct hda_intel, irq_pending_work);
7159a34af4aSTakashi Iwai struct azx *chip = &hda->chip;
7167833c3f8STakashi Iwai struct hdac_bus *bus = azx_bus(chip);
7177833c3f8STakashi Iwai struct hdac_stream *s;
7187833c3f8STakashi Iwai int pending, ok;
7199ad593f6STakashi Iwai
7209a34af4aSTakashi Iwai if (!hda->irq_pending_warned) {
7214e76a883STakashi Iwai dev_info(chip->card->dev,
7224e76a883STakashi Iwai "IRQ timing workaround is activated for card #%d. Suggest a bigger bdl_pos_adj.\n",
723a6a950a8STakashi Iwai chip->card->number);
7249a34af4aSTakashi Iwai hda->irq_pending_warned = 1;
725a6a950a8STakashi Iwai }
726a6a950a8STakashi Iwai
7279ad593f6STakashi Iwai for (;;) {
7289ad593f6STakashi Iwai pending = 0;
729a41d1224STakashi Iwai spin_lock_irq(&bus->reg_lock);
7307833c3f8STakashi Iwai list_for_each_entry(s, &bus->stream_list, list) {
7317833c3f8STakashi Iwai struct azx_dev *azx_dev = stream_to_azx_dev(s);
7329ad593f6STakashi Iwai if (!azx_dev->irq_pending ||
7337833c3f8STakashi Iwai !s->substream ||
7347833c3f8STakashi Iwai !s->running)
7359ad593f6STakashi Iwai continue;
736e5463720SJaroslav Kysela ok = azx_position_ok(chip, azx_dev);
737e5463720SJaroslav Kysela if (ok > 0) {
7389ad593f6STakashi Iwai azx_dev->irq_pending = 0;
739a41d1224STakashi Iwai spin_unlock(&bus->reg_lock);
7407833c3f8STakashi Iwai snd_pcm_period_elapsed(s->substream);
741a41d1224STakashi Iwai spin_lock(&bus->reg_lock);
742e5463720SJaroslav Kysela } else if (ok < 0) {
743e5463720SJaroslav Kysela pending = 0; /* too early */
7449ad593f6STakashi Iwai } else
7459ad593f6STakashi Iwai pending++;
7469ad593f6STakashi Iwai }
747a41d1224STakashi Iwai spin_unlock_irq(&bus->reg_lock);
7489ad593f6STakashi Iwai if (!pending)
7499ad593f6STakashi Iwai return;
75008af495fSTakashi Iwai msleep(1);
7519ad593f6STakashi Iwai }
7529ad593f6STakashi Iwai }
7539ad593f6STakashi Iwai
7549ad593f6STakashi Iwai /* clear irq_pending flags and assure no on-going workq */
azx_clear_irq_pending(struct azx * chip)7559ad593f6STakashi Iwai static void azx_clear_irq_pending(struct azx *chip)
7569ad593f6STakashi Iwai {
7577833c3f8STakashi Iwai struct hdac_bus *bus = azx_bus(chip);
7587833c3f8STakashi Iwai struct hdac_stream *s;
7599ad593f6STakashi Iwai
760a41d1224STakashi Iwai spin_lock_irq(&bus->reg_lock);
7617833c3f8STakashi Iwai list_for_each_entry(s, &bus->stream_list, list) {
7627833c3f8STakashi Iwai struct azx_dev *azx_dev = stream_to_azx_dev(s);
7637833c3f8STakashi Iwai azx_dev->irq_pending = 0;
7647833c3f8STakashi Iwai }
765a41d1224STakashi Iwai spin_unlock_irq(&bus->reg_lock);
7661da177e4SLinus Torvalds }
7671da177e4SLinus Torvalds
azx_acquire_irq(struct azx * chip,int do_disconnect)76868e7fffcSTakashi Iwai static int azx_acquire_irq(struct azx *chip, int do_disconnect)
76968e7fffcSTakashi Iwai {
770a41d1224STakashi Iwai struct hdac_bus *bus = azx_bus(chip);
771a41d1224STakashi Iwai
772437a5a46STakashi Iwai if (request_irq(chip->pci->irq, azx_interrupt,
773437a5a46STakashi Iwai chip->msi ? 0 : IRQF_SHARED,
774de65360bSHeiner Kallweit chip->card->irq_descr, chip)) {
7754e76a883STakashi Iwai dev_err(chip->card->dev,
7764e76a883STakashi Iwai "unable to grab IRQ %d, disabling device\n",
7774e76a883STakashi Iwai chip->pci->irq);
77868e7fffcSTakashi Iwai if (do_disconnect)
77968e7fffcSTakashi Iwai snd_card_disconnect(chip->card);
78068e7fffcSTakashi Iwai return -1;
78168e7fffcSTakashi Iwai }
782a41d1224STakashi Iwai bus->irq = chip->pci->irq;
783f36da940STakashi Iwai chip->card->sync_irq = bus->irq;
78469e13418STakashi Iwai pci_intx(chip->pci, !chip->msi);
78568e7fffcSTakashi Iwai return 0;
78668e7fffcSTakashi Iwai }
78768e7fffcSTakashi Iwai
788b6050ef6STakashi Iwai /* get the current DMA position with correction on VIA chips */
azx_via_get_position(struct azx * chip,struct azx_dev * azx_dev)789b6050ef6STakashi Iwai static unsigned int azx_via_get_position(struct azx *chip,
790b6050ef6STakashi Iwai struct azx_dev *azx_dev)
791b6050ef6STakashi Iwai {
792b6050ef6STakashi Iwai unsigned int link_pos, mini_pos, bound_pos;
793b6050ef6STakashi Iwai unsigned int mod_link_pos, mod_dma_pos, mod_mini_pos;
794b6050ef6STakashi Iwai unsigned int fifo_size;
795b6050ef6STakashi Iwai
7961604eeeeSTakashi Iwai link_pos = snd_hdac_stream_get_pos_lpib(azx_stream(azx_dev));
7977833c3f8STakashi Iwai if (azx_dev->core.substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
798b6050ef6STakashi Iwai /* Playback, no problem using link position */
799b6050ef6STakashi Iwai return link_pos;
800b6050ef6STakashi Iwai }
801b6050ef6STakashi Iwai
802b6050ef6STakashi Iwai /* Capture */
803b6050ef6STakashi Iwai /* For new chipset,
804b6050ef6STakashi Iwai * use mod to get the DMA position just like old chipset
805b6050ef6STakashi Iwai */
8067833c3f8STakashi Iwai mod_dma_pos = le32_to_cpu(*azx_dev->core.posbuf);
8077833c3f8STakashi Iwai mod_dma_pos %= azx_dev->core.period_bytes;
808b6050ef6STakashi Iwai
8097da20788STakashi Iwai fifo_size = azx_stream(azx_dev)->fifo_size - 1;
810b6050ef6STakashi Iwai
811b6050ef6STakashi Iwai if (azx_dev->insufficient) {
812b6050ef6STakashi Iwai /* Link position never gather than FIFO size */
813b6050ef6STakashi Iwai if (link_pos <= fifo_size)
814b6050ef6STakashi Iwai return 0;
815b6050ef6STakashi Iwai
816b6050ef6STakashi Iwai azx_dev->insufficient = 0;
817b6050ef6STakashi Iwai }
818b6050ef6STakashi Iwai
819b6050ef6STakashi Iwai if (link_pos <= fifo_size)
8207833c3f8STakashi Iwai mini_pos = azx_dev->core.bufsize + link_pos - fifo_size;
821b6050ef6STakashi Iwai else
822b6050ef6STakashi Iwai mini_pos = link_pos - fifo_size;
823b6050ef6STakashi Iwai
824b6050ef6STakashi Iwai /* Find nearest previous boudary */
8257833c3f8STakashi Iwai mod_mini_pos = mini_pos % azx_dev->core.period_bytes;
8267833c3f8STakashi Iwai mod_link_pos = link_pos % azx_dev->core.period_bytes;
827b6050ef6STakashi Iwai if (mod_link_pos >= fifo_size)
828b6050ef6STakashi Iwai bound_pos = link_pos - mod_link_pos;
829b6050ef6STakashi Iwai else if (mod_dma_pos >= mod_mini_pos)
830b6050ef6STakashi Iwai bound_pos = mini_pos - mod_mini_pos;
831b6050ef6STakashi Iwai else {
8327833c3f8STakashi Iwai bound_pos = mini_pos - mod_mini_pos + azx_dev->core.period_bytes;
8337833c3f8STakashi Iwai if (bound_pos >= azx_dev->core.bufsize)
834b6050ef6STakashi Iwai bound_pos = 0;
835b6050ef6STakashi Iwai }
836b6050ef6STakashi Iwai
837b6050ef6STakashi Iwai /* Calculate real DMA position we want */
838b6050ef6STakashi Iwai return bound_pos + mod_dma_pos;
839b6050ef6STakashi Iwai }
840b6050ef6STakashi Iwai
841c02f77d3STakashi Iwai #define AMD_FIFO_SIZE 32
842c02f77d3STakashi Iwai
843c02f77d3STakashi Iwai /* get the current DMA position with FIFO size correction */
azx_get_pos_fifo(struct azx * chip,struct azx_dev * azx_dev)844c02f77d3STakashi Iwai static unsigned int azx_get_pos_fifo(struct azx *chip, struct azx_dev *azx_dev)
845c02f77d3STakashi Iwai {
846c02f77d3STakashi Iwai struct snd_pcm_substream *substream = azx_dev->core.substream;
847c02f77d3STakashi Iwai struct snd_pcm_runtime *runtime = substream->runtime;
848c02f77d3STakashi Iwai unsigned int pos, delay;
849c02f77d3STakashi Iwai
850c02f77d3STakashi Iwai pos = snd_hdac_stream_get_pos_lpib(azx_stream(azx_dev));
851c02f77d3STakashi Iwai if (!runtime)
852c02f77d3STakashi Iwai return pos;
853c02f77d3STakashi Iwai
854c02f77d3STakashi Iwai runtime->delay = AMD_FIFO_SIZE;
855c02f77d3STakashi Iwai delay = frames_to_bytes(runtime, AMD_FIFO_SIZE);
856c02f77d3STakashi Iwai if (azx_dev->insufficient) {
857c02f77d3STakashi Iwai if (pos < delay) {
858c02f77d3STakashi Iwai delay = pos;
859c02f77d3STakashi Iwai runtime->delay = bytes_to_frames(runtime, pos);
860c02f77d3STakashi Iwai } else {
861c02f77d3STakashi Iwai azx_dev->insufficient = 0;
862c02f77d3STakashi Iwai }
863c02f77d3STakashi Iwai }
864c02f77d3STakashi Iwai
865c02f77d3STakashi Iwai /* correct the DMA position for capture stream */
866c02f77d3STakashi Iwai if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
867c02f77d3STakashi Iwai if (pos < delay)
868c02f77d3STakashi Iwai pos += azx_dev->core.bufsize;
869c02f77d3STakashi Iwai pos -= delay;
870c02f77d3STakashi Iwai }
871c02f77d3STakashi Iwai
872c02f77d3STakashi Iwai return pos;
873c02f77d3STakashi Iwai }
874c02f77d3STakashi Iwai
azx_get_delay_from_fifo(struct azx * chip,struct azx_dev * azx_dev,unsigned int pos)875c02f77d3STakashi Iwai static int azx_get_delay_from_fifo(struct azx *chip, struct azx_dev *azx_dev,
876c02f77d3STakashi Iwai unsigned int pos)
877c02f77d3STakashi Iwai {
878c02f77d3STakashi Iwai struct snd_pcm_substream *substream = azx_dev->core.substream;
879c02f77d3STakashi Iwai
880c02f77d3STakashi Iwai /* just read back the calculated value in the above */
881c02f77d3STakashi Iwai return substream->runtime->delay;
882c02f77d3STakashi Iwai }
883c02f77d3STakashi Iwai
__azx_shutdown_chip(struct azx * chip,bool skip_link_reset)8846f445784STakashi Iwai static void __azx_shutdown_chip(struct azx *chip, bool skip_link_reset)
885472e18f6SImre Deak {
886472e18f6SImre Deak azx_stop_chip(chip);
8876f445784STakashi Iwai if (!skip_link_reset)
888472e18f6SImre Deak azx_enter_link_reset(chip);
889472e18f6SImre Deak azx_clear_irq_pending(chip);
890472e18f6SImre Deak display_power(chip, false);
891472e18f6SImre Deak }
892472e18f6SImre Deak
89383012a7cSTakashi Iwai #ifdef CONFIG_PM
89465fcd41dSTakashi Iwai static DEFINE_MUTEX(card_list_lock);
89565fcd41dSTakashi Iwai static LIST_HEAD(card_list);
89665fcd41dSTakashi Iwai
azx_shutdown_chip(struct azx * chip)8976f445784STakashi Iwai static void azx_shutdown_chip(struct azx *chip)
8986f445784STakashi Iwai {
8996f445784STakashi Iwai __azx_shutdown_chip(chip, false);
9006f445784STakashi Iwai }
9016f445784STakashi Iwai
azx_add_card_list(struct azx * chip)90265fcd41dSTakashi Iwai static void azx_add_card_list(struct azx *chip)
90365fcd41dSTakashi Iwai {
9049a34af4aSTakashi Iwai struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
90565fcd41dSTakashi Iwai mutex_lock(&card_list_lock);
9069a34af4aSTakashi Iwai list_add(&hda->list, &card_list);
90765fcd41dSTakashi Iwai mutex_unlock(&card_list_lock);
90865fcd41dSTakashi Iwai }
90965fcd41dSTakashi Iwai
azx_del_card_list(struct azx * chip)91065fcd41dSTakashi Iwai static void azx_del_card_list(struct azx *chip)
91165fcd41dSTakashi Iwai {
9129a34af4aSTakashi Iwai struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
91365fcd41dSTakashi Iwai mutex_lock(&card_list_lock);
9149a34af4aSTakashi Iwai list_del_init(&hda->list);
91565fcd41dSTakashi Iwai mutex_unlock(&card_list_lock);
91665fcd41dSTakashi Iwai }
91765fcd41dSTakashi Iwai
91865fcd41dSTakashi Iwai /* trigger power-save check at writing parameter */
param_set_xint(const char * val,const struct kernel_param * kp)91965fcd41dSTakashi Iwai static int param_set_xint(const char *val, const struct kernel_param *kp)
92065fcd41dSTakashi Iwai {
9219a34af4aSTakashi Iwai struct hda_intel *hda;
92265fcd41dSTakashi Iwai struct azx *chip;
92365fcd41dSTakashi Iwai int prev = power_save;
92465fcd41dSTakashi Iwai int ret = param_set_int(val, kp);
92565fcd41dSTakashi Iwai
92665fcd41dSTakashi Iwai if (ret || prev == power_save)
92765fcd41dSTakashi Iwai return ret;
92865fcd41dSTakashi Iwai
92965fcd41dSTakashi Iwai mutex_lock(&card_list_lock);
9309a34af4aSTakashi Iwai list_for_each_entry(hda, &card_list, list) {
9319a34af4aSTakashi Iwai chip = &hda->chip;
932a41d1224STakashi Iwai if (!hda->probe_continued || chip->disabled)
93365fcd41dSTakashi Iwai continue;
934a41d1224STakashi Iwai snd_hda_set_power_save(&chip->bus, power_save * 1000);
93565fcd41dSTakashi Iwai }
93665fcd41dSTakashi Iwai mutex_unlock(&card_list_lock);
93765fcd41dSTakashi Iwai return 0;
93865fcd41dSTakashi Iwai }
9395c0b9becSTakashi Iwai
9405c0b9becSTakashi Iwai /*
9415c0b9becSTakashi Iwai * power management
9425c0b9becSTakashi Iwai */
azx_is_pm_ready(struct snd_card * card)9433baffc4aSTakashi Iwai static bool azx_is_pm_ready(struct snd_card *card)
9441da177e4SLinus Torvalds {
9452d9772efSTakashi Iwai struct azx *chip;
9462d9772efSTakashi Iwai struct hda_intel *hda;
9471da177e4SLinus Torvalds
9482d9772efSTakashi Iwai if (!card)
9493baffc4aSTakashi Iwai return false;
9502d9772efSTakashi Iwai chip = card->private_data;
9512d9772efSTakashi Iwai hda = container_of(chip, struct hda_intel, chip);
952342e8449SU. Artie Eoff if (chip->disabled || hda->init_failed || !chip->running)
9533baffc4aSTakashi Iwai return false;
9543baffc4aSTakashi Iwai return true;
9553baffc4aSTakashi Iwai }
956c5c21523STakashi Iwai
__azx_runtime_resume(struct azx * chip)957f5dac54dSKai-Heng Feng static void __azx_runtime_resume(struct azx *chip)
9581da177e4SLinus Torvalds {
9593baffc4aSTakashi Iwai struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
9603baffc4aSTakashi Iwai struct hdac_bus *bus = azx_bus(chip);
9613baffc4aSTakashi Iwai struct hda_codec *codec;
9623baffc4aSTakashi Iwai int status;
963c5c21523STakashi Iwai
964029d92c2STakashi Iwai display_power(chip, true);
965a52ff34eSTakashi Iwai if (hda->need_i915_power)
966a52ff34eSTakashi Iwai snd_hdac_i915_set_bclk(bus);
967a52ff34eSTakashi Iwai
9683baffc4aSTakashi Iwai /* Read STATESTS before controller reset */
9693baffc4aSTakashi Iwai status = azx_readw(chip, STATESTS);
970d804ad92SMaxim Levitsky
9713baffc4aSTakashi Iwai azx_init_pci(chip);
9720a673521SLu, Han hda_intel_init_chip(chip, true);
973d804ad92SMaxim Levitsky
974f5dac54dSKai-Heng Feng /* Avoid codec resume if runtime resume is for system suspend */
975f5dac54dSKai-Heng Feng if (!chip->pm_prepared) {
976a6e7d0a4SKai Vehmanen list_for_each_codec(codec, &chip->bus) {
977a6e7d0a4SKai Vehmanen if (codec->relaxed_resume)
978a6e7d0a4SKai Vehmanen continue;
979a6e7d0a4SKai Vehmanen
980a6e7d0a4SKai Vehmanen if (codec->forced_resume || (status & (1 << codec->addr)))
981a6e7d0a4SKai Vehmanen pm_request_resume(hda_codec_dev(codec));
982a6e7d0a4SKai Vehmanen }
9833baffc4aSTakashi Iwai }
9843baffc4aSTakashi Iwai
985a52ff34eSTakashi Iwai /* power down again for link-controlled chips */
986e454ff8eSTakashi Iwai if (!hda->need_i915_power)
987029d92c2STakashi Iwai display_power(chip, false);
9883baffc4aSTakashi Iwai }
989a52ff34eSTakashi Iwai
9903baffc4aSTakashi Iwai #ifdef CONFIG_PM_SLEEP
azx_prepare(struct device * dev)991f5dac54dSKai-Heng Feng static int azx_prepare(struct device *dev)
992f5dac54dSKai-Heng Feng {
993f5dac54dSKai-Heng Feng struct snd_card *card = dev_get_drvdata(dev);
994f5dac54dSKai-Heng Feng struct azx *chip;
995f5dac54dSKai-Heng Feng
99666affb7bSTakashi Iwai if (!azx_is_pm_ready(card))
99766affb7bSTakashi Iwai return 0;
99866affb7bSTakashi Iwai
999f5dac54dSKai-Heng Feng chip = card->private_data;
1000f5dac54dSKai-Heng Feng chip->pm_prepared = 1;
1001c8f79808STakashi Iwai snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
1002f5dac54dSKai-Heng Feng
100313661fc4STakashi Iwai flush_work(&azx_bus(chip)->unsol_work);
100413661fc4STakashi Iwai
1005f5dac54dSKai-Heng Feng /* HDA controller always requires different WAKEEN for runtime suspend
1006f5dac54dSKai-Heng Feng * and system suspend, so don't use direct-complete here.
1007f5dac54dSKai-Heng Feng */
1008f5dac54dSKai-Heng Feng return 0;
1009f5dac54dSKai-Heng Feng }
1010f5dac54dSKai-Heng Feng
azx_complete(struct device * dev)1011f5dac54dSKai-Heng Feng static void azx_complete(struct device *dev)
1012f5dac54dSKai-Heng Feng {
1013f5dac54dSKai-Heng Feng struct snd_card *card = dev_get_drvdata(dev);
1014f5dac54dSKai-Heng Feng struct azx *chip;
1015f5dac54dSKai-Heng Feng
101666affb7bSTakashi Iwai if (!azx_is_pm_ready(card))
101766affb7bSTakashi Iwai return;
101866affb7bSTakashi Iwai
1019f5dac54dSKai-Heng Feng chip = card->private_data;
1020c8f79808STakashi Iwai snd_power_change_state(card, SNDRV_CTL_POWER_D0);
1021f5dac54dSKai-Heng Feng chip->pm_prepared = 0;
1022f5dac54dSKai-Heng Feng }
1023f5dac54dSKai-Heng Feng
azx_suspend(struct device * dev)10243baffc4aSTakashi Iwai static int azx_suspend(struct device *dev)
10253baffc4aSTakashi Iwai {
10263baffc4aSTakashi Iwai struct snd_card *card = dev_get_drvdata(dev);
10273baffc4aSTakashi Iwai struct azx *chip;
10283baffc4aSTakashi Iwai struct hdac_bus *bus;
10293baffc4aSTakashi Iwai
10303baffc4aSTakashi Iwai if (!azx_is_pm_ready(card))
10313baffc4aSTakashi Iwai return 0;
10323baffc4aSTakashi Iwai
10333baffc4aSTakashi Iwai chip = card->private_data;
10343baffc4aSTakashi Iwai bus = azx_bus(chip);
1035472e18f6SImre Deak azx_shutdown_chip(chip);
10363baffc4aSTakashi Iwai if (bus->irq >= 0) {
10373baffc4aSTakashi Iwai free_irq(bus->irq, chip);
10383baffc4aSTakashi Iwai bus->irq = -1;
1039f36da940STakashi Iwai chip->card->sync_irq = -1;
10403baffc4aSTakashi Iwai }
10413baffc4aSTakashi Iwai
10423baffc4aSTakashi Iwai if (chip->msi)
10433baffc4aSTakashi Iwai pci_disable_msi(chip->pci);
10443baffc4aSTakashi Iwai
10453baffc4aSTakashi Iwai trace_azx_suspend(chip);
10463baffc4aSTakashi Iwai return 0;
10473baffc4aSTakashi Iwai }
10483baffc4aSTakashi Iwai
azx_resume(struct device * dev)10493baffc4aSTakashi Iwai static int azx_resume(struct device *dev)
10503baffc4aSTakashi Iwai {
10513baffc4aSTakashi Iwai struct snd_card *card = dev_get_drvdata(dev);
10523baffc4aSTakashi Iwai struct azx *chip;
10533baffc4aSTakashi Iwai
10543baffc4aSTakashi Iwai if (!azx_is_pm_ready(card))
10553baffc4aSTakashi Iwai return 0;
10563baffc4aSTakashi Iwai
10573baffc4aSTakashi Iwai chip = card->private_data;
10583baffc4aSTakashi Iwai if (chip->msi)
10593baffc4aSTakashi Iwai if (pci_enable_msi(chip->pci) < 0)
10603baffc4aSTakashi Iwai chip->msi = 0;
10613baffc4aSTakashi Iwai if (azx_acquire_irq(chip, 1) < 0)
10623baffc4aSTakashi Iwai return -EIO;
1063c4c8dd6eSTakashi Iwai
1064f5dac54dSKai-Heng Feng __azx_runtime_resume(chip);
1065785d8c4bSLibin Yang
1066785d8c4bSLibin Yang trace_azx_resume(chip);
10671da177e4SLinus Torvalds return 0;
10681da177e4SLinus Torvalds }
1069b8dfc462SMengdong Lin
10703e6db33aSXiong Zhang /* put codec down to D3 at hibernation for Intel SKL+;
10713e6db33aSXiong Zhang * otherwise BIOS may still access the codec and screw up the driver
10723e6db33aSXiong Zhang */
azx_freeze_noirq(struct device * dev)10733e6db33aSXiong Zhang static int azx_freeze_noirq(struct device *dev)
10743e6db33aSXiong Zhang {
1075a4b4793fSTakashi Iwai struct snd_card *card = dev_get_drvdata(dev);
1076a4b4793fSTakashi Iwai struct azx *chip = card->private_data;
10773e6db33aSXiong Zhang struct pci_dev *pci = to_pci_dev(dev);
10783e6db33aSXiong Zhang
107910db5bccSTakashi Iwai if (!azx_is_pm_ready(card))
108010db5bccSTakashi Iwai return 0;
1081a4b4793fSTakashi Iwai if (chip->driver_type == AZX_DRIVER_SKL)
10823e6db33aSXiong Zhang pci_set_power_state(pci, PCI_D3hot);
10833e6db33aSXiong Zhang
10843e6db33aSXiong Zhang return 0;
10853e6db33aSXiong Zhang }
10863e6db33aSXiong Zhang
azx_thaw_noirq(struct device * dev)10873e6db33aSXiong Zhang static int azx_thaw_noirq(struct device *dev)
10883e6db33aSXiong Zhang {
1089a4b4793fSTakashi Iwai struct snd_card *card = dev_get_drvdata(dev);
1090a4b4793fSTakashi Iwai struct azx *chip = card->private_data;
10913e6db33aSXiong Zhang struct pci_dev *pci = to_pci_dev(dev);
10923e6db33aSXiong Zhang
109310db5bccSTakashi Iwai if (!azx_is_pm_ready(card))
109410db5bccSTakashi Iwai return 0;
1095a4b4793fSTakashi Iwai if (chip->driver_type == AZX_DRIVER_SKL)
10963e6db33aSXiong Zhang pci_set_power_state(pci, PCI_D0);
10973e6db33aSXiong Zhang
10983e6db33aSXiong Zhang return 0;
10993e6db33aSXiong Zhang }
11003e6db33aSXiong Zhang #endif /* CONFIG_PM_SLEEP */
11013e6db33aSXiong Zhang
azx_runtime_suspend(struct device * dev)1102b8dfc462SMengdong Lin static int azx_runtime_suspend(struct device *dev)
1103b8dfc462SMengdong Lin {
1104b8dfc462SMengdong Lin struct snd_card *card = dev_get_drvdata(dev);
11052d9772efSTakashi Iwai struct azx *chip;
1106b8dfc462SMengdong Lin
11073baffc4aSTakashi Iwai if (!azx_is_pm_ready(card))
11082d9772efSTakashi Iwai return 0;
11092d9772efSTakashi Iwai chip = card->private_data;
1110246efa4aSDave Airlie
11117d4f606cSWang Xingchao /* enable controller wake up event */
1112f5dac54dSKai-Heng Feng azx_writew(chip, WAKEEN, azx_readw(chip, WAKEEN) | STATESTS_INT_MASK);
11137d4f606cSWang Xingchao
1114472e18f6SImre Deak azx_shutdown_chip(chip);
1115785d8c4bSLibin Yang trace_azx_runtime_suspend(chip);
1116b8dfc462SMengdong Lin return 0;
1117b8dfc462SMengdong Lin }
1118b8dfc462SMengdong Lin
azx_runtime_resume(struct device * dev)1119b8dfc462SMengdong Lin static int azx_runtime_resume(struct device *dev)
1120b8dfc462SMengdong Lin {
1121b8dfc462SMengdong Lin struct snd_card *card = dev_get_drvdata(dev);
11222d9772efSTakashi Iwai struct azx *chip;
1123b8dfc462SMengdong Lin
11243baffc4aSTakashi Iwai if (!azx_is_pm_ready(card))
11252d9772efSTakashi Iwai return 0;
11262d9772efSTakashi Iwai chip = card->private_data;
1127f5dac54dSKai-Heng Feng __azx_runtime_resume(chip);
11287d4f606cSWang Xingchao
11297d4f606cSWang Xingchao /* disable controller Wake Up event*/
1130f5dac54dSKai-Heng Feng azx_writew(chip, WAKEEN, azx_readw(chip, WAKEEN) & ~STATESTS_INT_MASK);
11317d4f606cSWang Xingchao
1132785d8c4bSLibin Yang trace_azx_runtime_resume(chip);
1133b8dfc462SMengdong Lin return 0;
1134b8dfc462SMengdong Lin }
11356eb827d2STakashi Iwai
azx_runtime_idle(struct device * dev)11366eb827d2STakashi Iwai static int azx_runtime_idle(struct device *dev)
11376eb827d2STakashi Iwai {
11386eb827d2STakashi Iwai struct snd_card *card = dev_get_drvdata(dev);
11392d9772efSTakashi Iwai struct azx *chip;
11402d9772efSTakashi Iwai struct hda_intel *hda;
11416eb827d2STakashi Iwai
11422d9772efSTakashi Iwai if (!card)
11432d9772efSTakashi Iwai return 0;
11442d9772efSTakashi Iwai
11452d9772efSTakashi Iwai chip = card->private_data;
11462d9772efSTakashi Iwai hda = container_of(chip, struct hda_intel, chip);
11471618e84aSTakashi Iwai if (chip->disabled || hda->init_failed)
1148246efa4aSDave Airlie return 0;
1149246efa4aSDave Airlie
115055ed9cd1STakashi Iwai if (!power_save_controller || !azx_has_pm_runtime(chip) ||
1151342e8449SU. Artie Eoff azx_bus(chip)->codec_powered || !chip->running)
11526eb827d2STakashi Iwai return -EBUSY;
11536eb827d2STakashi Iwai
115437a3a98eSTakashi Iwai /* ELD notification gets broken when HD-audio bus is off */
1155dd23e1d5STakashi Iwai if (needs_eld_notify_link(chip))
115637a3a98eSTakashi Iwai return -EBUSY;
115737a3a98eSTakashi Iwai
11586eb827d2STakashi Iwai return 0;
11596eb827d2STakashi Iwai }
11606eb827d2STakashi Iwai
1161b8dfc462SMengdong Lin static const struct dev_pm_ops azx_pm = {
1162b8dfc462SMengdong Lin SET_SYSTEM_SLEEP_PM_OPS(azx_suspend, azx_resume)
11633e6db33aSXiong Zhang #ifdef CONFIG_PM_SLEEP
1164f5dac54dSKai-Heng Feng .prepare = azx_prepare,
1165f5dac54dSKai-Heng Feng .complete = azx_complete,
11663e6db33aSXiong Zhang .freeze_noirq = azx_freeze_noirq,
11673e6db33aSXiong Zhang .thaw_noirq = azx_thaw_noirq,
11683e6db33aSXiong Zhang #endif
11696eb827d2STakashi Iwai SET_RUNTIME_PM_OPS(azx_runtime_suspend, azx_runtime_resume, azx_runtime_idle)
1170b8dfc462SMengdong Lin };
1171b8dfc462SMengdong Lin
117268cb2b55STakashi Iwai #define AZX_PM_OPS &azx_pm
117368cb2b55STakashi Iwai #else
11743baffc4aSTakashi Iwai #define azx_add_card_list(chip) /* NOP */
11753baffc4aSTakashi Iwai #define azx_del_card_list(chip) /* NOP */
117668cb2b55STakashi Iwai #define AZX_PM_OPS NULL
1177b8dfc462SMengdong Lin #endif /* CONFIG_PM */
11781da177e4SLinus Torvalds
11791da177e4SLinus Torvalds
118048c8b0ebSTakashi Iwai static int azx_probe_continue(struct azx *chip);
1181a82d51edSTakashi Iwai
11828393ec4aSSteven Newbury #ifdef SUPPORT_VGA_SWITCHEROO
1183e23e7a14SBill Pemberton static struct pci_dev *get_bound_vga(struct pci_dev *pci);
1184a82d51edSTakashi Iwai
azx_vs_set_state(struct pci_dev * pci,enum vga_switcheroo_state state)1185a82d51edSTakashi Iwai static void azx_vs_set_state(struct pci_dev *pci,
1186a82d51edSTakashi Iwai enum vga_switcheroo_state state)
1187a82d51edSTakashi Iwai {
1188a82d51edSTakashi Iwai struct snd_card *card = pci_get_drvdata(pci);
1189a82d51edSTakashi Iwai struct azx *chip = card->private_data;
11909a34af4aSTakashi Iwai struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
119107f4f97dSLukas Wunner struct hda_codec *codec;
1192a82d51edSTakashi Iwai bool disabled;
1193a82d51edSTakashi Iwai
11949a34af4aSTakashi Iwai wait_for_completion(&hda->probe_wait);
11959a34af4aSTakashi Iwai if (hda->init_failed)
1196a82d51edSTakashi Iwai return;
1197a82d51edSTakashi Iwai
1198a82d51edSTakashi Iwai disabled = (state == VGA_SWITCHEROO_OFF);
1199a82d51edSTakashi Iwai if (chip->disabled == disabled)
1200a82d51edSTakashi Iwai return;
1201a82d51edSTakashi Iwai
1202a41d1224STakashi Iwai if (!hda->probe_continued) {
1203a82d51edSTakashi Iwai chip->disabled = disabled;
1204a82d51edSTakashi Iwai if (!disabled) {
12054e76a883STakashi Iwai dev_info(chip->card->dev,
12064e76a883STakashi Iwai "Start delayed initialization\n");
12072393e755STakashi Iwai if (azx_probe_continue(chip) < 0)
12084e76a883STakashi Iwai dev_err(chip->card->dev, "initialization error\n");
1209a82d51edSTakashi Iwai }
1210a82d51edSTakashi Iwai } else {
12112b760d88SLukas Wunner dev_info(chip->card->dev, "%s via vga_switcheroo\n",
1212445a51b3SDaniel J Blueman disabled ? "Disabling" : "Enabling");
1213a82d51edSTakashi Iwai if (disabled) {
121407f4f97dSLukas Wunner list_for_each_codec(codec, &chip->bus) {
121507f4f97dSLukas Wunner pm_runtime_suspend(hda_codec_dev(codec));
121607f4f97dSLukas Wunner pm_runtime_disable(hda_codec_dev(codec));
121707f4f97dSLukas Wunner }
121807f4f97dSLukas Wunner pm_runtime_suspend(card->dev);
121907f4f97dSLukas Wunner pm_runtime_disable(card->dev);
12202b760d88SLukas Wunner /* when we get suspended by vga_switcheroo we end up in D3cold,
1221246efa4aSDave Airlie * however we have no ACPI handle, so pci/acpi can't put us there,
1222246efa4aSDave Airlie * put ourselves there */
1223246efa4aSDave Airlie pci->current_state = PCI_D3cold;
1224a82d51edSTakashi Iwai chip->disabled = true;
1225a41d1224STakashi Iwai if (snd_hda_lock_devices(&chip->bus))
12264e76a883STakashi Iwai dev_warn(chip->card->dev,
12274e76a883STakashi Iwai "Cannot lock devices!\n");
1228a82d51edSTakashi Iwai } else {
1229a41d1224STakashi Iwai snd_hda_unlock_devices(&chip->bus);
1230a82d51edSTakashi Iwai chip->disabled = false;
123107f4f97dSLukas Wunner pm_runtime_enable(card->dev);
123207f4f97dSLukas Wunner list_for_each_codec(codec, &chip->bus) {
123307f4f97dSLukas Wunner pm_runtime_enable(hda_codec_dev(codec));
123407f4f97dSLukas Wunner pm_runtime_resume(hda_codec_dev(codec));
123507f4f97dSLukas Wunner }
1236a82d51edSTakashi Iwai }
1237a82d51edSTakashi Iwai }
1238a82d51edSTakashi Iwai }
1239a82d51edSTakashi Iwai
azx_vs_can_switch(struct pci_dev * pci)1240a82d51edSTakashi Iwai static bool azx_vs_can_switch(struct pci_dev *pci)
1241a82d51edSTakashi Iwai {
1242a82d51edSTakashi Iwai struct snd_card *card = pci_get_drvdata(pci);
1243a82d51edSTakashi Iwai struct azx *chip = card->private_data;
12449a34af4aSTakashi Iwai struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
1245a82d51edSTakashi Iwai
12469a34af4aSTakashi Iwai wait_for_completion(&hda->probe_wait);
12479a34af4aSTakashi Iwai if (hda->init_failed)
1248a82d51edSTakashi Iwai return false;
1249a41d1224STakashi Iwai if (chip->disabled || !hda->probe_continued)
1250a82d51edSTakashi Iwai return true;
1251a41d1224STakashi Iwai if (snd_hda_lock_devices(&chip->bus))
1252a82d51edSTakashi Iwai return false;
1253a41d1224STakashi Iwai snd_hda_unlock_devices(&chip->bus);
1254a82d51edSTakashi Iwai return true;
1255a82d51edSTakashi Iwai }
1256a82d51edSTakashi Iwai
125737a3a98eSTakashi Iwai /*
125837a3a98eSTakashi Iwai * The discrete GPU cannot power down unless the HDA controller runtime
125937a3a98eSTakashi Iwai * suspends, so activate runtime PM on codecs even if power_save == 0.
126037a3a98eSTakashi Iwai */
setup_vga_switcheroo_runtime_pm(struct azx * chip)126137a3a98eSTakashi Iwai static void setup_vga_switcheroo_runtime_pm(struct azx *chip)
126237a3a98eSTakashi Iwai {
126337a3a98eSTakashi Iwai struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
126437a3a98eSTakashi Iwai struct hda_codec *codec;
126537a3a98eSTakashi Iwai
1266dd23e1d5STakashi Iwai if (hda->use_vga_switcheroo && !needs_eld_notify_link(chip)) {
126737a3a98eSTakashi Iwai list_for_each_codec(codec, &chip->bus)
126837a3a98eSTakashi Iwai codec->auto_runtime_pm = 1;
126937a3a98eSTakashi Iwai /* reset the power save setup */
127037a3a98eSTakashi Iwai if (chip->running)
127137a3a98eSTakashi Iwai set_default_power_save(chip);
127237a3a98eSTakashi Iwai }
127337a3a98eSTakashi Iwai }
127437a3a98eSTakashi Iwai
azx_vs_gpu_bound(struct pci_dev * pci,enum vga_switcheroo_client_id client_id)127537a3a98eSTakashi Iwai static void azx_vs_gpu_bound(struct pci_dev *pci,
127637a3a98eSTakashi Iwai enum vga_switcheroo_client_id client_id)
127737a3a98eSTakashi Iwai {
127837a3a98eSTakashi Iwai struct snd_card *card = pci_get_drvdata(pci);
127937a3a98eSTakashi Iwai struct azx *chip = card->private_data;
128037a3a98eSTakashi Iwai
128137a3a98eSTakashi Iwai if (client_id == VGA_SWITCHEROO_DIS)
1282dd23e1d5STakashi Iwai chip->bus.keep_power = 0;
128337a3a98eSTakashi Iwai setup_vga_switcheroo_runtime_pm(chip);
128437a3a98eSTakashi Iwai }
128537a3a98eSTakashi Iwai
init_vga_switcheroo(struct azx * chip)1286e23e7a14SBill Pemberton static void init_vga_switcheroo(struct azx *chip)
1287a82d51edSTakashi Iwai {
12889a34af4aSTakashi Iwai struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
1289a82d51edSTakashi Iwai struct pci_dev *p = get_bound_vga(chip->pci);
1290bacd8614SKai-Heng Feng struct pci_dev *parent;
1291a82d51edSTakashi Iwai if (p) {
12924e76a883STakashi Iwai dev_info(chip->card->dev,
12932b760d88SLukas Wunner "Handle vga_switcheroo audio client\n");
12949a34af4aSTakashi Iwai hda->use_vga_switcheroo = 1;
1295bacd8614SKai-Heng Feng
1296bacd8614SKai-Heng Feng /* cleared in either gpu_bound op or codec probe, or when its
1297bacd8614SKai-Heng Feng * upstream port has _PR3 (i.e. dGPU).
1298bacd8614SKai-Heng Feng */
1299bacd8614SKai-Heng Feng parent = pci_upstream_bridge(p);
1300bacd8614SKai-Heng Feng chip->bus.keep_power = parent ? !pci_pr3_present(parent) : 1;
130107f4f97dSLukas Wunner chip->driver_caps |= AZX_DCAPS_PM_RUNTIME;
1302a82d51edSTakashi Iwai pci_dev_put(p);
1303a82d51edSTakashi Iwai }
1304a82d51edSTakashi Iwai }
1305a82d51edSTakashi Iwai
1306a82d51edSTakashi Iwai static const struct vga_switcheroo_client_ops azx_vs_ops = {
1307a82d51edSTakashi Iwai .set_gpu_state = azx_vs_set_state,
1308a82d51edSTakashi Iwai .can_switch = azx_vs_can_switch,
130937a3a98eSTakashi Iwai .gpu_bound = azx_vs_gpu_bound,
1310a82d51edSTakashi Iwai };
1311a82d51edSTakashi Iwai
register_vga_switcheroo(struct azx * chip)1312e23e7a14SBill Pemberton static int register_vga_switcheroo(struct azx *chip)
1313a82d51edSTakashi Iwai {
13149a34af4aSTakashi Iwai struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
13154aaf448fSJim Qu struct pci_dev *p;
1316128960a9STakashi Iwai int err;
1317128960a9STakashi Iwai
13189a34af4aSTakashi Iwai if (!hda->use_vga_switcheroo)
1319a82d51edSTakashi Iwai return 0;
13204aaf448fSJim Qu
13214aaf448fSJim Qu p = get_bound_vga(chip->pci);
13224aaf448fSJim Qu err = vga_switcheroo_register_audio_client(chip->pci, &azx_vs_ops, p);
13234aaf448fSJim Qu pci_dev_put(p);
13244aaf448fSJim Qu
1325128960a9STakashi Iwai if (err < 0)
1326128960a9STakashi Iwai return err;
13279a34af4aSTakashi Iwai hda->vga_switcheroo_registered = 1;
1328246efa4aSDave Airlie
1329128960a9STakashi Iwai return 0;
1330a82d51edSTakashi Iwai }
1331a82d51edSTakashi Iwai #else
1332a82d51edSTakashi Iwai #define init_vga_switcheroo(chip) /* NOP */
1333a82d51edSTakashi Iwai #define register_vga_switcheroo(chip) 0
13348393ec4aSSteven Newbury #define check_hdmi_disabled(pci) false
133537a3a98eSTakashi Iwai #define setup_vga_switcheroo_runtime_pm(chip) /* NOP */
1336a82d51edSTakashi Iwai #endif /* SUPPORT_VGA_SWITCHER */
1337a82d51edSTakashi Iwai
13380cbf0098STakashi Iwai /*
13391da177e4SLinus Torvalds * destructor
13401da177e4SLinus Torvalds */
azx_free(struct azx * chip)13412393e755STakashi Iwai static void azx_free(struct azx *chip)
13421da177e4SLinus Torvalds {
1343c67e2228SWang Xingchao struct pci_dev *pci = chip->pci;
1344a07187c9SMengdong Lin struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
1345a41d1224STakashi Iwai struct hdac_bus *bus = azx_bus(chip);
13464ce107b9STakashi Iwai
13472393e755STakashi Iwai if (hda->freed)
13482393e755STakashi Iwai return;
13492393e755STakashi Iwai
13504f66a9efSTakashi Iwai if (azx_has_pm_runtime(chip) && chip->running) {
1351c67e2228SWang Xingchao pm_runtime_get_noresume(&pci->dev);
13524f66a9efSTakashi Iwai pm_runtime_forbid(&pci->dev);
13534f66a9efSTakashi Iwai pm_runtime_dont_use_autosuspend(&pci->dev);
13544f66a9efSTakashi Iwai }
13554f66a9efSTakashi Iwai
135637a3a98eSTakashi Iwai chip->running = 0;
1357c67e2228SWang Xingchao
135865fcd41dSTakashi Iwai azx_del_card_list(chip);
135965fcd41dSTakashi Iwai
13609a34af4aSTakashi Iwai hda->init_failed = 1; /* to be sure */
13619a34af4aSTakashi Iwai complete_all(&hda->probe_wait);
1362f4c482a4STakashi Iwai
13639a34af4aSTakashi Iwai if (use_vga_switcheroo(hda)) {
1364a41d1224STakashi Iwai if (chip->disabled && hda->probe_continued)
1365a41d1224STakashi Iwai snd_hda_unlock_devices(&chip->bus);
136607f4f97dSLukas Wunner if (hda->vga_switcheroo_registered)
1367a82d51edSTakashi Iwai vga_switcheroo_unregister_client(chip->pci);
1368a82d51edSTakashi Iwai }
1369a82d51edSTakashi Iwai
1370a41d1224STakashi Iwai if (bus->chip_init) {
13719ad593f6STakashi Iwai azx_clear_irq_pending(chip);
13727833c3f8STakashi Iwai azx_stop_all_streams(chip);
13731a7f60b9STakashi Iwai azx_stop_chip(chip);
13741da177e4SLinus Torvalds }
13751da177e4SLinus Torvalds
1376a41d1224STakashi Iwai if (bus->irq >= 0)
1377a41d1224STakashi Iwai free_irq(bus->irq, (void*)chip);
13781da177e4SLinus Torvalds
137967908994SDylan Reid azx_free_stream_pages(chip);
1380a41d1224STakashi Iwai azx_free_streams(chip);
1381a41d1224STakashi Iwai snd_hdac_bus_exit(bus);
1382a41d1224STakashi Iwai
13834918cdabSTakashi Iwai #ifdef CONFIG_SND_HDA_PATCH_LOADER
13844918cdabSTakashi Iwai release_firmware(chip->fw);
13854918cdabSTakashi Iwai #endif
1386029d92c2STakashi Iwai display_power(chip, false);
1387e454ff8eSTakashi Iwai
1388fc18282cSTakashi Iwai if (chip->driver_caps & AZX_DCAPS_I915_COMPONENT)
1389fcc88d91STakashi Iwai snd_hdac_i915_exit(bus);
13901da177e4SLinus Torvalds
13912393e755STakashi Iwai hda->freed = 1;
13921da177e4SLinus Torvalds }
13931da177e4SLinus Torvalds
azx_dev_disconnect(struct snd_device * device)1394a41d1224STakashi Iwai static int azx_dev_disconnect(struct snd_device *device)
1395a41d1224STakashi Iwai {
1396a41d1224STakashi Iwai struct azx *chip = device->device_data;
1397ca58f551STakashi Iwai struct hdac_bus *bus = azx_bus(chip);
1398a41d1224STakashi Iwai
1399a41d1224STakashi Iwai chip->bus.shutdown = 1;
1400ca58f551STakashi Iwai cancel_work_sync(&bus->unsol_work);
1401ca58f551STakashi Iwai
1402a41d1224STakashi Iwai return 0;
1403a41d1224STakashi Iwai }
1404a41d1224STakashi Iwai
azx_dev_free(struct snd_device * device)1405a98f90fdSTakashi Iwai static int azx_dev_free(struct snd_device *device)
14061da177e4SLinus Torvalds {
14072393e755STakashi Iwai azx_free(device->device_data);
14082393e755STakashi Iwai return 0;
14091da177e4SLinus Torvalds }
14101da177e4SLinus Torvalds
14118393ec4aSSteven Newbury #ifdef SUPPORT_VGA_SWITCHEROO
1412586bc4aaSAlex Deucher #ifdef CONFIG_ACPI
1413586bc4aaSAlex Deucher /* ATPX is in the integrated GPU's namespace */
atpx_present(void)1414586bc4aaSAlex Deucher static bool atpx_present(void)
1415586bc4aaSAlex Deucher {
1416586bc4aaSAlex Deucher struct pci_dev *pdev = NULL;
1417586bc4aaSAlex Deucher acpi_handle dhandle, atpx_handle;
1418586bc4aaSAlex Deucher acpi_status status;
1419586bc4aaSAlex Deucher
14208cc0991cSAlex Deucher while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) {
14218cc0991cSAlex Deucher dhandle = ACPI_HANDLE(&pdev->dev);
14228cc0991cSAlex Deucher if (dhandle) {
14238cc0991cSAlex Deucher status = acpi_get_handle(dhandle, "ATPX", &atpx_handle);
142410e92724SBjorn Helgaas if (ACPI_SUCCESS(status)) {
14258cc0991cSAlex Deucher pci_dev_put(pdev);
14268cc0991cSAlex Deucher return true;
14278cc0991cSAlex Deucher }
14288cc0991cSAlex Deucher }
14298cc0991cSAlex Deucher }
14308cc0991cSAlex Deucher while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_OTHER << 8, pdev)) != NULL) {
1431586bc4aaSAlex Deucher dhandle = ACPI_HANDLE(&pdev->dev);
1432586bc4aaSAlex Deucher if (dhandle) {
1433586bc4aaSAlex Deucher status = acpi_get_handle(dhandle, "ATPX", &atpx_handle);
143410e92724SBjorn Helgaas if (ACPI_SUCCESS(status)) {
1435586bc4aaSAlex Deucher pci_dev_put(pdev);
1436586bc4aaSAlex Deucher return true;
1437586bc4aaSAlex Deucher }
1438586bc4aaSAlex Deucher }
1439586bc4aaSAlex Deucher }
1440586bc4aaSAlex Deucher return false;
1441586bc4aaSAlex Deucher }
1442586bc4aaSAlex Deucher #else
atpx_present(void)1443586bc4aaSAlex Deucher static bool atpx_present(void)
1444586bc4aaSAlex Deucher {
1445586bc4aaSAlex Deucher return false;
1446586bc4aaSAlex Deucher }
1447586bc4aaSAlex Deucher #endif
1448586bc4aaSAlex Deucher
14491da177e4SLinus Torvalds /*
14502b760d88SLukas Wunner * Check of disabled HDMI controller by vga_switcheroo
14519121947dSTakashi Iwai */
get_bound_vga(struct pci_dev * pci)1452e23e7a14SBill Pemberton static struct pci_dev *get_bound_vga(struct pci_dev *pci)
14539121947dSTakashi Iwai {
14549121947dSTakashi Iwai struct pci_dev *p;
14559121947dSTakashi Iwai
14569121947dSTakashi Iwai /* check only discrete GPU */
14579121947dSTakashi Iwai switch (pci->vendor) {
14589121947dSTakashi Iwai case PCI_VENDOR_ID_ATI:
14599121947dSTakashi Iwai case PCI_VENDOR_ID_AMD:
1460586bc4aaSAlex Deucher if (pci->devfn == 1) {
1461586bc4aaSAlex Deucher p = pci_get_domain_bus_and_slot(pci_domain_nr(pci->bus),
1462586bc4aaSAlex Deucher pci->bus->number, 0);
1463586bc4aaSAlex Deucher if (p) {
1464586bc4aaSAlex Deucher /* ATPX is in the integrated GPU's ACPI namespace
1465586bc4aaSAlex Deucher * rather than the dGPU's namespace. However,
1466586bc4aaSAlex Deucher * the dGPU is the one who is involved in
1467586bc4aaSAlex Deucher * vgaswitcheroo.
1468586bc4aaSAlex Deucher */
1469586bc4aaSAlex Deucher if (((p->class >> 16) == PCI_BASE_CLASS_DISPLAY) &&
14705beb5627SOrlando Chamberlain (atpx_present() || apple_gmux_detect(NULL, NULL)))
1471586bc4aaSAlex Deucher return p;
1472586bc4aaSAlex Deucher pci_dev_put(p);
1473586bc4aaSAlex Deucher }
1474586bc4aaSAlex Deucher }
1475586bc4aaSAlex Deucher break;
14769121947dSTakashi Iwai case PCI_VENDOR_ID_NVIDIA:
14779121947dSTakashi Iwai if (pci->devfn == 1) {
14789121947dSTakashi Iwai p = pci_get_domain_bus_and_slot(pci_domain_nr(pci->bus),
14799121947dSTakashi Iwai pci->bus->number, 0);
14809121947dSTakashi Iwai if (p) {
1481b6d7b362SJim Qu if ((p->class >> 16) == PCI_BASE_CLASS_DISPLAY)
14829121947dSTakashi Iwai return p;
14839121947dSTakashi Iwai pci_dev_put(p);
14849121947dSTakashi Iwai }
14859121947dSTakashi Iwai }
14869121947dSTakashi Iwai break;
14879121947dSTakashi Iwai }
14889121947dSTakashi Iwai return NULL;
14899121947dSTakashi Iwai }
14909121947dSTakashi Iwai
check_hdmi_disabled(struct pci_dev * pci)1491e23e7a14SBill Pemberton static bool check_hdmi_disabled(struct pci_dev *pci)
14929121947dSTakashi Iwai {
14939121947dSTakashi Iwai bool vga_inactive = false;
14949121947dSTakashi Iwai struct pci_dev *p = get_bound_vga(pci);
14959121947dSTakashi Iwai
14969121947dSTakashi Iwai if (p) {
149712b78a7fSTakashi Iwai if (vga_switcheroo_get_client_state(p) == VGA_SWITCHEROO_OFF)
14989121947dSTakashi Iwai vga_inactive = true;
14999121947dSTakashi Iwai pci_dev_put(p);
15009121947dSTakashi Iwai }
15019121947dSTakashi Iwai return vga_inactive;
15029121947dSTakashi Iwai }
15038393ec4aSSteven Newbury #endif /* SUPPORT_VGA_SWITCHEROO */
15049121947dSTakashi Iwai
15059121947dSTakashi Iwai /*
15066317e5ebSTakashi Iwai * allow/deny-listing for position_fix
15073372a153STakashi Iwai */
1508a5dc05e4STakashi Iwai static const struct snd_pci_quirk position_fix_list[] = {
1509d2e1c973STakashi Iwai SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_LPIB),
1510d2e1c973STakashi Iwai SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_LPIB),
15112f703e7aSTakashi Iwai SND_PCI_QUIRK(0x103c, 0x306d, "HP dv3", POS_FIX_LPIB),
1512d2e1c973STakashi Iwai SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB),
1513dd37f8e8SDaniel T Chen SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS", POS_FIX_LPIB),
15149f75c1b1SDaniel T Chen SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS M2V", POS_FIX_LPIB),
1515e96d3127SDaniel T Chen SND_PCI_QUIRK(0x104d, 0x9069, "Sony VPCS11V9E", POS_FIX_LPIB),
1516b01de4fbSDavid Henningsson SND_PCI_QUIRK(0x10de, 0xcb89, "Macbook Pro 7,1", POS_FIX_LPIB),
151761bb42c3SDaniel T Chen SND_PCI_QUIRK(0x1297, 0x3166, "Shuttle", POS_FIX_LPIB),
15189ec8ddadSDaniel T Chen SND_PCI_QUIRK(0x1458, 0xa022, "ga-ma770-ud3", POS_FIX_LPIB),
151945d4ebf1STakashi Iwai SND_PCI_QUIRK(0x1462, 0x1002, "MSI Wind U115", POS_FIX_LPIB),
15208815cd03STakashi Iwai SND_PCI_QUIRK(0x1565, 0x8218, "Biostar Microtech", POS_FIX_LPIB),
1521b90c0764SDaniel T Chen SND_PCI_QUIRK(0x1849, 0x0888, "775Dual-VSTA", POS_FIX_LPIB),
15220e0280dcSDaniel T Chen SND_PCI_QUIRK(0x8086, 0x2503, "DG965OT AAD63733-203", POS_FIX_LPIB),
15233372a153STakashi Iwai {}
15243372a153STakashi Iwai };
15253372a153STakashi Iwai
check_position_fix(struct azx * chip,int fix)1526e23e7a14SBill Pemberton static int check_position_fix(struct azx *chip, int fix)
15273372a153STakashi Iwai {
15283372a153STakashi Iwai const struct snd_pci_quirk *q;
15293372a153STakashi Iwai
1530c673ba1cSTakashi Iwai switch (fix) {
15311dac6695STakashi Iwai case POS_FIX_AUTO:
1532c673ba1cSTakashi Iwai case POS_FIX_LPIB:
1533c673ba1cSTakashi Iwai case POS_FIX_POSBUF:
15344cb36310SDavid Henningsson case POS_FIX_VIACOMBO:
1535a6f2fd55STakashi Iwai case POS_FIX_COMBO:
1536f87e7f25STakashi Iwai case POS_FIX_SKL:
1537c02f77d3STakashi Iwai case POS_FIX_FIFO:
1538c673ba1cSTakashi Iwai return fix;
1539c673ba1cSTakashi Iwai }
1540c673ba1cSTakashi Iwai
15413372a153STakashi Iwai q = snd_pci_quirk_lookup(chip->pci, position_fix_list);
15423372a153STakashi Iwai if (q) {
15434e76a883STakashi Iwai dev_info(chip->card->dev,
15444e76a883STakashi Iwai "position_fix set to %d for device %04x:%04x\n",
15453372a153STakashi Iwai q->value, q->subvendor, q->subdevice);
15463372a153STakashi Iwai return q->value;
15473372a153STakashi Iwai }
1548bdd9ef24SDavid Henningsson
1549bdd9ef24SDavid Henningsson /* Check VIA/ATI HD Audio Controller exist */
155026f05717STakashi Iwai if (chip->driver_type == AZX_DRIVER_VIA) {
15514e76a883STakashi Iwai dev_dbg(chip->card->dev, "Using VIACOMBO position fix\n");
1552bdd9ef24SDavid Henningsson return POS_FIX_VIACOMBO;
1553bdd9ef24SDavid Henningsson }
1554c02f77d3STakashi Iwai if (chip->driver_caps & AZX_DCAPS_AMD_WORKAROUND) {
1555c02f77d3STakashi Iwai dev_dbg(chip->card->dev, "Using FIFO position fix\n");
1556c02f77d3STakashi Iwai return POS_FIX_FIFO;
1557c02f77d3STakashi Iwai }
15589477c58eSTakashi Iwai if (chip->driver_caps & AZX_DCAPS_POSFIX_LPIB) {
15594e76a883STakashi Iwai dev_dbg(chip->card->dev, "Using LPIB position fix\n");
15609477c58eSTakashi Iwai return POS_FIX_LPIB;
15619477c58eSTakashi Iwai }
1562a4b4793fSTakashi Iwai if (chip->driver_type == AZX_DRIVER_SKL) {
1563f87e7f25STakashi Iwai dev_dbg(chip->card->dev, "Using SKL position fix\n");
1564f87e7f25STakashi Iwai return POS_FIX_SKL;
1565f87e7f25STakashi Iwai }
1566c673ba1cSTakashi Iwai return POS_FIX_AUTO;
15673372a153STakashi Iwai }
15683372a153STakashi Iwai
assign_position_fix(struct azx * chip,int fix)1569b6050ef6STakashi Iwai static void assign_position_fix(struct azx *chip, int fix)
1570b6050ef6STakashi Iwai {
1571bf82326fSTakashi Iwai static const azx_get_pos_callback_t callbacks[] = {
1572b6050ef6STakashi Iwai [POS_FIX_AUTO] = NULL,
1573b6050ef6STakashi Iwai [POS_FIX_LPIB] = azx_get_pos_lpib,
1574b6050ef6STakashi Iwai [POS_FIX_POSBUF] = azx_get_pos_posbuf,
1575b6050ef6STakashi Iwai [POS_FIX_VIACOMBO] = azx_via_get_position,
1576b6050ef6STakashi Iwai [POS_FIX_COMBO] = azx_get_pos_lpib,
1577c4ca3871STakashi Iwai [POS_FIX_SKL] = azx_get_pos_posbuf,
1578c02f77d3STakashi Iwai [POS_FIX_FIFO] = azx_get_pos_fifo,
1579b6050ef6STakashi Iwai };
1580b6050ef6STakashi Iwai
1581b6050ef6STakashi Iwai chip->get_position[0] = chip->get_position[1] = callbacks[fix];
1582b6050ef6STakashi Iwai
1583b6050ef6STakashi Iwai /* combo mode uses LPIB only for playback */
1584b6050ef6STakashi Iwai if (fix == POS_FIX_COMBO)
1585b6050ef6STakashi Iwai chip->get_position[1] = NULL;
1586b6050ef6STakashi Iwai
1587f87e7f25STakashi Iwai if ((fix == POS_FIX_POSBUF || fix == POS_FIX_SKL) &&
1588b6050ef6STakashi Iwai (chip->driver_caps & AZX_DCAPS_COUNT_LPIB_DELAY)) {
1589b6050ef6STakashi Iwai chip->get_delay[0] = chip->get_delay[1] =
1590b6050ef6STakashi Iwai azx_get_delay_from_lpib;
1591b6050ef6STakashi Iwai }
1592b6050ef6STakashi Iwai
1593c02f77d3STakashi Iwai if (fix == POS_FIX_FIFO)
1594c02f77d3STakashi Iwai chip->get_delay[0] = chip->get_delay[1] =
1595c02f77d3STakashi Iwai azx_get_delay_from_fifo;
1596b6050ef6STakashi Iwai }
1597b6050ef6STakashi Iwai
15983372a153STakashi Iwai /*
15996317e5ebSTakashi Iwai * deny-lists for probe_mask
1600669ba27aSTakashi Iwai */
1601a5dc05e4STakashi Iwai static const struct snd_pci_quirk probe_mask_list[] = {
1602669ba27aSTakashi Iwai /* Thinkpad often breaks the controller communication when accessing
1603669ba27aSTakashi Iwai * to the non-working (or non-existing) modem codec slot.
1604669ba27aSTakashi Iwai */
1605669ba27aSTakashi Iwai SND_PCI_QUIRK(0x1014, 0x05b7, "Thinkpad Z60", 0x01),
1606669ba27aSTakashi Iwai SND_PCI_QUIRK(0x17aa, 0x2010, "Thinkpad X/T/R60", 0x01),
1607669ba27aSTakashi Iwai SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X/T/R61", 0x01),
16080edb9454STakashi Iwai /* broken BIOS */
16090edb9454STakashi Iwai SND_PCI_QUIRK(0x1028, 0x20ac, "Dell Studio Desktop", 0x01),
1610ef1681d8STakashi Iwai /* including bogus ALC268 in slot#2 that conflicts with ALC888 */
1611ef1681d8STakashi Iwai SND_PCI_QUIRK(0x17c0, 0x4085, "Medion MD96630", 0x01),
161220db7cb0STakashi Iwai /* forced codec slots */
161393574844SOzan Çağlayan SND_PCI_QUIRK(0x1043, 0x1262, "ASUS W5Fm", 0x103),
161420db7cb0STakashi Iwai SND_PCI_QUIRK(0x1046, 0x1262, "ASUS W5F", 0x103),
1615dd8e5b16STakashi Iwai SND_PCI_QUIRK(0x1558, 0x0351, "Schenker Dock 15", 0x105),
1616f3af9051SJaroslav Kysela /* WinFast VP200 H (Teradici) user reported broken communication */
1617f3af9051SJaroslav Kysela SND_PCI_QUIRK(0x3a21, 0x040d, "WinFast VP200 H", 0x101),
1618669ba27aSTakashi Iwai {}
1619669ba27aSTakashi Iwai };
1620669ba27aSTakashi Iwai
1621f1eaaeecSTakashi Iwai #define AZX_FORCE_CODEC_MASK 0x100
1622f1eaaeecSTakashi Iwai
check_probe_mask(struct azx * chip,int dev)1623e23e7a14SBill Pemberton static void check_probe_mask(struct azx *chip, int dev)
1624669ba27aSTakashi Iwai {
1625669ba27aSTakashi Iwai const struct snd_pci_quirk *q;
1626669ba27aSTakashi Iwai
1627f1eaaeecSTakashi Iwai chip->codec_probe_mask = probe_mask[dev];
1628f1eaaeecSTakashi Iwai if (chip->codec_probe_mask == -1) {
1629669ba27aSTakashi Iwai q = snd_pci_quirk_lookup(chip->pci, probe_mask_list);
1630669ba27aSTakashi Iwai if (q) {
16314e76a883STakashi Iwai dev_info(chip->card->dev,
16324e76a883STakashi Iwai "probe_mask set to 0x%x for device %04x:%04x\n",
1633669ba27aSTakashi Iwai q->value, q->subvendor, q->subdevice);
1634f1eaaeecSTakashi Iwai chip->codec_probe_mask = q->value;
1635669ba27aSTakashi Iwai }
1636669ba27aSTakashi Iwai }
1637f1eaaeecSTakashi Iwai
1638f1eaaeecSTakashi Iwai /* check forced option */
1639f1eaaeecSTakashi Iwai if (chip->codec_probe_mask != -1 &&
1640f1eaaeecSTakashi Iwai (chip->codec_probe_mask & AZX_FORCE_CODEC_MASK)) {
1641a41d1224STakashi Iwai azx_bus(chip)->codec_mask = chip->codec_probe_mask & 0xff;
16424e76a883STakashi Iwai dev_info(chip->card->dev, "codec_mask forced to 0x%x\n",
1643a41d1224STakashi Iwai (int)azx_bus(chip)->codec_mask);
1644f1eaaeecSTakashi Iwai }
1645669ba27aSTakashi Iwai }
1646669ba27aSTakashi Iwai
16474d8e22e0STakashi Iwai /*
16486317e5ebSTakashi Iwai * allow/deny-list for enable_msi
16494d8e22e0STakashi Iwai */
16506317e5ebSTakashi Iwai static const struct snd_pci_quirk msi_deny_list[] = {
1651693e0cb0SDavid Henningsson SND_PCI_QUIRK(0x103c, 0x2191, "HP", 0), /* AMD Hudson */
1652693e0cb0SDavid Henningsson SND_PCI_QUIRK(0x103c, 0x2192, "HP", 0), /* AMD Hudson */
1653693e0cb0SDavid Henningsson SND_PCI_QUIRK(0x103c, 0x21f7, "HP", 0), /* AMD Hudson */
1654693e0cb0SDavid Henningsson SND_PCI_QUIRK(0x103c, 0x21fa, "HP", 0), /* AMD Hudson */
16559dc8398bSTakashi Iwai SND_PCI_QUIRK(0x1043, 0x81f2, "ASUS", 0), /* Athlon64 X2 + nvidia */
16560a27fcfaSTakashi Iwai SND_PCI_QUIRK(0x1043, 0x81f6, "ASUS", 0), /* nvidia */
1657ecd21626SRalf Gerbig SND_PCI_QUIRK(0x1043, 0x822d, "ASUS", 0), /* Athlon64 X2 + nvidia MCP55 */
165883f72151STakashi Iwai SND_PCI_QUIRK(0x1179, 0xfb44, "Toshiba Satellite C870", 0), /* AMD Hudson */
16594193d13bSMichele Ballabio SND_PCI_QUIRK(0x1849, 0x0888, "ASRock", 0), /* Athlon64 X2 + nvidia */
16603815595eSTakashi Iwai SND_PCI_QUIRK(0xa0a0, 0x0575, "Aopen MZ915-M", 0), /* ICH6 */
16614d8e22e0STakashi Iwai {}
16624d8e22e0STakashi Iwai };
16634d8e22e0STakashi Iwai
check_msi(struct azx * chip)1664e23e7a14SBill Pemberton static void check_msi(struct azx *chip)
16654d8e22e0STakashi Iwai {
16664d8e22e0STakashi Iwai const struct snd_pci_quirk *q;
16674d8e22e0STakashi Iwai
166871623855STakashi Iwai if (enable_msi >= 0) {
166971623855STakashi Iwai chip->msi = !!enable_msi;
16704d8e22e0STakashi Iwai return;
167171623855STakashi Iwai }
167271623855STakashi Iwai chip->msi = 1; /* enable MSI as default */
16736317e5ebSTakashi Iwai q = snd_pci_quirk_lookup(chip->pci, msi_deny_list);
16744d8e22e0STakashi Iwai if (q) {
16754e76a883STakashi Iwai dev_info(chip->card->dev,
16764e76a883STakashi Iwai "msi for device %04x:%04x set to %d\n",
16774d8e22e0STakashi Iwai q->subvendor, q->subdevice, q->value);
16784d8e22e0STakashi Iwai chip->msi = q->value;
167980c43ed7STakashi Iwai return;
168080c43ed7STakashi Iwai }
168180c43ed7STakashi Iwai
168280c43ed7STakashi Iwai /* NVidia chipsets seem to cause troubles with MSI */
16839477c58eSTakashi Iwai if (chip->driver_caps & AZX_DCAPS_NO_MSI) {
16844e76a883STakashi Iwai dev_info(chip->card->dev, "Disabling MSI\n");
168580c43ed7STakashi Iwai chip->msi = 0;
16864d8e22e0STakashi Iwai }
16874d8e22e0STakashi Iwai }
16884d8e22e0STakashi Iwai
1689a1585d76STakashi Iwai /* check the snoop mode availability */
azx_check_snoop_available(struct azx * chip)1690e23e7a14SBill Pemberton static void azx_check_snoop_available(struct azx *chip)
1691a1585d76STakashi Iwai {
16927c732015STakashi Iwai int snoop = hda_snoop;
1693a1585d76STakashi Iwai
16947c732015STakashi Iwai if (snoop >= 0) {
16957c732015STakashi Iwai dev_info(chip->card->dev, "Force to %s mode by module option\n",
16967c732015STakashi Iwai snoop ? "snoop" : "non-snoop");
16977c732015STakashi Iwai chip->snoop = snoop;
169878c9be61STakashi Iwai chip->uc_buffer = !snoop;
16997c732015STakashi Iwai return;
17007c732015STakashi Iwai }
17017c732015STakashi Iwai
17027c732015STakashi Iwai snoop = true;
170337e661eeSTakashi Iwai if (azx_get_snoop_type(chip) == AZX_SNOOP_TYPE_NONE &&
170437e661eeSTakashi Iwai chip->driver_type == AZX_DRIVER_VIA) {
1705a1585d76STakashi Iwai /* force to non-snoop mode for a new VIA controller
1706a1585d76STakashi Iwai * when BIOS is set
1707a1585d76STakashi Iwai */
1708a1585d76STakashi Iwai u8 val;
1709a1585d76STakashi Iwai pci_read_config_byte(chip->pci, 0x42, &val);
1710af52f998SDavid Wang if (!(val & 0x80) && (chip->pci->revision == 0x30 ||
1711af52f998SDavid Wang chip->pci->revision == 0x20))
1712a1585d76STakashi Iwai snoop = false;
1713a1585d76STakashi Iwai }
1714a1585d76STakashi Iwai
171537e661eeSTakashi Iwai if (chip->driver_caps & AZX_DCAPS_SNOOP_OFF)
171637e661eeSTakashi Iwai snoop = false;
171737e661eeSTakashi Iwai
1718a1585d76STakashi Iwai chip->snoop = snoop;
171978c9be61STakashi Iwai if (!snoop) {
17207c732015STakashi Iwai dev_info(chip->card->dev, "Force to non-snoop mode\n");
172178c9be61STakashi Iwai /* C-Media requires non-cached pages only for CORB/RIRB */
172278c9be61STakashi Iwai if (chip->driver_type != AZX_DRIVER_CMEDIA)
172378c9be61STakashi Iwai chip->uc_buffer = true;
172478c9be61STakashi Iwai }
1725a1585d76STakashi Iwai }
1726669ba27aSTakashi Iwai
azx_probe_work(struct work_struct * work)172799a2008dSWang Xingchao static void azx_probe_work(struct work_struct *work)
172899a2008dSWang Xingchao {
1729c0f1886dSTakashi Iwai struct hda_intel *hda = container_of(work, struct hda_intel, probe_work.work);
17309a34af4aSTakashi Iwai azx_probe_continue(&hda->chip);
173199a2008dSWang Xingchao }
173299a2008dSWang Xingchao
default_bdl_pos_adj(struct azx * chip)17334f0189beSTakashi Iwai static int default_bdl_pos_adj(struct azx *chip)
17344f0189beSTakashi Iwai {
17352cf721dbSTakashi Iwai /* some exceptions: Atoms seem problematic with value 1 */
17362cf721dbSTakashi Iwai if (chip->pci->vendor == PCI_VENDOR_ID_INTEL) {
17372cf721dbSTakashi Iwai switch (chip->pci->device) {
1738580118d5SRui Salvaterra case PCI_DEVICE_ID_INTEL_HDA_BYT:
1739580118d5SRui Salvaterra case PCI_DEVICE_ID_INTEL_HDA_BSW:
17402cf721dbSTakashi Iwai return 32;
1741034a0061SRui Salvaterra case PCI_DEVICE_ID_INTEL_HDA_APL:
1742034a0061SRui Salvaterra return 64;
17432cf721dbSTakashi Iwai }
17442cf721dbSTakashi Iwai }
17452cf721dbSTakashi Iwai
17464f0189beSTakashi Iwai switch (chip->driver_type) {
1747c51e4310Sjasontao /*
1748c51e4310Sjasontao * increase the bdl size for Glenfly Gpus for hardware
1749c51e4310Sjasontao * limitation on hdac interrupt interval
1750c51e4310Sjasontao */
1751c51e4310Sjasontao case AZX_DRIVER_GFHDMI:
1752c51e4310Sjasontao return 128;
17534f0189beSTakashi Iwai case AZX_DRIVER_ICH:
17544f0189beSTakashi Iwai case AZX_DRIVER_PCH:
17554f0189beSTakashi Iwai return 1;
17564f0189beSTakashi Iwai default:
17574f0189beSTakashi Iwai return 32;
17584f0189beSTakashi Iwai }
17594f0189beSTakashi Iwai }
17604f0189beSTakashi Iwai
1761669ba27aSTakashi Iwai /*
17621da177e4SLinus Torvalds * constructor
17631da177e4SLinus Torvalds */
1764a43ff5baSTakashi Iwai static const struct hda_controller_ops pci_hda_ops;
1765a43ff5baSTakashi Iwai
azx_create(struct snd_card * card,struct pci_dev * pci,int dev,unsigned int driver_caps,struct azx ** rchip)1766e23e7a14SBill Pemberton static int azx_create(struct snd_card *card, struct pci_dev *pci,
17679477c58eSTakashi Iwai int dev, unsigned int driver_caps,
1768a98f90fdSTakashi Iwai struct azx **rchip)
17691da177e4SLinus Torvalds {
177041f394a8STakashi Iwai static const struct snd_device_ops ops = {
1771a41d1224STakashi Iwai .dev_disconnect = azx_dev_disconnect,
17721da177e4SLinus Torvalds .dev_free = azx_dev_free,
17731da177e4SLinus Torvalds };
1774a07187c9SMengdong Lin struct hda_intel *hda;
1775a82d51edSTakashi Iwai struct azx *chip;
1776a82d51edSTakashi Iwai int err;
17771da177e4SLinus Torvalds
17781da177e4SLinus Torvalds *rchip = NULL;
17791da177e4SLinus Torvalds
17803fcaf24eSTakashi Iwai err = pcim_enable_device(pci);
1781927fc866SPavel Machek if (err < 0)
17821da177e4SLinus Torvalds return err;
17831da177e4SLinus Torvalds
17842393e755STakashi Iwai hda = devm_kzalloc(&pci->dev, sizeof(*hda), GFP_KERNEL);
17853fcaf24eSTakashi Iwai if (!hda)
17861da177e4SLinus Torvalds return -ENOMEM;
17871da177e4SLinus Torvalds
1788a07187c9SMengdong Lin chip = &hda->chip;
178962932df8SIngo Molnar mutex_init(&chip->open_mutex);
17901da177e4SLinus Torvalds chip->card = card;
17911da177e4SLinus Torvalds chip->pci = pci;
1792a43ff5baSTakashi Iwai chip->ops = &pci_hda_ops;
17939477c58eSTakashi Iwai chip->driver_caps = driver_caps;
17949477c58eSTakashi Iwai chip->driver_type = driver_caps & 0xff;
17954d8e22e0STakashi Iwai check_msi(chip);
1796555e219fSTakashi Iwai chip->dev_index = dev;
17973a182c84STakashi Iwai if (jackpoll_ms[dev] >= 50 && jackpoll_ms[dev] <= 60000)
17983a182c84STakashi Iwai chip->jackpoll_interval = msecs_to_jiffies(jackpoll_ms[dev]);
179901b65bfbSTakashi Iwai INIT_LIST_HEAD(&chip->pcm_list);
18009a34af4aSTakashi Iwai INIT_WORK(&hda->irq_pending_work, azx_irq_pending_work);
18019a34af4aSTakashi Iwai INIT_LIST_HEAD(&hda->list);
1802a82d51edSTakashi Iwai init_vga_switcheroo(chip);
18039a34af4aSTakashi Iwai init_completion(&hda->probe_wait);
18041da177e4SLinus Torvalds
1805b6050ef6STakashi Iwai assign_position_fix(chip, check_position_fix(chip, position_fix[dev]));
1806a6f2fd55STakashi Iwai
180741438f13STakashi Iwai if (single_cmd < 0) /* allow fallback to single_cmd at errors */
180841438f13STakashi Iwai chip->fallback_to_single_cmd = 1;
180941438f13STakashi Iwai else /* explicitly set to single_cmd or not */
181027346166STakashi Iwai chip->single_cmd = single_cmd;
181141438f13STakashi Iwai
1812a1585d76STakashi Iwai azx_check_snoop_available(chip);
1813c74db86bSTakashi Iwai
18144f0189beSTakashi Iwai if (bdl_pos_adj[dev] < 0)
18154f0189beSTakashi Iwai chip->bdl_pos_adj = default_bdl_pos_adj(chip);
18164f0189beSTakashi Iwai else
18174f0189beSTakashi Iwai chip->bdl_pos_adj = bdl_pos_adj[dev];
18185c0d7bc1STakashi Iwai
181919abfefdSTakashi Iwai err = azx_bus_init(chip, model[dev]);
18203fcaf24eSTakashi Iwai if (err < 0)
1821a41d1224STakashi Iwai return err;
1822a41d1224STakashi Iwai
1823619a1f19STakashi Iwai /* use the non-cached pages in non-snoop mode */
1824619a1f19STakashi Iwai if (!azx_snoop(chip))
182537137ec2STakashi Iwai azx_bus(chip)->dma_type = SNDRV_DMA_TYPE_DEV_WC_SG;
1826619a1f19STakashi Iwai
18277d9a1808STakashi Iwai if (chip->driver_type == AZX_DRIVER_NVIDIA) {
18287d9a1808STakashi Iwai dev_dbg(chip->card->dev, "Enable delay in RIRB handling\n");
18295f2cb361STakashi Iwai chip->bus.core.needs_damn_long_delay = 1;
18307d9a1808STakashi Iwai }
18317d9a1808STakashi Iwai
18326317f744STakashi Iwai check_probe_mask(chip, dev);
18336317f744STakashi Iwai
1834a82d51edSTakashi Iwai err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
1835a82d51edSTakashi Iwai if (err < 0) {
18364e76a883STakashi Iwai dev_err(card->dev, "Error creating device [card]!\n");
1837a82d51edSTakashi Iwai azx_free(chip);
1838a82d51edSTakashi Iwai return err;
1839a82d51edSTakashi Iwai }
1840a82d51edSTakashi Iwai
184199a2008dSWang Xingchao /* continue probing in work context as may trigger request module */
1842c0f1886dSTakashi Iwai INIT_DELAYED_WORK(&hda->probe_work, azx_probe_work);
184399a2008dSWang Xingchao
1844a82d51edSTakashi Iwai *rchip = chip;
184599a2008dSWang Xingchao
1846a82d51edSTakashi Iwai return 0;
1847a82d51edSTakashi Iwai }
1848a82d51edSTakashi Iwai
azx_first_init(struct azx * chip)184948c8b0ebSTakashi Iwai static int azx_first_init(struct azx *chip)
1850a82d51edSTakashi Iwai {
1851a82d51edSTakashi Iwai int dev = chip->dev_index;
1852a82d51edSTakashi Iwai struct pci_dev *pci = chip->pci;
1853a82d51edSTakashi Iwai struct snd_card *card = chip->card;
1854a41d1224STakashi Iwai struct hdac_bus *bus = azx_bus(chip);
185567908994SDylan Reid int err;
1856a82d51edSTakashi Iwai unsigned short gcap;
1857413cbf46STakashi Iwai unsigned int dma_bits = 64;
1858a82d51edSTakashi Iwai
185907e4ca50STakashi Iwai #if BITS_PER_LONG != 64
186007e4ca50STakashi Iwai /* Fix up base address on ULI M5461 */
186107e4ca50STakashi Iwai if (chip->driver_type == AZX_DRIVER_ULI) {
186207e4ca50STakashi Iwai u16 tmp3;
186307e4ca50STakashi Iwai pci_read_config_word(pci, 0x40, &tmp3);
186407e4ca50STakashi Iwai pci_write_config_word(pci, 0x40, tmp3 | 0x10);
186507e4ca50STakashi Iwai pci_write_config_dword(pci, PCI_BASE_ADDRESS_1, 0);
186607e4ca50STakashi Iwai }
186707e4ca50STakashi Iwai #endif
1868c51e4310Sjasontao /*
1869c51e4310Sjasontao * Fix response write request not synced to memory when handle
1870c51e4310Sjasontao * hdac interrupt on Glenfly Gpus
1871c51e4310Sjasontao */
1872c51e4310Sjasontao if (chip->driver_type == AZX_DRIVER_GFHDMI)
1873c51e4310Sjasontao bus->polling_mode = 1;
187407e4ca50STakashi Iwai
1875cbc3e98aSYanteng Si if (chip->driver_type == AZX_DRIVER_LOONGSON) {
1876cbc3e98aSYanteng Si bus->polling_mode = 1;
1877cbc3e98aSYanteng Si bus->not_use_interrupts = 1;
1878942ccdd8SYanteng Si bus->access_sdnctl_in_dword = 1;
1879cbc3e98aSYanteng Si }
1880cbc3e98aSYanteng Si
18813fcaf24eSTakashi Iwai err = pcim_iomap_regions(pci, 1 << 0, "ICH HD audio");
1882a82d51edSTakashi Iwai if (err < 0)
18831da177e4SLinus Torvalds return err;
18841da177e4SLinus Torvalds
1885a41d1224STakashi Iwai bus->addr = pci_resource_start(pci, 0);
18863fcaf24eSTakashi Iwai bus->remap_addr = pcim_iomap_table(pci)[0];
18871da177e4SLinus Torvalds
1888a4b4793fSTakashi Iwai if (chip->driver_type == AZX_DRIVER_SKL)
188950279d9bSGuneshwor Singh snd_hdac_bus_parse_capabilities(bus);
189050279d9bSGuneshwor Singh
189150279d9bSGuneshwor Singh /*
189250279d9bSGuneshwor Singh * Some Intel CPUs has always running timer (ART) feature and
189350279d9bSGuneshwor Singh * controller may have Global time sync reporting capability, so
189450279d9bSGuneshwor Singh * check both of these before declaring synchronized time reporting
189550279d9bSGuneshwor Singh * capability SNDRV_PCM_INFO_HAS_LINK_SYNCHRONIZED_ATIME
189650279d9bSGuneshwor Singh */
189750279d9bSGuneshwor Singh chip->gts_present = false;
189850279d9bSGuneshwor Singh
189950279d9bSGuneshwor Singh #ifdef CONFIG_X86
190050279d9bSGuneshwor Singh if (bus->ppcap && boot_cpu_has(X86_FEATURE_ART))
190150279d9bSGuneshwor Singh chip->gts_present = true;
190250279d9bSGuneshwor Singh #endif
190350279d9bSGuneshwor Singh
1904db79afa1SBenjamin Herrenschmidt if (chip->msi) {
1905db79afa1SBenjamin Herrenschmidt if (chip->driver_caps & AZX_DCAPS_NO_MSI64) {
1906db79afa1SBenjamin Herrenschmidt dev_dbg(card->dev, "Disabling 64bit MSI\n");
1907db79afa1SBenjamin Herrenschmidt pci->no_64bit_msi = true;
1908db79afa1SBenjamin Herrenschmidt }
190968e7fffcSTakashi Iwai if (pci_enable_msi(pci) < 0)
191068e7fffcSTakashi Iwai chip->msi = 0;
1911db79afa1SBenjamin Herrenschmidt }
19127376d013SStephen Hemminger
19131da177e4SLinus Torvalds pci_set_master(pci);
19141da177e4SLinus Torvalds
1915bcd72003STobin Davis gcap = azx_readw(chip, GCAP);
19164e76a883STakashi Iwai dev_dbg(card->dev, "chipset global capabilities = 0x%x\n", gcap);
1917bcd72003STobin Davis
1918413cbf46STakashi Iwai /* AMD devices support 40 or 48bit DMA, take the safe one */
1919413cbf46STakashi Iwai if (chip->pci->vendor == PCI_VENDOR_ID_AMD)
1920413cbf46STakashi Iwai dma_bits = 40;
1921413cbf46STakashi Iwai
1922dc4c2e6bSAndiry Brienza /* disable SB600 64bit support for safety */
19239477c58eSTakashi Iwai if (chip->pci->vendor == PCI_VENDOR_ID_ATI) {
1924dc4c2e6bSAndiry Brienza struct pci_dev *p_smbus;
1925413cbf46STakashi Iwai dma_bits = 40;
1926dc4c2e6bSAndiry Brienza p_smbus = pci_get_device(PCI_VENDOR_ID_ATI,
1927dc4c2e6bSAndiry Brienza PCI_DEVICE_ID_ATI_SBX00_SMBUS,
1928dc4c2e6bSAndiry Brienza NULL);
1929dc4c2e6bSAndiry Brienza if (p_smbus) {
1930dc4c2e6bSAndiry Brienza if (p_smbus->revision < 0x30)
1931fb1d8ac2STakashi Iwai gcap &= ~AZX_GCAP_64OK;
1932dc4c2e6bSAndiry Brienza pci_dev_put(p_smbus);
1933dc4c2e6bSAndiry Brienza }
1934dc4c2e6bSAndiry Brienza }
193509240cf4STakashi Iwai
19363ab7511eSArd Biesheuvel /* NVidia hardware normally only supports up to 40 bits of DMA */
19373ab7511eSArd Biesheuvel if (chip->pci->vendor == PCI_VENDOR_ID_NVIDIA)
19383ab7511eSArd Biesheuvel dma_bits = 40;
19393ab7511eSArd Biesheuvel
19409477c58eSTakashi Iwai /* disable 64bit DMA address on some devices */
19419477c58eSTakashi Iwai if (chip->driver_caps & AZX_DCAPS_NO_64BIT) {
19424e76a883STakashi Iwai dev_dbg(card->dev, "Disabling 64bit DMA\n");
1943fb1d8ac2STakashi Iwai gcap &= ~AZX_GCAP_64OK;
19449477c58eSTakashi Iwai }
1945396087eaSJaroslav Kysela
19462ae66c26SPierre-Louis Bossart /* disable buffer size rounding to 128-byte multiples if supported */
19477bfe059eSTakashi Iwai if (align_buffer_size >= 0)
19487bfe059eSTakashi Iwai chip->align_buffer_size = !!align_buffer_size;
19497bfe059eSTakashi Iwai else {
1950103884a3STakashi Iwai if (chip->driver_caps & AZX_DCAPS_NO_ALIGN_BUFSIZE)
195152409aa6STakashi Iwai chip->align_buffer_size = 0;
19527bfe059eSTakashi Iwai else
19537bfe059eSTakashi Iwai chip->align_buffer_size = 1;
19547bfe059eSTakashi Iwai }
19552ae66c26SPierre-Louis Bossart
1956cf7aaca8STakashi Iwai /* allow 64bit DMA address if supported by H/W */
1957413cbf46STakashi Iwai if (!(gcap & AZX_GCAP_64OK))
1958413cbf46STakashi Iwai dma_bits = 32;
1959669f65eaSTakashi Iwai if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(dma_bits)))
1960669f65eaSTakashi Iwai dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32));
1961acd289e0STakashi Iwai dma_set_max_seg_size(&pci->dev, UINT_MAX);
1962cf7aaca8STakashi Iwai
1963bcd72003STobin Davis /* read number of streams from GCAP register instead of using
1964bcd72003STobin Davis * hardcoded value
1965bcd72003STobin Davis */
19668b6ed8e7STakashi Iwai chip->capture_streams = (gcap >> 8) & 0x0f;
19678b6ed8e7STakashi Iwai chip->playback_streams = (gcap >> 12) & 0x0f;
19688b6ed8e7STakashi Iwai if (!chip->playback_streams && !chip->capture_streams) {
1969bcd72003STobin Davis /* gcap didn't give any info, switching to old method */
1970bcd72003STobin Davis
197107e4ca50STakashi Iwai switch (chip->driver_type) {
197207e4ca50STakashi Iwai case AZX_DRIVER_ULI:
197307e4ca50STakashi Iwai chip->playback_streams = ULI_NUM_PLAYBACK;
197407e4ca50STakashi Iwai chip->capture_streams = ULI_NUM_CAPTURE;
197507e4ca50STakashi Iwai break;
1976778b6e1bSFelix Kuehling case AZX_DRIVER_ATIHDMI:
19771815b34aSAndiry Xu case AZX_DRIVER_ATIHDMI_NS:
1978778b6e1bSFelix Kuehling chip->playback_streams = ATIHDMI_NUM_PLAYBACK;
1979778b6e1bSFelix Kuehling chip->capture_streams = ATIHDMI_NUM_CAPTURE;
1980778b6e1bSFelix Kuehling break;
1981c51e4310Sjasontao case AZX_DRIVER_GFHDMI:
1982c4da29caSYang, Libin case AZX_DRIVER_GENERIC:
198307e4ca50STakashi Iwai default:
198407e4ca50STakashi Iwai chip->playback_streams = ICH6_NUM_PLAYBACK;
198507e4ca50STakashi Iwai chip->capture_streams = ICH6_NUM_CAPTURE;
198607e4ca50STakashi Iwai break;
198707e4ca50STakashi Iwai }
1988bcd72003STobin Davis }
19898b6ed8e7STakashi Iwai chip->capture_index_offset = 0;
19908b6ed8e7STakashi Iwai chip->playback_index_offset = chip->capture_streams;
199107e4ca50STakashi Iwai chip->num_streams = chip->playback_streams + chip->capture_streams;
199207e4ca50STakashi Iwai
1993df56c3dbSJaroslav Kysela /* sanity check for the SDxCTL.STRM field overflow */
1994df56c3dbSJaroslav Kysela if (chip->num_streams > 15 &&
1995df56c3dbSJaroslav Kysela (chip->driver_caps & AZX_DCAPS_SEPARATE_STREAM_TAG) == 0) {
1996df56c3dbSJaroslav Kysela dev_warn(chip->card->dev, "number of I/O streams is %d, "
1997df56c3dbSJaroslav Kysela "forcing separate stream tags", chip->num_streams);
1998df56c3dbSJaroslav Kysela chip->driver_caps |= AZX_DCAPS_SEPARATE_STREAM_TAG;
1999df56c3dbSJaroslav Kysela }
2000df56c3dbSJaroslav Kysela
2001a41d1224STakashi Iwai /* initialize streams */
2002a41d1224STakashi Iwai err = azx_init_streams(chip);
200367908994SDylan Reid if (err < 0)
200467908994SDylan Reid return err;
20051da177e4SLinus Torvalds
20061da177e4SLinus Torvalds err = azx_alloc_stream_pages(chip);
20071da177e4SLinus Torvalds if (err < 0)
20081da177e4SLinus Torvalds return err;
20091da177e4SLinus Torvalds
20101da177e4SLinus Torvalds /* initialize chip */
2011cb53c626STakashi Iwai azx_init_pci(chip);
2012e4d9e513SMengdong Lin
2013bb03ed21STakashi Iwai snd_hdac_i915_set_bclk(bus);
2014e4d9e513SMengdong Lin
20150a673521SLu, Han hda_intel_init_chip(chip, (probe_only[dev] & 2) == 0);
20161da177e4SLinus Torvalds
20171da177e4SLinus Torvalds /* codec detection */
2018a41d1224STakashi Iwai if (!azx_bus(chip)->codec_mask) {
20194e76a883STakashi Iwai dev_err(card->dev, "no codecs found!\n");
20209479e75fSTakashi Iwai /* keep running the rest for the runtime PM */
20211da177e4SLinus Torvalds }
20221da177e4SLinus Torvalds
2023f495222eSTakashi Iwai if (azx_acquire_irq(chip, 0) < 0)
2024f495222eSTakashi Iwai return -EBUSY;
2025f495222eSTakashi Iwai
202607e4ca50STakashi Iwai strcpy(card->driver, "HDA-Intel");
202775b1a8f9SJoe Perches strscpy(card->shortname, driver_short_names[chip->driver_type],
202818cb7109STakashi Iwai sizeof(card->shortname));
202918cb7109STakashi Iwai snprintf(card->longname, sizeof(card->longname),
203018cb7109STakashi Iwai "%s at 0x%lx irq %i",
2031a41d1224STakashi Iwai card->shortname, bus->addr, bus->irq);
203207e4ca50STakashi Iwai
20331da177e4SLinus Torvalds return 0;
20341da177e4SLinus Torvalds }
20351da177e4SLinus Torvalds
203697c6a3d1STakashi Iwai #ifdef CONFIG_SND_HDA_PATCH_LOADER
20375cb543dbSTakashi Iwai /* callback from request_firmware_nowait() */
azx_firmware_cb(const struct firmware * fw,void * context)20385cb543dbSTakashi Iwai static void azx_firmware_cb(const struct firmware *fw, void *context)
20395cb543dbSTakashi Iwai {
20405cb543dbSTakashi Iwai struct snd_card *card = context;
20415cb543dbSTakashi Iwai struct azx *chip = card->private_data;
20425cb543dbSTakashi Iwai
204325faa4bdSTakashi Iwai if (fw)
20445cb543dbSTakashi Iwai chip->fw = fw;
204525faa4bdSTakashi Iwai else
204625faa4bdSTakashi Iwai dev_err(card->dev, "Cannot load firmware, continue without patching\n");
20475cb543dbSTakashi Iwai if (!chip->disabled) {
20485cb543dbSTakashi Iwai /* continue probing */
204925faa4bdSTakashi Iwai azx_probe_continue(chip);
20505cb543dbSTakashi Iwai }
20515cb543dbSTakashi Iwai }
205297c6a3d1STakashi Iwai #endif
20535cb543dbSTakashi Iwai
disable_msi_reset_irq(struct azx * chip)2054f46ea609SDylan Reid static int disable_msi_reset_irq(struct azx *chip)
2055f46ea609SDylan Reid {
2056a41d1224STakashi Iwai struct hdac_bus *bus = azx_bus(chip);
2057f46ea609SDylan Reid int err;
2058f46ea609SDylan Reid
2059a41d1224STakashi Iwai free_irq(bus->irq, chip);
2060a41d1224STakashi Iwai bus->irq = -1;
2061f36da940STakashi Iwai chip->card->sync_irq = -1;
2062f46ea609SDylan Reid pci_disable_msi(chip->pci);
2063f46ea609SDylan Reid chip->msi = 0;
2064f46ea609SDylan Reid err = azx_acquire_irq(chip, 1);
2065f46ea609SDylan Reid if (err < 0)
2066f46ea609SDylan Reid return err;
2067f46ea609SDylan Reid
2068f46ea609SDylan Reid return 0;
2069f46ea609SDylan Reid }
2070f46ea609SDylan Reid
20716317e5ebSTakashi Iwai /* Denylist for skipping the whole probe:
20723c6fd1f0STakashi Iwai * some HD-audio PCI entries are exposed without any codecs, and such devices
20733c6fd1f0STakashi Iwai * should be ignored from the beginning.
20743c6fd1f0STakashi Iwai */
20756317e5ebSTakashi Iwai static const struct pci_device_id driver_denylist[] = {
2076977dfef4STakashi Iwai { PCI_DEVICE_SUB(0x1022, 0x1487, 0x1043, 0x874f) }, /* ASUS ROG Zenith II / Strix */
2077977dfef4STakashi Iwai { PCI_DEVICE_SUB(0x1022, 0x1487, 0x1462, 0xcb59) }, /* MSI TRX40 Creator */
2078977dfef4STakashi Iwai { PCI_DEVICE_SUB(0x1022, 0x1487, 0x1462, 0xcb60) }, /* MSI TRX40 */
20793c6fd1f0STakashi Iwai {}
20803c6fd1f0STakashi Iwai };
20813c6fd1f0STakashi Iwai
2082a43ff5baSTakashi Iwai static const struct hda_controller_ops pci_hda_ops = {
2083a43ff5baSTakashi Iwai .disable_msi_reset_irq = disable_msi_reset_irq,
20847ca954a8SDylan Reid .position_check = azx_position_check,
208540830813SDylan Reid };
208640830813SDylan Reid
208769458e2cSTakashi Iwai static DECLARE_BITMAP(probed_devs, SNDRV_CARDS);
208869458e2cSTakashi Iwai
azx_probe(struct pci_dev * pci,const struct pci_device_id * pci_id)2089e23e7a14SBill Pemberton static int azx_probe(struct pci_dev *pci,
2090d01ce99fSTakashi Iwai const struct pci_device_id *pci_id)
20911da177e4SLinus Torvalds {
2092a98f90fdSTakashi Iwai struct snd_card *card;
20939a34af4aSTakashi Iwai struct hda_intel *hda;
2094a98f90fdSTakashi Iwai struct azx *chip;
2095aad730d0STakashi Iwai bool schedule_probe;
209669458e2cSTakashi Iwai int dev;
2097927fc866SPavel Machek int err;
20981da177e4SLinus Torvalds
20996317e5ebSTakashi Iwai if (pci_match_id(driver_denylist, pci)) {
21006317e5ebSTakashi Iwai dev_info(&pci->dev, "Skipping the device on the denylist\n");
21013c6fd1f0STakashi Iwai return -ENODEV;
21023c6fd1f0STakashi Iwai }
21033c6fd1f0STakashi Iwai
210469458e2cSTakashi Iwai dev = find_first_zero_bit(probed_devs, SNDRV_CARDS);
21055aba4f8eSTakashi Iwai if (dev >= SNDRV_CARDS)
21065aba4f8eSTakashi Iwai return -ENODEV;
21075aba4f8eSTakashi Iwai if (!enable[dev]) {
210869458e2cSTakashi Iwai set_bit(dev, probed_devs);
21095aba4f8eSTakashi Iwai return -ENOENT;
21105aba4f8eSTakashi Iwai }
21115aba4f8eSTakashi Iwai
211282d9d54aSJaroslav Kysela /*
211382d9d54aSJaroslav Kysela * stop probe if another Intel's DSP driver should be activated
211482d9d54aSJaroslav Kysela */
21157fba6aeaSTakashi Iwai if (dmic_detect) {
211682d9d54aSJaroslav Kysela err = snd_intel_dsp_driver_probe(pci);
2117ae035947SPierre-Louis Bossart if (err != SND_INTEL_DSP_DRIVER_ANY && err != SND_INTEL_DSP_DRIVER_LEGACY) {
2118ae035947SPierre-Louis Bossart dev_dbg(&pci->dev, "HDAudio driver not selected, aborting probe\n");
211982d9d54aSJaroslav Kysela return -ENODEV;
2120ae035947SPierre-Louis Bossart }
21217fba6aeaSTakashi Iwai } else {
21227fba6aeaSTakashi Iwai dev_warn(&pci->dev, "dmic_detect option is deprecated, pass snd-intel-dspcfg.dsp_driver=1 option instead\n");
212382d9d54aSJaroslav Kysela }
212482d9d54aSJaroslav Kysela
212560c5772bSTakashi Iwai err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
212660c5772bSTakashi Iwai 0, &card);
2127e58de7baSTakashi Iwai if (err < 0) {
21284e76a883STakashi Iwai dev_err(&pci->dev, "Error creating card!\n");
2129e58de7baSTakashi Iwai return err;
21301da177e4SLinus Torvalds }
21311da177e4SLinus Torvalds
2132a43ff5baSTakashi Iwai err = azx_create(card, pci, dev, pci_id->driver_data, &chip);
213341dda0fdSWu Fengguang if (err < 0)
213441dda0fdSWu Fengguang goto out_free;
2135421a1252STakashi Iwai card->private_data = chip;
21369a34af4aSTakashi Iwai hda = container_of(chip, struct hda_intel, chip);
2137f4c482a4STakashi Iwai
2138f4c482a4STakashi Iwai pci_set_drvdata(pci, card);
2139f4c482a4STakashi Iwai
2140f4c482a4STakashi Iwai err = register_vga_switcheroo(chip);
2141f4c482a4STakashi Iwai if (err < 0) {
21422b760d88SLukas Wunner dev_err(card->dev, "Error registering vga_switcheroo client\n");
2143f4c482a4STakashi Iwai goto out_free;
2144f4c482a4STakashi Iwai }
2145f4c482a4STakashi Iwai
2146f4c482a4STakashi Iwai if (check_hdmi_disabled(pci)) {
21474e76a883STakashi Iwai dev_info(card->dev, "VGA controller is disabled\n");
21484e76a883STakashi Iwai dev_info(card->dev, "Delaying initialization\n");
2149f4c482a4STakashi Iwai chip->disabled = true;
2150f4c482a4STakashi Iwai }
2151f4c482a4STakashi Iwai
2152aad730d0STakashi Iwai schedule_probe = !chip->disabled;
21531da177e4SLinus Torvalds
21544918cdabSTakashi Iwai #ifdef CONFIG_SND_HDA_PATCH_LOADER
21554918cdabSTakashi Iwai if (patch[dev] && *patch[dev]) {
21564e76a883STakashi Iwai dev_info(card->dev, "Applying patch firmware '%s'\n",
21574e76a883STakashi Iwai patch[dev]);
21585cb543dbSTakashi Iwai err = request_firmware_nowait(THIS_MODULE, true, patch[dev],
21595cb543dbSTakashi Iwai &pci->dev, GFP_KERNEL, card,
21605cb543dbSTakashi Iwai azx_firmware_cb);
21614918cdabSTakashi Iwai if (err < 0)
21624918cdabSTakashi Iwai goto out_free;
2163aad730d0STakashi Iwai schedule_probe = false; /* continued in azx_firmware_cb() */
21644918cdabSTakashi Iwai }
21654918cdabSTakashi Iwai #endif /* CONFIG_SND_HDA_PATCH_LOADER */
21664918cdabSTakashi Iwai
2167aad730d0STakashi Iwai #ifndef CONFIG_SND_HDA_I915
21681b21bd7aSAmadeusz Sławiński if (HDA_CONTROLLER_IN_GPU(pci))
21696ee8eeb4STakashi Iwai dev_err(card->dev, "Haswell/Broadwell HDMI/DP must build in CONFIG_SND_HDA_I915\n");
217099a2008dSWang Xingchao #endif
217199a2008dSWang Xingchao
2172aad730d0STakashi Iwai if (schedule_probe)
2173c0f1886dSTakashi Iwai schedule_delayed_work(&hda->probe_work, 0);
2174a82d51edSTakashi Iwai
217569458e2cSTakashi Iwai set_bit(dev, probed_devs);
217688d071fcSTakashi Iwai if (chip->disabled)
21779a34af4aSTakashi Iwai complete_all(&hda->probe_wait);
2178a82d51edSTakashi Iwai return 0;
2179a82d51edSTakashi Iwai
2180a82d51edSTakashi Iwai out_free:
2181a82d51edSTakashi Iwai snd_card_free(card);
2182a82d51edSTakashi Iwai return err;
2183a82d51edSTakashi Iwai }
2184a82d51edSTakashi Iwai
21851ba8f9d3SHans de Goede #ifdef CONFIG_PM
21861ba8f9d3SHans de Goede /* On some boards setting power_save to a non 0 value leads to clicking /
21871ba8f9d3SHans de Goede * popping sounds when ever we enter/leave powersaving mode. Ideally we would
21881ba8f9d3SHans de Goede * figure out how to avoid these sounds, but that is not always feasible.
21891ba8f9d3SHans de Goede * So we keep a list of devices where we disable powersaving as its known
21901ba8f9d3SHans de Goede * to causes problems on these devices.
21911ba8f9d3SHans de Goede */
21926317e5ebSTakashi Iwai static const struct snd_pci_quirk power_save_denylist[] = {
21931ba8f9d3SHans de Goede /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */
21948e82a728SHans de Goede SND_PCI_QUIRK(0x1849, 0xc892, "Asrock B85M-ITX", 0),
21951ba8f9d3SHans de Goede /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */
219639070a98SHans de Goede SND_PCI_QUIRK(0x1849, 0x0397, "Asrock N68C-S UCC", 0),
219739070a98SHans de Goede /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */
219845e5fbc2SHans de Goede SND_PCI_QUIRK(0x1849, 0x7662, "Asrock H81M-HDS", 0),
219945e5fbc2SHans de Goede /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */
22001ba8f9d3SHans de Goede SND_PCI_QUIRK(0x1043, 0x8733, "Asus Prime X370-Pro", 0),
220138d9c12cSHans de Goede /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */
22025cb6b5fcSHans de Goede SND_PCI_QUIRK(0x1028, 0x0497, "Dell Precision T3600", 0),
22035cb6b5fcSHans de Goede /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */
220438d9c12cSHans de Goede /* Note the P55A-UD3 and Z87-D3HP share the subsys id for the HDA dev */
220538d9c12cSHans de Goede SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte P55A-UD3 / Z87-D3HP", 0),
22065cb6b5fcSHans de Goede /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */
22075cb6b5fcSHans de Goede SND_PCI_QUIRK(0x8086, 0x2040, "Intel DZ77BH-55K", 0),
2208f91f1806SHans de Goede /* https://bugzilla.kernel.org/show_bug.cgi?id=199607 */
2209f91f1806SHans de Goede SND_PCI_QUIRK(0x8086, 0x2057, "Intel NUC5i7RYB", 0),
2210cae30527SHui Wang /* https://bugs.launchpad.net/bugs/1821663 */
2211cae30527SHui Wang SND_PCI_QUIRK(0x8086, 0x2064, "Intel SDP 8086:2064", 0),
2212dd6dd536SHans de Goede /* https://bugzilla.redhat.com/show_bug.cgi?id=1520902 */
2213dd6dd536SHans de Goede SND_PCI_QUIRK(0x8086, 0x2068, "Intel NUC7i3BNB", 0),
22141ba8f9d3SHans de Goede /* https://bugzilla.kernel.org/show_bug.cgi?id=198611 */
22151ba8f9d3SHans de Goede SND_PCI_QUIRK(0x17aa, 0x2227, "Lenovo X1 Carbon 3rd Gen", 0),
2216057a28efSKailang Yang SND_PCI_QUIRK(0x17aa, 0x316e, "Lenovo ThinkCentre M70q", 0),
2217721f1e6cSJaroslav Kysela /* https://bugzilla.redhat.com/show_bug.cgi?id=1689623 */
2218721f1e6cSJaroslav Kysela SND_PCI_QUIRK(0x17aa, 0x367b, "Lenovo IdeaCentre B550", 0),
2219721f1e6cSJaroslav Kysela /* https://bugzilla.redhat.com/show_bug.cgi?id=1572975 */
2220721f1e6cSJaroslav Kysela SND_PCI_QUIRK(0x17aa, 0x36a7, "Lenovo C50 All in one", 0),
2221cae30527SHui Wang /* https://bugs.launchpad.net/bugs/1821663 */
2222cae30527SHui Wang SND_PCI_QUIRK(0x1631, 0xe017, "Packard Bell NEC IMEDIA 5204", 0),
222395c06d0dSTakashi Iwai /* KONTRON SinglePC may cause a stall at runtime resume */
222495c06d0dSTakashi Iwai SND_PCI_QUIRK(0x1734, 0x1232, "KONTRON SinglePC", 0),
2225*3f63e8feSHoku Ishibe /* Dell ALC3271 */
2226*3f63e8feSHoku Ishibe SND_PCI_QUIRK(0x1028, 0x0962, "Dell ALC3271", 0),
22271ba8f9d3SHans de Goede {}
22281ba8f9d3SHans de Goede };
22291ba8f9d3SHans de Goede #endif /* CONFIG_PM */
22301ba8f9d3SHans de Goede
set_default_power_save(struct azx * chip)223137a3a98eSTakashi Iwai static void set_default_power_save(struct azx *chip)
223237a3a98eSTakashi Iwai {
223337a3a98eSTakashi Iwai int val = power_save;
223437a3a98eSTakashi Iwai
223537a3a98eSTakashi Iwai #ifdef CONFIG_PM
223637a3a98eSTakashi Iwai if (pm_blacklist) {
223737a3a98eSTakashi Iwai const struct snd_pci_quirk *q;
223837a3a98eSTakashi Iwai
22396317e5ebSTakashi Iwai q = snd_pci_quirk_lookup(chip->pci, power_save_denylist);
224037a3a98eSTakashi Iwai if (q && val) {
22416317e5ebSTakashi Iwai dev_info(chip->card->dev, "device %04x:%04x is on the power_save denylist, forcing power_save to 0\n",
224237a3a98eSTakashi Iwai q->subvendor, q->subdevice);
224337a3a98eSTakashi Iwai val = 0;
224437a3a98eSTakashi Iwai }
224537a3a98eSTakashi Iwai }
224637a3a98eSTakashi Iwai #endif /* CONFIG_PM */
224737a3a98eSTakashi Iwai snd_hda_set_power_save(&chip->bus, val * 1000);
224837a3a98eSTakashi Iwai }
224937a3a98eSTakashi Iwai
2250e62a42aeSDylan Reid /* number of codec slots for each chipset: 0 = default slots (i.e. 4) */
2251bf82326fSTakashi Iwai static const unsigned int azx_max_codecs[AZX_NUM_DRIVERS] = {
2252e62a42aeSDylan Reid [AZX_DRIVER_NVIDIA] = 8,
2253e62a42aeSDylan Reid [AZX_DRIVER_TERA] = 1,
2254e62a42aeSDylan Reid };
2255e62a42aeSDylan Reid
azx_probe_continue(struct azx * chip)225648c8b0ebSTakashi Iwai static int azx_probe_continue(struct azx *chip)
2257a82d51edSTakashi Iwai {
22589a34af4aSTakashi Iwai struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
225998d8fc6cSMengdong Lin struct hdac_bus *bus = azx_bus(chip);
2260c67e2228SWang Xingchao struct pci_dev *pci = chip->pci;
2261a82d51edSTakashi Iwai int dev = chip->dev_index;
2262a82d51edSTakashi Iwai int err;
2263a82d51edSTakashi Iwai
2264c0f1886dSTakashi Iwai if (chip->disabled || hda->init_failed)
2265c0f1886dSTakashi Iwai return -EIO;
2266c0f1886dSTakashi Iwai if (hda->probe_retry)
2267c0f1886dSTakashi Iwai goto probe_retry;
2268c0f1886dSTakashi Iwai
2269305a0adeSTakashi Iwai to_hda_bus(bus)->bus_probing = 1;
2270a41d1224STakashi Iwai hda->probe_continued = 1;
2271795614ddSMengdong Lin
2272fcc88d91STakashi Iwai /* bind with i915 if needed */
2273dba9b7b6STakashi Iwai if (chip->driver_caps & AZX_DCAPS_I915_COMPONENT) {
227498d8fc6cSMengdong Lin err = snd_hdac_i915_init(bus);
2275535115b5STakashi Iwai if (err < 0) {
2276535115b5STakashi Iwai /* if the controller is bound only with HDMI/DP
2277535115b5STakashi Iwai * (for HSW and BDW), we need to abort the probe;
2278535115b5STakashi Iwai * for other chips, still continue probing as other
2279535115b5STakashi Iwai * codecs can be on the same link.
2280535115b5STakashi Iwai */
22811b21bd7aSAmadeusz Sławiński if (HDA_CONTROLLER_IN_GPU(pci)) {
2282bed2e98eSTakashi Iwai dev_err(chip->card->dev,
2283bed2e98eSTakashi Iwai "HSW/BDW HD-audio HDMI/DP requires binding with gfx driver\n");
2284535115b5STakashi Iwai goto out_free;
2285fcc88d91STakashi Iwai } else {
2286fcc88d91STakashi Iwai /* don't bother any longer */
2287e454ff8eSTakashi Iwai chip->driver_caps &= ~AZX_DCAPS_I915_COMPONENT;
2288535115b5STakashi Iwai }
2289fcc88d91STakashi Iwai }
2290e454ff8eSTakashi Iwai
2291e454ff8eSTakashi Iwai /* HSW/BDW controllers need this power */
22921b21bd7aSAmadeusz Sławiński if (HDA_CONTROLLER_IN_GPU(pci))
229362c2b4beSJiapeng Zhong hda->need_i915_power = true;
2294fcc88d91STakashi Iwai }
2295fcc88d91STakashi Iwai
2296fcc88d91STakashi Iwai /* Request display power well for the HDA controller or codec. For
2297fcc88d91STakashi Iwai * Haswell/Broadwell, both the display HDA controller and codec need
2298fcc88d91STakashi Iwai * this power. For other platforms, like Baytrail/Braswell, only the
2299fcc88d91STakashi Iwai * display codec needs the power and it can be released after probe.
2300fcc88d91STakashi Iwai */
23014f799e73STakashi Iwai display_power(chip, true);
230299a2008dSWang Xingchao
23035c90680eSTakashi Iwai err = azx_first_init(chip);
23045c90680eSTakashi Iwai if (err < 0)
23055c90680eSTakashi Iwai goto out_free;
23065c90680eSTakashi Iwai
23072dca0bbaSJaroslav Kysela #ifdef CONFIG_SND_HDA_INPUT_BEEP
23082dca0bbaSJaroslav Kysela chip->beep_mode = beep_mode[dev];
23092dca0bbaSJaroslav Kysela #endif
23102dca0bbaSJaroslav Kysela
2311d045bcefSJaroslav Kysela chip->ctl_dev_id = ctl_dev_id;
2312d045bcefSJaroslav Kysela
23131da177e4SLinus Torvalds /* create codec instances */
23149479e75fSTakashi Iwai if (bus->codec_mask) {
231596d2bd6eSTakashi Iwai err = azx_probe_codecs(chip, azx_max_codecs[chip->driver_type]);
231696d2bd6eSTakashi Iwai if (err < 0)
231796d2bd6eSTakashi Iwai goto out_free;
23189479e75fSTakashi Iwai }
231996d2bd6eSTakashi Iwai
23204ea6fbc8STakashi Iwai #ifdef CONFIG_SND_HDA_PATCH_LOADER
23214918cdabSTakashi Iwai if (chip->fw) {
2322a41d1224STakashi Iwai err = snd_hda_load_patch(&chip->bus, chip->fw->size,
23234918cdabSTakashi Iwai chip->fw->data);
23244ea6fbc8STakashi Iwai if (err < 0)
23254ea6fbc8STakashi Iwai goto out_free;
2326e39ae856STakashi Iwai #ifndef CONFIG_PM
23274918cdabSTakashi Iwai release_firmware(chip->fw); /* no longer needed */
23284918cdabSTakashi Iwai chip->fw = NULL;
2329e39ae856STakashi Iwai #endif
23304ea6fbc8STakashi Iwai }
23314ea6fbc8STakashi Iwai #endif
2332c0f1886dSTakashi Iwai
2333c0f1886dSTakashi Iwai probe_retry:
23349479e75fSTakashi Iwai if (bus->codec_mask && !(probe_only[dev] & 1)) {
2335a1e21c90STakashi Iwai err = azx_codec_configure(chip);
2336c0f1886dSTakashi Iwai if (err) {
2337c0f1886dSTakashi Iwai if ((chip->driver_caps & AZX_DCAPS_RETRY_PROBE) &&
2338c0f1886dSTakashi Iwai ++hda->probe_retry < 60) {
2339c0f1886dSTakashi Iwai schedule_delayed_work(&hda->probe_work,
2340c0f1886dSTakashi Iwai msecs_to_jiffies(1000));
2341c0f1886dSTakashi Iwai return 0; /* keep things up */
2342c0f1886dSTakashi Iwai }
2343c0f1886dSTakashi Iwai dev_err(chip->card->dev, "Cannot probe codecs, giving up\n");
2344a1e21c90STakashi Iwai goto out_free;
2345a1e21c90STakashi Iwai }
2346c0f1886dSTakashi Iwai }
23471da177e4SLinus Torvalds
2348a82d51edSTakashi Iwai err = snd_card_register(chip->card);
234941dda0fdSWu Fengguang if (err < 0)
235041dda0fdSWu Fengguang goto out_free;
23511da177e4SLinus Torvalds
235237a3a98eSTakashi Iwai setup_vga_switcheroo_runtime_pm(chip);
235337a3a98eSTakashi Iwai
2354cb53c626STakashi Iwai chip->running = 1;
235565fcd41dSTakashi Iwai azx_add_card_list(chip);
235607f4f97dSLukas Wunner
235737a3a98eSTakashi Iwai set_default_power_save(chip);
23581ba8f9d3SHans de Goede
23593ba21113SRoy Spliet if (azx_has_pm_runtime(chip)) {
23603ba21113SRoy Spliet pm_runtime_use_autosuspend(&pci->dev);
23619fc149c3SKai-Heng Feng pm_runtime_allow(&pci->dev);
236230ff5957SVille Syrjälä pm_runtime_put_autosuspend(&pci->dev);
23633ba21113SRoy Spliet }
23641da177e4SLinus Torvalds
236541dda0fdSWu Fengguang out_free:
23662393e755STakashi Iwai if (err < 0) {
236739173303STakashi Iwai pci_set_drvdata(pci, NULL);
236839173303STakashi Iwai snd_card_free(chip->card);
23692393e755STakashi Iwai return err;
23702393e755STakashi Iwai }
23712393e755STakashi Iwai
23722393e755STakashi Iwai if (!hda->need_i915_power)
2373029d92c2STakashi Iwai display_power(chip, false);
23749a34af4aSTakashi Iwai complete_all(&hda->probe_wait);
2375305a0adeSTakashi Iwai to_hda_bus(bus)->bus_probing = 0;
2376c0f1886dSTakashi Iwai hda->probe_retry = 0;
23772393e755STakashi Iwai return 0;
23781da177e4SLinus Torvalds }
23791da177e4SLinus Torvalds
azx_remove(struct pci_dev * pci)2380e23e7a14SBill Pemberton static void azx_remove(struct pci_dev *pci)
23811da177e4SLinus Torvalds {
23829121947dSTakashi Iwai struct snd_card *card = pci_get_drvdata(pci);
2383991f86d7STakashi Iwai struct azx *chip;
2384991f86d7STakashi Iwai struct hda_intel *hda;
2385b8dfc462SMengdong Lin
2386991f86d7STakashi Iwai if (card) {
23870b8c8219STakashi Iwai /* cancel the pending probing work */
2388991f86d7STakashi Iwai chip = card->private_data;
2389991f86d7STakashi Iwai hda = container_of(chip, struct hda_intel, chip);
2390ab949d51STakashi Iwai /* FIXME: below is an ugly workaround.
2391ab949d51STakashi Iwai * Both device_release_driver() and driver_probe_device()
2392ab949d51STakashi Iwai * take *both* the device's and its parent's lock before
2393ab949d51STakashi Iwai * calling the remove() and probe() callbacks. The codec
2394ab949d51STakashi Iwai * probe takes the locks of both the codec itself and its
2395ab949d51STakashi Iwai * parent, i.e. the PCI controller dev. Meanwhile, when
2396ab949d51STakashi Iwai * the PCI controller is unbound, it takes its lock, too
2397ab949d51STakashi Iwai * ==> ouch, a deadlock!
2398ab949d51STakashi Iwai * As a workaround, we unlock temporarily here the controller
2399ab949d51STakashi Iwai * device during cancel_work_sync() call.
2400ab949d51STakashi Iwai */
2401ab949d51STakashi Iwai device_unlock(&pci->dev);
2402c0f1886dSTakashi Iwai cancel_delayed_work_sync(&hda->probe_work);
2403ab949d51STakashi Iwai device_lock(&pci->dev);
2404991f86d7STakashi Iwai
240569458e2cSTakashi Iwai clear_bit(chip->dev_index, probed_devs);
2406e81478bbSKai Vehmanen pci_set_drvdata(pci, NULL);
24079121947dSTakashi Iwai snd_card_free(card);
24081da177e4SLinus Torvalds }
2409991f86d7STakashi Iwai }
24101da177e4SLinus Torvalds
azx_shutdown(struct pci_dev * pci)2411b2a0bafaSTakashi Iwai static void azx_shutdown(struct pci_dev *pci)
2412b2a0bafaSTakashi Iwai {
2413b2a0bafaSTakashi Iwai struct snd_card *card = pci_get_drvdata(pci);
2414b2a0bafaSTakashi Iwai struct azx *chip;
2415b2a0bafaSTakashi Iwai
2416b2a0bafaSTakashi Iwai if (!card)
2417b2a0bafaSTakashi Iwai return;
2418b2a0bafaSTakashi Iwai chip = card->private_data;
2419b2a0bafaSTakashi Iwai if (chip && chip->running)
24206f445784STakashi Iwai __azx_shutdown_chip(chip, true);
2421b2a0bafaSTakashi Iwai }
2422b2a0bafaSTakashi Iwai
24231da177e4SLinus Torvalds /* PCI IDs */
24246f51f6cfSBenoit Taine static const struct pci_device_id azx_ids[] = {
2425d2f2fcd2SSeth Heasley /* CPT */
2426e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_CPT, AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM) },
2427cea310e8SSeth Heasley /* PBG */
2428e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_PBG, AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM) },
2429d2edeb7cSSeth Heasley /* Panther Point */
2430e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_PPT, AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM) },
24318bc039a1SSeth Heasley /* Lynx Point */
2432e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_LPT, AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH) },
243377f07800STakashi Iwai /* 9 Series */
2434e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_9_SERIES, AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH) },
2435884b088fSJames Ralston /* Wellsburg */
2436e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_WBG_0, AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH) },
2437e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_WBG_1, AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH) },
24385cf92c8bSAlexandra Yates /* Lewisburg */
2439e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_LBG_0, AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE) },
2440e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_LBG_1, AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE) },
2441144dad99SJames Ralston /* Lynx Point-LP */
2442e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_LPT_LP_0, AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH) },
2443144dad99SJames Ralston /* Lynx Point-LP */
2444e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_LPT_LP_1, AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH) },
24454eeca499SJames Ralston /* Wildcat Point-LP */
2446e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_WPT_LP, AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH) },
2447e6232c80SAmadeusz Sławiński /* Skylake (Sunrise Point) */
2448e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_SKL, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
2449e6232c80SAmadeusz Sławiński /* Skylake-LP (Sunrise Point-LP) */
2450e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_SKL_LP, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
245135639a0eSVinod Koul /* Kabylake */
2452e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_KBL, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
245335639a0eSVinod Koul /* Kabylake-LP */
2454e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_KBL_LP, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
24556858107eSVinod Koul /* Kabylake-H */
2456e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_KBL_H, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
2457e79b0006SMegha Dey /* Coffelake */
2458e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_CNL_H, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
24592357f6f0SGuneshwor Singh /* Cannonlake */
2460e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_CNL_LP, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
2461d4c2ccdbSPierre-Louis Bossart /* CometLake-LP */
2462e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_CML_LP, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
2463d4c2ccdbSPierre-Louis Bossart /* CometLake-H */
2464e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_CML_H, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
2465e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_RKL_S, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
2466b73a5854SChiou, Cooper /* CometLake-S */
2467e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_CML_S, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
2468f84d3a1eSKai-Chuan Hsieh /* CometLake-R */
2469e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_CML_R, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
2470491f8331SGuneshwor Singh /* Icelake */
2471e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_ICL_LP, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
2472d50313a5SPierre-Louis Bossart /* Icelake-H */
2473e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_ICL_H, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
24744750c212SPan Xiuli /* Jasperlake */
2475e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_ICL_N, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
2476e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_JSL_N, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
24774750c212SPan Xiuli /* Tigerlake */
2478e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_TGL_LP, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
2479d50313a5SPierre-Louis Bossart /* Tigerlake-H */
2480e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_TGL_H, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
248169b08bdfSKai Vehmanen /* DG1 */
2482e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_DG1, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
2483d85ffff5SKai Vehmanen /* DG2 */
2484e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_DG2_0, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
2485e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_DG2_1, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
2486e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_DG2_2, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
2487d78359b2SKai Vehmanen /* Alderlake-S */
2488e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_ADL_S, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
24895e941fc0SKai Vehmanen /* Alderlake-P */
2490e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_ADL_P, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
2491e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_ADL_PS, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
2492e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_ADL_PX, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
24934ad7935dSKai Vehmanen /* Alderlake-M */
2494e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_ADL_M, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
24954d5a628dSKai Vehmanen /* Alderlake-N */
2496e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_ADL_N, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
2497f94287b6SLai, Poey Seng /* Elkhart Lake */
2498e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_EHL_0, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
2499e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_EHL_3, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
2500a531caa5SKai Vehmanen /* Raptor Lake */
2501e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_RPL_S, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
2502e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_RPL_P_0, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
2503e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_RPL_P_1, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
2504e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_RPL_M, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
2505e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_RPL_PX, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
2506e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_MTL, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
2507714b2f02SFred Oh /* Lunarlake-P */
2508e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_LNL_P, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
25093bef0681SKai Vehmanen /* Arrow Lake-S */
25103bef0681SKai Vehmanen { PCI_DEVICE_DATA(INTEL, HDA_ARL_S, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
25110f04f8d6SPierre-Louis Bossart /* Arrow Lake */
25120f04f8d6SPierre-Louis Bossart { PCI_DEVICE_DATA(INTEL, HDA_ARL, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
2513e6232c80SAmadeusz Sławiński /* Apollolake (Broxton-P) */
2514e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_APL, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_BROXTON) },
251544b46d73SVinod Koul /* Gemini-Lake */
2516e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_GML, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_BROXTON) },
2517e926f2c8SWang Xingchao /* Haswell */
2518e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_HSW_0, AZX_DRIVER_HDMI | AZX_DCAPS_INTEL_HASWELL) },
2519e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_HSW_2, AZX_DRIVER_HDMI | AZX_DCAPS_INTEL_HASWELL) },
2520e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_HSW_3, AZX_DRIVER_HDMI | AZX_DCAPS_INTEL_HASWELL) },
2521862d7618SMengdong Lin /* Broadwell */
2522e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_BDW, AZX_DRIVER_HDMI | AZX_DCAPS_INTEL_BROADWELL) },
252399df18b3SPierre-Louis Bossart /* 5 Series/3400 */
2524e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_5_3400_SERIES_0, AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_NOPM) },
2525e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_5_3400_SERIES_1, AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_NOPM) },
2526f748abccSTakashi Iwai /* Poulsbo */
2527e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_POULSBO, AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_BASE |
2528e6232c80SAmadeusz Sławiński AZX_DCAPS_POSFIX_LPIB) },
2529f748abccSTakashi Iwai /* Oaktrail */
2530e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_OAKTRAIL, AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_BASE) },
2531e44007e0SChew, Chiau Ee /* BayTrail */
2532e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_BYT, AZX_DRIVER_PCH | AZX_DCAPS_INTEL_BAYTRAIL) },
2533f31b2ffcSLibin Yang /* Braswell */
2534e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_BSW, AZX_DRIVER_PCH | AZX_DCAPS_INTEL_BRASWELL) },
2535b42b4afbSTakashi Iwai /* ICH6 */
2536e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_ICH6, AZX_DRIVER_ICH | AZX_DCAPS_INTEL_ICH) },
2537b42b4afbSTakashi Iwai /* ICH7 */
2538e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_ICH7, AZX_DRIVER_ICH | AZX_DCAPS_INTEL_ICH) },
2539b42b4afbSTakashi Iwai /* ESB2 */
2540e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_ESB2, AZX_DRIVER_ICH | AZX_DCAPS_INTEL_ICH) },
2541b42b4afbSTakashi Iwai /* ICH8 */
2542e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_ICH8, AZX_DRIVER_ICH | AZX_DCAPS_INTEL_ICH) },
2543b42b4afbSTakashi Iwai /* ICH9 */
2544e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_ICH9_0, AZX_DRIVER_ICH | AZX_DCAPS_INTEL_ICH) },
2545b42b4afbSTakashi Iwai /* ICH9 */
2546e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_ICH9_1, AZX_DRIVER_ICH | AZX_DCAPS_INTEL_ICH) },
2547b42b4afbSTakashi Iwai /* ICH10 */
2548e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_ICH10_0, AZX_DRIVER_ICH | AZX_DCAPS_INTEL_ICH) },
2549b42b4afbSTakashi Iwai /* ICH10 */
2550e6232c80SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_ICH10_1, AZX_DRIVER_ICH | AZX_DCAPS_INTEL_ICH) },
2551b6864535STakashi Iwai /* Generic Intel */
2552b6864535STakashi Iwai { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_ANY_ID),
2553b6864535STakashi Iwai .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
2554b6864535STakashi Iwai .class_mask = 0xffffff,
2555103884a3STakashi Iwai .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_NO_ALIGN_BUFSIZE },
25569477c58eSTakashi Iwai /* ATI SB 450/600/700/800/900 */
2557e6232c80SAmadeusz Sławiński { PCI_VDEVICE(ATI, 0x437b),
25589477c58eSTakashi Iwai .driver_data = AZX_DRIVER_ATI | AZX_DCAPS_PRESET_ATI_SB },
2559e6232c80SAmadeusz Sławiński { PCI_VDEVICE(ATI, 0x4383),
25609477c58eSTakashi Iwai .driver_data = AZX_DRIVER_ATI | AZX_DCAPS_PRESET_ATI_SB },
25619477c58eSTakashi Iwai /* AMD Hudson */
2562e6232c80SAmadeusz Sławiński { PCI_VDEVICE(AMD, 0x780d),
25639477c58eSTakashi Iwai .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_SB },
2564c02f77d3STakashi Iwai /* AMD, X370 & co */
2565e6232c80SAmadeusz Sławiński { PCI_VDEVICE(AMD, 0x1457),
2566c02f77d3STakashi Iwai .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_AMD_SB },
2567de768ce4STakashi Iwai /* AMD, X570 & co */
2568e6232c80SAmadeusz Sławiński { PCI_VDEVICE(AMD, 0x1487),
2569de768ce4STakashi Iwai .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_AMD_SB },
25703deef52cSKai-Heng Feng /* AMD Stoney */
2571e6232c80SAmadeusz Sławiński { PCI_VDEVICE(AMD, 0x157a),
25723deef52cSKai-Heng Feng .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_SB |
25733deef52cSKai-Heng Feng AZX_DCAPS_PM_RUNTIME },
25749ceace3cSVijendar Mukunda /* AMD Raven */
2575e6232c80SAmadeusz Sławiński { PCI_VDEVICE(AMD, 0x15e3),
2576d2c63b7dSTakashi Iwai .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_AMD_SB },
257787218e9cSTakashi Iwai /* ATI HDMI */
2578e6232c80SAmadeusz Sławiński { PCI_VDEVICE(ATI, 0x0002),
257920c7842eSAlex Deucher .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
258020c7842eSAlex Deucher AZX_DCAPS_PM_RUNTIME },
2581e6232c80SAmadeusz Sławiński { PCI_VDEVICE(ATI, 0x1308),
2582650474fbSAlex Deucher .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
2583e6232c80SAmadeusz Sławiński { PCI_VDEVICE(ATI, 0x157a),
25845022813dSMaruthi Srinivas Bayyavarapu .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
2585e6232c80SAmadeusz Sławiński { PCI_VDEVICE(ATI, 0x15b3),
2586d716fb03SAwais Belal .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
2587e6232c80SAmadeusz Sławiński { PCI_VDEVICE(ATI, 0x793b),
25889477c58eSTakashi Iwai .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
2589e6232c80SAmadeusz Sławiński { PCI_VDEVICE(ATI, 0x7919),
25909477c58eSTakashi Iwai .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
2591e6232c80SAmadeusz Sławiński { PCI_VDEVICE(ATI, 0x960f),
25929477c58eSTakashi Iwai .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
2593e6232c80SAmadeusz Sławiński { PCI_VDEVICE(ATI, 0x970f),
25949477c58eSTakashi Iwai .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
2595e6232c80SAmadeusz Sławiński { PCI_VDEVICE(ATI, 0x9840),
2596650474fbSAlex Deucher .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
2597e6232c80SAmadeusz Sławiński { PCI_VDEVICE(ATI, 0xaa00),
25989477c58eSTakashi Iwai .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
2599e6232c80SAmadeusz Sławiński { PCI_VDEVICE(ATI, 0xaa08),
26009477c58eSTakashi Iwai .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
2601e6232c80SAmadeusz Sławiński { PCI_VDEVICE(ATI, 0xaa10),
26029477c58eSTakashi Iwai .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
2603e6232c80SAmadeusz Sławiński { PCI_VDEVICE(ATI, 0xaa18),
26049477c58eSTakashi Iwai .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
2605e6232c80SAmadeusz Sławiński { PCI_VDEVICE(ATI, 0xaa20),
26069477c58eSTakashi Iwai .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
2607e6232c80SAmadeusz Sławiński { PCI_VDEVICE(ATI, 0xaa28),
26089477c58eSTakashi Iwai .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
2609e6232c80SAmadeusz Sławiński { PCI_VDEVICE(ATI, 0xaa30),
26109477c58eSTakashi Iwai .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
2611e6232c80SAmadeusz Sławiński { PCI_VDEVICE(ATI, 0xaa38),
26129477c58eSTakashi Iwai .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
2613e6232c80SAmadeusz Sławiński { PCI_VDEVICE(ATI, 0xaa40),
26149477c58eSTakashi Iwai .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
2615e6232c80SAmadeusz Sławiński { PCI_VDEVICE(ATI, 0xaa48),
26169477c58eSTakashi Iwai .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
2617e6232c80SAmadeusz Sławiński { PCI_VDEVICE(ATI, 0xaa50),
2618bbaa0d66SClemens Ladisch .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
2619e6232c80SAmadeusz Sławiński { PCI_VDEVICE(ATI, 0xaa58),
2620bbaa0d66SClemens Ladisch .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
2621e6232c80SAmadeusz Sławiński { PCI_VDEVICE(ATI, 0xaa60),
2622bbaa0d66SClemens Ladisch .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
2623e6232c80SAmadeusz Sławiński { PCI_VDEVICE(ATI, 0xaa68),
2624bbaa0d66SClemens Ladisch .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
2625e6232c80SAmadeusz Sławiński { PCI_VDEVICE(ATI, 0xaa80),
2626bbaa0d66SClemens Ladisch .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
2627e6232c80SAmadeusz Sławiński { PCI_VDEVICE(ATI, 0xaa88),
2628bbaa0d66SClemens Ladisch .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
2629e6232c80SAmadeusz Sławiński { PCI_VDEVICE(ATI, 0xaa90),
2630bbaa0d66SClemens Ladisch .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
2631e6232c80SAmadeusz Sławiński { PCI_VDEVICE(ATI, 0xaa98),
2632bbaa0d66SClemens Ladisch .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
2633e6232c80SAmadeusz Sławiński { PCI_VDEVICE(ATI, 0x9902),
263437e661eeSTakashi Iwai .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
2635e6232c80SAmadeusz Sławiński { PCI_VDEVICE(ATI, 0xaaa0),
263637e661eeSTakashi Iwai .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
2637e6232c80SAmadeusz Sławiński { PCI_VDEVICE(ATI, 0xaaa8),
263837e661eeSTakashi Iwai .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
2639e6232c80SAmadeusz Sławiński { PCI_VDEVICE(ATI, 0xaab0),
264037e661eeSTakashi Iwai .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
2641e6232c80SAmadeusz Sławiński { PCI_VDEVICE(ATI, 0xaac0),
264220c7842eSAlex Deucher .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
264320c7842eSAlex Deucher AZX_DCAPS_PM_RUNTIME },
2644e6232c80SAmadeusz Sławiński { PCI_VDEVICE(ATI, 0xaac8),
264520c7842eSAlex Deucher .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
264620c7842eSAlex Deucher AZX_DCAPS_PM_RUNTIME },
2647e6232c80SAmadeusz Sławiński { PCI_VDEVICE(ATI, 0xaad8),
264873b1422bSAlex Deucher .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
264973b1422bSAlex Deucher AZX_DCAPS_PM_RUNTIME },
2650e6232c80SAmadeusz Sławiński { PCI_VDEVICE(ATI, 0xaae0),
265173b1422bSAlex Deucher .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
265273b1422bSAlex Deucher AZX_DCAPS_PM_RUNTIME },
2653e6232c80SAmadeusz Sławiński { PCI_VDEVICE(ATI, 0xaae8),
265473b1422bSAlex Deucher .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
265573b1422bSAlex Deucher AZX_DCAPS_PM_RUNTIME },
2656e6232c80SAmadeusz Sławiński { PCI_VDEVICE(ATI, 0xaaf0),
265773b1422bSAlex Deucher .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
265873b1422bSAlex Deucher AZX_DCAPS_PM_RUNTIME },
2659e6232c80SAmadeusz Sławiński { PCI_VDEVICE(ATI, 0xaaf8),
266073b1422bSAlex Deucher .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
266173b1422bSAlex Deucher AZX_DCAPS_PM_RUNTIME },
2662e6232c80SAmadeusz Sławiński { PCI_VDEVICE(ATI, 0xab00),
266373b1422bSAlex Deucher .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
266473b1422bSAlex Deucher AZX_DCAPS_PM_RUNTIME },
2665e6232c80SAmadeusz Sławiński { PCI_VDEVICE(ATI, 0xab08),
266673b1422bSAlex Deucher .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
266773b1422bSAlex Deucher AZX_DCAPS_PM_RUNTIME },
2668e6232c80SAmadeusz Sławiński { PCI_VDEVICE(ATI, 0xab10),
266973b1422bSAlex Deucher .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
267073b1422bSAlex Deucher AZX_DCAPS_PM_RUNTIME },
2671e6232c80SAmadeusz Sławiński { PCI_VDEVICE(ATI, 0xab18),
267273b1422bSAlex Deucher .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
267373b1422bSAlex Deucher AZX_DCAPS_PM_RUNTIME },
2674e6232c80SAmadeusz Sławiński { PCI_VDEVICE(ATI, 0xab20),
267573b1422bSAlex Deucher .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
267673b1422bSAlex Deucher AZX_DCAPS_PM_RUNTIME },
2677e6232c80SAmadeusz Sławiński { PCI_VDEVICE(ATI, 0xab28),
267827a7c670SHersen Wu .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
267927a7c670SHersen Wu AZX_DCAPS_PM_RUNTIME },
2680e6232c80SAmadeusz Sławiński { PCI_VDEVICE(ATI, 0xab30),
2681fdcc4c22SEvan Quan .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
2682fdcc4c22SEvan Quan AZX_DCAPS_PM_RUNTIME },
2683e6232c80SAmadeusz Sławiński { PCI_VDEVICE(ATI, 0xab38),
268473b1422bSAlex Deucher .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
268573b1422bSAlex Deucher AZX_DCAPS_PM_RUNTIME },
2686c51e4310Sjasontao /* GLENFLY */
2687bd9a77a9SWangYuli { PCI_DEVICE(PCI_VENDOR_ID_GLENFLY, PCI_ANY_ID),
2688c51e4310Sjasontao .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
2689c51e4310Sjasontao .class_mask = 0xffffff,
2690c51e4310Sjasontao .driver_data = AZX_DRIVER_GFHDMI | AZX_DCAPS_POSFIX_LPIB |
2691c51e4310Sjasontao AZX_DCAPS_NO_MSI | AZX_DCAPS_NO_64BIT },
269287218e9cSTakashi Iwai /* VIA VT8251/VT8237A */
2693e6232c80SAmadeusz Sławiński { PCI_VDEVICE(VIA, 0x3288), .driver_data = AZX_DRIVER_VIA },
2694754fdff8SAnnie Liu /* VIA GFX VT7122/VX900 */
2695e6232c80SAmadeusz Sławiński { PCI_VDEVICE(VIA, 0x9170), .driver_data = AZX_DRIVER_GENERIC },
2696754fdff8SAnnie Liu /* VIA GFX VT6122/VX11 */
2697e6232c80SAmadeusz Sławiński { PCI_VDEVICE(VIA, 0x9140), .driver_data = AZX_DRIVER_GENERIC },
269887218e9cSTakashi Iwai /* SIS966 */
2699e6232c80SAmadeusz Sławiński { PCI_VDEVICE(SI, 0x7502), .driver_data = AZX_DRIVER_SIS },
270087218e9cSTakashi Iwai /* ULI M5461 */
2701e6232c80SAmadeusz Sławiński { PCI_VDEVICE(AL, 0x5461), .driver_data = AZX_DRIVER_ULI },
270287218e9cSTakashi Iwai /* NVIDIA MCP */
27030c2fd1bfSTakashi Iwai { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID),
27040c2fd1bfSTakashi Iwai .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
27050c2fd1bfSTakashi Iwai .class_mask = 0xffffff,
27069477c58eSTakashi Iwai .driver_data = AZX_DRIVER_NVIDIA | AZX_DCAPS_PRESET_NVIDIA },
2707f269002eSKailang Yang /* Teradici */
27089477c58eSTakashi Iwai { PCI_DEVICE(0x6549, 0x1200),
27099477c58eSTakashi Iwai .driver_data = AZX_DRIVER_TERA | AZX_DCAPS_NO_64BIT },
2710f0b3da98SLars R. Damerow { PCI_DEVICE(0x6549, 0x2200),
2711f0b3da98SLars R. Damerow .driver_data = AZX_DRIVER_TERA | AZX_DCAPS_NO_64BIT },
27124e01f54bSTakashi Iwai /* Creative X-Fi (CA0110-IBG) */
2713f2a8ecafSTakashi Iwai /* CTHDA chips */
2714e6232c80SAmadeusz Sławiński { PCI_VDEVICE(CREATIVE, 0x0010),
2715f2a8ecafSTakashi Iwai .driver_data = AZX_DRIVER_CTHDA | AZX_DCAPS_PRESET_CTHDA },
2716e6232c80SAmadeusz Sławiński { PCI_VDEVICE(CREATIVE, 0x0012),
2717f2a8ecafSTakashi Iwai .driver_data = AZX_DRIVER_CTHDA | AZX_DCAPS_PRESET_CTHDA },
27188eeaa2f9STakashi Iwai #if !IS_ENABLED(CONFIG_SND_CTXFI)
2719313f6e2dSTakashi Iwai /* the following entry conflicts with snd-ctxfi driver,
2720313f6e2dSTakashi Iwai * as ctxfi driver mutates from HD-audio to native mode with
2721313f6e2dSTakashi Iwai * a special command sequence.
2722313f6e2dSTakashi Iwai */
27234e01f54bSTakashi Iwai { PCI_DEVICE(PCI_VENDOR_ID_CREATIVE, PCI_ANY_ID),
27244e01f54bSTakashi Iwai .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
27254e01f54bSTakashi Iwai .class_mask = 0xffffff,
27269477c58eSTakashi Iwai .driver_data = AZX_DRIVER_CTX | AZX_DCAPS_CTX_WORKAROUND |
2727ef85f299STakashi Iwai AZX_DCAPS_NO_64BIT | AZX_DCAPS_POSFIX_LPIB },
2728313f6e2dSTakashi Iwai #else
2729313f6e2dSTakashi Iwai /* this entry seems still valid -- i.e. without emu20kx chip */
2730e6232c80SAmadeusz Sławiński { PCI_VDEVICE(CREATIVE, 0x0009),
27319477c58eSTakashi Iwai .driver_data = AZX_DRIVER_CTX | AZX_DCAPS_CTX_WORKAROUND |
2732ef85f299STakashi Iwai AZX_DCAPS_NO_64BIT | AZX_DCAPS_POSFIX_LPIB },
2733313f6e2dSTakashi Iwai #endif
2734c563f473STakashi Iwai /* CM8888 */
2735e6232c80SAmadeusz Sławiński { PCI_VDEVICE(CMEDIA, 0x5011),
2736c563f473STakashi Iwai .driver_data = AZX_DRIVER_CMEDIA |
273737e661eeSTakashi Iwai AZX_DCAPS_NO_MSI | AZX_DCAPS_POSFIX_LPIB | AZX_DCAPS_SNOOP_OFF },
2738e35d4b11SOtavio Salvador /* Vortex86MX */
2739e6232c80SAmadeusz Sławiński { PCI_VDEVICE(RDC, 0x3010), .driver_data = AZX_DRIVER_GENERIC },
27400f0714c5SBankim Bhavsar /* VMware HDAudio */
2741e6232c80SAmadeusz Sławiński { PCI_VDEVICE(VMWARE, 0x1977), .driver_data = AZX_DRIVER_GENERIC },
27429176b672SAndiry Brienza /* AMD/ATI Generic, PCI class code and Vendor ID for HD Audio */
2743c4da29caSYang, Libin { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_ANY_ID),
2744c4da29caSYang, Libin .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
2745c4da29caSYang, Libin .class_mask = 0xffffff,
27469477c58eSTakashi Iwai .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_HDMI },
27479176b672SAndiry Brienza { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_ANY_ID),
27489176b672SAndiry Brienza .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
27499176b672SAndiry Brienza .class_mask = 0xffffff,
27509477c58eSTakashi Iwai .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_HDMI },
2751b6fcab14STony W Wang-oc /* Zhaoxin */
2752e6232c80SAmadeusz Sławiński { PCI_VDEVICE(ZHAOXIN, 0x3288), .driver_data = AZX_DRIVER_ZHAOXIN },
275328bd137aSYanteng Si /* Loongson HDAudio*/
2754e6232c80SAmadeusz Sławiński { PCI_VDEVICE(LOONGSON, PCI_DEVICE_ID_LOONGSON_HDA),
275528bd137aSYanteng Si .driver_data = AZX_DRIVER_LOONGSON },
2756e6232c80SAmadeusz Sławiński { PCI_VDEVICE(LOONGSON, PCI_DEVICE_ID_LOONGSON_HDMI),
275728bd137aSYanteng Si .driver_data = AZX_DRIVER_LOONGSON },
27581da177e4SLinus Torvalds { 0, }
27591da177e4SLinus Torvalds };
27601da177e4SLinus Torvalds MODULE_DEVICE_TABLE(pci, azx_ids);
27611da177e4SLinus Torvalds
27621da177e4SLinus Torvalds /* pci_driver definition */
2763e9f66d9bSTakashi Iwai static struct pci_driver azx_driver = {
27643733e424STakashi Iwai .name = KBUILD_MODNAME,
27651da177e4SLinus Torvalds .id_table = azx_ids,
27661da177e4SLinus Torvalds .probe = azx_probe,
2767e23e7a14SBill Pemberton .remove = azx_remove,
2768b2a0bafaSTakashi Iwai .shutdown = azx_shutdown,
276968cb2b55STakashi Iwai .driver = {
277068cb2b55STakashi Iwai .pm = AZX_PM_OPS,
277168cb2b55STakashi Iwai },
27721da177e4SLinus Torvalds };
27731da177e4SLinus Torvalds
2774e9f66d9bSTakashi Iwai module_pci_driver(azx_driver);
2775