.. | .. |
---|
| 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 | |
---|