#include <linux/init.h>
#include <linux/pci.h>
#include <linux/slab.h>
-#include <linux/gameport.h>
#include <linux/moduleparam.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/ac97_codec.h>
#include <sound/info.h>
-#include <sound/mpu401.h>
#include <sound/initval.h>
/* for 440MX workaround */
#include <asm/pgtable.h>
"{Intel,82801DB-ICH4},"
"{Intel,ICH5},"
"{Intel,ICH6},"
+ "{Intel,ICH7},"
"{Intel,6300ESB},"
"{Intel,MX440},"
"{SiS,SI7012},"
"{AMD,AMD8111},"
"{ALI,M5455}}");
-#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
-#define SUPPORT_JOYSTICK 1
-#endif
-#define SUPPORT_MIDI 1
-
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
static int ac97_clock[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0};
-static int ac97_quirk[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = AC97_TUNE_DEFAULT};
+static char *ac97_quirk[SNDRV_CARDS];
static int buggy_irq[SNDRV_CARDS];
-#ifdef SUPPORT_JOYSTICK
-static int joystick[SNDRV_CARDS];
-#endif
+static int xbox[SNDRV_CARDS];
+
#ifdef SUPPORT_MIDI
static int mpu_port[SNDRV_CARDS]; /* disabled */
#endif
-static int boot_devs;
-module_param_array(index, int, boot_devs, 0444);
+module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for Intel i8x0 soundcard.");
-module_param_array(id, charp, boot_devs, 0444);
+module_param_array(id, charp, NULL, 0444);
MODULE_PARM_DESC(id, "ID string for Intel i8x0 soundcard.");
-module_param_array(enable, bool, boot_devs, 0444);
+module_param_array(enable, bool, NULL, 0444);
MODULE_PARM_DESC(enable, "Enable Intel i8x0 soundcard.");
-module_param_array(ac97_clock, int, boot_devs, 0444);
+module_param_array(ac97_clock, int, NULL, 0444);
MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (0 = auto-detect).");
-module_param_array(ac97_quirk, int, boot_devs, 0444);
+module_param_array(ac97_quirk, charp, NULL, 0444);
MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware.");
-module_param_array(buggy_irq, bool, boot_devs, 0444);
+module_param_array(buggy_irq, bool, NULL, 0444);
MODULE_PARM_DESC(buggy_irq, "Enable workaround for buggy interrupts on some motherboards.");
-#ifdef SUPPORT_JOYSTICK
-module_param_array(joystick, bool, boot_devs, 0444);
-MODULE_PARM_DESC(joystick, "Enable joystick for Intel i8x0 soundcard.");
-#endif
-#ifdef SUPPORT_MIDI
-module_param_array(mpu_port, int, boot_devs, 0444);
-MODULE_PARM_DESC(mpu_port, "MPU401 port # for Intel i8x0 driver.");
-#endif
+module_param_array(xbox, bool, NULL, 0444);
+MODULE_PARM_DESC(xbox, "Set to 1 for Xbox, if you have problems with the AC'97 codec detection.");
/*
* Direct registers
#ifndef PCI_DEVICE_ID_INTEL_ICH6_3
#define PCI_DEVICE_ID_INTEL_ICH6_3 0x266e
#endif
+#ifndef PCI_DEVICE_ID_INTEL_ICH7_20
+#define PCI_DEVICE_ID_INTEL_ICH7_20 0x27de
+#endif
#ifndef PCI_DEVICE_ID_SI_7012
#define PCI_DEVICE_ID_SI_7012 0x7012
#endif
unsigned int ali_slot; /* ALI DMA slot */
struct ac97_pcm *pcm;
int pcm_open_flag;
+ unsigned int page_attr_changed: 1;
} ichdev_t;
typedef struct _snd_intel8x0 intel8x0_t;
unsigned int mmio;
unsigned long addr;
- void __iomem * remap_addr;
+ void __iomem *remap_addr;
unsigned int bm_mmio;
unsigned long bmaddr;
- void __iomem * remap_bmaddr;
+ void __iomem *remap_bmaddr;
struct pci_dev *pci;
snd_card_t *card;
unsigned multi4: 1,
multi6: 1,
+ dra: 1,
smp20bit: 1;
unsigned in_ac97_init: 1,
in_sdin_init: 1;
- unsigned fix_nocache: 1; /* workaround for 440MX */
- unsigned buggy_irq: 1; /* workaround for buggy mobos */
+ unsigned in_measurement: 1; /* during ac97 clock measurement */
+ unsigned fix_nocache: 1; /* workaround for 440MX */
+ unsigned buggy_irq: 1; /* workaround for buggy mobos */
+ unsigned xbox: 1; /* workaround for Xbox AC'97 detection */
+
+ int spdif_idx; /* SPDIF BAR index; *_SPBAR or -1 if use PCMOUT */
ac97_bus_t *ac97_bus;
ac97_t *ac97[3];
unsigned int ac97_sdin[3];
- snd_rawmidi_t *rmidi;
-
spinlock_t reg_lock;
- spinlock_t ac97_lock;
u32 bdbars_count;
struct snd_dma_buffer bdbars;
{ 0x8086, 0x24d5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL_ICH4 }, /* ICH5 */
{ 0x8086, 0x25a6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL_ICH4 }, /* ESB */
{ 0x8086, 0x266e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL_ICH4 }, /* ICH6 */
+ { 0x8086, 0x27de, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL_ICH4 }, /* ICH7 */
{ 0x8086, 0x7195, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* 440MX */
{ 0x1039, 0x7012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_SIS }, /* SI7012 */
{ 0x10de, 0x01b1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE }, /* NFORCE */
{
intel8x0_t *chip = ac97->private_data;
- spin_lock(&chip->ac97_lock);
if (snd_intel8x0_codec_semaphore(chip, ac97->num) < 0) {
if (! chip->in_ac97_init)
snd_printk("codec_write %d: semaphore is not ready for register 0x%x\n", ac97->num, reg);
}
iaputword(chip, reg + ac97->num * 0x80, val);
- spin_unlock(&chip->ac97_lock);
}
static unsigned short snd_intel8x0_codec_read(ac97_t *ac97,
unsigned short res;
unsigned int tmp;
- spin_lock(&chip->ac97_lock);
if (snd_intel8x0_codec_semaphore(chip, ac97->num) < 0) {
if (! chip->in_ac97_init)
snd_printk("codec_read %d: semaphore is not ready for register 0x%x\n", ac97->num, reg);
res = 0xffff;
}
}
- spin_unlock(&chip->ac97_lock);
return res;
}
{
unsigned int tmp;
- spin_lock(&chip->ac97_lock);
if (snd_intel8x0_codec_semaphore(chip, codec) >= 0) {
iagetword(chip, codec * 0x80);
if ((tmp = igetdword(chip, ICHREG(GLOB_STA))) & ICH_RCS) {
iputdword(chip, ICHREG(GLOB_STA), tmp & ~(ICH_SRI|ICH_PRI|ICH_TRI|ICH_GSCI));
}
}
- spin_unlock(&chip->ac97_lock);
}
/*
intel8x0_t *chip = ac97->private_data;
unsigned short data = 0xffff;
- spin_lock(&chip->ac97_lock);
if (snd_intel8x0_ali_codec_semaphore(chip))
goto __err;
reg |= ALI_CPR_ADDR_READ;
goto __err;
data = igetword(chip, ICHREG(ALI_SPR));
__err:
- spin_unlock(&chip->ac97_lock);
return data;
}
{
intel8x0_t *chip = ac97->private_data;
- spin_lock(&chip->ac97_lock);
- if (snd_intel8x0_ali_codec_semaphore(chip)) {
- spin_unlock(&chip->ac97_lock);
+ if (snd_intel8x0_ali_codec_semaphore(chip))
return;
- }
iputword(chip, ICHREG(ALI_CPR), val);
if (ac97->num)
reg |= ALI_CPR_ADDR_SECONDARY;
iputword(chip, ICHREG(ALI_CPR_ADDR), reg);
snd_intel8x0_ali_codec_ready(chip, ALI_CSPSR_WRITE_OK);
- spin_unlock(&chip->ac97_lock);
}
}
ichdev->position += step * ichdev->fragsize1;
- ichdev->position %= ichdev->size;
+ if (! chip->in_measurement)
+ ichdev->position %= ichdev->size;
ichdev->lvi += step;
ichdev->lvi &= ICH_REG_LVI_MASK;
iputbyte(chip, port + ICH_REG_OFF_LVI, ichdev->lvi);
intel8x0_t *chip = snd_pcm_substream_chip(substream);
ichdev_t *ichdev = get_ichdev(substream);
snd_pcm_runtime_t *runtime = substream->runtime;
- size_t size = params_buffer_bytes(hw_params);
+ int dbl = params_rate(hw_params) > 48000;
int err;
- if (chip->fix_nocache && runtime->dma_area && runtime->dma_bytes < size)
+ if (chip->fix_nocache && ichdev->page_attr_changed) {
fill_nocache(runtime->dma_area, runtime->dma_bytes, 0); /* clear */
+ ichdev->page_attr_changed = 0;
+ }
err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
if (err < 0)
return err;
- if (chip->fix_nocache && err > 0)
- fill_nocache(runtime->dma_area, runtime->dma_bytes, 1);
+ if (chip->fix_nocache) {
+ if (runtime->dma_area && ! ichdev->page_attr_changed) {
+ fill_nocache(runtime->dma_area, runtime->dma_bytes, 1);
+ ichdev->page_attr_changed = 1;
+ }
+ }
if (ichdev->pcm_open_flag) {
snd_ac97_pcm_close(ichdev->pcm);
ichdev->pcm_open_flag = 0;
}
err = snd_ac97_pcm_open(ichdev->pcm, params_rate(hw_params),
params_channels(hw_params),
- ichdev->pcm->r[0].slots);
+ ichdev->pcm->r[dbl].slots);
if (err >= 0) {
ichdev->pcm_open_flag = 1;
- /* FIXME: hack to enable spdif support */
- if (ichdev->ichd == ICHD_PCMOUT && chip->device_type == DEVICE_SIS)
+ /* Force SPDIF setting */
+ if (ichdev->ichd == ICHD_PCMOUT && chip->spdif_idx < 0)
snd_ac97_set_rate(ichdev->pcm->r[0].codec[0], AC97_SPDIF, params_rate(hw_params));
}
return err;
snd_ac97_pcm_close(ichdev->pcm);
ichdev->pcm_open_flag = 0;
}
- if (chip->fix_nocache && substream->runtime->dma_area)
+ if (chip->fix_nocache && ichdev->page_attr_changed) {
fill_nocache(substream->runtime->dma_area, substream->runtime->dma_bytes, 0);
+ ichdev->page_attr_changed = 0;
+ }
return snd_pcm_lib_free_pages(substream);
}
static void snd_intel8x0_setup_pcm_out(intel8x0_t *chip,
- int channels, int sample_bits)
+ snd_pcm_runtime_t *runtime)
{
unsigned int cnt;
+ int dbl = runtime->rate > 48000;
switch (chip->device_type) {
case DEVICE_ALI:
cnt = igetdword(chip, ICHREG(ALI_SCR));
cnt &= ~ICH_ALI_SC_PCM_246_MASK;
- if (chip->multi4 && channels == 4)
+ if (runtime->channels == 4 || dbl)
cnt |= ICH_ALI_SC_PCM_4;
- else if (chip->multi6 && channels == 6)
+ else if (runtime->channels == 6)
cnt |= ICH_ALI_SC_PCM_6;
iputdword(chip, ICHREG(ALI_SCR), cnt);
break;
case DEVICE_SIS:
cnt = igetdword(chip, ICHREG(GLOB_CNT));
cnt &= ~ICH_SIS_PCM_246_MASK;
- if (chip->multi4 && channels == 4)
+ if (runtime->channels == 4 || dbl)
cnt |= ICH_SIS_PCM_4;
- else if (chip->multi6 && channels == 6)
+ else if (runtime->channels == 6)
cnt |= ICH_SIS_PCM_6;
iputdword(chip, ICHREG(GLOB_CNT), cnt);
break;
default:
cnt = igetdword(chip, ICHREG(GLOB_CNT));
cnt &= ~(ICH_PCM_246_MASK | ICH_PCM_20BIT);
- if (chip->multi4 && channels == 4)
+ if (runtime->channels == 4 || dbl)
cnt |= ICH_PCM_4;
- else if (chip->multi6 && channels == 6)
+ else if (runtime->channels == 6)
cnt |= ICH_PCM_6;
if (chip->device_type == DEVICE_NFORCE) {
/* reset to 2ch once to keep the 6 channel data in alignment,
*/
if (cnt & ICH_PCM_246_MASK) {
iputdword(chip, ICHREG(GLOB_CNT), cnt & ~ICH_PCM_246_MASK);
+ spin_unlock_irq(&chip->reg_lock);
msleep(50); /* grrr... */
+ spin_lock_irq(&chip->reg_lock);
}
} else if (chip->device_type == DEVICE_INTEL_ICH4) {
- if (sample_bits > 16)
+ if (runtime->sample_bits > 16)
cnt |= ICH_PCM_20BIT;
}
iputdword(chip, ICHREG(GLOB_CNT), cnt);
ichdev->fragsize = snd_pcm_lib_period_bytes(substream);
spin_lock_irq(&chip->reg_lock);
if (ichdev->ichd == ICHD_PCMOUT) {
- snd_intel8x0_setup_pcm_out(chip, runtime->channels,
- runtime->sample_bits);
+ snd_intel8x0_setup_pcm_out(chip, runtime);
if (chip->device_type == DEVICE_INTEL_ICH4) {
ichdev->pos_shift = (runtime->sample_bits > 16) ? 2 : 1;
}
runtime->hw.channels_max = 4;
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, &hw_constraints_channels4);
}
+ if (chip->dra) {
+ snd_ac97_pcm_double_rate_rules(runtime);
+ }
if (chip->smp20bit) {
runtime->hw.formats |= SNDRV_PCM_FMTBIT_S32_LE;
snd_pcm_hw_constraint_msbits(runtime, 0, 32, 20);
(1 << AC97_SLOT_PCM_SLEFT) |
(1 << AC97_SLOT_PCM_SRIGHT) |
(1 << AC97_SLOT_LFE)
+ },
+ {
+ .slots = (1 << AC97_SLOT_PCM_LEFT) |
+ (1 << AC97_SLOT_PCM_RIGHT) |
+ (1 << AC97_SLOT_PCM_LEFT_0) |
+ (1 << AC97_SLOT_PCM_RIGHT_0)
}
}
},
};
static struct ac97_quirk ac97_quirks[] __devinitdata = {
+ {
+ .vendor = 0x0e11,
+ .device = 0x008a,
+ .name = "Compaq Evo W4000", /* AD1885 */
+ .type = AC97_TUNE_HP_ONLY
+ },
{
.vendor = 0x0e11,
.device = 0x00b8,
.name = "Compaq Evo D510C",
.type = AC97_TUNE_HP_ONLY
},
+ {
+ .vendor = 0x0e11,
+ .device = 0x0860,
+ .name = "HP/Compaq nx7010",
+ .type = AC97_TUNE_MUTE_LED
+ },
{
.vendor = 0x1014,
.device = 0x1f00,
.name = "Dell Precision 530", /* AD1885 */
.type = AC97_TUNE_HP_ONLY
},
+ {
+ .vendor = 0x1028,
+ .device = 0x010d,
+ .name = "Dell", /* which model? AD1885 */
+ .type = AC97_TUNE_HP_ONLY
+ },
{
.vendor = 0x1028,
.device = 0x0126,
.name = "Dell Precision 450", /* AD1981B*/
.type = AC97_TUNE_HP_ONLY
},
+ {
+ .vendor = 0x1028,
+ .device = 0x0147,
+ .name = "Dell", /* which model? AD1981B*/
+ .type = AC97_TUNE_HP_ONLY
+ },
+ {
+ .vendor = 0x103c,
+ .device = 0x006d,
+ .name = "HP zv5000",
+ .type = AC97_TUNE_MUTE_LED /*AD1981B*/
+ },
{ /* FIXME: which codec? */
.vendor = 0x103c,
.device = 0x00c3,
- .name = "Hewlett-Packard onboard",
+ .name = "HP xw6000",
+ .type = AC97_TUNE_HP_ONLY
+ },
+ {
+ .vendor = 0x103c,
+ .device = 0x088c,
+ .name = "HP nc8000",
+ .type = AC97_TUNE_MUTE_LED
+ },
+ {
+ .vendor = 0x103c,
+ .device = 0x0890,
+ .name = "HP nc6000",
+ .type = AC97_TUNE_MUTE_LED
+ },
+ {
+ .vendor = 0x103c,
+ .device = 0x129d,
+ .name = "HP xw8000",
.type = AC97_TUNE_HP_ONLY
},
{
.name = "HP xw8200", /* AD1981B*/
.type = AC97_TUNE_HP_ONLY
},
+ {
+ .vendor = 0x103c,
+ .device = 0x12f2,
+ .name = "HP xw6200",
+ .type = AC97_TUNE_HP_ONLY
+ },
{
.vendor = 0x103c,
.device = 0x3008,
.name = "HP xw4200", /* AD1981B*/
.type = AC97_TUNE_HP_ONLY
},
+ {
+ .vendor = 0x104d,
+ .device = 0x8197,
+ .name = "Sony S1XP",
+ .type = AC97_TUNE_INV_EAPD
+ },
{
.vendor = 0x1043,
.device = 0x80f3,
.name = "ASUS ICH5/AD1985",
.type = AC97_TUNE_AD_SHARING
},
+ {
+ .vendor = 0x10cf,
+ .device = 0x11c3,
+ .name = "Fujitsu-Siemens E4010",
+ .type = AC97_TUNE_HP_ONLY
+ },
{
.vendor = 0x10f1,
.device = 0x2665,
{ } /* terminator */
};
-static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock, int ac97_quirk)
+static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock, const char *quirk_override)
{
ac97_bus_t *pbus;
ac97_template_t ac97;
int err;
unsigned int i, codecs;
unsigned int glob_sta = 0;
- int spdif_idx = -1; /* disabled */
ac97_bus_ops_t *ops;
static ac97_bus_ops_t standard_bus_ops = {
.write = snd_intel8x0_codec_write,
.read = snd_intel8x0_ali_codec_read,
};
+ chip->spdif_idx = -1; /* use PCMOUT (or disabled) */
switch (chip->device_type) {
case DEVICE_NFORCE:
- spdif_idx = NVD_SPBAR;
+ chip->spdif_idx = NVD_SPBAR;
break;
case DEVICE_ALI:
- spdif_idx = ALID_AC97SPDIFOUT;
+ chip->spdif_idx = ALID_AC97SPDIFOUT;
break;
- default:
- if (chip->device_type == DEVICE_INTEL_ICH4)
- spdif_idx = ICHD_SPBAR;
+ case DEVICE_INTEL_ICH4:
+ chip->spdif_idx = ICHD_SPBAR;
break;
};
ac97.private_data = chip;
ac97.private_free = snd_intel8x0_mixer_free_ac97;
ac97.scaps = AC97_SCAP_SKIP_MODEM;
+ if (chip->xbox)
+ ac97.scaps |= AC97_SCAP_DETECT_BY_VENDOR;
if (chip->device_type != DEVICE_ALI) {
glob_sta = igetdword(chip, ICHREG(GLOB_STA));
ops = &standard_bus_ops;
/* FIXME: my test board doesn't work well with VRA... */
if (chip->device_type == DEVICE_ALI)
pbus->no_vra = 1;
+ pbus->dra = 1;
chip->ac97_bus = pbus;
ac97.pci = chip->pci;
}
}
/* tune up the primary codec */
- snd_ac97_tune_hardware(chip->ac97[0], ac97_quirks, ac97_quirk);
+ snd_ac97_tune_hardware(chip->ac97[0], ac97_quirks, quirk_override);
/* enable separate SDINs for ICH4 */
if (chip->device_type == DEVICE_INTEL_ICH4)
pbus->isdin = 1;
i = ARRAY_SIZE(ac97_pcm_defs);
if (chip->device_type != DEVICE_INTEL_ICH4)
i -= 2; /* do not allocate PCM2IN and MIC2 */
- if (spdif_idx < 0)
+ if (chip->spdif_idx < 0)
i--; /* do not allocate S/PDIF */
err = snd_ac97_pcm_assign(pbus, i, ac97_pcm_defs);
if (err < 0)
chip->ichd[ICHD_PCMOUT].pcm = &pbus->pcms[0];
chip->ichd[ICHD_PCMIN].pcm = &pbus->pcms[1];
chip->ichd[ICHD_MIC].pcm = &pbus->pcms[2];
- if (spdif_idx >= 0)
- chip->ichd[spdif_idx].pcm = &pbus->pcms[3];
+ if (chip->spdif_idx >= 0)
+ chip->ichd[chip->spdif_idx].pcm = &pbus->pcms[3];
if (chip->device_type == DEVICE_INTEL_ICH4) {
chip->ichd[ICHD_PCM2IN].pcm = &pbus->pcms[4];
chip->ichd[ICHD_MIC2].pcm = &pbus->pcms[5];
if (pbus->pcms[0].r[0].slots & (1 << AC97_SLOT_LFE))
chip->multi6 = 1;
}
+ if (pbus->pcms[0].r[1].rslots[0]) {
+ chip->dra = 1;
+ }
if (chip->device_type == DEVICE_INTEL_ICH4) {
if ((igetdword(chip, ICHREG(GLOB_STA)) & ICH_SAMPLE_CAP) == ICH_SAMPLE_16_20)
chip->smp20bit = 1;
}
if (chip->device_type == DEVICE_NFORCE) {
/* 48kHz only */
- chip->ichd[spdif_idx].pcm->rates = SNDRV_PCM_RATE_48000;
+ chip->ichd[chip->spdif_idx].pcm->rates = SNDRV_PCM_RATE_48000;
+ }
+ if (chip->device_type == DEVICE_INTEL_ICH4) {
+ /* use slot 10/11 for SPDIF */
+ u32 val;
+ val = igetdword(chip, ICHREG(GLOB_CNT)) & ~ICH_PCM_SPDIF_MASK;
+ val |= ICH_PCM_SPDIF_1011;
+ iputdword(chip, ICHREG(GLOB_CNT), val);
+ snd_ac97_update_bits(chip->ac97[0], AC97_EXTENDED_STATUS, 0x03 << 4, 0x03 << 4);
}
chip->in_ac97_init = 0;
return 0;
if (chip->remap_bmaddr)
iounmap(chip->remap_bmaddr);
pci_release_regions(chip->pci);
+ pci_disable_device(chip->pci);
kfree(chip);
return 0;
}
for (i = 0; i < chip->pcm_devs; i++)
snd_pcm_suspend_all(chip->pcm[i]);
+ /* clear nocache */
+ if (chip->fix_nocache) {
+ for (i = 0; i < chip->bdbars_count; i++) {
+ ichdev_t *ichdev = &chip->ichd[i];
+ if (ichdev->substream && ichdev->page_attr_changed) {
+ snd_pcm_runtime_t *runtime = ichdev->substream->runtime;
+ if (runtime->dma_area)
+ fill_nocache(runtime->dma_area, runtime->dma_bytes, 0);
+ }
+ }
+ }
for (i = 0; i < 3; i++)
if (chip->ac97[i])
snd_ac97_suspend(chip->ac97[i]);
- snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+ pci_disable_device(chip->pci);
return 0;
}
if (chip->fix_nocache) {
for (i = 0; i < chip->bdbars_count; i++) {
ichdev_t *ichdev = &chip->ichd[i];
- if (ichdev->substream) {
+ if (ichdev->substream && ichdev->page_attr_changed) {
snd_pcm_runtime_t *runtime = ichdev->substream->runtime;
if (runtime->dma_area)
fill_nocache(runtime->dma_area, runtime->dma_bytes, 1);
}
}
- snd_power_change_state(card, SNDRV_CTL_POWER_D0);
return 0;
}
#endif /* CONFIG_PM */
snd_intel8x0_setup_periods(chip, ichdev);
port = ichdev->reg_offset;
spin_lock_irq(&chip->reg_lock);
+ chip->in_measurement = 1;
/* trigger */
if (chip->device_type != DEVICE_ALI)
iputbyte(chip, port + ICH_REG_OFF_CR, ICH_IOCE | ICH_STARTBM);
}
do_gettimeofday(&start_time);
spin_unlock_irq(&chip->reg_lock);
-#if 0
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(HZ / 20);
-#else
- /* FIXME: schedule() can take too long time and overlap the boundary.. */
- mdelay(50);
-#endif
spin_lock_irq(&chip->reg_lock);
/* check the position */
pos = ichdev->fragsize1;
pos -= igetword(chip, ichdev->reg_offset + ichdev->roff_picb) << ichdev->pos_shift;
pos += ichdev->position;
+ chip->in_measurement = 0;
do_gettimeofday(&stop_time);
/* stop */
if (chip->device_type == DEVICE_ALI) {
return err;
chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
- if (chip == NULL)
+ if (chip == NULL) {
+ pci_disable_device(pci);
return -ENOMEM;
+ }
spin_lock_init(&chip->reg_lock);
- spin_lock_init(&chip->ac97_lock);
chip->device_type = device_type;
chip->card = card;
chip->pci = pci;
if ((err = pci_request_regions(pci, card->shortname)) < 0) {
kfree(chip);
+ pci_disable_device(pci);
return err;
}
if (pci_resource_flags(pci, 2) & IORESOURCE_MEM) { /* ICH4 and Nforce */
chip->mmio = 1;
chip->addr = pci_resource_start(pci, 2);
- chip->remap_addr = ioremap_nocache(chip->addr, pci_resource_len(pci, 2));
- if (!chip->remap_addr) {
+ chip->remap_addr = ioremap_nocache(chip->addr,
+ pci_resource_len(pci, 2));
+ if (chip->remap_addr == NULL) {
snd_printk("AC'97 space ioremap problem\n");
snd_intel8x0_free(chip);
return -EIO;
if (pci_resource_flags(pci, 3) & IORESOURCE_MEM) { /* ICH4 */
chip->bm_mmio = 1;
chip->bmaddr = pci_resource_start(pci, 3);
- chip->remap_bmaddr = ioremap_nocache(chip->bmaddr, pci_resource_len(pci, 3));
- if (!chip->remap_bmaddr) {
+ chip->remap_bmaddr = ioremap_nocache(chip->bmaddr,
+ pci_resource_len(pci, 3));
+ if (chip->remap_bmaddr == NULL) {
snd_printk("Controller space ioremap problem\n");
snd_intel8x0_free(chip);
return -EIO;
{ PCI_DEVICE_ID_INTEL_ICH5, "Intel ICH5" },
{ PCI_DEVICE_ID_INTEL_ESB_5, "Intel 6300ESB" },
{ PCI_DEVICE_ID_INTEL_ICH6_3, "Intel ICH6" },
+ { PCI_DEVICE_ID_INTEL_ICH7_20, "Intel ICH7" },
{ PCI_DEVICE_ID_SI_7012, "SiS SI7012" },
{ PCI_DEVICE_ID_NVIDIA_MCP_AUDIO, "NVidia nForce" },
{ PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO, "NVidia nForce2" },
case DEVICE_NFORCE:
strcpy(card->driver, "NFORCE");
break;
+ case DEVICE_INTEL_ICH4:
+ strcpy(card->driver, "ICH4");
+ break;
default:
strcpy(card->driver, "ICH");
break;
}
if (buggy_irq[dev])
chip->buggy_irq = 1;
+ if (xbox[dev])
+ chip->xbox = 1;
if ((err = snd_intel8x0_mixer(chip, ac97_clock[dev], ac97_quirk[dev])) < 0) {
snd_card_free(card);
return err;
}
- if (mpu_port[dev] == 0x300 || mpu_port[dev] == 0x330) {
- if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_INTEL8X0,
- mpu_port[dev], 0,
- -1, 0, &chip->rmidi)) < 0) {
- printk(KERN_ERR "intel8x0: no UART401 device at 0x%x, skipping.\n", mpu_port[dev]);
- mpu_port[dev] = 0;
- }
- } else
- mpu_port[dev] = 0;
-
snd_intel8x0_proc_init(chip);
- sprintf(card->longname, "%s at 0x%lx, irq %i",
- card->shortname, chip->addr, chip->irq);
+ snprintf(card->longname, sizeof(card->longname),
+ "%s with %s at %#lx, irq %i", card->shortname,
+ snd_ac97_get_short_name(chip->ac97[0]), chip->addr, chip->irq);
if (! ac97_clock[dev])
intel8x0_measure_ac97_clock(chip);
};
-#if defined(SUPPORT_JOYSTICK) || defined(SUPPORT_MIDI)
-/*
- * initialize joystick/midi addresses
- */
-
-#ifdef SUPPORT_JOYSTICK
-/* there is only one available device, so we keep it here */
-static struct pci_dev *ich_gameport_pci;
-static struct gameport ich_gameport = { .io = 0x200 };
-#endif
-
-static int __devinit snd_intel8x0_joystick_probe(struct pci_dev *pci,
- const struct pci_device_id *id)
-{
- u16 val;
- static int dev;
- if (dev >= SNDRV_CARDS)
- return -ENODEV;
- if (!enable[dev]) {
- dev++;
- return -ENOENT;
- }
-
- pci_read_config_word(pci, 0xe6, &val);
-#ifdef SUPPORT_JOYSTICK
- val &= ~0x100;
- if (joystick[dev]) {
- if (! request_region(ich_gameport.io, 8, "ICH gameport")) {
- printk(KERN_WARNING "intel8x0: cannot grab gameport 0x%x\n", ich_gameport.io);
- joystick[dev] = 0;
- } else {
- ich_gameport_pci = pci;
- gameport_register_port(&ich_gameport);
- val |= 0x100;
- }
- }
-#endif
-#ifdef SUPPORT_MIDI
- val &= ~0x20;
- if (mpu_port[dev] > 0) {
- if (mpu_port[dev] == 0x300 || mpu_port[dev] == 0x330) {
- u8 b;
- val |= 0x20;
- pci_read_config_byte(pci, 0xe2, &b);
- if (mpu_port[dev] == 0x300)
- b |= 0x08;
- else
- b &= ~0x08;
- pci_write_config_byte(pci, 0xe2, b);
- }
- }
-#endif
- pci_write_config_word(pci, 0xe6, val);
- return 0;
-}
-
-static void __devexit snd_intel8x0_joystick_remove(struct pci_dev *pci)
-{
- u16 val;
-#ifdef SUPPORT_JOYSTICK
- if (ich_gameport_pci == pci) {
- gameport_unregister_port(&ich_gameport);
- release_region(ich_gameport.io, 8);
- ich_gameport_pci = NULL;
- }
-#endif
- /* disable joystick and MIDI */
- pci_read_config_word(pci, 0xe6, &val);
- val &= ~0x120;
- pci_write_config_word(pci, 0xe6, val);
-}
-
-static struct pci_device_id snd_intel8x0_joystick_ids[] = {
- { 0x8086, 0x2410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* 82801AA */
- { 0x8086, 0x2420, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* 82901AB */
- { 0x8086, 0x2440, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ICH2 */
- { 0x8086, 0x244c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ICH2M */
- { 0x8086, 0x248c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ICH3 */
- // { 0x8086, 0x7195, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* 440MX */
- // { 0x1039, 0x7012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* SI7012 */
- { 0x10de, 0x01b2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* NFORCE */
- { 0x10de, 0x006b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* NFORCE2 */
- { 0x10de, 0x00db, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* NFORCE3 */
- { 0, }
-};
-
-static struct pci_driver joystick_driver = {
- .name = "Intel ICH Joystick",
- .id_table = snd_intel8x0_joystick_ids,
- .probe = snd_intel8x0_joystick_probe,
- .remove = __devexit_p(snd_intel8x0_joystick_remove),
-};
-
-static int have_joystick;
-#endif
-
static int __init alsa_card_intel8x0_init(void)
{
- int err;
-
- if ((err = pci_module_init(&driver)) < 0)
- return err;
-
-#if defined(SUPPORT_JOYSTICK) || defined(SUPPORT_MIDI)
- if (pci_module_init(&joystick_driver) < 0) {
- snd_printdd(KERN_INFO "no joystick found\n");
- have_joystick = 0;
- } else {
- snd_printdd(KERN_INFO "joystick(s) found\n");
- have_joystick = 1;
- }
-#endif
- return 0;
-
+ return pci_module_init(&driver);
}
static void __exit alsa_card_intel8x0_exit(void)
{
pci_unregister_driver(&driver);
-#if defined(SUPPORT_JOYSTICK) || defined(SUPPORT_MIDI)
- if (have_joystick)
- pci_unregister_driver(&joystick_driver);
-#endif
}
module_init(alsa_card_intel8x0_init)