[alsa-devel] [PATCH 0/7] TCO fixes for RME MADI/Raydat/AIO/AES cards
Hi!
I've spent another day at IOSONO to work with them on QA patches for the RME MADI series, especially the optional TCO module (LTC synchronisation with video cameras).
Here are our results, all tested for an entire week in their lab.
Cheers
Adrian Knoth (7): ALSA: hdspm - Refactor sample rate acquisition ALSA: hdspm - Allow the TCO and SYNC-IN to be used in slave mode ALSA: hdspm - Provide ALSA control to disable 96K frames ALSA: hdspm - Remove duplicate code from ALSA controls ALSA: hdspm - Also check for TCO sync states ALSA: hdspm - Add ALSA controls to read the TCO LTC state ALSA: hdspm - Enable new TCO ALSA controls
sound/pci/rme9652/hdspm.c | 379 ++++++++++++++++++++++++++++----------------- 1 file changed, 237 insertions(+), 142 deletions(-)
This commit introduces hdspm_get_pll_freq() to avoid code duplication. Reading the sample rate from the DDS register will be required by upcoming code.
Signed-off-by: Adrian Knoth adi@drcomp.erfurt.thur.de
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index 223c3d9..50cba5c 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, struct hdspm *hdspm);
static inline void snd_hdspm_initialize_midi_flush(struct hdspm *hdspm); +static inline int hdspm_get_pll_freq(struct hdspm *hdspm); static int hdspm_update_simple_mixer_controls(struct hdspm *hdspm); static int hdspm_autosync_ref(struct hdspm *hdspm); static int snd_hdspm_set_defaults(struct hdspm *hdspm); @@ -1979,16 +1980,25 @@ static void hdspm_midi_tasklet(unsigned long arg) /* get the system sample rate which is set */
+static inline int hdspm_get_pll_freq(struct hdspm *hdspm) +{ + unsigned int period, rate; + + period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ); + rate = hdspm_calc_dds_value(hdspm, period); + + return rate; +} + /** * Calculate the real sample rate from the * current DDS value. **/ static int hdspm_get_system_sample_rate(struct hdspm *hdspm) { - unsigned int period, rate; + unsigned int rate;
- period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ); - rate = hdspm_calc_dds_value(hdspm, period); + rate = hdspm_get_pll_freq(hdspm);
if (rate > 207000) { /* Unreasonable high sample rate as seen on PCI MADI cards. */
When using the additional Time Code Option module in slave mode or the SYNC-In wordclock connector, the sample rate needs to be returned by hdspm_external_sample_rate().
Since this sample rate may contain any value with 1Hz granularity, we need to round it to a common rate as done by the OSX driver.
Signed-off-by: Adrian Knoth adi@drcomp.erfurt.thur.de
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index 50cba5c..830a899 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -1076,6 +1076,17 @@ static int snd_hdspm_use_is_exclusive(struct hdspm *hdspm) return ret; }
+/* round arbitary sample rates to commonly known rates */ +static int hdspm_round_frequency(int rate) +{ + if (rate < 38050) + return 32000; + if (rate < 46008) + return 44100; + else + return 48000; +} + /* check for external sample rate */ static int hdspm_external_sample_rate(struct hdspm *hdspm) { @@ -1217,21 +1228,44 @@ static int hdspm_external_sample_rate(struct hdspm *hdspm) break; }
- /* QS and DS rates normally can not be detected - * automatically by the card. Only exception is MADI - * in 96k frame mode. - * - * So if we read SS values (32 .. 48k), check for - * user-provided DS/QS bits in the control register - * and multiply the base frequency accordingly. - */ - if (rate <= 48000) { - if (hdspm->control_register & HDSPM_QuadSpeed) - rate *= 4; - else if (hdspm->control_register & - HDSPM_DoubleSpeed) - rate *= 2; + } /* endif HDSPM_madiLock */ + + /* check sample rate from TCO or SYNC_IN */ + { + bool is_valid_input = 0; + bool has_sync = 0; + + syncref = hdspm_autosync_ref(hdspm); + if (HDSPM_AUTOSYNC_FROM_TCO == syncref) { + is_valid_input = 1; + has_sync = (HDSPM_SYNC_CHECK_SYNC == + hdspm_tco_sync_check(hdspm)); + } else if (HDSPM_AUTOSYNC_FROM_SYNC_IN == syncref) { + is_valid_input = 1; + has_sync = (HDSPM_SYNC_CHECK_SYNC == + hdspm_sync_in_sync_check(hdspm)); } + + if (is_valid_input && has_sync) { + rate = hdspm_round_frequency( + hdspm_get_pll_freq(hdspm)); + } + } + + /* QS and DS rates normally can not be detected + * automatically by the card. Only exception is MADI + * in 96k frame mode. + * + * So if we read SS values (32 .. 48k), check for + * user-provided DS/QS bits in the control register + * and multiply the base frequency accordingly. + */ + if (rate <= 48000) { + if (hdspm->control_register & HDSPM_QuadSpeed) + rate *= 4; + else if (hdspm->control_register & + HDSPM_DoubleSpeed) + rate *= 2; } break; }
For 96kHz, MADI allows to multiplex the samples (SMUX) or to use a dedicated 96K mode. The RME cards default to 96K mode, but since not all external MADI equipment supports this, provide a switch to users that changes the on-wire protocol to SMUX.
Signed-off-by: Adrian Knoth adi@drcomp.erfurt.thur.de
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index 830a899..60e992d 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -4189,6 +4189,7 @@ static struct snd_kcontrol_new snd_hdspm_controls_madi[] = { HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 3), HDSPM_TOGGLE_SETTING("Line Out", HDSPM_LineOut), HDSPM_TOGGLE_SETTING("TX 64 channels mode", HDSPM_TX_64ch), + HDSPM_TOGGLE_SETTING("Disable 96K frames", HDSPM_SMUX), HDSPM_TOGGLE_SETTING("Clear Track Marker", HDSPM_clr_tms), HDSPM_TOGGLE_SETTING("Safe Mode", HDSPM_AutoInp), HDSPM_INPUT_SELECT("Input Select", 0),
Considerably shorten the code by using a macro. Though this won't lower the binary size, it makes the source more readable.
Signed-off-by: Adrian Knoth adi@drcomp.erfurt.thur.de
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index 60e992d..9c79803e 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -2172,6 +2172,16 @@ static int hdspm_get_s1_sample_rate(struct hdspm *hdspm, unsigned int idx) return (status >> (idx*4)) & 0xF; }
+#define ENUMERATED_CTL_INFO(info, texts) \ +{ \ + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; \ + uinfo->count = 1; \ + uinfo->value.enumerated.items = ARRAY_SIZE(texts); \ + if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) \ + uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; \ + strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); \ +} +
#define HDSPM_AUTOSYNC_SAMPLE_RATE(xname, xindex) \ @@ -2187,14 +2197,7 @@ static int hdspm_get_s1_sample_rate(struct hdspm *hdspm, unsigned int idx) static int snd_hdspm_info_autosync_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 10; - - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, - texts_freq[uinfo->value.enumerated.item]); + ENUMERATED_CTL_INFO(uinfo, texts_freq); return 0; }
@@ -2360,15 +2363,7 @@ static int snd_hdspm_info_system_clock_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { static char *texts[] = { "Master", "AutoSync" }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 2; - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = - uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); + ENUMERATED_CTL_INFO(uinfo, texts); return 0; }
@@ -3018,17 +3013,7 @@ static int snd_hdspm_info_input_select(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { static char *texts[] = { "optical", "coaxial" }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 2; - - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = - uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); - + ENUMERATED_CTL_INFO(uinfo, texts); return 0; }
@@ -3090,17 +3075,7 @@ static int snd_hdspm_info_ds_wire(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { static char *texts[] = { "Single", "Double" }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 2; - - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = - uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); - + ENUMERATED_CTL_INFO(uinfo, texts); return 0; }
@@ -3173,17 +3148,7 @@ static int snd_hdspm_info_qs_wire(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { static char *texts[] = { "Single", "Double", "Quad" }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 3; - - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = - uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); - + ENUMERATED_CTL_INFO(uinfo, texts); return 0; }
@@ -3259,17 +3224,7 @@ static int snd_hdspm_info_madi_speedmode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { static char *texts[] = { "Single", "Double", "Quad" }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 3; - - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = - uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); - + ENUMERATED_CTL_INFO(uinfo, texts); return 0; }
@@ -3494,14 +3449,7 @@ static int snd_hdspm_info_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { static char *texts[] = { "No Lock", "Lock", "Sync", "N/A" }; - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 4; - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = - uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); + ENUMERATED_CTL_INFO(uinfo, texts); return 0; }
@@ -3857,17 +3805,7 @@ static int snd_hdspm_info_tco_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { static char *texts[] = { "44.1 kHz", "48 kHz" }; - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 2; - - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = - uinfo->value.enumerated.items - 1; - - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); - + ENUMERATED_CTL_INFO(uinfo, texts); return 0; }
@@ -3913,17 +3851,7 @@ static int snd_hdspm_info_tco_pull(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { static char *texts[] = { "0", "+ 0.1 %", "- 0.1 %", "+ 4 %", "- 4 %" }; - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 5; - - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = - uinfo->value.enumerated.items - 1; - - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); - + ENUMERATED_CTL_INFO(uinfo, texts); return 0; }
@@ -3968,17 +3896,7 @@ static int snd_hdspm_info_tco_wck_conversion(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { static char *texts[] = { "1:1", "44.1 -> 48", "48 -> 44.1" }; - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 3; - - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = - uinfo->value.enumerated.items - 1; - - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); - + ENUMERATED_CTL_INFO(uinfo, texts); return 0; }
@@ -4025,17 +3943,7 @@ static int snd_hdspm_info_tco_frame_rate(struct snd_kcontrol *kcontrol, { static char *texts[] = { "24 fps", "25 fps", "29.97fps", "29.97 dfps", "30 fps", "30 dfps" }; - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 6; - - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = - uinfo->value.enumerated.items - 1; - - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); - + ENUMERATED_CTL_INFO(uinfo, texts); return 0; }
@@ -4081,17 +3989,7 @@ static int snd_hdspm_info_tco_sync_source(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { static char *texts[] = { "LTC", "Video", "WCK" }; - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 3; - - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = - uinfo->value.enumerated.items - 1; - - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); - + ENUMERATED_CTL_INFO(uinfo, texts); return 0; }
This patch prepares snd_hdspm_get_sync_check() to also check the TCO sync state. The added feature will be exposed to the user in a later commit.
Signed-off-by: Adrian Knoth adi@drcomp.erfurt.thur.de
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index 9c79803e..9b5382f 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -3444,6 +3444,16 @@ static int snd_hdspm_put_playback_mixer(struct snd_kcontrol *kcontrol, .get = snd_hdspm_get_sync_check \ }
+#define HDSPM_TCO_LOCK_CHECK(xname, xindex) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ + .name = xname, \ + .private_value = xindex, \ + .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ + .info = snd_hdspm_tco_info_lock_check, \ + .get = snd_hdspm_get_sync_check \ +} + +
static int snd_hdspm_info_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) @@ -3453,6 +3463,14 @@ static int snd_hdspm_info_sync_check(struct snd_kcontrol *kcontrol, return 0; }
+static int snd_hdspm_tco_info_lock_check(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + static char *texts[] = { "No Lock", "Lock" }; + ENUMERATED_CTL_INFO(uinfo, texts); + return 0; +} + static int hdspm_wc_sync_check(struct hdspm *hdspm) { int status, status2; @@ -3582,6 +3600,14 @@ static int hdspm_aes_sync_check(struct hdspm *hdspm, int idx) return 0; }
+static int hdspm_tco_input_check(struct hdspm *hdspm, u32 mask) +{ + u32 status; + status = hdspm_read(hdspm, HDSPM_RD_TCO + 4); + + return (status & mask) ? 1 : 0; +} +
static int hdspm_tco_sync_check(struct hdspm *hdspm) { @@ -3689,6 +3715,22 @@ static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol,
}
+ if (hdspm->tco) { + switch (kcontrol->private_value) { + case 11: + /* Check TCO for lock state of its current input */ + val = hdspm_tco_input_check(hdspm, HDSPM_TCO1_TCO_lock); + break; + case 12: + /* Check TCO for valid time code on LTC input. */ + val = hdspm_tco_input_check(hdspm, + HDSPM_TCO1_LTC_Input_valid); + break; + default: + break; + } + } + if (-1 == val) val = 3;
This patch adds new ALSA controls to query the LTC state from userspace.
Signed-off-by: Adrian Knoth adi@drcomp.erfurt.thur.de
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index 9b5382f..f5ef788 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -2927,6 +2927,112 @@ static int snd_hdspm_get_autosync_ref(struct snd_kcontrol *kcontrol, return 0; }
+ + +#define HDSPM_TCO_VIDEO_INPUT_FORMAT(xname, xindex) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ + .name = xname, \ + .access = SNDRV_CTL_ELEM_ACCESS_READ |\ + SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ + .info = snd_hdspm_info_tco_video_input_format, \ + .get = snd_hdspm_get_tco_video_input_format, \ +} + +static int snd_hdspm_info_tco_video_input_format(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + static char *texts[] = {"No video", "NTSC", "PAL"}; + ENUMERATED_CTL_INFO(uinfo, texts); + return 0; +} + +static int snd_hdspm_get_tco_video_input_format(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + u32 status; + int ret = 0; + + struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); + status = hdspm_read(hdspm, HDSPM_RD_TCO + 4); + switch (status & (HDSPM_TCO1_Video_Input_Format_NTSC | + HDSPM_TCO1_Video_Input_Format_PAL)) { + case HDSPM_TCO1_Video_Input_Format_NTSC: + /* ntsc */ + ret = 1; + break; + case HDSPM_TCO1_Video_Input_Format_PAL: + /* pal */ + ret = 2; + break; + default: + /* no video */ + ret = 0; + break; + } + ucontrol->value.enumerated.item[0] = ret; + return 0; +} + + + +#define HDSPM_TCO_LTC_FRAMES(xname, xindex) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ + .name = xname, \ + .access = SNDRV_CTL_ELEM_ACCESS_READ |\ + SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ + .info = snd_hdspm_info_tco_ltc_frames, \ + .get = snd_hdspm_get_tco_ltc_frames, \ +} + +static int snd_hdspm_info_tco_ltc_frames(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + static char *texts[] = {"No lock", "24 fps", "25 fps", "29.97 fps", + "30 fps"}; + ENUMERATED_CTL_INFO(uinfo, texts); + return 0; +} + +static int hdspm_tco_ltc_frames(struct hdspm *hdspm) +{ + u32 status; + int ret = 0; + + status = hdspm_read(hdspm, HDSPM_RD_TCO + 4); + if (status & HDSPM_TCO1_LTC_Input_valid) { + switch (status & (HDSPM_TCO1_LTC_Format_LSB | + HDSPM_TCO1_LTC_Format_MSB)) { + case 0: + /* 24 fps */ + ret = 1; + break; + case HDSPM_TCO1_LTC_Format_LSB: + /* 25 fps */ + ret = 2; + break; + case HDSPM_TCO1_LTC_Format_MSB: + /* 25 fps */ + ret = 3; + break; + default: + /* 30 fps */ + ret = 4; + break; + } + } + + return ret; +} + +static int snd_hdspm_get_tco_ltc_frames(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); + + ucontrol->value.enumerated.item[0] = hdspm_tco_ltc_frames(hdspm); + return 0; +} + #define HDSPM_TOGGLE_SETTING(xname, xindex) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ .name = xname, \
Expose the newly added TCO LTC and sync check functions to userspace.
Signed-off-by: Adrian Knoth adi@drcomp.erfurt.thur.de
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index f5ef788..c3516ed 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -4363,7 +4363,11 @@ static struct snd_kcontrol_new snd_hdspm_controls_tco[] = { HDSPM_TCO_WCK_CONVERSION("TCO WCK Conversion", 0), HDSPM_TCO_FRAME_RATE("TCO Frame Rate", 0), HDSPM_TCO_SYNC_SOURCE("TCO Sync Source", 0), - HDSPM_TCO_WORD_TERM("TCO Word Term", 0) + HDSPM_TCO_WORD_TERM("TCO Word Term", 0), + HDSPM_TCO_LOCK_CHECK("TCO Input Check", 11), + HDSPM_TCO_LOCK_CHECK("TCO LTC Valid", 12), + HDSPM_TCO_LTC_FRAMES("TCO Detected Frame Rate", 0), + HDSPM_TCO_VIDEO_INPUT_FORMAT("Video Input Format", 0) };
At Sun, 10 Mar 2013 00:37:20 +0100, Adrian Knoth wrote:
Hi!
I've spent another day at IOSONO to work with them on QA patches for the RME MADI series, especially the optional TCO module (LTC synchronisation with video cameras).
Here are our results, all tested for an entire week in their lab.
Thanks, applied all patches now.
Takashi
Cheers
Adrian Knoth (7): ALSA: hdspm - Refactor sample rate acquisition ALSA: hdspm - Allow the TCO and SYNC-IN to be used in slave mode ALSA: hdspm - Provide ALSA control to disable 96K frames ALSA: hdspm - Remove duplicate code from ALSA controls ALSA: hdspm - Also check for TCO sync states ALSA: hdspm - Add ALSA controls to read the TCO LTC state ALSA: hdspm - Enable new TCO ALSA controls
sound/pci/rme9652/hdspm.c | 379 ++++++++++++++++++++++++++++----------------- 1 file changed, 237 insertions(+), 142 deletions(-)
-- 1.7.10.4
At Mon, 11 Mar 2013 09:55:51 +0100, Takashi Iwai wrote:
At Sun, 10 Mar 2013 00:37:20 +0100, Adrian Knoth wrote:
Hi!
I've spent another day at IOSONO to work with them on QA patches for the RME MADI series, especially the optional TCO module (LTC synchronisation with video cameras).
Here are our results, all tested for an entire week in their lab.
Thanks, applied all patches now.
... then I found an obvious build error. I fixed up the patch with the following.
Takashi
--- diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index c3516ed..9ea05e9 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -1087,6 +1087,9 @@ static int hdspm_round_frequency(int rate) return 48000; }
+static int hdspm_tco_sync_check(struct hdspm *hdspm); +static int hdspm_sync_in_sync_check(struct hdspm *hdspm); + /* check for external sample rate */ static int hdspm_external_sample_rate(struct hdspm *hdspm) {
On Mon, Mar 11, 2013 at 10:15:35AM +0100, Takashi Iwai wrote:
I've spent another day at IOSONO to work with them on QA patches for the RME MADI series, especially the optional TCO module (LTC synchronisation with video cameras).
Here are our results, all tested for an entire week in their lab.
Thanks, applied all patches now.
... then I found an obvious build error. I fixed up the patch with the following.
Mea culpa, I've prepared the series on an outdated out-of-tree repo while travelling and forgot to transfer the prototypes to the kernel repo.
Thanks for fixing.
Cheers
participants (2)
-
Adrian Knoth
-
Takashi Iwai