|
@@ -25,244 +25,6 @@ MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
|
|
MODULE_LICENSE("GPL v2");
|
|
MODULE_LICENSE("GPL v2");
|
|
MODULE_ALIAS("snd-firewire-speakers");
|
|
MODULE_ALIAS("snd-firewire-speakers");
|
|
|
|
|
|
-static int firewave_rate_constraint(struct snd_pcm_hw_params *params,
|
|
|
|
- struct snd_pcm_hw_rule *rule)
|
|
|
|
-{
|
|
|
|
- static unsigned int stereo_rates[] = { 48000, 96000 };
|
|
|
|
- struct snd_interval *channels =
|
|
|
|
- hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
|
|
|
|
- struct snd_interval *rate =
|
|
|
|
- hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
|
|
|
|
-
|
|
|
|
- /* two channels work only at 48/96 kHz */
|
|
|
|
- if (snd_interval_max(channels) < 6)
|
|
|
|
- return snd_interval_list(rate, 2, stereo_rates, 0);
|
|
|
|
- return 0;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static int firewave_channels_constraint(struct snd_pcm_hw_params *params,
|
|
|
|
- struct snd_pcm_hw_rule *rule)
|
|
|
|
-{
|
|
|
|
- static const struct snd_interval all_channels = { .min = 6, .max = 6 };
|
|
|
|
- struct snd_interval *rate =
|
|
|
|
- hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
|
|
|
|
- struct snd_interval *channels =
|
|
|
|
- hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
|
|
|
|
-
|
|
|
|
- /* 32/44.1 kHz work only with all six channels */
|
|
|
|
- if (snd_interval_max(rate) < 48000)
|
|
|
|
- return snd_interval_refine(channels, &all_channels);
|
|
|
|
- return 0;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static int firewave_constraints(struct snd_pcm_runtime *runtime)
|
|
|
|
-{
|
|
|
|
- static unsigned int channels_list[] = { 2, 6 };
|
|
|
|
- static struct snd_pcm_hw_constraint_list channels_list_constraint = {
|
|
|
|
- .count = 2,
|
|
|
|
- .list = channels_list,
|
|
|
|
- };
|
|
|
|
- int err;
|
|
|
|
-
|
|
|
|
- runtime->hw.rates = SNDRV_PCM_RATE_32000 |
|
|
|
|
- SNDRV_PCM_RATE_44100 |
|
|
|
|
- SNDRV_PCM_RATE_48000 |
|
|
|
|
- SNDRV_PCM_RATE_96000;
|
|
|
|
- runtime->hw.channels_max = 6;
|
|
|
|
-
|
|
|
|
- err = snd_pcm_hw_constraint_list(runtime, 0,
|
|
|
|
- SNDRV_PCM_HW_PARAM_CHANNELS,
|
|
|
|
- &channels_list_constraint);
|
|
|
|
- if (err < 0)
|
|
|
|
- return err;
|
|
|
|
- err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
|
|
|
|
- firewave_rate_constraint, NULL,
|
|
|
|
- SNDRV_PCM_HW_PARAM_CHANNELS, -1);
|
|
|
|
- if (err < 0)
|
|
|
|
- return err;
|
|
|
|
- err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
|
|
|
|
- firewave_channels_constraint, NULL,
|
|
|
|
- SNDRV_PCM_HW_PARAM_RATE, -1);
|
|
|
|
- if (err < 0)
|
|
|
|
- return err;
|
|
|
|
-
|
|
|
|
- return 0;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static int lacie_speakers_constraints(struct snd_pcm_runtime *runtime)
|
|
|
|
-{
|
|
|
|
- runtime->hw.rates = SNDRV_PCM_RATE_32000 |
|
|
|
|
- SNDRV_PCM_RATE_44100 |
|
|
|
|
- SNDRV_PCM_RATE_48000 |
|
|
|
|
- SNDRV_PCM_RATE_88200 |
|
|
|
|
- SNDRV_PCM_RATE_96000;
|
|
|
|
-
|
|
|
|
- return 0;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static int oxfw_open(struct snd_pcm_substream *substream)
|
|
|
|
-{
|
|
|
|
- static const struct snd_pcm_hardware hardware = {
|
|
|
|
- .info = SNDRV_PCM_INFO_MMAP |
|
|
|
|
- SNDRV_PCM_INFO_MMAP_VALID |
|
|
|
|
- SNDRV_PCM_INFO_BATCH |
|
|
|
|
- SNDRV_PCM_INFO_INTERLEAVED |
|
|
|
|
- SNDRV_PCM_INFO_BLOCK_TRANSFER,
|
|
|
|
- .formats = AMDTP_OUT_PCM_FORMAT_BITS,
|
|
|
|
- .channels_min = 2,
|
|
|
|
- .channels_max = 2,
|
|
|
|
- .buffer_bytes_max = 4 * 1024 * 1024,
|
|
|
|
- .period_bytes_min = 1,
|
|
|
|
- .period_bytes_max = UINT_MAX,
|
|
|
|
- .periods_min = 1,
|
|
|
|
- .periods_max = UINT_MAX,
|
|
|
|
- };
|
|
|
|
- struct snd_oxfw *oxfw = substream->private_data;
|
|
|
|
- struct snd_pcm_runtime *runtime = substream->runtime;
|
|
|
|
- int err;
|
|
|
|
-
|
|
|
|
- runtime->hw = hardware;
|
|
|
|
-
|
|
|
|
- err = oxfw->device_info->pcm_constraints(runtime);
|
|
|
|
- if (err < 0)
|
|
|
|
- return err;
|
|
|
|
- err = snd_pcm_limit_hw_rates(runtime);
|
|
|
|
- if (err < 0)
|
|
|
|
- return err;
|
|
|
|
-
|
|
|
|
- err = amdtp_stream_add_pcm_hw_constraints(&oxfw->rx_stream, runtime);
|
|
|
|
- if (err < 0)
|
|
|
|
- return err;
|
|
|
|
-
|
|
|
|
- return 0;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static int oxfw_close(struct snd_pcm_substream *substream)
|
|
|
|
-{
|
|
|
|
- return 0;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static int oxfw_hw_params(struct snd_pcm_substream *substream,
|
|
|
|
- struct snd_pcm_hw_params *hw_params)
|
|
|
|
-{
|
|
|
|
- struct snd_oxfw *oxfw = substream->private_data;
|
|
|
|
- int err;
|
|
|
|
-
|
|
|
|
- mutex_lock(&oxfw->mutex);
|
|
|
|
-
|
|
|
|
- snd_oxfw_stream_stop_simplex(oxfw);
|
|
|
|
-
|
|
|
|
- err = snd_pcm_lib_alloc_vmalloc_buffer(substream,
|
|
|
|
- params_buffer_bytes(hw_params));
|
|
|
|
- if (err < 0)
|
|
|
|
- goto error;
|
|
|
|
-
|
|
|
|
- amdtp_stream_set_parameters(&oxfw->rx_stream,
|
|
|
|
- params_rate(hw_params),
|
|
|
|
- params_channels(hw_params),
|
|
|
|
- 0);
|
|
|
|
-
|
|
|
|
- amdtp_stream_set_pcm_format(&oxfw->rx_stream,
|
|
|
|
- params_format(hw_params));
|
|
|
|
-
|
|
|
|
- err = avc_general_set_sig_fmt(oxfw->unit, params_rate(hw_params),
|
|
|
|
- AVC_GENERAL_PLUG_DIR_IN, 0);
|
|
|
|
- if (err < 0) {
|
|
|
|
- dev_err(&oxfw->unit->device, "failed to set sample rate\n");
|
|
|
|
- goto err_buffer;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return 0;
|
|
|
|
-
|
|
|
|
-err_buffer:
|
|
|
|
- snd_pcm_lib_free_vmalloc_buffer(substream);
|
|
|
|
-error:
|
|
|
|
- mutex_unlock(&oxfw->mutex);
|
|
|
|
- return err;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static int oxfw_hw_free(struct snd_pcm_substream *substream)
|
|
|
|
-{
|
|
|
|
- struct snd_oxfw *oxfw = substream->private_data;
|
|
|
|
-
|
|
|
|
- mutex_lock(&oxfw->mutex);
|
|
|
|
- snd_oxfw_stream_stop_simplex(oxfw);
|
|
|
|
- mutex_unlock(&oxfw->mutex);
|
|
|
|
-
|
|
|
|
- return snd_pcm_lib_free_vmalloc_buffer(substream);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static int oxfw_prepare(struct snd_pcm_substream *substream)
|
|
|
|
-{
|
|
|
|
- struct snd_oxfw *oxfw = substream->private_data;
|
|
|
|
- int err;
|
|
|
|
-
|
|
|
|
- mutex_lock(&oxfw->mutex);
|
|
|
|
-
|
|
|
|
- snd_oxfw_stream_stop_simplex(oxfw);
|
|
|
|
-
|
|
|
|
- err = snd_oxfw_stream_start_simplex(oxfw);
|
|
|
|
- if (err < 0)
|
|
|
|
- goto end;
|
|
|
|
-
|
|
|
|
- amdtp_stream_pcm_prepare(&oxfw->rx_stream);
|
|
|
|
-end:
|
|
|
|
- mutex_unlock(&oxfw->mutex);
|
|
|
|
- return err;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static int oxfw_trigger(struct snd_pcm_substream *substream, int cmd)
|
|
|
|
-{
|
|
|
|
- struct snd_oxfw *oxfw = substream->private_data;
|
|
|
|
- struct snd_pcm_substream *pcm;
|
|
|
|
-
|
|
|
|
- switch (cmd) {
|
|
|
|
- case SNDRV_PCM_TRIGGER_START:
|
|
|
|
- pcm = substream;
|
|
|
|
- break;
|
|
|
|
- case SNDRV_PCM_TRIGGER_STOP:
|
|
|
|
- pcm = NULL;
|
|
|
|
- break;
|
|
|
|
- default:
|
|
|
|
- return -EINVAL;
|
|
|
|
- }
|
|
|
|
- amdtp_stream_pcm_trigger(&oxfw->rx_stream, pcm);
|
|
|
|
- return 0;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static snd_pcm_uframes_t oxfw_pointer(struct snd_pcm_substream *substream)
|
|
|
|
-{
|
|
|
|
- struct snd_oxfw *oxfw = substream->private_data;
|
|
|
|
-
|
|
|
|
- return amdtp_stream_pcm_pointer(&oxfw->rx_stream);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static int oxfw_create_pcm(struct snd_oxfw *oxfw)
|
|
|
|
-{
|
|
|
|
- static struct snd_pcm_ops ops = {
|
|
|
|
- .open = oxfw_open,
|
|
|
|
- .close = oxfw_close,
|
|
|
|
- .ioctl = snd_pcm_lib_ioctl,
|
|
|
|
- .hw_params = oxfw_hw_params,
|
|
|
|
- .hw_free = oxfw_hw_free,
|
|
|
|
- .prepare = oxfw_prepare,
|
|
|
|
- .trigger = oxfw_trigger,
|
|
|
|
- .pointer = oxfw_pointer,
|
|
|
|
- .page = snd_pcm_lib_get_vmalloc_page,
|
|
|
|
- .mmap = snd_pcm_lib_mmap_vmalloc,
|
|
|
|
- };
|
|
|
|
- struct snd_pcm *pcm;
|
|
|
|
- int err;
|
|
|
|
-
|
|
|
|
- err = snd_pcm_new(oxfw->card, "OXFW", 0, 1, 0, &pcm);
|
|
|
|
- if (err < 0)
|
|
|
|
- return err;
|
|
|
|
- pcm->private_data = oxfw;
|
|
|
|
- strcpy(pcm->name, oxfw->device_info->short_name);
|
|
|
|
- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &ops);
|
|
|
|
- return 0;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
enum control_action { CTL_READ, CTL_WRITE };
|
|
enum control_action { CTL_READ, CTL_WRITE };
|
|
enum control_attribute {
|
|
enum control_attribute {
|
|
CTL_MIN = 0x02,
|
|
CTL_MIN = 0x02,
|
|
@@ -587,7 +349,7 @@ static int oxfw_probe(struct fw_unit *unit,
|
|
dev_name(&unit->device), 100 << fw_dev->max_speed);
|
|
dev_name(&unit->device), 100 << fw_dev->max_speed);
|
|
strcpy(card->mixername, "OXFW");
|
|
strcpy(card->mixername, "OXFW");
|
|
|
|
|
|
- err = oxfw_create_pcm(oxfw);
|
|
|
|
|
|
+ err = snd_oxfw_create_pcm(oxfw);
|
|
if (err < 0)
|
|
if (err < 0)
|
|
goto error;
|
|
goto error;
|
|
|
|
|