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