1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * sh_dac_audio.c - SuperH DAC audio driver for ALSA
5 * Copyright (c) 2009 by Rafael Ignacio Zurita <rizurita@yahoo.com>
7 * Based on sh_dac_audio.c (Copyright (C) 2004, 2005 by Andriy Skulysh)
10 #include <linux/hrtimer.h>
11 #include <linux/interrupt.h>
13 #include <linux/platform_device.h>
14 #include <linux/slab.h>
15 #include <linux/module.h>
16 #include <sound/core.h>
17 #include <sound/initval.h>
18 #include <sound/pcm.h>
19 #include <sound/sh_dac_audio.h>
20 #include <asm/clock.h>
21 #include <asm/hd64461.h>
22 #include <mach/hp6xx.h>
25 MODULE_AUTHOR("Rafael Ignacio Zurita <rizurita@yahoo.com>");
26 MODULE_DESCRIPTION("SuperH DAC audio driver");
27 MODULE_LICENSE("GPL");
29 /* Module Parameters */
30 static int index
= SNDRV_DEFAULT_IDX1
;
31 static char *id
= SNDRV_DEFAULT_STR1
;
32 module_param(index
, int, 0444);
33 MODULE_PARM_DESC(index
, "Index value for SuperH DAC audio.");
34 module_param(id
, charp
, 0444);
35 MODULE_PARM_DESC(id
, "ID string for SuperH DAC audio.");
39 struct snd_card
*card
;
40 struct snd_pcm_substream
*substream
;
41 struct hrtimer hrtimer
;
42 ktime_t wakeups_per_second
;
46 char *data_buffer
, *buffer_begin
, *buffer_end
;
47 int processed
; /* bytes proccesed, to compare with period_size */
49 struct dac_audio_pdata
*pdata
;
53 static void dac_audio_start_timer(struct snd_sh_dac
*chip
)
55 hrtimer_start(&chip
->hrtimer
, chip
->wakeups_per_second
,
59 static void dac_audio_stop_timer(struct snd_sh_dac
*chip
)
61 hrtimer_cancel(&chip
->hrtimer
);
64 static void dac_audio_reset(struct snd_sh_dac
*chip
)
66 dac_audio_stop_timer(chip
);
67 chip
->buffer_begin
= chip
->buffer_end
= chip
->data_buffer
;
72 static void dac_audio_set_rate(struct snd_sh_dac
*chip
)
74 chip
->wakeups_per_second
= 1000000000 / chip
->rate
;
80 static const struct snd_pcm_hardware snd_sh_dac_pcm_hw
= {
81 .info
= (SNDRV_PCM_INFO_MMAP
|
82 SNDRV_PCM_INFO_MMAP_VALID
|
83 SNDRV_PCM_INFO_INTERLEAVED
|
84 SNDRV_PCM_INFO_HALF_DUPLEX
),
85 .formats
= SNDRV_PCM_FMTBIT_U8
,
86 .rates
= SNDRV_PCM_RATE_8000
,
91 .buffer_bytes_max
= (48*1024),
92 .period_bytes_min
= 1,
93 .period_bytes_max
= (48*1024),
98 static int snd_sh_dac_pcm_open(struct snd_pcm_substream
*substream
)
100 struct snd_sh_dac
*chip
= snd_pcm_substream_chip(substream
);
101 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
103 runtime
->hw
= snd_sh_dac_pcm_hw
;
105 chip
->substream
= substream
;
106 chip
->buffer_begin
= chip
->buffer_end
= chip
->data_buffer
;
110 chip
->pdata
->start(chip
->pdata
);
115 static int snd_sh_dac_pcm_close(struct snd_pcm_substream
*substream
)
117 struct snd_sh_dac
*chip
= snd_pcm_substream_chip(substream
);
119 chip
->substream
= NULL
;
121 dac_audio_stop_timer(chip
);
122 chip
->pdata
->stop(chip
->pdata
);
127 static int snd_sh_dac_pcm_prepare(struct snd_pcm_substream
*substream
)
129 struct snd_sh_dac
*chip
= snd_pcm_substream_chip(substream
);
130 struct snd_pcm_runtime
*runtime
= chip
->substream
->runtime
;
132 chip
->buffer_size
= runtime
->buffer_size
;
133 memset(chip
->data_buffer
, 0, chip
->pdata
->buffer_size
);
138 static int snd_sh_dac_pcm_trigger(struct snd_pcm_substream
*substream
, int cmd
)
140 struct snd_sh_dac
*chip
= snd_pcm_substream_chip(substream
);
143 case SNDRV_PCM_TRIGGER_START
:
144 dac_audio_start_timer(chip
);
146 case SNDRV_PCM_TRIGGER_STOP
:
147 chip
->buffer_begin
= chip
->buffer_end
= chip
->data_buffer
;
150 dac_audio_stop_timer(chip
);
159 static int snd_sh_dac_pcm_copy(struct snd_pcm_substream
*substream
,
160 int channel
, unsigned long pos
,
161 struct iov_iter
*src
, unsigned long count
)
163 /* channel is not used (interleaved data) */
164 struct snd_sh_dac
*chip
= snd_pcm_substream_chip(substream
);
166 if (copy_from_iter_toio(chip
->data_buffer
+ pos
, src
, count
))
168 chip
->buffer_end
= chip
->data_buffer
+ pos
+ count
;
172 dac_audio_start_timer(chip
);
178 static int snd_sh_dac_pcm_silence(struct snd_pcm_substream
*substream
,
179 int channel
, unsigned long pos
,
182 /* channel is not used (interleaved data) */
183 struct snd_sh_dac
*chip
= snd_pcm_substream_chip(substream
);
185 memset_io(chip
->data_buffer
+ pos
, 0, count
);
186 chip
->buffer_end
= chip
->data_buffer
+ pos
+ count
;
190 dac_audio_start_timer(chip
);
197 snd_pcm_uframes_t
snd_sh_dac_pcm_pointer(struct snd_pcm_substream
*substream
)
199 struct snd_sh_dac
*chip
= snd_pcm_substream_chip(substream
);
200 int pointer
= chip
->buffer_begin
- chip
->data_buffer
;
206 static const struct snd_pcm_ops snd_sh_dac_pcm_ops
= {
207 .open
= snd_sh_dac_pcm_open
,
208 .close
= snd_sh_dac_pcm_close
,
209 .prepare
= snd_sh_dac_pcm_prepare
,
210 .trigger
= snd_sh_dac_pcm_trigger
,
211 .pointer
= snd_sh_dac_pcm_pointer
,
212 .copy
= snd_sh_dac_pcm_copy
,
213 .fill_silence
= snd_sh_dac_pcm_silence
,
214 .mmap
= snd_pcm_lib_mmap_iomem
,
217 static int snd_sh_dac_pcm(struct snd_sh_dac
*chip
, int device
)
222 /* device should be always 0 for us */
223 err
= snd_pcm_new(chip
->card
, "SH_DAC PCM", device
, 1, 0, &pcm
);
227 pcm
->private_data
= chip
;
228 strcpy(pcm
->name
, "SH_DAC PCM");
229 snd_pcm_set_ops(pcm
, SNDRV_PCM_STREAM_PLAYBACK
, &snd_sh_dac_pcm_ops
);
231 /* buffer size=48K */
232 snd_pcm_set_managed_buffer_all(pcm
, SNDRV_DMA_TYPE_CONTINUOUS
,
233 NULL
, 48 * 1024, 48 * 1024);
237 /* END OF PCM INTERFACE */
240 /* driver .remove -- destructor */
241 static void snd_sh_dac_remove(struct platform_device
*devptr
)
243 snd_card_free(platform_get_drvdata(devptr
));
246 /* free -- it has been defined by create */
247 static int snd_sh_dac_free(struct snd_sh_dac
*chip
)
249 /* release the data */
250 kfree(chip
->data_buffer
);
256 static int snd_sh_dac_dev_free(struct snd_device
*device
)
258 struct snd_sh_dac
*chip
= device
->device_data
;
260 return snd_sh_dac_free(chip
);
263 static enum hrtimer_restart
sh_dac_audio_timer(struct hrtimer
*handle
)
265 struct snd_sh_dac
*chip
= container_of(handle
, struct snd_sh_dac
,
267 struct snd_pcm_runtime
*runtime
= chip
->substream
->runtime
;
268 ssize_t b_ps
= frames_to_bytes(runtime
, runtime
->period_size
);
271 sh_dac_output(*chip
->buffer_begin
, chip
->pdata
->channel
);
272 chip
->buffer_begin
++;
275 if (chip
->processed
>= b_ps
) {
276 chip
->processed
-= b_ps
;
277 snd_pcm_period_elapsed(chip
->substream
);
280 if (chip
->buffer_begin
== (chip
->data_buffer
+
281 chip
->buffer_size
- 1))
282 chip
->buffer_begin
= chip
->data_buffer
;
284 if (chip
->buffer_begin
== chip
->buffer_end
)
290 hrtimer_start(&chip
->hrtimer
, chip
->wakeups_per_second
,
293 return HRTIMER_NORESTART
;
296 /* create -- chip-specific constructor for the cards components */
297 static int snd_sh_dac_create(struct snd_card
*card
,
298 struct platform_device
*devptr
,
299 struct snd_sh_dac
**rchip
)
301 struct snd_sh_dac
*chip
;
304 static const struct snd_device_ops ops
= {
305 .dev_free
= snd_sh_dac_dev_free
,
310 chip
= kzalloc(sizeof(*chip
), GFP_KERNEL
);
316 hrtimer_init(&chip
->hrtimer
, CLOCK_MONOTONIC
, HRTIMER_MODE_REL
);
317 chip
->hrtimer
.function
= sh_dac_audio_timer
;
319 dac_audio_reset(chip
);
321 dac_audio_set_rate(chip
);
323 chip
->pdata
= devptr
->dev
.platform_data
;
325 chip
->data_buffer
= kmalloc(chip
->pdata
->buffer_size
, GFP_KERNEL
);
326 if (chip
->data_buffer
== NULL
) {
331 err
= snd_device_new(card
, SNDRV_DEV_LOWLEVEL
, chip
, &ops
);
333 snd_sh_dac_free(chip
);
342 /* driver .probe -- constructor */
343 static int snd_sh_dac_probe(struct platform_device
*devptr
)
345 struct snd_sh_dac
*chip
;
346 struct snd_card
*card
;
349 err
= snd_card_new(&devptr
->dev
, index
, id
, THIS_MODULE
, 0, &card
);
351 dev_err(&devptr
->dev
, "cannot allocate the card\n");
355 err
= snd_sh_dac_create(card
, devptr
, &chip
);
359 err
= snd_sh_dac_pcm(chip
, 0);
363 strcpy(card
->driver
, "snd_sh_dac");
364 strcpy(card
->shortname
, "SuperH DAC audio driver");
365 dev_info(&devptr
->dev
, "%s %s\n", card
->longname
, card
->shortname
);
367 err
= snd_card_register(card
);
371 dev_info(&devptr
->dev
, "ALSA driver for SuperH DAC audio\n");
373 platform_set_drvdata(devptr
, card
);
382 * "driver" definition
384 static struct platform_driver sh_dac_driver
= {
385 .probe
= snd_sh_dac_probe
,
386 .remove
= snd_sh_dac_remove
,
392 module_platform_driver(sh_dac_driver
);