~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
JACK/drivers/alsa/hdsp.c


** Warning: Cannot open xref database.

1 /* 2 Copyright (C) 2001 Paul Davis 3 Copyright (C) 2002 Dave LaRose 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 2 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program; if not, write to the Free Software 17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 19 $Id: hdsp.c,v 1.5 2003/08/29 00:06:30 trutkin Exp $ 20 */ 21 22 #include <jack/hardware.h> 23 #include "alsa_driver.h" 24 #include "hdsp.h" 25 #include <jack/internal.h> 26 27 /* Constants to make working with the hdsp matrix mixer easier */ 28 static const int HDSP_MINUS_INFINITY_GAIN = 0; 29 static const int HDSP_UNITY_GAIN = 32768; 30 static const int HDSP_MAX_GAIN = 65535; 31 32 /* 33 * Use these two arrays to choose the value of the input_channel 34 * argument to hsdp_set_mixer_gain(). hdsp_physical_input_index[n] 35 * selects the nth optical/analog input. audio_stream_index[n] 36 * selects the nth channel being received from the host via pci/pccard. 37 */ 38 static const int hdsp_num_input_channels = 52; 39 static const int hdsp_physical_input_index[] = { 40 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 41 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25}; 42 static const int hdsp_audio_stream_index[] = { 43 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 44 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51}; 45 46 /* 47 * Use this array to choose the value of the output_channel 48 * argument to hsdp_set_mixer_gain(). hdsp_physical_output_index[26] 49 * and hdsp_physical_output_index[27] refer to the two "line out" 50 * channels (1/4" phone jack on the front of digiface/multiface). 51 */ 52 static const int hdsp_num_output_channels = 28; 53 static const int hdsp_physical_output_index[] = { 54 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 55 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}; 56 57 58 /* Function for checking argument values */ 59 static int clamp_int(int value, int lower_bound, int upper_bound) 60 { 61 if(value < lower_bound) { 62 return lower_bound; 63 } 64 if(value > upper_bound) { 65 return upper_bound; 66 } 67 return value; 68 } 69 70 /* Note(XXX): Maybe should share this code with hammerfall.c? */ 71 static void 72 set_control_id (snd_ctl_elem_id_t *ctl, const char *name) 73 { 74 snd_ctl_elem_id_set_name (ctl, name); 75 snd_ctl_elem_id_set_numid (ctl, 0); 76 snd_ctl_elem_id_set_interface (ctl, SND_CTL_ELEM_IFACE_HWDEP); 77 snd_ctl_elem_id_set_device (ctl, 0); 78 snd_ctl_elem_id_set_subdevice (ctl, 0); 79 snd_ctl_elem_id_set_index (ctl, 0); 80 } 81 82 /* The hdsp matrix mixer lets you connect pretty much any input to */ 83 /* any output with gain from -inf to about +2dB. Pretty slick. */ 84 /* This routine makes a convenient way to set the gain from */ 85 /* input_channel to output_channel (see hdsp_physical_input_index */ 86 /* etc. above. */ 87 /* gain is an int from 0 to 65535, with 0 being -inf gain, and */ 88 /* 65535 being about +2dB. */ 89 90 static int hdsp_set_mixer_gain(jack_hardware_t *hw, int input_channel, 91 int output_channel, int gain) 92 { 93 hdsp_t *h = (hdsp_t *) hw->private; 94 snd_ctl_elem_value_t *ctl; 95 snd_ctl_elem_id_t *ctl_id; 96 int err; 97 98 /* Check args */ 99 input_channel = clamp_int(input_channel, 0, hdsp_num_input_channels); 100 output_channel = clamp_int(output_channel, 0, hdsp_num_output_channels); 101 gain = clamp_int(gain, HDSP_MINUS_INFINITY_GAIN, HDSP_MAX_GAIN); 102 103 /* Allocate control element and select "Mixer" control */ 104 snd_ctl_elem_value_alloca (&ctl); 105 snd_ctl_elem_id_alloca (&ctl_id); 106 set_control_id (ctl_id, "Mixer"); 107 snd_ctl_elem_value_set_id (ctl, ctl_id); 108 109 /* Apparently non-standard and unstable interface for the */ 110 /* mixer control. */ 111 snd_ctl_elem_value_set_integer (ctl, 0, input_channel); 112 snd_ctl_elem_value_set_integer (ctl, 1, output_channel); 113 snd_ctl_elem_value_set_integer (ctl, 2, gain); 114 115 /* Commit the mixer value and check for errors */ 116 if ((err = snd_ctl_elem_write (h->driver->ctl_handle, ctl)) != 0) { 117 jack_error ("ALSA/HDSP: cannot set mixer gain (%s)", snd_strerror (err)); 118 return -1; 119 } 120 121 /* Note (XXX): Perhaps we should maintain a cache of the current */ 122 /* mixer values, since it's not clear how to query them from the */ 123 /* hdsp hardware. We'll leave this out until a little later. */ 124 return 0; 125 } 126 127 static int hdsp_set_input_monitor_mask (jack_hardware_t *hw, unsigned long mask) 128 { 129 int i; 130 131 /* For each input channel */ 132 for (i = 0; i < 26; i++) { 133 /* Monitoring requested for this channel? */ 134 if(mask & (1<<i)) { 135 /* Yes. Connect physical input to output */ 136 137 if(hdsp_set_mixer_gain (hw, hdsp_physical_input_index[i], 138 hdsp_physical_output_index[i], 139 HDSP_UNITY_GAIN) != 0) { 140 return -1; 141 } 142 143 #ifdef CANNOT_HEAR_SOFTWARE_STREAM_WHEN_MONITORING 144 /* ...and disconnect the corresponding software */ 145 /* channel */ 146 if(hdsp_set_mixer_gain (hw, hdsp_audio_stream_index[i], 147 hdsp_physical_output_index[i], 148 HDSP_MINUS_INFINITY_GAIN) != 0) { 149 return -1; 150 } 151 #endif 152 153 } else { 154 /* No. Disconnect physical input from output */ 155 if(hdsp_set_mixer_gain (hw, hdsp_physical_input_index[i], 156 hdsp_physical_output_index[i], 157 HDSP_MINUS_INFINITY_GAIN) != 0) { 158 return -1; 159 } 160 161 #ifdef CANNOT_HEAR_SOFTWARE_STREAM_WHEN_MONITORING 162 /* ...and connect the corresponding software */ 163 /* channel */ 164 if(hdsp_set_mixer_gain (hw, hdsp_audio_stream_index[i], 165 hdsp_physical_output_index[i], 166 HDSP_UNITY_GAIN) != 0) { 167 return -1; 168 } 169 #endif 170 } 171 } 172 /* Cache the monitor mask */ 173 hw->input_monitor_mask = mask; 174 return 0; 175 } 176 177 178 static int hdsp_change_sample_clock (jack_hardware_t *hw, SampleClockMode mode) 179 { 180 // Empty for now, until Dave understands more about clock sync so 181 // he can test. 182 return -1; 183 } 184 185 static double hdsp_get_hardware_peak (jack_port_t *port, jack_nframes_t frame) 186 { 187 return 0; 188 } 189 190 static double hdsp_get_hardware_power (jack_port_t *port, jack_nframes_t frame) 191 { 192 return 0; 193 } 194 195 void 196 jack_alsa_hdsp_release (jack_hardware_t *hw) 197 198 { 199 hdsp_t *h = (hdsp_t *) hw->private; 200 201 if (h != 0) { 202 free (h); 203 } 204 } 205 206 /* Mostly copied directly from hammerfall.c */ 207 jack_hardware_t * 208 jack_alsa_hdsp_hw_new (alsa_driver_t *driver) 209 210 { 211 jack_hardware_t *hw; 212 hdsp_t *h; 213 214 hw = (jack_hardware_t *) malloc (sizeof (jack_hardware_t)); 215 216 /* Not using clock lock-sync-whatever in home hardware setup */ 217 /* yet. Will write this code when can test it. */ 218 /* hw->capabilities = Cap_HardwareMonitoring|Cap_AutoSync|Cap_WordClock|Cap_ClockMaster|Cap_ClockLockReporting; */ 219 hw->capabilities = Cap_HardwareMonitoring | Cap_HardwareMetering; 220 hw->input_monitor_mask = 0; 221 hw->private = 0; 222 223 hw->set_input_monitor_mask = hdsp_set_input_monitor_mask; 224 hw->change_sample_clock = hdsp_change_sample_clock; 225 hw->release = jack_alsa_hdsp_release; 226 hw->get_hardware_peak = hdsp_get_hardware_peak; 227 hw->get_hardware_power = hdsp_get_hardware_power; 228 229 h = (hdsp_t *) malloc (sizeof (hdsp_t)); 230 h->driver = driver; 231 hw->private = h; 232 233 return hw; 234 } 235

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.