Commit 40290333 authored by Jaroslav Kysela's avatar Jaroslav Kysela Committed by Linus Torvalds

[PATCH] ALSA update [4/10] - 2002/07/14

  - seq_virmidi - exported snd_virmidi_receive() for processing the incoming events from the event handler of a remote virmidi port.
  - pcm_lib.c - fixed wrong spinlock
  - AC'97 code
    - added VIA codecs, fixed order
    - added S/PDIF support for Conexant CX20468
  - ALI5451 - fixed wrong spinlock
  - ES1968 - fixed wrong mutex
  - ICE1712 - fixed SMP dead-lock
  - HDSP driver update
  - RME9652 - fixed wrong spinlock
parent f7fb77bf
......@@ -151,8 +151,8 @@ static inline int snd_info_done(void) { return 0; }
static inline int snd_info_get_line(snd_info_buffer_t * buffer, char *line, int len) { return 0; }
static inline char *snd_info_get_str(char *dest, char *src, int len) { return NULL; }
static inline snd_info_entry_t *snd_info_create_module_entry(struct module * module, const char *name, snd_info_entry_t *parent) { return NULL; }
static inline snd_info_entry_t *snd_info_create_card_entry(snd_card_t * card, const char *name, snd_info_entry_t *parent) { return NULL; }
static inline snd_info_entry_t *snd_info_create_module_entry(struct module * module, const char *name, snd_info_entry_t * parent) { return NULL; }
static inline snd_info_entry_t *snd_info_create_card_entry(snd_card_t * card, const char *name, snd_info_entry_t * parent) { return NULL; }
static inline void snd_info_free_entry(snd_info_entry_t * entry) { ; }
static inline snd_info_entry_t *snd_info_create_device(const char *name,
unsigned int number,
......
......@@ -45,7 +45,7 @@ typedef struct _snd_virmidi {
snd_rawmidi_substream_t *substream;
} snd_virmidi_t;
#define SNDRV_VIRMIDI_SUBSCRIBE (1<<0)
#define SNDRV_VIRMIDI_SUBSCRIBE (1<<0)
#define SNDRV_VIRMIDI_USE (1<<1)
/*
......@@ -69,14 +69,16 @@ struct _snd_virmidi_dev {
* ATTACH = input/output events from midi device are routed to the
* attached sequencer port. sequencer port is not created
* by virmidi itself.
* the input to rawmidi must be processed by passing the
* incoming events via snd_virmidi_receive()
* DISPATCH = input/output events are routed to subscribers.
* sequencer port is created in virmidi.
*/
#define SNDRV_VIRMIDI_SEQ_NONE 0
#define SNDRV_VIRMIDI_SEQ_ATTACH 1
#define SNDRV_VIRMIDI_SEQ_ATTACH 1
#define SNDRV_VIRMIDI_SEQ_DISPATCH 2
int snd_virmidi_new(snd_card_t *card, int device, snd_rawmidi_t **rrmidi);
int snd_virmidi_receive(snd_rawmidi_t *rmidi, snd_seq_event_t *ev);
#endif /* __SOUND_SEQ_VIRMIDI */
/* include/version.h. Generated automatically by configure. */
#define CONFIG_SND_VERSION "0.9.0rc2"
#define CONFIG_SND_DATE " (Wed Jul 03 16:51:35 2002 UTC)"
#define CONFIG_SND_DATE " (Sun Jul 14 21:30:57 2002 UTC)"
......@@ -1899,7 +1899,7 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(snd_pcm_substream_t *substream,
frames = cont;
if (frames == 0 && runtime->status->state == SNDRV_PCM_STATE_PAUSED) {
err = -EPIPE;
goto _end;
goto _end_unlock;
}
snd_assert(frames != 0,
spin_unlock_irq(&runtime->lock);
......
......@@ -89,11 +89,6 @@ static int snd_virmidi_dev_receive_event(snd_virmidi_dev_t *rdev, snd_seq_event_
unsigned char msg[4];
int len;
snd_assert(rdev != NULL, return -EINVAL);
if (!(rdev->flags & SNDRV_VIRMIDI_USE))
return 0; /* ignored */
read_lock(&rdev->filelist_lock);
list_for_each(list, &rdev->filelist) {
vmidi = list_entry(list, snd_virmidi_t, list);
......@@ -115,14 +110,32 @@ static int snd_virmidi_dev_receive_event(snd_virmidi_dev_t *rdev, snd_seq_event_
}
/*
* event_input callback from sequencer
* receive an event from the remote virmidi port
*
* for rawmidi inputs, you can call this function from the event
* handler of a remote port which is attached to the virmidi via
* SNDRV_VIRMIDI_SEQ_ATTACH.
*/
/* exported */
int snd_virmidi_receive(snd_rawmidi_t *rmidi, snd_seq_event_t *ev)
{
snd_virmidi_dev_t *rdev;
rdev = snd_magic_cast(snd_virmidi_dev_t, rmidi->private_data, return -EINVAL);
return snd_virmidi_dev_receive_event(rdev, ev);
}
/*
* event handler of virmidi port
*/
int snd_virmidi_receive(snd_seq_event_t *ev, int direct,
void *private_data, int atomic, int hop)
static int snd_virmidi_event_input(snd_seq_event_t *ev, int direct,
void *private_data, int atomic, int hop)
{
snd_virmidi_dev_t *rdev;
rdev = snd_magic_cast(snd_virmidi_dev_t, private_data, return -EINVAL);
if (!(rdev->flags & SNDRV_VIRMIDI_USE))
return 0; /* ignored */
return snd_virmidi_dev_receive_event(rdev, ev);
}
......@@ -387,7 +400,7 @@ static int snd_virmidi_dev_attach_seq(snd_virmidi_dev_t *rdev)
pcallbacks.unsubscribe = snd_virmidi_unsubscribe;
pcallbacks.use = snd_virmidi_use;
pcallbacks.unuse = snd_virmidi_unuse;
pcallbacks.event_input = snd_virmidi_receive;
pcallbacks.event_input = snd_virmidi_event_input;
pinfo.kernel = &pcallbacks;
err = snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_CREATE_PORT, &pinfo);
if (err < 0) {
......@@ -470,7 +483,9 @@ static void snd_virmidi_free(snd_rawmidi_t *rmidi)
/*
* create a new device
*
*/
/* exported */
int snd_virmidi_new(snd_card_t *card, int device, snd_rawmidi_t **rrmidi)
{
snd_rawmidi_t *rmidi;
......@@ -525,3 +540,4 @@ module_init(alsa_virmidi_init)
module_exit(alsa_virmidi_exit)
EXPORT_SYMBOL(snd_virmidi_new);
EXPORT_SYMBOL(snd_virmidi_receive);
......@@ -79,17 +79,19 @@ static const ac97_codec_id_t snd_ac97_codec_id_vendors[] = {
{ 0x414c4300, 0xffffff00, "Realtek", NULL },
{ 0x414c4700, 0xffffff00, "Avance Logic", NULL },
{ 0x43525900, 0xffffff00, "Cirrus Logic", NULL },
{ 0x43585400, 0xffffff00, "Conexant", NULL },
{ 0x45838300, 0xffffff00, "ESS Technology", NULL },
{ 0x48525300, 0xffffff00, "Intersil", NULL },
{ 0x49434500, 0xffffff00, "ICEnsemble", NULL },
{ 0x4e534300, 0xffffff00, "National Semiconductor", NULL },
{ 0x53494c00, 0xffffff00, "Silicon Laboratory", NULL },
{ 0x54524100, 0xffffff00, "TriTech", NULL },
{ 0x54584e00, 0xffffff00, "Texas Instruments", NULL },
{ 0x56494100, 0xffffff00, "VIA Technologies", NULL },
{ 0x57454300, 0xffffff00, "Winbond", NULL },
{ 0x574d4c00, 0xffffff00, "Wolfson", NULL },
{ 0x594d4800, 0xffffff00, "Yamaha", NULL },
{ 0x83847600, 0xffffff00, "SigmaTel", NULL },
{ 0x45838300, 0xffffff00, "ESS Technology", NULL },
{ 0, 0, NULL, NULL }
};
......@@ -115,12 +117,14 @@ static const ac97_codec_id_t snd_ac97_codec_ids[] = {
{ 0x414c4750, 0xfffffff0, "ALC250", NULL },
{ 0x43525900, 0xfffffff8, "CS4297", NULL },
{ 0x43525910, 0xfffffff8, "CS4297A", patch_cirrus_spdif },
{ 0x42525920, 0xfffffff8, "CS4294/4298", NULL },
{ 0x42525928, 0xfffffff8, "CS4294", NULL },
{ 0x43525920, 0xfffffff8, "CS4294/4298", NULL },
{ 0x43525928, 0xfffffff8, "CS4294", NULL },
{ 0x43525930, 0xfffffff8, "CS4299", patch_cirrus_cs4299 },
{ 0x43525948, 0xfffffff8, "CS4201", NULL },
{ 0x43525958, 0xfffffff8, "CS4205", patch_cirrus_spdif },
{ 0x43525960, 0xfffffff8, "CS4291", NULL },
{ 0x43585429, 0xffffffff, "Cx20468", patch_conexant },
{ 0x45838308, 0xffffffff, "ESS1988", NULL },
{ 0x48525300, 0xffffff00, "HMP9701", NULL },
{ 0x49434501, 0xffffffff, "ICE1230", NULL },
{ 0x49434511, 0xffffffff, "ICE1232", NULL }, // alias VIA VT1611A?
......@@ -131,6 +135,7 @@ static const ac97_codec_id_t snd_ac97_codec_ids[] = {
{ 0x54524108, 0xffffffff, "TR28028", patch_tritech_tr28028 }, // added by xin jin [07/09/99]
{ 0x54524123, 0xffffffff, "TR28602", NULL }, // only guess --jk [TR28023 = eMicro EM28023 (new CT1297)]
{ 0x54584e20, 0xffffffff, "TLC320AD9xC", NULL },
{ 0x56494161, 0xffffffff, "VIA1612A", NULL }, // modified ICE1232 with S/PDIF
{ 0x57454301, 0xffffffff, "W83971D", NULL },
{ 0x574d4c00, 0xffffffff, "WM9701A", patch_wolfson00 },
{ 0x574d4c03, 0xffffffff, "WM9703/9707", patch_wolfson03 },
......@@ -143,8 +148,6 @@ static const ac97_codec_id_t snd_ac97_codec_ids[] = {
{ 0x83847609, 0xffffffff, "STAC9721/23", patch_sigmatel_stac9721 },
{ 0x83847644, 0xffffffff, "STAC9744", patch_sigmatel_stac9744 },
{ 0x83847656, 0xffffffff, "STAC9756/57", patch_sigmatel_stac9756 },
{ 0x45838308, 0xffffffff, "ESS1988", NULL },
{ 0x43585429, 0xffffffff, "Cx20468", patch_conexant },
{ 0, 0, NULL, NULL }
};
......
......@@ -1440,8 +1440,10 @@ static int snd_ali_capture_prepare(snd_pcm_substream_t * substream)
unsigned int rate;
if (codec->revision != ALI_5451_V02)
if (codec->revision != ALI_5451_V02) {
spin_unlock_irqrestore(&codec->reg_lock, flags);
return -1;
}
rate = snd_ali_get_spdif_in_rate(codec);
if (rate == 0) {
snd_printk("ali_capture_preapre: spdif rate detect err!\n");
......
......@@ -1446,8 +1446,10 @@ static esm_memory_t *snd_es1968_new_memory(es1968_t *chip, int size)
__found:
if (buf->size > size) {
esm_memory_t *chunk = kmalloc(sizeof(*chunk), GFP_KERNEL);
if (chunk == NULL)
if (chunk == NULL) {
up(&chip->memory_mutex);
return NULL;
}
chunk->size = buf->size - size;
chunk->buf = buf->buf + size;
chunk->addr = buf->addr + size;
......
......@@ -1142,6 +1142,8 @@ static int snd_ice1712_cs8427_set_input_clock(ice1712_t *ice, int spdif_clock)
{
unsigned char reg[2] = { 0x80 | 4, 0 }; /* CS8427 auto increment | register number 4 + data */
unsigned char val, nval;
int res = 0;
snd_i2c_lock(ice->i2c);
if (snd_i2c_sendbytes(ice->cs8427, reg, 1) != 1) {
snd_i2c_unlock(ice->i2c);
......@@ -1159,13 +1161,13 @@ static int snd_ice1712_cs8427_set_input_clock(ice1712_t *ice, int spdif_clock)
if (val != nval) {
reg[1] = nval;
if (snd_i2c_sendbytes(ice->cs8427, reg, 2) != 2) {
snd_i2c_unlock(ice->i2c);
return -EREMOTE;
res = -EREMOTE;
} else {
res++;
}
return 1;
}
snd_i2c_unlock(ice->i2c);
return 0;
return res;
}
/*
......
/* stored in little-endian */
static u32 digiface_firmware[97652] __devinitdata = {
static u32 digiface_firmware[24413] __devinitdata = {
0xffffffff, 0x66aa9955, 0x8001000c, 0xe0000000, 0x8006800c, 0xb0000000,
0x8004800c, 0xb4fc0100, 0x8003000c, 0x00000000, 0x8001000c, 0x90000000,
0x8004000c, 0x00000000, 0x8001000c, 0x80000000, 0x0002000c, 0x581a000a,
......
......@@ -42,6 +42,8 @@ static int snd_index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *snd_id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
static int snd_enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
static int snd_precise_ptr[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 0 }; /* Enable precise pointer */
static int snd_line_outs_monitor[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 0}; /* Send all inputs/playback to line outs */
static int snd_force_firmware[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 0}; /* Force firmware reload */
MODULE_PARM(snd_index, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
MODULE_PARM_DESC(snd_index, "Index value for RME Hammerfall DSP interface.");
......@@ -55,8 +57,14 @@ MODULE_PARM_SYNTAX(snd_enable, SNDRV_ENABLE_DESC);
MODULE_PARM(snd_precise_ptr, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
MODULE_PARM_DESC(snd_precise_ptr, "Enable precise pointer (doesn't work reliably).");
MODULE_PARM_SYNTAX(snd_precise_ptr, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC);
MODULE_PARM(snd_line_outs_monitor,"1-" __MODULE_STRING(SNDRV_CARDS) "i");
MODULE_PARM_DESC(snd_line_outs_monitor, "Send all input and playback streams to line outs by default.");
MODULE_PARM_SYNTAX(snd_line_outs_monitor, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC);
MODULE_PARM(snd_force_firmware,"1-" __MODULE_STRING(SNDRV_CARDS) "i");
MODULE_PARM_DESC(snd_force_firmware, "Force a reload of the I/O box firmware");
MODULE_PARM_SYNTAX(snd_force_firmware, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC);
MODULE_AUTHOR("Paul Davis <pbd@op.net>");
MODULE_DESCRIPTION("RME Hammerfall DDSP");
MODULE_DESCRIPTION("RME Hammerfall DSP");
MODULE_LICENSE("GPL");
MODULE_CLASSES("{sound}");
MODULE_DEVICES("{{RME,Hammerfall-DSP},");
......@@ -2190,6 +2198,25 @@ static void snd_hdsp_set_defaults(hdsp_t *hdsp)
for (i = 0; i < 2048; i++)
hdsp_write_gain (hdsp, i, MINUS_INFINITY_GAIN);
if (snd_line_outs_monitor[hdsp->dev]) {
snd_printk ("sending all inputs and playback streams to line outs.\n");
/* route all inputs to the line outs for easy monitoring. send
odd numbered channels to right, even to left.
*/
for (i = 0; i < HDSP_MAX_CHANNELS; i++) {
if (i & 1) {
hdsp_write_gain (hdsp, INPUT_TO_OUTPUT_KEY (i, 26), UNITY_GAIN);
hdsp_write_gain (hdsp, PLAYBACK_TO_OUTPUT_KEY (i, 26), UNITY_GAIN);
} else {
hdsp_write_gain (hdsp, INPUT_TO_OUTPUT_KEY (i, 27), UNITY_GAIN);
hdsp_write_gain (hdsp, PLAYBACK_TO_OUTPUT_KEY (i, 27), UNITY_GAIN);
}
}
}
hdsp->passthru = 0;
/* set a default rate so that the channel map is set up.
......@@ -2812,7 +2839,6 @@ static int __devinit snd_hdsp_create_pcm(snd_card_t *card,
static int __devinit snd_hdsp_initialize_firmware (hdsp_t *hdsp)
{
int i;
int status_reg;
u32 *firmware_ptr;
if (hdsp_check_for_iobox (hdsp)) {
......@@ -2830,52 +2856,33 @@ static int __devinit snd_hdsp_initialize_firmware (hdsp_t *hdsp)
hdsp_write (hdsp, HDSP_outputEnable + (4 * i), 1);
}
status_reg = hdsp_read (hdsp, HDSP_statusRegister);
if (snd_force_firmware[hdsp->dev] || (hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
if ((status_reg & HDSP_DllError) == 0) {
/* i/o box is connected, firmware already loaded */
if (hdsp_read (hdsp, HDSP_status2Register) & HDSP_version1) {
hdsp->type = Multiface;
hdsp->card_name = "RME Hammerfall DSP (Multiface)";
hdsp->ss_channels = MULTIFACE_SS_CHANNELS;
hdsp->ds_channels = MULTIFACE_DS_CHANNELS;
} else {
hdsp->type = Digiface;
hdsp->card_name = "RME Hammerfall DSP (Digiface)";
hdsp->ss_channels = DIGIFACE_SS_CHANNELS;
hdsp->ds_channels = DIGIFACE_DS_CHANNELS;
}
} else {
snd_printk ("loading firmware\n");
/* firmware not loaded, but i/o box is connected */
hdsp_write (hdsp, HDSP_jtagReg, HDSP_PROGRAM);
hdsp_write (hdsp, HDSP_fifoData, 0);
hdsp_fifo_wait (hdsp, 0, HDSP_SHORT_WAIT);
if (hdsp_fifo_wait (hdsp, 0, HDSP_SHORT_WAIT) < 0) {
snd_printk ("timeout waiting for firmware setup\n");
return -EIO;
}
hdsp_write (hdsp, HDSP_jtagReg, HDSP_S_LOAD);
hdsp_write (hdsp, HDSP_fifoData, 0);
if (hdsp_fifo_wait (hdsp, 0, HDSP_SHORT_WAIT) < 0) {
printk ("looks like a multiface\n");
if (hdsp_fifo_wait (hdsp, 0, HDSP_SHORT_WAIT)) {
hdsp->type = Multiface;
hdsp->card_name = "RME Hammerfall DSP (Multiface)";
hdsp_write (hdsp, HDSP_jtagReg, HDSP_VERSION_BIT);
hdsp_write (hdsp, HDSP_jtagReg, HDSP_S_LOAD);
hdsp_fifo_wait (hdsp, 0, HDSP_SHORT_WAIT);
} else {
printk ("looks like a digiface\n");
hdsp->type = Digiface;
hdsp->card_name = "RME Hammerfall DSP (Digiface)";
}
hdsp_write (hdsp, HDSP_jtagReg, HDSP_S_PROGRAM);
hdsp_write (hdsp, HDSP_fifoData, 0);
if (hdsp_fifo_wait (hdsp, 0, HDSP_LONG_WAIT) < 0) {
if (hdsp_fifo_wait (hdsp, 0, HDSP_LONG_WAIT)) {
snd_printk ("timeout waiting for download preparation\n");
return -EIO;
}
......@@ -2883,9 +2890,9 @@ static int __devinit snd_hdsp_initialize_firmware (hdsp_t *hdsp)
hdsp_write (hdsp, HDSP_jtagReg, HDSP_S_LOAD);
if (hdsp->type == Digiface) {
firmware_ptr = digiface_firmware;
firmware_ptr = (u32 *) digiface_firmware;
} else {
firmware_ptr = multiface_firmware;
firmware_ptr = (u32 *) multiface_firmware;
}
for (i = 0; i < 24413; ++i) {
......@@ -2901,8 +2908,30 @@ static int __devinit snd_hdsp_initialize_firmware (hdsp_t *hdsp)
return -EIO;
}
} else {
/* firmware already loaded, but we need to know what type
of I/O box is connected.
*/
if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version1) {
hdsp->type = Multiface;
} else {
hdsp->type = Digiface;
}
}
if (hdsp->type == Digiface) {
snd_printk ("I/O Box is a Digiface\n");
hdsp->card_name = "RME Hammerfall DSP (Digiface)";
hdsp->ss_channels = DIGIFACE_SS_CHANNELS;
hdsp->ds_channels = DIGIFACE_DS_CHANNELS;
} else {
snd_printk ("I/O Box is a Multiface\n");
hdsp->card_name = "RME Hammerfall DSP (Multiface)";
hdsp->ss_channels = MULTIFACE_SS_CHANNELS;
hdsp->ds_channels = MULTIFACE_DS_CHANNELS;
}
snd_hdsp_flush_midi_input (hdsp, 0);
snd_hdsp_flush_midi_input (hdsp, 1);
......
/* stored in little-endian */
static u32 multiface_firmware[97652] __devinitdata = {
static u32 multiface_firmware[24413] __devinitdata = {
0xffffffff, 0x66aa9955, 0x8001000c, 0xe0000000, 0x8006800c, 0xb0000000,
0x8004800c, 0xb4fc0100, 0x8003000c, 0x00000000, 0x8001000c, 0x90000000,
0x8004000c, 0x00000000, 0x8001000c, 0x80000000, 0x0002000c, 0x581a000a,
......
......@@ -523,6 +523,7 @@ static int rme9652_set_rate(rme9652_t *rme9652, int rate)
rate = RME9652_DS | RME9652_freq;
break;
default:
spin_unlock_irq(&rme9652->lock);
return -EINVAL;
}
......
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