root/sound/isa/sb/sb8_main.c

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

DEFINITIONS

This source file includes following definitions.
  1. snd_sb8_hw_constraint_rate_channels
  2. snd_sb8_hw_constraint_channels_rate
  3. snd_sb8_playback_prepare
  4. snd_sb8_playback_trigger
  5. snd_sb8_hw_params
  6. snd_sb8_hw_free
  7. snd_sb8_capture_prepare
  8. snd_sb8_capture_trigger
  9. snd_sb8dsp_interrupt
  10. snd_sb8_playback_pointer
  11. snd_sb8_capture_pointer
  12. snd_sb8_open
  13. snd_sb8_close
  14. snd_sb8dsp_pcm

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
   4  *                   Uros Bizjak <uros@kss-loka.si>
   5  *
   6  *  Routines for control of 8-bit SoundBlaster cards and clones
   7  *  Please note: I don't have access to old SB8 soundcards.
   8  *
   9  * --
  10  *
  11  * Thu Apr 29 20:36:17 BST 1999 George David Morrison <gdm@gedamo.demon.co.uk>
  12  *   DSP can't respond to commands whilst in "high speed" mode. Caused 
  13  *   glitching during playback. Fixed.
  14  *
  15  * Wed Jul 12 22:02:55 CEST 2000 Uros Bizjak <uros@kss-loka.si>
  16  *   Cleaned up and rewrote lowlevel routines.
  17  */
  18 
  19 #include <linux/io.h>
  20 #include <asm/dma.h>
  21 #include <linux/init.h>
  22 #include <linux/time.h>
  23 #include <linux/module.h>
  24 #include <sound/core.h>
  25 #include <sound/sb.h>
  26 
  27 MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Uros Bizjak <uros@kss-loka.si>");
  28 MODULE_DESCRIPTION("Routines for control of 8-bit SoundBlaster cards and clones");
  29 MODULE_LICENSE("GPL");
  30 
  31 #define SB8_CLOCK       1000000
  32 #define SB8_DEN(v)      ((SB8_CLOCK + (v) / 2) / (v))
  33 #define SB8_RATE(v)     (SB8_CLOCK / SB8_DEN(v))
  34 
  35 static const struct snd_ratnum clock = {
  36         .num = SB8_CLOCK,
  37         .den_min = 1,
  38         .den_max = 256,
  39         .den_step = 1,
  40 };
  41 
  42 static const struct snd_pcm_hw_constraint_ratnums hw_constraints_clock = {
  43         .nrats = 1,
  44         .rats = &clock,
  45 };
  46 
  47 static const struct snd_ratnum stereo_clocks[] = {
  48         {
  49                 .num = SB8_CLOCK,
  50                 .den_min = SB8_DEN(22050),
  51                 .den_max = SB8_DEN(22050),
  52                 .den_step = 1,
  53         },
  54         {
  55                 .num = SB8_CLOCK,
  56                 .den_min = SB8_DEN(11025),
  57                 .den_max = SB8_DEN(11025),
  58                 .den_step = 1,
  59         }
  60 };
  61 
  62 static int snd_sb8_hw_constraint_rate_channels(struct snd_pcm_hw_params *params,
  63                                                struct snd_pcm_hw_rule *rule)
  64 {
  65         struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
  66         if (c->min > 1) {
  67                 unsigned int num = 0, den = 0;
  68                 int err = snd_interval_ratnum(hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE),
  69                                           2, stereo_clocks, &num, &den);
  70                 if (err >= 0 && den) {
  71                         params->rate_num = num;
  72                         params->rate_den = den;
  73                 }
  74                 return err;
  75         }
  76         return 0;
  77 }
  78 
  79 static int snd_sb8_hw_constraint_channels_rate(struct snd_pcm_hw_params *params,
  80                                                struct snd_pcm_hw_rule *rule)
  81 {
  82         struct snd_interval *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
  83         if (r->min > SB8_RATE(22050) || r->max <= SB8_RATE(11025)) {
  84                 struct snd_interval t = { .min = 1, .max = 1 };
  85                 return snd_interval_refine(hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS), &t);
  86         }
  87         return 0;
  88 }
  89 
  90 static int snd_sb8_playback_prepare(struct snd_pcm_substream *substream)
  91 {
  92         unsigned long flags;
  93         struct snd_sb *chip = snd_pcm_substream_chip(substream);
  94         struct snd_pcm_runtime *runtime = substream->runtime;
  95         unsigned int mixreg, rate, size, count;
  96         unsigned char format;
  97         unsigned char stereo = runtime->channels > 1;
  98         int dma;
  99 
 100         rate = runtime->rate;
 101         switch (chip->hardware) {
 102         case SB_HW_JAZZ16:
 103                 if (runtime->format == SNDRV_PCM_FORMAT_S16_LE) {
 104                         if (chip->mode & SB_MODE_CAPTURE_16)
 105                                 return -EBUSY;
 106                         else
 107                                 chip->mode |= SB_MODE_PLAYBACK_16;
 108                 }
 109                 chip->playback_format = SB_DSP_LO_OUTPUT_AUTO;
 110                 break;
 111         case SB_HW_PRO:
 112                 if (runtime->channels > 1) {
 113                         if (snd_BUG_ON(rate != SB8_RATE(11025) &&
 114                                        rate != SB8_RATE(22050)))
 115                                 return -EINVAL;
 116                         chip->playback_format = SB_DSP_HI_OUTPUT_AUTO;
 117                         break;
 118                 }
 119                 /* fall through */
 120         case SB_HW_201:
 121                 if (rate > 23000) {
 122                         chip->playback_format = SB_DSP_HI_OUTPUT_AUTO;
 123                         break;
 124                 }
 125                 /* fall through */
 126         case SB_HW_20:
 127                 chip->playback_format = SB_DSP_LO_OUTPUT_AUTO;
 128                 break;
 129         case SB_HW_10:
 130                 chip->playback_format = SB_DSP_OUTPUT;
 131                 break;
 132         default:
 133                 return -EINVAL;
 134         }
 135         if (chip->mode & SB_MODE_PLAYBACK_16) {
 136                 format = stereo ? SB_DSP_STEREO_16BIT : SB_DSP_MONO_16BIT;
 137                 dma = chip->dma16;
 138         } else {
 139                 format = stereo ? SB_DSP_STEREO_8BIT : SB_DSP_MONO_8BIT;
 140                 chip->mode |= SB_MODE_PLAYBACK_8;
 141                 dma = chip->dma8;
 142         }
 143         size = chip->p_dma_size = snd_pcm_lib_buffer_bytes(substream);
 144         count = chip->p_period_size = snd_pcm_lib_period_bytes(substream);
 145         spin_lock_irqsave(&chip->reg_lock, flags);
 146         snd_sbdsp_command(chip, SB_DSP_SPEAKER_ON);
 147         if (chip->hardware == SB_HW_JAZZ16)
 148                 snd_sbdsp_command(chip, format);
 149         else if (stereo) {
 150                 /* set playback stereo mode */
 151                 spin_lock(&chip->mixer_lock);
 152                 mixreg = snd_sbmixer_read(chip, SB_DSP_STEREO_SW);
 153                 snd_sbmixer_write(chip, SB_DSP_STEREO_SW, mixreg | 0x02);
 154                 spin_unlock(&chip->mixer_lock);
 155 
 156                 /* Soundblaster hardware programming reference guide, 3-23 */
 157                 snd_sbdsp_command(chip, SB_DSP_DMA8_EXIT);
 158                 runtime->dma_area[0] = 0x80;
 159                 snd_dma_program(dma, runtime->dma_addr, 1, DMA_MODE_WRITE);
 160                 /* force interrupt */
 161                 snd_sbdsp_command(chip, SB_DSP_OUTPUT);
 162                 snd_sbdsp_command(chip, 0);
 163                 snd_sbdsp_command(chip, 0);
 164         }
 165         snd_sbdsp_command(chip, SB_DSP_SAMPLE_RATE);
 166         if (stereo) {
 167                 snd_sbdsp_command(chip, 256 - runtime->rate_den / 2);
 168                 spin_lock(&chip->mixer_lock);
 169                 /* save output filter status and turn it off */
 170                 mixreg = snd_sbmixer_read(chip, SB_DSP_PLAYBACK_FILT);
 171                 snd_sbmixer_write(chip, SB_DSP_PLAYBACK_FILT, mixreg | 0x20);
 172                 spin_unlock(&chip->mixer_lock);
 173                 /* just use force_mode16 for temporary storate... */
 174                 chip->force_mode16 = mixreg;
 175         } else {
 176                 snd_sbdsp_command(chip, 256 - runtime->rate_den);
 177         }
 178         if (chip->playback_format != SB_DSP_OUTPUT) {
 179                 if (chip->mode & SB_MODE_PLAYBACK_16)
 180                         count /= 2;
 181                 count--;
 182                 snd_sbdsp_command(chip, SB_DSP_BLOCK_SIZE);
 183                 snd_sbdsp_command(chip, count & 0xff);
 184                 snd_sbdsp_command(chip, count >> 8);
 185         }
 186         spin_unlock_irqrestore(&chip->reg_lock, flags);
 187         snd_dma_program(dma, runtime->dma_addr,
 188                         size, DMA_MODE_WRITE | DMA_AUTOINIT);
 189         return 0;
 190 }
 191 
 192 static int snd_sb8_playback_trigger(struct snd_pcm_substream *substream,
 193                                     int cmd)
 194 {
 195         unsigned long flags;
 196         struct snd_sb *chip = snd_pcm_substream_chip(substream);
 197         unsigned int count;
 198 
 199         spin_lock_irqsave(&chip->reg_lock, flags);
 200         switch (cmd) {
 201         case SNDRV_PCM_TRIGGER_START:
 202                 snd_sbdsp_command(chip, chip->playback_format);
 203                 if (chip->playback_format == SB_DSP_OUTPUT) {
 204                         count = chip->p_period_size - 1;
 205                         snd_sbdsp_command(chip, count & 0xff);
 206                         snd_sbdsp_command(chip, count >> 8);
 207                 }
 208                 break;
 209         case SNDRV_PCM_TRIGGER_STOP:
 210                 if (chip->playback_format == SB_DSP_HI_OUTPUT_AUTO) {
 211                         struct snd_pcm_runtime *runtime = substream->runtime;
 212                         snd_sbdsp_reset(chip);
 213                         if (runtime->channels > 1) {
 214                                 spin_lock(&chip->mixer_lock);
 215                                 /* restore output filter and set hardware to mono mode */ 
 216                                 snd_sbmixer_write(chip, SB_DSP_STEREO_SW, chip->force_mode16 & ~0x02);
 217                                 spin_unlock(&chip->mixer_lock);
 218                         }
 219                 } else {
 220                         snd_sbdsp_command(chip, SB_DSP_DMA8_OFF);
 221                 }
 222                 snd_sbdsp_command(chip, SB_DSP_SPEAKER_OFF);
 223         }
 224         spin_unlock_irqrestore(&chip->reg_lock, flags);
 225         return 0;
 226 }
 227 
 228 static int snd_sb8_hw_params(struct snd_pcm_substream *substream,
 229                              struct snd_pcm_hw_params *hw_params)
 230 {
 231         return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
 232 }
 233 
 234 static int snd_sb8_hw_free(struct snd_pcm_substream *substream)
 235 {
 236         snd_pcm_lib_free_pages(substream);
 237         return 0;
 238 }
 239 
 240 static int snd_sb8_capture_prepare(struct snd_pcm_substream *substream)
 241 {
 242         unsigned long flags;
 243         struct snd_sb *chip = snd_pcm_substream_chip(substream);
 244         struct snd_pcm_runtime *runtime = substream->runtime;
 245         unsigned int mixreg, rate, size, count;
 246         unsigned char format;
 247         unsigned char stereo = runtime->channels > 1;
 248         int dma;
 249 
 250         rate = runtime->rate;
 251         switch (chip->hardware) {
 252         case SB_HW_JAZZ16:
 253                 if (runtime->format == SNDRV_PCM_FORMAT_S16_LE) {
 254                         if (chip->mode & SB_MODE_PLAYBACK_16)
 255                                 return -EBUSY;
 256                         else
 257                                 chip->mode |= SB_MODE_CAPTURE_16;
 258                 }
 259                 chip->capture_format = SB_DSP_LO_INPUT_AUTO;
 260                 break;
 261         case SB_HW_PRO:
 262                 if (runtime->channels > 1) {
 263                         if (snd_BUG_ON(rate != SB8_RATE(11025) &&
 264                                        rate != SB8_RATE(22050)))
 265                                 return -EINVAL;
 266                         chip->capture_format = SB_DSP_HI_INPUT_AUTO;
 267                         break;
 268                 }
 269                 chip->capture_format = (rate > 23000) ? SB_DSP_HI_INPUT_AUTO : SB_DSP_LO_INPUT_AUTO;
 270                 break;
 271         case SB_HW_201:
 272                 if (rate > 13000) {
 273                         chip->capture_format = SB_DSP_HI_INPUT_AUTO;
 274                         break;
 275                 }
 276                 /* fall through */
 277         case SB_HW_20:
 278                 chip->capture_format = SB_DSP_LO_INPUT_AUTO;
 279                 break;
 280         case SB_HW_10:
 281                 chip->capture_format = SB_DSP_INPUT;
 282                 break;
 283         default:
 284                 return -EINVAL;
 285         }
 286         if (chip->mode & SB_MODE_CAPTURE_16) {
 287                 format = stereo ? SB_DSP_STEREO_16BIT : SB_DSP_MONO_16BIT;
 288                 dma = chip->dma16;
 289         } else {
 290                 format = stereo ? SB_DSP_STEREO_8BIT : SB_DSP_MONO_8BIT;
 291                 chip->mode |= SB_MODE_CAPTURE_8;
 292                 dma = chip->dma8;
 293         }
 294         size = chip->c_dma_size = snd_pcm_lib_buffer_bytes(substream);
 295         count = chip->c_period_size = snd_pcm_lib_period_bytes(substream);
 296         spin_lock_irqsave(&chip->reg_lock, flags);
 297         snd_sbdsp_command(chip, SB_DSP_SPEAKER_OFF);
 298         if (chip->hardware == SB_HW_JAZZ16)
 299                 snd_sbdsp_command(chip, format);
 300         else if (stereo)
 301                 snd_sbdsp_command(chip, SB_DSP_STEREO_8BIT);
 302         snd_sbdsp_command(chip, SB_DSP_SAMPLE_RATE);
 303         if (stereo) {
 304                 snd_sbdsp_command(chip, 256 - runtime->rate_den / 2);
 305                 spin_lock(&chip->mixer_lock);
 306                 /* save input filter status and turn it off */
 307                 mixreg = snd_sbmixer_read(chip, SB_DSP_CAPTURE_FILT);
 308                 snd_sbmixer_write(chip, SB_DSP_CAPTURE_FILT, mixreg | 0x20);
 309                 spin_unlock(&chip->mixer_lock);
 310                 /* just use force_mode16 for temporary storate... */
 311                 chip->force_mode16 = mixreg;
 312         } else {
 313                 snd_sbdsp_command(chip, 256 - runtime->rate_den);
 314         }
 315         if (chip->capture_format != SB_DSP_INPUT) {
 316                 if (chip->mode & SB_MODE_PLAYBACK_16)
 317                         count /= 2;
 318                 count--;
 319                 snd_sbdsp_command(chip, SB_DSP_BLOCK_SIZE);
 320                 snd_sbdsp_command(chip, count & 0xff);
 321                 snd_sbdsp_command(chip, count >> 8);
 322         }
 323         spin_unlock_irqrestore(&chip->reg_lock, flags);
 324         snd_dma_program(dma, runtime->dma_addr,
 325                         size, DMA_MODE_READ | DMA_AUTOINIT);
 326         return 0;
 327 }
 328 
 329 static int snd_sb8_capture_trigger(struct snd_pcm_substream *substream,
 330                                    int cmd)
 331 {
 332         unsigned long flags;
 333         struct snd_sb *chip = snd_pcm_substream_chip(substream);
 334         unsigned int count;
 335 
 336         spin_lock_irqsave(&chip->reg_lock, flags);
 337         switch (cmd) {
 338         case SNDRV_PCM_TRIGGER_START:
 339                 snd_sbdsp_command(chip, chip->capture_format);
 340                 if (chip->capture_format == SB_DSP_INPUT) {
 341                         count = chip->c_period_size - 1;
 342                         snd_sbdsp_command(chip, count & 0xff);
 343                         snd_sbdsp_command(chip, count >> 8);
 344                 }
 345                 break;
 346         case SNDRV_PCM_TRIGGER_STOP:
 347                 if (chip->capture_format == SB_DSP_HI_INPUT_AUTO) {
 348                         struct snd_pcm_runtime *runtime = substream->runtime;
 349                         snd_sbdsp_reset(chip);
 350                         if (runtime->channels > 1) {
 351                                 /* restore input filter status */
 352                                 spin_lock(&chip->mixer_lock);
 353                                 snd_sbmixer_write(chip, SB_DSP_CAPTURE_FILT, chip->force_mode16);
 354                                 spin_unlock(&chip->mixer_lock);
 355                                 /* set hardware to mono mode */
 356                                 snd_sbdsp_command(chip, SB_DSP_MONO_8BIT);
 357                         }
 358                 } else {
 359                         snd_sbdsp_command(chip, SB_DSP_DMA8_OFF);
 360                 }
 361                 snd_sbdsp_command(chip, SB_DSP_SPEAKER_OFF);
 362         }
 363         spin_unlock_irqrestore(&chip->reg_lock, flags);
 364         return 0;
 365 }
 366 
 367 irqreturn_t snd_sb8dsp_interrupt(struct snd_sb *chip)
 368 {
 369         struct snd_pcm_substream *substream;
 370 
 371         snd_sb_ack_8bit(chip);
 372         switch (chip->mode) {
 373         case SB_MODE_PLAYBACK_16:       /* ok.. playback is active */
 374                 if (chip->hardware != SB_HW_JAZZ16)
 375                         break;
 376                 /* fall through */
 377         case SB_MODE_PLAYBACK_8:
 378                 substream = chip->playback_substream;
 379                 if (chip->playback_format == SB_DSP_OUTPUT)
 380                         snd_sb8_playback_trigger(substream, SNDRV_PCM_TRIGGER_START);
 381                 snd_pcm_period_elapsed(substream);
 382                 break;
 383         case SB_MODE_CAPTURE_16:
 384                 if (chip->hardware != SB_HW_JAZZ16)
 385                         break;
 386                 /* fall through */
 387         case SB_MODE_CAPTURE_8:
 388                 substream = chip->capture_substream;
 389                 if (chip->capture_format == SB_DSP_INPUT)
 390                         snd_sb8_capture_trigger(substream, SNDRV_PCM_TRIGGER_START);
 391                 snd_pcm_period_elapsed(substream);
 392                 break;
 393         }
 394         return IRQ_HANDLED;
 395 }
 396 
 397 static snd_pcm_uframes_t snd_sb8_playback_pointer(struct snd_pcm_substream *substream)
 398 {
 399         struct snd_sb *chip = snd_pcm_substream_chip(substream);
 400         size_t ptr;
 401         int dma;
 402 
 403         if (chip->mode & SB_MODE_PLAYBACK_8)
 404                 dma = chip->dma8;
 405         else if (chip->mode & SB_MODE_PLAYBACK_16)
 406                 dma = chip->dma16;
 407         else
 408                 return 0;
 409         ptr = snd_dma_pointer(dma, chip->p_dma_size);
 410         return bytes_to_frames(substream->runtime, ptr);
 411 }
 412 
 413 static snd_pcm_uframes_t snd_sb8_capture_pointer(struct snd_pcm_substream *substream)
 414 {
 415         struct snd_sb *chip = snd_pcm_substream_chip(substream);
 416         size_t ptr;
 417         int dma;
 418 
 419         if (chip->mode & SB_MODE_CAPTURE_8)
 420                 dma = chip->dma8;
 421         else if (chip->mode & SB_MODE_CAPTURE_16)
 422                 dma = chip->dma16;
 423         else
 424                 return 0;
 425         ptr = snd_dma_pointer(dma, chip->c_dma_size);
 426         return bytes_to_frames(substream->runtime, ptr);
 427 }
 428 
 429 /*
 430 
 431  */
 432 
 433 static const struct snd_pcm_hardware snd_sb8_playback =
 434 {
 435         .info =                 (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
 436                                  SNDRV_PCM_INFO_MMAP_VALID),
 437         .formats =               SNDRV_PCM_FMTBIT_U8,
 438         .rates =                (SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000 |
 439                                  SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_22050),
 440         .rate_min =             4000,
 441         .rate_max =             23000,
 442         .channels_min =         1,
 443         .channels_max =         1,
 444         .buffer_bytes_max =     65536,
 445         .period_bytes_min =     64,
 446         .period_bytes_max =     65536,
 447         .periods_min =          1,
 448         .periods_max =          1024,
 449         .fifo_size =            0,
 450 };
 451 
 452 static const struct snd_pcm_hardware snd_sb8_capture =
 453 {
 454         .info =                 (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
 455                                  SNDRV_PCM_INFO_MMAP_VALID),
 456         .formats =              SNDRV_PCM_FMTBIT_U8,
 457         .rates =                (SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000 |
 458                                  SNDRV_PCM_RATE_11025),
 459         .rate_min =             4000,
 460         .rate_max =             13000,
 461         .channels_min =         1,
 462         .channels_max =         1,
 463         .buffer_bytes_max =     65536,
 464         .period_bytes_min =     64,
 465         .period_bytes_max =     65536,
 466         .periods_min =          1,
 467         .periods_max =          1024,
 468         .fifo_size =            0,
 469 };
 470 
 471 /*
 472  *
 473  */
 474  
 475 static int snd_sb8_open(struct snd_pcm_substream *substream)
 476 {
 477         struct snd_sb *chip = snd_pcm_substream_chip(substream);
 478         struct snd_pcm_runtime *runtime = substream->runtime;
 479         unsigned long flags;
 480 
 481         spin_lock_irqsave(&chip->open_lock, flags);
 482         if (chip->open) {
 483                 spin_unlock_irqrestore(&chip->open_lock, flags);
 484                 return -EAGAIN;
 485         }
 486         chip->open |= SB_OPEN_PCM;
 487         spin_unlock_irqrestore(&chip->open_lock, flags);
 488         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 489                 chip->playback_substream = substream;
 490                 runtime->hw = snd_sb8_playback;
 491         } else {
 492                 chip->capture_substream = substream;
 493                 runtime->hw = snd_sb8_capture;
 494         }
 495         switch (chip->hardware) {
 496         case SB_HW_JAZZ16:
 497                 if (chip->dma16 == 5 || chip->dma16 == 7)
 498                         runtime->hw.formats |= SNDRV_PCM_FMTBIT_S16_LE;
 499                 runtime->hw.rates |= SNDRV_PCM_RATE_8000_48000;
 500                 runtime->hw.rate_min = 4000;
 501                 runtime->hw.rate_max = 50000;
 502                 runtime->hw.channels_max = 2;
 503                 break;
 504         case SB_HW_PRO:
 505                 runtime->hw.rate_max = 44100;
 506                 runtime->hw.channels_max = 2;
 507                 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
 508                                     snd_sb8_hw_constraint_rate_channels, NULL,
 509                                     SNDRV_PCM_HW_PARAM_CHANNELS,
 510                                     SNDRV_PCM_HW_PARAM_RATE, -1);
 511                 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
 512                                      snd_sb8_hw_constraint_channels_rate, NULL,
 513                                      SNDRV_PCM_HW_PARAM_RATE, -1);
 514                 break;
 515         case SB_HW_201:
 516                 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 517                         runtime->hw.rate_max = 44100;
 518                 } else {
 519                         runtime->hw.rate_max = 15000;
 520                 }
 521         default:
 522                 break;
 523         }
 524         snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
 525                                       &hw_constraints_clock);
 526         if (chip->dma8 > 3 || chip->dma16 >= 0) {
 527                 snd_pcm_hw_constraint_step(runtime, 0,
 528                                            SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 2);
 529                 snd_pcm_hw_constraint_step(runtime, 0,
 530                                            SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 2);
 531                 runtime->hw.buffer_bytes_max = 128 * 1024 * 1024;
 532                 runtime->hw.period_bytes_max = 128 * 1024 * 1024;
 533         }
 534         return 0;       
 535 }
 536 
 537 static int snd_sb8_close(struct snd_pcm_substream *substream)
 538 {
 539         unsigned long flags;
 540         struct snd_sb *chip = snd_pcm_substream_chip(substream);
 541 
 542         chip->playback_substream = NULL;
 543         chip->capture_substream = NULL;
 544         spin_lock_irqsave(&chip->open_lock, flags);
 545         chip->open &= ~SB_OPEN_PCM;
 546         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 547                 chip->mode &= ~SB_MODE_PLAYBACK;
 548         else
 549                 chip->mode &= ~SB_MODE_CAPTURE;
 550         spin_unlock_irqrestore(&chip->open_lock, flags);
 551         return 0;
 552 }
 553 
 554 /*
 555  *  Initialization part
 556  */
 557  
 558 static const struct snd_pcm_ops snd_sb8_playback_ops = {
 559         .open =                 snd_sb8_open,
 560         .close =                snd_sb8_close,
 561         .ioctl =                snd_pcm_lib_ioctl,
 562         .hw_params =            snd_sb8_hw_params,
 563         .hw_free =              snd_sb8_hw_free,
 564         .prepare =              snd_sb8_playback_prepare,
 565         .trigger =              snd_sb8_playback_trigger,
 566         .pointer =              snd_sb8_playback_pointer,
 567 };
 568 
 569 static const struct snd_pcm_ops snd_sb8_capture_ops = {
 570         .open =                 snd_sb8_open,
 571         .close =                snd_sb8_close,
 572         .ioctl =                snd_pcm_lib_ioctl,
 573         .hw_params =            snd_sb8_hw_params,
 574         .hw_free =              snd_sb8_hw_free,
 575         .prepare =              snd_sb8_capture_prepare,
 576         .trigger =              snd_sb8_capture_trigger,
 577         .pointer =              snd_sb8_capture_pointer,
 578 };
 579 
 580 int snd_sb8dsp_pcm(struct snd_sb *chip, int device)
 581 {
 582         struct snd_card *card = chip->card;
 583         struct snd_pcm *pcm;
 584         int err;
 585         size_t max_prealloc = 64 * 1024;
 586 
 587         if ((err = snd_pcm_new(card, "SB8 DSP", device, 1, 1, &pcm)) < 0)
 588                 return err;
 589         sprintf(pcm->name, "DSP v%i.%i", chip->version >> 8, chip->version & 0xff);
 590         pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX;
 591         pcm->private_data = chip;
 592 
 593         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_sb8_playback_ops);
 594         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_sb8_capture_ops);
 595 
 596         if (chip->dma8 > 3 || chip->dma16 >= 0)
 597                 max_prealloc = 128 * 1024;
 598         snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
 599                                               card->dev,
 600                                               64*1024, max_prealloc);
 601 
 602         return 0;
 603 }
 604 
 605 EXPORT_SYMBOL(snd_sb8dsp_pcm);
 606 EXPORT_SYMBOL(snd_sb8dsp_interrupt);
 607   /* sb8_midi.c */
 608 EXPORT_SYMBOL(snd_sb8dsp_midi_interrupt);
 609 EXPORT_SYMBOL(snd_sb8dsp_midi);

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