.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * USB Audio Driver for ALSA |
---|
3 | 4 | * |
---|
.. | .. |
---|
11 | 12 | * |
---|
12 | 13 | * Audio Advantage Micro II support added by: |
---|
13 | 14 | * Przemek Rudy (prudy1@o2.pl) |
---|
14 | | - * |
---|
15 | | - * This program is free software; you can redistribute it and/or modify |
---|
16 | | - * it under the terms of the GNU General Public License as published by |
---|
17 | | - * the Free Software Foundation; either version 2 of the License, or |
---|
18 | | - * (at your option) any later version. |
---|
19 | | - * |
---|
20 | | - * This program is distributed in the hope that it will be useful, |
---|
21 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
22 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
23 | | - * GNU General Public License for more details. |
---|
24 | | - * |
---|
25 | | - * You should have received a copy of the GNU General Public License |
---|
26 | | - * along with this program; if not, write to the Free Software |
---|
27 | | - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
---|
28 | 15 | */ |
---|
29 | 16 | |
---|
30 | 17 | #include <linux/hid.h> |
---|
31 | 18 | #include <linux/init.h> |
---|
| 19 | +#include <linux/math64.h> |
---|
32 | 20 | #include <linux/slab.h> |
---|
33 | 21 | #include <linux/usb.h> |
---|
34 | 22 | #include <linux/usb/audio.h> |
---|
.. | .. |
---|
44 | 32 | #include "mixer.h" |
---|
45 | 33 | #include "mixer_quirks.h" |
---|
46 | 34 | #include "mixer_scarlett.h" |
---|
| 35 | +#include "mixer_scarlett_gen2.h" |
---|
47 | 36 | #include "mixer_us16x08.h" |
---|
| 37 | +#include "mixer_s1810c.h" |
---|
48 | 38 | #include "helper.h" |
---|
49 | 39 | |
---|
50 | 40 | struct std_mono_table { |
---|
.. | .. |
---|
520 | 510 | list->kctl->private_value); |
---|
521 | 511 | } |
---|
522 | 512 | |
---|
523 | | -static struct snd_kcontrol_new snd_emu0204_control = { |
---|
| 513 | +static const struct snd_kcontrol_new snd_emu0204_control = { |
---|
524 | 514 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
---|
525 | 515 | .name = "Front Jack Channels", |
---|
526 | 516 | .info = snd_emu0204_ch_switch_info, |
---|
.. | .. |
---|
588 | 578 | list->kctl->private_value); |
---|
589 | 579 | } |
---|
590 | 580 | |
---|
591 | | -static struct snd_kcontrol_new snd_xonar_u1_output_switch = { |
---|
| 581 | +static const struct snd_kcontrol_new snd_xonar_u1_output_switch = { |
---|
592 | 582 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
---|
593 | 583 | .name = "Digital Playback Switch", |
---|
594 | 584 | .info = snd_ctl_boolean_mono_info, |
---|
.. | .. |
---|
715 | 705 | return snd_mbox1_switch_update(list->mixer, list->kctl->private_value); |
---|
716 | 706 | } |
---|
717 | 707 | |
---|
718 | | -static struct snd_kcontrol_new snd_mbox1_switch = { |
---|
| 708 | +static const struct snd_kcontrol_new snd_mbox1_switch = { |
---|
719 | 709 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
---|
720 | 710 | .name = "Clock Source", |
---|
721 | 711 | .index = 0, |
---|
.. | .. |
---|
800 | 790 | return err < 0 ? err : 1; |
---|
801 | 791 | } |
---|
802 | 792 | |
---|
803 | | -static struct snd_kcontrol_new snd_nativeinstruments_ta6_mixers[] = { |
---|
| 793 | +static const struct snd_kcontrol_new snd_nativeinstruments_ta6_mixers[] = { |
---|
804 | 794 | { |
---|
805 | 795 | .name = "Direct Thru Channel A", |
---|
806 | 796 | .private_value = _MAKE_NI_CONTROL(0x01, 0x03), |
---|
.. | .. |
---|
819 | 809 | }, |
---|
820 | 810 | }; |
---|
821 | 811 | |
---|
822 | | -static struct snd_kcontrol_new snd_nativeinstruments_ta10_mixers[] = { |
---|
| 812 | +static const struct snd_kcontrol_new snd_nativeinstruments_ta10_mixers[] = { |
---|
823 | 813 | { |
---|
824 | 814 | .name = "Direct Thru Channel A", |
---|
825 | 815 | .private_value = _MAKE_NI_CONTROL(0x01, 0x03), |
---|
.. | .. |
---|
1679 | 1669 | return err < 0 ? err : 1; |
---|
1680 | 1670 | } |
---|
1681 | 1671 | |
---|
1682 | | -static struct snd_kcontrol_new snd_microii_mixer_spdif[] = { |
---|
| 1672 | +static const struct snd_kcontrol_new snd_microii_mixer_spdif[] = { |
---|
1683 | 1673 | { |
---|
1684 | 1674 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
---|
1685 | 1675 | .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT), |
---|
.. | .. |
---|
1786 | 1776 | return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(texts), texts); |
---|
1787 | 1777 | } |
---|
1788 | 1778 | |
---|
1789 | | -static struct snd_kcontrol_new snd_soundblaster_e1_input_switch = { |
---|
| 1779 | +static const struct snd_kcontrol_new snd_soundblaster_e1_input_switch = { |
---|
1790 | 1780 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
---|
1791 | 1781 | .name = "Input Source", |
---|
1792 | 1782 | .info = snd_soundblaster_e1_switch_info, |
---|
.. | .. |
---|
1823 | 1813 | return 0; |
---|
1824 | 1814 | } |
---|
1825 | 1815 | |
---|
| 1816 | +/* RME Class Compliant device quirks */ |
---|
| 1817 | + |
---|
| 1818 | +#define SND_RME_GET_STATUS1 23 |
---|
| 1819 | +#define SND_RME_GET_CURRENT_FREQ 17 |
---|
| 1820 | +#define SND_RME_CLK_SYSTEM_SHIFT 16 |
---|
| 1821 | +#define SND_RME_CLK_SYSTEM_MASK 0x1f |
---|
| 1822 | +#define SND_RME_CLK_AES_SHIFT 8 |
---|
| 1823 | +#define SND_RME_CLK_SPDIF_SHIFT 12 |
---|
| 1824 | +#define SND_RME_CLK_AES_SPDIF_MASK 0xf |
---|
| 1825 | +#define SND_RME_CLK_SYNC_SHIFT 6 |
---|
| 1826 | +#define SND_RME_CLK_SYNC_MASK 0x3 |
---|
| 1827 | +#define SND_RME_CLK_FREQMUL_SHIFT 18 |
---|
| 1828 | +#define SND_RME_CLK_FREQMUL_MASK 0x7 |
---|
| 1829 | +#define SND_RME_CLK_SYSTEM(x) \ |
---|
| 1830 | + ((x >> SND_RME_CLK_SYSTEM_SHIFT) & SND_RME_CLK_SYSTEM_MASK) |
---|
| 1831 | +#define SND_RME_CLK_AES(x) \ |
---|
| 1832 | + ((x >> SND_RME_CLK_AES_SHIFT) & SND_RME_CLK_AES_SPDIF_MASK) |
---|
| 1833 | +#define SND_RME_CLK_SPDIF(x) \ |
---|
| 1834 | + ((x >> SND_RME_CLK_SPDIF_SHIFT) & SND_RME_CLK_AES_SPDIF_MASK) |
---|
| 1835 | +#define SND_RME_CLK_SYNC(x) \ |
---|
| 1836 | + ((x >> SND_RME_CLK_SYNC_SHIFT) & SND_RME_CLK_SYNC_MASK) |
---|
| 1837 | +#define SND_RME_CLK_FREQMUL(x) \ |
---|
| 1838 | + ((x >> SND_RME_CLK_FREQMUL_SHIFT) & SND_RME_CLK_FREQMUL_MASK) |
---|
| 1839 | +#define SND_RME_CLK_AES_LOCK 0x1 |
---|
| 1840 | +#define SND_RME_CLK_AES_SYNC 0x4 |
---|
| 1841 | +#define SND_RME_CLK_SPDIF_LOCK 0x2 |
---|
| 1842 | +#define SND_RME_CLK_SPDIF_SYNC 0x8 |
---|
| 1843 | +#define SND_RME_SPDIF_IF_SHIFT 4 |
---|
| 1844 | +#define SND_RME_SPDIF_FORMAT_SHIFT 5 |
---|
| 1845 | +#define SND_RME_BINARY_MASK 0x1 |
---|
| 1846 | +#define SND_RME_SPDIF_IF(x) \ |
---|
| 1847 | + ((x >> SND_RME_SPDIF_IF_SHIFT) & SND_RME_BINARY_MASK) |
---|
| 1848 | +#define SND_RME_SPDIF_FORMAT(x) \ |
---|
| 1849 | + ((x >> SND_RME_SPDIF_FORMAT_SHIFT) & SND_RME_BINARY_MASK) |
---|
| 1850 | + |
---|
| 1851 | +static const u32 snd_rme_rate_table[] = { |
---|
| 1852 | + 32000, 44100, 48000, 50000, |
---|
| 1853 | + 64000, 88200, 96000, 100000, |
---|
| 1854 | + 128000, 176400, 192000, 200000, |
---|
| 1855 | + 256000, 352800, 384000, 400000, |
---|
| 1856 | + 512000, 705600, 768000, 800000 |
---|
| 1857 | +}; |
---|
| 1858 | +/* maximum number of items for AES and S/PDIF rates for above table */ |
---|
| 1859 | +#define SND_RME_RATE_IDX_AES_SPDIF_NUM 12 |
---|
| 1860 | + |
---|
| 1861 | +enum snd_rme_domain { |
---|
| 1862 | + SND_RME_DOMAIN_SYSTEM, |
---|
| 1863 | + SND_RME_DOMAIN_AES, |
---|
| 1864 | + SND_RME_DOMAIN_SPDIF |
---|
| 1865 | +}; |
---|
| 1866 | + |
---|
| 1867 | +enum snd_rme_clock_status { |
---|
| 1868 | + SND_RME_CLOCK_NOLOCK, |
---|
| 1869 | + SND_RME_CLOCK_LOCK, |
---|
| 1870 | + SND_RME_CLOCK_SYNC |
---|
| 1871 | +}; |
---|
| 1872 | + |
---|
| 1873 | +static int snd_rme_read_value(struct snd_usb_audio *chip, |
---|
| 1874 | + unsigned int item, |
---|
| 1875 | + u32 *value) |
---|
| 1876 | +{ |
---|
| 1877 | + struct usb_device *dev = chip->dev; |
---|
| 1878 | + int err; |
---|
| 1879 | + |
---|
| 1880 | + err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), |
---|
| 1881 | + item, |
---|
| 1882 | + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
---|
| 1883 | + 0, 0, |
---|
| 1884 | + value, sizeof(*value)); |
---|
| 1885 | + if (err < 0) |
---|
| 1886 | + dev_err(&dev->dev, |
---|
| 1887 | + "unable to issue vendor read request %d (ret = %d)", |
---|
| 1888 | + item, err); |
---|
| 1889 | + return err; |
---|
| 1890 | +} |
---|
| 1891 | + |
---|
| 1892 | +static int snd_rme_get_status1(struct snd_kcontrol *kcontrol, |
---|
| 1893 | + u32 *status1) |
---|
| 1894 | +{ |
---|
| 1895 | + struct usb_mixer_elem_list *list = snd_kcontrol_chip(kcontrol); |
---|
| 1896 | + struct snd_usb_audio *chip = list->mixer->chip; |
---|
| 1897 | + int err; |
---|
| 1898 | + |
---|
| 1899 | + err = snd_usb_lock_shutdown(chip); |
---|
| 1900 | + if (err < 0) |
---|
| 1901 | + return err; |
---|
| 1902 | + err = snd_rme_read_value(chip, SND_RME_GET_STATUS1, status1); |
---|
| 1903 | + snd_usb_unlock_shutdown(chip); |
---|
| 1904 | + return err; |
---|
| 1905 | +} |
---|
| 1906 | + |
---|
| 1907 | +static int snd_rme_rate_get(struct snd_kcontrol *kcontrol, |
---|
| 1908 | + struct snd_ctl_elem_value *ucontrol) |
---|
| 1909 | +{ |
---|
| 1910 | + u32 status1; |
---|
| 1911 | + u32 rate = 0; |
---|
| 1912 | + int idx; |
---|
| 1913 | + int err; |
---|
| 1914 | + |
---|
| 1915 | + err = snd_rme_get_status1(kcontrol, &status1); |
---|
| 1916 | + if (err < 0) |
---|
| 1917 | + return err; |
---|
| 1918 | + switch (kcontrol->private_value) { |
---|
| 1919 | + case SND_RME_DOMAIN_SYSTEM: |
---|
| 1920 | + idx = SND_RME_CLK_SYSTEM(status1); |
---|
| 1921 | + if (idx < ARRAY_SIZE(snd_rme_rate_table)) |
---|
| 1922 | + rate = snd_rme_rate_table[idx]; |
---|
| 1923 | + break; |
---|
| 1924 | + case SND_RME_DOMAIN_AES: |
---|
| 1925 | + idx = SND_RME_CLK_AES(status1); |
---|
| 1926 | + if (idx < SND_RME_RATE_IDX_AES_SPDIF_NUM) |
---|
| 1927 | + rate = snd_rme_rate_table[idx]; |
---|
| 1928 | + break; |
---|
| 1929 | + case SND_RME_DOMAIN_SPDIF: |
---|
| 1930 | + idx = SND_RME_CLK_SPDIF(status1); |
---|
| 1931 | + if (idx < SND_RME_RATE_IDX_AES_SPDIF_NUM) |
---|
| 1932 | + rate = snd_rme_rate_table[idx]; |
---|
| 1933 | + break; |
---|
| 1934 | + default: |
---|
| 1935 | + return -EINVAL; |
---|
| 1936 | + } |
---|
| 1937 | + ucontrol->value.integer.value[0] = rate; |
---|
| 1938 | + return 0; |
---|
| 1939 | +} |
---|
| 1940 | + |
---|
| 1941 | +static int snd_rme_sync_state_get(struct snd_kcontrol *kcontrol, |
---|
| 1942 | + struct snd_ctl_elem_value *ucontrol) |
---|
| 1943 | +{ |
---|
| 1944 | + u32 status1; |
---|
| 1945 | + int idx = SND_RME_CLOCK_NOLOCK; |
---|
| 1946 | + int err; |
---|
| 1947 | + |
---|
| 1948 | + err = snd_rme_get_status1(kcontrol, &status1); |
---|
| 1949 | + if (err < 0) |
---|
| 1950 | + return err; |
---|
| 1951 | + switch (kcontrol->private_value) { |
---|
| 1952 | + case SND_RME_DOMAIN_AES: /* AES */ |
---|
| 1953 | + if (status1 & SND_RME_CLK_AES_SYNC) |
---|
| 1954 | + idx = SND_RME_CLOCK_SYNC; |
---|
| 1955 | + else if (status1 & SND_RME_CLK_AES_LOCK) |
---|
| 1956 | + idx = SND_RME_CLOCK_LOCK; |
---|
| 1957 | + break; |
---|
| 1958 | + case SND_RME_DOMAIN_SPDIF: /* SPDIF */ |
---|
| 1959 | + if (status1 & SND_RME_CLK_SPDIF_SYNC) |
---|
| 1960 | + idx = SND_RME_CLOCK_SYNC; |
---|
| 1961 | + else if (status1 & SND_RME_CLK_SPDIF_LOCK) |
---|
| 1962 | + idx = SND_RME_CLOCK_LOCK; |
---|
| 1963 | + break; |
---|
| 1964 | + default: |
---|
| 1965 | + return -EINVAL; |
---|
| 1966 | + } |
---|
| 1967 | + ucontrol->value.enumerated.item[0] = idx; |
---|
| 1968 | + return 0; |
---|
| 1969 | +} |
---|
| 1970 | + |
---|
| 1971 | +static int snd_rme_spdif_if_get(struct snd_kcontrol *kcontrol, |
---|
| 1972 | + struct snd_ctl_elem_value *ucontrol) |
---|
| 1973 | +{ |
---|
| 1974 | + u32 status1; |
---|
| 1975 | + int err; |
---|
| 1976 | + |
---|
| 1977 | + err = snd_rme_get_status1(kcontrol, &status1); |
---|
| 1978 | + if (err < 0) |
---|
| 1979 | + return err; |
---|
| 1980 | + ucontrol->value.enumerated.item[0] = SND_RME_SPDIF_IF(status1); |
---|
| 1981 | + return 0; |
---|
| 1982 | +} |
---|
| 1983 | + |
---|
| 1984 | +static int snd_rme_spdif_format_get(struct snd_kcontrol *kcontrol, |
---|
| 1985 | + struct snd_ctl_elem_value *ucontrol) |
---|
| 1986 | +{ |
---|
| 1987 | + u32 status1; |
---|
| 1988 | + int err; |
---|
| 1989 | + |
---|
| 1990 | + err = snd_rme_get_status1(kcontrol, &status1); |
---|
| 1991 | + if (err < 0) |
---|
| 1992 | + return err; |
---|
| 1993 | + ucontrol->value.enumerated.item[0] = SND_RME_SPDIF_FORMAT(status1); |
---|
| 1994 | + return 0; |
---|
| 1995 | +} |
---|
| 1996 | + |
---|
| 1997 | +static int snd_rme_sync_source_get(struct snd_kcontrol *kcontrol, |
---|
| 1998 | + struct snd_ctl_elem_value *ucontrol) |
---|
| 1999 | +{ |
---|
| 2000 | + u32 status1; |
---|
| 2001 | + int err; |
---|
| 2002 | + |
---|
| 2003 | + err = snd_rme_get_status1(kcontrol, &status1); |
---|
| 2004 | + if (err < 0) |
---|
| 2005 | + return err; |
---|
| 2006 | + ucontrol->value.enumerated.item[0] = SND_RME_CLK_SYNC(status1); |
---|
| 2007 | + return 0; |
---|
| 2008 | +} |
---|
| 2009 | + |
---|
| 2010 | +static int snd_rme_current_freq_get(struct snd_kcontrol *kcontrol, |
---|
| 2011 | + struct snd_ctl_elem_value *ucontrol) |
---|
| 2012 | +{ |
---|
| 2013 | + struct usb_mixer_elem_list *list = snd_kcontrol_chip(kcontrol); |
---|
| 2014 | + struct snd_usb_audio *chip = list->mixer->chip; |
---|
| 2015 | + u32 status1; |
---|
| 2016 | + const u64 num = 104857600000000ULL; |
---|
| 2017 | + u32 den; |
---|
| 2018 | + unsigned int freq; |
---|
| 2019 | + int err; |
---|
| 2020 | + |
---|
| 2021 | + err = snd_usb_lock_shutdown(chip); |
---|
| 2022 | + if (err < 0) |
---|
| 2023 | + return err; |
---|
| 2024 | + err = snd_rme_read_value(chip, SND_RME_GET_STATUS1, &status1); |
---|
| 2025 | + if (err < 0) |
---|
| 2026 | + goto end; |
---|
| 2027 | + err = snd_rme_read_value(chip, SND_RME_GET_CURRENT_FREQ, &den); |
---|
| 2028 | + if (err < 0) |
---|
| 2029 | + goto end; |
---|
| 2030 | + freq = (den == 0) ? 0 : div64_u64(num, den); |
---|
| 2031 | + freq <<= SND_RME_CLK_FREQMUL(status1); |
---|
| 2032 | + ucontrol->value.integer.value[0] = freq; |
---|
| 2033 | + |
---|
| 2034 | +end: |
---|
| 2035 | + snd_usb_unlock_shutdown(chip); |
---|
| 2036 | + return err; |
---|
| 2037 | +} |
---|
| 2038 | + |
---|
| 2039 | +static int snd_rme_rate_info(struct snd_kcontrol *kcontrol, |
---|
| 2040 | + struct snd_ctl_elem_info *uinfo) |
---|
| 2041 | +{ |
---|
| 2042 | + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
---|
| 2043 | + uinfo->count = 1; |
---|
| 2044 | + switch (kcontrol->private_value) { |
---|
| 2045 | + case SND_RME_DOMAIN_SYSTEM: |
---|
| 2046 | + uinfo->value.integer.min = 32000; |
---|
| 2047 | + uinfo->value.integer.max = 800000; |
---|
| 2048 | + break; |
---|
| 2049 | + case SND_RME_DOMAIN_AES: |
---|
| 2050 | + case SND_RME_DOMAIN_SPDIF: |
---|
| 2051 | + default: |
---|
| 2052 | + uinfo->value.integer.min = 0; |
---|
| 2053 | + uinfo->value.integer.max = 200000; |
---|
| 2054 | + } |
---|
| 2055 | + uinfo->value.integer.step = 0; |
---|
| 2056 | + return 0; |
---|
| 2057 | +} |
---|
| 2058 | + |
---|
| 2059 | +static int snd_rme_sync_state_info(struct snd_kcontrol *kcontrol, |
---|
| 2060 | + struct snd_ctl_elem_info *uinfo) |
---|
| 2061 | +{ |
---|
| 2062 | + static const char *const sync_states[] = { |
---|
| 2063 | + "No Lock", "Lock", "Sync" |
---|
| 2064 | + }; |
---|
| 2065 | + |
---|
| 2066 | + return snd_ctl_enum_info(uinfo, 1, |
---|
| 2067 | + ARRAY_SIZE(sync_states), sync_states); |
---|
| 2068 | +} |
---|
| 2069 | + |
---|
| 2070 | +static int snd_rme_spdif_if_info(struct snd_kcontrol *kcontrol, |
---|
| 2071 | + struct snd_ctl_elem_info *uinfo) |
---|
| 2072 | +{ |
---|
| 2073 | + static const char *const spdif_if[] = { |
---|
| 2074 | + "Coaxial", "Optical" |
---|
| 2075 | + }; |
---|
| 2076 | + |
---|
| 2077 | + return snd_ctl_enum_info(uinfo, 1, |
---|
| 2078 | + ARRAY_SIZE(spdif_if), spdif_if); |
---|
| 2079 | +} |
---|
| 2080 | + |
---|
| 2081 | +static int snd_rme_spdif_format_info(struct snd_kcontrol *kcontrol, |
---|
| 2082 | + struct snd_ctl_elem_info *uinfo) |
---|
| 2083 | +{ |
---|
| 2084 | + static const char *const optical_type[] = { |
---|
| 2085 | + "Consumer", "Professional" |
---|
| 2086 | + }; |
---|
| 2087 | + |
---|
| 2088 | + return snd_ctl_enum_info(uinfo, 1, |
---|
| 2089 | + ARRAY_SIZE(optical_type), optical_type); |
---|
| 2090 | +} |
---|
| 2091 | + |
---|
| 2092 | +static int snd_rme_sync_source_info(struct snd_kcontrol *kcontrol, |
---|
| 2093 | + struct snd_ctl_elem_info *uinfo) |
---|
| 2094 | +{ |
---|
| 2095 | + static const char *const sync_sources[] = { |
---|
| 2096 | + "Internal", "AES", "SPDIF", "Internal" |
---|
| 2097 | + }; |
---|
| 2098 | + |
---|
| 2099 | + return snd_ctl_enum_info(uinfo, 1, |
---|
| 2100 | + ARRAY_SIZE(sync_sources), sync_sources); |
---|
| 2101 | +} |
---|
| 2102 | + |
---|
| 2103 | +static const struct snd_kcontrol_new snd_rme_controls[] = { |
---|
| 2104 | + { |
---|
| 2105 | + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
---|
| 2106 | + .name = "AES Rate", |
---|
| 2107 | + .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, |
---|
| 2108 | + .info = snd_rme_rate_info, |
---|
| 2109 | + .get = snd_rme_rate_get, |
---|
| 2110 | + .private_value = SND_RME_DOMAIN_AES |
---|
| 2111 | + }, |
---|
| 2112 | + { |
---|
| 2113 | + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
---|
| 2114 | + .name = "AES Sync", |
---|
| 2115 | + .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, |
---|
| 2116 | + .info = snd_rme_sync_state_info, |
---|
| 2117 | + .get = snd_rme_sync_state_get, |
---|
| 2118 | + .private_value = SND_RME_DOMAIN_AES |
---|
| 2119 | + }, |
---|
| 2120 | + { |
---|
| 2121 | + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
---|
| 2122 | + .name = "SPDIF Rate", |
---|
| 2123 | + .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, |
---|
| 2124 | + .info = snd_rme_rate_info, |
---|
| 2125 | + .get = snd_rme_rate_get, |
---|
| 2126 | + .private_value = SND_RME_DOMAIN_SPDIF |
---|
| 2127 | + }, |
---|
| 2128 | + { |
---|
| 2129 | + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
---|
| 2130 | + .name = "SPDIF Sync", |
---|
| 2131 | + .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, |
---|
| 2132 | + .info = snd_rme_sync_state_info, |
---|
| 2133 | + .get = snd_rme_sync_state_get, |
---|
| 2134 | + .private_value = SND_RME_DOMAIN_SPDIF |
---|
| 2135 | + }, |
---|
| 2136 | + { |
---|
| 2137 | + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
---|
| 2138 | + .name = "SPDIF Interface", |
---|
| 2139 | + .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, |
---|
| 2140 | + .info = snd_rme_spdif_if_info, |
---|
| 2141 | + .get = snd_rme_spdif_if_get, |
---|
| 2142 | + }, |
---|
| 2143 | + { |
---|
| 2144 | + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
---|
| 2145 | + .name = "SPDIF Format", |
---|
| 2146 | + .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, |
---|
| 2147 | + .info = snd_rme_spdif_format_info, |
---|
| 2148 | + .get = snd_rme_spdif_format_get, |
---|
| 2149 | + }, |
---|
| 2150 | + { |
---|
| 2151 | + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
---|
| 2152 | + .name = "Sync Source", |
---|
| 2153 | + .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, |
---|
| 2154 | + .info = snd_rme_sync_source_info, |
---|
| 2155 | + .get = snd_rme_sync_source_get |
---|
| 2156 | + }, |
---|
| 2157 | + { |
---|
| 2158 | + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
---|
| 2159 | + .name = "System Rate", |
---|
| 2160 | + .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, |
---|
| 2161 | + .info = snd_rme_rate_info, |
---|
| 2162 | + .get = snd_rme_rate_get, |
---|
| 2163 | + .private_value = SND_RME_DOMAIN_SYSTEM |
---|
| 2164 | + }, |
---|
| 2165 | + { |
---|
| 2166 | + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
---|
| 2167 | + .name = "Current Frequency", |
---|
| 2168 | + .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, |
---|
| 2169 | + .info = snd_rme_rate_info, |
---|
| 2170 | + .get = snd_rme_current_freq_get |
---|
| 2171 | + } |
---|
| 2172 | +}; |
---|
| 2173 | + |
---|
| 2174 | +static int snd_rme_controls_create(struct usb_mixer_interface *mixer) |
---|
| 2175 | +{ |
---|
| 2176 | + int err, i; |
---|
| 2177 | + |
---|
| 2178 | + for (i = 0; i < ARRAY_SIZE(snd_rme_controls); ++i) { |
---|
| 2179 | + err = add_single_ctl_with_resume(mixer, 0, |
---|
| 2180 | + NULL, |
---|
| 2181 | + &snd_rme_controls[i], |
---|
| 2182 | + NULL); |
---|
| 2183 | + if (err < 0) |
---|
| 2184 | + return err; |
---|
| 2185 | + } |
---|
| 2186 | + |
---|
| 2187 | + return 0; |
---|
| 2188 | +} |
---|
| 2189 | + |
---|
| 2190 | +/* |
---|
| 2191 | + * RME Babyface Pro (FS) |
---|
| 2192 | + * |
---|
| 2193 | + * These devices exposes a couple of DSP functions via request to EP0. |
---|
| 2194 | + * Switches are available via control registers, while routing is controlled |
---|
| 2195 | + * by controlling the volume on each possible crossing point. |
---|
| 2196 | + * Volume control is linear, from -inf (dec. 0) to +6dB (dec. 65536) with |
---|
| 2197 | + * 0dB being at dec. 32768. |
---|
| 2198 | + */ |
---|
| 2199 | +enum { |
---|
| 2200 | + SND_BBFPRO_CTL_REG1 = 0, |
---|
| 2201 | + SND_BBFPRO_CTL_REG2 |
---|
| 2202 | +}; |
---|
| 2203 | + |
---|
| 2204 | +#define SND_BBFPRO_CTL_REG_MASK 1 |
---|
| 2205 | +#define SND_BBFPRO_CTL_IDX_MASK 0xff |
---|
| 2206 | +#define SND_BBFPRO_CTL_IDX_SHIFT 1 |
---|
| 2207 | +#define SND_BBFPRO_CTL_VAL_MASK 1 |
---|
| 2208 | +#define SND_BBFPRO_CTL_VAL_SHIFT 9 |
---|
| 2209 | +#define SND_BBFPRO_CTL_REG1_CLK_MASTER 0 |
---|
| 2210 | +#define SND_BBFPRO_CTL_REG1_CLK_OPTICAL 1 |
---|
| 2211 | +#define SND_BBFPRO_CTL_REG1_SPDIF_PRO 7 |
---|
| 2212 | +#define SND_BBFPRO_CTL_REG1_SPDIF_EMPH 8 |
---|
| 2213 | +#define SND_BBFPRO_CTL_REG1_SPDIF_OPTICAL 10 |
---|
| 2214 | +#define SND_BBFPRO_CTL_REG2_48V_AN1 0 |
---|
| 2215 | +#define SND_BBFPRO_CTL_REG2_48V_AN2 1 |
---|
| 2216 | +#define SND_BBFPRO_CTL_REG2_SENS_IN3 2 |
---|
| 2217 | +#define SND_BBFPRO_CTL_REG2_SENS_IN4 3 |
---|
| 2218 | +#define SND_BBFPRO_CTL_REG2_PAD_AN1 4 |
---|
| 2219 | +#define SND_BBFPRO_CTL_REG2_PAD_AN2 5 |
---|
| 2220 | + |
---|
| 2221 | +#define SND_BBFPRO_MIXER_IDX_MASK 0x1ff |
---|
| 2222 | +#define SND_BBFPRO_MIXER_VAL_MASK 0x3ffff |
---|
| 2223 | +#define SND_BBFPRO_MIXER_VAL_SHIFT 9 |
---|
| 2224 | +#define SND_BBFPRO_MIXER_VAL_MIN 0 // -inf |
---|
| 2225 | +#define SND_BBFPRO_MIXER_VAL_MAX 65536 // +6dB |
---|
| 2226 | + |
---|
| 2227 | +#define SND_BBFPRO_USBREQ_CTL_REG1 0x10 |
---|
| 2228 | +#define SND_BBFPRO_USBREQ_CTL_REG2 0x17 |
---|
| 2229 | +#define SND_BBFPRO_USBREQ_MIXER 0x12 |
---|
| 2230 | + |
---|
| 2231 | +static int snd_bbfpro_ctl_update(struct usb_mixer_interface *mixer, u8 reg, |
---|
| 2232 | + u8 index, u8 value) |
---|
| 2233 | +{ |
---|
| 2234 | + int err; |
---|
| 2235 | + u16 usb_req, usb_idx, usb_val; |
---|
| 2236 | + struct snd_usb_audio *chip = mixer->chip; |
---|
| 2237 | + |
---|
| 2238 | + err = snd_usb_lock_shutdown(chip); |
---|
| 2239 | + if (err < 0) |
---|
| 2240 | + return err; |
---|
| 2241 | + |
---|
| 2242 | + if (reg == SND_BBFPRO_CTL_REG1) { |
---|
| 2243 | + usb_req = SND_BBFPRO_USBREQ_CTL_REG1; |
---|
| 2244 | + if (index == SND_BBFPRO_CTL_REG1_CLK_OPTICAL) { |
---|
| 2245 | + usb_idx = 3; |
---|
| 2246 | + usb_val = value ? 3 : 0; |
---|
| 2247 | + } else { |
---|
| 2248 | + usb_idx = 1 << index; |
---|
| 2249 | + usb_val = value ? usb_idx : 0; |
---|
| 2250 | + } |
---|
| 2251 | + } else { |
---|
| 2252 | + usb_req = SND_BBFPRO_USBREQ_CTL_REG2; |
---|
| 2253 | + usb_idx = 1 << index; |
---|
| 2254 | + usb_val = value ? usb_idx : 0; |
---|
| 2255 | + } |
---|
| 2256 | + |
---|
| 2257 | + err = snd_usb_ctl_msg(chip->dev, |
---|
| 2258 | + usb_sndctrlpipe(chip->dev, 0), usb_req, |
---|
| 2259 | + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
---|
| 2260 | + usb_val, usb_idx, NULL, 0); |
---|
| 2261 | + |
---|
| 2262 | + snd_usb_unlock_shutdown(chip); |
---|
| 2263 | + return err; |
---|
| 2264 | +} |
---|
| 2265 | + |
---|
| 2266 | +static int snd_bbfpro_ctl_get(struct snd_kcontrol *kcontrol, |
---|
| 2267 | + struct snd_ctl_elem_value *ucontrol) |
---|
| 2268 | +{ |
---|
| 2269 | + u8 reg, idx, val; |
---|
| 2270 | + int pv; |
---|
| 2271 | + |
---|
| 2272 | + pv = kcontrol->private_value; |
---|
| 2273 | + reg = pv & SND_BBFPRO_CTL_REG_MASK; |
---|
| 2274 | + idx = (pv >> SND_BBFPRO_CTL_IDX_SHIFT) & SND_BBFPRO_CTL_IDX_MASK; |
---|
| 2275 | + val = kcontrol->private_value >> SND_BBFPRO_CTL_VAL_SHIFT; |
---|
| 2276 | + |
---|
| 2277 | + if ((reg == SND_BBFPRO_CTL_REG1 && |
---|
| 2278 | + idx == SND_BBFPRO_CTL_REG1_CLK_OPTICAL) || |
---|
| 2279 | + (reg == SND_BBFPRO_CTL_REG2 && |
---|
| 2280 | + (idx == SND_BBFPRO_CTL_REG2_SENS_IN3 || |
---|
| 2281 | + idx == SND_BBFPRO_CTL_REG2_SENS_IN4))) { |
---|
| 2282 | + ucontrol->value.enumerated.item[0] = val; |
---|
| 2283 | + } else { |
---|
| 2284 | + ucontrol->value.integer.value[0] = val; |
---|
| 2285 | + } |
---|
| 2286 | + return 0; |
---|
| 2287 | +} |
---|
| 2288 | + |
---|
| 2289 | +static int snd_bbfpro_ctl_info(struct snd_kcontrol *kcontrol, |
---|
| 2290 | + struct snd_ctl_elem_info *uinfo) |
---|
| 2291 | +{ |
---|
| 2292 | + u8 reg, idx; |
---|
| 2293 | + int pv; |
---|
| 2294 | + |
---|
| 2295 | + pv = kcontrol->private_value; |
---|
| 2296 | + reg = pv & SND_BBFPRO_CTL_REG_MASK; |
---|
| 2297 | + idx = (pv >> SND_BBFPRO_CTL_IDX_SHIFT) & SND_BBFPRO_CTL_IDX_MASK; |
---|
| 2298 | + |
---|
| 2299 | + if (reg == SND_BBFPRO_CTL_REG1 && |
---|
| 2300 | + idx == SND_BBFPRO_CTL_REG1_CLK_OPTICAL) { |
---|
| 2301 | + static const char * const texts[2] = { |
---|
| 2302 | + "AutoSync", |
---|
| 2303 | + "Internal" |
---|
| 2304 | + }; |
---|
| 2305 | + return snd_ctl_enum_info(uinfo, 1, 2, texts); |
---|
| 2306 | + } else if (reg == SND_BBFPRO_CTL_REG2 && |
---|
| 2307 | + (idx == SND_BBFPRO_CTL_REG2_SENS_IN3 || |
---|
| 2308 | + idx == SND_BBFPRO_CTL_REG2_SENS_IN4)) { |
---|
| 2309 | + static const char * const texts[2] = { |
---|
| 2310 | + "-10dBV", |
---|
| 2311 | + "+4dBu" |
---|
| 2312 | + }; |
---|
| 2313 | + return snd_ctl_enum_info(uinfo, 1, 2, texts); |
---|
| 2314 | + } |
---|
| 2315 | + |
---|
| 2316 | + uinfo->count = 1; |
---|
| 2317 | + uinfo->value.integer.min = 0; |
---|
| 2318 | + uinfo->value.integer.max = 1; |
---|
| 2319 | + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; |
---|
| 2320 | + return 0; |
---|
| 2321 | +} |
---|
| 2322 | + |
---|
| 2323 | +static int snd_bbfpro_ctl_put(struct snd_kcontrol *kcontrol, |
---|
| 2324 | + struct snd_ctl_elem_value *ucontrol) |
---|
| 2325 | +{ |
---|
| 2326 | + int err; |
---|
| 2327 | + u8 reg, idx; |
---|
| 2328 | + int old_value, pv, val; |
---|
| 2329 | + |
---|
| 2330 | + struct usb_mixer_elem_list *list = snd_kcontrol_chip(kcontrol); |
---|
| 2331 | + struct usb_mixer_interface *mixer = list->mixer; |
---|
| 2332 | + |
---|
| 2333 | + pv = kcontrol->private_value; |
---|
| 2334 | + reg = pv & SND_BBFPRO_CTL_REG_MASK; |
---|
| 2335 | + idx = (pv >> SND_BBFPRO_CTL_IDX_SHIFT) & SND_BBFPRO_CTL_IDX_MASK; |
---|
| 2336 | + old_value = (pv >> SND_BBFPRO_CTL_VAL_SHIFT) & SND_BBFPRO_CTL_VAL_MASK; |
---|
| 2337 | + |
---|
| 2338 | + if ((reg == SND_BBFPRO_CTL_REG1 && |
---|
| 2339 | + idx == SND_BBFPRO_CTL_REG1_CLK_OPTICAL) || |
---|
| 2340 | + (reg == SND_BBFPRO_CTL_REG2 && |
---|
| 2341 | + (idx == SND_BBFPRO_CTL_REG2_SENS_IN3 || |
---|
| 2342 | + idx == SND_BBFPRO_CTL_REG2_SENS_IN4))) { |
---|
| 2343 | + val = ucontrol->value.enumerated.item[0]; |
---|
| 2344 | + } else { |
---|
| 2345 | + val = ucontrol->value.integer.value[0]; |
---|
| 2346 | + } |
---|
| 2347 | + |
---|
| 2348 | + if (val > 1) |
---|
| 2349 | + return -EINVAL; |
---|
| 2350 | + |
---|
| 2351 | + if (val == old_value) |
---|
| 2352 | + return 0; |
---|
| 2353 | + |
---|
| 2354 | + kcontrol->private_value = reg |
---|
| 2355 | + | ((idx & SND_BBFPRO_CTL_IDX_MASK) << SND_BBFPRO_CTL_IDX_SHIFT) |
---|
| 2356 | + | ((val & SND_BBFPRO_CTL_VAL_MASK) << SND_BBFPRO_CTL_VAL_SHIFT); |
---|
| 2357 | + |
---|
| 2358 | + err = snd_bbfpro_ctl_update(mixer, reg, idx, val); |
---|
| 2359 | + return err < 0 ? err : 1; |
---|
| 2360 | +} |
---|
| 2361 | + |
---|
| 2362 | +static int snd_bbfpro_ctl_resume(struct usb_mixer_elem_list *list) |
---|
| 2363 | +{ |
---|
| 2364 | + u8 reg, idx; |
---|
| 2365 | + int value, pv; |
---|
| 2366 | + |
---|
| 2367 | + pv = list->kctl->private_value; |
---|
| 2368 | + reg = pv & SND_BBFPRO_CTL_REG_MASK; |
---|
| 2369 | + idx = (pv >> SND_BBFPRO_CTL_IDX_SHIFT) & SND_BBFPRO_CTL_IDX_MASK; |
---|
| 2370 | + value = (pv >> SND_BBFPRO_CTL_VAL_SHIFT) & SND_BBFPRO_CTL_VAL_MASK; |
---|
| 2371 | + |
---|
| 2372 | + return snd_bbfpro_ctl_update(list->mixer, reg, idx, value); |
---|
| 2373 | +} |
---|
| 2374 | + |
---|
| 2375 | +static int snd_bbfpro_vol_update(struct usb_mixer_interface *mixer, u16 index, |
---|
| 2376 | + u32 value) |
---|
| 2377 | +{ |
---|
| 2378 | + struct snd_usb_audio *chip = mixer->chip; |
---|
| 2379 | + int err; |
---|
| 2380 | + u16 idx; |
---|
| 2381 | + u16 usb_idx, usb_val; |
---|
| 2382 | + u32 v; |
---|
| 2383 | + |
---|
| 2384 | + err = snd_usb_lock_shutdown(chip); |
---|
| 2385 | + if (err < 0) |
---|
| 2386 | + return err; |
---|
| 2387 | + |
---|
| 2388 | + idx = index & SND_BBFPRO_MIXER_IDX_MASK; |
---|
| 2389 | + // 18 bit linear volume, split so 2 bits end up in index. |
---|
| 2390 | + v = value & SND_BBFPRO_MIXER_VAL_MASK; |
---|
| 2391 | + usb_idx = idx | (v & 0x3) << 14; |
---|
| 2392 | + usb_val = (v >> 2) & 0xffff; |
---|
| 2393 | + |
---|
| 2394 | + err = snd_usb_ctl_msg(chip->dev, |
---|
| 2395 | + usb_sndctrlpipe(chip->dev, 0), |
---|
| 2396 | + SND_BBFPRO_USBREQ_MIXER, |
---|
| 2397 | + USB_DIR_OUT | USB_TYPE_VENDOR | |
---|
| 2398 | + USB_RECIP_DEVICE, |
---|
| 2399 | + usb_val, usb_idx, NULL, 0); |
---|
| 2400 | + |
---|
| 2401 | + snd_usb_unlock_shutdown(chip); |
---|
| 2402 | + return err; |
---|
| 2403 | +} |
---|
| 2404 | + |
---|
| 2405 | +static int snd_bbfpro_vol_get(struct snd_kcontrol *kcontrol, |
---|
| 2406 | + struct snd_ctl_elem_value *ucontrol) |
---|
| 2407 | +{ |
---|
| 2408 | + ucontrol->value.integer.value[0] = |
---|
| 2409 | + kcontrol->private_value >> SND_BBFPRO_MIXER_VAL_SHIFT; |
---|
| 2410 | + return 0; |
---|
| 2411 | +} |
---|
| 2412 | + |
---|
| 2413 | +static int snd_bbfpro_vol_info(struct snd_kcontrol *kcontrol, |
---|
| 2414 | + struct snd_ctl_elem_info *uinfo) |
---|
| 2415 | +{ |
---|
| 2416 | + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
---|
| 2417 | + uinfo->count = 1; |
---|
| 2418 | + uinfo->value.integer.min = SND_BBFPRO_MIXER_VAL_MIN; |
---|
| 2419 | + uinfo->value.integer.max = SND_BBFPRO_MIXER_VAL_MAX; |
---|
| 2420 | + return 0; |
---|
| 2421 | +} |
---|
| 2422 | + |
---|
| 2423 | +static int snd_bbfpro_vol_put(struct snd_kcontrol *kcontrol, |
---|
| 2424 | + struct snd_ctl_elem_value *ucontrol) |
---|
| 2425 | +{ |
---|
| 2426 | + int err; |
---|
| 2427 | + u16 idx; |
---|
| 2428 | + u32 new_val, old_value, uvalue; |
---|
| 2429 | + struct usb_mixer_elem_list *list = snd_kcontrol_chip(kcontrol); |
---|
| 2430 | + struct usb_mixer_interface *mixer = list->mixer; |
---|
| 2431 | + |
---|
| 2432 | + uvalue = ucontrol->value.integer.value[0]; |
---|
| 2433 | + idx = kcontrol->private_value & SND_BBFPRO_MIXER_IDX_MASK; |
---|
| 2434 | + old_value = kcontrol->private_value >> SND_BBFPRO_MIXER_VAL_SHIFT; |
---|
| 2435 | + |
---|
| 2436 | + if (uvalue > SND_BBFPRO_MIXER_VAL_MAX) |
---|
| 2437 | + return -EINVAL; |
---|
| 2438 | + |
---|
| 2439 | + if (uvalue == old_value) |
---|
| 2440 | + return 0; |
---|
| 2441 | + |
---|
| 2442 | + new_val = uvalue & SND_BBFPRO_MIXER_VAL_MASK; |
---|
| 2443 | + |
---|
| 2444 | + kcontrol->private_value = idx |
---|
| 2445 | + | (new_val << SND_BBFPRO_MIXER_VAL_SHIFT); |
---|
| 2446 | + |
---|
| 2447 | + err = snd_bbfpro_vol_update(mixer, idx, new_val); |
---|
| 2448 | + return err < 0 ? err : 1; |
---|
| 2449 | +} |
---|
| 2450 | + |
---|
| 2451 | +static int snd_bbfpro_vol_resume(struct usb_mixer_elem_list *list) |
---|
| 2452 | +{ |
---|
| 2453 | + int pv = list->kctl->private_value; |
---|
| 2454 | + u16 idx = pv & SND_BBFPRO_MIXER_IDX_MASK; |
---|
| 2455 | + u32 val = (pv >> SND_BBFPRO_MIXER_VAL_SHIFT) |
---|
| 2456 | + & SND_BBFPRO_MIXER_VAL_MASK; |
---|
| 2457 | + return snd_bbfpro_vol_update(list->mixer, idx, val); |
---|
| 2458 | +} |
---|
| 2459 | + |
---|
| 2460 | +// Predfine elements |
---|
| 2461 | +static const struct snd_kcontrol_new snd_bbfpro_ctl_control = { |
---|
| 2462 | + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
---|
| 2463 | + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, |
---|
| 2464 | + .index = 0, |
---|
| 2465 | + .info = snd_bbfpro_ctl_info, |
---|
| 2466 | + .get = snd_bbfpro_ctl_get, |
---|
| 2467 | + .put = snd_bbfpro_ctl_put |
---|
| 2468 | +}; |
---|
| 2469 | + |
---|
| 2470 | +static const struct snd_kcontrol_new snd_bbfpro_vol_control = { |
---|
| 2471 | + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
---|
| 2472 | + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, |
---|
| 2473 | + .index = 0, |
---|
| 2474 | + .info = snd_bbfpro_vol_info, |
---|
| 2475 | + .get = snd_bbfpro_vol_get, |
---|
| 2476 | + .put = snd_bbfpro_vol_put |
---|
| 2477 | +}; |
---|
| 2478 | + |
---|
| 2479 | +static int snd_bbfpro_ctl_add(struct usb_mixer_interface *mixer, u8 reg, |
---|
| 2480 | + u8 index, char *name) |
---|
| 2481 | +{ |
---|
| 2482 | + struct snd_kcontrol_new knew = snd_bbfpro_ctl_control; |
---|
| 2483 | + |
---|
| 2484 | + knew.name = name; |
---|
| 2485 | + knew.private_value = (reg & SND_BBFPRO_CTL_REG_MASK) |
---|
| 2486 | + | ((index & SND_BBFPRO_CTL_IDX_MASK) |
---|
| 2487 | + << SND_BBFPRO_CTL_IDX_SHIFT); |
---|
| 2488 | + |
---|
| 2489 | + return add_single_ctl_with_resume(mixer, 0, snd_bbfpro_ctl_resume, |
---|
| 2490 | + &knew, NULL); |
---|
| 2491 | +} |
---|
| 2492 | + |
---|
| 2493 | +static int snd_bbfpro_vol_add(struct usb_mixer_interface *mixer, u16 index, |
---|
| 2494 | + char *name) |
---|
| 2495 | +{ |
---|
| 2496 | + struct snd_kcontrol_new knew = snd_bbfpro_vol_control; |
---|
| 2497 | + |
---|
| 2498 | + knew.name = name; |
---|
| 2499 | + knew.private_value = index & SND_BBFPRO_MIXER_IDX_MASK; |
---|
| 2500 | + |
---|
| 2501 | + return add_single_ctl_with_resume(mixer, 0, snd_bbfpro_vol_resume, |
---|
| 2502 | + &knew, NULL); |
---|
| 2503 | +} |
---|
| 2504 | + |
---|
| 2505 | +static int snd_bbfpro_controls_create(struct usb_mixer_interface *mixer) |
---|
| 2506 | +{ |
---|
| 2507 | + int err, i, o; |
---|
| 2508 | + char name[48]; |
---|
| 2509 | + |
---|
| 2510 | + static const char * const input[] = { |
---|
| 2511 | + "AN1", "AN2", "IN3", "IN4", "AS1", "AS2", "ADAT3", |
---|
| 2512 | + "ADAT4", "ADAT5", "ADAT6", "ADAT7", "ADAT8"}; |
---|
| 2513 | + |
---|
| 2514 | + static const char * const output[] = { |
---|
| 2515 | + "AN1", "AN2", "PH3", "PH4", "AS1", "AS2", "ADAT3", "ADAT4", |
---|
| 2516 | + "ADAT5", "ADAT6", "ADAT7", "ADAT8"}; |
---|
| 2517 | + |
---|
| 2518 | + for (o = 0 ; o < 12 ; ++o) { |
---|
| 2519 | + for (i = 0 ; i < 12 ; ++i) { |
---|
| 2520 | + // Line routing |
---|
| 2521 | + snprintf(name, sizeof(name), |
---|
| 2522 | + "%s-%s-%s Playback Volume", |
---|
| 2523 | + (i < 2 ? "Mic" : "Line"), |
---|
| 2524 | + input[i], output[o]); |
---|
| 2525 | + err = snd_bbfpro_vol_add(mixer, (26 * o + i), name); |
---|
| 2526 | + if (err < 0) |
---|
| 2527 | + return err; |
---|
| 2528 | + |
---|
| 2529 | + // PCM routing... yes, it is output remapping |
---|
| 2530 | + snprintf(name, sizeof(name), |
---|
| 2531 | + "PCM-%s-%s Playback Volume", |
---|
| 2532 | + output[i], output[o]); |
---|
| 2533 | + err = snd_bbfpro_vol_add(mixer, (26 * o + 12 + i), |
---|
| 2534 | + name); |
---|
| 2535 | + if (err < 0) |
---|
| 2536 | + return err; |
---|
| 2537 | + } |
---|
| 2538 | + } |
---|
| 2539 | + |
---|
| 2540 | + // Control Reg 1 |
---|
| 2541 | + err = snd_bbfpro_ctl_add(mixer, SND_BBFPRO_CTL_REG1, |
---|
| 2542 | + SND_BBFPRO_CTL_REG1_CLK_OPTICAL, |
---|
| 2543 | + "Sample Clock Source"); |
---|
| 2544 | + if (err < 0) |
---|
| 2545 | + return err; |
---|
| 2546 | + |
---|
| 2547 | + err = snd_bbfpro_ctl_add(mixer, SND_BBFPRO_CTL_REG1, |
---|
| 2548 | + SND_BBFPRO_CTL_REG1_SPDIF_PRO, |
---|
| 2549 | + "IEC958 Pro Mask"); |
---|
| 2550 | + if (err < 0) |
---|
| 2551 | + return err; |
---|
| 2552 | + |
---|
| 2553 | + err = snd_bbfpro_ctl_add(mixer, SND_BBFPRO_CTL_REG1, |
---|
| 2554 | + SND_BBFPRO_CTL_REG1_SPDIF_EMPH, |
---|
| 2555 | + "IEC958 Emphasis"); |
---|
| 2556 | + if (err < 0) |
---|
| 2557 | + return err; |
---|
| 2558 | + |
---|
| 2559 | + err = snd_bbfpro_ctl_add(mixer, SND_BBFPRO_CTL_REG1, |
---|
| 2560 | + SND_BBFPRO_CTL_REG1_SPDIF_OPTICAL, |
---|
| 2561 | + "IEC958 Switch"); |
---|
| 2562 | + if (err < 0) |
---|
| 2563 | + return err; |
---|
| 2564 | + |
---|
| 2565 | + // Control Reg 2 |
---|
| 2566 | + err = snd_bbfpro_ctl_add(mixer, SND_BBFPRO_CTL_REG2, |
---|
| 2567 | + SND_BBFPRO_CTL_REG2_48V_AN1, |
---|
| 2568 | + "Mic-AN1 48V"); |
---|
| 2569 | + if (err < 0) |
---|
| 2570 | + return err; |
---|
| 2571 | + |
---|
| 2572 | + err = snd_bbfpro_ctl_add(mixer, SND_BBFPRO_CTL_REG2, |
---|
| 2573 | + SND_BBFPRO_CTL_REG2_48V_AN2, |
---|
| 2574 | + "Mic-AN2 48V"); |
---|
| 2575 | + if (err < 0) |
---|
| 2576 | + return err; |
---|
| 2577 | + |
---|
| 2578 | + err = snd_bbfpro_ctl_add(mixer, SND_BBFPRO_CTL_REG2, |
---|
| 2579 | + SND_BBFPRO_CTL_REG2_SENS_IN3, |
---|
| 2580 | + "Line-IN3 Sens."); |
---|
| 2581 | + if (err < 0) |
---|
| 2582 | + return err; |
---|
| 2583 | + |
---|
| 2584 | + err = snd_bbfpro_ctl_add(mixer, SND_BBFPRO_CTL_REG2, |
---|
| 2585 | + SND_BBFPRO_CTL_REG2_SENS_IN4, |
---|
| 2586 | + "Line-IN4 Sens."); |
---|
| 2587 | + if (err < 0) |
---|
| 2588 | + return err; |
---|
| 2589 | + |
---|
| 2590 | + err = snd_bbfpro_ctl_add(mixer, SND_BBFPRO_CTL_REG2, |
---|
| 2591 | + SND_BBFPRO_CTL_REG2_PAD_AN1, |
---|
| 2592 | + "Mic-AN1 PAD"); |
---|
| 2593 | + if (err < 0) |
---|
| 2594 | + return err; |
---|
| 2595 | + |
---|
| 2596 | + err = snd_bbfpro_ctl_add(mixer, SND_BBFPRO_CTL_REG2, |
---|
| 2597 | + SND_BBFPRO_CTL_REG2_PAD_AN2, |
---|
| 2598 | + "Mic-AN2 PAD"); |
---|
| 2599 | + if (err < 0) |
---|
| 2600 | + return err; |
---|
| 2601 | + |
---|
| 2602 | + return 0; |
---|
| 2603 | +} |
---|
| 2604 | + |
---|
| 2605 | +/* |
---|
| 2606 | + * Pioneer DJ DJM Mixers |
---|
| 2607 | + * |
---|
| 2608 | + * These devices generally have options for soft-switching the playback and |
---|
| 2609 | + * capture sources in addition to the recording level. Although different |
---|
| 2610 | + * devices have different configurations, there seems to be canonical values |
---|
| 2611 | + * for specific capture/playback types: See the definitions of these below. |
---|
| 2612 | + * |
---|
| 2613 | + * The wValue is masked with the stereo channel number. e.g. Setting Ch2 to |
---|
| 2614 | + * capture phono would be 0x0203. Capture, playback and capture level have |
---|
| 2615 | + * different wIndexes. |
---|
| 2616 | + */ |
---|
| 2617 | + |
---|
| 2618 | +// Capture types |
---|
| 2619 | +#define SND_DJM_CAP_LINE 0x00 |
---|
| 2620 | +#define SND_DJM_CAP_CDLINE 0x01 |
---|
| 2621 | +#define SND_DJM_CAP_DIGITAL 0x02 |
---|
| 2622 | +#define SND_DJM_CAP_PHONO 0x03 |
---|
| 2623 | +#define SND_DJM_CAP_PFADER 0x06 |
---|
| 2624 | +#define SND_DJM_CAP_XFADERA 0x07 |
---|
| 2625 | +#define SND_DJM_CAP_XFADERB 0x08 |
---|
| 2626 | +#define SND_DJM_CAP_MIC 0x09 |
---|
| 2627 | +#define SND_DJM_CAP_AUX 0x0d |
---|
| 2628 | +#define SND_DJM_CAP_RECOUT 0x0a |
---|
| 2629 | +#define SND_DJM_CAP_NONE 0x0f |
---|
| 2630 | +#define SND_DJM_CAP_CH1PFADER 0x11 |
---|
| 2631 | +#define SND_DJM_CAP_CH2PFADER 0x12 |
---|
| 2632 | +#define SND_DJM_CAP_CH3PFADER 0x13 |
---|
| 2633 | +#define SND_DJM_CAP_CH4PFADER 0x14 |
---|
| 2634 | + |
---|
| 2635 | +// Playback types |
---|
| 2636 | +#define SND_DJM_PB_CH1 0x00 |
---|
| 2637 | +#define SND_DJM_PB_CH2 0x01 |
---|
| 2638 | +#define SND_DJM_PB_AUX 0x04 |
---|
| 2639 | + |
---|
| 2640 | +#define SND_DJM_WINDEX_CAP 0x8002 |
---|
| 2641 | +#define SND_DJM_WINDEX_CAPLVL 0x8003 |
---|
| 2642 | +#define SND_DJM_WINDEX_PB 0x8016 |
---|
| 2643 | + |
---|
| 2644 | +// kcontrol->private_value layout |
---|
| 2645 | +#define SND_DJM_VALUE_MASK 0x0000ffff |
---|
| 2646 | +#define SND_DJM_GROUP_MASK 0x00ff0000 |
---|
| 2647 | +#define SND_DJM_DEVICE_MASK 0xff000000 |
---|
| 2648 | +#define SND_DJM_GROUP_SHIFT 16 |
---|
| 2649 | +#define SND_DJM_DEVICE_SHIFT 24 |
---|
| 2650 | + |
---|
| 2651 | +// device table index |
---|
| 2652 | +#define SND_DJM_250MK2_IDX 0x0 |
---|
| 2653 | +#define SND_DJM_750_IDX 0x1 |
---|
| 2654 | +#define SND_DJM_900NXS2_IDX 0x2 |
---|
| 2655 | + |
---|
| 2656 | + |
---|
| 2657 | +#define SND_DJM_CTL(_name, suffix, _default_value, _windex) { \ |
---|
| 2658 | + .name = _name, \ |
---|
| 2659 | + .options = snd_djm_opts_##suffix, \ |
---|
| 2660 | + .noptions = ARRAY_SIZE(snd_djm_opts_##suffix), \ |
---|
| 2661 | + .default_value = _default_value, \ |
---|
| 2662 | + .wIndex = _windex } |
---|
| 2663 | + |
---|
| 2664 | +#define SND_DJM_DEVICE(suffix) { \ |
---|
| 2665 | + .controls = snd_djm_ctls_##suffix, \ |
---|
| 2666 | + .ncontrols = ARRAY_SIZE(snd_djm_ctls_##suffix) } |
---|
| 2667 | + |
---|
| 2668 | + |
---|
| 2669 | +struct snd_djm_device { |
---|
| 2670 | + const char *name; |
---|
| 2671 | + const struct snd_djm_ctl *controls; |
---|
| 2672 | + size_t ncontrols; |
---|
| 2673 | +}; |
---|
| 2674 | + |
---|
| 2675 | +struct snd_djm_ctl { |
---|
| 2676 | + const char *name; |
---|
| 2677 | + const u16 *options; |
---|
| 2678 | + size_t noptions; |
---|
| 2679 | + u16 default_value; |
---|
| 2680 | + u16 wIndex; |
---|
| 2681 | +}; |
---|
| 2682 | + |
---|
| 2683 | +static const char *snd_djm_get_label_caplevel(u16 wvalue) |
---|
| 2684 | +{ |
---|
| 2685 | + switch (wvalue) { |
---|
| 2686 | + case 0x0000: return "-19dB"; |
---|
| 2687 | + case 0x0100: return "-15dB"; |
---|
| 2688 | + case 0x0200: return "-10dB"; |
---|
| 2689 | + case 0x0300: return "-5dB"; |
---|
| 2690 | + default: return NULL; |
---|
| 2691 | + } |
---|
| 2692 | +}; |
---|
| 2693 | + |
---|
| 2694 | +static const char *snd_djm_get_label_cap(u16 wvalue) |
---|
| 2695 | +{ |
---|
| 2696 | + switch (wvalue & 0x00ff) { |
---|
| 2697 | + case SND_DJM_CAP_LINE: return "Control Tone LINE"; |
---|
| 2698 | + case SND_DJM_CAP_CDLINE: return "Control Tone CD/LINE"; |
---|
| 2699 | + case SND_DJM_CAP_DIGITAL: return "Control Tone DIGITAL"; |
---|
| 2700 | + case SND_DJM_CAP_PHONO: return "Control Tone PHONO"; |
---|
| 2701 | + case SND_DJM_CAP_PFADER: return "Post Fader"; |
---|
| 2702 | + case SND_DJM_CAP_XFADERA: return "Cross Fader A"; |
---|
| 2703 | + case SND_DJM_CAP_XFADERB: return "Cross Fader B"; |
---|
| 2704 | + case SND_DJM_CAP_MIC: return "Mic"; |
---|
| 2705 | + case SND_DJM_CAP_RECOUT: return "Rec Out"; |
---|
| 2706 | + case SND_DJM_CAP_AUX: return "Aux"; |
---|
| 2707 | + case SND_DJM_CAP_NONE: return "None"; |
---|
| 2708 | + case SND_DJM_CAP_CH1PFADER: return "Post Fader Ch1"; |
---|
| 2709 | + case SND_DJM_CAP_CH2PFADER: return "Post Fader Ch2"; |
---|
| 2710 | + case SND_DJM_CAP_CH3PFADER: return "Post Fader Ch3"; |
---|
| 2711 | + case SND_DJM_CAP_CH4PFADER: return "Post Fader Ch4"; |
---|
| 2712 | + default: return NULL; |
---|
| 2713 | + } |
---|
| 2714 | +}; |
---|
| 2715 | + |
---|
| 2716 | +static const char *snd_djm_get_label_pb(u16 wvalue) |
---|
| 2717 | +{ |
---|
| 2718 | + switch (wvalue & 0x00ff) { |
---|
| 2719 | + case SND_DJM_PB_CH1: return "Ch1"; |
---|
| 2720 | + case SND_DJM_PB_CH2: return "Ch2"; |
---|
| 2721 | + case SND_DJM_PB_AUX: return "Aux"; |
---|
| 2722 | + default: return NULL; |
---|
| 2723 | + } |
---|
| 2724 | +}; |
---|
| 2725 | + |
---|
| 2726 | +static const char *snd_djm_get_label(u16 wvalue, u16 windex) |
---|
| 2727 | +{ |
---|
| 2728 | + switch (windex) { |
---|
| 2729 | + case SND_DJM_WINDEX_CAPLVL: return snd_djm_get_label_caplevel(wvalue); |
---|
| 2730 | + case SND_DJM_WINDEX_CAP: return snd_djm_get_label_cap(wvalue); |
---|
| 2731 | + case SND_DJM_WINDEX_PB: return snd_djm_get_label_pb(wvalue); |
---|
| 2732 | + default: return NULL; |
---|
| 2733 | + } |
---|
| 2734 | +}; |
---|
| 2735 | + |
---|
| 2736 | + |
---|
| 2737 | +// DJM-250MK2 |
---|
| 2738 | +static const u16 snd_djm_opts_cap_level[] = { |
---|
| 2739 | + 0x0000, 0x0100, 0x0200, 0x0300 }; |
---|
| 2740 | + |
---|
| 2741 | +static const u16 snd_djm_opts_250mk2_cap1[] = { |
---|
| 2742 | + 0x0103, 0x0100, 0x0106, 0x0107, 0x0108, 0x0109, 0x010d, 0x010a }; |
---|
| 2743 | + |
---|
| 2744 | +static const u16 snd_djm_opts_250mk2_cap2[] = { |
---|
| 2745 | + 0x0203, 0x0200, 0x0206, 0x0207, 0x0208, 0x0209, 0x020d, 0x020a }; |
---|
| 2746 | + |
---|
| 2747 | +static const u16 snd_djm_opts_250mk2_cap3[] = { |
---|
| 2748 | + 0x030a, 0x0311, 0x0312, 0x0307, 0x0308, 0x0309, 0x030d }; |
---|
| 2749 | + |
---|
| 2750 | +static const u16 snd_djm_opts_250mk2_pb1[] = { 0x0100, 0x0101, 0x0104 }; |
---|
| 2751 | +static const u16 snd_djm_opts_250mk2_pb2[] = { 0x0200, 0x0201, 0x0204 }; |
---|
| 2752 | +static const u16 snd_djm_opts_250mk2_pb3[] = { 0x0300, 0x0301, 0x0304 }; |
---|
| 2753 | + |
---|
| 2754 | +static const struct snd_djm_ctl snd_djm_ctls_250mk2[] = { |
---|
| 2755 | + SND_DJM_CTL("Capture Level", cap_level, 0, SND_DJM_WINDEX_CAPLVL), |
---|
| 2756 | + SND_DJM_CTL("Ch1 Input", 250mk2_cap1, 2, SND_DJM_WINDEX_CAP), |
---|
| 2757 | + SND_DJM_CTL("Ch2 Input", 250mk2_cap2, 2, SND_DJM_WINDEX_CAP), |
---|
| 2758 | + SND_DJM_CTL("Ch3 Input", 250mk2_cap3, 0, SND_DJM_WINDEX_CAP), |
---|
| 2759 | + SND_DJM_CTL("Ch1 Output", 250mk2_pb1, 0, SND_DJM_WINDEX_PB), |
---|
| 2760 | + SND_DJM_CTL("Ch2 Output", 250mk2_pb2, 1, SND_DJM_WINDEX_PB), |
---|
| 2761 | + SND_DJM_CTL("Ch3 Output", 250mk2_pb3, 2, SND_DJM_WINDEX_PB) |
---|
| 2762 | +}; |
---|
| 2763 | + |
---|
| 2764 | + |
---|
| 2765 | +// DJM-750 |
---|
| 2766 | +static const u16 snd_djm_opts_750_cap1[] = { |
---|
| 2767 | + 0x0101, 0x0103, 0x0106, 0x0107, 0x0108, 0x0109, 0x010a, 0x010f }; |
---|
| 2768 | +static const u16 snd_djm_opts_750_cap2[] = { |
---|
| 2769 | + 0x0200, 0x0201, 0x0206, 0x0207, 0x0208, 0x0209, 0x020a, 0x020f }; |
---|
| 2770 | +static const u16 snd_djm_opts_750_cap3[] = { |
---|
| 2771 | + 0x0300, 0x0301, 0x0306, 0x0307, 0x0308, 0x0309, 0x030a, 0x030f }; |
---|
| 2772 | +static const u16 snd_djm_opts_750_cap4[] = { |
---|
| 2773 | + 0x0401, 0x0403, 0x0406, 0x0407, 0x0408, 0x0409, 0x040a, 0x040f }; |
---|
| 2774 | + |
---|
| 2775 | +static const struct snd_djm_ctl snd_djm_ctls_750[] = { |
---|
| 2776 | + SND_DJM_CTL("Capture Level", cap_level, 0, SND_DJM_WINDEX_CAPLVL), |
---|
| 2777 | + SND_DJM_CTL("Ch1 Input", 750_cap1, 2, SND_DJM_WINDEX_CAP), |
---|
| 2778 | + SND_DJM_CTL("Ch2 Input", 750_cap2, 2, SND_DJM_WINDEX_CAP), |
---|
| 2779 | + SND_DJM_CTL("Ch3 Input", 750_cap3, 0, SND_DJM_WINDEX_CAP), |
---|
| 2780 | + SND_DJM_CTL("Ch4 Input", 750_cap4, 0, SND_DJM_WINDEX_CAP) |
---|
| 2781 | +}; |
---|
| 2782 | + |
---|
| 2783 | + |
---|
| 2784 | +// DJM-900NXS2 |
---|
| 2785 | +static const u16 snd_djm_opts_900nxs2_cap1[] = { |
---|
| 2786 | + 0x0100, 0x0102, 0x0103, 0x0106, 0x0107, 0x0108, 0x0109, 0x010a }; |
---|
| 2787 | +static const u16 snd_djm_opts_900nxs2_cap2[] = { |
---|
| 2788 | + 0x0200, 0x0202, 0x0203, 0x0206, 0x0207, 0x0208, 0x0209, 0x020a }; |
---|
| 2789 | +static const u16 snd_djm_opts_900nxs2_cap3[] = { |
---|
| 2790 | + 0x0300, 0x0302, 0x0303, 0x0306, 0x0307, 0x0308, 0x0309, 0x030a }; |
---|
| 2791 | +static const u16 snd_djm_opts_900nxs2_cap4[] = { |
---|
| 2792 | + 0x0400, 0x0402, 0x0403, 0x0406, 0x0407, 0x0408, 0x0409, 0x040a }; |
---|
| 2793 | +static const u16 snd_djm_opts_900nxs2_cap5[] = { |
---|
| 2794 | + 0x0507, 0x0508, 0x0509, 0x050a, 0x0511, 0x0512, 0x0513, 0x0514 }; |
---|
| 2795 | + |
---|
| 2796 | +static const struct snd_djm_ctl snd_djm_ctls_900nxs2[] = { |
---|
| 2797 | + SND_DJM_CTL("Capture Level", cap_level, 0, SND_DJM_WINDEX_CAPLVL), |
---|
| 2798 | + SND_DJM_CTL("Ch1 Input", 900nxs2_cap1, 2, SND_DJM_WINDEX_CAP), |
---|
| 2799 | + SND_DJM_CTL("Ch2 Input", 900nxs2_cap2, 2, SND_DJM_WINDEX_CAP), |
---|
| 2800 | + SND_DJM_CTL("Ch3 Input", 900nxs2_cap3, 2, SND_DJM_WINDEX_CAP), |
---|
| 2801 | + SND_DJM_CTL("Ch4 Input", 900nxs2_cap4, 2, SND_DJM_WINDEX_CAP), |
---|
| 2802 | + SND_DJM_CTL("Ch5 Input", 900nxs2_cap5, 3, SND_DJM_WINDEX_CAP) |
---|
| 2803 | +}; |
---|
| 2804 | + |
---|
| 2805 | + |
---|
| 2806 | +static const struct snd_djm_device snd_djm_devices[] = { |
---|
| 2807 | + SND_DJM_DEVICE(250mk2), |
---|
| 2808 | + SND_DJM_DEVICE(750), |
---|
| 2809 | + SND_DJM_DEVICE(900nxs2) |
---|
| 2810 | +}; |
---|
| 2811 | + |
---|
| 2812 | + |
---|
| 2813 | +static int snd_djm_controls_info(struct snd_kcontrol *kctl, |
---|
| 2814 | + struct snd_ctl_elem_info *info) |
---|
| 2815 | +{ |
---|
| 2816 | + unsigned long private_value = kctl->private_value; |
---|
| 2817 | + u8 device_idx = (private_value & SND_DJM_DEVICE_MASK) >> SND_DJM_DEVICE_SHIFT; |
---|
| 2818 | + u8 ctl_idx = (private_value & SND_DJM_GROUP_MASK) >> SND_DJM_GROUP_SHIFT; |
---|
| 2819 | + const struct snd_djm_device *device = &snd_djm_devices[device_idx]; |
---|
| 2820 | + const char *name; |
---|
| 2821 | + const struct snd_djm_ctl *ctl; |
---|
| 2822 | + size_t noptions; |
---|
| 2823 | + |
---|
| 2824 | + if (ctl_idx >= device->ncontrols) |
---|
| 2825 | + return -EINVAL; |
---|
| 2826 | + |
---|
| 2827 | + ctl = &device->controls[ctl_idx]; |
---|
| 2828 | + noptions = ctl->noptions; |
---|
| 2829 | + if (info->value.enumerated.item >= noptions) |
---|
| 2830 | + info->value.enumerated.item = noptions - 1; |
---|
| 2831 | + |
---|
| 2832 | + name = snd_djm_get_label(ctl->options[info->value.enumerated.item], |
---|
| 2833 | + ctl->wIndex); |
---|
| 2834 | + if (!name) |
---|
| 2835 | + return -EINVAL; |
---|
| 2836 | + |
---|
| 2837 | + strlcpy(info->value.enumerated.name, name, sizeof(info->value.enumerated.name)); |
---|
| 2838 | + info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
---|
| 2839 | + info->count = 1; |
---|
| 2840 | + info->value.enumerated.items = noptions; |
---|
| 2841 | + return 0; |
---|
| 2842 | +} |
---|
| 2843 | + |
---|
| 2844 | +static int snd_djm_controls_update(struct usb_mixer_interface *mixer, |
---|
| 2845 | + u8 device_idx, u8 group, u16 value) |
---|
| 2846 | +{ |
---|
| 2847 | + int err; |
---|
| 2848 | + const struct snd_djm_device *device = &snd_djm_devices[device_idx]; |
---|
| 2849 | + |
---|
| 2850 | + if ((group >= device->ncontrols) || value >= device->controls[group].noptions) |
---|
| 2851 | + return -EINVAL; |
---|
| 2852 | + |
---|
| 2853 | + err = snd_usb_lock_shutdown(mixer->chip); |
---|
| 2854 | + if (err) |
---|
| 2855 | + return err; |
---|
| 2856 | + |
---|
| 2857 | + err = snd_usb_ctl_msg( |
---|
| 2858 | + mixer->chip->dev, usb_sndctrlpipe(mixer->chip->dev, 0), |
---|
| 2859 | + USB_REQ_SET_FEATURE, |
---|
| 2860 | + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
---|
| 2861 | + device->controls[group].options[value], |
---|
| 2862 | + device->controls[group].wIndex, |
---|
| 2863 | + NULL, 0); |
---|
| 2864 | + |
---|
| 2865 | + snd_usb_unlock_shutdown(mixer->chip); |
---|
| 2866 | + return err; |
---|
| 2867 | +} |
---|
| 2868 | + |
---|
| 2869 | +static int snd_djm_controls_get(struct snd_kcontrol *kctl, |
---|
| 2870 | + struct snd_ctl_elem_value *elem) |
---|
| 2871 | +{ |
---|
| 2872 | + elem->value.enumerated.item[0] = kctl->private_value & SND_DJM_VALUE_MASK; |
---|
| 2873 | + return 0; |
---|
| 2874 | +} |
---|
| 2875 | + |
---|
| 2876 | +static int snd_djm_controls_put(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *elem) |
---|
| 2877 | +{ |
---|
| 2878 | + struct usb_mixer_elem_list *list = snd_kcontrol_chip(kctl); |
---|
| 2879 | + struct usb_mixer_interface *mixer = list->mixer; |
---|
| 2880 | + unsigned long private_value = kctl->private_value; |
---|
| 2881 | + |
---|
| 2882 | + u8 device = (private_value & SND_DJM_DEVICE_MASK) >> SND_DJM_DEVICE_SHIFT; |
---|
| 2883 | + u8 group = (private_value & SND_DJM_GROUP_MASK) >> SND_DJM_GROUP_SHIFT; |
---|
| 2884 | + u16 value = elem->value.enumerated.item[0]; |
---|
| 2885 | + |
---|
| 2886 | + kctl->private_value = (((unsigned long)device << SND_DJM_DEVICE_SHIFT) | |
---|
| 2887 | + (group << SND_DJM_GROUP_SHIFT) | |
---|
| 2888 | + value); |
---|
| 2889 | + |
---|
| 2890 | + return snd_djm_controls_update(mixer, device, group, value); |
---|
| 2891 | +} |
---|
| 2892 | + |
---|
| 2893 | +static int snd_djm_controls_resume(struct usb_mixer_elem_list *list) |
---|
| 2894 | +{ |
---|
| 2895 | + unsigned long private_value = list->kctl->private_value; |
---|
| 2896 | + u8 device = (private_value & SND_DJM_DEVICE_MASK) >> SND_DJM_DEVICE_SHIFT; |
---|
| 2897 | + u8 group = (private_value & SND_DJM_GROUP_MASK) >> SND_DJM_GROUP_SHIFT; |
---|
| 2898 | + u16 value = (private_value & SND_DJM_VALUE_MASK); |
---|
| 2899 | + |
---|
| 2900 | + return snd_djm_controls_update(list->mixer, device, group, value); |
---|
| 2901 | +} |
---|
| 2902 | + |
---|
| 2903 | +static int snd_djm_controls_create(struct usb_mixer_interface *mixer, |
---|
| 2904 | + const u8 device_idx) |
---|
| 2905 | +{ |
---|
| 2906 | + int err, i; |
---|
| 2907 | + u16 value; |
---|
| 2908 | + |
---|
| 2909 | + const struct snd_djm_device *device = &snd_djm_devices[device_idx]; |
---|
| 2910 | + |
---|
| 2911 | + struct snd_kcontrol_new knew = { |
---|
| 2912 | + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
---|
| 2913 | + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, |
---|
| 2914 | + .index = 0, |
---|
| 2915 | + .info = snd_djm_controls_info, |
---|
| 2916 | + .get = snd_djm_controls_get, |
---|
| 2917 | + .put = snd_djm_controls_put |
---|
| 2918 | + }; |
---|
| 2919 | + |
---|
| 2920 | + for (i = 0; i < device->ncontrols; i++) { |
---|
| 2921 | + value = device->controls[i].default_value; |
---|
| 2922 | + knew.name = device->controls[i].name; |
---|
| 2923 | + knew.private_value = ( |
---|
| 2924 | + ((unsigned long)device_idx << SND_DJM_DEVICE_SHIFT) | |
---|
| 2925 | + (i << SND_DJM_GROUP_SHIFT) | |
---|
| 2926 | + value); |
---|
| 2927 | + err = snd_djm_controls_update(mixer, device_idx, i, value); |
---|
| 2928 | + if (err) |
---|
| 2929 | + return err; |
---|
| 2930 | + err = add_single_ctl_with_resume(mixer, 0, snd_djm_controls_resume, |
---|
| 2931 | + &knew, NULL); |
---|
| 2932 | + if (err) |
---|
| 2933 | + return err; |
---|
| 2934 | + } |
---|
| 2935 | + return 0; |
---|
| 2936 | +} |
---|
| 2937 | + |
---|
1826 | 2938 | int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) |
---|
1827 | 2939 | { |
---|
1828 | 2940 | int err = 0; |
---|
1829 | | - struct snd_info_entry *entry; |
---|
1830 | 2941 | |
---|
1831 | 2942 | err = snd_usb_soundblaster_remote_init(mixer); |
---|
1832 | 2943 | if (err < 0) |
---|
.. | .. |
---|
1845 | 2956 | err = snd_audigy2nx_controls_create(mixer); |
---|
1846 | 2957 | if (err < 0) |
---|
1847 | 2958 | break; |
---|
1848 | | - if (!snd_card_proc_new(mixer->chip->card, "audigy2nx", &entry)) |
---|
1849 | | - snd_info_set_text_ops(entry, mixer, |
---|
1850 | | - snd_audigy2nx_proc_read); |
---|
| 2959 | + snd_card_ro_proc_new(mixer->chip->card, "audigy2nx", |
---|
| 2960 | + mixer, snd_audigy2nx_proc_read); |
---|
1851 | 2961 | break; |
---|
1852 | 2962 | |
---|
1853 | 2963 | /* EMU0204 */ |
---|
.. | .. |
---|
1904 | 3014 | err = snd_scarlett_controls_create(mixer); |
---|
1905 | 3015 | break; |
---|
1906 | 3016 | |
---|
| 3017 | + case USB_ID(0x1235, 0x8203): /* Focusrite Scarlett 6i6 2nd Gen */ |
---|
| 3018 | + case USB_ID(0x1235, 0x8204): /* Focusrite Scarlett 18i8 2nd Gen */ |
---|
| 3019 | + case USB_ID(0x1235, 0x8201): /* Focusrite Scarlett 18i20 2nd Gen */ |
---|
| 3020 | + err = snd_scarlett_gen2_init(mixer); |
---|
| 3021 | + break; |
---|
| 3022 | + |
---|
1907 | 3023 | case USB_ID(0x041e, 0x323b): /* Creative Sound Blaster E1 */ |
---|
1908 | 3024 | err = snd_soundblaster_e1_switch_create(mixer); |
---|
1909 | 3025 | break; |
---|
1910 | 3026 | case USB_ID(0x0bda, 0x4014): /* Dell WD15 dock */ |
---|
1911 | 3027 | err = dell_dock_mixer_init(mixer); |
---|
| 3028 | + break; |
---|
| 3029 | + |
---|
| 3030 | + case USB_ID(0x2a39, 0x3fd2): /* RME ADI-2 Pro */ |
---|
| 3031 | + case USB_ID(0x2a39, 0x3fd3): /* RME ADI-2 DAC */ |
---|
| 3032 | + case USB_ID(0x2a39, 0x3fd4): /* RME */ |
---|
| 3033 | + err = snd_rme_controls_create(mixer); |
---|
| 3034 | + break; |
---|
| 3035 | + |
---|
| 3036 | + case USB_ID(0x194f, 0x010c): /* Presonus Studio 1810c */ |
---|
| 3037 | + err = snd_sc1810_init_mixer(mixer); |
---|
| 3038 | + break; |
---|
| 3039 | + case USB_ID(0x2a39, 0x3fb0): /* RME Babyface Pro FS */ |
---|
| 3040 | + err = snd_bbfpro_controls_create(mixer); |
---|
| 3041 | + break; |
---|
| 3042 | + case USB_ID(0x2b73, 0x0017): /* Pioneer DJ DJM-250MK2 */ |
---|
| 3043 | + err = snd_djm_controls_create(mixer, SND_DJM_250MK2_IDX); |
---|
| 3044 | + break; |
---|
| 3045 | + case USB_ID(0x08e4, 0x017f): /* Pioneer DJ DJM-750 */ |
---|
| 3046 | + err = snd_djm_controls_create(mixer, SND_DJM_750_IDX); |
---|
| 3047 | + break; |
---|
| 3048 | + case USB_ID(0x2b73, 0x000a): /* Pioneer DJ DJM-900NXS2 */ |
---|
| 3049 | + err = snd_djm_controls_create(mixer, SND_DJM_900NXS2_IDX); |
---|
1912 | 3050 | break; |
---|
1913 | 3051 | } |
---|
1914 | 3052 | |
---|
.. | .. |
---|
1997 | 3135 | if (unitid == 7 && cval->control == UAC_FU_VOLUME) |
---|
1998 | 3136 | snd_dragonfly_quirk_db_scale(mixer, cval, kctl); |
---|
1999 | 3137 | break; |
---|
2000 | | - /* lowest playback value is muted on C-Media devices */ |
---|
2001 | | - case USB_ID(0x0d8c, 0x000c): |
---|
2002 | | - case USB_ID(0x0d8c, 0x0014): |
---|
| 3138 | + /* lowest playback value is muted on some devices */ |
---|
| 3139 | + case USB_ID(0x0d8c, 0x000c): /* C-Media */ |
---|
| 3140 | + case USB_ID(0x0d8c, 0x0014): /* C-Media */ |
---|
| 3141 | + case USB_ID(0x19f7, 0x0003): /* RODE NT-USB */ |
---|
2003 | 3142 | if (strstr(kctl->id.name, "Playback")) |
---|
2004 | 3143 | cval->min_mute = 1; |
---|
2005 | 3144 | break; |
---|