aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2005-11-11 15:05:27 -0500
committerJaroslav Kysela <perex@suse.cz>2006-01-03 06:16:01 -0500
commit755e137138007200c3e2549fbd8390a4e7708ed9 (patch)
tree162e6823a0a331297cccebb4e4797e3add05dc1e
parentfd6715e564a53bc3fca22e4f0a9d76b6b72afdb5 (diff)
[ALSA] ali5451 - Fix and clean up codec accessor
Modules: ALI5451 driver Fix the codec accessors to avoid soft lockup. Spin locks are revised, too. Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--sound/pci/ali5451/ali5451.c89
1 files changed, 36 insertions, 53 deletions
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c
index feffbe73387e..21be4c26ebc4 100644
--- a/sound/pci/ali5451/ali5451.c
+++ b/sound/pci/ali5451/ali5451.c
@@ -387,26 +387,24 @@ static inline void snd_ali_5451_poke( ali_t *codec,
387} 387}
388 388
389static int snd_ali_codec_ready( ali_t *codec, 389static int snd_ali_codec_ready( ali_t *codec,
390 unsigned int port, 390 unsigned int port )
391 int sched )
392{ 391{
393 unsigned long end_time; 392 unsigned long end_time;
394 unsigned int res; 393 unsigned int res;
395 394
396 end_time = jiffies + 10 * msecs_to_jiffies(250); 395 end_time = jiffies + msecs_to_jiffies(250);
397 do { 396 do {
398 res = snd_ali_5451_peek(codec,port); 397 res = snd_ali_5451_peek(codec,port);
399 if (! (res & 0x8000)) 398 if (! (res & 0x8000))
400 return 0; 399 return 0;
401 if (sched) 400 schedule_timeout_uninterruptible(1);
402 schedule_timeout_uninterruptible(1);
403 } while (time_after_eq(end_time, jiffies)); 401 } while (time_after_eq(end_time, jiffies));
404 snd_ali_5451_poke(codec, port, res & ~0x8000); 402 snd_ali_5451_poke(codec, port, res & ~0x8000);
405 snd_printdd("ali_codec_ready: codec is not ready.\n "); 403 snd_printdd("ali_codec_ready: codec is not ready.\n ");
406 return -EIO; 404 return -EIO;
407} 405}
408 406
409static int snd_ali_stimer_ready(ali_t *codec, int sched) 407static int snd_ali_stimer_ready(ali_t *codec)
410{ 408{
411 unsigned long end_time; 409 unsigned long end_time;
412 unsigned long dwChk1,dwChk2; 410 unsigned long dwChk1,dwChk2;
@@ -414,13 +412,12 @@ static int snd_ali_stimer_ready(ali_t *codec, int sched)
414 dwChk1 = snd_ali_5451_peek(codec, ALI_STIMER); 412 dwChk1 = snd_ali_5451_peek(codec, ALI_STIMER);
415 dwChk2 = snd_ali_5451_peek(codec, ALI_STIMER); 413 dwChk2 = snd_ali_5451_peek(codec, ALI_STIMER);
416 414
417 end_time = jiffies + 10 * msecs_to_jiffies(250); 415 end_time = jiffies + msecs_to_jiffies(250);
418 do { 416 do {
419 dwChk2 = snd_ali_5451_peek(codec, ALI_STIMER); 417 dwChk2 = snd_ali_5451_peek(codec, ALI_STIMER);
420 if (dwChk2 != dwChk1) 418 if (dwChk2 != dwChk1)
421 return 0; 419 return 0;
422 if (sched) 420 schedule_timeout_uninterruptible(1);
423 schedule_timeout_uninterruptible(1);
424 } while (time_after_eq(end_time, jiffies)); 421 } while (time_after_eq(end_time, jiffies));
425 snd_printk(KERN_ERR "ali_stimer_read: stimer is not ready.\n"); 422 snd_printk(KERN_ERR "ali_stimer_read: stimer is not ready.\n");
426 return -EIO; 423 return -EIO;
@@ -440,9 +437,9 @@ static void snd_ali_codec_poke(ali_t *codec,int secondary,
440 437
441 port = codec->chregs.regs.ac97write; 438 port = codec->chregs.regs.ac97write;
442 439
443 if (snd_ali_codec_ready(codec, port, 0) < 0) 440 if (snd_ali_codec_ready(codec, port) < 0)
444 return; 441 return;
445 if (snd_ali_stimer_ready(codec, 0) < 0) 442 if (snd_ali_stimer_ready(codec) < 0)
446 return; 443 return;
447 444
448 dwVal = (unsigned int) (reg & 0xff); 445 dwVal = (unsigned int) (reg & 0xff);
@@ -469,9 +466,9 @@ static unsigned short snd_ali_codec_peek( ali_t *codec,
469 466
470 port = codec->chregs.regs.ac97read; 467 port = codec->chregs.regs.ac97read;
471 468
472 if (snd_ali_codec_ready(codec, port, 0) < 0) 469 if (snd_ali_codec_ready(codec, port) < 0)
473 return ~0; 470 return ~0;
474 if (snd_ali_stimer_ready(codec, 0) < 0) 471 if (snd_ali_stimer_ready(codec) < 0)
475 return ~0; 472 return ~0;
476 473
477 dwVal = (unsigned int) (reg & 0xff); 474 dwVal = (unsigned int) (reg & 0xff);
@@ -480,9 +477,9 @@ static unsigned short snd_ali_codec_peek( ali_t *codec,
480 477
481 snd_ali_5451_poke(codec, port, dwVal); 478 snd_ali_5451_poke(codec, port, dwVal);
482 479
483 if (snd_ali_stimer_ready(codec, 0) < 0) 480 if (snd_ali_stimer_ready(codec) < 0)
484 return ~0; 481 return ~0;
485 if (snd_ali_codec_ready(codec, port, 0) < 0) 482 if (snd_ali_codec_ready(codec, port) < 0)
486 return ~0; 483 return ~0;
487 484
488 return (snd_ali_5451_peek(codec, port) & 0xffff0000)>>16; 485 return (snd_ali_5451_peek(codec, port) & 0xffff0000)>>16;
@@ -770,7 +767,7 @@ static void snd_ali_delay(ali_t *codec,int interval)
770 currenttimer = inl(ALI_REG(codec, ALI_STIMER)); 767 currenttimer = inl(ALI_REG(codec, ALI_STIMER));
771 768
772 while (currenttimer < begintimer + interval) { 769 while (currenttimer < begintimer + interval) {
773 if(snd_ali_stimer_ready(codec, 1) < 0) 770 if(snd_ali_stimer_ready(codec) < 0)
774 break; 771 break;
775 currenttimer = inl(ALI_REG(codec, ALI_STIMER)); 772 currenttimer = inl(ALI_REG(codec, ALI_STIMER));
776 } 773 }
@@ -1065,35 +1062,34 @@ static irqreturn_t snd_ali_card_interrupt(int irq,
1065static snd_ali_voice_t *snd_ali_alloc_voice(ali_t * codec, int type, int rec, int channel) 1062static snd_ali_voice_t *snd_ali_alloc_voice(ali_t * codec, int type, int rec, int channel)
1066{ 1063{
1067 snd_ali_voice_t *pvoice = NULL; 1064 snd_ali_voice_t *pvoice = NULL;
1068 unsigned long flags;
1069 int idx; 1065 int idx;
1070 1066
1071 snd_ali_printk("alloc_voice: type=%d rec=%d\n",type,rec); 1067 snd_ali_printk("alloc_voice: type=%d rec=%d\n",type,rec);
1072 1068
1073 spin_lock_irqsave(&codec->voice_alloc, flags); 1069 spin_lock_irq(&codec->voice_alloc);
1074 if (type == SNDRV_ALI_VOICE_TYPE_PCM) { 1070 if (type == SNDRV_ALI_VOICE_TYPE_PCM) {
1075 idx = channel > 0 ? snd_ali_alloc_pcm_channel(codec, channel) : 1071 idx = channel > 0 ? snd_ali_alloc_pcm_channel(codec, channel) :
1076 snd_ali_find_free_channel(codec,rec); 1072 snd_ali_find_free_channel(codec,rec);
1077 if(idx < 0) { 1073 if(idx < 0) {
1078 snd_printk(KERN_ERR "ali_alloc_voice: err.\n"); 1074 snd_printk(KERN_ERR "ali_alloc_voice: err.\n");
1079 spin_unlock_irqrestore(&codec->voice_alloc, flags); 1075 spin_unlock_irq(&codec->voice_alloc);
1080 return NULL; 1076 return NULL;
1081 } 1077 }
1082 pvoice = &(codec->synth.voices[idx]); 1078 pvoice = &(codec->synth.voices[idx]);
1079 pvoice->codec = codec;
1083 pvoice->use = 1; 1080 pvoice->use = 1;
1084 pvoice->pcm = 1; 1081 pvoice->pcm = 1;
1085 pvoice->mode = rec; 1082 pvoice->mode = rec;
1086 spin_unlock_irqrestore(&codec->voice_alloc, flags); 1083 spin_unlock_irq(&codec->voice_alloc);
1087 return pvoice; 1084 return pvoice;
1088 } 1085 }
1089 spin_unlock_irqrestore(&codec->voice_alloc, flags); 1086 spin_unlock_irq(&codec->voice_alloc);
1090 return NULL; 1087 return NULL;
1091} 1088}
1092 1089
1093 1090
1094static void snd_ali_free_voice(ali_t * codec, snd_ali_voice_t *pvoice) 1091static void snd_ali_free_voice(ali_t * codec, snd_ali_voice_t *pvoice)
1095{ 1092{
1096 unsigned long flags;
1097 void (*private_free)(void *); 1093 void (*private_free)(void *);
1098 void *private_data; 1094 void *private_data;
1099 1095
@@ -1101,7 +1097,7 @@ static void snd_ali_free_voice(ali_t * codec, snd_ali_voice_t *pvoice)
1101 if (pvoice == NULL || !pvoice->use) 1097 if (pvoice == NULL || !pvoice->use)
1102 return; 1098 return;
1103 snd_ali_clear_voices(codec, pvoice->number, pvoice->number); 1099 snd_ali_clear_voices(codec, pvoice->number, pvoice->number);
1104 spin_lock_irqsave(&codec->voice_alloc, flags); 1100 spin_lock_irq(&codec->voice_alloc);
1105 private_free = pvoice->private_free; 1101 private_free = pvoice->private_free;
1106 private_data = pvoice->private_data; 1102 private_data = pvoice->private_data;
1107 pvoice->private_free = NULL; 1103 pvoice->private_free = NULL;
@@ -1111,7 +1107,7 @@ static void snd_ali_free_voice(ali_t * codec, snd_ali_voice_t *pvoice)
1111 } 1107 }
1112 pvoice->use = pvoice->pcm = pvoice->synth = 0; 1108 pvoice->use = pvoice->pcm = pvoice->synth = 0;
1113 pvoice->substream = NULL; 1109 pvoice->substream = NULL;
1114 spin_unlock_irqrestore(&codec->voice_alloc, flags); 1110 spin_unlock_irq(&codec->voice_alloc);
1115 if (private_free) 1111 if (private_free)
1116 private_free(private_data); 1112 private_free(private_data);
1117} 1113}
@@ -1357,7 +1353,6 @@ static int snd_ali_playback_prepare(snd_pcm_substream_t * substream)
1357 snd_pcm_runtime_t *runtime = substream->runtime; 1353 snd_pcm_runtime_t *runtime = substream->runtime;
1358 snd_ali_voice_t *pvoice = (snd_ali_voice_t *) runtime->private_data; 1354 snd_ali_voice_t *pvoice = (snd_ali_voice_t *) runtime->private_data;
1359 snd_ali_voice_t *evoice = pvoice->extra; 1355 snd_ali_voice_t *evoice = pvoice->extra;
1360 unsigned long flags;
1361 1356
1362 unsigned int LBA; 1357 unsigned int LBA;
1363 unsigned int Delta; 1358 unsigned int Delta;
@@ -1370,7 +1365,7 @@ static int snd_ali_playback_prepare(snd_pcm_substream_t * substream)
1370 1365
1371 snd_ali_printk("playback_prepare ...\n"); 1366 snd_ali_printk("playback_prepare ...\n");
1372 1367
1373 spin_lock_irqsave(&codec->reg_lock, flags); 1368 spin_lock_irq(&codec->reg_lock);
1374 1369
1375 /* set Delta (rate) value */ 1370 /* set Delta (rate) value */
1376 Delta = snd_ali_convert_rate(runtime->rate, 0); 1371 Delta = snd_ali_convert_rate(runtime->rate, 0);
@@ -1435,7 +1430,7 @@ static int snd_ali_playback_prepare(snd_pcm_substream_t * substream)
1435 CTRL, 1430 CTRL,
1436 EC); 1431 EC);
1437 } 1432 }
1438 spin_unlock_irqrestore(&codec->reg_lock, flags); 1433 spin_unlock_irq(&codec->reg_lock);
1439 return 0; 1434 return 0;
1440} 1435}
1441 1436
@@ -1445,7 +1440,6 @@ static int snd_ali_prepare(snd_pcm_substream_t * substream)
1445 ali_t *codec = snd_pcm_substream_chip(substream); 1440 ali_t *codec = snd_pcm_substream_chip(substream);
1446 snd_pcm_runtime_t *runtime = substream->runtime; 1441 snd_pcm_runtime_t *runtime = substream->runtime;
1447 snd_ali_voice_t *pvoice = (snd_ali_voice_t *) runtime->private_data; 1442 snd_ali_voice_t *pvoice = (snd_ali_voice_t *) runtime->private_data;
1448 unsigned long flags;
1449 unsigned int LBA; 1443 unsigned int LBA;
1450 unsigned int Delta; 1444 unsigned int Delta;
1451 unsigned int ESO; 1445 unsigned int ESO;
@@ -1456,7 +1450,7 @@ static int snd_ali_prepare(snd_pcm_substream_t * substream)
1456 unsigned int EC; 1450 unsigned int EC;
1457 u8 bValue; 1451 u8 bValue;
1458 1452
1459 spin_lock_irqsave(&codec->reg_lock, flags); 1453 spin_lock_irq(&codec->reg_lock);
1460 1454
1461 snd_ali_printk("ali_prepare...\n"); 1455 snd_ali_printk("ali_prepare...\n");
1462 1456
@@ -1471,15 +1465,16 @@ static int snd_ali_prepare(snd_pcm_substream_t * substream)
1471 1465
1472 unsigned int rate; 1466 unsigned int rate;
1473 1467
1474 if (codec->revision != ALI_5451_V02) { 1468 spin_unlock_irq(&codec->reg_lock);
1475 spin_unlock_irqrestore(&codec->reg_lock, flags); 1469 if (codec->revision != ALI_5451_V02)
1476 return -1; 1470 return -1;
1477 } 1471
1478 rate = snd_ali_get_spdif_in_rate(codec); 1472 rate = snd_ali_get_spdif_in_rate(codec);
1479 if (rate == 0) { 1473 if (rate == 0) {
1480 snd_printk(KERN_WARNING "ali_capture_preapre: spdif rate detect err!\n"); 1474 snd_printk(KERN_WARNING "ali_capture_preapre: spdif rate detect err!\n");
1481 rate = 48000; 1475 rate = 48000;
1482 } 1476 }
1477 spin_lock_irq(&codec->reg_lock);
1483 bValue = inb(ALI_REG(codec,ALI_SPDIF_CTRL)); 1478 bValue = inb(ALI_REG(codec,ALI_SPDIF_CTRL));
1484 if (bValue & 0x10) { 1479 if (bValue & 0x10) {
1485 outb(bValue,ALI_REG(codec,ALI_SPDIF_CTRL)); 1480 outb(bValue,ALI_REG(codec,ALI_SPDIF_CTRL));
@@ -1521,7 +1516,7 @@ static int snd_ali_prepare(snd_pcm_substream_t * substream)
1521 EC); 1516 EC);
1522 1517
1523 1518
1524 spin_unlock_irqrestore(&codec->reg_lock, flags); 1519 spin_unlock_irq(&codec->reg_lock);
1525 1520
1526 return 0; 1521 return 0;
1527} 1522}
@@ -1554,16 +1549,15 @@ static snd_pcm_uframes_t snd_ali_pointer(snd_pcm_substream_t *substream)
1554 snd_pcm_runtime_t *runtime = substream->runtime; 1549 snd_pcm_runtime_t *runtime = substream->runtime;
1555 snd_ali_voice_t *pvoice = (snd_ali_voice_t *) runtime->private_data; 1550 snd_ali_voice_t *pvoice = (snd_ali_voice_t *) runtime->private_data;
1556 unsigned int cso; 1551 unsigned int cso;
1557 unsigned long flags;
1558 1552
1559 spin_lock_irqsave(&codec->reg_lock, flags); 1553 spin_lock(&codec->reg_lock);
1560 if (!pvoice->running) { 1554 if (!pvoice->running) {
1561 spin_unlock_irqrestore(&codec->reg_lock, flags); 1555 spin_unlock_irq(&codec->reg_lock);
1562 return 0; 1556 return 0;
1563 } 1557 }
1564 outb(pvoice->number, ALI_REG(codec, ALI_GC_CIR)); 1558 outb(pvoice->number, ALI_REG(codec, ALI_GC_CIR));
1565 cso = inw(ALI_REG(codec, ALI_CSO_ALPHA_FMS + 2)); 1559 cso = inw(ALI_REG(codec, ALI_CSO_ALPHA_FMS + 2));
1566 spin_unlock_irqrestore(&codec->reg_lock, flags); 1560 spin_unlock(&codec->reg_lock);
1567 1561
1568 return cso; 1562 return cso;
1569} 1563}
@@ -1618,15 +1612,12 @@ static snd_pcm_hardware_t snd_ali_capture =
1618 1612
1619static void snd_ali_pcm_free_substream(snd_pcm_runtime_t *runtime) 1613static void snd_ali_pcm_free_substream(snd_pcm_runtime_t *runtime)
1620{ 1614{
1621 unsigned long flags;
1622 snd_ali_voice_t *pvoice = (snd_ali_voice_t *) runtime->private_data; 1615 snd_ali_voice_t *pvoice = (snd_ali_voice_t *) runtime->private_data;
1623 ali_t *codec; 1616 ali_t *codec;
1624 1617
1625 if (pvoice) { 1618 if (pvoice) {
1626 codec = pvoice->codec; 1619 codec = pvoice->codec;
1627 spin_lock_irqsave(&codec->reg_lock, flags);
1628 snd_ali_free_voice(pvoice->codec, pvoice); 1620 snd_ali_free_voice(pvoice->codec, pvoice);
1629 spin_unlock_irqrestore(&codec->reg_lock, flags);
1630 } 1621 }
1631} 1622}
1632 1623
@@ -1636,16 +1627,10 @@ static int snd_ali_open(snd_pcm_substream_t * substream, int rec, int channel,
1636 ali_t *codec = snd_pcm_substream_chip(substream); 1627 ali_t *codec = snd_pcm_substream_chip(substream);
1637 snd_pcm_runtime_t *runtime = substream->runtime; 1628 snd_pcm_runtime_t *runtime = substream->runtime;
1638 snd_ali_voice_t *pvoice; 1629 snd_ali_voice_t *pvoice;
1639 unsigned long flags = 0;
1640 1630
1641 spin_lock_irqsave(&codec->reg_lock, flags);
1642 pvoice = snd_ali_alloc_voice(codec, SNDRV_ALI_VOICE_TYPE_PCM, rec, channel); 1631 pvoice = snd_ali_alloc_voice(codec, SNDRV_ALI_VOICE_TYPE_PCM, rec, channel);
1643 if (pvoice == NULL) { 1632 if (pvoice == NULL)
1644 spin_unlock_irqrestore(&codec->reg_lock, flags);
1645 return -EAGAIN; 1633 return -EAGAIN;
1646 }
1647 pvoice->codec = codec;
1648 spin_unlock_irqrestore(&codec->reg_lock, flags);
1649 1634
1650 pvoice->substream = substream; 1635 pvoice->substream = substream;
1651 runtime->private_data = pvoice; 1636 runtime->private_data = pvoice;
@@ -1864,13 +1849,12 @@ static int snd_ali5451_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
1864 1849
1865static int snd_ali5451_spdif_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 1850static int snd_ali5451_spdif_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
1866{ 1851{
1867 unsigned long flags;
1868 ali_t *codec = kcontrol->private_data; 1852 ali_t *codec = kcontrol->private_data;
1869 unsigned int enable; 1853 unsigned int enable;
1870 1854
1871 enable = ucontrol->value.integer.value[0] ? 1 : 0; 1855 enable = ucontrol->value.integer.value[0] ? 1 : 0;
1872 1856
1873 spin_lock_irqsave(&codec->reg_lock, flags); 1857 spin_lock_irq(&codec->reg_lock);
1874 switch(kcontrol->private_value) { 1858 switch(kcontrol->private_value) {
1875 case 0: 1859 case 0:
1876 enable = (codec->spdif_mask & 0x02) ? 1 : 0; 1860 enable = (codec->spdif_mask & 0x02) ? 1 : 0;
@@ -1885,19 +1869,18 @@ static int snd_ali5451_spdif_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
1885 break; 1869 break;
1886 } 1870 }
1887 ucontrol->value.integer.value[0] = enable; 1871 ucontrol->value.integer.value[0] = enable;
1888 spin_unlock_irqrestore(&codec->reg_lock, flags); 1872 spin_unlock_irq(&codec->reg_lock);
1889 return 0; 1873 return 0;
1890} 1874}
1891 1875
1892static int snd_ali5451_spdif_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 1876static int snd_ali5451_spdif_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
1893{ 1877{
1894 unsigned long flags;
1895 ali_t *codec = kcontrol->private_data; 1878 ali_t *codec = kcontrol->private_data;
1896 unsigned int change = 0, enable = 0; 1879 unsigned int change = 0, enable = 0;
1897 1880
1898 enable = ucontrol->value.integer.value[0] ? 1 : 0; 1881 enable = ucontrol->value.integer.value[0] ? 1 : 0;
1899 1882
1900 spin_lock_irqsave(&codec->reg_lock, flags); 1883 spin_lock_irq(&codec->reg_lock);
1901 switch (kcontrol->private_value) { 1884 switch (kcontrol->private_value) {
1902 case 0: 1885 case 0:
1903 change = (codec->spdif_mask & 0x02) ? 1 : 0; 1886 change = (codec->spdif_mask & 0x02) ? 1 : 0;
@@ -1942,7 +1925,7 @@ static int snd_ali5451_spdif_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
1942 default: 1925 default:
1943 break; 1926 break;
1944 } 1927 }
1945 spin_unlock_irqrestore(&codec->reg_lock, flags); 1928 spin_unlock_irq(&codec->reg_lock);
1946 1929
1947 return change; 1930 return change;
1948} 1931}