| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * rt5514-spi.c -- RT5514 SPI driver |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Copyright 2015 Realtek Semiconductor Corp. |
|---|
| 5 | 6 | * Author: Oder Chiou <oder_chiou@realtek.com> |
|---|
| 6 | | - * |
|---|
| 7 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 8 | | - * it under the terms of the GNU General Public License version 2 as |
|---|
| 9 | | - * published by the Free Software Foundation. |
|---|
| 10 | 7 | */ |
|---|
| 11 | 8 | |
|---|
| 12 | 9 | #include <linux/module.h> |
|---|
| .. | .. |
|---|
| 91 | 88 | |
|---|
| 92 | 89 | runtime = rt5514_dsp->substream->runtime; |
|---|
| 93 | 90 | period_bytes = snd_pcm_lib_period_bytes(rt5514_dsp->substream); |
|---|
| 91 | + if (!period_bytes) { |
|---|
| 92 | + schedule_delayed_work(&rt5514_dsp->copy_work, 5); |
|---|
| 93 | + goto done; |
|---|
| 94 | + } |
|---|
| 95 | + |
|---|
| 96 | + if (rt5514_dsp->buf_size % period_bytes) |
|---|
| 97 | + rt5514_dsp->buf_size = (rt5514_dsp->buf_size / period_bytes) * |
|---|
| 98 | + period_bytes; |
|---|
| 94 | 99 | |
|---|
| 95 | 100 | if (rt5514_dsp->get_size >= rt5514_dsp->buf_size) { |
|---|
| 96 | 101 | rt5514_spi_burst_read(RT5514_BUFFER_VOICE_WP, (u8 *)&buf, |
|---|
| .. | .. |
|---|
| 149 | 154 | |
|---|
| 150 | 155 | static void rt5514_schedule_copy(struct rt5514_dsp *rt5514_dsp) |
|---|
| 151 | 156 | { |
|---|
| 152 | | - size_t period_bytes; |
|---|
| 153 | 157 | u8 buf[8]; |
|---|
| 154 | 158 | |
|---|
| 155 | 159 | if (!rt5514_dsp->substream) |
|---|
| 156 | 160 | return; |
|---|
| 157 | 161 | |
|---|
| 158 | | - period_bytes = snd_pcm_lib_period_bytes(rt5514_dsp->substream); |
|---|
| 159 | 162 | rt5514_dsp->get_size = 0; |
|---|
| 160 | 163 | |
|---|
| 161 | 164 | /** |
|---|
| .. | .. |
|---|
| 183 | 186 | |
|---|
| 184 | 187 | rt5514_dsp->buf_size = rt5514_dsp->buf_limit - rt5514_dsp->buf_base; |
|---|
| 185 | 188 | |
|---|
| 186 | | - if (rt5514_dsp->buf_size % period_bytes) |
|---|
| 187 | | - rt5514_dsp->buf_size = (rt5514_dsp->buf_size / period_bytes) * |
|---|
| 188 | | - period_bytes; |
|---|
| 189 | | - |
|---|
| 190 | 189 | if (rt5514_dsp->buf_base && rt5514_dsp->buf_limit && |
|---|
| 191 | 190 | rt5514_dsp->buf_rp && rt5514_dsp->buf_size) |
|---|
| 192 | 191 | schedule_delayed_work(&rt5514_dsp->copy_work, 0); |
|---|
| .. | .. |
|---|
| 202 | 201 | } |
|---|
| 203 | 202 | |
|---|
| 204 | 203 | /* PCM for streaming audio from the DSP buffer */ |
|---|
| 205 | | -static int rt5514_spi_pcm_open(struct snd_pcm_substream *substream) |
|---|
| 204 | +static int rt5514_spi_pcm_open(struct snd_soc_component *component, |
|---|
| 205 | + struct snd_pcm_substream *substream) |
|---|
| 206 | 206 | { |
|---|
| 207 | 207 | snd_soc_set_runtime_hwparams(substream, &rt5514_spi_pcm_hardware); |
|---|
| 208 | 208 | |
|---|
| 209 | 209 | return 0; |
|---|
| 210 | 210 | } |
|---|
| 211 | 211 | |
|---|
| 212 | | -static int rt5514_spi_hw_params(struct snd_pcm_substream *substream, |
|---|
| 213 | | - struct snd_pcm_hw_params *hw_params) |
|---|
| 212 | +static int rt5514_spi_hw_params(struct snd_soc_component *component, |
|---|
| 213 | + struct snd_pcm_substream *substream, |
|---|
| 214 | + struct snd_pcm_hw_params *hw_params) |
|---|
| 214 | 215 | { |
|---|
| 215 | | - struct snd_soc_pcm_runtime *rtd = substream->private_data; |
|---|
| 216 | | - struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME); |
|---|
| 217 | 216 | struct rt5514_dsp *rt5514_dsp = |
|---|
| 218 | 217 | snd_soc_component_get_drvdata(component); |
|---|
| 219 | | - int ret; |
|---|
| 220 | 218 | u8 buf[8]; |
|---|
| 221 | 219 | |
|---|
| 222 | 220 | mutex_lock(&rt5514_dsp->dma_lock); |
|---|
| 223 | | - ret = snd_pcm_lib_alloc_vmalloc_buffer(substream, |
|---|
| 224 | | - params_buffer_bytes(hw_params)); |
|---|
| 225 | 221 | rt5514_dsp->substream = substream; |
|---|
| 226 | 222 | rt5514_dsp->dma_offset = 0; |
|---|
| 227 | 223 | |
|---|
| .. | .. |
|---|
| 232 | 228 | |
|---|
| 233 | 229 | mutex_unlock(&rt5514_dsp->dma_lock); |
|---|
| 234 | 230 | |
|---|
| 235 | | - return ret; |
|---|
| 231 | + return 0; |
|---|
| 236 | 232 | } |
|---|
| 237 | 233 | |
|---|
| 238 | | -static int rt5514_spi_hw_free(struct snd_pcm_substream *substream) |
|---|
| 234 | +static int rt5514_spi_hw_free(struct snd_soc_component *component, |
|---|
| 235 | + struct snd_pcm_substream *substream) |
|---|
| 239 | 236 | { |
|---|
| 240 | | - struct snd_soc_pcm_runtime *rtd = substream->private_data; |
|---|
| 241 | | - struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME); |
|---|
| 242 | 237 | struct rt5514_dsp *rt5514_dsp = |
|---|
| 243 | 238 | snd_soc_component_get_drvdata(component); |
|---|
| 244 | 239 | |
|---|
| .. | .. |
|---|
| 248 | 243 | |
|---|
| 249 | 244 | cancel_delayed_work_sync(&rt5514_dsp->copy_work); |
|---|
| 250 | 245 | |
|---|
| 251 | | - return snd_pcm_lib_free_vmalloc_buffer(substream); |
|---|
| 246 | + return 0; |
|---|
| 252 | 247 | } |
|---|
| 253 | 248 | |
|---|
| 254 | 249 | static snd_pcm_uframes_t rt5514_spi_pcm_pointer( |
|---|
| 250 | + struct snd_soc_component *component, |
|---|
| 255 | 251 | struct snd_pcm_substream *substream) |
|---|
| 256 | 252 | { |
|---|
| 257 | 253 | struct snd_pcm_runtime *runtime = substream->runtime; |
|---|
| 258 | | - struct snd_soc_pcm_runtime *rtd = substream->private_data; |
|---|
| 259 | | - struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME); |
|---|
| 260 | 254 | struct rt5514_dsp *rt5514_dsp = |
|---|
| 261 | 255 | snd_soc_component_get_drvdata(component); |
|---|
| 262 | 256 | |
|---|
| 263 | 257 | return bytes_to_frames(runtime, rt5514_dsp->dma_offset); |
|---|
| 264 | 258 | } |
|---|
| 265 | 259 | |
|---|
| 266 | | -static const struct snd_pcm_ops rt5514_spi_pcm_ops = { |
|---|
| 267 | | - .open = rt5514_spi_pcm_open, |
|---|
| 268 | | - .hw_params = rt5514_spi_hw_params, |
|---|
| 269 | | - .hw_free = rt5514_spi_hw_free, |
|---|
| 270 | | - .pointer = rt5514_spi_pcm_pointer, |
|---|
| 271 | | - .page = snd_pcm_lib_get_vmalloc_page, |
|---|
| 272 | | -}; |
|---|
| 273 | 260 | |
|---|
| 274 | 261 | static int rt5514_spi_pcm_probe(struct snd_soc_component *component) |
|---|
| 275 | 262 | { |
|---|
| .. | .. |
|---|
| 302 | 289 | return 0; |
|---|
| 303 | 290 | } |
|---|
| 304 | 291 | |
|---|
| 292 | +static int rt5514_spi_pcm_new(struct snd_soc_component *component, |
|---|
| 293 | + struct snd_soc_pcm_runtime *rtd) |
|---|
| 294 | +{ |
|---|
| 295 | + snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_VMALLOC, |
|---|
| 296 | + NULL, 0, 0); |
|---|
| 297 | + return 0; |
|---|
| 298 | +} |
|---|
| 299 | + |
|---|
| 305 | 300 | static const struct snd_soc_component_driver rt5514_spi_component = { |
|---|
| 306 | | - .name = DRV_NAME, |
|---|
| 307 | | - .probe = rt5514_spi_pcm_probe, |
|---|
| 308 | | - .ops = &rt5514_spi_pcm_ops, |
|---|
| 301 | + .name = DRV_NAME, |
|---|
| 302 | + .probe = rt5514_spi_pcm_probe, |
|---|
| 303 | + .open = rt5514_spi_pcm_open, |
|---|
| 304 | + .hw_params = rt5514_spi_hw_params, |
|---|
| 305 | + .hw_free = rt5514_spi_hw_free, |
|---|
| 306 | + .pointer = rt5514_spi_pcm_pointer, |
|---|
| 307 | + .pcm_construct = rt5514_spi_pcm_new, |
|---|
| 309 | 308 | }; |
|---|
| 310 | 309 | |
|---|
| 311 | 310 | /** |
|---|
| .. | .. |
|---|
| 471 | 470 | |
|---|
| 472 | 471 | static int __maybe_unused rt5514_resume(struct device *dev) |
|---|
| 473 | 472 | { |
|---|
| 474 | | - struct snd_soc_component *component = snd_soc_lookup_component(dev, DRV_NAME); |
|---|
| 475 | | - struct rt5514_dsp *rt5514_dsp = |
|---|
| 476 | | - snd_soc_component_get_drvdata(component); |
|---|
| 473 | + struct rt5514_dsp *rt5514_dsp = dev_get_drvdata(dev); |
|---|
| 477 | 474 | int irq = to_spi_device(dev)->irq; |
|---|
| 478 | 475 | u8 buf[8]; |
|---|
| 479 | 476 | |
|---|