Newer
Older
bdl[3] = rest ? 0 : cpu_to_le32(0x01);
bdl += 4;
azx_dev->frags++;
ofs += size;
} while (rest > 0);
}
/*
* set up the SD for streaming
*/
static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev)
{
unsigned char val;
int timeout;
/* make sure the run bit is zero for SD */
azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) &
~SD_CTL_DMA_START);
azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) |
SD_CTL_STREAM_RESET);
udelay(3);
timeout = 300;
while (!((val = azx_sd_readb(azx_dev, SD_CTL)) & SD_CTL_STREAM_RESET) &&
--timeout)
;
val &= ~SD_CTL_STREAM_RESET;
azx_sd_writeb(azx_dev, SD_CTL, val);
udelay(3);
timeout = 300;
/* waiting for hardware to report that the stream is out of reset */
while (((val = azx_sd_readb(azx_dev, SD_CTL)) & SD_CTL_STREAM_RESET) &&
--timeout)
;
/* program the stream_tag */
azx_sd_writel(azx_dev, SD_CTL,
(azx_sd_readl(azx_dev, SD_CTL) & ~SD_CTL_STREAM_TAG_MASK)|
(azx_dev->stream_tag << SD_CTL_STREAM_TAG_SHIFT));
/* program the length of samples in cyclic buffer */
azx_sd_writel(azx_dev, SD_CBL, azx_dev->bufsize);
/* program the stream format */
/* this value needs to be the same as the one programmed */
azx_sd_writew(azx_dev, SD_FORMAT, azx_dev->format_val);
/* program the stream LVI (last valid index) of the BDL */
azx_sd_writew(azx_dev, SD_LVI, azx_dev->frags - 1);
/* program the BDL address */
/* lower BDL address */
azx_sd_writel(azx_dev, SD_BDLPL, (u32)azx_dev->bdl.addr);
azx_sd_writel(azx_dev, SD_BDLPU, upper_32bit(azx_dev->bdl.addr));
/* enable the position buffer */
if (!(azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE))
azx_writel(chip, DPLBASE,
(u32)chip->posbuf.addr |ICH6_DPLBASE_ENABLE);
/* set the interrupt enable bits in the descriptor control register */
azx_sd_writel(azx_dev, SD_CTL,
azx_sd_readl(azx_dev, SD_CTL) | SD_INT_MASK);
return 0;
}
/*
* Codec initialization
*/
static unsigned int azx_max_codecs[] __devinitdata = {
[AZX_DRIVER_ICH] = 3,
[AZX_DRIVER_ATI] = 4,
[AZX_DRIVER_ATIHDMI] = 4,
[AZX_DRIVER_VIA] = 3, /* FIXME: correct? */
[AZX_DRIVER_SIS] = 3, /* FIXME: correct? */
[AZX_DRIVER_ULI] = 3, /* FIXME: correct? */
[AZX_DRIVER_NVIDIA] = 3, /* FIXME: correct? */
};
static int __devinit azx_codec_create(struct azx *chip, const char *model,
unsigned int codec_probe_mask)
int c, codecs, audio_codecs, err;
memset(&bus_temp, 0, sizeof(bus_temp));
bus_temp.private_data = chip;
bus_temp.modelname = model;
bus_temp.pci = chip->pci;
bus_temp.ops.command = azx_send_cmd;
bus_temp.ops.get_response = azx_get_response;
#ifdef CONFIG_SND_HDA_POWER_SAVE
bus_temp.ops.pm_notify = azx_power_notify;
#endif
err = snd_hda_bus_new(chip->card, &bus_temp, &chip->bus);
if (err < 0)
codecs = audio_codecs = 0;
for (c = 0; c < AZX_MAX_CODECS; c++) {
if ((chip->codec_mask & (1 << c)) & codec_probe_mask) {
struct hda_codec *codec;
err = snd_hda_codec_new(chip->bus, c, &codec);
if (codec->afg)
audio_codecs++;
if (!audio_codecs) {
/* probe additional slots if no codec is found */
for (; c < azx_max_codecs[chip->driver_type]; c++) {
if ((chip->codec_mask & (1 << c)) & codec_probe_mask) {
err = snd_hda_codec_new(chip->bus, c, NULL);
if (err < 0)
continue;
codecs++;
}
}
}
if (!codecs) {
snd_printk(KERN_ERR SFX "no codecs initialized\n");
return -ENXIO;
}
return 0;
}
/*
* PCM support
*/
/* assign a stream for the PCM */
static inline struct azx_dev *azx_assign_device(struct azx *chip, int stream)
int dev, i, nums;
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
dev = chip->playback_index_offset;
nums = chip->playback_streams;
} else {
dev = chip->capture_index_offset;
nums = chip->capture_streams;
}
for (i = 0; i < nums; i++, dev++)
chip->azx_dev[dev].opened = 1;
return &chip->azx_dev[dev];
}
return NULL;
}
/* release the assigned stream */
static inline void azx_release_device(struct azx_dev *azx_dev)
static struct snd_pcm_hardware azx_pcm_hw = {
.info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_MMAP_VALID |
/* No full-resume yet implemented */
/* SNDRV_PCM_INFO_RESUME |*/
SNDRV_PCM_INFO_PAUSE),
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.rates = SNDRV_PCM_RATE_48000,
.rate_min = 48000,
.rate_max = 48000,
.channels_min = 2,
.channels_max = 2,
.buffer_bytes_max = AZX_MAX_BUF_SIZE,
.period_bytes_min = 128,
.period_bytes_max = AZX_MAX_BUF_SIZE / 2,
.periods_min = 2,
.periods_max = AZX_MAX_FRAG,
.fifo_size = 0,
};
struct azx_pcm {
struct hda_codec *codec;
struct hda_pcm_stream *hinfo[2];
};
static int azx_pcm_open(struct snd_pcm_substream *substream)
{
struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream];
struct azx *chip = apcm->chip;
struct azx_dev *azx_dev;
struct snd_pcm_runtime *runtime = substream->runtime;
azx_dev = azx_assign_device(chip, substream->stream);
if (azx_dev == NULL) {
return -EBUSY;
}
runtime->hw = azx_pcm_hw;
runtime->hw.channels_min = hinfo->channels_min;
runtime->hw.channels_max = hinfo->channels_max;
runtime->hw.formats = hinfo->formats;
runtime->hw.rates = hinfo->rates;
snd_pcm_limit_hw_rates(runtime);
snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
128);
snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
128);
err = hinfo->ops.open(hinfo, apcm->codec, substream);
if (err < 0) {
snd_hda_power_down(apcm->codec);
return err;
}
spin_lock_irqsave(&chip->reg_lock, flags);
azx_dev->substream = substream;
azx_dev->running = 0;
spin_unlock_irqrestore(&chip->reg_lock, flags);
runtime->private_data = azx_dev;
static int azx_pcm_close(struct snd_pcm_substream *substream)
{
struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream];
struct azx *chip = apcm->chip;
struct azx_dev *azx_dev = get_azx_dev(substream);
spin_lock_irqsave(&chip->reg_lock, flags);
azx_dev->substream = NULL;
azx_dev->running = 0;
spin_unlock_irqrestore(&chip->reg_lock, flags);
azx_release_device(azx_dev);
hinfo->ops.close(hinfo, apcm->codec, substream);
snd_hda_power_down(apcm->codec);
static int azx_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *hw_params)
return snd_pcm_lib_malloc_pages(substream,
params_buffer_bytes(hw_params));
static int azx_pcm_hw_free(struct snd_pcm_substream *substream)
{
struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
struct azx_dev *azx_dev = get_azx_dev(substream);
struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream];
/* reset BDL address */
azx_sd_writel(azx_dev, SD_BDLPL, 0);
azx_sd_writel(azx_dev, SD_BDLPU, 0);
azx_sd_writel(azx_dev, SD_CTL, 0);
hinfo->ops.cleanup(hinfo, apcm->codec, substream);
return snd_pcm_lib_free_pages(substream);
}
static int azx_pcm_prepare(struct snd_pcm_substream *substream)
{
struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
struct azx *chip = apcm->chip;
struct azx_dev *azx_dev = get_azx_dev(substream);
struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream];
struct snd_pcm_runtime *runtime = substream->runtime;
azx_dev->bufsize = snd_pcm_lib_buffer_bytes(substream);
azx_dev->format_val = snd_hda_calc_stream_format(runtime->rate,
runtime->channels,
runtime->format,
hinfo->maxbps);
if (!azx_dev->format_val) {
snd_printk(KERN_ERR SFX
"invalid format_val, rate=%d, ch=%d, format=%d\n",
runtime->rate, runtime->channels, runtime->format);
return -EINVAL;
}
snd_printdd("azx_pcm_prepare: bufsize=0x%x, format=0x%x\n",
azx_dev->bufsize, azx_dev->format_val);
if (azx_setup_periods(substream, azx_dev) < 0)
return -EINVAL;
azx_setup_controller(chip, azx_dev);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
azx_dev->fifo_size = azx_sd_readw(azx_dev, SD_FIFOSIZE) + 1;
else
azx_dev->fifo_size = 0;
return hinfo->ops.prepare(hinfo, apcm->codec, azx_dev->stream_tag,
azx_dev->format_val, substream);
}
static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{
struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
struct azx_dev *azx_dev = get_azx_dev(substream);
struct azx *chip = apcm->chip;
int err = 0;
spin_lock(&chip->reg_lock);
switch (cmd) {
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_START:
azx_stream_start(chip, azx_dev);
azx_dev->running = 1;
break;
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_STOP:
azx_stream_stop(chip, azx_dev);
azx_dev->running = 0;
break;
default:
err = -EINVAL;
}
spin_unlock(&chip->reg_lock);
if (cmd == SNDRV_PCM_TRIGGER_PAUSE_PUSH ||
cmd == SNDRV_PCM_TRIGGER_SUSPEND ||
cmd == SNDRV_PCM_TRIGGER_STOP) {
int timeout = 5000;
while ((azx_sd_readb(azx_dev, SD_CTL) & SD_CTL_DMA_START) &&
--timeout)
static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream)
struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
struct azx *chip = apcm->chip;
struct azx_dev *azx_dev = get_azx_dev(substream);
if (chip->position_fix == POS_FIX_POSBUF ||
chip->position_fix == POS_FIX_AUTO) {
if (chip->position_fix == POS_FIX_AUTO &&
azx_dev->period_intr == 1 && !pos) {
printk(KERN_WARNING
"hda-intel: Invalid position buffer, "
"using LPIB read method instead.\n");
chip->position_fix = POS_FIX_NONE;
goto read_lpib;
}
/* read LPIB */
pos = azx_sd_readl(azx_dev, SD_LPIB);
if (chip->position_fix == POS_FIX_FIFO)
pos += azx_dev->fifo_size;
}
if (pos >= azx_dev->bufsize)
pos = 0;
return bytes_to_frames(substream->runtime, pos);
}
static struct snd_pcm_ops azx_pcm_ops = {
.open = azx_pcm_open,
.close = azx_pcm_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = azx_pcm_hw_params,
.hw_free = azx_pcm_hw_free,
.prepare = azx_pcm_prepare,
.trigger = azx_pcm_trigger,
.pointer = azx_pcm_pointer,
static void azx_pcm_free(struct snd_pcm *pcm)
static int __devinit create_codec_pcm(struct azx *chip, struct hda_codec *codec,
struct hda_pcm *cpcm)
/* if no substreams are defined for both playback and capture,
* it's just a placeholder. ignore it.
*/
if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams)
return 0;
err = snd_pcm_new(chip->card, cpcm->name, cpcm->device,
cpcm->stream[0].substreams,
cpcm->stream[1].substreams,
&pcm);
if (err < 0)
return err;
strcpy(pcm->name, cpcm->name);
apcm = kmalloc(sizeof(*apcm), GFP_KERNEL);
if (apcm == NULL)
return -ENOMEM;
apcm->chip = chip;
apcm->codec = codec;
apcm->hinfo[0] = &cpcm->stream[0];
apcm->hinfo[1] = &cpcm->stream[1];
pcm->private_data = apcm;
pcm->private_free = azx_pcm_free;
if (cpcm->stream[0].substreams)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &azx_pcm_ops);
if (cpcm->stream[1].substreams)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &azx_pcm_ops);
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
1024 * 64, 1024 * 1024);
chip->pcm[cpcm->device] = pcm;
static int __devinit azx_pcm_create(struct azx *chip)
static const char *dev_name[HDA_PCM_NTYPES] = {
"Audio", "SPDIF", "HDMI", "Modem"
};
/* starting device index for each PCM type */
static int dev_idx[HDA_PCM_NTYPES] = {
[HDA_PCM_TYPE_AUDIO] = 0,
[HDA_PCM_TYPE_SPDIF] = 1,
[HDA_PCM_TYPE_HDMI] = 3,
[HDA_PCM_TYPE_MODEM] = 6
};
/* normal audio device indices; not linear to keep compatibility */
static int audio_idx[4] = { 0, 2, 4, 5 };
int num_devs[HDA_PCM_NTYPES];
err = snd_hda_build_pcms(chip->bus);
if (err < 0)
memset(num_devs, 0, sizeof(num_devs));
list_for_each_entry(codec, &chip->bus->codec_list, list) {
for (c = 0; c < codec->num_pcms; c++) {
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
struct hda_pcm *cpcm = &codec->pcm_info[c];
int type = cpcm->pcm_type;
switch (type) {
case HDA_PCM_TYPE_AUDIO:
if (num_devs[type] >= ARRAY_SIZE(audio_idx)) {
snd_printk(KERN_WARNING
"Too many audio devices\n");
continue;
}
cpcm->device = audio_idx[num_devs[type]];
break;
case HDA_PCM_TYPE_SPDIF:
case HDA_PCM_TYPE_HDMI:
case HDA_PCM_TYPE_MODEM:
if (num_devs[type]) {
snd_printk(KERN_WARNING
"%s already defined\n",
dev_name[type]);
continue;
}
cpcm->device = dev_idx[type];
break;
default:
snd_printk(KERN_WARNING
"Invalid PCM type %d\n", type);
continue;
num_devs[type]++;
err = create_codec_pcm(chip, codec, cpcm);
if (err < 0)
return err;
}
}
return 0;
}
/*
* mixer creation - all stuff is implemented in hda module
*/
static int __devinit azx_mixer_create(struct azx *chip)
{
return snd_hda_build_controls(chip->bus);
}
/*
* initialize SD streams
*/
static int __devinit azx_init_stream(struct azx *chip)
{
int i;
/* initialize each stream (aka device)
* assign the starting bdl address to each stream (device)
* and initialize
for (i = 0; i < chip->num_streams; i++) {
struct azx_dev *azx_dev = &chip->azx_dev[i];
azx_dev->posbuf = (u32 __iomem *)(chip->posbuf.area + i * 8);
/* offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */
azx_dev->sd_addr = chip->remap_addr + (0x20 * i + 0x80);
/* int mask: SDI0=0x01, SDI1=0x02, ... SDO3=0x80 */
azx_dev->sd_int_sta_mask = 1 << i;
/* stream tag: must be non-zero and unique */
azx_dev->index = i;
azx_dev->stream_tag = i + 1;
}
return 0;
}
static int azx_acquire_irq(struct azx *chip, int do_disconnect)
{
if (request_irq(chip->pci->irq, azx_interrupt,
chip->msi ? 0 : IRQF_SHARED,
"HDA Intel", chip)) {
printk(KERN_ERR "hda-intel: unable to grab IRQ %d, "
"disabling device\n", chip->pci->irq);
if (do_disconnect)
snd_card_disconnect(chip->card);
return -1;
}
chip->irq = chip->pci->irq;
pci_intx(chip->pci, !chip->msi);
static void azx_stop_chip(struct azx *chip)
{
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
return;
/* disable interrupts */
azx_int_disable(chip);
azx_int_clear(chip);
/* disable CORB/RIRB */
azx_free_cmd_io(chip);
/* disable position buffer */
azx_writel(chip, DPLBASE, 0);
azx_writel(chip, DPUBASE, 0);
chip->initialized = 0;
}
#ifdef CONFIG_SND_HDA_POWER_SAVE
/* power-up/down the controller */
static void azx_power_notify(struct hda_codec *codec)
{
struct azx *chip = codec->bus->private_data;
struct hda_codec *c;
int power_on = 0;
list_for_each_entry(c, &codec->bus->codec_list, list) {
if (c->power_on) {
power_on = 1;
break;
}
}
if (power_on)
azx_init_chip(chip);
else if (chip->running && power_save_controller)
azx_stop_chip(chip);
}
#endif /* CONFIG_SND_HDA_POWER_SAVE */
#ifdef CONFIG_PM
/*
* power management
*/
static int azx_suspend(struct pci_dev *pci, pm_message_t state)
struct snd_card *card = pci_get_drvdata(pci);
struct azx *chip = card->private_data;
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
for (i = 0; i < AZX_MAX_PCMS; i++)
if (chip->initialized)
snd_hda_suspend(chip->bus, state);
if (chip->irq >= 0) {
synchronize_irq(chip->irq);
free_irq(chip->irq, chip);
chip->irq = -1;
}
pci_disable_msi(chip->pci);
pci_disable_device(pci);
pci_save_state(pci);
pci_set_power_state(pci, pci_choose_state(pci, state));
static int azx_resume(struct pci_dev *pci)
struct snd_card *card = pci_get_drvdata(pci);
struct azx *chip = card->private_data;
pci_set_power_state(pci, PCI_D0);
if (pci_enable_device(pci) < 0) {
printk(KERN_ERR "hda-intel: pci_enable_device failed, "
"disabling device\n");
snd_card_disconnect(card);
return -EIO;
}
pci_set_master(pci);
if (chip->msi)
if (pci_enable_msi(pci) < 0)
chip->msi = 0;
if (azx_acquire_irq(chip, 1) < 0)
return -EIO;
if (snd_hda_codecs_inuse(chip->bus))
azx_init_chip(chip);
snd_power_change_state(card, SNDRV_CTL_POWER_D0);
return 0;
}
#endif /* CONFIG_PM */
/*
* destructor
*/
static int azx_free(struct azx *chip)
for (i = 0; i < chip->num_streams; i++)
synchronize_irq(chip->irq);
pci_disable_msi(chip->pci);
if (chip->remap_addr)
iounmap(chip->remap_addr);
if (chip->azx_dev) {
for (i = 0; i < chip->num_streams; i++)
if (chip->azx_dev[i].bdl.area)
snd_dma_free_pages(&chip->azx_dev[i].bdl);
}
if (chip->rb.area)
snd_dma_free_pages(&chip->rb);
if (chip->posbuf.area)
snd_dma_free_pages(&chip->posbuf);
pci_release_regions(chip->pci);
pci_disable_device(chip->pci);
static int azx_dev_free(struct snd_device *device)
{
return azx_free(device->device_data);
}
/*
* white/black-listing for position_fix
*/
static struct snd_pci_quirk position_fix_list[] __devinitdata = {
SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_NONE),
SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_NONE),
{}
};
static int __devinit check_position_fix(struct azx *chip, int fix)
{
const struct snd_pci_quirk *q;
if (fix == POS_FIX_AUTO) {
q = snd_pci_quirk_lookup(chip->pci, position_fix_list);
if (q) {
"hda_intel: position_fix set to %d "
"for device %04x:%04x\n",
q->value, q->subvendor, q->subdevice);
return q->value;
}
}
return fix;
}
/*
* black-lists for probe_mask
*/
static struct snd_pci_quirk probe_mask_list[] __devinitdata = {
/* 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),
{}
};
static void __devinit check_probe_mask(struct azx *chip, int dev)
{
const struct snd_pci_quirk *q;
if (probe_mask[dev] == -1) {
q = snd_pci_quirk_lookup(chip->pci, probe_mask_list);
if (q) {
printk(KERN_INFO
"hda_intel: probe_mask set to 0x%x "
"for device %04x:%04x\n",
q->value, q->subvendor, q->subdevice);
static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
static struct snd_device_ops ops = {
.dev_free = azx_dev_free,
};
*rchip = NULL;
err = pci_enable_device(pci);
if (err < 0)
chip = kzalloc(sizeof(*chip), GFP_KERNEL);
snd_printk(KERN_ERR SFX "cannot allocate chip\n");
pci_disable_device(pci);
return -ENOMEM;
}
spin_lock_init(&chip->reg_lock);
chip->card = card;
chip->pci = pci;
chip->irq = -1;
chip->driver_type = driver_type;
chip->msi = enable_msi;
chip->position_fix = check_position_fix(chip, position_fix[dev]);
check_probe_mask(chip, dev);
chip->single_cmd = single_cmd;
#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");
if (err < 0) {
kfree(chip);
pci_disable_device(pci);
return err;
}
chip->addr = pci_resource_start(pci, 0);
chip->remap_addr = ioremap_nocache(chip->addr, pci_resource_len(pci,0));
if (chip->remap_addr == NULL) {
snd_printk(KERN_ERR SFX "ioremap error\n");
err = -ENXIO;
goto errout;
}
if (chip->msi)
if (pci_enable_msi(pci) < 0)
chip->msi = 0;
if (azx_acquire_irq(chip, 0) < 0) {
err = -EBUSY;
goto errout;
}
pci_set_master(pci);
synchronize_irq(chip->irq);
gcap = azx_readw(chip, GCAP);
snd_printdd("chipset global capabilities = 0x%x\n", gcap);
/* allow 64bit DMA address if supported by H/W */
if ((gcap & 0x01) && !pci_set_dma_mask(pci, DMA_64BIT_MASK))
pci_set_consistent_dma_mask(pci, DMA_64BIT_MASK);
/* 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;
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);
snd_printk(KERN_ERR "cannot malloc azx_dev\n");
goto errout;
}
for (i = 0; i < chip->num_streams; i++) {
/* allocate memory for the BDL for each stream */
err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
snd_dma_pci_data(chip->pci),
BDL_SIZE, &chip->azx_dev[i].bdl);
if (err < 0) {
snd_printk(KERN_ERR SFX "cannot allocate BDL\n");
goto errout;
}
/* allocate memory for the position buffer */
err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
snd_dma_pci_data(chip->pci),
chip->num_streams * 8, &chip->posbuf);
if (err < 0) {
snd_printk(KERN_ERR SFX "cannot allocate posbuf\n");
goto errout;
if (!chip->single_cmd) {
err = azx_alloc_cmd_io(chip);
if (err < 0)
/* initialize streams */
azx_init_stream(chip);
/* initialize chip */
snd_printk(KERN_ERR SFX "no codecs found!\n");
err = -ENODEV;
goto errout;
}
err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
if (err <0) {
snd_printk(KERN_ERR SFX "Error creating device [card]!\n");
goto errout;
}
strcpy(card->driver, "HDA-Intel");
strcpy(card->shortname, driver_short_names[chip->driver_type]);
sprintf(card->longname, "%s at 0x%lx irq %i",
card->shortname, chip->addr, chip->irq);
*rchip = chip;
return 0;
errout:
azx_free(chip);
return err;
}
static void power_down_all_codecs(struct azx *chip)
{
#ifdef CONFIG_SND_HDA_POWER_SAVE
/* 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
}
static int __devinit azx_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
struct snd_card *card;
struct azx *chip;
if (dev >= SNDRV_CARDS)
return -ENODEV;
if (!enable[dev]) {
dev++;
return -ENOENT;
}
card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
snd_printk(KERN_ERR SFX "Error creating card!\n");
return -ENOMEM;
}
err = azx_create(card, pci, dev, pci_id->driver_data, &chip);
err = azx_codec_create(chip, model[dev], probe_mask[dev]);
snd_card_free(card);
return err;
}
/* create PCM streams */
err = azx_pcm_create(chip);
if (err < 0) {
snd_card_free(card);
return err;
}
/* create mixer controls */
err = azx_mixer_create(chip);
if (err < 0) {
snd_card_free(card);
return err;
}
snd_card_set_dev(card, &pci->dev);
err = snd_card_register(card);
if (err < 0) {