/*
* TC Applied Technologies Digital Interface Communications Engine driver
*
* Copyright (c) Clemens Ladisch <clemens@ladisch.de>
* Licensed under the terms of the GNU General Public License, version 2.
*/
#include "dice.h"
MODULE_DESCRIPTION("DICE driver");
MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
MODULE_LICENSE("GPL v2");
const unsigned int snd_dice_rates[SND_DICE_RATES_COUNT] = {
/* mode 0 */
[0] = 32000,
[1] = 44100,
[2] = 48000,
/* mode 1 */
[3] = 88200,
[4] = 96000,
/* mode 2 */
[5] = 176400,
[6] = 192000,
};
static unsigned int rate_to_index(unsigned int rate)
{
unsigned int i;
for (i = 0; i < ARRAY_SIZE(snd_dice_rates); ++i)
if (snd_dice_rates[i] == rate)
return i;
return 0;
}
static unsigned int rate_index_to_mode(unsigned int rate_index)
{
return ((int)rate_index - 1) / 2;
}
static void dice_lock_changed(struct snd_dice *dice)
{
dice->dev_lock_changed = true;
wake_up(&dice->hwdep_wait);
}
static int dice_try_lock(struct snd_dice *dice)
{
int err;
spin_lock_irq(&dice->lock);
if (dice->dev_lock_count < 0) {
err = -EBUSY;
goto out;
}
if (dice->dev_lock_count++ == 0)
dice_lock_changed(dice);
err = 0;
out:
spin_unlock_irq(&dice->lock);
return err;
}
static void dice_unlock(struct snd_dice *dice)
{
spin_lock_irq(&dice->lock);
if (WARN_ON(dice->dev_lock_count <= 0))
goto out;
if (--dice->dev_lock_count == 0)
dice_lock_changed(dice);
out:
spin_unlock_irq(&dice->lock);
}
static int dice_rate_constraint(struct snd_pcm_hw_params *params,
struct snd_pcm_hw_rule *rule)
{
struct snd_dice *dice = rule->private;
const struct snd_interval *channels =
hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_CHANNELS);
struct snd_interval *rate =
hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
struct snd_interval allowed_rates = {
.min = UINT_MAX, .max = 0, .integer = 1
};
unsigned int i, mode;
for (