Commit 74521715 authored by Jaroslav Kysela's avatar Jaroslav Kysela

Merge suse.cz:/home/perex/bk/linux-sound/linux-sound

into suse.cz:/home/perex/bk/linux-sound/work
parents d99c48c6 c3c8a7e8
......@@ -207,7 +207,7 @@ MIDI CONTROLLER
---------------
The MPU401-UART interface is enabled as default only for the first
(CMIPCI) card. You need to set module option "snd_midi_port" properly
(CMIPCI) card. You need to set module option "midi_port" properly
for the 2nd (CMIPCI) card.
There is _no_ hardware wavetable function on this chip (except for
......@@ -221,7 +221,7 @@ FM OPL/3 Synth
--------------
The FM OPL/3 is also enabled as default only for the first card.
Set "snd_fm_port" module option for more cards.
Set "fm_port" module option for more cards.
The output quality of FM OPL/3 is, however, very weird.
I don't know why..
......
......@@ -1377,6 +1377,8 @@
module_init(alsa_card_mychip_init)
module_exit(alsa_card_mychip_exit)
EXPORT_NO_SYMBOLS; /* for old kernels only */
]]>
</programlisting>
</example>
......@@ -2758,6 +2760,17 @@
</para>
</section>
<section id="pcm-interface-operators-ack">
<title>ack callback</title>
<para>
This callback is also not mandatory. This callback is called
when the appl_ptr is updated in read or write operations.
Some drivers like emu10k1-fx and cs46xx need to track the
current appl_ptr for the internal buffer, and this callback
is useful only for such a purpose.
</para>
</section>
<section id="pcm-interface-operators-page-callback">
<title>page callback</title>
......
......@@ -2,7 +2,7 @@
Serial UART 16450/16550 MIDI driver
===================================
The snd_adaptor module parameter allows you to select either:
The adaptor module parameter allows you to select either:
0 - Roland Soundcanvas support (default)
1 - Midiator MS-124T support (1)
......@@ -24,37 +24,35 @@ send the F5 NN command sequence at all; perhaps it ought to.
Usage example for simple serial converter:
/sbin/setserial /dev/ttyS0 none
/sbin/modprobe snd-serial-u16550 snd_port=0x3f8 snd_irq=4 \
snd_speed=115200
/sbin/modprobe snd-serial-u16550 port=0x3f8 irq=4 speed=115200
Usage example for Roland SoundCanvas with 4 MIDI ports:
/sbin/setserial /dev/ttyS0 none
/sbin/modprobe snd-serial-u16550 snd_port=0x3f8 snd_irq=4 snd_outs=4
/sbin/modprobe snd-serial-u16550 port=0x3f8 irq=4 outs=4
In MS-124T mode, one raw MIDI substream is supported (midiCnD0); the snd_outs
In MS-124T mode, one raw MIDI substream is supported (midiCnD0); the outs
module parameter is automatically set to 1. The driver sends the same data to
all four MIDI Out connectors. Set the A-B switch and the snd_speed module
all four MIDI Out connectors. Set the A-B switch and the speed module
parameter to match (A=19200, B=9600).
Usage example for MS-124T, with A-B switch in A position:
/sbin/setserial /dev/ttyS0 none
/sbin/modprobe snd-serial-u16550 snd_port=0x3f8 snd_irq=4 \
snd_adaptor=1 snd_speed=19200
/sbin/modprobe snd-serial-u16550 port=0x3f8 irq=4 adaptor=1 \
speed=19200
In MS-124W S/A mode, one raw MIDI substream is supported (midiCnD0);
the snd_outs module parameter is automatically set to 1. The driver sends
the outs module parameter is automatically set to 1. The driver sends
the same data to all four MIDI Out connectors at full MIDI speed.
Usage example for S/A mode:
/sbin/setserial /dev/ttyS0 none
/sbin/modprobe snd-serial-u16550 snd_port=0x3f8 snd_irq=4 \
snd_adaptor=2
/sbin/modprobe snd-serial-u16550 port=0x3f8 irq=4 adaptor=2
In MS-124W M/B mode, the driver supports 16 ALSA raw MIDI substreams;
the snd_outs module parameter is automatically set to 16. The substream
the outs module parameter is automatically set to 16. The substream
number gives a bitmask of which MIDI Out connectors the data should be
sent to, with midiCnD1 sending to Out 1, midiCnD2 to Out 2, midiCnD4 to
Out 3, and midiCnD8 to Out 4. Thus midiCnD15 sends the data to all 4 ports.
......@@ -67,8 +65,7 @@ one byte every 320 us per port.
Usage example for M/B mode:
/sbin/setserial /dev/ttyS0 none
/sbin/modprobe snd-serial-u16550 snd_port=0x3f8 snd_irq=4 \
snd_adaptor=3
/sbin/modprobe snd-serial-u16550 port=0x3f8 irq=4 adaptor=3
The MS-124W hardware's M/A mode is currently not supported. This mode allows
the MIDI Outs to act independently at double the aggregate throughput of M/B,
......@@ -88,4 +85,4 @@ The Generic driver supports multiple input and output substreams over a single
serial port. Similar to Roland Soundcanvas mode, F5 NN is used to select the
appropriate input or output stream (depending on the data direction).
Additionally, the CTS signal is used to regulate the data flow. The number of
inputs is specified by the snd_ins parameter.
inputs is specified by the ins parameter.
......@@ -268,6 +268,14 @@ struct _snd_ac97 {
};
/* conditions */
static inline int ac97_is_audio(ac97_t * ac97)
{
return (ac97->scaps & AC97_SCAP_AUDIO);
}
static inline int ac97_is_modem(ac97_t * ac97)
{
return (ac97->scaps & AC97_SCAP_MODEM);
}
static inline int ac97_is_rev22(ac97_t * ac97)
{
return (ac97->ext_id & AC97_EI_REV_MASK) == AC97_EI_REV_22;
......@@ -278,7 +286,8 @@ static inline int ac97_can_amap(ac97_t * ac97)
}
/* functions */
int snd_ac97_mixer(snd_card_t * card, ac97_t * _ac97, ac97_t ** rac97);
int snd_ac97_mixer(snd_card_t * card, ac97_t * _ac97, ac97_t ** rac97); /* create mixer controls */
int snd_ac97_modem(snd_card_t * card, ac97_t * _ac97, ac97_t ** rac97); /* create modem controls */
void snd_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short value);
unsigned short snd_ac97_read(ac97_t *ac97, unsigned short reg);
......@@ -296,6 +305,7 @@ enum { AC97_TUNE_HP_ONLY, AC97_TUNE_SWAP_HP };
struct ac97_quirk {
unsigned short vendor;
unsigned short device;
const char *name;
int type;
};
......
......@@ -93,7 +93,7 @@ struct sndrv_aes_iec958 {
* *
****************************************************************************/
#define SNDRV_HWDEP_VERSION SNDRV_PROTOCOL_VERSION(1, 0, 0)
#define SNDRV_HWDEP_VERSION SNDRV_PROTOCOL_VERSION(1, 0, 1)
enum sndrv_hwdep_iface {
SNDRV_HWDEP_IFACE_OPL2 = 0,
......@@ -104,9 +104,10 @@ enum sndrv_hwdep_iface {
SNDRV_HWDEP_IFACE_YSS225, /* Yamaha FX processor */
SNDRV_HWDEP_IFACE_ICS2115, /* Wavetable synth */
SNDRV_HWDEP_IFACE_SSCAPE, /* Ensoniq SoundScape ISA card (MC68EC000) */
SNDRV_HWDEP_IFACE_VX, /* Digigram VX cards */
/* Don't forget to change the following: */
SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_SSCAPE,
SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_VX,
};
struct sndrv_hwdep_info {
......@@ -118,9 +119,29 @@ struct sndrv_hwdep_info {
unsigned char reserved[64]; /* reserved for future */
};
/* generic DSP loader */
struct sndrv_hwdep_dsp_status {
unsigned int version; /* R: driver-specific version */
unsigned char id[32]; /* R: driver-specific ID string */
unsigned int num_dsps; /* R: number of DSP images to transfer */
unsigned int dsp_loaded; /* R: bit flags indicating the loaded DSPs */
unsigned int chip_ready; /* R: 1 = initialization finished */
unsigned char reserved[16]; /* reserved for future use */
};
struct sndrv_hwdep_dsp_image {
unsigned int index; /* W: DSP index */
unsigned char name[64]; /* W: ID (e.g. file name) */
unsigned char *image; /* W: binary image */
size_t length; /* W: size of image in bytes */
unsigned long driver_data; /* W: driver-specific data */
};
enum {
SNDRV_HWDEP_IOCTL_PVERSION = _IOR ('H', 0x00, int),
SNDRV_HWDEP_IOCTL_INFO = _IOR ('H', 0x01, struct sndrv_hwdep_info),
SNDRV_HWDEP_IOCTL_DSP_STATUS = _IOR('H', 0x02, struct sndrv_hwdep_dsp_status),
SNDRV_HWDEP_IOCTL_DSP_LOAD = _IOW('H', 0x03, struct sndrv_hwdep_dsp_image)
};
/*****************************************************************************
......@@ -129,7 +150,7 @@ enum {
* *
*****************************************************************************/
#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 3)
#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 4)
typedef unsigned long sndrv_pcm_uframes_t;
typedef long sndrv_pcm_sframes_t;
......@@ -434,6 +455,7 @@ enum {
SNDRV_PCM_IOCTL_REWIND = _IOW('A', 0x46, sndrv_pcm_uframes_t),
SNDRV_PCM_IOCTL_RESUME = _IO('A', 0x47),
SNDRV_PCM_IOCTL_XRUN = _IO('A', 0x48),
SNDRV_PCM_IOCTL_FORWARD = _IOW('A', 0x49, sndrv_pcm_uframes_t),
SNDRV_PCM_IOCTL_WRITEI_FRAMES = _IOW('A', 0x50, struct sndrv_xferi),
SNDRV_PCM_IOCTL_READI_FRAMES = _IOR('A', 0x51, struct sndrv_xferi),
SNDRV_PCM_IOCTL_WRITEN_FRAMES = _IOW('A', 0x52, struct sndrv_xfern),
......
......@@ -27,6 +27,8 @@
typedef enum sndrv_hwdep_iface snd_hwdep_iface_t;
typedef struct sndrv_hwdep_info snd_hwdep_info_t;
typedef struct sndrv_hwdep_dsp_status snd_hwdep_dsp_status_t;
typedef struct sndrv_hwdep_dsp_image snd_hwdep_dsp_image_t;
typedef struct _snd_hwdep_ops {
long long (*llseek) (snd_hwdep_t *hw, struct file * file, long long offset, int orig);
......@@ -37,6 +39,8 @@ typedef struct _snd_hwdep_ops {
unsigned int (*poll) (snd_hwdep_t * hw, struct file * file, poll_table * wait);
int (*ioctl) (snd_hwdep_t * hw, struct file * file, unsigned int cmd, unsigned long arg);
int (*mmap) (snd_hwdep_t * hw, struct file * file, struct vm_area_struct * vma);
int (*dsp_status) (snd_hwdep_t * hw, snd_hwdep_dsp_status_t * status);
int (*dsp_load) (snd_hwdep_t * hw, snd_hwdep_dsp_image_t * image);
} snd_hwdep_ops_t;
struct _snd_hwdep {
......@@ -56,6 +60,11 @@ struct _snd_hwdep {
wait_queue_head_t open_wait;
void *private_data;
void (*private_free) (snd_hwdep_t *hwdep);
struct semaphore open_mutex;
int used;
unsigned int dsp_loaded;
unsigned int exclusive: 1;
};
extern int snd_hwdep_new(snd_card_t * card, char *id, int device, snd_hwdep_t ** rhwdep);
......
......@@ -67,7 +67,7 @@ static const char __module_generic_string_##name [] \
#define SNDRV_BOOLEAN_TRUE_DESC "allows:{{0,Disabled},{1,Enabled}},default:1,dialog:check"
#define SNDRV_BOOLEAN_FALSE_DESC "allows:{{0,Disabled},{1,Enabled}},default:0,dialog:check"
#define SNDRV_ENABLED "enable:(snd_enable)"
#define SNDRV_ENABLED "enable:(enable)"
#define SNDRV_INDEX_DESC SNDRV_ENABLED ",allows:{{0,7}},unique,skill:required,dialog:list"
#define SNDRV_ID_DESC SNDRV_ENABLED ",unique"
......
......@@ -97,6 +97,7 @@ typedef struct _snd_pcm_ops {
int (*silence)(snd_pcm_substream_t *substream, int channel,
snd_pcm_uframes_t pos, snd_pcm_uframes_t count);
struct page *(*page)(snd_pcm_substream_t *substream, unsigned long offset);
int (*ack)(snd_pcm_substream_t *substream);
} snd_pcm_ops_t;
/*
......
......@@ -15,10 +15,15 @@
* features support
*/
/* $Id: uda1341.h,v 1.2 2002/04/17 07:53:22 perex Exp $ */
/* $Id: uda1341.h,v 1.4 2003/02/25 12:48:16 perex Exp $ */
#define UDA1341_ALSA_NAME "snd-uda1341"
/*
* Default rate set after inicialization
*/
#define AUDIO_RATE_DEFAULT 44100
/*
* UDA1341 L3 address and command types
*/
......
/* include/version.h. Generated by configure. */
#define CONFIG_SND_VERSION "0.9.0rc7"
#define CONFIG_SND_DATE " (Sat Feb 15 15:01:21 2003 UTC)"
#define CONFIG_SND_DATE " (Tue Feb 25 13:00:09 2003 UTC)"
This diff is collapsed.
......@@ -107,7 +107,12 @@ static int snd_hwdep_open(struct inode *inode, struct file * file)
#endif
init_waitqueue_entry(&wait, current);
add_wait_queue(&hw->open_wait, &wait);
down(&hw->open_mutex);
while (1) {
if (hw->exclusive && hw->used > 0) {
err = -EBUSY;
break;
}
err = hw->ops.open(hw, file);
if (err >= 0)
break;
......@@ -127,20 +132,26 @@ static int snd_hwdep_open(struct inode *inode, struct file * file)
}
set_current_state(TASK_RUNNING);
remove_wait_queue(&hw->open_wait, &wait);
if (err >= 0)
if (err >= 0) {
file->private_data = hw;
hw->used++;
}
up(&hw->open_mutex);
return err;
}
static int snd_hwdep_release(struct inode *inode, struct file * file)
{
int err;
int err = -ENXIO;
snd_hwdep_t *hw = snd_magic_cast(snd_hwdep_t, file->private_data, return -ENXIO);
down(&hw->open_mutex);
if (hw->ops.release) {
err = hw->ops.release(hw, file);
wake_up(&hw->open_wait);
return err;
}
if (hw->used > 0)
hw->used--;
up(&hw->open_mutex);
return -ENXIO;
}
......@@ -166,14 +177,58 @@ static int snd_hwdep_info(snd_hwdep_t *hw, snd_hwdep_info_t *_info)
return 0;
}
static int snd_hwdep_dsp_status(snd_hwdep_t *hw, snd_hwdep_dsp_status_t *_info)
{
snd_hwdep_dsp_status_t info;
int err;
if (! hw->ops.dsp_status)
return -ENXIO;
memset(&info, 0, sizeof(info));
info.dsp_loaded = hw->dsp_loaded;
if ((err = hw->ops.dsp_status(hw, &info)) < 0)
return err;
if (copy_to_user(_info, &info, sizeof(info)))
return -EFAULT;
return 0;
}
static int snd_hwdep_dsp_load(snd_hwdep_t *hw, snd_hwdep_dsp_image_t *_info)
{
snd_hwdep_dsp_image_t info;
int err;
if (! hw->ops.dsp_load || ! hw->ops.dsp_status)
return -ENXIO;
memset(&info, 0, sizeof(info));
if (copy_from_user(&info, _info, sizeof(info)))
return -EFAULT;
/* check whether the dsp was already loaded */
if (hw->dsp_loaded & (1 << info.index))
return -EBUSY;
if (verify_area(VERIFY_READ, info.image, info.length))
return -EFAULT;
err = hw->ops.dsp_load(hw, &info);
if (err < 0)
return err;
hw->dsp_loaded |= (1 << info.index);
return 0;
}
static int snd_hwdep_ioctl(struct inode *inode, struct file * file,
unsigned int cmd, unsigned long arg)
{
snd_hwdep_t *hw = snd_magic_cast(snd_hwdep_t, file->private_data, return -ENXIO);
if (cmd == SNDRV_HWDEP_IOCTL_PVERSION)
switch (cmd) {
case SNDRV_HWDEP_IOCTL_PVERSION:
return put_user(SNDRV_HWDEP_VERSION, (int *)arg);
if (cmd == SNDRV_HWDEP_IOCTL_INFO)
case SNDRV_HWDEP_IOCTL_INFO:
return snd_hwdep_info(hw, (snd_hwdep_info_t *)arg);
case SNDRV_HWDEP_IOCTL_DSP_STATUS:
return snd_hwdep_dsp_status(hw, (snd_hwdep_dsp_status_t *)arg);
case SNDRV_HWDEP_IOCTL_DSP_LOAD:
return snd_hwdep_dsp_load(hw, (snd_hwdep_dsp_image_t *)arg);
}
if (hw->ops.ioctl)
return hw->ops.ioctl(hw, file, cmd, arg);
return -ENOTTY;
......@@ -298,6 +353,7 @@ int snd_hwdep_new(snd_card_t * card, char *id, int device, snd_hwdep_t ** rhwdep
return err;
}
init_waitqueue_head(&hwdep->open_wait);
init_MUTEX(&hwdep->open_mutex);
*rhwdep = hwdep;
return 0;
}
......
......@@ -20,13 +20,52 @@
#include <sound/driver.h>
#include <linux/time.h>
#include <linux/fs.h>
#include <sound/core.h>
#include <sound/timer.h>
#include <sound/hwdep.h>
#include <asm/uaccess.h>
#include "ioctl32.h"
struct sndrv_hwdep_dsp_image32 {
u32 index;
unsigned char name[64];
u32 image; /* pointer */
u32 length;
} /* don't set packed attribute here */;
static int _snd_ioctl32_hwdep_dsp_image(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
{
struct sndrv_hwdep_dsp_image data;
struct sndrv_hwdep_dsp_image data32;
mm_segment_t oldseg;
int err;
if (copy_from_user(&data32, (void*)arg, sizeof(data32)))
return -EFAULT;
memset(&data, 0, sizeof(data));
data.index = data32.index;
memcpy(data.name, data32.name, sizeof(data.name));
data.image = A(data32.image);
data.length = data32.length;
oldseg = get_fs();
set_fs(KERNEL_DS);
err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)&data);
set_fs(oldseg);
return err;
}
DEFINE_ALSA_IOCTL_ENTRY(hwdep_dsp_image, hwdep_dsp_image, SNDRV_HWDEP_IOCTL_DSP_LOAD);
#define AP(x) snd_ioctl32_##x
enum {
SNDRV_HWDEP_IOCTL_DSP_LOAD32 = _IOW('H', 0x03, struct sndrv_hwdep_dsp_image32)
};
struct ioctl32_mapper hwdep_mappers[] = {
{ SNDRV_HWDEP_IOCTL_PVERSION, NULL },
{ SNDRV_HWDEP_IOCTL_INFO, NULL },
MAP_COMPAT(SNDRV_HWDEP_IOCTL_PVERSION),
MAP_COMPAT(SNDRV_HWDEP_IOCTL_INFO),
MAP_COMPAT(SNDRV_HWDEP_IOCTL_DSP_STATUS),
{ SNDRV_HWDEP_IOCTL_DSP_LOAD32, AP(hwdep_dsp_image) },
{ 0 },
};
......@@ -77,27 +77,6 @@ void snd_verbose_printd(const char *file, int line, const char *format, ...)
va_end(args);
tmpbuf[sizeof(tmpbuf)-1] = '\0';
printk(tmpbuf);
}
#endif
#if defined(CONFIG_SND_DEBUG) && !defined(CONFIG_SND_VERBOSE_PRINTK)
void snd_printd(const char *format, ...)
{
va_list args;
char tmpbuf[512];
if (format[0] == '<' && format[1] >= '0' && format[1] <= '9' && format[2] == '>') {
char tmp[] = "<0>";
tmp[1] = format[1];
printk("%sALSA: ", tmp);
format += 3;
} else {
printk(KERN_DEBUG "ALSA: ");
}
va_start(args, format);
vsnprintf(tmpbuf, sizeof(tmpbuf)-1, format, args);
va_end(args);
tmpbuf[sizeof(tmpbuf)-1] = '\0';
printk(tmpbuf);
}
#endif
......@@ -2186,6 +2186,8 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(snd_pcm_substream_t *substream,
} else {
runtime->control->appl_ptr = appl_ptr;
}
if (substream->ops->ack)
substream->ops->ack(substream);
offset += frames;
size -= frames;
......@@ -2478,6 +2480,8 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(snd_pcm_substream_t *substream, void
} else {
runtime->control->appl_ptr = appl_ptr;
}
if (substream->ops->ack)
substream->ops->ack(substream);
offset += frames;
size -= frames;
......
......@@ -527,7 +527,7 @@ u_int8_t snd_pcm_format_silence(snd_pcm_format_t format)
*
* Sets the silence data on the buffer for the given samples.
*
* Returns zero if sucessful, or a negative error code on failure.
* Returns zero if successful, or a negative error code on failure.
*/
int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int samples)
{
......
......@@ -1982,6 +1982,106 @@ snd_pcm_sframes_t snd_pcm_capture_rewind(snd_pcm_substream_t *substream, snd_pcm
return ret;
}
snd_pcm_sframes_t snd_pcm_playback_forward(snd_pcm_substream_t *substream, snd_pcm_uframes_t frames)
{
snd_pcm_runtime_t *runtime = substream->runtime;
snd_pcm_sframes_t appl_ptr;
snd_pcm_sframes_t ret;
snd_pcm_sframes_t avail;
if (frames == 0)
return 0;
spin_lock_irq(&runtime->lock);
switch (runtime->status->state) {
case SNDRV_PCM_STATE_PREPARED:
case SNDRV_PCM_STATE_PAUSED:
break;
case SNDRV_PCM_STATE_DRAINING:
case SNDRV_PCM_STATE_RUNNING:
if (snd_pcm_update_hw_ptr(substream) >= 0)
break;
/* Fall through */
case SNDRV_PCM_STATE_XRUN:
ret = -EPIPE;
goto __end;
default:
ret = -EBADFD;
goto __end;
}
avail = snd_pcm_playback_avail(runtime);
if (avail <= 0) {
ret = 0;
goto __end;
}
if (frames > (snd_pcm_uframes_t)avail)
frames = avail;
else
frames -= frames % runtime->xfer_align;
appl_ptr = runtime->control->appl_ptr + frames;
if (appl_ptr >= runtime->boundary)
appl_ptr -= runtime->boundary;
runtime->control->appl_ptr = appl_ptr;
if (runtime->status->state == SNDRV_PCM_STATE_RUNNING &&
runtime->sleep_min)
snd_pcm_tick_prepare(substream);
ret = frames;
__end:
spin_unlock_irq(&runtime->lock);
return ret;
}
snd_pcm_sframes_t snd_pcm_capture_forward(snd_pcm_substream_t *substream, snd_pcm_uframes_t frames)
{
snd_pcm_runtime_t *runtime = substream->runtime;
snd_pcm_sframes_t appl_ptr;
snd_pcm_sframes_t ret;
snd_pcm_sframes_t avail;
if (frames == 0)
return 0;
spin_lock_irq(&runtime->lock);
switch (runtime->status->state) {
case SNDRV_PCM_STATE_PREPARED:
case SNDRV_PCM_STATE_DRAINING:
case SNDRV_PCM_STATE_PAUSED:
break;
case SNDRV_PCM_STATE_RUNNING:
if (snd_pcm_update_hw_ptr(substream) >= 0)
break;
/* Fall through */
case SNDRV_PCM_STATE_XRUN:
ret = -EPIPE;
goto __end;
default:
ret = -EBADFD;
goto __end;
}
avail = snd_pcm_capture_avail(runtime);
if (avail <= 0) {
ret = 0;
goto __end;
}
if (frames > (snd_pcm_uframes_t)avail)
frames = avail;
else
frames -= frames % runtime->xfer_align;
appl_ptr = runtime->control->appl_ptr + frames;
if (appl_ptr >= runtime->boundary)
appl_ptr -= runtime->boundary;
runtime->control->appl_ptr = appl_ptr;
if (runtime->status->state == SNDRV_PCM_STATE_RUNNING &&
runtime->sleep_min)
snd_pcm_tick_prepare(substream);
ret = frames;
__end:
spin_unlock_irq(&runtime->lock);
return ret;
}
static int snd_pcm_hwsync(snd_pcm_substream_t *substream)
{
snd_pcm_runtime_t *runtime = substream->runtime;
......@@ -2169,6 +2269,18 @@ static int snd_pcm_playback_ioctl1(snd_pcm_substream_t *substream,
__put_user(result, _frames);
return result < 0 ? result : 0;
}
case SNDRV_PCM_IOCTL_FORWARD:
{
snd_pcm_uframes_t frames, *_frames = arg;
snd_pcm_sframes_t result;
if (get_user(frames, _frames))
return -EFAULT;
if (put_user(0, _frames))
return -EFAULT;
result = snd_pcm_playback_forward(substream, frames);
__put_user(result, _frames);
return result < 0 ? result : 0;
}
case SNDRV_PCM_IOCTL_PAUSE:
{
int res;
......@@ -2244,6 +2356,18 @@ static int snd_pcm_capture_ioctl1(snd_pcm_substream_t *substream,
__put_user(result, _frames);
return result < 0 ? result : 0;
}
case SNDRV_PCM_IOCTL_FORWARD:
{
snd_pcm_uframes_t frames, *_frames = arg;
snd_pcm_sframes_t result;
if (get_user(frames, _frames))
return -EFAULT;
if (put_user(0, _frames))
return -EFAULT;
result = snd_pcm_capture_forward(substream, frames);
__put_user(result, _frames);
return result < 0 ? result : 0;
}
case SNDRV_PCM_IOCTL_DRAIN:
return snd_pcm_capture_drain(substream);
case SNDRV_PCM_IOCTL_DROP:
......
......@@ -358,11 +358,19 @@ snd_seq_midisynth_register_port(snd_seq_device_t *dev)
if (snd_rawmidi_info_select(card, &info) >= 0)
strcpy(port.name, info.subname);
if (! port.name[0]) {
if (info.name[0]) {
if (ports > 1)
snprintf(port.name, sizeof(port.name), "%s-%d", info.name, p);
else
snprintf(port.name, sizeof(port.name), "%s", info.name);
} else {
/* last resort */
if (ports > 1)
sprintf(port.name, "MIDI %d-%d-%d", card->number, device, p);
else
sprintf(port.name, "MIDI %d-%d", card->number, device);
}
}
if ((info.flags & SNDRV_RAWMIDI_INFO_OUTPUT) && p < output_count)
port.capability |= SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SYNC_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE;
if ((info.flags & SNDRV_RAWMIDI_INFO_INPUT) && p < input_count)
......
......@@ -521,9 +521,6 @@ EXPORT_SYMBOL(snd_verbose_printk);
#endif
#if defined(CONFIG_SND_DEBUG) && defined(CONFIG_SND_VERBOSE_PRINTK)
EXPORT_SYMBOL(snd_verbose_printd);
#endif
#if defined(CONFIG_SND_DEBUG) && !defined(CONFIG_SND_VERBOSE_PRINTK)
EXPORT_SYMBOL(snd_printd);
#endif
/* wrappers */
#ifdef CONFIG_SND_DEBUG_MEMORY
......
......@@ -474,7 +474,7 @@ int snd_mpu401_uart_new(snd_card_t * card, int device,
}
mpu->irq = irq;
mpu->irq_flags = irq_flags;
strcpy(rmidi->name, "MPU-401 (UART)");
sprintf(rmidi->name, "MPU-401 (UART) %d-%d", card->number, device);
snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_mpu401_uart_output);
snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_mpu401_uart_input);
rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT |
......
......@@ -802,7 +802,7 @@ module_exit(alsa_card_mtpav_exit)
#ifndef MODULE
/* format is: snd-mtpav=snd_enable,index,id,
/* format is: snd-mtpav=enable,index,id,
port,irq,hwports */
static int __init alsa_card_mtpav_setup(char *str)
......
......@@ -379,7 +379,7 @@ module_exit(alsa_card_dt019x_exit)
#ifndef MODULE
/* format is: snd-dt019x=enable,index,id,snd_isapnp,
/* format is: snd-dt019x=enable,index,id,
port,mpu_port,fm_port,
irq,mpu_irq,dma8,dma8_size */
......
......@@ -277,7 +277,7 @@ module_exit(alsa_card_es968_exit)
#ifndef MODULE
/* format is: snd-es968=enable,index,id,
port,irq,snd_dma1 */
port,irq,dma1 */
static int __init alsa_card_es968_setup(char *str)
{
......
......@@ -213,7 +213,10 @@ static int snd_sb_csp_ioctl(snd_hwdep_t * hw, struct file *file, unsigned int cm
info.run_width = p->run_width;
info.version = p->version;
info.state = p->running;
err = copy_to_user((void *) arg, &info, sizeof(info));
if (copy_to_user((void *) arg, &info, sizeof(info)))
err = -EFAULT;
else
err = 0;
break;
/* load CSP microcode */
......
......@@ -44,7 +44,7 @@ MODULE_DEVICES("{{Aztech Systems,Sound Galaxy}}");
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
static int snd_enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
static long sbport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220,0x240 */
static long wssport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x530,0xe80,0xf40,0x604 */
static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 7,9,10,11 */
......@@ -300,7 +300,7 @@ static int __init alsa_card_sgalaxy_init(void)
{
int dev, cards;
for (dev = cards = 0; dev < SNDRV_CARDS && snd_enable[dev]; dev++) {
for (dev = cards = 0; dev < SNDRV_CARDS && enable[dev]; dev++) {
if (snd_sgalaxy_probe(dev) >= 0)
cards++;
}
......@@ -327,7 +327,7 @@ module_exit(alsa_card_sgalaxy_exit)
#ifndef MODULE
/* format is: snd-sgalaxy=snd_enable,index,id,
/* format is: snd-sgalaxy=enable,index,id,
sbport,wssport,
irq,dma1 */
......@@ -337,7 +337,7 @@ static int __init alsa_card_sgalaxy_setup(char *str)
if (nr_dev >= SNDRV_CARDS)
return 0;
(void)(get_option(&str,&snd_enable[nr_dev]) == 2 &&
(void)(get_option(&str,&enable[nr_dev]) == 2 &&
get_option(&str,&index[nr_dev]) == 2 &&
get_id(&str,&id[nr_dev]) == 2 &&
get_option(&str,(int *)&sbport[nr_dev]) == 2 &&
......
This diff is collapsed.
......@@ -31,6 +31,7 @@
#define AC97_ID_AD1886 0x41445361
#define AC97_ID_AD1887 0x41445362
#define AC97_ID_AD1886A 0x41445363
#define AC97_ID_AD1980 0x41445370
#define AC97_ID_TR28028 0x54524108
#define AC97_ID_STAC9700 0x83847600
#define AC97_ID_STAC9704 0x83847604
......
......@@ -672,28 +672,21 @@ static void snd_cs46xx_set_capture_sample_rate(cs46xx_t *chip, unsigned int rate
* PCM part
*/
static int snd_cs46xx_playback_transfer(snd_pcm_substream_t *substream,
snd_pcm_uframes_t frames)
static int snd_cs46xx_playback_transfer(snd_pcm_substream_t *substream)
{
/* cs46xx_t *chip = snd_pcm_substream_chip(substream); */
snd_pcm_runtime_t *runtime = substream->runtime;
cs46xx_pcm_t * cpcm = snd_magic_cast(cs46xx_pcm_t, runtime->private_data, return -ENXIO);
snd_pcm_uframes_t appl_ptr = runtime->control->appl_ptr;
snd_pcm_sframes_t diff;
cs46xx_pcm_t * cpcm;
int buffer_size;
cpcm = snd_magic_cast(cs46xx_pcm_t, substream->runtime->private_data, return -ENXIO);
snd_pcm_sframes_t diff = appl_ptr - cpcm->appl_ptr;
int buffer_size = runtime->period_size * CS46XX_FRAGS << cpcm->shift;
buffer_size = runtime->period_size * CS46XX_FRAGS << cpcm->shift;
diff = appl_ptr - cpcm->appl_ptr;
if (diff) {
if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2))
diff += runtime->boundary;
frames += diff;
cpcm->sw_ready += diff * (1 << cpcm->shift);
cpcm->appl_ptr = appl_ptr;
}
cpcm->sw_ready += frames << cpcm->shift;
cpcm->appl_ptr = appl_ptr + frames;
while (cpcm->hw_ready < buffer_size &&
cpcm->sw_ready > 0) {
size_t hw_to_end = buffer_size - cpcm->hw_data;
......@@ -720,21 +713,20 @@ static int snd_cs46xx_playback_transfer(snd_pcm_substream_t *substream,
return 0;
}
static int snd_cs46xx_capture_transfer(snd_pcm_substream_t *substream,
snd_pcm_uframes_t frames)
static int snd_cs46xx_capture_transfer(snd_pcm_substream_t *substream)
{
cs46xx_t *chip = snd_pcm_substream_chip(substream);
snd_pcm_runtime_t *runtime = substream->runtime;
snd_pcm_uframes_t appl_ptr = runtime->control->appl_ptr;
snd_pcm_sframes_t diff = appl_ptr - chip->capt.appl_ptr;
int buffer_size = runtime->period_size * CS46XX_FRAGS << chip->capt.shift;
if (diff) {
if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2))
diff += runtime->boundary;
frames += diff;
chip->capt.sw_ready -= diff * (1 << chip->capt.shift);
chip->capt.appl_ptr = appl_ptr;
}
chip->capt.sw_ready -= frames << chip->capt.shift;
chip->capt.appl_ptr = appl_ptr + frames;
while (chip->capt.hw_ready > 0 &&
chip->capt.sw_ready < (int)chip->capt.sw_bufsize) {
size_t hw_to_end = buffer_size - chip->capt.hw_data;
......@@ -802,7 +794,7 @@ static snd_pcm_uframes_t snd_cs46xx_playback_indirect_pointer(snd_pcm_substream_
cpcm->sw_io += bytes;
if (cpcm->sw_io >= cpcm->sw_bufsize)
cpcm->sw_io -= cpcm->sw_bufsize;
snd_cs46xx_playback_transfer(substream, 0);
snd_cs46xx_playback_transfer(substream);
return cpcm->sw_io >> cpcm->shift;
}
......@@ -827,57 +819,10 @@ static snd_pcm_uframes_t snd_cs46xx_capture_indirect_pointer(snd_pcm_substream_t
chip->capt.sw_io += bytes;
if (chip->capt.sw_io >= chip->capt.sw_bufsize)
chip->capt.sw_io -= chip->capt.sw_bufsize;
snd_cs46xx_capture_transfer(substream, 0);
snd_cs46xx_capture_transfer(substream);
return chip->capt.sw_io >> chip->capt.shift;
}
static int snd_cs46xx_playback_copy(snd_pcm_substream_t *substream,
int channel,
snd_pcm_uframes_t hwoff,
void *src,
snd_pcm_uframes_t frames)
{
snd_pcm_runtime_t *runtime = substream->runtime;
/*cs46xx_t *chip = snd_pcm_substream_chip(substream); */
size_t hwoffb;
size_t bytes;
char *hwbuf;
cs46xx_pcm_t *cpcm = snd_magic_cast(cs46xx_pcm_t, substream->runtime->private_data, return -ENXIO);
snd_assert(runtime->dma_area, return -EINVAL);
hwoffb = hwoff << cpcm->shift;
bytes = frames << cpcm->shift;
hwbuf = runtime->dma_area + hwoffb;
if (copy_from_user(hwbuf, src, bytes))
return -EFAULT;
spin_lock_irq(&runtime->lock);
snd_cs46xx_playback_transfer(substream, frames);
spin_unlock_irq(&runtime->lock);
return 0;
}
static int snd_cs46xx_capture_copy(snd_pcm_substream_t *substream,
int channel,
snd_pcm_uframes_t hwoff,
void *dst,
snd_pcm_uframes_t frames)
{
snd_pcm_runtime_t *runtime = substream->runtime;
cs46xx_t *chip = snd_pcm_substream_chip(substream);
size_t hwoffb = hwoff << chip->capt.shift;
size_t bytes = frames << chip->capt.shift;
char *hwbuf = runtime->dma_area + hwoffb;
if (copy_to_user(dst, hwbuf, bytes))
return -EFAULT;
spin_lock_irq(&runtime->lock);
snd_cs46xx_capture_transfer(substream, frames);
spin_unlock_irq(&runtime->lock);
return 0;
}
static int snd_cs46xx_playback_trigger(snd_pcm_substream_t * substream,
int cmd)
{
......@@ -909,10 +854,10 @@ static int snd_cs46xx_playback_trigger(snd_pcm_substream_t * substream,
cs46xx_dsp_pcm_link(chip,cpcm->pcm_channel);
if (substream->runtime->periods != CS46XX_FRAGS)
snd_cs46xx_playback_transfer(substream, 0);
snd_cs46xx_playback_transfer(substream);
#else
if (substream->runtime->periods != CS46XX_FRAGS)
snd_cs46xx_playback_transfer(substream, 0);
snd_cs46xx_playback_transfer(substream);
{ unsigned int tmp;
tmp = snd_cs46xx_peek(chip, BA1_PCTL);
tmp &= 0x0000ffff;
......@@ -1587,8 +1532,8 @@ snd_pcm_ops_t snd_cs46xx_playback_indirect_rear_ops = {
.hw_free = snd_cs46xx_playback_hw_free,
.prepare = snd_cs46xx_playback_prepare,
.trigger = snd_cs46xx_playback_trigger,
.copy = snd_cs46xx_playback_copy,
.pointer = snd_cs46xx_playback_indirect_pointer,
.ack = snd_cs46xx_playback_transfer,
};
snd_pcm_ops_t snd_cs46xx_playback_iec958_ops = {
......@@ -1610,8 +1555,8 @@ snd_pcm_ops_t snd_cs46xx_playback_indirect_iec958_ops = {
.hw_free = snd_cs46xx_playback_hw_free,
.prepare = snd_cs46xx_playback_prepare,
.trigger = snd_cs46xx_playback_trigger,
.copy = snd_cs46xx_playback_copy,
.pointer = snd_cs46xx_playback_indirect_pointer,
.ack = snd_cs46xx_playback_transfer,
};
#endif
......@@ -1635,8 +1580,8 @@ snd_pcm_ops_t snd_cs46xx_playback_indirect_ops = {
.hw_free = snd_cs46xx_playback_hw_free,
.prepare = snd_cs46xx_playback_prepare,
.trigger = snd_cs46xx_playback_trigger,
.copy = snd_cs46xx_playback_copy,
.pointer = snd_cs46xx_playback_indirect_pointer,
.ack = snd_cs46xx_playback_transfer,
};
snd_pcm_ops_t snd_cs46xx_capture_ops = {
......@@ -1658,8 +1603,8 @@ snd_pcm_ops_t snd_cs46xx_capture_indirect_ops = {
.hw_free = snd_cs46xx_capture_hw_free,
.prepare = snd_cs46xx_capture_prepare,
.trigger = snd_cs46xx_capture_trigger,
.copy = snd_cs46xx_capture_copy,
.pointer = snd_cs46xx_capture_indirect_pointer,
.ack = snd_cs46xx_capture_transfer,
};
static void snd_cs46xx_pcm_free(snd_pcm_t *pcm)
......@@ -2505,9 +2450,6 @@ int __devinit snd_cs46xx_mixer(cs46xx_t *chip)
strcpy(id.name, "External Amplifier Power Down");
chip->eapd_switch = snd_ctl_find_id(chip->card, &id);
/* turn on amplifier */
chip->amplifier_ctrl(chip, 1);
#ifdef CONFIG_SND_CS46XX_NEW_DSP
/* do soundcard specific mixer setup */
if (chip->mixer_init) {
......@@ -2516,6 +2458,9 @@ int __devinit snd_cs46xx_mixer(cs46xx_t *chip)
}
#endif
/* turn on amplifier */
chip->amplifier_ctrl(chip, 1);
return 0;
}
......
......@@ -520,8 +520,7 @@ static void snd_emu10k1_fx8010_playback_tram_poke(emu10k1_t *emu,
*tram_pos -= frames;
}
static int snd_emu10k1_fx8010_playback_transfer(snd_pcm_substream_t *substream,
snd_pcm_uframes_t frames)
static int snd_emu10k1_fx8010_playback_transfer(snd_pcm_substream_t *substream)
{
emu10k1_t *emu = snd_pcm_substream_chip(substream);
snd_pcm_runtime_t *runtime = substream->runtime;
......@@ -529,13 +528,13 @@ static int snd_emu10k1_fx8010_playback_transfer(snd_pcm_substream_t *substream,
snd_pcm_uframes_t appl_ptr = runtime->control->appl_ptr;
snd_pcm_sframes_t diff = appl_ptr - pcm->appl_ptr;
snd_pcm_uframes_t buffer_size = pcm->buffer_size / 2;
if (diff) {
if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2))
diff += runtime->boundary;
frames += diff;
pcm->sw_ready += diff;
pcm->appl_ptr = appl_ptr;
}
pcm->sw_ready += frames;
pcm->appl_ptr = appl_ptr + frames;
while (pcm->hw_ready < buffer_size &&
pcm->sw_ready > 0) {
size_t hw_to_end = buffer_size - pcm->hw_data;
......@@ -632,7 +631,7 @@ static int snd_emu10k1_fx8010_playback_trigger(snd_pcm_substream_t * substream,
result = snd_emu10k1_fx8010_register_irq_handler(emu, snd_emu10k1_fx8010_playback_irq, pcm->gpr_running, substream, &pcm->irq);
if (result < 0)
goto __err;
snd_emu10k1_fx8010_playback_transfer(substream, 0); /* roll the ball */
snd_emu10k1_fx8010_playback_transfer(substream); /* roll the ball */
snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_trigger, 0, 1);
break;
case SNDRV_PCM_TRIGGER_STOP:
......@@ -670,28 +669,10 @@ static snd_pcm_uframes_t snd_emu10k1_fx8010_playback_pointer(snd_pcm_substream_t
pcm->sw_io += frames;
if (pcm->sw_io > runtime->buffer_size)
pcm->sw_io -= runtime->buffer_size;
snd_emu10k1_fx8010_playback_transfer(substream, 0);
snd_emu10k1_fx8010_playback_transfer(substream);
return pcm->sw_io;
}
static int snd_emu10k1_fx8010_playback_copy(snd_pcm_substream_t *substream,
int channel,
snd_pcm_uframes_t hwoff,
void *src,
snd_pcm_uframes_t frames)
{
snd_pcm_runtime_t *runtime = substream->runtime;
size_t hwoffb = hwoff << 2;
size_t bytes = frames << 2;
char *hwbuf = runtime->dma_area + hwoffb;
if (copy_from_user(hwbuf, src, bytes))
return -EFAULT;
spin_lock_irq(&runtime->lock);
snd_emu10k1_fx8010_playback_transfer(substream, frames);
spin_unlock_irq(&runtime->lock);
return 0;
}
static snd_pcm_hardware_t snd_emu10k1_fx8010_playback =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
......@@ -748,8 +729,8 @@ static snd_pcm_ops_t snd_emu10k1_fx8010_playback_ops = {
.hw_free = snd_emu10k1_fx8010_playback_hw_free,
.prepare = snd_emu10k1_fx8010_playback_prepare,
.trigger = snd_emu10k1_fx8010_playback_trigger,
.copy = snd_emu10k1_fx8010_playback_copy,
.pointer = snd_emu10k1_fx8010_playback_pointer,
.ack = snd_emu10k1_fx8010_playback_transfer,
};
static void snd_emu10k1_fx8010_pcm_free(snd_pcm_t *pcm)
......@@ -1252,12 +1233,14 @@ static void __devinit snd_emu10k1_init_stereo_onoff_control(emu10k1_fx8010_contr
* initial DSP configuration for Audigy
*/
#define A_GPR_ACCU 0xd6
static int __devinit _snd_emu10k1_audigy_init_efx(emu10k1_t *emu)
{
int err, i, gpr, tmp, playback, capture, nctl;
int err, i, z, gpr, tmp, playback, capture, nctl;
u32 ptr;
emu10k1_fx8010_code_t *icode;
emu10k1_fx8010_control_gpr_t *controls;
emu10k1_fx8010_control_gpr_t *controls, *ctl;
mm_segment_t seg;
spin_lock_init(&emu->fx8010.irq_lock);
......@@ -1278,9 +1261,9 @@ static int __devinit _snd_emu10k1_audigy_init_efx(emu10k1_t *emu)
ptr = 0;
nctl = 0;
playback = 10;
capture = playback + 10; /* we reserve 10 voices */
capture = playback + (SND_EMU10K1_PLAYBACK_CHANNELS * 2); /* we reserve 10 voices */
gpr = capture + 10;
tmp = 0x80;
tmp = 0x88;
/* stop FX processor */
snd_emu10k1_ptr_write(emu, A_DBG, 0, (emu->fx8010.dbg = 0) | A_DBG_SINGLE_STEP);
......@@ -1422,21 +1405,111 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
#define A_PUT_STEREO_OUTPUT(out1,out2,src) \
{A_PUT_OUTPUT(out1,src); A_PUT_OUTPUT(out2,src+1);}
#define _A_SWITCH(icode, ptr, dst, src, sw) \
A_OP((icode), ptr, iMACINT0, dst, A_C_00000000, src, sw);
#define A_SWITCH(icode, ptr, dst, src, sw) \
_A_SWITCH(icode, ptr, A_GPR(dst), A_GPR(src), A_GPR(sw))
#define _A_SWITCH_NEG(icode, ptr, dst, src) \
A_OP((icode), ptr, iANDXOR, dst, src, A_C_00000001, A_C_00000001);
#define A_SWITCH_NEG(icode, ptr, dst, src) \
_A_SWITCH_NEG(icode, ptr, A_GPR(dst), A_GPR(src))
/*
* Process tone control
*/
A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 0), A_GPR(playback + 0), A_C_00000000, A_C_00000000); /* left */
A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 1), A_GPR(playback + 1), A_C_00000000, A_C_00000000); /* right */
A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 2), A_GPR(playback + 2), A_C_00000000, A_C_00000000); /* rear left */
A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 3), A_GPR(playback + 3), A_C_00000000, A_C_00000000); /* rear right */
A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 4), A_GPR(playback + 4), A_C_00000000, A_C_00000000); /* center */
A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 5), A_GPR(playback + 5), A_C_00000000, A_C_00000000); /* LFE */
ctl = &controls[nctl + 0];
ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
strcpy(ctl->id.name, "Tone Control - Bass");
ctl->vcount = 2;
ctl->count = 10;
ctl->min = 0;
ctl->max = 40;
ctl->value[0] = ctl->value[1] = 20;
ctl->translation = EMU10K1_GRP_TRANSLATION_BASS;
ctl = &controls[nctl + 1];
ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
strcpy(ctl->id.name, "Tone Control - Treble");
ctl->vcount = 2;
ctl->count = 10;
ctl->min = 0;
ctl->max = 40;
ctl->value[0] = ctl->value[1] = 20;
ctl->translation = EMU10K1_GRP_TRANSLATION_TREBLE;
#define BASS_GPR 0x8c
#define TREBLE_GPR 0x96
for (z = 0; z < 5; z++) {
int j;
for (j = 0; j < 2; j++) {
controls[nctl + 0].gpr[z * 2 + j] = BASS_GPR + z * 2 + j;
controls[nctl + 1].gpr[z * 2 + j] = TREBLE_GPR + z * 2 + j;
}
}
for (z = 0; z < 3; z++) { /* front/rear/center-lfe */
int j, k, l, d;
for (j = 0; j < 2; j++) { /* left/right */
k = 0xb0 + (z * 8) + (j * 4);
l = 0xe0 + (z * 8) + (j * 4);
d = playback + SND_EMU10K1_PLAYBACK_CHANNELS + z * 2 + j;
A_OP(icode, &ptr, iMAC0, A_C_00000000, A_C_00000000, A_GPR(d), A_GPR(BASS_GPR + 0 + j));
A_OP(icode, &ptr, iMACMV, A_GPR(k+1), A_GPR(k), A_GPR(k+1), A_GPR(BASS_GPR + 4 + j));
A_OP(icode, &ptr, iMACMV, A_GPR(k), A_GPR(d), A_GPR(k), A_GPR(BASS_GPR + 2 + j));
A_OP(icode, &ptr, iMACMV, A_GPR(k+3), A_GPR(k+2), A_GPR(k+3), A_GPR(BASS_GPR + 8 + j));
A_OP(icode, &ptr, iMAC0, A_GPR(k+2), A_GPR_ACCU, A_GPR(k+2), A_GPR(BASS_GPR + 6 + j));
A_OP(icode, &ptr, iACC3, A_GPR(k+2), A_GPR(k+2), A_GPR(k+2), A_C_00000000);
A_OP(icode, &ptr, iMAC0, A_C_00000000, A_C_00000000, A_GPR(k+2), A_GPR(TREBLE_GPR + 0 + j));
A_OP(icode, &ptr, iMACMV, A_GPR(l+1), A_GPR(l), A_GPR(l+1), A_GPR(TREBLE_GPR + 4 + j));
A_OP(icode, &ptr, iMACMV, A_GPR(l), A_GPR(k+2), A_GPR(l), A_GPR(TREBLE_GPR + 2 + j));
A_OP(icode, &ptr, iMACMV, A_GPR(l+3), A_GPR(l+2), A_GPR(l+3), A_GPR(TREBLE_GPR + 8 + j));
A_OP(icode, &ptr, iMAC0, A_GPR(l+2), A_GPR_ACCU, A_GPR(l+2), A_GPR(TREBLE_GPR + 6 + j));
A_OP(icode, &ptr, iMACINT0, A_GPR(l+2), A_C_00000000, A_GPR(l+2), A_C_00000010);
A_OP(icode, &ptr, iACC3, A_GPR(d), A_GPR(l+2), A_C_00000000, A_C_00000000);
if (z == 2) /* center */
break;
}
}
nctl += 2;
#undef BASS_GPR
#undef TREBLE_GPR
for (z = 0; z < 6; z++) {
A_SWITCH(icode, &ptr, tmp + 0, playback + SND_EMU10K1_PLAYBACK_CHANNELS + z, gpr + 0);
A_SWITCH_NEG(icode, &ptr, tmp + 1, gpr + 0);
A_SWITCH(icode, &ptr, tmp + 1, playback + z, tmp + 1);
A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + z), A_GPR(tmp + 0), A_GPR(tmp + 1), A_C_00000000);
}
snd_emu10k1_init_stereo_onoff_control(controls + nctl++, "Tone Control - Switch", gpr, 0);
gpr += 2;
/* digital outputs */
A_PUT_STEREO_OUTPUT(A_EXTOUT_FRONT_L, A_EXTOUT_FRONT_R, playback);
A_PUT_STEREO_OUTPUT(A_EXTOUT_REAR_L, A_EXTOUT_REAR_R, playback+2);
A_PUT_OUTPUT(A_EXTOUT_CENTER, playback+4);
A_PUT_OUTPUT(A_EXTOUT_LFE, playback+5);
A_PUT_STEREO_OUTPUT(A_EXTOUT_FRONT_L, A_EXTOUT_FRONT_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS);
A_PUT_STEREO_OUTPUT(A_EXTOUT_REAR_L, A_EXTOUT_REAR_R, playback+2 + SND_EMU10K1_PLAYBACK_CHANNELS);
A_PUT_OUTPUT(A_EXTOUT_CENTER, playback+4 + SND_EMU10K1_PLAYBACK_CHANNELS);
A_PUT_OUTPUT(A_EXTOUT_LFE, playback+5 + SND_EMU10K1_PLAYBACK_CHANNELS);
/* analog speakers */
//A_PUT_STEREO_OUTPUT(A_EXTOUT_AFRONT_L, A_EXTOUT_AFRONT_R, playback);
A_PUT_STEREO_OUTPUT(A_EXTOUT_AC97_L, A_EXTOUT_AC97_R, playback);
A_PUT_STEREO_OUTPUT(A_EXTOUT_AREAR_L, A_EXTOUT_AREAR_R, playback+2);
A_PUT_OUTPUT(A_EXTOUT_ACENTER, playback+4);
A_PUT_OUTPUT(A_EXTOUT_ALFE, playback+5);
//A_PUT_STEREO_OUTPUT(A_EXTOUT_AFRONT_L, A_EXTOUT_AFRONT_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS);
A_PUT_STEREO_OUTPUT(A_EXTOUT_AC97_L, A_EXTOUT_AC97_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS);
A_PUT_STEREO_OUTPUT(A_EXTOUT_AREAR_L, A_EXTOUT_AREAR_R, playback+2 + SND_EMU10K1_PLAYBACK_CHANNELS);
A_PUT_OUTPUT(A_EXTOUT_ACENTER, playback+4 + SND_EMU10K1_PLAYBACK_CHANNELS);
A_PUT_OUTPUT(A_EXTOUT_ALFE, playback+5 + SND_EMU10K1_PLAYBACK_CHANNELS);
/* headphone */
A_PUT_STEREO_OUTPUT(A_EXTOUT_HEADPHONE_L, A_EXTOUT_HEADPHONE_R, playback);
A_PUT_STEREO_OUTPUT(A_EXTOUT_HEADPHONE_L, A_EXTOUT_HEADPHONE_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS);
/* ADC buffer */
A_PUT_OUTPUT(A_EXTOUT_ADC_CAP_L, capture);
......
......@@ -1508,12 +1508,16 @@ static struct _ac97_ali_rate_regs {
{ ALID_SPDIFIN, { 0, 0, 0 }, -1 },
};
static struct ac97_quirk ac97_quirks[] = {
{ 0x1028, 0x0126, "Dell Optiplex GX260", AC97_TUNE_HP_ONLY },
{ } /* terminator */
};
static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock)
{
ac97_t ac97, *x97;
ichdev_t *ichdev;
int err, i, channels = 2, codecs;
int err, i, num, channels = 2, codecs, _codecs;
unsigned int glob_sta = 0;
for (i = 0; i <= ICHD_LAST; i++) {
......@@ -1589,6 +1593,7 @@ static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock)
if ((err = snd_ac97_mixer(chip->card, &ac97, &x97)) < 0)
return err;
chip->ac97[0] = x97;
snd_ac97_tune_hardware(chip->ac97[0], chip->pci, ac97_quirks);
chip->ichd[ICHD_PCMOUT].ac97 = x97;
chip->ichd[ICHD_PCMIN].ac97 = x97;
if (x97->ext_id & AC97_EI_VRM)
......@@ -1604,20 +1609,20 @@ static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock)
snd_ac97_update_bits(x97, AC97_EXTENDED_ID, AC97_EI_DACS_SLOT_MASK, 0);
/* AnalogDevices CNR boards uses special codec chaining */
/* skip standard test method for secondary codecs in this case */
if (x97->flags & AC97_AD_MULTI) {
if (x97->flags & AC97_AD_MULTI)
codecs = 1;
goto __skip_secondary;
}
if (codecs < 2)
goto __skip_secondary;
for (i = 1; i < codecs; i++) {
ac97.num = i;
for (i = 1, num = 1, _codecs = codecs; num < _codecs; num++) {
ac97.num = num;
if ((err = snd_ac97_mixer(chip->card, &ac97, &x97)) < 0) {
snd_printk("Unable to initialize codec #%i [device = %i, GLOB_STA = 0x%x]\n", i, chip->device_type, glob_sta);
codecs = i;
break;
codecs--;
continue;
}
chip->ac97[i] = x97;
chip->ac97[i++] = x97;
if (!ac97_is_audio(x97))
continue;
switch (chip->device_type) {
case DEVICE_INTEL_ICH4:
if (chip->ichd[ICHD_PCM2IN].ac97 == NULL)
......@@ -1656,14 +1661,16 @@ static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock)
}
iputbyte(chip, ICHREG(SDM), tmp);
}
for (i = 0; i < 3; i++) {
if ((x97 = chip->ac97[i]) == NULL)
for (i = 0; i < codecs; i++) {
x97 = chip->ac97[i];
if (!ac97_is_audio(x97))
continue;
if (x97->scaps & AC97_SCAP_SURROUND_DAC)
chip->multi4 = 1;
}
for (i = 0; i < 3 && chip->multi4; i++) {
if ((x97 = chip->ac97[i]) == NULL)
for (i = 0; i < codecs && chip->multi4; i++) {
x97 = chip->ac97[i];
if (!ac97_is_audio(x97))
continue;
if (x97->scaps & AC97_SCAP_CENTER_LFE_DAC)
chip->multi6 = 1;
......@@ -1674,7 +1681,10 @@ static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock)
if (chip->multi4)
goto __6ch;
for ( ; i < codecs; i++) {
if (ac97_is_rev22(x97 = chip->ac97[i])) {
x97 = chip->ac97[i];
if (!ac97_is_audio(x97))
continue;
if (ac97_is_rev22(x97)) {
snd_ac97_update_bits(x97, AC97_EXTENDED_ID, AC97_EI_DACS_SLOT_MASK, 1);
chip->multi4 = 1;
break;
......@@ -1682,7 +1692,10 @@ static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock)
}
__6ch:
for ( ; i < codecs && chip->multi4; i++) {
if (ac97_is_rev22(x97 = chip->ac97[i])) {
x97 = chip->ac97[i];
if (!ac97_is_audio(x97))
continue;
if (ac97_is_rev22(x97)) {
snd_ac97_update_bits(x97, AC97_EXTENDED_ID, AC97_EI_DACS_SLOT_MASK, 2);
chip->multi6 = 1;
break;
......@@ -1691,7 +1704,10 @@ static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock)
/* ok, some older codecs might support only AMAP */
if (!chip->multi4) {
for (i = 1; i < codecs; i++) {
if (ac97_can_amap(x97 = chip->ac97[i])) {
x97 = chip->ac97[i];
if (!ac97_is_audio(x97))
continue;
if (ac97_can_amap(x97)) {
if (x97->addr == 1) {
chip->multi4 = 1;
break;
......@@ -1699,7 +1715,9 @@ static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock)
}
}
for ( ; i < codecs && chip->multi4; i++) {
if (ac97_can_amap(x97 = chip->ac97[i])) {
if (!ac97_is_audio(x97))
continue;
if (ac97_can_amap(x97)) {
if (x97->addr == 2) {
chip->multi6 = 1;
break;
......
This diff is collapsed.
......@@ -820,6 +820,7 @@ static int snd_via686_playback_prepare(snd_pcm_substream_t *substream)
snd_pcm_runtime_t *runtime = substream->runtime;
snd_ac97_set_rate(chip->ac97, AC97_PCM_FRONT_DAC_RATE, runtime->rate);
snd_ac97_set_rate(chip->ac97, AC97_SPDIF, runtime->rate);
via686_setup_format(chip, viadev, runtime);
return 0;
}
......@@ -909,18 +910,37 @@ static int snd_via8233_multi_prepare(snd_pcm_substream_t *substream)
snd_via82xx_channel_reset(chip, viadev);
snd_via82xx_set_table_ptr(chip, viadev);
/* FIXME: a more generic solutions would be better */
if (chip->chip_type == TYPE_VIA8233A) {
/* VIA8233A cannot change the slot mapping, so we need
* to swap the RL/RR with C/L.
*/
#define AC97_ID_ALC650 0x414c4720
if (chip->ac97->id == AC97_ID_ALC650) {
unsigned short val;
if (runtime->channels > 4)
/* slot mapping: 3,4,7,8 */
val = 0;
else
/* slot mapping: 3,4,6,9,7,8 */
val = 0x4000;
snd_ac97_update_bits(chip->ac97, AC97_ALC650_MULTICH, 0xc000, val);
}
}
fmt = (runtime->format == SNDRV_PCM_FORMAT_S16_LE) ? VIA_REG_MULTPLAY_FMT_16BIT : VIA_REG_MULTPLAY_FMT_8BIT;
fmt |= runtime->channels << 4;
outb(fmt, VIADEV_REG(viadev, OFS_MULTPLAY_FORMAT));
/* set sample number to slot 3, 4, 7, 8, 6, 9 */
/* set sample number to slot 3, 4, 7, 8, 6, 9 (for VIA8233/C,8235) */
/* corresponding to FL, FR, RL, RR, C, LFE ?? */
switch (runtime->channels) {
case 1: slots = (1<<0) | (1<<4); break;
case 2: slots = (1<<0) | (2<<4); break;
case 3: slots = (1<<0) | (2<<4) | (5<<8); break;
case 4: slots = (1<<0) | (2<<4) | (3<<8) | (4<<12); break;
case 5: slots = (1<<0) | (2<<4) | (5<<8) | (3<<12) | (4<<16); break;
case 6: slots = (1<<0) | (2<<4) | (5<<8) | (6<<12) | (3<<16) | (4<<20); break;
case 5: slots = (1<<0) | (2<<4) | (3<<8) | (4<<12) | (5<<16); break;
case 6: slots = (1<<0) | (2<<4) | (3<<8) | (4<<12) | (5<<16) | (6<<20); break;
default: slots = 0; break;
}
/* STOP index is never reached */
......@@ -1438,7 +1458,7 @@ static void snd_via82xx_mixer_free_ac97(ac97_t *ac97)
}
static struct ac97_quirk ac97_quirks[] = {
{ 0x1106, 0x4161, AC97_TUNE_HP_ONLY }, /* ASRock K7VT2 */
{ 0x1106, 0x4161, "ASRock K7VT2", AC97_TUNE_HP_ONLY },
{ } /* terminator */
};
......@@ -1457,7 +1477,7 @@ static int __devinit snd_via82xx_mixer_new(via82xx_t *chip)
if ((err = snd_ac97_mixer(chip->card, &ac97, &chip->ac97)) < 0)
return err;
snd_ac97_tune_hardware(&chip->ac97, chip->pci, ac97_quirks);
snd_ac97_tune_hardware(chip->ac97, chip->pci, ac97_quirks);
if (chip->chip_type != TYPE_VIA686) {
/* use slot 10/11 */
......
......@@ -1051,7 +1051,7 @@ static int set_format(snd_usb_substream_t *subs, snd_pcm_runtime_t *runtime)
}
/* create a data pipe */
ep = get_endpoint(alts, 0)->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
ep = fmt->endpoint & USB_ENDPOINT_NUMBER_MASK;
if (is_playback)
subs->datapipe = usb_sndisocpipe(dev, ep);
else
......@@ -1062,9 +1062,16 @@ static int set_format(snd_usb_substream_t *subs, snd_pcm_runtime_t *runtime)
subs->fill_max = 0;
/* we need a sync pipe in async OUT or adaptive IN mode */
attr = get_endpoint(alts, 0)->bmAttributes & EP_ATTR_MASK;
attr = fmt->ep_attr & EP_ATTR_MASK;
if ((is_playback && attr == EP_ATTR_ASYNC) ||
(! is_playback && attr == EP_ATTR_ADAPTIVE)) {
/*
* QUIRK: plantronics headset has adaptive-in
* although it's really not...
*/
if (dev->descriptor.idVendor == 0x047f &&
dev->descriptor.idProduct == 0x0ca1)
goto _ok;
/* check endpoint */
if (altsd->bNumEndpoints < 2 ||
get_endpoint(alts, 1)->bmAttributes != 0x01 ||
......@@ -1088,6 +1095,7 @@ static int set_format(snd_usb_substream_t *subs, snd_pcm_runtime_t *runtime)
subs->syncinterval = get_endpoint(alts, 1)->bRefresh;
}
_ok:
if ((err = init_usb_pitch(dev, subs->interface, alts, fmt)) < 0 ||
(err = init_usb_sample_rate(dev, subs->interface, alts, fmt,
runtime->rate)) < 0)
......@@ -1651,7 +1659,7 @@ static void proc_dump_substream_formats(snd_usb_substream_t *subs, snd_info_buff
fp->endpoint & USB_DIR_IN ? "IN" : "OUT",
sync_types[(fp->ep_attr & EP_ATTR_MASK) >> 2]);
if (fp->rates & SNDRV_PCM_RATE_CONTINUOUS) {
snd_iprintf(buffer, " Rates: %d - %d (continous)\n",
snd_iprintf(buffer, " Rates: %d - %d (continuous)\n",
fp->rate_min, fp->rate_max);
} else {
unsigned int i;
......
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