diff options
Diffstat (limited to 'sound/pci')
-rw-r--r-- | sound/pci/ac97/ac97_patch.c | 2 | ||||
-rw-r--r-- | sound/pci/hda/Kconfig | 4 | ||||
-rw-r--r-- | sound/pci/hda/hda_intel.c | 3 | ||||
-rw-r--r-- | sound/pci/hda/hda_tegra.c | 50 | ||||
-rw-r--r-- | sound/pci/hda/patch_hdmi.c | 13 | ||||
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 51 | ||||
-rw-r--r-- | sound/pci/oxygen/xonar_pcm179x.c | 4 |
7 files changed, 109 insertions, 18 deletions
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index ebf926728c5f..45ef0f52ec55 100644 --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c @@ -1356,7 +1356,7 @@ static int patch_cx20551(struct snd_ac97 *ac97) } /* - * Analog Device AD18xx, AD19xx codecs + * Analog Devices AD18xx, AD19xx codecs */ #ifdef CONFIG_PM static void ad18xx_resume(struct snd_ac97 *ac97) diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig index e1d3082a4fe9..7ba542e45a3d 100644 --- a/sound/pci/hda/Kconfig +++ b/sound/pci/hda/Kconfig @@ -99,10 +99,10 @@ comment "Set to Y if you want auto-loading the codec driver" depends on SND_HDA=y && SND_HDA_CODEC_REALTEK=m config SND_HDA_CODEC_ANALOG - tristate "Build Analog Device HD-audio codec support" + tristate "Build Analog Devices HD-audio codec support" select SND_HDA_GENERIC help - Say Y or M here to include Analog Device HD-audio codec support in + Say Y or M here to include Analog Devices HD-audio codec support in snd-hda-intel driver, such as AD1986A. comment "Set to Y if you want auto-loading the codec driver" diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 0310193ea1bd..41a03c61a74b 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2662,6 +2662,9 @@ static const struct pci_device_id azx_ids[] = { { PCI_DEVICE(0x1002, 0xab20), .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS | AZX_DCAPS_PM_RUNTIME }, + { PCI_DEVICE(0x1002, 0xab28), + .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS | + AZX_DCAPS_PM_RUNTIME }, { PCI_DEVICE(0x1002, 0xab38), .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS | AZX_DCAPS_PM_RUNTIME }, diff --git a/sound/pci/hda/hda_tegra.c b/sound/pci/hda/hda_tegra.c index 773992a07efa..0cc5fad1af8a 100644 --- a/sound/pci/hda/hda_tegra.c +++ b/sound/pci/hda/hda_tegra.c @@ -52,10 +52,21 @@ #define HDA_IPFS_INTR_MASK 0x188 #define HDA_IPFS_EN_INTR (1 << 16) +/* FPCI */ +#define FPCI_DBG_CFG_2 0x10F4 +#define FPCI_GCAP_NSDO_SHIFT 18 +#define FPCI_GCAP_NSDO_MASK (0x3 << FPCI_GCAP_NSDO_SHIFT) + /* max number of SDs */ #define NUM_CAPTURE_SD 1 #define NUM_PLAYBACK_SD 1 +/* + * Tegra194 does not reflect correct number of SDO lines. Below macro + * is used to update the GCAP register to workaround the issue. + */ +#define TEGRA194_NUM_SDO_LINES 4 + struct hda_tegra { struct azx chip; struct device *dev; @@ -275,6 +286,7 @@ static int hda_tegra_init_clk(struct hda_tegra *hda) static int hda_tegra_first_init(struct azx *chip, struct platform_device *pdev) { + struct hda_tegra *hda = container_of(chip, struct hda_tegra, chip); struct hdac_bus *bus = azx_bus(chip); struct snd_card *card = chip->card; int err; @@ -298,6 +310,26 @@ static int hda_tegra_first_init(struct azx *chip, struct platform_device *pdev) bus->irq = irq_id; card->sync_irq = bus->irq; + /* + * Tegra194 has 4 SDO lines and the STRIPE can be used to + * indicate how many of the SDO lines the stream should be + * striped. But GCAP register does not reflect the true + * capability of HW. Below workaround helps to fix this. + * + * GCAP_NSDO is bits 19:18 in T_AZA_DBG_CFG_2, + * 0 for 1 SDO, 1 for 2 SDO, 2 for 4 SDO lines. + */ + if (of_device_is_compatible(np, "nvidia,tegra194-hda")) { + u32 val; + + dev_info(card->dev, "Override SDO lines to %u\n", + TEGRA194_NUM_SDO_LINES); + + val = readl(hda->regs + FPCI_DBG_CFG_2) & ~FPCI_GCAP_NSDO_MASK; + val |= (TEGRA194_NUM_SDO_LINES >> 1) << FPCI_GCAP_NSDO_SHIFT; + writel(val, hda->regs + FPCI_DBG_CFG_2); + } + gcap = azx_readw(chip, GCAP); dev_dbg(card->dev, "chipset global capabilities = 0x%x\n", gcap); @@ -332,6 +364,23 @@ static int hda_tegra_first_init(struct azx *chip, struct platform_device *pdev) /* initialize chip */ azx_init_chip(chip, 1); + /* + * Playback (for 44.1K/48K, 2-channel, 16-bps) fails with + * 4 SDO lines due to legacy design limitation. Following + * is, from HD Audio Specification (Revision 1.0a), used to + * control striping of the stream across multiple SDO lines + * for sample rates <= 48K. + * + * { ((num_channels * bits_per_sample) / number of SDOs) >= 8 } + * + * Due to legacy design issue it is recommended that above + * ratio must be greater than 8. Since number of SDO lines is + * in powers of 2, next available ratio is 16 which can be + * used as a limiting factor here. + */ + if (of_device_is_compatible(np, "nvidia,tegra194-hda")) + chip->bus.core.sdo_limit = 16; + /* codec detection */ if (!bus->codec_mask) { dev_err(card->dev, "no codecs found!\n"); @@ -408,6 +457,7 @@ static int hda_tegra_create(struct snd_card *card, static const struct of_device_id hda_tegra_match[] = { { .compatible = "nvidia,tegra30-hda" }, + { .compatible = "nvidia,tegra194-hda" }, {}, }; MODULE_DEVICE_TABLE(of, hda_tegra_match); diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 93760a3564cf..fbd7cc6026d8 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -2024,7 +2024,7 @@ static const struct hda_pcm_ops generic_ops = { static int hdmi_get_spk_alloc(struct hdac_device *hdac, int pcm_idx) { - struct hda_codec *codec = container_of(hdac, struct hda_codec, core); + struct hda_codec *codec = hdac_to_hda_codec(hdac); struct hdmi_spec *spec = codec->spec; struct hdmi_spec_per_pin *per_pin = pcm_idx_to_pin(spec, pcm_idx); @@ -2037,7 +2037,7 @@ static int hdmi_get_spk_alloc(struct hdac_device *hdac, int pcm_idx) static void hdmi_get_chmap(struct hdac_device *hdac, int pcm_idx, unsigned char *chmap) { - struct hda_codec *codec = container_of(hdac, struct hda_codec, core); + struct hda_codec *codec = hdac_to_hda_codec(hdac); struct hdmi_spec *spec = codec->spec; struct hdmi_spec_per_pin *per_pin = pcm_idx_to_pin(spec, pcm_idx); @@ -2051,7 +2051,7 @@ static void hdmi_get_chmap(struct hdac_device *hdac, int pcm_idx, static void hdmi_set_chmap(struct hdac_device *hdac, int pcm_idx, unsigned char *chmap, int prepared) { - struct hda_codec *codec = container_of(hdac, struct hda_codec, core); + struct hda_codec *codec = hdac_to_hda_codec(hdac); struct hdmi_spec *spec = codec->spec; struct hdmi_spec_per_pin *per_pin = pcm_idx_to_pin(spec, pcm_idx); @@ -2067,7 +2067,7 @@ static void hdmi_set_chmap(struct hdac_device *hdac, int pcm_idx, static bool is_hdmi_pcm_attached(struct hdac_device *hdac, int pcm_idx) { - struct hda_codec *codec = container_of(hdac, struct hda_codec, core); + struct hda_codec *codec = hdac_to_hda_codec(hdac); struct hdmi_spec *spec = codec->spec; struct hdmi_spec_per_pin *per_pin = pcm_idx_to_pin(spec, pcm_idx); @@ -3787,7 +3787,7 @@ static int atihdmi_paired_chmap_validate(struct hdac_chmap *chmap, static int atihdmi_pin_set_slot_channel(struct hdac_device *hdac, hda_nid_t pin_nid, int hdmi_slot, int stream_channel) { - struct hda_codec *codec = container_of(hdac, struct hda_codec, core); + struct hda_codec *codec = hdac_to_hda_codec(hdac); int verb; int ati_channel_setup = 0; @@ -3823,7 +3823,7 @@ static int atihdmi_pin_set_slot_channel(struct hdac_device *hdac, static int atihdmi_pin_get_slot_channel(struct hdac_device *hdac, hda_nid_t pin_nid, int asp_slot) { - struct hda_codec *codec = container_of(hdac, struct hda_codec, core); + struct hda_codec *codec = hdac_to_hda_codec(hdac); bool was_odd = false; int ati_asp_slot = asp_slot; int verb; @@ -4169,6 +4169,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(0x8086281a, "Jasperlake HDMI", patch_i915_icl_hdmi), +HDA_CODEC_ENTRY(0x8086281b, "Elkhartlake HDMI", patch_i915_icl_hdmi), HDA_CODEC_ENTRY(0x80862880, "CedarTrail HDMI", patch_generic_hdmi), HDA_CODEC_ENTRY(0x80862882, "Valleyview2 HDMI", patch_i915_byt_hdmi), HDA_CODEC_ENTRY(0x80862883, "Braswell HDMI", patch_i915_byt_hdmi), diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index e62d58872b6e..0aa778ff7f2b 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -17,6 +17,7 @@ #include <linux/dmi.h> #include <linux/module.h> #include <linux/input.h> +#include <linux/leds.h> #include <sound/core.h> #include <sound/jack.h> #include <sound/hda_codec.h> @@ -81,6 +82,7 @@ struct alc_spec { /* mute LED for HP laptops, see alc269_fixup_mic_mute_hook() */ int mute_led_polarity; + int micmute_led_polarity; hda_nid_t mute_led_nid; hda_nid_t cap_mute_led_nid; @@ -4080,11 +4082,9 @@ static void alc269_fixup_hp_mute_led_mic3(struct hda_codec *codec, /* update LED status via GPIO */ static void alc_update_gpio_led(struct hda_codec *codec, unsigned int mask, - bool enabled) + int polarity, bool enabled) { - struct alc_spec *spec = codec->spec; - - if (spec->mute_led_polarity) + if (polarity) enabled = !enabled; alc_update_gpio_data(codec, mask, !enabled); /* muted -> LED on */ } @@ -4095,7 +4095,8 @@ static void alc_fixup_gpio_mute_hook(void *private_data, int enabled) struct hda_codec *codec = private_data; struct alc_spec *spec = codec->spec; - alc_update_gpio_led(codec, spec->gpio_mute_led_mask, enabled); + alc_update_gpio_led(codec, spec->gpio_mute_led_mask, + spec->mute_led_polarity, enabled); } /* turn on/off mic-mute LED via GPIO per capture hook */ @@ -4104,9 +4105,30 @@ static void alc_gpio_micmute_update(struct hda_codec *codec) struct alc_spec *spec = codec->spec; alc_update_gpio_led(codec, spec->gpio_mic_led_mask, + spec->micmute_led_polarity, spec->gen.micmute_led.led_value); } +#if IS_REACHABLE(CONFIG_LEDS_TRIGGER_AUDIO) +static int micmute_led_set(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + struct hda_codec *codec = dev_to_hda_codec(led_cdev->dev->parent); + struct alc_spec *spec = codec->spec; + + alc_update_gpio_led(codec, spec->gpio_mic_led_mask, + spec->micmute_led_polarity, !!brightness); + return 0; +} + +static struct led_classdev micmute_led_cdev = { + .name = "hda::micmute", + .max_brightness = 1, + .brightness_set_blocking = micmute_led_set, + .default_trigger = "audio-micmute", +}; +#endif + /* setup mute and mic-mute GPIO bits, add hooks appropriately */ static void alc_fixup_hp_gpio_led(struct hda_codec *codec, int action, @@ -4114,6 +4136,9 @@ static void alc_fixup_hp_gpio_led(struct hda_codec *codec, unsigned int micmute_mask) { struct alc_spec *spec = codec->spec; +#if IS_REACHABLE(CONFIG_LEDS_TRIGGER_AUDIO) + int err; +#endif alc_fixup_gpio(codec, action, mute_mask | micmute_mask); @@ -4126,6 +4151,13 @@ static void alc_fixup_hp_gpio_led(struct hda_codec *codec, if (micmute_mask) { spec->gpio_mic_led_mask = micmute_mask; snd_hda_gen_add_micmute_led(codec, alc_gpio_micmute_update); + +#if IS_REACHABLE(CONFIG_LEDS_TRIGGER_AUDIO) + micmute_led_cdev.brightness = ledtrig_audio_get(LED_AUDIO_MICMUTE); + err = devm_led_classdev_register(&codec->core.dev, &micmute_led_cdev); + if (err) + codec_warn(codec, "failed to register micmute LED\n"); +#endif } } @@ -4138,7 +4170,11 @@ static void alc269_fixup_hp_gpio_led(struct hda_codec *codec, static void alc285_fixup_hp_gpio_led(struct hda_codec *codec, const struct hda_fixup *fix, int action) { - alc_fixup_hp_gpio_led(codec, action, 0x04, 0x00); + struct alc_spec *spec = codec->spec; + + spec->micmute_led_polarity = 1; + + alc_fixup_hp_gpio_led(codec, action, 0x04, 0x01); } static void alc286_fixup_hp_gpio_led(struct hda_codec *codec, @@ -5808,7 +5844,8 @@ static void alc280_hp_gpio4_automute_hook(struct hda_codec *codec, snd_hda_gen_hp_automute(codec, jack); /* mute_led_polarity is set to 0, so we pass inverted value here */ - alc_update_gpio_led(codec, 0x10, !spec->gen.hp_jack_present); + alc_update_gpio_led(codec, 0x10, spec->mute_led_polarity, + !spec->gen.hp_jack_present); } /* Manage GPIOs for HP EliteBook Folio 9480m. diff --git a/sound/pci/oxygen/xonar_pcm179x.c b/sound/pci/oxygen/xonar_pcm179x.c index 6a0520c4fb5a..cf801a235df9 100644 --- a/sound/pci/oxygen/xonar_pcm179x.c +++ b/sound/pci/oxygen/xonar_pcm179x.c @@ -460,7 +460,7 @@ static void xonar_st_init(struct oxygen *chip) data->generic.anti_pop_delay = 100; data->h6 = chip->model.dac_channels_mixer > 2; - data->has_cs2000 = 1; + data->has_cs2000 = true; data->cs2000_regs[CS2000_FUN_CFG_1] = CS2000_REF_CLK_DIV_1; data->broken_i2c = true; @@ -502,7 +502,7 @@ static void xonar_xense_init(struct oxygen *chip) xonar_init_ext_power(chip); data->generic.anti_pop_delay = 100; - data->has_cs2000 = 1; + data->has_cs2000 = true; data->cs2000_regs[CS2000_FUN_CFG_1] = CS2000_REF_CLK_DIV_1; oxygen_write16(chip, OXYGEN_I2S_A_FORMAT, |