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 */  | 
