diff options
Diffstat (limited to 'sound/hda/codecs/realtek/realtek.h')
-rw-r--r-- | sound/hda/codecs/realtek/realtek.h | 298 |
1 files changed, 298 insertions, 0 deletions
diff --git a/sound/hda/codecs/realtek/realtek.h b/sound/hda/codecs/realtek/realtek.h new file mode 100644 index 000000000000..ee893da0c486 --- /dev/null +++ b/sound/hda/codecs/realtek/realtek.h @@ -0,0 +1,298 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// +// Realtek HD-audio codec support code +// + +#ifndef __HDA_REALTEK_H +#define __HDA_REALTEK_H + +#include <linux/acpi.h> +#include <linux/cleanup.h> +#include <linux/init.h> +#include <linux/delay.h> +#include <linux/slab.h> +#include <linux/pci.h> +#include <linux/dmi.h> +#include <linux/module.h> +#include <linux/i2c.h> +#include <linux/input.h> +#include <linux/leds.h> +#include <linux/ctype.h> +#include <linux/spi/spi.h> +#include <sound/core.h> +#include <sound/jack.h> +#include <sound/hda_codec.h> +#include "hda_local.h" +#include "hda_auto_parser.h" +#include "hda_beep.h" +#include "hda_jack.h" +#include "../generic.h" +#include "../side-codecs/hda_component.h" + +/* extra amp-initialization sequence types */ +enum { + ALC_INIT_UNDEFINED, + ALC_INIT_NONE, + ALC_INIT_DEFAULT, +}; + +enum { + ALC_HEADSET_MODE_UNKNOWN, + ALC_HEADSET_MODE_UNPLUGGED, + ALC_HEADSET_MODE_HEADSET, + ALC_HEADSET_MODE_MIC, + ALC_HEADSET_MODE_HEADPHONE, +}; + +enum { + ALC_HEADSET_TYPE_UNKNOWN, + ALC_HEADSET_TYPE_CTIA, + ALC_HEADSET_TYPE_OMTP, +}; + +enum { + ALC_KEY_MICMUTE_INDEX, +}; + +struct alc_customize_define { + unsigned int sku_cfg; + unsigned char port_connectivity; + unsigned char check_sum; + unsigned char customization; + unsigned char external_amp; + unsigned int enable_pcbeep:1; + unsigned int platform_type:1; + unsigned int swap:1; + unsigned int override:1; + unsigned int fixup:1; /* Means that this sku is set by driver, not read from hw */ +}; + +struct alc_coef_led { + unsigned int idx; + unsigned int mask; + unsigned int on; + unsigned int off; +}; + +struct alc_spec { + struct hda_gen_spec gen; /* must be at head */ + + /* codec parameterization */ + 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; + bool gpio_write_delay; /* add a delay before writing gpio_data */ + + /* mute LED for HP laptops, see vref_mute_led_set() */ + int mute_led_polarity; + int micmute_led_polarity; + hda_nid_t mute_led_nid; + hda_nid_t cap_mute_led_nid; + + unsigned int gpio_mute_led_mask; + unsigned int gpio_mic_led_mask; + struct alc_coef_led mute_led_coef; + struct alc_coef_led mic_led_coef; + struct mutex coef_mutex; + + hda_nid_t headset_mic_pin; + hda_nid_t headphone_mic_pin; + int current_headset_mode; + int current_headset_type; + + /* hooks */ + void (*init_hook)(struct hda_codec *codec); + void (*power_hook)(struct hda_codec *codec); + void (*shutup)(struct hda_codec *codec); + + int init_amp; + int codec_variant; /* flag for other variants */ + unsigned int has_alc5505_dsp:1; + unsigned int no_depop_delay:1; + unsigned int done_hp_init:1; + 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; + unsigned int en_3kpull_low:1; + int num_speaker_amps; + + /* for PLL fix */ + hda_nid_t pll_nid; + unsigned int pll_coef_idx, pll_coef_bit; + unsigned int coef0; + struct input_dev *kb_dev; + u8 alc_mute_keycode_map[1]; + + /* component binding */ + struct hda_component_parent comps; +}; + +int alc_read_coefex_idx(struct hda_codec *codec, hda_nid_t nid, + unsigned int coef_idx); +void alc_write_coefex_idx(struct hda_codec *codec, hda_nid_t nid, + unsigned int coef_idx, unsigned int coef_val); +void alc_update_coefex_idx(struct hda_codec *codec, hda_nid_t nid, + unsigned int coef_idx, unsigned int mask, + unsigned int bits_set); +#define alc_read_coef_idx(codec, coef_idx) \ + alc_read_coefex_idx(codec, 0x20, coef_idx) +#define alc_write_coef_idx(codec, coef_idx, coef_val) \ + alc_write_coefex_idx(codec, 0x20, coef_idx, coef_val) +#define alc_update_coef_idx(codec, coef_idx, mask, bits_set) \ + alc_update_coefex_idx(codec, 0x20, coef_idx, mask, bits_set) + +unsigned int alc_get_coef0(struct hda_codec *codec); + +/* coef writes/updates batch */ +struct coef_fw { + unsigned char nid; + unsigned char idx; + unsigned short mask; + unsigned short val; +}; + +#define UPDATE_COEFEX(_nid, _idx, _mask, _val) \ + { .nid = (_nid), .idx = (_idx), .mask = (_mask), .val = (_val) } +#define WRITE_COEFEX(_nid, _idx, _val) UPDATE_COEFEX(_nid, _idx, -1, _val) +#define WRITE_COEF(_idx, _val) WRITE_COEFEX(0x20, _idx, _val) +#define UPDATE_COEF(_idx, _mask, _val) UPDATE_COEFEX(0x20, _idx, _mask, _val) + +void alc_process_coef_fw(struct hda_codec *codec, const struct coef_fw *fw); + +/* + * GPIO helpers + */ +void alc_setup_gpio(struct hda_codec *codec, unsigned int mask); +void alc_write_gpio_data(struct hda_codec *codec); +void alc_update_gpio_data(struct hda_codec *codec, unsigned int mask, + bool on); +void alc_write_gpio(struct hda_codec *codec); + +/* common GPIO fixups */ +void alc_fixup_gpio(struct hda_codec *codec, int action, unsigned int mask); +void alc_fixup_gpio1(struct hda_codec *codec, + const struct hda_fixup *fix, int action); +void alc_fixup_gpio2(struct hda_codec *codec, + const struct hda_fixup *fix, int action); +void alc_fixup_gpio3(struct hda_codec *codec, + const struct hda_fixup *fix, int action); +void alc_fixup_gpio4(struct hda_codec *codec, + const struct hda_fixup *fix, int action); +void alc_fixup_micmute_led(struct hda_codec *codec, + const struct hda_fixup *fix, int action); + +/* + * Common init code, callbacks and helpers + */ +void alc_fix_pll(struct hda_codec *codec); +void alc_fix_pll_init(struct hda_codec *codec, hda_nid_t nid, + unsigned int coef_idx, unsigned int coef_bit); +void alc_fill_eapd_coef(struct hda_codec *codec); +void alc_auto_setup_eapd(struct hda_codec *codec, bool on); + +int alc_find_ext_mic_pin(struct hda_codec *codec); +void alc_headset_mic_no_shutup(struct hda_codec *codec); +void alc_shutup_pins(struct hda_codec *codec); +void alc_eapd_shutup(struct hda_codec *codec); +void alc_auto_init_amp(struct hda_codec *codec, int type); +hda_nid_t alc_get_hp_pin(struct alc_spec *spec); +int alc_auto_parse_customize_define(struct hda_codec *codec); +int alc_subsystem_id(struct hda_codec *codec, const hda_nid_t *ports); +void alc_ssid_check(struct hda_codec *codec, const hda_nid_t *ports); +int alc_build_controls(struct hda_codec *codec); +void alc_update_knob_master(struct hda_codec *codec, + struct hda_jack_callback *jack); + +static inline void alc_pre_init(struct hda_codec *codec) +{ + alc_fill_eapd_coef(codec); +} + +#define is_s3_resume(codec) \ + ((codec)->core.dev.power.power_state.event == PM_EVENT_RESUME) +#define is_s4_resume(codec) \ + ((codec)->core.dev.power.power_state.event == PM_EVENT_RESTORE) +#define is_s4_suspend(codec) \ + ((codec)->core.dev.power.power_state.event == PM_EVENT_FREEZE) + +int alc_init(struct hda_codec *codec); +void alc_shutup(struct hda_codec *codec); +void alc_power_eapd(struct hda_codec *codec); +int alc_suspend(struct hda_codec *codec); +int alc_resume(struct hda_codec *codec); + +int alc_parse_auto_config(struct hda_codec *codec, + const hda_nid_t *ignore_nids, + const hda_nid_t *ssid_nids); +int alc_alloc_spec(struct hda_codec *codec, hda_nid_t mixer_nid); + +#define alc_codec_rename(codec, name) snd_hda_codec_set_name(codec, name) + +#ifdef CONFIG_SND_HDA_INPUT_BEEP +int alc_set_beep_amp(struct alc_spec *spec, hda_nid_t nid, int idx, int dir); +int alc_has_cdefine_beep(struct hda_codec *codec); +#define set_beep_amp alc_set_beep_amp +#define has_cdefine_beep alc_has_cdefine_beep +#else +#define set_beep_amp(spec, nid, idx, dir) 0 +#define has_cdefine_beep(codec) 0 +#endif + +static inline void rename_ctl(struct hda_codec *codec, const char *oldname, + const char *newname) +{ + struct snd_kcontrol *kctl; + + kctl = snd_hda_find_mixer_ctl(codec, oldname); + if (kctl) + snd_ctl_rename(codec->card, kctl, newname); +} + +/* Common fixups */ +void alc_fixup_sku_ignore(struct hda_codec *codec, + const struct hda_fixup *fix, int action); +void alc_fixup_no_depop_delay(struct hda_codec *codec, + const struct hda_fixup *fix, int action); +void alc_fixup_inv_dmic(struct hda_codec *codec, + const struct hda_fixup *fix, int action); +void alc_fixup_dual_codecs(struct hda_codec *codec, + const struct hda_fixup *fix, int action); +void alc_fixup_bass_chmap(struct hda_codec *codec, + const struct hda_fixup *fix, int action); +void alc_fixup_headset_mode(struct hda_codec *codec, + const struct hda_fixup *fix, int action); +void alc_fixup_headset_mode_no_hp_mic(struct hda_codec *codec, + const struct hda_fixup *fix, int action); +void alc_fixup_headset_mic(struct hda_codec *codec, + const struct hda_fixup *fix, int action); +void alc_update_headset_jack_cb(struct hda_codec *codec, + struct hda_jack_callback *jack); +void alc_update_gpio_led(struct hda_codec *codec, unsigned int mask, + int polarity, bool enabled); +void alc_fixup_hp_gpio_led(struct hda_codec *codec, + int action, + unsigned int mute_mask, + unsigned int micmute_mask); +void alc_fixup_no_jack_detect(struct hda_codec *codec, + const struct hda_fixup *fix, int action); +void alc_fixup_disable_aamix(struct hda_codec *codec, + const struct hda_fixup *fix, int action); +void alc_fixup_auto_mute_via_amp(struct hda_codec *codec, + const struct hda_fixup *fix, int action); + +/* device-specific, but used by multiple codec drivers */ +void alc1220_fixup_gb_dual_codecs(struct hda_codec *codec, + const struct hda_fixup *fix, + int action); +void alc233_alc662_fixup_lenovo_dual_codecs(struct hda_codec *codec, + const struct hda_fixup *fix, + int action); +void alc_fixup_dell_xps13(struct hda_codec *codec, + const struct hda_fixup *fix, int action); + +#endif /* __HDA_REALTEK_H */ |