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 fallthrough; 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 scoped_guard(mutex, &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 break; 75 } 76 } 77 tmp &= ~mask; 78 tmp |= val; 79 pdacf_reg_write(chip, PDAUDIOCF_REG_SCR, tmp); 80 } 81 snd_ak4117_check_rate_and_errors(chip->ak4117, AK4117_CHECK_NO_RATE); 82 return ret; 83 } 84 85 /* 86 * pdacf_pcm_prepare - prepare callback for playback and capture 87 */ 88 static int pdacf_pcm_prepare(struct snd_pcm_substream *subs) 89 { 90 struct snd_pdacf *chip = snd_pcm_substream_chip(subs); 91 struct snd_pcm_runtime *runtime = subs->runtime; 92 u16 val, nval, aval; 93 94 if (chip->chip_status & PDAUDIOCF_STAT_IS_STALE) 95 return -EBUSY; 96 97 chip->pcm_channels = runtime->channels; 98 99 chip->pcm_little = snd_pcm_format_little_endian(runtime->format) > 0; 100 #ifdef SNDRV_LITTLE_ENDIAN 101 chip->pcm_swab = snd_pcm_format_big_endian(runtime->format) > 0; 102 #else 103 chip->pcm_swab = chip->pcm_little; 104 #endif 105 106 if (snd_pcm_format_unsigned(runtime->format)) 107 chip->pcm_xor = 0x80008000; 108 109 if (pdacf_pcm_clear_sram(chip) < 0) 110 return -EIO; 111 112 val = nval = pdacf_reg_read(chip, PDAUDIOCF_REG_SCR); 113 nval &= ~(PDAUDIOCF_DATAFMT0|PDAUDIOCF_DATAFMT1); 114 switch (runtime->format) { 115 case SNDRV_PCM_FORMAT_S16_LE: 116 case SNDRV_PCM_FORMAT_S16_BE: 117 break; 118 default: /* 24-bit */ 119 nval |= PDAUDIOCF_DATAFMT0 | PDAUDIOCF_DATAFMT1; 120 break; 121 } 122 aval = 0; 123 chip->pcm_sample = 4; 124 switch (runtime->format) { 125 case SNDRV_PCM_FORMAT_S16_LE: 126 case SNDRV_PCM_FORMAT_S16_BE: 127 aval = AK4117_DIF_16R; 128 chip->pcm_frame = 2; 129 chip->pcm_sample = 2; 130 break; 131 case SNDRV_PCM_FORMAT_S24_3LE: 132 case SNDRV_PCM_FORMAT_S24_3BE: 133 chip->pcm_sample = 3; 134 fallthrough; 135 default: /* 24-bit */ 136 aval = AK4117_DIF_24R; 137 chip->pcm_frame = 3; 138 chip->pcm_xor &= 0xffff0000; 139 break; 140 } 141 142 if (val != nval) { 143 snd_ak4117_reg_write(chip->ak4117, AK4117_REG_IO, AK4117_DIF2|AK4117_DIF1|AK4117_DIF0, aval); 144 pdacf_reg_write(chip, PDAUDIOCF_REG_SCR, nval); 145 } 146 147 val = pdacf_reg_read(chip, PDAUDIOCF_REG_IER); 148 val &= ~(PDAUDIOCF_IRQLVLEN1); 149 val |= PDAUDIOCF_IRQLVLEN0; 150 pdacf_reg_write(chip, PDAUDIOCF_REG_IER, val); 151 152 chip->pcm_size = runtime->buffer_size; 153 chip->pcm_period = runtime->period_size; 154 chip->pcm_area = runtime->dma_area; 155 156 return 0; 157 } 158 159 160 /* 161 * capture hw information 162 */ 163 164 static const struct snd_pcm_hardware pdacf_pcm_capture_hw = { 165 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | 166 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME | 167 SNDRV_PCM_INFO_MMAP_VALID | 168 SNDRV_PCM_INFO_BATCH), 169 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | 170 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE | 171 SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE, 172 .rates = SNDRV_PCM_RATE_32000 | 173 SNDRV_PCM_RATE_44100 | 174 SNDRV_PCM_RATE_48000 | 175 SNDRV_PCM_RATE_88200 | 176 SNDRV_PCM_RATE_96000 | 177 SNDRV_PCM_RATE_176400 | 178 SNDRV_PCM_RATE_192000, 179 .rate_min = 32000, 180 .rate_max = 192000, 181 .channels_min = 1, 182 .channels_max = 2, 183 .buffer_bytes_max = (512*1024), 184 .period_bytes_min = 8*1024, 185 .period_bytes_max = (64*1024), 186 .periods_min = 2, 187 .periods_max = 128, 188 .fifo_size = 0, 189 }; 190 191 192 /* 193 * pdacf_pcm_capture_open - open callback for capture 194 */ 195 static int pdacf_pcm_capture_open(struct snd_pcm_substream *subs) 196 { 197 struct snd_pcm_runtime *runtime = subs->runtime; 198 struct snd_pdacf *chip = snd_pcm_substream_chip(subs); 199 200 if (chip->chip_status & PDAUDIOCF_STAT_IS_STALE) 201 return -EBUSY; 202 203 runtime->hw = pdacf_pcm_capture_hw; 204 runtime->private_data = chip; 205 chip->pcm_substream = subs; 206 207 return 0; 208 } 209 210 /* 211 * pdacf_pcm_capture_close - close callback for capture 212 */ 213 static int pdacf_pcm_capture_close(struct snd_pcm_substream *subs) 214 { 215 struct snd_pdacf *chip = snd_pcm_substream_chip(subs); 216 217 if (!chip) 218 return -EINVAL; 219 pdacf_reinit(chip, 0); 220 chip->pcm_substream = NULL; 221 return 0; 222 } 223 224 225 /* 226 * pdacf_pcm_capture_pointer - pointer callback for capture 227 */ 228 static snd_pcm_uframes_t pdacf_pcm_capture_pointer(struct snd_pcm_substream *subs) 229 { 230 struct snd_pdacf *chip = snd_pcm_substream_chip(subs); 231 return chip->pcm_hwptr; 232 } 233 234 /* 235 * operators for PCM capture 236 */ 237 static const struct snd_pcm_ops pdacf_pcm_capture_ops = { 238 .open = pdacf_pcm_capture_open, 239 .close = pdacf_pcm_capture_close, 240 .prepare = pdacf_pcm_prepare, 241 .trigger = pdacf_pcm_trigger, 242 .pointer = pdacf_pcm_capture_pointer, 243 }; 244 245 246 /* 247 * snd_pdacf_pcm_new - create and initialize a pcm 248 */ 249 int snd_pdacf_pcm_new(struct snd_pdacf *chip) 250 { 251 struct snd_pcm *pcm; 252 int err; 253 254 err = snd_pcm_new(chip->card, "PDAudioCF", 0, 0, 1, &pcm); 255 if (err < 0) 256 return err; 257 258 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pdacf_pcm_capture_ops); 259 snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC, NULL, 260 0, 0); 261 262 pcm->private_data = chip; 263 pcm->info_flags = 0; 264 pcm->nonatomic = true; 265 strscpy(pcm->name, chip->card->shortname); 266 chip->pcm = pcm; 267 268 err = snd_ak4117_build(chip->ak4117, pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream); 269 if (err < 0) 270 return err; 271 272 return 0; 273 } 274