Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/parisc/harmony.c
29265 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/* Hewlett-Packard Harmony audio driver
3
*
4
* This is a driver for the Harmony audio chipset found
5
* on the LASI ASIC of various early HP PA-RISC workstations.
6
*
7
* Copyright (C) 2004, Kyle McMartin <kyle@{debian.org,parisc-linux.org}>
8
*
9
* Based on the previous Harmony incarnations by,
10
* Copyright 2000 (c) Linuxcare Canada, Alex deVries
11
* Copyright 2000-2003 (c) Helge Deller
12
* Copyright 2001 (c) Matthieu Delahaye
13
* Copyright 2001 (c) Jean-Christophe Vaugeois
14
* Copyright 2003 (c) Laurent Canet
15
* Copyright 2004 (c) Stuart Brady
16
*
17
* Notes:
18
* - graveyard and silence buffers last for lifetime of
19
* the driver. playback and capture buffers are allocated
20
* per _open()/_close().
21
*
22
* TODO:
23
*/
24
25
#include <linux/init.h>
26
#include <linux/slab.h>
27
#include <linux/time.h>
28
#include <linux/wait.h>
29
#include <linux/delay.h>
30
#include <linux/module.h>
31
#include <linux/interrupt.h>
32
#include <linux/spinlock.h>
33
#include <linux/dma-mapping.h>
34
#include <linux/io.h>
35
36
#include <sound/core.h>
37
#include <sound/pcm.h>
38
#include <sound/control.h>
39
#include <sound/rawmidi.h>
40
#include <sound/initval.h>
41
#include <sound/info.h>
42
43
#include <asm/hardware.h>
44
#include <asm/parisc-device.h>
45
46
#include "harmony.h"
47
48
static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */
49
static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */
50
module_param(index, int, 0444);
51
MODULE_PARM_DESC(index, "Index value for Harmony driver.");
52
module_param(id, charp, 0444);
53
MODULE_PARM_DESC(id, "ID string for Harmony driver.");
54
55
56
static const struct parisc_device_id snd_harmony_devtable[] __initconst = {
57
/* bushmaster / flounder */
58
{ HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007A },
59
/* 712 / 715 */
60
{ HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007B },
61
/* pace */
62
{ HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007E },
63
/* outfield / coral II */
64
{ HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007F },
65
{ 0, }
66
};
67
68
MODULE_DEVICE_TABLE(parisc, snd_harmony_devtable);
69
70
#define NAME "harmony"
71
#define PFX NAME ": "
72
73
static const unsigned int snd_harmony_rates[] = {
74
5512, 6615, 8000, 9600,
75
11025, 16000, 18900, 22050,
76
27428, 32000, 33075, 37800,
77
44100, 48000
78
};
79
80
static const unsigned int rate_bits[14] = {
81
HARMONY_SR_5KHZ, HARMONY_SR_6KHZ, HARMONY_SR_8KHZ,
82
HARMONY_SR_9KHZ, HARMONY_SR_11KHZ, HARMONY_SR_16KHZ,
83
HARMONY_SR_18KHZ, HARMONY_SR_22KHZ, HARMONY_SR_27KHZ,
84
HARMONY_SR_32KHZ, HARMONY_SR_33KHZ, HARMONY_SR_37KHZ,
85
HARMONY_SR_44KHZ, HARMONY_SR_48KHZ
86
};
87
88
static const struct snd_pcm_hw_constraint_list hw_constraint_rates = {
89
.count = ARRAY_SIZE(snd_harmony_rates),
90
.list = snd_harmony_rates,
91
.mask = 0,
92
};
93
94
static inline unsigned long
95
harmony_read(struct snd_harmony *h, unsigned r)
96
{
97
return __raw_readl(h->iobase + r);
98
}
99
100
static inline void
101
harmony_write(struct snd_harmony *h, unsigned r, unsigned long v)
102
{
103
__raw_writel(v, h->iobase + r);
104
}
105
106
static inline void
107
harmony_wait_for_control(struct snd_harmony *h)
108
{
109
while (harmony_read(h, HARMONY_CNTL) & HARMONY_CNTL_C) ;
110
}
111
112
static inline void
113
harmony_reset(struct snd_harmony *h)
114
{
115
harmony_write(h, HARMONY_RESET, 1);
116
mdelay(50);
117
harmony_write(h, HARMONY_RESET, 0);
118
}
119
120
static void
121
harmony_disable_interrupts(struct snd_harmony *h)
122
{
123
u32 dstatus;
124
harmony_wait_for_control(h);
125
dstatus = harmony_read(h, HARMONY_DSTATUS);
126
dstatus &= ~HARMONY_DSTATUS_IE;
127
harmony_write(h, HARMONY_DSTATUS, dstatus);
128
}
129
130
static void
131
harmony_enable_interrupts(struct snd_harmony *h)
132
{
133
u32 dstatus;
134
harmony_wait_for_control(h);
135
dstatus = harmony_read(h, HARMONY_DSTATUS);
136
dstatus |= HARMONY_DSTATUS_IE;
137
harmony_write(h, HARMONY_DSTATUS, dstatus);
138
}
139
140
static void
141
harmony_mute(struct snd_harmony *h)
142
{
143
guard(spinlock_irqsave)(&h->mixer_lock);
144
harmony_wait_for_control(h);
145
harmony_write(h, HARMONY_GAINCTL, HARMONY_GAIN_SILENCE);
146
}
147
148
static void
149
harmony_unmute(struct snd_harmony *h)
150
{
151
guard(spinlock_irqsave)(&h->mixer_lock);
152
harmony_wait_for_control(h);
153
harmony_write(h, HARMONY_GAINCTL, h->st.gain);
154
}
155
156
static void
157
harmony_set_control(struct snd_harmony *h)
158
{
159
u32 ctrl;
160
161
guard(spinlock_irqsave)(&h->lock);
162
163
ctrl = (HARMONY_CNTL_C |
164
(h->st.format << 6) |
165
(h->st.stereo << 5) |
166
(h->st.rate));
167
168
harmony_wait_for_control(h);
169
harmony_write(h, HARMONY_CNTL, ctrl);
170
}
171
172
static irqreturn_t
173
snd_harmony_interrupt(int irq, void *dev)
174
{
175
u32 dstatus;
176
struct snd_harmony *h = dev;
177
178
scoped_guard(spinlock, &h->lock) {
179
harmony_disable_interrupts(h);
180
harmony_wait_for_control(h);
181
dstatus = harmony_read(h, HARMONY_DSTATUS);
182
}
183
184
if (dstatus & HARMONY_DSTATUS_PN) {
185
if (h->psubs && h->st.playing) {
186
scoped_guard(spinlock, &h->lock) {
187
h->pbuf.buf += h->pbuf.count; /* PAGE_SIZE */
188
h->pbuf.buf %= h->pbuf.size; /* MAX_BUFS*PAGE_SIZE */
189
190
harmony_write(h, HARMONY_PNXTADD,
191
h->pbuf.addr + h->pbuf.buf);
192
h->stats.play_intr++;
193
}
194
snd_pcm_period_elapsed(h->psubs);
195
} else {
196
scoped_guard(spinlock, &h->lock) {
197
harmony_write(h, HARMONY_PNXTADD, h->sdma.addr);
198
h->stats.silence_intr++;
199
}
200
}
201
}
202
203
if (dstatus & HARMONY_DSTATUS_RN) {
204
if (h->csubs && h->st.capturing) {
205
scoped_guard(spinlock, &h->lock) {
206
h->cbuf.buf += h->cbuf.count;
207
h->cbuf.buf %= h->cbuf.size;
208
209
harmony_write(h, HARMONY_RNXTADD,
210
h->cbuf.addr + h->cbuf.buf);
211
h->stats.rec_intr++;
212
}
213
snd_pcm_period_elapsed(h->csubs);
214
} else {
215
scoped_guard(spinlock, &h->lock) {
216
harmony_write(h, HARMONY_RNXTADD, h->gdma.addr);
217
h->stats.graveyard_intr++;
218
}
219
}
220
}
221
222
scoped_guard(spinlock, &h->lock) {
223
harmony_enable_interrupts(h);
224
}
225
226
return IRQ_HANDLED;
227
}
228
229
static unsigned int
230
snd_harmony_rate_bits(int rate)
231
{
232
unsigned int i;
233
234
for (i = 0; i < ARRAY_SIZE(snd_harmony_rates); i++)
235
if (snd_harmony_rates[i] == rate)
236
return rate_bits[i];
237
238
return HARMONY_SR_44KHZ;
239
}
240
241
static const struct snd_pcm_hardware snd_harmony_playback =
242
{
243
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
244
SNDRV_PCM_INFO_JOINT_DUPLEX | SNDRV_PCM_INFO_MMAP_VALID |
245
SNDRV_PCM_INFO_BLOCK_TRANSFER),
246
.formats = (SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_MU_LAW |
247
SNDRV_PCM_FMTBIT_A_LAW),
248
.rates = (SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_48000 |
249
SNDRV_PCM_RATE_KNOT),
250
.rate_min = 5512,
251
.rate_max = 48000,
252
.channels_min = 1,
253
.channels_max = 2,
254
.buffer_bytes_max = MAX_BUF_SIZE,
255
.period_bytes_min = BUF_SIZE,
256
.period_bytes_max = BUF_SIZE,
257
.periods_min = 1,
258
.periods_max = MAX_BUFS,
259
.fifo_size = 0,
260
};
261
262
static const struct snd_pcm_hardware snd_harmony_capture =
263
{
264
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
265
SNDRV_PCM_INFO_JOINT_DUPLEX | SNDRV_PCM_INFO_MMAP_VALID |
266
SNDRV_PCM_INFO_BLOCK_TRANSFER),
267
.formats = (SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_MU_LAW |
268
SNDRV_PCM_FMTBIT_A_LAW),
269
.rates = (SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_48000 |
270
SNDRV_PCM_RATE_KNOT),
271
.rate_min = 5512,
272
.rate_max = 48000,
273
.channels_min = 1,
274
.channels_max = 2,
275
.buffer_bytes_max = MAX_BUF_SIZE,
276
.period_bytes_min = BUF_SIZE,
277
.period_bytes_max = BUF_SIZE,
278
.periods_min = 1,
279
.periods_max = MAX_BUFS,
280
.fifo_size = 0,
281
};
282
283
static int
284
snd_harmony_playback_trigger(struct snd_pcm_substream *ss, int cmd)
285
{
286
struct snd_harmony *h = snd_pcm_substream_chip(ss);
287
288
if (h->st.capturing)
289
return -EBUSY;
290
291
guard(spinlock)(&h->lock);
292
switch (cmd) {
293
case SNDRV_PCM_TRIGGER_START:
294
h->st.playing = 1;
295
harmony_write(h, HARMONY_PNXTADD, h->pbuf.addr);
296
harmony_write(h, HARMONY_RNXTADD, h->gdma.addr);
297
harmony_unmute(h);
298
harmony_enable_interrupts(h);
299
break;
300
case SNDRV_PCM_TRIGGER_STOP:
301
h->st.playing = 0;
302
harmony_mute(h);
303
harmony_write(h, HARMONY_PNXTADD, h->sdma.addr);
304
harmony_disable_interrupts(h);
305
break;
306
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
307
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
308
case SNDRV_PCM_TRIGGER_SUSPEND:
309
default:
310
snd_BUG();
311
return -EINVAL;
312
}
313
314
return 0;
315
}
316
317
static int
318
snd_harmony_capture_trigger(struct snd_pcm_substream *ss, int cmd)
319
{
320
struct snd_harmony *h = snd_pcm_substream_chip(ss);
321
322
if (h->st.playing)
323
return -EBUSY;
324
325
guard(spinlock)(&h->lock);
326
switch (cmd) {
327
case SNDRV_PCM_TRIGGER_START:
328
h->st.capturing = 1;
329
harmony_write(h, HARMONY_PNXTADD, h->sdma.addr);
330
harmony_write(h, HARMONY_RNXTADD, h->cbuf.addr);
331
harmony_unmute(h);
332
harmony_enable_interrupts(h);
333
break;
334
case SNDRV_PCM_TRIGGER_STOP:
335
h->st.capturing = 0;
336
harmony_mute(h);
337
harmony_write(h, HARMONY_RNXTADD, h->gdma.addr);
338
harmony_disable_interrupts(h);
339
break;
340
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
341
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
342
case SNDRV_PCM_TRIGGER_SUSPEND:
343
default:
344
snd_BUG();
345
return -EINVAL;
346
}
347
348
return 0;
349
}
350
351
static int
352
snd_harmony_set_data_format(struct snd_harmony *h, int fmt, int force)
353
{
354
int o = h->st.format;
355
int n;
356
357
switch(fmt) {
358
case SNDRV_PCM_FORMAT_S16_BE:
359
n = HARMONY_DF_16BIT_LINEAR;
360
break;
361
case SNDRV_PCM_FORMAT_A_LAW:
362
n = HARMONY_DF_8BIT_ALAW;
363
break;
364
case SNDRV_PCM_FORMAT_MU_LAW:
365
n = HARMONY_DF_8BIT_ULAW;
366
break;
367
default:
368
n = HARMONY_DF_16BIT_LINEAR;
369
break;
370
}
371
372
if (force || o != n) {
373
snd_pcm_format_set_silence(fmt, h->sdma.area, SILENCE_BUFSZ /
374
(snd_pcm_format_physical_width(fmt)
375
/ 8));
376
}
377
378
return n;
379
}
380
381
static int
382
snd_harmony_playback_prepare(struct snd_pcm_substream *ss)
383
{
384
struct snd_harmony *h = snd_pcm_substream_chip(ss);
385
struct snd_pcm_runtime *rt = ss->runtime;
386
387
if (h->st.capturing)
388
return -EBUSY;
389
390
h->pbuf.size = snd_pcm_lib_buffer_bytes(ss);
391
h->pbuf.count = snd_pcm_lib_period_bytes(ss);
392
if (h->pbuf.buf >= h->pbuf.size)
393
h->pbuf.buf = 0;
394
h->st.playing = 0;
395
396
h->st.rate = snd_harmony_rate_bits(rt->rate);
397
h->st.format = snd_harmony_set_data_format(h, rt->format, 0);
398
399
if (rt->channels == 2)
400
h->st.stereo = HARMONY_SS_STEREO;
401
else
402
h->st.stereo = HARMONY_SS_MONO;
403
404
harmony_set_control(h);
405
406
h->pbuf.addr = rt->dma_addr;
407
408
return 0;
409
}
410
411
static int
412
snd_harmony_capture_prepare(struct snd_pcm_substream *ss)
413
{
414
struct snd_harmony *h = snd_pcm_substream_chip(ss);
415
struct snd_pcm_runtime *rt = ss->runtime;
416
417
if (h->st.playing)
418
return -EBUSY;
419
420
h->cbuf.size = snd_pcm_lib_buffer_bytes(ss);
421
h->cbuf.count = snd_pcm_lib_period_bytes(ss);
422
if (h->cbuf.buf >= h->cbuf.size)
423
h->cbuf.buf = 0;
424
h->st.capturing = 0;
425
426
h->st.rate = snd_harmony_rate_bits(rt->rate);
427
h->st.format = snd_harmony_set_data_format(h, rt->format, 0);
428
429
if (rt->channels == 2)
430
h->st.stereo = HARMONY_SS_STEREO;
431
else
432
h->st.stereo = HARMONY_SS_MONO;
433
434
harmony_set_control(h);
435
436
h->cbuf.addr = rt->dma_addr;
437
438
return 0;
439
}
440
441
static snd_pcm_uframes_t
442
snd_harmony_playback_pointer(struct snd_pcm_substream *ss)
443
{
444
struct snd_pcm_runtime *rt = ss->runtime;
445
struct snd_harmony *h = snd_pcm_substream_chip(ss);
446
unsigned long pcuradd;
447
unsigned long played;
448
449
if (!(h->st.playing) || (h->psubs == NULL))
450
return 0;
451
452
if ((h->pbuf.addr == 0) || (h->pbuf.size == 0))
453
return 0;
454
455
pcuradd = harmony_read(h, HARMONY_PCURADD);
456
played = pcuradd - h->pbuf.addr;
457
458
#ifdef HARMONY_DEBUG
459
printk(KERN_DEBUG PFX "playback_pointer is 0x%lx-0x%lx = %d bytes\n",
460
pcuradd, h->pbuf.addr, played);
461
#endif
462
463
if (pcuradd > h->pbuf.addr + h->pbuf.size) {
464
return 0;
465
}
466
467
return bytes_to_frames(rt, played);
468
}
469
470
static snd_pcm_uframes_t
471
snd_harmony_capture_pointer(struct snd_pcm_substream *ss)
472
{
473
struct snd_pcm_runtime *rt = ss->runtime;
474
struct snd_harmony *h = snd_pcm_substream_chip(ss);
475
unsigned long rcuradd;
476
unsigned long caught;
477
478
if (!(h->st.capturing) || (h->csubs == NULL))
479
return 0;
480
481
if ((h->cbuf.addr == 0) || (h->cbuf.size == 0))
482
return 0;
483
484
rcuradd = harmony_read(h, HARMONY_RCURADD);
485
caught = rcuradd - h->cbuf.addr;
486
487
#ifdef HARMONY_DEBUG
488
printk(KERN_DEBUG PFX "capture_pointer is 0x%lx-0x%lx = %d bytes\n",
489
rcuradd, h->cbuf.addr, caught);
490
#endif
491
492
if (rcuradd > h->cbuf.addr + h->cbuf.size) {
493
return 0;
494
}
495
496
return bytes_to_frames(rt, caught);
497
}
498
499
static int
500
snd_harmony_playback_open(struct snd_pcm_substream *ss)
501
{
502
struct snd_harmony *h = snd_pcm_substream_chip(ss);
503
struct snd_pcm_runtime *rt = ss->runtime;
504
int err;
505
506
h->psubs = ss;
507
rt->hw = snd_harmony_playback;
508
snd_pcm_hw_constraint_list(rt, 0, SNDRV_PCM_HW_PARAM_RATE,
509
&hw_constraint_rates);
510
511
err = snd_pcm_hw_constraint_integer(rt, SNDRV_PCM_HW_PARAM_PERIODS);
512
if (err < 0)
513
return err;
514
515
return 0;
516
}
517
518
static int
519
snd_harmony_capture_open(struct snd_pcm_substream *ss)
520
{
521
struct snd_harmony *h = snd_pcm_substream_chip(ss);
522
struct snd_pcm_runtime *rt = ss->runtime;
523
int err;
524
525
h->csubs = ss;
526
rt->hw = snd_harmony_capture;
527
snd_pcm_hw_constraint_list(rt, 0, SNDRV_PCM_HW_PARAM_RATE,
528
&hw_constraint_rates);
529
530
err = snd_pcm_hw_constraint_integer(rt, SNDRV_PCM_HW_PARAM_PERIODS);
531
if (err < 0)
532
return err;
533
534
return 0;
535
}
536
537
static int
538
snd_harmony_playback_close(struct snd_pcm_substream *ss)
539
{
540
struct snd_harmony *h = snd_pcm_substream_chip(ss);
541
h->psubs = NULL;
542
return 0;
543
}
544
545
static int
546
snd_harmony_capture_close(struct snd_pcm_substream *ss)
547
{
548
struct snd_harmony *h = snd_pcm_substream_chip(ss);
549
h->csubs = NULL;
550
return 0;
551
}
552
553
static const struct snd_pcm_ops snd_harmony_playback_ops = {
554
.open = snd_harmony_playback_open,
555
.close = snd_harmony_playback_close,
556
.prepare = snd_harmony_playback_prepare,
557
.trigger = snd_harmony_playback_trigger,
558
.pointer = snd_harmony_playback_pointer,
559
};
560
561
static const struct snd_pcm_ops snd_harmony_capture_ops = {
562
.open = snd_harmony_capture_open,
563
.close = snd_harmony_capture_close,
564
.prepare = snd_harmony_capture_prepare,
565
.trigger = snd_harmony_capture_trigger,
566
.pointer = snd_harmony_capture_pointer,
567
};
568
569
static int
570
snd_harmony_pcm_init(struct snd_harmony *h)
571
{
572
struct snd_pcm *pcm;
573
int err;
574
575
if (snd_BUG_ON(!h))
576
return -EINVAL;
577
578
harmony_disable_interrupts(h);
579
580
err = snd_pcm_new(h->card, "harmony", 0, 1, 1, &pcm);
581
if (err < 0)
582
return err;
583
584
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
585
&snd_harmony_playback_ops);
586
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
587
&snd_harmony_capture_ops);
588
589
pcm->private_data = h;
590
pcm->info_flags = 0;
591
strscpy(pcm->name, "harmony");
592
h->pcm = pcm;
593
594
h->psubs = NULL;
595
h->csubs = NULL;
596
597
/* initialize graveyard buffer */
598
h->dma.type = SNDRV_DMA_TYPE_DEV;
599
h->dma.dev = &h->dev->dev;
600
err = snd_dma_alloc_pages(h->dma.type,
601
h->dma.dev,
602
BUF_SIZE*GRAVEYARD_BUFS,
603
&h->gdma);
604
if (err < 0) {
605
printk(KERN_ERR PFX "cannot allocate graveyard buffer!\n");
606
return err;
607
}
608
609
/* initialize silence buffers */
610
err = snd_dma_alloc_pages(h->dma.type,
611
h->dma.dev,
612
BUF_SIZE*SILENCE_BUFS,
613
&h->sdma);
614
if (err < 0) {
615
printk(KERN_ERR PFX "cannot allocate silence buffer!\n");
616
return err;
617
}
618
619
/* pre-allocate space for DMA */
620
snd_pcm_set_managed_buffer_all(pcm, h->dma.type, h->dma.dev,
621
MAX_BUF_SIZE, MAX_BUF_SIZE);
622
623
h->st.format = snd_harmony_set_data_format(h,
624
SNDRV_PCM_FORMAT_S16_BE, 1);
625
626
return 0;
627
}
628
629
static void
630
snd_harmony_set_new_gain(struct snd_harmony *h)
631
{
632
harmony_wait_for_control(h);
633
harmony_write(h, HARMONY_GAINCTL, h->st.gain);
634
}
635
636
static int
637
snd_harmony_mixercontrol_info(struct snd_kcontrol *kc,
638
struct snd_ctl_elem_info *uinfo)
639
{
640
int mask = (kc->private_value >> 16) & 0xff;
641
int left_shift = (kc->private_value) & 0xff;
642
int right_shift = (kc->private_value >> 8) & 0xff;
643
644
uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN :
645
SNDRV_CTL_ELEM_TYPE_INTEGER;
646
uinfo->count = left_shift == right_shift ? 1 : 2;
647
uinfo->value.integer.min = 0;
648
uinfo->value.integer.max = mask;
649
650
return 0;
651
}
652
653
static int
654
snd_harmony_volume_get(struct snd_kcontrol *kc,
655
struct snd_ctl_elem_value *ucontrol)
656
{
657
struct snd_harmony *h = snd_kcontrol_chip(kc);
658
int shift_left = (kc->private_value) & 0xff;
659
int shift_right = (kc->private_value >> 8) & 0xff;
660
int mask = (kc->private_value >> 16) & 0xff;
661
int invert = (kc->private_value >> 24) & 0xff;
662
int left, right;
663
664
guard(spinlock_irq)(&h->mixer_lock);
665
666
left = (h->st.gain >> shift_left) & mask;
667
right = (h->st.gain >> shift_right) & mask;
668
if (invert) {
669
left = mask - left;
670
right = mask - right;
671
}
672
673
ucontrol->value.integer.value[0] = left;
674
if (shift_left != shift_right)
675
ucontrol->value.integer.value[1] = right;
676
677
return 0;
678
}
679
680
static int
681
snd_harmony_volume_put(struct snd_kcontrol *kc,
682
struct snd_ctl_elem_value *ucontrol)
683
{
684
struct snd_harmony *h = snd_kcontrol_chip(kc);
685
int shift_left = (kc->private_value) & 0xff;
686
int shift_right = (kc->private_value >> 8) & 0xff;
687
int mask = (kc->private_value >> 16) & 0xff;
688
int invert = (kc->private_value >> 24) & 0xff;
689
int left, right;
690
int old_gain = h->st.gain;
691
692
guard(spinlock_irq)(&h->mixer_lock);
693
694
left = ucontrol->value.integer.value[0] & mask;
695
if (invert)
696
left = mask - left;
697
h->st.gain &= ~( (mask << shift_left ) );
698
h->st.gain |= (left << shift_left);
699
700
if (shift_left != shift_right) {
701
right = ucontrol->value.integer.value[1] & mask;
702
if (invert)
703
right = mask - right;
704
h->st.gain &= ~( (mask << shift_right) );
705
h->st.gain |= (right << shift_right);
706
}
707
708
snd_harmony_set_new_gain(h);
709
710
return h->st.gain != old_gain;
711
}
712
713
static int
714
snd_harmony_captureroute_info(struct snd_kcontrol *kc,
715
struct snd_ctl_elem_info *uinfo)
716
{
717
static const char * const texts[2] = { "Line", "Mic" };
718
719
return snd_ctl_enum_info(uinfo, 1, 2, texts);
720
}
721
722
static int
723
snd_harmony_captureroute_get(struct snd_kcontrol *kc,
724
struct snd_ctl_elem_value *ucontrol)
725
{
726
struct snd_harmony *h = snd_kcontrol_chip(kc);
727
int value;
728
729
guard(spinlock_irq)(&h->mixer_lock);
730
731
value = (h->st.gain >> HARMONY_GAIN_IS_SHIFT) & 1;
732
ucontrol->value.enumerated.item[0] = value;
733
734
return 0;
735
}
736
737
static int
738
snd_harmony_captureroute_put(struct snd_kcontrol *kc,
739
struct snd_ctl_elem_value *ucontrol)
740
{
741
struct snd_harmony *h = snd_kcontrol_chip(kc);
742
int value;
743
int old_gain = h->st.gain;
744
745
guard(spinlock_irq)(&h->mixer_lock);
746
747
value = ucontrol->value.enumerated.item[0] & 1;
748
h->st.gain &= ~HARMONY_GAIN_IS_MASK;
749
h->st.gain |= value << HARMONY_GAIN_IS_SHIFT;
750
751
snd_harmony_set_new_gain(h);
752
753
return h->st.gain != old_gain;
754
}
755
756
#define HARMONY_CONTROLS ARRAY_SIZE(snd_harmony_controls)
757
758
#define HARMONY_VOLUME(xname, left_shift, right_shift, mask, invert) \
759
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
760
.info = snd_harmony_mixercontrol_info, \
761
.get = snd_harmony_volume_get, .put = snd_harmony_volume_put, \
762
.private_value = ((left_shift) | ((right_shift) << 8) | \
763
((mask) << 16) | ((invert) << 24)) }
764
765
static const struct snd_kcontrol_new snd_harmony_controls[] = {
766
HARMONY_VOLUME("Master Playback Volume", HARMONY_GAIN_LO_SHIFT,
767
HARMONY_GAIN_RO_SHIFT, HARMONY_GAIN_OUT, 1),
768
HARMONY_VOLUME("Capture Volume", HARMONY_GAIN_LI_SHIFT,
769
HARMONY_GAIN_RI_SHIFT, HARMONY_GAIN_IN, 0),
770
HARMONY_VOLUME("Monitor Volume", HARMONY_GAIN_MA_SHIFT,
771
HARMONY_GAIN_MA_SHIFT, HARMONY_GAIN_MA, 1),
772
{
773
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
774
.name = "Input Route",
775
.info = snd_harmony_captureroute_info,
776
.get = snd_harmony_captureroute_get,
777
.put = snd_harmony_captureroute_put
778
},
779
HARMONY_VOLUME("Internal Speaker Switch", HARMONY_GAIN_SE_SHIFT,
780
HARMONY_GAIN_SE_SHIFT, 1, 0),
781
HARMONY_VOLUME("Line-Out Switch", HARMONY_GAIN_LE_SHIFT,
782
HARMONY_GAIN_LE_SHIFT, 1, 0),
783
HARMONY_VOLUME("Headphones Switch", HARMONY_GAIN_HE_SHIFT,
784
HARMONY_GAIN_HE_SHIFT, 1, 0),
785
};
786
787
static void
788
snd_harmony_mixer_reset(struct snd_harmony *h)
789
{
790
harmony_mute(h);
791
harmony_reset(h);
792
h->st.gain = HARMONY_GAIN_DEFAULT;
793
harmony_unmute(h);
794
}
795
796
static int
797
snd_harmony_mixer_init(struct snd_harmony *h)
798
{
799
struct snd_card *card;
800
int idx, err;
801
802
if (snd_BUG_ON(!h))
803
return -EINVAL;
804
card = h->card;
805
strscpy(card->mixername, "Harmony Gain control interface");
806
807
for (idx = 0; idx < HARMONY_CONTROLS; idx++) {
808
err = snd_ctl_add(card,
809
snd_ctl_new1(&snd_harmony_controls[idx], h));
810
if (err < 0)
811
return err;
812
}
813
814
snd_harmony_mixer_reset(h);
815
816
return 0;
817
}
818
819
static int
820
snd_harmony_free(struct snd_harmony *h)
821
{
822
if (h->gdma.addr)
823
snd_dma_free_pages(&h->gdma);
824
if (h->sdma.addr)
825
snd_dma_free_pages(&h->sdma);
826
827
if (h->irq >= 0)
828
free_irq(h->irq, h);
829
830
iounmap(h->iobase);
831
kfree(h);
832
return 0;
833
}
834
835
static int
836
snd_harmony_dev_free(struct snd_device *dev)
837
{
838
struct snd_harmony *h = dev->device_data;
839
return snd_harmony_free(h);
840
}
841
842
static int
843
snd_harmony_create(struct snd_card *card,
844
struct parisc_device *padev,
845
struct snd_harmony **rchip)
846
{
847
int err;
848
struct snd_harmony *h;
849
static const struct snd_device_ops ops = {
850
.dev_free = snd_harmony_dev_free,
851
};
852
853
*rchip = NULL;
854
855
h = kzalloc(sizeof(*h), GFP_KERNEL);
856
if (h == NULL)
857
return -ENOMEM;
858
859
h->hpa = padev->hpa.start;
860
h->card = card;
861
h->dev = padev;
862
h->irq = -1;
863
h->iobase = ioremap(padev->hpa.start, HARMONY_SIZE);
864
if (h->iobase == NULL) {
865
printk(KERN_ERR PFX "unable to remap hpa 0x%lx\n",
866
(unsigned long)padev->hpa.start);
867
err = -EBUSY;
868
goto free_and_ret;
869
}
870
871
err = request_irq(padev->irq, snd_harmony_interrupt, 0,
872
"harmony", h);
873
if (err) {
874
printk(KERN_ERR PFX "could not obtain interrupt %d",
875
padev->irq);
876
goto free_and_ret;
877
}
878
h->irq = padev->irq;
879
880
spin_lock_init(&h->mixer_lock);
881
spin_lock_init(&h->lock);
882
883
err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, h, &ops);
884
if (err < 0)
885
goto free_and_ret;
886
887
*rchip = h;
888
889
return 0;
890
891
free_and_ret:
892
snd_harmony_free(h);
893
return err;
894
}
895
896
static int __init
897
snd_harmony_probe(struct parisc_device *padev)
898
{
899
int err;
900
struct snd_card *card;
901
struct snd_harmony *h;
902
903
err = snd_card_new(&padev->dev, index, id, THIS_MODULE, 0, &card);
904
if (err < 0)
905
return err;
906
907
err = snd_harmony_create(card, padev, &h);
908
if (err < 0)
909
goto free_and_ret;
910
911
err = snd_harmony_pcm_init(h);
912
if (err < 0)
913
goto free_and_ret;
914
915
err = snd_harmony_mixer_init(h);
916
if (err < 0)
917
goto free_and_ret;
918
919
strscpy(card->driver, "harmony");
920
strscpy(card->shortname, "Harmony");
921
sprintf(card->longname, "%s at 0x%lx, irq %i",
922
card->shortname, h->hpa, h->irq);
923
924
err = snd_card_register(card);
925
if (err < 0)
926
goto free_and_ret;
927
928
parisc_set_drvdata(padev, card);
929
return 0;
930
931
free_and_ret:
932
snd_card_free(card);
933
return err;
934
}
935
936
static void __exit
937
snd_harmony_remove(struct parisc_device *padev)
938
{
939
snd_card_free(parisc_get_drvdata(padev));
940
}
941
942
static struct parisc_driver snd_harmony_driver __refdata = {
943
.name = "harmony",
944
.id_table = snd_harmony_devtable,
945
.probe = snd_harmony_probe,
946
.remove = __exit_p(snd_harmony_remove),
947
};
948
949
static int __init
950
alsa_harmony_init(void)
951
{
952
return register_parisc_driver(&snd_harmony_driver);
953
}
954
955
static void __exit
956
alsa_harmony_fini(void)
957
{
958
unregister_parisc_driver(&snd_harmony_driver);
959
}
960
961
MODULE_LICENSE("GPL");
962
MODULE_AUTHOR("Kyle McMartin <[email protected]>");
963
MODULE_DESCRIPTION("Harmony sound driver");
964
965
module_init(alsa_harmony_init);
966
module_exit(alsa_harmony_fini);
967
968