From 01655193c2da12510af8a8b66b56da5e13ce1f91 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Sun, 17 Jun 2018 15:46:29 +0200 Subject: ALSA: ice1724: remove unused array This fixes a warning seen with clang: sound/pci/ice1712/prodigy_hifi.c:321:28: warning: variable 'wm_vol' is not needed and will not be emitted [-Wunneeded-internal-declaration] static const unsigned char wm_vol[256] = { ^ Signed-off-by: Stefan Agner Signed-off-by: Takashi Iwai --- sound/pci/ice1712/prodigy_hifi.c | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) (limited to 'sound') diff --git a/sound/pci/ice1712/prodigy_hifi.c b/sound/pci/ice1712/prodigy_hifi.c index d7366ade5a25..c97b5528e4b8 100644 --- a/sound/pci/ice1712/prodigy_hifi.c +++ b/sound/pci/ice1712/prodigy_hifi.c @@ -314,26 +314,7 @@ static struct snd_kcontrol_new prodigy_hd2_controls[] = { /* --------------- */ -/* - * Logarithmic volume values for WM87*6 - * Computed as 20 * Log10(255 / x) - */ -static const unsigned char wm_vol[256] = { - 127, 48, 42, 39, 36, 34, 33, 31, 30, 29, 28, 27, 27, 26, 25, 25, 24, 24, 23, - 23, 22, 22, 21, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18, 18, 18, 17, 17, 17, - 17, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, 13, - 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, - 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0 -}; - -#define WM_VOL_MAX (sizeof(wm_vol) - 1) +#define WM_VOL_MAX 255 #define WM_VOL_MUTE 0x8000 -- cgit v1.2.3 From a753af301c616cd51dedb3b5a8b3ba6cac3e58b8 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Sun, 17 Jun 2018 15:46:49 +0200 Subject: ALSA: ctxfi: use enum type CT_SUM_CTL where appropriate Currently a variable of type enum CT_AMIXER_CTL is used for enum CT_SUM_CTL values. This leads to warnings when using clang: sound/pci/ctxfi/ctmixer.c:945:32: warning: implicit conversion from enumeration type 'enum CT_SUM_CTL' to different enumeration type 'enum CT_AMIXER_CTL' [-Wenum-conversion] for (i = AMIXER_MASTER_F, j = SUM_IN_F; ~ ^~~~~~~~ sound/pci/ctxfi/ctmixer.c:975:29: warning: implicit conversion from enumeration type 'enum CT_SUM_CTL' to different enumeration type 'enum CT_AMIXER_CTL' [-Wenum-conversion] for (i = AMIXER_PCM_F, j = SUM_IN_F; i <= AMIXER_PCM_S; i++, j++) { ~ ^~~~~~~~ Introduce enum CT_SUM_CTL k and it instead. Signed-off-by: Stefan Agner Signed-off-by: Takashi Iwai --- sound/pci/ctxfi/ctmixer.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'sound') diff --git a/sound/pci/ctxfi/ctmixer.c b/sound/pci/ctxfi/ctmixer.c index db710d0a609f..4777d50fbbf8 100644 --- a/sound/pci/ctxfi/ctmixer.c +++ b/sound/pci/ctxfi/ctmixer.c @@ -938,17 +938,18 @@ static int ct_mixer_topology_build(struct ct_mixer *mixer) struct sum *sum; struct amixer *amix_d, *amix_s; enum CT_AMIXER_CTL i, j; + enum CT_SUM_CTL k; /* Build topology from destination to source */ /* Set up Master mixer */ - for (i = AMIXER_MASTER_F, j = SUM_IN_F; - i <= AMIXER_MASTER_S; i++, j++) { + for (i = AMIXER_MASTER_F, k = SUM_IN_F; + i <= AMIXER_MASTER_S; i++, k++) { amix_d = mixer->amixers[i*CHN_NUM]; - sum = mixer->sums[j*CHN_NUM]; + sum = mixer->sums[k*CHN_NUM]; amix_d->ops->setup(amix_d, &sum->rsc, INIT_VOL, NULL); amix_d = mixer->amixers[i*CHN_NUM+1]; - sum = mixer->sums[j*CHN_NUM+1]; + sum = mixer->sums[k*CHN_NUM+1]; amix_d->ops->setup(amix_d, &sum->rsc, INIT_VOL, NULL); } @@ -972,12 +973,12 @@ static int ct_mixer_topology_build(struct ct_mixer *mixer) amix_d->ops->setup(amix_d, &amix_s->rsc, INIT_VOL, NULL); /* Set up PCM-in mixer */ - for (i = AMIXER_PCM_F, j = SUM_IN_F; i <= AMIXER_PCM_S; i++, j++) { + for (i = AMIXER_PCM_F, k = SUM_IN_F; i <= AMIXER_PCM_S; i++, k++) { amix_d = mixer->amixers[i*CHN_NUM]; - sum = mixer->sums[j*CHN_NUM]; + sum = mixer->sums[k*CHN_NUM]; amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum); amix_d = mixer->amixers[i*CHN_NUM+1]; - sum = mixer->sums[j*CHN_NUM+1]; + sum = mixer->sums[k*CHN_NUM+1]; amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum); } -- cgit v1.2.3 From a8eaad7b04eaab3df6b8db722d4418286815b46c Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 18 Jun 2018 17:41:01 +0200 Subject: ALSA: line6: stop using get_seconds() The get_seconds() function is deprecated because it truncates the timestamp to 32 bits, so all users should change to ktime_get_seconds() or ktime_get_real_seconds(). The firmware interface for passing the timestamp is also limited to 32 bits, so this patch only has the cosmetic effect of avoiding the old interface. Signed-off-by: Arnd Bergmann Signed-off-by: Takashi Iwai --- sound/usb/line6/toneport.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/usb/line6/toneport.c b/sound/usb/line6/toneport.c index 750467fb95db..f47ba94e6f4a 100644 --- a/sound/usb/line6/toneport.c +++ b/sound/usb/line6/toneport.c @@ -367,12 +367,13 @@ static bool toneport_has_source_select(struct usb_line6_toneport *toneport) */ static void toneport_setup(struct usb_line6_toneport *toneport) { - int ticks; + u32 ticks; struct usb_line6 *line6 = &toneport->line6; struct usb_device *usbdev = line6->usbdev; /* sync time on device with host: */ - ticks = (int)get_seconds(); + /* note: 32-bit timestamps overflow in year 2106 */ + ticks = (u32)ktime_get_real_seconds(); line6_write_data(line6, 0x80c6, &ticks, 4); /* enable device: */ -- cgit v1.2.3 From 6c1549c4cc3c1b0d8623cde00e28f094b2db0d41 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Mon, 18 Jun 2018 21:07:51 +0900 Subject: ALSA: firewire-motu: suppless consumption for unused element of array in stack In MOTU firewire protocol, data block consists of 24 bit data chunks except for one quadlet for source packet header (SPH). The number of data chunk in a data block is different between three clock modes; low, middle and high. When unit supports ADAT on optical interface, the data block includes some chunks for ADAT channels. These ADAT chunks are unavailable at high mode. This driver has local functions to calculate the number of ADAT chunks. But They uses stack for three clock modes. This is useless for higher mode. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/motu/motu-protocol-v2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/firewire/motu/motu-protocol-v2.c b/sound/firewire/motu/motu-protocol-v2.c index 525b746330be..a51fd196d884 100644 --- a/sound/firewire/motu/motu-protocol-v2.c +++ b/sound/firewire/motu/motu-protocol-v2.c @@ -176,7 +176,7 @@ static void calculate_differed_part(struct snd_motu_packet_format *formats, enum snd_motu_spec_flags flags, u32 data, u32 mask, u32 shift) { - unsigned char pcm_chunks[3] = {0, 0}; + unsigned char pcm_chunks[2] = {0, 0}; /* * When optical interfaces are configured for S/PDIF (TOSLINK), -- cgit v1.2.3 From 81720c6d49b7932d642e7dca736bef9a40c9b5f7 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Mon, 18 Jun 2018 21:07:52 +0900 Subject: ALSA: firewire-motu: add a flag for chunks for main 1/2 out This driver explicitly assumes that all of supported models have main data chunk separated from chunk for analog ports. However, MOTU Traveler doesn't support the separated main data chunk. This commit adds a flag for the separated main data chunk. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/motu/motu-protocol-v2.c | 14 +++++++++----- sound/firewire/motu/motu-protocol-v3.c | 14 +++++++++----- sound/firewire/motu/motu.c | 3 +++ sound/firewire/motu/motu.h | 1 + 4 files changed, 22 insertions(+), 10 deletions(-) (limited to 'sound') diff --git a/sound/firewire/motu/motu-protocol-v2.c b/sound/firewire/motu/motu-protocol-v2.c index a51fd196d884..614f9b11e010 100644 --- a/sound/firewire/motu/motu-protocol-v2.c +++ b/sound/firewire/motu/motu-protocol-v2.c @@ -149,11 +149,15 @@ static void calculate_fixed_part(struct snd_motu_packet_format *formats, pcm_chunks[1] += 2; } } else { - /* - * Packets to v2 units transfer main-out-1/2 and phone-out-1/2. - */ - pcm_chunks[0] += 4; - pcm_chunks[1] += 4; + if (flags & SND_MOTU_SPEC_RX_SEPARETED_MAIN) { + pcm_chunks[0] += 2; + pcm_chunks[1] += 2; + } + + // Packets to v2 units include 2 chunks for phone 1/2, except + // for 176.4/192.0 kHz. + pcm_chunks[0] += 2; + pcm_chunks[1] += 2; } /* diff --git a/sound/firewire/motu/motu-protocol-v3.c b/sound/firewire/motu/motu-protocol-v3.c index c7cd9864dc4d..293353991591 100644 --- a/sound/firewire/motu/motu-protocol-v3.c +++ b/sound/firewire/motu/motu-protocol-v3.c @@ -188,11 +188,15 @@ static void calculate_fixed_part(struct snd_motu_packet_format *formats, pcm_chunks[1] += 2; } } else { - /* - * Packets to v2 units transfer main-out-1/2 and phone-out-1/2. - */ - pcm_chunks[0] += 4; - pcm_chunks[1] += 4; + if (flags & SND_MOTU_SPEC_RX_SEPARETED_MAIN) { + pcm_chunks[0] += 2; + pcm_chunks[1] += 2; + } + + // Packets to v3 units include 2 chunks for phone 1/2, except + // for 176.4/192.0 kHz. + pcm_chunks[0] += 2; + pcm_chunks[1] += 2; } /* diff --git a/sound/firewire/motu/motu.c b/sound/firewire/motu/motu.c index 0d6b526105ab..445aa589582d 100644 --- a/sound/firewire/motu/motu.c +++ b/sound/firewire/motu/motu.c @@ -200,6 +200,7 @@ static const struct snd_motu_spec motu_828mk2 = { .flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 | SND_MOTU_SPEC_TX_MICINST_CHUNK | SND_MOTU_SPEC_TX_RETURN_CHUNK | + SND_MOTU_SPEC_RX_SEPARETED_MAIN | SND_MOTU_SPEC_HAS_OPT_IFACE_A | SND_MOTU_SPEC_RX_MIDI_2ND_Q | SND_MOTU_SPEC_TX_MIDI_2ND_Q, @@ -216,6 +217,7 @@ static const struct snd_motu_spec motu_828mk3 = { SND_MOTU_SPEC_TX_MICINST_CHUNK | SND_MOTU_SPEC_TX_RETURN_CHUNK | SND_MOTU_SPEC_TX_REVERB_CHUNK | + SND_MOTU_SPEC_RX_SEPARETED_MAIN | SND_MOTU_SPEC_HAS_OPT_IFACE_A | SND_MOTU_SPEC_HAS_OPT_IFACE_B | SND_MOTU_SPEC_RX_MIDI_3RD_Q | @@ -231,6 +233,7 @@ static const struct snd_motu_spec motu_audio_express = { .flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 | SND_MOTU_SPEC_TX_MICINST_CHUNK | SND_MOTU_SPEC_TX_RETURN_CHUNK | + SND_MOTU_SPEC_RX_SEPARETED_MAIN | SND_MOTU_SPEC_RX_MIDI_2ND_Q | SND_MOTU_SPEC_TX_MIDI_3RD_Q, .analog_in_ports = 2, diff --git a/sound/firewire/motu/motu.h b/sound/firewire/motu/motu.h index 4b23cf337c4b..bced0407179e 100644 --- a/sound/firewire/motu/motu.h +++ b/sound/firewire/motu/motu.h @@ -86,6 +86,7 @@ enum snd_motu_spec_flags { SND_MOTU_SPEC_RX_MIDI_3RD_Q = 0x0200, SND_MOTU_SPEC_TX_MIDI_2ND_Q = 0x0400, SND_MOTU_SPEC_TX_MIDI_3RD_Q = 0x0800, + SND_MOTU_SPEC_RX_SEPARETED_MAIN = 0x1000, }; #define SND_MOTU_CLOCK_RATE_COUNT 6 -- cgit v1.2.3 From 06ac0b6f8f74e98d32f9dea5209bd26f3e7b50ba Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Mon, 18 Jun 2018 21:07:53 +0900 Subject: ALSA: firewire-motu: add a flag for AES/EBU on XLR interface MOTU Traveler supports AES/EBU on XLR interface and data block of rx/tx packet includes two chunk for the interface. This commit adds a flag for this purpose. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/motu/motu-protocol-v2.c | 5 +++++ sound/firewire/motu/motu-protocol-v3.c | 5 +++++ sound/firewire/motu/motu.h | 2 +- 3 files changed, 11 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/firewire/motu/motu-protocol-v2.c b/sound/firewire/motu/motu-protocol-v2.c index 614f9b11e010..f25b1ba118a2 100644 --- a/sound/firewire/motu/motu-protocol-v2.c +++ b/sound/firewire/motu/motu-protocol-v2.c @@ -160,6 +160,11 @@ static void calculate_fixed_part(struct snd_motu_packet_format *formats, pcm_chunks[1] += 2; } + if (flags & SND_MOTU_SPEC_HAS_AESEBU_IFACE) { + pcm_chunks[0] += 2; + pcm_chunks[1] += 2; + } + /* * All of v2 models have a pair of coaxial interfaces for digital in/out * port. At 44.1/48.0/88.2/96.0 kHz, packets includes PCM from these diff --git a/sound/firewire/motu/motu-protocol-v3.c b/sound/firewire/motu/motu-protocol-v3.c index 293353991591..7cc80a05e91f 100644 --- a/sound/firewire/motu/motu-protocol-v3.c +++ b/sound/firewire/motu/motu-protocol-v3.c @@ -199,6 +199,11 @@ static void calculate_fixed_part(struct snd_motu_packet_format *formats, pcm_chunks[1] += 2; } + if (flags & SND_MOTU_SPEC_HAS_AESEBU_IFACE) { + pcm_chunks[0] += 2; + pcm_chunks[1] += 2; + } + /* * At least, packets have two data chunks for S/PDIF on coaxial * interface. diff --git a/sound/firewire/motu/motu.h b/sound/firewire/motu/motu.h index bced0407179e..2764bcaab327 100644 --- a/sound/firewire/motu/motu.h +++ b/sound/firewire/motu/motu.h @@ -79,7 +79,7 @@ enum snd_motu_spec_flags { SND_MOTU_SPEC_TX_MICINST_CHUNK = 0x0004, SND_MOTU_SPEC_TX_RETURN_CHUNK = 0x0008, SND_MOTU_SPEC_TX_REVERB_CHUNK = 0x0010, - SND_MOTU_SPEC_TX_AESEBU_CHUNK = 0x0020, + SND_MOTU_SPEC_HAS_AESEBU_IFACE = 0x0020, SND_MOTU_SPEC_HAS_OPT_IFACE_A = 0x0040, SND_MOTU_SPEC_HAS_OPT_IFACE_B = 0x0080, SND_MOTU_SPEC_RX_MIDI_2ND_Q = 0x0100, -- cgit v1.2.3 From 191ef57683aab1939d9b7afdc43f9213c21c5e1e Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Mon, 18 Jun 2018 21:07:54 +0900 Subject: ALSA: firewire-motu: cancel chunk alignment for protocol version 2 For MOTU protocol version 2, this driver arranges the number of data chunks to align chunks to quadlet data channel. However, MOTU Traveler has padding bytes in the end of data block at high clock mode. This commit removes the arrangement. Fortunately, at low and middle clock mode, supported model for v2 protocol (828mkII) gets no influence from this change because all of combination for data chunks are just aligned to quadlet data channel. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/motu/motu-protocol-v2.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'sound') diff --git a/sound/firewire/motu/motu-protocol-v2.c b/sound/firewire/motu/motu-protocol-v2.c index f25b1ba118a2..e5bd3ac02300 100644 --- a/sound/firewire/motu/motu-protocol-v2.c +++ b/sound/firewire/motu/motu-protocol-v2.c @@ -173,12 +173,9 @@ static void calculate_fixed_part(struct snd_motu_packet_format *formats, pcm_chunks[0] += 2; pcm_chunks[1] += 2; - /* This part should be multiples of 4. */ - formats->fixed_part_pcm_chunks[0] = round_up(2 + pcm_chunks[0], 4) - 2; - formats->fixed_part_pcm_chunks[1] = round_up(2 + pcm_chunks[1], 4) - 2; - if (flags & SND_MOTU_SPEC_SUPPORT_CLOCK_X4) - formats->fixed_part_pcm_chunks[2] = - round_up(2 + pcm_chunks[2], 4) - 2; + formats->fixed_part_pcm_chunks[0] = pcm_chunks[0]; + formats->fixed_part_pcm_chunks[1] = pcm_chunks[1]; + formats->fixed_part_pcm_chunks[2] = pcm_chunks[2]; } static void calculate_differed_part(struct snd_motu_packet_format *formats, -- cgit v1.2.3 From 6c5e1ac0e144a8560cfa11bed8cdadab9491952f Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Mon, 18 Jun 2018 21:07:55 +0900 Subject: ALSA: firewire-motu: add support for Motu Traveler This commit adds support for MOTU Traveler, launched in 2005, discontinued quite before. As a result, transmission of PCM frame and MIDI messages is available via ALSA PCM and RawMIDI/Sequencer interfaces. This model supports sampling transmission frequency up to 192.0 kHz, and AES/EBU on XLR interface and ADAT on optical interface. Unlike Motu 828MkII, Windows driver can switch fetching mode for DSP, like mute/unmute feature. Although this commit enables high sampling transmission frequency, actual sound from this model is not good. As long as I tested, it's silence at 176.4 kHz, and it includes hissing noise at 192.0 kHz. In my opinion, as I reported at 3526ce7f9ba7 ('ALSA: firewire-motu: add MOTU specific protocol layer'), timestamping on source packet header (SPH) may not still be good for this model as well. $ python2 crpp < /sys/bus/firewire/devices/fw1/config_rom ROM header and bus information block ----------------------------------------------------------------- 400 04106505 bus_info_length 4, crc_length 16, crc 25861 404 31333934 bus_name "1394" 408 20001000 irmc 0, cmc 0, isc 1, bmc 0, cyc_clk_acc 0, max_rec 1 (4) 40c 0001f200 company_id 0001f2 | 410 0001f32f device_id 000001f32f | EUI-64 0001f2000001f32f root directory ----------------------------------------------------------------- 414 0004c65c directory_length 4, crc 50780 418 030001f2 vendor 41c 0c0083c0 node capabilities per IEEE 1394 420 8d000006 --> eui-64 leaf at 438 424 d1000001 --> unit directory at 428 unit directory at 428 ----------------------------------------------------------------- 428 00035955 directory_length 3, crc 22869 42c 120001f2 specifier id 430 13000009 version 434 17107800 model eui-64 leaf at 438 ----------------------------------------------------------------- 438 000206b2 leaf_length 2, crc 1714 43c 0001f200 company_id 0001f2 | 440 0001f32f device_id 000001f32f | EUI-64 0001f2000001f32f Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/motu/motu-protocol-v2.c | 34 ++++++++++++++++++++++++++++++++-- sound/firewire/motu/motu.c | 16 ++++++++++++++++ sound/firewire/motu/motu.h | 2 ++ 3 files changed, 50 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/firewire/motu/motu-protocol-v2.c b/sound/firewire/motu/motu-protocol-v2.c index e5bd3ac02300..453fc29fade7 100644 --- a/sound/firewire/motu/motu-protocol-v2.c +++ b/sound/firewire/motu/motu-protocol-v2.c @@ -13,6 +13,8 @@ #define V2_CLOCK_RATE_SHIFT 3 #define V2_CLOCK_SRC_MASK 0x00000007 #define V2_CLOCK_SRC_SHIFT 0 +#define V2_CLOCK_TRAVELER_FETCH_DISABLE 0x04000000 +#define V2_CLOCK_TRAVELER_FETCH_ENABLE 0x03000000 #define V2_IN_OUT_CONF_OFFSET 0x0c04 #define V2_OPT_OUT_IFACE_MASK 0x00000c00 @@ -66,6 +68,11 @@ static int v2_set_clock_rate(struct snd_motu *motu, unsigned int rate) data &= ~V2_CLOCK_RATE_MASK; data |= i << V2_CLOCK_RATE_SHIFT; + if (motu->spec == &snd_motu_spec_traveler) { + data &= ~V2_CLOCK_TRAVELER_FETCH_ENABLE; + data |= V2_CLOCK_TRAVELER_FETCH_DISABLE; + } + reg = cpu_to_be32(data); return snd_motu_transaction_write(motu, V2_CLOCK_STATUS_OFFSET, ®, sizeof(reg)); @@ -121,8 +128,31 @@ static int v2_get_clock_source(struct snd_motu *motu, static int v2_switch_fetching_mode(struct snd_motu *motu, bool enable) { - /* V2 protocol doesn't have this feature. */ - return 0; + __be32 reg; + u32 data; + int err = 0; + + if (motu->spec == &snd_motu_spec_traveler) { + err = snd_motu_transaction_read(motu, V2_CLOCK_STATUS_OFFSET, + ®, sizeof(reg)); + if (err < 0) + return err; + data = be32_to_cpu(reg); + + data &= ~(V2_CLOCK_TRAVELER_FETCH_DISABLE | + V2_CLOCK_TRAVELER_FETCH_ENABLE); + + if (enable) + data |= V2_CLOCK_TRAVELER_FETCH_ENABLE; + else + data |= V2_CLOCK_TRAVELER_FETCH_DISABLE; + + reg = cpu_to_be32(data); + err = snd_motu_transaction_write(motu, V2_CLOCK_STATUS_OFFSET, + ®, sizeof(reg)); + } + + return err; } static void calculate_fixed_part(struct snd_motu_packet_format *formats, diff --git a/sound/firewire/motu/motu.c b/sound/firewire/motu/motu.c index 445aa589582d..300d31b6f191 100644 --- a/sound/firewire/motu/motu.c +++ b/sound/firewire/motu/motu.c @@ -209,6 +209,21 @@ static const struct snd_motu_spec motu_828mk2 = { .analog_out_ports = 8, }; +const struct snd_motu_spec snd_motu_spec_traveler = { + .name = "Traveler", + .protocol = &snd_motu_protocol_v2, + .flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 | + SND_MOTU_SPEC_SUPPORT_CLOCK_X4 | + SND_MOTU_SPEC_TX_RETURN_CHUNK | + SND_MOTU_SPEC_HAS_AESEBU_IFACE | + SND_MOTU_SPEC_HAS_OPT_IFACE_A | + SND_MOTU_SPEC_RX_MIDI_2ND_Q | + SND_MOTU_SPEC_TX_MIDI_2ND_Q, + + .analog_in_ports = 8, + .analog_out_ports = 8, +}; + static const struct snd_motu_spec motu_828mk3 = { .name = "828mk3", .protocol = &snd_motu_protocol_v3, @@ -253,6 +268,7 @@ static const struct snd_motu_spec motu_audio_express = { static const struct ieee1394_device_id motu_id_table[] = { SND_MOTU_DEV_ENTRY(0x101800, &motu_828mk2), + SND_MOTU_DEV_ENTRY(0x107800, &snd_motu_spec_traveler), SND_MOTU_DEV_ENTRY(0x106800, &motu_828mk3), /* FireWire only. */ SND_MOTU_DEV_ENTRY(0x100800, &motu_828mk3), /* Hybrid. */ SND_MOTU_DEV_ENTRY(0x104800, &motu_audio_express), diff --git a/sound/firewire/motu/motu.h b/sound/firewire/motu/motu.h index 2764bcaab327..fd5327d30ab1 100644 --- a/sound/firewire/motu/motu.h +++ b/sound/firewire/motu/motu.h @@ -129,6 +129,8 @@ struct snd_motu_spec { extern const struct snd_motu_protocol snd_motu_protocol_v2; extern const struct snd_motu_protocol snd_motu_protocol_v3; +extern const struct snd_motu_spec snd_motu_spec_traveler; + int amdtp_motu_init(struct amdtp_stream *s, struct fw_unit *unit, enum amdtp_stream_direction dir, const struct snd_motu_protocol *const protocol); -- cgit v1.2.3 From f567b78851d49a4887b9bb1a8b3cfad37da515c8 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 18 Jun 2018 17:26:12 +0200 Subject: ALSA: hda - Move mic mute LED helper to the generic parser MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the code for setting up and controlling the mic mute LED hook from dell-wmi helper to the generic parser, so that it can be referred from the multiple driver codes. No functional change. Tested-by: Pali Rohár Signed-off-by: Takashi Iwai --- sound/pci/hda/dell_wmi_helper.c | 116 ++------------------------------- sound/pci/hda/hda_generic.c | 140 ++++++++++++++++++++++++++++++++++++++++ sound/pci/hda/hda_generic.h | 16 +++++ 3 files changed, 162 insertions(+), 110 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/dell_wmi_helper.c b/sound/pci/hda/dell_wmi_helper.c index 1b48a8c19d28..8a7dbd1a7fbf 100644 --- a/sound/pci/hda/dell_wmi_helper.c +++ b/sound/pci/hda/dell_wmi_helper.c @@ -6,111 +6,18 @@ #if IS_ENABLED(CONFIG_DELL_LAPTOP) #include -enum { - MICMUTE_LED_ON, - MICMUTE_LED_OFF, - MICMUTE_LED_FOLLOW_CAPTURE, - MICMUTE_LED_FOLLOW_MUTE, -}; - -static int dell_led_mode = MICMUTE_LED_FOLLOW_MUTE; -static int dell_capture; -static int dell_led_value; static int (*dell_micmute_led_set_func)(int); -static void (*dell_old_cap_hook)(struct hda_codec *, - struct snd_kcontrol *, - struct snd_ctl_elem_value *); - -static void call_micmute_led_update(void) -{ - int val; - - switch (dell_led_mode) { - case MICMUTE_LED_ON: - val = 1; - break; - case MICMUTE_LED_OFF: - val = 0; - break; - case MICMUTE_LED_FOLLOW_CAPTURE: - val = dell_capture; - break; - case MICMUTE_LED_FOLLOW_MUTE: - default: - val = !dell_capture; - break; - } - - if (val == dell_led_value) - return; - dell_led_value = val; - dell_micmute_led_set_func(dell_led_value); -} - -static void update_dell_wmi_micmute_led(struct hda_codec *codec, - struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - if (dell_old_cap_hook) - dell_old_cap_hook(codec, kcontrol, ucontrol); - - if (!ucontrol || !dell_micmute_led_set_func) - return; - if (strcmp("Capture Switch", ucontrol->id.name) == 0 && ucontrol->id.index == 0) { - /* TODO: How do I verify if it's a mono or stereo here? */ - dell_capture = (ucontrol->value.integer.value[0] || - ucontrol->value.integer.value[1]); - call_micmute_led_update(); - } -} -static int dell_mic_mute_led_mode_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) +static void dell_micmute_update(struct hda_codec *codec) { - static const char * const texts[] = { - "On", "Off", "Follow Capture", "Follow Mute", - }; - - return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(texts), texts); -} + struct hda_gen_spec *spec = codec->spec; -static int dell_mic_mute_led_mode_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - ucontrol->value.enumerated.item[0] = dell_led_mode; - return 0; + dell_micmute_led_set_func(spec->micmute_led.led_value); } -static int dell_mic_mute_led_mode_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - unsigned int mode; - - mode = ucontrol->value.enumerated.item[0]; - if (mode > MICMUTE_LED_FOLLOW_MUTE) - mode = MICMUTE_LED_FOLLOW_MUTE; - if (mode == dell_led_mode) - return 0; - dell_led_mode = mode; - call_micmute_led_update(); - return 1; -} - -static const struct snd_kcontrol_new dell_mic_mute_mode_ctls[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Mic Mute-LED Mode", - .info = dell_mic_mute_led_mode_info, - .get = dell_mic_mute_led_mode_get, - .put = dell_mic_mute_led_mode_put, - }, - {} -}; - static void alc_fixup_dell_wmi(struct hda_codec *codec, const struct hda_fixup *fix, int action) { - struct alc_spec *spec = codec->spec; bool removefunc = false; if (action == HDA_FIXUP_ACT_PROBE) { @@ -121,25 +28,14 @@ static void alc_fixup_dell_wmi(struct hda_codec *codec, return; } - removefunc = true; - if (dell_micmute_led_set_func(false) >= 0) { - dell_led_value = 0; - if (spec->gen.num_adc_nids > 1 && !spec->gen.dyn_adc_switch) - codec_dbg(codec, "Skipping micmute LED control due to several ADCs"); - else { - dell_old_cap_hook = spec->gen.cap_sync_hook; - spec->gen.cap_sync_hook = update_dell_wmi_micmute_led; - removefunc = false; - add_mixer(spec, dell_mic_mute_mode_ctls); - } - } - + removefunc = (dell_micmute_led_set_func(false) < 0) || + (snd_hda_gen_add_micmute_led(codec, + dell_micmute_update) <= 0); } if (dell_micmute_led_set_func && (action == HDA_FIXUP_ACT_FREE || removefunc)) { symbol_put(dell_micmute_led_set); dell_micmute_led_set_func = NULL; - dell_old_cap_hook = NULL; } } diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index db773e219aaa..cdce9ce6b901 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c @@ -3899,6 +3899,146 @@ static int parse_mic_boost(struct hda_codec *codec) return 0; } +/* + * mic mute LED hook helpers + */ +enum { + MICMUTE_LED_ON, + MICMUTE_LED_OFF, + MICMUTE_LED_FOLLOW_CAPTURE, + MICMUTE_LED_FOLLOW_MUTE, +}; + +static void call_micmute_led_update(struct hda_codec *codec) +{ + struct hda_gen_spec *spec = codec->spec; + unsigned int val; + + switch (spec->micmute_led.led_mode) { + case MICMUTE_LED_ON: + val = 1; + break; + case MICMUTE_LED_OFF: + val = 0; + break; + case MICMUTE_LED_FOLLOW_CAPTURE: + val = spec->micmute_led.capture; + break; + case MICMUTE_LED_FOLLOW_MUTE: + default: + val = !spec->micmute_led.capture; + break; + } + + if (val == spec->micmute_led.led_value) + return; + spec->micmute_led.led_value = val; + if (spec->micmute_led.update) + spec->micmute_led.update(codec); +} + +static void update_micmute_led(struct hda_codec *codec, + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct hda_gen_spec *spec = codec->spec; + + if (spec->micmute_led.old_hook) + spec->micmute_led.old_hook(codec, kcontrol, ucontrol); + + if (!ucontrol) + return; + if (!strcmp("Capture Switch", ucontrol->id.name) && + !ucontrol->id.index) { + /* TODO: How do I verify if it's a mono or stereo here? */ + spec->micmute_led.capture = (ucontrol->value.integer.value[0] || + ucontrol->value.integer.value[1]); + call_micmute_led_update(codec); + } +} + +static int micmute_led_mode_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + static const char * const texts[] = { + "On", "Off", "Follow Capture", "Follow Mute", + }; + + return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(texts), texts); +} + +static int micmute_led_mode_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + struct hda_gen_spec *spec = codec->spec; + + ucontrol->value.enumerated.item[0] = spec->micmute_led.led_mode; + return 0; +} + +static int micmute_led_mode_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + struct hda_gen_spec *spec = codec->spec; + unsigned int mode; + + mode = ucontrol->value.enumerated.item[0]; + if (mode > MICMUTE_LED_FOLLOW_MUTE) + mode = MICMUTE_LED_FOLLOW_MUTE; + if (mode == spec->micmute_led.led_mode) + return 0; + spec->micmute_led.led_mode = mode; + call_micmute_led_update(codec); + return 1; +} + +static const struct snd_kcontrol_new micmute_led_mode_ctl = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Mic Mute-LED Mode", + .info = micmute_led_mode_info, + .get = micmute_led_mode_get, + .put = micmute_led_mode_put, +}; + +/** + * snd_hda_gen_add_micmute_led - helper for setting up mic mute LED hook + * @codec: the HDA codec + * @hook: the callback for updating LED + * + * Called from the codec drivers for offering the mic mute LED controls. + * Only valid for a single ADC (or a single input). When established, it + * sets up cap_sync_hook and triggers the callback at each time when the + * capture mixer switch changes. The callback is supposed to update the LED + * accordingly. + * + * Returns 1 if the hook is established, 0 if skipped (no valid config), or + * a negative error code. + */ +int snd_hda_gen_add_micmute_led(struct hda_codec *codec, + void (*hook)(struct hda_codec *)) +{ + struct hda_gen_spec *spec = codec->spec; + + if (spec->num_adc_nids > 1 && !spec->dyn_adc_switch) { + codec_dbg(codec, + "Skipping micmute LED control due to several ADCs"); + return 0; + } + + spec->micmute_led.led_mode = MICMUTE_LED_FOLLOW_MUTE; + spec->micmute_led.capture = 0; + spec->micmute_led.led_value = 0; + spec->micmute_led.old_hook = spec->cap_sync_hook; + spec->micmute_led.update = hook; + spec->cap_sync_hook = update_micmute_led; + if (!snd_hda_gen_add_kctl(spec, NULL, &micmute_led_mode_ctl)) + return -ENOMEM; + return 1; +} +EXPORT_SYMBOL_GPL(snd_hda_gen_add_micmute_led); + /* * parse digital I/Os and set up NIDs in BIOS auto-parse mode */ diff --git a/sound/pci/hda/hda_generic.h b/sound/pci/hda/hda_generic.h index 61772317de46..10123664fa61 100644 --- a/sound/pci/hda/hda_generic.h +++ b/sound/pci/hda/hda_generic.h @@ -86,6 +86,16 @@ struct badness_table { extern const struct badness_table hda_main_out_badness; extern const struct badness_table hda_extra_out_badness; +struct hda_micmute_hook { + unsigned int led_mode; + unsigned int capture; + unsigned int led_value; + void (*update)(struct hda_codec *codec); + void (*old_hook)(struct hda_codec *codec, + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol); +}; + struct hda_gen_spec { char stream_name_analog[32]; /* analog PCM stream */ const struct hda_pcm_stream *stream_analog_playback; @@ -276,6 +286,9 @@ struct hda_gen_spec { struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); + /* mic mute LED hook; called via cap_sync_hook */ + struct hda_micmute_hook micmute_led; + /* PCM hooks */ void (*pcm_playback_hook)(struct hda_pcm_stream *hinfo, struct hda_codec *codec, @@ -342,4 +355,7 @@ unsigned int snd_hda_gen_path_power_filter(struct hda_codec *codec, void snd_hda_gen_stream_pm(struct hda_codec *codec, hda_nid_t nid, bool on); int snd_hda_gen_fix_pin_power(struct hda_codec *codec, hda_nid_t pin); +int snd_hda_gen_add_micmute_led(struct hda_codec *codec, + void (*hook)(struct hda_codec *)); + #endif /* __SOUND_HDA_GENERIC_H */ -- cgit v1.2.3 From 69b2c6d7c0204e68185b694f9cfcb8f2636fed5d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 18 Jun 2018 17:28:45 +0200 Subject: ALSA: hda - Use the common helper for thinkpad_acpi mic mute LED handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the new common helper for setting up and controlling the mic mute LED over thinkpad_acpi. This also provides a new mixer enum "Mic Mute-LED Mode" (that was present only for Dell models), which allows user to choose the mic mute LED behavior. For example, if you want the mic mute LED turned on only while mic is on, choose "Follow Capture" there. Tested-by: Pali Rohár Signed-off-by: Takashi Iwai --- sound/pci/hda/thinkpad_helper.c | 27 ++++++++------------------- 1 file changed, 8 insertions(+), 19 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/thinkpad_helper.c b/sound/pci/hda/thinkpad_helper.c index 65bb3ac6af4c..97f49b751e6e 100644 --- a/sound/pci/hda/thinkpad_helper.c +++ b/sound/pci/hda/thinkpad_helper.c @@ -27,17 +27,11 @@ static void update_tpacpi_mute_led(void *private_data, int enabled) led_set_func(TPACPI_LED_MUTE, !enabled); } -static void update_tpacpi_micmute_led(struct hda_codec *codec, - struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) +static void update_tpacpi_micmute(struct hda_codec *codec) { - if (!ucontrol || !led_set_func) - return; - if (strcmp("Capture Switch", ucontrol->id.name) == 0 && ucontrol->id.index == 0) { - /* TODO: How do I verify if it's a mono or stereo here? */ - bool val = ucontrol->value.integer.value[0] || ucontrol->value.integer.value[1]; - led_set_func(TPACPI_LED_MICMUTE, !val); - } + struct hda_gen_spec *spec = codec->spec; + + led_set_func(TPACPI_LED_MICMUTE, spec->micmute_led.led_value); } static void hda_fixup_thinkpad_acpi(struct hda_codec *codec, @@ -63,15 +57,10 @@ static void hda_fixup_thinkpad_acpi(struct hda_codec *codec, spec->vmaster_mute.hook = update_tpacpi_mute_led; removefunc = false; } - if (led_set_func(TPACPI_LED_MICMUTE, false) >= 0) { - if (spec->num_adc_nids > 1 && !spec->dyn_adc_switch) - codec_dbg(codec, - "Skipping micmute LED control due to several ADCs"); - else { - spec->cap_sync_hook = update_tpacpi_micmute_led; - removefunc = false; - } - } + if (led_set_func(TPACPI_LED_MICMUTE, false) >= 0 && + snd_hda_gen_add_micmute_led(codec, + update_tpacpi_micmute) > 0) + removefunc = false; } if (led_set_func && (action == HDA_FIXUP_ACT_FREE || removefunc)) { -- cgit v1.2.3 From d03abecab5b4f4fa533f5971a4b205d05e9a4bc3 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 19 Jun 2018 12:29:13 +0200 Subject: ALSA: hda/realtek - Use the mic-mute LED helper for HP and others Similar as the previous commit, convert to use the common helper for controlling the mic mute LED for HP and other machines in the Realtek codec driver, too. This will give the mic mute LED enum as gratis. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 49 ++++++++++++++++--------------------------- 1 file changed, 18 insertions(+), 31 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 487ceb9fd038..32a7a72033ae 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -3718,16 +3718,12 @@ static void alc_fixup_gpio_mute_hook(void *private_data, int enabled) } /* turn on/off mic-mute LED via GPIO per capture hook */ -static void alc_fixup_gpio_mic_mute_hook(struct hda_codec *codec, - struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) +static void alc_gpio_micmute_update(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; - if (ucontrol) - alc_update_gpio_led(codec, spec->gpio_mic_led_mask, - ucontrol->value.integer.value[0] || - ucontrol->value.integer.value[1]); + alc_update_gpio_led(codec, spec->gpio_mic_led_mask, + spec->gen.micmute_led.led_value); } static void alc269_fixup_hp_gpio_led(struct hda_codec *codec, @@ -3742,12 +3738,12 @@ static void alc269_fixup_hp_gpio_led(struct hda_codec *codec, if (action == HDA_FIXUP_ACT_PRE_PROBE) { spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook; - spec->gen.cap_sync_hook = alc_fixup_gpio_mic_mute_hook; spec->gpio_led = 0; spec->mute_led_polarity = 0; spec->gpio_mute_led_mask = 0x08; spec->gpio_mic_led_mask = 0x10; snd_hda_add_verbs(codec, gpio_init); + snd_hda_gen_add_micmute_led(codec, alc_gpio_micmute_update); } } @@ -3763,39 +3759,30 @@ static void alc286_fixup_hp_gpio_led(struct hda_codec *codec, if (action == HDA_FIXUP_ACT_PRE_PROBE) { spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook; - spec->gen.cap_sync_hook = alc_fixup_gpio_mic_mute_hook; spec->gpio_led = 0; spec->mute_led_polarity = 0; spec->gpio_mute_led_mask = 0x02; spec->gpio_mic_led_mask = 0x20; snd_hda_add_verbs(codec, gpio_init); + snd_hda_gen_add_micmute_led(codec, alc_gpio_micmute_update); } } /* turn on/off mic-mute LED per capture hook */ -static void alc269_fixup_hp_cap_mic_mute_hook(struct hda_codec *codec, - struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) +static void alc_cap_micmute_update(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; - unsigned int pinval, enable, disable; + unsigned int pinval; + if (!spec->cap_mute_led_nid) + return; pinval = snd_hda_codec_get_pin_target(codec, spec->cap_mute_led_nid); pinval &= ~AC_PINCTL_VREFEN; - enable = pinval | AC_PINCTL_VREF_80; - disable = pinval | AC_PINCTL_VREF_HIZ; - - if (!ucontrol) - return; - - if (ucontrol->value.integer.value[0] || - ucontrol->value.integer.value[1]) - pinval = disable; + if (spec->gen.micmute_led.led_value) + pinval |= AC_PINCTL_VREF_80; else - pinval = enable; - - if (spec->cap_mute_led_nid) - snd_hda_set_pin_ctl_cache(codec, spec->cap_mute_led_nid, pinval); + pinval |= AC_PINCTL_VREF_HIZ; + snd_hda_set_pin_ctl_cache(codec, spec->cap_mute_led_nid, pinval); } static void alc269_fixup_hp_gpio_mic1_led(struct hda_codec *codec, @@ -3810,12 +3797,12 @@ static void alc269_fixup_hp_gpio_mic1_led(struct hda_codec *codec, if (action == HDA_FIXUP_ACT_PRE_PROBE) { spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook; - spec->gen.cap_sync_hook = alc269_fixup_hp_cap_mic_mute_hook; spec->gpio_led = 0; spec->mute_led_polarity = 0; spec->gpio_mute_led_mask = 0x08; spec->cap_mute_led_nid = 0x18; snd_hda_add_verbs(codec, gpio_init); + snd_hda_gen_add_micmute_led(codec, alc_cap_micmute_update); codec->power_filter = led_power_filter; } } @@ -3833,12 +3820,12 @@ static void alc280_fixup_hp_gpio4(struct hda_codec *codec, if (action == HDA_FIXUP_ACT_PRE_PROBE) { spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook; - spec->gen.cap_sync_hook = alc269_fixup_hp_cap_mic_mute_hook; spec->gpio_led = 0; spec->mute_led_polarity = 0; spec->gpio_mute_led_mask = 0x08; spec->cap_mute_led_nid = 0x18; snd_hda_add_verbs(codec, gpio_init); + snd_hda_gen_add_micmute_led(codec, alc_cap_micmute_update); codec->power_filter = led_power_filter; } } @@ -3915,11 +3902,11 @@ static void alc280_fixup_hp_gpio2_mic_hotkey(struct hda_codec *codec, gpio2_mic_hotkey_event); spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook; - spec->gen.cap_sync_hook = alc_fixup_gpio_mic_mute_hook; spec->gpio_led = 0; spec->mute_led_polarity = 0; spec->gpio_mute_led_mask = 0x08; spec->gpio_mic_led_mask = 0x10; + snd_hda_gen_add_micmute_led(codec, alc_gpio_micmute_update); return; } @@ -3957,10 +3944,10 @@ static void alc233_fixup_lenovo_line2_mic_hotkey(struct hda_codec *codec, snd_hda_jack_detect_enable_callback(codec, 0x1b, gpio2_mic_hotkey_event); - spec->gen.cap_sync_hook = alc_fixup_gpio_mic_mute_hook; spec->gpio_led = 0; spec->mute_led_polarity = 0; spec->gpio_mic_led_mask = 0x04; + snd_hda_gen_add_micmute_led(codec, alc_gpio_micmute_update); return; } @@ -3988,10 +3975,10 @@ static void alc269_fixup_hp_line1_mic1_led(struct hda_codec *codec, if (action == HDA_FIXUP_ACT_PRE_PROBE) { spec->gen.vmaster_mute.hook = alc269_fixup_mic_mute_hook; - spec->gen.cap_sync_hook = alc269_fixup_hp_cap_mic_mute_hook; spec->mute_led_polarity = 0; spec->mute_led_nid = 0x1a; spec->cap_mute_led_nid = 0x18; + snd_hda_gen_add_micmute_led(codec, alc_cap_micmute_update); spec->gen.vmaster_mute_enum = 1; codec->power_filter = led_power_filter; } -- cgit v1.2.3 From 184e302b46c94bfb1d53fe3d4c925a45a6990430 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 19 Jun 2018 12:36:36 +0200 Subject: ALSA: hda/conexant - Use the mic-mute LED helper Convert to use the common helper for controlling the mic mute LED for HP laptops, just as we've done for Realtek codecs. This will give the mic mute LED enum as gratis. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_conexant.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index e7fcfc3b8885..a9fd0572d526 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -695,16 +695,12 @@ static void cxt_fixup_gpio_mute_hook(void *private_data, int enabled) } /* turn on/off mic-mute LED via GPIO per capture hook */ -static void cxt_fixup_gpio_mic_mute_hook(struct hda_codec *codec, - struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) +static void cxt_gpio_micmute_update(struct hda_codec *codec) { struct conexant_spec *spec = codec->spec; - if (ucontrol) - cxt_update_gpio_led(codec, spec->gpio_mic_led_mask, - ucontrol->value.integer.value[0] || - ucontrol->value.integer.value[1]); + cxt_update_gpio_led(codec, spec->gpio_mic_led_mask, + spec->gen.micmute_led.led_value); } @@ -721,11 +717,11 @@ static void cxt_fixup_mute_led_gpio(struct hda_codec *codec, if (action == HDA_FIXUP_ACT_PRE_PROBE) { spec->gen.vmaster_mute.hook = cxt_fixup_gpio_mute_hook; - spec->gen.cap_sync_hook = cxt_fixup_gpio_mic_mute_hook; spec->gpio_led = 0; spec->mute_led_polarity = 0; spec->gpio_mute_led_mask = 0x01; spec->gpio_mic_led_mask = 0x02; + snd_hda_gen_add_micmute_led(codec, cxt_gpio_micmute_update); } snd_hda_add_verbs(codec, gpio_init); if (spec->gpio_led) -- cgit v1.2.3 From c647f806b8c227de05f7f91b0ba8450b58cb3dfe Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 19 Jun 2018 12:42:03 +0200 Subject: ALSA: hda - Allow multiple ADCs for mic mute LED controls Instead of refusing, allow the configuration with the multiple ADCs (thus multiple capture switches) for enabling the mic mute LED. This has been done for Sigmatel/IDT codecs, and we treat the OR-ed values from all capture switches as the boolean condition. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_generic.c | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index cdce9ce6b901..942f96e184b6 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c @@ -3922,7 +3922,7 @@ static void call_micmute_led_update(struct hda_codec *codec) val = 0; break; case MICMUTE_LED_FOLLOW_CAPTURE: - val = spec->micmute_led.capture; + val = !!spec->micmute_led.capture; break; case MICMUTE_LED_FOLLOW_MUTE: default: @@ -3942,17 +3942,21 @@ static void update_micmute_led(struct hda_codec *codec, struct snd_ctl_elem_value *ucontrol) { struct hda_gen_spec *spec = codec->spec; + unsigned int mask; if (spec->micmute_led.old_hook) spec->micmute_led.old_hook(codec, kcontrol, ucontrol); if (!ucontrol) return; - if (!strcmp("Capture Switch", ucontrol->id.name) && - !ucontrol->id.index) { + mask = 1U << snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); + if (!strcmp("Capture Switch", ucontrol->id.name)) { /* TODO: How do I verify if it's a mono or stereo here? */ - spec->micmute_led.capture = (ucontrol->value.integer.value[0] || - ucontrol->value.integer.value[1]); + if (ucontrol->value.integer.value[0] || + ucontrol->value.integer.value[1]) + spec->micmute_led.capture |= mask; + else + spec->micmute_led.capture &= ~mask; call_micmute_led_update(codec); } } @@ -4008,25 +4012,17 @@ static const struct snd_kcontrol_new micmute_led_mode_ctl = { * @hook: the callback for updating LED * * Called from the codec drivers for offering the mic mute LED controls. - * Only valid for a single ADC (or a single input). When established, it - * sets up cap_sync_hook and triggers the callback at each time when the - * capture mixer switch changes. The callback is supposed to update the LED - * accordingly. + * When established, it sets up cap_sync_hook and triggers the callback at + * each time when the capture mixer switch changes. The callback is supposed + * to update the LED accordingly. * - * Returns 1 if the hook is established, 0 if skipped (no valid config), or - * a negative error code. + * Returns 0 if the hook is established or a negative error code. */ int snd_hda_gen_add_micmute_led(struct hda_codec *codec, void (*hook)(struct hda_codec *)) { struct hda_gen_spec *spec = codec->spec; - if (spec->num_adc_nids > 1 && !spec->dyn_adc_switch) { - codec_dbg(codec, - "Skipping micmute LED control due to several ADCs"); - return 0; - } - spec->micmute_led.led_mode = MICMUTE_LED_FOLLOW_MUTE; spec->micmute_led.capture = 0; spec->micmute_led.led_value = 0; @@ -4035,7 +4031,7 @@ int snd_hda_gen_add_micmute_led(struct hda_codec *codec, spec->cap_sync_hook = update_micmute_led; if (!snd_hda_gen_add_kctl(spec, NULL, &micmute_led_mode_ctl)) return -ENOMEM; - return 1; + return 0; } EXPORT_SYMBOL_GPL(snd_hda_gen_add_micmute_led); -- cgit v1.2.3 From 3bf29db731ce22480de748464031b4447b248c0f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 19 Jun 2018 12:44:35 +0200 Subject: ALSA: hda/sigmatel - Use common helper for mic mute LED To simplify the code and to get the mic-mute LED behavior control, use the new helper function for controlling the mic mute LED instead of open-codes. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_sigmatel.c | 31 ++++++------------------------- 1 file changed, 6 insertions(+), 25 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 63d15b545b33..046705b4691a 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -332,33 +332,15 @@ static void stac_gpio_set(struct hda_codec *codec, unsigned int mask, } /* hook for controlling mic-mute LED GPIO */ -static void stac_capture_led_hook(struct hda_codec *codec, - struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) +static void stac_capture_led_update(struct hda_codec *codec) { struct sigmatel_spec *spec = codec->spec; - unsigned int mask; - bool cur_mute, prev_mute; - if (!kcontrol || !ucontrol) - return; - - mask = 1U << snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - prev_mute = !spec->mic_enabled; - if (ucontrol->value.integer.value[0] || - ucontrol->value.integer.value[1]) - spec->mic_enabled |= mask; + if (spec->gen.micmute_led.led_value) + spec->gpio_data |= spec->mic_mute_led_gpio; else - spec->mic_enabled &= ~mask; - cur_mute = !spec->mic_enabled; - if (cur_mute != prev_mute) { - if (cur_mute) - spec->gpio_data |= spec->mic_mute_led_gpio; - else - spec->gpio_data &= ~spec->mic_mute_led_gpio; - stac_gpio_set(codec, spec->gpio_mask, - spec->gpio_dir, spec->gpio_data); - } + spec->gpio_data &= ~spec->mic_mute_led_gpio; + stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, spec->gpio_data); } static int stac_vrefout_set(struct hda_codec *codec, @@ -4656,8 +4638,7 @@ static void stac_setup_gpio(struct hda_codec *codec) spec->gpio_dir |= spec->mic_mute_led_gpio; spec->mic_enabled = 0; spec->gpio_data |= spec->mic_mute_led_gpio; - - spec->gen.cap_sync_hook = stac_capture_led_hook; + snd_hda_gen_add_micmute_led(codec, stac_capture_led_update); } } -- cgit v1.2.3 From 0bed2aa3ac5cbbd0b89bf5e94f165e2ef18180ad Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 19 Jun 2018 12:45:53 +0200 Subject: ALSA: hda - Sanity check of unexpected cap_sync_hook override There are a couple of places setting cap_sync_hook in the codec drivers, and they just overwrite the value. Add a sanity check via WARN_ON() in case if an old non-NULL value is overridden and forgotten. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_conexant.c | 1 + sound/pci/hda/patch_realtek.c | 1 + 2 files changed, 2 insertions(+) (limited to 'sound') diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index a9fd0572d526..b7339cb5c45b 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -343,6 +343,7 @@ static void cxt_fixup_headphone_mic(struct hda_codec *codec, snd_hdac_regmap_add_vendor_verb(&codec->core, 0x410); break; case HDA_FIXUP_ACT_PROBE: + WARN_ON(spec->gen.cap_sync_hook); spec->gen.cap_sync_hook = cxt_update_headset_mode_hook; spec->gen.automute_hook = cxt_update_headset_mode; break; diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 32a7a72033ae..d9461eebcfdf 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4828,6 +4828,7 @@ static void alc_probe_headset_mode(struct hda_codec *codec) spec->headphone_mic_pin = cfg->inputs[i].pin; } + WARN_ON(spec->gen.cap_sync_hook); spec->gen.cap_sync_hook = alc_update_headset_mode_hook; spec->gen.automute_hook = alc_update_headset_mode; spec->gen.hp_automute_hook = alc_update_headset_jack_cb; -- cgit v1.2.3 From 1bce62a6e0dd85c15cbab36a0f7b9d4766cef18e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 19 Jun 2018 23:15:59 +0200 Subject: ALSA: hda/realtek - Simplify alc269_fixup_hp_line1_mic1_led() alc269_fixup_hp_line1_mic1_led() can be simplified more with the existing helper code. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index d9461eebcfdf..7934c5df4d80 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -3973,14 +3973,10 @@ static void alc269_fixup_hp_line1_mic1_led(struct hda_codec *codec, { struct alc_spec *spec = codec->spec; + alc269_fixup_hp_mute_led_micx(codec, fix, action, 0x1a); if (action == HDA_FIXUP_ACT_PRE_PROBE) { - spec->gen.vmaster_mute.hook = alc269_fixup_mic_mute_hook; - spec->mute_led_polarity = 0; - spec->mute_led_nid = 0x1a; spec->cap_mute_led_nid = 0x18; snd_hda_gen_add_micmute_led(codec, alc_cap_micmute_update); - spec->gen.vmaster_mute_enum = 1; - codec->power_filter = led_power_filter; } } -- cgit v1.2.3 From 2225a3e6af78e605119e0f178ae957d860882b1d Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Fri, 22 Jun 2018 21:28:34 +0200 Subject: ALSA: ac97: add codecs devicetree binding Add a devicetree binding for codecs. This is especially useful if the AC97 bitclk clock is provided by the codec, as it has to be described in the devicetree description for the ac97 bus code to aquire it. Signed-off-by: Robert Jarzmik Signed-off-by: Takashi Iwai --- sound/ac97/bus.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'sound') diff --git a/sound/ac97/bus.c b/sound/ac97/bus.c index 31f858eceffc..7a0dfca03a57 100644 --- a/sound/ac97/bus.c +++ b/sound/ac97/bus.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -68,6 +69,27 @@ ac97_codec_find(struct ac97_controller *ac97_ctrl, unsigned int codec_num) return ac97_ctrl->codecs[codec_num]; } +static struct device_node * +ac97_of_get_child_device(struct ac97_controller *ac97_ctrl, int idx, + unsigned int vendor_id) +{ + struct device_node *node; + u32 reg; + char compat[] = "ac97,0000,0000"; + + snprintf(compat, sizeof(compat), "ac97,%04x,%04x", + vendor_id >> 16, vendor_id & 0xffff); + + for_each_child_of_node(ac97_ctrl->parent->of_node, node) { + if ((idx != of_property_read_u32(node, "reg", ®)) || + !of_device_is_compatible(node, compat)) + continue; + return of_node_get(node); + } + + return NULL; +} + static void ac97_codec_release(struct device *dev) { struct ac97_codec_device *adev; @@ -76,6 +98,7 @@ static void ac97_codec_release(struct device *dev) adev = to_ac97_device(dev); ac97_ctrl = adev->ac97_ctrl; ac97_ctrl->codecs[adev->num] = NULL; + of_node_put(dev->of_node); kfree(adev); } @@ -98,6 +121,8 @@ static int ac97_codec_add(struct ac97_controller *ac97_ctrl, int idx, device_initialize(&codec->dev); dev_set_name(&codec->dev, "%s:%u", dev_name(ac97_ctrl->parent), idx); + codec->dev.of_node = ac97_of_get_child_device(ac97_ctrl, idx, + vendor_id); ret = device_add(&codec->dev); if (ret) @@ -105,6 +130,7 @@ static int ac97_codec_add(struct ac97_controller *ac97_ctrl, int idx, return 0; err_free_codec: + of_node_put(codec->dev.of_node); put_device(&codec->dev); kfree(codec); ac97_ctrl->codecs[idx] = NULL; -- cgit v1.2.3 From 1c76aa5fb48d8357f38fb2f1d2cef742a617d695 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 21 Jun 2018 16:37:54 +0200 Subject: ALSA: hda/realtek - Allow skipping spec->init_amp detection Some devices have the overrides of spec->init_amp at HDA_FIXUP_ACT_PROBE just because alc_ssid_check() gives the false-positive values from the SSID. For more consistent behavior, define the logic in the following way: - Define ALC_INIT_UNDEFINED as the default value before calling alc_ssid_check() - Each fixup may set up spec->init_amp with another value at HDA_FIXUP_ACT_PRE_PROBE - At detection, check whether spec->init_amp is ALC_INIT_UNDEFINED or not; if it's different, we skip the detection Also, it turned out that ASUS TX300 requires the spec->init_amp override, too; currently it ignores the GPIO bits implicitly by its static init verb, but this will be changed in the later patchset. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 44 +++++++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 23 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 7934c5df4d80..1f054e5ae2b3 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -43,6 +43,7 @@ /* extra amp-initialization sequence types */ enum { + ALC_INIT_UNDEFINED, ALC_INIT_NONE, ALC_INIT_DEFAULT, ALC_INIT_GPIO1, @@ -656,20 +657,22 @@ do_sku: * 7~6 : Reserved */ tmp = (ass & 0x38) >> 3; /* external Amp control */ - switch (tmp) { - case 1: - spec->init_amp = ALC_INIT_GPIO1; - break; - case 3: - spec->init_amp = ALC_INIT_GPIO2; - break; - case 7: - spec->init_amp = ALC_INIT_GPIO3; - break; - case 5: - default: - spec->init_amp = ALC_INIT_DEFAULT; - break; + if (spec->init_amp == ALC_INIT_UNDEFINED) { + switch (tmp) { + case 1: + spec->init_amp = ALC_INIT_GPIO1; + break; + case 3: + spec->init_amp = ALC_INIT_GPIO2; + break; + case 7: + spec->init_amp = ALC_INIT_GPIO3; + break; + case 5: + default: + spec->init_amp = ALC_INIT_DEFAULT; + break; + } } /* is laptop or Desktop and enable the function "Mute internal speaker @@ -1589,8 +1592,6 @@ static void alc260_fixup_kn1(struct hda_codec *codec, switch (action) { case HDA_FIXUP_ACT_PRE_PROBE: snd_hda_apply_pincfgs(codec, pincfgs); - break; - case HDA_FIXUP_ACT_PROBE: spec->init_amp = ALC_INIT_NONE; break; } @@ -1600,7 +1601,7 @@ static void alc260_fixup_fsc_s7020(struct hda_codec *codec, const struct hda_fixup *fix, int action) { struct alc_spec *spec = codec->spec; - if (action == HDA_FIXUP_ACT_PROBE) + if (action == HDA_FIXUP_ACT_PRE_PROBE) spec->init_amp = ALC_INIT_NONE; } @@ -3892,6 +3893,7 @@ static void alc280_fixup_hp_gpio2_mic_hotkey(struct hda_codec *codec, struct alc_spec *spec = codec->spec; if (action == HDA_FIXUP_ACT_PRE_PROBE) { + spec->init_amp = ALC_INIT_DEFAULT; if (alc_register_micmute_input_device(codec) != 0) return; @@ -3914,9 +3916,6 @@ static void alc280_fixup_hp_gpio2_mic_hotkey(struct hda_codec *codec, return; switch (action) { - case HDA_FIXUP_ACT_PROBE: - spec->init_amp = ALC_INIT_DEFAULT; - break; case HDA_FIXUP_ACT_FREE: input_unregister_device(spec->kb_dev); spec->kb_dev = NULL; @@ -3937,6 +3936,7 @@ static void alc233_fixup_lenovo_line2_mic_hotkey(struct hda_codec *codec, struct alc_spec *spec = codec->spec; if (action == HDA_FIXUP_ACT_PRE_PROBE) { + spec->init_amp = ALC_INIT_DEFAULT; if (alc_register_micmute_input_device(codec) != 0) return; @@ -3955,9 +3955,6 @@ static void alc233_fixup_lenovo_line2_mic_hotkey(struct hda_codec *codec, return; switch (action) { - case HDA_FIXUP_ACT_PROBE: - spec->init_amp = ALC_INIT_DEFAULT; - break; case HDA_FIXUP_ACT_FREE: input_unregister_device(spec->kb_dev); spec->kb_dev = NULL; @@ -5227,6 +5224,7 @@ static void alc282_fixup_asus_tx300(struct hda_codec *codec, switch (action) { case HDA_FIXUP_ACT_PRE_PROBE: + spec->init_amp = ALC_INIT_DEFAULT; snd_hda_add_verbs(codec, gpio2_verbs); snd_hda_apply_pincfgs(codec, dock_pins); spec->gen.auto_mute_via_amp = 1; -- cgit v1.2.3 From 5579cd6f6629bc1e09b3b2d13ab7a1ed371c5ac2 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 19 Jun 2018 22:22:41 +0200 Subject: ALSA: hda/realtek - Manage GPIO bits commonly Currently the GPIO bits are managed by individual verbs in some cases while toggled dynamically in other cases. For simplifying the GPIO management, define the GPIO mask, dir and data bits in alc_spec fields, and refer to / set them consistently from all places. As a first step, along with the definition of the new gpio_* fields, this patch replaces the static verbs that are used at initialization and fixups with the common helper functions. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 129 ++++++++++++++++++++++++++---------------- 1 file changed, 81 insertions(+), 48 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 1f054e5ae2b3..489075b23652 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -46,9 +46,6 @@ enum { ALC_INIT_UNDEFINED, ALC_INIT_NONE, ALC_INIT_DEFAULT, - ALC_INIT_GPIO1, - ALC_INIT_GPIO2, - ALC_INIT_GPIO3, }; enum { @@ -93,6 +90,11 @@ struct alc_spec { struct alc_customize_define cdefine; unsigned int parse_flags; /* flag for snd_hda_parse_pin_defcfg() */ + /* GPIO bits */ + unsigned int gpio_mask; + unsigned int gpio_dir; + unsigned int gpio_data; + /* mute LED for HP laptops, see alc269_fixup_mic_mute_hook() */ int mute_led_polarity; hda_nid_t mute_led_nid; @@ -220,27 +222,63 @@ static void add_mixer(struct alc_spec *spec, const struct snd_kcontrol_new *mix) /* * GPIO setup tables, used in initialization */ + /* Enable GPIO mask and set output */ -static const struct hda_verb alc_gpio1_init_verbs[] = { - {0x01, AC_VERB_SET_GPIO_MASK, 0x01}, - {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01}, - {0x01, AC_VERB_SET_GPIO_DATA, 0x01}, - { } -}; +static void alc_setup_gpio(struct hda_codec *codec, unsigned int mask) +{ + struct alc_spec *spec = codec->spec; -static const struct hda_verb alc_gpio2_init_verbs[] = { - {0x01, AC_VERB_SET_GPIO_MASK, 0x02}, - {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02}, - {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, - { } -}; + spec->gpio_mask |= mask; + spec->gpio_dir |= mask; + spec->gpio_data |= mask; +} -static const struct hda_verb alc_gpio3_init_verbs[] = { - {0x01, AC_VERB_SET_GPIO_MASK, 0x03}, - {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03}, - {0x01, AC_VERB_SET_GPIO_DATA, 0x03}, - { } -}; +static void alc_write_gpio_data(struct hda_codec *codec) +{ + struct alc_spec *spec = codec->spec; + + snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, + spec->gpio_data); +} + +static void alc_write_gpio(struct hda_codec *codec) +{ + struct alc_spec *spec = codec->spec; + + if (!spec->gpio_mask) + return; + + snd_hda_codec_write(codec, codec->core.afg, 0, + AC_VERB_SET_GPIO_MASK, spec->gpio_mask); + snd_hda_codec_write(codec, codec->core.afg, 0, + AC_VERB_SET_GPIO_DIRECTION, spec->gpio_dir); + alc_write_gpio_data(codec); +} + +static void alc_fixup_gpio(struct hda_codec *codec, int action, + unsigned int mask) +{ + if (action == HDA_FIXUP_ACT_PRE_PROBE) + alc_setup_gpio(codec, mask); +} + +static void alc_fixup_gpio1(struct hda_codec *codec, + const struct hda_fixup *fix, int action) +{ + alc_fixup_gpio(codec, action, 0x01); +} + +static void alc_fixup_gpio2(struct hda_codec *codec, + const struct hda_fixup *fix, int action) +{ + alc_fixup_gpio(codec, action, 0x02); +} + +static void alc_fixup_gpio3(struct hda_codec *codec, + const struct hda_fixup *fix, int action) +{ + alc_fixup_gpio(codec, action, 0x03); +} /* * Fix hardware PLL issue @@ -448,16 +486,8 @@ static void alc_auto_init_amp(struct hda_codec *codec, int type) { alc_fill_eapd_coef(codec); alc_auto_setup_eapd(codec, true); + alc_write_gpio(codec); switch (type) { - case ALC_INIT_GPIO1: - snd_hda_sequence_write(codec, alc_gpio1_init_verbs); - break; - case ALC_INIT_GPIO2: - snd_hda_sequence_write(codec, alc_gpio2_init_verbs); - break; - case ALC_INIT_GPIO3: - snd_hda_sequence_write(codec, alc_gpio3_init_verbs); - break; case ALC_INIT_DEFAULT: switch (codec->core.vendor_id) { case 0x10ec0260: @@ -660,13 +690,13 @@ do_sku: if (spec->init_amp == ALC_INIT_UNDEFINED) { switch (tmp) { case 1: - spec->init_amp = ALC_INIT_GPIO1; + alc_setup_gpio(codec, 0x01); break; case 3: - spec->init_amp = ALC_INIT_GPIO2; + alc_setup_gpio(codec, 0x02); break; case 7: - spec->init_amp = ALC_INIT_GPIO3; + alc_setup_gpio(codec, 0x03); break; case 5: default: @@ -1107,12 +1137,12 @@ static void alc880_fixup_vol_knob(struct hda_codec *codec, static const struct hda_fixup alc880_fixups[] = { [ALC880_FIXUP_GPIO1] = { - .type = HDA_FIXUP_VERBS, - .v.verbs = alc_gpio1_init_verbs, + .type = HDA_FIXUP_FUNC, + .v.func = alc_fixup_gpio1, }, [ALC880_FIXUP_GPIO2] = { - .type = HDA_FIXUP_VERBS, - .v.verbs = alc_gpio2_init_verbs, + .type = HDA_FIXUP_FUNC, + .v.func = alc_fixup_gpio2, }, [ALC880_FIXUP_MEDION_RIM] = { .type = HDA_FIXUP_VERBS, @@ -1565,7 +1595,7 @@ static void alc260_fixup_gpio1_toggle(struct hda_codec *codec, spec->gen.autocfg.hp_pins[0] = 0x0f; /* copy it for automute */ snd_hda_jack_detect_enable_callback(codec, 0x0f, snd_hda_gen_hp_automute); - snd_hda_add_verbs(codec, alc_gpio1_init_verbs); + alc_setup_gpio(codec, 0x01); } } @@ -1639,8 +1669,8 @@ static const struct hda_fixup alc260_fixups[] = { }, }, [ALC260_FIXUP_GPIO1] = { - .type = HDA_FIXUP_VERBS, - .v.verbs = alc_gpio1_init_verbs, + .type = HDA_FIXUP_FUNC, + .v.func = alc_fixup_gpio1, }, [ALC260_FIXUP_GPIO1_TOGGLE] = { .type = HDA_FIXUP_FUNC, @@ -2144,20 +2174,20 @@ static const struct hda_fixup alc882_fixups[] = { } }, [ALC882_FIXUP_GPIO1] = { - .type = HDA_FIXUP_VERBS, - .v.verbs = alc_gpio1_init_verbs, + .type = HDA_FIXUP_FUNC, + .v.func = alc_fixup_gpio1, }, [ALC882_FIXUP_GPIO2] = { - .type = HDA_FIXUP_VERBS, - .v.verbs = alc_gpio2_init_verbs, + .type = HDA_FIXUP_FUNC, + .v.func = alc_fixup_gpio2, }, [ALC882_FIXUP_GPIO3] = { - .type = HDA_FIXUP_VERBS, - .v.verbs = alc_gpio3_init_verbs, + .type = HDA_FIXUP_FUNC, + .v.func = alc_fixup_gpio3, }, [ALC882_FIXUP_ASUS_W2JC] = { - .type = HDA_FIXUP_VERBS, - .v.verbs = alc_gpio1_init_verbs, + .type = HDA_FIXUP_FUNC, + .v.func = alc_fixup_gpio1, .chained = true, .chain_id = ALC882_FIXUP_EAPD, }, @@ -5232,6 +5262,9 @@ static void alc282_fixup_asus_tx300(struct hda_codec *codec, snd_hda_jack_detect_enable_callback(codec, 0x1b, snd_hda_gen_hp_automute); break; + case HDA_FIXUP_ACT_PROBE: + spec->init_amp = ALC_INIT_DEFAULT; + break; case HDA_FIXUP_ACT_BUILD: /* this is a bit tricky; give more sane names for the main * (tablet) speaker and the dock speaker, respectively -- cgit v1.2.3 From aaf312de4eb915e5b45c65c2da7304bf34b5ab47 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 19 Jun 2018 22:28:22 +0200 Subject: ALSA: hda/realtek - Add GPIO data update helper For updating GPIO bits dynamically, provide a new helper, and use it from the alc260 automute hook. This helper will be used by other places in future, too. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 489075b23652..bd54d9e25440 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -241,6 +241,20 @@ static void alc_write_gpio_data(struct hda_codec *codec) spec->gpio_data); } +static void alc_update_gpio_data(struct hda_codec *codec, unsigned int mask, + bool on) +{ + struct alc_spec *spec = codec->spec; + unsigned int oldval = spec->gpio_data; + + if (on) + spec->gpio_data |= mask; + else + spec->gpio_data &= ~mask; + if (oldval != spec->gpio_data) + alc_write_gpio_data(codec); +} + static void alc_write_gpio(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; @@ -1577,8 +1591,8 @@ enum { static void alc260_gpio1_automute(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; - snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, - spec->gen.hp_jack_present); + + alc_update_gpio_data(codec, 0x01, spec->gen.hp_jack_present); } static void alc260_fixup_gpio1_toggle(struct hda_codec *codec, -- cgit v1.2.3 From d261eec80ca987a2415dd26f982ca25844e4497c Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 19 Jun 2018 22:32:29 +0200 Subject: ALSA: hda/realtek - Consolidate gpio_data and gpio_led Until now, two fields, gpio_data and gpio_led, coexist in alc_spec although basically both of them serve for the same purpose -- the GPIO data bits. This patch consolidates both usages and eliminates the superfluous gpio_led field. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 28 ++++------------------------ 1 file changed, 4 insertions(+), 24 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index bd54d9e25440..0db8329aa114 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -100,7 +100,6 @@ struct alc_spec { hda_nid_t mute_led_nid; hda_nid_t cap_mute_led_nid; - unsigned int gpio_led; /* used for alc269_fixup_hp_gpio_led() */ unsigned int gpio_mute_led_mask; unsigned int gpio_mic_led_mask; @@ -3497,9 +3496,8 @@ static int alc269_resume(struct hda_codec *codec) * suspend, and won't restore the data after resume, so we restore it * in the driver. */ - if (spec->gpio_led) - snd_hda_codec_write(codec, codec->core.afg, 0, AC_VERB_SET_GPIO_DATA, - spec->gpio_led); + if (spec->gpio_data) + alc_write_gpio_data(codec); if (spec->has_alc5505_dsp) alc5505_dsp_resume(codec); @@ -3739,18 +3737,10 @@ static void alc_update_gpio_led(struct hda_codec *codec, unsigned int mask, bool enabled) { struct alc_spec *spec = codec->spec; - unsigned int oldval = spec->gpio_led; if (spec->mute_led_polarity) enabled = !enabled; - - if (enabled) - spec->gpio_led &= ~mask; - else - spec->gpio_led |= mask; - if (spec->gpio_led != oldval) - snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, - spec->gpio_led); + alc_update_gpio_data(codec, mask, !enabled); /* muted -> LED on */ } /* turn on/off mute LED via GPIO per vmaster hook */ @@ -3783,7 +3773,6 @@ static void alc269_fixup_hp_gpio_led(struct hda_codec *codec, if (action == HDA_FIXUP_ACT_PRE_PROBE) { spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook; - spec->gpio_led = 0; spec->mute_led_polarity = 0; spec->gpio_mute_led_mask = 0x08; spec->gpio_mic_led_mask = 0x10; @@ -3804,7 +3793,6 @@ static void alc286_fixup_hp_gpio_led(struct hda_codec *codec, if (action == HDA_FIXUP_ACT_PRE_PROBE) { spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook; - spec->gpio_led = 0; spec->mute_led_polarity = 0; spec->gpio_mute_led_mask = 0x02; spec->gpio_mic_led_mask = 0x20; @@ -3842,7 +3830,6 @@ static void alc269_fixup_hp_gpio_mic1_led(struct hda_codec *codec, if (action == HDA_FIXUP_ACT_PRE_PROBE) { spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook; - spec->gpio_led = 0; spec->mute_led_polarity = 0; spec->gpio_mute_led_mask = 0x08; spec->cap_mute_led_nid = 0x18; @@ -3865,7 +3852,6 @@ static void alc280_fixup_hp_gpio4(struct hda_codec *codec, if (action == HDA_FIXUP_ACT_PRE_PROBE) { spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook; - spec->gpio_led = 0; spec->mute_led_polarity = 0; spec->gpio_mute_led_mask = 0x08; spec->cap_mute_led_nid = 0x18; @@ -3948,7 +3934,6 @@ static void alc280_fixup_hp_gpio2_mic_hotkey(struct hda_codec *codec, gpio2_mic_hotkey_event); spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook; - spec->gpio_led = 0; spec->mute_led_polarity = 0; spec->gpio_mute_led_mask = 0x08; spec->gpio_mic_led_mask = 0x10; @@ -3988,7 +3973,6 @@ static void alc233_fixup_lenovo_line2_mic_hotkey(struct hda_codec *codec, snd_hda_jack_detect_enable_callback(codec, 0x1b, gpio2_mic_hotkey_event); - spec->gpio_led = 0; spec->mute_led_polarity = 0; spec->gpio_mic_led_mask = 0x04; snd_hda_gen_add_micmute_led(codec, alc_gpio_micmute_update); @@ -5365,9 +5349,6 @@ static void alc280_fixup_hp_9480m(struct hda_codec *codec, spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook; spec->gen.hp_automute_hook = alc280_hp_gpio4_automute_hook; - /* The GPIOs are currently off */ - spec->gpio_led = 0; - /* GPIO3 is connected to the output mute LED, * high is on, low is off */ @@ -7592,7 +7573,7 @@ static unsigned int gpio_led_power_filter(struct hda_codec *codec, unsigned int power_state) { struct alc_spec *spec = codec->spec; - if (nid == codec->core.afg && power_state == AC_PWRST_D3 && spec->gpio_led) + if (nid == codec->core.afg && power_state == AC_PWRST_D3 && spec->gpio_data) return AC_PWRST_D0; return power_state; } @@ -7609,7 +7590,6 @@ static void alc662_fixup_led_gpio1(struct hda_codec *codec, if (action == HDA_FIXUP_ACT_PRE_PROBE) { spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook; - spec->gpio_led = 0; spec->mute_led_polarity = 1; spec->gpio_mute_led_mask = 0x01; snd_hda_add_verbs(codec, gpio_init); -- cgit v1.2.3 From 215c850cf205fa502aa45c2540b8d8bc70bd0f1e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 19 Jun 2018 22:34:26 +0200 Subject: ALSA: hda/realtek - Simplify alc885_fixup_macpro_gpio() The fixup for Macbook Pro is nothing but setting the GPIO bits as usual but with one exception: it adds some delay at writing the GPIO bits. Add a flag to put the conditional delay in the common helper, and clean up alc885_fixup_macpro_gpio() with the new flag. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 44 +++++++------------------------------------ 1 file changed, 7 insertions(+), 37 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 0db8329aa114..786b29eb2ba9 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -94,6 +94,7 @@ struct alc_spec { unsigned int gpio_mask; unsigned int gpio_dir; unsigned int gpio_data; + bool gpio_write_delay; /* add a delay before writing gpio_data */ /* mute LED for HP laptops, see alc269_fixup_mic_mute_hook() */ int mute_led_polarity; @@ -265,6 +266,8 @@ static void alc_write_gpio(struct hda_codec *codec) AC_VERB_SET_GPIO_MASK, spec->gpio_mask); snd_hda_codec_write(codec, codec->core.afg, 0, AC_VERB_SET_GPIO_DIRECTION, spec->gpio_dir); + if (spec->gpio_write_delay) + msleep(1); alc_write_gpio_data(codec); } @@ -1868,47 +1871,14 @@ static void alc889_fixup_coef(struct hda_codec *codec, alc_update_coef_idx(codec, 7, 0, 0x2030); } -/* toggle speaker-output according to the hp-jack state */ -static void alc882_gpio_mute(struct hda_codec *codec, int pin, int muted) -{ - unsigned int gpiostate, gpiomask, gpiodir; - - gpiostate = snd_hda_codec_read(codec, codec->core.afg, 0, - AC_VERB_GET_GPIO_DATA, 0); - - if (!muted) - gpiostate |= (1 << pin); - else - gpiostate &= ~(1 << pin); - - gpiomask = snd_hda_codec_read(codec, codec->core.afg, 0, - AC_VERB_GET_GPIO_MASK, 0); - gpiomask |= (1 << pin); - - gpiodir = snd_hda_codec_read(codec, codec->core.afg, 0, - AC_VERB_GET_GPIO_DIRECTION, 0); - gpiodir |= (1 << pin); - - - snd_hda_codec_write(codec, codec->core.afg, 0, - AC_VERB_SET_GPIO_MASK, gpiomask); - snd_hda_codec_write(codec, codec->core.afg, 0, - AC_VERB_SET_GPIO_DIRECTION, gpiodir); - - msleep(1); - - snd_hda_codec_write(codec, codec->core.afg, 0, - AC_VERB_SET_GPIO_DATA, gpiostate); -} - /* set up GPIO at initialization */ static void alc885_fixup_macpro_gpio(struct hda_codec *codec, const struct hda_fixup *fix, int action) { - if (action != HDA_FIXUP_ACT_INIT) - return; - alc882_gpio_mute(codec, 0, 0); - alc882_gpio_mute(codec, 1, 0); + struct alc_spec *spec = codec->spec; + + spec->gpio_write_delay = true; + alc_fixup_gpio3(codec, fix, action); } /* Fix the connection of some pins for ALC889: -- cgit v1.2.3 From 01e4a275e93bc955d0b79520156da6367505658f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 19 Jun 2018 22:47:30 +0200 Subject: ALSA: hda/realtek - Simplify mute LED GPIO handling Now we can simplify the mute LED GPIO handling as well. Each fixup dealing with GPIO for the mute LED controls defined the static init verbs, and they are converted to the common GPIO bit fields with the new helper, alc_fixup_hp_gpio_led(). Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 149 +++++++++++++----------------------------- 1 file changed, 46 insertions(+), 103 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 786b29eb2ba9..a0881ffcd9d7 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -3731,44 +3731,38 @@ static void alc_gpio_micmute_update(struct hda_codec *codec) spec->gen.micmute_led.led_value); } -static void alc269_fixup_hp_gpio_led(struct hda_codec *codec, - const struct hda_fixup *fix, int action) +/* setup mute and mic-mute GPIO bits, add hooks appropriately */ +static void alc_fixup_hp_gpio_led(struct hda_codec *codec, + int action, + unsigned int mute_mask, + unsigned int micmute_mask) { struct alc_spec *spec = codec->spec; - static const struct hda_verb gpio_init[] = { - { 0x01, AC_VERB_SET_GPIO_MASK, 0x18 }, - { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x18 }, - {} - }; - if (action == HDA_FIXUP_ACT_PRE_PROBE) { + alc_fixup_gpio(codec, action, mute_mask | micmute_mask); + + if (action != HDA_FIXUP_ACT_PRE_PROBE) + return; + if (mute_mask) { + spec->gpio_mute_led_mask = mute_mask; spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook; - spec->mute_led_polarity = 0; - spec->gpio_mute_led_mask = 0x08; - spec->gpio_mic_led_mask = 0x10; - snd_hda_add_verbs(codec, gpio_init); + } + if (micmute_mask) { + spec->gpio_mic_led_mask = micmute_mask; snd_hda_gen_add_micmute_led(codec, alc_gpio_micmute_update); } } -static void alc286_fixup_hp_gpio_led(struct hda_codec *codec, +static void alc269_fixup_hp_gpio_led(struct hda_codec *codec, const struct hda_fixup *fix, int action) { - struct alc_spec *spec = codec->spec; - static const struct hda_verb gpio_init[] = { - { 0x01, AC_VERB_SET_GPIO_MASK, 0x22 }, - { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x22 }, - {} - }; + alc_fixup_hp_gpio_led(codec, action, 0x08, 0x10); +} - if (action == HDA_FIXUP_ACT_PRE_PROBE) { - spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook; - spec->mute_led_polarity = 0; - spec->gpio_mute_led_mask = 0x02; - spec->gpio_mic_led_mask = 0x20; - snd_hda_add_verbs(codec, gpio_init); - snd_hda_gen_add_micmute_led(codec, alc_gpio_micmute_update); - } +static void alc286_fixup_hp_gpio_led(struct hda_codec *codec, + const struct hda_fixup *fix, int action) +{ + alc_fixup_hp_gpio_led(codec, action, 0x02, 0x20); } /* turn on/off mic-mute LED per capture hook */ @@ -3792,18 +3786,15 @@ static void alc269_fixup_hp_gpio_mic1_led(struct hda_codec *codec, const struct hda_fixup *fix, int action) { struct alc_spec *spec = codec->spec; - static const struct hda_verb gpio_init[] = { - { 0x01, AC_VERB_SET_GPIO_MASK, 0x08 }, - { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x08 }, - {} - }; + alc_fixup_hp_gpio_led(codec, action, 0x08, 0); if (action == HDA_FIXUP_ACT_PRE_PROBE) { - spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook; - spec->mute_led_polarity = 0; - spec->gpio_mute_led_mask = 0x08; + /* Like hp_gpio_mic1_led, but also needs GPIO4 low to + * enable headphone amp + */ + spec->gpio_mask |= 0x10; + spec->gpio_dir |= 0x10; spec->cap_mute_led_nid = 0x18; - snd_hda_add_verbs(codec, gpio_init); snd_hda_gen_add_micmute_led(codec, alc_cap_micmute_update); codec->power_filter = led_power_filter; } @@ -3812,20 +3803,11 @@ static void alc269_fixup_hp_gpio_mic1_led(struct hda_codec *codec, static void alc280_fixup_hp_gpio4(struct hda_codec *codec, const struct hda_fixup *fix, int action) { - /* Like hp_gpio_mic1_led, but also needs GPIO4 low to enable headphone amp */ struct alc_spec *spec = codec->spec; - static const struct hda_verb gpio_init[] = { - { 0x01, AC_VERB_SET_GPIO_MASK, 0x18 }, - { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x18 }, - {} - }; + alc_fixup_hp_gpio_led(codec, action, 0x08, 0); if (action == HDA_FIXUP_ACT_PRE_PROBE) { - spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook; - spec->mute_led_polarity = 0; - spec->gpio_mute_led_mask = 0x08; spec->cap_mute_led_nid = 0x18; - snd_hda_add_verbs(codec, gpio_init); snd_hda_gen_add_micmute_led(codec, alc_cap_micmute_update); codec->power_filter = led_power_filter; } @@ -3876,38 +3858,29 @@ static int alc_register_micmute_input_device(struct hda_codec *codec) return 0; } +/* GPIO1 = set according to SKU external amp + * GPIO2 = mic mute hotkey + * GPIO3 = mute LED + * GPIO4 = mic mute LED + */ static void alc280_fixup_hp_gpio2_mic_hotkey(struct hda_codec *codec, const struct hda_fixup *fix, int action) { - /* GPIO1 = set according to SKU external amp - GPIO2 = mic mute hotkey - GPIO3 = mute LED - GPIO4 = mic mute LED */ - static const struct hda_verb gpio_init[] = { - { 0x01, AC_VERB_SET_GPIO_MASK, 0x1e }, - { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x1a }, - { 0x01, AC_VERB_SET_GPIO_DATA, 0x02 }, - {} - }; - struct alc_spec *spec = codec->spec; + alc_fixup_hp_gpio_led(codec, action, 0x08, 0x10); if (action == HDA_FIXUP_ACT_PRE_PROBE) { spec->init_amp = ALC_INIT_DEFAULT; if (alc_register_micmute_input_device(codec) != 0) return; - snd_hda_add_verbs(codec, gpio_init); + spec->gpio_mask |= 0x06; + spec->gpio_dir |= 0x02; + spec->gpio_data |= 0x02; snd_hda_codec_write_cache(codec, codec->core.afg, 0, AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x04); snd_hda_jack_detect_enable_callback(codec, codec->core.afg, gpio2_mic_hotkey_event); - - spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook; - spec->mute_led_polarity = 0; - spec->gpio_mute_led_mask = 0x08; - spec->gpio_mic_led_mask = 0x10; - snd_hda_gen_add_micmute_led(codec, alc_gpio_micmute_update); return; } @@ -3921,31 +3894,22 @@ static void alc280_fixup_hp_gpio2_mic_hotkey(struct hda_codec *codec, } } +/* Line2 = mic mute hotkey + * GPIO2 = mic mute LED + */ static void alc233_fixup_lenovo_line2_mic_hotkey(struct hda_codec *codec, const struct hda_fixup *fix, int action) { - /* Line2 = mic mute hotkey - GPIO2 = mic mute LED */ - static const struct hda_verb gpio_init[] = { - { 0x01, AC_VERB_SET_GPIO_MASK, 0x04 }, - { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x04 }, - {} - }; - struct alc_spec *spec = codec->spec; + alc_fixup_hp_gpio_led(codec, action, 0, 0x04); if (action == HDA_FIXUP_ACT_PRE_PROBE) { spec->init_amp = ALC_INIT_DEFAULT; if (alc_register_micmute_input_device(codec) != 0) return; - snd_hda_add_verbs(codec, gpio_init); snd_hda_jack_detect_enable_callback(codec, 0x1b, gpio2_mic_hotkey_event); - - spec->mute_led_polarity = 0; - spec->gpio_mic_led_mask = 0x04; - snd_hda_gen_add_micmute_led(codec, alc_gpio_micmute_update); return; } @@ -5306,27 +5270,13 @@ static void alc280_fixup_hp_9480m(struct hda_codec *codec, int action) { struct alc_spec *spec = codec->spec; - static const struct hda_verb gpio_init[] = { - { 0x01, AC_VERB_SET_GPIO_MASK, 0x18 }, - { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x18 }, - {} - }; + alc_fixup_hp_gpio_led(codec, action, 0x08, 0); if (action == HDA_FIXUP_ACT_PRE_PROBE) { - /* Set the hooks to turn the headphone amp on/off - * as needed - */ - spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook; + /* amp at GPIO4; toggled via alc280_hp_gpio4_automute_hook() */ + spec->gpio_mask |= 0x10; + spec->gpio_dir |= 0x10; spec->gen.hp_automute_hook = alc280_hp_gpio4_automute_hook; - - /* GPIO3 is connected to the output mute LED, - * high is on, low is off - */ - spec->mute_led_polarity = 0; - spec->gpio_mute_led_mask = 0x08; - - /* Initialize GPIO configuration */ - snd_hda_add_verbs(codec, gpio_init); } } @@ -7552,17 +7502,10 @@ static void alc662_fixup_led_gpio1(struct hda_codec *codec, const struct hda_fixup *fix, int action) { struct alc_spec *spec = codec->spec; - static const struct hda_verb gpio_init[] = { - { 0x01, AC_VERB_SET_GPIO_MASK, 0x01 }, - { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01 }, - {} - }; + alc_fixup_hp_gpio_led(codec, action, 0x01, 0); if (action == HDA_FIXUP_ACT_PRE_PROBE) { - spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook; spec->mute_led_polarity = 1; - spec->gpio_mute_led_mask = 0x01; - snd_hda_add_verbs(codec, gpio_init); codec->power_filter = gpio_led_power_filter; } } -- cgit v1.2.3 From ae065f1ce07c09600af0e1dbb6b071991f7cb6e5 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 19 Jun 2018 23:00:03 +0200 Subject: ALSA: hda/realtek - Convert some manual GPIO setups This patch converts the remaining static init verbs for GPIO bits with the common gpio_* fields management. Only the verbs setting the GPIO data bits are targeted in this patch. The rest will be changed in later patches. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 49 +++++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 23 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index a0881ffcd9d7..f5cc506504c0 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -296,6 +296,12 @@ static void alc_fixup_gpio3(struct hda_codec *codec, alc_fixup_gpio(codec, action, 0x03); } +static void alc_fixup_gpio4(struct hda_codec *codec, + const struct hda_fixup *fix, int action) +{ + alc_fixup_gpio(codec, action, 0x04); +} + /* * Fix hardware PLL issue * On some codecs, the analog PLL gating control must be off while @@ -5172,13 +5178,6 @@ static void alc282_fixup_asus_tx300(struct hda_codec *codec, const struct hda_fixup *fix, int action) { struct alc_spec *spec = codec->spec; - /* TX300 needs to set up GPIO2 for the speaker amp */ - static const struct hda_verb gpio2_verbs[] = { - { 0x01, AC_VERB_SET_GPIO_MASK, 0x04 }, - { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x04 }, - { 0x01, AC_VERB_SET_GPIO_DATA, 0x04 }, - {} - }; static const struct hda_pintbl dock_pins[] = { { 0x1b, 0x21114000 }, /* dock speaker pin */ {} @@ -5187,7 +5186,8 @@ static void alc282_fixup_asus_tx300(struct hda_codec *codec, switch (action) { case HDA_FIXUP_ACT_PRE_PROBE: spec->init_amp = ALC_INIT_DEFAULT; - snd_hda_add_verbs(codec, gpio2_verbs); + /* TX300 needs to set up GPIO2 for the speaker amp */ + alc_setup_gpio(codec, 0x04); snd_hda_apply_pincfgs(codec, dock_pins); spec->gen.auto_mute_via_amp = 1; spec->gen.automute_hook = asus_tx300_automute; @@ -5280,6 +5280,19 @@ static void alc280_fixup_hp_9480m(struct hda_codec *codec, } } +static void alc275_fixup_gpio4_off(struct hda_codec *codec, + const struct hda_fixup *fix, + int action) +{ + struct alc_spec *spec = codec->spec; + + if (action == HDA_FIXUP_ACT_PRE_PROBE) { + spec->gpio_mask |= 0x04; + spec->gpio_dir |= 0x04; + /* set data bit low */ + } +} + static void alc233_alc662_fixup_lenovo_dual_codecs(struct hda_codec *codec, const struct hda_fixup *fix, int action) @@ -5468,13 +5481,8 @@ static const struct hda_fixup alc269_fixups[] = { } }, [ALC275_FIXUP_SONY_VAIO_GPIO2] = { - .type = HDA_FIXUP_VERBS, - .v.verbs = (const struct hda_verb[]) { - {0x01, AC_VERB_SET_GPIO_MASK, 0x04}, - {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x04}, - {0x01, AC_VERB_SET_GPIO_DATA, 0x00}, - { } - }, + .type = HDA_FIXUP_FUNC, + .v.func = alc275_fixup_gpio4_off, .chained = true, .chain_id = ALC269_FIXUP_SONY_VAIO }, @@ -6219,14 +6227,9 @@ static const struct hda_fixup alc269_fixups[] = { .chain_id = ALC256_FIXUP_ASUS_HEADSET_MODE }, [ALC256_FIXUP_ASUS_AIO_GPIO2] = { - .type = HDA_FIXUP_VERBS, - .v.verbs = (const struct hda_verb[]) { - /* Set up GPIO2 for the speaker amp */ - { 0x01, AC_VERB_SET_GPIO_MASK, 0x04 }, - { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x04 }, - { 0x01, AC_VERB_SET_GPIO_DATA, 0x04 }, - {} - }, + .type = HDA_FIXUP_FUNC, + /* Set up GPIO2 for the speaker amp */ + .v.func = alc_fixup_gpio4, }, [ALC233_FIXUP_ASUS_MIC_NO_PRESENCE] = { .type = HDA_FIXUP_PINS, -- cgit v1.2.3 From d44a68640668544891fc4b468284d1eaeb49c1d8 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 19 Jun 2018 23:04:03 +0200 Subject: ALSA: hda/realtek - Simplify Dell XPS13 GPIO handling Dell XPS13 has multi-step fixups, and one of them (ALC288_FIXUP_DELL_XPS_13_GPIO6) corresponds to the management of GPIO bit6 (0x40). It used to be a static init verbs (to turn *off* the bit6). In this patch, we convert it as the gpio_mask and gpio_dir initializations folded in the existing fixup function. With this change, ALC288_FIXUP_DELL_XPS_13_GPIO6 becomes superfluous, thus it's removed. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index f5cc506504c0..2cda4a614435 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4881,13 +4881,10 @@ static void alc288_update_headset_jack_cb(struct hda_codec *codec, struct hda_jack_callback *jack) { struct alc_spec *spec = codec->spec; - int present; alc_update_headset_jack_cb(codec, jack); /* Headset Mic enable or disable, only for Dell Dino */ - present = spec->gen.hp_jack_present ? 0x40 : 0; - snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, - present); + alc_update_gpio_data(codec, 0x40, spec->gen.hp_jack_present); } static void alc_fixup_headset_mode_dell_alc288(struct hda_codec *codec, @@ -4896,6 +4893,9 @@ static void alc_fixup_headset_mode_dell_alc288(struct hda_codec *codec, alc_fixup_headset_mode(codec, fix, action); if (action == HDA_FIXUP_ACT_PROBE) { struct alc_spec *spec = codec->spec; + /* toggled via hp_automute_hook */ + spec->gpio_mask |= 0x40; + spec->gpio_dir |= 0x40; spec->gen.hp_automute_hook = alc288_update_headset_jack_cb; } } @@ -5433,7 +5433,6 @@ enum { ALC280_FIXUP_HP_9480M, ALC288_FIXUP_DELL_HEADSET_MODE, ALC288_FIXUP_DELL1_MIC_NO_PRESENCE, - ALC288_FIXUP_DELL_XPS_13_GPIO6, ALC288_FIXUP_DELL_XPS_13, ALC288_FIXUP_DISABLE_AAMIX, ALC292_FIXUP_DELL_E7X, @@ -6049,22 +6048,11 @@ static const struct hda_fixup alc269_fixups[] = { .chained = true, .chain_id = ALC288_FIXUP_DELL_HEADSET_MODE }, - [ALC288_FIXUP_DELL_XPS_13_GPIO6] = { - .type = HDA_FIXUP_VERBS, - .v.verbs = (const struct hda_verb[]) { - {0x01, AC_VERB_SET_GPIO_MASK, 0x40}, - {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x40}, - {0x01, AC_VERB_SET_GPIO_DATA, 0x00}, - { } - }, - .chained = true, - .chain_id = ALC288_FIXUP_DELL1_MIC_NO_PRESENCE - }, [ALC288_FIXUP_DISABLE_AAMIX] = { .type = HDA_FIXUP_FUNC, .v.func = alc_fixup_disable_aamix, .chained = true, - .chain_id = ALC288_FIXUP_DELL_XPS_13_GPIO6 + .chain_id = ALC288_FIXUP_DELL1_MIC_NO_PRESENCE }, [ALC288_FIXUP_DELL_XPS_13] = { .type = HDA_FIXUP_FUNC, @@ -6902,7 +6890,7 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { {0x12, 0x90a60130}, {0x19, 0x03a11020}, {0x21, 0x0321101f}), - SND_HDA_PIN_QUIRK(0x10ec0288, 0x1028, "Dell", ALC288_FIXUP_DELL_XPS_13_GPIO6, + SND_HDA_PIN_QUIRK(0x10ec0288, 0x1028, "Dell", ALC288_FIXUP_DELL1_MIC_NO_PRESENCE, {0x12, 0x90a60120}, {0x14, 0x90170110}, {0x21, 0x0321101f}), -- cgit v1.2.3 From df73d83fad97237b68949058e632b48d55533c09 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 19 Jun 2018 23:05:47 +0200 Subject: ALSA: hda/realtek - Use common GPIO mask for ALC660VD ASUS fixup The ALC660VD_FIX_ASUS_GPIO1 quirk requires to set up GPIO bit0 ON while bit 1 OFF. Implement the fixup function and convert from the static init verbs. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 2cda4a614435..1ee086bcefcf 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -7354,16 +7354,21 @@ static void alc861vd_fixup_dallas(struct hda_codec *codec, } } +/* reset GPIO1 */ +static void alc660vd_fixup_asus_gpio1(struct hda_codec *codec, + const struct hda_fixup *fix, int action) +{ + struct alc_spec *spec = codec->spec; + + if (action == HDA_FIXUP_ACT_PRE_PROBE) + spec->gpio_mask |= 0x02; + alc_fixup_gpio(codec, action, 0x01); +} + static const struct hda_fixup alc861vd_fixups[] = { [ALC660VD_FIX_ASUS_GPIO1] = { - .type = HDA_FIXUP_VERBS, - .v.verbs = (const struct hda_verb[]) { - /* reset GPIO1 */ - {0x01, AC_VERB_SET_GPIO_MASK, 0x03}, - {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01}, - {0x01, AC_VERB_SET_GPIO_DATA, 0x01}, - { } - } + .type = HDA_FIXUP_FUNC, + .v.func = alc660vd_fixup_asus_gpio1, }, [ALC861VD_FIX_DALLAS] = { .type = HDA_FIXUP_FUNC, -- cgit v1.2.3 From a5cb463a81737dde1ef3f1b1cf3e17bf69f20669 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 20 Jun 2018 12:50:11 +0200 Subject: ALSA: hda/realtek - Use common helper for creating ALC268 beep controls The beep mixer controls are the only remaining stuff that uses spec->mixers[] array, and they can be well converted to the standard helper in the generic parser, snd_hda_gen_add_kctl(). This simplifies the code, especially the superfluous mixers and num_mixers fields can be now removed from alc_spec. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 33 +++++++++------------------------ 1 file changed, 9 insertions(+), 24 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 1ee086bcefcf..42d3b0f77577 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -83,8 +83,6 @@ struct alc_spec { struct hda_gen_spec gen; /* must be at head */ /* codec parameterization */ - const struct snd_kcontrol_new *mixers[5]; /* mixer arrays */ - unsigned int num_mixers; unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */ struct alc_customize_define cdefine; @@ -207,18 +205,6 @@ static void alc_process_coef_fw(struct hda_codec *codec, } } -/* - * Append the given mixer and verb elements for the later use - * The mixer array is referred in build_controls(), and init_verbs are - * called in init(). - */ -static void add_mixer(struct alc_spec *spec, const struct snd_kcontrol_new *mix) -{ - if (snd_BUG_ON(spec->num_mixers >= ARRAY_SIZE(spec->mixers))) - return; - spec->mixers[spec->num_mixers++] = mix; -} - /* * GPIO setup tables, used in initialization */ @@ -789,18 +775,12 @@ static const struct snd_kcontrol_new alc_beep_mixer[] = { static int alc_build_controls(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; - int i, err; + int err; err = snd_hda_gen_build_controls(codec); if (err < 0) return err; - for (i = 0; i < spec->num_mixers; i++) { - err = snd_hda_add_new_ctls(codec, spec->mixers[i]); - if (err < 0) - return err; - } - #ifdef CONFIG_SND_HDA_INPUT_BEEP /* create beep controls if needed */ if (spec->beep_amp) { @@ -2663,7 +2643,6 @@ static const struct snd_kcontrol_new alc268_beep_mixer[] = { .put = alc268_beep_switch_put, .private_value = HDA_COMPOSE_AMP_VAL(0x0f, 3, 1, HDA_INPUT) }, - { } }; /* set PCBEEP vol = 0, mute connections */ @@ -2731,7 +2710,7 @@ static int alc268_parse_auto_config(struct hda_codec *codec) static int patch_alc268(struct hda_codec *codec) { struct alc_spec *spec; - int err; + int i, err; /* ALC268 has no aa-loopback mixer */ err = alc_alloc_spec(codec, 0); @@ -2753,7 +2732,13 @@ static int patch_alc268(struct hda_codec *codec) if (err > 0 && !spec->gen.no_analog && spec->gen.autocfg.speaker_pins[0] != 0x1d) { - add_mixer(spec, alc268_beep_mixer); + for (i = 0; i < ARRAY_SIZE(alc268_beep_mixer); i++) { + if (!snd_hda_gen_add_kctl(&spec->gen, NULL, + &alc268_beep_mixer[i])) { + err = -ENOMEM; + goto error; + } + } snd_hda_add_verbs(codec, alc268_beep_init_verbs); if (!query_amp_caps(codec, 0x1d, HDA_INPUT)) /* override the amp caps for beep generator */ -- cgit v1.2.3 From fea80fae552c428b67591cb0aacca56c11c3eeaf Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 20 Jun 2018 12:52:46 +0200 Subject: ALSA: hda/realtek - Use common helper for creating beep controls In the Realtek codec driver, we used to build kctl elements for beep mixer in the own build_controls callback. This is an open-code and can be covered by the standard feature of the generic parser with snd_hda_gen_add_kctl() instead. Also, after the conversion, spec->beep_amp becomes superfluous; hence it's removed along with the conversion. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 114 ++++++++++++++++++++++++------------------ 1 file changed, 65 insertions(+), 49 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 42d3b0f77577..0e84d9cdd42d 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -83,8 +83,6 @@ struct alc_spec { struct hda_gen_spec gen; /* must be at head */ /* codec parameterization */ - unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */ - struct alc_customize_define cdefine; unsigned int parse_flags; /* flag for snd_hda_parse_pin_defcfg() */ @@ -763,41 +761,14 @@ static void alc_fixup_inv_dmic(struct hda_codec *codec, } -#ifdef CONFIG_SND_HDA_INPUT_BEEP -/* additional beep mixers; the actual parameters are overwritten at build */ -static const struct snd_kcontrol_new alc_beep_mixer[] = { - HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_INPUT), - HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_INPUT), - { } /* end */ -}; -#endif - static int alc_build_controls(struct hda_codec *codec) { - struct alc_spec *spec = codec->spec; int err; err = snd_hda_gen_build_controls(codec); if (err < 0) return err; -#ifdef CONFIG_SND_HDA_INPUT_BEEP - /* create beep controls if needed */ - if (spec->beep_amp) { - const struct snd_kcontrol_new *knew; - for (knew = alc_beep_mixer; knew->name; knew++) { - struct snd_kcontrol *kctl; - kctl = snd_ctl_new1(knew, codec); - if (!kctl) - return -ENOMEM; - kctl->private_value = spec->beep_amp; - err = snd_hda_ctl_add(codec, 0, kctl); - if (err < 0) - return err; - } - } -#endif - snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_BUILD); return 0; } @@ -1008,8 +979,30 @@ static int alc_codec_rename_from_preset(struct hda_codec *codec) * Digital-beep handlers */ #ifdef CONFIG_SND_HDA_INPUT_BEEP -#define set_beep_amp(spec, nid, idx, dir) \ - ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir)) + +/* additional beep mixers; private_value will be overwritten */ +static const struct snd_kcontrol_new alc_beep_mixer[] = { + HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_INPUT), + HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_INPUT), +}; + +/* set up and create beep controls */ +static int set_beep_amp(struct alc_spec *spec, hda_nid_t nid, + int idx, int dir) +{ + struct snd_kcontrol_new *knew; + unsigned int beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir); + int i; + + for (i = 0; i < ARRAY_SIZE(alc_beep_mixer); i++) { + knew = snd_hda_gen_add_kctl(&spec->gen, NULL, + &alc_beep_mixer[i]); + if (!knew) + return -ENOMEM; + knew->private_value = beep_amp; + } + return 0; +} static const struct snd_pci_quirk beep_white_list[] = { SND_PCI_QUIRK(0x1043, 0x103c, "ASUS", 1), @@ -1034,7 +1027,7 @@ static inline int has_cdefine_beep(struct hda_codec *codec) return spec->cdefine.enable_pcbeep; } #else -#define set_beep_amp(spec, nid, idx, dir) /* NOP */ +#define set_beep_amp(spec, nid, idx, dir) 0 #define has_cdefine_beep(codec) 0 #endif @@ -1536,8 +1529,11 @@ static int patch_alc880(struct hda_codec *codec) if (err < 0) goto error; - if (!spec->gen.no_analog) - set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); + if (!spec->gen.no_analog) { + err = set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); + if (err < 0) + goto error; + } snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); @@ -1784,8 +1780,11 @@ static int patch_alc260(struct hda_codec *codec) if (err < 0) goto error; - if (!spec->gen.no_analog) - set_beep_amp(spec, 0x07, 0x05, HDA_INPUT); + if (!spec->gen.no_analog) { + err = set_beep_amp(spec, 0x07, 0x05, HDA_INPUT); + if (err < 0) + goto error; + } snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); @@ -2434,8 +2433,11 @@ static int patch_alc882(struct hda_codec *codec) if (err < 0) goto error; - if (!spec->gen.no_analog && spec->gen.beep_nid) - set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); + if (!spec->gen.no_analog && spec->gen.beep_nid) { + err = set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); + if (err < 0) + goto error; + } snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); @@ -2596,8 +2598,11 @@ static int patch_alc262(struct hda_codec *codec) if (err < 0) goto error; - if (!spec->gen.no_analog && spec->gen.beep_nid) - set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); + if (!spec->gen.no_analog && spec->gen.beep_nid) { + err = set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); + if (err < 0) + goto error; + } snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); @@ -7168,8 +7173,11 @@ static int patch_alc269(struct hda_codec *codec) if (err < 0) goto error; - if (!spec->gen.no_analog && spec->gen.beep_nid && spec->gen.mixer_nid) - set_beep_amp(spec, spec->gen.mixer_nid, 0x04, HDA_INPUT); + if (!spec->gen.no_analog && spec->gen.beep_nid && spec->gen.mixer_nid) { + err = set_beep_amp(spec, spec->gen.mixer_nid, 0x04, HDA_INPUT); + if (err < 0) + goto error; + } snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); @@ -7298,8 +7306,11 @@ static int patch_alc861(struct hda_codec *codec) if (err < 0) goto error; - if (!spec->gen.no_analog) - set_beep_amp(spec, 0x23, 0, HDA_OUTPUT); + if (!spec->gen.no_analog) { + err = set_beep_amp(spec, 0x23, 0, HDA_OUTPUT); + if (err < 0) + goto error; + } snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); @@ -7392,8 +7403,11 @@ static int patch_alc861vd(struct hda_codec *codec) if (err < 0) goto error; - if (!spec->gen.no_analog) - set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); + if (!spec->gen.no_analog) { + err = set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); + if (err < 0) + goto error; + } snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); @@ -8103,18 +8117,20 @@ static int patch_alc662(struct hda_codec *codec) if (!spec->gen.no_analog && spec->gen.beep_nid) { switch (codec->core.vendor_id) { case 0x10ec0662: - set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); + err = set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); break; case 0x10ec0272: case 0x10ec0663: case 0x10ec0665: case 0x10ec0668: - set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT); + err = set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT); break; case 0x10ec0273: - set_beep_amp(spec, 0x0b, 0x03, HDA_INPUT); + err = set_beep_amp(spec, 0x0b, 0x03, HDA_INPUT); break; } + if (err < 0) + goto error; } snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); -- cgit v1.2.3 From 51e19ca5f7555802687324d3bee3bc6b7df240d4 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 20 Jun 2018 17:06:58 +0200 Subject: ALSA: hda/conexant - Clean up beep code Like the previous commit for Realtek codec, the similar cleanup work can be applied to Conexant codec, too. A slight difference is that the call of cx_auto_parse_beep() is moved after snd_hda_gen_parse_auto_config(). It's not strictly needed, but it'd be good to make the creation of such beep mixers at the end, which matches with the former situation. Along with this conversion, cx_auto_build_controls() becomes just calling snd_hda_gen_build_controls(), so it's simply replaced with snd_hda_gen_build_controls. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_conexant.c | 85 ++++++++++++++---------------------------- 1 file changed, 27 insertions(+), 58 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index b7339cb5c45b..75ba66eb4ccd 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -37,8 +37,6 @@ struct conexant_spec { struct hda_gen_spec gen; - unsigned int beep_amp; - /* extra EAPD pins */ unsigned int num_eapds; hda_nid_t eapds[4]; @@ -62,65 +60,48 @@ struct conexant_spec { #ifdef CONFIG_SND_HDA_INPUT_BEEP -static inline void set_beep_amp(struct conexant_spec *spec, hda_nid_t nid, - int idx, int dir) -{ - spec->gen.beep_nid = nid; - spec->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir); -} -/* additional beep mixers; the actual parameters are overwritten at build */ +/* additional beep mixers; private_value will be overwritten */ static const struct snd_kcontrol_new cxt_beep_mixer[] = { HDA_CODEC_VOLUME_MONO("Beep Playback Volume", 0, 1, 0, HDA_OUTPUT), HDA_CODEC_MUTE_BEEP_MONO("Beep Playback Switch", 0, 1, 0, HDA_OUTPUT), - { } /* end */ }; -/* create beep controls if needed */ -static int add_beep_ctls(struct hda_codec *codec) +static int set_beep_amp(struct conexant_spec *spec, hda_nid_t nid, + int idx, int dir) { - struct conexant_spec *spec = codec->spec; - int err; + struct snd_kcontrol_new *knew; + unsigned int beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir); + int i; - if (spec->beep_amp) { - const struct snd_kcontrol_new *knew; - for (knew = cxt_beep_mixer; knew->name; knew++) { - struct snd_kcontrol *kctl; - kctl = snd_ctl_new1(knew, codec); - if (!kctl) - return -ENOMEM; - kctl->private_value = spec->beep_amp; - err = snd_hda_ctl_add(codec, 0, kctl); - if (err < 0) - return err; - } + spec->gen.beep_nid = nid; + for (i = 0; i < ARRAY_SIZE(cxt_beep_mixer); i++) { + knew = snd_hda_gen_add_kctl(&spec->gen, NULL, + &cxt_beep_mixer[i]); + if (!knew) + return -ENOMEM; + knew->private_value = beep_amp; } return 0; } -#else -#define set_beep_amp(spec, nid, idx, dir) /* NOP */ -#define add_beep_ctls(codec) 0 -#endif -/* - * Automatic parser for CX20641 & co - */ - -#ifdef CONFIG_SND_HDA_INPUT_BEEP -static void cx_auto_parse_beep(struct hda_codec *codec) +static int cx_auto_parse_beep(struct hda_codec *codec) { struct conexant_spec *spec = codec->spec; hda_nid_t nid; for_each_hda_codec_node(nid, codec) - if (get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_BEEP) { - set_beep_amp(spec, nid, 0, HDA_OUTPUT); - break; - } + if (get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_BEEP) + return set_beep_amp(spec, nid, 0, HDA_OUTPUT); + return 0; } #else -#define cx_auto_parse_beep(codec) +#define cx_auto_parse_beep(codec) 0 #endif +/* + * Automatic parser for CX20641 & co + */ + /* parse EAPDs */ static void cx_auto_parse_eapd(struct hda_codec *codec) { @@ -179,21 +160,6 @@ static void cx_auto_vmaster_hook_mute_led(void *private_data, int enabled) enabled ? 0x00 : 0x02); } -static int cx_auto_build_controls(struct hda_codec *codec) -{ - int err; - - err = snd_hda_gen_build_controls(codec); - if (err < 0) - return err; - - err = add_beep_ctls(codec); - if (err < 0) - return err; - - return 0; -} - static int cx_auto_init(struct hda_codec *codec) { struct conexant_spec *spec = codec->spec; @@ -234,7 +200,7 @@ static void cx_auto_free(struct hda_codec *codec) } static const struct hda_codec_ops cx_auto_patch_ops = { - .build_controls = cx_auto_build_controls, + .build_controls = snd_hda_gen_build_controls, .build_pcms = snd_hda_gen_build_pcms, .init = cx_auto_init, .reboot_notify = cx_auto_reboot_notify, @@ -1033,7 +999,6 @@ static int patch_conexant_auto(struct hda_codec *codec) codec->spec = spec; codec->patch_ops = cx_auto_patch_ops; - cx_auto_parse_beep(codec); cx_auto_parse_eapd(codec); spec->gen.own_eapd_ctl = 1; if (spec->dynamic_eapd) @@ -1093,6 +1058,10 @@ static int patch_conexant_auto(struct hda_codec *codec) if (err < 0) goto error; + err = cx_auto_parse_beep(codec); + if (err < 0) + goto error; + /* Some laptops with Conexant chips show stalls in S3 resume, * which falls into the single-cmd mode. * Better to make reset, then. -- cgit v1.2.3 From 0785b0ecb8fa960b4f49010d0679d174efad423c Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 20 Jun 2018 17:10:51 +0200 Subject: ALSA: hda/cirrus - Simplify creation of new controls This patch moves the mixer creation code in Cirrus codec driver from its own build_controls callback to snd_hda_gen_add_kctl() for simplification. As a bonus, this allows us to remove the cs421x_build_controls as it becomes identical with snd_hda_gen_build_controls(). Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_cirrus.c | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index d6e079f4ec09..a7f91be45194 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c @@ -1096,25 +1096,6 @@ static int cs421x_init(struct hda_codec *codec) return 0; } -static int cs421x_build_controls(struct hda_codec *codec) -{ - struct cs_spec *spec = codec->spec; - int err; - - err = snd_hda_gen_build_controls(codec); - if (err < 0) - return err; - - if (spec->gen.autocfg.speaker_outs && - spec->vendor_nid == CS4210_VENDOR_NID) { - err = snd_hda_ctl_add(codec, 0, - snd_ctl_new1(&cs421x_speaker_boost_ctl, codec)); - if (err < 0) - return err; - } - return 0; -} - static void fix_volume_caps(struct hda_codec *codec, hda_nid_t dac) { unsigned int caps; @@ -1144,6 +1125,14 @@ static int cs421x_parse_auto_config(struct hda_codec *codec) return err; parse_cs421x_digital(codec); + + if (spec->gen.autocfg.speaker_outs && + spec->vendor_nid == CS4210_VENDOR_NID) { + if (!snd_hda_gen_add_kctl(&spec->gen, NULL, + &cs421x_speaker_boost_ctl)) + return -ENOMEM; + } + return 0; } @@ -1175,7 +1164,7 @@ static int cs421x_suspend(struct hda_codec *codec) #endif static const struct hda_codec_ops cs421x_patch_ops = { - .build_controls = cs421x_build_controls, + .build_controls = snd_hda_gen_build_controls, .build_pcms = snd_hda_gen_build_pcms, .init = cs421x_init, .free = cs_free, -- cgit v1.2.3 From fcbdcc1a93dd49ccd0e0f34224ce1ba4203b75de Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 20 Jun 2018 22:36:17 +0200 Subject: ALSA: hda/via - Rewrite with error goto Currently VIA codec driver invokes via_free() at each place of the error path. Move the error handling to the end of each function commonly and do goto-error as a standard idiom. This is a preliminary patch for the further cleanups, and no functional changes. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_via.c | 100 +++++++++++++++++++++++++++------------------- 1 file changed, 60 insertions(+), 40 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index fc30d1e8aa76..76e47d088a41 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -686,10 +686,8 @@ static int patch_vt1708(struct hda_codec *codec) /* automatic parse from the BIOS config */ err = via_parse_auto_config(codec); - if (err < 0) { - via_free(codec); - return err; - } + if (err < 0) + goto error; /* add jack detect on/off control */ spec->mixers[spec->num_mixers++] = vt1708_jack_detect_ctl; @@ -700,6 +698,10 @@ static int patch_vt1708(struct hda_codec *codec) codec->jackpoll_interval = 0; return 0; + + error: + via_free(codec); + return err; } static int patch_vt1709(struct hda_codec *codec) @@ -715,12 +717,14 @@ static int patch_vt1709(struct hda_codec *codec) spec->gen.mixer_nid = 0x18; err = via_parse_auto_config(codec); - if (err < 0) { - via_free(codec); - return err; - } + if (err < 0) + goto error; return 0; + + error: + via_free(codec); + return err; } static int patch_vt1708S(struct hda_codec *codec); @@ -741,12 +745,14 @@ static int patch_vt1708B(struct hda_codec *codec) /* automatic parse from the BIOS config */ err = via_parse_auto_config(codec); - if (err < 0) { - via_free(codec); - return err; - } + if (err < 0) + goto error; return 0; + + error: + via_free(codec); + return err; } /* Patch for VT1708S */ @@ -793,14 +799,16 @@ static int patch_vt1708S(struct hda_codec *codec) /* automatic parse from the BIOS config */ err = via_parse_auto_config(codec); - if (err < 0) { - via_free(codec); - return err; - } + if (err < 0) + goto error; spec->init_verbs[spec->num_iverbs++] = vt1708S_init_verbs; return 0; + + error: + via_free(codec); + return err; } /* Patch for VT1702 */ @@ -834,14 +842,16 @@ static int patch_vt1702(struct hda_codec *codec) /* automatic parse from the BIOS config */ err = via_parse_auto_config(codec); - if (err < 0) { - via_free(codec); - return err; - } + if (err < 0) + goto error; spec->init_verbs[spec->num_iverbs++] = vt1702_init_verbs; return 0; + + error: + via_free(codec); + return err; } /* Patch for VT1718S */ @@ -906,14 +916,16 @@ static int patch_vt1718S(struct hda_codec *codec) /* automatic parse from the BIOS config */ err = via_parse_auto_config(codec); - if (err < 0) { - via_free(codec); - return err; - } + if (err < 0) + goto error; spec->init_verbs[spec->num_iverbs++] = vt1718S_init_verbs; return 0; + + error: + via_free(codec); + return err; } /* Patch for VT1716S */ @@ -1002,10 +1014,8 @@ static int patch_vt1716S(struct hda_codec *codec) /* automatic parse from the BIOS config */ err = via_parse_auto_config(codec); - if (err < 0) { - via_free(codec); - return err; - } + if (err < 0) + goto error; spec->init_verbs[spec->num_iverbs++] = vt1716S_init_verbs; @@ -1013,6 +1023,10 @@ static int patch_vt1716S(struct hda_codec *codec) spec->mixers[spec->num_mixers++] = vt1716S_mono_out_mixer; return 0; + + error: + via_free(codec); + return err; } /* for vt2002P */ @@ -1109,10 +1123,8 @@ static int patch_vt2002P(struct hda_codec *codec) /* automatic parse from the BIOS config */ err = via_parse_auto_config(codec); - if (err < 0) { - via_free(codec); - return err; - } + if (err < 0) + goto error; if (spec->codec_type == VT1802) spec->init_verbs[spec->num_iverbs++] = vt1802_init_verbs; @@ -1120,6 +1132,10 @@ static int patch_vt2002P(struct hda_codec *codec) spec->init_verbs[spec->num_iverbs++] = vt2002P_init_verbs; return 0; + + error: + via_free(codec); + return err; } /* for vt1812 */ @@ -1150,14 +1166,16 @@ static int patch_vt1812(struct hda_codec *codec) /* automatic parse from the BIOS config */ err = via_parse_auto_config(codec); - if (err < 0) { - via_free(codec); - return err; - } + if (err < 0) + goto error; spec->init_verbs[spec->num_iverbs++] = vt1812_init_verbs; return 0; + + error: + via_free(codec); + return err; } /* patch for vt3476 */ @@ -1187,14 +1205,16 @@ static int patch_vt3476(struct hda_codec *codec) /* automatic parse from the BIOS config */ err = via_parse_auto_config(codec); - if (err < 0) { - via_free(codec); - return err; - } + if (err < 0) + goto error; spec->init_verbs[spec->num_iverbs++] = vt3476_init_verbs; return 0; + + error: + via_free(codec); + return err; } /* -- cgit v1.2.3 From 0e8f9862493a55d85d3351cb4517f2e4d95c9600 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 20 Jun 2018 17:20:42 +0200 Subject: ALSA: hda/via - Simplify control management This patch replaces the control element creations in VIA codec driver with the standard snd_hda_gen_add_kctl() calls as a cleanup. There are two major fields targeted by this patch: the beep controls and static init controls. The former is converted just like other codec drivers do. The spec->beep_amp field can be eliminated by this change as well. The latter, static init controls, are replaced simply with explicit snd_hda_gen_add_kctl() calls. After these conversions, via_build_controls() becomes superfluous and replaced with snd_hda_gen_build_controls(), too. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_via.c | 130 ++++++++++++++++------------------------------ 1 file changed, 44 insertions(+), 86 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 76e47d088a41..dc4961f0dfd1 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -91,9 +91,6 @@ struct via_spec { struct hda_gen_spec gen; /* codec parameterization */ - const struct snd_kcontrol_new *mixers[6]; - unsigned int num_mixers; - const struct hda_verb *init_verbs[5]; unsigned int num_iverbs; @@ -107,8 +104,6 @@ struct via_spec { /* work to check hp jack state */ int hp_work_active; int vt1708_jack_detect; - - unsigned int beep_amp; }; static enum VIA_HDA_CODEC get_codec_type(struct hda_codec *codec); @@ -262,69 +257,51 @@ static int via_pin_power_ctl_put(struct snd_kcontrol *kcontrol, return 1; } -static const struct snd_kcontrol_new via_pin_power_ctl_enum[] = { - { +static const struct snd_kcontrol_new via_pin_power_ctl_enum = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Dynamic Power-Control", .info = via_pin_power_ctl_info, .get = via_pin_power_ctl_get, .put = via_pin_power_ctl_put, - }, - {} /* terminator */ }; #ifdef CONFIG_SND_HDA_INPUT_BEEP -static inline void set_beep_amp(struct via_spec *spec, hda_nid_t nid, - int idx, int dir) -{ - spec->gen.beep_nid = nid; - spec->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir); -} - /* additional beep mixers; the actual parameters are overwritten at build */ -static const struct snd_kcontrol_new cxt_beep_mixer[] = { +static const struct snd_kcontrol_new via_beep_mixer[] = { HDA_CODEC_VOLUME_MONO("Beep Playback Volume", 0, 1, 0, HDA_OUTPUT), HDA_CODEC_MUTE_BEEP_MONO("Beep Playback Switch", 0, 1, 0, HDA_OUTPUT), - { } /* end */ }; -/* create beep controls if needed */ -static int add_beep_ctls(struct hda_codec *codec) +static int set_beep_amp(struct via_spec *spec, hda_nid_t nid, + int idx, int dir) { - struct via_spec *spec = codec->spec; - int err; + struct snd_kcontrol_new *knew; + unsigned int beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir); + int i; - if (spec->beep_amp) { - const struct snd_kcontrol_new *knew; - for (knew = cxt_beep_mixer; knew->name; knew++) { - struct snd_kcontrol *kctl; - kctl = snd_ctl_new1(knew, codec); - if (!kctl) - return -ENOMEM; - kctl->private_value = spec->beep_amp; - err = snd_hda_ctl_add(codec, 0, kctl); - if (err < 0) - return err; - } + spec->gen.beep_nid = nid; + for (i = 0; i < ARRAY_SIZE(via_beep_mixer); i++) { + knew = snd_hda_gen_add_kctl(&spec->gen, NULL, + &via_beep_mixer[i]); + if (!knew) + return -ENOMEM; + knew->private_value = beep_amp; } return 0; } -static void auto_parse_beep(struct hda_codec *codec) +static int auto_parse_beep(struct hda_codec *codec) { struct via_spec *spec = codec->spec; hda_nid_t nid; for_each_hda_codec_node(nid, codec) - if (get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_BEEP) { - set_beep_amp(spec, nid, 0, HDA_OUTPUT); - break; - } + if (get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_BEEP) + return set_beep_amp(spec, nid, 0, HDA_OUTPUT); + return 0; } #else -#define set_beep_amp(spec, nid, idx, dir) /* NOP */ -#define add_beep_ctls(codec) 0 -#define auto_parse_beep(codec) +#define auto_parse_beep(codec) 0 #endif /* check AA path's mute status */ @@ -403,30 +380,6 @@ static void analog_low_current_mode(struct hda_codec *codec) return __analog_low_current_mode(codec, false); } -static int via_build_controls(struct hda_codec *codec) -{ - struct via_spec *spec = codec->spec; - int err, i; - - err = snd_hda_gen_build_controls(codec); - if (err < 0) - return err; - - err = add_beep_ctls(codec); - if (err < 0) - return err; - - spec->mixers[spec->num_mixers++] = via_pin_power_ctl_enum; - - for (i = 0; i < spec->num_mixers; i++) { - err = snd_hda_add_new_ctls(codec, spec->mixers[i]); - if (err < 0) - return err; - } - - return 0; -} - static void via_playback_pcm_hook(struct hda_pcm_stream *hinfo, struct hda_codec *codec, struct snd_pcm_substream *substream, @@ -481,7 +434,7 @@ static int via_check_power_status(struct hda_codec *codec, hda_nid_t nid) static int via_init(struct hda_codec *codec); static const struct hda_codec_ops via_patch_ops = { - .build_controls = via_build_controls, + .build_controls = snd_hda_gen_build_controls, .build_pcms = snd_hda_gen_build_pcms, .init = via_init, .free = via_free, @@ -545,16 +498,13 @@ static int vt1708_jack_detect_put(struct snd_kcontrol *kcontrol, return 1; } -static const struct snd_kcontrol_new vt1708_jack_detect_ctl[] = { - { +static const struct snd_kcontrol_new vt1708_jack_detect_ctl = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Jack Detect", .count = 1, .info = snd_ctl_boolean_mono_info, .get = vt1708_jack_detect_get, .put = vt1708_jack_detect_put, - }, - {} /* terminator */ }; static const struct badness_table via_main_out_badness = { @@ -586,12 +536,17 @@ static int via_parse_auto_config(struct hda_codec *codec) if (err < 0) return err; - auto_parse_beep(codec); - err = snd_hda_gen_parse_auto_config(codec, &spec->gen.autocfg); if (err < 0) return err; + err = auto_parse_beep(codec); + if (err < 0) + return err; + + if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &via_pin_power_ctl_enum)) + return -ENOMEM; + /* disable widget PM at start for compatibility */ codec->power_save_node = 0; spec->gen.power_down_unused = 0; @@ -623,7 +578,7 @@ static int vt1708_build_controls(struct hda_codec *codec) int err; int old_interval = codec->jackpoll_interval; codec->jackpoll_interval = msecs_to_jiffies(100); - err = via_build_controls(codec); + err = snd_hda_gen_build_controls(codec); codec->jackpoll_interval = old_interval; return err; } @@ -690,7 +645,10 @@ static int patch_vt1708(struct hda_codec *codec) goto error; /* add jack detect on/off control */ - spec->mixers[spec->num_mixers++] = vt1708_jack_detect_ctl; + if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &vt1708_jack_detect_ctl)) { + err = -ENOMEM; + goto error; + } spec->init_verbs[spec->num_iverbs++] = vt1708_init_verbs; @@ -967,9 +925,9 @@ static int vt1716s_dmic_put(struct snd_kcontrol *kcontrol, return 1; } -static const struct snd_kcontrol_new vt1716s_dmic_mixer[] = { - HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x22, 0x0, HDA_INPUT), - { +static const struct snd_kcontrol_new vt1716s_dmic_mixer_vol = + HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x22, 0x0, HDA_INPUT); +static const struct snd_kcontrol_new vt1716s_dmic_mixer_sw = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Digital Mic Capture Switch", .subdevice = HDA_SUBDEV_NID_FLAG | 0x26, @@ -977,16 +935,12 @@ static const struct snd_kcontrol_new vt1716s_dmic_mixer[] = { .info = vt1716s_dmic_info, .get = vt1716s_dmic_get, .put = vt1716s_dmic_put, - }, - {} /* end */ }; /* mono-out mixer elements */ -static const struct snd_kcontrol_new vt1716S_mono_out_mixer[] = { - HDA_CODEC_MUTE("Mono Playback Switch", 0x2a, 0x0, HDA_OUTPUT), - { } /* end */ -}; +static const struct snd_kcontrol_new vt1716S_mono_out_mixer = + HDA_CODEC_MUTE("Mono Playback Switch", 0x2a, 0x0, HDA_OUTPUT); static const struct hda_verb vt1716S_init_verbs[] = { /* Enable Boost Volume backdoor */ @@ -1019,8 +973,12 @@ static int patch_vt1716S(struct hda_codec *codec) spec->init_verbs[spec->num_iverbs++] = vt1716S_init_verbs; - spec->mixers[spec->num_mixers++] = vt1716s_dmic_mixer; - spec->mixers[spec->num_mixers++] = vt1716S_mono_out_mixer; + if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &vt1716s_dmic_mixer_vol) || + !snd_hda_gen_add_kctl(&spec->gen, NULL, &vt1716s_dmic_mixer_sw) || + !snd_hda_gen_add_kctl(&spec->gen, NULL, &vt1716S_mono_out_mixer)) { + err = -ENOMEM; + goto error; + } return 0; -- cgit v1.2.3 From f8bfc628f73c95c242dd49efa16d59005d8558fc Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 20 Jun 2018 17:27:50 +0200 Subject: ALSA: hda/via - Use standard verb containers In this patch, the remaining static init verbs in VIA codec driver are converted to the standard snd_hda_add_verbs() calls. The conversion is straightforward, but one change to be noted is the place of calls: since these verbs are supposed to be executed at the beginning of the init / resume procedure, we need to add snd_hda_add_verbs() calls before calling the other parsers. This is merely a cleanup, no functional changes. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_via.c | 64 ++++++++++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 29 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index dc4961f0dfd1..6b9617aee0e6 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -90,10 +90,6 @@ enum VIA_HDA_CODEC { struct via_spec { struct hda_gen_spec gen; - /* codec parameterization */ - const struct hda_verb *init_verbs[5]; - unsigned int num_iverbs; - /* HP mode source */ unsigned int dmic_enabled; enum VIA_HDA_CODEC codec_type; @@ -555,12 +551,6 @@ static int via_parse_auto_config(struct hda_codec *codec) static int via_init(struct hda_codec *codec) { - struct via_spec *spec = codec->spec; - int i; - - for (i = 0; i < spec->num_iverbs; i++) - snd_hda_sequence_write(codec, spec->init_verbs[i]); - /* init power states */ __analog_low_current_mode(codec, true); @@ -639,6 +629,10 @@ static int patch_vt1708(struct hda_codec *codec) vt1708_set_pinconfig_connect(codec, VT1708_HP_PIN_NID); vt1708_set_pinconfig_connect(codec, VT1708_CD_PIN_NID); + err = snd_hda_add_verbs(codec, vt1708_init_verbs); + if (err < 0) + goto error; + /* automatic parse from the BIOS config */ err = via_parse_auto_config(codec); if (err < 0) @@ -650,8 +644,6 @@ static int patch_vt1708(struct hda_codec *codec) goto error; } - spec->init_verbs[spec->num_iverbs++] = vt1708_init_verbs; - /* clear jackpoll_interval again; it's set dynamically */ codec->jackpoll_interval = 0; @@ -755,13 +747,15 @@ static int patch_vt1708S(struct hda_codec *codec) if (codec->core.vendor_id == 0x11064397) snd_hda_codec_set_name(codec, "VT1705"); + err = snd_hda_add_verbs(codec, vt1708S_init_verbs); + if (err < 0) + goto error; + /* automatic parse from the BIOS config */ err = via_parse_auto_config(codec); if (err < 0) goto error; - spec->init_verbs[spec->num_iverbs++] = vt1708S_init_verbs; - return 0; error: @@ -798,13 +792,15 @@ static int patch_vt1702(struct hda_codec *codec) (0x5 << AC_AMPCAP_STEP_SIZE_SHIFT) | (1 << AC_AMPCAP_MUTE_SHIFT)); + err = snd_hda_add_verbs(codec, vt1702_init_verbs); + if (err < 0) + goto error; + /* automatic parse from the BIOS config */ err = via_parse_auto_config(codec); if (err < 0) goto error; - spec->init_verbs[spec->num_iverbs++] = vt1702_init_verbs; - return 0; error: @@ -872,13 +868,15 @@ static int patch_vt1718S(struct hda_codec *codec) override_mic_boost(codec, 0x29, 0, 3, 40); add_secret_dac_path(codec); + err = snd_hda_add_verbs(codec, vt1718S_init_verbs); + if (err < 0) + goto error; + /* automatic parse from the BIOS config */ err = via_parse_auto_config(codec); if (err < 0) goto error; - spec->init_verbs[spec->num_iverbs++] = vt1718S_init_verbs; - return 0; error: @@ -966,13 +964,15 @@ static int patch_vt1716S(struct hda_codec *codec) override_mic_boost(codec, 0x1a, 0, 3, 40); override_mic_boost(codec, 0x1e, 0, 3, 40); + err = snd_hda_add_verbs(codec, vt1716S_init_verbs); + if (err < 0) + goto error; + /* automatic parse from the BIOS config */ err = via_parse_auto_config(codec); if (err < 0) goto error; - spec->init_verbs[spec->num_iverbs++] = vt1716S_init_verbs; - if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &vt1716s_dmic_mixer_vol) || !snd_hda_gen_add_kctl(&spec->gen, NULL, &vt1716s_dmic_mixer_sw) || !snd_hda_gen_add_kctl(&spec->gen, NULL, &vt1716S_mono_out_mixer)) { @@ -1079,16 +1079,18 @@ static int patch_vt2002P(struct hda_codec *codec) snd_hda_pick_fixup(codec, NULL, vt2002p_fixups, via_fixups); snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); + if (spec->codec_type == VT1802) + err = snd_hda_add_verbs(codec, vt1802_init_verbs); + else + err = snd_hda_add_verbs(codec, vt2002P_init_verbs); + if (err < 0) + goto error; + /* automatic parse from the BIOS config */ err = via_parse_auto_config(codec); if (err < 0) goto error; - if (spec->codec_type == VT1802) - spec->init_verbs[spec->num_iverbs++] = vt1802_init_verbs; - else - spec->init_verbs[spec->num_iverbs++] = vt2002P_init_verbs; - return 0; error: @@ -1122,13 +1124,15 @@ static int patch_vt1812(struct hda_codec *codec) override_mic_boost(codec, 0x29, 0, 3, 40); add_secret_dac_path(codec); + err = snd_hda_add_verbs(codec, vt1812_init_verbs); + if (err < 0) + goto error; + /* automatic parse from the BIOS config */ err = via_parse_auto_config(codec); if (err < 0) goto error; - spec->init_verbs[spec->num_iverbs++] = vt1812_init_verbs; - return 0; error: @@ -1161,13 +1165,15 @@ static int patch_vt3476(struct hda_codec *codec) spec->gen.mixer_nid = 0x3f; add_secret_dac_path(codec); + err = snd_hda_add_verbs(codec, vt3476_init_verbs); + if (err < 0) + goto error; + /* automatic parse from the BIOS config */ err = via_parse_auto_config(codec); if (err < 0) goto error; - spec->init_verbs[spec->num_iverbs++] = vt3476_init_verbs; - return 0; error: -- cgit v1.2.3 From efe557320ab6cea12205794fd4062e6e850b7e1c Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 15 Jun 2018 11:55:02 +0200 Subject: ALSA: hda/realtek - Apply PRE_PROBE fixup after ALC269 codec variant setups Currently patch_alc269() calls the fixup with HDA_FIXUP_ACT_PRE_PROBE before setting up the codec model-specific setups (e.g. setting codec_variant or mixer_nid setup). This is rather confusing as others do call the *_PRE_PROBE fixup after such a setup. Due to this disorder, we have to override spec->shutup not at the usual HDA_FIXUP_ACT_PRE_PROBE but the unusual HDA_FIXUP_ACT_PROBE time. This patch corrects the fixup call orders in patch_alc269(), and also corrects the action to set up spec->shutup accordingly. No functional changes but just refactoring. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 0e84d9cdd42d..c93e09f9c109 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4906,7 +4906,7 @@ static void alc_no_shutup(struct hda_codec *codec) static void alc_fixup_no_shutup(struct hda_codec *codec, const struct hda_fixup *fix, int action) { - if (action == HDA_FIXUP_ACT_PROBE) { + if (action == HDA_FIXUP_ACT_PRE_PROBE) { struct alc_spec *spec = codec->spec; spec->shutup = alc_no_shutup; } @@ -4988,10 +4988,9 @@ static void alc_fixup_dell_xps13(struct hda_codec *codec, * it causes a click noise at start up */ snd_hda_codec_set_pin_target(codec, 0x19, PIN_VREFHIZ); + spec->shutup = alc_shutup_dell_xps13; break; case HDA_FIXUP_ACT_PROBE: - spec->shutup = alc_shutup_dell_xps13; - /* Make the internal mic the default input source. */ for (i = 0; i < imux->num_items; i++) { if (spec->gen.imux_pins[i] == 0x12) { @@ -7037,18 +7036,6 @@ static int patch_alc269(struct hda_codec *codec) spec->shutup = alc_default_shutup; spec->init_hook = alc_default_init; - snd_hda_pick_fixup(codec, alc269_fixup_models, - alc269_fixup_tbl, alc269_fixups); - snd_hda_pick_pin_fixup(codec, alc269_pin_fixup_tbl, alc269_fixups); - snd_hda_pick_fixup(codec, NULL, alc269_fixup_vendor_tbl, - alc269_fixups); - snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); - - alc_auto_parse_customize_define(codec); - - if (has_cdefine_beep(codec)) - spec->gen.beep_nid = 0x01; - switch (codec->core.vendor_id) { case 0x10ec0269: spec->codec_variant = ALC269_TYPE_ALC269VA; @@ -7168,6 +7155,18 @@ static int patch_alc269(struct hda_codec *codec) spec->init_hook = alc5505_dsp_init; } + snd_hda_pick_fixup(codec, alc269_fixup_models, + alc269_fixup_tbl, alc269_fixups); + snd_hda_pick_pin_fixup(codec, alc269_pin_fixup_tbl, alc269_fixups); + snd_hda_pick_fixup(codec, NULL, alc269_fixup_vendor_tbl, + alc269_fixups); + snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); + + alc_auto_parse_customize_define(codec); + + if (has_cdefine_beep(codec)) + spec->gen.beep_nid = 0x01; + /* automatic parse from the BIOS config */ err = alc269_parse_auto_config(codec); if (err < 0) -- cgit v1.2.3 From 0e6995e3b37bac69b4a815a116f9992d31a7bba0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 26 Jun 2018 06:24:40 -0300 Subject: ALSA: Fix references to Documentation/.*/MultiSound Now that the documentation/script file got restored, fix the references within the Kernel tree. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Takashi Iwai --- Documentation/sound/alsa-configuration.rst | 2 +- sound/isa/Kconfig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/Documentation/sound/alsa-configuration.rst b/Documentation/sound/alsa-configuration.rst index 4d83c1c0ca04..4a3cecc8ad38 100644 --- a/Documentation/sound/alsa-configuration.rst +++ b/Documentation/sound/alsa-configuration.rst @@ -1568,7 +1568,7 @@ joystick_io The driver requires firmware files ``turtlebeach/msndinit.bin`` and ``turtlebeach/msndperm.bin`` in the proper firmware directory. -See Documentation/sound/oss/MultiSound for important information +See Documentation/sound/cards/multisound.sh for important information about this driver. Note that it has been discontinued, but the Voyetra Turtle Beach knowledge base entry for it is still available at diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig index 43b35a873d78..d7db1eeebc84 100644 --- a/sound/isa/Kconfig +++ b/sound/isa/Kconfig @@ -459,7 +459,7 @@ config SND_MSND_CLASSIC Say M here if you have a Turtle Beach MultiSound Classic, Tahiti or Monterey (not for the Pinnacle or Fiji). - See for important information + See for important information about this driver. Note that it has been discontinued, but the Voyetra Turtle Beach knowledge base entry for it is still available at . -- cgit v1.2.3 From aa3841b56b3b4f68d1e0a64941189ec932c4881b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 26 Jun 2018 07:42:40 +0200 Subject: ALSA: hda/realtek - Comprehensive model list for ALC662 & co ALC662 and others have far more fixup entries than the model table. Let's add more model string entries so that user can test / debug without compiling kernels at each time. Signed-off-by: Takashi Iwai --- Documentation/sound/hd-audio/models.rst | 36 +++++++++++++++++++++++++++++++++ sound/pci/hda/patch_realtek.c | 18 +++++++++++++++++ 2 files changed, 54 insertions(+) (limited to 'sound') diff --git a/Documentation/sound/hd-audio/models.rst b/Documentation/sound/hd-audio/models.rst index 7c2d37571af0..f2f8402ff899 100644 --- a/Documentation/sound/hd-audio/models.rst +++ b/Documentation/sound/hd-audio/models.rst @@ -87,8 +87,14 @@ alc700-ref ALC66x/67x/892 ============== +aspire + Subwoofer pin fixup for Aspire laptops +ideapad + Subwoofer pin fixup for Ideapad laptops mario Chromebook mario model fixup +hp-rp5800 + Headphone pin fixup for HP RP5800 asus-mode1 ASUS asus-mode2 @@ -105,10 +111,40 @@ asus-mode7 ASUS asus-mode8 ASUS +zotac-z68 + Front HP fixup for Zotac Z68 inv-dmic Inverted internal mic workaround +alc662-headset-multi + Dell headset jack, which can also be used as mic-in (ALC662) dell-headset-multi Headset jack, which can also be used as mic-in +alc662-headset + Headset mode support on ALC662 +alc668-headset + Headset mode support on ALC668 +bass16 + Bass speaker fixup on pin 0x16 +bass1a + Bass speaker fixup on pin 0x1a +automute + Auto-mute fixups for ALC668 +dell-xps13 + Dell XPS13 fixups +asus-nx50 + ASUS Nx50 fixups +asus-nx51 + ASUS Nx51 fixups +alc891-headset + Headset mode support on ALC891 +alc891-headset-multi + Dell headset jack, which can also be used as mic-in (ALC891) +acer-veriton + Acer Veriton speaker pin fixup +asrock-mobo + Fix invalid 0x15 / 0x16 pins +usi-headset + Headset support on USI machines dual-codecs Lenovo laptops with dual codecs diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index c93e09f9c109..c7c9b47c2d5d 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -8012,7 +8012,10 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = { }; static const struct hda_model_fixup alc662_fixup_models[] = { + {.id = ALC662_FIXUP_ASPIRE, .name = "aspire"}, + {.id = ALC662_FIXUP_IDEAPAD, .name = "ideapad"}, {.id = ALC272_FIXUP_MARIO, .name = "mario"}, + {.id = ALC662_FIXUP_HP_RP5800, .name = "hp-rp5800"}, {.id = ALC662_FIXUP_ASUS_MODE1, .name = "asus-mode1"}, {.id = ALC662_FIXUP_ASUS_MODE2, .name = "asus-mode2"}, {.id = ALC662_FIXUP_ASUS_MODE3, .name = "asus-mode3"}, @@ -8021,8 +8024,23 @@ static const struct hda_model_fixup alc662_fixup_models[] = { {.id = ALC662_FIXUP_ASUS_MODE6, .name = "asus-mode6"}, {.id = ALC662_FIXUP_ASUS_MODE7, .name = "asus-mode7"}, {.id = ALC662_FIXUP_ASUS_MODE8, .name = "asus-mode8"}, + {.id = ALC662_FIXUP_ZOTAC_Z68, .name = "zotac-z68"}, {.id = ALC662_FIXUP_INV_DMIC, .name = "inv-dmic"}, + {.id = ALC662_FIXUP_DELL_MIC_NO_PRESENCE, .name = "alc662-headset-multi"}, {.id = ALC668_FIXUP_DELL_MIC_NO_PRESENCE, .name = "dell-headset-multi"}, + {.id = ALC662_FIXUP_HEADSET_MODE, .name = "alc662-headset"}, + {.id = ALC668_FIXUP_HEADSET_MODE, .name = "alc668-headset"}, + {.id = ALC662_FIXUP_BASS_16, .name = "bass16"}, + {.id = ALC662_FIXUP_BASS_1A, .name = "bass1a"}, + {.id = ALC668_FIXUP_AUTO_MUTE, .name = "automute"}, + {.id = ALC668_FIXUP_DELL_XPS13, .name = "dell-xps13"}, + {.id = ALC662_FIXUP_ASUS_Nx50, .name = "asus-nx50"}, + {.id = ALC668_FIXUP_ASUS_Nx51, .name = "asus-nx51"}, + {.id = ALC891_FIXUP_HEADSET_MODE, .name = "alc891-headset"}, + {.id = ALC891_FIXUP_DELL_MIC_NO_PRESENCE, .name = "alc891-headset-multi"}, + {.id = ALC662_FIXUP_ACER_VERITON, .name = "acer-veriton"}, + {.id = ALC892_FIXUP_ASROCK_MOBO, .name = "asrock-mobo"}, + {.id = ALC662_FIXUP_USI_HEADSET_MODE, .name = "usi-headset"}, {.id = ALC662_FIXUP_LENOVO_MULTI_CODECS, .name = "dual-codecs"}, {} }; -- cgit v1.2.3 From a26d96c7802e09473d5997791829774ba4f7e867 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 26 Jun 2018 15:09:25 +0200 Subject: ALSA: hda/realtek - Comprehensive model list for ALC259 & co Like the previous commit for ALC662, let's give more comprehensive list of model entries for ALC269 & co as well. Signed-off-by: Takashi Iwai --- Documentation/sound/hd-audio/models.rst | 156 ++++++++++++++++++++++++++++++++ sound/pci/hda/patch_realtek.c | 82 +++++++++++++++++ 2 files changed, 238 insertions(+) (limited to 'sound') diff --git a/Documentation/sound/hd-audio/models.rst b/Documentation/sound/hd-audio/models.rst index f2f8402ff899..a403a7f34a78 100644 --- a/Documentation/sound/hd-audio/models.rst +++ b/Documentation/sound/hd-audio/models.rst @@ -70,6 +70,10 @@ dell-headset-multi Headset jack, which can also be used as mic-in dell-headset-dock Headset jack (without mic-in), and also dock I/O +dell-headset3 + Headset jack (without mic-in), and also dock I/O, variant 3 +dell-headset4 + Headset jack (without mic-in), and also dock I/O, variant 4 alc283-dac-wcaps Fixups for Chromebook with ALC283 alc283-sense-combo @@ -80,10 +84,162 @@ tpt440 Lenovo Thinkpad T440s setup tpt460 Lenovo Thinkpad T460/560 setup +tpt470-dock + Lenovo Thinkpad T470 dock setup dual-codecs Lenovo laptops with dual codecs alc700-ref Intel reference board with ALC700 codec +vaio + Pin fixups for Sony VAIO laptops +dell-m101z + COEF setup for Dell M101z +asus-g73jw + Subwoofer pin fixup for ASUS G73JW +lenovo-eapd + Inversed EAPD setup for Lenovo laptops +sony-hweq + H/W EQ COEF setup for Sony laptops +pcm44k + Fixed PCM 44kHz constraints (for buggy devices) +lifebook + Dock pin fixups for Fujitsu Lifebook +lifebook-extmic + Headset mic fixup for Fujitsu Lifebook +lifebook-hp-pin + Headphone pin fixup for Fujitsu Lifebook +lifebook-u7x7 + Lifebook U7x7 fixups +alc269vb-amic + ALC269VB analog mic pin fixups +alc269vb-dmic + ALC269VB digital mic pin fixups +hp-mute-led-mic1 + Mute LED via Mic1 pin on HP +hp-mute-led-mic2 + Mute LED via Mic2 pin on HP +hp-mute-led-mic3 + Mute LED via Mic3 pin on HP +hp-gpio-mic1 + GPIO + Mic1 pin LED on HP +hp-line1-mic1 + Mute LED via Line1 + Mic1 pins on HP +noshutup + Skip shutup callback +sony-nomic + Headset mic fixup for Sony laptops +aspire-headset-mic + Headset pin fixup for Acer Aspire +asus-x101 + ASUS X101 fixups +acer-ao7xx + Acer AO7xx fixups +acer-aspire-e1 + Acer Aspire E1 fixups +acer-ac700 + Acer AC700 fixups +limit-mic-boost + Limit internal mic boost on Lenovo machines +asus-zenbook + ASUS Zenbook fixups +asus-zenbook-ux31a + ASUS Zenbook UX31A fixups +ordissimo + Ordissimo EVE2 (or Malata PC-B1303) fixups +asus-tx300 + ASUS TX300 fixups +alc283-int-mic + ALC283 COEF setup for Lenovo machines +mono-speakers + Subwoofer and headset fixupes for Dell Inspiron +alc290-subwoofer + Subwoofer fixups for Dell Vostro +thinkpad + Binding with thinkpad_acpi driver for Lenovo machines +dmic-thinkpad + thinkpad_acpi binding + digital mic support +alc255-acer + ALC255 fixups on Acer machines +alc255-asus + ALC255 fixups on ASUS machines +alc255-dell1 + ALC255 fixups on Dell machines +alc255-dell2 + ALC255 fixups on Dell machines, variant 2 +alc293-dell1 + ALC293 fixups on Dell machines +alc283-headset + Headset pin fixups on ALC283 +aspire-v5 + Acer Aspire V5 fixups +hp-gpio4 + GPIO and Mic1 pin mute LED fixups for HP +hp-gpio-led + GPIO mute LEDs on HP +hp-gpio2-hotkey + GPIO mute LED with hot key handling on HP +hp-dock-pins + GPIO mute LEDs and dock support on HP +hp-dock-gpio-mic + GPIO, Mic mute LED and dock support on HP +hp-9480m + HP 9480m fixups +alc288-dell1 + ALC288 fixups on Dell machines +alc288-dell-xps13 + ALC288 fixups on Dell XPS13 +dell-e7x + Dell E7x fixups +alc293-dell + ALC293 fixups on Dell machines +alc298-dell1 + ALC298 fixups on Dell machines +alc298-dell-aio + ALC298 fixups on Dell AIO machines +alc275-dell-xps + ALC275 fixups on Dell XPS models +alc256-dell-xps13 + ALC256 fixups on Dell XPS13 +lenovo-spk-noise + Workaround for speaker noise on Lenovo machines +lenovo-hotkey + Hot-key support via Mic2 pin on Lenovo machines +dell-spk-noise + Workaround for speaker noise on Dell machines +alc255-dell1 + ALC255 fixups on Dell machines +alc295-disable-dac3 + Disable DAC3 routing on ALC295 +alc280-hp-headset + HP Elitebook fixups +alc221-hp-mic + Front mic pin fixup on HP machines +alc298-spk-volume + Speaker pin routing workaround on ALC298 +dell-inspiron-7559 + Dell Inspiron 7559 fixups +ativ-book + Samsung Ativ book 8 fixups +alc221-hp-mic + ALC221 headset fixups on HP machines +alc256-asus-mic + ALC256 fixups on ASUS machines +alc256-asus-aio + ALC256 fixups on ASUS AIO machines +alc233-eapd + ALC233 fixups on ASUS machines +alc294-lenovo-mic + ALC294 Mic pin fixup for Lenovo AIO machines +alc225-wyse + Dell Wyse fixups +alc274-dell-aio + ALC274 fixups on Dell AIO machines +alc255-dummy-lineout + Dell Precision 3930 fixups +alc255-dell-headset"}, + Dell Precision 3630 fixups +alc295-hp-x360 + HP Spectre X360 fixups ALC66x/67x/892 ============== diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index c7c9b47c2d5d..a0828befe62a 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -6620,13 +6620,95 @@ static const struct hda_model_fixup alc269_fixup_models[] = { {.id = ALC269_FIXUP_HP_DOCK_GPIO_MIC1_LED, .name = "hp-dock-gpio-mic1-led"}, {.id = ALC269_FIXUP_DELL1_MIC_NO_PRESENCE, .name = "dell-headset-multi"}, {.id = ALC269_FIXUP_DELL2_MIC_NO_PRESENCE, .name = "dell-headset-dock"}, + {.id = ALC269_FIXUP_DELL3_MIC_NO_PRESENCE, .name = "dell-headset3"}, + {.id = ALC269_FIXUP_DELL4_MIC_NO_PRESENCE, .name = "dell-headset4"}, {.id = ALC283_FIXUP_CHROME_BOOK, .name = "alc283-dac-wcaps"}, {.id = ALC283_FIXUP_SENSE_COMBO_JACK, .name = "alc283-sense-combo"}, {.id = ALC292_FIXUP_TPT440_DOCK, .name = "tpt440-dock"}, {.id = ALC292_FIXUP_TPT440, .name = "tpt440"}, {.id = ALC292_FIXUP_TPT460, .name = "tpt460"}, + {.id = ALC298_FIXUP_TPT470_DOCK, .name = "tpt470-dock"}, {.id = ALC233_FIXUP_LENOVO_MULTI_CODECS, .name = "dual-codecs"}, {.id = ALC700_FIXUP_INTEL_REFERENCE, .name = "alc700-ref"}, + {.id = ALC269_FIXUP_SONY_VAIO, .name = "vaio"}, + {.id = ALC269_FIXUP_DELL_M101Z, .name = "dell-m101z"}, + {.id = ALC269_FIXUP_ASUS_G73JW, .name = "asus-g73jw"}, + {.id = ALC269_FIXUP_LENOVO_EAPD, .name = "lenovo-eapd"}, + {.id = ALC275_FIXUP_SONY_HWEQ, .name = "sony-hweq"}, + {.id = ALC269_FIXUP_PCM_44K, .name = "pcm44k"}, + {.id = ALC269_FIXUP_LIFEBOOK, .name = "lifebook"}, + {.id = ALC269_FIXUP_LIFEBOOK_EXTMIC, .name = "lifebook-extmic"}, + {.id = ALC269_FIXUP_LIFEBOOK_HP_PIN, .name = "lifebook-hp-pin"}, + {.id = ALC255_FIXUP_LIFEBOOK_U7x7_HEADSET_MIC, .name = "lifebook-u7x7"}, + {.id = ALC269VB_FIXUP_AMIC, .name = "alc269vb-amic"}, + {.id = ALC269VB_FIXUP_DMIC, .name = "alc269vb-dmic"}, + {.id = ALC269_FIXUP_HP_MUTE_LED_MIC1, .name = "hp-mute-led-mic1"}, + {.id = ALC269_FIXUP_HP_MUTE_LED_MIC2, .name = "hp-mute-led-mic2"}, + {.id = ALC269_FIXUP_HP_MUTE_LED_MIC3, .name = "hp-mute-led-mic3"}, + {.id = ALC269_FIXUP_HP_GPIO_MIC1_LED, .name = "hp-gpio-mic1"}, + {.id = ALC269_FIXUP_HP_LINE1_MIC1_LED, .name = "hp-line1-mic1"}, + {.id = ALC269_FIXUP_NO_SHUTUP, .name = "noshutup"}, + {.id = ALC286_FIXUP_SONY_MIC_NO_PRESENCE, .name = "sony-nomic"}, + {.id = ALC269_FIXUP_ASPIRE_HEADSET_MIC, .name = "aspire-headset-mic"}, + {.id = ALC269_FIXUP_ASUS_X101, .name = "asus-x101"}, + {.id = ALC271_FIXUP_HP_GATE_MIC_JACK, .name = "acer-ao7xx"}, + {.id = ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572, .name = "acer-aspire-e1"}, + {.id = ALC269_FIXUP_ACER_AC700, .name = "acer-ac700"}, + {.id = ALC269_FIXUP_LIMIT_INT_MIC_BOOST, .name = "limit-mic-boost"}, + {.id = ALC269VB_FIXUP_ASUS_ZENBOOK, .name = "asus-zenbook"}, + {.id = ALC269VB_FIXUP_ASUS_ZENBOOK_UX31A, .name = "asus-zenbook-ux31a"}, + {.id = ALC269VB_FIXUP_ORDISSIMO_EVE2, .name = "ordissimo"}, + {.id = ALC282_FIXUP_ASUS_TX300, .name = "asus-tx300"}, + {.id = ALC283_FIXUP_INT_MIC, .name = "alc283-int-mic"}, + {.id = ALC290_FIXUP_MONO_SPEAKERS_HSJACK, .name = "mono-speakers"}, + {.id = ALC290_FIXUP_SUBWOOFER_HSJACK, .name = "alc290-subwoofer"}, + {.id = ALC269_FIXUP_THINKPAD_ACPI, .name = "thinkpad"}, + {.id = ALC269_FIXUP_DMIC_THINKPAD_ACPI, .name = "dmic-thinkpad"}, + {.id = ALC255_FIXUP_ACER_MIC_NO_PRESENCE, .name = "alc255-acer"}, + {.id = ALC255_FIXUP_ASUS_MIC_NO_PRESENCE, .name = "alc255-asus"}, + {.id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, .name = "alc255-dell1"}, + {.id = ALC255_FIXUP_DELL2_MIC_NO_PRESENCE, .name = "alc255-dell2"}, + {.id = ALC293_FIXUP_DELL1_MIC_NO_PRESENCE, .name = "alc293-dell1"}, + {.id = ALC283_FIXUP_HEADSET_MIC, .name = "alc283-headset"}, + {.id = ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED, .name = "alc255-dell-mute"}, + {.id = ALC282_FIXUP_ASPIRE_V5_PINS, .name = "aspire-v5"}, + {.id = ALC280_FIXUP_HP_GPIO4, .name = "hp-gpio4"}, + {.id = ALC286_FIXUP_HP_GPIO_LED, .name = "hp-gpio-led"}, + {.id = ALC280_FIXUP_HP_GPIO2_MIC_HOTKEY, .name = "hp-gpio2-hotkey"}, + {.id = ALC280_FIXUP_HP_DOCK_PINS, .name = "hp-dock-pins"}, + {.id = ALC269_FIXUP_HP_DOCK_GPIO_MIC1_LED, .name = "hp-dock-gpio-mic"}, + {.id = ALC280_FIXUP_HP_9480M, .name = "hp-9480m"}, + {.id = ALC288_FIXUP_DELL_HEADSET_MODE, .name = "alc288-dell-headset"}, + {.id = ALC288_FIXUP_DELL1_MIC_NO_PRESENCE, .name = "alc288-dell1"}, + {.id = ALC288_FIXUP_DELL_XPS_13, .name = "alc288-dell-xps13"}, + {.id = ALC292_FIXUP_DELL_E7X, .name = "dell-e7x"}, + {.id = ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK, .name = "alc293-dell"}, + {.id = ALC298_FIXUP_DELL1_MIC_NO_PRESENCE, .name = "alc298-dell1"}, + {.id = ALC298_FIXUP_DELL_AIO_MIC_NO_PRESENCE, .name = "alc298-dell-aio"}, + {.id = ALC275_FIXUP_DELL_XPS, .name = "alc275-dell-xps"}, + {.id = ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE, .name = "alc256-dell-xps13"}, + {.id = ALC293_FIXUP_LENOVO_SPK_NOISE, .name = "lenovo-spk-noise"}, + {.id = ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY, .name = "lenovo-hotkey"}, + {.id = ALC255_FIXUP_DELL_SPK_NOISE, .name = "dell-spk-noise"}, + {.id = ALC225_FIXUP_DELL1_MIC_NO_PRESENCE, .name = "alc255-dell1"}, + {.id = ALC295_FIXUP_DISABLE_DAC3, .name = "alc295-disable-dac3"}, + {.id = ALC280_FIXUP_HP_HEADSET_MIC, .name = "alc280-hp-headset"}, + {.id = ALC221_FIXUP_HP_FRONT_MIC, .name = "alc221-hp-mic"}, + {.id = ALC298_FIXUP_SPK_VOLUME, .name = "alc298-spk-volume"}, + {.id = ALC256_FIXUP_DELL_INSPIRON_7559_SUBWOOFER, .name = "dell-inspiron-7559"}, + {.id = ALC269_FIXUP_ATIV_BOOK_8, .name = "ativ-book"}, + {.id = ALC221_FIXUP_HP_MIC_NO_PRESENCE, .name = "alc221-hp-mic"}, + {.id = ALC256_FIXUP_ASUS_HEADSET_MODE, .name = "alc256-asus-headset"}, + {.id = ALC256_FIXUP_ASUS_MIC, .name = "alc256-asus-mic"}, + {.id = ALC256_FIXUP_ASUS_AIO_GPIO2, .name = "alc256-asus-aio"}, + {.id = ALC233_FIXUP_ASUS_MIC_NO_PRESENCE, .name = "alc233-asus"}, + {.id = ALC233_FIXUP_EAPD_COEF_AND_MIC_NO_PRESENCE, .name = "alc233-eapd"}, + {.id = ALC294_FIXUP_LENOVO_MIC_LOCATION, .name = "alc294-lenovo-mic"}, + {.id = ALC225_FIXUP_DELL_WYSE_MIC_NO_PRESENCE, .name = "alc225-wyse"}, + {.id = ALC274_FIXUP_DELL_AIO_LINEOUT_VERB, .name = "alc274-dell-aio"}, + {.id = ALC255_FIXUP_DUMMY_LINEOUT_VERB, .name = "alc255-dummy-lineout"}, + {.id = ALC255_FIXUP_DELL_HEADSET_MIC, .name = "alc255-dell-headset"}, + {.id = ALC295_FIXUP_HP_X360, .name = "alc295-hp-x360"}, {} }; #define ALC225_STANDARD_PINS \ -- cgit v1.2.3 From 03bf11c934c3ced43aa9be3cfb93962ab15d737b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 26 Jun 2018 16:56:41 +0200 Subject: ALSA: hda/realtek - Comprehensive model list for ALC268 Add the missing entry for ALC268 model strings. Only "spdif" was missing, and that's it. Signed-off-by: Takashi Iwai --- Documentation/sound/hd-audio/models.rst | 2 ++ sound/pci/hda/patch_realtek.c | 1 + 2 files changed, 3 insertions(+) (limited to 'sound') diff --git a/Documentation/sound/hd-audio/models.rst b/Documentation/sound/hd-audio/models.rst index a403a7f34a78..323c25c53eaf 100644 --- a/Documentation/sound/hd-audio/models.rst +++ b/Documentation/sound/hd-audio/models.rst @@ -41,6 +41,8 @@ inv-dmic Inverted internal mic workaround hp-eapd Disable HP EAPD on NID 0x15 +spdif + Enable SPDIF output on NID 0x1e ALC22x/23x/25x/269/27x/28x/29x (and vendor-specific ALC3xxx models) =================================================================== diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index a0828befe62a..74540e0fa19d 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -2688,6 +2688,7 @@ static const struct hda_fixup alc268_fixups[] = { static const struct hda_model_fixup alc268_fixup_models[] = { {.id = ALC268_FIXUP_INV_DMIC, .name = "inv-dmic"}, {.id = ALC268_FIXUP_HP_EAPD, .name = "hp-eapd"}, + {.id = ALC268_FIXUP_SPDIF, .name = "spdif"}, {} }; -- cgit v1.2.3 From e43c44d62dbb4d8e2f217198142c97fce1a25ac1 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 26 Jun 2018 17:02:08 +0200 Subject: ALSA: hda/realtek - Comprehensive model list for ALC262 Added a few missing entries for ALC262 model strings. All about specific hardwares. Signed-off-by: Takashi Iwai --- Documentation/sound/hd-audio/models.rst | 16 ++++++++++++++++ sound/pci/hda/patch_realtek.c | 8 ++++++++ 2 files changed, 24 insertions(+) (limited to 'sound') diff --git a/Documentation/sound/hd-audio/models.rst b/Documentation/sound/hd-audio/models.rst index 323c25c53eaf..560235519555 100644 --- a/Documentation/sound/hd-audio/models.rst +++ b/Documentation/sound/hd-audio/models.rst @@ -34,6 +34,22 @@ ALC262 ====== inv-dmic Inverted internal mic workaround +fsc-h270 + Fixups for Fujitsu-Siemens Celsius H270 +fsc-s7110 + Fixups for Fujitsu-Siemens Lifebook S7110 +hp-z200 + Fixups for HP Z200 +tyan + Fixups for Tyan Thunder n6650W +lenovo-3000 + Fixups for Lenovo 3000 +benq + Fixups for Benq ED8 +benq-t31 + Fixups for Benq T31 +bayleybay + Fixups for Intel BayleyBay ALC267/268 ========== diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 74540e0fa19d..fc21e2851b01 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -2557,6 +2557,14 @@ static const struct snd_pci_quirk alc262_fixup_tbl[] = { static const struct hda_model_fixup alc262_fixup_models[] = { {.id = ALC262_FIXUP_INV_DMIC, .name = "inv-dmic"}, + {.id = ALC262_FIXUP_FSC_H270, .name = "fsc-h270"}, + {.id = ALC262_FIXUP_FSC_S7110, .name = "fsc-s7110"}, + {.id = ALC262_FIXUP_HP_Z200, .name = "hp-z200"}, + {.id = ALC262_FIXUP_TYAN, .name = "tyan"}, + {.id = ALC262_FIXUP_LENOVO_3000, .name = "lenovo-3000"}, + {.id = ALC262_FIXUP_BENQ, .name = "benq"}, + {.id = ALC262_FIXUP_BENQ_T31, .name = "benq-t31"}, + {.id = ALC262_FIXUP_INTEL_BAYLEYBAY, .name = "bayleybay"}, {} }; -- cgit v1.2.3 From 772c2917ff4e3b15c38f74e77062360e5ffd1308 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 26 Jun 2018 17:17:53 +0200 Subject: ALSA: hda/realtek - Comprehensive model list for ALC882 & co More comprehensive list of model strings for ALC882 & co. Also corrected the subsection in models.rst, too. Signed-off-by: Takashi Iwai --- Documentation/sound/hd-audio/models.rst | 54 +++++++++++++++++++++++++++++++-- sound/pci/hda/patch_realtek.c | 25 +++++++++++++++ 2 files changed, 77 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/Documentation/sound/hd-audio/models.rst b/Documentation/sound/hd-audio/models.rst index 560235519555..e06238131f77 100644 --- a/Documentation/sound/hd-audio/models.rst +++ b/Documentation/sound/hd-audio/models.rst @@ -326,20 +326,70 @@ ALC680 ====== N/A -ALC88x/898/1150 -====================== +ALC88x/898/1150/1220 +==================== +abit-aw9d + Pin fixups for Abit AW9D-MAX +lenovo-y530 + Pin fixups for Lenovo Y530 +acer-aspire-7736 + Fixup for Acer Aspire 7736 +asus-w90v + Pin fixup for ASUS W90V +cd + Enable audio CD pin NID 0x1c +no-front-hp + Disable front HP pin NID 0x1b +vaio-tt + Pin fixup for VAIO TT +eee1601 + COEF setups for ASUS Eee 1601 +alc882-eapd + Change EAPD COEF mode on ALC882 +alc883-eapd + Change EAPD COEF mode on ALC883 +gpio1 + Enable GPIO1 +gpio2 + Enable GPIO2 +gpio3 + Enable GPIO3 +alc889-coef + Setup ALC889 COEF +asus-w2jc + Fixups for ASUS W2JC acer-aspire-4930g Acer Aspire 4930G/5930G/6530G/6930G/7730G acer-aspire-8930g Acer Aspire 8330G/6935G acer-aspire Acer Aspire others +macpro-gpio + GPIO setup for Mac Pro +dac-route + Workaround for DAC routing on Acer Aspire +mbp-vref + Vref setup for Macbook Pro +imac91-vref + Vref setup for iMac 9,1 +mba11-vref + Vref setup for MacBook Air 1,1 +mba21-vref + Vref setup for MacBook Air 2,1 +mp11-vref + Vref setup for Mac Pro 1,1 +mp41-vref + Vref setup for Mac Pro 4,1 inv-dmic Inverted internal mic workaround no-primary-hp VAIO Z/VGC-LN51JGB workaround (for fixed speaker DAC) +asus-bass + Bass speaker setup for ASUS ET2700 dual-codecs ALC1220 dual codecs for Gaming mobos +clevo-p950 + Fixups for Clevo P950 ALC861/660 ========== diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index fc21e2851b01..003e2c90e792 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -2374,12 +2374,37 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = { }; static const struct hda_model_fixup alc882_fixup_models[] = { + {.id = ALC882_FIXUP_ABIT_AW9D_MAX, .name = "abit-aw9d"}, + {.id = ALC882_FIXUP_LENOVO_Y530, .name = "lenovo-y530"}, + {.id = ALC882_FIXUP_ACER_ASPIRE_7736, .name = "acer-aspire-7736"}, + {.id = ALC882_FIXUP_ASUS_W90V, .name = "asus-w90v"}, + {.id = ALC889_FIXUP_CD, .name = "cd"}, + {.id = ALC889_FIXUP_FRONT_HP_NO_PRESENCE, .name = "no-front-hp"}, + {.id = ALC889_FIXUP_VAIO_TT, .name = "vaio-tt"}, + {.id = ALC888_FIXUP_EEE1601, .name = "eee1601"}, + {.id = ALC882_FIXUP_EAPD, .name = "alc882-eapd"}, + {.id = ALC883_FIXUP_EAPD, .name = "alc883-eapd"}, + {.id = ALC882_FIXUP_GPIO1, .name = "gpio1"}, + {.id = ALC882_FIXUP_GPIO2, .name = "gpio2"}, + {.id = ALC882_FIXUP_GPIO3, .name = "gpio3"}, + {.id = ALC889_FIXUP_COEF, .name = "alc889-coef"}, + {.id = ALC882_FIXUP_ASUS_W2JC, .name = "asus-w2jc"}, {.id = ALC882_FIXUP_ACER_ASPIRE_4930G, .name = "acer-aspire-4930g"}, {.id = ALC882_FIXUP_ACER_ASPIRE_8930G, .name = "acer-aspire-8930g"}, {.id = ALC883_FIXUP_ACER_EAPD, .name = "acer-aspire"}, + {.id = ALC885_FIXUP_MACPRO_GPIO, .name = "macpro-gpio"}, + {.id = ALC889_FIXUP_DAC_ROUTE, .name = "dac-route"}, + {.id = ALC889_FIXUP_MBP_VREF, .name = "mbp-vref"}, + {.id = ALC889_FIXUP_IMAC91_VREF, .name = "imac91-vref"}, + {.id = ALC889_FIXUP_MBA11_VREF, .name = "mba11-vref"}, + {.id = ALC889_FIXUP_MBA21_VREF, .name = "mba21-vref"}, + {.id = ALC889_FIXUP_MP11_VREF, .name = "mp11-vref"}, + {.id = ALC889_FIXUP_MP41_VREF, .name = "mp41-vref"}, {.id = ALC882_FIXUP_INV_DMIC, .name = "inv-dmic"}, {.id = ALC882_FIXUP_NO_PRIMARY_HP, .name = "no-primary-hp"}, + {.id = ALC887_FIXUP_ASUS_BASS, .name = "asus-bass"}, {.id = ALC1220_FIXUP_GB_DUAL_CODECS, .name = "dual-codecs"}, + {.id = ALC1220_FIXUP_CLEVO_P950, .name = "clevo-p950"}, {} }; -- cgit v1.2.3 From 401caff70cd3d3ef3c96e1a1cbf6f973c24ba899 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 27 Jun 2018 11:43:09 +0200 Subject: ALSA: hda - Kill snd_hda_codec_update_cache() snd_hda_codec_update_cache() used to serve for a slightly different purpose from snd_hdac_write_cache(), but now both of them became identical. Let's unify and replace with the latter one consistently. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 4 ++-- sound/pci/hda/hda_codec.h | 3 --- sound/pci/hda/hda_generic.c | 8 ++++---- sound/pci/hda/patch_analog.c | 4 ++-- sound/pci/hda/patch_conexant.c | 2 +- 5 files changed, 9 insertions(+), 12 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index d91c87e41756..f42af88bd2de 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -3842,7 +3842,7 @@ EXPORT_SYMBOL_GPL(snd_hda_correct_pin_ctl); * This function is a helper to set a pin ctl value more safely. * It corrects the pin ctl value via snd_hda_correct_pin_ctl(), stores the * value in pin target array via snd_hda_codec_set_pin_target(), then - * actually writes the value via either snd_hda_codec_update_cache() or + * actually writes the value via either snd_hda_codec_write_cache() or * snd_hda_codec_write() depending on @cached flag. */ int _snd_hda_set_pin_ctl(struct hda_codec *codec, hda_nid_t pin, @@ -3851,7 +3851,7 @@ int _snd_hda_set_pin_ctl(struct hda_codec *codec, hda_nid_t pin, val = snd_hda_correct_pin_ctl(codec, pin, val); snd_hda_codec_set_pin_target(codec, pin, val); if (cached) - return snd_hda_codec_update_cache(codec, pin, 0, + return snd_hda_codec_write_cache(codec, pin, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, val); else return snd_hda_codec_write(codec, pin, 0, diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 681c360f29f9..8a095c16ee65 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h @@ -381,9 +381,6 @@ snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid, return snd_hdac_regmap_write(&codec->core, nid, verb, parm); } -#define snd_hda_codec_update_cache(codec, nid, flags, verb, parm) \ - snd_hda_codec_write_cache(codec, nid, flags, verb, parm) - /* the struct for codec->pin_configs */ struct hda_pincfg { hda_nid_t nid; diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 942f96e184b6..579984ecdec3 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c @@ -209,7 +209,7 @@ static void parse_user_hints(struct hda_codec *codec) */ #define update_pin_ctl(codec, pin, val) \ - snd_hda_codec_update_cache(codec, pin, 0, \ + snd_hda_codec_write_cache(codec, pin, 0, \ AC_VERB_SET_PIN_WIDGET_CONTROL, val) /* restore the pinctl based on the cached value */ @@ -898,7 +898,7 @@ void snd_hda_activate_path(struct hda_codec *codec, struct nid_path *path, hda_nid_t nid = path->path[i]; if (enable && path->multi[i]) - snd_hda_codec_update_cache(codec, nid, 0, + snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, path->idx[i]); if (has_amp_in(codec, path, i)) @@ -930,7 +930,7 @@ static void set_pin_eapd(struct hda_codec *codec, hda_nid_t pin, bool enable) return; if (codec->inv_eapd) enable = !enable; - snd_hda_codec_update_cache(codec, pin, 0, + snd_hda_codec_write_cache(codec, pin, 0, AC_VERB_SET_EAPD_BTLENABLE, enable ? 0x02 : 0x00); } @@ -5973,7 +5973,7 @@ static void clear_unsol_on_unused_pins(struct hda_codec *codec) hda_nid_t nid = pin->nid; if (is_jack_detectable(codec, nid) && !snd_hda_jack_tbl_get(codec, nid)) - snd_hda_codec_update_cache(codec, nid, 0, + snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_UNSOLICITED_ENABLE, 0); } } diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 757857313426..fd476fb40e1b 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -148,7 +148,7 @@ static void ad_vmaster_eapd_hook(void *private_data, int enabled) return; if (codec->inv_eapd) enabled = !enabled; - snd_hda_codec_update_cache(codec, spec->eapd_nid, 0, + snd_hda_codec_write_cache(codec, spec->eapd_nid, 0, AC_VERB_SET_EAPD_BTLENABLE, enabled ? 0x02 : 0x00); } @@ -991,7 +991,7 @@ static void ad1884_vmaster_hp_gpio_hook(void *private_data, int enabled) if (spec->eapd_nid) ad_vmaster_eapd_hook(private_data, enabled); - snd_hda_codec_update_cache(codec, 0x01, 0, + snd_hda_codec_write_cache(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, enabled ? 0x00 : 0x02); } diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 75ba66eb4ccd..8b48352689b4 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -341,7 +341,7 @@ static void cxt_fixup_headset_mic(struct hda_codec *codec, * control. */ #define update_mic_pin(codec, nid, val) \ - snd_hda_codec_update_cache(codec, nid, 0, \ + snd_hda_codec_write_cache(codec, nid, 0, \ AC_VERB_SET_PIN_WIDGET_CONTROL, val) static const struct hda_input_mux olpc_xo_dc_bias = { -- cgit v1.2.3 From c288248f5b26cd5563112fcdc077bf44964a942d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 27 Jun 2018 14:59:00 +0200 Subject: ALSA: intel_hdmi: Use strlcpy() instead of strncpy() hdmi_lpe_audio_probe() copies the pcm name string via strncpy(), but as a gcc8 warning suggests, it misses a NUL terminator, and unlikely the expected result. Use the proper one, strlcpy() instead. Signed-off-by: Takashi Iwai --- sound/x86/intel_hdmi_audio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/x86/intel_hdmi_audio.c b/sound/x86/intel_hdmi_audio.c index 4ed9d0c41843..edc9f5a34eff 100644 --- a/sound/x86/intel_hdmi_audio.c +++ b/sound/x86/intel_hdmi_audio.c @@ -1854,7 +1854,7 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev) /* setup private data which can be retrieved when required */ pcm->private_data = ctx; pcm->info_flags = 0; - strncpy(pcm->name, card->shortname, strlen(card->shortname)); + strlcpy(pcm->name, card->shortname, strlen(card->shortname)); /* setup the ops for playabck */ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &had_pcm_ops); -- cgit v1.2.3 From feb20faec73ba0b30f949d54c4153cf0ad3807c8 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 27 Jun 2018 09:03:51 +0200 Subject: ALSA: hda - Move in_pm accessors to HDA core The in_pm atomic in hdac_device is an important field used as a flag as well as a refcount for PM. The existing snd_hdac_power_up/down helpers already refer to it in the HD-audio core code, while the code to actually setting the value (atomic_inc() / _dec()) is open-coded in HDA legacy side, which is hard to find. This patch adds the helper functions to set/reset the in_pm counter to HDA core and use them in HDA legacy side, for making it clearer who / where the PM is managed. There is no functional changes, just code refactoring. Reviewed-by: Chris Wilson Signed-off-by: Takashi Iwai --- include/sound/hdaudio.h | 27 +++++++++++++++++++++++++++ sound/pci/hda/hda_codec.c | 21 ++++++--------------- sound/pci/hda/patch_hdmi.c | 2 +- 3 files changed, 34 insertions(+), 16 deletions(-) (limited to 'sound') diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h index c052afc27547..294a5a21937b 100644 --- a/include/sound/hdaudio.h +++ b/include/sound/hdaudio.h @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -171,12 +172,38 @@ int snd_hdac_power_down(struct hdac_device *codec); int snd_hdac_power_up_pm(struct hdac_device *codec); int snd_hdac_power_down_pm(struct hdac_device *codec); int snd_hdac_keep_power_up(struct hdac_device *codec); + +/* call this at entering into suspend/resume callbacks in codec driver */ +static inline void snd_hdac_enter_pm(struct hdac_device *codec) +{ + atomic_inc(&codec->in_pm); +} + +/* call this at leaving from suspend/resume callbacks in codec driver */ +static inline void snd_hdac_leave_pm(struct hdac_device *codec) +{ + atomic_dec(&codec->in_pm); +} + +static inline bool snd_hdac_is_in_pm(struct hdac_device *codec) +{ + return atomic_read(&codec->in_pm); +} + +static inline bool snd_hdac_is_power_on(struct hdac_device *codec) +{ + return !pm_runtime_suspended(&codec->dev); +} #else static inline int snd_hdac_power_up(struct hdac_device *codec) { return 0; } static inline int snd_hdac_power_down(struct hdac_device *codec) { return 0; } static inline int snd_hdac_power_up_pm(struct hdac_device *codec) { return 0; } static inline int snd_hdac_power_down_pm(struct hdac_device *codec) { return 0; } static inline int snd_hdac_keep_power_up(struct hdac_device *codec) { return 0; } +static inline void snd_hdac_enter_pm(struct hdac_device *codec) {} +static inline void snd_hdac_leave_pm(struct hdac_device *codec) {} +static inline bool snd_hdac_is_in_pm(struct hdac_device *codec) { return 0; } +static inline bool snd_hdac_is_power_on(struct hdac_device *codec) { return 1; } #endif /* diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index f42af88bd2de..decd46b51087 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -37,15 +37,8 @@ #include "hda_jack.h" #include -#ifdef CONFIG_PM -#define codec_in_pm(codec) atomic_read(&(codec)->core.in_pm) -#define hda_codec_is_power_on(codec) \ - (!pm_runtime_suspended(hda_codec_dev(codec))) -#else -#define codec_in_pm(codec) 0 -#define hda_codec_is_power_on(codec) 1 -#endif - +#define codec_in_pm(codec) snd_hdac_is_in_pm(&codec->core) +#define hda_codec_is_power_on(codec) snd_hdac_is_power_on(&codec->core) #define codec_has_epss(codec) \ ((codec)->core.power_caps & AC_PWRST_EPSS) #define codec_has_clkstop(codec) \ @@ -2846,14 +2839,13 @@ static unsigned int hda_call_codec_suspend(struct hda_codec *codec) { unsigned int state; - atomic_inc(&codec->core.in_pm); - + snd_hdac_enter_pm(&codec->core); if (codec->patch_ops.suspend) codec->patch_ops.suspend(codec); hda_cleanup_all_streams(codec); state = hda_set_power_state(codec, AC_PWRST_D3); update_power_acct(codec, true); - atomic_dec(&codec->core.in_pm); + snd_hdac_leave_pm(&codec->core); return state; } @@ -2862,8 +2854,7 @@ static unsigned int hda_call_codec_suspend(struct hda_codec *codec) */ static void hda_call_codec_resume(struct hda_codec *codec) { - atomic_inc(&codec->core.in_pm); - + snd_hdac_enter_pm(&codec->core); if (codec->core.regmap) regcache_mark_dirty(codec->core.regmap); @@ -2886,7 +2877,7 @@ static void hda_call_codec_resume(struct hda_codec *codec) hda_jackpoll_work(&codec->jackpoll_work.work); else snd_hda_jack_report_sync(codec); - atomic_dec(&codec->core.in_pm); + snd_hdac_leave_pm(&codec->core); } static int hda_codec_runtime_suspend(struct device *dev) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 8840daf9c6a3..ed2318f79e3c 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -2489,7 +2489,7 @@ static void intel_pin_eld_notify(void *audio_ptr, int port, int pipe) if (snd_power_get_state(codec->card) != SNDRV_CTL_POWER_D0) return; /* ditto during suspend/resume process itself */ - if (atomic_read(&(codec)->core.in_pm)) + if (snd_hdac_is_in_pm(&codec->core)) return; snd_hdac_i915_set_bclk(&codec->bus->core); -- cgit v1.2.3 From 3787a39852b0d6a9e67336f8fb5815c13ab78bb6 Mon Sep 17 00:00:00 2001 From: Rakesh Ughreja Date: Fri, 1 Jun 2018 22:53:49 -0500 Subject: ALSA: hdac: Remove usage of struct hdac_ext_device and use hdac_device instead This patch removes the hdac_ext_device structure. The legacy and enhanced HDaudio capabilities can be handled in a backward-compatible way without separate definitions. Follow-up patches in this series handle the bus and driver definitions. Signed-off-by: Rakesh Ughreja Signed-off-by: Pierre-Louis Bossart Signed-off-by: Takashi Iwai --- include/sound/hdaudio_ext.h | 36 +--- sound/hda/ext/hdac_ext_bus.c | 25 ++- sound/soc/codecs/hdac_hdmi.c | 396 +++++++++++++++++++++---------------------- 3 files changed, 204 insertions(+), 253 deletions(-) (limited to 'sound') diff --git a/include/sound/hdaudio_ext.h b/include/sound/hdaudio_ext.h index 9c14e21dda85..c1a5ad0e6e39 100644 --- a/include/sound/hdaudio_ext.h +++ b/include/sound/hdaudio_ext.h @@ -181,48 +181,20 @@ struct hda_dai_map { u32 maxbps; }; -#define HDA_MAX_NIDS 16 - -/** - * struct hdac_ext_device - HDAC Ext device - * - * @hdac: hdac core device - * @nid_list - the dai map which matches the dai-name with the nid - * @map_cur_idx - the idx in use in dai_map - * @ops - the hda codec ops common to all codec drivers - * @pvt_data - private data, for asoc contains asoc codec object - */ -struct hdac_ext_device { - struct hdac_device hdev; - struct hdac_ext_bus *ebus; - - /* soc-dai to nid map */ - struct hda_dai_map nid_list[HDA_MAX_NIDS]; - unsigned int map_cur_idx; - - /* codec ops */ - struct hdac_ext_codec_ops ops; - - struct snd_card *card; - void *scodec; - void *private_data; -}; - struct hdac_ext_dma_params { u32 format; u8 stream_tag; }; -#define to_ehdac_device(dev) (container_of((dev), \ - struct hdac_ext_device, hdev)) + /* * HD-audio codec base driver */ struct hdac_ext_driver { struct hdac_driver hdac; - int (*probe)(struct hdac_ext_device *dev); - int (*remove)(struct hdac_ext_device *dev); - void (*shutdown)(struct hdac_ext_device *dev); + int (*probe)(struct hdac_device *dev); + int (*remove)(struct hdac_device *dev); + void (*shutdown)(struct hdac_device *dev); }; int snd_hda_ext_driver_register(struct hdac_ext_driver *drv); diff --git a/sound/hda/ext/hdac_ext_bus.c b/sound/hda/ext/hdac_ext_bus.c index 0daf31383084..0e4823fdd411 100644 --- a/sound/hda/ext/hdac_ext_bus.c +++ b/sound/hda/ext/hdac_ext_bus.c @@ -137,17 +137,16 @@ static void default_release(struct device *dev) */ int snd_hdac_ext_bus_device_init(struct hdac_ext_bus *ebus, int addr) { - struct hdac_ext_device *edev; struct hdac_device *hdev = NULL; struct hdac_bus *bus = ebus_to_hbus(ebus); char name[15]; int ret; - edev = kzalloc(sizeof(*edev), GFP_KERNEL); - if (!edev) + hdev = kzalloc(sizeof(*hdev), GFP_KERNEL); + if (!hdev) return -ENOMEM; - hdev = &edev->hdev; - edev->ebus = ebus; + + hdev->bus = bus; snprintf(name, sizeof(name), "ehdaudio%dD%d", ebus->idx, addr); @@ -176,10 +175,8 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_device_init); */ void snd_hdac_ext_bus_device_exit(struct hdac_device *hdev) { - struct hdac_ext_device *edev = to_ehdac_device(hdev); - snd_hdac_device_exit(hdev); - kfree(edev); + kfree(hdev); } EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_device_exit); @@ -212,27 +209,25 @@ static inline struct hdac_ext_driver *get_edrv(struct device *dev) return edrv; } -static inline struct hdac_ext_device *get_edev(struct device *dev) +static inline struct hdac_device *get_hdev(struct device *dev) { struct hdac_device *hdev = dev_to_hdac_dev(dev); - struct hdac_ext_device *edev = to_ehdac_device(hdev); - - return edev; + return hdev; } static int hda_ext_drv_probe(struct device *dev) { - return (get_edrv(dev))->probe(get_edev(dev)); + return (get_edrv(dev))->probe(get_hdev(dev)); } static int hdac_ext_drv_remove(struct device *dev) { - return (get_edrv(dev))->remove(get_edev(dev)); + return (get_edrv(dev))->remove(get_hdev(dev)); } static void hdac_ext_drv_shutdown(struct device *dev) { - return (get_edrv(dev))->shutdown(get_edev(dev)); + return (get_edrv(dev))->shutdown(get_hdev(dev)); } /** diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index 84f7a7a36e4b..f1e235817a65 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c @@ -85,7 +85,7 @@ struct hdac_hdmi_pin { bool mst_capable; struct hdac_hdmi_port *ports; int num_ports; - struct hdac_ext_device *edev; + struct hdac_device *hdev; }; struct hdac_hdmi_port { @@ -126,6 +126,9 @@ struct hdac_hdmi_drv_data { }; struct hdac_hdmi_priv { + struct hdac_device *hdev; + struct snd_soc_component *component; + struct snd_card *card; struct hdac_hdmi_dai_port_map dai_map[HDA_MAX_CVTS]; struct list_head pin_list; struct list_head cvt_list; @@ -139,7 +142,7 @@ struct hdac_hdmi_priv { struct snd_soc_dai_driver *dai_drv; }; -#define hdev_to_hdmi_priv(_hdev) ((to_ehdac_device(_hdev))->private_data) +#define hdev_to_hdmi_priv(_hdev) dev_get_drvdata(&(_hdev)->dev) static struct hdac_hdmi_pcm * hdac_hdmi_get_pcm_from_cvt(struct hdac_hdmi_priv *hdmi, @@ -158,7 +161,7 @@ hdac_hdmi_get_pcm_from_cvt(struct hdac_hdmi_priv *hdmi, static void hdac_hdmi_jack_report(struct hdac_hdmi_pcm *pcm, struct hdac_hdmi_port *port, bool is_connect) { - struct hdac_ext_device *edev = port->pin->edev; + struct hdac_device *hdev = port->pin->hdev; if (is_connect) snd_soc_dapm_enable_pin(port->dapm, port->jack_pin); @@ -172,7 +175,7 @@ static void hdac_hdmi_jack_report(struct hdac_hdmi_pcm *pcm, * ports. */ if (pcm->jack_event == 0) { - dev_dbg(&edev->hdev.dev, + dev_dbg(&hdev->dev, "jack report for pcm=%d\n", pcm->pcm_id); snd_soc_jack_report(pcm->jack, SND_JACK_AVOUT, @@ -198,19 +201,18 @@ static void hdac_hdmi_jack_report(struct hdac_hdmi_pcm *pcm, /* * Get the no devices that can be connected to a port on the Pin widget. */ -static int hdac_hdmi_get_port_len(struct hdac_ext_device *edev, hda_nid_t nid) +static int hdac_hdmi_get_port_len(struct hdac_device *hdev, hda_nid_t nid) { unsigned int caps; unsigned int type, param; - caps = get_wcaps(&edev->hdev, nid); + caps = get_wcaps(hdev, nid); type = get_wcaps_type(caps); if (!(caps & AC_WCAP_DIGITAL) || (type != AC_WID_PIN)) return 0; - param = snd_hdac_read_parm_uncached(&edev->hdev, nid, - AC_PAR_DEVLIST_LEN); + param = snd_hdac_read_parm_uncached(hdev, nid, AC_PAR_DEVLIST_LEN); if (param == -1) return param; @@ -222,10 +224,10 @@ static int hdac_hdmi_get_port_len(struct hdac_ext_device *edev, hda_nid_t nid) * id selected on the pin. Return 0 means the first port entry * is selected or MST is not supported. */ -static int hdac_hdmi_port_select_get(struct hdac_ext_device *edev, +static int hdac_hdmi_port_select_get(struct hdac_device *hdev, struct hdac_hdmi_port *port) { - return snd_hdac_codec_read(&edev->hdev, port->pin->nid, + return snd_hdac_codec_read(hdev, port->pin->nid, 0, AC_VERB_GET_DEVICE_SEL, 0); } @@ -233,7 +235,7 @@ static int hdac_hdmi_port_select_get(struct hdac_ext_device *edev, * Sets the selected port entry for the configuring Pin widget verb. * returns error if port set is not equal to port get otherwise success */ -static int hdac_hdmi_port_select_set(struct hdac_ext_device *edev, +static int hdac_hdmi_port_select_set(struct hdac_device *hdev, struct hdac_hdmi_port *port) { int num_ports; @@ -242,8 +244,7 @@ static int hdac_hdmi_port_select_set(struct hdac_ext_device *edev, return 0; /* AC_PAR_DEVLIST_LEN is 0 based. */ - num_ports = hdac_hdmi_get_port_len(edev, port->pin->nid); - + num_ports = hdac_hdmi_get_port_len(hdev, port->pin->nid); if (num_ports < 0) return -EIO; /* @@ -253,13 +254,13 @@ static int hdac_hdmi_port_select_set(struct hdac_ext_device *edev, if (num_ports + 1 < port->id) return 0; - snd_hdac_codec_write(&edev->hdev, port->pin->nid, 0, + snd_hdac_codec_write(hdev, port->pin->nid, 0, AC_VERB_SET_DEVICE_SEL, port->id); - if (port->id != hdac_hdmi_port_select_get(edev, port)) + if (port->id != hdac_hdmi_port_select_get(hdev, port)) return -EIO; - dev_dbg(&edev->hdev.dev, "Selected the port=%d\n", port->id); + dev_dbg(&hdev->dev, "Selected the port=%d\n", port->id); return 0; } @@ -277,13 +278,6 @@ static struct hdac_hdmi_pcm *get_hdmi_pcm_from_id(struct hdac_hdmi_priv *hdmi, return NULL; } -static inline struct hdac_ext_device *to_hda_ext_device(struct device *dev) -{ - struct hdac_device *hdev = dev_to_hdac_dev(dev); - - return to_ehdac_device(hdev); -} - static unsigned int sad_format(const u8 *sad) { return ((sad[0] >> 0x3) & 0x1f); @@ -324,15 +318,13 @@ format_constraint: } static void -hdac_hdmi_set_dip_index(struct hdac_ext_device *edev, hda_nid_t pin_nid, +hdac_hdmi_set_dip_index(struct hdac_device *hdev, hda_nid_t pin_nid, int packet_index, int byte_index) { int val; val = (packet_index << 5) | (byte_index & 0x1f); - - snd_hdac_codec_write(&edev->hdev, pin_nid, 0, - AC_VERB_SET_HDMI_DIP_INDEX, val); + snd_hdac_codec_write(hdev, pin_nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val); } struct dp_audio_infoframe { @@ -347,14 +339,14 @@ struct dp_audio_infoframe { u8 LFEPBL01_LSV36_DM_INH7; }; -static int hdac_hdmi_setup_audio_infoframe(struct hdac_ext_device *edev, +static int hdac_hdmi_setup_audio_infoframe(struct hdac_device *hdev, struct hdac_hdmi_pcm *pcm, struct hdac_hdmi_port *port) { uint8_t buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AUDIO_INFOFRAME_SIZE]; struct hdmi_audio_infoframe frame; struct hdac_hdmi_pin *pin = port->pin; struct dp_audio_infoframe dp_ai; - struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(&edev->hdev); + struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev); struct hdac_hdmi_cvt *cvt = pcm->cvt; u8 *dip; int ret; @@ -363,11 +355,11 @@ static int hdac_hdmi_setup_audio_infoframe(struct hdac_ext_device *edev, u8 conn_type; int channels, ca; - ca = snd_hdac_channel_allocation(&edev->hdev, port->eld.info.spk_alloc, + ca = snd_hdac_channel_allocation(hdev, port->eld.info.spk_alloc, pcm->channels, pcm->chmap_set, true, pcm->chmap); channels = snd_hdac_get_active_channels(ca); - hdmi->chmap.ops.set_channel_count(&edev->hdev, cvt->nid, channels); + hdmi->chmap.ops.set_channel_count(hdev, cvt->nid, channels); snd_hdac_setup_channel_mapping(&hdmi->chmap, pin->nid, false, ca, pcm->channels, pcm->chmap, pcm->chmap_set); @@ -400,32 +392,31 @@ static int hdac_hdmi_setup_audio_infoframe(struct hdac_ext_device *edev, break; default: - dev_err(&edev->hdev.dev, "Invalid connection type: %d\n", - conn_type); + dev_err(&hdev->dev, "Invalid connection type: %d\n", conn_type); return -EIO; } /* stop infoframe transmission */ - hdac_hdmi_set_dip_index(edev, pin->nid, 0x0, 0x0); - snd_hdac_codec_write(&edev->hdev, pin->nid, 0, + hdac_hdmi_set_dip_index(hdev, pin->nid, 0x0, 0x0); + snd_hdac_codec_write(hdev, pin->nid, 0, AC_VERB_SET_HDMI_DIP_XMIT, AC_DIPXMIT_DISABLE); /* Fill infoframe. Index auto-incremented */ - hdac_hdmi_set_dip_index(edev, pin->nid, 0x0, 0x0); + hdac_hdmi_set_dip_index(hdev, pin->nid, 0x0, 0x0); if (conn_type == DRM_ELD_CONN_TYPE_HDMI) { for (i = 0; i < sizeof(buffer); i++) - snd_hdac_codec_write(&edev->hdev, pin->nid, 0, + snd_hdac_codec_write(hdev, pin->nid, 0, AC_VERB_SET_HDMI_DIP_DATA, buffer[i]); } else { for (i = 0; i < sizeof(dp_ai); i++) - snd_hdac_codec_write(&edev->hdev, pin->nid, 0, + snd_hdac_codec_write(hdev, pin->nid, 0, AC_VERB_SET_HDMI_DIP_DATA, dip[i]); } /* Start infoframe */ - hdac_hdmi_set_dip_index(edev, pin->nid, 0x0, 0x0); - snd_hdac_codec_write(&edev->hdev, pin->nid, 0, + hdac_hdmi_set_dip_index(hdev, pin->nid, 0x0, 0x0); + snd_hdac_codec_write(hdev, pin->nid, 0, AC_VERB_SET_HDMI_DIP_XMIT, AC_DIPXMIT_BEST); return 0; @@ -435,12 +426,12 @@ static int hdac_hdmi_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) { - struct hdac_ext_device *edev = snd_soc_dai_get_drvdata(dai); - struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(&edev->hdev); + struct hdac_hdmi_priv *hdmi = snd_soc_dai_get_drvdata(dai); + struct hdac_device *hdev = hdmi->hdev; struct hdac_hdmi_dai_port_map *dai_map; struct hdac_hdmi_pcm *pcm; - dev_dbg(&edev->hdev.dev, "%s: strm_tag: %d\n", __func__, tx_mask); + dev_dbg(&hdev->dev, "%s: strm_tag: %d\n", __func__, tx_mask); dai_map = &hdmi->dai_map[dai->id]; @@ -455,8 +446,8 @@ static int hdac_hdmi_set_tdm_slot(struct snd_soc_dai *dai, static int hdac_hdmi_set_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hparams, struct snd_soc_dai *dai) { - struct hdac_ext_device *edev = snd_soc_dai_get_drvdata(dai); - struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(&edev->hdev); + struct hdac_hdmi_priv *hdmi = snd_soc_dai_get_drvdata(dai); + struct hdac_device *hdev = hdmi->hdev; struct hdac_hdmi_dai_port_map *dai_map; struct hdac_hdmi_port *port; struct hdac_hdmi_pcm *pcm; @@ -469,7 +460,7 @@ static int hdac_hdmi_set_hw_params(struct snd_pcm_substream *substream, return -ENODEV; if ((!port->eld.monitor_present) || (!port->eld.eld_valid)) { - dev_err(&edev->hdev.dev, + dev_err(&hdev->dev, "device is not configured for this pin:port%d:%d\n", port->pin->nid, port->id); return -ENODEV; @@ -489,28 +480,28 @@ static int hdac_hdmi_set_hw_params(struct snd_pcm_substream *substream, return 0; } -static int hdac_hdmi_query_port_connlist(struct hdac_ext_device *edev, +static int hdac_hdmi_query_port_connlist(struct hdac_device *hdev, struct hdac_hdmi_pin *pin, struct hdac_hdmi_port *port) { - if (!(get_wcaps(&edev->hdev, pin->nid) & AC_WCAP_CONN_LIST)) { - dev_warn(&edev->hdev.dev, + if (!(get_wcaps(hdev, pin->nid) & AC_WCAP_CONN_LIST)) { + dev_warn(&hdev->dev, "HDMI: pin %d wcaps %#x does not support connection list\n", - pin->nid, get_wcaps(&edev->hdev, pin->nid)); + pin->nid, get_wcaps(hdev, pin->nid)); return -EINVAL; } - if (hdac_hdmi_port_select_set(edev, port) < 0) + if (hdac_hdmi_port_select_set(hdev, port) < 0) return -EIO; - port->num_mux_nids = snd_hdac_get_connections(&edev->hdev, pin->nid, + port->num_mux_nids = snd_hdac_get_connections(hdev, pin->nid, port->mux_nids, HDA_MAX_CONNECTIONS); if (port->num_mux_nids == 0) - dev_warn(&edev->hdev.dev, + dev_warn(&hdev->dev, "No connections found for pin:port %d:%d\n", pin->nid, port->id); - dev_dbg(&edev->hdev.dev, "num_mux_nids %d for pin:port %d:%d\n", + dev_dbg(&hdev->dev, "num_mux_nids %d for pin:port %d:%d\n", port->num_mux_nids, pin->nid, port->id); return port->num_mux_nids; @@ -526,7 +517,7 @@ static int hdac_hdmi_query_port_connlist(struct hdac_ext_device *edev, * connected. */ static struct hdac_hdmi_port *hdac_hdmi_get_port_from_cvt( - struct hdac_ext_device *edev, + struct hdac_device *hdev, struct hdac_hdmi_priv *hdmi, struct hdac_hdmi_cvt *cvt) { @@ -541,7 +532,7 @@ static struct hdac_hdmi_port *hdac_hdmi_get_port_from_cvt( list_for_each_entry(port, &pcm->port_list, head) { mutex_lock(&pcm->lock); - ret = hdac_hdmi_query_port_connlist(edev, + ret = hdac_hdmi_query_port_connlist(hdev, port->pin, port); mutex_unlock(&pcm->lock); if (ret < 0) @@ -568,8 +559,8 @@ static struct hdac_hdmi_port *hdac_hdmi_get_port_from_cvt( static int hdac_hdmi_pcm_open(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct hdac_ext_device *edev = snd_soc_dai_get_drvdata(dai); - struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(&edev->hdev); + struct hdac_hdmi_priv *hdmi = snd_soc_dai_get_drvdata(dai); + struct hdac_device *hdev = hdmi->hdev; struct hdac_hdmi_dai_port_map *dai_map; struct hdac_hdmi_cvt *cvt; struct hdac_hdmi_port *port; @@ -578,7 +569,7 @@ static int hdac_hdmi_pcm_open(struct snd_pcm_substream *substream, dai_map = &hdmi->dai_map[dai->id]; cvt = dai_map->cvt; - port = hdac_hdmi_get_port_from_cvt(edev, hdmi, cvt); + port = hdac_hdmi_get_port_from_cvt(hdev, hdmi, cvt); /* * To make PA and other userland happy. @@ -589,7 +580,7 @@ static int hdac_hdmi_pcm_open(struct snd_pcm_substream *substream, if ((!port->eld.monitor_present) || (!port->eld.eld_valid)) { - dev_warn(&edev->hdev.dev, + dev_warn(&hdev->dev, "Failed: present?:%d ELD valid?:%d pin:port: %d:%d\n", port->eld.monitor_present, port->eld.eld_valid, port->pin->nid, port->id); @@ -611,8 +602,7 @@ static int hdac_hdmi_pcm_open(struct snd_pcm_substream *substream, static void hdac_hdmi_pcm_close(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct hdac_ext_device *edev = snd_soc_dai_get_drvdata(dai); - struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(&edev->hdev); + struct hdac_hdmi_priv *hdmi = snd_soc_dai_get_drvdata(dai); struct hdac_hdmi_dai_port_map *dai_map; struct hdac_hdmi_pcm *pcm; @@ -695,10 +685,10 @@ static void hdac_hdmi_fill_route(struct snd_soc_dapm_route *route, route->connected = handler; } -static struct hdac_hdmi_pcm *hdac_hdmi_get_pcm(struct hdac_ext_device *edev, +static struct hdac_hdmi_pcm *hdac_hdmi_get_pcm(struct hdac_device *hdev, struct hdac_hdmi_port *port) { - struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(&edev->hdev); + struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev); struct hdac_hdmi_pcm *pcm = NULL; struct hdac_hdmi_port *p; @@ -715,33 +705,32 @@ static struct hdac_hdmi_pcm *hdac_hdmi_get_pcm(struct hdac_ext_device *edev, return NULL; } -static void hdac_hdmi_set_power_state(struct hdac_ext_device *edev, +static void hdac_hdmi_set_power_state(struct hdac_device *hdev, hda_nid_t nid, unsigned int pwr_state) { int count; unsigned int state; - if (get_wcaps(&edev->hdev, nid) & AC_WCAP_POWER) { - if (!snd_hdac_check_power_state(&edev->hdev, nid, pwr_state)) { + if (get_wcaps(hdev, nid) & AC_WCAP_POWER) { + if (!snd_hdac_check_power_state(hdev, nid, pwr_state)) { for (count = 0; count < 10; count++) { - snd_hdac_codec_read(&edev->hdev, nid, 0, + snd_hdac_codec_read(hdev, nid, 0, AC_VERB_SET_POWER_STATE, pwr_state); - state = snd_hdac_sync_power_state(&edev->hdev, + state = snd_hdac_sync_power_state(hdev, nid, pwr_state); if (!(state & AC_PWRST_ERROR)) break; } } - } } -static void hdac_hdmi_set_amp(struct hdac_ext_device *edev, +static void hdac_hdmi_set_amp(struct hdac_device *hdev, hda_nid_t nid, int val) { - if (get_wcaps(&edev->hdev, nid) & AC_WCAP_OUT_AMP) - snd_hdac_codec_write(&edev->hdev, nid, 0, + if (get_wcaps(hdev, nid) & AC_WCAP_OUT_AMP) + snd_hdac_codec_write(hdev, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, val); } @@ -750,40 +739,40 @@ static int hdac_hdmi_pin_output_widget_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kc, int event) { struct hdac_hdmi_port *port = w->priv; - struct hdac_ext_device *edev = to_hda_ext_device(w->dapm->dev); + struct hdac_device *hdev = dev_to_hdac_dev(w->dapm->dev); struct hdac_hdmi_pcm *pcm; - dev_dbg(&edev->hdev.dev, "%s: widget: %s event: %x\n", + dev_dbg(&hdev->dev, "%s: widget: %s event: %x\n", __func__, w->name, event); - pcm = hdac_hdmi_get_pcm(edev, port); + pcm = hdac_hdmi_get_pcm(hdev, port); if (!pcm) return -EIO; /* set the device if pin is mst_capable */ - if (hdac_hdmi_port_select_set(edev, port) < 0) + if (hdac_hdmi_port_select_set(hdev, port) < 0) return -EIO; switch (event) { case SND_SOC_DAPM_PRE_PMU: - hdac_hdmi_set_power_state(edev, port->pin->nid, AC_PWRST_D0); + hdac_hdmi_set_power_state(hdev, port->pin->nid, AC_PWRST_D0); /* Enable out path for this pin widget */ - snd_hdac_codec_write(&edev->hdev, port->pin->nid, 0, + snd_hdac_codec_write(hdev, port->pin->nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); - hdac_hdmi_set_amp(edev, port->pin->nid, AMP_OUT_UNMUTE); + hdac_hdmi_set_amp(hdev, port->pin->nid, AMP_OUT_UNMUTE); - return hdac_hdmi_setup_audio_infoframe(edev, pcm, port); + return hdac_hdmi_setup_audio_infoframe(hdev, pcm, port); case SND_SOC_DAPM_POST_PMD: - hdac_hdmi_set_amp(edev, port->pin->nid, AMP_OUT_MUTE); + hdac_hdmi_set_amp(hdev, port->pin->nid, AMP_OUT_MUTE); /* Disable out path for this pin widget */ - snd_hdac_codec_write(&edev->hdev, port->pin->nid, 0, + snd_hdac_codec_write(hdev, port->pin->nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 0); - hdac_hdmi_set_power_state(edev, port->pin->nid, AC_PWRST_D3); + hdac_hdmi_set_power_state(hdev, port->pin->nid, AC_PWRST_D3); break; } @@ -795,11 +784,11 @@ static int hdac_hdmi_cvt_output_widget_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kc, int event) { struct hdac_hdmi_cvt *cvt = w->priv; - struct hdac_ext_device *edev = to_hda_ext_device(w->dapm->dev); - struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(&edev->hdev); + struct hdac_device *hdev = dev_to_hdac_dev(w->dapm->dev); + struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev); struct hdac_hdmi_pcm *pcm; - dev_dbg(&edev->hdev.dev, "%s: widget: %s event: %x\n", + dev_dbg(&hdev->dev, "%s: widget: %s event: %x\n", __func__, w->name, event); pcm = hdac_hdmi_get_pcm_from_cvt(hdmi, cvt); @@ -808,29 +797,29 @@ static int hdac_hdmi_cvt_output_widget_event(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_PRE_PMU: - hdac_hdmi_set_power_state(edev, cvt->nid, AC_PWRST_D0); + hdac_hdmi_set_power_state(hdev, cvt->nid, AC_PWRST_D0); /* Enable transmission */ - snd_hdac_codec_write(&edev->hdev, cvt->nid, 0, + snd_hdac_codec_write(hdev, cvt->nid, 0, AC_VERB_SET_DIGI_CONVERT_1, 1); /* Category Code (CC) to zero */ - snd_hdac_codec_write(&edev->hdev, cvt->nid, 0, + snd_hdac_codec_write(hdev, cvt->nid, 0, AC_VERB_SET_DIGI_CONVERT_2, 0); - snd_hdac_codec_write(&edev->hdev, cvt->nid, 0, + snd_hdac_codec_write(hdev, cvt->nid, 0, AC_VERB_SET_CHANNEL_STREAMID, pcm->stream_tag); - snd_hdac_codec_write(&edev->hdev, cvt->nid, 0, + snd_hdac_codec_write(hdev, cvt->nid, 0, AC_VERB_SET_STREAM_FORMAT, pcm->format); break; case SND_SOC_DAPM_POST_PMD: - snd_hdac_codec_write(&edev->hdev, cvt->nid, 0, + snd_hdac_codec_write(hdev, cvt->nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0); - snd_hdac_codec_write(&edev->hdev, cvt->nid, 0, + snd_hdac_codec_write(hdev, cvt->nid, 0, AC_VERB_SET_STREAM_FORMAT, 0); - hdac_hdmi_set_power_state(edev, cvt->nid, AC_PWRST_D3); + hdac_hdmi_set_power_state(hdev, cvt->nid, AC_PWRST_D3); break; } @@ -842,10 +831,10 @@ static int hdac_hdmi_pin_mux_widget_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kc, int event) { struct hdac_hdmi_port *port = w->priv; - struct hdac_ext_device *edev = to_hda_ext_device(w->dapm->dev); + struct hdac_device *hdev = dev_to_hdac_dev(w->dapm->dev); int mux_idx; - dev_dbg(&edev->hdev.dev, "%s: widget: %s event: %x\n", + dev_dbg(&hdev->dev, "%s: widget: %s event: %x\n", __func__, w->name, event); if (!kc) @@ -854,11 +843,11 @@ static int hdac_hdmi_pin_mux_widget_event(struct snd_soc_dapm_widget *w, mux_idx = dapm_kcontrol_get_value(kc); /* set the device if pin is mst_capable */ - if (hdac_hdmi_port_select_set(edev, port) < 0) + if (hdac_hdmi_port_select_set(hdev, port) < 0) return -EIO; if (mux_idx > 0) { - snd_hdac_codec_write(&edev->hdev, port->pin->nid, 0, + snd_hdac_codec_write(hdev, port->pin->nid, 0, AC_VERB_SET_CONNECT_SEL, (mux_idx - 1)); } @@ -877,8 +866,8 @@ static int hdac_hdmi_set_pin_port_mux(struct snd_kcontrol *kcontrol, struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol); struct snd_soc_dapm_context *dapm = w->dapm; struct hdac_hdmi_port *port = w->priv; - struct hdac_ext_device *edev = to_hda_ext_device(dapm->dev); - struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(&edev->hdev); + struct hdac_device *hdev = dev_to_hdac_dev(dapm->dev); + struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev); struct hdac_hdmi_pcm *pcm = NULL; const char *cvt_name = e->texts[ucontrol->value.enumerated.item[0]]; @@ -931,12 +920,12 @@ static int hdac_hdmi_set_pin_port_mux(struct snd_kcontrol *kcontrol, * care of selecting the right one and leaving all other inputs selected to * "NONE" */ -static int hdac_hdmi_create_pin_port_muxs(struct hdac_ext_device *edev, +static int hdac_hdmi_create_pin_port_muxs(struct hdac_device *hdev, struct hdac_hdmi_port *port, struct snd_soc_dapm_widget *widget, const char *widget_name) { - struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(&edev->hdev); + struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev); struct hdac_hdmi_pin *pin = port->pin; struct snd_kcontrol_new *kc; struct hdac_hdmi_cvt *cvt; @@ -948,17 +937,17 @@ static int hdac_hdmi_create_pin_port_muxs(struct hdac_ext_device *edev, int i = 0; int num_items = hdmi->num_cvt + 1; - kc = devm_kzalloc(&edev->hdev.dev, sizeof(*kc), GFP_KERNEL); + kc = devm_kzalloc(&hdev->dev, sizeof(*kc), GFP_KERNEL); if (!kc) return -ENOMEM; - se = devm_kzalloc(&edev->hdev.dev, sizeof(*se), GFP_KERNEL); + se = devm_kzalloc(&hdev->dev, sizeof(*se), GFP_KERNEL); if (!se) return -ENOMEM; snprintf(kc_name, NAME_SIZE, "Pin %d port %d Input", pin->nid, port->id); - kc->name = devm_kstrdup(&edev->hdev.dev, kc_name, GFP_KERNEL); + kc->name = devm_kstrdup(&hdev->dev, kc_name, GFP_KERNEL); if (!kc->name) return -ENOMEM; @@ -976,35 +965,35 @@ static int hdac_hdmi_create_pin_port_muxs(struct hdac_ext_device *edev, se->mask = roundup_pow_of_two(se->items) - 1; sprintf(mux_items, "NONE"); - items[i] = devm_kstrdup(&edev->hdev.dev, mux_items, GFP_KERNEL); + items[i] = devm_kstrdup(&hdev->dev, mux_items, GFP_KERNEL); if (!items[i]) return -ENOMEM; list_for_each_entry(cvt, &hdmi->cvt_list, head) { i++; sprintf(mux_items, "cvt %d", cvt->nid); - items[i] = devm_kstrdup(&edev->hdev.dev, mux_items, GFP_KERNEL); + items[i] = devm_kstrdup(&hdev->dev, mux_items, GFP_KERNEL); if (!items[i]) return -ENOMEM; } - se->texts = devm_kmemdup(&edev->hdev.dev, items, + se->texts = devm_kmemdup(&hdev->dev, items, (num_items * sizeof(char *)), GFP_KERNEL); if (!se->texts) return -ENOMEM; - return hdac_hdmi_fill_widget_info(&edev->hdev.dev, widget, + return hdac_hdmi_fill_widget_info(&hdev->dev, widget, snd_soc_dapm_mux, port, widget_name, NULL, kc, 1, hdac_hdmi_pin_mux_widget_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_REG); } /* Add cvt <- input <- mux route map */ -static void hdac_hdmi_add_pinmux_cvt_route(struct hdac_ext_device *edev, +static void hdac_hdmi_add_pinmux_cvt_route(struct hdac_device *hdev, struct snd_soc_dapm_widget *widgets, struct snd_soc_dapm_route *route, int rindex) { - struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(&edev->hdev); + struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev); const struct snd_kcontrol_new *kc; struct soc_enum *se; int mux_index = hdmi->num_cvt + hdmi->num_ports; @@ -1046,8 +1035,8 @@ static int create_fill_widget_route_map(struct snd_soc_dapm_context *dapm) { struct snd_soc_dapm_widget *widgets; struct snd_soc_dapm_route *route; - struct hdac_ext_device *edev = to_hda_ext_device(dapm->dev); - struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(&edev->hdev); + struct hdac_device *hdev = dev_to_hdac_dev(dapm->dev); + struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev); struct snd_soc_dai_driver *dai_drv = hdmi->dai_drv; char widget_name[NAME_SIZE]; struct hdac_hdmi_cvt *cvt; @@ -1099,7 +1088,7 @@ static int create_fill_widget_route_map(struct snd_soc_dapm_context *dapm) for (j = 0; j < pin->num_ports; j++) { sprintf(widget_name, "Pin%d-Port%d Mux", pin->nid, pin->ports[j].id); - ret = hdac_hdmi_create_pin_port_muxs(edev, + ret = hdac_hdmi_create_pin_port_muxs(hdev, &pin->ports[j], &widgets[i], widget_name); if (ret < 0) @@ -1134,7 +1123,7 @@ static int create_fill_widget_route_map(struct snd_soc_dapm_context *dapm) } } - hdac_hdmi_add_pinmux_cvt_route(edev, widgets, route, i); + hdac_hdmi_add_pinmux_cvt_route(hdev, widgets, route, i); snd_soc_dapm_new_controls(dapm, widgets, ((2 * hdmi->num_ports) + hdmi->num_cvt)); @@ -1146,9 +1135,9 @@ static int create_fill_widget_route_map(struct snd_soc_dapm_context *dapm) } -static int hdac_hdmi_init_dai_map(struct hdac_ext_device *edev) +static int hdac_hdmi_init_dai_map(struct hdac_device *hdev) { - struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(&edev->hdev); + struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev); struct hdac_hdmi_dai_port_map *dai_map; struct hdac_hdmi_cvt *cvt; int dai_id = 0; @@ -1164,7 +1153,7 @@ static int hdac_hdmi_init_dai_map(struct hdac_ext_device *edev) dai_id++; if (dai_id == HDA_MAX_CVTS) { - dev_warn(&edev->hdev.dev, + dev_warn(&hdev->dev, "Max dais supported: %d\n", dai_id); break; } @@ -1173,9 +1162,9 @@ static int hdac_hdmi_init_dai_map(struct hdac_ext_device *edev) return 0; } -static int hdac_hdmi_add_cvt(struct hdac_ext_device *edev, hda_nid_t nid) +static int hdac_hdmi_add_cvt(struct hdac_device *hdev, hda_nid_t nid) { - struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(&edev->hdev); + struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev); struct hdac_hdmi_cvt *cvt; char name[NAME_SIZE]; @@ -1190,10 +1179,10 @@ static int hdac_hdmi_add_cvt(struct hdac_ext_device *edev, hda_nid_t nid) list_add_tail(&cvt->head, &hdmi->cvt_list); hdmi->num_cvt++; - return hdac_hdmi_query_cvt_params(&edev->hdev, cvt); + return hdac_hdmi_query_cvt_params(hdev, cvt); } -static int hdac_hdmi_parse_eld(struct hdac_ext_device *edev, +static int hdac_hdmi_parse_eld(struct hdac_device *hdev, struct hdac_hdmi_port *port) { unsigned int ver, mnl; @@ -1202,7 +1191,7 @@ static int hdac_hdmi_parse_eld(struct hdac_ext_device *edev, >> DRM_ELD_VER_SHIFT; if (ver != ELD_VER_CEA_861D && ver != ELD_VER_PARTIAL) { - dev_err(&edev->hdev.dev, "HDMI: Unknown ELD version %d\n", ver); + dev_err(&hdev->dev, "HDMI: Unknown ELD version %d\n", ver); return -EINVAL; } @@ -1210,7 +1199,7 @@ static int hdac_hdmi_parse_eld(struct hdac_ext_device *edev, DRM_ELD_MNL_MASK) >> DRM_ELD_MNL_SHIFT; if (mnl > ELD_MAX_MNL) { - dev_err(&edev->hdev.dev, "HDMI: MNL Invalid %d\n", mnl); + dev_err(&hdev->dev, "HDMI: MNL Invalid %d\n", mnl); return -EINVAL; } @@ -1222,8 +1211,8 @@ static int hdac_hdmi_parse_eld(struct hdac_ext_device *edev, static void hdac_hdmi_present_sense(struct hdac_hdmi_pin *pin, struct hdac_hdmi_port *port) { - struct hdac_ext_device *edev = pin->edev; - struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(&edev->hdev); + struct hdac_device *hdev = pin->hdev; + struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev); struct hdac_hdmi_pcm *pcm; int size = 0; int port_id = -1; @@ -1241,14 +1230,14 @@ static void hdac_hdmi_present_sense(struct hdac_hdmi_pin *pin, if (pin->mst_capable) port_id = port->id; - size = snd_hdac_acomp_get_eld(&edev->hdev, pin->nid, port_id, + size = snd_hdac_acomp_get_eld(hdev, pin->nid, port_id, &port->eld.monitor_present, port->eld.eld_buffer, ELD_MAX_SIZE); if (size > 0) { size = min(size, ELD_MAX_SIZE); - if (hdac_hdmi_parse_eld(edev, port) < 0) + if (hdac_hdmi_parse_eld(hdev, port) < 0) size = -EINVAL; } @@ -1260,11 +1249,11 @@ static void hdac_hdmi_present_sense(struct hdac_hdmi_pin *pin, port->eld.eld_size = 0; } - pcm = hdac_hdmi_get_pcm(edev, port); + pcm = hdac_hdmi_get_pcm(hdev, port); if (!port->eld.monitor_present || !port->eld.eld_valid) { - dev_err(&edev->hdev.dev, "%s: disconnect for pin:port %d:%d\n", + dev_err(&hdev->dev, "%s: disconnect for pin:port %d:%d\n", __func__, pin->nid, port->id); /* @@ -1316,9 +1305,9 @@ static int hdac_hdmi_add_ports(struct hdac_hdmi_priv *hdmi, return 0; } -static int hdac_hdmi_add_pin(struct hdac_ext_device *edev, hda_nid_t nid) +static int hdac_hdmi_add_pin(struct hdac_device *hdev, hda_nid_t nid) { - struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(&edev->hdev); + struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev); struct hdac_hdmi_pin *pin; int ret; @@ -1328,7 +1317,7 @@ static int hdac_hdmi_add_pin(struct hdac_ext_device *edev, hda_nid_t nid) pin->nid = nid; pin->mst_capable = false; - pin->edev = edev; + pin->hdev = hdev; ret = hdac_hdmi_add_ports(hdmi, pin); if (ret < 0) return ret; @@ -1459,15 +1448,14 @@ static int hdac_hdmi_create_dais(struct hdac_device *hdev, * Parse all nodes and store the cvt/pin nids in array * Add one time initialization for pin and cvt widgets */ -static int hdac_hdmi_parse_and_map_nid(struct hdac_ext_device *edev, +static int hdac_hdmi_parse_and_map_nid(struct hdac_device *hdev, struct snd_soc_dai_driver **dais, int *num_dais) { hda_nid_t nid; int i, num_nodes; struct hdac_hdmi_cvt *temp_cvt, *cvt_next; struct hdac_hdmi_pin *temp_pin, *pin_next; - struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(&edev->hdev); - struct hdac_device *hdev = &edev->hdev; + struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev); int ret; hdac_hdmi_skl_enable_all_pins(hdev); @@ -1492,13 +1480,13 @@ static int hdac_hdmi_parse_and_map_nid(struct hdac_ext_device *edev, switch (type) { case AC_WID_AUD_OUT: - ret = hdac_hdmi_add_cvt(edev, nid); + ret = hdac_hdmi_add_cvt(hdev, nid); if (ret < 0) goto free_widgets; break; case AC_WID_PIN: - ret = hdac_hdmi_add_pin(edev, nid); + ret = hdac_hdmi_add_pin(hdev, nid); if (ret < 0) goto free_widgets; break; @@ -1518,7 +1506,7 @@ static int hdac_hdmi_parse_and_map_nid(struct hdac_ext_device *edev, } *num_dais = hdmi->num_cvt; - ret = hdac_hdmi_init_dai_map(edev); + ret = hdac_hdmi_init_dai_map(hdev); if (ret < 0) goto free_widgets; @@ -1544,17 +1532,17 @@ free_widgets: static void hdac_hdmi_eld_notify_cb(void *aptr, int port, int pipe) { - struct hdac_ext_device *edev = aptr; - struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(&edev->hdev); + struct hdac_device *hdev = aptr; + struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev); struct hdac_hdmi_pin *pin = NULL; struct hdac_hdmi_port *hport = NULL; - struct snd_soc_component *component = edev->scodec; + struct snd_soc_component *component = hdmi->component; int i; /* Don't know how this mapping is derived */ hda_nid_t pin_nid = port + 0x04; - dev_dbg(&edev->hdev.dev, "%s: for pin:%d port=%d\n", __func__, + dev_dbg(&hdev->dev, "%s: for pin:%d port=%d\n", __func__, pin_nid, pipe); /* @@ -1567,7 +1555,7 @@ static void hdac_hdmi_eld_notify_cb(void *aptr, int port, int pipe) SNDRV_CTL_POWER_D0) return; - if (atomic_read(&edev->hdev.in_pm)) + if (atomic_read(&hdev->in_pm)) return; list_for_each_entry(pin, &hdmi->pin_list, head) { @@ -1614,15 +1602,15 @@ static struct snd_pcm *hdac_hdmi_get_pcm_from_id(struct snd_soc_card *card, /* create jack pin kcontrols */ static int create_fill_jack_kcontrols(struct snd_soc_card *card, - struct hdac_ext_device *edev) + struct hdac_device *hdev) { struct hdac_hdmi_pin *pin; struct snd_kcontrol_new *kc; char kc_name[NAME_SIZE], xname[NAME_SIZE]; char *name; int i = 0, j; - struct snd_soc_component *component = edev->scodec; - struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(&edev->hdev); + struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev); + struct snd_soc_component *component = hdmi->component; kc = devm_kcalloc(component->dev, hdmi->num_ports, sizeof(*kc), GFP_KERNEL); @@ -1659,8 +1647,8 @@ static int create_fill_jack_kcontrols(struct snd_soc_card *card, int hdac_hdmi_jack_port_init(struct snd_soc_component *component, struct snd_soc_dapm_context *dapm) { - struct hdac_ext_device *edev = snd_soc_component_get_drvdata(component); - struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(&edev->hdev); + struct hdac_hdmi_priv *hdmi = snd_soc_component_get_drvdata(component); + struct hdac_device *hdev = hdmi->hdev; struct hdac_hdmi_pin *pin; struct snd_soc_dapm_widget *widgets; struct snd_soc_dapm_route *route; @@ -1715,7 +1703,7 @@ int hdac_hdmi_jack_port_init(struct snd_soc_component *component, return ret; /* Add Jack Pin switch Kcontrol */ - ret = create_fill_jack_kcontrols(dapm->card, edev); + ret = create_fill_jack_kcontrols(dapm->card, hdev); if (ret < 0) return ret; @@ -1735,8 +1723,8 @@ int hdac_hdmi_jack_init(struct snd_soc_dai *dai, int device, struct snd_soc_jack *jack) { struct snd_soc_component *component = dai->component; - struct hdac_ext_device *edev = snd_soc_component_get_drvdata(component); - struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(&edev->hdev); + struct hdac_hdmi_priv *hdmi = snd_soc_component_get_drvdata(component); + struct hdac_device *hdev = hdmi->hdev; struct hdac_hdmi_pcm *pcm; struct snd_pcm *snd_pcm; int err; @@ -1758,7 +1746,7 @@ int hdac_hdmi_jack_init(struct snd_soc_dai *dai, int device, if (snd_pcm) { err = snd_hdac_add_chmap_ctls(snd_pcm, device, &hdmi->chmap); if (err < 0) { - dev_err(&edev->hdev.dev, + dev_err(&hdev->dev, "chmap control add failed with err: %d for pcm: %d\n", err, device); kfree(pcm); @@ -1772,7 +1760,7 @@ int hdac_hdmi_jack_init(struct snd_soc_dai *dai, int device, } EXPORT_SYMBOL_GPL(hdac_hdmi_jack_init); -static void hdac_hdmi_present_sense_all_pins(struct hdac_ext_device *edev, +static void hdac_hdmi_present_sense_all_pins(struct hdac_device *hdev, struct hdac_hdmi_priv *hdmi, bool detect_pin_caps) { int i; @@ -1781,7 +1769,7 @@ static void hdac_hdmi_present_sense_all_pins(struct hdac_ext_device *edev, list_for_each_entry(pin, &hdmi->pin_list, head) { if (detect_pin_caps) { - if (hdac_hdmi_get_port_len(edev, pin->nid) == 0) + if (hdac_hdmi_get_port_len(hdev, pin->nid) == 0) pin->mst_capable = false; else pin->mst_capable = true; @@ -1798,68 +1786,68 @@ static void hdac_hdmi_present_sense_all_pins(struct hdac_ext_device *edev, static int hdmi_codec_probe(struct snd_soc_component *component) { - struct hdac_ext_device *edev = snd_soc_component_get_drvdata(component); - struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(&edev->hdev); + struct hdac_hdmi_priv *hdmi = snd_soc_component_get_drvdata(component); + struct hdac_device *hdev = hdmi->hdev; struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); struct hdac_ext_link *hlink = NULL; int ret; - edev->scodec = component; + hdmi->component = component; /* * hold the ref while we probe, also no need to drop the ref on * exit, we call pm_runtime_suspend() so that will do for us */ - hlink = snd_hdac_ext_bus_get_link(edev->ebus, dev_name(&edev->hdev.dev)); + hlink = snd_hdac_ext_bus_get_link(hbus_to_ebus(hdev->bus), + dev_name(&hdev->dev)); if (!hlink) { - dev_err(&edev->hdev.dev, "hdac link not found\n"); + dev_err(&hdev->dev, "hdac link not found\n"); return -EIO; } - snd_hdac_ext_bus_link_get(edev->ebus, hlink); + snd_hdac_ext_bus_link_get(hbus_to_ebus(hdev->bus), hlink); ret = create_fill_widget_route_map(dapm); if (ret < 0) return ret; - aops.audio_ptr = edev; + aops.audio_ptr = hdev; ret = snd_hdac_i915_register_notifier(&aops); if (ret < 0) { - dev_err(&edev->hdev.dev, "notifier register failed: err: %d\n", - ret); + dev_err(&hdev->dev, "notifier register failed: err: %d\n", ret); return ret; } - hdac_hdmi_present_sense_all_pins(edev, hdmi, true); + hdac_hdmi_present_sense_all_pins(hdev, hdmi, true); /* Imp: Store the card pointer in hda_codec */ - edev->card = dapm->card->snd_card; + hdmi->card = dapm->card->snd_card; /* * hdac_device core already sets the state to active and calls * get_noresume. So enable runtime and set the device to suspend. */ - pm_runtime_enable(&edev->hdev.dev); - pm_runtime_put(&edev->hdev.dev); - pm_runtime_suspend(&edev->hdev.dev); + pm_runtime_enable(&hdev->dev); + pm_runtime_put(&hdev->dev); + pm_runtime_suspend(&hdev->dev); return 0; } static void hdmi_codec_remove(struct snd_soc_component *component) { - struct hdac_ext_device *edev = snd_soc_component_get_drvdata(component); + struct hdac_hdmi_priv *hdmi = snd_soc_component_get_drvdata(component); + struct hdac_device *hdev = hdmi->hdev; - pm_runtime_disable(&edev->hdev.dev); + pm_runtime_disable(&hdev->dev); } #ifdef CONFIG_PM static int hdmi_codec_prepare(struct device *dev) { - struct hdac_ext_device *edev = to_hda_ext_device(dev); - struct hdac_device *hdev = &edev->hdev; + struct hdac_device *hdev = dev_to_hdac_dev(dev); - pm_runtime_get_sync(&edev->hdev.dev); + pm_runtime_get_sync(&hdev->dev); /* * Power down afg. @@ -1876,16 +1864,15 @@ static int hdmi_codec_prepare(struct device *dev) static void hdmi_codec_complete(struct device *dev) { - struct hdac_ext_device *edev = to_hda_ext_device(dev); - struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(&edev->hdev); - struct hdac_device *hdev = &edev->hdev; + struct hdac_device *hdev = dev_to_hdac_dev(dev); + struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev); /* Power up afg */ snd_hdac_codec_read(hdev, hdev->afg, 0, AC_VERB_SET_POWER_STATE, AC_PWRST_D0); - hdac_hdmi_skl_enable_all_pins(&edev->hdev); - hdac_hdmi_skl_enable_dp12(&edev->hdev); + hdac_hdmi_skl_enable_all_pins(hdev); + hdac_hdmi_skl_enable_dp12(hdev); /* * As the ELD notify callback request is not entertained while the @@ -1893,9 +1880,9 @@ static void hdmi_codec_complete(struct device *dev) * all pins here. pin capablity change is not support, so use the * already set pin caps. */ - hdac_hdmi_present_sense_all_pins(edev, hdmi, false); + hdac_hdmi_present_sense_all_pins(hdev, hdmi, false); - pm_runtime_put_sync(&edev->hdev.dev); + pm_runtime_put_sync(&hdev->dev); } #else #define hdmi_codec_prepare NULL @@ -1922,7 +1909,6 @@ static void hdac_hdmi_get_chmap(struct hdac_device *hdev, int pcm_idx, static void hdac_hdmi_set_chmap(struct hdac_device *hdev, int pcm_idx, unsigned char *chmap, int prepared) { - struct hdac_ext_device *edev = to_ehdac_device(hdev); struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev); struct hdac_hdmi_pcm *pcm = get_hdmi_pcm_from_id(hdmi, pcm_idx); struct hdac_hdmi_port *port; @@ -1938,7 +1924,7 @@ static void hdac_hdmi_set_chmap(struct hdac_device *hdev, int pcm_idx, memcpy(pcm->chmap, chmap, ARRAY_SIZE(pcm->chmap)); list_for_each_entry(port, &pcm->port_list, head) if (prepared) - hdac_hdmi_setup_audio_infoframe(edev, pcm, port); + hdac_hdmi_setup_audio_infoframe(hdev, pcm, port); mutex_unlock(&pcm->lock); } @@ -1987,10 +1973,9 @@ static struct hdac_hdmi_drv_data intel_drv_data = { .vendor_nid = INTEL_VENDOR_NID, }; -static int hdac_hdmi_dev_probe(struct hdac_ext_device *edev) +static int hdac_hdmi_dev_probe(struct hdac_device *hdev) { - struct hdac_device *hdev = &edev->hdev; - struct hdac_hdmi_priv *hdmi_priv; + struct hdac_hdmi_priv *hdmi_priv = NULL; struct snd_soc_dai_driver *hdmi_dais = NULL; struct hdac_ext_link *hlink = NULL; int num_dais = 0; @@ -1999,24 +1984,25 @@ static int hdac_hdmi_dev_probe(struct hdac_ext_device *edev) const struct hda_device_id *hdac_id = hdac_get_device_id(hdev, hdrv); /* hold the ref while we probe */ - hlink = snd_hdac_ext_bus_get_link(edev->ebus, dev_name(&edev->hdev.dev)); + hlink = snd_hdac_ext_bus_get_link(hbus_to_ebus(hdev->bus), + dev_name(&hdev->dev)); if (!hlink) { - dev_err(&edev->hdev.dev, "hdac link not found\n"); + dev_err(&hdev->dev, "hdac link not found\n"); return -EIO; } - snd_hdac_ext_bus_link_get(edev->ebus, hlink); + snd_hdac_ext_bus_link_get(hbus_to_ebus(hdev->bus), hlink); hdmi_priv = devm_kzalloc(&hdev->dev, sizeof(*hdmi_priv), GFP_KERNEL); if (hdmi_priv == NULL) return -ENOMEM; - edev->private_data = hdmi_priv; snd_hdac_register_chmap_ops(hdev, &hdmi_priv->chmap); hdmi_priv->chmap.ops.get_chmap = hdac_hdmi_get_chmap; hdmi_priv->chmap.ops.set_chmap = hdac_hdmi_set_chmap; hdmi_priv->chmap.ops.is_pcm_attached = is_hdac_hdmi_pcm_attached; hdmi_priv->chmap.ops.get_spk_alloc = hdac_hdmi_get_spk_alloc; + hdmi_priv->hdev = hdev; if (!hdac_id) return -ENODEV; @@ -2027,7 +2013,7 @@ static int hdac_hdmi_dev_probe(struct hdac_ext_device *edev) else hdmi_priv->drv_data = &intel_drv_data; - dev_set_drvdata(&hdev->dev, edev); + dev_set_drvdata(&hdev->dev, hdmi_priv); INIT_LIST_HEAD(&hdmi_priv->pin_list); INIT_LIST_HEAD(&hdmi_priv->cvt_list); @@ -2038,15 +2024,15 @@ static int hdac_hdmi_dev_probe(struct hdac_ext_device *edev) * Turned off in the runtime_suspend during the first explicit * pm_runtime_suspend call. */ - ret = snd_hdac_display_power(edev->hdev.bus, true); + ret = snd_hdac_display_power(hdev->bus, true); if (ret < 0) { - dev_err(&edev->hdev.dev, + dev_err(&hdev->dev, "Cannot turn on display power on i915 err: %d\n", ret); return ret; } - ret = hdac_hdmi_parse_and_map_nid(edev, &hdmi_dais, &num_dais); + ret = hdac_hdmi_parse_and_map_nid(hdev, &hdmi_dais, &num_dais); if (ret < 0) { dev_err(&hdev->dev, "Failed in parse and map nid with err: %d\n", ret); @@ -2058,14 +2044,14 @@ static int hdac_hdmi_dev_probe(struct hdac_ext_device *edev) ret = devm_snd_soc_register_component(&hdev->dev, &hdmi_hda_codec, hdmi_dais, num_dais); - snd_hdac_ext_bus_link_put(edev->ebus, hlink); + snd_hdac_ext_bus_link_put(hbus_to_ebus(hdev->bus), hlink); return ret; } -static int hdac_hdmi_dev_remove(struct hdac_ext_device *edev) +static int hdac_hdmi_dev_remove(struct hdac_device *hdev) { - struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(&edev->hdev); + struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev); struct hdac_hdmi_pin *pin, *pin_next; struct hdac_hdmi_cvt *cvt, *cvt_next; struct hdac_hdmi_pcm *pcm, *pcm_next; @@ -2105,8 +2091,7 @@ static int hdac_hdmi_dev_remove(struct hdac_ext_device *edev) #ifdef CONFIG_PM static int hdac_hdmi_runtime_suspend(struct device *dev) { - struct hdac_ext_device *edev = to_hda_ext_device(dev); - struct hdac_device *hdev = &edev->hdev; + struct hdac_device *hdev = dev_to_hdac_dev(dev); struct hdac_bus *bus = hdev->bus; struct hdac_ext_bus *ebus = hbus_to_ebus(bus); struct hdac_ext_link *hlink = NULL; @@ -2129,7 +2114,7 @@ static int hdac_hdmi_runtime_suspend(struct device *dev) AC_PWRST_D3); err = snd_hdac_display_power(bus, false); if (err < 0) { - dev_err(bus->dev, "Cannot turn on display power on i915\n"); + dev_err(dev, "Cannot turn on display power on i915\n"); return err; } @@ -2146,8 +2131,7 @@ static int hdac_hdmi_runtime_suspend(struct device *dev) static int hdac_hdmi_runtime_resume(struct device *dev) { - struct hdac_ext_device *edev = to_hda_ext_device(dev); - struct hdac_device *hdev = &edev->hdev; + struct hdac_device *hdev = dev_to_hdac_dev(dev); struct hdac_bus *bus = hdev->bus; struct hdac_ext_bus *ebus = hbus_to_ebus(bus); struct hdac_ext_link *hlink = NULL; @@ -2169,12 +2153,12 @@ static int hdac_hdmi_runtime_resume(struct device *dev) err = snd_hdac_display_power(bus, true); if (err < 0) { - dev_err(bus->dev, "Cannot turn on display power on i915\n"); + dev_err(dev, "Cannot turn on display power on i915\n"); return err; } - hdac_hdmi_skl_enable_all_pins(&edev->hdev); - hdac_hdmi_skl_enable_dp12(&edev->hdev); + hdac_hdmi_skl_enable_all_pins(hdev); + hdac_hdmi_skl_enable_dp12(hdev); /* Power up afg */ snd_hdac_codec_read(hdev, hdev->afg, 0, AC_VERB_SET_POWER_STATE, -- cgit v1.2.3 From 76f56fae1cf9040325a58d1375291baf71dfaf03 Mon Sep 17 00:00:00 2001 From: Rakesh Ughreja Date: Fri, 1 Jun 2018 22:53:50 -0500 Subject: ALSA: hdac: Remove usage of struct hdac_ext_bus and use hdac_bus instead This patch removes the hdac_ext_bus structure. The legacy and enhanced HDaudio capabilities can be handled in a backward-compatible way without separate definitions. Follow-up patches in this series handle the driver definition. Signed-off-by: Rakesh Ughreja Signed-off-by: Pierre-Louis Bossart Signed-off-by: Takashi Iwai --- include/sound/hdaudio.h | 15 +++ include/sound/hdaudio_ext.h | 74 +++++-------- sound/hda/ext/hdac_ext_bus.c | 27 +++-- sound/hda/ext/hdac_ext_controller.c | 55 +++++----- sound/hda/ext/hdac_ext_stream.c | 104 ++++++++----------- sound/soc/codecs/hdac_hdmi.c | 22 ++-- sound/soc/intel/skylake/skl-messages.c | 50 ++++----- sound/soc/intel/skylake/skl-nhlt.c | 8 +- sound/soc/intel/skylake/skl-pcm.c | 112 ++++++++++---------- sound/soc/intel/skylake/skl-topology.c | 20 ++-- sound/soc/intel/skylake/skl-topology.h | 6 +- sound/soc/intel/skylake/skl.c | 184 +++++++++++++++------------------ sound/soc/intel/skylake/skl.h | 7 +- 13 files changed, 308 insertions(+), 376 deletions(-) (limited to 'sound') diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h index c052afc27547..9735b51aef08 100644 --- a/include/sound/hdaudio.h +++ b/include/sound/hdaudio.h @@ -250,6 +250,11 @@ struct hdac_rb { * @mlcap: MultiLink capabilities pointer * @gtscap: gts capabilities pointer * @drsmcap: dma resume capabilities pointer + * @num_streams: streams supported + * @idx: HDA link index + * @hlink_list: link list of HDA links + * @lock: lock for link mgmt + * @cmd_dma_state: state of cmd DMAs: CORB and RIRB */ struct hdac_bus { struct device *dev; @@ -317,6 +322,16 @@ struct hdac_bus { /* i915 component interface */ struct i915_audio_component *audio_component; int i915_power_refcount; + + /* parameters required for enhanced capabilities */ + int num_streams; + int idx; + + struct list_head hlink_list; + + struct mutex lock; + bool cmd_dma_state; + }; int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev, diff --git a/include/sound/hdaudio_ext.h b/include/sound/hdaudio_ext.h index c1a5ad0e6e39..e5b0cd1ade19 100644 --- a/include/sound/hdaudio_ext.h +++ b/include/sound/hdaudio_ext.h @@ -4,38 +4,14 @@ #include -/** - * hdac_ext_bus: HDAC extended bus for extended HDA caps - * - * @bus: hdac bus - * @num_streams: streams supported - * @hlink_list: link list of HDA links - * @lock: lock for link mgmt - * @cmd_dma_state: state of cmd DMAs: CORB and RIRB - */ -struct hdac_ext_bus { - struct hdac_bus bus; - int num_streams; - int idx; - - struct list_head hlink_list; - - struct mutex lock; - bool cmd_dma_state; -}; - -int snd_hdac_ext_bus_init(struct hdac_ext_bus *sbus, struct device *dev, +int snd_hdac_ext_bus_init(struct hdac_bus *bus, struct device *dev, const struct hdac_bus_ops *ops, const struct hdac_io_ops *io_ops); -void snd_hdac_ext_bus_exit(struct hdac_ext_bus *sbus); -int snd_hdac_ext_bus_device_init(struct hdac_ext_bus *sbus, int addr); +void snd_hdac_ext_bus_exit(struct hdac_bus *bus); +int snd_hdac_ext_bus_device_init(struct hdac_bus *bus, int addr); void snd_hdac_ext_bus_device_exit(struct hdac_device *hdev); -void snd_hdac_ext_bus_device_remove(struct hdac_ext_bus *ebus); - -#define ebus_to_hbus(ebus) (&(ebus)->bus) -#define hbus_to_ebus(_bus) \ - container_of(_bus, struct hdac_ext_bus, bus) +void snd_hdac_ext_bus_device_remove(struct hdac_bus *bus); #define HDA_CODEC_REV_EXT_ENTRY(_vid, _rev, _name, drv_data) \ { .vendor_id = (_vid), .rev_id = (_rev), .name = (_name), \ @@ -44,14 +20,14 @@ void snd_hdac_ext_bus_device_remove(struct hdac_ext_bus *ebus); #define HDA_CODEC_EXT_ENTRY(_vid, _revid, _name, _drv_data) \ HDA_CODEC_REV_EXT_ENTRY(_vid, _revid, _name, _drv_data) -void snd_hdac_ext_bus_ppcap_enable(struct hdac_ext_bus *chip, bool enable); -void snd_hdac_ext_bus_ppcap_int_enable(struct hdac_ext_bus *chip, bool enable); +void snd_hdac_ext_bus_ppcap_enable(struct hdac_bus *chip, bool enable); +void snd_hdac_ext_bus_ppcap_int_enable(struct hdac_bus *chip, bool enable); -void snd_hdac_ext_stream_spbcap_enable(struct hdac_ext_bus *chip, +void snd_hdac_ext_stream_spbcap_enable(struct hdac_bus *chip, bool enable, int index); -int snd_hdac_ext_bus_get_ml_capabilities(struct hdac_ext_bus *bus); -struct hdac_ext_link *snd_hdac_ext_bus_get_link(struct hdac_ext_bus *bus, +int snd_hdac_ext_bus_get_ml_capabilities(struct hdac_bus *bus); +struct hdac_ext_link *snd_hdac_ext_bus_get_link(struct hdac_bus *bus, const char *codec_name); enum hdac_ext_stream_type { @@ -100,28 +76,28 @@ struct hdac_ext_stream { #define stream_to_hdac_ext_stream(s) \ container_of(s, struct hdac_ext_stream, hstream) -void snd_hdac_ext_stream_init(struct hdac_ext_bus *bus, +void snd_hdac_ext_stream_init(struct hdac_bus *bus, struct hdac_ext_stream *stream, int idx, int direction, int tag); -int snd_hdac_ext_stream_init_all(struct hdac_ext_bus *ebus, int start_idx, +int snd_hdac_ext_stream_init_all(struct hdac_bus *bus, int start_idx, int num_stream, int dir); -void snd_hdac_stream_free_all(struct hdac_ext_bus *ebus); -void snd_hdac_link_free_all(struct hdac_ext_bus *ebus); -struct hdac_ext_stream *snd_hdac_ext_stream_assign(struct hdac_ext_bus *bus, +void snd_hdac_stream_free_all(struct hdac_bus *bus); +void snd_hdac_link_free_all(struct hdac_bus *bus); +struct hdac_ext_stream *snd_hdac_ext_stream_assign(struct hdac_bus *bus, struct snd_pcm_substream *substream, int type); void snd_hdac_ext_stream_release(struct hdac_ext_stream *azx_dev, int type); -void snd_hdac_ext_stream_decouple(struct hdac_ext_bus *bus, +void snd_hdac_ext_stream_decouple(struct hdac_bus *bus, struct hdac_ext_stream *azx_dev, bool decouple); -void snd_hdac_ext_stop_streams(struct hdac_ext_bus *sbus); +void snd_hdac_ext_stop_streams(struct hdac_bus *bus); -int snd_hdac_ext_stream_set_spib(struct hdac_ext_bus *ebus, +int snd_hdac_ext_stream_set_spib(struct hdac_bus *bus, struct hdac_ext_stream *stream, u32 value); -int snd_hdac_ext_stream_get_spbmaxfifo(struct hdac_ext_bus *ebus, +int snd_hdac_ext_stream_get_spbmaxfifo(struct hdac_bus *bus, struct hdac_ext_stream *stream); -void snd_hdac_ext_stream_drsm_enable(struct hdac_ext_bus *ebus, +void snd_hdac_ext_stream_drsm_enable(struct hdac_bus *bus, bool enable, int index); -int snd_hdac_ext_stream_set_dpibr(struct hdac_ext_bus *ebus, +int snd_hdac_ext_stream_set_dpibr(struct hdac_bus *bus, struct hdac_ext_stream *stream, u32 value); int snd_hdac_ext_stream_set_lpib(struct hdac_ext_stream *stream, u32 value); @@ -144,17 +120,15 @@ struct hdac_ext_link { int snd_hdac_ext_bus_link_power_up(struct hdac_ext_link *link); int snd_hdac_ext_bus_link_power_down(struct hdac_ext_link *link); -int snd_hdac_ext_bus_link_power_up_all(struct hdac_ext_bus *ebus); -int snd_hdac_ext_bus_link_power_down_all(struct hdac_ext_bus *ebus); +int snd_hdac_ext_bus_link_power_up_all(struct hdac_bus *bus); +int snd_hdac_ext_bus_link_power_down_all(struct hdac_bus *bus); void snd_hdac_ext_link_set_stream_id(struct hdac_ext_link *link, int stream); void snd_hdac_ext_link_clear_stream_id(struct hdac_ext_link *link, int stream); -int snd_hdac_ext_bus_link_get(struct hdac_ext_bus *ebus, - struct hdac_ext_link *link); -int snd_hdac_ext_bus_link_put(struct hdac_ext_bus *ebus, - struct hdac_ext_link *link); +int snd_hdac_ext_bus_link_get(struct hdac_bus *bus, struct hdac_ext_link *link); +int snd_hdac_ext_bus_link_put(struct hdac_bus *bus, struct hdac_ext_link *link); /* update register macro */ #define snd_hdac_updatel(addr, reg, mask, val) \ diff --git a/sound/hda/ext/hdac_ext_bus.c b/sound/hda/ext/hdac_ext_bus.c index 0e4823fdd411..77547ede9ae8 100644 --- a/sound/hda/ext/hdac_ext_bus.c +++ b/sound/hda/ext/hdac_ext_bus.c @@ -87,7 +87,7 @@ static const struct hdac_io_ops hdac_ext_default_io = { * * Returns 0 if successful, or a negative error code. */ -int snd_hdac_ext_bus_init(struct hdac_ext_bus *ebus, struct device *dev, +int snd_hdac_ext_bus_init(struct hdac_bus *bus, struct device *dev, const struct hdac_bus_ops *ops, const struct hdac_io_ops *io_ops) { @@ -98,15 +98,15 @@ int snd_hdac_ext_bus_init(struct hdac_ext_bus *ebus, struct device *dev, if (io_ops == NULL) io_ops = &hdac_ext_default_io; - ret = snd_hdac_bus_init(&ebus->bus, dev, ops, io_ops); + ret = snd_hdac_bus_init(bus, dev, ops, io_ops); if (ret < 0) return ret; - INIT_LIST_HEAD(&ebus->hlink_list); - ebus->idx = idx++; + INIT_LIST_HEAD(&bus->hlink_list); + bus->idx = idx++; - mutex_init(&ebus->lock); - ebus->cmd_dma_state = true; + mutex_init(&bus->lock); + bus->cmd_dma_state = true; return 0; } @@ -116,10 +116,10 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_init); * snd_hdac_ext_bus_exit - clean up a HD-audio extended bus * @ebus: the pointer to extended bus object */ -void snd_hdac_ext_bus_exit(struct hdac_ext_bus *ebus) +void snd_hdac_ext_bus_exit(struct hdac_bus *bus) { - snd_hdac_bus_exit(&ebus->bus); - WARN_ON(!list_empty(&ebus->hlink_list)); + snd_hdac_bus_exit(bus); + WARN_ON(!list_empty(&bus->hlink_list)); } EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_exit); @@ -135,10 +135,9 @@ static void default_release(struct device *dev) * * Returns zero for success or a negative error code. */ -int snd_hdac_ext_bus_device_init(struct hdac_ext_bus *ebus, int addr) +int snd_hdac_ext_bus_device_init(struct hdac_bus *bus, int addr) { struct hdac_device *hdev = NULL; - struct hdac_bus *bus = ebus_to_hbus(ebus); char name[15]; int ret; @@ -148,7 +147,7 @@ int snd_hdac_ext_bus_device_init(struct hdac_ext_bus *ebus, int addr) hdev->bus = bus; - snprintf(name, sizeof(name), "ehdaudio%dD%d", ebus->idx, addr); + snprintf(name, sizeof(name), "ehdaudio%dD%d", bus->idx, addr); ret = snd_hdac_device_init(hdev, bus, name, addr); if (ret < 0) { @@ -185,14 +184,14 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_device_exit); * * @ebus: HD-audio extended bus */ -void snd_hdac_ext_bus_device_remove(struct hdac_ext_bus *ebus) +void snd_hdac_ext_bus_device_remove(struct hdac_bus *bus) { struct hdac_device *codec, *__codec; /* * we need to remove all the codec devices objects created in the * snd_hdac_ext_bus_device_init */ - list_for_each_entry_safe(codec, __codec, &ebus->bus.codec_list, list) { + list_for_each_entry_safe(codec, __codec, &bus->codec_list, list) { snd_hdac_device_unregister(codec); put_device(&codec->dev); } diff --git a/sound/hda/ext/hdac_ext_controller.c b/sound/hda/ext/hdac_ext_controller.c index 84f3b8168716..72774119dd11 100644 --- a/sound/hda/ext/hdac_ext_controller.c +++ b/sound/hda/ext/hdac_ext_controller.c @@ -39,9 +39,8 @@ * @ebus: HD-audio extended core bus * @enable: flag to turn on/off the capability */ -void snd_hdac_ext_bus_ppcap_enable(struct hdac_ext_bus *ebus, bool enable) +void snd_hdac_ext_bus_ppcap_enable(struct hdac_bus *bus, bool enable) { - struct hdac_bus *bus = &ebus->bus; if (!bus->ppcap) { dev_err(bus->dev, "Address of PP capability is NULL"); @@ -60,9 +59,8 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_ppcap_enable); * @ebus: HD-audio extended core bus * @enable: flag to enable/disable interrupt */ -void snd_hdac_ext_bus_ppcap_int_enable(struct hdac_ext_bus *ebus, bool enable) +void snd_hdac_ext_bus_ppcap_int_enable(struct hdac_bus *bus, bool enable) { - struct hdac_bus *bus = &ebus->bus; if (!bus->ppcap) { dev_err(bus->dev, "Address of PP capability is NULL\n"); @@ -89,12 +87,11 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_ppcap_int_enable); * in hlink_list of extended hdac bus * Note: this will be freed on bus exit by driver */ -int snd_hdac_ext_bus_get_ml_capabilities(struct hdac_ext_bus *ebus) +int snd_hdac_ext_bus_get_ml_capabilities(struct hdac_bus *bus) { int idx; u32 link_count; struct hdac_ext_link *hlink; - struct hdac_bus *bus = &ebus->bus; link_count = readl(bus->mlcap + AZX_REG_ML_MLCD) + 1; @@ -114,7 +111,7 @@ int snd_hdac_ext_bus_get_ml_capabilities(struct hdac_ext_bus *ebus) /* since link in On, update the ref */ hlink->ref_count = 1; - list_add_tail(&hlink->list, &ebus->hlink_list); + list_add_tail(&hlink->list, &bus->hlink_list); } return 0; @@ -127,12 +124,12 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_get_ml_capabilities); * @ebus: HD-audio ext core bus */ -void snd_hdac_link_free_all(struct hdac_ext_bus *ebus) +void snd_hdac_link_free_all(struct hdac_bus *bus) { struct hdac_ext_link *l; - while (!list_empty(&ebus->hlink_list)) { - l = list_first_entry(&ebus->hlink_list, struct hdac_ext_link, list); + while (!list_empty(&bus->hlink_list)) { + l = list_first_entry(&bus->hlink_list, struct hdac_ext_link, list); list_del(&l->list); kfree(l); } @@ -144,7 +141,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_link_free_all); * @ebus: HD-audio extended core bus * @codec_name: codec name */ -struct hdac_ext_link *snd_hdac_ext_bus_get_link(struct hdac_ext_bus *ebus, +struct hdac_ext_link *snd_hdac_ext_bus_get_link(struct hdac_bus *bus, const char *codec_name) { int i; @@ -153,10 +150,10 @@ struct hdac_ext_link *snd_hdac_ext_bus_get_link(struct hdac_ext_bus *ebus, if (sscanf(codec_name, "ehdaudio%dD%d", &bus_idx, &addr) != 2) return NULL; - if (ebus->idx != bus_idx) + if (bus->idx != bus_idx) return NULL; - list_for_each_entry(hlink, &ebus->hlink_list, list) { + list_for_each_entry(hlink, &bus->hlink_list, list) { for (i = 0; i < HDA_MAX_CODECS; i++) { if (hlink->lsdiid & (0x1 << addr)) return hlink; @@ -219,12 +216,12 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_power_down); * snd_hdac_ext_bus_link_power_up_all -power up all hda link * @ebus: HD-audio extended bus */ -int snd_hdac_ext_bus_link_power_up_all(struct hdac_ext_bus *ebus) +int snd_hdac_ext_bus_link_power_up_all(struct hdac_bus *bus) { struct hdac_ext_link *hlink = NULL; int ret; - list_for_each_entry(hlink, &ebus->hlink_list, list) { + list_for_each_entry(hlink, &bus->hlink_list, list) { snd_hdac_updatel(hlink->ml_addr, AZX_REG_ML_LCTL, 0, AZX_MLCTL_SPA); ret = check_hdac_link_power_active(hlink, true); @@ -240,12 +237,12 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_power_up_all); * snd_hdac_ext_bus_link_power_down_all -power down all hda link * @ebus: HD-audio extended bus */ -int snd_hdac_ext_bus_link_power_down_all(struct hdac_ext_bus *ebus) +int snd_hdac_ext_bus_link_power_down_all(struct hdac_bus *bus) { struct hdac_ext_link *hlink = NULL; int ret; - list_for_each_entry(hlink, &ebus->hlink_list, list) { + list_for_each_entry(hlink, &bus->hlink_list, list) { snd_hdac_updatel(hlink->ml_addr, AZX_REG_ML_LCTL, AZX_MLCTL_SPA, 0); ret = check_hdac_link_power_active(hlink, false); if (ret < 0) @@ -256,39 +253,39 @@ int snd_hdac_ext_bus_link_power_down_all(struct hdac_ext_bus *ebus) } EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_power_down_all); -int snd_hdac_ext_bus_link_get(struct hdac_ext_bus *ebus, +int snd_hdac_ext_bus_link_get(struct hdac_bus *bus, struct hdac_ext_link *link) { int ret = 0; - mutex_lock(&ebus->lock); + mutex_lock(&bus->lock); /* * if we move from 0 to 1, count will be 1 so power up this link * as well, also check the dma status and trigger that */ if (++link->ref_count == 1) { - if (!ebus->cmd_dma_state) { - snd_hdac_bus_init_cmd_io(&ebus->bus); - ebus->cmd_dma_state = true; + if (!bus->cmd_dma_state) { + snd_hdac_bus_init_cmd_io(bus); + bus->cmd_dma_state = true; } ret = snd_hdac_ext_bus_link_power_up(link); } - mutex_unlock(&ebus->lock); + mutex_unlock(&bus->lock); return ret; } EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_get); -int snd_hdac_ext_bus_link_put(struct hdac_ext_bus *ebus, +int snd_hdac_ext_bus_link_put(struct hdac_bus *bus, struct hdac_ext_link *link) { int ret = 0; struct hdac_ext_link *hlink; bool link_up = false; - mutex_lock(&ebus->lock); + mutex_lock(&bus->lock); /* * if we move from 1 to 0, count will be 0 @@ -301,7 +298,7 @@ int snd_hdac_ext_bus_link_put(struct hdac_ext_bus *ebus, * now check if all links are off, if so turn off * cmd dma as well */ - list_for_each_entry(hlink, &ebus->hlink_list, list) { + list_for_each_entry(hlink, &bus->hlink_list, list) { if (hlink->ref_count) { link_up = true; break; @@ -309,12 +306,12 @@ int snd_hdac_ext_bus_link_put(struct hdac_ext_bus *ebus, } if (!link_up) { - snd_hdac_bus_stop_cmd_io(&ebus->bus); - ebus->cmd_dma_state = false; + snd_hdac_bus_stop_cmd_io(bus); + bus->cmd_dma_state = false; } } - mutex_unlock(&ebus->lock); + mutex_unlock(&bus->lock); return ret; } EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_put); diff --git a/sound/hda/ext/hdac_ext_stream.c b/sound/hda/ext/hdac_ext_stream.c index c96d7a7a36af..1bd27576db98 100644 --- a/sound/hda/ext/hdac_ext_stream.c +++ b/sound/hda/ext/hdac_ext_stream.c @@ -25,7 +25,7 @@ /** * snd_hdac_ext_stream_init - initialize each stream (aka device) - * @ebus: HD-audio ext core bus + * @bus: HD-audio core bus * @stream: HD-audio ext core stream object to initialize * @idx: stream index number * @direction: stream direction (SNDRV_PCM_STREAM_PLAYBACK or SNDRV_PCM_STREAM_CAPTURE) @@ -34,18 +34,16 @@ * initialize the stream, if ppcap is enabled then init those and then * invoke hdac stream initialization routine */ -void snd_hdac_ext_stream_init(struct hdac_ext_bus *ebus, +void snd_hdac_ext_stream_init(struct hdac_bus *bus, struct hdac_ext_stream *stream, int idx, int direction, int tag) { - struct hdac_bus *bus = &ebus->bus; - if (bus->ppcap) { stream->pphc_addr = bus->ppcap + AZX_PPHC_BASE + AZX_PPHC_INTERVAL * idx; stream->pplc_addr = bus->ppcap + AZX_PPLC_BASE + - AZX_PPLC_MULTI * ebus->num_streams + + AZX_PPLC_MULTI * bus->num_streams + AZX_PPLC_INTERVAL * idx; } @@ -71,12 +69,12 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_init); /** * snd_hdac_ext_stream_init_all - create and initialize the stream objects * for an extended hda bus - * @ebus: HD-audio ext core bus + * @bus: HD-audio core bus * @start_idx: start index for streams * @num_stream: number of streams to initialize * @dir: direction of streams */ -int snd_hdac_ext_stream_init_all(struct hdac_ext_bus *ebus, int start_idx, +int snd_hdac_ext_stream_init_all(struct hdac_bus *bus, int start_idx, int num_stream, int dir) { int stream_tag = 0; @@ -88,7 +86,7 @@ int snd_hdac_ext_stream_init_all(struct hdac_ext_bus *ebus, int start_idx, if (!stream) return -ENOMEM; tag = ++stream_tag; - snd_hdac_ext_stream_init(ebus, stream, idx, dir, tag); + snd_hdac_ext_stream_init(bus, stream, idx, dir, tag); idx++; } @@ -100,17 +98,16 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_init_all); /** * snd_hdac_stream_free_all - free hdac extended stream objects * - * @ebus: HD-audio ext core bus + * @bus: HD-audio core bus */ -void snd_hdac_stream_free_all(struct hdac_ext_bus *ebus) +void snd_hdac_stream_free_all(struct hdac_bus *bus) { struct hdac_stream *s, *_s; struct hdac_ext_stream *stream; - struct hdac_bus *bus = ebus_to_hbus(ebus); list_for_each_entry_safe(s, _s, &bus->stream_list, list) { stream = stream_to_hdac_ext_stream(s); - snd_hdac_ext_stream_decouple(ebus, stream, false); + snd_hdac_ext_stream_decouple(bus, stream, false); list_del(&s->list); kfree(stream); } @@ -119,15 +116,14 @@ EXPORT_SYMBOL_GPL(snd_hdac_stream_free_all); /** * snd_hdac_ext_stream_decouple - decouple the hdac stream - * @ebus: HD-audio ext core bus + * @bus: HD-audio core bus * @stream: HD-audio ext core stream object to initialize * @decouple: flag to decouple */ -void snd_hdac_ext_stream_decouple(struct hdac_ext_bus *ebus, +void snd_hdac_ext_stream_decouple(struct hdac_bus *bus, struct hdac_ext_stream *stream, bool decouple) { struct hdac_stream *hstream = &stream->hstream; - struct hdac_bus *bus = &ebus->bus; u32 val; int mask = AZX_PPCTL_PROCEN(hstream->index); @@ -251,19 +247,18 @@ void snd_hdac_ext_link_clear_stream_id(struct hdac_ext_link *link, EXPORT_SYMBOL_GPL(snd_hdac_ext_link_clear_stream_id); static struct hdac_ext_stream * -hdac_ext_link_stream_assign(struct hdac_ext_bus *ebus, +hdac_ext_link_stream_assign(struct hdac_bus *bus, struct snd_pcm_substream *substream) { struct hdac_ext_stream *res = NULL; struct hdac_stream *stream = NULL; - struct hdac_bus *hbus = &ebus->bus; - if (!hbus->ppcap) { - dev_err(hbus->dev, "stream type not supported\n"); + if (!bus->ppcap) { + dev_err(bus->dev, "stream type not supported\n"); return NULL; } - list_for_each_entry(stream, &hbus->stream_list, list) { + list_for_each_entry(stream, &bus->stream_list, list) { struct hdac_ext_stream *hstream = container_of(stream, struct hdac_ext_stream, hstream); @@ -277,34 +272,33 @@ hdac_ext_link_stream_assign(struct hdac_ext_bus *ebus, } if (!hstream->link_locked) { - snd_hdac_ext_stream_decouple(ebus, hstream, true); + snd_hdac_ext_stream_decouple(bus, hstream, true); res = hstream; break; } } if (res) { - spin_lock_irq(&hbus->reg_lock); + spin_lock_irq(&bus->reg_lock); res->link_locked = 1; res->link_substream = substream; - spin_unlock_irq(&hbus->reg_lock); + spin_unlock_irq(&bus->reg_lock); } return res; } static struct hdac_ext_stream * -hdac_ext_host_stream_assign(struct hdac_ext_bus *ebus, +hdac_ext_host_stream_assign(struct hdac_bus *bus, struct snd_pcm_substream *substream) { struct hdac_ext_stream *res = NULL; struct hdac_stream *stream = NULL; - struct hdac_bus *hbus = &ebus->bus; - if (!hbus->ppcap) { - dev_err(hbus->dev, "stream type not supported\n"); + if (!bus->ppcap) { + dev_err(bus->dev, "stream type not supported\n"); return NULL; } - list_for_each_entry(stream, &hbus->stream_list, list) { + list_for_each_entry(stream, &bus->stream_list, list) { struct hdac_ext_stream *hstream = container_of(stream, struct hdac_ext_stream, hstream); @@ -313,17 +307,17 @@ hdac_ext_host_stream_assign(struct hdac_ext_bus *ebus, if (!stream->opened) { if (!hstream->decoupled) - snd_hdac_ext_stream_decouple(ebus, hstream, true); + snd_hdac_ext_stream_decouple(bus, hstream, true); res = hstream; break; } } if (res) { - spin_lock_irq(&hbus->reg_lock); + spin_lock_irq(&bus->reg_lock); res->hstream.opened = 1; res->hstream.running = 0; res->hstream.substream = substream; - spin_unlock_irq(&hbus->reg_lock); + spin_unlock_irq(&bus->reg_lock); } return res; @@ -331,7 +325,7 @@ hdac_ext_host_stream_assign(struct hdac_ext_bus *ebus, /** * snd_hdac_ext_stream_assign - assign a stream for the PCM - * @ebus: HD-audio ext core bus + * @bus: HD-audio core bus * @substream: PCM substream to assign * @type: type of stream (coupled, host or link stream) * @@ -346,27 +340,26 @@ hdac_ext_host_stream_assign(struct hdac_ext_bus *ebus, * the same stream object when it's used beforehand. when a stream is * decoupled, it becomes a host stream and link stream. */ -struct hdac_ext_stream *snd_hdac_ext_stream_assign(struct hdac_ext_bus *ebus, +struct hdac_ext_stream *snd_hdac_ext_stream_assign(struct hdac_bus *bus, struct snd_pcm_substream *substream, int type) { struct hdac_ext_stream *hstream = NULL; struct hdac_stream *stream = NULL; - struct hdac_bus *hbus = &ebus->bus; switch (type) { case HDAC_EXT_STREAM_TYPE_COUPLED: - stream = snd_hdac_stream_assign(hbus, substream); + stream = snd_hdac_stream_assign(bus, substream); if (stream) hstream = container_of(stream, struct hdac_ext_stream, hstream); return hstream; case HDAC_EXT_STREAM_TYPE_HOST: - return hdac_ext_host_stream_assign(ebus, substream); + return hdac_ext_host_stream_assign(bus, substream); case HDAC_EXT_STREAM_TYPE_LINK: - return hdac_ext_link_stream_assign(ebus, substream); + return hdac_ext_link_stream_assign(bus, substream); default: return NULL; @@ -384,7 +377,6 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_assign); void snd_hdac_ext_stream_release(struct hdac_ext_stream *stream, int type) { struct hdac_bus *bus = stream->hstream.bus; - struct hdac_ext_bus *ebus = hbus_to_ebus(bus); switch (type) { case HDAC_EXT_STREAM_TYPE_COUPLED: @@ -393,13 +385,13 @@ void snd_hdac_ext_stream_release(struct hdac_ext_stream *stream, int type) case HDAC_EXT_STREAM_TYPE_HOST: if (stream->decoupled && !stream->link_locked) - snd_hdac_ext_stream_decouple(ebus, stream, false); + snd_hdac_ext_stream_decouple(bus, stream, false); snd_hdac_stream_release(&stream->hstream); break; case HDAC_EXT_STREAM_TYPE_LINK: if (stream->decoupled && !stream->hstream.opened) - snd_hdac_ext_stream_decouple(ebus, stream, false); + snd_hdac_ext_stream_decouple(bus, stream, false); spin_lock_irq(&bus->reg_lock); stream->link_locked = 0; stream->link_substream = NULL; @@ -415,16 +407,15 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_release); /** * snd_hdac_ext_stream_spbcap_enable - enable SPIB for a stream - * @ebus: HD-audio ext core bus + * @bus: HD-audio core bus * @enable: flag to enable/disable SPIB * @index: stream index for which SPIB need to be enabled */ -void snd_hdac_ext_stream_spbcap_enable(struct hdac_ext_bus *ebus, +void snd_hdac_ext_stream_spbcap_enable(struct hdac_bus *bus, bool enable, int index) { u32 mask = 0; u32 register_mask = 0; - struct hdac_bus *bus = &ebus->bus; if (!bus->spbcap) { dev_err(bus->dev, "Address of SPB capability is NULL\n"); @@ -446,14 +437,13 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_spbcap_enable); /** * snd_hdac_ext_stream_set_spib - sets the spib value of a stream - * @ebus: HD-audio ext core bus + * @bus: HD-audio core bus * @stream: hdac_ext_stream * @value: spib value to set */ -int snd_hdac_ext_stream_set_spib(struct hdac_ext_bus *ebus, +int snd_hdac_ext_stream_set_spib(struct hdac_bus *bus, struct hdac_ext_stream *stream, u32 value) { - struct hdac_bus *bus = &ebus->bus; if (!bus->spbcap) { dev_err(bus->dev, "Address of SPB capability is NULL\n"); @@ -468,15 +458,14 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_set_spib); /** * snd_hdac_ext_stream_get_spbmaxfifo - gets the spib value of a stream - * @ebus: HD-audio ext core bus + * @bus: HD-audio core bus * @stream: hdac_ext_stream * * Return maxfifo for the stream */ -int snd_hdac_ext_stream_get_spbmaxfifo(struct hdac_ext_bus *ebus, +int snd_hdac_ext_stream_get_spbmaxfifo(struct hdac_bus *bus, struct hdac_ext_stream *stream) { - struct hdac_bus *bus = &ebus->bus; if (!bus->spbcap) { dev_err(bus->dev, "Address of SPB capability is NULL\n"); @@ -490,11 +479,10 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_get_spbmaxfifo); /** * snd_hdac_ext_stop_streams - stop all stream if running - * @ebus: HD-audio ext core bus + * @bus: HD-audio core bus */ -void snd_hdac_ext_stop_streams(struct hdac_ext_bus *ebus) +void snd_hdac_ext_stop_streams(struct hdac_bus *bus) { - struct hdac_bus *bus = ebus_to_hbus(ebus); struct hdac_stream *stream; if (bus->chip_init) { @@ -507,16 +495,15 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_stop_streams); /** * snd_hdac_ext_stream_drsm_enable - enable DMA resume for a stream - * @ebus: HD-audio ext core bus + * @bus: HD-audio core bus * @enable: flag to enable/disable DRSM * @index: stream index for which DRSM need to be enabled */ -void snd_hdac_ext_stream_drsm_enable(struct hdac_ext_bus *ebus, +void snd_hdac_ext_stream_drsm_enable(struct hdac_bus *bus, bool enable, int index) { u32 mask = 0; u32 register_mask = 0; - struct hdac_bus *bus = &ebus->bus; if (!bus->drsmcap) { dev_err(bus->dev, "Address of DRSM capability is NULL\n"); @@ -538,14 +525,13 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_drsm_enable); /** * snd_hdac_ext_stream_set_dpibr - sets the dpibr value of a stream - * @ebus: HD-audio ext core bus + * @bus: HD-audio core bus * @stream: hdac_ext_stream * @value: dpib value to set */ -int snd_hdac_ext_stream_set_dpibr(struct hdac_ext_bus *ebus, +int snd_hdac_ext_stream_set_dpibr(struct hdac_bus *bus, struct hdac_ext_stream *stream, u32 value) { - struct hdac_bus *bus = &ebus->bus; if (!bus->drsmcap) { dev_err(bus->dev, "Address of DRSM capability is NULL\n"); @@ -560,7 +546,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_set_dpibr); /** * snd_hdac_ext_stream_set_lpib - sets the lpib value of a stream - * @ebus: HD-audio ext core bus + * @bus: HD-audio core bus * @stream: hdac_ext_stream * @value: lpib value to set */ diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index f1e235817a65..c3ccc8d9c91d 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c @@ -1799,14 +1799,13 @@ static int hdmi_codec_probe(struct snd_soc_component *component) * hold the ref while we probe, also no need to drop the ref on * exit, we call pm_runtime_suspend() so that will do for us */ - hlink = snd_hdac_ext_bus_get_link(hbus_to_ebus(hdev->bus), - dev_name(&hdev->dev)); + hlink = snd_hdac_ext_bus_get_link(hdev->bus, dev_name(&hdev->dev)); if (!hlink) { dev_err(&hdev->dev, "hdac link not found\n"); return -EIO; } - snd_hdac_ext_bus_link_get(hbus_to_ebus(hdev->bus), hlink); + snd_hdac_ext_bus_link_get(hdev->bus, hlink); ret = create_fill_widget_route_map(dapm); if (ret < 0) @@ -1984,14 +1983,13 @@ static int hdac_hdmi_dev_probe(struct hdac_device *hdev) const struct hda_device_id *hdac_id = hdac_get_device_id(hdev, hdrv); /* hold the ref while we probe */ - hlink = snd_hdac_ext_bus_get_link(hbus_to_ebus(hdev->bus), - dev_name(&hdev->dev)); + hlink = snd_hdac_ext_bus_get_link(hdev->bus, dev_name(&hdev->dev)); if (!hlink) { dev_err(&hdev->dev, "hdac link not found\n"); return -EIO; } - snd_hdac_ext_bus_link_get(hbus_to_ebus(hdev->bus), hlink); + snd_hdac_ext_bus_link_get(hdev->bus, hlink); hdmi_priv = devm_kzalloc(&hdev->dev, sizeof(*hdmi_priv), GFP_KERNEL); if (hdmi_priv == NULL) @@ -2044,7 +2042,7 @@ static int hdac_hdmi_dev_probe(struct hdac_device *hdev) ret = devm_snd_soc_register_component(&hdev->dev, &hdmi_hda_codec, hdmi_dais, num_dais); - snd_hdac_ext_bus_link_put(hbus_to_ebus(hdev->bus), hlink); + snd_hdac_ext_bus_link_put(hdev->bus, hlink); return ret; } @@ -2093,7 +2091,6 @@ static int hdac_hdmi_runtime_suspend(struct device *dev) { struct hdac_device *hdev = dev_to_hdac_dev(dev); struct hdac_bus *bus = hdev->bus; - struct hdac_ext_bus *ebus = hbus_to_ebus(bus); struct hdac_ext_link *hlink = NULL; int err; @@ -2118,13 +2115,13 @@ static int hdac_hdmi_runtime_suspend(struct device *dev) return err; } - hlink = snd_hdac_ext_bus_get_link(ebus, dev_name(dev)); + hlink = snd_hdac_ext_bus_get_link(bus, dev_name(dev)); if (!hlink) { dev_err(dev, "hdac link not found\n"); return -EIO; } - snd_hdac_ext_bus_link_put(ebus, hlink); + snd_hdac_ext_bus_link_put(bus, hlink); return 0; } @@ -2133,7 +2130,6 @@ static int hdac_hdmi_runtime_resume(struct device *dev) { struct hdac_device *hdev = dev_to_hdac_dev(dev); struct hdac_bus *bus = hdev->bus; - struct hdac_ext_bus *ebus = hbus_to_ebus(bus); struct hdac_ext_link *hlink = NULL; int err; @@ -2143,13 +2139,13 @@ static int hdac_hdmi_runtime_resume(struct device *dev) if (!bus) return 0; - hlink = snd_hdac_ext_bus_get_link(ebus, dev_name(dev)); + hlink = snd_hdac_ext_bus_get_link(bus, dev_name(dev)); if (!hlink) { dev_err(dev, "hdac link not found\n"); return -EIO; } - snd_hdac_ext_bus_link_get(ebus, hlink); + snd_hdac_ext_bus_link_get(bus, hlink); err = snd_hdac_display_power(bus, true); if (err < 0) { diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c index d5f9c30eba32..8bfb8b0fa3d5 100644 --- a/sound/soc/intel/skylake/skl-messages.c +++ b/sound/soc/intel/skylake/skl-messages.c @@ -33,8 +33,7 @@ static int skl_alloc_dma_buf(struct device *dev, struct snd_dma_buffer *dmab, size_t size) { - struct hdac_ext_bus *ebus = dev_get_drvdata(dev); - struct hdac_bus *bus = ebus_to_hbus(ebus); + struct hdac_bus *bus = dev_get_drvdata(dev); if (!bus) return -ENODEV; @@ -44,8 +43,7 @@ static int skl_alloc_dma_buf(struct device *dev, static int skl_free_dma_buf(struct device *dev, struct snd_dma_buffer *dmab) { - struct hdac_ext_bus *ebus = dev_get_drvdata(dev); - struct hdac_bus *bus = ebus_to_hbus(ebus); + struct hdac_bus *bus = dev_get_drvdata(dev); if (!bus) return -ENODEV; @@ -89,8 +87,7 @@ void skl_dsp_enable_notification(struct skl_sst *ctx, bool enable) static int skl_dsp_setup_spib(struct device *dev, unsigned int size, int stream_tag, int enable) { - struct hdac_ext_bus *ebus = dev_get_drvdata(dev); - struct hdac_bus *bus = ebus_to_hbus(ebus); + struct hdac_bus *bus = dev_get_drvdata(dev); struct hdac_stream *stream = snd_hdac_get_stream(bus, SNDRV_PCM_STREAM_PLAYBACK, stream_tag); struct hdac_ext_stream *estream; @@ -100,10 +97,10 @@ static int skl_dsp_setup_spib(struct device *dev, unsigned int size, estream = stream_to_hdac_ext_stream(stream); /* enable/disable SPIB for this hdac stream */ - snd_hdac_ext_stream_spbcap_enable(ebus, enable, stream->index); + snd_hdac_ext_stream_spbcap_enable(bus, enable, stream->index); /* set the spib value */ - snd_hdac_ext_stream_set_spib(ebus, estream, size); + snd_hdac_ext_stream_set_spib(bus, estream, size); return 0; } @@ -111,8 +108,7 @@ static int skl_dsp_setup_spib(struct device *dev, unsigned int size, static int skl_dsp_prepare(struct device *dev, unsigned int format, unsigned int size, struct snd_dma_buffer *dmab) { - struct hdac_ext_bus *ebus = dev_get_drvdata(dev); - struct hdac_bus *bus = ebus_to_hbus(ebus); + struct hdac_bus *bus = dev_get_drvdata(dev); struct hdac_ext_stream *estream; struct hdac_stream *stream; struct snd_pcm_substream substream; @@ -124,7 +120,7 @@ static int skl_dsp_prepare(struct device *dev, unsigned int format, memset(&substream, 0, sizeof(substream)); substream.stream = SNDRV_PCM_STREAM_PLAYBACK; - estream = snd_hdac_ext_stream_assign(ebus, &substream, + estream = snd_hdac_ext_stream_assign(bus, &substream, HDAC_EXT_STREAM_TYPE_HOST); if (!estream) return -ENODEV; @@ -143,9 +139,8 @@ static int skl_dsp_prepare(struct device *dev, unsigned int format, static int skl_dsp_trigger(struct device *dev, bool start, int stream_tag) { - struct hdac_ext_bus *ebus = dev_get_drvdata(dev); + struct hdac_bus *bus = dev_get_drvdata(dev); struct hdac_stream *stream; - struct hdac_bus *bus = ebus_to_hbus(ebus); if (!bus) return -ENODEV; @@ -163,10 +158,9 @@ static int skl_dsp_trigger(struct device *dev, bool start, int stream_tag) static int skl_dsp_cleanup(struct device *dev, struct snd_dma_buffer *dmab, int stream_tag) { - struct hdac_ext_bus *ebus = dev_get_drvdata(dev); + struct hdac_bus *bus = dev_get_drvdata(dev); struct hdac_stream *stream; struct hdac_ext_stream *estream; - struct hdac_bus *bus = ebus_to_hbus(ebus); if (!bus) return -ENODEV; @@ -270,8 +264,7 @@ const struct skl_dsp_ops *skl_get_dsp_ops(int pci_id) int skl_init_dsp(struct skl *skl) { void __iomem *mmio_base; - struct hdac_ext_bus *ebus = &skl->ebus; - struct hdac_bus *bus = ebus_to_hbus(ebus); + struct hdac_bus *bus = skl_to_bus(skl); struct skl_dsp_loader_ops loader_ops; int irq = bus->irq; const struct skl_dsp_ops *ops; @@ -279,8 +272,8 @@ int skl_init_dsp(struct skl *skl) int ret; /* enable ppcap interrupt */ - snd_hdac_ext_bus_ppcap_enable(&skl->ebus, true); - snd_hdac_ext_bus_ppcap_int_enable(&skl->ebus, true); + snd_hdac_ext_bus_ppcap_enable(bus, true); + snd_hdac_ext_bus_ppcap_int_enable(bus, true); /* read the BAR of the ADSP MMIO */ mmio_base = pci_ioremap_bar(skl->pci, 4); @@ -335,12 +328,11 @@ unmap_mmio: int skl_free_dsp(struct skl *skl) { - struct hdac_ext_bus *ebus = &skl->ebus; - struct hdac_bus *bus = ebus_to_hbus(ebus); + struct hdac_bus *bus = skl_to_bus(skl); struct skl_sst *ctx = skl->skl_sst; /* disable ppcap interrupt */ - snd_hdac_ext_bus_ppcap_int_enable(&skl->ebus, false); + snd_hdac_ext_bus_ppcap_int_enable(bus, false); ctx->dsp_ops->cleanup(bus->dev, ctx); @@ -383,10 +375,11 @@ int skl_suspend_late_dsp(struct skl *skl) int skl_suspend_dsp(struct skl *skl) { struct skl_sst *ctx = skl->skl_sst; + struct hdac_bus *bus = skl_to_bus(skl); int ret; /* if ppcap is not supported return 0 */ - if (!skl->ebus.bus.ppcap) + if (!bus->ppcap) return 0; ret = skl_dsp_sleep(ctx->dsp); @@ -394,8 +387,8 @@ int skl_suspend_dsp(struct skl *skl) return ret; /* disable ppcap interrupt */ - snd_hdac_ext_bus_ppcap_int_enable(&skl->ebus, false); - snd_hdac_ext_bus_ppcap_enable(&skl->ebus, false); + snd_hdac_ext_bus_ppcap_int_enable(bus, false); + snd_hdac_ext_bus_ppcap_enable(bus, false); return 0; } @@ -403,15 +396,16 @@ int skl_suspend_dsp(struct skl *skl) int skl_resume_dsp(struct skl *skl) { struct skl_sst *ctx = skl->skl_sst; + struct hdac_bus *bus = skl_to_bus(skl); int ret; /* if ppcap is not supported return 0 */ - if (!skl->ebus.bus.ppcap) + if (!bus->ppcap) return 0; /* enable ppcap interrupt */ - snd_hdac_ext_bus_ppcap_enable(&skl->ebus, true); - snd_hdac_ext_bus_ppcap_int_enable(&skl->ebus, true); + snd_hdac_ext_bus_ppcap_enable(bus, true); + snd_hdac_ext_bus_ppcap_int_enable(bus, true); /* check if DSP 1st boot is done */ if (skl->skl_sst->is_first_boot == true) diff --git a/sound/soc/intel/skylake/skl-nhlt.c b/sound/soc/intel/skylake/skl-nhlt.c index b9b140275be0..01a050cf8775 100644 --- a/sound/soc/intel/skylake/skl-nhlt.c +++ b/sound/soc/intel/skylake/skl-nhlt.c @@ -141,7 +141,7 @@ struct nhlt_specific_cfg { struct nhlt_fmt *fmt; struct nhlt_endpoint *epnt; - struct hdac_bus *bus = ebus_to_hbus(&skl->ebus); + struct hdac_bus *bus = skl_to_bus(skl); struct device *dev = bus->dev; struct nhlt_specific_cfg *sp_config; struct nhlt_acpi_table *nhlt = skl->nhlt; @@ -228,7 +228,7 @@ static void skl_nhlt_trim_space(char *trim) int skl_nhlt_update_topology_bin(struct skl *skl) { struct nhlt_acpi_table *nhlt = (struct nhlt_acpi_table *)skl->nhlt; - struct hdac_bus *bus = ebus_to_hbus(&skl->ebus); + struct hdac_bus *bus = skl_to_bus(skl); struct device *dev = bus->dev; dev_dbg(dev, "oem_id %.6s, oem_table_id %8s oem_revision %d\n", @@ -248,8 +248,8 @@ static ssize_t skl_nhlt_platform_id_show(struct device *dev, struct device_attribute *attr, char *buf) { struct pci_dev *pci = to_pci_dev(dev); - struct hdac_ext_bus *ebus = pci_get_drvdata(pci); - struct skl *skl = ebus_to_skl(ebus); + struct hdac_bus *bus = pci_get_drvdata(pci); + struct skl *skl = bus_to_skl(bus); struct nhlt_acpi_table *nhlt = (struct nhlt_acpi_table *)skl->nhlt; char platform_id[32]; diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c index afa86b9e4dcf..d7fc3b2d3e68 100644 --- a/sound/soc/intel/skylake/skl-pcm.c +++ b/sound/soc/intel/skylake/skl-pcm.c @@ -67,16 +67,15 @@ struct hdac_ext_stream *get_hdac_ext_stream(struct snd_pcm_substream *substream) return substream->runtime->private_data; } -static struct hdac_ext_bus *get_bus_ctx(struct snd_pcm_substream *substream) +static struct hdac_bus *get_bus_ctx(struct snd_pcm_substream *substream) { struct hdac_ext_stream *stream = get_hdac_ext_stream(substream); struct hdac_stream *hstream = hdac_stream(stream); struct hdac_bus *bus = hstream->bus; - - return hbus_to_ebus(bus); + return bus; } -static int skl_substream_alloc_pages(struct hdac_ext_bus *ebus, +static int skl_substream_alloc_pages(struct hdac_bus *bus, struct snd_pcm_substream *substream, size_t size) { @@ -95,7 +94,7 @@ static int skl_substream_free_pages(struct hdac_bus *bus, return snd_pcm_lib_free_pages(substream); } -static void skl_set_pcm_constrains(struct hdac_ext_bus *ebus, +static void skl_set_pcm_constrains(struct hdac_bus *bus, struct snd_pcm_runtime *runtime) { snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); @@ -105,9 +104,9 @@ static void skl_set_pcm_constrains(struct hdac_ext_bus *ebus, 20, 178000000); } -static enum hdac_ext_stream_type skl_get_host_stream_type(struct hdac_ext_bus *ebus) +static enum hdac_ext_stream_type skl_get_host_stream_type(struct hdac_bus *bus) { - if ((ebus_to_hbus(ebus))->ppcap) + if (bus->ppcap) return HDAC_EXT_STREAM_TYPE_HOST; else return HDAC_EXT_STREAM_TYPE_COUPLED; @@ -123,9 +122,9 @@ static enum hdac_ext_stream_type skl_get_host_stream_type(struct hdac_ext_bus *e static void skl_set_suspend_active(struct snd_pcm_substream *substream, struct snd_soc_dai *dai, bool enable) { - struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev); + struct hdac_bus *bus = dev_get_drvdata(dai->dev); struct snd_soc_dapm_widget *w; - struct skl *skl = ebus_to_skl(ebus); + struct skl *skl = bus_to_skl(bus); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) w = dai->playback_widget; @@ -140,8 +139,7 @@ static void skl_set_suspend_active(struct snd_pcm_substream *substream, int skl_pcm_host_dma_prepare(struct device *dev, struct skl_pipe_params *params) { - struct hdac_ext_bus *ebus = dev_get_drvdata(dev); - struct hdac_bus *bus = ebus_to_hbus(ebus); + struct hdac_bus *bus = dev_get_drvdata(dev); unsigned int format_val; struct hdac_stream *hstream; struct hdac_ext_stream *stream; @@ -153,7 +151,7 @@ int skl_pcm_host_dma_prepare(struct device *dev, struct skl_pipe_params *params) return -EINVAL; stream = stream_to_hdac_ext_stream(hstream); - snd_hdac_ext_stream_decouple(ebus, stream, true); + snd_hdac_ext_stream_decouple(bus, stream, true); format_val = snd_hdac_calc_stream_format(params->s_freq, params->ch, params->format, params->host_bps, 0); @@ -177,8 +175,7 @@ int skl_pcm_host_dma_prepare(struct device *dev, struct skl_pipe_params *params) int skl_pcm_link_dma_prepare(struct device *dev, struct skl_pipe_params *params) { - struct hdac_ext_bus *ebus = dev_get_drvdata(dev); - struct hdac_bus *bus = ebus_to_hbus(ebus); + struct hdac_bus *bus = dev_get_drvdata(dev); unsigned int format_val; struct hdac_stream *hstream; struct hdac_ext_stream *stream; @@ -190,7 +187,7 @@ int skl_pcm_link_dma_prepare(struct device *dev, struct skl_pipe_params *params) return -EINVAL; stream = stream_to_hdac_ext_stream(hstream); - snd_hdac_ext_stream_decouple(ebus, stream, true); + snd_hdac_ext_stream_decouple(bus, stream, true); format_val = snd_hdac_calc_stream_format(params->s_freq, params->ch, params->format, params->link_bps, 0); @@ -201,7 +198,7 @@ int skl_pcm_link_dma_prepare(struct device *dev, struct skl_pipe_params *params) snd_hdac_ext_link_stream_setup(stream, format_val); - list_for_each_entry(link, &ebus->hlink_list, list) { + list_for_each_entry(link, &bus->hlink_list, list) { if (link->index == params->link_index) snd_hdac_ext_link_set_stream_id(link, hstream->stream_tag); @@ -215,7 +212,7 @@ int skl_pcm_link_dma_prepare(struct device *dev, struct skl_pipe_params *params) static int skl_pcm_open(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev); + struct hdac_bus *bus = dev_get_drvdata(dai->dev); struct hdac_ext_stream *stream; struct snd_pcm_runtime *runtime = substream->runtime; struct skl_dma_params *dma_params; @@ -224,12 +221,12 @@ static int skl_pcm_open(struct snd_pcm_substream *substream, dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name); - stream = snd_hdac_ext_stream_assign(ebus, substream, - skl_get_host_stream_type(ebus)); + stream = snd_hdac_ext_stream_assign(bus, substream, + skl_get_host_stream_type(bus)); if (stream == NULL) return -EBUSY; - skl_set_pcm_constrains(ebus, runtime); + skl_set_pcm_constrains(bus, runtime); /* * disable WALLCLOCK timestamps for capture streams @@ -301,7 +298,7 @@ static int skl_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev); + struct hdac_bus *bus = dev_get_drvdata(dai->dev); struct hdac_ext_stream *stream = get_hdac_ext_stream(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct skl_pipe_params p_params = {0}; @@ -309,7 +306,7 @@ static int skl_pcm_hw_params(struct snd_pcm_substream *substream, int ret, dma_id; dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name); - ret = skl_substream_alloc_pages(ebus, substream, + ret = skl_substream_alloc_pages(bus, substream, params_buffer_bytes(params)); if (ret < 0) return ret; @@ -343,14 +340,14 @@ static void skl_pcm_close(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct hdac_ext_stream *stream = get_hdac_ext_stream(substream); - struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev); + struct hdac_bus *bus = dev_get_drvdata(dai->dev); struct skl_dma_params *dma_params = NULL; - struct skl *skl = ebus_to_skl(ebus); + struct skl *skl = bus_to_skl(bus); struct skl_module_cfg *mconfig; dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name); - snd_hdac_ext_stream_release(stream, skl_get_host_stream_type(ebus)); + snd_hdac_ext_stream_release(stream, skl_get_host_stream_type(bus)); dma_params = snd_soc_dai_get_dma_data(dai, substream); /* @@ -380,7 +377,7 @@ static void skl_pcm_close(struct snd_pcm_substream *substream, static int skl_pcm_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev); + struct hdac_bus *bus = dev_get_drvdata(dai->dev); struct hdac_ext_stream *stream = get_hdac_ext_stream(substream); struct skl *skl = get_skl_ctx(dai->dev); struct skl_module_cfg *mconfig; @@ -400,7 +397,7 @@ static int skl_pcm_hw_free(struct snd_pcm_substream *substream, snd_hdac_stream_cleanup(hdac_stream(stream)); hdac_stream(stream)->prepared = 0; - return skl_substream_free_pages(ebus_to_hbus(ebus), substream); + return skl_substream_free_pages(bus, substream); } static int skl_be_hw_params(struct snd_pcm_substream *substream, @@ -420,8 +417,7 @@ static int skl_be_hw_params(struct snd_pcm_substream *substream, static int skl_decoupled_trigger(struct snd_pcm_substream *substream, int cmd) { - struct hdac_ext_bus *ebus = get_bus_ctx(substream); - struct hdac_bus *bus = ebus_to_hbus(ebus); + struct hdac_bus *bus = get_bus_ctx(substream); struct hdac_ext_stream *stream; int start; unsigned long cookie; @@ -470,7 +466,7 @@ static int skl_pcm_trigger(struct snd_pcm_substream *substream, int cmd, struct skl *skl = get_skl_ctx(dai->dev); struct skl_sst *ctx = skl->skl_sst; struct skl_module_cfg *mconfig; - struct hdac_ext_bus *ebus = get_bus_ctx(substream); + struct hdac_bus *bus = get_bus_ctx(substream); struct hdac_ext_stream *stream = get_hdac_ext_stream(substream); struct snd_soc_dapm_widget *w; int ret; @@ -492,9 +488,9 @@ static int skl_pcm_trigger(struct snd_pcm_substream *substream, int cmd, * dpib & lpib position to resume before starting the * DMA */ - snd_hdac_ext_stream_drsm_enable(ebus, true, + snd_hdac_ext_stream_drsm_enable(bus, true, hdac_stream(stream)->index); - snd_hdac_ext_stream_set_dpibr(ebus, stream, + snd_hdac_ext_stream_set_dpibr(bus, stream, stream->lpib); snd_hdac_ext_stream_set_lpib(stream, stream->lpib); } @@ -528,14 +524,14 @@ static int skl_pcm_trigger(struct snd_pcm_substream *substream, int cmd, ret = skl_decoupled_trigger(substream, cmd); if ((cmd == SNDRV_PCM_TRIGGER_SUSPEND) && !w->ignore_suspend) { /* save the dpib and lpib positions */ - stream->dpib = readl(ebus->bus.remap_addr + + stream->dpib = readl(bus->remap_addr + AZX_REG_VS_SDXDPIB_XBASE + (AZX_REG_VS_SDXDPIB_XINTERVAL * hdac_stream(stream)->index)); stream->lpib = snd_hdac_stream_get_pos_lpib( hdac_stream(stream)); - snd_hdac_ext_stream_decouple(ebus, stream, false); + snd_hdac_ext_stream_decouple(bus, stream, false); } break; @@ -546,11 +542,12 @@ static int skl_pcm_trigger(struct snd_pcm_substream *substream, int cmd, return 0; } + static int skl_link_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev); + struct hdac_bus *bus = dev_get_drvdata(dai->dev); struct hdac_ext_stream *link_dev; struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); struct snd_soc_dai *codec_dai = rtd->codec_dai; @@ -558,14 +555,14 @@ static int skl_link_hw_params(struct snd_pcm_substream *substream, struct hdac_ext_link *link; int stream_tag; - link_dev = snd_hdac_ext_stream_assign(ebus, substream, + link_dev = snd_hdac_ext_stream_assign(bus, substream, HDAC_EXT_STREAM_TYPE_LINK); if (!link_dev) return -EBUSY; snd_soc_dai_set_dma_data(dai, substream, (void *)link_dev); - link = snd_hdac_ext_bus_get_link(ebus, codec_dai->component->name); + link = snd_hdac_ext_bus_get_link(bus, codec_dai->component->name); if (!link) return -EINVAL; @@ -610,7 +607,7 @@ static int skl_link_pcm_trigger(struct snd_pcm_substream *substream, { struct hdac_ext_stream *link_dev = snd_soc_dai_get_dma_data(dai, substream); - struct hdac_ext_bus *ebus = get_bus_ctx(substream); + struct hdac_bus *bus = get_bus_ctx(substream); struct hdac_ext_stream *stream = get_hdac_ext_stream(substream); dev_dbg(dai->dev, "In %s cmd=%d\n", __func__, cmd); @@ -626,7 +623,7 @@ static int skl_link_pcm_trigger(struct snd_pcm_substream *substream, case SNDRV_PCM_TRIGGER_STOP: snd_hdac_ext_link_stream_clear(link_dev); if (cmd == SNDRV_PCM_TRIGGER_SUSPEND) - snd_hdac_ext_stream_decouple(ebus, stream, false); + snd_hdac_ext_stream_decouple(bus, stream, false); break; default: @@ -638,7 +635,7 @@ static int skl_link_pcm_trigger(struct snd_pcm_substream *substream, static int skl_link_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev); + struct hdac_bus *bus = dev_get_drvdata(dai->dev); struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); struct hdac_ext_stream *link_dev = snd_soc_dai_get_dma_data(dai, substream); @@ -648,7 +645,7 @@ static int skl_link_hw_free(struct snd_pcm_substream *substream, link_dev->link_prepared = 0; - link = snd_hdac_ext_bus_get_link(ebus, rtd->codec_dai->component->name); + link = snd_hdac_ext_bus_get_link(bus, rtd->codec_dai->component->name); if (!link) return -EINVAL; @@ -1041,8 +1038,7 @@ static int skl_platform_open(struct snd_pcm_substream *substream) static int skl_coupled_trigger(struct snd_pcm_substream *substream, int cmd) { - struct hdac_ext_bus *ebus = get_bus_ctx(substream); - struct hdac_bus *bus = ebus_to_hbus(ebus); + struct hdac_bus *bus = get_bus_ctx(substream); struct hdac_ext_stream *stream; struct snd_pcm_substream *s; bool start; @@ -1115,9 +1111,9 @@ static int skl_coupled_trigger(struct snd_pcm_substream *substream, static int skl_platform_pcm_trigger(struct snd_pcm_substream *substream, int cmd) { - struct hdac_ext_bus *ebus = get_bus_ctx(substream); + struct hdac_bus *bus = get_bus_ctx(substream); - if (!(ebus_to_hbus(ebus))->ppcap) + if (!bus->ppcap) return skl_coupled_trigger(substream, cmd); return 0; @@ -1127,7 +1123,7 @@ static snd_pcm_uframes_t skl_platform_pcm_pointer (struct snd_pcm_substream *substream) { struct hdac_ext_stream *hstream = get_hdac_ext_stream(substream); - struct hdac_ext_bus *ebus = get_bus_ctx(substream); + struct hdac_bus *bus = get_bus_ctx(substream); unsigned int pos; /* @@ -1152,12 +1148,12 @@ static snd_pcm_uframes_t skl_platform_pcm_pointer */ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - pos = readl(ebus->bus.remap_addr + AZX_REG_VS_SDXDPIB_XBASE + + pos = readl(bus->remap_addr + AZX_REG_VS_SDXDPIB_XBASE + (AZX_REG_VS_SDXDPIB_XINTERVAL * hdac_stream(hstream)->index)); } else { udelay(20); - readl(ebus->bus.remap_addr + + readl(bus->remap_addr + AZX_REG_VS_SDXDPIB_XBASE + (AZX_REG_VS_SDXDPIB_XINTERVAL * hdac_stream(hstream)->index)); @@ -1242,11 +1238,11 @@ static void skl_pcm_free(struct snd_pcm *pcm) static int skl_pcm_new(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_dai *dai = rtd->cpu_dai; - struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev); + struct hdac_bus *bus = dev_get_drvdata(dai->dev); struct snd_pcm *pcm = rtd->pcm; unsigned int size; int retval = 0; - struct skl *skl = ebus_to_skl(ebus); + struct skl *skl = bus_to_skl(bus); if (dai->driver->playback.channels_min || dai->driver->capture.channels_min) { @@ -1356,19 +1352,19 @@ static int skl_populate_modules(struct skl *skl) static int skl_platform_soc_probe(struct snd_soc_component *component) { - struct hdac_ext_bus *ebus = dev_get_drvdata(component->dev); - struct skl *skl = ebus_to_skl(ebus); + struct hdac_bus *bus = dev_get_drvdata(component->dev); + struct skl *skl = bus_to_skl(bus); const struct skl_dsp_ops *ops; int ret; pm_runtime_get_sync(component->dev); - if ((ebus_to_hbus(ebus))->ppcap) { + if (bus->ppcap) { skl->component = component; /* init debugfs */ skl->debugfs = skl_debugfs_init(skl); - ret = skl_tplg_init(component, ebus); + ret = skl_tplg_init(component, bus); if (ret < 0) { dev_err(component->dev, "Failed to init topology!\n"); return ret; @@ -1425,10 +1421,10 @@ static const struct snd_soc_component_driver skl_component = { int skl_platform_register(struct device *dev) { int ret; - struct hdac_ext_bus *ebus = dev_get_drvdata(dev); - struct skl *skl = ebus_to_skl(ebus); struct snd_soc_dai_driver *dais; int num_dais = ARRAY_SIZE(skl_platform_dai); + struct hdac_bus *bus = dev_get_drvdata(dev); + struct skl *skl = bus_to_skl(bus); INIT_LIST_HEAD(&skl->ppl_list); INIT_LIST_HEAD(&skl->bind_list); @@ -1464,8 +1460,8 @@ err: int skl_platform_unregister(struct device *dev) { - struct hdac_ext_bus *ebus = dev_get_drvdata(dev); - struct skl *skl = ebus_to_skl(ebus); + struct hdac_bus *bus = dev_get_drvdata(dev); + struct skl *skl = bus_to_skl(bus); struct skl_module_deferred_bind *modules, *tmp; if (!list_empty(&skl->bind_list)) { diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index fcdc716754b6..abfdb67c05cc 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -934,7 +934,7 @@ static int skl_tplg_find_moduleid_from_uuid(struct skl *skl, struct soc_bytes_ext *sb = (void *) k->private_value; struct skl_algo_data *bc = (struct skl_algo_data *)sb->dobj.private; struct skl_kpb_params *uuid_params, *params; - struct hdac_bus *bus = ebus_to_hbus(skl_to_ebus(skl)); + struct hdac_bus *bus = skl_to_bus(skl); int i, size, module_id; if (bc->set_params == SKL_PARAM_BIND && bc->max) { @@ -3029,9 +3029,8 @@ static int skl_tplg_widget_load(struct snd_soc_component *cmpnt, struct snd_soc_tplg_dapm_widget *tplg_w) { int ret; - struct hdac_ext_bus *ebus = snd_soc_component_get_drvdata(cmpnt); - struct skl *skl = ebus_to_skl(ebus); - struct hdac_bus *bus = ebus_to_hbus(ebus); + struct hdac_bus *bus = snd_soc_component_get_drvdata(cmpnt); + struct skl *skl = bus_to_skl(bus); struct skl_module_cfg *mconfig; if (!tplg_w->priv.size) @@ -3137,8 +3136,7 @@ static int skl_tplg_control_load(struct snd_soc_component *cmpnt, struct soc_bytes_ext *sb; struct snd_soc_tplg_bytes_control *tplg_bc; struct snd_soc_tplg_enum_control *tplg_ec; - struct hdac_ext_bus *ebus = snd_soc_component_get_drvdata(cmpnt); - struct hdac_bus *bus = ebus_to_hbus(ebus); + struct hdac_bus *bus = snd_soc_component_get_drvdata(cmpnt); struct soc_enum *se; switch (hdr->ops.info) { @@ -3622,9 +3620,8 @@ static int skl_tplg_get_manifest_data(struct snd_soc_tplg_manifest *manifest, static int skl_manifest_load(struct snd_soc_component *cmpnt, struct snd_soc_tplg_manifest *manifest) { - struct hdac_ext_bus *ebus = snd_soc_component_get_drvdata(cmpnt); - struct hdac_bus *bus = ebus_to_hbus(ebus); - struct skl *skl = ebus_to_skl(ebus); + struct hdac_bus *bus = snd_soc_component_get_drvdata(cmpnt); + struct skl *skl = bus_to_skl(bus); /* proceed only if we have private data defined */ if (manifest->priv.size == 0) @@ -3713,12 +3710,11 @@ static void skl_tplg_set_pipe_type(struct skl *skl, struct skl_pipe *pipe) /* * SKL topology init routine */ -int skl_tplg_init(struct snd_soc_component *component, struct hdac_ext_bus *ebus) +int skl_tplg_init(struct snd_soc_component *component, struct hdac_bus *bus) { int ret; const struct firmware *fw; - struct hdac_bus *bus = ebus_to_hbus(ebus); - struct skl *skl = ebus_to_skl(ebus); + struct skl *skl = bus_to_skl(bus); struct skl_pipeline *ppl; ret = request_firmware(&fw, skl->tplg_name, bus->dev); diff --git a/sound/soc/intel/skylake/skl-topology.h b/sound/soc/intel/skylake/skl-topology.h index 6d7e0569695f..daeb6d2bb7fc 100644 --- a/sound/soc/intel/skylake/skl-topology.h +++ b/sound/soc/intel/skylake/skl-topology.h @@ -458,9 +458,9 @@ enum skl_channel { static inline struct skl *get_skl_ctx(struct device *dev) { - struct hdac_ext_bus *ebus = dev_get_drvdata(dev); + struct hdac_bus *bus = dev_get_drvdata(dev); - return ebus_to_skl(ebus); + return bus_to_skl(bus); } int skl_tplg_be_update_params(struct snd_soc_dai *dai, @@ -470,7 +470,7 @@ int skl_dsp_set_dma_control(struct skl_sst *ctx, u32 *caps, void skl_tplg_set_be_dmic_config(struct snd_soc_dai *dai, struct skl_pipe_params *params, int stream); int skl_tplg_init(struct snd_soc_component *component, - struct hdac_ext_bus *ebus); + struct hdac_bus *ebus); struct skl_module_cfg *skl_tplg_fe_get_cpr_module( struct snd_soc_dai *dai, int stream); int skl_tplg_update_pipe_params(struct device *dev, diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c index f0d9793f872a..9c5a701d68ac 100644 --- a/sound/soc/intel/skylake/skl.c +++ b/sound/soc/intel/skylake/skl.c @@ -54,7 +54,7 @@ static void skl_update_pci_byte(struct pci_dev *pci, unsigned int reg, static void skl_init_pci(struct skl *skl) { - struct hdac_ext_bus *ebus = &skl->ebus; + struct hdac_bus *bus = skl_to_bus(skl); /* * Clear bits 0-2 of PCI register TCSEL (at offset 0x44) @@ -63,7 +63,7 @@ static void skl_init_pci(struct skl *skl) * codecs. * The PCI register TCSEL is defined in the Intel manuals. */ - dev_dbg(ebus_to_hbus(ebus)->dev, "Clearing TCSEL\n"); + dev_dbg(bus->dev, "Clearing TCSEL\n"); skl_update_pci_byte(skl->pci, AZX_PCIREG_TCSEL, 0x07, 0); } @@ -103,8 +103,7 @@ static void skl_enable_miscbdcge(struct device *dev, bool enable) static void skl_clock_power_gating(struct device *dev, bool enable) { struct pci_dev *pci = to_pci_dev(dev); - struct hdac_ext_bus *ebus = pci_get_drvdata(pci); - struct hdac_bus *bus = ebus_to_hbus(ebus); + struct hdac_bus *bus = pci_get_drvdata(pci); u32 val; /* Update PDCGE bit of CGCTL register */ @@ -127,7 +126,6 @@ static void skl_clock_power_gating(struct device *dev, bool enable) */ static int skl_init_chip(struct hdac_bus *bus, bool full_reset) { - struct hdac_ext_bus *ebus = hbus_to_ebus(bus); struct hdac_ext_link *hlink; int ret; @@ -135,7 +133,7 @@ static int skl_init_chip(struct hdac_bus *bus, bool full_reset) ret = snd_hdac_bus_init_chip(bus, full_reset); /* Reset stream-to-link mapping */ - list_for_each_entry(hlink, &ebus->hlink_list, list) + list_for_each_entry(hlink, &bus->hlink_list, list) bus->io_ops->reg_writel(0, hlink->ml_addr + AZX_REG_ML_LOSIDV); skl_enable_miscbdcge(bus->dev, true); @@ -146,8 +144,7 @@ static int skl_init_chip(struct hdac_bus *bus, bool full_reset) void skl_update_d0i3c(struct device *dev, bool enable) { struct pci_dev *pci = to_pci_dev(dev); - struct hdac_ext_bus *ebus = pci_get_drvdata(pci); - struct hdac_bus *bus = ebus_to_hbus(ebus); + struct hdac_bus *bus = pci_get_drvdata(pci); u8 reg; int timeout = 50; @@ -197,8 +194,7 @@ static void skl_stream_update(struct hdac_bus *bus, struct hdac_stream *hstr) static irqreturn_t skl_interrupt(int irq, void *dev_id) { - struct hdac_ext_bus *ebus = dev_id; - struct hdac_bus *bus = ebus_to_hbus(ebus); + struct hdac_bus *bus = dev_id; u32 status; if (!pm_runtime_active(bus->dev)) @@ -227,8 +223,7 @@ static irqreturn_t skl_interrupt(int irq, void *dev_id) static irqreturn_t skl_threaded_handler(int irq, void *dev_id) { - struct hdac_ext_bus *ebus = dev_id; - struct hdac_bus *bus = ebus_to_hbus(ebus); + struct hdac_bus *bus = dev_id; u32 status; status = snd_hdac_chip_readl(bus, INTSTS); @@ -238,16 +233,15 @@ static irqreturn_t skl_threaded_handler(int irq, void *dev_id) return IRQ_HANDLED; } -static int skl_acquire_irq(struct hdac_ext_bus *ebus, int do_disconnect) +static int skl_acquire_irq(struct hdac_bus *bus, int do_disconnect) { - struct skl *skl = ebus_to_skl(ebus); - struct hdac_bus *bus = ebus_to_hbus(ebus); + struct skl *skl = bus_to_skl(bus); int ret; ret = request_threaded_irq(skl->pci->irq, skl_interrupt, skl_threaded_handler, IRQF_SHARED, - KBUILD_MODNAME, ebus); + KBUILD_MODNAME, bus); if (ret) { dev_err(bus->dev, "unable to grab IRQ %d, disabling device\n", @@ -264,21 +258,20 @@ static int skl_acquire_irq(struct hdac_ext_bus *ebus, int do_disconnect) static int skl_suspend_late(struct device *dev) { struct pci_dev *pci = to_pci_dev(dev); - struct hdac_ext_bus *ebus = pci_get_drvdata(pci); - struct skl *skl = ebus_to_skl(ebus); + struct hdac_bus *bus = pci_get_drvdata(pci); + struct skl *skl = bus_to_skl(bus); return skl_suspend_late_dsp(skl); } #ifdef CONFIG_PM -static int _skl_suspend(struct hdac_ext_bus *ebus) +static int _skl_suspend(struct hdac_bus *bus) { - struct skl *skl = ebus_to_skl(ebus); - struct hdac_bus *bus = ebus_to_hbus(ebus); + struct skl *skl = bus_to_skl(bus); struct pci_dev *pci = to_pci_dev(bus->dev); int ret; - snd_hdac_ext_bus_link_power_down_all(ebus); + snd_hdac_ext_bus_link_power_down_all(bus); ret = skl_suspend_dsp(skl); if (ret < 0) @@ -295,10 +288,9 @@ static int _skl_suspend(struct hdac_ext_bus *ebus) return 0; } -static int _skl_resume(struct hdac_ext_bus *ebus) +static int _skl_resume(struct hdac_bus *bus) { - struct skl *skl = ebus_to_skl(ebus); - struct hdac_bus *bus = ebus_to_hbus(ebus); + struct skl *skl = bus_to_skl(bus); skl_init_pci(skl); skl_init_chip(bus, true); @@ -314,9 +306,8 @@ static int _skl_resume(struct hdac_ext_bus *ebus) static int skl_suspend(struct device *dev) { struct pci_dev *pci = to_pci_dev(dev); - struct hdac_ext_bus *ebus = pci_get_drvdata(pci); - struct skl *skl = ebus_to_skl(ebus); - struct hdac_bus *bus = ebus_to_hbus(ebus); + struct hdac_bus *bus = pci_get_drvdata(pci); + struct skl *skl = bus_to_skl(bus); int ret = 0; /* @@ -325,15 +316,15 @@ static int skl_suspend(struct device *dev) */ if (skl->supend_active) { /* turn off the links and stop the CORB/RIRB DMA if it is On */ - snd_hdac_ext_bus_link_power_down_all(ebus); + snd_hdac_ext_bus_link_power_down_all(bus); - if (ebus->cmd_dma_state) - snd_hdac_bus_stop_cmd_io(&ebus->bus); + if (bus->cmd_dma_state) + snd_hdac_bus_stop_cmd_io(bus); enable_irq_wake(bus->irq); pci_save_state(pci); } else { - ret = _skl_suspend(ebus); + ret = _skl_suspend(bus); if (ret < 0) return ret; skl->skl_sst->fw_loaded = false; @@ -352,9 +343,8 @@ static int skl_suspend(struct device *dev) static int skl_resume(struct device *dev) { struct pci_dev *pci = to_pci_dev(dev); - struct hdac_ext_bus *ebus = pci_get_drvdata(pci); - struct skl *skl = ebus_to_skl(ebus); - struct hdac_bus *bus = ebus_to_hbus(ebus); + struct hdac_bus *bus = pci_get_drvdata(pci); + struct skl *skl = bus_to_skl(bus); struct hdac_ext_link *hlink = NULL; int ret; @@ -374,32 +364,32 @@ static int skl_resume(struct device *dev) */ if (skl->supend_active) { pci_restore_state(pci); - snd_hdac_ext_bus_link_power_up_all(ebus); + snd_hdac_ext_bus_link_power_up_all(bus); disable_irq_wake(bus->irq); /* * turn On the links which are On before active suspend * and start the CORB/RIRB DMA if On before * active suspend. */ - list_for_each_entry(hlink, &ebus->hlink_list, list) { + list_for_each_entry(hlink, &bus->hlink_list, list) { if (hlink->ref_count) snd_hdac_ext_bus_link_power_up(hlink); } - if (ebus->cmd_dma_state) - snd_hdac_bus_init_cmd_io(&ebus->bus); ret = 0; + if (bus->cmd_dma_state) + snd_hdac_bus_init_cmd_io(bus); } else { - ret = _skl_resume(ebus); + ret = _skl_resume(bus); /* turn off the links which are off before suspend */ - list_for_each_entry(hlink, &ebus->hlink_list, list) { + list_for_each_entry(hlink, &bus->hlink_list, list) { if (!hlink->ref_count) snd_hdac_ext_bus_link_power_down(hlink); } - if (!ebus->cmd_dma_state) - snd_hdac_bus_stop_cmd_io(&ebus->bus); + if (!bus->cmd_dma_state) + snd_hdac_bus_stop_cmd_io(bus); } return ret; @@ -410,23 +400,21 @@ static int skl_resume(struct device *dev) static int skl_runtime_suspend(struct device *dev) { struct pci_dev *pci = to_pci_dev(dev); - struct hdac_ext_bus *ebus = pci_get_drvdata(pci); - struct hdac_bus *bus = ebus_to_hbus(ebus); + struct hdac_bus *bus = pci_get_drvdata(pci); dev_dbg(bus->dev, "in %s\n", __func__); - return _skl_suspend(ebus); + return _skl_suspend(bus); } static int skl_runtime_resume(struct device *dev) { struct pci_dev *pci = to_pci_dev(dev); - struct hdac_ext_bus *ebus = pci_get_drvdata(pci); - struct hdac_bus *bus = ebus_to_hbus(ebus); + struct hdac_bus *bus = pci_get_drvdata(pci); dev_dbg(bus->dev, "in %s\n", __func__); - return _skl_resume(ebus); + return _skl_resume(bus); } #endif /* CONFIG_PM */ @@ -439,20 +427,19 @@ static const struct dev_pm_ops skl_pm = { /* * destructor */ -static int skl_free(struct hdac_ext_bus *ebus) +static int skl_free(struct hdac_bus *bus) { - struct skl *skl = ebus_to_skl(ebus); - struct hdac_bus *bus = ebus_to_hbus(ebus); + struct skl *skl = bus_to_skl(bus); skl->init_done = 0; /* to be sure */ - snd_hdac_ext_stop_streams(ebus); + snd_hdac_ext_stop_streams(bus); if (bus->irq >= 0) - free_irq(bus->irq, (void *)ebus); + free_irq(bus->irq, (void *)bus); snd_hdac_bus_free_stream_pages(bus); - snd_hdac_stream_free_all(ebus); - snd_hdac_link_free_all(ebus); + snd_hdac_stream_free_all(bus); + snd_hdac_link_free_all(bus); if (bus->remap_addr) iounmap(bus->remap_addr); @@ -460,11 +447,11 @@ static int skl_free(struct hdac_ext_bus *ebus) pci_release_regions(skl->pci); pci_disable_device(skl->pci); - snd_hdac_ext_bus_exit(ebus); + snd_hdac_ext_bus_exit(bus); cancel_work_sync(&skl->probe_work); if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) - snd_hdac_i915_exit(&ebus->bus); + snd_hdac_i915_exit(bus); return 0; } @@ -488,8 +475,8 @@ static struct skl_ssp_clk skl_ssp_clks[] = { static int skl_find_machine(struct skl *skl, void *driver_data) { + struct hdac_bus *bus = skl_to_bus(skl); struct snd_soc_acpi_mach *mach = driver_data; - struct hdac_bus *bus = ebus_to_hbus(&skl->ebus); struct skl_machine_pdata *pdata; mach = snd_soc_acpi_find_machine(mach); @@ -510,7 +497,7 @@ static int skl_find_machine(struct skl *skl, void *driver_data) static int skl_machine_device_register(struct skl *skl) { - struct hdac_bus *bus = ebus_to_hbus(&skl->ebus); + struct hdac_bus *bus = skl_to_bus(skl); struct snd_soc_acpi_mach *mach = skl->mach; struct platform_device *pdev; int ret; @@ -544,7 +531,7 @@ static void skl_machine_device_unregister(struct skl *skl) static int skl_dmic_device_register(struct skl *skl) { - struct hdac_bus *bus = ebus_to_hbus(&skl->ebus); + struct hdac_bus *bus = skl_to_bus(skl); struct platform_device *pdev; int ret; @@ -643,9 +630,8 @@ static void skl_clock_device_unregister(struct skl *skl) /* * Probe the given codec address */ -static int probe_codec(struct hdac_ext_bus *ebus, int addr) +static int probe_codec(struct hdac_bus *bus, int addr) { - struct hdac_bus *bus = ebus_to_hbus(ebus); unsigned int cmd = (addr << 28) | (AC_NODE_ROOT << 20) | (AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID; unsigned int res = -1; @@ -658,13 +644,12 @@ static int probe_codec(struct hdac_ext_bus *ebus, int addr) return -EIO; dev_dbg(bus->dev, "codec #%d probed OK\n", addr); - return snd_hdac_ext_bus_device_init(ebus, addr); + return snd_hdac_ext_bus_device_init(bus, addr); } /* Codec initialization */ -static void skl_codec_create(struct hdac_ext_bus *ebus) +static void skl_codec_create(struct hdac_bus *bus) { - struct hdac_bus *bus = ebus_to_hbus(ebus); int c, max_slots; max_slots = HDA_MAX_CODECS; @@ -672,7 +657,7 @@ static void skl_codec_create(struct hdac_ext_bus *ebus) /* First try to probe all given codec slots */ for (c = 0; c < max_slots; c++) { if ((bus->codec_mask & (1 << c))) { - if (probe_codec(ebus, c) < 0) { + if (probe_codec(bus, c) < 0) { /* * Some BIOSen give you wrong codec addresses * that don't exist @@ -722,8 +707,7 @@ static int skl_i915_init(struct hdac_bus *bus) static void skl_probe_work(struct work_struct *work) { struct skl *skl = container_of(work, struct skl, probe_work); - struct hdac_ext_bus *ebus = &skl->ebus; - struct hdac_bus *bus = ebus_to_hbus(ebus); + struct hdac_bus *bus = skl_to_bus(skl); struct hdac_ext_link *hlink = NULL; int err; @@ -744,7 +728,7 @@ static void skl_probe_work(struct work_struct *work) dev_info(bus->dev, "no hda codecs found!\n"); /* create codec instances */ - skl_codec_create(ebus); + skl_codec_create(bus); /* register platform dai and controls */ err = skl_platform_register(bus->dev); @@ -773,8 +757,8 @@ static void skl_probe_work(struct work_struct *work) /* * we are done probing so decrement link counts */ - list_for_each_entry(hlink, &ebus->hlink_list, list) - snd_hdac_ext_bus_link_put(ebus, hlink); + list_for_each_entry(hlink, &bus->hlink_list, list) + snd_hdac_ext_bus_link_put(bus, hlink); /* configure PM */ pm_runtime_put_noidle(bus->dev); @@ -796,7 +780,7 @@ static int skl_create(struct pci_dev *pci, struct skl **rskl) { struct skl *skl; - struct hdac_ext_bus *ebus; + struct hdac_bus *bus; int err; @@ -811,23 +795,22 @@ static int skl_create(struct pci_dev *pci, pci_disable_device(pci); return -ENOMEM; } - ebus = &skl->ebus; - snd_hdac_ext_bus_init(ebus, &pci->dev, &bus_core_ops, io_ops); - ebus->bus.use_posbuf = 1; + + bus = skl_to_bus(skl); + snd_hdac_ext_bus_init(bus, &pci->dev, &bus_core_ops, io_ops); + bus->use_posbuf = 1; skl->pci = pci; INIT_WORK(&skl->probe_work, skl_probe_work); - - ebus->bus.bdl_pos_adj = 0; + bus->bdl_pos_adj = 0; *rskl = skl; return 0; } -static int skl_first_init(struct hdac_ext_bus *ebus) +static int skl_first_init(struct hdac_bus *bus) { - struct skl *skl = ebus_to_skl(ebus); - struct hdac_bus *bus = ebus_to_hbus(ebus); + struct skl *skl = bus_to_skl(bus); struct pci_dev *pci = skl->pci; int err; unsigned short gcap; @@ -848,7 +831,7 @@ static int skl_first_init(struct hdac_ext_bus *ebus) snd_hdac_bus_parse_capabilities(bus); - if (skl_acquire_irq(ebus, 0) < 0) + if (skl_acquire_irq(bus, 0) < 0) return -EBUSY; pci_set_master(pci); @@ -872,14 +855,14 @@ static int skl_first_init(struct hdac_ext_bus *ebus) if (!pb_streams && !cp_streams) return -EIO; - ebus->num_streams = cp_streams + pb_streams; + bus->num_streams = cp_streams + pb_streams; /* initialize streams */ snd_hdac_ext_stream_init_all - (ebus, 0, cp_streams, SNDRV_PCM_STREAM_CAPTURE); + (bus, 0, cp_streams, SNDRV_PCM_STREAM_CAPTURE); start_idx = cp_streams; snd_hdac_ext_stream_init_all - (ebus, start_idx, pb_streams, SNDRV_PCM_STREAM_PLAYBACK); + (bus, start_idx, pb_streams, SNDRV_PCM_STREAM_PLAYBACK); err = snd_hdac_bus_alloc_stream_pages(bus); if (err < 0) @@ -895,7 +878,6 @@ static int skl_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { struct skl *skl; - struct hdac_ext_bus *ebus = NULL; struct hdac_bus *bus = NULL; int err; @@ -904,10 +886,9 @@ static int skl_probe(struct pci_dev *pci, if (err < 0) return err; - ebus = &skl->ebus; - bus = ebus_to_hbus(ebus); + bus = skl_to_bus(skl); - err = skl_first_init(ebus); + err = skl_first_init(bus); if (err < 0) goto out_free; @@ -928,7 +909,7 @@ static int skl_probe(struct pci_dev *pci, skl_nhlt_update_topology_bin(skl); - pci_set_drvdata(skl->pci, ebus); + pci_set_drvdata(skl->pci, bus); skl_dmic_data.dmic_num = skl_get_dmic_geo(skl); @@ -952,7 +933,7 @@ static int skl_probe(struct pci_dev *pci, skl->skl_sst->clock_power_gating = skl_clock_power_gating; } if (bus->mlcap) - snd_hdac_ext_bus_get_ml_capabilities(ebus); + snd_hdac_ext_bus_get_ml_capabilities(bus); snd_hdac_bus_stop_chip(bus); @@ -972,31 +953,30 @@ out_clk_free: out_nhlt_free: skl_nhlt_free(skl->nhlt); out_free: - skl_free(ebus); + skl_free(bus); return err; } static void skl_shutdown(struct pci_dev *pci) { - struct hdac_ext_bus *ebus = pci_get_drvdata(pci); - struct hdac_bus *bus = ebus_to_hbus(ebus); + struct hdac_bus *bus = pci_get_drvdata(pci); struct hdac_stream *s; struct hdac_ext_stream *stream; struct skl *skl; - if (ebus == NULL) + if (!bus) return; - skl = ebus_to_skl(ebus); + skl = bus_to_skl(bus); if (!skl->init_done) return; - snd_hdac_ext_stop_streams(ebus); + snd_hdac_ext_stop_streams(bus); list_for_each_entry(s, &bus->stream_list, list) { stream = stream_to_hdac_ext_stream(s); - snd_hdac_ext_stream_decouple(ebus, stream, false); + snd_hdac_ext_stream_decouple(bus, stream, false); } snd_hdac_bus_stop_chip(bus); @@ -1004,15 +984,15 @@ static void skl_shutdown(struct pci_dev *pci) static void skl_remove(struct pci_dev *pci) { - struct hdac_ext_bus *ebus = pci_get_drvdata(pci); - struct skl *skl = ebus_to_skl(ebus); + struct hdac_bus *bus = pci_get_drvdata(pci); + struct skl *skl = bus_to_skl(bus); release_firmware(skl->tplg); pm_runtime_get_noresume(&pci->dev); /* codec removal, invoke bus_device_remove */ - snd_hdac_ext_bus_device_remove(ebus); + snd_hdac_ext_bus_device_remove(bus); skl->debugfs = NULL; skl_platform_unregister(&pci->dev); @@ -1022,7 +1002,7 @@ static void skl_remove(struct pci_dev *pci) skl_clock_device_unregister(skl); skl_nhlt_remove_sysfs(skl); skl_nhlt_free(skl->nhlt); - skl_free(ebus); + skl_free(bus); dev_set_drvdata(&pci->dev, NULL); } diff --git a/sound/soc/intel/skylake/skl.h b/sound/soc/intel/skylake/skl.h index 0d5375cbcf6e..78aa8bdcb619 100644 --- a/sound/soc/intel/skylake/skl.h +++ b/sound/soc/intel/skylake/skl.h @@ -71,7 +71,7 @@ struct skl_fw_config { }; struct skl { - struct hdac_ext_bus ebus; + struct hdac_bus hbus; struct pci_dev *pci; unsigned int init_done:1; /* delayed init status */ @@ -105,9 +105,8 @@ struct skl { struct snd_soc_acpi_mach *mach; }; -#define skl_to_ebus(s) (&(s)->ebus) -#define ebus_to_skl(sbus) \ - container_of(sbus, struct skl, sbus) +#define skl_to_bus(s) (&(s)->hbus) +#define bus_to_skl(bus) container_of(bus, struct skl, hbus) /* to pass dai dma data */ struct skl_dma_params { -- cgit v1.2.3 From e1df9317cbb192582ed7aa88c5f294c2336a3c75 Mon Sep 17 00:00:00 2001 From: Rakesh Ughreja Date: Fri, 1 Jun 2018 22:53:51 -0500 Subject: ALSA: hdac: Remove usage of struct hdac_ext_driver, use hdac_driver instead This patch removes the hdac_ext_driver structure. The legacy and enhanced HDaudio capabilities can be handled in a backward-compatible way without separate definitions. Signed-off-by: Rakesh Ughreja Signed-off-by: Takashi Iwai --- include/sound/hdaudio.h | 5 +++++ include/sound/hdaudio_ext.h | 17 ++--------------- sound/hda/ext/hdac_ext_bus.c | 30 ++++++++++++++---------------- sound/soc/codecs/hdac_hdmi.c | 12 +++++------- 4 files changed, 26 insertions(+), 38 deletions(-) (limited to 'sound') diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h index 9735b51aef08..59ffe63cf194 100644 --- a/include/sound/hdaudio.h +++ b/include/sound/hdaudio.h @@ -188,6 +188,11 @@ struct hdac_driver { const struct hda_device_id *id_table; int (*match)(struct hdac_device *dev, struct hdac_driver *drv); void (*unsol_event)(struct hdac_device *dev, unsigned int event); + + /* fields used by ext bus APIs */ + int (*probe)(struct hdac_device *dev); + int (*remove)(struct hdac_device *dev); + void (*shutdown)(struct hdac_device *dev); }; #define drv_to_hdac_driver(_drv) container_of(_drv, struct hdac_driver, driver) diff --git a/include/sound/hdaudio_ext.h b/include/sound/hdaudio_ext.h index e5b0cd1ade19..3c302477750b 100644 --- a/include/sound/hdaudio_ext.h +++ b/include/sound/hdaudio_ext.h @@ -160,20 +160,7 @@ struct hdac_ext_dma_params { u8 stream_tag; }; -/* - * HD-audio codec base driver - */ -struct hdac_ext_driver { - struct hdac_driver hdac; - - int (*probe)(struct hdac_device *dev); - int (*remove)(struct hdac_device *dev); - void (*shutdown)(struct hdac_device *dev); -}; - -int snd_hda_ext_driver_register(struct hdac_ext_driver *drv); -void snd_hda_ext_driver_unregister(struct hdac_ext_driver *drv); - -#define to_ehdac_driver(_drv) container_of(_drv, struct hdac_ext_driver, hdac) +int snd_hda_ext_driver_register(struct hdac_driver *drv); +void snd_hda_ext_driver_unregister(struct hdac_driver *drv); #endif /* __SOUND_HDAUDIO_EXT_H */ diff --git a/sound/hda/ext/hdac_ext_bus.c b/sound/hda/ext/hdac_ext_bus.c index 77547ede9ae8..52f07766fff3 100644 --- a/sound/hda/ext/hdac_ext_bus.c +++ b/sound/hda/ext/hdac_ext_bus.c @@ -200,12 +200,10 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_device_remove); #define dev_to_hdac(dev) (container_of((dev), \ struct hdac_device, dev)) -static inline struct hdac_ext_driver *get_edrv(struct device *dev) +static inline struct hdac_driver *get_hdrv(struct device *dev) { struct hdac_driver *hdrv = drv_to_hdac_driver(dev->driver); - struct hdac_ext_driver *edrv = to_ehdac_driver(hdrv); - - return edrv; + return hdrv; } static inline struct hdac_device *get_hdev(struct device *dev) @@ -216,17 +214,17 @@ static inline struct hdac_device *get_hdev(struct device *dev) static int hda_ext_drv_probe(struct device *dev) { - return (get_edrv(dev))->probe(get_hdev(dev)); + return (get_hdrv(dev))->probe(get_hdev(dev)); } static int hdac_ext_drv_remove(struct device *dev) { - return (get_edrv(dev))->remove(get_hdev(dev)); + return (get_hdrv(dev))->remove(get_hdev(dev)); } static void hdac_ext_drv_shutdown(struct device *dev) { - return (get_edrv(dev))->shutdown(get_hdev(dev)); + return (get_hdrv(dev))->shutdown(get_hdev(dev)); } /** @@ -234,20 +232,20 @@ static void hdac_ext_drv_shutdown(struct device *dev) * * @drv: ext hda driver structure */ -int snd_hda_ext_driver_register(struct hdac_ext_driver *drv) +int snd_hda_ext_driver_register(struct hdac_driver *drv) { - drv->hdac.type = HDA_DEV_ASOC; - drv->hdac.driver.bus = &snd_hda_bus_type; + drv->type = HDA_DEV_ASOC; + drv->driver.bus = &snd_hda_bus_type; /* we use default match */ if (drv->probe) - drv->hdac.driver.probe = hda_ext_drv_probe; + drv->driver.probe = hda_ext_drv_probe; if (drv->remove) - drv->hdac.driver.remove = hdac_ext_drv_remove; + drv->driver.remove = hdac_ext_drv_remove; if (drv->shutdown) - drv->hdac.driver.shutdown = hdac_ext_drv_shutdown; + drv->driver.shutdown = hdac_ext_drv_shutdown; - return driver_register(&drv->hdac.driver); + return driver_register(&drv->driver); } EXPORT_SYMBOL_GPL(snd_hda_ext_driver_register); @@ -256,8 +254,8 @@ EXPORT_SYMBOL_GPL(snd_hda_ext_driver_register); * * @drv: ext hda driver structure */ -void snd_hda_ext_driver_unregister(struct hdac_ext_driver *drv) +void snd_hda_ext_driver_unregister(struct hdac_driver *drv) { - driver_unregister(&drv->hdac.driver); + driver_unregister(&drv->driver); } EXPORT_SYMBOL_GPL(snd_hda_ext_driver_unregister); diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index c3ccc8d9c91d..3e3a2a9ef310 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c @@ -2186,14 +2186,12 @@ static const struct hda_device_id hdmi_list[] = { MODULE_DEVICE_TABLE(hdaudio, hdmi_list); -static struct hdac_ext_driver hdmi_driver = { - . hdac = { - .driver = { - .name = "HDMI HDA Codec", - .pm = &hdac_hdmi_pm, - }, - .id_table = hdmi_list, +static struct hdac_driver hdmi_driver = { + .driver = { + .name = "HDMI HDA Codec", + .pm = &hdac_hdmi_pm, }, + .id_table = hdmi_list, .probe = hdac_hdmi_dev_probe, .remove = hdac_hdmi_dev_remove, }; -- cgit v1.2.3 From f8a7fe1aea215e25eaf3bf04dff66fc7621ec9d7 Mon Sep 17 00:00:00 2001 From: Rakesh Ughreja Date: Fri, 1 Jun 2018 22:54:00 -0500 Subject: ALSA: hdac: ext: add wait for codec to respond after link reset As per HDA spec section 4.3 - Codec Discovery, the software shall wait for atleast 521usec for codec to respond after link reset. With the multi-link capability each link is turned ON/OFF individually. Link controller drives reset signal when it is turned ON. Signed-off-by: Rakesh Ughreja Signed-off-by: Pierre-Louis Bossart Signed-off-by: Takashi Iwai --- sound/hda/ext/hdac_ext_controller.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'sound') diff --git a/sound/hda/ext/hdac_ext_controller.c b/sound/hda/ext/hdac_ext_controller.c index 72774119dd11..5bc4a1d587d4 100644 --- a/sound/hda/ext/hdac_ext_controller.c +++ b/sound/hda/ext/hdac_ext_controller.c @@ -271,6 +271,15 @@ int snd_hdac_ext_bus_link_get(struct hdac_bus *bus, } ret = snd_hdac_ext_bus_link_power_up(link); + + /* + * wait for 521usec for codec to report status + * HDA spec section 4.3 - Codec Discovery + */ + udelay(521); + bus->codec_mask = snd_hdac_chip_readw(bus, STATESTS); + dev_dbg(bus->dev, "codec_mask = 0x%lx\n", bus->codec_mask); + snd_hdac_chip_writew(bus, STATESTS, bus->codec_mask); } mutex_unlock(&bus->lock); -- cgit v1.2.3 From 24494d3f939774c3c21d78b5e95d37f9e74d154c Mon Sep 17 00:00:00 2001 From: Rakesh Ughreja Date: Fri, 1 Jun 2018 22:53:56 -0500 Subject: ALSA: hda: split snd_hda_codec_new function Split snd_hda_codec_new into two separate functions. snd_hda_codec_device_init allocates memory and registers with bus. snd_hda_codec_device_new initialializes the fields and performs snd_device_new. This enables reuse of legacy HDA codec drivers as ASoC codec drivers. In addition mark some functions with EXPORT_SYMBOL_GPL so that it can be called by ASoC wrapper around the legacy HDA driver (hdac_hda). Signed-off-by: Rakesh Ughreja Signed-off-by: Pierre-Louis Bossart Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 68 +++++++++++++++++++++++++++++++++++------------ sound/pci/hda/hda_codec.h | 2 ++ 2 files changed, 53 insertions(+), 17 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index d91c87e41756..059cfade05cc 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -858,6 +858,39 @@ static void snd_hda_codec_dev_release(struct device *dev) kfree(codec); } +#define DEV_NAME_LEN 31 + +static int snd_hda_codec_device_init(struct hda_bus *bus, struct snd_card *card, + unsigned int codec_addr, struct hda_codec **codecp) +{ + char name[DEV_NAME_LEN]; + struct hda_codec *codec; + int err; + + dev_dbg(card->dev, "%s: entry\n", __func__); + + if (snd_BUG_ON(!bus)) + return -EINVAL; + if (snd_BUG_ON(codec_addr > HDA_MAX_CODEC_ADDRESS)) + return -EINVAL; + + codec = kzalloc(sizeof(*codec), GFP_KERNEL); + if (!codec) + return -ENOMEM; + + sprintf(name, "hdaudioC%dD%d", card->number, codec_addr); + err = snd_hdac_device_init(&codec->core, &bus->core, name, codec_addr); + if (err < 0) { + kfree(codec); + return err; + } + + codec->core.type = HDA_DEV_LEGACY; + *codecp = codec; + + return err; +} + /** * snd_hda_codec_new - create a HDA codec * @bus: the bus to assign @@ -869,7 +902,19 @@ static void snd_hda_codec_dev_release(struct device *dev) int snd_hda_codec_new(struct hda_bus *bus, struct snd_card *card, unsigned int codec_addr, struct hda_codec **codecp) { - struct hda_codec *codec; + int ret; + + ret = snd_hda_codec_device_init(bus, card, codec_addr, codecp); + if (ret < 0) + return ret; + + return snd_hda_codec_device_new(bus, card, codec_addr, *codecp); +} +EXPORT_SYMBOL_GPL(snd_hda_codec_new); + +int snd_hda_codec_device_new(struct hda_bus *bus, struct snd_card *card, + unsigned int codec_addr, struct hda_codec *codec) +{ char component[31]; hda_nid_t fg; int err; @@ -879,25 +924,14 @@ int snd_hda_codec_new(struct hda_bus *bus, struct snd_card *card, .dev_free = snd_hda_codec_dev_free, }; + dev_dbg(card->dev, "%s: entry\n", __func__); + if (snd_BUG_ON(!bus)) return -EINVAL; if (snd_BUG_ON(codec_addr > HDA_MAX_CODEC_ADDRESS)) return -EINVAL; - codec = kzalloc(sizeof(*codec), GFP_KERNEL); - if (!codec) - return -ENOMEM; - - sprintf(component, "hdaudioC%dD%d", card->number, codec_addr); - err = snd_hdac_device_init(&codec->core, &bus->core, component, - codec_addr); - if (err < 0) { - kfree(codec); - return err; - } - codec->core.dev.release = snd_hda_codec_dev_release; - codec->core.type = HDA_DEV_LEGACY; codec->core.exec_verb = codec_exec_verb; codec->bus = bus; @@ -957,15 +991,13 @@ int snd_hda_codec_new(struct hda_bus *bus, struct snd_card *card, if (err < 0) goto error; - if (codecp) - *codecp = codec; return 0; error: put_device(hda_codec_dev(codec)); return err; } -EXPORT_SYMBOL_GPL(snd_hda_codec_new); +EXPORT_SYMBOL_GPL(snd_hda_codec_device_new); /** * snd_hda_codec_update_widgets - Refresh widget caps and pin defaults @@ -2991,6 +3023,7 @@ int snd_hda_codec_build_controls(struct hda_codec *codec) sync_power_up_states(codec); return 0; } +EXPORT_SYMBOL_GPL(snd_hda_codec_build_controls); /* * PCM stuff @@ -3196,6 +3229,7 @@ int snd_hda_codec_parse_pcms(struct hda_codec *codec) return 0; } +EXPORT_SYMBOL_GPL(snd_hda_codec_parse_pcms); /* assign all PCMs of the given codec */ int snd_hda_codec_build_pcms(struct hda_codec *codec) diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 681c360f29f9..8bbedf7f3f54 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h @@ -307,6 +307,8 @@ struct hda_codec { */ int snd_hda_codec_new(struct hda_bus *bus, struct snd_card *card, unsigned int codec_addr, struct hda_codec **codecp); +int snd_hda_codec_device_new(struct hda_bus *bus, struct snd_card *card, + unsigned int codec_addr, struct hda_codec *codec); int snd_hda_codec_configure(struct hda_codec *codec); int snd_hda_codec_update_widgets(struct hda_codec *codec); -- cgit v1.2.3 From 6298542fa33b6ba0e3effbace5b99b70b93ed9ae Mon Sep 17 00:00:00 2001 From: Rakesh Ughreja Date: Fri, 1 Jun 2018 22:53:57 -0500 Subject: ALSA: hdac: remove memory allocation from snd_hdac_ext_bus_device_init Remove memory allocation within snd_hdac_ext_bus_device_init, to make its behaviour identical to snd_hdac_bus_device_init. So that caller can allocate the parent data structure containing hdac_device. This API change helps in reusing the legacy HDA codec drivers with ASoC platform drivers. Signed-off-by: Rakesh Ughreja Signed-off-by: Pierre-Louis Bossart Signed-off-by: Takashi Iwai --- include/sound/hdaudio_ext.h | 3 ++- sound/hda/ext/hdac_ext_bus.c | 8 ++------ sound/soc/intel/skylake/skl.c | 8 +++++++- 3 files changed, 11 insertions(+), 8 deletions(-) (limited to 'sound') diff --git a/include/sound/hdaudio_ext.h b/include/sound/hdaudio_ext.h index 3c302477750b..c188b801239f 100644 --- a/include/sound/hdaudio_ext.h +++ b/include/sound/hdaudio_ext.h @@ -9,7 +9,8 @@ int snd_hdac_ext_bus_init(struct hdac_bus *bus, struct device *dev, const struct hdac_io_ops *io_ops); void snd_hdac_ext_bus_exit(struct hdac_bus *bus); -int snd_hdac_ext_bus_device_init(struct hdac_bus *bus, int addr); +int snd_hdac_ext_bus_device_init(struct hdac_bus *bus, int addr, + struct hdac_device *hdev); void snd_hdac_ext_bus_device_exit(struct hdac_device *hdev); void snd_hdac_ext_bus_device_remove(struct hdac_bus *bus); diff --git a/sound/hda/ext/hdac_ext_bus.c b/sound/hda/ext/hdac_ext_bus.c index 52f07766fff3..1eb58244688e 100644 --- a/sound/hda/ext/hdac_ext_bus.c +++ b/sound/hda/ext/hdac_ext_bus.c @@ -135,16 +135,12 @@ static void default_release(struct device *dev) * * Returns zero for success or a negative error code. */ -int snd_hdac_ext_bus_device_init(struct hdac_bus *bus, int addr) +int snd_hdac_ext_bus_device_init(struct hdac_bus *bus, int addr, + struct hdac_device *hdev) { - struct hdac_device *hdev = NULL; char name[15]; int ret; - hdev = kzalloc(sizeof(*hdev), GFP_KERNEL); - if (!hdev) - return -ENOMEM; - hdev->bus = bus; snprintf(name, sizeof(name), "ehdaudio%dD%d", bus->idx, addr); diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c index 9c5a701d68ac..3a7f5eb4902b 100644 --- a/sound/soc/intel/skylake/skl.c +++ b/sound/soc/intel/skylake/skl.c @@ -635,6 +635,8 @@ static int probe_codec(struct hdac_bus *bus, int addr) unsigned int cmd = (addr << 28) | (AC_NODE_ROOT << 20) | (AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID; unsigned int res = -1; + struct skl *skl = bus_to_skl(bus); + struct hdac_device *hdev; mutex_lock(&bus->cmd_mutex); snd_hdac_bus_send_cmd(bus, cmd); @@ -644,7 +646,11 @@ static int probe_codec(struct hdac_bus *bus, int addr) return -EIO; dev_dbg(bus->dev, "codec #%d probed OK\n", addr); - return snd_hdac_ext_bus_device_init(bus, addr); + hdev = devm_kzalloc(&skl->pci->dev, sizeof(*hdev), GFP_KERNEL); + if (!hdev) + return -ENOMEM; + + return snd_hdac_ext_bus_device_init(bus, addr, hdev); } /* Codec initialization */ -- cgit v1.2.3 From cb04ba33187ca571142b67c2fb60d0a8c24994c8 Mon Sep 17 00:00:00 2001 From: Rakesh Ughreja Date: Fri, 1 Jun 2018 22:53:58 -0500 Subject: ALSA: hdac: add extended ops in the hdac_bus Add extended ops in the hdac_bus to allow calling the ASoC HDAC library ops to reuse the legacy HDA codec drivers with ASoC framework. Extended ops are used by the legacy codec drivers to call into hdac_hda library, in the subsequent patches.. Signed-off-by: Rakesh Ughreja Signed-off-by: Pierre-Louis Bossart Signed-off-by: Takashi Iwai --- include/sound/hdaudio.h | 9 +++++++++ include/sound/hdaudio_ext.h | 3 ++- sound/hda/ext/hdac_ext_bus.c | 4 +++- sound/soc/intel/skylake/skl.c | 2 +- 4 files changed, 15 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h index 59ffe63cf194..f1baaa88e766 100644 --- a/include/sound/hdaudio.h +++ b/include/sound/hdaudio.h @@ -213,6 +213,14 @@ struct hdac_bus_ops { int (*link_power)(struct hdac_bus *bus, bool enable); }; +/* + * ops used for ASoC HDA codec drivers + */ +struct hdac_ext_bus_ops { + int (*hdev_attach)(struct hdac_device *hdev); + int (*hdev_detach)(struct hdac_device *hdev); +}; + /* * Lowlevel I/O operators */ @@ -265,6 +273,7 @@ struct hdac_bus { struct device *dev; const struct hdac_bus_ops *ops; const struct hdac_io_ops *io_ops; + const struct hdac_ext_bus_ops *ext_ops; /* h/w resources */ unsigned long addr; diff --git a/include/sound/hdaudio_ext.h b/include/sound/hdaudio_ext.h index c188b801239f..f34aced69ca8 100644 --- a/include/sound/hdaudio_ext.h +++ b/include/sound/hdaudio_ext.h @@ -6,7 +6,8 @@ int snd_hdac_ext_bus_init(struct hdac_bus *bus, struct device *dev, const struct hdac_bus_ops *ops, - const struct hdac_io_ops *io_ops); + const struct hdac_io_ops *io_ops, + const struct hdac_ext_bus_ops *ext_ops); void snd_hdac_ext_bus_exit(struct hdac_bus *bus); int snd_hdac_ext_bus_device_init(struct hdac_bus *bus, int addr, diff --git a/sound/hda/ext/hdac_ext_bus.c b/sound/hda/ext/hdac_ext_bus.c index 1eb58244688e..9c37d9af3023 100644 --- a/sound/hda/ext/hdac_ext_bus.c +++ b/sound/hda/ext/hdac_ext_bus.c @@ -89,7 +89,8 @@ static const struct hdac_io_ops hdac_ext_default_io = { */ int snd_hdac_ext_bus_init(struct hdac_bus *bus, struct device *dev, const struct hdac_bus_ops *ops, - const struct hdac_io_ops *io_ops) + const struct hdac_io_ops *io_ops, + const struct hdac_ext_bus_ops *ext_ops) { int ret; static int idx; @@ -102,6 +103,7 @@ int snd_hdac_ext_bus_init(struct hdac_bus *bus, struct device *dev, if (ret < 0) return ret; + bus->ext_ops = ext_ops; INIT_LIST_HEAD(&bus->hlink_list); bus->idx = idx++; diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c index 3a7f5eb4902b..00e051467a40 100644 --- a/sound/soc/intel/skylake/skl.c +++ b/sound/soc/intel/skylake/skl.c @@ -803,7 +803,7 @@ static int skl_create(struct pci_dev *pci, } bus = skl_to_bus(skl); - snd_hdac_ext_bus_init(bus, &pci->dev, &bus_core_ops, io_ops); + snd_hdac_ext_bus_init(bus, &pci->dev, &bus_core_ops, io_ops, NULL); bus->use_posbuf = 1; skl->pci = pci; INIT_WORK(&skl->probe_work, skl_probe_work); -- cgit v1.2.3 From 1adca4b0cd65c14cb8b8c9c257720385869c3d5f Mon Sep 17 00:00:00 2001 From: Kai-Heng Feng Date: Thu, 28 Jun 2018 15:28:24 +0800 Subject: ALSA: hda: Add AZX_DCAPS_PM_RUNTIME for AMD Raven Ridge This patch can make audio controller in AMD Raven Ridge gets runtime suspended to D3, to save ~1W power when it's not in use. Cc: Vijendar Mukunda Signed-off-by: Kai-Heng Feng Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_intel.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 1ae1850b3bfd..a9b55d65f2bd 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2535,7 +2535,8 @@ static const struct pci_device_id azx_ids[] = { .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_SB }, /* AMD Raven */ { PCI_DEVICE(0x1022, 0x15e3), - .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_SB }, + .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_SB | + AZX_DCAPS_PM_RUNTIME }, /* ATI HDMI */ { PCI_DEVICE(0x1002, 0x0002), .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS }, -- cgit v1.2.3 From fdd49c510021d389bf5979282193e084f328e031 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 27 Jun 2018 09:54:46 +0200 Subject: ALSA: hda/hdmi - Don't fall back to generic when i915 binding fails When i915 component binding fails, it means that HDMI isn't applicable anyway. Although the probe with the generic HDMI parser would still work, it's essentially useless, hence better to be left unbound. This patch mimics the probe_id field at failing the i915 component binding so that the generic HDMI won't be bound after that. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.h | 1 + sound/pci/hda/patch_hdmi.c | 2 ++ 2 files changed, 3 insertions(+) (limited to 'sound') diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 8a095c16ee65..993294c8fd0a 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h @@ -84,6 +84,7 @@ struct hda_bus { */ typedef int (*hda_codec_patch_t)(struct hda_codec *); +#define HDA_CODEC_ID_SKIP_PROBE 0x00000001 #define HDA_CODEC_ID_GENERIC_HDMI 0x00000101 #define HDA_CODEC_ID_GENERIC 0x00000201 diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index ed2318f79e3c..cbf5f4e30027 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -2542,6 +2542,8 @@ static int alloc_intel_hdmi(struct hda_codec *codec) /* requires i915 binding */ if (!codec->bus->core.audio_component) { codec_info(codec, "No i915 binding for Intel HDMI/DP codec\n"); + /* set probe_id here to prevent generic fallback binding */ + codec->probe_id = HDA_CODEC_ID_SKIP_PROBE; return -ENODEV; } -- cgit v1.2.3 From 222bce5eb88d1af656419db04bcd84b2419fb900 Mon Sep 17 00:00:00 2001 From: Nicholas Mc Guire Date: Fri, 29 Jun 2018 19:07:42 +0200 Subject: ALSA: snd-aoa: add of_node_put() in error path Both calls to of_find_node_by_name() and of_get_next_child() return a node pointer with refcount incremented thus it must be explicidly decremented here after the last usage. As we are assured to have a refcounted np either from the initial of_find_node_by_name(NULL, name); or from the of_get_next_child(gpio, np) in the while loop if we reached the error code path below, an x of_node_put(np) is needed. Signed-off-by: Nicholas Mc Guire Fixes: commit f3d9478b2ce4 ("[ALSA] snd-aoa: add snd-aoa") Signed-off-by: Takashi Iwai --- sound/aoa/core/gpio-feature.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/aoa/core/gpio-feature.c b/sound/aoa/core/gpio-feature.c index 71960089e207..65557421fe0b 100644 --- a/sound/aoa/core/gpio-feature.c +++ b/sound/aoa/core/gpio-feature.c @@ -88,8 +88,10 @@ static struct device_node *get_gpio(char *name, } reg = of_get_property(np, "reg", NULL); - if (!reg) + if (!reg) { + of_node_put(np); return NULL; + } *gpioptr = *reg; -- cgit v1.2.3 From 9b11233d8e2ca80afc6e16200b680c5daf051333 Mon Sep 17 00:00:00 2001 From: John Ogness Date: Sun, 1 Jul 2018 17:28:07 +0200 Subject: ALSA: usb: caiaq: audio: use irqsave() in USB's complete callback The USB completion callback does not disable interrupts while acquiring the lock. We want to remove the local_irq_disable() invocation from __usb_hcd_giveback_urb() and therefore it is required for the callback handler to disable the interrupts while acquiring the lock. The callback may be invoked either in IRQ or BH context depending on the USB host controller. Use the _irqsave() variant of the locking primitives. Signed-off-by: John Ogness Signed-off-by: Sebastian Andrzej Siewior Acked-by: Daniel Mack Signed-off-by: Takashi Iwai --- sound/usb/caiaq/audio.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/usb/caiaq/audio.c b/sound/usb/caiaq/audio.c index f35d29f49ffe..15344d39a6cd 100644 --- a/sound/usb/caiaq/audio.c +++ b/sound/usb/caiaq/audio.c @@ -636,6 +636,7 @@ static void read_completed(struct urb *urb) struct device *dev; struct urb *out = NULL; int i, frame, len, send_it = 0, outframe = 0; + unsigned long flags; size_t offset = 0; if (urb->status || !info) @@ -672,10 +673,10 @@ static void read_completed(struct urb *urb) offset += len; if (len > 0) { - spin_lock(&cdev->spinlock); + spin_lock_irqsave(&cdev->spinlock, flags); fill_out_urb(cdev, out, &out->iso_frame_desc[outframe]); read_in_urb(cdev, urb, &urb->iso_frame_desc[frame]); - spin_unlock(&cdev->spinlock); + spin_unlock_irqrestore(&cdev->spinlock, flags); check_for_elapsed_periods(cdev, cdev->sub_playback); check_for_elapsed_periods(cdev, cdev->sub_capture); send_it = 1; -- cgit v1.2.3 From 1259d239799bf9c898091d92adc4317f2c3d74ad Mon Sep 17 00:00:00 2001 From: John Ogness Date: Sun, 1 Jul 2018 17:28:08 +0200 Subject: ALSA: usb-midi: use irqsave() in USB's complete callback The USB completion callback does not disable interrupts while acquiring the lock. We want to remove the local_irq_disable() invocation from __usb_hcd_giveback_urb() and therefore it is required for the callback handler to disable the interrupts while acquiring the lock. The callback may be invoked either in IRQ or BH context depending on the USB host controller. Use the _irqsave() variant of the locking primitives. Signed-off-by: John Ogness Signed-off-by: Sebastian Andrzej Siewior Acked-by: Clemens Ladisch Signed-off-by: Takashi Iwai --- sound/usb/midi.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/usb/midi.c b/sound/usb/midi.c index 2c1aaa3292bf..dcfc546d81b9 100644 --- a/sound/usb/midi.c +++ b/sound/usb/midi.c @@ -281,15 +281,16 @@ static void snd_usbmidi_out_urb_complete(struct urb *urb) struct out_urb_context *context = urb->context; struct snd_usb_midi_out_endpoint *ep = context->ep; unsigned int urb_index; + unsigned long flags; - spin_lock(&ep->buffer_lock); + spin_lock_irqsave(&ep->buffer_lock, flags); urb_index = context - ep->urbs; ep->active_urbs &= ~(1 << urb_index); if (unlikely(ep->drain_urbs)) { ep->drain_urbs &= ~(1 << urb_index); wake_up(&ep->drain_wait); } - spin_unlock(&ep->buffer_lock); + spin_unlock_irqrestore(&ep->buffer_lock, flags); if (urb->status < 0) { int err = snd_usbmidi_urb_error(urb); if (err < 0) { -- cgit v1.2.3 From 9cd641ed31f576d08f7b784850ba93eef050f32f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 4 Jul 2018 14:46:27 +0200 Subject: ALSA: pcm: trace XRUN event at injection, too The PCM xrun injection triggers directly snd_pcm_stop() without the standard xrun handler, hence it's not recorded on the event buffer. Ditto for snd_pcm_stop_xrun() call and SNDRV_PCM_IOCTL_XRUN ioctl. They are inconvenient from the debugging POV. Let's make them to trigger XRUN via the standard helper more consistently. Signed-off-by: Takashi Iwai --- sound/core/pcm.c | 2 +- sound/core/pcm_lib.c | 7 ++++--- sound/core/pcm_local.h | 2 ++ sound/core/pcm_native.c | 8 ++++---- 4 files changed, 11 insertions(+), 8 deletions(-) (limited to 'sound') diff --git a/sound/core/pcm.c b/sound/core/pcm.c index c352bfb973cc..6f037a4b8b52 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -497,7 +497,7 @@ static void snd_pcm_xrun_injection_write(struct snd_info_entry *entry, snd_pcm_stream_lock_irq(substream); runtime = substream->runtime; if (runtime && runtime->status->state == SNDRV_PCM_STATE_RUNNING) - snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); + __snd_pcm_xrun(substream); snd_pcm_stream_unlock_irq(substream); } diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 44b5ae833082..c1d2e8e1fc6b 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -153,7 +153,8 @@ EXPORT_SYMBOL(snd_pcm_debug_name); dump_stack(); \ } while (0) -static void xrun(struct snd_pcm_substream *substream) +/* call with stream lock held */ +void __snd_pcm_xrun(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; @@ -201,7 +202,7 @@ int snd_pcm_update_state(struct snd_pcm_substream *substream, } } else { if (avail >= runtime->stop_threshold) { - xrun(substream); + __snd_pcm_xrun(substream); return -EPIPE; } } @@ -297,7 +298,7 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, } if (pos == SNDRV_PCM_POS_XRUN) { - xrun(substream); + __snd_pcm_xrun(substream); return -EPIPE; } if (pos >= runtime->buffer_size) { diff --git a/sound/core/pcm_local.h b/sound/core/pcm_local.h index 7a499d02df6c..c515612969a4 100644 --- a/sound/core/pcm_local.h +++ b/sound/core/pcm_local.h @@ -65,4 +65,6 @@ static inline void snd_pcm_timer_init(struct snd_pcm_substream *substream) {} static inline void snd_pcm_timer_done(struct snd_pcm_substream *substream) {} #endif +void __snd_pcm_xrun(struct snd_pcm_substream *substream); + #endif /* __SOUND_CORE_PCM_LOCAL_H */ diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index cecc79772c94..20174d0c0527 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -1337,13 +1337,12 @@ int snd_pcm_drain_done(struct snd_pcm_substream *substream) int snd_pcm_stop_xrun(struct snd_pcm_substream *substream) { unsigned long flags; - int ret = 0; snd_pcm_stream_lock_irqsave(substream, flags); if (snd_pcm_running(substream)) - ret = snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); + __snd_pcm_xrun(substream); snd_pcm_stream_unlock_irqrestore(substream, flags); - return ret; + return 0; } EXPORT_SYMBOL_GPL(snd_pcm_stop_xrun); @@ -1591,7 +1590,8 @@ static int snd_pcm_xrun(struct snd_pcm_substream *substream) result = 0; /* already there */ break; case SNDRV_PCM_STATE_RUNNING: - result = snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); + __snd_pcm_xrun(substream); + result = 0; break; default: result = -EBADFD; -- cgit v1.2.3 From e647f5a5c5d165c87750e8c0dcbe341b5a378ffd Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 4 Jul 2018 15:08:05 +0200 Subject: ALSA: pcm: Use snd_pcm_stop_xrun() for xrun injection Basically the xrun injection routine can simply call the standard helper snd_pcm_stop_xrun(), but with one exception: it may be called even when the stream is closed. Make snd_pcm_stop_xrun() more robust and check the NULL runtime state, and simplify xrun injection code by calling it. Signed-off-by: Takashi Iwai --- sound/core/pcm.c | 7 +------ sound/core/pcm_native.c | 2 +- 2 files changed, 2 insertions(+), 7 deletions(-) (limited to 'sound') diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 6f037a4b8b52..fdb9b92fc8d6 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -492,13 +492,8 @@ static void snd_pcm_xrun_injection_write(struct snd_info_entry *entry, struct snd_info_buffer *buffer) { struct snd_pcm_substream *substream = entry->private_data; - struct snd_pcm_runtime *runtime; - snd_pcm_stream_lock_irq(substream); - runtime = substream->runtime; - if (runtime && runtime->status->state == SNDRV_PCM_STATE_RUNNING) - __snd_pcm_xrun(substream); - snd_pcm_stream_unlock_irq(substream); + snd_pcm_stop_xrun(substream); } static void snd_pcm_xrun_debug_read(struct snd_info_entry *entry, diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 20174d0c0527..66c90f486af9 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -1339,7 +1339,7 @@ int snd_pcm_stop_xrun(struct snd_pcm_substream *substream) unsigned long flags; snd_pcm_stream_lock_irqsave(substream, flags); - if (snd_pcm_running(substream)) + if (substream->runtime && snd_pcm_running(substream)) __snd_pcm_xrun(substream); snd_pcm_stream_unlock_irqrestore(substream, flags); return 0; -- cgit v1.2.3 From d64c5cf8e89d124355924c513a42b16f0d7d3a03 Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Fri, 6 Jul 2018 13:50:36 +0100 Subject: ALSA: pcm: Allow drivers to set R/W wait time. Currently ALSA core blocks userspace for about 10 seconds for PCM R/W IO. This needs to be configurable for modern hardware like DSPs where no pointer update in milliseconds can indicate terminal DSP errors. Add a substream variable to set the wait time in ms. This allows userspace and drivers to recover more quickly from terminal DSP errors. Signed-off-by: Liam Girdwood Signed-off-by: Takashi Iwai --- include/sound/pcm.h | 1 + sound/core/pcm_lib.c | 17 ++++++++++++----- 2 files changed, 13 insertions(+), 5 deletions(-) (limited to 'sound') diff --git a/include/sound/pcm.h b/include/sound/pcm.h index e054c583d3b3..fcdf358a25f0 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -462,6 +462,7 @@ struct snd_pcm_substream { /* -- timer section -- */ struct snd_timer *timer; /* timer */ unsigned timer_running: 1; /* time is running */ + long wait_time; /* time in ms for R/W to wait for avail */ /* -- next substream -- */ struct snd_pcm_substream *next; /* -- linked substreams -- */ diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index c1d2e8e1fc6b..5736860f325b 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -1833,12 +1833,19 @@ static int wait_for_avail(struct snd_pcm_substream *substream, if (runtime->no_period_wakeup) wait_time = MAX_SCHEDULE_TIMEOUT; else { - wait_time = 10; - if (runtime->rate) { - long t = runtime->period_size * 2 / runtime->rate; - wait_time = max(t, wait_time); + /* use wait time from substream if available */ + if (substream->wait_time) { + wait_time = substream->wait_time; + } else { + wait_time = 10; + + if (runtime->rate) { + long t = runtime->period_size * 2 / + runtime->rate; + wait_time = max(t, wait_time); + } + wait_time = msecs_to_jiffies(wait_time * 1000); } - wait_time = msecs_to_jiffies(wait_time * 1000); } for (;;) { -- cgit v1.2.3 From ff2d6acdf6f13d9f8fdcd890844c6d7535ac1f10 Mon Sep 17 00:00:00 2001 From: Timo Wischer Date: Tue, 10 Jul 2018 17:28:45 +0200 Subject: ALSA: pcm: Fix snd_interval_refine first/last with open min/max Without this commit the following intervals [x y), (x y) were be replaced to (y-1 y) by snd_interval_refine_last(). This was also done if y-1 is part of the previous interval. With this changes it will be replaced with [y-1 y) in case of y-1 is part of the previous interval. A similar behavior will be used for snd_interval_refine_first(). This commit adapts the changes for alsa-lib of commit 9bb985c ("pcm: snd_interval_refine_first/last: exclude value only if also excluded before") Signed-off-by: Timo Wischer Signed-off-by: Takashi Iwai --- sound/core/pcm_lib.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 5736860f325b..4e6110d778bd 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -627,27 +627,33 @@ EXPORT_SYMBOL(snd_interval_refine); static int snd_interval_refine_first(struct snd_interval *i) { + const unsigned int last_max = i->max; + if (snd_BUG_ON(snd_interval_empty(i))) return -EINVAL; if (snd_interval_single(i)) return 0; i->max = i->min; - i->openmax = i->openmin; - if (i->openmax) + if (i->openmin) i->max++; + /* only exclude max value if also excluded before refine */ + i->openmax = (i->openmax && i->max >= last_max); return 1; } static int snd_interval_refine_last(struct snd_interval *i) { + const unsigned int last_min = i->min; + if (snd_BUG_ON(snd_interval_empty(i))) return -EINVAL; if (snd_interval_single(i)) return 0; i->min = i->max; - i->openmin = i->openmax; - if (i->openmin) + if (i->openmax) i->min--; + /* only exclude min value if also excluded before refine */ + i->openmin = (i->openmin && i->min <= last_min); return 1; } -- cgit v1.2.3 From eeef847de593e2de4ddbf7ae3439c9fc9ebc8e84 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 16 Jul 2018 09:34:51 +0100 Subject: ALSA: opl3: remove redundant pointer opl3 Variable opl3 is being assigned but is never used hence it is redundant and can be removed. Cleans up several clang warnings: warning: variable 'opl3' set but not used [-Wunused-but-set-variable] Signed-off-by: Colin Ian King Signed-off-by: Takashi Iwai --- sound/drivers/opl3/opl3_midi.c | 12 ------------ sound/drivers/opl3/opl3_oss.c | 6 ------ 2 files changed, 18 deletions(-) (limited to 'sound') diff --git a/sound/drivers/opl3/opl3_midi.c b/sound/drivers/opl3/opl3_midi.c index bb3f3a5a6951..71cd5a2fbe82 100644 --- a/sound/drivers/opl3/opl3_midi.c +++ b/sound/drivers/opl3/opl3_midi.c @@ -721,9 +721,6 @@ void snd_opl3_note_off(void *p, int note, int vel, */ void snd_opl3_key_press(void *p, int note, int vel, struct snd_midi_channel *chan) { - struct snd_opl3 *opl3; - - opl3 = p; #ifdef DEBUG_MIDI snd_printk(KERN_DEBUG "Key pressure, ch#: %i, inst#: %i\n", chan->number, chan->midi_program); @@ -735,9 +732,6 @@ void snd_opl3_key_press(void *p, int note, int vel, struct snd_midi_channel *cha */ void snd_opl3_terminate_note(void *p, int note, struct snd_midi_channel *chan) { - struct snd_opl3 *opl3; - - opl3 = p; #ifdef DEBUG_MIDI snd_printk(KERN_DEBUG "Terminate note, ch#: %i, inst#: %i\n", chan->number, chan->midi_program); @@ -861,9 +855,6 @@ void snd_opl3_control(void *p, int type, struct snd_midi_channel *chan) void snd_opl3_nrpn(void *p, struct snd_midi_channel *chan, struct snd_midi_channel_set *chset) { - struct snd_opl3 *opl3; - - opl3 = p; #ifdef DEBUG_MIDI snd_printk(KERN_DEBUG "NRPN, ch#: %i, inst#: %i\n", chan->number, chan->midi_program); @@ -876,9 +867,6 @@ void snd_opl3_nrpn(void *p, struct snd_midi_channel *chan, void snd_opl3_sysex(void *p, unsigned char *buf, int len, int parsed, struct snd_midi_channel_set *chset) { - struct snd_opl3 *opl3; - - opl3 = p; #ifdef DEBUG_MIDI snd_printk(KERN_DEBUG "SYSEX\n"); #endif diff --git a/sound/drivers/opl3/opl3_oss.c b/sound/drivers/opl3/opl3_oss.c index 22c3e4bca220..8a0ce3f43f42 100644 --- a/sound/drivers/opl3/opl3_oss.c +++ b/sound/drivers/opl3/opl3_oss.c @@ -233,11 +233,8 @@ static int snd_opl3_load_patch_seq_oss(struct snd_seq_oss_arg *arg, int format, static int snd_opl3_ioctl_seq_oss(struct snd_seq_oss_arg *arg, unsigned int cmd, unsigned long ioarg) { - struct snd_opl3 *opl3; - if (snd_BUG_ON(!arg)) return -ENXIO; - opl3 = arg->private_data; switch (cmd) { case SNDCTL_FM_LOAD_INSTR: snd_printk(KERN_ERR "OPL3: " @@ -261,11 +258,8 @@ static int snd_opl3_ioctl_seq_oss(struct snd_seq_oss_arg *arg, unsigned int cmd, /* reset device */ static int snd_opl3_reset_seq_oss(struct snd_seq_oss_arg *arg) { - struct snd_opl3 *opl3; - if (snd_BUG_ON(!arg)) return -ENXIO; - opl3 = arg->private_data; return 0; } -- cgit v1.2.3 From a34e8aac49e6d2e3438998edba5f753bd5d5210f Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 16 Jul 2018 09:43:08 +0100 Subject: ALSA: es1688: remove redundant pointer chip Pointer chip is being assigned but is never used hence it is redundant and can be removed. Cleans up clang warning: warning: variable 'chip' set but not used [-Wunused-but-set-variable] Signed-off-by: Colin Ian King Signed-off-by: Takashi Iwai --- sound/isa/es1688/es1688.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'sound') diff --git a/sound/isa/es1688/es1688.c b/sound/isa/es1688/es1688.c index a826c138e7f5..3dfe7e592c25 100644 --- a/sound/isa/es1688/es1688.c +++ b/sound/isa/es1688/es1688.c @@ -260,7 +260,6 @@ static int snd_es968_pnp_detect(struct pnp_card_link *pcard, struct snd_card *card; static unsigned int dev; int error; - struct snd_es1688 *chip; if (snd_es968_pnp_is_probed) return -EBUSY; @@ -276,7 +275,6 @@ static int snd_es968_pnp_detect(struct pnp_card_link *pcard, sizeof(struct snd_es1688), &card); if (error < 0) return error; - chip = card->private_data; error = snd_card_es968_pnp(card, dev, pcard, pid); if (error < 0) { -- cgit v1.2.3 From 29fba9230de237312337fb7372a6ee2d5f2f893c Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 16 Jul 2018 09:49:38 +0100 Subject: ALSA: gus: remove redundant pointer private_data Pointer private_data is being assigned but is never used hence it is redundant and can be removed. Cleans up clang warning: warning: variable 'private_data' set but not used [-Wunused-but-set-variable] Signed-off-by: Colin Ian King Signed-off-by: Takashi Iwai --- sound/isa/gus/gus_reset.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'sound') diff --git a/sound/isa/gus/gus_reset.c b/sound/isa/gus/gus_reset.c index 3d1fed0c2620..59b3f683d49b 100644 --- a/sound/isa/gus/gus_reset.c +++ b/sound/isa/gus/gus_reset.c @@ -292,7 +292,6 @@ void snd_gf1_free_voice(struct snd_gus_card * gus, struct snd_gus_voice *voice) { unsigned long flags; void (*private_free)(struct snd_gus_voice *voice); - void *private_data; if (voice == NULL || !voice->use) return; @@ -300,7 +299,6 @@ void snd_gf1_free_voice(struct snd_gus_card * gus, struct snd_gus_voice *voice) snd_gf1_clear_voices(gus, voice->number, voice->number); spin_lock_irqsave(&gus->voice_alloc, flags); private_free = voice->private_free; - private_data = voice->private_data; voice->private_free = NULL; voice->private_data = NULL; if (voice->pcm) -- cgit v1.2.3 From 7527cd209eb88ed03aeab9f4f9bde0923fd6b5d5 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 16 Jul 2018 09:52:56 +0100 Subject: ALSA: sb8: remove redundant pointer runtime Pointer runtime is being assigned but is never used hence it is redundant and can be removed. Cleans up clang warning: warning: variable 'runtime' set but not used [-Wunused-but-set-variable] Signed-off-by: Colin Ian King Signed-off-by: Takashi Iwai --- sound/isa/sb/sb8_main.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'sound') diff --git a/sound/isa/sb/sb8_main.c b/sound/isa/sb/sb8_main.c index d45df5c54423..80e7dcaa551f 100644 --- a/sound/isa/sb/sb8_main.c +++ b/sound/isa/sb/sb8_main.c @@ -381,7 +381,6 @@ static int snd_sb8_capture_trigger(struct snd_pcm_substream *substream, irqreturn_t snd_sb8dsp_interrupt(struct snd_sb *chip) { struct snd_pcm_substream *substream; - struct snd_pcm_runtime *runtime; snd_sb_ack_8bit(chip); switch (chip->mode) { @@ -391,7 +390,6 @@ irqreturn_t snd_sb8dsp_interrupt(struct snd_sb *chip) /* fallthru */ case SB_MODE_PLAYBACK_8: substream = chip->playback_substream; - runtime = substream->runtime; if (chip->playback_format == SB_DSP_OUTPUT) snd_sb8_playback_trigger(substream, SNDRV_PCM_TRIGGER_START); snd_pcm_period_elapsed(substream); @@ -402,7 +400,6 @@ irqreturn_t snd_sb8dsp_interrupt(struct snd_sb *chip) /* fallthru */ case SB_MODE_CAPTURE_8: substream = chip->capture_substream; - runtime = substream->runtime; if (chip->capture_format == SB_DSP_INPUT) snd_sb8_capture_trigger(substream, SNDRV_PCM_TRIGGER_START); snd_pcm_period_elapsed(substream); -- cgit v1.2.3 From c888443951949530b2eb9075cb24f6db00b8118d Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 16 Jul 2018 09:57:38 +0100 Subject: ALSA: ali5451: remove redundant pointer 'codec' Pointer 'codec' is being assigned but is never used hence it is redundant and can be removed. Cleans up clang warning: warning: variable 'codec' set but not used [-Wunused-but-set-variable] Signed-off-by: Colin Ian King Signed-off-by: Takashi Iwai --- sound/pci/ali5451/ali5451.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c index 39547e32e584..9f569379b77e 100644 --- a/sound/pci/ali5451/ali5451.c +++ b/sound/pci/ali5451/ali5451.c @@ -1484,12 +1484,9 @@ static struct snd_pcm_hardware snd_ali_capture = static void snd_ali_pcm_free_substream(struct snd_pcm_runtime *runtime) { struct snd_ali_voice *pvoice = runtime->private_data; - struct snd_ali *codec; - if (pvoice) { - codec = pvoice->codec; + if (pvoice) snd_ali_free_voice(pvoice->codec, pvoice); - } } static int snd_ali_open(struct snd_pcm_substream *substream, int rec, -- cgit v1.2.3 From d6e08c7eabefc9b027d31d56024810eba76ce113 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 16 Jul 2018 10:03:15 +0100 Subject: ALSA: cs46xx: remove redundant pointer 'ins' Pointer 'ins' is being assigned but is never used hence it is redundant and can be removed. Cleans up clang warning: warning: variable 'ins' set but not used [-Wunused-but-set-variable] Signed-off-by: Colin Ian King Signed-off-by: Takashi Iwai --- sound/pci/cs46xx/dsp_spos_scb_lib.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'sound') diff --git a/sound/pci/cs46xx/dsp_spos_scb_lib.c b/sound/pci/cs46xx/dsp_spos_scb_lib.c index abb01ce66983..8d0a3d357345 100644 --- a/sound/pci/cs46xx/dsp_spos_scb_lib.c +++ b/sound/pci/cs46xx/dsp_spos_scb_lib.c @@ -73,13 +73,10 @@ static void cs46xx_dsp_proc_scb_info_read (struct snd_info_entry *entry, { struct proc_scb_info * scb_info = entry->private_data; struct dsp_scb_descriptor * scb = scb_info->scb_desc; - struct dsp_spos_instance * ins; struct snd_cs46xx *chip = scb_info->chip; int j,col; void __iomem *dst = chip->region.idx[1].remap_addr + DSP_PARAMETER_BYTE_OFFSET; - ins = chip->dsp_spos_instance; - mutex_lock(&chip->spos_mutex); snd_iprintf(buffer,"%04x %s:\n",scb->address,scb->scb_name); -- cgit v1.2.3 From c77e1ef1cdf74dba09edfa706fecc9fddd7bd084 Mon Sep 17 00:00:00 2001 From: Jorge Sanjuan Date: Wed, 11 Jul 2018 13:37:51 +0100 Subject: ALSA: usb-audio: Add support for Selector Units in UAC3 This patch add support for Selector Units and Clock Selector Units defined in the new UAC3 spec. Selector Units play a really important role in the new UAC3 spec as Processing Units do not define an on/off switch control anymore. This forces topology designers to add bypass paths in the topology to enable/dissable the Processing Units. Signed-off-by: Jorge Sanjuan Signed-off-by: Takashi Iwai --- sound/usb/mixer.c | 54 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 44 insertions(+), 10 deletions(-) (limited to 'sound') diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index ca963e94ec03..a51f2320a3dd 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -940,6 +940,19 @@ static int check_input_term(struct mixer_build *state, int id, return 0; } + case UAC3_SELECTOR_UNIT: + case UAC3_CLOCK_SELECTOR: { + struct uac_selector_unit_descriptor *d = p1; + /* call recursively to retrieve the channel info */ + err = check_input_term(state, d->baSourceID[0], term); + if (err < 0) + return err; + term->type = d->bDescriptorSubtype << 16; /* virtual type */ + term->id = id; + term->name = 0; /* TODO: UAC3 Class-specific strings */ + + return 0; + } default: return -ENODEV; } @@ -2509,11 +2522,20 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, cval->res = 1; cval->initialized = 1; - if (state->mixer->protocol == UAC_VERSION_1) + switch (state->mixer->protocol) { + case UAC_VERSION_1: + default: cval->control = 0; - else /* UAC_VERSION_2 */ - cval->control = (desc->bDescriptorSubtype == UAC2_CLOCK_SELECTOR) ? - UAC2_CX_CLOCK_SELECTOR : UAC2_SU_SELECTOR; + break; + case UAC_VERSION_2: + case UAC_VERSION_3: + if (desc->bDescriptorSubtype == UAC2_CLOCK_SELECTOR || + desc->bDescriptorSubtype == UAC3_CLOCK_SELECTOR) + cval->control = UAC2_CX_CLOCK_SELECTOR; + else /* UAC2/3_SELECTOR_UNIT */ + cval->control = UAC2_SU_SELECTOR; + break; + } namelist = kmalloc_array(desc->bNrInPins, sizeof(char *), GFP_KERNEL); if (!namelist) { @@ -2555,12 +2577,22 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name)); if (!len) { /* no mapping ? */ + switch (state->mixer->protocol) { + case UAC_VERSION_1: + case UAC_VERSION_2: + default: /* if iSelector is given, use it */ - nameid = uac_selector_unit_iSelector(desc); - if (nameid) - len = snd_usb_copy_string_desc(state->chip, nameid, - kctl->id.name, - sizeof(kctl->id.name)); + nameid = uac_selector_unit_iSelector(desc); + if (nameid) + len = snd_usb_copy_string_desc(state->chip, + nameid, kctl->id.name, + sizeof(kctl->id.name)); + break; + case UAC_VERSION_3: + /* TODO: Class-Specific strings not yet supported */ + break; + } + /* ... or pick up the terminal name at next */ if (!len) len = get_term_name(state->chip, &state->oterm, @@ -2570,7 +2602,8 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, strlcpy(kctl->id.name, "USB", sizeof(kctl->id.name)); /* and add the proper suffix */ - if (desc->bDescriptorSubtype == UAC2_CLOCK_SELECTOR) + if (desc->bDescriptorSubtype == UAC2_CLOCK_SELECTOR || + desc->bDescriptorSubtype == UAC3_CLOCK_SELECTOR) append_ctl_name(kctl, " Clock Source"); else if ((state->oterm.type & 0xff00) == 0x0100) append_ctl_name(kctl, " Capture Source"); @@ -2641,6 +2674,7 @@ static int parse_audio_unit(struct mixer_build *state, int unitid) return parse_audio_mixer_unit(state, unitid, p1); case UAC3_CLOCK_SOURCE: return parse_clock_source_unit(state, unitid, p1); + case UAC3_SELECTOR_UNIT: case UAC3_CLOCK_SELECTOR: return parse_audio_selector_unit(state, unitid, p1); case UAC3_FEATURE_UNIT: -- cgit v1.2.3 From 4e887af31cedec0d3b24521a5c3c14c3a190422b Mon Sep 17 00:00:00 2001 From: Jorge Sanjuan Date: Wed, 11 Jul 2018 13:37:52 +0100 Subject: ALSA: usb-audio: Processing Unit controls parsing in UAC2 Current support for UAC2 Processing Units does the parsing as one control per bit in the bitmap. However, the UAC2 spec defines the controls as bit pairs where b01 means read-only and b11 means read/write control. This patch fixes that and uses the helper functions for checking controls readability/writability when the control is defined as bit pairs (UAC2 and UAC3). Signed-off-by: Jorge Sanjuan Signed-off-by: Takashi Iwai --- sound/usb/mixer.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index a51f2320a3dd..bfb3484096a6 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -2300,8 +2300,16 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, for (valinfo = info->values; valinfo->control; valinfo++) { __u8 *controls = uac_processing_unit_bmControls(desc, state->mixer->protocol); - if (!(controls[valinfo->control / 8] & (1 << ((valinfo->control % 8) - 1)))) - continue; + if (state->mixer->protocol == UAC_VERSION_1) { + if (!(controls[valinfo->control / 8] & + (1 << ((valinfo->control % 8) - 1)))) + continue; + } else { /* UAC_VERSION_2/3 */ + if (!uac_v2v3_control_is_readable(controls[valinfo->control / 8], + valinfo->control)) + continue; + } + map = find_map(state->map, unitid, valinfo->control); if (check_ignored_ctl(map)) continue; @@ -2313,6 +2321,11 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, cval->val_type = valinfo->val_type; cval->channels = 1; + if (state->mixer->protocol > UAC_VERSION_1 && + !uac_v2v3_control_is_writeable(controls[valinfo->control / 8], + valinfo->control)) + cval->master_readonly = 1; + /* get min/max values */ if (type == UAC_PROCESS_UP_DOWNMIX && cval->control == UAC_UD_MODE_SELECT) { __u8 *control_spec = uac_processing_unit_specific(desc, state->mixer->protocol); -- cgit v1.2.3 From 0f292f023ffcc67ec49d63dcb7fe388711cbb83a Mon Sep 17 00:00:00 2001 From: Jorge Sanjuan Date: Wed, 11 Jul 2018 13:37:53 +0100 Subject: ALSA: usb-audio: Add support for Processing Units in UAC3 This patch adds support for the Processig Units defined in the UAC3 spec. The main difference with the previous specs is the lack of on/off switches in the controls for these units and the addiction of the new Multi Function Processing Unit. The current version of the UAC3 spec doesn't define any useful controls for the new Multi Function Processing Unit so no control will get created once this unit is parsed. Signed-off-by: Jorge Sanjuan Signed-off-by: Takashi Iwai --- include/linux/usb/audio-v3.h | 15 +++++++++++++ include/uapi/linux/usb/audio.h | 49 ++++++++++++++++++++++++++++++++-------- sound/usb/mixer.c | 51 ++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 104 insertions(+), 11 deletions(-) (limited to 'sound') diff --git a/include/linux/usb/audio-v3.h b/include/linux/usb/audio-v3.h index a710e28b5215..334bfa6dfb47 100644 --- a/include/linux/usb/audio-v3.h +++ b/include/linux/usb/audio-v3.h @@ -387,6 +387,12 @@ struct uac3_interrupt_data_msg { #define UAC3_CONNECTORS 0x0f #define UAC3_POWER_DOMAIN 0x10 +/* A.20 PROCESSING UNIT PROCESS TYPES */ +#define UAC3_PROCESS_UNDEFINED 0x00 +#define UAC3_PROCESS_UP_DOWNMIX 0x01 +#define UAC3_PROCESS_STEREO_EXTENDER 0x02 +#define UAC3_PROCESS_MULTI_FUNCTION 0x03 + /* A.22 AUDIO CLASS-SPECIFIC REQUEST CODES */ /* see audio-v2.h for the rest, which is identical to v2 */ #define UAC3_CS_REQ_INTEN 0x04 @@ -406,6 +412,15 @@ struct uac3_interrupt_data_msg { #define UAC3_TE_OVERFLOW 0x04 #define UAC3_TE_LATENCY 0x05 +/* A.23.10 PROCESSING UNITS CONTROL SELECTROS */ + +/* Up/Down Mixer */ +#define UAC3_UD_MODE_SELECT 0x01 + +/* Stereo Extender */ +#define UAC3_EXT_WIDTH_CONTROL 0x01 + + /* BADD predefined Unit/Terminal values */ #define UAC3_BADD_IT_ID1 1 /* Input Terminal ID1: bTerminalID = 1 */ #define UAC3_BADD_FU_ID2 2 /* Feature Unit ID2: bUnitID = 2 */ diff --git a/include/uapi/linux/usb/audio.h b/include/uapi/linux/usb/audio.h index 74e520fb944f..ddc5396800aa 100644 --- a/include/uapi/linux/usb/audio.h +++ b/include/uapi/linux/usb/audio.h @@ -390,33 +390,64 @@ static inline __u8 uac_processing_unit_iChannelNames(struct uac_processing_unit_ static inline __u8 uac_processing_unit_bControlSize(struct uac_processing_unit_descriptor *desc, int protocol) { - return (protocol == UAC_VERSION_1) ? - desc->baSourceID[desc->bNrInPins + 4] : - 2; /* in UAC2, this value is constant */ + switch (protocol) { + case UAC_VERSION_1: + return desc->baSourceID[desc->bNrInPins + 4]; + case UAC_VERSION_2: + return 2; /* in UAC2, this value is constant */ + case UAC_VERSION_3: + return 4; /* in UAC3, this value is constant */ + default: + return 1; + } } static inline __u8 *uac_processing_unit_bmControls(struct uac_processing_unit_descriptor *desc, int protocol) { - return (protocol == UAC_VERSION_1) ? - &desc->baSourceID[desc->bNrInPins + 5] : - &desc->baSourceID[desc->bNrInPins + 6]; + switch (protocol) { + case UAC_VERSION_1: + return &desc->baSourceID[desc->bNrInPins + 5]; + case UAC_VERSION_2: + return &desc->baSourceID[desc->bNrInPins + 6]; + case UAC_VERSION_3: + return &desc->baSourceID[desc->bNrInPins + 2]; + default: + return NULL; + } } static inline __u8 uac_processing_unit_iProcessing(struct uac_processing_unit_descriptor *desc, int protocol) { __u8 control_size = uac_processing_unit_bControlSize(desc, protocol); - return *(uac_processing_unit_bmControls(desc, protocol) - + control_size); + + switch (protocol) { + case UAC_VERSION_1: + case UAC_VERSION_2: + default: + return *(uac_processing_unit_bmControls(desc, protocol) + + control_size); + case UAC_VERSION_3: + return 0; /* UAC3 does not have this field */ + } } static inline __u8 *uac_processing_unit_specific(struct uac_processing_unit_descriptor *desc, int protocol) { __u8 control_size = uac_processing_unit_bControlSize(desc, protocol); - return uac_processing_unit_bmControls(desc, protocol) + + switch (protocol) { + case UAC_VERSION_1: + case UAC_VERSION_2: + default: + return uac_processing_unit_bmControls(desc, protocol) + control_size + 1; + case UAC_VERSION_3: + return uac_processing_unit_bmControls(desc, protocol) + + control_size; + } } /* 4.5.2 Class-Specific AS Interface Descriptor */ diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index bfb3484096a6..39fde49e8749 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -953,6 +953,23 @@ static int check_input_term(struct mixer_build *state, int id, return 0; } + case UAC3_PROCESSING_UNIT: { + struct uac_processing_unit_descriptor *d = p1; + + if (!d->bNrInPins) + return -EINVAL; + + /* call recursively to retrieve the channel info */ + err = check_input_term(state, d->baSourceID[0], term); + if (err < 0) + return err; + + term->type = d->bDescriptorSubtype << 16; /* virtual type */ + term->id = id; + term->name = 0; /* TODO: UAC3 Class-specific strings */ + + return 0; + } default: return -ENODEV; } @@ -2180,6 +2197,11 @@ struct procunit_info { struct procunit_value_info *values; }; +static struct procunit_value_info undefined_proc_info[] = { + { 0x00, "Control Undefined", 0 }, + { 0 } +}; + static struct procunit_value_info updown_proc_info[] = { { UAC_UD_ENABLE, "Switch", USB_MIXER_BOOLEAN }, { UAC_UD_MODE_SELECT, "Mode Select", USB_MIXER_U8, 1 }, @@ -2228,6 +2250,23 @@ static struct procunit_info procunits[] = { { UAC_PROCESS_DYN_RANGE_COMP, "DCR", dcr_proc_info }, { 0 }, }; + +static struct procunit_value_info uac3_updown_proc_info[] = { + { UAC3_UD_MODE_SELECT, "Mode Select", USB_MIXER_U8, 1 }, + { 0 } +}; +static struct procunit_value_info uac3_stereo_ext_proc_info[] = { + { UAC3_EXT_WIDTH_CONTROL, "Width Control", USB_MIXER_U8 }, + { 0 } +}; + +static struct procunit_info uac3_procunits[] = { + { UAC3_PROCESS_UP_DOWNMIX, "Up Down", uac3_updown_proc_info }, + { UAC3_PROCESS_STEREO_EXTENDER, "3D Stereo Extender", uac3_stereo_ext_proc_info }, + { UAC3_PROCESS_MULTI_FUNCTION, "Multi-Function", undefined_proc_info }, + { 0 }, +}; + /* * predefined data for extension units */ @@ -2388,8 +2427,16 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, static int parse_audio_processing_unit(struct mixer_build *state, int unitid, void *raw_desc) { - return build_audio_procunit(state, unitid, raw_desc, - procunits, "Processing Unit"); + switch (state->mixer->protocol) { + case UAC_VERSION_1: + case UAC_VERSION_2: + default: + return build_audio_procunit(state, unitid, raw_desc, + procunits, "Processing Unit"); + case UAC_VERSION_3: + return build_audio_procunit(state, unitid, raw_desc, + uac3_procunits, "Processing Unit"); + } } static int parse_audio_extension_unit(struct mixer_build *state, int unitid, -- cgit v1.2.3 From 8b3a087f7f6580e685a4f1ac980d07f96ad250a5 Mon Sep 17 00:00:00 2001 From: Jorge Sanjuan Date: Wed, 11 Jul 2018 13:37:54 +0100 Subject: ALSA: usb-audio: Unify virtual type units type to UAC3 values The Audio Control interface descriptor subtypes do not match across all the UAC versions. That makes reusability of the "virtual type" (Mixer, Processors, Selectors, etc) terminals difficult. It also makes the mixer get the default names for the virtual terminals wrong due to the overlap. This patch proposes an unified approach by always using the most comprehensive spec version to define them all (in this case UAC3). Signed-off-by: Jorge Sanjuan Signed-off-by: Takashi Iwai --- sound/usb/mixer.c | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) (limited to 'sound') diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 39fde49e8749..87f18cb74ca3 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -675,16 +675,16 @@ static int get_term_name(struct snd_usb_audio *chip, struct usb_audio_term *iter if (term_only) return 0; switch (iterm->type >> 16) { - case UAC_SELECTOR_UNIT: + case UAC3_SELECTOR_UNIT: strcpy(name, "Selector"); return 8; - case UAC1_PROCESSING_UNIT: + case UAC3_PROCESSING_UNIT: strcpy(name, "Process Unit"); return 12; - case UAC1_EXTENSION_UNIT: + case UAC3_EXTENSION_UNIT: strcpy(name, "Ext Unit"); return 8; - case UAC_MIXER_UNIT: + case UAC3_MIXER_UNIT: strcpy(name, "Mixer"); return 5; default: @@ -832,7 +832,7 @@ static int check_input_term(struct mixer_build *state, int id, case UAC_MIXER_UNIT: { struct uac_mixer_unit_descriptor *d = p1; - term->type = d->bDescriptorSubtype << 16; /* virtual type */ + term->type = UAC3_MIXER_UNIT << 16; /* virtual type */ term->channels = uac_mixer_unit_bNrChannels(d); term->chconfig = uac_mixer_unit_wChannelConfig(d, protocol); term->name = uac_mixer_unit_iMixer(d); @@ -845,15 +845,23 @@ static int check_input_term(struct mixer_build *state, int id, err = check_input_term(state, d->baSourceID[0], term); if (err < 0) return err; - term->type = d->bDescriptorSubtype << 16; /* virtual type */ + term->type = UAC3_SELECTOR_UNIT << 16; /* virtual type */ term->id = id; term->name = uac_selector_unit_iSelector(d); return 0; } case UAC1_PROCESSING_UNIT: + /* UAC2_EFFECT_UNIT */ + if (protocol == UAC_VERSION_1) + term->type = UAC3_PROCESSING_UNIT << 16; /* virtual type */ + else /* UAC_VERSION_2 */ + term->type = UAC3_EFFECT_UNIT << 16; /* virtual type */ case UAC1_EXTENSION_UNIT: /* UAC2_PROCESSING_UNIT_V2 */ - /* UAC2_EFFECT_UNIT */ + if (protocol == UAC_VERSION_1 && !term->type) + term->type = UAC3_EXTENSION_UNIT << 16; /* virtual type */ + else if (protocol == UAC_VERSION_2 && !term->type) + term->type = UAC3_PROCESSING_UNIT << 16; /* virtual type */ case UAC2_EXTENSION_UNIT_V2: { struct uac_processing_unit_descriptor *d = p1; @@ -869,7 +877,9 @@ static int check_input_term(struct mixer_build *state, int id, id = d->baSourceID[0]; break; /* continue to parse */ } - term->type = d->bDescriptorSubtype << 16; /* virtual type */ + if (!term->type) + term->type = UAC3_EXTENSION_UNIT << 16; /* virtual type */ + term->channels = uac_processing_unit_bNrChannels(d); term->chconfig = uac_processing_unit_wChannelConfig(d, protocol); term->name = uac_processing_unit_iProcessing(d, protocol); @@ -878,7 +888,7 @@ static int check_input_term(struct mixer_build *state, int id, case UAC2_CLOCK_SOURCE: { struct uac_clock_source_descriptor *d = p1; - term->type = d->bDescriptorSubtype << 16; /* virtual type */ + term->type = UAC3_CLOCK_SOURCE << 16; /* virtual type */ term->id = id; term->name = d->iClockSource; return 0; @@ -923,7 +933,7 @@ static int check_input_term(struct mixer_build *state, int id, case UAC3_CLOCK_SOURCE: { struct uac3_clock_source_descriptor *d = p1; - term->type = d->bDescriptorSubtype << 16; /* virtual type */ + term->type = UAC3_CLOCK_SOURCE << 16; /* virtual type */ term->id = id; term->name = le16_to_cpu(d->wClockSourceStr); return 0; @@ -936,7 +946,7 @@ static int check_input_term(struct mixer_build *state, int id, return err; term->channels = err; - term->type = d->bDescriptorSubtype << 16; /* virtual type */ + term->type = UAC3_MIXER_UNIT << 16; /* virtual type */ return 0; } @@ -947,7 +957,7 @@ static int check_input_term(struct mixer_build *state, int id, err = check_input_term(state, d->baSourceID[0], term); if (err < 0) return err; - term->type = d->bDescriptorSubtype << 16; /* virtual type */ + term->type = UAC3_SELECTOR_UNIT << 16; /* virtual type */ term->id = id; term->name = 0; /* TODO: UAC3 Class-specific strings */ @@ -964,7 +974,7 @@ static int check_input_term(struct mixer_build *state, int id, if (err < 0) return err; - term->type = d->bDescriptorSubtype << 16; /* virtual type */ + term->type = UAC3_PROCESSING_UNIT << 16; /* virtual type */ term->id = id; term->name = 0; /* TODO: UAC3 Class-specific strings */ -- cgit v1.2.3 From 55b8cb46a71137aa19eba2ae5a4be384500db89e Mon Sep 17 00:00:00 2001 From: Jorge Sanjuan Date: Wed, 11 Jul 2018 13:37:55 +0100 Subject: ALSA: usb-audio: Tidy up logic for Processing Unit min/max values This patch refactors the processing units min/max calculation logic for the mixer controls and fixes an issue where the Mode Select checking of the Up/Down mixers doesn't differentiate between the UAC1 and UAC2 Control Selector (0x02) and the UAC3 one which is different (0x01). Signed-off-by: Jorge Sanjuan Signed-off-by: Takashi Iwai --- sound/usb/mixer.c | 58 +++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 41 insertions(+), 17 deletions(-) (limited to 'sound') diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 87f18cb74ca3..73e811f86a95 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -2376,25 +2376,49 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, cval->master_readonly = 1; /* get min/max values */ - if (type == UAC_PROCESS_UP_DOWNMIX && cval->control == UAC_UD_MODE_SELECT) { - __u8 *control_spec = uac_processing_unit_specific(desc, state->mixer->protocol); - /* FIXME: hard-coded */ - cval->min = 1; - cval->max = control_spec[0]; - cval->res = 1; - cval->initialized = 1; - } else { - if (type == USB_XU_CLOCK_RATE) { - /* - * E-Mu USB 0404/0202/TrackerPre/0204 - * samplerate control quirk - */ - cval->min = 0; - cval->max = 5; + switch (type) { + case UAC_PROCESS_UP_DOWNMIX: { + bool mode_sel = false; + + switch (state->mixer->protocol) { + case UAC_VERSION_1: + case UAC_VERSION_2: + default: + if (cval->control == UAC_UD_MODE_SELECT) + mode_sel = true; + break; + case UAC_VERSION_3: + if (cval->control == UAC3_UD_MODE_SELECT) + mode_sel = true; + break; + } + + if (mode_sel) { + __u8 *control_spec = uac_processing_unit_specific(desc, + state->mixer->protocol); + cval->min = 1; + cval->max = control_spec[0]; cval->res = 1; cval->initialized = 1; - } else - get_min_max(cval, valinfo->min_value); + break; + } + + get_min_max(cval, valinfo->min_value); + break; + } + case USB_XU_CLOCK_RATE: + /* + * E-Mu USB 0404/0202/TrackerPre/0204 + * samplerate control quirk + */ + cval->min = 0; + cval->max = 5; + cval->res = 1; + cval->initialized = 1; + break; + default: + get_min_max(cval, valinfo->min_value); + break; } kctl = snd_ctl_new1(&mixer_procunit_ctl, cval); -- cgit v1.2.3 From b6d7b3622b6e7685767a616bb663aed40d04fdc6 Mon Sep 17 00:00:00 2001 From: Jim Qu Date: Mon, 16 Jul 2018 14:06:34 +0800 Subject: ALSA: hda: use PCI_BASE_CLASS_DISPLAY to replace PCI_CLASS_DISPLAY_VGA Except PCI_CLASS_DISPLAY_VGA, some PCI class is sometimes PCI_CLASS_DISPLAY_3D or PCI_CLASS_DISPLAY_OTHER. Signed-off-by: Jim Qu Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_intel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index a9b55d65f2bd..daedf662b940 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -1429,7 +1429,7 @@ static struct pci_dev *get_bound_vga(struct pci_dev *pci) p = pci_get_domain_bus_and_slot(pci_domain_nr(pci->bus), pci->bus->number, 0); if (p) { - if ((p->class >> 8) == PCI_CLASS_DISPLAY_VGA) + if ((p->class >> 16) == PCI_BASE_CLASS_DISPLAY) return p; pci_dev_put(p); } -- cgit v1.2.3 From 4aaf448fa9754e2d5ee188d32327b24ffc15ca4d Mon Sep 17 00:00:00 2001 From: Jim Qu Date: Tue, 17 Jul 2018 16:20:50 +0800 Subject: vga_switcheroo: set audio client id according to bound GPU id On modern laptop, there are more and more platforms have two GPUs, and each of them maybe have audio codec for HDMP/DP output. For some dGPU which is no output, audio codec usually is disabled. In currect HDA audio driver, it will set all codec as VGA_SWITCHEROO_DIS, the audio which is binded to UMA will be suspended if user use debugfs to contorl power In HDA driver side, it is difficult to know which GPU the audio has binded to. So set the bound gpu pci dev to vga_switcheroo. if the audio client is not the third registration, audio id will set in vga_switcheroo enable function. if the audio client is the last registration when vga_switcheroo _ready() get true, we should get audio client id from bound GPU directly. Signed-off-by: Jim Qu Reviewed-by: Lukas Wunner Signed-off-by: Takashi Iwai --- drivers/gpu/vga/vga_switcheroo.c | 63 +++++++++++++++++++++++++++++++++------- include/linux/vga_switcheroo.h | 8 ++--- sound/pci/hda/hda_intel.c | 11 +++---- 3 files changed, 62 insertions(+), 20 deletions(-) (limited to 'sound') diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c index fc4adf3d34e8..a96bf46bc483 100644 --- a/drivers/gpu/vga/vga_switcheroo.c +++ b/drivers/gpu/vga/vga_switcheroo.c @@ -103,9 +103,11 @@ * runtime pm. If true, writing ON and OFF to the vga_switcheroo debugfs * interface is a no-op so as not to interfere with runtime pm * @list: client list + * @vga_dev: pci device, indicate which GPU is bound to current audio client * * Registered client. A client can be either a GPU or an audio device on a GPU. - * For audio clients, the @fb_info and @active members are bogus. + * For audio clients, the @fb_info and @active members are bogus. For GPU + * clients, the @vga_dev is bogus. */ struct vga_switcheroo_client { struct pci_dev *pdev; @@ -116,6 +118,7 @@ struct vga_switcheroo_client { bool active; bool driver_power_control; struct list_head list; + struct pci_dev *vga_dev; }; /* @@ -161,9 +164,8 @@ struct vgasr_priv { }; #define ID_BIT_AUDIO 0x100 -#define client_is_audio(c) ((c)->id & ID_BIT_AUDIO) -#define client_is_vga(c) ((c)->id == VGA_SWITCHEROO_UNKNOWN_ID || \ - !client_is_audio(c)) +#define client_is_audio(c) ((c)->id & ID_BIT_AUDIO) +#define client_is_vga(c) (!client_is_audio(c)) #define client_id(c) ((c)->id & ~ID_BIT_AUDIO) static int vga_switcheroo_debugfs_init(struct vgasr_priv *priv); @@ -192,14 +194,29 @@ static void vga_switcheroo_enable(void) vgasr_priv.handler->init(); list_for_each_entry(client, &vgasr_priv.clients, list) { - if (client->id != VGA_SWITCHEROO_UNKNOWN_ID) + if (!client_is_vga(client) || + client_id(client) != VGA_SWITCHEROO_UNKNOWN_ID) continue; + ret = vgasr_priv.handler->get_client_id(client->pdev); if (ret < 0) return; client->id = ret; } + + list_for_each_entry(client, &vgasr_priv.clients, list) { + if (!client_is_audio(client) || + client_id(client) != VGA_SWITCHEROO_UNKNOWN_ID) + continue; + + ret = vgasr_priv.handler->get_client_id(client->vga_dev); + if (ret < 0) + return; + + client->id = ret | ID_BIT_AUDIO; + } + vga_switcheroo_debugfs_init(&vgasr_priv); vgasr_priv.active = true; } @@ -272,7 +289,9 @@ EXPORT_SYMBOL(vga_switcheroo_handler_flags); static int register_client(struct pci_dev *pdev, const struct vga_switcheroo_client_ops *ops, - enum vga_switcheroo_client_id id, bool active, + enum vga_switcheroo_client_id id, + struct pci_dev *vga_dev, + bool active, bool driver_power_control) { struct vga_switcheroo_client *client; @@ -287,6 +306,7 @@ static int register_client(struct pci_dev *pdev, client->id = id; client->active = active; client->driver_power_control = driver_power_control; + client->vga_dev = vga_dev; mutex_lock(&vgasr_mutex); list_add_tail(&client->list, &vgasr_priv.clients); @@ -319,7 +339,7 @@ int vga_switcheroo_register_client(struct pci_dev *pdev, const struct vga_switcheroo_client_ops *ops, bool driver_power_control) { - return register_client(pdev, ops, VGA_SWITCHEROO_UNKNOWN_ID, + return register_client(pdev, ops, VGA_SWITCHEROO_UNKNOWN_ID, NULL, pdev == vga_default_device(), driver_power_control); } @@ -329,19 +349,40 @@ EXPORT_SYMBOL(vga_switcheroo_register_client); * vga_switcheroo_register_audio_client - register audio client * @pdev: client pci device * @ops: client callbacks - * @id: client identifier + * @vga_dev: pci device which is bound to current audio client * * Register audio client (audio device on a GPU). The client is assumed * to use runtime PM. Beforehand, vga_switcheroo_client_probe_defer() * shall be called to ensure that all prerequisites are met. * - * Return: 0 on success, -ENOMEM on memory allocation error. + * Return: 0 on success, -ENOMEM on memory allocation error, -EINVAL on getting + * client id error. */ int vga_switcheroo_register_audio_client(struct pci_dev *pdev, const struct vga_switcheroo_client_ops *ops, - enum vga_switcheroo_client_id id) + struct pci_dev *vga_dev) { - return register_client(pdev, ops, id | ID_BIT_AUDIO, false, true); + enum vga_switcheroo_client_id id = VGA_SWITCHEROO_UNKNOWN_ID; + + /* + * if vga_switcheroo has enabled, that mean two GPU clients and also + * handler are registered. Get audio client id from bound GPU client + * id directly, otherwise, set it as VGA_SWITCHEROO_UNKNOWN_ID, + * it will set to correct id in later when vga_switcheroo_enable() + * is called. + */ + mutex_lock(&vgasr_mutex); + if (vgasr_priv.active) { + id = vgasr_priv.handler->get_client_id(vga_dev); + if (id < 0) { + mutex_unlock(&vgasr_mutex); + return -EINVAL; + } + } + mutex_unlock(&vgasr_mutex); + + return register_client(pdev, ops, id | ID_BIT_AUDIO, vga_dev, + false, true); } EXPORT_SYMBOL(vga_switcheroo_register_audio_client); diff --git a/include/linux/vga_switcheroo.h b/include/linux/vga_switcheroo.h index 77f0f0af3a71..a34539b7f750 100644 --- a/include/linux/vga_switcheroo.h +++ b/include/linux/vga_switcheroo.h @@ -84,8 +84,8 @@ enum vga_switcheroo_state { * Client identifier. Audio clients use the same identifier & 0x100. */ enum vga_switcheroo_client_id { - VGA_SWITCHEROO_UNKNOWN_ID = -1, - VGA_SWITCHEROO_IGD, + VGA_SWITCHEROO_UNKNOWN_ID = 0x1000, + VGA_SWITCHEROO_IGD = 0, VGA_SWITCHEROO_DIS, VGA_SWITCHEROO_MAX_CLIENTS, }; @@ -151,7 +151,7 @@ int vga_switcheroo_register_client(struct pci_dev *dev, bool driver_power_control); int vga_switcheroo_register_audio_client(struct pci_dev *pdev, const struct vga_switcheroo_client_ops *ops, - enum vga_switcheroo_client_id id); + struct pci_dev *vga_dev); void vga_switcheroo_client_fb_set(struct pci_dev *dev, struct fb_info *info); @@ -180,7 +180,7 @@ static inline int vga_switcheroo_register_handler(const struct vga_switcheroo_ha enum vga_switcheroo_handler_flags_t handler_flags) { return 0; } static inline int vga_switcheroo_register_audio_client(struct pci_dev *pdev, const struct vga_switcheroo_client_ops *ops, - enum vga_switcheroo_client_id id) { return 0; } + struct pci_dev *vga_dev) { return 0; } static inline void vga_switcheroo_unregister_handler(void) {} static inline enum vga_switcheroo_handler_flags_t vga_switcheroo_handler_flags(void) { return 0; } static inline int vga_switcheroo_lock_ddc(struct pci_dev *pdev) { return -ENODEV; } diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 1ae1850b3bfd..1967a5537d68 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -1319,15 +1319,16 @@ static const struct vga_switcheroo_client_ops azx_vs_ops = { static int register_vga_switcheroo(struct azx *chip) { struct hda_intel *hda = container_of(chip, struct hda_intel, chip); + struct pci_dev *p; int err; if (!hda->use_vga_switcheroo) return 0; - /* FIXME: currently only handling DIS controller - * is there any machine with two switchable HDMI audio controllers? - */ - err = vga_switcheroo_register_audio_client(chip->pci, &azx_vs_ops, - VGA_SWITCHEROO_DIS); + + p = get_bound_vga(chip->pci); + err = vga_switcheroo_register_audio_client(chip->pci, &azx_vs_ops, p); + pci_dev_put(p); + if (err < 0) return err; hda->vga_switcheroo_registered = 1; -- cgit v1.2.3 From e2d2f240497c63a157f897c87567b93ed43a2213 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Tue, 17 Jul 2018 10:00:43 -0500 Subject: ALSA: emu10k1_patch: Use swap macro in snd_emu10k1_sample_new Make use of the swap macro and remove unnecessary variable *tmp*. This makes the code easier to read and maintain. This code was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Signed-off-by: Takashi Iwai --- sound/pci/emu10k1/emu10k1_patch.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'sound') diff --git a/sound/pci/emu10k1/emu10k1_patch.c b/sound/pci/emu10k1/emu10k1_patch.c index 0e069aeab86d..c32eb7053715 100644 --- a/sound/pci/emu10k1/emu10k1_patch.c +++ b/sound/pci/emu10k1/emu10k1_patch.c @@ -70,11 +70,8 @@ snd_emu10k1_sample_new(struct snd_emux *rec, struct snd_sf_sample *sp, loopend = sampleend; /* be sure loop points start < end */ - if (sp->v.loopstart >= sp->v.loopend) { - int tmp = sp->v.loopstart; - sp->v.loopstart = sp->v.loopend; - sp->v.loopend = tmp; - } + if (sp->v.loopstart >= sp->v.loopend) + swap(sp->v.loopstart, sp->v.loopend); /* compute true data size to be loaded */ truesize = sp->v.size + BLANK_HEAD_SIZE; -- cgit v1.2.3 From 7373c2a99abf2b11b5e8a226071331c0176253ff Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Tue, 17 Jul 2018 10:06:10 -0500 Subject: ALSA: emu8000: Use swap macro in snd_emu8000_sample_new Make use of the swap macro and remove unnecessary variable *tmp*. This makes the code easier to read and maintain. This code was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Signed-off-by: Takashi Iwai --- sound/isa/sb/emu8000_patch.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'sound') diff --git a/sound/isa/sb/emu8000_patch.c b/sound/isa/sb/emu8000_patch.c index c2e41d2762f7..d45a6b9d6437 100644 --- a/sound/isa/sb/emu8000_patch.c +++ b/sound/isa/sb/emu8000_patch.c @@ -165,11 +165,8 @@ snd_emu8000_sample_new(struct snd_emux *rec, struct snd_sf_sample *sp, return 0; /* be sure loop points start < end */ - if (sp->v.loopstart > sp->v.loopend) { - int tmp = sp->v.loopstart; - sp->v.loopstart = sp->v.loopend; - sp->v.loopend = tmp; - } + if (sp->v.loopstart > sp->v.loopend) + swap(sp->v.loopstart, sp->v.loopend); /* compute true data size to be loaded */ truesize = sp->v.size; -- cgit v1.2.3 From ae891abe7c2ccf75b69ca8330225e37ecc06924e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 11 Jul 2018 15:17:22 +0200 Subject: drm/i915: Split audio component to a generic type For allowing other drivers to use the DRM audio component, rename the i915_audio_component_* with drm_audio_component_*, and split the generic part into drm_audio_component.h. The i915 specific stuff remains in struct i915_audio_component, which contains drm_audio_component as the base. The license of drm_audio_component.h is kept to MIT as same as the the original i915_component.h. This is a preliminary change for further development, and no functional changes by this patch itself, merely code-split and renames. v1->v2: Use SPDX for drm_audio_component.h, fix remaining i915 argument in drm_audio_component.h Reviewed-by: Rodrigo Vivi Signed-off-by: Takashi Iwai --- drivers/gpu/drm/i915/intel_audio.c | 22 +++++---- include/drm/drm_audio_component.h | 95 ++++++++++++++++++++++++++++++++++++++ include/drm/i915_component.h | 85 ++-------------------------------- include/sound/hda_i915.h | 6 +-- include/sound/hdaudio.h | 6 +-- sound/hda/hdac_i915.c | 40 ++++++++-------- sound/pci/hda/patch_hdmi.c | 8 ++-- sound/soc/codecs/hdac_hdmi.c | 2 +- 8 files changed, 144 insertions(+), 120 deletions(-) create mode 100644 include/drm/drm_audio_component.h (limited to 'sound') diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c index 3ea566f99450..7dd5605d94ae 100644 --- a/drivers/gpu/drm/i915/intel_audio.c +++ b/drivers/gpu/drm/i915/intel_audio.c @@ -639,11 +639,12 @@ void intel_audio_codec_enable(struct intel_encoder *encoder, dev_priv->av_enc_map[pipe] = encoder; mutex_unlock(&dev_priv->av_mutex); - if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify) { + if (acomp && acomp->base.audio_ops && + acomp->base.audio_ops->pin_eld_notify) { /* audio drivers expect pipe = -1 to indicate Non-MST cases */ if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST)) pipe = -1; - acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr, + acomp->base.audio_ops->pin_eld_notify(acomp->base.audio_ops->audio_ptr, (int) port, (int) pipe); } @@ -681,11 +682,12 @@ void intel_audio_codec_disable(struct intel_encoder *encoder, dev_priv->av_enc_map[pipe] = NULL; mutex_unlock(&dev_priv->av_mutex); - if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify) { + if (acomp && acomp->base.audio_ops && + acomp->base.audio_ops->pin_eld_notify) { /* audio drivers expect pipe = -1 to indicate Non-MST cases */ if (!intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_DP_MST)) pipe = -1; - acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr, + acomp->base.audio_ops->pin_eld_notify(acomp->base.audio_ops->audio_ptr, (int) port, (int) pipe); } @@ -880,7 +882,7 @@ static int i915_audio_component_get_eld(struct device *kdev, int port, return ret; } -static const struct i915_audio_component_ops i915_audio_component_ops = { +static const struct drm_audio_component_ops i915_audio_component_ops = { .owner = THIS_MODULE, .get_power = i915_audio_component_get_power, .put_power = i915_audio_component_put_power, @@ -897,12 +899,12 @@ static int i915_audio_component_bind(struct device *i915_kdev, struct drm_i915_private *dev_priv = kdev_to_i915(i915_kdev); int i; - if (WARN_ON(acomp->ops || acomp->dev)) + if (WARN_ON(acomp->base.ops || acomp->base.dev)) return -EEXIST; drm_modeset_lock_all(&dev_priv->drm); - acomp->ops = &i915_audio_component_ops; - acomp->dev = i915_kdev; + acomp->base.ops = &i915_audio_component_ops; + acomp->base.dev = i915_kdev; BUILD_BUG_ON(MAX_PORTS != I915_MAX_PORTS); for (i = 0; i < ARRAY_SIZE(acomp->aud_sample_rate); i++) acomp->aud_sample_rate[i] = 0; @@ -919,8 +921,8 @@ static void i915_audio_component_unbind(struct device *i915_kdev, struct drm_i915_private *dev_priv = kdev_to_i915(i915_kdev); drm_modeset_lock_all(&dev_priv->drm); - acomp->ops = NULL; - acomp->dev = NULL; + acomp->base.ops = NULL; + acomp->base.dev = NULL; dev_priv->audio_component = NULL; drm_modeset_unlock_all(&dev_priv->drm); } diff --git a/include/drm/drm_audio_component.h b/include/drm/drm_audio_component.h new file mode 100644 index 000000000000..e85689f212c2 --- /dev/null +++ b/include/drm/drm_audio_component.h @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: MIT +// Copyright © 2014 Intel Corporation + +#ifndef _DRM_AUDIO_COMPONENT_H_ +#define _DRM_AUDIO_COMPONENT_H_ + +/** + * struct drm_audio_component_ops - Ops implemented by DRM driver, called by hda driver + */ +struct drm_audio_component_ops { + /** + * @owner: drm module to pin down + */ + struct module *owner; + /** + * @get_power: get the POWER_DOMAIN_AUDIO power well + * + * Request the power well to be turned on. + */ + void (*get_power)(struct device *); + /** + * @put_power: put the POWER_DOMAIN_AUDIO power well + * + * Allow the power well to be turned off. + */ + void (*put_power)(struct device *); + /** + * @codec_wake_override: Enable/disable codec wake signal + */ + void (*codec_wake_override)(struct device *, bool enable); + /** + * @get_cdclk_freq: Get the Core Display Clock in kHz + */ + int (*get_cdclk_freq)(struct device *); + /** + * @sync_audio_rate: set n/cts based on the sample rate + * + * Called from audio driver. After audio driver sets the + * sample rate, it will call this function to set n/cts + */ + int (*sync_audio_rate)(struct device *, int port, int pipe, int rate); + /** + * @get_eld: fill the audio state and ELD bytes for the given port + * + * Called from audio driver to get the HDMI/DP audio state of the given + * digital port, and also fetch ELD bytes to the given pointer. + * + * It returns the byte size of the original ELD (not the actually + * copied size), zero for an invalid ELD, or a negative error code. + * + * Note that the returned size may be over @max_bytes. Then it + * implies that only a part of ELD has been copied to the buffer. + */ + int (*get_eld)(struct device *, int port, int pipe, bool *enabled, + unsigned char *buf, int max_bytes); +}; + +/** + * struct drm_audio_component_audio_ops - Ops implemented by hda driver, called by DRM driver + */ +struct drm_audio_component_audio_ops { + /** + * @audio_ptr: Pointer to be used in call to pin_eld_notify + */ + void *audio_ptr; + /** + * @pin_eld_notify: Notify the HDA driver that pin sense and/or ELD information has changed + * + * Called when the DRM driver has set up audio pipeline or has just + * begun to tear it down. This allows the HDA driver to update its + * status accordingly (even when the HDA controller is in power save + * mode). + */ + void (*pin_eld_notify)(void *audio_ptr, int port, int pipe); +}; + +/** + * struct drm_audio_component - Used for direct communication between DRM and hda drivers + */ +struct drm_audio_component { + /** + * @dev: DRM device, used as parameter for ops + */ + struct device *dev; + /** + * @ops: Ops implemented by DRM driver, called by hda driver + */ + const struct drm_audio_component_ops *ops; + /** + * @audio_ops: Ops implemented by hda driver, called by DRM driver + */ + const struct drm_audio_component_audio_ops *audio_ops; +}; + +#endif /* _DRM_AUDIO_COMPONENT_H_ */ diff --git a/include/drm/i915_component.h b/include/drm/i915_component.h index 346b1f5cb180..fca22d463e1b 100644 --- a/include/drm/i915_component.h +++ b/include/drm/i915_component.h @@ -24,101 +24,26 @@ #ifndef _I915_COMPONENT_H_ #define _I915_COMPONENT_H_ +#include "drm_audio_component.h" + /* MAX_PORT is the number of port * It must be sync with I915_MAX_PORTS defined i915_drv.h */ #define MAX_PORTS 6 -/** - * struct i915_audio_component_ops - Ops implemented by i915 driver, called by hda driver - */ -struct i915_audio_component_ops { - /** - * @owner: i915 module - */ - struct module *owner; - /** - * @get_power: get the POWER_DOMAIN_AUDIO power well - * - * Request the power well to be turned on. - */ - void (*get_power)(struct device *); - /** - * @put_power: put the POWER_DOMAIN_AUDIO power well - * - * Allow the power well to be turned off. - */ - void (*put_power)(struct device *); - /** - * @codec_wake_override: Enable/disable codec wake signal - */ - void (*codec_wake_override)(struct device *, bool enable); - /** - * @get_cdclk_freq: Get the Core Display Clock in kHz - */ - int (*get_cdclk_freq)(struct device *); - /** - * @sync_audio_rate: set n/cts based on the sample rate - * - * Called from audio driver. After audio driver sets the - * sample rate, it will call this function to set n/cts - */ - int (*sync_audio_rate)(struct device *, int port, int pipe, int rate); - /** - * @get_eld: fill the audio state and ELD bytes for the given port - * - * Called from audio driver to get the HDMI/DP audio state of the given - * digital port, and also fetch ELD bytes to the given pointer. - * - * It returns the byte size of the original ELD (not the actually - * copied size), zero for an invalid ELD, or a negative error code. - * - * Note that the returned size may be over @max_bytes. Then it - * implies that only a part of ELD has been copied to the buffer. - */ - int (*get_eld)(struct device *, int port, int pipe, bool *enabled, - unsigned char *buf, int max_bytes); -}; - -/** - * struct i915_audio_component_audio_ops - Ops implemented by hda driver, called by i915 driver - */ -struct i915_audio_component_audio_ops { - /** - * @audio_ptr: Pointer to be used in call to pin_eld_notify - */ - void *audio_ptr; - /** - * @pin_eld_notify: Notify the HDA driver that pin sense and/or ELD information has changed - * - * Called when the i915 driver has set up audio pipeline or has just - * begun to tear it down. This allows the HDA driver to update its - * status accordingly (even when the HDA controller is in power save - * mode). - */ - void (*pin_eld_notify)(void *audio_ptr, int port, int pipe); -}; - /** * struct i915_audio_component - Used for direct communication between i915 and hda drivers */ struct i915_audio_component { /** - * @dev: i915 device, used as parameter for ops + * @base: the drm_audio_component base class */ - struct device *dev; + struct drm_audio_component base; + /** * @aud_sample_rate: the array of audio sample rate per port */ int aud_sample_rate[MAX_PORTS]; - /** - * @ops: Ops implemented by i915 driver, called by hda driver - */ - const struct i915_audio_component_ops *ops; - /** - * @audio_ops: Ops implemented by hda driver, called by i915 driver - */ - const struct i915_audio_component_audio_ops *audio_ops; }; #endif /* _I915_COMPONENT_H_ */ diff --git a/include/sound/hda_i915.h b/include/sound/hda_i915.h index a94f5b6f92ac..f69ea84e7b65 100644 --- a/include/sound/hda_i915.h +++ b/include/sound/hda_i915.h @@ -5,7 +5,7 @@ #ifndef __SOUND_HDA_I915_H #define __SOUND_HDA_I915_H -#include +#include #ifdef CONFIG_SND_HDA_I915 int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable); @@ -17,7 +17,7 @@ int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid, int dev_id, bool *audio_enabled, char *buffer, int max_bytes); int snd_hdac_i915_init(struct hdac_bus *bus); int snd_hdac_i915_exit(struct hdac_bus *bus); -int snd_hdac_i915_register_notifier(const struct i915_audio_component_audio_ops *); +int snd_hdac_i915_register_notifier(const struct drm_audio_component_audio_ops *); #else static inline int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable) { @@ -49,7 +49,7 @@ static inline int snd_hdac_i915_exit(struct hdac_bus *bus) { return 0; } -static inline int snd_hdac_i915_register_notifier(const struct i915_audio_component_audio_ops *ops) +static inline int snd_hdac_i915_register_notifier(const struct drm_audio_component_audio_ops *ops) { return -ENODEV; } diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h index f1baaa88e766..ab5ee3ef2198 100644 --- a/include/sound/hdaudio.h +++ b/include/sound/hdaudio.h @@ -333,9 +333,9 @@ struct hdac_bus { spinlock_t reg_lock; struct mutex cmd_mutex; - /* i915 component interface */ - struct i915_audio_component *audio_component; - int i915_power_refcount; + /* DRM component interface */ + struct drm_audio_component *audio_component; + int drm_power_refcount; /* parameters required for enhanced capabilities */ int num_streams; diff --git a/sound/hda/hdac_i915.c b/sound/hda/hdac_i915.c index cbe818eda336..1a88c1aaf9bb 100644 --- a/sound/hda/hdac_i915.c +++ b/sound/hda/hdac_i915.c @@ -16,13 +16,13 @@ #include #include #include -#include +#include #include #include #include #include -static struct i915_audio_component *hdac_acomp; +static struct drm_audio_component *hdac_acomp; /** * snd_hdac_set_codec_wakeup - Enable / disable HDMI/DP codec wakeup @@ -39,7 +39,7 @@ static struct i915_audio_component *hdac_acomp; */ int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable) { - struct i915_audio_component *acomp = bus->audio_component; + struct drm_audio_component *acomp = bus->audio_component; if (!acomp || !acomp->ops) return -ENODEV; @@ -74,7 +74,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_set_codec_wakeup); */ int snd_hdac_display_power(struct hdac_bus *bus, bool enable) { - struct i915_audio_component *acomp = bus->audio_component; + struct drm_audio_component *acomp = bus->audio_component; if (!acomp || !acomp->ops) return -ENODEV; @@ -83,14 +83,14 @@ int snd_hdac_display_power(struct hdac_bus *bus, bool enable) enable ? "enable" : "disable"); if (enable) { - if (!bus->i915_power_refcount++) { + if (!bus->drm_power_refcount++) { acomp->ops->get_power(acomp->dev); snd_hdac_set_codec_wakeup(bus, true); snd_hdac_set_codec_wakeup(bus, false); } } else { - WARN_ON(!bus->i915_power_refcount); - if (!--bus->i915_power_refcount) + WARN_ON(!bus->drm_power_refcount); + if (!--bus->drm_power_refcount) acomp->ops->put_power(acomp->dev); } @@ -119,7 +119,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_display_power); */ void snd_hdac_i915_set_bclk(struct hdac_bus *bus) { - struct i915_audio_component *acomp = bus->audio_component; + struct drm_audio_component *acomp = bus->audio_component; struct pci_dev *pci = to_pci_dev(bus->dev); int cdclk_freq; unsigned int bclk_m, bclk_n; @@ -206,7 +206,7 @@ int snd_hdac_sync_audio_rate(struct hdac_device *codec, hda_nid_t nid, int dev_id, int rate) { struct hdac_bus *bus = codec->bus; - struct i915_audio_component *acomp = bus->audio_component; + struct drm_audio_component *acomp = bus->audio_component; int port, pipe; if (!acomp || !acomp->ops || !acomp->ops->sync_audio_rate) @@ -244,7 +244,7 @@ int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid, int dev_id, bool *audio_enabled, char *buffer, int max_bytes) { struct hdac_bus *bus = codec->bus; - struct i915_audio_component *acomp = bus->audio_component; + struct drm_audio_component *acomp = bus->audio_component; int port, pipe; if (!acomp || !acomp->ops || !acomp->ops->get_eld) @@ -262,7 +262,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_acomp_get_eld); static int hdac_component_master_bind(struct device *dev) { - struct i915_audio_component *acomp = hdac_acomp; + struct drm_audio_component *acomp = hdac_acomp; int ret; ret = component_bind_all(dev, acomp); @@ -294,7 +294,7 @@ out_unbind: static void hdac_component_master_unbind(struct device *dev) { - struct i915_audio_component *acomp = hdac_acomp; + struct drm_audio_component *acomp = hdac_acomp; module_put(acomp->ops->owner); component_unbind_all(dev, acomp); @@ -323,7 +323,7 @@ static int hdac_component_master_match(struct device *dev, void *data) * * Returns zero for success or a negative error code. */ -int snd_hdac_i915_register_notifier(const struct i915_audio_component_audio_ops *aops) +int snd_hdac_i915_register_notifier(const struct drm_audio_component_audio_ops *aops) { if (!hdac_acomp) return -ENODEV; @@ -361,7 +361,8 @@ int snd_hdac_i915_init(struct hdac_bus *bus) { struct component_match *match = NULL; struct device *dev = bus->dev; - struct i915_audio_component *acomp; + struct i915_audio_component *i915_acomp; + struct drm_audio_component *acomp; int ret; if (WARN_ON(hdac_acomp)) @@ -370,9 +371,10 @@ int snd_hdac_i915_init(struct hdac_bus *bus) if (!i915_gfx_present()) return -ENODEV; - acomp = kzalloc(sizeof(*acomp), GFP_KERNEL); - if (!acomp) + i915_acomp = kzalloc(sizeof(*i915_acomp), GFP_KERNEL); + if (!i915_acomp) return -ENOMEM; + acomp = &i915_acomp->base; bus->audio_component = acomp; hdac_acomp = acomp; @@ -421,13 +423,13 @@ EXPORT_SYMBOL_GPL(snd_hdac_i915_init); int snd_hdac_i915_exit(struct hdac_bus *bus) { struct device *dev = bus->dev; - struct i915_audio_component *acomp = bus->audio_component; + struct drm_audio_component *acomp = bus->audio_component; if (!acomp) return 0; - WARN_ON(bus->i915_power_refcount); - if (bus->i915_power_refcount > 0 && acomp->ops) + WARN_ON(bus->drm_power_refcount); + if (bus->drm_power_refcount > 0 && acomp->ops) acomp->ops->put_power(acomp->dev); component_master_del(dev, &hdac_component_master_ops); diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 8a49415aebac..c0847017114c 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -177,7 +177,7 @@ struct hdmi_spec { /* i915/powerwell (Haswell+/Valleyview+) specific */ bool use_acomp_notifier; /* use i915 eld_notify callback for hotplug */ - struct i915_audio_component_audio_ops i915_audio_ops; + struct drm_audio_component_audio_ops drm_audio_ops; struct hdac_chmap chmap; hda_nid_t vendor_nid; @@ -2511,14 +2511,14 @@ static void register_i915_notifier(struct hda_codec *codec) struct hdmi_spec *spec = codec->spec; spec->use_acomp_notifier = true; - spec->i915_audio_ops.audio_ptr = codec; + spec->drm_audio_ops.audio_ptr = codec; /* intel_audio_codec_enable() or intel_audio_codec_disable() * will call pin_eld_notify with using audio_ptr pointer * We need make sure audio_ptr is really setup */ wmb(); - spec->i915_audio_ops.pin_eld_notify = intel_pin_eld_notify; - snd_hdac_i915_register_notifier(&spec->i915_audio_ops); + spec->drm_audio_ops.pin_eld_notify = intel_pin_eld_notify; + snd_hdac_i915_register_notifier(&spec->drm_audio_ops); } /* setup_stream ops override for HSW+ */ diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index 3e3a2a9ef310..460075475f20 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c @@ -1583,7 +1583,7 @@ static void hdac_hdmi_eld_notify_cb(void *aptr, int port, int pipe) } -static struct i915_audio_component_audio_ops aops = { +static struct drm_audio_component_audio_ops aops = { .pin_eld_notify = hdac_hdmi_eld_notify_cb, }; -- cgit v1.2.3 From 82887c0beb1ee6b33eed8318d8e8d41c5b3eddae Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 11 Jul 2018 15:48:18 +0200 Subject: ALSA: hda/i915: Associate audio component with devres The HD-audio i915 binding code contains a single pointer, hdac_acomp, for allowing the access to audio component from the master bind/unbind callbacks. This was needed because the callbacks pass only the device pointer and we can't guarantee the object type assigned to the drvdata (which is free for each controller driver implementation). And this implementation will be a problem if we support multiple components for different DRM drivers, not only i915. As a solution, allocate the audio component object via devres and associate it with the given device, so that the component callbacks can refer to it via devres_find(). The removal of the object is still done half-manually via devres_destroy() to make the code consistent (although it may work without the explicit call). Also, the snd_hda_i915_register_notifier() had the reference to hdac_acomp as well. In this patch, the corresponding code is removed by passing hdac_bus object to the function, too. Signed-off-by: Takashi Iwai --- include/sound/hda_i915.h | 6 ++++-- sound/hda/hdac_i915.c | 34 +++++++++++++++++++++------------- sound/pci/hda/patch_hdmi.c | 5 +++-- sound/soc/codecs/hdac_hdmi.c | 2 +- 4 files changed, 29 insertions(+), 18 deletions(-) (limited to 'sound') diff --git a/include/sound/hda_i915.h b/include/sound/hda_i915.h index f69ea84e7b65..648263791559 100644 --- a/include/sound/hda_i915.h +++ b/include/sound/hda_i915.h @@ -17,7 +17,8 @@ int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid, int dev_id, bool *audio_enabled, char *buffer, int max_bytes); int snd_hdac_i915_init(struct hdac_bus *bus); int snd_hdac_i915_exit(struct hdac_bus *bus); -int snd_hdac_i915_register_notifier(const struct drm_audio_component_audio_ops *); +int snd_hdac_i915_register_notifier(struct hdac_bus *bus, + const struct drm_audio_component_audio_ops *ops); #else static inline int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable) { @@ -49,7 +50,8 @@ static inline int snd_hdac_i915_exit(struct hdac_bus *bus) { return 0; } -static inline int snd_hdac_i915_register_notifier(const struct drm_audio_component_audio_ops *ops) +static inline int snd_hdac_i915_register_notifier(struct hdac_bus *bus, + const struct drm_audio_component_audio_ops *ops) { return -ENODEV; } diff --git a/sound/hda/hdac_i915.c b/sound/hda/hdac_i915.c index 1a88c1aaf9bb..861b77bbc7df 100644 --- a/sound/hda/hdac_i915.c +++ b/sound/hda/hdac_i915.c @@ -22,7 +22,14 @@ #include #include -static struct drm_audio_component *hdac_acomp; +static void hdac_acomp_release(struct device *dev, void *res) +{ +} + +static struct drm_audio_component *hdac_get_acomp(struct device *dev) +{ + return devres_find(dev, hdac_acomp_release, NULL, NULL); +} /** * snd_hdac_set_codec_wakeup - Enable / disable HDMI/DP codec wakeup @@ -262,7 +269,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_acomp_get_eld); static int hdac_component_master_bind(struct device *dev) { - struct drm_audio_component *acomp = hdac_acomp; + struct drm_audio_component *acomp = hdac_get_acomp(dev); int ret; ret = component_bind_all(dev, acomp); @@ -294,7 +301,7 @@ out_unbind: static void hdac_component_master_unbind(struct device *dev) { - struct drm_audio_component *acomp = hdac_acomp; + struct drm_audio_component *acomp = hdac_get_acomp(dev); module_put(acomp->ops->owner); component_unbind_all(dev, acomp); @@ -314,6 +321,7 @@ static int hdac_component_master_match(struct device *dev, void *data) /** * snd_hdac_i915_register_notifier - Register i915 audio component ops + * @bus: HDA core bus * @aops: i915 audio component ops * * This function is supposed to be used only by a HD-audio controller @@ -323,12 +331,13 @@ static int hdac_component_master_match(struct device *dev, void *data) * * Returns zero for success or a negative error code. */ -int snd_hdac_i915_register_notifier(const struct drm_audio_component_audio_ops *aops) +int snd_hdac_i915_register_notifier(struct hdac_bus *bus, + const struct drm_audio_component_audio_ops *aops) { - if (!hdac_acomp) + if (!bus->audio_component) return -ENODEV; - hdac_acomp->audio_ops = aops; + bus->audio_component->audio_ops = aops; return 0; } EXPORT_SYMBOL_GPL(snd_hdac_i915_register_notifier); @@ -365,18 +374,19 @@ int snd_hdac_i915_init(struct hdac_bus *bus) struct drm_audio_component *acomp; int ret; - if (WARN_ON(hdac_acomp)) + if (WARN_ON(hdac_get_acomp(dev))) return -EBUSY; if (!i915_gfx_present()) return -ENODEV; - i915_acomp = kzalloc(sizeof(*i915_acomp), GFP_KERNEL); + i915_acomp = devres_alloc(hdac_acomp_release, sizeof(*i915_acomp), + GFP_KERNEL); if (!i915_acomp) return -ENOMEM; acomp = &i915_acomp->base; bus->audio_component = acomp; - hdac_acomp = acomp; + devres_add(dev, acomp); component_match_add(dev, &match, hdac_component_master_match, bus); ret = component_master_add_with_match(dev, &hdac_component_master_ops, @@ -400,9 +410,8 @@ int snd_hdac_i915_init(struct hdac_bus *bus) out_master_del: component_master_del(dev, &hdac_component_master_ops); out_err: - kfree(acomp); bus->audio_component = NULL; - hdac_acomp = NULL; + devres_destroy(dev, hdac_acomp_release, NULL, NULL); dev_info(dev, "failed to add i915 component master (%d)\n", ret); return ret; @@ -434,9 +443,8 @@ int snd_hdac_i915_exit(struct hdac_bus *bus) component_master_del(dev, &hdac_component_master_ops); - kfree(acomp); bus->audio_component = NULL; - hdac_acomp = NULL; + devres_destroy(dev, hdac_acomp_release, NULL, NULL); return 0; } diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index c0847017114c..bf174a013f2d 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -2288,7 +2288,7 @@ static void generic_hdmi_free(struct hda_codec *codec) int pin_idx, pcm_idx; if (codec_has_acomp(codec)) - snd_hdac_i915_register_notifier(NULL); + snd_hdac_i915_register_notifier(&codec->bus->core, NULL); for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); @@ -2518,7 +2518,8 @@ static void register_i915_notifier(struct hda_codec *codec) */ wmb(); spec->drm_audio_ops.pin_eld_notify = intel_pin_eld_notify; - snd_hdac_i915_register_notifier(&spec->drm_audio_ops); + snd_hdac_i915_register_notifier(&codec->bus->core, + &spec->drm_audio_ops); } /* setup_stream ops override for HSW+ */ diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index 460075475f20..2b7c33db4ded 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c @@ -1812,7 +1812,7 @@ static int hdmi_codec_probe(struct snd_soc_component *component) return ret; aops.audio_ptr = hdev; - ret = snd_hdac_i915_register_notifier(&aops); + ret = snd_hdac_i915_register_notifier(hdev->bus, &aops); if (ret < 0) { dev_err(&hdev->dev, "notifier register failed: err: %d\n", ret); return ret; -- cgit v1.2.3 From a57942bfdd61b46df94021c9c33b8faaae5b65e1 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 11 Jul 2018 16:23:16 +0200 Subject: ALSA: hda: Make audio component support more generic This is the final step for more generic support of DRM audio component. The generic audio component code is now moved to its own file, and the symbols are renamed from snd_hac_i915_* to snd_hdac_acomp_*, respectively. The generic code is enabled via the new kconfig, CONFIG_SND_HDA_COMPONENT, while CONFIG_SND_HDA_I915 is kept as the super-class. Along with the split, three new callbacks are added to audio_ops: pin2port is for providing the conversion between the pin number and the widget id, and master_bind/master_unbin are called at binding / unbinding the master component, respectively. All these are optional, but used in i915 implementation and also other later implementations. A note about the new snd_hdac_acomp_init() function: there is a slight difference between this and the old snd_hdac_i915_init(). The latter (still) synchronizes with the master component binding, i.e. it assures that the relevant DRM component gets bound when it returns, or gives a negative error. Meanwhile the new function doesn't synchronize but just leaves as is. It's the responsibility by the caller's side to synchronize, or the caller may accept the asynchronous binding on the fly. v1->v2: Fix missing NULL check in master_bind/unbind Signed-off-by: Takashi Iwai --- drivers/gpu/drm/i915/Kconfig | 1 + include/drm/drm_audio_component.h | 23 +++ include/sound/hda_component.h | 61 +++++++ include/sound/hda_i915.h | 39 +---- sound/hda/Kconfig | 7 +- sound/hda/Makefile | 1 + sound/hda/hdac_component.c | 335 +++++++++++++++++++++++++++++++++++++ sound/hda/hdac_i915.c | 343 ++------------------------------------ sound/pci/hda/patch_hdmi.c | 50 ++++-- sound/soc/codecs/hdac_hdmi.c | 8 +- 10 files changed, 486 insertions(+), 382 deletions(-) create mode 100644 include/sound/hda_component.h create mode 100644 sound/hda/hdac_component.c (limited to 'sound') diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig index dfd95889f4b7..5c607f2c707b 100644 --- a/drivers/gpu/drm/i915/Kconfig +++ b/drivers/gpu/drm/i915/Kconfig @@ -23,6 +23,7 @@ config DRM_I915 select SYNC_FILE select IOSF_MBI select CRC32 + select SND_HDA_I915 if SND_HDA_CORE help Choose this option if you have a system that has "Intel Graphics Media Accelerator" or "HD Graphics" integrated graphics, diff --git a/include/drm/drm_audio_component.h b/include/drm/drm_audio_component.h index e85689f212c2..4923b00328c1 100644 --- a/include/drm/drm_audio_component.h +++ b/include/drm/drm_audio_component.h @@ -4,6 +4,8 @@ #ifndef _DRM_AUDIO_COMPONENT_H_ #define _DRM_AUDIO_COMPONENT_H_ +struct drm_audio_component; + /** * struct drm_audio_component_ops - Ops implemented by DRM driver, called by hda driver */ @@ -72,6 +74,27 @@ struct drm_audio_component_audio_ops { * mode). */ void (*pin_eld_notify)(void *audio_ptr, int port, int pipe); + /** + * @pin2port: Check and convert from pin node to port number + * + * Called by HDA driver to check and convert from the pin widget node + * number to a port number in the graphics side. + */ + int (*pin2port)(void *audio_ptr, int pin); + /** + * @master_bind: (Optional) component master bind callback + * + * Called at binding master component, for HDA codec-specific + * handling of dynamic binding. + */ + int (*master_bind)(struct device *dev, struct drm_audio_component *); + /** + * @master_unbind: (Optional) component master unbind callback + * + * Called at unbinding master component, for HDA codec-specific + * handling of dynamic unbinding. + */ + void (*master_unbind)(struct device *dev, struct drm_audio_component *); }; /** diff --git a/include/sound/hda_component.h b/include/sound/hda_component.h new file mode 100644 index 000000000000..78626cde7081 --- /dev/null +++ b/include/sound/hda_component.h @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: GPL-2.0 +// HD-Audio helpers to sync with DRM driver + +#ifndef __SOUND_HDA_COMPONENT_H +#define __SOUND_HDA_COMPONENT_H + +#include + +#ifdef CONFIG_SND_HDA_COMPONENT +int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable); +int snd_hdac_display_power(struct hdac_bus *bus, bool enable); +int snd_hdac_sync_audio_rate(struct hdac_device *codec, hda_nid_t nid, + int dev_id, int rate); +int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid, int dev_id, + bool *audio_enabled, char *buffer, int max_bytes); +int snd_hdac_acomp_init(struct hdac_bus *bus, + const struct drm_audio_component_audio_ops *aops, + int (*match_master)(struct device *, void *), + size_t extra_size); +int snd_hdac_acomp_exit(struct hdac_bus *bus); +int snd_hdac_acomp_register_notifier(struct hdac_bus *bus, + const struct drm_audio_component_audio_ops *ops); +#else +static inline int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable) +{ + return 0; +} +static inline int snd_hdac_display_power(struct hdac_bus *bus, bool enable) +{ + return 0; +} +static inline int snd_hdac_sync_audio_rate(struct hdac_device *codec, + hda_nid_t nid, int dev_id, int rate) +{ + return 0; +} +static inline int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid, + int dev_id, bool *audio_enabled, + char *buffer, int max_bytes) +{ + return -ENODEV; +} +static inline int snd_hdac_acomp_init(struct hdac_bus *bus, + const struct drm_audio_component_audio_ops *aops, + int (*match_master)(struct device *, void *), + size_t extra_size) +{ + return -ENODEV; +} +static inline int snd_hdac_acomp_exit(struct hdac_bus *bus) +{ + return 0; +} +static inline int snd_hdac_acomp_register_notifier(struct hdac_bus *bus, + const struct drm_audio_component_audio_ops *ops) +{ + return -ENODEV; +} +#endif + +#endif /* __SOUND_HDA_COMPONENT_H */ diff --git a/include/sound/hda_i915.h b/include/sound/hda_i915.h index 648263791559..6b79614a893b 100644 --- a/include/sound/hda_i915.h +++ b/include/sound/hda_i915.h @@ -5,56 +5,23 @@ #ifndef __SOUND_HDA_I915_H #define __SOUND_HDA_I915_H -#include +#include "hda_component.h" #ifdef CONFIG_SND_HDA_I915 -int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable); -int snd_hdac_display_power(struct hdac_bus *bus, bool enable); void snd_hdac_i915_set_bclk(struct hdac_bus *bus); -int snd_hdac_sync_audio_rate(struct hdac_device *codec, hda_nid_t nid, - int dev_id, int rate); -int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid, int dev_id, - bool *audio_enabled, char *buffer, int max_bytes); int snd_hdac_i915_init(struct hdac_bus *bus); -int snd_hdac_i915_exit(struct hdac_bus *bus); -int snd_hdac_i915_register_notifier(struct hdac_bus *bus, - const struct drm_audio_component_audio_ops *ops); #else -static inline int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable) -{ - return 0; -} -static inline int snd_hdac_display_power(struct hdac_bus *bus, bool enable) -{ - return 0; -} static inline void snd_hdac_i915_set_bclk(struct hdac_bus *bus) { } -static inline int snd_hdac_sync_audio_rate(struct hdac_device *codec, - hda_nid_t nid, int dev_id, int rate) -{ - return 0; -} -static inline int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid, - int dev_id, bool *audio_enabled, - char *buffer, int max_bytes) -{ - return -ENODEV; -} static inline int snd_hdac_i915_init(struct hdac_bus *bus) { return -ENODEV; } +#endif static inline int snd_hdac_i915_exit(struct hdac_bus *bus) { - return 0; + return snd_hdac_acomp_exit(bus); } -static inline int snd_hdac_i915_register_notifier(struct hdac_bus *bus, - const struct drm_audio_component_audio_ops *ops) -{ - return -ENODEV; -} -#endif #endif /* __SOUND_HDA_I915_H */ diff --git a/sound/hda/Kconfig b/sound/hda/Kconfig index 3129546398d0..2d90e11b3eaa 100644 --- a/sound/hda/Kconfig +++ b/sound/hda/Kconfig @@ -5,11 +5,12 @@ config SND_HDA_CORE config SND_HDA_DSP_LOADER bool +config SND_HDA_COMPONENT + bool + config SND_HDA_I915 bool - default y - depends on DRM_I915 - depends on SND_HDA_CORE + select SND_HDA_COMPONENT config SND_HDA_EXT_CORE tristate diff --git a/sound/hda/Makefile b/sound/hda/Makefile index e4e726f2ce98..2160202e2dc1 100644 --- a/sound/hda/Makefile +++ b/sound/hda/Makefile @@ -6,6 +6,7 @@ snd-hda-core-objs += trace.o CFLAGS_trace.o := -I$(src) # for sync with i915 gfx driver +snd-hda-core-$(CONFIG_SND_HDA_COMPONENT) += hdac_component.o snd-hda-core-$(CONFIG_SND_HDA_I915) += hdac_i915.o obj-$(CONFIG_SND_HDA_CORE) += snd-hda-core.o diff --git a/sound/hda/hdac_component.c b/sound/hda/hdac_component.c new file mode 100644 index 000000000000..6e46a9c73aed --- /dev/null +++ b/sound/hda/hdac_component.c @@ -0,0 +1,335 @@ +// SPDX-License-Identifier: GPL-2.0 +// hdac_component.c - routines for sync between HD-A core and DRM driver + +#include +#include +#include +#include +#include +#include +#include +#include + +static void hdac_acomp_release(struct device *dev, void *res) +{ +} + +static struct drm_audio_component *hdac_get_acomp(struct device *dev) +{ + return devres_find(dev, hdac_acomp_release, NULL, NULL); +} + +/** + * snd_hdac_set_codec_wakeup - Enable / disable HDMI/DP codec wakeup + * @bus: HDA core bus + * @enable: enable or disable the wakeup + * + * This function is supposed to be used only by a HD-audio controller + * driver that needs the interaction with graphics driver. + * + * This function should be called during the chip reset, also called at + * resume for updating STATESTS register read. + * + * Returns zero for success or a negative error code. + */ +int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable) +{ + struct drm_audio_component *acomp = bus->audio_component; + + if (!acomp || !acomp->ops) + return -ENODEV; + + if (!acomp->ops->codec_wake_override) + return 0; + + dev_dbg(bus->dev, "%s codec wakeup\n", + enable ? "enable" : "disable"); + + acomp->ops->codec_wake_override(acomp->dev, enable); + + return 0; +} +EXPORT_SYMBOL_GPL(snd_hdac_set_codec_wakeup); + +/** + * snd_hdac_display_power - Power up / down the power refcount + * @bus: HDA core bus + * @enable: power up or down + * + * This function is supposed to be used only by a HD-audio controller + * driver that needs the interaction with graphics driver. + * + * This function manages a refcount and calls the get_power() and + * put_power() ops accordingly, toggling the codec wakeup, too. + * + * Returns zero for success or a negative error code. + */ +int snd_hdac_display_power(struct hdac_bus *bus, bool enable) +{ + struct drm_audio_component *acomp = bus->audio_component; + + if (!acomp || !acomp->ops) + return -ENODEV; + + dev_dbg(bus->dev, "display power %s\n", + enable ? "enable" : "disable"); + + if (enable) { + if (!bus->drm_power_refcount++) { + if (acomp->ops->get_power) + acomp->ops->get_power(acomp->dev); + snd_hdac_set_codec_wakeup(bus, true); + snd_hdac_set_codec_wakeup(bus, false); + } + } else { + WARN_ON(!bus->drm_power_refcount); + if (!--bus->drm_power_refcount) + if (acomp->ops->put_power) + acomp->ops->put_power(acomp->dev); + } + + return 0; +} +EXPORT_SYMBOL_GPL(snd_hdac_display_power); + +/** + * snd_hdac_sync_audio_rate - Set N/CTS based on the sample rate + * @codec: HDA codec + * @nid: the pin widget NID + * @dev_id: device identifier + * @rate: the sample rate to set + * + * This function is supposed to be used only by a HD-audio controller + * driver that needs the interaction with graphics driver. + * + * This function sets N/CTS value based on the given sample rate. + * Returns zero for success, or a negative error code. + */ +int snd_hdac_sync_audio_rate(struct hdac_device *codec, hda_nid_t nid, + int dev_id, int rate) +{ + struct hdac_bus *bus = codec->bus; + struct drm_audio_component *acomp = bus->audio_component; + int port, pipe; + + if (!acomp || !acomp->ops || !acomp->ops->sync_audio_rate) + return -ENODEV; + port = nid; + if (acomp->audio_ops && acomp->audio_ops->pin2port) { + port = acomp->audio_ops->pin2port(codec, nid); + if (port < 0) + return -EINVAL; + } + pipe = dev_id; + return acomp->ops->sync_audio_rate(acomp->dev, port, pipe, rate); +} +EXPORT_SYMBOL_GPL(snd_hdac_sync_audio_rate); + +/** + * snd_hdac_acomp_get_eld - Get the audio state and ELD via component + * @codec: HDA codec + * @nid: the pin widget NID + * @dev_id: device identifier + * @audio_enabled: the pointer to store the current audio state + * @buffer: the buffer pointer to store ELD bytes + * @max_bytes: the max bytes to be stored on @buffer + * + * This function is supposed to be used only by a HD-audio controller + * driver that needs the interaction with graphics driver. + * + * This function queries the current state of the audio on the given + * digital port and fetches the ELD bytes onto the given buffer. + * It returns the number of bytes for the total ELD data, zero for + * invalid ELD, or a negative error code. + * + * The return size is the total bytes required for the whole ELD bytes, + * thus it may be over @max_bytes. If it's over @max_bytes, it implies + * that only a part of ELD bytes have been fetched. + */ +int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid, int dev_id, + bool *audio_enabled, char *buffer, int max_bytes) +{ + struct hdac_bus *bus = codec->bus; + struct drm_audio_component *acomp = bus->audio_component; + int port, pipe; + + if (!acomp || !acomp->ops || !acomp->ops->get_eld) + return -ENODEV; + + port = nid; + if (acomp->audio_ops && acomp->audio_ops->pin2port) { + port = acomp->audio_ops->pin2port(codec, nid); + if (port < 0) + return -EINVAL; + } + pipe = dev_id; + return acomp->ops->get_eld(acomp->dev, port, pipe, audio_enabled, + buffer, max_bytes); +} +EXPORT_SYMBOL_GPL(snd_hdac_acomp_get_eld); + +static int hdac_component_master_bind(struct device *dev) +{ + struct drm_audio_component *acomp = hdac_get_acomp(dev); + int ret; + + if (WARN_ON(!acomp)) + return -EINVAL; + + ret = component_bind_all(dev, acomp); + if (ret < 0) + return ret; + + if (WARN_ON(!(acomp->dev && acomp->ops))) { + ret = -EINVAL; + goto out_unbind; + } + + /* pin the module to avoid dynamic unbinding, but only if given */ + if (!try_module_get(acomp->ops->owner)) { + ret = -ENODEV; + goto out_unbind; + } + + if (acomp->audio_ops && acomp->audio_ops->master_bind) { + ret = acomp->audio_ops->master_bind(dev, acomp); + if (ret < 0) + goto module_put; + } + + return 0; + + module_put: + module_put(acomp->ops->owner); +out_unbind: + component_unbind_all(dev, acomp); + + return ret; +} + +static void hdac_component_master_unbind(struct device *dev) +{ + struct drm_audio_component *acomp = hdac_get_acomp(dev); + + if (acomp->audio_ops && acomp->audio_ops->master_unbind) + acomp->audio_ops->master_unbind(dev, acomp); + module_put(acomp->ops->owner); + component_unbind_all(dev, acomp); + WARN_ON(acomp->ops || acomp->dev); +} + +static const struct component_master_ops hdac_component_master_ops = { + .bind = hdac_component_master_bind, + .unbind = hdac_component_master_unbind, +}; + +/** + * snd_hdac_acomp_register_notifier - Register audio component ops + * @bus: HDA core bus + * @aops: audio component ops + * + * This function is supposed to be used only by a HD-audio controller + * driver that needs the interaction with graphics driver. + * + * This function sets the given ops to be called by the graphics driver. + * + * Returns zero for success or a negative error code. + */ +int snd_hdac_acomp_register_notifier(struct hdac_bus *bus, + const struct drm_audio_component_audio_ops *aops) +{ + if (!bus->audio_component) + return -ENODEV; + + bus->audio_component->audio_ops = aops; + return 0; +} +EXPORT_SYMBOL_GPL(snd_hdac_acomp_register_notifier); + +/** + * snd_hdac_acomp_init - Initialize audio component + * @bus: HDA core bus + * @match_master: match function for finding components + * @extra_size: Extra bytes to allocate + * + * This function is supposed to be used only by a HD-audio controller + * driver that needs the interaction with graphics driver. + * + * This function initializes and sets up the audio component to communicate + * with graphics driver. + * + * Unlike snd_hdac_i915_init(), this function doesn't synchronize with the + * binding with the DRM component. Each caller needs to sync via master_bind + * audio_ops. + * + * Returns zero for success or a negative error code. + */ +int snd_hdac_acomp_init(struct hdac_bus *bus, + const struct drm_audio_component_audio_ops *aops, + int (*match_master)(struct device *, void *), + size_t extra_size) +{ + struct component_match *match = NULL; + struct device *dev = bus->dev; + struct drm_audio_component *acomp; + int ret; + + if (WARN_ON(hdac_get_acomp(dev))) + return -EBUSY; + + acomp = devres_alloc(hdac_acomp_release, sizeof(*acomp) + extra_size, + GFP_KERNEL); + if (!acomp) + return -ENOMEM; + acomp->audio_ops = aops; + bus->audio_component = acomp; + devres_add(dev, acomp); + + component_match_add(dev, &match, match_master, bus); + ret = component_master_add_with_match(dev, &hdac_component_master_ops, + match); + if (ret < 0) + goto out_err; + + return 0; + +out_err: + bus->audio_component = NULL; + devres_destroy(dev, hdac_acomp_release, NULL, NULL); + dev_info(dev, "failed to add audio component master (%d)\n", ret); + + return ret; +} +EXPORT_SYMBOL_GPL(snd_hdac_acomp_init); + +/** + * snd_hdac_acomp_exit - Finalize audio component + * @bus: HDA core bus + * + * This function is supposed to be used only by a HD-audio controller + * driver that needs the interaction with graphics driver. + * + * This function releases the audio component that has been used. + * + * Returns zero for success or a negative error code. + */ +int snd_hdac_acomp_exit(struct hdac_bus *bus) +{ + struct device *dev = bus->dev; + struct drm_audio_component *acomp = bus->audio_component; + + if (!acomp) + return 0; + + WARN_ON(bus->drm_power_refcount); + if (bus->drm_power_refcount > 0 && acomp->ops) + acomp->ops->put_power(acomp->dev); + + component_master_del(dev, &hdac_component_master_ops); + + bus->audio_component = NULL; + devres_destroy(dev, hdac_acomp_release, NULL, NULL); + + return 0; +} +EXPORT_SYMBOL_GPL(snd_hdac_acomp_exit); diff --git a/sound/hda/hdac_i915.c b/sound/hda/hdac_i915.c index 861b77bbc7df..8f2aa8bc1185 100644 --- a/sound/hda/hdac_i915.c +++ b/sound/hda/hdac_i915.c @@ -15,96 +15,11 @@ #include #include #include -#include -#include #include #include #include #include -static void hdac_acomp_release(struct device *dev, void *res) -{ -} - -static struct drm_audio_component *hdac_get_acomp(struct device *dev) -{ - return devres_find(dev, hdac_acomp_release, NULL, NULL); -} - -/** - * snd_hdac_set_codec_wakeup - Enable / disable HDMI/DP codec wakeup - * @bus: HDA core bus - * @enable: enable or disable the wakeup - * - * This function is supposed to be used only by a HD-audio controller - * driver that needs the interaction with i915 graphics. - * - * This function should be called during the chip reset, also called at - * resume for updating STATESTS register read. - * - * Returns zero for success or a negative error code. - */ -int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable) -{ - struct drm_audio_component *acomp = bus->audio_component; - - if (!acomp || !acomp->ops) - return -ENODEV; - - if (!acomp->ops->codec_wake_override) { - dev_warn(bus->dev, - "Invalid codec wake callback\n"); - return 0; - } - - dev_dbg(bus->dev, "%s codec wakeup\n", - enable ? "enable" : "disable"); - - acomp->ops->codec_wake_override(acomp->dev, enable); - - return 0; -} -EXPORT_SYMBOL_GPL(snd_hdac_set_codec_wakeup); - -/** - * snd_hdac_display_power - Power up / down the power refcount - * @bus: HDA core bus - * @enable: power up or down - * - * This function is supposed to be used only by a HD-audio controller - * driver that needs the interaction with i915 graphics. - * - * This function manages a refcount and calls the i915 get_power() and - * put_power() ops accordingly, toggling the codec wakeup, too. - * - * Returns zero for success or a negative error code. - */ -int snd_hdac_display_power(struct hdac_bus *bus, bool enable) -{ - struct drm_audio_component *acomp = bus->audio_component; - - if (!acomp || !acomp->ops) - return -ENODEV; - - dev_dbg(bus->dev, "display power %s\n", - enable ? "enable" : "disable"); - - if (enable) { - if (!bus->drm_power_refcount++) { - acomp->ops->get_power(acomp->dev); - snd_hdac_set_codec_wakeup(bus, true); - snd_hdac_set_codec_wakeup(bus, false); - } - } else { - WARN_ON(!bus->drm_power_refcount); - if (!--bus->drm_power_refcount) - acomp->ops->put_power(acomp->dev); - } - - return 0; -} -EXPORT_SYMBOL_GPL(snd_hdac_display_power); - #define CONTROLLER_IN_GPU(pci) (((pci)->device == 0x0a0c) || \ ((pci)->device == 0x0c0c) || \ ((pci)->device == 0x0d0c) || \ @@ -165,183 +80,11 @@ void snd_hdac_i915_set_bclk(struct hdac_bus *bus) } EXPORT_SYMBOL_GPL(snd_hdac_i915_set_bclk); -/* There is a fixed mapping between audio pin node and display port. - * on SNB, IVY, HSW, BSW, SKL, BXT, KBL: - * Pin Widget 5 - PORT B (port = 1 in i915 driver) - * Pin Widget 6 - PORT C (port = 2 in i915 driver) - * Pin Widget 7 - PORT D (port = 3 in i915 driver) - * - * on VLV, ILK: - * Pin Widget 4 - PORT B (port = 1 in i915 driver) - * Pin Widget 5 - PORT C (port = 2 in i915 driver) - * Pin Widget 6 - PORT D (port = 3 in i915 driver) - */ -static int pin2port(struct hdac_device *codec, hda_nid_t pin_nid) -{ - int base_nid; - - switch (codec->vendor_id) { - case 0x80860054: /* ILK */ - case 0x80862804: /* ILK */ - case 0x80862882: /* VLV */ - base_nid = 3; - break; - default: - base_nid = 4; - break; - } - - if (WARN_ON(pin_nid <= base_nid || pin_nid > base_nid + 3)) - return -1; - return pin_nid - base_nid; -} - -/** - * snd_hdac_sync_audio_rate - Set N/CTS based on the sample rate - * @codec: HDA codec - * @nid: the pin widget NID - * @dev_id: device identifier - * @rate: the sample rate to set - * - * This function is supposed to be used only by a HD-audio controller - * driver that needs the interaction with i915 graphics. - * - * This function sets N/CTS value based on the given sample rate. - * Returns zero for success, or a negative error code. - */ -int snd_hdac_sync_audio_rate(struct hdac_device *codec, hda_nid_t nid, - int dev_id, int rate) +static int i915_component_master_match(struct device *dev, void *data) { - struct hdac_bus *bus = codec->bus; - struct drm_audio_component *acomp = bus->audio_component; - int port, pipe; - - if (!acomp || !acomp->ops || !acomp->ops->sync_audio_rate) - return -ENODEV; - port = pin2port(codec, nid); - if (port < 0) - return -EINVAL; - pipe = dev_id; - return acomp->ops->sync_audio_rate(acomp->dev, port, pipe, rate); -} -EXPORT_SYMBOL_GPL(snd_hdac_sync_audio_rate); - -/** - * snd_hdac_acomp_get_eld - Get the audio state and ELD via component - * @codec: HDA codec - * @nid: the pin widget NID - * @dev_id: device identifier - * @audio_enabled: the pointer to store the current audio state - * @buffer: the buffer pointer to store ELD bytes - * @max_bytes: the max bytes to be stored on @buffer - * - * This function is supposed to be used only by a HD-audio controller - * driver that needs the interaction with i915 graphics. - * - * This function queries the current state of the audio on the given - * digital port and fetches the ELD bytes onto the given buffer. - * It returns the number of bytes for the total ELD data, zero for - * invalid ELD, or a negative error code. - * - * The return size is the total bytes required for the whole ELD bytes, - * thus it may be over @max_bytes. If it's over @max_bytes, it implies - * that only a part of ELD bytes have been fetched. - */ -int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid, int dev_id, - bool *audio_enabled, char *buffer, int max_bytes) -{ - struct hdac_bus *bus = codec->bus; - struct drm_audio_component *acomp = bus->audio_component; - int port, pipe; - - if (!acomp || !acomp->ops || !acomp->ops->get_eld) - return -ENODEV; - - port = pin2port(codec, nid); - if (port < 0) - return -EINVAL; - - pipe = dev_id; - return acomp->ops->get_eld(acomp->dev, port, pipe, audio_enabled, - buffer, max_bytes); -} -EXPORT_SYMBOL_GPL(snd_hdac_acomp_get_eld); - -static int hdac_component_master_bind(struct device *dev) -{ - struct drm_audio_component *acomp = hdac_get_acomp(dev); - int ret; - - ret = component_bind_all(dev, acomp); - if (ret < 0) - return ret; - - if (WARN_ON(!(acomp->dev && acomp->ops && acomp->ops->get_power && - acomp->ops->put_power && acomp->ops->get_cdclk_freq))) { - ret = -EINVAL; - goto out_unbind; - } - - /* - * Atm, we don't support dynamic unbinding initiated by the child - * component, so pin its containing module until we unbind. - */ - if (!try_module_get(acomp->ops->owner)) { - ret = -ENODEV; - goto out_unbind; - } - - return 0; - -out_unbind: - component_unbind_all(dev, acomp); - - return ret; -} - -static void hdac_component_master_unbind(struct device *dev) -{ - struct drm_audio_component *acomp = hdac_get_acomp(dev); - - module_put(acomp->ops->owner); - component_unbind_all(dev, acomp); - WARN_ON(acomp->ops || acomp->dev); -} - -static const struct component_master_ops hdac_component_master_ops = { - .bind = hdac_component_master_bind, - .unbind = hdac_component_master_unbind, -}; - -static int hdac_component_master_match(struct device *dev, void *data) -{ - /* i915 is the only supported component */ return !strcmp(dev->driver->name, "i915"); } -/** - * snd_hdac_i915_register_notifier - Register i915 audio component ops - * @bus: HDA core bus - * @aops: i915 audio component ops - * - * This function is supposed to be used only by a HD-audio controller - * driver that needs the interaction with i915 graphics. - * - * This function sets the given ops to be called by the i915 graphics driver. - * - * Returns zero for success or a negative error code. - */ -int snd_hdac_i915_register_notifier(struct hdac_bus *bus, - const struct drm_audio_component_audio_ops *aops) -{ - if (!bus->audio_component) - return -ENODEV; - - bus->audio_component->audio_ops = aops; - return 0; -} -EXPORT_SYMBOL_GPL(snd_hdac_i915_register_notifier); - /* check whether intel graphics is present */ static bool i915_gfx_present(void) { @@ -368,84 +111,26 @@ static bool i915_gfx_present(void) */ int snd_hdac_i915_init(struct hdac_bus *bus) { - struct component_match *match = NULL; - struct device *dev = bus->dev; - struct i915_audio_component *i915_acomp; struct drm_audio_component *acomp; - int ret; - - if (WARN_ON(hdac_get_acomp(dev))) - return -EBUSY; + int err; if (!i915_gfx_present()) return -ENODEV; - i915_acomp = devres_alloc(hdac_acomp_release, sizeof(*i915_acomp), - GFP_KERNEL); - if (!i915_acomp) - return -ENOMEM; - acomp = &i915_acomp->base; - bus->audio_component = acomp; - devres_add(dev, acomp); - - component_match_add(dev, &match, hdac_component_master_match, bus); - ret = component_master_add_with_match(dev, &hdac_component_master_ops, - match); - if (ret < 0) - goto out_err; - - /* - * Atm, we don't support deferring the component binding, so make sure - * i915 is loaded and that the binding successfully completes. - */ - request_module("i915"); - + err = snd_hdac_acomp_init(bus, NULL, + i915_component_master_match, + sizeof(struct i915_audio_component) - sizeof(*acomp)); + if (err < 0) + return err; + acomp = bus->audio_component; + if (!acomp) + return -ENODEV; + if (!acomp->ops) + request_module("i915"); if (!acomp->ops) { - ret = -ENODEV; - goto out_master_del; + snd_hdac_acomp_exit(bus); + return -ENODEV; } - dev_dbg(dev, "bound to i915 component master\n"); - return 0; -out_master_del: - component_master_del(dev, &hdac_component_master_ops); -out_err: - bus->audio_component = NULL; - devres_destroy(dev, hdac_acomp_release, NULL, NULL); - dev_info(dev, "failed to add i915 component master (%d)\n", ret); - - return ret; } EXPORT_SYMBOL_GPL(snd_hdac_i915_init); - -/** - * snd_hdac_i915_exit - Finalize i915 audio component - * @bus: HDA core bus - * - * This function is supposed to be used only by a HD-audio controller - * driver that needs the interaction with i915 graphics. - * - * This function releases the i915 audio component that has been used. - * - * Returns zero for success or a negative error code. - */ -int snd_hdac_i915_exit(struct hdac_bus *bus) -{ - struct device *dev = bus->dev; - struct drm_audio_component *acomp = bus->audio_component; - - if (!acomp) - return 0; - - WARN_ON(bus->drm_power_refcount); - if (bus->drm_power_refcount > 0 && acomp->ops) - acomp->ops->put_power(acomp->dev); - - component_master_del(dev, &hdac_component_master_ops); - - bus->audio_component = NULL; - devres_destroy(dev, hdac_acomp_release, NULL, NULL); - - return 0; -} -EXPORT_SYMBOL_GPL(snd_hdac_i915_exit); diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index bf174a013f2d..1de5491fb9bf 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -183,7 +183,7 @@ struct hdmi_spec { hda_nid_t vendor_nid; }; -#ifdef CONFIG_SND_HDA_I915 +#ifdef CONFIG_SND_HDA_COMPONENT static inline bool codec_has_acomp(struct hda_codec *codec) { struct hdmi_spec *spec = codec->spec; @@ -2288,7 +2288,7 @@ static void generic_hdmi_free(struct hda_codec *codec) int pin_idx, pcm_idx; if (codec_has_acomp(codec)) - snd_hdac_i915_register_notifier(&codec->bus->core, NULL); + snd_hdac_acomp_register_notifier(&codec->bus->core, NULL); for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); @@ -2471,6 +2471,38 @@ static void haswell_set_power_state(struct hda_codec *codec, hda_nid_t fg, snd_hda_codec_set_power_to_all(codec, fg, power_state); } +/* There is a fixed mapping between audio pin node and display port. + * on SNB, IVY, HSW, BSW, SKL, BXT, KBL: + * Pin Widget 5 - PORT B (port = 1 in i915 driver) + * Pin Widget 6 - PORT C (port = 2 in i915 driver) + * Pin Widget 7 - PORT D (port = 3 in i915 driver) + * + * on VLV, ILK: + * Pin Widget 4 - PORT B (port = 1 in i915 driver) + * Pin Widget 5 - PORT C (port = 2 in i915 driver) + * Pin Widget 6 - PORT D (port = 3 in i915 driver) + */ +static int intel_base_nid(struct hda_codec *codec) +{ + switch (codec->core.vendor_id) { + case 0x80860054: /* ILK */ + case 0x80862804: /* ILK */ + case 0x80862882: /* VLV */ + return 4; + default: + return 5; + } +} + +static int intel_pin2port(void *audio_ptr, int pin_nid) +{ + int base_nid = intel_base_nid(audio_ptr); + + if (WARN_ON(pin_nid < base_nid || pin_nid >= base_nid + 3)) + return -1; + return pin_nid - base_nid + 1; /* intel port is 1-based */ +} + static void intel_pin_eld_notify(void *audio_ptr, int port, int pipe) { struct hda_codec *codec = audio_ptr; @@ -2481,16 +2513,7 @@ static void intel_pin_eld_notify(void *audio_ptr, int port, int pipe) if (port < 1 || port > 3) return; - switch (codec->core.vendor_id) { - case 0x80860054: /* ILK */ - case 0x80862804: /* ILK */ - case 0x80862882: /* VLV */ - pin_nid = port + 0x03; - break; - default: - pin_nid = port + 0x04; - break; - } + pin_nid = port + intel_base_nid(codec) - 1; /* intel port is 1-based */ /* skip notification during system suspend (but not in runtime PM); * the state will be updated at resume @@ -2517,8 +2540,9 @@ static void register_i915_notifier(struct hda_codec *codec) * We need make sure audio_ptr is really setup */ wmb(); + spec->drm_audio_ops.pin2port = intel_pin2port; spec->drm_audio_ops.pin_eld_notify = intel_pin_eld_notify; - snd_hdac_i915_register_notifier(&codec->bus->core, + snd_hdac_acomp_register_notifier(&codec->bus->core, &spec->drm_audio_ops); } diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index 2b7c33db4ded..4748a9d5de3b 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c @@ -1530,6 +1530,11 @@ free_widgets: return ret; } +static int hdac_hdmi_pin2port(void *aptr, int pin) +{ + return pin - 4; /* map NID 0x05 -> port #1 */ +} + static void hdac_hdmi_eld_notify_cb(void *aptr, int port, int pipe) { struct hdac_device *hdev = aptr; @@ -1584,6 +1589,7 @@ static void hdac_hdmi_eld_notify_cb(void *aptr, int port, int pipe) } static struct drm_audio_component_audio_ops aops = { + .pin2port = hdac_hdmi_pin2port, .pin_eld_notify = hdac_hdmi_eld_notify_cb, }; @@ -1812,7 +1818,7 @@ static int hdmi_codec_probe(struct snd_soc_component *component) return ret; aops.audio_ptr = hdev; - ret = snd_hdac_i915_register_notifier(hdev->bus, &aops); + ret = snd_hdac_acomp_register_notifier(hdev->bus, &aops); if (ret < 0) { dev_err(&hdev->dev, "notifier register failed: err: %d\n", ret); return ret; -- cgit v1.2.3 From 5bed9139727f3bad06c9444bd092336a59397e9d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 17 Jul 2018 22:32:52 +0200 Subject: ALSA: rawmidi: Tidy up coding styles Just minor coding style fixes like removal of superfluous white space, adding missing blank lines, etc. No actual code changes at all. Signed-off-by: Takashi Iwai --- sound/core/rawmidi.c | 101 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 59 insertions(+), 42 deletions(-) (limited to 'sound') diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index b53026a72e73..14dec13ecde9 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -88,6 +88,7 @@ static inline unsigned short snd_rawmidi_file_flags(struct file *file) static inline int snd_rawmidi_ready(struct snd_rawmidi_substream *substream) { struct snd_rawmidi_runtime *runtime = substream->runtime; + return runtime->avail >= runtime->avail_min; } @@ -95,6 +96,7 @@ static inline int snd_rawmidi_ready_append(struct snd_rawmidi_substream *substre size_t count) { struct snd_rawmidi_runtime *runtime = substream->runtime; + return runtime->avail >= runtime->avail_min && (!substream->append || runtime->avail >= count); } @@ -103,6 +105,7 @@ static void snd_rawmidi_input_event_work(struct work_struct *work) { struct snd_rawmidi_runtime *runtime = container_of(work, struct snd_rawmidi_runtime, event_work); + if (runtime->event) runtime->event(runtime->substream); } @@ -111,7 +114,8 @@ static int snd_rawmidi_runtime_create(struct snd_rawmidi_substream *substream) { struct snd_rawmidi_runtime *runtime; - if ((runtime = kzalloc(sizeof(*runtime), GFP_KERNEL)) == NULL) + runtime = kzalloc(sizeof(*runtime), GFP_KERNEL); + if (!runtime) return -ENOMEM; runtime->substream = substream; spin_lock_init(&runtime->lock); @@ -124,7 +128,8 @@ static int snd_rawmidi_runtime_create(struct snd_rawmidi_substream *substream) runtime->avail = 0; else runtime->avail = runtime->buffer_size; - if ((runtime->buffer = kmalloc(runtime->buffer_size, GFP_KERNEL)) == NULL) { + runtime->buffer = kmalloc(runtime->buffer_size, GFP_KERNEL); + if (!runtime->buffer) { kfree(runtime); return -ENOMEM; } @@ -143,7 +148,7 @@ static int snd_rawmidi_runtime_free(struct snd_rawmidi_substream *substream) return 0; } -static inline void snd_rawmidi_output_trigger(struct snd_rawmidi_substream *substream,int up) +static inline void snd_rawmidi_output_trigger(struct snd_rawmidi_substream *substream, int up) { if (!substream->opened) return; @@ -330,7 +335,7 @@ static int rawmidi_open_priv(struct snd_rawmidi *rmidi, int subdevice, int mode, /* called from sound/core/seq/seq_midi.c */ int snd_rawmidi_kernel_open(struct snd_card *card, int device, int subdevice, - int mode, struct snd_rawmidi_file * rfile) + int mode, struct snd_rawmidi_file *rfile) { struct snd_rawmidi *rmidi; int err; @@ -370,7 +375,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) struct snd_rawmidi_file *rawmidi_file = NULL; wait_queue_entry_t wait; - if ((file->f_flags & O_APPEND) && !(file->f_flags & O_NONBLOCK)) + if ((file->f_flags & O_APPEND) && !(file->f_flags & O_NONBLOCK)) return -EINVAL; /* invalid combination */ err = nonseekable_open(inode, file); @@ -520,7 +525,7 @@ int snd_rawmidi_kernel_release(struct snd_rawmidi_file *rfile) if (snd_BUG_ON(!rfile)) return -ENXIO; - + rmidi = rfile->rmidi; rawmidi_release_priv(rfile); module_put(rmidi->card->module); @@ -548,7 +553,7 @@ static int snd_rawmidi_info(struct snd_rawmidi_substream *substream, struct snd_rawmidi_info *info) { struct snd_rawmidi *rmidi; - + if (substream == NULL) return -ENODEV; rmidi = substream->rmidi; @@ -568,11 +573,13 @@ static int snd_rawmidi_info(struct snd_rawmidi_substream *substream, } static int snd_rawmidi_info_user(struct snd_rawmidi_substream *substream, - struct snd_rawmidi_info __user * _info) + struct snd_rawmidi_info __user *_info) { struct snd_rawmidi_info info; int err; - if ((err = snd_rawmidi_info(substream, &info)) < 0) + + err = snd_rawmidi_info(substream, &info); + if (err < 0) return err; if (copy_to_user(_info, &info, sizeof(struct snd_rawmidi_info))) return -EFAULT; @@ -619,13 +626,15 @@ static int snd_rawmidi_info_select_user(struct snd_card *card, { int err; struct snd_rawmidi_info info; + if (get_user(info.device, &_info->device)) return -EFAULT; if (get_user(info.stream, &_info->stream)) return -EFAULT; if (get_user(info.subdevice, &_info->subdevice)) return -EFAULT; - if ((err = snd_rawmidi_info_select(card, &info)) < 0) + err = snd_rawmidi_info_select(card, &info); + if (err < 0) return err; if (copy_to_user(_info, &info, sizeof(struct snd_rawmidi_info))) return -EFAULT; @@ -633,20 +642,18 @@ static int snd_rawmidi_info_select_user(struct snd_card *card, } int snd_rawmidi_output_params(struct snd_rawmidi_substream *substream, - struct snd_rawmidi_params * params) + struct snd_rawmidi_params *params) { char *newbuf, *oldbuf; struct snd_rawmidi_runtime *runtime = substream->runtime; - + if (substream->append && substream->use_count > 1) return -EBUSY; snd_rawmidi_drain_output(substream); - if (params->buffer_size < 32 || params->buffer_size > 1024L * 1024L) { + if (params->buffer_size < 32 || params->buffer_size > 1024L * 1024L) return -EINVAL; - } - if (params->avail_min < 1 || params->avail_min > params->buffer_size) { + if (params->avail_min < 1 || params->avail_min > params->buffer_size) return -EINVAL; - } if (params->buffer_size != runtime->buffer_size) { newbuf = kmalloc(params->buffer_size, GFP_KERNEL); if (!newbuf) @@ -667,18 +674,16 @@ int snd_rawmidi_output_params(struct snd_rawmidi_substream *substream, EXPORT_SYMBOL(snd_rawmidi_output_params); int snd_rawmidi_input_params(struct snd_rawmidi_substream *substream, - struct snd_rawmidi_params * params) + struct snd_rawmidi_params *params) { char *newbuf, *oldbuf; struct snd_rawmidi_runtime *runtime = substream->runtime; snd_rawmidi_drain_input(substream); - if (params->buffer_size < 32 || params->buffer_size > 1024L * 1024L) { + if (params->buffer_size < 32 || params->buffer_size > 1024L * 1024L) return -EINVAL; - } - if (params->avail_min < 1 || params->avail_min > params->buffer_size) { + if (params->avail_min < 1 || params->avail_min > params->buffer_size) return -EINVAL; - } if (params->buffer_size != runtime->buffer_size) { newbuf = kmalloc(params->buffer_size, GFP_KERNEL); if (!newbuf) @@ -697,7 +702,7 @@ int snd_rawmidi_input_params(struct snd_rawmidi_substream *substream, EXPORT_SYMBOL(snd_rawmidi_input_params); static int snd_rawmidi_output_status(struct snd_rawmidi_substream *substream, - struct snd_rawmidi_status * status) + struct snd_rawmidi_status *status) { struct snd_rawmidi_runtime *runtime = substream->runtime; @@ -710,7 +715,7 @@ static int snd_rawmidi_output_status(struct snd_rawmidi_substream *substream, } static int snd_rawmidi_input_status(struct snd_rawmidi_substream *substream, - struct snd_rawmidi_status * status) + struct snd_rawmidi_status *status) { struct snd_rawmidi_runtime *runtime = substream->runtime; @@ -739,6 +744,7 @@ static long snd_rawmidi_ioctl(struct file *file, unsigned int cmd, unsigned long { int stream; struct snd_rawmidi_info __user *info = argp; + if (get_user(stream, &info->stream)) return -EFAULT; switch (stream) { @@ -753,6 +759,7 @@ static long snd_rawmidi_ioctl(struct file *file, unsigned int cmd, unsigned long case SNDRV_RAWMIDI_IOCTL_PARAMS: { struct snd_rawmidi_params params; + if (copy_from_user(¶ms, argp, sizeof(struct snd_rawmidi_params))) return -EFAULT; switch (params.stream) { @@ -772,6 +779,7 @@ static long snd_rawmidi_ioctl(struct file *file, unsigned int cmd, unsigned long { int err = 0; struct snd_rawmidi_status status; + if (copy_from_user(&status, argp, sizeof(struct snd_rawmidi_status))) return -EFAULT; switch (status.stream) { @@ -797,6 +805,7 @@ static long snd_rawmidi_ioctl(struct file *file, unsigned int cmd, unsigned long case SNDRV_RAWMIDI_IOCTL_DROP: { int val; + if (get_user(val, (int __user *) argp)) return -EFAULT; switch (val) { @@ -811,6 +820,7 @@ static long snd_rawmidi_ioctl(struct file *file, unsigned int cmd, unsigned long case SNDRV_RAWMIDI_IOCTL_DRAIN: { int val; + if (get_user(val, (int __user *) argp)) return -EFAULT; switch (val) { @@ -844,7 +854,7 @@ static int snd_rawmidi_control_ioctl(struct snd_card *card, case SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE: { int device; - + if (get_user(device, (int __user *)argp)) return -EFAULT; if (device >= SNDRV_RAWMIDI_DEVICES) /* next device is -1 */ @@ -866,7 +876,7 @@ static int snd_rawmidi_control_ioctl(struct snd_card *card, case SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE: { int val; - + if (get_user(val, (int __user *)argp)) return -EFAULT; control->preferred_subdevice[SND_CTL_SUBDEV_RAWMIDI] = val; @@ -1020,6 +1030,7 @@ static ssize_t snd_rawmidi_read(struct file *file, char __user *buf, size_t coun spin_lock_irq(&runtime->lock); while (!snd_rawmidi_ready(substream)) { wait_queue_entry_t wait; + if ((file->f_flags & O_NONBLOCK) != 0 || result > 0) { spin_unlock_irq(&runtime->lock); return result > 0 ? result : -EAGAIN; @@ -1072,7 +1083,7 @@ int snd_rawmidi_transmit_empty(struct snd_rawmidi_substream *substream) spin_lock_irqsave(&runtime->lock, flags); result = runtime->avail >= runtime->buffer_size; spin_unlock_irqrestore(&runtime->lock, flags); - return result; + return result; } EXPORT_SYMBOL(snd_rawmidi_transmit_empty); @@ -1210,7 +1221,7 @@ EXPORT_SYMBOL(snd_rawmidi_transmit_ack); * @substream: the rawmidi substream * @buffer: the buffer pointer * @count: the data size to transfer - * + * * Copies data from the buffer to the device and advances the pointer. * * Return: The copied size if successful, or a negative error code on failure. @@ -1324,6 +1335,7 @@ static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf, spin_lock_irq(&runtime->lock); while (!snd_rawmidi_ready_append(substream, count)) { wait_queue_entry_t wait; + if (file->f_flags & O_NONBLOCK) { spin_unlock_irq(&runtime->lock); return result > 0 ? result : -EAGAIN; @@ -1357,6 +1369,7 @@ static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf, while (runtime->avail != runtime->buffer_size) { wait_queue_entry_t wait; unsigned int last_avail = runtime->avail; + init_waitqueue_entry(&wait, current); add_wait_queue(&runtime->sleep, &wait); set_current_state(TASK_INTERRUPTIBLE); @@ -1374,7 +1387,7 @@ static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf, return result; } -static __poll_t snd_rawmidi_poll(struct file *file, poll_table * wait) +static __poll_t snd_rawmidi_poll(struct file *file, poll_table *wait) { struct snd_rawmidi_file *rfile; struct snd_rawmidi_runtime *runtime; @@ -1411,7 +1424,6 @@ static __poll_t snd_rawmidi_poll(struct file *file, poll_table * wait) #endif /* - */ static void snd_rawmidi_proc_info_read(struct snd_info_entry *entry, @@ -1479,8 +1491,7 @@ static void snd_rawmidi_proc_info_read(struct snd_info_entry *entry, * Register functions */ -static const struct file_operations snd_rawmidi_f_ops = -{ +static const struct file_operations snd_rawmidi_f_ops = { .owner = THIS_MODULE, .read = snd_rawmidi_read, .write = snd_rawmidi_write, @@ -1535,7 +1546,7 @@ static void release_rawmidi_device(struct device *dev) */ int snd_rawmidi_new(struct snd_card *card, char *id, int device, int output_count, int input_count, - struct snd_rawmidi ** rrawmidi) + struct snd_rawmidi **rrawmidi) { struct snd_rawmidi *rmidi; int err; @@ -1566,21 +1577,24 @@ int snd_rawmidi_new(struct snd_card *card, char *id, int device, rmidi->dev.release = release_rawmidi_device; dev_set_name(&rmidi->dev, "midiC%iD%i", card->number, device); - if ((err = snd_rawmidi_alloc_substreams(rmidi, - &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT], - SNDRV_RAWMIDI_STREAM_INPUT, - input_count)) < 0) { + err = snd_rawmidi_alloc_substreams(rmidi, + &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT], + SNDRV_RAWMIDI_STREAM_INPUT, + input_count); + if (err < 0) { snd_rawmidi_free(rmidi); return err; } - if ((err = snd_rawmidi_alloc_substreams(rmidi, - &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT], - SNDRV_RAWMIDI_STREAM_OUTPUT, - output_count)) < 0) { + err = snd_rawmidi_alloc_substreams(rmidi, + &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT], + SNDRV_RAWMIDI_STREAM_OUTPUT, + output_count); + if (err < 0) { snd_rawmidi_free(rmidi); return err; } - if ((err = snd_device_new(card, SNDRV_DEV_RAWMIDI, rmidi, &ops)) < 0) { + err = snd_device_new(card, SNDRV_DEV_RAWMIDI, rmidi, &ops); + if (err < 0) { snd_rawmidi_free(rmidi); return err; } @@ -1624,6 +1638,7 @@ static int snd_rawmidi_free(struct snd_rawmidi *rmidi) static int snd_rawmidi_dev_free(struct snd_device *device) { struct snd_rawmidi *rmidi = device->device_data; + return snd_rawmidi_free(rmidi); } @@ -1631,6 +1646,7 @@ static int snd_rawmidi_dev_free(struct snd_device *device) static void snd_rawmidi_dev_seq_free(struct snd_seq_device *device) { struct snd_rawmidi *rmidi = device->private_data; + rmidi->seq_dev = NULL; } #endif @@ -1732,6 +1748,7 @@ static int snd_rawmidi_dev_disconnect(struct snd_device *device) list_del_init(&rmidi->list); for (dir = 0; dir < 2; dir++) { struct snd_rawmidi_substream *s; + list_for_each_entry(s, &rmidi->streams[dir].substreams, list) { if (s->runtime) wake_up(&s->runtime->sleep); @@ -1769,7 +1786,7 @@ void snd_rawmidi_set_ops(struct snd_rawmidi *rmidi, int stream, const struct snd_rawmidi_ops *ops) { struct snd_rawmidi_substream *substream; - + list_for_each_entry(substream, &rmidi->streams[stream].substreams, list) substream->ops = ops; } -- cgit v1.2.3 From 7fdc9b08071b6a3fc85bf90b79e13f6e973a7e5e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 17 Jul 2018 22:45:50 +0200 Subject: ALSA: rawmidi: Simplify error paths Apply the standard idiom: rewrite the multiple unlocks in error paths in the goto-error-and-single-unlock way. Just a code refactoring, and no functional changes. Signed-off-by: Takashi Iwai --- sound/core/rawmidi.c | 76 +++++++++++++++++++++++++++------------------------- 1 file changed, 39 insertions(+), 37 deletions(-) (limited to 'sound') diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index 14dec13ecde9..6b24c2d2dae6 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -338,22 +338,20 @@ int snd_rawmidi_kernel_open(struct snd_card *card, int device, int subdevice, int mode, struct snd_rawmidi_file *rfile) { struct snd_rawmidi *rmidi; - int err; + int err = 0; if (snd_BUG_ON(!rfile)) return -EINVAL; mutex_lock(®ister_mutex); rmidi = snd_rawmidi_search(card, device); - if (rmidi == NULL) { - mutex_unlock(®ister_mutex); - return -ENODEV; - } - if (!try_module_get(rmidi->card->module)) { - mutex_unlock(®ister_mutex); - return -ENXIO; - } + if (!rmidi) + err = -ENODEV; + else if (!try_module_get(rmidi->card->module)) + err = -ENXIO; mutex_unlock(®ister_mutex); + if (err < 0) + return err; mutex_lock(&rmidi->open_mutex); err = rawmidi_open_priv(rmidi, subdevice, mode, rfile); @@ -1581,26 +1579,25 @@ int snd_rawmidi_new(struct snd_card *card, char *id, int device, &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT], SNDRV_RAWMIDI_STREAM_INPUT, input_count); - if (err < 0) { - snd_rawmidi_free(rmidi); - return err; - } + if (err < 0) + goto error; err = snd_rawmidi_alloc_substreams(rmidi, &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT], SNDRV_RAWMIDI_STREAM_OUTPUT, output_count); - if (err < 0) { - snd_rawmidi_free(rmidi); - return err; - } + if (err < 0) + goto error; err = snd_device_new(card, SNDRV_DEV_RAWMIDI, rmidi, &ops); - if (err < 0) { - snd_rawmidi_free(rmidi); - return err; - } + if (err < 0) + goto error; + if (rrawmidi) *rrawmidi = rmidi; return 0; + + error: + snd_rawmidi_free(rmidi); + return err; } EXPORT_SYMBOL(snd_rawmidi_new); @@ -1660,30 +1657,27 @@ static int snd_rawmidi_dev_register(struct snd_device *device) if (rmidi->device >= SNDRV_RAWMIDI_DEVICES) return -ENOMEM; + err = 0; mutex_lock(®ister_mutex); - if (snd_rawmidi_search(rmidi->card, rmidi->device)) { - mutex_unlock(®ister_mutex); - return -EBUSY; - } - list_add_tail(&rmidi->list, &snd_rawmidi_devices); + if (snd_rawmidi_search(rmidi->card, rmidi->device)) + err = -EBUSY; + else + list_add_tail(&rmidi->list, &snd_rawmidi_devices); mutex_unlock(®ister_mutex); + if (err < 0) + return err; + err = snd_register_device(SNDRV_DEVICE_TYPE_RAWMIDI, rmidi->card, rmidi->device, &snd_rawmidi_f_ops, rmidi, &rmidi->dev); if (err < 0) { rmidi_err(rmidi, "unable to register\n"); - mutex_lock(®ister_mutex); - list_del(&rmidi->list); - mutex_unlock(®ister_mutex); - return err; + goto error; } - if (rmidi->ops && rmidi->ops->dev_register && - (err = rmidi->ops->dev_register(rmidi)) < 0) { - snd_unregister_device(&rmidi->dev); - mutex_lock(®ister_mutex); - list_del(&rmidi->list); - mutex_unlock(®ister_mutex); - return err; + if (rmidi->ops && rmidi->ops->dev_register) { + err = rmidi->ops->dev_register(rmidi); + if (err < 0) + goto error_unregister; } #ifdef CONFIG_SND_OSSEMUL rmidi->ossreg = 0; @@ -1735,6 +1729,14 @@ static int snd_rawmidi_dev_register(struct snd_device *device) } #endif return 0; + + error_unregister: + snd_unregister_device(&rmidi->dev); + error: + mutex_lock(®ister_mutex); + list_del(&rmidi->list); + mutex_unlock(®ister_mutex); + return err; } static int snd_rawmidi_dev_disconnect(struct snd_device *device) -- cgit v1.2.3 From f5beb598b0c4dd023833ae1a7c188ecd987b7125 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 17 Jul 2018 23:07:29 +0200 Subject: ALSA: rawmidi: Minor code refactoring Unify a few open codes with helper functions to improve the readability. Minor behavior changes (rather fixes) are: - runtime->drain clearance is done within lock - active_sensing is updated before resizing buffer in SNDRV_RAWMIDI_IOCTL_PARAMS ioctl. Other than that, simply code cleanups. Signed-off-by: Takashi Iwai --- sound/core/rawmidi.c | 77 ++++++++++++++++++++++------------------------------ 1 file changed, 33 insertions(+), 44 deletions(-) (limited to 'sound') diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index 6b24c2d2dae6..cc944a3637a2 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -164,17 +164,28 @@ static void snd_rawmidi_input_trigger(struct snd_rawmidi_substream *substream, i cancel_work_sync(&substream->runtime->event_work); } -int snd_rawmidi_drop_output(struct snd_rawmidi_substream *substream) +static void __reset_runtime_ptrs(struct snd_rawmidi_runtime *runtime, + bool is_input) +{ + runtime->drain = 0; + runtime->appl_ptr = runtime->hw_ptr = 0; + runtime->avail = is_input ? 0 : runtime->buffer_size; +} + +static void reset_runtime_ptrs(struct snd_rawmidi_runtime *runtime, + bool is_input) { unsigned long flags; - struct snd_rawmidi_runtime *runtime = substream->runtime; - snd_rawmidi_output_trigger(substream, 0); - runtime->drain = 0; spin_lock_irqsave(&runtime->lock, flags); - runtime->appl_ptr = runtime->hw_ptr = 0; - runtime->avail = runtime->buffer_size; + __reset_runtime_ptrs(runtime, is_input); spin_unlock_irqrestore(&runtime->lock, flags); +} + +int snd_rawmidi_drop_output(struct snd_rawmidi_substream *substream) +{ + snd_rawmidi_output_trigger(substream, 0); + reset_runtime_ptrs(substream->runtime, false); return 0; } EXPORT_SYMBOL(snd_rawmidi_drop_output); @@ -213,15 +224,8 @@ EXPORT_SYMBOL(snd_rawmidi_drain_output); int snd_rawmidi_drain_input(struct snd_rawmidi_substream *substream) { - unsigned long flags; - struct snd_rawmidi_runtime *runtime = substream->runtime; - snd_rawmidi_input_trigger(substream, 0); - runtime->drain = 0; - spin_lock_irqsave(&runtime->lock, flags); - runtime->appl_ptr = runtime->hw_ptr = 0; - runtime->avail = 0; - spin_unlock_irqrestore(&runtime->lock, flags); + reset_runtime_ptrs(substream->runtime, true); return 0; } EXPORT_SYMBOL(snd_rawmidi_drain_input); @@ -639,15 +643,12 @@ static int snd_rawmidi_info_select_user(struct snd_card *card, return 0; } -int snd_rawmidi_output_params(struct snd_rawmidi_substream *substream, - struct snd_rawmidi_params *params) +static int resize_runtime_buffer(struct snd_rawmidi_runtime *runtime, + struct snd_rawmidi_params *params, + bool is_input) { char *newbuf, *oldbuf; - struct snd_rawmidi_runtime *runtime = substream->runtime; - if (substream->append && substream->use_count > 1) - return -EBUSY; - snd_rawmidi_drain_output(substream); if (params->buffer_size < 32 || params->buffer_size > 1024L * 1024L) return -EINVAL; if (params->avail_min < 1 || params->avail_min > params->buffer_size) @@ -660,42 +661,30 @@ int snd_rawmidi_output_params(struct snd_rawmidi_substream *substream, oldbuf = runtime->buffer; runtime->buffer = newbuf; runtime->buffer_size = params->buffer_size; - runtime->avail = runtime->buffer_size; - runtime->appl_ptr = runtime->hw_ptr = 0; + __reset_runtime_ptrs(runtime, is_input); spin_unlock_irq(&runtime->lock); kfree(oldbuf); } runtime->avail_min = params->avail_min; - substream->active_sensing = !params->no_active_sensing; return 0; } + +int snd_rawmidi_output_params(struct snd_rawmidi_substream *substream, + struct snd_rawmidi_params *params) +{ + if (substream->append && substream->use_count > 1) + return -EBUSY; + snd_rawmidi_drain_output(substream); + substream->active_sensing = !params->no_active_sensing; + return resize_runtime_buffer(substream->runtime, params, false); +} EXPORT_SYMBOL(snd_rawmidi_output_params); int snd_rawmidi_input_params(struct snd_rawmidi_substream *substream, struct snd_rawmidi_params *params) { - char *newbuf, *oldbuf; - struct snd_rawmidi_runtime *runtime = substream->runtime; - snd_rawmidi_drain_input(substream); - if (params->buffer_size < 32 || params->buffer_size > 1024L * 1024L) - return -EINVAL; - if (params->avail_min < 1 || params->avail_min > params->buffer_size) - return -EINVAL; - if (params->buffer_size != runtime->buffer_size) { - newbuf = kmalloc(params->buffer_size, GFP_KERNEL); - if (!newbuf) - return -ENOMEM; - spin_lock_irq(&runtime->lock); - oldbuf = runtime->buffer; - runtime->buffer = newbuf; - runtime->buffer_size = params->buffer_size; - runtime->appl_ptr = runtime->hw_ptr = 0; - spin_unlock_irq(&runtime->lock); - kfree(oldbuf); - } - runtime->avail_min = params->avail_min; - return 0; + return resize_runtime_buffer(substream->runtime, params, true); } EXPORT_SYMBOL(snd_rawmidi_input_params); -- cgit v1.2.3 From ef4db239cda2d74f53120e223643b0f5bbf947c1 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 17 Jul 2018 23:12:33 +0200 Subject: ALSA: rawmidi: Use kvmalloc() for buffers The size of in-kernel rawmidi buffers may be big up to 1MB, and it can be specified freely by user-space; which implies that user-space may trigger kmalloc() errors frequently. This patch replaces the buffer allocation via kvmalloc() for dealing with bigger buffers gracefully. Signed-off-by: Takashi Iwai --- sound/core/rawmidi.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index cc944a3637a2..69517e18ef07 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -128,7 +129,7 @@ static int snd_rawmidi_runtime_create(struct snd_rawmidi_substream *substream) runtime->avail = 0; else runtime->avail = runtime->buffer_size; - runtime->buffer = kmalloc(runtime->buffer_size, GFP_KERNEL); + runtime->buffer = kvmalloc(runtime->buffer_size, GFP_KERNEL); if (!runtime->buffer) { kfree(runtime); return -ENOMEM; @@ -142,7 +143,7 @@ static int snd_rawmidi_runtime_free(struct snd_rawmidi_substream *substream) { struct snd_rawmidi_runtime *runtime = substream->runtime; - kfree(runtime->buffer); + kvfree(runtime->buffer); kfree(runtime); substream->runtime = NULL; return 0; @@ -654,7 +655,7 @@ static int resize_runtime_buffer(struct snd_rawmidi_runtime *runtime, if (params->avail_min < 1 || params->avail_min > params->buffer_size) return -EINVAL; if (params->buffer_size != runtime->buffer_size) { - newbuf = kmalloc(params->buffer_size, GFP_KERNEL); + newbuf = kvmalloc(params->buffer_size, GFP_KERNEL); if (!newbuf) return -ENOMEM; spin_lock_irq(&runtime->lock); @@ -663,7 +664,7 @@ static int resize_runtime_buffer(struct snd_rawmidi_runtime *runtime, runtime->buffer_size = params->buffer_size; __reset_runtime_ptrs(runtime, is_input); spin_unlock_irq(&runtime->lock); - kfree(oldbuf); + kvfree(oldbuf); } runtime->avail_min = params->avail_min; return 0; -- cgit v1.2.3 From fa84cf094ef9667e2b91c104b0a788fd1896f482 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 18 Jul 2018 07:40:53 +0200 Subject: ALSA: pcm: Nuke snd_pcm_lib_mmap_vmalloc() snd_pcm_lib_mmap_vmalloc() was supposed to be implemented with somewhat special for vmalloc handling, but in the end, this turned to just the default handler, i.e. NULL. As the situation has never changed over decades, let's rip it off. Reviewed-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- drivers/staging/most/sound/sound.c | 1 - include/sound/pcm.h | 2 -- sound/drivers/aloop.c | 1 - sound/drivers/vx/vx_pcm.c | 2 -- sound/firewire/bebob/bebob_pcm.c | 1 - sound/firewire/dice/dice-pcm.c | 2 -- sound/firewire/digi00x/digi00x-pcm.c | 1 - sound/firewire/fireface/ff-pcm.c | 1 - sound/firewire/fireworks/fireworks_pcm.c | 1 - sound/firewire/isight.c | 1 - sound/firewire/motu/motu-pcm.c | 2 -- sound/firewire/oxfw/oxfw-pcm.c | 2 -- sound/firewire/tascam/tascam-pcm.c | 1 - sound/mips/sgio2audio.c | 3 --- sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c | 1 - sound/soc/codecs/rt5514-spi.c | 1 - sound/usb/6fire/pcm.c | 1 - sound/usb/caiaq/audio.c | 1 - sound/usb/hiface/pcm.c | 1 - sound/usb/misc/ua101.c | 2 -- sound/usb/pcm.c | 2 -- 21 files changed, 30 deletions(-) (limited to 'sound') diff --git a/drivers/staging/most/sound/sound.c b/drivers/staging/most/sound/sound.c index 04c18323c2ea..89b02fc305b8 100644 --- a/drivers/staging/most/sound/sound.c +++ b/drivers/staging/most/sound/sound.c @@ -457,7 +457,6 @@ static const struct snd_pcm_ops pcm_ops = { .trigger = pcm_trigger, .pointer = pcm_pointer, .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, }; static int split_arg_list(char *buf, char **card_name, u16 *ch_num, diff --git a/include/sound/pcm.h b/include/sound/pcm.h index fcdf358a25f0..1206045ccf03 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -1342,8 +1342,6 @@ int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream, struct vm_area_s #define snd_pcm_lib_mmap_iomem NULL #endif -#define snd_pcm_lib_mmap_vmalloc NULL - /** * snd_pcm_limit_isa_dma_size - Get the max size fitting with ISA DMA transfer * @dma: DMA number diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c index 78a2fdc38531..1e34e6381baa 100644 --- a/sound/drivers/aloop.c +++ b/sound/drivers/aloop.c @@ -778,7 +778,6 @@ static const struct snd_pcm_ops loopback_pcm_ops = { .trigger = loopback_trigger, .pointer = loopback_pointer, .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, }; static int loopback_pcm_new(struct loopback *loopback, diff --git a/sound/drivers/vx/vx_pcm.c b/sound/drivers/vx/vx_pcm.c index 380a028469c4..ba80f459bdc5 100644 --- a/sound/drivers/vx/vx_pcm.c +++ b/sound/drivers/vx/vx_pcm.c @@ -883,7 +883,6 @@ static const struct snd_pcm_ops vx_pcm_playback_ops = { .trigger = vx_pcm_trigger, .pointer = vx_pcm_playback_pointer, .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, }; @@ -1105,7 +1104,6 @@ static const struct snd_pcm_ops vx_pcm_capture_ops = { .trigger = vx_pcm_trigger, .pointer = vx_pcm_capture_pointer, .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, }; diff --git a/sound/firewire/bebob/bebob_pcm.c b/sound/firewire/bebob/bebob_pcm.c index e6adab3ef42e..ea9b86450580 100644 --- a/sound/firewire/bebob/bebob_pcm.c +++ b/sound/firewire/bebob/bebob_pcm.c @@ -373,7 +373,6 @@ int snd_bebob_create_pcm_devices(struct snd_bebob *bebob) .pointer = pcm_playback_pointer, .ack = pcm_playback_ack, .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, }; struct snd_pcm *pcm; int err; diff --git a/sound/firewire/dice/dice-pcm.c b/sound/firewire/dice/dice-pcm.c index 80351b29fe0d..bb3ef5ff3488 100644 --- a/sound/firewire/dice/dice-pcm.c +++ b/sound/firewire/dice/dice-pcm.c @@ -412,7 +412,6 @@ int snd_dice_create_pcm(struct snd_dice *dice) .pointer = capture_pointer, .ack = capture_ack, .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, }; static const struct snd_pcm_ops playback_ops = { .open = pcm_open, @@ -425,7 +424,6 @@ int snd_dice_create_pcm(struct snd_dice *dice) .pointer = playback_pointer, .ack = playback_ack, .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, }; struct snd_pcm *pcm; unsigned int capture, playback; diff --git a/sound/firewire/digi00x/digi00x-pcm.c b/sound/firewire/digi00x/digi00x-pcm.c index 796f4b4645f5..fdcff0460c53 100644 --- a/sound/firewire/digi00x/digi00x-pcm.c +++ b/sound/firewire/digi00x/digi00x-pcm.c @@ -352,7 +352,6 @@ int snd_dg00x_create_pcm_devices(struct snd_dg00x *dg00x) .pointer = pcm_playback_pointer, .ack = pcm_playback_ack, .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, }; struct snd_pcm *pcm; int err; diff --git a/sound/firewire/fireface/ff-pcm.c b/sound/firewire/fireface/ff-pcm.c index e3c16308363d..bf47f9ec8703 100644 --- a/sound/firewire/fireface/ff-pcm.c +++ b/sound/firewire/fireface/ff-pcm.c @@ -383,7 +383,6 @@ int snd_ff_create_pcm_devices(struct snd_ff *ff) .pointer = pcm_playback_pointer, .ack = pcm_playback_ack, .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, }; struct snd_pcm *pcm; int err; diff --git a/sound/firewire/fireworks/fireworks_pcm.c b/sound/firewire/fireworks/fireworks_pcm.c index 40faed5e6968..aed566d82726 100644 --- a/sound/firewire/fireworks/fireworks_pcm.c +++ b/sound/firewire/fireworks/fireworks_pcm.c @@ -397,7 +397,6 @@ int snd_efw_create_pcm_devices(struct snd_efw *efw) .pointer = pcm_playback_pointer, .ack = pcm_playback_ack, .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, }; struct snd_pcm *pcm; int err; diff --git a/sound/firewire/isight.c b/sound/firewire/isight.c index 3919e186a30b..30957477e005 100644 --- a/sound/firewire/isight.c +++ b/sound/firewire/isight.c @@ -454,7 +454,6 @@ static int isight_create_pcm(struct isight *isight) .trigger = isight_trigger, .pointer = isight_pointer, .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, }; struct snd_pcm *pcm; int err; diff --git a/sound/firewire/motu/motu-pcm.c b/sound/firewire/motu/motu-pcm.c index 4330220890e8..ab69d7e6ac05 100644 --- a/sound/firewire/motu/motu-pcm.c +++ b/sound/firewire/motu/motu-pcm.c @@ -363,7 +363,6 @@ int snd_motu_create_pcm_devices(struct snd_motu *motu) .pointer = capture_pointer, .ack = capture_ack, .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, }; static const struct snd_pcm_ops playback_ops = { .open = pcm_open, @@ -376,7 +375,6 @@ int snd_motu_create_pcm_devices(struct snd_motu *motu) .pointer = playback_pointer, .ack = playback_ack, .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, }; struct snd_pcm *pcm; int err; diff --git a/sound/firewire/oxfw/oxfw-pcm.c b/sound/firewire/oxfw/oxfw-pcm.c index 3dd46285c0e2..b3f6503dd34d 100644 --- a/sound/firewire/oxfw/oxfw-pcm.c +++ b/sound/firewire/oxfw/oxfw-pcm.c @@ -389,7 +389,6 @@ int snd_oxfw_create_pcm(struct snd_oxfw *oxfw) .pointer = pcm_capture_pointer, .ack = pcm_capture_ack, .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, }; static const struct snd_pcm_ops playback_ops = { .open = pcm_open, @@ -402,7 +401,6 @@ int snd_oxfw_create_pcm(struct snd_oxfw *oxfw) .pointer = pcm_playback_pointer, .ack = pcm_playback_ack, .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, }; struct snd_pcm *pcm; unsigned int cap = 0; diff --git a/sound/firewire/tascam/tascam-pcm.c b/sound/firewire/tascam/tascam-pcm.c index 6ec8ec634d4d..e4cc8990e195 100644 --- a/sound/firewire/tascam/tascam-pcm.c +++ b/sound/firewire/tascam/tascam-pcm.c @@ -279,7 +279,6 @@ int snd_tscm_create_pcm_devices(struct snd_tscm *tscm) .pointer = pcm_playback_pointer, .ack = pcm_playback_ack, .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, }; struct snd_pcm *pcm; int err; diff --git a/sound/mips/sgio2audio.c b/sound/mips/sgio2audio.c index 9fb68b35de5a..3ec9391a4736 100644 --- a/sound/mips/sgio2audio.c +++ b/sound/mips/sgio2audio.c @@ -685,7 +685,6 @@ static const struct snd_pcm_ops snd_sgio2audio_playback1_ops = { .trigger = snd_sgio2audio_pcm_trigger, .pointer = snd_sgio2audio_pcm_pointer, .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, }; static const struct snd_pcm_ops snd_sgio2audio_playback2_ops = { @@ -698,7 +697,6 @@ static const struct snd_pcm_ops snd_sgio2audio_playback2_ops = { .trigger = snd_sgio2audio_pcm_trigger, .pointer = snd_sgio2audio_pcm_pointer, .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, }; static const struct snd_pcm_ops snd_sgio2audio_capture_ops = { @@ -711,7 +709,6 @@ static const struct snd_pcm_ops snd_sgio2audio_capture_ops = { .trigger = snd_sgio2audio_pcm_trigger, .pointer = snd_sgio2audio_pcm_pointer, .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, }; /* diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c b/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c index 4a2354b5ae00..98a6863e933c 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c @@ -276,7 +276,6 @@ static const struct snd_pcm_ops pdacf_pcm_capture_ops = { .trigger = pdacf_pcm_trigger, .pointer = pdacf_pcm_capture_pointer, .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, }; diff --git a/sound/soc/codecs/rt5514-spi.c b/sound/soc/codecs/rt5514-spi.c index 18686ffb0cd5..6478d10c4f4a 100644 --- a/sound/soc/codecs/rt5514-spi.c +++ b/sound/soc/codecs/rt5514-spi.c @@ -268,7 +268,6 @@ static const struct snd_pcm_ops rt5514_spi_pcm_ops = { .hw_params = rt5514_spi_hw_params, .hw_free = rt5514_spi_hw_free, .pointer = rt5514_spi_pcm_pointer, - .mmap = snd_pcm_lib_mmap_vmalloc, .page = snd_pcm_lib_get_vmalloc_page, }; diff --git a/sound/usb/6fire/pcm.c b/sound/usb/6fire/pcm.c index 2dd2518a71d3..f8ef3e2a8ca0 100644 --- a/sound/usb/6fire/pcm.c +++ b/sound/usb/6fire/pcm.c @@ -565,7 +565,6 @@ static const struct snd_pcm_ops pcm_ops = { .trigger = usb6fire_pcm_trigger, .pointer = usb6fire_pcm_pointer, .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, }; static void usb6fire_pcm_init_urb(struct pcm_urb *urb, diff --git a/sound/usb/caiaq/audio.c b/sound/usb/caiaq/audio.c index 15344d39a6cd..c6108a3d7f8f 100644 --- a/sound/usb/caiaq/audio.c +++ b/sound/usb/caiaq/audio.c @@ -348,7 +348,6 @@ static const struct snd_pcm_ops snd_usb_caiaq_ops = { .trigger = snd_usb_caiaq_pcm_trigger, .pointer = snd_usb_caiaq_pcm_pointer, .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, }; static void check_for_elapsed_periods(struct snd_usb_caiaqdev *cdev, diff --git a/sound/usb/hiface/pcm.c b/sound/usb/hiface/pcm.c index 396c317115b1..e1fbb9cc9ea7 100644 --- a/sound/usb/hiface/pcm.c +++ b/sound/usb/hiface/pcm.c @@ -523,7 +523,6 @@ static const struct snd_pcm_ops pcm_ops = { .trigger = hiface_pcm_trigger, .pointer = hiface_pcm_pointer, .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, }; static int hiface_pcm_init_urb(struct pcm_urb *urb, diff --git a/sound/usb/misc/ua101.c b/sound/usb/misc/ua101.c index 386fbfd5c617..a0b6d039017f 100644 --- a/sound/usb/misc/ua101.c +++ b/sound/usb/misc/ua101.c @@ -900,7 +900,6 @@ static const struct snd_pcm_ops capture_pcm_ops = { .trigger = capture_pcm_trigger, .pointer = capture_pcm_pointer, .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, }; static const struct snd_pcm_ops playback_pcm_ops = { @@ -913,7 +912,6 @@ static const struct snd_pcm_ops playback_pcm_ops = { .trigger = playback_pcm_trigger, .pointer = playback_pcm_pointer, .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, }; static const struct uac_format_type_i_discrete_descriptor * diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 160f52c4871b..4b930fa47277 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -1694,7 +1694,6 @@ static const struct snd_pcm_ops snd_usb_playback_ops = { .trigger = snd_usb_substream_playback_trigger, .pointer = snd_usb_pcm_pointer, .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, }; static const struct snd_pcm_ops snd_usb_capture_ops = { @@ -1707,7 +1706,6 @@ static const struct snd_pcm_ops snd_usb_capture_ops = { .trigger = snd_usb_substream_capture_trigger, .pointer = snd_usb_pcm_pointer, .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, }; static const struct snd_pcm_ops snd_usb_playback_dev_ops = { -- cgit v1.2.3 From 58cabe8715f20b7fb33431bb1f2c5bd7a438b11b Mon Sep 17 00:00:00 2001 From: Adam Goode Date: Wed, 18 Jul 2018 16:41:05 -0400 Subject: ALSA: usb-audio: Allow changing from a bad sample rate If the audio device is externally clocked and set to a rate that does not match the external clock, the clock will never be valid and we cannot set the rate successfully. To fix this, allow a rate change even if the clock is initially invalid, and validate again after the rate is changed. This fixes problems with MOTU UltraLite AVB hardware over USB. Signed-off-by: Adam Goode Signed-off-by: Takashi Iwai --- sound/usb/clock.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/usb/clock.c b/sound/usb/clock.c index c79749613fa6..db5e39d67a90 100644 --- a/sound/usb/clock.c +++ b/sound/usb/clock.c @@ -513,14 +513,28 @@ static int set_sample_rate_v2v3(struct snd_usb_audio *chip, int iface, bool writeable; u32 bmControls; + /* First, try to find a valid clock. This may trigger + * automatic clock selection if the current clock is not + * valid. + */ clock = snd_usb_clock_find_source(chip, fmt->protocol, fmt->clock, true); - if (clock < 0) - return clock; + if (clock < 0) { + /* We did not find a valid clock, but that might be + * because the current sample rate does not match an + * external clock source. Try again without validation + * and we will do another validation after setting the + * rate. + */ + clock = snd_usb_clock_find_source(chip, fmt->protocol, + fmt->clock, false); + if (clock < 0) + return clock; + } prev_rate = get_sample_rate_v2v3(chip, iface, fmt->altsetting, clock); if (prev_rate == rate) - return 0; + goto validation; if (fmt->protocol == UAC_VERSION_3) { struct uac3_clock_source_descriptor *cs_desc; @@ -577,6 +591,10 @@ static int set_sample_rate_v2v3(struct snd_usb_audio *chip, int iface, snd_usb_set_interface_quirk(dev); } +validation: + /* validate clock after rate change */ + if (!uac_clock_source_is_valid(chip, fmt->protocol, clock)) + return -ENXIO; return 0; } -- cgit v1.2.3 From d10ee9c542365bdc0a7497306e21ff6c7f2172b0 Mon Sep 17 00:00:00 2001 From: Srikanth K H Date: Fri, 20 Jul 2018 11:13:51 +0530 Subject: ALSA: timer: catch invalid timer object creation A timer object for the classes SNDRV_TIMER_CLASS_CARD and SNDRV_TIMER_CLASS_PCM has to be associated with a card object, but we have no check at creation time. Such a timer object with NULL card causes various unexpected problems, e.g. NULL dereference at reading the sound timer proc file. So as preventive measure while the creating the sound timer object is created the card information availability is checked for the mentioned entries and returned error if its NULL. Signed-off-by: Srikanth K H Signed-off-by: Takashi Iwai --- sound/core/timer.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'sound') diff --git a/sound/core/timer.c b/sound/core/timer.c index b6f076bbc72d..61a0cec6e1f6 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -883,6 +883,11 @@ int snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid, if (snd_BUG_ON(!tid)) return -EINVAL; + if (tid->dev_class == SNDRV_TIMER_CLASS_CARD || + tid->dev_class == SNDRV_TIMER_CLASS_PCM) { + if (WARN_ON(!card)) + return -EINVAL; + } if (rtimer) *rtimer = NULL; timer = kzalloc(sizeof(*timer), GFP_KERNEL); -- cgit v1.2.3 From 1ea0358ecb848058b35b6da13d7f4c08610a73a8 Mon Sep 17 00:00:00 2001 From: Yue Wang Date: Mon, 23 Jul 2018 01:56:46 -0700 Subject: ALSA: usb-audio: Generic DSD detection for Thesycon-based implementations Thesycon provides solutions to XMOS chips, and has its own device vendor id. In this patch, we use generic method to detect DSD capability of Thesycon-based UAC2 implementations in order to support a wide range of current and future devices. The patch will enable the SNDRV_PCM_FMTBIT_DSD_U32_BE bit for the DAC hence enable native DSD playback up to DSD512 format. Signed-off-by: Yue Wang Signed-off-by: Takashi Iwai --- sound/usb/quirks.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound') diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 02b6cc02767f..06ae3f5adf4b 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -1443,6 +1443,7 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip, */ switch (USB_ID_VENDOR(chip->usb_id)) { case 0x20b1: /* XMOS based devices */ + case 0x152a: /* Thesycon devices */ case 0x25ce: /* Mytek devices */ if (fp->dsd_raw) return SNDRV_PCM_FMTBIT_DSD_U32_BE; -- cgit v1.2.3 From f9b54e1961c7052e7d7817d707826eb2b9a1ca09 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 11 Jul 2018 15:05:06 +0200 Subject: ALSA: hda/i915: Allow delayed i915 audio component binding Currently HD-audio i915 audio binding doesn't support any delayed binding, and supposes that the i915 driver registers the component immediately. This has been OK, so far, but the work-in-progress change in i915 may introduce the asynchronous binding, which effectively delays the component registration. For addressing it, implement a completion to be synced with the master binding. The timeout is set to 10 seconds which should be long enough and hopefully be not too annoying if anyone boots up a debugging session with i915 KMS turned off. Signed-off-by: Takashi Iwai --- sound/hda/hdac_i915.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/hda/hdac_i915.c b/sound/hda/hdac_i915.c index 8f2aa8bc1185..b5282cbbe489 100644 --- a/sound/hda/hdac_i915.c +++ b/sound/hda/hdac_i915.c @@ -20,6 +20,8 @@ #include #include +static struct completion bind_complete; + #define CONTROLLER_IN_GPU(pci) (((pci)->device == 0x0a0c) || \ ((pci)->device == 0x0c0c) || \ ((pci)->device == 0x0d0c) || \ @@ -97,6 +99,19 @@ static bool i915_gfx_present(void) return pci_dev_present(ids); } +static int i915_master_bind(struct device *dev, + struct drm_audio_component *acomp) +{ + complete_all(&bind_complete); + /* clear audio_ops here as it was needed only for completion call */ + acomp->audio_ops = NULL; + return 0; +} + +static const struct drm_audio_component_audio_ops i915_init_ops = { + .master_bind = i915_master_bind +}; + /** * snd_hdac_i915_init - Initialize i915 audio component * @bus: HDA core bus @@ -117,7 +132,9 @@ int snd_hdac_i915_init(struct hdac_bus *bus) if (!i915_gfx_present()) return -ENODEV; - err = snd_hdac_acomp_init(bus, NULL, + init_completion(&bind_complete); + + err = snd_hdac_acomp_init(bus, &i915_init_ops, i915_component_master_match, sizeof(struct i915_audio_component) - sizeof(*acomp)); if (err < 0) @@ -125,8 +142,11 @@ int snd_hdac_i915_init(struct hdac_bus *bus) acomp = bus->audio_component; if (!acomp) return -ENODEV; - if (!acomp->ops) + if (!acomp->ops) { request_module("i915"); + /* 10s timeout */ + wait_for_completion_timeout(&bind_complete, 10 * 1000); + } if (!acomp->ops) { snd_hdac_acomp_exit(bus); return -ENODEV; -- cgit v1.2.3 From b080dc5bd0dfc0b33c6cfc31f909c93d5e63c186 Mon Sep 17 00:00:00 2001 From: Jeff Crukley Date: Wed, 25 Jul 2018 15:05:01 -0400 Subject: ALSA: usb-audio: Add support for Encore mDSD USB DAC This patch adds native DSD playback support for the Encore mDSD USB DAC by specifying the vendor and product ID's Signed-off-by: Jeff Crukley Signed-off-by: Takashi Iwai --- sound/usb/quirks.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound') diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 06ae3f5adf4b..dde87d64bc32 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -1373,6 +1373,7 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip, return SNDRV_PCM_FMTBIT_DSD_U32_BE; break; + case USB_ID(0x16d0, 0x09dd): /* Encore mDSD */ case USB_ID(0x0d8c, 0x0316): /* Hegel HD12 DSD */ case USB_ID(0x16b0, 0x06b2): /* NuPrime DAC-10 */ case USB_ID(0x16d0, 0x0733): /* Furutech ADL Stratos */ -- cgit v1.2.3 From bd1cd0eb2ce9141100628d476ead4de485501b29 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 25 Jul 2018 23:00:46 +0200 Subject: ALSA: usb-audio: Fix multiple definitions in AU0828_DEVICE() macro AU0828_DEVICE() macro in quirks-table.h uses USB_DEVICE_VENDOR_SPEC() for expanding idVendor and idProduct fields. However, the latter macro adds also match_flags and bInterfaceClass, which are different from the values AU0828_DEVICE() macro sets after that. For fixing them, just expand idVendor and idProduct fields manually in AU0828_DEVICE(). This fixes sparse warnings like: sound/usb/quirks-table.h:2892:1: warning: Initializer entry defined twice Signed-off-by: Takashi Iwai --- sound/usb/quirks-table.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index 8aac48f9c322..08aa78007020 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -2875,7 +2875,8 @@ YAMAHA_DEVICE(0x7010, "UB99"), */ #define AU0828_DEVICE(vid, pid, vname, pname) { \ - USB_DEVICE_VENDOR_SPEC(vid, pid), \ + .idVendor = vid, \ + .idProduct = pid, \ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \ USB_DEVICE_ID_MATCH_INT_CLASS | \ USB_DEVICE_ID_MATCH_INT_SUBCLASS, \ -- cgit v1.2.3 From ab647a2d62f70cf45d7c64bf9f1574b8c52406e4 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 25 Jul 2018 23:00:47 +0200 Subject: ALSA: msnd: Add missing __iomem annotations The io-mapped buffers used in msnd drivers need __iomem annotations. This fixes sparse warnings like: sound/isa/msnd/msnd_pinnacle.c:172:45: warning: incorrect type in initializer (different address spaces) Signed-off-by: Takashi Iwai --- sound/isa/msnd/msnd.c | 18 +++++++++--------- sound/isa/msnd/msnd.h | 2 +- sound/isa/msnd/msnd_midi.c | 2 +- sound/isa/msnd/msnd_pinnacle.c | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) (limited to 'sound') diff --git a/sound/isa/msnd/msnd.c b/sound/isa/msnd/msnd.c index 569897f64fda..7c3203fe4869 100644 --- a/sound/isa/msnd/msnd.c +++ b/sound/isa/msnd/msnd.c @@ -54,7 +54,7 @@ #define LOGNAME "msnd" -void snd_msnd_init_queue(void *base, int start, int size) +void snd_msnd_init_queue(void __iomem *base, int start, int size) { writew(PCTODSP_BASED(start), base + JQS_wStart); writew(PCTODSP_OFFSET(size) - 1, base + JQS_wSize); @@ -270,7 +270,7 @@ int snd_msnd_DARQ(struct snd_msnd *chip, int bank) udelay(1); if (chip->capturePeriods == 2) { - void *pDAQ = chip->mappedbase + DARQ_DATA_BUFF + + void __iomem *pDAQ = chip->mappedbase + DARQ_DATA_BUFF + bank * DAQDS__size + DAQDS_wStart; unsigned short offset = 0x3000 + chip->capturePeriodBytes; @@ -309,7 +309,7 @@ int snd_msnd_DAPQ(struct snd_msnd *chip, int start) { u16 DAPQ_tail; int protect = start, nbanks = 0; - void *DAQD; + void __iomem *DAQD; static int play_banks_submitted; /* unsigned long flags; spin_lock_irqsave(&chip->lock, flags); not necessary */ @@ -370,7 +370,7 @@ static void snd_msnd_play_reset_queue(struct snd_msnd *chip, unsigned int pcm_count) { int n; - void *pDAQ = chip->mappedbase + DAPQ_DATA_BUFF; + void __iomem *pDAQ = chip->mappedbase + DAPQ_DATA_BUFF; chip->last_playbank = -1; chip->playLimit = pcm_count * (pcm_periods - 1); @@ -398,7 +398,7 @@ static void snd_msnd_capture_reset_queue(struct snd_msnd *chip, unsigned int pcm_count) { int n; - void *pDAQ; + void __iomem *pDAQ; /* unsigned long flags; */ /* snd_msnd_init_queue(chip->DARQ, DARQ_DATA_BUFF, DARQ_BUFF_SIZE); */ @@ -485,7 +485,7 @@ static int snd_msnd_playback_open(struct snd_pcm_substream *substream) clear_bit(F_WRITING, &chip->flags); snd_msnd_enable_irq(chip); - runtime->dma_area = chip->mappedbase; + runtime->dma_area = (__force void *)chip->mappedbase; runtime->dma_bytes = 0x3000; chip->playback_substream = substream; @@ -508,7 +508,7 @@ static int snd_msnd_playback_hw_params(struct snd_pcm_substream *substream, { int i; struct snd_msnd *chip = snd_pcm_substream_chip(substream); - void *pDAQ = chip->mappedbase + DAPQ_DATA_BUFF; + void __iomem *pDAQ = chip->mappedbase + DAPQ_DATA_BUFF; chip->play_sample_size = snd_pcm_format_width(params_format(params)); chip->play_channels = params_channels(params); @@ -589,7 +589,7 @@ static int snd_msnd_capture_open(struct snd_pcm_substream *substream) set_bit(F_AUDIO_READ_INUSE, &chip->flags); snd_msnd_enable_irq(chip); - runtime->dma_area = chip->mappedbase + 0x3000; + runtime->dma_area = (__force void *)chip->mappedbase + 0x3000; runtime->dma_bytes = 0x3000; memset(runtime->dma_area, 0, runtime->dma_bytes); chip->capture_substream = substream; @@ -654,7 +654,7 @@ static int snd_msnd_capture_hw_params(struct snd_pcm_substream *substream, { int i; struct snd_msnd *chip = snd_pcm_substream_chip(substream); - void *pDAQ = chip->mappedbase + DARQ_DATA_BUFF; + void __iomem *pDAQ = chip->mappedbase + DARQ_DATA_BUFF; chip->capture_sample_size = snd_pcm_format_width(params_format(params)); chip->capture_channels = params_channels(params); diff --git a/sound/isa/msnd/msnd.h b/sound/isa/msnd/msnd.h index 5f3c7dcd9f9d..80c718757eef 100644 --- a/sound/isa/msnd/msnd.h +++ b/sound/isa/msnd/msnd.h @@ -283,7 +283,7 @@ struct snd_msnd { }; -void snd_msnd_init_queue(void *base, int start, int size); +void snd_msnd_init_queue(void __iomem *base, int start, int size); int snd_msnd_send_dsp_cmd(struct snd_msnd *chip, u8 cmd); int snd_msnd_send_word(struct snd_msnd *chip, diff --git a/sound/isa/msnd/msnd_midi.c b/sound/isa/msnd/msnd_midi.c index 013d8d1170fe..42876b0cb68b 100644 --- a/sound/isa/msnd/msnd_midi.c +++ b/sound/isa/msnd/msnd_midi.c @@ -119,7 +119,7 @@ void snd_msndmidi_input_read(void *mpuv) { unsigned long flags; struct snd_msndmidi *mpu = mpuv; - void *pwMIDQData = mpu->dev->mappedbase + MIDQ_DATA_BUFF; + void __iomem *pwMIDQData = mpu->dev->mappedbase + MIDQ_DATA_BUFF; u16 head, tail, size; spin_lock_irqsave(&mpu->input_lock, flags); diff --git a/sound/isa/msnd/msnd_pinnacle.c b/sound/isa/msnd/msnd_pinnacle.c index 6c584d9b6c42..642609f7eda9 100644 --- a/sound/isa/msnd/msnd_pinnacle.c +++ b/sound/isa/msnd/msnd_pinnacle.c @@ -169,7 +169,7 @@ static void snd_msnd_eval_dsp_msg(struct snd_msnd *chip, u16 wMessage) static irqreturn_t snd_msnd_interrupt(int irq, void *dev_id) { struct snd_msnd *chip = dev_id; - void *pwDSPQData = chip->mappedbase + DSPQ_DATA_BUFF; + void __iomem *pwDSPQData = chip->mappedbase + DSPQ_DATA_BUFF; u16 head, tail, size; /* Send ack to DSP */ -- cgit v1.2.3 From 7c500f9ea139d0c9b80fdea5a9c911db3166ea54 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 25 Jul 2018 23:00:48 +0200 Subject: ALSA: msnd: Fix the default sample sizes The default sample sizes set by msnd driver are bogus; it sets ALSA PCM format, not the actual bit width. Signed-off-by: Takashi Iwai --- sound/isa/msnd/msnd_pinnacle.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/isa/msnd/msnd_pinnacle.c b/sound/isa/msnd/msnd_pinnacle.c index 642609f7eda9..7e3f52c8a6c6 100644 --- a/sound/isa/msnd/msnd_pinnacle.c +++ b/sound/isa/msnd/msnd_pinnacle.c @@ -82,10 +82,10 @@ static void set_default_audio_parameters(struct snd_msnd *chip) { - chip->play_sample_size = DEFSAMPLESIZE; + chip->play_sample_size = snd_pcm_format_width(DEFSAMPLESIZE); chip->play_sample_rate = DEFSAMPLERATE; chip->play_channels = DEFCHANNELS; - chip->capture_sample_size = DEFSAMPLESIZE; + chip->capture_sample_size = snd_pcm_format_width(DEFSAMPLESIZE); chip->capture_sample_rate = DEFSAMPLERATE; chip->capture_channels = DEFCHANNELS; } -- cgit v1.2.3 From bb86124c80780d9d2a2d9bef7f0840e61007ebb7 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 25 Jul 2018 23:00:49 +0200 Subject: ALSA: hda/ca0132 - Use NULL instead of 0 Use NULL for initializing the snd_kcontrol_new.tlv field, instead of 0, as warned by sparse: sound/pci/hda/patch_ca0132.c:5519:22: warning: Using plain integer as NULL pointer Also, the driver does the same initialization twice, once for knew.tlv.c and another for knew.tlv.p while both point to the same address (these are union). Drop the latter superfluous one. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_ca0132.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 321e95c409c1..27d3388cd2a2 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -5516,8 +5516,7 @@ static int ca0132_alt_add_effect_slider(struct hda_codec *codec, hda_nid_t nid, sprintf(namestr, "FX: %s %s Volume", pfx, dirstr[dir]); - knew.tlv.c = 0; - knew.tlv.p = 0; + knew.tlv.c = NULL; switch (nid) { case XBASS_XOVER: -- cgit v1.2.3 From dcda6f7853c52c42d242b474bfbd1d17d02c8870 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 25 Jul 2018 23:00:50 +0200 Subject: ALSA: msnd: Use NULL instead of 0 Fix a sparse warning: sound/isa/msnd/msnd_pinnacle.c:813:1: warning: Using plain integer as NULL pointer Signed-off-by: Takashi Iwai --- sound/isa/msnd/msnd_pinnacle.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/isa/msnd/msnd_pinnacle.c b/sound/isa/msnd/msnd_pinnacle.c index 7e3f52c8a6c6..11af9c40bc05 100644 --- a/sound/isa/msnd/msnd_pinnacle.c +++ b/sound/isa/msnd/msnd_pinnacle.c @@ -810,7 +810,7 @@ module_param(calibrate_signal, int, 0444); #ifndef MSND_CLASSIC module_param_array(digital, int, NULL, 0444); module_param_hw_array(cfg, long, ioport, NULL, 0444); -module_param_array(reset, int, 0, 0444); +module_param_array(reset, int, NULL, 0444); module_param_hw_array(mpu_io, long, ioport, NULL, 0444); module_param_hw_array(mpu_irq, int, irq, NULL, 0444); module_param_hw_array(ide_io0, long, ioport, NULL, 0444); -- cgit v1.2.3 From ebd836edfc4324da016ce0c09f809f882a133f50 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 25 Jul 2018 23:00:51 +0200 Subject: ALSA: hda - Fix a sparse warning about snd_ctl_elem_iface_t The knew->iface field is in snd_ctl_elem_iface_t, which is with __bitwise, hence it can't be converted implicitly from integer. Give an explicit cast for the invalid type. Spotted by sparse: sound/pci/hda/hda_codec.c:3280:25: warning: restricted snd_ctl_elem_iface_t degrades to integer Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 6d0c0b143270..0a5085537034 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -3277,8 +3277,8 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, for (; knew->name; knew++) { struct snd_kcontrol *kctl; int addr = 0, idx = 0; - if (knew->iface == -1) /* skip this codec private value */ - continue; + if (knew->iface == (__force snd_ctl_elem_iface_t)-1) + continue; /* skip this codec private value */ for (;;) { kctl = snd_ctl_new1(knew, codec); if (!kctl) -- cgit v1.2.3 From 7e9c20f40304a16d5f69dbdc44a551cc48252266 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 25 Jul 2018 23:00:52 +0200 Subject: ALSA: opl3: Declare common variables properly Move the declarations of common variables into opl3_voice.h instead of declaring at each file multiple times, which was error-prone. This fixes sparse warnings like: sound/drivers/opl3/opl3_synth.c:51:6: warning: symbol 'snd_opl3_regmap' was not declared. Should it be static? Signed-off-by: Takashi Iwai --- sound/drivers/opl3/opl3_drums.c | 2 -- sound/drivers/opl3/opl3_lib.c | 3 +-- sound/drivers/opl3/opl3_midi.c | 4 ---- sound/drivers/opl3/opl3_oss.c | 2 -- sound/drivers/opl3/opl3_synth.c | 1 + sound/drivers/opl3/opl3_voice.h | 4 ++++ 6 files changed, 6 insertions(+), 10 deletions(-) (limited to 'sound') diff --git a/sound/drivers/opl3/opl3_drums.c b/sound/drivers/opl3/opl3_drums.c index 73694380734a..14929822956c 100644 --- a/sound/drivers/opl3/opl3_drums.c +++ b/sound/drivers/opl3/opl3_drums.c @@ -21,8 +21,6 @@ #include "opl3_voice.h" -extern char snd_opl3_regmap[MAX_OPL2_VOICES][4]; - static char snd_opl3_drum_table[47] = { OPL3_BASSDRUM_ON, OPL3_BASSDRUM_ON, OPL3_HIHAT_ON, /* 35 - 37 */ diff --git a/sound/drivers/opl3/opl3_lib.c b/sound/drivers/opl3/opl3_lib.c index 588963d6be28..1a5355b747ec 100644 --- a/sound/drivers/opl3/opl3_lib.c +++ b/sound/drivers/opl3/opl3_lib.c @@ -31,13 +31,12 @@ #include #include #include +#include "opl3_voice.h" MODULE_AUTHOR("Jaroslav Kysela , Hannu Savolainen 1993-1996, Rob Hooft"); MODULE_DESCRIPTION("Routines for control of AdLib FM cards (OPL2/OPL3/OPL4 chips)"); MODULE_LICENSE("GPL"); -extern char snd_opl3_regmap[MAX_OPL2_VOICES][4]; - static void snd_opl2_command(struct snd_opl3 * opl3, unsigned short cmd, unsigned char val) { unsigned long flags; diff --git a/sound/drivers/opl3/opl3_midi.c b/sound/drivers/opl3/opl3_midi.c index 71cd5a2fbe82..471916ca0b6b 100644 --- a/sound/drivers/opl3/opl3_midi.c +++ b/sound/drivers/opl3/opl3_midi.c @@ -25,10 +25,6 @@ #include "opl3_voice.h" #include -extern char snd_opl3_regmap[MAX_OPL2_VOICES][4]; - -extern bool use_internal_drums; - static void snd_opl3_note_off_unsafe(void *p, int note, int vel, struct snd_midi_channel *chan); /* diff --git a/sound/drivers/opl3/opl3_oss.c b/sound/drivers/opl3/opl3_oss.c index 8a0ce3f43f42..869220ced4ed 100644 --- a/sound/drivers/opl3/opl3_oss.c +++ b/sound/drivers/opl3/opl3_oss.c @@ -29,8 +29,6 @@ static int snd_opl3_reset_seq_oss(struct snd_seq_oss_arg *arg); /* operators */ -extern struct snd_midi_op opl3_ops; - static struct snd_seq_oss_callback oss_callback = { .owner = THIS_MODULE, .open = snd_opl3_open_seq_oss, diff --git a/sound/drivers/opl3/opl3_synth.c b/sound/drivers/opl3/opl3_synth.c index 42920a243328..d522925fc5c0 100644 --- a/sound/drivers/opl3/opl3_synth.c +++ b/sound/drivers/opl3/opl3_synth.c @@ -24,6 +24,7 @@ #include #include #include +#include "opl3_voice.h" #if IS_ENABLED(CONFIG_SND_SEQUENCER) #define OPL3_SUPPORT_SYNTH diff --git a/sound/drivers/opl3/opl3_voice.h b/sound/drivers/opl3/opl3_voice.h index a2445163008e..5b02bd49fde4 100644 --- a/sound/drivers/opl3/opl3_voice.h +++ b/sound/drivers/opl3/opl3_voice.h @@ -52,4 +52,8 @@ void snd_opl3_free_seq_oss(struct snd_opl3 *opl3); #define snd_opl3_free_seq_oss(opl3) /* NOP */ #endif +extern char snd_opl3_regmap[MAX_OPL2_VOICES][4]; +extern bool use_internal_drums; +extern struct snd_midi_op opl3_ops; + #endif -- cgit v1.2.3 From 00966dcdf0e324e10ab79d505732c339f72417d9 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 25 Jul 2018 23:00:53 +0200 Subject: ALSA: usb-audio: Declare the common variable in header file Declare snd_usb_feature_unit_ctl properly in mixer.h. Otherwise it's error-prone. This fixes the sparse warning: sound/usb/mixer.c:1464:25: warning: symbol 'snd_usb_feature_unit_ctl' was not declared. Should it be static? Signed-off-by: Takashi Iwai --- sound/usb/mixer.h | 2 ++ sound/usb/mixer_quirks.c | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h index e02653465e29..3d12af8bf191 100644 --- a/sound/usb/mixer.h +++ b/sound/usb/mixer.h @@ -109,4 +109,6 @@ int snd_usb_get_cur_mix_value(struct usb_mixer_elem_info *cval, extern void snd_usb_mixer_elem_free(struct snd_kcontrol *kctl); +extern struct snd_kcontrol_new *snd_usb_feature_unit_ctl; + #endif /* __USBMIXER_H */ diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index e82a72fea9a1..cbfb48bdea51 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -47,8 +47,6 @@ #include "mixer_us16x08.h" #include "helper.h" -extern struct snd_kcontrol_new *snd_usb_feature_unit_ctl; - struct std_mono_table { unsigned int unitid, control, cmask; int val_type; -- cgit v1.2.3 From 191bb51e72c3b2b1ed1b2bd7ac30dd9f7ccea306 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 25 Jul 2018 23:00:55 +0200 Subject: ALSA: pcm: Use standard lower_32_bits() and upper_32_bits() Instead of open codes, use the standard macros for obtaining the lower and upper 32bit values. Signed-off-by: Takashi Iwai --- sound/core/oss/pcm_plugin.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c index 85a56af104bd..85bab922ce69 100644 --- a/sound/core/oss/pcm_plugin.c +++ b/sound/core/oss/pcm_plugin.c @@ -281,10 +281,10 @@ static int snd_pcm_plug_formats(const struct snd_mask *mask, SNDRV_PCM_FMTBIT_U32_BE | SNDRV_PCM_FMTBIT_S32_BE); snd_mask_set(&formats, (__force int)SNDRV_PCM_FORMAT_MU_LAW); - if (formats.bits[0] & (u32)linfmts) - formats.bits[0] |= (u32)linfmts; - if (formats.bits[1] & (u32)(linfmts >> 32)) - formats.bits[1] |= (u32)(linfmts >> 32); + if (formats.bits[0] & lower_32_bits(linfmts)) + formats.bits[0] |= lower_32_bits(linfmts); + if (formats.bits[1] & upper_32_bits(linfmts)) + formats.bits[1] |= upper_32_bits(linfmts); return snd_mask_test(&formats, (__force int)format); } -- cgit v1.2.3 From 0701492c86ac0446a834da35ef4991bcf8adb6c4 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 25 Jul 2018 23:00:56 +0200 Subject: ALSA: korg1212: Add __force annotation to cast in user-copy callbacks The user-copy callbacks in korg1212 driver contain the explicit cast from a user pointer to a kernel pointer, but they missed __force prefix. It's mandatory for converting between them. Spotted by sparse, a warning like: sound/pci/korg1212/korg1212.c:1329:33: warning: cast removes address space of expression Signed-off-by: Takashi Iwai --- sound/pci/korg1212/korg1212.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c index 4206ba44d8bb..4e189a93f475 100644 --- a/sound/pci/korg1212/korg1212.c +++ b/sound/pci/korg1212/korg1212.c @@ -1326,7 +1326,7 @@ static int snd_korg1212_copy_to(struct snd_pcm_substream *substream, } #endif if (in_kernel) - memcpy((void *)dst, src, size); + memcpy((__force void *)dst, src, size); else if (copy_to_user(dst, src, size)) return -EFAULT; src++; @@ -1365,7 +1365,7 @@ static int snd_korg1212_copy_from(struct snd_pcm_substream *substream, } #endif if (in_kernel) - memcpy((void *)dst, src, size); + memcpy(dst, (__force void *)src, size); else if (copy_from_user(dst, src, size)) return -EFAULT; dst++; -- cgit v1.2.3 From 63623646a06358833766016d8c1fe14d6576b3d0 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 25 Jul 2018 23:00:57 +0200 Subject: ALSA: emu10k1: Fix missing __force annotation for user/kernel pointer cast The cast between user-space and kernel-space needs an explicit __force prefix, but it's missing in many places in emu10k1 driver code. Spotted by sparse as a warning like: sound/pci/emu10k1/emufx.c:529:33: warning: cast removes address space of expression Signed-off-by: Takashi Iwai --- sound/pci/emu10k1/emufx.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'sound') diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c index de2ecbe95d6c..90713741c2dc 100644 --- a/sound/pci/emu10k1/emufx.c +++ b/sound/pci/emu10k1/emufx.c @@ -526,7 +526,7 @@ static int snd_emu10k1_gpr_poke(struct snd_emu10k1 *emu, if (!test_bit(gpr, icode->gpr_valid)) continue; if (in_kernel) - val = *(u32 *)&icode->gpr_map[gpr]; + val = *(__force u32 *)&icode->gpr_map[gpr]; else if (get_user(val, &icode->gpr_map[gpr])) return -EFAULT; snd_emu10k1_ptr_write(emu, emu->gpr_base + gpr, 0, val); @@ -560,8 +560,8 @@ static int snd_emu10k1_tram_poke(struct snd_emu10k1 *emu, if (!test_bit(tram, icode->tram_valid)) continue; if (in_kernel) { - val = *(u32 *)&icode->tram_data_map[tram]; - addr = *(u32 *)&icode->tram_addr_map[tram]; + val = *(__force u32 *)&icode->tram_data_map[tram]; + addr = *(__force u32 *)&icode->tram_addr_map[tram]; } else { if (get_user(val, &icode->tram_data_map[tram]) || get_user(addr, &icode->tram_addr_map[tram])) @@ -611,8 +611,8 @@ static int snd_emu10k1_code_poke(struct snd_emu10k1 *emu, if (!test_bit(pc / 2, icode->code_valid)) continue; if (in_kernel) { - lo = *(u32 *)&icode->code[pc + 0]; - hi = *(u32 *)&icode->code[pc + 1]; + lo = *(__force u32 *)&icode->code[pc + 0]; + hi = *(__force u32 *)&icode->code[pc + 1]; } else { if (get_user(lo, &icode->code[pc + 0]) || get_user(hi, &icode->code[pc + 1])) @@ -666,7 +666,7 @@ static unsigned int *copy_tlv(const unsigned int __user *_tlv, bool in_kernel) if (!_tlv) return NULL; if (in_kernel) - memcpy(data, (void *)_tlv, sizeof(data)); + memcpy(data, (__force void *)_tlv, sizeof(data)); else if (copy_from_user(data, _tlv, sizeof(data))) return NULL; if (data[1] >= MAX_TLV_SIZE) @@ -676,7 +676,7 @@ static unsigned int *copy_tlv(const unsigned int __user *_tlv, bool in_kernel) return NULL; memcpy(tlv, data, sizeof(data)); if (in_kernel) { - memcpy(tlv + 2, (void *)(_tlv + 2), data[1]); + memcpy(tlv + 2, (__force void *)(_tlv + 2), data[1]); } else if (copy_from_user(tlv + 2, _tlv + 2, data[1])) { kfree(tlv); return NULL; @@ -693,7 +693,7 @@ static int copy_gctl(struct snd_emu10k1 *emu, if (emu->support_tlv) { if (in_kernel) - memcpy(gctl, (void *)&_gctl[idx], sizeof(*gctl)); + memcpy(gctl, (__force void *)&_gctl[idx], sizeof(*gctl)); else if (copy_from_user(gctl, &_gctl[idx], sizeof(*gctl))) return -EFAULT; return 0; @@ -701,7 +701,7 @@ static int copy_gctl(struct snd_emu10k1 *emu, octl = (struct snd_emu10k1_fx8010_control_old_gpr __user *)_gctl; if (in_kernel) - memcpy(gctl, (void *)&octl[idx], sizeof(*octl)); + memcpy(gctl, (__force void *)&octl[idx], sizeof(*octl)); else if (copy_from_user(gctl, &octl[idx], sizeof(*octl))) return -EFAULT; gctl->tlv = NULL; @@ -735,7 +735,7 @@ static int snd_emu10k1_verify_controls(struct snd_emu10k1 *emu, for (i = 0, _id = icode->gpr_del_controls; i < icode->gpr_del_control_count; i++, _id++) { if (in_kernel) - id = *(struct snd_ctl_elem_id *)_id; + id = *(__force struct snd_ctl_elem_id *)_id; else if (copy_from_user(&id, _id, sizeof(id))) return -EFAULT; if (snd_emu10k1_look_for_ctl(emu, &id) == NULL) @@ -833,7 +833,7 @@ static int snd_emu10k1_add_controls(struct snd_emu10k1 *emu, knew.device = gctl->id.device; knew.subdevice = gctl->id.subdevice; knew.info = snd_emu10k1_gpr_ctl_info; - knew.tlv.p = copy_tlv(gctl->tlv, in_kernel); + knew.tlv.p = copy_tlv((__force const unsigned int __user *)gctl->tlv, in_kernel); if (knew.tlv.p) knew.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ; @@ -897,7 +897,7 @@ static int snd_emu10k1_del_controls(struct snd_emu10k1 *emu, for (i = 0, _id = icode->gpr_del_controls; i < icode->gpr_del_control_count; i++, _id++) { if (in_kernel) - id = *(struct snd_ctl_elem_id *)_id; + id = *(__force struct snd_ctl_elem_id *)_id; else if (copy_from_user(&id, _id, sizeof(id))) return -EFAULT; down_write(&card->controls_rwsem); -- cgit v1.2.3 From d6b340d7cb33c816ef4abe8143764ec5ab14a5cc Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 26 Jul 2018 14:58:03 +0200 Subject: ALSA: trident: Suppress gcc string warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The meddlesome gcc warns about the possible shortname string in trident driver code: sound/pci/trident/trident.c: In function ‘snd_trident_probe’: sound/pci/trident/trident.c:126:2: warning: ‘strcat’ accessing 17 or more bytes at offsets 36 and 20 may overlap 1 byte at offset 36 [-Wrestrict] strcat(card->shortname, card->driver); It happens since gcc calculates the possible string size from card->driver, but this can't be true since we did set the string just before that, and they are much shorter. For shutting it up, use the exactly same string set to card->driver for strcat() to card->shortname, too. Signed-off-by: Takashi Iwai --- sound/pci/trident/trident.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c index cedf13b64803..2f18b1cdc2cd 100644 --- a/sound/pci/trident/trident.c +++ b/sound/pci/trident/trident.c @@ -123,7 +123,7 @@ static int snd_trident_probe(struct pci_dev *pci, } else { strcpy(card->shortname, "Trident "); } - strcat(card->shortname, card->driver); + strcat(card->shortname, str); sprintf(card->longname, "%s PCI Audio at 0x%lx, irq %d", card->shortname, trident->port, trident->irq); -- cgit v1.2.3 From a6ea5fe95ab4a1a7af6d57429fe3ecde9acf5b5a Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 25 Jul 2018 23:19:36 +0200 Subject: ALSA: hda: Fix implicit PCM format type conversion The PCM format type is defined with __bitwise, hence it can't be passed as integer but needs an explicit cast. In this patch, instead of the messy cast flood, define the format argument of snd_hdac_calc_stream_format() to be the proper snd_pcm_format_t type. This fixes sparse warnings like: sound/hda/hdac_device.c:760:38: warning: incorrect type in argument 1 (different base types) Signed-off-by: Takashi Iwai --- include/sound/hdaudio.h | 3 ++- sound/hda/hdac_device.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h index 8305e7971035..6f1e1f3b3063 100644 --- a/include/sound/hdaudio.h +++ b/include/sound/hdaudio.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -133,7 +134,7 @@ int snd_hdac_get_sub_nodes(struct hdac_device *codec, hda_nid_t nid, hda_nid_t *start_id); unsigned int snd_hdac_calc_stream_format(unsigned int rate, unsigned int channels, - unsigned int format, + snd_pcm_format_t format, unsigned int maxbps, unsigned short spdif_ctls); int snd_hdac_query_supported_pcm(struct hdac_device *codec, hda_nid_t nid, diff --git a/sound/hda/hdac_device.c b/sound/hda/hdac_device.c index 7ba100bb1c3f..dbf02a3a8d2f 100644 --- a/sound/hda/hdac_device.c +++ b/sound/hda/hdac_device.c @@ -738,7 +738,7 @@ static struct hda_rate_tbl rate_bits[] = { */ unsigned int snd_hdac_calc_stream_format(unsigned int rate, unsigned int channels, - unsigned int format, + snd_pcm_format_t format, unsigned int maxbps, unsigned short spdif_ctls) { -- cgit v1.2.3 From 94dfee0c1a33baa974cba0bd8b83021b1d801297 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 25 Jul 2018 23:19:37 +0200 Subject: ALSA: riptide: Fix PCM format type conversion The PCM format type is with __bitwise, hence it needs to be explicitly declared as snd_pcm_format_t, as warned by sparse: sound/pci/riptide/riptide.c:1028:34: warning: incorrect type in argument 1 (different base types) sound/pci/riptide/riptide.c:1028:34: expected restricted snd_pcm_format_t [usertype] format sound/pci/riptide/riptide.c:1028:34: got unsigned char [unsigned] format Signed-off-by: Takashi Iwai --- sound/pci/riptide/riptide.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c index 44f3b48d47b1..9d2b2ef15c6b 100644 --- a/sound/pci/riptide/riptide.c +++ b/sound/pci/riptide/riptide.c @@ -1017,7 +1017,7 @@ getsamplerate(struct cmdif *cif, unsigned char *intdec, unsigned int *rate) static int setsampleformat(struct cmdif *cif, unsigned char mixer, unsigned char id, - unsigned char channels, unsigned char format) + unsigned char channels, snd_pcm_format_t format) { unsigned char w, ch, sig, order; -- cgit v1.2.3 From f8b6c0cfbdd7359db9bb4da38dd54217296f9264 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 25 Jul 2018 23:19:38 +0200 Subject: ALSA: pcm: Fix sparse warning wrt PCM format type The PCM format type is with __bitwise, hence it needs the explicit cast with __force. It's ugly, but there is a reason for that cost... This fixes the sparse warning: sound/core/oss/pcm_oss.c:1854:55: warning: incorrect type in argument 1 (different base types) Signed-off-by: Takashi Iwai --- sound/core/oss/pcm_oss.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 905a53c1cde5..f8d4a419f3af 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -1851,7 +1851,7 @@ static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file) format_mask = hw_param_mask_c(params, SNDRV_PCM_HW_PARAM_FORMAT); for (fmt = 0; fmt < 32; ++fmt) { if (snd_mask_test(format_mask, fmt)) { - int f = snd_pcm_oss_format_to(fmt); + int f = snd_pcm_oss_format_to((__force snd_pcm_format_t)fmt); if (f >= 0) formats |= f; } -- cgit v1.2.3 From d63f33d3f083bdb3a7c2dfd623f4d811b2a8d772 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 25 Jul 2018 23:19:39 +0200 Subject: ALSA: ad1816a: Fix sparse warning wrt PCM format type The PCM format type is with __bitwise, and it can't be converted from integer implicitly. Instead of an ugly cast, declare the function argument of snd_ad1816a_get_format() with the proper snd_pcm_format_t type. This fixes the sparse warning like: sound/isa/ad1816a/ad1816a_lib.c:93:14: warning: restricted snd_pcm_format_t degrades to integer Signed-off-by: Takashi Iwai --- sound/isa/ad1816a/ad1816a_lib.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/isa/ad1816a/ad1816a_lib.c b/sound/isa/ad1816a/ad1816a_lib.c index 923201414469..fba6d22f7f4b 100644 --- a/sound/isa/ad1816a/ad1816a_lib.c +++ b/sound/isa/ad1816a/ad1816a_lib.c @@ -85,7 +85,8 @@ static void snd_ad1816a_write_mask(struct snd_ad1816a *chip, unsigned char reg, static unsigned char snd_ad1816a_get_format(struct snd_ad1816a *chip, - unsigned int format, int channels) + snd_pcm_format_t format, + int channels) { unsigned char retval = AD1816A_FMT_LINEAR_8; -- cgit v1.2.3 From 10d3d91e3bc4e152a580bf523e4fd6bf279ae532 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 25 Jul 2018 23:19:40 +0200 Subject: ALSA: au88x0: Fix sparse warning wrt PCM format type The PCM format type is with __bitwise, and it can't be converted from integer implicitly. Instead of an ugly cast, declare the function argument of vortex_alsafmt_aspfmt() with the proper snd_pcm_format_t type. This fixes the sparse warning like: sound/pci/au88x0/au88x0_core.c:2778:14: warning: restricted snd_pcm_format_t degrades to integer Signed-off-by: Takashi Iwai --- sound/pci/au88x0/au88x0.h | 2 +- sound/pci/au88x0/au88x0_core.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/pci/au88x0/au88x0.h b/sound/pci/au88x0/au88x0.h index bcc648bf6478..e3e31f07d766 100644 --- a/sound/pci/au88x0/au88x0.h +++ b/sound/pci/au88x0/au88x0.h @@ -241,7 +241,7 @@ static int vortex_core_init(vortex_t * card); static int vortex_core_shutdown(vortex_t * card); static void vortex_enable_int(vortex_t * card); static irqreturn_t vortex_interrupt(int irq, void *dev_id); -static int vortex_alsafmt_aspfmt(int alsafmt, vortex_t *v); +static int vortex_alsafmt_aspfmt(snd_pcm_format_t alsafmt, vortex_t *v); /* Connection stuff. */ static void vortex_connect_default(vortex_t * vortex, int en); diff --git a/sound/pci/au88x0/au88x0_core.c b/sound/pci/au88x0/au88x0_core.c index 4083c8b01619..2e5b460a847c 100644 --- a/sound/pci/au88x0/au88x0_core.c +++ b/sound/pci/au88x0/au88x0_core.c @@ -2770,7 +2770,7 @@ static int vortex_core_shutdown(vortex_t * vortex) /* Alsa support. */ -static int vortex_alsafmt_aspfmt(int alsafmt, vortex_t *v) +static int vortex_alsafmt_aspfmt(snd_pcm_format_t alsafmt, vortex_t *v) { int fmt; -- cgit v1.2.3 From a91a0e774984aa57090c39dc3269a812417737ed Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 25 Jul 2018 23:19:41 +0200 Subject: ALSA: asihpi: Fix PCM format notations asihpi driver treats -1 as an own invalid PCM format, but this needs a proper cast with __force prefix since PCM format type is __bitwise. Define a constant with the proper type and use it allover. This fixes sparse warnings like: sound/pci/asihpi/asihpi.c:315:9: warning: incorrect type in initializer (different base types) Signed-off-by: Takashi Iwai --- sound/pci/asihpi/asihpi.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) (limited to 'sound') diff --git a/sound/pci/asihpi/asihpi.c b/sound/pci/asihpi/asihpi.c index 64e0961f93ba..a31fe1550903 100644 --- a/sound/pci/asihpi/asihpi.c +++ b/sound/pci/asihpi/asihpi.c @@ -311,27 +311,29 @@ static void print_hwparams(struct snd_pcm_substream *substream, snd_pcm_format_width(params_format(p)) / 8); } +#define INVALID_FORMAT (__force snd_pcm_format_t)(-1) + static snd_pcm_format_t hpi_to_alsa_formats[] = { - -1, /* INVALID */ + INVALID_FORMAT, /* INVALID */ SNDRV_PCM_FORMAT_U8, /* HPI_FORMAT_PCM8_UNSIGNED 1 */ SNDRV_PCM_FORMAT_S16, /* HPI_FORMAT_PCM16_SIGNED 2 */ - -1, /* HPI_FORMAT_MPEG_L1 3 */ + INVALID_FORMAT, /* HPI_FORMAT_MPEG_L1 3 */ SNDRV_PCM_FORMAT_MPEG, /* HPI_FORMAT_MPEG_L2 4 */ SNDRV_PCM_FORMAT_MPEG, /* HPI_FORMAT_MPEG_L3 5 */ - -1, /* HPI_FORMAT_DOLBY_AC2 6 */ - -1, /* HPI_FORMAT_DOLBY_AC3 7 */ + INVALID_FORMAT, /* HPI_FORMAT_DOLBY_AC2 6 */ + INVALID_FORMAT, /* HPI_FORMAT_DOLBY_AC3 7 */ SNDRV_PCM_FORMAT_S16_BE,/* HPI_FORMAT_PCM16_BIGENDIAN 8 */ - -1, /* HPI_FORMAT_AA_TAGIT1_HITS 9 */ - -1, /* HPI_FORMAT_AA_TAGIT1_INSERTS 10 */ + INVALID_FORMAT, /* HPI_FORMAT_AA_TAGIT1_HITS 9 */ + INVALID_FORMAT, /* HPI_FORMAT_AA_TAGIT1_INSERTS 10 */ SNDRV_PCM_FORMAT_S32, /* HPI_FORMAT_PCM32_SIGNED 11 */ - -1, /* HPI_FORMAT_RAW_BITSTREAM 12 */ - -1, /* HPI_FORMAT_AA_TAGIT1_HITS_EX1 13 */ + INVALID_FORMAT, /* HPI_FORMAT_RAW_BITSTREAM 12 */ + INVALID_FORMAT, /* HPI_FORMAT_AA_TAGIT1_HITS_EX1 13 */ SNDRV_PCM_FORMAT_FLOAT, /* HPI_FORMAT_PCM32_FLOAT 14 */ #if 1 /* ALSA can't handle 3 byte sample size together with power-of-2 * constraint on buffer_bytes, so disable this format */ - -1 + INVALID_FORMAT #else /* SNDRV_PCM_FORMAT_S24_3LE */ /* HPI_FORMAT_PCM24_SIGNED 15 */ #endif @@ -1023,7 +1025,7 @@ static u64 snd_card_asihpi_playback_formats(struct snd_card_asihpi *asihpi, format, sample_rate, 128000, 0); if (!err) err = hpi_outstream_query_format(h_stream, &hpi_format); - if (!err && (hpi_to_alsa_formats[format] != -1)) + if (!err && (hpi_to_alsa_formats[format] != INVALID_FORMAT)) formats |= pcm_format_to_bits(hpi_to_alsa_formats[format]); } return formats; @@ -1205,7 +1207,7 @@ static u64 snd_card_asihpi_capture_formats(struct snd_card_asihpi *asihpi, format, sample_rate, 128000, 0); if (!err) err = hpi_instream_query_format(h_stream, &hpi_format); - if (!err && (hpi_to_alsa_formats[format] != -1)) + if (!err && (hpi_to_alsa_formats[format] != INVALID_FORMAT)) formats |= pcm_format_to_bits(hpi_to_alsa_formats[format]); } return formats; -- cgit v1.2.3 From 6be9a60efb401487a4d658ef23d652a9e6860b34 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 25 Jul 2018 23:19:42 +0200 Subject: ALSA: wss: Fix sparse warning wrt PCM format type The PCM format type is with __bitwise, and it can't be converted from integer implicitly. Instead of an ugly cast, declare the function argument of snd_wss_get_format() with the proper snd_pcm_format_t type. This fixes the sparse warnings like: sound/isa/wss/wss_lib.c:551:14: warning: restricted snd_pcm_format_t degrades to integer Signed-off-by: Takashi Iwai --- sound/isa/wss/wss_lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/isa/wss/wss_lib.c b/sound/isa/wss/wss_lib.c index 8a852042a066..d23cc8abe1ef 100644 --- a/sound/isa/wss/wss_lib.c +++ b/sound/isa/wss/wss_lib.c @@ -541,7 +541,7 @@ static unsigned char snd_wss_get_rate(unsigned int rate) } static unsigned char snd_wss_get_format(struct snd_wss *chip, - int format, + snd_pcm_format_t format, int channels) { unsigned char rformat; -- cgit v1.2.3 From 55ff2d1ea5487fe131cce399baf4503dcf5cc8e1 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 25 Jul 2018 23:19:43 +0200 Subject: ALSA: sb: Fix PCM format bit calculation The PCM format type in snd_pcm_format_t can't be treated as integer implicitly since it's with __bitwise. We have already a helper function to get the bit index of the given type, and use it in each place instead. This fixes sparse warnings like: sound/isa/sb/sb16_main.c:61:44: warning: restricted snd_pcm_format_t degrades to integer Signed-off-by: Takashi Iwai --- sound/isa/sb/sb16_main.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/isa/sb/sb16_main.c b/sound/isa/sb/sb16_main.c index 3e39ba220c39..11ed4a6e5bf1 100644 --- a/sound/isa/sb/sb16_main.c +++ b/sound/isa/sb/sb16_main.c @@ -49,6 +49,9 @@ MODULE_AUTHOR("Jaroslav Kysela "); MODULE_DESCRIPTION("Routines for control of 16-bit SoundBlaster cards and clones"); MODULE_LICENSE("GPL"); +#define runtime_format_bits(runtime) \ + ((unsigned int)pcm_format_to_bits((runtime)->format)) + #ifdef CONFIG_SND_SB16_CSP static void snd_sb16_csp_playback_prepare(struct snd_sb *chip, struct snd_pcm_runtime *runtime) { @@ -58,7 +61,7 @@ static void snd_sb16_csp_playback_prepare(struct snd_sb *chip, struct snd_pcm_ru if (csp->running & SNDRV_SB_CSP_ST_LOADED) { /* manually loaded codec */ if ((csp->mode & SNDRV_SB_CSP_MODE_DSP_WRITE) && - ((1U << runtime->format) == csp->acc_format)) { + (runtime_format_bits(runtime) == csp->acc_format)) { /* Supported runtime PCM format for playback */ if (csp->ops.csp_use(csp) == 0) { /* If CSP was successfully acquired */ @@ -66,7 +69,7 @@ static void snd_sb16_csp_playback_prepare(struct snd_sb *chip, struct snd_pcm_ru } } else if ((csp->mode & SNDRV_SB_CSP_MODE_QSOUND) && (csp->q_enabled)) { /* QSound decoder is loaded and enabled */ - if ((1 << runtime->format) & (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 | + if (runtime_format_bits(runtime) & (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE)) { /* Only for simple PCM formats */ if (csp->ops.csp_use(csp) == 0) { @@ -106,7 +109,7 @@ static void snd_sb16_csp_capture_prepare(struct snd_sb *chip, struct snd_pcm_run if (csp->running & SNDRV_SB_CSP_ST_LOADED) { /* manually loaded codec */ if ((csp->mode & SNDRV_SB_CSP_MODE_DSP_READ) && - ((1U << runtime->format) == csp->acc_format)) { + (runtime_format_bits(runtime) == csp->acc_format)) { /* Supported runtime PCM format for capture */ if (csp->ops.csp_use(csp) == 0) { /* If CSP was successfully acquired */ -- cgit v1.2.3 From e5d3765b6c4cb3ba64295a4205a2f68a4e8fe083 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 25 Jul 2018 23:19:44 +0200 Subject: ALSA: sb: Fix sparse warning wrt PCM format type The PCM format type is with __bitwise, and it can't be converted from integer implicitly. Instead of an ugly cast, declare the function argument of snd_sb_csp_autoload() with the proper snd_pcm_format_t type. This fixes the sparse warnings like: sound/isa/sb/sb16_csp.c:743:22: warning: restricted snd_pcm_format_t degrades to integer Signed-off-by: Takashi Iwai --- include/sound/sb16_csp.h | 2 +- sound/isa/sb/sb16_csp.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/include/sound/sb16_csp.h b/include/sound/sb16_csp.h index c7c7788005e4..7817e88bd08d 100644 --- a/include/sound/sb16_csp.h +++ b/include/sound/sb16_csp.h @@ -46,7 +46,7 @@ enum { struct snd_sb_csp_ops { int (*csp_use) (struct snd_sb_csp * p); int (*csp_unuse) (struct snd_sb_csp * p); - int (*csp_autoload) (struct snd_sb_csp * p, int pcm_sfmt, int play_rec_mode); + int (*csp_autoload) (struct snd_sb_csp * p, snd_pcm_format_t pcm_sfmt, int play_rec_mode); int (*csp_start) (struct snd_sb_csp * p, int sample_width, int channels); int (*csp_stop) (struct snd_sb_csp * p); int (*csp_qsound_transfer) (struct snd_sb_csp * p); diff --git a/sound/isa/sb/sb16_csp.c b/sound/isa/sb/sb16_csp.c index fa5780bb0c68..2210e7c72787 100644 --- a/sound/isa/sb/sb16_csp.c +++ b/sound/isa/sb/sb16_csp.c @@ -93,7 +93,7 @@ static int snd_sb_csp_riff_load(struct snd_sb_csp * p, struct snd_sb_csp_microcode __user * code); static int snd_sb_csp_unload(struct snd_sb_csp * p); static int snd_sb_csp_load_user(struct snd_sb_csp * p, const unsigned char __user *buf, int size, int load_flags); -static int snd_sb_csp_autoload(struct snd_sb_csp * p, int pcm_sfmt, int play_rec_mode); +static int snd_sb_csp_autoload(struct snd_sb_csp * p, snd_pcm_format_t pcm_sfmt, int play_rec_mode); static int snd_sb_csp_check_version(struct snd_sb_csp * p); static int snd_sb_csp_use(struct snd_sb_csp * p); @@ -726,7 +726,7 @@ static int snd_sb_csp_firmware_load(struct snd_sb_csp *p, int index, int flags) * autoload hardware codec if necessary * return 0 if CSP is loaded and ready to run (p->running != 0) */ -static int snd_sb_csp_autoload(struct snd_sb_csp * p, int pcm_sfmt, int play_rec_mode) +static int snd_sb_csp_autoload(struct snd_sb_csp * p, snd_pcm_format_t pcm_sfmt, int play_rec_mode) { unsigned long flags; int err = 0; @@ -736,7 +736,7 @@ static int snd_sb_csp_autoload(struct snd_sb_csp * p, int pcm_sfmt, int play_rec return -EBUSY; /* autoload microcode only if requested hardware codec is not already loaded */ - if (((1 << pcm_sfmt) & p->acc_format) && (play_rec_mode & p->mode)) { + if (((1U << (__force int)pcm_sfmt) & p->acc_format) && (play_rec_mode & p->mode)) { p->running = SNDRV_SB_CSP_ST_AUTO; } else { switch (pcm_sfmt) { -- cgit v1.2.3 From 3ac14b3960185d4c8a2f14b84042aa1aa8531d88 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 25 Jul 2018 23:19:45 +0200 Subject: ALSA: xen: Use standard pcm_format_to_bits() for ALSA format bits The open codes with the bit shift in xen_snd_front_alsa.c give sparse warnings as the PCM format type is with __bitwise. There is already a standard macro to get the format bits, so let's use it instead. This fixes sparse warnings like: sound/xen/xen_snd_front_alsa.c:191:47: warning: restricted snd_pcm_format_t degrades to integer Signed-off-by: Takashi Iwai --- sound/xen/xen_snd_front_alsa.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/xen/xen_snd_front_alsa.c b/sound/xen/xen_snd_front_alsa.c index 5a2bd70a2fa1..129180e17db1 100644 --- a/sound/xen/xen_snd_front_alsa.c +++ b/sound/xen/xen_snd_front_alsa.c @@ -188,7 +188,7 @@ static u64 to_sndif_formats_mask(u64 alsa_formats) mask = 0; for (i = 0; i < ARRAY_SIZE(ALSA_SNDIF_FORMATS); i++) - if (1 << ALSA_SNDIF_FORMATS[i].alsa & alsa_formats) + if (pcm_format_to_bits(ALSA_SNDIF_FORMATS[i].alsa) & alsa_formats) mask |= 1 << ALSA_SNDIF_FORMATS[i].sndif; return mask; @@ -202,7 +202,7 @@ static u64 to_alsa_formats_mask(u64 sndif_formats) mask = 0; for (i = 0; i < ARRAY_SIZE(ALSA_SNDIF_FORMATS); i++) if (1 << ALSA_SNDIF_FORMATS[i].sndif & sndif_formats) - mask |= 1 << ALSA_SNDIF_FORMATS[i].alsa; + mask |= pcm_format_to_bits(ALSA_SNDIF_FORMATS[i].alsa); return mask; } -- cgit v1.2.3 From d3c637632da95d7646053c64b855641cd917960e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 25 Jul 2018 23:24:01 +0200 Subject: ALSA: ymfpci: Proper endian notations The bank values are all little-endians, so they should be defined with __le32. This fixes lots of sparse warnings like: sound/pci/ymfpci/ymfpci_main.c:315:23: warning: cast to restricted __le32 sound/pci/ymfpci/ymfpci_main.c:342:32: warning: incorrect type in assignment (different base types) Signed-off-by: Takashi Iwai --- sound/pci/ymfpci/ymfpci.h | 78 +++++++++++++++++++++--------------------- sound/pci/ymfpci/ymfpci_main.c | 6 ++-- 2 files changed, 42 insertions(+), 42 deletions(-) (limited to 'sound') diff --git a/sound/pci/ymfpci/ymfpci.h b/sound/pci/ymfpci/ymfpci.h index aa9bb065f385..e2fa7e360d79 100644 --- a/sound/pci/ymfpci/ymfpci.h +++ b/sound/pci/ymfpci/ymfpci.h @@ -185,50 +185,50 @@ */ struct snd_ymfpci_playback_bank { - u32 format; - u32 loop_default; - u32 base; /* 32-bit address */ - u32 loop_start; /* 32-bit offset */ - u32 loop_end; /* 32-bit offset */ - u32 loop_frac; /* 8-bit fraction - loop_start */ - u32 delta_end; /* pitch delta end */ - u32 lpfK_end; - u32 eg_gain_end; - u32 left_gain_end; - u32 right_gain_end; - u32 eff1_gain_end; - u32 eff2_gain_end; - u32 eff3_gain_end; - u32 lpfQ; - u32 status; - u32 num_of_frames; - u32 loop_count; - u32 start; - u32 start_frac; - u32 delta; - u32 lpfK; - u32 eg_gain; - u32 left_gain; - u32 right_gain; - u32 eff1_gain; - u32 eff2_gain; - u32 eff3_gain; - u32 lpfD1; - u32 lpfD2; + __le32 format; + __le32 loop_default; + __le32 base; /* 32-bit address */ + __le32 loop_start; /* 32-bit offset */ + __le32 loop_end; /* 32-bit offset */ + __le32 loop_frac; /* 8-bit fraction - loop_start */ + __le32 delta_end; /* pitch delta end */ + __le32 lpfK_end; + __le32 eg_gain_end; + __le32 left_gain_end; + __le32 right_gain_end; + __le32 eff1_gain_end; + __le32 eff2_gain_end; + __le32 eff3_gain_end; + __le32 lpfQ; + __le32 status; + __le32 num_of_frames; + __le32 loop_count; + __le32 start; + __le32 start_frac; + __le32 delta; + __le32 lpfK; + __le32 eg_gain; + __le32 left_gain; + __le32 right_gain; + __le32 eff1_gain; + __le32 eff2_gain; + __le32 eff3_gain; + __le32 lpfD1; + __le32 lpfD2; }; struct snd_ymfpci_capture_bank { - u32 base; /* 32-bit address */ - u32 loop_end; /* 32-bit offset */ - u32 start; /* 32-bit offset */ - u32 num_of_loops; /* counter */ + __le32 base; /* 32-bit address */ + __le32 loop_end; /* 32-bit offset */ + __le32 start; /* 32-bit offset */ + __le32 num_of_loops; /* counter */ }; struct snd_ymfpci_effect_bank { - u32 base; /* 32-bit address */ - u32 loop_end; /* 32-bit offset */ - u32 start; /* 32-bit offset */ - u32 temp; + __le32 base; /* 32-bit address */ + __le32 loop_end; /* 32-bit offset */ + __le32 start; /* 32-bit offset */ + __le32 temp; }; struct snd_ymfpci_pcm; @@ -316,7 +316,7 @@ struct snd_ymfpci { dma_addr_t work_base_addr; struct snd_dma_buffer ac3_tmp_base; - u32 *ctrl_playback; + __le32 *ctrl_playback; struct snd_ymfpci_playback_bank *bank_playback[YDSXG_PLAYBACK_VOICES][2]; struct snd_ymfpci_capture_bank *bank_capture[YDSXG_CAPTURE_VOICES][2]; struct snd_ymfpci_effect_bank *bank_effect[YDSXG_EFFECT_VOICES][2]; diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c index 6f81396aadc9..a4926fb03991 100644 --- a/sound/pci/ymfpci/ymfpci_main.c +++ b/sound/pci/ymfpci/ymfpci_main.c @@ -336,7 +336,7 @@ static void snd_ymfpci_pcm_interrupt(struct snd_ymfpci *chip, struct snd_ymfpci_ unsigned int subs = ypcm->substream->number; unsigned int next_bank = 1 - chip->active_bank; struct snd_ymfpci_playback_bank *bank; - u32 volume; + __le32 volume; bank = &voice->bank[next_bank]; volume = cpu_to_le32(chip->pcm_mixer[subs].left << 15); @@ -505,7 +505,7 @@ static void snd_ymfpci_pcm_init_voice(struct snd_ymfpci_pcm *ypcm, unsigned int u32 lpfK = snd_ymfpci_calc_lpfK(runtime->rate); struct snd_ymfpci_playback_bank *bank; unsigned int nbank; - u32 vol_left, vol_right; + __le32 vol_left, vol_right; u8 use_left, use_right; unsigned long flags; @@ -2135,7 +2135,7 @@ static int snd_ymfpci_memalloc(struct snd_ymfpci *chip) chip->bank_base_playback = ptr; chip->bank_base_playback_addr = ptr_addr; - chip->ctrl_playback = (u32 *)ptr; + chip->ctrl_playback = (__le32 *)ptr; chip->ctrl_playback[0] = cpu_to_le32(YDSXG_PLAYBACK_VOICES); ptr += ALIGN(playback_ctrl_size, 0x100); ptr_addr += ALIGN(playback_ctrl_size, 0x100); -- cgit v1.2.3 From 752089fea357b36ba9dd477db594bdc677110579 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 25 Jul 2018 23:24:02 +0200 Subject: ALSA: trident: Proper endian notations The TLB entries in Trident driver are represented in little-endian, hence they should be declared as __le32. This patch fixes the sparse warnings like: sound/pci/trident/trident_memory.c:226:17: warning: incorrect type in assignment (different base types) Signed-off-by: Takashi Iwai --- sound/pci/trident/trident.h | 2 +- sound/pci/trident/trident_main.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/pci/trident/trident.h b/sound/pci/trident/trident.h index 9624e5937719..2d62c1921255 100644 --- a/sound/pci/trident/trident.h +++ b/sound/pci/trident/trident.h @@ -264,7 +264,7 @@ struct snd_trident_memblk_arg { }; struct snd_trident_tlb { - unsigned int * entries; /* 16k-aligned TLB table */ + __le32 *entries; /* 16k-aligned TLB table */ dma_addr_t entries_dmaaddr; /* 16k-aligned PCI address to TLB table */ unsigned long * shadow_entries; /* shadow entries with virtual addresses */ struct snd_dma_buffer buffer; diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c index 49c64fae3466..5523e193d556 100644 --- a/sound/pci/trident/trident_main.c +++ b/sound/pci/trident/trident_main.c @@ -3359,7 +3359,7 @@ static int snd_trident_tlb_alloc(struct snd_trident *trident) dev_err(trident->card->dev, "unable to allocate TLB buffer\n"); return -ENOMEM; } - trident->tlb.entries = (unsigned int*)ALIGN((unsigned long)trident->tlb.buffer.area, SNDRV_TRIDENT_MAX_PAGES * 4); + trident->tlb.entries = (__le32 *)ALIGN((unsigned long)trident->tlb.buffer.area, SNDRV_TRIDENT_MAX_PAGES * 4); trident->tlb.entries_dmaaddr = ALIGN(trident->tlb.buffer.addr, SNDRV_TRIDENT_MAX_PAGES * 4); /* allocate shadow TLB page table (virtual addresses) */ trident->tlb.shadow_entries = -- cgit v1.2.3 From 7362b0fca5de9570b5ba7bce5034105028daa599 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 25 Jul 2018 23:24:03 +0200 Subject: ALSA: hda: Proper endian notations for BDL pointers The BDL pointer used in snd_hdac_dsp_prepare() should be declared as __le32, as warned by sparse: sound/hda/hdac_stream.c:655:47: warning: incorrect type in argument 4 (different base types) sound/hda/hdac_stream.c:655:47: expected restricted __le32 [usertype] **bdlp sound/hda/hdac_stream.c:655:47: got unsigned int [usertype] ** Signed-off-by: Takashi Iwai --- sound/hda/hdac_stream.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/hda/hdac_stream.c b/sound/hda/hdac_stream.c index e1472c7ab6c1..eee422390d8e 100644 --- a/sound/hda/hdac_stream.c +++ b/sound/hda/hdac_stream.c @@ -621,7 +621,7 @@ int snd_hdac_dsp_prepare(struct hdac_stream *azx_dev, unsigned int format, unsigned int byte_size, struct snd_dma_buffer *bufp) { struct hdac_bus *bus = azx_dev->bus; - u32 *bdl; + __le32 *bdl; int err; snd_hdac_dsp_lock(azx_dev); @@ -651,7 +651,7 @@ int snd_hdac_dsp_prepare(struct hdac_stream *azx_dev, unsigned int format, snd_hdac_stream_writel(azx_dev, SD_BDLPU, 0); azx_dev->frags = 0; - bdl = (u32 *)azx_dev->bdl.area; + bdl = (__le32 *)azx_dev->bdl.area; err = setup_bdle(bus, bufp, azx_dev, &bdl, 0, byte_size, 0); if (err < 0) goto error; -- cgit v1.2.3 From be05e3de3a933156d472127f659d4473c461dcc5 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 25 Jul 2018 23:24:04 +0200 Subject: ALSA: riptide: Properly endian notations The SG descriptor of Riptide contains the little-endian values, hence we need to define with __le32 properly. This fixes sparse warnings like: sound/pci/riptide/riptide.c:1112:40: warning: cast to restricted __le32 Signed-off-by: Takashi Iwai --- sound/pci/riptide/riptide.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c index 9d2b2ef15c6b..23017e3bc76c 100644 --- a/sound/pci/riptide/riptide.c +++ b/sound/pci/riptide/riptide.c @@ -470,10 +470,10 @@ struct snd_riptide { }; struct sgd { /* scatter gather desriptor */ - u32 dwNextLink; - u32 dwSegPtrPhys; - u32 dwSegLen; - u32 dwStat_Ctl; + __le32 dwNextLink; + __le32 dwSegPtrPhys; + __le32 dwSegLen; + __le32 dwStat_Ctl; }; struct pcmhw { /* pcm descriptor */ -- cgit v1.2.3 From 0e7ca66a97c3bbf0b7665010d1b1d6a8c8e3811e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 25 Jul 2018 23:24:05 +0200 Subject: ALSA: mixart: Proper endian notations The miXart driver deals with big-endian values as raw data, while it declares most of variables as u32. This leads to sparse warnings like sound/pci/mixart/mixart.c:1203:23: warning: cast to restricted __be32 Fix them by properly defining the structs and add the explicit cast to macros. Signed-off-by: Takashi Iwai --- sound/pci/mixart/mixart_core.c | 4 ++-- sound/pci/mixart/mixart_hwdep.c | 42 ++++++++++++++++++++--------------------- sound/pci/mixart/mixart_hwdep.h | 8 ++++---- 3 files changed, 27 insertions(+), 27 deletions(-) (limited to 'sound') diff --git a/sound/pci/mixart/mixart_core.c b/sound/pci/mixart/mixart_core.c index 8bf2ce32d4a8..46c292b52fd6 100644 --- a/sound/pci/mixart/mixart_core.c +++ b/sound/pci/mixart/mixart_core.c @@ -107,7 +107,7 @@ static int get_msg(struct mixart_mgr *mgr, struct mixart_msg *resp, #ifndef __BIG_ENDIAN size /= 4; /* u32 size */ for(i=0; i < size; i++) { - ((u32*)resp->data)[i] = be32_to_cpu(((u32*)resp->data)[i]); + ((u32*)resp->data)[i] = be32_to_cpu(((__be32*)resp->data)[i]); } #endif @@ -519,7 +519,7 @@ irqreturn_t snd_mixart_threaded_irq(int irq, void *dev_id) /* Traces are text: the swapped msg_data has to be swapped back ! */ int i; for(i=0; i<(resp.size/4); i++) { - (mixart_msg_data)[i] = cpu_to_be32((mixart_msg_data)[i]); + ((__be32*)mixart_msg_data)[i] = cpu_to_be32((mixart_msg_data)[i]); } #endif ((char*)mixart_msg_data)[resp.size - 1] = 0; diff --git a/sound/pci/mixart/mixart_hwdep.c b/sound/pci/mixart/mixart_hwdep.c index 5bfd3ac80db5..bc92758de82c 100644 --- a/sound/pci/mixart/mixart_hwdep.c +++ b/sound/pci/mixart/mixart_hwdep.c @@ -73,30 +73,30 @@ static int mixart_wait_nice_for_register_value(struct mixart_mgr *mgr, */ struct snd_mixart_elf32_ehdr { u8 e_ident[16]; - u16 e_type; - u16 e_machine; - u32 e_version; - u32 e_entry; - u32 e_phoff; - u32 e_shoff; - u32 e_flags; - u16 e_ehsize; - u16 e_phentsize; - u16 e_phnum; - u16 e_shentsize; - u16 e_shnum; - u16 e_shstrndx; + __be16 e_type; + __be16 e_machine; + __be32 e_version; + __be32 e_entry; + __be32 e_phoff; + __be32 e_shoff; + __be32 e_flags; + __be16 e_ehsize; + __be16 e_phentsize; + __be16 e_phnum; + __be16 e_shentsize; + __be16 e_shnum; + __be16 e_shstrndx; }; struct snd_mixart_elf32_phdr { - u32 p_type; - u32 p_offset; - u32 p_vaddr; - u32 p_paddr; - u32 p_filesz; - u32 p_memsz; - u32 p_flags; - u32 p_align; + __be32 p_type; + __be32 p_offset; + __be32 p_vaddr; + __be32 p_paddr; + __be32 p_filesz; + __be32 p_memsz; + __be32 p_flags; + __be32 p_align; }; static int mixart_load_elf(struct mixart_mgr *mgr, const struct firmware *dsp ) diff --git a/sound/pci/mixart/mixart_hwdep.h b/sound/pci/mixart/mixart_hwdep.h index 812e288ef2e7..2794cd385b8e 100644 --- a/sound/pci/mixart/mixart_hwdep.h +++ b/sound/pci/mixart/mixart_hwdep.h @@ -26,19 +26,19 @@ #include #ifndef readl_be -#define readl_be(x) be32_to_cpu(__raw_readl(x)) +#define readl_be(x) be32_to_cpu((__force __be32)__raw_readl(x)) #endif #ifndef writel_be -#define writel_be(data,addr) __raw_writel(cpu_to_be32(data),addr) +#define writel_be(data,addr) __raw_writel((__force u32)cpu_to_be32(data),addr) #endif #ifndef readl_le -#define readl_le(x) le32_to_cpu(__raw_readl(x)) +#define readl_le(x) le32_to_cpu((__force __le32)__raw_readl(x)) #endif #ifndef writel_le -#define writel_le(data,addr) __raw_writel(cpu_to_le32(data),addr) +#define writel_le(data,addr) __raw_writel((__force u32)cpu_to_le32(data),addr) #endif #define MIXART_MEM(mgr,x) ((mgr)->mem[0].virt + (x)) -- cgit v1.2.3 From 0d9a26fc74578289e0edeac36c6d562596f8a72e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 25 Jul 2018 23:24:06 +0200 Subject: ALSA: lola: Proper endian notations The BDL entries in lola driver are little-endian while we code them as u32. This leads to sparse warnings like: sound/pci/lola/lola.c:105:40: warning: incorrect type in assignment (different base types) sound/pci/lola/lola.c:105:40: expected unsigned int [unsigned] [usertype] sound/pci/lola/lola.c:105:40: got restricted __le32 [usertype] This patch fixes the declarations to the proper __le32 type. Also, there was a typo in the original code, where __user was used that was intended as __iomem. This was caused also by sparse: sound/pci/lola/lola_mixer.c:132:27: warning: incorrect type in assignment (different address spaces) Fixed in this patch as well. Signed-off-by: Takashi Iwai --- sound/pci/lola/lola.c | 4 ++-- sound/pci/lola/lola.h | 4 ++-- sound/pci/lola/lola_pcm.c | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) (limited to 'sound') diff --git a/sound/pci/lola/lola.c b/sound/pci/lola/lola.c index 9ff600084973..254f24366892 100644 --- a/sound/pci/lola/lola.c +++ b/sound/pci/lola/lola.c @@ -369,9 +369,9 @@ static int setup_corb_rirb(struct lola *chip) return err; chip->corb.addr = chip->rb.addr; - chip->corb.buf = (u32 *)chip->rb.area; + chip->corb.buf = (__le32 *)chip->rb.area; chip->rirb.addr = chip->rb.addr + 2048; - chip->rirb.buf = (u32 *)(chip->rb.area + 2048); + chip->rirb.buf = (__le32 *)(chip->rb.area + 2048); /* disable ringbuffer DMAs */ lola_writeb(chip, BAR0, RIRBCTL, 0); diff --git a/sound/pci/lola/lola.h b/sound/pci/lola/lola.h index f0b100059efd..bd852fed8bb6 100644 --- a/sound/pci/lola/lola.h +++ b/sound/pci/lola/lola.h @@ -220,7 +220,7 @@ struct lola_bar { /* CORB/RIRB */ struct lola_rb { - u32 *buf; /* CORB/RIRB buffer, 8 byte per each entry */ + __le32 *buf; /* CORB/RIRB buffer, 8 byte per each entry */ dma_addr_t addr; /* physical address of CORB/RIRB buffer */ unsigned short rp, wp; /* read/write pointers */ int cmds; /* number of pending requests */ @@ -275,7 +275,7 @@ struct lola_mixer_array { struct lola_mixer_widget { unsigned int nid; unsigned int caps; - struct lola_mixer_array __user *array; + struct lola_mixer_array __iomem *array; struct lola_mixer_array *array_saved; unsigned int src_stream_outs; unsigned int src_phys_ins; diff --git a/sound/pci/lola/lola_pcm.c b/sound/pci/lola/lola_pcm.c index 310b26a756c9..e70276c3ea20 100644 --- a/sound/pci/lola/lola_pcm.c +++ b/sound/pci/lola/lola_pcm.c @@ -316,10 +316,10 @@ static int lola_pcm_hw_free(struct snd_pcm_substream *substream) * set up a BDL entry */ static int setup_bdle(struct snd_pcm_substream *substream, - struct lola_stream *str, u32 **bdlp, + struct lola_stream *str, __le32 **bdlp, int ofs, int size) { - u32 *bdl = *bdlp; + __le32 *bdl = *bdlp; while (size > 0) { dma_addr_t addr; @@ -355,14 +355,14 @@ static int lola_setup_periods(struct lola *chip, struct lola_pcm *pcm, struct snd_pcm_substream *substream, struct lola_stream *str) { - u32 *bdl; + __le32 *bdl; int i, ofs, periods, period_bytes; period_bytes = str->period_bytes; periods = str->bufsize / period_bytes; /* program the initial BDL entries */ - bdl = (u32 *)(pcm->bdl.area + LOLA_BDL_ENTRY_SIZE * str->index); + bdl = (__le32 *)(pcm->bdl.area + LOLA_BDL_ENTRY_SIZE * str->index); ofs = 0; str->frags = 0; for (i = 0; i < periods; i++) { -- cgit v1.2.3 From 3c164e2ce601bd7abf76d9f37b7f4afa6fa988a1 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 25 Jul 2018 23:24:07 +0200 Subject: ALSA: intel8x0: Proper endian notations The BD address tables in intel8x0 driver are in little-endian, hence they should be represented as __le32 instead u32. Spotted by sparse, warnings like: sound/pci/intel8x0.c:688:40: warning: incorrect type in assignment (different base types) Signed-off-by: Takashi Iwai --- sound/pci/intel8x0.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 4c24346340f4..5ee468d1aefe 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -351,7 +351,7 @@ enum { struct ichdev { unsigned int ichd; /* ich device number */ unsigned long reg_offset; /* offset to bmaddr */ - u32 *bdbar; /* CPU address (32bit) */ + __le32 *bdbar; /* CPU address (32bit) */ unsigned int bdbar_addr; /* PCI bus address (32bit) */ struct snd_pcm_substream *substream; unsigned int physbuf; /* physical address (32bit) */ @@ -677,7 +677,7 @@ static void snd_intel8x0_ali_codec_write(struct snd_ac97 *ac97, unsigned short r static void snd_intel8x0_setup_periods(struct intel8x0 *chip, struct ichdev *ichdev) { int idx; - u32 *bdbar = ichdev->bdbar; + __le32 *bdbar = ichdev->bdbar; unsigned long port = ichdev->reg_offset; iputdword(chip, port + ICH_REG_OFF_BDBAR, ichdev->bdbar_addr); @@ -3143,7 +3143,7 @@ static int snd_intel8x0_create(struct snd_card *card, int_sta_masks = 0; for (i = 0; i < chip->bdbars_count; i++) { ichdev = &chip->ichd[i]; - ichdev->bdbar = ((u32 *)chip->bdbars.area) + + ichdev->bdbar = ((__le32 *)chip->bdbars.area) + (i * ICH_MAX_FRAGS * 2); ichdev->bdbar_addr = chip->bdbars.addr + (i * sizeof(u32) * ICH_MAX_FRAGS * 2); -- cgit v1.2.3 From 7752a7de2596097c8f702fd652cba05118f83bcc Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 25 Jul 2018 23:24:08 +0200 Subject: ALSA: intel8x0m: Proper endian notations The BD address tables in intel8x0m driver are in little-endian, hence they should be represented as __le32 instead u32. Spotted by sparse, warnings like: sound/pci/intel8x0m.c:406:40: warning: incorrect type in assignment (different base types) Signed-off-by: Takashi Iwai --- sound/pci/intel8x0m.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c index 3a4769a97d29..943a726b1c1b 100644 --- a/sound/pci/intel8x0m.c +++ b/sound/pci/intel8x0m.c @@ -168,7 +168,7 @@ enum { ALID_MDMIN, ALID_MDMOUT, ALID_MDMLAST = ALID_MDMOUT }; struct ichdev { unsigned int ichd; /* ich device number */ unsigned long reg_offset; /* offset to bmaddr */ - u32 *bdbar; /* CPU address (32bit) */ + __le32 *bdbar; /* CPU address (32bit) */ unsigned int bdbar_addr; /* PCI bus address (32bit) */ struct snd_pcm_substream *substream; unsigned int physbuf; /* physical address (32bit) */ @@ -395,7 +395,7 @@ static unsigned short snd_intel8x0m_codec_read(struct snd_ac97 *ac97, static void snd_intel8x0m_setup_periods(struct intel8x0m *chip, struct ichdev *ichdev) { int idx; - u32 *bdbar = ichdev->bdbar; + __le32 *bdbar = ichdev->bdbar; unsigned long port = ichdev->reg_offset; iputdword(chip, port + ICH_REG_OFF_BDBAR, ichdev->bdbar_addr); @@ -1217,7 +1217,7 @@ static int snd_intel8x0m_create(struct snd_card *card, int_sta_masks = 0; for (i = 0; i < chip->bdbars_count; i++) { ichdev = &chip->ichd[i]; - ichdev->bdbar = ((u32 *)chip->bdbars.area) + (i * ICH_MAX_FRAGS * 2); + ichdev->bdbar = ((__le32 *)chip->bdbars.area) + (i * ICH_MAX_FRAGS * 2); ichdev->bdbar_addr = chip->bdbars.addr + (i * sizeof(u32) * ICH_MAX_FRAGS * 2); int_sta_masks |= ichdev->int_sta_mask; } -- cgit v1.2.3 From 8c0ab942e05941ade5f1fca59d29b7034fdf164c Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 25 Jul 2018 23:24:09 +0200 Subject: ALSA: maestro3: Proper endian notations The ASSP data passed to maestro3 driver is in little-endian format, hence the data pointer should be with __le16. Spotted by sparse, warnings like: sound/pci/maestro3.c:2128:35: warning: cast to restricted __le16 Signed-off-by: Takashi Iwai --- sound/pci/maestro3.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c index 224e942f556d..62962178a9d7 100644 --- a/sound/pci/maestro3.c +++ b/sound/pci/maestro3.c @@ -2103,7 +2103,7 @@ static const u16 minisrc_lpf[MINISRC_LPF_LEN] = { static void snd_m3_assp_init(struct snd_m3 *chip) { unsigned int i; - const u16 *data; + const __le16 *data; /* zero kernel data */ for (i = 0; i < (REV_B_DATA_MEMORY_UNIT_LENGTH * NUM_UNITS_KERNEL_DATA) / 2; i++) @@ -2121,7 +2121,7 @@ static void snd_m3_assp_init(struct snd_m3 *chip) KDATA_DMA_XFER0); /* write kernel into code memory.. */ - data = (const u16 *)chip->assp_kernel_image->data; + data = (const __le16 *)chip->assp_kernel_image->data; for (i = 0 ; i * 2 < chip->assp_kernel_image->size; i++) { snd_m3_assp_write(chip, MEMTYPE_INTERNAL_CODE, REV_B_CODE_MEMORY_BEGIN + i, @@ -2134,7 +2134,7 @@ static void snd_m3_assp_init(struct snd_m3 *chip) * drop it there. It seems that the minisrc doesn't * need vectors, so we won't bother with them.. */ - data = (const u16 *)chip->assp_minisrc_image->data; + data = (const __le16 *)chip->assp_minisrc_image->data; for (i = 0; i * 2 < chip->assp_minisrc_image->size; i++) { snd_m3_assp_write(chip, MEMTYPE_INTERNAL_CODE, 0x400 + i, le16_to_cpu(data[i])); -- cgit v1.2.3 From 2a833a02a12b1dbb605739d589d11b4400c2078c Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 25 Jul 2018 23:24:10 +0200 Subject: ALSA: echoaudio: Proper endian notations Many data fields defined in echoaudio drivers are in little-endian, hence they should be defined with __le16 or __le32. This makes it easier to catch the forgotten conversions. Spotted by sparse, a warning like: sound/pci/echoaudio/echoaudio_dsp.c:990:36: warning: incorrect type in assignment (different base types) Signed-off-by: Takashi Iwai --- sound/pci/echoaudio/echoaudio.h | 2 +- sound/pci/echoaudio/echoaudio_3g.c | 14 ++++++----- sound/pci/echoaudio/echoaudio_dsp.c | 6 ++--- sound/pci/echoaudio/echoaudio_dsp.h | 50 ++++++++++++++++++------------------- sound/pci/echoaudio/echoaudio_gml.c | 8 +++--- 5 files changed, 42 insertions(+), 38 deletions(-) (limited to 'sound') diff --git a/sound/pci/echoaudio/echoaudio.h b/sound/pci/echoaudio/echoaudio.h index 44b390a667d5..be4d0489394a 100644 --- a/sound/pci/echoaudio/echoaudio.h +++ b/sound/pci/echoaudio/echoaudio.h @@ -294,7 +294,7 @@ struct audiopipe { - volatile u32 *dma_counter; /* Commpage register that contains + volatile __le32 *dma_counter; /* Commpage register that contains * the current dma position * (lower 32 bits only) */ diff --git a/sound/pci/echoaudio/echoaudio_3g.c b/sound/pci/echoaudio/echoaudio_3g.c index 22c786b8a889..cc3c79387194 100644 --- a/sound/pci/echoaudio/echoaudio_3g.c +++ b/sound/pci/echoaudio/echoaudio_3g.c @@ -73,19 +73,21 @@ register. write_control_reg sends the new control register value to the DSP. */ static int write_control_reg(struct echoaudio *chip, u32 ctl, u32 frq, char force) { + __le32 ctl_reg, frq_reg; + if (wait_handshake(chip)) return -EIO; dev_dbg(chip->card->dev, "WriteControlReg: Setting 0x%x, 0x%x\n", ctl, frq); - ctl = cpu_to_le32(ctl); - frq = cpu_to_le32(frq); + ctl_reg = cpu_to_le32(ctl); + frq_reg = cpu_to_le32(frq); - if (ctl != chip->comm_page->control_register || - frq != chip->comm_page->e3g_frq_register || force) { - chip->comm_page->e3g_frq_register = frq; - chip->comm_page->control_register = ctl; + if (ctl_reg != chip->comm_page->control_register || + frq_reg != chip->comm_page->e3g_frq_register || force) { + chip->comm_page->e3g_frq_register = frq_reg; + chip->comm_page->control_register = ctl_reg; clear_handshake(chip); return send_vector(chip, DSP_VC_WRITE_CONTROL_REG); } diff --git a/sound/pci/echoaudio/echoaudio_dsp.c b/sound/pci/echoaudio/echoaudio_dsp.c index 15aae2fad8e4..b181752b8481 100644 --- a/sound/pci/echoaudio/echoaudio_dsp.c +++ b/sound/pci/echoaudio/echoaudio_dsp.c @@ -679,7 +679,7 @@ static int restore_dsp_rettings(struct echoaudio *chip) /* Gina20/Darla20 only. Should be harmless for other cards. */ chip->comm_page->gd_clock_state = GD_CLOCK_UNDEF; chip->comm_page->gd_spdif_status = GD_SPDIF_STATUS_UNDEF; - chip->comm_page->handshake = 0xffffffff; + chip->comm_page->handshake = cpu_to_le32(0xffffffff); /* Restore output busses */ for (i = 0; i < num_busses_out(chip); i++) { @@ -989,7 +989,7 @@ static int init_dsp_comm_page(struct echoaudio *chip) /* Init the comm page */ chip->comm_page->comm_size = cpu_to_le32(sizeof(struct comm_page)); - chip->comm_page->handshake = 0xffffffff; + chip->comm_page->handshake = cpu_to_le32(0xffffffff); chip->comm_page->midi_out_free_count = cpu_to_le32(DSP_MIDI_OUT_FIFO_SIZE); chip->comm_page->sample_rate = cpu_to_le32(44100); @@ -1087,7 +1087,7 @@ static int allocate_pipes(struct echoaudio *chip, struct audiopipe *pipe, /* The counter register is where the DSP writes the 32 bit DMA position for a pipe. The DSP is constantly updating this value as it moves data. The DMA counter is in units of bytes, not samples. */ - pipe->dma_counter = &chip->comm_page->position[pipe_index]; + pipe->dma_counter = (__le32 *)&chip->comm_page->position[pipe_index]; *pipe->dma_counter = 0; return pipe_index; } diff --git a/sound/pci/echoaudio/echoaudio_dsp.h b/sound/pci/echoaudio/echoaudio_dsp.h index cb7d75a0a503..aa9129519795 100644 --- a/sound/pci/echoaudio/echoaudio_dsp.h +++ b/sound/pci/echoaudio/echoaudio_dsp.h @@ -627,8 +627,8 @@ sg_entry struct is read by the DSP, so all values must be little-endian. */ #define MAX_SGLIST_ENTRIES 512 struct sg_entry { - u32 addr; - u32 size; + __le32 addr; + __le32 size; }; @@ -643,18 +643,18 @@ struct sg_entry { ****************************************************************************/ struct comm_page { /* Base Length*/ - u32 comm_size; /* size of this object 0x000 4 */ - u32 flags; /* See Appendix A below 0x004 4 */ - u32 unused; /* Unused entry 0x008 4 */ - u32 sample_rate; /* Card sample rate in Hz 0x00c 4 */ - u32 handshake; /* DSP command handshake 0x010 4 */ - u32 cmd_start; /* Chs. to start mask 0x014 4 */ - u32 cmd_stop; /* Chs. to stop mask 0x018 4 */ - u32 cmd_reset; /* Chs. to reset mask 0x01c 4 */ - u16 audio_format[DSP_MAXPIPES]; /* Chs. audio format 0x020 32*2 */ + __le32 comm_size; /* size of this object 0x000 4 */ + __le32 flags; /* See Appendix A below 0x004 4 */ + __le32 unused; /* Unused entry 0x008 4 */ + __le32 sample_rate; /* Card sample rate in Hz 0x00c 4 */ + __le32 handshake; /* DSP command handshake 0x010 4 */ + __le32 cmd_start; /* Chs. to start mask 0x014 4 */ + __le32 cmd_stop; /* Chs. to stop mask 0x018 4 */ + __le32 cmd_reset; /* Chs. to reset mask 0x01c 4 */ + __le16 audio_format[DSP_MAXPIPES]; /* Chs. audio format 0x020 32*2 */ struct sg_entry sglist_addr[DSP_MAXPIPES]; /* Chs. Physical sglist addrs 0x060 32*8 */ - u32 position[DSP_MAXPIPES]; + __le32 position[DSP_MAXPIPES]; /* Positions for ea. ch. 0x160 32*4 */ s8 vu_meter[DSP_MAXPIPES]; /* VU meters 0x1e0 32*1 */ @@ -666,28 +666,28 @@ struct comm_page { /* Base Length*/ /* Input gain 0x230 16*1 */ s8 monitors[MONITOR_ARRAY_SIZE]; /* Monitor map 0x240 0x180 */ - u32 play_coeff[MAX_PLAY_TAPS]; + __le32 play_coeff[MAX_PLAY_TAPS]; /* Gina/Darla play filters - obsolete 0x3c0 168*4 */ - u32 rec_coeff[MAX_REC_TAPS]; + __le32 rec_coeff[MAX_REC_TAPS]; /* Gina/Darla record filters - obsolete 0x660 192*4 */ - u16 midi_input[MIDI_IN_BUFFER_SIZE]; + __le16 midi_input[MIDI_IN_BUFFER_SIZE]; /* MIDI input data transfer buffer 0x960 256*2 */ u8 gd_clock_state; /* Chg Gina/Darla clock state 0xb60 1 */ u8 gd_spdif_status; /* Chg. Gina/Darla S/PDIF state 0xb61 1 */ u8 gd_resampler_state; /* Should always be 3 0xb62 1 */ u8 filler2; /* 0xb63 1 */ - u32 nominal_level_mask; /* -10 level enable mask 0xb64 4 */ - u16 input_clock; /* Chg. Input clock state 0xb68 2 */ - u16 output_clock; /* Chg. Output clock state 0xb6a 2 */ - u32 status_clocks; /* Current Input clock state 0xb6c 4 */ - u32 ext_box_status; /* External box status 0xb70 4 */ - u32 cmd_add_buffer; /* Pipes to add (obsolete) 0xb74 4 */ - u32 midi_out_free_count; + __le32 nominal_level_mask; /* -10 level enable mask 0xb64 4 */ + __le16 input_clock; /* Chg. Input clock state 0xb68 2 */ + __le16 output_clock; /* Chg. Output clock state 0xb6a 2 */ + __le32 status_clocks; /* Current Input clock state 0xb6c 4 */ + __le32 ext_box_status; /* External box status 0xb70 4 */ + __le32 cmd_add_buffer; /* Pipes to add (obsolete) 0xb74 4 */ + __le32 midi_out_free_count; /* # of bytes free in MIDI output FIFO 0xb78 4 */ - u32 unused2; /* Cyclic pipes 0xb7c 4 */ - u32 control_register; + __le32 unused2; /* Cyclic pipes 0xb7c 4 */ + __le32 control_register; /* Mona, Gina24, Layla24, 3G ctrl reg 0xb80 4 */ - u32 e3g_frq_register; /* 3G frequency register 0xb84 4 */ + __le32 e3g_frq_register; /* 3G frequency register 0xb84 4 */ u8 filler[24]; /* filler 0xb88 24*1 */ s8 vmixer[VMIXER_ARRAY_SIZE]; /* Vmixer levels 0xba0 64*1 */ diff --git a/sound/pci/echoaudio/echoaudio_gml.c b/sound/pci/echoaudio/echoaudio_gml.c index 834b39e97db7..eea6fe530ab4 100644 --- a/sound/pci/echoaudio/echoaudio_gml.c +++ b/sound/pci/echoaudio/echoaudio_gml.c @@ -63,6 +63,8 @@ the control register. write_control_reg sends the new control register value to the DSP. */ static int write_control_reg(struct echoaudio *chip, u32 value, char force) { + __le32 reg_value; + /* Handle the digital input auto-mute */ if (chip->digital_in_automute) value |= GML_DIGITAL_IN_AUTO_MUTE; @@ -72,11 +74,11 @@ static int write_control_reg(struct echoaudio *chip, u32 value, char force) dev_dbg(chip->card->dev, "write_control_reg: 0x%x\n", value); /* Write the control register */ - value = cpu_to_le32(value); - if (value != chip->comm_page->control_register || force) { + reg_value = cpu_to_le32(value); + if (reg_value != chip->comm_page->control_register || force) { if (wait_handshake(chip)) return -EIO; - chip->comm_page->control_register = value; + chip->comm_page->control_register = reg_value; clear_handshake(chip); return send_vector(chip, DSP_VC_WRITE_CONTROL_REG); } -- cgit v1.2.3 From 58578d1894490c62bf64c3293cb06e0fcdc86a31 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 25 Jul 2018 23:24:11 +0200 Subject: ALSA: bt87x: Proper endian notations The RISC data in bt87x is in little-endian, hence we should define it with __le32 properly. Spotted by sparse, a warning like: sound/pci/bt87x.c:240:17: warning: incorrect type in assignment (different base types) Signed-off-by: Takashi Iwai --- sound/pci/bt87x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c index d8ade8771a32..ba971042f871 100644 --- a/sound/pci/bt87x.c +++ b/sound/pci/bt87x.c @@ -228,14 +228,14 @@ static int snd_bt87x_create_risc(struct snd_bt87x *chip, struct snd_pcm_substrea unsigned int periods, unsigned int period_bytes) { unsigned int i, offset; - u32 *risc; + __le32 *risc; if (chip->dma_risc.area == NULL) { if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci), PAGE_ALIGN(MAX_RISC_SIZE), &chip->dma_risc) < 0) return -ENOMEM; } - risc = (u32 *)chip->dma_risc.area; + risc = (__le32 *)chip->dma_risc.area; offset = 0; *risc++ = cpu_to_le32(RISC_SYNC | RISC_SYNC_FM1); *risc++ = cpu_to_le32(0); -- cgit v1.2.3 From c44a81a40af0e1aa52b88d1c60682e30c411fb23 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 25 Jul 2018 23:24:12 +0200 Subject: ALSA: atiixp: Proper endian notations The DMA address table in atiixp driver is in little-endian, hence we should define it with __le32 properly. Spotted by sparse, a warning like: sound/pci/atiixp.c:393:28: warning: incorrect type in assignment (different base types) Signed-off-by: Takashi Iwai --- sound/pci/atiixp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c index 7ae63d452bba..a1e4944dcfe8 100644 --- a/sound/pci/atiixp.c +++ b/sound/pci/atiixp.c @@ -207,10 +207,10 @@ struct atiixp; */ struct atiixp_dma_desc { - u32 addr; /* DMA buffer address */ + __le32 addr; /* DMA buffer address */ u16 status; /* status bits */ u16 size; /* size of the packet in dwords */ - u32 next; /* address of the next packet descriptor */ + __le32 next; /* address of the next packet descriptor */ }; /* -- cgit v1.2.3 From 7e49aadf64992c138b354a2e9ae35a3ae0399415 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 25 Jul 2018 23:24:13 +0200 Subject: ALSA: atiixp_modem: Proper endian notations The DMA address table in atiixp modem driver is in little-endian, hence we should define it with __le32 properly. Spotted by sparse, a warning like: sound/pci/atiixp_modem.c:360:28: warning: incorrect type in assignment (different base types) Signed-off-by: Takashi Iwai --- sound/pci/atiixp_modem.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c index a586635664e0..dc1de860cedf 100644 --- a/sound/pci/atiixp_modem.c +++ b/sound/pci/atiixp_modem.c @@ -183,10 +183,10 @@ struct atiixp_modem; */ struct atiixp_dma_desc { - u32 addr; /* DMA buffer address */ + __le32 addr; /* DMA buffer address */ u16 status; /* status bits */ u16 size; /* size of the packet in dwords */ - u32 next; /* address of the next packet descriptor */ + __le32 next; /* address of the next packet descriptor */ }; /* -- cgit v1.2.3 From 13e9a3edb4b702b701b5a9553b830aa3d2a3e3e9 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 25 Jul 2018 23:24:14 +0200 Subject: ALSA: sb: Proper endian notations The data types defined in SB CSP driver code are all in little-endian, hence the proper type like __le32 should be used. Spotted by sparse, a warning like: sound/isa/sb/sb16_csp.c:330:14: warning: cast to restricted __le32 Signed-off-by: Takashi Iwai --- sound/isa/sb/sb16_csp.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'sound') diff --git a/sound/isa/sb/sb16_csp.c b/sound/isa/sb/sb16_csp.c index 2210e7c72787..b9d67a7065cd 100644 --- a/sound/isa/sb/sb16_csp.c +++ b/sound/isa/sb/sb16_csp.c @@ -60,18 +60,18 @@ MODULE_FIRMWARE("sb16/ima_adpcm_capture.csp"); * RIFF data format */ struct riff_header { - __u32 name; - __u32 len; + __le32 name; + __le32 len; }; struct desc_header { struct riff_header info; - __u16 func_nr; - __u16 VOC_type; - __u16 flags_play_rec; - __u16 flags_16bit_8bit; - __u16 flags_stereo_mono; - __u16 flags_rates; + __le16 func_nr; + __le16 VOC_type; + __le16 flags_play_rec; + __le16 flags_16bit_8bit; + __le16 flags_stereo_mono; + __le16 flags_rates; }; /* @@ -314,7 +314,7 @@ static int snd_sb_csp_riff_load(struct snd_sb_csp * p, unsigned short func_nr = 0; struct riff_header file_h, item_h, code_h; - __u32 item_type; + __le32 item_type; struct desc_header funcdesc_h; unsigned long flags; @@ -326,7 +326,7 @@ static int snd_sb_csp_riff_load(struct snd_sb_csp * p, if (copy_from_user(&file_h, data_ptr, sizeof(file_h))) return -EFAULT; - if ((file_h.name != RIFF_HEADER) || + if ((le32_to_cpu(file_h.name) != RIFF_HEADER) || (le32_to_cpu(file_h.len) >= SNDRV_SB_CSP_MAX_MICROCODE_FILE_SIZE - sizeof(file_h))) { snd_printd("%s: Invalid RIFF header\n", __func__); return -EINVAL; @@ -336,7 +336,7 @@ static int snd_sb_csp_riff_load(struct snd_sb_csp * p, if (copy_from_user(&item_type, data_ptr, sizeof(item_type))) return -EFAULT; - if (item_type != CSP__HEADER) { + if (le32_to_cpu(item_type) != CSP__HEADER) { snd_printd("%s: Invalid RIFF file type\n", __func__); return -EINVAL; } @@ -346,12 +346,12 @@ static int snd_sb_csp_riff_load(struct snd_sb_csp * p, if (copy_from_user(&item_h, data_ptr, sizeof(item_h))) return -EFAULT; data_ptr += sizeof(item_h); - if (item_h.name != LIST_HEADER) + if (le32_to_cpu(item_h.name) != LIST_HEADER) continue; if (copy_from_user(&item_type, data_ptr, sizeof(item_type))) return -EFAULT; - switch (item_type) { + switch (le32_to_cpu(item_type)) { case FUNC_HEADER: if (copy_from_user(&funcdesc_h, data_ptr + sizeof(item_type), sizeof(funcdesc_h))) return -EFAULT; @@ -378,7 +378,7 @@ static int snd_sb_csp_riff_load(struct snd_sb_csp * p, return -EFAULT; /* init microcode blocks */ - if (code_h.name != INIT_HEADER) + if (le32_to_cpu(code_h.name) != INIT_HEADER) break; data_ptr += sizeof(code_h); err = snd_sb_csp_load_user(p, data_ptr, le32_to_cpu(code_h.len), @@ -391,7 +391,7 @@ static int snd_sb_csp_riff_load(struct snd_sb_csp * p, if (copy_from_user(&code_h, data_ptr, sizeof(code_h))) return -EFAULT; - if (code_h.name != MAIN_HEADER) { + if (le32_to_cpu(code_h.name) != MAIN_HEADER) { snd_printd("%s: Missing 'main' microcode\n", __func__); return -EINVAL; } -- cgit v1.2.3 From df3f0347fd856272ca9fdbb6e691b7b512b7acb4 Mon Sep 17 00:00:00 2001 From: Jia-Ju Bai Date: Fri, 27 Jul 2018 16:55:28 +0800 Subject: ALSA: usb-audio: quirks: Replace mdelay() with msleep() and usleep_range() snd_usb_select_mode_quirk(), snd_usb_set_interface_quirk() and snd_usb_ctl_msg_quirk() are never called in atomic context. They call mdelay() to busily wait, which is not necessary. mdelay() can be replaced with msleep() and usleep_range(). This is found by a static analysis tool named DCNS written by myself. Signed-off-by: Jia-Ju Bai Signed-off-by: Takashi Iwai --- sound/usb/quirks.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'sound') diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index dde87d64bc32..8a945ece9869 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -1213,7 +1213,7 @@ int snd_usb_select_mode_quirk(struct snd_usb_substream *subs, if (err < 0) return err; - mdelay(20); /* Delay needed after setting the interface */ + msleep(20); /* Delay needed after setting the interface */ /* Vendor mode switch cmd is required. */ if (fmt->formats & SNDRV_PCM_FMTBIT_DSD_U32_BE) { @@ -1234,7 +1234,7 @@ int snd_usb_select_mode_quirk(struct snd_usb_substream *subs, return err; } - mdelay(20); + msleep(20); } return 0; } @@ -1281,7 +1281,7 @@ void snd_usb_set_interface_quirk(struct usb_device *dev) switch (USB_ID_VENDOR(chip->usb_id)) { case 0x23ba: /* Playback Design */ case 0x0644: /* TEAC Corp. */ - mdelay(50); + msleep(50); break; } } @@ -1301,7 +1301,7 @@ void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe, */ if (USB_ID_VENDOR(chip->usb_id) == 0x23ba && (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS) - mdelay(20); + msleep(20); /* * "TEAC Corp." products need a 20ms delay after each @@ -1309,14 +1309,14 @@ void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe, */ if (USB_ID_VENDOR(chip->usb_id) == 0x0644 && (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS) - mdelay(20); + msleep(20); /* ITF-USB DSD based DACs functionality need a delay * after each class compliant request */ if (is_itf_usb_dsd_dac(chip->usb_id) && (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS) - mdelay(20); + msleep(20); /* Zoom R16/24, Logitech H650e, Jabra 550a needs a tiny delay here, * otherwise requests like get/set frequency return as failed despite @@ -1326,7 +1326,7 @@ void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe, chip->usb_id == USB_ID(0x046d, 0x0a46) || chip->usb_id == USB_ID(0x0b0e, 0x0349)) && (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS) - mdelay(1); + usleep_range(1000, 2000); } /* -- cgit v1.2.3 From 08fd8325d94eeddfe49ef8191337e5f54553f6b0 Mon Sep 17 00:00:00 2001 From: Jia-Ju Bai Date: Fri, 27 Jul 2018 16:57:56 +0800 Subject: ALSA:: ctxfi: cthw20k1: Replace mdelay() with msleep() hw_pll_init(), hw_reset_dac() and hw_card_init() are never called in atomic context. They calls mdelay() to busily wait, which is not necessary. mdelay() can be replaced with msleep(). This is found by a static analysis tool named DCNS written by myself. Signed-off-by: Jia-Ju Bai Signed-off-by: Takashi Iwai --- sound/pci/ctxfi/cthw20k1.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/pci/ctxfi/cthw20k1.c b/sound/pci/ctxfi/cthw20k1.c index 8e6eb9d7984b..6a051a1c3724 100644 --- a/sound/pci/ctxfi/cthw20k1.c +++ b/sound/pci/ctxfi/cthw20k1.c @@ -1319,7 +1319,7 @@ static int hw_pll_init(struct hw *hw, unsigned int rsr) break; hw_write_20kx(hw, PLLCTL, pllctl); - mdelay(40); + msleep(40); } if (i >= 3) { dev_alert(hw->card->dev, "PLL initialization failed!!!\n"); @@ -1407,7 +1407,7 @@ static int hw_reset_dac(struct hw *hw) /* To be effective, need to reset the DAC twice. */ for (i = 0; i < 2; i++) { /* set gpio */ - mdelay(100); + msleep(100); gpioorg = (u16)hw_read_20kx(hw, GPIO); gpioorg &= 0xfffd; hw_write_20kx(hw, GPIO, gpioorg); @@ -2030,7 +2030,7 @@ static int hw_card_init(struct hw *hw, struct card_conf *info) hw_write_20kx(hw, GIE, 0); /* Reset all SRC pending interrupts */ hw_write_20kx(hw, SRCIP, 0); - mdelay(30); + msleep(30); /* Detect the card ID and configure GPIO accordingly. */ switch (hw->model) { -- cgit v1.2.3 From fad56c895f1f33f9063da558067307b00d44d40d Mon Sep 17 00:00:00 2001 From: Jia-Ju Bai Date: Fri, 27 Jul 2018 17:01:43 +0800 Subject: ALSA: ctxfi: cthw20k2: Replace mdelay() with msleep() and usleep_range() hw_pll_init(), hw_dac_stop(), hw_dac_start() and hw_adc_init() are never called in atomic context. They call mdelay() to busily wait, which is not necessary. mdelay() can be replaced with msleep(). This is found by a static analysis tool named DCNS written by myself. Signed-off-by: Jia-Ju Bai Signed-off-by: Takashi Iwai --- sound/pci/ctxfi/cthw20k2.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'sound') diff --git a/sound/pci/ctxfi/cthw20k2.c b/sound/pci/ctxfi/cthw20k2.c index b866d6b2c923..3c966fafc754 100644 --- a/sound/pci/ctxfi/cthw20k2.c +++ b/sound/pci/ctxfi/cthw20k2.c @@ -1316,12 +1316,12 @@ static int hw_pll_init(struct hw *hw, unsigned int rsr) set_field(&pllctl, PLLCTL_FD, 48000 == rsr ? 16 - 4 : 147 - 4); set_field(&pllctl, PLLCTL_RD, 48000 == rsr ? 1 - 1 : 10 - 1); hw_write_20kx(hw, PLL_CTL, pllctl); - mdelay(40); + msleep(40); pllctl = hw_read_20kx(hw, PLL_CTL); set_field(&pllctl, PLLCTL_FD, 48000 == rsr ? 16 - 2 : 147 - 2); hw_write_20kx(hw, PLL_CTL, pllctl); - mdelay(40); + msleep(40); for (i = 0; i < 1000; i++) { pllstat = hw_read_20kx(hw, PLL_STAT); @@ -1584,7 +1584,7 @@ static void hw_dac_stop(struct hw *hw) data = hw_read_20kx(hw, GPIO_DATA); data &= 0xFFFFFFFD; hw_write_20kx(hw, GPIO_DATA, data); - mdelay(10); + usleep_range(10000, 11000); } static void hw_dac_start(struct hw *hw) @@ -1593,7 +1593,7 @@ static void hw_dac_start(struct hw *hw) data = hw_read_20kx(hw, GPIO_DATA); data |= 0x2; hw_write_20kx(hw, GPIO_DATA, data); - mdelay(50); + msleep(50); } static void hw_dac_reset(struct hw *hw) @@ -1864,11 +1864,11 @@ static int hw_adc_init(struct hw *hw, const struct adc_conf *info) hw_write_20kx(hw, GPIO_DATA, data); } - mdelay(10); + usleep_range(10000, 11000); /* Return the ADC to normal operation. */ data |= (0x1 << 15); hw_write_20kx(hw, GPIO_DATA, data); - mdelay(50); + msleep(50); /* I2C write to register offset 0x0B to set ADC LRCLK polarity */ /* invert bit, interface format to I2S, word length to 24-bit, */ -- cgit v1.2.3 From f69548ffafcc4942022f16f2f192b24143de1dba Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 12 Jul 2018 23:06:51 +0200 Subject: ALSA: hda/hdmi: Use single mutex unlock in error paths Instead of calling mutex_unlock() at each error path multiple times, take the standard goto-and-a-single-unlock approach. This will simplify the code and make easier to find the unbalanced mutex locks. No functional changes, but only the code readability improvement as a preliminary work for further changes. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 67 +++++++++++++++++++++++----------------------- 1 file changed, 33 insertions(+), 34 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index ee56359be9ee..cb587dce67a9 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -339,13 +339,13 @@ static int hdmi_eld_ctl_info(struct snd_kcontrol *kcontrol, if (!per_pin) { /* no pin is bound to the pcm */ uinfo->count = 0; - mutex_unlock(&spec->pcm_lock); - return 0; + goto unlock; } eld = &per_pin->sink_eld; uinfo->count = eld->eld_valid ? eld->eld_size : 0; - mutex_unlock(&spec->pcm_lock); + unlock: + mutex_unlock(&spec->pcm_lock); return 0; } @@ -357,6 +357,7 @@ static int hdmi_eld_ctl_get(struct snd_kcontrol *kcontrol, struct hdmi_spec_per_pin *per_pin; struct hdmi_eld *eld; int pcm_idx; + int err = 0; pcm_idx = kcontrol->private_value; mutex_lock(&spec->pcm_lock); @@ -365,16 +366,15 @@ static int hdmi_eld_ctl_get(struct snd_kcontrol *kcontrol, /* no pin is bound to the pcm */ memset(ucontrol->value.bytes.data, 0, ARRAY_SIZE(ucontrol->value.bytes.data)); - mutex_unlock(&spec->pcm_lock); - return 0; + goto unlock; } - eld = &per_pin->sink_eld; + eld = &per_pin->sink_eld; if (eld->eld_size > ARRAY_SIZE(ucontrol->value.bytes.data) || eld->eld_size > ELD_MAX_SIZE) { - mutex_unlock(&spec->pcm_lock); snd_BUG(); - return -EINVAL; + err = -EINVAL; + goto unlock; } memset(ucontrol->value.bytes.data, 0, @@ -382,9 +382,10 @@ static int hdmi_eld_ctl_get(struct snd_kcontrol *kcontrol, if (eld->eld_valid) memcpy(ucontrol->value.bytes.data, eld->eld_buffer, eld->eld_size); - mutex_unlock(&spec->pcm_lock); - return 0; + unlock: + mutex_unlock(&spec->pcm_lock); + return err; } static const struct snd_kcontrol_new eld_bytes_ctl = { @@ -1209,8 +1210,8 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, pin_idx = hinfo_to_pin_index(codec, hinfo); if (!spec->dyn_pcm_assign) { if (snd_BUG_ON(pin_idx < 0)) { - mutex_unlock(&spec->pcm_lock); - return -EINVAL; + err = -EINVAL; + goto unlock; } } else { /* no pin is assigned to the PCM @@ -1218,16 +1219,13 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, */ if (pin_idx < 0) { err = hdmi_pcm_open_no_pin(hinfo, codec, substream); - mutex_unlock(&spec->pcm_lock); - return err; + goto unlock; } } err = hdmi_choose_cvt(codec, pin_idx, &cvt_idx); - if (err < 0) { - mutex_unlock(&spec->pcm_lock); - return err; - } + if (err < 0) + goto unlock; per_cvt = get_cvt(spec, cvt_idx); /* Claim converter */ @@ -1264,12 +1262,11 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, per_cvt->assigned = 0; hinfo->nid = 0; snd_hda_spdif_ctls_unassign(codec, pcm_idx); - mutex_unlock(&spec->pcm_lock); - return -ENODEV; + err = -ENODEV; + goto unlock; } } - mutex_unlock(&spec->pcm_lock); /* Store the updated parameters */ runtime->hw.channels_min = hinfo->channels_min; runtime->hw.channels_max = hinfo->channels_max; @@ -1278,7 +1275,9 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, snd_pcm_hw_constraint_step(substream->runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 2); - return 0; + unlock: + mutex_unlock(&spec->pcm_lock); + return err; } /* @@ -1867,7 +1866,7 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, struct snd_pcm_runtime *runtime = substream->runtime; bool non_pcm; int pinctl; - int err; + int err = 0; mutex_lock(&spec->pcm_lock); pin_idx = hinfo_to_pin_index(codec, hinfo); @@ -1879,13 +1878,12 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, pin_cvt_fixup(codec, NULL, cvt_nid); snd_hda_codec_setup_stream(codec, cvt_nid, stream_tag, 0, format); - mutex_unlock(&spec->pcm_lock); - return 0; + goto unlock; } if (snd_BUG_ON(pin_idx < 0)) { - mutex_unlock(&spec->pcm_lock); - return -EINVAL; + err = -EINVAL; + goto unlock; } per_pin = get_pin(spec, pin_idx); pin_nid = per_pin->pin_nid; @@ -1924,6 +1922,7 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, /* snd_hda_set_dev_select() has been called before */ err = spec->ops.setup_stream(codec, cvt_nid, pin_nid, stream_tag, format); + unlock: mutex_unlock(&spec->pcm_lock); return err; } @@ -1945,6 +1944,7 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo, struct hdmi_spec_per_cvt *per_cvt; struct hdmi_spec_per_pin *per_pin; int pinctl; + int err = 0; if (hinfo->nid) { pcm_idx = hinfo_to_pcm_index(codec, hinfo); @@ -1963,14 +1963,12 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo, snd_hda_spdif_ctls_unassign(codec, pcm_idx); clear_bit(pcm_idx, &spec->pcm_in_use); pin_idx = hinfo_to_pin_index(codec, hinfo); - if (spec->dyn_pcm_assign && pin_idx < 0) { - mutex_unlock(&spec->pcm_lock); - return 0; - } + if (spec->dyn_pcm_assign && pin_idx < 0) + goto unlock; if (snd_BUG_ON(pin_idx < 0)) { - mutex_unlock(&spec->pcm_lock); - return -EINVAL; + err = -EINVAL; + goto unlock; } per_pin = get_pin(spec, pin_idx); @@ -1989,10 +1987,11 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo, per_pin->setup = false; per_pin->channels = 0; mutex_unlock(&per_pin->lock); + unlock: mutex_unlock(&spec->pcm_lock); } - return 0; + return err; } static const struct hda_pcm_ops generic_ops = { -- cgit v1.2.3 From f7debfe54090d1a1c38e1f070be20d83bb70a8e0 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sun, 29 Jul 2018 23:03:05 +0200 Subject: ALSA: seq: virmidi: Offload the output event processing The virmidi sequencer stuff tries to translate the rawmidi bytes to sequencer events and deliver the packets at trigger callback. The amount of the whole process of these translations and deliveries depends on the incoming rawmidi bytes, and we have no limit for that; this was the cause of a CPU soft lockup that had been reported and fixed recently. Although we've fixed the soft lockup by putting the temporary unlock and cond_resched(), it's rather a quick band aid. In this patch, meanwhile, the event parsing and delivery process is offloaded to a dedicated work, and the trigger callback just kicks it off. It has three merits, at least: - The processing is always done in a sleepable context, which can assure the event delivery with non-atomic flag without hackish is_atomic() usage. - Other relevant codes can be simplified, reducing the lines - It makes me happier Signed-off-by: Takashi Iwai --- include/sound/seq_virmidi.h | 1 + sound/core/seq/seq_virmidi.c | 100 ++++++++++++++++++++----------------------- 2 files changed, 47 insertions(+), 54 deletions(-) (limited to 'sound') diff --git a/include/sound/seq_virmidi.h b/include/sound/seq_virmidi.h index 695257ae64ac..d488dcfa3a4e 100644 --- a/include/sound/seq_virmidi.h +++ b/include/sound/seq_virmidi.h @@ -41,6 +41,7 @@ struct snd_virmidi { struct snd_seq_event event; struct snd_virmidi_dev *rdev; struct snd_rawmidi_substream *substream; + struct work_struct output_work; }; #define SNDRV_VIRMIDI_SUBSCRIBE (1<<0) diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c index 8ebbca554e99..67ea5d62cebc 100644 --- a/sound/core/seq/seq_virmidi.c +++ b/sound/core/seq/seq_virmidi.c @@ -154,70 +154,58 @@ static void snd_virmidi_input_trigger(struct snd_rawmidi_substream *substream, i } } -/* - * trigger rawmidi stream for output +/* process rawmidi bytes and send events; + * we need no lock here for vmidi->event since it's handled only in this work */ -static void snd_virmidi_output_trigger(struct snd_rawmidi_substream *substream, int up) +static void snd_vmidi_output_work(struct work_struct *work) { - struct snd_virmidi *vmidi = substream->runtime->private_data; - int count, res; - unsigned char buf[32], *pbuf; - unsigned long flags; - bool check_resched = !in_atomic(); + struct snd_virmidi *vmidi; + struct snd_rawmidi_substream *substream; + unsigned char input; + int ret; + + vmidi = container_of(work, struct snd_virmidi, output_work); + substream = vmidi->substream; + + /* discard the outputs in dispatch mode unless subscribed */ + if (vmidi->seq_mode == SNDRV_VIRMIDI_SEQ_DISPATCH && + !(vmidi->rdev->flags & SNDRV_VIRMIDI_SUBSCRIBE)) { + while (!snd_rawmidi_transmit_empty(substream)) + snd_rawmidi_transmit_ack(substream, 1); + return; + } - if (up) { - vmidi->trigger = 1; - if (vmidi->seq_mode == SNDRV_VIRMIDI_SEQ_DISPATCH && - !(vmidi->rdev->flags & SNDRV_VIRMIDI_SUBSCRIBE)) { - while (snd_rawmidi_transmit(substream, buf, - sizeof(buf)) > 0) { - /* ignored */ - } - return; - } - spin_lock_irqsave(&substream->runtime->lock, flags); + while (vmidi->trigger) { + if (snd_rawmidi_transmit(substream, &input, 1) != 1) + break; + if (snd_midi_event_encode_byte(vmidi->parser, input, + &vmidi->event) <= 0) + continue; if (vmidi->event.type != SNDRV_SEQ_EVENT_NONE) { - if (snd_seq_kernel_client_dispatch(vmidi->client, &vmidi->event, in_atomic(), 0) < 0) - goto out; + ret = snd_seq_kernel_client_dispatch(vmidi->client, + &vmidi->event, + false, 0); vmidi->event.type = SNDRV_SEQ_EVENT_NONE; - } - while (1) { - count = __snd_rawmidi_transmit_peek(substream, buf, sizeof(buf)); - if (count <= 0) + if (ret < 0) break; - pbuf = buf; - while (count > 0) { - res = snd_midi_event_encode(vmidi->parser, pbuf, count, &vmidi->event); - if (res < 0) { - snd_midi_event_reset_encode(vmidi->parser); - continue; - } - __snd_rawmidi_transmit_ack(substream, res); - pbuf += res; - count -= res; - if (vmidi->event.type != SNDRV_SEQ_EVENT_NONE) { - if (snd_seq_kernel_client_dispatch(vmidi->client, &vmidi->event, in_atomic(), 0) < 0) - goto out; - vmidi->event.type = SNDRV_SEQ_EVENT_NONE; - } - } - if (!check_resched) - continue; - /* do temporary unlock & cond_resched() for avoiding - * CPU soft lockup, which may happen via a write from - * a huge rawmidi buffer - */ - spin_unlock_irqrestore(&substream->runtime->lock, flags); - cond_resched(); - spin_lock_irqsave(&substream->runtime->lock, flags); } - out: - spin_unlock_irqrestore(&substream->runtime->lock, flags); - } else { - vmidi->trigger = 0; + /* rawmidi input might be huge, allow to have a break */ + cond_resched(); } } +/* + * trigger rawmidi stream for output + */ +static void snd_virmidi_output_trigger(struct snd_rawmidi_substream *substream, int up) +{ + struct snd_virmidi *vmidi = substream->runtime->private_data; + + vmidi->trigger = !!up; + if (up) + queue_work(system_highpri_wq, &vmidi->output_work); +} + /* * open rawmidi handle for input */ @@ -270,6 +258,7 @@ static int snd_virmidi_output_open(struct snd_rawmidi_substream *substream) vmidi->port = rdev->port; snd_virmidi_init_event(vmidi, &vmidi->event); vmidi->rdev = rdev; + INIT_WORK(&vmidi->output_work, snd_vmidi_output_work); runtime->private_data = vmidi; return 0; } @@ -299,6 +288,9 @@ static int snd_virmidi_input_close(struct snd_rawmidi_substream *substream) static int snd_virmidi_output_close(struct snd_rawmidi_substream *substream) { struct snd_virmidi *vmidi = substream->runtime->private_data; + + vmidi->trigger = 0; /* to be sure */ + cancel_work_sync(&vmidi->output_work); snd_midi_event_free(vmidi->parser); substream->runtime->private_data = NULL; kfree(vmidi); -- cgit v1.2.3 From 89b4ab213feb11a5bece544cfa12374f66c2c47c Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 30 Jul 2018 14:48:29 +0200 Subject: ALSA: seq: virmidi: Use READ_ONCE/WRITE_ONCE() macros The trigger flag in vmidi object can be referred in different contexts concurrently, hence it's better to be put with READ_ONCE() and WRITE_ONCE() macros to assure the accesses. Signed-off-by: Takashi Iwai --- include/sound/seq_virmidi.h | 2 +- sound/core/seq/seq_virmidi.c | 14 +++++--------- 2 files changed, 6 insertions(+), 10 deletions(-) (limited to 'sound') diff --git a/include/sound/seq_virmidi.h b/include/sound/seq_virmidi.h index d488dcfa3a4e..796ce7772213 100644 --- a/include/sound/seq_virmidi.h +++ b/include/sound/seq_virmidi.h @@ -36,7 +36,7 @@ struct snd_virmidi { int seq_mode; int client; int port; - unsigned int trigger: 1; + bool trigger; struct snd_midi_event *parser; struct snd_seq_event event; struct snd_virmidi_dev *rdev; diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c index 67ea5d62cebc..03ac5e72dbe6 100644 --- a/sound/core/seq/seq_virmidi.c +++ b/sound/core/seq/seq_virmidi.c @@ -89,7 +89,7 @@ static int snd_virmidi_dev_receive_event(struct snd_virmidi_dev *rdev, else down_read(&rdev->filelist_sem); list_for_each_entry(vmidi, &rdev->filelist, list) { - if (!vmidi->trigger) + if (!READ_ONCE(vmidi->trigger)) continue; if (ev->type == SNDRV_SEQ_EVENT_SYSEX) { if ((ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) != SNDRV_SEQ_EVENT_LENGTH_VARIABLE) @@ -147,11 +147,7 @@ static void snd_virmidi_input_trigger(struct snd_rawmidi_substream *substream, i { struct snd_virmidi *vmidi = substream->runtime->private_data; - if (up) { - vmidi->trigger = 1; - } else { - vmidi->trigger = 0; - } + WRITE_ONCE(vmidi->trigger, !!up); } /* process rawmidi bytes and send events; @@ -175,7 +171,7 @@ static void snd_vmidi_output_work(struct work_struct *work) return; } - while (vmidi->trigger) { + while (READ_ONCE(vmidi->trigger)) { if (snd_rawmidi_transmit(substream, &input, 1) != 1) break; if (snd_midi_event_encode_byte(vmidi->parser, input, @@ -201,7 +197,7 @@ static void snd_virmidi_output_trigger(struct snd_rawmidi_substream *substream, { struct snd_virmidi *vmidi = substream->runtime->private_data; - vmidi->trigger = !!up; + WRITE_ONCE(vmidi->trigger, !!up); if (up) queue_work(system_highpri_wq, &vmidi->output_work); } @@ -289,7 +285,7 @@ static int snd_virmidi_output_close(struct snd_rawmidi_substream *substream) { struct snd_virmidi *vmidi = substream->runtime->private_data; - vmidi->trigger = 0; /* to be sure */ + WRITE_ONCE(vmidi->trigger, false); /* to be sure */ cancel_work_sync(&vmidi->output_work); snd_midi_event_free(vmidi->parser); substream->runtime->private_data = NULL; -- cgit v1.2.3 From 11785ef53228d23ec386f5fe4a34601536f0c891 Mon Sep 17 00:00:00 2001 From: Jorge Sanjuan Date: Tue, 31 Jul 2018 13:28:42 +0100 Subject: ALSA: usb-audio: Initial Power Domain support Thee USB Audio Class 3 (UAC3) introduces Power Domains as a new feature to let a host turn individual parts of an audio function to different power states via USB requests. This lets the device get to know a bit amore about what the host is up to in order to optimize power consumption efficiently. The Power Domains are optional for UAC3 configuration but all UAC3 devices shall include at least one BADD configuration where the support for Power Domains is compulsory. This patch adds a set of features/helpers to parse these power domains and change their status. Signed-off-by: Jorge Sanjuan Signed-off-by: Takashi Iwai --- include/linux/usb/audio-v3.h | 4 ++ sound/usb/Makefile | 1 + sound/usb/power.c | 104 +++++++++++++++++++++++++++++++++++++++++++ sound/usb/power.h | 19 ++++++++ 4 files changed, 128 insertions(+) create mode 100644 sound/usb/power.c (limited to 'sound') diff --git a/include/linux/usb/audio-v3.h b/include/linux/usb/audio-v3.h index 334bfa6dfb47..6b708434b7f9 100644 --- a/include/linux/usb/audio-v3.h +++ b/include/linux/usb/audio-v3.h @@ -447,4 +447,8 @@ struct uac3_interrupt_data_msg { /* BADD sample rate is always fixed to 48kHz */ #define UAC3_BADD_SAMPLING_RATE 48000 +/* BADD power domains recovery times in 50us increments */ +#define UAC3_BADD_PD_RECOVER_D1D0 0x0258 /* 30ms */ +#define UAC3_BADD_PD_RECOVER_D2D0 0x1770 /* 300ms */ + #endif /* __LINUX_USB_AUDIO_V3_H */ diff --git a/sound/usb/Makefile b/sound/usb/Makefile index 05440e2df8d9..d330f74c90e6 100644 --- a/sound/usb/Makefile +++ b/sound/usb/Makefile @@ -13,6 +13,7 @@ snd-usb-audio-objs := card.o \ mixer_scarlett.o \ mixer_us16x08.o \ pcm.o \ + power.o \ proc.o \ quirks.o \ stream.o diff --git a/sound/usb/power.c b/sound/usb/power.c new file mode 100644 index 000000000000..bd303a1ba1b7 --- /dev/null +++ b/sound/usb/power.c @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * UAC3 Power Domain state management functions + */ + +#include +#include +#include +#include +#include + +#include "usbaudio.h" +#include "helper.h" +#include "power.h" + +struct snd_usb_power_domain * +snd_usb_find_power_domain(struct usb_host_interface *ctrl_iface, + unsigned char id) +{ + struct snd_usb_power_domain *pd; + void *p; + + pd = kzalloc(sizeof(*pd), GFP_KERNEL); + if (!pd) + return NULL; + + p = NULL; + while ((p = snd_usb_find_csint_desc(ctrl_iface->extra, + ctrl_iface->extralen, + p, UAC3_POWER_DOMAIN)) != NULL) { + struct uac3_power_domain_descriptor *pd_desc = p; + int i; + + for (i = 0; i < pd_desc->bNrEntities; i++) { + if (pd_desc->baEntityID[i] == id) { + pd->pd_id = pd_desc->bPowerDomainID; + pd->pd_d1d0_rec = + le16_to_cpu(pd_desc->waRecoveryTime1); + pd->pd_d2d0_rec = + le16_to_cpu(pd_desc->waRecoveryTime2); + return pd; + } + } + } + + kfree(pd); + return NULL; +} + +int snd_usb_power_domain_set(struct snd_usb_audio *chip, + struct snd_usb_power_domain *pd, + unsigned char state) +{ + struct usb_device *dev = chip->dev; + unsigned char current_state; + int err, idx; + + idx = snd_usb_ctrl_intf(chip) | (pd->pd_id << 8); + + err = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), + UAC2_CS_CUR, + USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, + UAC3_AC_POWER_DOMAIN_CONTROL << 8, idx, + ¤t_state, sizeof(current_state)); + if (err < 0) { + dev_err(&dev->dev, "Can't get UAC3 power state for id %d\n", + pd->pd_id); + return err; + } + + if (current_state == state) { + dev_dbg(&dev->dev, "UAC3 power domain id %d already in state %d\n", + pd->pd_id, state); + return 0; + } + + err = snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0), UAC2_CS_CUR, + USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, + UAC3_AC_POWER_DOMAIN_CONTROL << 8, idx, + &state, sizeof(state)); + if (err < 0) { + dev_err(&dev->dev, "Can't set UAC3 power state to %d for id %d\n", + state, pd->pd_id); + return err; + } + + if (state == UAC3_PD_STATE_D0) { + switch (current_state) { + case UAC3_PD_STATE_D2: + udelay(pd->pd_d2d0_rec * 50); + break; + case UAC3_PD_STATE_D1: + udelay(pd->pd_d1d0_rec * 50); + break; + default: + return -EINVAL; + } + } + + dev_dbg(&dev->dev, "UAC3 power domain id %d change to state %d\n", + pd->pd_id, state); + + return 0; +} diff --git a/sound/usb/power.h b/sound/usb/power.h index b2e25f60c5a2..6004231a7c75 100644 --- a/sound/usb/power.h +++ b/sound/usb/power.h @@ -2,6 +2,25 @@ #ifndef __USBAUDIO_POWER_H #define __USBAUDIO_POWER_H +struct snd_usb_power_domain { + int pd_id; /* UAC3 Power Domain ID */ + int pd_d1d0_rec; /* D1 to D0 recovery time */ + int pd_d2d0_rec; /* D2 to D0 recovery time */ +}; + +enum { + UAC3_PD_STATE_D0, + UAC3_PD_STATE_D1, + UAC3_PD_STATE_D2, +}; + +int snd_usb_power_domain_set(struct snd_usb_audio *chip, + struct snd_usb_power_domain *pd, + unsigned char state); +struct snd_usb_power_domain * +snd_usb_find_power_domain(struct usb_host_interface *ctrl_iface, + unsigned char id); + #ifdef CONFIG_PM int snd_usb_autoresume(struct snd_usb_audio *chip); void snd_usb_autosuspend(struct snd_usb_audio *chip); -- cgit v1.2.3 From 7edf3b5e6a4544b42d3572a7058f8ffe96349ee8 Mon Sep 17 00:00:00 2001 From: Jorge Sanjuan Date: Tue, 31 Jul 2018 13:28:43 +0100 Subject: ALSA: usb-audio: AudioStreaming Power Domain parsing Power Domains in the UAC3 spec are mainly intended to be associated to an Input or Output Terminal so the host changes the power state of the entire capture or playback path within the topology. This patch adds support for finding Power Domains associated to an Audio Streaming Interface (bTerminalLink) and adds a reference to them in the usb audio substreams (snd_usb_substream). Signed-off-by: Jorge Sanjuan Signed-off-by: Takashi Iwai --- sound/usb/card.h | 2 ++ sound/usb/stream.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 60 insertions(+), 8 deletions(-) (limited to 'sound') diff --git a/sound/usb/card.h b/sound/usb/card.h index 9b41b7dda84f..ac785d15ced4 100644 --- a/sound/usb/card.h +++ b/sound/usb/card.h @@ -37,6 +37,7 @@ struct audioformat { struct snd_usb_substream; struct snd_usb_endpoint; +struct snd_usb_power_domain; struct snd_urb_ctx { struct urb *urb; @@ -115,6 +116,7 @@ struct snd_usb_substream { int interface; /* current interface */ int endpoint; /* assigned endpoint */ struct audioformat *cur_audiofmt; /* current audioformat pointer (for hw_params callback) */ + struct snd_usb_power_domain *str_pd; /* UAC3 Power Domain for streaming path */ snd_pcm_format_t pcm_format; /* current audio format (for hw_params callback) */ unsigned int channels; /* current number of channels (for hw_params callback) */ unsigned int channels_max; /* max channels in the all audiofmts */ diff --git a/sound/usb/stream.c b/sound/usb/stream.c index 729afd808cc4..c0567fa1e84b 100644 --- a/sound/usb/stream.c +++ b/sound/usb/stream.c @@ -37,6 +37,7 @@ #include "format.h" #include "clock.h" #include "stream.h" +#include "power.h" /* * free a substream @@ -53,6 +54,7 @@ static void free_substream(struct snd_usb_substream *subs) kfree(fp); } kfree(subs->rate_list.list); + kfree(subs->str_pd); } @@ -82,7 +84,8 @@ static void snd_usb_audio_pcm_free(struct snd_pcm *pcm) static void snd_usb_init_substream(struct snd_usb_stream *as, int stream, - struct audioformat *fp) + struct audioformat *fp, + struct snd_usb_power_domain *pd) { struct snd_usb_substream *subs = &as->substream[stream]; @@ -107,6 +110,9 @@ static void snd_usb_init_substream(struct snd_usb_stream *as, if (fp->channels > subs->channels_max) subs->channels_max = fp->channels; + if (pd) + subs->str_pd = pd; + snd_usb_preallocate_buffer(subs); } @@ -468,9 +474,11 @@ snd_pcm_chmap_elem *convert_chmap_v3(struct uac3_cluster_header_descriptor * fmt_list and will be freed on the chip instance release. do not free * fp or do remove it from the substream fmt_list to avoid double-free. */ -int snd_usb_add_audio_stream(struct snd_usb_audio *chip, - int stream, - struct audioformat *fp) +static int __snd_usb_add_audio_stream(struct snd_usb_audio *chip, + int stream, + struct audioformat *fp, + struct snd_usb_power_domain *pd) + { struct snd_usb_stream *as; struct snd_usb_substream *subs; @@ -498,7 +506,7 @@ int snd_usb_add_audio_stream(struct snd_usb_audio *chip, err = snd_pcm_new_stream(as->pcm, stream, 1); if (err < 0) return err; - snd_usb_init_substream(as, stream, fp); + snd_usb_init_substream(as, stream, fp, pd); return add_chmap(as->pcm, stream, subs); } @@ -526,7 +534,7 @@ int snd_usb_add_audio_stream(struct snd_usb_audio *chip, else strcpy(pcm->name, "USB Audio"); - snd_usb_init_substream(as, stream, fp); + snd_usb_init_substream(as, stream, fp, pd); /* * Keep using head insertion for M-Audio Audiophile USB (tm) which has a @@ -544,6 +552,21 @@ int snd_usb_add_audio_stream(struct snd_usb_audio *chip, return add_chmap(pcm, stream, &as->substream[stream]); } +int snd_usb_add_audio_stream(struct snd_usb_audio *chip, + int stream, + struct audioformat *fp) +{ + return __snd_usb_add_audio_stream(chip, stream, fp, NULL); +} + +static int snd_usb_add_audio_stream_v3(struct snd_usb_audio *chip, + int stream, + struct audioformat *fp, + struct snd_usb_power_domain *pd) +{ + return __snd_usb_add_audio_stream(chip, stream, fp, pd); +} + static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip, struct usb_host_interface *alts, int protocol, int iface_no) @@ -819,6 +842,7 @@ found_clock: static struct audioformat * snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip, struct usb_host_interface *alts, + struct snd_usb_power_domain **pd_out, int iface_no, int altset_idx, int altno, int stream) { @@ -829,6 +853,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip, struct uac3_as_header_descriptor *as = NULL; struct uac3_hc_descriptor_header hc_header; struct snd_pcm_chmap_elem *chmap; + struct snd_usb_power_domain *pd; unsigned char badd_profile; u64 badd_formats = 0; unsigned int num_channels; @@ -1008,12 +1033,28 @@ found_clock: fp->rate_max = UAC3_BADD_SAMPLING_RATE; fp->rates = SNDRV_PCM_RATE_CONTINUOUS; + pd = kzalloc(sizeof(pd), GFP_KERNEL); + if (!pd) { + kfree(fp->rate_table); + kfree(fp); + return NULL; + } + pd->pd_id = (stream == SNDRV_PCM_STREAM_PLAYBACK) ? + UAC3_BADD_PD_ID10 : UAC3_BADD_PD_ID11; + pd->pd_d1d0_rec = UAC3_BADD_PD_RECOVER_D1D0; + pd->pd_d2d0_rec = UAC3_BADD_PD_RECOVER_D2D0; + } else { fp->attributes = parse_uac_endpoint_attributes(chip, alts, UAC_VERSION_3, iface_no); + + pd = snd_usb_find_power_domain(chip->ctrl_intf, + as->bTerminalLink); + /* ok, let's parse further... */ if (snd_usb_parse_audio_format_v3(chip, fp, as, stream) < 0) { + kfree(pd); kfree(fp->chmap); kfree(fp->rate_table); kfree(fp); @@ -1021,6 +1062,9 @@ found_clock: } } + if (pd) + *pd_out = pd; + return fp; } @@ -1032,6 +1076,7 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) struct usb_interface_descriptor *altsd; int i, altno, err, stream; struct audioformat *fp = NULL; + struct snd_usb_power_domain *pd = NULL; int num, protocol; dev = chip->dev; @@ -1114,7 +1159,7 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) break; } case UAC_VERSION_3: - fp = snd_usb_get_audioformat_uac3(chip, alts, + fp = snd_usb_get_audioformat_uac3(chip, alts, &pd, iface_no, i, altno, stream); break; } @@ -1125,9 +1170,14 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) return PTR_ERR(fp); dev_dbg(&dev->dev, "%u:%d: add audio endpoint %#x\n", iface_no, altno, fp->endpoint); - err = snd_usb_add_audio_stream(chip, stream, fp); + if (protocol == UAC_VERSION_3) + err = snd_usb_add_audio_stream_v3(chip, stream, fp, pd); + else + err = snd_usb_add_audio_stream(chip, stream, fp); + if (err < 0) { list_del(&fp->list); /* unlink for avoiding double-free */ + kfree(pd); kfree(fp->rate_table); kfree(fp->chmap); kfree(fp); -- cgit v1.2.3 From 3f59aa11c6776da8d0f9f50c741ef02bfc4a8766 Mon Sep 17 00:00:00 2001 From: Jorge Sanjuan Date: Tue, 31 Jul 2018 13:28:44 +0100 Subject: ALSA: usb-audio: Add UAC3 Power Domains to suspend/resume Set the UAC3 Power Domain state for an Audio Streaming interface to D2 state before suspending the device (usb_driver callback). This lets the device know there is no intention to use any of the Units in the Audio Function and that the host is not going to even listen for wake-up events (interrupts) on the units. When the usb_driver gets resumed, the state D0 (fully powered) will be set. This ties up the UAC3 Power Domains to the runtime PM. Signed-off-by: Jorge Sanjuan Signed-off-by: Takashi Iwai --- sound/usb/card.c | 9 +++++++++ sound/usb/pcm.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ sound/usb/pcm.h | 2 ++ 3 files changed, 59 insertions(+) (limited to 'sound') diff --git a/sound/usb/card.c b/sound/usb/card.c index a1ed798a1c6b..2bfe4e80a6b9 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -809,6 +809,7 @@ static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message) if (!chip->num_suspended_intf++) { list_for_each_entry(as, &chip->pcm_list, list) { snd_pcm_suspend_all(as->pcm); + snd_usb_pcm_suspend(as); as->substream[0].need_setup_ep = as->substream[1].need_setup_ep = true; } @@ -824,6 +825,7 @@ static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message) static int __usb_audio_resume(struct usb_interface *intf, bool reset_resume) { struct snd_usb_audio *chip = usb_get_intfdata(intf); + struct snd_usb_stream *as; struct usb_mixer_interface *mixer; struct list_head *p; int err = 0; @@ -834,6 +836,13 @@ static int __usb_audio_resume(struct usb_interface *intf, bool reset_resume) return 0; atomic_inc(&chip->active); /* avoid autopm */ + + list_for_each_entry(as, &chip->pcm_list, list) { + err = snd_usb_pcm_resume(as); + if (err < 0) + goto err_out; + } + /* * ALSA leaves material resumption to user space * we just notify and restart the mixers diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 4b930fa47277..99ec9d5caa58 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -711,6 +711,54 @@ static int configure_endpoint(struct snd_usb_substream *subs) return ret; } +static int snd_usb_pcm_change_state(struct snd_usb_substream *subs, int state) +{ + int ret; + + if (!subs->str_pd) + return 0; + + ret = snd_usb_power_domain_set(subs->stream->chip, subs->str_pd, state); + if (ret < 0) { + dev_err(&subs->dev->dev, + "Cannot change Power Domain ID: %d to state: %d. Err: %d\n", + subs->str_pd->pd_id, state, ret); + return ret; + } + + return 0; +} + +int snd_usb_pcm_suspend(struct snd_usb_stream *as) +{ + int ret; + + ret = snd_usb_pcm_change_state(&as->substream[0], UAC3_PD_STATE_D2); + if (ret < 0) + return ret; + + ret = snd_usb_pcm_change_state(&as->substream[1], UAC3_PD_STATE_D2); + if (ret < 0) + return ret; + + return 0; +} + +int snd_usb_pcm_resume(struct snd_usb_stream *as) +{ + int ret; + + ret = snd_usb_pcm_change_state(&as->substream[0], UAC3_PD_STATE_D0); + if (ret < 0) + return ret; + + ret = snd_usb_pcm_change_state(&as->substream[1], UAC3_PD_STATE_D0); + if (ret < 0) + return ret; + + return 0; +} + /* * hw_params callback * diff --git a/sound/usb/pcm.h b/sound/usb/pcm.h index f77ec58bf1a1..9833627c1eca 100644 --- a/sound/usb/pcm.h +++ b/sound/usb/pcm.h @@ -6,6 +6,8 @@ snd_pcm_uframes_t snd_usb_pcm_delay(struct snd_usb_substream *subs, unsigned int rate); void snd_usb_set_pcm_ops(struct snd_pcm *pcm, int stream); +int snd_usb_pcm_suspend(struct snd_usb_stream *as); +int snd_usb_pcm_resume(struct snd_usb_stream *as); int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface, struct usb_host_interface *alts, -- cgit v1.2.3 From a0a4959eb4e94ce98ee5549dd7d1296d41162ca8 Mon Sep 17 00:00:00 2001 From: Jorge Sanjuan Date: Tue, 31 Jul 2018 13:28:45 +0100 Subject: ALSA: usb-audio: Operate UAC3 Power Domains in PCM callbacks Make use of UAC3 Power Domains associated to an Audio Streaming path within the PCM's logic. This means, when there is no audio being transferred (pcm is closed), the host will set the Power Domain associated to that substream to state D1. When audio is being transferred (from hw_params onwards), the Power Domain will be set to D0 state. This is the way the host lets the device know which Terminal is going to be actively used and it is for the device to manage its own internal resources on that UAC3 Power Domain. Note the resume method now sets the Power Domain to D1 state as resuming the device doesn't mean audio streaming will occur. Signed-off-by: Jorge Sanjuan Signed-off-by: Takashi Iwai --- sound/usb/pcm.c | 24 +++++++++++++++++++----- sound/usb/stream.c | 6 +++++- 2 files changed, 24 insertions(+), 6 deletions(-) (limited to 'sound') diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 99ec9d5caa58..bbc7116c9543 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -748,11 +748,11 @@ int snd_usb_pcm_resume(struct snd_usb_stream *as) { int ret; - ret = snd_usb_pcm_change_state(&as->substream[0], UAC3_PD_STATE_D0); + ret = snd_usb_pcm_change_state(&as->substream[0], UAC3_PD_STATE_D1); if (ret < 0) return ret; - ret = snd_usb_pcm_change_state(&as->substream[1], UAC3_PD_STATE_D0); + ret = snd_usb_pcm_change_state(&as->substream[1], UAC3_PD_STATE_D1); if (ret < 0) return ret; @@ -803,16 +803,22 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, ret = snd_usb_lock_shutdown(subs->stream->chip); if (ret < 0) return ret; + + ret = snd_usb_pcm_change_state(subs, UAC3_PD_STATE_D0); + if (ret < 0) + goto unlock; + ret = set_format(subs, fmt); - snd_usb_unlock_shutdown(subs->stream->chip); if (ret < 0) - return ret; + goto unlock; subs->interface = fmt->iface; subs->altset_idx = fmt->altset_idx; subs->need_setup_ep = true; - return 0; + unlock: + snd_usb_unlock_shutdown(subs->stream->chip); + return ret; } /* @@ -869,6 +875,10 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) snd_usb_endpoint_sync_pending_stop(subs->sync_endpoint); snd_usb_endpoint_sync_pending_stop(subs->data_endpoint); + ret = snd_usb_pcm_change_state(subs, UAC3_PD_STATE_D0); + if (ret < 0) + goto unlock; + ret = set_format(subs, subs->cur_audiofmt); if (ret < 0) goto unlock; @@ -1313,6 +1323,7 @@ static int snd_usb_pcm_close(struct snd_pcm_substream *substream) int direction = substream->stream; struct snd_usb_stream *as = snd_pcm_substream_chip(substream); struct snd_usb_substream *subs = &as->substream[direction]; + int ret; stop_endpoints(subs, true); @@ -1321,7 +1332,10 @@ static int snd_usb_pcm_close(struct snd_pcm_substream *substream) !snd_usb_lock_shutdown(subs->stream->chip)) { usb_set_interface(subs->dev, subs->interface, 0); subs->interface = -1; + ret = snd_usb_pcm_change_state(subs, UAC3_PD_STATE_D1); snd_usb_unlock_shutdown(subs->stream->chip); + if (ret < 0) + return ret; } subs->pcm_substream = NULL; diff --git a/sound/usb/stream.c b/sound/usb/stream.c index c0567fa1e84b..8fe3b0e00e45 100644 --- a/sound/usb/stream.c +++ b/sound/usb/stream.c @@ -110,8 +110,12 @@ static void snd_usb_init_substream(struct snd_usb_stream *as, if (fp->channels > subs->channels_max) subs->channels_max = fp->channels; - if (pd) + if (pd) { subs->str_pd = pd; + /* Initialize Power Domain to idle status D1 */ + snd_usb_power_domain_set(subs->stream->chip, pd, + UAC3_PD_STATE_D1); + } snd_usb_preallocate_buffer(subs); } -- cgit v1.2.3 From 96963dedd000605a0e84e2ac6e41263a50f05953 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 1 Aug 2018 11:47:34 +0100 Subject: ALSA: asihpi: remove redundant variable max_streams Variable max_streams is being assigned but is never used hence it is redundant and can be removed. Cleans up clang warning: warning: variable 'max_streams' set but not used [-Wunused-but-set-variable] Signed-off-by: Colin Ian King Signed-off-by: Takashi Iwai --- sound/pci/asihpi/hpi6205.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'sound') diff --git a/sound/pci/asihpi/hpi6205.c b/sound/pci/asihpi/hpi6205.c index 8d5abfa4e24b..2864698436a5 100644 --- a/sound/pci/asihpi/hpi6205.c +++ b/sound/pci/asihpi/hpi6205.c @@ -635,7 +635,6 @@ static u16 create_adapter_obj(struct hpi_adapter_obj *pao, { struct hpi_message hm; struct hpi_response hr; - u32 max_streams; HPI_DEBUG_LOG(VERBOSE, "init ADAPTER_GET_INFO\n"); memset(&hm, 0, sizeof(hm)); @@ -660,10 +659,6 @@ static u16 create_adapter_obj(struct hpi_adapter_obj *pao, pao->type = hr.u.ax.info.adapter_type; pao->index = hr.u.ax.info.adapter_index; - max_streams = - hr.u.ax.info.num_outstreams + - hr.u.ax.info.num_instreams; - HPI_DEBUG_LOG(VERBOSE, "got adapter info type %x index %d serial %d\n", hr.u.ax.info.adapter_type, hr.u.ax.info.adapter_index, -- cgit v1.2.3 From 45bf41005ac0d7cae0c1caa85d06cb35976823fa Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 1 Aug 2018 11:47:35 +0100 Subject: ALSA: cs5535audio: remove redundant pointer 'dma' Pointer 'dma' is being assigned but is never used hence it is redundant and can be removed. Cleans up two clang warnings: warning: variable 'dma' set but not used [-Wunused-but-set-variable] Signed-off-by: Colin Ian King Signed-off-by: Takashi Iwai --- sound/pci/cs5535audio/cs5535audio.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'sound') diff --git a/sound/pci/cs5535audio/cs5535audio.c b/sound/pci/cs5535audio/cs5535audio.c index de409cda50aa..4590086d9cd8 100644 --- a/sound/pci/cs5535audio/cs5535audio.c +++ b/sound/pci/cs5535audio/cs5535audio.c @@ -192,8 +192,6 @@ static void process_bm0_irq(struct cs5535audio *cs5535au) bm_stat = cs_readb(cs5535au, ACC_BM0_STATUS); spin_unlock(&cs5535au->reg_lock); if (bm_stat & EOP) { - struct cs5535audio_dma *dma; - dma = cs5535au->playback_substream->runtime->private_data; snd_pcm_period_elapsed(cs5535au->playback_substream); } else { dev_err(cs5535au->card->dev, @@ -208,11 +206,8 @@ static void process_bm1_irq(struct cs5535audio *cs5535au) spin_lock(&cs5535au->reg_lock); bm_stat = cs_readb(cs5535au, ACC_BM1_STATUS); spin_unlock(&cs5535au->reg_lock); - if (bm_stat & EOP) { - struct cs5535audio_dma *dma; - dma = cs5535au->capture_substream->runtime->private_data; + if (bm_stat & EOP) snd_pcm_period_elapsed(cs5535au->capture_substream); - } } static irqreturn_t snd_cs5535audio_interrupt(int irq, void *dev_id) -- cgit v1.2.3 From de42b4b96ebe29058ce1cb59a1f98d58b8abd132 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 1 Aug 2018 11:47:36 +0100 Subject: ALSA: emu10k1: remove redundant variable attn Variable attn is being assigned but is never used hence it is redundant and can be removed. Cleans up clang warning: warning: variable 'attn' set but not used [-Wunused-but-set-variable] Signed-off-by: Colin Ian King Signed-off-by: Takashi Iwai --- sound/pci/emu10k1/emupcm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c index 69f9b100bd24..26f6eda3e766 100644 --- a/sound/pci/emu10k1/emupcm.c +++ b/sound/pci/emu10k1/emupcm.c @@ -290,7 +290,7 @@ static void snd_emu10k1_pcm_init_voice(struct snd_emu10k1 *emu, struct snd_pcm_runtime *runtime = substream->runtime; unsigned int silent_page, tmp; int voice, stereo, w_16; - unsigned char attn, send_amount[8]; + unsigned char send_amount[8]; unsigned char send_routing[8]; unsigned long flags; unsigned int pitch_target; @@ -313,7 +313,6 @@ static void snd_emu10k1_pcm_init_voice(struct snd_emu10k1 *emu, /* volume parameters */ if (extra) { - attn = 0; memset(send_routing, 0, sizeof(send_routing)); send_routing[0] = 0; send_routing[1] = 1; -- cgit v1.2.3 From 3b0cbc7812d759ffb38d881e75c0318512283d00 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 1 Aug 2018 11:47:37 +0100 Subject: ALSA: ens137x: remove redundant array pcm_devs The array pcm_devs is being assigned but is never used hence it is redundant and can be removed. Cleans up clang warning: warning: variable 'pcm_devs' set but not used [-Wunused-but-set-variable] Signed-off-by: Colin Ian King Signed-off-by: Takashi Iwai --- sound/pci/ens1370.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c index 39f79a6b5283..727eb3da1fda 100644 --- a/sound/pci/ens1370.c +++ b/sound/pci/ens1370.c @@ -2392,7 +2392,7 @@ static int snd_audiopci_probe(struct pci_dev *pci, static int dev; struct snd_card *card; struct ensoniq *ensoniq; - int err, pcm_devs[2]; + int err; if (dev >= SNDRV_CARDS) return -ENODEV; @@ -2412,7 +2412,6 @@ static int snd_audiopci_probe(struct pci_dev *pci, } card->private_data = ensoniq; - pcm_devs[0] = 0; pcm_devs[1] = 1; #ifdef CHIP1370 if ((err = snd_ensoniq_1370_mixer(ensoniq)) < 0) { snd_card_free(card); -- cgit v1.2.3 From 0d00085b905c904d6de4296aa6a1e3613d0a4d67 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 1 Aug 2018 11:47:38 +0100 Subject: ALSA: sonicvibes: remove redundant pointer 'dir' Pointer 'dir' is being assigned but is never used hence it is redundant and can be removed. Cleans up clang warning: warning: variable 'dir' set but not used [-Wunused-but-set-variable] Signed-off-by: Colin Ian King Signed-off-by: Takashi Iwai --- sound/pci/sonicvibes.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'sound') diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c index 7fbdb703bfcd..7218f38b59db 100644 --- a/sound/pci/sonicvibes.c +++ b/sound/pci/sonicvibes.c @@ -1433,14 +1433,12 @@ static int snd_sonicvibes_midi(struct sonicvibes *sonic, { struct snd_mpu401 * mpu = rmidi->private_data; struct snd_card *card = sonic->card; - struct snd_rawmidi_str *dir; unsigned int idx; int err; mpu->private_data = sonic; mpu->open_input = snd_sonicvibes_midi_input_open; mpu->close_input = snd_sonicvibes_midi_input_close; - dir = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT]; for (idx = 0; idx < ARRAY_SIZE(snd_sonicvibes_midi_controls); idx++) if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_sonicvibes_midi_controls[idx], sonic))) < 0) return err; -- cgit v1.2.3 From d36455a38ed82e7d1e6807573935874f0b279f45 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 1 Aug 2018 11:47:41 +0100 Subject: ALSA: usb-audio: remove redundant pointer 'urb' Pointer 'urb' is being assigned but is never used hence it is redundant and can be removed. Cleans up clang warning: warning: variable 'urb' set but not used [-Wunused-but-set-variable] Signed-off-by: Colin Ian King Signed-off-by: Takashi Iwai --- sound/usb/endpoint.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'sound') diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index c90607ebe155..d86be8bfe412 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -325,7 +325,6 @@ static void queue_pending_output_urbs(struct snd_usb_endpoint *ep) unsigned long flags; struct snd_usb_packet_info *uninitialized_var(packet); struct snd_urb_ctx *ctx = NULL; - struct urb *urb; int err, i; spin_lock_irqsave(&ep->lock, flags); @@ -345,7 +344,6 @@ static void queue_pending_output_urbs(struct snd_usb_endpoint *ep) return; list_del_init(&ctx->ready_list); - urb = ctx->urb; /* copy over the length information */ for (i = 0; i < packet->packets; i++) -- cgit v1.2.3 From 5a6cd13d4faef48bdcb7ae9c1e98175332ced7cd Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Wed, 1 Aug 2018 10:58:25 -0500 Subject: ALSA: pcm: Mark expected switch fall-through In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. Addresses-Coverity-ID: 1357375 ("Missing break in switch") Signed-off-by: Gustavo A. R. Silva Signed-off-by: Takashi Iwai --- sound/core/oss/pcm_plugin.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound') diff --git a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c index 85bab922ce69..0391cb1a4f19 100644 --- a/sound/core/oss/pcm_plugin.c +++ b/sound/core/oss/pcm_plugin.c @@ -353,6 +353,7 @@ snd_pcm_format_t snd_pcm_plug_slave_format(snd_pcm_format_t format, if (snd_mask_test(format_mask, (__force int)format1)) return format1; } + /* fall through */ default: return (__force snd_pcm_format_t)-EINVAL; } -- cgit v1.2.3 From d5e77fca87e636dda510710689b4c2ca93765598 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Wed, 1 Aug 2018 11:14:16 -0500 Subject: ALSA: usb: Mark expected switch fall-through In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. Addresses-Coverity-ID: 115084 ("Missing break in switch") Signed-off-by: Gustavo A. R. Silva Signed-off-by: Takashi Iwai --- sound/usb/pcm.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound') diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index bbc7116c9543..382847154227 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -1694,6 +1694,7 @@ static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substrea switch (cmd) { case SNDRV_PCM_TRIGGER_START: subs->trigger_tstamp_pending_update = true; + /* fall through */ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: subs->data_endpoint->prepare_data_urb = prepare_playback_urb; subs->data_endpoint->retire_data_urb = retire_playback_urb; -- cgit v1.2.3 From ef965ad5a7697ff16e3be01954f5c57208e36c22 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 1 Aug 2018 14:38:18 +0200 Subject: ALSA: seq: Minor cleanup of MIDI event parser helpers snd_midi_event_encode_byte() can never fail, and it can return rather true/false. Change the return type to bool, adjust the argument to receive a MIDI byte as unsigned char, and adjust the comment accordingly. This allows callers to drop error checks, which simplifies the code. Meanwhile, snd_midi_event_encode() helper is used only in seq_midi.c, and it can be better folded into it. This will reduce the total amount of lines in the end. Signed-off-by: Takashi Iwai --- include/sound/seq_midi_event.h | 6 ++---- sound/core/seq/oss/seq_oss_midi.c | 2 +- sound/core/seq/seq_midi.c | 24 ++++++++++------------ sound/core/seq/seq_midi_event.c | 42 +++++++-------------------------------- sound/core/seq/seq_virmidi.c | 4 ++-- 5 files changed, 22 insertions(+), 56 deletions(-) (limited to 'sound') diff --git a/include/sound/seq_midi_event.h b/include/sound/seq_midi_event.h index e40f43e6fc7b..2f135bccf457 100644 --- a/include/sound/seq_midi_event.h +++ b/include/sound/seq_midi_event.h @@ -43,10 +43,8 @@ void snd_midi_event_free(struct snd_midi_event *dev); void snd_midi_event_reset_encode(struct snd_midi_event *dev); void snd_midi_event_reset_decode(struct snd_midi_event *dev); void snd_midi_event_no_status(struct snd_midi_event *dev, int on); -/* encode from byte stream - return number of written bytes if success */ -long snd_midi_event_encode(struct snd_midi_event *dev, unsigned char *buf, long count, - struct snd_seq_event *ev); -int snd_midi_event_encode_byte(struct snd_midi_event *dev, int c, struct snd_seq_event *ev); +bool snd_midi_event_encode_byte(struct snd_midi_event *dev, unsigned char c, + struct snd_seq_event *ev); /* decode from event to bytes - return number of written bytes if success */ long snd_midi_event_decode(struct snd_midi_event *dev, unsigned char *buf, long count, struct snd_seq_event *ev); diff --git a/sound/core/seq/oss/seq_oss_midi.c b/sound/core/seq/oss/seq_oss_midi.c index 9debd1b8fd28..0d5f8b16d057 100644 --- a/sound/core/seq/oss/seq_oss_midi.c +++ b/sound/core/seq/oss/seq_oss_midi.c @@ -637,7 +637,7 @@ snd_seq_oss_midi_putc(struct seq_oss_devinfo *dp, int dev, unsigned char c, stru if ((mdev = get_mididev(dp, dev)) == NULL) return -ENODEV; - if (snd_midi_event_encode_byte(mdev->coder, c, ev) > 0) { + if (snd_midi_event_encode_byte(mdev->coder, c, ev)) { snd_seq_oss_fill_addr(dp, ev, mdev->client, mdev->port); snd_use_lock_free(&mdev->use_lock); return 0; diff --git a/sound/core/seq/seq_midi.c b/sound/core/seq/seq_midi.c index 5dd0ee258359..9e0dabd3ce5f 100644 --- a/sound/core/seq/seq_midi.c +++ b/sound/core/seq/seq_midi.c @@ -78,7 +78,7 @@ static void snd_midi_input_event(struct snd_rawmidi_substream *substream) struct seq_midisynth *msynth; struct snd_seq_event ev; char buf[16], *pbuf; - long res, count; + long res; if (substream == NULL) return; @@ -94,19 +94,15 @@ static void snd_midi_input_event(struct snd_rawmidi_substream *substream) if (msynth->parser == NULL) continue; pbuf = buf; - while (res > 0) { - count = snd_midi_event_encode(msynth->parser, pbuf, res, &ev); - if (count < 0) - break; - pbuf += count; - res -= count; - if (ev.type != SNDRV_SEQ_EVENT_NONE) { - ev.source.port = msynth->seq_port; - ev.dest.client = SNDRV_SEQ_ADDRESS_SUBSCRIBERS; - snd_seq_kernel_client_dispatch(msynth->seq_client, &ev, 1, 0); - /* clear event and reset header */ - memset(&ev, 0, sizeof(ev)); - } + while (res-- > 0) { + if (!snd_midi_event_encode_byte(msynth->parser, + *pbuf++, &ev)) + continue; + ev.source.port = msynth->seq_port; + ev.dest.client = SNDRV_SEQ_ADDRESS_SUBSCRIBERS; + snd_seq_kernel_client_dispatch(msynth->seq_client, &ev, 1, 0); + /* clear event and reset header */ + memset(&ev, 0, sizeof(ev)); } } } diff --git a/sound/core/seq/seq_midi_event.c b/sound/core/seq/seq_midi_event.c index 90bbbdbeba03..53c0dfab90d6 100644 --- a/sound/core/seq/seq_midi_event.c +++ b/sound/core/seq/seq_midi_event.c @@ -214,45 +214,17 @@ int snd_midi_event_resize_buffer(struct snd_midi_event *dev, int bufsize) } #endif /* 0 */ -/* - * read bytes and encode to sequencer event if finished - * return the size of encoded bytes - */ -long snd_midi_event_encode(struct snd_midi_event *dev, unsigned char *buf, long count, - struct snd_seq_event *ev) -{ - long result = 0; - int rc; - - ev->type = SNDRV_SEQ_EVENT_NONE; - - while (count-- > 0) { - rc = snd_midi_event_encode_byte(dev, *buf++, ev); - result++; - if (rc < 0) - return rc; - else if (rc > 0) - return result; - } - - return result; -} -EXPORT_SYMBOL(snd_midi_event_encode); - /* * read one byte and encode to sequencer event: - * return 1 if MIDI bytes are encoded to an event - * 0 data is not finished - * negative for error + * return true if MIDI bytes are encoded to an event + * false data is not finished */ -int snd_midi_event_encode_byte(struct snd_midi_event *dev, int c, - struct snd_seq_event *ev) +bool snd_midi_event_encode_byte(struct snd_midi_event *dev, unsigned char c, + struct snd_seq_event *ev) { - int rc = 0; + bool rc = false; unsigned long flags; - c &= 0xff; - if (c >= MIDI_CMD_COMMON_CLOCK) { /* real-time event */ ev->type = status_event[ST_SPECIAL + c - 0xf0].event; @@ -293,7 +265,7 @@ int snd_midi_event_encode_byte(struct snd_midi_event *dev, int c, status_event[dev->type].encode(dev, ev); if (dev->type >= ST_SPECIAL) dev->type = ST_INVALID; - rc = 1; + rc = true; } else if (dev->type == ST_SYSEX) { if (c == MIDI_CMD_COMMON_SYSEX_END || dev->read >= dev->bufsize) { @@ -306,7 +278,7 @@ int snd_midi_event_encode_byte(struct snd_midi_event *dev, int c, dev->read = 0; /* continue to parse */ else reset_encode(dev); /* all parsed */ - rc = 1; + rc = true; } } diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c index 03ac5e72dbe6..0c84926eb726 100644 --- a/sound/core/seq/seq_virmidi.c +++ b/sound/core/seq/seq_virmidi.c @@ -174,8 +174,8 @@ static void snd_vmidi_output_work(struct work_struct *work) while (READ_ONCE(vmidi->trigger)) { if (snd_rawmidi_transmit(substream, &input, 1) != 1) break; - if (snd_midi_event_encode_byte(vmidi->parser, input, - &vmidi->event) <= 0) + if (!snd_midi_event_encode_byte(vmidi->parser, input, + &vmidi->event)) continue; if (vmidi->event.type != SNDRV_SEQ_EVENT_NONE) { ret = snd_seq_kernel_client_dispatch(vmidi->client, -- cgit v1.2.3 From fc4bfd9a35f3d9cbf5ad6a20faedca71d1d9ed52 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 1 Aug 2018 14:59:07 +0200 Subject: ALSA: seq: Remove dead codes There are a few functions that have been commented out for ages. And also there are functions that do nothing but placeholders. Let's kill them. Signed-off-by: Takashi Iwai --- sound/core/seq/seq.c | 7 ------- sound/core/seq/seq_memory.c | 12 ----------- sound/core/seq/seq_memory.h | 6 ------ sound/core/seq/seq_midi_emul.c | 12 ----------- sound/core/seq/seq_midi_event.c | 45 ----------------------------------------- sound/core/seq/seq_virmidi.c | 33 ------------------------------ 6 files changed, 115 deletions(-) (limited to 'sound') diff --git a/sound/core/seq/seq.c b/sound/core/seq/seq.c index 639544b4fb04..e685eccdc741 100644 --- a/sound/core/seq/seq.c +++ b/sound/core/seq/seq.c @@ -87,10 +87,6 @@ static int __init alsa_seq_init(void) if ((err = client_init_data()) < 0) goto error; - /* init memory, room for selected events */ - if ((err = snd_sequencer_memory_init()) < 0) - goto error; - /* init event queues */ if ((err = snd_seq_queues_init()) < 0) goto error; @@ -126,9 +122,6 @@ static void __exit alsa_seq_exit(void) /* unregister sequencer device */ snd_sequencer_device_done(); - /* release event memory */ - snd_sequencer_memory_done(); - snd_seq_autoload_exit(); } diff --git a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c index a4c8543176b2..5b0388202bac 100644 --- a/sound/core/seq/seq_memory.c +++ b/sound/core/seq/seq_memory.c @@ -504,18 +504,6 @@ int snd_seq_pool_delete(struct snd_seq_pool **ppool) return 0; } -/* initialize sequencer memory */ -int __init snd_sequencer_memory_init(void) -{ - return 0; -} - -/* release sequencer memory */ -void __exit snd_sequencer_memory_done(void) -{ -} - - /* exported to seq_clientmgr.c */ void snd_seq_info_pool(struct snd_info_buffer *buffer, struct snd_seq_pool *pool, char *space) diff --git a/sound/core/seq/seq_memory.h b/sound/core/seq/seq_memory.h index 3abe306c394a..1292fe91f02e 100644 --- a/sound/core/seq/seq_memory.h +++ b/sound/core/seq/seq_memory.h @@ -94,12 +94,6 @@ struct snd_seq_pool *snd_seq_pool_new(int poolsize); /* remove pool */ int snd_seq_pool_delete(struct snd_seq_pool **pool); -/* init memory */ -int snd_sequencer_memory_init(void); - -/* release event memory */ -void snd_sequencer_memory_done(void); - /* polling */ int snd_seq_pool_poll_wait(struct snd_seq_pool *pool, struct file *file, poll_table *wait); diff --git a/sound/core/seq/seq_midi_emul.c b/sound/core/seq/seq_midi_emul.c index 288f839a554b..f9f21331aeea 100644 --- a/sound/core/seq/seq_midi_emul.c +++ b/sound/core/seq/seq_midi_emul.c @@ -728,15 +728,3 @@ void snd_midi_channel_free_set(struct snd_midi_channel_set *chset) kfree(chset); } EXPORT_SYMBOL(snd_midi_channel_free_set); - -static int __init alsa_seq_midi_emul_init(void) -{ - return 0; -} - -static void __exit alsa_seq_midi_emul_exit(void) -{ -} - -module_init(alsa_seq_midi_emul_init) -module_exit(alsa_seq_midi_emul_exit) diff --git a/sound/core/seq/seq_midi_event.c b/sound/core/seq/seq_midi_event.c index 53c0dfab90d6..b11419537062 100644 --- a/sound/core/seq/seq_midi_event.c +++ b/sound/core/seq/seq_midi_event.c @@ -175,45 +175,12 @@ void snd_midi_event_reset_decode(struct snd_midi_event *dev) } EXPORT_SYMBOL(snd_midi_event_reset_decode); -#if 0 -void snd_midi_event_init(struct snd_midi_event *dev) -{ - snd_midi_event_reset_encode(dev); - snd_midi_event_reset_decode(dev); -} -#endif /* 0 */ - void snd_midi_event_no_status(struct snd_midi_event *dev, int on) { dev->nostat = on ? 1 : 0; } EXPORT_SYMBOL(snd_midi_event_no_status); -/* - * resize buffer - */ -#if 0 -int snd_midi_event_resize_buffer(struct snd_midi_event *dev, int bufsize) -{ - unsigned char *new_buf, *old_buf; - unsigned long flags; - - if (bufsize == dev->bufsize) - return 0; - new_buf = kmalloc(bufsize, GFP_KERNEL); - if (new_buf == NULL) - return -ENOMEM; - spin_lock_irqsave(&dev->lock, flags); - old_buf = dev->buf; - dev->buf = new_buf; - dev->bufsize = bufsize; - reset_encode(dev); - spin_unlock_irqrestore(&dev->lock, flags); - kfree(old_buf); - return 0; -} -#endif /* 0 */ - /* * read one byte and encode to sequencer event: * return true if MIDI bytes are encoded to an event @@ -503,15 +470,3 @@ static int extra_decode_xrpn(struct snd_midi_event *dev, unsigned char *buf, } return idx; } - -static int __init alsa_seq_midi_event_init(void) -{ - return 0; -} - -static void __exit alsa_seq_midi_event_exit(void) -{ -} - -module_init(alsa_seq_midi_event_init) -module_exit(alsa_seq_midi_event_exit) diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c index 0c84926eb726..a2f1c6b58693 100644 --- a/sound/core/seq/seq_virmidi.c +++ b/sound/core/seq/seq_virmidi.c @@ -109,23 +109,6 @@ static int snd_virmidi_dev_receive_event(struct snd_virmidi_dev *rdev, return 0; } -/* - * receive an event from the remote virmidi port - * - * for rawmidi inputs, you can call this function from the event - * handler of a remote port which is attached to the virmidi via - * SNDRV_VIRMIDI_SEQ_ATTACH. - */ -#if 0 -int snd_virmidi_receive(struct snd_rawmidi *rmidi, struct snd_seq_event *ev) -{ - struct snd_virmidi_dev *rdev; - - rdev = rmidi->private_data; - return snd_virmidi_dev_receive_event(rdev, ev, true); -} -#endif /* 0 */ - /* * event handler of virmidi port */ @@ -544,19 +527,3 @@ int snd_virmidi_new(struct snd_card *card, int device, struct snd_rawmidi **rrmi return 0; } EXPORT_SYMBOL(snd_virmidi_new); - -/* - * ENTRY functions - */ - -static int __init alsa_virmidi_init(void) -{ - return 0; -} - -static void __exit alsa_virmidi_exit(void) -{ -} - -module_init(alsa_virmidi_init) -module_exit(alsa_virmidi_exit) -- cgit v1.2.3 From 00976ad5271999ba06d24319fd1031b178aff832 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 1 Aug 2018 16:37:02 +0200 Subject: ALSA: seq: Fix leftovers at probe error path The sequencer core module doesn't call some destructors in the error path of the init code, which may leave some resources. This patch mainly fix these leaks by calling the destructors appropriately at alsa_seq_init(). Also the patch brings a few cleanups along with it, namely: - Expand the old "if ((err = xxx) < 0)" coding style - Get rid of empty seq_queue_init() and its caller - Change snd_seq_info_done() to void Last but not least, a couple of functions lose __exit annotation since they are called also in alsa_seq_init(). No functional changes but minor code cleanups. Signed-off-by: Takashi Iwai --- sound/core/seq/seq.c | 26 ++++++++++++++++---------- sound/core/seq/seq_clientmgr.c | 2 +- sound/core/seq/seq_info.c | 10 ++-------- sound/core/seq/seq_info.h | 6 +++--- sound/core/seq/seq_queue.c | 12 +----------- sound/core/seq/seq_queue.h | 3 --- 6 files changed, 23 insertions(+), 36 deletions(-) (limited to 'sound') diff --git a/sound/core/seq/seq.c b/sound/core/seq/seq.c index e685eccdc741..7de98d71f2aa 100644 --- a/sound/core/seq/seq.c +++ b/sound/core/seq/seq.c @@ -84,26 +84,32 @@ static int __init alsa_seq_init(void) { int err; - if ((err = client_init_data()) < 0) - goto error; - - /* init event queues */ - if ((err = snd_seq_queues_init()) < 0) + err = client_init_data(); + if (err < 0) goto error; /* register sequencer device */ - if ((err = snd_sequencer_device_init()) < 0) + err = snd_sequencer_device_init(); + if (err < 0) goto error; /* register proc interface */ - if ((err = snd_seq_info_init()) < 0) - goto error; + err = snd_seq_info_init(); + if (err < 0) + goto error_device; /* register our internal client */ - if ((err = snd_seq_system_client_init()) < 0) - goto error; + err = snd_seq_system_client_init(); + if (err < 0) + goto error_info; snd_seq_autoload_init(); + return 0; + + error_info: + snd_seq_info_done(); + error_device: + snd_sequencer_device_done(); error: return err; } diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index 6fd4b074b206..a0b768e2f697 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -2543,7 +2543,7 @@ int __init snd_sequencer_device_init(void) /* * unregister sequencer device */ -void __exit snd_sequencer_device_done(void) +void snd_sequencer_device_done(void) { snd_unregister_device(&seq_dev); put_device(&seq_dev); diff --git a/sound/core/seq/seq_info.c b/sound/core/seq/seq_info.c index 97015447b9b3..b27fedd435b6 100644 --- a/sound/core/seq/seq_info.c +++ b/sound/core/seq/seq_info.c @@ -50,7 +50,7 @@ create_info_entry(char *name, void (*read)(struct snd_info_entry *, return entry; } -static void free_info_entries(void) +void snd_seq_info_done(void) { snd_info_free_entry(queues_entry); snd_info_free_entry(clients_entry); @@ -70,12 +70,6 @@ int __init snd_seq_info_init(void) return 0; error: - free_info_entries(); + snd_seq_info_done(); return -ENOMEM; } - -int __exit snd_seq_info_done(void) -{ - free_info_entries(); - return 0; -} diff --git a/sound/core/seq/seq_info.h b/sound/core/seq/seq_info.h index f8549f81a645..2cdf8f6e63f5 100644 --- a/sound/core/seq/seq_info.h +++ b/sound/core/seq/seq_info.h @@ -30,11 +30,11 @@ void snd_seq_info_queues_read(struct snd_info_entry *entry, struct snd_info_buff #ifdef CONFIG_SND_PROC_FS -int snd_seq_info_init( void ); -int snd_seq_info_done( void ); +int snd_seq_info_init(void); +void snd_seq_info_done(void); #else static inline int snd_seq_info_init(void) { return 0; } -static inline int snd_seq_info_done(void) { return 0; } +static inline void snd_seq_info_done(void) {} #endif #endif diff --git a/sound/core/seq/seq_queue.c b/sound/core/seq/seq_queue.c index b377f5048352..3b3ac96f1f5f 100644 --- a/sound/core/seq/seq_queue.c +++ b/sound/core/seq/seq_queue.c @@ -159,18 +159,8 @@ static void queue_delete(struct snd_seq_queue *q) /*----------------------------------------------------------------*/ -/* setup queues */ -int __init snd_seq_queues_init(void) -{ - /* - memset(queue_list, 0, sizeof(queue_list)); - num_queues = 0; - */ - return 0; -} - /* delete all existing queues */ -void __exit snd_seq_queues_delete(void) +void snd_seq_queues_delete(void) { int i; diff --git a/sound/core/seq/seq_queue.h b/sound/core/seq/seq_queue.h index 719093489a2c..76db43b79a2b 100644 --- a/sound/core/seq/seq_queue.h +++ b/sound/core/seq/seq_queue.h @@ -63,9 +63,6 @@ struct snd_seq_queue { /* get the number of current queues */ int snd_seq_queue_get_cur_queues(void); -/* init queues structure */ -int snd_seq_queues_init(void); - /* delete queues */ void snd_seq_queues_delete(void); -- cgit v1.2.3 From 04702e8d0092832eaeeacc6b1bfbf81a66f242c9 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 1 Aug 2018 16:42:29 +0200 Subject: ALSA: seq: Use no intrruptible mutex_lock All usages of mutex in ALSA sequencer core would take too long, hence we don't have to care about the user interruption that makes things complicated. Let's replace them with simpler mutex_lock(). Signed-off-by: Takashi Iwai --- sound/core/seq/seq_clientmgr.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) (limited to 'sound') diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index a0b768e2f697..92e6524a3a9d 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -311,10 +311,9 @@ static int snd_seq_open(struct inode *inode, struct file *file) if (err < 0) return err; - if (mutex_lock_interruptible(®ister_mutex)) - return -ERESTARTSYS; + mutex_lock(®ister_mutex); client = seq_create_client1(-1, SNDRV_SEQ_DEFAULT_EVENTS); - if (client == NULL) { + if (!client) { mutex_unlock(®ister_mutex); return -ENOMEM; /* failure code */ } @@ -1704,10 +1703,7 @@ static int snd_seq_ioctl_get_queue_timer(struct snd_seq_client *client, if (queue == NULL) return -EINVAL; - if (mutex_lock_interruptible(&queue->timer_mutex)) { - queuefree(queue); - return -ERESTARTSYS; - } + mutex_lock(&queue->timer_mutex); tmr = queue->timer; memset(timer, 0, sizeof(*timer)); timer->queue = queue->queue; @@ -1741,10 +1737,7 @@ static int snd_seq_ioctl_set_queue_timer(struct snd_seq_client *client, q = queueptr(timer->queue); if (q == NULL) return -ENXIO; - if (mutex_lock_interruptible(&q->timer_mutex)) { - queuefree(q); - return -ERESTARTSYS; - } + mutex_lock(&q->timer_mutex); tmr = q->timer; snd_seq_queue_timer_close(timer->queue); tmr->type = timer->type; @@ -2180,8 +2173,7 @@ int snd_seq_create_kernel_client(struct snd_card *card, int client_index, if (card == NULL && client_index >= SNDRV_SEQ_GLOBAL_CLIENTS) return -EINVAL; - if (mutex_lock_interruptible(®ister_mutex)) - return -ERESTARTSYS; + mutex_lock(®ister_mutex); if (card) { client_index += SNDRV_SEQ_GLOBAL_CLIENTS @@ -2522,19 +2514,15 @@ int __init snd_sequencer_device_init(void) snd_device_initialize(&seq_dev, NULL); dev_set_name(&seq_dev, "seq"); - if (mutex_lock_interruptible(®ister_mutex)) - return -ERESTARTSYS; - + mutex_lock(®ister_mutex); err = snd_register_device(SNDRV_DEVICE_TYPE_SEQUENCER, NULL, 0, &snd_seq_f_ops, NULL, &seq_dev); + mutex_unlock(®ister_mutex); if (err < 0) { - mutex_unlock(®ister_mutex); put_device(&seq_dev); return err; } - mutex_unlock(®ister_mutex); - return 0; } -- cgit v1.2.3 From 93ce1b12966d9d60ee5583ffbde822a22909568e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 1 Aug 2018 16:43:56 +0200 Subject: ALSA: seq: Drop unused 64bit division macros The old ugly macros remained in the code without usage. Rip them off. Signed-off-by: Takashi Iwai --- sound/core/seq/seq_queue.h | 24 ------------------------ 1 file changed, 24 deletions(-) (limited to 'sound') diff --git a/sound/core/seq/seq_queue.h b/sound/core/seq/seq_queue.h index 76db43b79a2b..e006fc8e3a36 100644 --- a/sound/core/seq/seq_queue.h +++ b/sound/core/seq/seq_queue.h @@ -109,28 +109,4 @@ int snd_seq_queue_is_used(int queueid, int client); int snd_seq_control_queue(struct snd_seq_event *ev, int atomic, int hop); -/* - * 64bit division - for sync stuff.. - */ -#if defined(i386) || defined(i486) - -#define udiv_qrnnd(q, r, n1, n0, d) \ - __asm__ ("divl %4" \ - : "=a" ((u32)(q)), \ - "=d" ((u32)(r)) \ - : "0" ((u32)(n0)), \ - "1" ((u32)(n1)), \ - "rm" ((u32)(d))) - -#define u64_div(x,y,q) do {u32 __tmp; udiv_qrnnd(q, __tmp, (x)>>32, x, y);} while (0) -#define u64_mod(x,y,r) do {u32 __tmp; udiv_qrnnd(__tmp, q, (x)>>32, x, y);} while (0) -#define u64_divmod(x,y,q,r) udiv_qrnnd(q, r, (x)>>32, x, y) - -#else -#define u64_div(x,y,q) ((q) = (u32)((u64)(x) / (u64)(y))) -#define u64_mod(x,y,r) ((r) = (u32)((u64)(x) % (u64)(y))) -#define u64_divmod(x,y,q,r) (u64_div(x,y,q), u64_mod(x,y,r)) -#endif - - #endif -- cgit v1.2.3 From 11175556eec58b27a1398e80f8b1302314f2242c Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Thu, 2 Aug 2018 04:31:02 +0000 Subject: ALSA: usb-audio: Fix invalid use of sizeof in parse_uac_endpoint_attributes() sizeof() when applied to a pointer typed expression gives the size of the pointer, not that of the pointed data. Fixes: 7edf3b5e6a45 ("ALSA: usb-audio: AudioStreaming Power Domain parsing") Signed-off-by: Wei Yongjun Signed-off-by: Takashi Iwai --- sound/usb/stream.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/usb/stream.c b/sound/usb/stream.c index 8fe3b0e00e45..67cf849aa16b 100644 --- a/sound/usb/stream.c +++ b/sound/usb/stream.c @@ -1037,7 +1037,7 @@ found_clock: fp->rate_max = UAC3_BADD_SAMPLING_RATE; fp->rates = SNDRV_PCM_RATE_CONTINUOUS; - pd = kzalloc(sizeof(pd), GFP_KERNEL); + pd = kzalloc(sizeof(*pd), GFP_KERNEL); if (!pd) { kfree(fp->rate_table); kfree(fp); -- cgit v1.2.3 From 789b7f43858f1c74a1c528e8b8f78c78624800d8 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 2 Aug 2018 07:40:19 +0200 Subject: ALSA: sb: Fix a typo There was a typo of COPY_USER in the dead code (that is disabled as default). Fixes: 4b83eff81c81 ("ALSA: sb: Convert to the new PCM ops") Signed-off-by: Takashi Iwai --- sound/isa/sb/emu8000_pcm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/isa/sb/emu8000_pcm.c b/sound/isa/sb/emu8000_pcm.c index bc5af71d3bdb..f46f6ec3ea0c 100644 --- a/sound/isa/sb/emu8000_pcm.c +++ b/sound/isa/sb/emu8000_pcm.c @@ -470,7 +470,7 @@ static int emu8k_pcm_copy(struct snd_pcm_substream *subs, /* convert to word unit */ pos = (pos << 1) + rec->loop_start[voice]; count <<= 1; - LOOP_WRITE(rec, pos, src, count, COPY_UESR); + LOOP_WRITE(rec, pos, src, count, COPY_USER); return 0; } -- cgit v1.2.3 From a9fe47e5e96be6401738f6c1e087edbcff6a5ceb Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 2 Aug 2018 15:40:37 -0500 Subject: ALSA: galaxy: Mark expected switch fall-throughs In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. Addresses-Coverity-ID: 1468367 ("Missing break in switch") Addresses-Coverity-ID: 115037 ("Missing break in switch") Addresses-Coverity-ID: 115038 ("Missing break in switch") Signed-off-by: Gustavo A. R. Silva Signed-off-by: Takashi Iwai --- sound/isa/galaxy/galaxy.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'sound') diff --git a/sound/isa/galaxy/galaxy.c b/sound/isa/galaxy/galaxy.c index b9994cc9f5fb..af9eea41379f 100644 --- a/sound/isa/galaxy/galaxy.c +++ b/sound/isa/galaxy/galaxy.c @@ -260,6 +260,7 @@ static int snd_galaxy_match(struct device *dev, unsigned int n) break; case 2: irq[n] = 9; + /* Fall through */ case 9: wss_config[n] |= WSS_CONFIG_IRQ_9; break; @@ -304,6 +305,7 @@ static int snd_galaxy_match(struct device *dev, unsigned int n) case 1: if (dma1[n] == 0) break; + /* Fall through */ default: dev_err(dev, "invalid capture DMA %d\n", dma2[n]); return 0; @@ -333,6 +335,7 @@ mpu: break; case 2: mpu_irq[n] = 9; + /* Fall through */ case 9: config[n] |= GALAXY_CONFIG_MPUIRQ_2; break; -- cgit v1.2.3 From 3e313f34720ea1bb876636263e30a779ff65836e Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 2 Aug 2018 15:41:21 -0500 Subject: ALSA: opti92x: mark expected switch fall-throughs In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. Addresses-Coverity-ID: 1165394 ("Missing break in switch") Addresses-Coverity-ID: 1167851 ("Missing break in switch") Addresses-Coverity-ID: 402015 ("Missing break in switch") Signed-off-by: Gustavo A. R. Silva Signed-off-by: Takashi Iwai --- sound/isa/opti9xx/opti92x-ad1848.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'sound') diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c index 505cd81e19fa..ac0ab6eb40f0 100644 --- a/sound/isa/opti9xx/opti92x-ad1848.c +++ b/sound/isa/opti9xx/opti92x-ad1848.c @@ -261,6 +261,7 @@ static unsigned char snd_opti9xx_read(struct snd_opti9xx *chip, retval = inb(chip->mc_base + 9); break; } + /* Fall through */ case OPTi9XX_HW_82C928: case OPTi9XX_HW_82C929: @@ -303,6 +304,7 @@ static void snd_opti9xx_write(struct snd_opti9xx *chip, unsigned char reg, outb(value, chip->mc_base + 9); break; } + /* Fall through */ case OPTi9XX_HW_82C928: case OPTi9XX_HW_82C929: @@ -350,6 +352,7 @@ static int snd_opti9xx_configure(struct snd_opti9xx *chip, snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(4), 0xf0, 0xfc); /* enable wave audio */ snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(6), 0x02, 0x02); + /* Fall through */ case OPTi9XX_HW_82C925: /* enable WSS mode */ -- cgit v1.2.3 From 734be97b967c7e2bab72b34da87534ccd854c72d Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 2 Aug 2018 15:41:55 -0500 Subject: ALSA: opti9xx: mark expected switch fall-throughs In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. Addresses-Coverity-ID: 402016 ("Missing break in switch") Addresses-Coverity-ID: 1056542 ("Missing break in switch") Addresses-Coverity-ID: 1339579 ("Missing break in switch") Addresses-Coverity-ID: 1369526 ("Missing break in switch") Addresses-Coverity-ID: 1369529 ("Missing break in switch") Signed-off-by: Gustavo A. R. Silva Signed-off-by: Takashi Iwai --- sound/isa/opti9xx/miro.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'sound') diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c index 8894c7c18ad6..c6136c6b0214 100644 --- a/sound/isa/opti9xx/miro.c +++ b/sound/isa/opti9xx/miro.c @@ -176,10 +176,13 @@ static int aci_busy_wait(struct snd_miro_aci *aci) switch (timeout-ACI_MINTIME) { case 0 ... 9: out /= 10; + /* fall through */ case 10 ... 19: out /= 10; + /* fall through */ case 20 ... 30: out /= 10; + /* fall through */ default: set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(out); @@ -834,6 +837,7 @@ static unsigned char snd_miro_read(struct snd_miro *chip, retval = inb(chip->mc_base + 9); break; } + /* fall through */ case OPTi9XX_HW_82C929: retval = inb(chip->mc_base + reg); @@ -863,6 +867,7 @@ static void snd_miro_write(struct snd_miro *chip, unsigned char reg, outb(value, chip->mc_base + 9); break; } + /* fall through */ case OPTi9XX_HW_82C929: outb(value, chip->mc_base + reg); -- cgit v1.2.3 From 13a01635823c409a0911304ee50987cb851317da Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 2 Aug 2018 15:42:39 -0500 Subject: ALSA: es18xx: mark expected switch fall-through In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. Addresses-Coverity-ID: 115075 ("Missing break in switch") Signed-off-by: Gustavo A. R. Silva Signed-off-by: Takashi Iwai --- sound/isa/es18xx.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound') diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c index 2a6960c3e2a4..0d103d6f805e 100644 --- a/sound/isa/es18xx.c +++ b/sound/isa/es18xx.c @@ -1024,6 +1024,7 @@ static int snd_es18xx_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem val = 3; } else retVal = snd_es18xx_mixer_bits(chip, 0x7a, 0x08, 0x00) != 0x00; + /* fall through */ /* 4 source chips */ case 0x1868: case 0x1878: -- cgit v1.2.3 From 9038820cef3c3824cdd846d69894746a73c053db Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 3 Aug 2018 14:47:56 +0100 Subject: ALSA: gus: fix spelling mistake "acumulator" -> "accumulator" Trivial spelling mistake fix in debug message Signed-off-by: Colin Ian King Signed-off-by: Takashi Iwai --- sound/isa/gus/gus_io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/isa/gus/gus_io.c b/sound/isa/gus/gus_io.c index ca79878d8d8c..2fd32ef22c30 100644 --- a/sound/isa/gus/gus_io.c +++ b/sound/isa/gus/gus_io.c @@ -461,7 +461,7 @@ void snd_gf1_print_voice_registers(struct snd_gus_card * gus) printk(KERN_INFO " -%i- GFA1 effect address = 0x%x\n", voice, snd_gf1_i_read_addr(gus, 0x11, ctrl & 4)); printk(KERN_INFO " -%i- GFA1 effect volume = 0x%x\n", voice, snd_gf1_i_read16(gus, 0x16)); printk(KERN_INFO " -%i- GFA1 effect volume final = 0x%x\n", voice, snd_gf1_i_read16(gus, 0x1d)); - printk(KERN_INFO " -%i- GFA1 effect acumulator = 0x%x\n", voice, snd_gf1_i_read8(gus, 0x14)); + printk(KERN_INFO " -%i- GFA1 effect accumulator = 0x%x\n", voice, snd_gf1_i_read8(gus, 0x14)); } if (mode & 0x20) { printk(KERN_INFO " -%i- GFA1 left offset = 0x%x (%i)\n", voice, snd_gf1_i_read16(gus, 0x13), snd_gf1_i_read16(gus, 0x13) >> 4); -- cgit v1.2.3 From a6403299893982a2c0b0a6f43261976c43e1598e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 3 Aug 2018 15:40:25 +0200 Subject: ALSA: compress: Remove empty init and exit For a sake of code simplification, remove the init and the exit entries that do nothing. Notes for readers: actually it's OK to remove *both* init and exit, but not OK to remove the exit entry. By removing only the exit while keeping init, the module becomes permanently loaded; i.e. you cannot unload it any longer! Signed-off-by: Takashi Iwai --- sound/core/compress_offload.c | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'sound') diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index 4b01a37c836e..26b5e245b074 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c @@ -1160,18 +1160,6 @@ int snd_compress_deregister(struct snd_compr *device) } EXPORT_SYMBOL_GPL(snd_compress_deregister); -static int __init snd_compress_init(void) -{ - return 0; -} - -static void __exit snd_compress_exit(void) -{ -} - -module_init(snd_compress_init); -module_exit(snd_compress_exit); - MODULE_DESCRIPTION("ALSA Compressed offload framework"); MODULE_AUTHOR("Vinod Koul "); MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 969686ee0e0ff62ece428e8e02b07f81ac88a84d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 3 Aug 2018 15:42:46 +0200 Subject: ALSA: drivers: Remove empty init and exit For a sake of code simplification, remove the init and the exit entries that do nothing. Notes for readers: actually it's OK to remove *both* init and exit, but not OK to remove the exit entry. By removing only the exit while keeping init, the module becomes permanently loaded; i.e. you cannot unload it any longer! Signed-off-by: Takashi Iwai --- sound/drivers/mpu401/mpu401_uart.c | 16 ---------------- sound/drivers/opl3/opl3_lib.c | 16 ---------------- sound/drivers/opl4/opl4_lib.c | 12 ------------ sound/drivers/vx/vx_core.c | 15 --------------- 4 files changed, 59 deletions(-) (limited to 'sound') diff --git a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c index 3e745f47dd2f..dae26e856b26 100644 --- a/sound/drivers/mpu401/mpu401_uart.c +++ b/sound/drivers/mpu401/mpu401_uart.c @@ -617,19 +617,3 @@ free_device: } EXPORT_SYMBOL(snd_mpu401_uart_new); - -/* - * INIT part - */ - -static int __init alsa_mpu401_uart_init(void) -{ - return 0; -} - -static void __exit alsa_mpu401_uart_exit(void) -{ -} - -module_init(alsa_mpu401_uart_init) -module_exit(alsa_mpu401_uart_exit) diff --git a/sound/drivers/opl3/opl3_lib.c b/sound/drivers/opl3/opl3_lib.c index 1a5355b747ec..cf86c36c7c3b 100644 --- a/sound/drivers/opl3/opl3_lib.c +++ b/sound/drivers/opl3/opl3_lib.c @@ -538,19 +538,3 @@ int snd_opl3_hwdep_new(struct snd_opl3 * opl3, } EXPORT_SYMBOL(snd_opl3_hwdep_new); - -/* - * INIT part - */ - -static int __init alsa_opl3_init(void) -{ - return 0; -} - -static void __exit alsa_opl3_exit(void) -{ -} - -module_init(alsa_opl3_init) -module_exit(alsa_opl3_exit) diff --git a/sound/drivers/opl4/opl4_lib.c b/sound/drivers/opl4/opl4_lib.c index db76a5bf2bd2..819d2dce2a19 100644 --- a/sound/drivers/opl4/opl4_lib.c +++ b/sound/drivers/opl4/opl4_lib.c @@ -263,15 +263,3 @@ int snd_opl4_create(struct snd_card *card, } EXPORT_SYMBOL(snd_opl4_create); - -static int __init alsa_opl4_init(void) -{ - return 0; -} - -static void __exit alsa_opl4_exit(void) -{ -} - -module_init(alsa_opl4_init) -module_exit(alsa_opl4_exit) diff --git a/sound/drivers/vx/vx_core.c b/sound/drivers/vx/vx_core.c index 121357397a6d..04368dd59a4c 100644 --- a/sound/drivers/vx/vx_core.c +++ b/sound/drivers/vx/vx_core.c @@ -815,18 +815,3 @@ struct vx_core *snd_vx_create(struct snd_card *card, struct snd_vx_hardware *hw, } EXPORT_SYMBOL(snd_vx_create); - -/* - * module entries - */ -static int __init alsa_vx_core_init(void) -{ - return 0; -} - -static void __exit alsa_vx_core_exit(void) -{ -} - -module_init(alsa_vx_core_init) -module_exit(alsa_vx_core_exit) -- cgit v1.2.3 From 498aaa9152eef3e101ec897f9c9b51662f700830 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 3 Aug 2018 15:44:15 +0200 Subject: ALSA: isa: Remove empty init and exit For a sake of code simplification, remove the init and the exit entries that do nothing. Notes for readers: actually it's OK to remove *both* init and exit, but not OK to remove the exit entry. By removing only the exit while keeping init, the module becomes permanently loaded; i.e. you cannot unload it any longer! Signed-off-by: Takashi Iwai --- sound/isa/es1688/es1688_lib.c | 16 ---------------- sound/isa/gus/gus_main.c | 16 ---------------- sound/isa/sb/sb16_csp.c | 16 ---------------- sound/isa/sb/sb16_main.c | 16 ---------------- sound/isa/sb/sb8_main.c | 16 ---------------- sound/isa/sb/sb_common.c | 16 ---------------- sound/isa/wss/wss_lib.c | 16 ---------------- 7 files changed, 112 deletions(-) (limited to 'sound') diff --git a/sound/isa/es1688/es1688_lib.c b/sound/isa/es1688/es1688_lib.c index f9c0662e9a22..50cdce0e8946 100644 --- a/sound/isa/es1688/es1688_lib.c +++ b/sound/isa/es1688/es1688_lib.c @@ -1029,19 +1029,3 @@ EXPORT_SYMBOL(snd_es1688_mixer_write); EXPORT_SYMBOL(snd_es1688_create); EXPORT_SYMBOL(snd_es1688_pcm); EXPORT_SYMBOL(snd_es1688_mixer); - -/* - * INIT part - */ - -static int __init alsa_es1688_init(void) -{ - return 0; -} - -static void __exit alsa_es1688_exit(void) -{ -} - -module_init(alsa_es1688_init) -module_exit(alsa_es1688_exit) diff --git a/sound/isa/gus/gus_main.c b/sound/isa/gus/gus_main.c index 3cf9b13c780a..3b8a0c880db5 100644 --- a/sound/isa/gus/gus_main.c +++ b/sound/isa/gus/gus_main.c @@ -465,19 +465,3 @@ EXPORT_SYMBOL(snd_gf1_mem_alloc); EXPORT_SYMBOL(snd_gf1_mem_xfree); EXPORT_SYMBOL(snd_gf1_mem_free); EXPORT_SYMBOL(snd_gf1_mem_lock); - -/* - * INIT part - */ - -static int __init alsa_gus_init(void) -{ - return 0; -} - -static void __exit alsa_gus_exit(void) -{ -} - -module_init(alsa_gus_init) -module_exit(alsa_gus_exit) diff --git a/sound/isa/sb/sb16_csp.c b/sound/isa/sb/sb16_csp.c index b9d67a7065cd..bf3db0d2ea12 100644 --- a/sound/isa/sb/sb16_csp.c +++ b/sound/isa/sb/sb16_csp.c @@ -1185,19 +1185,3 @@ static void info_read(struct snd_info_entry *entry, struct snd_info_buffer *buff /* */ EXPORT_SYMBOL(snd_sb_csp_new); - -/* - * INIT part - */ - -static int __init alsa_sb_csp_init(void) -{ - return 0; -} - -static void __exit alsa_sb_csp_exit(void) -{ -} - -module_init(alsa_sb_csp_init) -module_exit(alsa_sb_csp_exit) diff --git a/sound/isa/sb/sb16_main.c b/sound/isa/sb/sb16_main.c index 11ed4a6e5bf1..37e6ce7b0b13 100644 --- a/sound/isa/sb/sb16_main.c +++ b/sound/isa/sb/sb16_main.c @@ -900,19 +900,3 @@ EXPORT_SYMBOL(snd_sb16dsp_pcm); EXPORT_SYMBOL(snd_sb16dsp_get_pcm_ops); EXPORT_SYMBOL(snd_sb16dsp_configure); EXPORT_SYMBOL(snd_sb16dsp_interrupt); - -/* - * INIT part - */ - -static int __init alsa_sb16_init(void) -{ - return 0; -} - -static void __exit alsa_sb16_exit(void) -{ -} - -module_init(alsa_sb16_init) -module_exit(alsa_sb16_exit) diff --git a/sound/isa/sb/sb8_main.c b/sound/isa/sb/sb8_main.c index 80e7dcaa551f..481797744b3c 100644 --- a/sound/isa/sb/sb8_main.c +++ b/sound/isa/sb/sb8_main.c @@ -621,19 +621,3 @@ EXPORT_SYMBOL(snd_sb8dsp_interrupt); /* sb8_midi.c */ EXPORT_SYMBOL(snd_sb8dsp_midi_interrupt); EXPORT_SYMBOL(snd_sb8dsp_midi); - -/* - * INIT part - */ - -static int __init alsa_sb8_init(void) -{ - return 0; -} - -static void __exit alsa_sb8_exit(void) -{ -} - -module_init(alsa_sb8_init) -module_exit(alsa_sb8_exit) diff --git a/sound/isa/sb/sb_common.c b/sound/isa/sb/sb_common.c index 787a4ade4afd..90b254aaef74 100644 --- a/sound/isa/sb/sb_common.c +++ b/sound/isa/sb/sb_common.c @@ -305,19 +305,3 @@ EXPORT_SYMBOL(snd_sbmixer_add_ctl); EXPORT_SYMBOL(snd_sbmixer_suspend); EXPORT_SYMBOL(snd_sbmixer_resume); #endif - -/* - * INIT part - */ - -static int __init alsa_sb_common_init(void) -{ - return 0; -} - -static void __exit alsa_sb_common_exit(void) -{ -} - -module_init(alsa_sb_common_init) -module_exit(alsa_sb_common_exit) diff --git a/sound/isa/wss/wss_lib.c b/sound/isa/wss/wss_lib.c index d23cc8abe1ef..32453f81b95a 100644 --- a/sound/isa/wss/wss_lib.c +++ b/sound/isa/wss/wss_lib.c @@ -2279,19 +2279,3 @@ const struct snd_pcm_ops *snd_wss_get_pcm_ops(int direction) &snd_wss_playback_ops : &snd_wss_capture_ops; } EXPORT_SYMBOL(snd_wss_get_pcm_ops); - -/* - * INIT part - */ - -static int __init alsa_wss_init(void) -{ - return 0; -} - -static void __exit alsa_wss_exit(void) -{ -} - -module_init(alsa_wss_init); -module_exit(alsa_wss_exit); -- cgit v1.2.3 From 3b23dc52da90c340c51273414f4e2d13e07e594c Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 3 Aug 2018 15:48:26 +0200 Subject: ALSA: i2c: Remove empty init and exit For a sake of code simplification, remove the init and the exit entries that do nothing. Notes for readers: actually it's OK to remove *both* init and exit, but not OK to remove the exit entry. By removing only the exit while keeping init, the module becomes permanently loaded; i.e. you cannot unload it any longer! Signed-off-by: Takashi Iwai --- sound/i2c/cs8427.c | 12 ------------ sound/i2c/i2c.c | 13 ------------- sound/i2c/other/ak4xxx-adda.c | 12 ------------ sound/i2c/tea6330t.c | 16 ---------------- 4 files changed, 53 deletions(-) (limited to 'sound') diff --git a/sound/i2c/cs8427.c b/sound/i2c/cs8427.c index 7e21621e492a..2647309bc675 100644 --- a/sound/i2c/cs8427.c +++ b/sound/i2c/cs8427.c @@ -621,15 +621,3 @@ int snd_cs8427_iec958_pcm(struct snd_i2c_device *cs8427, unsigned int rate) } EXPORT_SYMBOL(snd_cs8427_iec958_pcm); - -static int __init alsa_cs8427_module_init(void) -{ - return 0; -} - -static void __exit alsa_cs8427_module_exit(void) -{ -} - -module_init(alsa_cs8427_module_init) -module_exit(alsa_cs8427_module_exit) diff --git a/sound/i2c/i2c.c b/sound/i2c/i2c.c index ef2a9afe9e19..c4a232f18a79 100644 --- a/sound/i2c/i2c.c +++ b/sound/i2c/i2c.c @@ -338,16 +338,3 @@ static int snd_i2c_bit_probeaddr(struct snd_i2c_bus *bus, unsigned short addr) snd_i2c_bit_stop(bus); return err; } - - -static int __init alsa_i2c_init(void) -{ - return 0; -} - -static void __exit alsa_i2c_exit(void) -{ -} - -module_init(alsa_i2c_init) -module_exit(alsa_i2c_exit) diff --git a/sound/i2c/other/ak4xxx-adda.c b/sound/i2c/other/ak4xxx-adda.c index bf377dc192aa..7f2761a2e7c8 100644 --- a/sound/i2c/other/ak4xxx-adda.c +++ b/sound/i2c/other/ak4xxx-adda.c @@ -911,15 +911,3 @@ int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak) return 0; } EXPORT_SYMBOL(snd_akm4xxx_build_controls); - -static int __init alsa_akm4xxx_module_init(void) -{ - return 0; -} - -static void __exit alsa_akm4xxx_module_exit(void) -{ -} - -module_init(alsa_akm4xxx_module_init) -module_exit(alsa_akm4xxx_module_exit) diff --git a/sound/i2c/tea6330t.c b/sound/i2c/tea6330t.c index 2d22310dce05..239c4822427f 100644 --- a/sound/i2c/tea6330t.c +++ b/sound/i2c/tea6330t.c @@ -368,19 +368,3 @@ int snd_tea6330t_update_mixer(struct snd_card *card, EXPORT_SYMBOL(snd_tea6330t_detect); EXPORT_SYMBOL(snd_tea6330t_update_mixer); - -/* - * INIT part - */ - -static int __init alsa_tea6330t_init(void) -{ - return 0; -} - -static void __exit alsa_tea6330t_exit(void) -{ -} - -module_init(alsa_tea6330t_init) -module_exit(alsa_tea6330t_exit) -- cgit v1.2.3 From a7da09fecf35cc1b328f0229c019757f6582f6bb Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 3 Aug 2018 15:48:41 +0200 Subject: ALSA: pci: Remove empty init and exit For a sake of code simplification, remove the init and the exit entries that do nothing. Notes for readers: actually it's OK to remove *both* init and exit, but not OK to remove the exit entry. By removing only the exit while keeping init, the module becomes permanently loaded; i.e. you cannot unload it any longer! Signed-off-by: Takashi Iwai --- sound/pci/ac97/ac97_codec.c | 16 ---------------- sound/pci/ice1712/ak4xxx.c | 12 ------------ 2 files changed, 28 deletions(-) (limited to 'sound') diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index 1ef7cdf1d3e8..f4459d1a9d67 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -2941,19 +2941,3 @@ int snd_ac97_tune_hardware(struct snd_ac97 *ac97, } EXPORT_SYMBOL(snd_ac97_tune_hardware); - -/* - * INIT part - */ - -static int __init alsa_ac97_init(void) -{ - return 0; -} - -static void __exit alsa_ac97_exit(void) -{ -} - -module_init(alsa_ac97_init) -module_exit(alsa_ac97_exit) diff --git a/sound/pci/ice1712/ak4xxx.c b/sound/pci/ice1712/ak4xxx.c index 179ef7a5f0d1..a553897a4c4f 100644 --- a/sound/pci/ice1712/ak4xxx.c +++ b/sound/pci/ice1712/ak4xxx.c @@ -179,18 +179,6 @@ int snd_ice1712_akm4xxx_build_controls(struct snd_ice1712 *ice) return 0; } -static int __init alsa_ice1712_akm4xxx_module_init(void) -{ - return 0; -} - -static void __exit alsa_ice1712_akm4xxx_module_exit(void) -{ -} - -module_init(alsa_ice1712_akm4xxx_module_init) -module_exit(alsa_ice1712_akm4xxx_module_exit) - EXPORT_SYMBOL(snd_ice1712_akm4xxx_init); EXPORT_SYMBOL(snd_ice1712_akm4xxx_free); EXPORT_SYMBOL(snd_ice1712_akm4xxx_build_controls); -- cgit v1.2.3 From c000c4f1d96534885bc7a8ef5185fd8c0de5e827 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 3 Aug 2018 15:48:54 +0200 Subject: ALSA: synth: Remove empty init and exit For a sake of code simplification, remove the init and the exit entries that do nothing. Notes for readers: actually it's OK to remove *both* init and exit, but not OK to remove the exit entry. By removing only the exit while keeping init, the module becomes permanently loaded; i.e. you cannot unload it any longer! Signed-off-by: Takashi Iwai --- sound/synth/emux/emux.c | 17 ----------------- sound/synth/util_mem.c | 16 ---------------- 2 files changed, 33 deletions(-) (limited to 'sound') diff --git a/sound/synth/emux/emux.c b/sound/synth/emux/emux.c index b840ff2dcfbb..64f3141a3e1b 100644 --- a/sound/synth/emux/emux.c +++ b/sound/synth/emux/emux.c @@ -163,20 +163,3 @@ int snd_emux_free(struct snd_emux *emu) } EXPORT_SYMBOL(snd_emux_free); - - -/* - * INIT part - */ - -static int __init alsa_emux_init(void) -{ - return 0; -} - -static void __exit alsa_emux_exit(void) -{ -} - -module_init(alsa_emux_init) -module_exit(alsa_emux_exit) diff --git a/sound/synth/util_mem.c b/sound/synth/util_mem.c index 8e34bc4e07ec..4bd1e98200d2 100644 --- a/sound/synth/util_mem.c +++ b/sound/synth/util_mem.c @@ -193,19 +193,3 @@ EXPORT_SYMBOL(snd_util_mem_avail); EXPORT_SYMBOL(__snd_util_mem_alloc); EXPORT_SYMBOL(__snd_util_mem_free); EXPORT_SYMBOL(__snd_util_memblk_new); - -/* - * INIT part - */ - -static int __init alsa_util_mem_init(void) -{ - return 0; -} - -static void __exit alsa_util_mem_exit(void) -{ -} - -module_init(alsa_util_mem_init) -module_exit(alsa_util_mem_exit) -- cgit v1.2.3 From 2f3b94e539a46052f8eba1f295ff5646e227578a Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Fri, 3 Aug 2018 15:52:33 -0500 Subject: ALSA: seq: Mark expected switch fall-through In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. Notice that in this particular case, I replaced the code comment with a proper "fall through" annotation, which is what GCC is expecting to find. Signed-off-by: Gustavo A. R. Silva Signed-off-by: Takashi Iwai --- sound/core/seq/seq_midi_emul.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/core/seq/seq_midi_emul.c b/sound/core/seq/seq_midi_emul.c index f9f21331aeea..c1975dd31871 100644 --- a/sound/core/seq/seq_midi_emul.c +++ b/sound/core/seq/seq_midi_emul.c @@ -318,7 +318,7 @@ do_control(struct snd_midi_op *ops, void *drv, struct snd_midi_channel_set *chse break; case MIDI_CTL_MSB_DATA_ENTRY: chan->control[MIDI_CTL_LSB_DATA_ENTRY] = 0; - /* go through here */ + /* fall through */ case MIDI_CTL_LSB_DATA_ENTRY: if (chan->param_type == SNDRV_MIDI_PARAM_TYPE_REGISTERED) rpn(ops, drv, chan, chset); -- cgit v1.2.3 From eb2caeb88c181904110f8e74995c7b0bb7fd39f6 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Fri, 3 Aug 2018 15:53:54 -0500 Subject: ALSA: seq_oss: Mark expected switch fall-through In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. Warning level 2 was used: -Wimplicit-fallthrough=2 Signed-off-by: Gustavo A. R. Silva Signed-off-by: Takashi Iwai --- sound/core/seq/oss/seq_oss_timer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/core/seq/oss/seq_oss_timer.c b/sound/core/seq/oss/seq_oss_timer.c index 4f24ea9fad93..ba127c22539a 100644 --- a/sound/core/seq/oss/seq_oss_timer.c +++ b/sound/core/seq/oss/seq_oss_timer.c @@ -92,7 +92,7 @@ snd_seq_oss_process_timer_event(struct seq_oss_timer *rec, union evrec *ev) case TMR_WAIT_REL: parm += rec->cur_tick; rec->realtime = 0; - /* continue to next */ + /* fall through and continue to next */ case TMR_WAIT_ABS: if (parm == 0) { rec->realtime = 1; -- cgit v1.2.3 From 56e40eb6d656194e55ce2012fee9d5a496270aaa Mon Sep 17 00:00:00 2001 From: Alexandru Gagniuc Date: Sat, 4 Aug 2018 11:44:44 -0500 Subject: ALSA: hda/realtek - Add mute LED quirk for HP Spectre x360 This device has the same issues as the HP x360 wrt the MUTE LED and the front speakers not working. This patch fixes the MUTE LED issue, but doesn't touch the HDA verbs. The fix for the x360 does not work on the Spectre. Signed-off-by: Alexandru Gagniuc Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index e2d0b2f3bd30..b20974ef1e13 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -6474,6 +6474,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x103c, 0x827e, "HP x360", ALC295_FIXUP_HP_X360), SND_PCI_QUIRK(0x103c, 0x82bf, "HP", ALC221_FIXUP_HP_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x103c, 0x82c0, "HP", ALC221_FIXUP_HP_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x103c, 0x83b9, "HP Spectre x360", ALC269_FIXUP_HP_MUTE_LED_MIC3), SND_PCI_QUIRK(0x1043, 0x103e, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC), SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300), SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), -- cgit v1.2.3 From ac69c2f578bf51a3804c5e96467571ea5be0e882 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Sat, 4 Aug 2018 15:11:03 -0500 Subject: ALSA: mixart: Mark expected switch fall-through In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. Signed-off-by: Gustavo A. R. Silva Signed-off-by: Takashi Iwai --- sound/pci/mixart/mixart.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound') diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c index a74f1ad7e7b8..9cd297a42f24 100644 --- a/sound/pci/mixart/mixart.c +++ b/sound/pci/mixart/mixart.c @@ -182,6 +182,7 @@ static int mixart_set_clock(struct mixart_mgr *mgr, case PIPE_RUNNING: if(rate != 0) break; + /* fall through */ default: if(rate == 0) return 0; /* nothing to do */ -- cgit v1.2.3 From 9d5a289a86a15a1a4248022f9338517f7e62832b Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Sat, 4 Aug 2018 15:12:09 -0500 Subject: ALSA: emu10k1: Mark expected switch fall-throughs In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. Notice that in this particular case, I replaced the code comment with a proper "fall through" annotation, which is what GCC is expecting to find. Signed-off-by: Gustavo A. R. Silva Signed-off-by: Takashi Iwai --- sound/pci/emu10k1/emupcm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c index 26f6eda3e766..9f2b6097f486 100644 --- a/sound/pci/emu10k1/emupcm.c +++ b/sound/pci/emu10k1/emupcm.c @@ -778,7 +778,7 @@ static int snd_emu10k1_playback_trigger(struct snd_pcm_substream *substream, case SNDRV_PCM_TRIGGER_START: snd_emu10k1_playback_invalidate_cache(emu, 1, epcm->extra); /* do we need this? */ snd_emu10k1_playback_invalidate_cache(emu, 0, epcm->voices[0]); - /* follow thru */ + /* fall through */ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: case SNDRV_PCM_TRIGGER_RESUME: if (cmd == SNDRV_PCM_TRIGGER_PAUSE_RELEASE) @@ -928,7 +928,7 @@ static int snd_emu10k1_efx_playback_trigger(struct snd_pcm_substream *substream, } snd_emu10k1_playback_invalidate_cache(emu, 1, epcm->extra); - /* follow thru */ + /* fall through */ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: case SNDRV_PCM_TRIGGER_RESUME: snd_emu10k1_playback_prepare_voice(emu, epcm->extra, 1, 1, NULL); -- cgit v1.2.3 From ef0075280cfe09ef076ce1b85f0a2294c5ed86f3 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Sat, 4 Aug 2018 15:13:26 -0500 Subject: ALSA: echoaudio: Mark expected switch fall-throughs In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. Addresses-Coverity-ID: 115156 ("Missing break in switch") Signed-off-by: Gustavo A. R. Silva Signed-off-by: Takashi Iwai --- sound/pci/echoaudio/echoaudio.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sound') diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c index 358ef7dcf410..907cf1a46712 100644 --- a/sound/pci/echoaudio/echoaudio.c +++ b/sound/pci/echoaudio/echoaudio.c @@ -713,6 +713,7 @@ static int pcm_prepare(struct snd_pcm_substream *substream) break; case SNDRV_PCM_FORMAT_S32_BE: format.data_are_bigendian = 1; + /* fall through */ case SNDRV_PCM_FORMAT_S32_LE: format.bits_per_sample = 32; break; @@ -764,6 +765,7 @@ static int pcm_trigger(struct snd_pcm_substream *substream, int cmd) pipe->last_counter = 0; pipe->position = 0; *pipe->dma_counter = 0; + /* fall through */ case PIPE_STATE_PAUSED: pipe->state = PIPE_STATE_STARTED; break; -- cgit v1.2.3 From d2f884612c42850db0b3521b74a05636a5fc035f Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 1 Aug 2018 11:47:42 +0100 Subject: ALSA: intel_hdmi: remove redundant variable cfg_val Variable cfg_val is being assigned but is never used hence it is redundant and can be removed. Cleans up clang warning: warning: variable 'cfg_val' set but not used [-Wunused-but-set-variable] [ Background info about val_bit field from alsa-devel ML thread: tiwai: Actually this made me wonder what is the definition of val_bit. It seems always 1 in the current code after the commit 964ca8083c02. Pierre? pbossart: This val_bit is only there for debug/test, it should be set to one by default and has nothing to do with the lpcm_id. This variable was set even in patches before upstream submission and was never needed, I guess it must be a 9-yr old issue. Good catch! ] Signed-off-by: Colin Ian King Acked-by: Pierre-Louis Bossart Signed-off-by: Takashi Iwai --- sound/x86/intel_hdmi_audio.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'sound') diff --git a/sound/x86/intel_hdmi_audio.c b/sound/x86/intel_hdmi_audio.c index edc9f5a34eff..fa7dca5a68c8 100644 --- a/sound/x86/intel_hdmi_audio.c +++ b/sound/x86/intel_hdmi_audio.c @@ -290,7 +290,6 @@ static void had_reset_audio(struct snd_intelhad *intelhaddata) static int had_prog_status_reg(struct snd_pcm_substream *substream, struct snd_intelhad *intelhaddata) { - union aud_cfg cfg_val = {.regval = 0}; union aud_ch_status_0 ch_stat0 = {.regval = 0}; union aud_ch_status_1 ch_stat1 = {.regval = 0}; @@ -298,7 +297,6 @@ static int had_prog_status_reg(struct snd_pcm_substream *substream, IEC958_AES0_NONAUDIO) >> 1; ch_stat0.regx.clk_acc = (intelhaddata->aes_bits & IEC958_AES3_CON_CLOCK) >> 4; - cfg_val.regx.val_bit = ch_stat0.regx.lpcm_id; switch (substream->runtime->rate) { case AUD_SAMPLE_RATE_32: -- cgit v1.2.3 From a62e4739473a29646af4e37a5da289795cde6dc0 Mon Sep 17 00:00:00 2001 From: Connor McAdams Date: Wed, 8 Aug 2018 13:34:12 -0400 Subject: ALSA: hda/ca0132 - Create mmio gpio function to make code clearer This patch adds a new function, ca0132_mmio_gpio_set, to clear up what is going on with writes to mmio region 0x320. Signed-off-by: Connor McAdams Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_ca0132.c | 62 +++++++++++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 24 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 27d3388cd2a2..665142ef1186 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -3072,6 +3072,24 @@ static bool dspload_wait_loaded(struct hda_codec *codec) * Setup GPIO for the other variants of Core3D. */ +/* + * For cards with PCI-E region2 (Sound Blaster Z/ZxR, Recon3D, and AE-5) + * the mmio address 0x320 is used to set GPIO pins. The format for the data + * The first eight bits are just the number of the pin. So far, I've only seen + * this number go to 7. + */ +static void ca0132_mmio_gpio_set(struct hda_codec *codec, unsigned int gpio_pin, + bool enable) +{ + struct ca0132_spec *spec = codec->spec; + unsigned short gpio_data; + + gpio_data = gpio_pin & 0xF; + gpio_data |= ((enable << 8) & 0x100); + + writew(gpio_data, spec->mem_base + 0x320); +} + /* * Sets up the GPIO pins so that they are discoverable. If this isn't done, * the card shows as having no GPIO pins. @@ -3947,9 +3965,9 @@ static int ca0132_alt_select_out(struct hda_codec *codec) /*speaker out config*/ switch (spec->quirk) { case QUIRK_SBZ: - writew(0x0007, spec->mem_base + 0x320); - writew(0x0104, spec->mem_base + 0x320); - writew(0x0101, spec->mem_base + 0x320); + ca0132_mmio_gpio_set(codec, 7, false); + ca0132_mmio_gpio_set(codec, 4, true); + ca0132_mmio_gpio_set(codec, 1, true); chipio_set_control_param(codec, 0x0D, 0x18); break; case QUIRK_R3DI: @@ -3983,9 +4001,9 @@ static int ca0132_alt_select_out(struct hda_codec *codec) /* Headphone out config*/ switch (spec->quirk) { case QUIRK_SBZ: - writew(0x0107, spec->mem_base + 0x320); - writew(0x0104, spec->mem_base + 0x320); - writew(0x0001, spec->mem_base + 0x320); + ca0132_mmio_gpio_set(codec, 7, true); + ca0132_mmio_gpio_set(codec, 4, true); + ca0132_mmio_gpio_set(codec, 1, false); chipio_set_control_param(codec, 0x0D, 0x12); break; case QUIRK_R3DI: @@ -4025,9 +4043,9 @@ static int ca0132_alt_select_out(struct hda_codec *codec) /* Surround out config*/ switch (spec->quirk) { case QUIRK_SBZ: - writew(0x0007, spec->mem_base + 0x320); - writew(0x0104, spec->mem_base + 0x320); - writew(0x0101, spec->mem_base + 0x320); + ca0132_mmio_gpio_set(codec, 7, false); + ca0132_mmio_gpio_set(codec, 4, true); + ca0132_mmio_gpio_set(codec, 1, true); chipio_set_control_param(codec, 0x0D, 0x18); break; case QUIRK_R3DI: @@ -4291,7 +4309,7 @@ static int ca0132_alt_select_in(struct hda_codec *codec) case REAR_MIC: switch (spec->quirk) { case QUIRK_SBZ: - writew(0x0000, spec->mem_base + 0x320); + ca0132_mmio_gpio_set(codec, 0, false); tmp = FLOAT_THREE; break; case QUIRK_R3DI: @@ -4323,7 +4341,7 @@ static int ca0132_alt_select_in(struct hda_codec *codec) ca0132_mic_boost_set(codec, 0); switch (spec->quirk) { case QUIRK_SBZ: - writew(0x0000, spec->mem_base + 0x320); + ca0132_mmio_gpio_set(codec, 0, false); break; case QUIRK_R3DI: r3di_gpio_mic_set(codec, R3DI_REAR_MIC); @@ -4349,8 +4367,8 @@ static int ca0132_alt_select_in(struct hda_codec *codec) case FRONT_MIC: switch (spec->quirk) { case QUIRK_SBZ: - writew(0x0100, spec->mem_base + 0x320); - writew(0x0005, spec->mem_base + 0x320); + ca0132_mmio_gpio_set(codec, 0, true); + ca0132_mmio_gpio_set(codec, 5, false); tmp = FLOAT_THREE; break; case QUIRK_R3DI: @@ -6890,16 +6908,12 @@ static void sbz_region2_exit(struct hda_codec *codec) writeb(0x0, spec->mem_base + 0x100); for (i = 0; i < 8; i++) writeb(0xb3, spec->mem_base + 0x304); - /* - * I believe these are GPIO, with the right most hex digit being the - * gpio pin, and the second digit being on or off. We see this more in - * the input/output select functions. - */ - writew(0x0000, spec->mem_base + 0x320); - writew(0x0001, spec->mem_base + 0x320); - writew(0x0104, spec->mem_base + 0x320); - writew(0x0005, spec->mem_base + 0x320); - writew(0x0007, spec->mem_base + 0x320); + + ca0132_mmio_gpio_set(codec, 0, false); + ca0132_mmio_gpio_set(codec, 1, false); + ca0132_mmio_gpio_set(codec, 4, true); + ca0132_mmio_gpio_set(codec, 5, false); + ca0132_mmio_gpio_set(codec, 7, false); } static void sbz_set_pin_ctl_default(struct hda_codec *codec) @@ -7236,7 +7250,7 @@ static int ca0132_init(struct hda_codec *codec) ca0132_refresh_widget_caps(codec); if (spec->quirk == QUIRK_SBZ) - writew(0x0107, spec->mem_base + 0x320); + ca0132_mmio_gpio_set(codec, 7, true); switch (spec->quirk) { case QUIRK_R3DI: -- cgit v1.2.3 From d97420d2b0379e498adc3fae5db8fa70945b5d56 Mon Sep 17 00:00:00 2001 From: Connor McAdams Date: Wed, 8 Aug 2018 13:34:13 -0400 Subject: ALSA: hda/ca0132 - Clean up ca0132_init function. This patch cleans up ca0132_init by removing unnecessary commands and ordering things better. Signed-off-by: Connor McAdams Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_ca0132.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 665142ef1186..8b98d18d97ac 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -7249,14 +7249,12 @@ static int ca0132_init(struct hda_codec *codec) ca0132_refresh_widget_caps(codec); - if (spec->quirk == QUIRK_SBZ) - ca0132_mmio_gpio_set(codec, 7, true); - switch (spec->quirk) { case QUIRK_R3DI: r3di_setup_defaults(codec); break; case QUIRK_SBZ: + sbz_setup_defaults(codec); break; default: ca0132_setup_defaults(codec); @@ -7287,20 +7285,12 @@ static int ca0132_init(struct hda_codec *codec) ca0132_gpio_setup(codec); snd_hda_sequence_write(codec, spec->spec_init_verbs); - switch (spec->quirk) { - case QUIRK_SBZ: - sbz_setup_defaults(codec); - ca0132_alt_select_out(codec); - ca0132_alt_select_in(codec); - break; - case QUIRK_R3DI: + if (spec->use_alt_functions) { ca0132_alt_select_out(codec); ca0132_alt_select_in(codec); - break; - default: + } else { ca0132_select_out(codec); ca0132_select_mic(codec); - break; } snd_hda_jack_report_sync(codec); -- cgit v1.2.3 From a1b7f016a1ae5e51f0e11a70cf1a5875d3ccee73 Mon Sep 17 00:00:00 2001 From: Connor McAdams Date: Wed, 8 Aug 2018 13:34:14 -0400 Subject: ALSA: hda/ca0132 - Add alt_functions unsolicited response This patch fixes a previous oversight where the microphone unsolicited response would use the wrong input selection function. Signed-off-by: Connor McAdams Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_ca0132.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 8b98d18d97ac..3e43d5686207 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -6744,7 +6744,12 @@ static void hp_callback(struct hda_codec *codec, struct hda_jack_callback *cb) static void amic_callback(struct hda_codec *codec, struct hda_jack_callback *cb) { - ca0132_select_mic(codec); + struct ca0132_spec *spec = codec->spec; + + if (spec->use_alt_functions) + ca0132_alt_select_in(codec); + else + ca0132_select_mic(codec); } static void ca0132_init_unsol(struct hda_codec *codec) -- cgit v1.2.3 From 8f8c523c4604afe231196920bf08310141a4f0ba Mon Sep 17 00:00:00 2001 From: Connor McAdams Date: Wed, 8 Aug 2018 13:34:15 -0400 Subject: ALSA: hda/ca0132 - Add quirk ID and enum for Recon3D This patch adds the PCI subsys ID for the Recon3D that has been tested, and adds the QUIRK_R3D enumeration. Signed-off-by: Connor McAdams Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_ca0132.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sound') diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 3e43d5686207..8a4be5fcba55 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -994,6 +994,7 @@ enum { QUIRK_ALIENWARE_M17XR4, QUIRK_SBZ, QUIRK_R3DI, + QUIRK_R3D, }; static const struct hda_pintbl alienware_pincfgs[] = { @@ -1050,6 +1051,7 @@ static const struct snd_pci_quirk ca0132_quirks[] = { SND_PCI_QUIRK(0x1458, 0xA016, "Recon3Di", QUIRK_R3DI), SND_PCI_QUIRK(0x1458, 0xA026, "Gigabyte G1.Sniper Z97", QUIRK_R3DI), SND_PCI_QUIRK(0x1458, 0xA036, "Gigabyte GA-Z170X-Gaming 7", QUIRK_R3DI), + SND_PCI_QUIRK(0x1102, 0x0013, "Recon3D", QUIRK_R3D), {} }; -- cgit v1.2.3 From 7f73df95401f7a2392ccf1880ba1e54cfed62779 Mon Sep 17 00:00:00 2001 From: Connor McAdams Date: Wed, 8 Aug 2018 13:34:16 -0400 Subject: ALSA: hda/ca0132 - Add Recon3D pincfg This patch adds pin configs from the Recon3D, taken from the Window's driver. Signed-off-by: Connor McAdams Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_ca0132.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 8a4be5fcba55..4d2b79e19516 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -1026,6 +1026,21 @@ static const struct hda_pintbl sbz_pincfgs[] = { {} }; +/* Recon3D pin configs taken from Windows Driver */ +static const struct hda_pintbl r3d_pincfgs[] = { + { 0x0b, 0x01014110 }, /* Port G -- Lineout FRONT L/R */ + { 0x0c, 0x014510f0 }, /* SPDIF Out 1 */ + { 0x0d, 0x014510f0 }, /* Digital Out */ + { 0x0e, 0x01c520f0 }, /* SPDIF In */ + { 0x0f, 0x0221401f }, /* Port A -- BackPanel HP */ + { 0x10, 0x01016011 }, /* Port D -- Center/LFE or FP Hp */ + { 0x11, 0x01011014 }, /* Port B -- LineMicIn2 / Rear L/R */ + { 0x12, 0x02a090f0 }, /* Port C -- LineIn1 */ + { 0x13, 0x908700f0 }, /* What U Hear In*/ + { 0x18, 0x50d000f0 }, /* N/A */ + {} +}; + /* Recon3D integrated pin configs taken from Windows Driver */ static const struct hda_pintbl r3di_pincfgs[] = { { 0x0b, 0x01014110 }, /* Port G -- Lineout FRONT L/R */ @@ -7396,8 +7411,15 @@ static void ca0132_config(struct hda_codec *codec) spec->unsol_tag_amic1 = 0x11; break; case QUIRK_SBZ: - codec_dbg(codec, "%s: QUIRK_SBZ applied.\n", __func__); - snd_hda_apply_pincfgs(codec, sbz_pincfgs); + case QUIRK_R3D: + if (spec->quirk == QUIRK_SBZ) { + codec_dbg(codec, "%s: QUIRK_SBZ applied.\n", __func__); + snd_hda_apply_pincfgs(codec, sbz_pincfgs); + } + if (spec->quirk == QUIRK_R3D) { + codec_dbg(codec, "%s: QUIRK_R3D applied.\n", __func__); + snd_hda_apply_pincfgs(codec, r3d_pincfgs); + } spec->num_outputs = 2; spec->out_pins[0] = 0x0B; /* Line out */ -- cgit v1.2.3 From 08eca6b1f1468a4021bac7b3929fd3eb491e2629 Mon Sep 17 00:00:00 2001 From: Connor McAdams Date: Wed, 8 Aug 2018 13:34:17 -0400 Subject: ALSA: hda/ca0132 - Add bool variable to enable/disable pci region2 mmio This patch adds the ability to choose whether or not to map the pci region2, which is used for things such as GPIO on the Recon3D and Sound Blaster Z. Signed-off-by: Connor McAdams Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_ca0132.c | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 4d2b79e19516..989770797a00 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -965,9 +965,11 @@ struct ca0132_spec { long cur_ctl_vals[TUNING_CTLS_COUNT]; #endif /* - * Sound Blaster Z PCI region 2 iomem, used for input and output - * switching, and other unknown commands. + * The Recon3D, Sound Blaster Z, Sound Blaster ZxR, and Sound Blaster + * AE-5 all use PCI region 2 to toggle GPIO and other currently unknown + * things. */ + bool use_pci_mmio; void __iomem *mem_base; /* @@ -7562,16 +7564,6 @@ static int patch_ca0132(struct hda_codec *codec) else spec->quirk = QUIRK_NONE; - /* Setup BAR Region 2 for Sound Blaster Z */ - if (spec->quirk == QUIRK_SBZ) { - spec->mem_base = pci_iomap(codec->bus->pci, 2, 0xC20); - if (spec->mem_base == NULL) { - codec_warn(codec, "pci_iomap failed!"); - codec_info(codec, "perhaps this is not an SBZ?"); - spec->quirk = QUIRK_NONE; - } - } - spec->dsp_state = DSP_DOWNLOAD_INIT; spec->num_mixers = 1; @@ -7590,19 +7582,33 @@ static int patch_ca0132(struct hda_codec *codec) break; } - /* Setup whether or not to use alt functions/controls */ + /* Setup whether or not to use alt functions/controls/pci_mmio */ switch (spec->quirk) { case QUIRK_SBZ: + spec->use_alt_controls = true; + spec->use_alt_functions = true; + spec->use_pci_mmio = true; + break; case QUIRK_R3DI: spec->use_alt_controls = true; spec->use_alt_functions = true; + spec->use_pci_mmio = false; break; default: spec->use_alt_controls = false; spec->use_alt_functions = false; + spec->use_pci_mmio = false; break; } + if (spec->use_pci_mmio) { + spec->mem_base = pci_iomap(codec->bus->pci, 2, 0xC20); + if (spec->mem_base == NULL) { + codec_warn(codec, "pci_iomap failed! Setting quirk to QUIRK_NONE."); + spec->quirk = QUIRK_NONE; + } + } + spec->base_init_verbs = ca0132_base_init_verbs; spec->base_exit_verbs = ca0132_base_exit_verbs; -- cgit v1.2.3 From e42c7c7313e41f121d252711e35deae7964c95ad Mon Sep 17 00:00:00 2001 From: Connor McAdams Date: Wed, 8 Aug 2018 13:34:18 -0400 Subject: ALSA: hda/ca0132 - Add Recon3D startup functions and setup This patch adds functions for Recon3D startup, and sets values for things such as use_pci_mmio. It also renames some functions and tables from the sbz prefix into ca0132, as the Recon3D uses them as well. Signed-off-by: Connor McAdams Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_ca0132.c | 49 ++++++++++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 13 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 989770797a00..c938298cb103 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -897,7 +897,7 @@ struct ca0132_spec { const struct hda_verb *base_init_verbs; const struct hda_verb *base_exit_verbs; const struct hda_verb *chip_init_verbs; - const struct hda_verb *sbz_init_verbs; + const struct hda_verb *desktop_init_verbs; struct hda_verb *spec_init_verbs; struct auto_pin_cfg autocfg; @@ -6839,8 +6839,8 @@ static struct hda_verb ca0132_init_verbs0[] = { {} }; -/* Extra init verbs for SBZ */ -static struct hda_verb sbz_init_verbs[] = { +/* Extra init verbs for desktop cards. */ +static struct hda_verb ca0132_init_verbs1[] = { {0x15, 0x70D, 0x20}, {0x15, 0x70E, 0x19}, {0x15, 0x707, 0x00}, @@ -7135,9 +7135,27 @@ static void sbz_pre_dsp_setup(struct hda_codec *codec) AC_VERB_SET_PIN_WIDGET_CONTROL, 0x44); } -/* - * Extra commands that don't really fit anywhere else. - */ +static void r3d_pre_dsp_setup(struct hda_codec *codec) +{ + + snd_hda_codec_write(codec, 0x15, 0, 0xd00, 0xfc); + snd_hda_codec_write(codec, 0x15, 0, 0xd00, 0xfd); + snd_hda_codec_write(codec, 0x15, 0, 0xd00, 0xfe); + snd_hda_codec_write(codec, 0x15, 0, 0xd00, 0xff); + + chipio_write(codec, 0x18b0a4, 0x000000c2); + + snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, + VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x1E); + snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, + VENDOR_CHIPIO_8051_ADDRESS_HIGH, 0x1C); + snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, + VENDOR_CHIPIO_8051_DATA_WRITE, 0x5B); + + snd_hda_codec_write(codec, 0x11, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, 0x44); +} + static void r3di_pre_dsp_setup(struct hda_codec *codec) { chipio_write(codec, 0x18b0a4, 0x000000c2); @@ -7162,13 +7180,12 @@ static void r3di_pre_dsp_setup(struct hda_codec *codec) AC_VERB_SET_PIN_WIDGET_CONTROL, 0x04); } - /* * These are sent before the DSP is downloaded. Not sure * what they do, or if they're necessary. Could possibly * be removed. Figure they're better to leave in. */ -static void sbz_region2_startup(struct hda_codec *codec) +static void ca0132_mmio_init(struct hda_codec *codec) { struct ca0132_spec *spec = codec->spec; @@ -7208,7 +7225,7 @@ static void ca0132_alt_init(struct hda_codec *codec) ca0132_gpio_init(codec); sbz_pre_dsp_setup(codec); snd_hda_sequence_write(codec, spec->chip_init_verbs); - snd_hda_sequence_write(codec, spec->sbz_init_verbs); + snd_hda_sequence_write(codec, spec->desktop_init_verbs); break; case QUIRK_R3DI: codec_dbg(codec, "R3DI alt_init"); @@ -7219,6 +7236,11 @@ static void ca0132_alt_init(struct hda_codec *codec) snd_hda_sequence_write(codec, spec->chip_init_verbs); snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, 0x6FF, 0xC4); break; + case QUIRK_R3D: + r3d_pre_dsp_setup(codec); + snd_hda_sequence_write(codec, spec->chip_init_verbs); + snd_hda_sequence_write(codec, spec->desktop_init_verbs); + break; } } @@ -7255,8 +7277,8 @@ static int ca0132_init(struct hda_codec *codec) spec->dsp_state = DSP_DOWNLOAD_INIT; spec->curr_chip_addx = INVALID_CHIP_ADDRESS; - if (spec->quirk == QUIRK_SBZ) - sbz_region2_startup(codec); + if (spec->use_pci_mmio) + ca0132_mmio_init(codec); snd_hda_power_up_pm(codec); @@ -7507,8 +7529,8 @@ static int ca0132_prepare_verbs(struct hda_codec *codec) struct ca0132_spec *spec = codec->spec; spec->chip_init_verbs = ca0132_init_verbs0; - if (spec->quirk == QUIRK_SBZ) - spec->sbz_init_verbs = sbz_init_verbs; + if (spec->quirk == QUIRK_SBZ || spec->quirk == QUIRK_R3D) + spec->desktop_init_verbs = ca0132_init_verbs1; spec->spec_init_verbs = kcalloc(NUM_SPEC_VERBS, sizeof(struct hda_verb), GFP_KERNEL); @@ -7585,6 +7607,7 @@ static int patch_ca0132(struct hda_codec *codec) /* Setup whether or not to use alt functions/controls/pci_mmio */ switch (spec->quirk) { case QUIRK_SBZ: + case QUIRK_R3D: spec->use_alt_controls = true; spec->use_alt_functions = true; spec->use_pci_mmio = true; -- cgit v1.2.3 From c986f50ca974397f8726bf6776ad8938d6808848 Mon Sep 17 00:00:00 2001 From: Connor McAdams Date: Wed, 8 Aug 2018 13:34:19 -0400 Subject: ALSA: hda/ca0132 - Add DSP setup defaults for Recon3D The Recon3D can use many of the same functions as the Recon3Di, so many of the r3di prefix function remain the same, but change their names to the more generic r3d prefix. This patch does this, and adds quirk checks for things specific to the Recon3Di. Signed-off-by: Connor McAdams Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_ca0132.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index c938298cb103..8edd7675fb77 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -6223,10 +6223,10 @@ static void ca0132_refresh_widget_caps(struct hda_codec *codec) } /* - * Recon3Di r3di_setup_defaults sub functions. + * Recon3D r3d_setup_defaults sub functions. */ -static void r3di_dsp_scp_startup(struct hda_codec *codec) +static void r3d_dsp_scp_startup(struct hda_codec *codec) { unsigned int tmp; @@ -6247,7 +6247,7 @@ static void r3di_dsp_scp_startup(struct hda_codec *codec) } -static void r3di_dsp_initial_mic_setup(struct hda_codec *codec) +static void r3d_dsp_initial_mic_setup(struct hda_codec *codec) { unsigned int tmp; @@ -6457,10 +6457,10 @@ static void ca0132_setup_defaults(struct hda_codec *codec) } /* - * Setup default parameters for Recon3Di DSP. + * Setup default parameters for Recon3D/Recon3Di DSP. */ -static void r3di_setup_defaults(struct hda_codec *codec) +static void r3d_setup_defaults(struct hda_codec *codec) { struct ca0132_spec *spec = codec->spec; unsigned int tmp; @@ -6470,9 +6470,9 @@ static void r3di_setup_defaults(struct hda_codec *codec) if (spec->dsp_state != DSP_DOWNLOADED) return; - r3di_dsp_scp_startup(codec); + r3d_dsp_scp_startup(codec); - r3di_dsp_initial_mic_setup(codec); + r3d_dsp_initial_mic_setup(codec); /*remove DSP headroom*/ tmp = FLOAT_ZERO; @@ -6486,7 +6486,8 @@ static void r3di_setup_defaults(struct hda_codec *codec) /* Set speaker source? */ dspio_set_uint_param(codec, 0x32, 0x00, tmp); - r3di_gpio_dsp_status_set(codec, R3DI_DSP_DOWNLOADED); + if (spec->quirk == QUIRK_R3DI) + r3di_gpio_dsp_status_set(codec, R3DI_DSP_DOWNLOADED); /* Setup effect defaults */ num_fx = OUT_EFFECTS_COUNT + IN_EFFECTS_COUNT + 1; @@ -6498,7 +6499,6 @@ static void r3di_setup_defaults(struct hda_codec *codec) ca0132_effects[idx].def_vals[i]); } } - } /* @@ -7297,7 +7297,8 @@ static int ca0132_init(struct hda_codec *codec) switch (spec->quirk) { case QUIRK_R3DI: - r3di_setup_defaults(codec); + case QUIRK_R3D: + r3d_setup_defaults(codec); break; case QUIRK_SBZ: sbz_setup_defaults(codec); -- cgit v1.2.3 From 42aa3a169062c48e5cbb1f3a6523f8b7c892b699 Mon Sep 17 00:00:00 2001 From: Connor McAdams Date: Wed, 8 Aug 2018 13:34:20 -0400 Subject: ALSA: hda/ca0132 - Add Recon3D input and output select commands This patch adds commands to the alternative input and output select commands to support the Recon3D. Signed-off-by: Connor McAdams Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_ca0132.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'sound') diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 8edd7675fb77..d46695e133c0 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -3993,6 +3993,10 @@ static int ca0132_alt_select_out(struct hda_codec *codec) chipio_set_control_param(codec, 0x0D, 0x24); r3di_gpio_out_set(codec, R3DI_LINE_OUT); break; + case QUIRK_R3D: + chipio_set_control_param(codec, 0x0D, 0x24); + ca0132_mmio_gpio_set(codec, 1, true); + break; } /* disable headphone node */ @@ -4029,6 +4033,10 @@ static int ca0132_alt_select_out(struct hda_codec *codec) chipio_set_control_param(codec, 0x0D, 0x21); r3di_gpio_out_set(codec, R3DI_HEADPHONE_OUT); break; + case QUIRK_R3D: + chipio_set_control_param(codec, 0x0D, 0x21); + ca0132_mmio_gpio_set(codec, 0x1, false); + break; } snd_hda_codec_write(codec, spec->out_pins[0], 0, @@ -4071,6 +4079,10 @@ static int ca0132_alt_select_out(struct hda_codec *codec) chipio_set_control_param(codec, 0x0D, 0x24); r3di_gpio_out_set(codec, R3DI_LINE_OUT); break; + case QUIRK_R3D: + ca0132_mmio_gpio_set(codec, 1, true); + chipio_set_control_param(codec, 0x0D, 0x24); + break; } /* enable line out node */ pin_ctl = snd_hda_codec_read(codec, spec->out_pins[0], 0, @@ -4328,6 +4340,7 @@ static int ca0132_alt_select_in(struct hda_codec *codec) case REAR_MIC: switch (spec->quirk) { case QUIRK_SBZ: + case QUIRK_R3D: ca0132_mmio_gpio_set(codec, 0, false); tmp = FLOAT_THREE; break; @@ -4360,6 +4373,7 @@ static int ca0132_alt_select_in(struct hda_codec *codec) ca0132_mic_boost_set(codec, 0); switch (spec->quirk) { case QUIRK_SBZ: + case QUIRK_R3D: ca0132_mmio_gpio_set(codec, 0, false); break; case QUIRK_R3DI: @@ -4386,6 +4400,7 @@ static int ca0132_alt_select_in(struct hda_codec *codec) case FRONT_MIC: switch (spec->quirk) { case QUIRK_SBZ: + case QUIRK_R3D: ca0132_mmio_gpio_set(codec, 0, true); ca0132_mmio_gpio_set(codec, 5, false); tmp = FLOAT_THREE; -- cgit v1.2.3 From e25e3445049c353223752fd1bacead9d413b0a5a Mon Sep 17 00:00:00 2001 From: Connor McAdams Date: Wed, 8 Aug 2018 13:34:21 -0400 Subject: ALSA: hda/ca0132 - Change mixer controls for Recon3D This patch adds changes to setup the Recon3D's mixer controls. Signed-off-by: Connor McAdams Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_ca0132.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index d46695e133c0..601efaa5c610 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -5780,11 +5780,11 @@ static const struct snd_kcontrol_new ca0132_mixer[] = { }; /* - * SBZ specific control mixer. Removes auto-detect for mic, and adds surround - * controls. Also sets both the Front Playback and Capture Volume controls to - * alt so they set the DSP's decibel level. + * Desktop specific control mixer. Removes auto-detect for mic, and adds + * surround controls. Also sets both the Front Playback and Capture Volume + * controls to alt so they set the DSP's decibel level. */ -static const struct snd_kcontrol_new sbz_mixer[] = { +static const struct snd_kcontrol_new desktop_mixer[] = { CA0132_ALT_CODEC_VOL("Front Playback Volume", 0x02, HDA_OUTPUT), CA0132_CODEC_MUTE("Front Playback Switch", VNID_SPK, HDA_OUTPUT), HDA_CODEC_VOLUME("Surround Playback Volume", 0x04, 0, HDA_OUTPUT), @@ -5855,8 +5855,8 @@ static int ca0132_build_controls(struct hda_codec *codec) */ num_fx = OUT_EFFECTS_COUNT + IN_EFFECTS_COUNT; for (i = 0; i < num_fx; i++) { - /* SBZ breaks if Echo Cancellation is used */ - if (spec->quirk == QUIRK_SBZ) { + /* SBZ and R3D break if Echo Cancellation is used. */ + if (spec->quirk == QUIRK_SBZ || spec->quirk == QUIRK_R3D) { if (i == (ECHO_CANCELLATION - IN_EFFECT_START_NID + OUT_EFFECTS_COUNT)) continue; @@ -7608,9 +7608,13 @@ static int patch_ca0132(struct hda_codec *codec) /* Set which mixers each quirk uses. */ switch (spec->quirk) { case QUIRK_SBZ: - spec->mixers[0] = sbz_mixer; + spec->mixers[0] = desktop_mixer; snd_hda_codec_set_name(codec, "Sound Blaster Z"); break; + case QUIRK_R3D: + spec->mixers[0] = desktop_mixer; + snd_hda_codec_set_name(codec, "Recon3D"); + break; case QUIRK_R3DI: spec->mixers[0] = r3di_mixer; snd_hda_codec_set_name(codec, "Recon3Di"); -- cgit v1.2.3 From 2f295f91b740f0055735a7528f8f4cf8b3111239 Mon Sep 17 00:00:00 2001 From: Connor McAdams Date: Wed, 8 Aug 2018 13:34:22 -0400 Subject: ALSA: hda/ca0132 - Add exit commands for Recon3D This patch adds exit functions for the Recon3D, and cleans up the current exit function. Signed-off-by: Connor McAdams Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_ca0132.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 601efaa5c610..0166a3d7cd55 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -6968,7 +6968,7 @@ static void sbz_set_pin_ctl_default(struct hda_codec *codec) AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00); } -static void sbz_clear_unsolicited(struct hda_codec *codec) +static void ca0132_clear_unsolicited(struct hda_codec *codec) { hda_nid_t pins[7] = {0x0B, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13}; unsigned int i; @@ -7021,21 +7021,22 @@ static void sbz_exit_chip(struct hda_codec *codec) chipio_set_control_param(codec, 0x0D, 0x24); - sbz_clear_unsolicited(codec); + ca0132_clear_unsolicited(codec); sbz_set_pin_ctl_default(codec); snd_hda_codec_write(codec, 0x0B, 0, AC_VERB_SET_EAPD_BTLENABLE, 0x00); - if (dspload_is_loaded(codec)) - dsp_reset(codec); - - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_CT_EXTENSIONS_ENABLE, 0x00); - sbz_region2_exit(codec); } +static void r3d_exit_chip(struct hda_codec *codec) +{ + ca0132_clear_unsolicited(codec); + snd_hda_codec_write(codec, 0x01, 0, 0x793, 0x00); + snd_hda_codec_write(codec, 0x01, 0, 0x794, 0x5b); +} + static void ca0132_exit_chip(struct hda_codec *codec) { /* put any chip cleanup stuffs here. */ @@ -7381,16 +7382,17 @@ static void ca0132_free(struct hda_codec *codec) case QUIRK_SBZ: sbz_exit_chip(codec); break; + case QUIRK_R3D: + r3d_exit_chip(codec); + break; case QUIRK_R3DI: r3di_gpio_shutdown(codec); - snd_hda_sequence_write(codec, spec->base_exit_verbs); - ca0132_exit_chip(codec); - break; - default: - snd_hda_sequence_write(codec, spec->base_exit_verbs); - ca0132_exit_chip(codec); break; } + + snd_hda_sequence_write(codec, spec->base_exit_verbs); + ca0132_exit_chip(codec); + snd_hda_power_down(codec); if (spec->mem_base) iounmap(spec->mem_base); -- cgit v1.2.3 From 0c93c5ce107659069d16fa34ddce465acdf9d996 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Wed, 8 Aug 2018 14:25:16 -0500 Subject: ALSA: opl3: Mark expected switch fall-through In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. Addresses-Coverity-ID: 114878 ("Missing break in switch") Signed-off-by: Gustavo A. R. Silva Signed-off-by: Takashi Iwai --- sound/drivers/opl3/opl3_midi.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound') diff --git a/sound/drivers/opl3/opl3_midi.c b/sound/drivers/opl3/opl3_midi.c index 471916ca0b6b..a33cb744e96c 100644 --- a/sound/drivers/opl3/opl3_midi.c +++ b/sound/drivers/opl3/opl3_midi.c @@ -368,6 +368,7 @@ void snd_opl3_note_on(void *p, int note, int vel, struct snd_midi_channel *chan) instr_4op = 1; break; } + /* fall through */ default: spin_unlock_irqrestore(&opl3->voice_lock, flags); return; -- cgit v1.2.3 From 725097323bbcbbca51ede20b542c6229a2869445 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Wed, 8 Aug 2018 17:11:48 -0500 Subject: ALSA: mixart: Mark expected switch fall-through In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. Notice that in this particular case, I replaced the code comment with a proper "fall through" annotation, which is what GCC is expecting to find. Addresses-Coverity-ID: 114889 ("Missing break in switch") Signed-off-by: Gustavo A. R. Silva Signed-off-by: Takashi Iwai --- sound/pci/mixart/mixart_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/pci/mixart/mixart_core.c b/sound/pci/mixart/mixart_core.c index 46c292b52fd6..71776bfe0485 100644 --- a/sound/pci/mixart/mixart_core.c +++ b/sound/pci/mixart/mixart_core.c @@ -540,7 +540,7 @@ irqreturn_t snd_mixart_threaded_irq(int irq, void *dev_id) dev_err(&mgr->pci->dev, "canceled notification %x !\n", msg); } - /* no break, continue ! */ + /* fall through */ case MSG_TYPE_ANSWER: /* answer or notification to a message we are waiting for*/ mutex_lock(&mgr->msg_lock); -- cgit v1.2.3 From 91c6e15efc1756b068dc6e945c1626397e60a119 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Wed, 8 Aug 2018 17:23:44 -0500 Subject: ALSA: usb-audio: Mark expected switch fall-through In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. Addresses-Coverity-ID: 1357413 ("Missing break in switch") Addresses-Coverity-ID: 114917 ("Missing break in switch") Signed-off-by: Gustavo A. R. Silva Signed-off-by: Takashi Iwai --- sound/usb/mixer.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sound') diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 73e811f86a95..c63c84b54969 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -856,12 +856,14 @@ static int check_input_term(struct mixer_build *state, int id, term->type = UAC3_PROCESSING_UNIT << 16; /* virtual type */ else /* UAC_VERSION_2 */ term->type = UAC3_EFFECT_UNIT << 16; /* virtual type */ + /* fall through */ case UAC1_EXTENSION_UNIT: /* UAC2_PROCESSING_UNIT_V2 */ if (protocol == UAC_VERSION_1 && !term->type) term->type = UAC3_EXTENSION_UNIT << 16; /* virtual type */ else if (protocol == UAC_VERSION_2 && !term->type) term->type = UAC3_PROCESSING_UNIT << 16; /* virtual type */ + /* fall through */ case UAC2_EXTENSION_UNIT_V2: { struct uac_processing_unit_descriptor *d = p1; -- cgit v1.2.3