linux/sound/oss/dmasound/dmasound_atari.c
<<
>>
Prefs
   1/*
   2 *  linux/sound/oss/dmasound/dmasound_atari.c
   3 *
   4 *  Atari TT and Falcon DMA Sound Driver
   5 *
   6 *  See linux/sound/oss/dmasound/dmasound_core.c for copyright and credits
   7 *  prior to 28/01/2001
   8 *
   9 *  28/01/2001 [0.1] Iain Sandoe
  10 *                   - added versioning
  11 *                   - put in and populated the hardware_afmts field.
  12 *             [0.2] - put in SNDCTL_DSP_GETCAPS value.
  13 *  01/02/2001 [0.3] - put in default hard/soft settings.
  14 */
  15
  16
  17#include <linux/module.h>
  18#include <linux/kernel.h>
  19#include <linux/init.h>
  20#include <linux/soundcard.h>
  21#include <linux/mm.h>
  22#include <linux/spinlock.h>
  23#include <linux/interrupt.h>
  24
  25#include <linux/uaccess.h>
  26#include <asm/atariints.h>
  27#include <asm/atari_stram.h>
  28
  29#include "dmasound.h"
  30
  31#define DMASOUND_ATARI_REVISION 0
  32#define DMASOUND_ATARI_EDITION 3
  33
  34extern void atari_microwire_cmd(int cmd);
  35
  36static int is_falcon;
  37static int write_sq_ignore_int; /* ++TeSche: used for Falcon */
  38
  39static int expand_bal;  /* Balance factor for expanding (not volume!) */
  40static int expand_data; /* Data for expanding */
  41
  42
  43/*** Translations ************************************************************/
  44
  45
  46/* ++TeSche: radically changed for new expanding purposes...
  47 *
  48 * These two routines now deal with copying/expanding/translating the samples
  49 * from user space into our buffer at the right frequency. They take care about
  50 * how much data there's actually to read, how much buffer space there is and
  51 * to convert samples into the right frequency/encoding. They will only work on
  52 * complete samples so it may happen they leave some bytes in the input stream
  53 * if the user didn't write a multiple of the current sample size. They both
  54 * return the number of bytes they've used from both streams so you may detect
  55 * such a situation. Luckily all programs should be able to cope with that.
  56 *
  57 * I think I've optimized anything as far as one can do in plain C, all
  58 * variables should fit in registers and the loops are really short. There's
  59 * one loop for every possible situation. Writing a more generalized and thus
  60 * parameterized loop would only produce slower code. Feel free to optimize
  61 * this in assembler if you like. :)
  62 *
  63 * I think these routines belong here because they're not yet really hardware
  64 * independent, especially the fact that the Falcon can play 16bit samples
  65 * only in stereo is hardcoded in both of them!
  66 *
  67 * ++geert: split in even more functions (one per format)
  68 */
  69
  70static ssize_t ata_ct_law(const u_char __user *userPtr, size_t userCount,
  71                          u_char frame[], ssize_t *frameUsed,
  72                          ssize_t frameLeft);
  73static ssize_t ata_ct_s8(const u_char __user *userPtr, size_t userCount,
  74                         u_char frame[], ssize_t *frameUsed,
  75                         ssize_t frameLeft);
  76static ssize_t ata_ct_u8(const u_char __user *userPtr, size_t userCount,
  77                         u_char frame[], ssize_t *frameUsed,
  78                         ssize_t frameLeft);
  79static ssize_t ata_ct_s16be(const u_char __user *userPtr, size_t userCount,
  80                            u_char frame[], ssize_t *frameUsed,
  81                            ssize_t frameLeft);
  82static ssize_t ata_ct_u16be(const u_char __user *userPtr, size_t userCount,
  83                            u_char frame[], ssize_t *frameUsed,
  84                            ssize_t frameLeft);
  85static ssize_t ata_ct_s16le(const u_char __user *userPtr, size_t userCount,
  86                            u_char frame[], ssize_t *frameUsed,
  87                            ssize_t frameLeft);
  88static ssize_t ata_ct_u16le(const u_char __user *userPtr, size_t userCount,
  89                            u_char frame[], ssize_t *frameUsed,
  90                            ssize_t frameLeft);
  91static ssize_t ata_ctx_law(const u_char __user *userPtr, size_t userCount,
  92                           u_char frame[], ssize_t *frameUsed,
  93                           ssize_t frameLeft);
  94static ssize_t ata_ctx_s8(const u_char __user *userPtr, size_t userCount,
  95                          u_char frame[], ssize_t *frameUsed,
  96                          ssize_t frameLeft);
  97static ssize_t ata_ctx_u8(const u_char __user *userPtr, size_t userCount,
  98                          u_char frame[], ssize_t *frameUsed,
  99                          ssize_t frameLeft);
 100static ssize_t ata_ctx_s16be(const u_char __user *userPtr, size_t userCount,
 101                             u_char frame[], ssize_t *frameUsed,
 102                             ssize_t frameLeft);
 103static ssize_t ata_ctx_u16be(const u_char __user *userPtr, size_t userCount,
 104                             u_char frame[], ssize_t *frameUsed,
 105                             ssize_t frameLeft);
 106static ssize_t ata_ctx_s16le(const u_char __user *userPtr, size_t userCount,
 107                             u_char frame[], ssize_t *frameUsed,
 108                             ssize_t frameLeft);
 109static ssize_t ata_ctx_u16le(const u_char __user *userPtr, size_t userCount,
 110                             u_char frame[], ssize_t *frameUsed,
 111                             ssize_t frameLeft);
 112
 113
 114/*** Low level stuff *********************************************************/
 115
 116
 117static void *AtaAlloc(unsigned int size, gfp_t flags);
 118static void AtaFree(void *, unsigned int size);
 119static int AtaIrqInit(void);
 120#ifdef MODULE
 121static void AtaIrqCleanUp(void);
 122#endif /* MODULE */
 123static int AtaSetBass(int bass);
 124static int AtaSetTreble(int treble);
 125static void TTSilence(void);
 126static void TTInit(void);
 127static int TTSetFormat(int format);
 128static int TTSetVolume(int volume);
 129static int TTSetGain(int gain);
 130static void FalconSilence(void);
 131static void FalconInit(void);
 132static int FalconSetFormat(int format);
 133static int FalconSetVolume(int volume);
 134static void AtaPlayNextFrame(int index);
 135static void AtaPlay(void);
 136static irqreturn_t AtaInterrupt(int irq, void *dummy);
 137
 138/*** Mid level stuff *********************************************************/
 139
 140static void TTMixerInit(void);
 141static void FalconMixerInit(void);
 142static int AtaMixerIoctl(u_int cmd, u_long arg);
 143static int TTMixerIoctl(u_int cmd, u_long arg);
 144static int FalconMixerIoctl(u_int cmd, u_long arg);
 145static int AtaWriteSqSetup(void);
 146static int AtaSqOpen(fmode_t mode);
 147static int TTStateInfo(char *buffer, size_t space);
 148static int FalconStateInfo(char *buffer, size_t space);
 149
 150
 151/*** Translations ************************************************************/
 152
 153
 154static ssize_t ata_ct_law(const u_char __user *userPtr, size_t userCount,
 155                          u_char frame[], ssize_t *frameUsed,
 156                          ssize_t frameLeft)
 157{
 158        char *table = dmasound.soft.format == AFMT_MU_LAW ? dmasound_ulaw2dma8
 159                                                          : dmasound_alaw2dma8;
 160        ssize_t count, used;
 161        u_char *p = &frame[*frameUsed];
 162
 163        count = min_t(unsigned long, userCount, frameLeft);
 164        if (dmasound.soft.stereo)
 165                count &= ~1;
 166        used = count;
 167        while (count > 0) {
 168                u_char data;
 169                if (get_user(data, userPtr++))
 170                        return -EFAULT;
 171                *p++ = table[data];
 172                count--;
 173        }
 174        *frameUsed += used;
 175        return used;
 176}
 177
 178
 179static ssize_t ata_ct_s8(const u_char __user *userPtr, size_t userCount,
 180                         u_char frame[], ssize_t *frameUsed,
 181                         ssize_t frameLeft)
 182{
 183        ssize_t count, used;
 184        void *p = &frame[*frameUsed];
 185
 186        count = min_t(unsigned long, userCount, frameLeft);
 187        if (dmasound.soft.stereo)
 188                count &= ~1;
 189        used = count;
 190        if (copy_from_user(p, userPtr, count))
 191                return -EFAULT;
 192        *frameUsed += used;
 193        return used;
 194}
 195
 196
 197static ssize_t ata_ct_u8(const u_char __user *userPtr, size_t userCount,
 198                         u_char frame[], ssize_t *frameUsed,
 199                         ssize_t frameLeft)
 200{
 201        ssize_t count, used;
 202
 203        if (!dmasound.soft.stereo) {
 204                u_char *p = &frame[*frameUsed];
 205                count = min_t(unsigned long, userCount, frameLeft);
 206                used = count;
 207                while (count > 0) {
 208                        u_char data;
 209                        if (get_user(data, userPtr++))
 210                                return -EFAULT;
 211                        *p++ = data ^ 0x80;
 212                        count--;
 213                }
 214        } else {
 215                u_short *p = (u_short *)&frame[*frameUsed];
 216                count = min_t(unsigned long, userCount, frameLeft)>>1;
 217                used = count*2;
 218                while (count > 0) {
 219                        u_short data;
 220                        if (get_user(data, (u_short __user *)userPtr))
 221                                return -EFAULT;
 222                        userPtr += 2;
 223                        *p++ = data ^ 0x8080;
 224                        count--;
 225                }
 226        }
 227        *frameUsed += used;
 228        return used;
 229}
 230
 231
 232static ssize_t ata_ct_s16be(const u_char __user *userPtr, size_t userCount,
 233                            u_char frame[], ssize_t *frameUsed,
 234                            ssize_t frameLeft)
 235{
 236        ssize_t count, used;
 237
 238        if (!dmasound.soft.stereo) {
 239                u_short *p = (u_short *)&frame[*frameUsed];
 240                count = min_t(unsigned long, userCount, frameLeft)>>1;
 241                used = count*2;
 242                while (count > 0) {
 243                        u_short data;
 244                        if (get_user(data, (u_short __user *)userPtr))
 245                                return -EFAULT;
 246                        userPtr += 2;
 247                        *p++ = data;
 248                        *p++ = data;
 249                        count--;
 250                }
 251                *frameUsed += used*2;
 252        } else {
 253                void *p = (u_short *)&frame[*frameUsed];
 254                count = min_t(unsigned long, userCount, frameLeft) & ~3;
 255                used = count;
 256                if (copy_from_user(p, userPtr, count))
 257                        return -EFAULT;
 258                *frameUsed += used;
 259        }
 260        return used;
 261}
 262
 263
 264static ssize_t ata_ct_u16be(const u_char __user *userPtr, size_t userCount,
 265                            u_char frame[], ssize_t *frameUsed,
 266                            ssize_t frameLeft)
 267{
 268        ssize_t count, used;
 269
 270        if (!dmasound.soft.stereo) {
 271                u_short *p = (u_short *)&frame[*frameUsed];
 272                count = min_t(unsigned long, userCount, frameLeft)>>1;
 273                used = count*2;
 274                while (count > 0) {
 275                        u_short data;
 276                        if (get_user(data, (u_short __user *)userPtr))
 277                                return -EFAULT;
 278                        userPtr += 2;
 279                        data ^= 0x8000;
 280                        *p++ = data;
 281                        *p++ = data;
 282                        count--;
 283                }
 284                *frameUsed += used*2;
 285        } else {
 286                u_long *p = (u_long *)&frame[*frameUsed];
 287                count = min_t(unsigned long, userCount, frameLeft)>>2;
 288                used = count*4;
 289                while (count > 0) {
 290                        u_int data;
 291                        if (get_user(data, (u_int __user *)userPtr))
 292                                return -EFAULT;
 293                        userPtr += 4;
 294                        *p++ = data ^ 0x80008000;
 295                        count--;
 296                }
 297                *frameUsed += used;
 298        }
 299        return used;
 300}
 301
 302
 303static ssize_t ata_ct_s16le(const u_char __user *userPtr, size_t userCount,
 304                            u_char frame[], ssize_t *frameUsed,
 305                            ssize_t frameLeft)
 306{
 307        ssize_t count, used;
 308
 309        count = frameLeft;
 310        if (!dmasound.soft.stereo) {
 311                u_short *p = (u_short *)&frame[*frameUsed];
 312                count = min_t(unsigned long, userCount, frameLeft)>>1;
 313                used = count*2;
 314                while (count > 0) {
 315                        u_short data;
 316                        if (get_user(data, (u_short __user *)userPtr))
 317                                return -EFAULT;
 318                        userPtr += 2;
 319                        data = le2be16(data);
 320                        *p++ = data;
 321                        *p++ = data;
 322                        count--;
 323                }
 324                *frameUsed += used*2;
 325        } else {
 326                u_long *p = (u_long *)&frame[*frameUsed];
 327                count = min_t(unsigned long, userCount, frameLeft)>>2;
 328                used = count*4;
 329                while (count > 0) {
 330                        u_long data;
 331                        if (get_user(data, (u_int __user *)userPtr))
 332                                return -EFAULT;
 333                        userPtr += 4;
 334                        data = le2be16dbl(data);
 335                        *p++ = data;
 336                        count--;
 337                }
 338                *frameUsed += used;
 339        }
 340        return used;
 341}
 342
 343
 344static ssize_t ata_ct_u16le(const u_char __user *userPtr, size_t userCount,
 345                            u_char frame[], ssize_t *frameUsed,
 346                            ssize_t frameLeft)
 347{
 348        ssize_t count, used;
 349
 350        count = frameLeft;
 351        if (!dmasound.soft.stereo) {
 352                u_short *p = (u_short *)&frame[*frameUsed];
 353                count = min_t(unsigned long, userCount, frameLeft)>>1;
 354                used = count*2;
 355                while (count > 0) {
 356                        u_short data;
 357                        if (get_user(data, (u_short __user *)userPtr))
 358                                return -EFAULT;
 359                        userPtr += 2;
 360                        data = le2be16(data) ^ 0x8000;
 361                        *p++ = data;
 362                        *p++ = data;
 363                }
 364                *frameUsed += used*2;
 365        } else {
 366                u_long *p = (u_long *)&frame[*frameUsed];
 367                count = min_t(unsigned long, userCount, frameLeft)>>2;
 368                used = count;
 369                while (count > 0) {
 370                        u_long data;
 371                        if (get_user(data, (u_int __user *)userPtr))
 372                                return -EFAULT;
 373                        userPtr += 4;
 374                        data = le2be16dbl(data) ^ 0x80008000;
 375                        *p++ = data;
 376                        count--;
 377                }
 378                *frameUsed += used;
 379        }
 380        return used;
 381}
 382
 383
 384static ssize_t ata_ctx_law(const u_char __user *userPtr, size_t userCount,
 385                           u_char frame[], ssize_t *frameUsed,
 386                           ssize_t frameLeft)
 387{
 388        char *table = dmasound.soft.format == AFMT_MU_LAW ? dmasound_ulaw2dma8
 389                                                          : dmasound_alaw2dma8;
 390        /* this should help gcc to stuff everything into registers */
 391        long bal = expand_bal;
 392        long hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;
 393        ssize_t used, usedf;
 394
 395        used = userCount;
 396        usedf = frameLeft;
 397        if (!dmasound.soft.stereo) {
 398                u_char *p = &frame[*frameUsed];
 399                u_char data = expand_data;
 400                while (frameLeft) {
 401                        u_char c;
 402                        if (bal < 0) {
 403                                if (!userCount)
 404                                        break;
 405                                if (get_user(c, userPtr++))
 406                                        return -EFAULT;
 407                                data = table[c];
 408                                userCount--;
 409                                bal += hSpeed;
 410                        }
 411                        *p++ = data;
 412                        frameLeft--;
 413                        bal -= sSpeed;
 414                }
 415                expand_data = data;
 416        } else {
 417                u_short *p = (u_short *)&frame[*frameUsed];
 418                u_short data = expand_data;
 419                while (frameLeft >= 2) {
 420                        u_char c;
 421                        if (bal < 0) {
 422                                if (userCount < 2)
 423                                        break;
 424                                if (get_user(c, userPtr++))
 425                                        return -EFAULT;
 426                                data = table[c] << 8;
 427                                if (get_user(c, userPtr++))
 428                                        return -EFAULT;
 429                                data |= table[c];
 430                                userCount -= 2;
 431                                bal += hSpeed;
 432                        }
 433                        *p++ = data;
 434                        frameLeft -= 2;
 435                        bal -= sSpeed;
 436                }
 437                expand_data = data;
 438        }
 439        expand_bal = bal;
 440        used -= userCount;
 441        *frameUsed += usedf-frameLeft;
 442        return used;
 443}
 444
 445
 446static ssize_t ata_ctx_s8(const u_char __user *userPtr, size_t userCount,
 447                          u_char frame[], ssize_t *frameUsed,
 448                          ssize_t frameLeft)
 449{
 450        /* this should help gcc to stuff everything into registers */
 451        long bal = expand_bal;
 452        long hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;
 453        ssize_t used, usedf;
 454
 455        used = userCount;
 456        usedf = frameLeft;
 457        if (!dmasound.soft.stereo) {
 458                u_char *p = &frame[*frameUsed];
 459                u_char data = expand_data;
 460                while (frameLeft) {
 461                        if (bal < 0) {
 462                                if (!userCount)
 463                                        break;
 464                                if (get_user(data, userPtr++))
 465                                        return -EFAULT;
 466                                userCount--;
 467                                bal += hSpeed;
 468                        }
 469                        *p++ = data;
 470                        frameLeft--;
 471                        bal -= sSpeed;
 472                }
 473                expand_data = data;
 474        } else {
 475                u_short *p = (u_short *)&frame[*frameUsed];
 476                u_short data = expand_data;
 477                while (frameLeft >= 2) {
 478                        if (bal < 0) {
 479                                if (userCount < 2)
 480                                        break;
 481                                if (get_user(data, (u_short __user *)userPtr))
 482                                        return -EFAULT;
 483                                userPtr += 2;
 484                                userCount -= 2;
 485                                bal += hSpeed;
 486                        }
 487                        *p++ = data;
 488                        frameLeft -= 2;
 489                        bal -= sSpeed;
 490                }
 491                expand_data = data;
 492        }
 493        expand_bal = bal;
 494        used -= userCount;
 495        *frameUsed += usedf-frameLeft;
 496        return used;
 497}
 498
 499
 500static ssize_t ata_ctx_u8(const u_char __user *userPtr, size_t userCount,
 501                          u_char frame[], ssize_t *frameUsed,
 502                          ssize_t frameLeft)
 503{
 504        /* this should help gcc to stuff everything into registers */
 505        long bal = expand_bal;
 506        long hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;
 507        ssize_t used, usedf;
 508
 509        used = userCount;
 510        usedf = frameLeft;
 511        if (!dmasound.soft.stereo) {
 512                u_char *p = &frame[*frameUsed];
 513                u_char data = expand_data;
 514                while (frameLeft) {
 515                        if (bal < 0) {
 516                                if (!userCount)
 517                                        break;
 518                                if (get_user(data, userPtr++))
 519                                        return -EFAULT;
 520                                data ^= 0x80;
 521                                userCount--;
 522                                bal += hSpeed;
 523                        }
 524                        *p++ = data;
 525                        frameLeft--;
 526                        bal -= sSpeed;
 527                }
 528                expand_data = data;
 529        } else {
 530                u_short *p = (u_short *)&frame[*frameUsed];
 531                u_short data = expand_data;
 532                while (frameLeft >= 2) {
 533                        if (bal < 0) {
 534                                if (userCount < 2)
 535                                        break;
 536                                if (get_user(data, (u_short __user *)userPtr))
 537                                        return -EFAULT;
 538                                userPtr += 2;
 539                                data ^= 0x8080;
 540                                userCount -= 2;
 541                                bal += hSpeed;
 542                        }
 543                        *p++ = data;
 544                        frameLeft -= 2;
 545                        bal -= sSpeed;
 546                }
 547                expand_data = data;
 548        }
 549        expand_bal = bal;
 550        used -= userCount;
 551        *frameUsed += usedf-frameLeft;
 552        return used;
 553}
 554
 555
 556static ssize_t ata_ctx_s16be(const u_char __user *userPtr, size_t userCount,
 557                             u_char frame[], ssize_t *frameUsed,
 558                             ssize_t frameLeft)
 559{
 560        /* this should help gcc to stuff everything into registers */
 561        long bal = expand_bal;
 562        long hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;
 563        ssize_t used, usedf;
 564
 565        used = userCount;
 566        usedf = frameLeft;
 567        if (!dmasound.soft.stereo) {
 568                u_short *p = (u_short *)&frame[*frameUsed];
 569                u_short data = expand_data;
 570                while (frameLeft >= 4) {
 571                        if (bal < 0) {
 572                                if (userCount < 2)
 573                                        break;
 574                                if (get_user(data, (u_short __user *)userPtr))
 575                                        return -EFAULT;
 576                                userPtr += 2;
 577                                userCount -= 2;
 578                                bal += hSpeed;
 579                        }
 580                        *p++ = data;
 581                        *p++ = data;
 582                        frameLeft -= 4;
 583                        bal -= sSpeed;
 584                }
 585                expand_data = data;
 586        } else {
 587                u_long *p = (u_long *)&frame[*frameUsed];
 588                u_long data = expand_data;
 589                while (frameLeft >= 4) {
 590                        if (bal < 0) {
 591                                if (userCount < 4)
 592                                        break;
 593                                if (get_user(data, (u_int __user *)userPtr))
 594                                        return -EFAULT;
 595                                userPtr += 4;
 596                                userCount -= 4;
 597                                bal += hSpeed;
 598                        }
 599                        *p++ = data;
 600                        frameLeft -= 4;
 601                        bal -= sSpeed;
 602                }
 603                expand_data = data;
 604        }
 605        expand_bal = bal;
 606        used -= userCount;
 607        *frameUsed += usedf-frameLeft;
 608        return used;
 609}
 610
 611
 612static ssize_t ata_ctx_u16be(const u_char __user *userPtr, size_t userCount,
 613                             u_char frame[], ssize_t *frameUsed,
 614                             ssize_t frameLeft)
 615{
 616        /* this should help gcc to stuff everything into registers */
 617        long bal = expand_bal;
 618        long hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;
 619        ssize_t used, usedf;
 620
 621        used = userCount;
 622        usedf = frameLeft;
 623        if (!dmasound.soft.stereo) {
 624                u_short *p = (u_short *)&frame[*frameUsed];
 625                u_short data = expand_data;
 626                while (frameLeft >= 4) {
 627                        if (bal < 0) {
 628                                if (userCount < 2)
 629                                        break;
 630                                if (get_user(data, (u_short __user *)userPtr))
 631                                        return -EFAULT;
 632                                userPtr += 2;
 633                                data ^= 0x8000;
 634                                userCount -= 2;
 635                                bal += hSpeed;
 636                        }
 637                        *p++ = data;
 638                        *p++ = data;
 639                        frameLeft -= 4;
 640                        bal -= sSpeed;
 641                }
 642                expand_data = data;
 643        } else {
 644                u_long *p = (u_long *)&frame[*frameUsed];
 645                u_long data = expand_data;
 646                while (frameLeft >= 4) {
 647                        if (bal < 0) {
 648                                if (userCount < 4)
 649                                        break;
 650                                if (get_user(data, (u_int __user *)userPtr))
 651                                        return -EFAULT;
 652                                userPtr += 4;
 653                                data ^= 0x80008000;
 654                                userCount -= 4;
 655                                bal += hSpeed;
 656                        }
 657                        *p++ = data;
 658                        frameLeft -= 4;
 659                        bal -= sSpeed;
 660                }
 661                expand_data = data;
 662        }
 663        expand_bal = bal;
 664        used -= userCount;
 665        *frameUsed += usedf-frameLeft;
 666        return used;
 667}
 668
 669
 670static ssize_t ata_ctx_s16le(const u_char __user *userPtr, size_t userCount,
 671                             u_char frame[], ssize_t *frameUsed,
 672                             ssize_t frameLeft)
 673{
 674        /* this should help gcc to stuff everything into registers */
 675        long bal = expand_bal;
 676        long hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;
 677        ssize_t used, usedf;
 678
 679        used = userCount;
 680        usedf = frameLeft;
 681        if (!dmasound.soft.stereo) {
 682                u_short *p = (u_short *)&frame[*frameUsed];
 683                u_short data = expand_data;
 684                while (frameLeft >= 4) {
 685                        if (bal < 0) {
 686                                if (userCount < 2)
 687                                        break;
 688                                if (get_user(data, (u_short __user *)userPtr))
 689                                        return -EFAULT;
 690                                userPtr += 2;
 691                                data = le2be16(data);
 692                                userCount -= 2;
 693                                bal += hSpeed;
 694                        }
 695                        *p++ = data;
 696                        *p++ = data;
 697                        frameLeft -= 4;
 698                        bal -= sSpeed;
 699                }
 700                expand_data = data;
 701        } else {
 702                u_long *p = (u_long *)&frame[*frameUsed];
 703                u_long data = expand_data;
 704                while (frameLeft >= 4) {
 705                        if (bal < 0) {
 706                                if (userCount < 4)
 707                                        break;
 708                                if (get_user(data, (u_int __user *)userPtr))
 709                                        return -EFAULT;
 710                                userPtr += 4;
 711                                data = le2be16dbl(data);
 712                                userCount -= 4;
 713                                bal += hSpeed;
 714                        }
 715                        *p++ = data;
 716                        frameLeft -= 4;
 717                        bal -= sSpeed;
 718                }
 719                expand_data = data;
 720        }
 721        expand_bal = bal;
 722        used -= userCount;
 723        *frameUsed += usedf-frameLeft;
 724        return used;
 725}
 726
 727
 728static ssize_t ata_ctx_u16le(const u_char __user *userPtr, size_t userCount,
 729                             u_char frame[], ssize_t *frameUsed,
 730                             ssize_t frameLeft)
 731{
 732        /* this should help gcc to stuff everything into registers */
 733        long bal = expand_bal;
 734        long hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;
 735        ssize_t used, usedf;
 736
 737        used = userCount;
 738        usedf = frameLeft;
 739        if (!dmasound.soft.stereo) {
 740                u_short *p = (u_short *)&frame[*frameUsed];
 741                u_short data = expand_data;
 742                while (frameLeft >= 4) {
 743                        if (bal < 0) {
 744                                if (userCount < 2)
 745                                        break;
 746                                if (get_user(data, (u_short __user *)userPtr))
 747                                        return -EFAULT;
 748                                userPtr += 2;
 749                                data = le2be16(data) ^ 0x8000;
 750                                userCount -= 2;
 751                                bal += hSpeed;
 752                        }
 753                        *p++ = data;
 754                        *p++ = data;
 755                        frameLeft -= 4;
 756                        bal -= sSpeed;
 757                }
 758                expand_data = data;
 759        } else {
 760                u_long *p = (u_long *)&frame[*frameUsed];
 761                u_long data = expand_data;
 762                while (frameLeft >= 4) {
 763                        if (bal < 0) {
 764                                if (userCount < 4)
 765                                        break;
 766                                if (get_user(data, (u_int __user *)userPtr))
 767                                        return -EFAULT;
 768                                userPtr += 4;
 769                                data = le2be16dbl(data) ^ 0x80008000;
 770                                userCount -= 4;
 771                                bal += hSpeed;
 772                        }
 773                        *p++ = data;
 774                        frameLeft -= 4;
 775                        bal -= sSpeed;
 776                }
 777                expand_data = data;
 778        }
 779        expand_bal = bal;
 780        used -= userCount;
 781        *frameUsed += usedf-frameLeft;
 782        return used;
 783}
 784
 785
 786static TRANS transTTNormal = {
 787        .ct_ulaw        = ata_ct_law,
 788        .ct_alaw        = ata_ct_law,
 789        .ct_s8          = ata_ct_s8,
 790        .ct_u8          = ata_ct_u8,
 791};
 792
 793static TRANS transTTExpanding = {
 794        .ct_ulaw        = ata_ctx_law,
 795        .ct_alaw        = ata_ctx_law,
 796        .ct_s8          = ata_ctx_s8,
 797        .ct_u8          = ata_ctx_u8,
 798};
 799
 800static TRANS transFalconNormal = {
 801        .ct_ulaw        = ata_ct_law,
 802        .ct_alaw        = ata_ct_law,
 803        .ct_s8          = ata_ct_s8,
 804        .ct_u8          = ata_ct_u8,
 805        .ct_s16be       = ata_ct_s16be,
 806        .ct_u16be       = ata_ct_u16be,
 807        .ct_s16le       = ata_ct_s16le,
 808        .ct_u16le       = ata_ct_u16le
 809};
 810
 811static TRANS transFalconExpanding = {
 812        .ct_ulaw        = ata_ctx_law,
 813        .ct_alaw        = ata_ctx_law,
 814        .ct_s8          = ata_ctx_s8,
 815        .ct_u8          = ata_ctx_u8,
 816        .ct_s16be       = ata_ctx_s16be,
 817        .ct_u16be       = ata_ctx_u16be,
 818        .ct_s16le       = ata_ctx_s16le,
 819        .ct_u16le       = ata_ctx_u16le,
 820};
 821
 822
 823/*** Low level stuff *********************************************************/
 824
 825
 826
 827/*
 828 * Atari (TT/Falcon)
 829 */
 830
 831static void *AtaAlloc(unsigned int size, gfp_t flags)
 832{
 833        return atari_stram_alloc(size, "dmasound");
 834}
 835
 836static void AtaFree(void *obj, unsigned int size)
 837{
 838        atari_stram_free( obj );
 839}
 840
 841static int __init AtaIrqInit(void)
 842{
 843        /* Set up timer A. Timer A
 844           will receive a signal upon end of playing from the sound
 845           hardware. Furthermore Timer A is able to count events
 846           and will cause an interrupt after a programmed number
 847           of events. So all we need to keep the music playing is
 848           to provide the sound hardware with new data upon
 849           an interrupt from timer A. */
 850        st_mfp.tim_ct_a = 0;    /* ++roman: Stop timer before programming! */
 851        st_mfp.tim_dt_a = 1;    /* Cause interrupt after first event. */
 852        st_mfp.tim_ct_a = 8;    /* Turn on event counting. */
 853        /* Register interrupt handler. */
 854        if (request_irq(IRQ_MFP_TIMA, AtaInterrupt, 0, "DMA sound",
 855                        AtaInterrupt))
 856                return 0;
 857        st_mfp.int_en_a |= 0x20;        /* Turn interrupt on. */
 858        st_mfp.int_mk_a |= 0x20;
 859        return 1;
 860}
 861
 862#ifdef MODULE
 863static void AtaIrqCleanUp(void)
 864{
 865        st_mfp.tim_ct_a = 0;            /* stop timer */
 866        st_mfp.int_en_a &= ~0x20;       /* turn interrupt off */
 867        free_irq(IRQ_MFP_TIMA, AtaInterrupt);
 868}
 869#endif /* MODULE */
 870
 871
 872#define TONE_VOXWARE_TO_DB(v) \
 873        (((v) < 0) ? -12 : ((v) > 100) ? 12 : ((v) - 50) * 6 / 25)
 874#define TONE_DB_TO_VOXWARE(v) (((v) * 25 + ((v) > 0 ? 5 : -5)) / 6 + 50)
 875
 876
 877static int AtaSetBass(int bass)
 878{
 879        dmasound.bass = TONE_VOXWARE_TO_DB(bass);
 880        atari_microwire_cmd(MW_LM1992_BASS(dmasound.bass));
 881        return TONE_DB_TO_VOXWARE(dmasound.bass);
 882}
 883
 884
 885static int AtaSetTreble(int treble)
 886{
 887        dmasound.treble = TONE_VOXWARE_TO_DB(treble);
 888        atari_microwire_cmd(MW_LM1992_TREBLE(dmasound.treble));
 889        return TONE_DB_TO_VOXWARE(dmasound.treble);
 890}
 891
 892
 893
 894/*
 895 * TT
 896 */
 897
 898
 899static void TTSilence(void)
 900{
 901        tt_dmasnd.ctrl = DMASND_CTRL_OFF;
 902        atari_microwire_cmd(MW_LM1992_PSG_HIGH); /* mix in PSG signal 1:1 */
 903}
 904
 905
 906static void TTInit(void)
 907{
 908        int mode, i, idx;
 909        const int freq[4] = {50066, 25033, 12517, 6258};
 910
 911        /* search a frequency that fits into the allowed error range */
 912
 913        idx = -1;
 914        for (i = 0; i < ARRAY_SIZE(freq); i++)
 915                /* this isn't as much useful for a TT than for a Falcon, but
 916                 * then it doesn't hurt very much to implement it for a TT too.
 917                 */
 918                if ((100 * abs(dmasound.soft.speed - freq[i]) / freq[i]) < catchRadius)
 919                        idx = i;
 920        if (idx > -1) {
 921                dmasound.soft.speed = freq[idx];
 922                dmasound.trans_write = &transTTNormal;
 923        } else
 924                dmasound.trans_write = &transTTExpanding;
 925
 926        TTSilence();
 927        dmasound.hard = dmasound.soft;
 928
 929        if (dmasound.hard.speed > 50066) {
 930                /* we would need to squeeze the sound, but we won't do that */
 931                dmasound.hard.speed = 50066;
 932                mode = DMASND_MODE_50KHZ;
 933                dmasound.trans_write = &transTTNormal;
 934        } else if (dmasound.hard.speed > 25033) {
 935                dmasound.hard.speed = 50066;
 936                mode = DMASND_MODE_50KHZ;
 937        } else if (dmasound.hard.speed > 12517) {
 938                dmasound.hard.speed = 25033;
 939                mode = DMASND_MODE_25KHZ;
 940        } else if (dmasound.hard.speed > 6258) {
 941                dmasound.hard.speed = 12517;
 942                mode = DMASND_MODE_12KHZ;
 943        } else {
 944                dmasound.hard.speed = 6258;
 945                mode = DMASND_MODE_6KHZ;
 946        }
 947
 948        tt_dmasnd.mode = (dmasound.hard.stereo ?
 949                          DMASND_MODE_STEREO : DMASND_MODE_MONO) |
 950                DMASND_MODE_8BIT | mode;
 951
 952        expand_bal = -dmasound.soft.speed;
 953}
 954
 955
 956static int TTSetFormat(int format)
 957{
 958        /* TT sound DMA supports only 8bit modes */
 959
 960        switch (format) {
 961        case AFMT_QUERY:
 962                return dmasound.soft.format;
 963        case AFMT_MU_LAW:
 964        case AFMT_A_LAW:
 965        case AFMT_S8:
 966        case AFMT_U8:
 967                break;
 968        default:
 969                format = AFMT_S8;
 970        }
 971
 972        dmasound.soft.format = format;
 973        dmasound.soft.size = 8;
 974        if (dmasound.minDev == SND_DEV_DSP) {
 975                dmasound.dsp.format = format;
 976                dmasound.dsp.size = 8;
 977        }
 978        TTInit();
 979
 980        return format;
 981}
 982
 983
 984#define VOLUME_VOXWARE_TO_DB(v) \
 985        (((v) < 0) ? -40 : ((v) > 100) ? 0 : ((v) * 2) / 5 - 40)
 986#define VOLUME_DB_TO_VOXWARE(v) ((((v) + 40) * 5 + 1) / 2)
 987
 988
 989static int TTSetVolume(int volume)
 990{
 991        dmasound.volume_left = VOLUME_VOXWARE_TO_DB(volume & 0xff);
 992        atari_microwire_cmd(MW_LM1992_BALLEFT(dmasound.volume_left));
 993        dmasound.volume_right = VOLUME_VOXWARE_TO_DB((volume & 0xff00) >> 8);
 994        atari_microwire_cmd(MW_LM1992_BALRIGHT(dmasound.volume_right));
 995        return VOLUME_DB_TO_VOXWARE(dmasound.volume_left) |
 996               (VOLUME_DB_TO_VOXWARE(dmasound.volume_right) << 8);
 997}
 998
 999
1000#define GAIN_VOXWARE_TO_DB(v) \
1001        (((v) < 0) ? -80 : ((v) > 100) ? 0 : ((v) * 4) / 5 - 80)
1002#define GAIN_DB_TO_VOXWARE(v) ((((v) + 80) * 5 + 1) / 4)
1003
1004static int TTSetGain(int gain)
1005{
1006        dmasound.gain = GAIN_VOXWARE_TO_DB(gain);
1007        atari_microwire_cmd(MW_LM1992_VOLUME(dmasound.gain));
1008        return GAIN_DB_TO_VOXWARE(dmasound.gain);
1009}
1010
1011
1012
1013/*
1014 * Falcon
1015 */
1016
1017
1018static void FalconSilence(void)
1019{
1020        /* stop playback, set sample rate 50kHz for PSG sound */
1021        tt_dmasnd.ctrl = DMASND_CTRL_OFF;
1022        tt_dmasnd.mode = DMASND_MODE_50KHZ | DMASND_MODE_STEREO | DMASND_MODE_8BIT;
1023        tt_dmasnd.int_div = 0; /* STE compatible divider */
1024        tt_dmasnd.int_ctrl = 0x0;
1025        tt_dmasnd.cbar_src = 0x0000; /* no matrix inputs */
1026        tt_dmasnd.cbar_dst = 0x0000; /* no matrix outputs */
1027        tt_dmasnd.dac_src = 1; /* connect ADC to DAC, disconnect matrix */
1028        tt_dmasnd.adc_src = 3; /* ADC Input = PSG */
1029}
1030
1031
1032static void FalconInit(void)
1033{
1034        int divider, i, idx;
1035        const int freq[8] = {49170, 32780, 24585, 19668, 16390, 12292, 9834, 8195};
1036
1037        /* search a frequency that fits into the allowed error range */
1038
1039        idx = -1;
1040        for (i = 0; i < ARRAY_SIZE(freq); i++)
1041                /* if we will tolerate 3% error 8000Hz->8195Hz (2.38%) would
1042                 * be playable without expanding, but that now a kernel runtime
1043                 * option
1044                 */
1045                if ((100 * abs(dmasound.soft.speed - freq[i]) / freq[i]) < catchRadius)
1046                        idx = i;
1047        if (idx > -1) {
1048                dmasound.soft.speed = freq[idx];
1049                dmasound.trans_write = &transFalconNormal;
1050        } else
1051                dmasound.trans_write = &transFalconExpanding;
1052
1053        FalconSilence();
1054        dmasound.hard = dmasound.soft;
1055
1056        if (dmasound.hard.size == 16) {
1057                /* the Falcon can play 16bit samples only in stereo */
1058                dmasound.hard.stereo = 1;
1059        }
1060
1061        if (dmasound.hard.speed > 49170) {
1062                /* we would need to squeeze the sound, but we won't do that */
1063                dmasound.hard.speed = 49170;
1064                divider = 1;
1065                dmasound.trans_write = &transFalconNormal;
1066        } else if (dmasound.hard.speed > 32780) {
1067                dmasound.hard.speed = 49170;
1068                divider = 1;
1069        } else if (dmasound.hard.speed > 24585) {
1070                dmasound.hard.speed = 32780;
1071                divider = 2;
1072        } else if (dmasound.hard.speed > 19668) {
1073                dmasound.hard.speed = 24585;
1074                divider = 3;
1075        } else if (dmasound.hard.speed > 16390) {
1076                dmasound.hard.speed = 19668;
1077                divider = 4;
1078        } else if (dmasound.hard.speed > 12292) {
1079                dmasound.hard.speed = 16390;
1080                divider = 5;
1081        } else if (dmasound.hard.speed > 9834) {
1082                dmasound.hard.speed = 12292;
1083                divider = 7;
1084        } else if (dmasound.hard.speed > 8195) {
1085                dmasound.hard.speed = 9834;
1086                divider = 9;
1087        } else {
1088                dmasound.hard.speed = 8195;
1089                divider = 11;
1090        }
1091        tt_dmasnd.int_div = divider;
1092
1093        /* Setup Falcon sound DMA for playback */
1094        tt_dmasnd.int_ctrl = 0x4; /* Timer A int at play end */
1095        tt_dmasnd.track_select = 0x0; /* play 1 track, track 1 */
1096        tt_dmasnd.cbar_src = 0x0001; /* DMA(25MHz) --> DAC */
1097        tt_dmasnd.cbar_dst = 0x0000;
1098        tt_dmasnd.rec_track_select = 0;
1099        tt_dmasnd.dac_src = 2; /* connect matrix to DAC */
1100        tt_dmasnd.adc_src = 0; /* ADC Input = Mic */
1101
1102        tt_dmasnd.mode = (dmasound.hard.stereo ?
1103                          DMASND_MODE_STEREO : DMASND_MODE_MONO) |
1104                ((dmasound.hard.size == 8) ?
1105                 DMASND_MODE_8BIT : DMASND_MODE_16BIT) |
1106                DMASND_MODE_6KHZ;
1107
1108        expand_bal = -dmasound.soft.speed;
1109}
1110
1111
1112static int FalconSetFormat(int format)
1113{
1114        int size;
1115        /* Falcon sound DMA supports 8bit and 16bit modes */
1116
1117        switch (format) {
1118        case AFMT_QUERY:
1119                return dmasound.soft.format;
1120        case AFMT_MU_LAW:
1121        case AFMT_A_LAW:
1122        case AFMT_U8:
1123        case AFMT_S8:
1124                size = 8;
1125                break;
1126        case AFMT_S16_BE:
1127        case AFMT_U16_BE:
1128        case AFMT_S16_LE:
1129        case AFMT_U16_LE:
1130                size = 16;
1131                break;
1132        default: /* :-) */
1133                size = 8;
1134                format = AFMT_S8;
1135        }
1136
1137        dmasound.soft.format = format;
1138        dmasound.soft.size = size;
1139        if (dmasound.minDev == SND_DEV_DSP) {
1140                dmasound.dsp.format = format;
1141                dmasound.dsp.size = dmasound.soft.size;
1142        }
1143
1144        FalconInit();
1145
1146        return format;
1147}
1148
1149
1150/* This is for the Falcon output *attenuation* in 1.5dB steps,
1151 * i.e. output level from 0 to -22.5dB in -1.5dB steps.
1152 */
1153#define VOLUME_VOXWARE_TO_ATT(v) \
1154        ((v) < 0 ? 15 : (v) > 100 ? 0 : 15 - (v) * 3 / 20)
1155#define VOLUME_ATT_TO_VOXWARE(v) (100 - (v) * 20 / 3)
1156
1157
1158static int FalconSetVolume(int volume)
1159{
1160        dmasound.volume_left = VOLUME_VOXWARE_TO_ATT(volume & 0xff);
1161        dmasound.volume_right = VOLUME_VOXWARE_TO_ATT((volume & 0xff00) >> 8);
1162        tt_dmasnd.output_atten = dmasound.volume_left << 8 | dmasound.volume_right << 4;
1163        return VOLUME_ATT_TO_VOXWARE(dmasound.volume_left) |
1164               VOLUME_ATT_TO_VOXWARE(dmasound.volume_right) << 8;
1165}
1166
1167
1168static void AtaPlayNextFrame(int index)
1169{
1170        char *start, *end;
1171
1172        /* used by AtaPlay() if all doubts whether there really is something
1173         * to be played are already wiped out.
1174         */
1175        start = write_sq.buffers[write_sq.front];
1176        end = start+((write_sq.count == index) ? write_sq.rear_size
1177                                               : write_sq.block_size);
1178        /* end might not be a legal virtual address. */
1179        DMASNDSetEnd(virt_to_phys(end - 1) + 1);
1180        DMASNDSetBase(virt_to_phys(start));
1181        /* Since only an even number of samples per frame can
1182           be played, we might lose one byte here. (TO DO) */
1183        write_sq.front = (write_sq.front+1) % write_sq.max_count;
1184        write_sq.active++;
1185        tt_dmasnd.ctrl = DMASND_CTRL_ON | DMASND_CTRL_REPEAT;
1186}
1187
1188
1189static void AtaPlay(void)
1190{
1191        /* ++TeSche: Note that write_sq.active is no longer just a flag but
1192         * holds the number of frames the DMA is currently programmed for
1193         * instead, may be 0, 1 (currently being played) or 2 (pre-programmed).
1194         *
1195         * Changes done to write_sq.count and write_sq.active are a bit more
1196         * subtle again so now I must admit I also prefer disabling the irq
1197         * here rather than considering all possible situations. But the point
1198         * is that disabling the irq doesn't have any bad influence on this
1199         * version of the driver as we benefit from having pre-programmed the
1200         * DMA wherever possible: There's no need to reload the DMA at the
1201         * exact time of an interrupt but only at some time while the
1202         * pre-programmed frame is playing!
1203         */
1204        atari_disable_irq(IRQ_MFP_TIMA);
1205
1206        if (write_sq.active == 2 ||     /* DMA is 'full' */
1207            write_sq.count <= 0) {      /* nothing to do */
1208                atari_enable_irq(IRQ_MFP_TIMA);
1209                return;
1210        }
1211
1212        if (write_sq.active == 0) {
1213                /* looks like there's nothing 'in' the DMA yet, so try
1214                 * to put two frames into it (at least one is available).
1215                 */
1216                if (write_sq.count == 1 &&
1217                    write_sq.rear_size < write_sq.block_size &&
1218                    !write_sq.syncing) {
1219                        /* hmmm, the only existing frame is not
1220                         * yet filled and we're not syncing?
1221                         */
1222                        atari_enable_irq(IRQ_MFP_TIMA);
1223                        return;
1224                }
1225                AtaPlayNextFrame(1);
1226                if (write_sq.count == 1) {
1227                        /* no more frames */
1228                        atari_enable_irq(IRQ_MFP_TIMA);
1229                        return;
1230                }
1231                if (write_sq.count == 2 &&
1232                    write_sq.rear_size < write_sq.block_size &&
1233                    !write_sq.syncing) {
1234                        /* hmmm, there were two frames, but the second
1235                         * one is not yet filled and we're not syncing?
1236                         */
1237                        atari_enable_irq(IRQ_MFP_TIMA);
1238                        return;
1239                }
1240                AtaPlayNextFrame(2);
1241        } else {
1242                /* there's already a frame being played so we may only stuff
1243                 * one new into the DMA, but even if this may be the last
1244                 * frame existing the previous one is still on write_sq.count.
1245                 */
1246                if (write_sq.count == 2 &&
1247                    write_sq.rear_size < write_sq.block_size &&
1248                    !write_sq.syncing) {
1249                        /* hmmm, the only existing frame is not
1250                         * yet filled and we're not syncing?
1251                         */
1252                        atari_enable_irq(IRQ_MFP_TIMA);
1253                        return;
1254                }
1255                AtaPlayNextFrame(2);
1256        }
1257        atari_enable_irq(IRQ_MFP_TIMA);
1258}
1259
1260
1261static irqreturn_t AtaInterrupt(int irq, void *dummy)
1262{
1263#if 0
1264        /* ++TeSche: if you should want to test this... */
1265        static int cnt;
1266        if (write_sq.active == 2)
1267                if (++cnt == 10) {
1268                        /* simulate losing an interrupt */
1269                        cnt = 0;
1270                        return IRQ_HANDLED;
1271                }
1272#endif
1273        spin_lock(&dmasound.lock);
1274        if (write_sq_ignore_int && is_falcon) {
1275                /* ++TeSche: Falcon only: ignore first irq because it comes
1276                 * immediately after starting a frame. after that, irqs come
1277                 * (almost) like on the TT.
1278                 */
1279                write_sq_ignore_int = 0;
1280                goto out;
1281        }
1282
1283        if (!write_sq.active) {
1284                /* playing was interrupted and sq_reset() has already cleared
1285                 * the sq variables, so better don't do anything here.
1286                 */
1287                WAKE_UP(write_sq.sync_queue);
1288                goto out;
1289        }
1290
1291        /* Probably ;) one frame is finished. Well, in fact it may be that a
1292         * pre-programmed one is also finished because there has been a long
1293         * delay in interrupt delivery and we've completely lost one, but
1294         * there's no way to detect such a situation. In such a case the last
1295         * frame will be played more than once and the situation will recover
1296         * as soon as the irq gets through.
1297         */
1298        write_sq.count--;
1299        write_sq.active--;
1300
1301        if (!write_sq.active) {
1302                tt_dmasnd.ctrl = DMASND_CTRL_OFF;
1303                write_sq_ignore_int = 1;
1304        }
1305
1306        WAKE_UP(write_sq.action_queue);
1307        /* At least one block of the queue is free now
1308           so wake up a writing process blocked because
1309           of a full queue. */
1310
1311        if ((write_sq.active != 1) || (write_sq.count != 1))
1312                /* We must be a bit carefully here: write_sq.count indicates the
1313                 * number of buffers used and not the number of frames to be
1314                 * played. If write_sq.count==1 and write_sq.active==1 that
1315                 * means the only remaining frame was already programmed
1316                 * earlier (and is currently running) so we mustn't call
1317                 * AtaPlay() here, otherwise we'll play one frame too much.
1318                 */
1319                AtaPlay();
1320
1321        if (!write_sq.active) WAKE_UP(write_sq.sync_queue);
1322        /* We are not playing after AtaPlay(), so there
1323           is nothing to play any more. Wake up a process
1324           waiting for audio output to drain. */
1325out:
1326        spin_unlock(&dmasound.lock);
1327        return IRQ_HANDLED;
1328}
1329
1330
1331/*** Mid level stuff *********************************************************/
1332
1333
1334/*
1335 * /dev/mixer abstraction
1336 */
1337
1338#define RECLEVEL_VOXWARE_TO_GAIN(v)     \
1339        ((v) < 0 ? 0 : (v) > 100 ? 15 : (v) * 3 / 20)
1340#define RECLEVEL_GAIN_TO_VOXWARE(v)     (((v) * 20 + 2) / 3)
1341
1342
1343static void __init TTMixerInit(void)
1344{
1345        atari_microwire_cmd(MW_LM1992_VOLUME(0));
1346        dmasound.volume_left = 0;
1347        atari_microwire_cmd(MW_LM1992_BALLEFT(0));
1348        dmasound.volume_right = 0;
1349        atari_microwire_cmd(MW_LM1992_BALRIGHT(0));
1350        atari_microwire_cmd(MW_LM1992_TREBLE(0));
1351        atari_microwire_cmd(MW_LM1992_BASS(0));
1352}
1353
1354static void __init FalconMixerInit(void)
1355{
1356        dmasound.volume_left = (tt_dmasnd.output_atten & 0xf00) >> 8;
1357        dmasound.volume_right = (tt_dmasnd.output_atten & 0xf0) >> 4;
1358}
1359
1360static int AtaMixerIoctl(u_int cmd, u_long arg)
1361{
1362        int data;
1363        unsigned long flags;
1364        switch (cmd) {
1365            case SOUND_MIXER_READ_SPEAKER:
1366                    if (is_falcon || MACH_IS_TT) {
1367                            int porta;
1368                            spin_lock_irqsave(&dmasound.lock, flags);
1369                            sound_ym.rd_data_reg_sel = 14;
1370                            porta = sound_ym.rd_data_reg_sel;
1371                            spin_unlock_irqrestore(&dmasound.lock, flags);
1372                            return IOCTL_OUT(arg, porta & 0x40 ? 0 : 100);
1373                    }
1374                    break;
1375            case SOUND_MIXER_WRITE_VOLUME:
1376                    IOCTL_IN(arg, data);
1377                    return IOCTL_OUT(arg, dmasound_set_volume(data));
1378            case SOUND_MIXER_WRITE_SPEAKER:
1379                    if (is_falcon || MACH_IS_TT) {
1380                            int porta;
1381                            IOCTL_IN(arg, data);
1382                            spin_lock_irqsave(&dmasound.lock, flags);
1383                            sound_ym.rd_data_reg_sel = 14;
1384                            porta = (sound_ym.rd_data_reg_sel & ~0x40) |
1385                                    (data < 50 ? 0x40 : 0);
1386                            sound_ym.wd_data = porta;
1387                            spin_unlock_irqrestore(&dmasound.lock, flags);
1388                            return IOCTL_OUT(arg, porta & 0x40 ? 0 : 100);
1389                    }
1390        }
1391        return -EINVAL;
1392}
1393
1394
1395static int TTMixerIoctl(u_int cmd, u_long arg)
1396{
1397        int data;
1398        switch (cmd) {
1399            case SOUND_MIXER_READ_RECMASK:
1400                return IOCTL_OUT(arg, 0);
1401            case SOUND_MIXER_READ_DEVMASK:
1402                return IOCTL_OUT(arg,
1403                                 SOUND_MASK_VOLUME | SOUND_MASK_TREBLE | SOUND_MASK_BASS |
1404                                 (MACH_IS_TT ? SOUND_MASK_SPEAKER : 0));
1405            case SOUND_MIXER_READ_STEREODEVS:
1406                return IOCTL_OUT(arg, SOUND_MASK_VOLUME);
1407            case SOUND_MIXER_READ_VOLUME:
1408                return IOCTL_OUT(arg,
1409                                 VOLUME_DB_TO_VOXWARE(dmasound.volume_left) |
1410                                 (VOLUME_DB_TO_VOXWARE(dmasound.volume_right) << 8));
1411            case SOUND_MIXER_READ_BASS:
1412                return IOCTL_OUT(arg, TONE_DB_TO_VOXWARE(dmasound.bass));
1413            case SOUND_MIXER_READ_TREBLE:
1414                return IOCTL_OUT(arg, TONE_DB_TO_VOXWARE(dmasound.treble));
1415            case SOUND_MIXER_READ_OGAIN:
1416                return IOCTL_OUT(arg, GAIN_DB_TO_VOXWARE(dmasound.gain));
1417            case SOUND_MIXER_WRITE_BASS:
1418                IOCTL_IN(arg, data);
1419                return IOCTL_OUT(arg, dmasound_set_bass(data));
1420            case SOUND_MIXER_WRITE_TREBLE:
1421                IOCTL_IN(arg, data);
1422                return IOCTL_OUT(arg, dmasound_set_treble(data));
1423            case SOUND_MIXER_WRITE_OGAIN:
1424                IOCTL_IN(arg, data);
1425                return IOCTL_OUT(arg, dmasound_set_gain(data));
1426        }
1427        return AtaMixerIoctl(cmd, arg);
1428}
1429
1430static int FalconMixerIoctl(u_int cmd, u_long arg)
1431{
1432        int data;
1433        switch (cmd) {
1434            case SOUND_MIXER_READ_RECMASK:
1435                return IOCTL_OUT(arg, SOUND_MASK_MIC);
1436            case SOUND_MIXER_READ_DEVMASK:
1437                return IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_MIC | SOUND_MASK_SPEAKER);
1438            case SOUND_MIXER_READ_STEREODEVS:
1439                return IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_MIC);
1440            case SOUND_MIXER_READ_VOLUME:
1441                return IOCTL_OUT(arg,
1442                        VOLUME_ATT_TO_VOXWARE(dmasound.volume_left) |
1443                        VOLUME_ATT_TO_VOXWARE(dmasound.volume_right) << 8);
1444            case SOUND_MIXER_READ_CAPS:
1445                return IOCTL_OUT(arg, SOUND_CAP_EXCL_INPUT);
1446            case SOUND_MIXER_WRITE_MIC:
1447                IOCTL_IN(arg, data);
1448                tt_dmasnd.input_gain =
1449                        RECLEVEL_VOXWARE_TO_GAIN(data & 0xff) << 4 |
1450                        RECLEVEL_VOXWARE_TO_GAIN(data >> 8 & 0xff);
1451                /* fall thru, return set value */
1452            case SOUND_MIXER_READ_MIC:
1453                return IOCTL_OUT(arg,
1454                        RECLEVEL_GAIN_TO_VOXWARE(tt_dmasnd.input_gain >> 4 & 0xf) |
1455                        RECLEVEL_GAIN_TO_VOXWARE(tt_dmasnd.input_gain & 0xf) << 8);
1456        }
1457        return AtaMixerIoctl(cmd, arg);
1458}
1459
1460static int AtaWriteSqSetup(void)
1461{
1462        write_sq_ignore_int = 0;
1463        return 0 ;
1464}
1465
1466static int AtaSqOpen(fmode_t mode)
1467{
1468        write_sq_ignore_int = 1;
1469        return 0 ;
1470}
1471
1472static int TTStateInfo(char *buffer, size_t space)
1473{
1474        int len = 0;
1475        len += sprintf(buffer+len, "\tvol left  %ddB [-40...  0]\n",
1476                       dmasound.volume_left);
1477        len += sprintf(buffer+len, "\tvol right %ddB [-40...  0]\n",
1478                       dmasound.volume_right);
1479        len += sprintf(buffer+len, "\tbass      %ddB [-12...+12]\n",
1480                       dmasound.bass);
1481        len += sprintf(buffer+len, "\ttreble    %ddB [-12...+12]\n",
1482                       dmasound.treble);
1483        if (len >= space) {
1484                printk(KERN_ERR "dmasound_atari: overflowed state buffer alloc.\n") ;
1485                len = space ;
1486        }
1487        return len;
1488}
1489
1490static int FalconStateInfo(char *buffer, size_t space)
1491{
1492        int len = 0;
1493        len += sprintf(buffer+len, "\tvol left  %ddB [-22.5 ... 0]\n",
1494                       dmasound.volume_left);
1495        len += sprintf(buffer+len, "\tvol right %ddB [-22.5 ... 0]\n",
1496                       dmasound.volume_right);
1497        if (len >= space) {
1498                printk(KERN_ERR "dmasound_atari: overflowed state buffer alloc.\n") ;
1499                len = space ;
1500        }
1501        return len;
1502}
1503
1504
1505/*** Machine definitions *****************************************************/
1506
1507static SETTINGS def_hard_falcon = {
1508        .format         = AFMT_S8,
1509        .stereo         = 0,
1510        .size           = 8,
1511        .speed          = 8195
1512} ;
1513
1514static SETTINGS def_hard_tt = {
1515        .format = AFMT_S8,
1516        .stereo = 0,
1517        .size   = 8,
1518        .speed  = 12517
1519} ;
1520
1521static SETTINGS def_soft = {
1522        .format = AFMT_U8,
1523        .stereo = 0,
1524        .size   = 8,
1525        .speed  = 8000
1526} ;
1527
1528static __initdata MACHINE machTT = {
1529        .name           = "Atari",
1530        .name2          = "TT",
1531        .owner          = THIS_MODULE,
1532        .dma_alloc      = AtaAlloc,
1533        .dma_free       = AtaFree,
1534        .irqinit        = AtaIrqInit,
1535#ifdef MODULE
1536        .irqcleanup     = AtaIrqCleanUp,
1537#endif /* MODULE */
1538        .init           = TTInit,
1539        .silence        = TTSilence,
1540        .setFormat      = TTSetFormat,
1541        .setVolume      = TTSetVolume,
1542        .setBass        = AtaSetBass,
1543        .setTreble      = AtaSetTreble,
1544        .setGain        = TTSetGain,
1545        .play           = AtaPlay,
1546        .mixer_init     = TTMixerInit,
1547        .mixer_ioctl    = TTMixerIoctl,
1548        .write_sq_setup = AtaWriteSqSetup,
1549        .sq_open        = AtaSqOpen,
1550        .state_info     = TTStateInfo,
1551        .min_dsp_speed  = 6258,
1552        .version        = ((DMASOUND_ATARI_REVISION<<8) | DMASOUND_ATARI_EDITION),
1553        .hardware_afmts = AFMT_S8,  /* h'ware-supported formats *only* here */
1554        .capabilities   =  DSP_CAP_BATCH        /* As per SNDCTL_DSP_GETCAPS */
1555};
1556
1557static __initdata MACHINE machFalcon = {
1558        .name           = "Atari",
1559        .name2          = "FALCON",
1560        .dma_alloc      = AtaAlloc,
1561        .dma_free       = AtaFree,
1562        .irqinit        = AtaIrqInit,
1563#ifdef MODULE
1564        .irqcleanup     = AtaIrqCleanUp,
1565#endif /* MODULE */
1566        .init           = FalconInit,
1567        .silence        = FalconSilence,
1568        .setFormat      = FalconSetFormat,
1569        .setVolume      = FalconSetVolume,
1570        .setBass        = AtaSetBass,
1571        .setTreble      = AtaSetTreble,
1572        .play           = AtaPlay,
1573        .mixer_init     = FalconMixerInit,
1574        .mixer_ioctl    = FalconMixerIoctl,
1575        .write_sq_setup = AtaWriteSqSetup,
1576        .sq_open        = AtaSqOpen,
1577        .state_info     = FalconStateInfo,
1578        .min_dsp_speed  = 8195,
1579        .version        = ((DMASOUND_ATARI_REVISION<<8) | DMASOUND_ATARI_EDITION),
1580        .hardware_afmts = (AFMT_S8 | AFMT_S16_BE), /* h'ware-supported formats *only* here */
1581        .capabilities   =  DSP_CAP_BATCH        /* As per SNDCTL_DSP_GETCAPS */
1582};
1583
1584
1585/*** Config & Setup **********************************************************/
1586
1587
1588static int __init dmasound_atari_init(void)
1589{
1590        if (MACH_IS_ATARI && ATARIHW_PRESENT(PCM_8BIT)) {
1591            if (ATARIHW_PRESENT(CODEC)) {
1592                dmasound.mach = machFalcon;
1593                dmasound.mach.default_soft = def_soft ;
1594                dmasound.mach.default_hard = def_hard_falcon ;
1595                is_falcon = 1;
1596            } else if (ATARIHW_PRESENT(MICROWIRE)) {
1597                dmasound.mach = machTT;
1598                dmasound.mach.default_soft = def_soft ;
1599                dmasound.mach.default_hard = def_hard_tt ;
1600                is_falcon = 0;
1601            } else
1602                return -ENODEV;
1603            if ((st_mfp.int_en_a & st_mfp.int_mk_a & 0x20) == 0)
1604                return dmasound_init();
1605            else {
1606                printk("DMA sound driver: Timer A interrupt already in use\n");
1607                return -EBUSY;
1608            }
1609        }
1610        return -ENODEV;
1611}
1612
1613static void __exit dmasound_atari_cleanup(void)
1614{
1615        dmasound_deinit();
1616}
1617
1618module_init(dmasound_atari_init);
1619module_exit(dmasound_atari_cleanup);
1620MODULE_LICENSE("GPL");
1621