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_dice
*dice
= rule
->private;
17 const struct snd_interval
*c
=
18 hw_param_interval_c(params
, SNDRV_PCM_HW_PARAM_CHANNELS
);
19 struct snd_interval
*r
=
20 hw_param_interval(params
, SNDRV_PCM_HW_PARAM_RATE
);
21 struct snd_interval rates
= {
22 .min
= UINT_MAX
, .max
= 0, .integer
= 1
24 unsigned int i
, rate
, mode
, *pcm_channels
= dice
->rx_channels
;
26 for (i
= 0; i
< ARRAY_SIZE(snd_dice_rates
); ++i
) {
27 rate
= snd_dice_rates
[i
];
28 if (snd_dice_stream_get_rate_mode(dice
, rate
, &mode
) < 0)
31 if (!snd_interval_test(c
, pcm_channels
[mode
]))
34 rates
.min
= min(rates
.min
, rate
);
35 rates
.max
= max(rates
.max
, rate
);
38 return snd_interval_refine(r
, &rates
);
41 static int dice_channels_constraint(struct snd_pcm_hw_params
*params
,
42 struct snd_pcm_hw_rule
*rule
)
44 struct snd_dice
*dice
= rule
->private;
46 const struct snd_interval
*r
=
47 hw_param_interval_c(params
, SNDRV_PCM_HW_PARAM_RATE
);
48 struct snd_interval
*c
=
49 hw_param_interval(params
, SNDRV_PCM_HW_PARAM_CHANNELS
);
50 struct snd_interval channels
= {
51 .min
= UINT_MAX
, .max
= 0, .integer
= 1
53 unsigned int i
, rate
, mode
, *pcm_channels
= dice
->rx_channels
;
55 for (i
= 0; i
< ARRAY_SIZE(snd_dice_rates
); ++i
) {
56 rate
= snd_dice_rates
[i
];
57 if (snd_dice_stream_get_rate_mode(dice
, rate
, &mode
) < 0)
60 if (!snd_interval_test(r
, rate
))
63 channels
.min
= min(channels
.min
, pcm_channels
[mode
]);
64 channels
.max
= max(channels
.max
, pcm_channels
[mode
]);
67 return snd_interval_refine(c
, &channels
);
70 static void limit_channels_and_rates(struct snd_dice
*dice
,
71 struct snd_pcm_runtime
*runtime
,
72 unsigned int *pcm_channels
)
74 struct snd_pcm_hardware
*hw
= &runtime
->hw
;
75 unsigned int i
, rate
, mode
;
77 hw
->channels_min
= UINT_MAX
;
80 for (i
= 0; i
< ARRAY_SIZE(snd_dice_rates
); ++i
) {
81 rate
= snd_dice_rates
[i
];
82 if (snd_dice_stream_get_rate_mode(dice
, rate
, &mode
) < 0)
84 hw
->rates
|= snd_pcm_rate_to_rate_bit(rate
);
86 if (pcm_channels
[mode
] == 0)
88 hw
->channels_min
= min(hw
->channels_min
, pcm_channels
[mode
]);
89 hw
->channels_max
= max(hw
->channels_max
, pcm_channels
[mode
]);
92 snd_pcm_limit_hw_rates(runtime
);
95 static void limit_period_and_buffer(struct snd_pcm_hardware
*hw
)
97 hw
->periods_min
= 2; /* SNDRV_PCM_INFO_BATCH */
98 hw
->periods_max
= UINT_MAX
;
100 hw
->period_bytes_min
= 4 * hw
->channels_max
; /* byte for a frame */
102 /* Just to prevent from allocating much pages. */
103 hw
->period_bytes_max
= hw
->period_bytes_min
* 2048;
104 hw
->buffer_bytes_max
= hw
->period_bytes_max
* hw
->periods_min
;
107 static int init_hw_info(struct snd_dice
*dice
,
108 struct snd_pcm_substream
*substream
)
110 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
111 struct snd_pcm_hardware
*hw
= &runtime
->hw
;
114 hw
->info
= SNDRV_PCM_INFO_MMAP
|
115 SNDRV_PCM_INFO_MMAP_VALID
|
116 SNDRV_PCM_INFO_BATCH
|
117 SNDRV_PCM_INFO_INTERLEAVED
|
118 SNDRV_PCM_INFO_BLOCK_TRANSFER
;
119 hw
->formats
= AMDTP_OUT_PCM_FORMAT_BITS
;
121 limit_channels_and_rates(dice
, runtime
, dice
->rx_channels
);
122 limit_period_and_buffer(hw
);
124 err
= snd_pcm_hw_rule_add(runtime
, 0, SNDRV_PCM_HW_PARAM_RATE
,
125 dice_rate_constraint
, dice
,
126 SNDRV_PCM_HW_PARAM_CHANNELS
, -1);
129 err
= snd_pcm_hw_rule_add(runtime
, 0, SNDRV_PCM_HW_PARAM_CHANNELS
,
130 dice_channels_constraint
, dice
,
131 SNDRV_PCM_HW_PARAM_RATE
, -1);
135 err
= amdtp_stream_add_pcm_hw_constraints(&dice
->rx_stream
, runtime
);
140 static int pcm_open(struct snd_pcm_substream
*substream
)
142 struct snd_dice
*dice
= substream
->private_data
;
143 unsigned int source
, rate
;
147 err
= snd_dice_stream_lock_try(dice
);
151 err
= init_hw_info(dice
, substream
);
155 err
= snd_dice_transaction_get_clock_source(dice
, &source
);
159 case CLOCK_SOURCE_AES1
:
160 case CLOCK_SOURCE_AES2
:
161 case CLOCK_SOURCE_AES3
:
162 case CLOCK_SOURCE_AES4
:
163 case CLOCK_SOURCE_AES_ANY
:
164 case CLOCK_SOURCE_ADAT
:
165 case CLOCK_SOURCE_TDIF
:
166 case CLOCK_SOURCE_WC
:
175 * When source of clock is not internal, available sampling rate is
176 * limited at current sampling rate.
179 err
= snd_dice_transaction_get_rate(dice
, &rate
);
182 substream
->runtime
->hw
.rate_min
= rate
;
183 substream
->runtime
->hw
.rate_max
= rate
;
186 snd_pcm_set_sync(substream
);
190 snd_dice_stream_lock_release(dice
);
194 static int pcm_close(struct snd_pcm_substream
*substream
)
196 struct snd_dice
*dice
= substream
->private_data
;
198 snd_dice_stream_lock_release(dice
);
203 static int playback_hw_params(struct snd_pcm_substream
*substream
,
204 struct snd_pcm_hw_params
*hw_params
)
206 struct snd_dice
*dice
= substream
->private_data
;
207 amdtp_stream_set_pcm_format(&dice
->rx_stream
,
208 params_format(hw_params
));
210 return snd_pcm_lib_alloc_vmalloc_buffer(substream
,
211 params_buffer_bytes(hw_params
));
214 static int playback_hw_free(struct snd_pcm_substream
*substream
)
216 struct snd_dice
*dice
= substream
->private_data
;
218 mutex_lock(&dice
->mutex
);
219 snd_dice_stream_stop_duplex(dice
);
220 mutex_unlock(&dice
->mutex
);
222 return snd_pcm_lib_free_vmalloc_buffer(substream
);
225 static int playback_prepare(struct snd_pcm_substream
*substream
)
227 struct snd_dice
*dice
= substream
->private_data
;
230 mutex_lock(&dice
->mutex
);
231 err
= snd_dice_stream_start_duplex(dice
, substream
->runtime
->rate
);
232 mutex_unlock(&dice
->mutex
);
234 amdtp_stream_pcm_prepare(&dice
->rx_stream
);
239 static int playback_trigger(struct snd_pcm_substream
*substream
, int cmd
)
241 struct snd_dice
*dice
= substream
->private_data
;
244 case SNDRV_PCM_TRIGGER_START
:
245 amdtp_stream_pcm_trigger(&dice
->rx_stream
, substream
);
247 case SNDRV_PCM_TRIGGER_STOP
:
248 amdtp_stream_pcm_trigger(&dice
->rx_stream
, NULL
);
257 static snd_pcm_uframes_t
playback_pointer(struct snd_pcm_substream
*substream
)
259 struct snd_dice
*dice
= substream
->private_data
;
261 return amdtp_stream_pcm_pointer(&dice
->rx_stream
);
264 int snd_dice_create_pcm(struct snd_dice
*dice
)
266 static struct snd_pcm_ops playback_ops
= {
269 .ioctl
= snd_pcm_lib_ioctl
,
270 .hw_params
= playback_hw_params
,
271 .hw_free
= playback_hw_free
,
272 .prepare
= playback_prepare
,
273 .trigger
= playback_trigger
,
274 .pointer
= playback_pointer
,
275 .page
= snd_pcm_lib_get_vmalloc_page
,
276 .mmap
= snd_pcm_lib_mmap_vmalloc
,
281 err
= snd_pcm_new(dice
->card
, "DICE", 0, 1, 0, &pcm
);
284 pcm
->private_data
= dice
;
285 strcpy(pcm
->name
, dice
->card
->shortname
);
286 snd_pcm_set_ops(pcm
, SNDRV_PCM_STREAM_PLAYBACK
, &playback_ops
);