aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorPavel Hofman <pavel.hofman@ivitera.com>2009-09-16 16:25:40 -0400
committerTakashi Iwai <tiwai@suse.de>2009-09-21 09:48:00 -0400
commit1ff97cb9dd9f53b33ce6710a4f861f43e70e8ca4 (patch)
treeb368fa7a43d062940e5fb29c31b609b16bc7bd9d /sound
parent6796d5a05f4d3caad17d2586b3e5776fda50ef82 (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')
-rw-r--r--sound/pci/ice1712/ice1712.h7
-rw-r--r--sound/pci/ice1712/ice1724.c58
-rw-r--r--sound/pci/ice1712/juli.c3
3 files changed, 52 insertions, 16 deletions
diff --git a/sound/pci/ice1712/ice1712.h b/sound/pci/ice1712/ice1712.h
index b31a59d0625c..4615bca39e18 100644
--- a/sound/pci/ice1712/ice1712.h
+++ b/sound/pci/ice1712/ice1712.h
@@ -379,8 +379,11 @@ struct snd_ice1712 {
379 unsigned int (*get_rate)(struct snd_ice1712 *ice); 379 unsigned int (*get_rate)(struct snd_ice1712 *ice);
380 void (*set_rate)(struct snd_ice1712 *ice, unsigned int rate); 380 void (*set_rate)(struct snd_ice1712 *ice, unsigned int rate);
381 unsigned char (*set_mclk)(struct snd_ice1712 *ice, unsigned int rate); 381 unsigned char (*set_mclk)(struct snd_ice1712 *ice, unsigned int rate);
382 void (*set_spdif_clock)(struct snd_ice1712 *ice); 382 int (*set_spdif_clock)(struct snd_ice1712 *ice, int type);
383 383 int (*get_spdif_master_type)(struct snd_ice1712 *ice);
384 char **ext_clock_names;
385 int ext_clock_count;
386 void (*pro_open)(struct snd_ice1712 *, struct snd_pcm_substream *);
384#ifdef CONFIG_PM 387#ifdef CONFIG_PM
385 int (*pm_suspend)(struct snd_ice1712 *); 388 int (*pm_suspend)(struct snd_ice1712 *);
386 int (*pm_resume)(struct snd_ice1712 *); 389 int (*pm_resume)(struct snd_ice1712 *);
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;
104static int PRO_RATE_RESET = 1; 104static int PRO_RATE_RESET = 1;
105static unsigned int PRO_RATE_DEFAULT = 44100; 105static unsigned int PRO_RATE_DEFAULT = 44100;
106 106
107static 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
1866static 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 */
1854static void stdclock_set_spdif_clock(struct snd_ice1712 *ice) 1873static 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
1865static int snd_vt1724_pro_internal_clock_put(struct snd_kcontrol *kcontrol, 1886static 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);
diff --git a/sound/pci/ice1712/juli.c b/sound/pci/ice1712/juli.c
index 4789e8bfdc17..4bed9633a4cd 100644
--- a/sound/pci/ice1712/juli.c
+++ b/sound/pci/ice1712/juli.c
@@ -529,13 +529,14 @@ static inline unsigned char juli_set_mclk(struct snd_ice1712 *ice,
529} 529}
530 530
531/* setting clock to external - SPDIF */ 531/* setting clock to external - SPDIF */
532static void juli_set_spdif_clock(struct snd_ice1712 *ice) 532static int juli_set_spdif_clock(struct snd_ice1712 *ice, int type)
533{ 533{
534 unsigned int old; 534 unsigned int old;
535 old = ice->gpio.get_data(ice); 535 old = ice->gpio.get_data(ice);
536 /* external clock (= 0), multiply 1x, 48kHz */ 536 /* external clock (= 0), multiply 1x, 48kHz */
537 ice->gpio.set_data(ice, (old & ~GPIO_RATE_MASK) | GPIO_MULTI_1X | 537 ice->gpio.set_data(ice, (old & ~GPIO_RATE_MASK) | GPIO_MULTI_1X |
538 GPIO_FREQ_48KHZ); 538 GPIO_FREQ_48KHZ);
539 return 0;
539} 540}
540 541
541/* Called when ak4114 detects change in the input SPDIF stream */ 542/* Called when ak4114 detects change in the input SPDIF stream */