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