Newer
Older
dev_info(chip->card->dev, "%s via VGA-switcheroo\n",
disabled ? "Disabling" : "Enabling");
pm_runtime_put_sync_suspend(card->dev);
azx_suspend(card->dev);
/* when we get suspended by vga switcheroo we end up in D3cold,
* however we have no ACPI handle, so pci/acpi can't put us there,
* put ourselves there */
pci->current_state = PCI_D3cold;
if (snd_hda_lock_devices(chip->bus))
dev_warn(chip->card->dev,
"Cannot lock devices!\n");
} else {
snd_hda_unlock_devices(chip->bus);
pm_runtime_get_noresume(card->dev);
azx_resume(card->dev);
}
}
}
static bool azx_vs_can_switch(struct pci_dev *pci)
{
struct snd_card *card = pci_get_drvdata(pci);
struct azx *chip = card->private_data;
struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
wait_for_completion(&hda->probe_wait);
if (hda->init_failed)
return false;
if (chip->disabled || !chip->bus)
return true;
if (snd_hda_lock_devices(chip->bus))
return false;
snd_hda_unlock_devices(chip->bus);
return true;
}
static void init_vga_switcheroo(struct azx *chip)
struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
struct pci_dev *p = get_bound_vga(chip->pci);
if (p) {
dev_info(chip->card->dev,
"Handle VGA-switcheroo audio client\n");
hda->use_vga_switcheroo = 1;
pci_dev_put(p);
}
}
static const struct vga_switcheroo_client_ops azx_vs_ops = {
.set_gpu_state = azx_vs_set_state,
.can_switch = azx_vs_can_switch,
};
static int register_vga_switcheroo(struct azx *chip)
struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
if (!hda->use_vga_switcheroo)
return 0;
/* FIXME: currently only handling DIS controller
* is there any machine with two switchable HDMI audio controllers?
*/
err = vga_switcheroo_register_audio_client(chip->pci, &azx_vs_ops,
VGA_SWITCHEROO_DIS,
chip->bus != NULL);
if (err < 0)
return err;
hda->vga_switcheroo_registered = 1;
/* register as an optimus hdmi audio power domain */
vga_switcheroo_init_domain_pm_optimus_hdmi_audio(chip->card->dev,
&hda->hdmi_pm_domain);
}
#else
#define init_vga_switcheroo(chip) /* NOP */
#define register_vga_switcheroo(chip) 0
#define check_hdmi_disabled(pci) false
#endif /* SUPPORT_VGA_SWITCHER */
static int azx_free(struct azx *chip)
struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
if ((chip->driver_caps & AZX_DCAPS_PM_RUNTIME)
&& chip->running)
pm_runtime_get_noresume(&pci->dev);
azx_del_card_list(chip);
hda->init_failed = 1; /* to be sure */
complete_all(&hda->probe_wait);
if (use_vga_switcheroo(hda)) {
if (chip->disabled && chip->bus)
snd_hda_unlock_devices(chip->bus);
if (hda->vga_switcheroo_registered)
vga_switcheroo_unregister_client(chip->pci);
for (i = 0; i < chip->num_streams; i++)
pci_disable_msi(chip->pci);
if (chip->remap_addr)
iounmap(chip->remap_addr);
azx_free_stream_pages(chip);
if (chip->region_requested)
pci_release_regions(chip->pci);
#ifdef CONFIG_SND_HDA_PATCH_LOADER
if (chip->fw)
release_firmware(chip->fw);
#endif
if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) {
hda_display_power(false);
hda_i915_exit();
}
kfree(hda);
static int azx_dev_free(struct snd_device *device)
{
return azx_free(device->device_data);
}
#ifdef SUPPORT_VGA_SWITCHEROO
/*
* Check of disabled HDMI controller by vga-switcheroo
*/
static struct pci_dev *get_bound_vga(struct pci_dev *pci)
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
{
struct pci_dev *p;
/* check only discrete GPU */
switch (pci->vendor) {
case PCI_VENDOR_ID_ATI:
case PCI_VENDOR_ID_AMD:
case PCI_VENDOR_ID_NVIDIA:
if (pci->devfn == 1) {
p = pci_get_domain_bus_and_slot(pci_domain_nr(pci->bus),
pci->bus->number, 0);
if (p) {
if ((p->class >> 8) == PCI_CLASS_DISPLAY_VGA)
return p;
pci_dev_put(p);
}
}
break;
}
return NULL;
}
static bool check_hdmi_disabled(struct pci_dev *pci)
{
bool vga_inactive = false;
struct pci_dev *p = get_bound_vga(pci);
if (p) {
if (vga_switcheroo_get_client_state(p) == VGA_SWITCHEROO_OFF)
vga_inactive = true;
pci_dev_put(p);
}
return vga_inactive;
}
#endif /* SUPPORT_VGA_SWITCHEROO */
/*
* white/black-listing for position_fix
*/
static struct snd_pci_quirk position_fix_list[] = {
SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_LPIB),
SND_PCI_QUIRK(0x103c, 0x306d, "HP dv3", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS M2V", POS_FIX_LPIB),
SND_PCI_QUIRK(0x104d, 0x9069, "Sony VPCS11V9E", POS_FIX_LPIB),
SND_PCI_QUIRK(0x10de, 0xcb89, "Macbook Pro 7,1", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1297, 0x3166, "Shuttle", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1458, 0xa022, "ga-ma770-ud3", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1462, 0x1002, "MSI Wind U115", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1565, 0x8218, "Biostar Microtech", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1849, 0x0888, "775Dual-VSTA", POS_FIX_LPIB),
SND_PCI_QUIRK(0x8086, 0x2503, "DG965OT AAD63733-203", POS_FIX_LPIB),
{}
};
static int check_position_fix(struct azx *chip, int fix)
{
const struct snd_pci_quirk *q;
switch (fix) {
case POS_FIX_LPIB:
case POS_FIX_POSBUF:
case POS_FIX_VIACOMBO:
return fix;
}
q = snd_pci_quirk_lookup(chip->pci, position_fix_list);
if (q) {
dev_info(chip->card->dev,
"position_fix set to %d for device %04x:%04x\n",
q->value, q->subvendor, q->subdevice);
return q->value;
David Henningsson
committed
/* Check VIA/ATI HD Audio Controller exist */
if (chip->driver_caps & AZX_DCAPS_POSFIX_VIA) {
dev_dbg(chip->card->dev, "Using VIACOMBO position fix\n");
David Henningsson
committed
return POS_FIX_VIACOMBO;
}
if (chip->driver_caps & AZX_DCAPS_POSFIX_LPIB) {
dev_dbg(chip->card->dev, "Using LPIB position fix\n");
return POS_FIX_LPIB;
David Henningsson
committed
}
return POS_FIX_AUTO;
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
static void assign_position_fix(struct azx *chip, int fix)
{
static azx_get_pos_callback_t callbacks[] = {
[POS_FIX_AUTO] = NULL,
[POS_FIX_LPIB] = azx_get_pos_lpib,
[POS_FIX_POSBUF] = azx_get_pos_posbuf,
[POS_FIX_VIACOMBO] = azx_via_get_position,
[POS_FIX_COMBO] = azx_get_pos_lpib,
};
chip->get_position[0] = chip->get_position[1] = callbacks[fix];
/* combo mode uses LPIB only for playback */
if (fix == POS_FIX_COMBO)
chip->get_position[1] = NULL;
if (fix == POS_FIX_POSBUF &&
(chip->driver_caps & AZX_DCAPS_COUNT_LPIB_DELAY)) {
chip->get_delay[0] = chip->get_delay[1] =
azx_get_delay_from_lpib;
}
}
/*
* black-lists for probe_mask
*/
static struct snd_pci_quirk probe_mask_list[] = {
/* Thinkpad often breaks the controller communication when accessing
* to the non-working (or non-existing) modem codec slot.
*/
SND_PCI_QUIRK(0x1014, 0x05b7, "Thinkpad Z60", 0x01),
SND_PCI_QUIRK(0x17aa, 0x2010, "Thinkpad X/T/R60", 0x01),
SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X/T/R61", 0x01),
/* broken BIOS */
SND_PCI_QUIRK(0x1028, 0x20ac, "Dell Studio Desktop", 0x01),
/* including bogus ALC268 in slot#2 that conflicts with ALC888 */
SND_PCI_QUIRK(0x17c0, 0x4085, "Medion MD96630", 0x01),
/* forced codec slots */
SND_PCI_QUIRK(0x1043, 0x1262, "ASUS W5Fm", 0x103),
SND_PCI_QUIRK(0x1046, 0x1262, "ASUS W5F", 0x103),
/* WinFast VP200 H (Teradici) user reported broken communication */
SND_PCI_QUIRK(0x3a21, 0x040d, "WinFast VP200 H", 0x101),
#define AZX_FORCE_CODEC_MASK 0x100
static void check_probe_mask(struct azx *chip, int dev)
{
const struct snd_pci_quirk *q;
chip->codec_probe_mask = probe_mask[dev];
if (chip->codec_probe_mask == -1) {
q = snd_pci_quirk_lookup(chip->pci, probe_mask_list);
if (q) {
dev_info(chip->card->dev,
"probe_mask set to 0x%x for device %04x:%04x\n",
q->value, q->subvendor, q->subdevice);
chip->codec_probe_mask = q->value;
/* check forced option */
if (chip->codec_probe_mask != -1 &&
(chip->codec_probe_mask & AZX_FORCE_CODEC_MASK)) {
chip->codec_mask = chip->codec_probe_mask & 0xff;
dev_info(chip->card->dev, "codec_mask forced to 0x%x\n",
chip->codec_mask);
static struct snd_pci_quirk msi_black_list[] = {
SND_PCI_QUIRK(0x103c, 0x2191, "HP", 0), /* AMD Hudson */
SND_PCI_QUIRK(0x103c, 0x2192, "HP", 0), /* AMD Hudson */
SND_PCI_QUIRK(0x103c, 0x21f7, "HP", 0), /* AMD Hudson */
SND_PCI_QUIRK(0x103c, 0x21fa, "HP", 0), /* AMD Hudson */
SND_PCI_QUIRK(0x1043, 0x81f2, "ASUS", 0), /* Athlon64 X2 + nvidia */
SND_PCI_QUIRK(0x1043, 0x81f6, "ASUS", 0), /* nvidia */
SND_PCI_QUIRK(0x1043, 0x822d, "ASUS", 0), /* Athlon64 X2 + nvidia MCP55 */
SND_PCI_QUIRK(0x1179, 0xfb44, "Toshiba Satellite C870", 0), /* AMD Hudson */
SND_PCI_QUIRK(0x1849, 0x0888, "ASRock", 0), /* Athlon64 X2 + nvidia */
SND_PCI_QUIRK(0xa0a0, 0x0575, "Aopen MZ915-M", 0), /* ICH6 */
static void check_msi(struct azx *chip)
{
const struct snd_pci_quirk *q;
if (enable_msi >= 0) {
chip->msi = !!enable_msi;
}
chip->msi = 1; /* enable MSI as default */
q = snd_pci_quirk_lookup(chip->pci, msi_black_list);
dev_info(chip->card->dev,
"msi for device %04x:%04x set to %d\n",
q->subvendor, q->subdevice, q->value);
return;
}
/* NVidia chipsets seem to cause troubles with MSI */
if (chip->driver_caps & AZX_DCAPS_NO_MSI) {
dev_info(chip->card->dev, "Disabling MSI\n");
/* check the snoop mode availability */
static void azx_check_snoop_available(struct azx *chip)
{
bool snoop = chip->snoop;
switch (chip->driver_type) {
case AZX_DRIVER_VIA:
/* force to non-snoop mode for a new VIA controller
* when BIOS is set
*/
if (snoop) {
u8 val;
pci_read_config_byte(chip->pci, 0x42, &val);
if (!(val & 0x80) && chip->pci->revision == 0x30)
snoop = false;
}
break;
case AZX_DRIVER_ATIHDMI_NS:
/* new ATI HDMI requires non-snoop */
snoop = false;
break;
case AZX_DRIVER_CTHDA:
case AZX_DRIVER_CMEDIA:
snoop = false;
break;
}
if (snoop != chip->snoop) {
dev_info(chip->card->dev, "Force to %s mode\n",
snoop ? "snoop" : "non-snoop");
chip->snoop = snoop;
}
}
static void azx_probe_work(struct work_struct *work)
{
struct hda_intel *hda = container_of(work, struct hda_intel, probe_work);
azx_probe_continue(&hda->chip);
static int azx_create(struct snd_card *card, struct pci_dev *pci,
int dev, unsigned int driver_caps,
const struct hda_controller_ops *hda_ops,
static struct snd_device_ops ops = {
struct hda_intel *hda;
err = pci_enable_device(pci);
if (err < 0)
hda = kzalloc(sizeof(*hda), GFP_KERNEL);
if (!hda) {
dev_err(card->dev, "Cannot allocate hda\n");
pci_disable_device(pci);
return -ENOMEM;
}
chip = &hda->chip;
chip->ops = hda_ops;
chip->driver_caps = driver_caps;
chip->driver_type = driver_caps & 0xff;
chip->jackpoll_ms = jackpoll_ms;
INIT_LIST_HEAD(&chip->pcm_list);
INIT_WORK(&hda->irq_pending_work, azx_irq_pending_work);
INIT_LIST_HEAD(&hda->list);
init_completion(&hda->probe_wait);
assign_position_fix(chip, check_position_fix(chip, position_fix[dev]));
check_probe_mask(chip, dev);
chip->single_cmd = single_cmd;
azx_check_snoop_available(chip);
if (bdl_pos_adj[dev] < 0) {
switch (chip->driver_type) {
break;
default:
break;
}
}
chip->bdl_pos_adj = bdl_pos_adj;
err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
if (err < 0) {
dev_err(card->dev, "Error creating device [card]!\n");
azx_free(chip);
return err;
}
/* continue probing in work context as may trigger request module */
INIT_WORK(&hda->probe_work, azx_probe_work);
static int azx_first_init(struct azx *chip)
{
int dev = chip->dev_index;
struct pci_dev *pci = chip->pci;
struct snd_card *card = chip->card;
unsigned int dma_bits = 64;
#if BITS_PER_LONG != 64
/* Fix up base address on ULI M5461 */
if (chip->driver_type == AZX_DRIVER_ULI) {
u16 tmp3;
pci_read_config_word(pci, 0x40, &tmp3);
pci_write_config_word(pci, 0x40, tmp3 | 0x10);
pci_write_config_dword(pci, PCI_BASE_ADDRESS_1, 0);
}
#endif
err = pci_request_regions(pci, "ICH HD audio");
chip->addr = pci_resource_start(pci, 0);
chip->remap_addr = pci_ioremap_bar(pci, 0);
dev_err(card->dev, "ioremap error\n");
if (chip->msi)
if (pci_enable_msi(pci) < 0)
chip->msi = 0;
if (azx_acquire_irq(chip, 0) < 0)
return -EBUSY;
pci_set_master(pci);
synchronize_irq(chip->irq);
dev_dbg(card->dev, "chipset global capabilities = 0x%x\n", gcap);
/* AMD devices support 40 or 48bit DMA, take the safe one */
if (chip->pci->vendor == PCI_VENDOR_ID_AMD)
dma_bits = 40;
/* disable SB600 64bit support for safety */
if (chip->pci->vendor == PCI_VENDOR_ID_ATI) {
struct pci_dev *p_smbus;
p_smbus = pci_get_device(PCI_VENDOR_ID_ATI,
PCI_DEVICE_ID_ATI_SBX00_SMBUS,
NULL);
if (p_smbus) {
if (p_smbus->revision < 0x30)
pci_dev_put(p_smbus);
}
}
/* disable 64bit DMA address on some devices */
if (chip->driver_caps & AZX_DCAPS_NO_64BIT) {
dev_dbg(card->dev, "Disabling 64bit DMA\n");
/* disable buffer size rounding to 128-byte multiples if supported */
if (align_buffer_size >= 0)
chip->align_buffer_size = !!align_buffer_size;
else {
if (chip->driver_caps & AZX_DCAPS_BUFSIZE)
chip->align_buffer_size = 0;
else if (chip->driver_caps & AZX_DCAPS_ALIGN_BUFSIZE)
chip->align_buffer_size = 1;
else
chip->align_buffer_size = 1;
}
/* allow 64bit DMA address if supported by H/W */
if (!(gcap & AZX_GCAP_64OK))
dma_bits = 32;
if (!pci_set_dma_mask(pci, DMA_BIT_MASK(dma_bits))) {
pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(dma_bits));
} else {
pci_set_dma_mask(pci, DMA_BIT_MASK(32));
pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(32));
/* read number of streams from GCAP register instead of using
* hardcoded value
*/
chip->capture_streams = (gcap >> 8) & 0x0f;
chip->playback_streams = (gcap >> 12) & 0x0f;
if (!chip->playback_streams && !chip->capture_streams) {
/* gcap didn't give any info, switching to old method */
switch (chip->driver_type) {
case AZX_DRIVER_ULI:
chip->playback_streams = ULI_NUM_PLAYBACK;
chip->capture_streams = ULI_NUM_CAPTURE;
break;
case AZX_DRIVER_ATIHDMI:
chip->playback_streams = ATIHDMI_NUM_PLAYBACK;
chip->capture_streams = ATIHDMI_NUM_CAPTURE;
break;
case AZX_DRIVER_GENERIC:
default:
chip->playback_streams = ICH6_NUM_PLAYBACK;
chip->capture_streams = ICH6_NUM_CAPTURE;
break;
}
chip->capture_index_offset = 0;
chip->playback_index_offset = chip->capture_streams;
chip->num_streams = chip->playback_streams + chip->capture_streams;
chip->azx_dev = kcalloc(chip->num_streams, sizeof(*chip->azx_dev),
GFP_KERNEL);
dev_err(card->dev, "cannot malloc azx_dev\n");
err = azx_alloc_stream_pages(chip);
if (err < 0)
/* initialize streams */
azx_init_stream(chip);
/* initialize chip */
Mengdong Lin
committed
if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL)
haswell_set_bclk(chip);
azx_init_chip(chip, (probe_only[dev] & 2) == 0);
dev_err(card->dev, "no codecs found!\n");
strcpy(card->driver, "HDA-Intel");
strlcpy(card->shortname, driver_short_names[chip->driver_type],
sizeof(card->shortname));
snprintf(card->longname, sizeof(card->longname),
"%s at 0x%lx irq %i",
card->shortname, chip->addr, chip->irq);
static void power_down_all_codecs(struct azx *chip)
{
/* The codecs were powered up in snd_hda_codec_new().
* Now all initialization done, so turn them down if possible
*/
struct hda_codec *codec;
list_for_each_entry(codec, &chip->bus->codec_list, list) {
snd_hda_power_down(codec);
}
#endif
}
#ifdef CONFIG_SND_HDA_PATCH_LOADER
/* callback from request_firmware_nowait() */
static void azx_firmware_cb(const struct firmware *fw, void *context)
{
struct snd_card *card = context;
struct azx *chip = card->private_data;
struct pci_dev *pci = chip->pci;
if (!fw) {
dev_err(card->dev, "Cannot load firmware, aborting\n");
goto error;
}
chip->fw = fw;
if (!chip->disabled) {
/* continue probing */
if (azx_probe_continue(chip))
goto error;
}
return; /* OK */
error:
snd_card_free(card);
pci_set_drvdata(pci, NULL);
}
/*
* HDA controller ops.
*/
/* PCI register access. */
static void pci_azx_writel(u32 value, u32 __iomem *addr)
{
writel(value, addr);
}
static u32 pci_azx_readl(u32 __iomem *addr)
{
return readl(addr);
}
static void pci_azx_writew(u16 value, u16 __iomem *addr)
{
writew(value, addr);
}
static u16 pci_azx_readw(u16 __iomem *addr)
{
return readw(addr);
}
static void pci_azx_writeb(u8 value, u8 __iomem *addr)
{
writeb(value, addr);
}
static u8 pci_azx_readb(u8 __iomem *addr)
{
return readb(addr);
}
static int disable_msi_reset_irq(struct azx *chip)
{
int err;
free_irq(chip->irq, chip);
chip->irq = -1;
pci_disable_msi(chip->pci);
chip->msi = 0;
err = azx_acquire_irq(chip, 1);
if (err < 0)
return err;
return 0;
}
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
/* DMA page allocation helpers. */
static int dma_alloc_pages(struct azx *chip,
int type,
size_t size,
struct snd_dma_buffer *buf)
{
int err;
err = snd_dma_alloc_pages(type,
chip->card->dev,
size, buf);
if (err < 0)
return err;
mark_pages_wc(chip, buf, true);
return 0;
}
static void dma_free_pages(struct azx *chip, struct snd_dma_buffer *buf)
{
mark_pages_wc(chip, buf, false);
snd_dma_free_pages(buf);
}
static int substream_alloc_pages(struct azx *chip,
struct snd_pcm_substream *substream,
size_t size)
{
struct azx_dev *azx_dev = get_azx_dev(substream);
int ret;
mark_runtime_wc(chip, azx_dev, substream, false);
azx_dev->bufsize = 0;
azx_dev->period_bytes = 0;
azx_dev->format_val = 0;
ret = snd_pcm_lib_malloc_pages(substream, size);
if (ret < 0)
return ret;
mark_runtime_wc(chip, azx_dev, substream, true);
return 0;
}
static int substream_free_pages(struct azx *chip,
struct snd_pcm_substream *substream)
{
struct azx_dev *azx_dev = get_azx_dev(substream);
mark_runtime_wc(chip, azx_dev, substream, false);
return snd_pcm_lib_free_pages(substream);
}
static void pcm_mmap_prepare(struct snd_pcm_substream *substream,
struct vm_area_struct *area)
{
#ifdef CONFIG_X86
struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
struct azx *chip = apcm->chip;
if (!azx_snoop(chip) && chip->driver_type != AZX_DRIVER_CMEDIA)
area->vm_page_prot = pgprot_writecombine(area->vm_page_prot);
#endif
}
static const struct hda_controller_ops pci_hda_ops = {
.reg_writel = pci_azx_writel,
.reg_readl = pci_azx_readl,
.reg_writew = pci_azx_writew,
.reg_readw = pci_azx_readw,
.reg_writeb = pci_azx_writeb,
.reg_readb = pci_azx_readb,
.disable_msi_reset_irq = disable_msi_reset_irq,
.dma_alloc_pages = dma_alloc_pages,
.dma_free_pages = dma_free_pages,
.substream_alloc_pages = substream_alloc_pages,
.substream_free_pages = substream_free_pages,
.pcm_mmap_prepare = pcm_mmap_prepare,
static int azx_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
struct hda_intel *hda;
bool schedule_probe;
if (dev >= SNDRV_CARDS)
return -ENODEV;
if (!enable[dev]) {
dev++;
return -ENOENT;
}
err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
0, &card);
dev_err(&pci->dev, "Error creating card!\n");
err = azx_create(card, pci, dev, pci_id->driver_data,
&pci_hda_ops, &chip);
hda = container_of(chip, struct hda_intel, chip);
pci_set_drvdata(pci, card);
err = register_vga_switcheroo(chip);
if (err < 0) {
dev_err(card->dev, "Error registering VGA-switcheroo client\n");
goto out_free;
}
if (check_hdmi_disabled(pci)) {
dev_info(card->dev, "VGA controller is disabled\n");
dev_info(card->dev, "Delaying initialization\n");
chip->disabled = true;
}
schedule_probe = !chip->disabled;
#ifdef CONFIG_SND_HDA_PATCH_LOADER
if (patch[dev] && *patch[dev]) {
dev_info(card->dev, "Applying patch firmware '%s'\n",
patch[dev]);
err = request_firmware_nowait(THIS_MODULE, true, patch[dev],
&pci->dev, GFP_KERNEL, card,
azx_firmware_cb);
if (err < 0)
goto out_free;
schedule_probe = false; /* continued in azx_firmware_cb() */
}
#endif /* CONFIG_SND_HDA_PATCH_LOADER */
#ifndef CONFIG_SND_HDA_I915
if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL)
dev_err(card->dev, "Haswell must build in CONFIG_SND_HDA_I915\n");
if (schedule_probe)
schedule_work(&hda->probe_work);
if (chip->disabled)
complete_all(&hda->probe_wait);
return 0;
out_free:
snd_card_free(card);
return err;
}
/* number of codec slots for each chipset: 0 = default slots (i.e. 4) */
static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] = {
[AZX_DRIVER_NVIDIA] = 8,
[AZX_DRIVER_TERA] = 1,
};
static int azx_probe_continue(struct azx *chip)
struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
int dev = chip->dev_index;
int err;
/* Request power well for Haswell HDA controller and codec */
if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) {
#ifdef CONFIG_SND_HDA_I915
err = hda_i915_init();
if (err < 0) {
dev_err(chip->card->dev,
"Error request power-well from i915\n");
goto out_free;
}
err = hda_display_power(true);
if (err < 0) {
dev_err(chip->card->dev,
"Cannot turn on display power on i915\n");
goto out_free;
}
#endif
err = azx_first_init(chip);
if (err < 0)
goto out_free;
#ifdef CONFIG_SND_HDA_INPUT_BEEP
chip->beep_mode = beep_mode[dev];
#endif
err = azx_codec_create(chip, model[dev],
azx_max_codecs[chip->driver_type],
power_save_addr);
if (chip->fw) {
err = snd_hda_load_patch(chip->bus, chip->fw->size,
chip->fw->data);
#ifndef CONFIG_PM
release_firmware(chip->fw); /* no longer needed */
chip->fw = NULL;
if ((probe_only[dev] & 1) == 0) {
err = azx_codec_configure(chip);
if (err < 0)
goto out_free;
}
err = snd_hda_build_pcms(chip->bus);
chip->running = 1;
power_down_all_codecs(chip);
azx_add_card_list(chip);
if ((chip->driver_caps & AZX_DCAPS_PM_RUNTIME) || hda->use_vga_switcheroo)
hda->init_failed = 1;
complete_all(&hda->probe_wait);
static void azx_remove(struct pci_dev *pci)
struct snd_card *card = pci_get_drvdata(pci);
if (card)
snd_card_free(card);
static const struct pci_device_id azx_ids[] = {
/* CPT */
{ PCI_DEVICE(0x8086, 0x1c20),
.driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM },
/* PBG */
{ PCI_DEVICE(0x8086, 0x1d20),
.driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM },
/* Panther Point */
{ PCI_DEVICE(0x8086, 0x1e20),
.driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
/* Lynx Point */
{ PCI_DEVICE(0x8086, 0x8c20),
.driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
/* 9 Series */
{ PCI_DEVICE(0x8086, 0x8ca0),
.driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
/* Wellsburg */
{ PCI_DEVICE(0x8086, 0x8d20),