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 int init_hw_info(struct snd_dice
*dice
,
55 struct snd_pcm_substream
*substream
)
57 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
58 struct snd_pcm_hardware
*hw
= &runtime
->hw
;
59 enum amdtp_stream_direction dir
;
60 struct amdtp_stream
*stream
;
62 unsigned int count
, size
;
65 if (substream
->stream
== SNDRV_PCM_STREAM_CAPTURE
) {
66 hw
->formats
= AM824_IN_PCM_FORMAT_BITS
;
67 dir
= AMDTP_IN_STREAM
;
68 stream
= &dice
->tx_stream
[substream
->pcm
->device
];
69 err
= snd_dice_transaction_read_tx(dice
, TX_NUMBER
, reg
,
72 hw
->formats
= AM824_OUT_PCM_FORMAT_BITS
;
73 dir
= AMDTP_OUT_STREAM
;
74 stream
= &dice
->rx_stream
[substream
->pcm
->device
];
75 err
= snd_dice_transaction_read_rx(dice
, RX_NUMBER
, reg
,
82 count
= min_t(unsigned int, be32_to_cpu(reg
[0]), MAX_STREAMS
);
83 if (substream
->pcm
->device
>= count
)
86 size
= be32_to_cpu(reg
[1]) * 4;
87 err
= limit_channels_and_rates(dice
, substream
->runtime
, dir
,
88 substream
->pcm
->device
, size
);
92 return amdtp_am824_add_pcm_hw_constraints(stream
, runtime
);
95 static int pcm_open(struct snd_pcm_substream
*substream
)
97 struct snd_dice
*dice
= substream
->private_data
;
100 err
= snd_dice_stream_lock_try(dice
);
104 err
= init_hw_info(dice
, substream
);
108 snd_pcm_set_sync(substream
);
112 snd_dice_stream_lock_release(dice
);
116 static int pcm_close(struct snd_pcm_substream
*substream
)
118 struct snd_dice
*dice
= substream
->private_data
;
120 snd_dice_stream_lock_release(dice
);
125 static int capture_hw_params(struct snd_pcm_substream
*substream
,
126 struct snd_pcm_hw_params
*hw_params
)
128 struct snd_dice
*dice
= substream
->private_data
;
131 err
= snd_pcm_lib_alloc_vmalloc_buffer(substream
,
132 params_buffer_bytes(hw_params
));
136 if (substream
->runtime
->status
->state
== SNDRV_PCM_STATE_OPEN
) {
137 mutex_lock(&dice
->mutex
);
138 dice
->substreams_counter
++;
139 mutex_unlock(&dice
->mutex
);
144 static int playback_hw_params(struct snd_pcm_substream
*substream
,
145 struct snd_pcm_hw_params
*hw_params
)
147 struct snd_dice
*dice
= substream
->private_data
;
150 err
= snd_pcm_lib_alloc_vmalloc_buffer(substream
,
151 params_buffer_bytes(hw_params
));
155 if (substream
->runtime
->status
->state
== SNDRV_PCM_STATE_OPEN
) {
156 mutex_lock(&dice
->mutex
);
157 dice
->substreams_counter
++;
158 mutex_unlock(&dice
->mutex
);
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
;
199 struct amdtp_stream
*stream
= &dice
->tx_stream
[substream
->pcm
->device
];
202 mutex_lock(&dice
->mutex
);
203 err
= snd_dice_stream_start_duplex(dice
, substream
->runtime
->rate
);
204 mutex_unlock(&dice
->mutex
);
206 amdtp_stream_pcm_prepare(stream
);
210 static int playback_prepare(struct snd_pcm_substream
*substream
)
212 struct snd_dice
*dice
= substream
->private_data
;
213 struct amdtp_stream
*stream
= &dice
->rx_stream
[substream
->pcm
->device
];
216 mutex_lock(&dice
->mutex
);
217 err
= snd_dice_stream_start_duplex(dice
, substream
->runtime
->rate
);
218 mutex_unlock(&dice
->mutex
);
220 amdtp_stream_pcm_prepare(stream
);
225 static int capture_trigger(struct snd_pcm_substream
*substream
, int cmd
)
227 struct snd_dice
*dice
= substream
->private_data
;
228 struct amdtp_stream
*stream
= &dice
->tx_stream
[substream
->pcm
->device
];
231 case SNDRV_PCM_TRIGGER_START
:
232 amdtp_stream_pcm_trigger(stream
, substream
);
234 case SNDRV_PCM_TRIGGER_STOP
:
235 amdtp_stream_pcm_trigger(stream
, NULL
);
243 static int playback_trigger(struct snd_pcm_substream
*substream
, int cmd
)
245 struct snd_dice
*dice
= substream
->private_data
;
246 struct amdtp_stream
*stream
= &dice
->rx_stream
[substream
->pcm
->device
];
249 case SNDRV_PCM_TRIGGER_START
:
250 amdtp_stream_pcm_trigger(stream
, substream
);
252 case SNDRV_PCM_TRIGGER_STOP
:
253 amdtp_stream_pcm_trigger(stream
, NULL
);
262 static snd_pcm_uframes_t
capture_pointer(struct snd_pcm_substream
*substream
)
264 struct snd_dice
*dice
= substream
->private_data
;
265 struct amdtp_stream
*stream
= &dice
->tx_stream
[substream
->pcm
->device
];
267 return amdtp_stream_pcm_pointer(stream
);
269 static snd_pcm_uframes_t
playback_pointer(struct snd_pcm_substream
*substream
)
271 struct snd_dice
*dice
= substream
->private_data
;
272 struct amdtp_stream
*stream
= &dice
->rx_stream
[substream
->pcm
->device
];
274 return amdtp_stream_pcm_pointer(stream
);
277 static int capture_ack(struct snd_pcm_substream
*substream
)
279 struct snd_dice
*dice
= substream
->private_data
;
280 struct amdtp_stream
*stream
= &dice
->tx_stream
[substream
->pcm
->device
];
282 return amdtp_stream_pcm_ack(stream
);
285 static int playback_ack(struct snd_pcm_substream
*substream
)
287 struct snd_dice
*dice
= substream
->private_data
;
288 struct amdtp_stream
*stream
= &dice
->rx_stream
[substream
->pcm
->device
];
290 return amdtp_stream_pcm_ack(stream
);
293 int snd_dice_create_pcm(struct snd_dice
*dice
)
295 static const struct snd_pcm_ops capture_ops
= {
298 .ioctl
= snd_pcm_lib_ioctl
,
299 .hw_params
= capture_hw_params
,
300 .hw_free
= capture_hw_free
,
301 .prepare
= capture_prepare
,
302 .trigger
= capture_trigger
,
303 .pointer
= capture_pointer
,
305 .page
= snd_pcm_lib_get_vmalloc_page
,
306 .mmap
= snd_pcm_lib_mmap_vmalloc
,
308 static const struct snd_pcm_ops playback_ops
= {
311 .ioctl
= snd_pcm_lib_ioctl
,
312 .hw_params
= playback_hw_params
,
313 .hw_free
= playback_hw_free
,
314 .prepare
= playback_prepare
,
315 .trigger
= playback_trigger
,
316 .pointer
= playback_pointer
,
318 .page
= snd_pcm_lib_get_vmalloc_page
,
319 .mmap
= snd_pcm_lib_mmap_vmalloc
,
323 unsigned int i
, max_capture
, max_playback
, capture
, playback
;
326 /* Check whether PCM substreams are required. */
327 if (dice
->force_two_pcms
) {
328 max_capture
= max_playback
= 2;
330 max_capture
= max_playback
= 0;
331 err
= snd_dice_transaction_read_tx(dice
, TX_NUMBER
, ®
,
335 max_capture
= min_t(unsigned int, be32_to_cpu(reg
), MAX_STREAMS
);
337 err
= snd_dice_transaction_read_rx(dice
, RX_NUMBER
, ®
,
341 max_playback
= min_t(unsigned int, be32_to_cpu(reg
), MAX_STREAMS
);
344 for (i
= 0; i
< MAX_STREAMS
; i
++) {
345 capture
= playback
= 0;
348 if (i
< max_playback
)
350 if (capture
== 0 && playback
== 0)
353 err
= snd_pcm_new(dice
->card
, "DICE", i
, playback
, capture
,
357 pcm
->private_data
= dice
;
358 strcpy(pcm
->name
, dice
->card
->shortname
);
361 snd_pcm_set_ops(pcm
, SNDRV_PCM_STREAM_CAPTURE
,
365 snd_pcm_set_ops(pcm
, SNDRV_PCM_STREAM_PLAYBACK
,