diff options
author | Timofei Bondarenko <tim@ipi.ac.ru> | 2007-10-31 12:36:20 -0400 |
---|---|---|
committer | Jaroslav Kysela <perex@perex.cz> | 2008-01-31 11:29:15 -0500 |
commit | 755c48abd8ec228a9e3c3bf9b36850ef5a12cc9c (patch) | |
tree | 6bb99684097e48ef3216edaf852b7f3f2a76014e /sound/pci/cmipci.c | |
parent | f889fa91ad47e6fcb530abf1184ca9f1473d3c72 (diff) |
[ALSA] cmipci at 96kHz
This patch adds support for 88.2k, 96k, and 128k samplerates
on cmi8738-55 chip.
Analog playback works fine on all channels.
Analog capture works well too, though the extra samples seems
interpolated by hardware.
spdif playback and capture works fine.
Signed-off-by: Timofei Bondarenko <tim@ipi.ac.ru>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
Diffstat (limited to 'sound/pci/cmipci.c')
-rw-r--r-- | sound/pci/cmipci.c | 83 |
1 files changed, 64 insertions, 19 deletions
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c index 1fa5f004e858..3a2d942f22bb 100644 --- a/sound/pci/cmipci.c +++ b/sound/pci/cmipci.c | |||
@@ -150,6 +150,8 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address."); | |||
150 | #define CM_CH0_SRATE_176K 0x00000200 | 150 | #define CM_CH0_SRATE_176K 0x00000200 |
151 | #define CM_CH0_SRATE_96K 0x00000200 /* model 055? */ | 151 | #define CM_CH0_SRATE_96K 0x00000200 /* model 055? */ |
152 | #define CM_CH0_SRATE_88K 0x00000100 | 152 | #define CM_CH0_SRATE_88K 0x00000100 |
153 | #define CM_CH0_SRATE_128K 0x00000300 | ||
154 | #define CM_CH0_SRATE_MASK 0x00000300 | ||
153 | 155 | ||
154 | #define CM_SPDIF_INVERSE2 0x00000080 /* model 055? */ | 156 | #define CM_SPDIF_INVERSE2 0x00000080 /* model 055? */ |
155 | #define CM_DBLSPDS 0x00000040 /* double SPDIF sample rate 88.2/96 */ | 157 | #define CM_DBLSPDS 0x00000040 /* double SPDIF sample rate 88.2/96 */ |
@@ -473,6 +475,7 @@ struct cmipci { | |||
473 | unsigned int can_ac3_sw: 1; | 475 | unsigned int can_ac3_sw: 1; |
474 | unsigned int can_ac3_hw: 1; | 476 | unsigned int can_ac3_hw: 1; |
475 | unsigned int can_multi_ch: 1; | 477 | unsigned int can_multi_ch: 1; |
478 | unsigned int can_96k: 1; /* samplerate above 48k */ | ||
476 | unsigned int do_soft_ac3: 1; | 479 | unsigned int do_soft_ac3: 1; |
477 | 480 | ||
478 | unsigned int spdif_playback_avail: 1; /* spdif ready? */ | 481 | unsigned int spdif_playback_avail: 1; /* spdif ready? */ |
@@ -603,8 +606,6 @@ static unsigned int snd_cmipci_rate_freq(unsigned int rate) | |||
603 | { | 606 | { |
604 | unsigned int i; | 607 | unsigned int i; |
605 | 608 | ||
606 | if (rate > 48000) | ||
607 | rate /= 2; | ||
608 | for (i = 0; i < ARRAY_SIZE(rates); i++) { | 609 | for (i = 0; i < ARRAY_SIZE(rates); i++) { |
609 | if (rates[i] == rate) | 610 | if (rates[i] == rate) |
610 | return i; | 611 | return i; |
@@ -782,7 +783,7 @@ static int set_dac_channels(struct cmipci *cm, struct cmipci_pcm *rec, int chann | |||
782 | static int snd_cmipci_pcm_prepare(struct cmipci *cm, struct cmipci_pcm *rec, | 783 | static int snd_cmipci_pcm_prepare(struct cmipci *cm, struct cmipci_pcm *rec, |
783 | struct snd_pcm_substream *substream) | 784 | struct snd_pcm_substream *substream) |
784 | { | 785 | { |
785 | unsigned int reg, freq, val; | 786 | unsigned int reg, freq, freq_ext, val; |
786 | unsigned int period_size; | 787 | unsigned int period_size; |
787 | struct snd_pcm_runtime *runtime = substream->runtime; | 788 | struct snd_pcm_runtime *runtime = substream->runtime; |
788 | 789 | ||
@@ -830,7 +831,17 @@ static int snd_cmipci_pcm_prepare(struct cmipci *cm, struct cmipci_pcm *rec, | |||
830 | //snd_printd("cmipci: functrl0 = %08x\n", cm->ctrl); | 831 | //snd_printd("cmipci: functrl0 = %08x\n", cm->ctrl); |
831 | 832 | ||
832 | /* set sample rate */ | 833 | /* set sample rate */ |
833 | freq = snd_cmipci_rate_freq(runtime->rate); | 834 | freq = 0; |
835 | freq_ext = 0; | ||
836 | if (runtime->rate > 48000) | ||
837 | switch (runtime->rate) { | ||
838 | case 88200: freq_ext = CM_CH0_SRATE_88K; break; | ||
839 | case 96000: freq_ext = CM_CH0_SRATE_96K; break; | ||
840 | case 128000: freq_ext = CM_CH0_SRATE_128K; break; | ||
841 | default: snd_BUG(); break; | ||
842 | } | ||
843 | else | ||
844 | freq = snd_cmipci_rate_freq(runtime->rate); | ||
834 | val = snd_cmipci_read(cm, CM_REG_FUNCTRL1); | 845 | val = snd_cmipci_read(cm, CM_REG_FUNCTRL1); |
835 | if (rec->ch) { | 846 | if (rec->ch) { |
836 | val &= ~CM_DSFC_MASK; | 847 | val &= ~CM_DSFC_MASK; |
@@ -851,15 +862,9 @@ static int snd_cmipci_pcm_prepare(struct cmipci *cm, struct cmipci_pcm *rec, | |||
851 | val &= ~CM_CH0FMT_MASK; | 862 | val &= ~CM_CH0FMT_MASK; |
852 | val |= rec->fmt << CM_CH0FMT_SHIFT; | 863 | val |= rec->fmt << CM_CH0FMT_SHIFT; |
853 | } | 864 | } |
854 | if (cm->chip_version == 68) { | 865 | if (cm->can_96k) { |
855 | if (runtime->rate == 88200) | 866 | val &= ~(CM_CH0_SRATE_MASK << (rec->ch * 2)); |
856 | val |= CM_CH0_SRATE_88K << (rec->ch * 2); | 867 | val |= freq_ext << (rec->ch * 2); |
857 | else | ||
858 | val &= ~(CM_CH0_SRATE_88K << (rec->ch * 2)); | ||
859 | if (runtime->rate == 96000) | ||
860 | val |= CM_CH0_SRATE_96K << (rec->ch * 2); | ||
861 | else | ||
862 | val &= ~(CM_CH0_SRATE_96K << (rec->ch * 2)); | ||
863 | } | 868 | } |
864 | snd_cmipci_write(cm, CM_REG_CHFORMAT, val); | 869 | snd_cmipci_write(cm, CM_REG_CHFORMAT, val); |
865 | //snd_printd("cmipci: chformat = %08x\n", val); | 870 | //snd_printd("cmipci: chformat = %08x\n", val); |
@@ -1280,7 +1285,7 @@ static int snd_cmipci_playback_prepare(struct snd_pcm_substream *substream) | |||
1280 | int rate = substream->runtime->rate; | 1285 | int rate = substream->runtime->rate; |
1281 | int err, do_spdif, do_ac3 = 0; | 1286 | int err, do_spdif, do_ac3 = 0; |
1282 | 1287 | ||
1283 | do_spdif = (rate >= 44100 && | 1288 | do_spdif = (rate >= 44100 && rate <= 96000 && |
1284 | substream->runtime->format == SNDRV_PCM_FORMAT_S16_LE && | 1289 | substream->runtime->format == SNDRV_PCM_FORMAT_S16_LE && |
1285 | substream->runtime->channels == 2); | 1290 | substream->runtime->channels == 2); |
1286 | if (do_spdif && cm->can_ac3_hw) | 1291 | if (do_spdif && cm->can_ac3_hw) |
@@ -1336,10 +1341,8 @@ static void snd_cmipci_silence_hack(struct cmipci *cm, struct cmipci_pcm *rec) | |||
1336 | val = snd_cmipci_read(cm, CM_REG_CHFORMAT); | 1341 | val = snd_cmipci_read(cm, CM_REG_CHFORMAT); |
1337 | val &= ~(CM_CH0FMT_MASK << (rec->ch * 2)); | 1342 | val &= ~(CM_CH0FMT_MASK << (rec->ch * 2)); |
1338 | val |= (3 << CM_CH0FMT_SHIFT) << (rec->ch * 2); | 1343 | val |= (3 << CM_CH0FMT_SHIFT) << (rec->ch * 2); |
1339 | if (cm->chip_version == 68) { | 1344 | if (cm->can_96k) |
1340 | val &= ~(CM_CH0_SRATE_88K << (rec->ch * 2)); | 1345 | val &= ~(CM_CH0_SRATE_MASK << (rec->ch * 2)); |
1341 | val &= ~(CM_CH0_SRATE_96K << (rec->ch * 2)); | ||
1342 | } | ||
1343 | snd_cmipci_write(cm, CM_REG_CHFORMAT, val); | 1346 | snd_cmipci_write(cm, CM_REG_CHFORMAT, val); |
1344 | 1347 | ||
1345 | /* start stream (we don't need interrupts) */ | 1348 | /* start stream (we don't need interrupts) */ |
@@ -1391,6 +1394,12 @@ static int snd_cmipci_capture_spdif_prepare(struct snd_pcm_substream *substream) | |||
1391 | 1394 | ||
1392 | spin_lock_irq(&cm->reg_lock); | 1395 | spin_lock_irq(&cm->reg_lock); |
1393 | snd_cmipci_set_bit(cm, CM_REG_FUNCTRL1, CM_CAPTURE_SPDF); | 1396 | snd_cmipci_set_bit(cm, CM_REG_FUNCTRL1, CM_CAPTURE_SPDF); |
1397 | if (cm->can_96k) { | ||
1398 | if (substream->runtime->rate > 48000) | ||
1399 | snd_cmipci_set_bit(cm, CM_REG_CHFORMAT, CM_DBLSPDS); | ||
1400 | else | ||
1401 | snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_DBLSPDS); | ||
1402 | } | ||
1394 | spin_unlock_irq(&cm->reg_lock); | 1403 | spin_unlock_irq(&cm->reg_lock); |
1395 | 1404 | ||
1396 | return snd_cmipci_pcm_prepare(cm, &cm->channel[CM_CH_CAPT], substream); | 1405 | return snd_cmipci_pcm_prepare(cm, &cm->channel[CM_CH_CAPT], substream); |
@@ -1567,6 +1576,14 @@ static struct snd_pcm_hardware snd_cmipci_capture_spdif = | |||
1567 | .fifo_size = 0, | 1576 | .fifo_size = 0, |
1568 | }; | 1577 | }; |
1569 | 1578 | ||
1579 | static unsigned int rate_constraints[] = { 5512, 8000, 11025, 16000, 22050, | ||
1580 | 32000, 44100, 48000, 88200, 96000, 128000 }; | ||
1581 | static struct snd_pcm_hw_constraint_list hw_constraints_rates = { | ||
1582 | .count = ARRAY_SIZE(rate_constraints), | ||
1583 | .list = rate_constraints, | ||
1584 | .mask = 0, | ||
1585 | }; | ||
1586 | |||
1570 | /* | 1587 | /* |
1571 | * check device open/close | 1588 | * check device open/close |
1572 | */ | 1589 | */ |
@@ -1636,6 +1653,13 @@ static int snd_cmipci_playback_open(struct snd_pcm_substream *substream) | |||
1636 | runtime->hw.rates |= SNDRV_PCM_RATE_88200 | | 1653 | runtime->hw.rates |= SNDRV_PCM_RATE_88200 | |
1637 | SNDRV_PCM_RATE_96000; | 1654 | SNDRV_PCM_RATE_96000; |
1638 | runtime->hw.rate_max = 96000; | 1655 | runtime->hw.rate_max = 96000; |
1656 | } else if (cm->chip_version == 55) { | ||
1657 | err = snd_pcm_hw_constraint_list(runtime, 0, | ||
1658 | SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates); | ||
1659 | if (err < 0) | ||
1660 | return err; | ||
1661 | runtime->hw.rates |= SNDRV_PCM_RATE_KNOT; | ||
1662 | runtime->hw.rate_max = 128000; | ||
1639 | } | 1663 | } |
1640 | snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 0x10000); | 1664 | snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 0x10000); |
1641 | cm->dig_pcm_status = cm->dig_status; | 1665 | cm->dig_pcm_status = cm->dig_status; |
@@ -1654,6 +1678,13 @@ static int snd_cmipci_capture_open(struct snd_pcm_substream *substream) | |||
1654 | if (cm->chip_version == 68) { // 8768 only supports 44k/48k recording | 1678 | if (cm->chip_version == 68) { // 8768 only supports 44k/48k recording |
1655 | runtime->hw.rate_min = 41000; | 1679 | runtime->hw.rate_min = 41000; |
1656 | runtime->hw.rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000; | 1680 | runtime->hw.rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000; |
1681 | } else if (cm->chip_version == 55) { | ||
1682 | err = snd_pcm_hw_constraint_list(runtime, 0, | ||
1683 | SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates); | ||
1684 | if (err < 0) | ||
1685 | return err; | ||
1686 | runtime->hw.rates |= SNDRV_PCM_RATE_KNOT; | ||
1687 | runtime->hw.rate_max = 128000; | ||
1657 | } | 1688 | } |
1658 | snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 0x10000); | 1689 | snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 0x10000); |
1659 | return 0; | 1690 | return 0; |
@@ -1685,6 +1716,13 @@ static int snd_cmipci_playback2_open(struct snd_pcm_substream *substream) | |||
1685 | runtime->hw.rates |= SNDRV_PCM_RATE_88200 | | 1716 | runtime->hw.rates |= SNDRV_PCM_RATE_88200 | |
1686 | SNDRV_PCM_RATE_96000; | 1717 | SNDRV_PCM_RATE_96000; |
1687 | runtime->hw.rate_max = 96000; | 1718 | runtime->hw.rate_max = 96000; |
1719 | } else if (cm->chip_version == 55) { | ||
1720 | err = snd_pcm_hw_constraint_list(runtime, 0, | ||
1721 | SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates); | ||
1722 | if (err < 0) | ||
1723 | return err; | ||
1724 | runtime->hw.rates |= SNDRV_PCM_RATE_KNOT; | ||
1725 | runtime->hw.rate_max = 128000; | ||
1688 | } | 1726 | } |
1689 | snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 0x10000); | 1727 | snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 0x10000); |
1690 | return 0; | 1728 | return 0; |
@@ -1704,7 +1742,7 @@ static int snd_cmipci_playback_spdif_open(struct snd_pcm_substream *substream) | |||
1704 | runtime->hw.formats |= SNDRV_PCM_FMTBIT_S32_LE; | 1742 | runtime->hw.formats |= SNDRV_PCM_FMTBIT_S32_LE; |
1705 | snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); | 1743 | snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); |
1706 | } | 1744 | } |
1707 | if (cm->chip_version == 68) { | 1745 | if (cm->can_96k) { |
1708 | runtime->hw.rates |= SNDRV_PCM_RATE_88200 | | 1746 | runtime->hw.rates |= SNDRV_PCM_RATE_88200 | |
1709 | SNDRV_PCM_RATE_96000; | 1747 | SNDRV_PCM_RATE_96000; |
1710 | runtime->hw.rate_max = 96000; | 1748 | runtime->hw.rate_max = 96000; |
@@ -1726,6 +1764,11 @@ static int snd_cmipci_capture_spdif_open(struct snd_pcm_substream *substream) | |||
1726 | if ((err = open_device_check(cm, CM_OPEN_SPDIF_CAPTURE, substream)) < 0) /* use channel B */ | 1764 | if ((err = open_device_check(cm, CM_OPEN_SPDIF_CAPTURE, substream)) < 0) /* use channel B */ |
1727 | return err; | 1765 | return err; |
1728 | runtime->hw = snd_cmipci_capture_spdif; | 1766 | runtime->hw = snd_cmipci_capture_spdif; |
1767 | if (cm->can_96k && !(cm->chip_version == 68)) { | ||
1768 | runtime->hw.rates |= SNDRV_PCM_RATE_88200 | | ||
1769 | SNDRV_PCM_RATE_96000; | ||
1770 | runtime->hw.rate_max = 96000; | ||
1771 | } | ||
1729 | snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 0x40000); | 1772 | snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 0x40000); |
1730 | return 0; | 1773 | return 0; |
1731 | } | 1774 | } |
@@ -2785,9 +2828,11 @@ static void __devinit query_chip(struct cmipci *cm) | |||
2785 | } else if (detect & CM_CHIP_8768) { | 2828 | } else if (detect & CM_CHIP_8768) { |
2786 | cm->chip_version = 68; | 2829 | cm->chip_version = 68; |
2787 | cm->max_channels = 8; | 2830 | cm->max_channels = 8; |
2831 | cm->can_96k = 1; | ||
2788 | } else { | 2832 | } else { |
2789 | cm->chip_version = 55; | 2833 | cm->chip_version = 55; |
2790 | cm->max_channels = 6; | 2834 | cm->max_channels = 6; |
2835 | cm->can_96k = 1; | ||
2791 | } | 2836 | } |
2792 | cm->can_ac3_hw = 1; | 2837 | cm->can_ac3_hw = 1; |
2793 | cm->can_multi_ch = 1; | 2838 | cm->can_multi_ch = 1; |