cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

au88x0_a3d.c (24495B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/***************************************************************************
      3 *            au88x0_a3d.c
      4 *
      5 *  Fri Jul 18 14:16:22 2003
      6 *  Copyright  2003  mjander
      7 *  mjander@users.sourceforge.net
      8 *
      9 * A3D. You may think i'm crazy, but this may work someday. Who knows...
     10 ****************************************************************************/
     11
     12/*
     13 */
     14
     15#include "au88x0_a3d.h"
     16#include "au88x0_a3ddata.c"
     17#include "au88x0_xtalk.h"
     18#include "au88x0.h"
     19
     20static void
     21a3dsrc_SetTimeConsts(a3dsrc_t * a, short HrtfTrack, short ItdTrack,
     22		     short GTrack, short CTrack)
     23{
     24	vortex_t *vortex = (vortex_t *) (a->vortex);
     25	hwwrite(vortex->mmio,
     26		a3d_addrA(a->slice, a->source, A3D_A_HrtfTrackTC), HrtfTrack);
     27	hwwrite(vortex->mmio,
     28		a3d_addrA(a->slice, a->source, A3D_A_ITDTrackTC), ItdTrack);
     29	hwwrite(vortex->mmio,
     30		a3d_addrA(a->slice, a->source, A3D_A_GainTrackTC), GTrack);
     31	hwwrite(vortex->mmio,
     32		a3d_addrA(a->slice, a->source, A3D_A_CoeffTrackTC), CTrack);
     33}
     34
     35#if 0
     36static void
     37a3dsrc_GetTimeConsts(a3dsrc_t * a, short *HrtfTrack, short *ItdTrack,
     38		     short *GTrack, short *CTrack)
     39{
     40	// stub!
     41}
     42
     43#endif
     44/* Atmospheric absorption. */
     45
     46static void
     47a3dsrc_SetAtmosTarget(a3dsrc_t * a, short aa, short b, short c, short d,
     48		      short e)
     49{
     50	vortex_t *vortex = (vortex_t *) (a->vortex);
     51	hwwrite(vortex->mmio,
     52		a3d_addrB(a->slice, a->source, A3D_B_A21Target),
     53		(e << 0x10) | d);
     54	hwwrite(vortex->mmio,
     55		a3d_addrB(a->slice, a->source, A3D_B_B10Target),
     56		(b << 0x10) | aa);
     57	hwwrite(vortex->mmio,
     58		a3d_addrB(a->slice, a->source, A3D_B_B2Target), c);
     59}
     60
     61static void
     62a3dsrc_SetAtmosCurrent(a3dsrc_t * a, short aa, short b, short c, short d,
     63		       short e)
     64{
     65	vortex_t *vortex = (vortex_t *) (a->vortex);
     66	hwwrite(vortex->mmio,
     67		a3d_addrB(a->slice, a->source, A3D_B_A12Current),
     68		(e << 0x10) | d);
     69	hwwrite(vortex->mmio,
     70		a3d_addrB(a->slice, a->source, A3D_B_B01Current),
     71		(b << 0x10) | aa);
     72	hwwrite(vortex->mmio,
     73		a3d_addrB(a->slice, a->source, A3D_B_B2Current), c);
     74}
     75
     76static void
     77a3dsrc_SetAtmosState(a3dsrc_t * a, short x1, short x2, short y1, short y2)
     78{
     79	vortex_t *vortex = (vortex_t *) (a->vortex);
     80	hwwrite(vortex->mmio, a3d_addrA(a->slice, a->source, A3D_A_x1), x1);
     81	hwwrite(vortex->mmio, a3d_addrA(a->slice, a->source, A3D_A_x2), x2);
     82	hwwrite(vortex->mmio, a3d_addrA(a->slice, a->source, A3D_A_y1), y1);
     83	hwwrite(vortex->mmio, a3d_addrA(a->slice, a->source, A3D_A_y2), y2);
     84}
     85
     86#if 0
     87static void
     88a3dsrc_GetAtmosTarget(a3dsrc_t * a, short *aa, short *b, short *c,
     89		      short *d, short *e)
     90{
     91}
     92static void
     93a3dsrc_GetAtmosCurrent(a3dsrc_t * a, short *bb01, short *ab01, short *b2,
     94		       short *aa12, short *ba12)
     95{
     96	vortex_t *vortex = (vortex_t *) (a->vortex);
     97	*aa12 =
     98	    hwread(vortex->mmio,
     99		   a3d_addrA(a->slice, a->source, A3D_A_A12Current));
    100	*ba12 =
    101	    hwread(vortex->mmio,
    102		   a3d_addrB(a->slice, a->source, A3D_B_A12Current));
    103	*ab01 =
    104	    hwread(vortex->mmio,
    105		   a3d_addrA(a->slice, a->source, A3D_A_B01Current));
    106	*bb01 =
    107	    hwread(vortex->mmio,
    108		   a3d_addrB(a->slice, a->source, A3D_B_B01Current));
    109	*b2 =
    110	    hwread(vortex->mmio,
    111		   a3d_addrA(a->slice, a->source, A3D_A_B2Current));
    112}
    113
    114static void
    115a3dsrc_GetAtmosState(a3dsrc_t * a, short *x1, short *x2, short *y1, short *y2)
    116{
    117
    118}
    119
    120#endif
    121/* HRTF */
    122
    123static void
    124a3dsrc_SetHrtfTarget(a3dsrc_t * a, a3d_Hrtf_t const aa, a3d_Hrtf_t const b)
    125{
    126	vortex_t *vortex = (vortex_t *) (a->vortex);
    127	int i;
    128
    129	for (i = 0; i < HRTF_SZ; i++)
    130		hwwrite(vortex->mmio,
    131			a3d_addrB(a->slice, a->source,
    132				  A3D_B_HrtfTarget) + (i << 2),
    133			(b[i] << 0x10) | aa[i]);
    134}
    135
    136static void
    137a3dsrc_SetHrtfCurrent(a3dsrc_t * a, a3d_Hrtf_t const aa, a3d_Hrtf_t const b)
    138{
    139	vortex_t *vortex = (vortex_t *) (a->vortex);
    140	int i;
    141
    142	for (i = 0; i < HRTF_SZ; i++)
    143		hwwrite(vortex->mmio,
    144			a3d_addrB(a->slice, a->source,
    145				  A3D_B_HrtfCurrent) + (i << 2),
    146			(b[i] << 0x10) | aa[i]);
    147}
    148
    149static void
    150a3dsrc_SetHrtfState(a3dsrc_t * a, a3d_Hrtf_t const aa, a3d_Hrtf_t const b)
    151{
    152	vortex_t *vortex = (vortex_t *) (a->vortex);
    153	int i;
    154
    155	for (i = 0; i < HRTF_SZ; i++)
    156		hwwrite(vortex->mmio,
    157			a3d_addrB(a->slice, a->source,
    158				  A3D_B_HrtfDelayLine) + (i << 2),
    159			(b[i] << 0x10) | aa[i]);
    160}
    161
    162static void a3dsrc_SetHrtfOutput(a3dsrc_t * a, short left, short right)
    163{
    164	vortex_t *vortex = (vortex_t *) (a->vortex);
    165	hwwrite(vortex->mmio,
    166		a3d_addrA(a->slice, a->source, A3D_A_HrtfOutL), left);
    167	hwwrite(vortex->mmio,
    168		a3d_addrA(a->slice, a->source, A3D_A_HrtfOutR), right);
    169}
    170
    171#if 0
    172static void a3dsrc_GetHrtfTarget(a3dsrc_t * a, a3d_Hrtf_t aa, a3d_Hrtf_t b)
    173{
    174	vortex_t *vortex = (vortex_t *) (a->vortex);
    175	int i;
    176
    177	for (i = 0; i < HRTF_SZ; i++)
    178		aa[i] =
    179		    hwread(vortex->mmio,
    180			   a3d_addrA(a->slice, a->source,
    181				     A3D_A_HrtfTarget + (i << 2)));
    182	for (i = 0; i < HRTF_SZ; i++)
    183		b[i] =
    184		    hwread(vortex->mmio,
    185			   a3d_addrB(a->slice, a->source,
    186				     A3D_B_HrtfTarget + (i << 2)));
    187}
    188
    189static void a3dsrc_GetHrtfCurrent(a3dsrc_t * a, a3d_Hrtf_t aa, a3d_Hrtf_t b)
    190{
    191	vortex_t *vortex = (vortex_t *) (a->vortex);
    192	int i;
    193
    194	for (i = 0; i < HRTF_SZ; i++)
    195		aa[i] =
    196		    hwread(vortex->mmio,
    197			   a3d_addrA(a->slice, a->source,
    198				     A3D_A_HrtfCurrent + (i << 2)));
    199	for (i = 0; i < HRTF_SZ; i++)
    200		b[i] =
    201		    hwread(vortex->mmio,
    202			   a3d_addrB(a->slice, a->source,
    203				     A3D_B_HrtfCurrent + (i << 2)));
    204}
    205
    206static void a3dsrc_GetHrtfState(a3dsrc_t * a, a3d_Hrtf_t aa, a3d_Hrtf_t b)
    207{
    208	vortex_t *vortex = (vortex_t *) (a->vortex);
    209	int i;
    210	// FIXME: verify this!
    211	for (i = 0; i < HRTF_SZ; i++)
    212		aa[i] =
    213		    hwread(vortex->mmio,
    214			   a3d_addrA(a->slice, a->source,
    215				     A3D_A_HrtfDelayLine + (i << 2)));
    216	for (i = 0; i < HRTF_SZ; i++)
    217		b[i] =
    218		    hwread(vortex->mmio,
    219			   a3d_addrB(a->slice, a->source,
    220				     A3D_B_HrtfDelayLine + (i << 2)));
    221}
    222
    223static void a3dsrc_GetHrtfOutput(a3dsrc_t * a, short *left, short *right)
    224{
    225	vortex_t *vortex = (vortex_t *) (a->vortex);
    226	*left =
    227	    hwread(vortex->mmio,
    228		   a3d_addrA(a->slice, a->source, A3D_A_HrtfOutL));
    229	*right =
    230	    hwread(vortex->mmio,
    231		   a3d_addrA(a->slice, a->source, A3D_A_HrtfOutR));
    232}
    233
    234#endif
    235
    236/* Interaural Time Difference. 
    237 * "The other main clue that humans use to locate sounds, is called 
    238 * Interaural Time Difference (ITD). The differences in distance from 
    239 * the sound source to a listeners ears means  that the sound will 
    240 * reach one ear slightly before the other....", found somewhere with google.*/
    241static void a3dsrc_SetItdTarget(a3dsrc_t * a, short litd, short ritd)
    242{
    243	vortex_t *vortex = (vortex_t *) (a->vortex);
    244
    245	if (litd < 0)
    246		litd = 0;
    247	if (litd > 0x57FF)
    248		litd = 0x57FF;
    249	if (ritd < 0)
    250		ritd = 0;
    251	if (ritd > 0x57FF)
    252		ritd = 0x57FF;
    253	hwwrite(vortex->mmio,
    254		a3d_addrB(a->slice, a->source, A3D_B_ITDTarget),
    255		(ritd << 0x10) | litd);
    256	//hwwrite(vortex->mmio, addr(0x191DF+5, this04, this08), (ritd<<0x10)|litd);
    257}
    258
    259static void a3dsrc_SetItdCurrent(a3dsrc_t * a, short litd, short ritd)
    260{
    261	vortex_t *vortex = (vortex_t *) (a->vortex);
    262
    263	if (litd < 0)
    264		litd = 0;
    265	if (litd > 0x57FF)
    266		litd = 0x57FF;
    267	if (ritd < 0)
    268		ritd = 0;
    269	if (ritd > 0x57FF)
    270		ritd = 0x57FF;
    271	hwwrite(vortex->mmio,
    272		a3d_addrB(a->slice, a->source, A3D_B_ITDCurrent),
    273		(ritd << 0x10) | litd);
    274	//hwwrite(vortex->mmio, addr(0x191DF+1, this04, this08), (ritd<<0x10)|litd);
    275}
    276
    277static void a3dsrc_SetItdDline(a3dsrc_t * a, a3d_ItdDline_t const dline)
    278{
    279	vortex_t *vortex = (vortex_t *) (a->vortex);
    280	int i;
    281	/* 45 != 40 -> Check this ! */
    282	for (i = 0; i < DLINE_SZ; i++)
    283		hwwrite(vortex->mmio,
    284			a3d_addrA(a->slice, a->source,
    285				  A3D_A_ITDDelayLine) + (i << 2), dline[i]);
    286}
    287
    288#if 0
    289static void a3dsrc_GetItdTarget(a3dsrc_t * a, short *litd, short *ritd)
    290{
    291	vortex_t *vortex = (vortex_t *) (a->vortex);
    292	*ritd =
    293	    hwread(vortex->mmio,
    294		   a3d_addrA(a->slice, a->source, A3D_A_ITDTarget));
    295	*litd =
    296	    hwread(vortex->mmio,
    297		   a3d_addrB(a->slice, a->source, A3D_B_ITDTarget));
    298}
    299
    300static void a3dsrc_GetItdCurrent(a3dsrc_t * a, short *litd, short *ritd)
    301{
    302	vortex_t *vortex = (vortex_t *) (a->vortex);
    303
    304	*ritd =
    305	    hwread(vortex->mmio,
    306		   a3d_addrA(a->slice, a->source, A3D_A_ITDCurrent));
    307	*litd =
    308	    hwread(vortex->mmio,
    309		   a3d_addrB(a->slice, a->source, A3D_B_ITDCurrent));
    310}
    311
    312static void a3dsrc_GetItdDline(a3dsrc_t * a, a3d_ItdDline_t dline)
    313{
    314	vortex_t *vortex = (vortex_t *) (a->vortex);
    315	int i;
    316
    317	for (i = 0; i < DLINE_SZ; i++)
    318		dline[i] =
    319		    hwread(vortex->mmio,
    320			   a3d_addrA(a->slice, a->source,
    321				     A3D_A_ITDDelayLine + (i << 2)));
    322}
    323
    324#endif
    325/* This is may be used for ILD Interaural Level Difference. */
    326
    327static void a3dsrc_SetGainTarget(a3dsrc_t * a, short left, short right)
    328{
    329	vortex_t *vortex = (vortex_t *) (a->vortex);
    330	hwwrite(vortex->mmio,
    331		a3d_addrB(a->slice, a->source, A3D_B_GainTarget),
    332		(right << 0x10) | left);
    333}
    334
    335static void a3dsrc_SetGainCurrent(a3dsrc_t * a, short left, short right)
    336{
    337	vortex_t *vortex = (vortex_t *) (a->vortex);
    338	hwwrite(vortex->mmio,
    339		a3d_addrB(a->slice, a->source, A3D_B_GainCurrent),
    340		(right << 0x10) | left);
    341}
    342
    343#if 0
    344static void a3dsrc_GetGainTarget(a3dsrc_t * a, short *left, short *right)
    345{
    346	vortex_t *vortex = (vortex_t *) (a->vortex);
    347	*right =
    348	    hwread(vortex->mmio,
    349		   a3d_addrA(a->slice, a->source, A3D_A_GainTarget));
    350	*left =
    351	    hwread(vortex->mmio,
    352		   a3d_addrB(a->slice, a->source, A3D_B_GainTarget));
    353}
    354
    355static void a3dsrc_GetGainCurrent(a3dsrc_t * a, short *left, short *right)
    356{
    357	vortex_t *vortex = (vortex_t *) (a->vortex);
    358	*right =
    359	    hwread(vortex->mmio,
    360		   a3d_addrA(a->slice, a->source, A3D_A_GainCurrent));
    361	*left =
    362	    hwread(vortex->mmio,
    363		   a3d_addrB(a->slice, a->source, A3D_B_GainCurrent));
    364}
    365
    366/* CA3dIO this func seems to be inlined all over this place. */
    367static void CA3dIO_WriteReg(a3dsrc_t * a, unsigned long addr, short aa, short b)
    368{
    369	vortex_t *vortex = (vortex_t *) (a->vortex);
    370	hwwrite(vortex->mmio, addr, (aa << 0x10) | b);
    371}
    372
    373#endif
    374/* Generic A3D stuff */
    375
    376static void a3dsrc_SetA3DSampleRate(a3dsrc_t * a, int sr)
    377{
    378	vortex_t *vortex = (vortex_t *) (a->vortex);
    379	int esp0 = 0;
    380
    381	esp0 = (((esp0 & 0x7fffffff) | 0xB8000000) & 0x7) | ((sr & 0x1f) << 3);
    382	hwwrite(vortex->mmio, A3D_SLICE_Control + ((a->slice) << 0xd), esp0);
    383	//hwwrite(vortex->mmio, 0x19C38 + (this08<<0xd), esp0);
    384}
    385
    386static void a3dsrc_EnableA3D(a3dsrc_t * a)
    387{
    388	vortex_t *vortex = (vortex_t *) (a->vortex);
    389	hwwrite(vortex->mmio, A3D_SLICE_Control + ((a->slice) << 0xd),
    390		0xF0000001);
    391	//hwwrite(vortex->mmio, 0x19C38 + (this08<<0xd), 0xF0000001);
    392}
    393
    394static void a3dsrc_DisableA3D(a3dsrc_t * a)
    395{
    396	vortex_t *vortex = (vortex_t *) (a->vortex);
    397	hwwrite(vortex->mmio, A3D_SLICE_Control + ((a->slice) << 0xd),
    398		0xF0000000);
    399}
    400
    401static void a3dsrc_SetA3DControlReg(a3dsrc_t * a, unsigned long ctrl)
    402{
    403	vortex_t *vortex = (vortex_t *) (a->vortex);
    404	hwwrite(vortex->mmio, A3D_SLICE_Control + ((a->slice) << 0xd), ctrl);
    405}
    406
    407static void a3dsrc_SetA3DPointerReg(a3dsrc_t * a, unsigned long ptr)
    408{
    409	vortex_t *vortex = (vortex_t *) (a->vortex);
    410	hwwrite(vortex->mmio, A3D_SLICE_Pointers + ((a->slice) << 0xd), ptr);
    411}
    412
    413#if 0
    414static void a3dsrc_GetA3DSampleRate(a3dsrc_t * a, int *sr)
    415{
    416	vortex_t *vortex = (vortex_t *) (a->vortex);
    417	*sr = ((hwread(vortex->mmio, A3D_SLICE_Control + (a->slice << 0xd))
    418		>> 3) & 0x1f);
    419	//*sr = ((hwread(vortex->mmio, 0x19C38 + (this08<<0xd))>>3)&0x1f);
    420}
    421
    422static void a3dsrc_GetA3DControlReg(a3dsrc_t * a, unsigned long *ctrl)
    423{
    424	vortex_t *vortex = (vortex_t *) (a->vortex);
    425	*ctrl = hwread(vortex->mmio, A3D_SLICE_Control + ((a->slice) << 0xd));
    426}
    427
    428static void a3dsrc_GetA3DPointerReg(a3dsrc_t * a, unsigned long *ptr)
    429{
    430	vortex_t *vortex = (vortex_t *) (a->vortex);
    431	*ptr = hwread(vortex->mmio, A3D_SLICE_Pointers + ((a->slice) << 0xd));
    432}
    433
    434#endif
    435static void a3dsrc_ZeroSliceIO(a3dsrc_t * a)
    436{
    437	vortex_t *vortex = (vortex_t *) (a->vortex);
    438	int i;
    439
    440	for (i = 0; i < 8; i++)
    441		hwwrite(vortex->mmio,
    442			A3D_SLICE_VDBDest +
    443			((((a->slice) << 0xb) + i) << 2), 0);
    444	for (i = 0; i < 4; i++)
    445		hwwrite(vortex->mmio,
    446			A3D_SLICE_VDBSource +
    447			((((a->slice) << 0xb) + i) << 2), 0);
    448}
    449
    450/* Reset Single A3D source. */
    451static void a3dsrc_ZeroState(a3dsrc_t * a)
    452{
    453	/*
    454	pr_debug( "vortex: ZeroState slice: %d, source %d\n",
    455	       a->slice, a->source);
    456	*/
    457	a3dsrc_SetAtmosState(a, 0, 0, 0, 0);
    458	a3dsrc_SetHrtfState(a, A3dHrirZeros, A3dHrirZeros);
    459	a3dsrc_SetItdDline(a, A3dItdDlineZeros);
    460	a3dsrc_SetHrtfOutput(a, 0, 0);
    461	a3dsrc_SetTimeConsts(a, 0, 0, 0, 0);
    462
    463	a3dsrc_SetAtmosCurrent(a, 0, 0, 0, 0, 0);
    464	a3dsrc_SetAtmosTarget(a, 0, 0, 0, 0, 0);
    465	a3dsrc_SetItdCurrent(a, 0, 0);
    466	a3dsrc_SetItdTarget(a, 0, 0);
    467	a3dsrc_SetGainCurrent(a, 0, 0);
    468	a3dsrc_SetGainTarget(a, 0, 0);
    469
    470	a3dsrc_SetHrtfCurrent(a, A3dHrirZeros, A3dHrirZeros);
    471	a3dsrc_SetHrtfTarget(a, A3dHrirZeros, A3dHrirZeros);
    472}
    473
    474/* Reset entire A3D engine */
    475static void a3dsrc_ZeroStateA3D(a3dsrc_t *a, vortex_t *v)
    476{
    477	int i, var, var2;
    478
    479	if ((a->vortex) == NULL) {
    480		dev_err(v->card->dev,
    481			"ZeroStateA3D: ERROR: a->vortex is NULL\n");
    482		return;
    483	}
    484
    485	a3dsrc_SetA3DControlReg(a, 0);
    486	a3dsrc_SetA3DPointerReg(a, 0);
    487
    488	var = a->slice;
    489	var2 = a->source;
    490	for (i = 0; i < 4; i++) {
    491		a->slice = i;
    492		a3dsrc_ZeroSliceIO(a);
    493		//a3dsrc_ZeroState(a);
    494	}
    495	a->source = var2;
    496	a->slice = var;
    497}
    498
    499/* Program A3D block as pass through */
    500static void a3dsrc_ProgramPipe(a3dsrc_t * a)
    501{
    502	a3dsrc_SetTimeConsts(a, 0, 0, 0, 0);
    503	a3dsrc_SetAtmosCurrent(a, 0, 0x4000, 0, 0, 0);
    504	a3dsrc_SetAtmosTarget(a, 0x4000, 0, 0, 0, 0);
    505	a3dsrc_SetItdCurrent(a, 0, 0);
    506	a3dsrc_SetItdTarget(a, 0, 0);
    507	a3dsrc_SetGainCurrent(a, 0x7fff, 0x7fff);
    508	a3dsrc_SetGainTarget(a, 0x7fff, 0x7fff);
    509
    510	/* SET HRTF HERE */
    511
    512	/* Single spike leads to identity transfer function. */
    513	a3dsrc_SetHrtfCurrent(a, A3dHrirImpulse, A3dHrirImpulse);
    514	a3dsrc_SetHrtfTarget(a, A3dHrirImpulse, A3dHrirImpulse);
    515
    516	/* Test: Sounds saturated. */
    517	//a3dsrc_SetHrtfCurrent(a, A3dHrirSatTest, A3dHrirSatTest);
    518	//a3dsrc_SetHrtfTarget(a, A3dHrirSatTest, A3dHrirSatTest);      
    519}
    520
    521/* VDB = Vortex audio Dataflow Bus */
    522#if 0
    523static void a3dsrc_ClearVDBData(a3dsrc_t * a, unsigned long aa)
    524{
    525	vortex_t *vortex = (vortex_t *) (a->vortex);
    526
    527	// ((aa >> 2) << 8) - (aa >> 2)
    528	hwwrite(vortex->mmio,
    529		a3d_addrS(a->slice, A3D_SLICE_VDBDest) + (a->source << 2), 0);
    530	hwwrite(vortex->mmio,
    531		a3d_addrS(a->slice,
    532			  A3D_SLICE_VDBDest + 4) + (a->source << 2), 0);
    533	/*
    534	   hwwrite(vortex->mmio, 0x19c00 + (((aa>>2)*255*4)+aa)*8, 0);
    535	   hwwrite(vortex->mmio, 0x19c04 + (((aa>>2)*255*4)+aa)*8, 0);
    536	 */
    537}
    538#endif
    539
    540/* A3D HwSource stuff. */
    541
    542static void vortex_A3dSourceHw_Initialize(vortex_t * v, int source, int slice)
    543{
    544	a3dsrc_t *a3dsrc = &(v->a3d[source + (slice * 4)]);
    545	//a3dsrc_t *a3dsrc = &(v->a3d[source + (slice*4)]);
    546
    547	a3dsrc->vortex = (void *)v;
    548	a3dsrc->source = source;	/* source */
    549	a3dsrc->slice = slice;	/* slice */
    550	a3dsrc_ZeroState(a3dsrc);
    551	/* Added by me. */
    552	a3dsrc_SetA3DSampleRate(a3dsrc, 0x11);
    553}
    554
    555static int Vort3DRend_Initialize(vortex_t * v, unsigned short mode)
    556{
    557	v->xt_mode = mode;	/* this_14 */
    558
    559	vortex_XtalkHw_init(v);
    560	vortex_XtalkHw_SetGainsAllChan(v);
    561	switch (v->xt_mode) {
    562	case XT_SPEAKER0:
    563		vortex_XtalkHw_ProgramXtalkNarrow(v);
    564		break;
    565	case XT_SPEAKER1:
    566		vortex_XtalkHw_ProgramXtalkWide(v);
    567		break;
    568	default:
    569	case XT_HEADPHONE:
    570		vortex_XtalkHw_ProgramPipe(v);
    571		break;
    572	case XT_DIAMOND:
    573		vortex_XtalkHw_ProgramDiamondXtalk(v);
    574		break;
    575	}
    576	vortex_XtalkHw_SetSampleRate(v, 0x11);
    577	vortex_XtalkHw_Enable(v);
    578	return 0;
    579}
    580
    581/* 3D Sound entry points. */
    582
    583static int vortex_a3d_register_controls(vortex_t * vortex);
    584static void vortex_a3d_unregister_controls(vortex_t * vortex);
    585/* A3D base support init/shudown */
    586static void vortex_Vort3D_enable(vortex_t *v)
    587{
    588	int i;
    589
    590	Vort3DRend_Initialize(v, XT_HEADPHONE);
    591	for (i = 0; i < NR_A3D; i++) {
    592		vortex_A3dSourceHw_Initialize(v, i % 4, i >> 2);
    593		a3dsrc_ZeroStateA3D(&v->a3d[0], v);
    594	}
    595	/* Register ALSA controls */
    596	vortex_a3d_register_controls(v);
    597}
    598
    599static void vortex_Vort3D_disable(vortex_t * v)
    600{
    601	vortex_XtalkHw_Disable(v);
    602	vortex_a3d_unregister_controls(v);
    603}
    604
    605/* Make A3D subsystem connections. */
    606static void vortex_Vort3D_connect(vortex_t * v, int en)
    607{
    608	int i;
    609	
    610// Disable AU8810 routes, since they seem to be wrong (in au8810.h).
    611#ifdef CHIP_AU8810
    612	return;
    613#endif
    614	
    615#if 1
    616	/* Alloc Xtalk mixin resources */
    617	v->mixxtlk[0] =
    618	    vortex_adb_checkinout(v, v->fixed_res, en, VORTEX_RESOURCE_MIXIN);
    619	if (v->mixxtlk[0] < 0) {
    620		dev_warn(v->card->dev,
    621			 "vortex_Vort3D: ERROR: not enough free mixer resources.\n");
    622		return;
    623	}
    624	v->mixxtlk[1] =
    625	    vortex_adb_checkinout(v, v->fixed_res, en, VORTEX_RESOURCE_MIXIN);
    626	if (v->mixxtlk[1] < 0) {
    627		dev_warn(v->card->dev,
    628			 "vortex_Vort3D: ERROR: not enough free mixer resources.\n");
    629		return;
    630	}
    631#endif
    632
    633	/* Connect A3D -> XTALK */
    634	for (i = 0; i < 4; i++) {
    635		// 2 outputs per each A3D slice. 
    636		vortex_route(v, en, 0x11, ADB_A3DOUT(i * 2), ADB_XTALKIN(i));
    637		vortex_route(v, en, 0x11, ADB_A3DOUT(i * 2) + 1, ADB_XTALKIN(5 + i));
    638	}
    639#if 0
    640	vortex_route(v, en, 0x11, ADB_XTALKOUT(0), ADB_EQIN(2));
    641	vortex_route(v, en, 0x11, ADB_XTALKOUT(1), ADB_EQIN(3));
    642#else
    643	/* Connect XTalk -> mixer */
    644	vortex_route(v, en, 0x11, ADB_XTALKOUT(0), ADB_MIXIN(v->mixxtlk[0]));
    645	vortex_route(v, en, 0x11, ADB_XTALKOUT(1), ADB_MIXIN(v->mixxtlk[1]));
    646	vortex_connection_mixin_mix(v, en, v->mixxtlk[0], v->mixplayb[0], 0);
    647	vortex_connection_mixin_mix(v, en, v->mixxtlk[1], v->mixplayb[1], 0);
    648	vortex_mix_setinputvolumebyte(v, v->mixplayb[0], v->mixxtlk[0],
    649				      en ? MIX_DEFIGAIN : VOL_MIN);
    650	vortex_mix_setinputvolumebyte(v, v->mixplayb[1], v->mixxtlk[1],
    651				      en ? MIX_DEFIGAIN : VOL_MIN);
    652	if (VORTEX_IS_QUAD(v)) {
    653		vortex_connection_mixin_mix(v, en, v->mixxtlk[0],
    654					    v->mixplayb[2], 0);
    655		vortex_connection_mixin_mix(v, en, v->mixxtlk[1],
    656					    v->mixplayb[3], 0);
    657		vortex_mix_setinputvolumebyte(v, v->mixplayb[2],
    658					      v->mixxtlk[0],
    659					      en ? MIX_DEFIGAIN : VOL_MIN);
    660		vortex_mix_setinputvolumebyte(v, v->mixplayb[3],
    661					      v->mixxtlk[1],
    662					      en ? MIX_DEFIGAIN : VOL_MIN);
    663	}
    664#endif
    665}
    666
    667/* Initialize one single A3D source. */
    668static void vortex_Vort3D_InitializeSource(a3dsrc_t *a, int en, vortex_t *v)
    669{
    670	if (a->vortex == NULL) {
    671		dev_warn(v->card->dev,
    672			 "Vort3D_InitializeSource: A3D source not initialized\n");
    673		return;
    674	}
    675	if (en) {
    676		a3dsrc_ProgramPipe(a);
    677		a3dsrc_SetA3DSampleRate(a, 0x11);
    678		a3dsrc_SetTimeConsts(a, HrtfTCDefault,
    679				     ItdTCDefault, GainTCDefault,
    680				     CoefTCDefault);
    681		/* Remark: zero gain is muted. */
    682		//a3dsrc_SetGainTarget(a,0,0);
    683		//a3dsrc_SetGainCurrent(a,0,0);
    684		a3dsrc_EnableA3D(a);
    685	} else {
    686		a3dsrc_DisableA3D(a);
    687		a3dsrc_ZeroState(a);
    688	}
    689}
    690
    691/* Conversion of coordinates into 3D parameters. */
    692
    693static void vortex_a3d_coord2hrtf(a3d_Hrtf_t hrtf, int *coord)
    694{
    695	/* FIXME: implement this. */
    696
    697}
    698static void vortex_a3d_coord2itd(a3d_Itd_t itd, int *coord)
    699{
    700	/* FIXME: implement this. */
    701
    702}
    703static void vortex_a3d_coord2ild(a3d_LRGains_t ild, int left, int right)
    704{
    705	/* FIXME: implement this. */
    706
    707}
    708static void vortex_a3d_translate_filter(a3d_atmos_t filter, int *params)
    709{
    710	/* FIXME: implement this. */
    711
    712}
    713
    714/* ALSA control interface.  */
    715
    716static int
    717snd_vortex_a3d_hrtf_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
    718{
    719	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
    720	uinfo->count = 6;
    721	uinfo->value.integer.min = 0x00000000;
    722	uinfo->value.integer.max = 0xffffffff;
    723	return 0;
    724}
    725static int
    726snd_vortex_a3d_itd_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
    727{
    728	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
    729	uinfo->count = 2;
    730	uinfo->value.integer.min = 0x00000000;
    731	uinfo->value.integer.max = 0xffffffff;
    732	return 0;
    733}
    734static int
    735snd_vortex_a3d_ild_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
    736{
    737	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
    738	uinfo->count = 2;
    739	uinfo->value.integer.min = 0x00000000;
    740	uinfo->value.integer.max = 0xffffffff;
    741	return 0;
    742}
    743static int
    744snd_vortex_a3d_filter_info(struct snd_kcontrol *kcontrol,
    745			   struct snd_ctl_elem_info *uinfo)
    746{
    747	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
    748	uinfo->count = 4;
    749	uinfo->value.integer.min = 0x00000000;
    750	uinfo->value.integer.max = 0xffffffff;
    751	return 0;
    752}
    753
    754static int
    755snd_vortex_a3d_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
    756{
    757	//a3dsrc_t *a = kcontrol->private_data;
    758	/* No read yet. Would this be really useable/needed ? */
    759
    760	return 0;
    761}
    762
    763static int
    764snd_vortex_a3d_hrtf_put(struct snd_kcontrol *kcontrol,
    765			struct snd_ctl_elem_value *ucontrol)
    766{
    767	a3dsrc_t *a = kcontrol->private_data;
    768	int i;
    769	int coord[6];
    770	for (i = 0; i < 6; i++)
    771		coord[i] = ucontrol->value.integer.value[i];
    772	/* Translate orientation coordinates to a3d params. */
    773	vortex_a3d_coord2hrtf(a->hrtf[0], coord);
    774	vortex_a3d_coord2hrtf(a->hrtf[1], coord);
    775	a3dsrc_SetHrtfTarget(a, a->hrtf[0], a->hrtf[1]);
    776	a3dsrc_SetHrtfCurrent(a, a->hrtf[0], a->hrtf[1]);
    777	return 1;
    778}
    779
    780static int
    781snd_vortex_a3d_itd_put(struct snd_kcontrol *kcontrol,
    782		       struct snd_ctl_elem_value *ucontrol)
    783{
    784	a3dsrc_t *a = kcontrol->private_data;
    785	int coord[6];
    786	int i;
    787	for (i = 0; i < 6; i++)
    788		coord[i] = ucontrol->value.integer.value[i];
    789	/* Translate orientation coordinates to a3d params. */
    790	vortex_a3d_coord2itd(a->hrtf[0], coord);
    791	vortex_a3d_coord2itd(a->hrtf[1], coord);
    792	/* Inter aural time difference. */
    793	a3dsrc_SetItdTarget(a, a->itd[0], a->itd[1]);
    794	a3dsrc_SetItdCurrent(a, a->itd[0], a->itd[1]);
    795	a3dsrc_SetItdDline(a, a->dline);
    796	return 1;
    797}
    798
    799static int
    800snd_vortex_a3d_ild_put(struct snd_kcontrol *kcontrol,
    801		       struct snd_ctl_elem_value *ucontrol)
    802{
    803	a3dsrc_t *a = kcontrol->private_data;
    804	int l, r;
    805	/* There may be some scale tranlation needed here. */
    806	l = ucontrol->value.integer.value[0];
    807	r = ucontrol->value.integer.value[1];
    808	vortex_a3d_coord2ild(a->ild, l, r);
    809	/* Left Right panning. */
    810	a3dsrc_SetGainTarget(a, l, r);
    811	a3dsrc_SetGainCurrent(a, l, r);
    812	return 1;
    813}
    814
    815static int
    816snd_vortex_a3d_filter_put(struct snd_kcontrol *kcontrol,
    817			  struct snd_ctl_elem_value *ucontrol)
    818{
    819	a3dsrc_t *a = kcontrol->private_data;
    820	int i;
    821	int params[6];
    822	for (i = 0; i < 6; i++)
    823		params[i] = ucontrol->value.integer.value[i];
    824	/* Translate generic filter params to a3d filter params. */
    825	vortex_a3d_translate_filter(a->filter, params);
    826	/* Atmospheric absorption and filtering. */
    827	a3dsrc_SetAtmosTarget(a, a->filter[0],
    828			      a->filter[1], a->filter[2],
    829			      a->filter[3], a->filter[4]);
    830	a3dsrc_SetAtmosCurrent(a, a->filter[0],
    831			       a->filter[1], a->filter[2],
    832			       a->filter[3], a->filter[4]);
    833	return 1;
    834}
    835
    836static const struct snd_kcontrol_new vortex_a3d_kcontrol = {
    837	.iface = SNDRV_CTL_ELEM_IFACE_PCM,
    838	.name = "Playback PCM advanced processing",
    839	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
    840	.info = snd_vortex_a3d_hrtf_info,
    841	.get = snd_vortex_a3d_get,
    842	.put = snd_vortex_a3d_hrtf_put,
    843};
    844
    845/* Control (un)registration. */
    846static int vortex_a3d_register_controls(vortex_t *vortex)
    847{
    848	struct snd_kcontrol *kcontrol;
    849	int err, i;
    850	/* HRTF controls. */
    851	for (i = 0; i < NR_A3D; i++) {
    852		kcontrol = snd_ctl_new1(&vortex_a3d_kcontrol, &vortex->a3d[i]);
    853		if (!kcontrol)
    854			return -ENOMEM;
    855		kcontrol->id.numid = CTRLID_HRTF;
    856		kcontrol->info = snd_vortex_a3d_hrtf_info;
    857		kcontrol->put = snd_vortex_a3d_hrtf_put;
    858		err = snd_ctl_add(vortex->card, kcontrol);
    859		if (err < 0)
    860			return err;
    861	}
    862	/* ITD controls. */
    863	for (i = 0; i < NR_A3D; i++) {
    864		kcontrol = snd_ctl_new1(&vortex_a3d_kcontrol, &vortex->a3d[i]);
    865		if (!kcontrol)
    866			return -ENOMEM;
    867		kcontrol->id.numid = CTRLID_ITD;
    868		kcontrol->info = snd_vortex_a3d_itd_info;
    869		kcontrol->put = snd_vortex_a3d_itd_put;
    870		err = snd_ctl_add(vortex->card, kcontrol);
    871		if (err < 0)
    872			return err;
    873	}
    874	/* ILD (gains) controls. */
    875	for (i = 0; i < NR_A3D; i++) {
    876		kcontrol = snd_ctl_new1(&vortex_a3d_kcontrol, &vortex->a3d[i]);
    877		if (!kcontrol)
    878			return -ENOMEM;
    879		kcontrol->id.numid = CTRLID_GAINS;
    880		kcontrol->info = snd_vortex_a3d_ild_info;
    881		kcontrol->put = snd_vortex_a3d_ild_put;
    882		err = snd_ctl_add(vortex->card, kcontrol);
    883		if (err < 0)
    884			return err;
    885	}
    886	/* Filter controls. */
    887	for (i = 0; i < NR_A3D; i++) {
    888		kcontrol = snd_ctl_new1(&vortex_a3d_kcontrol, &vortex->a3d[i]);
    889		if (!kcontrol)
    890			return -ENOMEM;
    891		kcontrol->id.numid = CTRLID_FILTER;
    892		kcontrol->info = snd_vortex_a3d_filter_info;
    893		kcontrol->put = snd_vortex_a3d_filter_put;
    894		err = snd_ctl_add(vortex->card, kcontrol);
    895		if (err < 0)
    896			return err;
    897	}
    898	return 0;
    899}
    900
    901static void vortex_a3d_unregister_controls(vortex_t * vortex)
    902{
    903
    904}
    905
    906/* End of File*/