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