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