From 0be3b5d3fb94c36c517655d18a936681d7108667 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 5 Sep 2005 17:11:40 +0200 Subject: [ALSA] hda-intel - Check validity of DMA position HDA Intel driver Check the validity of the current DMA position when position_fix=0 (auto) is set. If the DMA position overcomes the threshold, the driver changes the fix behavior automatically to use POSBUF. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_intel.c | 63 ++++++++++++++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 22 deletions(-) (limited to 'sound/pci/hda/hda_intel.c') diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 15107df1f49..96f9e872919 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -62,7 +62,7 @@ MODULE_PARM_DESC(enable, "Enable Intel HD audio interface."); module_param_array(model, charp, NULL, 0444); MODULE_PARM_DESC(model, "Use the given board model."); module_param_array(position_fix, int, NULL, 0444); -MODULE_PARM_DESC(position_fix, "Fix DMA pointer (0 = FIFO size, 1 = none, 2 = POSBUF)."); +MODULE_PARM_DESC(position_fix, "Fix DMA pointer (0 = auto, 1 = none, 2 = POSBUF, 3 = FIFO size)."); MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("{{Intel, ICH6}," @@ -211,9 +211,10 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; /* position fix mode */ enum { - POS_FIX_FIFO, + POS_FIX_AUTO, POS_FIX_NONE, - POS_FIX_POSBUF + POS_FIX_POSBUF, + POS_FIX_FIFO, }; /* Defines for ATI HD Audio support in SB450 south bridge */ @@ -243,6 +244,7 @@ struct snd_azx_dev { unsigned int fragsize; /* size of each period in bytes */ unsigned int frags; /* number for period in the play buffer */ unsigned int fifo_size; /* FIFO size */ + unsigned int last_pos; /* last updated period position */ void __iomem *sd_addr; /* stream descriptor pointer */ @@ -256,6 +258,7 @@ struct snd_azx_dev { unsigned int opened: 1; unsigned int running: 1; + unsigned int period_updating: 1; }; /* CORB/RIRB */ @@ -724,11 +727,9 @@ static void azx_init_chip(azx_t *chip) /* initialize the codec command I/O */ azx_init_cmd_io(chip); - if (chip->position_fix == POS_FIX_POSBUF) { - /* program the position buffer */ - azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr); - azx_writel(chip, DPUBASE, upper_32bit(chip->posbuf.addr)); - } + /* program the position buffer */ + azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr); + azx_writel(chip, DPUBASE, upper_32bit(chip->posbuf.addr)); /* For ATI SB450 azalia HD audio, we need to enable snoop */ if (chip->driver_type == AZX_DRIVER_ATI) { @@ -763,9 +764,11 @@ static irqreturn_t azx_interrupt(int irq, void* dev_id, struct pt_regs *regs) if (status & azx_dev->sd_int_sta_mask) { azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK); if (azx_dev->substream && azx_dev->running) { + azx_dev->period_updating = 1; spin_unlock(&chip->reg_lock); snd_pcm_period_elapsed(azx_dev->substream); spin_lock(&chip->reg_lock); + azx_dev->period_updating = 0; } } } @@ -866,11 +869,9 @@ static int azx_setup_controller(azx_t *chip, azx_dev_t *azx_dev) /* upper BDL address */ azx_sd_writel(azx_dev, SD_BDLPU, upper_32bit(azx_dev->bdl_addr)); - if (chip->position_fix == POS_FIX_POSBUF) { - /* enable the position buffer */ - if (! (azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE)) - azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE); - } + /* 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); @@ -1078,6 +1079,7 @@ static int azx_pcm_prepare(snd_pcm_substream_t *substream) azx_dev->fifo_size = azx_sd_readw(azx_dev, SD_FIFOSIZE) + 1; else azx_dev->fifo_size = 0; + azx_dev->last_pos = 0; return hinfo->ops.prepare(hinfo, apcm->codec, azx_dev->stream_tag, azx_dev->format_val, substream); @@ -1133,6 +1135,26 @@ static snd_pcm_uframes_t azx_pcm_pointer(snd_pcm_substream_t *substream) pos = azx_sd_readl(azx_dev, SD_LPIB); if (chip->position_fix == POS_FIX_FIFO) pos += azx_dev->fifo_size; + else if (chip->position_fix == POS_FIX_AUTO && azx_dev->period_updating) { + /* check the validity of DMA position */ + unsigned int diff = 0; + azx_dev->last_pos += azx_dev->fragsize; + if (azx_dev->last_pos > pos) + diff = azx_dev->last_pos - pos; + if (azx_dev->last_pos >= azx_dev->bufsize) { + if (pos < azx_dev->fragsize) + diff = 0; + azx_dev->last_pos = 0; + } + if (diff > 0 && diff <= azx_dev->fifo_size) + pos += azx_dev->fifo_size; + else { + snd_printdd(KERN_INFO "hda_intel: DMA position fix %d, switching to posbuf\n", diff); + chip->position_fix = POS_FIX_POSBUF; + pos = *azx_dev->posbuf; + } + azx_dev->period_updating = 0; + } } if (pos >= azx_dev->bufsize) pos = 0; @@ -1244,8 +1266,7 @@ static int __devinit azx_init_stream(azx_t *chip) azx_dev_t *azx_dev = &chip->azx_dev[i]; azx_dev->bdl = (u32 *)(chip->bdl.area + off); azx_dev->bdl_addr = chip->bdl.addr + off; - if (chip->position_fix == POS_FIX_POSBUF) - azx_dev->posbuf = (volatile u32 *)(chip->posbuf.area + i * 8); + azx_dev->posbuf = (volatile u32 *)(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 */ @@ -1437,13 +1458,11 @@ static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci, snd_printk(KERN_ERR SFX "cannot allocate BDL\n"); goto errout; } - if (chip->position_fix == POS_FIX_POSBUF) { - /* allocate memory for the position buffer */ - if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci), - chip->num_streams * 8, &chip->posbuf)) < 0) { - snd_printk(KERN_ERR SFX "cannot allocate posbuf\n"); - goto errout; - } + /* allocate memory for the position buffer */ + if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci), + chip->num_streams * 8, &chip->posbuf)) < 0) { + snd_printk(KERN_ERR SFX "cannot allocate posbuf\n"); + goto errout; } /* allocate CORB/RIRB */ if ((err = azx_alloc_cmd_io(chip)) < 0) -- cgit v1.2.3 From ec9e1c5c9c7350cc8214f8b9c529f9678036d9a8 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 7 Sep 2005 13:29:22 +0200 Subject: [ALSA] hda-codec - Assign audio PCMS first HDA Codec driver,HDA Intel driver,HDA generic driver Assign audio PCMs first before modem PCMs. The modem stream is assigned up to device #6, to be consistent over different models. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_intel.c | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) (limited to 'sound/pci/hda/hda_intel.c') diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 96f9e872919..2098de7c567 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -164,7 +164,9 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; /* max buffer size - no h/w limit, you can increase as you like */ #define AZX_MAX_BUF_SIZE (1024*1024*1024) /* max number of PCM devics per card */ -#define AZX_MAX_PCMS 8 +#define AZX_MAX_AUDIO_PCMS 6 +#define AZX_MAX_MODEM_PCMS 2 +#define AZX_MAX_PCMS (AZX_MAX_AUDIO_PCMS + AZX_MAX_MODEM_PCMS) /* RIRB int mask: overrun[2], response[0] */ #define RIRB_INT_RESPONSE 0x01 @@ -1225,12 +1227,33 @@ static int __devinit azx_pcm_create(azx_t *chip) if ((err = snd_hda_build_pcms(chip->bus)) < 0) return err; + /* create audio PCMs */ pcm_dev = 0; list_for_each(p, &chip->bus->codec_list) { codec = list_entry(p, struct hda_codec, list); for (c = 0; c < codec->num_pcms; c++) { - if (pcm_dev >= AZX_MAX_PCMS) { - snd_printk(KERN_ERR SFX "Too many PCMs\n"); + if (codec->pcm_info[c].is_modem) + continue; /* create later */ + if (pcm_dev >= AZX_MAX_AUDIO_PCMS) { + snd_printk(KERN_ERR SFX "Too many audio PCMs\n"); + return -EINVAL; + } + err = create_codec_pcm(chip, codec, &codec->pcm_info[c], pcm_dev); + if (err < 0) + return err; + pcm_dev++; + } + } + + /* create modem PCMs */ + pcm_dev = AZX_MAX_AUDIO_PCMS; + list_for_each(p, &chip->bus->codec_list) { + codec = list_entry(p, struct hda_codec, list); + for (c = 0; c < codec->num_pcms; c++) { + if (! codec->pcm_info[c].is_modem) + continue; /* already created */ + if (pcm_dev >= AZX_MAX_MODEM_PCMS) { + snd_printk(KERN_ERR SFX "Too many modem PCMs\n"); return -EINVAL; } err = create_codec_pcm(chip, codec, &codec->pcm_info[c], pcm_dev); -- cgit v1.2.3 From a28f1cda0d01f6f98e3bef6a07c483a90f6a35d6 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 7 Sep 2005 15:26:56 +0200 Subject: [ALSA] hda-intel - Fix modem PCM creation HDA Intel driver Fix a bug of modem PCM creation (due to a typo). Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_intel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/pci/hda/hda_intel.c') diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 2098de7c567..a8eaeb463b0 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -1252,7 +1252,7 @@ static int __devinit azx_pcm_create(azx_t *chip) for (c = 0; c < codec->num_pcms; c++) { if (! codec->pcm_info[c].is_modem) continue; /* already created */ - if (pcm_dev >= AZX_MAX_MODEM_PCMS) { + if (pcm_dev >= AZX_MAX_PCMS) { snd_printk(KERN_ERR SFX "Too many modem PCMs\n"); return -EINVAL; } -- cgit v1.2.3 From e560d8d8368ad8b6161839984b253de622863265 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 9 Sep 2005 14:21:46 +0200 Subject: [ALSA] Replace with kzalloc() - pci stuff AD1889 driver,ATIIXP driver,ATIIXP-modem driver,AZT3328 driver BT87x driver,CMIPCI driver,CS4281 driver,ENS1370/1+ driver ES1938 driver,ES1968 driver,FM801 driver,Intel8x0 driver Intel8x0-modem driver,Maestro3 driver,SonicVibes driver,VIA82xx driver VIA82xx-modem driver,AC97 Codec,AK4531 codec,au88x0 driver CA0106 driver,CS46xx driver,EMU10K1/EMU10K2 driver,HDA Codec driver HDA generic driver,HDA Intel driver,ICE1712 driver,ICE1724 driver KORG1212 driver,MIXART driver,NM256 driver,Trident driver,YMFPCI driver Replace kcalloc(1,..) with kzalloc(). Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_intel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/pci/hda/hda_intel.c') diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index a8eaeb463b0..7e0c05936c3 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -1402,7 +1402,7 @@ static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci, if ((err = pci_enable_device(pci)) < 0) return err; - chip = kcalloc(1, sizeof(*chip), GFP_KERNEL); + chip = kzalloc(sizeof(*chip), GFP_KERNEL); if (NULL == chip) { snd_printk(KERN_ERR SFX "cannot allocate chip\n"); -- cgit v1.2.3 From 3bcd4649bca99ee9242f20d7da35e3f8741c6549 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Mon, 12 Sep 2005 08:20:54 +0200 Subject: [ALSA] set owner field in struct pci_driver AD1889 driver,ALS4000 driver,ATIIXP driver,ATIIXP-modem driver AZT3328 driver,BT87x driver,CMIPCI driver,CS4281 driver ENS1370/1+ driver,ES1938 driver,ES1968 driver,FM801 driver Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,RME32 driver RME96 driver,SonicVibes driver,VIA82xx driver,VIA82xx-modem driver ALI5451 driver,au88x0 driver,CS46xx driver,EMU10K1/EMU10K2 driver HDA Intel driver,ICE1712 driver,ICE1724 driver,KORG1212 driver MIXART driver,NM256 driver,RME HDSP driver,RME9652 driver Trident driver,Digigram VX222 driver,YMFPCI driver Set the module owner field in each driver's struct pci_driver to get the driver symlink in the sysfs device directory. Signed-off-by: Clemens Ladisch --- sound/pci/hda/hda_intel.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound/pci/hda/hda_intel.c') diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 7e0c05936c3..9590ece2099 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -1603,6 +1603,7 @@ MODULE_DEVICE_TABLE(pci, azx_ids); /* pci_driver definition */ static struct pci_driver driver = { .name = "HDA Intel", + .owner = THIS_MODULE, .id_table = azx_ids, .probe = azx_probe, .remove = __devexit_p(azx_remove), -- cgit v1.2.3