1 /* 2 * oxfw_pcm.c - a part of driver for OXFW970/971 based devices 3 * 4 * Copyright (c) Clemens Ladisch <clemens@ladisch.de> 5 * Licensed under the terms of the GNU General Public License, version 2. 6 */ 7 8 #include "oxfw.h" 9 10 static int firewave_rate_constraint(struct snd_pcm_hw_params *params, 11 struct snd_pcm_hw_rule *rule) 12 { 13 static unsigned int stereo_rates[] = { 48000, 96000 }; 14 struct snd_interval *channels = 15 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); 16 struct snd_interval *rate = 17 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); 18 19 /* two channels work only at 48/96 kHz */ 20 if (snd_interval_max(channels) < 6) 21 return snd_interval_list(rate, 2, stereo_rates, 0); 22 return 0; 23 } 24 25 static int firewave_channels_constraint(struct snd_pcm_hw_params *params, 26 struct snd_pcm_hw_rule *rule) 27 { 28 static const struct snd_interval all_channels = { .min = 6, .max = 6 }; 29 struct snd_interval *rate = 30 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); 31 struct snd_interval *channels = 32 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); 33 34 /* 32/44.1 kHz work only with all six channels */ 35 if (snd_interval_max(rate) < 48000) 36 return snd_interval_refine(channels, &all_channels); 37 return 0; 38 } 39 40 int firewave_constraints(struct snd_pcm_runtime *runtime) 41 { 42 static unsigned int channels_list[] = { 2, 6 }; 43 static struct snd_pcm_hw_constraint_list channels_list_constraint = { 44 .count = 2, 45 .list = channels_list, 46 }; 47 int err; 48 49 runtime->hw.rates = SNDRV_PCM_RATE_32000 | 50 SNDRV_PCM_RATE_44100 | 51 SNDRV_PCM_RATE_48000 | 52 SNDRV_PCM_RATE_96000; 53 runtime->hw.channels_max = 6; 54 55 err = snd_pcm_hw_constraint_list(runtime, 0, 56 SNDRV_PCM_HW_PARAM_CHANNELS, 57 &channels_list_constraint); 58 if (err < 0) 59 return err; 60 err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, 61 firewave_rate_constraint, NULL, 62 SNDRV_PCM_HW_PARAM_CHANNELS, -1); 63 if (err < 0) 64 return err; 65 err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 66 firewave_channels_constraint, NULL, 67 SNDRV_PCM_HW_PARAM_RATE, -1); 68 if (err < 0) 69 return err; 70 71 return 0; 72 } 73 74 int lacie_speakers_constraints(struct snd_pcm_runtime *runtime) 75 { 76 runtime->hw.rates = SNDRV_PCM_RATE_32000 | 77 SNDRV_PCM_RATE_44100 | 78 SNDRV_PCM_RATE_48000 | 79 SNDRV_PCM_RATE_88200 | 80 SNDRV_PCM_RATE_96000; 81 82 return 0; 83 } 84 85 static int pcm_open(struct snd_pcm_substream *substream) 86 { 87 static const struct snd_pcm_hardware hardware = { 88 .info = SNDRV_PCM_INFO_MMAP | 89 SNDRV_PCM_INFO_MMAP_VALID | 90 SNDRV_PCM_INFO_BATCH | 91 SNDRV_PCM_INFO_INTERLEAVED | 92 SNDRV_PCM_INFO_BLOCK_TRANSFER, 93 .formats = AMDTP_OUT_PCM_FORMAT_BITS, 94 .channels_min = 2, 95 .channels_max = 2, 96 .buffer_bytes_max = 4 * 1024 * 1024, 97 .period_bytes_min = 1, 98 .period_bytes_max = UINT_MAX, 99 .periods_min = 1, 100 .periods_max = UINT_MAX, 101 }; 102 struct snd_oxfw *oxfw = substream->private_data; 103 struct snd_pcm_runtime *runtime = substream->runtime; 104 bool used; 105 int err; 106 107 err = cmp_connection_check_used(&oxfw->in_conn, &used); 108 if ((err < 0) || used) 109 goto end; 110 111 runtime->hw = hardware; 112 113 err = oxfw->device_info->pcm_constraints(runtime); 114 if (err < 0) 115 goto end; 116 err = snd_pcm_limit_hw_rates(runtime); 117 if (err < 0) 118 goto end; 119 120 err = amdtp_stream_add_pcm_hw_constraints(&oxfw->rx_stream, runtime); 121 end: 122 return err; 123 } 124 125 static int pcm_close(struct snd_pcm_substream *substream) 126 { 127 return 0; 128 } 129 130 static int pcm_hw_params(struct snd_pcm_substream *substream, 131 struct snd_pcm_hw_params *hw_params) 132 { 133 struct snd_oxfw *oxfw = substream->private_data; 134 int err; 135 136 mutex_lock(&oxfw->mutex); 137 138 snd_oxfw_stream_stop_simplex(oxfw); 139 140 err = snd_pcm_lib_alloc_vmalloc_buffer(substream, 141 params_buffer_bytes(hw_params)); 142 if (err < 0) 143 goto error; 144 145 amdtp_stream_set_parameters(&oxfw->rx_stream, 146 params_rate(hw_params), 147 params_channels(hw_params), 148 0); 149 150 amdtp_stream_set_pcm_format(&oxfw->rx_stream, 151 params_format(hw_params)); 152 153 err = avc_general_set_sig_fmt(oxfw->unit, params_rate(hw_params), 154 AVC_GENERAL_PLUG_DIR_IN, 0); 155 if (err < 0) { 156 dev_err(&oxfw->unit->device, "failed to set sample rate\n"); 157 goto err_buffer; 158 } 159 160 return 0; 161 162 err_buffer: 163 snd_pcm_lib_free_vmalloc_buffer(substream); 164 error: 165 mutex_unlock(&oxfw->mutex); 166 return err; 167 } 168 169 static int pcm_hw_free(struct snd_pcm_substream *substream) 170 { 171 struct snd_oxfw *oxfw = substream->private_data; 172 173 mutex_lock(&oxfw->mutex); 174 snd_oxfw_stream_stop_simplex(oxfw); 175 mutex_unlock(&oxfw->mutex); 176 177 return snd_pcm_lib_free_vmalloc_buffer(substream); 178 } 179 180 static int pcm_prepare(struct snd_pcm_substream *substream) 181 { 182 struct snd_oxfw *oxfw = substream->private_data; 183 int err; 184 185 mutex_lock(&oxfw->mutex); 186 187 snd_oxfw_stream_stop_simplex(oxfw); 188 189 err = snd_oxfw_stream_start_simplex(oxfw); 190 if (err < 0) 191 goto end; 192 193 amdtp_stream_pcm_prepare(&oxfw->rx_stream); 194 end: 195 mutex_unlock(&oxfw->mutex); 196 return err; 197 } 198 199 static int pcm_trigger(struct snd_pcm_substream *substream, int cmd) 200 { 201 struct snd_oxfw *oxfw = substream->private_data; 202 struct snd_pcm_substream *pcm; 203 204 switch (cmd) { 205 case SNDRV_PCM_TRIGGER_START: 206 pcm = substream; 207 break; 208 case SNDRV_PCM_TRIGGER_STOP: 209 pcm = NULL; 210 break; 211 default: 212 return -EINVAL; 213 } 214 amdtp_stream_pcm_trigger(&oxfw->rx_stream, pcm); 215 return 0; 216 } 217 218 static snd_pcm_uframes_t pcm_pointer(struct snd_pcm_substream *substream) 219 { 220 struct snd_oxfw *oxfw = substream->private_data; 221 222 return amdtp_stream_pcm_pointer(&oxfw->rx_stream); 223 } 224 225 int snd_oxfw_create_pcm(struct snd_oxfw *oxfw) 226 { 227 static struct snd_pcm_ops ops = { 228 .open = pcm_open, 229 .close = pcm_close, 230 .ioctl = snd_pcm_lib_ioctl, 231 .hw_params = pcm_hw_params, 232 .hw_free = pcm_hw_free, 233 .prepare = pcm_prepare, 234 .trigger = pcm_trigger, 235 .pointer = pcm_pointer, 236 .page = snd_pcm_lib_get_vmalloc_page, 237 .mmap = snd_pcm_lib_mmap_vmalloc, 238 }; 239 struct snd_pcm *pcm; 240 int err; 241 242 err = snd_pcm_new(oxfw->card, oxfw->card->driver, 0, 1, 0, &pcm); 243 if (err < 0) 244 return err; 245 pcm->private_data = oxfw; 246 strcpy(pcm->name, oxfw->card->shortname); 247 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &ops); 248 return 0; 249 } 250