root/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c

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

DEFINITIONS

This source file includes following definitions.
  1. pdacf_pcm_clear_sram
  2. pdacf_pcm_trigger
  3. pdacf_pcm_hw_params
  4. pdacf_pcm_hw_free
  5. pdacf_pcm_prepare
  6. pdacf_pcm_capture_open
  7. pdacf_pcm_capture_close
  8. pdacf_pcm_capture_pointer
  9. snd_pdacf_pcm_new

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * Driver for Sound Core PDAudioCF soundcards
   4  *
   5  * PCM part
   6  *
   7  * Copyright (c) 2003 by Jaroslav Kysela <perex@perex.cz>
   8  */
   9 
  10 #include <linux/delay.h>
  11 #include <sound/core.h>
  12 #include <sound/asoundef.h>
  13 #include "pdaudiocf.h"
  14 
  15 
  16 /*
  17  * clear the SRAM contents
  18  */
  19 static int pdacf_pcm_clear_sram(struct snd_pdacf *chip)
  20 {
  21         int max_loop = 64 * 1024;
  22 
  23         while (inw(chip->port + PDAUDIOCF_REG_RDP) != inw(chip->port + PDAUDIOCF_REG_WDP)) {
  24                 if (max_loop-- < 0)
  25                         return -EIO;
  26                 inw(chip->port + PDAUDIOCF_REG_MD);
  27         }
  28         return 0;
  29 }
  30 
  31 /*
  32  * pdacf_pcm_trigger - trigger callback for capture
  33  */
  34 static int pdacf_pcm_trigger(struct snd_pcm_substream *subs, int cmd)
  35 {
  36         struct snd_pdacf *chip = snd_pcm_substream_chip(subs);
  37         struct snd_pcm_runtime *runtime = subs->runtime;
  38         int inc, ret = 0, rate;
  39         unsigned short mask, val, tmp;
  40 
  41         if (chip->chip_status & PDAUDIOCF_STAT_IS_STALE)
  42                 return -EBUSY;
  43 
  44         switch (cmd) {
  45         case SNDRV_PCM_TRIGGER_START:
  46                 chip->pcm_hwptr = 0;
  47                 chip->pcm_tdone = 0;
  48                 /* fall thru */
  49         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
  50         case SNDRV_PCM_TRIGGER_RESUME:
  51                 mask = 0;
  52                 val = PDAUDIOCF_RECORD;
  53                 inc = 1;
  54                 rate = snd_ak4117_check_rate_and_errors(chip->ak4117, AK4117_CHECK_NO_STAT|AK4117_CHECK_NO_RATE);
  55                 break;
  56         case SNDRV_PCM_TRIGGER_STOP:
  57         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
  58         case SNDRV_PCM_TRIGGER_SUSPEND:
  59                 mask = PDAUDIOCF_RECORD;
  60                 val = 0;
  61                 inc = -1;
  62                 rate = 0;
  63                 break;
  64         default:
  65                 return -EINVAL;
  66         }
  67         mutex_lock(&chip->reg_lock);
  68         chip->pcm_running += inc;
  69         tmp = pdacf_reg_read(chip, PDAUDIOCF_REG_SCR);
  70         if (chip->pcm_running) {
  71                 if ((chip->ak4117->rcs0 & AK4117_UNLCK) || runtime->rate != rate) {
  72                         chip->pcm_running -= inc;
  73                         ret = -EIO;
  74                         goto __end;
  75                 }
  76         }
  77         tmp &= ~mask;
  78         tmp |= val;
  79         pdacf_reg_write(chip, PDAUDIOCF_REG_SCR, tmp);
  80       __end:
  81         mutex_unlock(&chip->reg_lock);
  82         snd_ak4117_check_rate_and_errors(chip->ak4117, AK4117_CHECK_NO_RATE);
  83         return ret;
  84 }
  85 
  86 /*
  87  * pdacf_pcm_hw_params - hw_params callback for playback and capture
  88  */
  89 static int pdacf_pcm_hw_params(struct snd_pcm_substream *subs,
  90                                      struct snd_pcm_hw_params *hw_params)
  91 {
  92         return snd_pcm_lib_alloc_vmalloc_32_buffer
  93                                         (subs, params_buffer_bytes(hw_params));
  94 }
  95 
  96 /*
  97  * pdacf_pcm_hw_free - hw_free callback for playback and capture
  98  */
  99 static int pdacf_pcm_hw_free(struct snd_pcm_substream *subs)
 100 {
 101         return snd_pcm_lib_free_vmalloc_buffer(subs);
 102 }
 103 
 104 /*
 105  * pdacf_pcm_prepare - prepare callback for playback and capture
 106  */
 107 static int pdacf_pcm_prepare(struct snd_pcm_substream *subs)
 108 {
 109         struct snd_pdacf *chip = snd_pcm_substream_chip(subs);
 110         struct snd_pcm_runtime *runtime = subs->runtime;
 111         u16 val, nval, aval;
 112 
 113         if (chip->chip_status & PDAUDIOCF_STAT_IS_STALE)
 114                 return -EBUSY;
 115 
 116         chip->pcm_channels = runtime->channels;
 117 
 118         chip->pcm_little = snd_pcm_format_little_endian(runtime->format) > 0;
 119 #ifdef SNDRV_LITTLE_ENDIAN
 120         chip->pcm_swab = snd_pcm_format_big_endian(runtime->format) > 0;
 121 #else
 122         chip->pcm_swab = chip->pcm_little;
 123 #endif
 124 
 125         if (snd_pcm_format_unsigned(runtime->format))
 126                 chip->pcm_xor = 0x80008000;
 127 
 128         if (pdacf_pcm_clear_sram(chip) < 0)
 129                 return -EIO;
 130         
 131         val = nval = pdacf_reg_read(chip, PDAUDIOCF_REG_SCR);
 132         nval &= ~(PDAUDIOCF_DATAFMT0|PDAUDIOCF_DATAFMT1);
 133         switch (runtime->format) {
 134         case SNDRV_PCM_FORMAT_S16_LE:
 135         case SNDRV_PCM_FORMAT_S16_BE:
 136                 break;
 137         default: /* 24-bit */
 138                 nval |= PDAUDIOCF_DATAFMT0 | PDAUDIOCF_DATAFMT1;
 139                 break;
 140         }
 141         aval = 0;
 142         chip->pcm_sample = 4;
 143         switch (runtime->format) {
 144         case SNDRV_PCM_FORMAT_S16_LE:
 145         case SNDRV_PCM_FORMAT_S16_BE:
 146                 aval = AK4117_DIF_16R;
 147                 chip->pcm_frame = 2;
 148                 chip->pcm_sample = 2;
 149                 break;
 150         case SNDRV_PCM_FORMAT_S24_3LE:
 151         case SNDRV_PCM_FORMAT_S24_3BE:
 152                 chip->pcm_sample = 3;
 153                 /* fall through */
 154         default: /* 24-bit */
 155                 aval = AK4117_DIF_24R;
 156                 chip->pcm_frame = 3;
 157                 chip->pcm_xor &= 0xffff0000;
 158                 break;
 159         }
 160 
 161         if (val != nval) {
 162                 snd_ak4117_reg_write(chip->ak4117, AK4117_REG_IO, AK4117_DIF2|AK4117_DIF1|AK4117_DIF0, aval);
 163                 pdacf_reg_write(chip, PDAUDIOCF_REG_SCR, nval);
 164         }
 165 
 166         val = pdacf_reg_read(chip,  PDAUDIOCF_REG_IER);
 167         val &= ~(PDAUDIOCF_IRQLVLEN1);
 168         val |= PDAUDIOCF_IRQLVLEN0;
 169         pdacf_reg_write(chip, PDAUDIOCF_REG_IER, val);
 170 
 171         chip->pcm_size = runtime->buffer_size;
 172         chip->pcm_period = runtime->period_size;
 173         chip->pcm_area = runtime->dma_area;
 174 
 175         return 0;
 176 }
 177 
 178 
 179 /*
 180  * capture hw information
 181  */
 182 
 183 static const struct snd_pcm_hardware pdacf_pcm_capture_hw = {
 184         .info =                 (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
 185                                  SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME |
 186                                  SNDRV_PCM_INFO_MMAP_VALID |
 187                                  SNDRV_PCM_INFO_BATCH),
 188         .formats =              SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |
 189                                 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE |
 190                                 SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE,
 191         .rates =                SNDRV_PCM_RATE_32000 |
 192                                 SNDRV_PCM_RATE_44100 |
 193                                 SNDRV_PCM_RATE_48000 |
 194                                 SNDRV_PCM_RATE_88200 |
 195                                 SNDRV_PCM_RATE_96000 |
 196                                 SNDRV_PCM_RATE_176400 |
 197                                 SNDRV_PCM_RATE_192000,
 198         .rate_min =             32000,
 199         .rate_max =             192000,
 200         .channels_min =         1,
 201         .channels_max =         2,
 202         .buffer_bytes_max =     (512*1024),
 203         .period_bytes_min =     8*1024,
 204         .period_bytes_max =     (64*1024),
 205         .periods_min =          2,
 206         .periods_max =          128,
 207         .fifo_size =            0,
 208 };
 209 
 210 
 211 /*
 212  * pdacf_pcm_capture_open - open callback for capture
 213  */
 214 static int pdacf_pcm_capture_open(struct snd_pcm_substream *subs)
 215 {
 216         struct snd_pcm_runtime *runtime = subs->runtime;
 217         struct snd_pdacf *chip = snd_pcm_substream_chip(subs);
 218 
 219         if (chip->chip_status & PDAUDIOCF_STAT_IS_STALE)
 220                 return -EBUSY;
 221 
 222         runtime->hw = pdacf_pcm_capture_hw;
 223         runtime->private_data = chip;
 224         chip->pcm_substream = subs;
 225 
 226         return 0;
 227 }
 228 
 229 /*
 230  * pdacf_pcm_capture_close - close callback for capture
 231  */
 232 static int pdacf_pcm_capture_close(struct snd_pcm_substream *subs)
 233 {
 234         struct snd_pdacf *chip = snd_pcm_substream_chip(subs);
 235 
 236         if (!chip)
 237                 return -EINVAL;
 238         pdacf_reinit(chip, 0);
 239         chip->pcm_substream = NULL;
 240         return 0;
 241 }
 242 
 243 
 244 /*
 245  * pdacf_pcm_capture_pointer - pointer callback for capture
 246  */
 247 static snd_pcm_uframes_t pdacf_pcm_capture_pointer(struct snd_pcm_substream *subs)
 248 {
 249         struct snd_pdacf *chip = snd_pcm_substream_chip(subs);
 250         return chip->pcm_hwptr;
 251 }
 252 
 253 /*
 254  * operators for PCM capture
 255  */
 256 static const struct snd_pcm_ops pdacf_pcm_capture_ops = {
 257         .open =         pdacf_pcm_capture_open,
 258         .close =        pdacf_pcm_capture_close,
 259         .ioctl =        snd_pcm_lib_ioctl,
 260         .hw_params =    pdacf_pcm_hw_params,
 261         .hw_free =      pdacf_pcm_hw_free,
 262         .prepare =      pdacf_pcm_prepare,
 263         .trigger =      pdacf_pcm_trigger,
 264         .pointer =      pdacf_pcm_capture_pointer,
 265         .page =         snd_pcm_lib_get_vmalloc_page,
 266 };
 267 
 268 
 269 /*
 270  * snd_pdacf_pcm_new - create and initialize a pcm
 271  */
 272 int snd_pdacf_pcm_new(struct snd_pdacf *chip)
 273 {
 274         struct snd_pcm *pcm;
 275         int err;
 276 
 277         err = snd_pcm_new(chip->card, "PDAudioCF", 0, 0, 1, &pcm);
 278         if (err < 0)
 279                 return err;
 280                 
 281         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pdacf_pcm_capture_ops);
 282 
 283         pcm->private_data = chip;
 284         pcm->info_flags = 0;
 285         pcm->nonatomic = true;
 286         strcpy(pcm->name, chip->card->shortname);
 287         chip->pcm = pcm;
 288         
 289         err = snd_ak4117_build(chip->ak4117, pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream);
 290         if (err < 0)
 291                 return err;
 292 
 293         return 0;
 294 }

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