#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 int buggy_irq[SNDRV_CARDS];
-static int xbox[SNDRV_CARDS];
-
+#ifdef SUPPORT_JOYSTICK
+static int joystick[SNDRV_CARDS];
+#endif
#ifdef SUPPORT_MIDI
static int mpu_port[SNDRV_CARDS]; /* disabled */
#endif
+static int boot_devs;
-module_param_array(index, int, NULL, 0444);
+module_param_array(index, int, boot_devs, 0444);
MODULE_PARM_DESC(index, "Index value for Intel i8x0 soundcard.");
-module_param_array(id, charp, NULL, 0444);
+module_param_array(id, charp, boot_devs, 0444);
MODULE_PARM_DESC(id, "ID string for Intel i8x0 soundcard.");
-module_param_array(enable, bool, NULL, 0444);
+module_param_array(enable, bool, boot_devs, 0444);
MODULE_PARM_DESC(enable, "Enable Intel i8x0 soundcard.");
-module_param_array(ac97_clock, int, NULL, 0444);
+module_param_array(ac97_clock, int, boot_devs, 0444);
MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (0 = auto-detect).");
-module_param_array(ac97_quirk, int, NULL, 0444);
+module_param_array(ac97_quirk, int, boot_devs, 0444);
MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware.");
-module_param_array(buggy_irq, bool, NULL, 0444);
+module_param_array(buggy_irq, bool, boot_devs, 0444);
MODULE_PARM_DESC(buggy_irq, "Enable workaround for buggy interrupts on some motherboards.");
-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.");
+#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
/*
* 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 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 */
+ unsigned fix_nocache: 1; /* workaround for 440MX */
+ unsigned buggy_irq: 1; /* workaround for buggy mobos */
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;
{ 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 */
}
ichdev->position += step * ichdev->fragsize1;
- if (! chip->in_measurement)
- ichdev->position %= ichdev->size;
+ ichdev->position %= ichdev->size;
ichdev->lvi += step;
ichdev->lvi &= ICH_REG_LVI_MASK;
iputbyte(chip, port + ICH_REG_OFF_LVI, ichdev->lvi);
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 && ichdev->page_attr_changed) {
+ if (chip->fix_nocache && runtime->dma_area && runtime->dma_bytes < size)
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) {
- if (runtime->dma_area && ! ichdev->page_attr_changed) {
- fill_nocache(runtime->dma_area, runtime->dma_bytes, 1);
- ichdev->page_attr_changed = 1;
- }
- }
+ if (chip->fix_nocache && err > 0)
+ fill_nocache(runtime->dma_area, runtime->dma_bytes, 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[dbl].slots);
+ ichdev->pcm->r[0].slots);
if (err >= 0) {
ichdev->pcm_open_flag = 1;
- /* Force SPDIF setting */
- if (ichdev->ichd == ICHD_PCMOUT && chip->spdif_idx < 0)
+ /* FIXME: hack to enable spdif support */
+ if (ichdev->ichd == ICHD_PCMOUT && chip->device_type == DEVICE_SIS)
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 && ichdev->page_attr_changed) {
+ if (chip->fix_nocache && substream->runtime->dma_area)
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,
- snd_pcm_runtime_t *runtime)
+ int channels, int sample_bits)
{
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 (runtime->channels == 4 || dbl)
+ if (chip->multi4 && channels == 4)
cnt |= ICH_ALI_SC_PCM_4;
- else if (runtime->channels == 6)
+ else if (chip->multi6 && 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 (runtime->channels == 4 || dbl)
+ if (chip->multi4 && channels == 4)
cnt |= ICH_SIS_PCM_4;
- else if (runtime->channels == 6)
+ else if (chip->multi6 && 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 (runtime->channels == 4 || dbl)
+ if (chip->multi4 && channels == 4)
cnt |= ICH_PCM_4;
- else if (runtime->channels == 6)
+ else if (chip->multi6 && channels == 6)
cnt |= ICH_PCM_6;
if (chip->device_type == DEVICE_NFORCE) {
/* reset to 2ch once to keep the 6 channel data in alignment,
spin_lock_irq(&chip->reg_lock);
}
} else if (chip->device_type == DEVICE_INTEL_ICH4) {
- if (runtime->sample_bits > 16)
+ if (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);
+ snd_intel8x0_setup_pcm_out(chip, runtime->channels,
+ runtime->sample_bits);
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 = "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
- },
{ /* FIXME: which codec? */
.vendor = 0x103c,
.device = 0x00c3,
.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,
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:
- chip->spdif_idx = NVD_SPBAR;
+ spdif_idx = NVD_SPBAR;
break;
case DEVICE_ALI:
- chip->spdif_idx = ALID_AC97SPDIFOUT;
+ spdif_idx = ALID_AC97SPDIFOUT;
break;
- case DEVICE_INTEL_ICH4:
- chip->spdif_idx = ICHD_SPBAR;
+ default:
+ if (chip->device_type == DEVICE_INTEL_ICH4)
+ 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;
i = ARRAY_SIZE(ac97_pcm_defs);
if (chip->device_type != DEVICE_INTEL_ICH4)
i -= 2; /* do not allocate PCM2IN and MIC2 */
- if (chip->spdif_idx < 0)
+ if (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 (chip->spdif_idx >= 0)
- chip->ichd[chip->spdif_idx].pcm = &pbus->pcms[3];
+ if (spdif_idx >= 0)
+ chip->ichd[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[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->ichd[spdif_idx].pcm->rates = SNDRV_PCM_RATE_48000;
}
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]);
- pci_disable_device(chip->pci);
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
return 0;
}
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) {
+ if (ichdev->substream) {
snd_pcm_runtime_t *runtime = ichdev->substream->runtime;
if (runtime->dma_area)
fill_nocache(runtime->dma_area, runtime->dma_bytes, 1);
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) {
- pci_disable_device(pci);
+ if (chip == NULL)
return -ENOMEM;
- }
spin_lock_init(&chip->reg_lock);
spin_lock_init(&chip->ac97_lock);
chip->device_type = device_type;
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 == NULL) {
+ chip->remap_addr = ioremap_nocache(chip->addr, pci_resource_len(pci, 2));
+ if (!chip->remap_addr) {
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 == NULL) {
+ chip->remap_bmaddr = ioremap_nocache(chip->bmaddr, pci_resource_len(pci, 3));
+ if (!chip->remap_bmaddr) {
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);
- 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);
+ sprintf(card->longname, "%s at 0x%lx, irq %i",
+ card->shortname, 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;
+
}
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)