diff options
author | Takashi Iwai <tiwai@suse.de> | 2008-02-06 08:50:19 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2008-04-24 06:00:08 -0400 |
commit | 4ce107b990d994a0fccea9b1e885b08a0daea495 (patch) | |
tree | ee2ddb3f4a659c8ec8b004424c3b75ac7e3fc5d0 /sound | |
parent | b76c850fbc280d6c0ff786653915f3a9700b5912 (diff) |
[ALSA] hda-intel - Use SG buffer
Use SG buffers for the HD-audio instead of linear buffers.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/pci/hda/hda_intel.c | 114 |
1 files changed, 71 insertions, 43 deletions
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 18475de074b2..b38a5a70ff08 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -206,8 +206,9 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; | |||
206 | #define MAX_AZX_DEV 16 | 206 | #define MAX_AZX_DEV 16 |
207 | 207 | ||
208 | /* max number of fragments - we may use more if allocating more pages for BDL */ | 208 | /* max number of fragments - we may use more if allocating more pages for BDL */ |
209 | #define BDL_SIZE PAGE_ALIGN(8192) | 209 | #define BDL_SIZE 4096 |
210 | #define AZX_MAX_FRAG (BDL_SIZE / (MAX_AZX_DEV * 16)) | 210 | #define AZX_MAX_BDL_ENTRIES (BDL_SIZE / 16) |
211 | #define AZX_MAX_FRAG 32 | ||
211 | /* max buffer size - no h/w limit, you can increase as you like */ | 212 | /* max buffer size - no h/w limit, you can increase as you like */ |
212 | #define AZX_MAX_BUF_SIZE (1024*1024*1024) | 213 | #define AZX_MAX_BUF_SIZE (1024*1024*1024) |
213 | /* max number of PCM devics per card */ | 214 | /* max number of PCM devics per card */ |
@@ -282,12 +283,10 @@ enum { | |||
282 | */ | 283 | */ |
283 | 284 | ||
284 | struct azx_dev { | 285 | struct azx_dev { |
285 | u32 *bdl; /* virtual address of the BDL */ | 286 | struct snd_dma_buffer bdl; /* BDL buffer */ |
286 | dma_addr_t bdl_addr; /* physical address of the BDL */ | ||
287 | u32 *posbuf; /* position buffer pointer */ | 287 | u32 *posbuf; /* position buffer pointer */ |
288 | 288 | ||
289 | unsigned int bufsize; /* size of the play buffer in bytes */ | 289 | unsigned int bufsize; /* size of the play buffer in bytes */ |
290 | unsigned int fragsize; /* size of each period in bytes */ | ||
291 | unsigned int frags; /* number for period in the play buffer */ | 290 | unsigned int frags; /* number for period in the play buffer */ |
292 | unsigned int fifo_size; /* FIFO size */ | 291 | unsigned int fifo_size; /* FIFO size */ |
293 | 292 | ||
@@ -358,8 +357,7 @@ struct azx { | |||
358 | struct azx_rb corb; | 357 | struct azx_rb corb; |
359 | struct azx_rb rirb; | 358 | struct azx_rb rirb; |
360 | 359 | ||
361 | /* BDL, CORB/RIRB and position buffers */ | 360 | /* CORB/RIRB and position buffers */ |
362 | struct snd_dma_buffer bdl; | ||
363 | struct snd_dma_buffer rb; | 361 | struct snd_dma_buffer rb; |
364 | struct snd_dma_buffer posbuf; | 362 | struct snd_dma_buffer posbuf; |
365 | 363 | ||
@@ -962,30 +960,57 @@ static irqreturn_t azx_interrupt(int irq, void *dev_id) | |||
962 | /* | 960 | /* |
963 | * set up BDL entries | 961 | * set up BDL entries |
964 | */ | 962 | */ |
965 | static void azx_setup_periods(struct azx_dev *azx_dev) | 963 | static int azx_setup_periods(struct snd_pcm_substream *substream, |
964 | struct azx_dev *azx_dev) | ||
966 | { | 965 | { |
967 | u32 *bdl = azx_dev->bdl; | 966 | struct snd_sg_buf *sgbuf = snd_pcm_substream_sgbuf(substream); |
968 | dma_addr_t dma_addr = azx_dev->substream->runtime->dma_addr; | 967 | u32 *bdl; |
969 | int idx; | 968 | int i, ofs, periods, period_bytes; |
970 | 969 | ||
971 | /* reset BDL address */ | 970 | /* reset BDL address */ |
972 | azx_sd_writel(azx_dev, SD_BDLPL, 0); | 971 | azx_sd_writel(azx_dev, SD_BDLPL, 0); |
973 | azx_sd_writel(azx_dev, SD_BDLPU, 0); | 972 | azx_sd_writel(azx_dev, SD_BDLPU, 0); |
974 | 973 | ||
974 | period_bytes = snd_pcm_lib_period_bytes(substream); | ||
975 | periods = azx_dev->bufsize / period_bytes; | ||
976 | |||
975 | /* program the initial BDL entries */ | 977 | /* program the initial BDL entries */ |
976 | for (idx = 0; idx < azx_dev->frags; idx++) { | 978 | bdl = (u32 *)azx_dev->bdl.area; |
977 | unsigned int off = idx << 2; /* 4 dword step */ | 979 | ofs = 0; |
978 | dma_addr_t addr = dma_addr + idx * azx_dev->fragsize; | 980 | azx_dev->frags = 0; |
979 | /* program the address field of the BDL entry */ | 981 | for (i = 0; i < periods; i++) { |
980 | bdl[off] = cpu_to_le32((u32)addr); | 982 | int size, rest; |
981 | bdl[off+1] = cpu_to_le32(upper_32bit(addr)); | 983 | if (i >= AZX_MAX_BDL_ENTRIES) { |
982 | 984 | snd_printk(KERN_ERR "Too many BDL entries: " | |
983 | /* program the size field of the BDL entry */ | 985 | "buffer=%d, period=%d\n", |
984 | bdl[off+2] = cpu_to_le32(azx_dev->fragsize); | 986 | azx_dev->bufsize, period_bytes); |
985 | 987 | /* reset */ | |
986 | /* program the IOC to enable interrupt when buffer completes */ | 988 | azx_sd_writel(azx_dev, SD_BDLPL, 0); |
987 | bdl[off+3] = cpu_to_le32(0x01); | 989 | azx_sd_writel(azx_dev, SD_BDLPU, 0); |
990 | return -EINVAL; | ||
991 | } | ||
992 | rest = period_bytes; | ||
993 | do { | ||
994 | dma_addr_t addr = snd_pcm_sgbuf_get_addr(sgbuf, ofs); | ||
995 | /* program the address field of the BDL entry */ | ||
996 | bdl[0] = cpu_to_le32((u32)addr); | ||
997 | bdl[1] = cpu_to_le32(upper_32bit(addr)); | ||
998 | /* program the size field of the BDL entry */ | ||
999 | size = PAGE_SIZE - (ofs % PAGE_SIZE); | ||
1000 | if (rest < size) | ||
1001 | size = rest; | ||
1002 | bdl[2] = cpu_to_le32(size); | ||
1003 | /* program the IOC to enable interrupt | ||
1004 | * only when the whole fragment is processed | ||
1005 | */ | ||
1006 | rest -= size; | ||
1007 | bdl[3] = rest ? 0 : cpu_to_le32(0x01); | ||
1008 | bdl += 4; | ||
1009 | azx_dev->frags++; | ||
1010 | ofs += size; | ||
1011 | } while (rest > 0); | ||
988 | } | 1012 | } |
1013 | return 0; | ||
989 | } | 1014 | } |
990 | 1015 | ||
991 | /* | 1016 | /* |
@@ -1034,9 +1059,9 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev) | |||
1034 | 1059 | ||
1035 | /* program the BDL address */ | 1060 | /* program the BDL address */ |
1036 | /* lower BDL address */ | 1061 | /* lower BDL address */ |
1037 | azx_sd_writel(azx_dev, SD_BDLPL, (u32)azx_dev->bdl_addr); | 1062 | azx_sd_writel(azx_dev, SD_BDLPL, (u32)azx_dev->bdl.addr); |
1038 | /* upper BDL address */ | 1063 | /* upper BDL address */ |
1039 | azx_sd_writel(azx_dev, SD_BDLPU, upper_32bit(azx_dev->bdl_addr)); | 1064 | azx_sd_writel(azx_dev, SD_BDLPU, upper_32bit(azx_dev->bdl.addr)); |
1040 | 1065 | ||
1041 | /* enable the position buffer */ | 1066 | /* enable the position buffer */ |
1042 | if (!(azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE)) | 1067 | if (!(azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE)) |
@@ -1272,8 +1297,6 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) | |||
1272 | struct snd_pcm_runtime *runtime = substream->runtime; | 1297 | struct snd_pcm_runtime *runtime = substream->runtime; |
1273 | 1298 | ||
1274 | azx_dev->bufsize = snd_pcm_lib_buffer_bytes(substream); | 1299 | azx_dev->bufsize = snd_pcm_lib_buffer_bytes(substream); |
1275 | azx_dev->fragsize = snd_pcm_lib_period_bytes(substream); | ||
1276 | azx_dev->frags = azx_dev->bufsize / azx_dev->fragsize; | ||
1277 | azx_dev->format_val = snd_hda_calc_stream_format(runtime->rate, | 1300 | azx_dev->format_val = snd_hda_calc_stream_format(runtime->rate, |
1278 | runtime->channels, | 1301 | runtime->channels, |
1279 | runtime->format, | 1302 | runtime->format, |
@@ -1288,7 +1311,8 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) | |||
1288 | snd_printdd("azx_pcm_prepare: bufsize=0x%x, fragsize=0x%x, " | 1311 | snd_printdd("azx_pcm_prepare: bufsize=0x%x, fragsize=0x%x, " |
1289 | "format=0x%x\n", | 1312 | "format=0x%x\n", |
1290 | azx_dev->bufsize, azx_dev->fragsize, azx_dev->format_val); | 1313 | azx_dev->bufsize, azx_dev->fragsize, azx_dev->format_val); |
1291 | azx_setup_periods(azx_dev); | 1314 | if (azx_setup_periods(substream, azx_dev) < 0) |
1315 | return -EINVAL; | ||
1292 | azx_setup_controller(chip, azx_dev); | 1316 | azx_setup_controller(chip, azx_dev); |
1293 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 1317 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
1294 | azx_dev->fifo_size = azx_sd_readw(azx_dev, SD_FIFOSIZE) + 1; | 1318 | azx_dev->fifo_size = azx_sd_readw(azx_dev, SD_FIFOSIZE) + 1; |
@@ -1375,6 +1399,7 @@ static struct snd_pcm_ops azx_pcm_ops = { | |||
1375 | .prepare = azx_pcm_prepare, | 1399 | .prepare = azx_pcm_prepare, |
1376 | .trigger = azx_pcm_trigger, | 1400 | .trigger = azx_pcm_trigger, |
1377 | .pointer = azx_pcm_pointer, | 1401 | .pointer = azx_pcm_pointer, |
1402 | .page = snd_pcm_sgbuf_ops_page, | ||
1378 | }; | 1403 | }; |
1379 | 1404 | ||
1380 | static void azx_pcm_free(struct snd_pcm *pcm) | 1405 | static void azx_pcm_free(struct snd_pcm *pcm) |
@@ -1417,7 +1442,7 @@ static int __devinit create_codec_pcm(struct azx *chip, struct hda_codec *codec, | |||
1417 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &azx_pcm_ops); | 1442 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &azx_pcm_ops); |
1418 | if (cpcm->stream[1].substreams) | 1443 | if (cpcm->stream[1].substreams) |
1419 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &azx_pcm_ops); | 1444 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &azx_pcm_ops); |
1420 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, | 1445 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, |
1421 | snd_dma_pci_data(chip->pci), | 1446 | snd_dma_pci_data(chip->pci), |
1422 | 1024 * 64, 1024 * 1024); | 1447 | 1024 * 64, 1024 * 1024); |
1423 | chip->pcm[cpcm->device] = pcm; | 1448 | chip->pcm[cpcm->device] = pcm; |
@@ -1507,10 +1532,7 @@ static int __devinit azx_init_stream(struct azx *chip) | |||
1507 | * and initialize | 1532 | * and initialize |
1508 | */ | 1533 | */ |
1509 | for (i = 0; i < chip->num_streams; i++) { | 1534 | for (i = 0; i < chip->num_streams; i++) { |
1510 | unsigned int off = sizeof(u32) * (i * AZX_MAX_FRAG * 4); | ||
1511 | struct azx_dev *azx_dev = &chip->azx_dev[i]; | 1535 | struct azx_dev *azx_dev = &chip->azx_dev[i]; |
1512 | azx_dev->bdl = (u32 *)(chip->bdl.area + off); | ||
1513 | azx_dev->bdl_addr = chip->bdl.addr + off; | ||
1514 | azx_dev->posbuf = (u32 __iomem *)(chip->posbuf.area + i * 8); | 1536 | azx_dev->posbuf = (u32 __iomem *)(chip->posbuf.area + i * 8); |
1515 | /* offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */ | 1537 | /* offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */ |
1516 | azx_dev->sd_addr = chip->remap_addr + (0x20 * i + 0x80); | 1538 | azx_dev->sd_addr = chip->remap_addr + (0x20 * i + 0x80); |
@@ -1646,8 +1668,9 @@ static int azx_resume(struct pci_dev *pci) | |||
1646 | */ | 1668 | */ |
1647 | static int azx_free(struct azx *chip) | 1669 | static int azx_free(struct azx *chip) |
1648 | { | 1670 | { |
1671 | int i; | ||
1672 | |||
1649 | if (chip->initialized) { | 1673 | if (chip->initialized) { |
1650 | int i; | ||
1651 | for (i = 0; i < chip->num_streams; i++) | 1674 | for (i = 0; i < chip->num_streams; i++) |
1652 | azx_stream_stop(chip, &chip->azx_dev[i]); | 1675 | azx_stream_stop(chip, &chip->azx_dev[i]); |
1653 | azx_stop_chip(chip); | 1676 | azx_stop_chip(chip); |
@@ -1662,8 +1685,11 @@ static int azx_free(struct azx *chip) | |||
1662 | if (chip->remap_addr) | 1685 | if (chip->remap_addr) |
1663 | iounmap(chip->remap_addr); | 1686 | iounmap(chip->remap_addr); |
1664 | 1687 | ||
1665 | if (chip->bdl.area) | 1688 | if (chip->azx_dev) { |
1666 | snd_dma_free_pages(&chip->bdl); | 1689 | for (i = 0; i < chip->num_streams; i++) |
1690 | if (chip->azx_dev[i].bdl.area) | ||
1691 | snd_dma_free_pages(&chip->azx_dev[i].bdl); | ||
1692 | } | ||
1667 | if (chip->rb.area) | 1693 | if (chip->rb.area) |
1668 | snd_dma_free_pages(&chip->rb); | 1694 | snd_dma_free_pages(&chip->rb); |
1669 | if (chip->posbuf.area) | 1695 | if (chip->posbuf.area) |
@@ -1745,7 +1771,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, | |||
1745 | struct azx **rchip) | 1771 | struct azx **rchip) |
1746 | { | 1772 | { |
1747 | struct azx *chip; | 1773 | struct azx *chip; |
1748 | int err; | 1774 | int i, err; |
1749 | unsigned short gcap; | 1775 | unsigned short gcap; |
1750 | static struct snd_device_ops ops = { | 1776 | static struct snd_device_ops ops = { |
1751 | .dev_free = azx_dev_free, | 1777 | .dev_free = azx_dev_free, |
@@ -1857,13 +1883,15 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, | |||
1857 | goto errout; | 1883 | goto errout; |
1858 | } | 1884 | } |
1859 | 1885 | ||
1860 | /* allocate memory for the BDL for each stream */ | 1886 | for (i = 0; i < chip->num_streams; i++) { |
1861 | err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, | 1887 | /* allocate memory for the BDL for each stream */ |
1862 | snd_dma_pci_data(chip->pci), | 1888 | err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, |
1863 | BDL_SIZE, &chip->bdl); | 1889 | snd_dma_pci_data(chip->pci), |
1864 | if (err < 0) { | 1890 | BDL_SIZE, &chip->azx_dev[i].bdl); |
1865 | snd_printk(KERN_ERR SFX "cannot allocate BDL\n"); | 1891 | if (err < 0) { |
1866 | goto errout; | 1892 | snd_printk(KERN_ERR SFX "cannot allocate BDL\n"); |
1893 | goto errout; | ||
1894 | } | ||
1867 | } | 1895 | } |
1868 | /* allocate memory for the position buffer */ | 1896 | /* allocate memory for the position buffer */ |
1869 | err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, | 1897 | err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, |