diff options
author | Pavel Hofman <pavel.hofman@ivitera.com> | 2009-09-16 16:25:40 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2009-09-21 09:48:00 -0400 |
commit | 1ff97cb9dd9f53b33ce6710a4f861f43e70e8ca4 (patch) | |
tree | b368fa7a43d062940e5fb29c31b609b16bc7bd9d /sound/pci/ice1712/ice1724.c | |
parent | 6796d5a05f4d3caad17d2586b3e5776fda50ef82 (diff) |
ALSA: ice1724 - Support for multiple external clock types
* Support for customization of the external clock names
* Adding hooks to playback_pro_open and capture_pro_open, allowing e.g.
limiting available stream rates to a single value when the external
clock rate is detected
Signed-off-by: Pavel Hofman <pavel.hofman@ivitera.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/ice1712/ice1724.c')
-rw-r--r-- | sound/pci/ice1712/ice1724.c | 58 |
1 files changed, 45 insertions, 13 deletions
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index 514e15385f7a..3f11195b2631 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c | |||
@@ -104,6 +104,8 @@ static int PRO_RATE_LOCKED; | |||
104 | static int PRO_RATE_RESET = 1; | 104 | static int PRO_RATE_RESET = 1; |
105 | static unsigned int PRO_RATE_DEFAULT = 44100; | 105 | static unsigned int PRO_RATE_DEFAULT = 44100; |
106 | 106 | ||
107 | static char *ext_clock_names[1] = { "IEC958 In" }; | ||
108 | |||
107 | /* | 109 | /* |
108 | * Basic I/O | 110 | * Basic I/O |
109 | */ | 111 | */ |
@@ -1042,6 +1044,8 @@ static int snd_vt1724_playback_pro_open(struct snd_pcm_substream *substream) | |||
1042 | VT1724_BUFFER_ALIGN); | 1044 | VT1724_BUFFER_ALIGN); |
1043 | snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, | 1045 | snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, |
1044 | VT1724_BUFFER_ALIGN); | 1046 | VT1724_BUFFER_ALIGN); |
1047 | if (ice->pro_open) | ||
1048 | ice->pro_open(ice, substream); | ||
1045 | return 0; | 1049 | return 0; |
1046 | } | 1050 | } |
1047 | 1051 | ||
@@ -1060,6 +1064,8 @@ static int snd_vt1724_capture_pro_open(struct snd_pcm_substream *substream) | |||
1060 | VT1724_BUFFER_ALIGN); | 1064 | VT1724_BUFFER_ALIGN); |
1061 | snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, | 1065 | snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, |
1062 | VT1724_BUFFER_ALIGN); | 1066 | VT1724_BUFFER_ALIGN); |
1067 | if (ice->pro_open) | ||
1068 | ice->pro_open(ice, substream); | ||
1063 | return 0; | 1069 | return 0; |
1064 | } | 1070 | } |
1065 | 1071 | ||
@@ -1813,15 +1819,21 @@ static int snd_vt1724_pro_internal_clock_info(struct snd_kcontrol *kcontrol, | |||
1813 | struct snd_ctl_elem_info *uinfo) | 1819 | struct snd_ctl_elem_info *uinfo) |
1814 | { | 1820 | { |
1815 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 1821 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
1816 | 1822 | int hw_rates_count = ice->hw_rates->count; | |
1817 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 1823 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
1818 | uinfo->count = 1; | 1824 | uinfo->count = 1; |
1819 | uinfo->value.enumerated.items = ice->hw_rates->count + 1; | 1825 | |
1826 | uinfo->value.enumerated.items = hw_rates_count + ice->ext_clock_count; | ||
1827 | /* upper limit - keep at top */ | ||
1820 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | 1828 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) |
1821 | uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; | 1829 | uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; |
1822 | if (uinfo->value.enumerated.item == uinfo->value.enumerated.items - 1) | 1830 | if (uinfo->value.enumerated.item >= hw_rates_count) |
1823 | strcpy(uinfo->value.enumerated.name, "IEC958 Input"); | 1831 | /* ext_clock items */ |
1832 | strcpy(uinfo->value.enumerated.name, | ||
1833 | ice->ext_clock_names[ | ||
1834 | uinfo->value.enumerated.item - hw_rates_count]); | ||
1824 | else | 1835 | else |
1836 | /* int clock items */ | ||
1825 | sprintf(uinfo->value.enumerated.name, "%d", | 1837 | sprintf(uinfo->value.enumerated.name, "%d", |
1826 | ice->hw_rates->list[uinfo->value.enumerated.item]); | 1838 | ice->hw_rates->list[uinfo->value.enumerated.item]); |
1827 | return 0; | 1839 | return 0; |
@@ -1835,7 +1847,8 @@ static int snd_vt1724_pro_internal_clock_get(struct snd_kcontrol *kcontrol, | |||
1835 | 1847 | ||
1836 | spin_lock_irq(&ice->reg_lock); | 1848 | spin_lock_irq(&ice->reg_lock); |
1837 | if (ice->is_spdif_master(ice)) { | 1849 | if (ice->is_spdif_master(ice)) { |
1838 | ucontrol->value.enumerated.item[0] = ice->hw_rates->count; | 1850 | ucontrol->value.enumerated.item[0] = ice->hw_rates->count + |
1851 | ice->get_spdif_master_type(ice); | ||
1839 | } else { | 1852 | } else { |
1840 | rate = ice->get_rate(ice); | 1853 | rate = ice->get_rate(ice); |
1841 | ucontrol->value.enumerated.item[0] = 0; | 1854 | ucontrol->value.enumerated.item[0] = 0; |
@@ -1850,8 +1863,14 @@ static int snd_vt1724_pro_internal_clock_get(struct snd_kcontrol *kcontrol, | |||
1850 | return 0; | 1863 | return 0; |
1851 | } | 1864 | } |
1852 | 1865 | ||
1866 | static int stdclock_get_spdif_master_type(struct snd_ice1712 *ice) | ||
1867 | { | ||
1868 | /* standard external clock - only single type - SPDIF IN */ | ||
1869 | return 0; | ||
1870 | } | ||
1871 | |||
1853 | /* setting clock to external - SPDIF */ | 1872 | /* setting clock to external - SPDIF */ |
1854 | static void stdclock_set_spdif_clock(struct snd_ice1712 *ice) | 1873 | static int stdclock_set_spdif_clock(struct snd_ice1712 *ice, int type) |
1855 | { | 1874 | { |
1856 | unsigned char oval; | 1875 | unsigned char oval; |
1857 | unsigned char i2s_oval; | 1876 | unsigned char i2s_oval; |
@@ -1860,27 +1879,30 @@ static void stdclock_set_spdif_clock(struct snd_ice1712 *ice) | |||
1860 | /* setting 256fs */ | 1879 | /* setting 256fs */ |
1861 | i2s_oval = inb(ICEMT1724(ice, I2S_FORMAT)); | 1880 | i2s_oval = inb(ICEMT1724(ice, I2S_FORMAT)); |
1862 | outb(i2s_oval & ~VT1724_MT_I2S_MCLK_128X, ICEMT1724(ice, I2S_FORMAT)); | 1881 | outb(i2s_oval & ~VT1724_MT_I2S_MCLK_128X, ICEMT1724(ice, I2S_FORMAT)); |
1882 | return 0; | ||
1863 | } | 1883 | } |
1864 | 1884 | ||
1885 | |||
1865 | static int snd_vt1724_pro_internal_clock_put(struct snd_kcontrol *kcontrol, | 1886 | static int snd_vt1724_pro_internal_clock_put(struct snd_kcontrol *kcontrol, |
1866 | struct snd_ctl_elem_value *ucontrol) | 1887 | struct snd_ctl_elem_value *ucontrol) |
1867 | { | 1888 | { |
1868 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 1889 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
1869 | unsigned int old_rate, new_rate; | 1890 | unsigned int old_rate, new_rate; |
1870 | unsigned int item = ucontrol->value.enumerated.item[0]; | 1891 | unsigned int item = ucontrol->value.enumerated.item[0]; |
1871 | unsigned int spdif = ice->hw_rates->count; | 1892 | unsigned int first_ext_clock = ice->hw_rates->count; |
1872 | 1893 | ||
1873 | if (item > spdif) | 1894 | if (item > first_ext_clock + ice->ext_clock_count - 1) |
1874 | return -EINVAL; | 1895 | return -EINVAL; |
1875 | 1896 | ||
1897 | /* if rate = 0 => external clock */ | ||
1876 | spin_lock_irq(&ice->reg_lock); | 1898 | spin_lock_irq(&ice->reg_lock); |
1877 | if (ice->is_spdif_master(ice)) | 1899 | if (ice->is_spdif_master(ice)) |
1878 | old_rate = 0; | 1900 | old_rate = 0; |
1879 | else | 1901 | else |
1880 | old_rate = ice->get_rate(ice); | 1902 | old_rate = ice->get_rate(ice); |
1881 | if (item == spdif) { | 1903 | if (item >= first_ext_clock) { |
1882 | /* switching to external clock via SPDIF */ | 1904 | /* switching to external clock */ |
1883 | ice->set_spdif_clock(ice); | 1905 | ice->set_spdif_clock(ice, item - first_ext_clock); |
1884 | new_rate = 0; | 1906 | new_rate = 0; |
1885 | } else { | 1907 | } else { |
1886 | /* internal on-card clock */ | 1908 | /* internal on-card clock */ |
@@ -1892,7 +1914,7 @@ static int snd_vt1724_pro_internal_clock_put(struct snd_kcontrol *kcontrol, | |||
1892 | } | 1914 | } |
1893 | spin_unlock_irq(&ice->reg_lock); | 1915 | spin_unlock_irq(&ice->reg_lock); |
1894 | 1916 | ||
1895 | /* the first reset to the SPDIF master mode? */ | 1917 | /* the first switch to the ext. clock mode? */ |
1896 | if (old_rate != new_rate && !new_rate) { | 1918 | if (old_rate != new_rate && !new_rate) { |
1897 | /* notify akm chips as well */ | 1919 | /* notify akm chips as well */ |
1898 | unsigned int i; | 1920 | unsigned int i; |
@@ -2550,6 +2572,9 @@ static int __devinit snd_vt1724_probe(struct pci_dev *pci, | |||
2550 | return err; | 2572 | return err; |
2551 | } | 2573 | } |
2552 | 2574 | ||
2575 | /* field init before calling chip_init */ | ||
2576 | ice->ext_clock_count = 0; | ||
2577 | |||
2553 | for (tbl = card_tables; *tbl; tbl++) { | 2578 | for (tbl = card_tables; *tbl; tbl++) { |
2554 | for (c = *tbl; c->subvendor; c++) { | 2579 | for (c = *tbl; c->subvendor; c++) { |
2555 | if (c->subvendor == ice->eeprom.subvendor) { | 2580 | if (c->subvendor == ice->eeprom.subvendor) { |
@@ -2588,6 +2613,13 @@ __found: | |||
2588 | ice->set_mclk = stdclock_set_mclk; | 2613 | ice->set_mclk = stdclock_set_mclk; |
2589 | if (!ice->set_spdif_clock) | 2614 | if (!ice->set_spdif_clock) |
2590 | ice->set_spdif_clock = stdclock_set_spdif_clock; | 2615 | ice->set_spdif_clock = stdclock_set_spdif_clock; |
2616 | if (!ice->get_spdif_master_type) | ||
2617 | ice->get_spdif_master_type = stdclock_get_spdif_master_type; | ||
2618 | if (!ice->ext_clock_names) | ||
2619 | ice->ext_clock_names = ext_clock_names; | ||
2620 | if (!ice->ext_clock_count) | ||
2621 | ice->ext_clock_count = ARRAY_SIZE(ext_clock_names); | ||
2622 | |||
2591 | if (!ice->hw_rates) | 2623 | if (!ice->hw_rates) |
2592 | set_std_hw_rates(ice); | 2624 | set_std_hw_rates(ice); |
2593 | 2625 | ||
@@ -2747,7 +2779,7 @@ static int snd_vt1724_resume(struct pci_dev *pci) | |||
2747 | 2779 | ||
2748 | if (ice->pm_saved_is_spdif_master) { | 2780 | if (ice->pm_saved_is_spdif_master) { |
2749 | /* switching to external clock via SPDIF */ | 2781 | /* switching to external clock via SPDIF */ |
2750 | ice->set_spdif_clock(ice); | 2782 | ice->set_spdif_clock(ice, 0); |
2751 | } else { | 2783 | } else { |
2752 | /* internal on-card clock */ | 2784 | /* internal on-card clock */ |
2753 | snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 1); | 2785 | snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 1); |