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 limit_channels_and_rates(struct snd_dice
*dice
,
13 struct snd_pcm_runtime
*runtime
,
14 enum amdtp_stream_direction dir
,
15 unsigned int index
, unsigned int size
)
17 struct snd_pcm_hardware
*hw
= &runtime
->hw
;
18 struct amdtp_stream
*stream
;
24 * Retrieve current Multi Bit Linear Audio data channel and limit to
27 if (dir
== AMDTP_IN_STREAM
) {
28 stream
= &dice
->tx_stream
[index
];
29 err
= snd_dice_transaction_read_tx(dice
,
30 size
* index
+ TX_NUMBER_AUDIO
,
33 stream
= &dice
->rx_stream
[index
];
34 err
= snd_dice_transaction_read_rx(dice
,
35 size
* index
+ RX_NUMBER_AUDIO
,
41 hw
->channels_min
= hw
->channels_max
= be32_to_cpu(reg
);
43 /* Retrieve current sampling transfer frequency and limit to it. */
44 err
= snd_dice_transaction_get_rate(dice
, &rate
);
48 hw
->rates
= snd_pcm_rate_to_rate_bit(rate
);
49 snd_pcm_limit_hw_rates(runtime
);
54 static void limit_period_and_buffer(struct snd_pcm_hardware
*hw
)
56 hw
->periods_min
= 2; /* SNDRV_PCM_INFO_BATCH */
57 hw
->periods_max
= UINT_MAX
;
59 hw
->period_bytes_min
= 4 * hw
->channels_max
; /* byte for a frame */
61 /* Just to prevent from allocating much pages. */
62 hw
->period_bytes_max
= hw
->period_bytes_min
* 2048;
63 hw
->buffer_bytes_max
= hw
->period_bytes_max
* hw
->periods_min
;
66 static int init_hw_info(struct snd_dice
*dice
,
67 struct snd_pcm_substream
*substream
)
69 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
70 struct snd_pcm_hardware
*hw
= &runtime
->hw
;
71 enum amdtp_stream_direction dir
;
72 struct amdtp_stream
*stream
;
74 unsigned int count
, size
;
77 hw
->info
= SNDRV_PCM_INFO_MMAP
|
78 SNDRV_PCM_INFO_MMAP_VALID
|
79 SNDRV_PCM_INFO_BATCH
|
80 SNDRV_PCM_INFO_INTERLEAVED
|
81 SNDRV_PCM_INFO_JOINT_DUPLEX
|
82 SNDRV_PCM_INFO_BLOCK_TRANSFER
;
84 if (substream
->stream
== SNDRV_PCM_STREAM_CAPTURE
) {
85 hw
->formats
= AM824_IN_PCM_FORMAT_BITS
;
86 dir
= AMDTP_IN_STREAM
;
87 stream
= &dice
->tx_stream
[substream
->pcm
->device
];
88 err
= snd_dice_transaction_read_tx(dice
, TX_NUMBER
, reg
,
91 hw
->formats
= AM824_OUT_PCM_FORMAT_BITS
;
92 dir
= AMDTP_OUT_STREAM
;
93 stream
= &dice
->rx_stream
[substream
->pcm
->device
];
94 err
= snd_dice_transaction_read_rx(dice
, RX_NUMBER
, reg
,
101 count
= min_t(unsigned int, be32_to_cpu(reg
[0]), MAX_STREAMS
);
102 if (substream
->pcm
->device
>= count
)
105 size
= be32_to_cpu(reg
[1]) * 4;
106 err
= limit_channels_and_rates(dice
, substream
->runtime
, dir
,
107 substream
->pcm
->device
, size
);
110 limit_period_and_buffer(hw
);
112 return amdtp_am824_add_pcm_hw_constraints(stream
, runtime
);
115 static int pcm_open(struct snd_pcm_substream
*substream
)
117 struct snd_dice
*dice
= substream
->private_data
;
120 err
= snd_dice_stream_lock_try(dice
);
124 err
= init_hw_info(dice
, substream
);
128 snd_pcm_set_sync(substream
);
132 snd_dice_stream_lock_release(dice
);
136 static int pcm_close(struct snd_pcm_substream
*substream
)
138 struct snd_dice
*dice
= substream
->private_data
;
140 snd_dice_stream_lock_release(dice
);
145 static int capture_hw_params(struct snd_pcm_substream
*substream
,
146 struct snd_pcm_hw_params
*hw_params
)
148 struct snd_dice
*dice
= substream
->private_data
;
149 struct amdtp_stream
*stream
= &dice
->tx_stream
[substream
->pcm
->device
];
152 err
= snd_pcm_lib_alloc_vmalloc_buffer(substream
,
153 params_buffer_bytes(hw_params
));
157 if (substream
->runtime
->status
->state
== SNDRV_PCM_STATE_OPEN
) {
158 mutex_lock(&dice
->mutex
);
159 dice
->substreams_counter
++;
160 mutex_unlock(&dice
->mutex
);
163 amdtp_am824_set_pcm_format(stream
, params_format(hw_params
));
167 static int playback_hw_params(struct snd_pcm_substream
*substream
,
168 struct snd_pcm_hw_params
*hw_params
)
170 struct snd_dice
*dice
= substream
->private_data
;
171 struct amdtp_stream
*stream
= &dice
->rx_stream
[substream
->pcm
->device
];
174 err
= snd_pcm_lib_alloc_vmalloc_buffer(substream
,
175 params_buffer_bytes(hw_params
));
179 if (substream
->runtime
->status
->state
== SNDRV_PCM_STATE_OPEN
) {
180 mutex_lock(&dice
->mutex
);
181 dice
->substreams_counter
++;
182 mutex_unlock(&dice
->mutex
);
185 amdtp_am824_set_pcm_format(stream
, params_format(hw_params
));
190 static int capture_hw_free(struct snd_pcm_substream
*substream
)
192 struct snd_dice
*dice
= substream
->private_data
;
194 mutex_lock(&dice
->mutex
);
196 if (substream
->runtime
->status
->state
!= SNDRV_PCM_STATE_OPEN
)
197 dice
->substreams_counter
--;
199 snd_dice_stream_stop_duplex(dice
);
201 mutex_unlock(&dice
->mutex
);
203 return snd_pcm_lib_free_vmalloc_buffer(substream
);
206 static int playback_hw_free(struct snd_pcm_substream
*substream
)
208 struct snd_dice
*dice
= substream
->private_data
;
210 mutex_lock(&dice
->mutex
);
212 if (substream
->runtime
->status
->state
!= SNDRV_PCM_STATE_OPEN
)
213 dice
->substreams_counter
--;
215 snd_dice_stream_stop_duplex(dice
);
217 mutex_unlock(&dice
->mutex
);
219 return snd_pcm_lib_free_vmalloc_buffer(substream
);
222 static int capture_prepare(struct snd_pcm_substream
*substream
)
224 struct snd_dice
*dice
= substream
->private_data
;
225 struct amdtp_stream
*stream
= &dice
->tx_stream
[substream
->pcm
->device
];
228 mutex_lock(&dice
->mutex
);
229 err
= snd_dice_stream_start_duplex(dice
, substream
->runtime
->rate
);
230 mutex_unlock(&dice
->mutex
);
232 amdtp_stream_pcm_prepare(stream
);
236 static int playback_prepare(struct snd_pcm_substream
*substream
)
238 struct snd_dice
*dice
= substream
->private_data
;
239 struct amdtp_stream
*stream
= &dice
->rx_stream
[substream
->pcm
->device
];
242 mutex_lock(&dice
->mutex
);
243 err
= snd_dice_stream_start_duplex(dice
, substream
->runtime
->rate
);
244 mutex_unlock(&dice
->mutex
);
246 amdtp_stream_pcm_prepare(stream
);
251 static int capture_trigger(struct snd_pcm_substream
*substream
, int cmd
)
253 struct snd_dice
*dice
= substream
->private_data
;
254 struct amdtp_stream
*stream
= &dice
->tx_stream
[substream
->pcm
->device
];
257 case SNDRV_PCM_TRIGGER_START
:
258 amdtp_stream_pcm_trigger(stream
, substream
);
260 case SNDRV_PCM_TRIGGER_STOP
:
261 amdtp_stream_pcm_trigger(stream
, NULL
);
269 static int playback_trigger(struct snd_pcm_substream
*substream
, int cmd
)
271 struct snd_dice
*dice
= substream
->private_data
;
272 struct amdtp_stream
*stream
= &dice
->rx_stream
[substream
->pcm
->device
];
275 case SNDRV_PCM_TRIGGER_START
:
276 amdtp_stream_pcm_trigger(stream
, substream
);
278 case SNDRV_PCM_TRIGGER_STOP
:
279 amdtp_stream_pcm_trigger(stream
, NULL
);
288 static snd_pcm_uframes_t
capture_pointer(struct snd_pcm_substream
*substream
)
290 struct snd_dice
*dice
= substream
->private_data
;
291 struct amdtp_stream
*stream
= &dice
->tx_stream
[substream
->pcm
->device
];
293 return amdtp_stream_pcm_pointer(stream
);
295 static snd_pcm_uframes_t
playback_pointer(struct snd_pcm_substream
*substream
)
297 struct snd_dice
*dice
= substream
->private_data
;
298 struct amdtp_stream
*stream
= &dice
->rx_stream
[substream
->pcm
->device
];
300 return amdtp_stream_pcm_pointer(stream
);
303 int snd_dice_create_pcm(struct snd_dice
*dice
)
305 static const struct snd_pcm_ops capture_ops
= {
308 .ioctl
= snd_pcm_lib_ioctl
,
309 .hw_params
= capture_hw_params
,
310 .hw_free
= capture_hw_free
,
311 .prepare
= capture_prepare
,
312 .trigger
= capture_trigger
,
313 .pointer
= capture_pointer
,
314 .page
= snd_pcm_lib_get_vmalloc_page
,
315 .mmap
= snd_pcm_lib_mmap_vmalloc
,
317 static const struct snd_pcm_ops playback_ops
= {
320 .ioctl
= snd_pcm_lib_ioctl
,
321 .hw_params
= playback_hw_params
,
322 .hw_free
= playback_hw_free
,
323 .prepare
= playback_prepare
,
324 .trigger
= playback_trigger
,
325 .pointer
= playback_pointer
,
326 .page
= snd_pcm_lib_get_vmalloc_page
,
327 .mmap
= snd_pcm_lib_mmap_vmalloc
,
331 unsigned int i
, max_capture
, max_playback
, capture
, playback
;
334 /* Check whether PCM substreams are required. */
335 if (dice
->force_two_pcms
) {
336 max_capture
= max_playback
= 2;
338 max_capture
= max_playback
= 0;
339 err
= snd_dice_transaction_read_tx(dice
, TX_NUMBER
, ®
,
343 max_capture
= min_t(unsigned int, be32_to_cpu(reg
), MAX_STREAMS
);
345 err
= snd_dice_transaction_read_rx(dice
, RX_NUMBER
, ®
,
349 max_playback
= min_t(unsigned int, be32_to_cpu(reg
), MAX_STREAMS
);
352 for (i
= 0; i
< MAX_STREAMS
; i
++) {
353 capture
= playback
= 0;
356 if (i
< max_playback
)
358 if (capture
== 0 && playback
== 0)
361 err
= snd_pcm_new(dice
->card
, "DICE", i
, playback
, capture
,
365 pcm
->private_data
= dice
;
366 strcpy(pcm
->name
, dice
->card
->shortname
);
369 snd_pcm_set_ops(pcm
, SNDRV_PCM_STREAM_CAPTURE
,
373 snd_pcm_set_ops(pcm
, SNDRV_PCM_STREAM_PLAYBACK
,