2 * dice_pcm.c - a part of driver for DICE based devices
4 * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
5 * Copyright (c) 2014 Takashi Sakamoto <o-takashi@sakamocchi.jp>
7 * Licensed under the terms of the GNU General Public License, version 2.
12 static int dice_rate_constraint(struct snd_pcm_hw_params
*params
,
13 struct snd_pcm_hw_rule
*rule
)
15 struct snd_pcm_substream
*substream
= rule
->private;
16 struct snd_dice
*dice
= substream
->private_data
;
18 const struct snd_interval
*c
=
19 hw_param_interval_c(params
, SNDRV_PCM_HW_PARAM_CHANNELS
);
20 struct snd_interval
*r
=
21 hw_param_interval(params
, SNDRV_PCM_HW_PARAM_RATE
);
22 struct snd_interval rates
= {
23 .min
= UINT_MAX
, .max
= 0, .integer
= 1
25 unsigned int i
, rate
, mode
, *pcm_channels
;
27 if (substream
->stream
== SNDRV_PCM_STREAM_CAPTURE
)
28 pcm_channels
= dice
->tx_channels
;
30 pcm_channels
= dice
->rx_channels
;
32 for (i
= 0; i
< ARRAY_SIZE(snd_dice_rates
); ++i
) {
33 rate
= snd_dice_rates
[i
];
34 if (snd_dice_stream_get_rate_mode(dice
, rate
, &mode
) < 0)
37 if (!snd_interval_test(c
, pcm_channels
[mode
]))
40 rates
.min
= min(rates
.min
, rate
);
41 rates
.max
= max(rates
.max
, rate
);
44 return snd_interval_refine(r
, &rates
);
47 static int dice_channels_constraint(struct snd_pcm_hw_params
*params
,
48 struct snd_pcm_hw_rule
*rule
)
50 struct snd_pcm_substream
*substream
= rule
->private;
51 struct snd_dice
*dice
= substream
->private_data
;
53 const struct snd_interval
*r
=
54 hw_param_interval_c(params
, SNDRV_PCM_HW_PARAM_RATE
);
55 struct snd_interval
*c
=
56 hw_param_interval(params
, SNDRV_PCM_HW_PARAM_CHANNELS
);
57 struct snd_interval channels
= {
58 .min
= UINT_MAX
, .max
= 0, .integer
= 1
60 unsigned int i
, rate
, mode
, *pcm_channels
;
62 if (substream
->stream
== SNDRV_PCM_STREAM_CAPTURE
)
63 pcm_channels
= dice
->tx_channels
;
65 pcm_channels
= dice
->rx_channels
;
67 for (i
= 0; i
< ARRAY_SIZE(snd_dice_rates
); ++i
) {
68 rate
= snd_dice_rates
[i
];
69 if (snd_dice_stream_get_rate_mode(dice
, rate
, &mode
) < 0)
72 if (!snd_interval_test(r
, rate
))
75 channels
.min
= min(channels
.min
, pcm_channels
[mode
]);
76 channels
.max
= max(channels
.max
, pcm_channels
[mode
]);
79 return snd_interval_refine(c
, &channels
);
82 static void limit_channels_and_rates(struct snd_dice
*dice
,
83 struct snd_pcm_runtime
*runtime
,
84 unsigned int *pcm_channels
)
86 struct snd_pcm_hardware
*hw
= &runtime
->hw
;
87 unsigned int i
, rate
, mode
;
89 hw
->channels_min
= UINT_MAX
;
92 for (i
= 0; i
< ARRAY_SIZE(snd_dice_rates
); ++i
) {
93 rate
= snd_dice_rates
[i
];
94 if (snd_dice_stream_get_rate_mode(dice
, rate
, &mode
) < 0)
96 hw
->rates
|= snd_pcm_rate_to_rate_bit(rate
);
98 if (pcm_channels
[mode
] == 0)
100 hw
->channels_min
= min(hw
->channels_min
, pcm_channels
[mode
]);
101 hw
->channels_max
= max(hw
->channels_max
, pcm_channels
[mode
]);
104 snd_pcm_limit_hw_rates(runtime
);
107 static void limit_period_and_buffer(struct snd_pcm_hardware
*hw
)
109 hw
->periods_min
= 2; /* SNDRV_PCM_INFO_BATCH */
110 hw
->periods_max
= UINT_MAX
;
112 hw
->period_bytes_min
= 4 * hw
->channels_max
; /* byte for a frame */
114 /* Just to prevent from allocating much pages. */
115 hw
->period_bytes_max
= hw
->period_bytes_min
* 2048;
116 hw
->buffer_bytes_max
= hw
->period_bytes_max
* hw
->periods_min
;
119 static int init_hw_info(struct snd_dice
*dice
,
120 struct snd_pcm_substream
*substream
)
122 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
123 struct snd_pcm_hardware
*hw
= &runtime
->hw
;
124 struct amdtp_stream
*stream
;
125 unsigned int *pcm_channels
;
128 hw
->info
= SNDRV_PCM_INFO_MMAP
|
129 SNDRV_PCM_INFO_MMAP_VALID
|
130 SNDRV_PCM_INFO_BATCH
|
131 SNDRV_PCM_INFO_INTERLEAVED
|
132 SNDRV_PCM_INFO_JOINT_DUPLEX
|
133 SNDRV_PCM_INFO_BLOCK_TRANSFER
;
135 if (substream
->stream
== SNDRV_PCM_STREAM_CAPTURE
) {
136 hw
->formats
= AMDTP_IN_PCM_FORMAT_BITS
;
137 stream
= &dice
->tx_stream
;
138 pcm_channels
= dice
->tx_channels
;
140 hw
->formats
= AMDTP_OUT_PCM_FORMAT_BITS
;
141 stream
= &dice
->rx_stream
;
142 pcm_channels
= dice
->rx_channels
;
145 limit_channels_and_rates(dice
, runtime
, pcm_channels
);
146 limit_period_and_buffer(hw
);
148 err
= snd_pcm_hw_rule_add(runtime
, 0, SNDRV_PCM_HW_PARAM_RATE
,
149 dice_rate_constraint
, substream
,
150 SNDRV_PCM_HW_PARAM_CHANNELS
, -1);
153 err
= snd_pcm_hw_rule_add(runtime
, 0, SNDRV_PCM_HW_PARAM_CHANNELS
,
154 dice_channels_constraint
, substream
,
155 SNDRV_PCM_HW_PARAM_RATE
, -1);
159 err
= amdtp_stream_add_pcm_hw_constraints(stream
, runtime
);
164 static int pcm_open(struct snd_pcm_substream
*substream
)
166 struct snd_dice
*dice
= substream
->private_data
;
167 unsigned int source
, rate
;
171 err
= snd_dice_stream_lock_try(dice
);
175 err
= init_hw_info(dice
, substream
);
179 err
= snd_dice_transaction_get_clock_source(dice
, &source
);
183 case CLOCK_SOURCE_AES1
:
184 case CLOCK_SOURCE_AES2
:
185 case CLOCK_SOURCE_AES3
:
186 case CLOCK_SOURCE_AES4
:
187 case CLOCK_SOURCE_AES_ANY
:
188 case CLOCK_SOURCE_ADAT
:
189 case CLOCK_SOURCE_TDIF
:
190 case CLOCK_SOURCE_WC
:
199 * When source of clock is not internal or any PCM streams are running,
200 * available sampling rate is limited at current sampling rate.
203 amdtp_stream_pcm_running(&dice
->tx_stream
) ||
204 amdtp_stream_pcm_running(&dice
->rx_stream
)) {
205 err
= snd_dice_transaction_get_rate(dice
, &rate
);
208 substream
->runtime
->hw
.rate_min
= rate
;
209 substream
->runtime
->hw
.rate_max
= rate
;
212 snd_pcm_set_sync(substream
);
216 snd_dice_stream_lock_release(dice
);
220 static int pcm_close(struct snd_pcm_substream
*substream
)
222 struct snd_dice
*dice
= substream
->private_data
;
224 snd_dice_stream_lock_release(dice
);
229 static int capture_hw_params(struct snd_pcm_substream
*substream
,
230 struct snd_pcm_hw_params
*hw_params
)
232 struct snd_dice
*dice
= substream
->private_data
;
234 if (substream
->runtime
->status
->state
== SNDRV_PCM_STATE_OPEN
) {
235 mutex_lock(&dice
->mutex
);
236 dice
->substreams_counter
++;
237 mutex_unlock(&dice
->mutex
);
240 amdtp_stream_set_pcm_format(&dice
->tx_stream
,
241 params_format(hw_params
));
243 return snd_pcm_lib_alloc_vmalloc_buffer(substream
,
244 params_buffer_bytes(hw_params
));
246 static int playback_hw_params(struct snd_pcm_substream
*substream
,
247 struct snd_pcm_hw_params
*hw_params
)
249 struct snd_dice
*dice
= substream
->private_data
;
251 if (substream
->runtime
->status
->state
== SNDRV_PCM_STATE_OPEN
) {
252 mutex_lock(&dice
->mutex
);
253 dice
->substreams_counter
++;
254 mutex_unlock(&dice
->mutex
);
257 amdtp_stream_set_pcm_format(&dice
->rx_stream
,
258 params_format(hw_params
));
260 return snd_pcm_lib_alloc_vmalloc_buffer(substream
,
261 params_buffer_bytes(hw_params
));
264 static int capture_hw_free(struct snd_pcm_substream
*substream
)
266 struct snd_dice
*dice
= substream
->private_data
;
268 mutex_lock(&dice
->mutex
);
270 if (substream
->runtime
->status
->state
!= SNDRV_PCM_STATE_OPEN
)
271 dice
->substreams_counter
--;
273 snd_dice_stream_stop_duplex(dice
);
275 mutex_unlock(&dice
->mutex
);
277 return snd_pcm_lib_free_vmalloc_buffer(substream
);
280 static int playback_hw_free(struct snd_pcm_substream
*substream
)
282 struct snd_dice
*dice
= substream
->private_data
;
284 mutex_lock(&dice
->mutex
);
286 if (substream
->runtime
->status
->state
!= SNDRV_PCM_STATE_OPEN
)
287 dice
->substreams_counter
--;
289 snd_dice_stream_stop_duplex(dice
);
291 mutex_unlock(&dice
->mutex
);
293 return snd_pcm_lib_free_vmalloc_buffer(substream
);
296 static int capture_prepare(struct snd_pcm_substream
*substream
)
298 struct snd_dice
*dice
= substream
->private_data
;
301 mutex_lock(&dice
->mutex
);
302 err
= snd_dice_stream_start_duplex(dice
, substream
->runtime
->rate
);
303 mutex_unlock(&dice
->mutex
);
305 amdtp_stream_pcm_prepare(&dice
->tx_stream
);
309 static int playback_prepare(struct snd_pcm_substream
*substream
)
311 struct snd_dice
*dice
= substream
->private_data
;
314 mutex_lock(&dice
->mutex
);
315 err
= snd_dice_stream_start_duplex(dice
, substream
->runtime
->rate
);
316 mutex_unlock(&dice
->mutex
);
318 amdtp_stream_pcm_prepare(&dice
->rx_stream
);
323 static int capture_trigger(struct snd_pcm_substream
*substream
, int cmd
)
325 struct snd_dice
*dice
= substream
->private_data
;
328 case SNDRV_PCM_TRIGGER_START
:
329 amdtp_stream_pcm_trigger(&dice
->tx_stream
, substream
);
331 case SNDRV_PCM_TRIGGER_STOP
:
332 amdtp_stream_pcm_trigger(&dice
->tx_stream
, NULL
);
340 static int playback_trigger(struct snd_pcm_substream
*substream
, int cmd
)
342 struct snd_dice
*dice
= substream
->private_data
;
345 case SNDRV_PCM_TRIGGER_START
:
346 amdtp_stream_pcm_trigger(&dice
->rx_stream
, substream
);
348 case SNDRV_PCM_TRIGGER_STOP
:
349 amdtp_stream_pcm_trigger(&dice
->rx_stream
, NULL
);
358 static snd_pcm_uframes_t
capture_pointer(struct snd_pcm_substream
*substream
)
360 struct snd_dice
*dice
= substream
->private_data
;
362 return amdtp_stream_pcm_pointer(&dice
->tx_stream
);
364 static snd_pcm_uframes_t
playback_pointer(struct snd_pcm_substream
*substream
)
366 struct snd_dice
*dice
= substream
->private_data
;
368 return amdtp_stream_pcm_pointer(&dice
->rx_stream
);
371 int snd_dice_create_pcm(struct snd_dice
*dice
)
373 static struct snd_pcm_ops capture_ops
= {
376 .ioctl
= snd_pcm_lib_ioctl
,
377 .hw_params
= capture_hw_params
,
378 .hw_free
= capture_hw_free
,
379 .prepare
= capture_prepare
,
380 .trigger
= capture_trigger
,
381 .pointer
= capture_pointer
,
382 .page
= snd_pcm_lib_get_vmalloc_page
,
383 .mmap
= snd_pcm_lib_mmap_vmalloc
,
385 static struct snd_pcm_ops playback_ops
= {
388 .ioctl
= snd_pcm_lib_ioctl
,
389 .hw_params
= playback_hw_params
,
390 .hw_free
= playback_hw_free
,
391 .prepare
= playback_prepare
,
392 .trigger
= playback_trigger
,
393 .pointer
= playback_pointer
,
394 .page
= snd_pcm_lib_get_vmalloc_page
,
395 .mmap
= snd_pcm_lib_mmap_vmalloc
,
398 unsigned int i
, capture
, playback
;
401 capture
= playback
= 0;
402 for (i
= 0; i
< 3; i
++) {
403 if (dice
->tx_channels
[i
] > 0)
405 if (dice
->rx_channels
[i
] > 0)
409 err
= snd_pcm_new(dice
->card
, "DICE", 0, playback
, capture
, &pcm
);
412 pcm
->private_data
= dice
;
413 strcpy(pcm
->name
, dice
->card
->shortname
);
416 snd_pcm_set_ops(pcm
, SNDRV_PCM_STREAM_CAPTURE
, &capture_ops
);
419 snd_pcm_set_ops(pcm
, SNDRV_PCM_STREAM_PLAYBACK
, &playback_ops
);