linux/sound/pci/hda/hda_generic.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Universal Interface for Intel High Definition Audio Codec
 *
 * Generic widget tree parser
 *
 * Copyright (c) 2004 Takashi Iwai <[email protected]>
 */

#include <linux/init.h>
#include <linux/slab.h>
#include <linux/export.h>
#include <linux/sort.h>
#include <linux/delay.h>
#include <linux/ctype.h>
#include <linux/string.h>
#include <linux/bitops.h>
#include <linux/module.h>
#include <linux/leds.h>
#include <sound/core.h>
#include <sound/jack.h>
#include <sound/tlv.h>
#include <sound/hda_codec.h>
#include "hda_local.h"
#include "hda_auto_parser.h"
#include "hda_jack.h"
#include "hda_beep.h"
#include "hda_generic.h"


/**
 * snd_hda_gen_spec_init - initialize hda_gen_spec struct
 * @spec: hda_gen_spec object to initialize
 *
 * Initialize the given hda_gen_spec object.
 */
int snd_hda_gen_spec_init(struct hda_gen_spec *spec)
{}
EXPORT_SYMBOL_GPL();

/**
 * snd_hda_gen_add_kctl - Add a new kctl_new struct from the template
 * @spec: hda_gen_spec object
 * @name: name string to override the template, NULL if unchanged
 * @temp: template for the new kctl
 *
 * Add a new kctl (actually snd_kcontrol_new to be instantiated later)
 * element based on the given snd_kcontrol_new template @temp and the
 * name string @name to the list in @spec.
 * Returns the newly created object or NULL as error.
 */
struct snd_kcontrol_new *
snd_hda_gen_add_kctl(struct hda_gen_spec *spec, const char *name,
		     const struct snd_kcontrol_new *temp)
{}
EXPORT_SYMBOL_GPL();

static void free_kctls(struct hda_gen_spec *spec)
{}

static void snd_hda_gen_spec_free(struct hda_gen_spec *spec)
{}

/*
 * store user hints
 */
static void parse_user_hints(struct hda_codec *codec)
{}

/*
 * pin control value accesses
 */

#define update_pin_ctl(codec, pin, val)

/* restore the pinctl based on the cached value */
static inline void restore_pin_ctl(struct hda_codec *codec, hda_nid_t pin)
{}

/* set the pinctl target value and write it if requested */
static void set_pin_target(struct hda_codec *codec, hda_nid_t pin,
			   unsigned int val, bool do_write)
{}

/* set pinctl target values for all given pins */
static void set_pin_targets(struct hda_codec *codec, int num_pins,
			    hda_nid_t *pins, unsigned int val)
{}

/*
 * parsing paths
 */

/* return the position of NID in the list, or -1 if not found */
static int find_idx_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
{}

/* return true if the given NID is contained in the path */
static bool is_nid_contained(struct nid_path *path, hda_nid_t nid)
{}

static struct nid_path *get_nid_path(struct hda_codec *codec,
				     hda_nid_t from_nid, hda_nid_t to_nid,
				     int anchor_nid)
{}

/**
 * snd_hda_get_path_idx - get the index number corresponding to the path
 * instance
 * @codec: the HDA codec
 * @path: nid_path object
 *
 * The returned index starts from 1, i.e. the actual array index with offset 1,
 * and zero is handled as an invalid path
 */
int snd_hda_get_path_idx(struct hda_codec *codec, struct nid_path *path)
{}
EXPORT_SYMBOL_GPL();

/**
 * snd_hda_get_path_from_idx - get the path instance corresponding to the
 * given index number
 * @codec: the HDA codec
 * @idx: the path index
 */
struct nid_path *snd_hda_get_path_from_idx(struct hda_codec *codec, int idx)
{}
EXPORT_SYMBOL_GPL();

/* check whether the given DAC is already found in any existing paths */
static bool is_dac_already_used(struct hda_codec *codec, hda_nid_t nid)
{}

/* check whether the given two widgets can be connected */
static bool is_reachable_path(struct hda_codec *codec,
			      hda_nid_t from_nid, hda_nid_t to_nid)
{}

/* nid, dir and idx */
#define AMP_VAL_COMPARE_MASK

/* check whether the given ctl is already assigned in any path elements */
static bool is_ctl_used(struct hda_codec *codec, unsigned int val, int type)
{}

/* check whether a control with the given (nid, dir, idx) was assigned */
static bool is_ctl_associated(struct hda_codec *codec, hda_nid_t nid,
			      int dir, int idx, int type)
{}

static void print_nid_path(struct hda_codec *codec,
			   const char *pfx, struct nid_path *path)
{}

/* called recursively */
static bool __parse_nid_path(struct hda_codec *codec,
			     hda_nid_t from_nid, hda_nid_t to_nid,
			     int anchor_nid, struct nid_path *path,
			     int depth)
{}

/*
 * snd_hda_parse_nid_path - parse the widget path from the given nid to
 * the target nid
 * @codec: the HDA codec
 * @from_nid: the NID where the path start from
 * @to_nid: the NID where the path ends at
 * @anchor_nid: the anchor indication
 * @path: the path object to store the result
 *
 * Returns true if a matching path is found.
 *
 * The parsing behavior depends on parameters:
 * when @from_nid is 0, try to find an empty DAC;
 * when @anchor_nid is set to a positive value, only paths through the widget
 * with the given value are evaluated.
 * when @anchor_nid is set to a negative value, paths through the widget
 * with the negative of given value are excluded, only other paths are chosen.
 * when @anchor_nid is zero, no special handling about path selection.
 */
static bool snd_hda_parse_nid_path(struct hda_codec *codec, hda_nid_t from_nid,
			    hda_nid_t to_nid, int anchor_nid,
			    struct nid_path *path)
{}

/**
 * snd_hda_add_new_path - parse the path between the given NIDs and
 * add to the path list
 * @codec: the HDA codec
 * @from_nid: the NID where the path start from
 * @to_nid: the NID where the path ends at
 * @anchor_nid: the anchor indication, see snd_hda_parse_nid_path()
 *
 * If no valid path is found, returns NULL.
 */
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)
{}
EXPORT_SYMBOL_GPL();

/* clear the given path as invalid so that it won't be picked up later */
static void invalidate_nid_path(struct hda_codec *codec, int idx)
{}

/* return a DAC if paired to the given pin by codec driver */
static hda_nid_t get_preferred_dac(struct hda_codec *codec, hda_nid_t pin)
{}

/* look for an empty DAC slot */
static hda_nid_t look_for_dac(struct hda_codec *codec, hda_nid_t pin,
			      bool is_digital)
{}

/* replace the channels in the composed amp value with the given number */
static unsigned int amp_val_replace_channels(unsigned int val, unsigned int chs)
{}

static bool same_amp_caps(struct hda_codec *codec, hda_nid_t nid1,
			  hda_nid_t nid2, int dir)
{}

/* look for a widget suitable for assigning a mute switch in the path */
static hda_nid_t look_for_out_mute_nid(struct hda_codec *codec,
				       struct nid_path *path)
{}

/* look for a widget suitable for assigning a volume ctl in the path */
static hda_nid_t look_for_out_vol_nid(struct hda_codec *codec,
				      struct nid_path *path)
{}

/*
 * path activation / deactivation
 */

/* can have the amp-in capability? */
static bool has_amp_in(struct hda_codec *codec, struct nid_path *path, int idx)
{}

/* can have the amp-out capability? */
static bool has_amp_out(struct hda_codec *codec, struct nid_path *path, int idx)
{}

/* check whether the given (nid,dir,idx) is active */
static bool is_active_nid(struct hda_codec *codec, hda_nid_t nid,
			  unsigned int dir, unsigned int idx)
{}

/* check whether the NID is referred by any active paths */
#define is_active_nid_for_any(codec, nid)

/* get the default amp value for the target state */
static int get_amp_val_to_activate(struct hda_codec *codec, hda_nid_t nid,
				   int dir, unsigned int caps, bool enable)
{}

/* is this a stereo widget or a stereo-to-mono mix? */
static bool is_stereo_amps(struct hda_codec *codec, hda_nid_t nid, int dir)
{}

/* initialize the amp value (only at the first time) */
static void init_amp(struct hda_codec *codec, hda_nid_t nid, int dir, int idx)
{}

/* update the amp, doing in stereo or mono depending on NID */
static int update_amp(struct hda_codec *codec, hda_nid_t nid, int dir, int idx,
		      unsigned int mask, unsigned int val)
{}

/* calculate amp value mask we can modify;
 * if the given amp is controlled by mixers, don't touch it
 */
static unsigned int get_amp_mask_to_modify(struct hda_codec *codec,
					   hda_nid_t nid, int dir, int idx,
					   unsigned int caps)
{}

static void activate_amp(struct hda_codec *codec, hda_nid_t nid, int dir,
			 int idx, int idx_to_check, bool enable)
{}

static void check_and_activate_amp(struct hda_codec *codec, hda_nid_t nid,
				   int dir, int idx, int idx_to_check,
				   bool enable)
{}

static void activate_amp_out(struct hda_codec *codec, struct nid_path *path,
			     int i, bool enable)
{}

static void activate_amp_in(struct hda_codec *codec, struct nid_path *path,
			    int i, bool enable, bool add_aamix)
{}

/* sync power of each widget in the given path */
static hda_nid_t path_power_update(struct hda_codec *codec,
				   struct nid_path *path,
				   bool allow_powerdown)
{}

/* do sync with the last power state change */
static void sync_power_state_change(struct hda_codec *codec, hda_nid_t nid)
{}

/**
 * snd_hda_activate_path - activate or deactivate the given path
 * @codec: the HDA codec
 * @path: the path to activate/deactivate
 * @enable: flag to activate or not
 * @add_aamix: enable the input from aamix NID
 *
 * If @add_aamix is set, enable the input from aa-mix NID as well (if any).
 */
void snd_hda_activate_path(struct hda_codec *codec, struct nid_path *path,
			   bool enable, bool add_aamix)
{}
EXPORT_SYMBOL_GPL();

/* if the given path is inactive, put widgets into D3 (only if suitable) */
static void path_power_down_sync(struct hda_codec *codec, struct nid_path *path)
{}

/* turn on/off EAPD on the given pin */
static void set_pin_eapd(struct hda_codec *codec, hda_nid_t pin, bool enable)
{}

/* re-initialize the path specified by the given path index */
static void resume_path_from_idx(struct hda_codec *codec, int path_idx)
{}


/*
 * Helper functions for creating mixer ctl elements
 */

static int hda_gen_mixer_mute_put(struct snd_kcontrol *kcontrol,
				  struct snd_ctl_elem_value *ucontrol);
static int hda_gen_bind_mute_get(struct snd_kcontrol *kcontrol,
				 struct snd_ctl_elem_value *ucontrol);
static int hda_gen_bind_mute_put(struct snd_kcontrol *kcontrol,
				 struct snd_ctl_elem_value *ucontrol);

enum {};
static const struct snd_kcontrol_new control_templates[] =;

/* add dynamic controls from template */
static struct snd_kcontrol_new *
add_control(struct hda_gen_spec *spec, int type, const char *name,
		       int cidx, unsigned long val)
{}

static int add_control_with_pfx(struct hda_gen_spec *spec, int type,
				const char *pfx, const char *dir,
				const char *sfx, int cidx, unsigned long val)
{}

#define add_pb_vol_ctrl(spec, type, pfx, val)
#define add_pb_sw_ctrl(spec, type, pfx, val)
#define __add_pb_vol_ctrl(spec, type, pfx, cidx, val)
#define __add_pb_sw_ctrl(spec, type, pfx, cidx, val)

static int add_vol_ctl(struct hda_codec *codec, const char *pfx, int cidx,
		       unsigned int chs, struct nid_path *path)
{}

/* return the channel bits suitable for the given path->ctls[] */
static int get_default_ch_nums(struct hda_codec *codec, struct nid_path *path,
			       int type)
{}

static int add_stereo_vol(struct hda_codec *codec, const char *pfx, int cidx,
			  struct nid_path *path)
{}

/* create a mute-switch for the given mixer widget;
 * if it has multiple sources (e.g. DAC and loopback), create a bind-mute
 */
static int add_sw_ctl(struct hda_codec *codec, const char *pfx, int cidx,
		      unsigned int chs, struct nid_path *path)
{}

static int add_stereo_sw(struct hda_codec *codec, const char *pfx,
				  int cidx, struct nid_path *path)
{}

/* playback mute control with the software mute bit check */
static void sync_auto_mute_bits(struct snd_kcontrol *kcontrol,
				struct snd_ctl_elem_value *ucontrol)
{}

static int hda_gen_mixer_mute_put(struct snd_kcontrol *kcontrol,
				  struct snd_ctl_elem_value *ucontrol)
{}

/*
 * Bound mute controls
 */
#define AMP_VAL_IDX_SHIFT
#define AMP_VAL_IDX_MASK

static int hda_gen_bind_mute_get(struct snd_kcontrol *kcontrol,
				 struct snd_ctl_elem_value *ucontrol)
{}

static int hda_gen_bind_mute_put(struct snd_kcontrol *kcontrol,
				 struct snd_ctl_elem_value *ucontrol)
{}

/* any ctl assigned to the path with the given index? */
static bool path_has_mixer(struct hda_codec *codec, int path_idx, int ctl_type)
{}

static const char * const channel_name[] =;

/* give some appropriate ctl name prefix for the given line out channel */
static const char *get_line_out_pfx(struct hda_codec *codec, int ch,
				    int *index, int ctl_type)
{}

/*
 * Parse output paths
 */

/* badness definition */
enum {};

/* look for widgets in the given path which are appropriate for
 * volume and mute controls, and assign the values to ctls[].
 *
 * When no appropriate widget is found in the path, the badness value
 * is incremented depending on the situation.  The function returns the
 * total badness for both volume and mute controls.
 */
static int assign_out_path_ctls(struct hda_codec *codec, struct nid_path *path)
{}

const struct badness_table hda_main_out_badness =;
EXPORT_SYMBOL_GPL();

const struct badness_table hda_extra_out_badness =;
EXPORT_SYMBOL_GPL();

/* get the DAC of the primary output corresponding to the given array index */
static hda_nid_t get_primary_out(struct hda_codec *codec, int idx)
{}

/* return the DAC if it's reachable, otherwise zero */
static inline hda_nid_t try_dac(struct hda_codec *codec,
				hda_nid_t dac, hda_nid_t pin)
{}

/* try to assign DACs to pins and return the resultant badness */
static int try_assign_dacs(struct hda_codec *codec, int num_outs,
			   const hda_nid_t *pins, hda_nid_t *dacs,
			   int *path_idx,
			   const struct badness_table *bad)
{}

/* return NID if the given pin has only a single connection to a certain DAC */
static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin)
{}

/* check whether the given pin can be a multi-io pin */
static bool can_be_multiio_pin(struct hda_codec *codec,
			       unsigned int location, hda_nid_t nid)
{}

/* count the number of input pins that are capable to be multi-io */
static int count_multiio_pins(struct hda_codec *codec, hda_nid_t reference_pin)
{}

/*
 * multi-io helper
 *
 * When hardwired is set, try to fill ony hardwired pins, and returns
 * zero if any pins are filled, non-zero if nothing found.
 * When hardwired is off, try to fill possible input pins, and returns
 * the badness value.
 */
static int fill_multi_ios(struct hda_codec *codec,
			  hda_nid_t reference_pin,
			  bool hardwired)
{}

/* map DACs for all pins in the list if they are single connections */
static bool map_singles(struct hda_codec *codec, int outs,
			const hda_nid_t *pins, hda_nid_t *dacs, int *path_idx)
{}

static inline bool has_aamix_out_paths(struct hda_gen_spec *spec)
{}

/* create a new path including aamix if available, and return its index */
static int check_aamix_out_path(struct hda_codec *codec, int path_idx)
{}

/* check whether the independent HP is available with the current config */
static bool indep_hp_possible(struct hda_codec *codec)
{}

/* fill the empty entries in the dac array for speaker/hp with the
 * shared dac pointed by the paths
 */
static void refill_shared_dacs(struct hda_codec *codec, int num_outs,
			       hda_nid_t *dacs, int *path_idx)
{}

/* fill in the dac_nids table from the parsed pin configuration */
static int fill_and_eval_dacs(struct hda_codec *codec,
			      bool fill_hardwired,
			      bool fill_mio_first)
{}

#define DEBUG_BADNESS

#ifdef DEBUG_BADNESS
#define debug_badness(fmt, ...)
#else
#define debug_badness
#endif

#ifdef DEBUG_BADNESS
static inline void print_nid_path_idx(struct hda_codec *codec,
				      const char *pfx, int idx)
{}

static void debug_show_configs(struct hda_codec *codec,
			       struct auto_pin_cfg *cfg)
{}
#else
#define debug_show_configs
#endif

/* find all available DACs of the codec */
static void fill_all_dac_nids(struct hda_codec *codec)
{}

static int parse_output_paths(struct hda_codec *codec)
{}

/* add playback controls from the parsed DAC table */
static int create_multi_out_ctls(struct hda_codec *codec,
				 const struct auto_pin_cfg *cfg)
{}

static int create_extra_out(struct hda_codec *codec, int path_idx,
			    const char *pfx, int cidx)
{}

/* add playback controls for speaker and HP outputs */
static int create_extra_outs(struct hda_codec *codec, int num_pins,
			     const int *paths, const char *pfx)
{}

static int create_hp_out_ctls(struct hda_codec *codec)
{}

static int create_speaker_out_ctls(struct hda_codec *codec)
{}

/*
 * independent HP controls
 */

static void call_hp_automute(struct hda_codec *codec,
			     struct hda_jack_callback *jack);
static int indep_hp_info(struct snd_kcontrol *kcontrol,
			 struct snd_ctl_elem_info *uinfo)
{}

static int indep_hp_get(struct snd_kcontrol *kcontrol,
			struct snd_ctl_elem_value *ucontrol)
{}

static void update_aamix_paths(struct hda_codec *codec, bool do_mix,
			       int nomix_path_idx, int mix_path_idx,
			       int out_type);

static int indep_hp_put(struct snd_kcontrol *kcontrol,
			struct snd_ctl_elem_value *ucontrol)
{}

static const struct snd_kcontrol_new indep_hp_ctl =;


static int create_indep_hp_ctls(struct hda_codec *codec)
{}

/*
 * channel mode enum control
 */

static int ch_mode_info(struct snd_kcontrol *kcontrol,
			struct snd_ctl_elem_info *uinfo)
{}

static int ch_mode_get(struct snd_kcontrol *kcontrol,
		       struct snd_ctl_elem_value *ucontrol)
{}

static inline struct nid_path *
get_multiio_path(struct hda_codec *codec, int idx)
{}

static void update_automute_all(struct hda_codec *codec);

/* Default value to be passed as aamix argument for snd_hda_activate_path();
 * used for output paths
 */
static bool aamix_default(struct hda_gen_spec *spec)
{}

static int set_multi_io(struct hda_codec *codec, int idx, bool output)
{}

static int ch_mode_put(struct snd_kcontrol *kcontrol,
		       struct snd_ctl_elem_value *ucontrol)
{}

static const struct snd_kcontrol_new channel_mode_enum =;

static int create_multi_channel_mode(struct hda_codec *codec)
{}

/*
 * aamix loopback enable/disable switch
 */

#define loopback_mixing_info

static int loopback_mixing_get(struct snd_kcontrol *kcontrol,
			       struct snd_ctl_elem_value *ucontrol)
{}

static void update_aamix_paths(struct hda_codec *codec, bool do_mix,
			       int nomix_path_idx, int mix_path_idx,
			       int out_type)
{}

/* re-initialize the output paths; only called from loopback_mixing_put() */
static void update_output_paths(struct hda_codec *codec, int num_outs,
				const int *paths)
{}

static int loopback_mixing_put(struct snd_kcontrol *kcontrol,
			       struct snd_ctl_elem_value *ucontrol)
{}

static const struct snd_kcontrol_new loopback_mixing_enum =;

static int create_loopback_mixing_ctl(struct hda_codec *codec)
{}

/*
 * shared headphone/mic handling
 */

static void call_update_outputs(struct hda_codec *codec);

/* for shared I/O, change the pin-control accordingly */
static void update_hp_mic(struct hda_codec *codec, int adc_mux, bool force)
{}

/* create a shared input with the headphone out */
static int create_hp_mic(struct hda_codec *codec)
{}

/*
 * output jack mode
 */

static int create_hp_mic_jack_mode(struct hda_codec *codec, hda_nid_t pin);

static const char * const out_jack_texts[] =;

static int out_jack_mode_info(struct snd_kcontrol *kcontrol,
			      struct snd_ctl_elem_info *uinfo)
{}

static int out_jack_mode_get(struct snd_kcontrol *kcontrol,
			     struct snd_ctl_elem_value *ucontrol)
{}

static int out_jack_mode_put(struct snd_kcontrol *kcontrol,
			     struct snd_ctl_elem_value *ucontrol)
{}

static const struct snd_kcontrol_new out_jack_mode_enum =;

static bool find_kctl_name(struct hda_codec *codec, const char *name, int idx)
{}

static void get_jack_mode_name(struct hda_codec *codec, hda_nid_t pin,
			       char *name, size_t name_len)
{}

static int get_out_jack_num_items(struct hda_codec *codec, hda_nid_t pin)
{}

static int create_out_jack_modes(struct hda_codec *codec, int num_pins,
				 hda_nid_t *pins)
{}

/*
 * input jack mode
 */

/* from AC_PINCTL_VREF_HIZ to AC_PINCTL_VREF_100 */
#define NUM_VREFS

static const char * const vref_texts[NUM_VREFS] =;

static unsigned int get_vref_caps(struct hda_codec *codec, hda_nid_t pin)
{}

/* convert from the enum item index to the vref ctl index (0=HIZ, 1=50%...) */
static int get_vref_idx(unsigned int vref_caps, unsigned int item_idx)
{}

/* convert back from the vref ctl index to the enum item index */
static int cvt_from_vref_idx(unsigned int vref_caps, unsigned int idx)
{}

static int in_jack_mode_info(struct snd_kcontrol *kcontrol,
			     struct snd_ctl_elem_info *uinfo)
{}

static int in_jack_mode_get(struct snd_kcontrol *kcontrol,
			    struct snd_ctl_elem_value *ucontrol)
{}

static int in_jack_mode_put(struct snd_kcontrol *kcontrol,
			    struct snd_ctl_elem_value *ucontrol)
{}

static const struct snd_kcontrol_new in_jack_mode_enum =;

static int get_in_jack_num_items(struct hda_codec *codec, hda_nid_t pin)
{}

static int create_in_jack_mode(struct hda_codec *codec, hda_nid_t pin)
{}

/*
 * HP/mic shared jack mode
 */
static int hp_mic_jack_mode_info(struct snd_kcontrol *kcontrol,
				 struct snd_ctl_elem_info *uinfo)
{}

static int get_cur_hp_mic_jack_mode(struct hda_codec *codec, hda_nid_t nid)
{}

static int hp_mic_jack_mode_get(struct snd_kcontrol *kcontrol,
				struct snd_ctl_elem_value *ucontrol)
{}

static int hp_mic_jack_mode_put(struct snd_kcontrol *kcontrol,
				struct snd_ctl_elem_value *ucontrol)
{}

static const struct snd_kcontrol_new hp_mic_jack_mode_enum =;

static int create_hp_mic_jack_mode(struct hda_codec *codec, hda_nid_t pin)
{}

/*
 * Parse input paths
 */

/* add the powersave loopback-list entry */
static int add_loopback_list(struct hda_gen_spec *spec, hda_nid_t mix, int idx)
{}

/* return true if either a volume or a mute amp is found for the given
 * aamix path; the amp has to be either in the mixer node or its direct leaf
 */
static bool look_for_mix_leaf_ctls(struct hda_codec *codec, hda_nid_t mix_nid,
				   hda_nid_t pin, unsigned int *mix_val,
				   unsigned int *mute_val)
{}

/* create input playback/capture controls for the given pin */
static int new_analog_input(struct hda_codec *codec, int input_idx,
			    hda_nid_t pin, const char *ctlname, int ctlidx,
			    hda_nid_t mix_nid)
{}

static int is_input_pin(struct hda_codec *codec, hda_nid_t nid)
{}

/* Parse the codec tree and retrieve ADCs */
static int fill_adc_nids(struct hda_codec *codec)
{}

/* filter out invalid adc_nids that don't give all active input pins;
 * if needed, check whether dynamic ADC-switching is available
 */
static int check_dyn_adc_switch(struct hda_codec *codec)
{}

/* parse capture source paths from the given pin and create imux items */
static int parse_capture_source(struct hda_codec *codec, hda_nid_t pin,
				int cfg_idx, int num_adcs,
				const char *label, int anchor)
{}

/*
 * create playback/capture controls for input pins
 */

/* fill the label for each input at first */
static int fill_input_pin_labels(struct hda_codec *codec)
{}

#define CFG_IDX_MIX

static int create_input_ctls(struct hda_codec *codec)
{}


/*
 * input source mux
 */

/* get the input path specified by the given adc and imux indices */
static struct nid_path *get_input_path(struct hda_codec *codec, int adc_idx, int imux_idx)
{}

static int mux_select(struct hda_codec *codec, unsigned int adc_idx,
		      unsigned int idx);

static int mux_enum_info(struct snd_kcontrol *kcontrol,
			 struct snd_ctl_elem_info *uinfo)
{}

static int mux_enum_get(struct snd_kcontrol *kcontrol,
			struct snd_ctl_elem_value *ucontrol)
{}

static int mux_enum_put(struct snd_kcontrol *kcontrol,
			    struct snd_ctl_elem_value *ucontrol)
{}

static const struct snd_kcontrol_new cap_src_temp =;

/*
 * capture volume and capture switch ctls
 */

put_call_t;

/* call the given amp update function for all amps in the imux list at once */
static int cap_put_caller(struct snd_kcontrol *kcontrol,
			  struct snd_ctl_elem_value *ucontrol,
			  put_call_t func, int type)
{}

/* capture volume ctl callbacks */
#define cap_vol_info
#define cap_vol_get
#define cap_vol_tlv

static int cap_vol_put(struct snd_kcontrol *kcontrol,
		       struct snd_ctl_elem_value *ucontrol)
{}

static const struct snd_kcontrol_new cap_vol_temp =;

/* capture switch ctl callbacks */
#define cap_sw_info
#define cap_sw_get

static int cap_sw_put(struct snd_kcontrol *kcontrol,
		      struct snd_ctl_elem_value *ucontrol)
{}

static const struct snd_kcontrol_new cap_sw_temp =;

static int parse_capvol_in_path(struct hda_codec *codec, struct nid_path *path)
{}

static bool is_inv_dmic_pin(struct hda_codec *codec, hda_nid_t nid)
{}

/* capture switch put callback for a single control with hook call */
static int cap_single_sw_put(struct snd_kcontrol *kcontrol,
			     struct snd_ctl_elem_value *ucontrol)
{}

static int add_single_cap_ctl(struct hda_codec *codec, const char *label,
			      int idx, bool is_switch, unsigned int ctl,
			      bool inv_dmic)
{}

/* create single (and simple) capture volume and switch controls */
static int create_single_cap_vol_ctl(struct hda_codec *codec, int idx,
				     unsigned int vol_ctl, unsigned int sw_ctl,
				     bool inv_dmic)
{}

/* create bound capture volume and switch controls */
static int create_bind_cap_vol_ctl(struct hda_codec *codec, int idx,
				   unsigned int vol_ctl, unsigned int sw_ctl)
{}

/* return the vol ctl when used first in the imux list */
static unsigned int get_first_cap_ctl(struct hda_codec *codec, int idx, int type)
{}

/* create individual capture volume and switch controls per input */
static int create_multi_cap_vol_ctl(struct hda_codec *codec)
{}

static int create_capture_mixers(struct hda_codec *codec)
{}

/*
 * add mic boosts if needed
 */

/* check whether the given amp is feasible as a boost volume */
static bool check_boost_vol(struct hda_codec *codec, hda_nid_t nid,
			    int dir, int idx)
{}

/* look for a boost amp in a widget close to the pin */
static unsigned int look_for_boost_amp(struct hda_codec *codec,
				       struct nid_path *path)
{}

static int parse_mic_boost(struct hda_codec *codec)
{}

#ifdef CONFIG_SND_HDA_GENERIC_LEDS
/*
 * vmaster mute LED hook helpers
 */

static int create_mute_led_cdev(struct hda_codec *codec,
				int (*callback)(struct led_classdev *,
						enum led_brightness),
				bool micmute)
{}

/**
 * snd_hda_gen_add_mute_led_cdev - Create a LED classdev and enable as vmaster mute LED
 * @codec: the HDA codec
 * @callback: the callback for LED classdev brightness_set_blocking
 */
int snd_hda_gen_add_mute_led_cdev(struct hda_codec *codec,
				  int (*callback)(struct led_classdev *,
						  enum led_brightness))
{}
EXPORT_SYMBOL_GPL();

/**
 * snd_hda_gen_add_micmute_led_cdev - Create a LED classdev and enable as mic-mute LED
 * @codec: the HDA codec
 * @callback: the callback for LED classdev brightness_set_blocking
 *
 * Called from the codec drivers for offering the mic mute LED controls.
 * This creates a LED classdev and sets up the cap_sync_hook that is called at
 * each time when the capture mixer switch changes.
 *
 * When NULL is passed to @callback, no classdev is created but only the
 * LED-trigger is set up.
 *
 * Returns 0 or a negative error.
 */
int snd_hda_gen_add_micmute_led_cdev(struct hda_codec *codec,
				     int (*callback)(struct led_classdev *,
						     enum led_brightness))
{}
EXPORT_SYMBOL_GPL();
#endif /* CONFIG_SND_HDA_GENERIC_LEDS */

/*
 * parse digital I/Os and set up NIDs in BIOS auto-parse mode
 */
static void parse_digital(struct hda_codec *codec)
{}


/*
 * input MUX handling
 */

static bool dyn_adc_pcm_resetup(struct hda_codec *codec, int cur);

/* select the given imux item; either unmute exclusively or select the route */
static int mux_select(struct hda_codec *codec, unsigned int adc_idx,
		      unsigned int idx)
{}

/* power up/down widgets in the all paths that match with the given NID
 * as terminals (either start- or endpoint)
 *
 * returns the last changed NID, or zero if unchanged.
 */
static hda_nid_t set_path_power(struct hda_codec *codec, hda_nid_t nid,
				int pin_state, int stream_state)
{}

/* check the jack status for power control */
static bool detect_pin_state(struct hda_codec *codec, hda_nid_t pin)
{}

/* power up/down the paths of the given pin according to the jack state;
 * power = 0/1 : only power up/down if it matches with the jack state,
 *       < 0   : force power up/down to follow the jack sate
 *
 * returns the last changed NID, or zero if unchanged.
 */
static hda_nid_t set_pin_power_jack(struct hda_codec *codec, hda_nid_t pin,
				    int power)
{}

static void pin_power_callback(struct hda_codec *codec,
			       struct hda_jack_callback *jack,
			       bool on)
{}

/* callback only doing power up -- called at first */
static void pin_power_up_callback(struct hda_codec *codec,
				  struct hda_jack_callback *jack)
{}

/* callback only doing power down -- called at last */
static void pin_power_down_callback(struct hda_codec *codec,
				    struct hda_jack_callback *jack)
{}

/* set up the power up/down callbacks */
static void add_pin_power_ctls(struct hda_codec *codec, int num_pins,
			       const hda_nid_t *pins, bool on)
{}

/* enabled power callback to each available I/O pin with jack detections;
 * the digital I/O pins are excluded because of the unreliable detectsion
 */
static void add_all_pin_power_ctls(struct hda_codec *codec, bool on)
{}

/* sync path power up/down with the jack states of given pins */
static void sync_pin_power_ctls(struct hda_codec *codec, int num_pins,
				const hda_nid_t *pins)
{}

/* sync path power up/down with pins; called at init and resume */
static void sync_all_pin_power_ctls(struct hda_codec *codec)
{}

/* add fake paths if not present yet */
static int add_fake_paths(struct hda_codec *codec, hda_nid_t nid,
			   int num_pins, const hda_nid_t *pins)
{}

/* create fake paths to all outputs from beep */
static int add_fake_beep_paths(struct hda_codec *codec)
{}

/* power up/down beep widget and its output paths */
static void beep_power_hook(struct hda_beep *beep, bool on)
{}

/**
 * snd_hda_gen_fix_pin_power - Fix the power of the given pin widget to D0
 * @codec: the HDA codec
 * @pin: NID of pin to fix
 */
int snd_hda_gen_fix_pin_power(struct hda_codec *codec, hda_nid_t pin)
{}
EXPORT_SYMBOL_GPL();

/*
 * Jack detections for HP auto-mute and mic-switch
 */

/* check each pin in the given array; returns true if any of them is plugged */
static bool detect_jacks(struct hda_codec *codec, int num_pins, const hda_nid_t *pins)
{}

/* standard HP/line-out auto-mute helper */
static void do_automute(struct hda_codec *codec, int num_pins, const hda_nid_t *pins,
			int *paths, bool mute)
{}

/**
 * snd_hda_gen_update_outputs - Toggle outputs muting
 * @codec: the HDA codec
 *
 * Update the mute status of all outputs based on the current jack states.
 */
void snd_hda_gen_update_outputs(struct hda_codec *codec)
{}
EXPORT_SYMBOL_GPL();

static void call_update_outputs(struct hda_codec *codec)
{}

/**
 * snd_hda_gen_hp_automute - standard HP-automute helper
 * @codec: the HDA codec
 * @jack: jack object, NULL for the whole
 */
void snd_hda_gen_hp_automute(struct hda_codec *codec,
			     struct hda_jack_callback *jack)
{}
EXPORT_SYMBOL_GPL();

/**
 * snd_hda_gen_line_automute - standard line-out-automute helper
 * @codec: the HDA codec
 * @jack: jack object, NULL for the whole
 */
void snd_hda_gen_line_automute(struct hda_codec *codec,
			       struct hda_jack_callback *jack)
{}
EXPORT_SYMBOL_GPL();

/**
 * snd_hda_gen_mic_autoswitch - standard mic auto-switch helper
 * @codec: the HDA codec
 * @jack: jack object, NULL for the whole
 */
void snd_hda_gen_mic_autoswitch(struct hda_codec *codec,
				struct hda_jack_callback *jack)
{}
EXPORT_SYMBOL_GPL();

/* call appropriate hooks */
static void call_hp_automute(struct hda_codec *codec,
			     struct hda_jack_callback *jack)
{}

static void call_line_automute(struct hda_codec *codec,
			       struct hda_jack_callback *jack)
{}

static void call_mic_autoswitch(struct hda_codec *codec,
				struct hda_jack_callback *jack)
{}

/* update jack retasking */
static void update_automute_all(struct hda_codec *codec)
{}

/*
 * Auto-Mute mode mixer enum support
 */
static int automute_mode_info(struct snd_kcontrol *kcontrol,
			      struct snd_ctl_elem_info *uinfo)
{}

static int automute_mode_get(struct snd_kcontrol *kcontrol,
			     struct snd_ctl_elem_value *ucontrol)
{}

static int automute_mode_put(struct snd_kcontrol *kcontrol,
			     struct snd_ctl_elem_value *ucontrol)
{}

static const struct snd_kcontrol_new automute_mode_enum =;

static int add_automute_mode_enum(struct hda_codec *codec)
{}

/*
 * Check the availability of HP/line-out auto-mute;
 * Set up appropriately if really supported
 */
static int check_auto_mute_availability(struct hda_codec *codec)
{}

/* check whether all auto-mic pins are valid; setup indices if OK */
static bool auto_mic_check_imux(struct hda_codec *codec)
{}

static int compare_attr(const void *ap, const void *bp)
{}

/*
 * Check the availability of auto-mic switch;
 * Set up if really supported
 */
static int check_auto_mic_availability(struct hda_codec *codec)
{}

/**
 * snd_hda_gen_path_power_filter - power_filter hook to make inactive widgets
 * into power down
 * @codec: the HDA codec
 * @nid: NID to evalute
 * @power_state: target power state
 */
unsigned int snd_hda_gen_path_power_filter(struct hda_codec *codec,
						  hda_nid_t nid,
						  unsigned int power_state)
{}
EXPORT_SYMBOL_GPL();

/* mute all aamix inputs initially; parse up to the first leaves */
static void mute_all_mixer_nid(struct hda_codec *codec, hda_nid_t mix)
{}

/**
 * snd_hda_gen_stream_pm - Stream power management callback
 * @codec: the HDA codec
 * @nid: audio widget
 * @on: power on/off flag
 *
 * Set this in patch_ops.stream_pm.  Only valid with power_save_node flag.
 */
void snd_hda_gen_stream_pm(struct hda_codec *codec, hda_nid_t nid, bool on)
{}
EXPORT_SYMBOL_GPL();

/* forcibly mute the speaker output without caching; return true if updated */
static bool force_mute_output_path(struct hda_codec *codec, hda_nid_t nid)
{}

/**
 * snd_hda_gen_shutup_speakers - Forcibly mute the speaker outputs
 * @codec: the HDA codec
 *
 * Forcibly mute the speaker outputs, to be called at suspend or shutdown.
 *
 * The mute state done by this function isn't cached, hence the original state
 * will be restored at resume.
 *
 * Return true if the mute state has been changed.
 */
bool snd_hda_gen_shutup_speakers(struct hda_codec *codec)
{}
EXPORT_SYMBOL_GPL();

/**
 * snd_hda_gen_parse_auto_config - Parse the given BIOS configuration and
 * set up the hda_gen_spec
 * @codec: the HDA codec
 * @cfg: Parsed pin configuration
 *
 * return 1 if successful, 0 if the proper config is not found,
 * or a negative error code
 */
int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
				  struct auto_pin_cfg *cfg)
{}
EXPORT_SYMBOL_GPL();


/*
 * Build control elements
 */

/* follower controls for virtual master */
static const char * const follower_pfxs[] =;

/**
 * snd_hda_gen_build_controls - Build controls from the parsed results
 * @codec: the HDA codec
 *
 * Pass this to build_controls patch_ops.
 */
int snd_hda_gen_build_controls(struct hda_codec *codec)
{}
EXPORT_SYMBOL_GPL();


/*
 * PCM definitions
 */

static void call_pcm_playback_hook(struct hda_pcm_stream *hinfo,
				   struct hda_codec *codec,
				   struct snd_pcm_substream *substream,
				   int action)
{}

static void call_pcm_capture_hook(struct hda_pcm_stream *hinfo,
				  struct hda_codec *codec,
				  struct snd_pcm_substream *substream,
				  int action)
{}

/*
 * Analog playback callbacks
 */
static int playback_pcm_open(struct hda_pcm_stream *hinfo,
			     struct hda_codec *codec,
			     struct snd_pcm_substream *substream)
{}

static int playback_pcm_prepare(struct hda_pcm_stream *hinfo,
				struct hda_codec *codec,
				unsigned int stream_tag,
				unsigned int format,
				struct snd_pcm_substream *substream)
{}

static int playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
				struct hda_codec *codec,
				struct snd_pcm_substream *substream)
{}

static int playback_pcm_close(struct hda_pcm_stream *hinfo,
			      struct hda_codec *codec,
			      struct snd_pcm_substream *substream)
{}

static int capture_pcm_open(struct hda_pcm_stream *hinfo,
			    struct hda_codec *codec,
			    struct snd_pcm_substream *substream)
{}

static int capture_pcm_prepare(struct hda_pcm_stream *hinfo,
			       struct hda_codec *codec,
			       unsigned int stream_tag,
			       unsigned int format,
			       struct snd_pcm_substream *substream)
{}

static int capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
			       struct hda_codec *codec,
			       struct snd_pcm_substream *substream)
{}

static int capture_pcm_close(struct hda_pcm_stream *hinfo,
			     struct hda_codec *codec,
			     struct snd_pcm_substream *substream)
{}

static int alt_playback_pcm_open(struct hda_pcm_stream *hinfo,
				 struct hda_codec *codec,
				 struct snd_pcm_substream *substream)
{}

static int alt_playback_pcm_close(struct hda_pcm_stream *hinfo,
				  struct hda_codec *codec,
				  struct snd_pcm_substream *substream)
{}

static int alt_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
				    struct hda_codec *codec,
				    unsigned int stream_tag,
				    unsigned int format,
				    struct snd_pcm_substream *substream)
{}

static int alt_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
				    struct hda_codec *codec,
				    struct snd_pcm_substream *substream)
{}

/*
 * Digital out
 */
static int dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
				 struct hda_codec *codec,
				 struct snd_pcm_substream *substream)
{}

static int dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
				    struct hda_codec *codec,
				    unsigned int stream_tag,
				    unsigned int format,
				    struct snd_pcm_substream *substream)
{}

static int dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
				    struct hda_codec *codec,
				    struct snd_pcm_substream *substream)
{}

static int dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
				  struct hda_codec *codec,
				  struct snd_pcm_substream *substream)
{}

/*
 * Analog capture
 */
#define alt_capture_pcm_open
#define alt_capture_pcm_close

static int alt_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
				   struct hda_codec *codec,
				   unsigned int stream_tag,
				   unsigned int format,
				   struct snd_pcm_substream *substream)
{}

static int alt_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
				   struct hda_codec *codec,
				   struct snd_pcm_substream *substream)
{}

/*
 */
static const struct hda_pcm_stream pcm_analog_playback =;

static const struct hda_pcm_stream pcm_analog_capture =;

static const struct hda_pcm_stream pcm_analog_alt_playback =;

static const struct hda_pcm_stream pcm_analog_alt_capture =;

static const struct hda_pcm_stream pcm_digital_playback =;

static const struct hda_pcm_stream pcm_digital_capture =;

/* Used by build_pcms to flag that a PCM has no playback stream */
static const struct hda_pcm_stream pcm_null_stream =;

/*
 * dynamic changing ADC PCM streams
 */
static bool dyn_adc_pcm_resetup(struct hda_codec *codec, int cur)
{}

/* analog capture with dynamic dual-adc changes */
static int dyn_adc_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
				       struct hda_codec *codec,
				       unsigned int stream_tag,
				       unsigned int format,
				       struct snd_pcm_substream *substream)
{}

static int dyn_adc_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
				       struct hda_codec *codec,
				       struct snd_pcm_substream *substream)
{}

static const struct hda_pcm_stream dyn_adc_pcm_analog_capture =;

static void fill_pcm_stream_name(char *str, size_t len, const char *sfx,
				 const char *chip_name)
{}

/* copy PCM stream info from @default_str, and override non-NULL entries
 * from @spec_str and @nid
 */
static void setup_pcm_stream(struct hda_pcm_stream *str,
			     const struct hda_pcm_stream *default_str,
			     const struct hda_pcm_stream *spec_str,
			     hda_nid_t nid)
{}

/**
 * snd_hda_gen_build_pcms - build PCM streams based on the parsed results
 * @codec: the HDA codec
 *
 * Pass this to build_pcms patch_ops.
 */
int snd_hda_gen_build_pcms(struct hda_codec *codec)
{}
EXPORT_SYMBOL_GPL();


/*
 * Standard auto-parser initializations
 */

/* configure the given path as a proper output */
static void set_output_and_unmute(struct hda_codec *codec, int path_idx)
{}

/* initialize primary output paths */
static void init_multi_out(struct hda_codec *codec)
{}


static void __init_extra_out(struct hda_codec *codec, int num_outs, int *paths)
{}

/* initialize hp and speaker paths */
static void init_extra_out(struct hda_codec *codec)
{}

/* initialize multi-io paths */
static void init_multi_io(struct hda_codec *codec)
{}

static void init_aamix_paths(struct hda_codec *codec)
{}

/* set up input pins and loopback paths */
static void init_analog_input(struct hda_codec *codec)
{}

/* initialize ADC paths */
static void init_input_src(struct hda_codec *codec)
{}

/* set right pin controls for digital I/O */
static void init_digital(struct hda_codec *codec)
{}

/* clear unsol-event tags on unused pins; Conexant codecs seem to leave
 * invalid unsol tags by some reason
 */
static void clear_unsol_on_unused_pins(struct hda_codec *codec)
{}

/**
 * snd_hda_gen_init - initialize the generic spec
 * @codec: the HDA codec
 *
 * This can be put as patch_ops init function.
 */
int snd_hda_gen_init(struct hda_codec *codec)
{}
EXPORT_SYMBOL_GPL();

/**
 * snd_hda_gen_free - free the generic spec
 * @codec: the HDA codec
 *
 * This can be put as patch_ops free function.
 */
void snd_hda_gen_free(struct hda_codec *codec)
{}
EXPORT_SYMBOL_GPL();

/**
 * snd_hda_gen_check_power_status - check the loopback power save state
 * @codec: the HDA codec
 * @nid: NID to inspect
 *
 * This can be put as patch_ops check_power_status function.
 */
int snd_hda_gen_check_power_status(struct hda_codec *codec, hda_nid_t nid)
{}
EXPORT_SYMBOL_GPL();


/*
 * the generic codec support
 */

static const struct hda_codec_ops generic_patch_ops =;

/*
 * snd_hda_parse_generic_codec - Generic codec parser
 * @codec: the HDA codec
 */
static int snd_hda_parse_generic_codec(struct hda_codec *codec)
{}

static const struct hda_device_id snd_hda_id_generic[] =;
MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_generic);

static struct hda_codec_driver generic_driver =;

module_hda_codec_driver();

MODULE_LICENSE();
MODULE_DESCRIPTION();