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 | |
parent | 9e298f449e667833c4cafad040ce8025a8ba1eed (diff) | |
parent | 6ef80706184be792499a4485a7957f2660b6a076 (diff) |
Merge branch 'topic/ice1724-quartet' into topic/hda
Diffstat (limited to 'sound/pci/ice1712')
-rw-r--r-- | sound/pci/ice1712/Makefile | 2 | ||||
-rw-r--r-- | sound/pci/ice1712/ice1712.c | 12 | ||||
-rw-r--r-- | sound/pci/ice1712/ice1712.h | 14 | ||||
-rw-r--r-- | sound/pci/ice1712/ice1724.c | 103 | ||||
-rw-r--r-- | sound/pci/ice1712/juli.c | 24 | ||||
-rw-r--r-- | sound/pci/ice1712/quartet.c | 1130 | ||||
-rw-r--r-- | sound/pci/ice1712/quartet.h | 10 |
7 files changed, 1250 insertions, 45 deletions
diff --git a/sound/pci/ice1712/Makefile b/sound/pci/ice1712/Makefile index 536eae2ccf94..f7ce33f00ea5 100644 --- a/sound/pci/ice1712/Makefile +++ b/sound/pci/ice1712/Makefile | |||
@@ -5,7 +5,7 @@ | |||
5 | 5 | ||
6 | snd-ice17xx-ak4xxx-objs := ak4xxx.o | 6 | snd-ice17xx-ak4xxx-objs := ak4xxx.o |
7 | snd-ice1712-objs := ice1712.o delta.o hoontech.o ews.o | 7 | snd-ice1712-objs := ice1712.o delta.o hoontech.o ews.o |
8 | snd-ice1724-objs := ice1724.o amp.o revo.o aureon.o vt1720_mobo.o pontis.o prodigy192.o prodigy_hifi.o juli.o phase.o wtm.o se.o maya44.o | 8 | snd-ice1724-objs := ice1724.o amp.o revo.o aureon.o vt1720_mobo.o pontis.o prodigy192.o prodigy_hifi.o juli.o phase.o wtm.o se.o maya44.o quartet.o |
9 | 9 | ||
10 | # Toplevel Module Dependency | 10 | # Toplevel Module Dependency |
11 | obj-$(CONFIG_SND_ICE1712) += snd-ice1712.o snd-ice17xx-ak4xxx.o | 11 | obj-$(CONFIG_SND_ICE1712) += snd-ice1712.o snd-ice17xx-ak4xxx.o |
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c index d74033a2cfbe..c7cff6f8168a 100644 --- a/sound/pci/ice1712/ice1712.c +++ b/sound/pci/ice1712/ice1712.c | |||
@@ -298,6 +298,16 @@ static void snd_ice1712_set_gpio_dir(struct snd_ice1712 *ice, unsigned int data) | |||
298 | inb(ICEREG(ice, DATA)); /* dummy read for pci-posting */ | 298 | inb(ICEREG(ice, DATA)); /* dummy read for pci-posting */ |
299 | } | 299 | } |
300 | 300 | ||
301 | static unsigned int snd_ice1712_get_gpio_dir(struct snd_ice1712 *ice) | ||
302 | { | ||
303 | return snd_ice1712_read(ice, ICE1712_IREG_GPIO_DIRECTION); | ||
304 | } | ||
305 | |||
306 | static unsigned int snd_ice1712_get_gpio_mask(struct snd_ice1712 *ice) | ||
307 | { | ||
308 | return snd_ice1712_read(ice, ICE1712_IREG_GPIO_WRITE_MASK); | ||
309 | } | ||
310 | |||
301 | static void snd_ice1712_set_gpio_mask(struct snd_ice1712 *ice, unsigned int data) | 311 | static void snd_ice1712_set_gpio_mask(struct snd_ice1712 *ice, unsigned int data) |
302 | { | 312 | { |
303 | snd_ice1712_write(ice, ICE1712_IREG_GPIO_WRITE_MASK, data); | 313 | snd_ice1712_write(ice, ICE1712_IREG_GPIO_WRITE_MASK, data); |
@@ -2557,7 +2567,9 @@ static int __devinit snd_ice1712_create(struct snd_card *card, | |||
2557 | mutex_init(&ice->i2c_mutex); | 2567 | mutex_init(&ice->i2c_mutex); |
2558 | mutex_init(&ice->open_mutex); | 2568 | mutex_init(&ice->open_mutex); |
2559 | ice->gpio.set_mask = snd_ice1712_set_gpio_mask; | 2569 | ice->gpio.set_mask = snd_ice1712_set_gpio_mask; |
2570 | ice->gpio.get_mask = snd_ice1712_get_gpio_mask; | ||
2560 | ice->gpio.set_dir = snd_ice1712_set_gpio_dir; | 2571 | ice->gpio.set_dir = snd_ice1712_set_gpio_dir; |
2572 | ice->gpio.get_dir = snd_ice1712_get_gpio_dir; | ||
2561 | ice->gpio.set_data = snd_ice1712_set_gpio_data; | 2573 | ice->gpio.set_data = snd_ice1712_set_gpio_data; |
2562 | ice->gpio.get_data = snd_ice1712_get_gpio_data; | 2574 | ice->gpio.get_data = snd_ice1712_get_gpio_data; |
2563 | 2575 | ||
diff --git a/sound/pci/ice1712/ice1712.h b/sound/pci/ice1712/ice1712.h index 9da2dae64c5b..4615bca39e18 100644 --- a/sound/pci/ice1712/ice1712.h +++ b/sound/pci/ice1712/ice1712.h | |||
@@ -359,7 +359,9 @@ struct snd_ice1712 { | |||
359 | unsigned int saved[2]; /* for ewx_i2c */ | 359 | unsigned int saved[2]; /* for ewx_i2c */ |
360 | /* operators */ | 360 | /* operators */ |
361 | void (*set_mask)(struct snd_ice1712 *ice, unsigned int data); | 361 | void (*set_mask)(struct snd_ice1712 *ice, unsigned int data); |
362 | unsigned int (*get_mask)(struct snd_ice1712 *ice); | ||
362 | void (*set_dir)(struct snd_ice1712 *ice, unsigned int data); | 363 | void (*set_dir)(struct snd_ice1712 *ice, unsigned int data); |
364 | unsigned int (*get_dir)(struct snd_ice1712 *ice); | ||
363 | void (*set_data)(struct snd_ice1712 *ice, unsigned int data); | 365 | void (*set_data)(struct snd_ice1712 *ice, unsigned int data); |
364 | unsigned int (*get_data)(struct snd_ice1712 *ice); | 366 | unsigned int (*get_data)(struct snd_ice1712 *ice); |
365 | /* misc operators - move to another place? */ | 367 | /* misc operators - move to another place? */ |
@@ -377,8 +379,11 @@ struct snd_ice1712 { | |||
377 | unsigned int (*get_rate)(struct snd_ice1712 *ice); | 379 | unsigned int (*get_rate)(struct snd_ice1712 *ice); |
378 | void (*set_rate)(struct snd_ice1712 *ice, unsigned int rate); | 380 | void (*set_rate)(struct snd_ice1712 *ice, unsigned int rate); |
379 | unsigned char (*set_mclk)(struct snd_ice1712 *ice, unsigned int rate); | 381 | unsigned char (*set_mclk)(struct snd_ice1712 *ice, unsigned int rate); |
380 | void (*set_spdif_clock)(struct snd_ice1712 *ice); | 382 | int (*set_spdif_clock)(struct snd_ice1712 *ice, int type); |
381 | 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 *); | ||
382 | #ifdef CONFIG_PM | 387 | #ifdef CONFIG_PM |
383 | int (*pm_suspend)(struct snd_ice1712 *); | 388 | int (*pm_suspend)(struct snd_ice1712 *); |
384 | int (*pm_resume)(struct snd_ice1712 *); | 389 | int (*pm_resume)(struct snd_ice1712 *); |
@@ -399,6 +404,11 @@ static inline void snd_ice1712_gpio_set_dir(struct snd_ice1712 *ice, unsigned in | |||
399 | ice->gpio.set_dir(ice, bits); | 404 | ice->gpio.set_dir(ice, bits); |
400 | } | 405 | } |
401 | 406 | ||
407 | static inline unsigned int snd_ice1712_gpio_get_dir(struct snd_ice1712 *ice) | ||
408 | { | ||
409 | return ice->gpio.get_dir(ice); | ||
410 | } | ||
411 | |||
402 | static inline void snd_ice1712_gpio_set_mask(struct snd_ice1712 *ice, unsigned int bits) | 412 | static inline void snd_ice1712_gpio_set_mask(struct snd_ice1712 *ice, unsigned int bits) |
403 | { | 413 | { |
404 | ice->gpio.set_mask(ice, bits); | 414 | ice->gpio.set_mask(ice, bits); |
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); |
diff --git a/sound/pci/ice1712/juli.c b/sound/pci/ice1712/juli.c index fd948bfd9aef..4bed9633a4cd 100644 --- a/sound/pci/ice1712/juli.c +++ b/sound/pci/ice1712/juli.c | |||
@@ -412,25 +412,6 @@ static struct snd_kcontrol_new juli_mute_controls[] __devinitdata = { | |||
412 | }, | 412 | }, |
413 | }; | 413 | }; |
414 | 414 | ||
415 | |||
416 | static void ak4358_proc_regs_read(struct snd_info_entry *entry, | ||
417 | struct snd_info_buffer *buffer) | ||
418 | { | ||
419 | struct snd_ice1712 *ice = (struct snd_ice1712 *)entry->private_data; | ||
420 | int reg, val; | ||
421 | for (reg = 0; reg <= 0xf; reg++) { | ||
422 | val = snd_akm4xxx_get(ice->akm, 0, reg); | ||
423 | snd_iprintf(buffer, "0x%02x = 0x%02x\n", reg, val); | ||
424 | } | ||
425 | } | ||
426 | |||
427 | static void ak4358_proc_init(struct snd_ice1712 *ice) | ||
428 | { | ||
429 | struct snd_info_entry *entry; | ||
430 | if (!snd_card_proc_new(ice->card, "ak4358_codec", &entry)) | ||
431 | snd_info_set_text_ops(entry, ice, ak4358_proc_regs_read); | ||
432 | } | ||
433 | |||
434 | static char *slave_vols[] __devinitdata = { | 415 | static char *slave_vols[] __devinitdata = { |
435 | PCM_VOLUME, | 416 | PCM_VOLUME, |
436 | MONITOR_AN_IN_VOLUME, | 417 | MONITOR_AN_IN_VOLUME, |
@@ -496,8 +477,6 @@ static int __devinit juli_add_controls(struct snd_ice1712 *ice) | |||
496 | /* only capture SPDIF over AK4114 */ | 477 | /* only capture SPDIF over AK4114 */ |
497 | err = snd_ak4114_build(spec->ak4114, NULL, | 478 | err = snd_ak4114_build(spec->ak4114, NULL, |
498 | ice->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream); | 479 | ice->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream); |
499 | |||
500 | ak4358_proc_init(ice); | ||
501 | if (err < 0) | 480 | if (err < 0) |
502 | return err; | 481 | return err; |
503 | return 0; | 482 | return 0; |
@@ -550,13 +529,14 @@ static inline unsigned char juli_set_mclk(struct snd_ice1712 *ice, | |||
550 | } | 529 | } |
551 | 530 | ||
552 | /* setting clock to external - SPDIF */ | 531 | /* setting clock to external - SPDIF */ |
553 | static void juli_set_spdif_clock(struct snd_ice1712 *ice) | 532 | static int juli_set_spdif_clock(struct snd_ice1712 *ice, int type) |
554 | { | 533 | { |
555 | unsigned int old; | 534 | unsigned int old; |
556 | old = ice->gpio.get_data(ice); | 535 | old = ice->gpio.get_data(ice); |
557 | /* external clock (= 0), multiply 1x, 48kHz */ | 536 | /* external clock (= 0), multiply 1x, 48kHz */ |
558 | 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 | |
559 | GPIO_FREQ_48KHZ); | 538 | GPIO_FREQ_48KHZ); |
539 | return 0; | ||
560 | } | 540 | } |
561 | 541 | ||
562 | /* Called when ak4114 detects change in the input SPDIF stream */ | 542 | /* Called when ak4114 detects change in the input SPDIF stream */ |
diff --git a/sound/pci/ice1712/quartet.c b/sound/pci/ice1712/quartet.c new file mode 100644 index 000000000000..1948632787e6 --- /dev/null +++ b/sound/pci/ice1712/quartet.c | |||
@@ -0,0 +1,1130 @@ | |||
1 | /* | ||
2 | * ALSA driver for ICEnsemble VT1724 (Envy24HT) | ||
3 | * | ||
4 | * Lowlevel functions for Infrasonic Quartet | ||
5 | * | ||
6 | * Copyright (c) 2009 Pavel Hofman <pavel.hofman@ivitera.com> | ||
7 | * | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #include <asm/io.h> | ||
26 | #include <linux/delay.h> | ||
27 | #include <linux/interrupt.h> | ||
28 | #include <linux/init.h> | ||
29 | #include <linux/slab.h> | ||
30 | #include <sound/core.h> | ||
31 | #include <sound/tlv.h> | ||
32 | #include <sound/info.h> | ||
33 | |||
34 | #include "ice1712.h" | ||
35 | #include "envy24ht.h" | ||
36 | #include <sound/ak4113.h> | ||
37 | #include "quartet.h" | ||
38 | |||
39 | struct qtet_spec { | ||
40 | struct ak4113 *ak4113; | ||
41 | unsigned int scr; /* system control register */ | ||
42 | unsigned int mcr; /* monitoring control register */ | ||
43 | unsigned int cpld; /* cpld register */ | ||
44 | }; | ||
45 | |||
46 | struct qtet_kcontrol_private { | ||
47 | unsigned int bit; | ||
48 | void (*set_register)(struct snd_ice1712 *ice, unsigned int val); | ||
49 | unsigned int (*get_register)(struct snd_ice1712 *ice); | ||
50 | unsigned char *texts[2]; | ||
51 | }; | ||
52 | |||
53 | enum { | ||
54 | IN12_SEL = 0, | ||
55 | IN34_SEL, | ||
56 | AIN34_SEL, | ||
57 | COAX_OUT, | ||
58 | IN12_MON12, | ||
59 | IN12_MON34, | ||
60 | IN34_MON12, | ||
61 | IN34_MON34, | ||
62 | OUT12_MON34, | ||
63 | OUT34_MON12, | ||
64 | }; | ||
65 | |||
66 | static char *ext_clock_names[3] = {"IEC958 In", "Word Clock 1xFS", | ||
67 | "Word Clock 256xFS"}; | ||
68 | |||
69 | /* chip address on I2C bus */ | ||
70 | #define AK4113_ADDR 0x26 /* S/PDIF receiver */ | ||
71 | |||
72 | /* chip address on SPI bus */ | ||
73 | #define AK4620_ADDR 0x02 /* ADC/DAC */ | ||
74 | |||
75 | |||
76 | /* | ||
77 | * GPIO pins | ||
78 | */ | ||
79 | |||
80 | /* GPIO0 - O - DATA0, def. 0 */ | ||
81 | #define GPIO_D0 (1<<0) | ||
82 | /* GPIO1 - I/O - DATA1, Jack Detect Input0 (0:present, 1:missing), def. 1 */ | ||
83 | #define GPIO_D1_JACKDTC0 (1<<1) | ||
84 | /* GPIO2 - I/O - DATA2, Jack Detect Input1 (0:present, 1:missing), def. 1 */ | ||
85 | #define GPIO_D2_JACKDTC1 (1<<2) | ||
86 | /* GPIO3 - I/O - DATA3, def. 1 */ | ||
87 | #define GPIO_D3 (1<<3) | ||
88 | /* GPIO4 - I/O - DATA4, SPI CDTO, def. 1 */ | ||
89 | #define GPIO_D4_SPI_CDTO (1<<4) | ||
90 | /* GPIO5 - I/O - DATA5, SPI CCLK, def. 1 */ | ||
91 | #define GPIO_D5_SPI_CCLK (1<<5) | ||
92 | /* GPIO6 - I/O - DATA6, Cable Detect Input (0:detected, 1:not detected */ | ||
93 | #define GPIO_D6_CD (1<<6) | ||
94 | /* GPIO7 - I/O - DATA7, Device Detect Input (0:detected, 1:not detected */ | ||
95 | #define GPIO_D7_DD (1<<7) | ||
96 | /* GPIO8 - O - CPLD Chip Select, def. 1 */ | ||
97 | #define GPIO_CPLD_CSN (1<<8) | ||
98 | /* GPIO9 - O - CPLD register read/write (0:write, 1:read), def. 0 */ | ||
99 | #define GPIO_CPLD_RW (1<<9) | ||
100 | /* GPIO10 - O - SPI Chip Select for CODEC#0, def. 1 */ | ||
101 | #define GPIO_SPI_CSN0 (1<<10) | ||
102 | /* GPIO11 - O - SPI Chip Select for CODEC#1, def. 1 */ | ||
103 | #define GPIO_SPI_CSN1 (1<<11) | ||
104 | /* GPIO12 - O - Ex. Register Output Enable (0:enable, 1:disable), def. 1, | ||
105 | * init 0 */ | ||
106 | #define GPIO_EX_GPIOE (1<<12) | ||
107 | /* GPIO13 - O - Ex. Register0 Chip Select for System Control Register, | ||
108 | * def. 1 */ | ||
109 | #define GPIO_SCR (1<<13) | ||
110 | /* GPIO14 - O - Ex. Register1 Chip Select for Monitor Control Register, | ||
111 | * def. 1 */ | ||
112 | #define GPIO_MCR (1<<14) | ||
113 | |||
114 | #define GPIO_SPI_ALL (GPIO_D4_SPI_CDTO | GPIO_D5_SPI_CCLK |\ | ||
115 | GPIO_SPI_CSN0 | GPIO_SPI_CSN1) | ||
116 | |||
117 | #define GPIO_DATA_MASK (GPIO_D0 | GPIO_D1_JACKDTC0 | \ | ||
118 | GPIO_D2_JACKDTC1 | GPIO_D3 | \ | ||
119 | GPIO_D4_SPI_CDTO | GPIO_D5_SPI_CCLK | \ | ||
120 | GPIO_D6_CD | GPIO_D7_DD) | ||
121 | |||
122 | /* System Control Register GPIO_SCR data bits */ | ||
123 | /* Mic/Line select relay (0:line, 1:mic) */ | ||
124 | #define SCR_RELAY GPIO_D0 | ||
125 | /* Phantom power drive control (0:5V, 1:48V) */ | ||
126 | #define SCR_PHP_V GPIO_D1_JACKDTC0 | ||
127 | /* H/W mute control (0:Normal, 1:Mute) */ | ||
128 | #define SCR_MUTE GPIO_D2_JACKDTC1 | ||
129 | /* Phantom power control (0:Phantom on, 1:off) */ | ||
130 | #define SCR_PHP GPIO_D3 | ||
131 | /* Analog input 1/2 Source Select */ | ||
132 | #define SCR_AIN12_SEL0 GPIO_D4_SPI_CDTO | ||
133 | #define SCR_AIN12_SEL1 GPIO_D5_SPI_CCLK | ||
134 | /* Analog input 3/4 Source Select (0:line, 1:hi-z) */ | ||
135 | #define SCR_AIN34_SEL GPIO_D6_CD | ||
136 | /* Codec Power Down (0:power down, 1:normal) */ | ||
137 | #define SCR_CODEC_PDN GPIO_D7_DD | ||
138 | |||
139 | #define SCR_AIN12_LINE (0) | ||
140 | #define SCR_AIN12_MIC (SCR_AIN12_SEL0) | ||
141 | #define SCR_AIN12_LOWCUT (SCR_AIN12_SEL1 | SCR_AIN12_SEL0) | ||
142 | |||
143 | /* Monitor Control Register GPIO_MCR data bits */ | ||
144 | /* Input 1/2 to Monitor 1/2 (0:off, 1:on) */ | ||
145 | #define MCR_IN12_MON12 GPIO_D0 | ||
146 | /* Input 1/2 to Monitor 3/4 (0:off, 1:on) */ | ||
147 | #define MCR_IN12_MON34 GPIO_D1_JACKDTC0 | ||
148 | /* Input 3/4 to Monitor 1/2 (0:off, 1:on) */ | ||
149 | #define MCR_IN34_MON12 GPIO_D2_JACKDTC1 | ||
150 | /* Input 3/4 to Monitor 3/4 (0:off, 1:on) */ | ||
151 | #define MCR_IN34_MON34 GPIO_D3 | ||
152 | /* Output to Monitor 1/2 (0:off, 1:on) */ | ||
153 | #define MCR_OUT34_MON12 GPIO_D4_SPI_CDTO | ||
154 | /* Output to Monitor 3/4 (0:off, 1:on) */ | ||
155 | #define MCR_OUT12_MON34 GPIO_D5_SPI_CCLK | ||
156 | |||
157 | /* CPLD Register DATA bits */ | ||
158 | /* Clock Rate Select */ | ||
159 | #define CPLD_CKS0 GPIO_D0 | ||
160 | #define CPLD_CKS1 GPIO_D1_JACKDTC0 | ||
161 | #define CPLD_CKS2 GPIO_D2_JACKDTC1 | ||
162 | /* Sync Source Select (0:Internal, 1:External) */ | ||
163 | #define CPLD_SYNC_SEL GPIO_D3 | ||
164 | /* Word Clock FS Select (0:FS, 1:256FS) */ | ||
165 | #define CPLD_WORD_SEL GPIO_D4_SPI_CDTO | ||
166 | /* Coaxial Output Source (IS-Link) (0:SPDIF, 1:I2S) */ | ||
167 | #define CPLD_COAX_OUT GPIO_D5_SPI_CCLK | ||
168 | /* Input 1/2 Source Select (0:Analog12, 1:An34) */ | ||
169 | #define CPLD_IN12_SEL GPIO_D6_CD | ||
170 | /* Input 3/4 Source Select (0:Analog34, 1:Digital In) */ | ||
171 | #define CPLD_IN34_SEL GPIO_D7_DD | ||
172 | |||
173 | /* internal clock (CPLD_SYNC_SEL = 0) options */ | ||
174 | #define CPLD_CKS_44100HZ (0) | ||
175 | #define CPLD_CKS_48000HZ (CPLD_CKS0) | ||
176 | #define CPLD_CKS_88200HZ (CPLD_CKS1) | ||
177 | #define CPLD_CKS_96000HZ (CPLD_CKS1 | CPLD_CKS0) | ||
178 | #define CPLD_CKS_176400HZ (CPLD_CKS2) | ||
179 | #define CPLD_CKS_192000HZ (CPLD_CKS2 | CPLD_CKS0) | ||
180 | |||
181 | #define CPLD_CKS_MASK (CPLD_CKS0 | CPLD_CKS1 | CPLD_CKS2) | ||
182 | |||
183 | /* external clock (CPLD_SYNC_SEL = 1) options */ | ||
184 | /* external clock - SPDIF */ | ||
185 | #define CPLD_EXT_SPDIF (0 | CPLD_SYNC_SEL) | ||
186 | /* external clock - WordClock 1xfs */ | ||
187 | #define CPLD_EXT_WORDCLOCK_1FS (CPLD_CKS1 | CPLD_SYNC_SEL) | ||
188 | /* external clock - WordClock 256xfs */ | ||
189 | #define CPLD_EXT_WORDCLOCK_256FS (CPLD_CKS1 | CPLD_WORD_SEL |\ | ||
190 | CPLD_SYNC_SEL) | ||
191 | |||
192 | #define EXT_SPDIF_TYPE 0 | ||
193 | #define EXT_WORDCLOCK_1FS_TYPE 1 | ||
194 | #define EXT_WORDCLOCK_256FS_TYPE 2 | ||
195 | |||
196 | #define AK4620_DFS0 (1<<0) | ||
197 | #define AK4620_DFS1 (1<<1) | ||
198 | #define AK4620_CKS0 (1<<2) | ||
199 | #define AK4620_CKS1 (1<<3) | ||
200 | /* Clock and Format Control register */ | ||
201 | #define AK4620_DFS_REG 0x02 | ||
202 | |||
203 | /* Deem and Volume Control register */ | ||
204 | #define AK4620_DEEMVOL_REG 0x03 | ||
205 | #define AK4620_SMUTE (1<<7) | ||
206 | |||
207 | /* | ||
208 | * Conversion from int value to its binary form. Used for debugging. | ||
209 | * The output buffer must be allocated prior to calling the function. | ||
210 | */ | ||
211 | static char *get_binary(char *buffer, int value) | ||
212 | { | ||
213 | int i, j, pos; | ||
214 | pos = 0; | ||
215 | for (i = 0; i < 4; ++i) { | ||
216 | for (j = 0; j < 8; ++j) { | ||
217 | if (value & (1 << (31-(i*8 + j)))) | ||
218 | buffer[pos] = '1'; | ||
219 | else | ||
220 | buffer[pos] = '0'; | ||
221 | pos++; | ||
222 | } | ||
223 | if (i < 3) { | ||
224 | buffer[pos] = ' '; | ||
225 | pos++; | ||
226 | } | ||
227 | } | ||
228 | buffer[pos] = '\0'; | ||
229 | return buffer; | ||
230 | } | ||
231 | |||
232 | /* | ||
233 | * Initial setup of the conversion array GPIO <-> rate | ||
234 | */ | ||
235 | static unsigned int qtet_rates[] = { | ||
236 | 44100, 48000, 88200, | ||
237 | 96000, 176400, 192000, | ||
238 | }; | ||
239 | |||
240 | static unsigned int cks_vals[] = { | ||
241 | CPLD_CKS_44100HZ, CPLD_CKS_48000HZ, CPLD_CKS_88200HZ, | ||
242 | CPLD_CKS_96000HZ, CPLD_CKS_176400HZ, CPLD_CKS_192000HZ, | ||
243 | }; | ||
244 | |||
245 | static struct snd_pcm_hw_constraint_list qtet_rates_info = { | ||
246 | .count = ARRAY_SIZE(qtet_rates), | ||
247 | .list = qtet_rates, | ||
248 | .mask = 0, | ||
249 | }; | ||
250 | |||
251 | static void qtet_ak4113_write(void *private_data, unsigned char reg, | ||
252 | unsigned char val) | ||
253 | { | ||
254 | snd_vt1724_write_i2c((struct snd_ice1712 *)private_data, AK4113_ADDR, | ||
255 | reg, val); | ||
256 | } | ||
257 | |||
258 | static unsigned char qtet_ak4113_read(void *private_data, unsigned char reg) | ||
259 | { | ||
260 | return snd_vt1724_read_i2c((struct snd_ice1712 *)private_data, | ||
261 | AK4113_ADDR, reg); | ||
262 | } | ||
263 | |||
264 | |||
265 | /* | ||
266 | * AK4620 section | ||
267 | */ | ||
268 | |||
269 | /* | ||
270 | * Write data to addr register of ak4620 | ||
271 | */ | ||
272 | static void qtet_akm_write(struct snd_akm4xxx *ak, int chip, | ||
273 | unsigned char addr, unsigned char data) | ||
274 | { | ||
275 | unsigned int tmp, orig_dir; | ||
276 | int idx; | ||
277 | unsigned int addrdata; | ||
278 | struct snd_ice1712 *ice = ak->private_data[0]; | ||
279 | |||
280 | if (snd_BUG_ON(chip < 0 || chip >= 4)) | ||
281 | return; | ||
282 | /*printk(KERN_DEBUG "Writing to AK4620: chip=%d, addr=0x%x, | ||
283 | data=0x%x\n", chip, addr, data);*/ | ||
284 | orig_dir = ice->gpio.get_dir(ice); | ||
285 | ice->gpio.set_dir(ice, orig_dir | GPIO_SPI_ALL); | ||
286 | /* set mask - only SPI bits */ | ||
287 | ice->gpio.set_mask(ice, ~GPIO_SPI_ALL); | ||
288 | |||
289 | tmp = ice->gpio.get_data(ice); | ||
290 | /* high all */ | ||
291 | tmp |= GPIO_SPI_ALL; | ||
292 | ice->gpio.set_data(ice, tmp); | ||
293 | udelay(100); | ||
294 | /* drop chip select */ | ||
295 | if (chip) | ||
296 | /* CODEC 1 */ | ||
297 | tmp &= ~GPIO_SPI_CSN1; | ||
298 | else | ||
299 | tmp &= ~GPIO_SPI_CSN0; | ||
300 | ice->gpio.set_data(ice, tmp); | ||
301 | udelay(100); | ||
302 | |||
303 | /* build I2C address + data byte */ | ||
304 | addrdata = (AK4620_ADDR << 6) | 0x20 | (addr & 0x1f); | ||
305 | addrdata = (addrdata << 8) | data; | ||
306 | for (idx = 15; idx >= 0; idx--) { | ||
307 | /* drop clock */ | ||
308 | tmp &= ~GPIO_D5_SPI_CCLK; | ||
309 | ice->gpio.set_data(ice, tmp); | ||
310 | udelay(100); | ||
311 | /* set data */ | ||
312 | if (addrdata & (1 << idx)) | ||
313 | tmp |= GPIO_D4_SPI_CDTO; | ||
314 | else | ||
315 | tmp &= ~GPIO_D4_SPI_CDTO; | ||
316 | ice->gpio.set_data(ice, tmp); | ||
317 | udelay(100); | ||
318 | /* raise clock */ | ||
319 | tmp |= GPIO_D5_SPI_CCLK; | ||
320 | ice->gpio.set_data(ice, tmp); | ||
321 | udelay(100); | ||
322 | } | ||
323 | /* all back to 1 */ | ||
324 | tmp |= GPIO_SPI_ALL; | ||
325 | ice->gpio.set_data(ice, tmp); | ||
326 | udelay(100); | ||
327 | |||
328 | /* return all gpios to non-writable */ | ||
329 | ice->gpio.set_mask(ice, 0xffffff); | ||
330 | /* restore GPIOs direction */ | ||
331 | ice->gpio.set_dir(ice, orig_dir); | ||
332 | } | ||
333 | |||
334 | static void qtet_akm_set_regs(struct snd_akm4xxx *ak, unsigned char addr, | ||
335 | unsigned char mask, unsigned char value) | ||
336 | { | ||
337 | unsigned char tmp; | ||
338 | int chip; | ||
339 | for (chip = 0; chip < ak->num_chips; chip++) { | ||
340 | tmp = snd_akm4xxx_get(ak, chip, addr); | ||
341 | /* clear the bits */ | ||
342 | tmp &= ~mask; | ||
343 | /* set the new bits */ | ||
344 | tmp |= value; | ||
345 | snd_akm4xxx_write(ak, chip, addr, tmp); | ||
346 | } | ||
347 | } | ||
348 | |||
349 | /* | ||
350 | * change the rate of AK4620 | ||
351 | */ | ||
352 | static void qtet_akm_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate) | ||
353 | { | ||
354 | unsigned char ak4620_dfs; | ||
355 | |||
356 | if (rate == 0) /* no hint - S/PDIF input is master or the new spdif | ||
357 | input rate undetected, simply return */ | ||
358 | return; | ||
359 | |||
360 | /* adjust DFS on codecs - see datasheet */ | ||
361 | if (rate > 108000) | ||
362 | ak4620_dfs = AK4620_DFS1 | AK4620_CKS1; | ||
363 | else if (rate > 54000) | ||
364 | ak4620_dfs = AK4620_DFS0 | AK4620_CKS0; | ||
365 | else | ||
366 | ak4620_dfs = 0; | ||
367 | |||
368 | /* set new value */ | ||
369 | qtet_akm_set_regs(ak, AK4620_DFS_REG, AK4620_DFS0 | AK4620_DFS1 | | ||
370 | AK4620_CKS0 | AK4620_CKS1, ak4620_dfs); | ||
371 | } | ||
372 | |||
373 | #define AK_CONTROL(xname, xch) { .name = xname, .num_channels = xch } | ||
374 | |||
375 | #define PCM_12_PLAYBACK_VOLUME "PCM 1/2 Playback Volume" | ||
376 | #define PCM_34_PLAYBACK_VOLUME "PCM 3/4 Playback Volume" | ||
377 | #define PCM_12_CAPTURE_VOLUME "PCM 1/2 Capture Volume" | ||
378 | #define PCM_34_CAPTURE_VOLUME "PCM 3/4 Capture Volume" | ||
379 | |||
380 | static const struct snd_akm4xxx_dac_channel qtet_dac[] = { | ||
381 | AK_CONTROL(PCM_12_PLAYBACK_VOLUME, 2), | ||
382 | AK_CONTROL(PCM_34_PLAYBACK_VOLUME, 2), | ||
383 | }; | ||
384 | |||
385 | static const struct snd_akm4xxx_adc_channel qtet_adc[] = { | ||
386 | AK_CONTROL(PCM_12_CAPTURE_VOLUME, 2), | ||
387 | AK_CONTROL(PCM_34_CAPTURE_VOLUME, 2), | ||
388 | }; | ||
389 | |||
390 | static struct snd_akm4xxx akm_qtet_dac __devinitdata = { | ||
391 | .type = SND_AK4620, | ||
392 | .num_dacs = 4, /* DAC1 - Output 12 | ||
393 | */ | ||
394 | .num_adcs = 4, /* ADC1 - Input 12 | ||
395 | */ | ||
396 | .ops = { | ||
397 | .write = qtet_akm_write, | ||
398 | .set_rate_val = qtet_akm_set_rate_val, | ||
399 | }, | ||
400 | .dac_info = qtet_dac, | ||
401 | .adc_info = qtet_adc, | ||
402 | }; | ||
403 | |||
404 | /* Communication routines with the CPLD */ | ||
405 | |||
406 | |||
407 | /* Writes data to external register reg, both reg and data are | ||
408 | * GPIO representations */ | ||
409 | static void reg_write(struct snd_ice1712 *ice, unsigned int reg, | ||
410 | unsigned int data) | ||
411 | { | ||
412 | unsigned int tmp; | ||
413 | |||
414 | mutex_lock(&ice->gpio_mutex); | ||
415 | /* set direction of used GPIOs*/ | ||
416 | /* all outputs */ | ||
417 | tmp = 0x00ffff; | ||
418 | ice->gpio.set_dir(ice, tmp); | ||
419 | /* mask - writable bits */ | ||
420 | ice->gpio.set_mask(ice, ~(tmp)); | ||
421 | /* write the data */ | ||
422 | tmp = ice->gpio.get_data(ice); | ||
423 | tmp &= ~GPIO_DATA_MASK; | ||
424 | tmp |= data; | ||
425 | ice->gpio.set_data(ice, tmp); | ||
426 | udelay(100); | ||
427 | /* drop output enable */ | ||
428 | tmp &= ~GPIO_EX_GPIOE; | ||
429 | ice->gpio.set_data(ice, tmp); | ||
430 | udelay(100); | ||
431 | /* drop the register gpio */ | ||
432 | tmp &= ~reg; | ||
433 | ice->gpio.set_data(ice, tmp); | ||
434 | udelay(100); | ||
435 | /* raise the register GPIO */ | ||
436 | tmp |= reg; | ||
437 | ice->gpio.set_data(ice, tmp); | ||
438 | udelay(100); | ||
439 | |||
440 | /* raise all data gpios */ | ||
441 | tmp |= GPIO_DATA_MASK; | ||
442 | ice->gpio.set_data(ice, tmp); | ||
443 | /* mask - immutable bits */ | ||
444 | ice->gpio.set_mask(ice, 0xffffff); | ||
445 | /* outputs only 8-15 */ | ||
446 | ice->gpio.set_dir(ice, 0x00ff00); | ||
447 | mutex_unlock(&ice->gpio_mutex); | ||
448 | } | ||
449 | |||
450 | static unsigned int get_scr(struct snd_ice1712 *ice) | ||
451 | { | ||
452 | struct qtet_spec *spec = ice->spec; | ||
453 | return spec->scr; | ||
454 | } | ||
455 | |||
456 | static unsigned int get_mcr(struct snd_ice1712 *ice) | ||
457 | { | ||
458 | struct qtet_spec *spec = ice->spec; | ||
459 | return spec->mcr; | ||
460 | } | ||
461 | |||
462 | static unsigned int get_cpld(struct snd_ice1712 *ice) | ||
463 | { | ||
464 | struct qtet_spec *spec = ice->spec; | ||
465 | return spec->cpld; | ||
466 | } | ||
467 | |||
468 | static void set_scr(struct snd_ice1712 *ice, unsigned int val) | ||
469 | { | ||
470 | struct qtet_spec *spec = ice->spec; | ||
471 | reg_write(ice, GPIO_SCR, val); | ||
472 | spec->scr = val; | ||
473 | } | ||
474 | |||
475 | static void set_mcr(struct snd_ice1712 *ice, unsigned int val) | ||
476 | { | ||
477 | struct qtet_spec *spec = ice->spec; | ||
478 | reg_write(ice, GPIO_MCR, val); | ||
479 | spec->mcr = val; | ||
480 | } | ||
481 | |||
482 | static void set_cpld(struct snd_ice1712 *ice, unsigned int val) | ||
483 | { | ||
484 | struct qtet_spec *spec = ice->spec; | ||
485 | reg_write(ice, GPIO_CPLD_CSN, val); | ||
486 | spec->cpld = val; | ||
487 | } | ||
488 | #ifdef CONFIG_PROC_FS | ||
489 | static void proc_regs_read(struct snd_info_entry *entry, | ||
490 | struct snd_info_buffer *buffer) | ||
491 | { | ||
492 | struct snd_ice1712 *ice = entry->private_data; | ||
493 | char bin_buffer[36]; | ||
494 | |||
495 | snd_iprintf(buffer, "SCR: %s\n", get_binary(bin_buffer, | ||
496 | get_scr(ice))); | ||
497 | snd_iprintf(buffer, "MCR: %s\n", get_binary(bin_buffer, | ||
498 | get_mcr(ice))); | ||
499 | snd_iprintf(buffer, "CPLD: %s\n", get_binary(bin_buffer, | ||
500 | get_cpld(ice))); | ||
501 | } | ||
502 | |||
503 | static void proc_init(struct snd_ice1712 *ice) | ||
504 | { | ||
505 | struct snd_info_entry *entry; | ||
506 | if (!snd_card_proc_new(ice->card, "quartet", &entry)) | ||
507 | snd_info_set_text_ops(entry, ice, proc_regs_read); | ||
508 | } | ||
509 | #else /* !CONFIG_PROC_FS */ | ||
510 | static void proc_init(struct snd_ice1712 *ice) {} | ||
511 | #endif | ||
512 | |||
513 | static int qtet_mute_get(struct snd_kcontrol *kcontrol, | ||
514 | struct snd_ctl_elem_value *ucontrol) | ||
515 | { | ||
516 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | ||
517 | unsigned int val; | ||
518 | val = get_scr(ice) & SCR_MUTE; | ||
519 | ucontrol->value.integer.value[0] = (val) ? 0 : 1; | ||
520 | return 0; | ||
521 | } | ||
522 | |||
523 | static int qtet_mute_put(struct snd_kcontrol *kcontrol, | ||
524 | struct snd_ctl_elem_value *ucontrol) | ||
525 | { | ||
526 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | ||
527 | unsigned int old, new, smute; | ||
528 | old = get_scr(ice) & SCR_MUTE; | ||
529 | if (ucontrol->value.integer.value[0]) { | ||
530 | /* unmute */ | ||
531 | new = 0; | ||
532 | /* un-smuting DAC */ | ||
533 | smute = 0; | ||
534 | } else { | ||
535 | /* mute */ | ||
536 | new = SCR_MUTE; | ||
537 | /* smuting DAC */ | ||
538 | smute = AK4620_SMUTE; | ||
539 | } | ||
540 | if (old != new) { | ||
541 | struct snd_akm4xxx *ak = ice->akm; | ||
542 | set_scr(ice, (get_scr(ice) & ~SCR_MUTE) | new); | ||
543 | /* set smute */ | ||
544 | qtet_akm_set_regs(ak, AK4620_DEEMVOL_REG, AK4620_SMUTE, smute); | ||
545 | return 1; | ||
546 | } | ||
547 | /* no change */ | ||
548 | return 0; | ||
549 | } | ||
550 | |||
551 | static int qtet_ain12_enum_info(struct snd_kcontrol *kcontrol, | ||
552 | struct snd_ctl_elem_info *uinfo) | ||
553 | { | ||
554 | static char *texts[3] = {"Line In 1/2", "Mic", "Mic + Low-cut"}; | ||
555 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
556 | uinfo->count = 1; | ||
557 | uinfo->value.enumerated.items = ARRAY_SIZE(texts); | ||
558 | |||
559 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
560 | uinfo->value.enumerated.item = | ||
561 | uinfo->value.enumerated.items - 1; | ||
562 | strcpy(uinfo->value.enumerated.name, | ||
563 | texts[uinfo->value.enumerated.item]); | ||
564 | |||
565 | return 0; | ||
566 | } | ||
567 | |||
568 | static int qtet_ain12_sw_get(struct snd_kcontrol *kcontrol, | ||
569 | struct snd_ctl_elem_value *ucontrol) | ||
570 | { | ||
571 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | ||
572 | unsigned int val, result; | ||
573 | val = get_scr(ice) & (SCR_AIN12_SEL1 | SCR_AIN12_SEL0); | ||
574 | switch (val) { | ||
575 | case SCR_AIN12_LINE: | ||
576 | result = 0; | ||
577 | break; | ||
578 | case SCR_AIN12_MIC: | ||
579 | result = 1; | ||
580 | break; | ||
581 | case SCR_AIN12_LOWCUT: | ||
582 | result = 2; | ||
583 | break; | ||
584 | default: | ||
585 | /* BUG - no other combinations allowed */ | ||
586 | snd_BUG(); | ||
587 | result = 0; | ||
588 | } | ||
589 | ucontrol->value.integer.value[0] = result; | ||
590 | return 0; | ||
591 | } | ||
592 | |||
593 | static int qtet_ain12_sw_put(struct snd_kcontrol *kcontrol, | ||
594 | struct snd_ctl_elem_value *ucontrol) | ||
595 | { | ||
596 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | ||
597 | unsigned int old, new, tmp, masked_old; | ||
598 | old = new = get_scr(ice); | ||
599 | masked_old = old & (SCR_AIN12_SEL1 | SCR_AIN12_SEL0); | ||
600 | tmp = ucontrol->value.integer.value[0]; | ||
601 | if (tmp == 2) | ||
602 | tmp = 3; /* binary 10 is not supported */ | ||
603 | tmp <<= 4; /* shifting to SCR_AIN12_SEL0 */ | ||
604 | if (tmp != masked_old) { | ||
605 | /* change requested */ | ||
606 | switch (tmp) { | ||
607 | case SCR_AIN12_LINE: | ||
608 | new = old & ~(SCR_AIN12_SEL1 | SCR_AIN12_SEL0); | ||
609 | set_scr(ice, new); | ||
610 | /* turn off relay */ | ||
611 | new &= ~SCR_RELAY; | ||
612 | set_scr(ice, new); | ||
613 | break; | ||
614 | case SCR_AIN12_MIC: | ||
615 | /* turn on relay */ | ||
616 | new = old | SCR_RELAY; | ||
617 | set_scr(ice, new); | ||
618 | new = (new & ~SCR_AIN12_SEL1) | SCR_AIN12_SEL0; | ||
619 | set_scr(ice, new); | ||
620 | break; | ||
621 | case SCR_AIN12_LOWCUT: | ||
622 | /* turn on relay */ | ||
623 | new = old | SCR_RELAY; | ||
624 | set_scr(ice, new); | ||
625 | new |= SCR_AIN12_SEL1 | SCR_AIN12_SEL0; | ||
626 | set_scr(ice, new); | ||
627 | break; | ||
628 | default: | ||
629 | snd_BUG(); | ||
630 | } | ||
631 | return 1; | ||
632 | } | ||
633 | /* no change */ | ||
634 | return 0; | ||
635 | } | ||
636 | |||
637 | static int qtet_php_get(struct snd_kcontrol *kcontrol, | ||
638 | struct snd_ctl_elem_value *ucontrol) | ||
639 | { | ||
640 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | ||
641 | unsigned int val; | ||
642 | /* if phantom voltage =48V, phantom on */ | ||
643 | val = get_scr(ice) & SCR_PHP_V; | ||
644 | ucontrol->value.integer.value[0] = val ? 1 : 0; | ||
645 | return 0; | ||
646 | } | ||
647 | |||
648 | static int qtet_php_put(struct snd_kcontrol *kcontrol, | ||
649 | struct snd_ctl_elem_value *ucontrol) | ||
650 | { | ||
651 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | ||
652 | unsigned int old, new; | ||
653 | old = new = get_scr(ice); | ||
654 | if (ucontrol->value.integer.value[0] /* phantom on requested */ | ||
655 | && (~old & SCR_PHP_V)) /* 0 = voltage 5V */ { | ||
656 | /* is off, turn on */ | ||
657 | /* turn voltage on first, = 1 */ | ||
658 | new = old | SCR_PHP_V; | ||
659 | set_scr(ice, new); | ||
660 | /* turn phantom on, = 0 */ | ||
661 | new &= ~SCR_PHP; | ||
662 | set_scr(ice, new); | ||
663 | } else if (!ucontrol->value.integer.value[0] && (old & SCR_PHP_V)) { | ||
664 | /* phantom off requested and 1 = voltage 48V */ | ||
665 | /* is on, turn off */ | ||
666 | /* turn voltage off first, = 0 */ | ||
667 | new = old & ~SCR_PHP_V; | ||
668 | set_scr(ice, new); | ||
669 | /* turn phantom off, = 1 */ | ||
670 | new |= SCR_PHP; | ||
671 | set_scr(ice, new); | ||
672 | } | ||
673 | if (old != new) | ||
674 | return 1; | ||
675 | /* no change */ | ||
676 | return 0; | ||
677 | } | ||
678 | |||
679 | #define PRIV_SW(xid, xbit, xreg) [xid] = {.bit = xbit,\ | ||
680 | .set_register = set_##xreg,\ | ||
681 | .get_register = get_##xreg, } | ||
682 | |||
683 | |||
684 | #define PRIV_ENUM2(xid, xbit, xreg, xtext1, xtext2) [xid] = {.bit = xbit,\ | ||
685 | .set_register = set_##xreg,\ | ||
686 | .get_register = get_##xreg,\ | ||
687 | .texts = {xtext1, xtext2} } | ||
688 | |||
689 | static struct qtet_kcontrol_private qtet_privates[] = { | ||
690 | PRIV_ENUM2(IN12_SEL, CPLD_IN12_SEL, cpld, "An In 1/2", "An In 3/4"), | ||
691 | PRIV_ENUM2(IN34_SEL, CPLD_IN34_SEL, cpld, "An In 3/4", "IEC958 In"), | ||
692 | PRIV_ENUM2(AIN34_SEL, SCR_AIN34_SEL, scr, "Line In 3/4", "Hi-Z"), | ||
693 | PRIV_ENUM2(COAX_OUT, CPLD_COAX_OUT, cpld, "IEC958", "I2S"), | ||
694 | PRIV_SW(IN12_MON12, MCR_IN12_MON12, mcr), | ||
695 | PRIV_SW(IN12_MON34, MCR_IN12_MON34, mcr), | ||
696 | PRIV_SW(IN34_MON12, MCR_IN34_MON12, mcr), | ||
697 | PRIV_SW(IN34_MON34, MCR_IN34_MON34, mcr), | ||
698 | PRIV_SW(OUT12_MON34, MCR_OUT12_MON34, mcr), | ||
699 | PRIV_SW(OUT34_MON12, MCR_OUT34_MON12, mcr), | ||
700 | }; | ||
701 | |||
702 | static int qtet_enum_info(struct snd_kcontrol *kcontrol, | ||
703 | struct snd_ctl_elem_info *uinfo) | ||
704 | { | ||
705 | struct qtet_kcontrol_private private = | ||
706 | qtet_privates[kcontrol->private_value]; | ||
707 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
708 | uinfo->count = 1; | ||
709 | uinfo->value.enumerated.items = ARRAY_SIZE(private.texts); | ||
710 | |||
711 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
712 | uinfo->value.enumerated.item = | ||
713 | uinfo->value.enumerated.items - 1; | ||
714 | strcpy(uinfo->value.enumerated.name, | ||
715 | private.texts[uinfo->value.enumerated.item]); | ||
716 | |||
717 | return 0; | ||
718 | } | ||
719 | |||
720 | static int qtet_sw_get(struct snd_kcontrol *kcontrol, | ||
721 | struct snd_ctl_elem_value *ucontrol) | ||
722 | { | ||
723 | struct qtet_kcontrol_private private = | ||
724 | qtet_privates[kcontrol->private_value]; | ||
725 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | ||
726 | ucontrol->value.integer.value[0] = | ||
727 | (private.get_register(ice) & private.bit) ? 1 : 0; | ||
728 | return 0; | ||
729 | } | ||
730 | |||
731 | static int qtet_sw_put(struct snd_kcontrol *kcontrol, | ||
732 | struct snd_ctl_elem_value *ucontrol) | ||
733 | { | ||
734 | struct qtet_kcontrol_private private = | ||
735 | qtet_privates[kcontrol->private_value]; | ||
736 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | ||
737 | unsigned int old, new; | ||
738 | old = private.get_register(ice); | ||
739 | if (ucontrol->value.integer.value[0]) | ||
740 | new = old | private.bit; | ||
741 | else | ||
742 | new = old & ~private.bit; | ||
743 | if (old != new) { | ||
744 | private.set_register(ice, new); | ||
745 | return 1; | ||
746 | } | ||
747 | /* no change */ | ||
748 | return 0; | ||
749 | } | ||
750 | |||
751 | #define qtet_sw_info snd_ctl_boolean_mono_info | ||
752 | |||
753 | #define QTET_CONTROL(xname, xtype, xpriv) \ | ||
754 | {.iface = SNDRV_CTL_ELEM_IFACE_MIXER,\ | ||
755 | .name = xname,\ | ||
756 | .info = qtet_##xtype##_info,\ | ||
757 | .get = qtet_sw_get,\ | ||
758 | .put = qtet_sw_put,\ | ||
759 | .private_value = xpriv } | ||
760 | |||
761 | static struct snd_kcontrol_new qtet_controls[] __devinitdata = { | ||
762 | { | ||
763 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
764 | .name = "Master Playback Switch", | ||
765 | .info = qtet_sw_info, | ||
766 | .get = qtet_mute_get, | ||
767 | .put = qtet_mute_put, | ||
768 | .private_value = 0 | ||
769 | }, | ||
770 | { | ||
771 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
772 | .name = "Phantom Power", | ||
773 | .info = qtet_sw_info, | ||
774 | .get = qtet_php_get, | ||
775 | .put = qtet_php_put, | ||
776 | .private_value = 0 | ||
777 | }, | ||
778 | { | ||
779 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
780 | .name = "Analog In 1/2 Capture Switch", | ||
781 | .info = qtet_ain12_enum_info, | ||
782 | .get = qtet_ain12_sw_get, | ||
783 | .put = qtet_ain12_sw_put, | ||
784 | .private_value = 0 | ||
785 | }, | ||
786 | QTET_CONTROL("Analog In 3/4 Capture Switch", enum, AIN34_SEL), | ||
787 | QTET_CONTROL("PCM In 1/2 Capture Switch", enum, IN12_SEL), | ||
788 | QTET_CONTROL("PCM In 3/4 Capture Switch", enum, IN34_SEL), | ||
789 | QTET_CONTROL("Coax Output Source", enum, COAX_OUT), | ||
790 | QTET_CONTROL("Analog In 1/2 to Monitor 1/2", sw, IN12_MON12), | ||
791 | QTET_CONTROL("Analog In 1/2 to Monitor 3/4", sw, IN12_MON34), | ||
792 | QTET_CONTROL("Analog In 3/4 to Monitor 1/2", sw, IN34_MON12), | ||
793 | QTET_CONTROL("Analog In 3/4 to Monitor 3/4", sw, IN34_MON34), | ||
794 | QTET_CONTROL("Output 1/2 to Monitor 3/4", sw, OUT12_MON34), | ||
795 | QTET_CONTROL("Output 3/4 to Monitor 1/2", sw, OUT34_MON12), | ||
796 | }; | ||
797 | |||
798 | static char *slave_vols[] __devinitdata = { | ||
799 | PCM_12_PLAYBACK_VOLUME, | ||
800 | PCM_34_PLAYBACK_VOLUME, | ||
801 | NULL | ||
802 | }; | ||
803 | |||
804 | static __devinitdata | ||
805 | DECLARE_TLV_DB_SCALE(qtet_master_db_scale, -6350, 50, 1); | ||
806 | |||
807 | static struct snd_kcontrol __devinit *ctl_find(struct snd_card *card, | ||
808 | const char *name) | ||
809 | { | ||
810 | struct snd_ctl_elem_id sid; | ||
811 | memset(&sid, 0, sizeof(sid)); | ||
812 | /* FIXME: strcpy is bad. */ | ||
813 | strcpy(sid.name, name); | ||
814 | sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | ||
815 | return snd_ctl_find_id(card, &sid); | ||
816 | } | ||
817 | |||
818 | static void __devinit add_slaves(struct snd_card *card, | ||
819 | struct snd_kcontrol *master, char **list) | ||
820 | { | ||
821 | for (; *list; list++) { | ||
822 | struct snd_kcontrol *slave = ctl_find(card, *list); | ||
823 | if (slave) | ||
824 | snd_ctl_add_slave(master, slave); | ||
825 | } | ||
826 | } | ||
827 | |||
828 | static int __devinit qtet_add_controls(struct snd_ice1712 *ice) | ||
829 | { | ||
830 | struct qtet_spec *spec = ice->spec; | ||
831 | int err, i; | ||
832 | struct snd_kcontrol *vmaster; | ||
833 | err = snd_ice1712_akm4xxx_build_controls(ice); | ||
834 | if (err < 0) | ||
835 | return err; | ||
836 | for (i = 0; i < ARRAY_SIZE(qtet_controls); i++) { | ||
837 | err = snd_ctl_add(ice->card, | ||
838 | snd_ctl_new1(&qtet_controls[i], ice)); | ||
839 | if (err < 0) | ||
840 | return err; | ||
841 | } | ||
842 | |||
843 | /* Create virtual master control */ | ||
844 | vmaster = snd_ctl_make_virtual_master("Master Playback Volume", | ||
845 | qtet_master_db_scale); | ||
846 | if (!vmaster) | ||
847 | return -ENOMEM; | ||
848 | add_slaves(ice->card, vmaster, slave_vols); | ||
849 | err = snd_ctl_add(ice->card, vmaster); | ||
850 | if (err < 0) | ||
851 | return err; | ||
852 | /* only capture SPDIF over AK4113 */ | ||
853 | err = snd_ak4113_build(spec->ak4113, | ||
854 | ice->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream); | ||
855 | if (err < 0) | ||
856 | return err; | ||
857 | return 0; | ||
858 | } | ||
859 | |||
860 | static inline int qtet_is_spdif_master(struct snd_ice1712 *ice) | ||
861 | { | ||
862 | /* CPLD_SYNC_SEL: 0 = internal, 1 = external (i.e. spdif master) */ | ||
863 | return (get_cpld(ice) & CPLD_SYNC_SEL) ? 1 : 0; | ||
864 | } | ||
865 | |||
866 | static unsigned int qtet_get_rate(struct snd_ice1712 *ice) | ||
867 | { | ||
868 | int i; | ||
869 | unsigned char result; | ||
870 | |||
871 | result = get_cpld(ice) & CPLD_CKS_MASK; | ||
872 | for (i = 0; i < ARRAY_SIZE(cks_vals); i++) | ||
873 | if (cks_vals[i] == result) | ||
874 | return qtet_rates[i]; | ||
875 | return 0; | ||
876 | } | ||
877 | |||
878 | static int get_cks_val(int rate) | ||
879 | { | ||
880 | int i; | ||
881 | for (i = 0; i < ARRAY_SIZE(qtet_rates); i++) | ||
882 | if (qtet_rates[i] == rate) | ||
883 | return cks_vals[i]; | ||
884 | return 0; | ||
885 | } | ||
886 | |||
887 | /* setting new rate */ | ||
888 | static void qtet_set_rate(struct snd_ice1712 *ice, unsigned int rate) | ||
889 | { | ||
890 | unsigned int new; | ||
891 | unsigned char val; | ||
892 | /* switching ice1724 to external clock - supplied by ext. circuits */ | ||
893 | val = inb(ICEMT1724(ice, RATE)); | ||
894 | outb(val | VT1724_SPDIF_MASTER, ICEMT1724(ice, RATE)); | ||
895 | |||
896 | new = (get_cpld(ice) & ~CPLD_CKS_MASK) | get_cks_val(rate); | ||
897 | /* switch to internal clock, drop CPLD_SYNC_SEL */ | ||
898 | new &= ~CPLD_SYNC_SEL; | ||
899 | /* printk(KERN_DEBUG "QT - set_rate: old %x, new %x\n", | ||
900 | get_cpld(ice), new); */ | ||
901 | set_cpld(ice, new); | ||
902 | } | ||
903 | |||
904 | static inline unsigned char qtet_set_mclk(struct snd_ice1712 *ice, | ||
905 | unsigned int rate) | ||
906 | { | ||
907 | /* no change in master clock */ | ||
908 | return 0; | ||
909 | } | ||
910 | |||
911 | /* setting clock to external - SPDIF */ | ||
912 | static int qtet_set_spdif_clock(struct snd_ice1712 *ice, int type) | ||
913 | { | ||
914 | unsigned int old, new; | ||
915 | |||
916 | old = new = get_cpld(ice); | ||
917 | new &= ~(CPLD_CKS_MASK | CPLD_WORD_SEL); | ||
918 | switch (type) { | ||
919 | case EXT_SPDIF_TYPE: | ||
920 | new |= CPLD_EXT_SPDIF; | ||
921 | break; | ||
922 | case EXT_WORDCLOCK_1FS_TYPE: | ||
923 | new |= CPLD_EXT_WORDCLOCK_1FS; | ||
924 | break; | ||
925 | case EXT_WORDCLOCK_256FS_TYPE: | ||
926 | new |= CPLD_EXT_WORDCLOCK_256FS; | ||
927 | break; | ||
928 | default: | ||
929 | snd_BUG(); | ||
930 | } | ||
931 | if (old != new) { | ||
932 | set_cpld(ice, new); | ||
933 | /* changed */ | ||
934 | return 1; | ||
935 | } | ||
936 | return 0; | ||
937 | } | ||
938 | |||
939 | static int qtet_get_spdif_master_type(struct snd_ice1712 *ice) | ||
940 | { | ||
941 | unsigned int val; | ||
942 | int result; | ||
943 | val = get_cpld(ice); | ||
944 | /* checking only rate/clock-related bits */ | ||
945 | val &= (CPLD_CKS_MASK | CPLD_WORD_SEL | CPLD_SYNC_SEL); | ||
946 | if (!(val & CPLD_SYNC_SEL)) { | ||
947 | /* switched to internal clock, is not any external type */ | ||
948 | result = -1; | ||
949 | } else { | ||
950 | switch (val) { | ||
951 | case (CPLD_EXT_SPDIF): | ||
952 | result = EXT_SPDIF_TYPE; | ||
953 | break; | ||
954 | case (CPLD_EXT_WORDCLOCK_1FS): | ||
955 | result = EXT_WORDCLOCK_1FS_TYPE; | ||
956 | break; | ||
957 | case (CPLD_EXT_WORDCLOCK_256FS): | ||
958 | result = EXT_WORDCLOCK_256FS_TYPE; | ||
959 | break; | ||
960 | default: | ||
961 | /* undefined combination of external clock setup */ | ||
962 | snd_BUG(); | ||
963 | result = 0; | ||
964 | } | ||
965 | } | ||
966 | return result; | ||
967 | } | ||
968 | |||
969 | /* Called when ak4113 detects change in the input SPDIF stream */ | ||
970 | static void qtet_ak4113_change(struct ak4113 *ak4113, unsigned char c0, | ||
971 | unsigned char c1) | ||
972 | { | ||
973 | struct snd_ice1712 *ice = ak4113->change_callback_private; | ||
974 | int rate; | ||
975 | if ((qtet_get_spdif_master_type(ice) == EXT_SPDIF_TYPE) && | ||
976 | c1) { | ||
977 | /* only for SPDIF master mode, rate was changed */ | ||
978 | rate = snd_ak4113_external_rate(ak4113); | ||
979 | /* printk(KERN_DEBUG "ak4113 - input rate changed to %d\n", | ||
980 | rate); */ | ||
981 | qtet_akm_set_rate_val(ice->akm, rate); | ||
982 | } | ||
983 | } | ||
984 | |||
985 | /* | ||
986 | * If clock slaved to SPDIF-IN, setting runtime rate | ||
987 | * to the detected external rate | ||
988 | */ | ||
989 | static void qtet_spdif_in_open(struct snd_ice1712 *ice, | ||
990 | struct snd_pcm_substream *substream) | ||
991 | { | ||
992 | struct qtet_spec *spec = ice->spec; | ||
993 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
994 | int rate; | ||
995 | |||
996 | if (qtet_get_spdif_master_type(ice) != EXT_SPDIF_TYPE) | ||
997 | /* not external SPDIF, no rate limitation */ | ||
998 | return; | ||
999 | /* only external SPDIF can detect incoming sample rate */ | ||
1000 | rate = snd_ak4113_external_rate(spec->ak4113); | ||
1001 | if (rate >= runtime->hw.rate_min && rate <= runtime->hw.rate_max) { | ||
1002 | runtime->hw.rate_min = rate; | ||
1003 | runtime->hw.rate_max = rate; | ||
1004 | } | ||
1005 | } | ||
1006 | |||
1007 | /* | ||
1008 | * initialize the chip | ||
1009 | */ | ||
1010 | static int __devinit qtet_init(struct snd_ice1712 *ice) | ||
1011 | { | ||
1012 | static const unsigned char ak4113_init_vals[] = { | ||
1013 | /* AK4113_REG_PWRDN */ AK4113_RST | AK4113_PWN | | ||
1014 | AK4113_OCKS0 | AK4113_OCKS1, | ||
1015 | /* AK4113_REQ_FORMAT */ AK4113_DIF_I24I2S | AK4113_VTX | | ||
1016 | AK4113_DEM_OFF | AK4113_DEAU, | ||
1017 | /* AK4113_REG_IO0 */ AK4113_OPS2 | AK4113_TXE | | ||
1018 | AK4113_XTL_24_576M, | ||
1019 | /* AK4113_REG_IO1 */ AK4113_EFH_1024LRCLK | AK4113_IPS(0), | ||
1020 | /* AK4113_REG_INT0_MASK */ 0, | ||
1021 | /* AK4113_REG_INT1_MASK */ 0, | ||
1022 | /* AK4113_REG_DATDTS */ 0, | ||
1023 | }; | ||
1024 | int err; | ||
1025 | struct qtet_spec *spec; | ||
1026 | struct snd_akm4xxx *ak; | ||
1027 | unsigned char val; | ||
1028 | |||
1029 | /* switching ice1724 to external clock - supplied by ext. circuits */ | ||
1030 | val = inb(ICEMT1724(ice, RATE)); | ||
1031 | outb(val | VT1724_SPDIF_MASTER, ICEMT1724(ice, RATE)); | ||
1032 | |||
1033 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
1034 | if (!spec) | ||
1035 | return -ENOMEM; | ||
1036 | /* qtet is clocked by Xilinx array */ | ||
1037 | ice->hw_rates = &qtet_rates_info; | ||
1038 | ice->is_spdif_master = qtet_is_spdif_master; | ||
1039 | ice->get_rate = qtet_get_rate; | ||
1040 | ice->set_rate = qtet_set_rate; | ||
1041 | ice->set_mclk = qtet_set_mclk; | ||
1042 | ice->set_spdif_clock = qtet_set_spdif_clock; | ||
1043 | ice->get_spdif_master_type = qtet_get_spdif_master_type; | ||
1044 | ice->ext_clock_names = ext_clock_names; | ||
1045 | ice->ext_clock_count = ARRAY_SIZE(ext_clock_names); | ||
1046 | /* since Qtet can detect correct SPDIF-in rate, all streams can be | ||
1047 | * limited to this specific rate */ | ||
1048 | ice->spdif.ops.open = ice->pro_open = qtet_spdif_in_open; | ||
1049 | ice->spec = spec; | ||
1050 | |||
1051 | /* Mute Off */ | ||
1052 | /* SCR Initialize*/ | ||
1053 | /* keep codec power down first */ | ||
1054 | set_scr(ice, SCR_PHP); | ||
1055 | udelay(1); | ||
1056 | /* codec power up */ | ||
1057 | set_scr(ice, SCR_PHP | SCR_CODEC_PDN); | ||
1058 | |||
1059 | /* MCR Initialize */ | ||
1060 | set_mcr(ice, 0); | ||
1061 | |||
1062 | /* CPLD Initialize */ | ||
1063 | set_cpld(ice, 0); | ||
1064 | |||
1065 | |||
1066 | ice->num_total_dacs = 2; | ||
1067 | ice->num_total_adcs = 2; | ||
1068 | |||
1069 | ice->akm = kcalloc(2, sizeof(struct snd_akm4xxx), GFP_KERNEL); | ||
1070 | ak = ice->akm; | ||
1071 | if (!ak) | ||
1072 | return -ENOMEM; | ||
1073 | /* only one codec with two chips */ | ||
1074 | ice->akm_codecs = 1; | ||
1075 | err = snd_ice1712_akm4xxx_init(ak, &akm_qtet_dac, NULL, ice); | ||
1076 | if (err < 0) | ||
1077 | return err; | ||
1078 | err = snd_ak4113_create(ice->card, | ||
1079 | qtet_ak4113_read, | ||
1080 | qtet_ak4113_write, | ||
1081 | ak4113_init_vals, | ||
1082 | ice, &spec->ak4113); | ||
1083 | if (err < 0) | ||
1084 | return err; | ||
1085 | /* callback for codecs rate setting */ | ||
1086 | spec->ak4113->change_callback = qtet_ak4113_change; | ||
1087 | spec->ak4113->change_callback_private = ice; | ||
1088 | /* AK41143 in Quartet can detect external rate correctly | ||
1089 | * (i.e. check_flags = 0) */ | ||
1090 | spec->ak4113->check_flags = 0; | ||
1091 | |||
1092 | proc_init(ice); | ||
1093 | |||
1094 | qtet_set_rate(ice, 44100); | ||
1095 | return 0; | ||
1096 | } | ||
1097 | |||
1098 | static unsigned char qtet_eeprom[] __devinitdata = { | ||
1099 | [ICE_EEP2_SYSCONF] = 0x28, /* clock 256(24MHz), mpu401, 1xADC, | ||
1100 | 1xDACs, SPDIF in */ | ||
1101 | [ICE_EEP2_ACLINK] = 0x80, /* I2S */ | ||
1102 | [ICE_EEP2_I2S] = 0x78, /* 96k, 24bit, 192k */ | ||
1103 | [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, in, out-ext */ | ||
1104 | [ICE_EEP2_GPIO_DIR] = 0x00, /* 0-7 inputs, switched to output | ||
1105 | only during output operations */ | ||
1106 | [ICE_EEP2_GPIO_DIR1] = 0xff, /* 8-15 outputs */ | ||
1107 | [ICE_EEP2_GPIO_DIR2] = 0x00, | ||
1108 | [ICE_EEP2_GPIO_MASK] = 0xff, /* changed only for OUT operations */ | ||
1109 | [ICE_EEP2_GPIO_MASK1] = 0x00, | ||
1110 | [ICE_EEP2_GPIO_MASK2] = 0xff, | ||
1111 | |||
1112 | [ICE_EEP2_GPIO_STATE] = 0x00, /* inputs */ | ||
1113 | [ICE_EEP2_GPIO_STATE1] = 0x7d, /* all 1, but GPIO_CPLD_RW | ||
1114 | and GPIO15 always zero */ | ||
1115 | [ICE_EEP2_GPIO_STATE2] = 0x00, /* inputs */ | ||
1116 | }; | ||
1117 | |||
1118 | /* entry point */ | ||
1119 | struct snd_ice1712_card_info snd_vt1724_qtet_cards[] __devinitdata = { | ||
1120 | { | ||
1121 | .subvendor = VT1724_SUBDEVICE_QTET, | ||
1122 | .name = "Infrasonic Quartet", | ||
1123 | .model = "quartet", | ||
1124 | .chip_init = qtet_init, | ||
1125 | .build_controls = qtet_add_controls, | ||
1126 | .eeprom_size = sizeof(qtet_eeprom), | ||
1127 | .eeprom_data = qtet_eeprom, | ||
1128 | }, | ||
1129 | { } /* terminator */ | ||
1130 | }; | ||
diff --git a/sound/pci/ice1712/quartet.h b/sound/pci/ice1712/quartet.h new file mode 100644 index 000000000000..80809b72439a --- /dev/null +++ b/sound/pci/ice1712/quartet.h | |||
@@ -0,0 +1,10 @@ | |||
1 | #ifndef __SOUND_QTET_H | ||
2 | #define __SOUND_QTET_H | ||
3 | |||
4 | #define QTET_DEVICE_DESC "{Infrasonic,Quartet}," | ||
5 | |||
6 | #define VT1724_SUBDEVICE_QTET 0x30305349 /* Infrasonic Quartet */ | ||
7 | |||
8 | extern struct snd_ice1712_card_info snd_vt1724_qtet_cards[]; | ||
9 | |||
10 | #endif /* __SOUND_QTET_H */ | ||