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);
int snd_info_store_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_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_unregister(snd_info_entry_t * entry);
......
......@@ -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 *s;
snd_info_entry_t *entry;
struct proc_dir_entry *p;
snd_assert(card != NULL, return -ENXIO);
......@@ -717,11 +715,20 @@ int snd_info_card_register(snd_card_t * card)
return -ENOMEM;
}
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;
s = snd_kmalloc_strdup(str, GFP_KERNEL);
s = snd_kmalloc_strdup(card->proc_root->name, GFP_KERNEL);
if (s == NULL)
return -ENOMEM;
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)
return 0;
}
int snd_info_card_unregister(snd_card_t * card)
int snd_info_card_free(snd_card_t * card)
{
void *data;
......
......@@ -23,6 +23,7 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/time.h>
#include <linux/ctype.h>
#include <sound/core.h>
#include <sound/control.h>
#include <sound/info.h>
......@@ -45,7 +46,6 @@ snd_card_t *snd_card_new(int idx, const char *xid,
struct module *module, int extra_size)
{
snd_card_t *card;
snd_info_entry_t *entry;
int err;
if (extra_size < 0)
......@@ -79,8 +79,6 @@ snd_card_t *snd_card_new(int idx, const char *xid,
snd_cards_lock |= 1 << idx; /* lock it */
write_unlock(&snd_card_rwlock);
card->number = idx;
if (!card->id[0])
sprintf(card->id, "card%i", card->number);
card->module = module;
INIT_LIST_HEAD(&card->devices);
rwlock_init(&card->control_rwlock);
......@@ -97,28 +95,14 @@ snd_card_t *snd_card_new(int idx, const char *xid,
snd_printd("unable to register control minors\n");
goto __error;
}
if ((err = snd_info_card_register(card)) < 0) {
snd_printd("unable to register card info\n");
if ((err = snd_info_card_create(card)) < 0) {
snd_printd("unable to create card info\n");
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)
card->private_data = (char *)card + sizeof(snd_card_t);
return card;
__error_info:
snd_info_card_unregister(card);
__error_ctl:
snd_ctl_unregister(card);
__error:
......@@ -157,8 +141,8 @@ int snd_card_free(snd_card_t * card)
if (card->private_free)
card->private_free(card);
snd_info_free_entry(card->proc_id);
if (snd_info_card_unregister(card) < 0) {
snd_printk(KERN_WARNING "unable to unregister card info\n");
if (snd_info_card_free(card) < 0) {
snd_printk(KERN_WARNING "unable to free card info\n");
/* Not fatal error */
}
write_lock(&snd_card_rwlock);
......@@ -168,9 +152,66 @@ int snd_card_free(snd_card_t * card)
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 err;
snd_info_entry_t *entry;
snd_runtime_check(card != NULL, return -EINVAL);
if ((err = snd_device_register_all(card)) < 0)
......@@ -181,9 +222,28 @@ int snd_card_register(snd_card_t * card)
write_unlock(&snd_card_rwlock);
return 0;
}
if (!card->id[0])
choose_default_id(card);
snd_cards[card->number] = card;
snd_cards_count++;
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 (snd_mixer_oss_notify_callback)
snd_mixer_oss_notify_callback(card, 0);
......
......@@ -154,10 +154,10 @@ struct _snd_es18xx {
#define ES18XX_PM 0x07
#define ES18XX_PM_GPO0 0x01
#define ES18XX_PM_GPO1 0x02
#define ES18XX_PM_PDR 0x03
#define ES18XX_PM_ANA 0x04
#define ES18XX_PM_FM 0x06
#define ES18XX_PM_SUS 0x08
#define ES18XX_PM_PDR 0x04
#define ES18XX_PM_ANA 0x08
#define ES18XX_PM_FM 0x020
#define ES18XX_PM_SUS 0x080
typedef struct _snd_es18xx es18xx_t;
......
......@@ -201,11 +201,16 @@ typedef struct {
} 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,
struct pci_dev *pci)
struct pci_dev *pci,
int periods, int fragsize)
{
int i, idx, ofs, rest, fragsize;
snd_pcm_runtime_t *runtime = substream->runtime;
int i, idx, ofs, rest;
struct snd_sg_buf *sgbuf = snd_magic_cast(snd_pcm_sgbuf_t, substream->dma_private, return -EINVAL);
if (! dev->table) {
......@@ -223,10 +228,9 @@ static int build_via_table(viadev_t *dev, snd_pcm_substream_t *substream,
}
/* fill the entries */
fragsize = snd_pcm_lib_period_bytes(substream);
idx = 0;
ofs = 0;
for (i = 0; i < runtime->periods; i++) {
for (i = 0; i < periods; i++) {
rest = fragsize;
/* fill descriptors for a period.
* 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,
r = rest;
rest -= r;
if (! rest) {
if (i == runtime->periods - 1)
if (i == periods - 1)
flag = VIA_TBL_BIT_EOL; /* buffer boundary */
else
flag = VIA_TBL_BIT_FLAG; /* period boundary */
......@@ -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_runtime_t *runtime = substream->runtime;
unsigned long port = chip->port + viadev->reg_offset;
int err;
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);
switch (chip->chip_type) {
case TYPE_VIA686:
......@@ -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,
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)
{
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;
}
......@@ -606,7 +622,7 @@ static int snd_via82xx_playback_prepare(snd_pcm_substream_t * substream)
tmp = inl(VIAREG(chip, PLAYBACK_STOP_IDX)) & ~0xfffff;
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)
......@@ -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);
if (chip->chip_type == TYPE_VIA8233)
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)
......@@ -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)
{
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;
snd_pcm_sgbuf_delete(substream);
return 0;
}
static int snd_via82xx_capture_close(snd_pcm_substream_t * 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;
snd_pcm_sgbuf_delete(substream);
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