diff options
Diffstat (limited to 'sound/pci')
-rw-r--r-- | sound/pci/emu10k1/emu10k1x.c | 4 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.c | 2 | ||||
-rw-r--r-- | sound/pci/hda/hda_generic.c | 12 | ||||
-rw-r--r-- | sound/pci/hda/hda_generic.h | 1 | ||||
-rw-r--r-- | sound/pci/hda/hda_intel.c | 3 | ||||
-rw-r--r-- | sound/pci/hda/hda_proc.c | 38 | ||||
-rw-r--r-- | sound/pci/hda/hda_sysfs.c | 2 | ||||
-rw-r--r-- | sound/pci/hda/patch_ca0132.c | 739 | ||||
-rw-r--r-- | sound/pci/hda/patch_hdmi.c | 128 | ||||
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 203 | ||||
-rw-r--r-- | sound/pci/mixart/mixart_core.c | 5 | ||||
-rw-r--r-- | sound/pci/rme32.c | 1 | ||||
-rw-r--r-- | sound/pci/rme9652/hdspm.c | 9 | ||||
-rw-r--r-- | sound/pci/rme9652/rme9652.c | 7 |
14 files changed, 803 insertions, 351 deletions
diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c index def8161cde4c..785ec0cf3933 100644 --- a/sound/pci/emu10k1/emu10k1x.c +++ b/sound/pci/emu10k1/emu10k1x.c @@ -894,8 +894,8 @@ static int snd_emu10k1x_create(struct snd_card *card, if ((err = pci_enable_device(pci)) < 0) return err; - if (pci_set_dma_mask(pci, DMA_BIT_MASK(28)) < 0 || - pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(28)) < 0) { + + if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(28)) < 0) { dev_err(card->dev, "error to set 28bit mask DMA\n"); pci_disable_device(pci); return -ENXIO; diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 4bb58e8b08a8..687216e74526 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -1803,7 +1803,7 @@ int snd_hda_codec_reset(struct hda_codec *codec) return -EBUSY; /* OK, let it free */ - snd_hdac_device_unregister(&codec->core); + device_release_driver(hda_codec_dev(codec)); /* allow device access again */ snd_hda_unlock_devices(bus); diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index bbb17481159e..8060cc86dfea 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c @@ -1364,16 +1364,20 @@ static int try_assign_dacs(struct hda_codec *codec, int num_outs, struct nid_path *path; hda_nid_t pin = pins[i]; - path = snd_hda_get_path_from_idx(codec, path_idx[i]); - if (path) { - badness += assign_out_path_ctls(codec, path); - continue; + if (!spec->obey_preferred_dacs) { + path = snd_hda_get_path_from_idx(codec, path_idx[i]); + if (path) { + badness += assign_out_path_ctls(codec, path); + continue; + } } dacs[i] = get_preferred_dac(codec, pin); if (dacs[i]) { if (is_dac_already_used(codec, dacs[i])) badness += bad->shared_primary; + } else if (spec->obey_preferred_dacs) { + badness += BAD_NO_PRIMARY_DAC; } if (!dacs[i]) diff --git a/sound/pci/hda/hda_generic.h b/sound/pci/hda/hda_generic.h index a43f0bb77dae..0886bc81f40b 100644 --- a/sound/pci/hda/hda_generic.h +++ b/sound/pci/hda/hda_generic.h @@ -237,6 +237,7 @@ struct hda_gen_spec { unsigned int power_down_unused:1; /* power down unused widgets */ unsigned int dac_min_mute:1; /* minimal = mute for DACs */ unsigned int suppress_vmaster:1; /* don't create vmaster kctls */ + unsigned int obey_preferred_dacs:1; /* obey preferred_dacs assignment */ /* other internal flags */ unsigned int no_analog:1; /* digital I/O only */ diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index d539f52009a1..6852668f1bcb 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2506,6 +2506,9 @@ static const struct pci_device_id azx_ids[] = { /* DG1 */ { PCI_DEVICE(0x8086, 0x490d), .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, + /* Alderlake-S */ + { PCI_DEVICE(0x8086, 0x7ad0), + .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, /* Elkhart Lake */ { PCI_DEVICE(0x8086, 0x4b55), .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c index 0631f31ef87f..00c2eeb2c472 100644 --- a/sound/pci/hda/hda_proc.c +++ b/sound/pci/hda/hda_proc.c @@ -679,6 +679,38 @@ static void print_gpio(struct snd_info_buffer *buffer, print_nid_array(buffer, codec, nid, &codec->nids); } +static void print_dpmst_connections(struct snd_info_buffer *buffer, struct hda_codec *codec, + hda_nid_t nid, int dev_num) +{ + int c, conn_len, curr, dev_id_saved; + hda_nid_t *conn; + + conn_len = snd_hda_get_num_raw_conns(codec, nid); + if (conn_len <= 0) + return; + + conn = kmalloc_array(conn_len, sizeof(hda_nid_t), GFP_KERNEL); + if (!conn) + return; + + dev_id_saved = snd_hda_get_dev_select(codec, nid); + + snd_hda_set_dev_select(codec, nid, dev_num); + curr = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0); + if (snd_hda_get_raw_connections(codec, nid, conn, conn_len) < 0) + goto out; + + for (c = 0; c < conn_len; c++) { + snd_iprintf(buffer, " 0x%02x", conn[c]); + if (c == curr) + snd_iprintf(buffer, "*"); + } + +out: + kfree(conn); + snd_hda_set_dev_select(codec, nid, dev_id_saved); +} + static void print_device_list(struct snd_info_buffer *buffer, struct hda_codec *codec, hda_nid_t nid) { @@ -702,10 +734,14 @@ static void print_device_list(struct snd_info_buffer *buffer, snd_iprintf(buffer, " "); snd_iprintf(buffer, - "Dev %02d: PD = %d, ELDV = %d, IA = %d\n", i, + "Dev %02d: PD = %d, ELDV = %d, IA = %d, Connections [", i, !!(dev_list[i] & AC_DE_PD), !!(dev_list[i] & AC_DE_ELDV), !!(dev_list[i] & AC_DE_IA)); + + print_dpmst_connections(buffer, codec, nid, i); + + snd_iprintf(buffer, " ]\n"); } } diff --git a/sound/pci/hda/hda_sysfs.c b/sound/pci/hda/hda_sysfs.c index eb8ec109d7ad..d5ffcba794e5 100644 --- a/sound/pci/hda/hda_sysfs.c +++ b/sound/pci/hda/hda_sysfs.c @@ -139,7 +139,7 @@ static int reconfig_codec(struct hda_codec *codec) "The codec is being used, can't reconfigure.\n"); goto error; } - err = snd_hda_codec_configure(codec); + err = device_reprobe(hda_codec_dev(codec)); if (err < 0) goto error; err = snd_card_register(codec->card); diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index e0c38f2735c6..7e62aed172a9 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -95,7 +95,7 @@ enum { }; /* Strings for Input Source Enum Control */ -static const char *const in_src_str[3] = {"Rear Mic", "Line", "Front Mic" }; +static const char *const in_src_str[3] = { "Microphone", "Line In", "Front Microphone" }; #define IN_SRC_NUM_OF_INPUTS 3 enum { REAR_MIC, @@ -788,6 +788,40 @@ static const struct ae5_filter_set ae5_filter_presets[] = { } }; +/* + * Data structures for storing audio router remapping data. These are used to + * remap a currently active streams ports. + */ +struct chipio_stream_remap_data { + unsigned int stream_id; + unsigned int count; + + unsigned int offset[16]; + unsigned int value[16]; +}; + +static const struct chipio_stream_remap_data stream_remap_data[] = { + { .stream_id = 0x14, + .count = 0x04, + .offset = { 0x00, 0x04, 0x08, 0x0c }, + .value = { 0x0001f8c0, 0x0001f9c1, 0x0001fac6, 0x0001fbc7 }, + }, + { .stream_id = 0x0c, + .count = 0x0c, + .offset = { 0x00, 0x04, 0x08, 0x0c, 0x10, 0x14, 0x18, 0x1c, + 0x20, 0x24, 0x28, 0x2c }, + .value = { 0x0001e0c0, 0x0001e1c1, 0x0001e4c2, 0x0001e5c3, + 0x0001e2c4, 0x0001e3c5, 0x0001e8c6, 0x0001e9c7, + 0x0001ecc8, 0x0001edc9, 0x0001eaca, 0x0001ebcb }, + }, + { .stream_id = 0x0c, + .count = 0x08, + .offset = { 0x08, 0x0c, 0x10, 0x14, 0x20, 0x24, 0x28, 0x2c }, + .value = { 0x000140c2, 0x000141c3, 0x000150c4, 0x000151c5, + 0x000142c8, 0x000143c9, 0x000152ca, 0x000153cb }, + } +}; + enum hda_cmd_vendor_io { /* for DspIO node */ VENDOR_DSPIO_SCP_WRITE_DATA_LOW = 0x000, @@ -1223,7 +1257,7 @@ static const struct hda_pintbl ae5_pincfgs[] = { { 0x0e, 0x01c510f0 }, /* SPDIF In */ { 0x0f, 0x01017114 }, /* Port A -- Rear L/R. */ { 0x10, 0x01017012 }, /* Port D -- Center/LFE or FP Hp */ - { 0x11, 0x01a170ff }, /* Port B -- LineMicIn2 / Rear Headphone */ + { 0x11, 0x012170ff }, /* Port B -- LineMicIn2 / Rear Headphone */ { 0x12, 0x01a170f0 }, /* Port C -- LineIn1 */ { 0x13, 0x908700f0 }, /* What U Hear In*/ { 0x18, 0x50d000f0 }, /* N/A */ @@ -1829,6 +1863,18 @@ static void chipio_set_stream_control(struct hda_codec *codec, CONTROL_PARAM_STREAM_CONTROL, enable); } +/* + * Get ChipIO audio stream's status. + */ +static void chipio_get_stream_control(struct hda_codec *codec, + int streamid, unsigned int *enable) +{ + chipio_set_control_param_no_mutex(codec, + CONTROL_PARAM_STREAM_ID, streamid); + *enable = snd_hda_codec_read(codec, WIDGET_CHIP_CTRL, 0, + VENDOR_CHIPIO_PARAM_GET, + CONTROL_PARAM_STREAM_CONTROL); +} /* * Set sampling rate of the connection point. NO MUTEX. @@ -1868,25 +1914,110 @@ static void chipio_8051_write_direct(struct hda_codec *codec, } /* - * Enable clocks. + * Writes to the 8051's exram, which has 16-bits of address space. + * Data at addresses 0x2000-0x7fff is mirrored to 0x8000-0xdfff. + * Data at 0x8000-0xdfff can also be used as program memory for the 8051 by + * setting the pmem bank selection SFR. + * 0xe000-0xffff is always mapped as program memory, with only 0xf000-0xffff + * being writable. */ -static void chipio_enable_clocks(struct hda_codec *codec) +static void chipio_8051_set_address(struct hda_codec *codec, unsigned int addr) { - struct ca0132_spec *spec = codec->spec; + unsigned int tmp; - mutex_lock(&spec->chipio_mutex); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_ADDRESS_LOW, 0); + /* Lower 8-bits. */ + tmp = addr & 0xff; snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_PLL_PMU_WRITE, 0xff); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_ADDRESS_LOW, 5); + VENDOR_CHIPIO_8051_ADDRESS_LOW, tmp); + + /* Upper 8-bits. */ + tmp = (addr >> 8) & 0xff; snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_PLL_PMU_WRITE, 0x0b); + VENDOR_CHIPIO_8051_ADDRESS_HIGH, tmp); +} + +static void chipio_8051_set_data(struct hda_codec *codec, unsigned int data) +{ + /* 8-bits of data. */ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_ADDRESS_LOW, 6); + VENDOR_CHIPIO_8051_DATA_WRITE, data & 0xff); +} + +static unsigned int chipio_8051_get_data(struct hda_codec *codec) +{ + return snd_hda_codec_read(codec, WIDGET_CHIP_CTRL, 0, + VENDOR_CHIPIO_8051_DATA_READ, 0); +} + +/* PLL_PMU writes share the lower address register of the 8051 exram writes. */ +static void chipio_8051_set_data_pll(struct hda_codec *codec, unsigned int data) +{ + /* 8-bits of data. */ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_PLL_PMU_WRITE, 0xff); + VENDOR_CHIPIO_PLL_PMU_WRITE, data & 0xff); +} + +static void chipio_8051_write_exram(struct hda_codec *codec, + unsigned int addr, unsigned int data) +{ + struct ca0132_spec *spec = codec->spec; + + mutex_lock(&spec->chipio_mutex); + + chipio_8051_set_address(codec, addr); + chipio_8051_set_data(codec, data); + + mutex_unlock(&spec->chipio_mutex); +} + +static void chipio_8051_write_exram_no_mutex(struct hda_codec *codec, + unsigned int addr, unsigned int data) +{ + chipio_8051_set_address(codec, addr); + chipio_8051_set_data(codec, data); +} + +/* Readback data from the 8051's exram. No mutex. */ +static void chipio_8051_read_exram(struct hda_codec *codec, + unsigned int addr, unsigned int *data) +{ + chipio_8051_set_address(codec, addr); + *data = chipio_8051_get_data(codec); +} + +static void chipio_8051_write_pll_pmu(struct hda_codec *codec, + unsigned int addr, unsigned int data) +{ + struct ca0132_spec *spec = codec->spec; + + mutex_lock(&spec->chipio_mutex); + + chipio_8051_set_address(codec, addr & 0xff); + chipio_8051_set_data_pll(codec, data); + + mutex_unlock(&spec->chipio_mutex); +} + +static void chipio_8051_write_pll_pmu_no_mutex(struct hda_codec *codec, + unsigned int addr, unsigned int data) +{ + chipio_8051_set_address(codec, addr & 0xff); + chipio_8051_set_data_pll(codec, data); +} + +/* + * Enable clocks. + */ +static void chipio_enable_clocks(struct hda_codec *codec) +{ + struct ca0132_spec *spec = codec->spec; + + mutex_lock(&spec->chipio_mutex); + + chipio_8051_write_pll_pmu_no_mutex(codec, 0x00, 0xff); + chipio_8051_write_pll_pmu_no_mutex(codec, 0x05, 0x0b); + chipio_8051_write_pll_pmu_no_mutex(codec, 0x06, 0xff); + mutex_unlock(&spec->chipio_mutex); } @@ -2316,13 +2447,6 @@ static int dspio_set_uint_param(struct hda_codec *codec, int mod_id, sizeof(unsigned int)); } -static int dspio_set_uint_param_no_source(struct hda_codec *codec, int mod_id, - int req, const unsigned int data) -{ - return dspio_set_param(codec, mod_id, 0x00, req, &data, - sizeof(unsigned int)); -} - /* * Allocate a DSP DMA channel via an SCP message */ @@ -7388,18 +7512,10 @@ static void ca0132_init_analog_mic2(struct hda_codec *codec) struct ca0132_spec *spec = codec->spec; mutex_lock(&spec->chipio_mutex); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x20); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_ADDRESS_HIGH, 0x19); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_DATA_WRITE, 0x00); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x2D); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_ADDRESS_HIGH, 0x19); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_DATA_WRITE, 0x00); + + chipio_8051_write_exram_no_mutex(codec, 0x1920, 0x00); + chipio_8051_write_exram_no_mutex(codec, 0x192d, 0x00); + mutex_unlock(&spec->chipio_mutex); } @@ -7423,6 +7539,199 @@ static void ca0132_refresh_widget_caps(struct hda_codec *codec) } } + +/* If there is an active channel for some reason, find it and free it. */ +static void ca0132_alt_free_active_dma_channels(struct hda_codec *codec) +{ + unsigned int i, tmp; + int status; + + /* Read active DSPDMAC channel register. */ + status = chipio_read(codec, DSPDMAC_CHNLSTART_MODULE_OFFSET, &tmp); + if (status >= 0) { + /* AND against 0xfff to get the active channel bits. */ + tmp = tmp & 0xfff; + + /* If there are no active channels, nothing to free. */ + if (!tmp) + return; + } else { + codec_dbg(codec, "%s: Failed to read active DSP DMA channel register.\n", + __func__); + return; + } + + /* + * Check each DSP DMA channel for activity, and if the channel is + * active, free it. + */ + for (i = 0; i < DSPDMAC_DMA_CFG_CHANNEL_COUNT; i++) { + if (dsp_is_dma_active(codec, i)) { + status = dspio_free_dma_chan(codec, i); + if (status < 0) + codec_dbg(codec, "%s: Failed to free active DSP DMA channel %d.\n", + __func__, i); + } + } +} + +/* + * In the case of CT_EXTENSIONS_ENABLE being set to 1, and the DSP being in + * use, audio is no longer routed directly to the DAC/ADC from the HDA stream. + * Instead, audio is now routed through the DSP's DMA controllers, which + * the DSP is tasked with setting up itself. Through debugging, it seems the + * cause of most of the no-audio on startup issues were due to improperly + * configured DSP DMA channels. + * + * Normally, the DSP configures these the first time an HDA audio stream is + * started post DSP firmware download. That is why creating a 'dummy' stream + * worked in fixing the audio in some cases. This works most of the time, but + * sometimes if a stream is started/stopped before the DSP can setup the DMA + * configuration registers, it ends up in a broken state. Issues can also + * arise if streams are started in an unusual order, i.e the audio output dma + * channel being sandwiched between the mic1 and mic2 dma channels. + * + * The solution to this is to make sure that the DSP has no DMA channels + * in use post DSP firmware download, and then to manually start each default + * DSP stream that uses the DMA channels. These are 0x0c, the audio output + * stream, 0x03, analog mic 1, and 0x04, analog mic 2. + */ +static void ca0132_alt_start_dsp_audio_streams(struct hda_codec *codec) +{ + const unsigned int dsp_dma_stream_ids[] = { 0x0c, 0x03, 0x04 }; + struct ca0132_spec *spec = codec->spec; + unsigned int i, tmp; + + /* + * Check if any of the default streams are active, and if they are, + * stop them. + */ + mutex_lock(&spec->chipio_mutex); + + for (i = 0; i < ARRAY_SIZE(dsp_dma_stream_ids); i++) { + chipio_get_stream_control(codec, dsp_dma_stream_ids[i], &tmp); + + if (tmp) { + chipio_set_stream_control(codec, + dsp_dma_stream_ids[i], 0); + } + } + + mutex_unlock(&spec->chipio_mutex); + + /* + * If all DSP streams are inactive, there should be no active DSP DMA + * channels. Check and make sure this is the case, and if it isn't, + * free any active channels. + */ + ca0132_alt_free_active_dma_channels(codec); + + mutex_lock(&spec->chipio_mutex); + + /* Make sure stream 0x0c is six channels. */ + chipio_set_stream_channels(codec, 0x0c, 6); + + for (i = 0; i < ARRAY_SIZE(dsp_dma_stream_ids); i++) { + chipio_set_stream_control(codec, + dsp_dma_stream_ids[i], 1); + + /* Give the DSP some time to setup the DMA channel. */ + msleep(75); + } + + mutex_unlock(&spec->chipio_mutex); +} + +/* + * The region of ChipIO memory from 0x190000-0x1903fc is a sort of 'audio + * router', where each entry represents a 48khz audio channel, with a format + * of an 8-bit destination, an 8-bit source, and an unknown 2-bit number + * value. The 2-bit number value is seemingly 0 if inactive, 1 if active, + * and 3 if it's using Sample Rate Converter ports. + * An example is: + * 0x0001f8c0 + * In this case, f8 is the destination, and c0 is the source. The number value + * is 1. + * This region of memory is normally managed internally by the 8051, where + * the region of exram memory from 0x1477-0x1575 has each byte represent an + * entry within the 0x190000 range, and when a range of entries is in use, the + * ending value is overwritten with 0xff. + * 0x1578 in exram is a table of 0x25 entries, corresponding to the ChipIO + * streamID's, where each entry is a starting 0x190000 port offset. + * 0x159d in exram is the same as 0x1578, except it contains the ending port + * offset for the corresponding streamID. + * + * On certain cards, such as the SBZ/ZxR/AE7, these are originally setup by + * the 8051, then manually overwritten to remap the ports to work with the + * new DACs. + * + * Currently known portID's: + * 0x00-0x1f: HDA audio stream input/output ports. + * 0x80-0xbf: Sample rate converter input/outputs. Only valid ports seem to + * have the lower-nibble set to 0x1, 0x2, and 0x9. + * 0xc0-0xdf: DSP DMA input/output ports. Dynamically assigned. + * 0xe0-0xff: DAC/ADC audio input/output ports. + * + * Currently known streamID's: + * 0x03: Mic1 ADC to DSP. + * 0x04: Mic2 ADC to DSP. + * 0x05: HDA node 0x02 audio stream to DSP. + * 0x0f: DSP Mic exit to HDA node 0x07. + * 0x0c: DSP processed audio to DACs. + * 0x14: DAC0, front L/R. + * + * It is possible to route the HDA audio streams directly to the DAC and + * bypass the DSP entirely, with the only downside being that since the DSP + * does volume control, the only volume control you'll get is through PCM on + * the PC side, in the same way volume is handled for optical out. This may be + * useful for debugging. + */ +static void chipio_remap_stream(struct hda_codec *codec, + const struct chipio_stream_remap_data *remap_data) +{ + unsigned int i, stream_offset; + + /* Get the starting port for the stream to be remapped. */ + chipio_8051_read_exram(codec, 0x1578 + remap_data->stream_id, + &stream_offset); + + /* + * Check if the stream's port value is 0xff, because the 8051 may not + * have gotten around to setting up the stream yet. Wait until it's + * setup to remap it's ports. + */ + if (stream_offset == 0xff) { + for (i = 0; i < 5; i++) { + msleep(25); + + chipio_8051_read_exram(codec, 0x1578 + remap_data->stream_id, + &stream_offset); + + if (stream_offset != 0xff) + break; + } + } + + if (stream_offset == 0xff) { + codec_info(codec, "%s: Stream 0x%02x ports aren't allocated, remap failed!\n", + __func__, remap_data->stream_id); + return; + } + + /* Offset isn't in bytes, its in 32-bit words, so multiply it by 4. */ + stream_offset *= 0x04; + stream_offset += 0x190000; + + for (i = 0; i < remap_data->count; i++) { + chipio_write_no_mutex(codec, + stream_offset + remap_data->offset[i], + remap_data->value[i]); + } + + /* Update stream map configuration. */ + chipio_write_no_mutex(codec, 0x19042c, 0x00000001); +} + /* * Default speaker tuning values setup for alternative codecs. */ @@ -7486,24 +7795,6 @@ static void ca0132_alt_init_speaker_tuning(struct hda_codec *codec) } /* - * Creates a dummy stream to bind the output to. This seems to have to be done - * after changing the main outputs source and destination streams. - */ -static void ca0132_alt_create_dummy_stream(struct hda_codec *codec) -{ - struct ca0132_spec *spec = codec->spec; - unsigned int stream_format; - - stream_format = snd_hdac_calc_stream_format(48000, 2, - SNDRV_PCM_FORMAT_S32_LE, 32, 0); - - snd_hda_codec_setup_stream(codec, spec->dacs[0], spec->dsp_stream_id, - 0, stream_format); - - snd_hda_codec_cleanup_stream(codec, spec->dacs[0]); -} - -/* * Initialize mic for non-chromebook ca0132 implementations. */ static void ca0132_alt_init_analog_mics(struct hda_codec *codec) @@ -7544,9 +7835,6 @@ static void sbz_connect_streams(struct hda_codec *codec) codec_dbg(codec, "Connect Streams entered, mutex locked and loaded.\n"); - chipio_set_stream_channels(codec, 0x0C, 6); - chipio_set_stream_control(codec, 0x0C, 1); - /* This value is 0x43 for 96khz, and 0x83 for 192khz. */ chipio_write_no_mutex(codec, 0x18a020, 0x00000043); @@ -7570,102 +7858,37 @@ static void sbz_connect_streams(struct hda_codec *codec) */ static void sbz_chipio_startup_data(struct hda_codec *codec) { + const struct chipio_stream_remap_data *dsp_out_remap_data; struct ca0132_spec *spec = codec->spec; mutex_lock(&spec->chipio_mutex); codec_dbg(codec, "Startup Data entered, mutex locked and loaded.\n"); - /* These control audio output */ - chipio_write_no_mutex(codec, 0x190060, 0x0001f8c0); - chipio_write_no_mutex(codec, 0x190064, 0x0001f9c1); - chipio_write_no_mutex(codec, 0x190068, 0x0001fac6); - chipio_write_no_mutex(codec, 0x19006c, 0x0001fbc7); - /* Signal to update I think */ - chipio_write_no_mutex(codec, 0x19042c, 0x00000001); + /* Remap DAC0's output ports. */ + chipio_remap_stream(codec, &stream_remap_data[0]); - chipio_set_stream_channels(codec, 0x0C, 6); - chipio_set_stream_control(codec, 0x0C, 1); - /* No clue what these control */ - if (ca0132_quirk(spec) == QUIRK_SBZ) { - chipio_write_no_mutex(codec, 0x190030, 0x0001e0c0); - chipio_write_no_mutex(codec, 0x190034, 0x0001e1c1); - chipio_write_no_mutex(codec, 0x190038, 0x0001e4c2); - chipio_write_no_mutex(codec, 0x19003c, 0x0001e5c3); - chipio_write_no_mutex(codec, 0x190040, 0x0001e2c4); - chipio_write_no_mutex(codec, 0x190044, 0x0001e3c5); - chipio_write_no_mutex(codec, 0x190048, 0x0001e8c6); - chipio_write_no_mutex(codec, 0x19004c, 0x0001e9c7); - chipio_write_no_mutex(codec, 0x190050, 0x0001ecc8); - chipio_write_no_mutex(codec, 0x190054, 0x0001edc9); - chipio_write_no_mutex(codec, 0x190058, 0x0001eaca); - chipio_write_no_mutex(codec, 0x19005c, 0x0001ebcb); - } else if (ca0132_quirk(spec) == QUIRK_ZXR) { - chipio_write_no_mutex(codec, 0x190038, 0x000140c2); - chipio_write_no_mutex(codec, 0x19003c, 0x000141c3); - chipio_write_no_mutex(codec, 0x190040, 0x000150c4); - chipio_write_no_mutex(codec, 0x190044, 0x000151c5); - chipio_write_no_mutex(codec, 0x190050, 0x000142c8); - chipio_write_no_mutex(codec, 0x190054, 0x000143c9); - chipio_write_no_mutex(codec, 0x190058, 0x000152ca); - chipio_write_no_mutex(codec, 0x19005c, 0x000153cb); + /* Remap DSP audio output stream ports. */ + switch (ca0132_quirk(spec)) { + case QUIRK_SBZ: + dsp_out_remap_data = &stream_remap_data[1]; + break; + + case QUIRK_ZXR: + dsp_out_remap_data = &stream_remap_data[2]; + break; + + default: + dsp_out_remap_data = NULL; + break; } - chipio_write_no_mutex(codec, 0x19042c, 0x00000001); + + if (dsp_out_remap_data) + chipio_remap_stream(codec, dsp_out_remap_data); codec_dbg(codec, "Startup Data exited, mutex released.\n"); mutex_unlock(&spec->chipio_mutex); } -/* - * Custom DSP SCP commands where the src value is 0x00 instead of 0x20. This is - * done after the DSP is loaded. - */ -static void ca0132_alt_dsp_scp_startup(struct hda_codec *codec) -{ - struct ca0132_spec *spec = codec->spec; - unsigned int tmp, i; - - /* - * Gotta run these twice, or else mic works inconsistently. Not clear - * why this is, but multiple tests have confirmed it. - */ - for (i = 0; i < 2; i++) { - switch (ca0132_quirk(spec)) { - case QUIRK_SBZ: - case QUIRK_AE5: - case QUIRK_AE7: - tmp = 0x00000003; - dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp); - tmp = 0x00000000; - dspio_set_uint_param_no_source(codec, 0x80, 0x0A, tmp); - tmp = 0x00000001; - dspio_set_uint_param_no_source(codec, 0x80, 0x0B, tmp); - tmp = 0x00000004; - dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp); - tmp = 0x00000005; - dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp); - tmp = 0x00000000; - dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp); - break; - case QUIRK_R3D: - case QUIRK_R3DI: - tmp = 0x00000000; - dspio_set_uint_param_no_source(codec, 0x80, 0x0A, tmp); - tmp = 0x00000001; - dspio_set_uint_param_no_source(codec, 0x80, 0x0B, tmp); - tmp = 0x00000004; - dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp); - tmp = 0x00000005; - dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp); - tmp = 0x00000000; - dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp); - break; - default: - break; - } - msleep(100); - } -} - static void ca0132_alt_dsp_initial_mic_setup(struct hda_codec *codec) { struct ca0132_spec *spec = codec->spec; @@ -7702,10 +7925,7 @@ static void ae5_post_dsp_register_set(struct hda_codec *codec) struct ca0132_spec *spec = codec->spec; chipio_8051_write_direct(codec, 0x93, 0x10); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x44); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_PLL_PMU_WRITE, 0xc2); + chipio_8051_write_pll_pmu(codec, 0x44, 0xc2); writeb(0xff, spec->mem_base + 0x304); writeb(0xff, spec->mem_base + 0x304); @@ -7742,40 +7962,16 @@ static void ae5_post_dsp_param_setup(struct hda_codec *codec) snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, 0x724, 0x83); chipio_set_control_param(codec, CONTROL_PARAM_ASI, 0); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x92); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_ADDRESS_HIGH, 0xfa); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_DATA_WRITE, 0x22); + chipio_8051_write_exram(codec, 0xfa92, 0x22); } static void ae5_post_dsp_pll_setup(struct hda_codec *codec) { - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x41); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_PLL_PMU_WRITE, 0xc8); - - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x45); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_PLL_PMU_WRITE, 0xcc); - - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x40); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_PLL_PMU_WRITE, 0xcb); - - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x43); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_PLL_PMU_WRITE, 0xc7); - - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x51); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_PLL_PMU_WRITE, 0x8d); + chipio_8051_write_pll_pmu(codec, 0x41, 0xc8); + chipio_8051_write_pll_pmu(codec, 0x45, 0xcc); + chipio_8051_write_pll_pmu(codec, 0x40, 0xcb); + chipio_8051_write_pll_pmu(codec, 0x43, 0xc7); + chipio_8051_write_pll_pmu(codec, 0x51, 0x8d); } static void ae5_post_dsp_stream_setup(struct hda_codec *codec) @@ -7788,9 +7984,6 @@ static void ae5_post_dsp_stream_setup(struct hda_codec *codec) chipio_set_conn_rate_no_mutex(codec, 0x70, SR_96_000); - chipio_set_stream_channels(codec, 0x0C, 6); - chipio_set_stream_control(codec, 0x0C, 1); - chipio_set_stream_source_dest(codec, 0x5, 0x43, 0x0); chipio_set_stream_source_dest(codec, 0x18, 0x9, 0xd0); @@ -7800,10 +7993,7 @@ static void ae5_post_dsp_stream_setup(struct hda_codec *codec) chipio_set_control_param_no_mutex(codec, CONTROL_PARAM_ASI, 4); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x43); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_PLL_PMU_WRITE, 0xc7); + chipio_8051_write_pll_pmu_no_mutex(codec, 0x43, 0xc7); ca0113_mmio_command_set(codec, 0x48, 0x01, 0x80); @@ -7842,34 +8032,14 @@ static void ae5_post_dsp_startup_data(struct hda_codec *codec) mutex_unlock(&spec->chipio_mutex); } -static const unsigned int ae7_port_set_data[] = { - 0x0001e0c0, 0x0001e1c1, 0x0001e4c2, 0x0001e5c3, 0x0001e2c4, 0x0001e3c5, - 0x0001e8c6, 0x0001e9c7, 0x0001ecc8, 0x0001edc9, 0x0001eaca, 0x0001ebcb -}; - static void ae7_post_dsp_setup_ports(struct hda_codec *codec) { struct ca0132_spec *spec = codec->spec; - unsigned int i, count, addr; mutex_lock(&spec->chipio_mutex); - chipio_set_stream_channels(codec, 0x0c, 6); - chipio_set_stream_control(codec, 0x0c, 1); - - count = ARRAY_SIZE(ae7_port_set_data); - addr = 0x190030; - for (i = 0; i < count; i++) { - chipio_write_no_mutex(codec, addr, ae7_port_set_data[i]); - - /* Addresses are incremented by 4-bytes. */ - addr += 0x04; - } - - /* - * Port setting always ends with a write of 0x1 to address 0x19042c. - */ - chipio_write_no_mutex(codec, 0x19042c, 0x00000001); + /* Seems to share the same port remapping as the SBZ. */ + chipio_remap_stream(codec, &stream_remap_data[1]); ca0113_mmio_command_set(codec, 0x30, 0x30, 0x00); ca0113_mmio_command_set(codec, 0x48, 0x0d, 0x40); @@ -7893,8 +8063,6 @@ static void ae7_post_dsp_asi_stream_setup(struct hda_codec *codec) ca0113_mmio_command_set(codec, 0x30, 0x2b, 0x00); chipio_set_conn_rate_no_mutex(codec, 0x70, SR_96_000); - chipio_set_stream_channels(codec, 0x0c, 6); - chipio_set_stream_control(codec, 0x0c, 1); chipio_set_stream_source_dest(codec, 0x05, 0x43, 0x00); chipio_set_stream_source_dest(codec, 0x18, 0x09, 0xd0); @@ -7918,12 +8086,8 @@ static void ae7_post_dsp_pll_setup(struct hda_codec *codec) }; unsigned int i; - for (i = 0; i < ARRAY_SIZE(addr); i++) { - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_ADDRESS_LOW, addr[i]); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_PLL_PMU_WRITE, data[i]); - } + for (i = 0; i < ARRAY_SIZE(addr); i++) + chipio_8051_write_pll_pmu_no_mutex(codec, addr[i], data[i]); } static void ae7_post_dsp_asi_setup_ports(struct hda_codec *codec) @@ -7939,10 +8103,7 @@ static void ae7_post_dsp_asi_setup_ports(struct hda_codec *codec) mutex_lock(&spec->chipio_mutex); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x43); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_PLL_PMU_WRITE, 0xc7); + chipio_8051_write_pll_pmu_no_mutex(codec, 0x43, 0xc7); chipio_write_no_mutex(codec, 0x189000, 0x0001f101); chipio_write_no_mutex(codec, 0x189004, 0x0001f101); @@ -8015,10 +8176,7 @@ static void ae7_post_dsp_asi_setup(struct hda_codec *codec) { chipio_8051_write_direct(codec, 0x93, 0x10); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x44); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_PLL_PMU_WRITE, 0xc2); + chipio_8051_write_pll_pmu(codec, 0x44, 0xc2); ca0113_mmio_command_set_type2(codec, 0x48, 0x07, 0x83); ca0113_mmio_command_set(codec, 0x30, 0x2e, 0x3f); @@ -8030,20 +8188,12 @@ static void ae7_post_dsp_asi_setup(struct hda_codec *codec) chipio_set_control_param(codec, CONTROL_PARAM_ASI, 0); snd_hda_codec_write(codec, 0x17, 0, 0x794, 0x00); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x92); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_ADDRESS_HIGH, 0xfa); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_DATA_WRITE, 0x22); + chipio_8051_write_exram(codec, 0xfa92, 0x22); ae7_post_dsp_pll_setup(codec); ae7_post_dsp_asi_stream_setup(codec); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x43); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_PLL_PMU_WRITE, 0xc7); + chipio_8051_write_pll_pmu(codec, 0x43, 0xc7); ae7_post_dsp_asi_setup_ports(codec); } @@ -8106,8 +8256,8 @@ static void r3d_setup_defaults(struct hda_codec *codec) if (spec->dsp_state != DSP_DOWNLOADED) return; - ca0132_alt_dsp_scp_startup(codec); ca0132_alt_init_analog_mics(codec); + ca0132_alt_start_dsp_audio_streams(codec); /*remove DSP headroom*/ tmp = FLOAT_ZERO; @@ -8156,14 +8306,11 @@ static void sbz_setup_defaults(struct hda_codec *codec) if (spec->dsp_state != DSP_DOWNLOADED) return; - ca0132_alt_dsp_scp_startup(codec); ca0132_alt_init_analog_mics(codec); + ca0132_alt_start_dsp_audio_streams(codec); sbz_connect_streams(codec); sbz_chipio_startup_data(codec); - chipio_set_stream_control(codec, 0x03, 1); - chipio_set_stream_control(codec, 0x04, 1); - /* * Sets internal input loopback to off, used to have a switch to * enable input loopback, but turned out to be way too buggy. @@ -8198,8 +8345,6 @@ static void sbz_setup_defaults(struct hda_codec *codec) } ca0132_alt_init_speaker_tuning(codec); - - ca0132_alt_create_dummy_stream(codec); } /* @@ -8215,10 +8360,8 @@ static void ae5_setup_defaults(struct hda_codec *codec) if (spec->dsp_state != DSP_DOWNLOADED) return; - ca0132_alt_dsp_scp_startup(codec); ca0132_alt_init_analog_mics(codec); - chipio_set_stream_control(codec, 0x03, 1); - chipio_set_stream_control(codec, 0x04, 1); + ca0132_alt_start_dsp_audio_streams(codec); /* New, unknown SCP req's */ tmp = FLOAT_ZERO; @@ -8267,8 +8410,6 @@ static void ae5_setup_defaults(struct hda_codec *codec) } ca0132_alt_init_speaker_tuning(codec); - - ca0132_alt_create_dummy_stream(codec); } /* @@ -8284,8 +8425,8 @@ static void ae7_setup_defaults(struct hda_codec *codec) if (spec->dsp_state != DSP_DOWNLOADED) return; - ca0132_alt_dsp_scp_startup(codec); ca0132_alt_init_analog_mics(codec); + ca0132_alt_start_dsp_audio_streams(codec); ae7_post_dsp_setup_ports(codec); tmp = FLOAT_ZERO; @@ -8352,8 +8493,6 @@ static void ae7_setup_defaults(struct hda_codec *codec) } ca0132_alt_init_speaker_tuning(codec); - - ca0132_alt_create_dummy_stream(codec); } /* @@ -8544,7 +8683,7 @@ static void amic_callback(struct hda_codec *codec, struct hda_jack_callback *cb) ca0132_select_mic(codec); } -static void ca0132_init_unsol(struct hda_codec *codec) +static void ca0132_setup_unsol(struct hda_codec *codec) { struct ca0132_spec *spec = codec->spec; snd_hda_jack_detect_enable_callback(codec, spec->unsol_tag_hp, hp_callback); @@ -8642,6 +8781,22 @@ static void ca0132_init_chip(struct hda_codec *codec) mutex_init(&spec->chipio_mutex); + /* + * The Windows driver always does this upon startup, which seems to + * clear out any previous configuration. This should help issues where + * a boot into Windows prior to a boot into Linux breaks things. Also, + * Windows always sends the reset twice. + */ + if (ca0132_use_alt_functions(spec)) { + chipio_set_control_flag(codec, CONTROL_FLAG_IDLE_ENABLE, 0); + chipio_write_no_mutex(codec, 0x18b0a4, 0x000000c2); + + snd_hda_codec_write(codec, codec->core.afg, 0, + AC_VERB_SET_CODEC_RESET, 0); + snd_hda_codec_write(codec, codec->core.afg, 0, + AC_VERB_SET_CODEC_RESET, 0); + } + spec->cur_out_type = SPEAKER_OUT; if (!ca0132_use_alt_functions(spec)) spec->cur_mic_type = DIGITAL_MIC; @@ -9013,12 +9168,7 @@ static void r3d_pre_dsp_setup(struct hda_codec *codec) { 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); + chipio_8051_write_exram(codec, 0x1c1e, 0x5b); snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x44); @@ -9028,27 +9178,53 @@ static void r3di_pre_dsp_setup(struct hda_codec *codec) { 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, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x20); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_ADDRESS_HIGH, 0x19); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_DATA_WRITE, 0x00); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_DATA_WRITE, 0x40); + chipio_8051_write_exram(codec, 0x1c1e, 0x5b); + chipio_8051_write_exram(codec, 0x1920, 0x00); + chipio_8051_write_exram(codec, 0x1921, 0x40); snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x04); } /* + * The ZxR seems to use alternative DAC's for the surround channels, which + * require PLL PMU setup for the clock rate, I'm guessing. Without setting + * this up, we get no audio out of the surround jacks. + */ +static void zxr_pre_dsp_setup(struct hda_codec *codec) +{ + static const unsigned int addr[] = { 0x43, 0x40, 0x41, 0x42, 0x45 }; + static const unsigned int data[] = { 0x08, 0x0c, 0x0b, 0x07, 0x0d }; + unsigned int i; + + chipio_write(codec, 0x189000, 0x0001f100); + msleep(50); + chipio_write(codec, 0x18900c, 0x0001f100); + msleep(50); + + /* + * This writes a RET instruction at the entry point of the function at + * 0xfa92 in exram. This function seems to have something to do with + * ASI. Might be some way to prevent the card from reconfiguring the + * ASI stuff itself. + */ + chipio_8051_write_exram(codec, 0xfa92, 0x22); + + chipio_8051_write_pll_pmu(codec, 0x51, 0x98); + + snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, 0x725, 0x82); + chipio_set_control_param(codec, CONTROL_PARAM_ASI, 3); + + chipio_write(codec, 0x18902c, 0x00000000); + msleep(50); + chipio_write(codec, 0x18902c, 0x00000003); + msleep(50); + + for (i = 0; i < ARRAY_SIZE(addr); i++) + chipio_8051_write_pll_pmu(codec, addr[i], data[i]); +} + +/* * 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. @@ -9183,6 +9359,8 @@ static void ca0132_mmio_init(struct hda_codec *codec) case QUIRK_AE5: ca0132_mmio_init_ae5(codec); break; + default: + break; } } @@ -9210,18 +9388,11 @@ static void ae5_register_set(struct hda_codec *codec) unsigned int i, cur_addr; unsigned char tmp[3]; - if (ca0132_quirk(spec) == QUIRK_AE7) { - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x41); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_PLL_PMU_WRITE, 0xc8); - } + if (ca0132_quirk(spec) == QUIRK_AE7) + chipio_8051_write_pll_pmu(codec, 0x41, 0xc8); chipio_8051_write_direct(codec, 0x93, 0x10); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x44); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_PLL_PMU_WRITE, 0xc2); + chipio_8051_write_pll_pmu(codec, 0x44, 0xc2); if (ca0132_quirk(spec) == QUIRK_AE7) { tmp[0] = 0x03; @@ -9260,11 +9431,6 @@ static void ae5_register_set(struct hda_codec *codec) if (ca0132_quirk(spec) == QUIRK_AE5) ca0113_mmio_command_set(codec, 0x48, 0x07, 0x83); - - chipio_write(codec, 0x18b0a4, 0x000000c2); - - snd_hda_codec_write(codec, 0x01, 0, 0x7ff, 0x00); - snd_hda_codec_write(codec, 0x01, 0, 0x7ff, 0x00); } /* @@ -9302,10 +9468,7 @@ static void ca0132_alt_init(struct hda_codec *codec) break; case QUIRK_AE5: ca0132_gpio_init(codec); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x49); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_PLL_PMU_WRITE, 0x88); + chipio_8051_write_pll_pmu(codec, 0x49, 0x88); chipio_write(codec, 0x18b030, 0x00000020); snd_hda_sequence_write(codec, spec->chip_init_verbs); snd_hda_sequence_write(codec, spec->desktop_init_verbs); @@ -9313,10 +9476,7 @@ static void ca0132_alt_init(struct hda_codec *codec) break; case QUIRK_AE7: ca0132_gpio_init(codec); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x49); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_PLL_PMU_WRITE, 0x88); + chipio_8051_write_pll_pmu(codec, 0x49, 0x88); snd_hda_sequence_write(codec, spec->chip_init_verbs); snd_hda_sequence_write(codec, spec->desktop_init_verbs); chipio_write(codec, 0x18b008, 0x000000f8); @@ -9325,8 +9485,10 @@ static void ca0132_alt_init(struct hda_codec *codec) ca0113_mmio_command_set(codec, 0x30, 0x32, 0x3f); break; case QUIRK_ZXR: + chipio_8051_write_pll_pmu(codec, 0x49, 0x88); snd_hda_sequence_write(codec, spec->chip_init_verbs); snd_hda_sequence_write(codec, spec->desktop_init_verbs); + zxr_pre_dsp_setup(codec); break; default: break; @@ -9374,7 +9536,6 @@ static int ca0132_init(struct hda_codec *codec) if (ca0132_quirk(spec) == QUIRK_AE5 || ca0132_quirk(spec) == QUIRK_AE7) ae5_register_set(codec); - ca0132_init_unsol(codec); ca0132_init_params(codec); ca0132_init_flags(codec); @@ -9939,6 +10100,8 @@ static int patch_ca0132(struct hda_codec *codec) if (err < 0) goto error; + ca0132_setup_unsol(codec); + return 0; error: diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index ccd1df059654..1e4a4b83fbf6 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -78,6 +78,7 @@ struct hdmi_spec_per_pin { int pcm_idx; /* which pcm is attached. -1 means no pcm is attached */ int repoll_count; bool setup; /* the stream has been set up by prepare callback */ + bool silent_stream; int channels; /* current number of channels */ bool non_pcm; bool chmap_set; /* channel-map override by ALSA API? */ @@ -252,7 +253,7 @@ static int pin_id_to_pin_index(struct hda_codec *codec, return pin_idx; } - codec_warn(codec, "HDMI: pin nid %d not registered\n", pin_nid); + codec_warn(codec, "HDMI: pin NID 0x%x not registered\n", pin_nid); return -EINVAL; } @@ -312,7 +313,7 @@ static int cvt_nid_to_cvt_index(struct hda_codec *codec, hda_nid_t cvt_nid) if (get_cvt(spec, cvt_idx)->cvt_nid == cvt_nid) return cvt_idx; - codec_warn(codec, "HDMI: cvt nid %d not registered\n", cvt_nid); + codec_warn(codec, "HDMI: cvt NID 0x%x not registered\n", cvt_nid); return -EINVAL; } @@ -637,11 +638,11 @@ static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid, u8 val; int i; + hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); if (snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_HDMI_DIP_XMIT, 0) != AC_DIPXMIT_BEST) return false; - hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); for (i = 0; i < size; i++) { val = snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_HDMI_DIP_DATA, 0); @@ -686,8 +687,7 @@ static void hdmi_pin_setup_infoframe(struct hda_codec *codec, dp_ai->CC02_CT47 = active_channels - 1; dp_ai->CA = ca; } else { - codec_dbg(codec, "HDMI: unknown connection type at pin %d\n", - pin_nid); + codec_dbg(codec, "HDMI: unknown connection type at pin NID 0x%x\n", pin_nid); return; } @@ -700,10 +700,8 @@ static void hdmi_pin_setup_infoframe(struct hda_codec *codec, */ if (!hdmi_infoframe_uptodate(codec, pin_nid, ai.bytes, sizeof(ai))) { - codec_dbg(codec, - "hdmi_pin_setup_infoframe: pin=%d channels=%d ca=0x%02x\n", - pin_nid, - active_channels, ca); + codec_dbg(codec, "%s: pin NID=0x%x channels=%d ca=0x%02x\n", + __func__, pin_nid, active_channels, ca); hdmi_stop_infoframe_trans(codec, pin_nid); hdmi_fill_audio_infoframe(codec, pin_nid, ai.bytes, sizeof(ai)); @@ -795,7 +793,7 @@ static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res, jack->jack_dirty = 1; codec_dbg(codec, - "HDMI hot plug event: Codec=%d Pin=%d Device=%d Inactive=%d Presence_Detect=%d ELD_Valid=%d\n", + "HDMI hot plug event: Codec=%d NID=0x%x Device=%d Inactive=%d Presence_Detect=%d ELD_Valid=%d\n", codec->addr, jack->nid, jack->dev_id, !!(res & AC_UNSOL_RES_IA), !!(res & AC_UNSOL_RES_PD), !!(res & AC_UNSOL_RES_ELDV)); @@ -873,7 +871,7 @@ static void haswell_verify_D0(struct hda_codec *codec, msleep(40); pwr = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_POWER_STATE, 0); pwr = (pwr & AC_PWRST_ACTUAL) >> AC_PWRST_ACTUAL_SHIFT; - codec_dbg(codec, "Haswell HDMI audio: Power for pin 0x%x is now D%d\n", nid, pwr); + codec_dbg(codec, "Haswell HDMI audio: Power for NID 0x%x is now D%d\n", nid, pwr); } } @@ -979,6 +977,13 @@ static int hdmi_choose_cvt(struct hda_codec *codec, else per_pin = get_pin(spec, pin_idx); + if (per_pin && per_pin->silent_stream) { + cvt_idx = cvt_nid_to_cvt_index(codec, per_pin->cvt_nid); + if (cvt_id) + *cvt_id = cvt_idx; + return 0; + } + /* Dynamically assign converter to stream */ for (cvt_idx = 0; cvt_idx < spec->num_cvts; cvt_idx++) { per_cvt = get_cvt(spec, cvt_idx); @@ -1113,8 +1118,8 @@ static void intel_not_share_assigned_cvt(struct hda_codec *codec, per_cvt = get_cvt(spec, cvt_idx); if (!per_cvt->assigned) { codec_dbg(codec, - "choose cvt %d for pin nid %d\n", - cvt_idx, nid); + "choose cvt %d for pin NID 0x%x\n", + cvt_idx, nid); snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, cvt_idx); @@ -1312,7 +1317,7 @@ static int hdmi_read_pin_conn(struct hda_codec *codec, int pin_idx) if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) { codec_warn(codec, - "HDMI: pin %d wcaps %#x does not support connection list\n", + "HDMI: pin NID 0x%x wcaps %#x does not support connection list\n", pin_nid, get_wcaps(codec, pin_nid)); return -EINVAL; } @@ -1627,7 +1632,7 @@ static void hdmi_present_sense_via_verbs(struct hdmi_spec_per_pin *per_pin, eld->eld_valid = false; codec_dbg(codec, - "HDMI status: Codec=%d Pin=%d Presence_Detect=%d ELD_Valid=%d\n", + "HDMI status: Codec=%d NID=0x%x Presence_Detect=%d ELD_Valid=%d\n", codec->addr, pin_nid, eld->monitor_present, eld->eld_valid); if (eld->eld_valid) { @@ -1642,30 +1647,95 @@ static void hdmi_present_sense_via_verbs(struct hdmi_spec_per_pin *per_pin, snd_hda_power_down_pm(codec); } +#define I915_SILENT_RATE 48000 +#define I915_SILENT_CHANNELS 2 +#define I915_SILENT_FORMAT SNDRV_PCM_FORMAT_S16_LE +#define I915_SILENT_FORMAT_BITS 16 +#define I915_SILENT_FMT_MASK 0xf + static void silent_stream_enable(struct hda_codec *codec, - struct hdmi_spec_per_pin *per_pin) + struct hdmi_spec_per_pin *per_pin) { - unsigned int newval, oldval; - - codec_dbg(codec, "hdmi: enabling silent stream for NID %d\n", - per_pin->pin_nid); + struct hdmi_spec *spec = codec->spec; + struct hdmi_spec_per_cvt *per_cvt; + int cvt_idx, pin_idx, err; + unsigned int format; mutex_lock(&per_pin->lock); - if (!per_pin->channels) - per_pin->channels = 2; + if (per_pin->setup) { + codec_dbg(codec, "hdmi: PCM already open, no silent stream\n"); + goto unlock_out; + } - oldval = snd_hda_codec_read(codec, per_pin->pin_nid, 0, - AC_VERB_GET_CONV, 0); - newval = (oldval & 0xF0) | 0xF; - snd_hda_codec_write(codec, per_pin->pin_nid, 0, - AC_VERB_SET_CHANNEL_STREAMID, newval); + pin_idx = pin_id_to_pin_index(codec, per_pin->pin_nid, per_pin->dev_id); + err = hdmi_choose_cvt(codec, pin_idx, &cvt_idx); + if (err) { + codec_err(codec, "hdmi: no free converter to enable silent mode\n"); + goto unlock_out; + } + per_cvt = get_cvt(spec, cvt_idx); + per_cvt->assigned = 1; + per_pin->cvt_nid = per_cvt->cvt_nid; + per_pin->silent_stream = true; + + codec_dbg(codec, "hdmi: enabling silent stream pin-NID=0x%x cvt-NID=0x%x\n", + per_pin->pin_nid, per_cvt->cvt_nid); + + snd_hda_set_dev_select(codec, per_pin->pin_nid, per_pin->dev_id); + snd_hda_codec_write_cache(codec, per_pin->pin_nid, 0, + AC_VERB_SET_CONNECT_SEL, + per_pin->mux_idx); + + /* configure unused pins to choose other converters */ + pin_cvt_fixup(codec, per_pin, 0); + + snd_hdac_sync_audio_rate(&codec->core, per_pin->pin_nid, + per_pin->dev_id, I915_SILENT_RATE); + + /* trigger silent stream generation in hw */ + format = snd_hdac_calc_stream_format(I915_SILENT_RATE, I915_SILENT_CHANNELS, + I915_SILENT_FORMAT, I915_SILENT_FORMAT_BITS, 0); + snd_hda_codec_setup_stream(codec, per_pin->cvt_nid, + I915_SILENT_FMT_MASK, I915_SILENT_FMT_MASK, format); + usleep_range(100, 200); + snd_hda_codec_setup_stream(codec, per_pin->cvt_nid, I915_SILENT_FMT_MASK, 0, format); + + per_pin->channels = I915_SILENT_CHANNELS; hdmi_setup_audio_infoframe(codec, per_pin, per_pin->non_pcm); + unlock_out: mutex_unlock(&per_pin->lock); } +static void silent_stream_disable(struct hda_codec *codec, + struct hdmi_spec_per_pin *per_pin) +{ + struct hdmi_spec *spec = codec->spec; + struct hdmi_spec_per_cvt *per_cvt; + int cvt_idx; + + mutex_lock(&per_pin->lock); + if (!per_pin->silent_stream) + goto unlock_out; + + codec_dbg(codec, "HDMI: disable silent stream on pin-NID=0x%x cvt-NID=0x%x\n", + per_pin->pin_nid, per_pin->cvt_nid); + + cvt_idx = cvt_nid_to_cvt_index(codec, per_pin->cvt_nid); + if (cvt_idx >= 0 && cvt_idx < spec->num_cvts) { + per_cvt = get_cvt(spec, cvt_idx); + per_cvt->assigned = 0; + } + + per_pin->cvt_nid = 0; + per_pin->silent_stream = false; + + unlock_out: + mutex_unlock(&spec->pcm_lock); +} + /* update ELD and jack state via audio component */ static void sync_eld_via_acomp(struct hda_codec *codec, struct hdmi_spec_per_pin *per_pin) @@ -1701,6 +1771,7 @@ static void sync_eld_via_acomp(struct hda_codec *codec, pm_ret); silent_stream_enable(codec, per_pin); } else if (monitor_prev && !monitor_next) { + silent_stream_disable(codec, per_pin); pm_ret = snd_hda_power_down_pm(codec); if (pm_ret < 0) codec_err(codec, @@ -2721,7 +2792,7 @@ static int intel_pin2port(void *audio_ptr, int pin_nid) return i; } - codec_info(codec, "Can't find the HDMI/DP port for pin %d\n", pin_nid); + codec_info(codec, "Can't find the HDMI/DP port for pin NID 0x%x\n", pin_nid); return -1; } @@ -4274,6 +4345,7 @@ HDA_CODEC_ENTRY(0x8086280d, "Geminilake HDMI", patch_i915_glk_hdmi), HDA_CODEC_ENTRY(0x8086280f, "Icelake HDMI", patch_i915_icl_hdmi), HDA_CODEC_ENTRY(0x80862812, "Tigerlake HDMI", patch_i915_tgl_hdmi), HDA_CODEC_ENTRY(0x80862814, "DG1 HDMI", patch_i915_tgl_hdmi), +HDA_CODEC_ENTRY(0x80862815, "Alderlake HDMI", patch_i915_tgl_hdmi), HDA_CODEC_ENTRY(0x80862816, "Rocketlake HDMI", patch_i915_tgl_hdmi), HDA_CODEC_ENTRY(0x8086281a, "Jasperlake HDMI", patch_i915_icl_hdmi), HDA_CODEC_ENTRY(0x8086281b, "Elkhartlake HDMI", patch_i915_icl_hdmi), diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 6899089d132e..dde5ba209541 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -119,6 +119,7 @@ struct alc_spec { unsigned int no_shutup_pins:1; unsigned int ultra_low_power:1; unsigned int has_hs_key:1; + unsigned int no_internal_mic_pin:1; /* for PLL fix */ hda_nid_t pll_nid; @@ -445,6 +446,7 @@ static void alc_fill_eapd_coef(struct hda_codec *codec) alc_update_coef_idx(codec, 0x7, 1<<5, 0); break; case 0x10ec0892: + case 0x10ec0897: alc_update_coef_idx(codec, 0x7, 1<<5, 0); break; case 0x10ec0899: @@ -2514,6 +2516,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = { SND_PCI_QUIRK(0x1458, 0xa0ce, "Gigabyte X570 Aorus Xtreme", ALC1220_FIXUP_CLEVO_P950), SND_PCI_QUIRK(0x1462, 0x11f7, "MSI-GE63", ALC1220_FIXUP_CLEVO_P950), SND_PCI_QUIRK(0x1462, 0x1228, "MSI-GP63", ALC1220_FIXUP_CLEVO_P950), + SND_PCI_QUIRK(0x1462, 0x1229, "MSI-GP73", ALC1220_FIXUP_CLEVO_P950), SND_PCI_QUIRK(0x1462, 0x1275, "MSI-GL63", ALC1220_FIXUP_CLEVO_P950), SND_PCI_QUIRK(0x1462, 0x1276, "MSI-GL73", ALC1220_FIXUP_CLEVO_P950), SND_PCI_QUIRK(0x1462, 0x1293, "MSI-GP65", ALC1220_FIXUP_CLEVO_P950), @@ -2522,13 +2525,23 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = { SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3), SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", ALC882_FIXUP_ABIT_AW9D_MAX), SND_PCI_QUIRK(0x1558, 0x9501, "Clevo P950HR", ALC1220_FIXUP_CLEVO_P950), + SND_PCI_QUIRK(0x1558, 0x9506, "Clevo P955HQ", ALC1220_FIXUP_CLEVO_P950), + SND_PCI_QUIRK(0x1558, 0x950A, "Clevo P955H[PR]", ALC1220_FIXUP_CLEVO_P950), SND_PCI_QUIRK(0x1558, 0x95e1, "Clevo P95xER", ALC1220_FIXUP_CLEVO_P950), SND_PCI_QUIRK(0x1558, 0x95e2, "Clevo P950ER", ALC1220_FIXUP_CLEVO_P950), + SND_PCI_QUIRK(0x1558, 0x95e3, "Clevo P955[ER]T", ALC1220_FIXUP_CLEVO_P950), + SND_PCI_QUIRK(0x1558, 0x95e4, "Clevo P955ER", ALC1220_FIXUP_CLEVO_P950), + SND_PCI_QUIRK(0x1558, 0x95e5, "Clevo P955EE6", ALC1220_FIXUP_CLEVO_P950), + SND_PCI_QUIRK(0x1558, 0x95e6, "Clevo P950R[CDF]", ALC1220_FIXUP_CLEVO_P950), SND_PCI_QUIRK(0x1558, 0x96e1, "Clevo P960[ER][CDFN]-K", ALC1220_FIXUP_CLEVO_P950), SND_PCI_QUIRK(0x1558, 0x97e1, "Clevo P970[ER][CDFN]", ALC1220_FIXUP_CLEVO_P950), + SND_PCI_QUIRK(0x1558, 0x97e2, "Clevo P970RC-M", ALC1220_FIXUP_CLEVO_P950), + SND_PCI_QUIRK(0x1558, 0x50d3, "Clevo PC50[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS), SND_PCI_QUIRK(0x1558, 0x65d1, "Clevo PB51[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS), + SND_PCI_QUIRK(0x1558, 0x65d2, "Clevo PB51R[CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS), + SND_PCI_QUIRK(0x1558, 0x65e1, "Clevo PB51[ED][DF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS), SND_PCI_QUIRK(0x1558, 0x67d1, "Clevo PB71[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS), - SND_PCI_QUIRK(0x1558, 0x50d3, "Clevo PC50[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS), + SND_PCI_QUIRK(0x1558, 0x67e1, "Clevo PB71[DE][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS), SND_PCI_QUIRK(0x1558, 0x70d1, "Clevo PC70[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS), SND_PCI_QUIRK(0x1558, 0x7714, "Clevo X170", ALC1220_FIXUP_CLEVO_PB51ED_PINS), SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC882_FIXUP_EAPD), @@ -3092,6 +3105,7 @@ static void alc_disable_headset_jack_key(struct hda_codec *codec) case 0x10ec0215: case 0x10ec0225: case 0x10ec0285: + case 0x10ec0287: case 0x10ec0295: case 0x10ec0289: case 0x10ec0299: @@ -3118,6 +3132,7 @@ static void alc_enable_headset_jack_key(struct hda_codec *codec) case 0x10ec0215: case 0x10ec0225: case 0x10ec0285: + case 0x10ec0287: case 0x10ec0295: case 0x10ec0289: case 0x10ec0299: @@ -4216,6 +4231,12 @@ static void alc286_fixup_hp_gpio_led(struct hda_codec *codec, alc_fixup_hp_gpio_led(codec, action, 0x02, 0x20); } +static void alc287_fixup_hp_gpio_led(struct hda_codec *codec, + const struct hda_fixup *fix, int action) +{ + alc_fixup_hp_gpio_led(codec, action, 0x10, 0); +} + /* turn on/off mic-mute LED per capture hook via VREF change */ static int vref_micmute_led_set(struct led_classdev *led_cdev, enum led_brightness brightness) @@ -4507,6 +4528,7 @@ static const struct coef_fw alc225_pre_hsmode[] = { static void alc_headset_mode_unplugged(struct hda_codec *codec) { + struct alc_spec *spec = codec->spec; static const struct coef_fw coef0255[] = { WRITE_COEF(0x1b, 0x0c0b), /* LDO and MISC control */ WRITE_COEF(0x45, 0xd089), /* UAJ function set to menual mode */ @@ -4581,6 +4603,11 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec) {} }; + if (spec->no_internal_mic_pin) { + alc_update_coef_idx(codec, 0x45, 0xf<<12 | 1<<10, 5<<12); + return; + } + switch (codec->core.vendor_id) { case 0x10ec0255: alc_process_coef_fw(codec, coef0255); @@ -5147,6 +5174,11 @@ static void alc_determine_headset_type(struct hda_codec *codec) {} }; + if (spec->no_internal_mic_pin) { + alc_update_coef_idx(codec, 0x45, 0xf<<12 | 1<<10, 5<<12); + return; + } + switch (codec->core.vendor_id) { case 0x10ec0255: alc_process_coef_fw(codec, coef0255); @@ -5998,6 +6030,21 @@ static void alc274_fixup_bind_dacs(struct hda_codec *codec, codec->power_save_node = 0; } +/* avoid DAC 0x06 for bass speaker 0x17; it has no volume control */ +static void alc289_fixup_asus_ga401(struct hda_codec *codec, + const struct hda_fixup *fix, int action) +{ + static const hda_nid_t preferred_pairs[] = { + 0x14, 0x02, 0x17, 0x02, 0x21, 0x03, 0 + }; + struct alc_spec *spec = codec->spec; + + if (action == HDA_FIXUP_ACT_PRE_PROBE) { + spec->gen.preferred_dacs = preferred_pairs; + spec->gen.obey_preferred_dacs = 1; + } +} + /* The DAC of NID 0x3 will introduce click/pop noise on headphones, so invalidate it */ static void alc285_fixup_invalidate_dacs(struct hda_codec *codec, const struct hda_fixup *fix, int action) @@ -6105,6 +6152,23 @@ static void alc274_fixup_hp_headset_mic(struct hda_codec *codec, } } +static void alc_fixup_no_int_mic(struct hda_codec *codec, + const struct hda_fixup *fix, int action) +{ + struct alc_spec *spec = codec->spec; + + switch (action) { + case HDA_FIXUP_ACT_PRE_PROBE: + /* Mic RING SLEEVE swap for combo jack */ + alc_update_coef_idx(codec, 0x45, 0xf<<12 | 1<<10, 5<<12); + spec->no_internal_mic_pin = true; + break; + case HDA_FIXUP_ACT_INIT: + alc_combo_jack_hp_jd_restart(codec); + break; + } +} + /* for hda_fixup_thinkpad_acpi() */ #include "thinkpad_helper.c" @@ -6301,6 +6365,11 @@ enum { ALC274_FIXUP_HP_MIC, ALC274_FIXUP_HP_HEADSET_MIC, ALC256_FIXUP_ASUS_HPE, + ALC285_FIXUP_THINKPAD_NO_BASS_SPK_HEADSET_JACK, + ALC287_FIXUP_HP_GPIO_LED, + ALC256_FIXUP_HP_HEADSET_MIC, + ALC236_FIXUP_DELL_AIO_HEADSET_MIC, + ALC282_FIXUP_ACER_DISABLE_LINEOUT, }; static const struct hda_fixup alc269_fixups[] = { @@ -7550,11 +7619,10 @@ static const struct hda_fixup alc269_fixups[] = { .chain_id = ALC269_FIXUP_HEADSET_MIC }, [ALC289_FIXUP_ASUS_GA401] = { - .type = HDA_FIXUP_PINS, - .v.pins = (const struct hda_pintbl[]) { - { 0x19, 0x03a11020 }, /* headset mic with jack detect */ - { } - }, + .type = HDA_FIXUP_FUNC, + .v.func = alc289_fixup_asus_ga401, + .chained = true, + .chain_id = ALC289_FIXUP_ASUS_GA502, }, [ALC289_FIXUP_ASUS_GA502] = { .type = HDA_FIXUP_PINS, @@ -7678,7 +7746,7 @@ static const struct hda_fixup alc269_fixups[] = { { } }, .chained = true, - .chain_id = ALC289_FIXUP_ASUS_GA401 + .chain_id = ALC289_FIXUP_ASUS_GA502 }, [ALC274_FIXUP_HP_MIC] = { .type = HDA_FIXUP_VERBS, @@ -7705,6 +7773,36 @@ static const struct hda_fixup alc269_fixups[] = { .chained = true, .chain_id = ALC294_FIXUP_ASUS_HEADSET_MIC }, + [ALC285_FIXUP_THINKPAD_NO_BASS_SPK_HEADSET_JACK] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc_fixup_headset_jack, + .chained = true, + .chain_id = ALC269_FIXUP_THINKPAD_ACPI + }, + [ALC287_FIXUP_HP_GPIO_LED] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc287_fixup_hp_gpio_led, + }, + [ALC256_FIXUP_HP_HEADSET_MIC] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc274_fixup_hp_headset_mic, + }, + [ALC236_FIXUP_DELL_AIO_HEADSET_MIC] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc_fixup_no_int_mic, + .chained = true, + .chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE + }, + [ALC282_FIXUP_ACER_DISABLE_LINEOUT] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { + { 0x1b, 0x411111f0 }, + { 0x18, 0x01a1913c }, /* use as headset mic, without its own jack detect */ + { }, + }, + .chained = true, + .chain_id = ALC269_FIXUP_HEADSET_MODE + }, }; static const struct snd_pci_quirk alc269_fixup_tbl[] = { @@ -7719,11 +7817,14 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1025, 0x0762, "Acer Aspire E1-472", ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572), SND_PCI_QUIRK(0x1025, 0x0775, "Acer Aspire E1-572", ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572), SND_PCI_QUIRK(0x1025, 0x079b, "Acer Aspire V5-573G", ALC282_FIXUP_ASPIRE_V5_PINS), + SND_PCI_QUIRK(0x1025, 0x101c, "Acer Veriton N2510G", ALC269_FIXUP_LIFEBOOK), SND_PCI_QUIRK(0x1025, 0x102b, "Acer Aspire C24-860", ALC286_FIXUP_ACER_AIO_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1025, 0x1065, "Acer Aspire C20-820", ALC269VC_FIXUP_ACER_HEADSET_MIC), SND_PCI_QUIRK(0x1025, 0x106d, "Acer Cloudbook 14", ALC283_FIXUP_CHROME_BOOK), SND_PCI_QUIRK(0x1025, 0x1099, "Acer Aspire E5-523G", ALC255_FIXUP_ACER_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1025, 0x110e, "Acer Aspire ES1-432", ALC255_FIXUP_ACER_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1025, 0x1166, "Acer Veriton N4640G", ALC269_FIXUP_LIFEBOOK), + SND_PCI_QUIRK(0x1025, 0x1167, "Acer Veriton N6640G", ALC269_FIXUP_LIFEBOOK), SND_PCI_QUIRK(0x1025, 0x1246, "Acer Predator Helios 500", ALC299_FIXUP_PREDATOR_SPK), SND_PCI_QUIRK(0x1025, 0x1247, "Acer vCopperbox", ALC269VC_FIXUP_ACER_VCOPPERBOX_PINS), SND_PCI_QUIRK(0x1025, 0x1248, "Acer Veriton N4660G", ALC269VC_FIXUP_ACER_MIC_NO_PRESENCE), @@ -7782,6 +7883,9 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1028, 0x097d, "Dell Precision", ALC289_FIXUP_DUAL_SPK), SND_PCI_QUIRK(0x1028, 0x098d, "Dell Precision", ALC233_FIXUP_ASUS_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x09bf, "Dell Precision", ALC233_FIXUP_ASUS_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1028, 0x0a2e, "Dell", ALC236_FIXUP_DELL_AIO_HEADSET_MIC), + SND_PCI_QUIRK(0x1028, 0x0a30, "Dell", ALC236_FIXUP_DELL_AIO_HEADSET_MIC), + SND_PCI_QUIRK(0x1028, 0x0a58, "Dell Precision 3650 Tower", ALC255_FIXUP_DELL_HEADSET_MIC), SND_PCI_QUIRK(0x1028, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x164b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2), @@ -7848,6 +7952,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x103c, 0x820d, "HP Pavilion 15", ALC269_FIXUP_HP_MUTE_LED_MIC3), SND_PCI_QUIRK(0x103c, 0x8256, "HP", ALC221_FIXUP_HP_FRONT_MIC), SND_PCI_QUIRK(0x103c, 0x827e, "HP x360", ALC295_FIXUP_HP_X360), + SND_PCI_QUIRK(0x103c, 0x827f, "HP x360", ALC269_FIXUP_HP_MUTE_LED_MIC3), SND_PCI_QUIRK(0x103c, 0x82bf, "HP G3 mini", ALC221_FIXUP_HP_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x103c, 0x82c0, "HP G3 mini premium", ALC221_FIXUP_HP_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x103c, 0x83b9, "HP Spectre x360", ALC269_FIXUP_HP_MUTE_LED_MIC3), @@ -7859,6 +7964,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x103c, 0x8760, "HP", ALC285_FIXUP_HP_MUTE_LED), SND_PCI_QUIRK(0x103c, 0x877a, "HP", ALC285_FIXUP_HP_MUTE_LED), SND_PCI_QUIRK(0x103c, 0x877d, "HP", ALC236_FIXUP_HP_MUTE_LED), + SND_PCI_QUIRK(0x103c, 0x87f4, "HP", ALC287_FIXUP_HP_GPIO_LED), + SND_PCI_QUIRK(0x103c, 0x87f5, "HP", ALC287_FIXUP_HP_GPIO_LED), 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), @@ -7867,6 +7974,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1043, 0x10d0, "ASUS X540LA/X540LJ", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1043, 0x115d, "Asus 1015E", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), SND_PCI_QUIRK(0x1043, 0x11c0, "ASUS X556UR", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1043, 0x1271, "ASUS X430UN", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1043, 0x1290, "ASUS X441SA", ALC233_FIXUP_EAPD_COEF_AND_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1043, 0x12a0, "ASUS X441UV", ALC233_FIXUP_EAPD_COEF_AND_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1043, 0x12f0, "ASUS X541UV", ALC256_FIXUP_ASUS_MIC), @@ -7887,6 +7995,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1043, 0x1b13, "Asus U41SV", ALC269_FIXUP_INV_DMIC), SND_PCI_QUIRK(0x1043, 0x1bbd, "ASUS Z550MA", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1043, 0x1c23, "Asus X55U", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), + SND_PCI_QUIRK(0x1043, 0x125e, "ASUS Q524UQK", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1043, 0x1ccd, "ASUS X555UB", ALC256_FIXUP_ASUS_MIC), SND_PCI_QUIRK(0x1043, 0x1d4e, "ASUS TM420", ALC256_FIXUP_ASUS_HPE), SND_PCI_QUIRK(0x1043, 0x1e11, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA502), @@ -7924,11 +8033,50 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1458, 0xfa53, "Gigabyte BXBT-2807", ALC283_FIXUP_HEADSET_MIC), SND_PCI_QUIRK(0x1462, 0xb120, "MSI Cubi MS-B120", ALC283_FIXUP_HEADSET_MIC), SND_PCI_QUIRK(0x1462, 0xb171, "Cubi N 8GL (MS-B171)", ALC283_FIXUP_HEADSET_MIC), + SND_PCI_QUIRK(0x152d, 0x1082, "Quanta NL3", ALC269_FIXUP_LIFEBOOK), + SND_PCI_QUIRK(0x1558, 0x1323, "Clevo N130ZU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0x1325, "System76 Darter Pro (darp5)", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x1401, "Clevo L140[CZ]U", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x1403, "Clevo N140CU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x1404, "Clevo N150CU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x14a1, "Clevo L141MU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x4018, "Clevo NV40M[BE]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x4019, "Clevo NV40MZ", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x4020, "Clevo NV40MB", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x40a1, "Clevo NL40GU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x40c1, "Clevo NL40[CZ]U", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x40d1, "Clevo NL41DU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x50a3, "Clevo NJ51GU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x50b3, "Clevo NK50S[BEZ]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x50b6, "Clevo NK50S5", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x50b8, "Clevo NK50SZ", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x50d5, "Clevo NP50D5", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x50f0, "Clevo NH50A[CDF]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x50f3, "Clevo NH58DPQ", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x5101, "Clevo S510WU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x5157, "Clevo W517GU1", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x51a1, "Clevo NS50MU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x70a1, "Clevo NB70T[HJK]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x70b3, "Clevo NK70SB", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x8228, "Clevo NR40BU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x8520, "Clevo NH50D[CD]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x8521, "Clevo NH77D[CD]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x8535, "Clevo NH50D[BE]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x8536, "Clevo NH79D[BE]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0x8550, "System76 Gazelle (gaze14)", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0x8551, "System76 Gazelle (gaze14)", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0x8560, "System76 Gazelle (gaze14)", ALC269_FIXUP_HEADSET_MIC), SND_PCI_QUIRK(0x1558, 0x8561, "System76 Gazelle (gaze14)", ALC269_FIXUP_HEADSET_MIC), + SND_PCI_QUIRK(0x1558, 0x8668, "Clevo NP50B[BE]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x8680, "Clevo NJ50LU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x8686, "Clevo NH50[CZ]U", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x8a20, "Clevo NH55DCQ-Y", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x8a51, "Clevo NH70RCQ-Y", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x8d50, "Clevo NH55RCQ-M", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x951d, "Clevo N950T[CDF]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x961d, "Clevo N960S[CDF]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x971d, "Clevo N970T[CDF]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0xa500, "Clevo NL53RU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x17aa, 0x1036, "Lenovo P520", ALC233_FIXUP_LENOVO_MULTI_CODECS), SND_PCI_QUIRK(0x17aa, 0x1048, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC), SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE), @@ -7966,6 +8114,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x225d, "Thinkpad T480", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), SND_PCI_QUIRK(0x17aa, 0x2292, "Thinkpad X1 Carbon 7th", ALC285_FIXUP_THINKPAD_HEADSET_JACK), SND_PCI_QUIRK(0x17aa, 0x22be, "Thinkpad X1 Carbon 8th", ALC285_FIXUP_THINKPAD_HEADSET_JACK), + SND_PCI_QUIRK(0x17aa, 0x22c1, "Thinkpad P1 Gen 3", ALC285_FIXUP_THINKPAD_NO_BASS_SPK_HEADSET_JACK), + SND_PCI_QUIRK(0x17aa, 0x22c2, "Thinkpad X1 Extreme Gen 3", ALC285_FIXUP_THINKPAD_NO_BASS_SPK_HEADSET_JACK), SND_PCI_QUIRK(0x17aa, 0x30bb, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY), SND_PCI_QUIRK(0x17aa, 0x30e2, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY), SND_PCI_QUIRK(0x17aa, 0x310c, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION), @@ -8278,6 +8428,12 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { {0x19, 0x02a11020}, {0x1a, 0x02a11030}, {0x21, 0x0221101f}), + SND_HDA_PIN_QUIRK(0x10ec0236, 0x1028, "Dell", ALC236_FIXUP_DELL_AIO_HEADSET_MIC, + {0x21, 0x02211010}), + SND_HDA_PIN_QUIRK(0x10ec0236, 0x103c, "HP", ALC256_FIXUP_HP_HEADSET_MIC, + {0x14, 0x90170110}, + {0x19, 0x02a11020}, + {0x21, 0x02211030}), SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL2_MIC_NO_PRESENCE, {0x14, 0x90170110}, {0x21, 0x02211020}), @@ -8380,6 +8536,10 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { {0x1a, 0x90a70130}, {0x1b, 0x90170110}, {0x21, 0x03211020}), + SND_HDA_PIN_QUIRK(0x10ec0256, 0x103c, "HP", ALC256_FIXUP_HP_HEADSET_MIC, + {0x14, 0x90170110}, + {0x19, 0x02a11020}, + {0x21, 0x0221101f}), SND_HDA_PIN_QUIRK(0x10ec0274, 0x103c, "HP", ALC274_FIXUP_HP_HEADSET_MIC, {0x17, 0x90170110}, {0x19, 0x03a11030}, @@ -8421,6 +8581,22 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { {0x12, 0x90a60140}, {0x19, 0x04a11030}, {0x21, 0x04211020}), + SND_HDA_PIN_QUIRK(0x10ec0282, 0x1025, "Acer", ALC282_FIXUP_ACER_DISABLE_LINEOUT, + ALC282_STANDARD_PINS, + {0x12, 0x90a609c0}, + {0x18, 0x03a11830}, + {0x19, 0x04a19831}, + {0x1a, 0x0481303f}, + {0x1b, 0x04211020}, + {0x21, 0x0321101f}), + SND_HDA_PIN_QUIRK(0x10ec0282, 0x1025, "Acer", ALC282_FIXUP_ACER_DISABLE_LINEOUT, + ALC282_STANDARD_PINS, + {0x12, 0x90a60940}, + {0x18, 0x03a11830}, + {0x19, 0x04a19831}, + {0x1a, 0x0481303f}, + {0x1b, 0x04211020}, + {0x21, 0x0321101f}), SND_HDA_PIN_QUIRK(0x10ec0283, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE, ALC282_STANDARD_PINS, {0x12, 0x90a60130}, @@ -8434,11 +8610,20 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { {0x12, 0x90a60130}, {0x19, 0x03a11020}, {0x21, 0x0321101f}), + SND_HDA_PIN_QUIRK(0x10ec0285, 0x17aa, "Lenovo", ALC285_FIXUP_THINKPAD_NO_BASS_SPK_HEADSET_JACK, + {0x14, 0x90170110}, + {0x19, 0x04a11040}, + {0x21, 0x04211020}), SND_HDA_PIN_QUIRK(0x10ec0285, 0x17aa, "Lenovo", ALC285_FIXUP_LENOVO_PC_BEEP_IN_NOISE, {0x12, 0x90a60130}, {0x14, 0x90170110}, {0x19, 0x04a11040}, {0x21, 0x04211020}), + SND_HDA_PIN_QUIRK(0x10ec0287, 0x17aa, "Lenovo", ALC285_FIXUP_THINKPAD_HEADSET_JACK, + {0x14, 0x90170110}, + {0x17, 0x90170111}, + {0x19, 0x03a11030}, + {0x21, 0x03211020}), SND_HDA_PIN_QUIRK(0x10ec0286, 0x1025, "Acer", ALC286_FIXUP_ACER_AIO_MIC_NO_PRESENCE, {0x12, 0x90a60130}, {0x17, 0x90170110}, @@ -8502,6 +8687,9 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { SND_HDA_PIN_QUIRK(0x10ec0293, 0x1028, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE, ALC292_STANDARD_PINS, {0x13, 0x90a60140}), + SND_HDA_PIN_QUIRK(0x10ec0294, 0x1043, "ASUS", ALC294_FIXUP_ASUS_HPE, + {0x17, 0x90170110}, + {0x21, 0x04211020}), SND_HDA_PIN_QUIRK(0x10ec0294, 0x1043, "ASUS", ALC294_FIXUP_ASUS_MIC, {0x14, 0x90170110}, {0x1b, 0x90a70130}, @@ -10088,6 +10276,7 @@ static const struct hda_device_id snd_hda_id_realtek[] = { HDA_CODEC_ENTRY(0x10ec0888, "ALC888", patch_alc882), HDA_CODEC_ENTRY(0x10ec0889, "ALC889", patch_alc882), HDA_CODEC_ENTRY(0x10ec0892, "ALC892", patch_alc662), + HDA_CODEC_ENTRY(0x10ec0897, "ALC897", patch_alc662), HDA_CODEC_ENTRY(0x10ec0899, "ALC898", patch_alc882), HDA_CODEC_ENTRY(0x10ec0900, "ALC1150", patch_alc882), HDA_CODEC_ENTRY(0x10ec0b00, "ALCS1200A", patch_alc882), diff --git a/sound/pci/mixart/mixart_core.c b/sound/pci/mixart/mixart_core.c index 0bdd33b0af65..fb8895af0363 100644 --- a/sound/pci/mixart/mixart_core.c +++ b/sound/pci/mixart/mixart_core.c @@ -70,7 +70,6 @@ static int get_msg(struct mixart_mgr *mgr, struct mixart_msg *resp, unsigned int i; #endif - mutex_lock(&mgr->msg_lock); err = 0; /* copy message descriptor from miXart to driver */ @@ -119,8 +118,6 @@ static int get_msg(struct mixart_mgr *mgr, struct mixart_msg *resp, writel_be(headptr, MIXART_MEM(mgr, MSG_OUTBOUND_FREE_HEAD)); _clean_exit: - mutex_unlock(&mgr->msg_lock); - return err; } @@ -258,7 +255,9 @@ int snd_mixart_send_msg(struct mixart_mgr *mgr, struct mixart_msg *request, int resp.data = resp_data; resp.size = max_resp_size; + mutex_lock(&mgr->msg_lock); err = get_msg(mgr, &resp, msg_frame); + mutex_unlock(&mgr->msg_lock); if( request->message_id != resp.message_id ) dev_err(&mgr->pci->dev, "RESPONSE ERROR!\n"); diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c index 869af8a32c98..4eabece4dcba 100644 --- a/sound/pci/rme32.c +++ b/sound/pci/rme32.c @@ -468,7 +468,6 @@ static int snd_rme32_capture_getrate(struct rme32 * rme32, int *is_adat) return 32000; default: return -1; - break; } else switch (n) { /* supporting the CS8412 */ diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index 4a1f576dd9cf..04e878a0f773 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -2286,7 +2286,6 @@ static int hdspm_get_wc_sample_rate(struct hdspm *hdspm) case AIO: status = hdspm_read(hdspm, HDSPM_RD_STATUS_1); return (status >> 16) & 0xF; - break; case AES32: status = hdspm_read(hdspm, HDSPM_statusRegister); return (status >> HDSPM_AES32_wcFreq_bit) & 0xF; @@ -2312,7 +2311,6 @@ static int hdspm_get_tco_sample_rate(struct hdspm *hdspm) case AIO: status = hdspm_read(hdspm, HDSPM_RD_STATUS_1); return (status >> 20) & 0xF; - break; case AES32: status = hdspm_read(hdspm, HDSPM_statusRegister); return (status >> 1) & 0xF; @@ -2338,7 +2336,6 @@ static int hdspm_get_sync_in_sample_rate(struct hdspm *hdspm) case AIO: status = hdspm_read(hdspm, HDSPM_RD_STATUS_2); return (status >> 12) & 0xF; - break; default: break; } @@ -2358,7 +2355,6 @@ static int hdspm_get_aes_sample_rate(struct hdspm *hdspm, int index) case AES32: timecode = hdspm_read(hdspm, HDSPM_timecodeRegister); return (timecode >> (4*index)) & 0xF; - break; default: break; } @@ -3845,7 +3841,6 @@ static int hdspm_wc_sync_check(struct hdspm *hdspm) return 1; } return 0; - break; case MADI: status2 = hdspm_read(hdspm, HDSPM_statusRegister2); @@ -3856,7 +3851,6 @@ static int hdspm_wc_sync_check(struct hdspm *hdspm) return 1; } return 0; - break; case RayDAT: case AIO: @@ -3868,8 +3862,6 @@ static int hdspm_wc_sync_check(struct hdspm *hdspm) return 1; return 0; - break; - case MADIface: break; } @@ -6321,6 +6313,7 @@ static int snd_hdspm_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, (statusregister & HDSPM_RX_64ch) ? 1 : 0; /* TODO: Mac driver sets it when f_s>48kHz */ status.card_specific.madi.frame_format = 0; + break; default: break; diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c index 7ab10028d9fa..012fbec5e6a7 100644 --- a/sound/pci/rme9652/rme9652.c +++ b/sound/pci/rme9652/rme9652.c @@ -732,34 +732,27 @@ static inline int rme9652_spdif_sample_rate(struct snd_rme9652 *s) switch (rme9652_decode_spdif_rate(rate_bits)) { case 0x7: return 32000; - break; case 0x6: return 44100; - break; case 0x5: return 48000; - break; case 0x4: return 88200; - break; case 0x3: return 96000; - break; case 0x0: return 64000; - break; default: dev_err(s->card->dev, "%s: unknown S/PDIF input rate (bits = 0x%x)\n", s->card_name, rate_bits); return 0; - break; } } |