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