Commit 44c76a96 authored by Takashi Iwai's avatar Takashi Iwai

Merge branch 'topic/misc' into for-linus

parents dbf117cb c6b76d1f
...@@ -264,7 +264,7 @@ struct snd_pcm_hw_constraint_ratdens { ...@@ -264,7 +264,7 @@ struct snd_pcm_hw_constraint_ratdens {
struct snd_pcm_hw_constraint_list { struct snd_pcm_hw_constraint_list {
unsigned int count; unsigned int count;
unsigned int *list; const unsigned int *list;
unsigned int mask; unsigned int mask;
}; };
...@@ -781,7 +781,8 @@ void snd_interval_muldivk(const struct snd_interval *a, const struct snd_interva ...@@ -781,7 +781,8 @@ void snd_interval_muldivk(const struct snd_interval *a, const struct snd_interva
unsigned int k, struct snd_interval *c); unsigned int k, struct snd_interval *c);
void snd_interval_mulkdiv(const struct snd_interval *a, unsigned int k, void snd_interval_mulkdiv(const struct snd_interval *a, unsigned int k,
const struct snd_interval *b, struct snd_interval *c); const struct snd_interval *b, struct snd_interval *c);
int snd_interval_list(struct snd_interval *i, unsigned int count, unsigned int *list, unsigned int mask); int snd_interval_list(struct snd_interval *i, unsigned int count,
const unsigned int *list, unsigned int mask);
int snd_interval_ratnum(struct snd_interval *i, int snd_interval_ratnum(struct snd_interval *i,
unsigned int rats_count, struct snd_ratnum *rats, unsigned int rats_count, struct snd_ratnum *rats,
unsigned int *nump, unsigned int *denp); unsigned int *nump, unsigned int *denp);
......
/* include/version.h */ /* include/version.h */
#define CONFIG_SND_VERSION "1.0.24" #define CONFIG_SND_VERSION "1.0.25"
#define CONFIG_SND_DATE "" #define CONFIG_SND_DATE ""
...@@ -366,6 +366,8 @@ struct snd_ymfpci { ...@@ -366,6 +366,8 @@ struct snd_ymfpci {
#ifdef CONFIG_PM #ifdef CONFIG_PM
u32 *saved_regs; u32 *saved_regs;
u32 saved_ydsxgr_mode; u32 saved_ydsxgr_mode;
u16 saved_dsxg_legacy;
u16 saved_dsxg_elegacy;
#endif #endif
}; };
......
...@@ -1132,15 +1132,4 @@ static struct i2c_driver onyx_driver = { ...@@ -1132,15 +1132,4 @@ static struct i2c_driver onyx_driver = {
.id_table = onyx_i2c_id, .id_table = onyx_i2c_id,
}; };
static int __init onyx_init(void) module_i2c_driver(onyx_driver);
{
return i2c_add_driver(&onyx_driver);
}
static void __exit onyx_exit(void)
{
i2c_del_driver(&onyx_driver);
}
module_init(onyx_init);
module_exit(onyx_exit);
...@@ -1026,15 +1026,4 @@ static struct i2c_driver tas_driver = { ...@@ -1026,15 +1026,4 @@ static struct i2c_driver tas_driver = {
.id_table = tas_i2c_id, .id_table = tas_i2c_id,
}; };
static int __init tas_init(void) module_i2c_driver(tas_driver);
{
return i2c_add_driver(&tas_driver);
}
static void __exit tas_exit(void)
{
i2c_del_driver(&tas_driver);
}
module_init(tas_init);
module_exit(tas_exit);
...@@ -480,74 +480,104 @@ int snd_card_free(struct snd_card *card) ...@@ -480,74 +480,104 @@ int snd_card_free(struct snd_card *card)
EXPORT_SYMBOL(snd_card_free); EXPORT_SYMBOL(snd_card_free);
static void snd_card_set_id_no_lock(struct snd_card *card, const char *nid) /* retrieve the last word of shortname or longname */
static const char *retrieve_id_from_card_name(const char *name)
{ {
int i, len, idx_flag = 0, loops = SNDRV_CARDS; const char *spos = name;
const char *spos, *src;
char *id;
if (nid == NULL) { while (*name) {
id = card->shortname; if (isspace(*name) && isalnum(name[1]))
spos = src = id; spos = name + 1;
while (*id != '\0') { name++;
if (*id == ' ')
spos = id + 1;
id++;
} }
} else { return spos;
spos = src = nid; }
/* return true if the given id string doesn't conflict any other card ids */
static bool card_id_ok(struct snd_card *card, const char *id)
{
int i;
if (!snd_info_check_reserved_words(id))
return false;
for (i = 0; i < snd_ecards_limit; i++) {
if (snd_cards[i] && snd_cards[i] != card &&
!strcmp(snd_cards[i]->id, id))
return false;
} }
id = card->id; return true;
while (*spos != '\0' && !isalnum(*spos)) }
spos++;
if (isdigit(*spos)) /* copy to card->id only with valid letters from nid */
*id++ = isalpha(src[0]) ? src[0] : 'D'; static void copy_valid_id_string(struct snd_card *card, const char *src,
while (*spos != '\0' && (size_t)(id - card->id) < sizeof(card->id) - 1) { const char *nid)
if (isalnum(*spos)) {
*id++ = *spos; char *id = card->id;
spos++;
while (*nid && !isalnum(*nid))
nid++;
if (isdigit(*nid))
*id++ = isalpha(*src) ? *src : 'D';
while (*nid && (size_t)(id - card->id) < sizeof(card->id) - 1) {
if (isalnum(*nid))
*id++ = *nid;
nid++;
} }
*id = '\0'; *id = 0;
}
/* Set card->id from the given string
* If the string conflicts with other ids, add a suffix to make it unique.
*/
static void snd_card_set_id_no_lock(struct snd_card *card, const char *src,
const char *nid)
{
int len, loops;
bool with_suffix;
bool is_default = false;
char *id;
copy_valid_id_string(card, src, nid);
id = card->id; id = card->id;
if (*id == '\0') again:
/* use "Default" for obviously invalid strings
* ("card" conflicts with proc directories)
*/
if (!*id || !strncmp(id, "card", 4)) {
strcpy(id, "Default"); strcpy(id, "Default");
is_default = true;
while (1) {
if (loops-- == 0) {
snd_printk(KERN_ERR "unable to set card id (%s)\n", id);
strcpy(card->id, card->proc_root->name);
return;
}
if (!snd_info_check_reserved_words(id))
goto __change;
for (i = 0; i < snd_ecards_limit; i++) {
if (snd_cards[i] && !strcmp(snd_cards[i]->id, id))
goto __change;
} }
break;
__change: with_suffix = false;
for (loops = 0; loops < SNDRV_CARDS; loops++) {
if (card_id_ok(card, id))
return; /* OK */
len = strlen(id); len = strlen(id);
if (idx_flag) { if (!with_suffix) {
if (id[len-1] != '9') /* add the "_X" suffix */
id[len-1]++; char *spos = id + len;
else if (len > sizeof(card->id) - 3)
id[len-1] = 'A'; spos = id + sizeof(card->id) - 3;
} else if ((size_t)len <= sizeof(card->id) - 3) { strcpy(spos, "_1");
strcat(id, "_1"); with_suffix = true;
idx_flag++;
} else { } else {
spos = id + len - 2; /* modify the existing suffix */
if ((size_t)len <= sizeof(card->id) - 2) if (id[len - 1] != '9')
spos++; id[len - 1]++;
*(char *)spos++ = '_'; else
*(char *)spos++ = '1'; id[len - 1] = 'A';
*(char *)spos++ = '\0'; }
idx_flag++;
} }
/* fallback to the default id */
if (!is_default) {
*id = 0;
goto again;
} }
/* last resort... */
snd_printk(KERN_ERR "unable to set card id (%s)\n", id);
if (card->proc_root->name)
strcpy(card->id, card->proc_root->name);
} }
/** /**
...@@ -564,7 +594,7 @@ void snd_card_set_id(struct snd_card *card, const char *nid) ...@@ -564,7 +594,7 @@ void snd_card_set_id(struct snd_card *card, const char *nid)
if (card->id[0] != '\0') if (card->id[0] != '\0')
return; return;
mutex_lock(&snd_card_mutex); mutex_lock(&snd_card_mutex);
snd_card_set_id_no_lock(card, nid); snd_card_set_id_no_lock(card, nid, nid);
mutex_unlock(&snd_card_mutex); mutex_unlock(&snd_card_mutex);
} }
EXPORT_SYMBOL(snd_card_set_id); EXPORT_SYMBOL(snd_card_set_id);
...@@ -596,22 +626,12 @@ card_id_store_attr(struct device *dev, struct device_attribute *attr, ...@@ -596,22 +626,12 @@ card_id_store_attr(struct device *dev, struct device_attribute *attr,
memcpy(buf1, buf, copy); memcpy(buf1, buf, copy);
buf1[copy] = '\0'; buf1[copy] = '\0';
mutex_lock(&snd_card_mutex); mutex_lock(&snd_card_mutex);
if (!snd_info_check_reserved_words(buf1)) { if (!card_id_ok(NULL, buf1)) {
__exist:
mutex_unlock(&snd_card_mutex); mutex_unlock(&snd_card_mutex);
return -EEXIST; return -EEXIST;
} }
for (idx = 0; idx < snd_ecards_limit; idx++) {
if (snd_cards[idx] && !strcmp(snd_cards[idx]->id, buf1)) {
if (card == snd_cards[idx])
goto __ok;
else
goto __exist;
}
}
strcpy(card->id, buf1); strcpy(card->id, buf1);
snd_info_card_id_change(card); snd_info_card_id_change(card);
__ok:
mutex_unlock(&snd_card_mutex); mutex_unlock(&snd_card_mutex);
return count; return count;
...@@ -665,7 +685,18 @@ int snd_card_register(struct snd_card *card) ...@@ -665,7 +685,18 @@ int snd_card_register(struct snd_card *card)
mutex_unlock(&snd_card_mutex); mutex_unlock(&snd_card_mutex);
return 0; return 0;
} }
snd_card_set_id_no_lock(card, card->id[0] == '\0' ? NULL : card->id); if (*card->id) {
/* make a unique id name from the given string */
char tmpid[sizeof(card->id)];
memcpy(tmpid, card->id, sizeof(card->id));
snd_card_set_id_no_lock(card, tmpid, tmpid);
} else {
/* create an id from either shortname or longname */
const char *src;
src = *card->shortname ? card->shortname : card->longname;
snd_card_set_id_no_lock(card, src,
retrieve_id_from_card_name(src));
}
snd_cards[card->number] = card; snd_cards[card->number] = card;
mutex_unlock(&snd_card_mutex); mutex_unlock(&snd_card_mutex);
init_info_for_card(card); init_info_for_card(card);
......
...@@ -1029,7 +1029,8 @@ static int snd_interval_ratden(struct snd_interval *i, ...@@ -1029,7 +1029,8 @@ static int snd_interval_ratden(struct snd_interval *i,
* *
* Returns non-zero if the value is changed, zero if not changed. * Returns non-zero if the value is changed, zero if not changed.
*/ */
int snd_interval_list(struct snd_interval *i, unsigned int count, unsigned int *list, unsigned int mask) int snd_interval_list(struct snd_interval *i, unsigned int count,
const unsigned int *list, unsigned int mask)
{ {
unsigned int k; unsigned int k;
struct snd_interval list_range; struct snd_interval list_range;
......
...@@ -1586,12 +1586,18 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd) ...@@ -1586,12 +1586,18 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
struct file *file; struct file *file;
struct snd_pcm_file *pcm_file; struct snd_pcm_file *pcm_file;
struct snd_pcm_substream *substream1; struct snd_pcm_substream *substream1;
struct snd_pcm_group *group;
file = snd_pcm_file_fd(fd); file = snd_pcm_file_fd(fd);
if (!file) if (!file)
return -EBADFD; return -EBADFD;
pcm_file = file->private_data; pcm_file = file->private_data;
substream1 = pcm_file->substream; substream1 = pcm_file->substream;
group = kmalloc(sizeof(*group), GFP_KERNEL);
if (!group) {
res = -ENOMEM;
goto _nolock;
}
down_write(&snd_pcm_link_rwsem); down_write(&snd_pcm_link_rwsem);
write_lock_irq(&snd_pcm_link_rwlock); write_lock_irq(&snd_pcm_link_rwlock);
if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN || if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN ||
...@@ -1604,11 +1610,7 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd) ...@@ -1604,11 +1610,7 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
goto _end; goto _end;
} }
if (!snd_pcm_stream_linked(substream)) { if (!snd_pcm_stream_linked(substream)) {
substream->group = kmalloc(sizeof(struct snd_pcm_group), GFP_ATOMIC); substream->group = group;
if (substream->group == NULL) {
res = -ENOMEM;
goto _end;
}
spin_lock_init(&substream->group->lock); spin_lock_init(&substream->group->lock);
INIT_LIST_HEAD(&substream->group->substreams); INIT_LIST_HEAD(&substream->group->substreams);
list_add_tail(&substream->link_list, &substream->group->substreams); list_add_tail(&substream->link_list, &substream->group->substreams);
...@@ -1620,7 +1622,10 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd) ...@@ -1620,7 +1622,10 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
_end: _end:
write_unlock_irq(&snd_pcm_link_rwlock); write_unlock_irq(&snd_pcm_link_rwlock);
up_write(&snd_pcm_link_rwsem); up_write(&snd_pcm_link_rwsem);
_nolock:
fput(file); fput(file);
if (res < 0)
kfree(group);
return res; return res;
} }
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
#include <sound/mpu401.h> #include <sound/mpu401.h>
#include <sound/hwdep.h> #include <sound/hwdep.h>
#include <sound/ac97_codec.h> #include <sound/ac97_codec.h>
#include <sound/tlv.h>
#endif #endif
#ifndef CHIP_AU8820 #ifndef CHIP_AU8820
...@@ -107,6 +107,14 @@ ...@@ -107,6 +107,14 @@
#define NR_WTPB 0x20 /* WT channels per each bank. */ #define NR_WTPB 0x20 /* WT channels per each bank. */
#define NR_PCM 0x10 #define NR_PCM 0x10
struct pcm_vol {
struct snd_kcontrol *kctl;
int active;
int dma;
int mixin[4];
int vol[4];
};
/* Structs */ /* Structs */
typedef struct { typedef struct {
//int this_08; /* Still unknown */ //int this_08; /* Still unknown */
...@@ -168,6 +176,7 @@ struct snd_vortex { ...@@ -168,6 +176,7 @@ struct snd_vortex {
/* Xtalk canceler */ /* Xtalk canceler */
int xt_mode; /* 1: speakers, 0:headphones. */ int xt_mode; /* 1: speakers, 0:headphones. */
#endif #endif
struct pcm_vol pcm_vol[NR_PCM];
int isquad; /* cache of extended ID codec flag. */ int isquad; /* cache of extended ID codec flag. */
...@@ -239,7 +248,7 @@ static int vortex_alsafmt_aspfmt(int alsafmt); ...@@ -239,7 +248,7 @@ static int vortex_alsafmt_aspfmt(int alsafmt);
/* Connection stuff. */ /* Connection stuff. */
static void vortex_connect_default(vortex_t * vortex, int en); static void vortex_connect_default(vortex_t * vortex, int en);
static int vortex_adb_allocroute(vortex_t * vortex, int dma, int nr_ch, static int vortex_adb_allocroute(vortex_t * vortex, int dma, int nr_ch,
int dir, int type); int dir, int type, int subdev);
static char vortex_adb_checkinout(vortex_t * vortex, int resmap[], int out, static char vortex_adb_checkinout(vortex_t * vortex, int resmap[], int out,
int restype); int restype);
#ifndef CHIP_AU8810 #ifndef CHIP_AU8810
......
...@@ -2050,8 +2050,6 @@ vortex_adb_checkinout(vortex_t * vortex, int resmap[], int out, int restype) ...@@ -2050,8 +2050,6 @@ vortex_adb_checkinout(vortex_t * vortex, int resmap[], int out, int restype)
} }
/* Default Connections */ /* Default Connections */
static int
vortex_adb_allocroute(vortex_t * vortex, int dma, int nr_ch, int dir, int type);
static void vortex_connect_default(vortex_t * vortex, int en) static void vortex_connect_default(vortex_t * vortex, int en)
{ {
...@@ -2111,14 +2109,12 @@ static void vortex_connect_default(vortex_t * vortex, int en) ...@@ -2111,14 +2109,12 @@ static void vortex_connect_default(vortex_t * vortex, int en)
Return: Return allocated DMA or same DMA passed as "dma" when dma >= 0. Return: Return allocated DMA or same DMA passed as "dma" when dma >= 0.
*/ */
static int static int
vortex_adb_allocroute(vortex_t * vortex, int dma, int nr_ch, int dir, int type) vortex_adb_allocroute(vortex_t *vortex, int dma, int nr_ch, int dir,
int type, int subdev)
{ {
stream_t *stream; stream_t *stream;
int i, en; int i, en;
struct pcm_vol *p;
if ((nr_ch == 3)
|| ((dir == SNDRV_PCM_STREAM_CAPTURE) && (nr_ch > 2)))
return -EBUSY;
if (dma >= 0) { if (dma >= 0) {
en = 0; en = 0;
...@@ -2250,6 +2246,14 @@ vortex_adb_allocroute(vortex_t * vortex, int dma, int nr_ch, int dir, int type) ...@@ -2250,6 +2246,14 @@ vortex_adb_allocroute(vortex_t * vortex, int dma, int nr_ch, int dir, int type)
MIX_DEFIGAIN); MIX_DEFIGAIN);
#endif #endif
} }
if (stream->type == VORTEX_PCM_ADB && en) {
p = &vortex->pcm_vol[subdev];
p->dma = dma;
for (i = 0; i < nr_ch; i++)
p->mixin[i] = mix[i];
for (i = 0; i < ch_top; i++)
p->vol[i] = 0;
}
} }
#ifndef CHIP_AU8820 #ifndef CHIP_AU8820
else { else {
...@@ -2473,7 +2477,7 @@ static irqreturn_t vortex_interrupt(int irq, void *dev_id) ...@@ -2473,7 +2477,7 @@ static irqreturn_t vortex_interrupt(int irq, void *dev_id)
hwread(vortex->mmio, VORTEX_IRQ_STAT); hwread(vortex->mmio, VORTEX_IRQ_STAT);
handled = 1; handled = 1;
} }
if (source & IRQ_MIDI) { if ((source & IRQ_MIDI) && vortex->rmidi) {
snd_mpu401_uart_interrupt(vortex->irq, snd_mpu401_uart_interrupt(vortex->irq,
vortex->rmidi->private_data); vortex->rmidi->private_data);
handled = 1; handled = 1;
......
...@@ -122,6 +122,18 @@ static struct snd_pcm_hw_constraint_list hw_constraints_au8830_channels = { ...@@ -122,6 +122,18 @@ static struct snd_pcm_hw_constraint_list hw_constraints_au8830_channels = {
.mask = 0, .mask = 0,
}; };
#endif #endif
static void vortex_notify_pcm_vol_change(struct snd_card *card,
struct snd_kcontrol *kctl, int activate)
{
if (activate)
kctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
else
kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE |
SNDRV_CTL_EVENT_MASK_INFO, &(kctl->id));
}
/* open callback */ /* open callback */
static int snd_vortex_pcm_open(struct snd_pcm_substream *substream) static int snd_vortex_pcm_open(struct snd_pcm_substream *substream)
{ {
...@@ -230,12 +242,14 @@ snd_vortex_pcm_hw_params(struct snd_pcm_substream *substream, ...@@ -230,12 +242,14 @@ snd_vortex_pcm_hw_params(struct snd_pcm_substream *substream,
if (stream != NULL) if (stream != NULL)
vortex_adb_allocroute(chip, stream->dma, vortex_adb_allocroute(chip, stream->dma,
stream->nr_ch, stream->dir, stream->nr_ch, stream->dir,
stream->type); stream->type,
substream->number);
/* Alloc routes. */ /* Alloc routes. */
dma = dma =
vortex_adb_allocroute(chip, -1, vortex_adb_allocroute(chip, -1,
params_channels(hw_params), params_channels(hw_params),
substream->stream, type); substream->stream, type,
substream->number);
if (dma < 0) { if (dma < 0) {
spin_unlock_irq(&chip->lock); spin_unlock_irq(&chip->lock);
return dma; return dma;
...@@ -246,6 +260,11 @@ snd_vortex_pcm_hw_params(struct snd_pcm_substream *substream, ...@@ -246,6 +260,11 @@ snd_vortex_pcm_hw_params(struct snd_pcm_substream *substream,
vortex_adbdma_setbuffers(chip, dma, vortex_adbdma_setbuffers(chip, dma,
params_period_bytes(hw_params), params_period_bytes(hw_params),
params_periods(hw_params)); params_periods(hw_params));
if (VORTEX_PCM_TYPE(substream->pcm) == VORTEX_PCM_ADB) {
chip->pcm_vol[substream->number].active = 1;
vortex_notify_pcm_vol_change(chip->card,
chip->pcm_vol[substream->number].kctl, 1);
}
} }
#ifndef CHIP_AU8810 #ifndef CHIP_AU8810
else { else {
...@@ -275,10 +294,18 @@ static int snd_vortex_pcm_hw_free(struct snd_pcm_substream *substream) ...@@ -275,10 +294,18 @@ static int snd_vortex_pcm_hw_free(struct snd_pcm_substream *substream)
spin_lock_irq(&chip->lock); spin_lock_irq(&chip->lock);
// Delete audio routes. // Delete audio routes.
if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT) { if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT) {
if (stream != NULL) if (stream != NULL) {
if (VORTEX_PCM_TYPE(substream->pcm) == VORTEX_PCM_ADB) {
chip->pcm_vol[substream->number].active = 0;
vortex_notify_pcm_vol_change(chip->card,
chip->pcm_vol[substream->number].kctl,
0);
}
vortex_adb_allocroute(chip, stream->dma, vortex_adb_allocroute(chip, stream->dma,
stream->nr_ch, stream->dir, stream->nr_ch, stream->dir,
stream->type); stream->type,
substream->number);
}
} }
#ifndef CHIP_AU8810 #ifndef CHIP_AU8810
else { else {
...@@ -506,6 +533,83 @@ static struct snd_kcontrol_new snd_vortex_mixer_spdif[] __devinitdata = { ...@@ -506,6 +533,83 @@ static struct snd_kcontrol_new snd_vortex_mixer_spdif[] __devinitdata = {
}, },
}; };
/* subdevice PCM Volume control */
static int snd_vortex_pcm_vol_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
vortex_t *vortex = snd_kcontrol_chip(kcontrol);
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = (VORTEX_IS_QUAD(vortex) ? 4 : 2);
uinfo->value.integer.min = -128;
uinfo->value.integer.max = 32;
return 0;
}
static int snd_vortex_pcm_vol_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
int i;
vortex_t *vortex = snd_kcontrol_chip(kcontrol);
int subdev = kcontrol->id.subdevice;
struct pcm_vol *p = &vortex->pcm_vol[subdev];
int max_chn = (VORTEX_IS_QUAD(vortex) ? 4 : 2);
for (i = 0; i < max_chn; i++)
ucontrol->value.integer.value[i] = p->vol[i];
return 0;
}
static int snd_vortex_pcm_vol_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
int i;
int changed = 0;
int mixin;
unsigned char vol;
vortex_t *vortex = snd_kcontrol_chip(kcontrol);
int subdev = kcontrol->id.subdevice;
struct pcm_vol *p = &vortex->pcm_vol[subdev];
int max_chn = (VORTEX_IS_QUAD(vortex) ? 4 : 2);
for (i = 0; i < max_chn; i++) {
if (p->vol[i] != ucontrol->value.integer.value[i]) {
p->vol[i] = ucontrol->value.integer.value[i];
if (p->active) {
switch (vortex->dma_adb[p->dma].nr_ch) {
case 1:
mixin = p->mixin[0];
break;
case 2:
default:
mixin = p->mixin[(i < 2) ? i : (i - 2)];
break;
case 4:
mixin = p->mixin[i];
break;
};
vol = p->vol[i];
vortex_mix_setinputvolumebyte(vortex,
vortex->mixplayb[i], mixin, vol);
}
changed = 1;
}
}
return changed;
}
static const DECLARE_TLV_DB_MINMAX(vortex_pcm_vol_db_scale, -9600, 2400);
static struct snd_kcontrol_new snd_vortex_pcm_vol __devinitdata = {
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = "PCM Playback Volume",
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
SNDRV_CTL_ELEM_ACCESS_TLV_READ |
SNDRV_CTL_ELEM_ACCESS_INACTIVE,
.info = snd_vortex_pcm_vol_info,
.get = snd_vortex_pcm_vol_get,
.put = snd_vortex_pcm_vol_put,
.tlv = { .p = vortex_pcm_vol_db_scale },
};
/* create a pcm device */ /* create a pcm device */
static int __devinit snd_vortex_new_pcm(vortex_t *chip, int idx, int nr) static int __devinit snd_vortex_new_pcm(vortex_t *chip, int idx, int nr)
{ {
...@@ -555,5 +659,20 @@ static int __devinit snd_vortex_new_pcm(vortex_t *chip, int idx, int nr) ...@@ -555,5 +659,20 @@ static int __devinit snd_vortex_new_pcm(vortex_t *chip, int idx, int nr)
return err; return err;
} }
} }
if (VORTEX_PCM_TYPE(pcm) == VORTEX_PCM_ADB) {
for (i = 0; i < NR_PCM; i++) {
chip->pcm_vol[i].active = 0;
chip->pcm_vol[i].dma = -1;
kctl = snd_ctl_new1(&snd_vortex_pcm_vol, chip);
if (!kctl)
return -ENOMEM;
chip->pcm_vol[i].kctl = kctl;
kctl->id.device = 0;
kctl->id.subdevice = i;
err = snd_ctl_add(chip->card, kctl);
if (err < 0)
return err;
}
}
return 0; return 0;
} }
...@@ -36,7 +36,7 @@ get_vm_block(struct ct_vm *vm, unsigned int size) ...@@ -36,7 +36,7 @@ get_vm_block(struct ct_vm *vm, unsigned int size)
size = CT_PAGE_ALIGN(size); size = CT_PAGE_ALIGN(size);
if (size > vm->size) { if (size > vm->size) {
printk(KERN_ERR "ctxfi: Fail! No sufficient device virtural " printk(KERN_ERR "ctxfi: Fail! No sufficient device virtual "
"memory space available!\n"); "memory space available!\n");
return NULL; return NULL;
} }
......
...@@ -1013,6 +1013,25 @@ static int set_rate_constraints(struct snd_ice1712 *ice, ...@@ -1013,6 +1013,25 @@ static int set_rate_constraints(struct snd_ice1712 *ice,
ice->hw_rates); ice->hw_rates);
} }
/* if the card has the internal rate locked (is_pro_locked), limit runtime
hw rates to the current internal rate only.
*/
static void constrain_rate_if_locked(struct snd_pcm_substream *substream)
{
struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
struct snd_pcm_runtime *runtime = substream->runtime;
unsigned int rate;
if (is_pro_rate_locked(ice)) {
rate = ice->get_rate(ice);
if (rate >= runtime->hw.rate_min
&& rate <= runtime->hw.rate_max) {
runtime->hw.rate_min = rate;
runtime->hw.rate_max = rate;
}
}
}
/* multi-channel playback needs alignment 8x32bit regardless of the channels /* multi-channel playback needs alignment 8x32bit regardless of the channels
* actually used * actually used
*/ */
...@@ -1046,6 +1065,7 @@ static int snd_vt1724_playback_pro_open(struct snd_pcm_substream *substream) ...@@ -1046,6 +1065,7 @@ static int snd_vt1724_playback_pro_open(struct snd_pcm_substream *substream)
VT1724_BUFFER_ALIGN); VT1724_BUFFER_ALIGN);
snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
VT1724_BUFFER_ALIGN); VT1724_BUFFER_ALIGN);
constrain_rate_if_locked(substream);
if (ice->pro_open) if (ice->pro_open)
ice->pro_open(ice, substream); ice->pro_open(ice, substream);
return 0; return 0;
...@@ -1066,6 +1086,7 @@ static int snd_vt1724_capture_pro_open(struct snd_pcm_substream *substream) ...@@ -1066,6 +1086,7 @@ static int snd_vt1724_capture_pro_open(struct snd_pcm_substream *substream)
VT1724_BUFFER_ALIGN); VT1724_BUFFER_ALIGN);
snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
VT1724_BUFFER_ALIGN); VT1724_BUFFER_ALIGN);
constrain_rate_if_locked(substream);
if (ice->pro_open) if (ice->pro_open)
ice->pro_open(ice, substream); ice->pro_open(ice, substream);
return 0; return 0;
...@@ -1215,6 +1236,7 @@ static int snd_vt1724_playback_spdif_open(struct snd_pcm_substream *substream) ...@@ -1215,6 +1236,7 @@ static int snd_vt1724_playback_spdif_open(struct snd_pcm_substream *substream)
VT1724_BUFFER_ALIGN); VT1724_BUFFER_ALIGN);
snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
VT1724_BUFFER_ALIGN); VT1724_BUFFER_ALIGN);
constrain_rate_if_locked(substream);
if (ice->spdif.ops.open) if (ice->spdif.ops.open)
ice->spdif.ops.open(ice, substream); ice->spdif.ops.open(ice, substream);
return 0; return 0;
...@@ -1251,6 +1273,7 @@ static int snd_vt1724_capture_spdif_open(struct snd_pcm_substream *substream) ...@@ -1251,6 +1273,7 @@ static int snd_vt1724_capture_spdif_open(struct snd_pcm_substream *substream)
VT1724_BUFFER_ALIGN); VT1724_BUFFER_ALIGN);
snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
VT1724_BUFFER_ALIGN); VT1724_BUFFER_ALIGN);
constrain_rate_if_locked(substream);
if (ice->spdif.ops.open) if (ice->spdif.ops.open)
ice->spdif.ops.open(ice, substream); ice->spdif.ops.open(ice, substream);
return 0; return 0;
......
...@@ -2317,6 +2317,10 @@ int snd_ymfpci_suspend(struct pci_dev *pci, pm_message_t state) ...@@ -2317,6 +2317,10 @@ int snd_ymfpci_suspend(struct pci_dev *pci, pm_message_t state)
for (i = 0; i < YDSXGR_NUM_SAVED_REGS; i++) for (i = 0; i < YDSXGR_NUM_SAVED_REGS; i++)
chip->saved_regs[i] = snd_ymfpci_readl(chip, saved_regs_index[i]); chip->saved_regs[i] = snd_ymfpci_readl(chip, saved_regs_index[i]);
chip->saved_ydsxgr_mode = snd_ymfpci_readl(chip, YDSXGR_MODE); chip->saved_ydsxgr_mode = snd_ymfpci_readl(chip, YDSXGR_MODE);
pci_read_config_word(chip->pci, PCIR_DSXG_LEGACY,
&chip->saved_dsxg_legacy);
pci_read_config_word(chip->pci, PCIR_DSXG_ELEGACY,
&chip->saved_dsxg_elegacy);
snd_ymfpci_writel(chip, YDSXGR_NATIVEDACOUTVOL, 0); snd_ymfpci_writel(chip, YDSXGR_NATIVEDACOUTVOL, 0);
snd_ymfpci_writel(chip, YDSXGR_BUF441OUTVOL, 0); snd_ymfpci_writel(chip, YDSXGR_BUF441OUTVOL, 0);
snd_ymfpci_disable_dsp(chip); snd_ymfpci_disable_dsp(chip);
...@@ -2351,6 +2355,11 @@ int snd_ymfpci_resume(struct pci_dev *pci) ...@@ -2351,6 +2355,11 @@ int snd_ymfpci_resume(struct pci_dev *pci)
snd_ac97_resume(chip->ac97); snd_ac97_resume(chip->ac97);
pci_write_config_word(chip->pci, PCIR_DSXG_LEGACY,
chip->saved_dsxg_legacy);
pci_write_config_word(chip->pci, PCIR_DSXG_ELEGACY,
chip->saved_dsxg_elegacy);
/* start hw again */ /* start hw again */
if (chip->start_count > 0) { if (chip->start_count > 0) {
spin_lock_irq(&chip->reg_lock); spin_lock_irq(&chip->reg_lock);
......
...@@ -1112,17 +1112,7 @@ static struct spi_driver at73c213_driver = { ...@@ -1112,17 +1112,7 @@ static struct spi_driver at73c213_driver = {
.remove = __devexit_p(snd_at73c213_remove), .remove = __devexit_p(snd_at73c213_remove),
}; };
static int __init at73c213_init(void) module_spi_driver(at73c213_driver);
{
return spi_register_driver(&at73c213_driver);
}
module_init(at73c213_init);
static void __exit at73c213_exit(void)
{
spi_unregister_driver(&at73c213_driver);
}
module_exit(at73c213_exit);
MODULE_AUTHOR("Hans-Christian Egtvedt <egtvedt@samfundet.no>"); MODULE_AUTHOR("Hans-Christian Egtvedt <egtvedt@samfundet.no>");
MODULE_DESCRIPTION("Sound driver for AT73C213 with Atmel SSC"); MODULE_DESCRIPTION("Sound driver for AT73C213 with Atmel SSC");
......
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
* *
* Author: Torsten Schenk <torsten.schenk@zoho.com> * Author: Torsten Schenk <torsten.schenk@zoho.com>
* Created: Jan 01, 2011 * Created: Jan 01, 2011
* Version: 0.3.0
* Copyright: (C) Torsten Schenk * Copyright: (C) Torsten Schenk
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -29,7 +28,7 @@ ...@@ -29,7 +28,7 @@
#include <sound/initval.h> #include <sound/initval.h>
MODULE_AUTHOR("Torsten Schenk <torsten.schenk@zoho.com>"); MODULE_AUTHOR("Torsten Schenk <torsten.schenk@zoho.com>");
MODULE_DESCRIPTION("TerraTec DMX 6Fire USB audio driver, version 0.3.0"); MODULE_DESCRIPTION("TerraTec DMX 6Fire USB audio driver");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
MODULE_SUPPORTED_DEVICE("{{TerraTec, DMX 6Fire USB}}"); MODULE_SUPPORTED_DEVICE("{{TerraTec, DMX 6Fire USB}}");
......
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
* *
* Author: Torsten Schenk <torsten.schenk@zoho.com> * Author: Torsten Schenk <torsten.schenk@zoho.com>
* Created: Jan 01, 2011 * Created: Jan 01, 2011
* Version: 0.3.0
* Copyright: (C) Torsten Schenk * Copyright: (C) Torsten Schenk
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
* *
* Author: Torsten Schenk <torsten.schenk@zoho.com> * Author: Torsten Schenk <torsten.schenk@zoho.com>
* Created: Jan 01, 2011 * Created: Jan 01, 2011
* Version: 0.3.0
* Copyright: (C) Torsten Schenk * Copyright: (C) Torsten Schenk
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
* *
* Author: Torsten Schenk <torsten.schenk@zoho.com> * Author: Torsten Schenk <torsten.schenk@zoho.com>
* Created: Jan 01, 2011 * Created: Jan 01, 2011
* Version: 0.3.0
* Copyright: (C) Torsten Schenk * Copyright: (C) Torsten Schenk
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
* *
* Author: Torsten Schenk <torsten.schenk@zoho.com> * Author: Torsten Schenk <torsten.schenk@zoho.com>
* Created: Jan 01, 2011 * Created: Jan 01, 2011
* Version: 0.3.0
* Copyright: (C) Torsten Schenk * Copyright: (C) Torsten Schenk
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
This diff is collapsed.
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
* *
* Author: Torsten Schenk <torsten.schenk@zoho.com> * Author: Torsten Schenk <torsten.schenk@zoho.com>
* Created: Jan 01, 2011 * Created: Jan 01, 2011
* Version: 0.3.0
* Copyright: (C) Torsten Schenk * Copyright: (C) Torsten Schenk
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -44,7 +43,11 @@ struct control_runtime { ...@@ -44,7 +43,11 @@ struct control_runtime {
bool line_phono_switch; bool line_phono_switch;
bool digital_thru_switch; bool digital_thru_switch;
bool usb_streaming; bool usb_streaming;
u8 master_vol; u8 output_vol[6];
u8 ovol_updated;
u8 output_mute;
s8 input_vol[2];
u8 ivol_updated;
}; };
int __devinit usb6fire_control_init(struct sfire_chip *chip); int __devinit usb6fire_control_init(struct sfire_chip *chip);
......
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
* *
* Author: Torsten Schenk <torsten.schenk@zoho.com> * Author: Torsten Schenk <torsten.schenk@zoho.com>
* Created: Jan 01, 2011 * Created: Jan 01, 2011
* Version: 0.3.0
* Copyright: (C) Torsten Schenk * Copyright: (C) Torsten Schenk
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
* *
* Author: Torsten Schenk <torsten.schenk@zoho.com> * Author: Torsten Schenk <torsten.schenk@zoho.com>
* Created: Jan 01, 2011 * Created: Jan 01, 2011
* Version: 0.3.0
* Copyright: (C) Torsten Schenk * Copyright: (C) Torsten Schenk
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
* *
* Author: Torsten Schenk <torsten.schenk@zoho.com> * Author: Torsten Schenk <torsten.schenk@zoho.com>
* Created: Jan 01, 2011 * Created: Jan 01, 2011
* Version: 0.3.0
* Copyright: (C) Torsten Schenk * Copyright: (C) Torsten Schenk
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
* *
* Author: Torsten Schenk <torsten.schenk@zoho.com> * Author: Torsten Schenk <torsten.schenk@zoho.com>
* Created: Jan 01, 2011 * Created: Jan 01, 2011
* Version: 0.3.0
* Copyright: (C) Torsten Schenk * Copyright: (C) Torsten Schenk
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
* *
* Author: Torsten Schenk <torsten.schenk@zoho.com> * Author: Torsten Schenk <torsten.schenk@zoho.com>
* Created: Jan 01, 2011 * Created: Jan 01, 2011
* Version: 0.3.0
* Copyright: (C) Torsten Schenk * Copyright: (C) Torsten Schenk
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
...@@ -106,6 +106,7 @@ config SND_USB_6FIRE ...@@ -106,6 +106,7 @@ config SND_USB_6FIRE
select BITREVERSE select BITREVERSE
select SND_RAWMIDI select SND_RAWMIDI
select SND_PCM select SND_PCM
select SND_VMASTER
help help
Say Y here to include support for TerraTec 6fire DMX USB interface. Say Y here to include support for TerraTec 6fire DMX USB interface.
......
...@@ -695,6 +695,7 @@ static int snd_usb_pcm_check_knot(struct snd_pcm_runtime *runtime, ...@@ -695,6 +695,7 @@ static int snd_usb_pcm_check_knot(struct snd_pcm_runtime *runtime,
struct snd_usb_substream *subs) struct snd_usb_substream *subs)
{ {
struct audioformat *fp; struct audioformat *fp;
int *rate_list;
int count = 0, needs_knot = 0; int count = 0, needs_knot = 0;
int err; int err;
...@@ -708,7 +709,8 @@ static int snd_usb_pcm_check_knot(struct snd_pcm_runtime *runtime, ...@@ -708,7 +709,8 @@ static int snd_usb_pcm_check_knot(struct snd_pcm_runtime *runtime,
if (!needs_knot) if (!needs_knot)
return 0; return 0;
subs->rate_list.list = kmalloc(sizeof(int) * count, GFP_KERNEL); subs->rate_list.list = rate_list =
kmalloc(sizeof(int) * count, GFP_KERNEL);
if (!subs->rate_list.list) if (!subs->rate_list.list)
return -ENOMEM; return -ENOMEM;
subs->rate_list.count = count; subs->rate_list.count = count;
...@@ -717,7 +719,7 @@ static int snd_usb_pcm_check_knot(struct snd_pcm_runtime *runtime, ...@@ -717,7 +719,7 @@ static int snd_usb_pcm_check_knot(struct snd_pcm_runtime *runtime,
list_for_each_entry(fp, &subs->fmt_list, list) { list_for_each_entry(fp, &subs->fmt_list, list) {
int i; int i;
for (i = 0; i < fp->nr_rates; i++) for (i = 0; i < fp->nr_rates; i++)
subs->rate_list.list[count++] = fp->rate_table[i]; rate_list[count++] = fp->rate_table[i];
} }
err = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, err = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
&subs->rate_list); &subs->rate_list);
......
...@@ -80,7 +80,7 @@ static int usX2Y_urb_capt_retire(struct snd_usX2Y_substream *subs) ...@@ -80,7 +80,7 @@ static int usX2Y_urb_capt_retire(struct snd_usX2Y_substream *subs)
cp = (unsigned char*)urb->transfer_buffer + urb->iso_frame_desc[i].offset; cp = (unsigned char*)urb->transfer_buffer + urb->iso_frame_desc[i].offset;
if (urb->iso_frame_desc[i].status) { /* active? hmm, skip this */ if (urb->iso_frame_desc[i].status) { /* active? hmm, skip this */
snd_printk(KERN_ERR "active frame status %i. " snd_printk(KERN_ERR "active frame status %i. "
"Most propably some hardware problem.\n", "Most probably some hardware problem.\n",
urb->iso_frame_desc[i].status); urb->iso_frame_desc[i].status);
return urb->iso_frame_desc[i].status; return urb->iso_frame_desc[i].status;
} }
...@@ -300,7 +300,7 @@ static void usX2Y_error_sequence(struct usX2Ydev *usX2Y, ...@@ -300,7 +300,7 @@ static void usX2Y_error_sequence(struct usX2Ydev *usX2Y,
{ {
snd_printk(KERN_ERR snd_printk(KERN_ERR
"Sequence Error!(hcd_frame=%i ep=%i%s;wait=%i,frame=%i).\n" "Sequence Error!(hcd_frame=%i ep=%i%s;wait=%i,frame=%i).\n"
"Most propably some urb of usb-frame %i is still missing.\n" "Most probably some urb of usb-frame %i is still missing.\n"
"Cause could be too long delays in usb-hcd interrupt handling.\n", "Cause could be too long delays in usb-hcd interrupt handling.\n",
usb_get_current_frame_number(usX2Y->dev), usb_get_current_frame_number(usX2Y->dev),
subs->endpoint, usb_pipein(urb->pipe) ? "in" : "out", subs->endpoint, usb_pipein(urb->pipe) ? "in" : "out",
......
...@@ -74,7 +74,7 @@ static int usX2Y_usbpcm_urb_capt_retire(struct snd_usX2Y_substream *subs) ...@@ -74,7 +74,7 @@ static int usX2Y_usbpcm_urb_capt_retire(struct snd_usX2Y_substream *subs)
} }
for (i = 0; i < nr_of_packs(); i++) { for (i = 0; i < nr_of_packs(); i++) {
if (urb->iso_frame_desc[i].status) { /* active? hmm, skip this */ if (urb->iso_frame_desc[i].status) { /* active? hmm, skip this */
snd_printk(KERN_ERR "activ frame status %i. Most propably some hardware problem.\n", urb->iso_frame_desc[i].status); snd_printk(KERN_ERR "active frame status %i. Most probably some hardware problem.\n", urb->iso_frame_desc[i].status);
return urb->iso_frame_desc[i].status; return urb->iso_frame_desc[i].status;
} }
lens += urb->iso_frame_desc[i].actual_length / usX2Y->stride; lens += urb->iso_frame_desc[i].actual_length / usX2Y->stride;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment