Initial commit

Original modules copied with their dependencies
DKMS config and makefiles created

sq
This commit is contained in:
naoto 2024-01-22 15:45:44 +01:00
commit cc894cefff
16 changed files with 18890 additions and 0 deletions

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
.ccls-cache
.ccls-cache/*

7
hp-wmi/Makefile Normal file
View file

@ -0,0 +1,7 @@
obj-m += hp-wmi.o
all:
make -C /lib/modules/${kernelver}/build M=$(PWD) modules
clean:
make -C /lib/modules/${kernelver}/build M=$(PWD) clean

6
hp-wmi/dkms.conf Normal file
View file

@ -0,0 +1,6 @@
BUILT_MODULE_NAME=hp-wmi
BUILT_MODULE_LOCATION=./
DEST_MODULE_LOCATION=/kernel/drivers/platform/x86/
PACKAGE_NAME=omen-hp-wmi
PACKAGE_VERSION=1.0
AUTOINSTALL=yes

1723
hp-wmi/hp-wmi.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,9 @@
snd-hda-codec-realtek-objs := patch_realtek.o
obj-m += snd-hda-codec-realtek.o
EXTRA_CFLAGS=-I$(PWD)/inc
all:
make -C /lib/modules/${kernelver}/build M=$(PWD) modules
clean:
make -C /lib/modules/${kernelver}/build M=$(PWD) clean

View file

@ -0,0 +1,6 @@
BUILT_MODULE_NAME=snd-hda-codec-realtek
BUILT_MODULE_LOCATION=./
DEST_MODULE_LOCATION=/kernel/sound/pci/hda/
PACKAGE_NAME=omen-snd-hda-codec-realtek
PACKAGE_VERSION=1.0
AUTOINSTALL=yes

View file

@ -0,0 +1,115 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* BIOS auto-parser helper functions for HD-audio
*
* Copyright (c) 2012 Takashi Iwai <tiwai@suse.de>
*/
#ifndef __SOUND_HDA_AUTO_PARSER_H
#define __SOUND_HDA_AUTO_PARSER_H
/*
* Helper for automatic pin configuration
*/
enum {
AUTO_PIN_MIC,
AUTO_PIN_LINE_IN,
AUTO_PIN_CD,
AUTO_PIN_AUX,
AUTO_PIN_LAST
};
enum {
AUTO_PIN_LINE_OUT,
AUTO_PIN_SPEAKER_OUT,
AUTO_PIN_HP_OUT
};
#define AUTO_CFG_MAX_OUTS HDA_MAX_OUTS
#define AUTO_CFG_MAX_INS 18
struct auto_pin_cfg_item {
hda_nid_t pin;
int type;
unsigned int is_headset_mic:1;
unsigned int is_headphone_mic:1; /* Mic-only in headphone jack */
unsigned int has_boost_on_pin:1;
};
struct auto_pin_cfg;
const char *hda_get_autocfg_input_label(struct hda_codec *codec,
const struct auto_pin_cfg *cfg,
int input);
int snd_hda_get_pin_label(struct hda_codec *codec, hda_nid_t nid,
const struct auto_pin_cfg *cfg,
char *label, int maxlen, int *indexp);
enum {
INPUT_PIN_ATTR_UNUSED, /* pin not connected */
INPUT_PIN_ATTR_INT, /* internal mic/line-in */
INPUT_PIN_ATTR_DOCK, /* docking mic/line-in */
INPUT_PIN_ATTR_NORMAL, /* mic/line-in jack */
INPUT_PIN_ATTR_REAR, /* mic/line-in jack in rear */
INPUT_PIN_ATTR_FRONT, /* mic/line-in jack in front */
INPUT_PIN_ATTR_LAST = INPUT_PIN_ATTR_FRONT,
};
int snd_hda_get_input_pin_attr(unsigned int def_conf);
struct auto_pin_cfg {
int line_outs;
/* sorted in the order of Front/Surr/CLFE/Side */
hda_nid_t line_out_pins[AUTO_CFG_MAX_OUTS];
int speaker_outs;
hda_nid_t speaker_pins[AUTO_CFG_MAX_OUTS];
int hp_outs;
int line_out_type; /* AUTO_PIN_XXX_OUT */
hda_nid_t hp_pins[AUTO_CFG_MAX_OUTS];
int num_inputs;
struct auto_pin_cfg_item inputs[AUTO_CFG_MAX_INS];
int dig_outs;
hda_nid_t dig_out_pins[2];
hda_nid_t dig_in_pin;
hda_nid_t mono_out_pin;
int dig_out_type[2]; /* HDA_PCM_TYPE_XXX */
int dig_in_type; /* HDA_PCM_TYPE_XXX */
};
/* bit-flags for snd_hda_parse_pin_def_config() behavior */
#define HDA_PINCFG_NO_HP_FIXUP (1 << 0) /* no HP-split */
#define HDA_PINCFG_NO_LO_FIXUP (1 << 1) /* don't take other outs as LO */
#define HDA_PINCFG_HEADSET_MIC (1 << 2) /* Try to find headset mic; mark seq number as 0xc to trigger */
#define HDA_PINCFG_HEADPHONE_MIC (1 << 3) /* Try to find headphone mic; mark seq number as 0xd to trigger */
int snd_hda_parse_pin_defcfg(struct hda_codec *codec,
struct auto_pin_cfg *cfg,
const hda_nid_t *ignore_nids,
unsigned int cond_flags);
/* older function */
#define snd_hda_parse_pin_def_config(codec, cfg, ignore) \
snd_hda_parse_pin_defcfg(codec, cfg, ignore, 0)
static inline int auto_cfg_hp_outs(const struct auto_pin_cfg *cfg)
{
return (cfg->line_out_type == AUTO_PIN_HP_OUT) ?
cfg->line_outs : cfg->hp_outs;
}
static inline const hda_nid_t *auto_cfg_hp_pins(const struct auto_pin_cfg *cfg)
{
return (cfg->line_out_type == AUTO_PIN_HP_OUT) ?
cfg->line_out_pins : cfg->hp_pins;
}
static inline int auto_cfg_speaker_outs(const struct auto_pin_cfg *cfg)
{
return (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) ?
cfg->line_outs : cfg->speaker_outs;
}
static inline const hda_nid_t *auto_cfg_speaker_pins(const struct auto_pin_cfg *cfg)
{
return (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) ?
cfg->line_out_pins : cfg->speaker_pins;
}
#endif /* __SOUND_HDA_AUTO_PARSER_H */

View file

@ -0,0 +1,19 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* HD audio Component Binding Interface
*
* Copyright (C) 2021 Cirrus Logic, Inc. and
* Cirrus Logic International Semiconductor Ltd.
*/
#include <linux/component.h>
#define HDA_MAX_COMPONENTS 4
#define HDA_MAX_NAME_SIZE 50
struct hda_component {
struct device *dev;
char name[HDA_MAX_NAME_SIZE];
struct hda_codec *codec;
void (*playback_hook)(struct device *dev, int action);
};

View file

@ -0,0 +1,356 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Generic BIOS auto-parser helper functions for HD-audio
*
* Copyright (c) 2012 Takashi Iwai <tiwai@suse.de>
*/
#ifndef __SOUND_HDA_GENERIC_H
#define __SOUND_HDA_GENERIC_H
#include <linux/leds.h>
/* table entry for multi-io paths */
struct hda_multi_io {
hda_nid_t pin; /* multi-io widget pin NID */
hda_nid_t dac; /* DAC to be connected */
unsigned int ctl_in; /* cached input-pin control value */
};
/* Widget connection path
*
* For output, stored in the order of DAC -> ... -> pin,
* for input, pin -> ... -> ADC.
*
* idx[i] contains the source index number to select on of the widget path[i];
* e.g. idx[1] is the index of the DAC (path[0]) selected by path[1] widget
* multi[] indicates whether it's a selector widget with multi-connectors
* (i.e. the connection selection is mandatory)
* vol_ctl and mute_ctl contains the NIDs for the assigned mixers
*/
#define MAX_NID_PATH_DEPTH 10
enum {
NID_PATH_VOL_CTL,
NID_PATH_MUTE_CTL,
NID_PATH_BOOST_CTL,
NID_PATH_NUM_CTLS
};
struct nid_path {
int depth;
hda_nid_t path[MAX_NID_PATH_DEPTH];
unsigned char idx[MAX_NID_PATH_DEPTH];
unsigned char multi[MAX_NID_PATH_DEPTH];
unsigned int ctls[NID_PATH_NUM_CTLS]; /* NID_PATH_XXX_CTL */
bool active:1; /* activated by driver */
bool pin_enabled:1; /* pins are enabled */
bool pin_fixed:1; /* path with fixed pin */
bool stream_enabled:1; /* stream is active */
};
/* mic/line-in auto switching entry */
#define MAX_AUTO_MIC_PINS 3
struct automic_entry {
hda_nid_t pin; /* pin */
int idx; /* imux index, -1 = invalid */
unsigned int attr; /* pin attribute (INPUT_PIN_ATTR_*) */
};
/* active stream id */
enum { STREAM_MULTI_OUT, STREAM_INDEP_HP };
/* PCM hook action */
enum {
HDA_GEN_PCM_ACT_OPEN,
HDA_GEN_PCM_ACT_PREPARE,
HDA_GEN_PCM_ACT_CLEANUP,
HDA_GEN_PCM_ACT_CLOSE,
};
/* DAC assignment badness table */
struct badness_table {
int no_primary_dac; /* no primary DAC */
int no_dac; /* no secondary DACs */
int shared_primary; /* primary DAC is shared with main output */
int shared_surr; /* secondary DAC shared with main or primary */
int shared_clfe; /* third DAC shared with main or primary */
int shared_surr_main; /* secondary DAC sahred with main/DAC0 */
};
extern const struct badness_table hda_main_out_badness;
extern const struct badness_table hda_extra_out_badness;
struct hda_gen_spec {
char stream_name_analog[32]; /* analog PCM stream */
const struct hda_pcm_stream *stream_analog_playback;
const struct hda_pcm_stream *stream_analog_capture;
char stream_name_alt_analog[32]; /* alternative analog PCM stream */
const struct hda_pcm_stream *stream_analog_alt_playback;
const struct hda_pcm_stream *stream_analog_alt_capture;
char stream_name_digital[32]; /* digital PCM stream */
const struct hda_pcm_stream *stream_digital_playback;
const struct hda_pcm_stream *stream_digital_capture;
/* PCM */
unsigned int active_streams;
struct mutex pcm_mutex;
/* playback */
struct hda_multi_out multiout; /* playback set-up
* max_channels, dacs must be set
* dig_out_nid and hp_nid are optional
*/
hda_nid_t alt_dac_nid;
hda_nid_t follower_dig_outs[3]; /* optional - for auto-parsing */
int dig_out_type;
/* capture */
unsigned int num_adc_nids;
hda_nid_t adc_nids[AUTO_CFG_MAX_INS];
hda_nid_t dig_in_nid; /* digital-in NID; optional */
hda_nid_t mixer_nid; /* analog-mixer NID */
hda_nid_t mixer_merge_nid; /* aamix merge-point NID (optional) */
const char *input_labels[HDA_MAX_NUM_INPUTS];
int input_label_idxs[HDA_MAX_NUM_INPUTS];
/* capture setup for dynamic dual-adc switch */
hda_nid_t cur_adc;
unsigned int cur_adc_stream_tag;
unsigned int cur_adc_format;
/* capture source */
struct hda_input_mux input_mux;
unsigned int cur_mux[3];
/* channel model */
/* min_channel_count contains the minimum channel count for primary
* outputs. When multi_ios is set, the channels can be configured
* between min_channel_count and (min_channel_count + multi_ios * 2).
*
* ext_channel_count contains the current channel count of the primary
* out. This varies in the range above.
*
* Meanwhile, const_channel_count is the channel count for all outputs
* including headphone and speakers. It's a constant value, and the
* PCM is set up as max(ext_channel_count, const_channel_count).
*/
int min_channel_count; /* min. channel count for primary out */
int ext_channel_count; /* current channel count for primary */
int const_channel_count; /* channel count for all */
/* PCM information */
struct hda_pcm *pcm_rec[3]; /* used in build_pcms() */
/* dynamic controls, init_verbs and input_mux */
struct auto_pin_cfg autocfg;
struct snd_array kctls;
hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
hda_nid_t imux_pins[HDA_MAX_NUM_INPUTS];
unsigned int dyn_adc_idx[HDA_MAX_NUM_INPUTS];
/* shared hp/mic */
hda_nid_t shared_mic_vref_pin;
hda_nid_t hp_mic_pin;
int hp_mic_mux_idx;
/* DAC/ADC lists */
int num_all_dacs;
hda_nid_t all_dacs[16];
int num_all_adcs;
hda_nid_t all_adcs[AUTO_CFG_MAX_INS];
/* path list */
struct snd_array paths;
/* path indices */
int out_paths[AUTO_CFG_MAX_OUTS];
int hp_paths[AUTO_CFG_MAX_OUTS];
int speaker_paths[AUTO_CFG_MAX_OUTS];
int aamix_out_paths[3];
int digout_paths[AUTO_CFG_MAX_OUTS];
int input_paths[HDA_MAX_NUM_INPUTS][AUTO_CFG_MAX_INS];
int loopback_paths[HDA_MAX_NUM_INPUTS];
int loopback_merge_path;
int digin_path;
/* auto-mic stuff */
int am_num_entries;
struct automic_entry am_entry[MAX_AUTO_MIC_PINS];
/* for pin sensing */
/* current status; set in hda_generic.c */
unsigned int hp_jack_present:1;
unsigned int line_jack_present:1;
unsigned int speaker_muted:1; /* current status of speaker mute */
unsigned int line_out_muted:1; /* current status of LO mute */
/* internal states of automute / autoswitch behavior */
unsigned int auto_mic:1;
unsigned int automute_speaker:1; /* automute speaker outputs */
unsigned int automute_lo:1; /* automute LO outputs */
/* capabilities detected by parser */
unsigned int detect_hp:1; /* Headphone detection enabled */
unsigned int detect_lo:1; /* Line-out detection enabled */
unsigned int automute_speaker_possible:1; /* there are speakers and either LO or HP */
unsigned int automute_lo_possible:1; /* there are line outs and HP */
/* additional parameters set by codec drivers */
unsigned int master_mute:1; /* master mute over all */
unsigned int keep_vref_in_automute:1; /* Don't clear VREF in automute */
unsigned int line_in_auto_switch:1; /* allow line-in auto switch */
unsigned int auto_mute_via_amp:1; /* auto-mute via amp instead of pinctl */
/* parser behavior flags; set before snd_hda_gen_parse_auto_config() */
unsigned int suppress_auto_mute:1; /* suppress input jack auto mute */
unsigned int suppress_auto_mic:1; /* suppress input jack auto switch */
/* other parse behavior flags */
unsigned int need_dac_fix:1; /* need to limit DACs for multi channels */
unsigned int hp_mic:1; /* Allow HP as a mic-in */
unsigned int suppress_hp_mic_detect:1; /* Don't detect HP/mic */
unsigned int no_primary_hp:1; /* Don't prefer HP pins to speaker pins */
unsigned int no_multi_io:1; /* Don't try multi I/O config */
unsigned int multi_cap_vol:1; /* allow multiple capture xxx volumes */
unsigned int inv_dmic_split:1; /* inverted dmic w/a for conexant */
unsigned int own_eapd_ctl:1; /* set EAPD by own function */
unsigned int keep_eapd_on:1; /* don't turn off EAPD automatically */
unsigned int vmaster_mute_led:1; /* add SPK-LED flag to vmaster mute switch */
unsigned int mic_mute_led:1; /* add MIC-LED flag to capture mute switch */
unsigned int indep_hp:1; /* independent HP supported */
unsigned int prefer_hp_amp:1; /* enable HP amp for speaker if any */
unsigned int add_stereo_mix_input:2; /* add aamix as a capture src */
unsigned int add_jack_modes:1; /* add i/o jack mode enum ctls */
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 */
unsigned int dyn_adc_switch:1; /* switch ADCs (for ALC275) */
unsigned int indep_hp_enabled:1; /* independent HP enabled */
unsigned int have_aamix_ctl:1;
unsigned int hp_mic_jack_modes:1;
unsigned int skip_verbs:1; /* don't apply verbs at snd_hda_gen_init() */
/* additional mute flags (only effective with auto_mute_via_amp=1) */
u64 mute_bits;
/* bitmask for skipping volume controls */
u64 out_vol_mask;
/* badness tables for output path evaluations */
const struct badness_table *main_out_badness;
const struct badness_table *extra_out_badness;
/* preferred pin/DAC pairs; an array of paired NIDs */
const hda_nid_t *preferred_dacs;
/* loopback mixing mode */
bool aamix_mode;
/* digital beep */
hda_nid_t beep_nid;
/* for virtual master */
hda_nid_t vmaster_nid;
unsigned int vmaster_tlv[4];
struct hda_vmaster_mute_hook vmaster_mute;
struct hda_loopback_check loopback;
struct snd_array loopback_list;
/* multi-io */
int multi_ios;
struct hda_multi_io multi_io[4];
/* hooks */
void (*init_hook)(struct hda_codec *codec);
void (*automute_hook)(struct hda_codec *codec);
void (*cap_sync_hook)(struct hda_codec *codec,
struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
/* PCM hooks */
void (*pcm_playback_hook)(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
struct snd_pcm_substream *substream,
int action);
void (*pcm_capture_hook)(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
struct snd_pcm_substream *substream,
int action);
/* automute / autoswitch hooks */
void (*hp_automute_hook)(struct hda_codec *codec,
struct hda_jack_callback *cb);
void (*line_automute_hook)(struct hda_codec *codec,
struct hda_jack_callback *cb);
void (*mic_autoswitch_hook)(struct hda_codec *codec,
struct hda_jack_callback *cb);
/* leds */
struct led_classdev *led_cdevs[NUM_AUDIO_LEDS];
};
/* values for add_stereo_mix_input flag */
enum {
HDA_HINT_STEREO_MIX_DISABLE, /* No stereo mix input */
HDA_HINT_STEREO_MIX_ENABLE, /* Add stereo mix input */
HDA_HINT_STEREO_MIX_AUTO, /* Add only if auto-mic is disabled */
};
int snd_hda_gen_spec_init(struct hda_gen_spec *spec);
int snd_hda_gen_init(struct hda_codec *codec);
void snd_hda_gen_free(struct hda_codec *codec);
int snd_hda_get_path_idx(struct hda_codec *codec, struct nid_path *path);
struct nid_path *snd_hda_get_path_from_idx(struct hda_codec *codec, int idx);
struct nid_path *
snd_hda_add_new_path(struct hda_codec *codec, hda_nid_t from_nid,
hda_nid_t to_nid, int anchor_nid);
void snd_hda_activate_path(struct hda_codec *codec, struct nid_path *path,
bool enable, bool add_aamix);
struct snd_kcontrol_new *
snd_hda_gen_add_kctl(struct hda_gen_spec *spec, const char *name,
const struct snd_kcontrol_new *temp);
int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
struct auto_pin_cfg *cfg);
int snd_hda_gen_build_controls(struct hda_codec *codec);
int snd_hda_gen_build_pcms(struct hda_codec *codec);
/* standard jack event callbacks */
void snd_hda_gen_hp_automute(struct hda_codec *codec,
struct hda_jack_callback *jack);
void snd_hda_gen_line_automute(struct hda_codec *codec,
struct hda_jack_callback *jack);
void snd_hda_gen_mic_autoswitch(struct hda_codec *codec,
struct hda_jack_callback *jack);
void snd_hda_gen_update_outputs(struct hda_codec *codec);
#ifdef CONFIG_PM
int snd_hda_gen_check_power_status(struct hda_codec *codec, hda_nid_t nid);
#endif
unsigned int snd_hda_gen_path_power_filter(struct hda_codec *codec,
hda_nid_t nid,
unsigned int power_state);
void snd_hda_gen_stream_pm(struct hda_codec *codec, hda_nid_t nid, bool on);
int snd_hda_gen_fix_pin_power(struct hda_codec *codec, hda_nid_t pin);
int snd_hda_gen_add_mute_led_cdev(struct hda_codec *codec,
int (*callback)(struct led_classdev *,
enum led_brightness));
int snd_hda_gen_add_micmute_led_cdev(struct hda_codec *codec,
int (*callback)(struct led_classdev *,
enum led_brightness));
#endif /* __SOUND_HDA_GENERIC_H */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,195 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Jack-detection handling for HD-audio
*
* Copyright (c) 2011 Takashi Iwai <tiwai@suse.de>
*/
#ifndef __SOUND_HDA_JACK_H
#define __SOUND_HDA_JACK_H
#include <linux/err.h>
#include <sound/jack.h>
struct auto_pin_cfg;
struct hda_jack_tbl;
struct hda_jack_callback;
typedef void (*hda_jack_callback_fn) (struct hda_codec *, struct hda_jack_callback *);
struct hda_jack_callback {
hda_nid_t nid;
int dev_id;
hda_jack_callback_fn func;
unsigned int private_data; /* arbitrary data */
unsigned int unsol_res; /* unsolicited event bits */
struct hda_jack_tbl *jack; /* associated jack entry */
struct hda_jack_callback *next;
};
struct hda_jack_tbl {
hda_nid_t nid;
int dev_id;
unsigned char tag; /* unsol event tag */
struct hda_jack_callback *callback;
/* jack-detection stuff */
unsigned int pin_sense; /* cached pin-sense value */
unsigned int jack_detect:1; /* capable of jack-detection? */
unsigned int jack_dirty:1; /* needs to update? */
unsigned int phantom_jack:1; /* a fixed, always present port? */
unsigned int block_report:1; /* in a transitional state - do not report to userspace */
hda_nid_t gating_jack; /* valid when gating jack plugged */
hda_nid_t gated_jack; /* gated is dependent on this jack */
hda_nid_t key_report_jack; /* key reports to this jack */
int type;
int button_state;
struct snd_jack *jack;
};
struct hda_jack_keymap {
enum snd_jack_types type;
int key;
};
struct hda_jack_tbl *
snd_hda_jack_tbl_get_mst(struct hda_codec *codec, hda_nid_t nid, int dev_id);
/**
* snd_hda_jack_tbl_get - query the jack-table entry for the given NID
* @codec: the HDA codec
* @nid: pin NID to refer to
*/
static inline struct hda_jack_tbl *
snd_hda_jack_tbl_get(struct hda_codec *codec, hda_nid_t nid)
{
return snd_hda_jack_tbl_get_mst(codec, nid, 0);
}
struct hda_jack_tbl *
snd_hda_jack_tbl_get_from_tag(struct hda_codec *codec,
unsigned char tag, int dev_id);
void snd_hda_jack_tbl_disconnect(struct hda_codec *codec);
void snd_hda_jack_tbl_clear(struct hda_codec *codec);
void snd_hda_jack_set_dirty_all(struct hda_codec *codec);
int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid,
int dev_id);
struct hda_jack_callback *
snd_hda_jack_detect_enable_callback_mst(struct hda_codec *codec, hda_nid_t nid,
int dev_id, hda_jack_callback_fn func);
/**
* snd_hda_jack_detect_enable - enable the jack-detection
* @codec: the HDA codec
* @nid: pin NID to enable
* @func: callback function to register
*
* In the case of error, the return value will be a pointer embedded with
* errno. Check and handle the return value appropriately with standard
* macros such as @IS_ERR() and @PTR_ERR().
*/
static inline struct hda_jack_callback *
snd_hda_jack_detect_enable_callback(struct hda_codec *codec, hda_nid_t nid,
hda_jack_callback_fn cb)
{
return snd_hda_jack_detect_enable_callback_mst(codec, nid, 0, cb);
}
int snd_hda_jack_set_gating_jack(struct hda_codec *codec, hda_nid_t gated_nid,
hda_nid_t gating_nid);
int snd_hda_jack_bind_keymap(struct hda_codec *codec, hda_nid_t key_nid,
const struct hda_jack_keymap *keymap,
hda_nid_t jack_nid);
void snd_hda_jack_set_button_state(struct hda_codec *codec, hda_nid_t jack_nid,
int button_state);
u32 snd_hda_jack_pin_sense(struct hda_codec *codec, hda_nid_t nid, int dev_id);
/* the jack state returned from snd_hda_jack_detect_state() */
enum {
HDA_JACK_NOT_PRESENT, HDA_JACK_PRESENT, HDA_JACK_PHANTOM,
};
int snd_hda_jack_detect_state_mst(struct hda_codec *codec, hda_nid_t nid,
int dev_id);
/**
* snd_hda_jack_detect_state - query pin Presence Detect status
* @codec: the CODEC to sense
* @nid: the pin NID to sense
*
* Query and return the pin's Presence Detect status, as either
* HDA_JACK_NOT_PRESENT, HDA_JACK_PRESENT or HDA_JACK_PHANTOM.
*/
static inline int
snd_hda_jack_detect_state(struct hda_codec *codec, hda_nid_t nid)
{
return snd_hda_jack_detect_state_mst(codec, nid, 0);
}
/**
* snd_hda_jack_detect_mst - Detect the jack
* @codec: the HDA codec
* @nid: pin NID to check jack detection
* @dev_id: pin device entry id
*/
static inline bool
snd_hda_jack_detect_mst(struct hda_codec *codec, hda_nid_t nid, int dev_id)
{
return snd_hda_jack_detect_state_mst(codec, nid, dev_id) !=
HDA_JACK_NOT_PRESENT;
}
/**
* snd_hda_jack_detect - Detect the jack
* @codec: the HDA codec
* @nid: pin NID to check jack detection
*/
static inline bool
snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid)
{
return snd_hda_jack_detect_mst(codec, nid, 0);
}
bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid);
int snd_hda_jack_add_kctl_mst(struct hda_codec *codec, hda_nid_t nid,
int dev_id, const char *name, bool phantom_jack,
int type, const struct hda_jack_keymap *keymap);
/**
* snd_hda_jack_add_kctl - Add a kctl for the given pin
* @codec: the HDA codec
* @nid: pin NID to assign
* @name: string name for the jack
* @phantom_jack: flag to deal as a phantom jack
* @type: jack type bits to be reported, 0 for guessing from pincfg
* @keymap: optional jack / key mapping
*
* This assigns a jack-detection kctl to the given pin. The kcontrol
* will have the given name and index.
*/
static inline int
snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid,
const char *name, bool phantom_jack,
int type, const struct hda_jack_keymap *keymap)
{
return snd_hda_jack_add_kctl_mst(codec, nid, 0,
name, phantom_jack, type, keymap);
}
int snd_hda_jack_add_kctls(struct hda_codec *codec,
const struct auto_pin_cfg *cfg);
void snd_hda_jack_report_sync(struct hda_codec *codec);
void snd_hda_jack_unsol_event(struct hda_codec *codec, unsigned int res);
void snd_hda_jack_poll_all(struct hda_codec *codec);
#endif /* __SOUND_HDA_JACK_H */

View file

@ -0,0 +1,737 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Universal Interface for Intel High Definition Audio Codec
*
* Local helper functions
*
* Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
*/
#ifndef __SOUND_HDA_LOCAL_H
#define __SOUND_HDA_LOCAL_H
/* We abuse kcontrol_new.subdev field to pass the NID corresponding to
* the given new control. If id.subdev has a bit flag HDA_SUBDEV_NID_FLAG,
* snd_hda_ctl_add() takes the lower-bit subdev value as a valid NID.
*
* Note that the subdevice field is cleared again before the real registration
* in snd_hda_ctl_add(), so that this value won't appear in the outside.
*/
#define HDA_SUBDEV_NID_FLAG (1U << 31)
#define HDA_SUBDEV_AMP_FLAG (1U << 30)
/*
* for mixer controls
*/
#define HDA_COMPOSE_AMP_VAL_OFS(nid,chs,idx,dir,ofs) \
((nid) | ((chs)<<16) | ((dir)<<18) | ((idx)<<19) | ((ofs)<<23))
#define HDA_AMP_VAL_MIN_MUTE (1<<29)
#define HDA_COMPOSE_AMP_VAL(nid,chs,idx,dir) \
HDA_COMPOSE_AMP_VAL_OFS(nid, chs, idx, dir, 0)
/* mono volume with index (index=0,1,...) (channel=1,2) */
#define HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, channel, xindex, dir, flags) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \
.subdevice = HDA_SUBDEV_AMP_FLAG, \
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, \
.info = snd_hda_mixer_amp_volume_info, \
.get = snd_hda_mixer_amp_volume_get, \
.put = snd_hda_mixer_amp_volume_put, \
.tlv = { .c = snd_hda_mixer_amp_tlv }, \
.private_value = HDA_COMPOSE_AMP_VAL(nid, channel, xindex, dir) | flags }
/* stereo volume with index */
#define HDA_CODEC_VOLUME_IDX(xname, xcidx, nid, xindex, direction) \
HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, 3, xindex, direction, 0)
/* mono volume */
#define HDA_CODEC_VOLUME_MONO(xname, nid, channel, xindex, direction) \
HDA_CODEC_VOLUME_MONO_IDX(xname, 0, nid, channel, xindex, direction, 0)
/* stereo volume */
#define HDA_CODEC_VOLUME(xname, nid, xindex, direction) \
HDA_CODEC_VOLUME_MONO(xname, nid, 3, xindex, direction)
/* stereo volume with min=mute */
#define HDA_CODEC_VOLUME_MIN_MUTE(xname, nid, xindex, direction) \
HDA_CODEC_VOLUME_MONO_IDX(xname, 0, nid, 3, xindex, direction, \
HDA_AMP_VAL_MIN_MUTE)
/* mono mute switch with index (index=0,1,...) (channel=1,2) */
#define HDA_CODEC_MUTE_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \
.subdevice = HDA_SUBDEV_AMP_FLAG, \
.info = snd_hda_mixer_amp_switch_info, \
.get = snd_hda_mixer_amp_switch_get, \
.put = snd_hda_mixer_amp_switch_put, \
.private_value = HDA_COMPOSE_AMP_VAL(nid, channel, xindex, direction) }
/* stereo mute switch with index */
#define HDA_CODEC_MUTE_IDX(xname, xcidx, nid, xindex, direction) \
HDA_CODEC_MUTE_MONO_IDX(xname, xcidx, nid, 3, xindex, direction)
/* mono mute switch */
#define HDA_CODEC_MUTE_MONO(xname, nid, channel, xindex, direction) \
HDA_CODEC_MUTE_MONO_IDX(xname, 0, nid, channel, xindex, direction)
/* stereo mute switch */
#define HDA_CODEC_MUTE(xname, nid, xindex, direction) \
HDA_CODEC_MUTE_MONO(xname, nid, 3, xindex, direction)
#ifdef CONFIG_SND_HDA_INPUT_BEEP
/* special beep mono mute switch with index (index=0,1,...) (channel=1,2) */
#define HDA_CODEC_MUTE_BEEP_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \
.subdevice = HDA_SUBDEV_AMP_FLAG, \
.info = snd_hda_mixer_amp_switch_info, \
.get = snd_hda_mixer_amp_switch_get_beep, \
.put = snd_hda_mixer_amp_switch_put_beep, \
.private_value = HDA_COMPOSE_AMP_VAL(nid, channel, xindex, direction) }
#else
/* no digital beep - just the standard one */
#define HDA_CODEC_MUTE_BEEP_MONO_IDX(xname, xcidx, nid, ch, xidx, dir) \
HDA_CODEC_MUTE_MONO_IDX(xname, xcidx, nid, ch, xidx, dir)
#endif /* CONFIG_SND_HDA_INPUT_BEEP */
/* special beep mono mute switch */
#define HDA_CODEC_MUTE_BEEP_MONO(xname, nid, channel, xindex, direction) \
HDA_CODEC_MUTE_BEEP_MONO_IDX(xname, 0, nid, channel, xindex, direction)
/* special beep stereo mute switch */
#define HDA_CODEC_MUTE_BEEP(xname, nid, xindex, direction) \
HDA_CODEC_MUTE_BEEP_MONO(xname, nid, 3, xindex, direction)
extern const char *snd_hda_pcm_type_name[];
int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo);
int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
unsigned int size, unsigned int __user *_tlv);
int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo);
int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
#ifdef CONFIG_SND_HDA_INPUT_BEEP
int snd_hda_mixer_amp_switch_get_beep(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
int snd_hda_mixer_amp_switch_put_beep(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
#endif
/* lowlevel accessor with caching; use carefully */
#define snd_hda_codec_amp_read(codec, nid, ch, dir, idx) \
snd_hdac_regmap_get_amp(&(codec)->core, nid, ch, dir, idx)
int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid,
int ch, int dir, int idx, int mask, int val);
int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
int direction, int idx, int mask, int val);
int snd_hda_codec_amp_init(struct hda_codec *codec, hda_nid_t nid, int ch,
int direction, int idx, int mask, int val);
int snd_hda_codec_amp_init_stereo(struct hda_codec *codec, hda_nid_t nid,
int dir, int idx, int mask, int val);
void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir,
unsigned int *tlv);
struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
const char *name);
int __snd_hda_add_vmaster(struct hda_codec *codec, char *name,
unsigned int *tlv, const char * const *followers,
const char *suffix, bool init_follower_vol,
unsigned int access, struct snd_kcontrol **ctl_ret);
#define snd_hda_add_vmaster(codec, name, tlv, followers, suffix, access) \
__snd_hda_add_vmaster(codec, name, tlv, followers, suffix, true, access, NULL)
int snd_hda_codec_reset(struct hda_codec *codec);
void snd_hda_codec_disconnect_pcms(struct hda_codec *codec);
#define snd_hda_regmap_sync(codec) snd_hdac_regmap_sync(&(codec)->core)
struct hda_vmaster_mute_hook {
/* below two fields must be filled by the caller of
* snd_hda_add_vmaster_hook() beforehand
*/
struct snd_kcontrol *sw_kctl;
void (*hook)(void *, int);
/* below are initialized automatically */
struct hda_codec *codec;
};
int snd_hda_add_vmaster_hook(struct hda_codec *codec,
struct hda_vmaster_mute_hook *hook);
void snd_hda_sync_vmaster_hook(struct hda_vmaster_mute_hook *hook);
/* amp value bits */
#define HDA_AMP_MUTE 0x80
#define HDA_AMP_UNMUTE 0x00
#define HDA_AMP_VOLMASK 0x7f
/*
* SPDIF I/O
*/
int snd_hda_create_dig_out_ctls(struct hda_codec *codec,
hda_nid_t associated_nid,
hda_nid_t cvt_nid, int type);
#define snd_hda_create_spdif_out_ctls(codec, anid, cnid) \
snd_hda_create_dig_out_ctls(codec, anid, cnid, HDA_PCM_TYPE_SPDIF)
int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid);
/*
* input MUX helper
*/
#define HDA_MAX_NUM_INPUTS 36
struct hda_input_mux_item {
char label[32];
unsigned int index;
};
struct hda_input_mux {
unsigned int num_items;
struct hda_input_mux_item items[HDA_MAX_NUM_INPUTS];
};
int snd_hda_input_mux_info(const struct hda_input_mux *imux,
struct snd_ctl_elem_info *uinfo);
int snd_hda_input_mux_put(struct hda_codec *codec,
const struct hda_input_mux *imux,
struct snd_ctl_elem_value *ucontrol, hda_nid_t nid,
unsigned int *cur_val);
int snd_hda_add_imux_item(struct hda_codec *codec,
struct hda_input_mux *imux, const char *label,
int index, int *type_idx);
/*
* Multi-channel / digital-out PCM helper
*/
enum { HDA_FRONT, HDA_REAR, HDA_CLFE, HDA_SIDE }; /* index for dac_nidx */
enum { HDA_DIG_NONE, HDA_DIG_EXCLUSIVE, HDA_DIG_ANALOG_DUP }; /* dig_out_used */
#define HDA_MAX_OUTS 5
struct hda_multi_out {
int num_dacs; /* # of DACs, must be more than 1 */
const hda_nid_t *dac_nids; /* DAC list */
hda_nid_t hp_nid; /* optional DAC for HP, 0 when not exists */
hda_nid_t hp_out_nid[HDA_MAX_OUTS]; /* DACs for multiple HPs */
hda_nid_t extra_out_nid[HDA_MAX_OUTS]; /* other (e.g. speaker) DACs */
hda_nid_t dig_out_nid; /* digital out audio widget */
const hda_nid_t *follower_dig_outs;
int max_channels; /* currently supported analog channels */
int dig_out_used; /* current usage of digital out (HDA_DIG_XXX) */
int no_share_stream; /* don't share a stream with multiple pins */
int share_spdif; /* share SPDIF pin */
/* PCM information for both analog and SPDIF DACs */
unsigned int analog_rates;
unsigned int analog_maxbps;
u64 analog_formats;
unsigned int spdif_rates;
unsigned int spdif_maxbps;
u64 spdif_formats;
};
int snd_hda_create_spdif_share_sw(struct hda_codec *codec,
struct hda_multi_out *mout);
int snd_hda_multi_out_dig_open(struct hda_codec *codec,
struct hda_multi_out *mout);
int snd_hda_multi_out_dig_close(struct hda_codec *codec,
struct hda_multi_out *mout);
int snd_hda_multi_out_dig_prepare(struct hda_codec *codec,
struct hda_multi_out *mout,
unsigned int stream_tag,
unsigned int format,
struct snd_pcm_substream *substream);
int snd_hda_multi_out_dig_cleanup(struct hda_codec *codec,
struct hda_multi_out *mout);
int snd_hda_multi_out_analog_open(struct hda_codec *codec,
struct hda_multi_out *mout,
struct snd_pcm_substream *substream,
struct hda_pcm_stream *hinfo);
int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
struct hda_multi_out *mout,
unsigned int stream_tag,
unsigned int format,
struct snd_pcm_substream *substream);
int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
struct hda_multi_out *mout);
/*
* generic proc interface
*/
#ifdef CONFIG_SND_PROC_FS
int snd_hda_codec_proc_new(struct hda_codec *codec);
#else
static inline int snd_hda_codec_proc_new(struct hda_codec *codec) { return 0; }
#endif
#define SND_PRINT_BITS_ADVISED_BUFSIZE 16
void snd_print_pcm_bits(int pcm, char *buf, int buflen);
/*
* Misc
*/
int snd_hda_add_new_ctls(struct hda_codec *codec,
const struct snd_kcontrol_new *knew);
/*
* Fix-up pin default configurations and add default verbs
*/
struct hda_pintbl {
hda_nid_t nid;
u32 val;
};
struct hda_model_fixup {
const int id;
const char *name;
};
struct hda_fixup {
int type;
bool chained:1; /* call the chained fixup(s) after this */
bool chained_before:1; /* call the chained fixup(s) before this */
int chain_id;
union {
const struct hda_pintbl *pins;
const struct hda_verb *verbs;
void (*func)(struct hda_codec *codec,
const struct hda_fixup *fix,
int action);
} v;
};
struct snd_hda_pin_quirk {
unsigned int codec; /* Codec vendor/device ID */
unsigned short subvendor; /* PCI subvendor ID */
const struct hda_pintbl *pins; /* list of matching pins */
#ifdef CONFIG_SND_DEBUG_VERBOSE
const char *name;
#endif
int value; /* quirk value */
};
#ifdef CONFIG_SND_DEBUG_VERBOSE
#define SND_HDA_PIN_QUIRK(_codec, _subvendor, _name, _value, _pins...) \
{ .codec = _codec,\
.subvendor = _subvendor,\
.name = _name,\
.value = _value,\
.pins = (const struct hda_pintbl[]) { _pins, {0, 0}} \
}
#else
#define SND_HDA_PIN_QUIRK(_codec, _subvendor, _name, _value, _pins...) \
{ .codec = _codec,\
.subvendor = _subvendor,\
.value = _value,\
.pins = (const struct hda_pintbl[]) { _pins, {0, 0}} \
}
#endif
#define HDA_FIXUP_ID_NOT_SET -1
#define HDA_FIXUP_ID_NO_FIXUP -2
/* fixup types */
enum {
HDA_FIXUP_INVALID,
HDA_FIXUP_PINS,
HDA_FIXUP_VERBS,
HDA_FIXUP_FUNC,
HDA_FIXUP_PINCTLS,
};
/* fixup action definitions */
enum {
HDA_FIXUP_ACT_PRE_PROBE,
HDA_FIXUP_ACT_PROBE,
HDA_FIXUP_ACT_INIT,
HDA_FIXUP_ACT_BUILD,
HDA_FIXUP_ACT_FREE,
};
int snd_hda_add_verbs(struct hda_codec *codec, const struct hda_verb *list);
void snd_hda_apply_verbs(struct hda_codec *codec);
void snd_hda_apply_pincfgs(struct hda_codec *codec,
const struct hda_pintbl *cfg);
void snd_hda_apply_fixup(struct hda_codec *codec, int action);
void __snd_hda_apply_fixup(struct hda_codec *codec, int id, int action, int depth);
void snd_hda_pick_fixup(struct hda_codec *codec,
const struct hda_model_fixup *models,
const struct snd_pci_quirk *quirk,
const struct hda_fixup *fixlist);
void snd_hda_pick_pin_fixup(struct hda_codec *codec,
const struct snd_hda_pin_quirk *pin_quirk,
const struct hda_fixup *fixlist,
bool match_all_pins);
/* helper macros to retrieve pin default-config values */
#define get_defcfg_connect(cfg) \
((cfg & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT)
#define get_defcfg_association(cfg) \
((cfg & AC_DEFCFG_DEF_ASSOC) >> AC_DEFCFG_ASSOC_SHIFT)
#define get_defcfg_location(cfg) \
((cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT)
#define get_defcfg_sequence(cfg) \
(cfg & AC_DEFCFG_SEQUENCE)
#define get_defcfg_device(cfg) \
((cfg & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT)
#define get_defcfg_misc(cfg) \
((cfg & AC_DEFCFG_MISC) >> AC_DEFCFG_MISC_SHIFT)
/* amp values */
#define AMP_IN_MUTE(idx) (0x7080 | ((idx)<<8))
#define AMP_IN_UNMUTE(idx) (0x7000 | ((idx)<<8))
#define AMP_OUT_MUTE 0xb080
#define AMP_OUT_UNMUTE 0xb000
#define AMP_OUT_ZERO 0xb000
/* pinctl values */
#define PIN_IN (AC_PINCTL_IN_EN)
#define PIN_VREFHIZ (AC_PINCTL_IN_EN | AC_PINCTL_VREF_HIZ)
#define PIN_VREF50 (AC_PINCTL_IN_EN | AC_PINCTL_VREF_50)
#define PIN_VREFGRD (AC_PINCTL_IN_EN | AC_PINCTL_VREF_GRD)
#define PIN_VREF80 (AC_PINCTL_IN_EN | AC_PINCTL_VREF_80)
#define PIN_VREF100 (AC_PINCTL_IN_EN | AC_PINCTL_VREF_100)
#define PIN_OUT (AC_PINCTL_OUT_EN)
#define PIN_HP (AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN)
#define PIN_HP_AMP (AC_PINCTL_HP_EN)
unsigned int snd_hda_get_default_vref(struct hda_codec *codec, hda_nid_t pin);
unsigned int snd_hda_correct_pin_ctl(struct hda_codec *codec,
hda_nid_t pin, unsigned int val);
int _snd_hda_set_pin_ctl(struct hda_codec *codec, hda_nid_t pin,
unsigned int val, bool cached);
/**
* _snd_hda_set_pin_ctl - Set a pin-control value safely
* @codec: the codec instance
* @pin: the pin NID to set the control
* @val: the pin-control value (AC_PINCTL_* bits)
*
* This function sets the pin-control value to the given pin, but
* filters out the invalid pin-control bits when the pin has no such
* capabilities. For example, when PIN_HP is passed but the pin has no
* HP-drive capability, the HP bit is omitted.
*
* The function doesn't check the input VREF capability bits, though.
* Use snd_hda_get_default_vref() to guess the right value.
* Also, this function is only for analog pins, not for HDMI pins.
*/
static inline int
snd_hda_set_pin_ctl(struct hda_codec *codec, hda_nid_t pin, unsigned int val)
{
return _snd_hda_set_pin_ctl(codec, pin, val, false);
}
/**
* snd_hda_set_pin_ctl_cache - Set a pin-control value safely
* @codec: the codec instance
* @pin: the pin NID to set the control
* @val: the pin-control value (AC_PINCTL_* bits)
*
* Just like snd_hda_set_pin_ctl() but write to cache as well.
*/
static inline int
snd_hda_set_pin_ctl_cache(struct hda_codec *codec, hda_nid_t pin,
unsigned int val)
{
return _snd_hda_set_pin_ctl(codec, pin, val, true);
}
int snd_hda_codec_get_pin_target(struct hda_codec *codec, hda_nid_t nid);
int snd_hda_codec_set_pin_target(struct hda_codec *codec, hda_nid_t nid,
unsigned int val);
#define for_each_hda_codec_node(nid, codec) \
for ((nid) = (codec)->core.start_nid; (nid) < (codec)->core.end_nid; (nid)++)
/* Set the codec power_state flag to indicate to allow unsol event handling;
* see hda_codec_unsol_event() in hda_bind.c. Calling this might confuse the
* state tracking, so use with care.
*/
static inline void snd_hda_codec_allow_unsol_events(struct hda_codec *codec)
{
codec->core.dev.power.power_state = PMSG_ON;
}
/*
* get widget capabilities
*/
static inline u32 get_wcaps(struct hda_codec *codec, hda_nid_t nid)
{
if (nid < codec->core.start_nid ||
nid >= codec->core.start_nid + codec->core.num_nodes)
return 0;
return codec->wcaps[nid - codec->core.start_nid];
}
/* get the widget type from widget capability bits */
static inline int get_wcaps_type(unsigned int wcaps)
{
if (!wcaps)
return -1; /* invalid type */
return (wcaps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
}
static inline unsigned int get_wcaps_channels(u32 wcaps)
{
unsigned int chans;
chans = (wcaps & AC_WCAP_CHAN_CNT_EXT) >> 13;
chans = ((chans << 1) | 1) + 1;
return chans;
}
static inline void snd_hda_override_wcaps(struct hda_codec *codec,
hda_nid_t nid, u32 val)
{
if (nid >= codec->core.start_nid &&
nid < codec->core.start_nid + codec->core.num_nodes)
codec->wcaps[nid - codec->core.start_nid] = val;
}
u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction);
int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
unsigned int caps);
/**
* snd_hda_query_pin_caps - Query PIN capabilities
* @codec: the HD-auio codec
* @nid: the NID to query
*
* Query PIN capabilities for the given widget.
* Returns the obtained capability bits.
*
* When cap bits have been already read, this doesn't read again but
* returns the cached value.
*/
static inline u32
snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid)
{
return snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
}
/**
* snd_hda_override_pin_caps - Override the pin capabilities
* @codec: the CODEC
* @nid: the NID to override
* @caps: the capability bits to set
*
* Override the cached PIN capabilitiy bits value by the given one.
*
* Returns zero if successful or a negative error code.
*/
static inline int
snd_hda_override_pin_caps(struct hda_codec *codec, hda_nid_t nid,
unsigned int caps)
{
return snd_hdac_override_parm(&codec->core, nid, AC_PAR_PIN_CAP, caps);
}
bool snd_hda_check_amp_caps(struct hda_codec *codec, hda_nid_t nid,
int dir, unsigned int bits);
#define nid_has_mute(codec, nid, dir) \
snd_hda_check_amp_caps(codec, nid, dir, (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE))
#define nid_has_volume(codec, nid, dir) \
snd_hda_check_amp_caps(codec, nid, dir, AC_AMPCAP_NUM_STEPS)
/* flags for hda_nid_item */
#define HDA_NID_ITEM_AMP (1<<0)
struct hda_nid_item {
struct snd_kcontrol *kctl;
unsigned int index;
hda_nid_t nid;
unsigned short flags;
};
int snd_hda_ctl_add(struct hda_codec *codec, hda_nid_t nid,
struct snd_kcontrol *kctl);
int snd_hda_add_nid(struct hda_codec *codec, struct snd_kcontrol *kctl,
unsigned int index, hda_nid_t nid);
void snd_hda_ctls_clear(struct hda_codec *codec);
/*
* hwdep interface
*/
#ifdef CONFIG_SND_HDA_HWDEP
int snd_hda_create_hwdep(struct hda_codec *codec);
#else
static inline int snd_hda_create_hwdep(struct hda_codec *codec) { return 0; }
#endif
void snd_hda_sysfs_init(struct hda_codec *codec);
void snd_hda_sysfs_clear(struct hda_codec *codec);
extern const struct attribute_group *snd_hda_dev_attr_groups[];
#ifdef CONFIG_SND_HDA_RECONFIG
const char *snd_hda_get_hint(struct hda_codec *codec, const char *key);
int snd_hda_get_bool_hint(struct hda_codec *codec, const char *key);
int snd_hda_get_int_hint(struct hda_codec *codec, const char *key, int *valp);
#else
static inline
const char *snd_hda_get_hint(struct hda_codec *codec, const char *key)
{
return NULL;
}
static inline
int snd_hda_get_bool_hint(struct hda_codec *codec, const char *key)
{
return -ENOENT;
}
static inline
int snd_hda_get_int_hint(struct hda_codec *codec, const char *key, int *valp)
{
return -ENOENT;
}
#endif
/*
* power-management
*/
void snd_hda_schedule_power_save(struct hda_codec *codec);
struct hda_amp_list {
hda_nid_t nid;
unsigned char dir;
unsigned char idx;
};
struct hda_loopback_check {
const struct hda_amp_list *amplist;
int power_on;
};
int snd_hda_check_amp_list_power(struct hda_codec *codec,
struct hda_loopback_check *check,
hda_nid_t nid);
/* check whether the actual power state matches with the target state */
static inline bool
snd_hda_check_power_state(struct hda_codec *codec, hda_nid_t nid,
unsigned int target_state)
{
return snd_hdac_check_power_state(&codec->core, nid, target_state);
}
static inline unsigned int snd_hda_sync_power_state(struct hda_codec *codec,
hda_nid_t nid,
unsigned int target_state)
{
return snd_hdac_sync_power_state(&codec->core, nid, target_state);
}
unsigned int snd_hda_codec_eapd_power_filter(struct hda_codec *codec,
hda_nid_t nid,
unsigned int power_state);
void snd_hda_codec_shutdown(struct hda_codec *codec);
/*
* AMP control callbacks
*/
/* retrieve parameters from private_value */
#define get_amp_nid_(pv) ((pv) & 0xffff)
#define get_amp_nid(kc) get_amp_nid_((kc)->private_value)
#define get_amp_channels(kc) (((kc)->private_value >> 16) & 0x3)
#define get_amp_direction_(pv) (((pv) >> 18) & 0x1)
#define get_amp_direction(kc) get_amp_direction_((kc)->private_value)
#define get_amp_index_(pv) (((pv) >> 19) & 0xf)
#define get_amp_index(kc) get_amp_index_((kc)->private_value)
#define get_amp_offset(kc) (((kc)->private_value >> 23) & 0x3f)
#define get_amp_min_mute(kc) (((kc)->private_value >> 29) & 0x1)
/*
* enum control helper
*/
int snd_hda_enum_helper_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo,
int num_items, const char * const *texts);
#define snd_hda_enum_bool_helper_info(kcontrol, uinfo) \
snd_hda_enum_helper_info(kcontrol, uinfo, 0, NULL)
/*
* CEA Short Audio Descriptor data
*/
struct cea_sad {
int channels;
int format; /* (format == 0) indicates invalid SAD */
int rates;
int sample_bits; /* for LPCM */
int max_bitrate; /* for AC3...ATRAC */
int profile; /* for WMAPRO */
};
#define ELD_FIXED_BYTES 20
#define ELD_MAX_SIZE 256
#define ELD_MAX_MNL 16
#define ELD_MAX_SAD 16
/*
* ELD: EDID Like Data
*/
struct parsed_hdmi_eld {
/*
* all fields will be cleared before updating ELD
*/
int baseline_len;
int eld_ver;
int cea_edid_ver;
char monitor_name[ELD_MAX_MNL + 1];
int manufacture_id;
int product_id;
u64 port_id;
int support_hdcp;
int support_ai;
int conn_type;
int aud_synch_delay;
int spk_alloc;
int sad_count;
struct cea_sad sad[ELD_MAX_SAD];
};
struct hdmi_eld {
bool monitor_present;
bool eld_valid;
int eld_size;
char eld_buffer[ELD_MAX_SIZE];
struct parsed_hdmi_eld info;
};
int snd_hdmi_get_eld_size(struct hda_codec *codec, hda_nid_t nid);
int snd_hdmi_get_eld(struct hda_codec *codec, hda_nid_t nid,
unsigned char *buf, int *eld_size);
int snd_hdmi_parse_eld(struct hda_codec *codec, struct parsed_hdmi_eld *e,
const unsigned char *buf, int size);
void snd_hdmi_show_eld(struct hda_codec *codec, struct parsed_hdmi_eld *e);
void snd_hdmi_eld_update_pcm_info(struct parsed_hdmi_eld *e,
struct hda_pcm_stream *hinfo);
int snd_hdmi_get_eld_ati(struct hda_codec *codec, hda_nid_t nid,
unsigned char *buf, int *eld_size,
bool rev3_or_later);
#ifdef CONFIG_SND_PROC_FS
void snd_hdmi_print_eld_info(struct hdmi_eld *eld,
struct snd_info_buffer *buffer,
hda_nid_t pin_nid, int dev_id, hda_nid_t cvt_nid);
void snd_hdmi_write_eld_info(struct hdmi_eld *eld,
struct snd_info_buffer *buffer);
#endif
#define SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE 80
void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen);
void snd_hda_codec_display_power(struct hda_codec *codec, bool enable);
/*
*/
#define codec_err(codec, fmt, args...) \
dev_err(hda_codec_dev(codec), fmt, ##args)
#define codec_warn(codec, fmt, args...) \
dev_warn(hda_codec_dev(codec), fmt, ##args)
#define codec_info(codec, fmt, args...) \
dev_info(hda_codec_dev(codec), fmt, ##args)
#define codec_dbg(codec, fmt, args...) \
dev_dbg(hda_codec_dev(codec), fmt, ##args)
#endif /* __SOUND_HDA_LOCAL_H */

View file

@ -0,0 +1,95 @@
// SPDX-License-Identifier: GPL-2.0
/* Fixes for HP X360 laptops with top B&O speakers
* to be included from codec driver
*/
static void alc295_fixup_hp_top_speakers(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
static const struct hda_pintbl pincfgs[] = {
{ 0x17, 0x90170110 },
{ }
};
static const struct coef_fw alc295_hp_speakers_coefs[] = {
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0000), WRITE_COEF(0x28, 0x0000), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x003f), WRITE_COEF(0x28, 0x1000), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0004), WRITE_COEF(0x28, 0x0600), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x006a), WRITE_COEF(0x28, 0x0006), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x006c), WRITE_COEF(0x28, 0xc0c0), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0008), WRITE_COEF(0x28, 0xb000), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x002e), WRITE_COEF(0x28, 0x0800), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x006a), WRITE_COEF(0x28, 0x00c1), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x006c), WRITE_COEF(0x28, 0x0320), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0039), WRITE_COEF(0x28, 0x0000), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x003b), WRITE_COEF(0x28, 0xffff), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x003c), WRITE_COEF(0x28, 0xffd0), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x003a), WRITE_COEF(0x28, 0x1dfe), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0080), WRITE_COEF(0x28, 0x0880), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x003a), WRITE_COEF(0x28, 0x0dfe), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0018), WRITE_COEF(0x28, 0x0219), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x006a), WRITE_COEF(0x28, 0x005d), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x006c), WRITE_COEF(0x28, 0x9142), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00c0), WRITE_COEF(0x28, 0x01ce), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00c1), WRITE_COEF(0x28, 0xed0c), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00c2), WRITE_COEF(0x28, 0x1c00), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00c3), WRITE_COEF(0x28, 0x0000), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00c4), WRITE_COEF(0x28, 0x0200), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00c5), WRITE_COEF(0x28, 0x0000), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00c6), WRITE_COEF(0x28, 0x0399), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00c7), WRITE_COEF(0x28, 0x2330), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00c8), WRITE_COEF(0x28, 0x1e5d), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00c9), WRITE_COEF(0x28, 0x6eff), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00ca), WRITE_COEF(0x28, 0x01c0), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00cb), WRITE_COEF(0x28, 0xed0c), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00cc), WRITE_COEF(0x28, 0x1c00), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00cd), WRITE_COEF(0x28, 0x0000), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00ce), WRITE_COEF(0x28, 0x0200), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00cf), WRITE_COEF(0x28, 0x0000), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00d0), WRITE_COEF(0x28, 0x0399), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00d1), WRITE_COEF(0x28, 0x2330), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00d2), WRITE_COEF(0x28, 0x1e5d), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00d3), WRITE_COEF(0x28, 0x6eff), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0062), WRITE_COEF(0x28, 0x8000), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0063), WRITE_COEF(0x28, 0x5f5f), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0064), WRITE_COEF(0x28, 0x1000), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0065), WRITE_COEF(0x28, 0x0000), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0066), WRITE_COEF(0x28, 0x4004), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0067), WRITE_COEF(0x28, 0x0802), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0068), WRITE_COEF(0x28, 0x890f), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0069), WRITE_COEF(0x28, 0xe021), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0070), WRITE_COEF(0x28, 0x8012), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0071), WRITE_COEF(0x28, 0x3450), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0072), WRITE_COEF(0x28, 0x0123), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0073), WRITE_COEF(0x28, 0x4543), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0074), WRITE_COEF(0x28, 0x2100), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0075), WRITE_COEF(0x28, 0x4321), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0076), WRITE_COEF(0x28, 0x0000), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0050), WRITE_COEF(0x28, 0x8200), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x003a), WRITE_COEF(0x28, 0x1dfe), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0051), WRITE_COEF(0x28, 0x0707), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0052), WRITE_COEF(0x28, 0x4090), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x006a), WRITE_COEF(0x28, 0x0090), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x006c), WRITE_COEF(0x28, 0x721f), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0012), WRITE_COEF(0x28, 0xebeb), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x009e), WRITE_COEF(0x28, 0x0000), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0060), WRITE_COEF(0x28, 0x2213), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x006a), WRITE_COEF(0x28, 0x0006), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x006c), WRITE_COEF(0x28, 0x0000), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x003f), WRITE_COEF(0x28, 0x3000), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0004), WRITE_COEF(0x28, 0x0500), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0040), WRITE_COEF(0x28, 0x800c), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0046), WRITE_COEF(0x28, 0xc22e), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x004b), WRITE_COEF(0x28, 0x0000), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0050), WRITE_COEF(0x28, 0x82ec), WRITE_COEF(0x29, 0xb024),
};
switch (action) {
case HDA_FIXUP_ACT_PRE_PROBE:
snd_hda_apply_pincfgs(codec, pincfgs);
alc295_fixup_disable_dac3(codec, fix, action);
break;
case HDA_FIXUP_ACT_INIT:
alc_process_coef_fw(codec, alc295_hp_speakers_coefs);
break;
}
}

View file

@ -0,0 +1,492 @@
// SPDX-License-Identifier: GPL-2.0
/* Fixes for Lenovo Ideapad S740, to be included from codec driver */
static const struct hda_verb alc285_ideapad_s740_coefs[] = {
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x10 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0320 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x24 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0041 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x24 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0041 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x007f },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x007f },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x003c },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0011 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x003c },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0011 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x000c },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x001a },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x000c },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x001a },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x000f },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0042 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x000f },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0042 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0010 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0040 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0010 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0040 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0003 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0009 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0003 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0009 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x001c },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x004c },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x001c },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x004c },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x001d },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x004e },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x001d },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x004e },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x001b },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x001b },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0019 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0025 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0019 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0025 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0018 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0037 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0018 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0037 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x001a },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0040 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x001a },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0040 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0016 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0076 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0016 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0076 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0017 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0010 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0017 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0010 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0015 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0015 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0015 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0015 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0007 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0086 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0007 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0086 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0002 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0002 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0002 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0002 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x24 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0042 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x24 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0042 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x007f },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x007f },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x003c },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0011 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x003c },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0011 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x000c },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x002a },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x000c },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x002a },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x000f },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0046 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x000f },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0046 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0010 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0044 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0010 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0044 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0003 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0009 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0003 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0009 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x001c },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x004c },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x001c },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x004c },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x001b },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x001b },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0019 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0025 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0019 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0025 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0018 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0037 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0018 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0037 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x001a },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0040 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x001a },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0040 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0016 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0076 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0016 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0076 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0017 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0010 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0017 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0010 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0015 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0015 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0015 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0015 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0007 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0086 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0007 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0086 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0002 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0002 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0002 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
{}
};
static void alc285_fixup_ideapad_s740_coef(struct hda_codec *codec,
const struct hda_fixup *fix,
int action)
{
switch (action) {
case HDA_FIXUP_ACT_PRE_PROBE:
snd_hda_add_verbs(codec, alc285_ideapad_s740_coefs);
break;
}
}

View file

@ -0,0 +1,36 @@
// SPDX-License-Identifier: GPL-2.0
/* Helper functions for Thinkpad LED control;
* to be included from codec driver
*/
#if IS_ENABLED(CONFIG_THINKPAD_ACPI)
#include <linux/acpi.h>
#include <linux/leds.h>
static bool is_thinkpad(struct hda_codec *codec)
{
return (codec->core.subsystem_id >> 16 == 0x17aa) &&
(acpi_dev_found("LEN0068") || acpi_dev_found("LEN0268") ||
acpi_dev_found("IBM0068"));
}
static void hda_fixup_thinkpad_acpi(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
if (action == HDA_FIXUP_ACT_PRE_PROBE) {
if (!is_thinkpad(codec))
return;
snd_hda_gen_add_mute_led_cdev(codec, NULL);
snd_hda_gen_add_micmute_led_cdev(codec, NULL);
}
}
#else /* CONFIG_THINKPAD_ACPI */
static void hda_fixup_thinkpad_acpi(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
}
#endif /* CONFIG_THINKPAD_ACPI */

File diff suppressed because it is too large Load diff