~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/isa/sb/sb8_main.c

Version: ~ [ linux-5.4-rc7 ] ~ [ linux-5.3.11 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.84 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.154 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.201 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.201 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.77 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp