diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-03 12:10:23 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-03 12:10:23 -0400 |
commit | 9992ba72327fa0d8bdc9fb624e80f5cce338a711 (patch) | |
tree | e0bf31ae53cb19c44674df7e0d0343a26037ad34 /sound/pci/rme9652 | |
parent | 00fdffb5131125dce0702bf61e24a806ec3aed80 (diff) | |
parent | 4ca231b2e6ed171107c5b21f9e92d1965fd6fd9e (diff) |
Merge tag 'sound-3.10' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound updates from Takashi Iwai:
"Mostly many small changes spread as seen in diffstat in sound/*
directory by this update. A significant change in the subsystem level
is the introduction of snd_soc_component, which will help more generic
handling of SoC and off-SoC components.
Also, snd_BUG_ON() macro is enabled unconditionally now due to its
misuses, so people might hit kernel warnings (it's a good thing for
us).
- compress-offload: support for capture by Charles Keepax
- HD-audio: codec delay support by Dylan Reid
- HD-audio: improvements/fixes in generic parser: better headphone
mic and headset mic support, jack_modes hint consolidation, proper
beep attach/detachment, generalized power filter controls by David
Henningsson, et al
- HD-audio: Improved management of HDMI codec pins/converters
- HD-audio: Better pin/DAC assignment for VIA codecs
- HD-audio: Haswell HDMI workarounds
- HD-audio: ALC268 codec support, a few new quirks for Chromebooks
- USB: regression fixes: USB-MIDI autopm fix, the recent ISO latency
fix by Clemens Ladisch
- USB: support for DSD formats by Daniel Mack
- USB: A few UAC2 device endian/cock fixes by Eldad Zack
- USB: quirks for Emu 192kHz support, Novation Twitch DJ controller,
Yamaha THRxx devices
- HDSPM: updates for TCO controls by Adrian Knoth
- ASoC: Add a snd_soc_component object type for generic handling of
SoC and off-SoC components by Kuninori Morimoto,
- dmaengine: a large set of cleanups and conversions by Lars-Peter
Clausen
- ASoC DAPM: performance optimizations from Ryo Tsutsui
- ASoC DAPM: support for mixer control sharing by Stephen Warren
- ASoC: multiplatform ARM cleanups from Arnd Bergmann
- ASoC: new codec drivers for AK5385 and TAS5086 from Daniel Mack"
* tag 'sound-3.10' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (315 commits)
ALSA: usb-audio: caiaq: fix endianness bug in snd_usb_caiaq_maschine_dispatch
ALSA: asihpi: add format support check in snd_card_asihpi_capture_formats
ALSA: pcm_format_to_bits strong-typed conversion
ALSA: compress: fix the states to check for allowing read
ALSA: hda - Move Thinkpad X220 to use auto parser
ALSA: USB: adjust for changed 3.8 USB API
ALSA: usb - Avoid unnecessary sample rate changes on USB 2.0 clock sources
sound: oss/dmabuf: use dma_map_single
ALSA: ali5451: use mdelay instead of large udelay constants
ALSA: hda - Add the support for ALC286 codec
ALSA: usb-audio: USB quirk for Yamaha THR10C
ALSA: usb-audio: USB quirk for Yamaha THR5A
ALSA: usb-audio: USB quirk for Yamaha THR10
ALSA: usb-audio: Fix autopm error during probing
ALSA: snd-usb: try harder to find USB_DT_CS_ENDPOINT
ALSA: sound kconfig typo
ALSA: emu10k1: Fix dock firmware loading
ASoC: ux500: forward declare msp_i2s_platform_data
ASoC: davinci-mcasp: Add Support BCLK-to-LRCLK ratio for TDM modes
ASoC: davinci-pcm, davinci-mcasp: Clean up active_serializers
...
Diffstat (limited to 'sound/pci/rme9652')
-rw-r--r-- | sound/pci/rme9652/hdspm.c | 382 |
1 files changed, 240 insertions, 142 deletions
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index 223c3d9cc69e..9ea05e956474 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c | |||
@@ -969,6 +969,7 @@ static int snd_hdspm_create_pcm(struct snd_card *card, | |||
969 | struct hdspm *hdspm); | 969 | struct hdspm *hdspm); |
970 | 970 | ||
971 | static inline void snd_hdspm_initialize_midi_flush(struct hdspm *hdspm); | 971 | static inline void snd_hdspm_initialize_midi_flush(struct hdspm *hdspm); |
972 | static inline int hdspm_get_pll_freq(struct hdspm *hdspm); | ||
972 | static int hdspm_update_simple_mixer_controls(struct hdspm *hdspm); | 973 | static int hdspm_update_simple_mixer_controls(struct hdspm *hdspm); |
973 | static int hdspm_autosync_ref(struct hdspm *hdspm); | 974 | static int hdspm_autosync_ref(struct hdspm *hdspm); |
974 | static int snd_hdspm_set_defaults(struct hdspm *hdspm); | 975 | static int snd_hdspm_set_defaults(struct hdspm *hdspm); |
@@ -1075,6 +1076,20 @@ static int snd_hdspm_use_is_exclusive(struct hdspm *hdspm) | |||
1075 | return ret; | 1076 | return ret; |
1076 | } | 1077 | } |
1077 | 1078 | ||
1079 | /* round arbitary sample rates to commonly known rates */ | ||
1080 | static int hdspm_round_frequency(int rate) | ||
1081 | { | ||
1082 | if (rate < 38050) | ||
1083 | return 32000; | ||
1084 | if (rate < 46008) | ||
1085 | return 44100; | ||
1086 | else | ||
1087 | return 48000; | ||
1088 | } | ||
1089 | |||
1090 | static int hdspm_tco_sync_check(struct hdspm *hdspm); | ||
1091 | static int hdspm_sync_in_sync_check(struct hdspm *hdspm); | ||
1092 | |||
1078 | /* check for external sample rate */ | 1093 | /* check for external sample rate */ |
1079 | static int hdspm_external_sample_rate(struct hdspm *hdspm) | 1094 | static int hdspm_external_sample_rate(struct hdspm *hdspm) |
1080 | { | 1095 | { |
@@ -1216,22 +1231,45 @@ static int hdspm_external_sample_rate(struct hdspm *hdspm) | |||
1216 | break; | 1231 | break; |
1217 | } | 1232 | } |
1218 | 1233 | ||
1219 | /* QS and DS rates normally can not be detected | 1234 | } /* endif HDSPM_madiLock */ |
1220 | * automatically by the card. Only exception is MADI | 1235 | |
1221 | * in 96k frame mode. | 1236 | /* check sample rate from TCO or SYNC_IN */ |
1222 | * | 1237 | { |
1223 | * So if we read SS values (32 .. 48k), check for | 1238 | bool is_valid_input = 0; |
1224 | * user-provided DS/QS bits in the control register | 1239 | bool has_sync = 0; |
1225 | * and multiply the base frequency accordingly. | 1240 | |
1226 | */ | 1241 | syncref = hdspm_autosync_ref(hdspm); |
1227 | if (rate <= 48000) { | 1242 | if (HDSPM_AUTOSYNC_FROM_TCO == syncref) { |
1228 | if (hdspm->control_register & HDSPM_QuadSpeed) | 1243 | is_valid_input = 1; |
1229 | rate *= 4; | 1244 | has_sync = (HDSPM_SYNC_CHECK_SYNC == |
1230 | else if (hdspm->control_register & | 1245 | hdspm_tco_sync_check(hdspm)); |
1231 | HDSPM_DoubleSpeed) | 1246 | } else if (HDSPM_AUTOSYNC_FROM_SYNC_IN == syncref) { |
1232 | rate *= 2; | 1247 | is_valid_input = 1; |
1248 | has_sync = (HDSPM_SYNC_CHECK_SYNC == | ||
1249 | hdspm_sync_in_sync_check(hdspm)); | ||
1250 | } | ||
1251 | |||
1252 | if (is_valid_input && has_sync) { | ||
1253 | rate = hdspm_round_frequency( | ||
1254 | hdspm_get_pll_freq(hdspm)); | ||
1233 | } | 1255 | } |
1234 | } | 1256 | } |
1257 | |||
1258 | /* QS and DS rates normally can not be detected | ||
1259 | * automatically by the card. Only exception is MADI | ||
1260 | * in 96k frame mode. | ||
1261 | * | ||
1262 | * So if we read SS values (32 .. 48k), check for | ||
1263 | * user-provided DS/QS bits in the control register | ||
1264 | * and multiply the base frequency accordingly. | ||
1265 | */ | ||
1266 | if (rate <= 48000) { | ||
1267 | if (hdspm->control_register & HDSPM_QuadSpeed) | ||
1268 | rate *= 4; | ||
1269 | else if (hdspm->control_register & | ||
1270 | HDSPM_DoubleSpeed) | ||
1271 | rate *= 2; | ||
1272 | } | ||
1235 | break; | 1273 | break; |
1236 | } | 1274 | } |
1237 | 1275 | ||
@@ -1979,16 +2017,25 @@ static void hdspm_midi_tasklet(unsigned long arg) | |||
1979 | /* get the system sample rate which is set */ | 2017 | /* get the system sample rate which is set */ |
1980 | 2018 | ||
1981 | 2019 | ||
2020 | static inline int hdspm_get_pll_freq(struct hdspm *hdspm) | ||
2021 | { | ||
2022 | unsigned int period, rate; | ||
2023 | |||
2024 | period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ); | ||
2025 | rate = hdspm_calc_dds_value(hdspm, period); | ||
2026 | |||
2027 | return rate; | ||
2028 | } | ||
2029 | |||
1982 | /** | 2030 | /** |
1983 | * Calculate the real sample rate from the | 2031 | * Calculate the real sample rate from the |
1984 | * current DDS value. | 2032 | * current DDS value. |
1985 | **/ | 2033 | **/ |
1986 | static int hdspm_get_system_sample_rate(struct hdspm *hdspm) | 2034 | static int hdspm_get_system_sample_rate(struct hdspm *hdspm) |
1987 | { | 2035 | { |
1988 | unsigned int period, rate; | 2036 | unsigned int rate; |
1989 | 2037 | ||
1990 | period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ); | 2038 | rate = hdspm_get_pll_freq(hdspm); |
1991 | rate = hdspm_calc_dds_value(hdspm, period); | ||
1992 | 2039 | ||
1993 | if (rate > 207000) { | 2040 | if (rate > 207000) { |
1994 | /* Unreasonable high sample rate as seen on PCI MADI cards. */ | 2041 | /* Unreasonable high sample rate as seen on PCI MADI cards. */ |
@@ -2128,6 +2175,16 @@ static int hdspm_get_s1_sample_rate(struct hdspm *hdspm, unsigned int idx) | |||
2128 | return (status >> (idx*4)) & 0xF; | 2175 | return (status >> (idx*4)) & 0xF; |
2129 | } | 2176 | } |
2130 | 2177 | ||
2178 | #define ENUMERATED_CTL_INFO(info, texts) \ | ||
2179 | { \ | ||
2180 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; \ | ||
2181 | uinfo->count = 1; \ | ||
2182 | uinfo->value.enumerated.items = ARRAY_SIZE(texts); \ | ||
2183 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) \ | ||
2184 | uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; \ | ||
2185 | strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); \ | ||
2186 | } | ||
2187 | |||
2131 | 2188 | ||
2132 | 2189 | ||
2133 | #define HDSPM_AUTOSYNC_SAMPLE_RATE(xname, xindex) \ | 2190 | #define HDSPM_AUTOSYNC_SAMPLE_RATE(xname, xindex) \ |
@@ -2143,14 +2200,7 @@ static int hdspm_get_s1_sample_rate(struct hdspm *hdspm, unsigned int idx) | |||
2143 | static int snd_hdspm_info_autosync_sample_rate(struct snd_kcontrol *kcontrol, | 2200 | static int snd_hdspm_info_autosync_sample_rate(struct snd_kcontrol *kcontrol, |
2144 | struct snd_ctl_elem_info *uinfo) | 2201 | struct snd_ctl_elem_info *uinfo) |
2145 | { | 2202 | { |
2146 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 2203 | ENUMERATED_CTL_INFO(uinfo, texts_freq); |
2147 | uinfo->count = 1; | ||
2148 | uinfo->value.enumerated.items = 10; | ||
2149 | |||
2150 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
2151 | uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; | ||
2152 | strcpy(uinfo->value.enumerated.name, | ||
2153 | texts_freq[uinfo->value.enumerated.item]); | ||
2154 | return 0; | 2204 | return 0; |
2155 | } | 2205 | } |
2156 | 2206 | ||
@@ -2316,15 +2366,7 @@ static int snd_hdspm_info_system_clock_mode(struct snd_kcontrol *kcontrol, | |||
2316 | struct snd_ctl_elem_info *uinfo) | 2366 | struct snd_ctl_elem_info *uinfo) |
2317 | { | 2367 | { |
2318 | static char *texts[] = { "Master", "AutoSync" }; | 2368 | static char *texts[] = { "Master", "AutoSync" }; |
2319 | 2369 | ENUMERATED_CTL_INFO(uinfo, texts); | |
2320 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
2321 | uinfo->count = 1; | ||
2322 | uinfo->value.enumerated.items = 2; | ||
2323 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
2324 | uinfo->value.enumerated.item = | ||
2325 | uinfo->value.enumerated.items - 1; | ||
2326 | strcpy(uinfo->value.enumerated.name, | ||
2327 | texts[uinfo->value.enumerated.item]); | ||
2328 | return 0; | 2370 | return 0; |
2329 | } | 2371 | } |
2330 | 2372 | ||
@@ -2888,6 +2930,112 @@ static int snd_hdspm_get_autosync_ref(struct snd_kcontrol *kcontrol, | |||
2888 | return 0; | 2930 | return 0; |
2889 | } | 2931 | } |
2890 | 2932 | ||
2933 | |||
2934 | |||
2935 | #define HDSPM_TCO_VIDEO_INPUT_FORMAT(xname, xindex) \ | ||
2936 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
2937 | .name = xname, \ | ||
2938 | .access = SNDRV_CTL_ELEM_ACCESS_READ |\ | ||
2939 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ | ||
2940 | .info = snd_hdspm_info_tco_video_input_format, \ | ||
2941 | .get = snd_hdspm_get_tco_video_input_format, \ | ||
2942 | } | ||
2943 | |||
2944 | static int snd_hdspm_info_tco_video_input_format(struct snd_kcontrol *kcontrol, | ||
2945 | struct snd_ctl_elem_info *uinfo) | ||
2946 | { | ||
2947 | static char *texts[] = {"No video", "NTSC", "PAL"}; | ||
2948 | ENUMERATED_CTL_INFO(uinfo, texts); | ||
2949 | return 0; | ||
2950 | } | ||
2951 | |||
2952 | static int snd_hdspm_get_tco_video_input_format(struct snd_kcontrol *kcontrol, | ||
2953 | struct snd_ctl_elem_value *ucontrol) | ||
2954 | { | ||
2955 | u32 status; | ||
2956 | int ret = 0; | ||
2957 | |||
2958 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | ||
2959 | status = hdspm_read(hdspm, HDSPM_RD_TCO + 4); | ||
2960 | switch (status & (HDSPM_TCO1_Video_Input_Format_NTSC | | ||
2961 | HDSPM_TCO1_Video_Input_Format_PAL)) { | ||
2962 | case HDSPM_TCO1_Video_Input_Format_NTSC: | ||
2963 | /* ntsc */ | ||
2964 | ret = 1; | ||
2965 | break; | ||
2966 | case HDSPM_TCO1_Video_Input_Format_PAL: | ||
2967 | /* pal */ | ||
2968 | ret = 2; | ||
2969 | break; | ||
2970 | default: | ||
2971 | /* no video */ | ||
2972 | ret = 0; | ||
2973 | break; | ||
2974 | } | ||
2975 | ucontrol->value.enumerated.item[0] = ret; | ||
2976 | return 0; | ||
2977 | } | ||
2978 | |||
2979 | |||
2980 | |||
2981 | #define HDSPM_TCO_LTC_FRAMES(xname, xindex) \ | ||
2982 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
2983 | .name = xname, \ | ||
2984 | .access = SNDRV_CTL_ELEM_ACCESS_READ |\ | ||
2985 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ | ||
2986 | .info = snd_hdspm_info_tco_ltc_frames, \ | ||
2987 | .get = snd_hdspm_get_tco_ltc_frames, \ | ||
2988 | } | ||
2989 | |||
2990 | static int snd_hdspm_info_tco_ltc_frames(struct snd_kcontrol *kcontrol, | ||
2991 | struct snd_ctl_elem_info *uinfo) | ||
2992 | { | ||
2993 | static char *texts[] = {"No lock", "24 fps", "25 fps", "29.97 fps", | ||
2994 | "30 fps"}; | ||
2995 | ENUMERATED_CTL_INFO(uinfo, texts); | ||
2996 | return 0; | ||
2997 | } | ||
2998 | |||
2999 | static int hdspm_tco_ltc_frames(struct hdspm *hdspm) | ||
3000 | { | ||
3001 | u32 status; | ||
3002 | int ret = 0; | ||
3003 | |||
3004 | status = hdspm_read(hdspm, HDSPM_RD_TCO + 4); | ||
3005 | if (status & HDSPM_TCO1_LTC_Input_valid) { | ||
3006 | switch (status & (HDSPM_TCO1_LTC_Format_LSB | | ||
3007 | HDSPM_TCO1_LTC_Format_MSB)) { | ||
3008 | case 0: | ||
3009 | /* 24 fps */ | ||
3010 | ret = 1; | ||
3011 | break; | ||
3012 | case HDSPM_TCO1_LTC_Format_LSB: | ||
3013 | /* 25 fps */ | ||
3014 | ret = 2; | ||
3015 | break; | ||
3016 | case HDSPM_TCO1_LTC_Format_MSB: | ||
3017 | /* 25 fps */ | ||
3018 | ret = 3; | ||
3019 | break; | ||
3020 | default: | ||
3021 | /* 30 fps */ | ||
3022 | ret = 4; | ||
3023 | break; | ||
3024 | } | ||
3025 | } | ||
3026 | |||
3027 | return ret; | ||
3028 | } | ||
3029 | |||
3030 | static int snd_hdspm_get_tco_ltc_frames(struct snd_kcontrol *kcontrol, | ||
3031 | struct snd_ctl_elem_value *ucontrol) | ||
3032 | { | ||
3033 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | ||
3034 | |||
3035 | ucontrol->value.enumerated.item[0] = hdspm_tco_ltc_frames(hdspm); | ||
3036 | return 0; | ||
3037 | } | ||
3038 | |||
2891 | #define HDSPM_TOGGLE_SETTING(xname, xindex) \ | 3039 | #define HDSPM_TOGGLE_SETTING(xname, xindex) \ |
2892 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 3040 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
2893 | .name = xname, \ | 3041 | .name = xname, \ |
@@ -2974,17 +3122,7 @@ static int snd_hdspm_info_input_select(struct snd_kcontrol *kcontrol, | |||
2974 | struct snd_ctl_elem_info *uinfo) | 3122 | struct snd_ctl_elem_info *uinfo) |
2975 | { | 3123 | { |
2976 | static char *texts[] = { "optical", "coaxial" }; | 3124 | static char *texts[] = { "optical", "coaxial" }; |
2977 | 3125 | ENUMERATED_CTL_INFO(uinfo, texts); | |
2978 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
2979 | uinfo->count = 1; | ||
2980 | uinfo->value.enumerated.items = 2; | ||
2981 | |||
2982 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
2983 | uinfo->value.enumerated.item = | ||
2984 | uinfo->value.enumerated.items - 1; | ||
2985 | strcpy(uinfo->value.enumerated.name, | ||
2986 | texts[uinfo->value.enumerated.item]); | ||
2987 | |||
2988 | return 0; | 3126 | return 0; |
2989 | } | 3127 | } |
2990 | 3128 | ||
@@ -3046,17 +3184,7 @@ static int snd_hdspm_info_ds_wire(struct snd_kcontrol *kcontrol, | |||
3046 | struct snd_ctl_elem_info *uinfo) | 3184 | struct snd_ctl_elem_info *uinfo) |
3047 | { | 3185 | { |
3048 | static char *texts[] = { "Single", "Double" }; | 3186 | static char *texts[] = { "Single", "Double" }; |
3049 | 3187 | ENUMERATED_CTL_INFO(uinfo, texts); | |
3050 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
3051 | uinfo->count = 1; | ||
3052 | uinfo->value.enumerated.items = 2; | ||
3053 | |||
3054 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
3055 | uinfo->value.enumerated.item = | ||
3056 | uinfo->value.enumerated.items - 1; | ||
3057 | strcpy(uinfo->value.enumerated.name, | ||
3058 | texts[uinfo->value.enumerated.item]); | ||
3059 | |||
3060 | return 0; | 3188 | return 0; |
3061 | } | 3189 | } |
3062 | 3190 | ||
@@ -3129,17 +3257,7 @@ static int snd_hdspm_info_qs_wire(struct snd_kcontrol *kcontrol, | |||
3129 | struct snd_ctl_elem_info *uinfo) | 3257 | struct snd_ctl_elem_info *uinfo) |
3130 | { | 3258 | { |
3131 | static char *texts[] = { "Single", "Double", "Quad" }; | 3259 | static char *texts[] = { "Single", "Double", "Quad" }; |
3132 | 3260 | ENUMERATED_CTL_INFO(uinfo, texts); | |
3133 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
3134 | uinfo->count = 1; | ||
3135 | uinfo->value.enumerated.items = 3; | ||
3136 | |||
3137 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
3138 | uinfo->value.enumerated.item = | ||
3139 | uinfo->value.enumerated.items - 1; | ||
3140 | strcpy(uinfo->value.enumerated.name, | ||
3141 | texts[uinfo->value.enumerated.item]); | ||
3142 | |||
3143 | return 0; | 3261 | return 0; |
3144 | } | 3262 | } |
3145 | 3263 | ||
@@ -3215,17 +3333,7 @@ static int snd_hdspm_info_madi_speedmode(struct snd_kcontrol *kcontrol, | |||
3215 | struct snd_ctl_elem_info *uinfo) | 3333 | struct snd_ctl_elem_info *uinfo) |
3216 | { | 3334 | { |
3217 | static char *texts[] = { "Single", "Double", "Quad" }; | 3335 | static char *texts[] = { "Single", "Double", "Quad" }; |
3218 | 3336 | ENUMERATED_CTL_INFO(uinfo, texts); | |
3219 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
3220 | uinfo->count = 1; | ||
3221 | uinfo->value.enumerated.items = 3; | ||
3222 | |||
3223 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
3224 | uinfo->value.enumerated.item = | ||
3225 | uinfo->value.enumerated.items - 1; | ||
3226 | strcpy(uinfo->value.enumerated.name, | ||
3227 | texts[uinfo->value.enumerated.item]); | ||
3228 | |||
3229 | return 0; | 3337 | return 0; |
3230 | } | 3338 | } |
3231 | 3339 | ||
@@ -3445,19 +3553,30 @@ static int snd_hdspm_put_playback_mixer(struct snd_kcontrol *kcontrol, | |||
3445 | .get = snd_hdspm_get_sync_check \ | 3553 | .get = snd_hdspm_get_sync_check \ |
3446 | } | 3554 | } |
3447 | 3555 | ||
3556 | #define HDSPM_TCO_LOCK_CHECK(xname, xindex) \ | ||
3557 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
3558 | .name = xname, \ | ||
3559 | .private_value = xindex, \ | ||
3560 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ | ||
3561 | .info = snd_hdspm_tco_info_lock_check, \ | ||
3562 | .get = snd_hdspm_get_sync_check \ | ||
3563 | } | ||
3564 | |||
3565 | |||
3448 | 3566 | ||
3449 | static int snd_hdspm_info_sync_check(struct snd_kcontrol *kcontrol, | 3567 | static int snd_hdspm_info_sync_check(struct snd_kcontrol *kcontrol, |
3450 | struct snd_ctl_elem_info *uinfo) | 3568 | struct snd_ctl_elem_info *uinfo) |
3451 | { | 3569 | { |
3452 | static char *texts[] = { "No Lock", "Lock", "Sync", "N/A" }; | 3570 | static char *texts[] = { "No Lock", "Lock", "Sync", "N/A" }; |
3453 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 3571 | ENUMERATED_CTL_INFO(uinfo, texts); |
3454 | uinfo->count = 1; | 3572 | return 0; |
3455 | uinfo->value.enumerated.items = 4; | 3573 | } |
3456 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | 3574 | |
3457 | uinfo->value.enumerated.item = | 3575 | static int snd_hdspm_tco_info_lock_check(struct snd_kcontrol *kcontrol, |
3458 | uinfo->value.enumerated.items - 1; | 3576 | struct snd_ctl_elem_info *uinfo) |
3459 | strcpy(uinfo->value.enumerated.name, | 3577 | { |
3460 | texts[uinfo->value.enumerated.item]); | 3578 | static char *texts[] = { "No Lock", "Lock" }; |
3579 | ENUMERATED_CTL_INFO(uinfo, texts); | ||
3461 | return 0; | 3580 | return 0; |
3462 | } | 3581 | } |
3463 | 3582 | ||
@@ -3590,6 +3709,14 @@ static int hdspm_aes_sync_check(struct hdspm *hdspm, int idx) | |||
3590 | return 0; | 3709 | return 0; |
3591 | } | 3710 | } |
3592 | 3711 | ||
3712 | static int hdspm_tco_input_check(struct hdspm *hdspm, u32 mask) | ||
3713 | { | ||
3714 | u32 status; | ||
3715 | status = hdspm_read(hdspm, HDSPM_RD_TCO + 4); | ||
3716 | |||
3717 | return (status & mask) ? 1 : 0; | ||
3718 | } | ||
3719 | |||
3593 | 3720 | ||
3594 | static int hdspm_tco_sync_check(struct hdspm *hdspm) | 3721 | static int hdspm_tco_sync_check(struct hdspm *hdspm) |
3595 | { | 3722 | { |
@@ -3697,6 +3824,22 @@ static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol, | |||
3697 | 3824 | ||
3698 | } | 3825 | } |
3699 | 3826 | ||
3827 | if (hdspm->tco) { | ||
3828 | switch (kcontrol->private_value) { | ||
3829 | case 11: | ||
3830 | /* Check TCO for lock state of its current input */ | ||
3831 | val = hdspm_tco_input_check(hdspm, HDSPM_TCO1_TCO_lock); | ||
3832 | break; | ||
3833 | case 12: | ||
3834 | /* Check TCO for valid time code on LTC input. */ | ||
3835 | val = hdspm_tco_input_check(hdspm, | ||
3836 | HDSPM_TCO1_LTC_Input_valid); | ||
3837 | break; | ||
3838 | default: | ||
3839 | break; | ||
3840 | } | ||
3841 | } | ||
3842 | |||
3700 | if (-1 == val) | 3843 | if (-1 == val) |
3701 | val = 3; | 3844 | val = 3; |
3702 | 3845 | ||
@@ -3813,17 +3956,7 @@ static int snd_hdspm_info_tco_sample_rate(struct snd_kcontrol *kcontrol, | |||
3813 | struct snd_ctl_elem_info *uinfo) | 3956 | struct snd_ctl_elem_info *uinfo) |
3814 | { | 3957 | { |
3815 | static char *texts[] = { "44.1 kHz", "48 kHz" }; | 3958 | static char *texts[] = { "44.1 kHz", "48 kHz" }; |
3816 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 3959 | ENUMERATED_CTL_INFO(uinfo, texts); |
3817 | uinfo->count = 1; | ||
3818 | uinfo->value.enumerated.items = 2; | ||
3819 | |||
3820 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
3821 | uinfo->value.enumerated.item = | ||
3822 | uinfo->value.enumerated.items - 1; | ||
3823 | |||
3824 | strcpy(uinfo->value.enumerated.name, | ||
3825 | texts[uinfo->value.enumerated.item]); | ||
3826 | |||
3827 | return 0; | 3960 | return 0; |
3828 | } | 3961 | } |
3829 | 3962 | ||
@@ -3869,17 +4002,7 @@ static int snd_hdspm_info_tco_pull(struct snd_kcontrol *kcontrol, | |||
3869 | struct snd_ctl_elem_info *uinfo) | 4002 | struct snd_ctl_elem_info *uinfo) |
3870 | { | 4003 | { |
3871 | static char *texts[] = { "0", "+ 0.1 %", "- 0.1 %", "+ 4 %", "- 4 %" }; | 4004 | static char *texts[] = { "0", "+ 0.1 %", "- 0.1 %", "+ 4 %", "- 4 %" }; |
3872 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 4005 | ENUMERATED_CTL_INFO(uinfo, texts); |
3873 | uinfo->count = 1; | ||
3874 | uinfo->value.enumerated.items = 5; | ||
3875 | |||
3876 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
3877 | uinfo->value.enumerated.item = | ||
3878 | uinfo->value.enumerated.items - 1; | ||
3879 | |||
3880 | strcpy(uinfo->value.enumerated.name, | ||
3881 | texts[uinfo->value.enumerated.item]); | ||
3882 | |||
3883 | return 0; | 4006 | return 0; |
3884 | } | 4007 | } |
3885 | 4008 | ||
@@ -3924,17 +4047,7 @@ static int snd_hdspm_info_tco_wck_conversion(struct snd_kcontrol *kcontrol, | |||
3924 | struct snd_ctl_elem_info *uinfo) | 4047 | struct snd_ctl_elem_info *uinfo) |
3925 | { | 4048 | { |
3926 | static char *texts[] = { "1:1", "44.1 -> 48", "48 -> 44.1" }; | 4049 | static char *texts[] = { "1:1", "44.1 -> 48", "48 -> 44.1" }; |
3927 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 4050 | ENUMERATED_CTL_INFO(uinfo, texts); |
3928 | uinfo->count = 1; | ||
3929 | uinfo->value.enumerated.items = 3; | ||
3930 | |||
3931 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
3932 | uinfo->value.enumerated.item = | ||
3933 | uinfo->value.enumerated.items - 1; | ||
3934 | |||
3935 | strcpy(uinfo->value.enumerated.name, | ||
3936 | texts[uinfo->value.enumerated.item]); | ||
3937 | |||
3938 | return 0; | 4051 | return 0; |
3939 | } | 4052 | } |
3940 | 4053 | ||
@@ -3981,17 +4094,7 @@ static int snd_hdspm_info_tco_frame_rate(struct snd_kcontrol *kcontrol, | |||
3981 | { | 4094 | { |
3982 | static char *texts[] = { "24 fps", "25 fps", "29.97fps", | 4095 | static char *texts[] = { "24 fps", "25 fps", "29.97fps", |
3983 | "29.97 dfps", "30 fps", "30 dfps" }; | 4096 | "29.97 dfps", "30 fps", "30 dfps" }; |
3984 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 4097 | ENUMERATED_CTL_INFO(uinfo, texts); |
3985 | uinfo->count = 1; | ||
3986 | uinfo->value.enumerated.items = 6; | ||
3987 | |||
3988 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
3989 | uinfo->value.enumerated.item = | ||
3990 | uinfo->value.enumerated.items - 1; | ||
3991 | |||
3992 | strcpy(uinfo->value.enumerated.name, | ||
3993 | texts[uinfo->value.enumerated.item]); | ||
3994 | |||
3995 | return 0; | 4098 | return 0; |
3996 | } | 4099 | } |
3997 | 4100 | ||
@@ -4037,17 +4140,7 @@ static int snd_hdspm_info_tco_sync_source(struct snd_kcontrol *kcontrol, | |||
4037 | struct snd_ctl_elem_info *uinfo) | 4140 | struct snd_ctl_elem_info *uinfo) |
4038 | { | 4141 | { |
4039 | static char *texts[] = { "LTC", "Video", "WCK" }; | 4142 | static char *texts[] = { "LTC", "Video", "WCK" }; |
4040 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 4143 | ENUMERATED_CTL_INFO(uinfo, texts); |
4041 | uinfo->count = 1; | ||
4042 | uinfo->value.enumerated.items = 3; | ||
4043 | |||
4044 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
4045 | uinfo->value.enumerated.item = | ||
4046 | uinfo->value.enumerated.items - 1; | ||
4047 | |||
4048 | strcpy(uinfo->value.enumerated.name, | ||
4049 | texts[uinfo->value.enumerated.item]); | ||
4050 | |||
4051 | return 0; | 4144 | return 0; |
4052 | } | 4145 | } |
4053 | 4146 | ||
@@ -4145,6 +4238,7 @@ static struct snd_kcontrol_new snd_hdspm_controls_madi[] = { | |||
4145 | HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 3), | 4238 | HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 3), |
4146 | HDSPM_TOGGLE_SETTING("Line Out", HDSPM_LineOut), | 4239 | HDSPM_TOGGLE_SETTING("Line Out", HDSPM_LineOut), |
4147 | HDSPM_TOGGLE_SETTING("TX 64 channels mode", HDSPM_TX_64ch), | 4240 | HDSPM_TOGGLE_SETTING("TX 64 channels mode", HDSPM_TX_64ch), |
4241 | HDSPM_TOGGLE_SETTING("Disable 96K frames", HDSPM_SMUX), | ||
4148 | HDSPM_TOGGLE_SETTING("Clear Track Marker", HDSPM_clr_tms), | 4242 | HDSPM_TOGGLE_SETTING("Clear Track Marker", HDSPM_clr_tms), |
4149 | HDSPM_TOGGLE_SETTING("Safe Mode", HDSPM_AutoInp), | 4243 | HDSPM_TOGGLE_SETTING("Safe Mode", HDSPM_AutoInp), |
4150 | HDSPM_INPUT_SELECT("Input Select", 0), | 4244 | HDSPM_INPUT_SELECT("Input Select", 0), |
@@ -4272,7 +4366,11 @@ static struct snd_kcontrol_new snd_hdspm_controls_tco[] = { | |||
4272 | HDSPM_TCO_WCK_CONVERSION("TCO WCK Conversion", 0), | 4366 | HDSPM_TCO_WCK_CONVERSION("TCO WCK Conversion", 0), |
4273 | HDSPM_TCO_FRAME_RATE("TCO Frame Rate", 0), | 4367 | HDSPM_TCO_FRAME_RATE("TCO Frame Rate", 0), |
4274 | HDSPM_TCO_SYNC_SOURCE("TCO Sync Source", 0), | 4368 | HDSPM_TCO_SYNC_SOURCE("TCO Sync Source", 0), |
4275 | HDSPM_TCO_WORD_TERM("TCO Word Term", 0) | 4369 | HDSPM_TCO_WORD_TERM("TCO Word Term", 0), |
4370 | HDSPM_TCO_LOCK_CHECK("TCO Input Check", 11), | ||
4371 | HDSPM_TCO_LOCK_CHECK("TCO LTC Valid", 12), | ||
4372 | HDSPM_TCO_LTC_FRAMES("TCO Detected Frame Rate", 0), | ||
4373 | HDSPM_TCO_VIDEO_INPUT_FORMAT("Video Input Format", 0) | ||
4276 | }; | 4374 | }; |
4277 | 4375 | ||
4278 | 4376 | ||