- 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).
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);
*/
-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);
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);
return 0;
}
-int snd_info_card_unregister(snd_card_t * card)
+int snd_info_card_free(snd_card_t * card)
{
void *data;
#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>
struct module *module, int extra_size)
{
snd_card_t *card;
- snd_info_entry_t *entry;
int err;
if (extra_size < 0)
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);
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:
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);
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)
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);
#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;
} 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) {
}
/* 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
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 */
}
-static int snd_via82xx_setup_periods(via82xx_t *chip, viadev_t *viadev,
- snd_pcm_substream_t *substream)
+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:
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;
}
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)
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)
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;
}