summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVojtech Pavlik <vojtech@suse.cz>2002-11-11 11:29:50 +0100
committerVojtech Pavlik <vojtech@suse.cz>2002-11-11 11:29:50 +0100
commitcdd78a965de150f55dc6bc2836995e5f8bc991a9 (patch)
tree9bb3263b0110d8606c393810bf52e7911e59d3df
parent20889760dda09fd104cfe859b03b3f63300faa83 (diff)
parent5be2bc3c89f6813ab0ab21cdd27d6d0f2ee94d91 (diff)
Merge suse.cz:/home/vojtech/bk/linus into suse.cz:/home/vojtech/bk/input
-rw-r--r--Makefile2
-rw-r--r--arch/i386/mm/hugetlbpage.c92
-rw-r--r--arch/i386/mm/init.c31
-rw-r--r--drivers/block/genhd.c19
-rw-r--r--drivers/block/ll_rw_blk.c40
-rw-r--r--drivers/net/3c59x.c10
-rw-r--r--drivers/parisc/led.c9
-rw-r--r--fs/buffer.c92
-rw-r--r--fs/ext3/super.c1
-rw-r--r--fs/jfs/jfs_acl.h3
-rw-r--r--fs/proc/proc_misc.c42
-rw-r--r--include/linux/blkdev.h21
-rw-r--r--include/linux/hugetlb.h9
-rw-r--r--include/linux/sched.h3
-rw-r--r--include/sound/core.h6
-rw-r--r--include/sound/cs4231.h45
-rw-r--r--include/sound/cs46xx.h83
-rw-r--r--include/sound/cs46xx_dsp_spos.h45
-rw-r--r--include/sound/info.h3
-rw-r--r--include/sound/pcm.h4
-rw-r--r--include/sound/pcm_sgbuf.h2
-rw-r--r--include/sound/version.h2
-rw-r--r--kernel/sched.c51
-rw-r--r--kernel/sysctl.c14
-rw-r--r--mm/filemap.c2
-rw-r--r--mm/page_alloc.c27
-rw-r--r--sound/core/info.c19
-rw-r--r--sound/core/init.c102
-rw-r--r--sound/core/oss/pcm_oss.c10
-rw-r--r--sound/core/pcm_native.c16
-rw-r--r--sound/core/pcm_sgbuf.c24
-rw-r--r--sound/core/rawmidi.c4
-rw-r--r--sound/core/seq/seq_prioq.c1
-rw-r--r--sound/i2c/l3/uda1341.c4
-rw-r--r--sound/isa/cs423x/cs4231_lib.c247
-rw-r--r--sound/isa/es18xx.c8
-rw-r--r--sound/isa/sb/emu8000_pcm.c22
-rw-r--r--sound/pci/ac97/ac97_codec.c31
-rw-r--r--sound/pci/ac97/ac97_id.h1
-rw-r--r--sound/pci/ac97/ac97_patch.c12
-rw-r--r--sound/pci/ac97/ac97_patch.h1
-rw-r--r--sound/pci/ali5451/ali5451.c9
-rw-r--r--sound/pci/cs46xx/cs46xx.c17
-rw-r--r--sound/pci/cs46xx/cs46xx_lib.c751
-rw-r--r--sound/pci/cs46xx/cs46xx_lib.h33
-rw-r--r--sound/pci/cs46xx/dsp_spos.c125
-rw-r--r--sound/pci/cs46xx/dsp_spos.h25
-rw-r--r--sound/pci/cs46xx/dsp_spos_scb_lib.c326
-rw-r--r--sound/pci/ens1370.c305
-rw-r--r--sound/pci/ice1712/ak4524.c178
-rw-r--r--sound/pci/ice1712/delta.c26
-rw-r--r--sound/pci/ice1712/delta.h6
-rw-r--r--sound/pci/ice1712/ews.c3
-rw-r--r--sound/pci/ice1712/ice1712.c46
-rw-r--r--sound/pci/ice1712/ice1712.h6
-rw-r--r--sound/pci/rme9652/hammerfall_mem.c3
-rw-r--r--sound/pci/via82xx.c56
-rw-r--r--sound/sparc/amd7930.c1
-rw-r--r--sound/usb/usbaudio.c76
-rw-r--r--sound/usb/usbaudio.h11
-rw-r--r--sound/usb/usbmidi.c111
61 files changed, 2275 insertions, 999 deletions
diff --git a/Makefile b/Makefile
index ae82175e94e4..3eea30aa2788 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
VERSION = 2
PATCHLEVEL = 5
-SUBLEVEL = 46
+SUBLEVEL = 47
EXTRAVERSION =
# *DOCUMENTATION*
diff --git a/arch/i386/mm/hugetlbpage.c b/arch/i386/mm/hugetlbpage.c
index 0705e47afa57..4f248bfb6a76 100644
--- a/arch/i386/mm/hugetlbpage.c
+++ b/arch/i386/mm/hugetlbpage.c
@@ -12,21 +12,22 @@
#include <linux/pagemap.h>
#include <linux/smp_lock.h>
#include <linux/slab.h>
-
+#include <linux/module.h>
#include <asm/mman.h>
#include <asm/pgalloc.h>
#include <asm/tlb.h>
#include <asm/tlbflush.h>
-struct vm_operations_struct hugetlb_vm_ops;
-struct list_head htlbpage_freelist;
-spinlock_t htlbpage_lock = SPIN_LOCK_UNLOCKED;
-extern long htlbpagemem;
+static long htlbpagemem;
+int htlbpage_max;
+static long htlbzone_pages;
-void zap_hugetlb_resources(struct vm_area_struct *);
+struct vm_operations_struct hugetlb_vm_ops;
+static LIST_HEAD(htlbpage_freelist);
+static spinlock_t htlbpage_lock = SPIN_LOCK_UNLOCKED;
#define MAX_ID 32
-struct htlbpagekey {
+static struct htlbpagekey {
struct inode *in;
int key;
} htlbpagek[MAX_ID];
@@ -108,7 +109,7 @@ static int anon_get_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vm
return page ? 1 : -1;
}
-int make_hugetlb_pages_present(unsigned long addr, unsigned long end, int flags)
+static int make_hugetlb_pages_present(unsigned long addr, unsigned long end, int flags)
{
int write;
struct mm_struct *mm = current->mm;
@@ -143,7 +144,7 @@ int make_hugetlb_pages_present(unsigned long addr, unsigned long end, int flags)
out_error: /* Error case, remove the partial lp_resources. */
if (addr > vma->vm_start) {
vma->vm_end = addr;
- zap_hugetlb_resources(vma);
+ zap_hugepage_range(vma, vma->vm_start, vma->vm_end - vma->vm_start);
vma->vm_end = end;
}
spin_unlock(&mm->page_table_lock);
@@ -296,30 +297,6 @@ void zap_hugepage_range(struct vm_area_struct *vma, unsigned long start, unsigne
spin_unlock(&mm->page_table_lock);
}
-void zap_hugetlb_resources(struct vm_area_struct *vma)
-{
- zap_hugepage_range(vma, vma->vm_start, vma->vm_end);
-}
-
-static void unlink_vma(struct vm_area_struct *mpnt)
-{
- struct mm_struct *mm = current->mm;
- struct vm_area_struct *vma;
-
- vma = mm->mmap;
- if (vma == mpnt) {
- mm->mmap = vma->vm_next;
- } else {
- while (vma->vm_next != mpnt) {
- vma = vma->vm_next;
- }
- vma->vm_next = mpnt->vm_next;
- }
- rb_erase(&mpnt->vm_rb, &mm->mm_rb);
- mm->mmap_cache = NULL;
- mm->map_count--;
-}
-
static struct inode *set_new_inode(unsigned long len, int prot, int flag, int key)
{
struct inode *inode;
@@ -430,7 +407,7 @@ out:
unsigned long raddr;
raddr = vma->vm_end;
vma->vm_end = addr;
- zap_hugetlb_resources(vma);
+ zap_hugepage_range(vma, vma->vm_start, vma->vm_end - vma->vm_start);
vma->vm_end = raddr;
}
spin_unlock(&mm->page_table_lock);
@@ -569,6 +546,53 @@ int set_hugetlb_mem_size(int count)
return (int) htlbzone_pages;
}
+int hugetlb_sysctl_handler(ctl_table *table, int write, struct file *file, void *buffer, size_t *length)
+{
+ proc_dointvec(table, write, file, buffer, length);
+ htlbpage_max = set_hugetlb_mem_size(htlbpage_max);
+ return 0;
+}
+
+static int __init hugetlb_setup(char *s)
+{
+ if (sscanf(s, "%d", &htlbpage_max) <= 0)
+ htlbpage_max = 0;
+ return 1;
+}
+__setup("hugepages=", hugetlb_setup);
+
+static int __init hugetlb_init(void)
+{
+ int i, j;
+ struct page *page;
+
+ for (i = 0; i < htlbpage_max; ++i) {
+ page = alloc_pages(__GFP_HIGHMEM, HUGETLB_PAGE_ORDER);
+ if (!page)
+ break;
+ for (j = 0; j < HPAGE_SIZE/PAGE_SIZE; ++j)
+ SetPageReserved(&page[j]);
+ spin_lock(&htlbpage_lock);
+ list_add(&page->list, &htlbpage_freelist);
+ spin_unlock(&htlbpage_lock);
+ }
+ htlbpage_max = htlbpagemem = htlbzone_pages = i;
+ printk("Total HugeTLB memory allocated, %ld\n", htlbpagemem);
+ return 0;
+}
+module_init(hugetlb_init);
+
+int hugetlb_report_meminfo(char *buf)
+{
+ return sprintf(buf,
+ "HugePages_Total: %5lu\n"
+ "HugePages_Free: %5lu\n"
+ "Hugepagesize: %5lu kB\n",
+ htlbzone_pages,
+ htlbpagemem,
+ HPAGE_SIZE/1024);
+}
+
static struct page * hugetlb_nopage(struct vm_area_struct * area, unsigned long address, int unused)
{
BUG();
diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c
index 01f3fa7b856c..fe912c8b6b74 100644
--- a/arch/i386/mm/init.c
+++ b/arch/i386/mm/init.c
@@ -422,13 +422,6 @@ static void __init set_max_mapnr_init(void)
extern void set_max_mapnr_init(void);
#endif /* !CONFIG_DISCONTIGMEM */
-#ifdef CONFIG_HUGETLB_PAGE
-long htlbpagemem = 0;
-int htlbpage_max;
-long htlbzone_pages;
-extern struct list_head htlbpage_freelist;
-#endif
-
void __init mem_init(void)
{
extern int ppro_with_ram_bug(void);
@@ -497,30 +490,6 @@ void __init mem_init(void)
#ifndef CONFIG_SMP
zap_low_mappings();
#endif
-#ifdef CONFIG_HUGETLB_PAGE
- {
- long i, j;
- struct page *page, *map;
- /*For now reserve quarter for hugetlb_pages.*/
- htlbzone_pages = (max_low_pfn >> ((HPAGE_SHIFT - PAGE_SHIFT) + 2)) ;
- /*Will make this kernel command line. */
- INIT_LIST_HEAD(&htlbpage_freelist);
- for (i=0; i<htlbzone_pages; i++) {
- page = alloc_pages(__GFP_HIGHMEM, HUGETLB_PAGE_ORDER);
- if (page == NULL)
- break;
- map = page;
- for (j=0; j<(HPAGE_SIZE/PAGE_SIZE); j++) {
- SetPageReserved(map);
- map++;
- }
- list_add(&page->list, &htlbpage_freelist);
- }
- printk("Total Huge_TLB_Page memory pages allocated %ld\n", i);
- htlbzone_pages = htlbpagemem = i;
- htlbpage_max = i;
- }
-#endif
}
#if CONFIG_X86_PAE
diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c
index c9d6d5b2b839..5bba83e69485 100644
--- a/drivers/block/genhd.c
+++ b/drivers/block/genhd.c
@@ -324,9 +324,16 @@ static ssize_t disk_size_read(struct gendisk * disk,
{
return off ? 0 : sprintf(page, "%llu\n",(unsigned long long)get_capacity(disk));
}
-static inline unsigned MSEC(unsigned x)
+
+static inline unsigned jiffies_to_msec(unsigned jif)
{
- return x * 1000 / HZ;
+#if 1000 % HZ == 0
+ return jif * (1000 / HZ);
+#elif HZ % 1000 == 0
+ return jif / (HZ / 1000);
+#else
+ return (jif / HZ) * 1000 + (jif % HZ) * 1000 / HZ;
+#endif
}
static ssize_t disk_stat_read(struct gendisk * disk,
char *page, size_t count, loff_t off)
@@ -338,11 +345,11 @@ static ssize_t disk_stat_read(struct gendisk * disk,
"%8u %8u %8u"
"\n",
disk->reads, disk->read_merges, (u64)disk->read_sectors,
- MSEC(disk->read_ticks),
+ jiffies_to_msec(disk->read_ticks),
disk->writes, disk->write_merges, (u64)disk->write_sectors,
- MSEC(disk->write_ticks),
- disk->in_flight, MSEC(disk->io_ticks),
- MSEC(disk->time_in_queue));
+ jiffies_to_msec(disk->write_ticks),
+ disk->in_flight, jiffies_to_msec(disk->io_ticks),
+ jiffies_to_msec(disk->time_in_queue));
}
static struct disk_attribute disk_attr_dev = {
.attr = {.name = "dev", .mode = S_IRUGO },
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
index bc7404143240..7698b794961d 100644
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -28,11 +28,6 @@
#include <linux/slab.h>
/*
- * Disk stats
- */
-struct disk_stat dkstat;
-
-/*
* For the allocated request tables
*/
static kmem_cache_t *request_cachep;
@@ -56,7 +51,6 @@ static int queue_nr_requests;
static int batch_requests;
unsigned long blk_max_low_pfn, blk_max_pfn;
-atomic_t nr_iowait_tasks = ATOMIC_INIT(0);
int blk_nohighio = 0;
static struct congestion_state {
@@ -115,27 +109,6 @@ static void set_queue_congested(request_queue_t *q, int rw)
atomic_inc(&congestion_states[rw].nr_congested_queues);
}
-/*
- * This task is about to go to sleep on IO. Increment nr_iowait_tasks so
- * that process accounting knows that this is a task in IO wait state.
- *
- * But don't do that if it is a deliberate, throttling IO wait (this task
- * has set its backing_dev_info: the queue against which it should throttle)
- */
-void io_schedule(void)
-{
- atomic_inc(&nr_iowait_tasks);
- schedule();
- atomic_dec(&nr_iowait_tasks);
-}
-
-void io_schedule_timeout(long timeout)
-{
- atomic_inc(&nr_iowait_tasks);
- schedule_timeout(timeout);
- atomic_dec(&nr_iowait_tasks);
-}
-
/**
* blk_get_backing_dev_info - get the address of a queue's backing_dev_info
* @dev: device
@@ -1434,19 +1407,6 @@ void drive_stat_acct(struct request *rq, int nr_sectors, int new_io)
major = rq->rq_disk->major;
index = rq->rq_disk->first_minor >> rq->rq_disk->minor_shift;
-
- if ((index >= DK_MAX_DISK) || (major >= DK_MAX_MAJOR))
- return;
-
- dkstat.drive[major][index] += new_io;
- if (rw == READ) {
- dkstat.drive_rio[major][index] += new_io;
- dkstat.drive_rblk[major][index] += nr_sectors;
- } else if (rw == WRITE) {
- dkstat.drive_wio[major][index] += new_io;
- dkstat.drive_wblk[major][index] += nr_sectors;
- } else
- printk(KERN_ERR "drive_stat_acct: cmd not R/W?\n");
}
/*
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index 974cf6e876b7..8f8312227910 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -1804,10 +1804,10 @@ static void vortex_tx_timeout(struct net_device *dev)
inw(ioaddr + EL3_STATUS));
EL3WINDOW(4);
printk(KERN_ERR " diagnostics: net %04x media %04x dma %08x fifo %04x\n",
- (unsigned)inw(ioaddr + Wn4_NetDiag),
- (unsigned)inw(ioaddr + Wn4_Media),
- (unsigned)inl(ioaddr + PktStatus),
- (unsigned)inw(ioaddr + Wn4_FIFODiag));
+ inw(ioaddr + Wn4_NetDiag),
+ inw(ioaddr + Wn4_Media),
+ inl(ioaddr + PktStatus),
+ inw(ioaddr + Wn4_FIFODiag));
/* Slight code bloat to be user friendly. */
if ((inb(ioaddr + TxStatus) & 0x88) == 0x88)
printk(KERN_ERR "%s: Transmitter encountered 16 collisions --"
@@ -2644,7 +2644,7 @@ dump_tx_ring(struct net_device *dev)
vp->dirty_tx, vp->dirty_tx % TX_RING_SIZE,
vp->cur_tx, vp->cur_tx % TX_RING_SIZE);
printk(KERN_ERR " Transmit list %8.8x vs. %p.\n",
- (unsigned)inl(ioaddr + DownListPtr),
+ inl(ioaddr + DownListPtr),
&vp->tx_ring[vp->dirty_tx % TX_RING_SIZE]);
issue_and_wait(dev, DownStall);
for (i = 0; i < TX_RING_SIZE; i++) {
diff --git a/drivers/parisc/led.c b/drivers/parisc/led.c
index d57179c44908..3e2e0afd6e3a 100644
--- a/drivers/parisc/led.c
+++ b/drivers/parisc/led.c
@@ -404,6 +404,14 @@ static void led_get_diskio_stats(int addvalue)
int major, disk, total;
total = 0;
+#ifdef 0
+ /*
+ * this section will no longer work in 2.5, as we no longer
+ * have either kstat.dk_drive nor DK_MAX_*. It can probably
+ * be rewritten to use the per-disk statistics now kept in the
+ * gendisk, but since I have no HP machines to test it on, I'm
+ * not really up to that. ricklind@us.ibm.com 11/7/02
+ */
for (major = 0; major < DK_MAX_MAJOR; major++) {
for (disk = 0; disk < DK_MAX_DISK; disk++)
total += dkstat.drive[major][disk];
@@ -417,6 +425,7 @@ static void led_get_diskio_stats(int addvalue)
} else
led_diskio_counter += CALC_ADD(total, diskio_max, addvalue);
}
+#endif
diskio_total_last += total;
}
diff --git a/fs/buffer.c b/fs/buffer.c
index 3c5a0d5d7080..a97e0dfe5f5d 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -367,7 +367,7 @@ out:
* succeeds, there is no need to take private_lock. (But if
* private_lock is contended then so is mapping->page_lock).
*/
-struct buffer_head *
+static struct buffer_head *
__find_get_block_slow(struct block_device *bdev, sector_t block, int unused)
{
struct inode *bd_inode = bdev->bd_inode;
@@ -1077,18 +1077,6 @@ grow_buffers(struct block_device *bdev, unsigned long block, int size)
return 1;
}
-/*
- * __getblk will locate (and, if necessary, create) the buffer_head
- * which corresponds to the passed block_device, block and size. The
- * returned buffer has its reference count incremented.
- *
- * __getblk() cannot fail - it just keeps trying. If you pass it an
- * illegal block number, __getblk() will happily return a buffer_head
- * which represents the non-existent block. Very weird.
- *
- * __getblk() will lock up the machine if grow_dev_page's try_to_free_buffers()
- * attempt is failing. FIXME, perhaps?
- */
struct buffer_head *
__getblk_slow(struct block_device *bdev, sector_t block, int size)
{
@@ -1096,10 +1084,8 @@ __getblk_slow(struct block_device *bdev, sector_t block, int size)
struct buffer_head * bh;
bh = __find_get_block(bdev, block, size);
- if (bh) {
- touch_buffer(bh);
+ if (bh)
return bh;
- }
if (!grow_buffers(bdev, block, size))
free_more_memory();
@@ -1182,21 +1168,8 @@ void __bforget(struct buffer_head *bh)
__brelse(bh);
}
-/**
- * __bread() - reads a specified block and returns the bh
- * @block: number of block
- * @size: size (in bytes) to read
- *
- * Reads a specified block, and returns buffer head that contains it.
- * It returns NULL if the block was unreadable.
- */
-struct buffer_head *
-__bread_slow(struct block_device *bdev, sector_t block, int size)
+static struct buffer_head *__bread_slow(struct buffer_head *bh)
{
- struct buffer_head *bh = __getblk(bdev, block, size);
-
- if (buffer_uptodate(bh))
- return bh;
lock_buffer(bh);
if (buffer_uptodate(bh)) {
unlock_buffer(bh);
@@ -1260,9 +1233,6 @@ static void bh_lru_install(struct buffer_head *bh)
struct buffer_head *evictee = NULL;
struct bh_lru *lru;
- if (bh == NULL)
- return;
-
check_irqs_on();
bh_lru_lock();
lru = &per_cpu(bh_lrus, smp_processor_id());
@@ -1293,14 +1263,15 @@ static void bh_lru_install(struct buffer_head *bh)
}
bh_lru_unlock();
- if (evictee) {
- touch_buffer(evictee);
+ if (evictee)
__brelse(evictee);
- }
}
+/*
+ * Look up the bh in this cpu's LRU. If it's there, move it to the head.
+ */
static inline struct buffer_head *
-lookup_bh(struct block_device *bdev, sector_t block, int size)
+lookup_bh_lru(struct block_device *bdev, sector_t block, int size)
{
struct buffer_head *ret = NULL;
struct bh_lru *lru;
@@ -1330,44 +1301,65 @@ lookup_bh(struct block_device *bdev, sector_t block, int size)
return ret;
}
+/*
+ * Perform a pagecache lookup for the matching buffer. If it's there, refresh
+ * it in the LRU and mark it as accessed. If it is not present then return
+ * NULL
+ */
struct buffer_head *
__find_get_block(struct block_device *bdev, sector_t block, int size)
{
- struct buffer_head *bh = lookup_bh(bdev, block, size);
+ struct buffer_head *bh = lookup_bh_lru(bdev, block, size);
if (bh == NULL) {
bh = __find_get_block_slow(bdev, block, size);
- bh_lru_install(bh);
+ if (bh)
+ bh_lru_install(bh);
}
+ if (bh)
+ touch_buffer(bh);
return bh;
}
EXPORT_SYMBOL(__find_get_block);
+/*
+ * __getblk will locate (and, if necessary, create) the buffer_head
+ * which corresponds to the passed block_device, block and size. The
+ * returned buffer has its reference count incremented.
+ *
+ * __getblk() cannot fail - it just keeps trying. If you pass it an
+ * illegal block number, __getblk() will happily return a buffer_head
+ * which represents the non-existent block. Very weird.
+ *
+ * __getblk() will lock up the machine if grow_dev_page's try_to_free_buffers()
+ * attempt is failing. FIXME, perhaps?
+ */
struct buffer_head *
__getblk(struct block_device *bdev, sector_t block, int size)
{
struct buffer_head *bh = __find_get_block(bdev, block, size);
- if (bh == NULL) {
+ if (bh == NULL)
bh = __getblk_slow(bdev, block, size);
- bh_lru_install(bh);
- }
return bh;
}
EXPORT_SYMBOL(__getblk);
+/**
+ * __bread() - reads a specified block and returns the bh
+ * @block: number of block
+ * @size: size (in bytes) to read
+ *
+ * Reads a specified block, and returns buffer head that contains it.
+ * It returns NULL if the block was unreadable.
+ */
struct buffer_head *
__bread(struct block_device *bdev, sector_t block, int size)
{
struct buffer_head *bh = __getblk(bdev, block, size);
- if (bh) {
- if (buffer_uptodate(bh))
- return bh;
- __brelse(bh);
- }
- bh = __bread_slow(bdev, block, size);
- bh_lru_install(bh);
+ if (!buffer_uptodate(bh))
+ bh = __bread_slow(bh);
return bh;
}
EXPORT_SYMBOL(__bread);
@@ -1565,7 +1557,7 @@ void unmap_underlying_metadata(struct block_device *bdev, sector_t block)
{
struct buffer_head *old_bh;
- old_bh = __find_get_block(bdev, block, 0);
+ old_bh = __find_get_block_slow(bdev, block, 0);
if (old_bh) {
#if 0 /* This happens. Later. */
if (buffer_dirty(old_bh))
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index 424f807dadb5..c081e426fd1f 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -1021,6 +1021,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
sbi->s_mount_opt = 0;
sbi->s_resuid = EXT3_DEF_RESUID;
sbi->s_resgid = EXT3_DEF_RESGID;
+ setup_ro_after(sb);
blocksize = sb_min_blocksize(sb, EXT3_MIN_BLOCK_SIZE);
if (!blocksize) {
diff --git a/fs/jfs/jfs_acl.h b/fs/jfs/jfs_acl.h
index 3a246ef01778..179a3893a945 100644
--- a/fs/jfs/jfs_acl.h
+++ b/fs/jfs/jfs_acl.h
@@ -29,4 +29,5 @@ int jfs_permission(struct inode *, int);
int jfs_init_acl(struct inode *, struct inode *);
int jfs_setattr(struct dentry *, struct iattr *);
-#endif /* CONFIG_JFS_POSIX_ACL */
+#endif /* CONFIG_JFS_POSIX_ACL */
+#endif /* _H_JFS_ACL */
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
index 8b6f9370d187..3f1db05f5445 100644
--- a/fs/proc/proc_misc.c
+++ b/fs/proc/proc_misc.c
@@ -40,7 +40,7 @@
#include <linux/times.h>
#include <linux/profile.h>
#include <linux/blkdev.h>
-
+#include <linux/hugetlb.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
#include <asm/io.h>
@@ -199,19 +199,8 @@ static int meminfo_read_proc(char *page, char **start, off_t off,
ps.nr_reverse_maps
);
-#ifdef CONFIG_HUGETLB_PAGE
- {
- extern unsigned long htlbpagemem, htlbzone_pages;
- len += sprintf(page + len,
- "HugePages_Total: %5lu\n"
- "HugePages_Free: %5lu\n"
- "Hugepagesize: %5lu kB\n",
- htlbzone_pages,
- htlbpagemem,
- HPAGE_SIZE/1024);
- }
+ len += hugetlb_report_meminfo(page + len);
-#endif
return proc_calc_metrics(page, start, off, count, eof, len);
#undef K
}
@@ -341,7 +330,6 @@ static int kstat_read_proc(char *page, char **start, off_t off,
extern unsigned long total_forks;
unsigned long jif = jiffies;
unsigned int sum = 0, user = 0, nice = 0, system = 0, idle = 0, iowait = 0;
- int major, disk;
for (i = 0 ; i < NR_CPUS; i++) {
int j;
@@ -372,7 +360,7 @@ static int kstat_read_proc(char *page, char **start, off_t off,
jiffies_to_clock_t(kstat_cpu(i).cpustat.nice),
jiffies_to_clock_t(kstat_cpu(i).cpustat.system),
jiffies_to_clock_t(kstat_cpu(i).cpustat.idle),
- jiffies_to_clock_t(kstat_cpu(i).cpustat.idle));
+ jiffies_to_clock_t(kstat_cpu(i).cpustat.iowait));
}
len += sprintf(page + len, "intr %u", sum);
@@ -381,37 +369,17 @@ static int kstat_read_proc(char *page, char **start, off_t off,
len += sprintf(page + len, " %u", kstat_irqs(i));
#endif
- len += sprintf(page + len, "\ndisk_io: ");
-
- for (major = 0; major < DK_MAX_MAJOR; major++) {
- for (disk = 0; disk < DK_MAX_DISK; disk++) {
- int active = dkstat.drive[major][disk] +
- dkstat.drive_rblk[major][disk] +
- dkstat.drive_wblk[major][disk];
- if (active)
- len += sprintf(page + len,
- "(%u,%u):(%u,%u,%u,%u,%u) ",
- major, disk,
- dkstat.drive[major][disk],
- dkstat.drive_rio[major][disk],
- dkstat.drive_rblk[major][disk],
- dkstat.drive_wio[major][disk],
- dkstat.drive_wblk[major][disk]
- );
- }
- }
-
len += sprintf(page + len,
"\nctxt %lu\n"
"btime %lu\n"
"processes %lu\n"
"procs_running %lu\n"
- "procs_blocked %u\n",
+ "procs_blocked %lu\n",
nr_context_switches(),
xtime.tv_sec - jif / HZ,
total_forks,
nr_running(),
- atomic_read(&nr_iowait_tasks));
+ nr_iowait());
return proc_calc_metrics(page, start, off, count, eof, len);
}
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 472432a57b06..a3927e6b6dee 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -11,22 +11,6 @@
#include <asm/scatterlist.h>
-/*
- * Disk stats ...
- */
-
-#define DK_MAX_MAJOR 16
-#define DK_MAX_DISK 16
-
-struct disk_stat {
- unsigned int drive[DK_MAX_MAJOR][DK_MAX_DISK];
- unsigned int drive_rio[DK_MAX_MAJOR][DK_MAX_DISK];
- unsigned int drive_wio[DK_MAX_MAJOR][DK_MAX_DISK];
- unsigned int drive_rblk[DK_MAX_MAJOR][DK_MAX_DISK];
- unsigned int drive_wblk[DK_MAX_MAJOR][DK_MAX_DISK];
-};
-extern struct disk_stat dkstat;
-
struct request_queue;
typedef struct request_queue request_queue_t;
struct elevator_s;
@@ -470,9 +454,4 @@ static inline void put_dev_sector(Sector p)
#endif
-
-extern atomic_t nr_iowait_tasks;
-void io_schedule(void);
-void io_schedule_timeout(long timeout);
-
#endif
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h
index 30fa2437be15..37c3621b2f03 100644
--- a/include/linux/hugetlb.h
+++ b/include/linux/hugetlb.h
@@ -2,17 +2,25 @@
#define _LINUX_HUGETLB_H
#ifdef CONFIG_HUGETLB_PAGE
+
+struct ctl_table;
+
static inline int is_vm_hugetlb_page(struct vm_area_struct *vma)
{
return vma->vm_flags & VM_HUGETLB;
}
+int hugetlb_sysctl_handler(struct ctl_table *, int, struct file *, void *, size_t *);
int copy_hugetlb_page_range(struct mm_struct *, struct mm_struct *, struct vm_area_struct *);
int follow_hugetlb_page(struct mm_struct *, struct vm_area_struct *, struct page **, struct vm_area_struct **, unsigned long *, int *, int);
void zap_hugepage_range(struct vm_area_struct *, unsigned long, unsigned long);
void unmap_hugepage_range(struct vm_area_struct *, unsigned long, unsigned long);
int hugetlb_prefault(struct address_space *, struct vm_area_struct *);
void huge_page_release(struct page *);
+int hugetlb_report_meminfo(char *);
+
+extern int htlbpage_max;
+
#else /* !CONFIG_HUGETLB_PAGE */
static inline int is_vm_hugetlb_page(struct vm_area_struct *vma)
{
@@ -25,6 +33,7 @@ static inline int is_vm_hugetlb_page(struct vm_area_struct *vma)
#define zap_hugepage_range(vma, start, len) BUG()
#define unmap_hugepage_range(vma, start, end) BUG()
#define huge_page_release(page) BUG()
+#define hugetlb_report_meminfo(buf) 0
#endif /* !CONFIG_HUGETLB_PAGE */
diff --git a/include/linux/sched.h b/include/linux/sched.h
index c26b6d0d8d7a..93b1328d59e4 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -88,6 +88,7 @@ extern int nr_threads;
extern int last_pid;
extern unsigned long nr_running(void);
extern unsigned long nr_uninterruptible(void);
+extern unsigned long nr_iowait(void);
#include <linux/time.h>
#include <linux/param.h>
@@ -147,6 +148,8 @@ extern void show_trace(unsigned long *stack);
extern void show_stack(unsigned long *stack);
extern void show_regs(struct pt_regs *);
+void io_schedule(void);
+void io_schedule_timeout(long timeout);
extern void cpu_init (void);
extern void trap_init(void);
diff --git a/include/sound/core.h b/include/sound/core.h
index e21feca3b8c0..4ba70412cb79 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -241,11 +241,15 @@ void *snd_hidden_vmalloc(unsigned long size);
void snd_hidden_vfree(void *obj);
#define kmalloc(size, flags) snd_hidden_kmalloc(size, flags)
#define kfree(obj) snd_hidden_kfree(obj)
-#define kfree_nocheck(obj) snd_wrapper_kfree(obj)
#define vmalloc(size) snd_hidden_vmalloc(size)
#define vfree(obj) snd_hidden_vfree(obj)
+#define kmalloc_nocheck(size, flags) snd_wrapper_kmalloc(size, flags)
+#define vmalloc_nocheck(size) snd_wrapper_vmalloc(size)
+#define kfree_nocheck(obj) snd_wrapper_kfree(obj)
#define vfree_nocheck(obj) snd_wrapper_vfree(obj)
#else
+#define kmalloc_nocheck(size, flags) kmalloc(size, flags)
+#define vmalloc_nocheck(size) vmalloc(size)
#define kfree_nocheck(obj) kfree(obj)
#define vfree_nocheck(obj) vfree(obj)
#endif
diff --git a/include/sound/cs4231.h b/include/sound/cs4231.h
index 610c2e94705b..75d1b588ee87 100644
--- a/include/sound/cs4231.h
+++ b/include/sound/cs4231.h
@@ -26,9 +26,24 @@
#include "pcm.h"
#include "timer.h"
+#ifdef CONFIG_SBUS
+#define SBUS_SUPPORT
+#include <asm/sbus.h>
+#endif
+
+#if defined(CONFIG_PCI) && defined(CONFIG_SPARC64)
+#define EBUS_SUPPORT
+#include <linux/pci.h>
+#include <asm/ebus.h>
+#endif
+
+#if !defined(SBUS_SUPPORT) && !defined(EBUS_SUPPORT)
+#define LEGACY_SUPPORT
+#endif
+
/* IO ports */
-#define CS4231P(chip, x) ((chip)->port + c_d_c_CS4231##x)
+#define CS4231P(x) (c_d_c_CS4231##x)
#define c_d_c_CS4231REGSEL 0
#define c_d_c_CS4231REG 1
@@ -221,17 +236,38 @@ typedef struct _snd_cs4231 cs4231_t;
struct _snd_cs4231 {
unsigned long port; /* base i/o port */
+#ifdef LEGACY_SUPPORT
struct resource *res_port;
unsigned long cport; /* control base i/o port (CS4236) */
struct resource *res_cport;
int irq; /* IRQ line */
int dma1; /* playback DMA */
int dma2; /* record DMA */
+#endif
unsigned short version; /* version of CODEC chip */
unsigned short mode; /* see to CS4231_MODE_XXXX */
unsigned short hardware; /* see to CS4231_HW_XXXX */
unsigned short hwshare; /* shared resources */
- unsigned short single_dma:1; /* forced single DMA mode (GUS 16-bit daughter board) or dma1 == dma2 */
+ unsigned short single_dma:1, /* forced single DMA mode (GUS 16-bit daughter board) or dma1 == dma2 */
+ ebus_flag:1; /* SPARC: EBUS present */
+
+#ifdef EBUS_SUPPORT
+ struct ebus_dma_info eb2c;
+ struct ebus_dma_info eb2p;
+#endif
+
+#if defined(SBUS_SUPPORT) || defined(EBUS_SUPPORT)
+ union {
+#ifdef SBUS_SUPPORT
+ struct sbus_dev *sdev;
+#endif
+#ifdef EBUS_SUPPORT
+ struct pci_dev *pdev;
+#endif
+ } dev_u;
+ unsigned int p_periods_sent;
+ unsigned int c_periods_sent;
+#endif
snd_card_t *card;
snd_pcm_t *pcm;
@@ -245,8 +281,10 @@ struct _snd_cs4231 {
int mce_bit;
int calibrate_mute;
int sw_3d_bit;
+#ifdef LEGACY_SUPPORT
unsigned int p_dma_size;
unsigned int c_dma_size;
+#endif
spinlock_t reg_lock;
struct semaphore mce_mutex;
@@ -255,14 +293,17 @@ struct _snd_cs4231 {
int (*rate_constraint) (snd_pcm_runtime_t *runtime);
void (*set_playback_format) (cs4231_t *chip, snd_pcm_hw_params_t *hw_params, unsigned char pdfr);
void (*set_capture_format) (cs4231_t *chip, snd_pcm_hw_params_t *hw_params, unsigned char cdfr);
+ void (*trigger) (cs4231_t *chip, unsigned int what, int start);
#ifdef CONFIG_PM
struct pm_dev *pm_dev;
void (*suspend) (cs4231_t *chip);
void (*resume) (cs4231_t *chip);
#endif
void *dma_private_data;
+#ifdef LEGACY_SUPPORT
int (*claim_dma) (cs4231_t *chip, void *dma_private_data, int dma);
int (*release_dma) (cs4231_t *chip, void *dma_private_data, int dma);
+#endif
};
/* exported functions */
diff --git a/include/sound/cs46xx.h b/include/sound/cs46xx.h
index a9303d3a503c..09ae6c772aa0 100644
--- a/include/sound/cs46xx.h
+++ b/include/sound/cs46xx.h
@@ -196,80 +196,6 @@
#define BA1_OMNI_MEM 0x000E0000
-
-
-/*
- * The following define the offsets of the AC97 shadow registers, which appear
- * as a virtual extension to the base address register zero memory range.
- */
-#define AC97_REG_OFFSET_MASK 0x0000007EL
-#define AC97_CODEC_NUMBER_MASK 0x00003000L
-
-#define BA0_AC97_RESET 0x00001000L
-#define BA0_AC97_MASTER_VOLUME 0x00001002L
-#define BA0_AC97_HEADPHONE_VOLUME 0x00001004L
-#define BA0_AC97_MASTER_VOLUME_MONO 0x00001006L
-#define BA0_AC97_MASTER_TONE 0x00001008L
-#define BA0_AC97_PC_BEEP_VOLUME 0x0000100AL
-#define BA0_AC97_PHONE_VOLUME 0x0000100CL
-#define BA0_AC97_MIC_VOLUME 0x0000100EL
-#define BA0_AC97_LINE_IN_VOLUME 0x00001010L
-#define BA0_AC97_CD_VOLUME 0x00001012L
-#define BA0_AC97_VIDEO_VOLUME 0x00001014L
-#define BA0_AC97_AUX_VOLUME 0x00001016L
-#define BA0_AC97_PCM_OUT_VOLUME 0x00001018L
-#define BA0_AC97_RECORD_SELECT 0x0000101AL
-#define BA0_AC97_RECORD_GAIN 0x0000101CL
-#define BA0_AC97_RECORD_GAIN_MIC 0x0000101EL
-#define BA0_AC97_GENERAL_PURPOSE 0x00001020L
-#define BA0_AC97_3D_CONTROL 0x00001022L
-#define BA0_AC97_MODEM_RATE 0x00001024L
-#define BA0_AC97_POWERDOWN 0x00001026L
-#define BA0_AC97_EXT_AUDIO_ID 0x00001028L
-#define BA0_AC97_EXT_AUDIO_POWER 0x0000102AL
-#define BA0_AC97_PCM_FRONT_DAC_RATE 0x0000102CL
-#define BA0_AC97_PCM_SURR_DAC_RATE 0x0000102EL
-#define BA0_AC97_PCM_LFE_DAC_RATE 0x00001030L
-#define BA0_AC97_PCM_LR_ADC_RATE 0x00001032L
-#define BA0_AC97_MIC_ADC_RATE 0x00001034L
-#define BA0_AC97_6CH_VOL_C_LFE 0x00001036L
-#define BA0_AC97_6CH_VOL_SURROUND 0x00001038L
-#define BA0_AC97_RESERVED_3A 0x0000103AL
-#define BA0_AC97_EXT_MODEM_ID 0x0000103CL
-#define BA0_AC97_EXT_MODEM_POWER 0x0000103EL
-#define BA0_AC97_LINE1_CODEC_RATE 0x00001040L
-#define BA0_AC97_LINE2_CODEC_RATE 0x00001042L
-#define BA0_AC97_HANDSET_CODEC_RATE 0x00001044L
-#define BA0_AC97_LINE1_CODEC_LEVEL 0x00001046L
-#define BA0_AC97_LINE2_CODEC_LEVEL 0x00001048L
-#define BA0_AC97_HANDSET_CODEC_LEVEL 0x0000104AL
-#define BA0_AC97_GPIO_PIN_CONFIG 0x0000104CL
-#define BA0_AC97_GPIO_PIN_TYPE 0x0000104EL
-#define BA0_AC97_GPIO_PIN_STICKY 0x00001050L
-#define BA0_AC97_GPIO_PIN_WAKEUP 0x00001052L
-#define BA0_AC97_GPIO_PIN_STATUS 0x00001054L
-#define BA0_AC97_MISC_MODEM_AFE_STAT 0x00001056L
-#define BA0_AC97_RESERVED_58 0x00001058L
-#define BA0_AC97_CRYSTAL_REV_N_FAB_ID 0x0000105AL
-#define BA0_AC97_TEST_AND_MISC_CTRL 0x0000105CL
-#define BA0_AC97_AC_MODE 0x0000105EL
-#define BA0_AC97_MISC_CRYSTAL_CONTROL 0x00001060L
-#define BA0_AC97_LINE1_HYPRID_CTRL 0x00001062L
-#define BA0_AC97_VENDOR_RESERVED_64 0x00001064L
-#define BA0_AC97_VENDOR_RESERVED_66 0x00001066L
-#define BA0_AC97_SPDIF_CONTROL 0x00001068L
-#define BA0_AC97_VENDOR_RESERVED_6A 0x0000106AL
-#define BA0_AC97_VENDOR_RESERVED_6C 0x0000106CL
-#define BA0_AC97_VENDOR_RESERVED_6E 0x0000106EL
-#define BA0_AC97_VENDOR_RESERVED_70 0x00001070L
-#define BA0_AC97_VENDOR_RESERVED_72 0x00001072L
-#define BA0_AC97_VENDOR_RESERVED_74 0x00001074L
-#define BA0_AC97_CAL_ADDRESS 0x00001076L
-#define BA0_AC97_CAL_DATA 0x00001078L
-#define BA0_AC97_VENDOR_RESERVED_7A 0x0000107AL
-#define BA0_AC97_VENDOR_ID1 0x0000107CL
-#define BA0_AC97_VENDOR_ID2 0x0000107EL
-
/*
* The following defines are for the flags in the host interrupt status
* register.
@@ -1790,6 +1716,7 @@ struct _snd_cs46xx {
struct pci_dev *pci;
snd_card_t *card;
snd_pcm_t *pcm;
+
snd_rawmidi_t *rmidi;
snd_rawmidi_substream_t *midi_input;
snd_rawmidi_substream_t *midi_output;
@@ -1814,12 +1741,15 @@ struct _snd_cs46xx {
struct pm_dev *pm_dev;
#endif
#ifdef CONFIG_SND_CS46XX_DEBUG_GPIO
- int current_gpio;
+ int current_gpio;
#endif
#ifdef CONFIG_SND_CS46XX_NEW_DSP
struct semaphore spos_mutex;
dsp_spos_instance_t * dsp_spos_instance;
+
+ snd_pcm_t *pcm_rear;
+ snd_pcm_t *pcm_iec958;
#else /* for compatibility */
cs46xx_pcm_t *playback_pcm;
unsigned int play_ctl;
@@ -1832,8 +1762,11 @@ int snd_cs46xx_create(snd_card_t *card,
cs46xx_t **rcodec);
int snd_cs46xx_pcm(cs46xx_t *chip, int device, snd_pcm_t **rpcm);
+int snd_cs46xx_pcm_rear(cs46xx_t *chip, int device, snd_pcm_t **rpcm);
+int snd_cs46xx_pcm_iec958(cs46xx_t *chip, int device, snd_pcm_t **rpcm);
int snd_cs46xx_mixer(cs46xx_t *chip);
int snd_cs46xx_midi(cs46xx_t *chip, int device, snd_rawmidi_t **rmidi);
+int snd_cs46xx_start_dsp(cs46xx_t *chip);
void snd_cs46xx_gameport(cs46xx_t *chip);
#ifdef CONFIG_PM
diff --git a/include/sound/cs46xx_dsp_spos.h b/include/sound/cs46xx_dsp_spos.h
index 271e72f5c8c5..8366aefaff6b 100644
--- a/include/sound/cs46xx_dsp_spos.h
+++ b/include/sound/cs46xx_dsp_spos.h
@@ -36,24 +36,35 @@
#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_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_DCDC 0x0badf1d0ul /* dont care */
#define DSP_SPOS_DCDCHI 0x0badul
#define DSP_SPOS_DCDCLO 0xf1d0ul
-#define DSP_MAX_TASK_NAME 60
+#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_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
+#define DSP_PCM_MAIN_CHANNEL 1
+#define DSP_PCM_REAR_CHANNEL 2
+#define DSP_PCM_CENTER_CHANNEL 3
+#define DSP_PCM_LFE_CHANNEL 4
+#define DSP_IEC958_CHANNEL 5
+
+#define DSP_SPDIF_STATUS_OUTPUT_ENABLED 1
+#define DSP_SPDIF_STATUS_PLAYBACK_OPEN 2
+#define DSP_SPDIF_STATUS_HW_ENABLED 4
+#define DSP_SPDIF_STATUS_AC3_MODE 8
+
struct _dsp_module_desc_t;
typedef struct _symbol_entry_t {
@@ -129,6 +140,8 @@ typedef struct _pcm_channel_descriptor_t {
u32 unlinked;
dsp_scb_descriptor_t * pcm_reader_scb;
dsp_scb_descriptor_t * src_scb;
+ dsp_scb_descriptor_t * mixer_scb;
+ int pcm_channel_id;
void * private_data;
} pcm_channel_descriptor_t;
@@ -141,8 +154,14 @@ typedef struct _dsp_spos_instance_t {
segment_desc_t code;
- /* PCM playback */
+ /* Main PCM playback mixer */
dsp_scb_descriptor_t * master_mix_scb;
+ u16 dac_volume_right;
+ u16 dac_volume_left;
+
+ /* Rear PCM playback mixer */
+ dsp_scb_descriptor_t * rear_mix_scb;
+
int npcm_channels;
int nsrc_scb;
pcm_channel_descriptor_t pcm_channels[DSP_MAX_PCM_CHANNELS];
@@ -175,7 +194,8 @@ typedef struct _dsp_spos_instance_t {
/* SPDIF status */
int spdif_status_out;
int spdif_status_in;
- u32 spdif_input_volume;
+ u16 spdif_input_volume_right;
+ u16 spdif_input_volume_left;
/* SPDIF input sample rate converter */
dsp_scb_descriptor_t * spdif_in_src;
@@ -191,6 +211,12 @@ typedef struct _dsp_spos_instance_t {
/* reference snooper */
dsp_scb_descriptor_t * ref_snoop_scb;
+ /* SPDIF output PCM reference */
+ dsp_scb_descriptor_t * spdif_pcm_input_scb;
+
+ /* asynch TX task */
+ dsp_scb_descriptor_t * asynch_tx_scb;
+
/* record sources */
dsp_scb_descriptor_t * pcm_input;
dsp_scb_descriptor_t * adc_input;
@@ -199,4 +225,3 @@ typedef struct _dsp_spos_instance_t {
} dsp_spos_instance_t;
#endif /* __DSP_SPOS_H__ */
-
diff --git a/include/sound/info.h b/include/sound/info.h
index b45b422063e2..6984c6e736dc 100644
--- a/include/sound/info.h
+++ b/include/sound/info.h
@@ -130,8 +130,9 @@ void snd_info_free_device(snd_info_entry_t * entry);
int snd_info_store_text(snd_info_entry_t * entry);
int snd_info_restore_text(snd_info_entry_t * entry);
+int snd_info_card_create(snd_card_t * card);
int snd_info_card_register(snd_card_t * card);
-int snd_info_card_unregister(snd_card_t * card);
+int snd_info_card_free(snd_card_t * card);
int snd_info_register(snd_info_entry_t * entry);
int snd_info_unregister(snd_info_entry_t * entry);
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index 2c329a00dcae..c7f41630c253 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -96,7 +96,7 @@ typedef struct _snd_pcm_ops {
void *buf, snd_pcm_uframes_t count);
int (*silence)(snd_pcm_substream_t *substream, int channel,
snd_pcm_uframes_t pos, snd_pcm_uframes_t count);
- void *(*page)(snd_pcm_substream_t *substream, unsigned long offset);
+ struct page *(*page)(snd_pcm_substream_t *substream, unsigned long offset);
} snd_pcm_ops_t;
/*
@@ -125,7 +125,7 @@ typedef struct _snd_pcm_ops {
#define SNDRV_PCM_DMA_TYPE_PCI 2 /* PCI continuous */
#define SNDRV_PCM_DMA_TYPE_SBUS 3 /* SBUS continuous */
-/* If you change this don't forget to changed snd_pcm_rates table in pcm_lib.c */
+/* If you change this don't forget to change rates[] table in pcm_native.c */
#define SNDRV_PCM_RATE_5512 (1<<0) /* 5512Hz */
#define SNDRV_PCM_RATE_8000 (1<<1) /* 8000Hz */
#define SNDRV_PCM_RATE_11025 (1<<2) /* 11025Hz */
diff --git a/include/sound/pcm_sgbuf.h b/include/sound/pcm_sgbuf.h
index 63eacc892da8..bc6474559c57 100644
--- a/include/sound/pcm_sgbuf.h
+++ b/include/sound/pcm_sgbuf.h
@@ -61,7 +61,7 @@ int snd_pcm_sgbuf_free(snd_pcm_substream_t *substream);
int snd_pcm_sgbuf_ops_copy_playback(snd_pcm_substream_t *substream, int channel, snd_pcm_uframes_t hwoff, void *buf, snd_pcm_uframes_t count);
int snd_pcm_sgbuf_ops_copy_capture(snd_pcm_substream_t *substream, int channel, snd_pcm_uframes_t hwoff, void *buf, snd_pcm_uframes_t count);
int snd_pcm_sgbuf_ops_silence(snd_pcm_substream_t *substream, int channel, snd_pcm_uframes_t hwoff, snd_pcm_uframes_t count);
-void *snd_pcm_sgbuf_ops_page(snd_pcm_substream_t *substream, unsigned long offset);
+struct page *snd_pcm_sgbuf_ops_page(snd_pcm_substream_t *substream, unsigned long offset);
#endif /* __SOUND_PCM_SGBUF_H */
diff --git a/include/sound/version.h b/include/sound/version.h
index de5e5218a7b4..acaac7181bbe 100644
--- a/include/sound/version.h
+++ b/include/sound/version.h
@@ -1,3 +1,3 @@
/* include/version.h. Generated automatically by configure. */
#define CONFIG_SND_VERSION "0.9.0rc5"
-#define CONFIG_SND_DATE " (Tue Oct 29 09:19:27 2002 UTC)"
+#define CONFIG_SND_DATE " (Sun Nov 10 19:48:18 2002 UTC)"
diff --git a/kernel/sched.c b/kernel/sched.c
index 6821d73ff10b..35373ad017f5 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -157,6 +157,7 @@ struct runqueue {
task_t *migration_thread;
struct list_head migration_queue;
+ atomic_t nr_iowait;
} ____cacheline_aligned;
static struct runqueue runqueues[NR_CPUS] __cacheline_aligned;
@@ -557,9 +558,11 @@ unsigned long nr_uninterruptible(void)
{
unsigned long i, sum = 0;
- for (i = 0; i < NR_CPUS; i++)
+ for (i = 0; i < NR_CPUS; i++) {
+ if (!cpu_online(i))
+ continue;
sum += cpu_rq(i)->nr_uninterruptible;
-
+ }
return sum;
}
@@ -567,9 +570,23 @@ unsigned long nr_context_switches(void)
{
unsigned long i, sum = 0;
- for (i = 0; i < NR_CPUS; i++)
+ for (i = 0; i < NR_CPUS; i++) {
+ if (!cpu_online(i))
+ continue;
sum += cpu_rq(i)->nr_switches;
+ }
+ return sum;
+}
+
+unsigned long nr_iowait(void)
+{
+ unsigned long i, sum = 0;
+ for (i = 0; i < NR_CPUS; ++i) {
+ if (!cpu_online(i))
+ continue;
+ sum += atomic_read(&cpu_rq(i)->nr_iowait);
+ }
return sum;
}
@@ -875,7 +892,7 @@ void scheduler_tick(int user_ticks, int sys_ticks)
/* note: this timer irq context must be accounted for as well */
if (irq_count() - HARDIRQ_OFFSET >= SOFTIRQ_OFFSET)
kstat_cpu(cpu).cpustat.system += sys_ticks;
- else if (atomic_read(&nr_iowait_tasks) > 0)
+ else if (atomic_read(&rq->nr_iowait) > 0)
kstat_cpu(cpu).cpustat.iowait += sys_ticks;
else
kstat_cpu(cpu).cpustat.idle += sys_ticks;
@@ -1712,6 +1729,31 @@ void yield(void)
sys_sched_yield();
}
+/*
+ * This task is about to go to sleep on IO. Increment rq->nr_iowait so
+ * that process accounting knows that this is a task in IO wait state.
+ *
+ * But don't do that if it is a deliberate, throttling IO wait (this task
+ * has set its backing_dev_info: the queue against which it should throttle)
+ */
+void io_schedule(void)
+{
+ struct runqueue *rq = this_rq();
+
+ atomic_inc(&rq->nr_iowait);
+ schedule();
+ atomic_dec(&rq->nr_iowait);
+}
+
+void io_schedule_timeout(long timeout)
+{
+ struct runqueue *rq = this_rq();
+
+ atomic_inc(&rq->nr_iowait);
+ schedule_timeout(timeout);
+ atomic_dec(&rq->nr_iowait);
+}
+
/**
* sys_sched_get_priority_max - return maximum RT priority.
* @policy: scheduling class.
@@ -2160,6 +2202,7 @@ void __init sched_init(void)
rq->expired = rq->arrays + 1;
spin_lock_init(&rq->lock);
INIT_LIST_HEAD(&rq->migration_queue);
+ atomic_set(&rq->nr_iowait, 0);
for (j = 0; j < 2; j++) {
array = rq->arrays + j;
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 0317dd749b2b..c6eeba758371 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -31,7 +31,7 @@
#include <linux/sysrq.h>
#include <linux/highuid.h>
#include <linux/writeback.h>
-
+#include <linux/hugetlb.h>
#include <asm/uaccess.h>
#ifdef CONFIG_ROOT_NFS
@@ -99,11 +99,6 @@ int proc_dol2crvec(ctl_table *table, int write, struct file *filp,
extern int acct_parm[];
#endif
-#ifdef CONFIG_HUGETLB_PAGE
-extern int htlbpage_max;
-extern int set_hugetlb_mem_size(int);
-#endif
-
static int parse_table(int *, int, void *, size_t *, void *, size_t,
ctl_table *, void **);
static int proc_doutsstring(ctl_table *table, int write, struct file *filp,
@@ -315,8 +310,7 @@ static ctl_table vm_table[] = {
0644, NULL, &proc_dointvec_minmax, &sysctl_intvec, NULL, &zero,
&one_hundred },
#ifdef CONFIG_HUGETLB_PAGE
- {VM_HUGETLB_PAGES, "nr_hugepages", &htlbpage_max, sizeof(int), 0644, NULL,
- &proc_dointvec},
+ {VM_HUGETLB_PAGES, "nr_hugepages", &htlbpage_max, sizeof(int), 0644, NULL, &hugetlb_sysctl_handler},
#endif
{0}
};
@@ -907,10 +901,6 @@ static int do_proc_dointvec(ctl_table *table, int write, struct file *filp,
val = -val;
buffer += len;
left -= len;
-#ifdef CONFIG_HUGETLB_PAGE
- if (i == &htlbpage_max)
- val = set_hugetlb_mem_size(val);
-#endif
switch(op) {
case OP_SET: *i = val; break;
case OP_AND: *i &= val; break;
diff --git a/mm/filemap.c b/mm/filemap.c
index 4dcbc344f2d2..421b8597995a 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -791,6 +791,7 @@ __generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
if (seg == 0)
return -EFAULT;
nr_segs = seg;
+ count -= iv->iov_len; /* This segment is no good */
break;
}
@@ -1578,6 +1579,7 @@ generic_file_write_nolock(struct file *file, const struct iovec *iov,
if (seg == 0)
return -EFAULT;
nr_segs = seg;
+ ocount -= iv->iov_len; /* This segment is no good */
break;
}
count = ocount;
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 819a65b3d33a..0158427d2502 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -175,7 +175,6 @@ free_pages_bulk(struct zone *zone, int count,
/* have to delete it as __free_pages_bulk list manipulates */
list_del(&page->list);
__free_pages_bulk(page, base, zone, area, mask, order);
- mod_page_state(pgfree, count<<order);
ret++;
}
spin_unlock_irqrestore(&zone->lock, flags);
@@ -186,6 +185,7 @@ void __free_pages_ok(struct page *page, unsigned int order)
{
LIST_HEAD(list);
+ mod_page_state(pgfree, 1 << order);
free_pages_check(__FUNCTION__, page);
list_add(&page->list, &list);
free_pages_bulk(page_zone(page), 1, &list, order);
@@ -291,32 +291,19 @@ static int rmqueue_bulk(struct zone *zone, unsigned int order,
unsigned long count, struct list_head *list)
{
unsigned long flags;
- int i, allocated = 0;
+ int i;
+ int allocated = 0;
struct page *page;
- struct list_head *curr;
- LIST_HEAD(temp);
spin_lock_irqsave(&zone->lock, flags);
for (i = 0; i < count; ++i) {
page = __rmqueue(zone, order);
if (page == NULL)
break;
- ++allocated;
- list_add(&page->list, &temp);
+ allocated++;
+ list_add_tail(&page->list, list);
}
spin_unlock_irqrestore(&zone->lock, flags);
-
- /*
- * This may look inefficient because we're walking the list again,
- * but the cachelines are hot, so it's very cheap, and this way we
- * can drop the zone lock much earlier
- */
- list_for_each(curr, &temp) {
- page = list_entry(curr, struct page, list);
- BUG_ON(bad_range(zone, page));
- prep_new_page(page, order);
- }
- list_splice(&temp, list->prev);
return allocated;
}
@@ -354,6 +341,7 @@ static void free_hot_cold_page(struct page *page, int cold)
struct per_cpu_pages *pcp;
unsigned long flags;
+ inc_page_state(pgfree);
free_pages_check(__FUNCTION__, page);
pcp = &zone->pageset[get_cpu()].pcp[cold];
local_irq_save(flags);
@@ -405,6 +393,7 @@ static struct page *buffered_rmqueue(struct zone *zone, int order, int cold)
if (page != NULL) {
BUG_ON(bad_range(zone, page));
+ mod_page_state(pgalloc, 1 << order);
prep_new_page(page, order);
}
return page;
@@ -431,8 +420,6 @@ __alloc_pages(unsigned int gfp_mask, unsigned int order,
if (gfp_mask & __GFP_COLD)
cold = 1;
- mod_page_state(pgalloc, 1<<order);
-
zones = zonelist->zones; /* the list of zones suitable for gfp_mask */
classzone = zones[0];
if (classzone == NULL) /* no zones in the zonelist */
diff --git a/sound/core/info.c b/sound/core/info.c
index 0e1bfb625ddf..9792d9ee75a1 100644
--- a/sound/core/info.c
+++ b/sound/core/info.c
@@ -699,12 +699,10 @@ int __exit snd_info_done(void)
*/
-int snd_info_card_register(snd_card_t * card)
+int snd_info_card_create(snd_card_t * card)
{
char str[8];
- char *s;
snd_info_entry_t *entry;
- struct proc_dir_entry *p;
snd_assert(card != NULL, return -ENXIO);
@@ -717,11 +715,20 @@ int snd_info_card_register(snd_card_t * card)
return -ENOMEM;
}
card->proc_root = entry;
+ return 0;
+}
+
+int snd_info_card_register(snd_card_t * card)
+{
+ char *s;
+ struct proc_dir_entry *p;
+
+ snd_assert(card != NULL, return -ENXIO);
- if (!strcmp(card->id, str))
+ if (!strcmp(card->id, card->proc_root->name))
return 0;
- s = snd_kmalloc_strdup(str, GFP_KERNEL);
+ s = snd_kmalloc_strdup(card->proc_root->name, GFP_KERNEL);
if (s == NULL)
return -ENOMEM;
p = snd_create_proc_entry(card->id, S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO, snd_proc_root);
@@ -738,7 +745,7 @@ int snd_info_card_register(snd_card_t * card)
return 0;
}
-int snd_info_card_unregister(snd_card_t * card)
+int snd_info_card_free(snd_card_t * card)
{
void *data;
diff --git a/sound/core/init.c b/sound/core/init.c
index 3e15f1a4fe61..77565af5ba45 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -23,6 +23,7 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/time.h>
+#include <linux/ctype.h>
#include <sound/core.h>
#include <sound/control.h>
#include <sound/info.h>
@@ -45,7 +46,6 @@ snd_card_t *snd_card_new(int idx, const char *xid,
struct module *module, int extra_size)
{
snd_card_t *card;
- snd_info_entry_t *entry;
int err;
if (extra_size < 0)
@@ -79,8 +79,6 @@ snd_card_t *snd_card_new(int idx, const char *xid,
snd_cards_lock |= 1 << idx; /* lock it */
write_unlock(&snd_card_rwlock);
card->number = idx;
- if (!card->id[0])
- sprintf(card->id, "card%i", card->number);
card->module = module;
INIT_LIST_HEAD(&card->devices);
rwlock_init(&card->control_rwlock);
@@ -97,28 +95,14 @@ snd_card_t *snd_card_new(int idx, const char *xid,
snd_printd("unable to register control minors\n");
goto __error;
}
- if ((err = snd_info_card_register(card)) < 0) {
- snd_printd("unable to register card info\n");
+ if ((err = snd_info_card_create(card)) < 0) {
+ snd_printd("unable to create card info\n");
goto __error_ctl;
}
- if ((entry = snd_info_create_card_entry(card, "id", card->proc_root)) == NULL) {
- snd_printd("unable to create card entry\n");
- goto __error_info;
- }
- entry->content = SNDRV_INFO_CONTENT_TEXT;
- entry->c.text.read_size = PAGE_SIZE;
- entry->c.text.read = snd_card_id_read;
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- goto __error_info;
- }
- card->proc_id = entry;
if (extra_size > 0)
card->private_data = (char *)card + sizeof(snd_card_t);
return card;
- __error_info:
- snd_info_card_unregister(card);
__error_ctl:
snd_ctl_unregister(card);
__error:
@@ -157,8 +141,8 @@ int snd_card_free(snd_card_t * card)
if (card->private_free)
card->private_free(card);
snd_info_free_entry(card->proc_id);
- if (snd_info_card_unregister(card) < 0) {
- snd_printk(KERN_WARNING "unable to unregister card info\n");
+ if (snd_info_card_free(card) < 0) {
+ snd_printk(KERN_WARNING "unable to free card info\n");
/* Not fatal error */
}
write_lock(&snd_card_rwlock);
@@ -168,9 +152,66 @@ int snd_card_free(snd_card_t * card)
return 0;
}
+static void choose_default_id(snd_card_t *card)
+{
+ int i, len, idx_flag = 0, loops = 8;
+ char *id, *spos;
+
+ id = spos = card->shortname;
+ while (*id != '\0') {
+ if (*id == ' ')
+ spos = id + 1;
+ id++;
+ }
+ id = card->id;
+ while (*spos != '\0' && id - card->id < sizeof(card->id) - 1) {
+ if (isalnum(*spos))
+ *id++ = *spos;
+ spos++;
+ }
+ *id = '\0';
+
+ id = card->id;
+
+ while (1) {
+ if (loops-- == 0) {
+ snd_printk(KERN_ERR "unable to choose default card id (%s)", id);
+ strcpy(card->id, card->proc_root->name);
+ return;
+ }
+ if (!snd_info_check_reserved_words(id))
+ goto __change;
+ for (i = 0; i < snd_ecards_limit; i++) {
+ if (snd_cards[i] && !strcmp(snd_cards[i]->id, id))
+ goto __change;
+ }
+ break;
+
+ __change:
+ len = strlen(id);
+ if (idx_flag)
+ id[len-1]++;
+ else if (len <= sizeof(card->id) - 3) {
+ strcat(id, "_1");
+ idx_flag++;
+ } else {
+ spos = id + len - 2;
+ if (len <= sizeof(card->id) - 2)
+ spos++;
+ *spos++ = '_';
+ *spos++ = '1';
+ *spos++ = '\0';
+ idx_flag++;
+ }
+ }
+
+ strcpy(card->id, id);
+}
+
int snd_card_register(snd_card_t * card)
{
int err;
+ snd_info_entry_t *entry;
snd_runtime_check(card != NULL, return -EINVAL);
if ((err = snd_device_register_all(card)) < 0)
@@ -181,9 +222,28 @@ int snd_card_register(snd_card_t * card)
write_unlock(&snd_card_rwlock);
return 0;
}
+ if (!card->id[0])
+ choose_default_id(card);
snd_cards[card->number] = card;
snd_cards_count++;
write_unlock(&snd_card_rwlock);
+ if ((err = snd_info_card_register(card)) < 0) {
+ snd_printd("unable to create card info\n");
+ goto __skip_info;
+ }
+ if ((entry = snd_info_create_card_entry(card, "id", card->proc_root)) == NULL) {
+ snd_printd("unable to create card entry\n");
+ goto __skip_info;
+ }
+ entry->content = SNDRV_INFO_CONTENT_TEXT;
+ entry->c.text.read_size = PAGE_SIZE;
+ entry->c.text.read = snd_card_id_read;
+ if (snd_info_register(entry) < 0) {
+ snd_info_free_entry(entry);
+ entry = NULL;
+ }
+ card->proc_id = entry;
+ __skip_info:
#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
if (snd_mixer_oss_notify_callback)
snd_mixer_oss_notify_callback(card, 0);
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index cc7617872bb2..ad505e74f82d 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -564,7 +564,15 @@ snd_pcm_sframes_t snd_pcm_oss_read3(snd_pcm_substream_t *substream, char *ptr, s
} else {
ret = snd_pcm_lib_read(substream, ptr, frames);
}
- if (ret != -EPIPE && ret != -ESTRPIPE)
+ if (ret == -EPIPE) {
+ if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
+ ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, 0);
+ if (ret < 0)
+ break;
+ }
+ continue;
+ }
+ if (ret != -ESTRPIPE)
break;
}
return ret;
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 275a30cb43c0..7a28d0905fd6 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -1996,7 +1996,7 @@ static int snd_pcm_delay(snd_pcm_substream_t *substream, snd_pcm_sframes_t *res)
{
snd_pcm_runtime_t *runtime = substream->runtime;
int err;
- snd_pcm_sframes_t n;
+ snd_pcm_sframes_t n = 0;
spin_lock_irq(&runtime->lock);
switch (runtime->status->state) {
@@ -2014,8 +2014,6 @@ static int snd_pcm_delay(snd_pcm_substream_t *substream, snd_pcm_sframes_t *res)
n = snd_pcm_playback_hw_avail(runtime);
else
n = snd_pcm_capture_avail(runtime);
- if (put_user(n, res))
- err = -EFAULT;
break;
case SNDRV_PCM_STATE_XRUN:
err = -EPIPE;
@@ -2026,6 +2024,9 @@ static int snd_pcm_delay(snd_pcm_substream_t *substream, snd_pcm_sframes_t *res)
break;
}
spin_unlock_irq(&runtime->lock);
+ if (!err)
+ if (put_user(n, res))
+ err = -EFAULT;
return err;
}
@@ -2668,12 +2669,13 @@ static unsigned long snd_pcm_mmap_data_nopage(struct vm_area_struct *area, unsig
if (offset > dma_bytes - PAGE_SIZE)
return NOPAGE_SIGBUS;
if (substream->ops->page) {
- vaddr = substream->ops->page(substream, offset);
- if (! vaddr)
+ page = substream->ops->page(substream, offset);
+ if (! page)
return NOPAGE_OOM;
- } else
+ } else {
vaddr = runtime->dma_area + offset;
- page = virt_to_page(vaddr);
+ page = virt_to_page(vaddr);
+ }
get_page(page);
#ifndef LINUX_2_2
return page;
diff --git a/sound/core/pcm_sgbuf.c b/sound/core/pcm_sgbuf.c
index 5f7b9a047ef8..11371eb5130b 100644
--- a/sound/core/pcm_sgbuf.c
+++ b/sound/core/pcm_sgbuf.c
@@ -66,7 +66,7 @@ int snd_pcm_sgbuf_init(snd_pcm_substream_t *substream, struct pci_dev *pci, int
sgbuf->tblsize = tblsize;
sgbuf->table = kmalloc(sizeof(struct snd_sg_page) * tblsize, GFP_KERNEL);
if (! sgbuf->table) {
- snd_pcm_sgbuf_free(substream);
+ snd_pcm_sgbuf_delete(substream);
return -ENOMEM;
}
memset(sgbuf->table, 0, sizeof(struct snd_sg_page) * tblsize);
@@ -158,9 +158,8 @@ int snd_pcm_sgbuf_free(snd_pcm_substream_t *substream)
/*
* get the page pointer on the given offset
- * used as the page callback of pcm ops
*/
-void *snd_pcm_sgbuf_ops_page(snd_pcm_substream_t *substream, unsigned long offset)
+static void *sgbuf_get_addr(snd_pcm_substream_t *substream, unsigned long offset)
{
struct snd_sg_buf *sgbuf;
unsigned int idx;
@@ -173,6 +172,19 @@ void *snd_pcm_sgbuf_ops_page(snd_pcm_substream_t *substream, unsigned long offse
}
/*
+ * get the page struct at the given offset
+ * used as the page callback of pcm ops
+ */
+struct page *snd_pcm_sgbuf_ops_page(snd_pcm_substream_t *substream, unsigned long offset)
+{
+ void *addr = sgbuf_get_addr(substream, offset);
+ if (addr)
+ return virt_to_page(addr);
+ else
+ return 0;
+}
+
+/*
* do copy_from_user to the sg buffer
*/
static int copy_from_user_sg_buf(snd_pcm_substream_t *substream,
@@ -184,7 +196,7 @@ static int copy_from_user_sg_buf(snd_pcm_substream_t *substream,
hwoff -= p;
len = PAGE_SIZE - hwoff;
for (;;) {
- addr = snd_pcm_sgbuf_ops_page(substream, p);
+ addr = sgbuf_get_addr(substream, p);
if (! addr)
return -EFAULT;
if (len > bytes)
@@ -214,7 +226,7 @@ static int copy_to_user_sg_buf(snd_pcm_substream_t *substream,
hwoff -= p;
len = PAGE_SIZE - hwoff;
for (;;) {
- addr = snd_pcm_sgbuf_ops_page(substream, p);
+ addr = sgbuf_get_addr(substream, p);
if (! addr)
return -EFAULT;
if (len > bytes)
@@ -246,7 +258,7 @@ static int set_silence_sg_buf(snd_pcm_substream_t *substream,
len = bytes_to_samples(substream->runtime, PAGE_SIZE - hwoff);
page_len = bytes_to_samples(substream->runtime, PAGE_SIZE);
for (;;) {
- addr = snd_pcm_sgbuf_ops_page(substream, p);
+ addr = sgbuf_get_addr(substream, p);
if (! addr)
return -EFAULT;
if (len > samples)
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index 6b3bb04c6c56..2b5e56617107 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -699,7 +699,6 @@ static int snd_rawmidi_ioctl(struct inode *inode, struct file *file,
case SNDRV_RAWMIDI_IOCTL_PARAMS:
{
snd_rawmidi_params_t params;
- int err;
if (copy_from_user(&params, (snd_rawmidi_params_t *) arg, sizeof(snd_rawmidi_params_t)))
return -EFAULT;
switch (params.stream) {
@@ -714,9 +713,6 @@ static int snd_rawmidi_ioctl(struct inode *inode, struct file *file,
default:
return -EINVAL;
}
- if (copy_to_user((snd_rawmidi_params_t *) arg, &params, sizeof(snd_rawmidi_params_t)))
- return -EFAULT;
- return err;
}
case SNDRV_RAWMIDI_IOCTL_STATUS:
{
diff --git a/sound/core/seq/seq_prioq.c b/sound/core/seq/seq_prioq.c
index b28a1b2ec15f..f954d0115f08 100644
--- a/sound/core/seq/seq_prioq.c
+++ b/sound/core/seq/seq_prioq.c
@@ -25,7 +25,6 @@
#include <sound/core.h>
#include "seq_timer.h"
#include "seq_prioq.h"
-#include "seq_timer.h"
/* Implementation is a simple linked list for now...
diff --git a/sound/i2c/l3/uda1341.c b/sound/i2c/l3/uda1341.c
index 97facb47b564..51ae6acf0b85 100644
--- a/sound/i2c/l3/uda1341.c
+++ b/sound/i2c/l3/uda1341.c
@@ -16,7 +16,7 @@
* 2002-04-12 Tomas Kasparek Proc interface update, code cleanup
*/
-/* $Id: uda1341.c,v 1.4 2002/08/15 12:13:06 perex Exp $ */
+/* $Id: uda1341.c,v 1.5 2002/11/09 13:12:19 perex Exp $ */
#include <sound/driver.h>
#include <linux/module.h>
@@ -341,7 +341,7 @@ static void snd_uda1341_proc_read(snd_info_entry_t *entry,
snd_iprintf(buffer, "Automatic Gain Ctrl : %s\n", uda->cfg[CMD_AGC] ? "on" : "off");
snd_iprintf(buffer, "AGC attack time : %d ms\n", AGC_atime[uda->cfg[CMD_AGC_TIME]]);
- snd_iprintf(buffer, "AGC decay time : %d ns\n", AGC_dtime[uda->cfg[CMD_AGC_TIME]]);
+ snd_iprintf(buffer, "AGC decay time : %d ms\n", AGC_dtime[uda->cfg[CMD_AGC_TIME]]);
snd_iprintf(buffer, "AGC output level : %s dB\n\n", AGC_level[uda->cfg[CMD_AGC_LEVEL]]);
snd_iprintf(buffer, "Mute : %s\n", uda->cfg[CMD_MUTE] ? "on" : "off");
diff --git a/sound/isa/cs423x/cs4231_lib.c b/sound/isa/cs423x/cs4231_lib.c
index 827c3c2541d2..0982bba6b988 100644
--- a/sound/isa/cs423x/cs4231_lib.c
+++ b/sound/isa/cs423x/cs4231_lib.c
@@ -124,6 +124,48 @@ static unsigned char snd_cs4231_original_image[32] =
* Basic I/O functions
*/
+#if !defined(EBUS_SUPPORT) && !defined(SBUS_SUPPORT)
+#define __CS4231_INLINE__ inline
+#else
+#define __CS4231_INLINE__ /* nothing */
+#endif
+
+static __CS4231_INLINE__ void cs4231_outb(cs4231_t *chip, u8 offset, u8 val)
+{
+#ifdef EBUS_SUPPORT
+ if (chip->ebus->flag) {
+ writeb(val, chip->port + (offset << 2));
+ } else {
+#endif
+#ifdef SBUS_SUPPORT
+ sbus_writeb(val, chip->port + (offset << 2));
+#endif
+#ifdef EBUS_SUPPORT
+ }
+#endif
+#ifdef LEGACY_SUPPORT
+ outb(val, chip->port + offset);
+#endif
+}
+
+static __CS4231_INLINE__ u8 cs4231_inb(cs4231_t *chip, u8 offset)
+{
+#ifdef EBUS_SUPPORT
+ if (chip->ebus_flag) {
+ return readb(chip->port + (offset << 2));
+ } else {
+#endif
+#ifdef SBUS_SUPPORT
+ return sbus_writeb(chip->port + (offset << 2));
+#endif
+#ifdef EBUS_SUPPORT
+ }
+#endif
+#ifdef LEGACY_SUPPORT
+ return inb(chip->port + offset);
+#endif
+}
+
void snd_cs4231_outm(cs4231_t *chip, unsigned char reg,
unsigned char mask, unsigned char value)
{
@@ -131,21 +173,21 @@ void snd_cs4231_outm(cs4231_t *chip, unsigned char reg,
unsigned char tmp;
for (timeout = 250;
- timeout > 0 && (inb(CS4231P(chip, REGSEL)) & CS4231_INIT);
+ timeout > 0 && (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT);
timeout--)
udelay(100);
#ifdef CONFIG_SND_DEBUG
- if (inb(CS4231P(chip, REGSEL)) & CS4231_INIT)
+ if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
snd_printk("outm: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value);
#endif
if (chip->calibrate_mute) {
chip->image[reg] &= mask;
chip->image[reg] |= value;
} else {
- outb(chip->mce_bit | reg, CS4231P(chip, REGSEL));
+ cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg);
mb();
tmp = (chip->image[reg] & mask) | value;
- outb(tmp, CS4231P(chip, REG));
+ cs4231_outb(chip, CS4231P(REG), tmp);
chip->image[reg] = tmp;
mb();
}
@@ -156,11 +198,11 @@ static void snd_cs4231_dout(cs4231_t *chip, unsigned char reg, unsigned char val
int timeout;
for (timeout = 250;
- timeout > 0 && (inb(CS4231P(chip, REGSEL)) & CS4231_INIT);
+ timeout > 0 && (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT);
timeout--)
udelay(10);
- outb(chip->mce_bit | reg, CS4231P(chip, REGSEL));
- outb(value, CS4231P(chip, REG));
+ cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg);
+ cs4231_outb(chip, CS4231P(REG), value);
mb();
}
@@ -169,15 +211,15 @@ void snd_cs4231_out(cs4231_t *chip, unsigned char reg, unsigned char value)
int timeout;
for (timeout = 250;
- timeout > 0 && (inb(CS4231P(chip, REGSEL)) & CS4231_INIT);
+ timeout > 0 && (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT);
timeout--)
udelay(100);
#ifdef CONFIG_SND_DEBUG
- if (inb(CS4231P(chip, REGSEL)) & CS4231_INIT)
+ if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
snd_printk("out: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value);
#endif
- outb(chip->mce_bit | reg, CS4231P(chip, REGSEL));
- outb(value, CS4231P(chip, REG));
+ cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg);
+ cs4231_outb(chip, CS4231P(REG), value);
chip->image[reg] = value;
mb();
#if 0
@@ -190,23 +232,23 @@ unsigned char snd_cs4231_in(cs4231_t *chip, unsigned char reg)
int timeout;
for (timeout = 250;
- timeout > 0 && (inb(CS4231P(chip, REGSEL)) & CS4231_INIT);
+ timeout > 0 && (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT);
timeout--)
udelay(100);
#ifdef CONFIG_SND_DEBUG
- if (inb(CS4231P(chip, REGSEL)) & CS4231_INIT)
+ if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
snd_printk("in: auto calibration time out - reg = 0x%x\n", reg);
#endif
- outb(chip->mce_bit | reg, CS4231P(chip, REGSEL));
+ cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg);
mb();
- return inb(CS4231P(chip, REG));
+ return cs4231_inb(chip, CS4231P(REG));
}
void snd_cs4236_ext_out(cs4231_t *chip, unsigned char reg, unsigned char val)
{
- outb(chip->mce_bit | 0x17, CS4231P(chip, REGSEL));
- outb(reg | (chip->image[CS4236_EXT_REG] & 0x01), CS4231P(chip, REG));
- outb(val, CS4231P(chip, REG));
+ cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | 0x17);
+ cs4231_outb(chip, CS4231P(REG), reg | (chip->image[CS4236_EXT_REG] & 0x01));
+ cs4231_outb(chip, CS4231P(REG), val);
chip->eimage[CS4236_REG(reg)] = val;
#if 0
printk("ext out : reg = 0x%x, val = 0x%x\n", reg, val);
@@ -215,14 +257,14 @@ void snd_cs4236_ext_out(cs4231_t *chip, unsigned char reg, unsigned char val)
unsigned char snd_cs4236_ext_in(cs4231_t *chip, unsigned char reg)
{
- outb(chip->mce_bit | 0x17, CS4231P(chip, REGSEL));
- outb(reg | (chip->image[CS4236_EXT_REG] & 0x01), CS4231P(chip, REG));
+ cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | 0x17);
+ cs4231_outb(chip, CS4231P(REG), reg | (chip->image[CS4236_EXT_REG] & 0x01));
#if 1
- return inb(CS4231P(chip, REG));
+ return cs4231_inb(chip, CS4231P(REG));
#else
{
unsigned char res;
- res = inb(CS4231P(chip, REG));
+ res = cs4231_inb(chip, CS4231P(REG));
printk("ext in : reg = 0x%x, val = 0x%x\n", reg, res);
return res;
}
@@ -233,8 +275,8 @@ unsigned char snd_cs4236_ext_in(cs4231_t *chip, unsigned char reg)
void snd_cs4231_debug(cs4231_t *chip)
{
- printk("CS4231 REGS: INDEX = 0x%02x ", inb(CS4231P(chip, REGSEL)));
- printk(" STATUS = 0x%02x\n", inb(CS4231P(chip, STATUS)));
+ printk("CS4231 REGS: INDEX = 0x%02x ", cs4231_inb(chip, CS4231P(REGSEL)));
+ printk(" STATUS = 0x%02x\n", cs4231_inb(chip, CS4231P(STATUS)));
printk(" 0x00: left input = 0x%02x ", snd_cs4231_in(chip, 0x00));
printk(" 0x10: alt 1 (CFIG 2) = 0x%02x\n", snd_cs4231_in(chip, 0x10));
printk(" 0x01: right input = 0x%02x ", snd_cs4231_in(chip, 0x01));
@@ -281,10 +323,10 @@ static void snd_cs4231_busy_wait(cs4231_t *chip)
/* huh.. looks like this sequence is proper for CS4231A chip (GUS MAX) */
for (timeout = 5; timeout > 0; timeout--)
- inb(CS4231P(chip, REGSEL));
+ cs4231_inb(chip, CS4231P(REGSEL));
/* end of cleanup sequence */
for (timeout = 250;
- timeout > 0 && (inb(CS4231P(chip, REGSEL)) & CS4231_INIT);
+ timeout > 0 && (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT);
timeout--)
udelay(10);
}
@@ -295,18 +337,18 @@ void snd_cs4231_mce_up(cs4231_t *chip)
int timeout;
spin_lock_irqsave(&chip->reg_lock, flags);
- for (timeout = 250; timeout > 0 && (inb(CS4231P(chip, REGSEL)) & CS4231_INIT); timeout--)
+ for (timeout = 250; timeout > 0 && (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT); timeout--)
udelay(100);
#ifdef CONFIG_SND_DEBUG
- if (inb(CS4231P(chip, REGSEL)) & CS4231_INIT)
+ if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
snd_printk("mce_up - auto calibration time out (0)\n");
#endif
chip->mce_bit |= CS4231_MCE;
- timeout = inb(CS4231P(chip, REGSEL));
+ timeout = cs4231_inb(chip, CS4231P(REGSEL));
if (timeout == 0x80)
snd_printk("mce_up [0x%lx]: serious init problem - codec still busy\n", chip->port);
if (!(timeout & CS4231_MCE))
- outb(chip->mce_bit | (timeout & 0x1f), CS4231P(chip, REGSEL));
+ cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f));
spin_unlock_irqrestore(&chip->reg_lock, flags);
}
@@ -322,12 +364,12 @@ void snd_cs4231_mce_down(cs4231_t *chip)
printk("(1) timeout = %i\n", timeout);
#endif
#ifdef CONFIG_SND_DEBUG
- if (inb(CS4231P(chip, REGSEL)) & CS4231_INIT)
- snd_printk("mce_down [0x%lx] - auto calibration time out (0)\n", CS4231P(chip, REGSEL));
+ if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
+ snd_printk("mce_down [0x%lx] - auto calibration time out (0)\n", (long)CS4231P(REGSEL));
#endif
chip->mce_bit &= ~CS4231_MCE;
- timeout = inb(CS4231P(chip, REGSEL));
- outb(chip->mce_bit | (timeout & 0x1f), CS4231P(chip, REGSEL));
+ timeout = cs4231_inb(chip, CS4231P(REGSEL));
+ cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f));
if (timeout == 0x80)
snd_printk("mce_down [0x%lx]: serious init problem - codec still busy\n", chip->port);
if ((timeout & CS4231_MCE) == 0 ||
@@ -364,7 +406,7 @@ void snd_cs4231_mce_down(cs4231_t *chip)
printk("(3) jiffies = %li\n", jiffies);
#endif
time = HZ / 10;
- while (inb(CS4231P(chip, REGSEL)) & CS4231_INIT) {
+ while (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) {
spin_unlock_irqrestore(&chip->reg_lock, flags);
if (time <= 0) {
snd_printk("mce_down - auto calibration time out (3)\n");
@@ -377,7 +419,7 @@ void snd_cs4231_mce_down(cs4231_t *chip)
spin_unlock_irqrestore(&chip->reg_lock, flags);
#if 0
printk("(4) jiffies = %li\n", jiffies);
- snd_printk("mce_down - exit = 0x%x\n", inb(CS4231P(chip, REGSEL)));
+ snd_printk("mce_down - exit = 0x%x\n", cs4231_inb(chip, CS4231P(REGSEL)));
#endif
}
@@ -403,7 +445,7 @@ static int snd_cs4231_trigger(snd_pcm_substream_t *substream,
int result = 0;
#if 0
- printk("codec trigger!!! - what = %i, enable = %i, status = 0x%x\n", what, enable, inb(CS4231P(card, STATUS)));
+ printk("codec trigger!!! - what = %i, enable = %i, status = 0x%x\n", what, enable, cs4231_inb(chip, CS4231P(STATUS)));
#endif
switch (cmd) {
@@ -423,10 +465,15 @@ static int snd_cs4231_trigger(snd_pcm_substream_t *substream,
s = s->link_next;
} while (s != substream);
spin_lock(&chip->reg_lock);
- if (cmd == SNDRV_PCM_TRIGGER_START)
+ if (cmd == SNDRV_PCM_TRIGGER_START) {
chip->image[CS4231_IFACE_CTRL] |= what;
- else
+ if (chip->trigger)
+ chip->trigger(chip, what, 1);
+ } else {
chip->image[CS4231_IFACE_CTRL] &= ~what;
+ if (chip->trigger)
+ chip->trigger(chip, what, 0);
+ }
snd_cs4231_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]);
spin_unlock(&chip->reg_lock);
break;
@@ -640,7 +687,7 @@ static void snd_cs4231_init(cs4231_t *chip)
snd_cs4231_mce_down(chip);
-#ifdef SNDRV_DEBUG_MCE
+#ifdef SNDRV_DEBUGq_MCE
snd_printk("init: (1)\n");
#endif
snd_cs4231_mce_up(chip);
@@ -713,8 +760,8 @@ static int snd_cs4231_open(cs4231_t *chip, unsigned int mode)
CS4231_RECORD_IRQ |
CS4231_TIMER_IRQ);
snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0);
- outb(0, CS4231P(chip, STATUS)); /* clear IRQ */
- outb(0, CS4231P(chip, STATUS)); /* clear IRQ */
+ cs4231_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
+ cs4231_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
chip->image[CS4231_PIN_CTRL] |= CS4231_IRQ_ENABLE;
snd_cs4231_out(chip, CS4231_PIN_CTRL, chip->image[CS4231_PIN_CTRL]);
snd_cs4231_out(chip, CS4231_IRQ_STATUS, CS4231_PLAYBACK_IRQ |
@@ -743,8 +790,8 @@ static void snd_cs4231_close(cs4231_t *chip, unsigned int mode)
/* disable IRQ */
spin_lock_irqsave(&chip->reg_lock, flags);
snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0);
- outb(0, CS4231P(chip, STATUS)); /* clear IRQ */
- outb(0, CS4231P(chip, STATUS)); /* clear IRQ */
+ cs4231_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
+ cs4231_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
chip->image[CS4231_PIN_CTRL] &= ~CS4231_IRQ_ENABLE;
snd_cs4231_out(chip, CS4231_PIN_CTRL, chip->image[CS4231_PIN_CTRL]);
@@ -765,8 +812,8 @@ static void snd_cs4231_close(cs4231_t *chip, unsigned int mode)
/* clear IRQ again */
snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0);
- outb(0, CS4231P(chip, STATUS)); /* clear IRQ */
- outb(0, CS4231P(chip, STATUS)); /* clear IRQ */
+ cs4231_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
+ cs4231_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
spin_unlock_irqrestore(&chip->reg_lock, flags);
snd_cs4231_calibrate_mute(chip, 0);
@@ -829,6 +876,7 @@ static int snd_cs4231_playback_hw_free(snd_pcm_substream_t * substream)
return snd_pcm_lib_free_pages(substream);
}
+#ifdef LEGACY_SUPPORT
static int snd_cs4231_playback_prepare(snd_pcm_substream_t * substream)
{
cs4231_t *chip = snd_pcm_substream_chip(substream);
@@ -850,6 +898,7 @@ static int snd_cs4231_playback_prepare(snd_pcm_substream_t * substream)
#endif
return 0;
}
+#endif /* LEGACY_SUPPORT */
static int snd_cs4231_capture_hw_params(snd_pcm_substream_t * substream,
snd_pcm_hw_params_t * hw_params)
@@ -871,6 +920,7 @@ static int snd_cs4231_capture_hw_free(snd_pcm_substream_t * substream)
return snd_pcm_lib_free_pages(substream);
}
+#ifdef LEGACY_SUPPORT
static int snd_cs4231_capture_prepare(snd_pcm_substream_t * substream)
{
cs4231_t *chip = snd_pcm_substream_chip(substream);
@@ -894,6 +944,7 @@ static int snd_cs4231_capture_prepare(snd_pcm_substream_t * substream)
spin_unlock_irqrestore(&chip->reg_lock, flags);
return 0;
}
+#endif
static void snd_cs4231_overrange(cs4231_t *chip)
{
@@ -940,6 +991,7 @@ void snd_cs4231_interrupt(int irq, void *dev_id, struct pt_regs *regs)
spin_unlock(&chip->reg_lock);
}
+#ifdef LEGACY_SUPPORT
static snd_pcm_uframes_t snd_cs4231_playback_pointer(snd_pcm_substream_t * substream)
{
cs4231_t *chip = snd_pcm_substream_chip(substream);
@@ -961,12 +1013,13 @@ static snd_pcm_uframes_t snd_cs4231_capture_pointer(snd_pcm_substream_t * substr
ptr = chip->c_dma_size - snd_dma_residue(chip->dma2);
return bytes_to_frames(substream->runtime, ptr);
}
+#endif /* LEGACY_SUPPORT */
/*
*/
-static int snd_cs4231_probe(cs4231_t *chip)
+int snd_cs4231_probe(cs4231_t *chip)
{
unsigned long flags;
int i, id, rev;
@@ -979,7 +1032,7 @@ static int snd_cs4231_probe(cs4231_t *chip)
id = 0;
for (i = 0; i < 50; i++) {
mb();
- if (inb(CS4231P(chip, REGSEL)) & CS4231_INIT)
+ if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
udelay(2000);
else {
spin_lock_irqsave(&chip->reg_lock, flags);
@@ -1020,8 +1073,8 @@ static int snd_cs4231_probe(cs4231_t *chip)
}
}
spin_lock_irqsave(&chip->reg_lock, flags);
- inb(CS4231P(chip, STATUS)); /* clear any pendings IRQ */
- outb(0, CS4231P(chip, STATUS));
+ cs4231_inb(chip, CS4231P(STATUS)); /* clear any pendings IRQ */
+ cs4231_outb(chip, CS4231P(STATUS), 0);
mb();
spin_unlock_irqrestore(&chip->reg_lock, flags);
@@ -1189,6 +1242,7 @@ static int snd_cs4231_playback_open(snd_pcm_substream_t * substream)
chip->hardware == CS4231_HW_CS4239)
runtime->hw.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE;
+#ifdef LEGACY_SUPPORT
snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.buffer_bytes_max);
snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.period_bytes_max);
@@ -1196,14 +1250,20 @@ static int snd_cs4231_playback_open(snd_pcm_substream_t * substream)
if ((err = chip->claim_dma(chip, chip->dma_private_data, chip->dma1)) < 0)
return err;
}
+#endif
if ((err = snd_cs4231_open(chip, CS4231_MODE_PLAY)) < 0) {
+#ifdef LEGACY_SUPPORT
if (chip->release_dma)
chip->release_dma(chip, chip->dma_private_data, chip->dma1);
+#endif
snd_free_pages(runtime->dma_area, runtime->dma_bytes);
return err;
}
chip->playback_substream = substream;
+#if defined(SBUS_SUPPORT) || defined(EBUS_SUPPORT)
+ chip->p_periods_sent = 0;
+#endif
snd_pcm_set_sync(substream);
chip->rate_constraint(runtime);
return 0;
@@ -1222,21 +1282,28 @@ static int snd_cs4231_capture_open(snd_pcm_substream_t * substream)
chip->hardware == CS4231_HW_CS4239)
runtime->hw.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE;
+#ifdef LEGACY_SUPPORT
+ snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.buffer_bytes_max);
+ snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.period_bytes_max);
+
if (chip->claim_dma) {
if ((err = chip->claim_dma(chip, chip->dma_private_data, chip->dma2)) < 0)
return err;
}
-
- snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.buffer_bytes_max);
- snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.period_bytes_max);
+#endif
if ((err = snd_cs4231_open(chip, CS4231_MODE_RECORD)) < 0) {
+#ifdef LEGACY_SUPPORT
if (chip->release_dma)
chip->release_dma(chip, chip->dma_private_data, chip->dma2);
+#endif
snd_free_pages(runtime->dma_area, runtime->dma_bytes);
return err;
}
chip->capture_substream = substream;
+#if defined(SBUS_SUPPORT) || defined(EBUS_SUPPORT)
+ chip->c_periods_sent = 0;
+#endif
snd_pcm_set_sync(substream);
chip->rate_constraint(runtime);
return 0;
@@ -1301,8 +1368,8 @@ static void snd_cs4231_resume(cs4231_t *chip)
spin_lock_irqsave(&chip->reg_lock, flags);
snd_cs4231_busy_wait(chip);
chip->mce_bit &= ~CS4231_MCE;
- timeout = inb(CS4231P(chip, REGSEL));
- outb(chip->mce_bit | (timeout & 0x1f), CS4231P(chip, REGSEL));
+ timeout = cs4231_inb(chip, CS4231P(REGSEL));
+ cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f));
if (timeout == 0x80)
snd_printk("down [0x%lx]: serious init problem - codec still busy\n", chip->port);
if ((timeout & CS4231_MCE) == 0 ||
@@ -1334,6 +1401,8 @@ static int snd_cs4231_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *d
#endif /* CONFIG_PM */
+#ifdef LEGACY_SUPPORT
+
static int snd_cs4231_free(cs4231_t *chip)
{
if (chip->res_port) {
@@ -1373,6 +1442,8 @@ static int snd_cs4231_dev_free(snd_device_t *device)
return snd_cs4231_free(chip);
}
+#endif /* LEGACY_SUPPORT */
+
const char *snd_cs4231_chip_id(cs4231_t *chip)
{
switch (chip->hardware) {
@@ -1392,6 +1463,35 @@ const char *snd_cs4231_chip_id(cs4231_t *chip)
}
}
+static int snd_cs4231_new(snd_card_t * card,
+ unsigned short hardware,
+ unsigned short hwshare,
+ cs4231_t ** rchip)
+{
+ cs4231_t *chip;
+
+ *rchip = NULL;
+ chip = snd_magic_kcalloc(cs4231_t, 0, GFP_KERNEL);
+ if (chip == NULL)
+ return -ENOMEM;
+ chip->hardware = hardware;
+ chip->hwshare = hwshare;
+
+ spin_lock_init(&chip->reg_lock);
+ init_MUTEX(&chip->mce_mutex);
+ init_MUTEX(&chip->open_mutex);
+ chip->card = card;
+ chip->rate_constraint = snd_cs4231_xrate;
+ chip->set_playback_format = snd_cs4231_playback_format;
+ chip->set_capture_format = snd_cs4231_capture_format;
+ memcpy(&chip->image, &snd_cs4231_original_image, sizeof(snd_cs4231_original_image));
+
+ *rchip = chip;
+ return 0;
+}
+
+#ifdef LEGACY_SUPPORT
+
int snd_cs4231_create(snd_card_t * card,
unsigned long port,
unsigned long cport,
@@ -1406,15 +1506,13 @@ int snd_cs4231_create(snd_card_t * card,
cs4231_t *chip;
int err;
- *rchip = NULL;
- chip = snd_magic_kcalloc(cs4231_t, 0, GFP_KERNEL);
- if (chip == NULL)
- return -ENOMEM;
+ err = snd_cs4231_new(card, hardware, hwshare, &chip);
+ if (err < 0)
+ return err;
+
chip->irq = -1;
chip->dma1 = -1;
chip->dma2 = -1;
- chip->hardware = hardware;
- chip->hwshare = hwshare;
if ((chip->res_port = request_region(port, 4, "CS4231")) == NULL) {
snd_cs4231_free(chip);
@@ -1446,15 +1544,6 @@ int snd_cs4231_create(snd_card_t * card,
} else
chip->dma2 = dma2;
- spin_lock_init(&chip->reg_lock);
- init_MUTEX(&chip->mce_mutex);
- init_MUTEX(&chip->open_mutex);
- chip->card = card;
- chip->rate_constraint = snd_cs4231_xrate;
- chip->set_playback_format = snd_cs4231_playback_format;
- chip->set_capture_format = snd_cs4231_capture_format;
- memcpy(&chip->image, &snd_cs4231_original_image, sizeof(snd_cs4231_original_image));
-
/* global setup */
if (snd_cs4231_probe(chip) < 0) {
snd_cs4231_free(chip);
@@ -1486,6 +1575,8 @@ int snd_cs4231_create(snd_card_t * card,
return 0;
}
+#endif /* LEGACY_SUPPORT */
+
static snd_pcm_ops_t snd_cs4231_playback_ops = {
.open = snd_cs4231_playback_open,
.close = snd_cs4231_playback_close,
@@ -1540,7 +1631,23 @@ int snd_cs4231_pcm(cs4231_t *chip, int device, snd_pcm_t **rpcm)
pcm->info_flags |= SNDRV_PCM_INFO_JOINT_DUPLEX;
strcpy(pcm->name, snd_cs4231_chip_id(chip));
+#ifdef LEGACY_SUPPORT
snd_pcm_lib_preallocate_isa_pages_for_all(pcm, 64*1024, chip->dma1 > 3 || chip->dma2 > 3 ? 128*1024 : 64*1024);
+#else
+# ifdef EBUS_SUPPORT
+ if (chip->ebus_flag) {
+ snd_pcm_lib_preallocate_pci_pages_for_all(chip->dev_u.pdev, pcm,
+ 64*1024, 128*1024);
+ } else {
+# endif
+# ifdef SBUS_SUPPORT
+ snd_pcm_lib_preallocate_sbus_pages_for_all(chip->dev_u.sdev, pcm,
+ 64*1024, 128*1024);
+# endif
+# ifdef EBUS_SUPPORT
+ }
+# endif
+#endif
chip->pcm = pcm;
if (rpcm)
diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c
index 900b36f66256..67bc35c40661 100644
--- a/sound/isa/es18xx.c
+++ b/sound/isa/es18xx.c
@@ -154,10 +154,10 @@ struct _snd_es18xx {
#define ES18XX_PM 0x07
#define ES18XX_PM_GPO0 0x01
#define ES18XX_PM_GPO1 0x02
-#define ES18XX_PM_PDR 0x03
-#define ES18XX_PM_ANA 0x04
-#define ES18XX_PM_FM 0x06
-#define ES18XX_PM_SUS 0x08
+#define ES18XX_PM_PDR 0x04
+#define ES18XX_PM_ANA 0x08
+#define ES18XX_PM_FM 0x020
+#define ES18XX_PM_SUS 0x080
typedef struct _snd_es18xx es18xx_t;
diff --git a/sound/isa/sb/emu8000_pcm.c b/sound/isa/sb/emu8000_pcm.c
index 02830393730e..c01d3ceaad65 100644
--- a/sound/isa/sb/emu8000_pcm.c
+++ b/sound/isa/sb/emu8000_pcm.c
@@ -115,13 +115,15 @@ emu8k_open_dram_for_pcm(emu8000_t *emu, int channels)
/*
*/
static void
-snd_emu8000_write_wait(emu8000_t *emu)
+snd_emu8000_write_wait(emu8000_t *emu, int can_schedule)
{
while ((EMU8000_SMALW_READ(emu) & 0x80000000) != 0) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- if (signal_pending(current))
- break;
+ if (can_schedule) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(1);
+ if (signal_pending(current))
+ break;
+ }
}
}
@@ -457,7 +459,7 @@ static int emu8k_pcm_copy(snd_pcm_substream_t *subs,
emu8k_pcm_t *rec = subs->runtime->private_data;
emu8000_t *emu = rec->emu;
- snd_emu8000_write_wait(emu);
+ snd_emu8000_write_wait(emu, 1);
if (voice == -1) {
unsigned short *buf = src;
int i, err;
@@ -494,7 +496,7 @@ static int emu8k_pcm_silence(snd_pcm_substream_t *subs,
emu8k_pcm_t *rec = subs->runtime->private_data;
emu8000_t *emu = rec->emu;
- snd_emu8000_write_wait(emu);
+ snd_emu8000_write_wait(emu, 1);
if (voice == -1 && rec->voices == 1)
voice = 0;
if (voice == -1) {
@@ -524,7 +526,7 @@ static int emu8k_pcm_copy(snd_pcm_substream_t *subs,
emu8000_t *emu = rec->emu;
unsigned short *buf = src;
- snd_emu8000_write_wait(emu);
+ snd_emu8000_write_wait(emu, 1);
EMU8000_SMALW_WRITE(emu, pos + rec->loop_start[0]);
if (rec->voices > 1)
EMU8000_SMARW_WRITE(emu, pos + rec->loop_start[1]);
@@ -553,7 +555,7 @@ static int emu8k_pcm_silence(snd_pcm_substream_t *subs,
emu8k_pcm_t *rec = subs->runtime->private_data;
emu8000_t *emu = rec->emu;
- snd_emu8000_write_wait(emu);
+ snd_emu8000_write_wait(emu, 1);
EMU8000_SMALW_WRITE(emu, rec->loop_start[0] + pos);
if (rec->voices > 1)
EMU8000_SMARW_WRITE(emu, rec->loop_start[1] + pos);
@@ -645,7 +647,7 @@ static int emu8k_pcm_prepare(snd_pcm_substream_t *subs)
rec->dram_opened = 1;
/* clear loop blanks */
- snd_emu8000_write_wait(rec->emu);
+ snd_emu8000_write_wait(rec->emu, 0);
EMU8000_SMALW_WRITE(rec->emu, rec->offset);
for (i = 0; i < LOOP_BLANK_SIZE; i++)
EMU8000_SMLD_WRITE(rec->emu, 0);
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c
index 6496473e7387..85c2ab2bb234 100644
--- a/sound/pci/ac97/ac97_codec.c
+++ b/sound/pci/ac97/ac97_codec.c
@@ -105,7 +105,7 @@ static const ac97_codec_id_t snd_ac97_codec_ids[] = {
{ 0x414c4310, 0xfffffff0, "RL5382", NULL },
{ 0x414c4320, 0xfffffff0, "RL5383", NULL },
{ 0x414c4710, 0xfffffff0, "ALC200/200P", NULL },
-{ 0x414c4720, 0xfffffff0, "ALC650", NULL },
+{ 0x414c4720, 0xfffffff0, "ALC650", patch_alc650 },
{ 0x414c4730, 0xffffffff, "ALC101", NULL },
{ 0x414c4740, 0xfffffff0, "ALC202", NULL },
{ 0x414c4750, 0xfffffff0, "ALC250", NULL },
@@ -915,6 +915,25 @@ AD18XX_PCM_BITS("LFE Playback Volume", 2, 0, 31)
};
/*
+ * ALC650
+ */
+static const snd_kcontrol_new_t snd_ac97_controls_alc650[] = {
+ AC97_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0),
+ AC97_SINGLE("Surround Down Mix", AC97_ALC650_MULTICH, 1, 1, 0),
+ AC97_SINGLE("Center/LFE Down Mix", AC97_ALC650_MULTICH, 2, 1, 0),
+ AC97_SINGLE("Exchange Center/LFE", AC97_ALC650_MULTICH, 3, 1, 0),
+ AC97_SINGLE("Line-In As Surround", AC97_ALC650_MULTICH, 9, 1, 0),
+ AC97_SINGLE("Mic As Center/LFE", AC97_ALC650_MULTICH, 10, 1, 0),
+ AC97_SINGLE("IEC958 Capture Switch", AC97_ALC650_MULTICH, 11, 1, 0),
+ AC97_SINGLE("Analog to IEC958 Output", AC97_ALC650_MULTICH, 12, 1, 0),
+ AC97_SINGLE("IEC958 Input Monitor", AC97_ALC650_MULTICH, 13, 1, 0),
+#if 0 /* always set in patch_alc650 */
+ AC97_SINGLE("IEC958 Input Clock Enable", AC97_ALC650_CLOCK, 0, 1, 0),
+ AC97_SINGLE("IEC958 Input Pin Enable", AC97_ALC650_CLOCK, 1, 1, 0),
+#endif
+};
+
+/*
*
*/
@@ -1340,7 +1359,7 @@ static int snd_ac97_mixer_build(snd_card_t * card, ac97_t * ac97)
}
/* build S/PDIF controls */
- if (ac97->ext_id & AC97_EA_SPDIF) {
+ if (ac97->ext_id & AC97_EI_SPDIF) {
if (ac97->flags & AC97_CS_SPDIF) {
for (idx = 0; idx < 3; idx++)
if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_spdif[idx], ac97))) < 0)
@@ -1379,7 +1398,7 @@ static int snd_ac97_mixer_build(snd_card_t * card, ac97_t * ac97)
ac97->spdif_status = SNDRV_PCM_DEFAULT_CON_SPDIF;
}
- /* build Sigmatel specific controls */
+ /* build chip specific controls */
switch (ac97->id) {
case AC97_ID_STAC9700:
case AC97_ID_STAC9708:
@@ -1393,6 +1412,12 @@ static int snd_ac97_mixer_build(snd_card_t * card, ac97_t * ac97)
if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_ANALOG, 0))
if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_sigmatel_controls[1], ac97))) < 0)
return err;
+ break;
+ case AC97_ID_ALC650:
+ for (idx = 0; idx < ARRAY_SIZE(snd_ac97_controls_alc650); idx++)
+ if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_alc650[idx], ac97))) < 0)
+ return err;
+ break;
default:
/* nothing */
break;
diff --git a/sound/pci/ac97/ac97_id.h b/sound/pci/ac97/ac97_id.h
index b5b4dc1d9181..7f7ffe24aa0f 100644
--- a/sound/pci/ac97/ac97_id.h
+++ b/sound/pci/ac97/ac97_id.h
@@ -43,3 +43,4 @@
#define AC97_ID_CS4299 0x43525930
#define AC97_ID_CS4201 0x43525948
#define AC97_ID_CS4205 0x43525958
+#define AC97_ID_ALC650 0x414c4720
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c
index 7b755ec4382d..b9f3f9378071 100644
--- a/sound/pci/ac97/ac97_patch.c
+++ b/sound/pci/ac97/ac97_patch.c
@@ -168,7 +168,7 @@ int patch_cirrus_spdif(ac97_t * ac97)
ac97->flags |= AC97_CS_SPDIF;
ac97->rates[AC97_RATES_SPDIF] &= ~SNDRV_PCM_RATE_32000;
- ac97->ext_id |= AC97_EA_SPDIF; /* force the detection of spdif */
+ ac97->ext_id |= AC97_EI_SPDIF; /* force the detection of spdif */
snd_ac97_write_cache(ac97, AC97_CSR_ACMODE, 0x0080);
return 0;
}
@@ -184,7 +184,7 @@ int patch_cirrus_cs4299(ac97_t * ac97)
int patch_conexant(ac97_t * ac97)
{
ac97->flags |= AC97_CX_SPDIF;
- ac97->ext_id |= AC97_EA_SPDIF; /* force the detection of spdif */
+ ac97->ext_id |= AC97_EI_SPDIF; /* force the detection of spdif */
return 0;
}
@@ -336,3 +336,11 @@ int patch_ad1980(ac97_t * ac97)
snd_ac97_write_cache(ac97, AC97_AD_MISC, misc | 0x0420);
return 0;
}
+
+int patch_alc650(ac97_t * ac97)
+{
+ /* enable spdif in */
+ snd_ac97_write_cache(ac97, AC97_ALC650_CLOCK,
+ snd_ac97_read(ac97, AC97_ALC650_CLOCK) | 0x03);
+ return 0;
+}
diff --git a/sound/pci/ac97/ac97_patch.h b/sound/pci/ac97/ac97_patch.h
index b7ee01f5ea51..317669c7bdec 100644
--- a/sound/pci/ac97/ac97_patch.h
+++ b/sound/pci/ac97/ac97_patch.h
@@ -38,3 +38,4 @@ int patch_ad1881(ac97_t * ac97);
int patch_ad1885(ac97_t * ac97);
int patch_ad1886(ac97_t * ac97);
int patch_ad1980(ac97_t * ac97);
+int patch_alc650(ac97_t * ac97);
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c
index c944f71d3fe2..140da1843066 100644
--- a/sound/pci/ali5451/ali5451.c
+++ b/sound/pci/ali5451/ali5451.c
@@ -233,6 +233,7 @@ struct snd_stru_ali {
unsigned long port;
unsigned char revision;
+ unsigned int hw_initialized: 1;
struct resource *res_port;
struct pci_dev *pci;
@@ -1965,7 +1966,8 @@ static void snd_ali_resume(struct pci_dev *dev)
static int snd_ali_free(ali_t * codec)
{
- snd_ali_disable_address_interrupt(codec);
+ if (codec->hw_initialized)
+ snd_ali_disable_address_interrupt(codec);
if (codec->irq >= 0) {
synchronize_irq(codec->irq);
free_irq(codec->irq, (void *)codec);
@@ -2036,13 +2038,11 @@ static int __devinit snd_ali_resources(ali_t *codec)
{
snd_ali_printk("resouces allocation ...\n");
if ((codec->res_port = request_region(codec->port, 0x100, "ALI 5451")) == NULL) {
- snd_ali_free(codec);
snd_printk("Unalbe to request io ports.\n");
return -EBUSY;
}
if (request_irq(codec->pci->irq, snd_ali_card_interrupt, SA_INTERRUPT|SA_SHIRQ, "ALI 5451", (void *)codec)) {
- snd_ali_free(codec);
snd_printk("Unable to request irq.\n");
return -EBUSY;
}
@@ -2112,6 +2112,7 @@ static int __devinit snd_ali_create(snd_card_t * card,
pci_set_master(pci);
if (snd_ali_resources(codec)) {
+ snd_ali_free(codec);
return -EBUSY;
}
@@ -2156,7 +2157,6 @@ static int __devinit snd_ali_create(snd_card_t * card,
if ((err = snd_ali_chip_init(codec)) < 0) {
snd_printk("ali create: chip init error.\n");
- snd_ali_free(codec);
return err;
}
@@ -2167,6 +2167,7 @@ static int __devinit snd_ali_create(snd_card_t * card,
#endif
snd_ali_enable_address_interrupt(codec);
+ codec->hw_initialized = 1;
*r_ali = codec;
snd_ali_printk("created.\n");
diff --git a/sound/pci/cs46xx/cs46xx.c b/sound/pci/cs46xx/cs46xx.c
index 618a844c4f4b..a2c05f2bf15f 100644
--- a/sound/pci/cs46xx/cs46xx.c
+++ b/sound/pci/cs46xx/cs46xx.c
@@ -110,6 +110,16 @@ static int __devinit snd_card_cs46xx_probe(struct pci_dev *pci,
snd_card_free(card);
return err;
}
+#ifdef CONFIG_SND_CS46XX_NEW_DSP
+ if ((err = snd_cs46xx_pcm_rear(chip,1, NULL)) < 0) {
+ snd_card_free(card);
+ return err;
+ }
+ if ((err = snd_cs46xx_pcm_iec958(chip,2,NULL)) < 0) {
+ snd_card_free(card);
+ return err;
+ }
+#endif
if ((err = snd_cs46xx_mixer(chip)) < 0) {
snd_card_free(card);
return err;
@@ -118,6 +128,12 @@ static int __devinit snd_card_cs46xx_probe(struct pci_dev *pci,
snd_card_free(card);
return err;
}
+ if ((err = snd_cs46xx_start_dsp(chip)) < 0) {
+ snd_card_free(card);
+ return err;
+ }
+
+
snd_cs46xx_gameport(chip);
strcpy(card->driver, "CS46xx");
@@ -132,6 +148,7 @@ static int __devinit snd_card_cs46xx_probe(struct pci_dev *pci,
snd_card_free(card);
return err;
}
+
pci_set_drvdata(pci, chip);
dev++;
return 0;
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c
index 466af9f8673f..efff0b7466d9 100644
--- a/sound/pci/cs46xx/cs46xx_lib.c
+++ b/sound/pci/cs46xx/cs46xx_lib.c
@@ -15,8 +15,8 @@
* TODO:
* - Secondary CODEC on some soundcards
* - SPDIF input support for other sample rates then 48khz
- * - Independent PCM channels for rear output
* - Posibility to mix the SPDIF output with analog sources.
+ * - PCM channels for Center and LFE on secondary codec
*
* NOTE: with CONFIG_SND_CS46XX_NEW_DSP unset uses old DSP image (which
* is default configuration), no SPDIF, no secondary codec, no
@@ -269,23 +269,35 @@ static void snd_cs46xx_ac97_write(ac97_t *ac97,
unsigned short val)
{
cs46xx_t *chip = snd_magic_cast(cs46xx_t, ac97->private_data, return);
+#ifndef CONFIG_SND_CS46XX_NEW_DSP
int val2 = 0;
+#endif
int codec_index = -1;
/* UGGLY: nr_ac97_codecs == 0 primery codec detection is in progress */
if (ac97 == chip->ac97[CS46XX_PRIMARY_CODEC_INDEX] || chip->nr_ac97_codecs == 0)
codec_index = CS46XX_PRIMARY_CODEC_INDEX;
- /* UGGLY: nr_ac97_codecs == 0 secondary codec detection is in progress */
+ /* UGGLY: nr_ac97_codecs == 1 secondary codec detection is in progress */
else if (ac97 == chip->ac97[CS46XX_SECONDARY_CODEC_INDEX] || chip->nr_ac97_codecs == 1)
codec_index = CS46XX_SECONDARY_CODEC_INDEX;
else
snd_assert(0,return);
- chip->active_ctrl(chip, 1);
+
+#ifndef CONFIG_SND_CS46XX_NEW_DSP
if (reg == AC97_CD)
val2 = snd_cs46xx_codec_read(chip, AC97_CD, codec_index);
+#endif
snd_cs46xx_codec_write(chip, reg, val, codec_index);
+#ifndef CONFIG_SND_CS46XX_NEW_DSP
+ /* Benny: I've not found *one* soundcard where
+ this code below could do any sense, and
+ with the HW mixering it's anyway broken, with
+ more then 1 PCM stream the amplifier will not
+ be turned off by unmuting CD channel. So just
+ lets skip it.
+ */
/*
* Adjust power if the mixer is selected/deselected according
@@ -323,6 +335,7 @@ static void snd_cs46xx_ac97_write(ac97_t *ac97,
}
chip->active_ctrl(chip, -1);
+#endif
}
@@ -432,9 +445,33 @@ static void snd_cs46xx_reset(cs46xx_t *chip)
snd_cs46xx_poke(chip, BA1_FRMT, 0xadf);
}
+static int cs46xx_wait_for_fifo(cs46xx_t * chip,int retry_timeout)
+{
+ u32 i, status;
+ /*
+ * Make sure the previous FIFO write operation has completed.
+ */
+ for(i = 0; i < 50; i++){
+ status = snd_cs46xx_peekBA0(chip, BA0_SERBST);
+
+ if( !(status & SERBST_WBSY) )
+ break;
+
+ mdelay(retry_timeout);
+ }
+
+ if(status & SERBST_WBSY) {
+ snd_printk( KERN_ERR "cs46xx: failure waiting for FIFO command to complete\n");
+
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static void snd_cs46xx_clear_serial_FIFOs(cs46xx_t *chip)
{
- int idx, loop, powerdown = 0;
+ int idx, powerdown = 0;
unsigned int tmp;
/*
@@ -451,24 +488,23 @@ static void snd_cs46xx_clear_serial_FIFOs(cs46xx_t *chip)
* We want to clear out the serial port FIFOs so we don't end up playing
* whatever random garbage happens to be in them. We fill the sample FIFOS
* with zero (silence).
- */
+ */
snd_cs46xx_pokeBA0(chip, BA0_SERBWP, 0);
/*
* Fill all 256 sample FIFO locations.
*/
- for (idx = 0; idx < 256; idx++) {
+ for (idx = 0; idx < 0xFF; idx++) {
/*
* Make sure the previous FIFO write operation has completed.
*/
- for (loop = 0; loop < 5; loop++) {
- udelay(50);
- if (!(snd_cs46xx_peekBA0(chip, BA0_SERBST) & SERBST_WBSY))
- break;
- }
- if (snd_cs46xx_peekBA0(chip, BA0_SERBST) & SERBST_WBSY) {
+ if (cs46xx_wait_for_fifo(chip,1)) {
+ snd_printdd ("failed waiting for FIFO at addr (%02X)\n",idx);
+
if (powerdown)
snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp);
+
+ break;
}
/*
* Write the serial port FIFO index.
@@ -692,6 +728,8 @@ static int snd_cs46xx_playback_transfer(snd_pcm_substream_t *substream,
snd_pcm_runtime_t *runtime = substream->runtime;
snd_pcm_sframes_t diff;
cs46xx_pcm_t * cpcm;
+ int buffer_size = runtime->period_size * CS46XX_FRAGS * 4;
+
cpcm = snd_magic_cast(cs46xx_pcm_t, substream->runtime->private_data, return -ENXIO);
diff = runtime->control->appl_ptr - cpcm->appl_ptr;
@@ -702,11 +740,11 @@ static int snd_cs46xx_playback_transfer(snd_pcm_substream_t *substream,
}
cpcm->sw_ready += frames << cpcm->shift;
cpcm->appl_ptr = runtime->control->appl_ptr + frames;
- while (cpcm->hw_ready < CS46XX_BUFFER_SIZE &&
+ while (cpcm->hw_ready < buffer_size &&
cpcm->sw_ready > 0) {
- size_t hw_to_end = CS46XX_BUFFER_SIZE - cpcm->hw_data;
+ size_t hw_to_end = buffer_size - cpcm->hw_data;
size_t sw_to_end = cpcm->sw_bufsize - cpcm->sw_data;
- size_t bytes = CS46XX_BUFFER_SIZE - cpcm->hw_ready;
+ size_t bytes = buffer_size - cpcm->hw_ready;
if (cpcm->sw_ready < bytes)
bytes = cpcm->sw_ready;
if (hw_to_end < bytes)
@@ -717,7 +755,7 @@ static int snd_cs46xx_playback_transfer(snd_pcm_substream_t *substream,
runtime->dma_area + cpcm->sw_data,
bytes);
cpcm->hw_data += bytes;
- if (cpcm->hw_data == CS46XX_BUFFER_SIZE)
+ if (cpcm->hw_data == buffer_size)
cpcm->hw_data = 0;
cpcm->sw_data += bytes;
if (cpcm->sw_data == cpcm->sw_bufsize)
@@ -734,6 +772,7 @@ 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_sframes_t diff = runtime->control->appl_ptr - chip->capt.appl_ptr;
+ int buffer_size = runtime->period_size * CS46XX_FRAGS * 4;
if (diff) {
if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2))
diff += runtime->boundary;
@@ -743,7 +782,7 @@ static int snd_cs46xx_capture_transfer(snd_pcm_substream_t *substream,
chip->capt.appl_ptr = runtime->control->appl_ptr + frames;
while (chip->capt.hw_ready > 0 &&
chip->capt.sw_ready < chip->capt.sw_bufsize) {
- size_t hw_to_end = CS46XX_BUFFER_SIZE - chip->capt.hw_data;
+ size_t hw_to_end = buffer_size - chip->capt.hw_data;
size_t sw_to_end = chip->capt.sw_bufsize - chip->capt.sw_data;
size_t bytes = chip->capt.sw_bufsize - chip->capt.sw_ready;
if (chip->capt.hw_ready < bytes)
@@ -756,7 +795,7 @@ static int snd_cs46xx_capture_transfer(snd_pcm_substream_t *substream,
chip->capt.hw_area + chip->capt.hw_data,
bytes);
chip->capt.hw_data += bytes;
- if (chip->capt.hw_data == CS46XX_BUFFER_SIZE)
+ if (chip->capt.hw_data == buffer_size)
chip->capt.hw_data = 0;
chip->capt.sw_data += bytes;
if (chip->capt.sw_data == chip->capt.sw_bufsize)
@@ -789,6 +828,7 @@ static snd_pcm_uframes_t snd_cs46xx_playback_indirect_pointer(snd_pcm_substream_
size_t ptr;
cs46xx_pcm_t *cpcm = snd_magic_cast(cs46xx_pcm_t, substream->runtime->private_data, return -ENXIO);
ssize_t bytes;
+ int buffer_size = substream->runtime->period_size * CS46XX_FRAGS * 4;
#ifdef CONFIG_SND_CS46XX_NEW_DSP
snd_assert (cpcm->pcm_channel,return -ENXIO);
@@ -801,7 +841,7 @@ static snd_pcm_uframes_t snd_cs46xx_playback_indirect_pointer(snd_pcm_substream_
bytes = ptr - cpcm->hw_io;
if (bytes < 0)
- bytes += CS46XX_BUFFER_SIZE;
+ bytes += buffer_size;
cpcm->hw_io = ptr;
cpcm->hw_ready -= bytes;
cpcm->sw_io += bytes;
@@ -823,8 +863,10 @@ static snd_pcm_uframes_t snd_cs46xx_capture_indirect_pointer(snd_pcm_substream_t
cs46xx_t *chip = snd_pcm_substream_chip(substream);
size_t ptr = snd_cs46xx_peek(chip, BA1_CBA) - chip->capt.hw_addr;
ssize_t bytes = ptr - chip->capt.hw_io;
+ int buffer_size = substream->runtime->period_size * CS46XX_FRAGS * 4;
+
if (bytes < 0)
- bytes += CS46XX_BUFFER_SIZE;
+ bytes += buffer_size;
chip->capt.hw_io = ptr;
chip->capt.hw_ready += bytes;
chip->capt.sw_io += bytes;
@@ -910,7 +952,9 @@ static int snd_cs46xx_playback_trigger(snd_pcm_substream_t * substream,
snd_cs46xx_playback_transfer(substream, 0);
/* raise playback volume */
- snd_cs46xx_poke(chip, (cpcm->pcm_channel->pcm_reader_scb->address + 0xE) << 2, 0x80008000);
+ cs46xx_dsp_scb_set_volume (chip,cpcm->pcm_channel->pcm_reader_scb,
+ chip->dsp_spos_instance->dac_volume_right,
+ chip->dsp_spos_instance->dac_volume_left);
#else
if (substream->runtime->periods != CS46XX_FRAGS)
snd_cs46xx_playback_transfer(substream, 0);
@@ -924,8 +968,9 @@ static int snd_cs46xx_playback_trigger(snd_pcm_substream_t * substream,
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
#ifdef CONFIG_SND_CS46XX_NEW_DSP
- /* mute channel */
- snd_cs46xx_poke(chip, (cpcm->pcm_channel->pcm_reader_scb->address + 0xE) << 2, 0xffffffff);
+ /* mute channel */
+ cs46xx_dsp_scb_set_volume (chip,cpcm->pcm_channel->pcm_reader_scb,0,0);
+
if (!cpcm->pcm_channel->unlinked)
cs46xx_dsp_pcm_unlink(chip,cpcm->pcm_channel);
#else
@@ -978,6 +1023,44 @@ static int snd_cs46xx_capture_trigger(snd_pcm_substream_t * substream,
return result;
}
+static int _cs46xx_adjust_sample_rate (cs46xx_t *chip, cs46xx_pcm_t *cpcm,
+ int sample_rate)
+{
+ /* if this is the only PCMReaderSCB child under current
+ SrcTask then there no need to re-create pcm-channel */
+ if ( cpcm->pcm_channel->src_scb->ref_count == 1 &&
+ cpcm->pcm_channel->sample_rate != sample_rate &&
+ /* never set a 0 khz sample rate */
+ sample_rate) {
+ /* sample rate not set or we can reuse
+ the same SRC*/
+ cs46xx_dsp_set_src_sample_rate (chip,cpcm->pcm_channel->src_scb,sample_rate);
+ cpcm->pcm_channel->sample_rate = sample_rate;
+ }
+
+ /* if there is more then 1 PCMReaderSCB child's under current
+ SrcTask then we must recreate channel */
+ if (cpcm->pcm_channel->sample_rate != sample_rate &&
+ cpcm->pcm_channel->src_scb->ref_count != 1 &&
+ /* never set a 0 khz sample rate */
+ sample_rate) {
+ int unlinked = cpcm->pcm_channel->unlinked;
+ cs46xx_dsp_destroy_pcm_channel (chip,cpcm->pcm_channel);
+
+ if ( (cpcm->pcm_channel = cs46xx_dsp_create_pcm_channel (chip, sample_rate, cpcm,
+ cpcm->hw_addr,
+ cpcm->pcm_channel->pcm_channel_id)) == NULL) {
+ snd_printk(KERN_ERR "cs46xx: failed to re-create virtual PCM channel\n");
+ up (&chip->spos_mutex);
+ return -ENXIO;
+ }
+
+ if (!unlinked) cs46xx_dsp_pcm_link (chip,cpcm->pcm_channel);
+ cpcm->pcm_channel->sample_rate = sample_rate;
+ }
+
+ return 0;
+}
static int snd_cs46xx_playback_hw_params(snd_pcm_substream_t * substream,
snd_pcm_hw_params_t * hw_params)
{
@@ -985,27 +1068,88 @@ static int snd_cs46xx_playback_hw_params(snd_pcm_substream_t * substream,
snd_pcm_runtime_t *runtime = substream->runtime;
cs46xx_pcm_t *cpcm;
int err;
-
+ cs46xx_t *chip = snd_pcm_substream_chip(substream);
+ int sample_rate = params_rate(hw_params);
+ int period_size = params_period_size(hw_params);
cpcm = snd_magic_cast(cs46xx_pcm_t, runtime->private_data, return -ENXIO);
+#ifdef CONFIG_SND_CS46XX_NEW_DSP
+ down (&chip->spos_mutex);
+
+ snd_assert (cpcm->pcm_channel != NULL);
+
+ /* if IEC958 is opened in AC3 mode dont adjust SRCTask is not
+ used so dont adjust sample rate */
+ if (cpcm->pcm_channel->pcm_channel_id != DSP_IEC958_CHANNEL ||
+ !(chip->dsp_spos_instance->spdif_status_out & DSP_SPDIF_STATUS_AC3_MODE)) {
+ if (_cs46xx_adjust_sample_rate (chip,cpcm,sample_rate)) {
+ return -ENXIO;
+ }
+ }
+
+ if (cs46xx_dsp_pcm_channel_set_period (chip,cpcm->pcm_channel,period_size * 4)) {
+ up (&chip->spos_mutex);
+ return -EINVAL;
+ }
+ snd_printdd ("period_size (%d), periods (%d)\n",
+ period_size, params_periods(hw_params));
+#endif
+
if (params_periods(hw_params) == CS46XX_FRAGS) {
if (runtime->dma_area != cpcm->hw_area)
snd_pcm_lib_free_pages(substream);
runtime->dma_area = cpcm->hw_area;
runtime->dma_addr = cpcm->hw_addr;
runtime->dma_bytes = cpcm->hw_size;
+
+
+#ifdef CONFIG_SND_CS46XX_NEW_DSP
+ if (cpcm->pcm_channel->pcm_channel_id == DSP_PCM_MAIN_CHANNEL) {
+ substream->ops = &snd_cs46xx_playback_ops;
+ } else if (cpcm->pcm_channel->pcm_channel_id == DSP_PCM_REAR_CHANNEL) {
+ substream->ops = &snd_cs46xx_playback_rear_ops;
+ } else if (cpcm->pcm_channel->pcm_channel_id == DSP_IEC958_CHANNEL) {
+ substream->ops = &snd_cs46xx_playback_iec958_ops;
+ } else {
+ snd_assert(0);
+ }
+#else
substream->ops = &snd_cs46xx_playback_ops;
+#endif
+
} else {
if (runtime->dma_area == cpcm->hw_area) {
runtime->dma_area = NULL;
runtime->dma_addr = 0;
runtime->dma_bytes = 0;
}
- if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
+ if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0) {
+#ifdef CONFIG_SND_CS46XX_NEW_DSP
+ up (&chip->spos_mutex);
+#endif
return err;
+ }
+
+#ifdef CONFIG_SND_CS46XX_NEW_DSP
+ if (cpcm->pcm_channel->pcm_channel_id == DSP_PCM_MAIN_CHANNEL) {
+ substream->ops = &snd_cs46xx_playback_indirect_ops;
+ } else if (cpcm->pcm_channel->pcm_channel_id == DSP_PCM_REAR_CHANNEL) {
+ substream->ops = &snd_cs46xx_playback_indirect_rear_ops;
+ } else if (cpcm->pcm_channel->pcm_channel_id == DSP_IEC958_CHANNEL) {
+ substream->ops = &snd_cs46xx_playback_indirect_iec958_ops;
+ } else {
+ snd_assert(0);
+ }
+#else
substream->ops = &snd_cs46xx_playback_indirect_ops;
+#endif
+
}
+#ifdef CONFIG_SND_CS46XX_NEW_DSP
+ up (&chip->spos_mutex);
+#endif
+
return 0;
}
@@ -1038,35 +1182,10 @@ static int snd_cs46xx_playback_prepare(snd_pcm_substream_t * substream)
cpcm = snd_magic_cast(cs46xx_pcm_t, runtime->private_data, return -ENXIO);
#ifdef CONFIG_SND_CS46XX_NEW_DSP
- down (&chip->spos_mutex);
-
- if ( cpcm->pcm_channel->src_scb->ref_count == 1 &&
- cpcm->pcm_channel->sample_rate != runtime->rate) {
- /* sample rate not set or we can reuse
- the same SRC*/
-
- cs46xx_dsp_set_src_sample_rate (chip,cpcm->pcm_channel->src_scb,runtime->rate);
- cpcm->pcm_channel->sample_rate = runtime->rate;
- }
-
- if (cpcm->pcm_channel->sample_rate != runtime->rate &&
- cpcm->pcm_channel->src_scb->ref_count != 1) {
- int unlinked = cpcm->pcm_channel->unlinked;
- cs46xx_dsp_destroy_pcm_channel (chip,cpcm->pcm_channel);
-
- if ( (cpcm->pcm_channel = cs46xx_dsp_create_pcm_channel (chip, runtime->rate, cpcm, cpcm->hw_addr)) == NULL) {
- snd_printk(KERN_ERR "cs46xx: failed to re-create virtual PCM channel\n");
- up (&chip->spos_mutex);
- return -ENXIO;
- }
-
- if (!unlinked) cs46xx_dsp_pcm_link (chip,cpcm->pcm_channel);
- cpcm->pcm_channel->sample_rate = runtime->rate;
- }
+ snd_assert (cpcm->pcm_channel != NULL, return -ENXIO);
pfie = snd_cs46xx_peek(chip, (cpcm->pcm_channel->pcm_reader_scb->address + 1) << 2 );
pfie &= ~0x0000f03f;
- up (&chip->spos_mutex);
#else
/* old dsp */
pfie = snd_cs46xx_peek(chip, BA1_PFIE);
@@ -1101,6 +1220,7 @@ static int snd_cs46xx_playback_prepare(snd_pcm_substream_t * substream)
cpcm->appl_ptr = 0;
#ifdef CONFIG_SND_CS46XX_NEW_DSP
+
tmp = snd_cs46xx_peek(chip, (cpcm->pcm_channel->pcm_reader_scb->address) << 2);
tmp &= ~0x000003ff;
tmp |= (4 << cpcm->shift) - 1;
@@ -1128,7 +1248,13 @@ static int snd_cs46xx_capture_hw_params(snd_pcm_substream_t * substream,
cs46xx_t *chip = snd_pcm_substream_chip(substream);
snd_pcm_runtime_t *runtime = substream->runtime;
int err;
+ int period_size = params_period_size(hw_params);
+
+#ifdef CONFIG_SND_CS46XX_NEW_DSP
+ snd_printdd ("capture period size (%d)\n",period_size);
+ cs46xx_dsp_pcm_ostream_set_period (chip,period_size * 4);
+#endif
if (runtime->periods == CS46XX_FRAGS) {
if (runtime->dma_area != chip->capt.hw_area)
snd_pcm_lib_free_pages(substream);
@@ -1285,8 +1411,8 @@ static snd_pcm_hardware_t snd_cs46xx_playback =
.channels_min = 1,
.channels_max = 2,
.buffer_bytes_max = (256 * 1024),
- .period_bytes_min = CS46XX_PERIOD_SIZE,
- .period_bytes_max = CS46XX_PERIOD_SIZE,
+ .period_bytes_min = CS46XX_MIN_PERIOD_SIZE,
+ .period_bytes_max = CS46XX_MAX_PERIOD_SIZE,
.periods_min = CS46XX_FRAGS,
.periods_max = 1024,
.fifo_size = 0,
@@ -1305,13 +1431,23 @@ static snd_pcm_hardware_t snd_cs46xx_capture =
.channels_min = 2,
.channels_max = 2,
.buffer_bytes_max = (256 * 1024),
- .period_bytes_min = CS46XX_PERIOD_SIZE,
- .period_bytes_max = CS46XX_PERIOD_SIZE,
+ .period_bytes_min = CS46XX_MIN_PERIOD_SIZE,
+ .period_bytes_max = CS46XX_MAX_PERIOD_SIZE,
.periods_min = CS46XX_FRAGS,
.periods_max = 1024,
.fifo_size = 0,
};
+static unsigned int period_sizes[] = { 8, 16, 32, 64, 128, 256, 512 };
+
+#define PERIOD_SIZES sizeof(period_sizes) / sizeof(period_sizes[0])
+
+static snd_pcm_hw_constraint_list_t hw_constraints_period_sizes = {
+ .count = PERIOD_SIZES,
+ .list = period_sizes,
+ .mask = 0
+};
+
static void snd_cs46xx_pcm_free_substream(snd_pcm_runtime_t *runtime)
{
cs46xx_pcm_t * cpcm = snd_magic_cast(cs46xx_pcm_t, runtime->private_data, return);
@@ -1320,7 +1456,7 @@ static void snd_cs46xx_pcm_free_substream(snd_pcm_runtime_t *runtime)
snd_magic_kfree(cpcm);
}
-static int snd_cs46xx_playback_open(snd_pcm_substream_t * substream)
+static int _cs46xx_playback_open_channel (snd_pcm_substream_t * substream,int pcm_channel_id)
{
cs46xx_t *chip = snd_pcm_substream_chip(substream);
cs46xx_pcm_t * cpcm;
@@ -1342,7 +1478,7 @@ static int snd_cs46xx_playback_open(snd_pcm_substream_t * substream)
cpcm->substream = substream;
#ifdef CONFIG_SND_CS46XX_NEW_DSP
down (&chip->spos_mutex);
- cpcm->pcm_channel = cs46xx_dsp_create_pcm_channel (chip, runtime->rate, cpcm, cpcm->hw_addr);
+ cpcm->pcm_channel = cs46xx_dsp_create_pcm_channel (chip, runtime->rate, cpcm, cpcm->hw_addr,pcm_channel_id);
if (cpcm->pcm_channel == NULL) {
snd_printk(KERN_ERR "cs46xx: failed to create virtual PCM channel\n");
@@ -1352,6 +1488,8 @@ static int snd_cs46xx_playback_open(snd_pcm_substream_t * substream)
return -ENOMEM;
}
+ snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
+ &hw_constraints_period_sizes);
up (&chip->spos_mutex);
#else
chip->playback_pcm = cpcm; /* HACK */
@@ -1365,6 +1503,52 @@ static int snd_cs46xx_playback_open(snd_pcm_substream_t * substream)
return 0;
}
+static int snd_cs46xx_playback_open(snd_pcm_substream_t * substream)
+{
+ snd_printdd("open front channel\n");
+ return _cs46xx_playback_open_channel(substream,DSP_PCM_MAIN_CHANNEL);
+}
+
+#ifdef CONFIG_SND_CS46XX_NEW_DSP
+static int snd_cs46xx_playback_open_rear(snd_pcm_substream_t * substream)
+{
+ snd_printdd("open rear channel\n");
+
+ return _cs46xx_playback_open_channel(substream,DSP_PCM_REAR_CHANNEL);
+}
+
+static int snd_cs46xx_playback_open_iec958(snd_pcm_substream_t * substream)
+{
+ cs46xx_t *chip = snd_pcm_substream_chip(substream);
+
+ snd_printdd("open raw iec958 channel\n");
+
+ down (&chip->spos_mutex);
+ cs46xx_iec958_pre_open (chip);
+ up (&chip->spos_mutex);
+
+ return _cs46xx_playback_open_channel(substream,DSP_IEC958_CHANNEL);
+}
+
+static int snd_cs46xx_playback_close(snd_pcm_substream_t * substream);
+
+static int snd_cs46xx_playback_close_iec958(snd_pcm_substream_t * substream)
+{
+ int err;
+ cs46xx_t *chip = snd_pcm_substream_chip(substream);
+
+ snd_printdd("close raw iec958 channel\n");
+
+ err = snd_cs46xx_playback_close(substream);
+
+ down (&chip->spos_mutex);
+ cs46xx_iec958_post_close (chip);
+ up (&chip->spos_mutex);
+
+ return err;
+}
+#endif
+
static int snd_cs46xx_capture_open(snd_pcm_substream_t * substream)
{
cs46xx_t *chip = snd_pcm_substream_chip(substream);
@@ -1375,11 +1559,15 @@ static int snd_cs46xx_capture_open(snd_pcm_substream_t * substream)
substream->runtime->hw = snd_cs46xx_capture;
if (chip->accept_valid)
- substream->runtime->hw.info |= SNDRV_PCM_INFO_MMAP_VALID;
+ substream->runtime->hw.info |= SNDRV_PCM_INFO_MMAP_VALID;
chip->active_ctrl(chip, 1);
chip->amplifier_ctrl(chip, 1);
+#ifdef CONFIG_SND_CS46XX_NEW_DSP
+ snd_pcm_hw_constraint_list(substream->runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
+ &hw_constraints_period_sizes);
+#endif
return 0;
}
@@ -1422,6 +1610,55 @@ static int snd_cs46xx_capture_close(snd_pcm_substream_t * substream)
return 0;
}
+#ifdef CONFIG_SND_CS46XX_NEW_DSP
+snd_pcm_ops_t snd_cs46xx_playback_rear_ops = {
+ .open = snd_cs46xx_playback_open_rear,
+ .close = snd_cs46xx_playback_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = snd_cs46xx_playback_hw_params,
+ .hw_free = snd_cs46xx_playback_hw_free,
+ .prepare = snd_cs46xx_playback_prepare,
+ .trigger = snd_cs46xx_playback_trigger,
+ .pointer = snd_cs46xx_playback_direct_pointer,
+};
+
+snd_pcm_ops_t snd_cs46xx_playback_indirect_rear_ops = {
+ .open = snd_cs46xx_playback_open_rear,
+ .close = snd_cs46xx_playback_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = snd_cs46xx_playback_hw_params,
+ .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,
+};
+
+snd_pcm_ops_t snd_cs46xx_playback_iec958_ops = {
+ .open = snd_cs46xx_playback_open_iec958,
+ .close = snd_cs46xx_playback_close_iec958,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = snd_cs46xx_playback_hw_params,
+ .hw_free = snd_cs46xx_playback_hw_free,
+ .prepare = snd_cs46xx_playback_prepare,
+ .trigger = snd_cs46xx_playback_trigger,
+ .pointer = snd_cs46xx_playback_direct_pointer,
+};
+
+snd_pcm_ops_t snd_cs46xx_playback_indirect_iec958_ops = {
+ .open = snd_cs46xx_playback_open_iec958,
+ .close = snd_cs46xx_playback_close_iec958,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = snd_cs46xx_playback_hw_params,
+ .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,
+};
+
+#endif
+
snd_pcm_ops_t snd_cs46xx_playback_ops = {
.open = snd_cs46xx_playback_open,
.close = snd_cs46xx_playback_close,
@@ -1476,6 +1713,20 @@ static void snd_cs46xx_pcm_free(snd_pcm_t *pcm)
}
#ifdef CONFIG_SND_CS46XX_NEW_DSP
+static void snd_cs46xx_pcm_rear_free(snd_pcm_t *pcm)
+{
+ cs46xx_t *chip = snd_magic_cast(cs46xx_t, pcm->private_data, return);
+ chip->pcm_rear = NULL;
+ snd_pcm_lib_preallocate_free_for_all(pcm);
+}
+
+static void snd_cs46xx_pcm_iec958_free(snd_pcm_t *pcm)
+{
+ cs46xx_t *chip = snd_magic_cast(cs46xx_t, pcm->private_data, return);
+ chip->pcm_iec958 = NULL;
+ snd_pcm_lib_preallocate_free_for_all(pcm);
+}
+
#define MAX_PLAYBACK_CHANNELS (DSP_MAX_PCM_CHANNELS - 1)
#else
#define MAX_PLAYBACK_CHANNELS 1
@@ -1490,6 +1741,7 @@ int __devinit snd_cs46xx_pcm(cs46xx_t *chip, int device, snd_pcm_t ** rpcm)
*rpcm = NULL;
if ((err = snd_pcm_new(chip->card, "CS46xx", device, MAX_PLAYBACK_CHANNELS, 1, &pcm)) < 0)
return err;
+
pcm->private_data = chip;
pcm->private_free = snd_cs46xx_pcm_free;
@@ -1505,13 +1757,74 @@ int __devinit snd_cs46xx_pcm(cs46xx_t *chip, int device, snd_pcm_t ** rpcm)
if (rpcm)
*rpcm = pcm;
+
+ return 0;
+}
+
+
+#ifdef CONFIG_SND_CS46XX_NEW_DSP
+int __devinit snd_cs46xx_pcm_rear(cs46xx_t *chip, int device, snd_pcm_t ** rpcm)
+{
+ snd_pcm_t *pcm;
+ int err;
+
+ if (rpcm)
+ *rpcm = NULL;
+
+ if ((err = snd_pcm_new(chip->card, "CS46xx - Rear", device, MAX_PLAYBACK_CHANNELS, 0, &pcm)) < 0)
+ return err;
+
+ pcm->private_data = chip;
+ pcm->private_free = snd_cs46xx_pcm_rear_free;
+
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cs46xx_playback_rear_ops);
+
+ /* global setup */
+ pcm->info_flags = 0;
+ strcpy(pcm->name, "CS46xx - Rear");
+ chip->pcm_rear = pcm;
+
+ snd_pcm_lib_preallocate_pci_pages_for_all(chip->pci, pcm, 64*1024, 256*1024);
+
+ if (rpcm)
+ *rpcm = pcm;
+
return 0;
}
+int __devinit snd_cs46xx_pcm_iec958(cs46xx_t *chip, int device, snd_pcm_t ** rpcm)
+{
+ snd_pcm_t *pcm;
+ int err;
+
+ if (rpcm)
+ *rpcm = NULL;
+
+ if ((err = snd_pcm_new(chip->card, "CS46xx - IEC958", device, 1, 0, &pcm)) < 0)
+ return err;
+
+ pcm->private_data = chip;
+ pcm->private_free = snd_cs46xx_pcm_iec958_free;
+
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cs46xx_playback_iec958_ops);
+
+ /* global setup */
+ pcm->info_flags = 0;
+ strcpy(pcm->name, "CS46xx - IEC958");
+ chip->pcm_rear = pcm;
+
+ snd_pcm_lib_preallocate_pci_pages_for_all(chip->pci, pcm, 64*1024, 256*1024);
+
+ if (rpcm)
+ *rpcm = pcm;
+
+ return 0;
+}
+#endif
+
/*
* Mixer routines
*/
-
static void snd_cs46xx_mixer_free_ac97(ac97_t *ac97)
{
cs46xx_t *chip = snd_magic_cast(cs46xx_t, ac97->private_data, return);
@@ -1534,7 +1847,7 @@ static int snd_cs46xx_vol_info(snd_kcontrol_t *kcontrol,
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 32767;
+ uinfo->value.integer.max = 0x7fff;
return 0;
}
@@ -1556,26 +1869,9 @@ static int snd_cs46xx_vol_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *
(0xffff - ucontrol->value.integer.value[1]));
unsigned int old = snd_cs46xx_peek(chip, reg);
int change = (old != val);
+
if (change) {
snd_cs46xx_poke(chip, reg, val);
-#ifdef CONFIG_SND_CS46XX_NEW_DSP
- /* NOTE: this updates the current left and right volume
- that should be automatically updated by the DSP and
- not touched by the host. But for some strange reason
- the DSP only updates the right channel volume, so with
- this dirty hack we force updating the right and left
- channel volume.
- */
- snd_cs46xx_poke(chip, reg + 4, val);
-
- /* shadow the SPDIF input volume */
- if (reg == (ASYNCRX_SCB_ADDR + 0xE) << 2) {
- /* FIXME: I known this is uggly ...
- any other suggestion ?
- */
- chip->dsp_spos_instance->spdif_input_volume = val;
- }
-#endif
}
return change;
@@ -1583,6 +1879,57 @@ static int snd_cs46xx_vol_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *
#ifdef CONFIG_SND_CS46XX_NEW_DSP
+static int snd_cs46xx_vol_dac_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+ cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
+
+ ucontrol->value.integer.value[0] = chip->dsp_spos_instance->dac_volume_right;
+ ucontrol->value.integer.value[1] = chip->dsp_spos_instance->dac_volume_left;
+
+ return 0;
+}
+
+static int snd_cs46xx_vol_dac_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+ cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
+ int change = 0;
+
+ if (chip->dsp_spos_instance->dac_volume_right != ucontrol->value.integer.value[0] ||
+ chip->dsp_spos_instance->dac_volume_left != ucontrol->value.integer.value[1]) {
+ cs46xx_dsp_set_dac_volume(chip,
+ ucontrol->value.integer.value[0],
+ ucontrol->value.integer.value[1]);
+ change = 1;
+ }
+
+ return change;
+}
+
+static int snd_cs46xx_vol_iec958_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+ cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
+
+ ucontrol->value.integer.value[0] = chip->dsp_spos_instance->spdif_input_volume_right;
+ ucontrol->value.integer.value[1] = chip->dsp_spos_instance->spdif_input_volume_left;
+ return 0;
+}
+
+static int snd_cs46xx_vol_iec958_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+ cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
+ int change = 0;
+
+ if (chip->dsp_spos_instance->spdif_input_volume_right != ucontrol->value.integer.value[0] ||
+ chip->dsp_spos_instance->spdif_input_volume_left != ucontrol->value.integer.value[1]) {
+ cs46xx_dsp_set_iec958_volume (chip,
+ ucontrol->value.integer.value[0],
+ ucontrol->value.integer.value[1]);
+ change = 1;
+ }
+
+ return change;
+}
+
static int snd_mixer_boolean_info(snd_kcontrol_t *kcontrol,
snd_ctl_elem_info_t *uinfo)
{
@@ -1600,7 +1947,7 @@ static int snd_cs46xx_iec958_get(snd_kcontrol_t *kcontrol,
int reg = kcontrol->private_value;
if (reg == CS46XX_MIXER_SPDIF_OUTPUT_ELEMENT)
- ucontrol->value.integer.value[0] = chip->dsp_spos_instance->spdif_status_out;
+ ucontrol->value.integer.value[0] = (chip->dsp_spos_instance->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED);
else
ucontrol->value.integer.value[0] = chip->dsp_spos_instance->spdif_status_in;
@@ -1615,13 +1962,15 @@ static int snd_cs46xx_iec958_put(snd_kcontrol_t *kcontrol,
switch (kcontrol->private_value) {
case CS46XX_MIXER_SPDIF_OUTPUT_ELEMENT:
- change = chip->dsp_spos_instance->spdif_status_out;
+ down (&chip->spos_mutex);
+ change = (chip->dsp_spos_instance->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED);
if (ucontrol->value.integer.value[0] && !change)
cs46xx_dsp_enable_spdif_out(chip);
else if (change && !ucontrol->value.integer.value[0])
cs46xx_dsp_disable_spdif_out(chip);
- res = (change != chip->dsp_spos_instance->spdif_status_out);
+ res = (change != (chip->dsp_spos_instance->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED));
+ up (&chip->spos_mutex);
break;
case CS46XX_MIXER_SPDIF_INPUT_ELEMENT:
change = chip->dsp_spos_instance->spdif_status_in;
@@ -1686,6 +2035,35 @@ static int snd_cs46xx_pcm_capture_get(snd_kcontrol_t *kcontrol,
return 0;
}
+static int snd_cs46xx_iec958_ac3_mode_get(snd_kcontrol_t *kcontrol,
+ snd_ctl_elem_value_t *ucontrol)
+{
+ cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
+ dsp_spos_instance_t * ins = chip->dsp_spos_instance;
+
+ if (!ins->spdif_status_out & DSP_SPDIF_STATUS_AC3_MODE)
+ ucontrol->value.integer.value[0] = 1;
+ else
+ ucontrol->value.integer.value[0] = 0;
+
+ return 0;
+}
+
+static int snd_cs46xx_iec958_ac3_mode_put(snd_kcontrol_t *kcontrol,
+ snd_ctl_elem_value_t *ucontrol)
+{
+ cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
+ dsp_spos_instance_t * ins = chip->dsp_spos_instance;
+ int old = ins->spdif_status_out;
+
+ if (ucontrol->value.integer.value[0])
+ ins->spdif_status_out |= DSP_SPDIF_STATUS_AC3_MODE;
+ else
+ ins->spdif_status_out &= ~DSP_SPDIF_STATUS_AC3_MODE;
+
+ return (old != ins->spdif_status_out);
+}
+
static int snd_cs46xx_pcm_capture_put(snd_kcontrol_t *kcontrol,
snd_ctl_elem_value_t *ucontrol)
{
@@ -1720,7 +2098,7 @@ static int snd_herc_spdif_select_get(snd_kcontrol_t *kcontrol,
}
/*
- * Game Theatre XP card - EGPIO[0] is used to select SDPIF input optical or coaxial.
+ * Game Theatre XP card - EGPIO[0] is used to select SPDIF input optical or coaxial.
*/
static int snd_herc_spdif_select_put(snd_kcontrol_t *kcontrol,
snd_ctl_elem_value_t *ucontrol)
@@ -1818,13 +2196,13 @@ static snd_kcontrol_new_t snd_cs46xx_controls[] __devinitdata = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "DAC Volume",
.info = snd_cs46xx_vol_info,
+#ifndef CONFIG_SND_CS46XX_NEW_DSP
.get = snd_cs46xx_vol_get,
.put = snd_cs46xx_vol_put,
-
-#ifndef CONFIG_SND_CS46XX_NEW_DSP
.private_value = BA1_PVOL,
#else
- .private_value = (MASTERMIX_SCB_ADDR + 0xE) << 2,
+ .get = snd_cs46xx_vol_dac_get,
+ .put = snd_cs46xx_vol_dac_put,
#endif
},
@@ -1865,6 +2243,13 @@ static snd_kcontrol_new_t snd_cs46xx_controls[] __devinitdata = {
},
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "IEC 958 AC3 Mode Switch",
+ .info = snd_mixer_boolean_info,
+ .get = snd_cs46xx_iec958_ac3_mode_get,
+ .put = snd_cs46xx_iec958_ac3_mode_put,
+},
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "IEC 958 Input Switch",
.info = snd_mixer_boolean_info,
.get = snd_cs46xx_iec958_get,
@@ -1875,8 +2260,8 @@ static snd_kcontrol_new_t snd_cs46xx_controls[] __devinitdata = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "IEC 958 Input Volume",
.info = snd_cs46xx_vol_info,
- .get = snd_cs46xx_vol_get,
- .put = snd_cs46xx_vol_put,
+ .get = snd_cs46xx_vol_iec958_get,
+ .put = snd_cs46xx_vol_iec958_put,
.private_value = (ASYNCRX_SCB_ADDR + 0xE) << 2,
},
#endif
@@ -1927,6 +2312,48 @@ static snd_kcontrol_new_t snd_hercules_controls[] __devinitdata = {
.put = snd_herc_spdif_select_put,
},
};
+
+
+static void snd_cs46xx_sec_codec_reset (ac97_t * ac97)
+{
+ signed long end_time;
+ int err;
+
+ /* reset to defaults */
+ snd_ac97_write(ac97, AC97_RESET, 0);
+
+ /* set codec in extended mode */
+ snd_cs46xx_ac97_write(ac97,AC97_CSR_ACMODE,0x3);
+
+ udelay(50);
+
+ /* it's necessary to wait awhile until registers are accessible after RESET */
+ /* because the PCM or MASTER volume registers can be modified, */
+ /* the REC_GAIN register is used for tests */
+ end_time = jiffies + HZ;
+ do {
+ unsigned short ext_mid;
+
+ /* use preliminary reads to settle the communication */
+ snd_ac97_read(ac97, AC97_RESET);
+ snd_ac97_read(ac97, AC97_VENDOR_ID1);
+ snd_ac97_read(ac97, AC97_VENDOR_ID2);
+ /* modem? */
+ ext_mid = snd_ac97_read(ac97, AC97_EXTENDED_MID);
+ if (ext_mid != 0xffff && (ext_mid & 1) != 0)
+ return;
+
+ /* test if we can write to the record gain volume register */
+ snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x8a05);
+ if ((err = snd_ac97_read(ac97, AC97_REC_GAIN)) == 0x8a05)
+ return;
+
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(HZ/100);
+ } while (time_after_eq(end_time, jiffies));
+
+ snd_printk("CS46xx secondary codec dont respond!\n");
+}
#endif
int __devinit snd_cs46xx_mixer(cs46xx_t *chip)
@@ -2001,11 +2428,16 @@ int __devinit snd_cs46xx_mixer(cs46xx_t *chip)
/* well, one codec only ... */
goto _end;
_ok2:
+ /* set secondary codec in extended mode */
+
+ /* use custom reset to set secondary codec in
+ extended mode */
+ ac97.reset = snd_cs46xx_sec_codec_reset;
+
if ((err = snd_ac97_mixer(card, &ac97, &chip->ac97[CS46XX_SECONDARY_CODEC_INDEX])) < 0)
return err;
chip->nr_ac97_codecs = 2;
-
- /* add cs4630 mixer controls */
+
_end:
/* dosoundcard specific mixer setup */
@@ -2016,6 +2448,7 @@ int __devinit snd_cs46xx_mixer(cs46xx_t *chip)
#endif /* CONFIG_SND_CS46XX_NEW_DSP */
+ /* add cs4630 mixer controls */
for (idx = 0; idx < sizeof(snd_cs46xx_controls) /
sizeof(snd_cs46xx_controls[0]); idx++) {
snd_kcontrol_t *kctl;
@@ -2491,10 +2924,8 @@ static int snd_cs46xx_dev_free(snd_device_t *device)
/*
* initialize chip
*/
-
static int snd_cs46xx_chip_init(cs46xx_t *chip, int busywait)
{
- unsigned int tmp;
int timeout;
/*
@@ -2581,6 +3012,11 @@ static int snd_cs46xx_chip_init(cs46xx_t *chip, int busywait)
snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, CLKCR1_PLLP | CLKCR1_SWCE);
/*
+ * Enable FIFO Host Bypass
+ */
+ snd_cs46xx_pokeBA0(chip, BA0_SERBCF, SERBCF_HBP);
+
+ /*
* Fill the serial port FIFOs with silence.
*/
snd_cs46xx_clear_serial_FIFOs(chip);
@@ -2598,6 +3034,7 @@ static int snd_cs46xx_chip_init(cs46xx_t *chip, int busywait)
snd_cs46xx_pokeBA0(chip, BA0_SERC2, SERC2_SI1F_AC97 | SERC1_SO1EN);
snd_cs46xx_pokeBA0(chip, BA0_SERMC1, SERMC1_PTC_AC97 | SERMC1_MSPE);
+
#ifdef CONFIG_SND_CS46XX_NEW_DSP
snd_cs46xx_pokeBA0(chip, BA0_SERC7, SERC7_ASDI2EN);
snd_cs46xx_pokeBA0(chip, BA0_SERC3, 0);
@@ -2608,6 +3045,7 @@ static int snd_cs46xx_chip_init(cs46xx_t *chip, int busywait)
mdelay(5);
+
/*
* Wait for the codec ready signal from the AC97 codec.
*/
@@ -2660,6 +3098,7 @@ static int snd_cs46xx_chip_init(cs46xx_t *chip, int busywait)
snd_cs46xx_pokeBA0(chip, BA0_ACCTL2, ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN);
#endif
+
/*
* Wait until we've sampled input slots 3 and 4 as valid, meaning that
* the codec is pumping ADC data across the AC-link.
@@ -2688,7 +3127,10 @@ static int snd_cs46xx_chip_init(cs46xx_t *chip, int busywait)
* Now, assert valid frame and the slot 3 and 4 valid bits. This will
* commense the transfer of digital audio data to the AC97 codec.
*/
- snd_cs46xx_pokeBA0(chip, BA0_ACOSV, ACOSV_SLV3 | ACOSV_SLV4 | ACOSV_SLV7 | ACOSV_SLV8);
+
+ snd_cs46xx_pokeBA0(chip, BA0_ACOSV, ACOSV_SLV3 | ACOSV_SLV4 |
+ ACOSV_SLV7 | ACOSV_SLV8);
+
/*
* Power down the DAC and ADC. We will power them up (if) when we need
@@ -2703,13 +3145,21 @@ static int snd_cs46xx_chip_init(cs46xx_t *chip, int busywait)
/* tmp = snd_cs46xx_peekBA0(chip, BA0_CLKCR1) & ~CLKCR1_SWCE; */
/* snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp); */
+ return 0;
+}
+
+/*
+ * start and load DSP
+ */
+int __devinit snd_cs46xx_start_dsp(cs46xx_t *chip)
+{
+ unsigned int tmp;
/*
- * Reset the processor.
- */
+ * Reset the processor.
+ */
snd_cs46xx_reset(chip);
-
/*
- * Download the image to the processor.
+ * Download the image to the processor.
*/
#ifdef CONFIG_SND_CS46XX_NEW_DSP
#if 0
@@ -2741,7 +3191,6 @@ static int snd_cs46xx_chip_init(cs46xx_t *chip, int busywait)
if (cs46xx_dsp_scb_and_task_init(chip) < 0)
return -EIO;
- snd_printdd("[get here]\n");
#else
/* old image */
if (snd_cs46xx_download_image(chip) < 0) {
@@ -2775,7 +3224,7 @@ static int snd_cs46xx_chip_init(cs46xx_t *chip, int busywait)
* Enable interrupts on the part.
*/
snd_cs46xx_pokeBA0(chip, BA0_HICR, HICR_IEV | HICR_CHGM);
-
+
tmp = snd_cs46xx_peek(chip, BA1_PFIE);
tmp &= ~0x0000f03f;
snd_cs46xx_poke(chip, BA1_PFIE, tmp); /* playback interrupt enable */
@@ -2785,19 +3234,24 @@ static int snd_cs46xx_chip_init(cs46xx_t *chip, int busywait)
tmp |= 0x00000001;
snd_cs46xx_poke(chip, BA1_CIE, tmp); /* capture interrupt enable */
+#ifdef CONFIG_SND_CS46XX_NEW_DSP
/* set the attenuation to 0dB */
- snd_cs46xx_poke(chip, BA1_PVOL, 0x80008000);
- snd_cs46xx_poke(chip, BA1_CVOL, 0x80008000);
+ snd_cs46xx_poke(chip, (MASTERMIX_SCB_ADDR + 0xE) << 2, 0x80008000);
+ snd_cs46xx_poke(chip, (VARIDECIMATE_SCB_ADDR + 0xE) << 2, 0x80008000);
+
+ /*
+ * Initialize cs46xx SPDIF controller
+ */
-#ifdef CONFIG_SND_CS46XX_NEW_DSP
/* time countdown enable */
cs46xx_poke_via_dsp (chip,SP_ASER_COUNTDOWN, 0x80000000);
-
+
/* SPDIF input MASTER ENABLE */
cs46xx_poke_via_dsp (chip,SP_SPDIN_CONTROL, 0x800003ff);
-
- /* mute spdif out */
- cs46xx_dsp_disable_spdif_out(chip);
+#else
+ /* set the attenuation to 0dB */
+ snd_cs46xx_poke(chip, BA1_PVOL, 0x80008000);
+ snd_cs46xx_poke(chip, BA1_CVOL, 0x80008000);
#endif
return 0;
@@ -2812,15 +3266,26 @@ static void amp_none(cs46xx_t *chip, int change)
{
}
-
#ifdef CONFIG_SND_CS46XX_NEW_DSP
static int voyetra_setup_eapd_slot(cs46xx_t *chip)
{
- int i;
- u32 idx;
- u16 modem_power,pin_config,logic_type,valid_slots,status;
+
+ u32 idx, valid_slots,tmp,powerdown = 0;
+ u16 modem_power,pin_config,logic_type;
+
+ snd_printdd ("cs46xx: cs46xx_setup_eapd_slot()+\n");
+
+ /*
+ * See if the devices are powered down. If so, we must power them up first
+ * or they will not respond.
+ */
+ tmp = snd_cs46xx_peekBA0(chip, BA0_CLKCR1);
+
+ if (!(tmp & CLKCR1_SWCE)) {
+ snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp | CLKCR1_SWCE);
+ powerdown = 1;
+ }
- snd_printd ("cs46xx: cs46xx_setup_eapd_slot()+\n");
/*
* Clear PRA. The Bonzo chip will be used for GPIO not for modem
* stuff.
@@ -2831,45 +3296,50 @@ static int voyetra_setup_eapd_slot(cs46xx_t *chip)
}
modem_power = snd_cs46xx_codec_read (chip,
- BA0_AC97_EXT_MODEM_POWER,
+ AC97_EXTENDED_MSTATUS,
CS46XX_SECONDARY_CODEC_INDEX);
modem_power &=0xFEFF;
snd_cs46xx_codec_write(chip,
- BA0_AC97_EXT_MODEM_POWER, modem_power,
+ AC97_EXTENDED_MSTATUS, modem_power,
CS46XX_SECONDARY_CODEC_INDEX);
/*
* Set GPIO pin's 7 and 8 so that they are configured for output.
*/
pin_config = snd_cs46xx_codec_read (chip,
- BA0_AC97_GPIO_PIN_CONFIG,
+ AC97_GPIO_CFG,
CS46XX_SECONDARY_CODEC_INDEX);
pin_config &=0x27F;
snd_cs46xx_codec_write(chip,
- BA0_AC97_GPIO_PIN_CONFIG, pin_config,
+ AC97_GPIO_CFG, pin_config,
CS46XX_SECONDARY_CODEC_INDEX);
/*
* Set GPIO pin's 7 and 8 so that they are compatible with CMOS logic.
*/
- logic_type = snd_cs46xx_codec_read(chip, BA0_AC97_GPIO_PIN_TYPE,
+ logic_type = snd_cs46xx_codec_read(chip, AC97_GPIO_POLARITY,
CS46XX_SECONDARY_CODEC_INDEX);
logic_type &=0x27F;
- snd_cs46xx_codec_write (chip, BA0_AC97_GPIO_PIN_TYPE, logic_type,
+ snd_cs46xx_codec_write (chip, AC97_GPIO_POLARITY, logic_type,
CS46XX_SECONDARY_CODEC_INDEX);
valid_slots = snd_cs46xx_peekBA0(chip, BA0_ACOSV);
valid_slots |= 0x200;
snd_cs46xx_pokeBA0(chip, BA0_ACOSV, valid_slots);
+ if ( cs46xx_wait_for_fifo(chip,1) ) {
+ snd_printdd("FIFO is busy\n");
+
+ return -EINVAL;
+ }
+
/*
* Fill slots 12 with the correct value for the GPIO pins.
*/
for(idx = 0x90; idx <= 0x9F; idx++) {
-
/*
* Initialize the fifo so that bits 7 and 8 are on.
*
@@ -2877,25 +3347,16 @@ static int voyetra_setup_eapd_slot(cs46xx_t *chip)
* the left. 0x1800 corresponds to bits 7 and 8.
*/
snd_cs46xx_pokeBA0(chip, BA0_SERBWP, 0x1800);
-
+
/*
- * Make sure the previous FIFO write operation has completed.
+ * Wait for command to complete
*/
- for(i = 0; i < 5; i++){
- status = snd_cs46xx_peekBA0(chip, BA0_SERBST);
+ if ( cs46xx_wait_for_fifo(chip,200) ) {
+ snd_printdd("failed waiting for FIFO at addr (%02X)\n",idx);
- if( !(status & SERBST_WBSY) ) {
- break;
- }
- mdelay(100);
- }
-
- if(status & SERBST_WBSY) {
- snd_printk( KERN_ERR "cs46xx: cs46xx_setup_eapd_slot() " \
- "Failure to write the GPIO pins for slot 12.\n");
return -EINVAL;
}
-
+
/*
* Write the serial port FIFO index.
*/
@@ -2907,6 +3368,16 @@ static int voyetra_setup_eapd_slot(cs46xx_t *chip)
snd_cs46xx_pokeBA0(chip, BA0_SERBCM, SERBCM_WRC);
}
+ /* wait for last command to complete */
+ cs46xx_wait_for_fifo(chip,200);
+
+ /*
+ * Now, if we powered up the devices, then power them back down again.
+ * This is kinda ugly, but should never happen.
+ */
+ if (powerdown)
+ snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp);
+
return 0;
}
#endif
@@ -2981,6 +3452,18 @@ static void amp_hercules(cs46xx_t *chip, int change)
}
}
+static void voyetra_mixer_init (cs46xx_t *chip)
+{
+ snd_printdd ("initializing Voyetra mixer\n");
+
+ /* turnon Amplifier and leave it on */
+ chip->amplifier_ctrl(chip, 1);
+
+ /* Enable SPDIF out */
+ snd_cs46xx_pokeBA0(chip, BA0_EGPIODR, EGPIODR_GPOE0);
+ snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR, EGPIODR_GPOE0);
+}
+
static void hercules_mixer_init (cs46xx_t *chip)
{
#ifdef CONFIG_SND_CS46XX_NEW_DSP
@@ -3113,7 +3596,7 @@ struct cs_card_type
static struct cs_card_type __initdata cards[] = {
{0x1489, 0x7001, "Genius Soundmaker 128 value", NULL, amp_none, NULL, NULL},
- {0x5053, 0x3357, "Voyetra", NULL, amp_voyetra, NULL, NULL},
+ {0x5053, 0x3357, "Voyetra", NULL, amp_voyetra, NULL, voyetra_mixer_init},
{0x1071, 0x6003, "Mitac MI6020/21", NULL, amp_voyetra, NULL, NULL},
{0x14AF, 0x0050, "Hercules Game Theatre XP", NULL, amp_hercules, NULL, hercules_mixer_init},
{0x1681, 0x0050, "Hercules Game Theatre XP", NULL, amp_hercules, NULL, hercules_mixer_init},
@@ -3286,7 +3769,7 @@ int __devinit snd_cs46xx_create(snd_card_t * card,
for (cp = &cards[0]; cp->name; cp++) {
if (cp->vendor == ss_vendor && cp->id == ss_card) {
- snd_printd("hack for %s enabled\n", cp->name);
+ snd_printd ("hack for %s enabled\n", cp->name);
if (cp->init)
cp->init(chip);
chip->amplifier_ctrl = cp->amp;
@@ -3362,7 +3845,7 @@ int __devinit snd_cs46xx_create(snd_card_t * card,
snd_cs46xx_free(chip);
return err;
}
-
+
chip->active_ctrl(chip, -1);
*rchip = chip;
diff --git a/sound/pci/cs46xx/cs46xx_lib.h b/sound/pci/cs46xx/cs46xx_lib.h
index 0517e7f7bfe1..53694dfd5bbb 100644
--- a/sound/pci/cs46xx/cs46xx_lib.h
+++ b/sound/pci/cs46xx/cs46xx_lib.h
@@ -35,9 +35,17 @@
#define CS46XX_BA1_REG_SIZE 0x0100
-#define CS46XX_PERIOD_SIZE 2048
+
+#ifdef CONFIG_SND_CS46XX_NEW_DSP
+#define CS46XX_MIN_PERIOD_SIZE 1
+#define CS46XX_MAX_PERIOD_SIZE 1024*1024
+#else
+#define CS46XX_MIN_PERIOD_SIZE 2048
+#define CS46XX_MAX_PERIOD_SIZE 2048
+#endif
+
#define CS46XX_FRAGS 2
-#define CS46XX_BUFFER_SIZE CS46XX_PERIOD_SIZE * CS46XX_FRAGS
+/* #define CS46XX_BUFFER_SIZE CS46XX_MAX_PERIOD_SIZE * CS46XX_FRAGS */
#define SCB_NO_PARENT 0
#define SCB_ON_PARENT_NEXT_SCB 1
@@ -51,6 +59,10 @@ extern snd_pcm_ops_t snd_cs46xx_playback_ops;
extern snd_pcm_ops_t snd_cs46xx_playback_indirect_ops;
extern snd_pcm_ops_t snd_cs46xx_capture_ops;
extern snd_pcm_ops_t snd_cs46xx_capture_indirect_ops;
+extern snd_pcm_ops_t snd_cs46xx_playback_rear_ops;
+extern snd_pcm_ops_t snd_cs46xx_playback_indirect_rear_ops;
+extern snd_pcm_ops_t snd_cs46xx_playback_iec958_ops;
+extern snd_pcm_ops_t snd_cs46xx_playback_indirect_iec958_ops;
/*
@@ -96,6 +108,7 @@ int snd_cs46xx_download (cs46xx_t *chip,u32 *src,unsigned lon
unsigned long len);
int snd_cs46xx_clear_BA1(cs46xx_t *chip,unsigned long offset,unsigned long len);
int cs46xx_dsp_enable_spdif_out (cs46xx_t *chip);
+int cs46xx_dsp_enable_spdif_hw (cs46xx_t *chip);
int cs46xx_dsp_disable_spdif_out (cs46xx_t *chip);
int cs46xx_dsp_enable_spdif_in (cs46xx_t *chip);
int cs46xx_dsp_disable_spdif_in (cs46xx_t *chip);
@@ -185,7 +198,8 @@ dsp_scb_descriptor_t * cs46xx_dsp_create_magic_snoop_scb(cs46xx_t * chip,char *
dsp_scb_descriptor_t * snoop_scb,
dsp_scb_descriptor_t * parent_scb,
int scb_child_type);
-pcm_channel_descriptor_t * cs46xx_dsp_create_pcm_channel (cs46xx_t * chip,u32 sample_rate, void * private_data, u32 hw_dma_addr);
+pcm_channel_descriptor_t * cs46xx_dsp_create_pcm_channel (cs46xx_t * chip,u32 sample_rate, void * private_data, u32 hw_dma_addr,
+ int pcm_channel_id);
void cs46xx_dsp_destroy_pcm_channel (cs46xx_t * chip,
pcm_channel_descriptor_t * pcm_channel);
void cs46xx_dsp_set_src_sample_rate(cs46xx_t * chip,dsp_scb_descriptor_t * src,
@@ -194,6 +208,15 @@ int cs46xx_dsp_pcm_unlink (cs46xx_t * chip,pcm_channel_de
int cs46xx_dsp_pcm_link (cs46xx_t * chip,pcm_channel_descriptor_t * pcm_channel);
dsp_scb_descriptor_t * cs46xx_add_record_source (cs46xx_t *chip,dsp_scb_descriptor_t * source,
u16 addr,char * scb_name);
-int cs46xx_src_unlink(cs46xx_t *chip,dsp_scb_descriptor_t * src);
-int cs46xx_src_link(cs46xx_t *chip,dsp_scb_descriptor_t * src);
+int cs46xx_src_unlink(cs46xx_t *chip,dsp_scb_descriptor_t * src);
+int cs46xx_src_link(cs46xx_t *chip,dsp_scb_descriptor_t * src);
+int cs46xx_iec958_pre_open (cs46xx_t *chip);
+int cs46xx_iec958_post_close (cs46xx_t *chip);
+int cs46xx_dsp_pcm_channel_set_period (cs46xx_t * chip,
+ pcm_channel_descriptor_t * pcm_channel,
+ int period_size);
+int cs46xx_dsp_pcm_ostream_set_period (cs46xx_t * chip,
+ int period_size);
+int cs46xx_dsp_set_dac_volume (cs46xx_t * chip,u16 right,u16 left);
+int cs46xx_dsp_set_iec958_volume (cs46xx_t * chip,u16 right,u16 left);
#endif /* __CS46XX_LIB_H__ */
diff --git a/sound/pci/cs46xx/dsp_spos.c b/sound/pci/cs46xx/dsp_spos.c
index c2c120bc7794..6a3b05de6b1a 100644
--- a/sound/pci/cs46xx/dsp_spos.c
+++ b/sound/pci/cs46xx/dsp_spos.c
@@ -257,7 +257,10 @@ dsp_spos_instance_t * cs46xx_dsp_spos_create (cs46xx_t * chip)
ins->spdif_in_sample_rate = 48000;
/* maximize volume */
- ins->spdif_input_volume = 0x80008000;
+ ins->dac_volume_right = 0x8000;
+ ins->dac_volume_left = 0x8000;
+ ins->spdif_input_volume_right = 0x8000;
+ ins->spdif_input_volume_left = 0x8000;
return ins;
}
@@ -1017,11 +1020,10 @@ int cs46xx_dsp_scb_and_task_init (cs46xx_t *chip)
dsp_scb_descriptor_t * codec_in_scb;
dsp_scb_descriptor_t * src_task_scb;
dsp_scb_descriptor_t * master_mix_scb;
+ dsp_scb_descriptor_t * rear_mix_scb;
dsp_scb_descriptor_t * record_mix_scb;
dsp_scb_descriptor_t * write_back_scb;
dsp_scb_descriptor_t * vari_decimate_scb;
- dsp_scb_descriptor_t * pcm_serial_input_task;
- dsp_scb_descriptor_t * asynch_tx_scb;
dsp_scb_descriptor_t * sec_codec_out_scb;
dsp_scb_descriptor_t * magic_snoop_scb;
@@ -1095,6 +1097,7 @@ int cs46xx_dsp_scb_and_task_init (cs46xx_t *chip)
ins->the_null_scb->sub_list_ptr = ins->the_null_scb;
ins->the_null_scb->next_scb_ptr = ins->the_null_scb;
ins->the_null_scb->parent_scb_ptr = NULL;
+ cs46xx_dsp_proc_register_scb_desc (chip,ins->the_null_scb);
}
{
@@ -1264,9 +1267,9 @@ int cs46xx_dsp_scb_and_task_init (cs46xx_t *chip)
/* create codec in */
codec_in_scb = cs46xx_dsp_create_codec_in_scb(chip,"CodecInSCB",0x0010,0x00A0,
- CODEC_INPUT_BUF1,
- CODECIN_SCB_ADDR,codec_out_scb,
- SCB_ON_PARENT_NEXT_SCB);
+ CODEC_INPUT_BUF1,
+ CODECIN_SCB_ADDR,codec_out_scb,
+ SCB_ON_PARENT_NEXT_SCB);
if (!codec_in_scb) goto _fail_end;
ins->codec_in_scb = codec_in_scb;
@@ -1309,46 +1312,38 @@ int cs46xx_dsp_scb_and_task_init (cs46xx_t *chip)
/* create secondary CODEC output */
sec_codec_out_scb = cs46xx_dsp_create_codec_out_scb(chip,"CodecOutSCB_II",0x0010,0x0040,
- OUTPUTSNOOP_SCB_ADDR,
+ REAR_MIXER_SCB_ADDR,
SEC_CODECOUT_SCB_ADDR,codec_in_scb,
SCB_ON_PARENT_NEXT_SCB);
if (!sec_codec_out_scb) goto _fail_end;
+
+ /* create the rear PCM channel mixer SCB */
+ rear_mix_scb = cs46xx_dsp_create_mix_only_scb(chip,"RearMixerSCB",
+ MIX_SAMPLE_BUF3,
+ REAR_MIXER_SCB_ADDR,
+ sec_codec_out_scb,
+ SCB_ON_PARENT_SUBLIST_SCB);
+ ins->rear_mix_scb = rear_mix_scb;
+ if (!rear_mix_scb) goto _fail_end;
+
/* the magic snooper */
magic_snoop_scb = cs46xx_dsp_create_magic_snoop_scb (chip,"MagicSnoopSCB_I",OUTPUTSNOOP_SCB_ADDR,
OUTPUT_SNOOP_BUFFER,
codec_out_scb,
sec_codec_out_scb,
- SCB_ON_PARENT_SUBLIST_SCB);
+ SCB_ON_PARENT_NEXT_SCB);
+
if (!magic_snoop_scb) goto _fail_end;
ins->ref_snoop_scb = magic_snoop_scb;
-
- /* The asynch. transfer task */
- asynch_tx_scb = cs46xx_dsp_create_asynch_fg_tx_scb(chip,"AsynchFGTxSCB",ASYNCTX_SCB_ADDR,
- SPDIFO_SCB_INST,
- SPDIFO_IP_OUTPUT_BUFFER1,
- magic_snoop_scb,
- SCB_ON_PARENT_NEXT_SCB);
-
- if (!asynch_tx_scb) goto _fail_end;
-
- /* pcm input */
- pcm_serial_input_task = cs46xx_dsp_create_pcm_serial_input_scb(chip,"PCMSerialInput_II",
- PCMSERIALINII_SCB_ADDR,
- magic_snoop_scb,asynch_tx_scb,
- SCB_ON_PARENT_SUBLIST_SCB);
-
- if (!pcm_serial_input_task) goto _fail_end;
-
/* SP IO access */
if (!cs46xx_dsp_create_spio_write_scb(chip,"SPIOWriteSCB",SPIOWRITE_SCB_ADDR,
- asynch_tx_scb,
+ magic_snoop_scb,
SCB_ON_PARENT_NEXT_SCB))
goto _fail_end;
-
/* SPDIF input sampel rate converter */
src_task_scb = cs46xx_dsp_create_src_task_scb(chip,"SrcTaskSCB_SPDIFI",
SRC_OUTPUT_BUF1,
@@ -1505,6 +1500,7 @@ int cs46xx_dsp_async_init (cs46xx_t *chip, dsp_scb_descriptor_t * fg_entry)
};
spdifo_scb_desc = cs46xx_dsp_create_scb(chip,"SPDIFOSCB",(u32 *)&spdifo_scb,SPDIFO_SCB_INST);
+
snd_assert(spdifo_scb_desc, return -EIO);
spdifi_scb_desc = cs46xx_dsp_create_scb(chip,"SPDIFISCB",(u32 *)&spdifi_scb,SPDIFI_SCB_INST);
snd_assert(spdifi_scb_desc, return -EIO);
@@ -1530,6 +1526,11 @@ int cs46xx_dsp_async_init (cs46xx_t *chip, dsp_scb_descriptor_t * fg_entry)
is the FG task tree */
fg_entry->parent_scb_ptr = spdifo_scb_desc;
+ /* for proc fs */
+ cs46xx_dsp_proc_register_scb_desc (chip,spdifo_scb_desc);
+ cs46xx_dsp_proc_register_scb_desc (chip,spdifi_scb_desc);
+ cs46xx_dsp_proc_register_scb_desc (chip,async_codec_scb_desc);
+
/* Async MASTER ENABLE, affects both SPDIF input and output */
snd_cs46xx_pokeBA0(chip, BA0_ASER_MASTER, 0x1 );
}
@@ -1537,7 +1538,7 @@ int cs46xx_dsp_async_init (cs46xx_t *chip, dsp_scb_descriptor_t * fg_entry)
return 0;
}
-int cs46xx_dsp_enable_spdif_out (cs46xx_t *chip)
+int cs46xx_dsp_enable_spdif_hw (cs46xx_t *chip)
{
dsp_spos_instance_t * ins = chip->dsp_spos_instance;
@@ -1547,29 +1548,11 @@ int cs46xx_dsp_enable_spdif_out (cs46xx_t *chip)
/* SPDIF output MASTER ENABLE */
cs46xx_poke_via_dsp (chip,SP_SPDOUT_CONTROL, 0x80000000);
- /* right and left validate bit
- NOTE: 0x80000000 and enables the SCMC protection on stream
- */
+ /* right and left validate bit */
cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV, 0x00000000 | (1 << 13) | (1 << 12));
/* monitor state */
- ins->spdif_status_out = 1;
-
- return 0;
-}
-
-int cs46xx_dsp_disable_spdif_out (cs46xx_t *chip)
-{
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
-
- /* disable SPDIF output FIFO slot */
- snd_cs46xx_pokeBA0(chip, BA0_ASER_FADDR, 0);
-
- /* SPDIF output MASTER DISABLE */
- cs46xx_poke_via_dsp (chip,SP_SPDOUT_CONTROL, 0x0);
-
- /* monitor state */
- ins->spdif_status_out = 0;
+ ins->spdif_status_out |= DSP_SPDIF_STATUS_HW_ENABLED;
return 0;
}
@@ -1605,8 +1588,10 @@ int cs46xx_dsp_enable_spdif_in (cs46xx_t *chip)
cs46xx_src_link(chip,ins->spdif_in_src);
/* restore SPDIF input volume */
- snd_cs46xx_poke(chip, (ASYNCRX_SCB_ADDR + 0xE) << 2, ins->spdif_input_volume);
- snd_cs46xx_poke(chip, (ASYNCRX_SCB_ADDR + 0xF) << 2, ins->spdif_input_volume);
+ cs46xx_dsp_scb_set_volume (chip,ins->spdif_in_src,
+ ins->spdif_input_volume_right,
+ ins->spdif_input_volume_left);
+
spin_unlock_irq(&chip->reg_lock);
/* set SPDIF input sample rate and unmute
@@ -1739,3 +1724,41 @@ int cs46xx_poke_via_dsp (cs46xx_t *chip,u32 address,u32 data)
return 0;
}
+
+int cs46xx_dsp_set_dac_volume (cs46xx_t * chip,u16 right,u16 left)
+{
+ int i;
+ dsp_spos_instance_t * ins = chip->dsp_spos_instance;
+
+ down(&chip->spos_mutex);
+
+ ins->dac_volume_right = right;
+ ins->dac_volume_left = left;
+
+ for (i = 0; i < DSP_MAX_PCM_CHANNELS; ++i) {
+ if (ins->pcm_channels[i].active &&
+ !ins->pcm_channels[i].unlinked) {
+ cs46xx_dsp_scb_set_volume (chip,ins->pcm_channels[i].pcm_reader_scb,
+ right,left);
+
+ }
+ }
+
+ up(&chip->spos_mutex);
+
+ return 0;
+}
+
+int cs46xx_dsp_set_iec958_volume (cs46xx_t * chip,u16 right,u16 left) {
+ dsp_spos_instance_t * ins = chip->dsp_spos_instance;
+
+ down(&chip->spos_mutex);
+ cs46xx_dsp_scb_set_volume (chip,ins->spdif_in_src,
+ right,left);
+
+ ins->spdif_input_volume_right = right;
+ ins->spdif_input_volume_left = left;
+ up(&chip->spos_mutex);
+
+ return 0;
+}
diff --git a/sound/pci/cs46xx/dsp_spos.h b/sound/pci/cs46xx/dsp_spos.h
index fe5d47bf1907..1dfba850c687 100644
--- a/sound/pci/cs46xx/dsp_spos.h
+++ b/sound/pci/cs46xx/dsp_spos.h
@@ -73,7 +73,10 @@ typedef enum {
#define SPDIFI_IP_OUTPUT_BUFFER1 0x0E00
#define SPDIFO_IP_OUTPUT_BUFFER1 0x1000
#define MIX_SAMPLE_BUF1 0x1400
-#define MIX_SAMPLE_BUF2 0x3000
+#define MIX_SAMPLE_BUF2 0x2D00
+#define MIX_SAMPLE_BUF3 0x2E00
+#define MIX_SAMPLE_BUF4 0x2F00
+#define MIX_SAMPLE_BUF5 0x3000
/* Task stack address */
#define HFG_STACK 0x066A
@@ -104,6 +107,8 @@ typedef enum {
#define OUTPUTSNOOPII_SCB_ADDR 0x150
#define PCMSERIALIN_PCM_SCB_ADDR 0x160
#define RECORD_MIXER_SCB_ADDR 0x170
+#define REAR_MIXER_SCB_ADDR 0x180
+#define SPDIF_MIXER_SCB_ADDR 0x190
/* hyperforground SCB's*/
#define HFG_TREE_SCB 0xBA0
@@ -123,6 +128,7 @@ typedef enum {
#define SCBfuncEntryPtr 0xA
#define SRCCorPerGof 0x2
#define SRCPhiIncr6Int26Frac 0xd
+#define SCBVolumeCtrl 0xe
/* conf */
#define UseASER1Input 1
@@ -179,5 +185,22 @@ typedef enum {
#define SP_SPDOUT_CONTROL 0x804D
#define SP_SPDOUT_CSUV 0x808E
+static inline void cs46xx_dsp_spos_update_scb (cs46xx_t * chip,dsp_scb_descriptor_t * scb)
+{
+ /* update nextSCB and subListPtr in SCB */
+ snd_cs46xx_poke(chip,
+ (scb->address + SCBsubListPtr) << 2,
+ (scb->sub_list_ptr->address << 0x10) |
+ (scb->next_scb_ptr->address));
+}
+
+static inline void cs46xx_dsp_scb_set_volume (cs46xx_t * chip,dsp_scb_descriptor_t * scb,
+ u16 right,u16 left) {
+ unsigned int val = ((0xffff - right) << 16 | (0xffff - left));
+
+ snd_cs46xx_poke(chip, (scb->address + SCBVolumeCtrl) << 2, val);
+ snd_cs46xx_poke(chip, (scb->address + SCBVolumeCtrl + 1) << 2, val);
+}
+
#endif /* __DSP_SPOS_H__ */
#endif /* CONFIG_SND_CS46XX_NEW_DSP */
diff --git a/sound/pci/cs46xx/dsp_spos_scb_lib.c b/sound/pci/cs46xx/dsp_spos_scb_lib.c
index 28a6dfa0b551..b08ba01f51c0 100644
--- a/sound/pci/cs46xx/dsp_spos_scb_lib.c
+++ b/sound/pci/cs46xx/dsp_spos_scb_lib.c
@@ -150,17 +150,11 @@ static void _dsp_unlink_scb (cs46xx_t *chip,dsp_scb_descriptor_t * scb)
spin_lock_irqsave(&chip->reg_lock, flags);
/* update parent first entry in DSP RAM */
- snd_cs46xx_poke(chip,
- (scb->parent_scb_ptr->address + SCBsubListPtr) << 2,
- (scb->parent_scb_ptr->sub_list_ptr->address << 0x10) |
- (scb->parent_scb_ptr->next_scb_ptr->address));
+ cs46xx_dsp_spos_update_scb(chip,scb->parent_scb_ptr);
/* then update entry in DSP RAM */
- snd_cs46xx_poke(chip,
- (scb->address + SCBsubListPtr) << 2,
- (scb->sub_list_ptr->address << 0x10) |
- (scb->next_scb_ptr->address));
-
+ cs46xx_dsp_spos_update_scb(chip,scb);
+
scb->parent_scb_ptr = NULL;
spin_unlock_irqrestore(&chip->reg_lock, flags);
}
@@ -173,6 +167,7 @@ static void _dsp_clear_sample_buffer (cs46xx_t *chip, u32 sample_buffer_addr, in
for (i = 0; i < dword_count ; ++i ) {
writel(0, dst);
+ dst += 4;
}
}
@@ -328,11 +323,9 @@ _dsp_create_generic_scb (cs46xx_t *chip,char * name, u32 * scb_data,u32 dest,
}
spin_lock_irqsave(&chip->reg_lock, flags);
+
/* update entry in DSP RAM */
- snd_cs46xx_poke(chip,
- (scb->parent_scb_ptr->address + SCBsubListPtr) << 2,
- (scb->parent_scb_ptr->sub_list_ptr->address << 0x10) |
- (scb->parent_scb_ptr->next_scb_ptr->address));
+ cs46xx_dsp_spos_update_scb(chip,scb->parent_scb_ptr);
spin_unlock_irqrestore(&chip->reg_lock, flags);
}
@@ -610,7 +603,7 @@ cs46xx_dsp_create_src_task_scb(cs46xx_t * chip,char * scb_name,
src_buffer_addr << 0x10,
0x04000000,
{
- 0xffff,0xffff,
+ 0x8000,0x8000,
0xffff,0xffff
}
};
@@ -665,7 +658,7 @@ cs46xx_dsp_create_mix_only_scb(cs46xx_t * chip,char * scb_name,
/* D */ 0,
{
/* E */ 0x8000,0x8000,
- /* F */ 0x8000,0x8000
+ /* F */ 0xffff,0xffff
}
};
@@ -832,7 +825,7 @@ cs46xx_dsp_create_asynch_fg_tx_scb(cs46xx_t * chip,char * scb_name,u32 dest,
0x0058,0x0028, /* Min Delta 7 dwords == 28 bytes */
/* : Max delta 25 dwords == 100 bytes */
0,hfg_scb_address, /* Point to HFG task SCB */
- 0,0, /* Initialize current Delta and Consumer ptr adjustment count */
+ 0,0, /* Initialize current Delta and Consumer ptr adjustment count */
0, /* Initialize accumulated Phi to 0 */
0,0x2aab, /* Const 1/3 */
@@ -847,13 +840,13 @@ cs46xx_dsp_create_asynch_fg_tx_scb(cs46xx_t * chip,char * scb_name,u32 dest,
RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_256, /* Stereo, 256 dword */
(asynch_buffer_address) << 0x10, /* This should be automagically synchronized
- to the producer pointer */
+ to the producer pointer */
/* There is no correct initial value, it will depend upon the detected
rate etc */
0x18000000, /* Phi increment for approx 32k operation */
0x8000,0x8000, /* Volume controls are unused at this time */
- 0x8000,0x8000
+ 0xffff,0xffff
};
scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&asynch_fg_tx_scb,
@@ -1093,15 +1086,46 @@ static u32 src_delay_buffer_addr[DSP_MAX_SRC_NR] = {
};
-pcm_channel_descriptor_t * cs46xx_dsp_create_pcm_channel (cs46xx_t * chip,u32 sample_rate, void * private_data, u32 hw_dma_addr)
+pcm_channel_descriptor_t * cs46xx_dsp_create_pcm_channel (cs46xx_t * chip,
+ u32 sample_rate, void * private_data,
+ u32 hw_dma_addr,
+ int pcm_channel_id)
{
dsp_spos_instance_t * ins = chip->dsp_spos_instance;
- dsp_scb_descriptor_t * src_scb = NULL,* pcm_scb;
+ dsp_scb_descriptor_t * src_scb = NULL,* pcm_scb, * mixer_scb = NULL;
/*dsp_scb_descriptor_t * pcm_parent_scb;*/
char scb_name[DSP_MAX_SCB_NAME];
int i,pcm_index = -1, insert_point, src_index = -1;
unsigned long flags;
+ switch (pcm_channel_id) {
+ case DSP_PCM_MAIN_CHANNEL:
+ mixer_scb = ins->master_mix_scb;
+ break;
+ case DSP_PCM_REAR_CHANNEL:
+ mixer_scb = ins->rear_mix_scb;
+ break;
+ case DSP_PCM_CENTER_CHANNEL:
+ /* TODO */
+ snd_assert(0);
+ break;
+ case DSP_PCM_LFE_CHANNEL:
+ /* TODO */
+ snd_assert(0);
+ break;
+ case DSP_IEC958_CHANNEL:
+ snd_assert (ins->asynch_tx_scb != NULL, return NULL);
+ mixer_scb = ins->asynch_tx_scb;
+ if (ins->spdif_status_out & DSP_SPDIF_STATUS_AC3_MODE) {
+ snd_printdd ("IEC958 opened in AC3 mode\n");
+ /*src_scb = ins->asynch_tx_scb;
+ ins->asynch_tx_scb->ref_count ++;*/
+ }
+ break;
+ default:
+ snd_assert (0);
+ return NULL;
+ }
/* default sample rate is 44100 */
if (!sample_rate) sample_rate = 44100;
@@ -1114,7 +1138,9 @@ pcm_channel_descriptor_t * cs46xx_dsp_create_pcm_channel (cs46xx_t * chip,u32 sa
if (i == CS46XX_DSP_CAPTURE_CHANNEL) continue;
if (ins->pcm_channels[i].active) {
- if (!src_scb && ins->pcm_channels[i].sample_rate == sample_rate) {
+ if (!src_scb &&
+ ins->pcm_channels[i].sample_rate == sample_rate &&
+ ins->pcm_channels[i].mixer_scb == mixer_scb) {
src_scb = ins->pcm_channels[i].src_scb;
ins->pcm_channels[i].src_scb->ref_count ++;
src_index = ins->pcm_channels[i].src_slot;
@@ -1148,11 +1174,11 @@ pcm_channel_descriptor_t * cs46xx_dsp_create_pcm_channel (cs46xx_t * chip,u32 sa
snd_assert (src_index != -1,return NULL);
/* we need to create a new SRC SCB */
- if (ins->master_mix_scb->sub_list_ptr == ins->the_null_scb) {
- src_parent_scb = ins->master_mix_scb;
+ if (mixer_scb->sub_list_ptr == ins->the_null_scb) {
+ src_parent_scb = mixer_scb;
insert_point = SCB_ON_PARENT_SUBLIST_SCB;
} else {
- src_parent_scb = find_next_free_scb(chip,ins->master_mix_scb->sub_list_ptr);
+ src_parent_scb = find_next_free_scb(chip,mixer_scb->sub_list_ptr);
insert_point = SCB_ON_PARENT_NEXT_SCB;
}
@@ -1172,7 +1198,9 @@ pcm_channel_descriptor_t * cs46xx_dsp_create_pcm_channel (cs46xx_t * chip,u32 sa
return NULL;
}
- cs46xx_dsp_set_src_sample_rate(chip,src_scb,sample_rate);
+ if (pcm_channel_id != DSP_IEC958_CHANNEL ||
+ !(ins->spdif_status_out & DSP_SPDIF_STATUS_AC3_MODE))
+ cs46xx_dsp_set_src_sample_rate(chip,src_scb,sample_rate);
ins->nsrc_scb ++;
}
@@ -1180,7 +1208,8 @@ pcm_channel_descriptor_t * cs46xx_dsp_create_pcm_channel (cs46xx_t * chip,u32 sa
snprintf (scb_name,DSP_MAX_SCB_NAME,"PCMReader_SCB%d",pcm_index);
- snd_printdd( "dsp_spos: creating PCM \"%s\"\n",scb_name);
+ snd_printdd( "dsp_spos: creating PCM \"%s\" (%d)\n",scb_name,
+ pcm_channel_id);
pcm_scb = cs46xx_dsp_create_pcm_reader_scb(chip,scb_name,
pcm_reader_buffer_addr[pcm_index],
@@ -1206,12 +1235,91 @@ pcm_channel_descriptor_t * cs46xx_dsp_create_pcm_channel (cs46xx_t * chip,u32 sa
ins->pcm_channels[pcm_index].src_slot = src_index;
ins->pcm_channels[pcm_index].active = 1;
ins->pcm_channels[pcm_index].pcm_slot = pcm_index;
+ ins->pcm_channels[pcm_index].mixer_scb = mixer_scb;
+ ins->pcm_channels[pcm_index].pcm_channel_id = pcm_channel_id;
ins->npcm_channels ++;
spin_unlock_irqrestore(&chip->reg_lock, flags);
return (ins->pcm_channels + pcm_index);
}
+int cs46xx_dsp_pcm_channel_set_period (cs46xx_t * chip,
+ pcm_channel_descriptor_t * pcm_channel,
+ int period_size)
+{
+ u32 temp = snd_cs46xx_peek (chip,pcm_channel->pcm_reader_scb->address << 2);
+ temp &= ~DMA_RQ_C1_SOURCE_SIZE_MASK;
+
+ switch (period_size) {
+ case 2048:
+ temp |= DMA_RQ_C1_SOURCE_MOD1024;
+ break;
+ case 1024:
+ temp |= DMA_RQ_C1_SOURCE_MOD512;
+ break;
+ case 512:
+ temp |= DMA_RQ_C1_SOURCE_MOD256;
+ break;
+ case 256:
+ temp |= DMA_RQ_C1_SOURCE_MOD128;
+ break;
+ case 128:
+ temp |= DMA_RQ_C1_SOURCE_MOD64;
+ break;
+ case 64:
+ temp |= DMA_RQ_C1_SOURCE_MOD32;
+ break;
+ case 32:
+ temp |= DMA_RQ_C1_SOURCE_MOD16;
+ break;
+ default:
+ snd_printdd ("period size (%d) not supported by HW\n");
+ return -EINVAL;
+ }
+
+ snd_cs46xx_poke (chip,pcm_channel->pcm_reader_scb->address << 2,temp);
+
+ return 0;
+}
+
+int cs46xx_dsp_pcm_ostream_set_period (cs46xx_t * chip,
+ int period_size)
+{
+ u32 temp = snd_cs46xx_peek (chip,WRITEBACK_SCB_ADDR << 2);
+ temp &= ~DMA_RQ_C1_DEST_SIZE_MASK;
+
+ switch (period_size) {
+ case 2048:
+ temp |= DMA_RQ_C1_DEST_MOD1024;
+ break;
+ case 1024:
+ temp |= DMA_RQ_C1_DEST_MOD512;
+ break;
+ case 512:
+ temp |= DMA_RQ_C1_DEST_MOD256;
+ break;
+ case 256:
+ temp |= DMA_RQ_C1_DEST_MOD128;
+ break;
+ case 128:
+ temp |= DMA_RQ_C1_DEST_MOD64;
+ break;
+ case 64:
+ temp |= DMA_RQ_C1_DEST_MOD32;
+ break;
+ case 32:
+ temp |= DMA_RQ_C1_DEST_MOD16;
+ break;
+ default:
+ snd_printdd ("period size (%d) not supported by HW\n");
+ return -EINVAL;
+ }
+
+ snd_cs46xx_poke (chip,WRITEBACK_SCB_ADDR << 2,temp);
+
+ return 0;
+}
+
void cs46xx_dsp_destroy_pcm_channel (cs46xx_t * chip,pcm_channel_descriptor_t * pcm_channel)
{
dsp_spos_instance_t * ins = chip->dsp_spos_instance;
@@ -1293,17 +1401,13 @@ int cs46xx_dsp_pcm_link (cs46xx_t * chip,pcm_channel_descriptor_t * pcm_channel)
snd_assert (pcm_channel->pcm_reader_scb->parent_scb_ptr == NULL, ; );
pcm_channel->pcm_reader_scb->parent_scb_ptr = parent_scb;
- /* update entry in DSP RAM */
spin_lock_irqsave(&chip->reg_lock, flags);
- snd_cs46xx_poke(chip,
- (pcm_channel->pcm_reader_scb->address + SCBsubListPtr) << 2,
- (pcm_channel->pcm_reader_scb->sub_list_ptr->address << 0x10) |
- (pcm_channel->pcm_reader_scb->next_scb_ptr->address));
-
- snd_cs46xx_poke(chip,
- (parent_scb->address + SCBsubListPtr) << 2,
- (parent_scb->sub_list_ptr->address << 0x10) |
- (parent_scb->next_scb_ptr->address));
+
+ /* update SCB entry in DSP RAM */
+ cs46xx_dsp_spos_update_scb(chip,pcm_channel->pcm_reader_scb);
+
+ /* update parent SCB entry */
+ cs46xx_dsp_spos_update_scb(chip,parent_scb);
pcm_channel->unlinked = 0;
spin_unlock_irqrestore(&chip->reg_lock, flags);
@@ -1358,14 +1462,16 @@ void cs46xx_dsp_set_src_sample_rate(cs46xx_t *chip,dsp_scb_descriptor_t * src, u
spin_lock_irqsave(&chip->reg_lock, flags);
/* mute SCB */
- snd_cs46xx_poke(chip, (src->address + 0xE) << 2, 0xffffffff);
+ /* cs46xx_dsp_scb_set_volume (chip,src,0,0); */
+
snd_cs46xx_poke(chip, (src->address + SRCCorPerGof) << 2,
((correctionPerSec << 16) & 0xFFFF0000) | (correctionPerGOF & 0xFFFF));
snd_cs46xx_poke(chip, (src->address + SRCPhiIncr6Int26Frac) << 2, phiIncr);
/* raise volume */
- snd_cs46xx_poke(chip, (src->address + 0xE) << 2, 0x80008000);
+ /* cs46xx_dsp_scb_set_volume (chip,src,0x7fff,0x7fff); */
+
spin_unlock_irqrestore(&chip->reg_lock, flags);
}
@@ -1399,7 +1505,7 @@ int cs46xx_src_unlink(cs46xx_t *chip,dsp_scb_descriptor_t * src)
snd_assert (src->parent_scb_ptr != NULL, return -EINVAL );
/* mute SCB */
- snd_cs46xx_poke(chip, (src->address + 0xE) << 2, 0xffffffff);
+ cs46xx_dsp_scb_set_volume (chip,src,0,0);
_dsp_unlink_scb (chip,src);
@@ -1425,10 +1531,144 @@ int cs46xx_src_link(cs46xx_t *chip,dsp_scb_descriptor_t * src)
src->parent_scb_ptr = parent_scb;
/* update entry in DSP RAM */
- snd_cs46xx_poke(chip,
- (parent_scb->address + SCBsubListPtr) << 2,
- (parent_scb->sub_list_ptr->address << 0x10) |
- (parent_scb->next_scb_ptr->address));
+ cs46xx_dsp_spos_update_scb(chip,parent_scb);
+
+ return 0;
+}
+
+int cs46xx_dsp_enable_spdif_out (cs46xx_t *chip)
+{
+ dsp_spos_instance_t * ins = chip->dsp_spos_instance;
+
+ if ( ! (ins->spdif_status_out & DSP_SPDIF_STATUS_HW_ENABLED) ) {
+ cs46xx_dsp_enable_spdif_hw (chip);
+ }
+
+ /* dont touch anything if SPDIF is open */
+ if ( ins->spdif_status_out & DSP_SPDIF_STATUS_PLAYBACK_OPEN) {
+ /* when cs46xx_iec958_post_close(...) is called it
+ will call this function if necesary depending on
+ this bit */
+ ins->spdif_status_out |= DSP_SPDIF_STATUS_OUTPUT_ENABLED;
+
+ return -EBUSY;
+ }
+
+ snd_assert (ins->asynch_tx_scb == NULL, return -EINVAL);
+ snd_assert (ins->master_mix_scb->next_scb_ptr == ins->the_null_scb, return -EINVAL);
+
+ /* reset output snooper sample buffer pointer */
+ snd_cs46xx_poke (chip, (ins->ref_snoop_scb->address + 2) << 2,
+ (OUTPUT_SNOOP_BUFFER + 0x10) << 0x10 );
+
+ /* The asynch. transfer task */
+ ins->asynch_tx_scb = cs46xx_dsp_create_asynch_fg_tx_scb(chip,"AsynchFGTxSCB",ASYNCTX_SCB_ADDR,
+ SPDIFO_SCB_INST,
+ SPDIFO_IP_OUTPUT_BUFFER1,
+ ins->master_mix_scb,
+ SCB_ON_PARENT_NEXT_SCB);
+ if (!ins->asynch_tx_scb) return -ENOMEM;
+
+ ins->spdif_pcm_input_scb = cs46xx_dsp_create_pcm_serial_input_scb(chip,"PCMSerialInput_II",
+ PCMSERIALINII_SCB_ADDR,
+ ins->ref_snoop_scb,
+ ins->asynch_tx_scb,
+ SCB_ON_PARENT_SUBLIST_SCB);
+
+ if (!ins->spdif_pcm_input_scb) return -ENOMEM;
+
+ /* monitor state */
+ ins->spdif_status_out |= DSP_SPDIF_STATUS_OUTPUT_ENABLED;
+
+ return 0;
+}
+
+int cs46xx_dsp_disable_spdif_out (cs46xx_t *chip)
+{
+ dsp_spos_instance_t * ins = chip->dsp_spos_instance;
+
+ /* dont touch anything if SPDIF is open */
+ if ( ins->spdif_status_out & DSP_SPDIF_STATUS_PLAYBACK_OPEN) {
+ ins->spdif_status_out &= ~DSP_SPDIF_STATUS_OUTPUT_ENABLED;
+ return -EBUSY;
+ }
+
+ /* check integrety */
+ snd_assert (ins->asynch_tx_scb != NULL, return -EINVAL);
+ snd_assert (ins->spdif_pcm_input_scb != NULL,return -EINVAL);
+ snd_assert (ins->master_mix_scb->next_scb_ptr == ins->asynch_tx_scb, return -EINVAL);
+ snd_assert (ins->asynch_tx_scb->parent_scb_ptr == ins->master_mix_scb, return -EINVAL);
+
+ cs46xx_dsp_remove_scb (chip,ins->spdif_pcm_input_scb);
+ cs46xx_dsp_remove_scb (chip,ins->asynch_tx_scb);
+
+ ins->spdif_pcm_input_scb = NULL;
+ ins->asynch_tx_scb = NULL;
+
+ /* clear buffer to prevent any undesired noise */
+ _dsp_clear_sample_buffer(chip,SPDIFO_IP_OUTPUT_BUFFER1,256);
+
+ /* monitor state */
+ ins->spdif_status_out &= ~DSP_SPDIF_STATUS_OUTPUT_ENABLED;
+
+
+ return 0;
+}
+
+int cs46xx_iec958_pre_open (cs46xx_t *chip)
+{
+ dsp_spos_instance_t * ins = chip->dsp_spos_instance;
+
+ if ( ins->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED ) {
+ /* remove AsynchFGTxSCB and and PCMSerialInput_II */
+ cs46xx_dsp_disable_spdif_out (chip);
+
+ /* save state */
+ ins->spdif_status_out |= DSP_SPDIF_STATUS_OUTPUT_ENABLED;
+ }
+
+ /* if not enabled already */
+ if (ins->spdif_status_out & DSP_SPDIF_STATUS_HW_ENABLED) {
+ cs46xx_dsp_enable_spdif_hw (chip);
+ }
+
+ /* Create the asynch. transfer task for playback */
+ ins->asynch_tx_scb = cs46xx_dsp_create_asynch_fg_tx_scb(chip,"AsynchFGTxSCB",ASYNCTX_SCB_ADDR,
+ SPDIFO_SCB_INST,
+ SPDIFO_IP_OUTPUT_BUFFER1,
+ ins->master_mix_scb,
+ SCB_ON_PARENT_NEXT_SCB);
+
+
+ if (ins->spdif_status_out & DSP_SPDIF_STATUS_AC3_MODE)
+ /* set left (13), right validity bit (12) , and non-audio(1) and profsional bit (0) */
+ cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV, 0x00000000 | (1 << 13) | (1 << 12) | (1 << 1) | 1);
+
+ ins->spdif_status_out |= DSP_SPDIF_STATUS_PLAYBACK_OPEN;
+
+ return 0;
+}
+
+int cs46xx_iec958_post_close (cs46xx_t *chip)
+{
+ dsp_spos_instance_t * ins = chip->dsp_spos_instance;
+
+ snd_assert (ins->asynch_tx_scb != NULL, return -EINVAL);
+
+ ins->spdif_status_out &= ~DSP_SPDIF_STATUS_PLAYBACK_OPEN;
+
+ /* restore settings */
+ cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV, 0x00000000 | (1 << 13) | (1 << 12));
+
+ /* deallocate stuff */
+ cs46xx_dsp_remove_scb (chip,ins->asynch_tx_scb);
+ ins->asynch_tx_scb = NULL;
+
+ /* restore state */
+ if ( ins->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED ) {
+ cs46xx_dsp_enable_spdif_out (chip);
+ }
+
return 0;
}
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c
index 99613539adbb..12933f97c860 100644
--- a/sound/pci/ens1370.c
+++ b/sound/pci/ens1370.c
@@ -37,6 +37,7 @@
#endif
#define SNDRV_GET_ID
#include <sound/initval.h>
+#include <sound/asoundef.h>
#define chip_t ensoniq_t
@@ -109,66 +110,70 @@ MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
#define ES_REG_CONTROL 0x00 /* R/W: Interrupt/Chip select control register */
#define ES_1370_ADC_STOP (1<<31) /* disable capture buffer transfers */
#define ES_1370_XCTL1 (1<<30) /* general purpose output bit */
-#define ES_1371_SPDIF_EN (1<<26) /* SPDIF enable */
-#define ES_1371_JOY_ASEL(o) (((o)&0x03)<<24) /* joystick port mapping */
+#define ES_1373_TEST_BIT (1<<29) /* should be set to 0 for normal operation */
+#define ES_1373_RECEN_B (1<<28) /* mix record with playback for I2S/SPDIF out */
+#define ES_1373_SPDIF_THRU (1<<26) /* 0 = SPDIF thru mode, 1 = SPDIF == dig out */
+#define ES_1371_JOY_ASEL(o) (((o)&0x03)<<24)/* joystick port mapping */
#define ES_1371_JOY_ASELM (0x03<<24) /* mask for above */
#define ES_1371_JOY_ASELI(i) (((i)>>24)&0x03)
-#define ES_1371_GPIO_IN(i) (((i)>>20)&0x0f) /* GPIO in [3:0] pins - R/O */
-#define ES_1370_PCLKDIVO(o) (((o)&0x1fff)<<16) /* clock divide ratio for DAC2 */
+#define ES_1371_GPIO_IN(i) (((i)>>20)&0x0f)/* GPIO in [3:0] pins - R/O */
+#define ES_1370_PCLKDIVO(o) (((o)&0x1fff)<<16)/* clock divide ratio for DAC2 */
#define ES_1370_PCLKDIVM ((0x1fff)<<16) /* mask for above */
-#define ES_1370_PCLKDIVI(i) (((i)>>16)&0x1fff) /* clock divide ratio for DAC2 */
-#define ES_1371_GPIO_OUT(o) (((o)&0x0f)<<16) /* GPIO out [3:0] pins - W/R */
+#define ES_1370_PCLKDIVI(i) (((i)>>16)&0x1fff)/* clock divide ratio for DAC2 */
+#define ES_1371_GPIO_OUT(o) (((o)&0x0f)<<16)/* GPIO out [3:0] pins - W/R */
#define ES_1371_GPIO_OUTM (0x0f<<16) /* mask for above */
#define ES_MSFMTSEL (1<<15) /* MPEG serial data format; 0 = SONY, 1 = I2S */
#define ES_1370_M_SBB (1<<14) /* clock source for DAC - 0 = clock generator; 1 = MPEG clocks */
#define ES_1371_SYNC_RES (1<<14) /* Warm AC97 reset */
-#define ES_1370_WTSRSEL(o) (((o)&0x03)<<12) /* fixed frequency clock for DAC1 */
+#define ES_1370_WTSRSEL(o) (((o)&0x03)<<12)/* fixed frequency clock for DAC1 */
#define ES_1370_WTSRSELM (0x03<<12) /* mask for above */
#define ES_1371_ADC_STOP (1<<13) /* disable CCB transfer capture information */
#define ES_1371_PWR_INTRM (1<<12) /* power level change interrupts enable */
#define ES_1370_DAC_SYNC (1<<11) /* DAC's are synchronous */
-#define ES_1371_M_CB (1<<11) /* capture clock source; 0 = ADC; 1 = I2S */
+#define ES_1371_M_CB (1<<11) /* capture clock source; 0 = AC'97 ADC; 1 = I2S */
#define ES_CCB_INTRM (1<<10) /* CCB voice interrupts enable */
-#define ES_1370_M_CB (1<<9) /* capture clock source; 0 = ADC; 1 = MPEG */
-#define ES_1370_XCTL0 (1<<8) /* generap purpose output bit */
-#define ES_1371_PDLEV(o) (((o)&0x03)<<8) /* current power down level */
+#define ES_1370_M_CB (1<<9) /* capture clock source; 0 = ADC; 1 = MPEG */
+#define ES_1370_XCTL0 (1<<8) /* generap purpose output bit */
+#define ES_1371_PDLEV(o) (((o)&0x03)<<8) /* current power down level */
#define ES_1371_PDLEVM (0x03<<8) /* mask for above */
-#define ES_BREQ (1<<7) /* memory bus request enable */
-#define ES_DAC1_EN (1<<6) /* DAC1 playback channel enable */
-#define ES_DAC2_EN (1<<5) /* DAC2 playback channel enable */
-#define ES_ADC_EN (1<<4) /* ADC capture channel enable */
-#define ES_UART_EN (1<<3) /* UART enable */
-#define ES_JYSTK_EN (1<<2) /* Joystick module enable */
-#define ES_1370_CDC_EN (1<<1) /* Codec interface enable */
-#define ES_1371_XTALCKDIS (1<<1) /* Xtal clock disable */
-#define ES_1370_SERR_DISABLE (1<<0) /* PCI serr signal disable */
-#define ES_1371_PCICLKDIS (1<<0) /* PCI clock disable */
+#define ES_BREQ (1<<7) /* memory bus request enable */
+#define ES_DAC1_EN (1<<6) /* DAC1 playback channel enable */
+#define ES_DAC2_EN (1<<5) /* DAC2 playback channel enable */
+#define ES_ADC_EN (1<<4) /* ADC capture channel enable */
+#define ES_UART_EN (1<<3) /* UART enable */
+#define ES_JYSTK_EN (1<<2) /* Joystick module enable */
+#define ES_1370_CDC_EN (1<<1) /* Codec interface enable */
+#define ES_1371_XTALCKDIS (1<<1) /* Xtal clock disable */
+#define ES_1370_SERR_DISABLE (1<<0) /* PCI serr signal disable */
+#define ES_1371_PCICLKDIS (1<<0) /* PCI clock disable */
#define ES_REG_STATUS 0x04 /* R/O: Interrupt/Chip select status register */
-#define ES_INTR (1<<31) /* Interrupt is pending */
-#define ES_1371_ST_AC97_RST (1<<29) /* CT5880 AC'97 Reset bit */
-#define ES_1371_ST_SPDIF_EN (1<<18) /* SPDIF enable */
-#define ES_1371_ST_SPDIF_TEST (1<<17) /* SPDIF test */
-#define ES_1371_TEST (1<<16) /* test ASIC */
-#define ES_1370_CSTAT (1<<10) /* CODEC is busy or register write in progress */
-#define ES_1370_CBUSY (1<<9) /* CODEC is busy */
-#define ES_1370_CWRIP (1<<8) /* CODEC register write in progress */
-#define ES_1371_SYNC_ERR (1<<8) /* CODEC synchronization error occured */
-#define ES_1371_VC(i) (((i)>>6)&0x03) /* voice code from CCB module */
-#define ES_1370_VC(i) (((i)>>5)&0x03) /* voice code from CCB module */
-#define ES_1371_MPWR (1<<5) /* power level interrupt pending */
-#define ES_MCCB (1<<4) /* CCB interrupt pending */
-#define ES_UART (1<<3) /* UART interrupt pending */
-#define ES_DAC1 (1<<2) /* DAC1 channel interrupt pending */
-#define ES_DAC2 (1<<1) /* DAC2 channel interrupt pending */
-#define ES_ADC (1<<0) /* ADC channel interrupt pending */
+#define ES_INTR (1<<31) /* Interrupt is pending */
+#define ES_1371_ST_AC97_RST (1<<29) /* CT5880 AC'97 Reset bit */
+#define ES_1373_GPIO_INT_EN(o)(((o)&0x0f)<<20)/* GPIO [3:0] pins - interrupt enable */
+#define ES_1373_SPDIF_EN (1<<18) /* SPDIF enable */
+#define ES_1373_SPDIF_TEST (1<<17) /* SPDIF test */
+#define ES_1371_TEST (1<<16) /* test ASIC */
+#define ES_1373_GPIO_INT(i) (((i)&0x0f)>>12)/* GPIO [3:0] pins - interrupt pending */
+#define ES_1370_CSTAT (1<<10) /* CODEC is busy or register write in progress */
+#define ES_1370_CBUSY (1<<9) /* CODEC is busy */
+#define ES_1370_CWRIP (1<<8) /* CODEC register write in progress */
+#define ES_1371_SYNC_ERR (1<<8) /* CODEC synchronization error occured */
+#define ES_1371_VC(i) (((i)>>6)&0x03) /* voice code from CCB module */
+#define ES_1370_VC(i) (((i)>>5)&0x03) /* voice code from CCB module */
+#define ES_1371_MPWR (1<<5) /* power level interrupt pending */
+#define ES_MCCB (1<<4) /* CCB interrupt pending */
+#define ES_UART (1<<3) /* UART interrupt pending */
+#define ES_DAC1 (1<<2) /* DAC1 channel interrupt pending */
+#define ES_DAC2 (1<<1) /* DAC2 channel interrupt pending */
+#define ES_ADC (1<<0) /* ADC channel interrupt pending */
#define ES_REG_UART_DATA 0x08 /* R/W: UART data register */
#define ES_REG_UART_STATUS 0x09 /* R/O: UART status register */
-#define ES_RXINT (1<<7) /* RX interrupt occured */
-#define ES_TXINT (1<<2) /* TX interrupt occured */
-#define ES_TXRDY (1<<1) /* transmitter ready */
-#define ES_RXRDY (1<<0) /* receiver ready */
+#define ES_RXINT (1<<7) /* RX interrupt occured */
+#define ES_TXINT (1<<2) /* TX interrupt occured */
+#define ES_TXRDY (1<<1) /* transmitter ready */
+#define ES_RXRDY (1<<0) /* receiver ready */
#define ES_REG_UART_CONTROL 0x09 /* W/O: UART control register */
-#define ES_RXINTEN (1<<7) /* RX interrupt enable */
+#define ES_RXINTEN (1<<7) /* RX interrupt enable */
#define ES_TXINTENO(o) (((o)&0x03)<<5) /* TX interrupt enable */
#define ES_TXINTENM (0x03<<5) /* mask for above */
#define ES_TXINTENI(i) (((i)>>5)&0x03)
@@ -191,29 +196,29 @@ MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
#define ES_1371_CODEC_READ(i) (((i)>>0)&0xffff)
#define ES_REG_1371_SMPRATE 0x10 /* W/R: Codec rate converter interface register */
-#define ES_1371_SRC_RAM_ADDRO(o) (((o)&0x7f)<<25) /* address of the sample rate converter */
+#define ES_1371_SRC_RAM_ADDRO(o) (((o)&0x7f)<<25)/* address of the sample rate converter */
#define ES_1371_SRC_RAM_ADDRM (0x7f<<25) /* mask for above */
-#define ES_1371_SRC_RAM_ADDRI(i) (((i)>>25)&0x7f) /* address of the sample rate converter */
+#define ES_1371_SRC_RAM_ADDRI(i) (((i)>>25)&0x7f)/* address of the sample rate converter */
#define ES_1371_SRC_RAM_WE (1<<24) /* R/W: read/write control for sample rate converter */
#define ES_1371_SRC_RAM_BUSY (1<<23) /* R/O: sample rate memory is busy */
#define ES_1371_SRC_DISABLE (1<<22) /* sample rate converter disable */
#define ES_1371_DIS_P1 (1<<21) /* playback channel 1 accumulator update disable */
#define ES_1371_DIS_P2 (1<<20) /* playback channel 1 accumulator update disable */
#define ES_1371_DIS_R1 (1<<19) /* capture channel accumulator update disable */
-#define ES_1371_SRC_RAM_DATAO(o) (((o)&0xffff)<<0) /* current value of the sample rate converter */
+#define ES_1371_SRC_RAM_DATAO(o) (((o)&0xffff)<<0)/* current value of the sample rate converter */
#define ES_1371_SRC_RAM_DATAM (0xffff<<0) /* mask for above */
-#define ES_1371_SRC_RAM_DATAI(i) (((i)>>0)&0xffff) /* current value of the sample rate converter */
+#define ES_1371_SRC_RAM_DATAI(i) (((i)>>0)&0xffff)/* current value of the sample rate converter */
#define ES_REG_1371_LEGACY 0x18 /* W/R: Legacy control/status register */
#define ES_1371_JFAST (1<<31) /* fast joystick timing */
#define ES_1371_HIB (1<<30) /* host interrupt blocking enable */
#define ES_1371_VSB (1<<29) /* SB; 0 = addr 0x220xH, 1 = 0x22FxH */
-#define ES_1371_VMPUO(o) (((o)&0x03)<<27) /* base register address; 0 = 0x320xH; 1 = 0x330xH; 2 = 0x340xH; 3 = 0x350xH */
+#define ES_1371_VMPUO(o) (((o)&0x03)<<27)/* base register address; 0 = 0x320xH; 1 = 0x330xH; 2 = 0x340xH; 3 = 0x350xH */
#define ES_1371_VMPUM (0x03<<27) /* mask for above */
-#define ES_1371_VMPUI(i) (((i)>>27)&0x03) /* base register address */
-#define ES_1371_VCDCO(o) (((o)&0x03)<<25) /* CODEC; 0 = 0x530xH; 1 = undefined; 2 = 0xe80xH; 3 = 0xF40xH */
+#define ES_1371_VMPUI(i) (((i)>>27)&0x03)/* base register address */
+#define ES_1371_VCDCO(o) (((o)&0x03)<<25)/* CODEC; 0 = 0x530xH; 1 = undefined; 2 = 0xe80xH; 3 = 0xF40xH */
#define ES_1371_VCDCM (0x03<<25) /* mask for above */
-#define ES_1371_VCDCI(i) (((i)>>25)&0x03) /* CODEC address */
+#define ES_1371_VCDCI(i) (((i)>>25)&0x03)/* CODEC address */
#define ES_1371_FIRQ (1<<24) /* force an interrupt */
#define ES_1371_SDMACAP (1<<23) /* enable event capture for slave DMA controller */
#define ES_1371_SPICAP (1<<22) /* enable event capture for slave IRQ controller */
@@ -223,36 +228,38 @@ MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
#define ES_1371_SVCAP (1<<18) /* enable event capture for SB registers */
#define ES_1371_CDCCAP (1<<17) /* enable event capture for CODEC registers */
#define ES_1371_BACAP (1<<16) /* enable event capture for SoundScape base address */
-#define ES_1371_EXI(i) (((i)>>8)&0x07) /* event number */
-#define ES_1371_AI(i) (((i)>>3)&0x1f) /* event significant I/O address */
+#define ES_1371_EXI(i) (((i)>>8)&0x07) /* event number */
+#define ES_1371_AI(i) (((i)>>3)&0x1f) /* event significant I/O address */
#define ES_1371_WR (1<<2) /* event capture; 0 = read; 1 = write */
#define ES_1371_LEGINT (1<<0) /* interrupt for legacy events; 0 = interrupt did occur */
+#define ES_REG_CHANNEL_STATUS 0x1c /* R/W: first 32-bits from S/PDIF channel status block, es1373 */
+
#define ES_REG_SERIAL 0x20 /* R/W: Serial interface control register */
#define ES_1371_DAC_TEST (1<<22) /* DAC test mode enable */
-#define ES_P2_END_INCO(o) (((o)&0x07)<<19) /* binary offset value to increment / loop end */
+#define ES_P2_END_INCO(o) (((o)&0x07)<<19)/* binary offset value to increment / loop end */
#define ES_P2_END_INCM (0x07<<19) /* mask for above */
-#define ES_P2_END_INCI(i) (((i)>>16)&0x07) /* binary offset value to increment / loop end */
-#define ES_P2_ST_INCO(o) (((o)&0x07)<<16) /* binary offset value to increment / start */
+#define ES_P2_END_INCI(i) (((i)>>16)&0x07)/* binary offset value to increment / loop end */
+#define ES_P2_ST_INCO(o) (((o)&0x07)<<16)/* binary offset value to increment / start */
#define ES_P2_ST_INCM (0x07<<16) /* mask for above */
-#define ES_P2_ST_INCI(i) (((i)<<16)&0x07) /* binary offset value to increment / start */
+#define ES_P2_ST_INCI(i) (((i)<<16)&0x07)/* binary offset value to increment / start */
#define ES_R1_LOOP_SEL (1<<15) /* ADC; 0 - loop mode; 1 = stop mode */
#define ES_P2_LOOP_SEL (1<<14) /* DAC2; 0 - loop mode; 1 = stop mode */
#define ES_P1_LOOP_SEL (1<<13) /* DAC1; 0 - loop mode; 1 = stop mode */
#define ES_P2_PAUSE (1<<12) /* DAC2; 0 - play mode; 1 = pause mode */
#define ES_P1_PAUSE (1<<11) /* DAC1; 0 - play mode; 1 = pause mode */
#define ES_R1_INT_EN (1<<10) /* ADC interrupt enable */
-#define ES_P2_INT_EN (1<<9) /* DAC2 interrupt enable */
-#define ES_P1_INT_EN (1<<8) /* DAC1 interrupt enable */
-#define ES_P1_SCT_RLD (1<<7) /* force sample counter reload for DAC1 */
-#define ES_P2_DAC_SEN (1<<6) /* when stop mode: 0 - DAC2 play back zeros; 1 = DAC2 play back last sample */
-#define ES_R1_MODEO(o) (((o)&0x03)<<4) /* ADC mode; 0 = 8-bit mono; 1 = 8-bit stereo; 2 = 16-bit mono; 3 = 16-bit stereo */
+#define ES_P2_INT_EN (1<<9) /* DAC2 interrupt enable */
+#define ES_P1_INT_EN (1<<8) /* DAC1 interrupt enable */
+#define ES_P1_SCT_RLD (1<<7) /* force sample counter reload for DAC1 */
+#define ES_P2_DAC_SEN (1<<6) /* when stop mode: 0 - DAC2 play back zeros; 1 = DAC2 play back last sample */
+#define ES_R1_MODEO(o) (((o)&0x03)<<4) /* ADC mode; 0 = 8-bit mono; 1 = 8-bit stereo; 2 = 16-bit mono; 3 = 16-bit stereo */
#define ES_R1_MODEM (0x03<<4) /* mask for above */
#define ES_R1_MODEI(i) (((i)>>4)&0x03)
-#define ES_P2_MODEO(o) (((o)&0x03)<<2) /* DAC2 mode; -- '' -- */
+#define ES_P2_MODEO(o) (((o)&0x03)<<2) /* DAC2 mode; -- '' -- */
#define ES_P2_MODEM (0x03<<2) /* mask for above */
#define ES_P2_MODEI(i) (((i)>>2)&0x03)
-#define ES_P1_MODEO(o) (((o)&0x03)<<0) /* DAC1 mode; -- '' -- */
+#define ES_P1_MODEO(o) (((o)&0x03)<<0) /* DAC1 mode; -- '' -- */
#define ES_P1_MODEM (0x03<<0) /* mask for above */
#define ES_P1_MODEI(i) (((i)>>0)&0x03)
@@ -386,6 +393,10 @@ struct _snd_ensoniq {
snd_rawmidi_substream_t *midi_input;
snd_rawmidi_substream_t *midi_output;
+ unsigned int spdif;
+ unsigned int spdif_default;
+ unsigned int spdif_stream;
+
snd_info_entry_t *proc_entry;
#ifdef CHIP1370
@@ -1032,6 +1043,10 @@ static int snd_ensoniq_playback1_open(snd_pcm_substream_t * substream)
ensoniq->playback1_substream = substream;
runtime->hw = snd_ensoniq_playback1;
snd_pcm_set_sync(substream);
+ spin_lock_irq(&ensoniq->reg_lock);
+ if (ensoniq->spdif && ensoniq->playback2_substream == NULL)
+ ensoniq->spdif_stream = ensoniq->spdif_default;
+ spin_unlock_irq(&ensoniq->reg_lock);
#ifdef CHIP1370
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
&snd_es1370_hw_constraints_rates);
@@ -1051,6 +1066,10 @@ static int snd_ensoniq_playback2_open(snd_pcm_substream_t * substream)
ensoniq->playback2_substream = substream;
runtime->hw = snd_ensoniq_playback2;
snd_pcm_set_sync(substream);
+ spin_lock_irq(&ensoniq->reg_lock);
+ if (ensoniq->spdif && ensoniq->playback1_substream == NULL)
+ ensoniq->spdif_stream = ensoniq->spdif_default;
+ spin_unlock_irq(&ensoniq->reg_lock);
#ifdef CHIP1370
snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
&snd_es1370_hw_constraints_clock);
@@ -1241,6 +1260,116 @@ static int __devinit snd_ensoniq_pcm2(ensoniq_t * ensoniq, int device, snd_pcm_t
#ifdef CHIP1371
+
+static int snd_ens1373_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
+ uinfo->count = 1;
+ return 0;
+}
+
+static int snd_ens1373_spdif_default_get(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ ensoniq_t *ensoniq = snd_kcontrol_chip(kcontrol);
+ spin_lock_irq(&ensoniq->reg_lock);
+ ucontrol->value.iec958.status[0] = (ensoniq->spdif_default >> 0) & 0xff;
+ ucontrol->value.iec958.status[1] = (ensoniq->spdif_default >> 8) & 0xff;
+ ucontrol->value.iec958.status[2] = (ensoniq->spdif_default >> 16) & 0xff;
+ ucontrol->value.iec958.status[3] = (ensoniq->spdif_default >> 24) & 0xff;
+ spin_unlock_irq(&ensoniq->reg_lock);
+ return 0;
+}
+
+static int snd_ens1373_spdif_default_put(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ ensoniq_t *ensoniq = snd_kcontrol_chip(kcontrol);
+ unsigned int val;
+ int change;
+
+ val = ((u32)ucontrol->value.iec958.status[0] << 0) |
+ ((u32)ucontrol->value.iec958.status[1] << 8) |
+ ((u32)ucontrol->value.iec958.status[2] << 16) |
+ ((u32)ucontrol->value.iec958.status[3] << 24);
+ spin_lock_irq(&ensoniq->reg_lock);
+ change = ensoniq->spdif_default != val;
+ ensoniq->spdif_default = val;
+ if (change && ensoniq->playback1_substream == NULL && ensoniq->playback2_substream == NULL)
+ outl(val, ES_REG(ensoniq, CHANNEL_STATUS));
+ spin_unlock_irq(&ensoniq->reg_lock);
+ return change;
+}
+
+static int snd_ens1373_spdif_mask_get(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ ucontrol->value.iec958.status[0] = 0xff;
+ ucontrol->value.iec958.status[1] = 0xff;
+ ucontrol->value.iec958.status[2] = 0xff;
+ ucontrol->value.iec958.status[3] = 0xff;
+ return 0;
+}
+
+static int snd_ens1373_spdif_stream_get(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ ensoniq_t *ensoniq = snd_kcontrol_chip(kcontrol);
+ spin_lock_irq(&ensoniq->reg_lock);
+ ucontrol->value.iec958.status[0] = (ensoniq->spdif_stream >> 0) & 0xff;
+ ucontrol->value.iec958.status[1] = (ensoniq->spdif_stream >> 8) & 0xff;
+ ucontrol->value.iec958.status[2] = (ensoniq->spdif_stream >> 16) & 0xff;
+ ucontrol->value.iec958.status[3] = (ensoniq->spdif_stream >> 24) & 0xff;
+ spin_unlock_irq(&ensoniq->reg_lock);
+ return 0;
+}
+
+static int snd_ens1373_spdif_stream_put(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ ensoniq_t *ensoniq = snd_kcontrol_chip(kcontrol);
+ unsigned int val;
+ int change;
+
+ val = ((u32)ucontrol->value.iec958.status[0] << 0) |
+ ((u32)ucontrol->value.iec958.status[1] << 8) |
+ ((u32)ucontrol->value.iec958.status[2] << 16) |
+ ((u32)ucontrol->value.iec958.status[3] << 24);
+ spin_lock_irq(&ensoniq->reg_lock);
+ change = ensoniq->spdif_stream != val;
+ ensoniq->spdif_stream = val;
+ if (change && (ensoniq->playback1_substream != NULL || ensoniq->playback2_substream != NULL))
+ outl(val, ES_REG(ensoniq, CHANNEL_STATUS));
+ spin_unlock_irq(&ensoniq->reg_lock);
+ return change;
+}
+
+static snd_kcontrol_new_t snd_ens1373_spdif_default __devinitdata =
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
+ .info = snd_ens1373_spdif_info,
+ .get = snd_ens1373_spdif_default_get,
+ .put = snd_ens1373_spdif_default_put,
+};
+
+static snd_kcontrol_new_t snd_ens1373_spdif_mask __devinitdata =
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
+ .info = snd_ens1373_spdif_info,
+ .get = snd_ens1373_spdif_mask_get
+};
+
+static snd_kcontrol_new_t snd_ens1373_spdif_stream __devinitdata =
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM),
+ .info = snd_ens1373_spdif_info,
+ .get = snd_ens1373_spdif_stream_get,
+ .put = snd_ens1373_spdif_stream_put
+};
+
#define ES1371_SPDIF(xname) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_es1371_spdif_info, \
.get = snd_es1371_spdif_get, .put = snd_es1371_spdif_put }
@@ -1257,32 +1386,30 @@ static int snd_es1371_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *
static int snd_es1371_spdif_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
ensoniq_t *ensoniq = snd_kcontrol_chip(kcontrol);
- unsigned long flags;
- spin_lock_irqsave(&ensoniq->reg_lock, flags);
- ucontrol->value.integer.value[0] = ensoniq->ctrl & ES_1371_SPDIF_EN ? 1 : 0;
- spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
+ spin_lock_irq(&ensoniq->reg_lock);
+ ucontrol->value.integer.value[0] = ensoniq->ctrl & ES_1373_SPDIF_THRU ? 1 : 0;
+ spin_unlock_irq(&ensoniq->reg_lock);
return 0;
}
static int snd_es1371_spdif_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
ensoniq_t *ensoniq = snd_kcontrol_chip(kcontrol);
- unsigned long flags;
unsigned int nval1, nval2;
int change;
- nval1 = ucontrol->value.integer.value[0] ? ES_1371_SPDIF_EN : 0;
- nval2 = ucontrol->value.integer.value[0] ? ES_1371_ST_SPDIF_EN : 0;
- spin_lock_irqsave(&ensoniq->reg_lock, flags);
- change = (ensoniq->ctrl & ES_1371_SPDIF_EN) != nval1;
- ensoniq->ctrl &= ~ES_1371_SPDIF_EN;
+ nval1 = ucontrol->value.integer.value[0] ? ES_1373_SPDIF_THRU : 0;
+ nval2 = ucontrol->value.integer.value[0] ? ES_1373_SPDIF_EN : 0;
+ spin_lock_irq(&ensoniq->reg_lock);
+ change = (ensoniq->ctrl & ES_1373_SPDIF_THRU) != nval1;
+ ensoniq->ctrl &= ~ES_1373_SPDIF_THRU;
ensoniq->ctrl |= nval1;
- ensoniq->cssr &= ~ES_1371_ST_SPDIF_EN;
+ ensoniq->cssr &= ~ES_1373_SPDIF_EN;
ensoniq->cssr |= nval2;
outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
outl(ensoniq->cssr, ES_REG(ensoniq, STATUS));
- spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
+ spin_unlock_irq(&ensoniq->reg_lock);
return change;
}
@@ -1299,7 +1426,7 @@ static struct {
unsigned short vid; /* vendor ID */
unsigned short did; /* device ID */
unsigned char rev; /* revision */
-} es1371_spdif_present[] = {
+} __devinitdata es1371_spdif_present[] = {
{ .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_C },
{ .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_D },
{ .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_E },
@@ -1325,9 +1452,29 @@ static int snd_ensoniq_1371_mixer(ensoniq_t * ensoniq)
if (ensoniq->pci->vendor == es1371_spdif_present[idx].vid &&
ensoniq->pci->device == es1371_spdif_present[idx].did &&
ensoniq->rev == es1371_spdif_present[idx].rev) {
- snd_kcontrol_t *kctl = snd_ctl_new1(&snd_es1371_mixer_spdif, ensoniq);
+ snd_kcontrol_t *kctl;
+ int index = 0;
+
+ ensoniq->spdif_default = ensoniq->spdif_stream = SNDRV_PCM_DEFAULT_CON_SPDIF;
+ outl(ensoniq->spdif_default, ES_REG(ensoniq, CHANNEL_STATUS));
+
if (ensoniq->u.es1371.ac97->ext_id & AC97_EI_SPDIF)
- kctl->id.index = 1;
+ index++;
+
+ kctl = snd_ctl_new1(&snd_es1371_mixer_spdif, ensoniq);
+ kctl->id.index = index;
+ snd_ctl_add(card, kctl);
+
+ kctl = snd_ctl_new1(&snd_ens1373_spdif_default, ensoniq);
+ kctl->id.index = index;
+ snd_ctl_add(card, kctl);
+
+ kctl = snd_ctl_new1(&snd_ens1373_spdif_mask, ensoniq);
+ kctl->id.index = index;
+ snd_ctl_add(card, kctl);
+
+ kctl = snd_ctl_new1(&snd_ens1373_spdif_stream, ensoniq);
+ kctl->id.index = index;
snd_ctl_add(card, kctl);
break;
}
diff --git a/sound/pci/ice1712/ak4524.c b/sound/pci/ice1712/ak4524.c
index bf0f0cdeb3bd..fe2e2a061de4 100644
--- a/sound/pci/ice1712/ak4524.c
+++ b/sound/pci/ice1712/ak4524.c
@@ -1,7 +1,7 @@
/*
* ALSA driver for ICEnsemble ICE1712 (Envy24)
*
- * AK4524 / AK4528 interface
+ * AK4524 / AK4528 / AK4529 interface
*
* Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz>
*
@@ -67,6 +67,7 @@ void snd_ice1712_ak4524_write(ice1712_t *ice, int chip,
addr &= 0x07;
/* build I2C address + data byte */
+ /* assume C1=1, C0=0 */
addrdata = 0xa000 | (addr << 8) | data;
for (idx = 15; idx >= 0; idx--) {
tmp &= ~(ak->data_mask | ak->clk_mask);
@@ -80,11 +81,13 @@ void snd_ice1712_ak4524_write(ice1712_t *ice, int chip,
udelay(1);
}
- if ((addr != 0x04 && addr != 0x05) || (data & 0x80) == 0)
- ak->images[chip][addr] = data;
- else
- ak->ipga_gain[chip][addr-4] = data;
-
+ if (ak->type == SND_AK4524) {
+ if ((addr != 0x04 && addr != 0x05) || (data & 0x80) == 0)
+ ak->images[chip][addr] = data;
+ else
+ ak->ipga_gain[chip][addr-4] = data;
+ }
+
if (ak->cs_mask == ak->cs_addr) {
if (ak->cif) {
/* assert a cs pulse to trigger */
@@ -112,16 +115,26 @@ void snd_ice1712_ak4524_reset(ice1712_t *ice, int state)
unsigned char reg;
ak4524_t *ak = &ice->ak4524;
- for (chip = 0; chip < ak->num_dacs/2; chip++) {
- snd_ice1712_ak4524_write(ice, chip, 0x01, state ? 0x00 : 0x03);
- if (state)
- continue;
- for (reg = 0x04; reg < (ak->is_ak4528 ? 0x06 : 0x08); reg++)
- snd_ice1712_ak4524_write(ice, chip, reg, ak->images[chip][reg]);
- if (ak->is_ak4528)
- continue;
- for (reg = 0x04; reg < 0x06; reg++)
- snd_ice1712_ak4524_write(ice, chip, reg, ak->ipga_gain[chip][reg-4]);
+ switch (ak->type) {
+ case SND_AK4524:
+ case SND_AK4528:
+ for (chip = 0; chip < ak->num_dacs/2; chip++) {
+ snd_ice1712_ak4524_write(ice, chip, 0x01, state ? 0x00 : 0x03);
+ if (state)
+ continue;
+ /* DAC volumes */
+ for (reg = 0x04; reg < (ak->type == SND_AK4528 ? 0x06 : 0x08); reg++)
+ snd_ice1712_ak4524_write(ice, chip, reg, ak->images[chip][reg]);
+ if (ak->type == SND_AK4528)
+ continue;
+ /* IPGA */
+ for (reg = 0x04; reg < 0x06; reg++)
+ snd_ice1712_ak4524_write(ice, chip, reg, ak->ipga_gain[chip][reg-4]);
+ }
+ break;
+ case SND_AK4529:
+ /* FIXME: needed for ak4529? */
+ break;
}
}
@@ -130,7 +143,7 @@ void snd_ice1712_ak4524_reset(ice1712_t *ice, int state)
*/
void __devinit snd_ice1712_ak4524_init(ice1712_t *ice)
{
- static unsigned char inits[] = {
+ static unsigned char inits_ak4524[] = {
0x00, 0x07, /* 0: all power up */
0x01, 0x00, /* 1: ADC/DAC reset */
0x02, 0x60, /* 2: 24bit I2S */
@@ -144,28 +157,68 @@ void __devinit snd_ice1712_ak4524_init(ice1712_t *ice)
0x07, 0x00, /* 7: DAC right muted */
0xff, 0xff
};
- int chip, idx;
- unsigned char *ptr, reg, data;
+ static unsigned char inits_ak4528[] = {
+ 0x00, 0x07, /* 0: all power up */
+ 0x01, 0x00, /* 1: ADC/DAC reset */
+ 0x02, 0x60, /* 2: 24bit I2S */
+ 0x03, 0x0d, /* 3: deemphasis off, turn LR highpass filters on */
+ 0x01, 0x03, /* 1: ADC/DAC enable */
+ 0x04, 0x00, /* 4: ADC left muted */
+ 0x05, 0x00, /* 5: ADC right muted */
+ 0xff, 0xff
+ };
+ static unsigned char inits_ak4529[] = {
+ 0x09, 0x01, /* 9: ATS=0, RSTN=1 */
+ 0x0a, 0x3f, /* A: all power up, no zero/overflow detection */
+ 0x00, 0x08, /* 0: TDM=0, 24bit I2S, SMUTE=0 */
+ 0x01, 0x00, /* 1: ACKS=0, ADC, loop off */
+ 0x02, 0xff, /* 2: LOUT1 muted */
+ 0x03, 0xff, /* 3: ROUT1 muted */
+ 0x04, 0xff, /* 4: LOUT2 muted */
+ 0x05, 0xff, /* 5: ROUT2 muted */
+ 0x06, 0xff, /* 6: LOUT3 muted */
+ 0x07, 0xff, /* 7: ROUT3 muted */
+ 0x0b, 0xff, /* B: LOUT4 muted */
+ 0x0c, 0xff, /* C: ROUT4 muted */
+ 0x08, 0x55, /* 8: deemphasis all off */
+ 0xff, 0xff
+ };
+ int chip, num_chips;
+ unsigned char *ptr, reg, data, *inits;
ak4524_t *ak = &ice->ak4524;
- for (chip = idx = 0; chip < ak->num_dacs/2; chip++) {
+ switch (ak->type) {
+ case SND_AK4524:
+ inits = inits_ak4524;
+ num_chips = ak->num_dacs / 2;
+ break;
+ case SND_AK4528:
+ inits = inits_ak4528;
+ num_chips = ak->num_dacs / 2;
+ break;
+ case SND_AK4529:
+ default:
+ inits = inits_ak4529;
+ num_chips = 1;
+ break;
+ }
+
+ for (chip = 0; chip < num_chips; chip++) {
ptr = inits;
while (*ptr != 0xff) {
reg = *ptr++;
data = *ptr++;
- if (ak->is_ak4528) {
- if (reg > 5)
- continue;
- if (reg >= 4 && (data & 0x80))
- continue;
- }
- if (reg == 0x03 && ak->is_ak4528)
- data = 0x0d; /* deemphasis off, turn LR highpass filters on */
snd_ice1712_ak4524_write(ice, chip, reg, data);
}
}
}
+
+#define AK_GET_CHIP(val) (((val) >> 8) & 0xff)
+#define AK_GET_ADDR(val) ((val) & 0xff)
+#define AK_GET_SHIFT(val) (((val) >> 16) & 0xff)
+#define AK_COMPOSE(chip,addr,shift) (((chip) << 8) | (addr) | ((shift) << 16))
+
static int snd_ice1712_ak4524_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
@@ -178,8 +231,8 @@ static int snd_ice1712_ak4524_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem
static int snd_ice1712_ak4524_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
{
ice1712_t *ice = snd_kcontrol_chip(kcontrol);
- int chip = kcontrol->private_value / 8;
- int addr = kcontrol->private_value % 8;
+ int chip = AK_GET_CHIP(kcontrol->private_value);
+ int addr = AK_GET_ADDR(kcontrol->private_value);
ucontrol->value.integer.value[0] = ice->ak4524.images[chip][addr];
return 0;
}
@@ -187,8 +240,8 @@ static int snd_ice1712_ak4524_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_
static int snd_ice1712_ak4524_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
{
ice1712_t *ice = snd_kcontrol_chip(kcontrol);
- int chip = kcontrol->private_value / 8;
- int addr = kcontrol->private_value % 8;
+ int chip = AK_GET_CHIP(kcontrol->private_value);
+ int addr = AK_GET_ADDR(kcontrol->private_value);
unsigned char nval = ucontrol->value.integer.value[0];
int change = ice->ak4524.images[chip][addr] != nval;
if (change)
@@ -208,8 +261,8 @@ static int snd_ice1712_ak4524_ipga_gain_info(snd_kcontrol_t *kcontrol, snd_ctl_e
static int snd_ice1712_ak4524_ipga_gain_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
{
ice1712_t *ice = snd_kcontrol_chip(kcontrol);
- int chip = kcontrol->private_value / 8;
- int addr = kcontrol->private_value % 8;
+ int chip = AK_GET_CHIP(kcontrol->private_value);
+ int addr = AK_GET_ADDR(kcontrol->private_value);
ucontrol->value.integer.value[0] = ice->ak4524.ipga_gain[chip][addr-4] & 0x7f;
return 0;
}
@@ -217,8 +270,8 @@ static int snd_ice1712_ak4524_ipga_gain_get(snd_kcontrol_t *kcontrol, snd_ctl_el
static int snd_ice1712_ak4524_ipga_gain_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
{
ice1712_t *ice = snd_kcontrol_chip(kcontrol);
- int chip = kcontrol->private_value / 8;
- int addr = kcontrol->private_value % 8;
+ int chip = AK_GET_CHIP(kcontrol->private_value);
+ int addr = AK_GET_ADDR(kcontrol->private_value);
unsigned char nval = (ucontrol->value.integer.value[0] % 37) | 0x80;
int change = ice->ak4524.ipga_gain[chip][addr] != nval;
if (change)
@@ -243,21 +296,26 @@ static int snd_ice1712_ak4524_deemphasis_info(snd_kcontrol_t *kcontrol, snd_ctl_
static int snd_ice1712_ak4524_deemphasis_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
{
ice1712_t *ice = snd_kcontrol_chip(kcontrol);
- int chip = kcontrol->id.index;
- ucontrol->value.enumerated.item[0] = ice->ak4524.images[chip][3] & 3;
+ int chip = AK_GET_CHIP(kcontrol->private_value);
+ int addr = AK_GET_ADDR(kcontrol->private_value);
+ int shift = AK_GET_SHIFT(kcontrol->private_value);
+ ucontrol->value.enumerated.item[0] = (ice->ak4524.images[chip][addr] >> shift) & 3;
return 0;
}
static int snd_ice1712_ak4524_deemphasis_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
{
ice1712_t *ice = snd_kcontrol_chip(kcontrol);
- int chip = kcontrol->id.index;
- unsigned char nval = ucontrol->value.enumerated.item[0];
+ int chip = AK_GET_CHIP(kcontrol->private_value);
+ int addr = AK_GET_ADDR(kcontrol->private_value);
+ int shift = AK_GET_SHIFT(kcontrol->private_value);
+ unsigned char nval = ucontrol->value.enumerated.item[0] & 3;
int change;
- nval |= (nval & 3) | (ice->ak4524.images[chip][3] & ~3);
- change = ice->ak4524.images[chip][3] != nval;
+
+ nval = (nval << shift) | (ice->ak4524.images[chip][addr] & ~(3 << shift));
+ change = ice->ak4524.images[chip][addr] != nval;
if (change)
- snd_ice1712_ak4524_write(ice, chip, 3, nval);
+ snd_ice1712_ak4524_write(ice, chip, addr, nval);
return change;
}
@@ -280,15 +338,24 @@ int __devinit snd_ice1712_ak4524_build_controls(ice1712_t *ice)
ctl.access = SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE;
ctl.get = snd_ice1712_ak4524_volume_get;
ctl.put = snd_ice1712_ak4524_volume_put;
- if (ak->is_ak4528)
- ctl.private_value = (idx / 2) * 8 + (idx % 2) + 4; /* register 4 & 5 */
- else
- ctl.private_value = (idx / 2) * 8 + (idx % 2) + 6; /* register 6 & 7 */
+ switch (ak->type) {
+ case SND_AK4524:
+ ctl.private_value = AK_COMPOSE(idx/2, (idx%2) + 6, 0); /* register 6 & 7 */
+ break;
+ case SND_AK4528:
+ ctl.private_value = AK_COMPOSE(idx/2, (idx%2) + 4, 0); /* register 4 & 5 */
+ break;
+ case SND_AK4529: {
+ int val = idx < 6 ? idx + 2 : (idx - 6) + 0xb; /* registers 2-7 and b,c */
+ ctl.private_value = AK_COMPOSE(0, val, 0);
+ break;
+ }
+ }
ctl.private_data = ice;
if ((err = snd_ctl_add(ice->card, snd_ctl_new(&ctl))) < 0)
return err;
}
- for (idx = 0; idx < ak->num_adcs && !ak->is_ak4528; ++idx) {
+ for (idx = 0; idx < ak->num_adcs && ak->type == SND_AK4524; ++idx) {
snd_kcontrol_t ctl;
memset(&ctl, 0, sizeof(ctl));
strcpy(ctl.id.name, "ADC Volume");
@@ -298,7 +365,7 @@ int __devinit snd_ice1712_ak4524_build_controls(ice1712_t *ice)
ctl.access = SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE;
ctl.get = snd_ice1712_ak4524_volume_get;
ctl.put = snd_ice1712_ak4524_volume_put;
- ctl.private_value = (idx / 2) * 8 + (idx % 2) + 4; /* register 4 & 5 */
+ ctl.private_value = AK_COMPOSE(idx/2, (idx%2) + 4, 0); /* register 4 & 5 */
ctl.private_data = ice;
if ((err = snd_ctl_add(ice->card, snd_ctl_new(&ctl))) < 0)
return err;
@@ -310,7 +377,7 @@ int __devinit snd_ice1712_ak4524_build_controls(ice1712_t *ice)
ctl.access = SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE;
ctl.get = snd_ice1712_ak4524_ipga_gain_get;
ctl.put = snd_ice1712_ak4524_ipga_gain_put;
- ctl.private_value = (idx / 2) * 8 + (idx % 2) + 4; /* register 4 & 5 */
+ ctl.private_value = AK_COMPOSE(idx/2, (idx%2) + 4, 0); /* register 4 & 5 */
ctl.private_data = ice;
if ((err = snd_ctl_add(ice->card, snd_ctl_new(&ctl))) < 0)
return err;
@@ -325,6 +392,17 @@ int __devinit snd_ice1712_ak4524_build_controls(ice1712_t *ice)
ctl.access = SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE;
ctl.get = snd_ice1712_ak4524_deemphasis_get;
ctl.put = snd_ice1712_ak4524_deemphasis_put;
+ switch (ak->type) {
+ case SND_AK4524:
+ case SND_AK4528:
+ ctl.private_value = AK_COMPOSE(idx, 3, 0); /* register 3 */
+ break;
+ case SND_AK4529: {
+ int shift = idx == 3 ? 6 : (2 - idx) * 2;
+ ctl.private_value = AK_COMPOSE(0, 8, shift); /* register 8 with shift */
+ break;
+ }
+ }
ctl.private_data = ice;
if ((err = snd_ctl_add(ice->card, snd_ctl_new(&ctl))) < 0)
return err;
diff --git a/sound/pci/ice1712/delta.c b/sound/pci/ice1712/delta.c
index 46a293aba458..e4518ddab848 100644
--- a/sound/pci/ice1712/delta.c
+++ b/sound/pci/ice1712/delta.c
@@ -337,6 +337,9 @@ static int __devinit snd_ice1712_delta_init(ice1712_t *ice)
case ICE1712_SUBDEVICE_AUDIOPHILE:
ice->num_total_dacs = 2;
break;
+ case ICE1712_SUBDEVICE_DELTA410:
+ ice->num_total_dacs = 8;
+ break;
case ICE1712_SUBDEVICE_DELTA44:
case ICE1712_SUBDEVICE_DELTA66:
ice->num_total_dacs = ice->omni ? 8 : 4;
@@ -350,6 +353,7 @@ static int __devinit snd_ice1712_delta_init(ice1712_t *ice)
/* initialize spdif */
switch (ice->eeprom.subvendor) {
case ICE1712_SUBDEVICE_AUDIOPHILE:
+ case ICE1712_SUBDEVICE_DELTA410:
case ICE1712_SUBDEVICE_DELTA1010LT:
if ((err = snd_i2c_bus_create(ice->card, "ICE1712 GPIO 1", NULL, &ice->i2c)) < 0) {
snd_printk("unable to create I2C bus\n");
@@ -378,12 +382,17 @@ static int __devinit snd_ice1712_delta_init(ice1712_t *ice)
ak = &ice->ak4524;
switch (ice->eeprom.subvendor) {
case ICE1712_SUBDEVICE_AUDIOPHILE:
+ case ICE1712_SUBDEVICE_DELTA410:
ak->num_adcs = ak->num_dacs = 2;
- ak->is_ak4528 = 1;
- ak->cif = 0; /* the default level of the CIF pin from AK4524 */
+ ak->type = SND_AK4528;
+ if (ice->eeprom.subvendor == ICE1712_SUBDEVICE_DELTA410) {
+ ak->num_dacs = 8;
+ ak->type = SND_AK4529;
+ }
+ ak->cif = 0; /* the default level of the CIF pin from AK4528/4529 */
ak->data_mask = ICE1712_DELTA_AP_DOUT;
ak->clk_mask = ICE1712_DELTA_AP_CCLK;
- ak->cs_mask = ak->cs_addr = ICE1712_DELTA_AP_CS_CODEC; /* select AK4528 codec */
+ ak->cs_mask = ak->cs_addr = ICE1712_DELTA_AP_CS_CODEC; /* select AK4528/4529 codec */
ak->cs_none = 0;
ak->add_flags = ICE1712_DELTA_AP_CS_DIGITAL; /* assert digital high */
ak->mask_flags = 0;
@@ -392,6 +401,7 @@ static int __devinit snd_ice1712_delta_init(ice1712_t *ice)
break;
case ICE1712_SUBDEVICE_DELTA1010LT:
ak->num_adcs = ak->num_dacs = 8;
+ ak->type = SND_AK4524;
ak->cif = 0; /* the default level of the CIF pin from AK4524 */
ak->data_mask = ICE1712_DELTA_1010LT_DOUT;
ak->clk_mask = ICE1712_DELTA_1010LT_CCLK;
@@ -406,6 +416,7 @@ static int __devinit snd_ice1712_delta_init(ice1712_t *ice)
case ICE1712_SUBDEVICE_DELTA66:
case ICE1712_SUBDEVICE_DELTA44:
ak->num_adcs = ak->num_dacs = 4;
+ ak->type = SND_AK4524;
ak->cif = 0; /* the default level of the CIF pin from AK4524 */
ak->data_mask = ICE1712_DELTA_CODEC_SERIAL_DATA;
ak->clk_mask = ICE1712_DELTA_CODEC_SERIAL_CLOCK;
@@ -471,6 +482,8 @@ static int __devinit snd_ice1712_delta_add_controls(ice1712_t *ice)
case ICE1712_SUBDEVICE_DELTADIO2496:
case ICE1712_SUBDEVICE_DELTA66:
case ICE1712_SUBDEVICE_AUDIOPHILE:
+ case ICE1712_SUBDEVICE_DELTA410:
+ case ICE1712_SUBDEVICE_DELTA1010LT:
err = snd_ice1712_spdif_build_controls(ice);
if (err < 0)
return err;
@@ -492,6 +505,7 @@ static int __devinit snd_ice1712_delta_add_controls(ice1712_t *ice)
switch (ice->eeprom.subvendor) {
case ICE1712_SUBDEVICE_DELTA1010LT:
case ICE1712_SUBDEVICE_AUDIOPHILE:
+ case ICE1712_SUBDEVICE_DELTA410:
case ICE1712_SUBDEVICE_DELTA44:
case ICE1712_SUBDEVICE_DELTA66:
err = snd_ice1712_ak4524_build_controls(ice);
@@ -539,6 +553,12 @@ struct snd_ice1712_card_info snd_ice1712_delta_cards[] __devinitdata = {
snd_ice1712_delta_add_controls,
},
{
+ ICE1712_SUBDEVICE_DELTA410,
+ "M Audio Delta 410",
+ snd_ice1712_delta_init,
+ snd_ice1712_delta_add_controls,
+ },
+ {
ICE1712_SUBDEVICE_DELTA1010LT,
"M Audio Delta 1010LT",
snd_ice1712_delta_init,
diff --git a/sound/pci/ice1712/delta.h b/sound/pci/ice1712/delta.h
index edae9fbcf224..dc8a3a61428d 100644
--- a/sound/pci/ice1712/delta.h
+++ b/sound/pci/ice1712/delta.h
@@ -37,6 +37,7 @@
#define ICE1712_SUBDEVICE_DELTA66 0x121432d6
#define ICE1712_SUBDEVICE_DELTA44 0x121433d6
#define ICE1712_SUBDEVICE_AUDIOPHILE 0x121434d6
+#define ICE1712_SUBDEVICE_DELTA410 0x121438d6
#define ICE1712_SUBDEVICE_DELTA1010LT 0x12143bd6
/* entry point */
@@ -106,7 +107,8 @@ extern struct snd_ice1712_card_info snd_ice1712_delta_cards[];
/* 0x40 = CODEC_CHIP_A */
/* 0x80 = CODEC_CHIP_B */
-/* MidiMan M-Audio Audiophile definitions */
+/* MidiMan M-Audio Audiophile/Delta410 definitions */
+/* thanks to Kristof Pelckmans <Kristof.Pelckmans@antwerpen.be> for Delta410 info */
/* 0x01 = DFS */
#define ICE1712_DELTA_AP_CCLK 0x02 /* SPI clock */
/* (clocking on rising edge - 0->1) */
@@ -114,7 +116,7 @@ extern struct snd_ice1712_card_info snd_ice1712_delta_cards[];
#define ICE1712_DELTA_AP_DOUT 0x08 /* data output */
#define ICE1712_DELTA_AP_CS_DIGITAL 0x10 /* CS8427 chip select */
/* low signal = select */
-#define ICE1712_DELTA_AP_CS_CODEC 0x20 /* AK4528 chip select */
+#define ICE1712_DELTA_AP_CS_CODEC 0x20 /* AK4528 (audiophile), AK4529 (Delta410) chip select */
/* low signal = select */
/* MidiMan M-Audio Delta1010LT definitions */
diff --git a/sound/pci/ice1712/ews.c b/sound/pci/ice1712/ews.c
index 230731ad8a14..2195982175a0 100644
--- a/sound/pci/ice1712/ews.c
+++ b/sound/pci/ice1712/ews.c
@@ -406,6 +406,7 @@ static int __devinit snd_ice1712_ews_init(ice1712_t *ice)
switch (ice->eeprom.subvendor) {
case ICE1712_SUBDEVICE_EWS88MT:
ak->num_adcs = ak->num_dacs = 8;
+ ak->type = SND_AK4524;
ak->cif = 1; /* CIF high */
ak->data_mask = ICE1712_EWS88_SERIAL_DATA;
ak->clk_mask = ICE1712_EWS88_SERIAL_CLOCK;
@@ -418,6 +419,7 @@ static int __devinit snd_ice1712_ews_init(ice1712_t *ice)
break;
case ICE1712_SUBDEVICE_EWX2496:
ak->num_adcs = ak->num_dacs = 2;
+ ak->type = SND_AK4524;
ak->cif = 1; /* CIF high */
ak->data_mask = ICE1712_EWS88_SERIAL_DATA;
ak->clk_mask = ICE1712_EWS88_SERIAL_CLOCK;
@@ -430,6 +432,7 @@ static int __devinit snd_ice1712_ews_init(ice1712_t *ice)
break;
case ICE1712_SUBDEVICE_DMX6FIRE:
ak->num_adcs = ak->num_dacs = 6;
+ ak->type = SND_AK4524;
ak->cif = 1; /* CIF high */
ak->data_mask = ICE1712_6FIRE_SERIAL_DATA;
ak->clk_mask = ICE1712_6FIRE_SERIAL_CLOCK;
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c
index 2e7f439874b2..e1dba1ddbfcb 100644
--- a/sound/pci/ice1712/ice1712.c
+++ b/sound/pci/ice1712/ice1712.c
@@ -1532,7 +1532,7 @@ static snd_kcontrol_new_t snd_ice1712_eeprom __devinitdata = {
/*
*/
-static int snd_ice1712_spdif_default_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_ice1712_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
uinfo->count = 1;
@@ -1559,20 +1559,13 @@ static int snd_ice1712_spdif_default_put(snd_kcontrol_t * kcontrol,
static snd_kcontrol_new_t snd_ice1712_spdif_default __devinitdata =
{
- .iface = SNDRV_CTL_ELEM_IFACE_PCM,
- .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
- .info = snd_ice1712_spdif_default_info,
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
+ .info = snd_ice1712_spdif_info,
.get = snd_ice1712_spdif_default_get,
.put = snd_ice1712_spdif_default_put
};
-static int snd_ice1712_spdif_mask_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
- uinfo->count = 1;
- return 0;
-}
-
static int snd_ice1712_spdif_maskc_get(snd_kcontrol_t * kcontrol,
snd_ctl_elem_value_t * ucontrol)
{
@@ -1617,29 +1610,22 @@ static int snd_ice1712_spdif_maskp_get(snd_kcontrol_t * kcontrol,
static snd_kcontrol_new_t snd_ice1712_spdif_maskc __devinitdata =
{
- .access = SNDRV_CTL_ELEM_ACCESS_READ,
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
- .info = snd_ice1712_spdif_mask_info,
+ .access = SNDRV_CTL_ELEM_ACCESS_READ,
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
+ .info = snd_ice1712_spdif_info,
.get = snd_ice1712_spdif_maskc_get,
};
static snd_kcontrol_new_t snd_ice1712_spdif_maskp __devinitdata =
{
- .access = SNDRV_CTL_ELEM_ACCESS_READ,
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK),
- .info = snd_ice1712_spdif_mask_info,
+ .access = SNDRV_CTL_ELEM_ACCESS_READ,
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK),
+ .info = snd_ice1712_spdif_info,
.get = snd_ice1712_spdif_maskp_get,
};
-static int snd_ice1712_spdif_stream_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
- uinfo->count = 1;
- return 0;
-}
-
static int snd_ice1712_spdif_stream_get(snd_kcontrol_t * kcontrol,
snd_ctl_elem_value_t * ucontrol)
{
@@ -1660,10 +1646,10 @@ static int snd_ice1712_spdif_stream_put(snd_kcontrol_t * kcontrol,
static snd_kcontrol_new_t snd_ice1712_spdif_stream __devinitdata =
{
- .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
- .iface = SNDRV_CTL_ELEM_IFACE_PCM,
- .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM),
- .info = snd_ice1712_spdif_stream_info,
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM),
+ .info = snd_ice1712_spdif_info,
.get = snd_ice1712_spdif_stream_get,
.put = snd_ice1712_spdif_stream_put
};
diff --git a/sound/pci/ice1712/ice1712.h b/sound/pci/ice1712/ice1712.h
index d530dd64d629..3d6ae77c1d62 100644
--- a/sound/pci/ice1712/ice1712.h
+++ b/sound/pci/ice1712/ice1712.h
@@ -239,10 +239,12 @@ typedef struct {
struct snd_ak4524 {
int num_adcs; /* AK4524 or AK4528 ADCs */
int num_dacs; /* AK4524 or AK4528 DACs */
- unsigned char images[4][8];
+ unsigned char images[4][16];
unsigned char ipga_gain[4][2];
/* */
- unsigned int is_ak4528: 1; /* AK4524 or AK4528 */
+ enum {
+ SND_AK4524, SND_AK4528, SND_AK4529
+ } type;
unsigned int cif: 1;
unsigned char data_mask;
unsigned char clk_mask;
diff --git a/sound/pci/rme9652/hammerfall_mem.c b/sound/pci/rme9652/hammerfall_mem.c
index 747e9d7cf2be..2705ca915220 100644
--- a/sound/pci/rme9652/hammerfall_mem.c
+++ b/sound/pci/rme9652/hammerfall_mem.c
@@ -25,7 +25,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- $Id: hammerfall_mem.c,v 1.4 2002/10/21 18:28:25 perex Exp $
+ $Id: hammerfall_mem.c,v 1.5 2002/11/04 09:11:42 perex Exp $
Tue Oct 17 2000 Jaroslav Kysela <perex@suse.cz>
@@ -34,7 +34,6 @@
*/
-#include <linux/config.h>
#include <linux/version.h>
#include <linux/module.h>
#include <linux/pci.h>
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c
index b7cb6b04aaac..3cff7ac49a53 100644
--- a/sound/pci/via82xx.c
+++ b/sound/pci/via82xx.c
@@ -201,11 +201,16 @@ typedef struct {
} viadev_t;
+/*
+ * allocate and initialize the descriptor buffers
+ * periods = number of periods
+ * fragsize = period size in bytes
+ */
static int build_via_table(viadev_t *dev, snd_pcm_substream_t *substream,
- struct pci_dev *pci)
+ struct pci_dev *pci,
+ int periods, int fragsize)
{
- int i, idx, ofs, rest, fragsize;
- snd_pcm_runtime_t *runtime = substream->runtime;
+ int i, idx, ofs, rest;
struct snd_sg_buf *sgbuf = snd_magic_cast(snd_pcm_sgbuf_t, substream->dma_private, return -EINVAL);
if (! dev->table) {
@@ -223,10 +228,9 @@ static int build_via_table(viadev_t *dev, snd_pcm_substream_t *substream,
}
/* fill the entries */
- fragsize = snd_pcm_lib_period_bytes(substream);
idx = 0;
ofs = 0;
- for (i = 0; i < runtime->periods; i++) {
+ for (i = 0; i < periods; i++) {
rest = fragsize;
/* fill descriptors for a period.
* a period can be split to several descriptors if it's
@@ -241,7 +245,7 @@ static int build_via_table(viadev_t *dev, snd_pcm_substream_t *substream,
r = rest;
rest -= r;
if (! rest) {
- if (i == runtime->periods - 1)
+ if (i == periods - 1)
flag = VIA_TBL_BIT_EOL; /* buffer boundary */
else
flag = VIA_TBL_BIT_FLAG; /* period boundary */
@@ -472,19 +476,14 @@ static int snd_via82xx_trigger(via82xx_t *chip, viadev_t *viadev, int cmd)
}
-static int snd_via82xx_setup_periods(via82xx_t *chip, viadev_t *viadev,
- snd_pcm_substream_t *substream)
+static int snd_via82xx_set_format(via82xx_t *chip, viadev_t *viadev,
+ snd_pcm_substream_t *substream)
{
snd_pcm_runtime_t *runtime = substream->runtime;
unsigned long port = chip->port + viadev->reg_offset;
- int err;
snd_via82xx_channel_reset(chip, viadev);
- err = build_via_table(viadev, substream, chip->pci);
- if (err < 0)
- return err;
-
outl((u32)viadev->table_addr, port + VIA_REG_OFFSET_TABLE_PTR);
switch (chip->chip_type) {
case TYPE_VIA686:
@@ -583,11 +582,28 @@ static int snd_via82xx_capture_trigger(snd_pcm_substream_t * substream,
static int snd_via82xx_hw_params(snd_pcm_substream_t * substream,
snd_pcm_hw_params_t * hw_params)
{
- return snd_pcm_sgbuf_alloc(substream, params_buffer_bytes(hw_params));
+ via82xx_t *chip = snd_pcm_substream_chip(substream);
+ viadev_t *viadev = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? &chip->playback : &chip->capture;
+ int err;
+
+ err = snd_pcm_sgbuf_alloc(substream, params_buffer_bytes(hw_params));
+ if (err < 0)
+ return err;
+ err = build_via_table(viadev, substream, chip->pci,
+ params_periods(hw_params),
+ params_period_bytes(hw_params));
+ if (err < 0)
+ return err;
+ return err;
}
static int snd_via82xx_hw_free(snd_pcm_substream_t * substream)
{
+ via82xx_t *chip = snd_pcm_substream_chip(substream);
+ viadev_t *viadev = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? &chip->playback : &chip->capture;
+
+ clean_via_table(viadev, substream, chip->pci);
+ snd_pcm_sgbuf_free(substream);
return 0;
}
@@ -606,7 +622,7 @@ static int snd_via82xx_playback_prepare(snd_pcm_substream_t * substream)
tmp = inl(VIAREG(chip, PLAYBACK_STOP_IDX)) & ~0xfffff;
outl(tmp | (0xffff * runtime->rate)/(48000/16), VIAREG(chip, PLAYBACK_STOP_IDX));
}
- return snd_via82xx_setup_periods(chip, &chip->playback, substream);
+ return snd_via82xx_set_format(chip, &chip->playback, substream);
}
static int snd_via82xx_capture_prepare(snd_pcm_substream_t * substream)
@@ -617,7 +633,7 @@ static int snd_via82xx_capture_prepare(snd_pcm_substream_t * substream)
snd_ac97_set_rate(chip->ac97, AC97_PCM_LR_ADC_RATE, runtime->rate);
if (chip->chip_type == TYPE_VIA8233)
outb(VIA_REG_CAPTURE_FIFO_ENABLE, VIAREG(chip, CAPTURE_FIFO));
- return snd_via82xx_setup_periods(chip, &chip->capture, substream);
+ return snd_via82xx_set_format(chip, &chip->capture, substream);
}
static inline unsigned int snd_via82xx_cur_ptr(via82xx_t *chip, viadev_t *viadev)
@@ -761,20 +777,16 @@ static int snd_via82xx_capture_open(snd_pcm_substream_t * substream)
static int snd_via82xx_playback_close(snd_pcm_substream_t * substream)
{
via82xx_t *chip = snd_pcm_substream_chip(substream);
-
- clean_via_table(&chip->playback, substream, chip->pci);
- snd_pcm_sgbuf_delete(substream);
chip->playback.substream = NULL;
+ snd_pcm_sgbuf_delete(substream);
return 0;
}
static int snd_via82xx_capture_close(snd_pcm_substream_t * substream)
{
via82xx_t *chip = snd_pcm_substream_chip(substream);
-
- clean_via_table(&chip->capture, substream, chip->pci);
- snd_pcm_sgbuf_delete(substream);
chip->capture.substream = NULL;
+ snd_pcm_sgbuf_delete(substream);
return 0;
}
diff --git a/sound/sparc/amd7930.c b/sound/sparc/amd7930.c
index f4c34e0318bb..6922201b7bf5 100644
--- a/sound/sparc/amd7930.c
+++ b/sound/sparc/amd7930.c
@@ -29,7 +29,6 @@
* --- End of notes from Thoamas's original driver ---
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index 24c693642b65..d18451343ddf 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -935,7 +935,8 @@ static int set_format(snd_usb_substream_t *subs, snd_pcm_runtime_t *runtime)
struct usb_device *dev = subs->dev;
struct usb_host_config *config = dev->actconfig;
struct usb_host_interface *alts;
- struct usb_interface *iface;
+ struct usb_interface_descriptor *altsd;
+ struct usb_interface *iface;
struct audioformat *fmt;
unsigned int ep, attr;
unsigned char data[3];
@@ -951,7 +952,8 @@ static int set_format(snd_usb_substream_t *subs, snd_pcm_runtime_t *runtime)
iface = &config->interface[fmt->iface];
alts = &iface->altsetting[fmt->altset_idx];
- snd_assert(alts->desc.bAlternateSetting == fmt->altsetting, return -EINVAL);
+ altsd = get_iface_desc(alts);
+ snd_assert(altsd->bAlternateSetting == fmt->altsetting, return -EINVAL);
/* close the old interface */
if (subs->interface >= 0 && subs->interface != fmt->iface) {
@@ -973,31 +975,31 @@ static int set_format(snd_usb_substream_t *subs, snd_pcm_runtime_t *runtime)
}
/* create a data pipe */
- ep = alts->endpoint[0].desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+ ep = get_endpoint(alts, 0)->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
if (is_playback)
subs->datapipe = usb_sndisocpipe(dev, ep);
else
subs->datapipe = usb_rcvisocpipe(dev, ep);
subs->syncpipe = subs->syncinterval = 0;
- subs->maxpacksize = alts->endpoint[0].desc.wMaxPacketSize;
+ subs->maxpacksize = get_endpoint(alts, 0)->wMaxPacketSize;
subs->maxframesize = bytes_to_frames(runtime, subs->maxpacksize);
subs->fill_max = 0;
/* we need a sync pipe in async OUT or adaptive IN mode */
- attr = alts->endpoint[0].desc.bmAttributes & EP_ATTR_MASK;
+ attr = get_endpoint(alts, 0)->bmAttributes & EP_ATTR_MASK;
if ((is_playback && attr == EP_ATTR_ASYNC) ||
(! is_playback && attr == EP_ATTR_ADAPTIVE)) {
/* check endpoint */
- if (alts->desc.bNumEndpoints < 2 ||
- alts->endpoint[1].desc.bmAttributes != 0x01 ||
- alts->endpoint[1].desc.bSynchAddress != 0) {
+ if (altsd->bNumEndpoints < 2 ||
+ get_endpoint(alts, 1)->bmAttributes != 0x01 ||
+ get_endpoint(alts, 1)->bSynchAddress != 0) {
snd_printk(KERN_ERR "%d:%d:%d : invalid synch pipe\n",
dev->devnum, fmt->iface, fmt->altsetting);
return -EINVAL;
}
- ep = alts->endpoint[1].desc.bEndpointAddress;
- if ((is_playback && ep != (alts->endpoint[0].desc.bSynchAddress | USB_DIR_IN)) ||
- (! is_playback && ep != (alts->endpoint[0].desc.bSynchAddress & ~USB_DIR_IN))) {
+ ep = get_endpoint(alts, 1)->bEndpointAddress;
+ if ((is_playback && ep != (get_endpoint(alts, 0)->bSynchAddress | USB_DIR_IN)) ||
+ (! is_playback && ep != (get_endpoint(alts, 0)->bSynchAddress & ~USB_DIR_IN))) {
snd_printk(KERN_ERR "%d:%d:%d : invalid synch pipe\n",
dev->devnum, fmt->iface, fmt->altsetting);
return -EINVAL;
@@ -1007,10 +1009,10 @@ static int set_format(snd_usb_substream_t *subs, snd_pcm_runtime_t *runtime)
subs->syncpipe = usb_rcvisocpipe(dev, ep);
else
subs->syncpipe = usb_sndisocpipe(dev, ep);
- subs->syncinterval = alts->endpoint[1].desc.bRefresh;
+ subs->syncinterval = get_endpoint(alts, 1)->bRefresh;
}
- ep = alts->endpoint[0].desc.bEndpointAddress;
+ ep = get_endpoint(alts, 0)->bEndpointAddress;
/* if endpoint has pitch control, enable it */
if (fmt->attributes & EP_CS_ATTR_PITCH_CONTROL) {
data[0] = 1;
@@ -1676,6 +1678,7 @@ static int parse_audio_endpoints(snd_usb_audio_t *chip, unsigned char *buffer, i
struct usb_host_config *config;
struct usb_interface *iface;
struct usb_host_interface *alts;
+ struct usb_interface_descriptor *altsd;
int i, altno, err, stream;
int channels, nr_rates, pcm_format, format;
struct audioformat *fp;
@@ -1688,19 +1691,20 @@ static int parse_audio_endpoints(snd_usb_audio_t *chip, unsigned char *buffer, i
iface = &config->interface[iface_no];
for (i = 0; i < iface->num_altsetting; i++) {
alts = &iface->altsetting[i];
+ altsd = get_iface_desc(alts);
/* skip invalid one */
- if (alts->desc.bInterfaceClass != USB_CLASS_AUDIO ||
- alts->desc.bInterfaceSubClass != USB_SUBCLASS_AUDIO_STREAMING ||
- alts->desc.bNumEndpoints < 1)
+ if (altsd->bInterfaceClass != USB_CLASS_AUDIO ||
+ altsd->bInterfaceSubClass != USB_SUBCLASS_AUDIO_STREAMING ||
+ altsd->bNumEndpoints < 1)
continue;
/* must be isochronous */
- if ((alts->endpoint[0].desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) !=
+ if ((get_endpoint(alts, 0)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) !=
USB_ENDPOINT_XFER_ISOC)
continue;
/* check direction */
- stream = (alts->endpoint[0].desc.bEndpointAddress & USB_DIR_IN) ?
+ stream = (get_endpoint(alts, 0)->bEndpointAddress & USB_DIR_IN) ?
SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
- altno = alts->desc.bAlternateSetting;
+ altno = altsd->bAlternateSetting;
/* get audio formats */
fmt = snd_usb_find_csint_desc(buffer, buflen, NULL, AS_GENERAL, iface_no, altno);
@@ -1767,8 +1771,8 @@ static int parse_audio_endpoints(snd_usb_audio_t *chip, unsigned char *buffer, i
fp->altsetting = altno;
fp->altset_idx = i;
fp->format = pcm_format;
- fp->endpoint = alts->endpoint[0].desc.bEndpointAddress;
- fp->ep_attr = alts->endpoint[0].desc.bmAttributes;
+ fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress;
+ fp->ep_attr = get_endpoint(alts, 0)->bmAttributes;
fp->channels = channels;
fp->attributes = csep[3];
@@ -1857,8 +1861,10 @@ static int snd_usb_create_streams(snd_usb_audio_t *chip, int ctrlif,
*/
config = dev->actconfig;
for (i = 0; i < p1[7]; i++) {
+ struct usb_host_interface *alts;
+ struct usb_interface_descriptor *altsd;
j = p1[8 + i];
- if (j >= config->desc.bNumInterfaces) {
+ if (j >= get_cfg_desc(config)->bNumInterfaces) {
snd_printk(KERN_ERR "%d:%u:%d : does not exist\n",
dev->devnum, ctrlif, j);
continue;
@@ -1868,8 +1874,10 @@ static int snd_usb_create_streams(snd_usb_audio_t *chip, int ctrlif,
snd_printdd(KERN_INFO "%d:%d:%d: skipping, already claimed\n", dev->devnum, ctrlif, j);
continue;
}
- if (iface->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO &&
- iface->altsetting[0].desc.bInterfaceSubClass == USB_SUBCLASS_MIDI_STREAMING) {
+ alts = &iface->altsetting[0];
+ altsd = get_iface_desc(alts);
+ if (altsd->bInterfaceClass == USB_CLASS_AUDIO &&
+ altsd->bInterfaceSubClass == USB_SUBCLASS_MIDI_STREAMING) {
if (snd_usb_create_midi_interface(chip, iface, NULL) < 0) {
snd_printk(KERN_ERR "%d:%u:%d: cannot create sequencer device\n", dev->devnum, ctrlif, j);
continue;
@@ -1877,9 +1885,9 @@ static int snd_usb_create_streams(snd_usb_audio_t *chip, int ctrlif,
usb_driver_claim_interface(&usb_audio_driver, iface, (void *)-1);
continue;
}
- if (iface->altsetting[0].desc.bInterfaceClass != USB_CLASS_AUDIO ||
- iface->altsetting[0].desc.bInterfaceSubClass != USB_SUBCLASS_AUDIO_STREAMING) {
- snd_printdd(KERN_ERR "%d:%u:%d: skipping non-supported interface %d\n", dev->devnum, ctrlif, j, iface->altsetting[0].desc.bInterfaceClass);
+ if (altsd->bInterfaceClass != USB_CLASS_AUDIO ||
+ altsd->bInterfaceSubClass != USB_SUBCLASS_AUDIO_STREAMING) {
+ snd_printdd(KERN_ERR "%d:%u:%d: skipping non-supported interface %d\n", dev->devnum, ctrlif, j, altsd->bInterfaceClass);
/* skip non-supported classes */
continue;
}
@@ -1941,7 +1949,7 @@ static int snd_usb_roland_ua100_hack(snd_usb_audio_t *chip)
struct usb_interface *iface;
int err;
- if (cfg->desc.bNumInterfaces != 3) {
+ if (get_cfg_desc(cfg)->bNumInterfaces != 3) {
snd_printdd(KERN_ERR "invalid UA-100 descriptor\n");
return -ENXIO;
}
@@ -2134,18 +2142,22 @@ static void *snd_usb_audio_probe(struct usb_device *dev,
struct usb_interface *intf,
const struct usb_device_id *usb_id)
{
- struct usb_host_config *config = dev->actconfig;
+ struct usb_host_config *config = dev->actconfig;
const snd_usb_audio_quirk_t *quirk = (const snd_usb_audio_quirk_t *)usb_id->driver_info;
int i;
snd_card_t *card;
snd_usb_audio_t *chip;
- int ifnum = intf->altsetting->desc.bInterfaceNumber;
+ struct usb_host_interface *alts;
+ int ifnum;
+
+ alts = &intf->altsetting[0];
+ ifnum = get_iface_desc(alts)->bInterfaceNumber;
if (quirk && quirk->ifnum != QUIRK_ANY_INTERFACE && ifnum != quirk->ifnum)
goto __err_val;
- if (usb_set_configuration(dev, config->desc.bConfigurationValue) < 0) {
- snd_printk(KERN_ERR "cannot set configuration (value 0x%x)\n", config->desc.bConfigurationValue);
+ if (usb_set_configuration(dev, get_cfg_desc(config)->bConfigurationValue) < 0) {
+ snd_printk(KERN_ERR "cannot set configuration (value 0x%x)\n", get_cfg_desc(config)->bConfigurationValue);
goto __err_val;
}
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index 868143cd4f47..1f70895ea831 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -191,4 +191,15 @@ int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif, unsigned char *buffe
int snd_usb_create_midi_interface(snd_usb_audio_t *chip, struct usb_interface *iface, const snd_usb_audio_quirk_t *quirk);
+/*
+ * retrieve usb_interface descriptor from the host interface
+ * (conditional for compatibility with the older API)
+ */
+#ifndef get_iface_desc
+#define get_iface_desc(iface) (&iface->desc)
+#define get_endpoint(alt,ep) (&(alt)->endpoint[ep].desc)
+#define get_ep_desc(ep) (&(ep)->desc)
+#define get_cfg_desc(cfg) (&(cfg)->desc)
+#endif
+
#endif /* __USBAUDIO_H */
diff --git a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c
index f26b2069e5b2..4e75e1c102ec 100644
--- a/sound/usb/usbmidi.c
+++ b/sound/usb/usbmidi.c
@@ -515,7 +515,8 @@ static void snd_usbmidi_in_endpoint_delete(snd_usb_midi_in_endpoint_t* ep)
static struct usb_endpoint_descriptor* snd_usbmidi_get_int_epd(snd_usb_midi_t* umidi)
{
struct usb_interface* intf;
- struct usb_host_interface* intfd;
+ struct usb_host_interface *hostif;
+ struct usb_interface_descriptor* intfd;
if (umidi->chip->dev->descriptor.idVendor != 0x0582)
return NULL;
@@ -523,29 +524,37 @@ static struct usb_endpoint_descriptor* snd_usbmidi_get_int_epd(snd_usb_midi_t* u
if (!intf || intf->num_altsetting != 2)
return NULL;
- intfd = &intf->altsetting[0];
- if (intfd->desc.bNumEndpoints != 2 ||
- (intfd->endpoint[0].desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK ||
- (intfd->endpoint[1].desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK)
+ hostif = &intf->altsetting[0];
+ intfd = get_iface_desc(hostif);
+ if (intfd->bNumEndpoints != 2 ||
+ (get_endpoint(hostif, 0)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK ||
+ (get_endpoint(hostif, 1)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK)
return NULL;
- intfd = &intf->altsetting[1];
- if (intfd->desc.bNumEndpoints != 2 ||
- (intfd->endpoint[0].desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK ||
- (intfd->endpoint[1].desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT)
+ hostif = &intf->altsetting[1];
+ intfd = get_iface_desc(hostif);
+ if (intfd->bNumEndpoints != 2 ||
+ (get_endpoint(hostif, 0)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK ||
+ (get_endpoint(hostif, 1)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT)
return NULL;
- usb_set_interface(umidi->chip->dev, intfd->desc.bInterfaceNumber,
- intfd->desc.bAlternateSetting);
- return &intfd->endpoint[1].desc;
+ usb_set_interface(umidi->chip->dev, intfd->bInterfaceNumber,
+ intfd->bAlternateSetting);
+ return get_endpoint(hostif, 1);
}
static struct usb_endpoint_descriptor* snd_usbmidi_get_midiman_int_epd(snd_usb_midi_t* umidi)
{
struct usb_interface* intf = umidi->iface;
- if (!intf || intf->altsetting[0].desc.bNumEndpoints < 1)
+ struct usb_host_interface *hostif;
+ struct usb_interface_descriptor *intfd;
+ if (!intf)
+ return NULL;
+ hostif = &intf->altsetting[0];
+ intfd = get_iface_desc(hostif);
+ if (intfd->bNumEndpoints < 1)
return NULL;
- return &intf->altsetting[0].endpoint[0].desc;
+ return get_endpoint(hostif, 0);
}
/*
@@ -772,18 +781,21 @@ static int snd_usbmidi_get_ms_info(snd_usb_midi_t* umidi,
snd_usb_midi_endpoint_info_t* endpoints)
{
struct usb_interface* intf;
- struct usb_host_interface* intfd;
+ struct usb_host_interface *hostif;
+ struct usb_interface_descriptor* intfd;
struct usb_ms_header_descriptor* ms_header;
- struct usb_host_endpoint* ep;
+ struct usb_host_endpoint *hostep;
+ struct usb_endpoint_descriptor* ep;
struct usb_ms_endpoint_descriptor* ms_ep;
int i, epidx;
intf = umidi->iface;
if (!intf)
return -ENXIO;
- intfd = &intf->altsetting[0];
- ms_header = (struct usb_ms_header_descriptor*)intfd->extra;
- if (intfd->extralen >= 7 &&
+ hostif = &intf->altsetting[0];
+ intfd = get_iface_desc(hostif);
+ ms_header = (struct usb_ms_header_descriptor*)hostif->extra;
+ if (hostif->extralen >= 7 &&
ms_header->bLength >= 7 &&
ms_header->bDescriptorType == USB_DT_CS_INTERFACE &&
ms_header->bDescriptorSubtype == HEADER)
@@ -793,33 +805,34 @@ static int snd_usbmidi_get_ms_info(snd_usb_midi_t* umidi,
printk(KERN_WARNING "snd-usb-midi: MIDIStreaming interface descriptor not found\n");
epidx = 0;
- for (i = 0; i < intfd->desc.bNumEndpoints; ++i) {
- ep = &intfd->endpoint[i];
- if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK)
+ for (i = 0; i < intfd->bNumEndpoints; ++i) {
+ hostep = &hostif->endpoint[i];
+ ep = get_ep_desc(hostep);
+ if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK)
continue;
- ms_ep = (struct usb_ms_endpoint_descriptor*)ep->extra;
- if (ep->extralen < 4 ||
+ ms_ep = (struct usb_ms_endpoint_descriptor*)hostep->extra;
+ if (hostep->extralen < 4 ||
ms_ep->bLength < 4 ||
ms_ep->bDescriptorType != USB_DT_CS_ENDPOINT ||
ms_ep->bDescriptorSubtype != MS_GENERAL)
continue;
if (endpoints[epidx].epnum != 0 &&
- endpoints[epidx].epnum != (ep->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK)) {
+ endpoints[epidx].epnum != (ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK)) {
++epidx;
if (epidx >= MIDI_MAX_ENDPOINTS) {
printk(KERN_WARNING "snd-usb-midi: too many endpoints\n");
break;
}
}
- endpoints[epidx].epnum = ep->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
- if (ep->desc.bEndpointAddress & USB_DIR_IN) {
+ endpoints[epidx].epnum = ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+ if (ep->bEndpointAddress & USB_DIR_IN) {
endpoints[epidx].in_cables = (1 << ms_ep->bNumEmbMIDIJack) - 1;
} else {
endpoints[epidx].out_cables = (1 << ms_ep->bNumEmbMIDIJack) - 1;
}
printk(KERN_INFO "snd-usb-midi: detected %d %s jack(s) on endpoint %d\n",
ms_ep->bNumEmbMIDIJack,
- ep->desc.bEndpointAddress & USB_DIR_IN ? "input" : "output",
+ ep->bEndpointAddress & USB_DIR_IN ? "input" : "output",
endpoints[epidx].epnum);
}
return 0;
@@ -833,17 +846,19 @@ static int snd_usbmidi_detect_endpoint(snd_usb_midi_t* umidi,
snd_usb_midi_endpoint_info_t* endpoint)
{
struct usb_interface* intf;
- struct usb_host_interface* intfd;
+ struct usb_host_interface *hostif;
+ struct usb_interface_descriptor* intfd;
struct usb_endpoint_descriptor* epd;
if (endpoint->epnum == -1) {
intf = umidi->iface;
if (!intf || intf->num_altsetting < 1)
return -ENOENT;
- intfd = intf->altsetting;
- if (intfd->desc.bNumEndpoints < 1)
+ hostif = intf->altsetting;
+ intfd = get_iface_desc(hostif);
+ if (intfd->bNumEndpoints < 1)
return -ENOENT;
- epd = &intfd->endpoint [0].desc;
+ epd = get_endpoint(hostif, 0);
endpoint->epnum = epd->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
}
return 0;
@@ -856,18 +871,20 @@ static int snd_usbmidi_detect_yamaha(snd_usb_midi_t* umidi,
snd_usb_midi_endpoint_info_t* endpoint)
{
struct usb_interface* intf;
- struct usb_host_interface* intfd;
+ struct usb_host_interface *hostif;
+ struct usb_interface_descriptor* intfd;
uint8_t* cs_desc;
intf = umidi->iface;
if (!intf)
return -ENOENT;
- intfd = intf->altsetting;
- if (intfd->desc.bNumEndpoints < 1)
+ hostif = intf->altsetting;
+ intfd = get_iface_desc(hostif);
+ if (intfd->bNumEndpoints < 1)
return -ENOENT;
- for (cs_desc = intfd->extra;
- cs_desc < intfd->extra + intfd->extralen && cs_desc[0] >= 2;
+ for (cs_desc = hostif->extra;
+ cs_desc < hostif->extra + hostif->extralen && cs_desc[0] >= 2;
cs_desc += cs_desc[0]) {
if (cs_desc[1] == CS_AUDIO_INTERFACE) {
if (cs_desc[2] == MIDI_IN_JACK)
@@ -890,33 +907,35 @@ static int snd_usbmidi_create_endpoints_midiman(snd_usb_midi_t* umidi, int ports
{
snd_usb_midi_endpoint_info_t ep_info;
struct usb_interface* intf;
- struct usb_host_interface* intfd;
+ struct usb_host_interface *hostif;
+ struct usb_interface_descriptor* intfd;
struct usb_endpoint_descriptor* epd;
int cable, err;
intf = umidi->iface;
if (!intf)
return -ENOENT;
- intfd = intf->altsetting;
- if (intfd->desc.bNumEndpoints < (ports > 1 ? 5 : 3)) {
+ hostif = intf->altsetting;
+ intfd = get_iface_desc(hostif);
+ if (intfd->bNumEndpoints < (ports > 1 ? 5 : 3)) {
snd_printdd(KERN_ERR "not enough endpoints\n");
return -ENOENT;
}
- epd = &intfd->endpoint[0].desc;
+ epd = get_endpoint(hostif, 0);
if ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) != USB_DIR_IN ||
(epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT) {
snd_printdd(KERN_ERR "endpoint[0] isn't interrupt\n");
return -ENXIO;
}
- epd = &intfd->endpoint[2].desc;
+ epd = get_endpoint(hostif, 2);
if ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) != USB_DIR_OUT ||
(epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK) {
snd_printdd(KERN_ERR "endpoint[2] isn't bulk output\n");
return -ENXIO;
}
if (ports > 1) {
- epd = &intfd->endpoint[4].desc;
+ epd = get_endpoint(hostif, 4);
if ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) != USB_DIR_OUT ||
(epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK) {
snd_printdd(KERN_ERR "endpoint[4] isn't bulk output\n");
@@ -924,13 +943,13 @@ static int snd_usbmidi_create_endpoints_midiman(snd_usb_midi_t* umidi, int ports
}
}
- ep_info.epnum = intfd->endpoint[2].desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+ ep_info.epnum = get_endpoint(hostif, 2)->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
ep_info.out_cables = 0x5555 & ((1 << ports) - 1);
err = snd_usbmidi_out_endpoint_create(umidi, &ep_info, &umidi->endpoints[0]);
if (err < 0)
return err;
- ep_info.epnum = intfd->endpoint[0].desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+ ep_info.epnum = get_endpoint(hostif, 0)->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
ep_info.in_cables = (1 << ports) - 1;
err = snd_usbmidi_in_endpoint_create(umidi, &ep_info, &umidi->endpoints[0]);
if (err < 0)
@@ -938,7 +957,7 @@ static int snd_usbmidi_create_endpoints_midiman(snd_usb_midi_t* umidi, int ports
umidi->endpoints[0].in->urb->complete = snd_usbmidi_in_midiman_complete;
if (ports > 1) {
- ep_info.epnum = intfd->endpoint[4].desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+ ep_info.epnum = get_endpoint(hostif, 4)->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
ep_info.out_cables = 0xaaaa & ((1 << ports) - 1);
err = snd_usbmidi_out_endpoint_create(umidi, &ep_info, &umidi->endpoints[1]);
if (err < 0)