diff options
Diffstat (limited to 'sound')
87 files changed, 10420 insertions, 971 deletions
diff --git a/sound/aoa/codecs/onyx.c b/sound/aoa/codecs/onyx.c index f01bffb702bc..401107b85d30 100644 --- a/sound/aoa/codecs/onyx.c +++ b/sound/aoa/codecs/onyx.c | |||
@@ -241,7 +241,7 @@ static struct snd_kcontrol_new inputgain_control = { | |||
241 | static int onyx_snd_capture_source_info(struct snd_kcontrol *kcontrol, | 241 | static int onyx_snd_capture_source_info(struct snd_kcontrol *kcontrol, |
242 | struct snd_ctl_elem_info *uinfo) | 242 | struct snd_ctl_elem_info *uinfo) |
243 | { | 243 | { |
244 | static char *texts[] = { "Line-In", "Microphone" }; | 244 | static const char * const texts[] = { "Line-In", "Microphone" }; |
245 | 245 | ||
246 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 246 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
247 | uinfo->count = 1; | 247 | uinfo->count = 1; |
diff --git a/sound/atmel/ac97c.c b/sound/atmel/ac97c.c index 05ec049c9faf..a04d23174dc2 100644 --- a/sound/atmel/ac97c.c +++ b/sound/atmel/ac97c.c | |||
@@ -1198,6 +1198,7 @@ static int atmel_ac97c_remove(struct platform_device *pdev) | |||
1198 | } | 1198 | } |
1199 | 1199 | ||
1200 | static struct platform_driver atmel_ac97c_driver = { | 1200 | static struct platform_driver atmel_ac97c_driver = { |
1201 | .probe = atmel_ac97c_probe, | ||
1201 | .remove = atmel_ac97c_remove, | 1202 | .remove = atmel_ac97c_remove, |
1202 | .driver = { | 1203 | .driver = { |
1203 | .name = "atmel_ac97c", | 1204 | .name = "atmel_ac97c", |
@@ -1205,19 +1206,7 @@ static struct platform_driver atmel_ac97c_driver = { | |||
1205 | .pm = ATMEL_AC97C_PM_OPS, | 1206 | .pm = ATMEL_AC97C_PM_OPS, |
1206 | }, | 1207 | }, |
1207 | }; | 1208 | }; |
1208 | 1209 | module_platform_driver(atmel_ac97c_driver); | |
1209 | static int __init atmel_ac97c_init(void) | ||
1210 | { | ||
1211 | return platform_driver_probe(&atmel_ac97c_driver, | ||
1212 | atmel_ac97c_probe); | ||
1213 | } | ||
1214 | module_init(atmel_ac97c_init); | ||
1215 | |||
1216 | static void __exit atmel_ac97c_exit(void) | ||
1217 | { | ||
1218 | platform_driver_unregister(&atmel_ac97c_driver); | ||
1219 | } | ||
1220 | module_exit(atmel_ac97c_exit); | ||
1221 | 1210 | ||
1222 | MODULE_LICENSE("GPL"); | 1211 | MODULE_LICENSE("GPL"); |
1223 | MODULE_DESCRIPTION("Driver for Atmel AC97 controller"); | 1212 | MODULE_DESCRIPTION("Driver for Atmel AC97 controller"); |
diff --git a/sound/core/pcm_dmaengine.c b/sound/core/pcm_dmaengine.c index 94d08733cb38..76cbb9ec953a 100644 --- a/sound/core/pcm_dmaengine.c +++ b/sound/core/pcm_dmaengine.c | |||
@@ -182,6 +182,7 @@ static int dmaengine_pcm_prepare_and_submit(struct snd_pcm_substream *substream) | |||
182 | int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | 182 | int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd) |
183 | { | 183 | { |
184 | struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); | 184 | struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); |
185 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
185 | int ret; | 186 | int ret; |
186 | 187 | ||
187 | switch (cmd) { | 188 | switch (cmd) { |
@@ -196,6 +197,11 @@ int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
196 | dmaengine_resume(prtd->dma_chan); | 197 | dmaengine_resume(prtd->dma_chan); |
197 | break; | 198 | break; |
198 | case SNDRV_PCM_TRIGGER_SUSPEND: | 199 | case SNDRV_PCM_TRIGGER_SUSPEND: |
200 | if (runtime->info & SNDRV_PCM_INFO_PAUSE) | ||
201 | dmaengine_pause(prtd->dma_chan); | ||
202 | else | ||
203 | dmaengine_terminate_all(prtd->dma_chan); | ||
204 | break; | ||
199 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 205 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
200 | dmaengine_pause(prtd->dma_chan); | 206 | dmaengine_pause(prtd->dma_chan); |
201 | break; | 207 | break; |
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index ce83def9f43b..9acc77eae487 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c | |||
@@ -345,7 +345,7 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, | |||
345 | snd_pcm_debug_name(substream, name, sizeof(name)); | 345 | snd_pcm_debug_name(substream, name, sizeof(name)); |
346 | xrun_log_show(substream); | 346 | xrun_log_show(substream); |
347 | pcm_err(substream->pcm, | 347 | pcm_err(substream->pcm, |
348 | "BUG: %s, pos = %ld, buffer size = %ld, period size = %ld\n", | 348 | "XRUN: %s, pos = %ld, buffer size = %ld, period size = %ld\n", |
349 | name, pos, runtime->buffer_size, | 349 | name, pos, runtime->buffer_size, |
350 | runtime->period_size); | 350 | runtime->period_size); |
351 | } | 351 | } |
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index 9ca5e647e54b..225c73152ee9 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c | |||
@@ -660,7 +660,7 @@ static int deliver_to_subscribers(struct snd_seq_client *client, | |||
660 | int atomic, int hop) | 660 | int atomic, int hop) |
661 | { | 661 | { |
662 | struct snd_seq_subscribers *subs; | 662 | struct snd_seq_subscribers *subs; |
663 | int err = 0, num_ev = 0; | 663 | int err, result = 0, num_ev = 0; |
664 | struct snd_seq_event event_saved; | 664 | struct snd_seq_event event_saved; |
665 | struct snd_seq_client_port *src_port; | 665 | struct snd_seq_client_port *src_port; |
666 | struct snd_seq_port_subs_info *grp; | 666 | struct snd_seq_port_subs_info *grp; |
@@ -685,8 +685,12 @@ static int deliver_to_subscribers(struct snd_seq_client *client, | |||
685 | subs->info.flags & SNDRV_SEQ_PORT_SUBS_TIME_REAL); | 685 | subs->info.flags & SNDRV_SEQ_PORT_SUBS_TIME_REAL); |
686 | err = snd_seq_deliver_single_event(client, event, | 686 | err = snd_seq_deliver_single_event(client, event, |
687 | 0, atomic, hop); | 687 | 0, atomic, hop); |
688 | if (err < 0) | 688 | if (err < 0) { |
689 | break; | 689 | /* save first error that occurs and continue */ |
690 | if (!result) | ||
691 | result = err; | ||
692 | continue; | ||
693 | } | ||
690 | num_ev++; | 694 | num_ev++; |
691 | /* restore original event record */ | 695 | /* restore original event record */ |
692 | *event = event_saved; | 696 | *event = event_saved; |
@@ -697,7 +701,7 @@ static int deliver_to_subscribers(struct snd_seq_client *client, | |||
697 | up_read(&grp->list_mutex); | 701 | up_read(&grp->list_mutex); |
698 | *event = event_saved; /* restore */ | 702 | *event = event_saved; /* restore */ |
699 | snd_seq_port_unlock(src_port); | 703 | snd_seq_port_unlock(src_port); |
700 | return (err < 0) ? err : num_ev; | 704 | return (result < 0) ? result : num_ev; |
701 | } | 705 | } |
702 | 706 | ||
703 | 707 | ||
@@ -709,7 +713,7 @@ static int port_broadcast_event(struct snd_seq_client *client, | |||
709 | struct snd_seq_event *event, | 713 | struct snd_seq_event *event, |
710 | int atomic, int hop) | 714 | int atomic, int hop) |
711 | { | 715 | { |
712 | int num_ev = 0, err = 0; | 716 | int num_ev = 0, err, result = 0; |
713 | struct snd_seq_client *dest_client; | 717 | struct snd_seq_client *dest_client; |
714 | struct snd_seq_client_port *port; | 718 | struct snd_seq_client_port *port; |
715 | 719 | ||
@@ -724,14 +728,18 @@ static int port_broadcast_event(struct snd_seq_client *client, | |||
724 | err = snd_seq_deliver_single_event(NULL, event, | 728 | err = snd_seq_deliver_single_event(NULL, event, |
725 | SNDRV_SEQ_FILTER_BROADCAST, | 729 | SNDRV_SEQ_FILTER_BROADCAST, |
726 | atomic, hop); | 730 | atomic, hop); |
727 | if (err < 0) | 731 | if (err < 0) { |
728 | break; | 732 | /* save first error that occurs and continue */ |
733 | if (!result) | ||
734 | result = err; | ||
735 | continue; | ||
736 | } | ||
729 | num_ev++; | 737 | num_ev++; |
730 | } | 738 | } |
731 | read_unlock(&dest_client->ports_lock); | 739 | read_unlock(&dest_client->ports_lock); |
732 | snd_seq_client_unlock(dest_client); | 740 | snd_seq_client_unlock(dest_client); |
733 | event->dest.port = SNDRV_SEQ_ADDRESS_BROADCAST; /* restore */ | 741 | event->dest.port = SNDRV_SEQ_ADDRESS_BROADCAST; /* restore */ |
734 | return (err < 0) ? err : num_ev; | 742 | return (result < 0) ? result : num_ev; |
735 | } | 743 | } |
736 | 744 | ||
737 | /* | 745 | /* |
@@ -741,7 +749,7 @@ static int port_broadcast_event(struct snd_seq_client *client, | |||
741 | static int broadcast_event(struct snd_seq_client *client, | 749 | static int broadcast_event(struct snd_seq_client *client, |
742 | struct snd_seq_event *event, int atomic, int hop) | 750 | struct snd_seq_event *event, int atomic, int hop) |
743 | { | 751 | { |
744 | int err = 0, num_ev = 0; | 752 | int err, result = 0, num_ev = 0; |
745 | int dest; | 753 | int dest; |
746 | struct snd_seq_addr addr; | 754 | struct snd_seq_addr addr; |
747 | 755 | ||
@@ -760,12 +768,16 @@ static int broadcast_event(struct snd_seq_client *client, | |||
760 | err = snd_seq_deliver_single_event(NULL, event, | 768 | err = snd_seq_deliver_single_event(NULL, event, |
761 | SNDRV_SEQ_FILTER_BROADCAST, | 769 | SNDRV_SEQ_FILTER_BROADCAST, |
762 | atomic, hop); | 770 | atomic, hop); |
763 | if (err < 0) | 771 | if (err < 0) { |
764 | break; | 772 | /* save first error that occurs and continue */ |
773 | if (!result) | ||
774 | result = err; | ||
775 | continue; | ||
776 | } | ||
765 | num_ev += err; | 777 | num_ev += err; |
766 | } | 778 | } |
767 | event->dest = addr; /* restore */ | 779 | event->dest = addr; /* restore */ |
768 | return (err < 0) ? err : num_ev; | 780 | return (result < 0) ? result : num_ev; |
769 | } | 781 | } |
770 | 782 | ||
771 | 783 | ||
diff --git a/sound/core/seq/seq_fifo.c b/sound/core/seq/seq_fifo.c index 559989992bef..53a403e17c5b 100644 --- a/sound/core/seq/seq_fifo.c +++ b/sound/core/seq/seq_fifo.c | |||
@@ -124,7 +124,7 @@ int snd_seq_fifo_event_in(struct snd_seq_fifo *f, | |||
124 | snd_use_lock_use(&f->use_lock); | 124 | snd_use_lock_use(&f->use_lock); |
125 | err = snd_seq_event_dup(f->pool, event, &cell, 1, NULL); /* always non-blocking */ | 125 | err = snd_seq_event_dup(f->pool, event, &cell, 1, NULL); /* always non-blocking */ |
126 | if (err < 0) { | 126 | if (err < 0) { |
127 | if (err == -ENOMEM) | 127 | if ((err == -ENOMEM) || (err == -EAGAIN)) |
128 | atomic_inc(&f->overflow); | 128 | atomic_inc(&f->overflow); |
129 | snd_use_lock_free(&f->use_lock); | 129 | snd_use_lock_free(&f->use_lock); |
130 | return err; | 130 | return err; |
diff --git a/sound/core/seq/seq_midi.c b/sound/core/seq/seq_midi.c index 3e05c55a2880..a1fd77af6059 100644 --- a/sound/core/seq/seq_midi.c +++ b/sound/core/seq/seq_midi.c | |||
@@ -362,13 +362,13 @@ snd_seq_midisynth_register_port(struct snd_seq_device *dev) | |||
362 | if (! port->name[0]) { | 362 | if (! port->name[0]) { |
363 | if (info->name[0]) { | 363 | if (info->name[0]) { |
364 | if (ports > 1) | 364 | if (ports > 1) |
365 | snprintf(port->name, sizeof(port->name), "%s-%d", info->name, p); | 365 | snprintf(port->name, sizeof(port->name), "%s-%u", info->name, p); |
366 | else | 366 | else |
367 | snprintf(port->name, sizeof(port->name), "%s", info->name); | 367 | snprintf(port->name, sizeof(port->name), "%s", info->name); |
368 | } else { | 368 | } else { |
369 | /* last resort */ | 369 | /* last resort */ |
370 | if (ports > 1) | 370 | if (ports > 1) |
371 | sprintf(port->name, "MIDI %d-%d-%d", card->number, device, p); | 371 | sprintf(port->name, "MIDI %d-%d-%u", card->number, device, p); |
372 | else | 372 | else |
373 | sprintf(port->name, "MIDI %d-%d", card->number, device); | 373 | sprintf(port->name, "MIDI %d-%d", card->number, device); |
374 | } | 374 | } |
diff --git a/sound/core/timer.c b/sound/core/timer.c index cfd455a8ac1a..777a45e08e53 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c | |||
@@ -390,7 +390,7 @@ static void snd_timer_notify1(struct snd_timer_instance *ti, int event) | |||
390 | struct timespec tstamp; | 390 | struct timespec tstamp; |
391 | 391 | ||
392 | if (timer_tstamp_monotonic) | 392 | if (timer_tstamp_monotonic) |
393 | do_posix_clock_monotonic_gettime(&tstamp); | 393 | ktime_get_ts(&tstamp); |
394 | else | 394 | else |
395 | getnstimeofday(&tstamp); | 395 | getnstimeofday(&tstamp); |
396 | if (snd_BUG_ON(event < SNDRV_TIMER_EVENT_START || | 396 | if (snd_BUG_ON(event < SNDRV_TIMER_EVENT_START || |
@@ -1203,7 +1203,7 @@ static void snd_timer_user_tinterrupt(struct snd_timer_instance *timeri, | |||
1203 | } | 1203 | } |
1204 | if (tu->last_resolution != resolution || ticks > 0) { | 1204 | if (tu->last_resolution != resolution || ticks > 0) { |
1205 | if (timer_tstamp_monotonic) | 1205 | if (timer_tstamp_monotonic) |
1206 | do_posix_clock_monotonic_gettime(&tstamp); | 1206 | ktime_get_ts(&tstamp); |
1207 | else | 1207 | else |
1208 | getnstimeofday(&tstamp); | 1208 | getnstimeofday(&tstamp); |
1209 | } | 1209 | } |
diff --git a/sound/firewire/Kconfig b/sound/firewire/Kconfig index b3e274fe4a77..775ef2efc296 100644 --- a/sound/firewire/Kconfig +++ b/sound/firewire/Kconfig | |||
@@ -9,12 +9,12 @@ if SND_FIREWIRE && FIREWIRE | |||
9 | 9 | ||
10 | config SND_FIREWIRE_LIB | 10 | config SND_FIREWIRE_LIB |
11 | tristate | 11 | tristate |
12 | depends on SND_PCM | 12 | select SND_PCM |
13 | select SND_RAWMIDI | ||
13 | 14 | ||
14 | config SND_DICE | 15 | config SND_DICE |
15 | tristate "DICE-based DACs (EXPERIMENTAL)" | 16 | tristate "DICE-based DACs (EXPERIMENTAL)" |
16 | select SND_HWDEP | 17 | select SND_HWDEP |
17 | select SND_PCM | ||
18 | select SND_FIREWIRE_LIB | 18 | select SND_FIREWIRE_LIB |
19 | help | 19 | help |
20 | Say Y here to include support for many DACs based on the DICE | 20 | Say Y here to include support for many DACs based on the DICE |
@@ -28,7 +28,6 @@ config SND_DICE | |||
28 | 28 | ||
29 | config SND_FIREWIRE_SPEAKERS | 29 | config SND_FIREWIRE_SPEAKERS |
30 | tristate "FireWire speakers" | 30 | tristate "FireWire speakers" |
31 | select SND_PCM | ||
32 | select SND_FIREWIRE_LIB | 31 | select SND_FIREWIRE_LIB |
33 | help | 32 | help |
34 | Say Y here to include support for the Griffin FireWave Surround | 33 | Say Y here to include support for the Griffin FireWave Surround |
@@ -39,7 +38,6 @@ config SND_FIREWIRE_SPEAKERS | |||
39 | 38 | ||
40 | config SND_ISIGHT | 39 | config SND_ISIGHT |
41 | tristate "Apple iSight microphone" | 40 | tristate "Apple iSight microphone" |
42 | select SND_PCM | ||
43 | select SND_FIREWIRE_LIB | 41 | select SND_FIREWIRE_LIB |
44 | help | 42 | help |
45 | Say Y here to include support for the front and rear microphones | 43 | Say Y here to include support for the front and rear microphones |
@@ -50,8 +48,6 @@ config SND_ISIGHT | |||
50 | 48 | ||
51 | config SND_SCS1X | 49 | config SND_SCS1X |
52 | tristate "Stanton Control System 1 MIDI" | 50 | tristate "Stanton Control System 1 MIDI" |
53 | select SND_PCM | ||
54 | select SND_RAWMIDI | ||
55 | select SND_FIREWIRE_LIB | 51 | select SND_FIREWIRE_LIB |
56 | help | 52 | help |
57 | Say Y here to include support for the MIDI ports of the Stanton | 53 | Say Y here to include support for the MIDI ports of the Stanton |
@@ -61,4 +57,59 @@ config SND_SCS1X | |||
61 | To compile this driver as a module, choose M here: the module | 57 | To compile this driver as a module, choose M here: the module |
62 | will be called snd-scs1x. | 58 | will be called snd-scs1x. |
63 | 59 | ||
60 | config SND_FIREWORKS | ||
61 | tristate "Echo Fireworks board module support" | ||
62 | select SND_FIREWIRE_LIB | ||
63 | select SND_HWDEP | ||
64 | help | ||
65 | Say Y here to include support for FireWire devices based | ||
66 | on Echo Digital Audio Fireworks board: | ||
67 | * Mackie Onyx 400F/1200F | ||
68 | * Echo AudioFire12/8(until 2009 July) | ||
69 | * Echo AudioFire2/4/Pre8/8(since 2009 July) | ||
70 | * Echo Fireworks 8/HDMI | ||
71 | * Gibson Robot Interface Pack/GoldTop | ||
72 | |||
73 | To compile this driver as a module, choose M here: the module | ||
74 | will be called snd-fireworks. | ||
75 | |||
76 | config SND_BEBOB | ||
77 | tristate "BridgeCo DM1000/DM1100/DM1500 with BeBoB firmware" | ||
78 | select SND_FIREWIRE_LIB | ||
79 | select SND_HWDEP | ||
80 | help | ||
81 | Say Y here to include support for FireWire devices based | ||
82 | on BridgeCo DM1000/DM1100/DM1500 with BeBoB firmware: | ||
83 | * Edirol FA-66/FA-101 | ||
84 | * PreSonus FIREBOX/FIREPOD/FP10/Inspire1394 | ||
85 | * BridgeCo RDAudio1/Audio5 | ||
86 | * Mackie Onyx 1220/1620/1640 (Firewire I/O Card) | ||
87 | * Mackie d.2 (Firewire Option) | ||
88 | * Stanton FinalScratch 2 (ScratchAmp) | ||
89 | * Tascam IF-FW/DM | ||
90 | * Behringer XENIX UFX 1204/1604 | ||
91 | * Behringer Digital Mixer X32 series (X-UF Card) | ||
92 | * Apogee Rosetta 200/400 (X-FireWire card) | ||
93 | * Apogee DA/AD/DD-16X (X-FireWire card) | ||
94 | * Apogee Ensemble | ||
95 | * ESI Quotafire610 | ||
96 | * AcousticReality eARMasterOne | ||
97 | * CME MatrixKFW | ||
98 | * Phonic Helix Board 12 MkII/18 MkII/24 MkII | ||
99 | * Phonic Helix Board 12 Universal/18 Universal/24 Universal | ||
100 | * Lynx Aurora 8/16 (LT-FW) | ||
101 | * ICON FireXon | ||
102 | * PrismSound Orpheus/ADA-8XR | ||
103 | * TerraTec PHASE 24 FW/PHASE X24 FW/PHASE 88 Rack FW | ||
104 | * Terratec EWS MIC2/EWS MIC4 | ||
105 | * Terratec Aureon 7.1 Firewire | ||
106 | * Yamaha GO44/GO46 | ||
107 | * Focusrite Saffire/Saffire LE/SaffirePro10 IO/SaffirePro26 IO | ||
108 | * M-Audio Firewire410/AudioPhile/Solo | ||
109 | * M-Audio Ozonic/NRV10/ProfireLightBridge | ||
110 | * M-Audio Firewire 1814/ProjectMix IO | ||
111 | |||
112 | To compile this driver as a module, choose M here: the module | ||
113 | will be called snd-bebob. | ||
114 | |||
64 | endif # SND_FIREWIRE | 115 | endif # SND_FIREWIRE |
diff --git a/sound/firewire/Makefile b/sound/firewire/Makefile index 509955061d30..fad8d49306ab 100644 --- a/sound/firewire/Makefile +++ b/sound/firewire/Makefile | |||
@@ -10,3 +10,5 @@ obj-$(CONFIG_SND_DICE) += snd-dice.o | |||
10 | obj-$(CONFIG_SND_FIREWIRE_SPEAKERS) += snd-firewire-speakers.o | 10 | obj-$(CONFIG_SND_FIREWIRE_SPEAKERS) += snd-firewire-speakers.o |
11 | obj-$(CONFIG_SND_ISIGHT) += snd-isight.o | 11 | obj-$(CONFIG_SND_ISIGHT) += snd-isight.o |
12 | obj-$(CONFIG_SND_SCS1X) += snd-scs1x.o | 12 | obj-$(CONFIG_SND_SCS1X) += snd-scs1x.o |
13 | obj-$(CONFIG_SND_FIREWORKS) += fireworks/ | ||
14 | obj-$(CONFIG_SND_BEBOB) += bebob/ | ||
diff --git a/sound/firewire/amdtp.c b/sound/firewire/amdtp.c index 9048777228e2..f96bf4c7c232 100644 --- a/sound/firewire/amdtp.c +++ b/sound/firewire/amdtp.c | |||
@@ -11,7 +11,10 @@ | |||
11 | #include <linux/firewire.h> | 11 | #include <linux/firewire.h> |
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
14 | #include <linux/sched.h> | ||
14 | #include <sound/pcm.h> | 15 | #include <sound/pcm.h> |
16 | #include <sound/pcm_params.h> | ||
17 | #include <sound/rawmidi.h> | ||
15 | #include "amdtp.h" | 18 | #include "amdtp.h" |
16 | 19 | ||
17 | #define TICKS_PER_CYCLE 3072 | 20 | #define TICKS_PER_CYCLE 3072 |
@@ -20,50 +23,78 @@ | |||
20 | 23 | ||
21 | #define TRANSFER_DELAY_TICKS 0x2e00 /* 479.17 µs */ | 24 | #define TRANSFER_DELAY_TICKS 0x2e00 /* 479.17 µs */ |
22 | 25 | ||
26 | /* isochronous header parameters */ | ||
27 | #define ISO_DATA_LENGTH_SHIFT 16 | ||
23 | #define TAG_CIP 1 | 28 | #define TAG_CIP 1 |
24 | 29 | ||
30 | /* common isochronous packet header parameters */ | ||
25 | #define CIP_EOH (1u << 31) | 31 | #define CIP_EOH (1u << 31) |
32 | #define CIP_EOH_MASK 0x80000000 | ||
26 | #define CIP_FMT_AM (0x10 << 24) | 33 | #define CIP_FMT_AM (0x10 << 24) |
27 | #define AMDTP_FDF_AM824 (0 << 19) | 34 | #define CIP_FMT_MASK 0x3f000000 |
28 | #define AMDTP_FDF_SFC_SHIFT 16 | 35 | #define CIP_SYT_MASK 0x0000ffff |
36 | #define CIP_SYT_NO_INFO 0xffff | ||
37 | #define CIP_FDF_MASK 0x00ff0000 | ||
38 | #define CIP_FDF_SFC_SHIFT 16 | ||
39 | |||
40 | /* | ||
41 | * Audio and Music transfer protocol specific parameters | ||
42 | * only "Clock-based rate control mode" is supported | ||
43 | */ | ||
44 | #define AMDTP_FDF_AM824 (0 << (CIP_FDF_SFC_SHIFT + 3)) | ||
45 | #define AMDTP_FDF_NO_DATA 0xff | ||
46 | #define AMDTP_DBS_MASK 0x00ff0000 | ||
47 | #define AMDTP_DBS_SHIFT 16 | ||
48 | #define AMDTP_DBC_MASK 0x000000ff | ||
29 | 49 | ||
30 | /* TODO: make these configurable */ | 50 | /* TODO: make these configurable */ |
31 | #define INTERRUPT_INTERVAL 16 | 51 | #define INTERRUPT_INTERVAL 16 |
32 | #define QUEUE_LENGTH 48 | 52 | #define QUEUE_LENGTH 48 |
33 | 53 | ||
54 | #define IN_PACKET_HEADER_SIZE 4 | ||
55 | #define OUT_PACKET_HEADER_SIZE 0 | ||
56 | |||
34 | static void pcm_period_tasklet(unsigned long data); | 57 | static void pcm_period_tasklet(unsigned long data); |
35 | 58 | ||
36 | /** | 59 | /** |
37 | * amdtp_out_stream_init - initialize an AMDTP output stream structure | 60 | * amdtp_stream_init - initialize an AMDTP stream structure |
38 | * @s: the AMDTP output stream to initialize | 61 | * @s: the AMDTP stream to initialize |
39 | * @unit: the target of the stream | 62 | * @unit: the target of the stream |
63 | * @dir: the direction of stream | ||
40 | * @flags: the packet transmission method to use | 64 | * @flags: the packet transmission method to use |
41 | */ | 65 | */ |
42 | int amdtp_out_stream_init(struct amdtp_out_stream *s, struct fw_unit *unit, | 66 | int amdtp_stream_init(struct amdtp_stream *s, struct fw_unit *unit, |
43 | enum cip_out_flags flags) | 67 | enum amdtp_stream_direction dir, enum cip_flags flags) |
44 | { | 68 | { |
45 | s->unit = fw_unit_get(unit); | 69 | s->unit = fw_unit_get(unit); |
70 | s->direction = dir; | ||
46 | s->flags = flags; | 71 | s->flags = flags; |
47 | s->context = ERR_PTR(-1); | 72 | s->context = ERR_PTR(-1); |
48 | mutex_init(&s->mutex); | 73 | mutex_init(&s->mutex); |
49 | tasklet_init(&s->period_tasklet, pcm_period_tasklet, (unsigned long)s); | 74 | tasklet_init(&s->period_tasklet, pcm_period_tasklet, (unsigned long)s); |
50 | s->packet_index = 0; | 75 | s->packet_index = 0; |
51 | 76 | ||
77 | init_waitqueue_head(&s->callback_wait); | ||
78 | s->callbacked = false; | ||
79 | s->sync_slave = NULL; | ||
80 | |||
81 | s->rx_blocks_for_midi = UINT_MAX; | ||
82 | |||
52 | return 0; | 83 | return 0; |
53 | } | 84 | } |
54 | EXPORT_SYMBOL(amdtp_out_stream_init); | 85 | EXPORT_SYMBOL(amdtp_stream_init); |
55 | 86 | ||
56 | /** | 87 | /** |
57 | * amdtp_out_stream_destroy - free stream resources | 88 | * amdtp_stream_destroy - free stream resources |
58 | * @s: the AMDTP output stream to destroy | 89 | * @s: the AMDTP stream to destroy |
59 | */ | 90 | */ |
60 | void amdtp_out_stream_destroy(struct amdtp_out_stream *s) | 91 | void amdtp_stream_destroy(struct amdtp_stream *s) |
61 | { | 92 | { |
62 | WARN_ON(amdtp_out_stream_running(s)); | 93 | WARN_ON(amdtp_stream_running(s)); |
63 | mutex_destroy(&s->mutex); | 94 | mutex_destroy(&s->mutex); |
64 | fw_unit_put(s->unit); | 95 | fw_unit_put(s->unit); |
65 | } | 96 | } |
66 | EXPORT_SYMBOL(amdtp_out_stream_destroy); | 97 | EXPORT_SYMBOL(amdtp_stream_destroy); |
67 | 98 | ||
68 | const unsigned int amdtp_syt_intervals[CIP_SFC_COUNT] = { | 99 | const unsigned int amdtp_syt_intervals[CIP_SFC_COUNT] = { |
69 | [CIP_SFC_32000] = 8, | 100 | [CIP_SFC_32000] = 8, |
@@ -76,9 +107,75 @@ const unsigned int amdtp_syt_intervals[CIP_SFC_COUNT] = { | |||
76 | }; | 107 | }; |
77 | EXPORT_SYMBOL(amdtp_syt_intervals); | 108 | EXPORT_SYMBOL(amdtp_syt_intervals); |
78 | 109 | ||
110 | const unsigned int amdtp_rate_table[CIP_SFC_COUNT] = { | ||
111 | [CIP_SFC_32000] = 32000, | ||
112 | [CIP_SFC_44100] = 44100, | ||
113 | [CIP_SFC_48000] = 48000, | ||
114 | [CIP_SFC_88200] = 88200, | ||
115 | [CIP_SFC_96000] = 96000, | ||
116 | [CIP_SFC_176400] = 176400, | ||
117 | [CIP_SFC_192000] = 192000, | ||
118 | }; | ||
119 | EXPORT_SYMBOL(amdtp_rate_table); | ||
120 | |||
121 | /** | ||
122 | * amdtp_stream_add_pcm_hw_constraints - add hw constraints for PCM substream | ||
123 | * @s: the AMDTP stream, which must be initialized. | ||
124 | * @runtime: the PCM substream runtime | ||
125 | */ | ||
126 | int amdtp_stream_add_pcm_hw_constraints(struct amdtp_stream *s, | ||
127 | struct snd_pcm_runtime *runtime) | ||
128 | { | ||
129 | int err; | ||
130 | |||
131 | /* AM824 in IEC 61883-6 can deliver 24bit data */ | ||
132 | err = snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); | ||
133 | if (err < 0) | ||
134 | goto end; | ||
135 | |||
136 | /* | ||
137 | * Currently firewire-lib processes 16 packets in one software | ||
138 | * interrupt callback. This equals to 2msec but actually the | ||
139 | * interval of the interrupts has a jitter. | ||
140 | * Additionally, even if adding a constraint to fit period size to | ||
141 | * 2msec, actual calculated frames per period doesn't equal to 2msec, | ||
142 | * depending on sampling rate. | ||
143 | * Anyway, the interval to call snd_pcm_period_elapsed() cannot 2msec. | ||
144 | * Here let us use 5msec for safe period interrupt. | ||
145 | */ | ||
146 | err = snd_pcm_hw_constraint_minmax(runtime, | ||
147 | SNDRV_PCM_HW_PARAM_PERIOD_TIME, | ||
148 | 5000, UINT_MAX); | ||
149 | if (err < 0) | ||
150 | goto end; | ||
151 | |||
152 | /* Non-Blocking stream has no more constraints */ | ||
153 | if (!(s->flags & CIP_BLOCKING)) | ||
154 | goto end; | ||
155 | |||
156 | /* | ||
157 | * One AMDTP packet can include some frames. In blocking mode, the | ||
158 | * number equals to SYT_INTERVAL. So the number is 8, 16 or 32, | ||
159 | * depending on its sampling rate. For accurate period interrupt, it's | ||
160 | * preferrable to aligh period/buffer sizes to current SYT_INTERVAL. | ||
161 | * | ||
162 | * TODO: These constraints can be improved with propper rules. | ||
163 | * Currently apply LCM of SYT_INTEVALs. | ||
164 | */ | ||
165 | err = snd_pcm_hw_constraint_step(runtime, 0, | ||
166 | SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 32); | ||
167 | if (err < 0) | ||
168 | goto end; | ||
169 | err = snd_pcm_hw_constraint_step(runtime, 0, | ||
170 | SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 32); | ||
171 | end: | ||
172 | return err; | ||
173 | } | ||
174 | EXPORT_SYMBOL(amdtp_stream_add_pcm_hw_constraints); | ||
175 | |||
79 | /** | 176 | /** |
80 | * amdtp_out_stream_set_parameters - set stream parameters | 177 | * amdtp_stream_set_parameters - set stream parameters |
81 | * @s: the AMDTP output stream to configure | 178 | * @s: the AMDTP stream to configure |
82 | * @rate: the sample rate | 179 | * @rate: the sample rate |
83 | * @pcm_channels: the number of PCM samples in each data block, to be encoded | 180 | * @pcm_channels: the number of PCM samples in each data block, to be encoded |
84 | * as AM824 multi-bit linear audio | 181 | * as AM824 multi-bit linear audio |
@@ -87,41 +184,30 @@ EXPORT_SYMBOL(amdtp_syt_intervals); | |||
87 | * The parameters must be set before the stream is started, and must not be | 184 | * The parameters must be set before the stream is started, and must not be |
88 | * changed while the stream is running. | 185 | * changed while the stream is running. |
89 | */ | 186 | */ |
90 | void amdtp_out_stream_set_parameters(struct amdtp_out_stream *s, | 187 | void amdtp_stream_set_parameters(struct amdtp_stream *s, |
91 | unsigned int rate, | 188 | unsigned int rate, |
92 | unsigned int pcm_channels, | 189 | unsigned int pcm_channels, |
93 | unsigned int midi_ports) | 190 | unsigned int midi_ports) |
94 | { | 191 | { |
95 | static const unsigned int rates[] = { | 192 | unsigned int i, sfc, midi_channels; |
96 | [CIP_SFC_32000] = 32000, | 193 | |
97 | [CIP_SFC_44100] = 44100, | 194 | midi_channels = DIV_ROUND_UP(midi_ports, 8); |
98 | [CIP_SFC_48000] = 48000, | ||
99 | [CIP_SFC_88200] = 88200, | ||
100 | [CIP_SFC_96000] = 96000, | ||
101 | [CIP_SFC_176400] = 176400, | ||
102 | [CIP_SFC_192000] = 192000, | ||
103 | }; | ||
104 | unsigned int sfc; | ||
105 | 195 | ||
106 | if (WARN_ON(amdtp_out_stream_running(s))) | 196 | if (WARN_ON(amdtp_stream_running(s)) | |
197 | WARN_ON(pcm_channels > AMDTP_MAX_CHANNELS_FOR_PCM) | | ||
198 | WARN_ON(midi_channels > AMDTP_MAX_CHANNELS_FOR_MIDI)) | ||
107 | return; | 199 | return; |
108 | 200 | ||
109 | for (sfc = 0; sfc < CIP_SFC_COUNT; ++sfc) | 201 | for (sfc = 0; sfc < ARRAY_SIZE(amdtp_rate_table); ++sfc) |
110 | if (rates[sfc] == rate) | 202 | if (amdtp_rate_table[sfc] == rate) |
111 | goto sfc_found; | 203 | goto sfc_found; |
112 | WARN_ON(1); | 204 | WARN_ON(1); |
113 | return; | 205 | return; |
114 | 206 | ||
115 | sfc_found: | 207 | sfc_found: |
116 | s->dual_wire = (s->flags & CIP_HI_DUALWIRE) && sfc > CIP_SFC_96000; | ||
117 | if (s->dual_wire) { | ||
118 | sfc -= 2; | ||
119 | rate /= 2; | ||
120 | pcm_channels *= 2; | ||
121 | } | ||
122 | s->sfc = sfc; | ||
123 | s->data_block_quadlets = pcm_channels + DIV_ROUND_UP(midi_ports, 8); | ||
124 | s->pcm_channels = pcm_channels; | 208 | s->pcm_channels = pcm_channels; |
209 | s->sfc = sfc; | ||
210 | s->data_block_quadlets = s->pcm_channels + midi_channels; | ||
125 | s->midi_ports = midi_ports; | 211 | s->midi_ports = midi_ports; |
126 | 212 | ||
127 | s->syt_interval = amdtp_syt_intervals[sfc]; | 213 | s->syt_interval = amdtp_syt_intervals[sfc]; |
@@ -131,48 +217,50 @@ sfc_found: | |||
131 | if (s->flags & CIP_BLOCKING) | 217 | if (s->flags & CIP_BLOCKING) |
132 | /* additional buffering needed to adjust for no-data packets */ | 218 | /* additional buffering needed to adjust for no-data packets */ |
133 | s->transfer_delay += TICKS_PER_SECOND * s->syt_interval / rate; | 219 | s->transfer_delay += TICKS_PER_SECOND * s->syt_interval / rate; |
220 | |||
221 | /* init the position map for PCM and MIDI channels */ | ||
222 | for (i = 0; i < pcm_channels; i++) | ||
223 | s->pcm_positions[i] = i; | ||
224 | s->midi_position = s->pcm_channels; | ||
134 | } | 225 | } |
135 | EXPORT_SYMBOL(amdtp_out_stream_set_parameters); | 226 | EXPORT_SYMBOL(amdtp_stream_set_parameters); |
136 | 227 | ||
137 | /** | 228 | /** |
138 | * amdtp_out_stream_get_max_payload - get the stream's packet size | 229 | * amdtp_stream_get_max_payload - get the stream's packet size |
139 | * @s: the AMDTP output stream | 230 | * @s: the AMDTP stream |
140 | * | 231 | * |
141 | * This function must not be called before the stream has been configured | 232 | * This function must not be called before the stream has been configured |
142 | * with amdtp_out_stream_set_parameters(). | 233 | * with amdtp_stream_set_parameters(). |
143 | */ | 234 | */ |
144 | unsigned int amdtp_out_stream_get_max_payload(struct amdtp_out_stream *s) | 235 | unsigned int amdtp_stream_get_max_payload(struct amdtp_stream *s) |
145 | { | 236 | { |
146 | return 8 + s->syt_interval * s->data_block_quadlets * 4; | 237 | return 8 + s->syt_interval * s->data_block_quadlets * 4; |
147 | } | 238 | } |
148 | EXPORT_SYMBOL(amdtp_out_stream_get_max_payload); | 239 | EXPORT_SYMBOL(amdtp_stream_get_max_payload); |
149 | 240 | ||
150 | static void amdtp_write_s16(struct amdtp_out_stream *s, | 241 | static void amdtp_write_s16(struct amdtp_stream *s, |
151 | struct snd_pcm_substream *pcm, | 242 | struct snd_pcm_substream *pcm, |
152 | __be32 *buffer, unsigned int frames); | 243 | __be32 *buffer, unsigned int frames); |
153 | static void amdtp_write_s32(struct amdtp_out_stream *s, | 244 | static void amdtp_write_s32(struct amdtp_stream *s, |
154 | struct snd_pcm_substream *pcm, | 245 | struct snd_pcm_substream *pcm, |
155 | __be32 *buffer, unsigned int frames); | 246 | __be32 *buffer, unsigned int frames); |
156 | static void amdtp_write_s16_dualwire(struct amdtp_out_stream *s, | 247 | static void amdtp_read_s32(struct amdtp_stream *s, |
157 | struct snd_pcm_substream *pcm, | 248 | struct snd_pcm_substream *pcm, |
158 | __be32 *buffer, unsigned int frames); | 249 | __be32 *buffer, unsigned int frames); |
159 | static void amdtp_write_s32_dualwire(struct amdtp_out_stream *s, | ||
160 | struct snd_pcm_substream *pcm, | ||
161 | __be32 *buffer, unsigned int frames); | ||
162 | 250 | ||
163 | /** | 251 | /** |
164 | * amdtp_out_stream_set_pcm_format - set the PCM format | 252 | * amdtp_stream_set_pcm_format - set the PCM format |
165 | * @s: the AMDTP output stream to configure | 253 | * @s: the AMDTP stream to configure |
166 | * @format: the format of the ALSA PCM device | 254 | * @format: the format of the ALSA PCM device |
167 | * | 255 | * |
168 | * The sample format must be set after the other paramters (rate/PCM channels/ | 256 | * The sample format must be set after the other paramters (rate/PCM channels/ |
169 | * MIDI) and before the stream is started, and must not be changed while the | 257 | * MIDI) and before the stream is started, and must not be changed while the |
170 | * stream is running. | 258 | * stream is running. |
171 | */ | 259 | */ |
172 | void amdtp_out_stream_set_pcm_format(struct amdtp_out_stream *s, | 260 | void amdtp_stream_set_pcm_format(struct amdtp_stream *s, |
173 | snd_pcm_format_t format) | 261 | snd_pcm_format_t format) |
174 | { | 262 | { |
175 | if (WARN_ON(amdtp_out_stream_running(s))) | 263 | if (WARN_ON(amdtp_stream_pcm_running(s))) |
176 | return; | 264 | return; |
177 | 265 | ||
178 | switch (format) { | 266 | switch (format) { |
@@ -180,41 +268,44 @@ void amdtp_out_stream_set_pcm_format(struct amdtp_out_stream *s, | |||
180 | WARN_ON(1); | 268 | WARN_ON(1); |
181 | /* fall through */ | 269 | /* fall through */ |
182 | case SNDRV_PCM_FORMAT_S16: | 270 | case SNDRV_PCM_FORMAT_S16: |
183 | if (s->dual_wire) | 271 | if (s->direction == AMDTP_OUT_STREAM) { |
184 | s->transfer_samples = amdtp_write_s16_dualwire; | ||
185 | else | ||
186 | s->transfer_samples = amdtp_write_s16; | 272 | s->transfer_samples = amdtp_write_s16; |
187 | break; | 273 | break; |
274 | } | ||
275 | WARN_ON(1); | ||
276 | /* fall through */ | ||
188 | case SNDRV_PCM_FORMAT_S32: | 277 | case SNDRV_PCM_FORMAT_S32: |
189 | if (s->dual_wire) | 278 | if (s->direction == AMDTP_OUT_STREAM) |
190 | s->transfer_samples = amdtp_write_s32_dualwire; | ||
191 | else | ||
192 | s->transfer_samples = amdtp_write_s32; | 279 | s->transfer_samples = amdtp_write_s32; |
280 | else | ||
281 | s->transfer_samples = amdtp_read_s32; | ||
193 | break; | 282 | break; |
194 | } | 283 | } |
195 | } | 284 | } |
196 | EXPORT_SYMBOL(amdtp_out_stream_set_pcm_format); | 285 | EXPORT_SYMBOL(amdtp_stream_set_pcm_format); |
197 | 286 | ||
198 | /** | 287 | /** |
199 | * amdtp_out_stream_pcm_prepare - prepare PCM device for running | 288 | * amdtp_stream_pcm_prepare - prepare PCM device for running |
200 | * @s: the AMDTP output stream | 289 | * @s: the AMDTP stream |
201 | * | 290 | * |
202 | * This function should be called from the PCM device's .prepare callback. | 291 | * This function should be called from the PCM device's .prepare callback. |
203 | */ | 292 | */ |
204 | void amdtp_out_stream_pcm_prepare(struct amdtp_out_stream *s) | 293 | void amdtp_stream_pcm_prepare(struct amdtp_stream *s) |
205 | { | 294 | { |
206 | tasklet_kill(&s->period_tasklet); | 295 | tasklet_kill(&s->period_tasklet); |
207 | s->pcm_buffer_pointer = 0; | 296 | s->pcm_buffer_pointer = 0; |
208 | s->pcm_period_pointer = 0; | 297 | s->pcm_period_pointer = 0; |
209 | s->pointer_flush = true; | 298 | s->pointer_flush = true; |
210 | } | 299 | } |
211 | EXPORT_SYMBOL(amdtp_out_stream_pcm_prepare); | 300 | EXPORT_SYMBOL(amdtp_stream_pcm_prepare); |
212 | 301 | ||
213 | static unsigned int calculate_data_blocks(struct amdtp_out_stream *s) | 302 | static unsigned int calculate_data_blocks(struct amdtp_stream *s) |
214 | { | 303 | { |
215 | unsigned int phase, data_blocks; | 304 | unsigned int phase, data_blocks; |
216 | 305 | ||
217 | if (!cip_sfc_is_base_44100(s->sfc)) { | 306 | if (s->flags & CIP_BLOCKING) |
307 | data_blocks = s->syt_interval; | ||
308 | else if (!cip_sfc_is_base_44100(s->sfc)) { | ||
218 | /* Sample_rate / 8000 is an integer, and precomputed. */ | 309 | /* Sample_rate / 8000 is an integer, and precomputed. */ |
219 | data_blocks = s->data_block_state; | 310 | data_blocks = s->data_block_state; |
220 | } else { | 311 | } else { |
@@ -243,7 +334,7 @@ static unsigned int calculate_data_blocks(struct amdtp_out_stream *s) | |||
243 | return data_blocks; | 334 | return data_blocks; |
244 | } | 335 | } |
245 | 336 | ||
246 | static unsigned int calculate_syt(struct amdtp_out_stream *s, | 337 | static unsigned int calculate_syt(struct amdtp_stream *s, |
247 | unsigned int cycle) | 338 | unsigned int cycle) |
248 | { | 339 | { |
249 | unsigned int syt_offset, phase, index, syt; | 340 | unsigned int syt_offset, phase, index, syt; |
@@ -280,175 +371,228 @@ static unsigned int calculate_syt(struct amdtp_out_stream *s, | |||
280 | syt = (cycle + syt_offset / TICKS_PER_CYCLE) << 12; | 371 | syt = (cycle + syt_offset / TICKS_PER_CYCLE) << 12; |
281 | syt += syt_offset % TICKS_PER_CYCLE; | 372 | syt += syt_offset % TICKS_PER_CYCLE; |
282 | 373 | ||
283 | return syt & 0xffff; | 374 | return syt & CIP_SYT_MASK; |
284 | } else { | 375 | } else { |
285 | return 0xffff; /* no info */ | 376 | return CIP_SYT_NO_INFO; |
286 | } | 377 | } |
287 | } | 378 | } |
288 | 379 | ||
289 | static void amdtp_write_s32(struct amdtp_out_stream *s, | 380 | static void amdtp_write_s32(struct amdtp_stream *s, |
290 | struct snd_pcm_substream *pcm, | 381 | struct snd_pcm_substream *pcm, |
291 | __be32 *buffer, unsigned int frames) | 382 | __be32 *buffer, unsigned int frames) |
292 | { | 383 | { |
293 | struct snd_pcm_runtime *runtime = pcm->runtime; | 384 | struct snd_pcm_runtime *runtime = pcm->runtime; |
294 | unsigned int channels, remaining_frames, frame_step, i, c; | 385 | unsigned int channels, remaining_frames, i, c; |
295 | const u32 *src; | 386 | const u32 *src; |
296 | 387 | ||
297 | channels = s->pcm_channels; | 388 | channels = s->pcm_channels; |
298 | src = (void *)runtime->dma_area + | 389 | src = (void *)runtime->dma_area + |
299 | frames_to_bytes(runtime, s->pcm_buffer_pointer); | 390 | frames_to_bytes(runtime, s->pcm_buffer_pointer); |
300 | remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer; | 391 | remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer; |
301 | frame_step = s->data_block_quadlets - channels; | ||
302 | 392 | ||
303 | for (i = 0; i < frames; ++i) { | 393 | for (i = 0; i < frames; ++i) { |
304 | for (c = 0; c < channels; ++c) { | 394 | for (c = 0; c < channels; ++c) { |
305 | *buffer = cpu_to_be32((*src >> 8) | 0x40000000); | 395 | buffer[s->pcm_positions[c]] = |
396 | cpu_to_be32((*src >> 8) | 0x40000000); | ||
306 | src++; | 397 | src++; |
307 | buffer++; | ||
308 | } | 398 | } |
309 | buffer += frame_step; | 399 | buffer += s->data_block_quadlets; |
310 | if (--remaining_frames == 0) | 400 | if (--remaining_frames == 0) |
311 | src = (void *)runtime->dma_area; | 401 | src = (void *)runtime->dma_area; |
312 | } | 402 | } |
313 | } | 403 | } |
314 | 404 | ||
315 | static void amdtp_write_s16(struct amdtp_out_stream *s, | 405 | static void amdtp_write_s16(struct amdtp_stream *s, |
316 | struct snd_pcm_substream *pcm, | 406 | struct snd_pcm_substream *pcm, |
317 | __be32 *buffer, unsigned int frames) | 407 | __be32 *buffer, unsigned int frames) |
318 | { | 408 | { |
319 | struct snd_pcm_runtime *runtime = pcm->runtime; | 409 | struct snd_pcm_runtime *runtime = pcm->runtime; |
320 | unsigned int channels, remaining_frames, frame_step, i, c; | 410 | unsigned int channels, remaining_frames, i, c; |
321 | const u16 *src; | 411 | const u16 *src; |
322 | 412 | ||
323 | channels = s->pcm_channels; | 413 | channels = s->pcm_channels; |
324 | src = (void *)runtime->dma_area + | 414 | src = (void *)runtime->dma_area + |
325 | frames_to_bytes(runtime, s->pcm_buffer_pointer); | 415 | frames_to_bytes(runtime, s->pcm_buffer_pointer); |
326 | remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer; | 416 | remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer; |
327 | frame_step = s->data_block_quadlets - channels; | ||
328 | 417 | ||
329 | for (i = 0; i < frames; ++i) { | 418 | for (i = 0; i < frames; ++i) { |
330 | for (c = 0; c < channels; ++c) { | 419 | for (c = 0; c < channels; ++c) { |
331 | *buffer = cpu_to_be32((*src << 8) | 0x40000000); | 420 | buffer[s->pcm_positions[c]] = |
421 | cpu_to_be32((*src << 8) | 0x42000000); | ||
332 | src++; | 422 | src++; |
333 | buffer++; | ||
334 | } | 423 | } |
335 | buffer += frame_step; | 424 | buffer += s->data_block_quadlets; |
336 | if (--remaining_frames == 0) | 425 | if (--remaining_frames == 0) |
337 | src = (void *)runtime->dma_area; | 426 | src = (void *)runtime->dma_area; |
338 | } | 427 | } |
339 | } | 428 | } |
340 | 429 | ||
341 | static void amdtp_write_s32_dualwire(struct amdtp_out_stream *s, | 430 | static void amdtp_read_s32(struct amdtp_stream *s, |
342 | struct snd_pcm_substream *pcm, | 431 | struct snd_pcm_substream *pcm, |
343 | __be32 *buffer, unsigned int frames) | 432 | __be32 *buffer, unsigned int frames) |
344 | { | 433 | { |
345 | struct snd_pcm_runtime *runtime = pcm->runtime; | 434 | struct snd_pcm_runtime *runtime = pcm->runtime; |
346 | unsigned int channels, frame_adjust_1, frame_adjust_2, i, c; | 435 | unsigned int channels, remaining_frames, i, c; |
347 | const u32 *src; | 436 | u32 *dst; |
348 | 437 | ||
349 | channels = s->pcm_channels; | 438 | channels = s->pcm_channels; |
350 | src = (void *)runtime->dma_area + | 439 | dst = (void *)runtime->dma_area + |
351 | s->pcm_buffer_pointer * (runtime->frame_bits / 8); | 440 | frames_to_bytes(runtime, s->pcm_buffer_pointer); |
352 | frame_adjust_1 = channels - 1; | 441 | remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer; |
353 | frame_adjust_2 = 1 - (s->data_block_quadlets - channels); | ||
354 | 442 | ||
355 | channels /= 2; | ||
356 | for (i = 0; i < frames; ++i) { | 443 | for (i = 0; i < frames; ++i) { |
357 | for (c = 0; c < channels; ++c) { | 444 | for (c = 0; c < channels; ++c) { |
358 | *buffer = cpu_to_be32((*src >> 8) | 0x40000000); | 445 | *dst = be32_to_cpu(buffer[s->pcm_positions[c]]) << 8; |
359 | src++; | 446 | dst++; |
360 | buffer += 2; | ||
361 | } | ||
362 | buffer -= frame_adjust_1; | ||
363 | for (c = 0; c < channels; ++c) { | ||
364 | *buffer = cpu_to_be32((*src >> 8) | 0x40000000); | ||
365 | src++; | ||
366 | buffer += 2; | ||
367 | } | 447 | } |
368 | buffer -= frame_adjust_2; | 448 | buffer += s->data_block_quadlets; |
449 | if (--remaining_frames == 0) | ||
450 | dst = (void *)runtime->dma_area; | ||
369 | } | 451 | } |
370 | } | 452 | } |
371 | 453 | ||
372 | static void amdtp_write_s16_dualwire(struct amdtp_out_stream *s, | 454 | static void amdtp_fill_pcm_silence(struct amdtp_stream *s, |
373 | struct snd_pcm_substream *pcm, | 455 | __be32 *buffer, unsigned int frames) |
374 | __be32 *buffer, unsigned int frames) | ||
375 | { | 456 | { |
376 | struct snd_pcm_runtime *runtime = pcm->runtime; | 457 | unsigned int i, c; |
377 | unsigned int channels, frame_adjust_1, frame_adjust_2, i, c; | ||
378 | const u16 *src; | ||
379 | |||
380 | channels = s->pcm_channels; | ||
381 | src = (void *)runtime->dma_area + | ||
382 | s->pcm_buffer_pointer * (runtime->frame_bits / 8); | ||
383 | frame_adjust_1 = channels - 1; | ||
384 | frame_adjust_2 = 1 - (s->data_block_quadlets - channels); | ||
385 | 458 | ||
386 | channels /= 2; | ||
387 | for (i = 0; i < frames; ++i) { | 459 | for (i = 0; i < frames; ++i) { |
388 | for (c = 0; c < channels; ++c) { | 460 | for (c = 0; c < s->pcm_channels; ++c) |
389 | *buffer = cpu_to_be32((*src << 8) | 0x40000000); | 461 | buffer[s->pcm_positions[c]] = cpu_to_be32(0x40000000); |
390 | src++; | 462 | buffer += s->data_block_quadlets; |
391 | buffer += 2; | ||
392 | } | ||
393 | buffer -= frame_adjust_1; | ||
394 | for (c = 0; c < channels; ++c) { | ||
395 | *buffer = cpu_to_be32((*src << 8) | 0x40000000); | ||
396 | src++; | ||
397 | buffer += 2; | ||
398 | } | ||
399 | buffer -= frame_adjust_2; | ||
400 | } | 463 | } |
401 | } | 464 | } |
402 | 465 | ||
403 | static void amdtp_fill_pcm_silence(struct amdtp_out_stream *s, | 466 | static void amdtp_fill_midi(struct amdtp_stream *s, |
404 | __be32 *buffer, unsigned int frames) | 467 | __be32 *buffer, unsigned int frames) |
405 | { | 468 | { |
406 | unsigned int i, c; | 469 | unsigned int f, port; |
470 | u8 *b; | ||
471 | |||
472 | for (f = 0; f < frames; f++) { | ||
473 | buffer[s->midi_position] = 0; | ||
474 | b = (u8 *)&buffer[s->midi_position]; | ||
475 | |||
476 | port = (s->data_block_counter + f) % 8; | ||
477 | if ((f >= s->rx_blocks_for_midi) || | ||
478 | (s->midi[port] == NULL) || | ||
479 | (snd_rawmidi_transmit(s->midi[port], b + 1, 1) <= 0)) | ||
480 | b[0] = 0x80; | ||
481 | else | ||
482 | b[0] = 0x81; | ||
407 | 483 | ||
408 | for (i = 0; i < frames; ++i) { | ||
409 | for (c = 0; c < s->pcm_channels; ++c) | ||
410 | buffer[c] = cpu_to_be32(0x40000000); | ||
411 | buffer += s->data_block_quadlets; | 484 | buffer += s->data_block_quadlets; |
412 | } | 485 | } |
413 | } | 486 | } |
414 | 487 | ||
415 | static void amdtp_fill_midi(struct amdtp_out_stream *s, | 488 | static void amdtp_pull_midi(struct amdtp_stream *s, |
416 | __be32 *buffer, unsigned int frames) | 489 | __be32 *buffer, unsigned int frames) |
417 | { | 490 | { |
418 | unsigned int i; | 491 | unsigned int f, port; |
492 | int len; | ||
493 | u8 *b; | ||
494 | |||
495 | for (f = 0; f < frames; f++) { | ||
496 | port = (s->data_block_counter + f) % 8; | ||
497 | b = (u8 *)&buffer[s->midi_position]; | ||
498 | |||
499 | len = b[0] - 0x80; | ||
500 | if ((1 <= len) && (len <= 3) && (s->midi[port])) | ||
501 | snd_rawmidi_receive(s->midi[port], b + 1, len); | ||
502 | |||
503 | buffer += s->data_block_quadlets; | ||
504 | } | ||
505 | } | ||
506 | |||
507 | static void update_pcm_pointers(struct amdtp_stream *s, | ||
508 | struct snd_pcm_substream *pcm, | ||
509 | unsigned int frames) | ||
510 | { unsigned int ptr; | ||
511 | |||
512 | ptr = s->pcm_buffer_pointer + frames; | ||
513 | if (ptr >= pcm->runtime->buffer_size) | ||
514 | ptr -= pcm->runtime->buffer_size; | ||
515 | ACCESS_ONCE(s->pcm_buffer_pointer) = ptr; | ||
516 | |||
517 | s->pcm_period_pointer += frames; | ||
518 | if (s->pcm_period_pointer >= pcm->runtime->period_size) { | ||
519 | s->pcm_period_pointer -= pcm->runtime->period_size; | ||
520 | s->pointer_flush = false; | ||
521 | tasklet_hi_schedule(&s->period_tasklet); | ||
522 | } | ||
523 | } | ||
524 | |||
525 | static void pcm_period_tasklet(unsigned long data) | ||
526 | { | ||
527 | struct amdtp_stream *s = (void *)data; | ||
528 | struct snd_pcm_substream *pcm = ACCESS_ONCE(s->pcm); | ||
419 | 529 | ||
420 | for (i = 0; i < frames; ++i) | 530 | if (pcm) |
421 | buffer[s->pcm_channels + i * s->data_block_quadlets] = | 531 | snd_pcm_period_elapsed(pcm); |
422 | cpu_to_be32(0x80000000); | ||
423 | } | 532 | } |
424 | 533 | ||
425 | static void queue_out_packet(struct amdtp_out_stream *s, unsigned int cycle) | 534 | static int queue_packet(struct amdtp_stream *s, |
535 | unsigned int header_length, | ||
536 | unsigned int payload_length, bool skip) | ||
537 | { | ||
538 | struct fw_iso_packet p = {0}; | ||
539 | int err = 0; | ||
540 | |||
541 | if (IS_ERR(s->context)) | ||
542 | goto end; | ||
543 | |||
544 | p.interrupt = IS_ALIGNED(s->packet_index + 1, INTERRUPT_INTERVAL); | ||
545 | p.tag = TAG_CIP; | ||
546 | p.header_length = header_length; | ||
547 | p.payload_length = (!skip) ? payload_length : 0; | ||
548 | p.skip = skip; | ||
549 | err = fw_iso_context_queue(s->context, &p, &s->buffer.iso_buffer, | ||
550 | s->buffer.packets[s->packet_index].offset); | ||
551 | if (err < 0) { | ||
552 | dev_err(&s->unit->device, "queueing error: %d\n", err); | ||
553 | goto end; | ||
554 | } | ||
555 | |||
556 | if (++s->packet_index >= QUEUE_LENGTH) | ||
557 | s->packet_index = 0; | ||
558 | end: | ||
559 | return err; | ||
560 | } | ||
561 | |||
562 | static inline int queue_out_packet(struct amdtp_stream *s, | ||
563 | unsigned int payload_length, bool skip) | ||
564 | { | ||
565 | return queue_packet(s, OUT_PACKET_HEADER_SIZE, | ||
566 | payload_length, skip); | ||
567 | } | ||
568 | |||
569 | static inline int queue_in_packet(struct amdtp_stream *s) | ||
570 | { | ||
571 | return queue_packet(s, IN_PACKET_HEADER_SIZE, | ||
572 | amdtp_stream_get_max_payload(s), false); | ||
573 | } | ||
574 | |||
575 | static void handle_out_packet(struct amdtp_stream *s, unsigned int syt) | ||
426 | { | 576 | { |
427 | __be32 *buffer; | 577 | __be32 *buffer; |
428 | unsigned int index, data_blocks, syt, ptr; | 578 | unsigned int data_blocks, payload_length; |
429 | struct snd_pcm_substream *pcm; | 579 | struct snd_pcm_substream *pcm; |
430 | struct fw_iso_packet packet; | ||
431 | int err; | ||
432 | 580 | ||
433 | if (s->packet_index < 0) | 581 | if (s->packet_index < 0) |
434 | return; | 582 | return; |
435 | index = s->packet_index; | ||
436 | 583 | ||
437 | /* this module generate empty packet for 'no data' */ | 584 | /* this module generate empty packet for 'no data' */ |
438 | syt = calculate_syt(s, cycle); | 585 | if (!(s->flags & CIP_BLOCKING) || (syt != CIP_SYT_NO_INFO)) |
439 | if (!(s->flags & CIP_BLOCKING)) | ||
440 | data_blocks = calculate_data_blocks(s); | 586 | data_blocks = calculate_data_blocks(s); |
441 | else if (syt != 0xffff) | ||
442 | data_blocks = s->syt_interval; | ||
443 | else | 587 | else |
444 | data_blocks = 0; | 588 | data_blocks = 0; |
445 | 589 | ||
446 | buffer = s->buffer.packets[index].buffer; | 590 | buffer = s->buffer.packets[s->packet_index].buffer; |
447 | buffer[0] = cpu_to_be32(ACCESS_ONCE(s->source_node_id_field) | | 591 | buffer[0] = cpu_to_be32(ACCESS_ONCE(s->source_node_id_field) | |
448 | (s->data_block_quadlets << 16) | | 592 | (s->data_block_quadlets << AMDTP_DBS_SHIFT) | |
449 | s->data_block_counter); | 593 | s->data_block_counter); |
450 | buffer[1] = cpu_to_be32(CIP_EOH | CIP_FMT_AM | AMDTP_FDF_AM824 | | 594 | buffer[1] = cpu_to_be32(CIP_EOH | CIP_FMT_AM | AMDTP_FDF_AM824 | |
451 | (s->sfc << AMDTP_FDF_SFC_SHIFT) | syt); | 595 | (s->sfc << CIP_FDF_SFC_SHIFT) | syt); |
452 | buffer += 2; | 596 | buffer += 2; |
453 | 597 | ||
454 | pcm = ACCESS_ONCE(s->pcm); | 598 | pcm = ACCESS_ONCE(s->pcm); |
@@ -461,58 +605,127 @@ static void queue_out_packet(struct amdtp_out_stream *s, unsigned int cycle) | |||
461 | 605 | ||
462 | s->data_block_counter = (s->data_block_counter + data_blocks) & 0xff; | 606 | s->data_block_counter = (s->data_block_counter + data_blocks) & 0xff; |
463 | 607 | ||
464 | packet.payload_length = 8 + data_blocks * 4 * s->data_block_quadlets; | 608 | payload_length = 8 + data_blocks * 4 * s->data_block_quadlets; |
465 | packet.interrupt = IS_ALIGNED(index + 1, INTERRUPT_INTERVAL); | 609 | if (queue_out_packet(s, payload_length, false) < 0) { |
466 | packet.skip = 0; | ||
467 | packet.tag = TAG_CIP; | ||
468 | packet.sy = 0; | ||
469 | packet.header_length = 0; | ||
470 | |||
471 | err = fw_iso_context_queue(s->context, &packet, &s->buffer.iso_buffer, | ||
472 | s->buffer.packets[index].offset); | ||
473 | if (err < 0) { | ||
474 | dev_err(&s->unit->device, "queueing error: %d\n", err); | ||
475 | s->packet_index = -1; | 610 | s->packet_index = -1; |
476 | amdtp_out_stream_pcm_abort(s); | 611 | amdtp_stream_pcm_abort(s); |
477 | return; | 612 | return; |
478 | } | 613 | } |
479 | 614 | ||
480 | if (++index >= QUEUE_LENGTH) | 615 | if (pcm) |
481 | index = 0; | 616 | update_pcm_pointers(s, pcm, data_blocks); |
482 | s->packet_index = index; | 617 | } |
483 | 618 | ||
484 | if (pcm) { | 619 | static void handle_in_packet(struct amdtp_stream *s, |
485 | if (s->dual_wire) | 620 | unsigned int payload_quadlets, |
486 | data_blocks *= 2; | 621 | __be32 *buffer) |
487 | 622 | { | |
488 | ptr = s->pcm_buffer_pointer + data_blocks; | 623 | u32 cip_header[2]; |
489 | if (ptr >= pcm->runtime->buffer_size) | 624 | unsigned int data_blocks, data_block_quadlets, data_block_counter, |
490 | ptr -= pcm->runtime->buffer_size; | 625 | dbc_interval; |
491 | ACCESS_ONCE(s->pcm_buffer_pointer) = ptr; | 626 | struct snd_pcm_substream *pcm = NULL; |
492 | 627 | bool lost; | |
493 | s->pcm_period_pointer += data_blocks; | 628 | |
494 | if (s->pcm_period_pointer >= pcm->runtime->period_size) { | 629 | cip_header[0] = be32_to_cpu(buffer[0]); |
495 | s->pcm_period_pointer -= pcm->runtime->period_size; | 630 | cip_header[1] = be32_to_cpu(buffer[1]); |
496 | s->pointer_flush = false; | 631 | |
497 | tasklet_hi_schedule(&s->period_tasklet); | 632 | /* |
633 | * This module supports 'Two-quadlet CIP header with SYT field'. | ||
634 | * For convenience, also check FMT field is AM824 or not. | ||
635 | */ | ||
636 | if (((cip_header[0] & CIP_EOH_MASK) == CIP_EOH) || | ||
637 | ((cip_header[1] & CIP_EOH_MASK) != CIP_EOH) || | ||
638 | ((cip_header[1] & CIP_FMT_MASK) != CIP_FMT_AM)) { | ||
639 | dev_info_ratelimited(&s->unit->device, | ||
640 | "Invalid CIP header for AMDTP: %08X:%08X\n", | ||
641 | cip_header[0], cip_header[1]); | ||
642 | goto end; | ||
643 | } | ||
644 | |||
645 | /* Calculate data blocks */ | ||
646 | if (payload_quadlets < 3 || | ||
647 | ((cip_header[1] & CIP_FDF_MASK) == | ||
648 | (AMDTP_FDF_NO_DATA << CIP_FDF_SFC_SHIFT))) { | ||
649 | data_blocks = 0; | ||
650 | } else { | ||
651 | data_block_quadlets = | ||
652 | (cip_header[0] & AMDTP_DBS_MASK) >> AMDTP_DBS_SHIFT; | ||
653 | /* avoid division by zero */ | ||
654 | if (data_block_quadlets == 0) { | ||
655 | dev_info_ratelimited(&s->unit->device, | ||
656 | "Detect invalid value in dbs field: %08X\n", | ||
657 | cip_header[0]); | ||
658 | goto err; | ||
498 | } | 659 | } |
660 | if (s->flags & CIP_WRONG_DBS) | ||
661 | data_block_quadlets = s->data_block_quadlets; | ||
662 | |||
663 | data_blocks = (payload_quadlets - 2) / data_block_quadlets; | ||
499 | } | 664 | } |
500 | } | ||
501 | 665 | ||
502 | static void pcm_period_tasklet(unsigned long data) | 666 | /* Check data block counter continuity */ |
503 | { | 667 | data_block_counter = cip_header[0] & AMDTP_DBC_MASK; |
504 | struct amdtp_out_stream *s = (void *)data; | 668 | if (data_blocks == 0 && (s->flags & CIP_EMPTY_HAS_WRONG_DBC) && |
505 | struct snd_pcm_substream *pcm = ACCESS_ONCE(s->pcm); | 669 | s->data_block_counter != UINT_MAX) |
670 | data_block_counter = s->data_block_counter; | ||
671 | |||
672 | if (((s->flags & CIP_SKIP_DBC_ZERO_CHECK) && data_block_counter == 0) || | ||
673 | (s->data_block_counter == UINT_MAX)) { | ||
674 | lost = false; | ||
675 | } else if (!(s->flags & CIP_DBC_IS_END_EVENT)) { | ||
676 | lost = data_block_counter != s->data_block_counter; | ||
677 | } else { | ||
678 | if ((data_blocks > 0) && (s->tx_dbc_interval > 0)) | ||
679 | dbc_interval = s->tx_dbc_interval; | ||
680 | else | ||
681 | dbc_interval = data_blocks; | ||
682 | |||
683 | lost = data_block_counter != | ||
684 | ((s->data_block_counter + dbc_interval) & 0xff); | ||
685 | } | ||
686 | |||
687 | if (lost) { | ||
688 | dev_info(&s->unit->device, | ||
689 | "Detect discontinuity of CIP: %02X %02X\n", | ||
690 | s->data_block_counter, data_block_counter); | ||
691 | goto err; | ||
692 | } | ||
693 | |||
694 | if (data_blocks > 0) { | ||
695 | buffer += 2; | ||
696 | |||
697 | pcm = ACCESS_ONCE(s->pcm); | ||
698 | if (pcm) | ||
699 | s->transfer_samples(s, pcm, buffer, data_blocks); | ||
700 | |||
701 | if (s->midi_ports) | ||
702 | amdtp_pull_midi(s, buffer, data_blocks); | ||
703 | } | ||
704 | |||
705 | if (s->flags & CIP_DBC_IS_END_EVENT) | ||
706 | s->data_block_counter = data_block_counter; | ||
707 | else | ||
708 | s->data_block_counter = | ||
709 | (data_block_counter + data_blocks) & 0xff; | ||
710 | end: | ||
711 | if (queue_in_packet(s) < 0) | ||
712 | goto err; | ||
506 | 713 | ||
507 | if (pcm) | 714 | if (pcm) |
508 | snd_pcm_period_elapsed(pcm); | 715 | update_pcm_pointers(s, pcm, data_blocks); |
716 | |||
717 | return; | ||
718 | err: | ||
719 | s->packet_index = -1; | ||
720 | amdtp_stream_pcm_abort(s); | ||
509 | } | 721 | } |
510 | 722 | ||
511 | static void out_packet_callback(struct fw_iso_context *context, u32 cycle, | 723 | static void out_stream_callback(struct fw_iso_context *context, u32 cycle, |
512 | size_t header_length, void *header, void *data) | 724 | size_t header_length, void *header, |
725 | void *private_data) | ||
513 | { | 726 | { |
514 | struct amdtp_out_stream *s = data; | 727 | struct amdtp_stream *s = private_data; |
515 | unsigned int i, packets = header_length / 4; | 728 | unsigned int i, syt, packets = header_length / 4; |
516 | 729 | ||
517 | /* | 730 | /* |
518 | * Compute the cycle of the last queued packet. | 731 | * Compute the cycle of the last queued packet. |
@@ -521,43 +734,102 @@ static void out_packet_callback(struct fw_iso_context *context, u32 cycle, | |||
521 | */ | 734 | */ |
522 | cycle += QUEUE_LENGTH - packets; | 735 | cycle += QUEUE_LENGTH - packets; |
523 | 736 | ||
524 | for (i = 0; i < packets; ++i) | 737 | for (i = 0; i < packets; ++i) { |
525 | queue_out_packet(s, ++cycle); | 738 | syt = calculate_syt(s, ++cycle); |
739 | handle_out_packet(s, syt); | ||
740 | } | ||
526 | fw_iso_context_queue_flush(s->context); | 741 | fw_iso_context_queue_flush(s->context); |
527 | } | 742 | } |
528 | 743 | ||
529 | static int queue_initial_skip_packets(struct amdtp_out_stream *s) | 744 | static void in_stream_callback(struct fw_iso_context *context, u32 cycle, |
745 | size_t header_length, void *header, | ||
746 | void *private_data) | ||
530 | { | 747 | { |
531 | struct fw_iso_packet skip_packet = { | 748 | struct amdtp_stream *s = private_data; |
532 | .skip = 1, | 749 | unsigned int p, syt, packets, payload_quadlets; |
533 | }; | 750 | __be32 *buffer, *headers = header; |
534 | unsigned int i; | ||
535 | int err; | ||
536 | 751 | ||
537 | for (i = 0; i < QUEUE_LENGTH; ++i) { | 752 | /* The number of packets in buffer */ |
538 | skip_packet.interrupt = IS_ALIGNED(s->packet_index + 1, | 753 | packets = header_length / IN_PACKET_HEADER_SIZE; |
539 | INTERRUPT_INTERVAL); | 754 | |
540 | err = fw_iso_context_queue(s->context, &skip_packet, NULL, 0); | 755 | for (p = 0; p < packets; p++) { |
541 | if (err < 0) | 756 | if (s->packet_index < 0) |
542 | return err; | 757 | break; |
543 | if (++s->packet_index >= QUEUE_LENGTH) | 758 | |
544 | s->packet_index = 0; | 759 | buffer = s->buffer.packets[s->packet_index].buffer; |
760 | |||
761 | /* Process sync slave stream */ | ||
762 | if (s->sync_slave && s->sync_slave->callbacked) { | ||
763 | syt = be32_to_cpu(buffer[1]) & CIP_SYT_MASK; | ||
764 | handle_out_packet(s->sync_slave, syt); | ||
765 | } | ||
766 | |||
767 | /* The number of quadlets in this packet */ | ||
768 | payload_quadlets = | ||
769 | (be32_to_cpu(headers[p]) >> ISO_DATA_LENGTH_SHIFT) / 4; | ||
770 | handle_in_packet(s, payload_quadlets, buffer); | ||
545 | } | 771 | } |
546 | 772 | ||
547 | return 0; | 773 | /* Queueing error or detecting discontinuity */ |
774 | if (s->packet_index < 0) { | ||
775 | /* Abort sync slave. */ | ||
776 | if (s->sync_slave) { | ||
777 | s->sync_slave->packet_index = -1; | ||
778 | amdtp_stream_pcm_abort(s->sync_slave); | ||
779 | } | ||
780 | return; | ||
781 | } | ||
782 | |||
783 | /* when sync to device, flush the packets for slave stream */ | ||
784 | if (s->sync_slave && s->sync_slave->callbacked) | ||
785 | fw_iso_context_queue_flush(s->sync_slave->context); | ||
786 | |||
787 | fw_iso_context_queue_flush(s->context); | ||
788 | } | ||
789 | |||
790 | /* processing is done by master callback */ | ||
791 | static void slave_stream_callback(struct fw_iso_context *context, u32 cycle, | ||
792 | size_t header_length, void *header, | ||
793 | void *private_data) | ||
794 | { | ||
795 | return; | ||
796 | } | ||
797 | |||
798 | /* this is executed one time */ | ||
799 | static void amdtp_stream_first_callback(struct fw_iso_context *context, | ||
800 | u32 cycle, size_t header_length, | ||
801 | void *header, void *private_data) | ||
802 | { | ||
803 | struct amdtp_stream *s = private_data; | ||
804 | |||
805 | /* | ||
806 | * For in-stream, first packet has come. | ||
807 | * For out-stream, prepared to transmit first packet | ||
808 | */ | ||
809 | s->callbacked = true; | ||
810 | wake_up(&s->callback_wait); | ||
811 | |||
812 | if (s->direction == AMDTP_IN_STREAM) | ||
813 | context->callback.sc = in_stream_callback; | ||
814 | else if ((s->flags & CIP_BLOCKING) && (s->flags & CIP_SYNC_TO_DEVICE)) | ||
815 | context->callback.sc = slave_stream_callback; | ||
816 | else | ||
817 | context->callback.sc = out_stream_callback; | ||
818 | |||
819 | context->callback.sc(context, cycle, header_length, header, s); | ||
548 | } | 820 | } |
549 | 821 | ||
550 | /** | 822 | /** |
551 | * amdtp_out_stream_start - start sending packets | 823 | * amdtp_stream_start - start transferring packets |
552 | * @s: the AMDTP output stream to start | 824 | * @s: the AMDTP stream to start |
553 | * @channel: the isochronous channel on the bus | 825 | * @channel: the isochronous channel on the bus |
554 | * @speed: firewire speed code | 826 | * @speed: firewire speed code |
555 | * | 827 | * |
556 | * The stream cannot be started until it has been configured with | 828 | * The stream cannot be started until it has been configured with |
557 | * amdtp_out_stream_set_parameters() and amdtp_out_stream_set_pcm_format(), | 829 | * amdtp_stream_set_parameters() and it must be started before any PCM or MIDI |
558 | * and it must be started before any PCM or MIDI device can be started. | 830 | * device can be started. |
559 | */ | 831 | */ |
560 | int amdtp_out_stream_start(struct amdtp_out_stream *s, int channel, int speed) | 832 | int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed) |
561 | { | 833 | { |
562 | static const struct { | 834 | static const struct { |
563 | unsigned int data_block; | 835 | unsigned int data_block; |
@@ -571,47 +843,72 @@ int amdtp_out_stream_start(struct amdtp_out_stream *s, int channel, int speed) | |||
571 | [CIP_SFC_88200] = { 0, 67 }, | 843 | [CIP_SFC_88200] = { 0, 67 }, |
572 | [CIP_SFC_176400] = { 0, 67 }, | 844 | [CIP_SFC_176400] = { 0, 67 }, |
573 | }; | 845 | }; |
574 | int err; | 846 | unsigned int header_size; |
847 | enum dma_data_direction dir; | ||
848 | int type, tag, err; | ||
575 | 849 | ||
576 | mutex_lock(&s->mutex); | 850 | mutex_lock(&s->mutex); |
577 | 851 | ||
578 | if (WARN_ON(amdtp_out_stream_running(s) || | 852 | if (WARN_ON(amdtp_stream_running(s) || |
579 | (!s->pcm_channels && !s->midi_ports))) { | 853 | (s->data_block_quadlets < 1))) { |
580 | err = -EBADFD; | 854 | err = -EBADFD; |
581 | goto err_unlock; | 855 | goto err_unlock; |
582 | } | 856 | } |
583 | 857 | ||
858 | if (s->direction == AMDTP_IN_STREAM && | ||
859 | s->flags & CIP_SKIP_INIT_DBC_CHECK) | ||
860 | s->data_block_counter = UINT_MAX; | ||
861 | else | ||
862 | s->data_block_counter = 0; | ||
584 | s->data_block_state = initial_state[s->sfc].data_block; | 863 | s->data_block_state = initial_state[s->sfc].data_block; |
585 | s->syt_offset_state = initial_state[s->sfc].syt_offset; | 864 | s->syt_offset_state = initial_state[s->sfc].syt_offset; |
586 | s->last_syt_offset = TICKS_PER_CYCLE; | 865 | s->last_syt_offset = TICKS_PER_CYCLE; |
587 | 866 | ||
867 | /* initialize packet buffer */ | ||
868 | if (s->direction == AMDTP_IN_STREAM) { | ||
869 | dir = DMA_FROM_DEVICE; | ||
870 | type = FW_ISO_CONTEXT_RECEIVE; | ||
871 | header_size = IN_PACKET_HEADER_SIZE; | ||
872 | } else { | ||
873 | dir = DMA_TO_DEVICE; | ||
874 | type = FW_ISO_CONTEXT_TRANSMIT; | ||
875 | header_size = OUT_PACKET_HEADER_SIZE; | ||
876 | } | ||
588 | err = iso_packets_buffer_init(&s->buffer, s->unit, QUEUE_LENGTH, | 877 | err = iso_packets_buffer_init(&s->buffer, s->unit, QUEUE_LENGTH, |
589 | amdtp_out_stream_get_max_payload(s), | 878 | amdtp_stream_get_max_payload(s), dir); |
590 | DMA_TO_DEVICE); | ||
591 | if (err < 0) | 879 | if (err < 0) |
592 | goto err_unlock; | 880 | goto err_unlock; |
593 | 881 | ||
594 | s->context = fw_iso_context_create(fw_parent_device(s->unit)->card, | 882 | s->context = fw_iso_context_create(fw_parent_device(s->unit)->card, |
595 | FW_ISO_CONTEXT_TRANSMIT, | 883 | type, channel, speed, header_size, |
596 | channel, speed, 0, | 884 | amdtp_stream_first_callback, s); |
597 | out_packet_callback, s); | ||
598 | if (IS_ERR(s->context)) { | 885 | if (IS_ERR(s->context)) { |
599 | err = PTR_ERR(s->context); | 886 | err = PTR_ERR(s->context); |
600 | if (err == -EBUSY) | 887 | if (err == -EBUSY) |
601 | dev_err(&s->unit->device, | 888 | dev_err(&s->unit->device, |
602 | "no free output stream on this controller\n"); | 889 | "no free stream on this controller\n"); |
603 | goto err_buffer; | 890 | goto err_buffer; |
604 | } | 891 | } |
605 | 892 | ||
606 | amdtp_out_stream_update(s); | 893 | amdtp_stream_update(s); |
607 | 894 | ||
608 | s->packet_index = 0; | 895 | s->packet_index = 0; |
609 | s->data_block_counter = 0; | 896 | do { |
610 | err = queue_initial_skip_packets(s); | 897 | if (s->direction == AMDTP_IN_STREAM) |
611 | if (err < 0) | 898 | err = queue_in_packet(s); |
612 | goto err_context; | 899 | else |
900 | err = queue_out_packet(s, 0, true); | ||
901 | if (err < 0) | ||
902 | goto err_context; | ||
903 | } while (s->packet_index > 0); | ||
613 | 904 | ||
614 | err = fw_iso_context_start(s->context, -1, 0, 0); | 905 | /* NOTE: TAG1 matches CIP. This just affects in stream. */ |
906 | tag = FW_ISO_CONTEXT_MATCH_TAG1; | ||
907 | if (s->flags & CIP_EMPTY_WITH_TAG0) | ||
908 | tag |= FW_ISO_CONTEXT_MATCH_TAG0; | ||
909 | |||
910 | s->callbacked = false; | ||
911 | err = fw_iso_context_start(s->context, -1, 0, tag); | ||
615 | if (err < 0) | 912 | if (err < 0) |
616 | goto err_context; | 913 | goto err_context; |
617 | 914 | ||
@@ -629,49 +926,49 @@ err_unlock: | |||
629 | 926 | ||
630 | return err; | 927 | return err; |
631 | } | 928 | } |
632 | EXPORT_SYMBOL(amdtp_out_stream_start); | 929 | EXPORT_SYMBOL(amdtp_stream_start); |
633 | 930 | ||
634 | /** | 931 | /** |
635 | * amdtp_out_stream_pcm_pointer - get the PCM buffer position | 932 | * amdtp_stream_pcm_pointer - get the PCM buffer position |
636 | * @s: the AMDTP output stream that transports the PCM data | 933 | * @s: the AMDTP stream that transports the PCM data |
637 | * | 934 | * |
638 | * Returns the current buffer position, in frames. | 935 | * Returns the current buffer position, in frames. |
639 | */ | 936 | */ |
640 | unsigned long amdtp_out_stream_pcm_pointer(struct amdtp_out_stream *s) | 937 | unsigned long amdtp_stream_pcm_pointer(struct amdtp_stream *s) |
641 | { | 938 | { |
642 | /* this optimization is allowed to be racy */ | 939 | /* this optimization is allowed to be racy */ |
643 | if (s->pointer_flush) | 940 | if (s->pointer_flush && amdtp_stream_running(s)) |
644 | fw_iso_context_flush_completions(s->context); | 941 | fw_iso_context_flush_completions(s->context); |
645 | else | 942 | else |
646 | s->pointer_flush = true; | 943 | s->pointer_flush = true; |
647 | 944 | ||
648 | return ACCESS_ONCE(s->pcm_buffer_pointer); | 945 | return ACCESS_ONCE(s->pcm_buffer_pointer); |
649 | } | 946 | } |
650 | EXPORT_SYMBOL(amdtp_out_stream_pcm_pointer); | 947 | EXPORT_SYMBOL(amdtp_stream_pcm_pointer); |
651 | 948 | ||
652 | /** | 949 | /** |
653 | * amdtp_out_stream_update - update the stream after a bus reset | 950 | * amdtp_stream_update - update the stream after a bus reset |
654 | * @s: the AMDTP output stream | 951 | * @s: the AMDTP stream |
655 | */ | 952 | */ |
656 | void amdtp_out_stream_update(struct amdtp_out_stream *s) | 953 | void amdtp_stream_update(struct amdtp_stream *s) |
657 | { | 954 | { |
658 | ACCESS_ONCE(s->source_node_id_field) = | 955 | ACCESS_ONCE(s->source_node_id_field) = |
659 | (fw_parent_device(s->unit)->card->node_id & 0x3f) << 24; | 956 | (fw_parent_device(s->unit)->card->node_id & 0x3f) << 24; |
660 | } | 957 | } |
661 | EXPORT_SYMBOL(amdtp_out_stream_update); | 958 | EXPORT_SYMBOL(amdtp_stream_update); |
662 | 959 | ||
663 | /** | 960 | /** |
664 | * amdtp_out_stream_stop - stop sending packets | 961 | * amdtp_stream_stop - stop sending packets |
665 | * @s: the AMDTP output stream to stop | 962 | * @s: the AMDTP stream to stop |
666 | * | 963 | * |
667 | * All PCM and MIDI devices of the stream must be stopped before the stream | 964 | * All PCM and MIDI devices of the stream must be stopped before the stream |
668 | * itself can be stopped. | 965 | * itself can be stopped. |
669 | */ | 966 | */ |
670 | void amdtp_out_stream_stop(struct amdtp_out_stream *s) | 967 | void amdtp_stream_stop(struct amdtp_stream *s) |
671 | { | 968 | { |
672 | mutex_lock(&s->mutex); | 969 | mutex_lock(&s->mutex); |
673 | 970 | ||
674 | if (!amdtp_out_stream_running(s)) { | 971 | if (!amdtp_stream_running(s)) { |
675 | mutex_unlock(&s->mutex); | 972 | mutex_unlock(&s->mutex); |
676 | return; | 973 | return; |
677 | } | 974 | } |
@@ -682,18 +979,20 @@ void amdtp_out_stream_stop(struct amdtp_out_stream *s) | |||
682 | s->context = ERR_PTR(-1); | 979 | s->context = ERR_PTR(-1); |
683 | iso_packets_buffer_destroy(&s->buffer, s->unit); | 980 | iso_packets_buffer_destroy(&s->buffer, s->unit); |
684 | 981 | ||
982 | s->callbacked = false; | ||
983 | |||
685 | mutex_unlock(&s->mutex); | 984 | mutex_unlock(&s->mutex); |
686 | } | 985 | } |
687 | EXPORT_SYMBOL(amdtp_out_stream_stop); | 986 | EXPORT_SYMBOL(amdtp_stream_stop); |
688 | 987 | ||
689 | /** | 988 | /** |
690 | * amdtp_out_stream_pcm_abort - abort the running PCM device | 989 | * amdtp_stream_pcm_abort - abort the running PCM device |
691 | * @s: the AMDTP stream about to be stopped | 990 | * @s: the AMDTP stream about to be stopped |
692 | * | 991 | * |
693 | * If the isochronous stream needs to be stopped asynchronously, call this | 992 | * If the isochronous stream needs to be stopped asynchronously, call this |
694 | * function first to stop the PCM device. | 993 | * function first to stop the PCM device. |
695 | */ | 994 | */ |
696 | void amdtp_out_stream_pcm_abort(struct amdtp_out_stream *s) | 995 | void amdtp_stream_pcm_abort(struct amdtp_stream *s) |
697 | { | 996 | { |
698 | struct snd_pcm_substream *pcm; | 997 | struct snd_pcm_substream *pcm; |
699 | 998 | ||
@@ -705,4 +1004,4 @@ void amdtp_out_stream_pcm_abort(struct amdtp_out_stream *s) | |||
705 | snd_pcm_stream_unlock_irq(pcm); | 1004 | snd_pcm_stream_unlock_irq(pcm); |
706 | } | 1005 | } |
707 | } | 1006 | } |
708 | EXPORT_SYMBOL(amdtp_out_stream_pcm_abort); | 1007 | EXPORT_SYMBOL(amdtp_stream_pcm_abort); |
diff --git a/sound/firewire/amdtp.h b/sound/firewire/amdtp.h index 2746ecd291af..d8ee7b0e9386 100644 --- a/sound/firewire/amdtp.h +++ b/sound/firewire/amdtp.h | |||
@@ -8,7 +8,7 @@ | |||
8 | #include "packets-buffer.h" | 8 | #include "packets-buffer.h" |
9 | 9 | ||
10 | /** | 10 | /** |
11 | * enum cip_out_flags - describes details of the streaming protocol | 11 | * enum cip_flags - describes details of the streaming protocol |
12 | * @CIP_NONBLOCKING: In non-blocking mode, each packet contains | 12 | * @CIP_NONBLOCKING: In non-blocking mode, each packet contains |
13 | * sample_rate/8000 samples, with rounding up or down to adjust | 13 | * sample_rate/8000 samples, with rounding up or down to adjust |
14 | * for clock skew and left-over fractional samples. This should | 14 | * for clock skew and left-over fractional samples. This should |
@@ -16,15 +16,30 @@ | |||
16 | * @CIP_BLOCKING: In blocking mode, each packet contains either zero or | 16 | * @CIP_BLOCKING: In blocking mode, each packet contains either zero or |
17 | * SYT_INTERVAL samples, with these two types alternating so that | 17 | * SYT_INTERVAL samples, with these two types alternating so that |
18 | * the overall sample rate comes out right. | 18 | * the overall sample rate comes out right. |
19 | * @CIP_HI_DUALWIRE: At rates above 96 kHz, pretend that the stream runs | 19 | * @CIP_SYNC_TO_DEVICE: In sync to device mode, time stamp in out packets is |
20 | * at half the actual sample rate with twice the number of channels; | 20 | * generated by in packets. Defaultly this driver generates timestamp. |
21 | * two samples of a channel are stored consecutively in the packet. | 21 | * @CIP_EMPTY_WITH_TAG0: Only for in-stream. Empty in-packets have TAG0. |
22 | * Requires blocking mode and SYT_INTERVAL-aligned PCM buffer size. | 22 | * @CIP_DBC_IS_END_EVENT: Only for in-stream. The value of dbc in an in-packet |
23 | * corresponds to the end of event in the packet. Out of IEC 61883. | ||
24 | * @CIP_WRONG_DBS: Only for in-stream. The value of dbs is wrong in in-packets. | ||
25 | * The value of data_block_quadlets is used instead of reported value. | ||
26 | * @SKIP_DBC_ZERO_CHECK: Only for in-stream. Packets with zero in dbc is | ||
27 | * skipped for detecting discontinuity. | ||
28 | * @CIP_SKIP_INIT_DBC_CHECK: Only for in-stream. The value of dbc in first | ||
29 | * packet is not continuous from an initial value. | ||
30 | * @CIP_EMPTY_HAS_WRONG_DBC: Only for in-stream. The value of dbc in empty | ||
31 | * packet is wrong but the others are correct. | ||
23 | */ | 32 | */ |
24 | enum cip_out_flags { | 33 | enum cip_flags { |
25 | CIP_NONBLOCKING = 0x00, | 34 | CIP_NONBLOCKING = 0x00, |
26 | CIP_BLOCKING = 0x01, | 35 | CIP_BLOCKING = 0x01, |
27 | CIP_HI_DUALWIRE = 0x02, | 36 | CIP_SYNC_TO_DEVICE = 0x02, |
37 | CIP_EMPTY_WITH_TAG0 = 0x04, | ||
38 | CIP_DBC_IS_END_EVENT = 0x08, | ||
39 | CIP_WRONG_DBS = 0x10, | ||
40 | CIP_SKIP_DBC_ZERO_CHECK = 0x20, | ||
41 | CIP_SKIP_INIT_DBC_CHECK = 0x40, | ||
42 | CIP_EMPTY_HAS_WRONG_DBC = 0x80, | ||
28 | }; | 43 | }; |
29 | 44 | ||
30 | /** | 45 | /** |
@@ -41,27 +56,55 @@ enum cip_sfc { | |||
41 | CIP_SFC_COUNT | 56 | CIP_SFC_COUNT |
42 | }; | 57 | }; |
43 | 58 | ||
59 | #define AMDTP_IN_PCM_FORMAT_BITS SNDRV_PCM_FMTBIT_S32 | ||
60 | |||
44 | #define AMDTP_OUT_PCM_FORMAT_BITS (SNDRV_PCM_FMTBIT_S16 | \ | 61 | #define AMDTP_OUT_PCM_FORMAT_BITS (SNDRV_PCM_FMTBIT_S16 | \ |
45 | SNDRV_PCM_FMTBIT_S32) | 62 | SNDRV_PCM_FMTBIT_S32) |
46 | 63 | ||
64 | |||
65 | /* | ||
66 | * This module supports maximum 64 PCM channels for one PCM stream | ||
67 | * This is for our convenience. | ||
68 | */ | ||
69 | #define AMDTP_MAX_CHANNELS_FOR_PCM 64 | ||
70 | |||
71 | /* | ||
72 | * AMDTP packet can include channels for MIDI conformant data. | ||
73 | * Each MIDI conformant data channel includes 8 MPX-MIDI data stream. | ||
74 | * Each MPX-MIDI data stream includes one data stream from/to MIDI ports. | ||
75 | * | ||
76 | * This module supports maximum 1 MIDI conformant data channels. | ||
77 | * Then this AMDTP packets can transfer maximum 8 MIDI data streams. | ||
78 | */ | ||
79 | #define AMDTP_MAX_CHANNELS_FOR_MIDI 1 | ||
80 | |||
47 | struct fw_unit; | 81 | struct fw_unit; |
48 | struct fw_iso_context; | 82 | struct fw_iso_context; |
49 | struct snd_pcm_substream; | 83 | struct snd_pcm_substream; |
84 | struct snd_pcm_runtime; | ||
85 | struct snd_rawmidi_substream; | ||
50 | 86 | ||
51 | struct amdtp_out_stream { | 87 | enum amdtp_stream_direction { |
88 | AMDTP_OUT_STREAM = 0, | ||
89 | AMDTP_IN_STREAM | ||
90 | }; | ||
91 | |||
92 | struct amdtp_stream { | ||
52 | struct fw_unit *unit; | 93 | struct fw_unit *unit; |
53 | enum cip_out_flags flags; | 94 | enum cip_flags flags; |
95 | enum amdtp_stream_direction direction; | ||
54 | struct fw_iso_context *context; | 96 | struct fw_iso_context *context; |
55 | struct mutex mutex; | 97 | struct mutex mutex; |
56 | 98 | ||
57 | enum cip_sfc sfc; | 99 | enum cip_sfc sfc; |
58 | bool dual_wire; | ||
59 | unsigned int data_block_quadlets; | 100 | unsigned int data_block_quadlets; |
60 | unsigned int pcm_channels; | 101 | unsigned int pcm_channels; |
61 | unsigned int midi_ports; | 102 | unsigned int midi_ports; |
62 | void (*transfer_samples)(struct amdtp_out_stream *s, | 103 | void (*transfer_samples)(struct amdtp_stream *s, |
63 | struct snd_pcm_substream *pcm, | 104 | struct snd_pcm_substream *pcm, |
64 | __be32 *buffer, unsigned int frames); | 105 | __be32 *buffer, unsigned int frames); |
106 | u8 pcm_positions[AMDTP_MAX_CHANNELS_FOR_PCM]; | ||
107 | u8 midi_position; | ||
65 | 108 | ||
66 | unsigned int syt_interval; | 109 | unsigned int syt_interval; |
67 | unsigned int transfer_delay; | 110 | unsigned int transfer_delay; |
@@ -82,65 +125,148 @@ struct amdtp_out_stream { | |||
82 | unsigned int pcm_buffer_pointer; | 125 | unsigned int pcm_buffer_pointer; |
83 | unsigned int pcm_period_pointer; | 126 | unsigned int pcm_period_pointer; |
84 | bool pointer_flush; | 127 | bool pointer_flush; |
128 | |||
129 | struct snd_rawmidi_substream *midi[AMDTP_MAX_CHANNELS_FOR_MIDI * 8]; | ||
130 | |||
131 | /* quirk: fixed interval of dbc between previos/current packets. */ | ||
132 | unsigned int tx_dbc_interval; | ||
133 | |||
134 | /* quirk: the first count of data blocks in an rx packet for MIDI */ | ||
135 | unsigned int rx_blocks_for_midi; | ||
136 | |||
137 | bool callbacked; | ||
138 | wait_queue_head_t callback_wait; | ||
139 | struct amdtp_stream *sync_slave; | ||
85 | }; | 140 | }; |
86 | 141 | ||
87 | int amdtp_out_stream_init(struct amdtp_out_stream *s, struct fw_unit *unit, | 142 | int amdtp_stream_init(struct amdtp_stream *s, struct fw_unit *unit, |
88 | enum cip_out_flags flags); | 143 | enum amdtp_stream_direction dir, |
89 | void amdtp_out_stream_destroy(struct amdtp_out_stream *s); | 144 | enum cip_flags flags); |
145 | void amdtp_stream_destroy(struct amdtp_stream *s); | ||
90 | 146 | ||
91 | void amdtp_out_stream_set_parameters(struct amdtp_out_stream *s, | 147 | void amdtp_stream_set_parameters(struct amdtp_stream *s, |
92 | unsigned int rate, | 148 | unsigned int rate, |
93 | unsigned int pcm_channels, | 149 | unsigned int pcm_channels, |
94 | unsigned int midi_ports); | 150 | unsigned int midi_ports); |
95 | unsigned int amdtp_out_stream_get_max_payload(struct amdtp_out_stream *s); | 151 | unsigned int amdtp_stream_get_max_payload(struct amdtp_stream *s); |
96 | 152 | ||
97 | int amdtp_out_stream_start(struct amdtp_out_stream *s, int channel, int speed); | 153 | int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed); |
98 | void amdtp_out_stream_update(struct amdtp_out_stream *s); | 154 | void amdtp_stream_update(struct amdtp_stream *s); |
99 | void amdtp_out_stream_stop(struct amdtp_out_stream *s); | 155 | void amdtp_stream_stop(struct amdtp_stream *s); |
100 | 156 | ||
101 | void amdtp_out_stream_set_pcm_format(struct amdtp_out_stream *s, | 157 | int amdtp_stream_add_pcm_hw_constraints(struct amdtp_stream *s, |
102 | snd_pcm_format_t format); | 158 | struct snd_pcm_runtime *runtime); |
103 | void amdtp_out_stream_pcm_prepare(struct amdtp_out_stream *s); | 159 | void amdtp_stream_set_pcm_format(struct amdtp_stream *s, |
104 | unsigned long amdtp_out_stream_pcm_pointer(struct amdtp_out_stream *s); | 160 | snd_pcm_format_t format); |
105 | void amdtp_out_stream_pcm_abort(struct amdtp_out_stream *s); | 161 | void amdtp_stream_pcm_prepare(struct amdtp_stream *s); |
162 | unsigned long amdtp_stream_pcm_pointer(struct amdtp_stream *s); | ||
163 | void amdtp_stream_pcm_abort(struct amdtp_stream *s); | ||
106 | 164 | ||
107 | extern const unsigned int amdtp_syt_intervals[CIP_SFC_COUNT]; | 165 | extern const unsigned int amdtp_syt_intervals[CIP_SFC_COUNT]; |
166 | extern const unsigned int amdtp_rate_table[CIP_SFC_COUNT]; | ||
108 | 167 | ||
109 | static inline bool amdtp_out_stream_running(struct amdtp_out_stream *s) | 168 | /** |
169 | * amdtp_stream_running - check stream is running or not | ||
170 | * @s: the AMDTP stream | ||
171 | * | ||
172 | * If this function returns true, the stream is running. | ||
173 | */ | ||
174 | static inline bool amdtp_stream_running(struct amdtp_stream *s) | ||
110 | { | 175 | { |
111 | return !IS_ERR(s->context); | 176 | return !IS_ERR(s->context); |
112 | } | 177 | } |
113 | 178 | ||
114 | /** | 179 | /** |
115 | * amdtp_out_streaming_error - check for streaming error | 180 | * amdtp_streaming_error - check for streaming error |
116 | * @s: the AMDTP output stream | 181 | * @s: the AMDTP stream |
117 | * | 182 | * |
118 | * If this function returns true, the stream's packet queue has stopped due to | 183 | * If this function returns true, the stream's packet queue has stopped due to |
119 | * an asynchronous error. | 184 | * an asynchronous error. |
120 | */ | 185 | */ |
121 | static inline bool amdtp_out_streaming_error(struct amdtp_out_stream *s) | 186 | static inline bool amdtp_streaming_error(struct amdtp_stream *s) |
122 | { | 187 | { |
123 | return s->packet_index < 0; | 188 | return s->packet_index < 0; |
124 | } | 189 | } |
125 | 190 | ||
126 | /** | 191 | /** |
127 | * amdtp_out_stream_pcm_trigger - start/stop playback from a PCM device | 192 | * amdtp_stream_pcm_running - check PCM substream is running or not |
128 | * @s: the AMDTP output stream | 193 | * @s: the AMDTP stream |
194 | * | ||
195 | * If this function returns true, PCM substream in the AMDTP stream is running. | ||
196 | */ | ||
197 | static inline bool amdtp_stream_pcm_running(struct amdtp_stream *s) | ||
198 | { | ||
199 | return !!s->pcm; | ||
200 | } | ||
201 | |||
202 | /** | ||
203 | * amdtp_stream_pcm_trigger - start/stop playback from a PCM device | ||
204 | * @s: the AMDTP stream | ||
129 | * @pcm: the PCM device to be started, or %NULL to stop the current device | 205 | * @pcm: the PCM device to be started, or %NULL to stop the current device |
130 | * | 206 | * |
131 | * Call this function on a running isochronous stream to enable the actual | 207 | * Call this function on a running isochronous stream to enable the actual |
132 | * transmission of PCM data. This function should be called from the PCM | 208 | * transmission of PCM data. This function should be called from the PCM |
133 | * device's .trigger callback. | 209 | * device's .trigger callback. |
134 | */ | 210 | */ |
135 | static inline void amdtp_out_stream_pcm_trigger(struct amdtp_out_stream *s, | 211 | static inline void amdtp_stream_pcm_trigger(struct amdtp_stream *s, |
136 | struct snd_pcm_substream *pcm) | 212 | struct snd_pcm_substream *pcm) |
137 | { | 213 | { |
138 | ACCESS_ONCE(s->pcm) = pcm; | 214 | ACCESS_ONCE(s->pcm) = pcm; |
139 | } | 215 | } |
140 | 216 | ||
217 | /** | ||
218 | * amdtp_stream_midi_trigger - start/stop playback/capture with a MIDI device | ||
219 | * @s: the AMDTP stream | ||
220 | * @port: index of MIDI port | ||
221 | * @midi: the MIDI device to be started, or %NULL to stop the current device | ||
222 | * | ||
223 | * Call this function on a running isochronous stream to enable the actual | ||
224 | * transmission of MIDI data. This function should be called from the MIDI | ||
225 | * device's .trigger callback. | ||
226 | */ | ||
227 | static inline void amdtp_stream_midi_trigger(struct amdtp_stream *s, | ||
228 | unsigned int port, | ||
229 | struct snd_rawmidi_substream *midi) | ||
230 | { | ||
231 | if (port < s->midi_ports) | ||
232 | ACCESS_ONCE(s->midi[port]) = midi; | ||
233 | } | ||
234 | |||
141 | static inline bool cip_sfc_is_base_44100(enum cip_sfc sfc) | 235 | static inline bool cip_sfc_is_base_44100(enum cip_sfc sfc) |
142 | { | 236 | { |
143 | return sfc & 1; | 237 | return sfc & 1; |
144 | } | 238 | } |
145 | 239 | ||
240 | static inline void amdtp_stream_set_sync(enum cip_flags sync_mode, | ||
241 | struct amdtp_stream *master, | ||
242 | struct amdtp_stream *slave) | ||
243 | { | ||
244 | if (sync_mode == CIP_SYNC_TO_DEVICE) { | ||
245 | master->flags |= CIP_SYNC_TO_DEVICE; | ||
246 | slave->flags |= CIP_SYNC_TO_DEVICE; | ||
247 | master->sync_slave = slave; | ||
248 | } else { | ||
249 | master->flags &= ~CIP_SYNC_TO_DEVICE; | ||
250 | slave->flags &= ~CIP_SYNC_TO_DEVICE; | ||
251 | master->sync_slave = NULL; | ||
252 | } | ||
253 | |||
254 | slave->sync_slave = NULL; | ||
255 | } | ||
256 | |||
257 | /** | ||
258 | * amdtp_stream_wait_callback - sleep till callbacked or timeout | ||
259 | * @s: the AMDTP stream | ||
260 | * @timeout: msec till timeout | ||
261 | * | ||
262 | * If this function return false, the AMDTP stream should be stopped. | ||
263 | */ | ||
264 | static inline bool amdtp_stream_wait_callback(struct amdtp_stream *s, | ||
265 | unsigned int timeout) | ||
266 | { | ||
267 | return wait_event_timeout(s->callback_wait, | ||
268 | s->callbacked == true, | ||
269 | msecs_to_jiffies(timeout)) > 0; | ||
270 | } | ||
271 | |||
146 | #endif | 272 | #endif |
diff --git a/sound/firewire/bebob/Makefile b/sound/firewire/bebob/Makefile new file mode 100644 index 000000000000..6cf470c80d1f --- /dev/null +++ b/sound/firewire/bebob/Makefile | |||
@@ -0,0 +1,4 @@ | |||
1 | snd-bebob-objs := bebob_command.o bebob_stream.o bebob_proc.o bebob_midi.o \ | ||
2 | bebob_pcm.o bebob_hwdep.o bebob_terratec.o bebob_yamaha.o \ | ||
3 | bebob_focusrite.o bebob_maudio.o bebob.o | ||
4 | obj-m += snd-bebob.o | ||
diff --git a/sound/firewire/bebob/bebob.c b/sound/firewire/bebob/bebob.c new file mode 100644 index 000000000000..fc19c99654aa --- /dev/null +++ b/sound/firewire/bebob/bebob.c | |||
@@ -0,0 +1,471 @@ | |||
1 | /* | ||
2 | * bebob.c - a part of driver for BeBoB based devices | ||
3 | * | ||
4 | * Copyright (c) 2013-2014 Takashi Sakamoto | ||
5 | * | ||
6 | * Licensed under the terms of the GNU General Public License, version 2. | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * BeBoB is 'BridgeCo enhanced Breakout Box'. This is installed to firewire | ||
11 | * devices with DM1000/DM1100/DM1500 chipset. It gives common way for host | ||
12 | * system to handle BeBoB based devices. | ||
13 | */ | ||
14 | |||
15 | #include "bebob.h" | ||
16 | |||
17 | MODULE_DESCRIPTION("BridgeCo BeBoB driver"); | ||
18 | MODULE_AUTHOR("Takashi Sakamoto <o-takashi@sakamocchi.jp>"); | ||
19 | MODULE_LICENSE("GPL v2"); | ||
20 | |||
21 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; | ||
22 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; | ||
23 | static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; | ||
24 | |||
25 | module_param_array(index, int, NULL, 0444); | ||
26 | MODULE_PARM_DESC(index, "card index"); | ||
27 | module_param_array(id, charp, NULL, 0444); | ||
28 | MODULE_PARM_DESC(id, "ID string"); | ||
29 | module_param_array(enable, bool, NULL, 0444); | ||
30 | MODULE_PARM_DESC(enable, "enable BeBoB sound card"); | ||
31 | |||
32 | static DEFINE_MUTEX(devices_mutex); | ||
33 | static DECLARE_BITMAP(devices_used, SNDRV_CARDS); | ||
34 | |||
35 | /* Offsets from information register. */ | ||
36 | #define INFO_OFFSET_GUID 0x10 | ||
37 | #define INFO_OFFSET_HW_MODEL_ID 0x18 | ||
38 | #define INFO_OFFSET_HW_MODEL_REVISION 0x1c | ||
39 | |||
40 | #define VEN_EDIROL 0x000040ab | ||
41 | #define VEN_PRESONUS 0x00000a92 | ||
42 | #define VEN_BRIDGECO 0x000007f5 | ||
43 | #define VEN_MACKIE 0x0000000f | ||
44 | #define VEN_STANTON 0x00001260 | ||
45 | #define VEN_TASCAM 0x0000022e | ||
46 | #define VEN_BEHRINGER 0x00001564 | ||
47 | #define VEN_APOGEE 0x000003db | ||
48 | #define VEN_ESI 0x00000f1b | ||
49 | #define VEN_ACOUSTIC 0x00000002 | ||
50 | #define VEN_CME 0x0000000a | ||
51 | #define VEN_PHONIC 0x00001496 | ||
52 | #define VEN_LYNX 0x000019e5 | ||
53 | #define VEN_ICON 0x00001a9e | ||
54 | #define VEN_PRISMSOUND 0x00001198 | ||
55 | #define VEN_TERRATEC 0x00000aac | ||
56 | #define VEN_YAMAHA 0x0000a0de | ||
57 | #define VEN_FOCUSRITE 0x0000130e | ||
58 | #define VEN_MAUDIO1 0x00000d6c | ||
59 | #define VEN_MAUDIO2 0x000007f5 | ||
60 | |||
61 | #define MODEL_FOCUSRITE_SAFFIRE_BOTH 0x00000000 | ||
62 | #define MODEL_MAUDIO_AUDIOPHILE_BOTH 0x00010060 | ||
63 | #define MODEL_MAUDIO_FW1814 0x00010071 | ||
64 | #define MODEL_MAUDIO_PROJECTMIX 0x00010091 | ||
65 | |||
66 | static int | ||
67 | name_device(struct snd_bebob *bebob, unsigned int vendor_id) | ||
68 | { | ||
69 | struct fw_device *fw_dev = fw_parent_device(bebob->unit); | ||
70 | char vendor[24] = {0}; | ||
71 | char model[32] = {0}; | ||
72 | u32 hw_id; | ||
73 | u32 data[2] = {0}; | ||
74 | u32 revision; | ||
75 | int err; | ||
76 | |||
77 | /* get vendor name from root directory */ | ||
78 | err = fw_csr_string(fw_dev->config_rom + 5, CSR_VENDOR, | ||
79 | vendor, sizeof(vendor)); | ||
80 | if (err < 0) | ||
81 | goto end; | ||
82 | |||
83 | /* get model name from unit directory */ | ||
84 | err = fw_csr_string(bebob->unit->directory, CSR_MODEL, | ||
85 | model, sizeof(model)); | ||
86 | if (err < 0) | ||
87 | goto end; | ||
88 | |||
89 | /* get hardware id */ | ||
90 | err = snd_bebob_read_quad(bebob->unit, INFO_OFFSET_HW_MODEL_ID, | ||
91 | &hw_id); | ||
92 | if (err < 0) | ||
93 | goto end; | ||
94 | |||
95 | /* get hardware revision */ | ||
96 | err = snd_bebob_read_quad(bebob->unit, INFO_OFFSET_HW_MODEL_REVISION, | ||
97 | &revision); | ||
98 | if (err < 0) | ||
99 | goto end; | ||
100 | |||
101 | /* get GUID */ | ||
102 | err = snd_bebob_read_block(bebob->unit, INFO_OFFSET_GUID, | ||
103 | data, sizeof(data)); | ||
104 | if (err < 0) | ||
105 | goto end; | ||
106 | |||
107 | strcpy(bebob->card->driver, "BeBoB"); | ||
108 | strcpy(bebob->card->shortname, model); | ||
109 | strcpy(bebob->card->mixername, model); | ||
110 | snprintf(bebob->card->longname, sizeof(bebob->card->longname), | ||
111 | "%s %s (id:%d, rev:%d), GUID %08x%08x at %s, S%d", | ||
112 | vendor, model, hw_id, revision, | ||
113 | data[0], data[1], dev_name(&bebob->unit->device), | ||
114 | 100 << fw_dev->max_speed); | ||
115 | end: | ||
116 | return err; | ||
117 | } | ||
118 | |||
119 | static void | ||
120 | bebob_card_free(struct snd_card *card) | ||
121 | { | ||
122 | struct snd_bebob *bebob = card->private_data; | ||
123 | |||
124 | if (bebob->card_index >= 0) { | ||
125 | mutex_lock(&devices_mutex); | ||
126 | clear_bit(bebob->card_index, devices_used); | ||
127 | mutex_unlock(&devices_mutex); | ||
128 | } | ||
129 | |||
130 | mutex_destroy(&bebob->mutex); | ||
131 | } | ||
132 | |||
133 | static const struct snd_bebob_spec * | ||
134 | get_saffire_spec(struct fw_unit *unit) | ||
135 | { | ||
136 | char name[24] = {0}; | ||
137 | |||
138 | if (fw_csr_string(unit->directory, CSR_MODEL, name, sizeof(name)) < 0) | ||
139 | return NULL; | ||
140 | |||
141 | if (strcmp(name, "SaffireLE") == 0) | ||
142 | return &saffire_le_spec; | ||
143 | else | ||
144 | return &saffire_spec; | ||
145 | } | ||
146 | |||
147 | static bool | ||
148 | check_audiophile_booted(struct fw_unit *unit) | ||
149 | { | ||
150 | char name[24] = {0}; | ||
151 | |||
152 | if (fw_csr_string(unit->directory, CSR_MODEL, name, sizeof(name)) < 0) | ||
153 | return false; | ||
154 | |||
155 | return strncmp(name, "FW Audiophile Bootloader", 15) != 0; | ||
156 | } | ||
157 | |||
158 | static int | ||
159 | bebob_probe(struct fw_unit *unit, | ||
160 | const struct ieee1394_device_id *entry) | ||
161 | { | ||
162 | struct snd_card *card; | ||
163 | struct snd_bebob *bebob; | ||
164 | const struct snd_bebob_spec *spec; | ||
165 | unsigned int card_index; | ||
166 | int err; | ||
167 | |||
168 | mutex_lock(&devices_mutex); | ||
169 | |||
170 | for (card_index = 0; card_index < SNDRV_CARDS; card_index++) { | ||
171 | if (!test_bit(card_index, devices_used) && enable[card_index]) | ||
172 | break; | ||
173 | } | ||
174 | if (card_index >= SNDRV_CARDS) { | ||
175 | err = -ENOENT; | ||
176 | goto end; | ||
177 | } | ||
178 | |||
179 | if ((entry->vendor_id == VEN_FOCUSRITE) && | ||
180 | (entry->model_id == MODEL_FOCUSRITE_SAFFIRE_BOTH)) | ||
181 | spec = get_saffire_spec(unit); | ||
182 | else if ((entry->vendor_id == VEN_MAUDIO1) && | ||
183 | (entry->model_id == MODEL_MAUDIO_AUDIOPHILE_BOTH) && | ||
184 | !check_audiophile_booted(unit)) | ||
185 | spec = NULL; | ||
186 | else | ||
187 | spec = (const struct snd_bebob_spec *)entry->driver_data; | ||
188 | |||
189 | if (spec == NULL) { | ||
190 | if ((entry->vendor_id == VEN_MAUDIO1) || | ||
191 | (entry->vendor_id == VEN_MAUDIO2)) | ||
192 | err = snd_bebob_maudio_load_firmware(unit); | ||
193 | else | ||
194 | err = -ENOSYS; | ||
195 | goto end; | ||
196 | } | ||
197 | |||
198 | err = snd_card_new(&unit->device, index[card_index], id[card_index], | ||
199 | THIS_MODULE, sizeof(struct snd_bebob), &card); | ||
200 | if (err < 0) | ||
201 | goto end; | ||
202 | bebob = card->private_data; | ||
203 | bebob->card_index = card_index; | ||
204 | set_bit(card_index, devices_used); | ||
205 | card->private_free = bebob_card_free; | ||
206 | |||
207 | bebob->card = card; | ||
208 | bebob->unit = unit; | ||
209 | bebob->spec = spec; | ||
210 | mutex_init(&bebob->mutex); | ||
211 | spin_lock_init(&bebob->lock); | ||
212 | init_waitqueue_head(&bebob->hwdep_wait); | ||
213 | |||
214 | err = name_device(bebob, entry->vendor_id); | ||
215 | if (err < 0) | ||
216 | goto error; | ||
217 | |||
218 | if ((entry->vendor_id == VEN_MAUDIO1) && | ||
219 | (entry->model_id == MODEL_MAUDIO_FW1814)) | ||
220 | err = snd_bebob_maudio_special_discover(bebob, true); | ||
221 | else if ((entry->vendor_id == VEN_MAUDIO1) && | ||
222 | (entry->model_id == MODEL_MAUDIO_PROJECTMIX)) | ||
223 | err = snd_bebob_maudio_special_discover(bebob, false); | ||
224 | else | ||
225 | err = snd_bebob_stream_discover(bebob); | ||
226 | if (err < 0) | ||
227 | goto error; | ||
228 | |||
229 | snd_bebob_proc_init(bebob); | ||
230 | |||
231 | if ((bebob->midi_input_ports > 0) || | ||
232 | (bebob->midi_output_ports > 0)) { | ||
233 | err = snd_bebob_create_midi_devices(bebob); | ||
234 | if (err < 0) | ||
235 | goto error; | ||
236 | } | ||
237 | |||
238 | err = snd_bebob_create_pcm_devices(bebob); | ||
239 | if (err < 0) | ||
240 | goto error; | ||
241 | |||
242 | err = snd_bebob_create_hwdep_device(bebob); | ||
243 | if (err < 0) | ||
244 | goto error; | ||
245 | |||
246 | err = snd_bebob_stream_init_duplex(bebob); | ||
247 | if (err < 0) | ||
248 | goto error; | ||
249 | |||
250 | if (!bebob->maudio_special_quirk) { | ||
251 | err = snd_card_register(card); | ||
252 | if (err < 0) { | ||
253 | snd_bebob_stream_destroy_duplex(bebob); | ||
254 | goto error; | ||
255 | } | ||
256 | } else { | ||
257 | /* | ||
258 | * This is a workaround. This bus reset seems to have an effect | ||
259 | * to make devices correctly handling transactions. Without | ||
260 | * this, the devices have gap_count mismatch. This causes much | ||
261 | * failure of transaction. | ||
262 | * | ||
263 | * Just after registration, user-land application receive | ||
264 | * signals from dbus and starts I/Os. To avoid I/Os till the | ||
265 | * future bus reset, registration is done in next update(). | ||
266 | */ | ||
267 | bebob->deferred_registration = true; | ||
268 | fw_schedule_bus_reset(fw_parent_device(bebob->unit)->card, | ||
269 | false, true); | ||
270 | } | ||
271 | |||
272 | dev_set_drvdata(&unit->device, bebob); | ||
273 | end: | ||
274 | mutex_unlock(&devices_mutex); | ||
275 | return err; | ||
276 | error: | ||
277 | mutex_unlock(&devices_mutex); | ||
278 | snd_card_free(card); | ||
279 | return err; | ||
280 | } | ||
281 | |||
282 | static void | ||
283 | bebob_update(struct fw_unit *unit) | ||
284 | { | ||
285 | struct snd_bebob *bebob = dev_get_drvdata(&unit->device); | ||
286 | |||
287 | if (bebob == NULL) | ||
288 | return; | ||
289 | |||
290 | fcp_bus_reset(bebob->unit); | ||
291 | snd_bebob_stream_update_duplex(bebob); | ||
292 | |||
293 | if (bebob->deferred_registration) { | ||
294 | if (snd_card_register(bebob->card) < 0) { | ||
295 | snd_bebob_stream_destroy_duplex(bebob); | ||
296 | snd_card_free(bebob->card); | ||
297 | } | ||
298 | bebob->deferred_registration = false; | ||
299 | } | ||
300 | } | ||
301 | |||
302 | static void bebob_remove(struct fw_unit *unit) | ||
303 | { | ||
304 | struct snd_bebob *bebob = dev_get_drvdata(&unit->device); | ||
305 | |||
306 | if (bebob == NULL) | ||
307 | return; | ||
308 | |||
309 | kfree(bebob->maudio_special_quirk); | ||
310 | |||
311 | snd_bebob_stream_destroy_duplex(bebob); | ||
312 | snd_card_disconnect(bebob->card); | ||
313 | snd_card_free_when_closed(bebob->card); | ||
314 | } | ||
315 | |||
316 | static struct snd_bebob_rate_spec normal_rate_spec = { | ||
317 | .get = &snd_bebob_stream_get_rate, | ||
318 | .set = &snd_bebob_stream_set_rate | ||
319 | }; | ||
320 | static const struct snd_bebob_spec spec_normal = { | ||
321 | .clock = NULL, | ||
322 | .rate = &normal_rate_spec, | ||
323 | .meter = NULL | ||
324 | }; | ||
325 | |||
326 | static const struct ieee1394_device_id bebob_id_table[] = { | ||
327 | /* Edirol, FA-66 */ | ||
328 | SND_BEBOB_DEV_ENTRY(VEN_EDIROL, 0x00010049, &spec_normal), | ||
329 | /* Edirol, FA-101 */ | ||
330 | SND_BEBOB_DEV_ENTRY(VEN_EDIROL, 0x00010048, &spec_normal), | ||
331 | /* Presonus, FIREBOX */ | ||
332 | SND_BEBOB_DEV_ENTRY(VEN_PRESONUS, 0x00010000, &spec_normal), | ||
333 | /* PreSonus, FIREPOD/FP10 */ | ||
334 | SND_BEBOB_DEV_ENTRY(VEN_PRESONUS, 0x00010066, &spec_normal), | ||
335 | /* PreSonus, Inspire1394 */ | ||
336 | SND_BEBOB_DEV_ENTRY(VEN_PRESONUS, 0x00010001, &spec_normal), | ||
337 | /* BridgeCo, RDAudio1 */ | ||
338 | SND_BEBOB_DEV_ENTRY(VEN_BRIDGECO, 0x00010048, &spec_normal), | ||
339 | /* BridgeCo, Audio5 */ | ||
340 | SND_BEBOB_DEV_ENTRY(VEN_BRIDGECO, 0x00010049, &spec_normal), | ||
341 | /* Mackie, Onyx 1220/1620/1640 (Firewire I/O Card) */ | ||
342 | SND_BEBOB_DEV_ENTRY(VEN_MACKIE, 0x00010065, &spec_normal), | ||
343 | /* Mackie, d.2 (Firewire Option) */ | ||
344 | SND_BEBOB_DEV_ENTRY(VEN_MACKIE, 0x00010067, &spec_normal), | ||
345 | /* Stanton, ScratchAmp */ | ||
346 | SND_BEBOB_DEV_ENTRY(VEN_STANTON, 0x00000001, &spec_normal), | ||
347 | /* Tascam, IF-FW DM */ | ||
348 | SND_BEBOB_DEV_ENTRY(VEN_TASCAM, 0x00010067, &spec_normal), | ||
349 | /* Behringer, XENIX UFX 1204 */ | ||
350 | SND_BEBOB_DEV_ENTRY(VEN_BEHRINGER, 0x00001204, &spec_normal), | ||
351 | /* Behringer, XENIX UFX 1604 */ | ||
352 | SND_BEBOB_DEV_ENTRY(VEN_BEHRINGER, 0x00001604, &spec_normal), | ||
353 | /* Behringer, Digital Mixer X32 series (X-UF Card) */ | ||
354 | SND_BEBOB_DEV_ENTRY(VEN_BEHRINGER, 0x00000006, &spec_normal), | ||
355 | /* Apogee Electronics, Rosetta 200/400 (X-FireWire card) */ | ||
356 | /* Apogee Electronics, DA/AD/DD-16X (X-FireWire card) */ | ||
357 | SND_BEBOB_DEV_ENTRY(VEN_APOGEE, 0x00010048, &spec_normal), | ||
358 | /* Apogee Electronics, Ensemble */ | ||
359 | SND_BEBOB_DEV_ENTRY(VEN_APOGEE, 0x00001eee, &spec_normal), | ||
360 | /* ESI, Quatafire610 */ | ||
361 | SND_BEBOB_DEV_ENTRY(VEN_ESI, 0x00010064, &spec_normal), | ||
362 | /* AcousticReality, eARMasterOne */ | ||
363 | SND_BEBOB_DEV_ENTRY(VEN_ACOUSTIC, 0x00000002, &spec_normal), | ||
364 | /* CME, MatrixKFW */ | ||
365 | SND_BEBOB_DEV_ENTRY(VEN_CME, 0x00030000, &spec_normal), | ||
366 | /* Phonic, Helix Board 12 MkII */ | ||
367 | SND_BEBOB_DEV_ENTRY(VEN_PHONIC, 0x00050000, &spec_normal), | ||
368 | /* Phonic, Helix Board 18 MkII */ | ||
369 | SND_BEBOB_DEV_ENTRY(VEN_PHONIC, 0x00060000, &spec_normal), | ||
370 | /* Phonic, Helix Board 24 MkII */ | ||
371 | SND_BEBOB_DEV_ENTRY(VEN_PHONIC, 0x00070000, &spec_normal), | ||
372 | /* Phonic, Helix Board 12 Universal/18 Universal/24 Universal */ | ||
373 | SND_BEBOB_DEV_ENTRY(VEN_PHONIC, 0x00000000, &spec_normal), | ||
374 | /* Lynx, Aurora 8/16 (LT-FW) */ | ||
375 | SND_BEBOB_DEV_ENTRY(VEN_LYNX, 0x00000001, &spec_normal), | ||
376 | /* ICON, FireXon */ | ||
377 | SND_BEBOB_DEV_ENTRY(VEN_ICON, 0x00000001, &spec_normal), | ||
378 | /* PrismSound, Orpheus */ | ||
379 | SND_BEBOB_DEV_ENTRY(VEN_PRISMSOUND, 0x00010048, &spec_normal), | ||
380 | /* PrismSound, ADA-8XR */ | ||
381 | SND_BEBOB_DEV_ENTRY(VEN_PRISMSOUND, 0x0000ada8, &spec_normal), | ||
382 | /* TerraTec Electronic GmbH, PHASE 88 Rack FW */ | ||
383 | SND_BEBOB_DEV_ENTRY(VEN_TERRATEC, 0x00000003, &phase88_rack_spec), | ||
384 | /* TerraTec Electronic GmbH, PHASE 24 FW */ | ||
385 | SND_BEBOB_DEV_ENTRY(VEN_TERRATEC, 0x00000004, &phase24_series_spec), | ||
386 | /* TerraTec Electronic GmbH, Phase X24 FW */ | ||
387 | SND_BEBOB_DEV_ENTRY(VEN_TERRATEC, 0x00000007, &phase24_series_spec), | ||
388 | /* TerraTec Electronic GmbH, EWS MIC2/MIC8 */ | ||
389 | SND_BEBOB_DEV_ENTRY(VEN_TERRATEC, 0x00000005, &spec_normal), | ||
390 | /* Terratec Electronic GmbH, Aureon 7.1 Firewire */ | ||
391 | SND_BEBOB_DEV_ENTRY(VEN_TERRATEC, 0x00000002, &spec_normal), | ||
392 | /* Yamaha, GO44 */ | ||
393 | SND_BEBOB_DEV_ENTRY(VEN_YAMAHA, 0x0010000b, &yamaha_go_spec), | ||
394 | /* YAMAHA, GO46 */ | ||
395 | SND_BEBOB_DEV_ENTRY(VEN_YAMAHA, 0x0010000c, &yamaha_go_spec), | ||
396 | /* Focusrite, SaffirePro 26 I/O */ | ||
397 | SND_BEBOB_DEV_ENTRY(VEN_FOCUSRITE, 0x00000003, &saffirepro_26_spec), | ||
398 | /* Focusrite, SaffirePro 10 I/O */ | ||
399 | SND_BEBOB_DEV_ENTRY(VEN_FOCUSRITE, 0x00000006, &saffirepro_10_spec), | ||
400 | /* Focusrite, Saffire(no label and LE) */ | ||
401 | SND_BEBOB_DEV_ENTRY(VEN_FOCUSRITE, MODEL_FOCUSRITE_SAFFIRE_BOTH, | ||
402 | &saffire_spec), | ||
403 | /* M-Audio, Firewire 410 */ | ||
404 | SND_BEBOB_DEV_ENTRY(VEN_MAUDIO2, 0x00010058, NULL), /* bootloader */ | ||
405 | SND_BEBOB_DEV_ENTRY(VEN_MAUDIO2, 0x00010046, &maudio_fw410_spec), | ||
406 | /* M-Audio, Firewire Audiophile */ | ||
407 | SND_BEBOB_DEV_ENTRY(VEN_MAUDIO1, MODEL_MAUDIO_AUDIOPHILE_BOTH, | ||
408 | &maudio_audiophile_spec), | ||
409 | /* M-Audio, Firewire Solo */ | ||
410 | SND_BEBOB_DEV_ENTRY(VEN_MAUDIO1, 0x00010062, &maudio_solo_spec), | ||
411 | /* M-Audio, Ozonic */ | ||
412 | SND_BEBOB_DEV_ENTRY(VEN_MAUDIO1, 0x0000000a, &maudio_ozonic_spec), | ||
413 | /* M-Audio NRV10 */ | ||
414 | SND_BEBOB_DEV_ENTRY(VEN_MAUDIO1, 0x00010081, &maudio_nrv10_spec), | ||
415 | /* M-Audio, ProFireLightbridge */ | ||
416 | SND_BEBOB_DEV_ENTRY(VEN_MAUDIO1, 0x000100a1, &spec_normal), | ||
417 | /* Firewire 1814 */ | ||
418 | SND_BEBOB_DEV_ENTRY(VEN_MAUDIO1, 0x00010070, NULL), /* bootloader */ | ||
419 | SND_BEBOB_DEV_ENTRY(VEN_MAUDIO1, MODEL_MAUDIO_FW1814, | ||
420 | &maudio_special_spec), | ||
421 | /* M-Audio ProjectMix */ | ||
422 | SND_BEBOB_DEV_ENTRY(VEN_MAUDIO1, MODEL_MAUDIO_PROJECTMIX, | ||
423 | &maudio_special_spec), | ||
424 | /* IDs are unknown but able to be supported */ | ||
425 | /* Apogee, Mini-ME Firewire */ | ||
426 | /* Apogee, Mini-DAC Firewire */ | ||
427 | /* Behringer, F-Control Audio 1616 */ | ||
428 | /* Behringer, F-Control Audio 610 */ | ||
429 | /* Cakawalk, Sonar Power Studio 66 */ | ||
430 | /* CME, UF400e */ | ||
431 | /* ESI, Quotafire XL */ | ||
432 | /* Infrasonic, DewX */ | ||
433 | /* Infrasonic, Windy6 */ | ||
434 | /* Mackie, Digital X Bus x.200 */ | ||
435 | /* Mackie, Digital X Bus x.400 */ | ||
436 | /* Phonic, HB 12 */ | ||
437 | /* Phonic, HB 24 */ | ||
438 | /* Phonic, HB 18 */ | ||
439 | /* Phonic, FireFly 202 */ | ||
440 | /* Phonic, FireFly 302 */ | ||
441 | /* Rolf Spuler, Firewire Guitar */ | ||
442 | {} | ||
443 | }; | ||
444 | MODULE_DEVICE_TABLE(ieee1394, bebob_id_table); | ||
445 | |||
446 | static struct fw_driver bebob_driver = { | ||
447 | .driver = { | ||
448 | .owner = THIS_MODULE, | ||
449 | .name = "snd-bebob", | ||
450 | .bus = &fw_bus_type, | ||
451 | }, | ||
452 | .probe = bebob_probe, | ||
453 | .update = bebob_update, | ||
454 | .remove = bebob_remove, | ||
455 | .id_table = bebob_id_table, | ||
456 | }; | ||
457 | |||
458 | static int __init | ||
459 | snd_bebob_init(void) | ||
460 | { | ||
461 | return driver_register(&bebob_driver.driver); | ||
462 | } | ||
463 | |||
464 | static void __exit | ||
465 | snd_bebob_exit(void) | ||
466 | { | ||
467 | driver_unregister(&bebob_driver.driver); | ||
468 | } | ||
469 | |||
470 | module_init(snd_bebob_init); | ||
471 | module_exit(snd_bebob_exit); | ||
diff --git a/sound/firewire/bebob/bebob.h b/sound/firewire/bebob/bebob.h new file mode 100644 index 000000000000..e13eef99c27a --- /dev/null +++ b/sound/firewire/bebob/bebob.h | |||
@@ -0,0 +1,255 @@ | |||
1 | /* | ||
2 | * bebob.h - a part of driver for BeBoB based devices | ||
3 | * | ||
4 | * Copyright (c) 2013-2014 Takashi Sakamoto | ||
5 | * | ||
6 | * Licensed under the terms of the GNU General Public License, version 2. | ||
7 | */ | ||
8 | |||
9 | #ifndef SOUND_BEBOB_H_INCLUDED | ||
10 | #define SOUND_BEBOB_H_INCLUDED | ||
11 | |||
12 | #include <linux/compat.h> | ||
13 | #include <linux/device.h> | ||
14 | #include <linux/firewire.h> | ||
15 | #include <linux/firewire-constants.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/mod_devicetable.h> | ||
18 | #include <linux/delay.h> | ||
19 | #include <linux/slab.h> | ||
20 | |||
21 | #include <sound/core.h> | ||
22 | #include <sound/initval.h> | ||
23 | #include <sound/info.h> | ||
24 | #include <sound/rawmidi.h> | ||
25 | #include <sound/pcm.h> | ||
26 | #include <sound/pcm_params.h> | ||
27 | #include <sound/firewire.h> | ||
28 | #include <sound/hwdep.h> | ||
29 | |||
30 | #include "../lib.h" | ||
31 | #include "../fcp.h" | ||
32 | #include "../packets-buffer.h" | ||
33 | #include "../iso-resources.h" | ||
34 | #include "../amdtp.h" | ||
35 | #include "../cmp.h" | ||
36 | |||
37 | /* basic register addresses on DM1000/DM1100/DM1500 */ | ||
38 | #define BEBOB_ADDR_REG_INFO 0xffffc8020000ULL | ||
39 | #define BEBOB_ADDR_REG_REQ 0xffffc8021000ULL | ||
40 | |||
41 | struct snd_bebob; | ||
42 | |||
43 | #define SND_BEBOB_STRM_FMT_ENTRIES 7 | ||
44 | struct snd_bebob_stream_formation { | ||
45 | unsigned int pcm; | ||
46 | unsigned int midi; | ||
47 | }; | ||
48 | /* this is a lookup table for index of stream formations */ | ||
49 | extern const unsigned int snd_bebob_rate_table[SND_BEBOB_STRM_FMT_ENTRIES]; | ||
50 | |||
51 | /* device specific operations */ | ||
52 | #define SND_BEBOB_CLOCK_INTERNAL "Internal" | ||
53 | struct snd_bebob_clock_spec { | ||
54 | unsigned int num; | ||
55 | char *const *labels; | ||
56 | int (*get)(struct snd_bebob *bebob, unsigned int *id); | ||
57 | }; | ||
58 | struct snd_bebob_rate_spec { | ||
59 | int (*get)(struct snd_bebob *bebob, unsigned int *rate); | ||
60 | int (*set)(struct snd_bebob *bebob, unsigned int rate); | ||
61 | }; | ||
62 | struct snd_bebob_meter_spec { | ||
63 | unsigned int num; | ||
64 | char *const *labels; | ||
65 | int (*get)(struct snd_bebob *bebob, u32 *target, unsigned int size); | ||
66 | }; | ||
67 | struct snd_bebob_spec { | ||
68 | struct snd_bebob_clock_spec *clock; | ||
69 | struct snd_bebob_rate_spec *rate; | ||
70 | struct snd_bebob_meter_spec *meter; | ||
71 | }; | ||
72 | |||
73 | struct snd_bebob { | ||
74 | struct snd_card *card; | ||
75 | struct fw_unit *unit; | ||
76 | int card_index; | ||
77 | |||
78 | struct mutex mutex; | ||
79 | spinlock_t lock; | ||
80 | |||
81 | const struct snd_bebob_spec *spec; | ||
82 | |||
83 | unsigned int midi_input_ports; | ||
84 | unsigned int midi_output_ports; | ||
85 | |||
86 | /* for bus reset quirk */ | ||
87 | struct completion bus_reset; | ||
88 | bool connected; | ||
89 | |||
90 | struct amdtp_stream *master; | ||
91 | struct amdtp_stream tx_stream; | ||
92 | struct amdtp_stream rx_stream; | ||
93 | struct cmp_connection out_conn; | ||
94 | struct cmp_connection in_conn; | ||
95 | atomic_t capture_substreams; | ||
96 | atomic_t playback_substreams; | ||
97 | |||
98 | struct snd_bebob_stream_formation | ||
99 | tx_stream_formations[SND_BEBOB_STRM_FMT_ENTRIES]; | ||
100 | struct snd_bebob_stream_formation | ||
101 | rx_stream_formations[SND_BEBOB_STRM_FMT_ENTRIES]; | ||
102 | |||
103 | int sync_input_plug; | ||
104 | |||
105 | /* for uapi */ | ||
106 | int dev_lock_count; | ||
107 | bool dev_lock_changed; | ||
108 | wait_queue_head_t hwdep_wait; | ||
109 | |||
110 | /* for M-Audio special devices */ | ||
111 | void *maudio_special_quirk; | ||
112 | bool deferred_registration; | ||
113 | }; | ||
114 | |||
115 | static inline int | ||
116 | snd_bebob_read_block(struct fw_unit *unit, u64 addr, void *buf, int size) | ||
117 | { | ||
118 | return snd_fw_transaction(unit, TCODE_READ_BLOCK_REQUEST, | ||
119 | BEBOB_ADDR_REG_INFO + addr, | ||
120 | buf, size, 0); | ||
121 | } | ||
122 | |||
123 | static inline int | ||
124 | snd_bebob_read_quad(struct fw_unit *unit, u64 addr, u32 *buf) | ||
125 | { | ||
126 | return snd_fw_transaction(unit, TCODE_READ_QUADLET_REQUEST, | ||
127 | BEBOB_ADDR_REG_INFO + addr, | ||
128 | (void *)buf, sizeof(u32), 0); | ||
129 | } | ||
130 | |||
131 | /* AV/C Audio Subunit Specification 1.0 (Oct 2000, 1394TA) */ | ||
132 | int avc_audio_set_selector(struct fw_unit *unit, unsigned int subunit_id, | ||
133 | unsigned int fb_id, unsigned int num); | ||
134 | int avc_audio_get_selector(struct fw_unit *unit, unsigned int subunit_id, | ||
135 | unsigned int fb_id, unsigned int *num); | ||
136 | |||
137 | /* | ||
138 | * AVC command extensions, AV/C Unit and Subunit, Revision 17 | ||
139 | * (Nov 2003, BridgeCo) | ||
140 | */ | ||
141 | #define AVC_BRIDGECO_ADDR_BYTES 6 | ||
142 | enum avc_bridgeco_plug_dir { | ||
143 | AVC_BRIDGECO_PLUG_DIR_IN = 0x00, | ||
144 | AVC_BRIDGECO_PLUG_DIR_OUT = 0x01 | ||
145 | }; | ||
146 | enum avc_bridgeco_plug_mode { | ||
147 | AVC_BRIDGECO_PLUG_MODE_UNIT = 0x00, | ||
148 | AVC_BRIDGECO_PLUG_MODE_SUBUNIT = 0x01, | ||
149 | AVC_BRIDGECO_PLUG_MODE_FUNCTION_BLOCK = 0x02 | ||
150 | }; | ||
151 | enum avc_bridgeco_plug_unit { | ||
152 | AVC_BRIDGECO_PLUG_UNIT_ISOC = 0x00, | ||
153 | AVC_BRIDGECO_PLUG_UNIT_EXT = 0x01, | ||
154 | AVC_BRIDGECO_PLUG_UNIT_ASYNC = 0x02 | ||
155 | }; | ||
156 | enum avc_bridgeco_plug_type { | ||
157 | AVC_BRIDGECO_PLUG_TYPE_ISOC = 0x00, | ||
158 | AVC_BRIDGECO_PLUG_TYPE_ASYNC = 0x01, | ||
159 | AVC_BRIDGECO_PLUG_TYPE_MIDI = 0x02, | ||
160 | AVC_BRIDGECO_PLUG_TYPE_SYNC = 0x03, | ||
161 | AVC_BRIDGECO_PLUG_TYPE_ANA = 0x04, | ||
162 | AVC_BRIDGECO_PLUG_TYPE_DIG = 0x05 | ||
163 | }; | ||
164 | static inline void | ||
165 | avc_bridgeco_fill_unit_addr(u8 buf[AVC_BRIDGECO_ADDR_BYTES], | ||
166 | enum avc_bridgeco_plug_dir dir, | ||
167 | enum avc_bridgeco_plug_unit unit, | ||
168 | unsigned int pid) | ||
169 | { | ||
170 | buf[0] = 0xff; /* Unit */ | ||
171 | buf[1] = dir; | ||
172 | buf[2] = AVC_BRIDGECO_PLUG_MODE_UNIT; | ||
173 | buf[3] = unit; | ||
174 | buf[4] = 0xff & pid; | ||
175 | buf[5] = 0xff; /* reserved */ | ||
176 | } | ||
177 | static inline void | ||
178 | avc_bridgeco_fill_msu_addr(u8 buf[AVC_BRIDGECO_ADDR_BYTES], | ||
179 | enum avc_bridgeco_plug_dir dir, | ||
180 | unsigned int pid) | ||
181 | { | ||
182 | buf[0] = 0x60; /* Music subunit */ | ||
183 | buf[1] = dir; | ||
184 | buf[2] = AVC_BRIDGECO_PLUG_MODE_SUBUNIT; | ||
185 | buf[3] = 0xff & pid; | ||
186 | buf[4] = 0xff; /* reserved */ | ||
187 | buf[5] = 0xff; /* reserved */ | ||
188 | } | ||
189 | int avc_bridgeco_get_plug_ch_pos(struct fw_unit *unit, | ||
190 | u8 addr[AVC_BRIDGECO_ADDR_BYTES], | ||
191 | u8 *buf, unsigned int len); | ||
192 | int avc_bridgeco_get_plug_type(struct fw_unit *unit, | ||
193 | u8 addr[AVC_BRIDGECO_ADDR_BYTES], | ||
194 | enum avc_bridgeco_plug_type *type); | ||
195 | int avc_bridgeco_get_plug_section_type(struct fw_unit *unit, | ||
196 | u8 addr[AVC_BRIDGECO_ADDR_BYTES], | ||
197 | unsigned int id, u8 *type); | ||
198 | int avc_bridgeco_get_plug_input(struct fw_unit *unit, | ||
199 | u8 addr[AVC_BRIDGECO_ADDR_BYTES], | ||
200 | u8 input[7]); | ||
201 | int avc_bridgeco_get_plug_strm_fmt(struct fw_unit *unit, | ||
202 | u8 addr[AVC_BRIDGECO_ADDR_BYTES], u8 *buf, | ||
203 | unsigned int *len, unsigned int eid); | ||
204 | |||
205 | /* for AMDTP streaming */ | ||
206 | int snd_bebob_stream_get_rate(struct snd_bebob *bebob, unsigned int *rate); | ||
207 | int snd_bebob_stream_set_rate(struct snd_bebob *bebob, unsigned int rate); | ||
208 | int snd_bebob_stream_check_internal_clock(struct snd_bebob *bebob, | ||
209 | bool *internal); | ||
210 | int snd_bebob_stream_discover(struct snd_bebob *bebob); | ||
211 | int snd_bebob_stream_init_duplex(struct snd_bebob *bebob); | ||
212 | int snd_bebob_stream_start_duplex(struct snd_bebob *bebob, unsigned int rate); | ||
213 | void snd_bebob_stream_stop_duplex(struct snd_bebob *bebob); | ||
214 | void snd_bebob_stream_update_duplex(struct snd_bebob *bebob); | ||
215 | void snd_bebob_stream_destroy_duplex(struct snd_bebob *bebob); | ||
216 | |||
217 | void snd_bebob_stream_lock_changed(struct snd_bebob *bebob); | ||
218 | int snd_bebob_stream_lock_try(struct snd_bebob *bebob); | ||
219 | void snd_bebob_stream_lock_release(struct snd_bebob *bebob); | ||
220 | |||
221 | void snd_bebob_proc_init(struct snd_bebob *bebob); | ||
222 | |||
223 | int snd_bebob_create_midi_devices(struct snd_bebob *bebob); | ||
224 | |||
225 | int snd_bebob_create_pcm_devices(struct snd_bebob *bebob); | ||
226 | |||
227 | int snd_bebob_create_hwdep_device(struct snd_bebob *bebob); | ||
228 | |||
229 | /* model specific operations */ | ||
230 | extern struct snd_bebob_spec phase88_rack_spec; | ||
231 | extern struct snd_bebob_spec phase24_series_spec; | ||
232 | extern struct snd_bebob_spec yamaha_go_spec; | ||
233 | extern struct snd_bebob_spec saffirepro_26_spec; | ||
234 | extern struct snd_bebob_spec saffirepro_10_spec; | ||
235 | extern struct snd_bebob_spec saffire_le_spec; | ||
236 | extern struct snd_bebob_spec saffire_spec; | ||
237 | extern struct snd_bebob_spec maudio_fw410_spec; | ||
238 | extern struct snd_bebob_spec maudio_audiophile_spec; | ||
239 | extern struct snd_bebob_spec maudio_solo_spec; | ||
240 | extern struct snd_bebob_spec maudio_ozonic_spec; | ||
241 | extern struct snd_bebob_spec maudio_nrv10_spec; | ||
242 | extern struct snd_bebob_spec maudio_special_spec; | ||
243 | int snd_bebob_maudio_special_discover(struct snd_bebob *bebob, bool is1814); | ||
244 | int snd_bebob_maudio_load_firmware(struct fw_unit *unit); | ||
245 | |||
246 | #define SND_BEBOB_DEV_ENTRY(vendor, model, data) \ | ||
247 | { \ | ||
248 | .match_flags = IEEE1394_MATCH_VENDOR_ID | \ | ||
249 | IEEE1394_MATCH_MODEL_ID, \ | ||
250 | .vendor_id = vendor, \ | ||
251 | .model_id = model, \ | ||
252 | .driver_data = (kernel_ulong_t)data \ | ||
253 | } | ||
254 | |||
255 | #endif | ||
diff --git a/sound/firewire/bebob/bebob_command.c b/sound/firewire/bebob/bebob_command.c new file mode 100644 index 000000000000..9402cc15dbc1 --- /dev/null +++ b/sound/firewire/bebob/bebob_command.c | |||
@@ -0,0 +1,282 @@ | |||
1 | /* | ||
2 | * bebob_command.c - driver for BeBoB based devices | ||
3 | * | ||
4 | * Copyright (c) 2013-2014 Takashi Sakamoto | ||
5 | * | ||
6 | * Licensed under the terms of the GNU General Public License, version 2. | ||
7 | */ | ||
8 | |||
9 | #include "./bebob.h" | ||
10 | |||
11 | int avc_audio_set_selector(struct fw_unit *unit, unsigned int subunit_id, | ||
12 | unsigned int fb_id, unsigned int num) | ||
13 | { | ||
14 | u8 *buf; | ||
15 | int err; | ||
16 | |||
17 | buf = kzalloc(12, GFP_KERNEL); | ||
18 | if (buf == NULL) | ||
19 | return -ENOMEM; | ||
20 | |||
21 | buf[0] = 0x00; /* AV/C CONTROL */ | ||
22 | buf[1] = 0x08 | (0x07 & subunit_id); /* AUDIO SUBUNIT ID */ | ||
23 | buf[2] = 0xb8; /* FUNCTION BLOCK */ | ||
24 | buf[3] = 0x80; /* type is 'selector'*/ | ||
25 | buf[4] = 0xff & fb_id; /* function block id */ | ||
26 | buf[5] = 0x10; /* control attribute is CURRENT */ | ||
27 | buf[6] = 0x02; /* selector length is 2 */ | ||
28 | buf[7] = 0xff & num; /* input function block plug number */ | ||
29 | buf[8] = 0x01; /* control selector is SELECTOR_CONTROL */ | ||
30 | |||
31 | err = fcp_avc_transaction(unit, buf, 12, buf, 12, | ||
32 | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | | ||
33 | BIT(6) | BIT(7) | BIT(8)); | ||
34 | if (err > 0 && err < 9) | ||
35 | err = -EIO; | ||
36 | else if (buf[0] == 0x08) /* NOT IMPLEMENTED */ | ||
37 | err = -ENOSYS; | ||
38 | else if (buf[0] == 0x0a) /* REJECTED */ | ||
39 | err = -EINVAL; | ||
40 | else if (err > 0) | ||
41 | err = 0; | ||
42 | |||
43 | kfree(buf); | ||
44 | return err; | ||
45 | } | ||
46 | |||
47 | int avc_audio_get_selector(struct fw_unit *unit, unsigned int subunit_id, | ||
48 | unsigned int fb_id, unsigned int *num) | ||
49 | { | ||
50 | u8 *buf; | ||
51 | int err; | ||
52 | |||
53 | buf = kzalloc(12, GFP_KERNEL); | ||
54 | if (buf == NULL) | ||
55 | return -ENOMEM; | ||
56 | |||
57 | buf[0] = 0x01; /* AV/C STATUS */ | ||
58 | buf[1] = 0x08 | (0x07 & subunit_id); /* AUDIO SUBUNIT ID */ | ||
59 | buf[2] = 0xb8; /* FUNCTION BLOCK */ | ||
60 | buf[3] = 0x80; /* type is 'selector'*/ | ||
61 | buf[4] = 0xff & fb_id; /* function block id */ | ||
62 | buf[5] = 0x10; /* control attribute is CURRENT */ | ||
63 | buf[6] = 0x02; /* selector length is 2 */ | ||
64 | buf[7] = 0xff; /* input function block plug number */ | ||
65 | buf[8] = 0x01; /* control selector is SELECTOR_CONTROL */ | ||
66 | |||
67 | err = fcp_avc_transaction(unit, buf, 12, buf, 12, | ||
68 | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | | ||
69 | BIT(6) | BIT(8)); | ||
70 | if (err > 0 && err < 9) | ||
71 | err = -EIO; | ||
72 | else if (buf[0] == 0x08) /* NOT IMPLEMENTED */ | ||
73 | err = -ENOSYS; | ||
74 | else if (buf[0] == 0x0a) /* REJECTED */ | ||
75 | err = -EINVAL; | ||
76 | else if (buf[0] == 0x0b) /* IN TRANSITION */ | ||
77 | err = -EAGAIN; | ||
78 | if (err < 0) | ||
79 | goto end; | ||
80 | |||
81 | *num = buf[7]; | ||
82 | err = 0; | ||
83 | end: | ||
84 | kfree(buf); | ||
85 | return err; | ||
86 | } | ||
87 | |||
88 | static inline void | ||
89 | avc_bridgeco_fill_extension_addr(u8 *buf, u8 *addr) | ||
90 | { | ||
91 | buf[1] = addr[0]; | ||
92 | memcpy(buf + 4, addr + 1, 5); | ||
93 | } | ||
94 | |||
95 | static inline void | ||
96 | avc_bridgeco_fill_plug_info_extension_command(u8 *buf, u8 *addr, | ||
97 | unsigned int itype) | ||
98 | { | ||
99 | buf[0] = 0x01; /* AV/C STATUS */ | ||
100 | buf[2] = 0x02; /* AV/C GENERAL PLUG INFO */ | ||
101 | buf[3] = 0xc0; /* BridgeCo extension */ | ||
102 | avc_bridgeco_fill_extension_addr(buf, addr); | ||
103 | buf[9] = itype; /* info type */ | ||
104 | } | ||
105 | |||
106 | int avc_bridgeco_get_plug_type(struct fw_unit *unit, | ||
107 | u8 addr[AVC_BRIDGECO_ADDR_BYTES], | ||
108 | enum avc_bridgeco_plug_type *type) | ||
109 | { | ||
110 | u8 *buf; | ||
111 | int err; | ||
112 | |||
113 | buf = kzalloc(12, GFP_KERNEL); | ||
114 | if (buf == NULL) | ||
115 | return -ENOMEM; | ||
116 | |||
117 | /* Info type is 'plug type'. */ | ||
118 | avc_bridgeco_fill_plug_info_extension_command(buf, addr, 0x00); | ||
119 | |||
120 | err = fcp_avc_transaction(unit, buf, 12, buf, 12, | ||
121 | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | | ||
122 | BIT(6) | BIT(7) | BIT(9)); | ||
123 | if ((err >= 0) && (err < 8)) | ||
124 | err = -EIO; | ||
125 | else if (buf[0] == 0x08) /* NOT IMPLEMENTED */ | ||
126 | err = -ENOSYS; | ||
127 | else if (buf[0] == 0x0a) /* REJECTED */ | ||
128 | err = -EINVAL; | ||
129 | else if (buf[0] == 0x0b) /* IN TRANSITION */ | ||
130 | err = -EAGAIN; | ||
131 | if (err < 0) | ||
132 | goto end; | ||
133 | |||
134 | *type = buf[10]; | ||
135 | err = 0; | ||
136 | end: | ||
137 | kfree(buf); | ||
138 | return err; | ||
139 | } | ||
140 | |||
141 | int avc_bridgeco_get_plug_ch_pos(struct fw_unit *unit, | ||
142 | u8 addr[AVC_BRIDGECO_ADDR_BYTES], | ||
143 | u8 *buf, unsigned int len) | ||
144 | { | ||
145 | int err; | ||
146 | |||
147 | /* Info type is 'channel position'. */ | ||
148 | avc_bridgeco_fill_plug_info_extension_command(buf, addr, 0x03); | ||
149 | |||
150 | err = fcp_avc_transaction(unit, buf, 12, buf, 256, | ||
151 | BIT(1) | BIT(2) | BIT(3) | BIT(4) | | ||
152 | BIT(5) | BIT(6) | BIT(7) | BIT(9)); | ||
153 | if ((err >= 0) && (err < 8)) | ||
154 | err = -EIO; | ||
155 | else if (buf[0] == 0x08) /* NOT IMPLEMENTED */ | ||
156 | err = -ENOSYS; | ||
157 | else if (buf[0] == 0x0a) /* REJECTED */ | ||
158 | err = -EINVAL; | ||
159 | else if (buf[0] == 0x0b) /* IN TRANSITION */ | ||
160 | err = -EAGAIN; | ||
161 | if (err < 0) | ||
162 | goto end; | ||
163 | |||
164 | /* Pick up specific data. */ | ||
165 | memmove(buf, buf + 10, err - 10); | ||
166 | err = 0; | ||
167 | end: | ||
168 | return err; | ||
169 | } | ||
170 | |||
171 | int avc_bridgeco_get_plug_section_type(struct fw_unit *unit, | ||
172 | u8 addr[AVC_BRIDGECO_ADDR_BYTES], | ||
173 | unsigned int id, u8 *type) | ||
174 | { | ||
175 | u8 *buf; | ||
176 | int err; | ||
177 | |||
178 | /* section info includes charactors but this module don't need it */ | ||
179 | buf = kzalloc(12, GFP_KERNEL); | ||
180 | if (buf == NULL) | ||
181 | return -ENOMEM; | ||
182 | |||
183 | /* Info type is 'section info'. */ | ||
184 | avc_bridgeco_fill_plug_info_extension_command(buf, addr, 0x07); | ||
185 | buf[10] = 0xff & ++id; /* section id */ | ||
186 | |||
187 | err = fcp_avc_transaction(unit, buf, 12, buf, 12, | ||
188 | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | | ||
189 | BIT(6) | BIT(7) | BIT(9) | BIT(10)); | ||
190 | if ((err >= 0) && (err < 8)) | ||
191 | err = -EIO; | ||
192 | else if (buf[0] == 0x08) /* NOT IMPLEMENTED */ | ||
193 | err = -ENOSYS; | ||
194 | else if (buf[0] == 0x0a) /* REJECTED */ | ||
195 | err = -EINVAL; | ||
196 | else if (buf[0] == 0x0b) /* IN TRANSITION */ | ||
197 | err = -EAGAIN; | ||
198 | if (err < 0) | ||
199 | goto end; | ||
200 | |||
201 | *type = buf[11]; | ||
202 | err = 0; | ||
203 | end: | ||
204 | kfree(buf); | ||
205 | return err; | ||
206 | } | ||
207 | |||
208 | int avc_bridgeco_get_plug_input(struct fw_unit *unit, | ||
209 | u8 addr[AVC_BRIDGECO_ADDR_BYTES], u8 input[7]) | ||
210 | { | ||
211 | int err; | ||
212 | u8 *buf; | ||
213 | |||
214 | buf = kzalloc(18, GFP_KERNEL); | ||
215 | if (buf == NULL) | ||
216 | return -ENOMEM; | ||
217 | |||
218 | /* Info type is 'plug input'. */ | ||
219 | avc_bridgeco_fill_plug_info_extension_command(buf, addr, 0x05); | ||
220 | |||
221 | err = fcp_avc_transaction(unit, buf, 16, buf, 16, | ||
222 | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | | ||
223 | BIT(6) | BIT(7)); | ||
224 | if ((err >= 0) && (err < 8)) | ||
225 | err = -EIO; | ||
226 | else if (buf[0] == 0x08) /* NOT IMPLEMENTED */ | ||
227 | err = -ENOSYS; | ||
228 | else if (buf[0] == 0x0a) /* REJECTED */ | ||
229 | err = -EINVAL; | ||
230 | else if (buf[0] == 0x0b) /* IN TRANSITION */ | ||
231 | err = -EAGAIN; | ||
232 | if (err < 0) | ||
233 | goto end; | ||
234 | |||
235 | memcpy(input, buf + 10, 5); | ||
236 | err = 0; | ||
237 | end: | ||
238 | kfree(buf); | ||
239 | return err; | ||
240 | } | ||
241 | |||
242 | int avc_bridgeco_get_plug_strm_fmt(struct fw_unit *unit, | ||
243 | u8 addr[AVC_BRIDGECO_ADDR_BYTES], u8 *buf, | ||
244 | unsigned int *len, unsigned int eid) | ||
245 | { | ||
246 | int err; | ||
247 | |||
248 | /* check given buffer */ | ||
249 | if ((buf == NULL) || (*len < 12)) { | ||
250 | err = -EINVAL; | ||
251 | goto end; | ||
252 | } | ||
253 | |||
254 | buf[0] = 0x01; /* AV/C STATUS */ | ||
255 | buf[2] = 0x2f; /* AV/C STREAM FORMAT SUPPORT */ | ||
256 | buf[3] = 0xc1; /* Bridgeco extension - List Request */ | ||
257 | avc_bridgeco_fill_extension_addr(buf, addr); | ||
258 | buf[10] = 0xff & eid; /* Entry ID */ | ||
259 | |||
260 | err = fcp_avc_transaction(unit, buf, 12, buf, *len, | ||
261 | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | | ||
262 | BIT(6) | BIT(7) | BIT(10)); | ||
263 | if ((err >= 0) && (err < 12)) | ||
264 | err = -EIO; | ||
265 | else if (buf[0] == 0x08) /* NOT IMPLEMENTED */ | ||
266 | err = -ENOSYS; | ||
267 | else if (buf[0] == 0x0a) /* REJECTED */ | ||
268 | err = -EINVAL; | ||
269 | else if (buf[0] == 0x0b) /* IN TRANSITION */ | ||
270 | err = -EAGAIN; | ||
271 | else if (buf[10] != eid) | ||
272 | err = -EIO; | ||
273 | if (err < 0) | ||
274 | goto end; | ||
275 | |||
276 | /* Pick up 'stream format info'. */ | ||
277 | memmove(buf, buf + 11, err - 11); | ||
278 | *len = err - 11; | ||
279 | err = 0; | ||
280 | end: | ||
281 | return err; | ||
282 | } | ||
diff --git a/sound/firewire/bebob/bebob_focusrite.c b/sound/firewire/bebob/bebob_focusrite.c new file mode 100644 index 000000000000..45a0eed6d5b1 --- /dev/null +++ b/sound/firewire/bebob/bebob_focusrite.c | |||
@@ -0,0 +1,279 @@ | |||
1 | /* | ||
2 | * bebob_focusrite.c - a part of driver for BeBoB based devices | ||
3 | * | ||
4 | * Copyright (c) 2013-2014 Takashi Sakamoto | ||
5 | * | ||
6 | * Licensed under the terms of the GNU General Public License, version 2. | ||
7 | */ | ||
8 | |||
9 | #include "./bebob.h" | ||
10 | |||
11 | #define ANA_IN "Analog In" | ||
12 | #define DIG_IN "Digital In" | ||
13 | #define ANA_OUT "Analog Out" | ||
14 | #define DIG_OUT "Digital Out" | ||
15 | #define STM_IN "Stream In" | ||
16 | |||
17 | #define SAFFIRE_ADDRESS_BASE 0x000100000000ULL | ||
18 | |||
19 | #define SAFFIRE_OFFSET_CLOCK_SOURCE 0x00f8 | ||
20 | #define SAFFIREPRO_OFFSET_CLOCK_SOURCE 0x0174 | ||
21 | |||
22 | /* whether sync to external device or not */ | ||
23 | #define SAFFIRE_OFFSET_CLOCK_SYNC_EXT 0x013c | ||
24 | #define SAFFIRE_LE_OFFSET_CLOCK_SYNC_EXT 0x0432 | ||
25 | #define SAFFIREPRO_OFFSET_CLOCK_SYNC_EXT 0x0164 | ||
26 | |||
27 | #define SAFFIRE_CLOCK_SOURCE_INTERNAL 0 | ||
28 | #define SAFFIRE_CLOCK_SOURCE_SPDIF 1 | ||
29 | |||
30 | /* '1' is absent, why... */ | ||
31 | #define SAFFIREPRO_CLOCK_SOURCE_INTERNAL 0 | ||
32 | #define SAFFIREPRO_CLOCK_SOURCE_SPDIF 2 | ||
33 | #define SAFFIREPRO_CLOCK_SOURCE_ADAT1 3 | ||
34 | #define SAFFIREPRO_CLOCK_SOURCE_ADAT2 4 | ||
35 | #define SAFFIREPRO_CLOCK_SOURCE_WORDCLOCK 5 | ||
36 | |||
37 | /* S/PDIF, ADAT1, ADAT2 is enabled or not. three quadlets */ | ||
38 | #define SAFFIREPRO_ENABLE_DIG_IFACES 0x01a4 | ||
39 | |||
40 | /* saffirepro has its own parameter for sampling frequency */ | ||
41 | #define SAFFIREPRO_RATE_NOREBOOT 0x01cc | ||
42 | /* index is the value for this register */ | ||
43 | static const unsigned int rates[] = { | ||
44 | [0] = 0, | ||
45 | [1] = 44100, | ||
46 | [2] = 48000, | ||
47 | [3] = 88200, | ||
48 | [4] = 96000, | ||
49 | [5] = 176400, | ||
50 | [6] = 192000 | ||
51 | }; | ||
52 | |||
53 | /* saffire(no label)/saffire LE has metering */ | ||
54 | #define SAFFIRE_OFFSET_METER 0x0100 | ||
55 | #define SAFFIRE_LE_OFFSET_METER 0x0168 | ||
56 | |||
57 | static inline int | ||
58 | saffire_read_block(struct snd_bebob *bebob, u64 offset, | ||
59 | u32 *buf, unsigned int size) | ||
60 | { | ||
61 | unsigned int i; | ||
62 | int err; | ||
63 | __be32 *tmp = (__be32 *)buf; | ||
64 | |||
65 | err = snd_fw_transaction(bebob->unit, TCODE_READ_BLOCK_REQUEST, | ||
66 | SAFFIRE_ADDRESS_BASE + offset, | ||
67 | tmp, size, 0); | ||
68 | if (err < 0) | ||
69 | goto end; | ||
70 | |||
71 | for (i = 0; i < size / sizeof(u32); i++) | ||
72 | buf[i] = be32_to_cpu(tmp[i]); | ||
73 | end: | ||
74 | return err; | ||
75 | } | ||
76 | |||
77 | static inline int | ||
78 | saffire_read_quad(struct snd_bebob *bebob, u64 offset, u32 *value) | ||
79 | { | ||
80 | int err; | ||
81 | __be32 tmp; | ||
82 | |||
83 | err = snd_fw_transaction(bebob->unit, TCODE_READ_QUADLET_REQUEST, | ||
84 | SAFFIRE_ADDRESS_BASE + offset, | ||
85 | &tmp, sizeof(__be32), 0); | ||
86 | if (err < 0) | ||
87 | goto end; | ||
88 | |||
89 | *value = be32_to_cpu(tmp); | ||
90 | end: | ||
91 | return err; | ||
92 | } | ||
93 | |||
94 | static inline int | ||
95 | saffire_write_quad(struct snd_bebob *bebob, u64 offset, u32 value) | ||
96 | { | ||
97 | __be32 data = cpu_to_be32(value); | ||
98 | |||
99 | return snd_fw_transaction(bebob->unit, TCODE_WRITE_QUADLET_REQUEST, | ||
100 | SAFFIRE_ADDRESS_BASE + offset, | ||
101 | &data, sizeof(__be32), 0); | ||
102 | } | ||
103 | |||
104 | static char *const saffirepro_26_clk_src_labels[] = { | ||
105 | SND_BEBOB_CLOCK_INTERNAL, "S/PDIF", "ADAT1", "ADAT2", "Word Clock" | ||
106 | }; | ||
107 | |||
108 | static char *const saffirepro_10_clk_src_labels[] = { | ||
109 | SND_BEBOB_CLOCK_INTERNAL, "S/PDIF", "Word Clock" | ||
110 | }; | ||
111 | static int | ||
112 | saffirepro_both_clk_freq_get(struct snd_bebob *bebob, unsigned int *rate) | ||
113 | { | ||
114 | u32 id; | ||
115 | int err; | ||
116 | |||
117 | err = saffire_read_quad(bebob, SAFFIREPRO_RATE_NOREBOOT, &id); | ||
118 | if (err < 0) | ||
119 | goto end; | ||
120 | if (id >= ARRAY_SIZE(rates)) | ||
121 | err = -EIO; | ||
122 | else | ||
123 | *rate = rates[id]; | ||
124 | end: | ||
125 | return err; | ||
126 | } | ||
127 | static int | ||
128 | saffirepro_both_clk_freq_set(struct snd_bebob *bebob, unsigned int rate) | ||
129 | { | ||
130 | u32 id; | ||
131 | |||
132 | for (id = 0; id < ARRAY_SIZE(rates); id++) { | ||
133 | if (rates[id] == rate) | ||
134 | break; | ||
135 | } | ||
136 | if (id == ARRAY_SIZE(rates)) | ||
137 | return -EINVAL; | ||
138 | |||
139 | return saffire_write_quad(bebob, SAFFIREPRO_RATE_NOREBOOT, id); | ||
140 | } | ||
141 | static int | ||
142 | saffirepro_both_clk_src_get(struct snd_bebob *bebob, unsigned int *id) | ||
143 | { | ||
144 | int err; | ||
145 | u32 value; | ||
146 | |||
147 | err = saffire_read_quad(bebob, SAFFIREPRO_OFFSET_CLOCK_SOURCE, &value); | ||
148 | if (err < 0) | ||
149 | goto end; | ||
150 | |||
151 | if (bebob->spec->clock->labels == saffirepro_10_clk_src_labels) { | ||
152 | if (value == SAFFIREPRO_CLOCK_SOURCE_WORDCLOCK) | ||
153 | *id = 2; | ||
154 | else if (value == SAFFIREPRO_CLOCK_SOURCE_SPDIF) | ||
155 | *id = 1; | ||
156 | } else if (value > 1) { | ||
157 | *id = value - 1; | ||
158 | } | ||
159 | end: | ||
160 | return err; | ||
161 | } | ||
162 | |||
163 | struct snd_bebob_spec saffire_le_spec; | ||
164 | static char *const saffire_both_clk_src_labels[] = { | ||
165 | SND_BEBOB_CLOCK_INTERNAL, "S/PDIF" | ||
166 | }; | ||
167 | static int | ||
168 | saffire_both_clk_src_get(struct snd_bebob *bebob, unsigned int *id) | ||
169 | { | ||
170 | int err; | ||
171 | u32 value; | ||
172 | |||
173 | err = saffire_read_quad(bebob, SAFFIRE_OFFSET_CLOCK_SOURCE, &value); | ||
174 | if (err >= 0) | ||
175 | *id = 0xff & value; | ||
176 | |||
177 | return err; | ||
178 | }; | ||
179 | static char *const saffire_le_meter_labels[] = { | ||
180 | ANA_IN, ANA_IN, DIG_IN, | ||
181 | ANA_OUT, ANA_OUT, ANA_OUT, ANA_OUT, | ||
182 | STM_IN, STM_IN | ||
183 | }; | ||
184 | static char *const saffire_meter_labels[] = { | ||
185 | ANA_IN, ANA_IN, | ||
186 | STM_IN, STM_IN, STM_IN, STM_IN, STM_IN, | ||
187 | }; | ||
188 | static int | ||
189 | saffire_meter_get(struct snd_bebob *bebob, u32 *buf, unsigned int size) | ||
190 | { | ||
191 | struct snd_bebob_meter_spec *spec = bebob->spec->meter; | ||
192 | unsigned int channels; | ||
193 | u64 offset; | ||
194 | int err; | ||
195 | |||
196 | if (spec->labels == saffire_le_meter_labels) | ||
197 | offset = SAFFIRE_LE_OFFSET_METER; | ||
198 | else | ||
199 | offset = SAFFIRE_OFFSET_METER; | ||
200 | |||
201 | channels = spec->num * 2; | ||
202 | if (size < channels * sizeof(u32)) | ||
203 | return -EIO; | ||
204 | |||
205 | err = saffire_read_block(bebob, offset, buf, size); | ||
206 | if (err >= 0 && spec->labels == saffire_le_meter_labels) { | ||
207 | swap(buf[1], buf[3]); | ||
208 | swap(buf[2], buf[3]); | ||
209 | swap(buf[3], buf[4]); | ||
210 | |||
211 | swap(buf[7], buf[10]); | ||
212 | swap(buf[8], buf[10]); | ||
213 | swap(buf[9], buf[11]); | ||
214 | swap(buf[11], buf[12]); | ||
215 | |||
216 | swap(buf[15], buf[16]); | ||
217 | } | ||
218 | |||
219 | return err; | ||
220 | } | ||
221 | |||
222 | static struct snd_bebob_rate_spec saffirepro_both_rate_spec = { | ||
223 | .get = &saffirepro_both_clk_freq_get, | ||
224 | .set = &saffirepro_both_clk_freq_set, | ||
225 | }; | ||
226 | /* Saffire Pro 26 I/O */ | ||
227 | static struct snd_bebob_clock_spec saffirepro_26_clk_spec = { | ||
228 | .num = ARRAY_SIZE(saffirepro_26_clk_src_labels), | ||
229 | .labels = saffirepro_26_clk_src_labels, | ||
230 | .get = &saffirepro_both_clk_src_get, | ||
231 | }; | ||
232 | struct snd_bebob_spec saffirepro_26_spec = { | ||
233 | .clock = &saffirepro_26_clk_spec, | ||
234 | .rate = &saffirepro_both_rate_spec, | ||
235 | .meter = NULL | ||
236 | }; | ||
237 | /* Saffire Pro 10 I/O */ | ||
238 | static struct snd_bebob_clock_spec saffirepro_10_clk_spec = { | ||
239 | .num = ARRAY_SIZE(saffirepro_10_clk_src_labels), | ||
240 | .labels = saffirepro_10_clk_src_labels, | ||
241 | .get = &saffirepro_both_clk_src_get, | ||
242 | }; | ||
243 | struct snd_bebob_spec saffirepro_10_spec = { | ||
244 | .clock = &saffirepro_10_clk_spec, | ||
245 | .rate = &saffirepro_both_rate_spec, | ||
246 | .meter = NULL | ||
247 | }; | ||
248 | |||
249 | static struct snd_bebob_rate_spec saffire_both_rate_spec = { | ||
250 | .get = &snd_bebob_stream_get_rate, | ||
251 | .set = &snd_bebob_stream_set_rate, | ||
252 | }; | ||
253 | static struct snd_bebob_clock_spec saffire_both_clk_spec = { | ||
254 | .num = ARRAY_SIZE(saffire_both_clk_src_labels), | ||
255 | .labels = saffire_both_clk_src_labels, | ||
256 | .get = &saffire_both_clk_src_get, | ||
257 | }; | ||
258 | /* Saffire LE */ | ||
259 | static struct snd_bebob_meter_spec saffire_le_meter_spec = { | ||
260 | .num = ARRAY_SIZE(saffire_le_meter_labels), | ||
261 | .labels = saffire_le_meter_labels, | ||
262 | .get = &saffire_meter_get, | ||
263 | }; | ||
264 | struct snd_bebob_spec saffire_le_spec = { | ||
265 | .clock = &saffire_both_clk_spec, | ||
266 | .rate = &saffire_both_rate_spec, | ||
267 | .meter = &saffire_le_meter_spec | ||
268 | }; | ||
269 | /* Saffire */ | ||
270 | static struct snd_bebob_meter_spec saffire_meter_spec = { | ||
271 | .num = ARRAY_SIZE(saffire_meter_labels), | ||
272 | .labels = saffire_meter_labels, | ||
273 | .get = &saffire_meter_get, | ||
274 | }; | ||
275 | struct snd_bebob_spec saffire_spec = { | ||
276 | .clock = &saffire_both_clk_spec, | ||
277 | .rate = &saffire_both_rate_spec, | ||
278 | .meter = &saffire_meter_spec | ||
279 | }; | ||
diff --git a/sound/firewire/bebob/bebob_hwdep.c b/sound/firewire/bebob/bebob_hwdep.c new file mode 100644 index 000000000000..ce731f4d8b4f --- /dev/null +++ b/sound/firewire/bebob/bebob_hwdep.c | |||
@@ -0,0 +1,199 @@ | |||
1 | /* | ||
2 | * bebob_hwdep.c - a part of driver for BeBoB based devices | ||
3 | * | ||
4 | * Copyright (c) 2013-2014 Takashi Sakamoto | ||
5 | * | ||
6 | * Licensed under the terms of the GNU General Public License, version 2. | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * This codes give three functionality. | ||
11 | * | ||
12 | * 1.get firewire node infomation | ||
13 | * 2.get notification about starting/stopping stream | ||
14 | * 3.lock/unlock stream | ||
15 | */ | ||
16 | |||
17 | #include "bebob.h" | ||
18 | |||
19 | static long | ||
20 | hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count, | ||
21 | loff_t *offset) | ||
22 | { | ||
23 | struct snd_bebob *bebob = hwdep->private_data; | ||
24 | DEFINE_WAIT(wait); | ||
25 | union snd_firewire_event event; | ||
26 | |||
27 | spin_lock_irq(&bebob->lock); | ||
28 | |||
29 | while (!bebob->dev_lock_changed) { | ||
30 | prepare_to_wait(&bebob->hwdep_wait, &wait, TASK_INTERRUPTIBLE); | ||
31 | spin_unlock_irq(&bebob->lock); | ||
32 | schedule(); | ||
33 | finish_wait(&bebob->hwdep_wait, &wait); | ||
34 | if (signal_pending(current)) | ||
35 | return -ERESTARTSYS; | ||
36 | spin_lock_irq(&bebob->lock); | ||
37 | } | ||
38 | |||
39 | memset(&event, 0, sizeof(event)); | ||
40 | if (bebob->dev_lock_changed) { | ||
41 | event.lock_status.type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS; | ||
42 | event.lock_status.status = (bebob->dev_lock_count > 0); | ||
43 | bebob->dev_lock_changed = false; | ||
44 | |||
45 | count = min_t(long, count, sizeof(event.lock_status)); | ||
46 | } | ||
47 | |||
48 | spin_unlock_irq(&bebob->lock); | ||
49 | |||
50 | if (copy_to_user(buf, &event, count)) | ||
51 | return -EFAULT; | ||
52 | |||
53 | return count; | ||
54 | } | ||
55 | |||
56 | static unsigned int | ||
57 | hwdep_poll(struct snd_hwdep *hwdep, struct file *file, poll_table *wait) | ||
58 | { | ||
59 | struct snd_bebob *bebob = hwdep->private_data; | ||
60 | unsigned int events; | ||
61 | |||
62 | poll_wait(file, &bebob->hwdep_wait, wait); | ||
63 | |||
64 | spin_lock_irq(&bebob->lock); | ||
65 | if (bebob->dev_lock_changed) | ||
66 | events = POLLIN | POLLRDNORM; | ||
67 | else | ||
68 | events = 0; | ||
69 | spin_unlock_irq(&bebob->lock); | ||
70 | |||
71 | return events; | ||
72 | } | ||
73 | |||
74 | static int | ||
75 | hwdep_get_info(struct snd_bebob *bebob, void __user *arg) | ||
76 | { | ||
77 | struct fw_device *dev = fw_parent_device(bebob->unit); | ||
78 | struct snd_firewire_get_info info; | ||
79 | |||
80 | memset(&info, 0, sizeof(info)); | ||
81 | info.type = SNDRV_FIREWIRE_TYPE_BEBOB; | ||
82 | info.card = dev->card->index; | ||
83 | *(__be32 *)&info.guid[0] = cpu_to_be32(dev->config_rom[3]); | ||
84 | *(__be32 *)&info.guid[4] = cpu_to_be32(dev->config_rom[4]); | ||
85 | strlcpy(info.device_name, dev_name(&dev->device), | ||
86 | sizeof(info.device_name)); | ||
87 | |||
88 | if (copy_to_user(arg, &info, sizeof(info))) | ||
89 | return -EFAULT; | ||
90 | |||
91 | return 0; | ||
92 | } | ||
93 | |||
94 | static int | ||
95 | hwdep_lock(struct snd_bebob *bebob) | ||
96 | { | ||
97 | int err; | ||
98 | |||
99 | spin_lock_irq(&bebob->lock); | ||
100 | |||
101 | if (bebob->dev_lock_count == 0) { | ||
102 | bebob->dev_lock_count = -1; | ||
103 | err = 0; | ||
104 | } else { | ||
105 | err = -EBUSY; | ||
106 | } | ||
107 | |||
108 | spin_unlock_irq(&bebob->lock); | ||
109 | |||
110 | return err; | ||
111 | } | ||
112 | |||
113 | static int | ||
114 | hwdep_unlock(struct snd_bebob *bebob) | ||
115 | { | ||
116 | int err; | ||
117 | |||
118 | spin_lock_irq(&bebob->lock); | ||
119 | |||
120 | if (bebob->dev_lock_count == -1) { | ||
121 | bebob->dev_lock_count = 0; | ||
122 | err = 0; | ||
123 | } else { | ||
124 | err = -EBADFD; | ||
125 | } | ||
126 | |||
127 | spin_unlock_irq(&bebob->lock); | ||
128 | |||
129 | return err; | ||
130 | } | ||
131 | |||
132 | static int | ||
133 | hwdep_release(struct snd_hwdep *hwdep, struct file *file) | ||
134 | { | ||
135 | struct snd_bebob *bebob = hwdep->private_data; | ||
136 | |||
137 | spin_lock_irq(&bebob->lock); | ||
138 | if (bebob->dev_lock_count == -1) | ||
139 | bebob->dev_lock_count = 0; | ||
140 | spin_unlock_irq(&bebob->lock); | ||
141 | |||
142 | return 0; | ||
143 | } | ||
144 | |||
145 | static int | ||
146 | hwdep_ioctl(struct snd_hwdep *hwdep, struct file *file, | ||
147 | unsigned int cmd, unsigned long arg) | ||
148 | { | ||
149 | struct snd_bebob *bebob = hwdep->private_data; | ||
150 | |||
151 | switch (cmd) { | ||
152 | case SNDRV_FIREWIRE_IOCTL_GET_INFO: | ||
153 | return hwdep_get_info(bebob, (void __user *)arg); | ||
154 | case SNDRV_FIREWIRE_IOCTL_LOCK: | ||
155 | return hwdep_lock(bebob); | ||
156 | case SNDRV_FIREWIRE_IOCTL_UNLOCK: | ||
157 | return hwdep_unlock(bebob); | ||
158 | default: | ||
159 | return -ENOIOCTLCMD; | ||
160 | } | ||
161 | } | ||
162 | |||
163 | #ifdef CONFIG_COMPAT | ||
164 | static int | ||
165 | hwdep_compat_ioctl(struct snd_hwdep *hwdep, struct file *file, | ||
166 | unsigned int cmd, unsigned long arg) | ||
167 | { | ||
168 | return hwdep_ioctl(hwdep, file, cmd, | ||
169 | (unsigned long)compat_ptr(arg)); | ||
170 | } | ||
171 | #else | ||
172 | #define hwdep_compat_ioctl NULL | ||
173 | #endif | ||
174 | |||
175 | static 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 | |||
183 | int snd_bebob_create_hwdep_device(struct snd_bebob *bebob) | ||
184 | { | ||
185 | struct snd_hwdep *hwdep; | ||
186 | int err; | ||
187 | |||
188 | err = snd_hwdep_new(bebob->card, "BeBoB", 0, &hwdep); | ||
189 | if (err < 0) | ||
190 | goto end; | ||
191 | strcpy(hwdep->name, "BeBoB"); | ||
192 | hwdep->iface = SNDRV_HWDEP_IFACE_FW_BEBOB; | ||
193 | hwdep->ops = hwdep_ops; | ||
194 | hwdep->private_data = bebob; | ||
195 | hwdep->exclusive = true; | ||
196 | end: | ||
197 | return err; | ||
198 | } | ||
199 | |||
diff --git a/sound/firewire/bebob/bebob_maudio.c b/sound/firewire/bebob/bebob_maudio.c new file mode 100644 index 000000000000..6af50eb80ea7 --- /dev/null +++ b/sound/firewire/bebob/bebob_maudio.c | |||
@@ -0,0 +1,792 @@ | |||
1 | /* | ||
2 | * bebob_maudio.c - a part of driver for BeBoB based devices | ||
3 | * | ||
4 | * Copyright (c) 2013-2014 Takashi Sakamoto | ||
5 | * | ||
6 | * Licensed under the terms of the GNU General Public License, version 2. | ||
7 | */ | ||
8 | |||
9 | #include "./bebob.h" | ||
10 | #include <sound/control.h> | ||
11 | |||
12 | /* | ||
13 | * Just powering on, Firewire 410/Audiophile/1814 and ProjectMix I/O wait to | ||
14 | * download firmware blob. To enable these devices, drivers should upload | ||
15 | * firmware blob and send a command to initialize configuration to factory | ||
16 | * settings when completing uploading. Then these devices generate bus reset | ||
17 | * and are recognized as new devices with the firmware. | ||
18 | * | ||
19 | * But with firmware version 5058 or later, the firmware is stored to flash | ||
20 | * memory in the device and drivers can tell bootloader to load the firmware | ||
21 | * by sending a cue. This cue must be sent one time. | ||
22 | * | ||
23 | * For streaming, both of output and input streams are needed for Firewire 410 | ||
24 | * and Ozonic. The single stream is OK for the other devices even if the clock | ||
25 | * source is not SYT-Match (I note no devices use SYT-Match). | ||
26 | * | ||
27 | * Without streaming, the devices except for Firewire Audiophile can mix any | ||
28 | * input and output. For this reason, Audiophile cannot be used as standalone | ||
29 | * mixer. | ||
30 | * | ||
31 | * Firewire 1814 and ProjectMix I/O uses special firmware. It will be freezed | ||
32 | * when receiving any commands which the firmware can't understand. These | ||
33 | * devices utilize completely different system to control. It is some | ||
34 | * write-transaction directly into a certain address. All of addresses for mixer | ||
35 | * functionality is between 0xffc700700000 to 0xffc70070009c. | ||
36 | */ | ||
37 | |||
38 | /* Offset from information register */ | ||
39 | #define INFO_OFFSET_SW_DATE 0x20 | ||
40 | |||
41 | /* Bootloader Protocol Version 1 */ | ||
42 | #define MAUDIO_BOOTLOADER_CUE1 0x00000001 | ||
43 | /* | ||
44 | * Initializing configuration to factory settings (= 0x1101), (swapped in line), | ||
45 | * Command code is zero (= 0x00), | ||
46 | * the number of operands is zero (= 0x00)(at least significant byte) | ||
47 | */ | ||
48 | #define MAUDIO_BOOTLOADER_CUE2 0x01110000 | ||
49 | /* padding */ | ||
50 | #define MAUDIO_BOOTLOADER_CUE3 0x00000000 | ||
51 | |||
52 | #define MAUDIO_SPECIFIC_ADDRESS 0xffc700000000ULL | ||
53 | |||
54 | #define METER_OFFSET 0x00600000 | ||
55 | |||
56 | /* some device has sync info after metering data */ | ||
57 | #define METER_SIZE_SPECIAL 84 /* with sync info */ | ||
58 | #define METER_SIZE_FW410 76 /* with sync info */ | ||
59 | #define METER_SIZE_AUDIOPHILE 60 /* with sync info */ | ||
60 | #define METER_SIZE_SOLO 52 /* with sync info */ | ||
61 | #define METER_SIZE_OZONIC 48 | ||
62 | #define METER_SIZE_NRV10 80 | ||
63 | |||
64 | /* labels for metering */ | ||
65 | #define ANA_IN "Analog In" | ||
66 | #define ANA_OUT "Analog Out" | ||
67 | #define DIG_IN "Digital In" | ||
68 | #define SPDIF_IN "S/PDIF In" | ||
69 | #define ADAT_IN "ADAT In" | ||
70 | #define DIG_OUT "Digital Out" | ||
71 | #define SPDIF_OUT "S/PDIF Out" | ||
72 | #define ADAT_OUT "ADAT Out" | ||
73 | #define STRM_IN "Stream In" | ||
74 | #define AUX_OUT "Aux Out" | ||
75 | #define HP_OUT "HP Out" | ||
76 | /* for NRV */ | ||
77 | #define UNKNOWN_METER "Unknown" | ||
78 | |||
79 | struct special_params { | ||
80 | bool is1814; | ||
81 | unsigned int clk_src; | ||
82 | unsigned int dig_in_fmt; | ||
83 | unsigned int dig_out_fmt; | ||
84 | unsigned int clk_lock; | ||
85 | struct snd_ctl_elem_id *ctl_id_sync; | ||
86 | }; | ||
87 | |||
88 | /* | ||
89 | * For some M-Audio devices, this module just send cue to load firmware. After | ||
90 | * loading, the device generates bus reset and newly detected. | ||
91 | * | ||
92 | * If we make any transactions to load firmware, the operation may failed. | ||
93 | */ | ||
94 | int snd_bebob_maudio_load_firmware(struct fw_unit *unit) | ||
95 | { | ||
96 | struct fw_device *device = fw_parent_device(unit); | ||
97 | int err, rcode; | ||
98 | u64 date; | ||
99 | __be32 cues[3] = { | ||
100 | MAUDIO_BOOTLOADER_CUE1, | ||
101 | MAUDIO_BOOTLOADER_CUE2, | ||
102 | MAUDIO_BOOTLOADER_CUE3 | ||
103 | }; | ||
104 | |||
105 | /* check date of software used to build */ | ||
106 | err = snd_bebob_read_block(unit, INFO_OFFSET_SW_DATE, | ||
107 | &date, sizeof(u64)); | ||
108 | if (err < 0) | ||
109 | goto end; | ||
110 | /* | ||
111 | * firmware version 5058 or later has date later than "20070401", but | ||
112 | * 'date' is not null-terminated. | ||
113 | */ | ||
114 | if (date < 0x3230303730343031LL) { | ||
115 | dev_err(&unit->device, | ||
116 | "Use firmware version 5058 or later\n"); | ||
117 | err = -ENOSYS; | ||
118 | goto end; | ||
119 | } | ||
120 | |||
121 | rcode = fw_run_transaction(device->card, TCODE_WRITE_BLOCK_REQUEST, | ||
122 | device->node_id, device->generation, | ||
123 | device->max_speed, BEBOB_ADDR_REG_REQ, | ||
124 | cues, sizeof(cues)); | ||
125 | if (rcode != RCODE_COMPLETE) { | ||
126 | dev_err(&unit->device, | ||
127 | "Failed to send a cue to load firmware\n"); | ||
128 | err = -EIO; | ||
129 | } | ||
130 | end: | ||
131 | return err; | ||
132 | } | ||
133 | |||
134 | static inline int | ||
135 | get_meter(struct snd_bebob *bebob, void *buf, unsigned int size) | ||
136 | { | ||
137 | return snd_fw_transaction(bebob->unit, TCODE_READ_BLOCK_REQUEST, | ||
138 | MAUDIO_SPECIFIC_ADDRESS + METER_OFFSET, | ||
139 | buf, size, 0); | ||
140 | } | ||
141 | |||
142 | static int | ||
143 | check_clk_sync(struct snd_bebob *bebob, unsigned int size, bool *sync) | ||
144 | { | ||
145 | int err; | ||
146 | u8 *buf; | ||
147 | |||
148 | buf = kmalloc(size, GFP_KERNEL); | ||
149 | if (buf == NULL) | ||
150 | return -ENOMEM; | ||
151 | |||
152 | err = get_meter(bebob, buf, size); | ||
153 | if (err < 0) | ||
154 | goto end; | ||
155 | |||
156 | /* if synced, this value is the same as SFC of FDF in CIP header */ | ||
157 | *sync = (buf[size - 2] != 0xff); | ||
158 | end: | ||
159 | kfree(buf); | ||
160 | return err; | ||
161 | } | ||
162 | |||
163 | /* | ||
164 | * dig_fmt: 0x00:S/PDIF, 0x01:ADAT | ||
165 | * clk_lock: 0x00:unlock, 0x01:lock | ||
166 | */ | ||
167 | static int | ||
168 | avc_maudio_set_special_clk(struct snd_bebob *bebob, unsigned int clk_src, | ||
169 | unsigned int dig_in_fmt, unsigned int dig_out_fmt, | ||
170 | unsigned int clk_lock) | ||
171 | { | ||
172 | struct special_params *params = bebob->maudio_special_quirk; | ||
173 | int err; | ||
174 | u8 *buf; | ||
175 | |||
176 | if (amdtp_stream_running(&bebob->rx_stream) || | ||
177 | amdtp_stream_running(&bebob->tx_stream)) | ||
178 | return -EBUSY; | ||
179 | |||
180 | buf = kmalloc(12, GFP_KERNEL); | ||
181 | if (buf == NULL) | ||
182 | return -ENOMEM; | ||
183 | |||
184 | buf[0] = 0x00; /* CONTROL */ | ||
185 | buf[1] = 0xff; /* UNIT */ | ||
186 | buf[2] = 0x00; /* vendor dependent */ | ||
187 | buf[3] = 0x04; /* company ID high */ | ||
188 | buf[4] = 0x00; /* company ID middle */ | ||
189 | buf[5] = 0x04; /* company ID low */ | ||
190 | buf[6] = 0xff & clk_src; /* clock source */ | ||
191 | buf[7] = 0xff & dig_in_fmt; /* input digital format */ | ||
192 | buf[8] = 0xff & dig_out_fmt; /* output digital format */ | ||
193 | buf[9] = 0xff & clk_lock; /* lock these settings */ | ||
194 | buf[10] = 0x00; /* padding */ | ||
195 | buf[11] = 0x00; /* padding */ | ||
196 | |||
197 | err = fcp_avc_transaction(bebob->unit, buf, 12, buf, 12, | ||
198 | BIT(1) | BIT(2) | BIT(3) | BIT(4) | | ||
199 | BIT(5) | BIT(6) | BIT(7) | BIT(8) | | ||
200 | BIT(9)); | ||
201 | if ((err > 0) && (err < 10)) | ||
202 | err = -EIO; | ||
203 | else if (buf[0] == 0x08) /* NOT IMPLEMENTED */ | ||
204 | err = -ENOSYS; | ||
205 | else if (buf[0] == 0x0a) /* REJECTED */ | ||
206 | err = -EINVAL; | ||
207 | if (err < 0) | ||
208 | goto end; | ||
209 | |||
210 | params->clk_src = buf[6]; | ||
211 | params->dig_in_fmt = buf[7]; | ||
212 | params->dig_out_fmt = buf[8]; | ||
213 | params->clk_lock = buf[9]; | ||
214 | |||
215 | if (params->ctl_id_sync) | ||
216 | snd_ctl_notify(bebob->card, SNDRV_CTL_EVENT_MASK_VALUE, | ||
217 | params->ctl_id_sync); | ||
218 | |||
219 | err = 0; | ||
220 | end: | ||
221 | kfree(buf); | ||
222 | return err; | ||
223 | } | ||
224 | static void | ||
225 | special_stream_formation_set(struct snd_bebob *bebob) | ||
226 | { | ||
227 | static const unsigned int ch_table[2][2][3] = { | ||
228 | /* AMDTP_OUT_STREAM */ | ||
229 | { { 6, 6, 4 }, /* SPDIF */ | ||
230 | { 12, 8, 4 } }, /* ADAT */ | ||
231 | /* AMDTP_IN_STREAM */ | ||
232 | { { 10, 10, 2 }, /* SPDIF */ | ||
233 | { 16, 12, 2 } } /* ADAT */ | ||
234 | }; | ||
235 | struct special_params *params = bebob->maudio_special_quirk; | ||
236 | unsigned int i, max; | ||
237 | |||
238 | max = SND_BEBOB_STRM_FMT_ENTRIES - 1; | ||
239 | if (!params->is1814) | ||
240 | max -= 2; | ||
241 | |||
242 | for (i = 0; i < max; i++) { | ||
243 | bebob->tx_stream_formations[i + 1].pcm = | ||
244 | ch_table[AMDTP_IN_STREAM][params->dig_in_fmt][i / 2]; | ||
245 | bebob->tx_stream_formations[i + 1].midi = 1; | ||
246 | |||
247 | bebob->rx_stream_formations[i + 1].pcm = | ||
248 | ch_table[AMDTP_OUT_STREAM][params->dig_out_fmt][i / 2]; | ||
249 | bebob->rx_stream_formations[i + 1].midi = 1; | ||
250 | } | ||
251 | } | ||
252 | |||
253 | static int add_special_controls(struct snd_bebob *bebob); | ||
254 | int | ||
255 | snd_bebob_maudio_special_discover(struct snd_bebob *bebob, bool is1814) | ||
256 | { | ||
257 | struct special_params *params; | ||
258 | int err; | ||
259 | |||
260 | params = kzalloc(sizeof(struct special_params), GFP_KERNEL); | ||
261 | if (params == NULL) | ||
262 | return -ENOMEM; | ||
263 | |||
264 | mutex_lock(&bebob->mutex); | ||
265 | |||
266 | bebob->maudio_special_quirk = (void *)params; | ||
267 | params->is1814 = is1814; | ||
268 | |||
269 | /* initialize these parameters because driver is not allowed to ask */ | ||
270 | bebob->rx_stream.context = ERR_PTR(-1); | ||
271 | bebob->tx_stream.context = ERR_PTR(-1); | ||
272 | err = avc_maudio_set_special_clk(bebob, 0x03, 0x00, 0x00, 0x00); | ||
273 | if (err < 0) { | ||
274 | dev_err(&bebob->unit->device, | ||
275 | "fail to initialize clock params: %d\n", err); | ||
276 | goto end; | ||
277 | } | ||
278 | |||
279 | err = add_special_controls(bebob); | ||
280 | if (err < 0) | ||
281 | goto end; | ||
282 | |||
283 | special_stream_formation_set(bebob); | ||
284 | |||
285 | if (params->is1814) { | ||
286 | bebob->midi_input_ports = 1; | ||
287 | bebob->midi_output_ports = 1; | ||
288 | } else { | ||
289 | bebob->midi_input_ports = 2; | ||
290 | bebob->midi_output_ports = 2; | ||
291 | } | ||
292 | end: | ||
293 | if (err < 0) { | ||
294 | kfree(params); | ||
295 | bebob->maudio_special_quirk = NULL; | ||
296 | } | ||
297 | mutex_unlock(&bebob->mutex); | ||
298 | return err; | ||
299 | } | ||
300 | |||
301 | /* Input plug shows actual rate. Output plug is needless for this purpose. */ | ||
302 | static int special_get_rate(struct snd_bebob *bebob, unsigned int *rate) | ||
303 | { | ||
304 | int err, trials; | ||
305 | |||
306 | trials = 0; | ||
307 | do { | ||
308 | err = avc_general_get_sig_fmt(bebob->unit, rate, | ||
309 | AVC_GENERAL_PLUG_DIR_IN, 0); | ||
310 | } while (err == -EAGAIN && ++trials < 3); | ||
311 | |||
312 | return err; | ||
313 | } | ||
314 | static int special_set_rate(struct snd_bebob *bebob, unsigned int rate) | ||
315 | { | ||
316 | struct special_params *params = bebob->maudio_special_quirk; | ||
317 | int err; | ||
318 | |||
319 | err = avc_general_set_sig_fmt(bebob->unit, rate, | ||
320 | AVC_GENERAL_PLUG_DIR_OUT, 0); | ||
321 | if (err < 0) | ||
322 | goto end; | ||
323 | |||
324 | /* | ||
325 | * Just after changing sampling rate for output, a followed command | ||
326 | * for input is easy to fail. This is a workaround fot this issue. | ||
327 | */ | ||
328 | msleep(100); | ||
329 | |||
330 | err = avc_general_set_sig_fmt(bebob->unit, rate, | ||
331 | AVC_GENERAL_PLUG_DIR_IN, 0); | ||
332 | if (err < 0) | ||
333 | goto end; | ||
334 | |||
335 | if (params->ctl_id_sync) | ||
336 | snd_ctl_notify(bebob->card, SNDRV_CTL_EVENT_MASK_VALUE, | ||
337 | params->ctl_id_sync); | ||
338 | end: | ||
339 | return err; | ||
340 | } | ||
341 | |||
342 | /* Clock source control for special firmware */ | ||
343 | static char *const special_clk_labels[] = { | ||
344 | SND_BEBOB_CLOCK_INTERNAL " with Digital Mute", "Digital", | ||
345 | "Word Clock", SND_BEBOB_CLOCK_INTERNAL}; | ||
346 | static int special_clk_get(struct snd_bebob *bebob, unsigned int *id) | ||
347 | { | ||
348 | struct special_params *params = bebob->maudio_special_quirk; | ||
349 | *id = params->clk_src; | ||
350 | return 0; | ||
351 | } | ||
352 | static int special_clk_ctl_info(struct snd_kcontrol *kctl, | ||
353 | struct snd_ctl_elem_info *einf) | ||
354 | { | ||
355 | einf->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
356 | einf->count = 1; | ||
357 | einf->value.enumerated.items = ARRAY_SIZE(special_clk_labels); | ||
358 | |||
359 | if (einf->value.enumerated.item >= einf->value.enumerated.items) | ||
360 | einf->value.enumerated.item = einf->value.enumerated.items - 1; | ||
361 | |||
362 | strcpy(einf->value.enumerated.name, | ||
363 | special_clk_labels[einf->value.enumerated.item]); | ||
364 | |||
365 | return 0; | ||
366 | } | ||
367 | static int special_clk_ctl_get(struct snd_kcontrol *kctl, | ||
368 | struct snd_ctl_elem_value *uval) | ||
369 | { | ||
370 | struct snd_bebob *bebob = snd_kcontrol_chip(kctl); | ||
371 | struct special_params *params = bebob->maudio_special_quirk; | ||
372 | uval->value.enumerated.item[0] = params->clk_src; | ||
373 | return 0; | ||
374 | } | ||
375 | static int special_clk_ctl_put(struct snd_kcontrol *kctl, | ||
376 | struct snd_ctl_elem_value *uval) | ||
377 | { | ||
378 | struct snd_bebob *bebob = snd_kcontrol_chip(kctl); | ||
379 | struct special_params *params = bebob->maudio_special_quirk; | ||
380 | int err, id; | ||
381 | |||
382 | mutex_lock(&bebob->mutex); | ||
383 | |||
384 | id = uval->value.enumerated.item[0]; | ||
385 | if (id >= ARRAY_SIZE(special_clk_labels)) | ||
386 | return 0; | ||
387 | |||
388 | err = avc_maudio_set_special_clk(bebob, id, | ||
389 | params->dig_in_fmt, | ||
390 | params->dig_out_fmt, | ||
391 | params->clk_lock); | ||
392 | mutex_unlock(&bebob->mutex); | ||
393 | |||
394 | return err >= 0; | ||
395 | } | ||
396 | static struct snd_kcontrol_new special_clk_ctl = { | ||
397 | .name = "Clock Source", | ||
398 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
399 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | ||
400 | .info = special_clk_ctl_info, | ||
401 | .get = special_clk_ctl_get, | ||
402 | .put = special_clk_ctl_put | ||
403 | }; | ||
404 | |||
405 | /* Clock synchronization control for special firmware */ | ||
406 | static int special_sync_ctl_info(struct snd_kcontrol *kctl, | ||
407 | struct snd_ctl_elem_info *einf) | ||
408 | { | ||
409 | einf->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
410 | einf->count = 1; | ||
411 | einf->value.integer.min = 0; | ||
412 | einf->value.integer.max = 1; | ||
413 | |||
414 | return 0; | ||
415 | } | ||
416 | static int special_sync_ctl_get(struct snd_kcontrol *kctl, | ||
417 | struct snd_ctl_elem_value *uval) | ||
418 | { | ||
419 | struct snd_bebob *bebob = snd_kcontrol_chip(kctl); | ||
420 | int err; | ||
421 | bool synced = 0; | ||
422 | |||
423 | err = check_clk_sync(bebob, METER_SIZE_SPECIAL, &synced); | ||
424 | if (err >= 0) | ||
425 | uval->value.integer.value[0] = synced; | ||
426 | |||
427 | return 0; | ||
428 | } | ||
429 | static struct snd_kcontrol_new special_sync_ctl = { | ||
430 | .name = "Sync Status", | ||
431 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
432 | .access = SNDRV_CTL_ELEM_ACCESS_READ, | ||
433 | .info = special_sync_ctl_info, | ||
434 | .get = special_sync_ctl_get, | ||
435 | }; | ||
436 | |||
437 | /* Digital interface control for special firmware */ | ||
438 | static char *const special_dig_iface_labels[] = { | ||
439 | "S/PDIF Optical", "S/PDIF Coaxial", "ADAT Optical" | ||
440 | }; | ||
441 | static int special_dig_in_iface_ctl_info(struct snd_kcontrol *kctl, | ||
442 | struct snd_ctl_elem_info *einf) | ||
443 | { | ||
444 | einf->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
445 | einf->count = 1; | ||
446 | einf->value.enumerated.items = ARRAY_SIZE(special_dig_iface_labels); | ||
447 | |||
448 | if (einf->value.enumerated.item >= einf->value.enumerated.items) | ||
449 | einf->value.enumerated.item = einf->value.enumerated.items - 1; | ||
450 | |||
451 | strcpy(einf->value.enumerated.name, | ||
452 | special_dig_iface_labels[einf->value.enumerated.item]); | ||
453 | |||
454 | return 0; | ||
455 | } | ||
456 | static int special_dig_in_iface_ctl_get(struct snd_kcontrol *kctl, | ||
457 | struct snd_ctl_elem_value *uval) | ||
458 | { | ||
459 | struct snd_bebob *bebob = snd_kcontrol_chip(kctl); | ||
460 | struct special_params *params = bebob->maudio_special_quirk; | ||
461 | unsigned int dig_in_iface; | ||
462 | int err, val; | ||
463 | |||
464 | mutex_lock(&bebob->mutex); | ||
465 | |||
466 | err = avc_audio_get_selector(bebob->unit, 0x00, 0x04, | ||
467 | &dig_in_iface); | ||
468 | if (err < 0) { | ||
469 | dev_err(&bebob->unit->device, | ||
470 | "fail to get digital input interface: %d\n", err); | ||
471 | goto end; | ||
472 | } | ||
473 | |||
474 | /* encoded id for user value */ | ||
475 | val = (params->dig_in_fmt << 1) | (dig_in_iface & 0x01); | ||
476 | |||
477 | /* for ADAT Optical */ | ||
478 | if (val > 2) | ||
479 | val = 2; | ||
480 | |||
481 | uval->value.enumerated.item[0] = val; | ||
482 | end: | ||
483 | mutex_unlock(&bebob->mutex); | ||
484 | return err; | ||
485 | } | ||
486 | static int special_dig_in_iface_ctl_set(struct snd_kcontrol *kctl, | ||
487 | struct snd_ctl_elem_value *uval) | ||
488 | { | ||
489 | struct snd_bebob *bebob = snd_kcontrol_chip(kctl); | ||
490 | struct special_params *params = bebob->maudio_special_quirk; | ||
491 | unsigned int id, dig_in_fmt, dig_in_iface; | ||
492 | int err; | ||
493 | |||
494 | mutex_lock(&bebob->mutex); | ||
495 | |||
496 | id = uval->value.enumerated.item[0]; | ||
497 | |||
498 | /* decode user value */ | ||
499 | dig_in_fmt = (id >> 1) & 0x01; | ||
500 | dig_in_iface = id & 0x01; | ||
501 | |||
502 | err = avc_maudio_set_special_clk(bebob, | ||
503 | params->clk_src, | ||
504 | dig_in_fmt, | ||
505 | params->dig_out_fmt, | ||
506 | params->clk_lock); | ||
507 | if ((err < 0) || (params->dig_in_fmt > 0)) /* ADAT */ | ||
508 | goto end; | ||
509 | |||
510 | err = avc_audio_set_selector(bebob->unit, 0x00, 0x04, dig_in_iface); | ||
511 | if (err < 0) | ||
512 | dev_err(&bebob->unit->device, | ||
513 | "fail to set digital input interface: %d\n", err); | ||
514 | end: | ||
515 | special_stream_formation_set(bebob); | ||
516 | mutex_unlock(&bebob->mutex); | ||
517 | return err; | ||
518 | } | ||
519 | static struct snd_kcontrol_new special_dig_in_iface_ctl = { | ||
520 | .name = "Digital Input Interface", | ||
521 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
522 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | ||
523 | .info = special_dig_in_iface_ctl_info, | ||
524 | .get = special_dig_in_iface_ctl_get, | ||
525 | .put = special_dig_in_iface_ctl_set | ||
526 | }; | ||
527 | |||
528 | static int special_dig_out_iface_ctl_info(struct snd_kcontrol *kctl, | ||
529 | struct snd_ctl_elem_info *einf) | ||
530 | { | ||
531 | einf->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
532 | einf->count = 1; | ||
533 | einf->value.enumerated.items = ARRAY_SIZE(special_dig_iface_labels) - 1; | ||
534 | |||
535 | if (einf->value.enumerated.item >= einf->value.enumerated.items) | ||
536 | einf->value.enumerated.item = einf->value.enumerated.items - 1; | ||
537 | |||
538 | strcpy(einf->value.enumerated.name, | ||
539 | special_dig_iface_labels[einf->value.enumerated.item + 1]); | ||
540 | |||
541 | return 0; | ||
542 | } | ||
543 | static int special_dig_out_iface_ctl_get(struct snd_kcontrol *kctl, | ||
544 | struct snd_ctl_elem_value *uval) | ||
545 | { | ||
546 | struct snd_bebob *bebob = snd_kcontrol_chip(kctl); | ||
547 | struct special_params *params = bebob->maudio_special_quirk; | ||
548 | mutex_lock(&bebob->mutex); | ||
549 | uval->value.enumerated.item[0] = params->dig_out_fmt; | ||
550 | mutex_unlock(&bebob->mutex); | ||
551 | return 0; | ||
552 | } | ||
553 | static int special_dig_out_iface_ctl_set(struct snd_kcontrol *kctl, | ||
554 | struct snd_ctl_elem_value *uval) | ||
555 | { | ||
556 | struct snd_bebob *bebob = snd_kcontrol_chip(kctl); | ||
557 | struct special_params *params = bebob->maudio_special_quirk; | ||
558 | unsigned int id; | ||
559 | int err; | ||
560 | |||
561 | mutex_lock(&bebob->mutex); | ||
562 | |||
563 | id = uval->value.enumerated.item[0]; | ||
564 | |||
565 | err = avc_maudio_set_special_clk(bebob, | ||
566 | params->clk_src, | ||
567 | params->dig_in_fmt, | ||
568 | id, params->clk_lock); | ||
569 | if (err >= 0) | ||
570 | special_stream_formation_set(bebob); | ||
571 | |||
572 | mutex_unlock(&bebob->mutex); | ||
573 | return err; | ||
574 | } | ||
575 | static struct snd_kcontrol_new special_dig_out_iface_ctl = { | ||
576 | .name = "Digital Output Interface", | ||
577 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
578 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | ||
579 | .info = special_dig_out_iface_ctl_info, | ||
580 | .get = special_dig_out_iface_ctl_get, | ||
581 | .put = special_dig_out_iface_ctl_set | ||
582 | }; | ||
583 | |||
584 | static int add_special_controls(struct snd_bebob *bebob) | ||
585 | { | ||
586 | struct snd_kcontrol *kctl; | ||
587 | struct special_params *params = bebob->maudio_special_quirk; | ||
588 | int err; | ||
589 | |||
590 | kctl = snd_ctl_new1(&special_clk_ctl, bebob); | ||
591 | err = snd_ctl_add(bebob->card, kctl); | ||
592 | if (err < 0) | ||
593 | goto end; | ||
594 | |||
595 | kctl = snd_ctl_new1(&special_sync_ctl, bebob); | ||
596 | err = snd_ctl_add(bebob->card, kctl); | ||
597 | if (err < 0) | ||
598 | goto end; | ||
599 | params->ctl_id_sync = &kctl->id; | ||
600 | |||
601 | kctl = snd_ctl_new1(&special_dig_in_iface_ctl, bebob); | ||
602 | err = snd_ctl_add(bebob->card, kctl); | ||
603 | if (err < 0) | ||
604 | goto end; | ||
605 | |||
606 | kctl = snd_ctl_new1(&special_dig_out_iface_ctl, bebob); | ||
607 | err = snd_ctl_add(bebob->card, kctl); | ||
608 | end: | ||
609 | return err; | ||
610 | } | ||
611 | |||
612 | /* Hardware metering for special firmware */ | ||
613 | static char *const special_meter_labels[] = { | ||
614 | ANA_IN, ANA_IN, ANA_IN, ANA_IN, | ||
615 | SPDIF_IN, | ||
616 | ADAT_IN, ADAT_IN, ADAT_IN, ADAT_IN, | ||
617 | ANA_OUT, ANA_OUT, | ||
618 | SPDIF_OUT, | ||
619 | ADAT_OUT, ADAT_OUT, ADAT_OUT, ADAT_OUT, | ||
620 | HP_OUT, HP_OUT, | ||
621 | AUX_OUT | ||
622 | }; | ||
623 | static int | ||
624 | special_meter_get(struct snd_bebob *bebob, u32 *target, unsigned int size) | ||
625 | { | ||
626 | u16 *buf; | ||
627 | unsigned int i, c, channels; | ||
628 | int err; | ||
629 | |||
630 | channels = ARRAY_SIZE(special_meter_labels) * 2; | ||
631 | if (size < channels * sizeof(u32)) | ||
632 | return -EINVAL; | ||
633 | |||
634 | /* omit last 4 bytes because it's clock info. */ | ||
635 | buf = kmalloc(METER_SIZE_SPECIAL - 4, GFP_KERNEL); | ||
636 | if (buf == NULL) | ||
637 | return -ENOMEM; | ||
638 | |||
639 | err = get_meter(bebob, (void *)buf, METER_SIZE_SPECIAL - 4); | ||
640 | if (err < 0) | ||
641 | goto end; | ||
642 | |||
643 | /* Its format is u16 and some channels are unknown. */ | ||
644 | i = 0; | ||
645 | for (c = 2; c < channels + 2; c++) | ||
646 | target[i++] = be16_to_cpu(buf[c]) << 16; | ||
647 | end: | ||
648 | kfree(buf); | ||
649 | return err; | ||
650 | } | ||
651 | |||
652 | /* last 4 bytes are omitted because it's clock info. */ | ||
653 | static char *const fw410_meter_labels[] = { | ||
654 | ANA_IN, DIG_IN, | ||
655 | ANA_OUT, ANA_OUT, ANA_OUT, ANA_OUT, DIG_OUT, | ||
656 | HP_OUT | ||
657 | }; | ||
658 | static char *const audiophile_meter_labels[] = { | ||
659 | ANA_IN, DIG_IN, | ||
660 | ANA_OUT, ANA_OUT, DIG_OUT, | ||
661 | HP_OUT, AUX_OUT, | ||
662 | }; | ||
663 | static char *const solo_meter_labels[] = { | ||
664 | ANA_IN, DIG_IN, | ||
665 | STRM_IN, STRM_IN, | ||
666 | ANA_OUT, DIG_OUT | ||
667 | }; | ||
668 | |||
669 | /* no clock info */ | ||
670 | static char *const ozonic_meter_labels[] = { | ||
671 | ANA_IN, ANA_IN, | ||
672 | STRM_IN, STRM_IN, | ||
673 | ANA_OUT, ANA_OUT | ||
674 | }; | ||
675 | /* TODO: need testers. these positions are based on authour's assumption */ | ||
676 | static char *const nrv10_meter_labels[] = { | ||
677 | ANA_IN, ANA_IN, ANA_IN, ANA_IN, | ||
678 | DIG_IN, | ||
679 | ANA_OUT, ANA_OUT, ANA_OUT, ANA_OUT, | ||
680 | DIG_IN | ||
681 | }; | ||
682 | static int | ||
683 | normal_meter_get(struct snd_bebob *bebob, u32 *buf, unsigned int size) | ||
684 | { | ||
685 | struct snd_bebob_meter_spec *spec = bebob->spec->meter; | ||
686 | unsigned int c, channels; | ||
687 | int err; | ||
688 | |||
689 | channels = spec->num * 2; | ||
690 | if (size < channels * sizeof(u32)) | ||
691 | return -EINVAL; | ||
692 | |||
693 | err = get_meter(bebob, (void *)buf, size); | ||
694 | if (err < 0) | ||
695 | goto end; | ||
696 | |||
697 | for (c = 0; c < channels; c++) | ||
698 | be32_to_cpus(&buf[c]); | ||
699 | |||
700 | /* swap stream channels because inverted */ | ||
701 | if (spec->labels == solo_meter_labels) { | ||
702 | swap(buf[4], buf[6]); | ||
703 | swap(buf[5], buf[7]); | ||
704 | } | ||
705 | end: | ||
706 | return err; | ||
707 | } | ||
708 | |||
709 | /* for special customized devices */ | ||
710 | static struct snd_bebob_rate_spec special_rate_spec = { | ||
711 | .get = &special_get_rate, | ||
712 | .set = &special_set_rate, | ||
713 | }; | ||
714 | static struct snd_bebob_clock_spec special_clk_spec = { | ||
715 | .num = ARRAY_SIZE(special_clk_labels), | ||
716 | .labels = special_clk_labels, | ||
717 | .get = &special_clk_get, | ||
718 | }; | ||
719 | static struct snd_bebob_meter_spec special_meter_spec = { | ||
720 | .num = ARRAY_SIZE(special_meter_labels), | ||
721 | .labels = special_meter_labels, | ||
722 | .get = &special_meter_get | ||
723 | }; | ||
724 | struct snd_bebob_spec maudio_special_spec = { | ||
725 | .clock = &special_clk_spec, | ||
726 | .rate = &special_rate_spec, | ||
727 | .meter = &special_meter_spec | ||
728 | }; | ||
729 | |||
730 | /* Firewire 410 specification */ | ||
731 | static struct snd_bebob_rate_spec usual_rate_spec = { | ||
732 | .get = &snd_bebob_stream_get_rate, | ||
733 | .set = &snd_bebob_stream_set_rate, | ||
734 | }; | ||
735 | static struct snd_bebob_meter_spec fw410_meter_spec = { | ||
736 | .num = ARRAY_SIZE(fw410_meter_labels), | ||
737 | .labels = fw410_meter_labels, | ||
738 | .get = &normal_meter_get | ||
739 | }; | ||
740 | struct snd_bebob_spec maudio_fw410_spec = { | ||
741 | .clock = NULL, | ||
742 | .rate = &usual_rate_spec, | ||
743 | .meter = &fw410_meter_spec | ||
744 | }; | ||
745 | |||
746 | /* Firewire Audiophile specification */ | ||
747 | static struct snd_bebob_meter_spec audiophile_meter_spec = { | ||
748 | .num = ARRAY_SIZE(audiophile_meter_labels), | ||
749 | .labels = audiophile_meter_labels, | ||
750 | .get = &normal_meter_get | ||
751 | }; | ||
752 | struct snd_bebob_spec maudio_audiophile_spec = { | ||
753 | .clock = NULL, | ||
754 | .rate = &usual_rate_spec, | ||
755 | .meter = &audiophile_meter_spec | ||
756 | }; | ||
757 | |||
758 | /* Firewire Solo specification */ | ||
759 | static struct snd_bebob_meter_spec solo_meter_spec = { | ||
760 | .num = ARRAY_SIZE(solo_meter_labels), | ||
761 | .labels = solo_meter_labels, | ||
762 | .get = &normal_meter_get | ||
763 | }; | ||
764 | struct snd_bebob_spec maudio_solo_spec = { | ||
765 | .clock = NULL, | ||
766 | .rate = &usual_rate_spec, | ||
767 | .meter = &solo_meter_spec | ||
768 | }; | ||
769 | |||
770 | /* Ozonic specification */ | ||
771 | static struct snd_bebob_meter_spec ozonic_meter_spec = { | ||
772 | .num = ARRAY_SIZE(ozonic_meter_labels), | ||
773 | .labels = ozonic_meter_labels, | ||
774 | .get = &normal_meter_get | ||
775 | }; | ||
776 | struct snd_bebob_spec maudio_ozonic_spec = { | ||
777 | .clock = NULL, | ||
778 | .rate = &usual_rate_spec, | ||
779 | .meter = &ozonic_meter_spec | ||
780 | }; | ||
781 | |||
782 | /* NRV10 specification */ | ||
783 | static struct snd_bebob_meter_spec nrv10_meter_spec = { | ||
784 | .num = ARRAY_SIZE(nrv10_meter_labels), | ||
785 | .labels = nrv10_meter_labels, | ||
786 | .get = &normal_meter_get | ||
787 | }; | ||
788 | struct snd_bebob_spec maudio_nrv10_spec = { | ||
789 | .clock = NULL, | ||
790 | .rate = &usual_rate_spec, | ||
791 | .meter = &nrv10_meter_spec | ||
792 | }; | ||
diff --git a/sound/firewire/bebob/bebob_midi.c b/sound/firewire/bebob/bebob_midi.c new file mode 100644 index 000000000000..63343d578df3 --- /dev/null +++ b/sound/firewire/bebob/bebob_midi.c | |||
@@ -0,0 +1,168 @@ | |||
1 | /* | ||
2 | * bebob_midi.c - a part of driver for BeBoB based devices | ||
3 | * | ||
4 | * Copyright (c) 2013-2014 Takashi Sakamoto | ||
5 | * | ||
6 | * Licensed under the terms of the GNU General Public License, version 2. | ||
7 | */ | ||
8 | |||
9 | #include "bebob.h" | ||
10 | |||
11 | static int midi_capture_open(struct snd_rawmidi_substream *substream) | ||
12 | { | ||
13 | struct snd_bebob *bebob = substream->rmidi->private_data; | ||
14 | int err; | ||
15 | |||
16 | err = snd_bebob_stream_lock_try(bebob); | ||
17 | if (err < 0) | ||
18 | goto end; | ||
19 | |||
20 | atomic_inc(&bebob->capture_substreams); | ||
21 | err = snd_bebob_stream_start_duplex(bebob, 0); | ||
22 | if (err < 0) | ||
23 | snd_bebob_stream_lock_release(bebob); | ||
24 | end: | ||
25 | return err; | ||
26 | } | ||
27 | |||
28 | static int midi_playback_open(struct snd_rawmidi_substream *substream) | ||
29 | { | ||
30 | struct snd_bebob *bebob = substream->rmidi->private_data; | ||
31 | int err; | ||
32 | |||
33 | err = snd_bebob_stream_lock_try(bebob); | ||
34 | if (err < 0) | ||
35 | goto end; | ||
36 | |||
37 | atomic_inc(&bebob->playback_substreams); | ||
38 | err = snd_bebob_stream_start_duplex(bebob, 0); | ||
39 | if (err < 0) | ||
40 | snd_bebob_stream_lock_release(bebob); | ||
41 | end: | ||
42 | return err; | ||
43 | } | ||
44 | |||
45 | static int midi_capture_close(struct snd_rawmidi_substream *substream) | ||
46 | { | ||
47 | struct snd_bebob *bebob = substream->rmidi->private_data; | ||
48 | |||
49 | atomic_dec(&bebob->capture_substreams); | ||
50 | snd_bebob_stream_stop_duplex(bebob); | ||
51 | |||
52 | snd_bebob_stream_lock_release(bebob); | ||
53 | return 0; | ||
54 | } | ||
55 | |||
56 | static int midi_playback_close(struct snd_rawmidi_substream *substream) | ||
57 | { | ||
58 | struct snd_bebob *bebob = substream->rmidi->private_data; | ||
59 | |||
60 | atomic_dec(&bebob->playback_substreams); | ||
61 | snd_bebob_stream_stop_duplex(bebob); | ||
62 | |||
63 | snd_bebob_stream_lock_release(bebob); | ||
64 | return 0; | ||
65 | } | ||
66 | |||
67 | static void midi_capture_trigger(struct snd_rawmidi_substream *substrm, int up) | ||
68 | { | ||
69 | struct snd_bebob *bebob = substrm->rmidi->private_data; | ||
70 | unsigned long flags; | ||
71 | |||
72 | spin_lock_irqsave(&bebob->lock, flags); | ||
73 | |||
74 | if (up) | ||
75 | amdtp_stream_midi_trigger(&bebob->tx_stream, | ||
76 | substrm->number, substrm); | ||
77 | else | ||
78 | amdtp_stream_midi_trigger(&bebob->tx_stream, | ||
79 | substrm->number, NULL); | ||
80 | |||
81 | spin_unlock_irqrestore(&bebob->lock, flags); | ||
82 | } | ||
83 | |||
84 | static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up) | ||
85 | { | ||
86 | struct snd_bebob *bebob = substrm->rmidi->private_data; | ||
87 | unsigned long flags; | ||
88 | |||
89 | spin_lock_irqsave(&bebob->lock, flags); | ||
90 | |||
91 | if (up) | ||
92 | amdtp_stream_midi_trigger(&bebob->rx_stream, | ||
93 | substrm->number, substrm); | ||
94 | else | ||
95 | amdtp_stream_midi_trigger(&bebob->rx_stream, | ||
96 | substrm->number, NULL); | ||
97 | |||
98 | spin_unlock_irqrestore(&bebob->lock, flags); | ||
99 | } | ||
100 | |||
101 | static struct snd_rawmidi_ops midi_capture_ops = { | ||
102 | .open = midi_capture_open, | ||
103 | .close = midi_capture_close, | ||
104 | .trigger = midi_capture_trigger, | ||
105 | }; | ||
106 | |||
107 | static struct snd_rawmidi_ops midi_playback_ops = { | ||
108 | .open = midi_playback_open, | ||
109 | .close = midi_playback_close, | ||
110 | .trigger = midi_playback_trigger, | ||
111 | }; | ||
112 | |||
113 | static void set_midi_substream_names(struct snd_bebob *bebob, | ||
114 | struct snd_rawmidi_str *str) | ||
115 | { | ||
116 | struct snd_rawmidi_substream *subs; | ||
117 | |||
118 | list_for_each_entry(subs, &str->substreams, list) { | ||
119 | snprintf(subs->name, sizeof(subs->name), | ||
120 | "%s MIDI %d", | ||
121 | bebob->card->shortname, subs->number + 1); | ||
122 | } | ||
123 | } | ||
124 | |||
125 | int snd_bebob_create_midi_devices(struct snd_bebob *bebob) | ||
126 | { | ||
127 | struct snd_rawmidi *rmidi; | ||
128 | struct snd_rawmidi_str *str; | ||
129 | int err; | ||
130 | |||
131 | /* create midi ports */ | ||
132 | err = snd_rawmidi_new(bebob->card, bebob->card->driver, 0, | ||
133 | bebob->midi_output_ports, bebob->midi_input_ports, | ||
134 | &rmidi); | ||
135 | if (err < 0) | ||
136 | return err; | ||
137 | |||
138 | snprintf(rmidi->name, sizeof(rmidi->name), | ||
139 | "%s MIDI", bebob->card->shortname); | ||
140 | rmidi->private_data = bebob; | ||
141 | |||
142 | if (bebob->midi_input_ports > 0) { | ||
143 | rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT; | ||
144 | |||
145 | snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, | ||
146 | &midi_capture_ops); | ||
147 | |||
148 | str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT]; | ||
149 | |||
150 | set_midi_substream_names(bebob, str); | ||
151 | } | ||
152 | |||
153 | if (bebob->midi_output_ports > 0) { | ||
154 | rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT; | ||
155 | |||
156 | snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, | ||
157 | &midi_playback_ops); | ||
158 | |||
159 | str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT]; | ||
160 | |||
161 | set_midi_substream_names(bebob, str); | ||
162 | } | ||
163 | |||
164 | if ((bebob->midi_output_ports > 0) && (bebob->midi_input_ports > 0)) | ||
165 | rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX; | ||
166 | |||
167 | return 0; | ||
168 | } | ||
diff --git a/sound/firewire/bebob/bebob_pcm.c b/sound/firewire/bebob/bebob_pcm.c new file mode 100644 index 000000000000..4a55561ed4ec --- /dev/null +++ b/sound/firewire/bebob/bebob_pcm.c | |||
@@ -0,0 +1,378 @@ | |||
1 | /* | ||
2 | * bebob_pcm.c - a part of driver for BeBoB based devices | ||
3 | * | ||
4 | * Copyright (c) 2013-2014 Takashi Sakamoto | ||
5 | * | ||
6 | * Licensed under the terms of the GNU General Public License, version 2. | ||
7 | */ | ||
8 | |||
9 | #include "./bebob.h" | ||
10 | |||
11 | static int | ||
12 | hw_rule_rate(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule) | ||
13 | { | ||
14 | struct snd_bebob_stream_formation *formations = rule->private; | ||
15 | struct snd_interval *r = | ||
16 | hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); | ||
17 | const struct snd_interval *c = | ||
18 | hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_CHANNELS); | ||
19 | struct snd_interval t = { | ||
20 | .min = UINT_MAX, .max = 0, .integer = 1 | ||
21 | }; | ||
22 | unsigned int i; | ||
23 | |||
24 | for (i = 0; i < SND_BEBOB_STRM_FMT_ENTRIES; i++) { | ||
25 | /* entry is invalid */ | ||
26 | if (formations[i].pcm == 0) | ||
27 | continue; | ||
28 | |||
29 | if (!snd_interval_test(c, formations[i].pcm)) | ||
30 | continue; | ||
31 | |||
32 | t.min = min(t.min, snd_bebob_rate_table[i]); | ||
33 | t.max = max(t.max, snd_bebob_rate_table[i]); | ||
34 | |||
35 | } | ||
36 | return snd_interval_refine(r, &t); | ||
37 | } | ||
38 | |||
39 | static int | ||
40 | hw_rule_channels(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule) | ||
41 | { | ||
42 | struct snd_bebob_stream_formation *formations = rule->private; | ||
43 | struct snd_interval *c = | ||
44 | hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); | ||
45 | const struct snd_interval *r = | ||
46 | hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE); | ||
47 | struct snd_interval t = { | ||
48 | .min = UINT_MAX, .max = 0, .integer = 1 | ||
49 | }; | ||
50 | |||
51 | unsigned int i; | ||
52 | |||
53 | for (i = 0; i < SND_BEBOB_STRM_FMT_ENTRIES; i++) { | ||
54 | /* entry is invalid */ | ||
55 | if (formations[i].pcm == 0) | ||
56 | continue; | ||
57 | |||
58 | if (!snd_interval_test(r, snd_bebob_rate_table[i])) | ||
59 | continue; | ||
60 | |||
61 | t.min = min(t.min, formations[i].pcm); | ||
62 | t.max = max(t.max, formations[i].pcm); | ||
63 | } | ||
64 | |||
65 | return snd_interval_refine(c, &t); | ||
66 | } | ||
67 | |||
68 | static void | ||
69 | limit_channels_and_rates(struct snd_pcm_hardware *hw, | ||
70 | struct snd_bebob_stream_formation *formations) | ||
71 | { | ||
72 | unsigned int i; | ||
73 | |||
74 | hw->channels_min = UINT_MAX; | ||
75 | hw->channels_max = 0; | ||
76 | |||
77 | hw->rate_min = UINT_MAX; | ||
78 | hw->rate_max = 0; | ||
79 | hw->rates = 0; | ||
80 | |||
81 | for (i = 0; i < SND_BEBOB_STRM_FMT_ENTRIES; i++) { | ||
82 | /* entry has no PCM channels */ | ||
83 | if (formations[i].pcm == 0) | ||
84 | continue; | ||
85 | |||
86 | hw->channels_min = min(hw->channels_min, formations[i].pcm); | ||
87 | hw->channels_max = max(hw->channels_max, formations[i].pcm); | ||
88 | |||
89 | hw->rate_min = min(hw->rate_min, snd_bebob_rate_table[i]); | ||
90 | hw->rate_max = max(hw->rate_max, snd_bebob_rate_table[i]); | ||
91 | hw->rates |= snd_pcm_rate_to_rate_bit(snd_bebob_rate_table[i]); | ||
92 | } | ||
93 | } | ||
94 | |||
95 | static void | ||
96 | limit_period_and_buffer(struct snd_pcm_hardware *hw) | ||
97 | { | ||
98 | hw->periods_min = 2; /* SNDRV_PCM_INFO_BATCH */ | ||
99 | hw->periods_max = UINT_MAX; | ||
100 | |||
101 | hw->period_bytes_min = 4 * hw->channels_max; /* bytes for a frame */ | ||
102 | |||
103 | /* Just to prevent from allocating much pages. */ | ||
104 | hw->period_bytes_max = hw->period_bytes_min * 2048; | ||
105 | hw->buffer_bytes_max = hw->period_bytes_max * hw->periods_min; | ||
106 | } | ||
107 | |||
108 | static int | ||
109 | pcm_init_hw_params(struct snd_bebob *bebob, | ||
110 | struct snd_pcm_substream *substream) | ||
111 | { | ||
112 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
113 | struct amdtp_stream *s; | ||
114 | struct snd_bebob_stream_formation *formations; | ||
115 | int err; | ||
116 | |||
117 | runtime->hw.info = SNDRV_PCM_INFO_BATCH | | ||
118 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
119 | SNDRV_PCM_INFO_INTERLEAVED | | ||
120 | SNDRV_PCM_INFO_JOINT_DUPLEX | | ||
121 | SNDRV_PCM_INFO_MMAP | | ||
122 | SNDRV_PCM_INFO_MMAP_VALID; | ||
123 | |||
124 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { | ||
125 | runtime->hw.formats = AMDTP_IN_PCM_FORMAT_BITS; | ||
126 | s = &bebob->tx_stream; | ||
127 | formations = bebob->tx_stream_formations; | ||
128 | } else { | ||
129 | runtime->hw.formats = AMDTP_OUT_PCM_FORMAT_BITS; | ||
130 | s = &bebob->rx_stream; | ||
131 | formations = bebob->rx_stream_formations; | ||
132 | } | ||
133 | |||
134 | limit_channels_and_rates(&runtime->hw, formations); | ||
135 | limit_period_and_buffer(&runtime->hw); | ||
136 | |||
137 | err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, | ||
138 | hw_rule_channels, formations, | ||
139 | SNDRV_PCM_HW_PARAM_RATE, -1); | ||
140 | if (err < 0) | ||
141 | goto end; | ||
142 | |||
143 | err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, | ||
144 | hw_rule_rate, formations, | ||
145 | SNDRV_PCM_HW_PARAM_CHANNELS, -1); | ||
146 | if (err < 0) | ||
147 | goto end; | ||
148 | |||
149 | err = amdtp_stream_add_pcm_hw_constraints(s, runtime); | ||
150 | end: | ||
151 | return err; | ||
152 | } | ||
153 | |||
154 | static int | ||
155 | pcm_open(struct snd_pcm_substream *substream) | ||
156 | { | ||
157 | struct snd_bebob *bebob = substream->private_data; | ||
158 | struct snd_bebob_rate_spec *spec = bebob->spec->rate; | ||
159 | unsigned int sampling_rate; | ||
160 | bool internal; | ||
161 | int err; | ||
162 | |||
163 | err = snd_bebob_stream_lock_try(bebob); | ||
164 | if (err < 0) | ||
165 | goto end; | ||
166 | |||
167 | err = pcm_init_hw_params(bebob, substream); | ||
168 | if (err < 0) | ||
169 | goto err_locked; | ||
170 | |||
171 | err = snd_bebob_stream_check_internal_clock(bebob, &internal); | ||
172 | if (err < 0) | ||
173 | goto err_locked; | ||
174 | |||
175 | /* | ||
176 | * When source of clock is internal or any PCM stream are running, | ||
177 | * the available sampling rate is limited at current sampling rate. | ||
178 | */ | ||
179 | if (!internal || | ||
180 | amdtp_stream_pcm_running(&bebob->tx_stream) || | ||
181 | amdtp_stream_pcm_running(&bebob->rx_stream)) { | ||
182 | err = spec->get(bebob, &sampling_rate); | ||
183 | if (err < 0) { | ||
184 | dev_err(&bebob->unit->device, | ||
185 | "fail to get sampling rate: %d\n", err); | ||
186 | goto err_locked; | ||
187 | } | ||
188 | |||
189 | substream->runtime->hw.rate_min = sampling_rate; | ||
190 | substream->runtime->hw.rate_max = sampling_rate; | ||
191 | } | ||
192 | |||
193 | snd_pcm_set_sync(substream); | ||
194 | end: | ||
195 | return err; | ||
196 | err_locked: | ||
197 | snd_bebob_stream_lock_release(bebob); | ||
198 | return err; | ||
199 | } | ||
200 | |||
201 | static int | ||
202 | pcm_close(struct snd_pcm_substream *substream) | ||
203 | { | ||
204 | struct snd_bebob *bebob = substream->private_data; | ||
205 | snd_bebob_stream_lock_release(bebob); | ||
206 | return 0; | ||
207 | } | ||
208 | |||
209 | static int | ||
210 | pcm_capture_hw_params(struct snd_pcm_substream *substream, | ||
211 | struct snd_pcm_hw_params *hw_params) | ||
212 | { | ||
213 | struct snd_bebob *bebob = substream->private_data; | ||
214 | |||
215 | if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) | ||
216 | atomic_inc(&bebob->capture_substreams); | ||
217 | amdtp_stream_set_pcm_format(&bebob->tx_stream, | ||
218 | params_format(hw_params)); | ||
219 | return snd_pcm_lib_alloc_vmalloc_buffer(substream, | ||
220 | params_buffer_bytes(hw_params)); | ||
221 | } | ||
222 | static int | ||
223 | pcm_playback_hw_params(struct snd_pcm_substream *substream, | ||
224 | struct snd_pcm_hw_params *hw_params) | ||
225 | { | ||
226 | struct snd_bebob *bebob = substream->private_data; | ||
227 | |||
228 | if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) | ||
229 | atomic_inc(&bebob->playback_substreams); | ||
230 | amdtp_stream_set_pcm_format(&bebob->rx_stream, | ||
231 | params_format(hw_params)); | ||
232 | return snd_pcm_lib_alloc_vmalloc_buffer(substream, | ||
233 | params_buffer_bytes(hw_params)); | ||
234 | } | ||
235 | |||
236 | static int | ||
237 | pcm_capture_hw_free(struct snd_pcm_substream *substream) | ||
238 | { | ||
239 | struct snd_bebob *bebob = substream->private_data; | ||
240 | |||
241 | if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) | ||
242 | atomic_dec(&bebob->capture_substreams); | ||
243 | |||
244 | snd_bebob_stream_stop_duplex(bebob); | ||
245 | |||
246 | return snd_pcm_lib_free_vmalloc_buffer(substream); | ||
247 | } | ||
248 | static int | ||
249 | pcm_playback_hw_free(struct snd_pcm_substream *substream) | ||
250 | { | ||
251 | struct snd_bebob *bebob = substream->private_data; | ||
252 | |||
253 | if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) | ||
254 | atomic_dec(&bebob->playback_substreams); | ||
255 | |||
256 | snd_bebob_stream_stop_duplex(bebob); | ||
257 | |||
258 | return snd_pcm_lib_free_vmalloc_buffer(substream); | ||
259 | } | ||
260 | |||
261 | static int | ||
262 | pcm_capture_prepare(struct snd_pcm_substream *substream) | ||
263 | { | ||
264 | struct snd_bebob *bebob = substream->private_data; | ||
265 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
266 | int err; | ||
267 | |||
268 | err = snd_bebob_stream_start_duplex(bebob, runtime->rate); | ||
269 | if (err >= 0) | ||
270 | amdtp_stream_pcm_prepare(&bebob->tx_stream); | ||
271 | |||
272 | return err; | ||
273 | } | ||
274 | static int | ||
275 | pcm_playback_prepare(struct snd_pcm_substream *substream) | ||
276 | { | ||
277 | struct snd_bebob *bebob = substream->private_data; | ||
278 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
279 | int err; | ||
280 | |||
281 | err = snd_bebob_stream_start_duplex(bebob, runtime->rate); | ||
282 | if (err >= 0) | ||
283 | amdtp_stream_pcm_prepare(&bebob->rx_stream); | ||
284 | |||
285 | return err; | ||
286 | } | ||
287 | |||
288 | static int | ||
289 | pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd) | ||
290 | { | ||
291 | struct snd_bebob *bebob = substream->private_data; | ||
292 | |||
293 | switch (cmd) { | ||
294 | case SNDRV_PCM_TRIGGER_START: | ||
295 | amdtp_stream_pcm_trigger(&bebob->tx_stream, substream); | ||
296 | break; | ||
297 | case SNDRV_PCM_TRIGGER_STOP: | ||
298 | amdtp_stream_pcm_trigger(&bebob->tx_stream, NULL); | ||
299 | break; | ||
300 | default: | ||
301 | return -EINVAL; | ||
302 | } | ||
303 | |||
304 | return 0; | ||
305 | } | ||
306 | static int | ||
307 | pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd) | ||
308 | { | ||
309 | struct snd_bebob *bebob = substream->private_data; | ||
310 | |||
311 | switch (cmd) { | ||
312 | case SNDRV_PCM_TRIGGER_START: | ||
313 | amdtp_stream_pcm_trigger(&bebob->rx_stream, substream); | ||
314 | break; | ||
315 | case SNDRV_PCM_TRIGGER_STOP: | ||
316 | amdtp_stream_pcm_trigger(&bebob->rx_stream, NULL); | ||
317 | break; | ||
318 | default: | ||
319 | return -EINVAL; | ||
320 | } | ||
321 | |||
322 | return 0; | ||
323 | } | ||
324 | |||
325 | static snd_pcm_uframes_t | ||
326 | pcm_capture_pointer(struct snd_pcm_substream *sbstrm) | ||
327 | { | ||
328 | struct snd_bebob *bebob = sbstrm->private_data; | ||
329 | return amdtp_stream_pcm_pointer(&bebob->tx_stream); | ||
330 | } | ||
331 | static snd_pcm_uframes_t | ||
332 | pcm_playback_pointer(struct snd_pcm_substream *sbstrm) | ||
333 | { | ||
334 | struct snd_bebob *bebob = sbstrm->private_data; | ||
335 | return amdtp_stream_pcm_pointer(&bebob->rx_stream); | ||
336 | } | ||
337 | |||
338 | static const struct snd_pcm_ops pcm_capture_ops = { | ||
339 | .open = pcm_open, | ||
340 | .close = pcm_close, | ||
341 | .ioctl = snd_pcm_lib_ioctl, | ||
342 | .hw_params = pcm_capture_hw_params, | ||
343 | .hw_free = pcm_capture_hw_free, | ||
344 | .prepare = pcm_capture_prepare, | ||
345 | .trigger = pcm_capture_trigger, | ||
346 | .pointer = pcm_capture_pointer, | ||
347 | .page = snd_pcm_lib_get_vmalloc_page, | ||
348 | }; | ||
349 | static const struct snd_pcm_ops pcm_playback_ops = { | ||
350 | .open = pcm_open, | ||
351 | .close = pcm_close, | ||
352 | .ioctl = snd_pcm_lib_ioctl, | ||
353 | .hw_params = pcm_playback_hw_params, | ||
354 | .hw_free = pcm_playback_hw_free, | ||
355 | .prepare = pcm_playback_prepare, | ||
356 | .trigger = pcm_playback_trigger, | ||
357 | .pointer = pcm_playback_pointer, | ||
358 | .page = snd_pcm_lib_get_vmalloc_page, | ||
359 | .mmap = snd_pcm_lib_mmap_vmalloc, | ||
360 | }; | ||
361 | |||
362 | int snd_bebob_create_pcm_devices(struct snd_bebob *bebob) | ||
363 | { | ||
364 | struct snd_pcm *pcm; | ||
365 | int err; | ||
366 | |||
367 | err = snd_pcm_new(bebob->card, bebob->card->driver, 0, 1, 1, &pcm); | ||
368 | if (err < 0) | ||
369 | goto end; | ||
370 | |||
371 | pcm->private_data = bebob; | ||
372 | snprintf(pcm->name, sizeof(pcm->name), | ||
373 | "%s PCM", bebob->card->shortname); | ||
374 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &pcm_playback_ops); | ||
375 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pcm_capture_ops); | ||
376 | end: | ||
377 | return err; | ||
378 | } | ||
diff --git a/sound/firewire/bebob/bebob_proc.c b/sound/firewire/bebob/bebob_proc.c new file mode 100644 index 000000000000..335da64506e0 --- /dev/null +++ b/sound/firewire/bebob/bebob_proc.c | |||
@@ -0,0 +1,196 @@ | |||
1 | /* | ||
2 | * bebob_proc.c - a part of driver for BeBoB based devices | ||
3 | * | ||
4 | * Copyright (c) 2013-2014 Takashi Sakamoto | ||
5 | * | ||
6 | * Licensed under the terms of the GNU General Public License, version 2. | ||
7 | */ | ||
8 | |||
9 | #include "./bebob.h" | ||
10 | |||
11 | /* contents of information register */ | ||
12 | struct hw_info { | ||
13 | u64 manufacturer; | ||
14 | u32 protocol_ver; | ||
15 | u32 bld_ver; | ||
16 | u32 guid[2]; | ||
17 | u32 model_id; | ||
18 | u32 model_rev; | ||
19 | u64 fw_date; | ||
20 | u64 fw_time; | ||
21 | u32 fw_id; | ||
22 | u32 fw_ver; | ||
23 | u32 base_addr; | ||
24 | u32 max_size; | ||
25 | u64 bld_date; | ||
26 | u64 bld_time; | ||
27 | /* may not used in product | ||
28 | u64 dbg_date; | ||
29 | u64 dbg_time; | ||
30 | u32 dbg_id; | ||
31 | u32 dbg_version; | ||
32 | */ | ||
33 | } __packed; | ||
34 | |||
35 | static void | ||
36 | proc_read_hw_info(struct snd_info_entry *entry, | ||
37 | struct snd_info_buffer *buffer) | ||
38 | { | ||
39 | struct snd_bebob *bebob = entry->private_data; | ||
40 | struct hw_info *info; | ||
41 | |||
42 | info = kzalloc(sizeof(struct hw_info), GFP_KERNEL); | ||
43 | if (info == NULL) | ||
44 | return; | ||
45 | |||
46 | if (snd_bebob_read_block(bebob->unit, 0, | ||
47 | info, sizeof(struct hw_info)) < 0) | ||
48 | goto end; | ||
49 | |||
50 | snd_iprintf(buffer, "Manufacturer:\t%.8s\n", | ||
51 | (char *)&info->manufacturer); | ||
52 | snd_iprintf(buffer, "Protocol Ver:\t%d\n", info->protocol_ver); | ||
53 | snd_iprintf(buffer, "Build Ver:\t%d\n", info->bld_ver); | ||
54 | snd_iprintf(buffer, "GUID:\t\t0x%.8X%.8X\n", | ||
55 | info->guid[0], info->guid[1]); | ||
56 | snd_iprintf(buffer, "Model ID:\t0x%02X\n", info->model_id); | ||
57 | snd_iprintf(buffer, "Model Rev:\t%d\n", info->model_rev); | ||
58 | snd_iprintf(buffer, "Firmware Date:\t%.8s\n", (char *)&info->fw_date); | ||
59 | snd_iprintf(buffer, "Firmware Time:\t%.8s\n", (char *)&info->fw_time); | ||
60 | snd_iprintf(buffer, "Firmware ID:\t0x%X\n", info->fw_id); | ||
61 | snd_iprintf(buffer, "Firmware Ver:\t%d\n", info->fw_ver); | ||
62 | snd_iprintf(buffer, "Base Addr:\t0x%X\n", info->base_addr); | ||
63 | snd_iprintf(buffer, "Max Size:\t%d\n", info->max_size); | ||
64 | snd_iprintf(buffer, "Loader Date:\t%.8s\n", (char *)&info->bld_date); | ||
65 | snd_iprintf(buffer, "Loader Time:\t%.8s\n", (char *)&info->bld_time); | ||
66 | |||
67 | end: | ||
68 | kfree(info); | ||
69 | } | ||
70 | |||
71 | static void | ||
72 | proc_read_meters(struct snd_info_entry *entry, | ||
73 | struct snd_info_buffer *buffer) | ||
74 | { | ||
75 | struct snd_bebob *bebob = entry->private_data; | ||
76 | struct snd_bebob_meter_spec *spec = bebob->spec->meter; | ||
77 | u32 *buf; | ||
78 | unsigned int i, c, channels, size; | ||
79 | |||
80 | if (spec == NULL) | ||
81 | return; | ||
82 | |||
83 | channels = spec->num * 2; | ||
84 | size = channels * sizeof(u32); | ||
85 | buf = kmalloc(size, GFP_KERNEL); | ||
86 | if (buf == NULL) | ||
87 | return; | ||
88 | |||
89 | if (spec->get(bebob, buf, size) < 0) | ||
90 | goto end; | ||
91 | |||
92 | for (i = 0, c = 1; i < channels; i++) { | ||
93 | snd_iprintf(buffer, "%s %d:\t%d\n", | ||
94 | spec->labels[i / 2], c++, buf[i]); | ||
95 | if ((i + 1 < channels - 1) && | ||
96 | (strcmp(spec->labels[i / 2], | ||
97 | spec->labels[(i + 1) / 2]) != 0)) | ||
98 | c = 1; | ||
99 | } | ||
100 | end: | ||
101 | kfree(buf); | ||
102 | } | ||
103 | |||
104 | static void | ||
105 | proc_read_formation(struct snd_info_entry *entry, | ||
106 | struct snd_info_buffer *buffer) | ||
107 | { | ||
108 | struct snd_bebob *bebob = entry->private_data; | ||
109 | struct snd_bebob_stream_formation *formation; | ||
110 | unsigned int i; | ||
111 | |||
112 | snd_iprintf(buffer, "Output Stream from device:\n"); | ||
113 | snd_iprintf(buffer, "\tRate\tPCM\tMIDI\n"); | ||
114 | formation = bebob->tx_stream_formations; | ||
115 | for (i = 0; i < SND_BEBOB_STRM_FMT_ENTRIES; i++) { | ||
116 | snd_iprintf(buffer, | ||
117 | "\t%d\t%d\t%d\n", snd_bebob_rate_table[i], | ||
118 | formation[i].pcm, formation[i].midi); | ||
119 | } | ||
120 | |||
121 | snd_iprintf(buffer, "Input Stream to device:\n"); | ||
122 | snd_iprintf(buffer, "\tRate\tPCM\tMIDI\n"); | ||
123 | formation = bebob->rx_stream_formations; | ||
124 | for (i = 0; i < SND_BEBOB_STRM_FMT_ENTRIES; i++) { | ||
125 | snd_iprintf(buffer, | ||
126 | "\t%d\t%d\t%d\n", snd_bebob_rate_table[i], | ||
127 | formation[i].pcm, formation[i].midi); | ||
128 | } | ||
129 | } | ||
130 | |||
131 | static void | ||
132 | proc_read_clock(struct snd_info_entry *entry, | ||
133 | struct snd_info_buffer *buffer) | ||
134 | { | ||
135 | struct snd_bebob *bebob = entry->private_data; | ||
136 | struct snd_bebob_rate_spec *rate_spec = bebob->spec->rate; | ||
137 | struct snd_bebob_clock_spec *clk_spec = bebob->spec->clock; | ||
138 | unsigned int rate, id; | ||
139 | bool internal; | ||
140 | |||
141 | if (rate_spec->get(bebob, &rate) >= 0) | ||
142 | snd_iprintf(buffer, "Sampling rate: %d\n", rate); | ||
143 | |||
144 | if (clk_spec) { | ||
145 | if (clk_spec->get(bebob, &id) >= 0) | ||
146 | snd_iprintf(buffer, "Clock Source: %s\n", | ||
147 | clk_spec->labels[id]); | ||
148 | } else { | ||
149 | if (snd_bebob_stream_check_internal_clock(bebob, | ||
150 | &internal) >= 0) | ||
151 | snd_iprintf(buffer, "Clock Source: %s (MSU-dest: %d)\n", | ||
152 | (internal) ? "Internal" : "External", | ||
153 | bebob->sync_input_plug); | ||
154 | } | ||
155 | } | ||
156 | |||
157 | static void | ||
158 | add_node(struct snd_bebob *bebob, struct snd_info_entry *root, const char *name, | ||
159 | void (*op)(struct snd_info_entry *e, struct snd_info_buffer *b)) | ||
160 | { | ||
161 | struct snd_info_entry *entry; | ||
162 | |||
163 | entry = snd_info_create_card_entry(bebob->card, name, root); | ||
164 | if (entry == NULL) | ||
165 | return; | ||
166 | |||
167 | snd_info_set_text_ops(entry, bebob, op); | ||
168 | if (snd_info_register(entry) < 0) | ||
169 | snd_info_free_entry(entry); | ||
170 | } | ||
171 | |||
172 | void snd_bebob_proc_init(struct snd_bebob *bebob) | ||
173 | { | ||
174 | struct snd_info_entry *root; | ||
175 | |||
176 | /* | ||
177 | * All nodes are automatically removed at snd_card_disconnect(), | ||
178 | * by following to link list. | ||
179 | */ | ||
180 | root = snd_info_create_card_entry(bebob->card, "firewire", | ||
181 | bebob->card->proc_root); | ||
182 | if (root == NULL) | ||
183 | return; | ||
184 | root->mode = S_IFDIR | S_IRUGO | S_IXUGO; | ||
185 | if (snd_info_register(root) < 0) { | ||
186 | snd_info_free_entry(root); | ||
187 | return; | ||
188 | } | ||
189 | |||
190 | add_node(bebob, root, "clock", proc_read_clock); | ||
191 | add_node(bebob, root, "firmware", proc_read_hw_info); | ||
192 | add_node(bebob, root, "formation", proc_read_formation); | ||
193 | |||
194 | if (bebob->spec->meter != NULL) | ||
195 | add_node(bebob, root, "meter", proc_read_meters); | ||
196 | } | ||
diff --git a/sound/firewire/bebob/bebob_stream.c b/sound/firewire/bebob/bebob_stream.c new file mode 100644 index 000000000000..ef4d0c9f6578 --- /dev/null +++ b/sound/firewire/bebob/bebob_stream.c | |||
@@ -0,0 +1,1021 @@ | |||
1 | /* | ||
2 | * bebob_stream.c - a part of driver for BeBoB based devices | ||
3 | * | ||
4 | * Copyright (c) 2013-2014 Takashi Sakamoto | ||
5 | * | ||
6 | * Licensed under the terms of the GNU General Public License, version 2. | ||
7 | */ | ||
8 | |||
9 | #include "./bebob.h" | ||
10 | |||
11 | #define CALLBACK_TIMEOUT 1000 | ||
12 | #define FW_ISO_RESOURCE_DELAY 1000 | ||
13 | |||
14 | /* | ||
15 | * NOTE; | ||
16 | * For BeBoB streams, Both of input and output CMP connection are important. | ||
17 | * | ||
18 | * For most devices, each CMP connection starts to transmit/receive a | ||
19 | * corresponding stream. But for a few devices, both of CMP connection needs | ||
20 | * to start transmitting stream. An example is 'M-Audio Firewire 410'. | ||
21 | */ | ||
22 | |||
23 | /* 128 is an arbitrary length but it seems to be enough */ | ||
24 | #define FORMAT_MAXIMUM_LENGTH 128 | ||
25 | |||
26 | const unsigned int snd_bebob_rate_table[SND_BEBOB_STRM_FMT_ENTRIES] = { | ||
27 | [0] = 32000, | ||
28 | [1] = 44100, | ||
29 | [2] = 48000, | ||
30 | [3] = 88200, | ||
31 | [4] = 96000, | ||
32 | [5] = 176400, | ||
33 | [6] = 192000, | ||
34 | }; | ||
35 | |||
36 | /* | ||
37 | * See: Table 51: Extended Stream Format Info ‘Sampling Frequency’ | ||
38 | * in Additional AVC commands (Nov 2003, BridgeCo) | ||
39 | */ | ||
40 | static const unsigned int bridgeco_freq_table[] = { | ||
41 | [0] = 0x02, | ||
42 | [1] = 0x03, | ||
43 | [2] = 0x04, | ||
44 | [3] = 0x0a, | ||
45 | [4] = 0x05, | ||
46 | [5] = 0x06, | ||
47 | [6] = 0x07, | ||
48 | }; | ||
49 | |||
50 | static unsigned int | ||
51 | get_formation_index(unsigned int rate) | ||
52 | { | ||
53 | unsigned int i; | ||
54 | |||
55 | for (i = 0; i < ARRAY_SIZE(snd_bebob_rate_table); i++) { | ||
56 | if (snd_bebob_rate_table[i] == rate) | ||
57 | return i; | ||
58 | } | ||
59 | return -EINVAL; | ||
60 | } | ||
61 | |||
62 | int | ||
63 | snd_bebob_stream_get_rate(struct snd_bebob *bebob, unsigned int *curr_rate) | ||
64 | { | ||
65 | unsigned int tx_rate, rx_rate, trials; | ||
66 | int err; | ||
67 | |||
68 | trials = 0; | ||
69 | do { | ||
70 | err = avc_general_get_sig_fmt(bebob->unit, &tx_rate, | ||
71 | AVC_GENERAL_PLUG_DIR_OUT, 0); | ||
72 | } while (err == -EAGAIN && ++trials < 3); | ||
73 | if (err < 0) | ||
74 | goto end; | ||
75 | |||
76 | trials = 0; | ||
77 | do { | ||
78 | err = avc_general_get_sig_fmt(bebob->unit, &rx_rate, | ||
79 | AVC_GENERAL_PLUG_DIR_IN, 0); | ||
80 | } while (err == -EAGAIN && ++trials < 3); | ||
81 | if (err < 0) | ||
82 | goto end; | ||
83 | |||
84 | *curr_rate = rx_rate; | ||
85 | if (rx_rate == tx_rate) | ||
86 | goto end; | ||
87 | |||
88 | /* synchronize receive stream rate to transmit stream rate */ | ||
89 | err = avc_general_set_sig_fmt(bebob->unit, rx_rate, | ||
90 | AVC_GENERAL_PLUG_DIR_IN, 0); | ||
91 | end: | ||
92 | return err; | ||
93 | } | ||
94 | |||
95 | int | ||
96 | snd_bebob_stream_set_rate(struct snd_bebob *bebob, unsigned int rate) | ||
97 | { | ||
98 | int err; | ||
99 | |||
100 | err = avc_general_set_sig_fmt(bebob->unit, rate, | ||
101 | AVC_GENERAL_PLUG_DIR_OUT, 0); | ||
102 | if (err < 0) | ||
103 | goto end; | ||
104 | |||
105 | err = avc_general_set_sig_fmt(bebob->unit, rate, | ||
106 | AVC_GENERAL_PLUG_DIR_IN, 0); | ||
107 | if (err < 0) | ||
108 | goto end; | ||
109 | |||
110 | /* | ||
111 | * Some devices need a bit time for transition. | ||
112 | * 300msec is got by some experiments. | ||
113 | */ | ||
114 | msleep(300); | ||
115 | end: | ||
116 | return err; | ||
117 | } | ||
118 | |||
119 | int | ||
120 | snd_bebob_stream_check_internal_clock(struct snd_bebob *bebob, bool *internal) | ||
121 | { | ||
122 | struct snd_bebob_clock_spec *clk_spec = bebob->spec->clock; | ||
123 | u8 addr[AVC_BRIDGECO_ADDR_BYTES], input[7]; | ||
124 | unsigned int id; | ||
125 | int err = 0; | ||
126 | |||
127 | *internal = false; | ||
128 | |||
129 | /* 1.The device has its own operation to switch source of clock */ | ||
130 | if (clk_spec) { | ||
131 | err = clk_spec->get(bebob, &id); | ||
132 | if (err < 0) | ||
133 | dev_err(&bebob->unit->device, | ||
134 | "fail to get clock source: %d\n", err); | ||
135 | else if (strncmp(clk_spec->labels[id], SND_BEBOB_CLOCK_INTERNAL, | ||
136 | strlen(SND_BEBOB_CLOCK_INTERNAL)) == 0) | ||
137 | *internal = true; | ||
138 | goto end; | ||
139 | } | ||
140 | |||
141 | /* | ||
142 | * 2.The device don't support to switch source of clock then assumed | ||
143 | * to use internal clock always | ||
144 | */ | ||
145 | if (bebob->sync_input_plug < 0) { | ||
146 | *internal = true; | ||
147 | goto end; | ||
148 | } | ||
149 | |||
150 | /* | ||
151 | * 3.The device supports to switch source of clock by an usual way. | ||
152 | * Let's check input for 'Music Sub Unit Sync Input' plug. | ||
153 | */ | ||
154 | avc_bridgeco_fill_msu_addr(addr, AVC_BRIDGECO_PLUG_DIR_IN, | ||
155 | bebob->sync_input_plug); | ||
156 | err = avc_bridgeco_get_plug_input(bebob->unit, addr, input); | ||
157 | if (err < 0) { | ||
158 | dev_err(&bebob->unit->device, | ||
159 | "fail to get an input for MSU in plug %d: %d\n", | ||
160 | bebob->sync_input_plug, err); | ||
161 | goto end; | ||
162 | } | ||
163 | |||
164 | /* | ||
165 | * If there are no input plugs, all of fields are 0xff. | ||
166 | * Here check the first field. This field is used for direction. | ||
167 | */ | ||
168 | if (input[0] == 0xff) { | ||
169 | *internal = true; | ||
170 | goto end; | ||
171 | } | ||
172 | |||
173 | /* | ||
174 | * If source of clock is internal CSR, Music Sub Unit Sync Input is | ||
175 | * a destination of Music Sub Unit Sync Output. | ||
176 | */ | ||
177 | *internal = ((input[0] == AVC_BRIDGECO_PLUG_DIR_OUT) && | ||
178 | (input[1] == AVC_BRIDGECO_PLUG_MODE_SUBUNIT) && | ||
179 | (input[2] == 0x0c) && | ||
180 | (input[3] == 0x00)); | ||
181 | end: | ||
182 | return err; | ||
183 | } | ||
184 | |||
185 | static unsigned int | ||
186 | map_data_channels(struct snd_bebob *bebob, struct amdtp_stream *s) | ||
187 | { | ||
188 | unsigned int sec, sections, ch, channels; | ||
189 | unsigned int pcm, midi, location; | ||
190 | unsigned int stm_pos, sec_loc, pos; | ||
191 | u8 *buf, addr[AVC_BRIDGECO_ADDR_BYTES], type; | ||
192 | enum avc_bridgeco_plug_dir dir; | ||
193 | int err; | ||
194 | |||
195 | /* | ||
196 | * The length of return value of this command cannot be expected. Here | ||
197 | * use the maximum length of FCP. | ||
198 | */ | ||
199 | buf = kzalloc(256, GFP_KERNEL); | ||
200 | if (buf == NULL) | ||
201 | return -ENOMEM; | ||
202 | |||
203 | if (s == &bebob->tx_stream) | ||
204 | dir = AVC_BRIDGECO_PLUG_DIR_OUT; | ||
205 | else | ||
206 | dir = AVC_BRIDGECO_PLUG_DIR_IN; | ||
207 | |||
208 | avc_bridgeco_fill_unit_addr(addr, dir, AVC_BRIDGECO_PLUG_UNIT_ISOC, 0); | ||
209 | err = avc_bridgeco_get_plug_ch_pos(bebob->unit, addr, buf, 256); | ||
210 | if (err < 0) { | ||
211 | dev_err(&bebob->unit->device, | ||
212 | "fail to get channel position for isoc %s plug 0: %d\n", | ||
213 | (dir == AVC_BRIDGECO_PLUG_DIR_IN) ? "in" : "out", | ||
214 | err); | ||
215 | goto end; | ||
216 | } | ||
217 | pos = 0; | ||
218 | |||
219 | /* positions in I/O buffer */ | ||
220 | pcm = 0; | ||
221 | midi = 0; | ||
222 | |||
223 | /* the number of sections in AMDTP packet */ | ||
224 | sections = buf[pos++]; | ||
225 | |||
226 | for (sec = 0; sec < sections; sec++) { | ||
227 | /* type of this section */ | ||
228 | avc_bridgeco_fill_unit_addr(addr, dir, | ||
229 | AVC_BRIDGECO_PLUG_UNIT_ISOC, 0); | ||
230 | err = avc_bridgeco_get_plug_section_type(bebob->unit, addr, | ||
231 | sec, &type); | ||
232 | if (err < 0) { | ||
233 | dev_err(&bebob->unit->device, | ||
234 | "fail to get section type for isoc %s plug 0: %d\n", | ||
235 | (dir == AVC_BRIDGECO_PLUG_DIR_IN) ? "in" : | ||
236 | "out", | ||
237 | err); | ||
238 | goto end; | ||
239 | } | ||
240 | /* NoType */ | ||
241 | if (type == 0xff) { | ||
242 | err = -ENOSYS; | ||
243 | goto end; | ||
244 | } | ||
245 | |||
246 | /* the number of channels in this section */ | ||
247 | channels = buf[pos++]; | ||
248 | |||
249 | for (ch = 0; ch < channels; ch++) { | ||
250 | /* position of this channel in AMDTP packet */ | ||
251 | stm_pos = buf[pos++] - 1; | ||
252 | /* location of this channel in this section */ | ||
253 | sec_loc = buf[pos++] - 1; | ||
254 | |||
255 | /* | ||
256 | * Basically the number of location is within the | ||
257 | * number of channels in this section. But some models | ||
258 | * of M-Audio don't follow this. Its location for MIDI | ||
259 | * is the position of MIDI channels in AMDTP packet. | ||
260 | */ | ||
261 | if (sec_loc >= channels) | ||
262 | sec_loc = ch; | ||
263 | |||
264 | switch (type) { | ||
265 | /* for MIDI conformant data channel */ | ||
266 | case 0x0a: | ||
267 | /* AMDTP_MAX_CHANNELS_FOR_MIDI is 1. */ | ||
268 | if ((midi > 0) && (stm_pos != midi)) { | ||
269 | err = -ENOSYS; | ||
270 | goto end; | ||
271 | } | ||
272 | s->midi_position = stm_pos; | ||
273 | midi = stm_pos; | ||
274 | break; | ||
275 | /* for PCM data channel */ | ||
276 | case 0x01: /* Headphone */ | ||
277 | case 0x02: /* Microphone */ | ||
278 | case 0x03: /* Line */ | ||
279 | case 0x04: /* SPDIF */ | ||
280 | case 0x05: /* ADAT */ | ||
281 | case 0x06: /* TDIF */ | ||
282 | case 0x07: /* MADI */ | ||
283 | /* for undefined/changeable signal */ | ||
284 | case 0x08: /* Analog */ | ||
285 | case 0x09: /* Digital */ | ||
286 | default: | ||
287 | location = pcm + sec_loc; | ||
288 | if (location >= AMDTP_MAX_CHANNELS_FOR_PCM) { | ||
289 | err = -ENOSYS; | ||
290 | goto end; | ||
291 | } | ||
292 | s->pcm_positions[location] = stm_pos; | ||
293 | break; | ||
294 | } | ||
295 | } | ||
296 | |||
297 | if (type != 0x0a) | ||
298 | pcm += channels; | ||
299 | else | ||
300 | midi += channels; | ||
301 | } | ||
302 | end: | ||
303 | kfree(buf); | ||
304 | return err; | ||
305 | } | ||
306 | |||
307 | static int | ||
308 | init_both_connections(struct snd_bebob *bebob) | ||
309 | { | ||
310 | int err; | ||
311 | |||
312 | err = cmp_connection_init(&bebob->in_conn, | ||
313 | bebob->unit, CMP_INPUT, 0); | ||
314 | if (err < 0) | ||
315 | goto end; | ||
316 | |||
317 | err = cmp_connection_init(&bebob->out_conn, | ||
318 | bebob->unit, CMP_OUTPUT, 0); | ||
319 | if (err < 0) | ||
320 | cmp_connection_destroy(&bebob->in_conn); | ||
321 | end: | ||
322 | return err; | ||
323 | } | ||
324 | |||
325 | static int | ||
326 | check_connection_used_by_others(struct snd_bebob *bebob, struct amdtp_stream *s) | ||
327 | { | ||
328 | struct cmp_connection *conn; | ||
329 | bool used; | ||
330 | int err; | ||
331 | |||
332 | if (s == &bebob->tx_stream) | ||
333 | conn = &bebob->out_conn; | ||
334 | else | ||
335 | conn = &bebob->in_conn; | ||
336 | |||
337 | err = cmp_connection_check_used(conn, &used); | ||
338 | if ((err >= 0) && used && !amdtp_stream_running(s)) { | ||
339 | dev_err(&bebob->unit->device, | ||
340 | "Connection established by others: %cPCR[%d]\n", | ||
341 | (conn->direction == CMP_OUTPUT) ? 'o' : 'i', | ||
342 | conn->pcr_index); | ||
343 | err = -EBUSY; | ||
344 | } | ||
345 | |||
346 | return err; | ||
347 | } | ||
348 | |||
349 | static int | ||
350 | make_both_connections(struct snd_bebob *bebob, unsigned int rate) | ||
351 | { | ||
352 | int index, pcm_channels, midi_channels, err = 0; | ||
353 | |||
354 | if (bebob->connected) | ||
355 | goto end; | ||
356 | |||
357 | /* confirm params for both streams */ | ||
358 | index = get_formation_index(rate); | ||
359 | pcm_channels = bebob->tx_stream_formations[index].pcm; | ||
360 | midi_channels = bebob->tx_stream_formations[index].midi; | ||
361 | amdtp_stream_set_parameters(&bebob->tx_stream, | ||
362 | rate, pcm_channels, midi_channels * 8); | ||
363 | pcm_channels = bebob->rx_stream_formations[index].pcm; | ||
364 | midi_channels = bebob->rx_stream_formations[index].midi; | ||
365 | amdtp_stream_set_parameters(&bebob->rx_stream, | ||
366 | rate, pcm_channels, midi_channels * 8); | ||
367 | |||
368 | /* establish connections for both streams */ | ||
369 | err = cmp_connection_establish(&bebob->out_conn, | ||
370 | amdtp_stream_get_max_payload(&bebob->tx_stream)); | ||
371 | if (err < 0) | ||
372 | goto end; | ||
373 | err = cmp_connection_establish(&bebob->in_conn, | ||
374 | amdtp_stream_get_max_payload(&bebob->rx_stream)); | ||
375 | if (err < 0) { | ||
376 | cmp_connection_break(&bebob->out_conn); | ||
377 | goto end; | ||
378 | } | ||
379 | |||
380 | bebob->connected = true; | ||
381 | end: | ||
382 | return err; | ||
383 | } | ||
384 | |||
385 | static void | ||
386 | break_both_connections(struct snd_bebob *bebob) | ||
387 | { | ||
388 | cmp_connection_break(&bebob->in_conn); | ||
389 | cmp_connection_break(&bebob->out_conn); | ||
390 | |||
391 | bebob->connected = false; | ||
392 | |||
393 | /* These models seems to be in transition state for a longer time. */ | ||
394 | if (bebob->maudio_special_quirk != NULL) | ||
395 | msleep(200); | ||
396 | } | ||
397 | |||
398 | static void | ||
399 | destroy_both_connections(struct snd_bebob *bebob) | ||
400 | { | ||
401 | break_both_connections(bebob); | ||
402 | |||
403 | cmp_connection_destroy(&bebob->in_conn); | ||
404 | cmp_connection_destroy(&bebob->out_conn); | ||
405 | } | ||
406 | |||
407 | static int | ||
408 | get_sync_mode(struct snd_bebob *bebob, enum cip_flags *sync_mode) | ||
409 | { | ||
410 | /* currently this module doesn't support SYT-Match mode */ | ||
411 | *sync_mode = CIP_SYNC_TO_DEVICE; | ||
412 | return 0; | ||
413 | } | ||
414 | |||
415 | static int | ||
416 | start_stream(struct snd_bebob *bebob, struct amdtp_stream *stream, | ||
417 | unsigned int rate) | ||
418 | { | ||
419 | struct cmp_connection *conn; | ||
420 | int err = 0; | ||
421 | |||
422 | if (stream == &bebob->rx_stream) | ||
423 | conn = &bebob->in_conn; | ||
424 | else | ||
425 | conn = &bebob->out_conn; | ||
426 | |||
427 | /* channel mapping */ | ||
428 | if (bebob->maudio_special_quirk == NULL) { | ||
429 | err = map_data_channels(bebob, stream); | ||
430 | if (err < 0) | ||
431 | goto end; | ||
432 | } | ||
433 | |||
434 | /* start amdtp stream */ | ||
435 | err = amdtp_stream_start(stream, | ||
436 | conn->resources.channel, | ||
437 | conn->speed); | ||
438 | end: | ||
439 | return err; | ||
440 | } | ||
441 | |||
442 | int snd_bebob_stream_init_duplex(struct snd_bebob *bebob) | ||
443 | { | ||
444 | int err; | ||
445 | |||
446 | err = init_both_connections(bebob); | ||
447 | if (err < 0) | ||
448 | goto end; | ||
449 | |||
450 | err = amdtp_stream_init(&bebob->tx_stream, bebob->unit, | ||
451 | AMDTP_IN_STREAM, CIP_BLOCKING); | ||
452 | if (err < 0) { | ||
453 | amdtp_stream_destroy(&bebob->tx_stream); | ||
454 | destroy_both_connections(bebob); | ||
455 | goto end; | ||
456 | } | ||
457 | /* See comments in next function */ | ||
458 | init_completion(&bebob->bus_reset); | ||
459 | bebob->tx_stream.flags |= CIP_SKIP_INIT_DBC_CHECK; | ||
460 | /* | ||
461 | * At high sampling rate, M-Audio special firmware transmits empty | ||
462 | * packet with the value of dbc incremented by 8 but the others are | ||
463 | * valid to IEC 61883-1. | ||
464 | */ | ||
465 | if (bebob->maudio_special_quirk) | ||
466 | bebob->tx_stream.flags |= CIP_EMPTY_HAS_WRONG_DBC; | ||
467 | |||
468 | err = amdtp_stream_init(&bebob->rx_stream, bebob->unit, | ||
469 | AMDTP_OUT_STREAM, CIP_BLOCKING); | ||
470 | if (err < 0) { | ||
471 | amdtp_stream_destroy(&bebob->tx_stream); | ||
472 | amdtp_stream_destroy(&bebob->rx_stream); | ||
473 | destroy_both_connections(bebob); | ||
474 | } | ||
475 | /* | ||
476 | * The firmware for these devices ignore MIDI messages in more than | ||
477 | * first 8 data blocks of an received AMDTP packet. | ||
478 | */ | ||
479 | if (bebob->spec == &maudio_fw410_spec || | ||
480 | bebob->spec == &maudio_special_spec) | ||
481 | bebob->rx_stream.rx_blocks_for_midi = 8; | ||
482 | end: | ||
483 | return err; | ||
484 | } | ||
485 | |||
486 | int snd_bebob_stream_start_duplex(struct snd_bebob *bebob, unsigned int rate) | ||
487 | { | ||
488 | struct snd_bebob_rate_spec *rate_spec = bebob->spec->rate; | ||
489 | struct amdtp_stream *master, *slave; | ||
490 | atomic_t *slave_substreams; | ||
491 | enum cip_flags sync_mode; | ||
492 | unsigned int curr_rate; | ||
493 | bool updated = false; | ||
494 | int err = 0; | ||
495 | |||
496 | /* | ||
497 | * Normal BeBoB firmware has a quirk at bus reset to transmits packets | ||
498 | * with discontinuous value in dbc field. | ||
499 | * | ||
500 | * This 'struct completion' is used to call .update() at first to update | ||
501 | * connections/streams. Next following codes handle streaming error. | ||
502 | */ | ||
503 | if (amdtp_streaming_error(&bebob->tx_stream)) { | ||
504 | if (completion_done(&bebob->bus_reset)) | ||
505 | reinit_completion(&bebob->bus_reset); | ||
506 | |||
507 | updated = (wait_for_completion_interruptible_timeout( | ||
508 | &bebob->bus_reset, | ||
509 | msecs_to_jiffies(FW_ISO_RESOURCE_DELAY)) > 0); | ||
510 | } | ||
511 | |||
512 | mutex_lock(&bebob->mutex); | ||
513 | |||
514 | /* Need no substreams */ | ||
515 | if (atomic_read(&bebob->playback_substreams) == 0 && | ||
516 | atomic_read(&bebob->capture_substreams) == 0) | ||
517 | goto end; | ||
518 | |||
519 | err = get_sync_mode(bebob, &sync_mode); | ||
520 | if (err < 0) | ||
521 | goto end; | ||
522 | if (sync_mode == CIP_SYNC_TO_DEVICE) { | ||
523 | master = &bebob->tx_stream; | ||
524 | slave = &bebob->rx_stream; | ||
525 | slave_substreams = &bebob->playback_substreams; | ||
526 | } else { | ||
527 | master = &bebob->rx_stream; | ||
528 | slave = &bebob->tx_stream; | ||
529 | slave_substreams = &bebob->capture_substreams; | ||
530 | } | ||
531 | |||
532 | /* | ||
533 | * Considering JACK/FFADO streaming: | ||
534 | * TODO: This can be removed hwdep functionality becomes popular. | ||
535 | */ | ||
536 | err = check_connection_used_by_others(bebob, master); | ||
537 | if (err < 0) | ||
538 | goto end; | ||
539 | |||
540 | /* | ||
541 | * packet queueing error or detecting discontinuity | ||
542 | * | ||
543 | * At bus reset, connections should not be broken here. So streams need | ||
544 | * to be re-started. This is a reason to use SKIP_INIT_DBC_CHECK flag. | ||
545 | */ | ||
546 | if (amdtp_streaming_error(master)) | ||
547 | amdtp_stream_stop(master); | ||
548 | if (amdtp_streaming_error(slave)) | ||
549 | amdtp_stream_stop(slave); | ||
550 | if (!updated && | ||
551 | !amdtp_stream_running(master) && !amdtp_stream_running(slave)) | ||
552 | break_both_connections(bebob); | ||
553 | |||
554 | /* stop streams if rate is different */ | ||
555 | err = rate_spec->get(bebob, &curr_rate); | ||
556 | if (err < 0) { | ||
557 | dev_err(&bebob->unit->device, | ||
558 | "fail to get sampling rate: %d\n", err); | ||
559 | goto end; | ||
560 | } | ||
561 | if (rate == 0) | ||
562 | rate = curr_rate; | ||
563 | if (rate != curr_rate) { | ||
564 | amdtp_stream_stop(master); | ||
565 | amdtp_stream_stop(slave); | ||
566 | break_both_connections(bebob); | ||
567 | } | ||
568 | |||
569 | /* master should be always running */ | ||
570 | if (!amdtp_stream_running(master)) { | ||
571 | amdtp_stream_set_sync(sync_mode, master, slave); | ||
572 | bebob->master = master; | ||
573 | |||
574 | /* | ||
575 | * NOTE: | ||
576 | * If establishing connections at first, Yamaha GO46 | ||
577 | * (and maybe Terratec X24) don't generate sound. | ||
578 | * | ||
579 | * For firmware customized by M-Audio, refer to next NOTE. | ||
580 | */ | ||
581 | if (bebob->maudio_special_quirk == NULL) { | ||
582 | err = rate_spec->set(bebob, rate); | ||
583 | if (err < 0) { | ||
584 | dev_err(&bebob->unit->device, | ||
585 | "fail to set sampling rate: %d\n", | ||
586 | err); | ||
587 | goto end; | ||
588 | } | ||
589 | } | ||
590 | |||
591 | err = make_both_connections(bebob, rate); | ||
592 | if (err < 0) | ||
593 | goto end; | ||
594 | |||
595 | err = start_stream(bebob, master, rate); | ||
596 | if (err < 0) { | ||
597 | dev_err(&bebob->unit->device, | ||
598 | "fail to run AMDTP master stream:%d\n", err); | ||
599 | break_both_connections(bebob); | ||
600 | goto end; | ||
601 | } | ||
602 | |||
603 | /* | ||
604 | * NOTE: | ||
605 | * The firmware customized by M-Audio uses these commands to | ||
606 | * start transmitting stream. This is not usual way. | ||
607 | */ | ||
608 | if (bebob->maudio_special_quirk != NULL) { | ||
609 | err = rate_spec->set(bebob, rate); | ||
610 | if (err < 0) { | ||
611 | dev_err(&bebob->unit->device, | ||
612 | "fail to ensure sampling rate: %d\n", | ||
613 | err); | ||
614 | amdtp_stream_stop(master); | ||
615 | break_both_connections(bebob); | ||
616 | goto end; | ||
617 | } | ||
618 | } | ||
619 | |||
620 | /* wait first callback */ | ||
621 | if (!amdtp_stream_wait_callback(master, CALLBACK_TIMEOUT)) { | ||
622 | amdtp_stream_stop(master); | ||
623 | break_both_connections(bebob); | ||
624 | err = -ETIMEDOUT; | ||
625 | goto end; | ||
626 | } | ||
627 | } | ||
628 | |||
629 | /* start slave if needed */ | ||
630 | if (atomic_read(slave_substreams) > 0 && !amdtp_stream_running(slave)) { | ||
631 | err = start_stream(bebob, slave, rate); | ||
632 | if (err < 0) { | ||
633 | dev_err(&bebob->unit->device, | ||
634 | "fail to run AMDTP slave stream:%d\n", err); | ||
635 | amdtp_stream_stop(master); | ||
636 | break_both_connections(bebob); | ||
637 | goto end; | ||
638 | } | ||
639 | |||
640 | /* wait first callback */ | ||
641 | if (!amdtp_stream_wait_callback(slave, CALLBACK_TIMEOUT)) { | ||
642 | amdtp_stream_stop(slave); | ||
643 | amdtp_stream_stop(master); | ||
644 | break_both_connections(bebob); | ||
645 | err = -ETIMEDOUT; | ||
646 | } | ||
647 | } | ||
648 | end: | ||
649 | mutex_unlock(&bebob->mutex); | ||
650 | return err; | ||
651 | } | ||
652 | |||
653 | void snd_bebob_stream_stop_duplex(struct snd_bebob *bebob) | ||
654 | { | ||
655 | struct amdtp_stream *master, *slave; | ||
656 | atomic_t *master_substreams, *slave_substreams; | ||
657 | |||
658 | if (bebob->master == &bebob->rx_stream) { | ||
659 | slave = &bebob->tx_stream; | ||
660 | master = &bebob->rx_stream; | ||
661 | slave_substreams = &bebob->capture_substreams; | ||
662 | master_substreams = &bebob->playback_substreams; | ||
663 | } else { | ||
664 | slave = &bebob->rx_stream; | ||
665 | master = &bebob->tx_stream; | ||
666 | slave_substreams = &bebob->playback_substreams; | ||
667 | master_substreams = &bebob->capture_substreams; | ||
668 | } | ||
669 | |||
670 | mutex_lock(&bebob->mutex); | ||
671 | |||
672 | if (atomic_read(slave_substreams) == 0) { | ||
673 | amdtp_stream_pcm_abort(slave); | ||
674 | amdtp_stream_stop(slave); | ||
675 | |||
676 | if (atomic_read(master_substreams) == 0) { | ||
677 | amdtp_stream_pcm_abort(master); | ||
678 | amdtp_stream_stop(master); | ||
679 | break_both_connections(bebob); | ||
680 | } | ||
681 | } | ||
682 | |||
683 | mutex_unlock(&bebob->mutex); | ||
684 | } | ||
685 | |||
686 | void snd_bebob_stream_update_duplex(struct snd_bebob *bebob) | ||
687 | { | ||
688 | /* vs. XRUN recovery due to discontinuity at bus reset */ | ||
689 | mutex_lock(&bebob->mutex); | ||
690 | |||
691 | if ((cmp_connection_update(&bebob->in_conn) < 0) || | ||
692 | (cmp_connection_update(&bebob->out_conn) < 0)) { | ||
693 | amdtp_stream_pcm_abort(&bebob->rx_stream); | ||
694 | amdtp_stream_pcm_abort(&bebob->tx_stream); | ||
695 | amdtp_stream_stop(&bebob->rx_stream); | ||
696 | amdtp_stream_stop(&bebob->tx_stream); | ||
697 | break_both_connections(bebob); | ||
698 | } else { | ||
699 | amdtp_stream_update(&bebob->rx_stream); | ||
700 | amdtp_stream_update(&bebob->tx_stream); | ||
701 | } | ||
702 | |||
703 | /* wake up stream_start_duplex() */ | ||
704 | if (!completion_done(&bebob->bus_reset)) | ||
705 | complete_all(&bebob->bus_reset); | ||
706 | |||
707 | mutex_unlock(&bebob->mutex); | ||
708 | } | ||
709 | |||
710 | void snd_bebob_stream_destroy_duplex(struct snd_bebob *bebob) | ||
711 | { | ||
712 | mutex_lock(&bebob->mutex); | ||
713 | |||
714 | amdtp_stream_pcm_abort(&bebob->rx_stream); | ||
715 | amdtp_stream_pcm_abort(&bebob->tx_stream); | ||
716 | |||
717 | amdtp_stream_stop(&bebob->rx_stream); | ||
718 | amdtp_stream_stop(&bebob->tx_stream); | ||
719 | |||
720 | amdtp_stream_destroy(&bebob->rx_stream); | ||
721 | amdtp_stream_destroy(&bebob->tx_stream); | ||
722 | |||
723 | destroy_both_connections(bebob); | ||
724 | |||
725 | mutex_unlock(&bebob->mutex); | ||
726 | } | ||
727 | |||
728 | /* | ||
729 | * See: Table 50: Extended Stream Format Info Format Hierarchy Level 2’ | ||
730 | * in Additional AVC commands (Nov 2003, BridgeCo) | ||
731 | * Also 'Clause 12 AM824 sequence adaption layers' in IEC 61883-6:2005 | ||
732 | */ | ||
733 | static int | ||
734 | parse_stream_formation(u8 *buf, unsigned int len, | ||
735 | struct snd_bebob_stream_formation *formation) | ||
736 | { | ||
737 | unsigned int i, e, channels, format; | ||
738 | |||
739 | /* | ||
740 | * this module can support a hierarchy combination that: | ||
741 | * Root: Audio and Music (0x90) | ||
742 | * Level 1: AM824 Compound (0x40) | ||
743 | */ | ||
744 | if ((buf[0] != 0x90) || (buf[1] != 0x40)) | ||
745 | return -ENOSYS; | ||
746 | |||
747 | /* check sampling rate */ | ||
748 | for (i = 0; i < ARRAY_SIZE(bridgeco_freq_table); i++) { | ||
749 | if (buf[2] == bridgeco_freq_table[i]) | ||
750 | break; | ||
751 | } | ||
752 | if (i == ARRAY_SIZE(bridgeco_freq_table)) | ||
753 | return -ENOSYS; | ||
754 | |||
755 | /* Avoid double count by different entries for the same rate. */ | ||
756 | memset(&formation[i], 0, sizeof(struct snd_bebob_stream_formation)); | ||
757 | |||
758 | for (e = 0; e < buf[4]; e++) { | ||
759 | channels = buf[5 + e * 2]; | ||
760 | format = buf[6 + e * 2]; | ||
761 | |||
762 | switch (format) { | ||
763 | /* IEC 60958 Conformant, currently handled as MBLA */ | ||
764 | case 0x00: | ||
765 | /* Multi bit linear audio */ | ||
766 | case 0x06: /* Raw */ | ||
767 | formation[i].pcm += channels; | ||
768 | break; | ||
769 | /* MIDI Conformant */ | ||
770 | case 0x0d: | ||
771 | formation[i].midi += channels; | ||
772 | break; | ||
773 | /* IEC 61937-3 to 7 */ | ||
774 | case 0x01: | ||
775 | case 0x02: | ||
776 | case 0x03: | ||
777 | case 0x04: | ||
778 | case 0x05: | ||
779 | /* Multi bit linear audio */ | ||
780 | case 0x07: /* DVD-Audio */ | ||
781 | case 0x0c: /* High Precision */ | ||
782 | /* One Bit Audio */ | ||
783 | case 0x08: /* (Plain) Raw */ | ||
784 | case 0x09: /* (Plain) SACD */ | ||
785 | case 0x0a: /* (Encoded) Raw */ | ||
786 | case 0x0b: /* (Encoded) SACD */ | ||
787 | /* Synchronization Stream (Stereo Raw audio) */ | ||
788 | case 0x40: | ||
789 | /* Don't care */ | ||
790 | case 0xff: | ||
791 | default: | ||
792 | return -ENOSYS; /* not supported */ | ||
793 | } | ||
794 | } | ||
795 | |||
796 | if (formation[i].pcm > AMDTP_MAX_CHANNELS_FOR_PCM || | ||
797 | formation[i].midi > AMDTP_MAX_CHANNELS_FOR_MIDI) | ||
798 | return -ENOSYS; | ||
799 | |||
800 | return 0; | ||
801 | } | ||
802 | |||
803 | static int | ||
804 | fill_stream_formations(struct snd_bebob *bebob, enum avc_bridgeco_plug_dir dir, | ||
805 | unsigned short pid) | ||
806 | { | ||
807 | u8 *buf; | ||
808 | struct snd_bebob_stream_formation *formations; | ||
809 | unsigned int len, eid; | ||
810 | u8 addr[AVC_BRIDGECO_ADDR_BYTES]; | ||
811 | int err; | ||
812 | |||
813 | buf = kmalloc(FORMAT_MAXIMUM_LENGTH, GFP_KERNEL); | ||
814 | if (buf == NULL) | ||
815 | return -ENOMEM; | ||
816 | |||
817 | if (dir == AVC_BRIDGECO_PLUG_DIR_IN) | ||
818 | formations = bebob->rx_stream_formations; | ||
819 | else | ||
820 | formations = bebob->tx_stream_formations; | ||
821 | |||
822 | for (eid = 0; eid < SND_BEBOB_STRM_FMT_ENTRIES; eid++) { | ||
823 | len = FORMAT_MAXIMUM_LENGTH; | ||
824 | avc_bridgeco_fill_unit_addr(addr, dir, | ||
825 | AVC_BRIDGECO_PLUG_UNIT_ISOC, pid); | ||
826 | err = avc_bridgeco_get_plug_strm_fmt(bebob->unit, addr, buf, | ||
827 | &len, eid); | ||
828 | /* No entries remained. */ | ||
829 | if (err == -EINVAL && eid > 0) { | ||
830 | err = 0; | ||
831 | break; | ||
832 | } else if (err < 0) { | ||
833 | dev_err(&bebob->unit->device, | ||
834 | "fail to get stream format %d for isoc %s plug %d:%d\n", | ||
835 | eid, | ||
836 | (dir == AVC_BRIDGECO_PLUG_DIR_IN) ? "in" : | ||
837 | "out", | ||
838 | pid, err); | ||
839 | break; | ||
840 | } | ||
841 | |||
842 | err = parse_stream_formation(buf, len, formations); | ||
843 | if (err < 0) | ||
844 | break; | ||
845 | } | ||
846 | |||
847 | kfree(buf); | ||
848 | return err; | ||
849 | } | ||
850 | |||
851 | static int | ||
852 | seek_msu_sync_input_plug(struct snd_bebob *bebob) | ||
853 | { | ||
854 | u8 plugs[AVC_PLUG_INFO_BUF_BYTES], addr[AVC_BRIDGECO_ADDR_BYTES]; | ||
855 | unsigned int i; | ||
856 | enum avc_bridgeco_plug_type type; | ||
857 | int err; | ||
858 | |||
859 | /* Get the number of Music Sub Unit for both direction. */ | ||
860 | err = avc_general_get_plug_info(bebob->unit, 0x0c, 0x00, 0x00, plugs); | ||
861 | if (err < 0) { | ||
862 | dev_err(&bebob->unit->device, | ||
863 | "fail to get info for MSU in/out plugs: %d\n", | ||
864 | err); | ||
865 | goto end; | ||
866 | } | ||
867 | |||
868 | /* seek destination plugs for 'MSU sync input' */ | ||
869 | bebob->sync_input_plug = -1; | ||
870 | for (i = 0; i < plugs[0]; i++) { | ||
871 | avc_bridgeco_fill_msu_addr(addr, AVC_BRIDGECO_PLUG_DIR_IN, i); | ||
872 | err = avc_bridgeco_get_plug_type(bebob->unit, addr, &type); | ||
873 | if (err < 0) { | ||
874 | dev_err(&bebob->unit->device, | ||
875 | "fail to get type for MSU in plug %d: %d\n", | ||
876 | i, err); | ||
877 | goto end; | ||
878 | } | ||
879 | |||
880 | if (type == AVC_BRIDGECO_PLUG_TYPE_SYNC) { | ||
881 | bebob->sync_input_plug = i; | ||
882 | break; | ||
883 | } | ||
884 | } | ||
885 | end: | ||
886 | return err; | ||
887 | } | ||
888 | |||
889 | int snd_bebob_stream_discover(struct snd_bebob *bebob) | ||
890 | { | ||
891 | struct snd_bebob_clock_spec *clk_spec = bebob->spec->clock; | ||
892 | u8 plugs[AVC_PLUG_INFO_BUF_BYTES], addr[AVC_BRIDGECO_ADDR_BYTES]; | ||
893 | enum avc_bridgeco_plug_type type; | ||
894 | unsigned int i; | ||
895 | int err; | ||
896 | |||
897 | /* the number of plugs for isoc in/out, ext in/out */ | ||
898 | err = avc_general_get_plug_info(bebob->unit, 0x1f, 0x07, 0x00, plugs); | ||
899 | if (err < 0) { | ||
900 | dev_err(&bebob->unit->device, | ||
901 | "fail to get info for isoc/external in/out plugs: %d\n", | ||
902 | err); | ||
903 | goto end; | ||
904 | } | ||
905 | |||
906 | /* | ||
907 | * This module supports at least one isoc input plug and one isoc | ||
908 | * output plug. | ||
909 | */ | ||
910 | if ((plugs[0] == 0) || (plugs[1] == 0)) { | ||
911 | err = -ENOSYS; | ||
912 | goto end; | ||
913 | } | ||
914 | |||
915 | avc_bridgeco_fill_unit_addr(addr, AVC_BRIDGECO_PLUG_DIR_IN, | ||
916 | AVC_BRIDGECO_PLUG_UNIT_ISOC, 0); | ||
917 | err = avc_bridgeco_get_plug_type(bebob->unit, addr, &type); | ||
918 | if (err < 0) { | ||
919 | dev_err(&bebob->unit->device, | ||
920 | "fail to get type for isoc in plug 0: %d\n", err); | ||
921 | goto end; | ||
922 | } else if (type != AVC_BRIDGECO_PLUG_TYPE_ISOC) { | ||
923 | err = -ENOSYS; | ||
924 | goto end; | ||
925 | } | ||
926 | err = fill_stream_formations(bebob, AVC_BRIDGECO_PLUG_DIR_IN, 0); | ||
927 | if (err < 0) | ||
928 | goto end; | ||
929 | |||
930 | avc_bridgeco_fill_unit_addr(addr, AVC_BRIDGECO_PLUG_DIR_OUT, | ||
931 | AVC_BRIDGECO_PLUG_UNIT_ISOC, 0); | ||
932 | err = avc_bridgeco_get_plug_type(bebob->unit, addr, &type); | ||
933 | if (err < 0) { | ||
934 | dev_err(&bebob->unit->device, | ||
935 | "fail to get type for isoc out plug 0: %d\n", err); | ||
936 | goto end; | ||
937 | } else if (type != AVC_BRIDGECO_PLUG_TYPE_ISOC) { | ||
938 | err = -ENOSYS; | ||
939 | goto end; | ||
940 | } | ||
941 | err = fill_stream_formations(bebob, AVC_BRIDGECO_PLUG_DIR_OUT, 0); | ||
942 | if (err < 0) | ||
943 | goto end; | ||
944 | |||
945 | /* count external input plugs for MIDI */ | ||
946 | bebob->midi_input_ports = 0; | ||
947 | for (i = 0; i < plugs[2]; i++) { | ||
948 | avc_bridgeco_fill_unit_addr(addr, AVC_BRIDGECO_PLUG_DIR_IN, | ||
949 | AVC_BRIDGECO_PLUG_UNIT_EXT, i); | ||
950 | err = avc_bridgeco_get_plug_type(bebob->unit, addr, &type); | ||
951 | if (err < 0) { | ||
952 | dev_err(&bebob->unit->device, | ||
953 | "fail to get type for external in plug %d: %d\n", | ||
954 | i, err); | ||
955 | goto end; | ||
956 | } else if (type == AVC_BRIDGECO_PLUG_TYPE_MIDI) { | ||
957 | bebob->midi_input_ports++; | ||
958 | } | ||
959 | } | ||
960 | |||
961 | /* count external output plugs for MIDI */ | ||
962 | bebob->midi_output_ports = 0; | ||
963 | for (i = 0; i < plugs[3]; i++) { | ||
964 | avc_bridgeco_fill_unit_addr(addr, AVC_BRIDGECO_PLUG_DIR_OUT, | ||
965 | AVC_BRIDGECO_PLUG_UNIT_EXT, i); | ||
966 | err = avc_bridgeco_get_plug_type(bebob->unit, addr, &type); | ||
967 | if (err < 0) { | ||
968 | dev_err(&bebob->unit->device, | ||
969 | "fail to get type for external out plug %d: %d\n", | ||
970 | i, err); | ||
971 | goto end; | ||
972 | } else if (type == AVC_BRIDGECO_PLUG_TYPE_MIDI) { | ||
973 | bebob->midi_output_ports++; | ||
974 | } | ||
975 | } | ||
976 | |||
977 | /* for check source of clock later */ | ||
978 | if (!clk_spec) | ||
979 | err = seek_msu_sync_input_plug(bebob); | ||
980 | end: | ||
981 | return err; | ||
982 | } | ||
983 | |||
984 | void snd_bebob_stream_lock_changed(struct snd_bebob *bebob) | ||
985 | { | ||
986 | bebob->dev_lock_changed = true; | ||
987 | wake_up(&bebob->hwdep_wait); | ||
988 | } | ||
989 | |||
990 | int snd_bebob_stream_lock_try(struct snd_bebob *bebob) | ||
991 | { | ||
992 | int err; | ||
993 | |||
994 | spin_lock_irq(&bebob->lock); | ||
995 | |||
996 | /* user land lock this */ | ||
997 | if (bebob->dev_lock_count < 0) { | ||
998 | err = -EBUSY; | ||
999 | goto end; | ||
1000 | } | ||
1001 | |||
1002 | /* this is the first time */ | ||
1003 | if (bebob->dev_lock_count++ == 0) | ||
1004 | snd_bebob_stream_lock_changed(bebob); | ||
1005 | err = 0; | ||
1006 | end: | ||
1007 | spin_unlock_irq(&bebob->lock); | ||
1008 | return err; | ||
1009 | } | ||
1010 | |||
1011 | void snd_bebob_stream_lock_release(struct snd_bebob *bebob) | ||
1012 | { | ||
1013 | spin_lock_irq(&bebob->lock); | ||
1014 | |||
1015 | if (WARN_ON(bebob->dev_lock_count <= 0)) | ||
1016 | goto end; | ||
1017 | if (--bebob->dev_lock_count == 0) | ||
1018 | snd_bebob_stream_lock_changed(bebob); | ||
1019 | end: | ||
1020 | spin_unlock_irq(&bebob->lock); | ||
1021 | } | ||
diff --git a/sound/firewire/bebob/bebob_terratec.c b/sound/firewire/bebob/bebob_terratec.c new file mode 100644 index 000000000000..eef8ea7d9b97 --- /dev/null +++ b/sound/firewire/bebob/bebob_terratec.c | |||
@@ -0,0 +1,68 @@ | |||
1 | /* | ||
2 | * bebob_terratec.c - a part of driver for BeBoB based devices | ||
3 | * | ||
4 | * Copyright (c) 2013-2014 Takashi Sakamoto | ||
5 | * | ||
6 | * Licensed under the terms of the GNU General Public License, version 2. | ||
7 | */ | ||
8 | |||
9 | #include "./bebob.h" | ||
10 | |||
11 | static char *const phase88_rack_clk_src_labels[] = { | ||
12 | SND_BEBOB_CLOCK_INTERNAL, "Digital In", "Word Clock" | ||
13 | }; | ||
14 | static int | ||
15 | phase88_rack_clk_src_get(struct snd_bebob *bebob, unsigned int *id) | ||
16 | { | ||
17 | unsigned int enable_ext, enable_word; | ||
18 | int err; | ||
19 | |||
20 | err = avc_audio_get_selector(bebob->unit, 0, 0, &enable_ext); | ||
21 | if (err < 0) | ||
22 | goto end; | ||
23 | err = avc_audio_get_selector(bebob->unit, 0, 0, &enable_word); | ||
24 | if (err < 0) | ||
25 | goto end; | ||
26 | |||
27 | *id = (enable_ext & 0x01) | ((enable_word & 0x01) << 1); | ||
28 | end: | ||
29 | return err; | ||
30 | } | ||
31 | |||
32 | static char *const phase24_series_clk_src_labels[] = { | ||
33 | SND_BEBOB_CLOCK_INTERNAL, "Digital In" | ||
34 | }; | ||
35 | static int | ||
36 | phase24_series_clk_src_get(struct snd_bebob *bebob, unsigned int *id) | ||
37 | { | ||
38 | return avc_audio_get_selector(bebob->unit, 0, 4, id); | ||
39 | } | ||
40 | |||
41 | static struct snd_bebob_rate_spec phase_series_rate_spec = { | ||
42 | .get = &snd_bebob_stream_get_rate, | ||
43 | .set = &snd_bebob_stream_set_rate, | ||
44 | }; | ||
45 | |||
46 | /* PHASE 88 Rack FW */ | ||
47 | static struct snd_bebob_clock_spec phase88_rack_clk = { | ||
48 | .num = ARRAY_SIZE(phase88_rack_clk_src_labels), | ||
49 | .labels = phase88_rack_clk_src_labels, | ||
50 | .get = &phase88_rack_clk_src_get, | ||
51 | }; | ||
52 | struct snd_bebob_spec phase88_rack_spec = { | ||
53 | .clock = &phase88_rack_clk, | ||
54 | .rate = &phase_series_rate_spec, | ||
55 | .meter = NULL | ||
56 | }; | ||
57 | |||
58 | /* 'PHASE 24 FW' and 'PHASE X24 FW' */ | ||
59 | static struct snd_bebob_clock_spec phase24_series_clk = { | ||
60 | .num = ARRAY_SIZE(phase24_series_clk_src_labels), | ||
61 | .labels = phase24_series_clk_src_labels, | ||
62 | .get = &phase24_series_clk_src_get, | ||
63 | }; | ||
64 | struct snd_bebob_spec phase24_series_spec = { | ||
65 | .clock = &phase24_series_clk, | ||
66 | .rate = &phase_series_rate_spec, | ||
67 | .meter = NULL | ||
68 | }; | ||
diff --git a/sound/firewire/bebob/bebob_yamaha.c b/sound/firewire/bebob/bebob_yamaha.c new file mode 100644 index 000000000000..9b7e798180ff --- /dev/null +++ b/sound/firewire/bebob/bebob_yamaha.c | |||
@@ -0,0 +1,50 @@ | |||
1 | /* | ||
2 | * bebob_yamaha.c - a part of driver for BeBoB based devices | ||
3 | * | ||
4 | * Copyright (c) 2013-2014 Takashi Sakamoto | ||
5 | * | ||
6 | * Licensed under the terms of the GNU General Public License, version 2. | ||
7 | */ | ||
8 | |||
9 | #include "./bebob.h" | ||
10 | |||
11 | /* | ||
12 | * NOTE: | ||
13 | * Yamaha GO44 is not designed to be used as stand-alone mixer. So any streams | ||
14 | * must be accompanied. If changing the state, a LED on the device starts to | ||
15 | * blink and its sync status is false. In this state, the device sounds nothing | ||
16 | * even if streaming. To start streaming at the current sampling rate is only | ||
17 | * way to revocer this state. GO46 is better for stand-alone mixer. | ||
18 | * | ||
19 | * Both of them have a capability to change its sampling rate up to 192.0kHz. | ||
20 | * At 192.0kHz, the device reports 4 PCM-in, 1 MIDI-in, 6 PCM-out, 1 MIDI-out. | ||
21 | * But Yamaha's driver reduce 2 PCM-in, 1 MIDI-in, 2 PCM-out, 1 MIDI-out to use | ||
22 | * 'Extended Stream Format Information Command - Single Request' in 'Additional | ||
23 | * AVC commands' defined by BridgeCo. | ||
24 | * This ALSA driver don't do this because a bit tiresome. Then isochronous | ||
25 | * streaming with many asynchronous transactions brings sounds with noises. | ||
26 | * Unfortunately current 'ffado-mixer' generated many asynchronous transaction | ||
27 | * to observe device's state, mainly check cmp connection and signal format. I | ||
28 | * reccomend users to close ffado-mixer at 192.0kHz if mixer is needless. | ||
29 | */ | ||
30 | |||
31 | static char *const clk_src_labels[] = {SND_BEBOB_CLOCK_INTERNAL, "SPDIF"}; | ||
32 | static int | ||
33 | clk_src_get(struct snd_bebob *bebob, unsigned int *id) | ||
34 | { | ||
35 | return avc_audio_get_selector(bebob->unit, 0, 4, id); | ||
36 | } | ||
37 | static struct snd_bebob_clock_spec clock_spec = { | ||
38 | .num = ARRAY_SIZE(clk_src_labels), | ||
39 | .labels = clk_src_labels, | ||
40 | .get = &clk_src_get, | ||
41 | }; | ||
42 | static struct snd_bebob_rate_spec rate_spec = { | ||
43 | .get = &snd_bebob_stream_get_rate, | ||
44 | .set = &snd_bebob_stream_set_rate, | ||
45 | }; | ||
46 | struct snd_bebob_spec yamaha_go_spec = { | ||
47 | .clock = &clock_spec, | ||
48 | .rate = &rate_spec, | ||
49 | .meter = NULL | ||
50 | }; | ||
diff --git a/sound/firewire/cmp.c b/sound/firewire/cmp.c index efdbf585e404..ba8df5a1be39 100644 --- a/sound/firewire/cmp.c +++ b/sound/firewire/cmp.c | |||
@@ -14,18 +14,28 @@ | |||
14 | #include "iso-resources.h" | 14 | #include "iso-resources.h" |
15 | #include "cmp.h" | 15 | #include "cmp.h" |
16 | 16 | ||
17 | #define IMPR_SPEED_MASK 0xc0000000 | 17 | /* MPR common fields */ |
18 | #define IMPR_SPEED_SHIFT 30 | 18 | #define MPR_SPEED_MASK 0xc0000000 |
19 | #define IMPR_XSPEED_MASK 0x00000060 | 19 | #define MPR_SPEED_SHIFT 30 |
20 | #define IMPR_XSPEED_SHIFT 5 | 20 | #define MPR_XSPEED_MASK 0x00000060 |
21 | #define IMPR_PLUGS_MASK 0x0000001f | 21 | #define MPR_XSPEED_SHIFT 5 |
22 | 22 | #define MPR_PLUGS_MASK 0x0000001f | |
23 | #define IPCR_ONLINE 0x80000000 | 23 | |
24 | #define IPCR_BCAST_CONN 0x40000000 | 24 | /* PCR common fields */ |
25 | #define IPCR_P2P_CONN_MASK 0x3f000000 | 25 | #define PCR_ONLINE 0x80000000 |
26 | #define IPCR_P2P_CONN_SHIFT 24 | 26 | #define PCR_BCAST_CONN 0x40000000 |
27 | #define IPCR_CHANNEL_MASK 0x003f0000 | 27 | #define PCR_P2P_CONN_MASK 0x3f000000 |
28 | #define IPCR_CHANNEL_SHIFT 16 | 28 | #define PCR_P2P_CONN_SHIFT 24 |
29 | #define PCR_CHANNEL_MASK 0x003f0000 | ||
30 | #define PCR_CHANNEL_SHIFT 16 | ||
31 | |||
32 | /* oPCR specific fields */ | ||
33 | #define OPCR_XSPEED_MASK 0x00C00000 | ||
34 | #define OPCR_XSPEED_SHIFT 22 | ||
35 | #define OPCR_SPEED_MASK 0x0000C000 | ||
36 | #define OPCR_SPEED_SHIFT 14 | ||
37 | #define OPCR_OVERHEAD_ID_MASK 0x00003C00 | ||
38 | #define OPCR_OVERHEAD_ID_SHIFT 10 | ||
29 | 39 | ||
30 | enum bus_reset_handling { | 40 | enum bus_reset_handling { |
31 | ABORT_ON_BUS_RESET, | 41 | ABORT_ON_BUS_RESET, |
@@ -39,10 +49,27 @@ void cmp_error(struct cmp_connection *c, const char *fmt, ...) | |||
39 | 49 | ||
40 | va_start(va, fmt); | 50 | va_start(va, fmt); |
41 | dev_err(&c->resources.unit->device, "%cPCR%u: %pV", | 51 | dev_err(&c->resources.unit->device, "%cPCR%u: %pV", |
42 | 'i', c->pcr_index, &(struct va_format){ fmt, &va }); | 52 | (c->direction == CMP_INPUT) ? 'i' : 'o', |
53 | c->pcr_index, &(struct va_format){ fmt, &va }); | ||
43 | va_end(va); | 54 | va_end(va); |
44 | } | 55 | } |
45 | 56 | ||
57 | static u64 mpr_address(struct cmp_connection *c) | ||
58 | { | ||
59 | if (c->direction == CMP_INPUT) | ||
60 | return CSR_REGISTER_BASE + CSR_IMPR; | ||
61 | else | ||
62 | return CSR_REGISTER_BASE + CSR_OMPR; | ||
63 | } | ||
64 | |||
65 | static u64 pcr_address(struct cmp_connection *c) | ||
66 | { | ||
67 | if (c->direction == CMP_INPUT) | ||
68 | return CSR_REGISTER_BASE + CSR_IPCR(c->pcr_index); | ||
69 | else | ||
70 | return CSR_REGISTER_BASE + CSR_OPCR(c->pcr_index); | ||
71 | } | ||
72 | |||
46 | static int pcr_modify(struct cmp_connection *c, | 73 | static int pcr_modify(struct cmp_connection *c, |
47 | __be32 (*modify)(struct cmp_connection *c, __be32 old), | 74 | __be32 (*modify)(struct cmp_connection *c, __be32 old), |
48 | int (*check)(struct cmp_connection *c, __be32 pcr), | 75 | int (*check)(struct cmp_connection *c, __be32 pcr), |
@@ -58,8 +85,7 @@ static int pcr_modify(struct cmp_connection *c, | |||
58 | 85 | ||
59 | err = snd_fw_transaction( | 86 | err = snd_fw_transaction( |
60 | c->resources.unit, TCODE_LOCK_COMPARE_SWAP, | 87 | c->resources.unit, TCODE_LOCK_COMPARE_SWAP, |
61 | CSR_REGISTER_BASE + CSR_IPCR(c->pcr_index), | 88 | pcr_address(c), buffer, 8, |
62 | buffer, 8, | ||
63 | FW_FIXED_GENERATION | c->resources.generation); | 89 | FW_FIXED_GENERATION | c->resources.generation); |
64 | 90 | ||
65 | if (err < 0) { | 91 | if (err < 0) { |
@@ -88,24 +114,25 @@ static int pcr_modify(struct cmp_connection *c, | |||
88 | * cmp_connection_init - initializes a connection manager | 114 | * cmp_connection_init - initializes a connection manager |
89 | * @c: the connection manager to initialize | 115 | * @c: the connection manager to initialize |
90 | * @unit: a unit of the target device | 116 | * @unit: a unit of the target device |
91 | * @ipcr_index: the index of the iPCR on the target device | 117 | * @pcr_index: the index of the iPCR/oPCR on the target device |
92 | */ | 118 | */ |
93 | int cmp_connection_init(struct cmp_connection *c, | 119 | int cmp_connection_init(struct cmp_connection *c, |
94 | struct fw_unit *unit, | 120 | struct fw_unit *unit, |
95 | unsigned int ipcr_index) | 121 | enum cmp_direction direction, |
122 | unsigned int pcr_index) | ||
96 | { | 123 | { |
97 | __be32 impr_be; | 124 | __be32 mpr_be; |
98 | u32 impr; | 125 | u32 mpr; |
99 | int err; | 126 | int err; |
100 | 127 | ||
128 | c->direction = direction; | ||
101 | err = snd_fw_transaction(unit, TCODE_READ_QUADLET_REQUEST, | 129 | err = snd_fw_transaction(unit, TCODE_READ_QUADLET_REQUEST, |
102 | CSR_REGISTER_BASE + CSR_IMPR, | 130 | mpr_address(c), &mpr_be, 4, 0); |
103 | &impr_be, 4, 0); | ||
104 | if (err < 0) | 131 | if (err < 0) |
105 | return err; | 132 | return err; |
106 | impr = be32_to_cpu(impr_be); | 133 | mpr = be32_to_cpu(mpr_be); |
107 | 134 | ||
108 | if (ipcr_index >= (impr & IMPR_PLUGS_MASK)) | 135 | if (pcr_index >= (mpr & MPR_PLUGS_MASK)) |
109 | return -EINVAL; | 136 | return -EINVAL; |
110 | 137 | ||
111 | err = fw_iso_resources_init(&c->resources, unit); | 138 | err = fw_iso_resources_init(&c->resources, unit); |
@@ -115,16 +142,36 @@ int cmp_connection_init(struct cmp_connection *c, | |||
115 | c->connected = false; | 142 | c->connected = false; |
116 | mutex_init(&c->mutex); | 143 | mutex_init(&c->mutex); |
117 | c->last_pcr_value = cpu_to_be32(0x80000000); | 144 | c->last_pcr_value = cpu_to_be32(0x80000000); |
118 | c->pcr_index = ipcr_index; | 145 | c->pcr_index = pcr_index; |
119 | c->max_speed = (impr & IMPR_SPEED_MASK) >> IMPR_SPEED_SHIFT; | 146 | c->max_speed = (mpr & MPR_SPEED_MASK) >> MPR_SPEED_SHIFT; |
120 | if (c->max_speed == SCODE_BETA) | 147 | if (c->max_speed == SCODE_BETA) |
121 | c->max_speed += (impr & IMPR_XSPEED_MASK) >> IMPR_XSPEED_SHIFT; | 148 | c->max_speed += (mpr & MPR_XSPEED_MASK) >> MPR_XSPEED_SHIFT; |
122 | 149 | ||
123 | return 0; | 150 | return 0; |
124 | } | 151 | } |
125 | EXPORT_SYMBOL(cmp_connection_init); | 152 | EXPORT_SYMBOL(cmp_connection_init); |
126 | 153 | ||
127 | /** | 154 | /** |
155 | * cmp_connection_check_used - check connection is already esablished or not | ||
156 | * @c: the connection manager to be checked | ||
157 | */ | ||
158 | int cmp_connection_check_used(struct cmp_connection *c, bool *used) | ||
159 | { | ||
160 | __be32 pcr; | ||
161 | int err; | ||
162 | |||
163 | err = snd_fw_transaction( | ||
164 | c->resources.unit, TCODE_READ_QUADLET_REQUEST, | ||
165 | pcr_address(c), &pcr, 4, 0); | ||
166 | if (err >= 0) | ||
167 | *used = !!(pcr & cpu_to_be32(PCR_BCAST_CONN | | ||
168 | PCR_P2P_CONN_MASK)); | ||
169 | |||
170 | return err; | ||
171 | } | ||
172 | EXPORT_SYMBOL(cmp_connection_check_used); | ||
173 | |||
174 | /** | ||
128 | * cmp_connection_destroy - free connection manager resources | 175 | * cmp_connection_destroy - free connection manager resources |
129 | * @c: the connection manager | 176 | * @c: the connection manager |
130 | */ | 177 | */ |
@@ -139,23 +186,70 @@ EXPORT_SYMBOL(cmp_connection_destroy); | |||
139 | 186 | ||
140 | static __be32 ipcr_set_modify(struct cmp_connection *c, __be32 ipcr) | 187 | static __be32 ipcr_set_modify(struct cmp_connection *c, __be32 ipcr) |
141 | { | 188 | { |
142 | ipcr &= ~cpu_to_be32(IPCR_BCAST_CONN | | 189 | ipcr &= ~cpu_to_be32(PCR_BCAST_CONN | |
143 | IPCR_P2P_CONN_MASK | | 190 | PCR_P2P_CONN_MASK | |
144 | IPCR_CHANNEL_MASK); | 191 | PCR_CHANNEL_MASK); |
145 | ipcr |= cpu_to_be32(1 << IPCR_P2P_CONN_SHIFT); | 192 | ipcr |= cpu_to_be32(1 << PCR_P2P_CONN_SHIFT); |
146 | ipcr |= cpu_to_be32(c->resources.channel << IPCR_CHANNEL_SHIFT); | 193 | ipcr |= cpu_to_be32(c->resources.channel << PCR_CHANNEL_SHIFT); |
147 | 194 | ||
148 | return ipcr; | 195 | return ipcr; |
149 | } | 196 | } |
150 | 197 | ||
151 | static int ipcr_set_check(struct cmp_connection *c, __be32 ipcr) | 198 | static int get_overhead_id(struct cmp_connection *c) |
152 | { | 199 | { |
153 | if (ipcr & cpu_to_be32(IPCR_BCAST_CONN | | 200 | int id; |
154 | IPCR_P2P_CONN_MASK)) { | 201 | |
202 | /* | ||
203 | * apply "oPCR overhead ID encoding" | ||
204 | * the encoding table can convert up to 512. | ||
205 | * here the value over 512 is converted as the same way as 512. | ||
206 | */ | ||
207 | for (id = 1; id < 16; id++) { | ||
208 | if (c->resources.bandwidth_overhead < (id << 5)) | ||
209 | break; | ||
210 | } | ||
211 | if (id == 16) | ||
212 | id = 0; | ||
213 | |||
214 | return id; | ||
215 | } | ||
216 | |||
217 | static __be32 opcr_set_modify(struct cmp_connection *c, __be32 opcr) | ||
218 | { | ||
219 | unsigned int spd, xspd; | ||
220 | |||
221 | /* generate speed and extended speed field value */ | ||
222 | if (c->speed > SCODE_400) { | ||
223 | spd = SCODE_800; | ||
224 | xspd = c->speed - SCODE_800; | ||
225 | } else { | ||
226 | spd = c->speed; | ||
227 | xspd = 0; | ||
228 | } | ||
229 | |||
230 | opcr &= ~cpu_to_be32(PCR_BCAST_CONN | | ||
231 | PCR_P2P_CONN_MASK | | ||
232 | OPCR_XSPEED_MASK | | ||
233 | PCR_CHANNEL_MASK | | ||
234 | OPCR_SPEED_MASK | | ||
235 | OPCR_OVERHEAD_ID_MASK); | ||
236 | opcr |= cpu_to_be32(1 << PCR_P2P_CONN_SHIFT); | ||
237 | opcr |= cpu_to_be32(xspd << OPCR_XSPEED_SHIFT); | ||
238 | opcr |= cpu_to_be32(c->resources.channel << PCR_CHANNEL_SHIFT); | ||
239 | opcr |= cpu_to_be32(spd << OPCR_SPEED_SHIFT); | ||
240 | opcr |= cpu_to_be32(get_overhead_id(c) << OPCR_OVERHEAD_ID_SHIFT); | ||
241 | |||
242 | return opcr; | ||
243 | } | ||
244 | |||
245 | static int pcr_set_check(struct cmp_connection *c, __be32 pcr) | ||
246 | { | ||
247 | if (pcr & cpu_to_be32(PCR_BCAST_CONN | | ||
248 | PCR_P2P_CONN_MASK)) { | ||
155 | cmp_error(c, "plug is already in use\n"); | 249 | cmp_error(c, "plug is already in use\n"); |
156 | return -EBUSY; | 250 | return -EBUSY; |
157 | } | 251 | } |
158 | if (!(ipcr & cpu_to_be32(IPCR_ONLINE))) { | 252 | if (!(pcr & cpu_to_be32(PCR_ONLINE))) { |
159 | cmp_error(c, "plug is not on-line\n"); | 253 | cmp_error(c, "plug is not on-line\n"); |
160 | return -ECONNREFUSED; | 254 | return -ECONNREFUSED; |
161 | } | 255 | } |
@@ -170,9 +264,9 @@ static int ipcr_set_check(struct cmp_connection *c, __be32 ipcr) | |||
170 | * | 264 | * |
171 | * This function establishes a point-to-point connection from the local | 265 | * This function establishes a point-to-point connection from the local |
172 | * computer to the target by allocating isochronous resources (channel and | 266 | * computer to the target by allocating isochronous resources (channel and |
173 | * bandwidth) and setting the target's input plug control register. When this | 267 | * bandwidth) and setting the target's input/output plug control register. |
174 | * function succeeds, the caller is responsible for starting transmitting | 268 | * When this function succeeds, the caller is responsible for starting |
175 | * packets. | 269 | * transmitting packets. |
176 | */ | 270 | */ |
177 | int cmp_connection_establish(struct cmp_connection *c, | 271 | int cmp_connection_establish(struct cmp_connection *c, |
178 | unsigned int max_payload_bytes) | 272 | unsigned int max_payload_bytes) |
@@ -193,8 +287,13 @@ retry_after_bus_reset: | |||
193 | if (err < 0) | 287 | if (err < 0) |
194 | goto err_mutex; | 288 | goto err_mutex; |
195 | 289 | ||
196 | err = pcr_modify(c, ipcr_set_modify, ipcr_set_check, | 290 | if (c->direction == CMP_OUTPUT) |
197 | ABORT_ON_BUS_RESET); | 291 | err = pcr_modify(c, opcr_set_modify, pcr_set_check, |
292 | ABORT_ON_BUS_RESET); | ||
293 | else | ||
294 | err = pcr_modify(c, ipcr_set_modify, pcr_set_check, | ||
295 | ABORT_ON_BUS_RESET); | ||
296 | |||
198 | if (err == -EAGAIN) { | 297 | if (err == -EAGAIN) { |
199 | fw_iso_resources_free(&c->resources); | 298 | fw_iso_resources_free(&c->resources); |
200 | goto retry_after_bus_reset; | 299 | goto retry_after_bus_reset; |
@@ -221,8 +320,8 @@ EXPORT_SYMBOL(cmp_connection_establish); | |||
221 | * cmp_connection_update - update the connection after a bus reset | 320 | * cmp_connection_update - update the connection after a bus reset |
222 | * @c: the connection manager | 321 | * @c: the connection manager |
223 | * | 322 | * |
224 | * This function must be called from the driver's .update handler to reestablish | 323 | * This function must be called from the driver's .update handler to |
225 | * any connection that might have been active. | 324 | * reestablish any connection that might have been active. |
226 | * | 325 | * |
227 | * Returns zero on success, or a negative error code. On an error, the | 326 | * Returns zero on success, or a negative error code. On an error, the |
228 | * connection is broken and the caller must stop transmitting iso packets. | 327 | * connection is broken and the caller must stop transmitting iso packets. |
@@ -242,8 +341,13 @@ int cmp_connection_update(struct cmp_connection *c) | |||
242 | if (err < 0) | 341 | if (err < 0) |
243 | goto err_unconnect; | 342 | goto err_unconnect; |
244 | 343 | ||
245 | err = pcr_modify(c, ipcr_set_modify, ipcr_set_check, | 344 | if (c->direction == CMP_OUTPUT) |
246 | SUCCEED_ON_BUS_RESET); | 345 | err = pcr_modify(c, opcr_set_modify, pcr_set_check, |
346 | SUCCEED_ON_BUS_RESET); | ||
347 | else | ||
348 | err = pcr_modify(c, ipcr_set_modify, pcr_set_check, | ||
349 | SUCCEED_ON_BUS_RESET); | ||
350 | |||
247 | if (err < 0) | 351 | if (err < 0) |
248 | goto err_resources; | 352 | goto err_resources; |
249 | 353 | ||
@@ -261,19 +365,18 @@ err_unconnect: | |||
261 | } | 365 | } |
262 | EXPORT_SYMBOL(cmp_connection_update); | 366 | EXPORT_SYMBOL(cmp_connection_update); |
263 | 367 | ||
264 | 368 | static __be32 pcr_break_modify(struct cmp_connection *c, __be32 pcr) | |
265 | static __be32 ipcr_break_modify(struct cmp_connection *c, __be32 ipcr) | ||
266 | { | 369 | { |
267 | return ipcr & ~cpu_to_be32(IPCR_BCAST_CONN | IPCR_P2P_CONN_MASK); | 370 | return pcr & ~cpu_to_be32(PCR_BCAST_CONN | PCR_P2P_CONN_MASK); |
268 | } | 371 | } |
269 | 372 | ||
270 | /** | 373 | /** |
271 | * cmp_connection_break - break the connection to the target | 374 | * cmp_connection_break - break the connection to the target |
272 | * @c: the connection manager | 375 | * @c: the connection manager |
273 | * | 376 | * |
274 | * This function deactives the connection in the target's input plug control | 377 | * This function deactives the connection in the target's input/output plug |
275 | * register, and frees the isochronous resources of the connection. Before | 378 | * control register, and frees the isochronous resources of the connection. |
276 | * calling this function, the caller should cease transmitting packets. | 379 | * Before calling this function, the caller should cease transmitting packets. |
277 | */ | 380 | */ |
278 | void cmp_connection_break(struct cmp_connection *c) | 381 | void cmp_connection_break(struct cmp_connection *c) |
279 | { | 382 | { |
@@ -286,7 +389,7 @@ void cmp_connection_break(struct cmp_connection *c) | |||
286 | return; | 389 | return; |
287 | } | 390 | } |
288 | 391 | ||
289 | err = pcr_modify(c, ipcr_break_modify, NULL, SUCCEED_ON_BUS_RESET); | 392 | err = pcr_modify(c, pcr_break_modify, NULL, SUCCEED_ON_BUS_RESET); |
290 | if (err < 0) | 393 | if (err < 0) |
291 | cmp_error(c, "plug is still connected\n"); | 394 | cmp_error(c, "plug is still connected\n"); |
292 | 395 | ||
diff --git a/sound/firewire/cmp.h b/sound/firewire/cmp.h index f47de08feb12..ebcb48484fca 100644 --- a/sound/firewire/cmp.h +++ b/sound/firewire/cmp.h | |||
@@ -7,12 +7,17 @@ | |||
7 | 7 | ||
8 | struct fw_unit; | 8 | struct fw_unit; |
9 | 9 | ||
10 | enum cmp_direction { | ||
11 | CMP_INPUT = 0, | ||
12 | CMP_OUTPUT, | ||
13 | }; | ||
14 | |||
10 | /** | 15 | /** |
11 | * struct cmp_connection - manages an isochronous connection to a device | 16 | * struct cmp_connection - manages an isochronous connection to a device |
12 | * @speed: the connection's actual speed | 17 | * @speed: the connection's actual speed |
13 | * | 18 | * |
14 | * This structure manages (using CMP) an isochronous stream from the local | 19 | * This structure manages (using CMP) an isochronous stream between the local |
15 | * computer to a device's input plug (iPCR). | 20 | * computer and a device's input plug (iPCR) and output plug (oPCR). |
16 | * | 21 | * |
17 | * There is no corresponding oPCR created on the local computer, so it is not | 22 | * There is no corresponding oPCR created on the local computer, so it is not |
18 | * possible to overlay connections on top of this one. | 23 | * possible to overlay connections on top of this one. |
@@ -26,11 +31,14 @@ struct cmp_connection { | |||
26 | __be32 last_pcr_value; | 31 | __be32 last_pcr_value; |
27 | unsigned int pcr_index; | 32 | unsigned int pcr_index; |
28 | unsigned int max_speed; | 33 | unsigned int max_speed; |
34 | enum cmp_direction direction; | ||
29 | }; | 35 | }; |
30 | 36 | ||
31 | int cmp_connection_init(struct cmp_connection *connection, | 37 | int cmp_connection_init(struct cmp_connection *connection, |
32 | struct fw_unit *unit, | 38 | struct fw_unit *unit, |
33 | unsigned int ipcr_index); | 39 | enum cmp_direction direction, |
40 | unsigned int pcr_index); | ||
41 | int cmp_connection_check_used(struct cmp_connection *connection, bool *used); | ||
34 | void cmp_connection_destroy(struct cmp_connection *connection); | 42 | void cmp_connection_destroy(struct cmp_connection *connection); |
35 | 43 | ||
36 | int cmp_connection_establish(struct cmp_connection *connection, | 44 | int cmp_connection_establish(struct cmp_connection *connection, |
diff --git a/sound/firewire/dice.c b/sound/firewire/dice.c index 0c3948630cf7..a9a30c0161f1 100644 --- a/sound/firewire/dice.c +++ b/sound/firewire/dice.c | |||
@@ -51,7 +51,7 @@ struct dice { | |||
51 | wait_queue_head_t hwdep_wait; | 51 | wait_queue_head_t hwdep_wait; |
52 | u32 notification_bits; | 52 | u32 notification_bits; |
53 | struct fw_iso_resources resources; | 53 | struct fw_iso_resources resources; |
54 | struct amdtp_out_stream stream; | 54 | struct amdtp_stream stream; |
55 | }; | 55 | }; |
56 | 56 | ||
57 | MODULE_DESCRIPTION("DICE driver"); | 57 | MODULE_DESCRIPTION("DICE driver"); |
@@ -420,22 +420,7 @@ static int dice_open(struct snd_pcm_substream *substream) | |||
420 | if (err < 0) | 420 | if (err < 0) |
421 | goto err_lock; | 421 | goto err_lock; |
422 | 422 | ||
423 | err = snd_pcm_hw_constraint_step(runtime, 0, | 423 | err = amdtp_stream_add_pcm_hw_constraints(&dice->stream, runtime); |
424 | SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 32); | ||
425 | if (err < 0) | ||
426 | goto err_lock; | ||
427 | err = snd_pcm_hw_constraint_step(runtime, 0, | ||
428 | SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 32); | ||
429 | if (err < 0) | ||
430 | goto err_lock; | ||
431 | |||
432 | err = snd_pcm_hw_constraint_minmax(runtime, | ||
433 | SNDRV_PCM_HW_PARAM_PERIOD_TIME, | ||
434 | 5000, UINT_MAX); | ||
435 | if (err < 0) | ||
436 | goto err_lock; | ||
437 | |||
438 | err = snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); | ||
439 | if (err < 0) | 424 | if (err < 0) |
440 | goto err_lock; | 425 | goto err_lock; |
441 | 426 | ||
@@ -460,17 +445,17 @@ static int dice_stream_start_packets(struct dice *dice) | |||
460 | { | 445 | { |
461 | int err; | 446 | int err; |
462 | 447 | ||
463 | if (amdtp_out_stream_running(&dice->stream)) | 448 | if (amdtp_stream_running(&dice->stream)) |
464 | return 0; | 449 | return 0; |
465 | 450 | ||
466 | err = amdtp_out_stream_start(&dice->stream, dice->resources.channel, | 451 | err = amdtp_stream_start(&dice->stream, dice->resources.channel, |
467 | fw_parent_device(dice->unit)->max_speed); | 452 | fw_parent_device(dice->unit)->max_speed); |
468 | if (err < 0) | 453 | if (err < 0) |
469 | return err; | 454 | return err; |
470 | 455 | ||
471 | err = dice_enable_set(dice); | 456 | err = dice_enable_set(dice); |
472 | if (err < 0) { | 457 | if (err < 0) { |
473 | amdtp_out_stream_stop(&dice->stream); | 458 | amdtp_stream_stop(&dice->stream); |
474 | return err; | 459 | return err; |
475 | } | 460 | } |
476 | 461 | ||
@@ -484,7 +469,7 @@ static int dice_stream_start(struct dice *dice) | |||
484 | 469 | ||
485 | if (!dice->resources.allocated) { | 470 | if (!dice->resources.allocated) { |
486 | err = fw_iso_resources_allocate(&dice->resources, | 471 | err = fw_iso_resources_allocate(&dice->resources, |
487 | amdtp_out_stream_get_max_payload(&dice->stream), | 472 | amdtp_stream_get_max_payload(&dice->stream), |
488 | fw_parent_device(dice->unit)->max_speed); | 473 | fw_parent_device(dice->unit)->max_speed); |
489 | if (err < 0) | 474 | if (err < 0) |
490 | goto error; | 475 | goto error; |
@@ -516,9 +501,9 @@ error: | |||
516 | 501 | ||
517 | static void dice_stream_stop_packets(struct dice *dice) | 502 | static void dice_stream_stop_packets(struct dice *dice) |
518 | { | 503 | { |
519 | if (amdtp_out_stream_running(&dice->stream)) { | 504 | if (amdtp_stream_running(&dice->stream)) { |
520 | dice_enable_clear(dice); | 505 | dice_enable_clear(dice); |
521 | amdtp_out_stream_stop(&dice->stream); | 506 | amdtp_stream_stop(&dice->stream); |
522 | } | 507 | } |
523 | } | 508 | } |
524 | 509 | ||
@@ -563,7 +548,7 @@ static int dice_hw_params(struct snd_pcm_substream *substream, | |||
563 | struct snd_pcm_hw_params *hw_params) | 548 | struct snd_pcm_hw_params *hw_params) |
564 | { | 549 | { |
565 | struct dice *dice = substream->private_data; | 550 | struct dice *dice = substream->private_data; |
566 | unsigned int rate_index, mode; | 551 | unsigned int rate_index, mode, rate, channels, i; |
567 | int err; | 552 | int err; |
568 | 553 | ||
569 | mutex_lock(&dice->mutex); | 554 | mutex_lock(&dice->mutex); |
@@ -575,18 +560,39 @@ static int dice_hw_params(struct snd_pcm_substream *substream, | |||
575 | if (err < 0) | 560 | if (err < 0) |
576 | return err; | 561 | return err; |
577 | 562 | ||
578 | rate_index = rate_to_index(params_rate(hw_params)); | 563 | rate = params_rate(hw_params); |
564 | rate_index = rate_to_index(rate); | ||
579 | err = dice_change_rate(dice, rate_index << CLOCK_RATE_SHIFT); | 565 | err = dice_change_rate(dice, rate_index << CLOCK_RATE_SHIFT); |
580 | if (err < 0) | 566 | if (err < 0) |
581 | return err; | 567 | return err; |
582 | 568 | ||
569 | /* | ||
570 | * At rates above 96 kHz, pretend that the stream runs at half the | ||
571 | * actual sample rate with twice the number of channels; two samples | ||
572 | * of a channel are stored consecutively in the packet. Requires | ||
573 | * blocking mode and PCM buffer size should be aligned to SYT_INTERVAL. | ||
574 | */ | ||
575 | channels = params_channels(hw_params); | ||
576 | if (rate_index > 4) { | ||
577 | if (channels > AMDTP_MAX_CHANNELS_FOR_PCM / 2) { | ||
578 | err = -ENOSYS; | ||
579 | return err; | ||
580 | } | ||
581 | |||
582 | for (i = 0; i < channels; i++) { | ||
583 | dice->stream.pcm_positions[i * 2] = i; | ||
584 | dice->stream.pcm_positions[i * 2 + 1] = i + channels; | ||
585 | } | ||
586 | |||
587 | rate /= 2; | ||
588 | channels *= 2; | ||
589 | } | ||
590 | |||
583 | mode = rate_index_to_mode(rate_index); | 591 | mode = rate_index_to_mode(rate_index); |
584 | amdtp_out_stream_set_parameters(&dice->stream, | 592 | amdtp_stream_set_parameters(&dice->stream, rate, channels, |
585 | params_rate(hw_params), | 593 | dice->rx_midi_ports[mode]); |
586 | params_channels(hw_params), | 594 | amdtp_stream_set_pcm_format(&dice->stream, |
587 | dice->rx_midi_ports[mode]); | 595 | params_format(hw_params)); |
588 | amdtp_out_stream_set_pcm_format(&dice->stream, | ||
589 | params_format(hw_params)); | ||
590 | 596 | ||
591 | return 0; | 597 | return 0; |
592 | } | 598 | } |
@@ -609,7 +615,7 @@ static int dice_prepare(struct snd_pcm_substream *substream) | |||
609 | 615 | ||
610 | mutex_lock(&dice->mutex); | 616 | mutex_lock(&dice->mutex); |
611 | 617 | ||
612 | if (amdtp_out_streaming_error(&dice->stream)) | 618 | if (amdtp_streaming_error(&dice->stream)) |
613 | dice_stream_stop_packets(dice); | 619 | dice_stream_stop_packets(dice); |
614 | 620 | ||
615 | err = dice_stream_start(dice); | 621 | err = dice_stream_start(dice); |
@@ -620,7 +626,7 @@ static int dice_prepare(struct snd_pcm_substream *substream) | |||
620 | 626 | ||
621 | mutex_unlock(&dice->mutex); | 627 | mutex_unlock(&dice->mutex); |
622 | 628 | ||
623 | amdtp_out_stream_pcm_prepare(&dice->stream); | 629 | amdtp_stream_pcm_prepare(&dice->stream); |
624 | 630 | ||
625 | return 0; | 631 | return 0; |
626 | } | 632 | } |
@@ -640,7 +646,7 @@ static int dice_trigger(struct snd_pcm_substream *substream, int cmd) | |||
640 | default: | 646 | default: |
641 | return -EINVAL; | 647 | return -EINVAL; |
642 | } | 648 | } |
643 | amdtp_out_stream_pcm_trigger(&dice->stream, pcm); | 649 | amdtp_stream_pcm_trigger(&dice->stream, pcm); |
644 | 650 | ||
645 | return 0; | 651 | return 0; |
646 | } | 652 | } |
@@ -649,7 +655,7 @@ static snd_pcm_uframes_t dice_pointer(struct snd_pcm_substream *substream) | |||
649 | { | 655 | { |
650 | struct dice *dice = substream->private_data; | 656 | struct dice *dice = substream->private_data; |
651 | 657 | ||
652 | return amdtp_out_stream_pcm_pointer(&dice->stream); | 658 | return amdtp_stream_pcm_pointer(&dice->stream); |
653 | } | 659 | } |
654 | 660 | ||
655 | static int dice_create_pcm(struct dice *dice) | 661 | static int dice_create_pcm(struct dice *dice) |
@@ -1104,7 +1110,7 @@ static void dice_card_free(struct snd_card *card) | |||
1104 | { | 1110 | { |
1105 | struct dice *dice = card->private_data; | 1111 | struct dice *dice = card->private_data; |
1106 | 1112 | ||
1107 | amdtp_out_stream_destroy(&dice->stream); | 1113 | amdtp_stream_destroy(&dice->stream); |
1108 | fw_core_remove_address_handler(&dice->notification_handler); | 1114 | fw_core_remove_address_handler(&dice->notification_handler); |
1109 | mutex_destroy(&dice->mutex); | 1115 | mutex_destroy(&dice->mutex); |
1110 | } | 1116 | } |
@@ -1360,8 +1366,8 @@ static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *id) | |||
1360 | goto err_owner; | 1366 | goto err_owner; |
1361 | dice->resources.channels_mask = 0x00000000ffffffffuLL; | 1367 | dice->resources.channels_mask = 0x00000000ffffffffuLL; |
1362 | 1368 | ||
1363 | err = amdtp_out_stream_init(&dice->stream, unit, | 1369 | err = amdtp_stream_init(&dice->stream, unit, AMDTP_OUT_STREAM, |
1364 | CIP_BLOCKING | CIP_HI_DUALWIRE); | 1370 | CIP_BLOCKING); |
1365 | if (err < 0) | 1371 | if (err < 0) |
1366 | goto err_resources; | 1372 | goto err_resources; |
1367 | 1373 | ||
@@ -1417,7 +1423,7 @@ static void dice_remove(struct fw_unit *unit) | |||
1417 | { | 1423 | { |
1418 | struct dice *dice = dev_get_drvdata(&unit->device); | 1424 | struct dice *dice = dev_get_drvdata(&unit->device); |
1419 | 1425 | ||
1420 | amdtp_out_stream_pcm_abort(&dice->stream); | 1426 | amdtp_stream_pcm_abort(&dice->stream); |
1421 | 1427 | ||
1422 | snd_card_disconnect(dice->card); | 1428 | snd_card_disconnect(dice->card); |
1423 | 1429 | ||
@@ -1443,7 +1449,7 @@ static void dice_bus_reset(struct fw_unit *unit) | |||
1443 | * to stop so that the application can restart them in an orderly | 1449 | * to stop so that the application can restart them in an orderly |
1444 | * manner. | 1450 | * manner. |
1445 | */ | 1451 | */ |
1446 | amdtp_out_stream_pcm_abort(&dice->stream); | 1452 | amdtp_stream_pcm_abort(&dice->stream); |
1447 | 1453 | ||
1448 | mutex_lock(&dice->mutex); | 1454 | mutex_lock(&dice->mutex); |
1449 | 1455 | ||
diff --git a/sound/firewire/fcp.c b/sound/firewire/fcp.c index 860c08073c59..0619597e3a3f 100644 --- a/sound/firewire/fcp.c +++ b/sound/firewire/fcp.c | |||
@@ -10,12 +10,14 @@ | |||
10 | #include <linux/firewire-constants.h> | 10 | #include <linux/firewire-constants.h> |
11 | #include <linux/list.h> | 11 | #include <linux/list.h> |
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/slab.h> | ||
13 | #include <linux/sched.h> | 14 | #include <linux/sched.h> |
14 | #include <linux/spinlock.h> | 15 | #include <linux/spinlock.h> |
15 | #include <linux/wait.h> | 16 | #include <linux/wait.h> |
16 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
17 | #include "fcp.h" | 18 | #include "fcp.h" |
18 | #include "lib.h" | 19 | #include "lib.h" |
20 | #include "amdtp.h" | ||
19 | 21 | ||
20 | #define CTS_AVC 0x00 | 22 | #define CTS_AVC 0x00 |
21 | 23 | ||
@@ -23,6 +25,158 @@ | |||
23 | #define ERROR_DELAY_MS 5 | 25 | #define ERROR_DELAY_MS 5 |
24 | #define FCP_TIMEOUT_MS 125 | 26 | #define FCP_TIMEOUT_MS 125 |
25 | 27 | ||
28 | int avc_general_set_sig_fmt(struct fw_unit *unit, unsigned int rate, | ||
29 | enum avc_general_plug_dir dir, | ||
30 | unsigned short pid) | ||
31 | { | ||
32 | unsigned int sfc; | ||
33 | u8 *buf; | ||
34 | bool flag; | ||
35 | int err; | ||
36 | |||
37 | flag = false; | ||
38 | for (sfc = 0; sfc < CIP_SFC_COUNT; sfc++) { | ||
39 | if (amdtp_rate_table[sfc] == rate) { | ||
40 | flag = true; | ||
41 | break; | ||
42 | } | ||
43 | } | ||
44 | if (!flag) | ||
45 | return -EINVAL; | ||
46 | |||
47 | buf = kzalloc(8, GFP_KERNEL); | ||
48 | if (buf == NULL) | ||
49 | return -ENOMEM; | ||
50 | |||
51 | buf[0] = 0x00; /* AV/C CONTROL */ | ||
52 | buf[1] = 0xff; /* UNIT */ | ||
53 | if (dir == AVC_GENERAL_PLUG_DIR_IN) | ||
54 | buf[2] = 0x19; /* INPUT PLUG SIGNAL FORMAT */ | ||
55 | else | ||
56 | buf[2] = 0x18; /* OUTPUT PLUG SIGNAL FORMAT */ | ||
57 | buf[3] = 0xff & pid; /* plug id */ | ||
58 | buf[4] = 0x90; /* EOH_1, Form_1, FMT. AM824 */ | ||
59 | buf[5] = 0x07 & sfc; /* FDF-hi. AM824, frequency */ | ||
60 | buf[6] = 0xff; /* FDF-mid. AM824, SYT hi (not used)*/ | ||
61 | buf[7] = 0xff; /* FDF-low. AM824, SYT lo (not used) */ | ||
62 | |||
63 | /* do transaction and check buf[1-5] are the same against command */ | ||
64 | err = fcp_avc_transaction(unit, buf, 8, buf, 8, | ||
65 | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5)); | ||
66 | if (err >= 0 && err < 8) | ||
67 | err = -EIO; | ||
68 | else if (buf[0] == 0x08) /* NOT IMPLEMENTED */ | ||
69 | err = -ENOSYS; | ||
70 | else if (buf[0] == 0x0a) /* REJECTED */ | ||
71 | err = -EINVAL; | ||
72 | if (err < 0) | ||
73 | goto end; | ||
74 | |||
75 | err = 0; | ||
76 | end: | ||
77 | kfree(buf); | ||
78 | return err; | ||
79 | } | ||
80 | EXPORT_SYMBOL(avc_general_set_sig_fmt); | ||
81 | |||
82 | int avc_general_get_sig_fmt(struct fw_unit *unit, unsigned int *rate, | ||
83 | enum avc_general_plug_dir dir, | ||
84 | unsigned short pid) | ||
85 | { | ||
86 | unsigned int sfc; | ||
87 | u8 *buf; | ||
88 | int err; | ||
89 | |||
90 | buf = kzalloc(8, GFP_KERNEL); | ||
91 | if (buf == NULL) | ||
92 | return -ENOMEM; | ||
93 | |||
94 | buf[0] = 0x01; /* AV/C STATUS */ | ||
95 | buf[1] = 0xff; /* Unit */ | ||
96 | if (dir == AVC_GENERAL_PLUG_DIR_IN) | ||
97 | buf[2] = 0x19; /* INPUT PLUG SIGNAL FORMAT */ | ||
98 | else | ||
99 | buf[2] = 0x18; /* OUTPUT PLUG SIGNAL FORMAT */ | ||
100 | buf[3] = 0xff & pid; /* plug id */ | ||
101 | buf[4] = 0x90; /* EOH_1, Form_1, FMT. AM824 */ | ||
102 | buf[5] = 0xff; /* FDF-hi. AM824, frequency */ | ||
103 | buf[6] = 0xff; /* FDF-mid. AM824, SYT hi (not used) */ | ||
104 | buf[7] = 0xff; /* FDF-low. AM824, SYT lo (not used) */ | ||
105 | |||
106 | /* do transaction and check buf[1-4] are the same against command */ | ||
107 | err = fcp_avc_transaction(unit, buf, 8, buf, 8, | ||
108 | BIT(1) | BIT(2) | BIT(3) | BIT(4)); | ||
109 | if (err >= 0 && err < 8) | ||
110 | err = -EIO; | ||
111 | else if (buf[0] == 0x08) /* NOT IMPLEMENTED */ | ||
112 | err = -ENOSYS; | ||
113 | else if (buf[0] == 0x0a) /* REJECTED */ | ||
114 | err = -EINVAL; | ||
115 | else if (buf[0] == 0x0b) /* IN TRANSITION */ | ||
116 | err = -EAGAIN; | ||
117 | if (err < 0) | ||
118 | goto end; | ||
119 | |||
120 | /* check sfc field and pick up rate */ | ||
121 | sfc = 0x07 & buf[5]; | ||
122 | if (sfc >= CIP_SFC_COUNT) { | ||
123 | err = -EAGAIN; /* also in transition */ | ||
124 | goto end; | ||
125 | } | ||
126 | |||
127 | *rate = amdtp_rate_table[sfc]; | ||
128 | err = 0; | ||
129 | end: | ||
130 | kfree(buf); | ||
131 | return err; | ||
132 | } | ||
133 | EXPORT_SYMBOL(avc_general_get_sig_fmt); | ||
134 | |||
135 | int avc_general_get_plug_info(struct fw_unit *unit, unsigned int subunit_type, | ||
136 | unsigned int subunit_id, unsigned int subfunction, | ||
137 | u8 info[AVC_PLUG_INFO_BUF_BYTES]) | ||
138 | { | ||
139 | u8 *buf; | ||
140 | int err; | ||
141 | |||
142 | /* extended subunit in spec.4.2 is not supported */ | ||
143 | if ((subunit_type == 0x1E) || (subunit_id == 5)) | ||
144 | return -EINVAL; | ||
145 | |||
146 | buf = kzalloc(8, GFP_KERNEL); | ||
147 | if (buf == NULL) | ||
148 | return -ENOMEM; | ||
149 | |||
150 | buf[0] = 0x01; /* AV/C STATUS */ | ||
151 | /* UNIT or Subunit, Functionblock */ | ||
152 | buf[1] = ((subunit_type & 0x1f) << 3) | (subunit_id & 0x7); | ||
153 | buf[2] = 0x02; /* PLUG INFO */ | ||
154 | buf[3] = 0xff & subfunction; | ||
155 | |||
156 | err = fcp_avc_transaction(unit, buf, 8, buf, 8, BIT(1) | BIT(2)); | ||
157 | if (err >= 0 && err < 8) | ||
158 | err = -EIO; | ||
159 | else if (buf[0] == 0x08) /* NOT IMPLEMENTED */ | ||
160 | err = -ENOSYS; | ||
161 | else if (buf[0] == 0x0a) /* REJECTED */ | ||
162 | err = -EINVAL; | ||
163 | else if (buf[0] == 0x0b) /* IN TRANSITION */ | ||
164 | err = -EAGAIN; | ||
165 | if (err < 0) | ||
166 | goto end; | ||
167 | |||
168 | info[0] = buf[4]; | ||
169 | info[1] = buf[5]; | ||
170 | info[2] = buf[6]; | ||
171 | info[3] = buf[7]; | ||
172 | |||
173 | err = 0; | ||
174 | end: | ||
175 | kfree(buf); | ||
176 | return err; | ||
177 | } | ||
178 | EXPORT_SYMBOL(avc_general_get_plug_info); | ||
179 | |||
26 | static DEFINE_SPINLOCK(transactions_lock); | 180 | static DEFINE_SPINLOCK(transactions_lock); |
27 | static LIST_HEAD(transactions); | 181 | static LIST_HEAD(transactions); |
28 | 182 | ||
@@ -30,6 +184,7 @@ enum fcp_state { | |||
30 | STATE_PENDING, | 184 | STATE_PENDING, |
31 | STATE_BUS_RESET, | 185 | STATE_BUS_RESET, |
32 | STATE_COMPLETE, | 186 | STATE_COMPLETE, |
187 | STATE_DEFERRED, | ||
33 | }; | 188 | }; |
34 | 189 | ||
35 | struct fcp_transaction { | 190 | struct fcp_transaction { |
@@ -40,6 +195,7 @@ struct fcp_transaction { | |||
40 | unsigned int response_match_bytes; | 195 | unsigned int response_match_bytes; |
41 | enum fcp_state state; | 196 | enum fcp_state state; |
42 | wait_queue_head_t wait; | 197 | wait_queue_head_t wait; |
198 | bool deferrable; | ||
43 | }; | 199 | }; |
44 | 200 | ||
45 | /** | 201 | /** |
@@ -62,8 +218,6 @@ struct fcp_transaction { | |||
62 | * | 218 | * |
63 | * @command and @response can point to the same buffer. | 219 | * @command and @response can point to the same buffer. |
64 | * | 220 | * |
65 | * Asynchronous operation (INTERIM, NOTIFY) is not supported at the moment. | ||
66 | * | ||
67 | * Returns the actual size of the response frame, or a negative error code. | 221 | * Returns the actual size of the response frame, or a negative error code. |
68 | */ | 222 | */ |
69 | int fcp_avc_transaction(struct fw_unit *unit, | 223 | int fcp_avc_transaction(struct fw_unit *unit, |
@@ -81,6 +235,9 @@ int fcp_avc_transaction(struct fw_unit *unit, | |||
81 | t.state = STATE_PENDING; | 235 | t.state = STATE_PENDING; |
82 | init_waitqueue_head(&t.wait); | 236 | init_waitqueue_head(&t.wait); |
83 | 237 | ||
238 | if (*(const u8 *)command == 0x00 || *(const u8 *)command == 0x03) | ||
239 | t.deferrable = true; | ||
240 | |||
84 | spin_lock_irq(&transactions_lock); | 241 | spin_lock_irq(&transactions_lock); |
85 | list_add_tail(&t.list, &transactions); | 242 | list_add_tail(&t.list, &transactions); |
86 | spin_unlock_irq(&transactions_lock); | 243 | spin_unlock_irq(&transactions_lock); |
@@ -93,11 +250,21 @@ int fcp_avc_transaction(struct fw_unit *unit, | |||
93 | (void *)command, command_size, 0); | 250 | (void *)command, command_size, 0); |
94 | if (ret < 0) | 251 | if (ret < 0) |
95 | break; | 252 | break; |
96 | 253 | deferred: | |
97 | wait_event_timeout(t.wait, t.state != STATE_PENDING, | 254 | wait_event_timeout(t.wait, t.state != STATE_PENDING, |
98 | msecs_to_jiffies(FCP_TIMEOUT_MS)); | 255 | msecs_to_jiffies(FCP_TIMEOUT_MS)); |
99 | 256 | ||
100 | if (t.state == STATE_COMPLETE) { | 257 | if (t.state == STATE_DEFERRED) { |
258 | /* | ||
259 | * 'AV/C General Specification' define no time limit | ||
260 | * on command completion once an INTERIM response has | ||
261 | * been sent. but we promise to finish this function | ||
262 | * for a caller. Here we use FCP_TIMEOUT_MS for next | ||
263 | * interval. This is not in the specification. | ||
264 | */ | ||
265 | t.state = STATE_PENDING; | ||
266 | goto deferred; | ||
267 | } else if (t.state == STATE_COMPLETE) { | ||
101 | ret = t.response_size; | 268 | ret = t.response_size; |
102 | break; | 269 | break; |
103 | } else if (t.state == STATE_BUS_RESET) { | 270 | } else if (t.state == STATE_BUS_RESET) { |
@@ -132,7 +299,8 @@ void fcp_bus_reset(struct fw_unit *unit) | |||
132 | spin_lock_irq(&transactions_lock); | 299 | spin_lock_irq(&transactions_lock); |
133 | list_for_each_entry(t, &transactions, list) { | 300 | list_for_each_entry(t, &transactions, list) { |
134 | if (t->unit == unit && | 301 | if (t->unit == unit && |
135 | t->state == STATE_PENDING) { | 302 | (t->state == STATE_PENDING || |
303 | t->state == STATE_DEFERRED)) { | ||
136 | t->state = STATE_BUS_RESET; | 304 | t->state = STATE_BUS_RESET; |
137 | wake_up(&t->wait); | 305 | wake_up(&t->wait); |
138 | } | 306 | } |
@@ -186,10 +354,15 @@ static void fcp_response(struct fw_card *card, struct fw_request *request, | |||
186 | 354 | ||
187 | if (t->state == STATE_PENDING && | 355 | if (t->state == STATE_PENDING && |
188 | is_matching_response(t, data, length)) { | 356 | is_matching_response(t, data, length)) { |
189 | t->state = STATE_COMPLETE; | 357 | if (t->deferrable && *(const u8 *)data == 0x0f) { |
190 | t->response_size = min((unsigned int)length, | 358 | t->state = STATE_DEFERRED; |
191 | t->response_size); | 359 | } else { |
192 | memcpy(t->response_buffer, data, t->response_size); | 360 | t->state = STATE_COMPLETE; |
361 | t->response_size = min_t(unsigned int, length, | ||
362 | t->response_size); | ||
363 | memcpy(t->response_buffer, data, | ||
364 | t->response_size); | ||
365 | } | ||
193 | wake_up(&t->wait); | 366 | wake_up(&t->wait); |
194 | } | 367 | } |
195 | } | 368 | } |
diff --git a/sound/firewire/fcp.h b/sound/firewire/fcp.h index 86595688bd91..63ae4f7ce3af 100644 --- a/sound/firewire/fcp.h +++ b/sound/firewire/fcp.h | |||
@@ -1,8 +1,29 @@ | |||
1 | #ifndef SOUND_FIREWIRE_FCP_H_INCLUDED | 1 | #ifndef SOUND_FIREWIRE_FCP_H_INCLUDED |
2 | #define SOUND_FIREWIRE_FCP_H_INCLUDED | 2 | #define SOUND_FIREWIRE_FCP_H_INCLUDED |
3 | 3 | ||
4 | #define AVC_PLUG_INFO_BUF_BYTES 4 | ||
5 | |||
4 | struct fw_unit; | 6 | struct fw_unit; |
5 | 7 | ||
8 | /* | ||
9 | * AV/C Digital Interface Command Set General Specification 4.2 | ||
10 | * (Sep 2004, 1394TA) | ||
11 | */ | ||
12 | enum avc_general_plug_dir { | ||
13 | AVC_GENERAL_PLUG_DIR_IN = 0, | ||
14 | AVC_GENERAL_PLUG_DIR_OUT = 1, | ||
15 | AVC_GENERAL_PLUG_DIR_COUNT | ||
16 | }; | ||
17 | int avc_general_set_sig_fmt(struct fw_unit *unit, unsigned int rate, | ||
18 | enum avc_general_plug_dir dir, | ||
19 | unsigned short plug); | ||
20 | int avc_general_get_sig_fmt(struct fw_unit *unit, unsigned int *rate, | ||
21 | enum avc_general_plug_dir dir, | ||
22 | unsigned short plug); | ||
23 | int avc_general_get_plug_info(struct fw_unit *unit, unsigned int subunit_type, | ||
24 | unsigned int subunit_id, unsigned int subfunction, | ||
25 | u8 info[AVC_PLUG_INFO_BUF_BYTES]); | ||
26 | |||
6 | int fcp_avc_transaction(struct fw_unit *unit, | 27 | int fcp_avc_transaction(struct fw_unit *unit, |
7 | const void *command, unsigned int command_size, | 28 | const void *command, unsigned int command_size, |
8 | void *response, unsigned int response_size, | 29 | void *response, unsigned int response_size, |
diff --git a/sound/firewire/fireworks/Makefile b/sound/firewire/fireworks/Makefile new file mode 100644 index 000000000000..0c7440826db8 --- /dev/null +++ b/sound/firewire/fireworks/Makefile | |||
@@ -0,0 +1,4 @@ | |||
1 | snd-fireworks-objs := fireworks_transaction.o fireworks_command.o \ | ||
2 | fireworks_stream.o fireworks_proc.o fireworks_midi.o \ | ||
3 | fireworks_pcm.o fireworks_hwdep.o fireworks.o | ||
4 | obj-m += snd-fireworks.o | ||
diff --git a/sound/firewire/fireworks/fireworks.c b/sound/firewire/fireworks/fireworks.c new file mode 100644 index 000000000000..3e2ed8e82cbc --- /dev/null +++ b/sound/firewire/fireworks/fireworks.c | |||
@@ -0,0 +1,352 @@ | |||
1 | /* | ||
2 | * fireworks.c - a part of driver for Fireworks based devices | ||
3 | * | ||
4 | * Copyright (c) 2009-2010 Clemens Ladisch | ||
5 | * Copyright (c) 2013-2014 Takashi Sakamoto | ||
6 | * | ||
7 | * Licensed under the terms of the GNU General Public License, version 2. | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * Fireworks is a board module which Echo Audio produced. This module consists | ||
12 | * of three chipsets: | ||
13 | * - Communication chipset for IEEE1394 PHY/Link and IEC 61883-1/6 | ||
14 | * - DSP or/and FPGA for signal processing | ||
15 | * - Flash Memory to store firmwares | ||
16 | */ | ||
17 | |||
18 | #include "fireworks.h" | ||
19 | |||
20 | MODULE_DESCRIPTION("Echo Fireworks driver"); | ||
21 | MODULE_AUTHOR("Takashi Sakamoto <o-takashi@sakamocchi.jp>"); | ||
22 | MODULE_LICENSE("GPL v2"); | ||
23 | |||
24 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; | ||
25 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; | ||
26 | static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; | ||
27 | unsigned int snd_efw_resp_buf_size = 1024; | ||
28 | bool snd_efw_resp_buf_debug = false; | ||
29 | |||
30 | module_param_array(index, int, NULL, 0444); | ||
31 | MODULE_PARM_DESC(index, "card index"); | ||
32 | module_param_array(id, charp, NULL, 0444); | ||
33 | MODULE_PARM_DESC(id, "ID string"); | ||
34 | module_param_array(enable, bool, NULL, 0444); | ||
35 | MODULE_PARM_DESC(enable, "enable Fireworks sound card"); | ||
36 | module_param_named(resp_buf_size, snd_efw_resp_buf_size, uint, 0444); | ||
37 | MODULE_PARM_DESC(resp_buf_size, | ||
38 | "response buffer size (max 4096, default 1024)"); | ||
39 | module_param_named(resp_buf_debug, snd_efw_resp_buf_debug, bool, 0444); | ||
40 | MODULE_PARM_DESC(resp_buf_debug, "store all responses to buffer"); | ||
41 | |||
42 | static DEFINE_MUTEX(devices_mutex); | ||
43 | static DECLARE_BITMAP(devices_used, SNDRV_CARDS); | ||
44 | |||
45 | #define VENDOR_LOUD 0x000ff2 | ||
46 | #define MODEL_MACKIE_400F 0x00400f | ||
47 | #define MODEL_MACKIE_1200F 0x01200f | ||
48 | |||
49 | #define VENDOR_ECHO 0x001486 | ||
50 | #define MODEL_ECHO_AUDIOFIRE_12 0x00af12 | ||
51 | #define MODEL_ECHO_AUDIOFIRE_12HD 0x0af12d | ||
52 | #define MODEL_ECHO_AUDIOFIRE_12_APPLE 0x0af12a | ||
53 | /* This is applied for AudioFire8 (until 2009 July) */ | ||
54 | #define MODEL_ECHO_AUDIOFIRE_8 0x000af8 | ||
55 | #define MODEL_ECHO_AUDIOFIRE_2 0x000af2 | ||
56 | #define MODEL_ECHO_AUDIOFIRE_4 0x000af4 | ||
57 | /* AudioFire9 is applied for AudioFire8(since 2009 July) and AudioFirePre8 */ | ||
58 | #define MODEL_ECHO_AUDIOFIRE_9 0x000af9 | ||
59 | /* unknown as product */ | ||
60 | #define MODEL_ECHO_FIREWORKS_8 0x0000f8 | ||
61 | #define MODEL_ECHO_FIREWORKS_HDMI 0x00afd1 | ||
62 | |||
63 | #define VENDOR_GIBSON 0x00075b | ||
64 | /* for Robot Interface Pack of Dark Fire, Dusk Tiger, Les Paul Standard 2010 */ | ||
65 | #define MODEL_GIBSON_RIP 0x00afb2 | ||
66 | /* unknown as product */ | ||
67 | #define MODEL_GIBSON_GOLDTOP 0x00afb9 | ||
68 | |||
69 | /* part of hardware capability flags */ | ||
70 | #define FLAG_RESP_ADDR_CHANGABLE 0 | ||
71 | |||
72 | static int | ||
73 | get_hardware_info(struct snd_efw *efw) | ||
74 | { | ||
75 | struct fw_device *fw_dev = fw_parent_device(efw->unit); | ||
76 | struct snd_efw_hwinfo *hwinfo; | ||
77 | char version[12] = {0}; | ||
78 | int err; | ||
79 | |||
80 | hwinfo = kzalloc(sizeof(struct snd_efw_hwinfo), GFP_KERNEL); | ||
81 | if (hwinfo == NULL) | ||
82 | return -ENOMEM; | ||
83 | |||
84 | err = snd_efw_command_get_hwinfo(efw, hwinfo); | ||
85 | if (err < 0) | ||
86 | goto end; | ||
87 | |||
88 | /* firmware version for communication chipset */ | ||
89 | snprintf(version, sizeof(version), "%u.%u", | ||
90 | (hwinfo->arm_version >> 24) & 0xff, | ||
91 | (hwinfo->arm_version >> 16) & 0xff); | ||
92 | efw->firmware_version = hwinfo->arm_version; | ||
93 | |||
94 | strcpy(efw->card->driver, "Fireworks"); | ||
95 | strcpy(efw->card->shortname, hwinfo->model_name); | ||
96 | strcpy(efw->card->mixername, hwinfo->model_name); | ||
97 | snprintf(efw->card->longname, sizeof(efw->card->longname), | ||
98 | "%s %s v%s, GUID %08x%08x at %s, S%d", | ||
99 | hwinfo->vendor_name, hwinfo->model_name, version, | ||
100 | hwinfo->guid_hi, hwinfo->guid_lo, | ||
101 | dev_name(&efw->unit->device), 100 << fw_dev->max_speed); | ||
102 | |||
103 | if (hwinfo->flags & BIT(FLAG_RESP_ADDR_CHANGABLE)) | ||
104 | efw->resp_addr_changable = true; | ||
105 | |||
106 | efw->supported_sampling_rate = 0; | ||
107 | if ((hwinfo->min_sample_rate <= 22050) | ||
108 | && (22050 <= hwinfo->max_sample_rate)) | ||
109 | efw->supported_sampling_rate |= SNDRV_PCM_RATE_22050; | ||
110 | if ((hwinfo->min_sample_rate <= 32000) | ||
111 | && (32000 <= hwinfo->max_sample_rate)) | ||
112 | efw->supported_sampling_rate |= SNDRV_PCM_RATE_32000; | ||
113 | if ((hwinfo->min_sample_rate <= 44100) | ||
114 | && (44100 <= hwinfo->max_sample_rate)) | ||
115 | efw->supported_sampling_rate |= SNDRV_PCM_RATE_44100; | ||
116 | if ((hwinfo->min_sample_rate <= 48000) | ||
117 | && (48000 <= hwinfo->max_sample_rate)) | ||
118 | efw->supported_sampling_rate |= SNDRV_PCM_RATE_48000; | ||
119 | if ((hwinfo->min_sample_rate <= 88200) | ||
120 | && (88200 <= hwinfo->max_sample_rate)) | ||
121 | efw->supported_sampling_rate |= SNDRV_PCM_RATE_88200; | ||
122 | if ((hwinfo->min_sample_rate <= 96000) | ||
123 | && (96000 <= hwinfo->max_sample_rate)) | ||
124 | efw->supported_sampling_rate |= SNDRV_PCM_RATE_96000; | ||
125 | if ((hwinfo->min_sample_rate <= 176400) | ||
126 | && (176400 <= hwinfo->max_sample_rate)) | ||
127 | efw->supported_sampling_rate |= SNDRV_PCM_RATE_176400; | ||
128 | if ((hwinfo->min_sample_rate <= 192000) | ||
129 | && (192000 <= hwinfo->max_sample_rate)) | ||
130 | efw->supported_sampling_rate |= SNDRV_PCM_RATE_192000; | ||
131 | |||
132 | /* the number of MIDI ports, not of MIDI conformant data channels */ | ||
133 | if (hwinfo->midi_out_ports > SND_EFW_MAX_MIDI_OUT_PORTS || | ||
134 | hwinfo->midi_in_ports > SND_EFW_MAX_MIDI_IN_PORTS) { | ||
135 | err = -EIO; | ||
136 | goto end; | ||
137 | } | ||
138 | efw->midi_out_ports = hwinfo->midi_out_ports; | ||
139 | efw->midi_in_ports = hwinfo->midi_in_ports; | ||
140 | |||
141 | if (hwinfo->amdtp_tx_pcm_channels > AMDTP_MAX_CHANNELS_FOR_PCM || | ||
142 | hwinfo->amdtp_tx_pcm_channels_2x > AMDTP_MAX_CHANNELS_FOR_PCM || | ||
143 | hwinfo->amdtp_tx_pcm_channels_4x > AMDTP_MAX_CHANNELS_FOR_PCM || | ||
144 | hwinfo->amdtp_rx_pcm_channels > AMDTP_MAX_CHANNELS_FOR_PCM || | ||
145 | hwinfo->amdtp_rx_pcm_channels_2x > AMDTP_MAX_CHANNELS_FOR_PCM || | ||
146 | hwinfo->amdtp_rx_pcm_channels_4x > AMDTP_MAX_CHANNELS_FOR_PCM) { | ||
147 | err = -ENOSYS; | ||
148 | goto end; | ||
149 | } | ||
150 | efw->pcm_capture_channels[0] = hwinfo->amdtp_tx_pcm_channels; | ||
151 | efw->pcm_capture_channels[1] = hwinfo->amdtp_tx_pcm_channels_2x; | ||
152 | efw->pcm_capture_channels[2] = hwinfo->amdtp_tx_pcm_channels_4x; | ||
153 | efw->pcm_playback_channels[0] = hwinfo->amdtp_rx_pcm_channels; | ||
154 | efw->pcm_playback_channels[1] = hwinfo->amdtp_rx_pcm_channels_2x; | ||
155 | efw->pcm_playback_channels[2] = hwinfo->amdtp_rx_pcm_channels_4x; | ||
156 | |||
157 | /* Hardware metering. */ | ||
158 | if (hwinfo->phys_in_grp_count > HWINFO_MAX_CAPS_GROUPS || | ||
159 | hwinfo->phys_out_grp_count > HWINFO_MAX_CAPS_GROUPS) { | ||
160 | err = -EIO; | ||
161 | goto end; | ||
162 | } | ||
163 | efw->phys_in = hwinfo->phys_in; | ||
164 | efw->phys_out = hwinfo->phys_out; | ||
165 | efw->phys_in_grp_count = hwinfo->phys_in_grp_count; | ||
166 | efw->phys_out_grp_count = hwinfo->phys_out_grp_count; | ||
167 | memcpy(&efw->phys_in_grps, hwinfo->phys_in_grps, | ||
168 | sizeof(struct snd_efw_phys_grp) * hwinfo->phys_in_grp_count); | ||
169 | memcpy(&efw->phys_out_grps, hwinfo->phys_out_grps, | ||
170 | sizeof(struct snd_efw_phys_grp) * hwinfo->phys_out_grp_count); | ||
171 | end: | ||
172 | kfree(hwinfo); | ||
173 | return err; | ||
174 | } | ||
175 | |||
176 | static void | ||
177 | efw_card_free(struct snd_card *card) | ||
178 | { | ||
179 | struct snd_efw *efw = card->private_data; | ||
180 | |||
181 | if (efw->card_index >= 0) { | ||
182 | mutex_lock(&devices_mutex); | ||
183 | clear_bit(efw->card_index, devices_used); | ||
184 | mutex_unlock(&devices_mutex); | ||
185 | } | ||
186 | |||
187 | mutex_destroy(&efw->mutex); | ||
188 | kfree(efw->resp_buf); | ||
189 | } | ||
190 | |||
191 | static int | ||
192 | efw_probe(struct fw_unit *unit, | ||
193 | const struct ieee1394_device_id *entry) | ||
194 | { | ||
195 | struct snd_card *card; | ||
196 | struct snd_efw *efw; | ||
197 | int card_index, err; | ||
198 | |||
199 | mutex_lock(&devices_mutex); | ||
200 | |||
201 | /* check registered cards */ | ||
202 | for (card_index = 0; card_index < SNDRV_CARDS; ++card_index) { | ||
203 | if (!test_bit(card_index, devices_used) && enable[card_index]) | ||
204 | break; | ||
205 | } | ||
206 | if (card_index >= SNDRV_CARDS) { | ||
207 | err = -ENOENT; | ||
208 | goto end; | ||
209 | } | ||
210 | |||
211 | err = snd_card_new(&unit->device, index[card_index], id[card_index], | ||
212 | THIS_MODULE, sizeof(struct snd_efw), &card); | ||
213 | if (err < 0) | ||
214 | goto end; | ||
215 | efw = card->private_data; | ||
216 | efw->card_index = card_index; | ||
217 | set_bit(card_index, devices_used); | ||
218 | card->private_free = efw_card_free; | ||
219 | |||
220 | efw->card = card; | ||
221 | efw->unit = unit; | ||
222 | mutex_init(&efw->mutex); | ||
223 | spin_lock_init(&efw->lock); | ||
224 | init_waitqueue_head(&efw->hwdep_wait); | ||
225 | |||
226 | /* prepare response buffer */ | ||
227 | snd_efw_resp_buf_size = clamp(snd_efw_resp_buf_size, | ||
228 | SND_EFW_RESPONSE_MAXIMUM_BYTES, 4096U); | ||
229 | efw->resp_buf = kzalloc(snd_efw_resp_buf_size, GFP_KERNEL); | ||
230 | if (efw->resp_buf == NULL) { | ||
231 | err = -ENOMEM; | ||
232 | goto error; | ||
233 | } | ||
234 | efw->pull_ptr = efw->push_ptr = efw->resp_buf; | ||
235 | snd_efw_transaction_add_instance(efw); | ||
236 | |||
237 | err = get_hardware_info(efw); | ||
238 | if (err < 0) | ||
239 | goto error; | ||
240 | if (entry->model_id == MODEL_ECHO_AUDIOFIRE_9) | ||
241 | efw->is_af9 = true; | ||
242 | |||
243 | snd_efw_proc_init(efw); | ||
244 | |||
245 | if (efw->midi_out_ports || efw->midi_in_ports) { | ||
246 | err = snd_efw_create_midi_devices(efw); | ||
247 | if (err < 0) | ||
248 | goto error; | ||
249 | } | ||
250 | |||
251 | err = snd_efw_create_pcm_devices(efw); | ||
252 | if (err < 0) | ||
253 | goto error; | ||
254 | |||
255 | err = snd_efw_create_hwdep_device(efw); | ||
256 | if (err < 0) | ||
257 | goto error; | ||
258 | |||
259 | err = snd_efw_stream_init_duplex(efw); | ||
260 | if (err < 0) | ||
261 | goto error; | ||
262 | |||
263 | err = snd_card_register(card); | ||
264 | if (err < 0) { | ||
265 | snd_efw_stream_destroy_duplex(efw); | ||
266 | goto error; | ||
267 | } | ||
268 | |||
269 | dev_set_drvdata(&unit->device, efw); | ||
270 | end: | ||
271 | mutex_unlock(&devices_mutex); | ||
272 | return err; | ||
273 | error: | ||
274 | snd_efw_transaction_remove_instance(efw); | ||
275 | mutex_unlock(&devices_mutex); | ||
276 | snd_card_free(card); | ||
277 | return err; | ||
278 | } | ||
279 | |||
280 | static void efw_update(struct fw_unit *unit) | ||
281 | { | ||
282 | struct snd_efw *efw = dev_get_drvdata(&unit->device); | ||
283 | |||
284 | snd_efw_transaction_bus_reset(efw->unit); | ||
285 | snd_efw_stream_update_duplex(efw); | ||
286 | } | ||
287 | |||
288 | static void efw_remove(struct fw_unit *unit) | ||
289 | { | ||
290 | struct snd_efw *efw = dev_get_drvdata(&unit->device); | ||
291 | |||
292 | snd_efw_stream_destroy_duplex(efw); | ||
293 | snd_efw_transaction_remove_instance(efw); | ||
294 | |||
295 | snd_card_disconnect(efw->card); | ||
296 | snd_card_free_when_closed(efw->card); | ||
297 | } | ||
298 | |||
299 | static const struct ieee1394_device_id efw_id_table[] = { | ||
300 | SND_EFW_DEV_ENTRY(VENDOR_LOUD, MODEL_MACKIE_400F), | ||
301 | SND_EFW_DEV_ENTRY(VENDOR_LOUD, MODEL_MACKIE_1200F), | ||
302 | SND_EFW_DEV_ENTRY(VENDOR_ECHO, MODEL_ECHO_AUDIOFIRE_8), | ||
303 | SND_EFW_DEV_ENTRY(VENDOR_ECHO, MODEL_ECHO_AUDIOFIRE_12), | ||
304 | SND_EFW_DEV_ENTRY(VENDOR_ECHO, MODEL_ECHO_AUDIOFIRE_12HD), | ||
305 | SND_EFW_DEV_ENTRY(VENDOR_ECHO, MODEL_ECHO_AUDIOFIRE_12_APPLE), | ||
306 | SND_EFW_DEV_ENTRY(VENDOR_ECHO, MODEL_ECHO_AUDIOFIRE_2), | ||
307 | SND_EFW_DEV_ENTRY(VENDOR_ECHO, MODEL_ECHO_AUDIOFIRE_4), | ||
308 | SND_EFW_DEV_ENTRY(VENDOR_ECHO, MODEL_ECHO_AUDIOFIRE_9), | ||
309 | SND_EFW_DEV_ENTRY(VENDOR_ECHO, MODEL_ECHO_FIREWORKS_8), | ||
310 | SND_EFW_DEV_ENTRY(VENDOR_ECHO, MODEL_ECHO_FIREWORKS_HDMI), | ||
311 | SND_EFW_DEV_ENTRY(VENDOR_GIBSON, MODEL_GIBSON_RIP), | ||
312 | SND_EFW_DEV_ENTRY(VENDOR_GIBSON, MODEL_GIBSON_GOLDTOP), | ||
313 | {} | ||
314 | }; | ||
315 | MODULE_DEVICE_TABLE(ieee1394, efw_id_table); | ||
316 | |||
317 | static struct fw_driver efw_driver = { | ||
318 | .driver = { | ||
319 | .owner = THIS_MODULE, | ||
320 | .name = "snd-fireworks", | ||
321 | .bus = &fw_bus_type, | ||
322 | }, | ||
323 | .probe = efw_probe, | ||
324 | .update = efw_update, | ||
325 | .remove = efw_remove, | ||
326 | .id_table = efw_id_table, | ||
327 | }; | ||
328 | |||
329 | static int __init snd_efw_init(void) | ||
330 | { | ||
331 | int err; | ||
332 | |||
333 | err = snd_efw_transaction_register(); | ||
334 | if (err < 0) | ||
335 | goto end; | ||
336 | |||
337 | err = driver_register(&efw_driver.driver); | ||
338 | if (err < 0) | ||
339 | snd_efw_transaction_unregister(); | ||
340 | |||
341 | end: | ||
342 | return err; | ||
343 | } | ||
344 | |||
345 | static void __exit snd_efw_exit(void) | ||
346 | { | ||
347 | snd_efw_transaction_unregister(); | ||
348 | driver_unregister(&efw_driver.driver); | ||
349 | } | ||
350 | |||
351 | module_init(snd_efw_init); | ||
352 | module_exit(snd_efw_exit); | ||
diff --git a/sound/firewire/fireworks/fireworks.h b/sound/firewire/fireworks/fireworks.h new file mode 100644 index 000000000000..4f0201a95222 --- /dev/null +++ b/sound/firewire/fireworks/fireworks.h | |||
@@ -0,0 +1,232 @@ | |||
1 | /* | ||
2 | * fireworks.h - a part of driver for Fireworks based devices | ||
3 | * | ||
4 | * Copyright (c) 2009-2010 Clemens Ladisch | ||
5 | * Copyright (c) 2013-2014 Takashi Sakamoto | ||
6 | * | ||
7 | * Licensed under the terms of the GNU General Public License, version 2. | ||
8 | */ | ||
9 | #ifndef SOUND_FIREWORKS_H_INCLUDED | ||
10 | #define SOUND_FIREWORKS_H_INCLUDED | ||
11 | |||
12 | #include <linux/compat.h> | ||
13 | #include <linux/device.h> | ||
14 | #include <linux/firewire.h> | ||
15 | #include <linux/firewire-constants.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/mod_devicetable.h> | ||
18 | #include <linux/delay.h> | ||
19 | #include <linux/slab.h> | ||
20 | |||
21 | #include <sound/core.h> | ||
22 | #include <sound/initval.h> | ||
23 | #include <sound/pcm.h> | ||
24 | #include <sound/info.h> | ||
25 | #include <sound/rawmidi.h> | ||
26 | #include <sound/pcm_params.h> | ||
27 | #include <sound/firewire.h> | ||
28 | #include <sound/hwdep.h> | ||
29 | |||
30 | #include "../packets-buffer.h" | ||
31 | #include "../iso-resources.h" | ||
32 | #include "../amdtp.h" | ||
33 | #include "../cmp.h" | ||
34 | #include "../lib.h" | ||
35 | |||
36 | #define SND_EFW_MAX_MIDI_OUT_PORTS 2 | ||
37 | #define SND_EFW_MAX_MIDI_IN_PORTS 2 | ||
38 | |||
39 | #define SND_EFW_MULTIPLIER_MODES 3 | ||
40 | #define HWINFO_NAME_SIZE_BYTES 32 | ||
41 | #define HWINFO_MAX_CAPS_GROUPS 8 | ||
42 | |||
43 | /* | ||
44 | * This should be greater than maximum bytes for EFW response content. | ||
45 | * Currently response against command for isochronous channel mapping is | ||
46 | * confirmed to be the maximum one. But for flexibility, use maximum data | ||
47 | * payload for asynchronous primary packets at S100 (Cable base rate) in | ||
48 | * IEEE Std 1394-1995. | ||
49 | */ | ||
50 | #define SND_EFW_RESPONSE_MAXIMUM_BYTES 0x200U | ||
51 | |||
52 | extern unsigned int snd_efw_resp_buf_size; | ||
53 | extern bool snd_efw_resp_buf_debug; | ||
54 | |||
55 | struct snd_efw_phys_grp { | ||
56 | u8 type; /* see enum snd_efw_grp_type */ | ||
57 | u8 count; | ||
58 | } __packed; | ||
59 | |||
60 | struct snd_efw { | ||
61 | struct snd_card *card; | ||
62 | struct fw_unit *unit; | ||
63 | int card_index; | ||
64 | |||
65 | struct mutex mutex; | ||
66 | spinlock_t lock; | ||
67 | |||
68 | /* for transaction */ | ||
69 | u32 seqnum; | ||
70 | bool resp_addr_changable; | ||
71 | |||
72 | /* for quirks */ | ||
73 | bool is_af9; | ||
74 | u32 firmware_version; | ||
75 | |||
76 | unsigned int midi_in_ports; | ||
77 | unsigned int midi_out_ports; | ||
78 | |||
79 | unsigned int supported_sampling_rate; | ||
80 | unsigned int pcm_capture_channels[SND_EFW_MULTIPLIER_MODES]; | ||
81 | unsigned int pcm_playback_channels[SND_EFW_MULTIPLIER_MODES]; | ||
82 | |||
83 | struct amdtp_stream *master; | ||
84 | struct amdtp_stream tx_stream; | ||
85 | struct amdtp_stream rx_stream; | ||
86 | struct cmp_connection out_conn; | ||
87 | struct cmp_connection in_conn; | ||
88 | atomic_t capture_substreams; | ||
89 | atomic_t playback_substreams; | ||
90 | |||
91 | /* hardware metering parameters */ | ||
92 | unsigned int phys_out; | ||
93 | unsigned int phys_in; | ||
94 | unsigned int phys_out_grp_count; | ||
95 | unsigned int phys_in_grp_count; | ||
96 | struct snd_efw_phys_grp phys_out_grps[HWINFO_MAX_CAPS_GROUPS]; | ||
97 | struct snd_efw_phys_grp phys_in_grps[HWINFO_MAX_CAPS_GROUPS]; | ||
98 | |||
99 | /* for uapi */ | ||
100 | int dev_lock_count; | ||
101 | bool dev_lock_changed; | ||
102 | wait_queue_head_t hwdep_wait; | ||
103 | |||
104 | /* response queue */ | ||
105 | u8 *resp_buf; | ||
106 | u8 *pull_ptr; | ||
107 | u8 *push_ptr; | ||
108 | unsigned int resp_queues; | ||
109 | }; | ||
110 | |||
111 | int snd_efw_transaction_cmd(struct fw_unit *unit, | ||
112 | const void *cmd, unsigned int size); | ||
113 | int snd_efw_transaction_run(struct fw_unit *unit, | ||
114 | const void *cmd, unsigned int cmd_size, | ||
115 | void *resp, unsigned int resp_size); | ||
116 | int snd_efw_transaction_register(void); | ||
117 | void snd_efw_transaction_unregister(void); | ||
118 | void snd_efw_transaction_bus_reset(struct fw_unit *unit); | ||
119 | void snd_efw_transaction_add_instance(struct snd_efw *efw); | ||
120 | void snd_efw_transaction_remove_instance(struct snd_efw *efw); | ||
121 | |||
122 | struct snd_efw_hwinfo { | ||
123 | u32 flags; | ||
124 | u32 guid_hi; | ||
125 | u32 guid_lo; | ||
126 | u32 type; | ||
127 | u32 version; | ||
128 | char vendor_name[HWINFO_NAME_SIZE_BYTES]; | ||
129 | char model_name[HWINFO_NAME_SIZE_BYTES]; | ||
130 | u32 supported_clocks; | ||
131 | u32 amdtp_rx_pcm_channels; | ||
132 | u32 amdtp_tx_pcm_channels; | ||
133 | u32 phys_out; | ||
134 | u32 phys_in; | ||
135 | u32 phys_out_grp_count; | ||
136 | struct snd_efw_phys_grp phys_out_grps[HWINFO_MAX_CAPS_GROUPS]; | ||
137 | u32 phys_in_grp_count; | ||
138 | struct snd_efw_phys_grp phys_in_grps[HWINFO_MAX_CAPS_GROUPS]; | ||
139 | u32 midi_out_ports; | ||
140 | u32 midi_in_ports; | ||
141 | u32 max_sample_rate; | ||
142 | u32 min_sample_rate; | ||
143 | u32 dsp_version; | ||
144 | u32 arm_version; | ||
145 | u32 mixer_playback_channels; | ||
146 | u32 mixer_capture_channels; | ||
147 | u32 fpga_version; | ||
148 | u32 amdtp_rx_pcm_channels_2x; | ||
149 | u32 amdtp_tx_pcm_channels_2x; | ||
150 | u32 amdtp_rx_pcm_channels_4x; | ||
151 | u32 amdtp_tx_pcm_channels_4x; | ||
152 | u32 reserved[16]; | ||
153 | } __packed; | ||
154 | enum snd_efw_grp_type { | ||
155 | SND_EFW_CH_TYPE_ANALOG = 0, | ||
156 | SND_EFW_CH_TYPE_SPDIF = 1, | ||
157 | SND_EFW_CH_TYPE_ADAT = 2, | ||
158 | SND_EFW_CH_TYPE_SPDIF_OR_ADAT = 3, | ||
159 | SND_EFW_CH_TYPE_ANALOG_MIRRORING = 4, | ||
160 | SND_EFW_CH_TYPE_HEADPHONES = 5, | ||
161 | SND_EFW_CH_TYPE_I2S = 6, | ||
162 | SND_EFW_CH_TYPE_GUITAR = 7, | ||
163 | SND_EFW_CH_TYPE_PIEZO_GUITAR = 8, | ||
164 | SND_EFW_CH_TYPE_GUITAR_STRING = 9, | ||
165 | SND_EFW_CH_TYPE_DUMMY | ||
166 | }; | ||
167 | struct snd_efw_phys_meters { | ||
168 | u32 status; /* guitar state/midi signal/clock input detect */ | ||
169 | u32 reserved0; | ||
170 | u32 reserved1; | ||
171 | u32 reserved2; | ||
172 | u32 reserved3; | ||
173 | u32 out_meters; | ||
174 | u32 in_meters; | ||
175 | u32 reserved4; | ||
176 | u32 reserved5; | ||
177 | u32 values[0]; | ||
178 | } __packed; | ||
179 | enum snd_efw_clock_source { | ||
180 | SND_EFW_CLOCK_SOURCE_INTERNAL = 0, | ||
181 | SND_EFW_CLOCK_SOURCE_SYTMATCH = 1, | ||
182 | SND_EFW_CLOCK_SOURCE_WORDCLOCK = 2, | ||
183 | SND_EFW_CLOCK_SOURCE_SPDIF = 3, | ||
184 | SND_EFW_CLOCK_SOURCE_ADAT_1 = 4, | ||
185 | SND_EFW_CLOCK_SOURCE_ADAT_2 = 5, | ||
186 | SND_EFW_CLOCK_SOURCE_CONTINUOUS = 6 /* internal variable clock */ | ||
187 | }; | ||
188 | enum snd_efw_transport_mode { | ||
189 | SND_EFW_TRANSPORT_MODE_WINDOWS = 0, | ||
190 | SND_EFW_TRANSPORT_MODE_IEC61883 = 1, | ||
191 | }; | ||
192 | int snd_efw_command_set_resp_addr(struct snd_efw *efw, | ||
193 | u16 addr_high, u32 addr_low); | ||
194 | int snd_efw_command_set_tx_mode(struct snd_efw *efw, | ||
195 | enum snd_efw_transport_mode mode); | ||
196 | int snd_efw_command_get_hwinfo(struct snd_efw *efw, | ||
197 | struct snd_efw_hwinfo *hwinfo); | ||
198 | int snd_efw_command_get_phys_meters(struct snd_efw *efw, | ||
199 | struct snd_efw_phys_meters *meters, | ||
200 | unsigned int len); | ||
201 | int snd_efw_command_get_clock_source(struct snd_efw *efw, | ||
202 | enum snd_efw_clock_source *source); | ||
203 | int snd_efw_command_get_sampling_rate(struct snd_efw *efw, unsigned int *rate); | ||
204 | int snd_efw_command_set_sampling_rate(struct snd_efw *efw, unsigned int rate); | ||
205 | |||
206 | int snd_efw_stream_init_duplex(struct snd_efw *efw); | ||
207 | int snd_efw_stream_start_duplex(struct snd_efw *efw, unsigned int rate); | ||
208 | void snd_efw_stream_stop_duplex(struct snd_efw *efw); | ||
209 | void snd_efw_stream_update_duplex(struct snd_efw *efw); | ||
210 | void snd_efw_stream_destroy_duplex(struct snd_efw *efw); | ||
211 | void snd_efw_stream_lock_changed(struct snd_efw *efw); | ||
212 | int snd_efw_stream_lock_try(struct snd_efw *efw); | ||
213 | void snd_efw_stream_lock_release(struct snd_efw *efw); | ||
214 | |||
215 | void snd_efw_proc_init(struct snd_efw *efw); | ||
216 | |||
217 | int snd_efw_create_midi_devices(struct snd_efw *efw); | ||
218 | |||
219 | int snd_efw_create_pcm_devices(struct snd_efw *efw); | ||
220 | int snd_efw_get_multiplier_mode(unsigned int sampling_rate, unsigned int *mode); | ||
221 | |||
222 | int snd_efw_create_hwdep_device(struct snd_efw *efw); | ||
223 | |||
224 | #define SND_EFW_DEV_ENTRY(vendor, model) \ | ||
225 | { \ | ||
226 | .match_flags = IEEE1394_MATCH_VENDOR_ID | \ | ||
227 | IEEE1394_MATCH_MODEL_ID, \ | ||
228 | .vendor_id = vendor,\ | ||
229 | .model_id = model \ | ||
230 | } | ||
231 | |||
232 | #endif | ||
diff --git a/sound/firewire/fireworks/fireworks_command.c b/sound/firewire/fireworks/fireworks_command.c new file mode 100644 index 000000000000..166f80584c2a --- /dev/null +++ b/sound/firewire/fireworks/fireworks_command.c | |||
@@ -0,0 +1,372 @@ | |||
1 | /* | ||
2 | * fireworks_command.c - a part of driver for Fireworks based devices | ||
3 | * | ||
4 | * Copyright (c) 2013-2014 Takashi Sakamoto | ||
5 | * | ||
6 | * Licensed under the terms of the GNU General Public License, version 2. | ||
7 | */ | ||
8 | |||
9 | #include "./fireworks.h" | ||
10 | |||
11 | /* | ||
12 | * This driver uses transaction version 1 or later to use extended hardware | ||
13 | * information. Then too old devices are not available. | ||
14 | * | ||
15 | * Each commands are not required to have continuous sequence numbers. This | ||
16 | * number is just used to match command and response. | ||
17 | * | ||
18 | * This module support a part of commands. Please see FFADO if you want to see | ||
19 | * whole commands. But there are some commands which FFADO don't implement. | ||
20 | * | ||
21 | * Fireworks also supports AV/C general commands and AV/C Stream Format | ||
22 | * Information commands. But this module don't use them. | ||
23 | */ | ||
24 | |||
25 | #define KERNEL_SEQNUM_MIN (SND_EFW_TRANSACTION_USER_SEQNUM_MAX + 2) | ||
26 | #define KERNEL_SEQNUM_MAX ((u32)~0) | ||
27 | |||
28 | /* for clock source and sampling rate */ | ||
29 | struct efc_clock { | ||
30 | u32 source; | ||
31 | u32 sampling_rate; | ||
32 | u32 index; | ||
33 | }; | ||
34 | |||
35 | /* command categories */ | ||
36 | enum efc_category { | ||
37 | EFC_CAT_HWINFO = 0, | ||
38 | EFC_CAT_TRANSPORT = 2, | ||
39 | EFC_CAT_HWCTL = 3, | ||
40 | }; | ||
41 | |||
42 | /* hardware info category commands */ | ||
43 | enum efc_cmd_hwinfo { | ||
44 | EFC_CMD_HWINFO_GET_CAPS = 0, | ||
45 | EFC_CMD_HWINFO_GET_POLLED = 1, | ||
46 | EFC_CMD_HWINFO_SET_RESP_ADDR = 2 | ||
47 | }; | ||
48 | |||
49 | enum efc_cmd_transport { | ||
50 | EFC_CMD_TRANSPORT_SET_TX_MODE = 0 | ||
51 | }; | ||
52 | |||
53 | /* hardware control category commands */ | ||
54 | enum efc_cmd_hwctl { | ||
55 | EFC_CMD_HWCTL_SET_CLOCK = 0, | ||
56 | EFC_CMD_HWCTL_GET_CLOCK = 1, | ||
57 | EFC_CMD_HWCTL_IDENTIFY = 5 | ||
58 | }; | ||
59 | |||
60 | /* return values in response */ | ||
61 | enum efr_status { | ||
62 | EFR_STATUS_OK = 0, | ||
63 | EFR_STATUS_BAD = 1, | ||
64 | EFR_STATUS_BAD_COMMAND = 2, | ||
65 | EFR_STATUS_COMM_ERR = 3, | ||
66 | EFR_STATUS_BAD_QUAD_COUNT = 4, | ||
67 | EFR_STATUS_UNSUPPORTED = 5, | ||
68 | EFR_STATUS_1394_TIMEOUT = 6, | ||
69 | EFR_STATUS_DSP_TIMEOUT = 7, | ||
70 | EFR_STATUS_BAD_RATE = 8, | ||
71 | EFR_STATUS_BAD_CLOCK = 9, | ||
72 | EFR_STATUS_BAD_CHANNEL = 10, | ||
73 | EFR_STATUS_BAD_PAN = 11, | ||
74 | EFR_STATUS_FLASH_BUSY = 12, | ||
75 | EFR_STATUS_BAD_MIRROR = 13, | ||
76 | EFR_STATUS_BAD_LED = 14, | ||
77 | EFR_STATUS_BAD_PARAMETER = 15, | ||
78 | EFR_STATUS_INCOMPLETE = 0x80000000 | ||
79 | }; | ||
80 | |||
81 | static const char *const efr_status_names[] = { | ||
82 | [EFR_STATUS_OK] = "OK", | ||
83 | [EFR_STATUS_BAD] = "bad", | ||
84 | [EFR_STATUS_BAD_COMMAND] = "bad command", | ||
85 | [EFR_STATUS_COMM_ERR] = "comm err", | ||
86 | [EFR_STATUS_BAD_QUAD_COUNT] = "bad quad count", | ||
87 | [EFR_STATUS_UNSUPPORTED] = "unsupported", | ||
88 | [EFR_STATUS_1394_TIMEOUT] = "1394 timeout", | ||
89 | [EFR_STATUS_DSP_TIMEOUT] = "DSP timeout", | ||
90 | [EFR_STATUS_BAD_RATE] = "bad rate", | ||
91 | [EFR_STATUS_BAD_CLOCK] = "bad clock", | ||
92 | [EFR_STATUS_BAD_CHANNEL] = "bad channel", | ||
93 | [EFR_STATUS_BAD_PAN] = "bad pan", | ||
94 | [EFR_STATUS_FLASH_BUSY] = "flash busy", | ||
95 | [EFR_STATUS_BAD_MIRROR] = "bad mirror", | ||
96 | [EFR_STATUS_BAD_LED] = "bad LED", | ||
97 | [EFR_STATUS_BAD_PARAMETER] = "bad parameter", | ||
98 | [EFR_STATUS_BAD_PARAMETER + 1] = "incomplete" | ||
99 | }; | ||
100 | |||
101 | static int | ||
102 | efw_transaction(struct snd_efw *efw, unsigned int category, | ||
103 | unsigned int command, | ||
104 | const __be32 *params, unsigned int param_bytes, | ||
105 | const __be32 *resp, unsigned int resp_bytes) | ||
106 | { | ||
107 | struct snd_efw_transaction *header; | ||
108 | __be32 *buf; | ||
109 | u32 seqnum; | ||
110 | unsigned int buf_bytes, cmd_bytes; | ||
111 | int err; | ||
112 | |||
113 | /* calculate buffer size*/ | ||
114 | buf_bytes = sizeof(struct snd_efw_transaction) + | ||
115 | max(param_bytes, resp_bytes); | ||
116 | |||
117 | /* keep buffer */ | ||
118 | buf = kzalloc(buf_bytes, GFP_KERNEL); | ||
119 | if (buf == NULL) | ||
120 | return -ENOMEM; | ||
121 | |||
122 | /* to keep consistency of sequence number */ | ||
123 | spin_lock(&efw->lock); | ||
124 | if ((efw->seqnum < KERNEL_SEQNUM_MIN) || | ||
125 | (efw->seqnum >= KERNEL_SEQNUM_MAX - 2)) | ||
126 | efw->seqnum = KERNEL_SEQNUM_MIN; | ||
127 | else | ||
128 | efw->seqnum += 2; | ||
129 | seqnum = efw->seqnum; | ||
130 | spin_unlock(&efw->lock); | ||
131 | |||
132 | /* fill transaction header fields */ | ||
133 | cmd_bytes = sizeof(struct snd_efw_transaction) + param_bytes; | ||
134 | header = (struct snd_efw_transaction *)buf; | ||
135 | header->length = cpu_to_be32(cmd_bytes / sizeof(__be32)); | ||
136 | header->version = cpu_to_be32(1); | ||
137 | header->seqnum = cpu_to_be32(seqnum); | ||
138 | header->category = cpu_to_be32(category); | ||
139 | header->command = cpu_to_be32(command); | ||
140 | header->status = 0; | ||
141 | |||
142 | /* fill transaction command parameters */ | ||
143 | memcpy(header->params, params, param_bytes); | ||
144 | |||
145 | err = snd_efw_transaction_run(efw->unit, buf, cmd_bytes, | ||
146 | buf, buf_bytes); | ||
147 | if (err < 0) | ||
148 | goto end; | ||
149 | |||
150 | /* check transaction header fields */ | ||
151 | if ((be32_to_cpu(header->version) < 1) || | ||
152 | (be32_to_cpu(header->category) != category) || | ||
153 | (be32_to_cpu(header->command) != command) || | ||
154 | (be32_to_cpu(header->status) != EFR_STATUS_OK)) { | ||
155 | dev_err(&efw->unit->device, "EFW command failed [%u/%u]: %s\n", | ||
156 | be32_to_cpu(header->category), | ||
157 | be32_to_cpu(header->command), | ||
158 | efr_status_names[be32_to_cpu(header->status)]); | ||
159 | err = -EIO; | ||
160 | goto end; | ||
161 | } | ||
162 | |||
163 | if (resp == NULL) | ||
164 | goto end; | ||
165 | |||
166 | /* fill transaction response parameters */ | ||
167 | memset((void *)resp, 0, resp_bytes); | ||
168 | resp_bytes = min_t(unsigned int, resp_bytes, | ||
169 | be32_to_cpu(header->length) * sizeof(__be32) - | ||
170 | sizeof(struct snd_efw_transaction)); | ||
171 | memcpy((void *)resp, &buf[6], resp_bytes); | ||
172 | end: | ||
173 | kfree(buf); | ||
174 | return err; | ||
175 | } | ||
176 | |||
177 | /* | ||
178 | * The address in host system for transaction response is changable when the | ||
179 | * device supports. struct hwinfo.flags includes its flag. The default is | ||
180 | * MEMORY_SPACE_EFW_RESPONSE. | ||
181 | */ | ||
182 | int snd_efw_command_set_resp_addr(struct snd_efw *efw, | ||
183 | u16 addr_high, u32 addr_low) | ||
184 | { | ||
185 | __be32 addr[2]; | ||
186 | |||
187 | addr[0] = cpu_to_be32(addr_high); | ||
188 | addr[1] = cpu_to_be32(addr_low); | ||
189 | |||
190 | if (!efw->resp_addr_changable) | ||
191 | return -ENOSYS; | ||
192 | |||
193 | return efw_transaction(efw, EFC_CAT_HWCTL, | ||
194 | EFC_CMD_HWINFO_SET_RESP_ADDR, | ||
195 | addr, sizeof(addr), NULL, 0); | ||
196 | } | ||
197 | |||
198 | /* | ||
199 | * This is for timestamp processing. In Windows mode, all 32bit fields of second | ||
200 | * CIP header in AMDTP transmit packet is used for 'presentation timestamp'. In | ||
201 | * 'no data' packet the value of this field is 0x90ffffff. | ||
202 | */ | ||
203 | int snd_efw_command_set_tx_mode(struct snd_efw *efw, | ||
204 | enum snd_efw_transport_mode mode) | ||
205 | { | ||
206 | __be32 param = cpu_to_be32(mode); | ||
207 | return efw_transaction(efw, EFC_CAT_TRANSPORT, | ||
208 | EFC_CMD_TRANSPORT_SET_TX_MODE, | ||
209 | ¶m, sizeof(param), NULL, 0); | ||
210 | } | ||
211 | |||
212 | int snd_efw_command_get_hwinfo(struct snd_efw *efw, | ||
213 | struct snd_efw_hwinfo *hwinfo) | ||
214 | { | ||
215 | int err; | ||
216 | |||
217 | err = efw_transaction(efw, EFC_CAT_HWINFO, | ||
218 | EFC_CMD_HWINFO_GET_CAPS, | ||
219 | NULL, 0, (__be32 *)hwinfo, sizeof(*hwinfo)); | ||
220 | if (err < 0) | ||
221 | goto end; | ||
222 | |||
223 | be32_to_cpus(&hwinfo->flags); | ||
224 | be32_to_cpus(&hwinfo->guid_hi); | ||
225 | be32_to_cpus(&hwinfo->guid_lo); | ||
226 | be32_to_cpus(&hwinfo->type); | ||
227 | be32_to_cpus(&hwinfo->version); | ||
228 | be32_to_cpus(&hwinfo->supported_clocks); | ||
229 | be32_to_cpus(&hwinfo->amdtp_rx_pcm_channels); | ||
230 | be32_to_cpus(&hwinfo->amdtp_tx_pcm_channels); | ||
231 | be32_to_cpus(&hwinfo->phys_out); | ||
232 | be32_to_cpus(&hwinfo->phys_in); | ||
233 | be32_to_cpus(&hwinfo->phys_out_grp_count); | ||
234 | be32_to_cpus(&hwinfo->phys_in_grp_count); | ||
235 | be32_to_cpus(&hwinfo->midi_out_ports); | ||
236 | be32_to_cpus(&hwinfo->midi_in_ports); | ||
237 | be32_to_cpus(&hwinfo->max_sample_rate); | ||
238 | be32_to_cpus(&hwinfo->min_sample_rate); | ||
239 | be32_to_cpus(&hwinfo->dsp_version); | ||
240 | be32_to_cpus(&hwinfo->arm_version); | ||
241 | be32_to_cpus(&hwinfo->mixer_playback_channels); | ||
242 | be32_to_cpus(&hwinfo->mixer_capture_channels); | ||
243 | be32_to_cpus(&hwinfo->fpga_version); | ||
244 | be32_to_cpus(&hwinfo->amdtp_rx_pcm_channels_2x); | ||
245 | be32_to_cpus(&hwinfo->amdtp_tx_pcm_channels_2x); | ||
246 | be32_to_cpus(&hwinfo->amdtp_rx_pcm_channels_4x); | ||
247 | be32_to_cpus(&hwinfo->amdtp_tx_pcm_channels_4x); | ||
248 | |||
249 | /* ensure terminated */ | ||
250 | hwinfo->vendor_name[HWINFO_NAME_SIZE_BYTES - 1] = '\0'; | ||
251 | hwinfo->model_name[HWINFO_NAME_SIZE_BYTES - 1] = '\0'; | ||
252 | end: | ||
253 | return err; | ||
254 | } | ||
255 | |||
256 | int snd_efw_command_get_phys_meters(struct snd_efw *efw, | ||
257 | struct snd_efw_phys_meters *meters, | ||
258 | unsigned int len) | ||
259 | { | ||
260 | __be32 *buf = (__be32 *)meters; | ||
261 | unsigned int i; | ||
262 | int err; | ||
263 | |||
264 | err = efw_transaction(efw, EFC_CAT_HWINFO, | ||
265 | EFC_CMD_HWINFO_GET_POLLED, | ||
266 | NULL, 0, (__be32 *)meters, len); | ||
267 | if (err >= 0) | ||
268 | for (i = 0; i < len / sizeof(u32); i++) | ||
269 | be32_to_cpus(&buf[i]); | ||
270 | |||
271 | return err; | ||
272 | } | ||
273 | |||
274 | static int | ||
275 | command_get_clock(struct snd_efw *efw, struct efc_clock *clock) | ||
276 | { | ||
277 | int err; | ||
278 | |||
279 | err = efw_transaction(efw, EFC_CAT_HWCTL, | ||
280 | EFC_CMD_HWCTL_GET_CLOCK, | ||
281 | NULL, 0, | ||
282 | (__be32 *)clock, sizeof(struct efc_clock)); | ||
283 | if (err >= 0) { | ||
284 | be32_to_cpus(&clock->source); | ||
285 | be32_to_cpus(&clock->sampling_rate); | ||
286 | be32_to_cpus(&clock->index); | ||
287 | } | ||
288 | |||
289 | return err; | ||
290 | } | ||
291 | |||
292 | /* give UINT_MAX if set nothing */ | ||
293 | static int | ||
294 | command_set_clock(struct snd_efw *efw, | ||
295 | unsigned int source, unsigned int rate) | ||
296 | { | ||
297 | struct efc_clock clock = {0}; | ||
298 | int err; | ||
299 | |||
300 | /* check arguments */ | ||
301 | if ((source == UINT_MAX) && (rate == UINT_MAX)) { | ||
302 | err = -EINVAL; | ||
303 | goto end; | ||
304 | } | ||
305 | |||
306 | /* get current status */ | ||
307 | err = command_get_clock(efw, &clock); | ||
308 | if (err < 0) | ||
309 | goto end; | ||
310 | |||
311 | /* no need */ | ||
312 | if ((clock.source == source) && (clock.sampling_rate == rate)) | ||
313 | goto end; | ||
314 | |||
315 | /* set params */ | ||
316 | if ((source != UINT_MAX) && (clock.source != source)) | ||
317 | clock.source = source; | ||
318 | if ((rate != UINT_MAX) && (clock.sampling_rate != rate)) | ||
319 | clock.sampling_rate = rate; | ||
320 | clock.index = 0; | ||
321 | |||
322 | cpu_to_be32s(&clock.source); | ||
323 | cpu_to_be32s(&clock.sampling_rate); | ||
324 | cpu_to_be32s(&clock.index); | ||
325 | |||
326 | err = efw_transaction(efw, EFC_CAT_HWCTL, | ||
327 | EFC_CMD_HWCTL_SET_CLOCK, | ||
328 | (__be32 *)&clock, sizeof(struct efc_clock), | ||
329 | NULL, 0); | ||
330 | if (err < 0) | ||
331 | goto end; | ||
332 | |||
333 | /* | ||
334 | * With firmware version 5.8, just after changing clock state, these | ||
335 | * parameters are not immediately retrieved by get command. In my | ||
336 | * trial, there needs to be 100msec to get changed parameters. | ||
337 | */ | ||
338 | msleep(150); | ||
339 | end: | ||
340 | return err; | ||
341 | } | ||
342 | |||
343 | int snd_efw_command_get_clock_source(struct snd_efw *efw, | ||
344 | enum snd_efw_clock_source *source) | ||
345 | { | ||
346 | int err; | ||
347 | struct efc_clock clock = {0}; | ||
348 | |||
349 | err = command_get_clock(efw, &clock); | ||
350 | if (err >= 0) | ||
351 | *source = clock.source; | ||
352 | |||
353 | return err; | ||
354 | } | ||
355 | |||
356 | int snd_efw_command_get_sampling_rate(struct snd_efw *efw, unsigned int *rate) | ||
357 | { | ||
358 | int err; | ||
359 | struct efc_clock clock = {0}; | ||
360 | |||
361 | err = command_get_clock(efw, &clock); | ||
362 | if (err >= 0) | ||
363 | *rate = clock.sampling_rate; | ||
364 | |||
365 | return err; | ||
366 | } | ||
367 | |||
368 | int snd_efw_command_set_sampling_rate(struct snd_efw *efw, unsigned int rate) | ||
369 | { | ||
370 | return command_set_clock(efw, UINT_MAX, rate); | ||
371 | } | ||
372 | |||
diff --git a/sound/firewire/fireworks/fireworks_hwdep.c b/sound/firewire/fireworks/fireworks_hwdep.c new file mode 100644 index 000000000000..33df8655fe81 --- /dev/null +++ b/sound/firewire/fireworks/fireworks_hwdep.c | |||
@@ -0,0 +1,298 @@ | |||
1 | /* | ||
2 | * fireworks_hwdep.c - a part of driver for Fireworks based devices | ||
3 | * | ||
4 | * Copyright (c) 2013-2014 Takashi Sakamoto | ||
5 | * | ||
6 | * Licensed under the terms of the GNU General Public License, version 2. | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * This codes have five functionalities. | ||
11 | * | ||
12 | * 1.get information about firewire node | ||
13 | * 2.get notification about starting/stopping stream | ||
14 | * 3.lock/unlock streaming | ||
15 | * 4.transmit command of EFW transaction | ||
16 | * 5.receive response of EFW transaction | ||
17 | * | ||
18 | */ | ||
19 | |||
20 | #include "fireworks.h" | ||
21 | |||
22 | static long | ||
23 | hwdep_read_resp_buf(struct snd_efw *efw, char __user *buf, long remained, | ||
24 | loff_t *offset) | ||
25 | { | ||
26 | unsigned int length, till_end, type; | ||
27 | struct snd_efw_transaction *t; | ||
28 | long count = 0; | ||
29 | |||
30 | if (remained < sizeof(type) + sizeof(struct snd_efw_transaction)) | ||
31 | return -ENOSPC; | ||
32 | |||
33 | /* data type is SNDRV_FIREWIRE_EVENT_EFW_RESPONSE */ | ||
34 | type = SNDRV_FIREWIRE_EVENT_EFW_RESPONSE; | ||
35 | if (copy_to_user(buf, &type, sizeof(type))) | ||
36 | return -EFAULT; | ||
37 | remained -= sizeof(type); | ||
38 | buf += sizeof(type); | ||
39 | |||
40 | /* write into buffer as many responses as possible */ | ||
41 | while (efw->resp_queues > 0) { | ||
42 | t = (struct snd_efw_transaction *)(efw->pull_ptr); | ||
43 | length = be32_to_cpu(t->length) * sizeof(__be32); | ||
44 | |||
45 | /* confirm enough space for this response */ | ||
46 | if (remained < length) | ||
47 | break; | ||
48 | |||
49 | /* copy from ring buffer to user buffer */ | ||
50 | while (length > 0) { | ||
51 | till_end = snd_efw_resp_buf_size - | ||
52 | (unsigned int)(efw->pull_ptr - efw->resp_buf); | ||
53 | till_end = min_t(unsigned int, length, till_end); | ||
54 | |||
55 | if (copy_to_user(buf, efw->pull_ptr, till_end)) | ||
56 | return -EFAULT; | ||
57 | |||
58 | efw->pull_ptr += till_end; | ||
59 | if (efw->pull_ptr >= efw->resp_buf + | ||
60 | snd_efw_resp_buf_size) | ||
61 | efw->pull_ptr -= snd_efw_resp_buf_size; | ||
62 | |||
63 | length -= till_end; | ||
64 | buf += till_end; | ||
65 | count += till_end; | ||
66 | remained -= till_end; | ||
67 | } | ||
68 | |||
69 | efw->resp_queues--; | ||
70 | } | ||
71 | |||
72 | return count; | ||
73 | } | ||
74 | |||
75 | static long | ||
76 | hwdep_read_locked(struct snd_efw *efw, char __user *buf, long count, | ||
77 | loff_t *offset) | ||
78 | { | ||
79 | union snd_firewire_event event; | ||
80 | |||
81 | memset(&event, 0, sizeof(event)); | ||
82 | |||
83 | event.lock_status.type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS; | ||
84 | event.lock_status.status = (efw->dev_lock_count > 0); | ||
85 | efw->dev_lock_changed = false; | ||
86 | |||
87 | count = min_t(long, count, sizeof(event.lock_status)); | ||
88 | |||
89 | if (copy_to_user(buf, &event, count)) | ||
90 | return -EFAULT; | ||
91 | |||
92 | return count; | ||
93 | } | ||
94 | |||
95 | static long | ||
96 | hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count, | ||
97 | loff_t *offset) | ||
98 | { | ||
99 | struct snd_efw *efw = hwdep->private_data; | ||
100 | DEFINE_WAIT(wait); | ||
101 | |||
102 | spin_lock_irq(&efw->lock); | ||
103 | |||
104 | while ((!efw->dev_lock_changed) && (efw->resp_queues == 0)) { | ||
105 | prepare_to_wait(&efw->hwdep_wait, &wait, TASK_INTERRUPTIBLE); | ||
106 | spin_unlock_irq(&efw->lock); | ||
107 | schedule(); | ||
108 | finish_wait(&efw->hwdep_wait, &wait); | ||
109 | if (signal_pending(current)) | ||
110 | return -ERESTARTSYS; | ||
111 | spin_lock_irq(&efw->lock); | ||
112 | } | ||
113 | |||
114 | if (efw->dev_lock_changed) | ||
115 | count = hwdep_read_locked(efw, buf, count, offset); | ||
116 | else if (efw->resp_queues > 0) | ||
117 | count = hwdep_read_resp_buf(efw, buf, count, offset); | ||
118 | |||
119 | spin_unlock_irq(&efw->lock); | ||
120 | |||
121 | return count; | ||
122 | } | ||
123 | |||
124 | static long | ||
125 | hwdep_write(struct snd_hwdep *hwdep, const char __user *data, long count, | ||
126 | loff_t *offset) | ||
127 | { | ||
128 | struct snd_efw *efw = hwdep->private_data; | ||
129 | u32 seqnum; | ||
130 | u8 *buf; | ||
131 | |||
132 | if (count < sizeof(struct snd_efw_transaction) || | ||
133 | SND_EFW_RESPONSE_MAXIMUM_BYTES < count) | ||
134 | return -EINVAL; | ||
135 | |||
136 | buf = memdup_user(data, count); | ||
137 | if (IS_ERR(buf)) | ||
138 | return PTR_ERR(buf); | ||
139 | |||
140 | /* check seqnum is not for kernel-land */ | ||
141 | seqnum = be32_to_cpu(((struct snd_efw_transaction *)buf)->seqnum); | ||
142 | if (seqnum > SND_EFW_TRANSACTION_USER_SEQNUM_MAX) { | ||
143 | count = -EINVAL; | ||
144 | goto end; | ||
145 | } | ||
146 | |||
147 | if (snd_efw_transaction_cmd(efw->unit, buf, count) < 0) | ||
148 | count = -EIO; | ||
149 | end: | ||
150 | kfree(buf); | ||
151 | return count; | ||
152 | } | ||
153 | |||
154 | static unsigned int | ||
155 | hwdep_poll(struct snd_hwdep *hwdep, struct file *file, poll_table *wait) | ||
156 | { | ||
157 | struct snd_efw *efw = hwdep->private_data; | ||
158 | unsigned int events; | ||
159 | |||
160 | poll_wait(file, &efw->hwdep_wait, wait); | ||
161 | |||
162 | spin_lock_irq(&efw->lock); | ||
163 | if (efw->dev_lock_changed || (efw->resp_queues > 0)) | ||
164 | events = POLLIN | POLLRDNORM; | ||
165 | else | ||
166 | events = 0; | ||
167 | spin_unlock_irq(&efw->lock); | ||
168 | |||
169 | return events | POLLOUT; | ||
170 | } | ||
171 | |||
172 | static int | ||
173 | hwdep_get_info(struct snd_efw *efw, void __user *arg) | ||
174 | { | ||
175 | struct fw_device *dev = fw_parent_device(efw->unit); | ||
176 | struct snd_firewire_get_info info; | ||
177 | |||
178 | memset(&info, 0, sizeof(info)); | ||
179 | info.type = SNDRV_FIREWIRE_TYPE_FIREWORKS; | ||
180 | info.card = dev->card->index; | ||
181 | *(__be32 *)&info.guid[0] = cpu_to_be32(dev->config_rom[3]); | ||
182 | *(__be32 *)&info.guid[4] = cpu_to_be32(dev->config_rom[4]); | ||
183 | strlcpy(info.device_name, dev_name(&dev->device), | ||
184 | sizeof(info.device_name)); | ||
185 | |||
186 | if (copy_to_user(arg, &info, sizeof(info))) | ||
187 | return -EFAULT; | ||
188 | |||
189 | return 0; | ||
190 | } | ||
191 | |||
192 | static int | ||
193 | hwdep_lock(struct snd_efw *efw) | ||
194 | { | ||
195 | int err; | ||
196 | |||
197 | spin_lock_irq(&efw->lock); | ||
198 | |||
199 | if (efw->dev_lock_count == 0) { | ||
200 | efw->dev_lock_count = -1; | ||
201 | err = 0; | ||
202 | } else { | ||
203 | err = -EBUSY; | ||
204 | } | ||
205 | |||
206 | spin_unlock_irq(&efw->lock); | ||
207 | |||
208 | return err; | ||
209 | } | ||
210 | |||
211 | static int | ||
212 | hwdep_unlock(struct snd_efw *efw) | ||
213 | { | ||
214 | int err; | ||
215 | |||
216 | spin_lock_irq(&efw->lock); | ||
217 | |||
218 | if (efw->dev_lock_count == -1) { | ||
219 | efw->dev_lock_count = 0; | ||
220 | err = 0; | ||
221 | } else { | ||
222 | err = -EBADFD; | ||
223 | } | ||
224 | |||
225 | spin_unlock_irq(&efw->lock); | ||
226 | |||
227 | return err; | ||
228 | } | ||
229 | |||
230 | static int | ||
231 | hwdep_release(struct snd_hwdep *hwdep, struct file *file) | ||
232 | { | ||
233 | struct snd_efw *efw = hwdep->private_data; | ||
234 | |||
235 | spin_lock_irq(&efw->lock); | ||
236 | if (efw->dev_lock_count == -1) | ||
237 | efw->dev_lock_count = 0; | ||
238 | spin_unlock_irq(&efw->lock); | ||
239 | |||
240 | return 0; | ||
241 | } | ||
242 | |||
243 | static int | ||
244 | hwdep_ioctl(struct snd_hwdep *hwdep, struct file *file, | ||
245 | unsigned int cmd, unsigned long arg) | ||
246 | { | ||
247 | struct snd_efw *efw = hwdep->private_data; | ||
248 | |||
249 | switch (cmd) { | ||
250 | case SNDRV_FIREWIRE_IOCTL_GET_INFO: | ||
251 | return hwdep_get_info(efw, (void __user *)arg); | ||
252 | case SNDRV_FIREWIRE_IOCTL_LOCK: | ||
253 | return hwdep_lock(efw); | ||
254 | case SNDRV_FIREWIRE_IOCTL_UNLOCK: | ||
255 | return hwdep_unlock(efw); | ||
256 | default: | ||
257 | return -ENOIOCTLCMD; | ||
258 | } | ||
259 | } | ||
260 | |||
261 | #ifdef CONFIG_COMPAT | ||
262 | static int | ||
263 | hwdep_compat_ioctl(struct snd_hwdep *hwdep, struct file *file, | ||
264 | unsigned int cmd, unsigned long arg) | ||
265 | { | ||
266 | return hwdep_ioctl(hwdep, file, cmd, | ||
267 | (unsigned long)compat_ptr(arg)); | ||
268 | } | ||
269 | #else | ||
270 | #define hwdep_compat_ioctl NULL | ||
271 | #endif | ||
272 | |||
273 | static const struct snd_hwdep_ops hwdep_ops = { | ||
274 | .read = hwdep_read, | ||
275 | .write = hwdep_write, | ||
276 | .release = hwdep_release, | ||
277 | .poll = hwdep_poll, | ||
278 | .ioctl = hwdep_ioctl, | ||
279 | .ioctl_compat = hwdep_compat_ioctl, | ||
280 | }; | ||
281 | |||
282 | int snd_efw_create_hwdep_device(struct snd_efw *efw) | ||
283 | { | ||
284 | struct snd_hwdep *hwdep; | ||
285 | int err; | ||
286 | |||
287 | err = snd_hwdep_new(efw->card, "Fireworks", 0, &hwdep); | ||
288 | if (err < 0) | ||
289 | goto end; | ||
290 | strcpy(hwdep->name, "Fireworks"); | ||
291 | hwdep->iface = SNDRV_HWDEP_IFACE_FW_FIREWORKS; | ||
292 | hwdep->ops = hwdep_ops; | ||
293 | hwdep->private_data = efw; | ||
294 | hwdep->exclusive = true; | ||
295 | end: | ||
296 | return err; | ||
297 | } | ||
298 | |||
diff --git a/sound/firewire/fireworks/fireworks_midi.c b/sound/firewire/fireworks/fireworks_midi.c new file mode 100644 index 000000000000..cf9c65260439 --- /dev/null +++ b/sound/firewire/fireworks/fireworks_midi.c | |||
@@ -0,0 +1,168 @@ | |||
1 | /* | ||
2 | * fireworks_midi.c - a part of driver for Fireworks based devices | ||
3 | * | ||
4 | * Copyright (c) 2009-2010 Clemens Ladisch | ||
5 | * Copyright (c) 2013-2014 Takashi Sakamoto | ||
6 | * | ||
7 | * Licensed under the terms of the GNU General Public License, version 2. | ||
8 | */ | ||
9 | #include "fireworks.h" | ||
10 | |||
11 | static int midi_capture_open(struct snd_rawmidi_substream *substream) | ||
12 | { | ||
13 | struct snd_efw *efw = substream->rmidi->private_data; | ||
14 | int err; | ||
15 | |||
16 | err = snd_efw_stream_lock_try(efw); | ||
17 | if (err < 0) | ||
18 | goto end; | ||
19 | |||
20 | atomic_inc(&efw->capture_substreams); | ||
21 | err = snd_efw_stream_start_duplex(efw, 0); | ||
22 | if (err < 0) | ||
23 | snd_efw_stream_lock_release(efw); | ||
24 | |||
25 | end: | ||
26 | return err; | ||
27 | } | ||
28 | |||
29 | static int midi_playback_open(struct snd_rawmidi_substream *substream) | ||
30 | { | ||
31 | struct snd_efw *efw = substream->rmidi->private_data; | ||
32 | int err; | ||
33 | |||
34 | err = snd_efw_stream_lock_try(efw); | ||
35 | if (err < 0) | ||
36 | goto end; | ||
37 | |||
38 | atomic_inc(&efw->playback_substreams); | ||
39 | err = snd_efw_stream_start_duplex(efw, 0); | ||
40 | if (err < 0) | ||
41 | snd_efw_stream_lock_release(efw); | ||
42 | end: | ||
43 | return err; | ||
44 | } | ||
45 | |||
46 | static int midi_capture_close(struct snd_rawmidi_substream *substream) | ||
47 | { | ||
48 | struct snd_efw *efw = substream->rmidi->private_data; | ||
49 | |||
50 | atomic_dec(&efw->capture_substreams); | ||
51 | snd_efw_stream_stop_duplex(efw); | ||
52 | |||
53 | snd_efw_stream_lock_release(efw); | ||
54 | return 0; | ||
55 | } | ||
56 | |||
57 | static int midi_playback_close(struct snd_rawmidi_substream *substream) | ||
58 | { | ||
59 | struct snd_efw *efw = substream->rmidi->private_data; | ||
60 | |||
61 | atomic_dec(&efw->playback_substreams); | ||
62 | snd_efw_stream_stop_duplex(efw); | ||
63 | |||
64 | snd_efw_stream_lock_release(efw); | ||
65 | return 0; | ||
66 | } | ||
67 | |||
68 | static void midi_capture_trigger(struct snd_rawmidi_substream *substrm, int up) | ||
69 | { | ||
70 | struct snd_efw *efw = substrm->rmidi->private_data; | ||
71 | unsigned long flags; | ||
72 | |||
73 | spin_lock_irqsave(&efw->lock, flags); | ||
74 | |||
75 | if (up) | ||
76 | amdtp_stream_midi_trigger(&efw->tx_stream, | ||
77 | substrm->number, substrm); | ||
78 | else | ||
79 | amdtp_stream_midi_trigger(&efw->tx_stream, | ||
80 | substrm->number, NULL); | ||
81 | |||
82 | spin_unlock_irqrestore(&efw->lock, flags); | ||
83 | } | ||
84 | |||
85 | static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up) | ||
86 | { | ||
87 | struct snd_efw *efw = substrm->rmidi->private_data; | ||
88 | unsigned long flags; | ||
89 | |||
90 | spin_lock_irqsave(&efw->lock, flags); | ||
91 | |||
92 | if (up) | ||
93 | amdtp_stream_midi_trigger(&efw->rx_stream, | ||
94 | substrm->number, substrm); | ||
95 | else | ||
96 | amdtp_stream_midi_trigger(&efw->rx_stream, | ||
97 | substrm->number, NULL); | ||
98 | |||
99 | spin_unlock_irqrestore(&efw->lock, flags); | ||
100 | } | ||
101 | |||
102 | static struct snd_rawmidi_ops midi_capture_ops = { | ||
103 | .open = midi_capture_open, | ||
104 | .close = midi_capture_close, | ||
105 | .trigger = midi_capture_trigger, | ||
106 | }; | ||
107 | |||
108 | static struct snd_rawmidi_ops midi_playback_ops = { | ||
109 | .open = midi_playback_open, | ||
110 | .close = midi_playback_close, | ||
111 | .trigger = midi_playback_trigger, | ||
112 | }; | ||
113 | |||
114 | static void set_midi_substream_names(struct snd_efw *efw, | ||
115 | struct snd_rawmidi_str *str) | ||
116 | { | ||
117 | struct snd_rawmidi_substream *subs; | ||
118 | |||
119 | list_for_each_entry(subs, &str->substreams, list) { | ||
120 | snprintf(subs->name, sizeof(subs->name), | ||
121 | "%s MIDI %d", efw->card->shortname, subs->number + 1); | ||
122 | } | ||
123 | } | ||
124 | |||
125 | int snd_efw_create_midi_devices(struct snd_efw *efw) | ||
126 | { | ||
127 | struct snd_rawmidi *rmidi; | ||
128 | struct snd_rawmidi_str *str; | ||
129 | int err; | ||
130 | |||
131 | /* create midi ports */ | ||
132 | err = snd_rawmidi_new(efw->card, efw->card->driver, 0, | ||
133 | efw->midi_out_ports, efw->midi_in_ports, | ||
134 | &rmidi); | ||
135 | if (err < 0) | ||
136 | return err; | ||
137 | |||
138 | snprintf(rmidi->name, sizeof(rmidi->name), | ||
139 | "%s MIDI", efw->card->shortname); | ||
140 | rmidi->private_data = efw; | ||
141 | |||
142 | if (efw->midi_in_ports > 0) { | ||
143 | rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT; | ||
144 | |||
145 | snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, | ||
146 | &midi_capture_ops); | ||
147 | |||
148 | str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT]; | ||
149 | |||
150 | set_midi_substream_names(efw, str); | ||
151 | } | ||
152 | |||
153 | if (efw->midi_out_ports > 0) { | ||
154 | rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT; | ||
155 | |||
156 | snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, | ||
157 | &midi_playback_ops); | ||
158 | |||
159 | str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT]; | ||
160 | |||
161 | set_midi_substream_names(efw, str); | ||
162 | } | ||
163 | |||
164 | if ((efw->midi_out_ports > 0) && (efw->midi_in_ports > 0)) | ||
165 | rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX; | ||
166 | |||
167 | return 0; | ||
168 | } | ||
diff --git a/sound/firewire/fireworks/fireworks_pcm.c b/sound/firewire/fireworks/fireworks_pcm.c new file mode 100644 index 000000000000..8a34753de210 --- /dev/null +++ b/sound/firewire/fireworks/fireworks_pcm.c | |||
@@ -0,0 +1,403 @@ | |||
1 | /* | ||
2 | * fireworks_pcm.c - a part of driver for Fireworks based devices | ||
3 | * | ||
4 | * Copyright (c) 2009-2010 Clemens Ladisch | ||
5 | * Copyright (c) 2013-2014 Takashi Sakamoto | ||
6 | * | ||
7 | * Licensed under the terms of the GNU General Public License, version 2. | ||
8 | */ | ||
9 | #include "./fireworks.h" | ||
10 | |||
11 | /* | ||
12 | * NOTE: | ||
13 | * Fireworks changes its AMDTP channels for PCM data according to its sampling | ||
14 | * rate. There are three modes. Here _XX is either _rx or _tx. | ||
15 | * 0: 32.0- 48.0 kHz then snd_efw_hwinfo.amdtp_XX_pcm_channels applied | ||
16 | * 1: 88.2- 96.0 kHz then snd_efw_hwinfo.amdtp_XX_pcm_channels_2x applied | ||
17 | * 2: 176.4-192.0 kHz then snd_efw_hwinfo.amdtp_XX_pcm_channels_4x applied | ||
18 | * | ||
19 | * The number of PCM channels for analog input and output are always fixed but | ||
20 | * the number of PCM channels for digital input and output are differed. | ||
21 | * | ||
22 | * Additionally, according to "AudioFire Owner's Manual Version 2.2", in some | ||
23 | * model, the number of PCM channels for digital input has more restriction | ||
24 | * depending on which digital interface is selected. | ||
25 | * - S/PDIF coaxial and optical : use input 1-2 | ||
26 | * - ADAT optical at 32.0-48.0 kHz : use input 1-8 | ||
27 | * - ADAT optical at 88.2-96.0 kHz : use input 1-4 (S/MUX format) | ||
28 | * | ||
29 | * The data in AMDTP channels for blank PCM channels are zero. | ||
30 | */ | ||
31 | static const unsigned int freq_table[] = { | ||
32 | /* multiplier mode 0 */ | ||
33 | [0] = 32000, | ||
34 | [1] = 44100, | ||
35 | [2] = 48000, | ||
36 | /* multiplier mode 1 */ | ||
37 | [3] = 88200, | ||
38 | [4] = 96000, | ||
39 | /* multiplier mode 2 */ | ||
40 | [5] = 176400, | ||
41 | [6] = 192000, | ||
42 | }; | ||
43 | |||
44 | static inline unsigned int | ||
45 | get_multiplier_mode_with_index(unsigned int index) | ||
46 | { | ||
47 | return ((int)index - 1) / 2; | ||
48 | } | ||
49 | |||
50 | int snd_efw_get_multiplier_mode(unsigned int sampling_rate, unsigned int *mode) | ||
51 | { | ||
52 | unsigned int i; | ||
53 | |||
54 | for (i = 0; i < ARRAY_SIZE(freq_table); i++) { | ||
55 | if (freq_table[i] == sampling_rate) { | ||
56 | *mode = get_multiplier_mode_with_index(i); | ||
57 | return 0; | ||
58 | } | ||
59 | } | ||
60 | |||
61 | return -EINVAL; | ||
62 | } | ||
63 | |||
64 | static int | ||
65 | hw_rule_rate(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule) | ||
66 | { | ||
67 | unsigned int *pcm_channels = rule->private; | ||
68 | struct snd_interval *r = | ||
69 | hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); | ||
70 | const struct snd_interval *c = | ||
71 | hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_CHANNELS); | ||
72 | struct snd_interval t = { | ||
73 | .min = UINT_MAX, .max = 0, .integer = 1 | ||
74 | }; | ||
75 | unsigned int i, mode; | ||
76 | |||
77 | for (i = 0; i < ARRAY_SIZE(freq_table); i++) { | ||
78 | mode = get_multiplier_mode_with_index(i); | ||
79 | if (!snd_interval_test(c, pcm_channels[mode])) | ||
80 | continue; | ||
81 | |||
82 | t.min = min(t.min, freq_table[i]); | ||
83 | t.max = max(t.max, freq_table[i]); | ||
84 | } | ||
85 | |||
86 | return snd_interval_refine(r, &t); | ||
87 | } | ||
88 | |||
89 | static int | ||
90 | hw_rule_channels(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule) | ||
91 | { | ||
92 | unsigned int *pcm_channels = rule->private; | ||
93 | struct snd_interval *c = | ||
94 | hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); | ||
95 | const struct snd_interval *r = | ||
96 | hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE); | ||
97 | struct snd_interval t = { | ||
98 | .min = UINT_MAX, .max = 0, .integer = 1 | ||
99 | }; | ||
100 | unsigned int i, mode; | ||
101 | |||
102 | for (i = 0; i < ARRAY_SIZE(freq_table); i++) { | ||
103 | mode = get_multiplier_mode_with_index(i); | ||
104 | if (!snd_interval_test(r, freq_table[i])) | ||
105 | continue; | ||
106 | |||
107 | t.min = min(t.min, pcm_channels[mode]); | ||
108 | t.max = max(t.max, pcm_channels[mode]); | ||
109 | } | ||
110 | |||
111 | return snd_interval_refine(c, &t); | ||
112 | } | ||
113 | |||
114 | static void | ||
115 | limit_channels(struct snd_pcm_hardware *hw, unsigned int *pcm_channels) | ||
116 | { | ||
117 | unsigned int i, mode; | ||
118 | |||
119 | hw->channels_min = UINT_MAX; | ||
120 | hw->channels_max = 0; | ||
121 | |||
122 | for (i = 0; i < ARRAY_SIZE(freq_table); i++) { | ||
123 | mode = get_multiplier_mode_with_index(i); | ||
124 | if (pcm_channels[mode] == 0) | ||
125 | continue; | ||
126 | |||
127 | hw->channels_min = min(hw->channels_min, pcm_channels[mode]); | ||
128 | hw->channels_max = max(hw->channels_max, pcm_channels[mode]); | ||
129 | } | ||
130 | } | ||
131 | |||
132 | static void | ||
133 | limit_period_and_buffer(struct snd_pcm_hardware *hw) | ||
134 | { | ||
135 | hw->periods_min = 2; /* SNDRV_PCM_INFO_BATCH */ | ||
136 | hw->periods_max = UINT_MAX; | ||
137 | |||
138 | hw->period_bytes_min = 4 * hw->channels_max; /* bytes for a frame */ | ||
139 | |||
140 | /* Just to prevent from allocating much pages. */ | ||
141 | hw->period_bytes_max = hw->period_bytes_min * 2048; | ||
142 | hw->buffer_bytes_max = hw->period_bytes_max * hw->periods_min; | ||
143 | } | ||
144 | |||
145 | static int | ||
146 | pcm_init_hw_params(struct snd_efw *efw, | ||
147 | struct snd_pcm_substream *substream) | ||
148 | { | ||
149 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
150 | struct amdtp_stream *s; | ||
151 | unsigned int *pcm_channels; | ||
152 | int err; | ||
153 | |||
154 | runtime->hw.info = SNDRV_PCM_INFO_BATCH | | ||
155 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
156 | SNDRV_PCM_INFO_INTERLEAVED | | ||
157 | SNDRV_PCM_INFO_JOINT_DUPLEX | | ||
158 | SNDRV_PCM_INFO_MMAP | | ||
159 | SNDRV_PCM_INFO_MMAP_VALID; | ||
160 | |||
161 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { | ||
162 | runtime->hw.formats = AMDTP_IN_PCM_FORMAT_BITS; | ||
163 | s = &efw->tx_stream; | ||
164 | pcm_channels = efw->pcm_capture_channels; | ||
165 | } else { | ||
166 | runtime->hw.formats = AMDTP_OUT_PCM_FORMAT_BITS; | ||
167 | s = &efw->rx_stream; | ||
168 | pcm_channels = efw->pcm_playback_channels; | ||
169 | } | ||
170 | |||
171 | /* limit rates */ | ||
172 | runtime->hw.rates = efw->supported_sampling_rate, | ||
173 | snd_pcm_limit_hw_rates(runtime); | ||
174 | |||
175 | limit_channels(&runtime->hw, pcm_channels); | ||
176 | limit_period_and_buffer(&runtime->hw); | ||
177 | |||
178 | err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, | ||
179 | hw_rule_channels, pcm_channels, | ||
180 | SNDRV_PCM_HW_PARAM_RATE, -1); | ||
181 | if (err < 0) | ||
182 | goto end; | ||
183 | |||
184 | err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, | ||
185 | hw_rule_rate, pcm_channels, | ||
186 | SNDRV_PCM_HW_PARAM_CHANNELS, -1); | ||
187 | if (err < 0) | ||
188 | goto end; | ||
189 | |||
190 | err = amdtp_stream_add_pcm_hw_constraints(s, runtime); | ||
191 | end: | ||
192 | return err; | ||
193 | } | ||
194 | |||
195 | static int pcm_open(struct snd_pcm_substream *substream) | ||
196 | { | ||
197 | struct snd_efw *efw = substream->private_data; | ||
198 | unsigned int sampling_rate; | ||
199 | enum snd_efw_clock_source clock_source; | ||
200 | int err; | ||
201 | |||
202 | err = snd_efw_stream_lock_try(efw); | ||
203 | if (err < 0) | ||
204 | goto end; | ||
205 | |||
206 | err = pcm_init_hw_params(efw, substream); | ||
207 | if (err < 0) | ||
208 | goto err_locked; | ||
209 | |||
210 | err = snd_efw_command_get_clock_source(efw, &clock_source); | ||
211 | if (err < 0) | ||
212 | goto err_locked; | ||
213 | |||
214 | /* | ||
215 | * When source of clock is not internal or any PCM streams are running, | ||
216 | * available sampling rate is limited at current sampling rate. | ||
217 | */ | ||
218 | if ((clock_source != SND_EFW_CLOCK_SOURCE_INTERNAL) || | ||
219 | amdtp_stream_pcm_running(&efw->tx_stream) || | ||
220 | amdtp_stream_pcm_running(&efw->rx_stream)) { | ||
221 | err = snd_efw_command_get_sampling_rate(efw, &sampling_rate); | ||
222 | if (err < 0) | ||
223 | goto err_locked; | ||
224 | substream->runtime->hw.rate_min = sampling_rate; | ||
225 | substream->runtime->hw.rate_max = sampling_rate; | ||
226 | } | ||
227 | |||
228 | snd_pcm_set_sync(substream); | ||
229 | end: | ||
230 | return err; | ||
231 | err_locked: | ||
232 | snd_efw_stream_lock_release(efw); | ||
233 | return err; | ||
234 | } | ||
235 | |||
236 | static int pcm_close(struct snd_pcm_substream *substream) | ||
237 | { | ||
238 | struct snd_efw *efw = substream->private_data; | ||
239 | snd_efw_stream_lock_release(efw); | ||
240 | return 0; | ||
241 | } | ||
242 | |||
243 | static int pcm_capture_hw_params(struct snd_pcm_substream *substream, | ||
244 | struct snd_pcm_hw_params *hw_params) | ||
245 | { | ||
246 | struct snd_efw *efw = substream->private_data; | ||
247 | |||
248 | if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) | ||
249 | atomic_inc(&efw->capture_substreams); | ||
250 | amdtp_stream_set_pcm_format(&efw->tx_stream, params_format(hw_params)); | ||
251 | |||
252 | return snd_pcm_lib_alloc_vmalloc_buffer(substream, | ||
253 | params_buffer_bytes(hw_params)); | ||
254 | } | ||
255 | static int pcm_playback_hw_params(struct snd_pcm_substream *substream, | ||
256 | struct snd_pcm_hw_params *hw_params) | ||
257 | { | ||
258 | struct snd_efw *efw = substream->private_data; | ||
259 | |||
260 | if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) | ||
261 | atomic_inc(&efw->playback_substreams); | ||
262 | amdtp_stream_set_pcm_format(&efw->rx_stream, params_format(hw_params)); | ||
263 | |||
264 | return snd_pcm_lib_alloc_vmalloc_buffer(substream, | ||
265 | params_buffer_bytes(hw_params)); | ||
266 | } | ||
267 | |||
268 | static int pcm_capture_hw_free(struct snd_pcm_substream *substream) | ||
269 | { | ||
270 | struct snd_efw *efw = substream->private_data; | ||
271 | |||
272 | if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) | ||
273 | atomic_dec(&efw->capture_substreams); | ||
274 | |||
275 | snd_efw_stream_stop_duplex(efw); | ||
276 | |||
277 | return snd_pcm_lib_free_vmalloc_buffer(substream); | ||
278 | } | ||
279 | static int pcm_playback_hw_free(struct snd_pcm_substream *substream) | ||
280 | { | ||
281 | struct snd_efw *efw = substream->private_data; | ||
282 | |||
283 | if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) | ||
284 | atomic_dec(&efw->playback_substreams); | ||
285 | |||
286 | snd_efw_stream_stop_duplex(efw); | ||
287 | |||
288 | return snd_pcm_lib_free_vmalloc_buffer(substream); | ||
289 | } | ||
290 | |||
291 | static int pcm_capture_prepare(struct snd_pcm_substream *substream) | ||
292 | { | ||
293 | struct snd_efw *efw = substream->private_data; | ||
294 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
295 | int err; | ||
296 | |||
297 | err = snd_efw_stream_start_duplex(efw, runtime->rate); | ||
298 | if (err >= 0) | ||
299 | amdtp_stream_pcm_prepare(&efw->tx_stream); | ||
300 | |||
301 | return err; | ||
302 | } | ||
303 | static int pcm_playback_prepare(struct snd_pcm_substream *substream) | ||
304 | { | ||
305 | struct snd_efw *efw = substream->private_data; | ||
306 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
307 | int err; | ||
308 | |||
309 | err = snd_efw_stream_start_duplex(efw, runtime->rate); | ||
310 | if (err >= 0) | ||
311 | amdtp_stream_pcm_prepare(&efw->rx_stream); | ||
312 | |||
313 | return err; | ||
314 | } | ||
315 | |||
316 | static int pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd) | ||
317 | { | ||
318 | struct snd_efw *efw = substream->private_data; | ||
319 | |||
320 | switch (cmd) { | ||
321 | case SNDRV_PCM_TRIGGER_START: | ||
322 | amdtp_stream_pcm_trigger(&efw->tx_stream, substream); | ||
323 | break; | ||
324 | case SNDRV_PCM_TRIGGER_STOP: | ||
325 | amdtp_stream_pcm_trigger(&efw->tx_stream, NULL); | ||
326 | break; | ||
327 | default: | ||
328 | return -EINVAL; | ||
329 | } | ||
330 | |||
331 | return 0; | ||
332 | } | ||
333 | static int pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd) | ||
334 | { | ||
335 | struct snd_efw *efw = substream->private_data; | ||
336 | |||
337 | switch (cmd) { | ||
338 | case SNDRV_PCM_TRIGGER_START: | ||
339 | amdtp_stream_pcm_trigger(&efw->rx_stream, substream); | ||
340 | break; | ||
341 | case SNDRV_PCM_TRIGGER_STOP: | ||
342 | amdtp_stream_pcm_trigger(&efw->rx_stream, NULL); | ||
343 | break; | ||
344 | default: | ||
345 | return -EINVAL; | ||
346 | } | ||
347 | |||
348 | return 0; | ||
349 | } | ||
350 | |||
351 | static snd_pcm_uframes_t pcm_capture_pointer(struct snd_pcm_substream *sbstrm) | ||
352 | { | ||
353 | struct snd_efw *efw = sbstrm->private_data; | ||
354 | return amdtp_stream_pcm_pointer(&efw->tx_stream); | ||
355 | } | ||
356 | static snd_pcm_uframes_t pcm_playback_pointer(struct snd_pcm_substream *sbstrm) | ||
357 | { | ||
358 | struct snd_efw *efw = sbstrm->private_data; | ||
359 | return amdtp_stream_pcm_pointer(&efw->rx_stream); | ||
360 | } | ||
361 | |||
362 | static 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 | }; | ||
373 | |||
374 | static const struct snd_pcm_ops pcm_playback_ops = { | ||
375 | .open = pcm_open, | ||
376 | .close = pcm_close, | ||
377 | .ioctl = snd_pcm_lib_ioctl, | ||
378 | .hw_params = pcm_playback_hw_params, | ||
379 | .hw_free = pcm_playback_hw_free, | ||
380 | .prepare = pcm_playback_prepare, | ||
381 | .trigger = pcm_playback_trigger, | ||
382 | .pointer = pcm_playback_pointer, | ||
383 | .page = snd_pcm_lib_get_vmalloc_page, | ||
384 | .mmap = snd_pcm_lib_mmap_vmalloc, | ||
385 | }; | ||
386 | |||
387 | int snd_efw_create_pcm_devices(struct snd_efw *efw) | ||
388 | { | ||
389 | struct snd_pcm *pcm; | ||
390 | int err; | ||
391 | |||
392 | err = snd_pcm_new(efw->card, efw->card->driver, 0, 1, 1, &pcm); | ||
393 | if (err < 0) | ||
394 | goto end; | ||
395 | |||
396 | pcm->private_data = efw; | ||
397 | snprintf(pcm->name, sizeof(pcm->name), "%s PCM", efw->card->shortname); | ||
398 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &pcm_playback_ops); | ||
399 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pcm_capture_ops); | ||
400 | end: | ||
401 | return err; | ||
402 | } | ||
403 | |||
diff --git a/sound/firewire/fireworks/fireworks_proc.c b/sound/firewire/fireworks/fireworks_proc.c new file mode 100644 index 000000000000..f29d4aaf56a1 --- /dev/null +++ b/sound/firewire/fireworks/fireworks_proc.c | |||
@@ -0,0 +1,232 @@ | |||
1 | /* | ||
2 | * fireworks_proc.c - a part of driver for Fireworks based devices | ||
3 | * | ||
4 | * Copyright (c) 2009-2010 Clemens Ladisch | ||
5 | * Copyright (c) 2013-2014 Takashi Sakamoto | ||
6 | * | ||
7 | * Licensed under the terms of the GNU General Public License, version 2. | ||
8 | */ | ||
9 | |||
10 | #include "./fireworks.h" | ||
11 | |||
12 | static inline const char* | ||
13 | get_phys_name(struct snd_efw_phys_grp *grp, bool input) | ||
14 | { | ||
15 | const char *const ch_type[] = { | ||
16 | "Analog", "S/PDIF", "ADAT", "S/PDIF or ADAT", "Mirroring", | ||
17 | "Headphones", "I2S", "Guitar", "Pirzo Guitar", "Guitar String", | ||
18 | }; | ||
19 | |||
20 | if (grp->type < ARRAY_SIZE(ch_type)) | ||
21 | return ch_type[grp->type]; | ||
22 | else if (input) | ||
23 | return "Input"; | ||
24 | else | ||
25 | return "Output"; | ||
26 | } | ||
27 | |||
28 | static void | ||
29 | proc_read_hwinfo(struct snd_info_entry *entry, struct snd_info_buffer *buffer) | ||
30 | { | ||
31 | struct snd_efw *efw = entry->private_data; | ||
32 | unsigned short i; | ||
33 | struct snd_efw_hwinfo *hwinfo; | ||
34 | |||
35 | hwinfo = kmalloc(sizeof(struct snd_efw_hwinfo), GFP_KERNEL); | ||
36 | if (hwinfo == NULL) | ||
37 | return; | ||
38 | |||
39 | if (snd_efw_command_get_hwinfo(efw, hwinfo) < 0) | ||
40 | goto end; | ||
41 | |||
42 | snd_iprintf(buffer, "guid_hi: 0x%X\n", hwinfo->guid_hi); | ||
43 | snd_iprintf(buffer, "guid_lo: 0x%X\n", hwinfo->guid_lo); | ||
44 | snd_iprintf(buffer, "type: 0x%X\n", hwinfo->type); | ||
45 | snd_iprintf(buffer, "version: 0x%X\n", hwinfo->version); | ||
46 | snd_iprintf(buffer, "vendor_name: %s\n", hwinfo->vendor_name); | ||
47 | snd_iprintf(buffer, "model_name: %s\n", hwinfo->model_name); | ||
48 | |||
49 | snd_iprintf(buffer, "dsp_version: 0x%X\n", hwinfo->dsp_version); | ||
50 | snd_iprintf(buffer, "arm_version: 0x%X\n", hwinfo->arm_version); | ||
51 | snd_iprintf(buffer, "fpga_version: 0x%X\n", hwinfo->fpga_version); | ||
52 | |||
53 | snd_iprintf(buffer, "flags: 0x%X\n", hwinfo->flags); | ||
54 | |||
55 | snd_iprintf(buffer, "max_sample_rate: 0x%X\n", hwinfo->max_sample_rate); | ||
56 | snd_iprintf(buffer, "min_sample_rate: 0x%X\n", hwinfo->min_sample_rate); | ||
57 | snd_iprintf(buffer, "supported_clock: 0x%X\n", | ||
58 | hwinfo->supported_clocks); | ||
59 | |||
60 | snd_iprintf(buffer, "phys out: 0x%X\n", hwinfo->phys_out); | ||
61 | snd_iprintf(buffer, "phys in: 0x%X\n", hwinfo->phys_in); | ||
62 | |||
63 | snd_iprintf(buffer, "phys in grps: 0x%X\n", | ||
64 | hwinfo->phys_in_grp_count); | ||
65 | for (i = 0; i < hwinfo->phys_in_grp_count; i++) { | ||
66 | snd_iprintf(buffer, | ||
67 | "phys in grp[0x%d]: type 0x%d, count 0x%d\n", | ||
68 | i, hwinfo->phys_out_grps[i].type, | ||
69 | hwinfo->phys_out_grps[i].count); | ||
70 | } | ||
71 | |||
72 | snd_iprintf(buffer, "phys out grps: 0x%X\n", | ||
73 | hwinfo->phys_out_grp_count); | ||
74 | for (i = 0; i < hwinfo->phys_out_grp_count; i++) { | ||
75 | snd_iprintf(buffer, | ||
76 | "phys out grps[0x%d]: type 0x%d, count 0x%d\n", | ||
77 | i, hwinfo->phys_out_grps[i].type, | ||
78 | hwinfo->phys_out_grps[i].count); | ||
79 | } | ||
80 | |||
81 | snd_iprintf(buffer, "amdtp rx pcm channels 1x: 0x%X\n", | ||
82 | hwinfo->amdtp_rx_pcm_channels); | ||
83 | snd_iprintf(buffer, "amdtp tx pcm channels 1x: 0x%X\n", | ||
84 | hwinfo->amdtp_tx_pcm_channels); | ||
85 | snd_iprintf(buffer, "amdtp rx pcm channels 2x: 0x%X\n", | ||
86 | hwinfo->amdtp_rx_pcm_channels_2x); | ||
87 | snd_iprintf(buffer, "amdtp tx pcm channels 2x: 0x%X\n", | ||
88 | hwinfo->amdtp_tx_pcm_channels_2x); | ||
89 | snd_iprintf(buffer, "amdtp rx pcm channels 4x: 0x%X\n", | ||
90 | hwinfo->amdtp_rx_pcm_channels_4x); | ||
91 | snd_iprintf(buffer, "amdtp tx pcm channels 4x: 0x%X\n", | ||
92 | hwinfo->amdtp_tx_pcm_channels_4x); | ||
93 | |||
94 | snd_iprintf(buffer, "midi out ports: 0x%X\n", hwinfo->midi_out_ports); | ||
95 | snd_iprintf(buffer, "midi in ports: 0x%X\n", hwinfo->midi_in_ports); | ||
96 | |||
97 | snd_iprintf(buffer, "mixer playback channels: 0x%X\n", | ||
98 | hwinfo->mixer_playback_channels); | ||
99 | snd_iprintf(buffer, "mixer capture channels: 0x%X\n", | ||
100 | hwinfo->mixer_capture_channels); | ||
101 | end: | ||
102 | kfree(hwinfo); | ||
103 | } | ||
104 | |||
105 | static void | ||
106 | proc_read_clock(struct snd_info_entry *entry, struct snd_info_buffer *buffer) | ||
107 | { | ||
108 | struct snd_efw *efw = entry->private_data; | ||
109 | enum snd_efw_clock_source clock_source; | ||
110 | unsigned int sampling_rate; | ||
111 | |||
112 | if (snd_efw_command_get_clock_source(efw, &clock_source) < 0) | ||
113 | return; | ||
114 | |||
115 | if (snd_efw_command_get_sampling_rate(efw, &sampling_rate) < 0) | ||
116 | return; | ||
117 | |||
118 | snd_iprintf(buffer, "Clock Source: %d\n", clock_source); | ||
119 | snd_iprintf(buffer, "Sampling Rate: %d\n", sampling_rate); | ||
120 | } | ||
121 | |||
122 | /* | ||
123 | * NOTE: | ||
124 | * dB = 20 * log10(linear / 0x01000000) | ||
125 | * -144.0 dB when linear is 0 | ||
126 | */ | ||
127 | static void | ||
128 | proc_read_phys_meters(struct snd_info_entry *entry, | ||
129 | struct snd_info_buffer *buffer) | ||
130 | { | ||
131 | struct snd_efw *efw = entry->private_data; | ||
132 | struct snd_efw_phys_meters *meters; | ||
133 | unsigned int g, c, m, max, size; | ||
134 | const char *name; | ||
135 | u32 *linear; | ||
136 | int err; | ||
137 | |||
138 | size = sizeof(struct snd_efw_phys_meters) + | ||
139 | (efw->phys_in + efw->phys_out) * sizeof(u32); | ||
140 | meters = kzalloc(size, GFP_KERNEL); | ||
141 | if (meters == NULL) | ||
142 | return; | ||
143 | |||
144 | err = snd_efw_command_get_phys_meters(efw, meters, size); | ||
145 | if (err < 0) | ||
146 | goto end; | ||
147 | |||
148 | snd_iprintf(buffer, "Physical Meters:\n"); | ||
149 | |||
150 | m = 0; | ||
151 | max = min(efw->phys_out, meters->out_meters); | ||
152 | linear = meters->values; | ||
153 | snd_iprintf(buffer, " %d Outputs:\n", max); | ||
154 | for (g = 0; g < efw->phys_out_grp_count; g++) { | ||
155 | name = get_phys_name(&efw->phys_out_grps[g], false); | ||
156 | for (c = 0; c < efw->phys_out_grps[g].count; c++) { | ||
157 | if (m < max) | ||
158 | snd_iprintf(buffer, "\t%s [%d]: %d\n", | ||
159 | name, c, linear[m++]); | ||
160 | } | ||
161 | } | ||
162 | |||
163 | m = 0; | ||
164 | max = min(efw->phys_in, meters->in_meters); | ||
165 | linear = meters->values + meters->out_meters; | ||
166 | snd_iprintf(buffer, " %d Inputs:\n", max); | ||
167 | for (g = 0; g < efw->phys_in_grp_count; g++) { | ||
168 | name = get_phys_name(&efw->phys_in_grps[g], true); | ||
169 | for (c = 0; c < efw->phys_in_grps[g].count; c++) | ||
170 | if (m < max) | ||
171 | snd_iprintf(buffer, "\t%s [%d]: %d\n", | ||
172 | name, c, linear[m++]); | ||
173 | } | ||
174 | end: | ||
175 | kfree(meters); | ||
176 | } | ||
177 | |||
178 | static void | ||
179 | proc_read_queues_state(struct snd_info_entry *entry, | ||
180 | struct snd_info_buffer *buffer) | ||
181 | { | ||
182 | struct snd_efw *efw = entry->private_data; | ||
183 | unsigned int consumed; | ||
184 | |||
185 | if (efw->pull_ptr > efw->push_ptr) | ||
186 | consumed = snd_efw_resp_buf_size - | ||
187 | (unsigned int)(efw->pull_ptr - efw->push_ptr); | ||
188 | else | ||
189 | consumed = (unsigned int)(efw->push_ptr - efw->pull_ptr); | ||
190 | |||
191 | snd_iprintf(buffer, "%d %d/%d\n", | ||
192 | efw->resp_queues, consumed, snd_efw_resp_buf_size); | ||
193 | } | ||
194 | |||
195 | static void | ||
196 | add_node(struct snd_efw *efw, struct snd_info_entry *root, const char *name, | ||
197 | void (*op)(struct snd_info_entry *e, struct snd_info_buffer *b)) | ||
198 | { | ||
199 | struct snd_info_entry *entry; | ||
200 | |||
201 | entry = snd_info_create_card_entry(efw->card, name, root); | ||
202 | if (entry == NULL) | ||
203 | return; | ||
204 | |||
205 | snd_info_set_text_ops(entry, efw, op); | ||
206 | if (snd_info_register(entry) < 0) | ||
207 | snd_info_free_entry(entry); | ||
208 | } | ||
209 | |||
210 | void snd_efw_proc_init(struct snd_efw *efw) | ||
211 | { | ||
212 | struct snd_info_entry *root; | ||
213 | |||
214 | /* | ||
215 | * All nodes are automatically removed at snd_card_disconnect(), | ||
216 | * by following to link list. | ||
217 | */ | ||
218 | root = snd_info_create_card_entry(efw->card, "firewire", | ||
219 | efw->card->proc_root); | ||
220 | if (root == NULL) | ||
221 | return; | ||
222 | root->mode = S_IFDIR | S_IRUGO | S_IXUGO; | ||
223 | if (snd_info_register(root) < 0) { | ||
224 | snd_info_free_entry(root); | ||
225 | return; | ||
226 | } | ||
227 | |||
228 | add_node(efw, root, "clock", proc_read_clock); | ||
229 | add_node(efw, root, "firmware", proc_read_hwinfo); | ||
230 | add_node(efw, root, "meters", proc_read_phys_meters); | ||
231 | add_node(efw, root, "queues", proc_read_queues_state); | ||
232 | } | ||
diff --git a/sound/firewire/fireworks/fireworks_stream.c b/sound/firewire/fireworks/fireworks_stream.c new file mode 100644 index 000000000000..b985fc5ebdc6 --- /dev/null +++ b/sound/firewire/fireworks/fireworks_stream.c | |||
@@ -0,0 +1,372 @@ | |||
1 | /* | ||
2 | * fireworks_stream.c - a part of driver for Fireworks based devices | ||
3 | * | ||
4 | * Copyright (c) 2013-2014 Takashi Sakamoto | ||
5 | * | ||
6 | * Licensed under the terms of the GNU General Public License, version 2. | ||
7 | */ | ||
8 | #include "./fireworks.h" | ||
9 | |||
10 | #define CALLBACK_TIMEOUT 100 | ||
11 | |||
12 | static int | ||
13 | init_stream(struct snd_efw *efw, struct amdtp_stream *stream) | ||
14 | { | ||
15 | struct cmp_connection *conn; | ||
16 | enum cmp_direction c_dir; | ||
17 | enum amdtp_stream_direction s_dir; | ||
18 | int err; | ||
19 | |||
20 | if (stream == &efw->tx_stream) { | ||
21 | conn = &efw->out_conn; | ||
22 | c_dir = CMP_OUTPUT; | ||
23 | s_dir = AMDTP_IN_STREAM; | ||
24 | } else { | ||
25 | conn = &efw->in_conn; | ||
26 | c_dir = CMP_INPUT; | ||
27 | s_dir = AMDTP_OUT_STREAM; | ||
28 | } | ||
29 | |||
30 | err = cmp_connection_init(conn, efw->unit, c_dir, 0); | ||
31 | if (err < 0) | ||
32 | goto end; | ||
33 | |||
34 | err = amdtp_stream_init(stream, efw->unit, s_dir, CIP_BLOCKING); | ||
35 | if (err < 0) { | ||
36 | amdtp_stream_destroy(stream); | ||
37 | cmp_connection_destroy(conn); | ||
38 | } | ||
39 | end: | ||
40 | return err; | ||
41 | } | ||
42 | |||
43 | static void | ||
44 | stop_stream(struct snd_efw *efw, struct amdtp_stream *stream) | ||
45 | { | ||
46 | amdtp_stream_pcm_abort(stream); | ||
47 | amdtp_stream_stop(stream); | ||
48 | |||
49 | if (stream == &efw->tx_stream) | ||
50 | cmp_connection_break(&efw->out_conn); | ||
51 | else | ||
52 | cmp_connection_break(&efw->in_conn); | ||
53 | } | ||
54 | |||
55 | static int | ||
56 | start_stream(struct snd_efw *efw, struct amdtp_stream *stream, | ||
57 | unsigned int sampling_rate) | ||
58 | { | ||
59 | struct cmp_connection *conn; | ||
60 | unsigned int mode, pcm_channels, midi_ports; | ||
61 | int err; | ||
62 | |||
63 | err = snd_efw_get_multiplier_mode(sampling_rate, &mode); | ||
64 | if (err < 0) | ||
65 | goto end; | ||
66 | if (stream == &efw->tx_stream) { | ||
67 | conn = &efw->out_conn; | ||
68 | pcm_channels = efw->pcm_capture_channels[mode]; | ||
69 | midi_ports = efw->midi_out_ports; | ||
70 | } else { | ||
71 | conn = &efw->in_conn; | ||
72 | pcm_channels = efw->pcm_playback_channels[mode]; | ||
73 | midi_ports = efw->midi_in_ports; | ||
74 | } | ||
75 | |||
76 | amdtp_stream_set_parameters(stream, sampling_rate, | ||
77 | pcm_channels, midi_ports); | ||
78 | |||
79 | /* establish connection via CMP */ | ||
80 | err = cmp_connection_establish(conn, | ||
81 | amdtp_stream_get_max_payload(stream)); | ||
82 | if (err < 0) | ||
83 | goto end; | ||
84 | |||
85 | /* start amdtp stream */ | ||
86 | err = amdtp_stream_start(stream, | ||
87 | conn->resources.channel, | ||
88 | conn->speed); | ||
89 | if (err < 0) { | ||
90 | stop_stream(efw, stream); | ||
91 | goto end; | ||
92 | } | ||
93 | |||
94 | /* wait first callback */ | ||
95 | if (!amdtp_stream_wait_callback(stream, CALLBACK_TIMEOUT)) { | ||
96 | stop_stream(efw, stream); | ||
97 | err = -ETIMEDOUT; | ||
98 | } | ||
99 | end: | ||
100 | return err; | ||
101 | } | ||
102 | |||
103 | static void | ||
104 | destroy_stream(struct snd_efw *efw, struct amdtp_stream *stream) | ||
105 | { | ||
106 | stop_stream(efw, stream); | ||
107 | |||
108 | amdtp_stream_destroy(stream); | ||
109 | |||
110 | if (stream == &efw->tx_stream) | ||
111 | cmp_connection_destroy(&efw->out_conn); | ||
112 | else | ||
113 | cmp_connection_destroy(&efw->in_conn); | ||
114 | } | ||
115 | |||
116 | static int | ||
117 | get_sync_mode(struct snd_efw *efw, enum cip_flags *sync_mode) | ||
118 | { | ||
119 | enum snd_efw_clock_source clock_source; | ||
120 | int err; | ||
121 | |||
122 | err = snd_efw_command_get_clock_source(efw, &clock_source); | ||
123 | if (err < 0) | ||
124 | return err; | ||
125 | |||
126 | if (clock_source == SND_EFW_CLOCK_SOURCE_SYTMATCH) | ||
127 | return -ENOSYS; | ||
128 | |||
129 | *sync_mode = CIP_SYNC_TO_DEVICE; | ||
130 | return 0; | ||
131 | } | ||
132 | |||
133 | static int | ||
134 | check_connection_used_by_others(struct snd_efw *efw, struct amdtp_stream *s) | ||
135 | { | ||
136 | struct cmp_connection *conn; | ||
137 | bool used; | ||
138 | int err; | ||
139 | |||
140 | if (s == &efw->tx_stream) | ||
141 | conn = &efw->out_conn; | ||
142 | else | ||
143 | conn = &efw->in_conn; | ||
144 | |||
145 | err = cmp_connection_check_used(conn, &used); | ||
146 | if ((err >= 0) && used && !amdtp_stream_running(s)) { | ||
147 | dev_err(&efw->unit->device, | ||
148 | "Connection established by others: %cPCR[%d]\n", | ||
149 | (conn->direction == CMP_OUTPUT) ? 'o' : 'i', | ||
150 | conn->pcr_index); | ||
151 | err = -EBUSY; | ||
152 | } | ||
153 | |||
154 | return err; | ||
155 | } | ||
156 | |||
157 | int snd_efw_stream_init_duplex(struct snd_efw *efw) | ||
158 | { | ||
159 | int err; | ||
160 | |||
161 | err = init_stream(efw, &efw->tx_stream); | ||
162 | if (err < 0) | ||
163 | goto end; | ||
164 | /* Fireworks transmits NODATA packets with TAG0. */ | ||
165 | efw->tx_stream.flags |= CIP_EMPTY_WITH_TAG0; | ||
166 | /* Fireworks has its own meaning for dbc. */ | ||
167 | efw->tx_stream.flags |= CIP_DBC_IS_END_EVENT; | ||
168 | /* Fireworks reset dbc at bus reset. */ | ||
169 | efw->tx_stream.flags |= CIP_SKIP_DBC_ZERO_CHECK; | ||
170 | /* AudioFire9 always reports wrong dbs. */ | ||
171 | if (efw->is_af9) | ||
172 | efw->tx_stream.flags |= CIP_WRONG_DBS; | ||
173 | /* Firmware version 5.5 reports fixed interval for dbc. */ | ||
174 | if (efw->firmware_version == 0x5050000) | ||
175 | efw->tx_stream.tx_dbc_interval = 8; | ||
176 | |||
177 | err = init_stream(efw, &efw->rx_stream); | ||
178 | if (err < 0) { | ||
179 | destroy_stream(efw, &efw->tx_stream); | ||
180 | goto end; | ||
181 | } | ||
182 | /* | ||
183 | * Fireworks ignores MIDI messages in more than first 8 data | ||
184 | * blocks of an received AMDTP packet. | ||
185 | */ | ||
186 | efw->rx_stream.rx_blocks_for_midi = 8; | ||
187 | |||
188 | /* set IEC61883 compliant mode (actually not fully compliant...) */ | ||
189 | err = snd_efw_command_set_tx_mode(efw, SND_EFW_TRANSPORT_MODE_IEC61883); | ||
190 | if (err < 0) { | ||
191 | destroy_stream(efw, &efw->tx_stream); | ||
192 | destroy_stream(efw, &efw->rx_stream); | ||
193 | } | ||
194 | end: | ||
195 | return err; | ||
196 | } | ||
197 | |||
198 | int snd_efw_stream_start_duplex(struct snd_efw *efw, unsigned int rate) | ||
199 | { | ||
200 | struct amdtp_stream *master, *slave; | ||
201 | atomic_t *slave_substreams; | ||
202 | enum cip_flags sync_mode; | ||
203 | unsigned int curr_rate; | ||
204 | int err = 0; | ||
205 | |||
206 | mutex_lock(&efw->mutex); | ||
207 | |||
208 | /* Need no substreams */ | ||
209 | if ((atomic_read(&efw->playback_substreams) == 0) && | ||
210 | (atomic_read(&efw->capture_substreams) == 0)) | ||
211 | goto end; | ||
212 | |||
213 | err = get_sync_mode(efw, &sync_mode); | ||
214 | if (err < 0) | ||
215 | goto end; | ||
216 | if (sync_mode == CIP_SYNC_TO_DEVICE) { | ||
217 | master = &efw->tx_stream; | ||
218 | slave = &efw->rx_stream; | ||
219 | slave_substreams = &efw->playback_substreams; | ||
220 | } else { | ||
221 | master = &efw->rx_stream; | ||
222 | slave = &efw->tx_stream; | ||
223 | slave_substreams = &efw->capture_substreams; | ||
224 | } | ||
225 | |||
226 | /* | ||
227 | * Considering JACK/FFADO streaming: | ||
228 | * TODO: This can be removed hwdep functionality becomes popular. | ||
229 | */ | ||
230 | err = check_connection_used_by_others(efw, master); | ||
231 | if (err < 0) | ||
232 | goto end; | ||
233 | |||
234 | /* packet queueing error */ | ||
235 | if (amdtp_streaming_error(slave)) | ||
236 | stop_stream(efw, slave); | ||
237 | if (amdtp_streaming_error(master)) | ||
238 | stop_stream(efw, master); | ||
239 | |||
240 | /* stop streams if rate is different */ | ||
241 | err = snd_efw_command_get_sampling_rate(efw, &curr_rate); | ||
242 | if (err < 0) | ||
243 | goto end; | ||
244 | if (rate == 0) | ||
245 | rate = curr_rate; | ||
246 | if (rate != curr_rate) { | ||
247 | stop_stream(efw, slave); | ||
248 | stop_stream(efw, master); | ||
249 | } | ||
250 | |||
251 | /* master should be always running */ | ||
252 | if (!amdtp_stream_running(master)) { | ||
253 | amdtp_stream_set_sync(sync_mode, master, slave); | ||
254 | efw->master = master; | ||
255 | |||
256 | err = snd_efw_command_set_sampling_rate(efw, rate); | ||
257 | if (err < 0) | ||
258 | goto end; | ||
259 | |||
260 | err = start_stream(efw, master, rate); | ||
261 | if (err < 0) { | ||
262 | dev_err(&efw->unit->device, | ||
263 | "fail to start AMDTP master stream:%d\n", err); | ||
264 | goto end; | ||
265 | } | ||
266 | } | ||
267 | |||
268 | /* start slave if needed */ | ||
269 | if (atomic_read(slave_substreams) > 0 && !amdtp_stream_running(slave)) { | ||
270 | err = start_stream(efw, slave, rate); | ||
271 | if (err < 0) { | ||
272 | dev_err(&efw->unit->device, | ||
273 | "fail to start AMDTP slave stream:%d\n", err); | ||
274 | stop_stream(efw, master); | ||
275 | } | ||
276 | } | ||
277 | end: | ||
278 | mutex_unlock(&efw->mutex); | ||
279 | return err; | ||
280 | } | ||
281 | |||
282 | void snd_efw_stream_stop_duplex(struct snd_efw *efw) | ||
283 | { | ||
284 | struct amdtp_stream *master, *slave; | ||
285 | atomic_t *master_substreams, *slave_substreams; | ||
286 | |||
287 | if (efw->master == &efw->rx_stream) { | ||
288 | slave = &efw->tx_stream; | ||
289 | master = &efw->rx_stream; | ||
290 | slave_substreams = &efw->capture_substreams; | ||
291 | master_substreams = &efw->playback_substreams; | ||
292 | } else { | ||
293 | slave = &efw->rx_stream; | ||
294 | master = &efw->tx_stream; | ||
295 | slave_substreams = &efw->playback_substreams; | ||
296 | master_substreams = &efw->capture_substreams; | ||
297 | } | ||
298 | |||
299 | mutex_lock(&efw->mutex); | ||
300 | |||
301 | if (atomic_read(slave_substreams) == 0) { | ||
302 | stop_stream(efw, slave); | ||
303 | |||
304 | if (atomic_read(master_substreams) == 0) | ||
305 | stop_stream(efw, master); | ||
306 | } | ||
307 | |||
308 | mutex_unlock(&efw->mutex); | ||
309 | } | ||
310 | |||
311 | void snd_efw_stream_update_duplex(struct snd_efw *efw) | ||
312 | { | ||
313 | if ((cmp_connection_update(&efw->out_conn) < 0) || | ||
314 | (cmp_connection_update(&efw->in_conn) < 0)) { | ||
315 | mutex_lock(&efw->mutex); | ||
316 | stop_stream(efw, &efw->rx_stream); | ||
317 | stop_stream(efw, &efw->tx_stream); | ||
318 | mutex_unlock(&efw->mutex); | ||
319 | } else { | ||
320 | amdtp_stream_update(&efw->rx_stream); | ||
321 | amdtp_stream_update(&efw->tx_stream); | ||
322 | } | ||
323 | } | ||
324 | |||
325 | void snd_efw_stream_destroy_duplex(struct snd_efw *efw) | ||
326 | { | ||
327 | mutex_lock(&efw->mutex); | ||
328 | |||
329 | destroy_stream(efw, &efw->rx_stream); | ||
330 | destroy_stream(efw, &efw->tx_stream); | ||
331 | |||
332 | mutex_unlock(&efw->mutex); | ||
333 | } | ||
334 | |||
335 | void snd_efw_stream_lock_changed(struct snd_efw *efw) | ||
336 | { | ||
337 | efw->dev_lock_changed = true; | ||
338 | wake_up(&efw->hwdep_wait); | ||
339 | } | ||
340 | |||
341 | int snd_efw_stream_lock_try(struct snd_efw *efw) | ||
342 | { | ||
343 | int err; | ||
344 | |||
345 | spin_lock_irq(&efw->lock); | ||
346 | |||
347 | /* user land lock this */ | ||
348 | if (efw->dev_lock_count < 0) { | ||
349 | err = -EBUSY; | ||
350 | goto end; | ||
351 | } | ||
352 | |||
353 | /* this is the first time */ | ||
354 | if (efw->dev_lock_count++ == 0) | ||
355 | snd_efw_stream_lock_changed(efw); | ||
356 | err = 0; | ||
357 | end: | ||
358 | spin_unlock_irq(&efw->lock); | ||
359 | return err; | ||
360 | } | ||
361 | |||
362 | void snd_efw_stream_lock_release(struct snd_efw *efw) | ||
363 | { | ||
364 | spin_lock_irq(&efw->lock); | ||
365 | |||
366 | if (WARN_ON(efw->dev_lock_count <= 0)) | ||
367 | goto end; | ||
368 | if (--efw->dev_lock_count == 0) | ||
369 | snd_efw_stream_lock_changed(efw); | ||
370 | end: | ||
371 | spin_unlock_irq(&efw->lock); | ||
372 | } | ||
diff --git a/sound/firewire/fireworks/fireworks_transaction.c b/sound/firewire/fireworks/fireworks_transaction.c new file mode 100644 index 000000000000..255dabc6fc33 --- /dev/null +++ b/sound/firewire/fireworks/fireworks_transaction.c | |||
@@ -0,0 +1,326 @@ | |||
1 | /* | ||
2 | * fireworks_transaction.c - a part of driver for Fireworks based devices | ||
3 | * | ||
4 | * Copyright (c) 2013-2014 Takashi Sakamoto | ||
5 | * | ||
6 | * Licensed under the terms of the GNU General Public License, version 2. | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Fireworks have its own transaction. The transaction can be delivered by AV/C | ||
11 | * Vendor Specific command frame or usual asynchronous transaction. At least, | ||
12 | * Windows driver and firmware version 5.5 or later don't use AV/C command. | ||
13 | * | ||
14 | * Transaction substance: | ||
15 | * At first, 6 data exist. Following to the data, parameters for each command | ||
16 | * exist. All of the parameters are 32 bit alighed to big endian. | ||
17 | * data[0]: Length of transaction substance | ||
18 | * data[1]: Transaction version | ||
19 | * data[2]: Sequence number. This is incremented by the device | ||
20 | * data[3]: Transaction category | ||
21 | * data[4]: Transaction command | ||
22 | * data[5]: Return value in response. | ||
23 | * data[6-]: Parameters | ||
24 | * | ||
25 | * Transaction address: | ||
26 | * command: 0xecc000000000 | ||
27 | * response: 0xecc080000000 (default) | ||
28 | * | ||
29 | * I note that the address for response can be changed by command. But this | ||
30 | * module uses the default address. | ||
31 | */ | ||
32 | #include "./fireworks.h" | ||
33 | |||
34 | #define MEMORY_SPACE_EFW_COMMAND 0xecc000000000ULL | ||
35 | #define MEMORY_SPACE_EFW_RESPONSE 0xecc080000000ULL | ||
36 | |||
37 | #define ERROR_RETRIES 3 | ||
38 | #define ERROR_DELAY_MS 5 | ||
39 | #define EFC_TIMEOUT_MS 125 | ||
40 | |||
41 | static DEFINE_SPINLOCK(instances_lock); | ||
42 | static struct snd_efw *instances[SNDRV_CARDS] = SNDRV_DEFAULT_PTR; | ||
43 | |||
44 | static DEFINE_SPINLOCK(transaction_queues_lock); | ||
45 | static LIST_HEAD(transaction_queues); | ||
46 | |||
47 | enum transaction_queue_state { | ||
48 | STATE_PENDING, | ||
49 | STATE_BUS_RESET, | ||
50 | STATE_COMPLETE | ||
51 | }; | ||
52 | |||
53 | struct transaction_queue { | ||
54 | struct list_head list; | ||
55 | struct fw_unit *unit; | ||
56 | void *buf; | ||
57 | unsigned int size; | ||
58 | u32 seqnum; | ||
59 | enum transaction_queue_state state; | ||
60 | wait_queue_head_t wait; | ||
61 | }; | ||
62 | |||
63 | int snd_efw_transaction_cmd(struct fw_unit *unit, | ||
64 | const void *cmd, unsigned int size) | ||
65 | { | ||
66 | return snd_fw_transaction(unit, TCODE_WRITE_BLOCK_REQUEST, | ||
67 | MEMORY_SPACE_EFW_COMMAND, | ||
68 | (void *)cmd, size, 0); | ||
69 | } | ||
70 | |||
71 | int snd_efw_transaction_run(struct fw_unit *unit, | ||
72 | const void *cmd, unsigned int cmd_size, | ||
73 | void *resp, unsigned int resp_size) | ||
74 | { | ||
75 | struct transaction_queue t; | ||
76 | unsigned int tries; | ||
77 | int ret; | ||
78 | |||
79 | t.unit = unit; | ||
80 | t.buf = resp; | ||
81 | t.size = resp_size; | ||
82 | t.seqnum = be32_to_cpu(((struct snd_efw_transaction *)cmd)->seqnum) + 1; | ||
83 | t.state = STATE_PENDING; | ||
84 | init_waitqueue_head(&t.wait); | ||
85 | |||
86 | spin_lock_irq(&transaction_queues_lock); | ||
87 | list_add_tail(&t.list, &transaction_queues); | ||
88 | spin_unlock_irq(&transaction_queues_lock); | ||
89 | |||
90 | tries = 0; | ||
91 | do { | ||
92 | ret = snd_efw_transaction_cmd(t.unit, (void *)cmd, cmd_size); | ||
93 | if (ret < 0) | ||
94 | break; | ||
95 | |||
96 | wait_event_timeout(t.wait, t.state != STATE_PENDING, | ||
97 | msecs_to_jiffies(EFC_TIMEOUT_MS)); | ||
98 | |||
99 | if (t.state == STATE_COMPLETE) { | ||
100 | ret = t.size; | ||
101 | break; | ||
102 | } else if (t.state == STATE_BUS_RESET) { | ||
103 | msleep(ERROR_DELAY_MS); | ||
104 | } else if (++tries >= ERROR_RETRIES) { | ||
105 | dev_err(&t.unit->device, "EFW transaction timed out\n"); | ||
106 | ret = -EIO; | ||
107 | break; | ||
108 | } | ||
109 | } while (1); | ||
110 | |||
111 | spin_lock_irq(&transaction_queues_lock); | ||
112 | list_del(&t.list); | ||
113 | spin_unlock_irq(&transaction_queues_lock); | ||
114 | |||
115 | return ret; | ||
116 | } | ||
117 | |||
118 | static void | ||
119 | copy_resp_to_buf(struct snd_efw *efw, void *data, size_t length, int *rcode) | ||
120 | { | ||
121 | size_t capacity, till_end; | ||
122 | struct snd_efw_transaction *t; | ||
123 | |||
124 | spin_lock_irq(&efw->lock); | ||
125 | |||
126 | t = (struct snd_efw_transaction *)data; | ||
127 | length = min_t(size_t, t->length * sizeof(t->length), length); | ||
128 | |||
129 | if (efw->push_ptr < efw->pull_ptr) | ||
130 | capacity = (unsigned int)(efw->pull_ptr - efw->push_ptr); | ||
131 | else | ||
132 | capacity = snd_efw_resp_buf_size - | ||
133 | (unsigned int)(efw->push_ptr - efw->pull_ptr); | ||
134 | |||
135 | /* confirm enough space for this response */ | ||
136 | if (capacity < length) { | ||
137 | *rcode = RCODE_CONFLICT_ERROR; | ||
138 | goto end; | ||
139 | } | ||
140 | |||
141 | /* copy to ring buffer */ | ||
142 | while (length > 0) { | ||
143 | till_end = snd_efw_resp_buf_size - | ||
144 | (unsigned int)(efw->push_ptr - efw->resp_buf); | ||
145 | till_end = min_t(unsigned int, length, till_end); | ||
146 | |||
147 | memcpy(efw->push_ptr, data, till_end); | ||
148 | |||
149 | efw->push_ptr += till_end; | ||
150 | if (efw->push_ptr >= efw->resp_buf + snd_efw_resp_buf_size) | ||
151 | efw->push_ptr -= snd_efw_resp_buf_size; | ||
152 | |||
153 | length -= till_end; | ||
154 | data += till_end; | ||
155 | } | ||
156 | |||
157 | /* for hwdep */ | ||
158 | efw->resp_queues++; | ||
159 | wake_up(&efw->hwdep_wait); | ||
160 | |||
161 | *rcode = RCODE_COMPLETE; | ||
162 | end: | ||
163 | spin_unlock_irq(&efw->lock); | ||
164 | } | ||
165 | |||
166 | static void | ||
167 | handle_resp_for_user(struct fw_card *card, int generation, int source, | ||
168 | void *data, size_t length, int *rcode) | ||
169 | { | ||
170 | struct fw_device *device; | ||
171 | struct snd_efw *efw; | ||
172 | unsigned int i; | ||
173 | |||
174 | spin_lock_irq(&instances_lock); | ||
175 | |||
176 | for (i = 0; i < SNDRV_CARDS; i++) { | ||
177 | efw = instances[i]; | ||
178 | if (efw == NULL) | ||
179 | continue; | ||
180 | device = fw_parent_device(efw->unit); | ||
181 | if ((device->card != card) || | ||
182 | (device->generation != generation)) | ||
183 | continue; | ||
184 | smp_rmb(); /* node id vs. generation */ | ||
185 | if (device->node_id != source) | ||
186 | continue; | ||
187 | |||
188 | break; | ||
189 | } | ||
190 | if (i == SNDRV_CARDS) | ||
191 | goto end; | ||
192 | |||
193 | copy_resp_to_buf(efw, data, length, rcode); | ||
194 | end: | ||
195 | spin_unlock_irq(&instances_lock); | ||
196 | } | ||
197 | |||
198 | static void | ||
199 | handle_resp_for_kernel(struct fw_card *card, int generation, int source, | ||
200 | void *data, size_t length, int *rcode, u32 seqnum) | ||
201 | { | ||
202 | struct fw_device *device; | ||
203 | struct transaction_queue *t; | ||
204 | unsigned long flags; | ||
205 | |||
206 | spin_lock_irqsave(&transaction_queues_lock, flags); | ||
207 | list_for_each_entry(t, &transaction_queues, list) { | ||
208 | device = fw_parent_device(t->unit); | ||
209 | if ((device->card != card) || | ||
210 | (device->generation != generation)) | ||
211 | continue; | ||
212 | smp_rmb(); /* node_id vs. generation */ | ||
213 | if (device->node_id != source) | ||
214 | continue; | ||
215 | |||
216 | if ((t->state == STATE_PENDING) && (t->seqnum == seqnum)) { | ||
217 | t->state = STATE_COMPLETE; | ||
218 | t->size = min_t(unsigned int, length, t->size); | ||
219 | memcpy(t->buf, data, t->size); | ||
220 | wake_up(&t->wait); | ||
221 | *rcode = RCODE_COMPLETE; | ||
222 | } | ||
223 | } | ||
224 | spin_unlock_irqrestore(&transaction_queues_lock, flags); | ||
225 | } | ||
226 | |||
227 | static void | ||
228 | efw_response(struct fw_card *card, struct fw_request *request, | ||
229 | int tcode, int destination, int source, | ||
230 | int generation, unsigned long long offset, | ||
231 | void *data, size_t length, void *callback_data) | ||
232 | { | ||
233 | int rcode, dummy; | ||
234 | u32 seqnum; | ||
235 | |||
236 | rcode = RCODE_TYPE_ERROR; | ||
237 | if (length < sizeof(struct snd_efw_transaction)) { | ||
238 | rcode = RCODE_DATA_ERROR; | ||
239 | goto end; | ||
240 | } else if (offset != MEMORY_SPACE_EFW_RESPONSE) { | ||
241 | rcode = RCODE_ADDRESS_ERROR; | ||
242 | goto end; | ||
243 | } | ||
244 | |||
245 | seqnum = be32_to_cpu(((struct snd_efw_transaction *)data)->seqnum); | ||
246 | if (seqnum > SND_EFW_TRANSACTION_USER_SEQNUM_MAX + 1) { | ||
247 | handle_resp_for_kernel(card, generation, source, | ||
248 | data, length, &rcode, seqnum); | ||
249 | if (snd_efw_resp_buf_debug) | ||
250 | handle_resp_for_user(card, generation, source, | ||
251 | data, length, &dummy); | ||
252 | } else { | ||
253 | handle_resp_for_user(card, generation, source, | ||
254 | data, length, &rcode); | ||
255 | } | ||
256 | end: | ||
257 | fw_send_response(card, request, rcode); | ||
258 | } | ||
259 | |||
260 | void snd_efw_transaction_add_instance(struct snd_efw *efw) | ||
261 | { | ||
262 | unsigned int i; | ||
263 | |||
264 | spin_lock_irq(&instances_lock); | ||
265 | |||
266 | for (i = 0; i < SNDRV_CARDS; i++) { | ||
267 | if (instances[i] != NULL) | ||
268 | continue; | ||
269 | instances[i] = efw; | ||
270 | break; | ||
271 | } | ||
272 | |||
273 | spin_unlock_irq(&instances_lock); | ||
274 | } | ||
275 | |||
276 | void snd_efw_transaction_remove_instance(struct snd_efw *efw) | ||
277 | { | ||
278 | unsigned int i; | ||
279 | |||
280 | spin_lock_irq(&instances_lock); | ||
281 | |||
282 | for (i = 0; i < SNDRV_CARDS; i++) { | ||
283 | if (instances[i] != efw) | ||
284 | continue; | ||
285 | instances[i] = NULL; | ||
286 | } | ||
287 | |||
288 | spin_unlock_irq(&instances_lock); | ||
289 | } | ||
290 | |||
291 | void snd_efw_transaction_bus_reset(struct fw_unit *unit) | ||
292 | { | ||
293 | struct transaction_queue *t; | ||
294 | |||
295 | spin_lock_irq(&transaction_queues_lock); | ||
296 | list_for_each_entry(t, &transaction_queues, list) { | ||
297 | if ((t->unit == unit) && | ||
298 | (t->state == STATE_PENDING)) { | ||
299 | t->state = STATE_BUS_RESET; | ||
300 | wake_up(&t->wait); | ||
301 | } | ||
302 | } | ||
303 | spin_unlock_irq(&transaction_queues_lock); | ||
304 | } | ||
305 | |||
306 | static struct fw_address_handler resp_register_handler = { | ||
307 | .length = SND_EFW_RESPONSE_MAXIMUM_BYTES, | ||
308 | .address_callback = efw_response | ||
309 | }; | ||
310 | |||
311 | int snd_efw_transaction_register(void) | ||
312 | { | ||
313 | static const struct fw_address_region resp_register_region = { | ||
314 | .start = MEMORY_SPACE_EFW_RESPONSE, | ||
315 | .end = MEMORY_SPACE_EFW_RESPONSE + | ||
316 | SND_EFW_RESPONSE_MAXIMUM_BYTES | ||
317 | }; | ||
318 | return fw_core_add_address_handler(&resp_register_handler, | ||
319 | &resp_register_region); | ||
320 | } | ||
321 | |||
322 | void snd_efw_transaction_unregister(void) | ||
323 | { | ||
324 | WARN_ON(!list_empty(&transaction_queues)); | ||
325 | fw_core_remove_address_handler(&resp_register_handler); | ||
326 | } | ||
diff --git a/sound/firewire/speakers.c b/sound/firewire/speakers.c index 9f7ef219b109..768d40ddfebb 100644 --- a/sound/firewire/speakers.c +++ b/sound/firewire/speakers.c | |||
@@ -51,7 +51,7 @@ struct fwspk { | |||
51 | const struct device_info *device_info; | 51 | const struct device_info *device_info; |
52 | struct mutex mutex; | 52 | struct mutex mutex; |
53 | struct cmp_connection connection; | 53 | struct cmp_connection connection; |
54 | struct amdtp_out_stream stream; | 54 | struct amdtp_stream stream; |
55 | bool mute; | 55 | bool mute; |
56 | s16 volume[6]; | 56 | s16 volume[6]; |
57 | s16 volume_min; | 57 | s16 volume_min; |
@@ -167,13 +167,7 @@ static int fwspk_open(struct snd_pcm_substream *substream) | |||
167 | if (err < 0) | 167 | if (err < 0) |
168 | return err; | 168 | return err; |
169 | 169 | ||
170 | err = snd_pcm_hw_constraint_minmax(runtime, | 170 | err = amdtp_stream_add_pcm_hw_constraints(&fwspk->stream, runtime); |
171 | SNDRV_PCM_HW_PARAM_PERIOD_TIME, | ||
172 | 5000, UINT_MAX); | ||
173 | if (err < 0) | ||
174 | return err; | ||
175 | |||
176 | err = snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); | ||
177 | if (err < 0) | 171 | if (err < 0) |
178 | return err; | 172 | return err; |
179 | 173 | ||
@@ -187,48 +181,12 @@ static int fwspk_close(struct snd_pcm_substream *substream) | |||
187 | 181 | ||
188 | static void fwspk_stop_stream(struct fwspk *fwspk) | 182 | static void fwspk_stop_stream(struct fwspk *fwspk) |
189 | { | 183 | { |
190 | if (amdtp_out_stream_running(&fwspk->stream)) { | 184 | if (amdtp_stream_running(&fwspk->stream)) { |
191 | amdtp_out_stream_stop(&fwspk->stream); | 185 | amdtp_stream_stop(&fwspk->stream); |
192 | cmp_connection_break(&fwspk->connection); | 186 | cmp_connection_break(&fwspk->connection); |
193 | } | 187 | } |
194 | } | 188 | } |
195 | 189 | ||
196 | static int fwspk_set_rate(struct fwspk *fwspk, unsigned int sfc) | ||
197 | { | ||
198 | u8 *buf; | ||
199 | int err; | ||
200 | |||
201 | buf = kmalloc(8, GFP_KERNEL); | ||
202 | if (!buf) | ||
203 | return -ENOMEM; | ||
204 | |||
205 | buf[0] = 0x00; /* AV/C, CONTROL */ | ||
206 | buf[1] = 0xff; /* unit */ | ||
207 | buf[2] = 0x19; /* INPUT PLUG SIGNAL FORMAT */ | ||
208 | buf[3] = 0x00; /* plug 0 */ | ||
209 | buf[4] = 0x90; /* format: audio */ | ||
210 | buf[5] = 0x00 | sfc; /* AM824, frequency */ | ||
211 | buf[6] = 0xff; /* SYT (not used) */ | ||
212 | buf[7] = 0xff; | ||
213 | |||
214 | err = fcp_avc_transaction(fwspk->unit, buf, 8, buf, 8, | ||
215 | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5)); | ||
216 | if (err < 0) | ||
217 | goto error; | ||
218 | if (err < 6 || buf[0] != 0x09 /* ACCEPTED */) { | ||
219 | dev_err(&fwspk->unit->device, "failed to set sample rate\n"); | ||
220 | err = -EIO; | ||
221 | goto error; | ||
222 | } | ||
223 | |||
224 | err = 0; | ||
225 | |||
226 | error: | ||
227 | kfree(buf); | ||
228 | |||
229 | return err; | ||
230 | } | ||
231 | |||
232 | static int fwspk_hw_params(struct snd_pcm_substream *substream, | 190 | static int fwspk_hw_params(struct snd_pcm_substream *substream, |
233 | struct snd_pcm_hw_params *hw_params) | 191 | struct snd_pcm_hw_params *hw_params) |
234 | { | 192 | { |
@@ -244,17 +202,20 @@ static int fwspk_hw_params(struct snd_pcm_substream *substream, | |||
244 | if (err < 0) | 202 | if (err < 0) |
245 | goto error; | 203 | goto error; |
246 | 204 | ||
247 | amdtp_out_stream_set_parameters(&fwspk->stream, | 205 | amdtp_stream_set_parameters(&fwspk->stream, |
248 | params_rate(hw_params), | 206 | params_rate(hw_params), |
249 | params_channels(hw_params), | 207 | params_channels(hw_params), |
250 | 0); | 208 | 0); |
251 | 209 | ||
252 | amdtp_out_stream_set_pcm_format(&fwspk->stream, | 210 | amdtp_stream_set_pcm_format(&fwspk->stream, |
253 | params_format(hw_params)); | 211 | params_format(hw_params)); |
254 | 212 | ||
255 | err = fwspk_set_rate(fwspk, fwspk->stream.sfc); | 213 | err = avc_general_set_sig_fmt(fwspk->unit, params_rate(hw_params), |
256 | if (err < 0) | 214 | AVC_GENERAL_PLUG_DIR_IN, 0); |
215 | if (err < 0) { | ||
216 | dev_err(&fwspk->unit->device, "failed to set sample rate\n"); | ||
257 | goto err_buffer; | 217 | goto err_buffer; |
218 | } | ||
258 | 219 | ||
259 | return 0; | 220 | return 0; |
260 | 221 | ||
@@ -282,25 +243,25 @@ static int fwspk_prepare(struct snd_pcm_substream *substream) | |||
282 | 243 | ||
283 | mutex_lock(&fwspk->mutex); | 244 | mutex_lock(&fwspk->mutex); |
284 | 245 | ||
285 | if (amdtp_out_streaming_error(&fwspk->stream)) | 246 | if (amdtp_streaming_error(&fwspk->stream)) |
286 | fwspk_stop_stream(fwspk); | 247 | fwspk_stop_stream(fwspk); |
287 | 248 | ||
288 | if (!amdtp_out_stream_running(&fwspk->stream)) { | 249 | if (!amdtp_stream_running(&fwspk->stream)) { |
289 | err = cmp_connection_establish(&fwspk->connection, | 250 | err = cmp_connection_establish(&fwspk->connection, |
290 | amdtp_out_stream_get_max_payload(&fwspk->stream)); | 251 | amdtp_stream_get_max_payload(&fwspk->stream)); |
291 | if (err < 0) | 252 | if (err < 0) |
292 | goto err_mutex; | 253 | goto err_mutex; |
293 | 254 | ||
294 | err = amdtp_out_stream_start(&fwspk->stream, | 255 | err = amdtp_stream_start(&fwspk->stream, |
295 | fwspk->connection.resources.channel, | 256 | fwspk->connection.resources.channel, |
296 | fwspk->connection.speed); | 257 | fwspk->connection.speed); |
297 | if (err < 0) | 258 | if (err < 0) |
298 | goto err_connection; | 259 | goto err_connection; |
299 | } | 260 | } |
300 | 261 | ||
301 | mutex_unlock(&fwspk->mutex); | 262 | mutex_unlock(&fwspk->mutex); |
302 | 263 | ||
303 | amdtp_out_stream_pcm_prepare(&fwspk->stream); | 264 | amdtp_stream_pcm_prepare(&fwspk->stream); |
304 | 265 | ||
305 | return 0; | 266 | return 0; |
306 | 267 | ||
@@ -327,7 +288,7 @@ static int fwspk_trigger(struct snd_pcm_substream *substream, int cmd) | |||
327 | default: | 288 | default: |
328 | return -EINVAL; | 289 | return -EINVAL; |
329 | } | 290 | } |
330 | amdtp_out_stream_pcm_trigger(&fwspk->stream, pcm); | 291 | amdtp_stream_pcm_trigger(&fwspk->stream, pcm); |
331 | return 0; | 292 | return 0; |
332 | } | 293 | } |
333 | 294 | ||
@@ -335,7 +296,7 @@ static snd_pcm_uframes_t fwspk_pointer(struct snd_pcm_substream *substream) | |||
335 | { | 296 | { |
336 | struct fwspk *fwspk = substream->private_data; | 297 | struct fwspk *fwspk = substream->private_data; |
337 | 298 | ||
338 | return amdtp_out_stream_pcm_pointer(&fwspk->stream); | 299 | return amdtp_stream_pcm_pointer(&fwspk->stream); |
339 | } | 300 | } |
340 | 301 | ||
341 | static int fwspk_create_pcm(struct fwspk *fwspk) | 302 | static int fwspk_create_pcm(struct fwspk *fwspk) |
@@ -653,7 +614,7 @@ static void fwspk_card_free(struct snd_card *card) | |||
653 | { | 614 | { |
654 | struct fwspk *fwspk = card->private_data; | 615 | struct fwspk *fwspk = card->private_data; |
655 | 616 | ||
656 | amdtp_out_stream_destroy(&fwspk->stream); | 617 | amdtp_stream_destroy(&fwspk->stream); |
657 | cmp_connection_destroy(&fwspk->connection); | 618 | cmp_connection_destroy(&fwspk->connection); |
658 | fw_unit_put(fwspk->unit); | 619 | fw_unit_put(fwspk->unit); |
659 | mutex_destroy(&fwspk->mutex); | 620 | mutex_destroy(&fwspk->mutex); |
@@ -679,11 +640,12 @@ static int fwspk_probe(struct fw_unit *unit, | |||
679 | fwspk->unit = fw_unit_get(unit); | 640 | fwspk->unit = fw_unit_get(unit); |
680 | fwspk->device_info = (const struct device_info *)id->driver_data; | 641 | fwspk->device_info = (const struct device_info *)id->driver_data; |
681 | 642 | ||
682 | err = cmp_connection_init(&fwspk->connection, unit, 0); | 643 | err = cmp_connection_init(&fwspk->connection, unit, CMP_INPUT, 0); |
683 | if (err < 0) | 644 | if (err < 0) |
684 | goto err_unit; | 645 | goto err_unit; |
685 | 646 | ||
686 | err = amdtp_out_stream_init(&fwspk->stream, unit, CIP_NONBLOCKING); | 647 | err = amdtp_stream_init(&fwspk->stream, unit, AMDTP_OUT_STREAM, |
648 | CIP_NONBLOCKING); | ||
687 | if (err < 0) | 649 | if (err < 0) |
688 | goto err_connection; | 650 | goto err_connection; |
689 | 651 | ||
@@ -733,21 +695,21 @@ static void fwspk_bus_reset(struct fw_unit *unit) | |||
733 | fcp_bus_reset(fwspk->unit); | 695 | fcp_bus_reset(fwspk->unit); |
734 | 696 | ||
735 | if (cmp_connection_update(&fwspk->connection) < 0) { | 697 | if (cmp_connection_update(&fwspk->connection) < 0) { |
736 | amdtp_out_stream_pcm_abort(&fwspk->stream); | 698 | amdtp_stream_pcm_abort(&fwspk->stream); |
737 | mutex_lock(&fwspk->mutex); | 699 | mutex_lock(&fwspk->mutex); |
738 | fwspk_stop_stream(fwspk); | 700 | fwspk_stop_stream(fwspk); |
739 | mutex_unlock(&fwspk->mutex); | 701 | mutex_unlock(&fwspk->mutex); |
740 | return; | 702 | return; |
741 | } | 703 | } |
742 | 704 | ||
743 | amdtp_out_stream_update(&fwspk->stream); | 705 | amdtp_stream_update(&fwspk->stream); |
744 | } | 706 | } |
745 | 707 | ||
746 | static void fwspk_remove(struct fw_unit *unit) | 708 | static void fwspk_remove(struct fw_unit *unit) |
747 | { | 709 | { |
748 | struct fwspk *fwspk = dev_get_drvdata(&unit->device); | 710 | struct fwspk *fwspk = dev_get_drvdata(&unit->device); |
749 | 711 | ||
750 | amdtp_out_stream_pcm_abort(&fwspk->stream); | 712 | amdtp_stream_pcm_abort(&fwspk->stream); |
751 | snd_card_disconnect(fwspk->card); | 713 | snd_card_disconnect(fwspk->card); |
752 | 714 | ||
753 | mutex_lock(&fwspk->mutex); | 715 | mutex_lock(&fwspk->mutex); |
diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c index 5abbbe477d16..ad55e5cb8e94 100644 --- a/sound/isa/gus/interwave.c +++ b/sound/isa/gus/interwave.c | |||
@@ -442,17 +442,11 @@ static void snd_interwave_detect_memory(struct snd_gus_card *gus) | |||
442 | for (bank_pos = 0; bank_pos < 16L * 1024L * 1024L; bank_pos += 4L * 1024L * 1024L) { | 442 | for (bank_pos = 0; bank_pos < 16L * 1024L * 1024L; bank_pos += 4L * 1024L * 1024L) { |
443 | for (i = 0; i < 8; ++i) | 443 | for (i = 0; i < 8; ++i) |
444 | iwave[i] = snd_gf1_peek(gus, bank_pos + i); | 444 | iwave[i] = snd_gf1_peek(gus, bank_pos + i); |
445 | #ifdef CONFIG_SND_DEBUG_ROM | ||
446 | printk(KERN_DEBUG "ROM at 0x%06x = %8phC\n", bank_pos, iwave); | ||
447 | #endif | ||
448 | if (strncmp(iwave, "INTRWAVE", 8)) | 445 | if (strncmp(iwave, "INTRWAVE", 8)) |
449 | continue; /* first check */ | 446 | continue; /* first check */ |
450 | csum = 0; | 447 | csum = 0; |
451 | for (i = 0; i < sizeof(struct rom_hdr); i++) | 448 | for (i = 0; i < sizeof(struct rom_hdr); i++) |
452 | csum += snd_gf1_peek(gus, bank_pos + i); | 449 | csum += snd_gf1_peek(gus, bank_pos + i); |
453 | #ifdef CONFIG_SND_DEBUG_ROM | ||
454 | printk(KERN_DEBUG "ROM checksum = 0x%x (computed)\n", csum); | ||
455 | #endif | ||
456 | if (csum != 0) | 450 | if (csum != 0) |
457 | continue; /* not valid rom */ | 451 | continue; /* not valid rom */ |
458 | gus->gf1.rom_banks++; | 452 | gus->gf1.rom_banks++; |
diff --git a/sound/isa/sb/sb_mixer.c b/sound/isa/sb/sb_mixer.c index 6496822c1808..1ff78ec9f0ac 100644 --- a/sound/isa/sb/sb_mixer.c +++ b/sound/isa/sb/sb_mixer.c | |||
@@ -818,12 +818,14 @@ int snd_sbmixer_new(struct snd_sb *chip) | |||
818 | return err; | 818 | return err; |
819 | break; | 819 | break; |
820 | case SB_HW_DT019X: | 820 | case SB_HW_DT019X: |
821 | if ((err = snd_sbmixer_init(chip, | 821 | err = snd_sbmixer_init(chip, |
822 | snd_dt019x_controls, | 822 | snd_dt019x_controls, |
823 | ARRAY_SIZE(snd_dt019x_controls), | 823 | ARRAY_SIZE(snd_dt019x_controls), |
824 | snd_dt019x_init_values, | 824 | snd_dt019x_init_values, |
825 | ARRAY_SIZE(snd_dt019x_init_values), | 825 | ARRAY_SIZE(snd_dt019x_init_values), |
826 | "DT019X")) < 0) | 826 | "DT019X"); |
827 | if (err < 0) | ||
828 | return err; | ||
827 | break; | 829 | break; |
828 | default: | 830 | default: |
829 | strcpy(card->mixername, "???"); | 831 | strcpy(card->mixername, "???"); |
diff --git a/sound/mips/au1x00.c b/sound/mips/au1x00.c index d10ef7675268..fbcaa5434fd8 100644 --- a/sound/mips/au1x00.c +++ b/sound/mips/au1x00.c | |||
@@ -648,14 +648,14 @@ static int au1000_ac97_probe(struct platform_device *pdev) | |||
648 | goto out; | 648 | goto out; |
649 | 649 | ||
650 | err = -EBUSY; | 650 | err = -EBUSY; |
651 | au1000->ac97_res_port = request_mem_region(r->start, | 651 | au1000->ac97_res_port = request_mem_region(r->start, resource_size(r), |
652 | r->end - r->start + 1, pdev->name); | 652 | pdev->name); |
653 | if (!au1000->ac97_res_port) { | 653 | if (!au1000->ac97_res_port) { |
654 | snd_printk(KERN_ERR "ALSA AC97: can't grab AC97 port\n"); | 654 | snd_printk(KERN_ERR "ALSA AC97: can't grab AC97 port\n"); |
655 | goto out; | 655 | goto out; |
656 | } | 656 | } |
657 | 657 | ||
658 | io = ioremap(r->start, r->end - r->start + 1); | 658 | io = ioremap(r->start, resource_size(r)); |
659 | if (!io) | 659 | if (!io) |
660 | goto out; | 660 | goto out; |
661 | 661 | ||
diff --git a/sound/oss/mpu401.c b/sound/oss/mpu401.c index 25e4609f8339..3bbc3ec5be82 100644 --- a/sound/oss/mpu401.c +++ b/sound/oss/mpu401.c | |||
@@ -567,7 +567,6 @@ static int mpu401_out(int dev, unsigned char midi_byte) | |||
567 | static int mpu401_command(int dev, mpu_command_rec * cmd) | 567 | static int mpu401_command(int dev, mpu_command_rec * cmd) |
568 | { | 568 | { |
569 | int i, timeout, ok; | 569 | int i, timeout, ok; |
570 | int ret = 0; | ||
571 | unsigned long flags; | 570 | unsigned long flags; |
572 | struct mpu_config *devc; | 571 | struct mpu_config *devc; |
573 | 572 | ||
@@ -644,7 +643,6 @@ retry: | |||
644 | } | 643 | } |
645 | } | 644 | } |
646 | } | 645 | } |
647 | ret = 0; | ||
648 | cmd->data[0] = 0; | 646 | cmd->data[0] = 0; |
649 | 647 | ||
650 | if (cmd->nr_returns) | 648 | if (cmd->nr_returns) |
@@ -666,7 +664,7 @@ retry: | |||
666 | } | 664 | } |
667 | } | 665 | } |
668 | spin_unlock_irqrestore(&devc->lock,flags); | 666 | spin_unlock_irqrestore(&devc->lock,flags); |
669 | return ret; | 667 | return 0; |
670 | } | 668 | } |
671 | 669 | ||
672 | static int mpu_cmd(int dev, int cmd, int data) | 670 | static int mpu_cmd(int dev, int cmd, int data) |
diff --git a/sound/oss/swarm_cs4297a.c b/sound/oss/swarm_cs4297a.c index f851fd0e199c..a33e8ce8085b 100644 --- a/sound/oss/swarm_cs4297a.c +++ b/sound/oss/swarm_cs4297a.c | |||
@@ -2625,15 +2625,12 @@ static int __init cs4297a_init(void) | |||
2625 | u32 pwr, id; | 2625 | u32 pwr, id; |
2626 | mm_segment_t fs; | 2626 | mm_segment_t fs; |
2627 | int rval; | 2627 | int rval; |
2628 | #ifndef CONFIG_BCM_CS4297A_CSWARM | ||
2629 | u64 cfg; | 2628 | u64 cfg; |
2630 | int mdio_val; | 2629 | int mdio_val; |
2631 | #endif | ||
2632 | 2630 | ||
2633 | CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, printk(KERN_INFO | 2631 | CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, printk(KERN_INFO |
2634 | "cs4297a: cs4297a_init_module()+ \n")); | 2632 | "cs4297a: cs4297a_init_module()+ \n")); |
2635 | 2633 | ||
2636 | #ifndef CONFIG_BCM_CS4297A_CSWARM | ||
2637 | mdio_val = __raw_readq(KSEG1 + A_MAC_REGISTER(2, R_MAC_MDIO)) & | 2634 | mdio_val = __raw_readq(KSEG1 + A_MAC_REGISTER(2, R_MAC_MDIO)) & |
2638 | (M_MAC_MDIO_DIR|M_MAC_MDIO_OUT); | 2635 | (M_MAC_MDIO_DIR|M_MAC_MDIO_OUT); |
2639 | 2636 | ||
@@ -2659,7 +2656,6 @@ static int __init cs4297a_init(void) | |||
2659 | __raw_writeq(mdio_val | M_MAC_GENC, KSEG1+A_MAC_REGISTER(2, R_MAC_MDIO)); | 2656 | __raw_writeq(mdio_val | M_MAC_GENC, KSEG1+A_MAC_REGISTER(2, R_MAC_MDIO)); |
2660 | /* Give the codec some time to finish resetting (start the bit clock) */ | 2657 | /* Give the codec some time to finish resetting (start the bit clock) */ |
2661 | udelay(100); | 2658 | udelay(100); |
2662 | #endif | ||
2663 | 2659 | ||
2664 | if (!(s = kzalloc(sizeof(struct cs4297a_state), GFP_KERNEL))) { | 2660 | if (!(s = kzalloc(sizeof(struct cs4297a_state), GFP_KERNEL))) { |
2665 | CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR | 2661 | CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR |
diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c index 8546711d12f9..70951fd9b354 100644 --- a/sound/pci/bt87x.c +++ b/sound/pci/bt87x.c | |||
@@ -443,7 +443,7 @@ static int snd_bt87x_pcm_open(struct snd_pcm_substream *substream) | |||
443 | 443 | ||
444 | _error: | 444 | _error: |
445 | clear_bit(0, &chip->opened); | 445 | clear_bit(0, &chip->opened); |
446 | smp_mb__after_clear_bit(); | 446 | smp_mb__after_atomic(); |
447 | return err; | 447 | return err; |
448 | } | 448 | } |
449 | 449 | ||
@@ -458,7 +458,7 @@ static int snd_bt87x_close(struct snd_pcm_substream *substream) | |||
458 | 458 | ||
459 | chip->substream = NULL; | 459 | chip->substream = NULL; |
460 | clear_bit(0, &chip->opened); | 460 | clear_bit(0, &chip->opened); |
461 | smp_mb__after_clear_bit(); | 461 | smp_mb__after_atomic(); |
462 | return 0; | 462 | return 0; |
463 | } | 463 | } |
464 | 464 | ||
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index db18ccabadd6..529f5f4f4c9c 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
24 | #include <linux/init.h> | 24 | #include <linux/init.h> |
25 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
26 | #include <linux/io.h> | ||
26 | #include <linux/pci.h> | 27 | #include <linux/pci.h> |
27 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
28 | #include <linux/module.h> | 29 | #include <linux/module.h> |
@@ -34,8 +35,6 @@ | |||
34 | #include <sound/opl3.h> | 35 | #include <sound/opl3.h> |
35 | #include <sound/initval.h> | 36 | #include <sound/initval.h> |
36 | 37 | ||
37 | #include <asm/io.h> | ||
38 | |||
39 | #ifdef CONFIG_SND_FM801_TEA575X_BOOL | 38 | #ifdef CONFIG_SND_FM801_TEA575X_BOOL |
40 | #include <media/tea575x.h> | 39 | #include <media/tea575x.h> |
41 | #endif | 40 | #endif |
@@ -80,7 +79,10 @@ MODULE_PARM_DESC(radio_nr, "Radio device numbers"); | |||
80 | * Direct registers | 79 | * Direct registers |
81 | */ | 80 | */ |
82 | 81 | ||
83 | #define FM801_REG(chip, reg) (chip->port + FM801_##reg) | 82 | #define fm801_writew(chip,reg,value) outw((value), chip->port + FM801_##reg) |
83 | #define fm801_readw(chip,reg) inw(chip->port + FM801_##reg) | ||
84 | |||
85 | #define fm801_writel(chip,reg,value) outl((value), chip->port + FM801_##reg) | ||
84 | 86 | ||
85 | #define FM801_PCM_VOL 0x00 /* PCM Output Volume */ | 87 | #define FM801_PCM_VOL 0x00 /* PCM Output Volume */ |
86 | #define FM801_FM_VOL 0x02 /* FM Output Volume */ | 88 | #define FM801_FM_VOL 0x02 /* FM Output Volume */ |
@@ -156,21 +158,27 @@ MODULE_PARM_DESC(radio_nr, "Radio device numbers"); | |||
156 | #define FM801_GPIO_GS3 (1<<15) | 158 | #define FM801_GPIO_GS3 (1<<15) |
157 | #define FM801_GPIO_GS(x) (1<<(12+(x))) | 159 | #define FM801_GPIO_GS(x) (1<<(12+(x))) |
158 | 160 | ||
159 | /* | 161 | /** |
160 | 162 | * struct fm801 - describes FM801 chip | |
163 | * @port: I/O port number | ||
164 | * @multichannel: multichannel support | ||
165 | * @secondary: secondary codec | ||
166 | * @secondary_addr: address of the secondary codec | ||
167 | * @tea575x_tuner: tuner access method & flags | ||
168 | * @ply_ctrl: playback control | ||
169 | * @cap_ctrl: capture control | ||
161 | */ | 170 | */ |
162 | |||
163 | struct fm801 { | 171 | struct fm801 { |
164 | int irq; | 172 | int irq; |
165 | 173 | ||
166 | unsigned long port; /* I/O port number */ | 174 | unsigned long port; |
167 | unsigned int multichannel: 1, /* multichannel support */ | 175 | unsigned int multichannel: 1, |
168 | secondary: 1; /* secondary codec */ | 176 | secondary: 1; |
169 | unsigned char secondary_addr; /* address of the secondary codec */ | 177 | unsigned char secondary_addr; |
170 | unsigned int tea575x_tuner; /* tuner access method & flags */ | 178 | unsigned int tea575x_tuner; |
171 | 179 | ||
172 | unsigned short ply_ctrl; /* playback control */ | 180 | unsigned short ply_ctrl; |
173 | unsigned short cap_ctrl; /* capture control */ | 181 | unsigned short cap_ctrl; |
174 | 182 | ||
175 | unsigned long ply_buffer; | 183 | unsigned long ply_buffer; |
176 | unsigned int ply_buf; | 184 | unsigned int ply_buf; |
@@ -222,6 +230,30 @@ MODULE_DEVICE_TABLE(pci, snd_fm801_ids); | |||
222 | * common I/O routines | 230 | * common I/O routines |
223 | */ | 231 | */ |
224 | 232 | ||
233 | static bool fm801_ac97_is_ready(struct fm801 *chip, unsigned int iterations) | ||
234 | { | ||
235 | unsigned int idx; | ||
236 | |||
237 | for (idx = 0; idx < iterations; idx++) { | ||
238 | if (!(fm801_readw(chip, AC97_CMD) & FM801_AC97_BUSY)) | ||
239 | return true; | ||
240 | udelay(10); | ||
241 | } | ||
242 | return false; | ||
243 | } | ||
244 | |||
245 | static bool fm801_ac97_is_valid(struct fm801 *chip, unsigned int iterations) | ||
246 | { | ||
247 | unsigned int idx; | ||
248 | |||
249 | for (idx = 0; idx < iterations; idx++) { | ||
250 | if (fm801_readw(chip, AC97_CMD) & FM801_AC97_VALID) | ||
251 | return true; | ||
252 | udelay(10); | ||
253 | } | ||
254 | return false; | ||
255 | } | ||
256 | |||
225 | static int snd_fm801_update_bits(struct fm801 *chip, unsigned short reg, | 257 | static int snd_fm801_update_bits(struct fm801 *chip, unsigned short reg, |
226 | unsigned short mask, unsigned short value) | 258 | unsigned short mask, unsigned short value) |
227 | { | 259 | { |
@@ -244,73 +276,54 @@ static void snd_fm801_codec_write(struct snd_ac97 *ac97, | |||
244 | unsigned short val) | 276 | unsigned short val) |
245 | { | 277 | { |
246 | struct fm801 *chip = ac97->private_data; | 278 | struct fm801 *chip = ac97->private_data; |
247 | int idx; | ||
248 | 279 | ||
249 | /* | 280 | /* |
250 | * Wait until the codec interface is not ready.. | 281 | * Wait until the codec interface is not ready.. |
251 | */ | 282 | */ |
252 | for (idx = 0; idx < 100; idx++) { | 283 | if (!fm801_ac97_is_ready(chip, 100)) { |
253 | if (!(inw(FM801_REG(chip, AC97_CMD)) & FM801_AC97_BUSY)) | 284 | dev_err(chip->card->dev, "AC'97 interface is busy (1)\n"); |
254 | goto ok1; | 285 | return; |
255 | udelay(10); | ||
256 | } | 286 | } |
257 | dev_err(chip->card->dev, "AC'97 interface is busy (1)\n"); | ||
258 | return; | ||
259 | 287 | ||
260 | ok1: | ||
261 | /* write data and address */ | 288 | /* write data and address */ |
262 | outw(val, FM801_REG(chip, AC97_DATA)); | 289 | fm801_writew(chip, AC97_DATA, val); |
263 | outw(reg | (ac97->addr << FM801_AC97_ADDR_SHIFT), FM801_REG(chip, AC97_CMD)); | 290 | fm801_writew(chip, AC97_CMD, reg | (ac97->addr << FM801_AC97_ADDR_SHIFT)); |
264 | /* | 291 | /* |
265 | * Wait until the write command is not completed.. | 292 | * Wait until the write command is not completed.. |
266 | */ | 293 | */ |
267 | for (idx = 0; idx < 1000; idx++) { | 294 | if (!fm801_ac97_is_ready(chip, 1000)) |
268 | if (!(inw(FM801_REG(chip, AC97_CMD)) & FM801_AC97_BUSY)) | 295 | dev_err(chip->card->dev, "AC'97 interface #%d is busy (2)\n", |
269 | return; | 296 | ac97->num); |
270 | udelay(10); | ||
271 | } | ||
272 | dev_err(chip->card->dev, "AC'97 interface #%d is busy (2)\n", ac97->num); | ||
273 | } | 297 | } |
274 | 298 | ||
275 | static unsigned short snd_fm801_codec_read(struct snd_ac97 *ac97, unsigned short reg) | 299 | static unsigned short snd_fm801_codec_read(struct snd_ac97 *ac97, unsigned short reg) |
276 | { | 300 | { |
277 | struct fm801 *chip = ac97->private_data; | 301 | struct fm801 *chip = ac97->private_data; |
278 | int idx; | ||
279 | 302 | ||
280 | /* | 303 | /* |
281 | * Wait until the codec interface is not ready.. | 304 | * Wait until the codec interface is not ready.. |
282 | */ | 305 | */ |
283 | for (idx = 0; idx < 100; idx++) { | 306 | if (!fm801_ac97_is_ready(chip, 100)) { |
284 | if (!(inw(FM801_REG(chip, AC97_CMD)) & FM801_AC97_BUSY)) | 307 | dev_err(chip->card->dev, "AC'97 interface is busy (1)\n"); |
285 | goto ok1; | 308 | return 0; |
286 | udelay(10); | ||
287 | } | 309 | } |
288 | dev_err(chip->card->dev, "AC'97 interface is busy (1)\n"); | ||
289 | return 0; | ||
290 | 310 | ||
291 | ok1: | ||
292 | /* read command */ | 311 | /* read command */ |
293 | outw(reg | (ac97->addr << FM801_AC97_ADDR_SHIFT) | FM801_AC97_READ, | 312 | fm801_writew(chip, AC97_CMD, |
294 | FM801_REG(chip, AC97_CMD)); | 313 | reg | (ac97->addr << FM801_AC97_ADDR_SHIFT) | FM801_AC97_READ); |
295 | for (idx = 0; idx < 100; idx++) { | 314 | if (!fm801_ac97_is_ready(chip, 100)) { |
296 | if (!(inw(FM801_REG(chip, AC97_CMD)) & FM801_AC97_BUSY)) | 315 | dev_err(chip->card->dev, "AC'97 interface #%d is busy (2)\n", |
297 | goto ok2; | 316 | ac97->num); |
298 | udelay(10); | 317 | return 0; |
299 | } | 318 | } |
300 | dev_err(chip->card->dev, "AC'97 interface #%d is busy (2)\n", ac97->num); | ||
301 | return 0; | ||
302 | 319 | ||
303 | ok2: | 320 | if (!fm801_ac97_is_valid(chip, 1000)) { |
304 | for (idx = 0; idx < 1000; idx++) { | 321 | dev_err(chip->card->dev, |
305 | if (inw(FM801_REG(chip, AC97_CMD)) & FM801_AC97_VALID) | 322 | "AC'97 interface #%d is not valid (2)\n", ac97->num); |
306 | goto ok3; | 323 | return 0; |
307 | udelay(10); | ||
308 | } | 324 | } |
309 | dev_err(chip->card->dev, "AC'97 interface #%d is not valid (2)\n", ac97->num); | ||
310 | return 0; | ||
311 | 325 | ||
312 | ok3: | 326 | return fm801_readw(chip, AC97_DATA); |
313 | return inw(FM801_REG(chip, AC97_DATA)); | ||
314 | } | 327 | } |
315 | 328 | ||
316 | static unsigned int rates[] = { | 329 | static unsigned int rates[] = { |
@@ -384,7 +397,7 @@ static int snd_fm801_playback_trigger(struct snd_pcm_substream *substream, | |||
384 | snd_BUG(); | 397 | snd_BUG(); |
385 | return -EINVAL; | 398 | return -EINVAL; |
386 | } | 399 | } |
387 | outw(chip->ply_ctrl, FM801_REG(chip, PLY_CTRL)); | 400 | fm801_writew(chip, PLY_CTRL, chip->ply_ctrl); |
388 | spin_unlock(&chip->reg_lock); | 401 | spin_unlock(&chip->reg_lock); |
389 | return 0; | 402 | return 0; |
390 | } | 403 | } |
@@ -419,7 +432,7 @@ static int snd_fm801_capture_trigger(struct snd_pcm_substream *substream, | |||
419 | snd_BUG(); | 432 | snd_BUG(); |
420 | return -EINVAL; | 433 | return -EINVAL; |
421 | } | 434 | } |
422 | outw(chip->cap_ctrl, FM801_REG(chip, CAP_CTRL)); | 435 | fm801_writew(chip, CAP_CTRL, chip->cap_ctrl); |
423 | spin_unlock(&chip->reg_lock); | 436 | spin_unlock(&chip->reg_lock); |
424 | return 0; | 437 | return 0; |
425 | } | 438 | } |
@@ -457,12 +470,13 @@ static int snd_fm801_playback_prepare(struct snd_pcm_substream *substream) | |||
457 | } | 470 | } |
458 | chip->ply_ctrl |= snd_fm801_rate_bits(runtime->rate) << FM801_RATE_SHIFT; | 471 | chip->ply_ctrl |= snd_fm801_rate_bits(runtime->rate) << FM801_RATE_SHIFT; |
459 | chip->ply_buf = 0; | 472 | chip->ply_buf = 0; |
460 | outw(chip->ply_ctrl, FM801_REG(chip, PLY_CTRL)); | 473 | fm801_writew(chip, PLY_CTRL, chip->ply_ctrl); |
461 | outw(chip->ply_count - 1, FM801_REG(chip, PLY_COUNT)); | 474 | fm801_writew(chip, PLY_COUNT, chip->ply_count - 1); |
462 | chip->ply_buffer = runtime->dma_addr; | 475 | chip->ply_buffer = runtime->dma_addr; |
463 | chip->ply_pos = 0; | 476 | chip->ply_pos = 0; |
464 | outl(chip->ply_buffer, FM801_REG(chip, PLY_BUF1)); | 477 | fm801_writel(chip, PLY_BUF1, chip->ply_buffer); |
465 | outl(chip->ply_buffer + (chip->ply_count % chip->ply_size), FM801_REG(chip, PLY_BUF2)); | 478 | fm801_writel(chip, PLY_BUF2, |
479 | chip->ply_buffer + (chip->ply_count % chip->ply_size)); | ||
466 | spin_unlock_irq(&chip->reg_lock); | 480 | spin_unlock_irq(&chip->reg_lock); |
467 | return 0; | 481 | return 0; |
468 | } | 482 | } |
@@ -483,12 +497,13 @@ static int snd_fm801_capture_prepare(struct snd_pcm_substream *substream) | |||
483 | chip->cap_ctrl |= FM801_STEREO; | 497 | chip->cap_ctrl |= FM801_STEREO; |
484 | chip->cap_ctrl |= snd_fm801_rate_bits(runtime->rate) << FM801_RATE_SHIFT; | 498 | chip->cap_ctrl |= snd_fm801_rate_bits(runtime->rate) << FM801_RATE_SHIFT; |
485 | chip->cap_buf = 0; | 499 | chip->cap_buf = 0; |
486 | outw(chip->cap_ctrl, FM801_REG(chip, CAP_CTRL)); | 500 | fm801_writew(chip, CAP_CTRL, chip->cap_ctrl); |
487 | outw(chip->cap_count - 1, FM801_REG(chip, CAP_COUNT)); | 501 | fm801_writew(chip, CAP_COUNT, chip->cap_count - 1); |
488 | chip->cap_buffer = runtime->dma_addr; | 502 | chip->cap_buffer = runtime->dma_addr; |
489 | chip->cap_pos = 0; | 503 | chip->cap_pos = 0; |
490 | outl(chip->cap_buffer, FM801_REG(chip, CAP_BUF1)); | 504 | fm801_writel(chip, CAP_BUF1, chip->cap_buffer); |
491 | outl(chip->cap_buffer + (chip->cap_count % chip->cap_size), FM801_REG(chip, CAP_BUF2)); | 505 | fm801_writel(chip, CAP_BUF2, |
506 | chip->cap_buffer + (chip->cap_count % chip->cap_size)); | ||
492 | spin_unlock_irq(&chip->reg_lock); | 507 | spin_unlock_irq(&chip->reg_lock); |
493 | return 0; | 508 | return 0; |
494 | } | 509 | } |
@@ -501,8 +516,8 @@ static snd_pcm_uframes_t snd_fm801_playback_pointer(struct snd_pcm_substream *su | |||
501 | if (!(chip->ply_ctrl & FM801_START)) | 516 | if (!(chip->ply_ctrl & FM801_START)) |
502 | return 0; | 517 | return 0; |
503 | spin_lock(&chip->reg_lock); | 518 | spin_lock(&chip->reg_lock); |
504 | ptr = chip->ply_pos + (chip->ply_count - 1) - inw(FM801_REG(chip, PLY_COUNT)); | 519 | ptr = chip->ply_pos + (chip->ply_count - 1) - fm801_readw(chip, PLY_COUNT); |
505 | if (inw(FM801_REG(chip, IRQ_STATUS)) & FM801_IRQ_PLAYBACK) { | 520 | if (fm801_readw(chip, IRQ_STATUS) & FM801_IRQ_PLAYBACK) { |
506 | ptr += chip->ply_count; | 521 | ptr += chip->ply_count; |
507 | ptr %= chip->ply_size; | 522 | ptr %= chip->ply_size; |
508 | } | 523 | } |
@@ -518,8 +533,8 @@ static snd_pcm_uframes_t snd_fm801_capture_pointer(struct snd_pcm_substream *sub | |||
518 | if (!(chip->cap_ctrl & FM801_START)) | 533 | if (!(chip->cap_ctrl & FM801_START)) |
519 | return 0; | 534 | return 0; |
520 | spin_lock(&chip->reg_lock); | 535 | spin_lock(&chip->reg_lock); |
521 | ptr = chip->cap_pos + (chip->cap_count - 1) - inw(FM801_REG(chip, CAP_COUNT)); | 536 | ptr = chip->cap_pos + (chip->cap_count - 1) - fm801_readw(chip, CAP_COUNT); |
522 | if (inw(FM801_REG(chip, IRQ_STATUS)) & FM801_IRQ_CAPTURE) { | 537 | if (fm801_readw(chip, IRQ_STATUS) & FM801_IRQ_CAPTURE) { |
523 | ptr += chip->cap_count; | 538 | ptr += chip->cap_count; |
524 | ptr %= chip->cap_size; | 539 | ptr %= chip->cap_size; |
525 | } | 540 | } |
@@ -533,12 +548,12 @@ static irqreturn_t snd_fm801_interrupt(int irq, void *dev_id) | |||
533 | unsigned short status; | 548 | unsigned short status; |
534 | unsigned int tmp; | 549 | unsigned int tmp; |
535 | 550 | ||
536 | status = inw(FM801_REG(chip, IRQ_STATUS)); | 551 | status = fm801_readw(chip, IRQ_STATUS); |
537 | status &= FM801_IRQ_PLAYBACK|FM801_IRQ_CAPTURE|FM801_IRQ_MPU|FM801_IRQ_VOLUME; | 552 | status &= FM801_IRQ_PLAYBACK|FM801_IRQ_CAPTURE|FM801_IRQ_MPU|FM801_IRQ_VOLUME; |
538 | if (! status) | 553 | if (! status) |
539 | return IRQ_NONE; | 554 | return IRQ_NONE; |
540 | /* ack first */ | 555 | /* ack first */ |
541 | outw(status, FM801_REG(chip, IRQ_STATUS)); | 556 | fm801_writew(chip, IRQ_STATUS, status); |
542 | if (chip->pcm && (status & FM801_IRQ_PLAYBACK) && chip->playback_substream) { | 557 | if (chip->pcm && (status & FM801_IRQ_PLAYBACK) && chip->playback_substream) { |
543 | spin_lock(&chip->reg_lock); | 558 | spin_lock(&chip->reg_lock); |
544 | chip->ply_buf++; | 559 | chip->ply_buf++; |
@@ -546,10 +561,10 @@ static irqreturn_t snd_fm801_interrupt(int irq, void *dev_id) | |||
546 | chip->ply_pos %= chip->ply_size; | 561 | chip->ply_pos %= chip->ply_size; |
547 | tmp = chip->ply_pos + chip->ply_count; | 562 | tmp = chip->ply_pos + chip->ply_count; |
548 | tmp %= chip->ply_size; | 563 | tmp %= chip->ply_size; |
549 | outl(chip->ply_buffer + tmp, | 564 | if (chip->ply_buf & 1) |
550 | (chip->ply_buf & 1) ? | 565 | fm801_writel(chip, PLY_BUF1, chip->ply_buffer + tmp); |
551 | FM801_REG(chip, PLY_BUF1) : | 566 | else |
552 | FM801_REG(chip, PLY_BUF2)); | 567 | fm801_writel(chip, PLY_BUF2, chip->ply_buffer + tmp); |
553 | spin_unlock(&chip->reg_lock); | 568 | spin_unlock(&chip->reg_lock); |
554 | snd_pcm_period_elapsed(chip->playback_substream); | 569 | snd_pcm_period_elapsed(chip->playback_substream); |
555 | } | 570 | } |
@@ -560,10 +575,10 @@ static irqreturn_t snd_fm801_interrupt(int irq, void *dev_id) | |||
560 | chip->cap_pos %= chip->cap_size; | 575 | chip->cap_pos %= chip->cap_size; |
561 | tmp = chip->cap_pos + chip->cap_count; | 576 | tmp = chip->cap_pos + chip->cap_count; |
562 | tmp %= chip->cap_size; | 577 | tmp %= chip->cap_size; |
563 | outl(chip->cap_buffer + tmp, | 578 | if (chip->cap_buf & 1) |
564 | (chip->cap_buf & 1) ? | 579 | fm801_writel(chip, CAP_BUF1, chip->cap_buffer + tmp); |
565 | FM801_REG(chip, CAP_BUF1) : | 580 | else |
566 | FM801_REG(chip, CAP_BUF2)); | 581 | fm801_writel(chip, CAP_BUF2, chip->cap_buffer + tmp); |
567 | spin_unlock(&chip->reg_lock); | 582 | spin_unlock(&chip->reg_lock); |
568 | snd_pcm_period_elapsed(chip->capture_substream); | 583 | snd_pcm_period_elapsed(chip->capture_substream); |
569 | } | 584 | } |
@@ -747,7 +762,7 @@ static struct snd_fm801_tea575x_gpio snd_fm801_tea575x_gpios[] = { | |||
747 | static void snd_fm801_tea575x_set_pins(struct snd_tea575x *tea, u8 pins) | 762 | static void snd_fm801_tea575x_set_pins(struct snd_tea575x *tea, u8 pins) |
748 | { | 763 | { |
749 | struct fm801 *chip = tea->private_data; | 764 | struct fm801 *chip = tea->private_data; |
750 | unsigned short reg = inw(FM801_REG(chip, GPIO_CTRL)); | 765 | unsigned short reg = fm801_readw(chip, GPIO_CTRL); |
751 | struct snd_fm801_tea575x_gpio gpio = *get_tea575x_gpio(chip); | 766 | struct snd_fm801_tea575x_gpio gpio = *get_tea575x_gpio(chip); |
752 | 767 | ||
753 | reg &= ~(FM801_GPIO_GP(gpio.data) | | 768 | reg &= ~(FM801_GPIO_GP(gpio.data) | |
@@ -759,13 +774,13 @@ static void snd_fm801_tea575x_set_pins(struct snd_tea575x *tea, u8 pins) | |||
759 | /* WRITE_ENABLE is inverted */ | 774 | /* WRITE_ENABLE is inverted */ |
760 | reg |= (pins & TEA575X_WREN) ? 0 : FM801_GPIO_GP(gpio.wren); | 775 | reg |= (pins & TEA575X_WREN) ? 0 : FM801_GPIO_GP(gpio.wren); |
761 | 776 | ||
762 | outw(reg, FM801_REG(chip, GPIO_CTRL)); | 777 | fm801_writew(chip, GPIO_CTRL, reg); |
763 | } | 778 | } |
764 | 779 | ||
765 | static u8 snd_fm801_tea575x_get_pins(struct snd_tea575x *tea) | 780 | static u8 snd_fm801_tea575x_get_pins(struct snd_tea575x *tea) |
766 | { | 781 | { |
767 | struct fm801 *chip = tea->private_data; | 782 | struct fm801 *chip = tea->private_data; |
768 | unsigned short reg = inw(FM801_REG(chip, GPIO_CTRL)); | 783 | unsigned short reg = fm801_readw(chip, GPIO_CTRL); |
769 | struct snd_fm801_tea575x_gpio gpio = *get_tea575x_gpio(chip); | 784 | struct snd_fm801_tea575x_gpio gpio = *get_tea575x_gpio(chip); |
770 | u8 ret; | 785 | u8 ret; |
771 | 786 | ||
@@ -780,7 +795,7 @@ static u8 snd_fm801_tea575x_get_pins(struct snd_tea575x *tea) | |||
780 | static void snd_fm801_tea575x_set_direction(struct snd_tea575x *tea, bool output) | 795 | static void snd_fm801_tea575x_set_direction(struct snd_tea575x *tea, bool output) |
781 | { | 796 | { |
782 | struct fm801 *chip = tea->private_data; | 797 | struct fm801 *chip = tea->private_data; |
783 | unsigned short reg = inw(FM801_REG(chip, GPIO_CTRL)); | 798 | unsigned short reg = fm801_readw(chip, GPIO_CTRL); |
784 | struct snd_fm801_tea575x_gpio gpio = *get_tea575x_gpio(chip); | 799 | struct snd_fm801_tea575x_gpio gpio = *get_tea575x_gpio(chip); |
785 | 800 | ||
786 | /* use GPIO lines and set write enable bit */ | 801 | /* use GPIO lines and set write enable bit */ |
@@ -811,7 +826,7 @@ static void snd_fm801_tea575x_set_direction(struct snd_tea575x *tea, bool output | |||
811 | FM801_GPIO_GP(gpio.clk)); | 826 | FM801_GPIO_GP(gpio.clk)); |
812 | } | 827 | } |
813 | 828 | ||
814 | outw(reg, FM801_REG(chip, GPIO_CTRL)); | 829 | fm801_writew(chip, GPIO_CTRL, reg); |
815 | } | 830 | } |
816 | 831 | ||
817 | static struct snd_tea575x_ops snd_fm801_tea_ops = { | 832 | static struct snd_tea575x_ops snd_fm801_tea_ops = { |
@@ -962,7 +977,7 @@ static int snd_fm801_get_mux(struct snd_kcontrol *kcontrol, | |||
962 | struct fm801 *chip = snd_kcontrol_chip(kcontrol); | 977 | struct fm801 *chip = snd_kcontrol_chip(kcontrol); |
963 | unsigned short val; | 978 | unsigned short val; |
964 | 979 | ||
965 | val = inw(FM801_REG(chip, REC_SRC)) & 7; | 980 | val = fm801_readw(chip, REC_SRC) & 7; |
966 | if (val > 4) | 981 | if (val > 4) |
967 | val = 4; | 982 | val = 4; |
968 | ucontrol->value.enumerated.item[0] = val; | 983 | ucontrol->value.enumerated.item[0] = val; |
@@ -1073,12 +1088,12 @@ static int wait_for_codec(struct fm801 *chip, unsigned int codec_id, | |||
1073 | { | 1088 | { |
1074 | unsigned long timeout = jiffies + waits; | 1089 | unsigned long timeout = jiffies + waits; |
1075 | 1090 | ||
1076 | outw(FM801_AC97_READ | (codec_id << FM801_AC97_ADDR_SHIFT) | reg, | 1091 | fm801_writew(chip, AC97_CMD, |
1077 | FM801_REG(chip, AC97_CMD)); | 1092 | reg | (codec_id << FM801_AC97_ADDR_SHIFT) | FM801_AC97_READ); |
1078 | udelay(5); | 1093 | udelay(5); |
1079 | do { | 1094 | do { |
1080 | if ((inw(FM801_REG(chip, AC97_CMD)) & (FM801_AC97_VALID|FM801_AC97_BUSY)) | 1095 | if ((fm801_readw(chip, AC97_CMD) & |
1081 | == FM801_AC97_VALID) | 1096 | (FM801_AC97_VALID | FM801_AC97_BUSY)) == FM801_AC97_VALID) |
1082 | return 0; | 1097 | return 0; |
1083 | schedule_timeout_uninterruptible(1); | 1098 | schedule_timeout_uninterruptible(1); |
1084 | } while (time_after(timeout, jiffies)); | 1099 | } while (time_after(timeout, jiffies)); |
@@ -1093,10 +1108,10 @@ static int snd_fm801_chip_init(struct fm801 *chip, int resume) | |||
1093 | goto __ac97_ok; | 1108 | goto __ac97_ok; |
1094 | 1109 | ||
1095 | /* codec cold reset + AC'97 warm reset */ | 1110 | /* codec cold reset + AC'97 warm reset */ |
1096 | outw((1<<5) | (1<<6), FM801_REG(chip, CODEC_CTRL)); | 1111 | fm801_writew(chip, CODEC_CTRL, (1 << 5) | (1 << 6)); |
1097 | inw(FM801_REG(chip, CODEC_CTRL)); /* flush posting data */ | 1112 | fm801_readw(chip, CODEC_CTRL); /* flush posting data */ |
1098 | udelay(100); | 1113 | udelay(100); |
1099 | outw(0, FM801_REG(chip, CODEC_CTRL)); | 1114 | fm801_writew(chip, CODEC_CTRL, 0); |
1100 | 1115 | ||
1101 | if (wait_for_codec(chip, 0, AC97_RESET, msecs_to_jiffies(750)) < 0) | 1116 | if (wait_for_codec(chip, 0, AC97_RESET, msecs_to_jiffies(750)) < 0) |
1102 | if (!resume) { | 1117 | if (!resume) { |
@@ -1117,7 +1132,7 @@ static int snd_fm801_chip_init(struct fm801 *chip, int resume) | |||
1117 | for (i = 3; i > 0; i--) { | 1132 | for (i = 3; i > 0; i--) { |
1118 | if (!wait_for_codec(chip, i, AC97_VENDOR_ID1, | 1133 | if (!wait_for_codec(chip, i, AC97_VENDOR_ID1, |
1119 | msecs_to_jiffies(50))) { | 1134 | msecs_to_jiffies(50))) { |
1120 | cmdw = inw(FM801_REG(chip, AC97_DATA)); | 1135 | cmdw = fm801_readw(chip, AC97_DATA); |
1121 | if (cmdw != 0xffff && cmdw != 0) { | 1136 | if (cmdw != 0xffff && cmdw != 0) { |
1122 | chip->secondary = 1; | 1137 | chip->secondary = 1; |
1123 | chip->secondary_addr = i; | 1138 | chip->secondary_addr = i; |
@@ -1135,23 +1150,24 @@ static int snd_fm801_chip_init(struct fm801 *chip, int resume) | |||
1135 | __ac97_ok: | 1150 | __ac97_ok: |
1136 | 1151 | ||
1137 | /* init volume */ | 1152 | /* init volume */ |
1138 | outw(0x0808, FM801_REG(chip, PCM_VOL)); | 1153 | fm801_writew(chip, PCM_VOL, 0x0808); |
1139 | outw(0x9f1f, FM801_REG(chip, FM_VOL)); | 1154 | fm801_writew(chip, FM_VOL, 0x9f1f); |
1140 | outw(0x8808, FM801_REG(chip, I2S_VOL)); | 1155 | fm801_writew(chip, I2S_VOL, 0x8808); |
1141 | 1156 | ||
1142 | /* I2S control - I2S mode */ | 1157 | /* I2S control - I2S mode */ |
1143 | outw(0x0003, FM801_REG(chip, I2S_MODE)); | 1158 | fm801_writew(chip, I2S_MODE, 0x0003); |
1144 | 1159 | ||
1145 | /* interrupt setup */ | 1160 | /* interrupt setup */ |
1146 | cmdw = inw(FM801_REG(chip, IRQ_MASK)); | 1161 | cmdw = fm801_readw(chip, IRQ_MASK); |
1147 | if (chip->irq < 0) | 1162 | if (chip->irq < 0) |
1148 | cmdw |= 0x00c3; /* mask everything, no PCM nor MPU */ | 1163 | cmdw |= 0x00c3; /* mask everything, no PCM nor MPU */ |
1149 | else | 1164 | else |
1150 | cmdw &= ~0x0083; /* unmask MPU, PLAYBACK & CAPTURE */ | 1165 | cmdw &= ~0x0083; /* unmask MPU, PLAYBACK & CAPTURE */ |
1151 | outw(cmdw, FM801_REG(chip, IRQ_MASK)); | 1166 | fm801_writew(chip, IRQ_MASK, cmdw); |
1152 | 1167 | ||
1153 | /* interrupt clear */ | 1168 | /* interrupt clear */ |
1154 | outw(FM801_IRQ_PLAYBACK|FM801_IRQ_CAPTURE|FM801_IRQ_MPU, FM801_REG(chip, IRQ_STATUS)); | 1169 | fm801_writew(chip, IRQ_STATUS, |
1170 | FM801_IRQ_PLAYBACK | FM801_IRQ_CAPTURE | FM801_IRQ_MPU); | ||
1155 | 1171 | ||
1156 | return 0; | 1172 | return 0; |
1157 | } | 1173 | } |
@@ -1165,9 +1181,9 @@ static int snd_fm801_free(struct fm801 *chip) | |||
1165 | goto __end_hw; | 1181 | goto __end_hw; |
1166 | 1182 | ||
1167 | /* interrupt setup - mask everything */ | 1183 | /* interrupt setup - mask everything */ |
1168 | cmdw = inw(FM801_REG(chip, IRQ_MASK)); | 1184 | cmdw = fm801_readw(chip, IRQ_MASK); |
1169 | cmdw |= 0x00c3; | 1185 | cmdw |= 0x00c3; |
1170 | outw(cmdw, FM801_REG(chip, IRQ_MASK)); | 1186 | fm801_writew(chip, IRQ_MASK, cmdw); |
1171 | 1187 | ||
1172 | __end_hw: | 1188 | __end_hw: |
1173 | #ifdef CONFIG_SND_FM801_TEA575X_BOOL | 1189 | #ifdef CONFIG_SND_FM801_TEA575X_BOOL |
@@ -1339,15 +1355,15 @@ static int snd_card_fm801_probe(struct pci_dev *pci, | |||
1339 | return err; | 1355 | return err; |
1340 | } | 1356 | } |
1341 | if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_FM801, | 1357 | if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_FM801, |
1342 | FM801_REG(chip, MPU401_DATA), | 1358 | chip->port + FM801_MPU401_DATA, |
1343 | MPU401_INFO_INTEGRATED | | 1359 | MPU401_INFO_INTEGRATED | |
1344 | MPU401_INFO_IRQ_HOOK, | 1360 | MPU401_INFO_IRQ_HOOK, |
1345 | -1, &chip->rmidi)) < 0) { | 1361 | -1, &chip->rmidi)) < 0) { |
1346 | snd_card_free(card); | 1362 | snd_card_free(card); |
1347 | return err; | 1363 | return err; |
1348 | } | 1364 | } |
1349 | if ((err = snd_opl3_create(card, FM801_REG(chip, OPL3_BANK0), | 1365 | if ((err = snd_opl3_create(card, chip->port + FM801_OPL3_BANK0, |
1350 | FM801_REG(chip, OPL3_BANK1), | 1366 | chip->port + FM801_OPL3_BANK1, |
1351 | OPL3_HW_OPL3_FM801, 1, &opl3)) < 0) { | 1367 | OPL3_HW_OPL3_FM801, 1, &opl3)) < 0) { |
1352 | snd_card_free(card); | 1368 | snd_card_free(card); |
1353 | return err; | 1369 | return err; |
diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig index ac17c3fc9388..ebf4c2fb99df 100644 --- a/sound/pci/hda/Kconfig +++ b/sound/pci/hda/Kconfig | |||
@@ -20,6 +20,21 @@ config SND_HDA_INTEL | |||
20 | To compile this driver as a module, choose M here: the module | 20 | To compile this driver as a module, choose M here: the module |
21 | will be called snd-hda-intel. | 21 | will be called snd-hda-intel. |
22 | 22 | ||
23 | config SND_HDA_TEGRA | ||
24 | tristate "NVIDIA Tegra HD Audio" | ||
25 | depends on ARCH_TEGRA | ||
26 | select SND_HDA | ||
27 | help | ||
28 | Say Y here to support the HDA controller present in NVIDIA | ||
29 | Tegra SoCs | ||
30 | |||
31 | This options enables support for the HD Audio controller | ||
32 | present in some NVIDIA Tegra SoCs, used to communicate audio | ||
33 | to the HDMI output. | ||
34 | |||
35 | To compile this driver as a module, choose M here: the module | ||
36 | will be called snd-hda-tegra. | ||
37 | |||
23 | if SND_HDA | 38 | if SND_HDA |
24 | 39 | ||
25 | config SND_HDA_DSP_LOADER | 40 | config SND_HDA_DSP_LOADER |
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile index d0d0c19ddfc2..194f30935e77 100644 --- a/sound/pci/hda/Makefile +++ b/sound/pci/hda/Makefile | |||
@@ -1,5 +1,6 @@ | |||
1 | snd-hda-intel-objs := hda_intel.o | 1 | snd-hda-intel-objs := hda_intel.o |
2 | snd-hda-controller-objs := hda_controller.o | 2 | snd-hda-controller-objs := hda_controller.o |
3 | snd-hda-tegra-objs := hda_tegra.o | ||
3 | # for haswell power well | 4 | # for haswell power well |
4 | snd-hda-intel-$(CONFIG_SND_HDA_I915) += hda_i915.o | 5 | snd-hda-intel-$(CONFIG_SND_HDA_I915) += hda_i915.o |
5 | 6 | ||
@@ -47,3 +48,4 @@ obj-$(CONFIG_SND_HDA_CODEC_HDMI) += snd-hda-codec-hdmi.o | |||
47 | # otherwise the codec patches won't be hooked before the PCI probe | 48 | # otherwise the codec patches won't be hooked before the PCI probe |
48 | # when built in kernel | 49 | # when built in kernel |
49 | obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-intel.o | 50 | obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-intel.o |
51 | obj-$(CONFIG_SND_HDA_TEGRA) += snd-hda-tegra.o | ||
diff --git a/sound/pci/hda/hda_auto_parser.c b/sound/pci/hda/hda_auto_parser.c index 90d2fda6c8f9..b684c6e4f301 100644 --- a/sound/pci/hda/hda_auto_parser.c +++ b/sound/pci/hda/hda_auto_parser.c | |||
@@ -839,6 +839,43 @@ void snd_hda_apply_fixup(struct hda_codec *codec, int action) | |||
839 | } | 839 | } |
840 | EXPORT_SYMBOL_GPL(snd_hda_apply_fixup); | 840 | EXPORT_SYMBOL_GPL(snd_hda_apply_fixup); |
841 | 841 | ||
842 | static bool pin_config_match(struct hda_codec *codec, | ||
843 | const struct hda_pintbl *pins) | ||
844 | { | ||
845 | for (; pins->nid; pins++) { | ||
846 | u32 def_conf = snd_hda_codec_get_pincfg(codec, pins->nid); | ||
847 | if (pins->val != def_conf) | ||
848 | return false; | ||
849 | } | ||
850 | return true; | ||
851 | } | ||
852 | |||
853 | void snd_hda_pick_pin_fixup(struct hda_codec *codec, | ||
854 | const struct snd_hda_pin_quirk *pin_quirk, | ||
855 | const struct hda_fixup *fixlist) | ||
856 | { | ||
857 | const struct snd_hda_pin_quirk *pq; | ||
858 | |||
859 | if (codec->fixup_forced) | ||
860 | return; | ||
861 | |||
862 | for (pq = pin_quirk; pq->subvendor; pq++) { | ||
863 | if ((codec->subsystem_id & 0xffff0000) != (pq->subvendor << 16)) | ||
864 | continue; | ||
865 | if (codec->vendor_id != pq->codec) | ||
866 | continue; | ||
867 | if (pin_config_match(codec, pq->pins)) { | ||
868 | codec->fixup_id = pq->value; | ||
869 | #ifdef CONFIG_SND_DEBUG_VERBOSE | ||
870 | codec->fixup_name = pq->name; | ||
871 | #endif | ||
872 | codec->fixup_list = fixlist; | ||
873 | return; | ||
874 | } | ||
875 | } | ||
876 | } | ||
877 | EXPORT_SYMBOL_GPL(snd_hda_pick_pin_fixup); | ||
878 | |||
842 | void snd_hda_pick_fixup(struct hda_codec *codec, | 879 | void snd_hda_pick_fixup(struct hda_codec *codec, |
843 | const struct hda_model_fixup *models, | 880 | const struct hda_model_fixup *models, |
844 | const struct snd_pci_quirk *quirk, | 881 | const struct snd_pci_quirk *quirk, |
@@ -852,15 +889,17 @@ void snd_hda_pick_fixup(struct hda_codec *codec, | |||
852 | if (codec->modelname && !strcmp(codec->modelname, "nofixup")) { | 889 | if (codec->modelname && !strcmp(codec->modelname, "nofixup")) { |
853 | codec->fixup_list = NULL; | 890 | codec->fixup_list = NULL; |
854 | codec->fixup_id = -1; | 891 | codec->fixup_id = -1; |
892 | codec->fixup_forced = 1; | ||
855 | return; | 893 | return; |
856 | } | 894 | } |
857 | 895 | ||
858 | if (codec->modelname && models) { | 896 | if (codec->modelname && models) { |
859 | while (models->name) { | 897 | while (models->name) { |
860 | if (!strcmp(codec->modelname, models->name)) { | 898 | if (!strcmp(codec->modelname, models->name)) { |
861 | id = models->id; | 899 | codec->fixup_id = models->id; |
862 | name = models->name; | 900 | codec->fixup_name = models->name; |
863 | break; | 901 | codec->fixup_forced = 1; |
902 | return; | ||
864 | } | 903 | } |
865 | models++; | 904 | models++; |
866 | } | 905 | } |
@@ -889,6 +928,7 @@ void snd_hda_pick_fixup(struct hda_codec *codec, | |||
889 | } | 928 | } |
890 | } | 929 | } |
891 | 930 | ||
931 | codec->fixup_forced = 0; | ||
892 | codec->fixup_id = id; | 932 | codec->fixup_id = id; |
893 | if (id >= 0) { | 933 | if (id >= 0) { |
894 | codec->fixup_list = fixlist; | 934 | codec->fixup_list = fixlist; |
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index a4233136cb93..5825aa17d8e3 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
@@ -402,6 +402,7 @@ struct hda_codec { | |||
402 | 402 | ||
403 | /* fix-up list */ | 403 | /* fix-up list */ |
404 | int fixup_id; | 404 | int fixup_id; |
405 | unsigned int fixup_forced:1; /* fixup explicitly set by user */ | ||
405 | const struct hda_fixup *fixup_list; | 406 | const struct hda_fixup *fixup_list; |
406 | const char *fixup_name; | 407 | const char *fixup_name; |
407 | 408 | ||
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 16133881e967..589e47c5aeb3 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c | |||
@@ -3722,7 +3722,7 @@ static void parse_digital(struct hda_codec *codec) | |||
3722 | } else { | 3722 | } else { |
3723 | spec->multiout.slave_dig_outs = spec->slave_dig_outs; | 3723 | spec->multiout.slave_dig_outs = spec->slave_dig_outs; |
3724 | if (nums >= ARRAY_SIZE(spec->slave_dig_outs) - 1) | 3724 | if (nums >= ARRAY_SIZE(spec->slave_dig_outs) - 1) |
3725 | break; | 3725 | break; |
3726 | spec->slave_dig_outs[nums - 1] = dig_nid; | 3726 | spec->slave_dig_outs[nums - 1] = dig_nid; |
3727 | } | 3727 | } |
3728 | nums++; | 3728 | nums++; |
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index b540ad71eb0d..bb65a124e006 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -237,6 +237,12 @@ enum { | |||
237 | AZX_DCAPS_COUNT_LPIB_DELAY | AZX_DCAPS_PM_RUNTIME | \ | 237 | AZX_DCAPS_COUNT_LPIB_DELAY | AZX_DCAPS_PM_RUNTIME | \ |
238 | AZX_DCAPS_I915_POWERWELL) | 238 | AZX_DCAPS_I915_POWERWELL) |
239 | 239 | ||
240 | /* Broadwell HDMI can't use position buffer reliably, force to use LPIB */ | ||
241 | #define AZX_DCAPS_INTEL_BROADWELL \ | ||
242 | (AZX_DCAPS_SCH_SNOOP | AZX_DCAPS_ALIGN_BUFSIZE | \ | ||
243 | AZX_DCAPS_POSFIX_LPIB | AZX_DCAPS_PM_RUNTIME | \ | ||
244 | AZX_DCAPS_I915_POWERWELL) | ||
245 | |||
240 | /* quirks for ATI SB / AMD Hudson */ | 246 | /* quirks for ATI SB / AMD Hudson */ |
241 | #define AZX_DCAPS_PRESET_ATI_SB \ | 247 | #define AZX_DCAPS_PRESET_ATI_SB \ |
242 | (AZX_DCAPS_ATI_SNOOP | AZX_DCAPS_NO_TCSEL | \ | 248 | (AZX_DCAPS_ATI_SNOOP | AZX_DCAPS_NO_TCSEL | \ |
@@ -1724,7 +1730,7 @@ static void azx_remove(struct pci_dev *pci) | |||
1724 | } | 1730 | } |
1725 | 1731 | ||
1726 | /* PCI IDs */ | 1732 | /* PCI IDs */ |
1727 | static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { | 1733 | static const struct pci_device_id azx_ids[] = { |
1728 | /* CPT */ | 1734 | /* CPT */ |
1729 | { PCI_DEVICE(0x8086, 0x1c20), | 1735 | { PCI_DEVICE(0x8086, 0x1c20), |
1730 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM }, | 1736 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM }, |
@@ -1737,6 +1743,9 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { | |||
1737 | /* Lynx Point */ | 1743 | /* Lynx Point */ |
1738 | { PCI_DEVICE(0x8086, 0x8c20), | 1744 | { PCI_DEVICE(0x8086, 0x8c20), |
1739 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, | 1745 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, |
1746 | /* 9 Series */ | ||
1747 | { PCI_DEVICE(0x8086, 0x8ca0), | ||
1748 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, | ||
1740 | /* Wellsburg */ | 1749 | /* Wellsburg */ |
1741 | { PCI_DEVICE(0x8086, 0x8d20), | 1750 | { PCI_DEVICE(0x8086, 0x8d20), |
1742 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, | 1751 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, |
@@ -1760,7 +1769,7 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { | |||
1760 | .driver_data = AZX_DRIVER_HDMI | AZX_DCAPS_INTEL_HASWELL }, | 1769 | .driver_data = AZX_DRIVER_HDMI | AZX_DCAPS_INTEL_HASWELL }, |
1761 | /* Broadwell */ | 1770 | /* Broadwell */ |
1762 | { PCI_DEVICE(0x8086, 0x160c), | 1771 | { PCI_DEVICE(0x8086, 0x160c), |
1763 | .driver_data = AZX_DRIVER_HDMI | AZX_DCAPS_INTEL_HASWELL }, | 1772 | .driver_data = AZX_DRIVER_HDMI | AZX_DCAPS_INTEL_BROADWELL }, |
1764 | /* 5 Series/3400 */ | 1773 | /* 5 Series/3400 */ |
1765 | { PCI_DEVICE(0x8086, 0x3b56), | 1774 | { PCI_DEVICE(0x8086, 0x3b56), |
1766 | .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_NOPM }, | 1775 | .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_NOPM }, |
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index e51d15529215..ebd1fa6f015c 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h | |||
@@ -407,6 +407,16 @@ struct hda_fixup { | |||
407 | } v; | 407 | } v; |
408 | }; | 408 | }; |
409 | 409 | ||
410 | struct snd_hda_pin_quirk { | ||
411 | unsigned int codec; /* Codec vendor/device ID */ | ||
412 | unsigned short subvendor; /* PCI subvendor ID */ | ||
413 | const struct hda_pintbl *pins; /* list of matching pins */ | ||
414 | #ifdef CONFIG_SND_DEBUG_VERBOSE | ||
415 | const char *name; | ||
416 | #endif | ||
417 | int value; /* quirk value */ | ||
418 | }; | ||
419 | |||
410 | /* fixup types */ | 420 | /* fixup types */ |
411 | enum { | 421 | enum { |
412 | HDA_FIXUP_INVALID, | 422 | HDA_FIXUP_INVALID, |
@@ -434,6 +444,10 @@ void snd_hda_pick_fixup(struct hda_codec *codec, | |||
434 | const struct hda_model_fixup *models, | 444 | const struct hda_model_fixup *models, |
435 | const struct snd_pci_quirk *quirk, | 445 | const struct snd_pci_quirk *quirk, |
436 | const struct hda_fixup *fixlist); | 446 | const struct hda_fixup *fixlist); |
447 | void snd_hda_pick_pin_fixup(struct hda_codec *codec, | ||
448 | const struct snd_hda_pin_quirk *pin_quirk, | ||
449 | const struct hda_fixup *fixlist); | ||
450 | |||
437 | 451 | ||
438 | /* | 452 | /* |
439 | * unsolicited event handler | 453 | * unsolicited event handler |
diff --git a/sound/pci/hda/hda_tegra.c b/sound/pci/hda/hda_tegra.c new file mode 100644 index 000000000000..a366ba9293a8 --- /dev/null +++ b/sound/pci/hda/hda_tegra.c | |||
@@ -0,0 +1,588 @@ | |||
1 | /* | ||
2 | * | ||
3 | * Implementation of primary ALSA driver code base for NVIDIA Tegra HDA. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms and conditions of the GNU General Public License, | ||
7 | * version 2, as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
16 | * | ||
17 | */ | ||
18 | |||
19 | #include <linux/clk.h> | ||
20 | #include <linux/clocksource.h> | ||
21 | #include <linux/completion.h> | ||
22 | #include <linux/delay.h> | ||
23 | #include <linux/dma-mapping.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/interrupt.h> | ||
26 | #include <linux/io.h> | ||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/moduleparam.h> | ||
30 | #include <linux/mutex.h> | ||
31 | #include <linux/of_device.h> | ||
32 | #include <linux/reboot.h> | ||
33 | #include <linux/slab.h> | ||
34 | #include <linux/time.h> | ||
35 | |||
36 | #include <sound/core.h> | ||
37 | #include <sound/initval.h> | ||
38 | |||
39 | #include "hda_codec.h" | ||
40 | #include "hda_controller.h" | ||
41 | #include "hda_priv.h" | ||
42 | |||
43 | /* Defines for Nvidia Tegra HDA support */ | ||
44 | #define HDA_BAR0 0x8000 | ||
45 | |||
46 | #define HDA_CFG_CMD 0x1004 | ||
47 | #define HDA_CFG_BAR0 0x1010 | ||
48 | |||
49 | #define HDA_ENABLE_IO_SPACE (1 << 0) | ||
50 | #define HDA_ENABLE_MEM_SPACE (1 << 1) | ||
51 | #define HDA_ENABLE_BUS_MASTER (1 << 2) | ||
52 | #define HDA_ENABLE_SERR (1 << 8) | ||
53 | #define HDA_DISABLE_INTR (1 << 10) | ||
54 | #define HDA_BAR0_INIT_PROGRAM 0xFFFFFFFF | ||
55 | #define HDA_BAR0_FINAL_PROGRAM (1 << 14) | ||
56 | |||
57 | /* IPFS */ | ||
58 | #define HDA_IPFS_CONFIG 0x180 | ||
59 | #define HDA_IPFS_EN_FPCI 0x1 | ||
60 | |||
61 | #define HDA_IPFS_FPCI_BAR0 0x80 | ||
62 | #define HDA_FPCI_BAR0_START 0x40 | ||
63 | |||
64 | #define HDA_IPFS_INTR_MASK 0x188 | ||
65 | #define HDA_IPFS_EN_INTR (1 << 16) | ||
66 | |||
67 | /* max number of SDs */ | ||
68 | #define NUM_CAPTURE_SD 1 | ||
69 | #define NUM_PLAYBACK_SD 1 | ||
70 | |||
71 | struct hda_tegra { | ||
72 | struct azx chip; | ||
73 | struct device *dev; | ||
74 | struct clk *hda_clk; | ||
75 | struct clk *hda2codec_2x_clk; | ||
76 | struct clk *hda2hdmi_clk; | ||
77 | void __iomem *regs; | ||
78 | }; | ||
79 | |||
80 | #ifdef CONFIG_PM | ||
81 | static int power_save = CONFIG_SND_HDA_POWER_SAVE_DEFAULT; | ||
82 | module_param(power_save, bint, 0644); | ||
83 | MODULE_PARM_DESC(power_save, | ||
84 | "Automatic power-saving timeout (in seconds, 0 = disable)."); | ||
85 | #else | ||
86 | static int power_save = 0; | ||
87 | #endif | ||
88 | |||
89 | /* | ||
90 | * DMA page allocation ops. | ||
91 | */ | ||
92 | static int dma_alloc_pages(struct azx *chip, int type, size_t size, | ||
93 | struct snd_dma_buffer *buf) | ||
94 | { | ||
95 | return snd_dma_alloc_pages(type, chip->card->dev, size, buf); | ||
96 | } | ||
97 | |||
98 | static void dma_free_pages(struct azx *chip, struct snd_dma_buffer *buf) | ||
99 | { | ||
100 | snd_dma_free_pages(buf); | ||
101 | } | ||
102 | |||
103 | static int substream_alloc_pages(struct azx *chip, | ||
104 | struct snd_pcm_substream *substream, | ||
105 | size_t size) | ||
106 | { | ||
107 | struct azx_dev *azx_dev = get_azx_dev(substream); | ||
108 | |||
109 | azx_dev->bufsize = 0; | ||
110 | azx_dev->period_bytes = 0; | ||
111 | azx_dev->format_val = 0; | ||
112 | return snd_pcm_lib_malloc_pages(substream, size); | ||
113 | } | ||
114 | |||
115 | static int substream_free_pages(struct azx *chip, | ||
116 | struct snd_pcm_substream *substream) | ||
117 | { | ||
118 | return snd_pcm_lib_free_pages(substream); | ||
119 | } | ||
120 | |||
121 | /* | ||
122 | * Register access ops. Tegra HDA register access is DWORD only. | ||
123 | */ | ||
124 | static void hda_tegra_writel(u32 value, u32 *addr) | ||
125 | { | ||
126 | writel(value, addr); | ||
127 | } | ||
128 | |||
129 | static u32 hda_tegra_readl(u32 *addr) | ||
130 | { | ||
131 | return readl(addr); | ||
132 | } | ||
133 | |||
134 | static void hda_tegra_writew(u16 value, u16 *addr) | ||
135 | { | ||
136 | unsigned int shift = ((unsigned long)(addr) & 0x3) << 3; | ||
137 | void *dword_addr = (void *)((unsigned long)(addr) & ~0x3); | ||
138 | u32 v; | ||
139 | |||
140 | v = readl(dword_addr); | ||
141 | v &= ~(0xffff << shift); | ||
142 | v |= value << shift; | ||
143 | writel(v, dword_addr); | ||
144 | } | ||
145 | |||
146 | static u16 hda_tegra_readw(u16 *addr) | ||
147 | { | ||
148 | unsigned int shift = ((unsigned long)(addr) & 0x3) << 3; | ||
149 | void *dword_addr = (void *)((unsigned long)(addr) & ~0x3); | ||
150 | u32 v; | ||
151 | |||
152 | v = readl(dword_addr); | ||
153 | return (v >> shift) & 0xffff; | ||
154 | } | ||
155 | |||
156 | static void hda_tegra_writeb(u8 value, u8 *addr) | ||
157 | { | ||
158 | unsigned int shift = ((unsigned long)(addr) & 0x3) << 3; | ||
159 | void *dword_addr = (void *)((unsigned long)(addr) & ~0x3); | ||
160 | u32 v; | ||
161 | |||
162 | v = readl(dword_addr); | ||
163 | v &= ~(0xff << shift); | ||
164 | v |= value << shift; | ||
165 | writel(v, dword_addr); | ||
166 | } | ||
167 | |||
168 | static u8 hda_tegra_readb(u8 *addr) | ||
169 | { | ||
170 | unsigned int shift = ((unsigned long)(addr) & 0x3) << 3; | ||
171 | void *dword_addr = (void *)((unsigned long)(addr) & ~0x3); | ||
172 | u32 v; | ||
173 | |||
174 | v = readl(dword_addr); | ||
175 | return (v >> shift) & 0xff; | ||
176 | } | ||
177 | |||
178 | static const struct hda_controller_ops hda_tegra_ops = { | ||
179 | .reg_writel = hda_tegra_writel, | ||
180 | .reg_readl = hda_tegra_readl, | ||
181 | .reg_writew = hda_tegra_writew, | ||
182 | .reg_readw = hda_tegra_readw, | ||
183 | .reg_writeb = hda_tegra_writeb, | ||
184 | .reg_readb = hda_tegra_readb, | ||
185 | .dma_alloc_pages = dma_alloc_pages, | ||
186 | .dma_free_pages = dma_free_pages, | ||
187 | .substream_alloc_pages = substream_alloc_pages, | ||
188 | .substream_free_pages = substream_free_pages, | ||
189 | }; | ||
190 | |||
191 | static void hda_tegra_init(struct hda_tegra *hda) | ||
192 | { | ||
193 | u32 v; | ||
194 | |||
195 | /* Enable PCI access */ | ||
196 | v = readl(hda->regs + HDA_IPFS_CONFIG); | ||
197 | v |= HDA_IPFS_EN_FPCI; | ||
198 | writel(v, hda->regs + HDA_IPFS_CONFIG); | ||
199 | |||
200 | /* Enable MEM/IO space and bus master */ | ||
201 | v = readl(hda->regs + HDA_CFG_CMD); | ||
202 | v &= ~HDA_DISABLE_INTR; | ||
203 | v |= HDA_ENABLE_MEM_SPACE | HDA_ENABLE_IO_SPACE | | ||
204 | HDA_ENABLE_BUS_MASTER | HDA_ENABLE_SERR; | ||
205 | writel(v, hda->regs + HDA_CFG_CMD); | ||
206 | |||
207 | writel(HDA_BAR0_INIT_PROGRAM, hda->regs + HDA_CFG_BAR0); | ||
208 | writel(HDA_BAR0_FINAL_PROGRAM, hda->regs + HDA_CFG_BAR0); | ||
209 | writel(HDA_FPCI_BAR0_START, hda->regs + HDA_IPFS_FPCI_BAR0); | ||
210 | |||
211 | v = readl(hda->regs + HDA_IPFS_INTR_MASK); | ||
212 | v |= HDA_IPFS_EN_INTR; | ||
213 | writel(v, hda->regs + HDA_IPFS_INTR_MASK); | ||
214 | } | ||
215 | |||
216 | static int hda_tegra_enable_clocks(struct hda_tegra *data) | ||
217 | { | ||
218 | int rc; | ||
219 | |||
220 | rc = clk_prepare_enable(data->hda_clk); | ||
221 | if (rc) | ||
222 | return rc; | ||
223 | rc = clk_prepare_enable(data->hda2codec_2x_clk); | ||
224 | if (rc) | ||
225 | goto disable_hda; | ||
226 | rc = clk_prepare_enable(data->hda2hdmi_clk); | ||
227 | if (rc) | ||
228 | goto disable_codec_2x; | ||
229 | |||
230 | return 0; | ||
231 | |||
232 | disable_codec_2x: | ||
233 | clk_disable_unprepare(data->hda2codec_2x_clk); | ||
234 | disable_hda: | ||
235 | clk_disable_unprepare(data->hda_clk); | ||
236 | return rc; | ||
237 | } | ||
238 | |||
239 | static void hda_tegra_disable_clocks(struct hda_tegra *data) | ||
240 | { | ||
241 | clk_disable_unprepare(data->hda2hdmi_clk); | ||
242 | clk_disable_unprepare(data->hda2codec_2x_clk); | ||
243 | clk_disable_unprepare(data->hda_clk); | ||
244 | } | ||
245 | |||
246 | #ifdef CONFIG_PM_SLEEP | ||
247 | /* | ||
248 | * power management | ||
249 | */ | ||
250 | static int hda_tegra_suspend(struct device *dev) | ||
251 | { | ||
252 | struct snd_card *card = dev_get_drvdata(dev); | ||
253 | struct azx *chip = card->private_data; | ||
254 | struct azx_pcm *p; | ||
255 | struct hda_tegra *hda = container_of(chip, struct hda_tegra, chip); | ||
256 | |||
257 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); | ||
258 | list_for_each_entry(p, &chip->pcm_list, list) | ||
259 | snd_pcm_suspend_all(p->pcm); | ||
260 | if (chip->initialized) | ||
261 | snd_hda_suspend(chip->bus); | ||
262 | |||
263 | azx_stop_chip(chip); | ||
264 | azx_enter_link_reset(chip); | ||
265 | hda_tegra_disable_clocks(hda); | ||
266 | |||
267 | return 0; | ||
268 | } | ||
269 | |||
270 | static int hda_tegra_resume(struct device *dev) | ||
271 | { | ||
272 | struct snd_card *card = dev_get_drvdata(dev); | ||
273 | struct azx *chip = card->private_data; | ||
274 | struct hda_tegra *hda = container_of(chip, struct hda_tegra, chip); | ||
275 | int status; | ||
276 | |||
277 | hda_tegra_enable_clocks(hda); | ||
278 | |||
279 | /* Read STATESTS before controller reset */ | ||
280 | status = azx_readw(chip, STATESTS); | ||
281 | |||
282 | hda_tegra_init(hda); | ||
283 | |||
284 | azx_init_chip(chip, 1); | ||
285 | |||
286 | snd_hda_resume(chip->bus); | ||
287 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | ||
288 | |||
289 | return 0; | ||
290 | } | ||
291 | #endif /* CONFIG_PM_SLEEP */ | ||
292 | |||
293 | static const struct dev_pm_ops hda_tegra_pm = { | ||
294 | SET_SYSTEM_SLEEP_PM_OPS(hda_tegra_suspend, hda_tegra_resume) | ||
295 | }; | ||
296 | |||
297 | /* | ||
298 | * reboot notifier for hang-up problem at power-down | ||
299 | */ | ||
300 | static int hda_tegra_halt(struct notifier_block *nb, unsigned long event, | ||
301 | void *buf) | ||
302 | { | ||
303 | struct azx *chip = container_of(nb, struct azx, reboot_notifier); | ||
304 | snd_hda_bus_reboot_notify(chip->bus); | ||
305 | azx_stop_chip(chip); | ||
306 | return NOTIFY_OK; | ||
307 | } | ||
308 | |||
309 | static void hda_tegra_notifier_register(struct azx *chip) | ||
310 | { | ||
311 | chip->reboot_notifier.notifier_call = hda_tegra_halt; | ||
312 | register_reboot_notifier(&chip->reboot_notifier); | ||
313 | } | ||
314 | |||
315 | static void hda_tegra_notifier_unregister(struct azx *chip) | ||
316 | { | ||
317 | if (chip->reboot_notifier.notifier_call) | ||
318 | unregister_reboot_notifier(&chip->reboot_notifier); | ||
319 | } | ||
320 | |||
321 | /* | ||
322 | * destructor | ||
323 | */ | ||
324 | static int hda_tegra_dev_free(struct snd_device *device) | ||
325 | { | ||
326 | int i; | ||
327 | struct azx *chip = device->device_data; | ||
328 | |||
329 | hda_tegra_notifier_unregister(chip); | ||
330 | |||
331 | if (chip->initialized) { | ||
332 | for (i = 0; i < chip->num_streams; i++) | ||
333 | azx_stream_stop(chip, &chip->azx_dev[i]); | ||
334 | azx_stop_chip(chip); | ||
335 | } | ||
336 | |||
337 | azx_free_stream_pages(chip); | ||
338 | |||
339 | return 0; | ||
340 | } | ||
341 | |||
342 | static int hda_tegra_init_chip(struct azx *chip, struct platform_device *pdev) | ||
343 | { | ||
344 | struct hda_tegra *hda = container_of(chip, struct hda_tegra, chip); | ||
345 | struct device *dev = hda->dev; | ||
346 | struct resource *res; | ||
347 | int err; | ||
348 | |||
349 | hda->hda_clk = devm_clk_get(dev, "hda"); | ||
350 | if (IS_ERR(hda->hda_clk)) | ||
351 | return PTR_ERR(hda->hda_clk); | ||
352 | hda->hda2codec_2x_clk = devm_clk_get(dev, "hda2codec_2x"); | ||
353 | if (IS_ERR(hda->hda2codec_2x_clk)) | ||
354 | return PTR_ERR(hda->hda2codec_2x_clk); | ||
355 | hda->hda2hdmi_clk = devm_clk_get(dev, "hda2hdmi"); | ||
356 | if (IS_ERR(hda->hda2hdmi_clk)) | ||
357 | return PTR_ERR(hda->hda2hdmi_clk); | ||
358 | |||
359 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
360 | hda->regs = devm_ioremap_resource(dev, res); | ||
361 | if (IS_ERR(chip->remap_addr)) | ||
362 | return PTR_ERR(chip->remap_addr); | ||
363 | |||
364 | chip->remap_addr = hda->regs + HDA_BAR0; | ||
365 | chip->addr = res->start + HDA_BAR0; | ||
366 | |||
367 | err = hda_tegra_enable_clocks(hda); | ||
368 | if (err) | ||
369 | return err; | ||
370 | |||
371 | hda_tegra_init(hda); | ||
372 | |||
373 | return 0; | ||
374 | } | ||
375 | |||
376 | /* | ||
377 | * The codecs were powered up in snd_hda_codec_new(). | ||
378 | * Now all initialization done, so turn them down if possible | ||
379 | */ | ||
380 | static void power_down_all_codecs(struct azx *chip) | ||
381 | { | ||
382 | struct hda_codec *codec; | ||
383 | list_for_each_entry(codec, &chip->bus->codec_list, list) | ||
384 | snd_hda_power_down(codec); | ||
385 | } | ||
386 | |||
387 | static int hda_tegra_first_init(struct azx *chip, struct platform_device *pdev) | ||
388 | { | ||
389 | struct snd_card *card = chip->card; | ||
390 | int err; | ||
391 | unsigned short gcap; | ||
392 | int irq_id = platform_get_irq(pdev, 0); | ||
393 | |||
394 | err = hda_tegra_init_chip(chip, pdev); | ||
395 | if (err) | ||
396 | return err; | ||
397 | |||
398 | err = devm_request_irq(chip->card->dev, irq_id, azx_interrupt, | ||
399 | IRQF_SHARED, KBUILD_MODNAME, chip); | ||
400 | if (err) { | ||
401 | dev_err(chip->card->dev, | ||
402 | "unable to request IRQ %d, disabling device\n", | ||
403 | irq_id); | ||
404 | return err; | ||
405 | } | ||
406 | chip->irq = irq_id; | ||
407 | |||
408 | synchronize_irq(chip->irq); | ||
409 | |||
410 | gcap = azx_readw(chip, GCAP); | ||
411 | dev_dbg(card->dev, "chipset global capabilities = 0x%x\n", gcap); | ||
412 | |||
413 | /* read number of streams from GCAP register instead of using | ||
414 | * hardcoded value | ||
415 | */ | ||
416 | chip->capture_streams = (gcap >> 8) & 0x0f; | ||
417 | chip->playback_streams = (gcap >> 12) & 0x0f; | ||
418 | if (!chip->playback_streams && !chip->capture_streams) { | ||
419 | /* gcap didn't give any info, switching to old method */ | ||
420 | chip->playback_streams = NUM_PLAYBACK_SD; | ||
421 | chip->capture_streams = NUM_CAPTURE_SD; | ||
422 | } | ||
423 | chip->capture_index_offset = 0; | ||
424 | chip->playback_index_offset = chip->capture_streams; | ||
425 | chip->num_streams = chip->playback_streams + chip->capture_streams; | ||
426 | chip->azx_dev = devm_kcalloc(card->dev, chip->num_streams, | ||
427 | sizeof(*chip->azx_dev), GFP_KERNEL); | ||
428 | if (!chip->azx_dev) | ||
429 | return -ENOMEM; | ||
430 | |||
431 | err = azx_alloc_stream_pages(chip); | ||
432 | if (err < 0) | ||
433 | return err; | ||
434 | |||
435 | /* initialize streams */ | ||
436 | azx_init_stream(chip); | ||
437 | |||
438 | /* initialize chip */ | ||
439 | azx_init_chip(chip, 1); | ||
440 | |||
441 | /* codec detection */ | ||
442 | if (!chip->codec_mask) { | ||
443 | dev_err(card->dev, "no codecs found!\n"); | ||
444 | return -ENODEV; | ||
445 | } | ||
446 | |||
447 | strcpy(card->driver, "tegra-hda"); | ||
448 | strcpy(card->shortname, "tegra-hda"); | ||
449 | snprintf(card->longname, sizeof(card->longname), | ||
450 | "%s at 0x%lx irq %i", | ||
451 | card->shortname, chip->addr, chip->irq); | ||
452 | |||
453 | return 0; | ||
454 | } | ||
455 | |||
456 | /* | ||
457 | * constructor | ||
458 | */ | ||
459 | static int hda_tegra_create(struct snd_card *card, | ||
460 | unsigned int driver_caps, | ||
461 | const struct hda_controller_ops *hda_ops, | ||
462 | struct hda_tegra *hda) | ||
463 | { | ||
464 | static struct snd_device_ops ops = { | ||
465 | .dev_free = hda_tegra_dev_free, | ||
466 | }; | ||
467 | struct azx *chip; | ||
468 | int err; | ||
469 | |||
470 | chip = &hda->chip; | ||
471 | |||
472 | spin_lock_init(&chip->reg_lock); | ||
473 | mutex_init(&chip->open_mutex); | ||
474 | chip->card = card; | ||
475 | chip->ops = hda_ops; | ||
476 | chip->irq = -1; | ||
477 | chip->driver_caps = driver_caps; | ||
478 | chip->driver_type = driver_caps & 0xff; | ||
479 | chip->dev_index = 0; | ||
480 | INIT_LIST_HEAD(&chip->pcm_list); | ||
481 | INIT_LIST_HEAD(&chip->list); | ||
482 | |||
483 | chip->position_fix[0] = POS_FIX_AUTO; | ||
484 | chip->position_fix[1] = POS_FIX_AUTO; | ||
485 | chip->codec_probe_mask = -1; | ||
486 | |||
487 | chip->single_cmd = false; | ||
488 | chip->snoop = true; | ||
489 | |||
490 | err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); | ||
491 | if (err < 0) { | ||
492 | dev_err(card->dev, "Error creating device\n"); | ||
493 | return err; | ||
494 | } | ||
495 | |||
496 | return 0; | ||
497 | } | ||
498 | |||
499 | static const struct of_device_id hda_tegra_match[] = { | ||
500 | { .compatible = "nvidia,tegra30-hda" }, | ||
501 | {}, | ||
502 | }; | ||
503 | MODULE_DEVICE_TABLE(of, hda_tegra_match); | ||
504 | |||
505 | static int hda_tegra_probe(struct platform_device *pdev) | ||
506 | { | ||
507 | struct snd_card *card; | ||
508 | struct azx *chip; | ||
509 | struct hda_tegra *hda; | ||
510 | int err; | ||
511 | const unsigned int driver_flags = AZX_DCAPS_RIRB_DELAY; | ||
512 | |||
513 | hda = devm_kzalloc(&pdev->dev, sizeof(*hda), GFP_KERNEL); | ||
514 | if (!hda) | ||
515 | return -ENOMEM; | ||
516 | hda->dev = &pdev->dev; | ||
517 | chip = &hda->chip; | ||
518 | |||
519 | err = snd_card_new(&pdev->dev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, | ||
520 | THIS_MODULE, 0, &card); | ||
521 | if (err < 0) { | ||
522 | dev_err(&pdev->dev, "Error creating card!\n"); | ||
523 | return err; | ||
524 | } | ||
525 | |||
526 | err = hda_tegra_create(card, driver_flags, &hda_tegra_ops, hda); | ||
527 | if (err < 0) | ||
528 | goto out_free; | ||
529 | card->private_data = chip; | ||
530 | |||
531 | dev_set_drvdata(&pdev->dev, card); | ||
532 | |||
533 | err = hda_tegra_first_init(chip, pdev); | ||
534 | if (err < 0) | ||
535 | goto out_free; | ||
536 | |||
537 | /* create codec instances */ | ||
538 | err = azx_codec_create(chip, NULL, 0, &power_save); | ||
539 | if (err < 0) | ||
540 | goto out_free; | ||
541 | |||
542 | err = azx_codec_configure(chip); | ||
543 | if (err < 0) | ||
544 | goto out_free; | ||
545 | |||
546 | /* create PCM streams */ | ||
547 | err = snd_hda_build_pcms(chip->bus); | ||
548 | if (err < 0) | ||
549 | goto out_free; | ||
550 | |||
551 | /* create mixer controls */ | ||
552 | err = azx_mixer_create(chip); | ||
553 | if (err < 0) | ||
554 | goto out_free; | ||
555 | |||
556 | err = snd_card_register(chip->card); | ||
557 | if (err < 0) | ||
558 | goto out_free; | ||
559 | |||
560 | chip->running = 1; | ||
561 | power_down_all_codecs(chip); | ||
562 | hda_tegra_notifier_register(chip); | ||
563 | |||
564 | return 0; | ||
565 | |||
566 | out_free: | ||
567 | snd_card_free(card); | ||
568 | return err; | ||
569 | } | ||
570 | |||
571 | static int hda_tegra_remove(struct platform_device *pdev) | ||
572 | { | ||
573 | return snd_card_free(dev_get_drvdata(&pdev->dev)); | ||
574 | } | ||
575 | |||
576 | static struct platform_driver tegra_platform_hda = { | ||
577 | .driver = { | ||
578 | .name = "tegra-hda", | ||
579 | .pm = &hda_tegra_pm, | ||
580 | .of_match_table = hda_tegra_match, | ||
581 | }, | ||
582 | .probe = hda_tegra_probe, | ||
583 | .remove = hda_tegra_remove, | ||
584 | }; | ||
585 | module_platform_driver(tegra_platform_hda); | ||
586 | |||
587 | MODULE_DESCRIPTION("Tegra HDA bus driver"); | ||
588 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 40ba06eb44af..06275f8807a8 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c | |||
@@ -332,6 +332,7 @@ static const struct hda_fixup ad1986a_fixups[] = { | |||
332 | 332 | ||
333 | static const struct snd_pci_quirk ad1986a_fixup_tbl[] = { | 333 | static const struct snd_pci_quirk ad1986a_fixup_tbl[] = { |
334 | SND_PCI_QUIRK(0x103c, 0x30af, "HP B2800", AD1986A_FIXUP_LAPTOP_IMIC), | 334 | SND_PCI_QUIRK(0x103c, 0x30af, "HP B2800", AD1986A_FIXUP_LAPTOP_IMIC), |
335 | SND_PCI_QUIRK(0x1043, 0x1447, "ASUS A8JN", AD1986A_FIXUP_EAPD), | ||
335 | SND_PCI_QUIRK_MASK(0x1043, 0xff00, 0x8100, "ASUS P5", AD1986A_FIXUP_3STACK), | 336 | SND_PCI_QUIRK_MASK(0x1043, 0xff00, 0x8100, "ASUS P5", AD1986A_FIXUP_3STACK), |
336 | SND_PCI_QUIRK_MASK(0x1043, 0xff00, 0x8200, "ASUS M2", AD1986A_FIXUP_3STACK), | 337 | SND_PCI_QUIRK_MASK(0x1043, 0xff00, 0x8200, "ASUS M2", AD1986A_FIXUP_3STACK), |
337 | SND_PCI_QUIRK(0x10de, 0xcb84, "ASUS A8N-VM", AD1986A_FIXUP_3STACK), | 338 | SND_PCI_QUIRK(0x10de, 0xcb84, "ASUS A8N-VM", AD1986A_FIXUP_3STACK), |
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 1edbb9c47c2d..3e4417b0ddbe 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c | |||
@@ -1127,10 +1127,6 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, | |||
1127 | AMP_OUT_UNMUTE); | 1127 | AMP_OUT_UNMUTE); |
1128 | 1128 | ||
1129 | eld = &per_pin->sink_eld; | 1129 | eld = &per_pin->sink_eld; |
1130 | if (!eld->monitor_present) { | ||
1131 | hdmi_set_channel_count(codec, per_pin->cvt_nid, channels); | ||
1132 | return; | ||
1133 | } | ||
1134 | 1130 | ||
1135 | if (!non_pcm && per_pin->chmap_set) | 1131 | if (!non_pcm && per_pin->chmap_set) |
1136 | ca = hdmi_manual_channel_allocation(channels, per_pin->chmap); | 1132 | ca = hdmi_manual_channel_allocation(channels, per_pin->chmap); |
@@ -1598,10 +1594,18 @@ static bool hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll) | |||
1598 | * Re-setup pin and infoframe. This is needed e.g. when | 1594 | * Re-setup pin and infoframe. This is needed e.g. when |
1599 | * - sink is first plugged-in (infoframe is not set up if !monitor_present) | 1595 | * - sink is first plugged-in (infoframe is not set up if !monitor_present) |
1600 | * - transcoder can change during stream playback on Haswell | 1596 | * - transcoder can change during stream playback on Haswell |
1597 | * and this can make HW reset converter selection on a pin. | ||
1601 | */ | 1598 | */ |
1602 | if (eld->eld_valid && !old_eld_valid && per_pin->setup) | 1599 | if (eld->eld_valid && !old_eld_valid && per_pin->setup) { |
1600 | if (is_haswell_plus(codec) || is_valleyview(codec)) { | ||
1601 | intel_verify_pin_cvt_connect(codec, per_pin); | ||
1602 | intel_not_share_assigned_cvt(codec, pin_nid, | ||
1603 | per_pin->mux_idx); | ||
1604 | } | ||
1605 | |||
1603 | hdmi_setup_audio_infoframe(codec, per_pin, | 1606 | hdmi_setup_audio_infoframe(codec, per_pin, |
1604 | per_pin->non_pcm); | 1607 | per_pin->non_pcm); |
1608 | } | ||
1605 | } | 1609 | } |
1606 | 1610 | ||
1607 | if (eld_changed) | 1611 | if (eld_changed) |
@@ -3324,6 +3328,7 @@ static const struct hda_codec_preset snd_hda_preset_hdmi[] = { | |||
3324 | { .id = 0x10de001a, .name = "GPU 1a HDMI/DP", .patch = patch_nvhdmi }, | 3328 | { .id = 0x10de001a, .name = "GPU 1a HDMI/DP", .patch = patch_nvhdmi }, |
3325 | { .id = 0x10de001b, .name = "GPU 1b HDMI/DP", .patch = patch_nvhdmi }, | 3329 | { .id = 0x10de001b, .name = "GPU 1b HDMI/DP", .patch = patch_nvhdmi }, |
3326 | { .id = 0x10de001c, .name = "GPU 1c HDMI/DP", .patch = patch_nvhdmi }, | 3330 | { .id = 0x10de001c, .name = "GPU 1c HDMI/DP", .patch = patch_nvhdmi }, |
3331 | { .id = 0x10de0028, .name = "Tegra12x HDMI", .patch = patch_nvhdmi }, | ||
3327 | { .id = 0x10de0040, .name = "GPU 40 HDMI/DP", .patch = patch_nvhdmi }, | 3332 | { .id = 0x10de0040, .name = "GPU 40 HDMI/DP", .patch = patch_nvhdmi }, |
3328 | { .id = 0x10de0041, .name = "GPU 41 HDMI/DP", .patch = patch_nvhdmi }, | 3333 | { .id = 0x10de0041, .name = "GPU 41 HDMI/DP", .patch = patch_nvhdmi }, |
3329 | { .id = 0x10de0042, .name = "GPU 42 HDMI/DP", .patch = patch_nvhdmi }, | 3334 | { .id = 0x10de0042, .name = "GPU 42 HDMI/DP", .patch = patch_nvhdmi }, |
@@ -3332,6 +3337,7 @@ static const struct hda_codec_preset snd_hda_preset_hdmi[] = { | |||
3332 | { .id = 0x10de0051, .name = "GPU 51 HDMI/DP", .patch = patch_nvhdmi }, | 3337 | { .id = 0x10de0051, .name = "GPU 51 HDMI/DP", .patch = patch_nvhdmi }, |
3333 | { .id = 0x10de0060, .name = "GPU 60 HDMI/DP", .patch = patch_nvhdmi }, | 3338 | { .id = 0x10de0060, .name = "GPU 60 HDMI/DP", .patch = patch_nvhdmi }, |
3334 | { .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch }, | 3339 | { .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch }, |
3340 | { .id = 0x10de0071, .name = "GPU 71 HDMI/DP", .patch = patch_nvhdmi }, | ||
3335 | { .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch }, | 3341 | { .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch }, |
3336 | { .id = 0x11069f80, .name = "VX900 HDMI/DP", .patch = patch_via_hdmi }, | 3342 | { .id = 0x11069f80, .name = "VX900 HDMI/DP", .patch = patch_via_hdmi }, |
3337 | { .id = 0x11069f81, .name = "VX900 HDMI/DP", .patch = patch_via_hdmi }, | 3343 | { .id = 0x11069f81, .name = "VX900 HDMI/DP", .patch = patch_via_hdmi }, |
@@ -3379,6 +3385,7 @@ MODULE_ALIAS("snd-hda-codec-id:10de0019"); | |||
3379 | MODULE_ALIAS("snd-hda-codec-id:10de001a"); | 3385 | MODULE_ALIAS("snd-hda-codec-id:10de001a"); |
3380 | MODULE_ALIAS("snd-hda-codec-id:10de001b"); | 3386 | MODULE_ALIAS("snd-hda-codec-id:10de001b"); |
3381 | MODULE_ALIAS("snd-hda-codec-id:10de001c"); | 3387 | MODULE_ALIAS("snd-hda-codec-id:10de001c"); |
3388 | MODULE_ALIAS("snd-hda-codec-id:10de0028"); | ||
3382 | MODULE_ALIAS("snd-hda-codec-id:10de0040"); | 3389 | MODULE_ALIAS("snd-hda-codec-id:10de0040"); |
3383 | MODULE_ALIAS("snd-hda-codec-id:10de0041"); | 3390 | MODULE_ALIAS("snd-hda-codec-id:10de0041"); |
3384 | MODULE_ALIAS("snd-hda-codec-id:10de0042"); | 3391 | MODULE_ALIAS("snd-hda-codec-id:10de0042"); |
@@ -3387,6 +3394,7 @@ MODULE_ALIAS("snd-hda-codec-id:10de0044"); | |||
3387 | MODULE_ALIAS("snd-hda-codec-id:10de0051"); | 3394 | MODULE_ALIAS("snd-hda-codec-id:10de0051"); |
3388 | MODULE_ALIAS("snd-hda-codec-id:10de0060"); | 3395 | MODULE_ALIAS("snd-hda-codec-id:10de0060"); |
3389 | MODULE_ALIAS("snd-hda-codec-id:10de0067"); | 3396 | MODULE_ALIAS("snd-hda-codec-id:10de0067"); |
3397 | MODULE_ALIAS("snd-hda-codec-id:10de0071"); | ||
3390 | MODULE_ALIAS("snd-hda-codec-id:10de8001"); | 3398 | MODULE_ALIAS("snd-hda-codec-id:10de8001"); |
3391 | MODULE_ALIAS("snd-hda-codec-id:11069f80"); | 3399 | MODULE_ALIAS("snd-hda-codec-id:11069f80"); |
3392 | MODULE_ALIAS("snd-hda-codec-id:11069f81"); | 3400 | MODULE_ALIAS("snd-hda-codec-id:11069f81"); |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 5f7c765391f1..af76995fa966 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -929,6 +929,7 @@ struct alc_codec_rename_pci_table { | |||
929 | }; | 929 | }; |
930 | 930 | ||
931 | static struct alc_codec_rename_table rename_tbl[] = { | 931 | static struct alc_codec_rename_table rename_tbl[] = { |
932 | { 0x10ec0221, 0xf00f, 0x1003, "ALC231" }, | ||
932 | { 0x10ec0269, 0xfff0, 0x3010, "ALC277" }, | 933 | { 0x10ec0269, 0xfff0, 0x3010, "ALC277" }, |
933 | { 0x10ec0269, 0xf0f0, 0x2010, "ALC259" }, | 934 | { 0x10ec0269, 0xf0f0, 0x2010, "ALC259" }, |
934 | { 0x10ec0269, 0xf0f0, 0x3010, "ALC258" }, | 935 | { 0x10ec0269, 0xf0f0, 0x3010, "ALC258" }, |
@@ -937,6 +938,7 @@ static struct alc_codec_rename_table rename_tbl[] = { | |||
937 | { 0x10ec0269, 0xffff, 0x6023, "ALC281X" }, | 938 | { 0x10ec0269, 0xffff, 0x6023, "ALC281X" }, |
938 | { 0x10ec0269, 0x00f0, 0x0020, "ALC269VC" }, | 939 | { 0x10ec0269, 0x00f0, 0x0020, "ALC269VC" }, |
939 | { 0x10ec0269, 0x00f0, 0x0030, "ALC269VD" }, | 940 | { 0x10ec0269, 0x00f0, 0x0030, "ALC269VD" }, |
941 | { 0x10ec0662, 0xffff, 0x4020, "ALC656" }, | ||
940 | { 0x10ec0887, 0x00f0, 0x0030, "ALC887-VD" }, | 942 | { 0x10ec0887, 0x00f0, 0x0030, "ALC887-VD" }, |
941 | { 0x10ec0888, 0x00f0, 0x0030, "ALC888-VD" }, | 943 | { 0x10ec0888, 0x00f0, 0x0030, "ALC888-VD" }, |
942 | { 0x10ec0888, 0xf0f0, 0x3020, "ALC886" }, | 944 | { 0x10ec0888, 0xf0f0, 0x3020, "ALC886" }, |
@@ -951,9 +953,24 @@ static struct alc_codec_rename_pci_table rename_pci_tbl[] = { | |||
951 | { 0x10ec0280, 0x1028, 0, "ALC3220" }, | 953 | { 0x10ec0280, 0x1028, 0, "ALC3220" }, |
952 | { 0x10ec0282, 0x1028, 0, "ALC3221" }, | 954 | { 0x10ec0282, 0x1028, 0, "ALC3221" }, |
953 | { 0x10ec0283, 0x1028, 0, "ALC3223" }, | 955 | { 0x10ec0283, 0x1028, 0, "ALC3223" }, |
956 | { 0x10ec0288, 0x1028, 0, "ALC3263" }, | ||
954 | { 0x10ec0292, 0x1028, 0, "ALC3226" }, | 957 | { 0x10ec0292, 0x1028, 0, "ALC3226" }, |
958 | { 0x10ec0293, 0x1028, 0, "ALC3235" }, | ||
955 | { 0x10ec0255, 0x1028, 0, "ALC3234" }, | 959 | { 0x10ec0255, 0x1028, 0, "ALC3234" }, |
956 | { 0x10ec0668, 0x1028, 0, "ALC3661" }, | 960 | { 0x10ec0668, 0x1028, 0, "ALC3661" }, |
961 | { 0x10ec0275, 0x1028, 0, "ALC3260" }, | ||
962 | { 0x10ec0899, 0x1028, 0, "ALC3861" }, | ||
963 | { 0x10ec0670, 0x1025, 0, "ALC669X" }, | ||
964 | { 0x10ec0676, 0x1025, 0, "ALC679X" }, | ||
965 | { 0x10ec0282, 0x1043, 0, "ALC3229" }, | ||
966 | { 0x10ec0233, 0x1043, 0, "ALC3236" }, | ||
967 | { 0x10ec0280, 0x103c, 0, "ALC3228" }, | ||
968 | { 0x10ec0282, 0x103c, 0, "ALC3227" }, | ||
969 | { 0x10ec0286, 0x103c, 0, "ALC3242" }, | ||
970 | { 0x10ec0290, 0x103c, 0, "ALC3241" }, | ||
971 | { 0x10ec0668, 0x103c, 0, "ALC3662" }, | ||
972 | { 0x10ec0283, 0x17aa, 0, "ALC3239" }, | ||
973 | { 0x10ec0292, 0x17aa, 0, "ALC3232" }, | ||
957 | { } /* terminator */ | 974 | { } /* terminator */ |
958 | }; | 975 | }; |
959 | 976 | ||
@@ -1410,6 +1427,7 @@ static const struct snd_pci_quirk alc880_fixup_tbl[] = { | |||
1410 | SND_PCI_QUIRK(0x1043, 0x10c3, "ASUS W5A", ALC880_FIXUP_ASUS_W5A), | 1427 | SND_PCI_QUIRK(0x1043, 0x10c3, "ASUS W5A", ALC880_FIXUP_ASUS_W5A), |
1411 | SND_PCI_QUIRK(0x1043, 0x1964, "ASUS Z71V", ALC880_FIXUP_Z71V), | 1428 | SND_PCI_QUIRK(0x1043, 0x1964, "ASUS Z71V", ALC880_FIXUP_Z71V), |
1412 | SND_PCI_QUIRK_VENDOR(0x1043, "ASUS", ALC880_FIXUP_GPIO1), | 1429 | SND_PCI_QUIRK_VENDOR(0x1043, "ASUS", ALC880_FIXUP_GPIO1), |
1430 | SND_PCI_QUIRK(0x147b, 0x1045, "ABit AA8XE", ALC880_FIXUP_6ST_AUTOMUTE), | ||
1413 | SND_PCI_QUIRK(0x1558, 0x5401, "Clevo GPIO2", ALC880_FIXUP_GPIO2), | 1431 | SND_PCI_QUIRK(0x1558, 0x5401, "Clevo GPIO2", ALC880_FIXUP_GPIO2), |
1414 | SND_PCI_QUIRK_VENDOR(0x1558, "Clevo", ALC880_FIXUP_EAPD_COEF), | 1432 | SND_PCI_QUIRK_VENDOR(0x1558, "Clevo", ALC880_FIXUP_EAPD_COEF), |
1415 | SND_PCI_QUIRK(0x1584, 0x9050, "Uniwill", ALC880_FIXUP_UNIWILL_DIG), | 1433 | SND_PCI_QUIRK(0x1584, 0x9050, "Uniwill", ALC880_FIXUP_UNIWILL_DIG), |
@@ -1647,12 +1665,10 @@ static const struct hda_fixup alc260_fixups[] = { | |||
1647 | [ALC260_FIXUP_COEF] = { | 1665 | [ALC260_FIXUP_COEF] = { |
1648 | .type = HDA_FIXUP_VERBS, | 1666 | .type = HDA_FIXUP_VERBS, |
1649 | .v.verbs = (const struct hda_verb[]) { | 1667 | .v.verbs = (const struct hda_verb[]) { |
1650 | { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 }, | 1668 | { 0x1a, AC_VERB_SET_COEF_INDEX, 0x07 }, |
1651 | { 0x20, AC_VERB_SET_PROC_COEF, 0x3040 }, | 1669 | { 0x1a, AC_VERB_SET_PROC_COEF, 0x3040 }, |
1652 | { } | 1670 | { } |
1653 | }, | 1671 | }, |
1654 | .chained = true, | ||
1655 | .chain_id = ALC260_FIXUP_HP_PIN_0F, | ||
1656 | }, | 1672 | }, |
1657 | [ALC260_FIXUP_GPIO1] = { | 1673 | [ALC260_FIXUP_GPIO1] = { |
1658 | .type = HDA_FIXUP_VERBS, | 1674 | .type = HDA_FIXUP_VERBS, |
@@ -1667,8 +1683,8 @@ static const struct hda_fixup alc260_fixups[] = { | |||
1667 | [ALC260_FIXUP_REPLACER] = { | 1683 | [ALC260_FIXUP_REPLACER] = { |
1668 | .type = HDA_FIXUP_VERBS, | 1684 | .type = HDA_FIXUP_VERBS, |
1669 | .v.verbs = (const struct hda_verb[]) { | 1685 | .v.verbs = (const struct hda_verb[]) { |
1670 | { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 }, | 1686 | { 0x1a, AC_VERB_SET_COEF_INDEX, 0x07 }, |
1671 | { 0x20, AC_VERB_SET_PROC_COEF, 0x3050 }, | 1687 | { 0x1a, AC_VERB_SET_PROC_COEF, 0x3050 }, |
1672 | { } | 1688 | { } |
1673 | }, | 1689 | }, |
1674 | .chained = true, | 1690 | .chained = true, |
@@ -3522,6 +3538,7 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec) | |||
3522 | /* Direct Drive HP Amp control */ | 3538 | /* Direct Drive HP Amp control */ |
3523 | alc_write_coefex_idx(codec, 0x57, 0x03, 0x8aa6); | 3539 | alc_write_coefex_idx(codec, 0x57, 0x03, 0x8aa6); |
3524 | break; | 3540 | break; |
3541 | case 0x10ec0233: | ||
3525 | case 0x10ec0283: | 3542 | case 0x10ec0283: |
3526 | alc_write_coef_idx(codec, 0x1b, 0x0c0b); | 3543 | alc_write_coef_idx(codec, 0x1b, 0x0c0b); |
3527 | alc_write_coef_idx(codec, 0x45, 0xc429); | 3544 | alc_write_coef_idx(codec, 0x45, 0xc429); |
@@ -3538,6 +3555,25 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec) | |||
3538 | alc_write_coef_idx(codec, 0x18, 0x7308); | 3555 | alc_write_coef_idx(codec, 0x18, 0x7308); |
3539 | alc_write_coef_idx(codec, 0x6b, 0xc429); | 3556 | alc_write_coef_idx(codec, 0x6b, 0xc429); |
3540 | break; | 3557 | break; |
3558 | case 0x10ec0293: | ||
3559 | /* SET Line1 JD to 0 */ | ||
3560 | val = alc_read_coef_idx(codec, 0x10); | ||
3561 | alc_write_coef_idx(codec, 0x10, (val & ~(7<<8)) | 6<<8); | ||
3562 | /* SET charge pump by verb */ | ||
3563 | val = alc_read_coefex_idx(codec, 0x57, 0x05); | ||
3564 | alc_write_coefex_idx(codec, 0x57, 0x05, (val & ~(1<<15|1<<13)) | 0x0); | ||
3565 | /* SET EN_OSW to 1 */ | ||
3566 | val = alc_read_coefex_idx(codec, 0x57, 0x03); | ||
3567 | alc_write_coefex_idx(codec, 0x57, 0x03, (val & ~(1<<10)) | (1<<10) ); | ||
3568 | /* Combo JD gating with LINE1-VREFO */ | ||
3569 | val = alc_read_coef_idx(codec, 0x1a); | ||
3570 | alc_write_coef_idx(codec, 0x1a, (val & ~(1<<3)) | (1<<3)); | ||
3571 | /* Set to TRS type */ | ||
3572 | alc_write_coef_idx(codec, 0x45, 0xc429); | ||
3573 | /* Combo Jack auto detect */ | ||
3574 | val = alc_read_coef_idx(codec, 0x4a); | ||
3575 | alc_write_coef_idx(codec, 0x4a, (val & 0xfff0) | 0x000e); | ||
3576 | break; | ||
3541 | case 0x10ec0668: | 3577 | case 0x10ec0668: |
3542 | alc_write_coef_idx(codec, 0x15, 0x0d40); | 3578 | alc_write_coef_idx(codec, 0x15, 0x0d40); |
3543 | alc_write_coef_idx(codec, 0xb7, 0x802b); | 3579 | alc_write_coef_idx(codec, 0xb7, 0x802b); |
@@ -3561,6 +3597,7 @@ static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin, | |||
3561 | alc_write_coef_idx(codec, 0x06, 0x6100); | 3597 | alc_write_coef_idx(codec, 0x06, 0x6100); |
3562 | snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50); | 3598 | snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50); |
3563 | break; | 3599 | break; |
3600 | case 0x10ec0233: | ||
3564 | case 0x10ec0283: | 3601 | case 0x10ec0283: |
3565 | alc_write_coef_idx(codec, 0x45, 0xc429); | 3602 | alc_write_coef_idx(codec, 0x45, 0xc429); |
3566 | snd_hda_set_pin_ctl_cache(codec, hp_pin, 0); | 3603 | snd_hda_set_pin_ctl_cache(codec, hp_pin, 0); |
@@ -3576,6 +3613,21 @@ static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin, | |||
3576 | alc_write_coef_idx(codec, 0x19, 0xa208); | 3613 | alc_write_coef_idx(codec, 0x19, 0xa208); |
3577 | alc_write_coef_idx(codec, 0x2e, 0xacf0); | 3614 | alc_write_coef_idx(codec, 0x2e, 0xacf0); |
3578 | break; | 3615 | break; |
3616 | case 0x10ec0293: | ||
3617 | /* Set to TRS mode */ | ||
3618 | alc_write_coef_idx(codec, 0x45, 0xc429); | ||
3619 | snd_hda_set_pin_ctl_cache(codec, hp_pin, 0); | ||
3620 | /* SET charge pump by verb */ | ||
3621 | val = alc_read_coefex_idx(codec, 0x57, 0x05); | ||
3622 | alc_write_coefex_idx(codec, 0x57, 0x05, (val & ~(1<<15|1<<13)) | (1<<15|1<<13)); | ||
3623 | /* SET EN_OSW to 0 */ | ||
3624 | val = alc_read_coefex_idx(codec, 0x57, 0x03); | ||
3625 | alc_write_coefex_idx(codec, 0x57, 0x03, (val & ~(1<<10)) | 0x0); | ||
3626 | /* Combo JD gating without LINE1-VREFO */ | ||
3627 | val = alc_read_coef_idx(codec, 0x1a); | ||
3628 | alc_write_coef_idx(codec, 0x1a, (val & ~(1<<3)) | 0x0); | ||
3629 | snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50); | ||
3630 | break; | ||
3579 | case 0x10ec0668: | 3631 | case 0x10ec0668: |
3580 | alc_write_coef_idx(codec, 0x11, 0x0001); | 3632 | alc_write_coef_idx(codec, 0x11, 0x0001); |
3581 | snd_hda_set_pin_ctl_cache(codec, hp_pin, 0); | 3633 | snd_hda_set_pin_ctl_cache(codec, hp_pin, 0); |
@@ -3591,6 +3643,8 @@ static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin, | |||
3591 | 3643 | ||
3592 | static void alc_headset_mode_default(struct hda_codec *codec) | 3644 | static void alc_headset_mode_default(struct hda_codec *codec) |
3593 | { | 3645 | { |
3646 | int val; | ||
3647 | |||
3594 | switch (codec->vendor_id) { | 3648 | switch (codec->vendor_id) { |
3595 | case 0x10ec0255: | 3649 | case 0x10ec0255: |
3596 | alc_write_coef_idx(codec, 0x45, 0xc089); | 3650 | alc_write_coef_idx(codec, 0x45, 0xc089); |
@@ -3598,6 +3652,7 @@ static void alc_headset_mode_default(struct hda_codec *codec) | |||
3598 | alc_write_coefex_idx(codec, 0x57, 0x03, 0x8ea6); | 3652 | alc_write_coefex_idx(codec, 0x57, 0x03, 0x8ea6); |
3599 | alc_write_coef_idx(codec, 0x49, 0x0049); | 3653 | alc_write_coef_idx(codec, 0x49, 0x0049); |
3600 | break; | 3654 | break; |
3655 | case 0x10ec0233: | ||
3601 | case 0x10ec0283: | 3656 | case 0x10ec0283: |
3602 | alc_write_coef_idx(codec, 0x06, 0x2100); | 3657 | alc_write_coef_idx(codec, 0x06, 0x2100); |
3603 | alc_write_coef_idx(codec, 0x32, 0x4ea3); | 3658 | alc_write_coef_idx(codec, 0x32, 0x4ea3); |
@@ -3608,6 +3663,16 @@ static void alc_headset_mode_default(struct hda_codec *codec) | |||
3608 | alc_write_coef_idx(codec, 0x6b, 0xc429); | 3663 | alc_write_coef_idx(codec, 0x6b, 0xc429); |
3609 | alc_write_coef_idx(codec, 0x18, 0x7308); | 3664 | alc_write_coef_idx(codec, 0x18, 0x7308); |
3610 | break; | 3665 | break; |
3666 | case 0x10ec0293: | ||
3667 | /* Combo Jack auto detect */ | ||
3668 | val = alc_read_coef_idx(codec, 0x4a); | ||
3669 | alc_write_coef_idx(codec, 0x4a, (val & 0xfff0) | 0x000e); | ||
3670 | /* Set to TRS type */ | ||
3671 | alc_write_coef_idx(codec, 0x45, 0xC429); | ||
3672 | /* Combo JD gating without LINE1-VREFO */ | ||
3673 | val = alc_read_coef_idx(codec, 0x1a); | ||
3674 | alc_write_coef_idx(codec, 0x1a, (val & ~(1<<3)) | 0x0); | ||
3675 | break; | ||
3611 | case 0x10ec0668: | 3676 | case 0x10ec0668: |
3612 | alc_write_coef_idx(codec, 0x11, 0x0041); | 3677 | alc_write_coef_idx(codec, 0x11, 0x0041); |
3613 | alc_write_coef_idx(codec, 0x15, 0x0d40); | 3678 | alc_write_coef_idx(codec, 0x15, 0x0d40); |
@@ -3620,6 +3685,8 @@ static void alc_headset_mode_default(struct hda_codec *codec) | |||
3620 | /* Iphone type */ | 3685 | /* Iphone type */ |
3621 | static void alc_headset_mode_ctia(struct hda_codec *codec) | 3686 | static void alc_headset_mode_ctia(struct hda_codec *codec) |
3622 | { | 3687 | { |
3688 | int val; | ||
3689 | |||
3623 | switch (codec->vendor_id) { | 3690 | switch (codec->vendor_id) { |
3624 | case 0x10ec0255: | 3691 | case 0x10ec0255: |
3625 | /* Set to CTIA type */ | 3692 | /* Set to CTIA type */ |
@@ -3627,6 +3694,7 @@ static void alc_headset_mode_ctia(struct hda_codec *codec) | |||
3627 | alc_write_coef_idx(codec, 0x1b, 0x0c2b); | 3694 | alc_write_coef_idx(codec, 0x1b, 0x0c2b); |
3628 | alc_write_coefex_idx(codec, 0x57, 0x03, 0x8ea6); | 3695 | alc_write_coefex_idx(codec, 0x57, 0x03, 0x8ea6); |
3629 | break; | 3696 | break; |
3697 | case 0x10ec0233: | ||
3630 | case 0x10ec0283: | 3698 | case 0x10ec0283: |
3631 | alc_write_coef_idx(codec, 0x45, 0xd429); | 3699 | alc_write_coef_idx(codec, 0x45, 0xd429); |
3632 | alc_write_coef_idx(codec, 0x1b, 0x0c2b); | 3700 | alc_write_coef_idx(codec, 0x1b, 0x0c2b); |
@@ -3637,6 +3705,13 @@ static void alc_headset_mode_ctia(struct hda_codec *codec) | |||
3637 | alc_write_coef_idx(codec, 0x76, 0x0008); | 3705 | alc_write_coef_idx(codec, 0x76, 0x0008); |
3638 | alc_write_coef_idx(codec, 0x18, 0x7388); | 3706 | alc_write_coef_idx(codec, 0x18, 0x7388); |
3639 | break; | 3707 | break; |
3708 | case 0x10ec0293: | ||
3709 | /* Set to ctia type */ | ||
3710 | alc_write_coef_idx(codec, 0x45, 0xd429); | ||
3711 | /* SET Line1 JD to 1 */ | ||
3712 | val = alc_read_coef_idx(codec, 0x10); | ||
3713 | alc_write_coef_idx(codec, 0x10, (val & ~(7<<8)) | 7<<8); | ||
3714 | break; | ||
3640 | case 0x10ec0668: | 3715 | case 0x10ec0668: |
3641 | alc_write_coef_idx(codec, 0x11, 0x0001); | 3716 | alc_write_coef_idx(codec, 0x11, 0x0001); |
3642 | alc_write_coef_idx(codec, 0x15, 0x0d60); | 3717 | alc_write_coef_idx(codec, 0x15, 0x0d60); |
@@ -3649,6 +3724,8 @@ static void alc_headset_mode_ctia(struct hda_codec *codec) | |||
3649 | /* Nokia type */ | 3724 | /* Nokia type */ |
3650 | static void alc_headset_mode_omtp(struct hda_codec *codec) | 3725 | static void alc_headset_mode_omtp(struct hda_codec *codec) |
3651 | { | 3726 | { |
3727 | int val; | ||
3728 | |||
3652 | switch (codec->vendor_id) { | 3729 | switch (codec->vendor_id) { |
3653 | case 0x10ec0255: | 3730 | case 0x10ec0255: |
3654 | /* Set to OMTP Type */ | 3731 | /* Set to OMTP Type */ |
@@ -3656,6 +3733,7 @@ static void alc_headset_mode_omtp(struct hda_codec *codec) | |||
3656 | alc_write_coef_idx(codec, 0x1b, 0x0c2b); | 3733 | alc_write_coef_idx(codec, 0x1b, 0x0c2b); |
3657 | alc_write_coefex_idx(codec, 0x57, 0x03, 0x8ea6); | 3734 | alc_write_coefex_idx(codec, 0x57, 0x03, 0x8ea6); |
3658 | break; | 3735 | break; |
3736 | case 0x10ec0233: | ||
3659 | case 0x10ec0283: | 3737 | case 0x10ec0283: |
3660 | alc_write_coef_idx(codec, 0x45, 0xe429); | 3738 | alc_write_coef_idx(codec, 0x45, 0xe429); |
3661 | alc_write_coef_idx(codec, 0x1b, 0x0c2b); | 3739 | alc_write_coef_idx(codec, 0x1b, 0x0c2b); |
@@ -3666,6 +3744,13 @@ static void alc_headset_mode_omtp(struct hda_codec *codec) | |||
3666 | alc_write_coef_idx(codec, 0x76, 0x0008); | 3744 | alc_write_coef_idx(codec, 0x76, 0x0008); |
3667 | alc_write_coef_idx(codec, 0x18, 0x7388); | 3745 | alc_write_coef_idx(codec, 0x18, 0x7388); |
3668 | break; | 3746 | break; |
3747 | case 0x10ec0293: | ||
3748 | /* Set to omtp type */ | ||
3749 | alc_write_coef_idx(codec, 0x45, 0xe429); | ||
3750 | /* SET Line1 JD to 1 */ | ||
3751 | val = alc_read_coef_idx(codec, 0x10); | ||
3752 | alc_write_coef_idx(codec, 0x10, (val & ~(7<<8)) | 7<<8); | ||
3753 | break; | ||
3669 | case 0x10ec0668: | 3754 | case 0x10ec0668: |
3670 | alc_write_coef_idx(codec, 0x11, 0x0001); | 3755 | alc_write_coef_idx(codec, 0x11, 0x0001); |
3671 | alc_write_coef_idx(codec, 0x15, 0x0d50); | 3756 | alc_write_coef_idx(codec, 0x15, 0x0d50); |
@@ -3691,6 +3776,7 @@ static void alc_determine_headset_type(struct hda_codec *codec) | |||
3691 | val = alc_read_coef_idx(codec, 0x46); | 3776 | val = alc_read_coef_idx(codec, 0x46); |
3692 | is_ctia = (val & 0x0070) == 0x0070; | 3777 | is_ctia = (val & 0x0070) == 0x0070; |
3693 | break; | 3778 | break; |
3779 | case 0x10ec0233: | ||
3694 | case 0x10ec0283: | 3780 | case 0x10ec0283: |
3695 | alc_write_coef_idx(codec, 0x45, 0xd029); | 3781 | alc_write_coef_idx(codec, 0x45, 0xd029); |
3696 | msleep(300); | 3782 | msleep(300); |
@@ -3703,6 +3789,16 @@ static void alc_determine_headset_type(struct hda_codec *codec) | |||
3703 | val = alc_read_coef_idx(codec, 0x6c); | 3789 | val = alc_read_coef_idx(codec, 0x6c); |
3704 | is_ctia = (val & 0x001c) == 0x001c; | 3790 | is_ctia = (val & 0x001c) == 0x001c; |
3705 | break; | 3791 | break; |
3792 | case 0x10ec0293: | ||
3793 | /* Combo Jack auto detect */ | ||
3794 | val = alc_read_coef_idx(codec, 0x4a); | ||
3795 | alc_write_coef_idx(codec, 0x4a, (val & 0xfff0) | 0x0008); | ||
3796 | /* Set to ctia type */ | ||
3797 | alc_write_coef_idx(codec, 0x45, 0xD429); | ||
3798 | msleep(300); | ||
3799 | val = alc_read_coef_idx(codec, 0x46); | ||
3800 | is_ctia = (val & 0x0070) == 0x0070; | ||
3801 | break; | ||
3706 | case 0x10ec0668: | 3802 | case 0x10ec0668: |
3707 | alc_write_coef_idx(codec, 0x11, 0x0001); | 3803 | alc_write_coef_idx(codec, 0x11, 0x0001); |
3708 | alc_write_coef_idx(codec, 0xb7, 0x802b); | 3804 | alc_write_coef_idx(codec, 0xb7, 0x802b); |
@@ -3894,6 +3990,39 @@ static void alc_fixup_no_shutup(struct hda_codec *codec, | |||
3894 | } | 3990 | } |
3895 | } | 3991 | } |
3896 | 3992 | ||
3993 | static void alc_fixup_disable_aamix(struct hda_codec *codec, | ||
3994 | const struct hda_fixup *fix, int action) | ||
3995 | { | ||
3996 | if (action == HDA_FIXUP_ACT_PRE_PROBE) { | ||
3997 | struct alc_spec *spec = codec->spec; | ||
3998 | /* Disable AA-loopback as it causes white noise */ | ||
3999 | spec->gen.mixer_nid = 0; | ||
4000 | } | ||
4001 | } | ||
4002 | |||
4003 | static unsigned int alc_power_filter_xps13(struct hda_codec *codec, | ||
4004 | hda_nid_t nid, | ||
4005 | unsigned int power_state) | ||
4006 | { | ||
4007 | struct alc_spec *spec = codec->spec; | ||
4008 | |||
4009 | /* Avoid pop noises when headphones are plugged in */ | ||
4010 | if (spec->gen.hp_jack_present) | ||
4011 | if (nid == codec->afg || nid == 0x02) | ||
4012 | return AC_PWRST_D0; | ||
4013 | return power_state; | ||
4014 | } | ||
4015 | |||
4016 | static void alc_fixup_dell_xps13(struct hda_codec *codec, | ||
4017 | const struct hda_fixup *fix, int action) | ||
4018 | { | ||
4019 | if (action == HDA_FIXUP_ACT_PROBE) { | ||
4020 | struct alc_spec *spec = codec->spec; | ||
4021 | spec->shutup = alc_no_shutup; | ||
4022 | codec->power_filter = alc_power_filter_xps13; | ||
4023 | } | ||
4024 | } | ||
4025 | |||
3897 | static void alc_fixup_headset_mode_alc668(struct hda_codec *codec, | 4026 | static void alc_fixup_headset_mode_alc668(struct hda_codec *codec, |
3898 | const struct hda_fixup *fix, int action) | 4027 | const struct hda_fixup *fix, int action) |
3899 | { | 4028 | { |
@@ -4110,12 +4239,14 @@ enum { | |||
4110 | ALC269_FIXUP_ASUS_G73JW, | 4239 | ALC269_FIXUP_ASUS_G73JW, |
4111 | ALC269_FIXUP_LENOVO_EAPD, | 4240 | ALC269_FIXUP_LENOVO_EAPD, |
4112 | ALC275_FIXUP_SONY_HWEQ, | 4241 | ALC275_FIXUP_SONY_HWEQ, |
4242 | ALC275_FIXUP_SONY_DISABLE_AAMIX, | ||
4113 | ALC271_FIXUP_DMIC, | 4243 | ALC271_FIXUP_DMIC, |
4114 | ALC269_FIXUP_PCM_44K, | 4244 | ALC269_FIXUP_PCM_44K, |
4115 | ALC269_FIXUP_STEREO_DMIC, | 4245 | ALC269_FIXUP_STEREO_DMIC, |
4116 | ALC269_FIXUP_HEADSET_MIC, | 4246 | ALC269_FIXUP_HEADSET_MIC, |
4117 | ALC269_FIXUP_QUANTA_MUTE, | 4247 | ALC269_FIXUP_QUANTA_MUTE, |
4118 | ALC269_FIXUP_LIFEBOOK, | 4248 | ALC269_FIXUP_LIFEBOOK, |
4249 | ALC269_FIXUP_LIFEBOOK_EXTMIC, | ||
4119 | ALC269_FIXUP_AMIC, | 4250 | ALC269_FIXUP_AMIC, |
4120 | ALC269_FIXUP_DMIC, | 4251 | ALC269_FIXUP_DMIC, |
4121 | ALC269VB_FIXUP_AMIC, | 4252 | ALC269VB_FIXUP_AMIC, |
@@ -4159,6 +4290,8 @@ enum { | |||
4159 | ALC255_FIXUP_DELL2_MIC_NO_PRESENCE, | 4290 | ALC255_FIXUP_DELL2_MIC_NO_PRESENCE, |
4160 | ALC255_FIXUP_HEADSET_MODE, | 4291 | ALC255_FIXUP_HEADSET_MODE, |
4161 | ALC255_FIXUP_HEADSET_MODE_NO_HP_MIC, | 4292 | ALC255_FIXUP_HEADSET_MODE_NO_HP_MIC, |
4293 | ALC293_FIXUP_DELL1_MIC_NO_PRESENCE, | ||
4294 | ALC292_FIXUP_TPT440_DOCK, | ||
4162 | }; | 4295 | }; |
4163 | 4296 | ||
4164 | static const struct hda_fixup alc269_fixups[] = { | 4297 | static const struct hda_fixup alc269_fixups[] = { |
@@ -4213,6 +4346,12 @@ static const struct hda_fixup alc269_fixups[] = { | |||
4213 | .chained = true, | 4346 | .chained = true, |
4214 | .chain_id = ALC275_FIXUP_SONY_VAIO_GPIO2 | 4347 | .chain_id = ALC275_FIXUP_SONY_VAIO_GPIO2 |
4215 | }, | 4348 | }, |
4349 | [ALC275_FIXUP_SONY_DISABLE_AAMIX] = { | ||
4350 | .type = HDA_FIXUP_FUNC, | ||
4351 | .v.func = alc_fixup_disable_aamix, | ||
4352 | .chained = true, | ||
4353 | .chain_id = ALC269_FIXUP_SONY_VAIO | ||
4354 | }, | ||
4216 | [ALC271_FIXUP_DMIC] = { | 4355 | [ALC271_FIXUP_DMIC] = { |
4217 | .type = HDA_FIXUP_FUNC, | 4356 | .type = HDA_FIXUP_FUNC, |
4218 | .v.func = alc271_fixup_dmic, | 4357 | .v.func = alc271_fixup_dmic, |
@@ -4245,6 +4384,13 @@ static const struct hda_fixup alc269_fixups[] = { | |||
4245 | .chained = true, | 4384 | .chained = true, |
4246 | .chain_id = ALC269_FIXUP_QUANTA_MUTE | 4385 | .chain_id = ALC269_FIXUP_QUANTA_MUTE |
4247 | }, | 4386 | }, |
4387 | [ALC269_FIXUP_LIFEBOOK_EXTMIC] = { | ||
4388 | .type = HDA_FIXUP_PINS, | ||
4389 | .v.pins = (const struct hda_pintbl[]) { | ||
4390 | { 0x19, 0x01a1903c }, /* headset mic, with jack detect */ | ||
4391 | { } | ||
4392 | }, | ||
4393 | }, | ||
4248 | [ALC269_FIXUP_AMIC] = { | 4394 | [ALC269_FIXUP_AMIC] = { |
4249 | .type = HDA_FIXUP_PINS, | 4395 | .type = HDA_FIXUP_PINS, |
4250 | .v.pins = (const struct hda_pintbl[]) { | 4396 | .v.pins = (const struct hda_pintbl[]) { |
@@ -4552,6 +4698,26 @@ static const struct hda_fixup alc269_fixups[] = { | |||
4552 | .type = HDA_FIXUP_FUNC, | 4698 | .type = HDA_FIXUP_FUNC, |
4553 | .v.func = alc_fixup_headset_mode_alc255_no_hp_mic, | 4699 | .v.func = alc_fixup_headset_mode_alc255_no_hp_mic, |
4554 | }, | 4700 | }, |
4701 | [ALC293_FIXUP_DELL1_MIC_NO_PRESENCE] = { | ||
4702 | .type = HDA_FIXUP_PINS, | ||
4703 | .v.pins = (const struct hda_pintbl[]) { | ||
4704 | { 0x18, 0x01a1913d }, /* use as headphone mic, without its own jack detect */ | ||
4705 | { 0x1a, 0x01a1913c }, /* use as headset mic, without its own jack detect */ | ||
4706 | { } | ||
4707 | }, | ||
4708 | .chained = true, | ||
4709 | .chain_id = ALC269_FIXUP_HEADSET_MODE | ||
4710 | }, | ||
4711 | [ALC292_FIXUP_TPT440_DOCK] = { | ||
4712 | .type = HDA_FIXUP_PINS, | ||
4713 | .v.pins = (const struct hda_pintbl[]) { | ||
4714 | { 0x16, 0x21211010 }, /* dock headphone */ | ||
4715 | { 0x19, 0x21a11010 }, /* dock mic */ | ||
4716 | { } | ||
4717 | }, | ||
4718 | .chained = true, | ||
4719 | .chain_id = ALC269_FIXUP_LIMIT_INT_MIC_BOOST | ||
4720 | }, | ||
4555 | }; | 4721 | }; |
4556 | 4722 | ||
4557 | static const struct snd_pci_quirk alc269_fixup_tbl[] = { | 4723 | static const struct snd_pci_quirk alc269_fixup_tbl[] = { |
@@ -4595,51 +4761,45 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
4595 | SND_PCI_QUIRK(0x1028, 0x0606, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | 4761 | SND_PCI_QUIRK(0x1028, 0x0606, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), |
4596 | SND_PCI_QUIRK(0x1028, 0x0608, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | 4762 | SND_PCI_QUIRK(0x1028, 0x0608, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), |
4597 | SND_PCI_QUIRK(0x1028, 0x0609, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | 4763 | SND_PCI_QUIRK(0x1028, 0x0609, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), |
4598 | SND_PCI_QUIRK(0x1028, 0x060f, "Dell", ALC269_FIXUP_DELL3_MIC_NO_PRESENCE), | ||
4599 | SND_PCI_QUIRK(0x1028, 0x0610, "Dell", ALC269_FIXUP_DELL3_MIC_NO_PRESENCE), | ||
4600 | SND_PCI_QUIRK(0x1028, 0x0613, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | 4764 | SND_PCI_QUIRK(0x1028, 0x0613, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), |
4601 | SND_PCI_QUIRK(0x1028, 0x0614, "Dell Inspiron 3135", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | 4765 | SND_PCI_QUIRK(0x1028, 0x0614, "Dell Inspiron 3135", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), |
4602 | SND_PCI_QUIRK(0x1028, 0x0615, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK), | 4766 | SND_PCI_QUIRK(0x1028, 0x0615, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK), |
4603 | SND_PCI_QUIRK(0x1028, 0x0616, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK), | 4767 | SND_PCI_QUIRK(0x1028, 0x0616, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK), |
4604 | SND_PCI_QUIRK(0x1028, 0x061f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
4605 | SND_PCI_QUIRK(0x1028, 0x0629, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
4606 | SND_PCI_QUIRK(0x1028, 0x062c, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
4607 | SND_PCI_QUIRK(0x1028, 0x062e, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
4608 | SND_PCI_QUIRK(0x1028, 0x0632, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
4609 | SND_PCI_QUIRK(0x1028, 0x0638, "Dell Inspiron 5439", ALC290_FIXUP_MONO_SPEAKERS_HSJACK), | 4768 | SND_PCI_QUIRK(0x1028, 0x0638, "Dell Inspiron 5439", ALC290_FIXUP_MONO_SPEAKERS_HSJACK), |
4610 | SND_PCI_QUIRK(0x1028, 0x063e, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
4611 | SND_PCI_QUIRK(0x1028, 0x063f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), | 4769 | SND_PCI_QUIRK(0x1028, 0x063f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), |
4612 | SND_PCI_QUIRK(0x1028, 0x0640, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), | 4770 | SND_PCI_QUIRK(0x1028, 0x064a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), |
4613 | SND_PCI_QUIRK(0x1028, 0x064d, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), | 4771 | SND_PCI_QUIRK(0x1028, 0x064b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), |
4614 | SND_PCI_QUIRK(0x1028, 0x0651, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
4615 | SND_PCI_QUIRK(0x1028, 0x0652, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
4616 | SND_PCI_QUIRK(0x1028, 0x0653, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
4617 | SND_PCI_QUIRK(0x1028, 0x0657, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
4618 | SND_PCI_QUIRK(0x1028, 0x0658, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
4619 | SND_PCI_QUIRK(0x1028, 0x065f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
4620 | SND_PCI_QUIRK(0x1028, 0x0662, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
4621 | SND_PCI_QUIRK(0x1028, 0x0667, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
4622 | SND_PCI_QUIRK(0x1028, 0x0668, "Dell", ALC255_FIXUP_DELL2_MIC_NO_PRESENCE), | 4772 | SND_PCI_QUIRK(0x1028, 0x0668, "Dell", ALC255_FIXUP_DELL2_MIC_NO_PRESENCE), |
4623 | SND_PCI_QUIRK(0x1028, 0x0669, "Dell", ALC255_FIXUP_DELL2_MIC_NO_PRESENCE), | 4773 | SND_PCI_QUIRK(0x1028, 0x0669, "Dell", ALC255_FIXUP_DELL2_MIC_NO_PRESENCE), |
4624 | SND_PCI_QUIRK(0x1028, 0x0674, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), | 4774 | SND_PCI_QUIRK(0x1028, 0x0684, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE), |
4625 | SND_PCI_QUIRK(0x1028, 0x067e, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
4626 | SND_PCI_QUIRK(0x1028, 0x067f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
4627 | SND_PCI_QUIRK(0x1028, 0x15cc, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE), | 4775 | SND_PCI_QUIRK(0x1028, 0x15cc, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE), |
4628 | SND_PCI_QUIRK(0x1028, 0x15cd, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE), | 4776 | SND_PCI_QUIRK(0x1028, 0x15cd, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE), |
4777 | SND_PCI_QUIRK(0x1028, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
4778 | SND_PCI_QUIRK(0x1028, 0x164b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
4629 | SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2), | 4779 | SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2), |
4630 | SND_PCI_QUIRK(0x103c, 0x18e6, "HP", ALC269_FIXUP_HP_GPIO_LED), | 4780 | SND_PCI_QUIRK(0x103c, 0x18e6, "HP", ALC269_FIXUP_HP_GPIO_LED), |
4631 | SND_PCI_QUIRK(0x103c, 0x1973, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4781 | SND_PCI_QUIRK(0x103c, 0x1973, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4632 | SND_PCI_QUIRK(0x103c, 0x1983, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4782 | SND_PCI_QUIRK(0x103c, 0x1983, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4633 | SND_PCI_QUIRK(0x103c, 0x218b, "HP", ALC269_FIXUP_LIMIT_INT_MIC_BOOST_MUTE_LED), | 4783 | SND_PCI_QUIRK(0x103c, 0x218b, "HP", ALC269_FIXUP_LIMIT_INT_MIC_BOOST_MUTE_LED), |
4634 | /* ALC282 */ | 4784 | /* ALC282 */ |
4785 | SND_PCI_QUIRK(0x103c, 0x220d, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4786 | SND_PCI_QUIRK(0x103c, 0x220e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4635 | SND_PCI_QUIRK(0x103c, 0x220f, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4787 | SND_PCI_QUIRK(0x103c, 0x220f, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4788 | SND_PCI_QUIRK(0x103c, 0x2210, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4789 | SND_PCI_QUIRK(0x103c, 0x2211, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4790 | SND_PCI_QUIRK(0x103c, 0x2212, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4636 | SND_PCI_QUIRK(0x103c, 0x2213, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4791 | SND_PCI_QUIRK(0x103c, 0x2213, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4792 | SND_PCI_QUIRK(0x103c, 0x2214, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4637 | SND_PCI_QUIRK(0x103c, 0x2266, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4793 | SND_PCI_QUIRK(0x103c, 0x2266, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4638 | SND_PCI_QUIRK(0x103c, 0x2267, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4794 | SND_PCI_QUIRK(0x103c, 0x2267, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4639 | SND_PCI_QUIRK(0x103c, 0x2268, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4795 | SND_PCI_QUIRK(0x103c, 0x2268, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4640 | SND_PCI_QUIRK(0x103c, 0x2269, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4796 | SND_PCI_QUIRK(0x103c, 0x2269, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4641 | SND_PCI_QUIRK(0x103c, 0x226a, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4797 | SND_PCI_QUIRK(0x103c, 0x226a, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4642 | SND_PCI_QUIRK(0x103c, 0x226b, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4798 | SND_PCI_QUIRK(0x103c, 0x226b, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4799 | SND_PCI_QUIRK(0x103c, 0x226c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4800 | SND_PCI_QUIRK(0x103c, 0x226d, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4801 | SND_PCI_QUIRK(0x103c, 0x226e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4802 | SND_PCI_QUIRK(0x103c, 0x226f, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4643 | SND_PCI_QUIRK(0x103c, 0x227a, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4803 | SND_PCI_QUIRK(0x103c, 0x227a, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4644 | SND_PCI_QUIRK(0x103c, 0x227b, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4804 | SND_PCI_QUIRK(0x103c, 0x227b, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4645 | SND_PCI_QUIRK(0x103c, 0x229e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4805 | SND_PCI_QUIRK(0x103c, 0x229e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
@@ -4679,6 +4839,10 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
4679 | SND_PCI_QUIRK(0x103c, 0x22c8, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4839 | SND_PCI_QUIRK(0x103c, 0x22c8, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4680 | SND_PCI_QUIRK(0x103c, 0x22c3, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4840 | SND_PCI_QUIRK(0x103c, 0x22c3, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4681 | SND_PCI_QUIRK(0x103c, 0x22c4, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4841 | SND_PCI_QUIRK(0x103c, 0x22c4, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4842 | SND_PCI_QUIRK(0x103c, 0x2334, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4843 | SND_PCI_QUIRK(0x103c, 0x2335, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4844 | SND_PCI_QUIRK(0x103c, 0x2336, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4845 | SND_PCI_QUIRK(0x103c, 0x2337, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4682 | SND_PCI_QUIRK_VENDOR(0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED), | 4846 | SND_PCI_QUIRK_VENDOR(0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED), |
4683 | SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300), | 4847 | SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300), |
4684 | SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), | 4848 | SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), |
@@ -4699,8 +4863,10 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
4699 | SND_PCI_QUIRK(0x104d, 0x9073, "Sony VAIO", ALC275_FIXUP_SONY_VAIO_GPIO2), | 4863 | SND_PCI_QUIRK(0x104d, 0x9073, "Sony VAIO", ALC275_FIXUP_SONY_VAIO_GPIO2), |
4700 | SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ), | 4864 | SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ), |
4701 | SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ), | 4865 | SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ), |
4866 | SND_PCI_QUIRK(0x104d, 0x9099, "Sony VAIO S13", ALC275_FIXUP_SONY_DISABLE_AAMIX), | ||
4702 | SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO), | 4867 | SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO), |
4703 | SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook", ALC269_FIXUP_LIFEBOOK), | 4868 | SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook", ALC269_FIXUP_LIFEBOOK), |
4869 | SND_PCI_QUIRK(0x10cf, 0x1845, "Lifebook U904", ALC269_FIXUP_LIFEBOOK_EXTMIC), | ||
4704 | SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE), | 4870 | SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE), |
4705 | SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE), | 4871 | SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE), |
4706 | SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE), | 4872 | SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE), |
@@ -4712,7 +4878,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
4712 | SND_PCI_QUIRK(0x17aa, 0x21fb, "Thinkpad T430s", ALC269_FIXUP_LENOVO_DOCK), | 4878 | SND_PCI_QUIRK(0x17aa, 0x21fb, "Thinkpad T430s", ALC269_FIXUP_LENOVO_DOCK), |
4713 | SND_PCI_QUIRK(0x17aa, 0x2203, "Thinkpad X230 Tablet", ALC269_FIXUP_LENOVO_DOCK), | 4879 | SND_PCI_QUIRK(0x17aa, 0x2203, "Thinkpad X230 Tablet", ALC269_FIXUP_LENOVO_DOCK), |
4714 | SND_PCI_QUIRK(0x17aa, 0x2208, "Thinkpad T431s", ALC269_FIXUP_LENOVO_DOCK), | 4880 | SND_PCI_QUIRK(0x17aa, 0x2208, "Thinkpad T431s", ALC269_FIXUP_LENOVO_DOCK), |
4715 | SND_PCI_QUIRK(0x17aa, 0x220c, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), | 4881 | SND_PCI_QUIRK(0x17aa, 0x220c, "Thinkpad T440s", ALC292_FIXUP_TPT440_DOCK), |
4882 | SND_PCI_QUIRK(0x17aa, 0x220e, "Thinkpad T440p", ALC292_FIXUP_TPT440_DOCK), | ||
4716 | SND_PCI_QUIRK(0x17aa, 0x2212, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), | 4883 | SND_PCI_QUIRK(0x17aa, 0x2212, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), |
4717 | SND_PCI_QUIRK(0x17aa, 0x2214, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), | 4884 | SND_PCI_QUIRK(0x17aa, 0x2214, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), |
4718 | SND_PCI_QUIRK(0x17aa, 0x2215, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), | 4885 | SND_PCI_QUIRK(0x17aa, 0x2215, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), |
@@ -4790,9 +4957,235 @@ static const struct hda_model_fixup alc269_fixup_models[] = { | |||
4790 | {.id = ALC269_FIXUP_DELL2_MIC_NO_PRESENCE, .name = "dell-headset-dock"}, | 4957 | {.id = ALC269_FIXUP_DELL2_MIC_NO_PRESENCE, .name = "dell-headset-dock"}, |
4791 | {.id = ALC283_FIXUP_CHROME_BOOK, .name = "alc283-dac-wcaps"}, | 4958 | {.id = ALC283_FIXUP_CHROME_BOOK, .name = "alc283-dac-wcaps"}, |
4792 | {.id = ALC283_FIXUP_SENSE_COMBO_JACK, .name = "alc283-sense-combo"}, | 4959 | {.id = ALC283_FIXUP_SENSE_COMBO_JACK, .name = "alc283-sense-combo"}, |
4960 | {.id = ALC292_FIXUP_TPT440_DOCK, .name = "tpt440-dock"}, | ||
4793 | {} | 4961 | {} |
4794 | }; | 4962 | }; |
4795 | 4963 | ||
4964 | static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { | ||
4965 | { | ||
4966 | .codec = 0x10ec0255, | ||
4967 | .subvendor = 0x1028, | ||
4968 | #ifdef CONFIG_SND_DEBUG_VERBOSE | ||
4969 | .name = "Dell", | ||
4970 | #endif | ||
4971 | .pins = (const struct hda_pintbl[]) { | ||
4972 | {0x12, 0x90a60140}, | ||
4973 | {0x14, 0x90170110}, | ||
4974 | {0x17, 0x40000000}, | ||
4975 | {0x18, 0x411111f0}, | ||
4976 | {0x19, 0x411111f0}, | ||
4977 | {0x1a, 0x411111f0}, | ||
4978 | {0x1b, 0x411111f0}, | ||
4979 | {0x1d, 0x40700001}, | ||
4980 | {0x1e, 0x411111f0}, | ||
4981 | {0x21, 0x02211020}, | ||
4982 | }, | ||
4983 | .value = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, | ||
4984 | }, | ||
4985 | { | ||
4986 | .codec = 0x10ec0255, | ||
4987 | .subvendor = 0x1028, | ||
4988 | #ifdef CONFIG_SND_DEBUG_VERBOSE | ||
4989 | .name = "Dell", | ||
4990 | #endif | ||
4991 | .pins = (const struct hda_pintbl[]) { | ||
4992 | {0x12, 0x90a60160}, | ||
4993 | {0x14, 0x90170120}, | ||
4994 | {0x17, 0x40000000}, | ||
4995 | {0x18, 0x411111f0}, | ||
4996 | {0x19, 0x411111f0}, | ||
4997 | {0x1a, 0x411111f0}, | ||
4998 | {0x1b, 0x411111f0}, | ||
4999 | {0x1d, 0x40700001}, | ||
5000 | {0x1e, 0x411111f0}, | ||
5001 | {0x21, 0x02211030}, | ||
5002 | }, | ||
5003 | .value = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, | ||
5004 | }, | ||
5005 | { | ||
5006 | .codec = 0x10ec0255, | ||
5007 | .subvendor = 0x1028, | ||
5008 | #ifdef CONFIG_SND_DEBUG_VERBOSE | ||
5009 | .name = "Dell", | ||
5010 | #endif | ||
5011 | .pins = (const struct hda_pintbl[]) { | ||
5012 | {0x12, 0x90a60160}, | ||
5013 | {0x14, 0x90170120}, | ||
5014 | {0x17, 0x90170140}, | ||
5015 | {0x18, 0x40000000}, | ||
5016 | {0x19, 0x411111f0}, | ||
5017 | {0x1a, 0x411111f0}, | ||
5018 | {0x1b, 0x411111f0}, | ||
5019 | {0x1d, 0x41163b05}, | ||
5020 | {0x1e, 0x411111f0}, | ||
5021 | {0x21, 0x0321102f}, | ||
5022 | }, | ||
5023 | .value = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, | ||
5024 | }, | ||
5025 | { | ||
5026 | .codec = 0x10ec0255, | ||
5027 | .subvendor = 0x1028, | ||
5028 | #ifdef CONFIG_SND_DEBUG_VERBOSE | ||
5029 | .name = "Dell", | ||
5030 | #endif | ||
5031 | .pins = (const struct hda_pintbl[]) { | ||
5032 | {0x12, 0x90a60160}, | ||
5033 | {0x14, 0x90170130}, | ||
5034 | {0x17, 0x40000000}, | ||
5035 | {0x18, 0x411111f0}, | ||
5036 | {0x19, 0x411111f0}, | ||
5037 | {0x1a, 0x411111f0}, | ||
5038 | {0x1b, 0x411111f0}, | ||
5039 | {0x1d, 0x40700001}, | ||
5040 | {0x1e, 0x411111f0}, | ||
5041 | {0x21, 0x02211040}, | ||
5042 | }, | ||
5043 | .value = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, | ||
5044 | }, | ||
5045 | { | ||
5046 | .codec = 0x10ec0255, | ||
5047 | .subvendor = 0x1028, | ||
5048 | #ifdef CONFIG_SND_DEBUG_VERBOSE | ||
5049 | .name = "Dell", | ||
5050 | #endif | ||
5051 | .pins = (const struct hda_pintbl[]) { | ||
5052 | {0x12, 0x90a60160}, | ||
5053 | {0x14, 0x90170140}, | ||
5054 | {0x17, 0x40000000}, | ||
5055 | {0x18, 0x411111f0}, | ||
5056 | {0x19, 0x411111f0}, | ||
5057 | {0x1a, 0x411111f0}, | ||
5058 | {0x1b, 0x411111f0}, | ||
5059 | {0x1d, 0x40700001}, | ||
5060 | {0x1e, 0x411111f0}, | ||
5061 | {0x21, 0x02211050}, | ||
5062 | }, | ||
5063 | .value = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, | ||
5064 | }, | ||
5065 | { | ||
5066 | .codec = 0x10ec0255, | ||
5067 | .subvendor = 0x1028, | ||
5068 | #ifdef CONFIG_SND_DEBUG_VERBOSE | ||
5069 | .name = "Dell", | ||
5070 | #endif | ||
5071 | .pins = (const struct hda_pintbl[]) { | ||
5072 | {0x12, 0x90a60170}, | ||
5073 | {0x14, 0x90170120}, | ||
5074 | {0x17, 0x40000000}, | ||
5075 | {0x18, 0x411111f0}, | ||
5076 | {0x19, 0x411111f0}, | ||
5077 | {0x1a, 0x411111f0}, | ||
5078 | {0x1b, 0x411111f0}, | ||
5079 | {0x1d, 0x40700001}, | ||
5080 | {0x1e, 0x411111f0}, | ||
5081 | {0x21, 0x02211030}, | ||
5082 | }, | ||
5083 | .value = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, | ||
5084 | }, | ||
5085 | { | ||
5086 | .codec = 0x10ec0255, | ||
5087 | .subvendor = 0x1028, | ||
5088 | #ifdef CONFIG_SND_DEBUG_VERBOSE | ||
5089 | .name = "Dell", | ||
5090 | #endif | ||
5091 | .pins = (const struct hda_pintbl[]) { | ||
5092 | {0x12, 0x90a60170}, | ||
5093 | {0x14, 0x90170130}, | ||
5094 | {0x17, 0x40000000}, | ||
5095 | {0x18, 0x411111f0}, | ||
5096 | {0x19, 0x411111f0}, | ||
5097 | {0x1a, 0x411111f0}, | ||
5098 | {0x1b, 0x411111f0}, | ||
5099 | {0x1d, 0x40700001}, | ||
5100 | {0x1e, 0x411111f0}, | ||
5101 | {0x21, 0x02211040}, | ||
5102 | }, | ||
5103 | .value = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, | ||
5104 | }, | ||
5105 | { | ||
5106 | .codec = 0x10ec0283, | ||
5107 | .subvendor = 0x1028, | ||
5108 | #ifdef CONFIG_SND_DEBUG_VERBOSE | ||
5109 | .name = "Dell", | ||
5110 | #endif | ||
5111 | .pins = (const struct hda_pintbl[]) { | ||
5112 | {0x12, 0x90a60130}, | ||
5113 | {0x14, 0x90170110}, | ||
5114 | {0x17, 0x40020008}, | ||
5115 | {0x18, 0x411111f0}, | ||
5116 | {0x19, 0x411111f0}, | ||
5117 | {0x1a, 0x411111f0}, | ||
5118 | {0x1b, 0x411111f0}, | ||
5119 | {0x1d, 0x40e00001}, | ||
5120 | {0x1e, 0x411111f0}, | ||
5121 | {0x21, 0x0321101f}, | ||
5122 | }, | ||
5123 | .value = ALC269_FIXUP_DELL1_MIC_NO_PRESENCE, | ||
5124 | }, | ||
5125 | { | ||
5126 | .codec = 0x10ec0283, | ||
5127 | .subvendor = 0x1028, | ||
5128 | #ifdef CONFIG_SND_DEBUG_VERBOSE | ||
5129 | .name = "Dell", | ||
5130 | #endif | ||
5131 | .pins = (const struct hda_pintbl[]) { | ||
5132 | {0x12, 0x90a60160}, | ||
5133 | {0x14, 0x90170120}, | ||
5134 | {0x17, 0x40000000}, | ||
5135 | {0x18, 0x411111f0}, | ||
5136 | {0x19, 0x411111f0}, | ||
5137 | {0x1a, 0x411111f0}, | ||
5138 | {0x1b, 0x411111f0}, | ||
5139 | {0x1d, 0x40700001}, | ||
5140 | {0x1e, 0x411111f0}, | ||
5141 | {0x21, 0x02211030}, | ||
5142 | }, | ||
5143 | .value = ALC269_FIXUP_DELL1_MIC_NO_PRESENCE, | ||
5144 | }, | ||
5145 | { | ||
5146 | .codec = 0x10ec0292, | ||
5147 | .subvendor = 0x1028, | ||
5148 | #ifdef CONFIG_SND_DEBUG_VERBOSE | ||
5149 | .name = "Dell", | ||
5150 | #endif | ||
5151 | .pins = (const struct hda_pintbl[]) { | ||
5152 | {0x12, 0x90a60140}, | ||
5153 | {0x13, 0x411111f0}, | ||
5154 | {0x14, 0x90170110}, | ||
5155 | {0x15, 0x0221401f}, | ||
5156 | {0x16, 0x411111f0}, | ||
5157 | {0x18, 0x411111f0}, | ||
5158 | {0x19, 0x411111f0}, | ||
5159 | {0x1a, 0x411111f0}, | ||
5160 | {0x1b, 0x411111f0}, | ||
5161 | {0x1d, 0x40700001}, | ||
5162 | {0x1e, 0x411111f0}, | ||
5163 | }, | ||
5164 | .value = ALC269_FIXUP_DELL3_MIC_NO_PRESENCE, | ||
5165 | }, | ||
5166 | { | ||
5167 | .codec = 0x10ec0293, | ||
5168 | .subvendor = 0x1028, | ||
5169 | #ifdef CONFIG_SND_DEBUG_VERBOSE | ||
5170 | .name = "Dell", | ||
5171 | #endif | ||
5172 | .pins = (const struct hda_pintbl[]) { | ||
5173 | {0x12, 0x40000000}, | ||
5174 | {0x13, 0x90a60140}, | ||
5175 | {0x14, 0x90170110}, | ||
5176 | {0x15, 0x0221401f}, | ||
5177 | {0x16, 0x21014020}, | ||
5178 | {0x18, 0x411111f0}, | ||
5179 | {0x19, 0x21a19030}, | ||
5180 | {0x1a, 0x411111f0}, | ||
5181 | {0x1b, 0x411111f0}, | ||
5182 | {0x1d, 0x40700001}, | ||
5183 | {0x1e, 0x411111f0}, | ||
5184 | }, | ||
5185 | .value = ALC293_FIXUP_DELL1_MIC_NO_PRESENCE, | ||
5186 | }, | ||
5187 | {} | ||
5188 | }; | ||
4796 | 5189 | ||
4797 | static void alc269_fill_coef(struct hda_codec *codec) | 5190 | static void alc269_fill_coef(struct hda_codec *codec) |
4798 | { | 5191 | { |
@@ -4854,6 +5247,7 @@ static int patch_alc269(struct hda_codec *codec) | |||
4854 | 5247 | ||
4855 | snd_hda_pick_fixup(codec, alc269_fixup_models, | 5248 | snd_hda_pick_fixup(codec, alc269_fixup_models, |
4856 | alc269_fixup_tbl, alc269_fixups); | 5249 | alc269_fixup_tbl, alc269_fixups); |
5250 | snd_hda_pick_pin_fixup(codec, alc269_pin_fixup_tbl, alc269_fixups); | ||
4857 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); | 5251 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); |
4858 | 5252 | ||
4859 | alc_auto_parse_customize_define(codec); | 5253 | alc_auto_parse_customize_define(codec); |
@@ -5310,6 +5704,8 @@ enum { | |||
5310 | ALC662_FIXUP_BASS_1A, | 5704 | ALC662_FIXUP_BASS_1A, |
5311 | ALC662_FIXUP_BASS_CHMAP, | 5705 | ALC662_FIXUP_BASS_CHMAP, |
5312 | ALC668_FIXUP_AUTO_MUTE, | 5706 | ALC668_FIXUP_AUTO_MUTE, |
5707 | ALC668_FIXUP_DELL_DISABLE_AAMIX, | ||
5708 | ALC668_FIXUP_DELL_XPS13, | ||
5313 | }; | 5709 | }; |
5314 | 5710 | ||
5315 | static const struct hda_fixup alc662_fixups[] = { | 5711 | static const struct hda_fixup alc662_fixups[] = { |
@@ -5476,6 +5872,18 @@ static const struct hda_fixup alc662_fixups[] = { | |||
5476 | .type = HDA_FIXUP_FUNC, | 5872 | .type = HDA_FIXUP_FUNC, |
5477 | .v.func = alc_fixup_inv_dmic_0x12, | 5873 | .v.func = alc_fixup_inv_dmic_0x12, |
5478 | }, | 5874 | }, |
5875 | [ALC668_FIXUP_DELL_XPS13] = { | ||
5876 | .type = HDA_FIXUP_FUNC, | ||
5877 | .v.func = alc_fixup_dell_xps13, | ||
5878 | .chained = true, | ||
5879 | .chain_id = ALC668_FIXUP_DELL_DISABLE_AAMIX | ||
5880 | }, | ||
5881 | [ALC668_FIXUP_DELL_DISABLE_AAMIX] = { | ||
5882 | .type = HDA_FIXUP_FUNC, | ||
5883 | .v.func = alc_fixup_disable_aamix, | ||
5884 | .chained = true, | ||
5885 | .chain_id = ALC668_FIXUP_DELL_MIC_NO_PRESENCE | ||
5886 | }, | ||
5479 | [ALC668_FIXUP_AUTO_MUTE] = { | 5887 | [ALC668_FIXUP_AUTO_MUTE] = { |
5480 | .type = HDA_FIXUP_FUNC, | 5888 | .type = HDA_FIXUP_FUNC, |
5481 | .v.func = alc_fixup_auto_mute_via_amp, | 5889 | .v.func = alc_fixup_auto_mute_via_amp, |
@@ -5536,13 +5944,9 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = { | |||
5536 | SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE), | 5944 | SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE), |
5537 | SND_PCI_QUIRK(0x1028, 0x05d8, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), | 5945 | SND_PCI_QUIRK(0x1028, 0x05d8, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), |
5538 | SND_PCI_QUIRK(0x1028, 0x05db, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), | 5946 | SND_PCI_QUIRK(0x1028, 0x05db, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), |
5539 | SND_PCI_QUIRK(0x1028, 0x060a, "Dell XPS 13", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), | 5947 | SND_PCI_QUIRK(0x1028, 0x060a, "Dell XPS 13", ALC668_FIXUP_DELL_XPS13), |
5540 | SND_PCI_QUIRK(0x1028, 0x0623, "Dell", ALC668_FIXUP_AUTO_MUTE), | ||
5541 | SND_PCI_QUIRK(0x1028, 0x0624, "Dell", ALC668_FIXUP_AUTO_MUTE), | ||
5542 | SND_PCI_QUIRK(0x1028, 0x0625, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), | 5948 | SND_PCI_QUIRK(0x1028, 0x0625, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), |
5543 | SND_PCI_QUIRK(0x1028, 0x0626, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), | 5949 | SND_PCI_QUIRK(0x1028, 0x0626, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), |
5544 | SND_PCI_QUIRK(0x1028, 0x0628, "Dell", ALC668_FIXUP_AUTO_MUTE), | ||
5545 | SND_PCI_QUIRK(0x1028, 0x064e, "Dell", ALC668_FIXUP_AUTO_MUTE), | ||
5546 | SND_PCI_QUIRK(0x1028, 0x0696, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), | 5950 | SND_PCI_QUIRK(0x1028, 0x0696, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), |
5547 | SND_PCI_QUIRK(0x1028, 0x0698, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), | 5951 | SND_PCI_QUIRK(0x1028, 0x0698, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), |
5548 | SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800), | 5952 | SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800), |
@@ -5634,6 +6038,94 @@ static const struct hda_model_fixup alc662_fixup_models[] = { | |||
5634 | {} | 6038 | {} |
5635 | }; | 6039 | }; |
5636 | 6040 | ||
6041 | static const struct snd_hda_pin_quirk alc662_pin_fixup_tbl[] = { | ||
6042 | { | ||
6043 | .codec = 0x10ec0668, | ||
6044 | .subvendor = 0x1028, | ||
6045 | #ifdef CONFIG_SND_DEBUG_VERBOSE | ||
6046 | .name = "Dell", | ||
6047 | #endif | ||
6048 | .pins = (const struct hda_pintbl[]) { | ||
6049 | {0x12, 0x99a30130}, | ||
6050 | {0x14, 0x90170110}, | ||
6051 | {0x15, 0x0321101f}, | ||
6052 | {0x16, 0x03011020}, | ||
6053 | {0x18, 0x40000008}, | ||
6054 | {0x19, 0x411111f0}, | ||
6055 | {0x1a, 0x411111f0}, | ||
6056 | {0x1b, 0x411111f0}, | ||
6057 | {0x1d, 0x41000001}, | ||
6058 | {0x1e, 0x411111f0}, | ||
6059 | {0x1f, 0x411111f0}, | ||
6060 | }, | ||
6061 | .value = ALC668_FIXUP_AUTO_MUTE, | ||
6062 | }, | ||
6063 | { | ||
6064 | .codec = 0x10ec0668, | ||
6065 | .subvendor = 0x1028, | ||
6066 | #ifdef CONFIG_SND_DEBUG_VERBOSE | ||
6067 | .name = "Dell", | ||
6068 | #endif | ||
6069 | .pins = (const struct hda_pintbl[]) { | ||
6070 | {0x12, 0x99a30140}, | ||
6071 | {0x14, 0x90170110}, | ||
6072 | {0x15, 0x0321101f}, | ||
6073 | {0x16, 0x03011020}, | ||
6074 | {0x18, 0x40000008}, | ||
6075 | {0x19, 0x411111f0}, | ||
6076 | {0x1a, 0x411111f0}, | ||
6077 | {0x1b, 0x411111f0}, | ||
6078 | {0x1d, 0x41000001}, | ||
6079 | {0x1e, 0x411111f0}, | ||
6080 | {0x1f, 0x411111f0}, | ||
6081 | }, | ||
6082 | .value = ALC668_FIXUP_AUTO_MUTE, | ||
6083 | }, | ||
6084 | { | ||
6085 | .codec = 0x10ec0668, | ||
6086 | .subvendor = 0x1028, | ||
6087 | #ifdef CONFIG_SND_DEBUG_VERBOSE | ||
6088 | .name = "Dell", | ||
6089 | #endif | ||
6090 | .pins = (const struct hda_pintbl[]) { | ||
6091 | {0x12, 0x99a30150}, | ||
6092 | {0x14, 0x90170110}, | ||
6093 | {0x15, 0x0321101f}, | ||
6094 | {0x16, 0x03011020}, | ||
6095 | {0x18, 0x40000008}, | ||
6096 | {0x19, 0x411111f0}, | ||
6097 | {0x1a, 0x411111f0}, | ||
6098 | {0x1b, 0x411111f0}, | ||
6099 | {0x1d, 0x41000001}, | ||
6100 | {0x1e, 0x411111f0}, | ||
6101 | {0x1f, 0x411111f0}, | ||
6102 | }, | ||
6103 | .value = ALC668_FIXUP_AUTO_MUTE, | ||
6104 | }, | ||
6105 | { | ||
6106 | .codec = 0x10ec0668, | ||
6107 | .subvendor = 0x1028, | ||
6108 | #ifdef CONFIG_SND_DEBUG_VERBOSE | ||
6109 | .name = "Dell", | ||
6110 | #endif | ||
6111 | .pins = (const struct hda_pintbl[]) { | ||
6112 | {0x12, 0x411111f0}, | ||
6113 | {0x14, 0x90170110}, | ||
6114 | {0x15, 0x0321101f}, | ||
6115 | {0x16, 0x03011020}, | ||
6116 | {0x18, 0x40000008}, | ||
6117 | {0x19, 0x411111f0}, | ||
6118 | {0x1a, 0x411111f0}, | ||
6119 | {0x1b, 0x411111f0}, | ||
6120 | {0x1d, 0x41000001}, | ||
6121 | {0x1e, 0x411111f0}, | ||
6122 | {0x1f, 0x411111f0}, | ||
6123 | }, | ||
6124 | .value = ALC668_FIXUP_AUTO_MUTE, | ||
6125 | }, | ||
6126 | {} | ||
6127 | }; | ||
6128 | |||
5637 | static void alc662_fill_coef(struct hda_codec *codec) | 6129 | static void alc662_fill_coef(struct hda_codec *codec) |
5638 | { | 6130 | { |
5639 | int val, coef; | 6131 | int val, coef; |
@@ -5683,6 +6175,7 @@ static int patch_alc662(struct hda_codec *codec) | |||
5683 | 6175 | ||
5684 | snd_hda_pick_fixup(codec, alc662_fixup_models, | 6176 | snd_hda_pick_fixup(codec, alc662_fixup_models, |
5685 | alc662_fixup_tbl, alc662_fixups); | 6177 | alc662_fixup_tbl, alc662_fixups); |
6178 | snd_hda_pick_pin_fixup(codec, alc662_pin_fixup_tbl, alc662_fixups); | ||
5686 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); | 6179 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); |
5687 | 6180 | ||
5688 | alc_auto_parse_customize_define(codec); | 6181 | alc_auto_parse_customize_define(codec); |
@@ -5771,6 +6264,7 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = { | |||
5771 | { .id = 0x10ec0221, .name = "ALC221", .patch = patch_alc269 }, | 6264 | { .id = 0x10ec0221, .name = "ALC221", .patch = patch_alc269 }, |
5772 | { .id = 0x10ec0231, .name = "ALC231", .patch = patch_alc269 }, | 6265 | { .id = 0x10ec0231, .name = "ALC231", .patch = patch_alc269 }, |
5773 | { .id = 0x10ec0233, .name = "ALC233", .patch = patch_alc269 }, | 6266 | { .id = 0x10ec0233, .name = "ALC233", .patch = patch_alc269 }, |
6267 | { .id = 0x10ec0235, .name = "ALC233", .patch = patch_alc269 }, | ||
5774 | { .id = 0x10ec0255, .name = "ALC255", .patch = patch_alc269 }, | 6268 | { .id = 0x10ec0255, .name = "ALC255", .patch = patch_alc269 }, |
5775 | { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 }, | 6269 | { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 }, |
5776 | { .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 }, | 6270 | { .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 }, |
@@ -5804,10 +6298,12 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = { | |||
5804 | .patch = patch_alc662 }, | 6298 | .patch = patch_alc662 }, |
5805 | { .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 }, | 6299 | { .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 }, |
5806 | { .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 }, | 6300 | { .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 }, |
6301 | { .id = 0x10ec0667, .name = "ALC667", .patch = patch_alc662 }, | ||
5807 | { .id = 0x10ec0668, .name = "ALC668", .patch = patch_alc662 }, | 6302 | { .id = 0x10ec0668, .name = "ALC668", .patch = patch_alc662 }, |
5808 | { .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 }, | 6303 | { .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 }, |
5809 | { .id = 0x10ec0671, .name = "ALC671", .patch = patch_alc662 }, | 6304 | { .id = 0x10ec0671, .name = "ALC671", .patch = patch_alc662 }, |
5810 | { .id = 0x10ec0680, .name = "ALC680", .patch = patch_alc680 }, | 6305 | { .id = 0x10ec0680, .name = "ALC680", .patch = patch_alc680 }, |
6306 | { .id = 0x10ec0867, .name = "ALC891", .patch = patch_alc882 }, | ||
5811 | { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 }, | 6307 | { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 }, |
5812 | { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 }, | 6308 | { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 }, |
5813 | { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc882 }, | 6309 | { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc882 }, |
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 75515b494034..7f40a150899c 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -795,7 +795,7 @@ static int find_mute_led_cfg(struct hda_codec *codec, int default_polarity) | |||
795 | } | 795 | } |
796 | 796 | ||
797 | while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, NULL, dev))) { | 797 | while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, NULL, dev))) { |
798 | if (sscanf(dev->name, "HP_Mute_LED_%d_%x", | 798 | if (sscanf(dev->name, "HP_Mute_LED_%u_%x", |
799 | &spec->gpio_led_polarity, | 799 | &spec->gpio_led_polarity, |
800 | &spec->gpio_led) == 2) { | 800 | &spec->gpio_led) == 2) { |
801 | unsigned int max_gpio; | 801 | unsigned int max_gpio; |
@@ -808,7 +808,7 @@ static int find_mute_led_cfg(struct hda_codec *codec, int default_polarity) | |||
808 | spec->vref_mute_led_nid = spec->gpio_led; | 808 | spec->vref_mute_led_nid = spec->gpio_led; |
809 | return 1; | 809 | return 1; |
810 | } | 810 | } |
811 | if (sscanf(dev->name, "HP_Mute_LED_%d", | 811 | if (sscanf(dev->name, "HP_Mute_LED_%u", |
812 | &spec->gpio_led_polarity) == 1) { | 812 | &spec->gpio_led_polarity) == 1) { |
813 | set_hp_led_gpio(codec); | 813 | set_hp_led_gpio(codec); |
814 | return 1; | 814 | return 1; |
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 68340d7df76d..c91860e0a28d 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c | |||
@@ -2779,7 +2779,7 @@ static void intel8x0_measure_ac97_clock(struct intel8x0 *chip) | |||
2779 | unsigned long port; | 2779 | unsigned long port; |
2780 | unsigned long pos, pos1, t; | 2780 | unsigned long pos, pos1, t; |
2781 | int civ, timeout = 1000, attempt = 1; | 2781 | int civ, timeout = 1000, attempt = 1; |
2782 | struct timespec start_time, stop_time; | 2782 | ktime_t start_time, stop_time; |
2783 | 2783 | ||
2784 | if (chip->ac97_bus->clock != 48000) | 2784 | if (chip->ac97_bus->clock != 48000) |
2785 | return; /* specified in module option */ | 2785 | return; /* specified in module option */ |
@@ -2813,7 +2813,7 @@ static void intel8x0_measure_ac97_clock(struct intel8x0 *chip) | |||
2813 | iputbyte(chip, port + ICH_REG_OFF_CR, ICH_IOCE); | 2813 | iputbyte(chip, port + ICH_REG_OFF_CR, ICH_IOCE); |
2814 | iputdword(chip, ICHREG(ALI_DMACR), 1 << ichdev->ali_slot); | 2814 | iputdword(chip, ICHREG(ALI_DMACR), 1 << ichdev->ali_slot); |
2815 | } | 2815 | } |
2816 | do_posix_clock_monotonic_gettime(&start_time); | 2816 | start_time = ktime_get(); |
2817 | spin_unlock_irq(&chip->reg_lock); | 2817 | spin_unlock_irq(&chip->reg_lock); |
2818 | msleep(50); | 2818 | msleep(50); |
2819 | spin_lock_irq(&chip->reg_lock); | 2819 | spin_lock_irq(&chip->reg_lock); |
@@ -2837,7 +2837,7 @@ static void intel8x0_measure_ac97_clock(struct intel8x0 *chip) | |||
2837 | pos += ichdev->position; | 2837 | pos += ichdev->position; |
2838 | } | 2838 | } |
2839 | chip->in_measurement = 0; | 2839 | chip->in_measurement = 0; |
2840 | do_posix_clock_monotonic_gettime(&stop_time); | 2840 | stop_time = ktime_get(); |
2841 | /* stop */ | 2841 | /* stop */ |
2842 | if (chip->device_type == DEVICE_ALI) { | 2842 | if (chip->device_type == DEVICE_ALI) { |
2843 | iputdword(chip, ICHREG(ALI_DMACR), 1 << (ichdev->ali_slot + 16)); | 2843 | iputdword(chip, ICHREG(ALI_DMACR), 1 << (ichdev->ali_slot + 16)); |
@@ -2865,9 +2865,7 @@ static void intel8x0_measure_ac97_clock(struct intel8x0 *chip) | |||
2865 | } | 2865 | } |
2866 | 2866 | ||
2867 | pos /= 4; | 2867 | pos /= 4; |
2868 | t = stop_time.tv_sec - start_time.tv_sec; | 2868 | t = ktime_us_delta(stop_time, start_time); |
2869 | t *= 1000000; | ||
2870 | t += (stop_time.tv_nsec - start_time.tv_nsec) / 1000; | ||
2871 | dev_info(chip->card->dev, | 2869 | dev_info(chip->card->dev, |
2872 | "%s: measured %lu usecs (%lu samples)\n", __func__, t, pos); | 2870 | "%s: measured %lu usecs (%lu samples)\n", __func__, t, pos); |
2873 | if (t == 0) { | 2871 | if (t == 0) { |
diff --git a/sound/pci/lola/lola_proc.c b/sound/pci/lola/lola_proc.c index 04df83defc09..c241dc06dd92 100644 --- a/sound/pci/lola/lola_proc.c +++ b/sound/pci/lola/lola_proc.c | |||
@@ -151,7 +151,7 @@ static void lola_proc_codec_rw_write(struct snd_info_entry *entry, | |||
151 | char line[64]; | 151 | char line[64]; |
152 | unsigned int id, verb, data, extdata; | 152 | unsigned int id, verb, data, extdata; |
153 | while (!snd_info_get_line(buffer, line, sizeof(line))) { | 153 | while (!snd_info_get_line(buffer, line, sizeof(line))) { |
154 | if (sscanf(line, "%i %i %i %i", &id, &verb, &data, &extdata) != 4) | 154 | if (sscanf(line, "%u %u %u %u", &id, &verb, &data, &extdata) != 4) |
155 | continue; | 155 | continue; |
156 | lola_codec_read(chip, id, verb, data, extdata, | 156 | lola_codec_read(chip, id, verb, data, extdata, |
157 | &chip->debug_res, | 157 | &chip->debug_res, |
diff --git a/sound/pci/lx6464es/lx_core.c b/sound/pci/lx6464es/lx_core.c index 2d8e95e9fbe5..e8f38e5df10a 100644 --- a/sound/pci/lx6464es/lx_core.c +++ b/sound/pci/lx6464es/lx_core.c | |||
@@ -24,6 +24,7 @@ | |||
24 | 24 | ||
25 | /* #define RMH_DEBUG 1 */ | 25 | /* #define RMH_DEBUG 1 */ |
26 | 26 | ||
27 | #include <linux/bitops.h> | ||
27 | #include <linux/module.h> | 28 | #include <linux/module.h> |
28 | #include <linux/pci.h> | 29 | #include <linux/pci.h> |
29 | #include <linux/delay.h> | 30 | #include <linux/delay.h> |
@@ -429,11 +430,6 @@ int lx_dsp_read_async_events(struct lx6464es *chip, u32 *data) | |||
429 | return ret; | 430 | return ret; |
430 | } | 431 | } |
431 | 432 | ||
432 | #define CSES_TIMEOUT 100 /* microseconds */ | ||
433 | #define CSES_CE 0x0001 | ||
434 | #define CSES_BROADCAST 0x0002 | ||
435 | #define CSES_UPDATE_LDSV 0x0004 | ||
436 | |||
437 | #define PIPE_INFO_TO_CMD(capture, pipe) \ | 433 | #define PIPE_INFO_TO_CMD(capture, pipe) \ |
438 | ((u32)((u32)(pipe) | ((capture) ? ID_IS_CAPTURE : 0L)) << ID_OFFSET) | 434 | ((u32)((u32)(pipe) | ((capture) ? ID_IS_CAPTURE : 0L)) << ID_OFFSET) |
439 | 435 | ||
@@ -519,7 +515,6 @@ int lx_buffer_ask(struct lx6464es *chip, u32 pipe, int is_capture, | |||
519 | *r_needed += 1; | 515 | *r_needed += 1; |
520 | } | 516 | } |
521 | 517 | ||
522 | #if 0 | ||
523 | dev_dbg(chip->card->dev, | 518 | dev_dbg(chip->card->dev, |
524 | "CMD_08_ASK_BUFFERS: needed %d, freed %d\n", | 519 | "CMD_08_ASK_BUFFERS: needed %d, freed %d\n", |
525 | *r_needed, *r_freed); | 520 | *r_needed, *r_freed); |
@@ -530,7 +525,6 @@ int lx_buffer_ask(struct lx6464es *chip, u32 pipe, int is_capture, | |||
530 | chip->rmh.stat[i], | 525 | chip->rmh.stat[i], |
531 | chip->rmh.stat[i] & MASK_DATA_SIZE); | 526 | chip->rmh.stat[i] & MASK_DATA_SIZE); |
532 | } | 527 | } |
533 | #endif | ||
534 | } | 528 | } |
535 | 529 | ||
536 | spin_unlock_irqrestore(&chip->msg_lock, flags); | 530 | spin_unlock_irqrestore(&chip->msg_lock, flags); |
@@ -971,9 +965,9 @@ int lx_level_peaks(struct lx6464es *chip, int is_capture, int channels, | |||
971 | 965 | ||
972 | /* interrupt handling */ | 966 | /* interrupt handling */ |
973 | #define PCX_IRQ_NONE 0 | 967 | #define PCX_IRQ_NONE 0 |
974 | #define IRQCS_ACTIVE_PCIDB 0x00002000L /* Bit nø 13 */ | 968 | #define IRQCS_ACTIVE_PCIDB BIT(13) |
975 | #define IRQCS_ENABLE_PCIIRQ 0x00000100L /* Bit nø 08 */ | 969 | #define IRQCS_ENABLE_PCIIRQ BIT(8) |
976 | #define IRQCS_ENABLE_PCIDB 0x00000200L /* Bit nø 09 */ | 970 | #define IRQCS_ENABLE_PCIDB BIT(9) |
977 | 971 | ||
978 | static u32 lx_interrupt_test_ack(struct lx6464es *chip) | 972 | static u32 lx_interrupt_test_ack(struct lx6464es *chip) |
979 | { | 973 | { |
@@ -1030,25 +1024,21 @@ static int lx_interrupt_handle_async_events(struct lx6464es *chip, u32 irqsrc, | |||
1030 | int err; | 1024 | int err; |
1031 | u32 stat[9]; /* answer from CMD_04_GET_EVENT */ | 1025 | u32 stat[9]; /* answer from CMD_04_GET_EVENT */ |
1032 | 1026 | ||
1033 | /* On peut optimiser pour ne pas lire les evenements vides | 1027 | /* We can optimize this to not read dumb events. |
1034 | * les mots de réponse sont dans l'ordre suivant : | 1028 | * Answer words are in the following order: |
1035 | * Stat[0] mot de status général | 1029 | * Stat[0] general status |
1036 | * Stat[1] fin de buffer OUT pF | 1030 | * Stat[1] end of buffer OUT pF |
1037 | * Stat[2] fin de buffer OUT pf | 1031 | * Stat[2] end of buffer OUT pf |
1038 | * Stat[3] fin de buffer IN pF | 1032 | * Stat[3] end of buffer IN pF |
1039 | * Stat[4] fin de buffer IN pf | 1033 | * Stat[4] end of buffer IN pf |
1040 | * Stat[5] underrun poid fort | 1034 | * Stat[5] MSB underrun |
1041 | * Stat[6] underrun poid faible | 1035 | * Stat[6] LSB underrun |
1042 | * Stat[7] overrun poid fort | 1036 | * Stat[7] MSB overrun |
1043 | * Stat[8] overrun poid faible | 1037 | * Stat[8] LSB overrun |
1044 | * */ | 1038 | * */ |
1045 | 1039 | ||
1046 | u64 orun_mask; | 1040 | u64 orun_mask; |
1047 | u64 urun_mask; | 1041 | u64 urun_mask; |
1048 | #if 0 | ||
1049 | int has_underrun = (irqsrc & MASK_SYS_STATUS_URUN) ? 1 : 0; | ||
1050 | int has_overrun = (irqsrc & MASK_SYS_STATUS_ORUN) ? 1 : 0; | ||
1051 | #endif | ||
1052 | int eb_pending_out = (irqsrc & MASK_SYS_STATUS_EOBO) ? 1 : 0; | 1042 | int eb_pending_out = (irqsrc & MASK_SYS_STATUS_EOBO) ? 1 : 0; |
1053 | int eb_pending_in = (irqsrc & MASK_SYS_STATUS_EOBI) ? 1 : 0; | 1043 | int eb_pending_in = (irqsrc & MASK_SYS_STATUS_EOBI) ? 1 : 0; |
1054 | 1044 | ||
@@ -1199,9 +1189,8 @@ irqreturn_t lx_interrupt(int irq, void *dev_id) | |||
1199 | if (irqsrc & MASK_SYS_STATUS_CMD_DONE) | 1189 | if (irqsrc & MASK_SYS_STATUS_CMD_DONE) |
1200 | goto exit; | 1190 | goto exit; |
1201 | 1191 | ||
1202 | #if 0 | ||
1203 | if (irqsrc & MASK_SYS_STATUS_EOBI) | 1192 | if (irqsrc & MASK_SYS_STATUS_EOBI) |
1204 | dev_dgg(chip->card->dev, "interrupt: EOBI\n"); | 1193 | dev_dbg(chip->card->dev, "interrupt: EOBI\n"); |
1205 | 1194 | ||
1206 | if (irqsrc & MASK_SYS_STATUS_EOBO) | 1195 | if (irqsrc & MASK_SYS_STATUS_EOBO) |
1207 | dev_dbg(chip->card->dev, "interrupt: EOBO\n"); | 1196 | dev_dbg(chip->card->dev, "interrupt: EOBO\n"); |
@@ -1211,7 +1200,6 @@ irqreturn_t lx_interrupt(int irq, void *dev_id) | |||
1211 | 1200 | ||
1212 | if (irqsrc & MASK_SYS_STATUS_ORUN) | 1201 | if (irqsrc & MASK_SYS_STATUS_ORUN) |
1213 | dev_dbg(chip->card->dev, "interrupt: ORUN\n"); | 1202 | dev_dbg(chip->card->dev, "interrupt: ORUN\n"); |
1214 | #endif | ||
1215 | 1203 | ||
1216 | if (async_pending) { | 1204 | if (async_pending) { |
1217 | u64 notified_in_pipe_mask = 0; | 1205 | u64 notified_in_pipe_mask = 0; |
@@ -1238,7 +1226,6 @@ irqreturn_t lx_interrupt(int irq, void *dev_id) | |||
1238 | } | 1226 | } |
1239 | 1227 | ||
1240 | if (async_escmd) { | 1228 | if (async_escmd) { |
1241 | #if 0 | ||
1242 | /* backdoor for ethersound commands | 1229 | /* backdoor for ethersound commands |
1243 | * | 1230 | * |
1244 | * for now, we do not need this | 1231 | * for now, we do not need this |
@@ -1246,7 +1233,6 @@ irqreturn_t lx_interrupt(int irq, void *dev_id) | |||
1246 | * */ | 1233 | * */ |
1247 | 1234 | ||
1248 | dev_dbg(chip->card->dev, "interrupt requests escmd handling\n"); | 1235 | dev_dbg(chip->card->dev, "interrupt requests escmd handling\n"); |
1249 | #endif | ||
1250 | } | 1236 | } |
1251 | 1237 | ||
1252 | exit: | 1238 | exit: |
diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c index 174bd546c08b..bb1149126c54 100644 --- a/sound/soc/atmel/sam9g20_wm8731.c +++ b/sound/soc/atmel/sam9g20_wm8731.c | |||
@@ -48,7 +48,6 @@ | |||
48 | 48 | ||
49 | #include <asm/mach-types.h> | 49 | #include <asm/mach-types.h> |
50 | #include <mach/hardware.h> | 50 | #include <mach/hardware.h> |
51 | #include <mach/gpio.h> | ||
52 | 51 | ||
53 | #include "../codecs/wm8731.h" | 52 | #include "../codecs/wm8731.h" |
54 | #include "atmel-pcm.h" | 53 | #include "atmel-pcm.h" |
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index cbfa1e18f651..0b9571c858f8 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig | |||
@@ -225,11 +225,11 @@ config SND_SOC_ADAU1373 | |||
225 | config SND_SOC_ADAU1701 | 225 | config SND_SOC_ADAU1701 |
226 | tristate "Analog Devices ADAU1701 CODEC" | 226 | tristate "Analog Devices ADAU1701 CODEC" |
227 | depends on I2C | 227 | depends on I2C |
228 | select SND_SOC_SIGMADSP | 228 | select SND_SOC_SIGMADSP_I2C |
229 | 229 | ||
230 | config SND_SOC_ADAU17X1 | 230 | config SND_SOC_ADAU17X1 |
231 | tristate | 231 | tristate |
232 | select SND_SOC_SIGMADSP | 232 | select SND_SOC_SIGMADSP_REGMAP |
233 | 233 | ||
234 | config SND_SOC_ADAU1761 | 234 | config SND_SOC_ADAU1761 |
235 | tristate | 235 | tristate |
@@ -476,6 +476,14 @@ config SND_SOC_SIGMADSP | |||
476 | tristate | 476 | tristate |
477 | select CRC32 | 477 | select CRC32 |
478 | 478 | ||
479 | config SND_SOC_SIGMADSP_I2C | ||
480 | tristate | ||
481 | select SND_SOC_SIGMADSP | ||
482 | |||
483 | config SND_SOC_SIGMADSP_REGMAP | ||
484 | tristate | ||
485 | select SND_SOC_SIGMADSP | ||
486 | |||
479 | config SND_SOC_SIRF_AUDIO_CODEC | 487 | config SND_SOC_SIRF_AUDIO_CODEC |
480 | tristate "SiRF SoC internal audio codec" | 488 | tristate "SiRF SoC internal audio codec" |
481 | select REGMAP_MMIO | 489 | select REGMAP_MMIO |
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index be3377b8d73f..1bd6e1cf6f82 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile | |||
@@ -77,6 +77,8 @@ snd-soc-sgtl5000-objs := sgtl5000.o | |||
77 | snd-soc-alc5623-objs := alc5623.o | 77 | snd-soc-alc5623-objs := alc5623.o |
78 | snd-soc-alc5632-objs := alc5632.o | 78 | snd-soc-alc5632-objs := alc5632.o |
79 | snd-soc-sigmadsp-objs := sigmadsp.o | 79 | snd-soc-sigmadsp-objs := sigmadsp.o |
80 | snd-soc-sigmadsp-i2c-objs := sigmadsp-i2c.o | ||
81 | snd-soc-sigmadsp-regmap-objs := sigmadsp-regmap.o | ||
80 | snd-soc-si476x-objs := si476x.o | 82 | snd-soc-si476x-objs := si476x.o |
81 | snd-soc-sirf-audio-codec-objs := sirf-audio-codec.o | 83 | snd-soc-sirf-audio-codec-objs := sirf-audio-codec.o |
82 | snd-soc-sn95031-objs := sn95031.o | 84 | snd-soc-sn95031-objs := sn95031.o |
@@ -240,6 +242,8 @@ obj-$(CONFIG_SND_SOC_RT5651) += snd-soc-rt5651.o | |||
240 | obj-$(CONFIG_SND_SOC_RT5677) += snd-soc-rt5677.o | 242 | obj-$(CONFIG_SND_SOC_RT5677) += snd-soc-rt5677.o |
241 | obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o | 243 | obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o |
242 | obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o | 244 | obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o |
245 | obj-$(CONFIG_SND_SOC_SIGMADSP_I2C) += snd-soc-sigmadsp-i2c.o | ||
246 | obj-$(CONFIG_SND_SOC_SIGMADSP_REGMAP) += snd-soc-sigmadsp-regmap.o | ||
243 | obj-$(CONFIG_SND_SOC_SI476X) += snd-soc-si476x.o | 247 | obj-$(CONFIG_SND_SOC_SI476X) += snd-soc-si476x.o |
244 | obj-$(CONFIG_SND_SOC_SN95031) +=snd-soc-sn95031.o | 248 | obj-$(CONFIG_SND_SOC_SN95031) +=snd-soc-sn95031.o |
245 | obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif-rx.o snd-soc-spdif-tx.o | 249 | obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif-rx.o snd-soc-spdif-tx.o |
diff --git a/sound/soc/codecs/sigmadsp-i2c.c b/sound/soc/codecs/sigmadsp-i2c.c new file mode 100644 index 000000000000..246081aae8ca --- /dev/null +++ b/sound/soc/codecs/sigmadsp-i2c.c | |||
@@ -0,0 +1,35 @@ | |||
1 | /* | ||
2 | * Load Analog Devices SigmaStudio firmware files | ||
3 | * | ||
4 | * Copyright 2009-2011 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2 or later. | ||
7 | */ | ||
8 | |||
9 | #include <linux/i2c.h> | ||
10 | #include <linux/export.h> | ||
11 | #include <linux/module.h> | ||
12 | |||
13 | #include "sigmadsp.h" | ||
14 | |||
15 | static int sigma_action_write_i2c(void *control_data, | ||
16 | const struct sigma_action *sa, size_t len) | ||
17 | { | ||
18 | return i2c_master_send(control_data, (const unsigned char *)&sa->addr, | ||
19 | len); | ||
20 | } | ||
21 | |||
22 | int process_sigma_firmware(struct i2c_client *client, const char *name) | ||
23 | { | ||
24 | struct sigma_firmware ssfw; | ||
25 | |||
26 | ssfw.control_data = client; | ||
27 | ssfw.write = sigma_action_write_i2c; | ||
28 | |||
29 | return _process_sigma_firmware(&client->dev, &ssfw, name); | ||
30 | } | ||
31 | EXPORT_SYMBOL(process_sigma_firmware); | ||
32 | |||
33 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | ||
34 | MODULE_DESCRIPTION("SigmaDSP I2C firmware loader"); | ||
35 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/sigmadsp-regmap.c b/sound/soc/codecs/sigmadsp-regmap.c new file mode 100644 index 000000000000..f78ed8d2cfb2 --- /dev/null +++ b/sound/soc/codecs/sigmadsp-regmap.c | |||
@@ -0,0 +1,36 @@ | |||
1 | /* | ||
2 | * Load Analog Devices SigmaStudio firmware files | ||
3 | * | ||
4 | * Copyright 2009-2011 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2 or later. | ||
7 | */ | ||
8 | |||
9 | #include <linux/regmap.h> | ||
10 | #include <linux/export.h> | ||
11 | #include <linux/module.h> | ||
12 | |||
13 | #include "sigmadsp.h" | ||
14 | |||
15 | static int sigma_action_write_regmap(void *control_data, | ||
16 | const struct sigma_action *sa, size_t len) | ||
17 | { | ||
18 | return regmap_raw_write(control_data, be16_to_cpu(sa->addr), | ||
19 | sa->payload, len - 2); | ||
20 | } | ||
21 | |||
22 | int process_sigma_firmware_regmap(struct device *dev, struct regmap *regmap, | ||
23 | const char *name) | ||
24 | { | ||
25 | struct sigma_firmware ssfw; | ||
26 | |||
27 | ssfw.control_data = regmap; | ||
28 | ssfw.write = sigma_action_write_regmap; | ||
29 | |||
30 | return _process_sigma_firmware(dev, &ssfw, name); | ||
31 | } | ||
32 | EXPORT_SYMBOL(process_sigma_firmware_regmap); | ||
33 | |||
34 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | ||
35 | MODULE_DESCRIPTION("SigmaDSP regmap firmware loader"); | ||
36 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/sigmadsp.c b/sound/soc/codecs/sigmadsp.c index 4068f2491232..f2de7e049bc6 100644 --- a/sound/soc/codecs/sigmadsp.c +++ b/sound/soc/codecs/sigmadsp.c | |||
@@ -34,23 +34,6 @@ enum { | |||
34 | SIGMA_ACTION_END, | 34 | SIGMA_ACTION_END, |
35 | }; | 35 | }; |
36 | 36 | ||
37 | struct sigma_action { | ||
38 | u8 instr; | ||
39 | u8 len_hi; | ||
40 | __le16 len; | ||
41 | __be16 addr; | ||
42 | unsigned char payload[]; | ||
43 | } __packed; | ||
44 | |||
45 | struct sigma_firmware { | ||
46 | const struct firmware *fw; | ||
47 | size_t pos; | ||
48 | |||
49 | void *control_data; | ||
50 | int (*write)(void *control_data, const struct sigma_action *sa, | ||
51 | size_t len); | ||
52 | }; | ||
53 | |||
54 | static inline u32 sigma_action_len(struct sigma_action *sa) | 37 | static inline u32 sigma_action_len(struct sigma_action *sa) |
55 | { | 38 | { |
56 | return (sa->len_hi << 16) | le16_to_cpu(sa->len); | 39 | return (sa->len_hi << 16) | le16_to_cpu(sa->len); |
@@ -138,7 +121,7 @@ process_sigma_actions(struct sigma_firmware *ssfw) | |||
138 | return 0; | 121 | return 0; |
139 | } | 122 | } |
140 | 123 | ||
141 | static int _process_sigma_firmware(struct device *dev, | 124 | int _process_sigma_firmware(struct device *dev, |
142 | struct sigma_firmware *ssfw, const char *name) | 125 | struct sigma_firmware *ssfw, const char *name) |
143 | { | 126 | { |
144 | int ret; | 127 | int ret; |
@@ -197,50 +180,6 @@ static int _process_sigma_firmware(struct device *dev, | |||
197 | 180 | ||
198 | return ret; | 181 | return ret; |
199 | } | 182 | } |
200 | 183 | EXPORT_SYMBOL_GPL(_process_sigma_firmware); | |
201 | #if IS_ENABLED(CONFIG_I2C) | ||
202 | |||
203 | static int sigma_action_write_i2c(void *control_data, | ||
204 | const struct sigma_action *sa, size_t len) | ||
205 | { | ||
206 | return i2c_master_send(control_data, (const unsigned char *)&sa->addr, | ||
207 | len); | ||
208 | } | ||
209 | |||
210 | int process_sigma_firmware(struct i2c_client *client, const char *name) | ||
211 | { | ||
212 | struct sigma_firmware ssfw; | ||
213 | |||
214 | ssfw.control_data = client; | ||
215 | ssfw.write = sigma_action_write_i2c; | ||
216 | |||
217 | return _process_sigma_firmware(&client->dev, &ssfw, name); | ||
218 | } | ||
219 | EXPORT_SYMBOL(process_sigma_firmware); | ||
220 | |||
221 | #endif | ||
222 | |||
223 | #if IS_ENABLED(CONFIG_REGMAP) | ||
224 | |||
225 | static int sigma_action_write_regmap(void *control_data, | ||
226 | const struct sigma_action *sa, size_t len) | ||
227 | { | ||
228 | return regmap_raw_write(control_data, be16_to_cpu(sa->addr), | ||
229 | sa->payload, len - 2); | ||
230 | } | ||
231 | |||
232 | int process_sigma_firmware_regmap(struct device *dev, struct regmap *regmap, | ||
233 | const char *name) | ||
234 | { | ||
235 | struct sigma_firmware ssfw; | ||
236 | |||
237 | ssfw.control_data = regmap; | ||
238 | ssfw.write = sigma_action_write_regmap; | ||
239 | |||
240 | return _process_sigma_firmware(dev, &ssfw, name); | ||
241 | } | ||
242 | EXPORT_SYMBOL(process_sigma_firmware_regmap); | ||
243 | |||
244 | #endif | ||
245 | 184 | ||
246 | MODULE_LICENSE("GPL"); | 185 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/codecs/sigmadsp.h b/sound/soc/codecs/sigmadsp.h index e439cbd7af7d..c47cd23e9827 100644 --- a/sound/soc/codecs/sigmadsp.h +++ b/sound/soc/codecs/sigmadsp.h | |||
@@ -12,6 +12,26 @@ | |||
12 | #include <linux/device.h> | 12 | #include <linux/device.h> |
13 | #include <linux/regmap.h> | 13 | #include <linux/regmap.h> |
14 | 14 | ||
15 | struct sigma_action { | ||
16 | u8 instr; | ||
17 | u8 len_hi; | ||
18 | __le16 len; | ||
19 | __be16 addr; | ||
20 | unsigned char payload[]; | ||
21 | } __packed; | ||
22 | |||
23 | struct sigma_firmware { | ||
24 | const struct firmware *fw; | ||
25 | size_t pos; | ||
26 | |||
27 | void *control_data; | ||
28 | int (*write)(void *control_data, const struct sigma_action *sa, | ||
29 | size_t len); | ||
30 | }; | ||
31 | |||
32 | int _process_sigma_firmware(struct device *dev, | ||
33 | struct sigma_firmware *ssfw, const char *name); | ||
34 | |||
15 | struct i2c_client; | 35 | struct i2c_client; |
16 | 36 | ||
17 | extern int process_sigma_firmware(struct i2c_client *client, const char *name); | 37 | extern int process_sigma_firmware(struct i2c_client *client, const char *name); |
diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c index b912d45a2a4c..d7a60614dd21 100644 --- a/sound/soc/fsl/fsl_spdif.c +++ b/sound/soc/fsl/fsl_spdif.c | |||
@@ -762,7 +762,7 @@ static int fsl_spdif_vbit_get(struct snd_kcontrol *kcontrol, | |||
762 | struct regmap *regmap = spdif_priv->regmap; | 762 | struct regmap *regmap = spdif_priv->regmap; |
763 | u32 val; | 763 | u32 val; |
764 | 764 | ||
765 | val = regmap_read(regmap, REG_SPDIF_SIS, &val); | 765 | regmap_read(regmap, REG_SPDIF_SIS, &val); |
766 | ucontrol->value.integer.value[0] = (val & INT_VAL_NOGOOD) != 0; | 766 | ucontrol->value.integer.value[0] = (val & INT_VAL_NOGOOD) != 0; |
767 | regmap_write(regmap, REG_SPDIF_SIC, INT_VAL_NOGOOD); | 767 | regmap_write(regmap, REG_SPDIF_SIC, INT_VAL_NOGOOD); |
768 | 768 | ||
@@ -1076,7 +1076,7 @@ static u32 fsl_spdif_txclk_caldiv(struct fsl_spdif_priv *spdif_priv, | |||
1076 | goto out; | 1076 | goto out; |
1077 | } else if (arate / rate[index] == 1) { | 1077 | } else if (arate / rate[index] == 1) { |
1078 | /* A little bigger than expect */ | 1078 | /* A little bigger than expect */ |
1079 | sub = (arate - rate[index]) * 100000; | 1079 | sub = (u64)(arate - rate[index]) * 100000; |
1080 | do_div(sub, rate[index]); | 1080 | do_div(sub, rate[index]); |
1081 | if (sub >= savesub) | 1081 | if (sub >= savesub) |
1082 | continue; | 1082 | continue; |
@@ -1086,7 +1086,7 @@ static u32 fsl_spdif_txclk_caldiv(struct fsl_spdif_priv *spdif_priv, | |||
1086 | spdif_priv->txrate[index] = arate; | 1086 | spdif_priv->txrate[index] = arate; |
1087 | } else if (rate[index] / arate == 1) { | 1087 | } else if (rate[index] / arate == 1) { |
1088 | /* A little smaller than expect */ | 1088 | /* A little smaller than expect */ |
1089 | sub = (rate[index] - arate) * 100000; | 1089 | sub = (u64)(rate[index] - arate) * 100000; |
1090 | do_div(sub, rate[index]); | 1090 | do_div(sub, rate[index]); |
1091 | if (sub >= savesub) | 1091 | if (sub >= savesub) |
1092 | continue; | 1092 | continue; |
diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c index 1f41951d8b7f..0cc41f94de4e 100644 --- a/sound/soc/omap/ams-delta.c +++ b/sound/soc/omap/ams-delta.c | |||
@@ -527,7 +527,7 @@ static int ams_delta_cx20442_init(struct snd_soc_pcm_runtime *rtd) | |||
527 | return 0; | 527 | return 0; |
528 | } | 528 | } |
529 | 529 | ||
530 | static int ams_delta_card_remove(struct snd_soc_pcm_runtime *rtd) | 530 | static int ams_delta_card_remove(struct snd_soc_card *card) |
531 | { | 531 | { |
532 | snd_soc_jack_free_gpios(&ams_delta_hook_switch, | 532 | snd_soc_jack_free_gpios(&ams_delta_hook_switch, |
533 | ARRAY_SIZE(ams_delta_hook_switch_gpios), | 533 | ARRAY_SIZE(ams_delta_hook_switch_gpios), |
diff --git a/sound/soc/omap/omap-twl4030.c b/sound/soc/omap/omap-twl4030.c index b4e282871658..f8a6adc2d81c 100644 --- a/sound/soc/omap/omap-twl4030.c +++ b/sound/soc/omap/omap-twl4030.c | |||
@@ -231,9 +231,8 @@ static int omap_twl4030_init(struct snd_soc_pcm_runtime *rtd) | |||
231 | return ret; | 231 | return ret; |
232 | } | 232 | } |
233 | 233 | ||
234 | static int omap_twl4030_card_remove(struct snd_soc_pcm_runtime *rtd) | 234 | static int omap_twl4030_card_remove(struct snd_soc_card *card) |
235 | { | 235 | { |
236 | struct snd_soc_card *card = rtd->card; | ||
237 | struct omap_twl4030 *priv = snd_soc_card_get_drvdata(card); | 236 | struct omap_twl4030 *priv = snd_soc_card_get_drvdata(card); |
238 | 237 | ||
239 | if (priv->jack_detect > 0) | 238 | if (priv->jack_detect > 0) |
diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c index 47a10290535b..943922c79f78 100644 --- a/sound/soc/omap/rx51.c +++ b/sound/soc/omap/rx51.c | |||
@@ -334,7 +334,7 @@ static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd) | |||
334 | return err; | 334 | return err; |
335 | } | 335 | } |
336 | 336 | ||
337 | static int rx51_card_remove(struct snd_soc_pcm_runtime *rtd) | 337 | static int rx51_card_remove(struct snd_soc_card *card) |
338 | { | 338 | { |
339 | snd_soc_jack_free_gpios(&rx51_av_jack, ARRAY_SIZE(rx51_av_jack_gpios), | 339 | snd_soc_jack_free_gpios(&rx51_av_jack, ARRAY_SIZE(rx51_av_jack_gpios), |
340 | rx51_av_jack_gpios); | 340 | rx51_av_jack_gpios); |
diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig index 6acb225ec6fd..2434b6d61675 100644 --- a/sound/soc/pxa/Kconfig +++ b/sound/soc/pxa/Kconfig | |||
@@ -11,6 +11,7 @@ config SND_PXA2XX_SOC | |||
11 | config SND_MMP_SOC | 11 | config SND_MMP_SOC |
12 | bool "Soc Audio for Marvell MMP chips" | 12 | bool "Soc Audio for Marvell MMP chips" |
13 | depends on ARCH_MMP | 13 | depends on ARCH_MMP |
14 | select MMP_SRAM | ||
14 | select SND_SOC_GENERIC_DMAENGINE_PCM | 15 | select SND_SOC_GENERIC_DMAENGINE_PCM |
15 | select SND_ARM | 16 | select SND_ARM |
16 | help | 17 | help |
@@ -40,7 +41,7 @@ config SND_MMP_SOC_SSPA | |||
40 | 41 | ||
41 | config SND_PXA2XX_SOC_CORGI | 42 | config SND_PXA2XX_SOC_CORGI |
42 | tristate "SoC Audio support for Sharp Zaurus SL-C7x0" | 43 | tristate "SoC Audio support for Sharp Zaurus SL-C7x0" |
43 | depends on SND_PXA2XX_SOC && PXA_SHARP_C7xx | 44 | depends on SND_PXA2XX_SOC && PXA_SHARP_C7xx && I2C |
44 | select SND_PXA2XX_SOC_I2S | 45 | select SND_PXA2XX_SOC_I2S |
45 | select SND_SOC_WM8731 | 46 | select SND_SOC_WM8731 |
46 | help | 47 | help |
@@ -49,7 +50,7 @@ config SND_PXA2XX_SOC_CORGI | |||
49 | 50 | ||
50 | config SND_PXA2XX_SOC_SPITZ | 51 | config SND_PXA2XX_SOC_SPITZ |
51 | tristate "SoC Audio support for Sharp Zaurus SL-Cxx00" | 52 | tristate "SoC Audio support for Sharp Zaurus SL-Cxx00" |
52 | depends on SND_PXA2XX_SOC && PXA_SHARP_Cxx00 | 53 | depends on SND_PXA2XX_SOC && PXA_SHARP_Cxx00 && I2C |
53 | select SND_PXA2XX_SOC_I2S | 54 | select SND_PXA2XX_SOC_I2S |
54 | select SND_SOC_WM8750 | 55 | select SND_SOC_WM8750 |
55 | help | 56 | help |
@@ -58,7 +59,7 @@ config SND_PXA2XX_SOC_SPITZ | |||
58 | 59 | ||
59 | config SND_PXA2XX_SOC_Z2 | 60 | config SND_PXA2XX_SOC_Z2 |
60 | tristate "SoC Audio support for Zipit Z2" | 61 | tristate "SoC Audio support for Zipit Z2" |
61 | depends on SND_PXA2XX_SOC && MACH_ZIPIT2 | 62 | depends on SND_PXA2XX_SOC && MACH_ZIPIT2 && I2C |
62 | select SND_PXA2XX_SOC_I2S | 63 | select SND_PXA2XX_SOC_I2S |
63 | select SND_SOC_WM8750 | 64 | select SND_SOC_WM8750 |
64 | help | 65 | help |
@@ -66,7 +67,7 @@ config SND_PXA2XX_SOC_Z2 | |||
66 | 67 | ||
67 | config SND_PXA2XX_SOC_POODLE | 68 | config SND_PXA2XX_SOC_POODLE |
68 | tristate "SoC Audio support for Poodle" | 69 | tristate "SoC Audio support for Poodle" |
69 | depends on SND_PXA2XX_SOC && MACH_POODLE | 70 | depends on SND_PXA2XX_SOC && MACH_POODLE && I2C |
70 | select SND_PXA2XX_SOC_I2S | 71 | select SND_PXA2XX_SOC_I2S |
71 | select SND_SOC_WM8731 | 72 | select SND_SOC_WM8731 |
72 | help | 73 | help |
@@ -181,7 +182,7 @@ config SND_PXA2XX_SOC_HX4700 | |||
181 | 182 | ||
182 | config SND_PXA2XX_SOC_MAGICIAN | 183 | config SND_PXA2XX_SOC_MAGICIAN |
183 | tristate "SoC Audio support for HTC Magician" | 184 | tristate "SoC Audio support for HTC Magician" |
184 | depends on SND_PXA2XX_SOC && MACH_MAGICIAN | 185 | depends on SND_PXA2XX_SOC && MACH_MAGICIAN && I2C |
185 | select SND_PXA2XX_SOC_I2S | 186 | select SND_PXA2XX_SOC_I2S |
186 | select SND_PXA_SOC_SSP | 187 | select SND_PXA_SOC_SSP |
187 | select SND_SOC_UDA1380 | 188 | select SND_SOC_UDA1380 |
diff --git a/sound/soc/pxa/hx4700.c b/sound/soc/pxa/hx4700.c index 6b81acaffddd..05559a725bec 100644 --- a/sound/soc/pxa/hx4700.c +++ b/sound/soc/pxa/hx4700.c | |||
@@ -152,7 +152,7 @@ static int hx4700_ak4641_init(struct snd_soc_pcm_runtime *rtd) | |||
152 | return err; | 152 | return err; |
153 | } | 153 | } |
154 | 154 | ||
155 | static int hx4700_card_remove(struct snd_soc_pcm_runtime *rtd) | 155 | static int hx4700_card_remove(struct snd_soc_card *card) |
156 | { | 156 | { |
157 | snd_soc_jack_free_gpios(&hs_jack, 1, &hs_jack_gpio); | 157 | snd_soc_jack_free_gpios(&hs_jack, 1, &hs_jack_gpio); |
158 | 158 | ||
diff --git a/sound/soc/samsung/h1940_uda1380.c b/sound/soc/samsung/h1940_uda1380.c index 720357f11a7f..f2d7980d7ddc 100644 --- a/sound/soc/samsung/h1940_uda1380.c +++ b/sound/soc/samsung/h1940_uda1380.c | |||
@@ -189,7 +189,7 @@ static int h1940_uda1380_init(struct snd_soc_pcm_runtime *rtd) | |||
189 | return 0; | 189 | return 0; |
190 | } | 190 | } |
191 | 191 | ||
192 | static int h1940_uda1380_card_remove(struct snd_soc_pcm_runtime *rtd) | 192 | static int h1940_uda1380_card_remove(struct snd_soc_card *card) |
193 | { | 193 | { |
194 | snd_soc_jack_free_gpios(&hp_jack, ARRAY_SIZE(hp_jack_gpios), | 194 | snd_soc_jack_free_gpios(&hp_jack, ARRAY_SIZE(hp_jack_gpios), |
195 | hp_jack_gpios); | 195 | hp_jack_gpios); |
diff --git a/sound/soc/samsung/rx1950_uda1380.c b/sound/soc/samsung/rx1950_uda1380.c index 192aa9fc102f..37688ebbb2b4 100644 --- a/sound/soc/samsung/rx1950_uda1380.c +++ b/sound/soc/samsung/rx1950_uda1380.c | |||
@@ -31,7 +31,7 @@ | |||
31 | #include "s3c24xx-i2s.h" | 31 | #include "s3c24xx-i2s.h" |
32 | 32 | ||
33 | static int rx1950_uda1380_init(struct snd_soc_pcm_runtime *rtd); | 33 | static int rx1950_uda1380_init(struct snd_soc_pcm_runtime *rtd); |
34 | static int rx1950_uda1380_card_remove(struct snd_soc_pcm_runtime *rtd); | 34 | static int rx1950_uda1380_card_remove(struct snd_soc_card *card); |
35 | static int rx1950_startup(struct snd_pcm_substream *substream); | 35 | static int rx1950_startup(struct snd_pcm_substream *substream); |
36 | static int rx1950_hw_params(struct snd_pcm_substream *substream, | 36 | static int rx1950_hw_params(struct snd_pcm_substream *substream, |
37 | struct snd_pcm_hw_params *params); | 37 | struct snd_pcm_hw_params *params); |
@@ -236,7 +236,7 @@ static int rx1950_uda1380_init(struct snd_soc_pcm_runtime *rtd) | |||
236 | return 0; | 236 | return 0; |
237 | } | 237 | } |
238 | 238 | ||
239 | static int rx1950_uda1380_card_remove(struct snd_soc_pcm_runtime *rtd) | 239 | static int rx1950_uda1380_card_remove(struct snd_soc_card *card) |
240 | { | 240 | { |
241 | snd_soc_jack_free_gpios(&hp_jack, ARRAY_SIZE(hp_jack_gpios), | 241 | snd_soc_jack_free_gpios(&hp_jack, ARRAY_SIZE(hp_jack_gpios), |
242 | hp_jack_gpios); | 242 | hp_jack_gpios); |
diff --git a/sound/soc/samsung/smartq_wm8987.c b/sound/soc/samsung/smartq_wm8987.c index 271a904277a1..9b0ffacab790 100644 --- a/sound/soc/samsung/smartq_wm8987.c +++ b/sound/soc/samsung/smartq_wm8987.c | |||
@@ -182,7 +182,7 @@ static int smartq_wm8987_init(struct snd_soc_pcm_runtime *rtd) | |||
182 | return err; | 182 | return err; |
183 | } | 183 | } |
184 | 184 | ||
185 | static int smartq_wm8987_card_remove(struct snd_soc_pcm_runtime *rtd) | 185 | static int smartq_wm8987_card_remove(struct snd_soc_card *card) |
186 | { | 186 | { |
187 | snd_soc_jack_free_gpios(&smartq_jack, ARRAY_SIZE(smartq_jack_gpios), | 187 | snd_soc_jack_free_gpios(&smartq_jack, ARRAY_SIZE(smartq_jack_gpios), |
188 | smartq_jack_gpios); | 188 | smartq_jack_gpios); |
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 91880156e1ae..4e86265f625c 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c | |||
@@ -315,7 +315,7 @@ static void rsnd_dma_of_name(struct rsnd_dma *dma, | |||
315 | dst_mod = mod[index]; | 315 | dst_mod = mod[index]; |
316 | } else { | 316 | } else { |
317 | src_mod = mod[index]; | 317 | src_mod = mod[index]; |
318 | dst_mod = mod[index + 1]; | 318 | dst_mod = mod[index - 1]; |
319 | } | 319 | } |
320 | 320 | ||
321 | index = 0; | 321 | index = 0; |
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index a74b9bf23d9f..cdc837ed144d 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c | |||
@@ -2755,7 +2755,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, | |||
2755 | unsigned int mask = (1 << fls(max)) - 1; | 2755 | unsigned int mask = (1 << fls(max)) - 1; |
2756 | unsigned int invert = mc->invert; | 2756 | unsigned int invert = mc->invert; |
2757 | unsigned int val; | 2757 | unsigned int val; |
2758 | int connect, change; | 2758 | int connect, change, reg_change = 0; |
2759 | struct snd_soc_dapm_update update; | 2759 | struct snd_soc_dapm_update update; |
2760 | int ret = 0; | 2760 | int ret = 0; |
2761 | 2761 | ||
@@ -2773,20 +2773,23 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, | |||
2773 | mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); | 2773 | mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); |
2774 | 2774 | ||
2775 | change = dapm_kcontrol_set_value(kcontrol, val); | 2775 | change = dapm_kcontrol_set_value(kcontrol, val); |
2776 | if (change) { | ||
2777 | if (reg != SND_SOC_NOPM) { | ||
2778 | mask = mask << shift; | ||
2779 | val = val << shift; | ||
2780 | |||
2781 | if (snd_soc_test_bits(codec, reg, mask, val)) { | ||
2782 | update.kcontrol = kcontrol; | ||
2783 | update.reg = reg; | ||
2784 | update.mask = mask; | ||
2785 | update.val = val; | ||
2786 | card->update = &update; | ||
2787 | } | ||
2788 | 2776 | ||
2777 | if (reg != SND_SOC_NOPM) { | ||
2778 | mask = mask << shift; | ||
2779 | val = val << shift; | ||
2780 | |||
2781 | reg_change = snd_soc_test_bits(codec, reg, mask, val); | ||
2782 | } | ||
2783 | |||
2784 | if (change || reg_change) { | ||
2785 | if (reg_change) { | ||
2786 | update.kcontrol = kcontrol; | ||
2787 | update.reg = reg; | ||
2788 | update.mask = mask; | ||
2789 | update.val = val; | ||
2790 | card->update = &update; | ||
2789 | } | 2791 | } |
2792 | change |= reg_change; | ||
2790 | 2793 | ||
2791 | ret = soc_dapm_mixer_update_power(card, kcontrol, connect); | 2794 | ret = soc_dapm_mixer_update_power(card, kcontrol, connect); |
2792 | 2795 | ||
diff --git a/sound/synth/emux/soundfont.c b/sound/synth/emux/soundfont.c index 1137b85c36e6..78683b2064f7 100644 --- a/sound/synth/emux/soundfont.c +++ b/sound/synth/emux/soundfont.c | |||
@@ -1021,6 +1021,7 @@ load_guspatch(struct snd_sf_list *sflist, const char __user *data, | |||
1021 | data, count); | 1021 | data, count); |
1022 | if (rc < 0) { | 1022 | if (rc < 0) { |
1023 | sf_sample_delete(sflist, sf, smp); | 1023 | sf_sample_delete(sflist, sf, smp); |
1024 | kfree(zone); | ||
1024 | return rc; | 1025 | return rc; |
1025 | } | 1026 | } |
1026 | /* memory offset is updated after */ | 1027 | /* memory offset is updated after */ |
diff --git a/sound/usb/Kconfig b/sound/usb/Kconfig index e05a86b7c0da..d393153c474f 100644 --- a/sound/usb/Kconfig +++ b/sound/usb/Kconfig | |||
@@ -147,5 +147,18 @@ config SND_USB_HIFACE | |||
147 | To compile this driver as a module, choose M here: the module | 147 | To compile this driver as a module, choose M here: the module |
148 | will be called snd-usb-hiface. | 148 | will be called snd-usb-hiface. |
149 | 149 | ||
150 | config SND_BCD2000 | ||
151 | tristate "Behringer BCD2000 MIDI driver" | ||
152 | select SND_RAWMIDI | ||
153 | help | ||
154 | Say Y here to include MIDI support for the Behringer BCD2000 DJ | ||
155 | controller. | ||
156 | |||
157 | Audio support is still work-in-progress at | ||
158 | https://github.com/anyc/snd-usb-bcd2000 | ||
159 | |||
160 | To compile this driver as a module, choose M here: the module | ||
161 | will be called snd-bcd2000. | ||
162 | |||
150 | endif # SND_USB | 163 | endif # SND_USB |
151 | 164 | ||
diff --git a/sound/usb/Makefile b/sound/usb/Makefile index abe668f660d1..2b92f0dcbc4c 100644 --- a/sound/usb/Makefile +++ b/sound/usb/Makefile | |||
@@ -23,4 +23,4 @@ obj-$(CONFIG_SND_USB_UA101) += snd-usbmidi-lib.o | |||
23 | obj-$(CONFIG_SND_USB_USX2Y) += snd-usbmidi-lib.o | 23 | obj-$(CONFIG_SND_USB_USX2Y) += snd-usbmidi-lib.o |
24 | obj-$(CONFIG_SND_USB_US122L) += snd-usbmidi-lib.o | 24 | obj-$(CONFIG_SND_USB_US122L) += snd-usbmidi-lib.o |
25 | 25 | ||
26 | obj-$(CONFIG_SND) += misc/ usx2y/ caiaq/ 6fire/ hiface/ | 26 | obj-$(CONFIG_SND) += misc/ usx2y/ caiaq/ 6fire/ hiface/ bcd2000/ |
diff --git a/sound/usb/bcd2000/Makefile b/sound/usb/bcd2000/Makefile new file mode 100644 index 000000000000..f09ccc0af6ff --- /dev/null +++ b/sound/usb/bcd2000/Makefile | |||
@@ -0,0 +1,3 @@ | |||
1 | snd-bcd2000-y := bcd2000.o | ||
2 | |||
3 | obj-$(CONFIG_SND_BCD2000) += snd-bcd2000.o \ No newline at end of file | ||
diff --git a/sound/usb/bcd2000/bcd2000.c b/sound/usb/bcd2000/bcd2000.c new file mode 100644 index 000000000000..820d6ca8c458 --- /dev/null +++ b/sound/usb/bcd2000/bcd2000.c | |||
@@ -0,0 +1,461 @@ | |||
1 | /* | ||
2 | * Behringer BCD2000 driver | ||
3 | * | ||
4 | * Copyright (C) 2014 Mario Kicherer (dev@kicherer.org) | ||
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 | #include <linux/kernel.h> | ||
18 | #include <linux/errno.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/module.h> | ||
22 | #include <linux/bitmap.h> | ||
23 | #include <linux/usb.h> | ||
24 | #include <linux/usb/audio.h> | ||
25 | #include <sound/core.h> | ||
26 | #include <sound/initval.h> | ||
27 | #include <sound/rawmidi.h> | ||
28 | |||
29 | #define PREFIX "snd-bcd2000: " | ||
30 | #define BUFSIZE 64 | ||
31 | |||
32 | static struct usb_device_id id_table[] = { | ||
33 | { USB_DEVICE(0x1397, 0x00bd) }, | ||
34 | { }, | ||
35 | }; | ||
36 | |||
37 | static unsigned char device_cmd_prefix[] = {0x03, 0x00}; | ||
38 | |||
39 | static unsigned char bcd2000_init_sequence[] = { | ||
40 | 0x07, 0x00, 0x00, 0x00, 0x78, 0x48, 0x1c, 0x81, | ||
41 | 0xc4, 0x00, 0x00, 0x00, 0x5e, 0x53, 0x4a, 0xf7, | ||
42 | 0x18, 0xfa, 0x11, 0xff, 0x6c, 0xf3, 0x90, 0xff, | ||
43 | 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, | ||
44 | 0x18, 0xfa, 0x11, 0xff, 0x14, 0x00, 0x00, 0x00, | ||
45 | 0x00, 0x00, 0x00, 0x00, 0xf2, 0x34, 0x4a, 0xf7, | ||
46 | 0x18, 0xfa, 0x11, 0xff | ||
47 | }; | ||
48 | |||
49 | struct bcd2000 { | ||
50 | struct usb_device *dev; | ||
51 | struct snd_card *card; | ||
52 | struct usb_interface *intf; | ||
53 | int card_index; | ||
54 | |||
55 | int midi_out_active; | ||
56 | struct snd_rawmidi *rmidi; | ||
57 | struct snd_rawmidi_substream *midi_receive_substream; | ||
58 | struct snd_rawmidi_substream *midi_out_substream; | ||
59 | |||
60 | unsigned char midi_in_buf[BUFSIZE]; | ||
61 | unsigned char midi_out_buf[BUFSIZE]; | ||
62 | |||
63 | struct urb *midi_out_urb; | ||
64 | struct urb *midi_in_urb; | ||
65 | |||
66 | struct usb_anchor anchor; | ||
67 | }; | ||
68 | |||
69 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; | ||
70 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; | ||
71 | |||
72 | static DEFINE_MUTEX(devices_mutex); | ||
73 | DECLARE_BITMAP(devices_used, SNDRV_CARDS); | ||
74 | static struct usb_driver bcd2000_driver; | ||
75 | |||
76 | #ifdef CONFIG_SND_DEBUG | ||
77 | static void bcd2000_dump_buffer(const char *prefix, const char *buf, int len) | ||
78 | { | ||
79 | print_hex_dump(KERN_DEBUG, prefix, | ||
80 | DUMP_PREFIX_NONE, 16, 1, | ||
81 | buf, len, false); | ||
82 | } | ||
83 | #else | ||
84 | static void bcd2000_dump_buffer(const char *prefix, const char *buf, int len) {} | ||
85 | #endif | ||
86 | |||
87 | static int bcd2000_midi_input_open(struct snd_rawmidi_substream *substream) | ||
88 | { | ||
89 | return 0; | ||
90 | } | ||
91 | |||
92 | static int bcd2000_midi_input_close(struct snd_rawmidi_substream *substream) | ||
93 | { | ||
94 | return 0; | ||
95 | } | ||
96 | |||
97 | /* (de)register midi substream from client */ | ||
98 | static void bcd2000_midi_input_trigger(struct snd_rawmidi_substream *substream, | ||
99 | int up) | ||
100 | { | ||
101 | struct bcd2000 *bcd2k = substream->rmidi->private_data; | ||
102 | bcd2k->midi_receive_substream = up ? substream : NULL; | ||
103 | } | ||
104 | |||
105 | static void bcd2000_midi_handle_input(struct bcd2000 *bcd2k, | ||
106 | const unsigned char *buf, unsigned int buf_len) | ||
107 | { | ||
108 | unsigned int payload_length, tocopy; | ||
109 | struct snd_rawmidi_substream *midi_receive_substream; | ||
110 | |||
111 | midi_receive_substream = ACCESS_ONCE(bcd2k->midi_receive_substream); | ||
112 | if (!midi_receive_substream) | ||
113 | return; | ||
114 | |||
115 | bcd2000_dump_buffer(PREFIX "received from device: ", buf, buf_len); | ||
116 | |||
117 | if (buf_len < 2) | ||
118 | return; | ||
119 | |||
120 | payload_length = buf[0]; | ||
121 | |||
122 | /* ignore packets without payload */ | ||
123 | if (payload_length == 0) | ||
124 | return; | ||
125 | |||
126 | tocopy = min(payload_length, buf_len-1); | ||
127 | |||
128 | bcd2000_dump_buffer(PREFIX "sending to userspace: ", | ||
129 | &buf[1], tocopy); | ||
130 | |||
131 | snd_rawmidi_receive(midi_receive_substream, | ||
132 | &buf[1], tocopy); | ||
133 | } | ||
134 | |||
135 | static void bcd2000_midi_send(struct bcd2000 *bcd2k) | ||
136 | { | ||
137 | int len, ret; | ||
138 | struct snd_rawmidi_substream *midi_out_substream; | ||
139 | |||
140 | BUILD_BUG_ON(sizeof(device_cmd_prefix) >= BUFSIZE); | ||
141 | |||
142 | midi_out_substream = ACCESS_ONCE(bcd2k->midi_out_substream); | ||
143 | if (!midi_out_substream) | ||
144 | return; | ||
145 | |||
146 | /* copy command prefix bytes */ | ||
147 | memcpy(bcd2k->midi_out_buf, device_cmd_prefix, | ||
148 | sizeof(device_cmd_prefix)); | ||
149 | |||
150 | /* | ||
151 | * get MIDI packet and leave space for command prefix | ||
152 | * and payload length | ||
153 | */ | ||
154 | len = snd_rawmidi_transmit(midi_out_substream, | ||
155 | bcd2k->midi_out_buf + 3, BUFSIZE - 3); | ||
156 | |||
157 | if (len < 0) | ||
158 | dev_err(&bcd2k->dev->dev, "%s: snd_rawmidi_transmit error %d\n", | ||
159 | __func__, len); | ||
160 | |||
161 | if (len <= 0) | ||
162 | return; | ||
163 | |||
164 | /* set payload length */ | ||
165 | bcd2k->midi_out_buf[2] = len; | ||
166 | bcd2k->midi_out_urb->transfer_buffer_length = BUFSIZE; | ||
167 | |||
168 | bcd2000_dump_buffer(PREFIX "sending to device: ", | ||
169 | bcd2k->midi_out_buf, len+3); | ||
170 | |||
171 | /* send packet to the BCD2000 */ | ||
172 | ret = usb_submit_urb(bcd2k->midi_out_urb, GFP_ATOMIC); | ||
173 | if (ret < 0) | ||
174 | dev_err(&bcd2k->dev->dev, PREFIX | ||
175 | "%s (%p): usb_submit_urb() failed, ret=%d, len=%d\n", | ||
176 | __func__, midi_out_substream, ret, len); | ||
177 | else | ||
178 | bcd2k->midi_out_active = 1; | ||
179 | } | ||
180 | |||
181 | static int bcd2000_midi_output_open(struct snd_rawmidi_substream *substream) | ||
182 | { | ||
183 | return 0; | ||
184 | } | ||
185 | |||
186 | static int bcd2000_midi_output_close(struct snd_rawmidi_substream *substream) | ||
187 | { | ||
188 | struct bcd2000 *bcd2k = substream->rmidi->private_data; | ||
189 | |||
190 | if (bcd2k->midi_out_active) { | ||
191 | usb_kill_urb(bcd2k->midi_out_urb); | ||
192 | bcd2k->midi_out_active = 0; | ||
193 | } | ||
194 | |||
195 | return 0; | ||
196 | } | ||
197 | |||
198 | /* (de)register midi substream from client */ | ||
199 | static void bcd2000_midi_output_trigger(struct snd_rawmidi_substream *substream, | ||
200 | int up) | ||
201 | { | ||
202 | struct bcd2000 *bcd2k = substream->rmidi->private_data; | ||
203 | |||
204 | if (up) { | ||
205 | bcd2k->midi_out_substream = substream; | ||
206 | /* check if there is data userspace wants to send */ | ||
207 | if (!bcd2k->midi_out_active) | ||
208 | bcd2000_midi_send(bcd2k); | ||
209 | } else { | ||
210 | bcd2k->midi_out_substream = NULL; | ||
211 | } | ||
212 | } | ||
213 | |||
214 | static void bcd2000_output_complete(struct urb *urb) | ||
215 | { | ||
216 | struct bcd2000 *bcd2k = urb->context; | ||
217 | |||
218 | bcd2k->midi_out_active = 0; | ||
219 | |||
220 | if (urb->status) | ||
221 | dev_warn(&urb->dev->dev, | ||
222 | PREFIX "output urb->status: %d\n", urb->status); | ||
223 | |||
224 | if (urb->status == -ESHUTDOWN) | ||
225 | return; | ||
226 | |||
227 | /* check if there is more data userspace wants to send */ | ||
228 | bcd2000_midi_send(bcd2k); | ||
229 | } | ||
230 | |||
231 | static void bcd2000_input_complete(struct urb *urb) | ||
232 | { | ||
233 | int ret; | ||
234 | struct bcd2000 *bcd2k = urb->context; | ||
235 | |||
236 | if (urb->status) | ||
237 | dev_warn(&urb->dev->dev, | ||
238 | PREFIX "input urb->status: %i\n", urb->status); | ||
239 | |||
240 | if (!bcd2k || urb->status == -ESHUTDOWN) | ||
241 | return; | ||
242 | |||
243 | if (urb->actual_length > 0) | ||
244 | bcd2000_midi_handle_input(bcd2k, urb->transfer_buffer, | ||
245 | urb->actual_length); | ||
246 | |||
247 | /* return URB to device */ | ||
248 | ret = usb_submit_urb(bcd2k->midi_in_urb, GFP_ATOMIC); | ||
249 | if (ret < 0) | ||
250 | dev_err(&bcd2k->dev->dev, PREFIX | ||
251 | "%s: usb_submit_urb() failed, ret=%d\n", | ||
252 | __func__, ret); | ||
253 | } | ||
254 | |||
255 | static struct snd_rawmidi_ops bcd2000_midi_output = { | ||
256 | .open = bcd2000_midi_output_open, | ||
257 | .close = bcd2000_midi_output_close, | ||
258 | .trigger = bcd2000_midi_output_trigger, | ||
259 | }; | ||
260 | |||
261 | static struct snd_rawmidi_ops bcd2000_midi_input = { | ||
262 | .open = bcd2000_midi_input_open, | ||
263 | .close = bcd2000_midi_input_close, | ||
264 | .trigger = bcd2000_midi_input_trigger, | ||
265 | }; | ||
266 | |||
267 | static void bcd2000_init_device(struct bcd2000 *bcd2k) | ||
268 | { | ||
269 | int ret; | ||
270 | |||
271 | init_usb_anchor(&bcd2k->anchor); | ||
272 | usb_anchor_urb(bcd2k->midi_out_urb, &bcd2k->anchor); | ||
273 | usb_anchor_urb(bcd2k->midi_in_urb, &bcd2k->anchor); | ||
274 | |||
275 | /* copy init sequence into buffer */ | ||
276 | memcpy(bcd2k->midi_out_buf, bcd2000_init_sequence, 52); | ||
277 | bcd2k->midi_out_urb->transfer_buffer_length = 52; | ||
278 | |||
279 | /* submit sequence */ | ||
280 | ret = usb_submit_urb(bcd2k->midi_out_urb, GFP_KERNEL); | ||
281 | if (ret < 0) | ||
282 | dev_err(&bcd2k->dev->dev, PREFIX | ||
283 | "%s: usb_submit_urb() out failed, ret=%d: ", | ||
284 | __func__, ret); | ||
285 | else | ||
286 | bcd2k->midi_out_active = 1; | ||
287 | |||
288 | /* pass URB to device to enable button and controller events */ | ||
289 | ret = usb_submit_urb(bcd2k->midi_in_urb, GFP_KERNEL); | ||
290 | if (ret < 0) | ||
291 | dev_err(&bcd2k->dev->dev, PREFIX | ||
292 | "%s: usb_submit_urb() in failed, ret=%d: ", | ||
293 | __func__, ret); | ||
294 | |||
295 | /* ensure initialization is finished */ | ||
296 | usb_wait_anchor_empty_timeout(&bcd2k->anchor, 1000); | ||
297 | } | ||
298 | |||
299 | static int bcd2000_init_midi(struct bcd2000 *bcd2k) | ||
300 | { | ||
301 | int ret; | ||
302 | struct snd_rawmidi *rmidi; | ||
303 | |||
304 | ret = snd_rawmidi_new(bcd2k->card, bcd2k->card->shortname, 0, | ||
305 | 1, /* output */ | ||
306 | 1, /* input */ | ||
307 | &rmidi); | ||
308 | |||
309 | if (ret < 0) | ||
310 | return ret; | ||
311 | |||
312 | strlcpy(rmidi->name, bcd2k->card->shortname, sizeof(rmidi->name)); | ||
313 | |||
314 | rmidi->info_flags = SNDRV_RAWMIDI_INFO_DUPLEX; | ||
315 | rmidi->private_data = bcd2k; | ||
316 | |||
317 | rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT; | ||
318 | snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, | ||
319 | &bcd2000_midi_output); | ||
320 | |||
321 | rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT; | ||
322 | snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, | ||
323 | &bcd2000_midi_input); | ||
324 | |||
325 | bcd2k->rmidi = rmidi; | ||
326 | |||
327 | bcd2k->midi_in_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
328 | bcd2k->midi_out_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
329 | |||
330 | if (!bcd2k->midi_in_urb || !bcd2k->midi_out_urb) { | ||
331 | dev_err(&bcd2k->dev->dev, PREFIX "usb_alloc_urb failed\n"); | ||
332 | return -ENOMEM; | ||
333 | } | ||
334 | |||
335 | usb_fill_int_urb(bcd2k->midi_in_urb, bcd2k->dev, | ||
336 | usb_rcvintpipe(bcd2k->dev, 0x81), | ||
337 | bcd2k->midi_in_buf, BUFSIZE, | ||
338 | bcd2000_input_complete, bcd2k, 1); | ||
339 | |||
340 | usb_fill_int_urb(bcd2k->midi_out_urb, bcd2k->dev, | ||
341 | usb_sndintpipe(bcd2k->dev, 0x1), | ||
342 | bcd2k->midi_out_buf, BUFSIZE, | ||
343 | bcd2000_output_complete, bcd2k, 1); | ||
344 | |||
345 | bcd2000_init_device(bcd2k); | ||
346 | |||
347 | return 0; | ||
348 | } | ||
349 | |||
350 | static void bcd2000_free_usb_related_resources(struct bcd2000 *bcd2k, | ||
351 | struct usb_interface *interface) | ||
352 | { | ||
353 | /* usb_kill_urb not necessary, urb is aborted automatically */ | ||
354 | |||
355 | usb_free_urb(bcd2k->midi_out_urb); | ||
356 | usb_free_urb(bcd2k->midi_in_urb); | ||
357 | |||
358 | if (bcd2k->intf) { | ||
359 | usb_set_intfdata(bcd2k->intf, NULL); | ||
360 | bcd2k->intf = NULL; | ||
361 | } | ||
362 | } | ||
363 | |||
364 | static int bcd2000_probe(struct usb_interface *interface, | ||
365 | const struct usb_device_id *usb_id) | ||
366 | { | ||
367 | struct snd_card *card; | ||
368 | struct bcd2000 *bcd2k; | ||
369 | unsigned int card_index; | ||
370 | char usb_path[32]; | ||
371 | int err; | ||
372 | |||
373 | mutex_lock(&devices_mutex); | ||
374 | |||
375 | for (card_index = 0; card_index < SNDRV_CARDS; ++card_index) | ||
376 | if (!test_bit(card_index, devices_used)) | ||
377 | break; | ||
378 | |||
379 | if (card_index >= SNDRV_CARDS) { | ||
380 | mutex_unlock(&devices_mutex); | ||
381 | return -ENOENT; | ||
382 | } | ||
383 | |||
384 | err = snd_card_new(&interface->dev, index[card_index], id[card_index], | ||
385 | THIS_MODULE, sizeof(*bcd2k), &card); | ||
386 | if (err < 0) { | ||
387 | mutex_unlock(&devices_mutex); | ||
388 | return err; | ||
389 | } | ||
390 | |||
391 | bcd2k = card->private_data; | ||
392 | bcd2k->dev = interface_to_usbdev(interface); | ||
393 | bcd2k->card = card; | ||
394 | bcd2k->card_index = card_index; | ||
395 | bcd2k->intf = interface; | ||
396 | |||
397 | snd_card_set_dev(card, &interface->dev); | ||
398 | |||
399 | strncpy(card->driver, "snd-bcd2000", sizeof(card->driver)); | ||
400 | strncpy(card->shortname, "BCD2000", sizeof(card->shortname)); | ||
401 | usb_make_path(bcd2k->dev, usb_path, sizeof(usb_path)); | ||
402 | snprintf(bcd2k->card->longname, sizeof(bcd2k->card->longname), | ||
403 | "Behringer BCD2000 at %s", | ||
404 | usb_path); | ||
405 | |||
406 | err = bcd2000_init_midi(bcd2k); | ||
407 | if (err < 0) | ||
408 | goto probe_error; | ||
409 | |||
410 | err = snd_card_register(card); | ||
411 | if (err < 0) | ||
412 | goto probe_error; | ||
413 | |||
414 | usb_set_intfdata(interface, bcd2k); | ||
415 | set_bit(card_index, devices_used); | ||
416 | |||
417 | mutex_unlock(&devices_mutex); | ||
418 | return 0; | ||
419 | |||
420 | probe_error: | ||
421 | dev_info(&bcd2k->dev->dev, PREFIX "error during probing"); | ||
422 | bcd2000_free_usb_related_resources(bcd2k, interface); | ||
423 | snd_card_free(card); | ||
424 | mutex_unlock(&devices_mutex); | ||
425 | return err; | ||
426 | } | ||
427 | |||
428 | static void bcd2000_disconnect(struct usb_interface *interface) | ||
429 | { | ||
430 | struct bcd2000 *bcd2k = usb_get_intfdata(interface); | ||
431 | |||
432 | if (!bcd2k) | ||
433 | return; | ||
434 | |||
435 | mutex_lock(&devices_mutex); | ||
436 | |||
437 | /* make sure that userspace cannot create new requests */ | ||
438 | snd_card_disconnect(bcd2k->card); | ||
439 | |||
440 | bcd2000_free_usb_related_resources(bcd2k, interface); | ||
441 | |||
442 | clear_bit(bcd2k->card_index, devices_used); | ||
443 | |||
444 | snd_card_free_when_closed(bcd2k->card); | ||
445 | |||
446 | mutex_unlock(&devices_mutex); | ||
447 | } | ||
448 | |||
449 | static struct usb_driver bcd2000_driver = { | ||
450 | .name = "snd-bcd2000", | ||
451 | .probe = bcd2000_probe, | ||
452 | .disconnect = bcd2000_disconnect, | ||
453 | .id_table = id_table, | ||
454 | }; | ||
455 | |||
456 | module_usb_driver(bcd2000_driver); | ||
457 | |||
458 | MODULE_DEVICE_TABLE(usb, id_table); | ||
459 | MODULE_AUTHOR("Mario Kicherer, dev@kicherer.org"); | ||
460 | MODULE_DESCRIPTION("Behringer BCD2000 driver"); | ||
461 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index d40a2850e270..0b728d886f0d 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c | |||
@@ -162,7 +162,7 @@ static int check_mapped_selector_name(struct mixer_build *state, int unitid, | |||
162 | { | 162 | { |
163 | const struct usbmix_selector_map *p; | 163 | const struct usbmix_selector_map *p; |
164 | 164 | ||
165 | if (! state->selector_map) | 165 | if (!state->selector_map) |
166 | return 0; | 166 | return 0; |
167 | for (p = state->selector_map; p->id; p++) { | 167 | for (p = state->selector_map; p->id; p++) { |
168 | if (p->id == unitid && index < p->count) | 168 | if (p->id == unitid && index < p->count) |
@@ -174,7 +174,8 @@ static int check_mapped_selector_name(struct mixer_build *state, int unitid, | |||
174 | /* | 174 | /* |
175 | * find an audio control unit with the given unit id | 175 | * find an audio control unit with the given unit id |
176 | */ | 176 | */ |
177 | static void *find_audio_control_unit(struct mixer_build *state, unsigned char unit) | 177 | static void *find_audio_control_unit(struct mixer_build *state, |
178 | unsigned char unit) | ||
178 | { | 179 | { |
179 | /* we just parse the header */ | 180 | /* we just parse the header */ |
180 | struct uac_feature_unit_descriptor *hdr = NULL; | 181 | struct uac_feature_unit_descriptor *hdr = NULL; |
@@ -194,7 +195,8 @@ static void *find_audio_control_unit(struct mixer_build *state, unsigned char un | |||
194 | /* | 195 | /* |
195 | * copy a string with the given id | 196 | * copy a string with the given id |
196 | */ | 197 | */ |
197 | static int snd_usb_copy_string_desc(struct mixer_build *state, int index, char *buf, int maxlen) | 198 | static int snd_usb_copy_string_desc(struct mixer_build *state, |
199 | int index, char *buf, int maxlen) | ||
198 | { | 200 | { |
199 | int len = usb_string(state->chip->dev, index, buf, maxlen - 1); | 201 | int len = usb_string(state->chip->dev, index, buf, maxlen - 1); |
200 | buf[len] = 0; | 202 | buf[len] = 0; |
@@ -253,7 +255,7 @@ static int convert_bytes_value(struct usb_mixer_elem_info *cval, int val) | |||
253 | 255 | ||
254 | static int get_relative_value(struct usb_mixer_elem_info *cval, int val) | 256 | static int get_relative_value(struct usb_mixer_elem_info *cval, int val) |
255 | { | 257 | { |
256 | if (! cval->res) | 258 | if (!cval->res) |
257 | cval->res = 1; | 259 | cval->res = 1; |
258 | if (val < cval->min) | 260 | if (val < cval->min) |
259 | return 0; | 261 | return 0; |
@@ -267,7 +269,7 @@ static int get_abs_value(struct usb_mixer_elem_info *cval, int val) | |||
267 | { | 269 | { |
268 | if (val < 0) | 270 | if (val < 0) |
269 | return cval->min; | 271 | return cval->min; |
270 | if (! cval->res) | 272 | if (!cval->res) |
271 | cval->res = 1; | 273 | cval->res = 1; |
272 | val *= cval->res; | 274 | val *= cval->res; |
273 | val += cval->min; | 275 | val += cval->min; |
@@ -281,7 +283,8 @@ static int get_abs_value(struct usb_mixer_elem_info *cval, int val) | |||
281 | * retrieve a mixer value | 283 | * retrieve a mixer value |
282 | */ | 284 | */ |
283 | 285 | ||
284 | static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret) | 286 | static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, |
287 | int validx, int *value_ret) | ||
285 | { | 288 | { |
286 | struct snd_usb_audio *chip = cval->mixer->chip; | 289 | struct snd_usb_audio *chip = cval->mixer->chip; |
287 | unsigned char buf[2]; | 290 | unsigned char buf[2]; |
@@ -292,6 +295,7 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int v | |||
292 | err = snd_usb_autoresume(cval->mixer->chip); | 295 | err = snd_usb_autoresume(cval->mixer->chip); |
293 | if (err < 0) | 296 | if (err < 0) |
294 | return -EIO; | 297 | return -EIO; |
298 | |||
295 | down_read(&chip->shutdown_rwsem); | 299 | down_read(&chip->shutdown_rwsem); |
296 | while (timeout-- > 0) { | 300 | while (timeout-- > 0) { |
297 | if (chip->shutdown) | 301 | if (chip->shutdown) |
@@ -316,10 +320,11 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int v | |||
316 | return err; | 320 | return err; |
317 | } | 321 | } |
318 | 322 | ||
319 | static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret) | 323 | static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, |
324 | int validx, int *value_ret) | ||
320 | { | 325 | { |
321 | struct snd_usb_audio *chip = cval->mixer->chip; | 326 | struct snd_usb_audio *chip = cval->mixer->chip; |
322 | unsigned char buf[2 + 3*sizeof(__u16)]; /* enough space for one range */ | 327 | unsigned char buf[2 + 3 * sizeof(__u16)]; /* enough space for one range */ |
323 | unsigned char *val; | 328 | unsigned char *val; |
324 | int idx = 0, ret, size; | 329 | int idx = 0, ret, size; |
325 | __u8 bRequest; | 330 | __u8 bRequest; |
@@ -339,9 +344,9 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v | |||
339 | goto error; | 344 | goto error; |
340 | 345 | ||
341 | down_read(&chip->shutdown_rwsem); | 346 | down_read(&chip->shutdown_rwsem); |
342 | if (chip->shutdown) | 347 | if (chip->shutdown) { |
343 | ret = -ENODEV; | 348 | ret = -ENODEV; |
344 | else { | 349 | } else { |
345 | idx = snd_usb_ctrl_intf(chip) | (cval->id << 8); | 350 | idx = snd_usb_ctrl_intf(chip) | (cval->id << 8); |
346 | ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest, | 351 | ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest, |
347 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, | 352 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, |
@@ -382,7 +387,8 @@ error: | |||
382 | return 0; | 387 | return 0; |
383 | } | 388 | } |
384 | 389 | ||
385 | static int get_ctl_value(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret) | 390 | static int get_ctl_value(struct usb_mixer_elem_info *cval, int request, |
391 | int validx, int *value_ret) | ||
386 | { | 392 | { |
387 | validx += cval->idx_off; | 393 | validx += cval->idx_off; |
388 | 394 | ||
@@ -391,7 +397,8 @@ static int get_ctl_value(struct usb_mixer_elem_info *cval, int request, int vali | |||
391 | get_ctl_value_v2(cval, request, validx, value_ret); | 397 | get_ctl_value_v2(cval, request, validx, value_ret); |
392 | } | 398 | } |
393 | 399 | ||
394 | static int get_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int *value) | 400 | static int get_cur_ctl_value(struct usb_mixer_elem_info *cval, |
401 | int validx, int *value) | ||
395 | { | 402 | { |
396 | return get_ctl_value(cval, UAC_GET_CUR, validx, value); | 403 | return get_ctl_value(cval, UAC_GET_CUR, validx, value); |
397 | } | 404 | } |
@@ -400,7 +407,9 @@ static int get_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int * | |||
400 | static inline int get_cur_mix_raw(struct usb_mixer_elem_info *cval, | 407 | static inline int get_cur_mix_raw(struct usb_mixer_elem_info *cval, |
401 | int channel, int *value) | 408 | int channel, int *value) |
402 | { | 409 | { |
403 | return get_ctl_value(cval, UAC_GET_CUR, (cval->control << 8) | channel, value); | 410 | return get_ctl_value(cval, UAC_GET_CUR, |
411 | (cval->control << 8) | channel, | ||
412 | value); | ||
404 | } | 413 | } |
405 | 414 | ||
406 | static int get_cur_mix_value(struct usb_mixer_elem_info *cval, | 415 | static int get_cur_mix_value(struct usb_mixer_elem_info *cval, |
@@ -417,7 +426,7 @@ static int get_cur_mix_value(struct usb_mixer_elem_info *cval, | |||
417 | if (!cval->mixer->ignore_ctl_error) | 426 | if (!cval->mixer->ignore_ctl_error) |
418 | usb_audio_dbg(cval->mixer->chip, | 427 | usb_audio_dbg(cval->mixer->chip, |
419 | "cannot get current value for control %d ch %d: err = %d\n", | 428 | "cannot get current value for control %d ch %d: err = %d\n", |
420 | cval->control, channel, err); | 429 | cval->control, channel, err); |
421 | return err; | 430 | return err; |
422 | } | 431 | } |
423 | cval->cached |= 1 << channel; | 432 | cval->cached |= 1 << channel; |
@@ -425,7 +434,6 @@ static int get_cur_mix_value(struct usb_mixer_elem_info *cval, | |||
425 | return 0; | 434 | return 0; |
426 | } | 435 | } |
427 | 436 | ||
428 | |||
429 | /* | 437 | /* |
430 | * set a mixer value | 438 | * set a mixer value |
431 | */ | 439 | */ |
@@ -474,7 +482,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, | |||
474 | } | 482 | } |
475 | } | 483 | } |
476 | usb_audio_dbg(chip, "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n", | 484 | usb_audio_dbg(chip, "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n", |
477 | request, validx, idx, cval->val_type, buf[0], buf[1]); | 485 | request, validx, idx, cval->val_type, buf[0], buf[1]); |
478 | err = -EINVAL; | 486 | err = -EINVAL; |
479 | 487 | ||
480 | out: | 488 | out: |
@@ -483,7 +491,8 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, | |||
483 | return err; | 491 | return err; |
484 | } | 492 | } |
485 | 493 | ||
486 | static int set_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int value) | 494 | static int set_cur_ctl_value(struct usb_mixer_elem_info *cval, |
495 | int validx, int value) | ||
487 | { | 496 | { |
488 | return snd_usb_mixer_set_ctl_value(cval, UAC_SET_CUR, validx, value); | 497 | return snd_usb_mixer_set_ctl_value(cval, UAC_SET_CUR, validx, value); |
489 | } | 498 | } |
@@ -503,8 +512,9 @@ static int set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, | |||
503 | return 0; | 512 | return 0; |
504 | } | 513 | } |
505 | 514 | ||
506 | err = snd_usb_mixer_set_ctl_value(cval, UAC_SET_CUR, (cval->control << 8) | channel, | 515 | err = snd_usb_mixer_set_ctl_value(cval, |
507 | value); | 516 | UAC_SET_CUR, (cval->control << 8) | channel, |
517 | value); | ||
508 | if (err < 0) | 518 | if (err < 0) |
509 | return err; | 519 | return err; |
510 | cval->cached |= 1 << channel; | 520 | cval->cached |= 1 << channel; |
@@ -541,13 +551,13 @@ static int parse_audio_unit(struct mixer_build *state, int unitid); | |||
541 | * check if the input/output channel routing is enabled on the given bitmap. | 551 | * check if the input/output channel routing is enabled on the given bitmap. |
542 | * used for mixer unit parser | 552 | * used for mixer unit parser |
543 | */ | 553 | */ |
544 | static int check_matrix_bitmap(unsigned char *bmap, int ich, int och, int num_outs) | 554 | static int check_matrix_bitmap(unsigned char *bmap, |
555 | int ich, int och, int num_outs) | ||
545 | { | 556 | { |
546 | int idx = ich * num_outs + och; | 557 | int idx = ich * num_outs + och; |
547 | return bmap[idx >> 3] & (0x80 >> (idx & 7)); | 558 | return bmap[idx >> 3] & (0x80 >> (idx & 7)); |
548 | } | 559 | } |
549 | 560 | ||
550 | |||
551 | /* | 561 | /* |
552 | * add an alsa control element | 562 | * add an alsa control element |
553 | * search and increment the index until an empty slot is found. | 563 | * search and increment the index until an empty slot is found. |
@@ -564,7 +574,8 @@ int snd_usb_mixer_add_control(struct usb_mixer_interface *mixer, | |||
564 | while (snd_ctl_find_id(mixer->chip->card, &kctl->id)) | 574 | while (snd_ctl_find_id(mixer->chip->card, &kctl->id)) |
565 | kctl->id.index++; | 575 | kctl->id.index++; |
566 | if ((err = snd_ctl_add(mixer->chip->card, kctl)) < 0) { | 576 | if ((err = snd_ctl_add(mixer->chip->card, kctl)) < 0) { |
567 | usb_audio_dbg(mixer->chip, "cannot add control (err = %d)\n", err); | 577 | usb_audio_dbg(mixer->chip, "cannot add control (err = %d)\n", |
578 | err); | ||
568 | return err; | 579 | return err; |
569 | } | 580 | } |
570 | cval->elem_id = &kctl->id; | 581 | cval->elem_id = &kctl->id; |
@@ -573,7 +584,6 @@ int snd_usb_mixer_add_control(struct usb_mixer_interface *mixer, | |||
573 | return 0; | 584 | return 0; |
574 | } | 585 | } |
575 | 586 | ||
576 | |||
577 | /* | 587 | /* |
578 | * get a terminal name string | 588 | * get a terminal name string |
579 | */ | 589 | */ |
@@ -627,7 +637,8 @@ static int get_term_name(struct mixer_build *state, struct usb_audio_term *iterm | |||
627 | struct iterm_name_combo *names; | 637 | struct iterm_name_combo *names; |
628 | 638 | ||
629 | if (iterm->name) | 639 | if (iterm->name) |
630 | return snd_usb_copy_string_desc(state, iterm->name, name, maxlen); | 640 | return snd_usb_copy_string_desc(state, iterm->name, |
641 | name, maxlen); | ||
631 | 642 | ||
632 | /* virtual type - not a real terminal */ | 643 | /* virtual type - not a real terminal */ |
633 | if (iterm->type >> 16) { | 644 | if (iterm->type >> 16) { |
@@ -635,13 +646,17 @@ static int get_term_name(struct mixer_build *state, struct usb_audio_term *iterm | |||
635 | return 0; | 646 | return 0; |
636 | switch (iterm->type >> 16) { | 647 | switch (iterm->type >> 16) { |
637 | case UAC_SELECTOR_UNIT: | 648 | case UAC_SELECTOR_UNIT: |
638 | strcpy(name, "Selector"); return 8; | 649 | strcpy(name, "Selector"); |
650 | return 8; | ||
639 | case UAC1_PROCESSING_UNIT: | 651 | case UAC1_PROCESSING_UNIT: |
640 | strcpy(name, "Process Unit"); return 12; | 652 | strcpy(name, "Process Unit"); |
653 | return 12; | ||
641 | case UAC1_EXTENSION_UNIT: | 654 | case UAC1_EXTENSION_UNIT: |
642 | strcpy(name, "Ext Unit"); return 8; | 655 | strcpy(name, "Ext Unit"); |
656 | return 8; | ||
643 | case UAC_MIXER_UNIT: | 657 | case UAC_MIXER_UNIT: |
644 | strcpy(name, "Mixer"); return 5; | 658 | strcpy(name, "Mixer"); |
659 | return 5; | ||
645 | default: | 660 | default: |
646 | return sprintf(name, "Unit %d", iterm->id); | 661 | return sprintf(name, "Unit %d", iterm->id); |
647 | } | 662 | } |
@@ -649,29 +664,35 @@ static int get_term_name(struct mixer_build *state, struct usb_audio_term *iterm | |||
649 | 664 | ||
650 | switch (iterm->type & 0xff00) { | 665 | switch (iterm->type & 0xff00) { |
651 | case 0x0100: | 666 | case 0x0100: |
652 | strcpy(name, "PCM"); return 3; | 667 | strcpy(name, "PCM"); |
668 | return 3; | ||
653 | case 0x0200: | 669 | case 0x0200: |
654 | strcpy(name, "Mic"); return 3; | 670 | strcpy(name, "Mic"); |
671 | return 3; | ||
655 | case 0x0400: | 672 | case 0x0400: |
656 | strcpy(name, "Headset"); return 7; | 673 | strcpy(name, "Headset"); |
674 | return 7; | ||
657 | case 0x0500: | 675 | case 0x0500: |
658 | strcpy(name, "Phone"); return 5; | 676 | strcpy(name, "Phone"); |
677 | return 5; | ||
659 | } | 678 | } |
660 | 679 | ||
661 | for (names = iterm_names; names->type; names++) | 680 | for (names = iterm_names; names->type; names++) { |
662 | if (names->type == iterm->type) { | 681 | if (names->type == iterm->type) { |
663 | strcpy(name, names->name); | 682 | strcpy(name, names->name); |
664 | return strlen(names->name); | 683 | return strlen(names->name); |
665 | } | 684 | } |
685 | } | ||
686 | |||
666 | return 0; | 687 | return 0; |
667 | } | 688 | } |
668 | 689 | ||
669 | |||
670 | /* | 690 | /* |
671 | * parse the source unit recursively until it reaches to a terminal | 691 | * parse the source unit recursively until it reaches to a terminal |
672 | * or a branched unit. | 692 | * or a branched unit. |
673 | */ | 693 | */ |
674 | static int check_input_term(struct mixer_build *state, int id, struct usb_audio_term *term) | 694 | static int check_input_term(struct mixer_build *state, int id, |
695 | struct usb_audio_term *term) | ||
675 | { | 696 | { |
676 | int err; | 697 | int err; |
677 | void *p1; | 698 | void *p1; |
@@ -766,7 +787,6 @@ static int check_input_term(struct mixer_build *state, int id, struct usb_audio_ | |||
766 | return -ENODEV; | 787 | return -ENODEV; |
767 | } | 788 | } |
768 | 789 | ||
769 | |||
770 | /* | 790 | /* |
771 | * Feature Unit | 791 | * Feature Unit |
772 | */ | 792 | */ |
@@ -794,7 +814,6 @@ static struct usb_feature_control_info audio_feature_info[] = { | |||
794 | { "Phase Inverter Control", USB_MIXER_BOOLEAN }, | 814 | { "Phase Inverter Control", USB_MIXER_BOOLEAN }, |
795 | }; | 815 | }; |
796 | 816 | ||
797 | |||
798 | /* private_free callback */ | 817 | /* private_free callback */ |
799 | static void usb_mixer_elem_free(struct snd_kcontrol *kctl) | 818 | static void usb_mixer_elem_free(struct snd_kcontrol *kctl) |
800 | { | 819 | { |
@@ -802,7 +821,6 @@ static void usb_mixer_elem_free(struct snd_kcontrol *kctl) | |||
802 | kctl->private_data = NULL; | 821 | kctl->private_data = NULL; |
803 | } | 822 | } |
804 | 823 | ||
805 | |||
806 | /* | 824 | /* |
807 | * interface to ALSA control for feature/mixer units | 825 | * interface to ALSA control for feature/mixer units |
808 | */ | 826 | */ |
@@ -906,7 +924,6 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval, | |||
906 | cval->res = 384; | 924 | cval->res = 384; |
907 | } | 925 | } |
908 | break; | 926 | break; |
909 | |||
910 | } | 927 | } |
911 | } | 928 | } |
912 | 929 | ||
@@ -939,21 +956,26 @@ static int get_min_max_with_quirks(struct usb_mixer_elem_info *cval, | |||
939 | get_ctl_value(cval, UAC_GET_MIN, (cval->control << 8) | minchn, &cval->min) < 0) { | 956 | get_ctl_value(cval, UAC_GET_MIN, (cval->control << 8) | minchn, &cval->min) < 0) { |
940 | usb_audio_err(cval->mixer->chip, | 957 | usb_audio_err(cval->mixer->chip, |
941 | "%d:%d: cannot get min/max values for control %d (id %d)\n", | 958 | "%d:%d: cannot get min/max values for control %d (id %d)\n", |
942 | cval->id, snd_usb_ctrl_intf(cval->mixer->chip), cval->control, cval->id); | 959 | cval->id, snd_usb_ctrl_intf(cval->mixer->chip), |
960 | cval->control, cval->id); | ||
943 | return -EINVAL; | 961 | return -EINVAL; |
944 | } | 962 | } |
945 | if (get_ctl_value(cval, UAC_GET_RES, (cval->control << 8) | minchn, &cval->res) < 0) { | 963 | if (get_ctl_value(cval, UAC_GET_RES, |
964 | (cval->control << 8) | minchn, | ||
965 | &cval->res) < 0) { | ||
946 | cval->res = 1; | 966 | cval->res = 1; |
947 | } else { | 967 | } else { |
948 | int last_valid_res = cval->res; | 968 | int last_valid_res = cval->res; |
949 | 969 | ||
950 | while (cval->res > 1) { | 970 | while (cval->res > 1) { |
951 | if (snd_usb_mixer_set_ctl_value(cval, UAC_SET_RES, | 971 | if (snd_usb_mixer_set_ctl_value(cval, UAC_SET_RES, |
952 | (cval->control << 8) | minchn, cval->res / 2) < 0) | 972 | (cval->control << 8) | minchn, |
973 | cval->res / 2) < 0) | ||
953 | break; | 974 | break; |
954 | cval->res /= 2; | 975 | cval->res /= 2; |
955 | } | 976 | } |
956 | if (get_ctl_value(cval, UAC_GET_RES, (cval->control << 8) | minchn, &cval->res) < 0) | 977 | if (get_ctl_value(cval, UAC_GET_RES, |
978 | (cval->control << 8) | minchn, &cval->res) < 0) | ||
957 | cval->res = last_valid_res; | 979 | cval->res = last_valid_res; |
958 | } | 980 | } |
959 | if (cval->res == 0) | 981 | if (cval->res == 0) |
@@ -1017,7 +1039,8 @@ static int get_min_max_with_quirks(struct usb_mixer_elem_info *cval, | |||
1017 | #define get_min_max(cval, def) get_min_max_with_quirks(cval, def, NULL) | 1039 | #define get_min_max(cval, def) get_min_max_with_quirks(cval, def, NULL) |
1018 | 1040 | ||
1019 | /* get a feature/mixer unit info */ | 1041 | /* get a feature/mixer unit info */ |
1020 | static int mixer_ctl_feature_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 1042 | static int mixer_ctl_feature_info(struct snd_kcontrol *kcontrol, |
1043 | struct snd_ctl_elem_info *uinfo) | ||
1021 | { | 1044 | { |
1022 | struct usb_mixer_elem_info *cval = kcontrol->private_data; | 1045 | struct usb_mixer_elem_info *cval = kcontrol->private_data; |
1023 | 1046 | ||
@@ -1051,7 +1074,8 @@ static int mixer_ctl_feature_info(struct snd_kcontrol *kcontrol, struct snd_ctl_ | |||
1051 | } | 1074 | } |
1052 | 1075 | ||
1053 | /* get the current value from feature/mixer unit */ | 1076 | /* get the current value from feature/mixer unit */ |
1054 | static int mixer_ctl_feature_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1077 | static int mixer_ctl_feature_get(struct snd_kcontrol *kcontrol, |
1078 | struct snd_ctl_elem_value *ucontrol) | ||
1055 | { | 1079 | { |
1056 | struct usb_mixer_elem_info *cval = kcontrol->private_data; | 1080 | struct usb_mixer_elem_info *cval = kcontrol->private_data; |
1057 | int c, cnt, val, err; | 1081 | int c, cnt, val, err; |
@@ -1082,7 +1106,8 @@ static int mixer_ctl_feature_get(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
1082 | } | 1106 | } |
1083 | 1107 | ||
1084 | /* put the current value to feature/mixer unit */ | 1108 | /* put the current value to feature/mixer unit */ |
1085 | static int mixer_ctl_feature_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1109 | static int mixer_ctl_feature_put(struct snd_kcontrol *kcontrol, |
1110 | struct snd_ctl_elem_value *ucontrol) | ||
1086 | { | 1111 | { |
1087 | struct usb_mixer_elem_info *cval = kcontrol->private_data; | 1112 | struct usb_mixer_elem_info *cval = kcontrol->private_data; |
1088 | int c, cnt, val, oval, err; | 1113 | int c, cnt, val, oval, err; |
@@ -1136,22 +1161,25 @@ static struct snd_kcontrol_new usb_feature_unit_ctl_ro = { | |||
1136 | .put = NULL, | 1161 | .put = NULL, |
1137 | }; | 1162 | }; |
1138 | 1163 | ||
1139 | /* This symbol is exported in order to allow the mixer quirks to | 1164 | /* |
1140 | * hook up to the standard feature unit control mechanism */ | 1165 | * This symbol is exported in order to allow the mixer quirks to |
1166 | * hook up to the standard feature unit control mechanism | ||
1167 | */ | ||
1141 | struct snd_kcontrol_new *snd_usb_feature_unit_ctl = &usb_feature_unit_ctl; | 1168 | struct snd_kcontrol_new *snd_usb_feature_unit_ctl = &usb_feature_unit_ctl; |
1142 | 1169 | ||
1143 | /* | 1170 | /* |
1144 | * build a feature control | 1171 | * build a feature control |
1145 | */ | 1172 | */ |
1146 | |||
1147 | static size_t append_ctl_name(struct snd_kcontrol *kctl, const char *str) | 1173 | static size_t append_ctl_name(struct snd_kcontrol *kctl, const char *str) |
1148 | { | 1174 | { |
1149 | return strlcat(kctl->id.name, str, sizeof(kctl->id.name)); | 1175 | return strlcat(kctl->id.name, str, sizeof(kctl->id.name)); |
1150 | } | 1176 | } |
1151 | 1177 | ||
1152 | /* A lot of headsets/headphones have a "Speaker" mixer. Make sure we | 1178 | /* |
1153 | rename it to "Headphone". We determine if something is a headphone | 1179 | * A lot of headsets/headphones have a "Speaker" mixer. Make sure we |
1154 | similar to how udev determines form factor. */ | 1180 | * rename it to "Headphone". We determine if something is a headphone |
1181 | * similar to how udev determines form factor. | ||
1182 | */ | ||
1155 | static void check_no_speaker_on_headset(struct snd_kcontrol *kctl, | 1183 | static void check_no_speaker_on_headset(struct snd_kcontrol *kctl, |
1156 | struct snd_card *card) | 1184 | struct snd_card *card) |
1157 | { | 1185 | { |
@@ -1201,10 +1229,8 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, | |||
1201 | return; | 1229 | return; |
1202 | 1230 | ||
1203 | cval = kzalloc(sizeof(*cval), GFP_KERNEL); | 1231 | cval = kzalloc(sizeof(*cval), GFP_KERNEL); |
1204 | if (! cval) { | 1232 | if (!cval) |
1205 | usb_audio_err(state->chip, "cannot malloc kcontrol\n"); | ||
1206 | return; | 1233 | return; |
1207 | } | ||
1208 | cval->mixer = state->mixer; | 1234 | cval->mixer = state->mixer; |
1209 | cval->id = unitid; | 1235 | cval->id = unitid; |
1210 | cval->control = control; | 1236 | cval->control = control; |
@@ -1222,15 +1248,17 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, | |||
1222 | cval->ch_readonly = readonly_mask; | 1248 | cval->ch_readonly = readonly_mask; |
1223 | } | 1249 | } |
1224 | 1250 | ||
1225 | /* if all channels in the mask are marked read-only, make the control | 1251 | /* |
1252 | * If all channels in the mask are marked read-only, make the control | ||
1226 | * read-only. set_cur_mix_value() will check the mask again and won't | 1253 | * read-only. set_cur_mix_value() will check the mask again and won't |
1227 | * issue write commands to read-only channels. */ | 1254 | * issue write commands to read-only channels. |
1255 | */ | ||
1228 | if (cval->channels == readonly_mask) | 1256 | if (cval->channels == readonly_mask) |
1229 | kctl = snd_ctl_new1(&usb_feature_unit_ctl_ro, cval); | 1257 | kctl = snd_ctl_new1(&usb_feature_unit_ctl_ro, cval); |
1230 | else | 1258 | else |
1231 | kctl = snd_ctl_new1(&usb_feature_unit_ctl, cval); | 1259 | kctl = snd_ctl_new1(&usb_feature_unit_ctl, cval); |
1232 | 1260 | ||
1233 | if (! kctl) { | 1261 | if (!kctl) { |
1234 | usb_audio_err(state->chip, "cannot malloc kcontrol\n"); | 1262 | usb_audio_err(state->chip, "cannot malloc kcontrol\n"); |
1235 | kfree(cval); | 1263 | kfree(cval); |
1236 | return; | 1264 | return; |
@@ -1239,48 +1267,53 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, | |||
1239 | 1267 | ||
1240 | len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name)); | 1268 | len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name)); |
1241 | mapped_name = len != 0; | 1269 | mapped_name = len != 0; |
1242 | if (! len && nameid) | 1270 | if (!len && nameid) |
1243 | len = snd_usb_copy_string_desc(state, nameid, | 1271 | len = snd_usb_copy_string_desc(state, nameid, |
1244 | kctl->id.name, sizeof(kctl->id.name)); | 1272 | kctl->id.name, sizeof(kctl->id.name)); |
1245 | 1273 | ||
1246 | switch (control) { | 1274 | switch (control) { |
1247 | case UAC_FU_MUTE: | 1275 | case UAC_FU_MUTE: |
1248 | case UAC_FU_VOLUME: | 1276 | case UAC_FU_VOLUME: |
1249 | /* determine the control name. the rule is: | 1277 | /* |
1278 | * determine the control name. the rule is: | ||
1250 | * - if a name id is given in descriptor, use it. | 1279 | * - if a name id is given in descriptor, use it. |
1251 | * - if the connected input can be determined, then use the name | 1280 | * - if the connected input can be determined, then use the name |
1252 | * of terminal type. | 1281 | * of terminal type. |
1253 | * - if the connected output can be determined, use it. | 1282 | * - if the connected output can be determined, use it. |
1254 | * - otherwise, anonymous name. | 1283 | * - otherwise, anonymous name. |
1255 | */ | 1284 | */ |
1256 | if (! len) { | 1285 | if (!len) { |
1257 | len = get_term_name(state, iterm, kctl->id.name, sizeof(kctl->id.name), 1); | 1286 | len = get_term_name(state, iterm, kctl->id.name, |
1258 | if (! len) | 1287 | sizeof(kctl->id.name), 1); |
1259 | len = get_term_name(state, &state->oterm, kctl->id.name, sizeof(kctl->id.name), 1); | 1288 | if (!len) |
1260 | if (! len) | 1289 | len = get_term_name(state, &state->oterm, |
1261 | len = snprintf(kctl->id.name, sizeof(kctl->id.name), | 1290 | kctl->id.name, |
1291 | sizeof(kctl->id.name), 1); | ||
1292 | if (!len) | ||
1293 | len = snprintf(kctl->id.name, | ||
1294 | sizeof(kctl->id.name), | ||
1262 | "Feature %d", unitid); | 1295 | "Feature %d", unitid); |
1263 | } | 1296 | } |
1264 | 1297 | ||
1265 | if (!mapped_name) | 1298 | if (!mapped_name) |
1266 | check_no_speaker_on_headset(kctl, state->mixer->chip->card); | 1299 | check_no_speaker_on_headset(kctl, state->mixer->chip->card); |
1267 | 1300 | ||
1268 | /* determine the stream direction: | 1301 | /* |
1302 | * determine the stream direction: | ||
1269 | * if the connected output is USB stream, then it's likely a | 1303 | * if the connected output is USB stream, then it's likely a |
1270 | * capture stream. otherwise it should be playback (hopefully :) | 1304 | * capture stream. otherwise it should be playback (hopefully :) |
1271 | */ | 1305 | */ |
1272 | if (! mapped_name && ! (state->oterm.type >> 16)) { | 1306 | if (!mapped_name && !(state->oterm.type >> 16)) { |
1273 | if ((state->oterm.type & 0xff00) == 0x0100) { | 1307 | if ((state->oterm.type & 0xff00) == 0x0100) |
1274 | len = append_ctl_name(kctl, " Capture"); | 1308 | len = append_ctl_name(kctl, " Capture"); |
1275 | } else { | 1309 | else |
1276 | len = append_ctl_name(kctl, " Playback"); | 1310 | len = append_ctl_name(kctl, " Playback"); |
1277 | } | ||
1278 | } | 1311 | } |
1279 | append_ctl_name(kctl, control == UAC_FU_MUTE ? | 1312 | append_ctl_name(kctl, control == UAC_FU_MUTE ? |
1280 | " Switch" : " Volume"); | 1313 | " Switch" : " Volume"); |
1281 | break; | 1314 | break; |
1282 | default: | 1315 | default: |
1283 | if (! len) | 1316 | if (!len) |
1284 | strlcpy(kctl->id.name, audio_feature_info[control-1].name, | 1317 | strlcpy(kctl->id.name, audio_feature_info[control-1].name, |
1285 | sizeof(kctl->id.name)); | 1318 | sizeof(kctl->id.name)); |
1286 | break; | 1319 | break; |
@@ -1300,33 +1333,35 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, | |||
1300 | } | 1333 | } |
1301 | 1334 | ||
1302 | range = (cval->max - cval->min) / cval->res; | 1335 | range = (cval->max - cval->min) / cval->res; |
1303 | /* Are there devices with volume range more than 255? I use a bit more | 1336 | /* |
1337 | * Are there devices with volume range more than 255? I use a bit more | ||
1304 | * to be sure. 384 is a resolution magic number found on Logitech | 1338 | * to be sure. 384 is a resolution magic number found on Logitech |
1305 | * devices. It will definitively catch all buggy Logitech devices. | 1339 | * devices. It will definitively catch all buggy Logitech devices. |
1306 | */ | 1340 | */ |
1307 | if (range > 384) { | 1341 | if (range > 384) { |
1308 | usb_audio_warn(state->chip, "Warning! Unlikely big " | 1342 | usb_audio_warn(state->chip, |
1309 | "volume range (=%u), cval->res is probably wrong.", | 1343 | "Warning! Unlikely big volume range (=%u), " |
1310 | range); | 1344 | "cval->res is probably wrong.", |
1345 | range); | ||
1311 | usb_audio_warn(state->chip, "[%d] FU [%s] ch = %d, " | 1346 | usb_audio_warn(state->chip, "[%d] FU [%s] ch = %d, " |
1312 | "val = %d/%d/%d", cval->id, | 1347 | "val = %d/%d/%d", cval->id, |
1313 | kctl->id.name, cval->channels, | 1348 | kctl->id.name, cval->channels, |
1314 | cval->min, cval->max, cval->res); | 1349 | cval->min, cval->max, cval->res); |
1315 | } | 1350 | } |
1316 | 1351 | ||
1317 | usb_audio_dbg(state->chip, "[%d] FU [%s] ch = %d, val = %d/%d/%d\n", | 1352 | usb_audio_dbg(state->chip, "[%d] FU [%s] ch = %d, val = %d/%d/%d\n", |
1318 | cval->id, kctl->id.name, cval->channels, cval->min, cval->max, cval->res); | 1353 | cval->id, kctl->id.name, cval->channels, |
1354 | cval->min, cval->max, cval->res); | ||
1319 | snd_usb_mixer_add_control(state->mixer, kctl); | 1355 | snd_usb_mixer_add_control(state->mixer, kctl); |
1320 | } | 1356 | } |
1321 | 1357 | ||
1322 | |||
1323 | |||
1324 | /* | 1358 | /* |
1325 | * parse a feature unit | 1359 | * parse a feature unit |
1326 | * | 1360 | * |
1327 | * most of controls are defined here. | 1361 | * most of controls are defined here. |
1328 | */ | 1362 | */ |
1329 | static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void *_ftr) | 1363 | static int parse_audio_feature_unit(struct mixer_build *state, int unitid, |
1364 | void *_ftr) | ||
1330 | { | 1365 | { |
1331 | int channels, i, j; | 1366 | int channels, i, j; |
1332 | struct usb_audio_term iterm; | 1367 | struct usb_audio_term iterm; |
@@ -1400,15 +1435,25 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void | |||
1400 | for (i = 0; i < 10; i++) { | 1435 | for (i = 0; i < 10; i++) { |
1401 | unsigned int ch_bits = 0; | 1436 | unsigned int ch_bits = 0; |
1402 | for (j = 0; j < channels; j++) { | 1437 | for (j = 0; j < channels; j++) { |
1403 | unsigned int mask = snd_usb_combine_bytes(bmaControls + csize * (j+1), csize); | 1438 | unsigned int mask; |
1439 | |||
1440 | mask = snd_usb_combine_bytes(bmaControls + | ||
1441 | csize * (j+1), csize); | ||
1404 | if (mask & (1 << i)) | 1442 | if (mask & (1 << i)) |
1405 | ch_bits |= (1 << j); | 1443 | ch_bits |= (1 << j); |
1406 | } | 1444 | } |
1407 | /* audio class v1 controls are never read-only */ | 1445 | /* audio class v1 controls are never read-only */ |
1408 | if (ch_bits & 1) /* the first channel must be set (for ease of programming) */ | 1446 | |
1409 | build_feature_ctl(state, _ftr, ch_bits, i, &iterm, unitid, 0); | 1447 | /* |
1448 | * The first channel must be set | ||
1449 | * (for ease of programming). | ||
1450 | */ | ||
1451 | if (ch_bits & 1) | ||
1452 | build_feature_ctl(state, _ftr, ch_bits, i, | ||
1453 | &iterm, unitid, 0); | ||
1410 | if (master_bits & (1 << i)) | 1454 | if (master_bits & (1 << i)) |
1411 | build_feature_ctl(state, _ftr, 0, i, &iterm, unitid, 0); | 1455 | build_feature_ctl(state, _ftr, 0, i, &iterm, |
1456 | unitid, 0); | ||
1412 | } | 1457 | } |
1413 | } else { /* UAC_VERSION_2 */ | 1458 | } else { /* UAC_VERSION_2 */ |
1414 | for (i = 0; i < ARRAY_SIZE(audio_feature_info); i++) { | 1459 | for (i = 0; i < ARRAY_SIZE(audio_feature_info); i++) { |
@@ -1416,7 +1461,10 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void | |||
1416 | unsigned int ch_read_only = 0; | 1461 | unsigned int ch_read_only = 0; |
1417 | 1462 | ||
1418 | for (j = 0; j < channels; j++) { | 1463 | for (j = 0; j < channels; j++) { |
1419 | unsigned int mask = snd_usb_combine_bytes(bmaControls + csize * (j+1), csize); | 1464 | unsigned int mask; |
1465 | |||
1466 | mask = snd_usb_combine_bytes(bmaControls + | ||
1467 | csize * (j+1), csize); | ||
1420 | if (uac2_control_is_readable(mask, i)) { | 1468 | if (uac2_control_is_readable(mask, i)) { |
1421 | ch_bits |= (1 << j); | 1469 | ch_bits |= (1 << j); |
1422 | if (!uac2_control_is_writeable(mask, i)) | 1470 | if (!uac2_control_is_writeable(mask, i)) |
@@ -1424,12 +1472,22 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void | |||
1424 | } | 1472 | } |
1425 | } | 1473 | } |
1426 | 1474 | ||
1427 | /* NOTE: build_feature_ctl() will mark the control read-only if all channels | 1475 | /* |
1428 | * are marked read-only in the descriptors. Otherwise, the control will be | 1476 | * NOTE: build_feature_ctl() will mark the control |
1429 | * reported as writeable, but the driver will not actually issue a write | 1477 | * read-only if all channels are marked read-only in |
1430 | * command for read-only channels */ | 1478 | * the descriptors. Otherwise, the control will be |
1431 | if (ch_bits & 1) /* the first channel must be set (for ease of programming) */ | 1479 | * reported as writeable, but the driver will not |
1432 | build_feature_ctl(state, _ftr, ch_bits, i, &iterm, unitid, ch_read_only); | 1480 | * actually issue a write command for read-only |
1481 | * channels. | ||
1482 | */ | ||
1483 | |||
1484 | /* | ||
1485 | * The first channel must be set | ||
1486 | * (for ease of programming). | ||
1487 | */ | ||
1488 | if (ch_bits & 1) | ||
1489 | build_feature_ctl(state, _ftr, ch_bits, i, | ||
1490 | &iterm, unitid, ch_read_only); | ||
1433 | if (uac2_control_is_readable(master_bits, i)) | 1491 | if (uac2_control_is_readable(master_bits, i)) |
1434 | build_feature_ctl(state, _ftr, 0, i, &iterm, unitid, | 1492 | build_feature_ctl(state, _ftr, 0, i, &iterm, unitid, |
1435 | !uac2_control_is_writeable(master_bits, i)); | 1493 | !uac2_control_is_writeable(master_bits, i)); |
@@ -1439,7 +1497,6 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void | |||
1439 | return 0; | 1497 | return 0; |
1440 | } | 1498 | } |
1441 | 1499 | ||
1442 | |||
1443 | /* | 1500 | /* |
1444 | * Mixer Unit | 1501 | * Mixer Unit |
1445 | */ | 1502 | */ |
@@ -1450,7 +1507,6 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void | |||
1450 | * the callbacks are identical with feature unit. | 1507 | * the callbacks are identical with feature unit. |
1451 | * input channel number (zero based) is given in control field instead. | 1508 | * input channel number (zero based) is given in control field instead. |
1452 | */ | 1509 | */ |
1453 | |||
1454 | static void build_mixer_unit_ctl(struct mixer_build *state, | 1510 | static void build_mixer_unit_ctl(struct mixer_build *state, |
1455 | struct uac_mixer_unit_descriptor *desc, | 1511 | struct uac_mixer_unit_descriptor *desc, |
1456 | int in_pin, int in_ch, int unitid, | 1512 | int in_pin, int in_ch, int unitid, |
@@ -1467,7 +1523,7 @@ static void build_mixer_unit_ctl(struct mixer_build *state, | |||
1467 | return; | 1523 | return; |
1468 | 1524 | ||
1469 | cval = kzalloc(sizeof(*cval), GFP_KERNEL); | 1525 | cval = kzalloc(sizeof(*cval), GFP_KERNEL); |
1470 | if (! cval) | 1526 | if (!cval) |
1471 | return; | 1527 | return; |
1472 | 1528 | ||
1473 | cval->mixer = state->mixer; | 1529 | cval->mixer = state->mixer; |
@@ -1475,7 +1531,9 @@ static void build_mixer_unit_ctl(struct mixer_build *state, | |||
1475 | cval->control = in_ch + 1; /* based on 1 */ | 1531 | cval->control = in_ch + 1; /* based on 1 */ |
1476 | cval->val_type = USB_MIXER_S16; | 1532 | cval->val_type = USB_MIXER_S16; |
1477 | for (i = 0; i < num_outs; i++) { | 1533 | for (i = 0; i < num_outs; i++) { |
1478 | if (check_matrix_bitmap(uac_mixer_unit_bmControls(desc, state->mixer->protocol), in_ch, i, num_outs)) { | 1534 | __u8 *c = uac_mixer_unit_bmControls(desc, state->mixer->protocol); |
1535 | |||
1536 | if (check_matrix_bitmap(c, in_ch, i, num_outs)) { | ||
1479 | cval->cmask |= (1 << i); | 1537 | cval->cmask |= (1 << i); |
1480 | cval->channels++; | 1538 | cval->channels++; |
1481 | } | 1539 | } |
@@ -1485,7 +1543,7 @@ static void build_mixer_unit_ctl(struct mixer_build *state, | |||
1485 | get_min_max(cval, 0); | 1543 | get_min_max(cval, 0); |
1486 | 1544 | ||
1487 | kctl = snd_ctl_new1(&usb_feature_unit_ctl, cval); | 1545 | kctl = snd_ctl_new1(&usb_feature_unit_ctl, cval); |
1488 | if (! kctl) { | 1546 | if (!kctl) { |
1489 | usb_audio_err(state->chip, "cannot malloc kcontrol\n"); | 1547 | usb_audio_err(state->chip, "cannot malloc kcontrol\n"); |
1490 | kfree(cval); | 1548 | kfree(cval); |
1491 | return; | 1549 | return; |
@@ -1493,9 +1551,10 @@ static void build_mixer_unit_ctl(struct mixer_build *state, | |||
1493 | kctl->private_free = usb_mixer_elem_free; | 1551 | kctl->private_free = usb_mixer_elem_free; |
1494 | 1552 | ||
1495 | len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name)); | 1553 | len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name)); |
1496 | if (! len) | 1554 | if (!len) |
1497 | len = get_term_name(state, iterm, kctl->id.name, sizeof(kctl->id.name), 0); | 1555 | len = get_term_name(state, iterm, kctl->id.name, |
1498 | if (! len) | 1556 | sizeof(kctl->id.name), 0); |
1557 | if (!len) | ||
1499 | len = sprintf(kctl->id.name, "Mixer Source %d", in_ch + 1); | 1558 | len = sprintf(kctl->id.name, "Mixer Source %d", in_ch + 1); |
1500 | append_ctl_name(kctl, " Volume"); | 1559 | append_ctl_name(kctl, " Volume"); |
1501 | 1560 | ||
@@ -1504,24 +1563,28 @@ static void build_mixer_unit_ctl(struct mixer_build *state, | |||
1504 | snd_usb_mixer_add_control(state->mixer, kctl); | 1563 | snd_usb_mixer_add_control(state->mixer, kctl); |
1505 | } | 1564 | } |
1506 | 1565 | ||
1507 | |||
1508 | /* | 1566 | /* |
1509 | * parse a mixer unit | 1567 | * parse a mixer unit |
1510 | */ | 1568 | */ |
1511 | static int parse_audio_mixer_unit(struct mixer_build *state, int unitid, void *raw_desc) | 1569 | static int parse_audio_mixer_unit(struct mixer_build *state, int unitid, |
1570 | void *raw_desc) | ||
1512 | { | 1571 | { |
1513 | struct uac_mixer_unit_descriptor *desc = raw_desc; | 1572 | struct uac_mixer_unit_descriptor *desc = raw_desc; |
1514 | struct usb_audio_term iterm; | 1573 | struct usb_audio_term iterm; |
1515 | int input_pins, num_ins, num_outs; | 1574 | int input_pins, num_ins, num_outs; |
1516 | int pin, ich, err; | 1575 | int pin, ich, err; |
1517 | 1576 | ||
1518 | if (desc->bLength < 11 || ! (input_pins = desc->bNrInPins) || ! (num_outs = uac_mixer_unit_bNrChannels(desc))) { | 1577 | if (desc->bLength < 11 || !(input_pins = desc->bNrInPins) || |
1519 | usb_audio_err(state->chip, "invalid MIXER UNIT descriptor %d\n", unitid); | 1578 | !(num_outs = uac_mixer_unit_bNrChannels(desc))) { |
1579 | usb_audio_err(state->chip, | ||
1580 | "invalid MIXER UNIT descriptor %d\n", | ||
1581 | unitid); | ||
1520 | return -EINVAL; | 1582 | return -EINVAL; |
1521 | } | 1583 | } |
1522 | /* no bmControls field (e.g. Maya44) -> ignore */ | 1584 | /* no bmControls field (e.g. Maya44) -> ignore */ |
1523 | if (desc->bLength <= 10 + input_pins) { | 1585 | if (desc->bLength <= 10 + input_pins) { |
1524 | usb_audio_dbg(state->chip, "MU %d has no bmControls field\n", unitid); | 1586 | usb_audio_dbg(state->chip, "MU %d has no bmControls field\n", |
1587 | unitid); | ||
1525 | return 0; | 1588 | return 0; |
1526 | } | 1589 | } |
1527 | 1590 | ||
@@ -1535,12 +1598,14 @@ static int parse_audio_mixer_unit(struct mixer_build *state, int unitid, void *r | |||
1535 | if (err < 0) | 1598 | if (err < 0) |
1536 | return err; | 1599 | return err; |
1537 | num_ins += iterm.channels; | 1600 | num_ins += iterm.channels; |
1538 | for (; ich < num_ins; ++ich) { | 1601 | for (; ich < num_ins; ich++) { |
1539 | int och, ich_has_controls = 0; | 1602 | int och, ich_has_controls = 0; |
1540 | 1603 | ||
1541 | for (och = 0; och < num_outs; ++och) { | 1604 | for (och = 0; och < num_outs; och++) { |
1542 | if (check_matrix_bitmap(uac_mixer_unit_bmControls(desc, state->mixer->protocol), | 1605 | __u8 *c = uac_mixer_unit_bmControls(desc, |
1543 | ich, och, num_outs)) { | 1606 | state->mixer->protocol); |
1607 | |||
1608 | if (check_matrix_bitmap(c, ich, och, num_outs)) { | ||
1544 | ich_has_controls = 1; | 1609 | ich_has_controls = 1; |
1545 | break; | 1610 | break; |
1546 | } | 1611 | } |
@@ -1553,13 +1618,13 @@ static int parse_audio_mixer_unit(struct mixer_build *state, int unitid, void *r | |||
1553 | return 0; | 1618 | return 0; |
1554 | } | 1619 | } |
1555 | 1620 | ||
1556 | |||
1557 | /* | 1621 | /* |
1558 | * Processing Unit / Extension Unit | 1622 | * Processing Unit / Extension Unit |
1559 | */ | 1623 | */ |
1560 | 1624 | ||
1561 | /* get callback for processing/extension unit */ | 1625 | /* get callback for processing/extension unit */ |
1562 | static int mixer_ctl_procunit_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1626 | static int mixer_ctl_procunit_get(struct snd_kcontrol *kcontrol, |
1627 | struct snd_ctl_elem_value *ucontrol) | ||
1563 | { | 1628 | { |
1564 | struct usb_mixer_elem_info *cval = kcontrol->private_data; | 1629 | struct usb_mixer_elem_info *cval = kcontrol->private_data; |
1565 | int err, val; | 1630 | int err, val; |
@@ -1577,7 +1642,8 @@ static int mixer_ctl_procunit_get(struct snd_kcontrol *kcontrol, struct snd_ctl_ | |||
1577 | } | 1642 | } |
1578 | 1643 | ||
1579 | /* put callback for processing/extension unit */ | 1644 | /* put callback for processing/extension unit */ |
1580 | static int mixer_ctl_procunit_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1645 | static int mixer_ctl_procunit_put(struct snd_kcontrol *kcontrol, |
1646 | struct snd_ctl_elem_value *ucontrol) | ||
1581 | { | 1647 | { |
1582 | struct usb_mixer_elem_info *cval = kcontrol->private_data; | 1648 | struct usb_mixer_elem_info *cval = kcontrol->private_data; |
1583 | int val, oval, err; | 1649 | int val, oval, err; |
@@ -1606,7 +1672,6 @@ static struct snd_kcontrol_new mixer_procunit_ctl = { | |||
1606 | .put = mixer_ctl_procunit_put, | 1672 | .put = mixer_ctl_procunit_put, |
1607 | }; | 1673 | }; |
1608 | 1674 | ||
1609 | |||
1610 | /* | 1675 | /* |
1611 | * predefined data for processing units | 1676 | * predefined data for processing units |
1612 | */ | 1677 | */ |
@@ -1697,10 +1762,13 @@ static struct procunit_info extunits[] = { | |||
1697 | { USB_XU_DEVICE_OPTIONS, "AnalogueIn Soft Limit", soft_limit_xu_info }, | 1762 | { USB_XU_DEVICE_OPTIONS, "AnalogueIn Soft Limit", soft_limit_xu_info }, |
1698 | { 0 } | 1763 | { 0 } |
1699 | }; | 1764 | }; |
1765 | |||
1700 | /* | 1766 | /* |
1701 | * build a processing/extension unit | 1767 | * build a processing/extension unit |
1702 | */ | 1768 | */ |
1703 | static int build_audio_procunit(struct mixer_build *state, int unitid, void *raw_desc, struct procunit_info *list, char *name) | 1769 | static int build_audio_procunit(struct mixer_build *state, int unitid, |
1770 | void *raw_desc, struct procunit_info *list, | ||
1771 | char *name) | ||
1704 | { | 1772 | { |
1705 | struct uac_processing_unit_descriptor *desc = raw_desc; | 1773 | struct uac_processing_unit_descriptor *desc = raw_desc; |
1706 | int num_ins = desc->bNrInPins; | 1774 | int num_ins = desc->bNrInPins; |
@@ -1733,22 +1801,20 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, void *raw | |||
1733 | for (info = list; info && info->type; info++) | 1801 | for (info = list; info && info->type; info++) |
1734 | if (info->type == type) | 1802 | if (info->type == type) |
1735 | break; | 1803 | break; |
1736 | if (! info || ! info->type) | 1804 | if (!info || !info->type) |
1737 | info = &default_info; | 1805 | info = &default_info; |
1738 | 1806 | ||
1739 | for (valinfo = info->values; valinfo->control; valinfo++) { | 1807 | for (valinfo = info->values; valinfo->control; valinfo++) { |
1740 | __u8 *controls = uac_processing_unit_bmControls(desc, state->mixer->protocol); | 1808 | __u8 *controls = uac_processing_unit_bmControls(desc, state->mixer->protocol); |
1741 | 1809 | ||
1742 | if (! (controls[valinfo->control / 8] & (1 << ((valinfo->control % 8) - 1)))) | 1810 | if (!(controls[valinfo->control / 8] & (1 << ((valinfo->control % 8) - 1)))) |
1743 | continue; | 1811 | continue; |
1744 | map = find_map(state, unitid, valinfo->control); | 1812 | map = find_map(state, unitid, valinfo->control); |
1745 | if (check_ignored_ctl(map)) | 1813 | if (check_ignored_ctl(map)) |
1746 | continue; | 1814 | continue; |
1747 | cval = kzalloc(sizeof(*cval), GFP_KERNEL); | 1815 | cval = kzalloc(sizeof(*cval), GFP_KERNEL); |
1748 | if (! cval) { | 1816 | if (!cval) |
1749 | usb_audio_err(state->chip, "cannot malloc kcontrol\n"); | ||
1750 | return -ENOMEM; | 1817 | return -ENOMEM; |
1751 | } | ||
1752 | cval->mixer = state->mixer; | 1818 | cval->mixer = state->mixer; |
1753 | cval->id = unitid; | 1819 | cval->id = unitid; |
1754 | cval->control = valinfo->control; | 1820 | cval->control = valinfo->control; |
@@ -1765,7 +1831,8 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, void *raw | |||
1765 | cval->initialized = 1; | 1831 | cval->initialized = 1; |
1766 | } else { | 1832 | } else { |
1767 | if (type == USB_XU_CLOCK_RATE) { | 1833 | if (type == USB_XU_CLOCK_RATE) { |
1768 | /* E-Mu USB 0404/0202/TrackerPre/0204 | 1834 | /* |
1835 | * E-Mu USB 0404/0202/TrackerPre/0204 | ||
1769 | * samplerate control quirk | 1836 | * samplerate control quirk |
1770 | */ | 1837 | */ |
1771 | cval->min = 0; | 1838 | cval->min = 0; |
@@ -1777,60 +1844,69 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, void *raw | |||
1777 | } | 1844 | } |
1778 | 1845 | ||
1779 | kctl = snd_ctl_new1(&mixer_procunit_ctl, cval); | 1846 | kctl = snd_ctl_new1(&mixer_procunit_ctl, cval); |
1780 | if (! kctl) { | 1847 | if (!kctl) { |
1781 | usb_audio_err(state->chip, "cannot malloc kcontrol\n"); | ||
1782 | kfree(cval); | 1848 | kfree(cval); |
1783 | return -ENOMEM; | 1849 | return -ENOMEM; |
1784 | } | 1850 | } |
1785 | kctl->private_free = usb_mixer_elem_free; | 1851 | kctl->private_free = usb_mixer_elem_free; |
1786 | 1852 | ||
1787 | if (check_mapped_name(map, kctl->id.name, | 1853 | if (check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name))) { |
1788 | sizeof(kctl->id.name))) | ||
1789 | /* nothing */ ; | 1854 | /* nothing */ ; |
1790 | else if (info->name) | 1855 | } else if (info->name) { |
1791 | strlcpy(kctl->id.name, info->name, sizeof(kctl->id.name)); | 1856 | strlcpy(kctl->id.name, info->name, sizeof(kctl->id.name)); |
1792 | else { | 1857 | } else { |
1793 | nameid = uac_processing_unit_iProcessing(desc, state->mixer->protocol); | 1858 | nameid = uac_processing_unit_iProcessing(desc, state->mixer->protocol); |
1794 | len = 0; | 1859 | len = 0; |
1795 | if (nameid) | 1860 | if (nameid) |
1796 | len = snd_usb_copy_string_desc(state, nameid, kctl->id.name, sizeof(kctl->id.name)); | 1861 | len = snd_usb_copy_string_desc(state, nameid, |
1797 | if (! len) | 1862 | kctl->id.name, |
1863 | sizeof(kctl->id.name)); | ||
1864 | if (!len) | ||
1798 | strlcpy(kctl->id.name, name, sizeof(kctl->id.name)); | 1865 | strlcpy(kctl->id.name, name, sizeof(kctl->id.name)); |
1799 | } | 1866 | } |
1800 | append_ctl_name(kctl, " "); | 1867 | append_ctl_name(kctl, " "); |
1801 | append_ctl_name(kctl, valinfo->suffix); | 1868 | append_ctl_name(kctl, valinfo->suffix); |
1802 | 1869 | ||
1803 | usb_audio_dbg(state->chip, | 1870 | usb_audio_dbg(state->chip, |
1804 | "[%d] PU [%s] ch = %d, val = %d/%d\n", | 1871 | "[%d] PU [%s] ch = %d, val = %d/%d\n", |
1805 | cval->id, kctl->id.name, cval->channels, cval->min, cval->max); | 1872 | cval->id, kctl->id.name, cval->channels, |
1806 | if ((err = snd_usb_mixer_add_control(state->mixer, kctl)) < 0) | 1873 | cval->min, cval->max); |
1874 | |||
1875 | err = snd_usb_mixer_add_control(state->mixer, kctl); | ||
1876 | if (err < 0) | ||
1807 | return err; | 1877 | return err; |
1808 | } | 1878 | } |
1809 | return 0; | 1879 | return 0; |
1810 | } | 1880 | } |
1811 | 1881 | ||
1812 | 1882 | static int parse_audio_processing_unit(struct mixer_build *state, int unitid, | |
1813 | static int parse_audio_processing_unit(struct mixer_build *state, int unitid, void *raw_desc) | 1883 | void *raw_desc) |
1814 | { | 1884 | { |
1815 | return build_audio_procunit(state, unitid, raw_desc, procunits, "Processing Unit"); | 1885 | return build_audio_procunit(state, unitid, raw_desc, |
1886 | procunits, "Processing Unit"); | ||
1816 | } | 1887 | } |
1817 | 1888 | ||
1818 | static int parse_audio_extension_unit(struct mixer_build *state, int unitid, void *raw_desc) | 1889 | static int parse_audio_extension_unit(struct mixer_build *state, int unitid, |
1890 | void *raw_desc) | ||
1819 | { | 1891 | { |
1820 | /* Note that we parse extension units with processing unit descriptors. | 1892 | /* |
1821 | * That's ok as the layout is the same */ | 1893 | * Note that we parse extension units with processing unit descriptors. |
1822 | return build_audio_procunit(state, unitid, raw_desc, extunits, "Extension Unit"); | 1894 | * That's ok as the layout is the same. |
1895 | */ | ||
1896 | return build_audio_procunit(state, unitid, raw_desc, | ||
1897 | extunits, "Extension Unit"); | ||
1823 | } | 1898 | } |
1824 | 1899 | ||
1825 | |||
1826 | /* | 1900 | /* |
1827 | * Selector Unit | 1901 | * Selector Unit |
1828 | */ | 1902 | */ |
1829 | 1903 | ||
1830 | /* info callback for selector unit | 1904 | /* |
1905 | * info callback for selector unit | ||
1831 | * use an enumerator type for routing | 1906 | * use an enumerator type for routing |
1832 | */ | 1907 | */ |
1833 | static int mixer_ctl_selector_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 1908 | static int mixer_ctl_selector_info(struct snd_kcontrol *kcontrol, |
1909 | struct snd_ctl_elem_info *uinfo) | ||
1834 | { | 1910 | { |
1835 | struct usb_mixer_elem_info *cval = kcontrol->private_data; | 1911 | struct usb_mixer_elem_info *cval = kcontrol->private_data; |
1836 | const char **itemlist = (const char **)kcontrol->private_value; | 1912 | const char **itemlist = (const char **)kcontrol->private_value; |
@@ -1841,7 +1917,8 @@ static int mixer_ctl_selector_info(struct snd_kcontrol *kcontrol, struct snd_ctl | |||
1841 | } | 1917 | } |
1842 | 1918 | ||
1843 | /* get callback for selector unit */ | 1919 | /* get callback for selector unit */ |
1844 | static int mixer_ctl_selector_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1920 | static int mixer_ctl_selector_get(struct snd_kcontrol *kcontrol, |
1921 | struct snd_ctl_elem_value *ucontrol) | ||
1845 | { | 1922 | { |
1846 | struct usb_mixer_elem_info *cval = kcontrol->private_data; | 1923 | struct usb_mixer_elem_info *cval = kcontrol->private_data; |
1847 | int val, err; | 1924 | int val, err; |
@@ -1860,7 +1937,8 @@ static int mixer_ctl_selector_get(struct snd_kcontrol *kcontrol, struct snd_ctl_ | |||
1860 | } | 1937 | } |
1861 | 1938 | ||
1862 | /* put callback for selector unit */ | 1939 | /* put callback for selector unit */ |
1863 | static int mixer_ctl_selector_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1940 | static int mixer_ctl_selector_put(struct snd_kcontrol *kcontrol, |
1941 | struct snd_ctl_elem_value *ucontrol) | ||
1864 | { | 1942 | { |
1865 | struct usb_mixer_elem_info *cval = kcontrol->private_data; | 1943 | struct usb_mixer_elem_info *cval = kcontrol->private_data; |
1866 | int val, oval, err; | 1944 | int val, oval, err; |
@@ -1889,8 +1967,8 @@ static struct snd_kcontrol_new mixer_selectunit_ctl = { | |||
1889 | .put = mixer_ctl_selector_put, | 1967 | .put = mixer_ctl_selector_put, |
1890 | }; | 1968 | }; |
1891 | 1969 | ||
1892 | 1970 | /* | |
1893 | /* private free callback. | 1971 | * private free callback. |
1894 | * free both private_data and private_value | 1972 | * free both private_data and private_value |
1895 | */ | 1973 | */ |
1896 | static void usb_mixer_selector_elem_free(struct snd_kcontrol *kctl) | 1974 | static void usb_mixer_selector_elem_free(struct snd_kcontrol *kctl) |
@@ -1915,7 +1993,8 @@ static void usb_mixer_selector_elem_free(struct snd_kcontrol *kctl) | |||
1915 | /* | 1993 | /* |
1916 | * parse a selector unit | 1994 | * parse a selector unit |
1917 | */ | 1995 | */ |
1918 | static int parse_audio_selector_unit(struct mixer_build *state, int unitid, void *raw_desc) | 1996 | static int parse_audio_selector_unit(struct mixer_build *state, int unitid, |
1997 | void *raw_desc) | ||
1919 | { | 1998 | { |
1920 | struct uac_selector_unit_descriptor *desc = raw_desc; | 1999 | struct uac_selector_unit_descriptor *desc = raw_desc; |
1921 | unsigned int i, nameid, len; | 2000 | unsigned int i, nameid, len; |
@@ -1944,10 +2023,8 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, void | |||
1944 | return 0; | 2023 | return 0; |
1945 | 2024 | ||
1946 | cval = kzalloc(sizeof(*cval), GFP_KERNEL); | 2025 | cval = kzalloc(sizeof(*cval), GFP_KERNEL); |
1947 | if (! cval) { | 2026 | if (!cval) |
1948 | usb_audio_err(state->chip, "cannot malloc kcontrol\n"); | ||
1949 | return -ENOMEM; | 2027 | return -ENOMEM; |
1950 | } | ||
1951 | cval->mixer = state->mixer; | 2028 | cval->mixer = state->mixer; |
1952 | cval->id = unitid; | 2029 | cval->id = unitid; |
1953 | cval->val_type = USB_MIXER_U8; | 2030 | cval->val_type = USB_MIXER_U8; |
@@ -1963,8 +2040,7 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, void | |||
1963 | cval->control = 0; | 2040 | cval->control = 0; |
1964 | 2041 | ||
1965 | namelist = kmalloc(sizeof(char *) * desc->bNrInPins, GFP_KERNEL); | 2042 | namelist = kmalloc(sizeof(char *) * desc->bNrInPins, GFP_KERNEL); |
1966 | if (! namelist) { | 2043 | if (!namelist) { |
1967 | usb_audio_err(state->chip, "cannot malloc\n"); | ||
1968 | kfree(cval); | 2044 | kfree(cval); |
1969 | return -ENOMEM; | 2045 | return -ENOMEM; |
1970 | } | 2046 | } |
@@ -1973,8 +2049,7 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, void | |||
1973 | struct usb_audio_term iterm; | 2049 | struct usb_audio_term iterm; |
1974 | len = 0; | 2050 | len = 0; |
1975 | namelist[i] = kmalloc(MAX_ITEM_NAME_LEN, GFP_KERNEL); | 2051 | namelist[i] = kmalloc(MAX_ITEM_NAME_LEN, GFP_KERNEL); |
1976 | if (! namelist[i]) { | 2052 | if (!namelist[i]) { |
1977 | usb_audio_err(state->chip, "cannot malloc\n"); | ||
1978 | while (i--) | 2053 | while (i--) |
1979 | kfree(namelist[i]); | 2054 | kfree(namelist[i]); |
1980 | kfree(namelist); | 2055 | kfree(namelist); |
@@ -1986,7 +2061,7 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, void | |||
1986 | if (! len && check_input_term(state, desc->baSourceID[i], &iterm) >= 0) | 2061 | if (! len && check_input_term(state, desc->baSourceID[i], &iterm) >= 0) |
1987 | len = get_term_name(state, &iterm, namelist[i], MAX_ITEM_NAME_LEN, 0); | 2062 | len = get_term_name(state, &iterm, namelist[i], MAX_ITEM_NAME_LEN, 0); |
1988 | if (! len) | 2063 | if (! len) |
1989 | sprintf(namelist[i], "Input %d", i); | 2064 | sprintf(namelist[i], "Input %u", i); |
1990 | } | 2065 | } |
1991 | 2066 | ||
1992 | kctl = snd_ctl_new1(&mixer_selectunit_ctl, cval); | 2067 | kctl = snd_ctl_new1(&mixer_selectunit_ctl, cval); |
@@ -2004,11 +2079,12 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, void | |||
2004 | if (len) | 2079 | if (len) |
2005 | ; | 2080 | ; |
2006 | else if (nameid) | 2081 | else if (nameid) |
2007 | snd_usb_copy_string_desc(state, nameid, kctl->id.name, sizeof(kctl->id.name)); | 2082 | snd_usb_copy_string_desc(state, nameid, kctl->id.name, |
2083 | sizeof(kctl->id.name)); | ||
2008 | else { | 2084 | else { |
2009 | len = get_term_name(state, &state->oterm, | 2085 | len = get_term_name(state, &state->oterm, |
2010 | kctl->id.name, sizeof(kctl->id.name), 0); | 2086 | kctl->id.name, sizeof(kctl->id.name), 0); |
2011 | if (! len) | 2087 | if (!len) |
2012 | strlcpy(kctl->id.name, "USB", sizeof(kctl->id.name)); | 2088 | strlcpy(kctl->id.name, "USB", sizeof(kctl->id.name)); |
2013 | 2089 | ||
2014 | if (desc->bDescriptorSubtype == UAC2_CLOCK_SELECTOR) | 2090 | if (desc->bDescriptorSubtype == UAC2_CLOCK_SELECTOR) |
@@ -2027,7 +2103,6 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, void | |||
2027 | return 0; | 2103 | return 0; |
2028 | } | 2104 | } |
2029 | 2105 | ||
2030 | |||
2031 | /* | 2106 | /* |
2032 | * parse an audio unit recursively | 2107 | * parse an audio unit recursively |
2033 | */ | 2108 | */ |
@@ -2125,14 +2200,16 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer) | |||
2125 | } | 2200 | } |
2126 | 2201 | ||
2127 | p = NULL; | 2202 | p = NULL; |
2128 | while ((p = snd_usb_find_csint_desc(mixer->hostif->extra, mixer->hostif->extralen, | 2203 | while ((p = snd_usb_find_csint_desc(mixer->hostif->extra, |
2204 | mixer->hostif->extralen, | ||
2129 | p, UAC_OUTPUT_TERMINAL)) != NULL) { | 2205 | p, UAC_OUTPUT_TERMINAL)) != NULL) { |
2130 | if (mixer->protocol == UAC_VERSION_1) { | 2206 | if (mixer->protocol == UAC_VERSION_1) { |
2131 | struct uac1_output_terminal_descriptor *desc = p; | 2207 | struct uac1_output_terminal_descriptor *desc = p; |
2132 | 2208 | ||
2133 | if (desc->bLength < sizeof(*desc)) | 2209 | if (desc->bLength < sizeof(*desc)) |
2134 | continue; /* invalid descriptor? */ | 2210 | continue; /* invalid descriptor? */ |
2135 | set_bit(desc->bTerminalID, state.unitbitmap); /* mark terminal ID as visited */ | 2211 | /* mark terminal ID as visited */ |
2212 | set_bit(desc->bTerminalID, state.unitbitmap); | ||
2136 | state.oterm.id = desc->bTerminalID; | 2213 | state.oterm.id = desc->bTerminalID; |
2137 | state.oterm.type = le16_to_cpu(desc->wTerminalType); | 2214 | state.oterm.type = le16_to_cpu(desc->wTerminalType); |
2138 | state.oterm.name = desc->iTerminal; | 2215 | state.oterm.name = desc->iTerminal; |
@@ -2144,7 +2221,8 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer) | |||
2144 | 2221 | ||
2145 | if (desc->bLength < sizeof(*desc)) | 2222 | if (desc->bLength < sizeof(*desc)) |
2146 | continue; /* invalid descriptor? */ | 2223 | continue; /* invalid descriptor? */ |
2147 | set_bit(desc->bTerminalID, state.unitbitmap); /* mark terminal ID as visited */ | 2224 | /* mark terminal ID as visited */ |
2225 | set_bit(desc->bTerminalID, state.unitbitmap); | ||
2148 | state.oterm.id = desc->bTerminalID; | 2226 | state.oterm.id = desc->bTerminalID; |
2149 | state.oterm.type = le16_to_cpu(desc->wTerminalType); | 2227 | state.oterm.type = le16_to_cpu(desc->wTerminalType); |
2150 | state.oterm.name = desc->iTerminal; | 2228 | state.oterm.name = desc->iTerminal; |
@@ -2152,7 +2230,10 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer) | |||
2152 | if (err < 0 && err != -EINVAL) | 2230 | if (err < 0 && err != -EINVAL) |
2153 | return err; | 2231 | return err; |
2154 | 2232 | ||
2155 | /* for UAC2, use the same approach to also add the clock selectors */ | 2233 | /* |
2234 | * For UAC2, use the same approach to also add the | ||
2235 | * clock selectors | ||
2236 | */ | ||
2156 | err = parse_audio_unit(&state, desc->bCSourceID); | 2237 | err = parse_audio_unit(&state, desc->bCSourceID); |
2157 | if (err < 0 && err != -EINVAL) | 2238 | if (err < 0 && err != -EINVAL) |
2158 | return err; | 2239 | return err; |
@@ -2306,7 +2387,9 @@ static void snd_usb_mixer_interrupt(struct urb *urb) | |||
2306 | } | 2387 | } |
2307 | 2388 | ||
2308 | requeue: | 2389 | requeue: |
2309 | if (ustatus != -ENOENT && ustatus != -ECONNRESET && ustatus != -ESHUTDOWN) { | 2390 | if (ustatus != -ENOENT && |
2391 | ustatus != -ECONNRESET && | ||
2392 | ustatus != -ESHUTDOWN) { | ||
2310 | urb->dev = mixer->chip->dev; | 2393 | urb->dev = mixer->chip->dev; |
2311 | usb_submit_urb(urb, GFP_ATOMIC); | 2394 | usb_submit_urb(urb, GFP_ATOMIC); |
2312 | } | 2395 | } |