2 * ff-pcm.c - a part of driver for RME Fireface series
4 * Copyright (c) 2015-2017 Takashi Sakamoto
6 * Licensed under the terms of the GNU General Public License, version 2.
11 static inline unsigned int get_multiplier_mode_with_index(unsigned int index
)
13 return ((int)index
- 1) / 2;
16 static int hw_rule_rate(struct snd_pcm_hw_params
*params
,
17 struct snd_pcm_hw_rule
*rule
)
19 const unsigned int *pcm_channels
= rule
->private;
20 struct snd_interval
*r
=
21 hw_param_interval(params
, SNDRV_PCM_HW_PARAM_RATE
);
22 const struct snd_interval
*c
=
23 hw_param_interval_c(params
, SNDRV_PCM_HW_PARAM_CHANNELS
);
24 struct snd_interval t
= {
25 .min
= UINT_MAX
, .max
= 0, .integer
= 1
29 for (i
= 0; i
< ARRAY_SIZE(amdtp_rate_table
); i
++) {
30 mode
= get_multiplier_mode_with_index(i
);
31 if (!snd_interval_test(c
, pcm_channels
[mode
]))
34 t
.min
= min(t
.min
, amdtp_rate_table
[i
]);
35 t
.max
= max(t
.max
, amdtp_rate_table
[i
]);
38 return snd_interval_refine(r
, &t
);
41 static int hw_rule_channels(struct snd_pcm_hw_params
*params
,
42 struct snd_pcm_hw_rule
*rule
)
44 const unsigned int *pcm_channels
= rule
->private;
45 struct snd_interval
*c
=
46 hw_param_interval(params
, SNDRV_PCM_HW_PARAM_CHANNELS
);
47 const struct snd_interval
*r
=
48 hw_param_interval_c(params
, SNDRV_PCM_HW_PARAM_RATE
);
49 struct snd_interval t
= {
50 .min
= UINT_MAX
, .max
= 0, .integer
= 1
54 for (i
= 0; i
< ARRAY_SIZE(amdtp_rate_table
); i
++) {
55 mode
= get_multiplier_mode_with_index(i
);
56 if (!snd_interval_test(r
, amdtp_rate_table
[i
]))
59 t
.min
= min(t
.min
, pcm_channels
[mode
]);
60 t
.max
= max(t
.max
, pcm_channels
[mode
]);
63 return snd_interval_refine(c
, &t
);
66 static void limit_channels_and_rates(struct snd_pcm_hardware
*hw
,
67 const unsigned int *pcm_channels
)
70 unsigned int rate
, channels
;
73 hw
->channels_min
= UINT_MAX
;
75 hw
->rate_min
= UINT_MAX
;
78 for (i
= 0; i
< ARRAY_SIZE(amdtp_rate_table
); i
++) {
79 mode
= get_multiplier_mode_with_index(i
);
81 channels
= pcm_channels
[mode
];
82 if (pcm_channels
[mode
] == 0)
84 hw
->channels_min
= min(hw
->channels_min
, channels
);
85 hw
->channels_max
= max(hw
->channels_max
, channels
);
87 rate
= amdtp_rate_table
[i
];
88 hw
->rates
|= snd_pcm_rate_to_rate_bit(rate
);
89 hw
->rate_min
= min(hw
->rate_min
, rate
);
90 hw
->rate_max
= max(hw
->rate_max
, rate
);
94 static int pcm_init_hw_params(struct snd_ff
*ff
,
95 struct snd_pcm_substream
*substream
)
97 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
98 struct amdtp_stream
*s
;
99 const unsigned int *pcm_channels
;
102 if (substream
->stream
== SNDRV_PCM_STREAM_CAPTURE
) {
103 runtime
->hw
.formats
= SNDRV_PCM_FMTBIT_S32
;
105 pcm_channels
= ff
->spec
->pcm_capture_channels
;
107 runtime
->hw
.formats
= SNDRV_PCM_FMTBIT_S32
;
109 pcm_channels
= ff
->spec
->pcm_playback_channels
;
112 limit_channels_and_rates(&runtime
->hw
, pcm_channels
);
114 err
= snd_pcm_hw_rule_add(runtime
, 0, SNDRV_PCM_HW_PARAM_CHANNELS
,
115 hw_rule_channels
, (void *)pcm_channels
,
116 SNDRV_PCM_HW_PARAM_RATE
, -1);
120 err
= snd_pcm_hw_rule_add(runtime
, 0, SNDRV_PCM_HW_PARAM_RATE
,
121 hw_rule_rate
, (void *)pcm_channels
,
122 SNDRV_PCM_HW_PARAM_CHANNELS
, -1);
126 return amdtp_ff_add_pcm_hw_constraints(s
, runtime
);
129 static int pcm_open(struct snd_pcm_substream
*substream
)
131 struct snd_ff
*ff
= substream
->private_data
;
133 enum snd_ff_clock_src src
;
136 err
= snd_ff_stream_lock_try(ff
);
140 err
= pcm_init_hw_params(ff
, substream
);
144 err
= ff
->spec
->protocol
->get_clock(ff
, &rate
, &src
);
148 if (src
!= SND_FF_CLOCK_SRC_INTERNAL
) {
149 for (i
= 0; i
< CIP_SFC_COUNT
; ++i
) {
150 if (amdtp_rate_table
[i
] == rate
)
154 * The unit is configured at sampling frequency which packet
155 * streaming engine can't support.
157 if (i
>= CIP_SFC_COUNT
) {
162 substream
->runtime
->hw
.rate_min
= rate
;
163 substream
->runtime
->hw
.rate_max
= rate
;
165 if (amdtp_stream_pcm_running(&ff
->rx_stream
) ||
166 amdtp_stream_pcm_running(&ff
->tx_stream
)) {
167 rate
= amdtp_rate_table
[ff
->rx_stream
.sfc
];
168 substream
->runtime
->hw
.rate_min
= rate
;
169 substream
->runtime
->hw
.rate_max
= rate
;
173 snd_pcm_set_sync(substream
);
178 snd_ff_stream_lock_release(ff
);
182 static int pcm_close(struct snd_pcm_substream
*substream
)
184 struct snd_ff
*ff
= substream
->private_data
;
186 snd_ff_stream_lock_release(ff
);
191 static int pcm_capture_hw_params(struct snd_pcm_substream
*substream
,
192 struct snd_pcm_hw_params
*hw_params
)
194 struct snd_ff
*ff
= substream
->private_data
;
197 err
= snd_pcm_lib_alloc_vmalloc_buffer(substream
,
198 params_buffer_bytes(hw_params
));
202 if (substream
->runtime
->status
->state
== SNDRV_PCM_STATE_OPEN
) {
203 mutex_lock(&ff
->mutex
);
204 ff
->substreams_counter
++;
205 mutex_unlock(&ff
->mutex
);
211 static int pcm_playback_hw_params(struct snd_pcm_substream
*substream
,
212 struct snd_pcm_hw_params
*hw_params
)
214 struct snd_ff
*ff
= substream
->private_data
;
217 err
= snd_pcm_lib_alloc_vmalloc_buffer(substream
,
218 params_buffer_bytes(hw_params
));
222 if (substream
->runtime
->status
->state
== SNDRV_PCM_STATE_OPEN
) {
223 mutex_lock(&ff
->mutex
);
224 ff
->substreams_counter
++;
225 mutex_unlock(&ff
->mutex
);
231 static int pcm_capture_hw_free(struct snd_pcm_substream
*substream
)
233 struct snd_ff
*ff
= substream
->private_data
;
235 mutex_lock(&ff
->mutex
);
237 if (substream
->runtime
->status
->state
!= SNDRV_PCM_STATE_OPEN
)
238 ff
->substreams_counter
--;
240 snd_ff_stream_stop_duplex(ff
);
242 mutex_unlock(&ff
->mutex
);
244 return snd_pcm_lib_free_vmalloc_buffer(substream
);
247 static int pcm_playback_hw_free(struct snd_pcm_substream
*substream
)
249 struct snd_ff
*ff
= substream
->private_data
;
251 mutex_lock(&ff
->mutex
);
253 if (substream
->runtime
->status
->state
!= SNDRV_PCM_STATE_OPEN
)
254 ff
->substreams_counter
--;
256 snd_ff_stream_stop_duplex(ff
);
258 mutex_unlock(&ff
->mutex
);
260 return snd_pcm_lib_free_vmalloc_buffer(substream
);
263 static int pcm_capture_prepare(struct snd_pcm_substream
*substream
)
265 struct snd_ff
*ff
= substream
->private_data
;
266 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
269 mutex_lock(&ff
->mutex
);
271 err
= snd_ff_stream_start_duplex(ff
, runtime
->rate
);
273 amdtp_stream_pcm_prepare(&ff
->tx_stream
);
275 mutex_unlock(&ff
->mutex
);
280 static int pcm_playback_prepare(struct snd_pcm_substream
*substream
)
282 struct snd_ff
*ff
= substream
->private_data
;
283 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
286 mutex_lock(&ff
->mutex
);
288 err
= snd_ff_stream_start_duplex(ff
, runtime
->rate
);
290 amdtp_stream_pcm_prepare(&ff
->rx_stream
);
292 mutex_unlock(&ff
->mutex
);
297 static int pcm_capture_trigger(struct snd_pcm_substream
*substream
, int cmd
)
299 struct snd_ff
*ff
= substream
->private_data
;
302 case SNDRV_PCM_TRIGGER_START
:
303 amdtp_stream_pcm_trigger(&ff
->tx_stream
, substream
);
305 case SNDRV_PCM_TRIGGER_STOP
:
306 amdtp_stream_pcm_trigger(&ff
->tx_stream
, NULL
);
315 static int pcm_playback_trigger(struct snd_pcm_substream
*substream
, int cmd
)
317 struct snd_ff
*ff
= substream
->private_data
;
320 case SNDRV_PCM_TRIGGER_START
:
321 amdtp_stream_pcm_trigger(&ff
->rx_stream
, substream
);
323 case SNDRV_PCM_TRIGGER_STOP
:
324 amdtp_stream_pcm_trigger(&ff
->rx_stream
, NULL
);
333 static snd_pcm_uframes_t
pcm_capture_pointer(struct snd_pcm_substream
*sbstrm
)
335 struct snd_ff
*ff
= sbstrm
->private_data
;
337 return amdtp_stream_pcm_pointer(&ff
->tx_stream
);
340 static snd_pcm_uframes_t
pcm_playback_pointer(struct snd_pcm_substream
*sbstrm
)
342 struct snd_ff
*ff
= sbstrm
->private_data
;
344 return amdtp_stream_pcm_pointer(&ff
->rx_stream
);
347 static int pcm_capture_ack(struct snd_pcm_substream
*substream
)
349 struct snd_ff
*ff
= substream
->private_data
;
351 return amdtp_stream_pcm_ack(&ff
->tx_stream
);
354 static int pcm_playback_ack(struct snd_pcm_substream
*substream
)
356 struct snd_ff
*ff
= substream
->private_data
;
358 return amdtp_stream_pcm_ack(&ff
->rx_stream
);
361 int snd_ff_create_pcm_devices(struct snd_ff
*ff
)
363 static const struct snd_pcm_ops pcm_capture_ops
= {
366 .ioctl
= snd_pcm_lib_ioctl
,
367 .hw_params
= pcm_capture_hw_params
,
368 .hw_free
= pcm_capture_hw_free
,
369 .prepare
= pcm_capture_prepare
,
370 .trigger
= pcm_capture_trigger
,
371 .pointer
= pcm_capture_pointer
,
372 .ack
= pcm_capture_ack
,
373 .page
= snd_pcm_lib_get_vmalloc_page
,
375 static const struct snd_pcm_ops pcm_playback_ops
= {
378 .ioctl
= snd_pcm_lib_ioctl
,
379 .hw_params
= pcm_playback_hw_params
,
380 .hw_free
= pcm_playback_hw_free
,
381 .prepare
= pcm_playback_prepare
,
382 .trigger
= pcm_playback_trigger
,
383 .pointer
= pcm_playback_pointer
,
384 .ack
= pcm_playback_ack
,
385 .page
= snd_pcm_lib_get_vmalloc_page
,
390 err
= snd_pcm_new(ff
->card
, ff
->card
->driver
, 0, 1, 1, &pcm
);
394 pcm
->private_data
= ff
;
395 snprintf(pcm
->name
, sizeof(pcm
->name
),
396 "%s PCM", ff
->card
->shortname
);
397 snd_pcm_set_ops(pcm
, SNDRV_PCM_STREAM_PLAYBACK
, &pcm_playback_ops
);
398 snd_pcm_set_ops(pcm
, SNDRV_PCM_STREAM_CAPTURE
, &pcm_capture_ops
);