| .. | .. |
|---|
| 44 | 44 | |
|---|
| 45 | 45 | static const struct snd_pcm_hardware stm32_adfsdm_pcm_hw = { |
|---|
| 46 | 46 | .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | |
|---|
| 47 | | - SNDRV_PCM_INFO_PAUSE, |
|---|
| 48 | | - .formats = SNDRV_PCM_FMTBIT_S32_LE, |
|---|
| 49 | | - |
|---|
| 50 | | - .rate_min = 8000, |
|---|
| 51 | | - .rate_max = 32000, |
|---|
| 47 | + SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_PAUSE, |
|---|
| 48 | + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, |
|---|
| 52 | 49 | |
|---|
| 53 | 50 | .channels_min = 1, |
|---|
| 54 | 51 | .channels_max = 1, |
|---|
| .. | .. |
|---|
| 141 | 138 | .capture = { |
|---|
| 142 | 139 | .channels_min = 1, |
|---|
| 143 | 140 | .channels_max = 1, |
|---|
| 144 | | - .formats = SNDRV_PCM_FMTBIT_S32_LE, |
|---|
| 145 | | - .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | |
|---|
| 146 | | - SNDRV_PCM_RATE_32000), |
|---|
| 141 | + .formats = SNDRV_PCM_FMTBIT_S16_LE | |
|---|
| 142 | + SNDRV_PCM_FMTBIT_S32_LE, |
|---|
| 143 | + .rates = SNDRV_PCM_RATE_CONTINUOUS, |
|---|
| 144 | + .rate_min = 8000, |
|---|
| 145 | + .rate_max = 48000, |
|---|
| 147 | 146 | }, |
|---|
| 148 | 147 | .ops = &stm32_adfsdm_dai_ops, |
|---|
| 149 | 148 | }; |
|---|
| .. | .. |
|---|
| 152 | 151 | .name = "stm32_dfsdm_audio", |
|---|
| 153 | 152 | }; |
|---|
| 154 | 153 | |
|---|
| 154 | +static void stm32_memcpy_32to16(void *dest, const void *src, size_t n) |
|---|
| 155 | +{ |
|---|
| 156 | + unsigned int i = 0; |
|---|
| 157 | + u16 *d = (u16 *)dest, *s = (u16 *)src; |
|---|
| 158 | + |
|---|
| 159 | + s++; |
|---|
| 160 | + for (i = n >> 1; i > 0; i--) { |
|---|
| 161 | + *d++ = *s++; |
|---|
| 162 | + s++; |
|---|
| 163 | + } |
|---|
| 164 | +} |
|---|
| 165 | + |
|---|
| 155 | 166 | static int stm32_afsdm_pcm_cb(const void *data, size_t size, void *private) |
|---|
| 156 | 167 | { |
|---|
| 157 | 168 | struct stm32_adfsdm_priv *priv = private; |
|---|
| 158 | | - struct snd_soc_pcm_runtime *rtd = priv->substream->private_data; |
|---|
| 169 | + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(priv->substream); |
|---|
| 159 | 170 | u8 *pcm_buff = priv->pcm_buff; |
|---|
| 160 | 171 | u8 *src_buff = (u8 *)data; |
|---|
| 161 | | - unsigned int buff_size = snd_pcm_lib_buffer_bytes(priv->substream); |
|---|
| 162 | | - unsigned int period_size = snd_pcm_lib_period_bytes(priv->substream); |
|---|
| 163 | 172 | unsigned int old_pos = priv->pos; |
|---|
| 164 | | - unsigned int cur_size = size; |
|---|
| 173 | + size_t buff_size = snd_pcm_lib_buffer_bytes(priv->substream); |
|---|
| 174 | + size_t period_size = snd_pcm_lib_period_bytes(priv->substream); |
|---|
| 175 | + size_t cur_size, src_size = size; |
|---|
| 176 | + snd_pcm_format_t format = priv->substream->runtime->format; |
|---|
| 177 | + |
|---|
| 178 | + if (format == SNDRV_PCM_FORMAT_S16_LE) |
|---|
| 179 | + src_size >>= 1; |
|---|
| 180 | + cur_size = src_size; |
|---|
| 165 | 181 | |
|---|
| 166 | 182 | dev_dbg(rtd->dev, "%s: buff_add :%pK, pos = %d, size = %zu\n", |
|---|
| 167 | | - __func__, &pcm_buff[priv->pos], priv->pos, size); |
|---|
| 183 | + __func__, &pcm_buff[priv->pos], priv->pos, src_size); |
|---|
| 168 | 184 | |
|---|
| 169 | | - if ((priv->pos + size) > buff_size) { |
|---|
| 170 | | - memcpy(&pcm_buff[priv->pos], src_buff, buff_size - priv->pos); |
|---|
| 185 | + if ((priv->pos + src_size) > buff_size) { |
|---|
| 186 | + if (format == SNDRV_PCM_FORMAT_S16_LE) |
|---|
| 187 | + stm32_memcpy_32to16(&pcm_buff[priv->pos], src_buff, |
|---|
| 188 | + buff_size - priv->pos); |
|---|
| 189 | + else |
|---|
| 190 | + memcpy(&pcm_buff[priv->pos], src_buff, |
|---|
| 191 | + buff_size - priv->pos); |
|---|
| 171 | 192 | cur_size -= buff_size - priv->pos; |
|---|
| 172 | 193 | priv->pos = 0; |
|---|
| 173 | 194 | } |
|---|
| 174 | 195 | |
|---|
| 175 | | - memcpy(&pcm_buff[priv->pos], &src_buff[size - cur_size], cur_size); |
|---|
| 196 | + if (format == SNDRV_PCM_FORMAT_S16_LE) |
|---|
| 197 | + stm32_memcpy_32to16(&pcm_buff[priv->pos], |
|---|
| 198 | + &src_buff[src_size - cur_size], cur_size); |
|---|
| 199 | + else |
|---|
| 200 | + memcpy(&pcm_buff[priv->pos], &src_buff[src_size - cur_size], |
|---|
| 201 | + cur_size); |
|---|
| 202 | + |
|---|
| 176 | 203 | priv->pos = (priv->pos + cur_size) % buff_size; |
|---|
| 177 | 204 | |
|---|
| 178 | | - if (cur_size != size || (old_pos && (old_pos % period_size < size))) |
|---|
| 205 | + if (cur_size != src_size || (old_pos && (old_pos % period_size < size))) |
|---|
| 179 | 206 | snd_pcm_period_elapsed(priv->substream); |
|---|
| 180 | 207 | |
|---|
| 181 | 208 | return 0; |
|---|
| 182 | 209 | } |
|---|
| 183 | 210 | |
|---|
| 184 | | -static int stm32_adfsdm_trigger(struct snd_pcm_substream *substream, int cmd) |
|---|
| 211 | +static int stm32_adfsdm_trigger(struct snd_soc_component *component, |
|---|
| 212 | + struct snd_pcm_substream *substream, int cmd) |
|---|
| 185 | 213 | { |
|---|
| 186 | | - struct snd_soc_pcm_runtime *rtd = substream->private_data; |
|---|
| 214 | + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); |
|---|
| 187 | 215 | struct stm32_adfsdm_priv *priv = |
|---|
| 188 | | - snd_soc_dai_get_drvdata(rtd->cpu_dai); |
|---|
| 216 | + snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); |
|---|
| 189 | 217 | |
|---|
| 190 | 218 | switch (cmd) { |
|---|
| 191 | 219 | case SNDRV_PCM_TRIGGER_START: |
|---|
| .. | .. |
|---|
| 201 | 229 | return -EINVAL; |
|---|
| 202 | 230 | } |
|---|
| 203 | 231 | |
|---|
| 204 | | -static int stm32_adfsdm_pcm_open(struct snd_pcm_substream *substream) |
|---|
| 232 | +static int stm32_adfsdm_pcm_open(struct snd_soc_component *component, |
|---|
| 233 | + struct snd_pcm_substream *substream) |
|---|
| 205 | 234 | { |
|---|
| 206 | | - struct snd_soc_pcm_runtime *rtd = substream->private_data; |
|---|
| 207 | | - struct stm32_adfsdm_priv *priv = snd_soc_dai_get_drvdata(rtd->cpu_dai); |
|---|
| 235 | + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); |
|---|
| 236 | + struct stm32_adfsdm_priv *priv = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); |
|---|
| 208 | 237 | int ret; |
|---|
| 209 | 238 | |
|---|
| 210 | 239 | ret = snd_soc_set_runtime_hwparams(substream, &stm32_adfsdm_pcm_hw); |
|---|
| .. | .. |
|---|
| 214 | 243 | return ret; |
|---|
| 215 | 244 | } |
|---|
| 216 | 245 | |
|---|
| 217 | | -static int stm32_adfsdm_pcm_close(struct snd_pcm_substream *substream) |
|---|
| 246 | +static int stm32_adfsdm_pcm_close(struct snd_soc_component *component, |
|---|
| 247 | + struct snd_pcm_substream *substream) |
|---|
| 218 | 248 | { |
|---|
| 219 | | - struct snd_soc_pcm_runtime *rtd = substream->private_data; |
|---|
| 249 | + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); |
|---|
| 220 | 250 | struct stm32_adfsdm_priv *priv = |
|---|
| 221 | | - snd_soc_dai_get_drvdata(rtd->cpu_dai); |
|---|
| 251 | + snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); |
|---|
| 222 | 252 | |
|---|
| 223 | | - snd_pcm_lib_free_pages(substream); |
|---|
| 224 | 253 | priv->substream = NULL; |
|---|
| 225 | 254 | |
|---|
| 226 | 255 | return 0; |
|---|
| 227 | 256 | } |
|---|
| 228 | 257 | |
|---|
| 229 | 258 | static snd_pcm_uframes_t stm32_adfsdm_pcm_pointer( |
|---|
| 259 | + struct snd_soc_component *component, |
|---|
| 230 | 260 | struct snd_pcm_substream *substream) |
|---|
| 231 | 261 | { |
|---|
| 232 | | - struct snd_soc_pcm_runtime *rtd = substream->private_data; |
|---|
| 262 | + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); |
|---|
| 233 | 263 | struct stm32_adfsdm_priv *priv = |
|---|
| 234 | | - snd_soc_dai_get_drvdata(rtd->cpu_dai); |
|---|
| 264 | + snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); |
|---|
| 235 | 265 | |
|---|
| 236 | 266 | return bytes_to_frames(substream->runtime, priv->pos); |
|---|
| 237 | 267 | } |
|---|
| 238 | 268 | |
|---|
| 239 | | -static int stm32_adfsdm_pcm_hw_params(struct snd_pcm_substream *substream, |
|---|
| 269 | +static int stm32_adfsdm_pcm_hw_params(struct snd_soc_component *component, |
|---|
| 270 | + struct snd_pcm_substream *substream, |
|---|
| 240 | 271 | struct snd_pcm_hw_params *params) |
|---|
| 241 | 272 | { |
|---|
| 242 | | - struct snd_soc_pcm_runtime *rtd = substream->private_data; |
|---|
| 273 | + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); |
|---|
| 243 | 274 | struct stm32_adfsdm_priv *priv = |
|---|
| 244 | | - snd_soc_dai_get_drvdata(rtd->cpu_dai); |
|---|
| 245 | | - int ret; |
|---|
| 275 | + snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); |
|---|
| 246 | 276 | |
|---|
| 247 | | - ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); |
|---|
| 248 | | - if (ret < 0) |
|---|
| 249 | | - return ret; |
|---|
| 250 | 277 | priv->pcm_buff = substream->runtime->dma_area; |
|---|
| 251 | 278 | |
|---|
| 252 | 279 | return iio_channel_cb_set_buffer_watermark(priv->iio_cb, |
|---|
| 253 | 280 | params_period_size(params)); |
|---|
| 254 | 281 | } |
|---|
| 255 | 282 | |
|---|
| 256 | | -static int stm32_adfsdm_pcm_hw_free(struct snd_pcm_substream *substream) |
|---|
| 257 | | -{ |
|---|
| 258 | | - snd_pcm_lib_free_pages(substream); |
|---|
| 259 | | - |
|---|
| 260 | | - return 0; |
|---|
| 261 | | -} |
|---|
| 262 | | - |
|---|
| 263 | | -static struct snd_pcm_ops stm32_adfsdm_pcm_ops = { |
|---|
| 264 | | - .open = stm32_adfsdm_pcm_open, |
|---|
| 265 | | - .close = stm32_adfsdm_pcm_close, |
|---|
| 266 | | - .hw_params = stm32_adfsdm_pcm_hw_params, |
|---|
| 267 | | - .hw_free = stm32_adfsdm_pcm_hw_free, |
|---|
| 268 | | - .trigger = stm32_adfsdm_trigger, |
|---|
| 269 | | - .pointer = stm32_adfsdm_pcm_pointer, |
|---|
| 270 | | -}; |
|---|
| 271 | | - |
|---|
| 272 | | -static int stm32_adfsdm_pcm_new(struct snd_soc_pcm_runtime *rtd) |
|---|
| 283 | +static int stm32_adfsdm_pcm_new(struct snd_soc_component *component, |
|---|
| 284 | + struct snd_soc_pcm_runtime *rtd) |
|---|
| 273 | 285 | { |
|---|
| 274 | 286 | struct snd_pcm *pcm = rtd->pcm; |
|---|
| 275 | 287 | struct stm32_adfsdm_priv *priv = |
|---|
| 276 | | - snd_soc_dai_get_drvdata(rtd->cpu_dai); |
|---|
| 288 | + snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); |
|---|
| 277 | 289 | unsigned int size = DFSDM_MAX_PERIODS * DFSDM_MAX_PERIOD_SIZE; |
|---|
| 278 | 290 | |
|---|
| 279 | | - return snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, |
|---|
| 280 | | - priv->dev, size, size); |
|---|
| 281 | | -} |
|---|
| 282 | | - |
|---|
| 283 | | -static void stm32_adfsdm_pcm_free(struct snd_pcm *pcm) |
|---|
| 284 | | -{ |
|---|
| 285 | | - struct snd_pcm_substream *substream; |
|---|
| 286 | | - |
|---|
| 287 | | - substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; |
|---|
| 288 | | - if (substream) |
|---|
| 289 | | - snd_pcm_lib_preallocate_free_for_all(pcm); |
|---|
| 291 | + snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, |
|---|
| 292 | + priv->dev, size, size); |
|---|
| 293 | + return 0; |
|---|
| 290 | 294 | } |
|---|
| 291 | 295 | |
|---|
| 292 | 296 | static struct snd_soc_component_driver stm32_adfsdm_soc_platform = { |
|---|
| 293 | | - .ops = &stm32_adfsdm_pcm_ops, |
|---|
| 294 | | - .pcm_new = stm32_adfsdm_pcm_new, |
|---|
| 295 | | - .pcm_free = stm32_adfsdm_pcm_free, |
|---|
| 297 | + .open = stm32_adfsdm_pcm_open, |
|---|
| 298 | + .close = stm32_adfsdm_pcm_close, |
|---|
| 299 | + .hw_params = stm32_adfsdm_pcm_hw_params, |
|---|
| 300 | + .trigger = stm32_adfsdm_trigger, |
|---|
| 301 | + .pointer = stm32_adfsdm_pcm_pointer, |
|---|
| 302 | + .pcm_construct = stm32_adfsdm_pcm_new, |
|---|
| 296 | 303 | }; |
|---|
| 297 | 304 | |
|---|
| 298 | 305 | static const struct of_device_id stm32_adfsdm_of_match[] = { |
|---|
| .. | .. |
|---|
| 335 | 342 | component = devm_kzalloc(&pdev->dev, sizeof(*component), GFP_KERNEL); |
|---|
| 336 | 343 | if (!component) |
|---|
| 337 | 344 | return -ENOMEM; |
|---|
| 345 | + |
|---|
| 346 | + ret = snd_soc_component_initialize(component, |
|---|
| 347 | + &stm32_adfsdm_soc_platform, |
|---|
| 348 | + &pdev->dev); |
|---|
| 349 | + if (ret < 0) |
|---|
| 350 | + return ret; |
|---|
| 338 | 351 | #ifdef CONFIG_DEBUG_FS |
|---|
| 339 | 352 | component->debugfs_prefix = "pcm"; |
|---|
| 340 | 353 | #endif |
|---|
| 341 | 354 | |
|---|
| 342 | | - ret = snd_soc_add_component(&pdev->dev, component, |
|---|
| 343 | | - &stm32_adfsdm_soc_platform, NULL, 0); |
|---|
| 355 | + ret = snd_soc_add_component(component, NULL, 0); |
|---|
| 344 | 356 | if (ret < 0) |
|---|
| 345 | 357 | dev_err(&pdev->dev, "%s: Failed to register PCM platform\n", |
|---|
| 346 | 358 | __func__); |
|---|