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 .
*/
/*
* Someday its supposed to make use of the WT DMA engine
* for a Wavetable synthesizer .
*/
# include "au88x0.h"
# include "au88x0_wt.h"
static void vortex_fifo_setwtvalid ( vortex_t * vortex , int fifo , int en ) ;
static void vortex_connection_adb_mixin ( vortex_t * vortex , int en ,
unsigned char channel ,
unsigned char source ,
unsigned char mixin ) ;
static void vortex_connection_mixin_mix ( vortex_t * vortex , int en ,
unsigned char mixin ,
unsigned char mix , int a ) ;
static void vortex_fifo_wtinitialize ( vortex_t * vortex , int fifo , int j ) ;
static int vortex_wt_SetReg ( vortex_t * vortex , unsigned char reg , int wt ,
2006-01-13 17:16:29 +01:00
u32 val ) ;
2005-04-16 15:20:36 -07:00
/* WT */
/* Put 2 WT channels together for one stereo interlaced channel. */
static void vortex_wt_setstereo ( vortex_t * vortex , u32 wt , u32 stereo )
{
int temp ;
//temp = hwread(vortex->mmio, 0x80 + ((wt >> 0x5)<< 0xf) + (((wt & 0x1f) >> 1) << 2));
temp = hwread ( vortex - > mmio , WT_STEREO ( wt ) ) ;
temp = ( temp & 0xfe ) | ( stereo & 1 ) ;
//hwwrite(vortex->mmio, 0x80 + ((wt >> 0x5)<< 0xf) + (((wt & 0x1f) >> 1) << 2), temp);
hwwrite ( vortex - > mmio , WT_STEREO ( wt ) , temp ) ;
}
/* Join to mixdown route. */
static void vortex_wt_setdsout ( vortex_t * vortex , u32 wt , int en )
{
int temp ;
/* There is one DSREG register for each bank (32 voices each). */
temp = hwread ( vortex - > mmio , WT_DSREG ( ( wt > = 0x20 ) ? 1 : 0 ) ) ;
if ( en )
temp | = ( 1 < < ( wt & 0x1f ) ) ;
else
temp & = ( 1 < < ~ ( wt & 0x1f ) ) ;
hwwrite ( vortex - > mmio , WT_DSREG ( ( wt > = 0x20 ) ? 1 : 0 ) , temp ) ;
}
/* Setup WT route. */
static int vortex_wt_allocroute ( vortex_t * vortex , int wt , int nr_ch )
{
wt_voice_t * voice = & ( vortex - > wt_voice [ wt ] ) ;
int temp ;
//FIXME: WT audio routing.
if ( nr_ch ) {
vortex_fifo_wtinitialize ( vortex , wt , 1 ) ;
vortex_fifo_setwtvalid ( vortex , wt , 1 ) ;
vortex_wt_setstereo ( vortex , wt , nr_ch - 1 ) ;
} else
vortex_fifo_setwtvalid ( vortex , wt , 0 ) ;
/* Set mixdown mode. */
vortex_wt_setdsout ( vortex , wt , 1 ) ;
/* Set other parameter registers. */
hwwrite ( vortex - > mmio , WT_SRAMP ( 0 ) , 0x880000 ) ;
//hwwrite(vortex->mmio, WT_GMODE(0), 0xffffffff);
# ifdef CHIP_AU8830
hwwrite ( vortex - > mmio , WT_SRAMP ( 1 ) , 0x880000 ) ;
//hwwrite(vortex->mmio, WT_GMODE(1), 0xffffffff);
# endif
hwwrite ( vortex - > mmio , WT_PARM ( wt , 0 ) , 0 ) ;
hwwrite ( vortex - > mmio , WT_PARM ( wt , 1 ) , 0 ) ;
hwwrite ( vortex - > mmio , WT_PARM ( wt , 2 ) , 0 ) ;
temp = hwread ( vortex - > mmio , WT_PARM ( wt , 3 ) ) ;
2005-10-20 18:26:44 +02:00
printk ( KERN_DEBUG " vortex: WT PARM3: %x \n " , temp ) ;
2005-04-16 15:20:36 -07:00
//hwwrite(vortex->mmio, WT_PARM(wt, 3), temp);
hwwrite ( vortex - > mmio , WT_DELAY ( wt , 0 ) , 0 ) ;
hwwrite ( vortex - > mmio , WT_DELAY ( wt , 1 ) , 0 ) ;
hwwrite ( vortex - > mmio , WT_DELAY ( wt , 2 ) , 0 ) ;
hwwrite ( vortex - > mmio , WT_DELAY ( wt , 3 ) , 0 ) ;
2005-10-20 18:26:44 +02:00
printk ( KERN_DEBUG " vortex: WT GMODE: %x \n " , hwread ( vortex - > mmio , WT_GMODE ( wt ) ) ) ;
2005-04-16 15:20:36 -07:00
hwwrite ( vortex - > mmio , WT_PARM ( wt , 2 ) , 0xffffffff ) ;
hwwrite ( vortex - > mmio , WT_PARM ( wt , 3 ) , 0xcff1c810 ) ;
voice - > parm0 = voice - > parm1 = 0xcfb23e2f ;
hwwrite ( vortex - > mmio , WT_PARM ( wt , 0 ) , voice - > parm0 ) ;
hwwrite ( vortex - > mmio , WT_PARM ( wt , 1 ) , voice - > parm1 ) ;
2005-10-20 18:26:44 +02:00
printk ( KERN_DEBUG " vortex: WT GMODE 2 : %x \n " , hwread ( vortex - > mmio , WT_GMODE ( wt ) ) ) ;
2005-04-16 15:20:36 -07:00
return 0 ;
}
static void vortex_wt_connect ( vortex_t * vortex , int en )
{
int i , ii , mix ;
# define NR_WTROUTES 6
# ifdef CHIP_AU8830
# define NR_WTBLOCKS 2
# else
# define NR_WTBLOCKS 1
# endif
for ( i = 0 ; i < NR_WTBLOCKS ; i + + ) {
for ( ii = 0 ; ii < NR_WTROUTES ; ii + + ) {
mix =
vortex_adb_checkinout ( vortex ,
vortex - > fixed_res , en ,
VORTEX_RESOURCE_MIXIN ) ;
vortex - > mixwt [ ( i * NR_WTROUTES ) + ii ] = mix ;
vortex_route ( vortex , en , 0x11 ,
ADB_WTOUT ( i , ii + 0x20 ) , ADB_MIXIN ( mix ) ) ;
vortex_connection_mixin_mix ( vortex , en , mix ,
vortex - > mixplayb [ ii % 2 ] , 0 ) ;
if ( VORTEX_IS_QUAD ( vortex ) )
vortex_connection_mixin_mix ( vortex , en ,
mix ,
vortex - > mixplayb [ 2 +
( ii % 2 ) ] , 0 ) ;
}
}
for ( i = 0 ; i < NR_WT ; i + + ) {
hwwrite ( vortex - > mmio , WT_RUN ( i ) , 1 ) ;
}
}
/* Read WT Register */
#if 0
static int vortex_wt_GetReg ( vortex_t * vortex , char reg , int wt )
{
//int eax, esi;
if ( reg = = 4 ) {
return hwread ( vortex - > mmio , WT_PARM ( wt , 3 ) ) ;
}
if ( reg = = 7 ) {
return hwread ( vortex - > mmio , WT_GMODE ( wt ) ) ;
}
return 0 ;
}
/* WT hardware abstraction layer generic register interface. */
static int
vortex_wt_SetReg2 ( vortex_t * vortex , unsigned char reg , int wt ,
2006-01-13 17:16:29 +01:00
u16 val )
2005-04-16 15:20:36 -07:00
{
/*
int eax , edx ;
if ( wt > = NR_WT ) // 0x40 -> NR_WT
return 0 ;
if ( ( reg - 0x20 ) > 0 ) {
if ( ( reg - 0x21 ) ! = 0 )
return 0 ;
eax = ( ( ( ( b & 0xff ) < < 0xb ) + ( edx & 0xff ) ) < < 4 ) + 0x208 ; // param 2
} else {
eax = ( ( ( ( b & 0xff ) < < 0xb ) + ( edx & 0xff ) ) < < 4 ) + 0x20a ; // param 3
}
hwwrite ( vortex - > mmio , eax , c ) ;
*/
return 1 ;
}
/*public: static void __thiscall CWTHal::SetReg(unsigned char,int,unsigned long) */
# endif
static int
vortex_wt_SetReg ( vortex_t * vortex , unsigned char reg , int wt ,
2006-01-13 17:16:29 +01:00
u32 val )
2005-04-16 15:20:36 -07:00
{
int ecx ;
if ( ( reg = = 5 ) | | ( ( reg > = 7 ) & & ( reg < = 10 ) ) | | ( reg = = 0xc ) ) {
if ( wt > = ( NR_WT / NR_WT_PB ) ) {
printk
( " vortex: WT SetReg: bank out of range. reg=0x%x, wt=%d \n " ,
reg , wt ) ;
return 0 ;
}
} else {
if ( wt > = NR_WT ) {
2005-10-20 18:26:44 +02:00
printk ( KERN_ERR " vortex: WT SetReg: voice out of range \n " ) ;
2005-04-16 15:20:36 -07:00
return 0 ;
}
}
if ( reg > 0xc )
return 0 ;
switch ( reg ) {
/* Voice specific parameters */
case 0 : /* running */
2009-02-05 16:11:31 +01:00
/*
printk ( KERN_DEBUG " vortex: WT SetReg(0x%x) = 0x%08x \n " ,
WT_RUN ( wt ) , ( int ) val ) ;
*/
2005-04-16 15:20:36 -07:00
hwwrite ( vortex - > mmio , WT_RUN ( wt ) , val ) ;
return 0xc ;
break ;
case 1 : /* param 0 */
2009-02-05 16:11:31 +01:00
/*
printk ( KERN_DEBUG " vortex: WT SetReg(0x%x) = 0x%08x \n " ,
WT_PARM ( wt , 0 ) , ( int ) val ) ;
*/
2005-04-16 15:20:36 -07:00
hwwrite ( vortex - > mmio , WT_PARM ( wt , 0 ) , val ) ;
return 0xc ;
break ;
case 2 : /* param 1 */
2009-02-05 16:11:31 +01:00
/*
printk ( KERN_DEBUG " vortex: WT SetReg(0x%x) = 0x%08x \n " ,
WT_PARM ( wt , 1 ) , ( int ) val ) ;
*/
2005-04-16 15:20:36 -07:00
hwwrite ( vortex - > mmio , WT_PARM ( wt , 1 ) , val ) ;
return 0xc ;
break ;
case 3 : /* param 2 */
2009-02-05 16:11:31 +01:00
/*
printk ( KERN_DEBUG " vortex: WT SetReg(0x%x) = 0x%08x \n " ,
WT_PARM ( wt , 2 ) , ( int ) val ) ;
*/
2005-04-16 15:20:36 -07:00
hwwrite ( vortex - > mmio , WT_PARM ( wt , 2 ) , val ) ;
return 0xc ;
break ;
case 4 : /* param 3 */
2009-02-05 16:11:31 +01:00
/*
printk ( KERN_DEBUG " vortex: WT SetReg(0x%x) = 0x%08x \n " ,
WT_PARM ( wt , 3 ) , ( int ) val ) ;
*/
2005-04-16 15:20:36 -07:00
hwwrite ( vortex - > mmio , WT_PARM ( wt , 3 ) , val ) ;
return 0xc ;
break ;
case 6 : /* mute */
2009-02-05 16:11:31 +01:00
/*
printk ( KERN_DEBUG " vortex: WT SetReg(0x%x) = 0x%08x \n " ,
WT_MUTE ( wt ) , ( int ) val ) ;
*/
2005-04-16 15:20:36 -07:00
hwwrite ( vortex - > mmio , WT_MUTE ( wt ) , val ) ;
return 0xc ;
break ;
case 0xb :
{ /* delay */
2009-02-05 16:11:31 +01:00
/*
printk ( KERN_DEBUG " vortex: WT SetReg(0x%x) = 0x%08x \n " ,
WT_DELAY ( wt , 0 ) , ( int ) val ) ;
*/
2005-04-16 15:20:36 -07:00
hwwrite ( vortex - > mmio , WT_DELAY ( wt , 3 ) , val ) ;
hwwrite ( vortex - > mmio , WT_DELAY ( wt , 2 ) , val ) ;
hwwrite ( vortex - > mmio , WT_DELAY ( wt , 1 ) , val ) ;
hwwrite ( vortex - > mmio , WT_DELAY ( wt , 0 ) , val ) ;
return 0xc ;
}
break ;
/* Global WT block parameters */
case 5 : /* sramp */
ecx = WT_SRAMP ( wt ) ;
break ;
case 8 : /* aramp */
ecx = WT_ARAMP ( wt ) ;
break ;
case 9 : /* mramp */
ecx = WT_MRAMP ( wt ) ;
break ;
case 0xa : /* ctrl */
ecx = WT_CTRL ( wt ) ;
break ;
case 0xc : /* ds_reg */
ecx = WT_DSREG ( wt ) ;
break ;
default :
return 0 ;
break ;
}
2009-02-05 16:11:31 +01:00
/*
printk ( KERN_DEBUG " vortex: WT SetReg(0x%x) = 0x%08x \n " , ecx , ( int ) val ) ;
*/
2005-04-16 15:20:36 -07:00
hwwrite ( vortex - > mmio , ecx , val ) ;
return 1 ;
}
static void vortex_wt_init ( vortex_t * vortex )
{
2006-01-13 17:16:29 +01:00
u32 var4 , var8 , varc , var10 = 0 , edi ;
2005-04-16 15:20:36 -07:00
var10 & = 0xFFFFFFE3 ;
var10 | = 0x22 ;
var10 & = 0xFFFFFEBF ;
var10 | = 0x80 ;
var10 | = 0x200 ;
var10 & = 0xfffffffe ;
var10 & = 0xfffffbff ;
var10 | = 0x1800 ;
// var10 = 0x1AA2
var4 = 0x10000000 ;
varc = 0x00830000 ;
var8 = 0x00830000 ;
/* Init Bank registers. */
for ( edi = 0 ; edi < ( NR_WT / NR_WT_PB ) ; edi + + ) {
vortex_wt_SetReg ( vortex , 0xc , edi , 0 ) ; /* ds_reg */
vortex_wt_SetReg ( vortex , 0xa , edi , var10 ) ; /* ctrl */
vortex_wt_SetReg ( vortex , 0x9 , edi , var4 ) ; /* mramp */
vortex_wt_SetReg ( vortex , 0x8 , edi , varc ) ; /* aramp */
vortex_wt_SetReg ( vortex , 0x5 , edi , var8 ) ; /* sramp */
}
/* Init Voice registers. */
for ( edi = 0 ; edi < NR_WT ; edi + + ) {
vortex_wt_SetReg ( vortex , 0x4 , edi , 0 ) ; /* param 3 0x20c */
vortex_wt_SetReg ( vortex , 0x3 , edi , 0 ) ; /* param 2 0x208 */
vortex_wt_SetReg ( vortex , 0x2 , edi , 0 ) ; /* param 1 0x204 */
vortex_wt_SetReg ( vortex , 0x1 , edi , 0 ) ; /* param 0 0x200 */
vortex_wt_SetReg ( vortex , 0xb , edi , 0 ) ; /* delay 0x400 - 0x40c */
}
var10 | = 1 ;
for ( edi = 0 ; edi < ( NR_WT / NR_WT_PB ) ; edi + + )
vortex_wt_SetReg ( vortex , 0xa , edi , var10 ) ; /* ctrl */
}
/* Extract of CAdbTopology::SetVolume(struct _ASPVOLUME *) */
#if 0
static void vortex_wt_SetVolume ( vortex_t * vortex , int wt , int vol [ ] )
{
wt_voice_t * voice = & ( vortex - > wt_voice [ wt ] ) ;
int ecx = vol [ 1 ] , eax = vol [ 0 ] ;
/* This is pure guess */
voice - > parm0 & = 0xff00ffff ;
voice - > parm0 | = ( vol [ 0 ] & 0xff ) < < 0x10 ;
voice - > parm1 & = 0xff00ffff ;
voice - > parm1 | = ( vol [ 1 ] & 0xff ) < < 0x10 ;
/* This is real */
hwwrite ( vortex , WT_PARM ( wt , 0 ) , voice - > parm0 ) ;
hwwrite ( vortex , WT_PARM ( wt , 1 ) , voice - > parm0 ) ;
if ( voice - > this_1D0 & 4 ) {
eax > > = 8 ;
ecx = eax ;
if ( ecx < 0x80 )
ecx = 0x7f ;
voice - > parm3 & = 0xFFFFC07F ;
voice - > parm3 | = ( ecx & 0x7f ) < < 7 ;
voice - > parm3 & = 0xFFFFFF80 ;
voice - > parm3 | = ( eax & 0x7f ) ;
} else {
voice - > parm3 & = 0xFFE03FFF ;
voice - > parm3 | = ( eax & 0xFE00 ) < < 5 ;
}
hwwrite ( vortex , WT_PARM ( wt , 3 ) , voice - > parm3 ) ;
}
/* Extract of CAdbTopology::SetFrequency(unsigned long arg_0) */
static void vortex_wt_SetFrequency ( vortex_t * vortex , int wt , unsigned int sr )
{
wt_voice_t * voice = & ( vortex - > wt_voice [ wt ] ) ;
2006-01-13 17:16:29 +01:00
u32 eax , edx ;
2005-04-16 15:20:36 -07:00
//FIXME: 64 bit operation.
eax = ( ( sr < < 0xf ) * 0x57619F1 ) & 0xffffffff ;
edx = ( ( ( sr < < 0xf ) * 0x57619F1 ) ) > > 0x20 ;
edx > > = 0xa ;
edx < < = 1 ;
if ( edx ) {
if ( edx & 0x0FFF80000 )
eax = 0x7fff ;
else {
edx < < = 0xd ;
eax = 7 ;
while ( ( edx & 0x80000000 ) = = 0 ) {
edx < < = 1 ;
eax - - ;
2007-09-10 23:15:50 +02:00
if ( eax = = 0 )
break ;
2005-04-16 15:20:36 -07:00
}
if ( eax )
edx < < = 1 ;
eax < < = 0xc ;
edx > > = 0x14 ;
eax | = edx ;
}
} else
eax = 0 ;
voice - > parm0 & = 0xffff0001 ;
voice - > parm0 | = ( eax & 0x7fff ) < < 1 ;
voice - > parm1 = voice - > parm0 | 1 ;
// Wt: this_1D4
//AuWt::WriteReg((ulong)(this_1DC<<4)+0x200, (ulong)this_1E4);
//AuWt::WriteReg((ulong)(this_1DC<<4)+0x204, (ulong)this_1E8);
hwwrite ( vortex - > mmio , WT_PARM ( wt , 0 ) , voice - > parm0 ) ;
hwwrite ( vortex - > mmio , WT_PARM ( wt , 1 ) , voice - > parm1 ) ;
}
# endif
/* End of File */