Commit 1c033b99 authored by Jaroslav Kysela's avatar Jaroslav Kysela

ALSA update - small patches

  - added kmalloc_nocheck and vmalloc_nocheck macros
  - PCM
    - the page callback returns 'struct page *'
    - fixed delay function (moved put_user call outside spinlock)
  - OSS PCM emulation
    - fixed read() lock when stream was terminated and no data is available
  - EMU8000
   - added 'can schedule' condition to snd_emu8000_write_wait()
  - AC'97
   - added ALC650 support
  - ALI5451
    - removed double free
parent 7e796024
...@@ -241,11 +241,15 @@ void *snd_hidden_vmalloc(unsigned long size); ...@@ -241,11 +241,15 @@ void *snd_hidden_vmalloc(unsigned long size);
void snd_hidden_vfree(void *obj); void snd_hidden_vfree(void *obj);
#define kmalloc(size, flags) snd_hidden_kmalloc(size, flags) #define kmalloc(size, flags) snd_hidden_kmalloc(size, flags)
#define kfree(obj) snd_hidden_kfree(obj) #define kfree(obj) snd_hidden_kfree(obj)
#define kfree_nocheck(obj) snd_wrapper_kfree(obj)
#define vmalloc(size) snd_hidden_vmalloc(size) #define vmalloc(size) snd_hidden_vmalloc(size)
#define vfree(obj) snd_hidden_vfree(obj) #define vfree(obj) snd_hidden_vfree(obj)
#define kmalloc_nocheck(size, flags) snd_wrapper_kmalloc(size, flags)
#define vmalloc_nocheck(size) snd_wrapper_vmalloc(size)
#define kfree_nocheck(obj) snd_wrapper_kfree(obj)
#define vfree_nocheck(obj) snd_wrapper_vfree(obj) #define vfree_nocheck(obj) snd_wrapper_vfree(obj)
#else #else
#define kmalloc_nocheck(size, flags) kmalloc(size, flags)
#define vmalloc_nocheck(size) vmalloc(size)
#define kfree_nocheck(obj) kfree(obj) #define kfree_nocheck(obj) kfree(obj)
#define vfree_nocheck(obj) vfree(obj) #define vfree_nocheck(obj) vfree(obj)
#endif #endif
......
...@@ -96,7 +96,7 @@ typedef struct _snd_pcm_ops { ...@@ -96,7 +96,7 @@ typedef struct _snd_pcm_ops {
void *buf, snd_pcm_uframes_t count); void *buf, snd_pcm_uframes_t count);
int (*silence)(snd_pcm_substream_t *substream, int channel, int (*silence)(snd_pcm_substream_t *substream, int channel,
snd_pcm_uframes_t pos, snd_pcm_uframes_t count); snd_pcm_uframes_t pos, snd_pcm_uframes_t count);
void *(*page)(snd_pcm_substream_t *substream, unsigned long offset); struct page *(*page)(snd_pcm_substream_t *substream, unsigned long offset);
} snd_pcm_ops_t; } snd_pcm_ops_t;
/* /*
...@@ -125,7 +125,7 @@ typedef struct _snd_pcm_ops { ...@@ -125,7 +125,7 @@ typedef struct _snd_pcm_ops {
#define SNDRV_PCM_DMA_TYPE_PCI 2 /* PCI continuous */ #define SNDRV_PCM_DMA_TYPE_PCI 2 /* PCI continuous */
#define SNDRV_PCM_DMA_TYPE_SBUS 3 /* SBUS continuous */ #define SNDRV_PCM_DMA_TYPE_SBUS 3 /* SBUS continuous */
/* If you change this don't forget to changed snd_pcm_rates table in pcm_lib.c */ /* If you change this don't forget to change rates[] table in pcm_native.c */
#define SNDRV_PCM_RATE_5512 (1<<0) /* 5512Hz */ #define SNDRV_PCM_RATE_5512 (1<<0) /* 5512Hz */
#define SNDRV_PCM_RATE_8000 (1<<1) /* 8000Hz */ #define SNDRV_PCM_RATE_8000 (1<<1) /* 8000Hz */
#define SNDRV_PCM_RATE_11025 (1<<2) /* 11025Hz */ #define SNDRV_PCM_RATE_11025 (1<<2) /* 11025Hz */
......
...@@ -61,7 +61,7 @@ int snd_pcm_sgbuf_free(snd_pcm_substream_t *substream); ...@@ -61,7 +61,7 @@ int snd_pcm_sgbuf_free(snd_pcm_substream_t *substream);
int snd_pcm_sgbuf_ops_copy_playback(snd_pcm_substream_t *substream, int channel, snd_pcm_uframes_t hwoff, void *buf, snd_pcm_uframes_t count); int snd_pcm_sgbuf_ops_copy_playback(snd_pcm_substream_t *substream, int channel, snd_pcm_uframes_t hwoff, void *buf, snd_pcm_uframes_t count);
int snd_pcm_sgbuf_ops_copy_capture(snd_pcm_substream_t *substream, int channel, snd_pcm_uframes_t hwoff, void *buf, snd_pcm_uframes_t count); int snd_pcm_sgbuf_ops_copy_capture(snd_pcm_substream_t *substream, int channel, snd_pcm_uframes_t hwoff, void *buf, snd_pcm_uframes_t count);
int snd_pcm_sgbuf_ops_silence(snd_pcm_substream_t *substream, int channel, snd_pcm_uframes_t hwoff, snd_pcm_uframes_t count); int snd_pcm_sgbuf_ops_silence(snd_pcm_substream_t *substream, int channel, snd_pcm_uframes_t hwoff, snd_pcm_uframes_t count);
void *snd_pcm_sgbuf_ops_page(snd_pcm_substream_t *substream, unsigned long offset); struct page *snd_pcm_sgbuf_ops_page(snd_pcm_substream_t *substream, unsigned long offset);
#endif /* __SOUND_PCM_SGBUF_H */ #endif /* __SOUND_PCM_SGBUF_H */
...@@ -564,7 +564,15 @@ snd_pcm_sframes_t snd_pcm_oss_read3(snd_pcm_substream_t *substream, char *ptr, s ...@@ -564,7 +564,15 @@ snd_pcm_sframes_t snd_pcm_oss_read3(snd_pcm_substream_t *substream, char *ptr, s
} else { } else {
ret = snd_pcm_lib_read(substream, ptr, frames); ret = snd_pcm_lib_read(substream, ptr, frames);
} }
if (ret != -EPIPE && ret != -ESTRPIPE) if (ret == -EPIPE) {
if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, 0);
if (ret < 0)
break;
}
continue;
}
if (ret != -ESTRPIPE)
break; break;
} }
return ret; return ret;
......
...@@ -1996,7 +1996,7 @@ static int snd_pcm_delay(snd_pcm_substream_t *substream, snd_pcm_sframes_t *res) ...@@ -1996,7 +1996,7 @@ static int snd_pcm_delay(snd_pcm_substream_t *substream, snd_pcm_sframes_t *res)
{ {
snd_pcm_runtime_t *runtime = substream->runtime; snd_pcm_runtime_t *runtime = substream->runtime;
int err; int err;
snd_pcm_sframes_t n; snd_pcm_sframes_t n = 0;
spin_lock_irq(&runtime->lock); spin_lock_irq(&runtime->lock);
switch (runtime->status->state) { switch (runtime->status->state) {
...@@ -2014,8 +2014,6 @@ static int snd_pcm_delay(snd_pcm_substream_t *substream, snd_pcm_sframes_t *res) ...@@ -2014,8 +2014,6 @@ static int snd_pcm_delay(snd_pcm_substream_t *substream, snd_pcm_sframes_t *res)
n = snd_pcm_playback_hw_avail(runtime); n = snd_pcm_playback_hw_avail(runtime);
else else
n = snd_pcm_capture_avail(runtime); n = snd_pcm_capture_avail(runtime);
if (put_user(n, res))
err = -EFAULT;
break; break;
case SNDRV_PCM_STATE_XRUN: case SNDRV_PCM_STATE_XRUN:
err = -EPIPE; err = -EPIPE;
...@@ -2026,6 +2024,9 @@ static int snd_pcm_delay(snd_pcm_substream_t *substream, snd_pcm_sframes_t *res) ...@@ -2026,6 +2024,9 @@ static int snd_pcm_delay(snd_pcm_substream_t *substream, snd_pcm_sframes_t *res)
break; break;
} }
spin_unlock_irq(&runtime->lock); spin_unlock_irq(&runtime->lock);
if (!err)
if (put_user(n, res))
err = -EFAULT;
return err; return err;
} }
...@@ -2668,12 +2669,13 @@ static unsigned long snd_pcm_mmap_data_nopage(struct vm_area_struct *area, unsig ...@@ -2668,12 +2669,13 @@ static unsigned long snd_pcm_mmap_data_nopage(struct vm_area_struct *area, unsig
if (offset > dma_bytes - PAGE_SIZE) if (offset > dma_bytes - PAGE_SIZE)
return NOPAGE_SIGBUS; return NOPAGE_SIGBUS;
if (substream->ops->page) { if (substream->ops->page) {
vaddr = substream->ops->page(substream, offset); page = substream->ops->page(substream, offset);
if (! vaddr) if (! page)
return NOPAGE_OOM; return NOPAGE_OOM;
} else } else {
vaddr = runtime->dma_area + offset; vaddr = runtime->dma_area + offset;
page = virt_to_page(vaddr); page = virt_to_page(vaddr);
}
get_page(page); get_page(page);
#ifndef LINUX_2_2 #ifndef LINUX_2_2
return page; return page;
......
...@@ -66,7 +66,7 @@ int snd_pcm_sgbuf_init(snd_pcm_substream_t *substream, struct pci_dev *pci, int ...@@ -66,7 +66,7 @@ int snd_pcm_sgbuf_init(snd_pcm_substream_t *substream, struct pci_dev *pci, int
sgbuf->tblsize = tblsize; sgbuf->tblsize = tblsize;
sgbuf->table = kmalloc(sizeof(struct snd_sg_page) * tblsize, GFP_KERNEL); sgbuf->table = kmalloc(sizeof(struct snd_sg_page) * tblsize, GFP_KERNEL);
if (! sgbuf->table) { if (! sgbuf->table) {
snd_pcm_sgbuf_free(substream); snd_pcm_sgbuf_delete(substream);
return -ENOMEM; return -ENOMEM;
} }
memset(sgbuf->table, 0, sizeof(struct snd_sg_page) * tblsize); memset(sgbuf->table, 0, sizeof(struct snd_sg_page) * tblsize);
...@@ -158,9 +158,8 @@ int snd_pcm_sgbuf_free(snd_pcm_substream_t *substream) ...@@ -158,9 +158,8 @@ int snd_pcm_sgbuf_free(snd_pcm_substream_t *substream)
/* /*
* get the page pointer on the given offset * get the page pointer on the given offset
* used as the page callback of pcm ops
*/ */
void *snd_pcm_sgbuf_ops_page(snd_pcm_substream_t *substream, unsigned long offset) static void *sgbuf_get_addr(snd_pcm_substream_t *substream, unsigned long offset)
{ {
struct snd_sg_buf *sgbuf; struct snd_sg_buf *sgbuf;
unsigned int idx; unsigned int idx;
...@@ -172,6 +171,19 @@ void *snd_pcm_sgbuf_ops_page(snd_pcm_substream_t *substream, unsigned long offse ...@@ -172,6 +171,19 @@ void *snd_pcm_sgbuf_ops_page(snd_pcm_substream_t *substream, unsigned long offse
return sgbuf->table[idx].buf; return sgbuf->table[idx].buf;
} }
/*
* get the page struct at the given offset
* used as the page callback of pcm ops
*/
struct page *snd_pcm_sgbuf_ops_page(snd_pcm_substream_t *substream, unsigned long offset)
{
void *addr = sgbuf_get_addr(substream, offset);
if (addr)
return virt_to_page(addr);
else
return 0;
}
/* /*
* do copy_from_user to the sg buffer * do copy_from_user to the sg buffer
*/ */
...@@ -184,7 +196,7 @@ static int copy_from_user_sg_buf(snd_pcm_substream_t *substream, ...@@ -184,7 +196,7 @@ static int copy_from_user_sg_buf(snd_pcm_substream_t *substream,
hwoff -= p; hwoff -= p;
len = PAGE_SIZE - hwoff; len = PAGE_SIZE - hwoff;
for (;;) { for (;;) {
addr = snd_pcm_sgbuf_ops_page(substream, p); addr = sgbuf_get_addr(substream, p);
if (! addr) if (! addr)
return -EFAULT; return -EFAULT;
if (len > bytes) if (len > bytes)
...@@ -214,7 +226,7 @@ static int copy_to_user_sg_buf(snd_pcm_substream_t *substream, ...@@ -214,7 +226,7 @@ static int copy_to_user_sg_buf(snd_pcm_substream_t *substream,
hwoff -= p; hwoff -= p;
len = PAGE_SIZE - hwoff; len = PAGE_SIZE - hwoff;
for (;;) { for (;;) {
addr = snd_pcm_sgbuf_ops_page(substream, p); addr = sgbuf_get_addr(substream, p);
if (! addr) if (! addr)
return -EFAULT; return -EFAULT;
if (len > bytes) if (len > bytes)
...@@ -246,7 +258,7 @@ static int set_silence_sg_buf(snd_pcm_substream_t *substream, ...@@ -246,7 +258,7 @@ static int set_silence_sg_buf(snd_pcm_substream_t *substream,
len = bytes_to_samples(substream->runtime, PAGE_SIZE - hwoff); len = bytes_to_samples(substream->runtime, PAGE_SIZE - hwoff);
page_len = bytes_to_samples(substream->runtime, PAGE_SIZE); page_len = bytes_to_samples(substream->runtime, PAGE_SIZE);
for (;;) { for (;;) {
addr = snd_pcm_sgbuf_ops_page(substream, p); addr = sgbuf_get_addr(substream, p);
if (! addr) if (! addr)
return -EFAULT; return -EFAULT;
if (len > samples) if (len > samples)
......
...@@ -699,7 +699,6 @@ static int snd_rawmidi_ioctl(struct inode *inode, struct file *file, ...@@ -699,7 +699,6 @@ static int snd_rawmidi_ioctl(struct inode *inode, struct file *file,
case SNDRV_RAWMIDI_IOCTL_PARAMS: case SNDRV_RAWMIDI_IOCTL_PARAMS:
{ {
snd_rawmidi_params_t params; snd_rawmidi_params_t params;
int err;
if (copy_from_user(&params, (snd_rawmidi_params_t *) arg, sizeof(snd_rawmidi_params_t))) if (copy_from_user(&params, (snd_rawmidi_params_t *) arg, sizeof(snd_rawmidi_params_t)))
return -EFAULT; return -EFAULT;
switch (params.stream) { switch (params.stream) {
...@@ -714,9 +713,6 @@ static int snd_rawmidi_ioctl(struct inode *inode, struct file *file, ...@@ -714,9 +713,6 @@ static int snd_rawmidi_ioctl(struct inode *inode, struct file *file,
default: default:
return -EINVAL; return -EINVAL;
} }
if (copy_to_user((snd_rawmidi_params_t *) arg, &params, sizeof(snd_rawmidi_params_t)))
return -EFAULT;
return err;
} }
case SNDRV_RAWMIDI_IOCTL_STATUS: case SNDRV_RAWMIDI_IOCTL_STATUS:
{ {
......
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
#include <sound/core.h> #include <sound/core.h>
#include "seq_timer.h" #include "seq_timer.h"
#include "seq_prioq.h" #include "seq_prioq.h"
#include "seq_timer.h"
/* Implementation is a simple linked list for now... /* Implementation is a simple linked list for now...
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
* 2002-04-12 Tomas Kasparek Proc interface update, code cleanup * 2002-04-12 Tomas Kasparek Proc interface update, code cleanup
*/ */
/* $Id: uda1341.c,v 1.4 2002/08/15 12:13:06 perex Exp $ */ /* $Id: uda1341.c,v 1.5 2002/11/09 13:12:19 perex Exp $ */
#include <sound/driver.h> #include <sound/driver.h>
#include <linux/module.h> #include <linux/module.h>
...@@ -341,7 +341,7 @@ static void snd_uda1341_proc_read(snd_info_entry_t *entry, ...@@ -341,7 +341,7 @@ static void snd_uda1341_proc_read(snd_info_entry_t *entry,
snd_iprintf(buffer, "Automatic Gain Ctrl : %s\n", uda->cfg[CMD_AGC] ? "on" : "off"); snd_iprintf(buffer, "Automatic Gain Ctrl : %s\n", uda->cfg[CMD_AGC] ? "on" : "off");
snd_iprintf(buffer, "AGC attack time : %d ms\n", AGC_atime[uda->cfg[CMD_AGC_TIME]]); snd_iprintf(buffer, "AGC attack time : %d ms\n", AGC_atime[uda->cfg[CMD_AGC_TIME]]);
snd_iprintf(buffer, "AGC decay time : %d ns\n", AGC_dtime[uda->cfg[CMD_AGC_TIME]]); snd_iprintf(buffer, "AGC decay time : %d ms\n", AGC_dtime[uda->cfg[CMD_AGC_TIME]]);
snd_iprintf(buffer, "AGC output level : %s dB\n\n", AGC_level[uda->cfg[CMD_AGC_LEVEL]]); snd_iprintf(buffer, "AGC output level : %s dB\n\n", AGC_level[uda->cfg[CMD_AGC_LEVEL]]);
snd_iprintf(buffer, "Mute : %s\n", uda->cfg[CMD_MUTE] ? "on" : "off"); snd_iprintf(buffer, "Mute : %s\n", uda->cfg[CMD_MUTE] ? "on" : "off");
......
...@@ -115,14 +115,16 @@ emu8k_open_dram_for_pcm(emu8000_t *emu, int channels) ...@@ -115,14 +115,16 @@ emu8k_open_dram_for_pcm(emu8000_t *emu, int channels)
/* /*
*/ */
static void static void
snd_emu8000_write_wait(emu8000_t *emu) snd_emu8000_write_wait(emu8000_t *emu, int can_schedule)
{ {
while ((EMU8000_SMALW_READ(emu) & 0x80000000) != 0) { while ((EMU8000_SMALW_READ(emu) & 0x80000000) != 0) {
if (can_schedule) {
set_current_state(TASK_INTERRUPTIBLE); set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(1); schedule_timeout(1);
if (signal_pending(current)) if (signal_pending(current))
break; break;
} }
}
} }
/* /*
...@@ -457,7 +459,7 @@ static int emu8k_pcm_copy(snd_pcm_substream_t *subs, ...@@ -457,7 +459,7 @@ static int emu8k_pcm_copy(snd_pcm_substream_t *subs,
emu8k_pcm_t *rec = subs->runtime->private_data; emu8k_pcm_t *rec = subs->runtime->private_data;
emu8000_t *emu = rec->emu; emu8000_t *emu = rec->emu;
snd_emu8000_write_wait(emu); snd_emu8000_write_wait(emu, 1);
if (voice == -1) { if (voice == -1) {
unsigned short *buf = src; unsigned short *buf = src;
int i, err; int i, err;
...@@ -494,7 +496,7 @@ static int emu8k_pcm_silence(snd_pcm_substream_t *subs, ...@@ -494,7 +496,7 @@ static int emu8k_pcm_silence(snd_pcm_substream_t *subs,
emu8k_pcm_t *rec = subs->runtime->private_data; emu8k_pcm_t *rec = subs->runtime->private_data;
emu8000_t *emu = rec->emu; emu8000_t *emu = rec->emu;
snd_emu8000_write_wait(emu); snd_emu8000_write_wait(emu, 1);
if (voice == -1 && rec->voices == 1) if (voice == -1 && rec->voices == 1)
voice = 0; voice = 0;
if (voice == -1) { if (voice == -1) {
...@@ -524,7 +526,7 @@ static int emu8k_pcm_copy(snd_pcm_substream_t *subs, ...@@ -524,7 +526,7 @@ static int emu8k_pcm_copy(snd_pcm_substream_t *subs,
emu8000_t *emu = rec->emu; emu8000_t *emu = rec->emu;
unsigned short *buf = src; unsigned short *buf = src;
snd_emu8000_write_wait(emu); snd_emu8000_write_wait(emu, 1);
EMU8000_SMALW_WRITE(emu, pos + rec->loop_start[0]); EMU8000_SMALW_WRITE(emu, pos + rec->loop_start[0]);
if (rec->voices > 1) if (rec->voices > 1)
EMU8000_SMARW_WRITE(emu, pos + rec->loop_start[1]); EMU8000_SMARW_WRITE(emu, pos + rec->loop_start[1]);
...@@ -553,7 +555,7 @@ static int emu8k_pcm_silence(snd_pcm_substream_t *subs, ...@@ -553,7 +555,7 @@ static int emu8k_pcm_silence(snd_pcm_substream_t *subs,
emu8k_pcm_t *rec = subs->runtime->private_data; emu8k_pcm_t *rec = subs->runtime->private_data;
emu8000_t *emu = rec->emu; emu8000_t *emu = rec->emu;
snd_emu8000_write_wait(emu); snd_emu8000_write_wait(emu, 1);
EMU8000_SMALW_WRITE(emu, rec->loop_start[0] + pos); EMU8000_SMALW_WRITE(emu, rec->loop_start[0] + pos);
if (rec->voices > 1) if (rec->voices > 1)
EMU8000_SMARW_WRITE(emu, rec->loop_start[1] + pos); EMU8000_SMARW_WRITE(emu, rec->loop_start[1] + pos);
...@@ -645,7 +647,7 @@ static int emu8k_pcm_prepare(snd_pcm_substream_t *subs) ...@@ -645,7 +647,7 @@ static int emu8k_pcm_prepare(snd_pcm_substream_t *subs)
rec->dram_opened = 1; rec->dram_opened = 1;
/* clear loop blanks */ /* clear loop blanks */
snd_emu8000_write_wait(rec->emu); snd_emu8000_write_wait(rec->emu, 0);
EMU8000_SMALW_WRITE(rec->emu, rec->offset); EMU8000_SMALW_WRITE(rec->emu, rec->offset);
for (i = 0; i < LOOP_BLANK_SIZE; i++) for (i = 0; i < LOOP_BLANK_SIZE; i++)
EMU8000_SMLD_WRITE(rec->emu, 0); EMU8000_SMLD_WRITE(rec->emu, 0);
......
...@@ -105,7 +105,7 @@ static const ac97_codec_id_t snd_ac97_codec_ids[] = { ...@@ -105,7 +105,7 @@ static const ac97_codec_id_t snd_ac97_codec_ids[] = {
{ 0x414c4310, 0xfffffff0, "RL5382", NULL }, { 0x414c4310, 0xfffffff0, "RL5382", NULL },
{ 0x414c4320, 0xfffffff0, "RL5383", NULL }, { 0x414c4320, 0xfffffff0, "RL5383", NULL },
{ 0x414c4710, 0xfffffff0, "ALC200/200P", NULL }, { 0x414c4710, 0xfffffff0, "ALC200/200P", NULL },
{ 0x414c4720, 0xfffffff0, "ALC650", NULL }, { 0x414c4720, 0xfffffff0, "ALC650", patch_alc650 },
{ 0x414c4730, 0xffffffff, "ALC101", NULL }, { 0x414c4730, 0xffffffff, "ALC101", NULL },
{ 0x414c4740, 0xfffffff0, "ALC202", NULL }, { 0x414c4740, 0xfffffff0, "ALC202", NULL },
{ 0x414c4750, 0xfffffff0, "ALC250", NULL }, { 0x414c4750, 0xfffffff0, "ALC250", NULL },
...@@ -914,6 +914,25 @@ static const snd_kcontrol_new_t snd_ac97_controls_ad18xx_lfe[1] = { ...@@ -914,6 +914,25 @@ static const snd_kcontrol_new_t snd_ac97_controls_ad18xx_lfe[1] = {
AD18XX_PCM_BITS("LFE Playback Volume", 2, 0, 31) AD18XX_PCM_BITS("LFE Playback Volume", 2, 0, 31)
}; };
/*
* ALC650
*/
static const snd_kcontrol_new_t snd_ac97_controls_alc650[] = {
AC97_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0),
AC97_SINGLE("Surround Down Mix", AC97_ALC650_MULTICH, 1, 1, 0),
AC97_SINGLE("Center/LFE Down Mix", AC97_ALC650_MULTICH, 2, 1, 0),
AC97_SINGLE("Exchange Center/LFE", AC97_ALC650_MULTICH, 3, 1, 0),
AC97_SINGLE("Line-In As Surround", AC97_ALC650_MULTICH, 9, 1, 0),
AC97_SINGLE("Mic As Center/LFE", AC97_ALC650_MULTICH, 10, 1, 0),
AC97_SINGLE("IEC958 Capture Switch", AC97_ALC650_MULTICH, 11, 1, 0),
AC97_SINGLE("Analog to IEC958 Output", AC97_ALC650_MULTICH, 12, 1, 0),
AC97_SINGLE("IEC958 Input Monitor", AC97_ALC650_MULTICH, 13, 1, 0),
#if 0 /* always set in patch_alc650 */
AC97_SINGLE("IEC958 Input Clock Enable", AC97_ALC650_CLOCK, 0, 1, 0),
AC97_SINGLE("IEC958 Input Pin Enable", AC97_ALC650_CLOCK, 1, 1, 0),
#endif
};
/* /*
* *
*/ */
...@@ -1340,7 +1359,7 @@ static int snd_ac97_mixer_build(snd_card_t * card, ac97_t * ac97) ...@@ -1340,7 +1359,7 @@ static int snd_ac97_mixer_build(snd_card_t * card, ac97_t * ac97)
} }
/* build S/PDIF controls */ /* build S/PDIF controls */
if (ac97->ext_id & AC97_EA_SPDIF) { if (ac97->ext_id & AC97_EI_SPDIF) {
if (ac97->flags & AC97_CS_SPDIF) { if (ac97->flags & AC97_CS_SPDIF) {
for (idx = 0; idx < 3; idx++) for (idx = 0; idx < 3; idx++)
if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_spdif[idx], ac97))) < 0) if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_spdif[idx], ac97))) < 0)
...@@ -1379,7 +1398,7 @@ static int snd_ac97_mixer_build(snd_card_t * card, ac97_t * ac97) ...@@ -1379,7 +1398,7 @@ static int snd_ac97_mixer_build(snd_card_t * card, ac97_t * ac97)
ac97->spdif_status = SNDRV_PCM_DEFAULT_CON_SPDIF; ac97->spdif_status = SNDRV_PCM_DEFAULT_CON_SPDIF;
} }
/* build Sigmatel specific controls */ /* build chip specific controls */
switch (ac97->id) { switch (ac97->id) {
case AC97_ID_STAC9700: case AC97_ID_STAC9700:
case AC97_ID_STAC9708: case AC97_ID_STAC9708:
...@@ -1393,6 +1412,12 @@ static int snd_ac97_mixer_build(snd_card_t * card, ac97_t * ac97) ...@@ -1393,6 +1412,12 @@ static int snd_ac97_mixer_build(snd_card_t * card, ac97_t * ac97)
if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_ANALOG, 0)) if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_ANALOG, 0))
if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_sigmatel_controls[1], ac97))) < 0) if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_sigmatel_controls[1], ac97))) < 0)
return err; return err;
break;
case AC97_ID_ALC650:
for (idx = 0; idx < ARRAY_SIZE(snd_ac97_controls_alc650); idx++)
if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_alc650[idx], ac97))) < 0)
return err;
break;
default: default:
/* nothing */ /* nothing */
break; break;
......
...@@ -43,3 +43,4 @@ ...@@ -43,3 +43,4 @@
#define AC97_ID_CS4299 0x43525930 #define AC97_ID_CS4299 0x43525930
#define AC97_ID_CS4201 0x43525948 #define AC97_ID_CS4201 0x43525948
#define AC97_ID_CS4205 0x43525958 #define AC97_ID_CS4205 0x43525958
#define AC97_ID_ALC650 0x414c4720
...@@ -168,7 +168,7 @@ int patch_cirrus_spdif(ac97_t * ac97) ...@@ -168,7 +168,7 @@ int patch_cirrus_spdif(ac97_t * ac97)
ac97->flags |= AC97_CS_SPDIF; ac97->flags |= AC97_CS_SPDIF;
ac97->rates[AC97_RATES_SPDIF] &= ~SNDRV_PCM_RATE_32000; ac97->rates[AC97_RATES_SPDIF] &= ~SNDRV_PCM_RATE_32000;
ac97->ext_id |= AC97_EA_SPDIF; /* force the detection of spdif */ ac97->ext_id |= AC97_EI_SPDIF; /* force the detection of spdif */
snd_ac97_write_cache(ac97, AC97_CSR_ACMODE, 0x0080); snd_ac97_write_cache(ac97, AC97_CSR_ACMODE, 0x0080);
return 0; return 0;
} }
...@@ -184,7 +184,7 @@ int patch_cirrus_cs4299(ac97_t * ac97) ...@@ -184,7 +184,7 @@ int patch_cirrus_cs4299(ac97_t * ac97)
int patch_conexant(ac97_t * ac97) int patch_conexant(ac97_t * ac97)
{ {
ac97->flags |= AC97_CX_SPDIF; ac97->flags |= AC97_CX_SPDIF;
ac97->ext_id |= AC97_EA_SPDIF; /* force the detection of spdif */ ac97->ext_id |= AC97_EI_SPDIF; /* force the detection of spdif */
return 0; return 0;
} }
...@@ -336,3 +336,11 @@ int patch_ad1980(ac97_t * ac97) ...@@ -336,3 +336,11 @@ int patch_ad1980(ac97_t * ac97)
snd_ac97_write_cache(ac97, AC97_AD_MISC, misc | 0x0420); snd_ac97_write_cache(ac97, AC97_AD_MISC, misc | 0x0420);
return 0; return 0;
} }
int patch_alc650(ac97_t * ac97)
{
/* enable spdif in */
snd_ac97_write_cache(ac97, AC97_ALC650_CLOCK,
snd_ac97_read(ac97, AC97_ALC650_CLOCK) | 0x03);
return 0;
}
...@@ -38,3 +38,4 @@ int patch_ad1881(ac97_t * ac97); ...@@ -38,3 +38,4 @@ int patch_ad1881(ac97_t * ac97);
int patch_ad1885(ac97_t * ac97); int patch_ad1885(ac97_t * ac97);
int patch_ad1886(ac97_t * ac97); int patch_ad1886(ac97_t * ac97);
int patch_ad1980(ac97_t * ac97); int patch_ad1980(ac97_t * ac97);
int patch_alc650(ac97_t * ac97);
...@@ -233,6 +233,7 @@ struct snd_stru_ali { ...@@ -233,6 +233,7 @@ struct snd_stru_ali {
unsigned long port; unsigned long port;
unsigned char revision; unsigned char revision;
unsigned int hw_initialized: 1;
struct resource *res_port; struct resource *res_port;
struct pci_dev *pci; struct pci_dev *pci;
...@@ -1965,6 +1966,7 @@ static void snd_ali_resume(struct pci_dev *dev) ...@@ -1965,6 +1966,7 @@ static void snd_ali_resume(struct pci_dev *dev)
static int snd_ali_free(ali_t * codec) static int snd_ali_free(ali_t * codec)
{ {
if (codec->hw_initialized)
snd_ali_disable_address_interrupt(codec); snd_ali_disable_address_interrupt(codec);
if (codec->irq >= 0) { if (codec->irq >= 0) {
synchronize_irq(codec->irq); synchronize_irq(codec->irq);
...@@ -2036,13 +2038,11 @@ static int __devinit snd_ali_resources(ali_t *codec) ...@@ -2036,13 +2038,11 @@ static int __devinit snd_ali_resources(ali_t *codec)
{ {
snd_ali_printk("resouces allocation ...\n"); snd_ali_printk("resouces allocation ...\n");
if ((codec->res_port = request_region(codec->port, 0x100, "ALI 5451")) == NULL) { if ((codec->res_port = request_region(codec->port, 0x100, "ALI 5451")) == NULL) {
snd_ali_free(codec);
snd_printk("Unalbe to request io ports.\n"); snd_printk("Unalbe to request io ports.\n");
return -EBUSY; return -EBUSY;
} }
if (request_irq(codec->pci->irq, snd_ali_card_interrupt, SA_INTERRUPT|SA_SHIRQ, "ALI 5451", (void *)codec)) { if (request_irq(codec->pci->irq, snd_ali_card_interrupt, SA_INTERRUPT|SA_SHIRQ, "ALI 5451", (void *)codec)) {
snd_ali_free(codec);
snd_printk("Unable to request irq.\n"); snd_printk("Unable to request irq.\n");
return -EBUSY; return -EBUSY;
} }
...@@ -2112,6 +2112,7 @@ static int __devinit snd_ali_create(snd_card_t * card, ...@@ -2112,6 +2112,7 @@ static int __devinit snd_ali_create(snd_card_t * card,
pci_set_master(pci); pci_set_master(pci);
if (snd_ali_resources(codec)) { if (snd_ali_resources(codec)) {
snd_ali_free(codec);
return -EBUSY; return -EBUSY;
} }
...@@ -2156,7 +2157,6 @@ static int __devinit snd_ali_create(snd_card_t * card, ...@@ -2156,7 +2157,6 @@ static int __devinit snd_ali_create(snd_card_t * card,
if ((err = snd_ali_chip_init(codec)) < 0) { if ((err = snd_ali_chip_init(codec)) < 0) {
snd_printk("ali create: chip init error.\n"); snd_printk("ali create: chip init error.\n");
snd_ali_free(codec);
return err; return err;
} }
...@@ -2167,6 +2167,7 @@ static int __devinit snd_ali_create(snd_card_t * card, ...@@ -2167,6 +2167,7 @@ static int __devinit snd_ali_create(snd_card_t * card,
#endif #endif
snd_ali_enable_address_interrupt(codec); snd_ali_enable_address_interrupt(codec);
codec->hw_initialized = 1;
*r_ali = codec; *r_ali = codec;
snd_ali_printk("created.\n"); snd_ali_printk("created.\n");
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
$Id: hammerfall_mem.c,v 1.4 2002/10/21 18:28:25 perex Exp $ $Id: hammerfall_mem.c,v 1.5 2002/11/04 09:11:42 perex Exp $
Tue Oct 17 2000 Jaroslav Kysela <perex@suse.cz> Tue Oct 17 2000 Jaroslav Kysela <perex@suse.cz>
...@@ -34,7 +34,6 @@ ...@@ -34,7 +34,6 @@
*/ */
#include <linux/config.h>
#include <linux/version.h> #include <linux/version.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/pci.h> #include <linux/pci.h>
......
...@@ -29,7 +29,6 @@ ...@@ -29,7 +29,6 @@
* --- End of notes from Thoamas's original driver --- * --- End of notes from Thoamas's original driver ---
*/ */
#include <linux/config.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/slab.h> #include <linux/slab.h>
......
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