1 /* 2 * Driver for Sound Core PDAudioCF soundcards 3 * 4 * PCM part 5 * 6 * Copyright (c) 2003 by Jaroslav Kysela <perex@perex.cz> 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 */ 22 23 #include <linux/slab.h> 24 #include <linux/vmalloc.h> 25 #include <linux/delay.h> 26 #include <sound/core.h> 27 #include <sound/asoundef.h> 28 #include "pdaudiocf.h" 29 30 31 /* 32 * we use a vmalloc'ed (sg-)buffer 33 */ 34 35 /* get the physical page pointer on the given offset */ 36 static struct page *snd_pcm_get_vmalloc_page(struct snd_pcm_substream *subs, unsigned long offset) 37 { 38 void *pageptr = subs->runtime->dma_area + offset; 39 return vmalloc_to_page(pageptr); 40 } 41 42 /* 43 * hw_params callback 44 * NOTE: this may be called not only once per pcm open! 45 */ 46 static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs, size_t size) 47 { 48 struct snd_pcm_runtime *runtime = subs->runtime; 49 if (runtime->dma_area) { 50 if (runtime->dma_bytes >= size) 51 return 0; /* already enough large */ 52 vfree(runtime->dma_area); 53 } 54 runtime->dma_area = vmalloc_32(size); 55 if (! runtime->dma_area) 56 return -ENOMEM; 57 runtime->dma_bytes = size; 58 return 0; 59 } 60 61 /* 62 * hw_free callback 63 * NOTE: this may be called not only once per pcm open! 64 */ 65 static int snd_pcm_free_vmalloc_buffer(struct snd_pcm_substream *subs) 66 { 67 struct snd_pcm_runtime *runtime = subs->runtime; 68 69 vfree(runtime->dma_area); 70 runtime->dma_area = NULL; 71 return 0; 72 } 73 74 /* 75 * clear the SRAM contents 76 */ 77 static int pdacf_pcm_clear_sram(struct snd_pdacf *chip) 78 { 79 int max_loop = 64 * 1024; 80 81 while (inw(chip->port + PDAUDIOCF_REG_RDP) != inw(chip->port + PDAUDIOCF_REG_WDP)) { 82 if (max_loop-- < 0) 83 return -EIO; 84 inw(chip->port + PDAUDIOCF_REG_MD); 85 } 86 return 0; 87 } 88 89 /* 90 * pdacf_pcm_trigger - trigger callback for capture 91 */ 92 static int pdacf_pcm_trigger(struct snd_pcm_substream *subs, int cmd) 93 { 94 struct snd_pdacf *chip = snd_pcm_substream_chip(subs); 95 struct snd_pcm_runtime *runtime = subs->runtime; 96 int inc, ret = 0, rate; 97 unsigned short mask, val, tmp; 98 99 if (chip->chip_status & PDAUDIOCF_STAT_IS_STALE) 100 return -EBUSY; 101 102 switch (cmd) { 103 case SNDRV_PCM_TRIGGER_START: 104 chip->pcm_hwptr = 0; 105 chip->pcm_tdone = 0; 106 /* fall thru */ 107 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 108 case SNDRV_PCM_TRIGGER_RESUME: 109 mask = 0; 110 val = PDAUDIOCF_RECORD; 111 inc = 1; 112 rate = snd_ak4117_check_rate_and_errors(chip->ak4117, AK4117_CHECK_NO_STAT|AK4117_CHECK_NO_RATE); 113 break; 114 case SNDRV_PCM_TRIGGER_STOP: 115 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 116 case SNDRV_PCM_TRIGGER_SUSPEND: 117 mask = PDAUDIOCF_RECORD; 118 val = 0; 119 inc = -1; 120 rate = 0; 121 break; 122 default: 123 return -EINVAL; 124 } 125 spin_lock(&chip->reg_lock); 126 chip->pcm_running += inc; 127 tmp = pdacf_reg_read(chip, PDAUDIOCF_REG_SCR); 128 if (chip->pcm_running) { 129 if ((chip->ak4117->rcs0 & AK4117_UNLCK) || runtime->rate != rate) { 130 chip->pcm_running -= inc; 131 ret = -EIO; 132 goto __end; 133 } 134 } 135 tmp &= ~mask; 136 tmp |= val; 137 pdacf_reg_write(chip, PDAUDIOCF_REG_SCR, tmp); 138 __end: 139 spin_unlock(&chip->reg_lock); 140 snd_ak4117_check_rate_and_errors(chip->ak4117, AK4117_CHECK_NO_RATE); 141 return ret; 142 } 143 144 /* 145 * pdacf_pcm_hw_params - hw_params callback for playback and capture 146 */ 147 static int pdacf_pcm_hw_params(struct snd_pcm_substream *subs, 148 struct snd_pcm_hw_params *hw_params) 149 { 150 return snd_pcm_alloc_vmalloc_buffer(subs, params_buffer_bytes(hw_params)); 151 } 152 153 /* 154 * pdacf_pcm_hw_free - hw_free callback for playback and capture 155 */ 156 static int pdacf_pcm_hw_free(struct snd_pcm_substream *subs) 157 { 158 return snd_pcm_free_vmalloc_buffer(subs); 159 } 160 161 /* 162 * pdacf_pcm_prepare - prepare callback for playback and capture 163 */ 164 static int pdacf_pcm_prepare(struct snd_pcm_substream *subs) 165 { 166 struct snd_pdacf *chip = snd_pcm_substream_chip(subs); 167 struct snd_pcm_runtime *runtime = subs->runtime; 168 u16 val, nval, aval; 169 170 if (chip->chip_status & PDAUDIOCF_STAT_IS_STALE) 171 return -EBUSY; 172 173 chip->pcm_channels = runtime->channels; 174 175 chip->pcm_little = snd_pcm_format_little_endian(runtime->format) > 0; 176 #ifdef SNDRV_LITTLE_ENDIAN 177 chip->pcm_swab = snd_pcm_format_big_endian(runtime->format) > 0; 178 #else 179 chip->pcm_swab = chip->pcm_little; 180 #endif 181 182 if (snd_pcm_format_unsigned(runtime->format)) 183 chip->pcm_xor = 0x80008000; 184 185 if (pdacf_pcm_clear_sram(chip) < 0) 186 return -EIO; 187 188 val = nval = pdacf_reg_read(chip, PDAUDIOCF_REG_SCR); 189 nval &= ~(PDAUDIOCF_DATAFMT0|PDAUDIOCF_DATAFMT1); 190 switch (runtime->format) { 191 case SNDRV_PCM_FORMAT_S16_LE: 192 case SNDRV_PCM_FORMAT_S16_BE: 193 break; 194 default: /* 24-bit */ 195 nval |= PDAUDIOCF_DATAFMT0 | PDAUDIOCF_DATAFMT1; 196 break; 197 } 198 aval = 0; 199 chip->pcm_sample = 4; 200 switch (runtime->format) { 201 case SNDRV_PCM_FORMAT_S16_LE: 202 case SNDRV_PCM_FORMAT_S16_BE: 203 aval = AK4117_DIF_16R; 204 chip->pcm_frame = 2; 205 chip->pcm_sample = 2; 206 break; 207 case SNDRV_PCM_FORMAT_S24_3LE: 208 case SNDRV_PCM_FORMAT_S24_3BE: 209 chip->pcm_sample = 3; 210 /* fall through */ 211 default: /* 24-bit */ 212 aval = AK4117_DIF_24R; 213 chip->pcm_frame = 3; 214 chip->pcm_xor &= 0xffff0000; 215 break; 216 } 217 218 if (val != nval) { 219 snd_ak4117_reg_write(chip->ak4117, AK4117_REG_IO, AK4117_DIF2|AK4117_DIF1|AK4117_DIF0, aval); 220 pdacf_reg_write(chip, PDAUDIOCF_REG_SCR, nval); 221 } 222 223 val = pdacf_reg_read(chip, PDAUDIOCF_REG_IER); 224 val &= ~(PDAUDIOCF_IRQLVLEN1); 225 val |= PDAUDIOCF_IRQLVLEN0; 226 pdacf_reg_write(chip, PDAUDIOCF_REG_IER, val); 227 228 chip->pcm_size = runtime->buffer_size; 229 chip->pcm_period = runtime->period_size; 230 chip->pcm_area = runtime->dma_area; 231 232 return 0; 233 } 234 235 236 /* 237 * capture hw information 238 */ 239 240 static struct snd_pcm_hardware pdacf_pcm_capture_hw = { 241 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | 242 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME | 243 SNDRV_PCM_INFO_MMAP_VALID), 244 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | 245 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE | 246 SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE, 247 .rates = SNDRV_PCM_RATE_32000 | 248 SNDRV_PCM_RATE_44100 | 249 SNDRV_PCM_RATE_48000 | 250 SNDRV_PCM_RATE_88200 | 251 SNDRV_PCM_RATE_96000 | 252 SNDRV_PCM_RATE_176400 | 253 SNDRV_PCM_RATE_192000, 254 .rate_min = 32000, 255 .rate_max = 192000, 256 .channels_min = 1, 257 .channels_max = 2, 258 .buffer_bytes_max = (512*1024), 259 .period_bytes_min = 8*1024, 260 .period_bytes_max = (64*1024), 261 .periods_min = 2, 262 .periods_max = 128, 263 .fifo_size = 0, 264 }; 265 266 267 /* 268 * pdacf_pcm_capture_open - open callback for capture 269 */ 270 static int pdacf_pcm_capture_open(struct snd_pcm_substream *subs) 271 { 272 struct snd_pcm_runtime *runtime = subs->runtime; 273 struct snd_pdacf *chip = snd_pcm_substream_chip(subs); 274 275 if (chip->chip_status & PDAUDIOCF_STAT_IS_STALE) 276 return -EBUSY; 277 278 runtime->hw = pdacf_pcm_capture_hw; 279 runtime->private_data = chip; 280 chip->pcm_substream = subs; 281 282 return 0; 283 } 284 285 /* 286 * pdacf_pcm_capture_close - close callback for capture 287 */ 288 static int pdacf_pcm_capture_close(struct snd_pcm_substream *subs) 289 { 290 struct snd_pdacf *chip = snd_pcm_substream_chip(subs); 291 292 if (!chip) 293 return -EINVAL; 294 pdacf_reinit(chip, 0); 295 chip->pcm_substream = NULL; 296 return 0; 297 } 298 299 300 /* 301 * pdacf_pcm_capture_pointer - pointer callback for capture 302 */ 303 static snd_pcm_uframes_t pdacf_pcm_capture_pointer(struct snd_pcm_substream *subs) 304 { 305 struct snd_pdacf *chip = snd_pcm_substream_chip(subs); 306 return chip->pcm_hwptr; 307 } 308 309 /* 310 * operators for PCM capture 311 */ 312 static struct snd_pcm_ops pdacf_pcm_capture_ops = { 313 .open = pdacf_pcm_capture_open, 314 .close = pdacf_pcm_capture_close, 315 .ioctl = snd_pcm_lib_ioctl, 316 .hw_params = pdacf_pcm_hw_params, 317 .hw_free = pdacf_pcm_hw_free, 318 .prepare = pdacf_pcm_prepare, 319 .trigger = pdacf_pcm_trigger, 320 .pointer = pdacf_pcm_capture_pointer, 321 .page = snd_pcm_get_vmalloc_page, 322 }; 323 324 325 /* 326 * snd_pdacf_pcm_new - create and initialize a pcm 327 */ 328 int snd_pdacf_pcm_new(struct snd_pdacf *chip) 329 { 330 struct snd_pcm *pcm; 331 int err; 332 333 err = snd_pcm_new(chip->card, "PDAudioCF", 0, 0, 1, &pcm); 334 if (err < 0) 335 return err; 336 337 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pdacf_pcm_capture_ops); 338 339 pcm->private_data = chip; 340 pcm->info_flags = 0; 341 strcpy(pcm->name, chip->card->shortname); 342 chip->pcm = pcm; 343 344 err = snd_ak4117_build(chip->ak4117, pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream); 345 if (err < 0) 346 return err; 347 348 return 0; 349 } 350