summaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-rw-r--r--sound/Kconfig2
-rw-r--r--sound/Makefile2
-rw-r--r--sound/core/rawmidi.c2
-rw-r--r--sound/core/seq/seq_memory.c9
-rw-r--r--sound/core/seq/seq_queue.c33
-rw-r--r--sound/core/seq/seq_virmidi.c4
-rw-r--r--sound/drivers/mpu401/mpu401_uart.c4
-rw-r--r--sound/drivers/mtpav.c4
-rw-r--r--sound/drivers/mts64.c4
-rw-r--r--sound/drivers/portman2x4.c4
-rw-r--r--sound/drivers/serial-u16550.c4
-rw-r--r--sound/drivers/vx/vx_pcm.c8
-rw-r--r--sound/firewire/Kconfig1
-rw-r--r--sound/firewire/bebob/bebob_hwdep.c17
-rw-r--r--sound/firewire/bebob/bebob_midi.c26
-rw-r--r--sound/firewire/bebob/bebob_pcm.c51
-rw-r--r--sound/firewire/dice/dice-interface.h1
-rw-r--r--sound/firewire/dice/dice-midi.c22
-rw-r--r--sound/firewire/dice/dice-stream.c12
-rw-r--r--sound/firewire/digi00x/digi00x-hwdep.c17
-rw-r--r--sound/firewire/digi00x/digi00x-midi.c52
-rw-r--r--sound/firewire/digi00x/digi00x-pcm.c52
-rw-r--r--sound/firewire/fireworks/fireworks_hwdep.c19
-rw-r--r--sound/firewire/fireworks/fireworks_midi.c26
-rw-r--r--sound/firewire/fireworks/fireworks_pcm.c52
-rw-r--r--sound/firewire/oxfw/oxfw-midi.c26
-rw-r--r--sound/firewire/oxfw/oxfw-scs1x.c14
-rw-r--r--sound/firewire/oxfw/oxfw.c1
-rw-r--r--sound/firewire/tascam/tascam-hwdep.c17
-rw-r--r--sound/firewire/tascam/tascam-midi.c26
-rw-r--r--sound/firewire/tascam/tascam-pcm.c52
-rw-r--r--sound/isa/gus/gus_uart.c4
-rw-r--r--sound/isa/msnd/msnd_midi.c2
-rw-r--r--sound/isa/sb/sb8_midi.c4
-rw-r--r--sound/isa/wavefront/wavefront_midi.c4
-rw-r--r--sound/mips/hal2.c4
-rw-r--r--sound/oss/ad1848.c7
-rw-r--r--sound/pci/ca0106/ca_midi.c4
-rw-r--r--sound/pci/cs4281.c4
-rw-r--r--sound/pci/cs46xx/cs46xx_lib.c44
-rw-r--r--sound/pci/cs5535audio/cs5535audio_pm.c4
-rw-r--r--sound/pci/echoaudio/midi.c4
-rw-r--r--sound/pci/emu10k1/emu10k1_callback.c2
-rw-r--r--sound/pci/emu10k1/emu10k1x.c4
-rw-r--r--sound/pci/emu10k1/emumpu401.c4
-rw-r--r--sound/pci/ens1370.c4
-rw-r--r--sound/pci/hda/hda_controller.c4
-rw-r--r--sound/pci/hda/hda_controller.h1
-rw-r--r--sound/pci/hda/hda_intel.c35
-rw-r--r--sound/pci/hda/patch_ca0132.c3
-rw-r--r--sound/pci/hda/patch_hdmi.c1
-rw-r--r--sound/pci/hda/patch_realtek.c43
-rw-r--r--sound/pci/hda/patch_sigmatel.c30
-rw-r--r--sound/pci/ice1712/ice1724.c4
-rw-r--r--sound/pci/mixart/mixart.h2
-rw-r--r--sound/pci/rme9652/hdsp.c4
-rw-r--r--sound/pci/rme9652/hdspm.c4
-rw-r--r--sound/pci/vx222/vx222_ops.c12
-rw-r--r--sound/pcmcia/vx/vxp_ops.c12
-rw-r--r--sound/synth/emux/emux_seq.c14
-rw-r--r--sound/usb/6fire/midi.c4
-rw-r--r--sound/usb/Makefile1
-rw-r--r--sound/usb/bcd2000/bcd2000.c4
-rw-r--r--sound/usb/caiaq/midi.c4
-rw-r--r--sound/usb/line6/driver.c49
-rw-r--r--sound/usb/line6/midi.c4
-rw-r--r--sound/usb/midi.c4
-rw-r--r--sound/usb/mixer_quirks.c5
-rw-r--r--sound/usb/mixer_us16x08.c1465
-rw-r--r--sound/usb/mixer_us16x08.h122
-rw-r--r--sound/usb/quirks.c15
-rw-r--r--sound/x86/Kconfig15
-rw-r--r--sound/x86/Makefile4
-rw-r--r--sound/x86/intel_hdmi_audio.c1851
-rw-r--r--sound/x86/intel_hdmi_audio.h136
-rw-r--r--sound/x86/intel_hdmi_lpe_audio.h328
76 files changed, 4443 insertions, 400 deletions
diff --git a/sound/Kconfig b/sound/Kconfig
index 5a240e050ae6..ee2e69a9ecd1 100644
--- a/sound/Kconfig
+++ b/sound/Kconfig
@@ -108,6 +108,8 @@ source "sound/parisc/Kconfig"
108 108
109source "sound/soc/Kconfig" 109source "sound/soc/Kconfig"
110 110
111source "sound/x86/Kconfig"
112
111endif # SND 113endif # SND
112 114
113menuconfig SOUND_PRIME 115menuconfig SOUND_PRIME
diff --git a/sound/Makefile b/sound/Makefile
index c41bdf5fdf24..6de45d2c32f7 100644
--- a/sound/Makefile
+++ b/sound/Makefile
@@ -5,7 +5,7 @@ obj-$(CONFIG_SOUND) += soundcore.o
5obj-$(CONFIG_SOUND_PRIME) += oss/ 5obj-$(CONFIG_SOUND_PRIME) += oss/
6obj-$(CONFIG_DMASOUND) += oss/ 6obj-$(CONFIG_DMASOUND) += oss/
7obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ sh/ synth/ usb/ \ 7obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ sh/ synth/ usb/ \
8 firewire/ sparc/ spi/ parisc/ pcmcia/ mips/ soc/ atmel/ hda/ 8 firewire/ sparc/ spi/ parisc/ pcmcia/ mips/ soc/ atmel/ hda/ x86/
9obj-$(CONFIG_SND_AOA) += aoa/ 9obj-$(CONFIG_SND_AOA) += aoa/
10 10
11# This one must be compilable even if sound is configured out 11# This one must be compilable even if sound is configured out
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index 2096bb0835c8..8da9cb245d01 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -1749,7 +1749,7 @@ static int snd_rawmidi_dev_disconnect(struct snd_device *device)
1749 * Sets the rawmidi operators for the given stream direction. 1749 * Sets the rawmidi operators for the given stream direction.
1750 */ 1750 */
1751void snd_rawmidi_set_ops(struct snd_rawmidi *rmidi, int stream, 1751void snd_rawmidi_set_ops(struct snd_rawmidi *rmidi, int stream,
1752 struct snd_rawmidi_ops *ops) 1752 const struct snd_rawmidi_ops *ops)
1753{ 1753{
1754 struct snd_rawmidi_substream *substream; 1754 struct snd_rawmidi_substream *substream;
1755 1755
diff --git a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c
index c850345c43b5..dfa5156f3585 100644
--- a/sound/core/seq/seq_memory.c
+++ b/sound/core/seq/seq_memory.c
@@ -419,7 +419,6 @@ int snd_seq_pool_done(struct snd_seq_pool *pool)
419{ 419{
420 unsigned long flags; 420 unsigned long flags;
421 struct snd_seq_event_cell *ptr; 421 struct snd_seq_event_cell *ptr;
422 int max_count = 5 * HZ;
423 422
424 if (snd_BUG_ON(!pool)) 423 if (snd_BUG_ON(!pool))
425 return -EINVAL; 424 return -EINVAL;
@@ -432,14 +431,8 @@ int snd_seq_pool_done(struct snd_seq_pool *pool)
432 if (waitqueue_active(&pool->output_sleep)) 431 if (waitqueue_active(&pool->output_sleep))
433 wake_up(&pool->output_sleep); 432 wake_up(&pool->output_sleep);
434 433
435 while (atomic_read(&pool->counter) > 0) { 434 while (atomic_read(&pool->counter) > 0)
436 if (max_count == 0) {
437 pr_warn("ALSA: snd_seq_pool_done timeout: %d cells remain\n", atomic_read(&pool->counter));
438 break;
439 }
440 schedule_timeout_uninterruptible(1); 435 schedule_timeout_uninterruptible(1);
441 max_count--;
442 }
443 436
444 /* release all resources */ 437 /* release all resources */
445 spin_lock_irqsave(&pool->lock, flags); 438 spin_lock_irqsave(&pool->lock, flags);
diff --git a/sound/core/seq/seq_queue.c b/sound/core/seq/seq_queue.c
index 0bec02e89d51..450c5187eecb 100644
--- a/sound/core/seq/seq_queue.c
+++ b/sound/core/seq/seq_queue.c
@@ -181,6 +181,8 @@ void __exit snd_seq_queues_delete(void)
181 } 181 }
182} 182}
183 183
184static void queue_use(struct snd_seq_queue *queue, int client, int use);
185
184/* allocate a new queue - 186/* allocate a new queue -
185 * return queue index value or negative value for error 187 * return queue index value or negative value for error
186 */ 188 */
@@ -192,11 +194,11 @@ int snd_seq_queue_alloc(int client, int locked, unsigned int info_flags)
192 if (q == NULL) 194 if (q == NULL)
193 return -ENOMEM; 195 return -ENOMEM;
194 q->info_flags = info_flags; 196 q->info_flags = info_flags;
197 queue_use(q, client, 1);
195 if (queue_list_add(q) < 0) { 198 if (queue_list_add(q) < 0) {
196 queue_delete(q); 199 queue_delete(q);
197 return -ENOMEM; 200 return -ENOMEM;
198 } 201 }
199 snd_seq_queue_use(q->queue, client, 1); /* use this queue */
200 return q->queue; 202 return q->queue;
201} 203}
202 204
@@ -502,19 +504,9 @@ int snd_seq_queue_timer_set_tempo(int queueid, int client,
502 return result; 504 return result;
503} 505}
504 506
505 507/* use or unuse this queue */
506/* use or unuse this queue - 508static void queue_use(struct snd_seq_queue *queue, int client, int use)
507 * if it is the first client, starts the timer.
508 * if it is not longer used by any clients, stop the timer.
509 */
510int snd_seq_queue_use(int queueid, int client, int use)
511{ 509{
512 struct snd_seq_queue *queue;
513
514 queue = queueptr(queueid);
515 if (queue == NULL)
516 return -EINVAL;
517 mutex_lock(&queue->timer_mutex);
518 if (use) { 510 if (use) {
519 if (!test_and_set_bit(client, queue->clients_bitmap)) 511 if (!test_and_set_bit(client, queue->clients_bitmap))
520 queue->clients++; 512 queue->clients++;
@@ -529,6 +521,21 @@ int snd_seq_queue_use(int queueid, int client, int use)
529 } else { 521 } else {
530 snd_seq_timer_close(queue); 522 snd_seq_timer_close(queue);
531 } 523 }
524}
525
526/* use or unuse this queue -
527 * if it is the first client, starts the timer.
528 * if it is not longer used by any clients, stop the timer.
529 */
530int snd_seq_queue_use(int queueid, int client, int use)
531{
532 struct snd_seq_queue *queue;
533
534 queue = queueptr(queueid);
535 if (queue == NULL)
536 return -EINVAL;
537 mutex_lock(&queue->timer_mutex);
538 queue_use(queue, client, use);
532 mutex_unlock(&queue->timer_mutex); 539 mutex_unlock(&queue->timer_mutex);
533 queuefree(queue); 540 queuefree(queue);
534 return 0; 541 return 0;
diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c
index c82ed3e70506..52f31f1498f9 100644
--- a/sound/core/seq/seq_virmidi.c
+++ b/sound/core/seq/seq_virmidi.c
@@ -349,13 +349,13 @@ static int snd_virmidi_unuse(void *private_data,
349 * Register functions 349 * Register functions
350 */ 350 */
351 351
352static struct snd_rawmidi_ops snd_virmidi_input_ops = { 352static const struct snd_rawmidi_ops snd_virmidi_input_ops = {
353 .open = snd_virmidi_input_open, 353 .open = snd_virmidi_input_open,
354 .close = snd_virmidi_input_close, 354 .close = snd_virmidi_input_close,
355 .trigger = snd_virmidi_input_trigger, 355 .trigger = snd_virmidi_input_trigger,
356}; 356};
357 357
358static struct snd_rawmidi_ops snd_virmidi_output_ops = { 358static const struct snd_rawmidi_ops snd_virmidi_output_ops = {
359 .open = snd_virmidi_output_open, 359 .open = snd_virmidi_output_open,
360 .close = snd_virmidi_output_close, 360 .close = snd_virmidi_output_close,
361 .trigger = snd_virmidi_output_trigger, 361 .trigger = snd_virmidi_output_trigger,
diff --git a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c
index 776596b5ee05..3a7c317ae012 100644
--- a/sound/drivers/mpu401/mpu401_uart.c
+++ b/sound/drivers/mpu401/mpu401_uart.c
@@ -481,14 +481,14 @@ snd_mpu401_uart_output_trigger(struct snd_rawmidi_substream *substream, int up)
481 481
482 */ 482 */
483 483
484static struct snd_rawmidi_ops snd_mpu401_uart_output = 484static const struct snd_rawmidi_ops snd_mpu401_uart_output =
485{ 485{
486 .open = snd_mpu401_uart_output_open, 486 .open = snd_mpu401_uart_output_open,
487 .close = snd_mpu401_uart_output_close, 487 .close = snd_mpu401_uart_output_close,
488 .trigger = snd_mpu401_uart_output_trigger, 488 .trigger = snd_mpu401_uart_output_trigger,
489}; 489};
490 490
491static struct snd_rawmidi_ops snd_mpu401_uart_input = 491static const struct snd_rawmidi_ops snd_mpu401_uart_input =
492{ 492{
493 .open = snd_mpu401_uart_input_open, 493 .open = snd_mpu401_uart_input_open,
494 .close = snd_mpu401_uart_input_close, 494 .close = snd_mpu401_uart_input_close,
diff --git a/sound/drivers/mtpav.c b/sound/drivers/mtpav.c
index 30e8a1d5bc87..00b31f92c504 100644
--- a/sound/drivers/mtpav.c
+++ b/sound/drivers/mtpav.c
@@ -600,13 +600,13 @@ static int snd_mtpav_get_ISA(struct mtpav *mcard)
600/* 600/*
601 */ 601 */
602 602
603static struct snd_rawmidi_ops snd_mtpav_output = { 603static const struct snd_rawmidi_ops snd_mtpav_output = {
604 .open = snd_mtpav_output_open, 604 .open = snd_mtpav_output_open,
605 .close = snd_mtpav_output_close, 605 .close = snd_mtpav_output_close,
606 .trigger = snd_mtpav_output_trigger, 606 .trigger = snd_mtpav_output_trigger,
607}; 607};
608 608
609static struct snd_rawmidi_ops snd_mtpav_input = { 609static const struct snd_rawmidi_ops snd_mtpav_input = {
610 .open = snd_mtpav_input_open, 610 .open = snd_mtpav_input_open,
611 .close = snd_mtpav_input_close, 611 .close = snd_mtpav_input_close,
612 .trigger = snd_mtpav_input_trigger, 612 .trigger = snd_mtpav_input_trigger,
diff --git a/sound/drivers/mts64.c b/sound/drivers/mts64.c
index fd4d18df84d3..f32e81342247 100644
--- a/sound/drivers/mts64.c
+++ b/sound/drivers/mts64.c
@@ -749,13 +749,13 @@ static void snd_mts64_rawmidi_input_trigger(struct snd_rawmidi_substream *substr
749 spin_unlock_irqrestore(&mts->lock, flags); 749 spin_unlock_irqrestore(&mts->lock, flags);
750} 750}
751 751
752static struct snd_rawmidi_ops snd_mts64_rawmidi_output_ops = { 752static const struct snd_rawmidi_ops snd_mts64_rawmidi_output_ops = {
753 .open = snd_mts64_rawmidi_open, 753 .open = snd_mts64_rawmidi_open,
754 .close = snd_mts64_rawmidi_close, 754 .close = snd_mts64_rawmidi_close,
755 .trigger = snd_mts64_rawmidi_output_trigger 755 .trigger = snd_mts64_rawmidi_output_trigger
756}; 756};
757 757
758static struct snd_rawmidi_ops snd_mts64_rawmidi_input_ops = { 758static const struct snd_rawmidi_ops snd_mts64_rawmidi_input_ops = {
759 .open = snd_mts64_rawmidi_open, 759 .open = snd_mts64_rawmidi_open,
760 .close = snd_mts64_rawmidi_close, 760 .close = snd_mts64_rawmidi_close,
761 .trigger = snd_mts64_rawmidi_input_trigger 761 .trigger = snd_mts64_rawmidi_input_trigger
diff --git a/sound/drivers/portman2x4.c b/sound/drivers/portman2x4.c
index 189e3e7028af..ec8a94325ef6 100644
--- a/sound/drivers/portman2x4.c
+++ b/sound/drivers/portman2x4.c
@@ -546,13 +546,13 @@ static void snd_portman_midi_output_trigger(struct snd_rawmidi_substream *substr
546 spin_unlock_irqrestore(&pm->reg_lock, flags); 546 spin_unlock_irqrestore(&pm->reg_lock, flags);
547} 547}
548 548
549static struct snd_rawmidi_ops snd_portman_midi_output = { 549static const struct snd_rawmidi_ops snd_portman_midi_output = {
550 .open = snd_portman_midi_open, 550 .open = snd_portman_midi_open,
551 .close = snd_portman_midi_close, 551 .close = snd_portman_midi_close,
552 .trigger = snd_portman_midi_output_trigger, 552 .trigger = snd_portman_midi_output_trigger,
553}; 553};
554 554
555static struct snd_rawmidi_ops snd_portman_midi_input = { 555static const struct snd_rawmidi_ops snd_portman_midi_input = {
556 .open = snd_portman_midi_open, 556 .open = snd_portman_midi_open,
557 .close = snd_portman_midi_close, 557 .close = snd_portman_midi_close,
558 .trigger = snd_portman_midi_input_trigger, 558 .trigger = snd_portman_midi_input_trigger,
diff --git a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c
index 1927b89e1d1f..60d51ac4ccfe 100644
--- a/sound/drivers/serial-u16550.c
+++ b/sound/drivers/serial-u16550.c
@@ -752,14 +752,14 @@ static void snd_uart16550_output_trigger(struct snd_rawmidi_substream *substream
752 snd_uart16550_output_write(substream); 752 snd_uart16550_output_write(substream);
753} 753}
754 754
755static struct snd_rawmidi_ops snd_uart16550_output = 755static const struct snd_rawmidi_ops snd_uart16550_output =
756{ 756{
757 .open = snd_uart16550_output_open, 757 .open = snd_uart16550_output_open,
758 .close = snd_uart16550_output_close, 758 .close = snd_uart16550_output_close,
759 .trigger = snd_uart16550_output_trigger, 759 .trigger = snd_uart16550_output_trigger,
760}; 760};
761 761
762static struct snd_rawmidi_ops snd_uart16550_input = 762static const struct snd_rawmidi_ops snd_uart16550_input =
763{ 763{
764 .open = snd_uart16550_input_open, 764 .open = snd_uart16550_input_open,
765 .close = snd_uart16550_input_close, 765 .close = snd_uart16550_input_close,
diff --git a/sound/drivers/vx/vx_pcm.c b/sound/drivers/vx/vx_pcm.c
index 11467272089e..ea7b377f0378 100644
--- a/sound/drivers/vx/vx_pcm.c
+++ b/sound/drivers/vx/vx_pcm.c
@@ -1015,7 +1015,7 @@ static void vx_pcm_capture_update(struct vx_core *chip, struct snd_pcm_substream
1015 int size, space, count; 1015 int size, space, count;
1016 struct snd_pcm_runtime *runtime = subs->runtime; 1016 struct snd_pcm_runtime *runtime = subs->runtime;
1017 1017
1018 if (! pipe->prepared || (chip->chip_status & VX_STAT_IS_STALE)) 1018 if (!pipe->running || (chip->chip_status & VX_STAT_IS_STALE))
1019 return; 1019 return;
1020 1020
1021 size = runtime->buffer_size - snd_pcm_capture_avail(runtime); 1021 size = runtime->buffer_size - snd_pcm_capture_avail(runtime);
@@ -1048,8 +1048,10 @@ static void vx_pcm_capture_update(struct vx_core *chip, struct snd_pcm_substream
1048 /* ok, let's accelerate! */ 1048 /* ok, let's accelerate! */
1049 int align = pipe->align * 3; 1049 int align = pipe->align * 3;
1050 space = (count / align) * align; 1050 space = (count / align) * align;
1051 vx_pseudo_dma_read(chip, runtime, pipe, space); 1051 if (space > 0) {
1052 count -= space; 1052 vx_pseudo_dma_read(chip, runtime, pipe, space);
1053 count -= space;
1054 }
1053 } 1055 }
1054 /* read the rest of bytes */ 1056 /* read the rest of bytes */
1055 while (count > 0) { 1057 while (count > 0) {
diff --git a/sound/firewire/Kconfig b/sound/firewire/Kconfig
index ab894ed1ff67..9f00696c4e4a 100644
--- a/sound/firewire/Kconfig
+++ b/sound/firewire/Kconfig
@@ -34,6 +34,7 @@ config SND_OXFW
34 * LaCie Firewire Speakers 34 * LaCie Firewire Speakers
35 * Behringer F-Control Audio 202 35 * Behringer F-Control Audio 202
36 * Mackie(Loud) Onyx-i series (former models) 36 * Mackie(Loud) Onyx-i series (former models)
37 * Mackie(Loud) Onyx 1640i (former model)
37 * Mackie(Loud) Onyx Satellite 38 * Mackie(Loud) Onyx Satellite
38 * Mackie(Loud) Tapco Link.Firewire 39 * Mackie(Loud) Tapco Link.Firewire
39 * Mackie(Loud) d.2 pro/d.4 pro 40 * Mackie(Loud) d.2 pro/d.4 pro
diff --git a/sound/firewire/bebob/bebob_hwdep.c b/sound/firewire/bebob/bebob_hwdep.c
index ce731f4d8b4f..2b367c21b80c 100644
--- a/sound/firewire/bebob/bebob_hwdep.c
+++ b/sound/firewire/bebob/bebob_hwdep.c
@@ -172,16 +172,15 @@ hwdep_compat_ioctl(struct snd_hwdep *hwdep, struct file *file,
172#define hwdep_compat_ioctl NULL 172#define hwdep_compat_ioctl NULL
173#endif 173#endif
174 174
175static const struct snd_hwdep_ops hwdep_ops = {
176 .read = hwdep_read,
177 .release = hwdep_release,
178 .poll = hwdep_poll,
179 .ioctl = hwdep_ioctl,
180 .ioctl_compat = hwdep_compat_ioctl,
181};
182
183int snd_bebob_create_hwdep_device(struct snd_bebob *bebob) 175int snd_bebob_create_hwdep_device(struct snd_bebob *bebob)
184{ 176{
177 static const struct snd_hwdep_ops ops = {
178 .read = hwdep_read,
179 .release = hwdep_release,
180 .poll = hwdep_poll,
181 .ioctl = hwdep_ioctl,
182 .ioctl_compat = hwdep_compat_ioctl,
183 };
185 struct snd_hwdep *hwdep; 184 struct snd_hwdep *hwdep;
186 int err; 185 int err;
187 186
@@ -190,7 +189,7 @@ int snd_bebob_create_hwdep_device(struct snd_bebob *bebob)
190 goto end; 189 goto end;
191 strcpy(hwdep->name, "BeBoB"); 190 strcpy(hwdep->name, "BeBoB");
192 hwdep->iface = SNDRV_HWDEP_IFACE_FW_BEBOB; 191 hwdep->iface = SNDRV_HWDEP_IFACE_FW_BEBOB;
193 hwdep->ops = hwdep_ops; 192 hwdep->ops = ops;
194 hwdep->private_data = bebob; 193 hwdep->private_data = bebob;
195 hwdep->exclusive = true; 194 hwdep->exclusive = true;
196end: 195end:
diff --git a/sound/firewire/bebob/bebob_midi.c b/sound/firewire/bebob/bebob_midi.c
index 868eb0decbec..3befa3eca6ef 100644
--- a/sound/firewire/bebob/bebob_midi.c
+++ b/sound/firewire/bebob/bebob_midi.c
@@ -106,18 +106,6 @@ static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up)
106 spin_unlock_irqrestore(&bebob->lock, flags); 106 spin_unlock_irqrestore(&bebob->lock, flags);
107} 107}
108 108
109static struct snd_rawmidi_ops midi_capture_ops = {
110 .open = midi_capture_open,
111 .close = midi_capture_close,
112 .trigger = midi_capture_trigger,
113};
114
115static struct snd_rawmidi_ops midi_playback_ops = {
116 .open = midi_playback_open,
117 .close = midi_playback_close,
118 .trigger = midi_playback_trigger,
119};
120
121static void set_midi_substream_names(struct snd_bebob *bebob, 109static void set_midi_substream_names(struct snd_bebob *bebob,
122 struct snd_rawmidi_str *str) 110 struct snd_rawmidi_str *str)
123{ 111{
@@ -132,6 +120,16 @@ static void set_midi_substream_names(struct snd_bebob *bebob,
132 120
133int snd_bebob_create_midi_devices(struct snd_bebob *bebob) 121int snd_bebob_create_midi_devices(struct snd_bebob *bebob)
134{ 122{
123 static const struct snd_rawmidi_ops capture_ops = {
124 .open = midi_capture_open,
125 .close = midi_capture_close,
126 .trigger = midi_capture_trigger,
127 };
128 static const struct snd_rawmidi_ops playback_ops = {
129 .open = midi_playback_open,
130 .close = midi_playback_close,
131 .trigger = midi_playback_trigger,
132 };
135 struct snd_rawmidi *rmidi; 133 struct snd_rawmidi *rmidi;
136 struct snd_rawmidi_str *str; 134 struct snd_rawmidi_str *str;
137 int err; 135 int err;
@@ -151,7 +149,7 @@ int snd_bebob_create_midi_devices(struct snd_bebob *bebob)
151 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT; 149 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
152 150
153 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, 151 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
154 &midi_capture_ops); 152 &capture_ops);
155 153
156 str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT]; 154 str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT];
157 155
@@ -162,7 +160,7 @@ int snd_bebob_create_midi_devices(struct snd_bebob *bebob)
162 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT; 160 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT;
163 161
164 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, 162 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
165 &midi_playback_ops); 163 &playback_ops);
166 164
167 str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT]; 165 str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT];
168 166
diff --git a/sound/firewire/bebob/bebob_pcm.c b/sound/firewire/bebob/bebob_pcm.c
index 5d7b9343fa85..9e27eb8e1dd4 100644
--- a/sound/firewire/bebob/bebob_pcm.c
+++ b/sound/firewire/bebob/bebob_pcm.c
@@ -359,32 +359,31 @@ pcm_playback_pointer(struct snd_pcm_substream *sbstrm)
359 return amdtp_stream_pcm_pointer(&bebob->rx_stream); 359 return amdtp_stream_pcm_pointer(&bebob->rx_stream);
360} 360}
361 361
362static const struct snd_pcm_ops pcm_capture_ops = {
363 .open = pcm_open,
364 .close = pcm_close,
365 .ioctl = snd_pcm_lib_ioctl,
366 .hw_params = pcm_capture_hw_params,
367 .hw_free = pcm_capture_hw_free,
368 .prepare = pcm_capture_prepare,
369 .trigger = pcm_capture_trigger,
370 .pointer = pcm_capture_pointer,
371 .page = snd_pcm_lib_get_vmalloc_page,
372};
373static const struct snd_pcm_ops pcm_playback_ops = {
374 .open = pcm_open,
375 .close = pcm_close,
376 .ioctl = snd_pcm_lib_ioctl,
377 .hw_params = pcm_playback_hw_params,
378 .hw_free = pcm_playback_hw_free,
379 .prepare = pcm_playback_prepare,
380 .trigger = pcm_playback_trigger,
381 .pointer = pcm_playback_pointer,
382 .page = snd_pcm_lib_get_vmalloc_page,
383 .mmap = snd_pcm_lib_mmap_vmalloc,
384};
385
386int snd_bebob_create_pcm_devices(struct snd_bebob *bebob) 362int snd_bebob_create_pcm_devices(struct snd_bebob *bebob)
387{ 363{
364 static const struct snd_pcm_ops capture_ops = {
365 .open = pcm_open,
366 .close = pcm_close,
367 .ioctl = snd_pcm_lib_ioctl,
368 .hw_params = pcm_capture_hw_params,
369 .hw_free = pcm_capture_hw_free,
370 .prepare = pcm_capture_prepare,
371 .trigger = pcm_capture_trigger,
372 .pointer = pcm_capture_pointer,
373 .page = snd_pcm_lib_get_vmalloc_page,
374 };
375 static const struct snd_pcm_ops playback_ops = {
376 .open = pcm_open,
377 .close = pcm_close,
378 .ioctl = snd_pcm_lib_ioctl,
379 .hw_params = pcm_playback_hw_params,
380 .hw_free = pcm_playback_hw_free,
381 .prepare = pcm_playback_prepare,
382 .trigger = pcm_playback_trigger,
383 .pointer = pcm_playback_pointer,
384 .page = snd_pcm_lib_get_vmalloc_page,
385 .mmap = snd_pcm_lib_mmap_vmalloc,
386 };
388 struct snd_pcm *pcm; 387 struct snd_pcm *pcm;
389 int err; 388 int err;
390 389
@@ -395,8 +394,8 @@ int snd_bebob_create_pcm_devices(struct snd_bebob *bebob)
395 pcm->private_data = bebob; 394 pcm->private_data = bebob;
396 snprintf(pcm->name, sizeof(pcm->name), 395 snprintf(pcm->name, sizeof(pcm->name),
397 "%s PCM", bebob->card->shortname); 396 "%s PCM", bebob->card->shortname);
398 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &pcm_playback_ops); 397 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_ops);
399 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pcm_capture_ops); 398 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &capture_ops);
400end: 399end:
401 return err; 400 return err;
402} 401}
diff --git a/sound/firewire/dice/dice-interface.h b/sound/firewire/dice/dice-interface.h
index 27b044f84c81..47f2c0a6f5d9 100644
--- a/sound/firewire/dice/dice-interface.h
+++ b/sound/firewire/dice/dice-interface.h
@@ -251,6 +251,7 @@
251 251
252/* 252/*
253 * The speed at which the packets are sent, SCODE_100-_400; read/write. 253 * The speed at which the packets are sent, SCODE_100-_400; read/write.
254 * SCODE_800 is only available in Dice III.
254 */ 255 */
255#define TX_SPEED 0x014 256#define TX_SPEED 0x014
256 257
diff --git a/sound/firewire/dice/dice-midi.c b/sound/firewire/dice/dice-midi.c
index a040617505a7..8ff6da3c51f7 100644
--- a/sound/firewire/dice/dice-midi.c
+++ b/sound/firewire/dice/dice-midi.c
@@ -78,18 +78,6 @@ static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up)
78 spin_unlock_irqrestore(&dice->lock, flags); 78 spin_unlock_irqrestore(&dice->lock, flags);
79} 79}
80 80
81static struct snd_rawmidi_ops capture_ops = {
82 .open = midi_open,
83 .close = midi_close,
84 .trigger = midi_capture_trigger,
85};
86
87static struct snd_rawmidi_ops playback_ops = {
88 .open = midi_open,
89 .close = midi_close,
90 .trigger = midi_playback_trigger,
91};
92
93static void set_midi_substream_names(struct snd_dice *dice, 81static void set_midi_substream_names(struct snd_dice *dice,
94 struct snd_rawmidi_str *str) 82 struct snd_rawmidi_str *str)
95{ 83{
@@ -103,6 +91,16 @@ static void set_midi_substream_names(struct snd_dice *dice,
103 91
104int snd_dice_create_midi(struct snd_dice *dice) 92int snd_dice_create_midi(struct snd_dice *dice)
105{ 93{
94 static const struct snd_rawmidi_ops capture_ops = {
95 .open = midi_open,
96 .close = midi_close,
97 .trigger = midi_capture_trigger,
98 };
99 static const struct snd_rawmidi_ops playback_ops = {
100 .open = midi_open,
101 .close = midi_close,
102 .trigger = midi_playback_trigger,
103 };
106 __be32 reg; 104 __be32 reg;
107 struct snd_rawmidi *rmidi; 105 struct snd_rawmidi *rmidi;
108 struct snd_rawmidi_str *str; 106 struct snd_rawmidi_str *str;
diff --git a/sound/firewire/dice/dice-stream.c b/sound/firewire/dice/dice-stream.c
index ec4db3a514fc..8573289c381e 100644
--- a/sound/firewire/dice/dice-stream.c
+++ b/sound/firewire/dice/dice-stream.c
@@ -195,6 +195,7 @@ static int start_streams(struct snd_dice *dice, enum amdtp_stream_direction dir,
195 unsigned int i, pcm_chs, midi_ports; 195 unsigned int i, pcm_chs, midi_ports;
196 struct amdtp_stream *streams; 196 struct amdtp_stream *streams;
197 struct fw_iso_resources *resources; 197 struct fw_iso_resources *resources;
198 struct fw_device *fw_dev = fw_parent_device(dice->unit);
198 int err = 0; 199 int err = 0;
199 200
200 if (dir == AMDTP_IN_STREAM) { 201 if (dir == AMDTP_IN_STREAM) {
@@ -237,8 +238,17 @@ static int start_streams(struct snd_dice *dice, enum amdtp_stream_direction dir,
237 if (err < 0) 238 if (err < 0)
238 return err; 239 return err;
239 240
241 if (dir == AMDTP_IN_STREAM) {
242 reg[0] = cpu_to_be32(fw_dev->max_speed);
243 err = snd_dice_transaction_write_tx(dice,
244 params->size * i + TX_SPEED,
245 reg, sizeof(reg[0]));
246 if (err < 0)
247 return err;
248 }
249
240 err = amdtp_stream_start(&streams[i], resources[i].channel, 250 err = amdtp_stream_start(&streams[i], resources[i].channel,
241 fw_parent_device(dice->unit)->max_speed); 251 fw_dev->max_speed);
242 if (err < 0) 252 if (err < 0)
243 return err; 253 return err;
244 } 254 }
diff --git a/sound/firewire/digi00x/digi00x-hwdep.c b/sound/firewire/digi00x/digi00x-hwdep.c
index f188e4758fd2..463c6b8e864d 100644
--- a/sound/firewire/digi00x/digi00x-hwdep.c
+++ b/sound/firewire/digi00x/digi00x-hwdep.c
@@ -173,16 +173,15 @@ static int hwdep_compat_ioctl(struct snd_hwdep *hwdep, struct file *file,
173#define hwdep_compat_ioctl NULL 173#define hwdep_compat_ioctl NULL
174#endif 174#endif
175 175
176static const struct snd_hwdep_ops hwdep_ops = {
177 .read = hwdep_read,
178 .release = hwdep_release,
179 .poll = hwdep_poll,
180 .ioctl = hwdep_ioctl,
181 .ioctl_compat = hwdep_compat_ioctl,
182};
183
184int snd_dg00x_create_hwdep_device(struct snd_dg00x *dg00x) 176int snd_dg00x_create_hwdep_device(struct snd_dg00x *dg00x)
185{ 177{
178 static const struct snd_hwdep_ops ops = {
179 .read = hwdep_read,
180 .release = hwdep_release,
181 .poll = hwdep_poll,
182 .ioctl = hwdep_ioctl,
183 .ioctl_compat = hwdep_compat_ioctl,
184 };
186 struct snd_hwdep *hwdep; 185 struct snd_hwdep *hwdep;
187 int err; 186 int err;
188 187
@@ -192,7 +191,7 @@ int snd_dg00x_create_hwdep_device(struct snd_dg00x *dg00x)
192 191
193 strcpy(hwdep->name, "Digi00x"); 192 strcpy(hwdep->name, "Digi00x");
194 hwdep->iface = SNDRV_HWDEP_IFACE_FW_DIGI00X; 193 hwdep->iface = SNDRV_HWDEP_IFACE_FW_DIGI00X;
195 hwdep->ops = hwdep_ops; 194 hwdep->ops = ops;
196 hwdep->private_data = dg00x; 195 hwdep->private_data = dg00x;
197 hwdep->exclusive = true; 196 hwdep->exclusive = true;
198 197
diff --git a/sound/firewire/digi00x/digi00x-midi.c b/sound/firewire/digi00x/digi00x-midi.c
index 1a72a382b384..915d2a21223e 100644
--- a/sound/firewire/digi00x/digi00x-midi.c
+++ b/sound/firewire/digi00x/digi00x-midi.c
@@ -76,18 +76,6 @@ static void midi_phys_playback_trigger(struct snd_rawmidi_substream *substream,
76 spin_unlock_irqrestore(&dg00x->lock, flags); 76 spin_unlock_irqrestore(&dg00x->lock, flags);
77} 77}
78 78
79static struct snd_rawmidi_ops midi_phys_capture_ops = {
80 .open = midi_phys_open,
81 .close = midi_phys_close,
82 .trigger = midi_phys_capture_trigger,
83};
84
85static struct snd_rawmidi_ops midi_phys_playback_ops = {
86 .open = midi_phys_open,
87 .close = midi_phys_close,
88 .trigger = midi_phys_playback_trigger,
89};
90
91static int midi_ctl_open(struct snd_rawmidi_substream *substream) 79static int midi_ctl_open(struct snd_rawmidi_substream *substream)
92{ 80{
93 /* Do nothing. */ 81 /* Do nothing. */
@@ -139,18 +127,6 @@ static void midi_ctl_playback_trigger(struct snd_rawmidi_substream *substream,
139 spin_unlock_irqrestore(&dg00x->lock, flags); 127 spin_unlock_irqrestore(&dg00x->lock, flags);
140} 128}
141 129
142static struct snd_rawmidi_ops midi_ctl_capture_ops = {
143 .open = midi_ctl_open,
144 .close = midi_ctl_capture_close,
145 .trigger = midi_ctl_capture_trigger,
146};
147
148static struct snd_rawmidi_ops midi_ctl_playback_ops = {
149 .open = midi_ctl_open,
150 .close = midi_ctl_playback_close,
151 .trigger = midi_ctl_playback_trigger,
152};
153
154static void set_midi_substream_names(struct snd_dg00x *dg00x, 130static void set_midi_substream_names(struct snd_dg00x *dg00x,
155 struct snd_rawmidi_str *str, 131 struct snd_rawmidi_str *str,
156 bool is_ctl) 132 bool is_ctl)
@@ -172,6 +148,26 @@ static void set_midi_substream_names(struct snd_dg00x *dg00x,
172 148
173int snd_dg00x_create_midi_devices(struct snd_dg00x *dg00x) 149int snd_dg00x_create_midi_devices(struct snd_dg00x *dg00x)
174{ 150{
151 static const struct snd_rawmidi_ops phys_capture_ops = {
152 .open = midi_phys_open,
153 .close = midi_phys_close,
154 .trigger = midi_phys_capture_trigger,
155 };
156 static const struct snd_rawmidi_ops phys_playback_ops = {
157 .open = midi_phys_open,
158 .close = midi_phys_close,
159 .trigger = midi_phys_playback_trigger,
160 };
161 static const struct snd_rawmidi_ops ctl_capture_ops = {
162 .open = midi_ctl_open,
163 .close = midi_ctl_capture_close,
164 .trigger = midi_ctl_capture_trigger,
165 };
166 static const struct snd_rawmidi_ops ctl_playback_ops = {
167 .open = midi_ctl_open,
168 .close = midi_ctl_playback_close,
169 .trigger = midi_ctl_playback_trigger,
170 };
175 struct snd_rawmidi *rmidi[2]; 171 struct snd_rawmidi *rmidi[2];
176 struct snd_rawmidi_str *str; 172 struct snd_rawmidi_str *str;
177 unsigned int i; 173 unsigned int i;
@@ -187,9 +183,9 @@ int snd_dg00x_create_midi_devices(struct snd_dg00x *dg00x)
187 "%s MIDI", dg00x->card->shortname); 183 "%s MIDI", dg00x->card->shortname);
188 184
189 snd_rawmidi_set_ops(rmidi[0], SNDRV_RAWMIDI_STREAM_INPUT, 185 snd_rawmidi_set_ops(rmidi[0], SNDRV_RAWMIDI_STREAM_INPUT,
190 &midi_phys_capture_ops); 186 &phys_capture_ops);
191 snd_rawmidi_set_ops(rmidi[0], SNDRV_RAWMIDI_STREAM_OUTPUT, 187 snd_rawmidi_set_ops(rmidi[0], SNDRV_RAWMIDI_STREAM_OUTPUT,
192 &midi_phys_playback_ops); 188 &phys_playback_ops);
193 189
194 /* Add a pair of control midi ports. */ 190 /* Add a pair of control midi ports. */
195 err = snd_rawmidi_new(dg00x->card, dg00x->card->driver, 1, 191 err = snd_rawmidi_new(dg00x->card, dg00x->card->driver, 1,
@@ -201,9 +197,9 @@ int snd_dg00x_create_midi_devices(struct snd_dg00x *dg00x)
201 "%s control", dg00x->card->shortname); 197 "%s control", dg00x->card->shortname);
202 198
203 snd_rawmidi_set_ops(rmidi[1], SNDRV_RAWMIDI_STREAM_INPUT, 199 snd_rawmidi_set_ops(rmidi[1], SNDRV_RAWMIDI_STREAM_INPUT,
204 &midi_ctl_capture_ops); 200 &ctl_capture_ops);
205 snd_rawmidi_set_ops(rmidi[1], SNDRV_RAWMIDI_STREAM_OUTPUT, 201 snd_rawmidi_set_ops(rmidi[1], SNDRV_RAWMIDI_STREAM_OUTPUT,
206 &midi_ctl_playback_ops); 202 &ctl_playback_ops);
207 203
208 for (i = 0; i < ARRAY_SIZE(rmidi); i++) { 204 for (i = 0; i < ARRAY_SIZE(rmidi); i++) {
209 rmidi[i]->private_data = dg00x; 205 rmidi[i]->private_data = dg00x;
diff --git a/sound/firewire/digi00x/digi00x-pcm.c b/sound/firewire/digi00x/digi00x-pcm.c
index 613f05872770..68d1c52db051 100644
--- a/sound/firewire/digi00x/digi00x-pcm.c
+++ b/sound/firewire/digi00x/digi00x-pcm.c
@@ -329,33 +329,31 @@ static snd_pcm_uframes_t pcm_playback_pointer(struct snd_pcm_substream *sbstrm)
329 return amdtp_stream_pcm_pointer(&dg00x->rx_stream); 329 return amdtp_stream_pcm_pointer(&dg00x->rx_stream);
330} 330}
331 331
332static const struct snd_pcm_ops pcm_capture_ops = {
333 .open = pcm_open,
334 .close = pcm_close,
335 .ioctl = snd_pcm_lib_ioctl,
336 .hw_params = pcm_capture_hw_params,
337 .hw_free = pcm_capture_hw_free,
338 .prepare = pcm_capture_prepare,
339 .trigger = pcm_capture_trigger,
340 .pointer = pcm_capture_pointer,
341 .page = snd_pcm_lib_get_vmalloc_page,
342};
343
344static const struct snd_pcm_ops pcm_playback_ops = {
345 .open = pcm_open,
346 .close = pcm_close,
347 .ioctl = snd_pcm_lib_ioctl,
348 .hw_params = pcm_playback_hw_params,
349 .hw_free = pcm_playback_hw_free,
350 .prepare = pcm_playback_prepare,
351 .trigger = pcm_playback_trigger,
352 .pointer = pcm_playback_pointer,
353 .page = snd_pcm_lib_get_vmalloc_page,
354 .mmap = snd_pcm_lib_mmap_vmalloc,
355};
356
357int snd_dg00x_create_pcm_devices(struct snd_dg00x *dg00x) 332int snd_dg00x_create_pcm_devices(struct snd_dg00x *dg00x)
358{ 333{
334 static const struct snd_pcm_ops capture_ops = {
335 .open = pcm_open,
336 .close = pcm_close,
337 .ioctl = snd_pcm_lib_ioctl,
338 .hw_params = pcm_capture_hw_params,
339 .hw_free = pcm_capture_hw_free,
340 .prepare = pcm_capture_prepare,
341 .trigger = pcm_capture_trigger,
342 .pointer = pcm_capture_pointer,
343 .page = snd_pcm_lib_get_vmalloc_page,
344 };
345 static const struct snd_pcm_ops playback_ops = {
346 .open = pcm_open,
347 .close = pcm_close,
348 .ioctl = snd_pcm_lib_ioctl,
349 .hw_params = pcm_playback_hw_params,
350 .hw_free = pcm_playback_hw_free,
351 .prepare = pcm_playback_prepare,
352 .trigger = pcm_playback_trigger,
353 .pointer = pcm_playback_pointer,
354 .page = snd_pcm_lib_get_vmalloc_page,
355 .mmap = snd_pcm_lib_mmap_vmalloc,
356 };
359 struct snd_pcm *pcm; 357 struct snd_pcm *pcm;
360 int err; 358 int err;
361 359
@@ -366,8 +364,8 @@ int snd_dg00x_create_pcm_devices(struct snd_dg00x *dg00x)
366 pcm->private_data = dg00x; 364 pcm->private_data = dg00x;
367 snprintf(pcm->name, sizeof(pcm->name), 365 snprintf(pcm->name, sizeof(pcm->name),
368 "%s PCM", dg00x->card->shortname); 366 "%s PCM", dg00x->card->shortname);
369 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &pcm_playback_ops); 367 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_ops);
370 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pcm_capture_ops); 368 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &capture_ops);
371 369
372 return 0; 370 return 0;
373} 371}
diff --git a/sound/firewire/fireworks/fireworks_hwdep.c b/sound/firewire/fireworks/fireworks_hwdep.c
index 2e1d9a23920c..a3a3a16f5e08 100644
--- a/sound/firewire/fireworks/fireworks_hwdep.c
+++ b/sound/firewire/fireworks/fireworks_hwdep.c
@@ -303,17 +303,16 @@ hwdep_compat_ioctl(struct snd_hwdep *hwdep, struct file *file,
303#define hwdep_compat_ioctl NULL 303#define hwdep_compat_ioctl NULL
304#endif 304#endif
305 305
306static const struct snd_hwdep_ops hwdep_ops = {
307 .read = hwdep_read,
308 .write = hwdep_write,
309 .release = hwdep_release,
310 .poll = hwdep_poll,
311 .ioctl = hwdep_ioctl,
312 .ioctl_compat = hwdep_compat_ioctl,
313};
314
315int snd_efw_create_hwdep_device(struct snd_efw *efw) 306int snd_efw_create_hwdep_device(struct snd_efw *efw)
316{ 307{
308 static const struct snd_hwdep_ops ops = {
309 .read = hwdep_read,
310 .write = hwdep_write,
311 .release = hwdep_release,
312 .poll = hwdep_poll,
313 .ioctl = hwdep_ioctl,
314 .ioctl_compat = hwdep_compat_ioctl,
315 };
317 struct snd_hwdep *hwdep; 316 struct snd_hwdep *hwdep;
318 int err; 317 int err;
319 318
@@ -322,7 +321,7 @@ int snd_efw_create_hwdep_device(struct snd_efw *efw)
322 goto end; 321 goto end;
323 strcpy(hwdep->name, "Fireworks"); 322 strcpy(hwdep->name, "Fireworks");
324 hwdep->iface = SNDRV_HWDEP_IFACE_FW_FIREWORKS; 323 hwdep->iface = SNDRV_HWDEP_IFACE_FW_FIREWORKS;
325 hwdep->ops = hwdep_ops; 324 hwdep->ops = ops;
326 hwdep->private_data = efw; 325 hwdep->private_data = efw;
327 hwdep->exclusive = true; 326 hwdep->exclusive = true;
328end: 327end:
diff --git a/sound/firewire/fireworks/fireworks_midi.c b/sound/firewire/fireworks/fireworks_midi.c
index 3e8c4cf9fe1e..f5da2cd4ce42 100644
--- a/sound/firewire/fireworks/fireworks_midi.c
+++ b/sound/firewire/fireworks/fireworks_midi.c
@@ -107,18 +107,6 @@ static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up)
107 spin_unlock_irqrestore(&efw->lock, flags); 107 spin_unlock_irqrestore(&efw->lock, flags);
108} 108}
109 109
110static struct snd_rawmidi_ops midi_capture_ops = {
111 .open = midi_capture_open,
112 .close = midi_capture_close,
113 .trigger = midi_capture_trigger,
114};
115
116static struct snd_rawmidi_ops midi_playback_ops = {
117 .open = midi_playback_open,
118 .close = midi_playback_close,
119 .trigger = midi_playback_trigger,
120};
121
122static void set_midi_substream_names(struct snd_efw *efw, 110static void set_midi_substream_names(struct snd_efw *efw,
123 struct snd_rawmidi_str *str) 111 struct snd_rawmidi_str *str)
124{ 112{
@@ -132,6 +120,16 @@ static void set_midi_substream_names(struct snd_efw *efw,
132 120
133int snd_efw_create_midi_devices(struct snd_efw *efw) 121int snd_efw_create_midi_devices(struct snd_efw *efw)
134{ 122{
123 static const struct snd_rawmidi_ops capture_ops = {
124 .open = midi_capture_open,
125 .close = midi_capture_close,
126 .trigger = midi_capture_trigger,
127 };
128 static const struct snd_rawmidi_ops playback_ops = {
129 .open = midi_playback_open,
130 .close = midi_playback_close,
131 .trigger = midi_playback_trigger,
132 };
135 struct snd_rawmidi *rmidi; 133 struct snd_rawmidi *rmidi;
136 struct snd_rawmidi_str *str; 134 struct snd_rawmidi_str *str;
137 int err; 135 int err;
@@ -151,7 +149,7 @@ int snd_efw_create_midi_devices(struct snd_efw *efw)
151 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT; 149 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
152 150
153 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, 151 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
154 &midi_capture_ops); 152 &capture_ops);
155 153
156 str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT]; 154 str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT];
157 155
@@ -162,7 +160,7 @@ int snd_efw_create_midi_devices(struct snd_efw *efw)
162 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT; 160 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT;
163 161
164 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, 162 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
165 &midi_playback_ops); 163 &playback_ops);
166 164
167 str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT]; 165 str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT];
168 166
diff --git a/sound/firewire/fireworks/fireworks_pcm.c b/sound/firewire/fireworks/fireworks_pcm.c
index f4fbf75ed198..9171702f7d0b 100644
--- a/sound/firewire/fireworks/fireworks_pcm.c
+++ b/sound/firewire/fireworks/fireworks_pcm.c
@@ -383,33 +383,31 @@ static snd_pcm_uframes_t pcm_playback_pointer(struct snd_pcm_substream *sbstrm)
383 return amdtp_stream_pcm_pointer(&efw->rx_stream); 383 return amdtp_stream_pcm_pointer(&efw->rx_stream);
384} 384}
385 385
386static const struct snd_pcm_ops pcm_capture_ops = {
387 .open = pcm_open,
388 .close = pcm_close,
389 .ioctl = snd_pcm_lib_ioctl,
390 .hw_params = pcm_capture_hw_params,
391 .hw_free = pcm_capture_hw_free,
392 .prepare = pcm_capture_prepare,
393 .trigger = pcm_capture_trigger,
394 .pointer = pcm_capture_pointer,
395 .page = snd_pcm_lib_get_vmalloc_page,
396};
397
398static const struct snd_pcm_ops pcm_playback_ops = {
399 .open = pcm_open,
400 .close = pcm_close,
401 .ioctl = snd_pcm_lib_ioctl,
402 .hw_params = pcm_playback_hw_params,
403 .hw_free = pcm_playback_hw_free,
404 .prepare = pcm_playback_prepare,
405 .trigger = pcm_playback_trigger,
406 .pointer = pcm_playback_pointer,
407 .page = snd_pcm_lib_get_vmalloc_page,
408 .mmap = snd_pcm_lib_mmap_vmalloc,
409};
410
411int snd_efw_create_pcm_devices(struct snd_efw *efw) 386int snd_efw_create_pcm_devices(struct snd_efw *efw)
412{ 387{
388 static const struct snd_pcm_ops capture_ops = {
389 .open = pcm_open,
390 .close = pcm_close,
391 .ioctl = snd_pcm_lib_ioctl,
392 .hw_params = pcm_capture_hw_params,
393 .hw_free = pcm_capture_hw_free,
394 .prepare = pcm_capture_prepare,
395 .trigger = pcm_capture_trigger,
396 .pointer = pcm_capture_pointer,
397 .page = snd_pcm_lib_get_vmalloc_page,
398 };
399 static const struct snd_pcm_ops playback_ops = {
400 .open = pcm_open,
401 .close = pcm_close,
402 .ioctl = snd_pcm_lib_ioctl,
403 .hw_params = pcm_playback_hw_params,
404 .hw_free = pcm_playback_hw_free,
405 .prepare = pcm_playback_prepare,
406 .trigger = pcm_playback_trigger,
407 .pointer = pcm_playback_pointer,
408 .page = snd_pcm_lib_get_vmalloc_page,
409 .mmap = snd_pcm_lib_mmap_vmalloc,
410 };
413 struct snd_pcm *pcm; 411 struct snd_pcm *pcm;
414 int err; 412 int err;
415 413
@@ -419,8 +417,8 @@ int snd_efw_create_pcm_devices(struct snd_efw *efw)
419 417
420 pcm->private_data = efw; 418 pcm->private_data = efw;
421 snprintf(pcm->name, sizeof(pcm->name), "%s PCM", efw->card->shortname); 419 snprintf(pcm->name, sizeof(pcm->name), "%s PCM", efw->card->shortname);
422 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &pcm_playback_ops); 420 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_ops);
423 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pcm_capture_ops); 421 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &capture_ops);
424end: 422end:
425 return err; 423 return err;
426} 424}
diff --git a/sound/firewire/oxfw/oxfw-midi.c b/sound/firewire/oxfw/oxfw-midi.c
index 8665e1043d41..b7bbd77dfff1 100644
--- a/sound/firewire/oxfw/oxfw-midi.c
+++ b/sound/firewire/oxfw/oxfw-midi.c
@@ -116,18 +116,6 @@ static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up)
116 spin_unlock_irqrestore(&oxfw->lock, flags); 116 spin_unlock_irqrestore(&oxfw->lock, flags);
117} 117}
118 118
119static struct snd_rawmidi_ops midi_capture_ops = {
120 .open = midi_capture_open,
121 .close = midi_capture_close,
122 .trigger = midi_capture_trigger,
123};
124
125static struct snd_rawmidi_ops midi_playback_ops = {
126 .open = midi_playback_open,
127 .close = midi_playback_close,
128 .trigger = midi_playback_trigger,
129};
130
131static void set_midi_substream_names(struct snd_oxfw *oxfw, 119static void set_midi_substream_names(struct snd_oxfw *oxfw,
132 struct snd_rawmidi_str *str) 120 struct snd_rawmidi_str *str)
133{ 121{
@@ -142,6 +130,16 @@ static void set_midi_substream_names(struct snd_oxfw *oxfw,
142 130
143int snd_oxfw_create_midi(struct snd_oxfw *oxfw) 131int snd_oxfw_create_midi(struct snd_oxfw *oxfw)
144{ 132{
133 static const struct snd_rawmidi_ops capture_ops = {
134 .open = midi_capture_open,
135 .close = midi_capture_close,
136 .trigger = midi_capture_trigger,
137 };
138 static const struct snd_rawmidi_ops playback_ops = {
139 .open = midi_playback_open,
140 .close = midi_playback_close,
141 .trigger = midi_playback_trigger,
142 };
145 struct snd_rawmidi *rmidi; 143 struct snd_rawmidi *rmidi;
146 struct snd_rawmidi_str *str; 144 struct snd_rawmidi_str *str;
147 int err; 145 int err;
@@ -164,7 +162,7 @@ int snd_oxfw_create_midi(struct snd_oxfw *oxfw)
164 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT; 162 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
165 163
166 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, 164 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
167 &midi_capture_ops); 165 &capture_ops);
168 166
169 str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT]; 167 str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT];
170 168
@@ -175,7 +173,7 @@ int snd_oxfw_create_midi(struct snd_oxfw *oxfw)
175 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT; 173 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT;
176 174
177 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, 175 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
178 &midi_playback_ops); 176 &playback_ops);
179 177
180 str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT]; 178 str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT];
181 179
diff --git a/sound/firewire/oxfw/oxfw-scs1x.c b/sound/firewire/oxfw/oxfw-scs1x.c
index f897c9831077..93209ebd9121 100644
--- a/sound/firewire/oxfw/oxfw-scs1x.c
+++ b/sound/firewire/oxfw/oxfw-scs1x.c
@@ -297,7 +297,7 @@ static void midi_capture_trigger(struct snd_rawmidi_substream *stream, int up)
297 } 297 }
298} 298}
299 299
300static struct snd_rawmidi_ops midi_capture_ops = { 300static const struct snd_rawmidi_ops midi_capture_ops = {
301 .open = midi_capture_open, 301 .open = midi_capture_open,
302 .close = midi_capture_close, 302 .close = midi_capture_close,
303 .trigger = midi_capture_trigger, 303 .trigger = midi_capture_trigger,
@@ -338,12 +338,6 @@ static void midi_playback_drain(struct snd_rawmidi_substream *stream)
338 wait_event(scs->idle_wait, scs->output_idle); 338 wait_event(scs->idle_wait, scs->output_idle);
339} 339}
340 340
341static struct snd_rawmidi_ops midi_playback_ops = {
342 .open = midi_playback_open,
343 .close = midi_playback_close,
344 .trigger = midi_playback_trigger,
345 .drain = midi_playback_drain,
346};
347static int register_address(struct snd_oxfw *oxfw) 341static int register_address(struct snd_oxfw *oxfw)
348{ 342{
349 struct fw_scs1x *scs = oxfw->spec; 343 struct fw_scs1x *scs = oxfw->spec;
@@ -369,6 +363,12 @@ void snd_oxfw_scs1x_update(struct snd_oxfw *oxfw)
369 363
370int snd_oxfw_scs1x_add(struct snd_oxfw *oxfw) 364int snd_oxfw_scs1x_add(struct snd_oxfw *oxfw)
371{ 365{
366 static const struct snd_rawmidi_ops midi_playback_ops = {
367 .open = midi_playback_open,
368 .close = midi_playback_close,
369 .trigger = midi_playback_trigger,
370 .drain = midi_playback_drain,
371 };
372 struct snd_rawmidi *rmidi; 372 struct snd_rawmidi *rmidi;
373 struct fw_scs1x *scs; 373 struct fw_scs1x *scs;
374 int err; 374 int err;
diff --git a/sound/firewire/oxfw/oxfw.c b/sound/firewire/oxfw/oxfw.c
index e629b88f7d93..74d7fb6efce6 100644
--- a/sound/firewire/oxfw/oxfw.c
+++ b/sound/firewire/oxfw/oxfw.c
@@ -43,6 +43,7 @@ static bool detect_loud_models(struct fw_unit *unit)
43 const char *const models[] = { 43 const char *const models[] = {
44 "Onyxi", 44 "Onyxi",
45 "Onyx-i", 45 "Onyx-i",
46 "Onyx 1640i",
46 "d.Pro", 47 "d.Pro",
47 "Mackie Onyx Satellite", 48 "Mackie Onyx Satellite",
48 "Tapco LINK.firewire 4x6", 49 "Tapco LINK.firewire 4x6",
diff --git a/sound/firewire/tascam/tascam-hwdep.c b/sound/firewire/tascam/tascam-hwdep.c
index 106406cbfaa3..8c4437d0051d 100644
--- a/sound/firewire/tascam/tascam-hwdep.c
+++ b/sound/firewire/tascam/tascam-hwdep.c
@@ -163,16 +163,15 @@ static int hwdep_compat_ioctl(struct snd_hwdep *hwdep, struct file *file,
163#define hwdep_compat_ioctl NULL 163#define hwdep_compat_ioctl NULL
164#endif 164#endif
165 165
166static const struct snd_hwdep_ops hwdep_ops = {
167 .read = hwdep_read,
168 .release = hwdep_release,
169 .poll = hwdep_poll,
170 .ioctl = hwdep_ioctl,
171 .ioctl_compat = hwdep_compat_ioctl,
172};
173
174int snd_tscm_create_hwdep_device(struct snd_tscm *tscm) 166int snd_tscm_create_hwdep_device(struct snd_tscm *tscm)
175{ 167{
168 static const struct snd_hwdep_ops ops = {
169 .read = hwdep_read,
170 .release = hwdep_release,
171 .poll = hwdep_poll,
172 .ioctl = hwdep_ioctl,
173 .ioctl_compat = hwdep_compat_ioctl,
174 };
176 struct snd_hwdep *hwdep; 175 struct snd_hwdep *hwdep;
177 int err; 176 int err;
178 177
@@ -182,7 +181,7 @@ int snd_tscm_create_hwdep_device(struct snd_tscm *tscm)
182 181
183 strcpy(hwdep->name, "Tascam"); 182 strcpy(hwdep->name, "Tascam");
184 hwdep->iface = SNDRV_HWDEP_IFACE_FW_TASCAM; 183 hwdep->iface = SNDRV_HWDEP_IFACE_FW_TASCAM;
185 hwdep->ops = hwdep_ops; 184 hwdep->ops = ops;
186 hwdep->private_data = tscm; 185 hwdep->private_data = tscm;
187 hwdep->exclusive = true; 186 hwdep->exclusive = true;
188 187
diff --git a/sound/firewire/tascam/tascam-midi.c b/sound/firewire/tascam/tascam-midi.c
index 41f842079d9d..df4f95d65925 100644
--- a/sound/firewire/tascam/tascam-midi.c
+++ b/sound/firewire/tascam/tascam-midi.c
@@ -68,20 +68,18 @@ static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up)
68 spin_unlock_irqrestore(&tscm->lock, flags); 68 spin_unlock_irqrestore(&tscm->lock, flags);
69} 69}
70 70
71static struct snd_rawmidi_ops midi_capture_ops = {
72 .open = midi_capture_open,
73 .close = midi_capture_close,
74 .trigger = midi_capture_trigger,
75};
76
77static struct snd_rawmidi_ops midi_playback_ops = {
78 .open = midi_playback_open,
79 .close = midi_playback_close,
80 .trigger = midi_playback_trigger,
81};
82
83int snd_tscm_create_midi_devices(struct snd_tscm *tscm) 71int snd_tscm_create_midi_devices(struct snd_tscm *tscm)
84{ 72{
73 static const struct snd_rawmidi_ops capture_ops = {
74 .open = midi_capture_open,
75 .close = midi_capture_close,
76 .trigger = midi_capture_trigger,
77 };
78 static const struct snd_rawmidi_ops playback_ops = {
79 .open = midi_playback_open,
80 .close = midi_playback_close,
81 .trigger = midi_playback_trigger,
82 };
85 struct snd_rawmidi *rmidi; 83 struct snd_rawmidi *rmidi;
86 struct snd_rawmidi_str *stream; 84 struct snd_rawmidi_str *stream;
87 struct snd_rawmidi_substream *subs; 85 struct snd_rawmidi_substream *subs;
@@ -100,7 +98,7 @@ int snd_tscm_create_midi_devices(struct snd_tscm *tscm)
100 98
101 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT; 99 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
102 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, 100 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
103 &midi_capture_ops); 101 &capture_ops);
104 stream = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT]; 102 stream = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT];
105 103
106 /* Set port names for MIDI input. */ 104 /* Set port names for MIDI input. */
@@ -116,7 +114,7 @@ int snd_tscm_create_midi_devices(struct snd_tscm *tscm)
116 114
117 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT; 115 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT;
118 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, 116 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
119 &midi_playback_ops); 117 &playback_ops);
120 stream = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT]; 118 stream = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT];
121 119
122 /* Set port names for MIDI ourput. */ 120 /* Set port names for MIDI ourput. */
diff --git a/sound/firewire/tascam/tascam-pcm.c b/sound/firewire/tascam/tascam-pcm.c
index 79db1b651f5c..f5dd6ce6b6f1 100644
--- a/sound/firewire/tascam/tascam-pcm.c
+++ b/sound/firewire/tascam/tascam-pcm.c
@@ -268,33 +268,31 @@ static snd_pcm_uframes_t pcm_playback_pointer(struct snd_pcm_substream *sbstrm)
268 return amdtp_stream_pcm_pointer(&tscm->rx_stream); 268 return amdtp_stream_pcm_pointer(&tscm->rx_stream);
269} 269}
270 270
271static const struct snd_pcm_ops pcm_capture_ops = {
272 .open = pcm_open,
273 .close = pcm_close,
274 .ioctl = snd_pcm_lib_ioctl,
275 .hw_params = pcm_capture_hw_params,
276 .hw_free = pcm_capture_hw_free,
277 .prepare = pcm_capture_prepare,
278 .trigger = pcm_capture_trigger,
279 .pointer = pcm_capture_pointer,
280 .page = snd_pcm_lib_get_vmalloc_page,
281};
282
283static const struct snd_pcm_ops pcm_playback_ops = {
284 .open = pcm_open,
285 .close = pcm_close,
286 .ioctl = snd_pcm_lib_ioctl,
287 .hw_params = pcm_playback_hw_params,
288 .hw_free = pcm_playback_hw_free,
289 .prepare = pcm_playback_prepare,
290 .trigger = pcm_playback_trigger,
291 .pointer = pcm_playback_pointer,
292 .page = snd_pcm_lib_get_vmalloc_page,
293 .mmap = snd_pcm_lib_mmap_vmalloc,
294};
295
296int snd_tscm_create_pcm_devices(struct snd_tscm *tscm) 271int snd_tscm_create_pcm_devices(struct snd_tscm *tscm)
297{ 272{
273 static const struct snd_pcm_ops capture_ops = {
274 .open = pcm_open,
275 .close = pcm_close,
276 .ioctl = snd_pcm_lib_ioctl,
277 .hw_params = pcm_capture_hw_params,
278 .hw_free = pcm_capture_hw_free,
279 .prepare = pcm_capture_prepare,
280 .trigger = pcm_capture_trigger,
281 .pointer = pcm_capture_pointer,
282 .page = snd_pcm_lib_get_vmalloc_page,
283 };
284 static const struct snd_pcm_ops playback_ops = {
285 .open = pcm_open,
286 .close = pcm_close,
287 .ioctl = snd_pcm_lib_ioctl,
288 .hw_params = pcm_playback_hw_params,
289 .hw_free = pcm_playback_hw_free,
290 .prepare = pcm_playback_prepare,
291 .trigger = pcm_playback_trigger,
292 .pointer = pcm_playback_pointer,
293 .page = snd_pcm_lib_get_vmalloc_page,
294 .mmap = snd_pcm_lib_mmap_vmalloc,
295 };
298 struct snd_pcm *pcm; 296 struct snd_pcm *pcm;
299 int err; 297 int err;
300 298
@@ -305,8 +303,8 @@ int snd_tscm_create_pcm_devices(struct snd_tscm *tscm)
305 pcm->private_data = tscm; 303 pcm->private_data = tscm;
306 snprintf(pcm->name, sizeof(pcm->name), 304 snprintf(pcm->name, sizeof(pcm->name),
307 "%s PCM", tscm->card->shortname); 305 "%s PCM", tscm->card->shortname);
308 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &pcm_playback_ops); 306 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_ops);
309 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pcm_capture_ops); 307 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &capture_ops);
310 308
311 return 0; 309 return 0;
312} 310}
diff --git a/sound/isa/gus/gus_uart.c b/sound/isa/gus/gus_uart.c
index 3992912743f5..ac5f5687d1a3 100644
--- a/sound/isa/gus/gus_uart.c
+++ b/sound/isa/gus/gus_uart.c
@@ -227,14 +227,14 @@ static void snd_gf1_uart_output_trigger(struct snd_rawmidi_substream *substream,
227 spin_unlock_irqrestore(&gus->uart_cmd_lock, flags); 227 spin_unlock_irqrestore(&gus->uart_cmd_lock, flags);
228} 228}
229 229
230static struct snd_rawmidi_ops snd_gf1_uart_output = 230static const struct snd_rawmidi_ops snd_gf1_uart_output =
231{ 231{
232 .open = snd_gf1_uart_output_open, 232 .open = snd_gf1_uart_output_open,
233 .close = snd_gf1_uart_output_close, 233 .close = snd_gf1_uart_output_close,
234 .trigger = snd_gf1_uart_output_trigger, 234 .trigger = snd_gf1_uart_output_trigger,
235}; 235};
236 236
237static struct snd_rawmidi_ops snd_gf1_uart_input = 237static const struct snd_rawmidi_ops snd_gf1_uart_input =
238{ 238{
239 .open = snd_gf1_uart_input_open, 239 .open = snd_gf1_uart_input_open,
240 .close = snd_gf1_uart_input_close, 240 .close = snd_gf1_uart_input_close,
diff --git a/sound/isa/msnd/msnd_midi.c b/sound/isa/msnd/msnd_midi.c
index ffc67fd80c23..912b5a9ccbab 100644
--- a/sound/isa/msnd/msnd_midi.c
+++ b/sound/isa/msnd/msnd_midi.c
@@ -142,7 +142,7 @@ void snd_msndmidi_input_read(void *mpuv)
142} 142}
143EXPORT_SYMBOL(snd_msndmidi_input_read); 143EXPORT_SYMBOL(snd_msndmidi_input_read);
144 144
145static struct snd_rawmidi_ops snd_msndmidi_input = { 145static const struct snd_rawmidi_ops snd_msndmidi_input = {
146 .open = snd_msndmidi_input_open, 146 .open = snd_msndmidi_input_open,
147 .close = snd_msndmidi_input_close, 147 .close = snd_msndmidi_input_close,
148 .trigger = snd_msndmidi_input_trigger, 148 .trigger = snd_msndmidi_input_trigger,
diff --git a/sound/isa/sb/sb8_midi.c b/sound/isa/sb/sb8_midi.c
index d551c50e549f..bd672abb4854 100644
--- a/sound/isa/sb/sb8_midi.c
+++ b/sound/isa/sb/sb8_midi.c
@@ -247,14 +247,14 @@ static void snd_sb8dsp_midi_output_trigger(struct snd_rawmidi_substream *substre
247 snd_sb8dsp_midi_output_write(substream); 247 snd_sb8dsp_midi_output_write(substream);
248} 248}
249 249
250static struct snd_rawmidi_ops snd_sb8dsp_midi_output = 250static const struct snd_rawmidi_ops snd_sb8dsp_midi_output =
251{ 251{
252 .open = snd_sb8dsp_midi_output_open, 252 .open = snd_sb8dsp_midi_output_open,
253 .close = snd_sb8dsp_midi_output_close, 253 .close = snd_sb8dsp_midi_output_close,
254 .trigger = snd_sb8dsp_midi_output_trigger, 254 .trigger = snd_sb8dsp_midi_output_trigger,
255}; 255};
256 256
257static struct snd_rawmidi_ops snd_sb8dsp_midi_input = 257static const struct snd_rawmidi_ops snd_sb8dsp_midi_input =
258{ 258{
259 .open = snd_sb8dsp_midi_input_open, 259 .open = snd_sb8dsp_midi_input_open,
260 .close = snd_sb8dsp_midi_input_close, 260 .close = snd_sb8dsp_midi_input_close,
diff --git a/sound/isa/wavefront/wavefront_midi.c b/sound/isa/wavefront/wavefront_midi.c
index 8a80fc6a616b..2aa05f3aaa38 100644
--- a/sound/isa/wavefront/wavefront_midi.c
+++ b/sound/isa/wavefront/wavefront_midi.c
@@ -559,14 +559,14 @@ snd_wavefront_midi_start (snd_wavefront_card_t *card)
559 return 0; 559 return 0;
560} 560}
561 561
562struct snd_rawmidi_ops snd_wavefront_midi_output = 562const struct snd_rawmidi_ops snd_wavefront_midi_output =
563{ 563{
564 .open = snd_wavefront_midi_output_open, 564 .open = snd_wavefront_midi_output_open,
565 .close = snd_wavefront_midi_output_close, 565 .close = snd_wavefront_midi_output_close,
566 .trigger = snd_wavefront_midi_output_trigger, 566 .trigger = snd_wavefront_midi_output_trigger,
567}; 567};
568 568
569struct snd_rawmidi_ops snd_wavefront_midi_input = 569const struct snd_rawmidi_ops snd_wavefront_midi_input =
570{ 570{
571 .open = snd_wavefront_midi_input_open, 571 .open = snd_wavefront_midi_input_open,
572 .close = snd_wavefront_midi_input_close, 572 .close = snd_wavefront_midi_input_close,
diff --git a/sound/mips/hal2.c b/sound/mips/hal2.c
index ede449f0b50d..00fc9241d266 100644
--- a/sound/mips/hal2.c
+++ b/sound/mips/hal2.c
@@ -219,6 +219,8 @@ static int hal2_gain_get(struct snd_kcontrol *kcontrol,
219 l = (tmp >> H2I_C2_L_GAIN_SHIFT) & 15; 219 l = (tmp >> H2I_C2_L_GAIN_SHIFT) & 15;
220 r = (tmp >> H2I_C2_R_GAIN_SHIFT) & 15; 220 r = (tmp >> H2I_C2_R_GAIN_SHIFT) & 15;
221 break; 221 break;
222 default:
223 return -EINVAL;
222 } 224 }
223 ucontrol->value.integer.value[0] = l; 225 ucontrol->value.integer.value[0] = l;
224 ucontrol->value.integer.value[1] = r; 226 ucontrol->value.integer.value[1] = r;
@@ -256,6 +258,8 @@ static int hal2_gain_put(struct snd_kcontrol *kcontrol,
256 new |= (r << H2I_C2_R_GAIN_SHIFT); 258 new |= (r << H2I_C2_R_GAIN_SHIFT);
257 hal2_i_write32(hal2, H2I_ADC_C2, new); 259 hal2_i_write32(hal2, H2I_ADC_C2, new);
258 break; 260 break;
261 default:
262 return -EINVAL;
259 } 263 }
260 return old != new; 264 return old != new;
261} 265}
diff --git a/sound/oss/ad1848.c b/sound/oss/ad1848.c
index 6368e5c7d0ba..f6156d8169d0 100644
--- a/sound/oss/ad1848.c
+++ b/sound/oss/ad1848.c
@@ -121,11 +121,6 @@ static bool deskpro_xl;
121static bool deskpro_m; 121static bool deskpro_m;
122static bool soundpro; 122static bool soundpro;
123 123
124static volatile signed char irq2dev[17] = {
125 -1, -1, -1, -1, -1, -1, -1, -1,
126 -1, -1, -1, -1, -1, -1, -1, -1, -1
127};
128
129#ifndef EXCLUDE_TIMERS 124#ifndef EXCLUDE_TIMERS
130static int timer_installed = -1; 125static int timer_installed = -1;
131#endif 126#endif
@@ -2060,7 +2055,7 @@ int ad1848_init (char *name, struct resource *ports, int irq, int dma_playback,
2060 else 2055 else
2061 devc->irq_ok = 1; /* Couldn't test. assume it's OK */ 2056 devc->irq_ok = 1; /* Couldn't test. assume it's OK */
2062 } else if (irq < 0) 2057 } else if (irq < 0)
2063 irq2dev[-irq] = devc->dev_no = my_dev; 2058 devc->dev_no = my_dev;
2064 2059
2065#ifndef EXCLUDE_TIMERS 2060#ifndef EXCLUDE_TIMERS
2066 if ((capabilities[devc->model].flags & CAP_F_TIMER) && 2061 if ((capabilities[devc->model].flags & CAP_F_TIMER) &&
diff --git a/sound/pci/ca0106/ca_midi.c b/sound/pci/ca0106/ca_midi.c
index b91c7f6d19f9..4d4d385205eb 100644
--- a/sound/pci/ca0106/ca_midi.c
+++ b/sound/pci/ca0106/ca_midi.c
@@ -255,14 +255,14 @@ static void ca_midi_output_trigger(struct snd_rawmidi_substream *substream, int
255 } 255 }
256} 256}
257 257
258static struct snd_rawmidi_ops ca_midi_output = 258static const struct snd_rawmidi_ops ca_midi_output =
259{ 259{
260 .open = ca_midi_output_open, 260 .open = ca_midi_output_open,
261 .close = ca_midi_output_close, 261 .close = ca_midi_output_close,
262 .trigger = ca_midi_output_trigger, 262 .trigger = ca_midi_output_trigger,
263}; 263};
264 264
265static struct snd_rawmidi_ops ca_midi_input = 265static const struct snd_rawmidi_ops ca_midi_input =
266{ 266{
267 .open = ca_midi_input_open, 267 .open = ca_midi_input_open,
268 .close = ca_midi_input_close, 268 .close = ca_midi_input_close,
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c
index 8f0f5f24e40e..fa7c51684dd2 100644
--- a/sound/pci/cs4281.c
+++ b/sound/pci/cs4281.c
@@ -1767,14 +1767,14 @@ static void snd_cs4281_midi_output_trigger(struct snd_rawmidi_substream *substre
1767 spin_unlock_irqrestore(&chip->reg_lock, flags); 1767 spin_unlock_irqrestore(&chip->reg_lock, flags);
1768} 1768}
1769 1769
1770static struct snd_rawmidi_ops snd_cs4281_midi_output = 1770static const struct snd_rawmidi_ops snd_cs4281_midi_output =
1771{ 1771{
1772 .open = snd_cs4281_midi_output_open, 1772 .open = snd_cs4281_midi_output_open,
1773 .close = snd_cs4281_midi_output_close, 1773 .close = snd_cs4281_midi_output_close,
1774 .trigger = snd_cs4281_midi_output_trigger, 1774 .trigger = snd_cs4281_midi_output_trigger,
1775}; 1775};
1776 1776
1777static struct snd_rawmidi_ops snd_cs4281_midi_input = 1777static const struct snd_rawmidi_ops snd_cs4281_midi_input =
1778{ 1778{
1779 .open = snd_cs4281_midi_input_open, 1779 .open = snd_cs4281_midi_input_open,
1780 .close = snd_cs4281_midi_input_close, 1780 .close = snd_cs4281_midi_input_close,
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c
index fde3cd48258c..e4cf3187b4dd 100644
--- a/sound/pci/cs46xx/cs46xx_lib.c
+++ b/sound/pci/cs46xx/cs46xx_lib.c
@@ -72,18 +72,18 @@
72static void amp_voyetra(struct snd_cs46xx *chip, int change); 72static void amp_voyetra(struct snd_cs46xx *chip, int change);
73 73
74#ifdef CONFIG_SND_CS46XX_NEW_DSP 74#ifdef CONFIG_SND_CS46XX_NEW_DSP
75static struct snd_pcm_ops snd_cs46xx_playback_rear_ops; 75static const struct snd_pcm_ops snd_cs46xx_playback_rear_ops;
76static struct snd_pcm_ops snd_cs46xx_playback_indirect_rear_ops; 76static const struct snd_pcm_ops snd_cs46xx_playback_indirect_rear_ops;
77static struct snd_pcm_ops snd_cs46xx_playback_clfe_ops; 77static const struct snd_pcm_ops snd_cs46xx_playback_clfe_ops;
78static struct snd_pcm_ops snd_cs46xx_playback_indirect_clfe_ops; 78static const struct snd_pcm_ops snd_cs46xx_playback_indirect_clfe_ops;
79static struct snd_pcm_ops snd_cs46xx_playback_iec958_ops; 79static const struct snd_pcm_ops snd_cs46xx_playback_iec958_ops;
80static struct snd_pcm_ops snd_cs46xx_playback_indirect_iec958_ops; 80static const struct snd_pcm_ops snd_cs46xx_playback_indirect_iec958_ops;
81#endif 81#endif
82 82
83static struct snd_pcm_ops snd_cs46xx_playback_ops; 83static const struct snd_pcm_ops snd_cs46xx_playback_ops;
84static struct snd_pcm_ops snd_cs46xx_playback_indirect_ops; 84static const struct snd_pcm_ops snd_cs46xx_playback_indirect_ops;
85static struct snd_pcm_ops snd_cs46xx_capture_ops; 85static const struct snd_pcm_ops snd_cs46xx_capture_ops;
86static struct snd_pcm_ops snd_cs46xx_capture_indirect_ops; 86static const struct snd_pcm_ops snd_cs46xx_capture_indirect_ops;
87 87
88static unsigned short snd_cs46xx_codec_read(struct snd_cs46xx *chip, 88static unsigned short snd_cs46xx_codec_read(struct snd_cs46xx *chip,
89 unsigned short reg, 89 unsigned short reg,
@@ -1654,7 +1654,7 @@ static int snd_cs46xx_capture_close(struct snd_pcm_substream *substream)
1654} 1654}
1655 1655
1656#ifdef CONFIG_SND_CS46XX_NEW_DSP 1656#ifdef CONFIG_SND_CS46XX_NEW_DSP
1657static struct snd_pcm_ops snd_cs46xx_playback_rear_ops = { 1657static const struct snd_pcm_ops snd_cs46xx_playback_rear_ops = {
1658 .open = snd_cs46xx_playback_open_rear, 1658 .open = snd_cs46xx_playback_open_rear,
1659 .close = snd_cs46xx_playback_close, 1659 .close = snd_cs46xx_playback_close,
1660 .ioctl = snd_pcm_lib_ioctl, 1660 .ioctl = snd_pcm_lib_ioctl,
@@ -1665,7 +1665,7 @@ static struct snd_pcm_ops snd_cs46xx_playback_rear_ops = {
1665 .pointer = snd_cs46xx_playback_direct_pointer, 1665 .pointer = snd_cs46xx_playback_direct_pointer,
1666}; 1666};
1667 1667
1668static struct snd_pcm_ops snd_cs46xx_playback_indirect_rear_ops = { 1668static const struct snd_pcm_ops snd_cs46xx_playback_indirect_rear_ops = {
1669 .open = snd_cs46xx_playback_open_rear, 1669 .open = snd_cs46xx_playback_open_rear,
1670 .close = snd_cs46xx_playback_close, 1670 .close = snd_cs46xx_playback_close,
1671 .ioctl = snd_pcm_lib_ioctl, 1671 .ioctl = snd_pcm_lib_ioctl,
@@ -1677,7 +1677,7 @@ static struct snd_pcm_ops snd_cs46xx_playback_indirect_rear_ops = {
1677 .ack = snd_cs46xx_playback_transfer, 1677 .ack = snd_cs46xx_playback_transfer,
1678}; 1678};
1679 1679
1680static struct snd_pcm_ops snd_cs46xx_playback_clfe_ops = { 1680static const struct snd_pcm_ops snd_cs46xx_playback_clfe_ops = {
1681 .open = snd_cs46xx_playback_open_clfe, 1681 .open = snd_cs46xx_playback_open_clfe,
1682 .close = snd_cs46xx_playback_close, 1682 .close = snd_cs46xx_playback_close,
1683 .ioctl = snd_pcm_lib_ioctl, 1683 .ioctl = snd_pcm_lib_ioctl,
@@ -1688,7 +1688,7 @@ static struct snd_pcm_ops snd_cs46xx_playback_clfe_ops = {
1688 .pointer = snd_cs46xx_playback_direct_pointer, 1688 .pointer = snd_cs46xx_playback_direct_pointer,
1689}; 1689};
1690 1690
1691static struct snd_pcm_ops snd_cs46xx_playback_indirect_clfe_ops = { 1691static const struct snd_pcm_ops snd_cs46xx_playback_indirect_clfe_ops = {
1692 .open = snd_cs46xx_playback_open_clfe, 1692 .open = snd_cs46xx_playback_open_clfe,
1693 .close = snd_cs46xx_playback_close, 1693 .close = snd_cs46xx_playback_close,
1694 .ioctl = snd_pcm_lib_ioctl, 1694 .ioctl = snd_pcm_lib_ioctl,
@@ -1700,7 +1700,7 @@ static struct snd_pcm_ops snd_cs46xx_playback_indirect_clfe_ops = {
1700 .ack = snd_cs46xx_playback_transfer, 1700 .ack = snd_cs46xx_playback_transfer,
1701}; 1701};
1702 1702
1703static struct snd_pcm_ops snd_cs46xx_playback_iec958_ops = { 1703static const struct snd_pcm_ops snd_cs46xx_playback_iec958_ops = {
1704 .open = snd_cs46xx_playback_open_iec958, 1704 .open = snd_cs46xx_playback_open_iec958,
1705 .close = snd_cs46xx_playback_close_iec958, 1705 .close = snd_cs46xx_playback_close_iec958,
1706 .ioctl = snd_pcm_lib_ioctl, 1706 .ioctl = snd_pcm_lib_ioctl,
@@ -1711,7 +1711,7 @@ static struct snd_pcm_ops snd_cs46xx_playback_iec958_ops = {
1711 .pointer = snd_cs46xx_playback_direct_pointer, 1711 .pointer = snd_cs46xx_playback_direct_pointer,
1712}; 1712};
1713 1713
1714static struct snd_pcm_ops snd_cs46xx_playback_indirect_iec958_ops = { 1714static const struct snd_pcm_ops snd_cs46xx_playback_indirect_iec958_ops = {
1715 .open = snd_cs46xx_playback_open_iec958, 1715 .open = snd_cs46xx_playback_open_iec958,
1716 .close = snd_cs46xx_playback_close_iec958, 1716 .close = snd_cs46xx_playback_close_iec958,
1717 .ioctl = snd_pcm_lib_ioctl, 1717 .ioctl = snd_pcm_lib_ioctl,
@@ -1725,7 +1725,7 @@ static struct snd_pcm_ops snd_cs46xx_playback_indirect_iec958_ops = {
1725 1725
1726#endif 1726#endif
1727 1727
1728static struct snd_pcm_ops snd_cs46xx_playback_ops = { 1728static const struct snd_pcm_ops snd_cs46xx_playback_ops = {
1729 .open = snd_cs46xx_playback_open, 1729 .open = snd_cs46xx_playback_open,
1730 .close = snd_cs46xx_playback_close, 1730 .close = snd_cs46xx_playback_close,
1731 .ioctl = snd_pcm_lib_ioctl, 1731 .ioctl = snd_pcm_lib_ioctl,
@@ -1736,7 +1736,7 @@ static struct snd_pcm_ops snd_cs46xx_playback_ops = {
1736 .pointer = snd_cs46xx_playback_direct_pointer, 1736 .pointer = snd_cs46xx_playback_direct_pointer,
1737}; 1737};
1738 1738
1739static struct snd_pcm_ops snd_cs46xx_playback_indirect_ops = { 1739static const struct snd_pcm_ops snd_cs46xx_playback_indirect_ops = {
1740 .open = snd_cs46xx_playback_open, 1740 .open = snd_cs46xx_playback_open,
1741 .close = snd_cs46xx_playback_close, 1741 .close = snd_cs46xx_playback_close,
1742 .ioctl = snd_pcm_lib_ioctl, 1742 .ioctl = snd_pcm_lib_ioctl,
@@ -1748,7 +1748,7 @@ static struct snd_pcm_ops snd_cs46xx_playback_indirect_ops = {
1748 .ack = snd_cs46xx_playback_transfer, 1748 .ack = snd_cs46xx_playback_transfer,
1749}; 1749};
1750 1750
1751static struct snd_pcm_ops snd_cs46xx_capture_ops = { 1751static const struct snd_pcm_ops snd_cs46xx_capture_ops = {
1752 .open = snd_cs46xx_capture_open, 1752 .open = snd_cs46xx_capture_open,
1753 .close = snd_cs46xx_capture_close, 1753 .close = snd_cs46xx_capture_close,
1754 .ioctl = snd_pcm_lib_ioctl, 1754 .ioctl = snd_pcm_lib_ioctl,
@@ -1759,7 +1759,7 @@ static struct snd_pcm_ops snd_cs46xx_capture_ops = {
1759 .pointer = snd_cs46xx_capture_direct_pointer, 1759 .pointer = snd_cs46xx_capture_direct_pointer,
1760}; 1760};
1761 1761
1762static struct snd_pcm_ops snd_cs46xx_capture_indirect_ops = { 1762static const struct snd_pcm_ops snd_cs46xx_capture_indirect_ops = {
1763 .open = snd_cs46xx_capture_open, 1763 .open = snd_cs46xx_capture_open,
1764 .close = snd_cs46xx_capture_close, 1764 .close = snd_cs46xx_capture_close,
1765 .ioctl = snd_pcm_lib_ioctl, 1765 .ioctl = snd_pcm_lib_ioctl,
@@ -2683,14 +2683,14 @@ static void snd_cs46xx_midi_output_trigger(struct snd_rawmidi_substream *substre
2683 spin_unlock_irqrestore(&chip->reg_lock, flags); 2683 spin_unlock_irqrestore(&chip->reg_lock, flags);
2684} 2684}
2685 2685
2686static struct snd_rawmidi_ops snd_cs46xx_midi_output = 2686static const struct snd_rawmidi_ops snd_cs46xx_midi_output =
2687{ 2687{
2688 .open = snd_cs46xx_midi_output_open, 2688 .open = snd_cs46xx_midi_output_open,
2689 .close = snd_cs46xx_midi_output_close, 2689 .close = snd_cs46xx_midi_output_close,
2690 .trigger = snd_cs46xx_midi_output_trigger, 2690 .trigger = snd_cs46xx_midi_output_trigger,
2691}; 2691};
2692 2692
2693static struct snd_rawmidi_ops snd_cs46xx_midi_input = 2693static const struct snd_rawmidi_ops snd_cs46xx_midi_input =
2694{ 2694{
2695 .open = snd_cs46xx_midi_input_open, 2695 .open = snd_cs46xx_midi_input_open,
2696 .close = snd_cs46xx_midi_input_close, 2696 .close = snd_cs46xx_midi_input_close,
diff --git a/sound/pci/cs5535audio/cs5535audio_pm.c b/sound/pci/cs5535audio/cs5535audio_pm.c
index 06ac5d8da362..82bd10b68a77 100644
--- a/sound/pci/cs5535audio/cs5535audio_pm.c
+++ b/sound/pci/cs5535audio/cs5535audio_pm.c
@@ -55,7 +55,7 @@ static void snd_cs5535audio_stop_hardware(struct cs5535audio *cs5535au)
55 55
56} 56}
57 57
58static int snd_cs5535audio_suspend(struct device *dev) 58static int __maybe_unused snd_cs5535audio_suspend(struct device *dev)
59{ 59{
60 struct snd_card *card = dev_get_drvdata(dev); 60 struct snd_card *card = dev_get_drvdata(dev);
61 struct cs5535audio *cs5535au = card->private_data; 61 struct cs5535audio *cs5535au = card->private_data;
@@ -74,7 +74,7 @@ static int snd_cs5535audio_suspend(struct device *dev)
74 return 0; 74 return 0;
75} 75}
76 76
77static int snd_cs5535audio_resume(struct device *dev) 77static int __maybe_unused snd_cs5535audio_resume(struct device *dev)
78{ 78{
79 struct snd_card *card = dev_get_drvdata(dev); 79 struct snd_card *card = dev_get_drvdata(dev);
80 struct cs5535audio *cs5535au = card->private_data; 80 struct cs5535audio *cs5535au = card->private_data;
diff --git a/sound/pci/echoaudio/midi.c b/sound/pci/echoaudio/midi.c
index a8fe58335ddc..8c685ddb1a41 100644
--- a/sound/pci/echoaudio/midi.c
+++ b/sound/pci/echoaudio/midi.c
@@ -288,13 +288,13 @@ static int snd_echo_midi_output_close(struct snd_rawmidi_substream *substream)
288 288
289 289
290 290
291static struct snd_rawmidi_ops snd_echo_midi_input = { 291static const struct snd_rawmidi_ops snd_echo_midi_input = {
292 .open = snd_echo_midi_input_open, 292 .open = snd_echo_midi_input_open,
293 .close = snd_echo_midi_input_close, 293 .close = snd_echo_midi_input_close,
294 .trigger = snd_echo_midi_input_trigger, 294 .trigger = snd_echo_midi_input_trigger,
295}; 295};
296 296
297static struct snd_rawmidi_ops snd_echo_midi_output = { 297static const struct snd_rawmidi_ops snd_echo_midi_output = {
298 .open = snd_echo_midi_output_open, 298 .open = snd_echo_midi_output_open,
299 .close = snd_echo_midi_output_close, 299 .close = snd_echo_midi_output_close,
300 .trigger = snd_echo_midi_output_trigger, 300 .trigger = snd_echo_midi_output_trigger,
diff --git a/sound/pci/emu10k1/emu10k1_callback.c b/sound/pci/emu10k1/emu10k1_callback.c
index d2c7ea3a7610..aa2cc27b8491 100644
--- a/sound/pci/emu10k1/emu10k1_callback.c
+++ b/sound/pci/emu10k1/emu10k1_callback.c
@@ -61,7 +61,7 @@ static void set_filterQ(struct snd_emu10k1 *hw, struct snd_emux_voice *vp);
61/* 61/*
62 * set up operators 62 * set up operators
63 */ 63 */
64static struct snd_emux_operators emu10k1_ops = { 64static const struct snd_emux_operators emu10k1_ops = {
65 .owner = THIS_MODULE, 65 .owner = THIS_MODULE,
66 .get_voice = get_voice, 66 .get_voice = get_voice,
67 .prepare = start_voice, 67 .prepare = start_voice,
diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c
index 921037ed8468..32842734ada6 100644
--- a/sound/pci/emu10k1/emu10k1x.c
+++ b/sound/pci/emu10k1/emu10k1x.c
@@ -1486,14 +1486,14 @@ static void snd_emu10k1x_midi_output_trigger(struct snd_rawmidi_substream *subst
1486 1486
1487 */ 1487 */
1488 1488
1489static struct snd_rawmidi_ops snd_emu10k1x_midi_output = 1489static const struct snd_rawmidi_ops snd_emu10k1x_midi_output =
1490{ 1490{
1491 .open = snd_emu10k1x_midi_output_open, 1491 .open = snd_emu10k1x_midi_output_open,
1492 .close = snd_emu10k1x_midi_output_close, 1492 .close = snd_emu10k1x_midi_output_close,
1493 .trigger = snd_emu10k1x_midi_output_trigger, 1493 .trigger = snd_emu10k1x_midi_output_trigger,
1494}; 1494};
1495 1495
1496static struct snd_rawmidi_ops snd_emu10k1x_midi_input = 1496static const struct snd_rawmidi_ops snd_emu10k1x_midi_input =
1497{ 1497{
1498 .open = snd_emu10k1x_midi_input_open, 1498 .open = snd_emu10k1x_midi_input_open,
1499 .close = snd_emu10k1x_midi_input_close, 1499 .close = snd_emu10k1x_midi_input_close,
diff --git a/sound/pci/emu10k1/emumpu401.c b/sound/pci/emu10k1/emumpu401.c
index fdf2b0ada489..b6650f5c1621 100644
--- a/sound/pci/emu10k1/emumpu401.c
+++ b/sound/pci/emu10k1/emumpu401.c
@@ -308,14 +308,14 @@ static void snd_emu10k1_midi_output_trigger(struct snd_rawmidi_substream *substr
308 308
309 */ 309 */
310 310
311static struct snd_rawmidi_ops snd_emu10k1_midi_output = 311static const struct snd_rawmidi_ops snd_emu10k1_midi_output =
312{ 312{
313 .open = snd_emu10k1_midi_output_open, 313 .open = snd_emu10k1_midi_output_open,
314 .close = snd_emu10k1_midi_output_close, 314 .close = snd_emu10k1_midi_output_close,
315 .trigger = snd_emu10k1_midi_output_trigger, 315 .trigger = snd_emu10k1_midi_output_trigger,
316}; 316};
317 317
318static struct snd_rawmidi_ops snd_emu10k1_midi_input = 318static const struct snd_rawmidi_ops snd_emu10k1_midi_input =
319{ 319{
320 .open = snd_emu10k1_midi_input_open, 320 .open = snd_emu10k1_midi_input_open,
321 .close = snd_emu10k1_midi_input_close, 321 .close = snd_emu10k1_midi_input_close,
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c
index 51736c2b5a00..164adad91650 100644
--- a/sound/pci/ens1370.c
+++ b/sound/pci/ens1370.c
@@ -2317,14 +2317,14 @@ static void snd_ensoniq_midi_output_trigger(struct snd_rawmidi_substream *substr
2317 spin_unlock_irqrestore(&ensoniq->reg_lock, flags); 2317 spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
2318} 2318}
2319 2319
2320static struct snd_rawmidi_ops snd_ensoniq_midi_output = 2320static const struct snd_rawmidi_ops snd_ensoniq_midi_output =
2321{ 2321{
2322 .open = snd_ensoniq_midi_output_open, 2322 .open = snd_ensoniq_midi_output_open,
2323 .close = snd_ensoniq_midi_output_close, 2323 .close = snd_ensoniq_midi_output_close,
2324 .trigger = snd_ensoniq_midi_output_trigger, 2324 .trigger = snd_ensoniq_midi_output_trigger,
2325}; 2325};
2326 2326
2327static struct snd_rawmidi_ops snd_ensoniq_midi_input = 2327static const struct snd_rawmidi_ops snd_ensoniq_midi_input =
2328{ 2328{
2329 .open = snd_ensoniq_midi_input_open, 2329 .open = snd_ensoniq_midi_input_open,
2330 .close = snd_ensoniq_midi_input_close, 2330 .close = snd_ensoniq_midi_input_close,
diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c
index 500878556578..3715a5725613 100644
--- a/sound/pci/hda/hda_controller.c
+++ b/sound/pci/hda/hda_controller.c
@@ -861,6 +861,10 @@ static int azx_rirb_get_response(struct hdac_bus *bus, unsigned int addr,
861 return -EIO; 861 return -EIO;
862 } 862 }
863 863
864 /* no fallback mechanism? */
865 if (!chip->fallback_to_single_cmd)
866 return -EIO;
867
864 /* a fatal communication error; need either to reset or to fallback 868 /* a fatal communication error; need either to reset or to fallback
865 * to the single_cmd mode 869 * to the single_cmd mode
866 */ 870 */
diff --git a/sound/pci/hda/hda_controller.h b/sound/pci/hda/hda_controller.h
index a50e0532622a..35a9ab2cac46 100644
--- a/sound/pci/hda/hda_controller.h
+++ b/sound/pci/hda/hda_controller.h
@@ -150,6 +150,7 @@ struct azx {
150 int bdl_pos_adj; 150 int bdl_pos_adj;
151 int poll_count; 151 int poll_count;
152 unsigned int running:1; 152 unsigned int running:1;
153 unsigned int fallback_to_single_cmd:1;
153 unsigned int single_cmd:1; 154 unsigned int single_cmd:1;
154 unsigned int polling_mode:1; 155 unsigned int polling_mode:1;
155 unsigned int msi:1; 156 unsigned int msi:1;
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index c64d986009a9..16108f0eb688 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -128,7 +128,7 @@ static int bdl_pos_adj[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = -1};
128static int probe_mask[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = -1}; 128static int probe_mask[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = -1};
129static int probe_only[SNDRV_CARDS]; 129static int probe_only[SNDRV_CARDS];
130static int jackpoll_ms[SNDRV_CARDS]; 130static int jackpoll_ms[SNDRV_CARDS];
131static bool single_cmd; 131static int single_cmd = -1;
132static int enable_msi = -1; 132static int enable_msi = -1;
133#ifdef CONFIG_SND_HDA_PATCH_LOADER 133#ifdef CONFIG_SND_HDA_PATCH_LOADER
134static char *patch[SNDRV_CARDS]; 134static char *patch[SNDRV_CARDS];
@@ -157,7 +157,7 @@ module_param_array(probe_only, int, NULL, 0444);
157MODULE_PARM_DESC(probe_only, "Only probing and no codec initialization."); 157MODULE_PARM_DESC(probe_only, "Only probing and no codec initialization.");
158module_param_array(jackpoll_ms, int, NULL, 0444); 158module_param_array(jackpoll_ms, int, NULL, 0444);
159MODULE_PARM_DESC(jackpoll_ms, "Ms between polling for jack events (default = 0, using unsol events only)"); 159MODULE_PARM_DESC(jackpoll_ms, "Ms between polling for jack events (default = 0, using unsol events only)");
160module_param(single_cmd, bool, 0444); 160module_param(single_cmd, bint, 0444);
161MODULE_PARM_DESC(single_cmd, "Use single command to communicate with codecs " 161MODULE_PARM_DESC(single_cmd, "Use single command to communicate with codecs "
162 "(for debugging only)."); 162 "(for debugging only).");
163module_param(enable_msi, bint, 0444); 163module_param(enable_msi, bint, 0444);
@@ -1596,7 +1596,11 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci,
1596 1596
1597 check_probe_mask(chip, dev); 1597 check_probe_mask(chip, dev);
1598 1598
1599 chip->single_cmd = single_cmd; 1599 if (single_cmd < 0) /* allow fallback to single_cmd at errors */
1600 chip->fallback_to_single_cmd = 1;
1601 else /* explicitly set to single_cmd or not */
1602 chip->single_cmd = single_cmd;
1603
1600 azx_check_snoop_available(chip); 1604 azx_check_snoop_available(chip);
1601 1605
1602 if (bdl_pos_adj[dev] < 0) 1606 if (bdl_pos_adj[dev] < 0)
@@ -1774,6 +1778,14 @@ static int azx_first_init(struct azx *chip)
1774 chip->playback_index_offset = chip->capture_streams; 1778 chip->playback_index_offset = chip->capture_streams;
1775 chip->num_streams = chip->playback_streams + chip->capture_streams; 1779 chip->num_streams = chip->playback_streams + chip->capture_streams;
1776 1780
1781 /* sanity check for the SDxCTL.STRM field overflow */
1782 if (chip->num_streams > 15 &&
1783 (chip->driver_caps & AZX_DCAPS_SEPARATE_STREAM_TAG) == 0) {
1784 dev_warn(chip->card->dev, "number of I/O streams is %d, "
1785 "forcing separate stream tags", chip->num_streams);
1786 chip->driver_caps |= AZX_DCAPS_SEPARATE_STREAM_TAG;
1787 }
1788
1777 /* initialize streams */ 1789 /* initialize streams */
1778 err = azx_init_streams(chip); 1790 err = azx_init_streams(chip);
1779 if (err < 0) 1791 if (err < 0)
@@ -2155,7 +2167,20 @@ static void azx_remove(struct pci_dev *pci)
2155 /* cancel the pending probing work */ 2167 /* cancel the pending probing work */
2156 chip = card->private_data; 2168 chip = card->private_data;
2157 hda = container_of(chip, struct hda_intel, chip); 2169 hda = container_of(chip, struct hda_intel, chip);
2170 /* FIXME: below is an ugly workaround.
2171 * Both device_release_driver() and driver_probe_device()
2172 * take *both* the device's and its parent's lock before
2173 * calling the remove() and probe() callbacks. The codec
2174 * probe takes the locks of both the codec itself and its
2175 * parent, i.e. the PCI controller dev. Meanwhile, when
2176 * the PCI controller is unbound, it takes its lock, too
2177 * ==> ouch, a deadlock!
2178 * As a workaround, we unlock temporarily here the controller
2179 * device during cancel_work_sync() call.
2180 */
2181 device_unlock(&pci->dev);
2158 cancel_work_sync(&hda->probe_work); 2182 cancel_work_sync(&hda->probe_work);
2183 device_lock(&pci->dev);
2159 2184
2160 snd_card_free(card); 2185 snd_card_free(card);
2161 } 2186 }
@@ -2197,9 +2222,9 @@ static const struct pci_device_id azx_ids[] = {
2197 .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, 2222 .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
2198 /* Lewisburg */ 2223 /* Lewisburg */
2199 { PCI_DEVICE(0x8086, 0xa1f0), 2224 { PCI_DEVICE(0x8086, 0xa1f0),
2200 .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, 2225 .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE },
2201 { PCI_DEVICE(0x8086, 0xa270), 2226 { PCI_DEVICE(0x8086, 0xa270),
2202 .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, 2227 .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE },
2203 /* Lynx Point-LP */ 2228 /* Lynx Point-LP */
2204 { PCI_DEVICE(0x8086, 0x9c20), 2229 { PCI_DEVICE(0x8086, 0x9c20),
2205 .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, 2230 .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c
index 11b9b2f17a2e..9ec4dba8a793 100644
--- a/sound/pci/hda/patch_ca0132.c
+++ b/sound/pci/hda/patch_ca0132.c
@@ -1482,6 +1482,9 @@ static int dspio_scp(struct hda_codec *codec,
1482 } else if (ret_size != reply_data_size) { 1482 } else if (ret_size != reply_data_size) {
1483 codec_dbg(codec, "RetLen and HdrLen .NE.\n"); 1483 codec_dbg(codec, "RetLen and HdrLen .NE.\n");
1484 return -EINVAL; 1484 return -EINVAL;
1485 } else if (!reply) {
1486 codec_dbg(codec, "NULL reply\n");
1487 return -EINVAL;
1485 } else { 1488 } else {
1486 *reply_len = ret_size*sizeof(unsigned int); 1489 *reply_len = ret_size*sizeof(unsigned int);
1487 memcpy(reply, scp_reply.data, *reply_len); 1490 memcpy(reply, scp_reply.data, *reply_len);
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index cf9bc042fe96..3fc201c3b95a 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -3639,6 +3639,7 @@ HDA_CODEC_ENTRY(0x10de0070, "GPU 70 HDMI/DP", patch_nvhdmi),
3639HDA_CODEC_ENTRY(0x10de0071, "GPU 71 HDMI/DP", patch_nvhdmi), 3639HDA_CODEC_ENTRY(0x10de0071, "GPU 71 HDMI/DP", patch_nvhdmi),
3640HDA_CODEC_ENTRY(0x10de0072, "GPU 72 HDMI/DP", patch_nvhdmi), 3640HDA_CODEC_ENTRY(0x10de0072, "GPU 72 HDMI/DP", patch_nvhdmi),
3641HDA_CODEC_ENTRY(0x10de007d, "GPU 7d HDMI/DP", patch_nvhdmi), 3641HDA_CODEC_ENTRY(0x10de007d, "GPU 7d HDMI/DP", patch_nvhdmi),
3642HDA_CODEC_ENTRY(0x10de0080, "GPU 80 HDMI/DP", patch_nvhdmi),
3642HDA_CODEC_ENTRY(0x10de0082, "GPU 82 HDMI/DP", patch_nvhdmi), 3643HDA_CODEC_ENTRY(0x10de0082, "GPU 82 HDMI/DP", patch_nvhdmi),
3643HDA_CODEC_ENTRY(0x10de0083, "GPU 83 HDMI/DP", patch_nvhdmi), 3644HDA_CODEC_ENTRY(0x10de0083, "GPU 83 HDMI/DP", patch_nvhdmi),
3644HDA_CODEC_ENTRY(0x10de8001, "MCP73 HDMI", patch_nvhdmi_2ch), 3645HDA_CODEC_ENTRY(0x10de8001, "MCP73 HDMI", patch_nvhdmi_2ch),
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 7d660ee1d5e8..73a00460b5c1 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -337,6 +337,7 @@ static void alc_fill_eapd_coef(struct hda_codec *codec)
337 case 0x10ec0288: 337 case 0x10ec0288:
338 case 0x10ec0295: 338 case 0x10ec0295:
339 case 0x10ec0298: 339 case 0x10ec0298:
340 case 0x10ec0299:
340 alc_update_coef_idx(codec, 0x10, 1<<9, 0); 341 alc_update_coef_idx(codec, 0x10, 1<<9, 0);
341 break; 342 break;
342 case 0x10ec0285: 343 case 0x10ec0285:
@@ -379,6 +380,7 @@ static void alc_fill_eapd_coef(struct hda_codec *codec)
379 break; 380 break;
380 case 0x10ec0899: 381 case 0x10ec0899:
381 case 0x10ec0900: 382 case 0x10ec0900:
383 case 0x10ec1220:
382 alc_update_coef_idx(codec, 0x7, 1<<1, 0); 384 alc_update_coef_idx(codec, 0x7, 1<<1, 0);
383 break; 385 break;
384 } 386 }
@@ -912,6 +914,7 @@ static struct alc_codec_rename_pci_table rename_pci_tbl[] = {
912 { 0x10ec0256, 0x1028, 0, "ALC3246" }, 914 { 0x10ec0256, 0x1028, 0, "ALC3246" },
913 { 0x10ec0225, 0x1028, 0, "ALC3253" }, 915 { 0x10ec0225, 0x1028, 0, "ALC3253" },
914 { 0x10ec0295, 0x1028, 0, "ALC3254" }, 916 { 0x10ec0295, 0x1028, 0, "ALC3254" },
917 { 0x10ec0299, 0x1028, 0, "ALC3271" },
915 { 0x10ec0670, 0x1025, 0, "ALC669X" }, 918 { 0x10ec0670, 0x1025, 0, "ALC669X" },
916 { 0x10ec0676, 0x1025, 0, "ALC679X" }, 919 { 0x10ec0676, 0x1025, 0, "ALC679X" },
917 { 0x10ec0282, 0x1043, 0, "ALC3229" }, 920 { 0x10ec0282, 0x1043, 0, "ALC3229" },
@@ -2309,6 +2312,7 @@ static int patch_alc882(struct hda_codec *codec)
2309 case 0x10ec0882: 2312 case 0x10ec0882:
2310 case 0x10ec0885: 2313 case 0x10ec0885:
2311 case 0x10ec0900: 2314 case 0x10ec0900:
2315 case 0x10ec1220:
2312 break; 2316 break;
2313 default: 2317 default:
2314 /* ALC883 and variants */ 2318 /* ALC883 and variants */
@@ -3717,6 +3721,7 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec)
3717 break; 3721 break;
3718 case 0x10ec0225: 3722 case 0x10ec0225:
3719 case 0x10ec0295: 3723 case 0x10ec0295:
3724 case 0x10ec0299:
3720 alc_process_coef_fw(codec, coef0225); 3725 alc_process_coef_fw(codec, coef0225);
3721 break; 3726 break;
3722 case 0x10ec0867: 3727 case 0x10ec0867:
@@ -3812,6 +3817,7 @@ static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin,
3812 case 0x10ec0867: 3817 case 0x10ec0867:
3813 alc_update_coefex_idx(codec, 0x57, 0x5, 0, 1<<14); 3818 alc_update_coefex_idx(codec, 0x57, 0x5, 0, 1<<14);
3814 /* fallthru */ 3819 /* fallthru */
3820 case 0x10ec0221:
3815 case 0x10ec0662: 3821 case 0x10ec0662:
3816 snd_hda_set_pin_ctl_cache(codec, hp_pin, 0); 3822 snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
3817 snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50); 3823 snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
@@ -3824,6 +3830,7 @@ static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin,
3824 break; 3830 break;
3825 case 0x10ec0225: 3831 case 0x10ec0225:
3826 case 0x10ec0295: 3832 case 0x10ec0295:
3833 case 0x10ec0299:
3827 alc_update_coef_idx(codec, 0x45, 0x3f<<10, 0x31<<10); 3834 alc_update_coef_idx(codec, 0x45, 0x3f<<10, 0x31<<10);
3828 snd_hda_set_pin_ctl_cache(codec, hp_pin, 0); 3835 snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
3829 alc_process_coef_fw(codec, coef0225); 3836 alc_process_coef_fw(codec, coef0225);
@@ -3882,6 +3889,7 @@ static void alc_headset_mode_default(struct hda_codec *codec)
3882 switch (codec->core.vendor_id) { 3889 switch (codec->core.vendor_id) {
3883 case 0x10ec0225: 3890 case 0x10ec0225:
3884 case 0x10ec0295: 3891 case 0x10ec0295:
3892 case 0x10ec0299:
3885 alc_process_coef_fw(codec, coef0225); 3893 alc_process_coef_fw(codec, coef0225);
3886 break; 3894 break;
3887 case 0x10ec0255: 3895 case 0x10ec0255:
@@ -3997,6 +4005,7 @@ static void alc_headset_mode_ctia(struct hda_codec *codec)
3997 break; 4005 break;
3998 case 0x10ec0225: 4006 case 0x10ec0225:
3999 case 0x10ec0295: 4007 case 0x10ec0295:
4008 case 0x10ec0299:
4000 alc_process_coef_fw(codec, coef0225); 4009 alc_process_coef_fw(codec, coef0225);
4001 break; 4010 break;
4002 case 0x10ec0867: 4011 case 0x10ec0867:
@@ -4090,6 +4099,7 @@ static void alc_headset_mode_omtp(struct hda_codec *codec)
4090 break; 4099 break;
4091 case 0x10ec0225: 4100 case 0x10ec0225:
4092 case 0x10ec0295: 4101 case 0x10ec0295:
4102 case 0x10ec0299:
4093 alc_process_coef_fw(codec, coef0225); 4103 alc_process_coef_fw(codec, coef0225);
4094 break; 4104 break;
4095 } 4105 }
@@ -4174,6 +4184,7 @@ static void alc_determine_headset_type(struct hda_codec *codec)
4174 break; 4184 break;
4175 case 0x10ec0225: 4185 case 0x10ec0225:
4176 case 0x10ec0295: 4186 case 0x10ec0295:
4187 case 0x10ec0299:
4177 alc_process_coef_fw(codec, coef0225); 4188 alc_process_coef_fw(codec, coef0225);
4178 msleep(800); 4189 msleep(800);
4179 val = alc_read_coef_idx(codec, 0x46); 4190 val = alc_read_coef_idx(codec, 0x46);
@@ -4401,7 +4412,7 @@ static void alc_no_shutup(struct hda_codec *codec)
4401static void alc_fixup_no_shutup(struct hda_codec *codec, 4412static void alc_fixup_no_shutup(struct hda_codec *codec,
4402 const struct hda_fixup *fix, int action) 4413 const struct hda_fixup *fix, int action)
4403{ 4414{
4404 if (action == HDA_FIXUP_ACT_PRE_PROBE) { 4415 if (action == HDA_FIXUP_ACT_PROBE) {
4405 struct alc_spec *spec = codec->spec; 4416 struct alc_spec *spec = codec->spec;
4406 spec->shutup = alc_no_shutup; 4417 spec->shutup = alc_no_shutup;
4407 } 4418 }
@@ -4857,6 +4868,8 @@ enum {
4857 ALC292_FIXUP_TPT460, 4868 ALC292_FIXUP_TPT460,
4858 ALC298_FIXUP_SPK_VOLUME, 4869 ALC298_FIXUP_SPK_VOLUME,
4859 ALC256_FIXUP_DELL_INSPIRON_7559_SUBWOOFER, 4870 ALC256_FIXUP_DELL_INSPIRON_7559_SUBWOOFER,
4871 ALC269_FIXUP_ATIV_BOOK_8,
4872 ALC221_FIXUP_HP_MIC_NO_PRESENCE,
4860}; 4873};
4861 4874
4862static const struct hda_fixup alc269_fixups[] = { 4875static const struct hda_fixup alc269_fixups[] = {
@@ -5529,6 +5542,22 @@ static const struct hda_fixup alc269_fixups[] = {
5529 .chained = true, 5542 .chained = true,
5530 .chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE 5543 .chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE
5531 }, 5544 },
5545 [ALC269_FIXUP_ATIV_BOOK_8] = {
5546 .type = HDA_FIXUP_FUNC,
5547 .v.func = alc_fixup_auto_mute_via_amp,
5548 .chained = true,
5549 .chain_id = ALC269_FIXUP_NO_SHUTUP
5550 },
5551 [ALC221_FIXUP_HP_MIC_NO_PRESENCE] = {
5552 .type = HDA_FIXUP_PINS,
5553 .v.pins = (const struct hda_pintbl[]) {
5554 { 0x18, 0x01a1913c }, /* use as headset mic, without its own jack detect */
5555 { 0x1a, 0x01a1913d }, /* use as headphone mic, without its own jack detect */
5556 { }
5557 },
5558 .chained = true,
5559 .chain_id = ALC269_FIXUP_HEADSET_MODE
5560 },
5532}; 5561};
5533 5562
5534static const struct snd_pci_quirk alc269_fixup_tbl[] = { 5563static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -5639,6 +5668,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
5639 SND_PCI_QUIRK(0x103c, 0x2337, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), 5668 SND_PCI_QUIRK(0x103c, 0x2337, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
5640 SND_PCI_QUIRK(0x103c, 0x221c, "HP EliteBook 755 G2", ALC280_FIXUP_HP_HEADSET_MIC), 5669 SND_PCI_QUIRK(0x103c, 0x221c, "HP EliteBook 755 G2", ALC280_FIXUP_HP_HEADSET_MIC),
5641 SND_PCI_QUIRK(0x103c, 0x8256, "HP", ALC221_FIXUP_HP_FRONT_MIC), 5670 SND_PCI_QUIRK(0x103c, 0x8256, "HP", ALC221_FIXUP_HP_FRONT_MIC),
5671 SND_PCI_QUIRK(0x103c, 0x82bf, "HP", ALC221_FIXUP_HP_MIC_NO_PRESENCE),
5672 SND_PCI_QUIRK(0x103c, 0x82c0, "HP", ALC221_FIXUP_HP_MIC_NO_PRESENCE),
5642 SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300), 5673 SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300),
5643 SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), 5674 SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
5644 SND_PCI_QUIRK(0x1043, 0x115d, "Asus 1015E", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), 5675 SND_PCI_QUIRK(0x1043, 0x115d, "Asus 1015E", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
@@ -5665,6 +5696,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
5665 SND_PCI_QUIRK(0x10cf, 0x1757, "Lifebook E752", ALC269_FIXUP_LIFEBOOK_HP_PIN), 5696 SND_PCI_QUIRK(0x10cf, 0x1757, "Lifebook E752", ALC269_FIXUP_LIFEBOOK_HP_PIN),
5666 SND_PCI_QUIRK(0x10cf, 0x1845, "Lifebook U904", ALC269_FIXUP_LIFEBOOK_EXTMIC), 5697 SND_PCI_QUIRK(0x10cf, 0x1845, "Lifebook U904", ALC269_FIXUP_LIFEBOOK_EXTMIC),
5667 SND_PCI_QUIRK(0x144d, 0xc109, "Samsung Ativ book 9 (NP900X3G)", ALC269_FIXUP_INV_DMIC), 5698 SND_PCI_QUIRK(0x144d, 0xc109, "Samsung Ativ book 9 (NP900X3G)", ALC269_FIXUP_INV_DMIC),
5699 SND_PCI_QUIRK(0x144d, 0xc740, "Samsung Ativ book 8 (NP870Z5G)", ALC269_FIXUP_ATIV_BOOK_8),
5668 SND_PCI_QUIRK(0x1458, 0xfa53, "Gigabyte BXBT-2807", ALC283_FIXUP_HEADSET_MIC), 5700 SND_PCI_QUIRK(0x1458, 0xfa53, "Gigabyte BXBT-2807", ALC283_FIXUP_HEADSET_MIC),
5669 SND_PCI_QUIRK(0x1462, 0xb120, "MSI Cubi MS-B120", ALC283_FIXUP_HEADSET_MIC), 5701 SND_PCI_QUIRK(0x1462, 0xb120, "MSI Cubi MS-B120", ALC283_FIXUP_HEADSET_MIC),
5670 SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE), 5702 SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE),
@@ -6065,6 +6097,12 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
6065 SND_HDA_PIN_QUIRK(0x10ec0298, 0x1028, "Dell", ALC298_FIXUP_DELL1_MIC_NO_PRESENCE, 6097 SND_HDA_PIN_QUIRK(0x10ec0298, 0x1028, "Dell", ALC298_FIXUP_DELL1_MIC_NO_PRESENCE,
6066 ALC298_STANDARD_PINS, 6098 ALC298_STANDARD_PINS,
6067 {0x17, 0x90170150}), 6099 {0x17, 0x90170150}),
6100 SND_HDA_PIN_QUIRK(0x10ec0298, 0x1028, "Dell", ALC298_FIXUP_SPK_VOLUME,
6101 {0x12, 0xb7a60140},
6102 {0x13, 0xb7a60150},
6103 {0x17, 0x90170110},
6104 {0x1a, 0x03011020},
6105 {0x21, 0x03211030}),
6068 {} 6106 {}
6069}; 6107};
6070 6108
@@ -6212,6 +6250,7 @@ static int patch_alc269(struct hda_codec *codec)
6212 break; 6250 break;
6213 case 0x10ec0225: 6251 case 0x10ec0225:
6214 case 0x10ec0295: 6252 case 0x10ec0295:
6253 case 0x10ec0299:
6215 spec->codec_variant = ALC269_TYPE_ALC225; 6254 spec->codec_variant = ALC269_TYPE_ALC225;
6216 break; 6255 break;
6217 case 0x10ec0234: 6256 case 0x10ec0234:
@@ -7250,6 +7289,7 @@ static const struct hda_device_id snd_hda_id_realtek[] = {
7250 HDA_CODEC_ENTRY(0x10ec0294, "ALC294", patch_alc269), 7289 HDA_CODEC_ENTRY(0x10ec0294, "ALC294", patch_alc269),
7251 HDA_CODEC_ENTRY(0x10ec0295, "ALC295", patch_alc269), 7290 HDA_CODEC_ENTRY(0x10ec0295, "ALC295", patch_alc269),
7252 HDA_CODEC_ENTRY(0x10ec0298, "ALC298", patch_alc269), 7291 HDA_CODEC_ENTRY(0x10ec0298, "ALC298", patch_alc269),
7292 HDA_CODEC_ENTRY(0x10ec0299, "ALC299", patch_alc269),
7253 HDA_CODEC_REV_ENTRY(0x10ec0861, 0x100340, "ALC660", patch_alc861), 7293 HDA_CODEC_REV_ENTRY(0x10ec0861, 0x100340, "ALC660", patch_alc861),
7254 HDA_CODEC_ENTRY(0x10ec0660, "ALC660-VD", patch_alc861vd), 7294 HDA_CODEC_ENTRY(0x10ec0660, "ALC660-VD", patch_alc861vd),
7255 HDA_CODEC_ENTRY(0x10ec0861, "ALC861", patch_alc861), 7295 HDA_CODEC_ENTRY(0x10ec0861, "ALC861", patch_alc861),
@@ -7281,6 +7321,7 @@ static const struct hda_device_id snd_hda_id_realtek[] = {
7281 HDA_CODEC_ENTRY(0x10ec0892, "ALC892", patch_alc662), 7321 HDA_CODEC_ENTRY(0x10ec0892, "ALC892", patch_alc662),
7282 HDA_CODEC_ENTRY(0x10ec0899, "ALC898", patch_alc882), 7322 HDA_CODEC_ENTRY(0x10ec0899, "ALC898", patch_alc882),
7283 HDA_CODEC_ENTRY(0x10ec0900, "ALC1150", patch_alc882), 7323 HDA_CODEC_ENTRY(0x10ec0900, "ALC1150", patch_alc882),
7324 HDA_CODEC_ENTRY(0x10ec1220, "ALC1220", patch_alc882),
7284 {} /* terminator */ 7325 {} /* terminator */
7285}; 7326};
7286MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_realtek); 7327MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_realtek);
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 37b70f8e878f..faa3d38bac0b 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -166,6 +166,7 @@ enum {
166 STAC_D965_VERBS, 166 STAC_D965_VERBS,
167 STAC_DELL_3ST, 167 STAC_DELL_3ST,
168 STAC_DELL_BIOS, 168 STAC_DELL_BIOS,
169 STAC_NEMO_DEFAULT,
169 STAC_DELL_BIOS_AMIC, 170 STAC_DELL_BIOS_AMIC,
170 STAC_DELL_BIOS_SPDIF, 171 STAC_DELL_BIOS_SPDIF,
171 STAC_927X_DELL_DMIC, 172 STAC_927X_DELL_DMIC,
@@ -1360,6 +1361,27 @@ static const struct hda_pintbl oqo9200_pin_configs[] = {
1360 {} 1361 {}
1361}; 1362};
1362 1363
1364/*
1365 * STAC 92HD700
1366 * 18881000 Amigaone X1000
1367 */
1368static const struct hda_pintbl nemo_pin_configs[] = {
1369 { 0x0a, 0x02214020 }, /* Front panel HP socket */
1370 { 0x0b, 0x02a19080 }, /* Front Mic */
1371 { 0x0c, 0x0181304e }, /* Line in */
1372 { 0x0d, 0x01014010 }, /* Line out */
1373 { 0x0e, 0x01a19040 }, /* Rear Mic */
1374 { 0x0f, 0x01011012 }, /* Rear speakers */
1375 { 0x10, 0x01016011 }, /* Center speaker */
1376 { 0x11, 0x01012014 }, /* Side speakers (7.1) */
1377 { 0x12, 0x103301f0 }, /* Motherboard CD line in connector */
1378 { 0x13, 0x411111f0 }, /* Unused */
1379 { 0x14, 0x411111f0 }, /* Unused */
1380 { 0x21, 0x01442170 }, /* S/PDIF line out */
1381 { 0x22, 0x411111f0 }, /* Unused */
1382 { 0x23, 0x411111f0 }, /* Unused */
1383 {}
1384};
1363 1385
1364static void stac9200_fixup_panasonic(struct hda_codec *codec, 1386static void stac9200_fixup_panasonic(struct hda_codec *codec,
1365 const struct hda_fixup *fix, int action) 1387 const struct hda_fixup *fix, int action)
@@ -3883,6 +3905,10 @@ static const struct hda_fixup stac927x_fixups[] = {
3883 .type = HDA_FIXUP_PINS, 3905 .type = HDA_FIXUP_PINS,
3884 .v.pins = d965_5st_no_fp_pin_configs, 3906 .v.pins = d965_5st_no_fp_pin_configs,
3885 }, 3907 },
3908 [STAC_NEMO_DEFAULT] = {
3909 .type = HDA_FIXUP_PINS,
3910 .v.pins = nemo_pin_configs,
3911 },
3886 [STAC_DELL_3ST] = { 3912 [STAC_DELL_3ST] = {
3887 .type = HDA_FIXUP_PINS, 3913 .type = HDA_FIXUP_PINS,
3888 .v.pins = dell_3st_pin_configs, 3914 .v.pins = dell_3st_pin_configs,
@@ -3939,6 +3965,7 @@ static const struct hda_model_fixup stac927x_models[] = {
3939 { .id = STAC_D965_5ST_NO_FP, .name = "5stack-no-fp" }, 3965 { .id = STAC_D965_5ST_NO_FP, .name = "5stack-no-fp" },
3940 { .id = STAC_DELL_3ST, .name = "dell-3stack" }, 3966 { .id = STAC_DELL_3ST, .name = "dell-3stack" },
3941 { .id = STAC_DELL_BIOS, .name = "dell-bios" }, 3967 { .id = STAC_DELL_BIOS, .name = "dell-bios" },
3968 { .id = STAC_NEMO_DEFAULT, .name = "nemo-default" },
3942 { .id = STAC_DELL_BIOS_AMIC, .name = "dell-bios-amic" }, 3969 { .id = STAC_DELL_BIOS_AMIC, .name = "dell-bios-amic" },
3943 { .id = STAC_927X_VOLKNOB, .name = "volknob" }, 3970 { .id = STAC_927X_VOLKNOB, .name = "volknob" },
3944 {} 3971 {}
@@ -3977,6 +4004,8 @@ static const struct snd_pci_quirk stac927x_fixup_tbl[] = {
3977 "Intel D965", STAC_D965_5ST), 4004 "Intel D965", STAC_D965_5ST),
3978 SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_INTEL, 0xff00, 0x2500, 4005 SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_INTEL, 0xff00, 0x2500,
3979 "Intel D965", STAC_D965_5ST), 4006 "Intel D965", STAC_D965_5ST),
4007 /* Nemo */
4008 SND_PCI_QUIRK(0x1888, 0x1000, "AmigaOne X1000", STAC_NEMO_DEFAULT),
3980 /* volume-knob fixes */ 4009 /* volume-knob fixes */
3981 SND_PCI_QUIRK_VENDOR(0x10cf, "FSC", STAC_927X_VOLKNOB), 4010 SND_PCI_QUIRK_VENDOR(0x10cf, "FSC", STAC_927X_VOLKNOB),
3982 {} /* terminator */ 4011 {} /* terminator */
@@ -5036,6 +5065,7 @@ static const struct hda_device_id snd_hda_id_sigmatel[] = {
5036 HDA_CODEC_ENTRY(0x83847683, "STAC9221D A2", patch_stac922x), 5065 HDA_CODEC_ENTRY(0x83847683, "STAC9221D A2", patch_stac922x),
5037 HDA_CODEC_ENTRY(0x83847618, "STAC9227", patch_stac927x), 5066 HDA_CODEC_ENTRY(0x83847618, "STAC9227", patch_stac927x),
5038 HDA_CODEC_ENTRY(0x83847619, "STAC9227", patch_stac927x), 5067 HDA_CODEC_ENTRY(0x83847619, "STAC9227", patch_stac927x),
5068 HDA_CODEC_ENTRY(0x83847638, "STAC92HD700", patch_stac927x),
5039 HDA_CODEC_ENTRY(0x83847616, "STAC9228", patch_stac927x), 5069 HDA_CODEC_ENTRY(0x83847616, "STAC9228", patch_stac927x),
5040 HDA_CODEC_ENTRY(0x83847617, "STAC9228", patch_stac927x), 5070 HDA_CODEC_ENTRY(0x83847617, "STAC9228", patch_stac927x),
5041 HDA_CODEC_ENTRY(0x83847614, "STAC9229", patch_stac927x), 5071 HDA_CODEC_ENTRY(0x83847614, "STAC9229", patch_stac927x),
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
index e5c52ed9b674..842744e7a139 100644
--- a/sound/pci/ice1712/ice1724.c
+++ b/sound/pci/ice1712/ice1724.c
@@ -367,7 +367,7 @@ static void vt1724_midi_output_drain(struct snd_rawmidi_substream *s)
367 } while (time_after(timeout, jiffies)); 367 } while (time_after(timeout, jiffies));
368} 368}
369 369
370static struct snd_rawmidi_ops vt1724_midi_output_ops = { 370static const struct snd_rawmidi_ops vt1724_midi_output_ops = {
371 .open = vt1724_midi_output_open, 371 .open = vt1724_midi_output_open,
372 .close = vt1724_midi_output_close, 372 .close = vt1724_midi_output_close,
373 .trigger = vt1724_midi_output_trigger, 373 .trigger = vt1724_midi_output_trigger,
@@ -402,7 +402,7 @@ static void vt1724_midi_input_trigger(struct snd_rawmidi_substream *s, int up)
402 spin_unlock_irqrestore(&ice->reg_lock, flags); 402 spin_unlock_irqrestore(&ice->reg_lock, flags);
403} 403}
404 404
405static struct snd_rawmidi_ops vt1724_midi_input_ops = { 405static const struct snd_rawmidi_ops vt1724_midi_input_ops = {
406 .open = vt1724_midi_input_open, 406 .open = vt1724_midi_input_open,
407 .close = vt1724_midi_input_close, 407 .close = vt1724_midi_input_close,
408 .trigger = vt1724_midi_input_trigger, 408 .trigger = vt1724_midi_input_trigger,
diff --git a/sound/pci/mixart/mixart.h b/sound/pci/mixart/mixart.h
index 0cc17e0ea34a..426743871540 100644
--- a/sound/pci/mixart/mixart.h
+++ b/sound/pci/mixart/mixart.h
@@ -86,7 +86,7 @@ struct mixart_mgr {
86 u32 msg_fifo[MSG_FIFO_SIZE]; 86 u32 msg_fifo[MSG_FIFO_SIZE];
87 int msg_fifo_readptr; 87 int msg_fifo_readptr;
88 int msg_fifo_writeptr; 88 int msg_fifo_writeptr;
89 atomic_t msg_processed; /* number of messages to be processed in takslet */ 89 atomic_t msg_processed; /* number of messages to be processed in tasklet */
90 90
91 struct mutex lock; /* interrupt lock */ 91 struct mutex lock; /* interrupt lock */
92 struct mutex msg_lock; /* mailbox lock */ 92 struct mutex msg_lock; /* mailbox lock */
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
index b94fc6357139..fc0face6cdc6 100644
--- a/sound/pci/rme9652/hdsp.c
+++ b/sound/pci/rme9652/hdsp.c
@@ -1510,14 +1510,14 @@ static int snd_hdsp_midi_output_close(struct snd_rawmidi_substream *substream)
1510 return 0; 1510 return 0;
1511} 1511}
1512 1512
1513static struct snd_rawmidi_ops snd_hdsp_midi_output = 1513static const struct snd_rawmidi_ops snd_hdsp_midi_output =
1514{ 1514{
1515 .open = snd_hdsp_midi_output_open, 1515 .open = snd_hdsp_midi_output_open,
1516 .close = snd_hdsp_midi_output_close, 1516 .close = snd_hdsp_midi_output_close,
1517 .trigger = snd_hdsp_midi_output_trigger, 1517 .trigger = snd_hdsp_midi_output_trigger,
1518}; 1518};
1519 1519
1520static struct snd_rawmidi_ops snd_hdsp_midi_input = 1520static const struct snd_rawmidi_ops snd_hdsp_midi_input =
1521{ 1521{
1522 .open = snd_hdsp_midi_input_open, 1522 .open = snd_hdsp_midi_input_open,
1523 .close = snd_hdsp_midi_input_close, 1523 .close = snd_hdsp_midi_input_close,
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
index 14bbf55c1ef9..c48acdb0e186 100644
--- a/sound/pci/rme9652/hdspm.c
+++ b/sound/pci/rme9652/hdspm.c
@@ -2043,14 +2043,14 @@ static int snd_hdspm_midi_output_close(struct snd_rawmidi_substream *substream)
2043 return 0; 2043 return 0;
2044} 2044}
2045 2045
2046static struct snd_rawmidi_ops snd_hdspm_midi_output = 2046static const struct snd_rawmidi_ops snd_hdspm_midi_output =
2047{ 2047{
2048 .open = snd_hdspm_midi_output_open, 2048 .open = snd_hdspm_midi_output_open,
2049 .close = snd_hdspm_midi_output_close, 2049 .close = snd_hdspm_midi_output_close,
2050 .trigger = snd_hdspm_midi_output_trigger, 2050 .trigger = snd_hdspm_midi_output_trigger,
2051}; 2051};
2052 2052
2053static struct snd_rawmidi_ops snd_hdspm_midi_input = 2053static const struct snd_rawmidi_ops snd_hdspm_midi_input =
2054{ 2054{
2055 .open = snd_hdspm_midi_input_open, 2055 .open = snd_hdspm_midi_input_open,
2056 .close = snd_hdspm_midi_input_close, 2056 .close = snd_hdspm_midi_input_close,
diff --git a/sound/pci/vx222/vx222_ops.c b/sound/pci/vx222/vx222_ops.c
index af83b3b38052..8e457ea27f89 100644
--- a/sound/pci/vx222/vx222_ops.c
+++ b/sound/pci/vx222/vx222_ops.c
@@ -269,12 +269,12 @@ static void vx2_dma_write(struct vx_core *chip, struct snd_pcm_runtime *runtime,
269 269
270 /* Transfer using pseudo-dma. 270 /* Transfer using pseudo-dma.
271 */ 271 */
272 if (offset + count > pipe->buffer_bytes) { 272 if (offset + count >= pipe->buffer_bytes) {
273 int length = pipe->buffer_bytes - offset; 273 int length = pipe->buffer_bytes - offset;
274 count -= length; 274 count -= length;
275 length >>= 2; /* in 32bit words */ 275 length >>= 2; /* in 32bit words */
276 /* Transfer using pseudo-dma. */ 276 /* Transfer using pseudo-dma. */
277 while (length-- > 0) { 277 for (; length > 0; length--) {
278 outl(cpu_to_le32(*addr), port); 278 outl(cpu_to_le32(*addr), port);
279 addr++; 279 addr++;
280 } 280 }
@@ -284,7 +284,7 @@ static void vx2_dma_write(struct vx_core *chip, struct snd_pcm_runtime *runtime,
284 pipe->hw_ptr += count; 284 pipe->hw_ptr += count;
285 count >>= 2; /* in 32bit words */ 285 count >>= 2; /* in 32bit words */
286 /* Transfer using pseudo-dma. */ 286 /* Transfer using pseudo-dma. */
287 while (count-- > 0) { 287 for (; count > 0; count--) {
288 outl(cpu_to_le32(*addr), port); 288 outl(cpu_to_le32(*addr), port);
289 addr++; 289 addr++;
290 } 290 }
@@ -307,12 +307,12 @@ static void vx2_dma_read(struct vx_core *chip, struct snd_pcm_runtime *runtime,
307 vx2_setup_pseudo_dma(chip, 0); 307 vx2_setup_pseudo_dma(chip, 0);
308 /* Transfer using pseudo-dma. 308 /* Transfer using pseudo-dma.
309 */ 309 */
310 if (offset + count > pipe->buffer_bytes) { 310 if (offset + count >= pipe->buffer_bytes) {
311 int length = pipe->buffer_bytes - offset; 311 int length = pipe->buffer_bytes - offset;
312 count -= length; 312 count -= length;
313 length >>= 2; /* in 32bit words */ 313 length >>= 2; /* in 32bit words */
314 /* Transfer using pseudo-dma. */ 314 /* Transfer using pseudo-dma. */
315 while (length-- > 0) 315 for (; length > 0; length--)
316 *addr++ = le32_to_cpu(inl(port)); 316 *addr++ = le32_to_cpu(inl(port));
317 addr = (u32 *)runtime->dma_area; 317 addr = (u32 *)runtime->dma_area;
318 pipe->hw_ptr = 0; 318 pipe->hw_ptr = 0;
@@ -320,7 +320,7 @@ static void vx2_dma_read(struct vx_core *chip, struct snd_pcm_runtime *runtime,
320 pipe->hw_ptr += count; 320 pipe->hw_ptr += count;
321 count >>= 2; /* in 32bit words */ 321 count >>= 2; /* in 32bit words */
322 /* Transfer using pseudo-dma. */ 322 /* Transfer using pseudo-dma. */
323 while (count-- > 0) 323 for (; count > 0; count--)
324 *addr++ = le32_to_cpu(inl(port)); 324 *addr++ = le32_to_cpu(inl(port));
325 325
326 vx2_release_pseudo_dma(chip); 326 vx2_release_pseudo_dma(chip);
diff --git a/sound/pcmcia/vx/vxp_ops.c b/sound/pcmcia/vx/vxp_ops.c
index 281972913c32..56aa1ba73ccc 100644
--- a/sound/pcmcia/vx/vxp_ops.c
+++ b/sound/pcmcia/vx/vxp_ops.c
@@ -369,12 +369,12 @@ static void vxp_dma_write(struct vx_core *chip, struct snd_pcm_runtime *runtime,
369 unsigned short *addr = (unsigned short *)(runtime->dma_area + offset); 369 unsigned short *addr = (unsigned short *)(runtime->dma_area + offset);
370 370
371 vx_setup_pseudo_dma(chip, 1); 371 vx_setup_pseudo_dma(chip, 1);
372 if (offset + count > pipe->buffer_bytes) { 372 if (offset + count >= pipe->buffer_bytes) {
373 int length = pipe->buffer_bytes - offset; 373 int length = pipe->buffer_bytes - offset;
374 count -= length; 374 count -= length;
375 length >>= 1; /* in 16bit words */ 375 length >>= 1; /* in 16bit words */
376 /* Transfer using pseudo-dma. */ 376 /* Transfer using pseudo-dma. */
377 while (length-- > 0) { 377 for (; length > 0; length--) {
378 outw(cpu_to_le16(*addr), port); 378 outw(cpu_to_le16(*addr), port);
379 addr++; 379 addr++;
380 } 380 }
@@ -384,7 +384,7 @@ static void vxp_dma_write(struct vx_core *chip, struct snd_pcm_runtime *runtime,
384 pipe->hw_ptr += count; 384 pipe->hw_ptr += count;
385 count >>= 1; /* in 16bit words */ 385 count >>= 1; /* in 16bit words */
386 /* Transfer using pseudo-dma. */ 386 /* Transfer using pseudo-dma. */
387 while (count-- > 0) { 387 for (; count > 0; count--) {
388 outw(cpu_to_le16(*addr), port); 388 outw(cpu_to_le16(*addr), port);
389 addr++; 389 addr++;
390 } 390 }
@@ -411,12 +411,12 @@ static void vxp_dma_read(struct vx_core *chip, struct snd_pcm_runtime *runtime,
411 if (snd_BUG_ON(count % 2)) 411 if (snd_BUG_ON(count % 2))
412 return; 412 return;
413 vx_setup_pseudo_dma(chip, 0); 413 vx_setup_pseudo_dma(chip, 0);
414 if (offset + count > pipe->buffer_bytes) { 414 if (offset + count >= pipe->buffer_bytes) {
415 int length = pipe->buffer_bytes - offset; 415 int length = pipe->buffer_bytes - offset;
416 count -= length; 416 count -= length;
417 length >>= 1; /* in 16bit words */ 417 length >>= 1; /* in 16bit words */
418 /* Transfer using pseudo-dma. */ 418 /* Transfer using pseudo-dma. */
419 while (length-- > 0) 419 for (; length > 0; length--)
420 *addr++ = le16_to_cpu(inw(port)); 420 *addr++ = le16_to_cpu(inw(port));
421 addr = (unsigned short *)runtime->dma_area; 421 addr = (unsigned short *)runtime->dma_area;
422 pipe->hw_ptr = 0; 422 pipe->hw_ptr = 0;
@@ -424,7 +424,7 @@ static void vxp_dma_read(struct vx_core *chip, struct snd_pcm_runtime *runtime,
424 pipe->hw_ptr += count; 424 pipe->hw_ptr += count;
425 count >>= 1; /* in 16bit words */ 425 count >>= 1; /* in 16bit words */
426 /* Transfer using pseudo-dma. */ 426 /* Transfer using pseudo-dma. */
427 while (count-- > 1) 427 for (; count > 1; count--)
428 *addr++ = le16_to_cpu(inw(port)); 428 *addr++ = le16_to_cpu(inw(port));
429 /* Disable DMA */ 429 /* Disable DMA */
430 pchip->regDIALOG &= ~VXP_DLG_DMAREAD_SEL_MASK; 430 pchip->regDIALOG &= ~VXP_DLG_DMAREAD_SEL_MASK;
diff --git a/sound/synth/emux/emux_seq.c b/sound/synth/emux/emux_seq.c
index a0209204ae48..55579f6b8cb2 100644
--- a/sound/synth/emux/emux_seq.c
+++ b/sound/synth/emux/emux_seq.c
@@ -33,13 +33,13 @@ static int snd_emux_unuse(void *private_data, struct snd_seq_port_subscribe *inf
33 * MIDI emulation operators 33 * MIDI emulation operators
34 */ 34 */
35static struct snd_midi_op emux_ops = { 35static struct snd_midi_op emux_ops = {
36 snd_emux_note_on, 36 .note_on = snd_emux_note_on,
37 snd_emux_note_off, 37 .note_off = snd_emux_note_off,
38 snd_emux_key_press, 38 .key_press = snd_emux_key_press,
39 snd_emux_terminate_note, 39 .note_terminate = snd_emux_terminate_note,
40 snd_emux_control, 40 .control = snd_emux_control,
41 snd_emux_nrpn, 41 .nrpn = snd_emux_nrpn,
42 snd_emux_sysex, 42 .sysex = snd_emux_sysex,
43}; 43};
44 44
45 45
diff --git a/sound/usb/6fire/midi.c b/sound/usb/6fire/midi.c
index 3d410969553e..aa5adbb6eb5d 100644
--- a/sound/usb/6fire/midi.c
+++ b/sound/usb/6fire/midi.c
@@ -139,14 +139,14 @@ static void usb6fire_midi_in_trigger(
139 spin_unlock_irqrestore(&rt->in_lock, flags); 139 spin_unlock_irqrestore(&rt->in_lock, flags);
140} 140}
141 141
142static struct snd_rawmidi_ops out_ops = { 142static const struct snd_rawmidi_ops out_ops = {
143 .open = usb6fire_midi_out_open, 143 .open = usb6fire_midi_out_open,
144 .close = usb6fire_midi_out_close, 144 .close = usb6fire_midi_out_close,
145 .trigger = usb6fire_midi_out_trigger, 145 .trigger = usb6fire_midi_out_trigger,
146 .drain = usb6fire_midi_out_drain 146 .drain = usb6fire_midi_out_drain
147}; 147};
148 148
149static struct snd_rawmidi_ops in_ops = { 149static const struct snd_rawmidi_ops in_ops = {
150 .open = usb6fire_midi_in_open, 150 .open = usb6fire_midi_in_open,
151 .close = usb6fire_midi_in_close, 151 .close = usb6fire_midi_in_close,
152 .trigger = usb6fire_midi_in_trigger 152 .trigger = usb6fire_midi_in_trigger
diff --git a/sound/usb/Makefile b/sound/usb/Makefile
index 2d2d122b069f..42cb33b94f6a 100644
--- a/sound/usb/Makefile
+++ b/sound/usb/Makefile
@@ -10,6 +10,7 @@ snd-usb-audio-objs := card.o \
10 mixer.o \ 10 mixer.o \
11 mixer_quirks.o \ 11 mixer_quirks.o \
12 mixer_scarlett.o \ 12 mixer_scarlett.o \
13 mixer_us16x08.o \
13 pcm.o \ 14 pcm.o \
14 proc.o \ 15 proc.o \
15 quirks.o \ 16 quirks.o \
diff --git a/sound/usb/bcd2000/bcd2000.c b/sound/usb/bcd2000/bcd2000.c
index d060dddcc52d..2ff9d578753a 100644
--- a/sound/usb/bcd2000/bcd2000.c
+++ b/sound/usb/bcd2000/bcd2000.c
@@ -252,13 +252,13 @@ static void bcd2000_input_complete(struct urb *urb)
252 __func__, ret); 252 __func__, ret);
253} 253}
254 254
255static struct snd_rawmidi_ops bcd2000_midi_output = { 255static const struct snd_rawmidi_ops bcd2000_midi_output = {
256 .open = bcd2000_midi_output_open, 256 .open = bcd2000_midi_output_open,
257 .close = bcd2000_midi_output_close, 257 .close = bcd2000_midi_output_close,
258 .trigger = bcd2000_midi_output_trigger, 258 .trigger = bcd2000_midi_output_trigger,
259}; 259};
260 260
261static struct snd_rawmidi_ops bcd2000_midi_input = { 261static const struct snd_rawmidi_ops bcd2000_midi_input = {
262 .open = bcd2000_midi_input_open, 262 .open = bcd2000_midi_input_open,
263 .close = bcd2000_midi_input_close, 263 .close = bcd2000_midi_input_close,
264 .trigger = bcd2000_midi_input_trigger, 264 .trigger = bcd2000_midi_input_trigger,
diff --git a/sound/usb/caiaq/midi.c b/sound/usb/caiaq/midi.c
index 2d7588461b33..f8e5b1b57c4f 100644
--- a/sound/usb/caiaq/midi.c
+++ b/sound/usb/caiaq/midi.c
@@ -102,14 +102,14 @@ static void snd_usb_caiaq_midi_output_trigger(struct snd_rawmidi_substream *subs
102} 102}
103 103
104 104
105static struct snd_rawmidi_ops snd_usb_caiaq_midi_output = 105static const struct snd_rawmidi_ops snd_usb_caiaq_midi_output =
106{ 106{
107 .open = snd_usb_caiaq_midi_output_open, 107 .open = snd_usb_caiaq_midi_output_open,
108 .close = snd_usb_caiaq_midi_output_close, 108 .close = snd_usb_caiaq_midi_output_close,
109 .trigger = snd_usb_caiaq_midi_output_trigger, 109 .trigger = snd_usb_caiaq_midi_output_trigger,
110}; 110};
111 111
112static struct snd_rawmidi_ops snd_usb_caiaq_midi_input = 112static const struct snd_rawmidi_ops snd_usb_caiaq_midi_input =
113{ 113{
114 .open = snd_usb_caiaq_midi_input_open, 114 .open = snd_usb_caiaq_midi_input_open,
115 .close = snd_usb_caiaq_midi_input_close, 115 .close = snd_usb_caiaq_midi_input_close,
diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c
index 90009c0b3a92..0ff5a7d2e19f 100644
--- a/sound/usb/line6/driver.c
+++ b/sound/usb/line6/driver.c
@@ -492,42 +492,46 @@ static void line6_destruct(struct snd_card *card)
492 usb_put_dev(usbdev); 492 usb_put_dev(usbdev);
493} 493}
494 494
495/* get data from endpoint descriptor (see usb_maxpacket): */ 495static void line6_get_usb_properties(struct usb_line6 *line6)
496static void line6_get_interval(struct usb_line6 *line6)
497{ 496{
498 struct usb_device *usbdev = line6->usbdev; 497 struct usb_device *usbdev = line6->usbdev;
499 const struct line6_properties *properties = line6->properties; 498 const struct line6_properties *properties = line6->properties;
500 int pipe; 499 int pipe;
501 struct usb_host_endpoint *ep; 500 struct usb_host_endpoint *ep = NULL;
502 501
503 if (properties->capabilities & LINE6_CAP_CONTROL_MIDI) { 502 if (properties->capabilities & LINE6_CAP_CONTROL) {
504 pipe = 503 if (properties->capabilities & LINE6_CAP_CONTROL_MIDI) {
505 usb_rcvintpipe(line6->usbdev, line6->properties->ep_ctrl_r); 504 pipe = usb_rcvintpipe(line6->usbdev,
506 } else { 505 line6->properties->ep_ctrl_r);
507 pipe = 506 } else {
508 usb_rcvbulkpipe(line6->usbdev, line6->properties->ep_ctrl_r); 507 pipe = usb_rcvbulkpipe(line6->usbdev,
508 line6->properties->ep_ctrl_r);
509 }
510 ep = usbdev->ep_in[usb_pipeendpoint(pipe)];
509 } 511 }
510 ep = usbdev->ep_in[usb_pipeendpoint(pipe)];
511 512
513 /* Control data transfer properties */
512 if (ep) { 514 if (ep) {
513 line6->interval = ep->desc.bInterval; 515 line6->interval = ep->desc.bInterval;
514 if (usbdev->speed == USB_SPEED_LOW) {
515 line6->intervals_per_second = USB_LOW_INTERVALS_PER_SECOND;
516 line6->iso_buffers = USB_LOW_ISO_BUFFERS;
517 } else {
518 line6->intervals_per_second = USB_HIGH_INTERVALS_PER_SECOND;
519 line6->iso_buffers = USB_HIGH_ISO_BUFFERS;
520 }
521
522 line6->max_packet_size = le16_to_cpu(ep->desc.wMaxPacketSize); 516 line6->max_packet_size = le16_to_cpu(ep->desc.wMaxPacketSize);
523 } else { 517 } else {
524 dev_err(line6->ifcdev, 518 if (properties->capabilities & LINE6_CAP_CONTROL) {
525 "endpoint not available, using fallback values"); 519 dev_err(line6->ifcdev,
520 "endpoint not available, using fallback values");
521 }
526 line6->interval = LINE6_FALLBACK_INTERVAL; 522 line6->interval = LINE6_FALLBACK_INTERVAL;
527 line6->max_packet_size = LINE6_FALLBACK_MAXPACKETSIZE; 523 line6->max_packet_size = LINE6_FALLBACK_MAXPACKETSIZE;
528 } 524 }
529}
530 525
526 /* Isochronous transfer properties */
527 if (usbdev->speed == USB_SPEED_LOW) {
528 line6->intervals_per_second = USB_LOW_INTERVALS_PER_SECOND;
529 line6->iso_buffers = USB_LOW_ISO_BUFFERS;
530 } else {
531 line6->intervals_per_second = USB_HIGH_INTERVALS_PER_SECOND;
532 line6->iso_buffers = USB_HIGH_ISO_BUFFERS;
533 }
534}
531 535
532/* Enable buffering of incoming messages, flush the buffer */ 536/* Enable buffering of incoming messages, flush the buffer */
533static int line6_hwdep_open(struct snd_hwdep *hw, struct file *file) 537static int line6_hwdep_open(struct snd_hwdep *hw, struct file *file)
@@ -754,8 +758,9 @@ int line6_probe(struct usb_interface *interface,
754 goto error; 758 goto error;
755 } 759 }
756 760
761 line6_get_usb_properties(line6);
762
757 if (properties->capabilities & LINE6_CAP_CONTROL) { 763 if (properties->capabilities & LINE6_CAP_CONTROL) {
758 line6_get_interval(line6);
759 ret = line6_init_cap_control(line6); 764 ret = line6_init_cap_control(line6);
760 if (ret < 0) 765 if (ret < 0)
761 goto error; 766 goto error;
diff --git a/sound/usb/line6/midi.c b/sound/usb/line6/midi.c
index d0fb2f205bd9..1d3a23b02d68 100644
--- a/sound/usb/line6/midi.c
+++ b/sound/usb/line6/midi.c
@@ -200,14 +200,14 @@ static void line6_midi_input_trigger(struct snd_rawmidi_substream *substream,
200 line6->line6midi->substream_receive = NULL; 200 line6->line6midi->substream_receive = NULL;
201} 201}
202 202
203static struct snd_rawmidi_ops line6_midi_output_ops = { 203static const struct snd_rawmidi_ops line6_midi_output_ops = {
204 .open = line6_midi_output_open, 204 .open = line6_midi_output_open,
205 .close = line6_midi_output_close, 205 .close = line6_midi_output_close,
206 .trigger = line6_midi_output_trigger, 206 .trigger = line6_midi_output_trigger,
207 .drain = line6_midi_output_drain, 207 .drain = line6_midi_output_drain,
208}; 208};
209 209
210static struct snd_rawmidi_ops line6_midi_input_ops = { 210static const struct snd_rawmidi_ops line6_midi_input_ops = {
211 .open = line6_midi_input_open, 211 .open = line6_midi_input_open,
212 .close = line6_midi_input_close, 212 .close = line6_midi_input_close,
213 .trigger = line6_midi_input_trigger, 213 .trigger = line6_midi_input_trigger,
diff --git a/sound/usb/midi.c b/sound/usb/midi.c
index 7ba92921bf28..6e763bc8d7db 100644
--- a/sound/usb/midi.c
+++ b/sound/usb/midi.c
@@ -1234,14 +1234,14 @@ static void snd_usbmidi_input_trigger(struct snd_rawmidi_substream *substream,
1234 clear_bit(substream->number, &umidi->input_triggered); 1234 clear_bit(substream->number, &umidi->input_triggered);
1235} 1235}
1236 1236
1237static struct snd_rawmidi_ops snd_usbmidi_output_ops = { 1237static const struct snd_rawmidi_ops snd_usbmidi_output_ops = {
1238 .open = snd_usbmidi_output_open, 1238 .open = snd_usbmidi_output_open,
1239 .close = snd_usbmidi_output_close, 1239 .close = snd_usbmidi_output_close,
1240 .trigger = snd_usbmidi_output_trigger, 1240 .trigger = snd_usbmidi_output_trigger,
1241 .drain = snd_usbmidi_output_drain, 1241 .drain = snd_usbmidi_output_drain,
1242}; 1242};
1243 1243
1244static struct snd_rawmidi_ops snd_usbmidi_input_ops = { 1244static const struct snd_rawmidi_ops snd_usbmidi_input_ops = {
1245 .open = snd_usbmidi_input_open, 1245 .open = snd_usbmidi_input_open,
1246 .close = snd_usbmidi_input_close, 1246 .close = snd_usbmidi_input_close,
1247 .trigger = snd_usbmidi_input_trigger 1247 .trigger = snd_usbmidi_input_trigger
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
index 04991b009132..4fa0053a40af 100644
--- a/sound/usb/mixer_quirks.c
+++ b/sound/usb/mixer_quirks.c
@@ -43,6 +43,7 @@
43#include "mixer.h" 43#include "mixer.h"
44#include "mixer_quirks.h" 44#include "mixer_quirks.h"
45#include "mixer_scarlett.h" 45#include "mixer_scarlett.h"
46#include "mixer_us16x08.h"
46#include "helper.h" 47#include "helper.h"
47 48
48extern struct snd_kcontrol_new *snd_usb_feature_unit_ctl; 49extern struct snd_kcontrol_new *snd_usb_feature_unit_ctl;
@@ -1729,6 +1730,10 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
1729 return err; 1730 return err;
1730 1731
1731 switch (mixer->chip->usb_id) { 1732 switch (mixer->chip->usb_id) {
1733 /* Tascam US-16x08 */
1734 case USB_ID(0x0644, 0x8047):
1735 err = snd_us16x08_controls_create(mixer);
1736 break;
1732 case USB_ID(0x041e, 0x3020): 1737 case USB_ID(0x041e, 0x3020):
1733 case USB_ID(0x041e, 0x3040): 1738 case USB_ID(0x041e, 0x3040):
1734 case USB_ID(0x041e, 0x3042): 1739 case USB_ID(0x041e, 0x3042):
diff --git a/sound/usb/mixer_us16x08.c b/sound/usb/mixer_us16x08.c
new file mode 100644
index 000000000000..301939b8f472
--- /dev/null
+++ b/sound/usb/mixer_us16x08.c
@@ -0,0 +1,1465 @@
1/*
2 * Tascam US-16x08 ALSA driver
3 *
4 * Copyright (c) 2016 by Detlef Urban (onkel@paraair.de)
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 */
17
18#include <linux/slab.h>
19#include <linux/usb.h>
20#include <linux/usb/audio-v2.h>
21
22#include <sound/core.h>
23#include <sound/control.h>
24
25#include "usbaudio.h"
26#include "mixer.h"
27#include "helper.h"
28
29#include "mixer_us16x08.h"
30
31/* USB control message templates */
32static const char route_msg[] = {
33 0x61,
34 0x02,
35 0x03, /* input from master (0x02) or input from computer bus (0x03) */
36 0x62,
37 0x02,
38 0x01, /* input index (0x01/0x02 eq. left/right) or bus (0x01-0x08) */
39 0x41,
40 0x01,
41 0x61,
42 0x02,
43 0x01,
44 0x62,
45 0x02,
46 0x01, /* output index (0x01-0x08) */
47 0x42,
48 0x01,
49 0x43,
50 0x01,
51 0x00,
52 0x00
53};
54
55static const char mix_init_msg1[] = {
56 0x71, 0x01, 0x00, 0x00
57};
58
59static const char mix_init_msg2[] = {
60 0x62, 0x02, 0x00, 0x61, 0x02, 0x04, 0xb1, 0x01, 0x00, 0x00
61};
62
63static const char mix_msg_in[] = {
64 /* default message head, equal to all mixers */
65 0x61, 0x02, 0x04, 0x62, 0x02, 0x01,
66 0x81, /* 0x06: Controller ID */
67 0x02, /* 0x07: */
68 0x00, /* 0x08: Value of common mixer */
69 0x00,
70 0x00
71};
72
73static const char mix_msg_out[] = {
74 /* default message head, equal to all mixers */
75 0x61, 0x02, 0x02, 0x62, 0x02, 0x01,
76 0x81, /* 0x06: Controller ID */
77 0x02, /* 0x07: */
78 0x00, /* 0x08: Value of common mixer */
79 0x00,
80 0x00
81};
82
83static const char bypass_msg_out[] = {
84 0x45,
85 0x02,
86 0x01, /* on/off flag */
87 0x00,
88 0x00
89};
90
91static const char bus_msg_out[] = {
92 0x44,
93 0x02,
94 0x01, /* on/off flag */
95 0x00,
96 0x00
97};
98
99static const char comp_msg[] = {
100 /* default message head, equal to all mixers */
101 0x61, 0x02, 0x04, 0x62, 0x02, 0x01,
102 0x91,
103 0x02,
104 0xf0, /* 0x08: Threshold db (8) (e0 ... 00) (+-0dB -- -32dB) x-32 */
105 0x92,
106 0x02,
107 0x0a, /* 0x0b: Ratio (0a,0b,0d,0f,11,14,19,1e,23,28,32,3c,50,a0,ff) */
108 0x93,
109 0x02,
110 0x02, /* 0x0e: Attack (0x02 ... 0xc0) (2ms ... 200ms) */
111 0x94,
112 0x02,
113 0x01, /* 0x11: Release (0x01 ... 0x64) (10ms ... 1000ms) x*10 */
114 0x95,
115 0x02,
116 0x03, /* 0x14: gain (0 ... 20) (0dB .. 20dB) */
117 0x96,
118 0x02,
119 0x01,
120 0x97,
121 0x02,
122 0x01, /* 0x1a: main Comp switch (0 ... 1) (off ... on)) */
123 0x00,
124 0x00
125};
126
127static const char eqs_msq[] = {
128 /* default message head, equal to all mixers */
129 0x61, 0x02, 0x04, 0x62, 0x02, 0x01,
130 0x51, /* 0x06: Controller ID */
131 0x02,
132 0x04, /* 0x08: EQ set num (0x01..0x04) (LOW, LOWMID, HIGHMID, HIGH)) */
133 0x52,
134 0x02,
135 0x0c, /* 0x0b: value dB (0 ... 12) (-12db .. +12db) x-6 */
136 0x53,
137 0x02,
138 0x0f, /* 0x0e: value freq (32-47) (1.7kHz..18kHz) */
139 0x54,
140 0x02,
141 0x02, /* 0x11: band width (0-6) (Q16-Q0.25) 2^x/4 (EQ xxMID only) */
142 0x55,
143 0x02,
144 0x01, /* 0x14: main EQ switch (0 ... 1) (off ... on)) */
145 0x00,
146 0x00
147};
148
149/* compressor ratio map */
150static const char ratio_map[] = {
151 0x0a, 0x0b, 0x0d, 0x0f, 0x11, 0x14, 0x19, 0x1e,
152 0x23, 0x28, 0x32, 0x3c, 0x50, 0xa0, 0xff
153};
154
155/* route enumeration names */
156const const char *route_names[] = {
157 "Master Left", "Master Right", "Output 1", "Output 2", "Output 3",
158 "Output 4", "Output 5", "Output 6", "Output 7", "Output 8",
159};
160
161static int snd_us16x08_recv_urb(struct snd_usb_audio *chip,
162 unsigned char *buf, int size)
163{
164
165 mutex_lock(&chip->mutex);
166 snd_usb_ctl_msg(chip->dev,
167 usb_rcvctrlpipe(chip->dev, 0),
168 SND_US16X08_URB_METER_REQUEST,
169 SND_US16X08_URB_METER_REQUESTTYPE, 0, 0, buf, size);
170 mutex_unlock(&chip->mutex);
171 return 0;
172}
173
174/* wrapper function to send prepared URB buffer to usb device. Return an error
175 * code if something went wrong
176 */
177static int snd_us16x08_send_urb(struct snd_usb_audio *chip, char *buf, int size)
178{
179 int err = 0;
180
181 if (chip) {
182 err = snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0),
183 SND_US16X08_URB_REQUEST, SND_US16X08_URB_REQUESTTYPE,
184 0, 0, buf, size);
185 }
186
187 return err;
188}
189
190static int snd_us16x08_route_info(struct snd_kcontrol *kcontrol,
191 struct snd_ctl_elem_info *uinfo)
192{
193 return snd_ctl_enum_info(uinfo, 1, 10, route_names);
194}
195
196static int snd_us16x08_route_get(struct snd_kcontrol *kcontrol,
197 struct snd_ctl_elem_value *ucontrol)
198{
199 struct usb_mixer_elem_info *elem = kcontrol->private_data;
200 int index = ucontrol->id.index;
201
202 /* route has no bias */
203 ucontrol->value.enumerated.item[0] = elem->cache_val[index];
204
205 return 0;
206}
207
208static int snd_us16x08_route_put(struct snd_kcontrol *kcontrol,
209 struct snd_ctl_elem_value *ucontrol)
210{
211 struct usb_mixer_elem_info *elem = kcontrol->private_data;
212 struct snd_usb_audio *chip = elem->head.mixer->chip;
213 int index = ucontrol->id.index;
214 char buf[sizeof(route_msg)];
215 int val, val_org, err = 0;
216
217 /* prepare the message buffer from template */
218 memcpy(buf, route_msg, sizeof(route_msg));
219
220 /* get the new value (no bias for routes) */
221 val = ucontrol->value.enumerated.item[0];
222
223 /* sanity check */
224 if (val < 0 || val > 9)
225 return -EINVAL;
226
227 if (val < 2) {
228 /* input comes from a master channel */
229 val_org = val;
230 buf[2] = 0x02;
231 } else {
232 /* input comes from a computer channel */
233 buf[2] = 0x03;
234 val_org = val - 2;
235 }
236
237 /* place new route selection in URB message */
238 buf[5] = (unsigned char) (val_org & 0x0f) + 1;
239 /* place route selector in URB message */
240 buf[13] = index + 1;
241
242 err = snd_us16x08_send_urb(chip, buf, sizeof(route_msg));
243
244 if (err > 0) {
245 elem->cached |= 1 << index;
246 elem->cache_val[index] = val;
247 } else {
248 usb_audio_dbg(chip, "Failed to set routing, err:%d\n", err);
249 }
250
251 return err > 0 ? 1 : 0;
252}
253
254static int snd_us16x08_master_info(struct snd_kcontrol *kcontrol,
255 struct snd_ctl_elem_info *uinfo)
256{
257 uinfo->count = 1;
258 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
259 uinfo->value.integer.max = SND_US16X08_KCMAX(kcontrol);
260 uinfo->value.integer.min = SND_US16X08_KCMIN(kcontrol);
261 uinfo->value.integer.step = SND_US16X08_KCSTEP(kcontrol);
262 return 0;
263}
264
265static int snd_us16x08_master_get(struct snd_kcontrol *kcontrol,
266 struct snd_ctl_elem_value *ucontrol)
267{
268 struct usb_mixer_elem_info *elem = kcontrol->private_data;
269 int index = ucontrol->id.index;
270
271 ucontrol->value.integer.value[0] = elem->cache_val[index];
272
273 return 0;
274}
275
276static int snd_us16x08_master_put(struct snd_kcontrol *kcontrol,
277 struct snd_ctl_elem_value *ucontrol)
278{
279 struct usb_mixer_elem_info *elem = kcontrol->private_data;
280 struct snd_usb_audio *chip = elem->head.mixer->chip;
281 char buf[sizeof(mix_msg_out)];
282 int val, err = 0;
283 int index = ucontrol->id.index;
284
285 /* prepare the message buffer from template */
286 memcpy(buf, mix_msg_out, sizeof(mix_msg_out));
287
288 /* new control value incl. bias*/
289 val = ucontrol->value.integer.value[0];
290
291 /* sanity check */
292 if (val < SND_US16X08_KCMIN(kcontrol)
293 || val > SND_US16X08_KCMAX(kcontrol))
294 return -EINVAL;
295
296 buf[8] = val - SND_US16X08_KCBIAS(kcontrol);
297 buf[6] = elem->head.id;
298
299 /* place channel selector in URB message */
300 buf[5] = index + 1;
301 err = snd_us16x08_send_urb(chip, buf, sizeof(mix_msg_out));
302
303 if (err > 0) {
304 elem->cached |= 1 << index;
305 elem->cache_val[index] = val;
306 } else {
307 usb_audio_dbg(chip, "Failed to set master, err:%d\n", err);
308 }
309
310 return err > 0 ? 1 : 0;
311}
312
313static int snd_us16x08_bus_put(struct snd_kcontrol *kcontrol,
314 struct snd_ctl_elem_value *ucontrol)
315{
316 struct usb_mixer_elem_info *elem = kcontrol->private_data;
317 struct snd_usb_audio *chip = elem->head.mixer->chip;
318 char buf[sizeof(mix_msg_out)];
319 int val, err = 0;
320
321 val = ucontrol->value.integer.value[0];
322
323 /* prepare the message buffer from template */
324 switch (elem->head.id) {
325 case SND_US16X08_ID_BYPASS:
326 memcpy(buf, bypass_msg_out, sizeof(bypass_msg_out));
327 buf[2] = val;
328 err = snd_us16x08_send_urb(chip, buf, sizeof(bypass_msg_out));
329 break;
330 case SND_US16X08_ID_BUSS_OUT:
331 memcpy(buf, bus_msg_out, sizeof(bus_msg_out));
332 buf[2] = val;
333 err = snd_us16x08_send_urb(chip, buf, sizeof(bus_msg_out));
334 break;
335 case SND_US16X08_ID_MUTE:
336 memcpy(buf, mix_msg_out, sizeof(mix_msg_out));
337 buf[8] = val;
338 buf[6] = elem->head.id;
339 buf[5] = 1;
340 err = snd_us16x08_send_urb(chip, buf, sizeof(mix_msg_out));
341 break;
342 }
343
344 if (err > 0) {
345 elem->cached |= 1;
346 elem->cache_val[0] = val;
347 } else {
348 usb_audio_dbg(chip, "Failed to set buss param, err:%d\n", err);
349 }
350
351 return err > 0 ? 1 : 0;
352}
353
354static int snd_us16x08_bus_get(struct snd_kcontrol *kcontrol,
355 struct snd_ctl_elem_value *ucontrol)
356{
357 struct usb_mixer_elem_info *elem = kcontrol->private_data;
358
359 switch (elem->head.id) {
360 case SND_US16X08_ID_BUSS_OUT:
361 ucontrol->value.integer.value[0] = elem->cache_val[0];
362 break;
363 case SND_US16X08_ID_BYPASS:
364 ucontrol->value.integer.value[0] = elem->cache_val[0];
365 break;
366 case SND_US16X08_ID_MUTE:
367 ucontrol->value.integer.value[0] = elem->cache_val[0];
368 break;
369 }
370
371 return 0;
372}
373
374/* gets a current mixer value from common store */
375static int snd_us16x08_channel_get(struct snd_kcontrol *kcontrol,
376 struct snd_ctl_elem_value *ucontrol)
377{
378 struct usb_mixer_elem_info *elem = kcontrol->private_data;
379 int index = ucontrol->id.index;
380
381 ucontrol->value.integer.value[0] = elem->cache_val[index];
382
383 return 0;
384}
385
386static int snd_us16x08_channel_put(struct snd_kcontrol *kcontrol,
387 struct snd_ctl_elem_value *ucontrol)
388{
389 struct usb_mixer_elem_info *elem = kcontrol->private_data;
390 struct snd_usb_audio *chip = elem->head.mixer->chip;
391 char buf[sizeof(mix_msg_in)];
392 int val, err;
393 int index = ucontrol->id.index;
394
395 /* prepare URB message from template */
396 memcpy(buf, mix_msg_in, sizeof(mix_msg_in));
397
398 val = ucontrol->value.integer.value[0];
399
400 /* sanity check */
401 if (val < SND_US16X08_KCMIN(kcontrol)
402 || val > SND_US16X08_KCMAX(kcontrol))
403 return -EINVAL;
404
405 /* add the bias to the new value */
406 buf[8] = val - SND_US16X08_KCBIAS(kcontrol);
407 buf[6] = elem->head.id;
408 buf[5] = index + 1;
409
410 err = snd_us16x08_send_urb(chip, buf, sizeof(mix_msg_in));
411
412 if (err > 0) {
413 elem->cached |= 1 << index;
414 elem->cache_val[index] = val;
415 } else {
416 usb_audio_dbg(chip, "Failed to set channel, err:%d\n", err);
417 }
418
419 return err > 0 ? 1 : 0;
420}
421
422static int snd_us16x08_mix_info(struct snd_kcontrol *kcontrol,
423 struct snd_ctl_elem_info *uinfo)
424{
425 uinfo->count = 1;
426 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
427 uinfo->value.integer.max = SND_US16X08_KCMAX(kcontrol);
428 uinfo->value.integer.min = SND_US16X08_KCMIN(kcontrol);
429 uinfo->value.integer.step = SND_US16X08_KCSTEP(kcontrol);
430 return 0;
431}
432
433static int snd_us16x08_comp_get(struct snd_kcontrol *kcontrol,
434 struct snd_ctl_elem_value *ucontrol)
435{
436 struct usb_mixer_elem_info *elem = kcontrol->private_data;
437 struct snd_us16x08_comp_store *store =
438 ((struct snd_us16x08_comp_store *) elem->private_data);
439 int index = ucontrol->id.index;
440 int val_idx = COMP_STORE_IDX(elem->head.id);
441
442 ucontrol->value.integer.value[0] = store->val[val_idx][index];
443
444 return 0;
445}
446
447static int snd_us16x08_comp_put(struct snd_kcontrol *kcontrol,
448 struct snd_ctl_elem_value *ucontrol)
449{
450 struct usb_mixer_elem_info *elem = kcontrol->private_data;
451 struct snd_usb_audio *chip = elem->head.mixer->chip;
452 struct snd_us16x08_comp_store *store =
453 ((struct snd_us16x08_comp_store *) elem->private_data);
454 int index = ucontrol->id.index;
455 char buf[sizeof(comp_msg)];
456 int val_idx, val;
457 int err = 0;
458
459 /* prepare compressor URB message from template */
460 memcpy(buf, comp_msg, sizeof(comp_msg));
461
462 /* new control value incl. bias*/
463 val_idx = elem->head.id - SND_US16X08_ID_COMP_BASE;
464
465 val = ucontrol->value.integer.value[0];
466
467 /* sanity check */
468 if (val < SND_US16X08_KCMIN(kcontrol)
469 || val > SND_US16X08_KCMAX(kcontrol))
470 return -EINVAL;
471
472 store->val[val_idx][index] = ucontrol->value.integer.value[0];
473
474 /* place comp values in message buffer watch bias! */
475 buf[8] = store->val[
476 COMP_STORE_IDX(SND_US16X08_ID_COMP_THRESHOLD)][index]
477 - SND_US16X08_COMP_THRESHOLD_BIAS;
478 buf[11] = ratio_map[store->val[
479 COMP_STORE_IDX(SND_US16X08_ID_COMP_RATIO)][index]];
480 buf[14] = store->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_ATTACK)][index]
481 + SND_US16X08_COMP_ATTACK_BIAS;
482 buf[17] = store->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_RELEASE)][index]
483 + SND_US16X08_COMP_RELEASE_BIAS;
484 buf[20] = store->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_GAIN)][index];
485 buf[26] = store->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_SWITCH)][index];
486
487 /* place channel selector in message buffer */
488 buf[5] = index + 1;
489
490 err = snd_us16x08_send_urb(chip, buf, sizeof(comp_msg));
491
492 if (err > 0) {
493 elem->cached |= 1 << index;
494 elem->cache_val[index] = val;
495 } else {
496 usb_audio_dbg(chip, "Failed to set compressor, err:%d\n", err);
497 }
498
499 return 1;
500}
501
502static int snd_us16x08_eqswitch_get(struct snd_kcontrol *kcontrol,
503 struct snd_ctl_elem_value *ucontrol)
504{
505 int val = 0;
506 struct usb_mixer_elem_info *elem = kcontrol->private_data;
507 struct snd_us16x08_eq_store *store =
508 ((struct snd_us16x08_eq_store *) elem->private_data);
509 int index = ucontrol->id.index;
510
511 /* get low switch from cache is enough, cause all bands are together */
512 val = store->val[EQ_STORE_BAND_IDX(elem->head.id)]
513 [EQ_STORE_PARAM_IDX(elem->head.id)][index];
514 ucontrol->value.integer.value[0] = val;
515
516 return 0;
517}
518
519static int snd_us16x08_eqswitch_put(struct snd_kcontrol *kcontrol,
520 struct snd_ctl_elem_value *ucontrol)
521{
522 struct usb_mixer_elem_info *elem = kcontrol->private_data;
523 struct snd_usb_audio *chip = elem->head.mixer->chip;
524 struct snd_us16x08_eq_store *store =
525 ((struct snd_us16x08_eq_store *) elem->private_data);
526 int index = ucontrol->id.index;
527
528 char buf[sizeof(eqs_msq)];
529 int val, err = 0;
530 int b_idx;
531
532 /* new control value incl. bias*/
533 val = ucontrol->value.integer.value[0] + SND_US16X08_KCBIAS(kcontrol);
534
535 /* prepare URB message from EQ template */
536 memcpy(buf, eqs_msq, sizeof(eqs_msq));
537
538 /* place channel index in URB message */
539 buf[5] = index + 1;
540 for (b_idx = 0; b_idx < SND_US16X08_ID_EQ_BAND_COUNT; b_idx++) {
541 /* all four EQ bands have to be enabled/disabled in once */
542 buf[20] = val;
543 buf[17] = store->val[b_idx][2][index];
544 buf[14] = store->val[b_idx][1][index];
545 buf[11] = store->val[b_idx][0][index];
546 buf[8] = b_idx + 1;
547 err = snd_us16x08_send_urb(chip, buf, sizeof(eqs_msq));
548 if (err < 0)
549 break;
550 store->val[b_idx][3][index] = val;
551 msleep(15);
552 }
553
554 if (err > 0) {
555 elem->cached |= 1 << index;
556 elem->cache_val[index] = val;
557 } else {
558 usb_audio_dbg(chip, "Failed to set eq switch, err:%d\n", err);
559 }
560
561 return 1;
562}
563
564static int snd_us16x08_eq_get(struct snd_kcontrol *kcontrol,
565 struct snd_ctl_elem_value *ucontrol)
566{
567 int val = 0;
568 struct usb_mixer_elem_info *elem = kcontrol->private_data;
569 struct snd_us16x08_eq_store *store =
570 ((struct snd_us16x08_eq_store *) elem->private_data);
571 int index = ucontrol->id.index;
572 int b_idx = EQ_STORE_BAND_IDX(elem->head.id) - 1;
573 int p_idx = EQ_STORE_PARAM_IDX(elem->head.id);
574
575 val = store->val[b_idx][p_idx][index];
576
577 ucontrol->value.integer.value[0] = val;
578
579 return 0;
580}
581
582static int snd_us16x08_eq_put(struct snd_kcontrol *kcontrol,
583 struct snd_ctl_elem_value *ucontrol)
584{
585 struct usb_mixer_elem_info *elem = kcontrol->private_data;
586 struct snd_usb_audio *chip = elem->head.mixer->chip;
587 struct snd_us16x08_eq_store *store =
588 ((struct snd_us16x08_eq_store *) elem->private_data);
589 int index = ucontrol->id.index;
590 char buf[sizeof(eqs_msq)];
591 int val, err = 0;
592 int b_idx = EQ_STORE_BAND_IDX(elem->head.id) - 1;
593 int p_idx = EQ_STORE_PARAM_IDX(elem->head.id);
594
595 /* copy URB buffer from EQ template */
596 memcpy(buf, eqs_msq, sizeof(eqs_msq));
597
598 val = ucontrol->value.integer.value[0];
599
600 /* sanity check */
601 if (val < SND_US16X08_KCMIN(kcontrol)
602 || val > SND_US16X08_KCMAX(kcontrol))
603 return -EINVAL;
604
605 store->val[b_idx][p_idx][index] = val;
606 buf[20] = store->val[b_idx][3][index];
607 buf[17] = store->val[b_idx][2][index];
608 buf[14] = store->val[b_idx][1][index];
609 buf[11] = store->val[b_idx][0][index];
610
611 /* place channel index in URB buffer */
612 buf[5] = index + 1;
613
614 /* place EQ band in URB buffer */
615 buf[8] = b_idx + 1;
616
617 err = snd_us16x08_send_urb(chip, buf, sizeof(eqs_msq));
618
619 if (err > 0) {
620 /* store new value in EQ band cache */
621 elem->cached |= 1 << index;
622 elem->cache_val[index] = val;
623 } else {
624 usb_audio_dbg(chip, "Failed to set eq param, err:%d\n", err);
625 }
626
627 return 1;
628}
629
630static int snd_us16x08_meter_info(struct snd_kcontrol *kcontrol,
631 struct snd_ctl_elem_info *uinfo)
632{
633 uinfo->count = 1;
634 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
635 uinfo->value.integer.max = 0x7FFF;
636 uinfo->value.integer.min = 0;
637
638 return 0;
639}
640
641/* calculate compressor index for reduction level request */
642static int snd_get_meter_comp_index(struct snd_us16x08_meter_store *store)
643{
644 int ret;
645
646 /* any channel active */
647 if (store->comp_active_index) {
648 /* check for stereo link */
649 if (store->comp_active_index & 0x20) {
650 /* reset comp_index to left channel*/
651 if (store->comp_index -
652 store->comp_active_index > 1)
653 store->comp_index =
654 store->comp_active_index;
655
656 ret = store->comp_index++ & 0x1F;
657 } else {
658 /* no stereo link */
659 ret = store->comp_active_index;
660 }
661 } else {
662 /* skip channels with no compressor active */
663 while (!store->comp_store->val[
664 COMP_STORE_IDX(SND_US16X08_ID_COMP_SWITCH)]
665 [store->comp_index - 1]
666 && store->comp_index <= SND_US16X08_MAX_CHANNELS) {
667 store->comp_index++;
668 }
669 ret = store->comp_index++;
670 if (store->comp_index > SND_US16X08_MAX_CHANNELS)
671 store->comp_index = 1;
672 }
673 return ret;
674}
675
676/* retrieve the meter level values from URB message */
677static void get_meter_levels_from_urb(int s,
678 struct snd_us16x08_meter_store *store,
679 u8 *meter_urb)
680{
681 int val = MUC2(meter_urb, s) + (MUC3(meter_urb, s) << 8);
682
683 if (MUA0(meter_urb, s) == 0x61 && MUA1(meter_urb, s) == 0x02 &&
684 MUA2(meter_urb, s) == 0x04 && MUB0(meter_urb, s) == 0x62) {
685 if (MUC0(meter_urb, s) == 0x72)
686 store->meter_level[MUB2(meter_urb, s) - 1] = val;
687 if (MUC0(meter_urb, s) == 0xb2)
688 store->comp_level[MUB2(meter_urb, s) - 1] = val;
689 }
690 if (MUA0(meter_urb, s) == 0x61 && MUA1(meter_urb, s) == 0x02 &&
691 MUA2(meter_urb, s) == 0x02 && MUB0(meter_urb, s) == 0x62)
692 store->master_level[MUB2(meter_urb, s) - 1] = val;
693}
694
695/* Function to retrieve current meter values from the device.
696 *
697 * The device needs to be polled for meter values with an initial
698 * requests. It will return with a sequence of different meter value
699 * packages. The first request (case 0:) initiate this meter response sequence.
700 * After the third response, an additional request can be placed,
701 * to retrieve compressor reduction level value for given channel. This round
702 * trip channel selector will skip all inactive compressors.
703 * A mixer can interrupt this round-trip by selecting one ore two (stereo-link)
704 * specific channels.
705 */
706static int snd_us16x08_meter_get(struct snd_kcontrol *kcontrol,
707 struct snd_ctl_elem_value *ucontrol)
708{
709 int i, set;
710 struct usb_mixer_elem_info *elem = kcontrol->private_data;
711 struct snd_usb_audio *chip = elem->head.mixer->chip;
712 struct snd_us16x08_meter_store *store = elem->private_data;
713 u8 meter_urb[64];
714 char tmp[max(sizeof(mix_init_msg1), sizeof(mix_init_msg2))];
715
716 if (elem) {
717 store = (struct snd_us16x08_meter_store *) elem->private_data;
718 chip = elem->head.mixer->chip;
719 } else
720 return 0;
721
722 switch (kcontrol->private_value) {
723 case 0:
724 memcpy(tmp, mix_init_msg1, sizeof(mix_init_msg1));
725 snd_us16x08_send_urb(chip, tmp, 4);
726 snd_us16x08_recv_urb(chip, meter_urb,
727 sizeof(meter_urb));
728 kcontrol->private_value++;
729 break;
730 case 1:
731 snd_us16x08_recv_urb(chip, meter_urb,
732 sizeof(meter_urb));
733 kcontrol->private_value++;
734 break;
735 case 2:
736 snd_us16x08_recv_urb(chip, meter_urb,
737 sizeof(meter_urb));
738 kcontrol->private_value++;
739 break;
740 case 3:
741 memcpy(tmp, mix_init_msg2, sizeof(mix_init_msg2));
742 tmp[2] = snd_get_meter_comp_index(store);
743 snd_us16x08_send_urb(chip, tmp, 10);
744 snd_us16x08_recv_urb(chip, meter_urb,
745 sizeof(meter_urb));
746 kcontrol->private_value = 0;
747 break;
748 }
749
750 for (set = 0; set < 6; set++)
751 get_meter_levels_from_urb(set, store, meter_urb);
752
753 for (i = 0; i < SND_US16X08_MAX_CHANNELS; i++) {
754 ucontrol->value.integer.value[i] =
755 store ? store->meter_level[i] : 0;
756 }
757
758 ucontrol->value.integer.value[i++] = store ? store->master_level[0] : 0;
759 ucontrol->value.integer.value[i++] = store ? store->master_level[1] : 0;
760
761 for (i = 2; i < SND_US16X08_MAX_CHANNELS + 2; i++)
762 ucontrol->value.integer.value[i + SND_US16X08_MAX_CHANNELS] =
763 store ? store->comp_level[i - 2] : 0;
764
765 return 1;
766}
767
768static int snd_us16x08_meter_put(struct snd_kcontrol *kcontrol,
769 struct snd_ctl_elem_value *ucontrol)
770{
771 struct usb_mixer_elem_info *elem = kcontrol->private_data;
772 struct snd_us16x08_meter_store *store = elem->private_data;
773 int val;
774
775 val = ucontrol->value.integer.value[0];
776
777 /* sanity check */
778 if (val < 0 || val >= SND_US16X08_MAX_CHANNELS)
779 return -EINVAL;
780
781 store->comp_active_index = val;
782 store->comp_index = val;
783
784 return 1;
785}
786
787static struct snd_kcontrol_new snd_us16x08_ch_boolean_ctl = {
788 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
789 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
790 .count = 16,
791 .info = snd_us16x08_switch_info,
792 .get = snd_us16x08_channel_get,
793 .put = snd_us16x08_channel_put,
794 .private_value = SND_US16X08_KCSET(SND_US16X08_NO_BIAS, 1, 0, 1)
795};
796
797static struct snd_kcontrol_new snd_us16x08_ch_int_ctl = {
798 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
799 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
800 .count = 16,
801 .info = snd_us16x08_mix_info,
802 .get = snd_us16x08_channel_get,
803 .put = snd_us16x08_channel_put,
804 .private_value = SND_US16X08_KCSET(SND_US16X08_FADER_BIAS, 1, 0, 133)
805};
806
807static struct snd_kcontrol_new snd_us16x08_pan_int_ctl = {
808 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
809 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
810 .count = 16,
811 .info = snd_us16x08_mix_info,
812 .get = snd_us16x08_channel_get,
813 .put = snd_us16x08_channel_put,
814 .private_value = SND_US16X08_KCSET(SND_US16X08_FADER_BIAS, 1, 0, 255)
815};
816
817static struct snd_kcontrol_new snd_us16x08_master_ctl = {
818 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
819 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
820 .count = 1,
821 .info = snd_us16x08_master_info,
822 .get = snd_us16x08_master_get,
823 .put = snd_us16x08_master_put,
824 .private_value = SND_US16X08_KCSET(SND_US16X08_FADER_BIAS, 1, 0, 133)
825};
826
827static struct snd_kcontrol_new snd_us16x08_route_ctl = {
828 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
829 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
830 .count = 8,
831 .info = snd_us16x08_route_info,
832 .get = snd_us16x08_route_get,
833 .put = snd_us16x08_route_put,
834 .private_value = SND_US16X08_KCSET(SND_US16X08_NO_BIAS, 1, 0, 9)
835};
836
837static struct snd_kcontrol_new snd_us16x08_bus_ctl = {
838 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
839 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
840 .count = 1,
841 .info = snd_us16x08_switch_info,
842 .get = snd_us16x08_bus_get,
843 .put = snd_us16x08_bus_put,
844 .private_value = SND_US16X08_KCSET(SND_US16X08_NO_BIAS, 1, 0, 1)
845};
846
847static struct snd_kcontrol_new snd_us16x08_compswitch_ctl = {
848 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
849 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
850 .count = 16,
851 .info = snd_us16x08_switch_info,
852 .get = snd_us16x08_comp_get,
853 .put = snd_us16x08_comp_put,
854 .private_value = SND_US16X08_KCSET(SND_US16X08_NO_BIAS, 1, 0, 1)
855};
856
857static struct snd_kcontrol_new snd_us16x08_comp_threshold_ctl = {
858 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
859 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
860 .count = 16,
861 .info = snd_us16x08_mix_info,
862 .get = snd_us16x08_comp_get,
863 .put = snd_us16x08_comp_put,
864 .private_value = SND_US16X08_KCSET(SND_US16X08_COMP_THRESHOLD_BIAS, 1,
865 0, 0x20)
866};
867
868static struct snd_kcontrol_new snd_us16x08_comp_ratio_ctl = {
869 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
870 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
871 .count = 16,
872 .info = snd_us16x08_mix_info,
873 .get = snd_us16x08_comp_get,
874 .put = snd_us16x08_comp_put,
875 .private_value = SND_US16X08_KCSET(SND_US16X08_NO_BIAS, 1, 0,
876 sizeof(ratio_map) - 1), /*max*/
877};
878
879static struct snd_kcontrol_new snd_us16x08_comp_gain_ctl = {
880 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
881 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
882 .count = 16,
883 .info = snd_us16x08_mix_info,
884 .get = snd_us16x08_comp_get,
885 .put = snd_us16x08_comp_put,
886 .private_value = SND_US16X08_KCSET(SND_US16X08_NO_BIAS, 1, 0, 0x14)
887};
888
889static struct snd_kcontrol_new snd_us16x08_comp_attack_ctl = {
890 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
891 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
892 .count = 16,
893 .info = snd_us16x08_mix_info,
894 .get = snd_us16x08_comp_get,
895 .put = snd_us16x08_comp_put,
896 .private_value =
897 SND_US16X08_KCSET(SND_US16X08_COMP_ATTACK_BIAS, 1, 0, 0xc6),
898};
899
900static struct snd_kcontrol_new snd_us16x08_comp_release_ctl = {
901 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
902 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
903 .count = 16,
904 .info = snd_us16x08_mix_info,
905 .get = snd_us16x08_comp_get,
906 .put = snd_us16x08_comp_put,
907 .private_value =
908 SND_US16X08_KCSET(SND_US16X08_COMP_RELEASE_BIAS, 1, 0, 0x63),
909};
910
911static struct snd_kcontrol_new snd_us16x08_eq_gain_ctl = {
912 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
913 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
914 .count = 16,
915 .info = snd_us16x08_mix_info,
916 .get = snd_us16x08_eq_get,
917 .put = snd_us16x08_eq_put,
918 .private_value = SND_US16X08_KCSET(SND_US16X08_NO_BIAS, 1, 0, 24),
919};
920
921static struct snd_kcontrol_new snd_us16x08_eq_low_freq_ctl = {
922 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
923 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
924 .count = 16,
925 .info = snd_us16x08_mix_info,
926 .get = snd_us16x08_eq_get,
927 .put = snd_us16x08_eq_put,
928 .private_value = SND_US16X08_KCSET(SND_US16X08_NO_BIAS, 1, 0, 0x1F),
929};
930
931static struct snd_kcontrol_new snd_us16x08_eq_mid_freq_ctl = {
932 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
933 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
934 .count = 16,
935 .info = snd_us16x08_mix_info,
936 .get = snd_us16x08_eq_get,
937 .put = snd_us16x08_eq_put,
938 .private_value = SND_US16X08_KCSET(SND_US16X08_NO_BIAS, 1, 0, 0x3F)
939};
940
941static struct snd_kcontrol_new snd_us16x08_eq_mid_width_ctl = {
942 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
943 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
944 .count = 16,
945 .info = snd_us16x08_mix_info,
946 .get = snd_us16x08_eq_get,
947 .put = snd_us16x08_eq_put,
948 .private_value = SND_US16X08_KCSET(SND_US16X08_NO_BIAS, 1, 0, 0x06)
949};
950
951static struct snd_kcontrol_new snd_us16x08_eq_high_freq_ctl = {
952 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
953 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
954 .count = 16,
955 .info = snd_us16x08_mix_info,
956 .get = snd_us16x08_eq_get,
957 .put = snd_us16x08_eq_put,
958 .private_value =
959 SND_US16X08_KCSET(SND_US16X08_EQ_HIGHFREQ_BIAS, 1, 0, 0x1F)
960};
961
962static struct snd_kcontrol_new snd_us16x08_eq_switch_ctl = {
963 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
964 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
965 .count = 16,
966 .info = snd_us16x08_switch_info,
967 .get = snd_us16x08_eqswitch_get,
968 .put = snd_us16x08_eqswitch_put,
969 .private_value = SND_US16X08_KCSET(SND_US16X08_NO_BIAS, 1, 0, 1)
970};
971
972static struct snd_kcontrol_new snd_us16x08_meter_ctl = {
973 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
974 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
975 .count = 1,
976 .info = snd_us16x08_meter_info,
977 .get = snd_us16x08_meter_get,
978 .put = snd_us16x08_meter_put
979};
980
981/* control store preparation */
982
983/* setup compressor store and assign default value */
984static struct snd_us16x08_comp_store *snd_us16x08_create_comp_store(void)
985{
986 int i = 0;
987 struct snd_us16x08_comp_store *tmp =
988 kmalloc(sizeof(struct snd_us16x08_comp_store), GFP_KERNEL);
989
990 if (tmp == NULL)
991 return NULL;
992
993 for (i = 0; i < SND_US16X08_MAX_CHANNELS; i++) {
994 tmp->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_THRESHOLD)][i]
995 = 0x20;
996 tmp->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_RATIO)][i] = 0x00;
997 tmp->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_GAIN)][i] = 0x00;
998 tmp->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_SWITCH)][i] = 0x00;
999 tmp->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_ATTACK)][i] = 0x00;
1000 tmp->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_RELEASE)][i] = 0x00;
1001 }
1002 return tmp;
1003}
1004
1005/* setup EQ store and assign default values */
1006static struct snd_us16x08_eq_store *snd_us16x08_create_eq_store(void)
1007{
1008 int i, b_idx;
1009 struct snd_us16x08_eq_store *tmp =
1010 kmalloc(sizeof(struct snd_us16x08_eq_store), GFP_KERNEL);
1011
1012 if (tmp == NULL)
1013 return NULL;
1014
1015 for (i = 0; i < SND_US16X08_MAX_CHANNELS; i++) {
1016 for (b_idx = 0; b_idx < SND_US16X08_ID_EQ_BAND_COUNT; b_idx++) {
1017 tmp->val[b_idx][0][i] = 0x0c;
1018 tmp->val[b_idx][3][i] = 0x00;
1019 switch (b_idx) {
1020 case 0: /* EQ Low */
1021 tmp->val[b_idx][1][i] = 0x05;
1022 tmp->val[b_idx][2][i] = 0xff;
1023 break;
1024 case 1: /* EQ Mid low */
1025 tmp->val[b_idx][1][i] = 0x0e;
1026 tmp->val[b_idx][2][i] = 0x02;
1027 break;
1028 case 2: /* EQ Mid High */
1029 tmp->val[b_idx][1][i] = 0x1b;
1030 tmp->val[b_idx][2][i] = 0x02;
1031 break;
1032 case 3: /* EQ High */
1033 tmp->val[b_idx][1][i] = 0x2f
1034 - SND_US16X08_EQ_HIGHFREQ_BIAS;
1035 tmp->val[b_idx][2][i] = 0xff;
1036 break;
1037 }
1038 }
1039 }
1040 return tmp;
1041}
1042
1043struct snd_us16x08_meter_store *snd_us16x08_create_meter_store(void)
1044{
1045 struct snd_us16x08_meter_store *tmp =
1046 kzalloc(sizeof(struct snd_us16x08_meter_store), GFP_KERNEL);
1047
1048 if (!tmp)
1049 return NULL;
1050 tmp->comp_index = 1;
1051 tmp->comp_active_index = 0;
1052 return tmp;
1053
1054}
1055
1056static int add_new_ctl(struct usb_mixer_interface *mixer,
1057 const struct snd_kcontrol_new *ncontrol,
1058 int index, int val_type, int channels,
1059 const char *name, const void *opt,
1060 void (*freeer)(struct snd_kcontrol *kctl),
1061 struct usb_mixer_elem_info **elem_ret)
1062{
1063 struct snd_kcontrol *kctl;
1064 struct usb_mixer_elem_info *elem;
1065 int err;
1066
1067 usb_audio_dbg(mixer->chip, "us16x08 add mixer %s\n", name);
1068
1069 elem = kzalloc(sizeof(*elem), GFP_KERNEL);
1070 if (!elem)
1071 return -ENOMEM;
1072
1073 elem->head.mixer = mixer;
1074 elem->head.resume = NULL;
1075 elem->control = 0;
1076 elem->idx_off = 0;
1077 elem->head.id = index;
1078 elem->val_type = val_type;
1079 elem->channels = channels;
1080 elem->private_data = (void *) opt;
1081
1082 kctl = snd_ctl_new1(ncontrol, elem);
1083 if (!kctl) {
1084 kfree(elem);
1085 return -ENOMEM;
1086 }
1087
1088 kctl->private_free = freeer;
1089
1090 strlcpy(kctl->id.name, name, sizeof(kctl->id.name));
1091
1092 err = snd_usb_mixer_add_control(&elem->head, kctl);
1093 if (err < 0)
1094 return err;
1095
1096 if (elem_ret)
1097 *elem_ret = elem;
1098
1099 return 0;
1100}
1101
1102static struct snd_us16x08_control_params control_params;
1103
1104/* table of EQ controls */
1105static struct snd_us16x08_control_params eq_controls[] = {
1106 { /* EQ switch */
1107 .kcontrol_new = &snd_us16x08_eq_switch_ctl,
1108 .control_id = SND_US16X08_ID_EQENABLE,
1109 .type = USB_MIXER_BOOLEAN,
1110 .num_channels = 16,
1111 .name = "EQ Switch",
1112 .freeer = snd_usb_mixer_elem_free
1113 },
1114 { /* EQ low gain */
1115 .kcontrol_new = &snd_us16x08_eq_gain_ctl,
1116 .control_id = SND_US16X08_ID_EQLOWLEVEL,
1117 .type = USB_MIXER_U8,
1118 .num_channels = 16,
1119 .name = "EQ Low Volume",
1120 .freeer = snd_usb_mixer_elem_free
1121 },
1122 { /* EQ low freq */
1123 .kcontrol_new = &snd_us16x08_eq_low_freq_ctl,
1124 .control_id = SND_US16X08_ID_EQLOWFREQ,
1125 .type = USB_MIXER_U8,
1126 .num_channels = 16,
1127 .name = "EQ Low Frequence",
1128 .freeer = NULL
1129 },
1130 { /* EQ mid low gain */
1131 .kcontrol_new = &snd_us16x08_eq_gain_ctl,
1132 .control_id = SND_US16X08_ID_EQLOWMIDLEVEL,
1133 .type = USB_MIXER_U8,
1134 .num_channels = 16,
1135 .name = "EQ MidLow Volume",
1136 .freeer = snd_usb_mixer_elem_free
1137 },
1138 { /* EQ mid low freq */
1139 .kcontrol_new = &snd_us16x08_eq_mid_freq_ctl,
1140 .control_id = SND_US16X08_ID_EQLOWMIDFREQ,
1141 .type = USB_MIXER_U8,
1142 .num_channels = 16,
1143 .name = "EQ MidLow Frequence",
1144 .freeer = NULL
1145 },
1146 { /* EQ mid low Q */
1147 .kcontrol_new = &snd_us16x08_eq_mid_width_ctl,
1148 .control_id = SND_US16X08_ID_EQLOWMIDWIDTH,
1149 .type = USB_MIXER_U8,
1150 .num_channels = 16,
1151 .name = "EQ MidQLow Q",
1152 .freeer = NULL
1153 },
1154 { /* EQ mid high gain */
1155 .kcontrol_new = &snd_us16x08_eq_gain_ctl,
1156 .control_id = SND_US16X08_ID_EQHIGHMIDLEVEL,
1157 .type = USB_MIXER_U8,
1158 .num_channels = 16,
1159 .name = "EQ MidHigh Volume",
1160 .freeer = snd_usb_mixer_elem_free
1161 },
1162 { /* EQ mid high freq */
1163 .kcontrol_new = &snd_us16x08_eq_mid_freq_ctl,
1164 .control_id = SND_US16X08_ID_EQHIGHMIDFREQ,
1165 .type = USB_MIXER_U8,
1166 .num_channels = 16,
1167 .name = "EQ MidHigh Frequence",
1168 .freeer = NULL
1169 },
1170 { /* EQ mid high Q */
1171 .kcontrol_new = &snd_us16x08_eq_mid_width_ctl,
1172 .control_id = SND_US16X08_ID_EQHIGHMIDWIDTH,
1173 .type = USB_MIXER_U8,
1174 .num_channels = 16,
1175 .name = "EQ MidHigh Q",
1176 .freeer = NULL
1177 },
1178 { /* EQ high gain */
1179 .kcontrol_new = &snd_us16x08_eq_gain_ctl,
1180 .control_id = SND_US16X08_ID_EQHIGHLEVEL,
1181 .type = USB_MIXER_U8,
1182 .num_channels = 16,
1183 .name = "EQ High Volume",
1184 .freeer = snd_usb_mixer_elem_free
1185 },
1186 { /* EQ low freq */
1187 .kcontrol_new = &snd_us16x08_eq_high_freq_ctl,
1188 .control_id = SND_US16X08_ID_EQHIGHFREQ,
1189 .type = USB_MIXER_U8,
1190 .num_channels = 16,
1191 .name = "EQ High Frequence",
1192 .freeer = NULL
1193 },
1194};
1195
1196/* table of compressor controls */
1197static struct snd_us16x08_control_params comp_controls[] = {
1198 { /* Comp enable */
1199 .kcontrol_new = &snd_us16x08_compswitch_ctl,
1200 .control_id = SND_US16X08_ID_COMP_SWITCH,
1201 .type = USB_MIXER_BOOLEAN,
1202 .num_channels = 16,
1203 .name = "Compressor Switch",
1204 .freeer = snd_usb_mixer_elem_free
1205 },
1206 { /* Comp threshold */
1207 .kcontrol_new = &snd_us16x08_comp_threshold_ctl,
1208 .control_id = SND_US16X08_ID_COMP_THRESHOLD,
1209 .type = USB_MIXER_U8,
1210 .num_channels = 16,
1211 .name = "Compressor Threshold Volume",
1212 .freeer = NULL
1213 },
1214 { /* Comp ratio */
1215 .kcontrol_new = &snd_us16x08_comp_ratio_ctl,
1216 .control_id = SND_US16X08_ID_COMP_RATIO,
1217 .type = USB_MIXER_U8,
1218 .num_channels = 16,
1219 .name = "Compressor Ratio",
1220 .freeer = NULL
1221 },
1222 { /* Comp attack */
1223 .kcontrol_new = &snd_us16x08_comp_attack_ctl,
1224 .control_id = SND_US16X08_ID_COMP_ATTACK,
1225 .type = USB_MIXER_U8,
1226 .num_channels = 16,
1227 .name = "Compressor Attack",
1228 .freeer = NULL
1229 },
1230 { /* Comp release */
1231 .kcontrol_new = &snd_us16x08_comp_release_ctl,
1232 .control_id = SND_US16X08_ID_COMP_RELEASE,
1233 .type = USB_MIXER_U8,
1234 .num_channels = 16,
1235 .name = "Compressor Release",
1236 .freeer = NULL
1237 },
1238 { /* Comp gain */
1239 .kcontrol_new = &snd_us16x08_comp_gain_ctl,
1240 .control_id = SND_US16X08_ID_COMP_GAIN,
1241 .type = USB_MIXER_U8,
1242 .num_channels = 16,
1243 .name = "Compressor Volume",
1244 .freeer = NULL
1245 },
1246};
1247
1248/* table of channel controls */
1249static struct snd_us16x08_control_params channel_controls[] = {
1250 { /* Phase */
1251 .kcontrol_new = &snd_us16x08_ch_boolean_ctl,
1252 .control_id = SND_US16X08_ID_PHASE,
1253 .type = USB_MIXER_BOOLEAN,
1254 .num_channels = 16,
1255 .name = "Phase Switch",
1256 .freeer = snd_usb_mixer_elem_free,
1257 .default_val = 0
1258 },
1259 { /* Fader */
1260 .kcontrol_new = &snd_us16x08_ch_int_ctl,
1261 .control_id = SND_US16X08_ID_FADER,
1262 .type = USB_MIXER_U8,
1263 .num_channels = 16,
1264 .name = "Line Volume",
1265 .freeer = NULL,
1266 .default_val = 127
1267 },
1268 { /* Mute */
1269 .kcontrol_new = &snd_us16x08_ch_boolean_ctl,
1270 .control_id = SND_US16X08_ID_MUTE,
1271 .type = USB_MIXER_BOOLEAN,
1272 .num_channels = 16,
1273 .name = "Mute Switch",
1274 .freeer = NULL,
1275 .default_val = 0
1276 },
1277 { /* Pan */
1278 .kcontrol_new = &snd_us16x08_pan_int_ctl,
1279 .control_id = SND_US16X08_ID_PAN,
1280 .type = USB_MIXER_U16,
1281 .num_channels = 16,
1282 .name = "Pan Left-Right Volume",
1283 .freeer = NULL,
1284 .default_val = 127
1285 },
1286};
1287
1288/* table of master controls */
1289static struct snd_us16x08_control_params master_controls[] = {
1290 { /* Master */
1291 .kcontrol_new = &snd_us16x08_master_ctl,
1292 .control_id = SND_US16X08_ID_FADER,
1293 .type = USB_MIXER_U8,
1294 .num_channels = 16,
1295 .name = "Master Volume",
1296 .freeer = NULL,
1297 .default_val = 127
1298 },
1299 { /* Bypass */
1300 .kcontrol_new = &snd_us16x08_bus_ctl,
1301 .control_id = SND_US16X08_ID_BYPASS,
1302 .type = USB_MIXER_BOOLEAN,
1303 .num_channels = 16,
1304 .name = "DSP Bypass Switch",
1305 .freeer = NULL,
1306 .default_val = 0
1307 },
1308 { /* Buss out */
1309 .kcontrol_new = &snd_us16x08_bus_ctl,
1310 .control_id = SND_US16X08_ID_BUSS_OUT,
1311 .type = USB_MIXER_BOOLEAN,
1312 .num_channels = 16,
1313 .name = "Buss Out Switch",
1314 .freeer = NULL,
1315 .default_val = 0
1316 },
1317 { /* Master mute */
1318 .kcontrol_new = &snd_us16x08_bus_ctl,
1319 .control_id = SND_US16X08_ID_MUTE,
1320 .type = USB_MIXER_BOOLEAN,
1321 .num_channels = 16,
1322 .name = "Master Mute Switch",
1323 .freeer = NULL,
1324 .default_val = 0
1325 },
1326
1327};
1328
1329int snd_us16x08_controls_create(struct usb_mixer_interface *mixer)
1330{
1331 int i, j;
1332 int err;
1333 struct usb_mixer_elem_info *elem;
1334 struct snd_us16x08_comp_store *comp_store;
1335 struct snd_us16x08_meter_store *meter_store;
1336 struct snd_us16x08_eq_store *eq_store;
1337
1338 /* just check for non-MIDI interface */
1339 if (mixer->hostif->desc.bInterfaceNumber == 3) {
1340
1341 /* create compressor mixer elements */
1342 comp_store = snd_us16x08_create_comp_store();
1343 if (comp_store == NULL)
1344 return -ENOMEM;
1345
1346 /* create eq store */
1347 eq_store = snd_us16x08_create_eq_store();
1348 if (eq_store == NULL) {
1349 kfree(comp_store);
1350 return -ENOMEM;
1351 }
1352
1353 /* create meters store */
1354 meter_store = snd_us16x08_create_meter_store();
1355 if (meter_store == NULL) {
1356 kfree(comp_store);
1357 kfree(eq_store);
1358 return -ENOMEM;
1359 }
1360
1361 /* add routing control */
1362 err = add_new_ctl(mixer, &snd_us16x08_route_ctl,
1363 SND_US16X08_ID_ROUTE, USB_MIXER_U8, 8, "Line Out Route",
1364 NULL, NULL, &elem);
1365 if (err < 0) {
1366 usb_audio_dbg(mixer->chip,
1367 "Failed to create route control, err:%d\n",
1368 err);
1369 return err;
1370 }
1371 for (i = 0; i < 8; i++)
1372 elem->cache_val[i] = i < 2 ? i : i + 2;
1373 elem->cached = 0xff;
1374
1375 /* add master controls */
1376 for (i = 0;
1377 i < sizeof(master_controls)
1378 / sizeof(control_params);
1379 i++) {
1380
1381 err = add_new_ctl(mixer,
1382 master_controls[i].kcontrol_new,
1383 master_controls[i].control_id,
1384 master_controls[i].type,
1385 master_controls[i].num_channels,
1386 master_controls[i].name,
1387 comp_store,
1388 master_controls[i].freeer, &elem);
1389 if (err < 0)
1390 return err;
1391 elem->cache_val[0] = master_controls[i].default_val;
1392 elem->cached = 1;
1393 }
1394
1395 /* add channel controls */
1396 for (i = 0;
1397 i < sizeof(channel_controls)
1398 / sizeof(control_params);
1399 i++) {
1400
1401 err = add_new_ctl(mixer,
1402 channel_controls[i].kcontrol_new,
1403 channel_controls[i].control_id,
1404 channel_controls[i].type,
1405 channel_controls[i].num_channels,
1406 channel_controls[i].name,
1407 comp_store,
1408 channel_controls[i].freeer, &elem);
1409 if (err < 0)
1410 return err;
1411 for (j = 0; j < SND_US16X08_MAX_CHANNELS; j++) {
1412 elem->cache_val[j] =
1413 channel_controls[i].default_val;
1414 }
1415 elem->cached = 0xffff;
1416 }
1417
1418 /* add EQ controls */
1419 for (i = 0; i < sizeof(eq_controls) /
1420 sizeof(control_params); i++) {
1421
1422 err = add_new_ctl(mixer,
1423 eq_controls[i].kcontrol_new,
1424 eq_controls[i].control_id,
1425 eq_controls[i].type,
1426 eq_controls[i].num_channels,
1427 eq_controls[i].name,
1428 eq_store,
1429 eq_controls[i].freeer, NULL);
1430 if (err < 0)
1431 return err;
1432 }
1433
1434 /* add compressor controls */
1435 for (i = 0;
1436 i < sizeof(comp_controls)
1437 / sizeof(control_params);
1438 i++) {
1439
1440 err = add_new_ctl(mixer,
1441 comp_controls[i].kcontrol_new,
1442 comp_controls[i].control_id,
1443 comp_controls[i].type,
1444 comp_controls[i].num_channels,
1445 comp_controls[i].name,
1446 comp_store,
1447 comp_controls[i].freeer, NULL);
1448 if (err < 0)
1449 return err;
1450 }
1451
1452 /* meter function 'get' must access to compressor store
1453 * so place a reference here
1454 */
1455 meter_store->comp_store = comp_store;
1456 err = add_new_ctl(mixer, &snd_us16x08_meter_ctl,
1457 SND_US16X08_ID_METER, USB_MIXER_U16, 0, "Level Meter",
1458 (void *) meter_store, snd_usb_mixer_elem_free, NULL);
1459 if (err < 0)
1460 return err;
1461 }
1462
1463 return 0;
1464}
1465
diff --git a/sound/usb/mixer_us16x08.h b/sound/usb/mixer_us16x08.h
new file mode 100644
index 000000000000..64f89b5eca2d
--- /dev/null
+++ b/sound/usb/mixer_us16x08.h
@@ -0,0 +1,122 @@
1#ifndef __USB_MIXER_US16X08_H
2#define __USB_MIXER_US16X08_H
3
4#define SND_US16X08_MAX_CHANNELS 16
5
6/* define some bias, cause some alsa-mixers wont work with
7 * negative ranges or if mixer-min != 0
8 */
9#define SND_US16X08_NO_BIAS 0
10#define SND_US16X08_FADER_BIAS 127
11#define SND_US16X08_EQ_HIGHFREQ_BIAS 0x20
12#define SND_US16X08_COMP_THRESHOLD_BIAS 0x20
13#define SND_US16X08_COMP_ATTACK_BIAS 2
14#define SND_US16X08_COMP_RELEASE_BIAS 1
15
16/* get macro for components of kcontrol private_value */
17#define SND_US16X08_KCBIAS(x) (((x)->private_value >> 24) & 0xff)
18#define SND_US16X08_KCSTEP(x) (((x)->private_value >> 16) & 0xff)
19#define SND_US16X08_KCMIN(x) (((x)->private_value >> 8) & 0xff)
20#define SND_US16X08_KCMAX(x) (((x)->private_value >> 0) & 0xff)
21/* set macro for kcontrol private_value */
22#define SND_US16X08_KCSET(bias, step, min, max) \
23 (((bias) << 24) | ((step) << 16) | ((min) << 8) | (max))
24
25/* the URB request/type to control Tascam mixers */
26#define SND_US16X08_URB_REQUEST 0x1D
27#define SND_US16X08_URB_REQUESTTYPE 0x40
28
29/* the URB params to retrieve meter ranges */
30#define SND_US16X08_URB_METER_REQUEST 0x1e
31#define SND_US16X08_URB_METER_REQUESTTYPE 0xc0
32
33#define MUA0(x, y) ((x)[(y) * 10 + 4])
34#define MUA1(x, y) ((x)[(y) * 10 + 5])
35#define MUA2(x, y) ((x)[(y) * 10 + 6])
36#define MUB0(x, y) ((x)[(y) * 10 + 7])
37#define MUB1(x, y) ((x)[(y) * 10 + 8])
38#define MUB2(x, y) ((x)[(y) * 10 + 9])
39#define MUC0(x, y) ((x)[(y) * 10 + 10])
40#define MUC1(x, y) ((x)[(y) * 10 + 11])
41#define MUC2(x, y) ((x)[(y) * 10 + 12])
42#define MUC3(x, y) ((x)[(y) * 10 + 13])
43
44/* Common Channel control IDs */
45#define SND_US16X08_ID_BYPASS 0x45
46#define SND_US16X08_ID_BUSS_OUT 0x44
47#define SND_US16X08_ID_PHASE 0x85
48#define SND_US16X08_ID_MUTE 0x83
49#define SND_US16X08_ID_FADER 0x81
50#define SND_US16X08_ID_PAN 0x82
51#define SND_US16X08_ID_METER 0xB1
52
53#define SND_US16X08_ID_EQ_BAND_COUNT 4
54#define SND_US16X08_ID_EQ_PARAM_COUNT 4
55
56/* EQ level IDs */
57#define SND_US16X08_ID_EQLOWLEVEL 0x01
58#define SND_US16X08_ID_EQLOWMIDLEVEL 0x02
59#define SND_US16X08_ID_EQHIGHMIDLEVEL 0x03
60#define SND_US16X08_ID_EQHIGHLEVEL 0x04
61
62/* EQ frequence IDs */
63#define SND_US16X08_ID_EQLOWFREQ 0x11
64#define SND_US16X08_ID_EQLOWMIDFREQ 0x12
65#define SND_US16X08_ID_EQHIGHMIDFREQ 0x13
66#define SND_US16X08_ID_EQHIGHFREQ 0x14
67
68/* EQ width IDs */
69#define SND_US16X08_ID_EQLOWMIDWIDTH 0x22
70#define SND_US16X08_ID_EQHIGHMIDWIDTH 0x23
71
72#define SND_US16X08_ID_EQENABLE 0x30
73
74#define EQ_STORE_BAND_IDX(x) ((x) & 0xf)
75#define EQ_STORE_PARAM_IDX(x) (((x) & 0xf0) >> 4)
76
77#define SND_US16X08_ID_ROUTE 0x00
78
79/* Compressor Ids */
80#define SND_US16X08_ID_COMP_BASE 0x32
81#define SND_US16X08_ID_COMP_THRESHOLD SND_US16X08_ID_COMP_BASE
82#define SND_US16X08_ID_COMP_RATIO (SND_US16X08_ID_COMP_BASE + 1)
83#define SND_US16X08_ID_COMP_ATTACK (SND_US16X08_ID_COMP_BASE + 2)
84#define SND_US16X08_ID_COMP_RELEASE (SND_US16X08_ID_COMP_BASE + 3)
85#define SND_US16X08_ID_COMP_GAIN (SND_US16X08_ID_COMP_BASE + 4)
86#define SND_US16X08_ID_COMP_SWITCH (SND_US16X08_ID_COMP_BASE + 5)
87#define SND_US16X08_ID_COMP_COUNT 6
88
89#define COMP_STORE_IDX(x) ((x) - SND_US16X08_ID_COMP_BASE)
90
91struct snd_us16x08_eq_store {
92 u8 val[SND_US16X08_ID_EQ_BAND_COUNT][SND_US16X08_ID_EQ_PARAM_COUNT]
93 [SND_US16X08_MAX_CHANNELS];
94};
95
96struct snd_us16x08_comp_store {
97 u8 val[SND_US16X08_ID_COMP_COUNT][SND_US16X08_MAX_CHANNELS];
98};
99
100struct snd_us16x08_meter_store {
101 int meter_level[SND_US16X08_MAX_CHANNELS];
102 int master_level[2]; /* level of meter for master output */
103 int comp_index; /* round trip channel selector */
104 int comp_active_index; /* channel select from user space mixer */
105 int comp_level[16]; /* compressor reduction level */
106 struct snd_us16x08_comp_store *comp_store;
107};
108
109struct snd_us16x08_control_params {
110 struct snd_kcontrol_new *kcontrol_new;
111 int control_id;
112 int type;
113 int num_channels;
114 const char *name;
115 void (*freeer)(struct snd_kcontrol *kctl);
116 int default_val;
117};
118
119#define snd_us16x08_switch_info snd_ctl_boolean_mono_info
120
121int snd_us16x08_controls_create(struct usb_mixer_interface *mixer);
122#endif /* __USB_MIXER_US16X08_H */
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index eb4b9f7a571e..01eff6ce6401 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -1360,6 +1360,21 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
1360 if (fp->altsetting == 3) 1360 if (fp->altsetting == 3)
1361 return SNDRV_PCM_FMTBIT_DSD_U32_BE; 1361 return SNDRV_PCM_FMTBIT_DSD_U32_BE;
1362 break; 1362 break;
1363
1364 /* Amanero Combo384 USB interface with native DSD support */
1365 case USB_ID(0x16d0, 0x071a):
1366 if (fp->altsetting == 2) {
1367 switch (chip->dev->descriptor.bcdDevice) {
1368 case 0x199:
1369 return SNDRV_PCM_FMTBIT_DSD_U32_LE;
1370 case 0x19b:
1371 return SNDRV_PCM_FMTBIT_DSD_U32_BE;
1372 default:
1373 break;
1374 }
1375 }
1376 break;
1377
1363 default: 1378 default:
1364 break; 1379 break;
1365 } 1380 }
diff --git a/sound/x86/Kconfig b/sound/x86/Kconfig
new file mode 100644
index 000000000000..30d066e4885e
--- /dev/null
+++ b/sound/x86/Kconfig
@@ -0,0 +1,15 @@
1menuconfig SND_X86
2 tristate "X86 sound devices"
3 depends on X86
4 ---help---
5 X86 sound devices that don't fall under SoC or PCI categories
6
7if SND_X86
8
9config HDMI_LPE_AUDIO
10 tristate "HDMI audio without HDaudio on Intel Atom platforms"
11 depends on DRM_I915
12 help
13 Choose this option to support HDMI LPE Audio mode
14
15endif # SND_X86
diff --git a/sound/x86/Makefile b/sound/x86/Makefile
new file mode 100644
index 000000000000..7ff919808320
--- /dev/null
+++ b/sound/x86/Makefile
@@ -0,0 +1,4 @@
1snd-hdmi-lpe-audio-objs += \
2 intel_hdmi_audio.o
3
4obj-$(CONFIG_HDMI_LPE_AUDIO) += snd-hdmi-lpe-audio.o
diff --git a/sound/x86/intel_hdmi_audio.c b/sound/x86/intel_hdmi_audio.c
new file mode 100644
index 000000000000..360cff35b239
--- /dev/null
+++ b/sound/x86/intel_hdmi_audio.c
@@ -0,0 +1,1851 @@
1/*
2 * intel_hdmi_audio.c - Intel HDMI audio driver
3 *
4 * Copyright (C) 2016 Intel Corp
5 * Authors: Sailaja Bandarupalli <sailaja.bandarupalli@intel.com>
6 * Ramesh Babu K V <ramesh.babu@intel.com>
7 * Vaibhav Agarwal <vaibhav.agarwal@intel.com>
8 * Jerome Anand <jerome.anand@intel.com>
9 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; version 2 of the License.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
19 *
20 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
21 * ALSA driver for Intel HDMI audio
22 */
23
24#include <linux/types.h>
25#include <linux/platform_device.h>
26#include <linux/io.h>
27#include <linux/slab.h>
28#include <linux/module.h>
29#include <linux/interrupt.h>
30#include <linux/pm_runtime.h>
31#include <linux/dma-mapping.h>
32#include <linux/delay.h>
33#include <asm/cacheflush.h>
34#include <sound/core.h>
35#include <sound/asoundef.h>
36#include <sound/pcm.h>
37#include <sound/pcm_params.h>
38#include <sound/initval.h>
39#include <sound/control.h>
40#include <sound/jack.h>
41#include <drm/drm_edid.h>
42#include <drm/intel_lpe_audio.h>
43#include "intel_hdmi_audio.h"
44
45/*standard module options for ALSA. This module supports only one card*/
46static int hdmi_card_index = SNDRV_DEFAULT_IDX1;
47static char *hdmi_card_id = SNDRV_DEFAULT_STR1;
48
49module_param_named(index, hdmi_card_index, int, 0444);
50MODULE_PARM_DESC(index,
51 "Index value for INTEL Intel HDMI Audio controller.");
52module_param_named(id, hdmi_card_id, charp, 0444);
53MODULE_PARM_DESC(id,
54 "ID string for INTEL Intel HDMI Audio controller.");
55
56/*
57 * ELD SA bits in the CEA Speaker Allocation data block
58 */
59static const int eld_speaker_allocation_bits[] = {
60 [0] = FL | FR,
61 [1] = LFE,
62 [2] = FC,
63 [3] = RL | RR,
64 [4] = RC,
65 [5] = FLC | FRC,
66 [6] = RLC | RRC,
67 /* the following are not defined in ELD yet */
68 [7] = 0,
69};
70
71/*
72 * This is an ordered list!
73 *
74 * The preceding ones have better chances to be selected by
75 * hdmi_channel_allocation().
76 */
77static struct cea_channel_speaker_allocation channel_allocations[] = {
78/* channel: 7 6 5 4 3 2 1 0 */
79{ .ca_index = 0x00, .speakers = { 0, 0, 0, 0, 0, 0, FR, FL } },
80 /* 2.1 */
81{ .ca_index = 0x01, .speakers = { 0, 0, 0, 0, 0, LFE, FR, FL } },
82 /* Dolby Surround */
83{ .ca_index = 0x02, .speakers = { 0, 0, 0, 0, FC, 0, FR, FL } },
84 /* surround40 */
85{ .ca_index = 0x08, .speakers = { 0, 0, RR, RL, 0, 0, FR, FL } },
86 /* surround41 */
87{ .ca_index = 0x09, .speakers = { 0, 0, RR, RL, 0, LFE, FR, FL } },
88 /* surround50 */
89{ .ca_index = 0x0a, .speakers = { 0, 0, RR, RL, FC, 0, FR, FL } },
90 /* surround51 */
91{ .ca_index = 0x0b, .speakers = { 0, 0, RR, RL, FC, LFE, FR, FL } },
92 /* 6.1 */
93{ .ca_index = 0x0f, .speakers = { 0, RC, RR, RL, FC, LFE, FR, FL } },
94 /* surround71 */
95{ .ca_index = 0x13, .speakers = { RRC, RLC, RR, RL, FC, LFE, FR, FL } },
96
97{ .ca_index = 0x03, .speakers = { 0, 0, 0, 0, FC, LFE, FR, FL } },
98{ .ca_index = 0x04, .speakers = { 0, 0, 0, RC, 0, 0, FR, FL } },
99{ .ca_index = 0x05, .speakers = { 0, 0, 0, RC, 0, LFE, FR, FL } },
100{ .ca_index = 0x06, .speakers = { 0, 0, 0, RC, FC, 0, FR, FL } },
101{ .ca_index = 0x07, .speakers = { 0, 0, 0, RC, FC, LFE, FR, FL } },
102{ .ca_index = 0x0c, .speakers = { 0, RC, RR, RL, 0, 0, FR, FL } },
103{ .ca_index = 0x0d, .speakers = { 0, RC, RR, RL, 0, LFE, FR, FL } },
104{ .ca_index = 0x0e, .speakers = { 0, RC, RR, RL, FC, 0, FR, FL } },
105{ .ca_index = 0x10, .speakers = { RRC, RLC, RR, RL, 0, 0, FR, FL } },
106{ .ca_index = 0x11, .speakers = { RRC, RLC, RR, RL, 0, LFE, FR, FL } },
107{ .ca_index = 0x12, .speakers = { RRC, RLC, RR, RL, FC, 0, FR, FL } },
108{ .ca_index = 0x14, .speakers = { FRC, FLC, 0, 0, 0, 0, FR, FL } },
109{ .ca_index = 0x15, .speakers = { FRC, FLC, 0, 0, 0, LFE, FR, FL } },
110{ .ca_index = 0x16, .speakers = { FRC, FLC, 0, 0, FC, 0, FR, FL } },
111{ .ca_index = 0x17, .speakers = { FRC, FLC, 0, 0, FC, LFE, FR, FL } },
112{ .ca_index = 0x18, .speakers = { FRC, FLC, 0, RC, 0, 0, FR, FL } },
113{ .ca_index = 0x19, .speakers = { FRC, FLC, 0, RC, 0, LFE, FR, FL } },
114{ .ca_index = 0x1a, .speakers = { FRC, FLC, 0, RC, FC, 0, FR, FL } },
115{ .ca_index = 0x1b, .speakers = { FRC, FLC, 0, RC, FC, LFE, FR, FL } },
116{ .ca_index = 0x1c, .speakers = { FRC, FLC, RR, RL, 0, 0, FR, FL } },
117{ .ca_index = 0x1d, .speakers = { FRC, FLC, RR, RL, 0, LFE, FR, FL } },
118{ .ca_index = 0x1e, .speakers = { FRC, FLC, RR, RL, FC, 0, FR, FL } },
119{ .ca_index = 0x1f, .speakers = { FRC, FLC, RR, RL, FC, LFE, FR, FL } },
120};
121
122static const struct channel_map_table map_tables[] = {
123 { SNDRV_CHMAP_FL, 0x00, FL },
124 { SNDRV_CHMAP_FR, 0x01, FR },
125 { SNDRV_CHMAP_RL, 0x04, RL },
126 { SNDRV_CHMAP_RR, 0x05, RR },
127 { SNDRV_CHMAP_LFE, 0x02, LFE },
128 { SNDRV_CHMAP_FC, 0x03, FC },
129 { SNDRV_CHMAP_RLC, 0x06, RLC },
130 { SNDRV_CHMAP_RRC, 0x07, RRC },
131 {} /* terminator */
132};
133
134/* hardware capability structure */
135static const struct snd_pcm_hardware had_pcm_hardware = {
136 .info = (SNDRV_PCM_INFO_INTERLEAVED |
137 SNDRV_PCM_INFO_MMAP |
138 SNDRV_PCM_INFO_MMAP_VALID |
139 SNDRV_PCM_INFO_NO_PERIOD_WAKEUP),
140 .formats = (SNDRV_PCM_FMTBIT_S16_LE |
141 SNDRV_PCM_FMTBIT_S24_LE |
142 SNDRV_PCM_FMTBIT_S32_LE),
143 .rates = SNDRV_PCM_RATE_32000 |
144 SNDRV_PCM_RATE_44100 |
145 SNDRV_PCM_RATE_48000 |
146 SNDRV_PCM_RATE_88200 |
147 SNDRV_PCM_RATE_96000 |
148 SNDRV_PCM_RATE_176400 |
149 SNDRV_PCM_RATE_192000,
150 .rate_min = HAD_MIN_RATE,
151 .rate_max = HAD_MAX_RATE,
152 .channels_min = HAD_MIN_CHANNEL,
153 .channels_max = HAD_MAX_CHANNEL,
154 .buffer_bytes_max = HAD_MAX_BUFFER,
155 .period_bytes_min = HAD_MIN_PERIOD_BYTES,
156 .period_bytes_max = HAD_MAX_PERIOD_BYTES,
157 .periods_min = HAD_MIN_PERIODS,
158 .periods_max = HAD_MAX_PERIODS,
159 .fifo_size = HAD_FIFO_SIZE,
160};
161
162/* Get the active PCM substream;
163 * Call had_substream_put() for unreferecing.
164 * Don't call this inside had_spinlock, as it takes by itself
165 */
166static struct snd_pcm_substream *
167had_substream_get(struct snd_intelhad *intelhaddata)
168{
169 struct snd_pcm_substream *substream;
170 unsigned long flags;
171
172 spin_lock_irqsave(&intelhaddata->had_spinlock, flags);
173 substream = intelhaddata->stream_info.substream;
174 if (substream)
175 intelhaddata->stream_info.substream_refcount++;
176 spin_unlock_irqrestore(&intelhaddata->had_spinlock, flags);
177 return substream;
178}
179
180/* Unref the active PCM substream;
181 * Don't call this inside had_spinlock, as it takes by itself
182 */
183static void had_substream_put(struct snd_intelhad *intelhaddata)
184{
185 unsigned long flags;
186
187 spin_lock_irqsave(&intelhaddata->had_spinlock, flags);
188 intelhaddata->stream_info.substream_refcount--;
189 spin_unlock_irqrestore(&intelhaddata->had_spinlock, flags);
190}
191
192/* Register access functions */
193static u32 had_read_register_raw(struct snd_intelhad *ctx, u32 reg)
194{
195 return ioread32(ctx->mmio_start + ctx->had_config_offset + reg);
196}
197
198static void had_write_register_raw(struct snd_intelhad *ctx, u32 reg, u32 val)
199{
200 iowrite32(val, ctx->mmio_start + ctx->had_config_offset + reg);
201}
202
203static void had_read_register(struct snd_intelhad *ctx, u32 reg, u32 *val)
204{
205 if (!ctx->connected)
206 *val = 0;
207 else
208 *val = had_read_register_raw(ctx, reg);
209}
210
211static void had_write_register(struct snd_intelhad *ctx, u32 reg, u32 val)
212{
213 if (ctx->connected)
214 had_write_register_raw(ctx, reg, val);
215}
216
217/*
218 * enable / disable audio configuration
219 *
220 * The normal read/modify should not directly be used on VLV2 for
221 * updating AUD_CONFIG register.
222 * This is because:
223 * Bit6 of AUD_CONFIG register is writeonly due to a silicon bug on VLV2
224 * HDMI IP. As a result a read-modify of AUD_CONFIG regiter will always
225 * clear bit6. AUD_CONFIG[6:4] represents the "channels" field of the
226 * register. This field should be 1xy binary for configuration with 6 or
227 * more channels. Read-modify of AUD_CONFIG (Eg. for enabling audio)
228 * causes the "channels" field to be updated as 0xy binary resulting in
229 * bad audio. The fix is to always write the AUD_CONFIG[6:4] with
230 * appropriate value when doing read-modify of AUD_CONFIG register.
231 */
232static void had_enable_audio(struct snd_intelhad *intelhaddata,
233 bool enable)
234{
235 /* update the cached value */
236 intelhaddata->aud_config.regx.aud_en = enable;
237 had_write_register(intelhaddata, AUD_CONFIG,
238 intelhaddata->aud_config.regval);
239}
240
241/* forcibly ACKs to both BUFFER_DONE and BUFFER_UNDERRUN interrupts */
242static void had_ack_irqs(struct snd_intelhad *ctx)
243{
244 u32 status_reg;
245
246 if (!ctx->connected)
247 return;
248 had_read_register(ctx, AUD_HDMI_STATUS, &status_reg);
249 status_reg |= HDMI_AUDIO_BUFFER_DONE | HDMI_AUDIO_UNDERRUN;
250 had_write_register(ctx, AUD_HDMI_STATUS, status_reg);
251 had_read_register(ctx, AUD_HDMI_STATUS, &status_reg);
252}
253
254/* Reset buffer pointers */
255static void had_reset_audio(struct snd_intelhad *intelhaddata)
256{
257 had_write_register(intelhaddata, AUD_HDMI_STATUS,
258 AUD_HDMI_STATUSG_MASK_FUNCRST);
259 had_write_register(intelhaddata, AUD_HDMI_STATUS, 0);
260}
261
262/*
263 * initialize audio channel status registers
264 * This function is called in the prepare callback
265 */
266static int had_prog_status_reg(struct snd_pcm_substream *substream,
267 struct snd_intelhad *intelhaddata)
268{
269 union aud_cfg cfg_val = {.regval = 0};
270 union aud_ch_status_0 ch_stat0 = {.regval = 0};
271 union aud_ch_status_1 ch_stat1 = {.regval = 0};
272
273 ch_stat0.regx.lpcm_id = (intelhaddata->aes_bits &
274 IEC958_AES0_NONAUDIO) >> 1;
275 ch_stat0.regx.clk_acc = (intelhaddata->aes_bits &
276 IEC958_AES3_CON_CLOCK) >> 4;
277 cfg_val.regx.val_bit = ch_stat0.regx.lpcm_id;
278
279 switch (substream->runtime->rate) {
280 case AUD_SAMPLE_RATE_32:
281 ch_stat0.regx.samp_freq = CH_STATUS_MAP_32KHZ;
282 break;
283
284 case AUD_SAMPLE_RATE_44_1:
285 ch_stat0.regx.samp_freq = CH_STATUS_MAP_44KHZ;
286 break;
287 case AUD_SAMPLE_RATE_48:
288 ch_stat0.regx.samp_freq = CH_STATUS_MAP_48KHZ;
289 break;
290 case AUD_SAMPLE_RATE_88_2:
291 ch_stat0.regx.samp_freq = CH_STATUS_MAP_88KHZ;
292 break;
293 case AUD_SAMPLE_RATE_96:
294 ch_stat0.regx.samp_freq = CH_STATUS_MAP_96KHZ;
295 break;
296 case AUD_SAMPLE_RATE_176_4:
297 ch_stat0.regx.samp_freq = CH_STATUS_MAP_176KHZ;
298 break;
299 case AUD_SAMPLE_RATE_192:
300 ch_stat0.regx.samp_freq = CH_STATUS_MAP_192KHZ;
301 break;
302
303 default:
304 /* control should never come here */
305 return -EINVAL;
306 }
307
308 had_write_register(intelhaddata,
309 AUD_CH_STATUS_0, ch_stat0.regval);
310
311 switch (substream->runtime->format) {
312 case SNDRV_PCM_FORMAT_S16_LE:
313 ch_stat1.regx.max_wrd_len = MAX_SMPL_WIDTH_20;
314 ch_stat1.regx.wrd_len = SMPL_WIDTH_16BITS;
315 break;
316 case SNDRV_PCM_FORMAT_S24_LE:
317 case SNDRV_PCM_FORMAT_S32_LE:
318 ch_stat1.regx.max_wrd_len = MAX_SMPL_WIDTH_24;
319 ch_stat1.regx.wrd_len = SMPL_WIDTH_24BITS;
320 break;
321 default:
322 return -EINVAL;
323 }
324
325 had_write_register(intelhaddata,
326 AUD_CH_STATUS_1, ch_stat1.regval);
327 return 0;
328}
329
330/*
331 * function to initialize audio
332 * registers and buffer confgiuration registers
333 * This function is called in the prepare callback
334 */
335static int had_init_audio_ctrl(struct snd_pcm_substream *substream,
336 struct snd_intelhad *intelhaddata)
337{
338 union aud_cfg cfg_val = {.regval = 0};
339 union aud_buf_config buf_cfg = {.regval = 0};
340 u8 channels;
341
342 had_prog_status_reg(substream, intelhaddata);
343
344 buf_cfg.regx.audio_fifo_watermark = FIFO_THRESHOLD;
345 buf_cfg.regx.dma_fifo_watermark = DMA_FIFO_THRESHOLD;
346 buf_cfg.regx.aud_delay = 0;
347 had_write_register(intelhaddata, AUD_BUF_CONFIG, buf_cfg.regval);
348
349 channels = substream->runtime->channels;
350 cfg_val.regx.num_ch = channels - 2;
351 if (channels <= 2)
352 cfg_val.regx.layout = LAYOUT0;
353 else
354 cfg_val.regx.layout = LAYOUT1;
355
356 if (substream->runtime->format == SNDRV_PCM_FORMAT_S16_LE)
357 cfg_val.regx.packet_mode = 1;
358
359 if (substream->runtime->format == SNDRV_PCM_FORMAT_S32_LE)
360 cfg_val.regx.left_align = 1;
361
362 cfg_val.regx.val_bit = 1;
363
364 /* fix up the DP bits */
365 if (intelhaddata->dp_output) {
366 cfg_val.regx.dp_modei = 1;
367 cfg_val.regx.set = 1;
368 }
369
370 had_write_register(intelhaddata, AUD_CONFIG, cfg_val.regval);
371 intelhaddata->aud_config = cfg_val;
372 return 0;
373}
374
375/*
376 * Compute derived values in channel_allocations[].
377 */
378static void init_channel_allocations(void)
379{
380 int i, j;
381 struct cea_channel_speaker_allocation *p;
382
383 for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
384 p = channel_allocations + i;
385 p->channels = 0;
386 p->spk_mask = 0;
387 for (j = 0; j < ARRAY_SIZE(p->speakers); j++)
388 if (p->speakers[j]) {
389 p->channels++;
390 p->spk_mask |= p->speakers[j];
391 }
392 }
393}
394
395/*
396 * The transformation takes two steps:
397 *
398 * eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask
399 * spk_mask => (channel_allocations[]) => ai->CA
400 *
401 * TODO: it could select the wrong CA from multiple candidates.
402 */
403static int had_channel_allocation(struct snd_intelhad *intelhaddata,
404 int channels)
405{
406 int i;
407 int ca = 0;
408 int spk_mask = 0;
409
410 /*
411 * CA defaults to 0 for basic stereo audio
412 */
413 if (channels <= 2)
414 return 0;
415
416 /*
417 * expand ELD's speaker allocation mask
418 *
419 * ELD tells the speaker mask in a compact(paired) form,
420 * expand ELD's notions to match the ones used by Audio InfoFrame.
421 */
422
423 for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) {
424 if (intelhaddata->eld[DRM_ELD_SPEAKER] & (1 << i))
425 spk_mask |= eld_speaker_allocation_bits[i];
426 }
427
428 /* search for the first working match in the CA table */
429 for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
430 if (channels == channel_allocations[i].channels &&
431 (spk_mask & channel_allocations[i].spk_mask) ==
432 channel_allocations[i].spk_mask) {
433 ca = channel_allocations[i].ca_index;
434 break;
435 }
436 }
437
438 dev_dbg(intelhaddata->dev, "select CA 0x%x for %d\n", ca, channels);
439
440 return ca;
441}
442
443/* from speaker bit mask to ALSA API channel position */
444static int spk_to_chmap(int spk)
445{
446 const struct channel_map_table *t = map_tables;
447
448 for (; t->map; t++) {
449 if (t->spk_mask == spk)
450 return t->map;
451 }
452 return 0;
453}
454
455static void had_build_channel_allocation_map(struct snd_intelhad *intelhaddata)
456{
457 int i, c;
458 int spk_mask = 0;
459 struct snd_pcm_chmap_elem *chmap;
460 u8 eld_high, eld_high_mask = 0xF0;
461 u8 high_msb;
462
463 kfree(intelhaddata->chmap->chmap);
464 intelhaddata->chmap->chmap = NULL;
465
466 chmap = kzalloc(sizeof(*chmap), GFP_KERNEL);
467 if (!chmap)
468 return;
469
470 dev_dbg(intelhaddata->dev, "eld speaker = %x\n",
471 intelhaddata->eld[DRM_ELD_SPEAKER]);
472
473 /* WA: Fix the max channel supported to 8 */
474
475 /*
476 * Sink may support more than 8 channels, if eld_high has more than
477 * one bit set. SOC supports max 8 channels.
478 * Refer eld_speaker_allocation_bits, for sink speaker allocation
479 */
480
481 /* if 0x2F < eld < 0x4F fall back to 0x2f, else fall back to 0x4F */
482 eld_high = intelhaddata->eld[DRM_ELD_SPEAKER] & eld_high_mask;
483 if ((eld_high & (eld_high-1)) && (eld_high > 0x1F)) {
484 /* eld_high & (eld_high-1): if more than 1 bit set */
485 /* 0x1F: 7 channels */
486 for (i = 1; i < 4; i++) {
487 high_msb = eld_high & (0x80 >> i);
488 if (high_msb) {
489 intelhaddata->eld[DRM_ELD_SPEAKER] &=
490 high_msb | 0xF;
491 break;
492 }
493 }
494 }
495
496 for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) {
497 if (intelhaddata->eld[DRM_ELD_SPEAKER] & (1 << i))
498 spk_mask |= eld_speaker_allocation_bits[i];
499 }
500
501 for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
502 if (spk_mask == channel_allocations[i].spk_mask) {
503 for (c = 0; c < channel_allocations[i].channels; c++) {
504 chmap->map[c] = spk_to_chmap(
505 channel_allocations[i].speakers[
506 (MAX_SPEAKERS - 1) - c]);
507 }
508 chmap->channels = channel_allocations[i].channels;
509 intelhaddata->chmap->chmap = chmap;
510 break;
511 }
512 }
513 if (i >= ARRAY_SIZE(channel_allocations))
514 kfree(chmap);
515}
516
517/*
518 * ALSA API channel-map control callbacks
519 */
520static int had_chmap_ctl_info(struct snd_kcontrol *kcontrol,
521 struct snd_ctl_elem_info *uinfo)
522{
523 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
524 uinfo->count = HAD_MAX_CHANNEL;
525 uinfo->value.integer.min = 0;
526 uinfo->value.integer.max = SNDRV_CHMAP_LAST;
527 return 0;
528}
529
530static int had_chmap_ctl_get(struct snd_kcontrol *kcontrol,
531 struct snd_ctl_elem_value *ucontrol)
532{
533 struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
534 struct snd_intelhad *intelhaddata = info->private_data;
535 int i;
536 const struct snd_pcm_chmap_elem *chmap;
537
538 memset(ucontrol->value.integer.value, 0,
539 sizeof(long) * HAD_MAX_CHANNEL);
540 mutex_lock(&intelhaddata->mutex);
541 if (!intelhaddata->chmap->chmap) {
542 mutex_unlock(&intelhaddata->mutex);
543 return 0;
544 }
545
546 chmap = intelhaddata->chmap->chmap;
547 for (i = 0; i < chmap->channels; i++)
548 ucontrol->value.integer.value[i] = chmap->map[i];
549 mutex_unlock(&intelhaddata->mutex);
550
551 return 0;
552}
553
554static int had_register_chmap_ctls(struct snd_intelhad *intelhaddata,
555 struct snd_pcm *pcm)
556{
557 int err;
558
559 err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK,
560 NULL, 0, (unsigned long)intelhaddata,
561 &intelhaddata->chmap);
562 if (err < 0)
563 return err;
564
565 intelhaddata->chmap->private_data = intelhaddata;
566 intelhaddata->chmap->kctl->info = had_chmap_ctl_info;
567 intelhaddata->chmap->kctl->get = had_chmap_ctl_get;
568 intelhaddata->chmap->chmap = NULL;
569 return 0;
570}
571
572/*
573 * Initialize Data Island Packets registers
574 * This function is called in the prepare callback
575 */
576static void had_prog_dip(struct snd_pcm_substream *substream,
577 struct snd_intelhad *intelhaddata)
578{
579 int i;
580 union aud_ctrl_st ctrl_state = {.regval = 0};
581 union aud_info_frame2 frame2 = {.regval = 0};
582 union aud_info_frame3 frame3 = {.regval = 0};
583 u8 checksum = 0;
584 u32 info_frame;
585 int channels;
586 int ca;
587
588 channels = substream->runtime->channels;
589
590 had_write_register(intelhaddata, AUD_CNTL_ST, ctrl_state.regval);
591
592 ca = had_channel_allocation(intelhaddata, channels);
593 if (intelhaddata->dp_output) {
594 info_frame = DP_INFO_FRAME_WORD1;
595 frame2.regval = (substream->runtime->channels - 1) | (ca << 24);
596 } else {
597 info_frame = HDMI_INFO_FRAME_WORD1;
598 frame2.regx.chnl_cnt = substream->runtime->channels - 1;
599 frame3.regx.chnl_alloc = ca;
600
601 /* Calculte the byte wide checksum for all valid DIP words */
602 for (i = 0; i < BYTES_PER_WORD; i++)
603 checksum += (info_frame >> (i * 8)) & 0xff;
604 for (i = 0; i < BYTES_PER_WORD; i++)
605 checksum += (frame2.regval >> (i * 8)) & 0xff;
606 for (i = 0; i < BYTES_PER_WORD; i++)
607 checksum += (frame3.regval >> (i * 8)) & 0xff;
608
609 frame2.regx.chksum = -(checksum);
610 }
611
612 had_write_register(intelhaddata, AUD_HDMIW_INFOFR, info_frame);
613 had_write_register(intelhaddata, AUD_HDMIW_INFOFR, frame2.regval);
614 had_write_register(intelhaddata, AUD_HDMIW_INFOFR, frame3.regval);
615
616 /* program remaining DIP words with zero */
617 for (i = 0; i < HAD_MAX_DIP_WORDS-VALID_DIP_WORDS; i++)
618 had_write_register(intelhaddata, AUD_HDMIW_INFOFR, 0x0);
619
620 ctrl_state.regx.dip_freq = 1;
621 ctrl_state.regx.dip_en_sta = 1;
622 had_write_register(intelhaddata, AUD_CNTL_ST, ctrl_state.regval);
623}
624
625static int had_calculate_maud_value(u32 aud_samp_freq, u32 link_rate)
626{
627 u32 maud_val;
628
629 /* Select maud according to DP 1.2 spec */
630 if (link_rate == DP_2_7_GHZ) {
631 switch (aud_samp_freq) {
632 case AUD_SAMPLE_RATE_32:
633 maud_val = AUD_SAMPLE_RATE_32_DP_2_7_MAUD_VAL;
634 break;
635
636 case AUD_SAMPLE_RATE_44_1:
637 maud_val = AUD_SAMPLE_RATE_44_1_DP_2_7_MAUD_VAL;
638 break;
639
640 case AUD_SAMPLE_RATE_48:
641 maud_val = AUD_SAMPLE_RATE_48_DP_2_7_MAUD_VAL;
642 break;
643
644 case AUD_SAMPLE_RATE_88_2:
645 maud_val = AUD_SAMPLE_RATE_88_2_DP_2_7_MAUD_VAL;
646 break;
647
648 case AUD_SAMPLE_RATE_96:
649 maud_val = AUD_SAMPLE_RATE_96_DP_2_7_MAUD_VAL;
650 break;
651
652 case AUD_SAMPLE_RATE_176_4:
653 maud_val = AUD_SAMPLE_RATE_176_4_DP_2_7_MAUD_VAL;
654 break;
655
656 case HAD_MAX_RATE:
657 maud_val = HAD_MAX_RATE_DP_2_7_MAUD_VAL;
658 break;
659
660 default:
661 maud_val = -EINVAL;
662 break;
663 }
664 } else if (link_rate == DP_1_62_GHZ) {
665 switch (aud_samp_freq) {
666 case AUD_SAMPLE_RATE_32:
667 maud_val = AUD_SAMPLE_RATE_32_DP_1_62_MAUD_VAL;
668 break;
669
670 case AUD_SAMPLE_RATE_44_1:
671 maud_val = AUD_SAMPLE_RATE_44_1_DP_1_62_MAUD_VAL;
672 break;
673
674 case AUD_SAMPLE_RATE_48:
675 maud_val = AUD_SAMPLE_RATE_48_DP_1_62_MAUD_VAL;
676 break;
677
678 case AUD_SAMPLE_RATE_88_2:
679 maud_val = AUD_SAMPLE_RATE_88_2_DP_1_62_MAUD_VAL;
680 break;
681
682 case AUD_SAMPLE_RATE_96:
683 maud_val = AUD_SAMPLE_RATE_96_DP_1_62_MAUD_VAL;
684 break;
685
686 case AUD_SAMPLE_RATE_176_4:
687 maud_val = AUD_SAMPLE_RATE_176_4_DP_1_62_MAUD_VAL;
688 break;
689
690 case HAD_MAX_RATE:
691 maud_val = HAD_MAX_RATE_DP_1_62_MAUD_VAL;
692 break;
693
694 default:
695 maud_val = -EINVAL;
696 break;
697 }
698 } else
699 maud_val = -EINVAL;
700
701 return maud_val;
702}
703
704/*
705 * Program HDMI audio CTS value
706 *
707 * @aud_samp_freq: sampling frequency of audio data
708 * @tmds: sampling frequency of the display data
709 * @link_rate: DP link rate
710 * @n_param: N value, depends on aud_samp_freq
711 * @intelhaddata: substream private data
712 *
713 * Program CTS register based on the audio and display sampling frequency
714 */
715static void had_prog_cts(u32 aud_samp_freq, u32 tmds, u32 link_rate,
716 u32 n_param, struct snd_intelhad *intelhaddata)
717{
718 u32 cts_val;
719 u64 dividend, divisor;
720
721 if (intelhaddata->dp_output) {
722 /* Substitute cts_val with Maud according to DP 1.2 spec*/
723 cts_val = had_calculate_maud_value(aud_samp_freq, link_rate);
724 } else {
725 /* Calculate CTS according to HDMI 1.3a spec*/
726 dividend = (u64)tmds * n_param*1000;
727 divisor = 128 * aud_samp_freq;
728 cts_val = div64_u64(dividend, divisor);
729 }
730 dev_dbg(intelhaddata->dev, "TMDS value=%d, N value=%d, CTS Value=%d\n",
731 tmds, n_param, cts_val);
732 had_write_register(intelhaddata, AUD_HDMI_CTS, (BIT(24) | cts_val));
733}
734
735static int had_calculate_n_value(u32 aud_samp_freq)
736{
737 int n_val;
738
739 /* Select N according to HDMI 1.3a spec*/
740 switch (aud_samp_freq) {
741 case AUD_SAMPLE_RATE_32:
742 n_val = 4096;
743 break;
744
745 case AUD_SAMPLE_RATE_44_1:
746 n_val = 6272;
747 break;
748
749 case AUD_SAMPLE_RATE_48:
750 n_val = 6144;
751 break;
752
753 case AUD_SAMPLE_RATE_88_2:
754 n_val = 12544;
755 break;
756
757 case AUD_SAMPLE_RATE_96:
758 n_val = 12288;
759 break;
760
761 case AUD_SAMPLE_RATE_176_4:
762 n_val = 25088;
763 break;
764
765 case HAD_MAX_RATE:
766 n_val = 24576;
767 break;
768
769 default:
770 n_val = -EINVAL;
771 break;
772 }
773 return n_val;
774}
775
776/*
777 * Program HDMI audio N value
778 *
779 * @aud_samp_freq: sampling frequency of audio data
780 * @n_param: N value, depends on aud_samp_freq
781 * @intelhaddata: substream private data
782 *
783 * This function is called in the prepare callback.
784 * It programs based on the audio and display sampling frequency
785 */
786static int had_prog_n(u32 aud_samp_freq, u32 *n_param,
787 struct snd_intelhad *intelhaddata)
788{
789 int n_val;
790
791 if (intelhaddata->dp_output) {
792 /*
793 * According to DP specs, Maud and Naud values hold
794 * a relationship, which is stated as:
795 * Maud/Naud = 512 * fs / f_LS_Clk
796 * where, fs is the sampling frequency of the audio stream
797 * and Naud is 32768 for Async clock.
798 */
799
800 n_val = DP_NAUD_VAL;
801 } else
802 n_val = had_calculate_n_value(aud_samp_freq);
803
804 if (n_val < 0)
805 return n_val;
806
807 had_write_register(intelhaddata, AUD_N_ENABLE, (BIT(24) | n_val));
808 *n_param = n_val;
809 return 0;
810}
811
812/*
813 * PCM ring buffer handling
814 *
815 * The hardware provides a ring buffer with the fixed 4 buffer descriptors
816 * (BDs). The driver maps these 4 BDs onto the PCM ring buffer. The mapping
817 * moves at each period elapsed. The below illustrates how it works:
818 *
819 * At time=0
820 * PCM | 0 | 1 | 2 | 3 | 4 | 5 | .... |n-1|
821 * BD | 0 | 1 | 2 | 3 |
822 *
823 * At time=1 (period elapsed)
824 * PCM | 0 | 1 | 2 | 3 | 4 | 5 | .... |n-1|
825 * BD | 1 | 2 | 3 | 0 |
826 *
827 * At time=2 (second period elapsed)
828 * PCM | 0 | 1 | 2 | 3 | 4 | 5 | .... |n-1|
829 * BD | 2 | 3 | 0 | 1 |
830 *
831 * The bd_head field points to the index of the BD to be read. It's also the
832 * position to be filled at next. The pcm_head and the pcm_filled fields
833 * point to the indices of the current position and of the next position to
834 * be filled, respectively. For PCM buffer there are both _head and _filled
835 * because they may be difference when nperiods > 4. For example, in the
836 * example above at t=1, bd_head=1 and pcm_head=1 while pcm_filled=5:
837 *
838 * pcm_head (=1) --v v-- pcm_filled (=5)
839 * PCM | 0 | 1 | 2 | 3 | 4 | 5 | .... |n-1|
840 * BD | 1 | 2 | 3 | 0 |
841 * bd_head (=1) --^ ^-- next to fill (= bd_head)
842 *
843 * For nperiods < 4, the remaining BDs out of 4 are marked as invalid, so that
844 * the hardware skips those BDs in the loop.
845 *
846 * An exceptional setup is the case with nperiods=1. Since we have to update
847 * BDs after finishing one BD processing, we'd need at least two BDs, where
848 * both BDs point to the same content, the same address, the same size of the
849 * whole PCM buffer.
850 */
851
852#define AUD_BUF_ADDR(x) (AUD_BUF_A_ADDR + (x) * HAD_REG_WIDTH)
853#define AUD_BUF_LEN(x) (AUD_BUF_A_LENGTH + (x) * HAD_REG_WIDTH)
854
855/* Set up a buffer descriptor at the "filled" position */
856static void had_prog_bd(struct snd_pcm_substream *substream,
857 struct snd_intelhad *intelhaddata)
858{
859 int idx = intelhaddata->bd_head;
860 int ofs = intelhaddata->pcmbuf_filled * intelhaddata->period_bytes;
861 u32 addr = substream->runtime->dma_addr + ofs;
862
863 addr |= AUD_BUF_VALID;
864 if (!substream->runtime->no_period_wakeup)
865 addr |= AUD_BUF_INTR_EN;
866 had_write_register(intelhaddata, AUD_BUF_ADDR(idx), addr);
867 had_write_register(intelhaddata, AUD_BUF_LEN(idx),
868 intelhaddata->period_bytes);
869
870 /* advance the indices to the next */
871 intelhaddata->bd_head++;
872 intelhaddata->bd_head %= intelhaddata->num_bds;
873 intelhaddata->pcmbuf_filled++;
874 intelhaddata->pcmbuf_filled %= substream->runtime->periods;
875}
876
877/* invalidate a buffer descriptor with the given index */
878static void had_invalidate_bd(struct snd_intelhad *intelhaddata,
879 int idx)
880{
881 had_write_register(intelhaddata, AUD_BUF_ADDR(idx), 0);
882 had_write_register(intelhaddata, AUD_BUF_LEN(idx), 0);
883}
884
885/* Initial programming of ring buffer */
886static void had_init_ringbuf(struct snd_pcm_substream *substream,
887 struct snd_intelhad *intelhaddata)
888{
889 struct snd_pcm_runtime *runtime = substream->runtime;
890 int i, num_periods;
891
892 num_periods = runtime->periods;
893 intelhaddata->num_bds = min(num_periods, HAD_NUM_OF_RING_BUFS);
894 /* set the minimum 2 BDs for num_periods=1 */
895 intelhaddata->num_bds = max(intelhaddata->num_bds, 2U);
896 intelhaddata->period_bytes =
897 frames_to_bytes(runtime, runtime->period_size);
898 WARN_ON(intelhaddata->period_bytes & 0x3f);
899
900 intelhaddata->bd_head = 0;
901 intelhaddata->pcmbuf_head = 0;
902 intelhaddata->pcmbuf_filled = 0;
903
904 for (i = 0; i < HAD_NUM_OF_RING_BUFS; i++) {
905 if (i < intelhaddata->num_bds)
906 had_prog_bd(substream, intelhaddata);
907 else /* invalidate the rest */
908 had_invalidate_bd(intelhaddata, i);
909 }
910
911 intelhaddata->bd_head = 0; /* reset at head again before starting */
912}
913
914/* process a bd, advance to the next */
915static void had_advance_ringbuf(struct snd_pcm_substream *substream,
916 struct snd_intelhad *intelhaddata)
917{
918 int num_periods = substream->runtime->periods;
919
920 /* reprogram the next buffer */
921 had_prog_bd(substream, intelhaddata);
922
923 /* proceed to next */
924 intelhaddata->pcmbuf_head++;
925 intelhaddata->pcmbuf_head %= num_periods;
926}
927
928/* process the current BD(s);
929 * returns the current PCM buffer byte position, or -EPIPE for underrun.
930 */
931static int had_process_ringbuf(struct snd_pcm_substream *substream,
932 struct snd_intelhad *intelhaddata)
933{
934 int len, processed;
935 unsigned long flags;
936
937 processed = 0;
938 spin_lock_irqsave(&intelhaddata->had_spinlock, flags);
939 for (;;) {
940 /* get the remaining bytes on the buffer */
941 had_read_register(intelhaddata,
942 AUD_BUF_LEN(intelhaddata->bd_head),
943 &len);
944 if (len < 0 || len > intelhaddata->period_bytes) {
945 dev_dbg(intelhaddata->dev, "Invalid buf length %d\n",
946 len);
947 len = -EPIPE;
948 goto out;
949 }
950
951 if (len > 0) /* OK, this is the current buffer */
952 break;
953
954 /* len=0 => already empty, check the next buffer */
955 if (++processed >= intelhaddata->num_bds) {
956 len = -EPIPE; /* all empty? - report underrun */
957 goto out;
958 }
959 had_advance_ringbuf(substream, intelhaddata);
960 }
961
962 len = intelhaddata->period_bytes - len;
963 len += intelhaddata->period_bytes * intelhaddata->pcmbuf_head;
964 out:
965 spin_unlock_irqrestore(&intelhaddata->had_spinlock, flags);
966 return len;
967}
968
969/* called from irq handler */
970static void had_process_buffer_done(struct snd_intelhad *intelhaddata)
971{
972 struct snd_pcm_substream *substream;
973
974 substream = had_substream_get(intelhaddata);
975 if (!substream)
976 return; /* no stream? - bail out */
977
978 if (!intelhaddata->connected) {
979 snd_pcm_stop_xrun(substream);
980 goto out; /* disconnected? - bail out */
981 }
982
983 /* process or stop the stream */
984 if (had_process_ringbuf(substream, intelhaddata) < 0)
985 snd_pcm_stop_xrun(substream);
986 else
987 snd_pcm_period_elapsed(substream);
988
989 out:
990 had_substream_put(intelhaddata);
991}
992
993/*
994 * The interrupt status 'sticky' bits might not be cleared by
995 * setting '1' to that bit once...
996 */
997static void wait_clear_underrun_bit(struct snd_intelhad *intelhaddata)
998{
999 int i;
1000 u32 val;
1001
1002 for (i = 0; i < 100; i++) {
1003 /* clear bit30, 31 AUD_HDMI_STATUS */
1004 had_read_register(intelhaddata, AUD_HDMI_STATUS, &val);
1005 if (!(val & AUD_HDMI_STATUS_MASK_UNDERRUN))
1006 return;
1007 udelay(100);
1008 cond_resched();
1009 had_write_register(intelhaddata, AUD_HDMI_STATUS, val);
1010 }
1011 dev_err(intelhaddata->dev, "Unable to clear UNDERRUN bits\n");
1012}
1013
1014/* Perform some reset procedure but only when need_reset is set;
1015 * this is called from prepare or hw_free callbacks once after trigger STOP
1016 * or underrun has been processed in order to settle down the h/w state.
1017 */
1018static void had_do_reset(struct snd_intelhad *intelhaddata)
1019{
1020 if (!intelhaddata->need_reset || !intelhaddata->connected)
1021 return;
1022
1023 /* Reset buffer pointers */
1024 had_reset_audio(intelhaddata);
1025 wait_clear_underrun_bit(intelhaddata);
1026 intelhaddata->need_reset = false;
1027}
1028
1029/* called from irq handler */
1030static void had_process_buffer_underrun(struct snd_intelhad *intelhaddata)
1031{
1032 struct snd_pcm_substream *substream;
1033
1034 /* Report UNDERRUN error to above layers */
1035 substream = had_substream_get(intelhaddata);
1036 if (substream) {
1037 snd_pcm_stop_xrun(substream);
1038 had_substream_put(intelhaddata);
1039 }
1040 intelhaddata->need_reset = true;
1041}
1042
1043/*
1044 * ALSA PCM open callback
1045 */
1046static int had_pcm_open(struct snd_pcm_substream *substream)
1047{
1048 struct snd_intelhad *intelhaddata;
1049 struct snd_pcm_runtime *runtime;
1050 int retval;
1051
1052 intelhaddata = snd_pcm_substream_chip(substream);
1053 runtime = substream->runtime;
1054
1055 pm_runtime_get_sync(intelhaddata->dev);
1056
1057 /* set the runtime hw parameter with local snd_pcm_hardware struct */
1058 runtime->hw = had_pcm_hardware;
1059
1060 retval = snd_pcm_hw_constraint_integer(runtime,
1061 SNDRV_PCM_HW_PARAM_PERIODS);
1062 if (retval < 0)
1063 goto error;
1064
1065 /* Make sure, that the period size is always aligned
1066 * 64byte boundary
1067 */
1068 retval = snd_pcm_hw_constraint_step(substream->runtime, 0,
1069 SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64);
1070 if (retval < 0)
1071 goto error;
1072
1073 retval = snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
1074 if (retval < 0)
1075 goto error;
1076
1077 /* expose PCM substream */
1078 spin_lock_irq(&intelhaddata->had_spinlock);
1079 intelhaddata->stream_info.substream = substream;
1080 intelhaddata->stream_info.substream_refcount++;
1081 spin_unlock_irq(&intelhaddata->had_spinlock);
1082
1083 return retval;
1084 error:
1085 pm_runtime_put(intelhaddata->dev);
1086 return retval;
1087}
1088
1089/*
1090 * ALSA PCM close callback
1091 */
1092static int had_pcm_close(struct snd_pcm_substream *substream)
1093{
1094 struct snd_intelhad *intelhaddata;
1095
1096 intelhaddata = snd_pcm_substream_chip(substream);
1097
1098 /* unreference and sync with the pending PCM accesses */
1099 spin_lock_irq(&intelhaddata->had_spinlock);
1100 intelhaddata->stream_info.substream = NULL;
1101 intelhaddata->stream_info.substream_refcount--;
1102 while (intelhaddata->stream_info.substream_refcount > 0) {
1103 spin_unlock_irq(&intelhaddata->had_spinlock);
1104 cpu_relax();
1105 spin_lock_irq(&intelhaddata->had_spinlock);
1106 }
1107 spin_unlock_irq(&intelhaddata->had_spinlock);
1108
1109 pm_runtime_put(intelhaddata->dev);
1110 return 0;
1111}
1112
1113/*
1114 * ALSA PCM hw_params callback
1115 */
1116static int had_pcm_hw_params(struct snd_pcm_substream *substream,
1117 struct snd_pcm_hw_params *hw_params)
1118{
1119 struct snd_intelhad *intelhaddata;
1120 unsigned long addr;
1121 int pages, buf_size, retval;
1122
1123 intelhaddata = snd_pcm_substream_chip(substream);
1124 buf_size = params_buffer_bytes(hw_params);
1125 retval = snd_pcm_lib_malloc_pages(substream, buf_size);
1126 if (retval < 0)
1127 return retval;
1128 dev_dbg(intelhaddata->dev, "%s:allocated memory = %d\n",
1129 __func__, buf_size);
1130 /* mark the pages as uncached region */
1131 addr = (unsigned long) substream->runtime->dma_area;
1132 pages = (substream->runtime->dma_bytes + PAGE_SIZE - 1) / PAGE_SIZE;
1133 retval = set_memory_uc(addr, pages);
1134 if (retval) {
1135 dev_err(intelhaddata->dev, "set_memory_uc failed.Error:%d\n",
1136 retval);
1137 return retval;
1138 }
1139 memset(substream->runtime->dma_area, 0, buf_size);
1140
1141 return retval;
1142}
1143
1144/*
1145 * ALSA PCM hw_free callback
1146 */
1147static int had_pcm_hw_free(struct snd_pcm_substream *substream)
1148{
1149 struct snd_intelhad *intelhaddata;
1150 unsigned long addr;
1151 u32 pages;
1152
1153 intelhaddata = snd_pcm_substream_chip(substream);
1154 had_do_reset(intelhaddata);
1155
1156 /* mark back the pages as cached/writeback region before the free */
1157 if (substream->runtime->dma_area != NULL) {
1158 addr = (unsigned long) substream->runtime->dma_area;
1159 pages = (substream->runtime->dma_bytes + PAGE_SIZE - 1) /
1160 PAGE_SIZE;
1161 set_memory_wb(addr, pages);
1162 return snd_pcm_lib_free_pages(substream);
1163 }
1164 return 0;
1165}
1166
1167/*
1168 * ALSA PCM trigger callback
1169 */
1170static int had_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
1171{
1172 int retval = 0;
1173 struct snd_intelhad *intelhaddata;
1174
1175 intelhaddata = snd_pcm_substream_chip(substream);
1176
1177 spin_lock(&intelhaddata->had_spinlock);
1178 switch (cmd) {
1179 case SNDRV_PCM_TRIGGER_START:
1180 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
1181 case SNDRV_PCM_TRIGGER_RESUME:
1182 /* Enable Audio */
1183 had_ack_irqs(intelhaddata); /* FIXME: do we need this? */
1184 had_enable_audio(intelhaddata, true);
1185 break;
1186
1187 case SNDRV_PCM_TRIGGER_STOP:
1188 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
1189 /* Disable Audio */
1190 had_enable_audio(intelhaddata, false);
1191 intelhaddata->need_reset = true;
1192 break;
1193
1194 default:
1195 retval = -EINVAL;
1196 }
1197 spin_unlock(&intelhaddata->had_spinlock);
1198 return retval;
1199}
1200
1201/*
1202 * ALSA PCM prepare callback
1203 */
1204static int had_pcm_prepare(struct snd_pcm_substream *substream)
1205{
1206 int retval;
1207 u32 disp_samp_freq, n_param;
1208 u32 link_rate = 0;
1209 struct snd_intelhad *intelhaddata;
1210 struct snd_pcm_runtime *runtime;
1211
1212 intelhaddata = snd_pcm_substream_chip(substream);
1213 runtime = substream->runtime;
1214
1215 dev_dbg(intelhaddata->dev, "period_size=%d\n",
1216 (int)frames_to_bytes(runtime, runtime->period_size));
1217 dev_dbg(intelhaddata->dev, "periods=%d\n", runtime->periods);
1218 dev_dbg(intelhaddata->dev, "buffer_size=%d\n",
1219 (int)snd_pcm_lib_buffer_bytes(substream));
1220 dev_dbg(intelhaddata->dev, "rate=%d\n", runtime->rate);
1221 dev_dbg(intelhaddata->dev, "channels=%d\n", runtime->channels);
1222
1223 had_do_reset(intelhaddata);
1224
1225 /* Get N value in KHz */
1226 disp_samp_freq = intelhaddata->tmds_clock_speed;
1227
1228 retval = had_prog_n(substream->runtime->rate, &n_param, intelhaddata);
1229 if (retval) {
1230 dev_err(intelhaddata->dev,
1231 "programming N value failed %#x\n", retval);
1232 goto prep_end;
1233 }
1234
1235 if (intelhaddata->dp_output)
1236 link_rate = intelhaddata->link_rate;
1237
1238 had_prog_cts(substream->runtime->rate, disp_samp_freq, link_rate,
1239 n_param, intelhaddata);
1240
1241 had_prog_dip(substream, intelhaddata);
1242
1243 retval = had_init_audio_ctrl(substream, intelhaddata);
1244
1245 /* Prog buffer address */
1246 had_init_ringbuf(substream, intelhaddata);
1247
1248 /*
1249 * Program channel mapping in following order:
1250 * FL, FR, C, LFE, RL, RR
1251 */
1252
1253 had_write_register(intelhaddata, AUD_BUF_CH_SWAP, SWAP_LFE_CENTER);
1254
1255prep_end:
1256 return retval;
1257}
1258
1259/*
1260 * ALSA PCM pointer callback
1261 */
1262static snd_pcm_uframes_t had_pcm_pointer(struct snd_pcm_substream *substream)
1263{
1264 struct snd_intelhad *intelhaddata;
1265 int len;
1266
1267 intelhaddata = snd_pcm_substream_chip(substream);
1268
1269 if (!intelhaddata->connected)
1270 return SNDRV_PCM_POS_XRUN;
1271
1272 len = had_process_ringbuf(substream, intelhaddata);
1273 if (len < 0)
1274 return SNDRV_PCM_POS_XRUN;
1275 len = bytes_to_frames(substream->runtime, len);
1276 /* wrapping may happen when periods=1 */
1277 len %= substream->runtime->buffer_size;
1278 return len;
1279}
1280
1281/*
1282 * ALSA PCM mmap callback
1283 */
1284static int had_pcm_mmap(struct snd_pcm_substream *substream,
1285 struct vm_area_struct *vma)
1286{
1287 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
1288 return remap_pfn_range(vma, vma->vm_start,
1289 substream->dma_buffer.addr >> PAGE_SHIFT,
1290 vma->vm_end - vma->vm_start, vma->vm_page_prot);
1291}
1292
1293/*
1294 * ALSA PCM ops
1295 */
1296static const struct snd_pcm_ops had_pcm_ops = {
1297 .open = had_pcm_open,
1298 .close = had_pcm_close,
1299 .ioctl = snd_pcm_lib_ioctl,
1300 .hw_params = had_pcm_hw_params,
1301 .hw_free = had_pcm_hw_free,
1302 .prepare = had_pcm_prepare,
1303 .trigger = had_pcm_trigger,
1304 .pointer = had_pcm_pointer,
1305 .mmap = had_pcm_mmap,
1306};
1307
1308/* process mode change of the running stream; called in mutex */
1309static int had_process_mode_change(struct snd_intelhad *intelhaddata)
1310{
1311 struct snd_pcm_substream *substream;
1312 int retval = 0;
1313 u32 disp_samp_freq, n_param;
1314 u32 link_rate = 0;
1315
1316 substream = had_substream_get(intelhaddata);
1317 if (!substream)
1318 return 0;
1319
1320 /* Disable Audio */
1321 had_enable_audio(intelhaddata, false);
1322
1323 /* Update CTS value */
1324 disp_samp_freq = intelhaddata->tmds_clock_speed;
1325
1326 retval = had_prog_n(substream->runtime->rate, &n_param, intelhaddata);
1327 if (retval) {
1328 dev_err(intelhaddata->dev,
1329 "programming N value failed %#x\n", retval);
1330 goto out;
1331 }
1332
1333 if (intelhaddata->dp_output)
1334 link_rate = intelhaddata->link_rate;
1335
1336 had_prog_cts(substream->runtime->rate, disp_samp_freq, link_rate,
1337 n_param, intelhaddata);
1338
1339 /* Enable Audio */
1340 had_enable_audio(intelhaddata, true);
1341
1342out:
1343 had_substream_put(intelhaddata);
1344 return retval;
1345}
1346
1347/* process hot plug, called from wq with mutex locked */
1348static void had_process_hot_plug(struct snd_intelhad *intelhaddata)
1349{
1350 struct snd_pcm_substream *substream;
1351
1352 spin_lock_irq(&intelhaddata->had_spinlock);
1353 if (intelhaddata->connected) {
1354 dev_dbg(intelhaddata->dev, "Device already connected\n");
1355 spin_unlock_irq(&intelhaddata->had_spinlock);
1356 return;
1357 }
1358
1359 intelhaddata->connected = true;
1360 dev_dbg(intelhaddata->dev,
1361 "%s @ %d:DEBUG PLUG/UNPLUG : HAD_DRV_CONNECTED\n",
1362 __func__, __LINE__);
1363 spin_unlock_irq(&intelhaddata->had_spinlock);
1364
1365 had_build_channel_allocation_map(intelhaddata);
1366
1367 /* Report to above ALSA layer */
1368 substream = had_substream_get(intelhaddata);
1369 if (substream) {
1370 snd_pcm_stop_xrun(substream);
1371 had_substream_put(intelhaddata);
1372 }
1373
1374 snd_jack_report(intelhaddata->jack, SND_JACK_AVOUT);
1375}
1376
1377/* process hot unplug, called from wq with mutex locked */
1378static void had_process_hot_unplug(struct snd_intelhad *intelhaddata)
1379{
1380 struct snd_pcm_substream *substream;
1381
1382 spin_lock_irq(&intelhaddata->had_spinlock);
1383 if (!intelhaddata->connected) {
1384 dev_dbg(intelhaddata->dev, "Device already disconnected\n");
1385 spin_unlock_irq(&intelhaddata->had_spinlock);
1386 return;
1387
1388 }
1389
1390 /* Disable Audio */
1391 had_enable_audio(intelhaddata, false);
1392
1393 intelhaddata->connected = false;
1394 dev_dbg(intelhaddata->dev,
1395 "%s @ %d:DEBUG PLUG/UNPLUG : HAD_DRV_DISCONNECTED\n",
1396 __func__, __LINE__);
1397 spin_unlock_irq(&intelhaddata->had_spinlock);
1398
1399 kfree(intelhaddata->chmap->chmap);
1400 intelhaddata->chmap->chmap = NULL;
1401
1402 /* Report to above ALSA layer */
1403 substream = had_substream_get(intelhaddata);
1404 if (substream) {
1405 snd_pcm_stop_xrun(substream);
1406 had_substream_put(intelhaddata);
1407 }
1408
1409 snd_jack_report(intelhaddata->jack, 0);
1410}
1411
1412/*
1413 * ALSA iec958 and ELD controls
1414 */
1415
1416static int had_iec958_info(struct snd_kcontrol *kcontrol,
1417 struct snd_ctl_elem_info *uinfo)
1418{
1419 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1420 uinfo->count = 1;
1421 return 0;
1422}
1423
1424static int had_iec958_get(struct snd_kcontrol *kcontrol,
1425 struct snd_ctl_elem_value *ucontrol)
1426{
1427 struct snd_intelhad *intelhaddata = snd_kcontrol_chip(kcontrol);
1428
1429 mutex_lock(&intelhaddata->mutex);
1430 ucontrol->value.iec958.status[0] = (intelhaddata->aes_bits >> 0) & 0xff;
1431 ucontrol->value.iec958.status[1] = (intelhaddata->aes_bits >> 8) & 0xff;
1432 ucontrol->value.iec958.status[2] =
1433 (intelhaddata->aes_bits >> 16) & 0xff;
1434 ucontrol->value.iec958.status[3] =
1435 (intelhaddata->aes_bits >> 24) & 0xff;
1436 mutex_unlock(&intelhaddata->mutex);
1437 return 0;
1438}
1439
1440static int had_iec958_mask_get(struct snd_kcontrol *kcontrol,
1441 struct snd_ctl_elem_value *ucontrol)
1442{
1443 ucontrol->value.iec958.status[0] = 0xff;
1444 ucontrol->value.iec958.status[1] = 0xff;
1445 ucontrol->value.iec958.status[2] = 0xff;
1446 ucontrol->value.iec958.status[3] = 0xff;
1447 return 0;
1448}
1449
1450static int had_iec958_put(struct snd_kcontrol *kcontrol,
1451 struct snd_ctl_elem_value *ucontrol)
1452{
1453 unsigned int val;
1454 struct snd_intelhad *intelhaddata = snd_kcontrol_chip(kcontrol);
1455 int changed = 0;
1456
1457 val = (ucontrol->value.iec958.status[0] << 0) |
1458 (ucontrol->value.iec958.status[1] << 8) |
1459 (ucontrol->value.iec958.status[2] << 16) |
1460 (ucontrol->value.iec958.status[3] << 24);
1461 mutex_lock(&intelhaddata->mutex);
1462 if (intelhaddata->aes_bits != val) {
1463 intelhaddata->aes_bits = val;
1464 changed = 1;
1465 }
1466 mutex_unlock(&intelhaddata->mutex);
1467 return changed;
1468}
1469
1470static int had_ctl_eld_info(struct snd_kcontrol *kcontrol,
1471 struct snd_ctl_elem_info *uinfo)
1472{
1473 uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
1474 uinfo->count = HDMI_MAX_ELD_BYTES;
1475 return 0;
1476}
1477
1478static int had_ctl_eld_get(struct snd_kcontrol *kcontrol,
1479 struct snd_ctl_elem_value *ucontrol)
1480{
1481 struct snd_intelhad *intelhaddata = snd_kcontrol_chip(kcontrol);
1482
1483 mutex_lock(&intelhaddata->mutex);
1484 memcpy(ucontrol->value.bytes.data, intelhaddata->eld,
1485 HDMI_MAX_ELD_BYTES);
1486 mutex_unlock(&intelhaddata->mutex);
1487 return 0;
1488}
1489
1490static const struct snd_kcontrol_new had_controls[] = {
1491 {
1492 .access = SNDRV_CTL_ELEM_ACCESS_READ,
1493 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1494 .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, MASK),
1495 .info = had_iec958_info, /* shared */
1496 .get = had_iec958_mask_get,
1497 },
1498 {
1499 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1500 .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
1501 .info = had_iec958_info,
1502 .get = had_iec958_get,
1503 .put = had_iec958_put,
1504 },
1505 {
1506 .access = (SNDRV_CTL_ELEM_ACCESS_READ |
1507 SNDRV_CTL_ELEM_ACCESS_VOLATILE),
1508 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1509 .name = "ELD",
1510 .info = had_ctl_eld_info,
1511 .get = had_ctl_eld_get,
1512 },
1513};
1514
1515/*
1516 * audio interrupt handler
1517 */
1518static irqreturn_t display_pipe_interrupt_handler(int irq, void *dev_id)
1519{
1520 struct snd_intelhad *ctx = dev_id;
1521 u32 audio_stat;
1522
1523 /* use raw register access to ack IRQs even while disconnected */
1524 audio_stat = had_read_register_raw(ctx, AUD_HDMI_STATUS);
1525
1526 if (audio_stat & HDMI_AUDIO_UNDERRUN) {
1527 had_write_register_raw(ctx, AUD_HDMI_STATUS,
1528 HDMI_AUDIO_UNDERRUN);
1529 had_process_buffer_underrun(ctx);
1530 }
1531
1532 if (audio_stat & HDMI_AUDIO_BUFFER_DONE) {
1533 had_write_register_raw(ctx, AUD_HDMI_STATUS,
1534 HDMI_AUDIO_BUFFER_DONE);
1535 had_process_buffer_done(ctx);
1536 }
1537
1538 return IRQ_HANDLED;
1539}
1540
1541/*
1542 * monitor plug/unplug notification from i915; just kick off the work
1543 */
1544static void notify_audio_lpe(struct platform_device *pdev)
1545{
1546 struct snd_intelhad *ctx = platform_get_drvdata(pdev);
1547
1548 schedule_work(&ctx->hdmi_audio_wq);
1549}
1550
1551/* the work to handle monitor hot plug/unplug */
1552static void had_audio_wq(struct work_struct *work)
1553{
1554 struct snd_intelhad *ctx =
1555 container_of(work, struct snd_intelhad, hdmi_audio_wq);
1556 struct intel_hdmi_lpe_audio_pdata *pdata = ctx->dev->platform_data;
1557
1558 pm_runtime_get_sync(ctx->dev);
1559 mutex_lock(&ctx->mutex);
1560 if (!pdata->hdmi_connected) {
1561 dev_dbg(ctx->dev, "%s: Event: HAD_NOTIFY_HOT_UNPLUG\n",
1562 __func__);
1563 memset(ctx->eld, 0, sizeof(ctx->eld)); /* clear the old ELD */
1564 had_process_hot_unplug(ctx);
1565 } else {
1566 struct intel_hdmi_lpe_audio_eld *eld = &pdata->eld;
1567
1568 dev_dbg(ctx->dev, "%s: HAD_NOTIFY_ELD : port = %d, tmds = %d\n",
1569 __func__, eld->port_id, pdata->tmds_clock_speed);
1570
1571 switch (eld->pipe_id) {
1572 case 0:
1573 ctx->had_config_offset = AUDIO_HDMI_CONFIG_A;
1574 break;
1575 case 1:
1576 ctx->had_config_offset = AUDIO_HDMI_CONFIG_B;
1577 break;
1578 case 2:
1579 ctx->had_config_offset = AUDIO_HDMI_CONFIG_C;
1580 break;
1581 default:
1582 dev_dbg(ctx->dev, "Invalid pipe %d\n",
1583 eld->pipe_id);
1584 break;
1585 }
1586
1587 memcpy(ctx->eld, eld->eld_data, sizeof(ctx->eld));
1588
1589 ctx->dp_output = pdata->dp_output;
1590 ctx->tmds_clock_speed = pdata->tmds_clock_speed;
1591 ctx->link_rate = pdata->link_rate;
1592
1593 had_process_hot_plug(ctx);
1594
1595 /* Process mode change if stream is active */
1596 had_process_mode_change(ctx);
1597 }
1598 mutex_unlock(&ctx->mutex);
1599 pm_runtime_put(ctx->dev);
1600}
1601
1602/*
1603 * Jack interface
1604 */
1605static int had_create_jack(struct snd_intelhad *ctx)
1606{
1607 int err;
1608
1609 err = snd_jack_new(ctx->card, "HDMI/DP", SND_JACK_AVOUT, &ctx->jack,
1610 true, false);
1611 if (err < 0)
1612 return err;
1613 ctx->jack->private_data = ctx;
1614 return 0;
1615}
1616
1617/*
1618 * PM callbacks
1619 */
1620
1621static int hdmi_lpe_audio_runtime_suspend(struct device *dev)
1622{
1623 struct snd_intelhad *ctx = dev_get_drvdata(dev);
1624 struct snd_pcm_substream *substream;
1625
1626 substream = had_substream_get(ctx);
1627 if (substream) {
1628 snd_pcm_suspend(substream);
1629 had_substream_put(ctx);
1630 }
1631
1632 return 0;
1633}
1634
1635static int __maybe_unused hdmi_lpe_audio_suspend(struct device *dev)
1636{
1637 struct snd_intelhad *ctx = dev_get_drvdata(dev);
1638 int err;
1639
1640 err = hdmi_lpe_audio_runtime_suspend(dev);
1641 if (!err)
1642 snd_power_change_state(ctx->card, SNDRV_CTL_POWER_D3hot);
1643 return err;
1644}
1645
1646static int __maybe_unused hdmi_lpe_audio_resume(struct device *dev)
1647{
1648 struct snd_intelhad *ctx = dev_get_drvdata(dev);
1649
1650 snd_power_change_state(ctx->card, SNDRV_CTL_POWER_D0);
1651 return 0;
1652}
1653
1654/* release resources */
1655static void hdmi_lpe_audio_free(struct snd_card *card)
1656{
1657 struct snd_intelhad *ctx = card->private_data;
1658
1659 cancel_work_sync(&ctx->hdmi_audio_wq);
1660
1661 if (ctx->mmio_start)
1662 iounmap(ctx->mmio_start);
1663 if (ctx->irq >= 0)
1664 free_irq(ctx->irq, ctx);
1665}
1666
1667/*
1668 * hdmi_lpe_audio_probe - start bridge with i915
1669 *
1670 * This function is called when the i915 driver creates the
1671 * hdmi-lpe-audio platform device.
1672 */
1673static int hdmi_lpe_audio_probe(struct platform_device *pdev)
1674{
1675 struct snd_card *card;
1676 struct snd_intelhad *ctx;
1677 struct snd_pcm *pcm;
1678 struct intel_hdmi_lpe_audio_pdata *pdata;
1679 int irq;
1680 struct resource *res_mmio;
1681 int i, ret;
1682
1683 pdata = pdev->dev.platform_data;
1684 if (!pdata) {
1685 dev_err(&pdev->dev, "%s: quit: pdata not allocated by i915!!\n", __func__);
1686 return -EINVAL;
1687 }
1688
1689 /* get resources */
1690 irq = platform_get_irq(pdev, 0);
1691 if (irq < 0) {
1692 dev_err(&pdev->dev, "Could not get irq resource\n");
1693 return -ENODEV;
1694 }
1695
1696 res_mmio = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1697 if (!res_mmio) {
1698 dev_err(&pdev->dev, "Could not get IO_MEM resources\n");
1699 return -ENXIO;
1700 }
1701
1702 /* create a card instance with ALSA framework */
1703 ret = snd_card_new(&pdev->dev, hdmi_card_index, hdmi_card_id,
1704 THIS_MODULE, sizeof(*ctx), &card);
1705 if (ret)
1706 return ret;
1707
1708 ctx = card->private_data;
1709 spin_lock_init(&ctx->had_spinlock);
1710 mutex_init(&ctx->mutex);
1711 ctx->connected = false;
1712 ctx->dev = &pdev->dev;
1713 ctx->card = card;
1714 ctx->aes_bits = SNDRV_PCM_DEFAULT_CON_SPDIF;
1715 strcpy(card->driver, INTEL_HAD);
1716 strcpy(card->shortname, "Intel HDMI/DP LPE Audio");
1717 strcpy(card->longname, "Intel HDMI/DP LPE Audio");
1718
1719 ctx->irq = -1;
1720 ctx->tmds_clock_speed = DIS_SAMPLE_RATE_148_5;
1721 INIT_WORK(&ctx->hdmi_audio_wq, had_audio_wq);
1722
1723 card->private_free = hdmi_lpe_audio_free;
1724
1725 /* assume pipe A as default */
1726 ctx->had_config_offset = AUDIO_HDMI_CONFIG_A;
1727
1728 platform_set_drvdata(pdev, ctx);
1729
1730 dev_dbg(&pdev->dev, "%s: mmio_start = 0x%x, mmio_end = 0x%x\n",
1731 __func__, (unsigned int)res_mmio->start,
1732 (unsigned int)res_mmio->end);
1733
1734 ctx->mmio_start = ioremap_nocache(res_mmio->start,
1735 (size_t)(resource_size(res_mmio)));
1736 if (!ctx->mmio_start) {
1737 dev_err(&pdev->dev, "Could not get ioremap\n");
1738 ret = -EACCES;
1739 goto err;
1740 }
1741
1742 /* setup interrupt handler */
1743 ret = request_irq(irq, display_pipe_interrupt_handler, 0,
1744 pdev->name, ctx);
1745 if (ret < 0) {
1746 dev_err(&pdev->dev, "request_irq failed\n");
1747 goto err;
1748 }
1749
1750 ctx->irq = irq;
1751
1752 ret = snd_pcm_new(card, INTEL_HAD, PCM_INDEX, MAX_PB_STREAMS,
1753 MAX_CAP_STREAMS, &pcm);
1754 if (ret)
1755 goto err;
1756
1757 /* setup private data which can be retrieved when required */
1758 pcm->private_data = ctx;
1759 pcm->info_flags = 0;
1760 strncpy(pcm->name, card->shortname, strlen(card->shortname));
1761 /* setup the ops for playabck */
1762 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &had_pcm_ops);
1763
1764 /* only 32bit addressable */
1765 dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
1766 dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
1767
1768 /* allocate dma pages;
1769 * try to allocate 600k buffer as default which is large enough
1770 */
1771 snd_pcm_lib_preallocate_pages_for_all(pcm,
1772 SNDRV_DMA_TYPE_DEV, NULL,
1773 HAD_DEFAULT_BUFFER, HAD_MAX_BUFFER);
1774
1775 /* create controls */
1776 for (i = 0; i < ARRAY_SIZE(had_controls); i++) {
1777 ret = snd_ctl_add(card, snd_ctl_new1(&had_controls[i], ctx));
1778 if (ret < 0)
1779 goto err;
1780 }
1781
1782 init_channel_allocations();
1783
1784 /* Register channel map controls */
1785 ret = had_register_chmap_ctls(ctx, pcm);
1786 if (ret < 0)
1787 goto err;
1788
1789 ret = had_create_jack(ctx);
1790 if (ret < 0)
1791 goto err;
1792
1793 ret = snd_card_register(card);
1794 if (ret)
1795 goto err;
1796
1797 spin_lock_irq(&pdata->lpe_audio_slock);
1798 pdata->notify_audio_lpe = notify_audio_lpe;
1799 pdata->notify_pending = false;
1800 spin_unlock_irq(&pdata->lpe_audio_slock);
1801
1802 pm_runtime_set_active(&pdev->dev);
1803 pm_runtime_enable(&pdev->dev);
1804
1805 dev_dbg(&pdev->dev, "%s: handle pending notification\n", __func__);
1806 schedule_work(&ctx->hdmi_audio_wq);
1807
1808 return 0;
1809
1810err:
1811 snd_card_free(card);
1812 return ret;
1813}
1814
1815/*
1816 * hdmi_lpe_audio_remove - stop bridge with i915
1817 *
1818 * This function is called when the platform device is destroyed.
1819 */
1820static int hdmi_lpe_audio_remove(struct platform_device *pdev)
1821{
1822 struct snd_intelhad *ctx = platform_get_drvdata(pdev);
1823
1824 snd_card_free(ctx->card);
1825 return 0;
1826}
1827
1828static const struct dev_pm_ops hdmi_lpe_audio_pm = {
1829 SET_SYSTEM_SLEEP_PM_OPS(hdmi_lpe_audio_suspend, hdmi_lpe_audio_resume)
1830 SET_RUNTIME_PM_OPS(hdmi_lpe_audio_runtime_suspend, NULL, NULL)
1831};
1832
1833static struct platform_driver hdmi_lpe_audio_driver = {
1834 .driver = {
1835 .name = "hdmi-lpe-audio",
1836 .pm = &hdmi_lpe_audio_pm,
1837 },
1838 .probe = hdmi_lpe_audio_probe,
1839 .remove = hdmi_lpe_audio_remove,
1840};
1841
1842module_platform_driver(hdmi_lpe_audio_driver);
1843MODULE_ALIAS("platform:hdmi_lpe_audio");
1844
1845MODULE_AUTHOR("Sailaja Bandarupalli <sailaja.bandarupalli@intel.com>");
1846MODULE_AUTHOR("Ramesh Babu K V <ramesh.babu@intel.com>");
1847MODULE_AUTHOR("Vaibhav Agarwal <vaibhav.agarwal@intel.com>");
1848MODULE_AUTHOR("Jerome Anand <jerome.anand@intel.com>");
1849MODULE_DESCRIPTION("Intel HDMI Audio driver");
1850MODULE_LICENSE("GPL v2");
1851MODULE_SUPPORTED_DEVICE("{Intel,Intel_HAD}");
diff --git a/sound/x86/intel_hdmi_audio.h b/sound/x86/intel_hdmi_audio.h
new file mode 100644
index 000000000000..2d3e389f76b3
--- /dev/null
+++ b/sound/x86/intel_hdmi_audio.h
@@ -0,0 +1,136 @@
1/*
2 * Copyright (C) 2016 Intel Corporation
3 * Authors: Sailaja Bandarupalli <sailaja.bandarupalli@intel.com>
4 * Ramesh Babu K V <ramesh.babu@intel.com>
5 * Vaibhav Agarwal <vaibhav.agarwal@intel.com>
6 * Jerome Anand <jerome.anand@intel.com>
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining
9 * a copy of this software and associated documentation files
10 * (the "Software"), to deal in the Software without restriction,
11 * including without limitation the rights to use, copy, modify, merge,
12 * publish, distribute, sublicense, and/or sell copies of the Software,
13 * and to permit persons to whom the Software is furnished to do so,
14 * subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice (including the
17 * next paragraph) shall be included in all copies or substantial
18 * portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
24 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
25 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
26 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 * SOFTWARE.
28 */
29
30#ifndef _INTEL_HDMI_AUDIO_H_
31#define _INTEL_HDMI_AUDIO_H_
32
33#include "intel_hdmi_lpe_audio.h"
34
35#define PCM_INDEX 0
36#define MAX_PB_STREAMS 1
37#define MAX_CAP_STREAMS 0
38#define BYTES_PER_WORD 0x4
39#define INTEL_HAD "HdmiLpeAudio"
40
41/*
42 * CEA speaker placement:
43 *
44 * FL FLC FC FRC FR
45 *
46 * LFE
47 *
48 * RL RLC RC RRC RR
49 *
50 * The Left/Right Surround channel _notions_ LS/RS in SMPTE 320M
51 * corresponds to CEA RL/RR; The SMPTE channel _assignment_ C/LFE is
52 * swapped to CEA LFE/FC.
53 */
54enum cea_speaker_placement {
55 FL = (1 << 0), /* Front Left */
56 FC = (1 << 1), /* Front Center */
57 FR = (1 << 2), /* Front Right */
58 FLC = (1 << 3), /* Front Left Center */
59 FRC = (1 << 4), /* Front Right Center */
60 RL = (1 << 5), /* Rear Left */
61 RC = (1 << 6), /* Rear Center */
62 RR = (1 << 7), /* Rear Right */
63 RLC = (1 << 8), /* Rear Left Center */
64 RRC = (1 << 9), /* Rear Right Center */
65 LFE = (1 << 10), /* Low Frequency Effect */
66};
67
68struct cea_channel_speaker_allocation {
69 int ca_index;
70 int speakers[8];
71
72 /* derived values, just for convenience */
73 int channels;
74 int spk_mask;
75};
76
77struct channel_map_table {
78 unsigned char map; /* ALSA API channel map position */
79 unsigned char cea_slot; /* CEA slot value */
80 int spk_mask; /* speaker position bit mask */
81};
82
83struct pcm_stream_info {
84 struct snd_pcm_substream *substream;
85 int substream_refcount;
86};
87
88/*
89 * struct snd_intelhad - intelhad driver structure
90 *
91 * @card: ptr to hold card details
92 * @connected: the monitor connection status
93 * @stream_info: stream information
94 * @eld: holds ELD info
95 * @curr_buf: pointer to hold current active ring buf
96 * @valid_buf_cnt: ring buffer count for stream
97 * @had_spinlock: driver lock
98 * @aes_bits: IEC958 status bits
99 * @buff_done: id of current buffer done intr
100 * @dev: platoform device handle
101 * @chmap: holds channel map info
102 */
103struct snd_intelhad {
104 struct snd_card *card;
105 bool connected;
106 struct pcm_stream_info stream_info;
107 unsigned char eld[HDMI_MAX_ELD_BYTES];
108 bool dp_output;
109 unsigned int aes_bits;
110 spinlock_t had_spinlock;
111 struct device *dev;
112 struct snd_pcm_chmap *chmap;
113 int tmds_clock_speed;
114 int link_rate;
115
116 /* ring buffer (BD) position index */
117 unsigned int bd_head;
118 /* PCM buffer position indices */
119 unsigned int pcmbuf_head; /* being processed */
120 unsigned int pcmbuf_filled; /* to be filled */
121
122 unsigned int num_bds; /* number of BDs */
123 unsigned int period_bytes; /* PCM period size in bytes */
124
125 /* internal stuff */
126 int irq;
127 void __iomem *mmio_start;
128 unsigned int had_config_offset;
129 union aud_cfg aud_config; /* AUD_CONFIG reg value cache */
130 struct work_struct hdmi_audio_wq;
131 struct mutex mutex; /* for protecting chmap and eld */
132 bool need_reset;
133 struct snd_jack *jack;
134};
135
136#endif /* _INTEL_HDMI_AUDIO_ */
diff --git a/sound/x86/intel_hdmi_lpe_audio.h b/sound/x86/intel_hdmi_lpe_audio.h
new file mode 100644
index 000000000000..477e5153307c
--- /dev/null
+++ b/sound/x86/intel_hdmi_lpe_audio.h
@@ -0,0 +1,328 @@
1/*
2 * intel_hdmi_lpe_audio.h - Intel HDMI LPE audio driver
3 *
4 * Copyright (C) 2016 Intel Corp
5 * Authors: Sailaja Bandarupalli <sailaja.bandarupalli@intel.com>
6 * Ramesh Babu K V <ramesh.babu@intel.com>
7 * Vaibhav Agarwal <vaibhav.agarwal@intel.com>
8 * Jerome Anand <jerome.anand@intel.com>
9 * Aravind Siddappaji <aravindx.siddappaji@intel.com>
10 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; version 2 of the License.
15 *
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
20 *
21 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
22 */
23#ifndef __INTEL_HDMI_LPE_AUDIO_H
24#define __INTEL_HDMI_LPE_AUDIO_H
25
26#define HAD_MIN_CHANNEL 2
27#define HAD_MAX_CHANNEL 8
28#define HAD_NUM_OF_RING_BUFS 4
29
30/* max 20bit address, aligned to 64 */
31#define HAD_MAX_BUFFER ((1024 * 1024 - 1) & ~0x3f)
32#define HAD_DEFAULT_BUFFER (600 * 1024) /* default prealloc size */
33#define HAD_MAX_PERIODS 256 /* arbitrary, but should suffice */
34#define HAD_MIN_PERIODS 1
35#define HAD_MAX_PERIOD_BYTES ((HAD_MAX_BUFFER / HAD_MIN_PERIODS) & ~0x3f)
36#define HAD_MIN_PERIOD_BYTES 1024 /* might be smaller */
37#define HAD_FIFO_SIZE 0 /* fifo not being used */
38#define MAX_SPEAKERS 8
39
40#define AUD_SAMPLE_RATE_32 32000
41#define AUD_SAMPLE_RATE_44_1 44100
42#define AUD_SAMPLE_RATE_48 48000
43#define AUD_SAMPLE_RATE_88_2 88200
44#define AUD_SAMPLE_RATE_96 96000
45#define AUD_SAMPLE_RATE_176_4 176400
46#define AUD_SAMPLE_RATE_192 192000
47
48#define HAD_MIN_RATE AUD_SAMPLE_RATE_32
49#define HAD_MAX_RATE AUD_SAMPLE_RATE_192
50
51#define DIS_SAMPLE_RATE_25_2 25200
52#define DIS_SAMPLE_RATE_27 27000
53#define DIS_SAMPLE_RATE_54 54000
54#define DIS_SAMPLE_RATE_74_25 74250
55#define DIS_SAMPLE_RATE_148_5 148500
56#define HAD_REG_WIDTH 0x08
57#define HAD_MAX_DIP_WORDS 16
58
59/* DP Link Rates */
60#define DP_2_7_GHZ 270000
61#define DP_1_62_GHZ 162000
62
63/* Maud Values */
64#define AUD_SAMPLE_RATE_32_DP_2_7_MAUD_VAL 1988
65#define AUD_SAMPLE_RATE_44_1_DP_2_7_MAUD_VAL 2740
66#define AUD_SAMPLE_RATE_48_DP_2_7_MAUD_VAL 2982
67#define AUD_SAMPLE_RATE_88_2_DP_2_7_MAUD_VAL 5480
68#define AUD_SAMPLE_RATE_96_DP_2_7_MAUD_VAL 5965
69#define AUD_SAMPLE_RATE_176_4_DP_2_7_MAUD_VAL 10961
70#define HAD_MAX_RATE_DP_2_7_MAUD_VAL 11930
71#define AUD_SAMPLE_RATE_32_DP_1_62_MAUD_VAL 3314
72#define AUD_SAMPLE_RATE_44_1_DP_1_62_MAUD_VAL 4567
73#define AUD_SAMPLE_RATE_48_DP_1_62_MAUD_VAL 4971
74#define AUD_SAMPLE_RATE_88_2_DP_1_62_MAUD_VAL 9134
75#define AUD_SAMPLE_RATE_96_DP_1_62_MAUD_VAL 9942
76#define AUD_SAMPLE_RATE_176_4_DP_1_62_MAUD_VAL 18268
77#define HAD_MAX_RATE_DP_1_62_MAUD_VAL 19884
78
79/* Naud Value */
80#define DP_NAUD_VAL 32768
81
82/* HDMI Controller register offsets - audio domain common */
83/* Base address for below regs = 0x65000 */
84enum hdmi_ctrl_reg_offset_common {
85 AUDIO_HDMI_CONFIG_A = 0x000,
86 AUDIO_HDMI_CONFIG_B = 0x800,
87 AUDIO_HDMI_CONFIG_C = 0x900,
88};
89/* HDMI controller register offsets */
90enum hdmi_ctrl_reg_offset {
91 AUD_CONFIG = 0x0,
92 AUD_CH_STATUS_0 = 0x08,
93 AUD_CH_STATUS_1 = 0x0C,
94 AUD_HDMI_CTS = 0x10,
95 AUD_N_ENABLE = 0x14,
96 AUD_SAMPLE_RATE = 0x18,
97 AUD_BUF_CONFIG = 0x20,
98 AUD_BUF_CH_SWAP = 0x24,
99 AUD_BUF_A_ADDR = 0x40,
100 AUD_BUF_A_LENGTH = 0x44,
101 AUD_BUF_B_ADDR = 0x48,
102 AUD_BUF_B_LENGTH = 0x4c,
103 AUD_BUF_C_ADDR = 0x50,
104 AUD_BUF_C_LENGTH = 0x54,
105 AUD_BUF_D_ADDR = 0x58,
106 AUD_BUF_D_LENGTH = 0x5c,
107 AUD_CNTL_ST = 0x60,
108 AUD_HDMI_STATUS = 0x64, /* v2 */
109 AUD_HDMIW_INFOFR = 0x68, /* v2 */
110};
111
112/* Audio configuration */
113union aud_cfg {
114 struct {
115 u32 aud_en:1;
116 u32 layout:1; /* LAYOUT[01], see below */
117 u32 fmt:2;
118 u32 num_ch:3;
119 u32 set:1;
120 u32 flat:1;
121 u32 val_bit:1;
122 u32 user_bit:1;
123 u32 underrun:1; /* 0: send null packets,
124 * 1: send silence stream
125 */
126 u32 packet_mode:1; /* 0: 32bit container, 1: 16bit */
127 u32 left_align:1; /* 0: MSB bits 0-23, 1: bits 8-31 */
128 u32 bogus_sample:1; /* bogus sample for odd channels */
129 u32 dp_modei:1; /* 0: HDMI, 1: DP */
130 u32 rsvd:16;
131 } regx;
132 u32 regval;
133};
134
135#define AUD_CONFIG_VALID_BIT (1 << 9)
136#define AUD_CONFIG_DP_MODE (1 << 15)
137#define AUD_CONFIG_CH_MASK 0x70
138#define LAYOUT0 0 /* interleaved stereo */
139#define LAYOUT1 1 /* for channels > 2 */
140
141/* Audio Channel Status 0 Attributes */
142union aud_ch_status_0 {
143 struct {
144 u32 ch_status:1;
145 u32 lpcm_id:1;
146 u32 cp_info:1;
147 u32 format:3;
148 u32 mode:2;
149 u32 ctg_code:8;
150 u32 src_num:4;
151 u32 ch_num:4;
152 u32 samp_freq:4; /* CH_STATUS_MAP_XXX */
153 u32 clk_acc:2;
154 u32 rsvd:2;
155 } regx;
156 u32 regval;
157};
158
159/* samp_freq values - Sampling rate as per IEC60958 Ver 3 */
160#define CH_STATUS_MAP_32KHZ 0x3
161#define CH_STATUS_MAP_44KHZ 0x0
162#define CH_STATUS_MAP_48KHZ 0x2
163#define CH_STATUS_MAP_88KHZ 0x8
164#define CH_STATUS_MAP_96KHZ 0xA
165#define CH_STATUS_MAP_176KHZ 0xC
166#define CH_STATUS_MAP_192KHZ 0xE
167
168/* Audio Channel Status 1 Attributes */
169union aud_ch_status_1 {
170 struct {
171 u32 max_wrd_len:1;
172 u32 wrd_len:3;
173 u32 rsvd:28;
174 } regx;
175 u32 regval;
176};
177
178#define MAX_SMPL_WIDTH_20 0x0
179#define MAX_SMPL_WIDTH_24 0x1
180#define SMPL_WIDTH_16BITS 0x1
181#define SMPL_WIDTH_24BITS 0x5
182
183/* CTS register */
184union aud_hdmi_cts {
185 struct {
186 u32 cts_val:24;
187 u32 en_cts_prog:1;
188 u32 rsvd:7;
189 } regx;
190 u32 regval;
191};
192
193/* N register */
194union aud_hdmi_n_enable {
195 struct {
196 u32 n_val:24;
197 u32 en_n_prog:1;
198 u32 rsvd:7;
199 } regx;
200 u32 regval;
201};
202
203/* Audio Buffer configurations */
204union aud_buf_config {
205 struct {
206 u32 audio_fifo_watermark:8;
207 u32 dma_fifo_watermark:3;
208 u32 rsvd0:5;
209 u32 aud_delay:8;
210 u32 rsvd1:8;
211 } regx;
212 u32 regval;
213};
214
215#define FIFO_THRESHOLD 0xFE
216#define DMA_FIFO_THRESHOLD 0x7
217
218/* Audio Sample Swapping offset */
219union aud_buf_ch_swap {
220 struct {
221 u32 first_0:3;
222 u32 second_0:3;
223 u32 first_1:3;
224 u32 second_1:3;
225 u32 first_2:3;
226 u32 second_2:3;
227 u32 first_3:3;
228 u32 second_3:3;
229 u32 rsvd:8;
230 } regx;
231 u32 regval;
232};
233
234#define SWAP_LFE_CENTER 0x00fac4c8 /* octal 76543210 */
235
236/* Address for Audio Buffer */
237union aud_buf_addr {
238 struct {
239 u32 valid:1;
240 u32 intr_en:1;
241 u32 rsvd:4;
242 u32 addr:26;
243 } regx;
244 u32 regval;
245};
246
247#define AUD_BUF_VALID (1U << 0)
248#define AUD_BUF_INTR_EN (1U << 1)
249
250/* Length of Audio Buffer */
251union aud_buf_len {
252 struct {
253 u32 buf_len:20;
254 u32 rsvd:12;
255 } regx;
256 u32 regval;
257};
258
259/* Audio Control State Register offset */
260union aud_ctrl_st {
261 struct {
262 u32 ram_addr:4;
263 u32 eld_ack:1;
264 u32 eld_addr:4;
265 u32 eld_buf_size:5;
266 u32 eld_valid:1;
267 u32 cp_ready:1;
268 u32 dip_freq:2;
269 u32 dip_idx:3;
270 u32 dip_en_sta:4;
271 u32 rsvd:7;
272 } regx;
273 u32 regval;
274};
275
276/* Audio HDMI Widget Data Island Packet offset */
277union aud_info_frame1 {
278 struct {
279 u32 pkt_type:8;
280 u32 ver_num:8;
281 u32 len:5;
282 u32 rsvd:11;
283 } regx;
284 u32 regval;
285};
286
287#define HDMI_INFO_FRAME_WORD1 0x000a0184
288#define DP_INFO_FRAME_WORD1 0x00441b84
289
290/* DIP frame 2 */
291union aud_info_frame2 {
292 struct {
293 u32 chksum:8;
294 u32 chnl_cnt:3;
295 u32 rsvd0:1;
296 u32 coding_type:4;
297 u32 smpl_size:2;
298 u32 smpl_freq:3;
299 u32 rsvd1:3;
300 u32 format:8;
301 } regx;
302 u32 regval;
303};
304
305/* DIP frame 3 */
306union aud_info_frame3 {
307 struct {
308 u32 chnl_alloc:8;
309 u32 rsvd0:3;
310 u32 lsv:4;
311 u32 dm_inh:1;
312 u32 rsvd1:16;
313 } regx;
314 u32 regval;
315};
316
317#define VALID_DIP_WORDS 3
318
319/* AUD_HDMI_STATUS bits */
320#define HDMI_AUDIO_UNDERRUN (1U << 31)
321#define HDMI_AUDIO_BUFFER_DONE (1U << 29)
322
323/* AUD_HDMI_STATUS register mask */
324#define AUD_HDMI_STATUS_MASK_UNDERRUN 0xC0000000
325#define AUD_HDMI_STATUS_MASK_SRDBG 0x00000002
326#define AUD_HDMI_STATUSG_MASK_FUNCRST 0x00000001
327
328#endif