aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci
diff options
context:
space:
mode:
authorShahin Ghazinouri <shahin.ghazinouri@pelagicore.com>2010-05-11 02:19:55 -0400
committerTakashi Iwai <tiwai@suse.de>2010-05-11 02:21:33 -0400
commitbeaffc399397eb9427225f37c1e56c099571b2df (patch)
treee9452284c4e3a5c0624dbc2c98482cd6fcbfe2b9 /sound/pci
parent5433137336b049f1de8fc9a393991a49f1c1eb66 (diff)
ALSA: hda - Fixes distorted recording on US15W chipset
The HDA controller in US15W (Poulsbo) reports inaccurate position values for capture streams when using the LPIB read method, resulting in distorted recordings. However, using the position buffer is broken for playback streams, resulting in a fallback to the LPIB method with the current driver. This patch works around the issue by independently detecting the read position method for capture and playback streams. The patch will not have any effect if the position fix method is explicitly set. [Code simplified by tiwai] Signed-off-by: Shahin Ghazinouri <shahin.ghazinouri@pelagicore.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci')
-rw-r--r--sound/pci/hda/hda_intel.c36
1 files changed, 22 insertions, 14 deletions
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 236b4caa142..cad9b70c27a 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -425,7 +425,7 @@ struct azx {
425 struct snd_dma_buffer posbuf; 425 struct snd_dma_buffer posbuf;
426 426
427 /* flags */ 427 /* flags */
428 int position_fix; 428 int position_fix[2]; /* for both playback/capture streams */
429 int poll_count; 429 int poll_count;
430 unsigned int running :1; 430 unsigned int running :1;
431 unsigned int initialized :1; 431 unsigned int initialized :1;
@@ -1306,8 +1306,10 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev)
1306 azx_sd_writel(azx_dev, SD_BDLPU, upper_32_bits(azx_dev->bdl.addr)); 1306 azx_sd_writel(azx_dev, SD_BDLPU, upper_32_bits(azx_dev->bdl.addr));
1307 1307
1308 /* enable the position buffer */ 1308 /* enable the position buffer */
1309 if (chip->position_fix == POS_FIX_POSBUF || 1309 if (chip->position_fix[0] == POS_FIX_POSBUF ||
1310 chip->position_fix == POS_FIX_AUTO || 1310 chip->position_fix[0] == POS_FIX_AUTO ||
1311 chip->position_fix[1] == POS_FIX_POSBUF ||
1312 chip->position_fix[1] == POS_FIX_AUTO ||
1311 chip->via_dmapos_patch) { 1313 chip->via_dmapos_patch) {
1312 if (!(azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE)) 1314 if (!(azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE))
1313 azx_writel(chip, DPLBASE, 1315 azx_writel(chip, DPLBASE,
@@ -1847,13 +1849,16 @@ static unsigned int azx_get_position(struct azx *chip,
1847 1849
1848 if (chip->via_dmapos_patch) 1850 if (chip->via_dmapos_patch)
1849 pos = azx_via_get_position(chip, azx_dev); 1851 pos = azx_via_get_position(chip, azx_dev);
1850 else if (chip->position_fix == POS_FIX_POSBUF || 1852 else {
1851 chip->position_fix == POS_FIX_AUTO) { 1853 int stream = azx_dev->substream->stream;
1852 /* use the position buffer */ 1854 if (chip->position_fix[stream] == POS_FIX_POSBUF ||
1853 pos = le32_to_cpu(*azx_dev->posbuf); 1855 chip->position_fix[stream] == POS_FIX_AUTO) {
1854 } else { 1856 /* use the position buffer */
1855 /* read LPIB */ 1857 pos = le32_to_cpu(*azx_dev->posbuf);
1856 pos = azx_sd_readl(azx_dev, SD_LPIB); 1858 } else {
1859 /* read LPIB */
1860 pos = azx_sd_readl(azx_dev, SD_LPIB);
1861 }
1857 } 1862 }
1858 if (pos >= azx_dev->bufsize) 1863 if (pos >= azx_dev->bufsize)
1859 pos = 0; 1864 pos = 0;
@@ -1881,22 +1886,24 @@ static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream)
1881static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev) 1886static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev)
1882{ 1887{
1883 unsigned int pos; 1888 unsigned int pos;
1889 int stream;
1884 1890
1885 if (azx_dev->start_flag && 1891 if (azx_dev->start_flag &&
1886 time_before_eq(jiffies, azx_dev->start_jiffies)) 1892 time_before_eq(jiffies, azx_dev->start_jiffies))
1887 return -1; /* bogus (too early) interrupt */ 1893 return -1; /* bogus (too early) interrupt */
1888 azx_dev->start_flag = 0; 1894 azx_dev->start_flag = 0;
1889 1895
1896 stream = azx_dev->substream->stream;
1890 pos = azx_get_position(chip, azx_dev); 1897 pos = azx_get_position(chip, azx_dev);
1891 if (chip->position_fix == POS_FIX_AUTO) { 1898 if (chip->position_fix[stream] == POS_FIX_AUTO) {
1892 if (!pos) { 1899 if (!pos) {
1893 printk(KERN_WARNING 1900 printk(KERN_WARNING
1894 "hda-intel: Invalid position buffer, " 1901 "hda-intel: Invalid position buffer, "
1895 "using LPIB read method instead.\n"); 1902 "using LPIB read method instead.\n");
1896 chip->position_fix = POS_FIX_LPIB; 1903 chip->position_fix[stream] = POS_FIX_LPIB;
1897 pos = azx_get_position(chip, azx_dev); 1904 pos = azx_get_position(chip, azx_dev);
1898 } else 1905 } else
1899 chip->position_fix = POS_FIX_POSBUF; 1906 chip->position_fix[stream] = POS_FIX_POSBUF;
1900 } 1907 }
1901 1908
1902 if (!bdl_pos_adj[chip->dev_index]) 1909 if (!bdl_pos_adj[chip->dev_index])
@@ -2435,7 +2442,8 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
2435 chip->dev_index = dev; 2442 chip->dev_index = dev;
2436 INIT_WORK(&chip->irq_pending_work, azx_irq_pending_work); 2443 INIT_WORK(&chip->irq_pending_work, azx_irq_pending_work);
2437 2444
2438 chip->position_fix = check_position_fix(chip, position_fix[dev]); 2445 chip->position_fix[0] = chip->position_fix[1] =
2446 check_position_fix(chip, position_fix[dev]);
2439 check_probe_mask(chip, dev); 2447 check_probe_mask(chip, dev);
2440 2448
2441 chip->single_cmd = single_cmd; 2449 chip->single_cmd = single_cmd;