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");
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)
if (chip->disabled || !hda->probe_continued)
if (snd_hda_lock_devices(&chip->bus))
snd_hda_unlock_devices(&chip->bus);
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,
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);
struct hdac_bus *bus = azx_bus(chip);
if (azx_has_pm_runtime(chip) && 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 && hda->probe_continued)
snd_hda_unlock_devices(&chip->bus);
if (hda->vga_switcheroo_registered)
vga_switcheroo_unregister_client(chip->pci);
azx_stop_all_streams(chip);
if (bus->irq >= 0)
free_irq(bus->irq, (void*)chip);
pci_disable_msi(chip->pci);
azx_free_stream_pages(chip);
azx_free_streams(chip);
snd_hdac_bus_exit(bus);
if (chip->region_requested)
pci_release_regions(chip->pci);
#ifdef CONFIG_SND_HDA_PATCH_LOADER
release_firmware(chip->fw);
if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) {
if (hda->need_i915_power)
hda_display_power(hda, false);
hda_i915_exit(hda);
kfree(hda);
static int azx_dev_disconnect(struct snd_device *device)
{
struct azx *chip = device->device_data;
chip->bus.shutdown = 1;
return 0;
}
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)
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
{
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;
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
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)) {
azx_bus(chip)->codec_mask = chip->codec_probe_mask & 0xff;
dev_info(chip->card->dev, "codec_mask forced to 0x%x\n",
(int)azx_bus(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)
int snoop = hda_snoop;
if (snoop >= 0) {
dev_info(chip->card->dev, "Force to %s mode by module option\n",
snoop ? "snoop" : "non-snoop");
chip->snoop = snoop;
return;
}
snoop = true;
if (azx_get_snoop_type(chip) == AZX_SNOOP_TYPE_NONE &&
chip->driver_type == AZX_DRIVER_VIA) {
/* force to non-snoop mode for a new VIA controller
* when BIOS is set
*/
u8 val;
pci_read_config_byte(chip->pci, 0x42, &val);
if (!(val & 0x80) && chip->pci->revision == 0x30)
snoop = false;
if (chip->driver_caps & AZX_DCAPS_SNOOP_OFF)
snoop = false;
chip->snoop = snoop;
if (!snoop)
dev_info(chip->card->dev, "Force to non-snoop mode\n");
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 const struct hdac_io_ops pci_hda_io_ops;
static const struct hda_controller_ops pci_hda_ops;
static int azx_create(struct snd_card *card, struct pci_dev *pci,
int dev, unsigned int driver_caps,
struct azx **rchip)
static struct snd_device_ops ops = {
.dev_disconnect = azx_dev_disconnect,
struct hda_intel *hda;
err = pci_enable_device(pci);
if (err < 0)
hda = kzalloc(sizeof(*hda), GFP_KERNEL);
if (!hda) {
pci_disable_device(pci);
return -ENOMEM;
}
chip = &hda->chip;
chip->ops = &pci_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 = azx_bus_init(chip, model[dev], &pci_hda_io_ops);
if (err < 0) {
kfree(hda);
pci_disable_device(pci);
return err;
}
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;
struct hdac_bus *bus = azx_bus(chip);
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");
bus->addr = pci_resource_start(pci, 0);
bus->remap_addr = pci_ioremap_bar(pci, 0);
if (bus->remap_addr == NULL) {
dev_err(card->dev, "ioremap error\n");
if (chip->msi) {
if (chip->driver_caps & AZX_DCAPS_NO_MSI64) {
dev_dbg(card->dev, "Disabling 64bit MSI\n");
pci->no_64bit_msi = true;
}
if (pci_enable_msi(pci) < 0)
chip->msi = 0;
if (azx_acquire_irq(chip, 0) < 0)
return -EBUSY;
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_NO_ALIGN_BUFSIZE)
chip->align_buffer_size = 0;
else
chip->align_buffer_size = 1;
}
/* allow 64bit DMA address if supported by H/W */
if (!(gcap & AZX_GCAP_64OK))
dma_bits = 32;
if (!dma_set_mask(&pci->dev, DMA_BIT_MASK(dma_bits))) {
dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(dma_bits));
dma_set_mask(&pci->dev, DMA_BIT_MASK(32));
dma_set_coherent_mask(&pci->dev, 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;
/* initialize streams */
err = azx_init_streams(chip);
if (err < 0)
err = azx_alloc_stream_pages(chip);
if (err < 0)
return err;
Mengdong Lin
committed
if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) {
struct hda_intel *hda;
hda = container_of(chip, struct hda_intel, chip);
haswell_set_bclk(hda);
}
Mengdong Lin
committed
azx_init_chip(chip, (probe_only[dev] & 2) == 0);
if (!azx_bus(chip)->codec_mask) {
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, bus->addr, bus->irq);
#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)
{
struct hdac_bus *bus = azx_bus(chip);
free_irq(bus->irq, chip);
bus->irq = -1;
pci_disable_msi(chip->pci);
chip->msi = 0;
err = azx_acquire_irq(chip, 1);
if (err < 0)
return err;
return 0;
}
/* DMA page allocation helpers. */
static int dma_alloc_pages(struct hdac_bus *bus,
int type,
size_t size,
struct snd_dma_buffer *buf)
{
struct azx *chip = bus_to_azx(bus);
int err;
err = snd_dma_alloc_pages(type,
bus->dev,
size, buf);
if (err < 0)
return err;
mark_pages_wc(chip, buf, true);
return 0;
}
static void dma_free_pages(struct hdac_bus *bus, struct snd_dma_buffer *buf)
struct azx *chip = bus_to_azx(bus);
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
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);
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 hdac_io_ops pci_hda_io_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,
.dma_alloc_pages = dma_alloc_pages,
.dma_free_pages = dma_free_pages,
};
static const struct hda_controller_ops pci_hda_ops = {
.disable_msi_reset_irq = disable_msi_reset_irq,
.substream_alloc_pages = substream_alloc_pages,
.substream_free_pages = substream_free_pages,
.pcm_mmap_prepare = pcm_mmap_prepare,
.link_power = azx_intel_link_power,
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, &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 display power well for the HDA controller or codec. For
* Haswell/Broadwell, both the display HDA controller and codec need
* this power. For other platforms, like Baytrail/Braswell, only the
* display codec needs the power and it can be released after probe.
*/
if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) {
Mengdong Lin
committed
/* Baytral/Braswell controllers don't need this power */
if (pci->device != 0x0f04 && pci->device != 0x2284)
hda->need_i915_power = 1;
err = hda_i915_init(hda);
goto i915_power_fail;
err = hda_display_power(hda, true);
if (err < 0) {
dev_err(chip->card->dev,
"Cannot turn on display power on i915\n");
goto i915_power_fail;
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_probe_codecs(chip, azx_max_codecs[chip->driver_type]);
err = snd_hda_load_patch(&chip->bus, chip->fw->size,
#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;
}
azx_add_card_list(chip);
snd_hda_set_power_save(&chip->bus, power_save * 1000);
if (azx_has_pm_runtime(chip) || hda->use_vga_switcheroo)
if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL
&& !hda->need_i915_power)
hda_display_power(hda, false);
i915_power_fail:
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 void azx_shutdown(struct pci_dev *pci)
{
struct snd_card *card = pci_get_drvdata(pci);
struct azx *chip;
if (!card)
return;
chip = card->private_data;
if (chip && chip->running)
azx_stop_chip(chip);
}
static const struct pci_device_id azx_ids[] = {
/* CPT */
{ PCI_DEVICE(0x8086, 0x1c20),
.driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM },
/* PBG */