Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/sound/sh/sh_dac_audio.c
10814 views
1
/*
2
* sh_dac_audio.c - SuperH DAC audio driver for ALSA
3
*
4
* Copyright (c) 2009 by Rafael Ignacio Zurita <[email protected]>
5
*
6
*
7
* Based on sh_dac_audio.c (Copyright (C) 2004, 2005 by Andriy Skulysh)
8
*
9
* This program is free software; you can redistribute it and/or modify
10
* it under the terms of the GNU General Public License as published by
11
* the Free Software Foundation; either version 2 of the License, or
12
* (at your option) any later version.
13
*
14
* This program is distributed in the hope that it will be useful,
15
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
* GNU General Public License for more details.
18
*
19
* You should have received a copy of the GNU General Public License
20
* along with this program; if not, write to the Free Software
21
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
*
23
*/
24
25
#include <linux/hrtimer.h>
26
#include <linux/interrupt.h>
27
#include <linux/io.h>
28
#include <linux/platform_device.h>
29
#include <linux/slab.h>
30
#include <sound/core.h>
31
#include <sound/initval.h>
32
#include <sound/pcm.h>
33
#include <sound/sh_dac_audio.h>
34
#include <asm/clock.h>
35
#include <asm/hd64461.h>
36
#include <mach/hp6xx.h>
37
#include <cpu/dac.h>
38
39
MODULE_AUTHOR("Rafael Ignacio Zurita <[email protected]>");
40
MODULE_DESCRIPTION("SuperH DAC audio driver");
41
MODULE_LICENSE("GPL");
42
MODULE_SUPPORTED_DEVICE("{{SuperH DAC audio support}}");
43
44
/* Module Parameters */
45
static int index = SNDRV_DEFAULT_IDX1;
46
static char *id = SNDRV_DEFAULT_STR1;
47
module_param(index, int, 0444);
48
MODULE_PARM_DESC(index, "Index value for SuperH DAC audio.");
49
module_param(id, charp, 0444);
50
MODULE_PARM_DESC(id, "ID string for SuperH DAC audio.");
51
52
/* main struct */
53
struct snd_sh_dac {
54
struct snd_card *card;
55
struct snd_pcm_substream *substream;
56
struct hrtimer hrtimer;
57
ktime_t wakeups_per_second;
58
59
int rate;
60
int empty;
61
char *data_buffer, *buffer_begin, *buffer_end;
62
int processed; /* bytes proccesed, to compare with period_size */
63
int buffer_size;
64
struct dac_audio_pdata *pdata;
65
};
66
67
68
static void dac_audio_start_timer(struct snd_sh_dac *chip)
69
{
70
hrtimer_start(&chip->hrtimer, chip->wakeups_per_second,
71
HRTIMER_MODE_REL);
72
}
73
74
static void dac_audio_stop_timer(struct snd_sh_dac *chip)
75
{
76
hrtimer_cancel(&chip->hrtimer);
77
}
78
79
static void dac_audio_reset(struct snd_sh_dac *chip)
80
{
81
dac_audio_stop_timer(chip);
82
chip->buffer_begin = chip->buffer_end = chip->data_buffer;
83
chip->processed = 0;
84
chip->empty = 1;
85
}
86
87
static void dac_audio_set_rate(struct snd_sh_dac *chip)
88
{
89
chip->wakeups_per_second = ktime_set(0, 1000000000 / chip->rate);
90
}
91
92
93
/* PCM INTERFACE */
94
95
static struct snd_pcm_hardware snd_sh_dac_pcm_hw = {
96
.info = (SNDRV_PCM_INFO_MMAP |
97
SNDRV_PCM_INFO_MMAP_VALID |
98
SNDRV_PCM_INFO_INTERLEAVED |
99
SNDRV_PCM_INFO_HALF_DUPLEX),
100
.formats = SNDRV_PCM_FMTBIT_U8,
101
.rates = SNDRV_PCM_RATE_8000,
102
.rate_min = 8000,
103
.rate_max = 8000,
104
.channels_min = 1,
105
.channels_max = 1,
106
.buffer_bytes_max = (48*1024),
107
.period_bytes_min = 1,
108
.period_bytes_max = (48*1024),
109
.periods_min = 1,
110
.periods_max = 1024,
111
};
112
113
static int snd_sh_dac_pcm_open(struct snd_pcm_substream *substream)
114
{
115
struct snd_sh_dac *chip = snd_pcm_substream_chip(substream);
116
struct snd_pcm_runtime *runtime = substream->runtime;
117
118
runtime->hw = snd_sh_dac_pcm_hw;
119
120
chip->substream = substream;
121
chip->buffer_begin = chip->buffer_end = chip->data_buffer;
122
chip->processed = 0;
123
chip->empty = 1;
124
125
chip->pdata->start(chip->pdata);
126
127
return 0;
128
}
129
130
static int snd_sh_dac_pcm_close(struct snd_pcm_substream *substream)
131
{
132
struct snd_sh_dac *chip = snd_pcm_substream_chip(substream);
133
134
chip->substream = NULL;
135
136
dac_audio_stop_timer(chip);
137
chip->pdata->stop(chip->pdata);
138
139
return 0;
140
}
141
142
static int snd_sh_dac_pcm_hw_params(struct snd_pcm_substream *substream,
143
struct snd_pcm_hw_params *hw_params)
144
{
145
return snd_pcm_lib_malloc_pages(substream,
146
params_buffer_bytes(hw_params));
147
}
148
149
static int snd_sh_dac_pcm_hw_free(struct snd_pcm_substream *substream)
150
{
151
return snd_pcm_lib_free_pages(substream);
152
}
153
154
static int snd_sh_dac_pcm_prepare(struct snd_pcm_substream *substream)
155
{
156
struct snd_sh_dac *chip = snd_pcm_substream_chip(substream);
157
struct snd_pcm_runtime *runtime = chip->substream->runtime;
158
159
chip->buffer_size = runtime->buffer_size;
160
memset(chip->data_buffer, 0, chip->pdata->buffer_size);
161
162
return 0;
163
}
164
165
static int snd_sh_dac_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
166
{
167
struct snd_sh_dac *chip = snd_pcm_substream_chip(substream);
168
169
switch (cmd) {
170
case SNDRV_PCM_TRIGGER_START:
171
dac_audio_start_timer(chip);
172
break;
173
case SNDRV_PCM_TRIGGER_STOP:
174
chip->buffer_begin = chip->buffer_end = chip->data_buffer;
175
chip->processed = 0;
176
chip->empty = 1;
177
dac_audio_stop_timer(chip);
178
break;
179
default:
180
return -EINVAL;
181
}
182
183
return 0;
184
}
185
186
static int snd_sh_dac_pcm_copy(struct snd_pcm_substream *substream, int channel,
187
snd_pcm_uframes_t pos, void __user *src, snd_pcm_uframes_t count)
188
{
189
/* channel is not used (interleaved data) */
190
struct snd_sh_dac *chip = snd_pcm_substream_chip(substream);
191
struct snd_pcm_runtime *runtime = substream->runtime;
192
ssize_t b_count = frames_to_bytes(runtime , count);
193
ssize_t b_pos = frames_to_bytes(runtime , pos);
194
195
if (count < 0)
196
return -EINVAL;
197
198
if (!count)
199
return 0;
200
201
memcpy_toio(chip->data_buffer + b_pos, src, b_count);
202
chip->buffer_end = chip->data_buffer + b_pos + b_count;
203
204
if (chip->empty) {
205
chip->empty = 0;
206
dac_audio_start_timer(chip);
207
}
208
209
return 0;
210
}
211
212
static int snd_sh_dac_pcm_silence(struct snd_pcm_substream *substream,
213
int channel, snd_pcm_uframes_t pos,
214
snd_pcm_uframes_t count)
215
{
216
/* channel is not used (interleaved data) */
217
struct snd_sh_dac *chip = snd_pcm_substream_chip(substream);
218
struct snd_pcm_runtime *runtime = substream->runtime;
219
ssize_t b_count = frames_to_bytes(runtime , count);
220
ssize_t b_pos = frames_to_bytes(runtime , pos);
221
222
if (count < 0)
223
return -EINVAL;
224
225
if (!count)
226
return 0;
227
228
memset_io(chip->data_buffer + b_pos, 0, b_count);
229
chip->buffer_end = chip->data_buffer + b_pos + b_count;
230
231
if (chip->empty) {
232
chip->empty = 0;
233
dac_audio_start_timer(chip);
234
}
235
236
return 0;
237
}
238
239
static
240
snd_pcm_uframes_t snd_sh_dac_pcm_pointer(struct snd_pcm_substream *substream)
241
{
242
struct snd_sh_dac *chip = snd_pcm_substream_chip(substream);
243
int pointer = chip->buffer_begin - chip->data_buffer;
244
245
return pointer;
246
}
247
248
/* pcm ops */
249
static struct snd_pcm_ops snd_sh_dac_pcm_ops = {
250
.open = snd_sh_dac_pcm_open,
251
.close = snd_sh_dac_pcm_close,
252
.ioctl = snd_pcm_lib_ioctl,
253
.hw_params = snd_sh_dac_pcm_hw_params,
254
.hw_free = snd_sh_dac_pcm_hw_free,
255
.prepare = snd_sh_dac_pcm_prepare,
256
.trigger = snd_sh_dac_pcm_trigger,
257
.pointer = snd_sh_dac_pcm_pointer,
258
.copy = snd_sh_dac_pcm_copy,
259
.silence = snd_sh_dac_pcm_silence,
260
.mmap = snd_pcm_lib_mmap_iomem,
261
};
262
263
static int __devinit snd_sh_dac_pcm(struct snd_sh_dac *chip, int device)
264
{
265
int err;
266
struct snd_pcm *pcm;
267
268
/* device should be always 0 for us */
269
err = snd_pcm_new(chip->card, "SH_DAC PCM", device, 1, 0, &pcm);
270
if (err < 0)
271
return err;
272
273
pcm->private_data = chip;
274
strcpy(pcm->name, "SH_DAC PCM");
275
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_sh_dac_pcm_ops);
276
277
/* buffer size=48K */
278
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
279
snd_dma_continuous_data(GFP_KERNEL),
280
48 * 1024,
281
48 * 1024);
282
283
return 0;
284
}
285
/* END OF PCM INTERFACE */
286
287
288
/* driver .remove -- destructor */
289
static int snd_sh_dac_remove(struct platform_device *devptr)
290
{
291
snd_card_free(platform_get_drvdata(devptr));
292
platform_set_drvdata(devptr, NULL);
293
294
return 0;
295
}
296
297
/* free -- it has been defined by create */
298
static int snd_sh_dac_free(struct snd_sh_dac *chip)
299
{
300
/* release the data */
301
kfree(chip->data_buffer);
302
kfree(chip);
303
304
return 0;
305
}
306
307
static int snd_sh_dac_dev_free(struct snd_device *device)
308
{
309
struct snd_sh_dac *chip = device->device_data;
310
311
return snd_sh_dac_free(chip);
312
}
313
314
static enum hrtimer_restart sh_dac_audio_timer(struct hrtimer *handle)
315
{
316
struct snd_sh_dac *chip = container_of(handle, struct snd_sh_dac,
317
hrtimer);
318
struct snd_pcm_runtime *runtime = chip->substream->runtime;
319
ssize_t b_ps = frames_to_bytes(runtime, runtime->period_size);
320
321
if (!chip->empty) {
322
sh_dac_output(*chip->buffer_begin, chip->pdata->channel);
323
chip->buffer_begin++;
324
325
chip->processed++;
326
if (chip->processed >= b_ps) {
327
chip->processed -= b_ps;
328
snd_pcm_period_elapsed(chip->substream);
329
}
330
331
if (chip->buffer_begin == (chip->data_buffer +
332
chip->buffer_size - 1))
333
chip->buffer_begin = chip->data_buffer;
334
335
if (chip->buffer_begin == chip->buffer_end)
336
chip->empty = 1;
337
338
}
339
340
if (!chip->empty)
341
hrtimer_start(&chip->hrtimer, chip->wakeups_per_second,
342
HRTIMER_MODE_REL);
343
344
return HRTIMER_NORESTART;
345
}
346
347
/* create -- chip-specific constructor for the cards components */
348
static int __devinit snd_sh_dac_create(struct snd_card *card,
349
struct platform_device *devptr,
350
struct snd_sh_dac **rchip)
351
{
352
struct snd_sh_dac *chip;
353
int err;
354
355
static struct snd_device_ops ops = {
356
.dev_free = snd_sh_dac_dev_free,
357
};
358
359
*rchip = NULL;
360
361
chip = kzalloc(sizeof(*chip), GFP_KERNEL);
362
if (chip == NULL)
363
return -ENOMEM;
364
365
chip->card = card;
366
367
hrtimer_init(&chip->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
368
chip->hrtimer.function = sh_dac_audio_timer;
369
370
dac_audio_reset(chip);
371
chip->rate = 8000;
372
dac_audio_set_rate(chip);
373
374
chip->pdata = devptr->dev.platform_data;
375
376
chip->data_buffer = kmalloc(chip->pdata->buffer_size, GFP_KERNEL);
377
if (chip->data_buffer == NULL) {
378
kfree(chip);
379
return -ENOMEM;
380
}
381
382
err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
383
if (err < 0) {
384
snd_sh_dac_free(chip);
385
return err;
386
}
387
388
*rchip = chip;
389
390
return 0;
391
}
392
393
/* driver .probe -- constructor */
394
static int __devinit snd_sh_dac_probe(struct platform_device *devptr)
395
{
396
struct snd_sh_dac *chip;
397
struct snd_card *card;
398
int err;
399
400
err = snd_card_create(index, id, THIS_MODULE, 0, &card);
401
if (err < 0) {
402
snd_printk(KERN_ERR "cannot allocate the card\n");
403
return err;
404
}
405
406
err = snd_sh_dac_create(card, devptr, &chip);
407
if (err < 0)
408
goto probe_error;
409
410
err = snd_sh_dac_pcm(chip, 0);
411
if (err < 0)
412
goto probe_error;
413
414
strcpy(card->driver, "snd_sh_dac");
415
strcpy(card->shortname, "SuperH DAC audio driver");
416
printk(KERN_INFO "%s %s", card->longname, card->shortname);
417
418
err = snd_card_register(card);
419
if (err < 0)
420
goto probe_error;
421
422
snd_printk("ALSA driver for SuperH DAC audio");
423
424
platform_set_drvdata(devptr, card);
425
return 0;
426
427
probe_error:
428
snd_card_free(card);
429
return err;
430
}
431
432
/*
433
* "driver" definition
434
*/
435
static struct platform_driver driver = {
436
.probe = snd_sh_dac_probe,
437
.remove = snd_sh_dac_remove,
438
.driver = {
439
.name = "dac_audio",
440
},
441
};
442
443
static int __init sh_dac_init(void)
444
{
445
return platform_driver_register(&driver);
446
}
447
448
static void __exit sh_dac_exit(void)
449
{
450
platform_driver_unregister(&driver);
451
}
452
453
module_init(sh_dac_init);
454
module_exit(sh_dac_exit);
455
456