提交 2fe9f798 编写于 作者: L Linus Torvalds

Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6

...@@ -42,19 +42,15 @@ ...@@ -42,19 +42,15 @@
* executing (see inherit_locked_prom_mappings() rant). * executing (see inherit_locked_prom_mappings() rant).
*/ */
sparc64_vpte_nucleus: sparc64_vpte_nucleus:
/* Load 0xf0000000, which is LOW_OBP_ADDRESS. */ /* Note that kvmap below has verified that the address is
mov 0xf, %g5 * in the range MODULES_VADDR --> VMALLOC_END already. So
sllx %g5, 28, %g5 * here we need only check if it is an OBP address or not.
*/
/* Is addr >= LOW_OBP_ADDRESS? */ sethi %hi(LOW_OBP_ADDRESS), %g5
cmp %g4, %g5 cmp %g4, %g5
blu,pn %xcc, sparc64_vpte_patchme1 blu,pn %xcc, sparc64_vpte_patchme1
mov 0x1, %g5 mov 0x1, %g5
/* Load 0x100000000, which is HI_OBP_ADDRESS. */
sllx %g5, 32, %g5 sllx %g5, 32, %g5
/* Is addr < HI_OBP_ADDRESS? */
cmp %g4, %g5 cmp %g4, %g5
blu,pn %xcc, obp_iaddr_patch blu,pn %xcc, obp_iaddr_patch
nop nop
...@@ -156,26 +152,29 @@ obp_daddr_patch: ...@@ -156,26 +152,29 @@ obp_daddr_patch:
* rather, use information saved during inherit_prom_mappings() using 8k * rather, use information saved during inherit_prom_mappings() using 8k
* pagesize. * pagesize.
*/ */
.align 32
kvmap: kvmap:
/* Load 0xf0000000, which is LOW_OBP_ADDRESS. */ sethi %hi(MODULES_VADDR), %g5
mov 0xf, %g5 cmp %g4, %g5
sllx %g5, 28, %g5 blu,pn %xcc, longpath
mov (VMALLOC_END >> 24), %g5
sllx %g5, 24, %g5
cmp %g4, %g5
bgeu,pn %xcc, longpath
nop
/* Is addr >= LOW_OBP_ADDRESS? */ kvmap_check_obp:
sethi %hi(LOW_OBP_ADDRESS), %g5
cmp %g4, %g5 cmp %g4, %g5
blu,pn %xcc, vmalloc_addr blu,pn %xcc, kvmap_vmalloc_addr
mov 0x1, %g5 mov 0x1, %g5
/* Load 0x100000000, which is HI_OBP_ADDRESS. */
sllx %g5, 32, %g5 sllx %g5, 32, %g5
/* Is addr < HI_OBP_ADDRESS? */
cmp %g4, %g5 cmp %g4, %g5
blu,pn %xcc, obp_daddr_patch blu,pn %xcc, obp_daddr_patch
nop nop
vmalloc_addr: kvmap_vmalloc_addr:
/* If we get here, a vmalloc addr accessed, load kernel VPTE. */ /* If we get here, a vmalloc addr was accessed, load kernel VPTE. */
ldxa [%g3 + %g6] ASI_N, %g5 ldxa [%g3 + %g6] ASI_N, %g5
brgez,pn %g5, longpath brgez,pn %g5, longpath
nop nop
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include <asm/psrcompat.h> #include <asm/psrcompat.h>
#include <asm/visasm.h> #include <asm/visasm.h>
#include <asm/spitfire.h> #include <asm/spitfire.h>
#include <asm/page.h>
/* Returning from ptrace is a bit tricky because the syscall return /* Returning from ptrace is a bit tricky because the syscall return
* low level code assumes any value returned which is negative and * low level code assumes any value returned which is negative and
...@@ -128,20 +129,20 @@ void flush_ptrace_access(struct vm_area_struct *vma, struct page *page, ...@@ -128,20 +129,20 @@ void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
* is mapped to in the user's address space, we can skip the * is mapped to in the user's address space, we can skip the
* D-cache flush. * D-cache flush.
*/ */
if ((uaddr ^ kaddr) & (1UL << 13)) { if ((uaddr ^ (unsigned long) kaddr) & (1UL << 13)) {
unsigned long start = __pa(kaddr); unsigned long start = __pa(kaddr);
unsigned long end = start + len; unsigned long end = start + len;
if (tlb_type == spitfire) { if (tlb_type == spitfire) {
for (; start < end; start += 32) for (; start < end; start += 32)
spitfire_put_dcache_tag(va & 0x3fe0, 0x0); spitfire_put_dcache_tag(start & 0x3fe0, 0x0);
} else { } else {
for (; start < end; start += 32) for (; start < end; start += 32)
__asm__ __volatile__( __asm__ __volatile__(
"stxa %%g0, [%0] %1\n\t" "stxa %%g0, [%0] %1\n\t"
"membar #Sync" "membar #Sync"
: /* no outputs */ : /* no outputs */
: "r" (va), : "r" (start),
"i" (ASI_DCACHE_INVALIDATE)); "i" (ASI_DCACHE_INVALIDATE));
} }
} }
......
...@@ -17,7 +17,7 @@ kernel_unaligned_trap_fault: ...@@ -17,7 +17,7 @@ kernel_unaligned_trap_fault:
__do_int_store: __do_int_store:
rd %asi, %o4 rd %asi, %o4
wr %o3, 0, %asi wr %o3, 0, %asi
ldx [%o2], %g3 mov %o2, %g3
cmp %o1, 2 cmp %o1, 2
be,pn %icc, 2f be,pn %icc, 2f
cmp %o1, 4 cmp %o1, 4
......
...@@ -184,13 +184,14 @@ extern void do_int_load(unsigned long *dest_reg, int size, ...@@ -184,13 +184,14 @@ extern void do_int_load(unsigned long *dest_reg, int size,
unsigned long *saddr, int is_signed, int asi); unsigned long *saddr, int is_signed, int asi);
extern void __do_int_store(unsigned long *dst_addr, int size, extern void __do_int_store(unsigned long *dst_addr, int size,
unsigned long *src_val, int asi); unsigned long src_val, int asi);
static inline void do_int_store(int reg_num, int size, unsigned long *dst_addr, static inline void do_int_store(int reg_num, int size, unsigned long *dst_addr,
struct pt_regs *regs, int asi) struct pt_regs *regs, int asi, int orig_asi)
{ {
unsigned long zero = 0; unsigned long zero = 0;
unsigned long *src_val = &zero; unsigned long *src_val_p = &zero;
unsigned long src_val;
if (size == 16) { if (size == 16) {
size = 8; size = 8;
...@@ -198,7 +199,25 @@ static inline void do_int_store(int reg_num, int size, unsigned long *dst_addr, ...@@ -198,7 +199,25 @@ static inline void do_int_store(int reg_num, int size, unsigned long *dst_addr,
(unsigned)fetch_reg(reg_num, regs) : 0)) << 32) | (unsigned)fetch_reg(reg_num, regs) : 0)) << 32) |
(unsigned)fetch_reg(reg_num + 1, regs); (unsigned)fetch_reg(reg_num + 1, regs);
} else if (reg_num) { } else if (reg_num) {
src_val = fetch_reg_addr(reg_num, regs); src_val_p = fetch_reg_addr(reg_num, regs);
}
src_val = *src_val_p;
if (unlikely(asi != orig_asi)) {
switch (size) {
case 2:
src_val = swab16(src_val);
break;
case 4:
src_val = swab32(src_val);
break;
case 8:
src_val = swab64(src_val);
break;
case 16:
default:
BUG();
break;
};
} }
__do_int_store(dst_addr, size, src_val, asi); __do_int_store(dst_addr, size, src_val, asi);
} }
...@@ -276,6 +295,7 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn, u ...@@ -276,6 +295,7 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn, u
kernel_mna_trap_fault(); kernel_mna_trap_fault();
} else { } else {
unsigned long addr; unsigned long addr;
int orig_asi, asi;
addr = compute_effective_address(regs, insn, addr = compute_effective_address(regs, insn,
((insn >> 25) & 0x1f)); ((insn >> 25) & 0x1f));
...@@ -285,18 +305,48 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn, u ...@@ -285,18 +305,48 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn, u
regs->tpc, dirstrings[dir], addr, size, regs->tpc, dirstrings[dir], addr, size,
regs->u_regs[UREG_RETPC]); regs->u_regs[UREG_RETPC]);
#endif #endif
orig_asi = asi = decode_asi(insn, regs);
switch (asi) {
case ASI_NL:
case ASI_AIUPL:
case ASI_AIUSL:
case ASI_PL:
case ASI_SL:
case ASI_PNFL:
case ASI_SNFL:
asi &= ~0x08;
break;
};
switch (dir) { switch (dir) {
case load: case load:
do_int_load(fetch_reg_addr(((insn>>25)&0x1f), regs), do_int_load(fetch_reg_addr(((insn>>25)&0x1f), regs),
size, (unsigned long *) addr, size, (unsigned long *) addr,
decode_signedness(insn), decode_signedness(insn), asi);
decode_asi(insn, regs)); if (unlikely(asi != orig_asi)) {
unsigned long val_in = *(unsigned long *) addr;
switch (size) {
case 2:
val_in = swab16(val_in);
break;
case 4:
val_in = swab32(val_in);
break;
case 8:
val_in = swab64(val_in);
break;
case 16:
default:
BUG();
break;
};
*(unsigned long *) addr = val_in;
}
break; break;
case store: case store:
do_int_store(((insn>>25)&0x1f), size, do_int_store(((insn>>25)&0x1f), size,
(unsigned long *) addr, regs, (unsigned long *) addr, regs,
decode_asi(insn, regs)); asi, orig_asi);
break; break;
default: default:
......
...@@ -174,7 +174,7 @@ int atyfb_xl_init(struct fb_info *info) ...@@ -174,7 +174,7 @@ int atyfb_xl_init(struct fb_info *info)
const struct xl_card_cfg_t * card = &card_cfg[xl_card]; const struct xl_card_cfg_t * card = &card_cfg[xl_card];
struct atyfb_par *par = (struct atyfb_par *) info->par; struct atyfb_par *par = (struct atyfb_par *) info->par;
union aty_pll pll; union aty_pll pll;
int i, err; int err;
u32 temp; u32 temp;
aty_st_8(CONFIG_STAT0, 0x85, par); aty_st_8(CONFIG_STAT0, 0x85, par);
...@@ -252,9 +252,12 @@ int atyfb_xl_init(struct fb_info *info) ...@@ -252,9 +252,12 @@ int atyfb_xl_init(struct fb_info *info)
aty_st_le32(0xEC, 0x00000000, par); aty_st_le32(0xEC, 0x00000000, par);
aty_st_le32(0xFC, 0x00000000, par); aty_st_le32(0xFC, 0x00000000, par);
#if defined (CONFIG_FB_ATY_GENERIC_LCD)
int i;
for (i=0; i<sizeof(lcd_tbl)/sizeof(lcd_tbl_t); i++) { for (i=0; i<sizeof(lcd_tbl)/sizeof(lcd_tbl_t); i++) {
aty_st_lcd(lcd_tbl[i].lcd_reg, lcd_tbl[i].val, par); aty_st_lcd(lcd_tbl[i].lcd_reg, lcd_tbl[i].val, par);
} }
#endif
aty_st_le16(CONFIG_STAT0, 0x00A4, par); aty_st_le16(CONFIG_STAT0, 0x00A4, par);
mdelay(10); mdelay(10);
......
...@@ -4,13 +4,6 @@ ...@@ -4,13 +4,6 @@
#include <linux/config.h> #include <linux/config.h>
#include <asm/page.h> #include <asm/page.h>
/* Flushing for D-cache alias handling is only needed if
* the page size is smaller than 16K.
*/
#if PAGE_SHIFT < 14
#define DCACHE_ALIASING_POSSIBLE
#endif
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#include <linux/mm.h> #include <linux/mm.h>
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <asm/io.h> #include <asm/io.h>
#include <asm/spitfire.h> #include <asm/spitfire.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <asm/page.h>
#ifndef MAX_HWIFS #ifndef MAX_HWIFS
# ifdef CONFIG_BLK_DEV_IDEPCI # ifdef CONFIG_BLK_DEV_IDEPCI
......
...@@ -21,6 +21,13 @@ ...@@ -21,6 +21,13 @@
#define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT) #define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT)
#define PAGE_MASK (~(PAGE_SIZE-1)) #define PAGE_MASK (~(PAGE_SIZE-1))
/* Flushing for D-cache alias handling is only needed if
* the page size is smaller than 16K.
*/
#if PAGE_SHIFT < 14
#define DCACHE_ALIASING_POSSIBLE
#endif
#ifdef __KERNEL__ #ifdef __KERNEL__
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <asm/spitfire.h> #include <asm/spitfire.h>
#include <asm/cpudata.h> #include <asm/cpudata.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <asm/page.h>
/* Page table allocation/freeing. */ /* Page table allocation/freeing. */
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
......
...@@ -24,21 +24,23 @@ ...@@ -24,21 +24,23 @@
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/const.h> #include <asm/const.h>
/* The kernel image occupies 0x4000000 to 0x1000000 (4MB --> 16MB). /* The kernel image occupies 0x4000000 to 0x1000000 (4MB --> 32MB).
* The page copy blockops use 0x1000000 to 0x18000000 (16MB --> 24MB). * The page copy blockops can use 0x2000000 to 0x10000000.
* The PROM resides in an area spanning 0xf0000000 to 0x100000000. * The PROM resides in an area spanning 0xf0000000 to 0x100000000.
* The vmalloc area spans 0x140000000 to 0x200000000. * The vmalloc area spans 0x100000000 to 0x200000000.
* Since modules need to be in the lowest 32-bits of the address space,
* we place them right before the OBP area from 0x10000000 to 0xf0000000.
* There is a single static kernel PMD which maps from 0x0 to address * There is a single static kernel PMD which maps from 0x0 to address
* 0x400000000. * 0x400000000.
*/ */
#define TLBTEMP_BASE _AC(0x0000000001000000,UL) #define TLBTEMP_BASE _AC(0x0000000002000000,UL)
#define MODULES_VADDR _AC(0x0000000002000000,UL) #define MODULES_VADDR _AC(0x0000000010000000,UL)
#define MODULES_LEN _AC(0x000000007e000000,UL) #define MODULES_LEN _AC(0x00000000e0000000,UL)
#define MODULES_END _AC(0x0000000080000000,UL) #define MODULES_END _AC(0x00000000f0000000,UL)
#define VMALLOC_START _AC(0x0000000140000000,UL)
#define VMALLOC_END _AC(0x0000000200000000,UL)
#define LOW_OBP_ADDRESS _AC(0x00000000f0000000,UL) #define LOW_OBP_ADDRESS _AC(0x00000000f0000000,UL)
#define HI_OBP_ADDRESS _AC(0x0000000100000000,UL) #define HI_OBP_ADDRESS _AC(0x0000000100000000,UL)
#define VMALLOC_START _AC(0x0000000100000000,UL)
#define VMALLOC_END _AC(0x0000000200000000,UL)
/* XXX All of this needs to be rethought so we can take advantage /* XXX All of this needs to be rethought so we can take advantage
* XXX cheetah's full 64-bit virtual address space, ie. no more hole * XXX cheetah's full 64-bit virtual address space, ie. no more hole
......
...@@ -5,6 +5,10 @@ ...@@ -5,6 +5,10 @@
* linux/byteorder_generic.h * linux/byteorder_generic.h
* Generic Byte-reordering support * Generic Byte-reordering support
* *
* The "... p" macros, like le64_to_cpup, can be used with pointers
* to unaligned data, but there will be a performance penalty on
* some architectures. Use get_unaligned for unaligned data.
*
* Francois-Rene Rideau <fare@tunes.org> 19970707 * Francois-Rene Rideau <fare@tunes.org> 19970707
* gathered all the good ideas from all asm-foo/byteorder.h into one file, * gathered all the good ideas from all asm-foo/byteorder.h into one file,
* cleaned them up. * cleaned them up.
......
...@@ -173,7 +173,7 @@ static cs4231_t *cs4231_list; ...@@ -173,7 +173,7 @@ static cs4231_t *cs4231_list;
#define CS4231_GLOBALIRQ 0x01 /* IRQ is active */ #define CS4231_GLOBALIRQ 0x01 /* IRQ is active */
/* definitions for codec irq status */ /* definitions for codec irq status - CS4231_IRQ_STATUS */
#define CS4231_PLAYBACK_IRQ 0x10 #define CS4231_PLAYBACK_IRQ 0x10
#define CS4231_RECORD_IRQ 0x20 #define CS4231_RECORD_IRQ 0x20
...@@ -402,7 +402,7 @@ static void snd_cs4231_outm(cs4231_t *chip, unsigned char reg, ...@@ -402,7 +402,7 @@ static void snd_cs4231_outm(cs4231_t *chip, unsigned char reg,
udelay(100); udelay(100);
#ifdef CONFIG_SND_DEBUG #ifdef CONFIG_SND_DEBUG
if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT)
snd_printk("outm: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value); snd_printdd("outm: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value);
#endif #endif
if (chip->calibrate_mute) { if (chip->calibrate_mute) {
chip->image[reg] &= mask; chip->image[reg] &= mask;
...@@ -425,6 +425,10 @@ static void snd_cs4231_dout(cs4231_t *chip, unsigned char reg, unsigned char val ...@@ -425,6 +425,10 @@ static void snd_cs4231_dout(cs4231_t *chip, unsigned char reg, unsigned char val
timeout > 0 && (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT); timeout > 0 && (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT);
timeout--) timeout--)
udelay(100); udelay(100);
#ifdef CONFIG_SND_DEBUG
if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT)
snd_printdd("out: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value);
#endif
__cs4231_writeb(chip, chip->mce_bit | reg, CS4231P(chip, REGSEL)); __cs4231_writeb(chip, chip->mce_bit | reg, CS4231P(chip, REGSEL));
__cs4231_writeb(chip, value, CS4231P(chip, REG)); __cs4231_writeb(chip, value, CS4231P(chip, REG));
mb(); mb();
...@@ -440,15 +444,12 @@ static void snd_cs4231_out(cs4231_t *chip, unsigned char reg, unsigned char valu ...@@ -440,15 +444,12 @@ static void snd_cs4231_out(cs4231_t *chip, unsigned char reg, unsigned char valu
udelay(100); udelay(100);
#ifdef CONFIG_SND_DEBUG #ifdef CONFIG_SND_DEBUG
if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT)
snd_printk("out: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value); snd_printdd("out: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value);
#endif #endif
__cs4231_writeb(chip, chip->mce_bit | reg, CS4231P(chip, REGSEL)); __cs4231_writeb(chip, chip->mce_bit | reg, CS4231P(chip, REGSEL));
__cs4231_writeb(chip, value, CS4231P(chip, REG)); __cs4231_writeb(chip, value, CS4231P(chip, REG));
chip->image[reg] = value; chip->image[reg] = value;
mb(); mb();
#if 0
printk("codec out - reg 0x%x = 0x%x\n", chip->mce_bit | reg, value);
#endif
} }
static unsigned char snd_cs4231_in(cs4231_t *chip, unsigned char reg) static unsigned char snd_cs4231_in(cs4231_t *chip, unsigned char reg)
...@@ -462,61 +463,14 @@ static unsigned char snd_cs4231_in(cs4231_t *chip, unsigned char reg) ...@@ -462,61 +463,14 @@ static unsigned char snd_cs4231_in(cs4231_t *chip, unsigned char reg)
udelay(100); udelay(100);
#ifdef CONFIG_SND_DEBUG #ifdef CONFIG_SND_DEBUG
if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT)
snd_printk("in: auto calibration time out - reg = 0x%x\n", reg); snd_printdd("in: auto calibration time out - reg = 0x%x\n", reg);
#endif #endif
__cs4231_writeb(chip, chip->mce_bit | reg, CS4231P(chip, REGSEL)); __cs4231_writeb(chip, chip->mce_bit | reg, CS4231P(chip, REGSEL));
mb(); mb();
ret = __cs4231_readb(chip, CS4231P(chip, REG)); ret = __cs4231_readb(chip, CS4231P(chip, REG));
#if 0
printk("codec in - reg 0x%x = 0x%x\n", chip->mce_bit | reg, ret);
#endif
return ret; return ret;
} }
#if 0
static void snd_cs4231_debug(cs4231_t *chip)
{
printk("CS4231 REGS: INDEX = 0x%02x ",
__cs4231_readb(chip, CS4231P(chip, REGSEL)));
printk(" STATUS = 0x%02x\n",
__cs4231_readb(chip, CS4231P(chip, 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));
printk(" 0x11: alt 2 (CFIG 3) = 0x%02x\n", snd_cs4231_in(chip, 0x11));
printk(" 0x02: GF1 left input = 0x%02x ", snd_cs4231_in(chip, 0x02));
printk(" 0x12: left line in = 0x%02x\n", snd_cs4231_in(chip, 0x12));
printk(" 0x03: GF1 right input = 0x%02x ", snd_cs4231_in(chip, 0x03));
printk(" 0x13: right line in = 0x%02x\n", snd_cs4231_in(chip, 0x13));
printk(" 0x04: CD left input = 0x%02x ", snd_cs4231_in(chip, 0x04));
printk(" 0x14: timer low = 0x%02x\n", snd_cs4231_in(chip, 0x14));
printk(" 0x05: CD right input = 0x%02x ", snd_cs4231_in(chip, 0x05));
printk(" 0x15: timer high = 0x%02x\n", snd_cs4231_in(chip, 0x15));
printk(" 0x06: left output = 0x%02x ", snd_cs4231_in(chip, 0x06));
printk(" 0x16: left MIC (PnP) = 0x%02x\n", snd_cs4231_in(chip, 0x16));
printk(" 0x07: right output = 0x%02x ", snd_cs4231_in(chip, 0x07));
printk(" 0x17: right MIC (PnP) = 0x%02x\n", snd_cs4231_in(chip, 0x17));
printk(" 0x08: playback format = 0x%02x ", snd_cs4231_in(chip, 0x08));
printk(" 0x18: IRQ status = 0x%02x\n", snd_cs4231_in(chip, 0x18));
printk(" 0x09: iface (CFIG 1) = 0x%02x ", snd_cs4231_in(chip, 0x09));
printk(" 0x19: left line out = 0x%02x\n", snd_cs4231_in(chip, 0x19));
printk(" 0x0a: pin control = 0x%02x ", snd_cs4231_in(chip, 0x0a));
printk(" 0x1a: mono control = 0x%02x\n", snd_cs4231_in(chip, 0x1a));
printk(" 0x0b: init & status = 0x%02x ", snd_cs4231_in(chip, 0x0b));
printk(" 0x1b: right line out = 0x%02x\n", snd_cs4231_in(chip, 0x1b));
printk(" 0x0c: revision & mode = 0x%02x ", snd_cs4231_in(chip, 0x0c));
printk(" 0x1c: record format = 0x%02x\n", snd_cs4231_in(chip, 0x1c));
printk(" 0x0d: loopback = 0x%02x ", snd_cs4231_in(chip, 0x0d));
printk(" 0x1d: var freq (PnP) = 0x%02x\n", snd_cs4231_in(chip, 0x1d));
printk(" 0x0e: ply upr count = 0x%02x ", snd_cs4231_in(chip, 0x0e));
printk(" 0x1e: rec upr count = 0x%02x\n", snd_cs4231_in(chip, 0x1e));
printk(" 0x0f: ply lwr count = 0x%02x ", snd_cs4231_in(chip, 0x0f));
printk(" 0x1f: rec lwr count = 0x%02x\n", snd_cs4231_in(chip, 0x1f));
}
#endif
/* /*
* CS4231 detection / MCE routines * CS4231 detection / MCE routines
*/ */
...@@ -528,11 +482,12 @@ static void snd_cs4231_busy_wait(cs4231_t *chip) ...@@ -528,11 +482,12 @@ static void snd_cs4231_busy_wait(cs4231_t *chip)
/* huh.. looks like this sequence is proper for CS4231A chip (GUS MAX) */ /* huh.. looks like this sequence is proper for CS4231A chip (GUS MAX) */
for (timeout = 5; timeout > 0; timeout--) for (timeout = 5; timeout > 0; timeout--)
__cs4231_readb(chip, CS4231P(chip, REGSEL)); __cs4231_readb(chip, CS4231P(chip, REGSEL));
/* end of cleanup sequence */ /* end of cleanup sequence */
for (timeout = 250; for (timeout = 500;
timeout > 0 && (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT); timeout > 0 && (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT);
timeout--) timeout--)
udelay(100); udelay(1000);
} }
static void snd_cs4231_mce_up(cs4231_t *chip) static void snd_cs4231_mce_up(cs4231_t *chip)
...@@ -545,12 +500,12 @@ static void snd_cs4231_mce_up(cs4231_t *chip) ...@@ -545,12 +500,12 @@ static void snd_cs4231_mce_up(cs4231_t *chip)
udelay(100); udelay(100);
#ifdef CONFIG_SND_DEBUG #ifdef CONFIG_SND_DEBUG
if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT)
snd_printk("mce_up - auto calibration time out (0)\n"); snd_printdd("mce_up - auto calibration time out (0)\n");
#endif #endif
chip->mce_bit |= CS4231_MCE; chip->mce_bit |= CS4231_MCE;
timeout = __cs4231_readb(chip, CS4231P(chip, REGSEL)); timeout = __cs4231_readb(chip, CS4231P(chip, REGSEL));
if (timeout == 0x80) if (timeout == 0x80)
snd_printk("mce_up [%p]: serious init problem - codec still busy\n", chip->port); snd_printdd("mce_up [%p]: serious init problem - codec still busy\n", chip->port);
if (!(timeout & CS4231_MCE)) if (!(timeout & CS4231_MCE))
__cs4231_writeb(chip, chip->mce_bit | (timeout & 0x1f), CS4231P(chip, REGSEL)); __cs4231_writeb(chip, chip->mce_bit | (timeout & 0x1f), CS4231P(chip, REGSEL));
spin_unlock_irqrestore(&chip->lock, flags); spin_unlock_irqrestore(&chip->lock, flags);
...@@ -563,18 +518,15 @@ static void snd_cs4231_mce_down(cs4231_t *chip) ...@@ -563,18 +518,15 @@ static void snd_cs4231_mce_down(cs4231_t *chip)
spin_lock_irqsave(&chip->lock, flags); spin_lock_irqsave(&chip->lock, flags);
snd_cs4231_busy_wait(chip); snd_cs4231_busy_wait(chip);
#if 0
printk("(1) timeout = %i\n", timeout);
#endif
#ifdef CONFIG_SND_DEBUG #ifdef CONFIG_SND_DEBUG
if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT)
snd_printk("mce_down [%p] - auto calibration time out (0)\n", CS4231P(chip, REGSEL)); snd_printdd("mce_down [%p] - auto calibration time out (0)\n", CS4231P(chip, REGSEL));
#endif #endif
chip->mce_bit &= ~CS4231_MCE; chip->mce_bit &= ~CS4231_MCE;
timeout = __cs4231_readb(chip, CS4231P(chip, REGSEL)); timeout = __cs4231_readb(chip, CS4231P(chip, REGSEL));
__cs4231_writeb(chip, chip->mce_bit | (timeout & 0x1f), CS4231P(chip, REGSEL)); __cs4231_writeb(chip, chip->mce_bit | (timeout & 0x1f), CS4231P(chip, REGSEL));
if (timeout == 0x80) if (timeout == 0x80)
snd_printk("mce_down [%p]: serious init problem - codec still busy\n", chip->port); snd_printdd("mce_down [%p]: serious init problem - codec still busy\n", chip->port);
if ((timeout & CS4231_MCE) == 0) { if ((timeout & CS4231_MCE) == 0) {
spin_unlock_irqrestore(&chip->lock, flags); spin_unlock_irqrestore(&chip->lock, flags);
return; return;
...@@ -590,9 +542,7 @@ static void snd_cs4231_mce_down(cs4231_t *chip) ...@@ -590,9 +542,7 @@ static void snd_cs4231_mce_down(cs4231_t *chip)
spin_unlock_irqrestore(&chip->lock, flags); spin_unlock_irqrestore(&chip->lock, flags);
return; return;
} }
#if 0
printk("(2) timeout = %i, jiffies = %li\n", timeout, jiffies);
#endif
/* in 10ms increments, check condition, up to 250ms */ /* in 10ms increments, check condition, up to 250ms */
timeout = 25; timeout = 25;
while (snd_cs4231_in(chip, CS4231_TEST_INIT) & CS4231_CALIB_IN_PROGRESS) { while (snd_cs4231_in(chip, CS4231_TEST_INIT) & CS4231_CALIB_IN_PROGRESS) {
...@@ -604,9 +554,7 @@ static void snd_cs4231_mce_down(cs4231_t *chip) ...@@ -604,9 +554,7 @@ static void snd_cs4231_mce_down(cs4231_t *chip)
msleep(10); msleep(10);
spin_lock_irqsave(&chip->lock, flags); spin_lock_irqsave(&chip->lock, flags);
} }
#if 0
printk("(3) jiffies = %li\n", jiffies);
#endif
/* in 10ms increments, check condition, up to 100ms */ /* in 10ms increments, check condition, up to 100ms */
timeout = 10; timeout = 10;
while (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) { while (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) {
...@@ -619,28 +567,7 @@ static void snd_cs4231_mce_down(cs4231_t *chip) ...@@ -619,28 +567,7 @@ static void snd_cs4231_mce_down(cs4231_t *chip)
spin_lock_irqsave(&chip->lock, flags); spin_lock_irqsave(&chip->lock, flags);
} }
spin_unlock_irqrestore(&chip->lock, flags); spin_unlock_irqrestore(&chip->lock, flags);
#if 0
printk("(4) jiffies = %li\n", jiffies);
snd_printk("mce_down - exit = 0x%x\n", __cs4231_readb(chip, CS4231P(chip, REGSEL)));
#endif
}
#if 0 /* Unused for now... */
static unsigned int snd_cs4231_get_count(unsigned char format, unsigned int size)
{
switch (format & 0xe0) {
case CS4231_LINEAR_16:
case CS4231_LINEAR_16_BIG:
size >>= 1;
break;
case CS4231_ADPCM_16:
return size >> 2;
}
if (format & CS4231_STEREO)
size >>= 1;
return size;
} }
#endif
#ifdef EBUS_SUPPORT #ifdef EBUS_SUPPORT
static void snd_cs4231_ebus_advance_dma(struct ebus_dma_info *p, snd_pcm_substream_t *substream, unsigned int *periods_sent) static void snd_cs4231_ebus_advance_dma(struct ebus_dma_info *p, snd_pcm_substream_t *substream, unsigned int *periods_sent)
...@@ -648,25 +575,50 @@ static void snd_cs4231_ebus_advance_dma(struct ebus_dma_info *p, snd_pcm_substre ...@@ -648,25 +575,50 @@ static void snd_cs4231_ebus_advance_dma(struct ebus_dma_info *p, snd_pcm_substre
snd_pcm_runtime_t *runtime = substream->runtime; snd_pcm_runtime_t *runtime = substream->runtime;
while (1) { while (1) {
unsigned int dma_size = snd_pcm_lib_period_bytes(substream); unsigned int period_size = snd_pcm_lib_period_bytes(substream);
unsigned int offset = dma_size * (*periods_sent); unsigned int offset = period_size * (*periods_sent);
if (dma_size >= (1 << 24)) if (period_size >= (1 << 24))
BUG(); BUG();
if (ebus_dma_request(p, runtime->dma_addr + offset, dma_size)) if (ebus_dma_request(p, runtime->dma_addr + offset, period_size))
return; return;
#if 0
printk("ebus_advance: Sent period %u (size[%x] offset[%x])\n",
(*periods_sent), dma_size, offset);
#endif
(*periods_sent) = ((*periods_sent) + 1) % runtime->periods; (*periods_sent) = ((*periods_sent) + 1) % runtime->periods;
} }
} }
#endif #endif
static void cs4231_dma_trigger(cs4231_t *chip, unsigned int what, int on) #ifdef SBUS_SUPPORT
static void snd_cs4231_sbus_advance_dma(snd_pcm_substream_t *substream, unsigned int *periods_sent)
{
cs4231_t *chip = snd_pcm_substream_chip(substream);
snd_pcm_runtime_t *runtime = substream->runtime;
unsigned int period_size = snd_pcm_lib_period_bytes(substream);
unsigned int offset = period_size * (*periods_sent % runtime->periods);
if (runtime->period_size > 0xffff + 1)
BUG();
switch (substream->stream) {
case SNDRV_PCM_STREAM_PLAYBACK:
sbus_writel(runtime->dma_addr + offset, chip->port + APCPNVA);
sbus_writel(period_size, chip->port + APCPNC);
break;
case SNDRV_PCM_STREAM_CAPTURE:
sbus_writel(runtime->dma_addr + offset, chip->port + APCCNVA);
sbus_writel(period_size, chip->port + APCCNC);
break;
}
(*periods_sent) = (*periods_sent + 1) % runtime->periods;
}
#endif
static void cs4231_dma_trigger(snd_pcm_substream_t *substream, unsigned int what, int on)
{ {
cs4231_t *chip = snd_pcm_substream_chip(substream);
#ifdef EBUS_SUPPORT #ifdef EBUS_SUPPORT
if (chip->flags & CS4231_FLAG_EBUS) { if (chip->flags & CS4231_FLAG_EBUS) {
if (what & CS4231_PLAYBACK_ENABLE) { if (what & CS4231_PLAYBACK_ENABLE) {
...@@ -694,6 +646,60 @@ static void cs4231_dma_trigger(cs4231_t *chip, unsigned int what, int on) ...@@ -694,6 +646,60 @@ static void cs4231_dma_trigger(cs4231_t *chip, unsigned int what, int on)
} else { } else {
#endif #endif
#ifdef SBUS_SUPPORT #ifdef SBUS_SUPPORT
u32 csr = sbus_readl(chip->port + APCCSR);
/* I don't know why, but on sbus the period counter must
* only start counting after the first period is sent.
* Therefore this dummy thing.
*/
unsigned int dummy = 0;
switch (what) {
case CS4231_PLAYBACK_ENABLE:
if (on) {
csr &= ~APC_XINT_PLAY;
sbus_writel(csr, chip->port + APCCSR);
csr &= ~APC_PPAUSE;
sbus_writel(csr, chip->port + APCCSR);
snd_cs4231_sbus_advance_dma(substream, &dummy);
csr |= APC_GENL_INT | APC_PLAY_INT | APC_XINT_ENA |
APC_XINT_PLAY | APC_XINT_EMPT | APC_XINT_GENL |
APC_XINT_PENA | APC_PDMA_READY;
sbus_writel(csr, chip->port + APCCSR);
} else {
csr |= APC_PPAUSE;
sbus_writel(csr, chip->port + APCCSR);
csr &= ~APC_PDMA_READY;
sbus_writel(csr, chip->port + APCCSR);
}
break;
case CS4231_RECORD_ENABLE:
if (on) {
csr &= ~APC_XINT_CAPT;
sbus_writel(csr, chip->port + APCCSR);
csr &= ~APC_CPAUSE;
sbus_writel(csr, chip->port + APCCSR);
snd_cs4231_sbus_advance_dma(substream, &dummy);
csr |= APC_GENL_INT | APC_CAPT_INT | APC_XINT_ENA |
APC_XINT_CAPT | APC_XINT_CEMP | APC_XINT_GENL |
APC_CDMA_READY;
sbus_writel(csr, chip->port + APCCSR);
} else {
csr |= APC_CPAUSE;
sbus_writel(csr, chip->port + APCCSR);
csr &= ~APC_CDMA_READY;
sbus_writel(csr, chip->port + APCCSR);
}
break;
}
#endif #endif
#ifdef EBUS_SUPPORT #ifdef EBUS_SUPPORT
} }
...@@ -725,25 +731,12 @@ static int snd_cs4231_trigger(snd_pcm_substream_t *substream, int cmd) ...@@ -725,25 +731,12 @@ static int snd_cs4231_trigger(snd_pcm_substream_t *substream, int cmd)
} }
} }
#if 0
printk("TRIGGER: what[%x] on(%d)\n",
what, (cmd == SNDRV_PCM_TRIGGER_START));
#endif
spin_lock_irqsave(&chip->lock, flags); spin_lock_irqsave(&chip->lock, flags);
if (cmd == SNDRV_PCM_TRIGGER_START) { if (cmd == SNDRV_PCM_TRIGGER_START) {
cs4231_dma_trigger(chip, what, 1); cs4231_dma_trigger(substream, what, 1);
chip->image[CS4231_IFACE_CTRL] |= what; chip->image[CS4231_IFACE_CTRL] |= what;
if (what & CS4231_PLAYBACK_ENABLE) {
snd_cs4231_out(chip, CS4231_PLY_LWR_CNT, 0xff);
snd_cs4231_out(chip, CS4231_PLY_UPR_CNT, 0xff);
}
if (what & CS4231_RECORD_ENABLE) {
snd_cs4231_out(chip, CS4231_REC_LWR_CNT, 0xff);
snd_cs4231_out(chip, CS4231_REC_UPR_CNT, 0xff);
}
} else { } else {
cs4231_dma_trigger(chip, what, 0); cs4231_dma_trigger(substream, what, 0);
chip->image[CS4231_IFACE_CTRL] &= ~what; chip->image[CS4231_IFACE_CTRL] &= ~what;
} }
snd_cs4231_out(chip, CS4231_IFACE_CTRL, snd_cs4231_out(chip, CS4231_IFACE_CTRL,
...@@ -755,9 +748,7 @@ static int snd_cs4231_trigger(snd_pcm_substream_t *substream, int cmd) ...@@ -755,9 +748,7 @@ static int snd_cs4231_trigger(snd_pcm_substream_t *substream, int cmd)
result = -EINVAL; result = -EINVAL;
break; break;
} }
#if 0
snd_cs4231_debug(chip);
#endif
return result; return result;
} }
...@@ -790,9 +781,6 @@ static unsigned char snd_cs4231_get_format(cs4231_t *chip, int format, int chann ...@@ -790,9 +781,6 @@ static unsigned char snd_cs4231_get_format(cs4231_t *chip, int format, int chann
} }
if (channels > 1) if (channels > 1)
rformat |= CS4231_STEREO; rformat |= CS4231_STEREO;
#if 0
snd_printk("get_format: 0x%x (mode=0x%x)\n", format, mode);
#endif
return rformat; return rformat;
} }
...@@ -944,7 +932,7 @@ static void snd_cs4231_init(cs4231_t *chip) ...@@ -944,7 +932,7 @@ static void snd_cs4231_init(cs4231_t *chip)
snd_cs4231_mce_down(chip); snd_cs4231_mce_down(chip);
#ifdef SNDRV_DEBUG_MCE #ifdef SNDRV_DEBUG_MCE
snd_printk("init: (1)\n"); snd_printdd("init: (1)\n");
#endif #endif
snd_cs4231_mce_up(chip); snd_cs4231_mce_up(chip);
spin_lock_irqsave(&chip->lock, flags); spin_lock_irqsave(&chip->lock, flags);
...@@ -957,7 +945,7 @@ static void snd_cs4231_init(cs4231_t *chip) ...@@ -957,7 +945,7 @@ static void snd_cs4231_init(cs4231_t *chip)
snd_cs4231_mce_down(chip); snd_cs4231_mce_down(chip);
#ifdef SNDRV_DEBUG_MCE #ifdef SNDRV_DEBUG_MCE
snd_printk("init: (2)\n"); snd_printdd("init: (2)\n");
#endif #endif
snd_cs4231_mce_up(chip); snd_cs4231_mce_up(chip);
...@@ -967,7 +955,7 @@ static void snd_cs4231_init(cs4231_t *chip) ...@@ -967,7 +955,7 @@ static void snd_cs4231_init(cs4231_t *chip)
snd_cs4231_mce_down(chip); snd_cs4231_mce_down(chip);
#ifdef SNDRV_DEBUG_MCE #ifdef SNDRV_DEBUG_MCE
snd_printk("init: (3) - afei = 0x%x\n", chip->image[CS4231_ALT_FEATURE_1]); snd_printdd("init: (3) - afei = 0x%x\n", chip->image[CS4231_ALT_FEATURE_1]);
#endif #endif
spin_lock_irqsave(&chip->lock, flags); spin_lock_irqsave(&chip->lock, flags);
...@@ -981,7 +969,7 @@ static void snd_cs4231_init(cs4231_t *chip) ...@@ -981,7 +969,7 @@ static void snd_cs4231_init(cs4231_t *chip)
snd_cs4231_mce_down(chip); snd_cs4231_mce_down(chip);
#ifdef SNDRV_DEBUG_MCE #ifdef SNDRV_DEBUG_MCE
snd_printk("init: (4)\n"); snd_printdd("init: (4)\n");
#endif #endif
snd_cs4231_mce_up(chip); snd_cs4231_mce_up(chip);
...@@ -991,7 +979,7 @@ static void snd_cs4231_init(cs4231_t *chip) ...@@ -991,7 +979,7 @@ static void snd_cs4231_init(cs4231_t *chip)
snd_cs4231_mce_down(chip); snd_cs4231_mce_down(chip);
#ifdef SNDRV_DEBUG_MCE #ifdef SNDRV_DEBUG_MCE
snd_printk("init: (5)\n"); snd_printdd("init: (5)\n");
#endif #endif
} }
...@@ -1022,6 +1010,7 @@ static int snd_cs4231_open(cs4231_t *chip, unsigned int mode) ...@@ -1022,6 +1010,7 @@ static int snd_cs4231_open(cs4231_t *chip, unsigned int mode)
CS4231_RECORD_IRQ | CS4231_RECORD_IRQ |
CS4231_TIMER_IRQ); CS4231_TIMER_IRQ);
snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0); snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0);
spin_unlock_irqrestore(&chip->lock, flags); spin_unlock_irqrestore(&chip->lock, flags);
chip->mode = mode; chip->mode = mode;
...@@ -1136,11 +1125,21 @@ static int snd_cs4231_playback_hw_free(snd_pcm_substream_t *substream) ...@@ -1136,11 +1125,21 @@ static int snd_cs4231_playback_hw_free(snd_pcm_substream_t *substream)
static int snd_cs4231_playback_prepare(snd_pcm_substream_t *substream) static int snd_cs4231_playback_prepare(snd_pcm_substream_t *substream)
{ {
cs4231_t *chip = snd_pcm_substream_chip(substream); cs4231_t *chip = snd_pcm_substream_chip(substream);
snd_pcm_runtime_t *runtime = substream->runtime;
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&chip->lock, flags); spin_lock_irqsave(&chip->lock, flags);
chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE | chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE |
CS4231_PLAYBACK_PIO); CS4231_PLAYBACK_PIO);
if (runtime->period_size > 0xffff + 1)
BUG();
snd_cs4231_out(chip, CS4231_PLY_LWR_CNT, (runtime->period_size - 1) & 0x00ff);
snd_cs4231_out(chip, CS4231_PLY_UPR_CNT, (runtime->period_size - 1) >> 8 & 0x00ff);
chip->p_periods_sent = 0;
spin_unlock_irqrestore(&chip->lock, flags); spin_unlock_irqrestore(&chip->lock, flags);
return 0; return 0;
...@@ -1172,12 +1171,16 @@ static int snd_cs4231_capture_hw_free(snd_pcm_substream_t *substream) ...@@ -1172,12 +1171,16 @@ static int snd_cs4231_capture_hw_free(snd_pcm_substream_t *substream)
static int snd_cs4231_capture_prepare(snd_pcm_substream_t *substream) static int snd_cs4231_capture_prepare(snd_pcm_substream_t *substream)
{ {
cs4231_t *chip = snd_pcm_substream_chip(substream); cs4231_t *chip = snd_pcm_substream_chip(substream);
snd_pcm_runtime_t *runtime = substream->runtime;
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&chip->lock, flags); spin_lock_irqsave(&chip->lock, flags);
chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_RECORD_ENABLE | chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_RECORD_ENABLE |
CS4231_RECORD_PIO); CS4231_RECORD_PIO);
snd_cs4231_out(chip, CS4231_REC_LWR_CNT, (runtime->period_size - 1) & 0x00ff);
snd_cs4231_out(chip, CS4231_REC_LWR_CNT, (runtime->period_size - 1) >> 8 & 0x00ff);
spin_unlock_irqrestore(&chip->lock, flags); spin_unlock_irqrestore(&chip->lock, flags);
return 0; return 0;
...@@ -1196,53 +1199,61 @@ static void snd_cs4231_overrange(cs4231_t *chip) ...@@ -1196,53 +1199,61 @@ static void snd_cs4231_overrange(cs4231_t *chip)
chip->capture_substream->runtime->overrange++; chip->capture_substream->runtime->overrange++;
} }
static void snd_cs4231_generic_interrupt(cs4231_t *chip) static irqreturn_t snd_cs4231_generic_interrupt(cs4231_t *chip)
{ {
unsigned long flags; unsigned long flags;
unsigned char status; unsigned char status;
/*This is IRQ is not raised by the cs4231*/
if (!(__cs4231_readb(chip, CS4231P(chip, STATUS)) & CS4231_GLOBALIRQ))
return IRQ_NONE;
status = snd_cs4231_in(chip, CS4231_IRQ_STATUS); status = snd_cs4231_in(chip, CS4231_IRQ_STATUS);
if (!status)
return;
if (status & CS4231_TIMER_IRQ) { if (status & CS4231_TIMER_IRQ) {
if (chip->timer) if (chip->timer)
snd_timer_interrupt(chip->timer, chip->timer->sticks); snd_timer_interrupt(chip->timer, chip->timer->sticks);
} }
if (status & CS4231_PLAYBACK_IRQ)
snd_pcm_period_elapsed(chip->playback_substream); if (status & CS4231_RECORD_IRQ)
if (status & CS4231_RECORD_IRQ) {
snd_cs4231_overrange(chip); snd_cs4231_overrange(chip);
snd_pcm_period_elapsed(chip->capture_substream);
}
/* ACK the CS4231 interrupt. */ /* ACK the CS4231 interrupt. */
spin_lock_irqsave(&chip->lock, flags); spin_lock_irqsave(&chip->lock, flags);
snd_cs4231_outm(chip, CS4231_IRQ_STATUS, ~CS4231_ALL_IRQS | ~status, 0); snd_cs4231_outm(chip, CS4231_IRQ_STATUS, ~CS4231_ALL_IRQS | ~status, 0);
spin_unlock_irqrestore(&chip->lock, flags); spin_unlock_irqrestore(&chip->lock, flags);
return 0;
} }
#ifdef SBUS_SUPPORT #ifdef SBUS_SUPPORT
static irqreturn_t snd_cs4231_sbus_interrupt(int irq, void *dev_id, struct pt_regs *regs) static irqreturn_t snd_cs4231_sbus_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
cs4231_t *chip = dev_id; cs4231_t *chip = dev_id;
u32 csr;
csr = sbus_readl(chip->port + APCCSR);
if (!(csr & (APC_INT_PENDING |
APC_PLAY_INT |
APC_CAPT_INT |
APC_GENL_INT |
APC_XINT_PEMP |
APC_XINT_CEMP)))
return IRQ_NONE;
/* ACK the APC interrupt. */ /* ACK the APC interrupt. */
u32 csr = sbus_readl(chip->port + APCCSR);
sbus_writel(csr, chip->port + APCCSR); sbus_writel(csr, chip->port + APCCSR);
snd_cs4231_generic_interrupt(chip); if ((chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE) &&
(csr & APC_PLAY_INT) &&
(csr & APC_XINT_PNVA) &&
!(csr & APC_XINT_EMPT)) {
snd_cs4231_sbus_advance_dma(chip->playback_substream,
&chip->p_periods_sent);
snd_pcm_period_elapsed(chip->playback_substream);
}
return IRQ_HANDLED; if ((chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE) &&
(csr & APC_CAPT_INT) &&
(csr & APC_XINT_CNVA)) {
snd_cs4231_sbus_advance_dma(chip->capture_substream,
&chip->c_periods_sent);
snd_pcm_period_elapsed(chip->capture_substream);
}
return snd_cs4231_generic_interrupt(chip);
} }
#endif #endif
...@@ -1290,7 +1301,8 @@ static snd_pcm_uframes_t snd_cs4231_playback_pointer(snd_pcm_substream_t *substr ...@@ -1290,7 +1301,8 @@ static snd_pcm_uframes_t snd_cs4231_playback_pointer(snd_pcm_substream_t *substr
#ifdef EBUS_SUPPORT #ifdef EBUS_SUPPORT
} }
#endif #endif
ptr += (period_bytes - residue); ptr += period_bytes - residue;
return bytes_to_frames(substream->runtime, ptr); return bytes_to_frames(substream->runtime, ptr);
} }
...@@ -1314,7 +1326,7 @@ static snd_pcm_uframes_t snd_cs4231_capture_pointer(snd_pcm_substream_t * substr ...@@ -1314,7 +1326,7 @@ static snd_pcm_uframes_t snd_cs4231_capture_pointer(snd_pcm_substream_t * substr
#ifdef EBUS_SUPPORT #ifdef EBUS_SUPPORT
} }
#endif #endif
ptr += (period_bytes - residue); ptr += period_bytes - residue;
return bytes_to_frames(substream->runtime, ptr); return bytes_to_frames(substream->runtime, ptr);
} }
...@@ -1328,9 +1340,6 @@ static int snd_cs4231_probe(cs4231_t *chip) ...@@ -1328,9 +1340,6 @@ static int snd_cs4231_probe(cs4231_t *chip)
int i, id, vers; int i, id, vers;
unsigned char *ptr; unsigned char *ptr;
#if 0
snd_cs4231_debug(chip);
#endif
id = vers = 0; id = vers = 0;
for (i = 0; i < 50; i++) { for (i = 0; i < 50; i++) {
mb(); mb();
...@@ -1985,13 +1994,13 @@ static int __init snd_cs4231_sbus_create(snd_card_t *card, ...@@ -1985,13 +1994,13 @@ static int __init snd_cs4231_sbus_create(snd_card_t *card,
chip->port = sbus_ioremap(&sdev->resource[0], 0, chip->port = sbus_ioremap(&sdev->resource[0], 0,
chip->regs_size, "cs4231"); chip->regs_size, "cs4231");
if (!chip->port) { if (!chip->port) {
snd_printk("cs4231-%d: Unable to map chip registers.\n", dev); snd_printdd("cs4231-%d: Unable to map chip registers.\n", dev);
return -EIO; return -EIO;
} }
if (request_irq(sdev->irqs[0], snd_cs4231_sbus_interrupt, if (request_irq(sdev->irqs[0], snd_cs4231_sbus_interrupt,
SA_SHIRQ, "cs4231", chip)) { SA_SHIRQ, "cs4231", chip)) {
snd_printk("cs4231-%d: Unable to grab SBUS IRQ %s\n", snd_printdd("cs4231-%d: Unable to grab SBUS IRQ %s\n",
dev, dev,
__irq_itoa(sdev->irqs[0])); __irq_itoa(sdev->irqs[0]));
snd_cs4231_sbus_free(chip); snd_cs4231_sbus_free(chip);
...@@ -2113,29 +2122,29 @@ static int __init snd_cs4231_ebus_create(snd_card_t *card, ...@@ -2113,29 +2122,29 @@ static int __init snd_cs4231_ebus_create(snd_card_t *card,
chip->eb2c.regs = ioremap(edev->resource[2].start, 0x10); chip->eb2c.regs = ioremap(edev->resource[2].start, 0x10);
if (!chip->port || !chip->eb2p.regs || !chip->eb2c.regs) { if (!chip->port || !chip->eb2p.regs || !chip->eb2c.regs) {
snd_cs4231_ebus_free(chip); snd_cs4231_ebus_free(chip);
snd_printk("cs4231-%d: Unable to map chip registers.\n", dev); snd_printdd("cs4231-%d: Unable to map chip registers.\n", dev);
return -EIO; return -EIO;
} }
if (ebus_dma_register(&chip->eb2c)) { if (ebus_dma_register(&chip->eb2c)) {
snd_cs4231_ebus_free(chip); snd_cs4231_ebus_free(chip);
snd_printk("cs4231-%d: Unable to register EBUS capture DMA\n", dev); snd_printdd("cs4231-%d: Unable to register EBUS capture DMA\n", dev);
return -EBUSY; return -EBUSY;
} }
if (ebus_dma_irq_enable(&chip->eb2c, 1)) { if (ebus_dma_irq_enable(&chip->eb2c, 1)) {
snd_cs4231_ebus_free(chip); snd_cs4231_ebus_free(chip);
snd_printk("cs4231-%d: Unable to enable EBUS capture IRQ\n", dev); snd_printdd("cs4231-%d: Unable to enable EBUS capture IRQ\n", dev);
return -EBUSY; return -EBUSY;
} }
if (ebus_dma_register(&chip->eb2p)) { if (ebus_dma_register(&chip->eb2p)) {
snd_cs4231_ebus_free(chip); snd_cs4231_ebus_free(chip);
snd_printk("cs4231-%d: Unable to register EBUS play DMA\n", dev); snd_printdd("cs4231-%d: Unable to register EBUS play DMA\n", dev);
return -EBUSY; return -EBUSY;
} }
if (ebus_dma_irq_enable(&chip->eb2p, 1)) { if (ebus_dma_irq_enable(&chip->eb2p, 1)) {
snd_cs4231_ebus_free(chip); snd_cs4231_ebus_free(chip);
snd_printk("cs4231-%d: Unable to enable EBUS play IRQ\n", dev); snd_printdd("cs4231-%d: Unable to enable EBUS play IRQ\n", dev);
return -EBUSY; return -EBUSY;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册