Browse Source

added new code for h/w monitoring with the RME HDSP interface

git-svn-id: svn+ssh://jackaudio.org/trunk/jack@283 0c269be4-1314-0410-8aa9-9f06e86f4224
tags/0.109.0
pbd 22 years ago
parent
commit
148d4588c2
5 changed files with 263 additions and 5 deletions
  1. +2
    -2
      configure.in
  2. +1
    -1
      drivers/alsa/Makefile.am
  3. +13
    -2
      drivers/alsa/alsa_driver.c
  4. +214
    -0
      drivers/alsa/hdsp.c
  5. +33
    -0
      jack/hdsp.h

+ 2
- 2
configure.in View File

@@ -13,8 +13,8 @@ dnl micro version = incremented when implementation-only
dnl changes are made
dnl ---
JACK_MAJOR_VERSION=0
JACK_MINOR_VERSION=42
JACK_MICRO_VERSION=2
JACK_MINOR_VERSION=43
JACK_MICRO_VERSION=0

dnl ---
dnl HOWTO: updating the libjack interface version


+ 1
- 1
drivers/alsa/Makefile.am View File

@@ -8,5 +8,5 @@ plugin_LTLIBRARIES = jack_alsa.la

jack_alsa_la_LDFLAGS = -module
jack_alsa_la_SOURCES = alsa_driver.c generic_hw.c memops.c \
hammerfall.c ice1712.c
hammerfall.c hdsp.c ice1712.c
jack_alsa_la_LIBADD = $(ALSA_LIBS)

+ 13
- 2
drivers/alsa/alsa_driver.c View File

@@ -32,6 +32,7 @@
#include <jack/internal.h>
#include <jack/engine.h>
#include <jack/hammerfall.h>
#include <jack/hdsp.h>
#include <jack/ice1712.h>
#include <jack/generic.h>
#include <jack/cycles.h>
@@ -108,6 +109,14 @@ alsa_driver_hammerfall_hardware (alsa_driver_t *driver)
return 0;
}

static int
alsa_driver_hdsp_hardware (alsa_driver_t *driver)

{
driver->hw = jack_alsa_hdsp_hw_new (driver);
return 0;
}

static int
alsa_driver_ice1712_hardware (alsa_driver_t *driver)

@@ -134,6 +143,10 @@ alsa_driver_hw_specific (alsa_driver_t *driver, int hw_monitoring)
if ((err = alsa_driver_hammerfall_hardware (driver)) != 0) {
return err;
}
} else if (!strcmp(driver->alsa_driver, "H-DSP")) {
if ((err = alsa_driver_hdsp_hardware (driver)) !=0) {
return err;
}
} else if (!strcmp(driver->alsa_driver, "ICE1712")) {
if ((err = alsa_driver_ice1712_hardware (driver)) !=0) {
return err;
@@ -1139,7 +1152,6 @@ alsa_driver_process (alsa_driver_t *driver, jack_nframes_t nframes)
}
if (!driver->hw_monitoring) {

if (driver->playback_handle) {
if (driver->all_monitor_in) {
for (chn = 0; chn < driver->playback_nchannels; chn++) {
@@ -1155,7 +1167,6 @@ alsa_driver_process (alsa_driver_t *driver, jack_nframes_t nframes)
}

} else {

if ((driver->hw->input_monitor_mask != driver->input_monitor_mask) && !driver->all_monitor_in) {
driver->hw->set_input_monitor_mask (driver->hw, driver->input_monitor_mask);
}


+ 214
- 0
drivers/alsa/hdsp.c View File

@@ -0,0 +1,214 @@
/*
Copyright (C) 2001 Paul Davis
Copyright (C) 2002 Dave LaRose

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

$Id$
*/

#include <jack/hardware.h>
#include <jack/alsa_driver.h>
#include <jack/hdsp.h>
#include <jack/error.h>
#include <jack/internal.h>

/* Constants to make working with the hdsp matrix mixer easier */
static const int HDSP_MINUS_INFINITY_GAIN = 0;
static const int HDSP_UNITY_GAIN = 32768;
static const int HDSP_MAX_GAIN = 65535;

/*
* Use these two arrays to choose the value of the input_channel
* argument to hsdp_set_mixer_gain(). hdsp_physical_input_index[n]
* selects the nth optical/analog input. audio_stream_index[n]
* selects the nth channel being received from the host via pci/pccard.
*/
static const int hdsp_num_input_channels = 52;
static const int hdsp_physical_input_index[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25};
static const int hdsp_audio_stream_index[] = {
26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51};

/*
* Use this array to choose the value of the output_channel
* argument to hsdp_set_mixer_gain(). hdsp_physical_output_index[26]
* and hdsp_physical_output_index[27] refer to the two "line out"
* channels (1/4" phone jack on the front of digiface/multiface).
*/
static const int hdsp_num_output_channels = 28;
static const int hdsp_physical_output_index[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27};


/* Function for checking argument values */
static int clamp_int(int value, int lower_bound, int upper_bound)
{
if(value < lower_bound) {
return lower_bound;
}
if(value > upper_bound) {
return upper_bound;
}
return value;
}

/* Note(XXX): Maybe should share this code with hammerfall.c? */
static void
set_control_id (snd_ctl_elem_id_t *ctl, const char *name)
{
snd_ctl_elem_id_set_name (ctl, name);
snd_ctl_elem_id_set_numid (ctl, 0);
snd_ctl_elem_id_set_interface (ctl, SND_CTL_ELEM_IFACE_PCM);
snd_ctl_elem_id_set_device (ctl, 0);
snd_ctl_elem_id_set_subdevice (ctl, 0);
snd_ctl_elem_id_set_index (ctl, 0);
}

/* The hdsp matrix mixer lets you connect pretty much any input to */
/* any output with gain from -inf to about +2dB. Pretty slick. */
/* This routine makes a convenient way to set the gain from */
/* input_channel to output_channel (see hdsp_physical_input_index */
/* etc. above. */
/* gain is an int from 0 to 65535, with 0 being -inf gain, and */
/* 65535 being about 2dB. */
static int hdsp_set_mixer_gain(jack_hardware_t *hw, int input_channel,
int output_channel, int gain)
{
hdsp_t *h = (hdsp_t *) hw->private;
snd_ctl_elem_value_t *ctl;
snd_ctl_elem_id_t *ctl_id;
int err;

/* Check args */
input_channel = clamp_int(input_channel, 0, hdsp_num_input_channels);
output_channel = clamp_int(output_channel, 0, hdsp_num_output_channels);
gain = clamp_int(gain, HDSP_MINUS_INFINITY_GAIN, HDSP_MAX_GAIN);

/* Allocate control element and select "Mixer" control */
snd_ctl_elem_value_alloca (&ctl);
snd_ctl_elem_id_alloca (&ctl_id);
set_control_id (ctl_id, "Mixer");
snd_ctl_elem_value_set_id (ctl, ctl_id);

/* Apparently non-standard and unstable interface for the */
/* mixer control. */
snd_ctl_elem_value_set_integer (ctl, 0, input_channel);
snd_ctl_elem_value_set_integer (ctl, 1, output_channel);
snd_ctl_elem_value_set_integer (ctl, 2, gain);

/* Commit the mixer value and check for errors */
if ((err = snd_ctl_elem_write (h->driver->ctl_handle, ctl)) != 0) {
jack_error ("ALSA/HDSP: cannot set mixer gain (%s)", snd_strerror (err));
return -1;
}

/* Note (XXX): Perhaps we should maintain a cache of the current */
/* mixer values, since it's not clear how to query them from the */
/* hdsp hardware. We'll leave this out until a little later. */
return 0;
}
static int hdsp_set_input_monitor_mask (jack_hardware_t *hw, unsigned long mask)
{
int i;

/* For each input channel */
for (i = 0; i < 26; i++) {
/* Monitoring requested for this channel? */
if(mask & (1<<i)) {
/* Yes. Connect physical input to output */
if(hdsp_set_mixer_gain (hw, hdsp_physical_input_index[i],
hdsp_physical_output_index[i],
HDSP_UNITY_GAIN) != 0) {
return -1;
}
/* ...and disconnect the corresponding software */
/* channel */
if(hdsp_set_mixer_gain (hw, hdsp_audio_stream_index[i],
hdsp_physical_output_index[i],
HDSP_MINUS_INFINITY_GAIN) != 0) {
return -1;
}
} else {
/* No. Disconnect physical input from output */
if(hdsp_set_mixer_gain (hw, hdsp_physical_input_index[i],
hdsp_physical_output_index[i],
HDSP_MINUS_INFINITY_GAIN) != 0) {
return -1;
}
/* ...and connect the corresponding software */
/* channel */
if(hdsp_set_mixer_gain (hw, hdsp_audio_stream_index[i],
hdsp_physical_output_index[i],
HDSP_UNITY_GAIN) != 0) {
return -1;
}
}
}
/* Cache the monitor mask */
hw->input_monitor_mask = mask;
return 0;
}


static int hdsp_change_sample_clock (jack_hardware_t *hw, SampleClockMode mode)
{
// Empty for now, until Dave understands more about clock sync so
// he can test.
return -1;
}

void
jack_alsa_hdsp_release (jack_hardware_t *hw)

{
hdsp_t *h = (hdsp_t *) hw->private;

if (h != 0) {
free (h);
}
}

/* Mostly copied directly from hammerfall.c */
jack_hardware_t *
jack_alsa_hdsp_hw_new (alsa_driver_t *driver)

{
jack_hardware_t *hw;
hdsp_t *h;

hw = (jack_hardware_t *) malloc (sizeof (jack_hardware_t));

/* Not using clock lock-sync-whatever in home hardware setup */
/* yet. Will write this code when can test it. */
/* hw->capabilities = Cap_HardwareMonitoring|Cap_AutoSync|Cap_WordClock|Cap_ClockMaster|Cap_ClockLockReporting; */
hw->capabilities = Cap_HardwareMonitoring;
hw->input_monitor_mask = 0;
hw->private = 0;

hw->set_input_monitor_mask = hdsp_set_input_monitor_mask;
hw->change_sample_clock = hdsp_change_sample_clock;
hw->release = jack_alsa_hdsp_release;

h = (hdsp_t *) malloc (sizeof (hdsp_t));
h->driver = driver;
hw->private = h;

return hw;
}

+ 33
- 0
jack/hdsp.h View File

@@ -0,0 +1,33 @@
/*
Copyright (C) 2001 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

$Id$
*/

#ifndef __jack_hdsp_h__
#define __jack_hdsp_h__

#include <sys/time.h>

typedef struct {
alsa_driver_t *driver;
} hdsp_t;

jack_hardware_t *
jack_alsa_hdsp_hw_new (alsa_driver_t *driver);

#endif /* __jack_hdsp_h__*/

Loading…
Cancel
Save