1 /* 2 * dice_pcm.c - a part of driver for DICE based devices 3 * 4 * Copyright (c) Clemens Ladisch <clemens@ladisch.de> 5 * Copyright (c) 2014 Takashi Sakamoto <o-takashi@sakamocchi.jp> 6 * 7 * Licensed under the terms of the GNU General Public License, version 2. 8 */ 9 10 #include "dice.h" 11 12 static int dice_rate_constraint(struct snd_pcm_hw_params *params, 13 struct snd_pcm_hw_rule *rule) 14 { 15 struct snd_dice *dice = rule->private; 16 17 const struct snd_interval *c = 18 hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_CHANNELS); 19 struct snd_interval *r = 20 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); 21 struct snd_interval rates = { 22 .min = UINT_MAX, .max = 0, .integer = 1 23 }; 24 unsigned int i, rate, mode, *pcm_channels = dice->rx_channels; 25 26 for (i = 0; i < ARRAY_SIZE(snd_dice_rates); ++i) { 27 rate = snd_dice_rates[i]; 28 if (snd_dice_stream_get_rate_mode(dice, rate, &mode) < 0) 29 continue; 30 31 if (!snd_interval_test(c, pcm_channels[mode])) 32 continue; 33 34 rates.min = min(rates.min, rate); 35 rates.max = max(rates.max, rate); 36 } 37 38 return snd_interval_refine(r, &rates); 39 } 40 41 static int dice_channels_constraint(struct snd_pcm_hw_params *params, 42 struct snd_pcm_hw_rule *rule) 43 { 44 struct snd_dice *dice = rule->private; 45 46 const struct snd_interval *r = 47 hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE); 48 struct snd_interval *c = 49 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); 50 struct snd_interval channels = { 51 .min = UINT_MAX, .max = 0, .integer = 1 52 }; 53 unsigned int i, rate, mode, *pcm_channels = dice->rx_channels; 54 55 for (i = 0; i < ARRAY_SIZE(snd_dice_rates); ++i) { 56 rate = snd_dice_rates[i]; 57 if (snd_dice_stream_get_rate_mode(dice, rate, &mode) < 0) 58 continue; 59 60 if (!snd_interval_test(r, rate)) 61 continue; 62 63 channels.min = min(channels.min, pcm_channels[mode]); 64 channels.max = max(channels.max, pcm_channels[mode]); 65 } 66 67 return snd_interval_refine(c, &channels); 68 } 69 70 static void limit_channels_and_rates(struct snd_dice *dice, 71 struct snd_pcm_runtime *runtime, 72 unsigned int *pcm_channels) 73 { 74 struct snd_pcm_hardware *hw = &runtime->hw; 75 unsigned int i, rate, mode; 76 77 hw->channels_min = UINT_MAX; 78 hw->channels_max = 0; 79 80 for (i = 0; i < ARRAY_SIZE(snd_dice_rates); ++i) { 81 rate = snd_dice_rates[i]; 82 if (snd_dice_stream_get_rate_mode(dice, rate, &mode) < 0) 83 continue; 84 hw->rates |= snd_pcm_rate_to_rate_bit(rate); 85 86 if (pcm_channels[mode] == 0) 87 continue; 88 hw->channels_min = min(hw->channels_min, pcm_channels[mode]); 89 hw->channels_max = max(hw->channels_max, pcm_channels[mode]); 90 } 91 92 snd_pcm_limit_hw_rates(runtime); 93 } 94 95 static void limit_period_and_buffer(struct snd_pcm_hardware *hw) 96 { 97 hw->periods_min = 2; /* SNDRV_PCM_INFO_BATCH */ 98 hw->periods_max = UINT_MAX; 99 100 hw->period_bytes_min = 4 * hw->channels_max; /* byte for a frame */ 101 102 /* Just to prevent from allocating much pages. */ 103 hw->period_bytes_max = hw->period_bytes_min * 2048; 104 hw->buffer_bytes_max = hw->period_bytes_max * hw->periods_min; 105 } 106 107 static int init_hw_info(struct snd_dice *dice, 108 struct snd_pcm_substream *substream) 109 { 110 struct snd_pcm_runtime *runtime = substream->runtime; 111 struct snd_pcm_hardware *hw = &runtime->hw; 112 int err; 113 114 hw->info = SNDRV_PCM_INFO_MMAP | 115 SNDRV_PCM_INFO_MMAP_VALID | 116 SNDRV_PCM_INFO_BATCH | 117 SNDRV_PCM_INFO_INTERLEAVED | 118 SNDRV_PCM_INFO_BLOCK_TRANSFER; 119 hw->formats = AMDTP_OUT_PCM_FORMAT_BITS; 120 121 limit_channels_and_rates(dice, runtime, dice->rx_channels); 122 limit_period_and_buffer(hw); 123 124 err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, 125 dice_rate_constraint, dice, 126 SNDRV_PCM_HW_PARAM_CHANNELS, -1); 127 if (err < 0) 128 goto end; 129 err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 130 dice_channels_constraint, dice, 131 SNDRV_PCM_HW_PARAM_RATE, -1); 132 if (err < 0) 133 goto end; 134 135 err = amdtp_stream_add_pcm_hw_constraints(&dice->rx_stream, runtime); 136 end: 137 return err; 138 } 139 140 static int pcm_open(struct snd_pcm_substream *substream) 141 { 142 struct snd_dice *dice = substream->private_data; 143 int err; 144 145 err = snd_dice_stream_lock_try(dice); 146 if (err < 0) 147 goto end; 148 149 err = init_hw_info(dice, substream); 150 if (err < 0) 151 goto err_locked; 152 end: 153 return err; 154 err_locked: 155 snd_dice_stream_lock_release(dice); 156 return err; 157 } 158 159 static int pcm_close(struct snd_pcm_substream *substream) 160 { 161 struct snd_dice *dice = substream->private_data; 162 163 snd_dice_stream_lock_release(dice); 164 165 return 0; 166 } 167 168 static int playback_hw_params(struct snd_pcm_substream *substream, 169 struct snd_pcm_hw_params *hw_params) 170 { 171 struct snd_dice *dice = substream->private_data; 172 unsigned int mode, rate, channels, i; 173 int err; 174 175 mutex_lock(&dice->mutex); 176 snd_dice_stream_stop(dice); 177 mutex_unlock(&dice->mutex); 178 179 err = snd_pcm_lib_alloc_vmalloc_buffer(substream, 180 params_buffer_bytes(hw_params)); 181 if (err < 0) 182 return err; 183 184 rate = params_rate(hw_params); 185 err = snd_dice_transaction_set_rate(dice, rate); 186 if (err < 0) 187 return err; 188 189 if (snd_dice_stream_get_rate_mode(dice, rate, &mode) < 0) 190 return err; 191 192 /* 193 * At 176.4/192.0 kHz, Dice has a quirk to transfer two PCM frames in 194 * one data block of AMDTP packet. Thus sampling transfer frequency is 195 * a half of PCM sampling frequency, i.e. PCM frames at 192.0 kHz are 196 * transferred on AMDTP packets at 96 kHz. Two successive samples of a 197 * channel are stored consecutively in the packet. This quirk is called 198 * as 'Dual Wire'. 199 * For this quirk, blocking mode is required and PCM buffer size should 200 * be aligned to SYT_INTERVAL. 201 */ 202 channels = params_channels(hw_params); 203 if (mode > 1) { 204 if (channels > AMDTP_MAX_CHANNELS_FOR_PCM / 2) { 205 err = -ENOSYS; 206 return err; 207 } 208 209 rate /= 2; 210 channels *= 2; 211 dice->rx_stream.double_pcm_frames = true; 212 } else { 213 dice->rx_stream.double_pcm_frames = false; 214 } 215 216 amdtp_stream_set_parameters(&dice->rx_stream, rate, channels, 217 dice->rx_midi_ports[mode]); 218 if (mode > 1) { 219 channels /= 2; 220 221 for (i = 0; i < channels; i++) { 222 dice->rx_stream.pcm_positions[i] = i * 2; 223 dice->rx_stream.pcm_positions[i + channels] = i * 2 + 1; 224 } 225 } 226 227 amdtp_stream_set_pcm_format(&dice->rx_stream, 228 params_format(hw_params)); 229 230 return 0; 231 } 232 233 static int playback_hw_free(struct snd_pcm_substream *substream) 234 { 235 struct snd_dice *dice = substream->private_data; 236 237 mutex_lock(&dice->mutex); 238 snd_dice_stream_stop(dice); 239 mutex_unlock(&dice->mutex); 240 241 return snd_pcm_lib_free_vmalloc_buffer(substream); 242 } 243 244 static int playback_prepare(struct snd_pcm_substream *substream) 245 { 246 struct snd_dice *dice = substream->private_data; 247 int err; 248 249 mutex_lock(&dice->mutex); 250 251 if (amdtp_streaming_error(&dice->rx_stream)) 252 snd_dice_stream_stop_packets(dice); 253 254 err = snd_dice_stream_start(dice); 255 if (err < 0) { 256 mutex_unlock(&dice->mutex); 257 return err; 258 } 259 260 mutex_unlock(&dice->mutex); 261 262 amdtp_stream_pcm_prepare(&dice->rx_stream); 263 264 return 0; 265 } 266 267 static int playback_trigger(struct snd_pcm_substream *substream, int cmd) 268 { 269 struct snd_dice *dice = substream->private_data; 270 271 switch (cmd) { 272 case SNDRV_PCM_TRIGGER_START: 273 amdtp_stream_pcm_trigger(&dice->rx_stream, substream); 274 break; 275 case SNDRV_PCM_TRIGGER_STOP: 276 amdtp_stream_pcm_trigger(&dice->rx_stream, NULL); 277 break; 278 default: 279 return -EINVAL; 280 } 281 282 return 0; 283 } 284 285 static snd_pcm_uframes_t playback_pointer(struct snd_pcm_substream *substream) 286 { 287 struct snd_dice *dice = substream->private_data; 288 289 return amdtp_stream_pcm_pointer(&dice->rx_stream); 290 } 291 292 int snd_dice_create_pcm(struct snd_dice *dice) 293 { 294 static struct snd_pcm_ops playback_ops = { 295 .open = pcm_open, 296 .close = pcm_close, 297 .ioctl = snd_pcm_lib_ioctl, 298 .hw_params = playback_hw_params, 299 .hw_free = playback_hw_free, 300 .prepare = playback_prepare, 301 .trigger = playback_trigger, 302 .pointer = playback_pointer, 303 .page = snd_pcm_lib_get_vmalloc_page, 304 .mmap = snd_pcm_lib_mmap_vmalloc, 305 }; 306 struct snd_pcm *pcm; 307 int err; 308 309 err = snd_pcm_new(dice->card, "DICE", 0, 1, 0, &pcm); 310 if (err < 0) 311 return err; 312 pcm->private_data = dice; 313 strcpy(pcm->name, dice->card->shortname); 314 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_ops); 315 316 return 0; 317 } 318