diff options
author | Takashi Iwai <tiwai@suse.de> | 2009-12-01 09:57:01 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2009-12-01 09:57:01 -0500 |
commit | 980f31c46b3c7895ad926fbb43c8edac6ce193ff (patch) | |
tree | ec61a87b42ce8e6eb24554d8a56173ef75aefdd2 /sound/pci/ice1712/ice1724.c | |
parent | 9e298f449e667833c4cafad040ce8025a8ba1eed (diff) | |
parent | 6ef80706184be792499a4485a7957f2660b6a076 (diff) |
Merge branch 'topic/ice1724-quartet' into topic/hda
Diffstat (limited to 'sound/pci/ice1712/ice1724.c')
-rw-r--r-- | sound/pci/ice1712/ice1724.c | 103 |
1 files changed, 83 insertions, 20 deletions
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index 10fc92c05574..ae29073eea93 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c | |||
@@ -53,6 +53,7 @@ | |||
53 | #include "phase.h" | 53 | #include "phase.h" |
54 | #include "wtm.h" | 54 | #include "wtm.h" |
55 | #include "se.h" | 55 | #include "se.h" |
56 | #include "quartet.h" | ||
56 | 57 | ||
57 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); | 58 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
58 | MODULE_DESCRIPTION("VIA ICEnsemble ICE1724/1720 (Envy24HT/PT)"); | 59 | MODULE_DESCRIPTION("VIA ICEnsemble ICE1724/1720 (Envy24HT/PT)"); |
@@ -70,6 +71,7 @@ MODULE_SUPPORTED_DEVICE("{" | |||
70 | PHASE_DEVICE_DESC | 71 | PHASE_DEVICE_DESC |
71 | WTM_DEVICE_DESC | 72 | WTM_DEVICE_DESC |
72 | SE_DEVICE_DESC | 73 | SE_DEVICE_DESC |
74 | QTET_DEVICE_DESC | ||
73 | "{VIA,VT1720}," | 75 | "{VIA,VT1720}," |
74 | "{VIA,VT1724}," | 76 | "{VIA,VT1724}," |
75 | "{ICEnsemble,Generic ICE1724}," | 77 | "{ICEnsemble,Generic ICE1724}," |
@@ -104,6 +106,8 @@ static int PRO_RATE_LOCKED; | |||
104 | static int PRO_RATE_RESET = 1; | 106 | static int PRO_RATE_RESET = 1; |
105 | static unsigned int PRO_RATE_DEFAULT = 44100; | 107 | static unsigned int PRO_RATE_DEFAULT = 44100; |
106 | 108 | ||
109 | static char *ext_clock_names[1] = { "IEC958 In" }; | ||
110 | |||
107 | /* | 111 | /* |
108 | * Basic I/O | 112 | * Basic I/O |
109 | */ | 113 | */ |
@@ -118,9 +122,12 @@ static inline int stdclock_is_spdif_master(struct snd_ice1712 *ice) | |||
118 | return (inb(ICEMT1724(ice, RATE)) & VT1724_SPDIF_MASTER) ? 1 : 0; | 122 | return (inb(ICEMT1724(ice, RATE)) & VT1724_SPDIF_MASTER) ? 1 : 0; |
119 | } | 123 | } |
120 | 124 | ||
125 | /* | ||
126 | * locking rate makes sense only for internal clock mode | ||
127 | */ | ||
121 | static inline int is_pro_rate_locked(struct snd_ice1712 *ice) | 128 | static inline int is_pro_rate_locked(struct snd_ice1712 *ice) |
122 | { | 129 | { |
123 | return ice->is_spdif_master(ice) || PRO_RATE_LOCKED; | 130 | return (!ice->is_spdif_master(ice)) && PRO_RATE_LOCKED; |
124 | } | 131 | } |
125 | 132 | ||
126 | /* | 133 | /* |
@@ -196,6 +203,12 @@ static void snd_vt1724_set_gpio_dir(struct snd_ice1712 *ice, unsigned int data) | |||
196 | inw(ICEREG1724(ice, GPIO_DIRECTION)); /* dummy read for pci-posting */ | 203 | inw(ICEREG1724(ice, GPIO_DIRECTION)); /* dummy read for pci-posting */ |
197 | } | 204 | } |
198 | 205 | ||
206 | /* get gpio direction 0 = read, 1 = write */ | ||
207 | static unsigned int snd_vt1724_get_gpio_dir(struct snd_ice1712 *ice) | ||
208 | { | ||
209 | return inl(ICEREG1724(ice, GPIO_DIRECTION)); | ||
210 | } | ||
211 | |||
199 | /* set the gpio mask (0 = writable) */ | 212 | /* set the gpio mask (0 = writable) */ |
200 | static void snd_vt1724_set_gpio_mask(struct snd_ice1712 *ice, unsigned int data) | 213 | static void snd_vt1724_set_gpio_mask(struct snd_ice1712 *ice, unsigned int data) |
201 | { | 214 | { |
@@ -205,6 +218,17 @@ static void snd_vt1724_set_gpio_mask(struct snd_ice1712 *ice, unsigned int data) | |||
205 | inw(ICEREG1724(ice, GPIO_WRITE_MASK)); /* dummy read for pci-posting */ | 218 | inw(ICEREG1724(ice, GPIO_WRITE_MASK)); /* dummy read for pci-posting */ |
206 | } | 219 | } |
207 | 220 | ||
221 | static unsigned int snd_vt1724_get_gpio_mask(struct snd_ice1712 *ice) | ||
222 | { | ||
223 | unsigned int mask; | ||
224 | if (!ice->vt1720) | ||
225 | mask = (unsigned int)inb(ICEREG1724(ice, GPIO_WRITE_MASK_22)); | ||
226 | else | ||
227 | mask = 0; | ||
228 | mask = (mask << 16) | inw(ICEREG1724(ice, GPIO_WRITE_MASK)); | ||
229 | return mask; | ||
230 | } | ||
231 | |||
208 | static void snd_vt1724_set_gpio_data(struct snd_ice1712 *ice, unsigned int data) | 232 | static void snd_vt1724_set_gpio_data(struct snd_ice1712 *ice, unsigned int data) |
209 | { | 233 | { |
210 | outw(data, ICEREG1724(ice, GPIO_DATA)); | 234 | outw(data, ICEREG1724(ice, GPIO_DATA)); |
@@ -651,16 +675,22 @@ static int snd_vt1724_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate, | |||
651 | return ((rate == ice->cur_rate) && !force) ? 0 : -EBUSY; | 675 | return ((rate == ice->cur_rate) && !force) ? 0 : -EBUSY; |
652 | } | 676 | } |
653 | if (!force && is_pro_rate_locked(ice)) { | 677 | if (!force && is_pro_rate_locked(ice)) { |
678 | /* comparing required and current rate - makes sense for | ||
679 | * internal clock only */ | ||
654 | spin_unlock_irqrestore(&ice->reg_lock, flags); | 680 | spin_unlock_irqrestore(&ice->reg_lock, flags); |
655 | return (rate == ice->cur_rate) ? 0 : -EBUSY; | 681 | return (rate == ice->cur_rate) ? 0 : -EBUSY; |
656 | } | 682 | } |
657 | 683 | ||
658 | old_rate = ice->get_rate(ice); | 684 | if (force || !ice->is_spdif_master(ice)) { |
659 | if (force || (old_rate != rate)) | 685 | /* force means the rate was switched by ucontrol, otherwise |
660 | ice->set_rate(ice, rate); | 686 | * setting clock rate for internal clock mode */ |
661 | else if (rate == ice->cur_rate) { | 687 | old_rate = ice->get_rate(ice); |
662 | spin_unlock_irqrestore(&ice->reg_lock, flags); | 688 | if (force || (old_rate != rate)) |
663 | return 0; | 689 | ice->set_rate(ice, rate); |
690 | else if (rate == ice->cur_rate) { | ||
691 | spin_unlock_irqrestore(&ice->reg_lock, flags); | ||
692 | return 0; | ||
693 | } | ||
664 | } | 694 | } |
665 | 695 | ||
666 | ice->cur_rate = rate; | 696 | ice->cur_rate = rate; |
@@ -1016,6 +1046,8 @@ static int snd_vt1724_playback_pro_open(struct snd_pcm_substream *substream) | |||
1016 | VT1724_BUFFER_ALIGN); | 1046 | VT1724_BUFFER_ALIGN); |
1017 | snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, | 1047 | snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, |
1018 | VT1724_BUFFER_ALIGN); | 1048 | VT1724_BUFFER_ALIGN); |
1049 | if (ice->pro_open) | ||
1050 | ice->pro_open(ice, substream); | ||
1019 | return 0; | 1051 | return 0; |
1020 | } | 1052 | } |
1021 | 1053 | ||
@@ -1034,6 +1066,8 @@ static int snd_vt1724_capture_pro_open(struct snd_pcm_substream *substream) | |||
1034 | VT1724_BUFFER_ALIGN); | 1066 | VT1724_BUFFER_ALIGN); |
1035 | snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, | 1067 | snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, |
1036 | VT1724_BUFFER_ALIGN); | 1068 | VT1724_BUFFER_ALIGN); |
1069 | if (ice->pro_open) | ||
1070 | ice->pro_open(ice, substream); | ||
1037 | return 0; | 1071 | return 0; |
1038 | } | 1072 | } |
1039 | 1073 | ||
@@ -1787,15 +1821,21 @@ static int snd_vt1724_pro_internal_clock_info(struct snd_kcontrol *kcontrol, | |||
1787 | struct snd_ctl_elem_info *uinfo) | 1821 | struct snd_ctl_elem_info *uinfo) |
1788 | { | 1822 | { |
1789 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 1823 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
1790 | 1824 | int hw_rates_count = ice->hw_rates->count; | |
1791 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 1825 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
1792 | uinfo->count = 1; | 1826 | uinfo->count = 1; |
1793 | uinfo->value.enumerated.items = ice->hw_rates->count + 1; | 1827 | |
1828 | uinfo->value.enumerated.items = hw_rates_count + ice->ext_clock_count; | ||
1829 | /* upper limit - keep at top */ | ||
1794 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | 1830 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) |
1795 | uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; | 1831 | uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; |
1796 | if (uinfo->value.enumerated.item == uinfo->value.enumerated.items - 1) | 1832 | if (uinfo->value.enumerated.item >= hw_rates_count) |
1797 | strcpy(uinfo->value.enumerated.name, "IEC958 Input"); | 1833 | /* ext_clock items */ |
1834 | strcpy(uinfo->value.enumerated.name, | ||
1835 | ice->ext_clock_names[ | ||
1836 | uinfo->value.enumerated.item - hw_rates_count]); | ||
1798 | else | 1837 | else |
1838 | /* int clock items */ | ||
1799 | sprintf(uinfo->value.enumerated.name, "%d", | 1839 | sprintf(uinfo->value.enumerated.name, "%d", |
1800 | ice->hw_rates->list[uinfo->value.enumerated.item]); | 1840 | ice->hw_rates->list[uinfo->value.enumerated.item]); |
1801 | return 0; | 1841 | return 0; |
@@ -1809,7 +1849,8 @@ static int snd_vt1724_pro_internal_clock_get(struct snd_kcontrol *kcontrol, | |||
1809 | 1849 | ||
1810 | spin_lock_irq(&ice->reg_lock); | 1850 | spin_lock_irq(&ice->reg_lock); |
1811 | if (ice->is_spdif_master(ice)) { | 1851 | if (ice->is_spdif_master(ice)) { |
1812 | ucontrol->value.enumerated.item[0] = ice->hw_rates->count; | 1852 | ucontrol->value.enumerated.item[0] = ice->hw_rates->count + |
1853 | ice->get_spdif_master_type(ice); | ||
1813 | } else { | 1854 | } else { |
1814 | rate = ice->get_rate(ice); | 1855 | rate = ice->get_rate(ice); |
1815 | ucontrol->value.enumerated.item[0] = 0; | 1856 | ucontrol->value.enumerated.item[0] = 0; |
@@ -1824,8 +1865,14 @@ static int snd_vt1724_pro_internal_clock_get(struct snd_kcontrol *kcontrol, | |||
1824 | return 0; | 1865 | return 0; |
1825 | } | 1866 | } |
1826 | 1867 | ||
1868 | static int stdclock_get_spdif_master_type(struct snd_ice1712 *ice) | ||
1869 | { | ||
1870 | /* standard external clock - only single type - SPDIF IN */ | ||
1871 | return 0; | ||
1872 | } | ||
1873 | |||
1827 | /* setting clock to external - SPDIF */ | 1874 | /* setting clock to external - SPDIF */ |
1828 | static void stdclock_set_spdif_clock(struct snd_ice1712 *ice) | 1875 | static int stdclock_set_spdif_clock(struct snd_ice1712 *ice, int type) |
1829 | { | 1876 | { |
1830 | unsigned char oval; | 1877 | unsigned char oval; |
1831 | unsigned char i2s_oval; | 1878 | unsigned char i2s_oval; |
@@ -1834,27 +1881,30 @@ static void stdclock_set_spdif_clock(struct snd_ice1712 *ice) | |||
1834 | /* setting 256fs */ | 1881 | /* setting 256fs */ |
1835 | i2s_oval = inb(ICEMT1724(ice, I2S_FORMAT)); | 1882 | i2s_oval = inb(ICEMT1724(ice, I2S_FORMAT)); |
1836 | outb(i2s_oval & ~VT1724_MT_I2S_MCLK_128X, ICEMT1724(ice, I2S_FORMAT)); | 1883 | outb(i2s_oval & ~VT1724_MT_I2S_MCLK_128X, ICEMT1724(ice, I2S_FORMAT)); |
1884 | return 0; | ||
1837 | } | 1885 | } |
1838 | 1886 | ||
1887 | |||
1839 | static int snd_vt1724_pro_internal_clock_put(struct snd_kcontrol *kcontrol, | 1888 | static int snd_vt1724_pro_internal_clock_put(struct snd_kcontrol *kcontrol, |
1840 | struct snd_ctl_elem_value *ucontrol) | 1889 | struct snd_ctl_elem_value *ucontrol) |
1841 | { | 1890 | { |
1842 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 1891 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
1843 | unsigned int old_rate, new_rate; | 1892 | unsigned int old_rate, new_rate; |
1844 | unsigned int item = ucontrol->value.enumerated.item[0]; | 1893 | unsigned int item = ucontrol->value.enumerated.item[0]; |
1845 | unsigned int spdif = ice->hw_rates->count; | 1894 | unsigned int first_ext_clock = ice->hw_rates->count; |
1846 | 1895 | ||
1847 | if (item > spdif) | 1896 | if (item > first_ext_clock + ice->ext_clock_count - 1) |
1848 | return -EINVAL; | 1897 | return -EINVAL; |
1849 | 1898 | ||
1899 | /* if rate = 0 => external clock */ | ||
1850 | spin_lock_irq(&ice->reg_lock); | 1900 | spin_lock_irq(&ice->reg_lock); |
1851 | if (ice->is_spdif_master(ice)) | 1901 | if (ice->is_spdif_master(ice)) |
1852 | old_rate = 0; | 1902 | old_rate = 0; |
1853 | else | 1903 | else |
1854 | old_rate = ice->get_rate(ice); | 1904 | old_rate = ice->get_rate(ice); |
1855 | if (item == spdif) { | 1905 | if (item >= first_ext_clock) { |
1856 | /* switching to external clock via SPDIF */ | 1906 | /* switching to external clock */ |
1857 | ice->set_spdif_clock(ice); | 1907 | ice->set_spdif_clock(ice, item - first_ext_clock); |
1858 | new_rate = 0; | 1908 | new_rate = 0; |
1859 | } else { | 1909 | } else { |
1860 | /* internal on-card clock */ | 1910 | /* internal on-card clock */ |
@@ -1866,7 +1916,7 @@ static int snd_vt1724_pro_internal_clock_put(struct snd_kcontrol *kcontrol, | |||
1866 | } | 1916 | } |
1867 | spin_unlock_irq(&ice->reg_lock); | 1917 | spin_unlock_irq(&ice->reg_lock); |
1868 | 1918 | ||
1869 | /* the first reset to the SPDIF master mode? */ | 1919 | /* the first switch to the ext. clock mode? */ |
1870 | if (old_rate != new_rate && !new_rate) { | 1920 | if (old_rate != new_rate && !new_rate) { |
1871 | /* notify akm chips as well */ | 1921 | /* notify akm chips as well */ |
1872 | unsigned int i; | 1922 | unsigned int i; |
@@ -2136,6 +2186,7 @@ static struct snd_ice1712_card_info *card_tables[] __devinitdata = { | |||
2136 | snd_vt1724_phase_cards, | 2186 | snd_vt1724_phase_cards, |
2137 | snd_vt1724_wtm_cards, | 2187 | snd_vt1724_wtm_cards, |
2138 | snd_vt1724_se_cards, | 2188 | snd_vt1724_se_cards, |
2189 | snd_vt1724_qtet_cards, | ||
2139 | NULL, | 2190 | NULL, |
2140 | }; | 2191 | }; |
2141 | 2192 | ||
@@ -2434,7 +2485,9 @@ static int __devinit snd_vt1724_create(struct snd_card *card, | |||
2434 | mutex_init(&ice->open_mutex); | 2485 | mutex_init(&ice->open_mutex); |
2435 | mutex_init(&ice->i2c_mutex); | 2486 | mutex_init(&ice->i2c_mutex); |
2436 | ice->gpio.set_mask = snd_vt1724_set_gpio_mask; | 2487 | ice->gpio.set_mask = snd_vt1724_set_gpio_mask; |
2488 | ice->gpio.get_mask = snd_vt1724_get_gpio_mask; | ||
2437 | ice->gpio.set_dir = snd_vt1724_set_gpio_dir; | 2489 | ice->gpio.set_dir = snd_vt1724_set_gpio_dir; |
2490 | ice->gpio.get_dir = snd_vt1724_get_gpio_dir; | ||
2438 | ice->gpio.set_data = snd_vt1724_set_gpio_data; | 2491 | ice->gpio.set_data = snd_vt1724_set_gpio_data; |
2439 | ice->gpio.get_data = snd_vt1724_get_gpio_data; | 2492 | ice->gpio.get_data = snd_vt1724_get_gpio_data; |
2440 | ice->card = card; | 2493 | ice->card = card; |
@@ -2522,6 +2575,9 @@ static int __devinit snd_vt1724_probe(struct pci_dev *pci, | |||
2522 | return err; | 2575 | return err; |
2523 | } | 2576 | } |
2524 | 2577 | ||
2578 | /* field init before calling chip_init */ | ||
2579 | ice->ext_clock_count = 0; | ||
2580 | |||
2525 | for (tbl = card_tables; *tbl; tbl++) { | 2581 | for (tbl = card_tables; *tbl; tbl++) { |
2526 | for (c = *tbl; c->subvendor; c++) { | 2582 | for (c = *tbl; c->subvendor; c++) { |
2527 | if (c->subvendor == ice->eeprom.subvendor) { | 2583 | if (c->subvendor == ice->eeprom.subvendor) { |
@@ -2560,6 +2616,13 @@ __found: | |||
2560 | ice->set_mclk = stdclock_set_mclk; | 2616 | ice->set_mclk = stdclock_set_mclk; |
2561 | if (!ice->set_spdif_clock) | 2617 | if (!ice->set_spdif_clock) |
2562 | ice->set_spdif_clock = stdclock_set_spdif_clock; | 2618 | ice->set_spdif_clock = stdclock_set_spdif_clock; |
2619 | if (!ice->get_spdif_master_type) | ||
2620 | ice->get_spdif_master_type = stdclock_get_spdif_master_type; | ||
2621 | if (!ice->ext_clock_names) | ||
2622 | ice->ext_clock_names = ext_clock_names; | ||
2623 | if (!ice->ext_clock_count) | ||
2624 | ice->ext_clock_count = ARRAY_SIZE(ext_clock_names); | ||
2625 | |||
2563 | if (!ice->hw_rates) | 2626 | if (!ice->hw_rates) |
2564 | set_std_hw_rates(ice); | 2627 | set_std_hw_rates(ice); |
2565 | 2628 | ||
@@ -2719,7 +2782,7 @@ static int snd_vt1724_resume(struct pci_dev *pci) | |||
2719 | 2782 | ||
2720 | if (ice->pm_saved_is_spdif_master) { | 2783 | if (ice->pm_saved_is_spdif_master) { |
2721 | /* switching to external clock via SPDIF */ | 2784 | /* switching to external clock via SPDIF */ |
2722 | ice->set_spdif_clock(ice); | 2785 | ice->set_spdif_clock(ice, 0); |
2723 | } else { | 2786 | } else { |
2724 | /* internal on-card clock */ | 2787 | /* internal on-card clock */ |
2725 | snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 1); | 2788 | snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 1); |