root/sound/pci/au88x0/au88x0_synth.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. vortex_wt_setstereo
  2. vortex_wt_setdsout
  3. vortex_wt_allocroute
  4. vortex_wt_connect
  5. vortex_wt_GetReg
  6. vortex_wt_SetReg2
  7. vortex_wt_SetReg
  8. vortex_wt_init
  9. vortex_wt_SetVolume
  10. vortex_wt_SetFrequency

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  */
   4 
   5 /*
   6  * Someday its supposed to make use of the WT DMA engine
   7  * for a Wavetable synthesizer.
   8  */
   9 
  10 #include "au88x0.h"
  11 #include "au88x0_wt.h"
  12 
  13 static void vortex_fifo_setwtvalid(vortex_t * vortex, int fifo, int en);
  14 static void vortex_connection_adb_mixin(vortex_t * vortex, int en,
  15                                         unsigned char channel,
  16                                         unsigned char source,
  17                                         unsigned char mixin);
  18 static void vortex_connection_mixin_mix(vortex_t * vortex, int en,
  19                                         unsigned char mixin,
  20                                         unsigned char mix, int a);
  21 static void vortex_fifo_wtinitialize(vortex_t * vortex, int fifo, int j);
  22 static int vortex_wt_SetReg(vortex_t * vortex, unsigned char reg, int wt,
  23                             u32 val);
  24 
  25 /* WT */
  26 
  27 /* Put 2 WT channels together for one stereo interlaced channel. */
  28 static void vortex_wt_setstereo(vortex_t * vortex, u32 wt, u32 stereo)
  29 {
  30         int temp;
  31 
  32         //temp = hwread(vortex->mmio, 0x80 + ((wt >> 0x5)<< 0xf) + (((wt & 0x1f) >> 1) << 2));
  33         temp = hwread(vortex->mmio, WT_STEREO(wt));
  34         temp = (temp & 0xfe) | (stereo & 1);
  35         //hwwrite(vortex->mmio, 0x80 + ((wt >> 0x5)<< 0xf) + (((wt & 0x1f) >> 1) << 2), temp);
  36         hwwrite(vortex->mmio, WT_STEREO(wt), temp);
  37 }
  38 
  39 /* Join to mixdown route. */
  40 static void vortex_wt_setdsout(vortex_t * vortex, u32 wt, int en)
  41 {
  42         int temp;
  43 
  44         /* There is one DSREG register for each bank (32 voices each). */
  45         temp = hwread(vortex->mmio, WT_DSREG((wt >= 0x20) ? 1 : 0));
  46         if (en)
  47                 temp |= (1 << (wt & 0x1f));
  48         else
  49                 temp &= ~(1 << (wt & 0x1f));
  50         hwwrite(vortex->mmio, WT_DSREG((wt >= 0x20) ? 1 : 0), temp);
  51 }
  52 
  53 /* Setup WT route. */
  54 static int vortex_wt_allocroute(vortex_t * vortex, int wt, int nr_ch)
  55 {
  56         wt_voice_t *voice = &(vortex->wt_voice[wt]);
  57         int temp;
  58 
  59         //FIXME: WT audio routing.
  60         if (nr_ch) {
  61                 vortex_fifo_wtinitialize(vortex, wt, 1);
  62                 vortex_fifo_setwtvalid(vortex, wt, 1);
  63                 vortex_wt_setstereo(vortex, wt, nr_ch - 1);
  64         } else
  65                 vortex_fifo_setwtvalid(vortex, wt, 0);
  66         
  67         /* Set mixdown mode. */
  68         vortex_wt_setdsout(vortex, wt, 1);
  69         /* Set other parameter registers. */
  70         hwwrite(vortex->mmio, WT_SRAMP(0), 0x880000);
  71         //hwwrite(vortex->mmio, WT_GMODE(0), 0xffffffff);
  72 #ifdef CHIP_AU8830
  73         hwwrite(vortex->mmio, WT_SRAMP(1), 0x880000);
  74         //hwwrite(vortex->mmio, WT_GMODE(1), 0xffffffff);
  75 #endif
  76         hwwrite(vortex->mmio, WT_PARM(wt, 0), 0);
  77         hwwrite(vortex->mmio, WT_PARM(wt, 1), 0);
  78         hwwrite(vortex->mmio, WT_PARM(wt, 2), 0);
  79 
  80         temp = hwread(vortex->mmio, WT_PARM(wt, 3));
  81         dev_dbg(vortex->card->dev, "WT PARM3: %x\n", temp);
  82         //hwwrite(vortex->mmio, WT_PARM(wt, 3), temp);
  83 
  84         hwwrite(vortex->mmio, WT_DELAY(wt, 0), 0);
  85         hwwrite(vortex->mmio, WT_DELAY(wt, 1), 0);
  86         hwwrite(vortex->mmio, WT_DELAY(wt, 2), 0);
  87         hwwrite(vortex->mmio, WT_DELAY(wt, 3), 0);
  88 
  89         dev_dbg(vortex->card->dev, "WT GMODE: %x\n",
  90                 hwread(vortex->mmio, WT_GMODE(wt)));
  91 
  92         hwwrite(vortex->mmio, WT_PARM(wt, 2), 0xffffffff);
  93         hwwrite(vortex->mmio, WT_PARM(wt, 3), 0xcff1c810);
  94 
  95         voice->parm0 = voice->parm1 = 0xcfb23e2f;
  96         hwwrite(vortex->mmio, WT_PARM(wt, 0), voice->parm0);
  97         hwwrite(vortex->mmio, WT_PARM(wt, 1), voice->parm1);
  98         dev_dbg(vortex->card->dev, "WT GMODE 2 : %x\n",
  99                 hwread(vortex->mmio, WT_GMODE(wt)));
 100         return 0;
 101 }
 102 
 103 
 104 static void vortex_wt_connect(vortex_t * vortex, int en)
 105 {
 106         int i, ii, mix;
 107 
 108 #define NR_WTROUTES 6
 109 #ifdef CHIP_AU8830
 110 #define NR_WTBLOCKS 2
 111 #else
 112 #define NR_WTBLOCKS 1
 113 #endif
 114 
 115         for (i = 0; i < NR_WTBLOCKS; i++) {
 116                 for (ii = 0; ii < NR_WTROUTES; ii++) {
 117                         mix =
 118                             vortex_adb_checkinout(vortex,
 119                                                   vortex->fixed_res, en,
 120                                                   VORTEX_RESOURCE_MIXIN);
 121                         vortex->mixwt[(i * NR_WTROUTES) + ii] = mix;
 122 
 123                         vortex_route(vortex, en, 0x11,
 124                                      ADB_WTOUT(i, ii + 0x20), ADB_MIXIN(mix));
 125 
 126                         vortex_connection_mixin_mix(vortex, en, mix,
 127                                                     vortex->mixplayb[ii % 2], 0);
 128                         if (VORTEX_IS_QUAD(vortex))
 129                                 vortex_connection_mixin_mix(vortex, en,
 130                                                             mix,
 131                                                             vortex->mixplayb[2 +
 132                                                                      (ii % 2)], 0);
 133                 }
 134         }
 135         for (i = 0; i < NR_WT; i++) {
 136                 hwwrite(vortex->mmio, WT_RUN(i), 1);
 137         }
 138 }
 139 
 140 /* Read WT Register */
 141 #if 0
 142 static int vortex_wt_GetReg(vortex_t * vortex, char reg, int wt)
 143 {
 144         //int eax, esi;
 145 
 146         if (reg == 4) {
 147                 return hwread(vortex->mmio, WT_PARM(wt, 3));
 148         }
 149         if (reg == 7) {
 150                 return hwread(vortex->mmio, WT_GMODE(wt));
 151         }
 152 
 153         return 0;
 154 }
 155 
 156 /* WT hardware abstraction layer generic register interface. */
 157 static int
 158 vortex_wt_SetReg2(vortex_t * vortex, unsigned char reg, int wt,
 159                   u16 val)
 160 {
 161         /*
 162            int eax, edx;
 163 
 164            if (wt >= NR_WT)  // 0x40 -> NR_WT
 165            return 0;
 166 
 167            if ((reg - 0x20) > 0) {
 168            if ((reg - 0x21) != 0) 
 169            return 0;
 170            eax = ((((b & 0xff) << 0xb) + (edx & 0xff)) << 4) + 0x208; // param 2
 171            } else {
 172            eax = ((((b & 0xff) << 0xb) + (edx & 0xff)) << 4) + 0x20a; // param 3
 173            }
 174            hwwrite(vortex->mmio, eax, c);
 175          */
 176         return 1;
 177 }
 178 
 179 /*public: static void __thiscall CWTHal::SetReg(unsigned char,int,unsigned long) */
 180 #endif
 181 static int
 182 vortex_wt_SetReg(vortex_t * vortex, unsigned char reg, int wt,
 183                  u32 val)
 184 {
 185         int ecx;
 186 
 187         if ((reg == 5) || ((reg >= 7) && (reg <= 10)) || (reg == 0xc)) {
 188                 if (wt >= (NR_WT / NR_WT_PB)) {
 189                         dev_warn(vortex->card->dev,
 190                                  "WT SetReg: bank out of range. reg=0x%x, wt=%d\n",
 191                                  reg, wt);
 192                         return 0;
 193                 }
 194         } else {
 195                 if (wt >= NR_WT) {
 196                         dev_err(vortex->card->dev,
 197                                 "WT SetReg: voice out of range\n");
 198                         return 0;
 199                 }
 200         }
 201         if (reg > 0xc)
 202                 return 0;
 203 
 204         switch (reg) {
 205                 /* Voice specific parameters */
 206         case 0:         /* running */
 207                 /*
 208                 pr_debug( "vortex: WT SetReg(0x%x) = 0x%08x\n",
 209                        WT_RUN(wt), (int)val);
 210                 */
 211                 hwwrite(vortex->mmio, WT_RUN(wt), val);
 212                 return 0xc;
 213         case 1:         /* param 0 */
 214                 /*
 215                 pr_debug( "vortex: WT SetReg(0x%x) = 0x%08x\n",
 216                        WT_PARM(wt,0), (int)val);
 217                 */
 218                 hwwrite(vortex->mmio, WT_PARM(wt, 0), val);
 219                 return 0xc;
 220         case 2:         /* param 1 */
 221                 /*
 222                 pr_debug( "vortex: WT SetReg(0x%x) = 0x%08x\n",
 223                        WT_PARM(wt,1), (int)val);
 224                 */
 225                 hwwrite(vortex->mmio, WT_PARM(wt, 1), val);
 226                 return 0xc;
 227         case 3:         /* param 2 */
 228                 /*
 229                 pr_debug( "vortex: WT SetReg(0x%x) = 0x%08x\n",
 230                        WT_PARM(wt,2), (int)val);
 231                 */
 232                 hwwrite(vortex->mmio, WT_PARM(wt, 2), val);
 233                 return 0xc;
 234         case 4:         /* param 3 */
 235                 /*
 236                 pr_debug( "vortex: WT SetReg(0x%x) = 0x%08x\n",
 237                        WT_PARM(wt,3), (int)val);
 238                 */
 239                 hwwrite(vortex->mmio, WT_PARM(wt, 3), val);
 240                 return 0xc;
 241         case 6:         /* mute */
 242                 /*
 243                 pr_debug( "vortex: WT SetReg(0x%x) = 0x%08x\n",
 244                        WT_MUTE(wt), (int)val);
 245                 */
 246                 hwwrite(vortex->mmio, WT_MUTE(wt), val);
 247                 return 0xc;
 248         case 0xb:
 249                         /* delay */
 250                 /*
 251                 pr_debug( "vortex: WT SetReg(0x%x) = 0x%08x\n",
 252                        WT_DELAY(wt,0), (int)val);
 253                 */
 254                 hwwrite(vortex->mmio, WT_DELAY(wt, 3), val);
 255                 hwwrite(vortex->mmio, WT_DELAY(wt, 2), val);
 256                 hwwrite(vortex->mmio, WT_DELAY(wt, 1), val);
 257                 hwwrite(vortex->mmio, WT_DELAY(wt, 0), val);
 258                 return 0xc;
 259                 /* Global WT block parameters */
 260         case 5:         /* sramp */
 261                 ecx = WT_SRAMP(wt);
 262                 break;
 263         case 8:         /* aramp */
 264                 ecx = WT_ARAMP(wt);
 265                 break;
 266         case 9:         /* mramp */
 267                 ecx = WT_MRAMP(wt);
 268                 break;
 269         case 0xa:               /* ctrl */
 270                 ecx = WT_CTRL(wt);
 271                 break;
 272         case 0xc:               /* ds_reg */
 273                 ecx = WT_DSREG(wt);
 274                 break;
 275         default:
 276                 return 0;
 277         }
 278         /*
 279         pr_debug( "vortex: WT SetReg(0x%x) = 0x%08x\n", ecx, (int)val);
 280         */
 281         hwwrite(vortex->mmio, ecx, val);
 282         return 1;
 283 }
 284 
 285 static void vortex_wt_init(vortex_t * vortex)
 286 {
 287         u32 var4, var8, varc, var10 = 0, edi;
 288 
 289         var10 &= 0xFFFFFFE3;
 290         var10 |= 0x22;
 291         var10 &= 0xFFFFFEBF;
 292         var10 |= 0x80;
 293         var10 |= 0x200;
 294         var10 &= 0xfffffffe;
 295         var10 &= 0xfffffbff;
 296         var10 |= 0x1800;
 297         // var10 = 0x1AA2
 298         var4 = 0x10000000;
 299         varc = 0x00830000;
 300         var8 = 0x00830000;
 301 
 302         /* Init Bank registers. */
 303         for (edi = 0; edi < (NR_WT / NR_WT_PB); edi++) {
 304                 vortex_wt_SetReg(vortex, 0xc, edi, 0);  /* ds_reg */
 305                 vortex_wt_SetReg(vortex, 0xa, edi, var10);      /* ctrl  */
 306                 vortex_wt_SetReg(vortex, 0x9, edi, var4);       /* mramp */
 307                 vortex_wt_SetReg(vortex, 0x8, edi, varc);       /* aramp */
 308                 vortex_wt_SetReg(vortex, 0x5, edi, var8);       /* sramp */
 309         }
 310         /* Init Voice registers. */
 311         for (edi = 0; edi < NR_WT; edi++) {
 312                 vortex_wt_SetReg(vortex, 0x4, edi, 0);  /* param 3 0x20c */
 313                 vortex_wt_SetReg(vortex, 0x3, edi, 0);  /* param 2 0x208 */
 314                 vortex_wt_SetReg(vortex, 0x2, edi, 0);  /* param 1 0x204 */
 315                 vortex_wt_SetReg(vortex, 0x1, edi, 0);  /* param 0 0x200 */
 316                 vortex_wt_SetReg(vortex, 0xb, edi, 0);  /* delay 0x400 - 0x40c */
 317         }
 318         var10 |= 1;
 319         for (edi = 0; edi < (NR_WT / NR_WT_PB); edi++)
 320                 vortex_wt_SetReg(vortex, 0xa, edi, var10);      /* ctrl */
 321 }
 322 
 323 /* Extract of CAdbTopology::SetVolume(struct _ASPVOLUME *) */
 324 #if 0
 325 static void vortex_wt_SetVolume(vortex_t * vortex, int wt, int vol[])
 326 {
 327         wt_voice_t *voice = &(vortex->wt_voice[wt]);
 328         int ecx = vol[1], eax = vol[0];
 329 
 330         /* This is pure guess */
 331         voice->parm0 &= 0xff00ffff;
 332         voice->parm0 |= (vol[0] & 0xff) << 0x10;
 333         voice->parm1 &= 0xff00ffff;
 334         voice->parm1 |= (vol[1] & 0xff) << 0x10;
 335 
 336         /* This is real */
 337         hwwrite(vortex, WT_PARM(wt, 0), voice->parm0);
 338         hwwrite(vortex, WT_PARM(wt, 1), voice->parm0);
 339 
 340         if (voice->this_1D0 & 4) {
 341                 eax >>= 8;
 342                 ecx = eax;
 343                 if (ecx < 0x80)
 344                         ecx = 0x7f;
 345                 voice->parm3 &= 0xFFFFC07F;
 346                 voice->parm3 |= (ecx & 0x7f) << 7;
 347                 voice->parm3 &= 0xFFFFFF80;
 348                 voice->parm3 |= (eax & 0x7f);
 349         } else {
 350                 voice->parm3 &= 0xFFE03FFF;
 351                 voice->parm3 |= (eax & 0xFE00) << 5;
 352         }
 353 
 354         hwwrite(vortex, WT_PARM(wt, 3), voice->parm3);
 355 }
 356 
 357 /* Extract of CAdbTopology::SetFrequency(unsigned long arg_0) */
 358 static void vortex_wt_SetFrequency(vortex_t * vortex, int wt, unsigned int sr)
 359 {
 360         wt_voice_t *voice = &(vortex->wt_voice[wt]);
 361         u32 eax, edx;
 362 
 363         //FIXME: 64 bit operation.
 364         eax = ((sr << 0xf) * 0x57619F1) & 0xffffffff;
 365         edx = (((sr << 0xf) * 0x57619F1)) >> 0x20;
 366 
 367         edx >>= 0xa;
 368         edx <<= 1;
 369         if (edx) {
 370                 if (edx & 0x0FFF80000)
 371                         eax = 0x7fff;
 372                 else {
 373                         edx <<= 0xd;
 374                         eax = 7;
 375                         while ((edx & 0x80000000) == 0) {
 376                                 edx <<= 1;
 377                                 eax--;
 378                                 if (eax == 0)
 379                                         break;
 380                         }
 381                         if (eax)
 382                                 edx <<= 1;
 383                         eax <<= 0xc;
 384                         edx >>= 0x14;
 385                         eax |= edx;
 386                 }
 387         } else
 388                 eax = 0;
 389         voice->parm0 &= 0xffff0001;
 390         voice->parm0 |= (eax & 0x7fff) << 1;
 391         voice->parm1 = voice->parm0 | 1;
 392         // Wt: this_1D4
 393         //AuWt::WriteReg((ulong)(this_1DC<<4)+0x200, (ulong)this_1E4);
 394         //AuWt::WriteReg((ulong)(this_1DC<<4)+0x204, (ulong)this_1E8);
 395         hwwrite(vortex->mmio, WT_PARM(wt, 0), voice->parm0);
 396         hwwrite(vortex->mmio, WT_PARM(wt, 1), voice->parm1);
 397 }
 398 #endif
 399 
 400 /* End of File */

/* [<][>][^][v][top][bottom][index][help] */