Skip to content

Commit

Permalink
TCO updates and status polling fix
Browse files Browse the repository at this point in the history
  • Loading branch information
PhilippeBekaert committed Mar 30, 2022
1 parent cc86215 commit 06aefae
Show file tree
Hide file tree
Showing 10 changed files with 557 additions and 46 deletions.
8 changes: 8 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,14 @@ insert: default
remove:
rmmod snd-hdspe

install: default
-rmmod snd-hdspm
-ln -s $(pwd) /usr/src/alsa-hdspe-0.0
dkms install alsa-hdspe/0.0

uninstall:
dkms remove alsa-hdspe/0.0 --all

list-controls:
-rm asound.state
alsactl -f asound.state store
Expand Down
7 changes: 5 additions & 2 deletions doc/controls.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ TCO controls

| Interface | Name | Access | Value Type | Description |
| :- | :- | :- | :- | :- |
| CARD | TCO Firmware | RO | Int | TCO module firmware version |
| CARD | LTC In | RV | Int64 | Incoming LTC code - see below **LTC control** |
| CARD | LTC In Drop Frame | RV | Bool | Whether incoming LTC is drop frame format or not |
| CARD | LTC In Frame Rate | RV | Enum | Incoming **LTC frame rate**: 24, 25 or 30 fps |
Expand All @@ -94,11 +95,13 @@ TCO controls
| CARD | TCO Lock | RV | Bool | Whether or not the TCO is locked to LTC, Video or Word Clock |
| CARD | TCO Pull | RW | Enum | Pull Up / Pull Down factor |
| CARD | TCO Sync Source | RW | Enum | TCO preferred synchronisation source: LTC, Video or Word Clock |
| CARD | TCO Video Format | RV | Enum | Video format reference signal detected: PAL or NTSC blackburst |
| CARD | TCO Video Format | RV | Enum | Video format reference signal detected: PAL or NTSC blackburst |
| CARD | TCO Video Frame Rate | RV | Enum | Video frame rate detected (meaningful only if TCO firmware >= 11) |
| CARD | TCO WordClk Conversion | RW | Enum | Word clock rate conversion 1:1, 44.1 -> 48 KHz, 48 -> 44.1 KHz |
| CARD | TCO WordClk Term | RW | Bool | Whether or not to 75 Ohm terminate the word clock/video input BNC |
| CARD | TCO WordClk Valid | RV | Bool | Whether or not a valid word clock signal is detected |
| CARD | TCO WordClk Speed | RV | Enum | Detected input word clock speed |
| CARD | TCO WordClk Speed | RV | Enum | Detected input word clock speed |
| CARD | TCO WorldClk Out Speed | RW | Enum | Output word clock speed |

**LTC Control**

Expand Down
52 changes: 50 additions & 2 deletions sound/pci/hdsp/hdspe/hdspe.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,19 @@
* @file hdspe.h
* @brief RME HDSPe driver user space API.
*
* Note: The definitions and structs defined in this header file are used
* within the driver as well as in IOCTLs. As they are used within the
* driver, they are up to date. However, the IOCTLs should be considered
* obsolete: the same information on the driver can be obtained via
* standard ALSA control mechanisms, except for the mixer and level
* meters at this time. To my knowledge (PhB), the only (public) application
* still using the IOCTL interface is hdspmixer. hdspeconf is fully based on
* the ALSA control mechanism. Do not use the IOCTLs for new development -
* inform [email protected] in case you wouldn't be able to do
* without.
*
* 20210728 ... 0813 - [email protected]
* 20220329,30 - PhB : API version 3 (TCO related additions)
*
* Based on earlier work by Winfried Ritsch (IEM, 2003) and
* Thomas Charbonnel ([email protected]),
Expand All @@ -21,7 +33,7 @@
* Structs returned by the HDSPe driver ioctls contain the API version with which the
* kernel driver has been compiled. API users should check that version against
* HDSPE_VERSION and take appropriate action in case versions differ. */
#define HDSPE_VERSION 2
#define HDSPE_VERSION 3

/* Maximum hardware input, software playback and hardware output
* channels is 64 even on 56Mode you have 64playbacks to matrix. */
Expand Down Expand Up @@ -460,11 +472,41 @@ enum hdspe_video_format {
};

#define HDSPE_VIDEO_FORMAT_NAME(i) \
(i == HDSPE_VIDEO_FORMAT_NO_VIDEO ? "No Video" : \
(i == HDSPE_VIDEO_FORMAT_NO_VIDEO ? "" : \
i == HDSPE_VIDEO_FORMAT_NTSC ? "NTSC" : \
i == HDSPE_VIDEO_FORMAT_PAL ? "PAL" : \
"???")

enum hdspe_video_fps { /* TCO firmware version 11 and above */
HDSPE_VIDEO_FPS_NO_VIDEO =0,
HDSPE_VIDEO_FPS_23_98 =1,
HDSPE_VIDEO_FPS_24 =2,
HDSPE_VIDEO_FPS_25 =3,
HDSPE_VIDEO_FPS_29_97 =4,
HDSPE_VIDEO_FPS_30 =5,
HDSPE_VIDEO_FPS_47_95 =6,
HDSPE_VIDEO_FPS_48 =7,
HDSPE_VIDEO_FPS_50 =8,
HDSPE_VIDEO_FPS_59_94 =9,
HDSPE_VIDEO_FPS_60 =10,
HDSPE_VIDEO_FPS_COUNT =11,
HDSPE_VIDEO_FOS_FORCE_32BIT = 0xffffffff
};

#define HDSPE_VIDEO_FPS_NAME(i) \
(i == HDSPE_VIDEO_FPS_NO_VIDEO ? "" : \
i == HDSPE_VIDEO_FPS_23_98 ? "23.98" : \
i == HDSPE_VIDEO_FPS_24 ? "24" : \
i == HDSPE_VIDEO_FPS_25 ? "25" : \
i == HDSPE_VIDEO_FPS_29_97 ? "29.97" : \
i == HDSPE_VIDEO_FPS_30 ? "30" : \
i == HDSPE_VIDEO_FPS_47_95 ? "47.95" : \
i == HDSPE_VIDEO_FPS_48 ? "28" : \
i == HDSPE_VIDEO_FPS_50 ? "50" : \
i == HDSPE_VIDEO_FPS_59_94 ? "59.94" : \
i == HDSPE_VIDEO_FPS_60 ? "60" : \
"???")

enum hdspe_tco_source {
HDSPE_TCO_SOURCE_WCK =0,
HDSPE_TCO_SOURCE_VIDEO =1,
Expand Down Expand Up @@ -612,6 +654,12 @@ struct hdspe_tco_status {
// LTC output control
enum hdspe_bool ltc_run;
enum hdspe_bool ltc_flywheel;

// HDSPE_VERSION 3:
uint32_t fw_version;
uint32_t fs_period_counter;
enum hdspe_video_fps video_in_fps; // if fw_version >= 11
enum hdspe_speed wck_out_speed;
};

#define SNDRV_HDSPE_IOCTL_GET_LTC _IOR('H', 0x46, struct hdspe_tco_status)
Expand Down
23 changes: 13 additions & 10 deletions sound/pci/hdsp/hdspe/hdspe_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* hdspe-control.c
* @brief RME HDSPe sound card driver status and control interface.
*
* 20210727,28,29,30,0908,09,10 - [email protected]
* 20210727,28,29,30,0908,09,10,20220330 - [email protected]
*
* Based on earlier work of the other MODULE_AUTHORS,
* information kindly made available by RME (www.rme-audio.com),
Expand Down Expand Up @@ -195,17 +195,20 @@ void hdspe_status_work(struct work_struct *work)

if (hdspe->last_status_change_jiffies == 0)
hdspe->last_status_change_jiffies = jiffies;

if (changed || jiffies > hdspe->last_status_change_jiffies + 2*HZ) {
if (jiffies > hdspe->last_status_change_jiffies + 2*HZ)
dev_dbg(hdspe->card->dev,
"%s: polling timeout expired.\n", __func__);

if (changed) {
hdspe->last_status_change_jiffies = 0;
hdspe->status_polling = 0; /* disable - user must re-enable */
HDSPE_CTL_NOTIFY(status_polling);
} else if (jiffies > hdspe->last_status_change_jiffies + 2*HZ) {
dev_dbg(hdspe->card->dev,
"%s: polling timeout expired: jiffies=%lu, last_status_change_jiffied=%lu, delta=%ld, 2*HZ=%d.\n", __func__,
jiffies, hdspe->last_status_change_jiffies,
jiffies - hdspe->last_status_change_jiffies, 2*HZ);
hdspe->last_status_change_jiffies = 0;
hdspe->status_polling = 0; /* disable - user must re-enable */
HDSPE_CTL_NOTIFY(status_polling);
}

if (changed)
hdspe->last_status_change_jiffies = jiffies;
}


Expand Down Expand Up @@ -809,7 +812,7 @@ int snd_hdspe_create_controls(struct snd_card *card,
HDSPE_ADD_RV_CONTROL_ID(CARD, "Running", running);
HDSPE_ADD_RV_CONTROL_ID(CARD, "Buffer Size", buffer_size);

HDSPE_ADD_RW_CONTROL_ID(CARD, "Status Polling", status_polling);
HDSPE_ADD_RWV_CONTROL_ID(CARD, "Status Polling", status_polling);
HDSPE_ADD_RV_CONTROL_ID(HWDEP, "Raw Sample Rate", raw_sample_rate);
HDSPE_ADD_RW_CONTROL_ID(HWDEP, "DDS", dds);
HDSPE_ADD_RW_CONTROL_ID(CARD, "Internal Frequency", internal_freq);
Expand Down
22 changes: 21 additions & 1 deletion sound/pci/hdsp/hdspe/hdspe_control.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* @file hdspe-control.h
* @brief RME HDSPe sound card driver status and control interface helpers.
*
* 20210728,0907,08,09,10 - [email protected]
* 20210728,0907,08,09,10,20220330 - [email protected]
*
* Based on earlier work of the other MODULE_AUTHORs,
* information kindly made available by RME (www.rme-audio.com),
Expand Down Expand Up @@ -72,6 +72,23 @@
.put = snd_hdspe_put_##prop \
}

/**
* HDSPE_RWV_KCTL - generate a snd_kcontrol_new struct for a read-write
* volatile property.
* @xface: MIXER, CARD, etc...
* @xname: display name for the property.
* @prop: source code name for the property.
*/
#define HDSPE_RWV_KCTL(xface, xname, prop) \
{ .iface = SNDRV_CTL_ELEM_IFACE_##xface, \
.name = xname, \
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
.info = snd_hdspe_info_##prop, \
.get = snd_hdspe_get_##prop, \
.put = snd_hdspe_put_##prop \
}

/**
* HDSPE_WO_KCTL - generate a snd_kcontrol_new struct for a write-only property.
* @xface: MIXER, CARD, etc...
Expand Down Expand Up @@ -444,5 +461,8 @@ static int snd_hdspe_put_##prop(struct snd_kcontrol *kcontrol, \
#define HDSPE_ADD_RW_BOOL_CONTROL_ID(iface, name, prop) \
HDSPE_ADD_CONTROL_ID(HDSPE_RW_BOOL_KCTL(iface, name, prop), prop)

#define HDSPE_ADD_RWV_CONTROL_ID(iface, name, prop) \
HDSPE_ADD_CONTROL_ID(HDSPE_RWV_KCTL(iface, name, prop), prop)


#endif /* _HDSPE_CONTROL_H_ */
2 changes: 2 additions & 0 deletions sound/pci/hdsp/hdspe/hdspe_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,8 @@ static int snd_hdspe_create(struct hdspe *hdspe)

pci_set_master(hdspe->pci);

/* TODO: mac driver sets PCI latency timer to 255 ??? */

err = pci_request_regions(pci, "hdspe");
if (err < 0)
return err;
Expand Down
7 changes: 6 additions & 1 deletion sound/pci/hdsp/hdspe/hdspe_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -788,6 +788,7 @@ struct hdspe_tco {
enum hdspe_pull pull;
enum hdspe_wck_conversion wck_conversion;
enum hdspe_bool term;
enum hdspe_speed wck_out_speed;

/* LTC out control */
u32 ltc_out; /* requested start LTC for output */
Expand All @@ -807,7 +808,7 @@ struct hdspe_tco {

/* for measuring the actual LTC In fps and pull factor */
#define LTC_CACHE_SIZE 60
u64 prev_ltc_time; /* nanosecond timestamp of previous LTC irq */
u64 prev_ltc_time; /* nanosecond timestamp of previous MTC irq */
u64 ltc_duration_sum; /* sum of observed LTC frame durations */
u32 ltc_duration[LTC_CACHE_SIZE]; /* observed LTC frame durations */
u32 ltc_count; /* number of received LTC frames */
Expand All @@ -818,6 +819,8 @@ struct hdspe_tco {
#ifdef DEBUG_MTC
u32 mtc; /* current MIDI time code */
#endif /*DEBUG_MTC*/

u8 fw_version; /* TCO firmware version */
};

/**
Expand Down Expand Up @@ -905,6 +908,8 @@ struct hdspe_ctl_ids {
struct snd_ctl_elem_id* tco_lock;
struct snd_ctl_elem_id* ltc_run;
struct snd_ctl_elem_id* ltc_jam_sync;
struct snd_ctl_elem_id* video_in_fps;
/* struct snd_ctl_elem_id* wck_out_rate; */
};

struct hdspe {
Expand Down
11 changes: 7 additions & 4 deletions sound/pci/hdsp/hdspe/hdspe_midi.c
Original file line number Diff line number Diff line change
Expand Up @@ -309,13 +309,13 @@ int snd_hdspe_create_midi(struct snd_card* card,
err = snd_rawmidi_new(card, buf, id, 1, 1, &m->rmidi);
if (err < 0)
return err;

snprintf(m->rmidi->name, sizeof(m->rmidi->name),
rw ? "%s MIDI %d" : "%s MTC %d",
card->id, id+1);

m->rmidi->private_data = &hdspe->midi[id];

if (rw) { // read-write port
snprintf(m->rmidi->name, sizeof(m->rmidi->name),
"%s MIDI %d", card->id, id+1);

snd_rawmidi_set_ops(m->rmidi,
SNDRV_RAWMIDI_STREAM_OUTPUT,
&snd_hdspe_midi_output);
Expand All @@ -328,6 +328,9 @@ int snd_hdspe_create_midi(struct snd_card* card,
SNDRV_RAWMIDI_INFO_INPUT |
SNDRV_RAWMIDI_INFO_DUPLEX;
} else { // read-only port (MTC from TCO module)
snprintf(m->rmidi->name, sizeof(m->rmidi->name),
"%s MTC", card->id);

snd_rawmidi_set_ops(m->rmidi,
SNDRV_RAWMIDI_STREAM_INPUT,
&snd_hdspe_midi_input);
Expand Down
Loading

0 comments on commit 06aefae

Please sign in to comment.