Commit 7ba59717 authored by Jaroslav Kysela's avatar Jaroslav Kysela Committed by Linus Torvalds

[PATCH] ALSA update [9/10] - 2002/08/01

  - CS46xx - added support for the new DSP image
    - S/PDIF and dual-codec support
  - sequencer
    - fixed deadlock at snd_seq_timer_start/stop
parent e2fa3083
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "pcm.h" #include "pcm.h"
#include "rawmidi.h" #include "rawmidi.h"
#include "ac97_codec.h" #include "ac97_codec.h"
#include "cs46xx_dsp_spos.h"
#ifndef PCI_VENDOR_ID_CIRRUS #ifndef PCI_VENDOR_ID_CIRRUS
#define PCI_VENDOR_ID_CIRRUS 0x1013 #define PCI_VENDOR_ID_CIRRUS 0x1013
...@@ -939,6 +940,7 @@ ...@@ -939,6 +940,7 @@
#define SERACC_TWO_CODECS 0x00000002 #define SERACC_TWO_CODECS 0x00000002
#define SERACC_MDM 0x00000004 #define SERACC_MDM 0x00000004
#define SERACC_HSP 0x00000008 #define SERACC_HSP 0x00000008
#define SERACC_ODT 0x00000010 /* only CS4630 */
#endif #endif
/* /*
...@@ -1626,12 +1628,38 @@ ...@@ -1626,12 +1628,38 @@
#define SAVE_REG_MAX 0x10 #define SAVE_REG_MAX 0x10
#define POWER_DOWN_ALL 0x7f0f #define POWER_DOWN_ALL 0x7f0f
/* maxinum number of AC97 codecs connected, AC97 2.0 defined 4 */
#define MAX_NR_AC97 4
#define CS46XX_PRIMARY_CODEC_INDEX 0
#define CS46XX_SECONDARY_CODEC_INDEX 1
#define CS46XX_SECONDARY_CODEC_OFFSET 0x80
/* /*
* *
*/ */
typedef struct _snd_cs46xx cs46xx_t; typedef struct _snd_cs46xx cs46xx_t;
typedef struct _snd_cs46xx_pcm_t {
unsigned char *hw_area;
dma_addr_t hw_addr; /* PCI bus address, not accessible */
unsigned long hw_size;
unsigned int ctl;
unsigned int shift; /* Shift count to trasform frames in bytes */
unsigned int sw_bufsize;
unsigned int sw_data; /* Offset to next dst (or src) in sw ring buffer */
unsigned int sw_io;
int sw_ready; /* Bytes ready to be transferred to/from hw */
unsigned int hw_data; /* Offset to next dst (or src) in hw ring buffer */
unsigned int hw_io; /* Ring buffer hw pointer */
int hw_ready; /* Bytes ready for play (or captured) in hw ring buffer */
size_t appl_ptr; /* Last seen appl_ptr */
snd_pcm_substream_t *substream;
pcm_channel_descriptor_t * pcm_channel;
} cs46xx_pcm_t;
typedef struct { typedef struct {
char name[24]; char name[24];
unsigned long base; unsigned long base;
...@@ -1674,10 +1702,11 @@ struct _snd_cs46xx { ...@@ -1674,10 +1702,11 @@ struct _snd_cs46xx {
int hw_ready; /* Bytes ready for play (or captured) in hw ring buffer */ int hw_ready; /* Bytes ready for play (or captured) in hw ring buffer */
size_t appl_ptr; /* Last seen appl_ptr */ size_t appl_ptr; /* Last seen appl_ptr */
snd_pcm_substream_t *substream; snd_pcm_substream_t *substream;
} play, capt; } capt;
ac97_t *ac97; int nr_ac97_codecs;
ac97_t *ac97[MAX_NR_AC97];
struct pci_dev *pci; struct pci_dev *pci;
snd_card_t *card; snd_card_t *card;
...@@ -1704,6 +1733,13 @@ struct _snd_cs46xx { ...@@ -1704,6 +1733,13 @@ struct _snd_cs46xx {
#ifdef CONFIG_PM #ifdef CONFIG_PM
struct pm_dev *pm_dev; struct pm_dev *pm_dev;
#endif #endif
#ifdef CONFIG_SND_CS46XX_NEW_DSP
dsp_spos_instance_t * dsp_spos_instance;
#else /* for compatibility */
cs46xx_pcm_t *playback_pcm;
unsigned int play_ctl;
#endif
}; };
int snd_cs46xx_create(snd_card_t *card, int snd_cs46xx_create(snd_card_t *card,
......
This diff is collapsed.
/*
* The driver for the Cirrus Logic's Sound Fusion CS46XX based soundcards
* Copyright (c) by Jaroslav Kysela <perex@suse.cz>
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifndef __CS46XX_DSP_SPOS_H__
#define __CS46XX_DSP_SPOS_H__
#include "cs46xx_dsp_scb_types.h"
#include "cs46xx_dsp_task_types.h"
#define SYMBOL_CONSTANT 0x0
#define SYMBOL_SAMPLE 0x1
#define SYMBOL_PARAMETER 0x2
#define SYMBOL_CODE 0x3
#define SEGTYPE_SP_PROGRAM 0x00000001
#define SEGTYPE_SP_PARAMETER 0x00000002
#define SEGTYPE_SP_SAMPLE 0x00000003
#define SEGTYPE_SP_COEFFICIENT 0x00000004
#define DSP_SPOS_UU 0x0deadul /* unused */
#define DSP_SPOS_DC 0x0badul /* dont care */
#define DSP_SPOS_DC_DC 0x0bad0badul /* dont care */
#define DSP_SPOS_UUUU 0xdeadc0edul /* unused */
#define DSP_SPOS_UUHI 0xdeadul
#define DSP_SPOS_UULO 0xc0edul
#define DSP_SPOS_DCDC 0x0badf1d0ul /* dont care */
#define DSP_SPOS_DCDCHI 0x0badul
#define DSP_SPOS_DCDCLO 0xf1d0ul
#define DSP_MAX_TASK_NAME 60
#define DSP_MAX_SYMBOL_NAME 100
#define DSP_MAX_SCB_NAME 60
#define DSP_MAX_SCB_DESC 200
#define DSP_MAX_TASK_DESC 50
#define DSP_MAX_PCM_CHANNELS 32
#define DSP_MAX_SRC_NR 6
struct _dsp_module_desc_t;
typedef struct _symbol_entry_t {
u32 address;
char symbol_name[DSP_MAX_SYMBOL_NAME];
int symbol_type;
/* initialized by driver */
struct _dsp_module_desc_t * module;
int deleted;
} symbol_entry_t;
typedef struct _symbol_desc_t {
int nsymbols;
symbol_entry_t * symbols;
/* initialized by driver */
int highest_frag_index;
} symbol_desc_t;
typedef struct _segment_desc_t {
int segment_type;
u32 offset;
u32 size;
u32 * data;
} segment_desc_t;
typedef struct _dsp_module_desc_t {
char * module_name;
symbol_desc_t symbol_table;
int nsegments;
segment_desc_t * segments;
/* initialized by driver */
u32 overlay_begin_address;
u32 load_address;
int nfixups;
} dsp_module_desc_t;
typedef struct _dsp_scb_descriptor_t {
char scb_name[DSP_MAX_SCB_NAME];
u32 address;
int index;
struct _dsp_scb_descriptor_t * sub_list_ptr;
struct _dsp_scb_descriptor_t * next_scb_ptr;
struct _dsp_scb_descriptor_t * parent_scb_ptr;
symbol_entry_t * task_entry;
symbol_entry_t * scb_symbol;
snd_info_entry_t *proc_info;
int ref_count;
int deleted;
} dsp_scb_descriptor_t;
typedef struct _dsp_task_descriptor_t {
char task_name[DSP_MAX_TASK_NAME];
int size;
u32 address;
int index;
} dsp_task_descriptor_t;
typedef struct _pcm_channel_descriptor_t {
int active;
int src_slot;
int pcm_slot;
u32 sample_rate;
u32 unlinked;
dsp_scb_descriptor_t * pcm_reader_scb;
dsp_scb_descriptor_t * src_scb;
void * private_data;
} pcm_channel_descriptor_t;
typedef struct _dsp_spos_instance_t {
symbol_desc_t symbol_table; /* currently availble loaded symbols in SP */
int nmodules;
dsp_module_desc_t * modules; /* modules loaded into SP */
segment_desc_t code;
/* PCM playback */
struct semaphore pcm_mutex;
dsp_scb_descriptor_t * master_mix_scb;
int npcm_channels;
int nsrc_scb;
pcm_channel_descriptor_t pcm_channels[DSP_MAX_PCM_CHANNELS];
int src_scb_slots[DSP_MAX_SRC_NR];
/* cache this symbols */
symbol_entry_t * null_algorithm; /* used by PCMreaderSCB's */
symbol_entry_t * s16_up; /* used by SRCtaskSCB's */
/* proc fs */
snd_card_t * snd_card;
snd_info_entry_t * proc_dsp_dir;
snd_info_entry_t * proc_sym_info_entry;
snd_info_entry_t * proc_modules_info_entry;
snd_info_entry_t * proc_parameter_dump_info_entry;
snd_info_entry_t * proc_sample_dump_info_entry;
/* SCB's descriptors */
struct semaphore scb_mutex;
int nscb;
int scb_highest_frag_index;
dsp_scb_descriptor_t scbs[DSP_MAX_SCB_DESC];
snd_info_entry_t * proc_scb_info_entry;
dsp_scb_descriptor_t * the_null_scb;
/* Task's descriptors */
int ntask;
dsp_task_descriptor_t tasks[DSP_MAX_TASK_DESC];
snd_info_entry_t * proc_task_info_entry;
/* SPDIF status */
int spdif_status_out;
int spdif_status_in;
} dsp_spos_instance_t;
#endif /* __DSP_SPOS_H__ */
/*
* The driver for the Cirrus Logic's Sound Fusion CS46XX based soundcards
* Copyright (c) by Jaroslav Kysela <perex@suse.cz>
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
* NOTE: comments are copy/paste from cwcemb80.lst
* provided by Tom Woller at Cirrus (my only
* documentation about the SP OS running inside
* the DSP)
*/
#ifndef __CS46XX_DSP_TASK_TYPES_H__
#define __CS46XX_DSP_TASK_TYPES_H__
/*********************************************************************************************
Example hierarchy of stream control blocks in the SP
hfgTree
Ptr____Call (c)
\
-------+------ ------------- ------------- ------------- -----
| SBlaster IF |______\| Foreground |___\| Middlegr'nd |___\| Background |___\| Nul |
| |Goto /| tree header |g /| tree header |g /| tree header |g /| SCB |r
-------------- (g) ------------- ------------- ------------- -----
|c |c |c |c
| | | |
\/ ------------- ------------- -------------
| Foreground |_\ | Middlegr'nd |_\ | Background |_\
| tree |g/ | tree |g/ | tree |g/
------------- ------------- -------------
|c |c |c
| | |
\/ \/ \/
*********************************************************************************************/
#define HFG_FIRST_EXECUTE_MODE 0x0001
#define HFG_FIRST_EXECUTE_MODE_BIT 0
#define HFG_CONTEXT_SWITCH_MODE 0x0002
#define HFG_CONTEXT_SWITCH_MODE_BIT 1
#define MAX_FG_STACK_SIZE 32 // THESE NEED TO BE COMPUTED PROPERLY
#define MAX_MG_STACK_SIZE 16
#define MAX_BG_STACK_SIZE 9
#define MAX_HFG_STACK_SIZE 4
#define SLEEP_ACTIVE_INCREMENT 0 /* Enable task tree thread to go to sleep
This should only ever be used on the Background thread */
#define STANDARD_ACTIVE_INCREMENT 1 /* Task tree thread normal operation */
#define SUSPEND_ACTIVE_INCREMENT 2 /* Cause execution to suspend in the task tree thread
This should only ever be used on the Background thread */
#define HOSTFLAGS_DISABLE_BG_SLEEP 0 /* Host-controlled flag that determines whether we go to sleep
at the end of BG */
/* Minimal context save area for Hyper Forground */
typedef struct _hf_save_area_t {
u32 r10_save;
u32 r54_save;
u32 r98_save;
u16 status_save;
u16 ind_save;
u16 rci1_save;
u16 rci0_save;
u32 r32_save;
u32 r76_save;
u32 rsd2_save;
u16 rsi2_save; /* See TaskTreeParameterBlock for
remainder of registers */
u16 rsa2Save;
/* saved as part of HFG context */
} hf_save_area_t;
/* Task link data structure */
typedef struct _tree_link_t {
/* Pointer to sibling task control block */
u16 next_scb;
/* Pointer to child task control block */
u16 sub_ptr;
/* Pointer to code entry point */
u16 entry_point;
/* Pointer to local data */
u16 this_spb;
} tree_link_t;
typedef struct _task_tree_data_t {
/* Initial tock count; controls task tree execution rate */
u16 tock_count_limit;
/* Tock down counter */
u16 tock_count;
/* Add to ActiveCount when TockCountLimit reached:
Subtract on task tree termination */
u16 active_tncrement;
/* Number of pending activations for task tree */
u16 active_count;
/* BitNumber to enable modification of correct bit in ActiveTaskFlags */
u16 active_bit;
/* Pointer to OS location for indicating current activity on task level */
u16 active_task_flags_ptr;
/* Data structure for controlling movement of memory blocks:-
currently unused */
u16 mem_upd_ptr;
/* Data structure for controlling synchronous link update */
u16 link_upd_ptr;
/* Save area for remainder of full context. */
u16 save_area;
/* Address of start of local stack for data storage */
u16 data_stack_base_ptr;
} task_tree_data_t;
typedef struct _interval_timer_data_t
{
/* These data items have the same relative locations to those */
u16 interval_timer_period;
u16 itd_unused;
/* used for this data in the SPOS control block for SPOS 1.0 */
u16 num_FG_ticks_this_interval;
u16 num_intervals;
} interval_timer_data_t;
/* This structure contains extra storage for the task tree
Currently, this additional data is related only to a full context save */
typedef struct _task_tree_context_block_t {
/* Up to 10 values are saved onto the stack. 8 for the task tree, 1 for
The access to the context switch (call or interrupt), and 1 spare that
users should never use. This last may be required by the system */
u16 stack1;
u16 stack0;
u16 stack3;
u16 stack2;
u16 stack5;
u16 stack4;
u16 stack7;
u16 stack6;
u16 stack9;
u16 stack8;
u32 saverfe;
/* Value may be overwriten by stack save algorithm.
Retain the size of the stack data saved here if used */
u16 reserved1;
u16 stack_size;
u32 saverba; /* (HFG) */
u32 saverdc;
u32 savers_config_23; /* (HFG) */
u32 savers_DMA23; /* (HFG) */
u32 saversa0;
u32 saversi0;
u32 saversa1;
u32 saversi1;
u32 saversa3;
u32 saversd0;
u32 saversd1;
u32 saversd3;
u32 savers_config01;
u32 savers_DMA01;
u32 saveacc0hl;
u32 saveacc1hl;
u32 saveacc0xacc1x;
u32 saveacc2hl;
u32 saveacc3hl;
u32 saveacc2xacc3x;
u32 saveaux0hl;
u32 saveaux1hl;
u32 saveaux0xaux1x;
u32 saveaux2hl;
u32 saveaux3hl;
u32 saveaux2xaux3x;
u32 savershouthl;
u32 savershoutxmacmode;
} task_tree_context_block_t;
typedef struct _task_tree_control_block_t {
hf_save_area_t context;
tree_link_t links;
task_tree_data_t data;
task_tree_context_block_t context_blk;
interval_timer_data_t int_timer;
} task_tree_control_block_t;
#endif /* __DSP_TASK_TYPES_H__ */
...@@ -79,6 +79,7 @@ static inline int _snd_magic_bad(void *obj, unsigned long magic) ...@@ -79,6 +79,7 @@ static inline int _snd_magic_bad(void *obj, unsigned long magic)
#define trident_t_magic 0xa15a1201 #define trident_t_magic 0xa15a1201
#define es1938_t_magic 0xa15a1301 #define es1938_t_magic 0xa15a1301
#define cs46xx_t_magic 0xa15a1401 #define cs46xx_t_magic 0xa15a1401
#define cs46xx_pcm_t_magic 0xa15a1402
#define ensoniq_t_magic 0xa15a1501 #define ensoniq_t_magic 0xa15a1501
#define sonicvibes_t_magic 0xa15a1601 #define sonicvibes_t_magic 0xa15a1601
#define mpu401_t_magic 0xa15a1701 #define mpu401_t_magic 0xa15a1701
......
/* include/version.h. Generated automatically by configure. */ /* include/version.h. Generated automatically by configure. */
#define CONFIG_SND_VERSION "0.9.0rc2" #define CONFIG_SND_VERSION "0.9.0rc2"
#define CONFIG_SND_DATE " (Wed Jul 31 15:28:28 2002 UTC)" #define CONFIG_SND_DATE " (Thu Aug 01 15:59:56 2002 UTC)"
...@@ -149,7 +149,7 @@ static queue_t *queue_new(int owner, int locked) ...@@ -149,7 +149,7 @@ static queue_t *queue_new(int owner, int locked)
static void queue_delete(queue_t *q) static void queue_delete(queue_t *q)
{ {
/* stop and release the timer */ /* stop and release the timer */
snd_seq_timer_stop(q->timer); snd_seq_timer_stop(q->timer, 0);
snd_seq_timer_close(q); snd_seq_timer_close(q);
/* wait until access free */ /* wait until access free */
snd_use_lock_sync(&q->use_lock); snd_use_lock_sync(&q->use_lock);
...@@ -348,7 +348,7 @@ static void snd_seq_check_queue_in_tasklet(unsigned long private_data) ...@@ -348,7 +348,7 @@ static void snd_seq_check_queue_in_tasklet(unsigned long private_data)
/* enqueue a event to singe queue */ /* enqueue a event to singe queue */
int snd_seq_enqueue_event(snd_seq_event_cell_t *cell, int atomic, int hop) int snd_seq_enqueue_event(snd_seq_event_cell_t *cell, int atomic, int hop)
{ {
int dest; int dest, err;
queue_t *q; queue_t *q;
snd_assert(cell != NULL, return -EINVAL); snd_assert(cell != NULL, return -EINVAL);
...@@ -373,14 +373,20 @@ int snd_seq_enqueue_event(snd_seq_event_cell_t *cell, int atomic, int hop) ...@@ -373,14 +373,20 @@ int snd_seq_enqueue_event(snd_seq_event_cell_t *cell, int atomic, int hop)
/* enqueue event in the real-time or midi queue */ /* enqueue event in the real-time or midi queue */
switch (cell->event.flags & SNDRV_SEQ_TIME_STAMP_MASK) { switch (cell->event.flags & SNDRV_SEQ_TIME_STAMP_MASK) {
case SNDRV_SEQ_TIME_STAMP_TICK: case SNDRV_SEQ_TIME_STAMP_TICK:
snd_seq_prioq_cell_in(q->tickq, cell); err = snd_seq_prioq_cell_in(q->tickq, cell);
break; break;
case SNDRV_SEQ_TIME_STAMP_REAL: case SNDRV_SEQ_TIME_STAMP_REAL:
snd_seq_prioq_cell_in(q->timeq, cell); default:
err = snd_seq_prioq_cell_in(q->timeq, cell);
break; break;
} }
if (err < 0) {
queuefree(q); /* unlock */
return err;
}
/* trigger dispatching */ /* trigger dispatching */
snd_seq_check_queue(q, atomic, hop); snd_seq_check_queue(q, atomic, hop);
...@@ -601,7 +607,7 @@ void snd_seq_queue_client_termination(int client) ...@@ -601,7 +607,7 @@ void snd_seq_queue_client_termination(int client)
spin_unlock_irqrestore(&q->owner_lock, flags); spin_unlock_irqrestore(&q->owner_lock, flags);
if (q->owner == client) { if (q->owner == client) {
if (q->timer->running) if (q->timer->running)
snd_seq_timer_stop(q->timer); snd_seq_timer_stop(q->timer, 0);
snd_seq_timer_reset(q->timer); snd_seq_timer_reset(q->timer);
} }
queuefree(q); queuefree(q);
...@@ -711,17 +717,17 @@ void snd_seq_queue_process_event(queue_t *q, snd_seq_event_t *ev, int from_timer ...@@ -711,17 +717,17 @@ void snd_seq_queue_process_event(queue_t *q, snd_seq_event_t *ev, int from_timer
case SNDRV_SEQ_EVENT_START: case SNDRV_SEQ_EVENT_START:
snd_seq_prioq_leave(q->tickq, ev->source.client, 1); snd_seq_prioq_leave(q->tickq, ev->source.client, 1);
snd_seq_prioq_leave(q->timeq, ev->source.client, 1); snd_seq_prioq_leave(q->timeq, ev->source.client, 1);
snd_seq_timer_start(q->timer); if (! snd_seq_timer_start(q->timer, atomic))
queue_broadcast_event(q, ev, from_timer_port, atomic, hop); queue_broadcast_event(q, ev, from_timer_port, atomic, hop);
break; break;
case SNDRV_SEQ_EVENT_CONTINUE: case SNDRV_SEQ_EVENT_CONTINUE:
snd_seq_timer_continue(q->timer); if (! snd_seq_timer_continue(q->timer, atomic))
queue_broadcast_event(q, ev, from_timer_port, atomic, hop); queue_broadcast_event(q, ev, from_timer_port, atomic, hop);
break; break;
case SNDRV_SEQ_EVENT_STOP: case SNDRV_SEQ_EVENT_STOP:
snd_seq_timer_stop(q->timer); snd_seq_timer_stop(q->timer, atomic);
queue_broadcast_event(q, ev, from_timer_port, atomic, hop); queue_broadcast_event(q, ev, from_timer_port, atomic, hop);
break; break;
......
...@@ -89,7 +89,7 @@ void snd_seq_timer_delete(seq_timer_t **tmr) ...@@ -89,7 +89,7 @@ void snd_seq_timer_delete(seq_timer_t **tmr)
t->running = 0; t->running = 0;
/* reset time */ /* reset time */
snd_seq_timer_stop(t); snd_seq_timer_stop(t, 0);
snd_seq_timer_reset(t); snd_seq_timer_reset(t);
kfree(t); kfree(t);
...@@ -313,14 +313,18 @@ int snd_seq_timer_close(queue_t *q) ...@@ -313,14 +313,18 @@ int snd_seq_timer_close(queue_t *q)
return 0; return 0;
} }
void snd_seq_timer_stop(seq_timer_t * tmr) int snd_seq_timer_stop(seq_timer_t * tmr, int in_callback)
{ {
if (! tmr->timeri) if (! tmr->timeri)
return; return -EINVAL;
if (!tmr->running) if (!tmr->running)
return; return 0;
tmr->running = 0; tmr->running = 0;
if (in_callback)
snd_timer_del(tmr->timeri);
else
snd_timer_stop(tmr->timeri); snd_timer_stop(tmr->timeri);
return 0;
} }
static int initialize_timer(seq_timer_t *tmr) static int initialize_timer(seq_timer_t *tmr)
...@@ -345,34 +349,36 @@ static int initialize_timer(seq_timer_t *tmr) ...@@ -345,34 +349,36 @@ static int initialize_timer(seq_timer_t *tmr)
return 0; return 0;
} }
void snd_seq_timer_start(seq_timer_t * tmr) int snd_seq_timer_start(seq_timer_t * tmr, int in_callback)
{ {
if (! tmr->timeri) if (! tmr->timeri)
return; return -EINVAL;
if (tmr->running) if (tmr->running)
snd_seq_timer_stop(tmr); snd_seq_timer_stop(tmr, in_callback);
snd_seq_timer_reset(tmr); snd_seq_timer_reset(tmr);
if (initialize_timer(tmr) < 0) if (initialize_timer(tmr) < 0)
return; return -EINVAL;
snd_timer_start(tmr->timeri, tmr->ticks); snd_timer_start(tmr->timeri, tmr->ticks);
tmr->running = 1; tmr->running = 1;
do_gettimeofday(&tmr->last_update); do_gettimeofday(&tmr->last_update);
return 0;
} }
void snd_seq_timer_continue(seq_timer_t * tmr) int snd_seq_timer_continue(seq_timer_t * tmr, int in_callback)
{ {
if (! tmr->timeri) if (! tmr->timeri)
return; return -EINVAL;
if (tmr->running) if (tmr->running)
return; return -EBUSY;
if (! tmr->initialized) { if (! tmr->initialized) {
snd_seq_timer_reset(tmr); snd_seq_timer_reset(tmr);
if (initialize_timer(tmr) < 0) if (initialize_timer(tmr) < 0)
return; return -EINVAL;
} }
snd_timer_start(tmr->timeri, tmr->ticks); snd_timer_start(tmr->timeri, tmr->ticks);
tmr->running = 1; tmr->running = 1;
do_gettimeofday(&tmr->last_update); do_gettimeofday(&tmr->last_update);
return 0;
} }
/* return current 'real' time. use timeofday() to get better granularity. */ /* return current 'real' time. use timeofday() to get better granularity. */
......
...@@ -127,9 +127,9 @@ int snd_seq_timer_midi_open(queue_t *q); ...@@ -127,9 +127,9 @@ int snd_seq_timer_midi_open(queue_t *q);
int snd_seq_timer_midi_close(queue_t *q); int snd_seq_timer_midi_close(queue_t *q);
void snd_seq_timer_defaults(seq_timer_t *tmr); void snd_seq_timer_defaults(seq_timer_t *tmr);
void snd_seq_timer_reset(seq_timer_t *tmr); void snd_seq_timer_reset(seq_timer_t *tmr);
void snd_seq_timer_stop(seq_timer_t *tmr); int snd_seq_timer_stop(seq_timer_t *tmr, int in_callback);
void snd_seq_timer_start(seq_timer_t *tmr); int snd_seq_timer_start(seq_timer_t *tmr, int in_callback);
void snd_seq_timer_continue(seq_timer_t *tmr); int snd_seq_timer_continue(seq_timer_t *tmr, int in_callback);
int snd_seq_timer_set_tempo(seq_timer_t *tmr, int tempo); int snd_seq_timer_set_tempo(seq_timer_t *tmr, int tempo);
int snd_seq_timer_set_ppq(seq_timer_t *tmr, int ppq); int snd_seq_timer_set_ppq(seq_timer_t *tmr, int ppq);
int snd_seq_timer_set_position_tick(seq_timer_t *tmr, snd_seq_tick_time_t position); int snd_seq_timer_set_position_tick(seq_timer_t *tmr, snd_seq_tick_time_t position);
......
...@@ -71,8 +71,8 @@ MODULE_PARM_DESC(snd_isapnp, "ISA PnP detection for WaveFront soundcards."); ...@@ -71,8 +71,8 @@ MODULE_PARM_DESC(snd_isapnp, "ISA PnP detection for WaveFront soundcards.");
MODULE_PARM_SYNTAX(snd_isapnp, SNDRV_ISAPNP_DESC); MODULE_PARM_SYNTAX(snd_isapnp, SNDRV_ISAPNP_DESC);
#endif #endif
MODULE_PARM(snd_cs4232_pcm_port, "1-" __MODULE_STRING(SNDRV_CARDS) "l"); MODULE_PARM(snd_cs4232_pcm_port, "1-" __MODULE_STRING(SNDRV_CARDS) "l");
MODULE_PARM_DESC(snd_4232_port, "Port # for CS4232 PCM interface."); MODULE_PARM_DESC(snd_cs4232_pcm_port, "Port # for CS4232 PCM interface.");
MODULE_PARM_SYNTAX(snd_cs4232_port, SNDRV_PORT12_DESC); MODULE_PARM_SYNTAX(snd_cs4232_pcm_port, SNDRV_PORT12_DESC);
MODULE_PARM(snd_cs4232_pcm_irq, "1-" __MODULE_STRING(SNDRV_CARDS) "i"); MODULE_PARM(snd_cs4232_pcm_irq, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
MODULE_PARM_DESC(snd_cs4232_pcm_irq, "IRQ # for CS4232 PCM interface."); MODULE_PARM_DESC(snd_cs4232_pcm_irq, "IRQ # for CS4232 PCM interface.");
MODULE_PARM_SYNTAX(snd_cs4232_pcm_irq, SNDRV_ENABLED ",allows:{{5},{7},{9},{11},{12},{15}},dialog:list"); MODULE_PARM_SYNTAX(snd_cs4232_pcm_irq, SNDRV_ENABLED ",allows:{{5},{7},{9},{11},{12},{15}},dialog:list");
......
...@@ -5,9 +5,8 @@ CONFIG_SND_CS46XX ...@@ -5,9 +5,8 @@ CONFIG_SND_CS46XX
Say 'Y' or 'M' to include support for Cirrus Logic CS4610 / CS4612 / Say 'Y' or 'M' to include support for Cirrus Logic CS4610 / CS4612 /
CS4614 / CS4615 / CS4622 / CS4624 / CS4630 / CS4280 chips. CS4614 / CS4615 / CS4622 / CS4624 / CS4630 / CS4280 chips.
CONFIG_SND_CS46XX_ACCEPT_VALID CONFIG_SND_CS46XX_NEW_DSP
Say 'Y' to allow sample resolution for mmap() transfers. Say 'Y' to use a new DSP image for SPDIF and dual codecs.
Note: This can be also specified via module option snd_mmap_valid.
CONFIG_SND_CS4281 CONFIG_SND_CS4281
Say 'Y' or 'M' to include support for Cirrus Logic CS4281. Say 'Y' or 'M' to include support for Cirrus Logic CS4281.
...@@ -39,6 +38,8 @@ CONFIG_SND_HDSP ...@@ -39,6 +38,8 @@ CONFIG_SND_HDSP
soundcards. soundcards.
CONFIG_SND_TRIDENT CONFIG_SND_TRIDENT
Say 'Y' or 'M' to include support for Trident 4D-Wave DX/NX and
SiS 7018 soundcards.
CONFIG_SND_YMFPCI CONFIG_SND_YMFPCI
Say 'Y' or 'M' to include support for Yamaha PCI audio chips - Say 'Y' or 'M' to include support for Yamaha PCI audio chips -
...@@ -75,7 +76,8 @@ CONFIG_SND_ICE1712 ...@@ -75,7 +76,8 @@ CONFIG_SND_ICE1712
Say 'Y' or 'M' to include support for ICE1712 (Envy24) based soundcards. Say 'Y' or 'M' to include support for ICE1712 (Envy24) based soundcards.
CONFIG_SND_INTEL8X0 CONFIG_SND_INTEL8X0
Say 'Y' or 'M' to include support for Intel8x0 based soundcards. Say 'Y' or 'M' to include support for Intel8x0 based soundcards,
SiS 7012, AMD768/8111 and NVidia NForce chips.
CONFIG_SND_SONICVIBES CONFIG_SND_SONICVIBES
Say 'Y' or 'M' to include support for S3 SonicVibes based soundcards. Say 'Y' or 'M' to include support for S3 SonicVibes based soundcards.
......
...@@ -5,9 +5,7 @@ comment 'PCI devices' ...@@ -5,9 +5,7 @@ comment 'PCI devices'
dep_tristate 'ALi PCI Audio M5451' CONFIG_SND_ALI5451 $CONFIG_SND dep_tristate 'ALi PCI Audio M5451' CONFIG_SND_ALI5451 $CONFIG_SND
dep_tristate 'Cirrus Logic (Sound Fusion) CS4280/CS461x/CS462x/CS463x' CONFIG_SND_CS46XX $CONFIG_SND dep_tristate 'Cirrus Logic (Sound Fusion) CS4280/CS461x/CS462x/CS463x' CONFIG_SND_CS46XX $CONFIG_SND
if [ "$CONFIG_SND_CS46XX" != "n" ]; then dep_mbool ' Cirrus Logic (Sound Fusion) New DSP support (EXPERIMENTAL)' CONFIG_SND_CS46XX_NEW_DSP $CONFIG_SND_CS46XX $CONFIG_EXPERIMENTAL
bool ' Cirrus Logic (Sound Fusion) MMAP support for OSS' CONFIG_SND_CS46XX_ACCEPT_VALID
fi
dep_tristate 'Cirrus Logic CS4281' CONFIG_SND_CS4281 $CONFIG_SND dep_tristate 'Cirrus Logic CS4281' CONFIG_SND_CS4281 $CONFIG_SND
dep_tristate 'EMU10K1 (SB Live!, E-mu APS)' CONFIG_SND_EMU10K1 $CONFIG_SND dep_tristate 'EMU10K1 (SB Live!, E-mu APS)' CONFIG_SND_EMU10K1 $CONFIG_SND
dep_tristate 'Korg 1212 IO' CONFIG_SND_KORG1212 $CONFIG_SND dep_tristate 'Korg 1212 IO' CONFIG_SND_KORG1212 $CONFIG_SND
......
...@@ -4,6 +4,9 @@ ...@@ -4,6 +4,9 @@
# #
snd-cs46xx-objs := cs46xx.o cs46xx_lib.o snd-cs46xx-objs := cs46xx.o cs46xx_lib.o
ifeq ($(CONFIG_SND_CS46XX_NEW_DSP),y)
snd-cs46xx-objs += dsp_spos.o dsp_spos_scb_lib.o
endif
# Toplevel Module Dependency # Toplevel Module Dependency
obj-$(CONFIG_SND_CS46XX) += snd-cs46xx.o obj-$(CONFIG_SND_CS46XX) += snd-cs46xx.o
......
...@@ -51,9 +51,7 @@ static char *snd_id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ ...@@ -51,9 +51,7 @@ 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_enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
static int snd_external_amp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; static int snd_external_amp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0};
static int snd_thinkpad[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; static int snd_thinkpad[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0};
#ifndef CONFIG_SND_CS46XX_ACCEPT_VALID
static int snd_mmap_valid[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; static int snd_mmap_valid[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0};
#endif
MODULE_PARM(snd_index, "1-" __MODULE_STRING(SNDRV_CARDS) "i"); MODULE_PARM(snd_index, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
MODULE_PARM_DESC(snd_index, "Index value for the CS46xx soundcard."); MODULE_PARM_DESC(snd_index, "Index value for the CS46xx soundcard.");
...@@ -70,11 +68,9 @@ MODULE_PARM_SYNTAX(snd_external_amp, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC) ...@@ -70,11 +68,9 @@ MODULE_PARM_SYNTAX(snd_external_amp, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC)
MODULE_PARM(snd_thinkpad, "1-" __MODULE_STRING(SNDRV_CARDS) "i"); MODULE_PARM(snd_thinkpad, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
MODULE_PARM_DESC(snd_thinkpad, "Force to enable Thinkpad's CLKRUN control."); MODULE_PARM_DESC(snd_thinkpad, "Force to enable Thinkpad's CLKRUN control.");
MODULE_PARM_SYNTAX(snd_thinkpad, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC); MODULE_PARM_SYNTAX(snd_thinkpad, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC);
#ifndef CONFIG_SND_CS46XX_ACCEPT_VALID
MODULE_PARM(snd_mmap_valid, "1-" __MODULE_STRING(SNDRV_CARDS) "i"); MODULE_PARM(snd_mmap_valid, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
MODULE_PARM_DESC(snd_mmap_valid, "Support OSS mmap."); MODULE_PARM_DESC(snd_mmap_valid, "Support OSS mmap.");
MODULE_PARM_SYNTAX(snd_mmap_valid, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC); MODULE_PARM_SYNTAX(snd_mmap_valid, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC);
#endif
static struct pci_device_id snd_cs46xx_ids[] __devinitdata = { static struct pci_device_id snd_cs46xx_ids[] __devinitdata = {
{ 0x1013, 0x6001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* CS4280 */ { 0x1013, 0x6001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* CS4280 */
...@@ -109,11 +105,7 @@ static int __devinit snd_card_cs46xx_probe(struct pci_dev *pci, ...@@ -109,11 +105,7 @@ static int __devinit snd_card_cs46xx_probe(struct pci_dev *pci,
snd_card_free(card); snd_card_free(card);
return err; return err;
} }
#ifdef CONFIG_SND_CS46XX_ACCEPT_VALID
chip->accept_valid = 1;
#else
chip->accept_valid = snd_mmap_valid[dev]; chip->accept_valid = snd_mmap_valid[dev];
#endif
if ((err = snd_cs46xx_pcm(chip, 0, NULL)) < 0) { if ((err = snd_cs46xx_pcm(chip, 0, NULL)) < 0) {
snd_card_free(card); snd_card_free(card);
return err; return err;
......
struct BA1struct BA1Struct = { struct BA1struct {
struct {
unsigned long offset;
unsigned long size;
} memory[BA1_MEMORY_COUNT];
u32 map[BA1_DWORD_SIZE];
};
static struct BA1struct BA1Struct = {
{{ 0x00000000, 0x00003000 },{ 0x00010000, 0x00003800 },{ 0x00020000, 0x00007000 }}, {{ 0x00000000, 0x00003000 },{ 0x00010000, 0x00003800 },{ 0x00020000, 0x00007000 }},
{0x00000000,0x00000000,0x00000000,0x00000000, {0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000, 0x00000000,0x00000000,0x00000000,0x00000000,
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*
* The driver for the Cirrus Logic's Sound Fusion CS46XX based soundcards
* Copyright (c) by Jaroslav Kysela <perex@suse.cz>
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
/*
* 2002-07 Benny Sjostrand benny@hostmobility.com
*/
#define DSP_MAX_SYMBOLS 1024
#define DSP_MAX_MODULES 64
#define DSP_CODE_BYTE_SIZE 0x00007000UL
#define DSP_PARAMETER_BYTE_SIZE 0x00003000UL
#define DSP_SAMPLE_BYTE_SIZE 0x00003800UL
#define DSP_PARAMETER_BYTE_OFFSET 0x00000000UL
#define DSP_SAMPLE_BYTE_OFFSET 0x00010000UL
#define DSP_CODE_BYTE_OFFSET 0x00020000UL
#define WIDE_INSTR_MASK 0x0040
#define WIDE_LADD_INSTR_MASK 0x0380
/* this instruction types
needs to be reallocated when load
code into DSP */
typedef enum {
WIDE_FOR_BEGIN_LOOP = 0x20,
WIDE_FOR_BEGIN_LOOP2,
WIDE_COND_GOTO_ADDR = 0x30,
WIDE_COND_GOTO_CALL,
WIDE_TBEQ_COND_GOTO_ADDR = 0x70,
WIDE_TBEQ_COND_CALL_ADDR,
WIDE_TBEQ_NCOND_GOTO_ADDR,
WIDE_TBEQ_NCOND_CALL_ADDR,
WIDE_TBEQ_COND_GOTO1_ADDR,
WIDE_TBEQ_COND_CALL1_ADDR,
WIDE_TBEQ_NCOND_GOTOI_ADDR,
WIDE_TBEQ_NCOND_CALL1_ADDR,
} wide_opcode_t;
/* SAMPLE segment */
#define VARI_DECIMATE_BUF1 0x0000
#define WRITE_BACK_BUF1 0x0400
#define CODEC_INPUT_BUF1 0x0500
#define PCM_READER_BUF1 0x0600
#define SRC_DELAY_BUF1 0x0680
#define VARI_DECIMATE_BUF0 0x0780
#define SRC_OUTPUT_BUF1 0x07A0
#define ASYNC_IP_OUTPUT_BUFFER1 0x0A00
#define OUTPUT_SNOOP_BUFFER 0x0B00
#define SPDIFI_IP_OUTPUT_BUFFER1 0x0E00
#define SPDIFO_IP_OUTPUT_BUFFER1 0x1000
#define MIX_SAMPLE_BUF1 0x1400
// #define SRC_OUTPUT_BUF2 0x1280
// #define SRC_DELAY_BUF2 0x1288
/* Task stack address */
#define HFG_STACK 0x066A
#define FG_STACK 0x066E
#define BG_STACK 0x068E
/* SCB's addresses */
#define SPOSCB_ADDR 0x070
#define BG_TREE_SCB_ADDR 0x635
#define NULL_SCB_ADDR 0x000
#define TIMINGMASTER_SCB_ADDR 0x010
#define CODECOUT_SCB_ADDR 0x020
#define PCMREADER_SCB_ADDR 0x030
#define WRITEBACK_SCB_ADDR 0x040
#define CODECIN_SCB_ADDR 0x080
#define MASTERMIX_SCB_ADDR 0x090
#define SRCTASK_SCB_ADDR 0x0A0
#define VARIDECIMATE_SCB_ADDR 0x0B0
#define PCMSERIALIN_SCB_ADDR 0x0C0
#define FG_TASK_HEADER_ADDR 0x600
#define ASYNCTX_SCB_ADDR 0x0E0
#define ASYNCRX_SCB_ADDR 0x0F0
#define SRCTASKII_SCB_ADDR 0x100
#define OUTPUTSNOOP_SCB_ADDR 0x110
#define PCMSERIALINII_SCB_ADDR 0x120
#define SPIOWRITE_SCB_ADDR 0x130
#define SEC_CODECOUT_SCB_ADDR 0x140
#define OUTPUTSNOOPII_SCB_ADDR 0x150
/* hyperforground SCB's*/
#define HFG_TREE_SCB 0xBA0
#define SPDIFI_SCB_INST 0xBB0
#define SPDIFO_SCB_INST 0xBC0
#define WRITE_BACK_SPB 0x0D0
/* offsets */
#define AsyncCIOFIFOPointer 0xd
#define SPDIFOFIFOPointer 0xd
#define SPDIFIFIFOPointer 0xd
#define TCBData 0xb
#define HFGFlags 0xa
#define TCBContextBlk 0x10
#define AFGTxAccumPhi 0x4
#define SCBsubListPtr 0x9
#define SCBfuncEntryPtr 0xA
#define SRCCorPerGof 0x2
#define SRCPhiIncr6Int26Frac 0xd
/* conf */
#define UseASER1Input 1
/* constants */
#define FG_INTERVAL_TIMER_PERIOD 0x0051
#define BG_INTERVAL_TIMER_PERIOD 0x0100
#define RSCONFIG_MODULO_32 0x00000002
#define RSCONFIG_MODULO_64 0x00000003
#define RSCONFIG_MODULO_256 0x00000005
#define RSCONFIG_MODULO_8 0x00000009
#define RSCONFIG_SAMPLE_16STEREO 0x000000C0
#define RSCONFIG_SAMPLE_16MONO 0x00000080
#define RSCONFIG_DMA_TO_HOST 0x00008000
#define RSCONFIG_DMA_ENABLE 0x20000000
#define RSCONFIG_STREAM_NUM_SHIFT 16
#define RSCONFIG_MAX_DMA_SIZE_SHIFT 24
/* Only SP accesible registers */
#define SP_ASER_COUNTDOWN 0x8040
#define SP_SPDOUT_FIFO 0x0108
#define SP_SPDIN_MI_FIFO 0x01E0
#define SP_SPDIN_D_FIFO 0x01F0
#define SP_SPDIN_STATUS 0x8048
#define SP_SPDIN_CONTROL 0x8049
#define SP_SPDIN_FIFOPTR 0x804A
#define SP_SPDOUT_STATUS 0x804C
#define SP_SPDOUT_CONTROL 0x804D
#define SP_SPDOUT_CSUV 0x808E
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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