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 struct amdtp_stream
*stream
)
16 struct snd_pcm_hardware
*hw
= &runtime
->hw
;
22 * Retrieve current Multi Bit Linear Audio data channel and limit to
25 if (stream
== &dice
->tx_stream
) {
26 err
= snd_dice_transaction_read_tx(dice
, TX_NUMBER_AUDIO
,
29 err
= snd_dice_transaction_read_rx(dice
, RX_NUMBER_AUDIO
,
35 hw
->channels_min
= hw
->channels_max
= be32_to_cpu(reg
[0]);
37 /* Retrieve current sampling transfer frequency and limit to it. */
38 err
= snd_dice_transaction_get_rate(dice
, &rate
);
42 hw
->rates
= snd_pcm_rate_to_rate_bit(rate
);
43 snd_pcm_limit_hw_rates(runtime
);
48 static void limit_period_and_buffer(struct snd_pcm_hardware
*hw
)
50 hw
->periods_min
= 2; /* SNDRV_PCM_INFO_BATCH */
51 hw
->periods_max
= UINT_MAX
;
53 hw
->period_bytes_min
= 4 * hw
->channels_max
; /* byte for a frame */
55 /* Just to prevent from allocating much pages. */
56 hw
->period_bytes_max
= hw
->period_bytes_min
* 2048;
57 hw
->buffer_bytes_max
= hw
->period_bytes_max
* hw
->periods_min
;
60 static int init_hw_info(struct snd_dice
*dice
,
61 struct snd_pcm_substream
*substream
)
63 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
64 struct snd_pcm_hardware
*hw
= &runtime
->hw
;
65 struct amdtp_stream
*stream
;
68 hw
->info
= SNDRV_PCM_INFO_MMAP
|
69 SNDRV_PCM_INFO_MMAP_VALID
|
70 SNDRV_PCM_INFO_BATCH
|
71 SNDRV_PCM_INFO_INTERLEAVED
|
72 SNDRV_PCM_INFO_JOINT_DUPLEX
|
73 SNDRV_PCM_INFO_BLOCK_TRANSFER
;
75 if (substream
->stream
== SNDRV_PCM_STREAM_CAPTURE
) {
76 hw
->formats
= AM824_IN_PCM_FORMAT_BITS
;
77 stream
= &dice
->tx_stream
;
79 hw
->formats
= AM824_OUT_PCM_FORMAT_BITS
;
80 stream
= &dice
->rx_stream
;
83 err
= limit_channels_and_rates(dice
, runtime
, stream
);
86 limit_period_and_buffer(hw
);
88 return amdtp_am824_add_pcm_hw_constraints(stream
, runtime
);
91 static int pcm_open(struct snd_pcm_substream
*substream
)
93 struct snd_dice
*dice
= substream
->private_data
;
96 err
= snd_dice_stream_lock_try(dice
);
100 err
= init_hw_info(dice
, substream
);
104 snd_pcm_set_sync(substream
);
108 snd_dice_stream_lock_release(dice
);
112 static int pcm_close(struct snd_pcm_substream
*substream
)
114 struct snd_dice
*dice
= substream
->private_data
;
116 snd_dice_stream_lock_release(dice
);
121 static int capture_hw_params(struct snd_pcm_substream
*substream
,
122 struct snd_pcm_hw_params
*hw_params
)
124 struct snd_dice
*dice
= substream
->private_data
;
127 err
= snd_pcm_lib_alloc_vmalloc_buffer(substream
,
128 params_buffer_bytes(hw_params
));
132 if (substream
->runtime
->status
->state
== SNDRV_PCM_STATE_OPEN
) {
133 mutex_lock(&dice
->mutex
);
134 dice
->substreams_counter
++;
135 mutex_unlock(&dice
->mutex
);
138 amdtp_am824_set_pcm_format(&dice
->tx_stream
, params_format(hw_params
));
142 static int playback_hw_params(struct snd_pcm_substream
*substream
,
143 struct snd_pcm_hw_params
*hw_params
)
145 struct snd_dice
*dice
= substream
->private_data
;
148 err
= snd_pcm_lib_alloc_vmalloc_buffer(substream
,
149 params_buffer_bytes(hw_params
));
153 if (substream
->runtime
->status
->state
== SNDRV_PCM_STATE_OPEN
) {
154 mutex_lock(&dice
->mutex
);
155 dice
->substreams_counter
++;
156 mutex_unlock(&dice
->mutex
);
159 amdtp_am824_set_pcm_format(&dice
->rx_stream
, params_format(hw_params
));
164 static int capture_hw_free(struct snd_pcm_substream
*substream
)
166 struct snd_dice
*dice
= substream
->private_data
;
168 mutex_lock(&dice
->mutex
);
170 if (substream
->runtime
->status
->state
!= SNDRV_PCM_STATE_OPEN
)
171 dice
->substreams_counter
--;
173 snd_dice_stream_stop_duplex(dice
);
175 mutex_unlock(&dice
->mutex
);
177 return snd_pcm_lib_free_vmalloc_buffer(substream
);
180 static int playback_hw_free(struct snd_pcm_substream
*substream
)
182 struct snd_dice
*dice
= substream
->private_data
;
184 mutex_lock(&dice
->mutex
);
186 if (substream
->runtime
->status
->state
!= SNDRV_PCM_STATE_OPEN
)
187 dice
->substreams_counter
--;
189 snd_dice_stream_stop_duplex(dice
);
191 mutex_unlock(&dice
->mutex
);
193 return snd_pcm_lib_free_vmalloc_buffer(substream
);
196 static int capture_prepare(struct snd_pcm_substream
*substream
)
198 struct snd_dice
*dice
= substream
->private_data
;
201 mutex_lock(&dice
->mutex
);
202 err
= snd_dice_stream_start_duplex(dice
, substream
->runtime
->rate
);
203 mutex_unlock(&dice
->mutex
);
205 amdtp_stream_pcm_prepare(&dice
->tx_stream
);
209 static int playback_prepare(struct snd_pcm_substream
*substream
)
211 struct snd_dice
*dice
= substream
->private_data
;
214 mutex_lock(&dice
->mutex
);
215 err
= snd_dice_stream_start_duplex(dice
, substream
->runtime
->rate
);
216 mutex_unlock(&dice
->mutex
);
218 amdtp_stream_pcm_prepare(&dice
->rx_stream
);
223 static int capture_trigger(struct snd_pcm_substream
*substream
, int cmd
)
225 struct snd_dice
*dice
= substream
->private_data
;
228 case SNDRV_PCM_TRIGGER_START
:
229 amdtp_stream_pcm_trigger(&dice
->tx_stream
, substream
);
231 case SNDRV_PCM_TRIGGER_STOP
:
232 amdtp_stream_pcm_trigger(&dice
->tx_stream
, NULL
);
240 static int playback_trigger(struct snd_pcm_substream
*substream
, int cmd
)
242 struct snd_dice
*dice
= substream
->private_data
;
245 case SNDRV_PCM_TRIGGER_START
:
246 amdtp_stream_pcm_trigger(&dice
->rx_stream
, substream
);
248 case SNDRV_PCM_TRIGGER_STOP
:
249 amdtp_stream_pcm_trigger(&dice
->rx_stream
, NULL
);
258 static snd_pcm_uframes_t
capture_pointer(struct snd_pcm_substream
*substream
)
260 struct snd_dice
*dice
= substream
->private_data
;
262 return amdtp_stream_pcm_pointer(&dice
->tx_stream
);
264 static snd_pcm_uframes_t
playback_pointer(struct snd_pcm_substream
*substream
)
266 struct snd_dice
*dice
= substream
->private_data
;
268 return amdtp_stream_pcm_pointer(&dice
->rx_stream
);
271 int snd_dice_create_pcm(struct snd_dice
*dice
)
273 static struct snd_pcm_ops capture_ops
= {
276 .ioctl
= snd_pcm_lib_ioctl
,
277 .hw_params
= capture_hw_params
,
278 .hw_free
= capture_hw_free
,
279 .prepare
= capture_prepare
,
280 .trigger
= capture_trigger
,
281 .pointer
= capture_pointer
,
282 .page
= snd_pcm_lib_get_vmalloc_page
,
283 .mmap
= snd_pcm_lib_mmap_vmalloc
,
285 static struct snd_pcm_ops playback_ops
= {
288 .ioctl
= snd_pcm_lib_ioctl
,
289 .hw_params
= playback_hw_params
,
290 .hw_free
= playback_hw_free
,
291 .prepare
= playback_prepare
,
292 .trigger
= playback_trigger
,
293 .pointer
= playback_pointer
,
294 .page
= snd_pcm_lib_get_vmalloc_page
,
295 .mmap
= snd_pcm_lib_mmap_vmalloc
,
299 unsigned int capture
, playback
;
303 * Check whether PCM substreams are required.
305 * TODO: in the case that any PCM substreams are not avail at a certain
306 * sampling transfer frequency?
308 err
= snd_dice_transaction_read_tx(dice
, TX_NUMBER_AUDIO
,
312 if (be32_to_cpu(reg
) > 0)
315 err
= snd_dice_transaction_read_rx(dice
, RX_NUMBER_AUDIO
,
319 if (be32_to_cpu(reg
) > 0)
322 err
= snd_pcm_new(dice
->card
, "DICE", 0, playback
, capture
, &pcm
);
325 pcm
->private_data
= dice
;
326 strcpy(pcm
->name
, dice
->card
->shortname
);
329 snd_pcm_set_ops(pcm
, SNDRV_PCM_STREAM_CAPTURE
, &capture_ops
);
332 snd_pcm_set_ops(pcm
, SNDRV_PCM_STREAM_PLAYBACK
, &playback_ops
);