2005-04-16 15:20:36 -07:00
/*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU Library General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place - Suite 330 , Boston , MA 02111 - 1307 , USA .
*/
/*
Vortex core low level functions .
Author : Manuel Jander ( mjander @ users . sourceforge . cl )
These functions are mainly the result of translations made
from the original disassembly of the au88x0 binary drivers ,
written by Aureal before they went down .
Many thanks to the Jeff Muizelaar , Kester Maddock , and whoever
contributed to the OpenVortex project .
The author of this file , put the few available pieces together
and translated the rest of the riddle ( Mix , Src and connection stuff ) .
Some things are still to be discovered , and their meanings are unclear .
Some of these functions aren ' t intended to be really used , rather
to help to understand how does the AU88X0 chips work . Keep them in , because
they could be used somewhere in the future .
This code hasn ' t been tested or proof read thoroughly . If you wanna help ,
take a look at the AU88X0 assembly and check if this matches .
Functions tested ok so far are ( they show the desired effect
at least ) :
vortex_routes ( ) ; ( 1 bug fixed ) .
vortex_adb_addroute ( ) ;
vortex_adb_addroutes ( ) ;
vortex_connect_codecplay ( ) ;
vortex_src_flushbuffers ( ) ;
vortex_adbdma_setmode ( ) ; note : still some unknown arguments !
vortex_adbdma_startfifo ( ) ;
vortex_adbdma_stopfifo ( ) ;
vortex_fifo_setadbctrl ( ) ; note : still some unknown arguments !
vortex_mix_setinputvolumebyte ( ) ;
vortex_mix_enableinput ( ) ;
vortex_mixer_addWTD ( ) ; ( fixed )
vortex_connection_adbdma_src_src ( ) ;
vortex_connection_adbdma_src ( ) ;
vortex_src_change_convratio ( ) ;
vortex_src_addWTD ( ) ; ( fixed )
History :
01 - 03 - 2003 First revision .
01 - 21 - 2003 Some bug fixes .
17 - 02 - 2003 many bugfixes after a big versioning mess .
18 - 02 - 2003 JAAAAAHHHUUUUUU ! ! ! ! The mixer works ! ! I ' m just so happy !
( 2 hours later . . . ) I cant believe it ! Im really lucky today .
Now the SRC is working too ! Yeah ! XMMS works !
20 - 02 - 2003 First steps into the ALSA world .
28 - 02 - 2003 As my birthday present , i discovered how the DMA buffer pages really
work : - ) . It was all wrong .
12 - 03 - 2003 ALSA driver starts working ( 2 channels ) .
16 - 03 - 2003 More srcblock_setupchannel discoveries .
12 - 04 - 2003 AU8830 playback support . Recording in the works .
17 - 04 - 2003 vortex_route ( ) and vortex_routes ( ) bug fixes . AU8830 recording
works now , but chipn ' dale effect is still there .
16 - 05 - 2003 SrcSetupChannel cleanup . Moved the Src setup stuff entirely
into au88x0_pcm . c .
06 - 06 - 2003 Buffer shifter bugfix . Mixer volume fix .
07 - 12 - 2003 A3D routing finally fixed . Believed to be OK .
25 - 03 - 2004 Many thanks to Claudia , for such valuable bug reports .
*/
# include "au88x0.h"
# include "au88x0_a3d.h"
# include <linux/delay.h>
/* MIXER (CAsp4Mix.s and CAsp4Mixer.s) */
// FIXME: get rid of this.
static int mchannels [ NR_MIXIN ] ;
static int rampchs [ NR_MIXIN ] ;
static void vortex_mixer_en_sr ( vortex_t * vortex , int channel )
{
hwwrite ( vortex - > mmio , VORTEX_MIXER_SR ,
hwread ( vortex - > mmio , VORTEX_MIXER_SR ) | ( 0x1 < < channel ) ) ;
}
static void vortex_mixer_dis_sr ( vortex_t * vortex , int channel )
{
hwwrite ( vortex - > mmio , VORTEX_MIXER_SR ,
hwread ( vortex - > mmio , VORTEX_MIXER_SR ) & ~ ( 0x1 < < channel ) ) ;
}
#if 0
static void
vortex_mix_muteinputgain ( vortex_t * vortex , unsigned char mix ,
unsigned char channel )
{
hwwrite ( vortex - > mmio , VORTEX_MIX_INVOL_A + ( ( mix < < 5 ) + channel ) ,
0x80 ) ;
hwwrite ( vortex - > mmio , VORTEX_MIX_INVOL_B + ( ( mix < < 5 ) + channel ) ,
0x80 ) ;
}
static int vortex_mix_getvolume ( vortex_t * vortex , unsigned char mix )
{
int a ;
a = hwread ( vortex - > mmio , VORTEX_MIX_VOL_A + ( mix < < 2 ) ) & 0xff ;
//FP2LinearFrac(a);
return ( a ) ;
}
static int
vortex_mix_getinputvolume ( vortex_t * vortex , unsigned char mix ,
int channel , int * vol )
{
int a ;
if ( ! ( mchannels [ mix ] & ( 1 < < channel ) ) )
return 0 ;
a = hwread ( vortex - > mmio ,
VORTEX_MIX_INVOL_A + ( ( ( mix < < 5 ) + channel ) < < 2 ) ) ;
/*
if ( rampchs [ mix ] = = 0 )
a = FP2LinearFrac ( a ) ;
else
a = FP2LinearFracWT ( a ) ;
*/
* vol = a ;
return ( 0 ) ;
}
static unsigned int vortex_mix_boost6db ( unsigned char vol )
{
return ( vol + 8 ) ; /* WOW! what a complex function! */
}
static void vortex_mix_rampvolume ( vortex_t * vortex , int mix )
{
int ch ;
char a ;
// This function is intended for ramping down only (see vortex_disableinput()).
for ( ch = 0 ; ch < 0x20 ; ch + + ) {
if ( ( ( 1 < < ch ) & rampchs [ mix ] ) = = 0 )
continue ;
a = hwread ( vortex - > mmio ,
VORTEX_MIX_INVOL_B + ( ( ( mix < < 5 ) + ch ) < < 2 ) ) ;
if ( a > - 126 ) {
a - = 2 ;
hwwrite ( vortex - > mmio ,
VORTEX_MIX_INVOL_A +
( ( ( mix < < 5 ) + ch ) < < 2 ) , a ) ;
hwwrite ( vortex - > mmio ,
VORTEX_MIX_INVOL_B +
( ( ( mix < < 5 ) + ch ) < < 2 ) , a ) ;
} else
vortex_mix_killinput ( vortex , mix , ch ) ;
}
}
static int
vortex_mix_getenablebit ( vortex_t * vortex , unsigned char mix , int mixin )
{
int addr , temp ;
if ( mixin > = 0 )
addr = mixin ;
else
addr = mixin + 3 ;
addr = ( ( mix < < 3 ) + ( addr > > 2 ) ) < < 2 ;
temp = hwread ( vortex - > mmio , VORTEX_MIX_ENIN + addr ) ;
return ( ( temp > > ( mixin & 3 ) ) & 1 ) ;
}
# endif
static void
vortex_mix_setvolumebyte ( vortex_t * vortex , unsigned char mix ,
unsigned char vol )
{
int temp ;
hwwrite ( vortex - > mmio , VORTEX_MIX_VOL_A + ( mix < < 2 ) , vol ) ;
if ( 1 ) { /*if (this_10) */
temp = hwread ( vortex - > mmio , VORTEX_MIX_VOL_B + ( mix < < 2 ) ) ;
if ( ( temp ! = 0x80 ) | | ( vol = = 0x80 ) )
return ;
}
hwwrite ( vortex - > mmio , VORTEX_MIX_VOL_B + ( mix < < 2 ) , vol ) ;
}
static void
vortex_mix_setinputvolumebyte ( vortex_t * vortex , unsigned char mix ,
int mixin , unsigned char vol )
{
int temp ;
hwwrite ( vortex - > mmio ,
VORTEX_MIX_INVOL_A + ( ( ( mix < < 5 ) + mixin ) < < 2 ) , vol ) ;
if ( 1 ) { /* this_10, initialized to 1. */
temp =
hwread ( vortex - > mmio ,
VORTEX_MIX_INVOL_B + ( ( ( mix < < 5 ) + mixin ) < < 2 ) ) ;
if ( ( temp ! = 0x80 ) | | ( vol = = 0x80 ) )
return ;
}
hwwrite ( vortex - > mmio ,
VORTEX_MIX_INVOL_B + ( ( ( mix < < 5 ) + mixin ) < < 2 ) , vol ) ;
}
static void
vortex_mix_setenablebit ( vortex_t * vortex , unsigned char mix , int mixin , int en )
{
int temp , addr ;
if ( mixin < 0 )
addr = ( mixin + 3 ) ;
else
addr = mixin ;
addr = ( ( mix < < 3 ) + ( addr > > 2 ) ) < < 2 ;
temp = hwread ( vortex - > mmio , VORTEX_MIX_ENIN + addr ) ;
if ( en )
temp | = ( 1 < < ( mixin & 3 ) ) ;
else
temp & = ~ ( 1 < < ( mixin & 3 ) ) ;
/* Mute input. Astatic void crackling? */
hwwrite ( vortex - > mmio ,
VORTEX_MIX_INVOL_B + ( ( ( mix < < 5 ) + mixin ) < < 2 ) , 0x80 ) ;
/* Looks like clear buffer. */
hwwrite ( vortex - > mmio , VORTEX_MIX_SMP + ( mixin < < 2 ) , 0x0 ) ;
hwwrite ( vortex - > mmio , VORTEX_MIX_SMP + 4 + ( mixin < < 2 ) , 0x0 ) ;
/* Write enable bit. */
hwwrite ( vortex - > mmio , VORTEX_MIX_ENIN + addr , temp ) ;
}
static void
vortex_mix_killinput ( vortex_t * vortex , unsigned char mix , int mixin )
{
rampchs [ mix ] & = ~ ( 1 < < mixin ) ;
vortex_mix_setinputvolumebyte ( vortex , mix , mixin , 0x80 ) ;
mchannels [ mix ] & = ~ ( 1 < < mixin ) ;
vortex_mix_setenablebit ( vortex , mix , mixin , 0 ) ;
}
static void
vortex_mix_enableinput ( vortex_t * vortex , unsigned char mix , int mixin )
{
vortex_mix_killinput ( vortex , mix , mixin ) ;
if ( ( mchannels [ mix ] & ( 1 < < mixin ) ) = = 0 ) {
vortex_mix_setinputvolumebyte ( vortex , mix , mixin , 0x80 ) ; /*0x80 : mute */
mchannels [ mix ] | = ( 1 < < mixin ) ;
}
vortex_mix_setenablebit ( vortex , mix , mixin , 1 ) ;
}
static void
vortex_mix_disableinput ( vortex_t * vortex , unsigned char mix , int channel ,
int ramp )
{
if ( ramp ) {
rampchs [ mix ] | = ( 1 < < channel ) ;
// Register callback.
//vortex_mix_startrampvolume(vortex);
vortex_mix_killinput ( vortex , mix , channel ) ;
} else
vortex_mix_killinput ( vortex , mix , channel ) ;
}
static int
vortex_mixer_addWTD ( vortex_t * vortex , unsigned char mix , unsigned char ch )
{
int temp , lifeboat = 0 , prev ;
temp = hwread ( vortex - > mmio , VORTEX_MIXER_SR ) ;
if ( ( temp & ( 1 < < ch ) ) = = 0 ) {
hwwrite ( vortex - > mmio , VORTEX_MIXER_CHNBASE + ( ch < < 2 ) , mix ) ;
vortex_mixer_en_sr ( vortex , ch ) ;
return 1 ;
}
prev = VORTEX_MIXER_CHNBASE + ( ch < < 2 ) ;
temp = hwread ( vortex - > mmio , prev ) ;
while ( temp & 0x10 ) {
prev = VORTEX_MIXER_RTBASE + ( ( temp & 0xf ) < < 2 ) ;
temp = hwread ( vortex - > mmio , prev ) ;
//printk(KERN_INFO "vortex: mixAddWTD: while addr=%x, val=%x\n", prev, temp);
if ( ( + + lifeboat ) > 0xf ) {
printk ( KERN_ERR
" vortex_mixer_addWTD: lifeboat overflow \n " ) ;
return 0 ;
}
}
hwwrite ( vortex - > mmio , VORTEX_MIXER_RTBASE + ( ( temp & 0xf ) < < 2 ) , mix ) ;
hwwrite ( vortex - > mmio , prev , ( temp & 0xf ) | 0x10 ) ;
return 1 ;
}
static int
vortex_mixer_delWTD ( vortex_t * vortex , unsigned char mix , unsigned char ch )
{
int esp14 = - 1 , esp18 , eax , ebx , edx , ebp , esi = 0 ;
//int esp1f=edi(while)=src, esp10=ch;
eax = hwread ( vortex - > mmio , VORTEX_MIXER_SR ) ;
if ( ( ( 1 < < ch ) & eax ) = = 0 ) {
printk ( KERN_ERR " mix ALARM %x \n " , eax ) ;
return 0 ;
}
ebp = VORTEX_MIXER_CHNBASE + ( ch < < 2 ) ;
esp18 = hwread ( vortex - > mmio , ebp ) ;
if ( esp18 & 0x10 ) {
ebx = ( esp18 & 0xf ) ;
if ( mix = = ebx ) {
ebx = VORTEX_MIXER_RTBASE + ( mix < < 2 ) ;
edx = hwread ( vortex - > mmio , ebx ) ;
//7b60
hwwrite ( vortex - > mmio , ebp , edx ) ;
hwwrite ( vortex - > mmio , ebx , 0 ) ;
} else {
//7ad3
edx =
hwread ( vortex - > mmio ,
VORTEX_MIXER_RTBASE + ( ebx < < 2 ) ) ;
//printk(KERN_INFO "vortex: mixdelWTD: 1 addr=%x, val=%x, src=%x\n", ebx, edx, src);
while ( ( edx & 0xf ) ! = mix ) {
if ( ( esi ) > 0xf ) {
printk ( KERN_ERR
" vortex: mixdelWTD: error lifeboat overflow \n " ) ;
return 0 ;
}
esp14 = ebx ;
ebx = edx & 0xf ;
ebp = ebx < < 2 ;
edx =
hwread ( vortex - > mmio ,
VORTEX_MIXER_RTBASE + ebp ) ;
//printk(KERN_INFO "vortex: mixdelWTD: while addr=%x, val=%x\n", ebp, edx);
esi + + ;
}
//7b30
ebp = ebx < < 2 ;
if ( edx & 0x10 ) { /* Delete entry in between others */
ebx = VORTEX_MIXER_RTBASE + ( ( edx & 0xf ) < < 2 ) ;
edx = hwread ( vortex - > mmio , ebx ) ;
//7b60
hwwrite ( vortex - > mmio ,
VORTEX_MIXER_RTBASE + ebp , edx ) ;
hwwrite ( vortex - > mmio , ebx , 0 ) ;
//printk(KERN_INFO "vortex mixdelWTD between addr= 0x%x, val= 0x%x\n", ebp, edx);
} else { /* Delete last entry */
//7b83
if ( esp14 = = - 1 )
hwwrite ( vortex - > mmio ,
VORTEX_MIXER_CHNBASE +
( ch < < 2 ) , esp18 & 0xef ) ;
else {
ebx = ( 0xffffffe0 & edx ) | ( 0xf & ebx ) ;
hwwrite ( vortex - > mmio ,
VORTEX_MIXER_RTBASE +
( esp14 < < 2 ) , ebx ) ;
//printk(KERN_INFO "vortex mixdelWTD last addr= 0x%x, val= 0x%x\n", esp14, ebx);
}
hwwrite ( vortex - > mmio ,
VORTEX_MIXER_RTBASE + ebp , 0 ) ;
return 1 ;
}
}
} else {
//printk(KERN_INFO "removed last mix\n");
//7be0
vortex_mixer_dis_sr ( vortex , ch ) ;
hwwrite ( vortex - > mmio , ebp , 0 ) ;
}
return 1 ;
}
static void vortex_mixer_init ( vortex_t * vortex )
{
2006-01-13 17:16:29 +01:00
u32 addr ;
2005-04-16 15:20:36 -07:00
int x ;
// FIXME: get rid of this crap.
memset ( mchannels , 0 , NR_MIXOUT * sizeof ( int ) ) ;
memset ( rampchs , 0 , NR_MIXOUT * sizeof ( int ) ) ;
addr = VORTEX_MIX_SMP + 0x17c ;
for ( x = 0x5f ; x > = 0 ; x - - ) {
hwwrite ( vortex - > mmio , addr , 0 ) ;
addr - = 4 ;
}
addr = VORTEX_MIX_ENIN + 0x1fc ;
for ( x = 0x7f ; x > = 0 ; x - - ) {
hwwrite ( vortex - > mmio , addr , 0 ) ;
addr - = 4 ;
}
addr = VORTEX_MIX_SMP + 0x17c ;
for ( x = 0x5f ; x > = 0 ; x - - ) {
hwwrite ( vortex - > mmio , addr , 0 ) ;
addr - = 4 ;
}
addr = VORTEX_MIX_INVOL_A + 0x7fc ;
for ( x = 0x1ff ; x > = 0 ; x - - ) {
hwwrite ( vortex - > mmio , addr , 0x80 ) ;
addr - = 4 ;
}
addr = VORTEX_MIX_VOL_A + 0x3c ;
for ( x = 0xf ; x > = 0 ; x - - ) {
hwwrite ( vortex - > mmio , addr , 0x80 ) ;
addr - = 4 ;
}
addr = VORTEX_MIX_INVOL_B + 0x7fc ;
for ( x = 0x1ff ; x > = 0 ; x - - ) {
hwwrite ( vortex - > mmio , addr , 0x80 ) ;
addr - = 4 ;
}
addr = VORTEX_MIX_VOL_B + 0x3c ;
for ( x = 0xf ; x > = 0 ; x - - ) {
hwwrite ( vortex - > mmio , addr , 0x80 ) ;
addr - = 4 ;
}
addr = VORTEX_MIXER_RTBASE + ( MIXER_RTBASE_SIZE - 1 ) * 4 ;
for ( x = ( MIXER_RTBASE_SIZE - 1 ) ; x > = 0 ; x - - ) {
hwwrite ( vortex - > mmio , addr , 0x0 ) ;
addr - = 4 ;
}
hwwrite ( vortex - > mmio , VORTEX_MIXER_SR , 0 ) ;
/* Set clipping ceiling (this may be all wrong). */
/*
for ( x = 0 ; x > 0x80 ; x + + ) {
hwwrite ( vortex - > mmio , VORTEX_MIXER_CLIP + ( x < < 2 ) , 0x3ffff ) ;
}
*/
/*
call CAsp4Mix__Initialize_CAsp4HwIO____CAsp4Mixer____
Register ISR callback for volume smooth fade out .
Maybe this avoids clicks when press " stop " ?
*/
}
/* SRC (CAsp4Src.s and CAsp4SrcBlock) */
static void vortex_src_en_sr ( vortex_t * vortex , int channel )
{
hwwrite ( vortex - > mmio , VORTEX_SRCBLOCK_SR ,
hwread ( vortex - > mmio , VORTEX_SRCBLOCK_SR ) | ( 0x1 < < channel ) ) ;
}
static void vortex_src_dis_sr ( vortex_t * vortex , int channel )
{
hwwrite ( vortex - > mmio , VORTEX_SRCBLOCK_SR ,
hwread ( vortex - > mmio , VORTEX_SRCBLOCK_SR ) & ~ ( 0x1 < < channel ) ) ;
}
static void vortex_src_flushbuffers ( vortex_t * vortex , unsigned char src )
{
int i ;
for ( i = 0x1f ; i > = 0 ; i - - )
hwwrite ( vortex - > mmio ,
VORTEX_SRC_DATA0 + ( src < < 7 ) + ( i < < 2 ) , 0 ) ;
hwwrite ( vortex - > mmio , VORTEX_SRC_DATA + ( src < < 3 ) , 0 ) ;
hwwrite ( vortex - > mmio , VORTEX_SRC_DATA + ( src < < 3 ) + 4 , 0 ) ;
}
static void vortex_src_cleardrift ( vortex_t * vortex , unsigned char src )
{
hwwrite ( vortex - > mmio , VORTEX_SRC_DRIFT0 + ( src < < 2 ) , 0 ) ;
hwwrite ( vortex - > mmio , VORTEX_SRC_DRIFT1 + ( src < < 2 ) , 0 ) ;
hwwrite ( vortex - > mmio , VORTEX_SRC_DRIFT2 + ( src < < 2 ) , 1 ) ;
}
static void
vortex_src_set_throttlesource ( vortex_t * vortex , unsigned char src , int en )
{
int temp ;
temp = hwread ( vortex - > mmio , VORTEX_SRC_SOURCE ) ;
if ( en )
temp | = 1 < < src ;
else
temp & = ~ ( 1 < < src ) ;
hwwrite ( vortex - > mmio , VORTEX_SRC_SOURCE , temp ) ;
}
static int
vortex_src_persist_convratio ( vortex_t * vortex , unsigned char src , int ratio )
{
int temp , lifeboat = 0 ;
do {
hwwrite ( vortex - > mmio , VORTEX_SRC_CONVRATIO + ( src < < 2 ) , ratio ) ;
temp = hwread ( vortex - > mmio , VORTEX_SRC_CONVRATIO + ( src < < 2 ) ) ;
if ( ( + + lifeboat ) > 0x9 ) {
printk ( KERN_ERR " Vortex: Src cvr fail \n " ) ;
break ;
}
}
while ( temp ! = ratio ) ;
return temp ;
}
#if 0
static void vortex_src_slowlock ( vortex_t * vortex , unsigned char src )
{
int temp ;
hwwrite ( vortex - > mmio , VORTEX_SRC_DRIFT2 + ( src < < 2 ) , 1 ) ;
hwwrite ( vortex - > mmio , VORTEX_SRC_DRIFT0 + ( src < < 2 ) , 0 ) ;
temp = hwread ( vortex - > mmio , VORTEX_SRC_U0 + ( src < < 2 ) ) ;
if ( temp & 0x200 )
hwwrite ( vortex - > mmio , VORTEX_SRC_U0 + ( src < < 2 ) ,
temp & ~ 0x200L ) ;
}
static void
vortex_src_change_convratio ( vortex_t * vortex , unsigned char src , int ratio )
{
int temp , a ;
if ( ( ratio & 0x10000 ) & & ( ratio ! = 0x10000 ) ) {
if ( ratio & 0x3fff )
a = ( 0x11 - ( ( ratio > > 0xe ) & 0x3 ) ) - 1 ;
else
a = ( 0x11 - ( ( ratio > > 0xe ) & 0x3 ) ) - 2 ;
} else
a = 0xc ;
temp = hwread ( vortex - > mmio , VORTEX_SRC_U0 + ( src < < 2 ) ) ;
if ( ( ( temp > > 4 ) & 0xf ) ! = a )
hwwrite ( vortex - > mmio , VORTEX_SRC_U0 + ( src < < 2 ) ,
( temp & 0xf ) | ( ( a & 0xf ) < < 4 ) ) ;
vortex_src_persist_convratio ( vortex , src , ratio ) ;
}
static int
vortex_src_checkratio ( vortex_t * vortex , unsigned char src ,
unsigned int desired_ratio )
{
int hw_ratio , lifeboat = 0 ;
hw_ratio = hwread ( vortex - > mmio , VORTEX_SRC_CONVRATIO + ( src < < 2 ) ) ;
while ( hw_ratio ! = desired_ratio ) {
hwwrite ( vortex - > mmio , VORTEX_SRC_CONVRATIO + ( src < < 2 ) , desired_ratio ) ;
if ( ( lifeboat + + ) > 15 ) {
printk ( KERN_ERR " Vortex: could not set src-%d from %d to %d \n " ,
src , hw_ratio , desired_ratio ) ;
break ;
}
}
return hw_ratio ;
}
# endif
/*
Objective : Set samplerate for given SRC module .
Arguments :
card : pointer to vortex_t strcut .
src : Integer index of the SRC module .
cr : Current sample rate conversion factor .
b : unknown 16 bit value .
sweep : Enable Samplerate fade from cr toward tr flag .
dirplay : 1 : playback , 0 : recording .
sl : Slow Lock flag .
tr : Target samplerate conversion .
thsource : Throttle source flag ( no idea what that means ) .
*/
static void vortex_src_setupchannel ( vortex_t * card , unsigned char src ,
unsigned int cr , unsigned int b , int sweep , int d ,
int dirplay , int sl , unsigned int tr , int thsource )
{
// noplayback: d=2,4,7,0xa,0xb when using first 2 src's.
// c: enables pitch sweep.
// looks like g is c related. Maybe g is a sweep parameter ?
// g = cvr
// dirplay: 0 = recording, 1 = playback
// d = src hw index.
int esi , ebp = 0 , esp10 ;
vortex_src_flushbuffers ( card , src ) ;
if ( sweep ) {
if ( ( tr & 0x10000 ) & & ( tr ! = 0x10000 ) ) {
tr = 0 ;
esi = 0x7 ;
} else {
if ( ( ( ( short ) tr ) < 0 ) & & ( tr ! = 0x8000 ) ) {
tr = 0 ;
esi = 0x8 ;
} else {
tr = 1 ;
esi = 0xc ;
}
}
} else {
if ( ( cr & 0x10000 ) & & ( cr ! = 0x10000 ) ) {
tr = 0 ; /*ebx = 0 */
esi = 0x11 - ( ( cr > > 0xe ) & 7 ) ;
if ( cr & 0x3fff )
esi - = 1 ;
else
esi - = 2 ;
} else {
tr = 1 ;
esi = 0xc ;
}
}
vortex_src_cleardrift ( card , src ) ;
vortex_src_set_throttlesource ( card , src , thsource ) ;
if ( ( dirplay = = 0 ) & & ( sweep = = 0 ) ) {
if ( tr )
esp10 = 0xf ;
else
esp10 = 0xc ;
ebp = 0 ;
} else {
if ( tr )
ebp = 0xf ;
else
ebp = 0xc ;
esp10 = 0 ;
}
hwwrite ( card - > mmio , VORTEX_SRC_U0 + ( src < < 2 ) ,
( sl < < 0x9 ) | ( sweep < < 0x8 ) | ( ( esi & 0xf ) < < 4 ) | d ) ;
/* 0xc0 esi=0xc c=f=0 d=0 */
vortex_src_persist_convratio ( card , src , cr ) ;
hwwrite ( card - > mmio , VORTEX_SRC_U1 + ( src < < 2 ) , b & 0xffff ) ;
/* 0 b=0 */
hwwrite ( card - > mmio , VORTEX_SRC_U2 + ( src < < 2 ) ,
( tr < < 0x11 ) | ( dirplay < < 0x10 ) | ( ebp < < 0x8 ) | esp10 ) ;
/* 0x30f00 e=g=1 esp10=0 ebp=f */
//printk(KERN_INFO "vortex: SRC %d, d=0x%x, esi=0x%x, esp10=0x%x, ebp=0x%x\n", src, d, esi, esp10, ebp);
}
static void vortex_srcblock_init ( vortex_t * vortex )
{
2006-01-13 17:16:29 +01:00
u32 addr ;
2005-04-16 15:20:36 -07:00
int x ;
hwwrite ( vortex - > mmio , VORTEX_SRC_SOURCESIZE , 0x1ff ) ;
/*
for ( x = 0 ; x < 0x10 ; x + + ) {
vortex_src_init ( & vortex_src [ x ] , x ) ;
}
*/
//addr = 0xcc3c;
//addr = 0x26c3c;
addr = VORTEX_SRC_RTBASE + 0x3c ;
for ( x = 0xf ; x > = 0 ; x - - ) {
hwwrite ( vortex - > mmio , addr , 0 ) ;
addr - = 4 ;
}
//addr = 0xcc94;
//addr = 0x26c94;
addr = VORTEX_SRC_CHNBASE + 0x54 ;
for ( x = 0x15 ; x > = 0 ; x - - ) {
hwwrite ( vortex - > mmio , addr , 0 ) ;
addr - = 4 ;
}
}
static int
vortex_src_addWTD ( vortex_t * vortex , unsigned char src , unsigned char ch )
{
int temp , lifeboat = 0 , prev ;
// esp13 = src
temp = hwread ( vortex - > mmio , VORTEX_SRCBLOCK_SR ) ;
if ( ( temp & ( 1 < < ch ) ) = = 0 ) {
hwwrite ( vortex - > mmio , VORTEX_SRC_CHNBASE + ( ch < < 2 ) , src ) ;
vortex_src_en_sr ( vortex , ch ) ;
return 1 ;
}
prev = VORTEX_SRC_CHNBASE + ( ch < < 2 ) ; /*ebp */
temp = hwread ( vortex - > mmio , prev ) ;
//while (temp & NR_SRC) {
while ( temp & 0x10 ) {
prev = VORTEX_SRC_RTBASE + ( ( temp & 0xf ) < < 2 ) ; /*esp12 */
//prev = VORTEX_SRC_RTBASE + ((temp & (NR_SRC-1)) << 2); /*esp12*/
temp = hwread ( vortex - > mmio , prev ) ;
//printk(KERN_INFO "vortex: srcAddWTD: while addr=%x, val=%x\n", prev, temp);
if ( ( + + lifeboat ) > 0xf ) {
printk ( KERN_ERR
" vortex_src_addWTD: lifeboat overflow \n " ) ;
return 0 ;
}
}
hwwrite ( vortex - > mmio , VORTEX_SRC_RTBASE + ( ( temp & 0xf ) < < 2 ) , src ) ;
//hwwrite(vortex->mmio, prev, (temp & (NR_SRC-1)) | NR_SRC);
hwwrite ( vortex - > mmio , prev , ( temp & 0xf ) | 0x10 ) ;
return 1 ;
}
static int
vortex_src_delWTD ( vortex_t * vortex , unsigned char src , unsigned char ch )
{
int esp14 = - 1 , esp18 , eax , ebx , edx , ebp , esi = 0 ;
//int esp1f=edi(while)=src, esp10=ch;
eax = hwread ( vortex - > mmio , VORTEX_SRCBLOCK_SR ) ;
if ( ( ( 1 < < ch ) & eax ) = = 0 ) {
printk ( KERN_ERR " src alarm \n " ) ;
return 0 ;
}
ebp = VORTEX_SRC_CHNBASE + ( ch < < 2 ) ;
esp18 = hwread ( vortex - > mmio , ebp ) ;
if ( esp18 & 0x10 ) {
ebx = ( esp18 & 0xf ) ;
if ( src = = ebx ) {
ebx = VORTEX_SRC_RTBASE + ( src < < 2 ) ;
edx = hwread ( vortex - > mmio , ebx ) ;
//7b60
hwwrite ( vortex - > mmio , ebp , edx ) ;
hwwrite ( vortex - > mmio , ebx , 0 ) ;
} else {
//7ad3
edx =
hwread ( vortex - > mmio ,
VORTEX_SRC_RTBASE + ( ebx < < 2 ) ) ;
//printk(KERN_INFO "vortex: srcdelWTD: 1 addr=%x, val=%x, src=%x\n", ebx, edx, src);
while ( ( edx & 0xf ) ! = src ) {
if ( ( esi ) > 0xf ) {
printk
( " vortex: srcdelWTD: error, lifeboat overflow \n " ) ;
return 0 ;
}
esp14 = ebx ;
ebx = edx & 0xf ;
ebp = ebx < < 2 ;
edx =
hwread ( vortex - > mmio ,
VORTEX_SRC_RTBASE + ebp ) ;
//printk(KERN_INFO "vortex: srcdelWTD: while addr=%x, val=%x\n", ebp, edx);
esi + + ;
}
//7b30
ebp = ebx < < 2 ;
if ( edx & 0x10 ) { /* Delete entry in between others */
ebx = VORTEX_SRC_RTBASE + ( ( edx & 0xf ) < < 2 ) ;
edx = hwread ( vortex - > mmio , ebx ) ;
//7b60
hwwrite ( vortex - > mmio ,
VORTEX_SRC_RTBASE + ebp , edx ) ;
hwwrite ( vortex - > mmio , ebx , 0 ) ;
//printk(KERN_INFO "vortex srcdelWTD between addr= 0x%x, val= 0x%x\n", ebp, edx);
} else { /* Delete last entry */
//7b83
if ( esp14 = = - 1 )
hwwrite ( vortex - > mmio ,
VORTEX_SRC_CHNBASE +
( ch < < 2 ) , esp18 & 0xef ) ;
else {
ebx = ( 0xffffffe0 & edx ) | ( 0xf & ebx ) ;
hwwrite ( vortex - > mmio ,
VORTEX_SRC_RTBASE +
( esp14 < < 2 ) , ebx ) ;
//printk(KERN_INFO"vortex srcdelWTD last addr= 0x%x, val= 0x%x\n", esp14, ebx);
}
hwwrite ( vortex - > mmio ,
VORTEX_SRC_RTBASE + ebp , 0 ) ;
return 1 ;
}
}
} else {
//7be0
vortex_src_dis_sr ( vortex , ch ) ;
hwwrite ( vortex - > mmio , ebp , 0 ) ;
}
return 1 ;
}
/*FIFO*/
static void
vortex_fifo_clearadbdata ( vortex_t * vortex , int fifo , int x )
{
for ( x - - ; x > = 0 ; x - - )
hwwrite ( vortex - > mmio ,
VORTEX_FIFO_ADBDATA +
( ( ( fifo < < FIFO_SIZE_BITS ) + x ) < < 2 ) , 0 ) ;
}
#if 0
static void vortex_fifo_adbinitialize ( vortex_t * vortex , int fifo , int j )
{
vortex_fifo_clearadbdata ( vortex , fifo , FIFO_SIZE ) ;
# ifdef CHIP_AU8820
hwwrite ( vortex - > mmio , VORTEX_FIFO_ADBCTRL + ( fifo < < 2 ) ,
( FIFO_U1 | ( ( j & FIFO_MASK ) < < 0xb ) ) ) ;
# else
hwwrite ( vortex - > mmio , VORTEX_FIFO_ADBCTRL + ( fifo < < 2 ) ,
( FIFO_U1 | ( ( j & FIFO_MASK ) < < 0xc ) ) ) ;
# endif
}
# endif
static void vortex_fifo_setadbvalid ( vortex_t * vortex , int fifo , int en )
{
hwwrite ( vortex - > mmio , VORTEX_FIFO_ADBCTRL + ( fifo < < 2 ) ,
( hwread ( vortex - > mmio , VORTEX_FIFO_ADBCTRL + ( fifo < < 2 ) ) &
0xffffffef ) | ( ( 1 & en ) < < 4 ) | FIFO_U1 ) ;
}
static void
vortex_fifo_setadbctrl ( vortex_t * vortex , int fifo , int b , int priority ,
int empty , int valid , int f )
{
int temp , lifeboat = 0 ;
//int this_8[NR_ADB] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; /* position */
int this_4 = 0x2 ;
/* f seems priority related.
* CAsp4AdbDma : : SetPriority is the only place that calls SetAdbCtrl with f set to 1
* every where else it is set to 0. It seems , however , that CAsp4AdbDma : : SetPriority
* is never called , thus the f related bits remain a mystery for now .
*/
do {
temp = hwread ( vortex - > mmio , VORTEX_FIFO_ADBCTRL + ( fifo < < 2 ) ) ;
if ( lifeboat + + > 0xbb8 ) {
printk ( KERN_ERR
" Vortex: vortex_fifo_setadbctrl fail \n " ) ;
break ;
}
}
while ( temp & FIFO_RDONLY ) ;
// AU8830 semes to take some special care about fifo content (data).
// But i'm just to lazy to translate that :)
if ( valid ) {
if ( ( temp & FIFO_VALID ) = = 0 ) {
//this_8[fifo] = 0;
vortex_fifo_clearadbdata ( vortex , fifo , FIFO_SIZE ) ; // this_4
# ifdef CHIP_AU8820
temp = ( this_4 & 0x1f ) < < 0xb ;
# else
temp = ( this_4 & 0x3f ) < < 0xc ;
# endif
temp = ( temp & 0xfffffffd ) | ( ( b & 1 ) < < 1 ) ;
temp = ( temp & 0xfffffff3 ) | ( ( priority & 3 ) < < 2 ) ;
temp = ( temp & 0xffffffef ) | ( ( valid & 1 ) < < 4 ) ;
temp | = FIFO_U1 ;
temp = ( temp & 0xffffffdf ) | ( ( empty & 1 ) < < 5 ) ;
# ifdef CHIP_AU8820
temp = ( temp & 0xfffbffff ) | ( ( f & 1 ) < < 0x12 ) ;
# endif
# ifdef CHIP_AU8830
temp = ( temp & 0xf7ffffff ) | ( ( f & 1 ) < < 0x1b ) ;
temp = ( temp & 0xefffffff ) | ( ( f & 1 ) < < 0x1c ) ;
# endif
# ifdef CHIP_AU8810
temp = ( temp & 0xfeffffff ) | ( ( f & 1 ) < < 0x18 ) ;
temp = ( temp & 0xfdffffff ) | ( ( f & 1 ) < < 0x19 ) ;
# endif
}
} else {
if ( temp & FIFO_VALID ) {
# ifdef CHIP_AU8820
temp = ( ( f & 1 ) < < 0x12 ) | ( temp & 0xfffbffef ) ;
# endif
# ifdef CHIP_AU8830
temp =
( ( f & 1 ) < < 0x1b ) | ( temp & 0xe7ffffef ) | FIFO_BITS ;
# endif
# ifdef CHIP_AU8810
temp =
( ( f & 1 ) < < 0x18 ) | ( temp & 0xfcffffef ) | FIFO_BITS ;
# endif
} else
/*if (this_8[fifo]) */
vortex_fifo_clearadbdata ( vortex , fifo , FIFO_SIZE ) ;
}
hwwrite ( vortex - > mmio , VORTEX_FIFO_ADBCTRL + ( fifo < < 2 ) , temp ) ;
hwread ( vortex - > mmio , VORTEX_FIFO_ADBCTRL + ( fifo < < 2 ) ) ;
}
# ifndef CHIP_AU8810
static void vortex_fifo_clearwtdata ( vortex_t * vortex , int fifo , int x )
{
if ( x < 1 )
return ;
for ( x - - ; x > = 0 ; x - - )
hwwrite ( vortex - > mmio ,
VORTEX_FIFO_WTDATA +
( ( ( fifo < < FIFO_SIZE_BITS ) + x ) < < 2 ) , 0 ) ;
}
static void vortex_fifo_wtinitialize ( vortex_t * vortex , int fifo , int j )
{
vortex_fifo_clearwtdata ( vortex , fifo , FIFO_SIZE ) ;
# ifdef CHIP_AU8820
hwwrite ( vortex - > mmio , VORTEX_FIFO_WTCTRL + ( fifo < < 2 ) ,
( FIFO_U1 | ( ( j & FIFO_MASK ) < < 0xb ) ) ) ;
# else
hwwrite ( vortex - > mmio , VORTEX_FIFO_WTCTRL + ( fifo < < 2 ) ,
( FIFO_U1 | ( ( j & FIFO_MASK ) < < 0xc ) ) ) ;
# endif
}
static void vortex_fifo_setwtvalid ( vortex_t * vortex , int fifo , int en )
{
hwwrite ( vortex - > mmio , VORTEX_FIFO_WTCTRL + ( fifo < < 2 ) ,
( hwread ( vortex - > mmio , VORTEX_FIFO_WTCTRL + ( fifo < < 2 ) ) &
0xffffffef ) | ( ( en & 1 ) < < 4 ) | FIFO_U1 ) ;
}
static void
vortex_fifo_setwtctrl ( vortex_t * vortex , int fifo , int ctrl , int priority ,
int empty , int valid , int f )
{
int temp = 0 , lifeboat = 0 ;
int this_4 = 2 ;
do {
temp = hwread ( vortex - > mmio , VORTEX_FIFO_WTCTRL + ( fifo < < 2 ) ) ;
if ( lifeboat + + > 0xbb8 ) {
printk ( KERN_ERR " Vortex: vortex_fifo_setwtctrl fail \n " ) ;
break ;
}
}
while ( temp & FIFO_RDONLY ) ;
if ( valid ) {
if ( ( temp & FIFO_VALID ) = = 0 ) {
vortex_fifo_clearwtdata ( vortex , fifo , FIFO_SIZE ) ; // this_4
# ifdef CHIP_AU8820
temp = ( this_4 & 0x1f ) < < 0xb ;
# else
temp = ( this_4 & 0x3f ) < < 0xc ;
# endif
temp = ( temp & 0xfffffffd ) | ( ( ctrl & 1 ) < < 1 ) ;
temp = ( temp & 0xfffffff3 ) | ( ( priority & 3 ) < < 2 ) ;
temp = ( temp & 0xffffffef ) | ( ( valid & 1 ) < < 4 ) ;
temp | = FIFO_U1 ;
temp = ( temp & 0xffffffdf ) | ( ( empty & 1 ) < < 5 ) ;
# ifdef CHIP_AU8820
temp = ( temp & 0xfffbffff ) | ( ( f & 1 ) < < 0x12 ) ;
# endif
# ifdef CHIP_AU8830
temp = ( temp & 0xf7ffffff ) | ( ( f & 1 ) < < 0x1b ) ;
temp = ( temp & 0xefffffff ) | ( ( f & 1 ) < < 0x1c ) ;
# endif
# ifdef CHIP_AU8810
temp = ( temp & 0xfeffffff ) | ( ( f & 1 ) < < 0x18 ) ;
temp = ( temp & 0xfdffffff ) | ( ( f & 1 ) < < 0x19 ) ;
# endif
}
} else {
if ( temp & FIFO_VALID ) {
# ifdef CHIP_AU8820
temp = ( ( f & 1 ) < < 0x12 ) | ( temp & 0xfffbffef ) ;
# endif
# ifdef CHIP_AU8830
temp =
( ( f & 1 ) < < 0x1b ) | ( temp & 0xe7ffffef ) | FIFO_BITS ;
# endif
# ifdef CHIP_AU8810
temp =
( ( f & 1 ) < < 0x18 ) | ( temp & 0xfcffffef ) | FIFO_BITS ;
# endif
} else
/*if (this_8[fifo]) */
vortex_fifo_clearwtdata ( vortex , fifo , FIFO_SIZE ) ;
}
hwwrite ( vortex - > mmio , VORTEX_FIFO_WTCTRL + ( fifo < < 2 ) , temp ) ;
hwread ( vortex - > mmio , VORTEX_FIFO_WTCTRL + ( fifo < < 2 ) ) ;
/*
do {
temp = hwread ( vortex - > mmio , VORTEX_FIFO_WTCTRL + ( fifo < < 2 ) ) ;
if ( lifeboat + + > 0xbb8 ) {
printk ( KERN_ERR " Vortex: vortex_fifo_setwtctrl fail (hanging) \n " ) ;
break ;
}
} while ( ( temp & FIFO_RDONLY ) & & ( temp & FIFO_VALID ) & & ( temp ! = 0xFFFFFFFF ) ) ;
if ( valid ) {
if ( temp & FIFO_VALID ) {
temp = 0x40000 ;
//temp |= 0x08000000;
//temp |= 0x10000000;
//temp |= 0x04000000;
//temp |= 0x00400000;
temp | = 0x1c400000 ;
temp & = 0xFFFFFFF3 ;
temp & = 0xFFFFFFEF ;
temp | = ( valid & 1 ) < < 4 ;
hwwrite ( vortex - > mmio , VORTEX_FIFO_WTCTRL + ( fifo < < 2 ) , temp ) ;
return ;
} else {
vortex_fifo_clearwtdata ( vortex , fifo , FIFO_SIZE ) ;
return ;
}
} else {
temp & = 0xffffffef ;
temp | = 0x08000000 ;
temp | = 0x10000000 ;
temp | = 0x04000000 ;
temp | = 0x00400000 ;
hwwrite ( vortex - > mmio , VORTEX_FIFO_WTCTRL + ( fifo < < 2 ) , temp ) ;
temp = hwread ( vortex - > mmio , VORTEX_FIFO_WTCTRL + ( fifo < < 2 ) ) ;
//((temp >> 6) & 0x3f)
priority = 0 ;
if ( ( ( temp & 0x0fc0 ) ^ ( ( temp > > 6 ) & 0x0fc0 ) ) & 0FF FFFFC0 )
vortex_fifo_clearwtdata ( vortex , fifo , FIFO_SIZE ) ;
valid = 0xfb ;
temp = ( temp & 0xfffffffd ) | ( ( ctrl & 1 ) < < 1 ) ;
temp = ( temp & 0xfffdffff ) | ( ( f & 1 ) < < 0x11 ) ;
temp = ( temp & 0xfffffff3 ) | ( ( priority & 3 ) < < 2 ) ;
temp = ( temp & 0xffffffef ) | ( ( valid & 1 ) < < 4 ) ;
temp = ( temp & 0xffffffdf ) | ( ( empty & 1 ) < < 5 ) ;
hwwrite ( vortex - > mmio , VORTEX_FIFO_WTCTRL + ( fifo < < 2 ) , temp ) ;
}
*/
/*
temp = ( temp & 0xfffffffd ) | ( ( ctrl & 1 ) < < 1 ) ;
temp = ( temp & 0xfffdffff ) | ( ( f & 1 ) < < 0x11 ) ;
temp = ( temp & 0xfffffff3 ) | ( ( priority & 3 ) < < 2 ) ;
temp = ( temp & 0xffffffef ) | ( ( valid & 1 ) < < 4 ) ;
temp = ( temp & 0xffffffdf ) | ( ( empty & 1 ) < < 5 ) ;
# ifdef FIFO_BITS
temp = temp | FIFO_BITS | 40000 ;
# endif
// 0x1c440010, 0x1c400000
hwwrite ( vortex - > mmio , VORTEX_FIFO_WTCTRL + ( fifo < < 2 ) , temp ) ;
*/
}
# endif
static void vortex_fifo_init ( vortex_t * vortex )
{
int x ;
2006-01-13 17:16:29 +01:00
u32 addr ;
2005-04-16 15:20:36 -07:00
/* ADB DMA channels fifos. */
addr = VORTEX_FIFO_ADBCTRL + ( ( NR_ADB - 1 ) * 4 ) ;
for ( x = NR_ADB - 1 ; x > = 0 ; x - - ) {
hwwrite ( vortex - > mmio , addr , ( FIFO_U0 | FIFO_U1 ) ) ;
if ( hwread ( vortex - > mmio , addr ) ! = ( FIFO_U0 | FIFO_U1 ) )
printk ( KERN_ERR " bad adb fifo reset! " ) ;
vortex_fifo_clearadbdata ( vortex , x , FIFO_SIZE ) ;
addr - = 4 ;
}
# ifndef CHIP_AU8810
/* WT DMA channels fifos. */
addr = VORTEX_FIFO_WTCTRL + ( ( NR_WT - 1 ) * 4 ) ;
for ( x = NR_WT - 1 ; x > = 0 ; x - - ) {
hwwrite ( vortex - > mmio , addr , FIFO_U0 ) ;
if ( hwread ( vortex - > mmio , addr ) ! = FIFO_U0 )
printk ( KERN_ERR
2006-01-13 17:16:29 +01:00
" bad wt fifo reset (0x%08x, 0x%08x)! \n " ,
2005-04-16 15:20:36 -07:00
addr , hwread ( vortex - > mmio , addr ) ) ;
vortex_fifo_clearwtdata ( vortex , x , FIFO_SIZE ) ;
addr - = 4 ;
}
# endif
/* trigger... */
# ifdef CHIP_AU8820
hwwrite ( vortex - > mmio , 0xf8c0 , 0xd03 ) ; //0x0843 0xd6b
# else
# ifdef CHIP_AU8830
hwwrite ( vortex - > mmio , 0x17000 , 0x61 ) ; /* wt a */
hwwrite ( vortex - > mmio , 0x17004 , 0x61 ) ; /* wt b */
# endif
hwwrite ( vortex - > mmio , 0x17008 , 0x61 ) ; /* adb */
# endif
}
/* ADBDMA */
static void vortex_adbdma_init ( vortex_t * vortex )
{
}
static void vortex_adbdma_setfirstbuffer ( vortex_t * vortex , int adbdma )
{
stream_t * dma = & vortex - > dma_adb [ adbdma ] ;
hwwrite ( vortex - > mmio , VORTEX_ADBDMA_CTRL + ( adbdma < < 2 ) ,
dma - > dma_ctrl ) ;
}
static void vortex_adbdma_setstartbuffer ( vortex_t * vortex , int adbdma , int sb )
{
stream_t * dma = & vortex - > dma_adb [ adbdma ] ;
//hwwrite(vortex->mmio, VORTEX_ADBDMA_START + (adbdma << 2), sb << (((NR_ADB-1)-((adbdma&0xf)*2))));
hwwrite ( vortex - > mmio , VORTEX_ADBDMA_START + ( adbdma < < 2 ) ,
sb < < ( ( 0xf - ( adbdma & 0xf ) ) * 2 ) ) ;
dma - > period_real = dma - > period_virt = sb ;
}
static void
vortex_adbdma_setbuffers ( vortex_t * vortex , int adbdma ,
2005-11-17 14:55:19 +01:00
struct snd_sg_buf * sgbuf , int psize , int count )
2005-04-16 15:20:36 -07:00
{
stream_t * dma = & vortex - > dma_adb [ adbdma ] ;
if ( sgbuf = = NULL ) {
printk ( KERN_INFO " vortex: FATAL: sgbuf is NULL! \n " ) ;
return ;
}
//printk(KERN_INFO "vortex: page count = %d, tblcount = %d\n", count, sgbuf->tblsize);
dma - > period_bytes = psize ;
dma - > nr_periods = count ;
dma - > sgbuf = sgbuf ;
dma - > cfg0 = 0 ;
dma - > cfg1 = 0 ;
switch ( count ) {
/* Four or more pages */
default :
case 4 :
dma - > cfg1 | = 0x88000000 | 0x44000000 | 0x30000000 | ( psize - 1 ) ;
hwwrite ( vortex - > mmio ,
VORTEX_ADBDMA_BUFBASE + ( adbdma < < 4 ) + 0xc ,
snd_sgbuf_get_addr ( sgbuf , psize * 3 ) ) ;
/* 3 pages */
case 3 :
dma - > cfg0 | = 0x12000000 ;
dma - > cfg1 | = 0x80000000 | 0x40000000 | ( ( psize - 1 ) < < 0xc ) ;
hwwrite ( vortex - > mmio ,
VORTEX_ADBDMA_BUFBASE + ( adbdma < < 4 ) + 0x8 ,
snd_sgbuf_get_addr ( sgbuf , psize * 2 ) ) ;
/* 2 pages */
case 2 :
dma - > cfg0 | = 0x88000000 | 0x44000000 | 0x10000000 | ( psize - 1 ) ;
hwwrite ( vortex - > mmio ,
VORTEX_ADBDMA_BUFBASE + ( adbdma < < 4 ) + 0x4 ,
snd_sgbuf_get_addr ( sgbuf , psize ) ) ;
/* 1 page */
case 1 :
dma - > cfg0 | = 0x80000000 | 0x40000000 | ( ( psize - 1 ) < < 0xc ) ;
hwwrite ( vortex - > mmio ,
VORTEX_ADBDMA_BUFBASE + ( adbdma < < 4 ) ,
snd_sgbuf_get_addr ( sgbuf , 0 ) ) ;
break ;
}
//printk("vortex: cfg0 = 0x%x\nvortex: cfg1=0x%x\n", dma->cfg0, dma->cfg1);
hwwrite ( vortex - > mmio , VORTEX_ADBDMA_BUFCFG0 + ( adbdma < < 3 ) , dma - > cfg0 ) ;
hwwrite ( vortex - > mmio , VORTEX_ADBDMA_BUFCFG1 + ( adbdma < < 3 ) , dma - > cfg1 ) ;
vortex_adbdma_setfirstbuffer ( vortex , adbdma ) ;
vortex_adbdma_setstartbuffer ( vortex , adbdma , 0 ) ;
}
static void
vortex_adbdma_setmode ( vortex_t * vortex , int adbdma , int ie , int dir ,
2006-01-13 17:16:29 +01:00
int fmt , int d , u32 offset )
2005-04-16 15:20:36 -07:00
{
stream_t * dma = & vortex - > dma_adb [ adbdma ] ;
dma - > dma_unknown = d ;
dma - > dma_ctrl =
( ( offset & OFFSET_MASK ) | ( dma - > dma_ctrl & ~ OFFSET_MASK ) ) ;
/* Enable PCMOUT interrupts. */
dma - > dma_ctrl =
( dma - > dma_ctrl & ~ IE_MASK ) | ( ( ie < < IE_SHIFT ) & IE_MASK ) ;
dma - > dma_ctrl =
( dma - > dma_ctrl & ~ DIR_MASK ) | ( ( dir < < DIR_SHIFT ) & DIR_MASK ) ;
dma - > dma_ctrl =
( dma - > dma_ctrl & ~ FMT_MASK ) | ( ( fmt < < FMT_SHIFT ) & FMT_MASK ) ;
hwwrite ( vortex - > mmio , VORTEX_ADBDMA_CTRL + ( adbdma < < 2 ) ,
dma - > dma_ctrl ) ;
hwread ( vortex - > mmio , VORTEX_ADBDMA_CTRL + ( adbdma < < 2 ) ) ;
}
static int vortex_adbdma_bufshift ( vortex_t * vortex , int adbdma )
{
stream_t * dma = & vortex - > dma_adb [ adbdma ] ;
int page , p , pp , delta , i ;
page =
( hwread ( vortex - > mmio , VORTEX_ADBDMA_STAT + ( adbdma < < 2 ) ) &
ADB_SUBBUF_MASK ) > > ADB_SUBBUF_SHIFT ;
if ( dma - > nr_periods > = 4 )
delta = ( page - dma - > period_real ) & 3 ;
else {
delta = ( page - dma - > period_real ) ;
if ( delta < 0 )
delta + = dma - > nr_periods ;
}
if ( delta = = 0 )
return 0 ;
/* refresh hw page table */
if ( dma - > nr_periods > 4 ) {
for ( i = 0 ; i < delta ; i + + ) {
/* p: audio buffer page index */
p = dma - > period_virt + i + 4 ;
if ( p > = dma - > nr_periods )
p - = dma - > nr_periods ;
/* pp: hardware DMA page index. */
pp = dma - > period_real + i ;
if ( pp > = 4 )
pp - = 4 ;
//hwwrite(vortex->mmio, VORTEX_ADBDMA_BUFBASE+(((adbdma << 2)+pp) << 2), dma->table[p].addr);
hwwrite ( vortex - > mmio ,
VORTEX_ADBDMA_BUFBASE + ( ( ( adbdma < < 2 ) + pp ) < < 2 ) ,
snd_sgbuf_get_addr ( dma - > sgbuf ,
dma - > period_bytes * p ) ) ;
/* Force write thru cache. */
hwread ( vortex - > mmio , VORTEX_ADBDMA_BUFBASE +
( ( ( adbdma < < 2 ) + pp ) < < 2 ) ) ;
}
}
dma - > period_virt + = delta ;
dma - > period_real = page ;
if ( dma - > period_virt > = dma - > nr_periods )
dma - > period_virt - = dma - > nr_periods ;
if ( delta ! = 1 )
printk ( KERN_INFO " vortex: %d virt=%d, real=%d, delta=%d \n " ,
adbdma , dma - > period_virt , dma - > period_real , delta ) ;
return delta ;
}
static void vortex_adbdma_resetup ( vortex_t * vortex , int adbdma ) {
stream_t * dma = & vortex - > dma_adb [ adbdma ] ;
int p , pp , i ;
/* refresh hw page table */
for ( i = 0 ; i < 4 & & i < dma - > nr_periods ; i + + ) {
/* p: audio buffer page index */
p = dma - > period_virt + i ;
if ( p > = dma - > nr_periods )
p - = dma - > nr_periods ;
/* pp: hardware DMA page index. */
pp = dma - > period_real + i ;
if ( dma - > nr_periods < 4 ) {
if ( pp > = dma - > nr_periods )
pp - = dma - > nr_periods ;
}
else {
if ( pp > = 4 )
pp - = 4 ;
}
hwwrite ( vortex - > mmio , VORTEX_ADBDMA_BUFBASE + ( ( ( adbdma < < 2 ) + pp ) < < 2 ) , snd_sgbuf_get_addr ( dma - > sgbuf , dma - > period_bytes * p ) ) ;
/* Force write thru cache. */
hwread ( vortex - > mmio , VORTEX_ADBDMA_BUFBASE + ( ( ( adbdma < < 2 ) + pp ) < < 2 ) ) ;
}
}
static int inline vortex_adbdma_getlinearpos ( vortex_t * vortex , int adbdma )
{
stream_t * dma = & vortex - > dma_adb [ adbdma ] ;
int temp ;
temp = hwread ( vortex - > mmio , VORTEX_ADBDMA_STAT + ( adbdma < < 2 ) ) ;
temp = ( dma - > period_virt * dma - > period_bytes ) + ( temp & POS_MASK ) ;
return ( temp ) ;
}
static void vortex_adbdma_startfifo ( vortex_t * vortex , int adbdma )
{
int this_8 = 0 /*empty */ , this_4 = 0 /*priority */ ;
stream_t * dma = & vortex - > dma_adb [ adbdma ] ;
switch ( dma - > fifo_status ) {
case FIFO_START :
vortex_fifo_setadbvalid ( vortex , adbdma ,
dma - > fifo_enabled ? 1 : 0 ) ;
break ;
case FIFO_STOP :
this_8 = 1 ;
hwwrite ( vortex - > mmio , VORTEX_ADBDMA_CTRL + ( adbdma < < 2 ) ,
dma - > dma_ctrl ) ;
vortex_fifo_setadbctrl ( vortex , adbdma , dma - > dma_unknown ,
this_4 , this_8 ,
dma - > fifo_enabled ? 1 : 0 , 0 ) ;
break ;
case FIFO_PAUSE :
vortex_fifo_setadbctrl ( vortex , adbdma , dma - > dma_unknown ,
this_4 , this_8 ,
dma - > fifo_enabled ? 1 : 0 , 0 ) ;
break ;
}
dma - > fifo_status = FIFO_START ;
}
static void vortex_adbdma_resumefifo ( vortex_t * vortex , int adbdma )
{
stream_t * dma = & vortex - > dma_adb [ adbdma ] ;
int this_8 = 1 , this_4 = 0 ;
switch ( dma - > fifo_status ) {
case FIFO_STOP :
hwwrite ( vortex - > mmio , VORTEX_ADBDMA_CTRL + ( adbdma < < 2 ) ,
dma - > dma_ctrl ) ;
vortex_fifo_setadbctrl ( vortex , adbdma , dma - > dma_unknown ,
this_4 , this_8 ,
dma - > fifo_enabled ? 1 : 0 , 0 ) ;
break ;
case FIFO_PAUSE :
vortex_fifo_setadbctrl ( vortex , adbdma , dma - > dma_unknown ,
this_4 , this_8 ,
dma - > fifo_enabled ? 1 : 0 , 0 ) ;
break ;
}
dma - > fifo_status = FIFO_START ;
}
static void vortex_adbdma_pausefifo ( vortex_t * vortex , int adbdma )
{
stream_t * dma = & vortex - > dma_adb [ adbdma ] ;
int this_8 = 0 , this_4 = 0 ;
switch ( dma - > fifo_status ) {
case FIFO_START :
vortex_fifo_setadbctrl ( vortex , adbdma , dma - > dma_unknown ,
this_4 , this_8 , 0 , 0 ) ;
break ;
case FIFO_STOP :
hwwrite ( vortex - > mmio , VORTEX_ADBDMA_CTRL + ( adbdma < < 2 ) ,
dma - > dma_ctrl ) ;
vortex_fifo_setadbctrl ( vortex , adbdma , dma - > dma_unknown ,
this_4 , this_8 , 0 , 0 ) ;
break ;
}
dma - > fifo_status = FIFO_PAUSE ;
}
#if 0 // Using pause instead
static void vortex_adbdma_stopfifo ( vortex_t * vortex , int adbdma )
{
stream_t * dma = & vortex - > dma_adb [ adbdma ] ;
int this_4 = 0 , this_8 = 0 ;
if ( dma - > fifo_status = = FIFO_START )
vortex_fifo_setadbctrl ( vortex , adbdma , dma - > dma_unknown ,
this_4 , this_8 , 0 , 0 ) ;
else if ( dma - > fifo_status = = FIFO_STOP )
return ;
dma - > fifo_status = FIFO_STOP ;
dma - > fifo_enabled = 0 ;
}
# endif
/* WTDMA */
# ifndef CHIP_AU8810
static void vortex_wtdma_setfirstbuffer ( vortex_t * vortex , int wtdma )
{
//int this_7c=dma_ctrl;
stream_t * dma = & vortex - > dma_wt [ wtdma ] ;
hwwrite ( vortex - > mmio , VORTEX_WTDMA_CTRL + ( wtdma < < 2 ) , dma - > dma_ctrl ) ;
}
static void vortex_wtdma_setstartbuffer ( vortex_t * vortex , int wtdma , int sb )
{
stream_t * dma = & vortex - > dma_wt [ wtdma ] ;
//hwwrite(vortex->mmio, VORTEX_WTDMA_START + (wtdma << 2), sb << ((0x1f-(wtdma&0xf)*2)));
hwwrite ( vortex - > mmio , VORTEX_WTDMA_START + ( wtdma < < 2 ) ,
sb < < ( ( 0xf - ( wtdma & 0xf ) ) * 2 ) ) ;
dma - > period_real = dma - > period_virt = sb ;
}
static void
vortex_wtdma_setbuffers ( vortex_t * vortex , int wtdma ,
2005-11-17 14:55:19 +01:00
struct snd_sg_buf * sgbuf , int psize , int count )
2005-04-16 15:20:36 -07:00
{
stream_t * dma = & vortex - > dma_wt [ wtdma ] ;
dma - > period_bytes = psize ;
dma - > nr_periods = count ;
dma - > sgbuf = sgbuf ;
dma - > cfg0 = 0 ;
dma - > cfg1 = 0 ;
switch ( count ) {
/* Four or more pages */
default :
case 4 :
dma - > cfg1 | = 0x88000000 | 0x44000000 | 0x30000000 | ( psize - 1 ) ;
hwwrite ( vortex - > mmio , VORTEX_WTDMA_BUFBASE + ( wtdma < < 4 ) + 0xc ,
snd_sgbuf_get_addr ( sgbuf , psize * 3 ) ) ;
/* 3 pages */
case 3 :
dma - > cfg0 | = 0x12000000 ;
dma - > cfg1 | = 0x80000000 | 0x40000000 | ( ( psize - 1 ) < < 0xc ) ;
hwwrite ( vortex - > mmio , VORTEX_WTDMA_BUFBASE + ( wtdma < < 4 ) + 0x8 ,
snd_sgbuf_get_addr ( sgbuf , psize * 2 ) ) ;
/* 2 pages */
case 2 :
dma - > cfg0 | = 0x88000000 | 0x44000000 | 0x10000000 | ( psize - 1 ) ;
hwwrite ( vortex - > mmio , VORTEX_WTDMA_BUFBASE + ( wtdma < < 4 ) + 0x4 ,
snd_sgbuf_get_addr ( sgbuf , psize ) ) ;
/* 1 page */
case 1 :
dma - > cfg0 | = 0x80000000 | 0x40000000 | ( ( psize - 1 ) < < 0xc ) ;
hwwrite ( vortex - > mmio , VORTEX_WTDMA_BUFBASE + ( wtdma < < 4 ) ,
snd_sgbuf_get_addr ( sgbuf , 0 ) ) ;
break ;
}
hwwrite ( vortex - > mmio , VORTEX_WTDMA_BUFCFG0 + ( wtdma < < 3 ) , dma - > cfg0 ) ;
hwwrite ( vortex - > mmio , VORTEX_WTDMA_BUFCFG1 + ( wtdma < < 3 ) , dma - > cfg1 ) ;
vortex_wtdma_setfirstbuffer ( vortex , wtdma ) ;
vortex_wtdma_setstartbuffer ( vortex , wtdma , 0 ) ;
}
static void
vortex_wtdma_setmode ( vortex_t * vortex , int wtdma , int ie , int fmt , int d ,
2006-01-13 17:16:29 +01:00
/*int e, */ u32 offset )
2005-04-16 15:20:36 -07:00
{
stream_t * dma = & vortex - > dma_wt [ wtdma ] ;
//dma->this_08 = e;
dma - > dma_unknown = d ;
dma - > dma_ctrl = 0 ;
dma - > dma_ctrl =
( ( offset & OFFSET_MASK ) | ( dma - > dma_ctrl & ~ OFFSET_MASK ) ) ;
/* PCMOUT interrupt */
dma - > dma_ctrl =
( dma - > dma_ctrl & ~ IE_MASK ) | ( ( ie < < IE_SHIFT ) & IE_MASK ) ;
/* Always playback. */
dma - > dma_ctrl | = ( 1 < < DIR_SHIFT ) ;
/* Audio Format */
dma - > dma_ctrl =
( dma - > dma_ctrl & FMT_MASK ) | ( ( fmt < < FMT_SHIFT ) & FMT_MASK ) ;
/* Write into hardware */
hwwrite ( vortex - > mmio , VORTEX_WTDMA_CTRL + ( wtdma < < 2 ) , dma - > dma_ctrl ) ;
}
static int vortex_wtdma_bufshift ( vortex_t * vortex , int wtdma )
{
stream_t * dma = & vortex - > dma_wt [ wtdma ] ;
int page , p , pp , delta , i ;
page =
( hwread ( vortex - > mmio , VORTEX_WTDMA_STAT + ( wtdma < < 2 ) ) &
WT_SUBBUF_MASK )
> > WT_SUBBUF_SHIFT ;
if ( dma - > nr_periods > = 4 )
delta = ( page - dma - > period_real ) & 3 ;
else {
delta = ( page - dma - > period_real ) ;
if ( delta < 0 )
delta + = dma - > nr_periods ;
}
if ( delta = = 0 )
return 0 ;
/* refresh hw page table */
if ( dma - > nr_periods > 4 ) {
for ( i = 0 ; i < delta ; i + + ) {
/* p: audio buffer page index */
p = dma - > period_virt + i + 4 ;
if ( p > = dma - > nr_periods )
p - = dma - > nr_periods ;
/* pp: hardware DMA page index. */
pp = dma - > period_real + i ;
if ( pp > = 4 )
pp - = 4 ;
hwwrite ( vortex - > mmio ,
VORTEX_WTDMA_BUFBASE +
( ( ( wtdma < < 2 ) + pp ) < < 2 ) ,
snd_sgbuf_get_addr ( dma - > sgbuf , dma - > period_bytes * p ) ) ;
/* Force write thru cache. */
hwread ( vortex - > mmio , VORTEX_WTDMA_BUFBASE +
( ( ( wtdma < < 2 ) + pp ) < < 2 ) ) ;
}
}
dma - > period_virt + = delta ;
if ( dma - > period_virt > = dma - > nr_periods )
dma - > period_virt - = dma - > nr_periods ;
dma - > period_real = page ;
if ( delta ! = 1 )
printk ( KERN_WARNING " vortex: wt virt = %d, delta = %d \n " ,
dma - > period_virt , delta ) ;
return delta ;
}
#if 0
static void
vortex_wtdma_getposition ( vortex_t * vortex , int wtdma , int * subbuf , int * pos )
{
int temp ;
temp = hwread ( vortex - > mmio , VORTEX_WTDMA_STAT + ( wtdma < < 2 ) ) ;
* subbuf = ( temp > > WT_SUBBUF_SHIFT ) & WT_SUBBUF_MASK ;
* pos = temp & POS_MASK ;
}
static int vortex_wtdma_getcursubuffer ( vortex_t * vortex , int wtdma )
{
return ( ( hwread ( vortex - > mmio , VORTEX_WTDMA_STAT + ( wtdma < < 2 ) ) > >
POS_SHIFT ) & POS_MASK ) ;
}
# endif
static int inline vortex_wtdma_getlinearpos ( vortex_t * vortex , int wtdma )
{
stream_t * dma = & vortex - > dma_wt [ wtdma ] ;
int temp ;
temp = hwread ( vortex - > mmio , VORTEX_WTDMA_STAT + ( wtdma < < 2 ) ) ;
//temp = (temp & POS_MASK) + (((temp>>WT_SUBBUF_SHIFT) & WT_SUBBUF_MASK)*(dma->cfg0&POS_MASK));
temp = ( temp & POS_MASK ) + ( ( dma - > period_virt ) * ( dma - > period_bytes ) ) ;
return temp ;
}
static void vortex_wtdma_startfifo ( vortex_t * vortex , int wtdma )
{
stream_t * dma = & vortex - > dma_wt [ wtdma ] ;
int this_8 = 0 , this_4 = 0 ;
switch ( dma - > fifo_status ) {
case FIFO_START :
vortex_fifo_setwtvalid ( vortex , wtdma ,
dma - > fifo_enabled ? 1 : 0 ) ;
break ;
case FIFO_STOP :
this_8 = 1 ;
hwwrite ( vortex - > mmio , VORTEX_WTDMA_CTRL + ( wtdma < < 2 ) ,
dma - > dma_ctrl ) ;
vortex_fifo_setwtctrl ( vortex , wtdma , dma - > dma_unknown ,
this_4 , this_8 ,
dma - > fifo_enabled ? 1 : 0 , 0 ) ;
break ;
case FIFO_PAUSE :
vortex_fifo_setwtctrl ( vortex , wtdma , dma - > dma_unknown ,
this_4 , this_8 ,
dma - > fifo_enabled ? 1 : 0 , 0 ) ;
break ;
}
dma - > fifo_status = FIFO_START ;
}
static void vortex_wtdma_resumefifo ( vortex_t * vortex , int wtdma )
{
stream_t * dma = & vortex - > dma_wt [ wtdma ] ;
int this_8 = 0 , this_4 = 0 ;
switch ( dma - > fifo_status ) {
case FIFO_STOP :
hwwrite ( vortex - > mmio , VORTEX_WTDMA_CTRL + ( wtdma < < 2 ) ,
dma - > dma_ctrl ) ;
vortex_fifo_setwtctrl ( vortex , wtdma , dma - > dma_unknown ,
this_4 , this_8 ,
dma - > fifo_enabled ? 1 : 0 , 0 ) ;
break ;
case FIFO_PAUSE :
vortex_fifo_setwtctrl ( vortex , wtdma , dma - > dma_unknown ,
this_4 , this_8 ,
dma - > fifo_enabled ? 1 : 0 , 0 ) ;
break ;
}
dma - > fifo_status = FIFO_START ;
}
static void vortex_wtdma_pausefifo ( vortex_t * vortex , int wtdma )
{
stream_t * dma = & vortex - > dma_wt [ wtdma ] ;
int this_8 = 0 , this_4 = 0 ;
switch ( dma - > fifo_status ) {
case FIFO_START :
vortex_fifo_setwtctrl ( vortex , wtdma , dma - > dma_unknown ,
this_4 , this_8 , 0 , 0 ) ;
break ;
case FIFO_STOP :
hwwrite ( vortex - > mmio , VORTEX_WTDMA_CTRL + ( wtdma < < 2 ) ,
dma - > dma_ctrl ) ;
vortex_fifo_setwtctrl ( vortex , wtdma , dma - > dma_unknown ,
this_4 , this_8 , 0 , 0 ) ;
break ;
}
dma - > fifo_status = FIFO_PAUSE ;
}
static void vortex_wtdma_stopfifo ( vortex_t * vortex , int wtdma )
{
stream_t * dma = & vortex - > dma_wt [ wtdma ] ;
int this_4 = 0 , this_8 = 0 ;
if ( dma - > fifo_status = = FIFO_START )
vortex_fifo_setwtctrl ( vortex , wtdma , dma - > dma_unknown ,
this_4 , this_8 , 0 , 0 ) ;
else if ( dma - > fifo_status = = FIFO_STOP )
return ;
dma - > fifo_status = FIFO_STOP ;
dma - > fifo_enabled = 0 ;
}
# endif
/* ADB Routes */
typedef int ADBRamLink ;
static void vortex_adb_init ( vortex_t * vortex )
{
int i ;
/* it looks like we are writing more than we need to...
* if we write what we are supposed to it breaks things . . . */
hwwrite ( vortex - > mmio , VORTEX_ADB_SR , 0 ) ;
for ( i = 0 ; i < VORTEX_ADB_RTBASE_COUNT ; i + + )
hwwrite ( vortex - > mmio , VORTEX_ADB_RTBASE + ( i < < 2 ) ,
hwread ( vortex - > mmio ,
VORTEX_ADB_RTBASE + ( i < < 2 ) ) | ROUTE_MASK ) ;
for ( i = 0 ; i < VORTEX_ADB_CHNBASE_COUNT ; i + + ) {
hwwrite ( vortex - > mmio , VORTEX_ADB_CHNBASE + ( i < < 2 ) ,
hwread ( vortex - > mmio ,
VORTEX_ADB_CHNBASE + ( i < < 2 ) ) | ROUTE_MASK ) ;
}
}
static void vortex_adb_en_sr ( vortex_t * vortex , int channel )
{
hwwrite ( vortex - > mmio , VORTEX_ADB_SR ,
hwread ( vortex - > mmio , VORTEX_ADB_SR ) | ( 0x1 < < channel ) ) ;
}
static void vortex_adb_dis_sr ( vortex_t * vortex , int channel )
{
hwwrite ( vortex - > mmio , VORTEX_ADB_SR ,
hwread ( vortex - > mmio , VORTEX_ADB_SR ) & ~ ( 0x1 < < channel ) ) ;
}
static void
vortex_adb_addroutes ( vortex_t * vortex , unsigned char channel ,
ADBRamLink * route , int rnum )
{
int temp , prev , lifeboat = 0 ;
if ( ( rnum < = 0 ) | | ( route = = NULL ) )
return ;
/* Write last routes. */
rnum - - ;
hwwrite ( vortex - > mmio ,
VORTEX_ADB_RTBASE + ( ( route [ rnum ] & ADB_MASK ) < < 2 ) ,
ROUTE_MASK ) ;
while ( rnum > 0 ) {
hwwrite ( vortex - > mmio ,
VORTEX_ADB_RTBASE +
( ( route [ rnum - 1 ] & ADB_MASK ) < < 2 ) , route [ rnum ] ) ;
rnum - - ;
}
/* Write first route. */
temp =
hwread ( vortex - > mmio ,
VORTEX_ADB_CHNBASE + ( channel < < 2 ) ) & ADB_MASK ;
if ( temp = = ADB_MASK ) {
/* First entry on this channel. */
hwwrite ( vortex - > mmio , VORTEX_ADB_CHNBASE + ( channel < < 2 ) ,
route [ 0 ] ) ;
vortex_adb_en_sr ( vortex , channel ) ;
return ;
}
/* Not first entry on this channel. Need to link. */
do {
prev = temp ;
temp =
hwread ( vortex - > mmio ,
VORTEX_ADB_RTBASE + ( temp < < 2 ) ) & ADB_MASK ;
if ( ( lifeboat + + ) > ADB_MASK ) {
printk ( KERN_ERR
" vortex_adb_addroutes: unending route! 0x%x \n " ,
* route ) ;
return ;
}
}
while ( temp ! = ADB_MASK ) ;
hwwrite ( vortex - > mmio , VORTEX_ADB_RTBASE + ( prev < < 2 ) , route [ 0 ] ) ;
}
static void
vortex_adb_delroutes ( vortex_t * vortex , unsigned char channel ,
ADBRamLink route0 , ADBRamLink route1 )
{
int temp , lifeboat = 0 , prev ;
/* Find route. */
temp =
hwread ( vortex - > mmio ,
VORTEX_ADB_CHNBASE + ( channel < < 2 ) ) & ADB_MASK ;
if ( temp = = ( route0 & ADB_MASK ) ) {
temp =
hwread ( vortex - > mmio ,
VORTEX_ADB_RTBASE + ( ( route1 & ADB_MASK ) < < 2 ) ) ;
if ( ( temp & ADB_MASK ) = = ADB_MASK )
vortex_adb_dis_sr ( vortex , channel ) ;
hwwrite ( vortex - > mmio , VORTEX_ADB_CHNBASE + ( channel < < 2 ) ,
temp ) ;
return ;
}
do {
prev = temp ;
temp =
hwread ( vortex - > mmio ,
VORTEX_ADB_RTBASE + ( prev < < 2 ) ) & ADB_MASK ;
if ( ( ( lifeboat + + ) > ADB_MASK ) | | ( temp = = ADB_MASK ) ) {
printk ( KERN_ERR
" vortex_adb_delroutes: route not found! 0x%x \n " ,
route0 ) ;
return ;
}
}
while ( temp ! = ( route0 & ADB_MASK ) ) ;
temp = hwread ( vortex - > mmio , VORTEX_ADB_RTBASE + ( temp < < 2 ) ) ;
if ( ( temp & ADB_MASK ) = = route1 )
temp = hwread ( vortex - > mmio , VORTEX_ADB_RTBASE + ( temp < < 2 ) ) ;
/* Make bridge over deleted route. */
hwwrite ( vortex - > mmio , VORTEX_ADB_RTBASE + ( prev < < 2 ) , temp ) ;
}
static void
vortex_route ( vortex_t * vortex , int en , unsigned char channel ,
unsigned char source , unsigned char dest )
{
ADBRamLink route ;
route = ( ( source & ADB_MASK ) < < ADB_SHIFT ) | ( dest & ADB_MASK ) ;
if ( en ) {
vortex_adb_addroutes ( vortex , channel , & route , 1 ) ;
if ( ( source < ( OFFSET_SRCOUT + NR_SRC ) )
& & ( source > = OFFSET_SRCOUT ) )
vortex_src_addWTD ( vortex , ( source - OFFSET_SRCOUT ) ,
channel ) ;
else if ( ( source < ( OFFSET_MIXOUT + NR_MIXOUT ) )
& & ( source > = OFFSET_MIXOUT ) )
vortex_mixer_addWTD ( vortex ,
( source - OFFSET_MIXOUT ) , channel ) ;
} else {
vortex_adb_delroutes ( vortex , channel , route , route ) ;
if ( ( source < ( OFFSET_SRCOUT + NR_SRC ) )
& & ( source > = OFFSET_SRCOUT ) )
vortex_src_delWTD ( vortex , ( source - OFFSET_SRCOUT ) ,
channel ) ;
else if ( ( source < ( OFFSET_MIXOUT + NR_MIXOUT ) )
& & ( source > = OFFSET_MIXOUT ) )
vortex_mixer_delWTD ( vortex ,
( source - OFFSET_MIXOUT ) , channel ) ;
}
}
#if 0
static void
vortex_routes ( vortex_t * vortex , int en , unsigned char channel ,
unsigned char source , unsigned char dest0 , unsigned char dest1 )
{
ADBRamLink route [ 2 ] ;
route [ 0 ] = ( ( source & ADB_MASK ) < < ADB_SHIFT ) | ( dest0 & ADB_MASK ) ;
route [ 1 ] = ( ( source & ADB_MASK ) < < ADB_SHIFT ) | ( dest1 & ADB_MASK ) ;
if ( en ) {
vortex_adb_addroutes ( vortex , channel , route , 2 ) ;
if ( ( source < ( OFFSET_SRCOUT + NR_SRC ) )
& & ( source > = ( OFFSET_SRCOUT ) ) )
vortex_src_addWTD ( vortex , ( source - OFFSET_SRCOUT ) ,
channel ) ;
else if ( ( source < ( OFFSET_MIXOUT + NR_MIXOUT ) )
& & ( source > = ( OFFSET_MIXOUT ) ) )
vortex_mixer_addWTD ( vortex ,
( source - OFFSET_MIXOUT ) , channel ) ;
} else {
vortex_adb_delroutes ( vortex , channel , route [ 0 ] , route [ 1 ] ) ;
if ( ( source < ( OFFSET_SRCOUT + NR_SRC ) )
& & ( source > = ( OFFSET_SRCOUT ) ) )
vortex_src_delWTD ( vortex , ( source - OFFSET_SRCOUT ) ,
channel ) ;
else if ( ( source < ( OFFSET_MIXOUT + NR_MIXOUT ) )
& & ( source > = ( OFFSET_MIXOUT ) ) )
vortex_mixer_delWTD ( vortex ,
( source - OFFSET_MIXOUT ) , channel ) ;
}
}
# endif
/* Route two sources to same target. Sources must be of same class !!! */
static void
vortex_routeLRT ( vortex_t * vortex , int en , unsigned char ch ,
unsigned char source0 , unsigned char source1 ,
unsigned char dest )
{
ADBRamLink route [ 2 ] ;
route [ 0 ] = ( ( source0 & ADB_MASK ) < < ADB_SHIFT ) | ( dest & ADB_MASK ) ;
route [ 1 ] = ( ( source1 & ADB_MASK ) < < ADB_SHIFT ) | ( dest & ADB_MASK ) ;
if ( dest < 0x10 )
route [ 1 ] = ( route [ 1 ] & ~ ADB_MASK ) | ( dest + 0x20 ) ; /* fifo A */
if ( en ) {
vortex_adb_addroutes ( vortex , ch , route , 2 ) ;
if ( ( source0 < ( OFFSET_SRCOUT + NR_SRC ) )
& & ( source0 > = OFFSET_SRCOUT ) ) {
vortex_src_addWTD ( vortex ,
( source0 - OFFSET_SRCOUT ) , ch ) ;
vortex_src_addWTD ( vortex ,
( source1 - OFFSET_SRCOUT ) , ch ) ;
} else if ( ( source0 < ( OFFSET_MIXOUT + NR_MIXOUT ) )
& & ( source0 > = OFFSET_MIXOUT ) ) {
vortex_mixer_addWTD ( vortex ,
( source0 - OFFSET_MIXOUT ) , ch ) ;
vortex_mixer_addWTD ( vortex ,
( source1 - OFFSET_MIXOUT ) , ch ) ;
}
} else {
vortex_adb_delroutes ( vortex , ch , route [ 0 ] , route [ 1 ] ) ;
if ( ( source0 < ( OFFSET_SRCOUT + NR_SRC ) )
& & ( source0 > = OFFSET_SRCOUT ) ) {
vortex_src_delWTD ( vortex ,
( source0 - OFFSET_SRCOUT ) , ch ) ;
vortex_src_delWTD ( vortex ,
( source1 - OFFSET_SRCOUT ) , ch ) ;
} else if ( ( source0 < ( OFFSET_MIXOUT + NR_MIXOUT ) )
& & ( source0 > = OFFSET_MIXOUT ) ) {
vortex_mixer_delWTD ( vortex ,
( source0 - OFFSET_MIXOUT ) , ch ) ;
vortex_mixer_delWTD ( vortex ,
( source1 - OFFSET_MIXOUT ) , ch ) ;
}
}
}
/* Connection stuff */
// Connect adbdma to src('s).
static void
vortex_connection_adbdma_src ( vortex_t * vortex , int en , unsigned char ch ,
unsigned char adbdma , unsigned char src )
{
vortex_route ( vortex , en , ch , ADB_DMA ( adbdma ) , ADB_SRCIN ( src ) ) ;
}
// Connect SRC to mixin.
static void
vortex_connection_src_mixin ( vortex_t * vortex , int en ,
unsigned char channel , unsigned char src ,
unsigned char mixin )
{
vortex_route ( vortex , en , channel , ADB_SRCOUT ( src ) , ADB_MIXIN ( mixin ) ) ;
}
// Connect mixin with mix output.
static void
vortex_connection_mixin_mix ( vortex_t * vortex , int en , unsigned char mixin ,
unsigned char mix , int a )
{
if ( en ) {
vortex_mix_enableinput ( vortex , mix , mixin ) ;
vortex_mix_setinputvolumebyte ( vortex , mix , mixin , MIX_DEFIGAIN ) ; // added to original code.
} else
vortex_mix_disableinput ( vortex , mix , mixin , a ) ;
}
// Connect absolut address to mixin.
static void
vortex_connection_adb_mixin ( vortex_t * vortex , int en ,
unsigned char channel , unsigned char source ,
unsigned char mixin )
{
vortex_route ( vortex , en , channel , source , ADB_MIXIN ( mixin ) ) ;
}
static void
vortex_connection_src_adbdma ( vortex_t * vortex , int en , unsigned char ch ,
unsigned char src , unsigned char adbdma )
{
vortex_route ( vortex , en , ch , ADB_SRCOUT ( src ) , ADB_DMA ( adbdma ) ) ;
}
static void
vortex_connection_src_src_adbdma ( vortex_t * vortex , int en ,
unsigned char ch , unsigned char src0 ,
unsigned char src1 , unsigned char adbdma )
{
vortex_routeLRT ( vortex , en , ch , ADB_SRCOUT ( src0 ) , ADB_SRCOUT ( src1 ) ,
ADB_DMA ( adbdma ) ) ;
}
// mix to absolut address.
static void
vortex_connection_mix_adb ( vortex_t * vortex , int en , unsigned char ch ,
unsigned char mix , unsigned char dest )
{
vortex_route ( vortex , en , ch , ADB_MIXOUT ( mix ) , dest ) ;
vortex_mix_setvolumebyte ( vortex , mix , MIX_DEFOGAIN ) ; // added to original code.
}
// mixer to src.
static void
vortex_connection_mix_src ( vortex_t * vortex , int en , unsigned char ch ,
unsigned char mix , unsigned char src )
{
vortex_route ( vortex , en , ch , ADB_MIXOUT ( mix ) , ADB_SRCIN ( src ) ) ;
vortex_mix_setvolumebyte ( vortex , mix , MIX_DEFOGAIN ) ; // added to original code.
}
#if 0
static void
vortex_connection_adbdma_src_src ( vortex_t * vortex , int en ,
unsigned char channel ,
unsigned char adbdma , unsigned char src0 ,
unsigned char src1 )
{
vortex_routes ( vortex , en , channel , ADB_DMA ( adbdma ) ,
ADB_SRCIN ( src0 ) , ADB_SRCIN ( src1 ) ) ;
}
// Connect two mix to AdbDma.
static void
vortex_connection_mix_mix_adbdma ( vortex_t * vortex , int en ,
unsigned char ch , unsigned char mix0 ,
unsigned char mix1 , unsigned char adbdma )
{
ADBRamLink routes [ 2 ] ;
routes [ 0 ] =
( ( ( mix0 +
OFFSET_MIXOUT ) & ADB_MASK ) < < ADB_SHIFT ) | ( adbdma & ADB_MASK ) ;
routes [ 1 ] =
( ( ( mix1 + OFFSET_MIXOUT ) & ADB_MASK ) < < ADB_SHIFT ) | ( ( adbdma +
0x20 ) &
ADB_MASK ) ;
if ( en ) {
vortex_adb_addroutes ( vortex , ch , routes , 0x2 ) ;
vortex_mixer_addWTD ( vortex , mix0 , ch ) ;
vortex_mixer_addWTD ( vortex , mix1 , ch ) ;
} else {
vortex_adb_delroutes ( vortex , ch , routes [ 0 ] , routes [ 1 ] ) ;
vortex_mixer_delWTD ( vortex , mix0 , ch ) ;
vortex_mixer_delWTD ( vortex , mix1 , ch ) ;
}
}
# endif
/* CODEC connect. */
static void
vortex_connect_codecplay ( vortex_t * vortex , int en , unsigned char mixers [ ] )
{
# ifdef CHIP_AU8820
vortex_connection_mix_adb ( vortex , en , 0x11 , mixers [ 0 ] , ADB_CODECOUT ( 0 ) ) ;
vortex_connection_mix_adb ( vortex , en , 0x11 , mixers [ 1 ] , ADB_CODECOUT ( 1 ) ) ;
# else
# if 1
// Connect front channels through EQ.
vortex_connection_mix_adb ( vortex , en , 0x11 , mixers [ 0 ] , ADB_EQIN ( 0 ) ) ;
vortex_connection_mix_adb ( vortex , en , 0x11 , mixers [ 1 ] , ADB_EQIN ( 1 ) ) ;
/* Lower volume, since EQ has some gain. */
vortex_mix_setvolumebyte ( vortex , mixers [ 0 ] , 0 ) ;
vortex_mix_setvolumebyte ( vortex , mixers [ 1 ] , 0 ) ;
vortex_route ( vortex , en , 0x11 , ADB_EQOUT ( 0 ) , ADB_CODECOUT ( 0 ) ) ;
vortex_route ( vortex , en , 0x11 , ADB_EQOUT ( 1 ) , ADB_CODECOUT ( 1 ) ) ;
/* Check if reg 0x28 has SDAC bit set. */
if ( VORTEX_IS_QUAD ( vortex ) ) {
/* Rear channel. Note: ADB_CODECOUT(0+2) and (1+2) is for AC97 modem */
vortex_connection_mix_adb ( vortex , en , 0x11 , mixers [ 2 ] ,
ADB_CODECOUT ( 0 + 4 ) ) ;
vortex_connection_mix_adb ( vortex , en , 0x11 , mixers [ 3 ] ,
ADB_CODECOUT ( 1 + 4 ) ) ;
//printk("SDAC detected ");
}
# else
// Use plain direct output to codec.
vortex_connection_mix_adb ( vortex , en , 0x11 , mixers [ 0 ] , ADB_CODECOUT ( 0 ) ) ;
vortex_connection_mix_adb ( vortex , en , 0x11 , mixers [ 1 ] , ADB_CODECOUT ( 1 ) ) ;
# endif
# endif
}
static void
vortex_connect_codecrec ( vortex_t * vortex , int en , unsigned char mixin0 ,
unsigned char mixin1 )
{
/*
Enable : 0x1 , 0x1
Channel : 0x11 , 0x11
ADB Source address : 0x48 , 0x49
Destination Asp4Topology_0x9c , 0x98
*/
vortex_connection_adb_mixin ( vortex , en , 0x11 , ADB_CODECIN ( 0 ) , mixin0 ) ;
vortex_connection_adb_mixin ( vortex , en , 0x11 , ADB_CODECIN ( 1 ) , mixin1 ) ;
}
// Higher level ADB audio path (de)allocator.
/* Resource manager */
static int resnum [ VORTEX_RESOURCE_LAST ] =
{ NR_ADB , NR_SRC , NR_MIXIN , NR_MIXOUT , NR_A3D } ;
/*
Checkout / Checkin resource of given type .
resmap : resource map to be used . If NULL means that we want to allocate
a DMA resource ( root of all other resources of a dma channel ) .
out : Mean checkout if ! = 0. Else mean Checkin resource .
restype : Indicates type of resource to be checked in or out .
*/
static char
vortex_adb_checkinout ( vortex_t * vortex , int resmap [ ] , int out , int restype )
{
int i , qty = resnum [ restype ] , resinuse = 0 ;
if ( out ) {
/* Gather used resources by all streams. */
for ( i = 0 ; i < NR_ADB ; i + + ) {
resinuse | = vortex - > dma_adb [ i ] . resources [ restype ] ;
}
resinuse | = vortex - > fixed_res [ restype ] ;
/* Find and take free resource. */
for ( i = 0 ; i < qty ; i + + ) {
if ( ( resinuse & ( 1 < < i ) ) = = 0 ) {
if ( resmap ! = NULL )
resmap [ restype ] | = ( 1 < < i ) ;
else
vortex - > dma_adb [ i ] . resources [ restype ] | = ( 1 < < i ) ;
//printk("vortex: ResManager: type %d out %d\n", restype, i);
return i ;
}
}
} else {
if ( resmap = = NULL )
return - EINVAL ;
/* Checkin first resource of type restype. */
for ( i = 0 ; i < qty ; i + + ) {
if ( resmap [ restype ] & ( 1 < < i ) ) {
resmap [ restype ] & = ~ ( 1 < < i ) ;
//printk("vortex: ResManager: type %d in %d\n",restype, i);
return i ;
}
}
}
2005-10-20 18:26:44 +02:00
printk ( KERN_ERR " vortex: FATAL: ResManager: resource type %d exhausted. \n " , restype ) ;
2005-04-16 15:20:36 -07:00
return - ENOMEM ;
}
/* Default Connections */
static int
vortex_adb_allocroute ( vortex_t * vortex , int dma , int nr_ch , int dir , int type ) ;
static void vortex_connect_default ( vortex_t * vortex , int en )
{
// Connect AC97 codec.
vortex - > mixplayb [ 0 ] = vortex_adb_checkinout ( vortex , vortex - > fixed_res , en ,
VORTEX_RESOURCE_MIXOUT ) ;
vortex - > mixplayb [ 1 ] = vortex_adb_checkinout ( vortex , vortex - > fixed_res , en ,
VORTEX_RESOURCE_MIXOUT ) ;
if ( VORTEX_IS_QUAD ( vortex ) ) {
vortex - > mixplayb [ 2 ] = vortex_adb_checkinout ( vortex , vortex - > fixed_res , en ,
VORTEX_RESOURCE_MIXOUT ) ;
vortex - > mixplayb [ 3 ] = vortex_adb_checkinout ( vortex , vortex - > fixed_res , en ,
VORTEX_RESOURCE_MIXOUT ) ;
}
vortex_connect_codecplay ( vortex , en , vortex - > mixplayb ) ;
vortex - > mixcapt [ 0 ] = vortex_adb_checkinout ( vortex , vortex - > fixed_res , en ,
VORTEX_RESOURCE_MIXIN ) ;
vortex - > mixcapt [ 1 ] = vortex_adb_checkinout ( vortex , vortex - > fixed_res , en ,
VORTEX_RESOURCE_MIXIN ) ;
vortex_connect_codecrec ( vortex , en , MIX_CAPT ( 0 ) , MIX_CAPT ( 1 ) ) ;
// Connect SPDIF
# ifndef CHIP_AU8820
vortex - > mixspdif [ 0 ] = vortex_adb_checkinout ( vortex , vortex - > fixed_res , en ,
VORTEX_RESOURCE_MIXOUT ) ;
vortex - > mixspdif [ 1 ] = vortex_adb_checkinout ( vortex , vortex - > fixed_res , en ,
VORTEX_RESOURCE_MIXOUT ) ;
vortex_connection_mix_adb ( vortex , en , 0x14 , vortex - > mixspdif [ 0 ] ,
ADB_SPDIFOUT ( 0 ) ) ;
vortex_connection_mix_adb ( vortex , en , 0x14 , vortex - > mixspdif [ 1 ] ,
ADB_SPDIFOUT ( 1 ) ) ;
# endif
// Connect WT
# ifndef CHIP_AU8810
vortex_wt_connect ( vortex , en ) ;
# endif
// A3D (crosstalk canceler and A3D slices). AU8810 disabled for now.
# ifndef CHIP_AU8820
vortex_Vort3D_connect ( vortex , en ) ;
# endif
// Connect I2S
// Connect DSP interface for SQ3500 turbo (not here i think...)
// Connect AC98 modem codec
}
/*
Allocate nr_ch pcm audio routes if dma < 0. If dma > = 0 , existing routes
are deallocated .
dma : DMA engine routes to be deallocated when dma > = 0.
nr_ch : Number of channels to be de / allocated .
dir : direction of stream . Uses same values as substream - > stream .
type : Type of audio output / source ( codec , spdif , i2s , dsp , etc )
Return : Return allocated DMA or same DMA passed as " dma " when dma > = 0.
*/
static int
vortex_adb_allocroute ( vortex_t * vortex , int dma , int nr_ch , int dir , int type )
{
stream_t * stream ;
int i , en ;
if ( ( nr_ch = = 3 )
| | ( ( dir = = SNDRV_PCM_STREAM_CAPTURE ) & & ( nr_ch > 2 ) ) )
return - EBUSY ;
if ( dma > = 0 ) {
en = 0 ;
vortex_adb_checkinout ( vortex ,
vortex - > dma_adb [ dma ] . resources , en ,
VORTEX_RESOURCE_DMA ) ;
} else {
en = 1 ;
if ( ( dma =
vortex_adb_checkinout ( vortex , NULL , en ,
VORTEX_RESOURCE_DMA ) ) < 0 )
return - EBUSY ;
}
stream = & vortex - > dma_adb [ dma ] ;
stream - > dma = dma ;
stream - > dir = dir ;
stream - > type = type ;
/* PLAYBACK ROUTES. */
if ( dir = = SNDRV_PCM_STREAM_PLAYBACK ) {
int src [ 4 ] , mix [ 4 ] , ch_top ;
# ifndef CHIP_AU8820
int a3d = 0 ;
# endif
/* Get SRC and MIXER hardware resources. */
if ( stream - > type ! = VORTEX_PCM_SPDIF ) {
for ( i = 0 ; i < nr_ch ; i + + ) {
if ( ( src [ i ] = vortex_adb_checkinout ( vortex ,
stream - > resources , en ,
VORTEX_RESOURCE_SRC ) ) < 0 ) {
memset ( stream - > resources , 0 ,
sizeof ( unsigned char ) *
VORTEX_RESOURCE_LAST ) ;
return - EBUSY ;
}
if ( stream - > type ! = VORTEX_PCM_A3D ) {
if ( ( mix [ i ] = vortex_adb_checkinout ( vortex ,
stream - > resources ,
en ,
VORTEX_RESOURCE_MIXIN ) ) < 0 ) {
memset ( stream - > resources ,
0 ,
sizeof ( unsigned char ) * VORTEX_RESOURCE_LAST ) ;
return - EBUSY ;
}
}
}
}
# ifndef CHIP_AU8820
if ( stream - > type = = VORTEX_PCM_A3D ) {
if ( ( a3d =
vortex_adb_checkinout ( vortex ,
stream - > resources , en ,
VORTEX_RESOURCE_A3D ) ) < 0 ) {
memset ( stream - > resources , 0 ,
sizeof ( unsigned char ) *
VORTEX_RESOURCE_LAST ) ;
2005-10-20 18:26:44 +02:00
printk ( KERN_ERR " vortex: out of A3D sources. Sorry \n " ) ;
2005-04-16 15:20:36 -07:00
return - EBUSY ;
}
/* (De)Initialize A3D hardware source. */
vortex_Vort3D_InitializeSource ( & ( vortex - > a3d [ a3d ] ) , en ) ;
}
/* Make SPDIF out exclusive to "spdif" device when in use. */
if ( ( stream - > type = = VORTEX_PCM_SPDIF ) & & ( en ) ) {
vortex_route ( vortex , 0 , 0x14 ,
ADB_MIXOUT ( vortex - > mixspdif [ 0 ] ) ,
ADB_SPDIFOUT ( 0 ) ) ;
vortex_route ( vortex , 0 , 0x14 ,
ADB_MIXOUT ( vortex - > mixspdif [ 1 ] ) ,
ADB_SPDIFOUT ( 1 ) ) ;
}
# endif
/* Make playback routes. */
for ( i = 0 ; i < nr_ch ; i + + ) {
if ( stream - > type = = VORTEX_PCM_ADB ) {
vortex_connection_adbdma_src ( vortex , en ,
src [ nr_ch - 1 ] ,
dma ,
src [ i ] ) ;
vortex_connection_src_mixin ( vortex , en ,
0x11 , src [ i ] ,
mix [ i ] ) ;
vortex_connection_mixin_mix ( vortex , en ,
mix [ i ] ,
MIX_PLAYB ( i ) , 0 ) ;
# ifndef CHIP_AU8820
vortex_connection_mixin_mix ( vortex , en ,
mix [ i ] ,
MIX_SPDIF ( i % 2 ) , 0 ) ;
vortex_mix_setinputvolumebyte ( vortex ,
MIX_SPDIF ( i % 2 ) ,
mix [ i ] ,
MIX_DEFIGAIN ) ;
# endif
}
# ifndef CHIP_AU8820
if ( stream - > type = = VORTEX_PCM_A3D ) {
vortex_connection_adbdma_src ( vortex , en ,
src [ nr_ch - 1 ] ,
dma ,
src [ i ] ) ;
vortex_route ( vortex , en , 0x11 , ADB_SRCOUT ( src [ i ] ) , ADB_A3DIN ( a3d ) ) ;
/* XTalk test. */
//vortex_route(vortex, en, 0x11, dma, ADB_XTALKIN(i?9:4));
//vortex_route(vortex, en, 0x11, ADB_SRCOUT(src[i]), ADB_XTALKIN(i?4:9));
}
if ( stream - > type = = VORTEX_PCM_SPDIF )
vortex_route ( vortex , en , 0x14 ,
ADB_DMA ( stream - > dma ) ,
ADB_SPDIFOUT ( i ) ) ;
# endif
}
if ( stream - > type ! = VORTEX_PCM_SPDIF & & stream - > type ! = VORTEX_PCM_A3D ) {
ch_top = ( VORTEX_IS_QUAD ( vortex ) ? 4 : 2 ) ;
for ( i = nr_ch ; i < ch_top ; i + + ) {
vortex_connection_mixin_mix ( vortex , en ,
mix [ i % nr_ch ] ,
MIX_PLAYB ( i ) , 0 ) ;
# ifndef CHIP_AU8820
vortex_connection_mixin_mix ( vortex , en ,
mix [ i % nr_ch ] ,
MIX_SPDIF ( i % 2 ) ,
0 ) ;
vortex_mix_setinputvolumebyte ( vortex ,
MIX_SPDIF ( i % 2 ) ,
mix [ i % nr_ch ] ,
MIX_DEFIGAIN ) ;
# endif
}
}
# ifndef CHIP_AU8820
else {
if ( nr_ch = = 1 & & stream - > type = = VORTEX_PCM_SPDIF )
vortex_route ( vortex , en , 0x14 ,
ADB_DMA ( stream - > dma ) ,
ADB_SPDIFOUT ( 1 ) ) ;
}
/* Reconnect SPDIF out when "spdif" device is down. */
if ( ( stream - > type = = VORTEX_PCM_SPDIF ) & & ( ! en ) ) {
vortex_route ( vortex , 1 , 0x14 ,
ADB_MIXOUT ( vortex - > mixspdif [ 0 ] ) ,
ADB_SPDIFOUT ( 0 ) ) ;
vortex_route ( vortex , 1 , 0x14 ,
ADB_MIXOUT ( vortex - > mixspdif [ 1 ] ) ,
ADB_SPDIFOUT ( 1 ) ) ;
}
# endif
/* CAPTURE ROUTES. */
} else {
int src [ 2 ] , mix [ 2 ] ;
/* Get SRC and MIXER hardware resources. */
for ( i = 0 ; i < nr_ch ; i + + ) {
if ( ( mix [ i ] =
vortex_adb_checkinout ( vortex ,
stream - > resources , en ,
VORTEX_RESOURCE_MIXOUT ) )
< 0 ) {
memset ( stream - > resources , 0 ,
sizeof ( unsigned char ) *
VORTEX_RESOURCE_LAST ) ;
return - EBUSY ;
}
if ( ( src [ i ] =
vortex_adb_checkinout ( vortex ,
stream - > resources , en ,
VORTEX_RESOURCE_SRC ) ) < 0 ) {
memset ( stream - > resources , 0 ,
sizeof ( unsigned char ) *
VORTEX_RESOURCE_LAST ) ;
return - EBUSY ;
}
}
/* Make capture routes. */
vortex_connection_mixin_mix ( vortex , en , MIX_CAPT ( 0 ) , mix [ 0 ] , 0 ) ;
vortex_connection_mix_src ( vortex , en , 0x11 , mix [ 0 ] , src [ 0 ] ) ;
if ( nr_ch = = 1 ) {
vortex_connection_mixin_mix ( vortex , en ,
MIX_CAPT ( 1 ) , mix [ 0 ] , 0 ) ;
vortex_connection_src_adbdma ( vortex , en ,
src [ 0 ] ,
src [ 0 ] , dma ) ;
} else {
vortex_connection_mixin_mix ( vortex , en ,
MIX_CAPT ( 1 ) , mix [ 1 ] , 0 ) ;
vortex_connection_mix_src ( vortex , en , 0x11 , mix [ 1 ] ,
src [ 1 ] ) ;
vortex_connection_src_src_adbdma ( vortex , en ,
src [ 1 ] , src [ 0 ] ,
src [ 1 ] , dma ) ;
}
}
vortex - > dma_adb [ dma ] . nr_ch = nr_ch ;
#if 0
/* AC97 Codec channel setup. FIXME: this has no effect on some cards !! */
if ( nr_ch < 4 ) {
/* Copy stereo to rear channel (surround) */
snd_ac97_write_cache ( vortex - > codec ,
AC97_SIGMATEL_DAC2INVERT ,
snd_ac97_read ( vortex - > codec ,
AC97_SIGMATEL_DAC2INVERT )
| 4 ) ;
} else {
/* Allow separate front and rear channels. */
snd_ac97_write_cache ( vortex - > codec ,
AC97_SIGMATEL_DAC2INVERT ,
snd_ac97_read ( vortex - > codec ,
AC97_SIGMATEL_DAC2INVERT )
& ~ ( ( u32 )
4 ) ) ;
}
# endif
return dma ;
}
/*
Set the SampleRate of the SRC ' s attached to the given DMA engine .
*/
static void
vortex_adb_setsrc ( vortex_t * vortex , int adbdma , unsigned int rate , int dir )
{
stream_t * stream = & ( vortex - > dma_adb [ adbdma ] ) ;
int i , cvrt ;
/* dir=1:play ; dir=0:rec */
if ( dir )
cvrt = SRC_RATIO ( rate , 48000 ) ;
else
cvrt = SRC_RATIO ( 48000 , rate ) ;
/* Setup SRC's */
for ( i = 0 ; i < NR_SRC ; i + + ) {
if ( stream - > resources [ VORTEX_RESOURCE_SRC ] & ( 1 < < i ) )
vortex_src_setupchannel ( vortex , i , cvrt , 0 , 0 , i , dir , 1 , cvrt , dir ) ;
}
}
// Timer and ISR functions.
static void vortex_settimer ( vortex_t * vortex , int period )
{
//set the timer period to <period> 48000ths of a second.
hwwrite ( vortex - > mmio , VORTEX_IRQ_STAT , period ) ;
}
#if 0
static void vortex_enable_timer_int ( vortex_t * card )
{
hwwrite ( card - > mmio , VORTEX_IRQ_CTRL ,
hwread ( card - > mmio , VORTEX_IRQ_CTRL ) | IRQ_TIMER | 0x60 ) ;
}
static void vortex_disable_timer_int ( vortex_t * card )
{
hwwrite ( card - > mmio , VORTEX_IRQ_CTRL ,
hwread ( card - > mmio , VORTEX_IRQ_CTRL ) & ~ IRQ_TIMER ) ;
}
# endif
static void vortex_enable_int ( vortex_t * card )
{
// CAsp4ISR__EnableVortexInt_void_
hwwrite ( card - > mmio , VORTEX_CTRL ,
hwread ( card - > mmio , VORTEX_CTRL ) | CTRL_IRQ_ENABLE ) ;
hwwrite ( card - > mmio , VORTEX_IRQ_CTRL ,
( hwread ( card - > mmio , VORTEX_IRQ_CTRL ) & 0xffffefc0 ) | 0x24 ) ;
}
static void vortex_disable_int ( vortex_t * card )
{
hwwrite ( card - > mmio , VORTEX_CTRL ,
hwread ( card - > mmio , VORTEX_CTRL ) & ~ CTRL_IRQ_ENABLE ) ;
}
static irqreturn_t vortex_interrupt ( int irq , void * dev_id , struct pt_regs * regs )
{
vortex_t * vortex = dev_id ;
int i , handled ;
u32 source ;
//check if the interrupt is ours.
if ( ! ( hwread ( vortex - > mmio , VORTEX_STAT ) & 0x1 ) )
return IRQ_NONE ;
// This is the Interrrupt Enable flag we set before (consistency check).
if ( ! ( hwread ( vortex - > mmio , VORTEX_CTRL ) & CTRL_IRQ_ENABLE ) )
return IRQ_NONE ;
source = hwread ( vortex - > mmio , VORTEX_IRQ_SOURCE ) ;
// Reset IRQ flags.
hwwrite ( vortex - > mmio , VORTEX_IRQ_SOURCE , source ) ;
hwread ( vortex - > mmio , VORTEX_IRQ_SOURCE ) ;
// Is at least one IRQ flag set?
if ( source = = 0 ) {
printk ( KERN_ERR " vortex: missing irq source \n " ) ;
return IRQ_NONE ;
}
handled = 0 ;
// Attend every interrupt source.
if ( unlikely ( source & IRQ_ERR_MASK ) ) {
if ( source & IRQ_FATAL ) {
printk ( KERN_ERR " vortex: IRQ fatal error \n " ) ;
}
if ( source & IRQ_PARITY ) {
printk ( KERN_ERR " vortex: IRQ parity error \n " ) ;
}
if ( source & IRQ_REG ) {
printk ( KERN_ERR " vortex: IRQ reg error \n " ) ;
}
if ( source & IRQ_FIFO ) {
printk ( KERN_ERR " vortex: IRQ fifo error \n " ) ;
}
if ( source & IRQ_DMA ) {
printk ( KERN_ERR " vortex: IRQ dma error \n " ) ;
}
handled = 1 ;
}
if ( source & IRQ_PCMOUT ) {
/* ALSA period acknowledge. */
spin_lock ( & vortex - > lock ) ;
for ( i = 0 ; i < NR_ADB ; i + + ) {
if ( vortex - > dma_adb [ i ] . fifo_status = = FIFO_START ) {
if ( vortex_adbdma_bufshift ( vortex , i ) ) ;
spin_unlock ( & vortex - > lock ) ;
snd_pcm_period_elapsed ( vortex - > dma_adb [ i ] .
substream ) ;
spin_lock ( & vortex - > lock ) ;
}
}
# ifndef CHIP_AU8810
for ( i = 0 ; i < NR_WT ; i + + ) {
if ( vortex - > dma_wt [ i ] . fifo_status = = FIFO_START ) {
if ( vortex_wtdma_bufshift ( vortex , i ) ) ;
spin_unlock ( & vortex - > lock ) ;
snd_pcm_period_elapsed ( vortex - > dma_wt [ i ] .
substream ) ;
spin_lock ( & vortex - > lock ) ;
}
}
# endif
spin_unlock ( & vortex - > lock ) ;
handled = 1 ;
}
//Acknowledge the Timer interrupt
if ( source & IRQ_TIMER ) {
hwread ( vortex - > mmio , VORTEX_IRQ_STAT ) ;
handled = 1 ;
}
if ( source & IRQ_MIDI ) {
snd_mpu401_uart_interrupt ( vortex - > irq ,
vortex - > rmidi - > private_data , regs ) ;
handled = 1 ;
}
if ( ! handled ) {
printk ( KERN_ERR " vortex: unknown irq source %x \n " , source ) ;
}
return IRQ_RETVAL ( handled ) ;
}
/* Codec */
# define POLL_COUNT 1000
static void vortex_codec_init ( vortex_t * vortex )
{
int i ;
for ( i = 0 ; i < 32 ; i + + ) {
/* the windows driver writes -i, so we write -i */
hwwrite ( vortex - > mmio , ( VORTEX_CODEC_CHN + ( i < < 2 ) ) , - i ) ;
msleep ( 2 ) ;
}
if ( 0 ) {
hwwrite ( vortex - > mmio , VORTEX_CODEC_CTRL , 0x8068 ) ;
msleep ( 1 ) ;
hwwrite ( vortex - > mmio , VORTEX_CODEC_CTRL , 0x00e8 ) ;
msleep ( 1 ) ;
} else {
hwwrite ( vortex - > mmio , VORTEX_CODEC_CTRL , 0x00a8 ) ;
msleep ( 2 ) ;
hwwrite ( vortex - > mmio , VORTEX_CODEC_CTRL , 0x80a8 ) ;
msleep ( 2 ) ;
hwwrite ( vortex - > mmio , VORTEX_CODEC_CTRL , 0x80e8 ) ;
msleep ( 2 ) ;
hwwrite ( vortex - > mmio , VORTEX_CODEC_CTRL , 0x80a8 ) ;
msleep ( 2 ) ;
hwwrite ( vortex - > mmio , VORTEX_CODEC_CTRL , 0x00a8 ) ;
msleep ( 2 ) ;
hwwrite ( vortex - > mmio , VORTEX_CODEC_CTRL , 0x00e8 ) ;
}
for ( i = 0 ; i < 32 ; i + + ) {
hwwrite ( vortex - > mmio , ( VORTEX_CODEC_CHN + ( i < < 2 ) ) , - i ) ;
msleep ( 5 ) ;
}
hwwrite ( vortex - > mmio , VORTEX_CODEC_CTRL , 0xe8 ) ;
msleep ( 1 ) ;
/* Enable codec channels 0 and 1. */
hwwrite ( vortex - > mmio , VORTEX_CODEC_EN ,
hwread ( vortex - > mmio , VORTEX_CODEC_EN ) | EN_CODEC ) ;
}
static void
2005-11-17 14:55:19 +01:00
vortex_codec_write ( struct snd_ac97 * codec , unsigned short addr , unsigned short data )
2005-04-16 15:20:36 -07:00
{
vortex_t * card = ( vortex_t * ) codec - > private_data ;
unsigned int lifeboat = 0 ;
/* wait for transactions to clear */
while ( ! ( hwread ( card - > mmio , VORTEX_CODEC_CTRL ) & 0x100 ) ) {
udelay ( 100 ) ;
if ( lifeboat + + > POLL_COUNT ) {
printk ( KERN_ERR " vortex: ac97 codec stuck busy \n " ) ;
return ;
}
}
/* write register */
hwwrite ( card - > mmio , VORTEX_CODEC_IO ,
( ( addr < < VORTEX_CODEC_ADDSHIFT ) & VORTEX_CODEC_ADDMASK ) |
( ( data < < VORTEX_CODEC_DATSHIFT ) & VORTEX_CODEC_DATMASK ) |
2005-09-16 19:22:44 +02:00
VORTEX_CODEC_WRITE |
( codec - > num < < VORTEX_CODEC_ID_SHIFT ) ) ;
2005-04-16 15:20:36 -07:00
/* Flush Caches. */
hwread ( card - > mmio , VORTEX_CODEC_IO ) ;
}
2005-11-17 14:55:19 +01:00
static unsigned short vortex_codec_read ( struct snd_ac97 * codec , unsigned short addr )
2005-04-16 15:20:36 -07:00
{
vortex_t * card = ( vortex_t * ) codec - > private_data ;
u32 read_addr , data ;
unsigned lifeboat = 0 ;
/* wait for transactions to clear */
while ( ! ( hwread ( card - > mmio , VORTEX_CODEC_CTRL ) & 0x100 ) ) {
udelay ( 100 ) ;
if ( lifeboat + + > POLL_COUNT ) {
printk ( KERN_ERR " vortex: ac97 codec stuck busy \n " ) ;
return 0xffff ;
}
}
/* set up read address */
2005-09-16 19:22:44 +02:00
read_addr = ( ( addr < < VORTEX_CODEC_ADDSHIFT ) & VORTEX_CODEC_ADDMASK ) |
( codec - > num < < VORTEX_CODEC_ID_SHIFT ) ;
2005-04-16 15:20:36 -07:00
hwwrite ( card - > mmio , VORTEX_CODEC_IO , read_addr ) ;
/* wait for address */
do {
udelay ( 100 ) ;
data = hwread ( card - > mmio , VORTEX_CODEC_IO ) ;
if ( lifeboat + + > POLL_COUNT ) {
printk ( KERN_ERR " vortex: ac97 address never arrived \n " ) ;
return 0xffff ;
}
} while ( ( data & VORTEX_CODEC_ADDMASK ) ! =
( addr < < VORTEX_CODEC_ADDSHIFT ) ) ;
/* return data. */
return ( u16 ) ( data & VORTEX_CODEC_DATMASK ) ;
}
/* SPDIF support */
static void vortex_spdif_init ( vortex_t * vortex , int spdif_sr , int spdif_mode )
{
int i , this_38 = 0 , this_04 = 0 , this_08 = 0 , this_0c = 0 ;
/* CAsp4Spdif::InitializeSpdifHardware(void) */
hwwrite ( vortex - > mmio , VORTEX_SPDIF_FLAGS ,
hwread ( vortex - > mmio , VORTEX_SPDIF_FLAGS ) & 0xfff3fffd ) ;
//for (i=0x291D4; i<0x29200; i+=4)
for ( i = 0 ; i < 11 ; i + + )
hwwrite ( vortex - > mmio , VORTEX_SPDIF_CFG1 + ( i < < 2 ) , 0 ) ;
//hwwrite(vortex->mmio, 0x29190, hwread(vortex->mmio, 0x29190) | 0xc0000);
hwwrite ( vortex - > mmio , VORTEX_CODEC_EN ,
hwread ( vortex - > mmio , VORTEX_CODEC_EN ) | EN_SPDIF ) ;
/* CAsp4Spdif::ProgramSRCInHardware(enum SPDIF_SR,enum SPDIFMODE) */
if ( this_04 & & this_08 ) {
int edi ;
i = ( ( ( 0x5DC00000 / spdif_sr ) + 1 ) > > 1 ) ;
if ( i > 0x800 ) {
if ( i < 0x1ffff )
edi = ( i > > 1 ) ;
else
edi = 0x1ffff ;
} else {
i = edi = 0x800 ;
}
/* this_04 and this_08 are the CASp4Src's (samplerate converters) */
vortex_src_setupchannel ( vortex , this_04 , edi , 0 , 1 ,
this_0c , 1 , 0 , edi , 1 ) ;
vortex_src_setupchannel ( vortex , this_08 , edi , 0 , 1 ,
this_0c , 1 , 0 , edi , 1 ) ;
}
i = spdif_sr ;
spdif_sr | = 0x8c ;
switch ( i ) {
case 32000 :
this_38 & = 0xFFFFFFFE ;
this_38 & = 0xFFFFFFFD ;
this_38 & = 0xF3FFFFFF ;
this_38 | = 0x03000000 ; /* set 32khz samplerate */
this_38 & = 0xFFFFFF3F ;
spdif_sr & = 0xFFFFFFFD ;
spdif_sr | = 1 ;
break ;
case 44100 :
this_38 & = 0xFFFFFFFE ;
this_38 & = 0xFFFFFFFD ;
this_38 & = 0xF0FFFFFF ;
this_38 | = 0x03000000 ;
this_38 & = 0xFFFFFF3F ;
spdif_sr & = 0xFFFFFFFC ;
break ;
case 48000 :
if ( spdif_mode = = 1 ) {
this_38 & = 0xFFFFFFFE ;
this_38 & = 0xFFFFFFFD ;
this_38 & = 0xF2FFFFFF ;
this_38 | = 0x02000000 ; /* set 48khz samplerate */
this_38 & = 0xFFFFFF3F ;
} else {
/* J. Gordon Wolfe: I think this stuff is for AC3 */
this_38 | = 0x00000003 ;
this_38 & = 0xFFFFFFBF ;
this_38 | = 0x80 ;
}
spdif_sr | = 2 ;
spdif_sr & = 0xFFFFFFFE ;
break ;
}
/* looks like the next 2 lines transfer a 16-bit value into 2 8-bit
registers . seems to be for the standard IEC / SPDIF initialization
stuff */
hwwrite ( vortex - > mmio , VORTEX_SPDIF_CFG0 , this_38 & 0xffff ) ;
hwwrite ( vortex - > mmio , VORTEX_SPDIF_CFG1 , this_38 > > 0x10 ) ;
hwwrite ( vortex - > mmio , VORTEX_SPDIF_SMPRATE , spdif_sr ) ;
}
/* Initialization */
2006-04-10 11:34:44 +02:00
static int __devinit vortex_core_init ( vortex_t * vortex )
2005-04-16 15:20:36 -07:00
{
printk ( KERN_INFO " Vortex: init.... " ) ;
/* Hardware Init. */
hwwrite ( vortex - > mmio , VORTEX_CTRL , 0xffffffff ) ;
msleep ( 5 ) ;
hwwrite ( vortex - > mmio , VORTEX_CTRL ,
hwread ( vortex - > mmio , VORTEX_CTRL ) & 0xffdfffff ) ;
msleep ( 5 ) ;
/* Reset IRQ flags */
hwwrite ( vortex - > mmio , VORTEX_IRQ_SOURCE , 0xffffffff ) ;
hwread ( vortex - > mmio , VORTEX_IRQ_STAT ) ;
vortex_codec_init ( vortex ) ;
# ifdef CHIP_AU8830
hwwrite ( vortex - > mmio , VORTEX_CTRL ,
hwread ( vortex - > mmio , VORTEX_CTRL ) | 0x1000000 ) ;
# endif
/* Init audio engine. */
vortex_adbdma_init ( vortex ) ;
hwwrite ( vortex - > mmio , VORTEX_ENGINE_CTRL , 0x0 ) ; //, 0xc83c7e58, 0xc5f93e58
vortex_adb_init ( vortex ) ;
/* Init processing blocks. */
vortex_fifo_init ( vortex ) ;
vortex_mixer_init ( vortex ) ;
vortex_srcblock_init ( vortex ) ;
# ifndef CHIP_AU8820
vortex_eq_init ( vortex ) ;
vortex_spdif_init ( vortex , 48000 , 1 ) ;
2006-07-05 16:51:05 +02:00
vortex_Vort3D_enable ( vortex ) ;
2005-04-16 15:20:36 -07:00
# endif
# ifndef CHIP_AU8810
vortex_wt_init ( vortex ) ;
# endif
// Moved to au88x0.c
//vortex_connect_default(vortex, 1);
vortex_settimer ( vortex , 0x90 ) ;
// Enable Interrupts.
// vortex_enable_int() must be first !!
// hwwrite(vortex->mmio, VORTEX_IRQ_CTRL, 0);
// vortex_enable_int(vortex);
//vortex_enable_timer_int(vortex);
//vortex_disable_timer_int(vortex);
printk ( KERN_INFO " done. \n " ) ;
spin_lock_init ( & vortex - > lock ) ;
return 0 ;
}
static int vortex_core_shutdown ( vortex_t * vortex )
{
printk ( KERN_INFO " Vortex: shutdown... " ) ;
# ifndef CHIP_AU8820
vortex_eq_free ( vortex ) ;
2006-07-05 16:51:05 +02:00
vortex_Vort3D_disable ( vortex ) ;
2005-04-16 15:20:36 -07:00
# endif
//vortex_disable_timer_int(vortex);
vortex_disable_int ( vortex ) ;
vortex_connect_default ( vortex , 0 ) ;
/* Reset all DMA fifos. */
vortex_fifo_init ( vortex ) ;
/* Erase all audio routes. */
vortex_adb_init ( vortex ) ;
/* Disable MPU401 */
//hwwrite(vortex->mmio, VORTEX_IRQ_CTRL, hwread(vortex->mmio, VORTEX_IRQ_CTRL) & ~IRQ_MIDI);
//hwwrite(vortex->mmio, VORTEX_CTRL, hwread(vortex->mmio, VORTEX_CTRL) & ~CTRL_MIDI_EN);
hwwrite ( vortex - > mmio , VORTEX_IRQ_CTRL , 0 ) ;
hwwrite ( vortex - > mmio , VORTEX_CTRL , 0 ) ;
msleep ( 5 ) ;
hwwrite ( vortex - > mmio , VORTEX_IRQ_SOURCE , 0xffff ) ;
printk ( KERN_INFO " done. \n " ) ;
return 0 ;
}
/* Alsa support. */
static int vortex_alsafmt_aspfmt ( int alsafmt )
{
int fmt ;
switch ( alsafmt ) {
case SNDRV_PCM_FORMAT_U8 :
fmt = 0x1 ;
break ;
case SNDRV_PCM_FORMAT_MU_LAW :
fmt = 0x2 ;
break ;
case SNDRV_PCM_FORMAT_A_LAW :
fmt = 0x3 ;
break ;
case SNDRV_PCM_FORMAT_SPECIAL :
fmt = 0x4 ; /* guess. */
break ;
case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE :
fmt = 0x5 ; /* guess. */
break ;
case SNDRV_PCM_FORMAT_S16_LE :
fmt = 0x8 ;
break ;
case SNDRV_PCM_FORMAT_S16_BE :
fmt = 0x9 ; /* check this... */
break ;
default :
fmt = 0x8 ;
printk ( KERN_ERR " vortex: format unsupported %d \n " , alsafmt ) ;
break ;
}
return fmt ;
}
/* Some not yet useful translations. */
#if 0
typedef enum {
ASPFMTLINEAR16 = 0 , /* 0x8 */
ASPFMTLINEAR8 , /* 0x1 */
ASPFMTULAW , /* 0x2 */
ASPFMTALAW , /* 0x3 */
ASPFMTSPORT , /* ? */
ASPFMTSPDIF , /* ? */
} ASPENCODING ;
static int
vortex_translateformat ( vortex_t * vortex , char bits , char nch , int encod )
{
int a , this_194 ;
if ( ( bits ! = 8 ) | | ( bits ! = 16 ) )
return - 1 ;
switch ( encod ) {
case 0 :
if ( bits = = 0x10 )
a = 8 ; // 16 bit
break ;
case 1 :
if ( bits = = 8 )
a = 1 ; // 8 bit
break ;
case 2 :
a = 2 ; // U_LAW
break ;
case 3 :
a = 3 ; // A_LAW
break ;
}
switch ( nch ) {
case 1 :
this_194 = 0 ;
break ;
case 2 :
this_194 = 1 ;
break ;
case 4 :
this_194 = 1 ;
break ;
case 6 :
this_194 = 1 ;
break ;
}
return ( a ) ;
}
static void vortex_cdmacore_setformat ( vortex_t * vortex , int bits , int nch )
{
short int d , this_148 ;
d = ( ( bits > > 3 ) * nch ) ;
this_148 = 0xbb80 / d ;
}
# endif