Commit a673e746 authored by Jaroslav Kysela's avatar Jaroslav Kysela

ALSA update

  - Moved initialization of card->id to card_register() function.
    The new default id is composed from the shortname given by driver.
  - ES18xx - Fixed power management defines
  - VIA82xx - The SG table is build inside hw_params (outside spinlock - memory allocation).
parent 1c033b99
...@@ -130,8 +130,9 @@ void snd_info_free_device(snd_info_entry_t * entry); ...@@ -130,8 +130,9 @@ void snd_info_free_device(snd_info_entry_t * entry);
int snd_info_store_text(snd_info_entry_t * entry); int snd_info_store_text(snd_info_entry_t * entry);
int snd_info_restore_text(snd_info_entry_t * entry); int snd_info_restore_text(snd_info_entry_t * entry);
int snd_info_card_create(snd_card_t * card);
int snd_info_card_register(snd_card_t * card); int snd_info_card_register(snd_card_t * card);
int snd_info_card_unregister(snd_card_t * card); int snd_info_card_free(snd_card_t * card);
int snd_info_register(snd_info_entry_t * entry); int snd_info_register(snd_info_entry_t * entry);
int snd_info_unregister(snd_info_entry_t * entry); int snd_info_unregister(snd_info_entry_t * entry);
......
...@@ -699,12 +699,10 @@ int __exit snd_info_done(void) ...@@ -699,12 +699,10 @@ int __exit snd_info_done(void)
*/ */
int snd_info_card_register(snd_card_t * card) int snd_info_card_create(snd_card_t * card)
{ {
char str[8]; char str[8];
char *s;
snd_info_entry_t *entry; snd_info_entry_t *entry;
struct proc_dir_entry *p;
snd_assert(card != NULL, return -ENXIO); snd_assert(card != NULL, return -ENXIO);
...@@ -717,11 +715,20 @@ int snd_info_card_register(snd_card_t * card) ...@@ -717,11 +715,20 @@ int snd_info_card_register(snd_card_t * card)
return -ENOMEM; return -ENOMEM;
} }
card->proc_root = entry; card->proc_root = entry;
return 0;
}
int snd_info_card_register(snd_card_t * card)
{
char *s;
struct proc_dir_entry *p;
snd_assert(card != NULL, return -ENXIO);
if (!strcmp(card->id, str)) if (!strcmp(card->id, card->proc_root->name))
return 0; return 0;
s = snd_kmalloc_strdup(str, GFP_KERNEL); s = snd_kmalloc_strdup(card->proc_root->name, GFP_KERNEL);
if (s == NULL) if (s == NULL)
return -ENOMEM; return -ENOMEM;
p = snd_create_proc_entry(card->id, S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO, snd_proc_root); p = snd_create_proc_entry(card->id, S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO, snd_proc_root);
...@@ -738,7 +745,7 @@ int snd_info_card_register(snd_card_t * card) ...@@ -738,7 +745,7 @@ int snd_info_card_register(snd_card_t * card)
return 0; return 0;
} }
int snd_info_card_unregister(snd_card_t * card) int snd_info_card_free(snd_card_t * card)
{ {
void *data; void *data;
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/time.h> #include <linux/time.h>
#include <linux/ctype.h>
#include <sound/core.h> #include <sound/core.h>
#include <sound/control.h> #include <sound/control.h>
#include <sound/info.h> #include <sound/info.h>
...@@ -45,7 +46,6 @@ snd_card_t *snd_card_new(int idx, const char *xid, ...@@ -45,7 +46,6 @@ snd_card_t *snd_card_new(int idx, const char *xid,
struct module *module, int extra_size) struct module *module, int extra_size)
{ {
snd_card_t *card; snd_card_t *card;
snd_info_entry_t *entry;
int err; int err;
if (extra_size < 0) if (extra_size < 0)
...@@ -79,8 +79,6 @@ snd_card_t *snd_card_new(int idx, const char *xid, ...@@ -79,8 +79,6 @@ snd_card_t *snd_card_new(int idx, const char *xid,
snd_cards_lock |= 1 << idx; /* lock it */ snd_cards_lock |= 1 << idx; /* lock it */
write_unlock(&snd_card_rwlock); write_unlock(&snd_card_rwlock);
card->number = idx; card->number = idx;
if (!card->id[0])
sprintf(card->id, "card%i", card->number);
card->module = module; card->module = module;
INIT_LIST_HEAD(&card->devices); INIT_LIST_HEAD(&card->devices);
rwlock_init(&card->control_rwlock); rwlock_init(&card->control_rwlock);
...@@ -97,28 +95,14 @@ snd_card_t *snd_card_new(int idx, const char *xid, ...@@ -97,28 +95,14 @@ snd_card_t *snd_card_new(int idx, const char *xid,
snd_printd("unable to register control minors\n"); snd_printd("unable to register control minors\n");
goto __error; goto __error;
} }
if ((err = snd_info_card_register(card)) < 0) { if ((err = snd_info_card_create(card)) < 0) {
snd_printd("unable to register card info\n"); snd_printd("unable to create card info\n");
goto __error_ctl; goto __error_ctl;
} }
if ((entry = snd_info_create_card_entry(card, "id", card->proc_root)) == NULL) {
snd_printd("unable to create card entry\n");
goto __error_info;
}
entry->content = SNDRV_INFO_CONTENT_TEXT;
entry->c.text.read_size = PAGE_SIZE;
entry->c.text.read = snd_card_id_read;
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);
goto __error_info;
}
card->proc_id = entry;
if (extra_size > 0) if (extra_size > 0)
card->private_data = (char *)card + sizeof(snd_card_t); card->private_data = (char *)card + sizeof(snd_card_t);
return card; return card;
__error_info:
snd_info_card_unregister(card);
__error_ctl: __error_ctl:
snd_ctl_unregister(card); snd_ctl_unregister(card);
__error: __error:
...@@ -157,8 +141,8 @@ int snd_card_free(snd_card_t * card) ...@@ -157,8 +141,8 @@ int snd_card_free(snd_card_t * card)
if (card->private_free) if (card->private_free)
card->private_free(card); card->private_free(card);
snd_info_free_entry(card->proc_id); snd_info_free_entry(card->proc_id);
if (snd_info_card_unregister(card) < 0) { if (snd_info_card_free(card) < 0) {
snd_printk(KERN_WARNING "unable to unregister card info\n"); snd_printk(KERN_WARNING "unable to free card info\n");
/* Not fatal error */ /* Not fatal error */
} }
write_lock(&snd_card_rwlock); write_lock(&snd_card_rwlock);
...@@ -168,9 +152,66 @@ int snd_card_free(snd_card_t * card) ...@@ -168,9 +152,66 @@ int snd_card_free(snd_card_t * card)
return 0; return 0;
} }
static void choose_default_id(snd_card_t *card)
{
int i, len, idx_flag = 0, loops = 8;
char *id, *spos;
id = spos = card->shortname;
while (*id != '\0') {
if (*id == ' ')
spos = id + 1;
id++;
}
id = card->id;
while (*spos != '\0' && id - card->id < sizeof(card->id) - 1) {
if (isalnum(*spos))
*id++ = *spos;
spos++;
}
*id = '\0';
id = card->id;
while (1) {
if (loops-- == 0) {
snd_printk(KERN_ERR "unable to choose default card id (%s)", 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:
len = strlen(id);
if (idx_flag)
id[len-1]++;
else if (len <= sizeof(card->id) - 3) {
strcat(id, "_1");
idx_flag++;
} else {
spos = id + len - 2;
if (len <= sizeof(card->id) - 2)
spos++;
*spos++ = '_';
*spos++ = '1';
*spos++ = '\0';
idx_flag++;
}
}
strcpy(card->id, id);
}
int snd_card_register(snd_card_t * card) int snd_card_register(snd_card_t * card)
{ {
int err; int err;
snd_info_entry_t *entry;
snd_runtime_check(card != NULL, return -EINVAL); snd_runtime_check(card != NULL, return -EINVAL);
if ((err = snd_device_register_all(card)) < 0) if ((err = snd_device_register_all(card)) < 0)
...@@ -181,9 +222,28 @@ int snd_card_register(snd_card_t * card) ...@@ -181,9 +222,28 @@ int snd_card_register(snd_card_t * card)
write_unlock(&snd_card_rwlock); write_unlock(&snd_card_rwlock);
return 0; return 0;
} }
if (!card->id[0])
choose_default_id(card);
snd_cards[card->number] = card; snd_cards[card->number] = card;
snd_cards_count++; snd_cards_count++;
write_unlock(&snd_card_rwlock); write_unlock(&snd_card_rwlock);
if ((err = snd_info_card_register(card)) < 0) {
snd_printd("unable to create card info\n");
goto __skip_info;
}
if ((entry = snd_info_create_card_entry(card, "id", card->proc_root)) == NULL) {
snd_printd("unable to create card entry\n");
goto __skip_info;
}
entry->content = SNDRV_INFO_CONTENT_TEXT;
entry->c.text.read_size = PAGE_SIZE;
entry->c.text.read = snd_card_id_read;
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);
entry = NULL;
}
card->proc_id = entry;
__skip_info:
#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) #if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
if (snd_mixer_oss_notify_callback) if (snd_mixer_oss_notify_callback)
snd_mixer_oss_notify_callback(card, 0); snd_mixer_oss_notify_callback(card, 0);
......
...@@ -154,10 +154,10 @@ struct _snd_es18xx { ...@@ -154,10 +154,10 @@ struct _snd_es18xx {
#define ES18XX_PM 0x07 #define ES18XX_PM 0x07
#define ES18XX_PM_GPO0 0x01 #define ES18XX_PM_GPO0 0x01
#define ES18XX_PM_GPO1 0x02 #define ES18XX_PM_GPO1 0x02
#define ES18XX_PM_PDR 0x03 #define ES18XX_PM_PDR 0x04
#define ES18XX_PM_ANA 0x04 #define ES18XX_PM_ANA 0x08
#define ES18XX_PM_FM 0x06 #define ES18XX_PM_FM 0x020
#define ES18XX_PM_SUS 0x08 #define ES18XX_PM_SUS 0x080
typedef struct _snd_es18xx es18xx_t; typedef struct _snd_es18xx es18xx_t;
......
...@@ -201,11 +201,16 @@ typedef struct { ...@@ -201,11 +201,16 @@ typedef struct {
} viadev_t; } viadev_t;
/*
* allocate and initialize the descriptor buffers
* periods = number of periods
* fragsize = period size in bytes
*/
static int build_via_table(viadev_t *dev, snd_pcm_substream_t *substream, static int build_via_table(viadev_t *dev, snd_pcm_substream_t *substream,
struct pci_dev *pci) struct pci_dev *pci,
int periods, int fragsize)
{ {
int i, idx, ofs, rest, fragsize; int i, idx, ofs, rest;
snd_pcm_runtime_t *runtime = substream->runtime;
struct snd_sg_buf *sgbuf = snd_magic_cast(snd_pcm_sgbuf_t, substream->dma_private, return -EINVAL); struct snd_sg_buf *sgbuf = snd_magic_cast(snd_pcm_sgbuf_t, substream->dma_private, return -EINVAL);
if (! dev->table) { if (! dev->table) {
...@@ -223,10 +228,9 @@ static int build_via_table(viadev_t *dev, snd_pcm_substream_t *substream, ...@@ -223,10 +228,9 @@ static int build_via_table(viadev_t *dev, snd_pcm_substream_t *substream,
} }
/* fill the entries */ /* fill the entries */
fragsize = snd_pcm_lib_period_bytes(substream);
idx = 0; idx = 0;
ofs = 0; ofs = 0;
for (i = 0; i < runtime->periods; i++) { for (i = 0; i < periods; i++) {
rest = fragsize; rest = fragsize;
/* fill descriptors for a period. /* fill descriptors for a period.
* a period can be split to several descriptors if it's * a period can be split to several descriptors if it's
...@@ -241,7 +245,7 @@ static int build_via_table(viadev_t *dev, snd_pcm_substream_t *substream, ...@@ -241,7 +245,7 @@ static int build_via_table(viadev_t *dev, snd_pcm_substream_t *substream,
r = rest; r = rest;
rest -= r; rest -= r;
if (! rest) { if (! rest) {
if (i == runtime->periods - 1) if (i == periods - 1)
flag = VIA_TBL_BIT_EOL; /* buffer boundary */ flag = VIA_TBL_BIT_EOL; /* buffer boundary */
else else
flag = VIA_TBL_BIT_FLAG; /* period boundary */ flag = VIA_TBL_BIT_FLAG; /* period boundary */
...@@ -472,19 +476,14 @@ static int snd_via82xx_trigger(via82xx_t *chip, viadev_t *viadev, int cmd) ...@@ -472,19 +476,14 @@ static int snd_via82xx_trigger(via82xx_t *chip, viadev_t *viadev, int cmd)
} }
static int snd_via82xx_setup_periods(via82xx_t *chip, viadev_t *viadev, static int snd_via82xx_set_format(via82xx_t *chip, viadev_t *viadev,
snd_pcm_substream_t *substream) snd_pcm_substream_t *substream)
{ {
snd_pcm_runtime_t *runtime = substream->runtime; snd_pcm_runtime_t *runtime = substream->runtime;
unsigned long port = chip->port + viadev->reg_offset; unsigned long port = chip->port + viadev->reg_offset;
int err;
snd_via82xx_channel_reset(chip, viadev); snd_via82xx_channel_reset(chip, viadev);
err = build_via_table(viadev, substream, chip->pci);
if (err < 0)
return err;
outl((u32)viadev->table_addr, port + VIA_REG_OFFSET_TABLE_PTR); outl((u32)viadev->table_addr, port + VIA_REG_OFFSET_TABLE_PTR);
switch (chip->chip_type) { switch (chip->chip_type) {
case TYPE_VIA686: case TYPE_VIA686:
...@@ -583,11 +582,28 @@ static int snd_via82xx_capture_trigger(snd_pcm_substream_t * substream, ...@@ -583,11 +582,28 @@ static int snd_via82xx_capture_trigger(snd_pcm_substream_t * substream,
static int snd_via82xx_hw_params(snd_pcm_substream_t * substream, static int snd_via82xx_hw_params(snd_pcm_substream_t * substream,
snd_pcm_hw_params_t * hw_params) snd_pcm_hw_params_t * hw_params)
{ {
return snd_pcm_sgbuf_alloc(substream, params_buffer_bytes(hw_params)); via82xx_t *chip = snd_pcm_substream_chip(substream);
viadev_t *viadev = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? &chip->playback : &chip->capture;
int err;
err = snd_pcm_sgbuf_alloc(substream, params_buffer_bytes(hw_params));
if (err < 0)
return err;
err = build_via_table(viadev, substream, chip->pci,
params_periods(hw_params),
params_period_bytes(hw_params));
if (err < 0)
return err;
return err;
} }
static int snd_via82xx_hw_free(snd_pcm_substream_t * substream) static int snd_via82xx_hw_free(snd_pcm_substream_t * substream)
{ {
via82xx_t *chip = snd_pcm_substream_chip(substream);
viadev_t *viadev = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? &chip->playback : &chip->capture;
clean_via_table(viadev, substream, chip->pci);
snd_pcm_sgbuf_free(substream);
return 0; return 0;
} }
...@@ -606,7 +622,7 @@ static int snd_via82xx_playback_prepare(snd_pcm_substream_t * substream) ...@@ -606,7 +622,7 @@ static int snd_via82xx_playback_prepare(snd_pcm_substream_t * substream)
tmp = inl(VIAREG(chip, PLAYBACK_STOP_IDX)) & ~0xfffff; tmp = inl(VIAREG(chip, PLAYBACK_STOP_IDX)) & ~0xfffff;
outl(tmp | (0xffff * runtime->rate)/(48000/16), VIAREG(chip, PLAYBACK_STOP_IDX)); outl(tmp | (0xffff * runtime->rate)/(48000/16), VIAREG(chip, PLAYBACK_STOP_IDX));
} }
return snd_via82xx_setup_periods(chip, &chip->playback, substream); return snd_via82xx_set_format(chip, &chip->playback, substream);
} }
static int snd_via82xx_capture_prepare(snd_pcm_substream_t * substream) static int snd_via82xx_capture_prepare(snd_pcm_substream_t * substream)
...@@ -617,7 +633,7 @@ static int snd_via82xx_capture_prepare(snd_pcm_substream_t * substream) ...@@ -617,7 +633,7 @@ static int snd_via82xx_capture_prepare(snd_pcm_substream_t * substream)
snd_ac97_set_rate(chip->ac97, AC97_PCM_LR_ADC_RATE, runtime->rate); snd_ac97_set_rate(chip->ac97, AC97_PCM_LR_ADC_RATE, runtime->rate);
if (chip->chip_type == TYPE_VIA8233) if (chip->chip_type == TYPE_VIA8233)
outb(VIA_REG_CAPTURE_FIFO_ENABLE, VIAREG(chip, CAPTURE_FIFO)); outb(VIA_REG_CAPTURE_FIFO_ENABLE, VIAREG(chip, CAPTURE_FIFO));
return snd_via82xx_setup_periods(chip, &chip->capture, substream); return snd_via82xx_set_format(chip, &chip->capture, substream);
} }
static inline unsigned int snd_via82xx_cur_ptr(via82xx_t *chip, viadev_t *viadev) static inline unsigned int snd_via82xx_cur_ptr(via82xx_t *chip, viadev_t *viadev)
...@@ -761,20 +777,16 @@ static int snd_via82xx_capture_open(snd_pcm_substream_t * substream) ...@@ -761,20 +777,16 @@ static int snd_via82xx_capture_open(snd_pcm_substream_t * substream)
static int snd_via82xx_playback_close(snd_pcm_substream_t * substream) static int snd_via82xx_playback_close(snd_pcm_substream_t * substream)
{ {
via82xx_t *chip = snd_pcm_substream_chip(substream); via82xx_t *chip = snd_pcm_substream_chip(substream);
clean_via_table(&chip->playback, substream, chip->pci);
snd_pcm_sgbuf_delete(substream);
chip->playback.substream = NULL; chip->playback.substream = NULL;
snd_pcm_sgbuf_delete(substream);
return 0; return 0;
} }
static int snd_via82xx_capture_close(snd_pcm_substream_t * substream) static int snd_via82xx_capture_close(snd_pcm_substream_t * substream)
{ {
via82xx_t *chip = snd_pcm_substream_chip(substream); via82xx_t *chip = snd_pcm_substream_chip(substream);
clean_via_table(&chip->capture, substream, chip->pci);
snd_pcm_sgbuf_delete(substream);
chip->capture.substream = NULL; chip->capture.substream = NULL;
snd_pcm_sgbuf_delete(substream);
return 0; return 0;
} }
......
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