Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2cf215bf authored by Takashi Iwai's avatar Takashi Iwai
Browse files

Merge branch 'topic/hda-gen-parser' into for-next

This is a merge of really big changes: the generic parser is heavily
enhanced for handling all cases, based on the former Realtek codec
driver code.  And all codec drivers except for a few ones (CA0132,
HDMI and modem) have been converted to use the new generic driver.

Conflicts:
	sound/pci/hda/patch_realtek.c
parents e152f180 657e1b93
Loading
Loading
Loading
Loading
+8 −3
Original line number Diff line number Diff line
@@ -86,6 +86,7 @@ config SND_HDA_PATCH_LOADER
config SND_HDA_CODEC_REALTEK
	bool "Build Realtek HD-audio codec support"
	default y
	select SND_HDA_GENERIC
	help
	  Say Y here to include Realtek HD-audio codec support in
	  snd-hda-intel driver, such as ALC880.
@@ -98,6 +99,7 @@ config SND_HDA_CODEC_REALTEK
config SND_HDA_CODEC_ANALOG
	bool "Build Analog Device HD-audio codec support"
	default y
	select SND_HDA_GENERIC
	help
	  Say Y here to include Analog Device HD-audio codec support in
	  snd-hda-intel driver, such as AD1986A.
@@ -110,6 +112,7 @@ config SND_HDA_CODEC_ANALOG
config SND_HDA_CODEC_SIGMATEL
	bool "Build IDT/Sigmatel HD-audio codec support"
	default y
	select SND_HDA_GENERIC
	help
	  Say Y here to include IDT (Sigmatel) HD-audio codec support in
	  snd-hda-intel driver, such as STAC9200.
@@ -122,6 +125,7 @@ config SND_HDA_CODEC_SIGMATEL
config SND_HDA_CODEC_VIA
	bool "Build VIA HD-audio codec support"
	default y
	select SND_HDA_GENERIC
	help
	  Say Y here to include VIA HD-audio codec support in
	  snd-hda-intel driver, such as VT1708.
@@ -147,8 +151,8 @@ config SND_HDA_CODEC_HDMI

config SND_HDA_CODEC_CIRRUS
	bool "Build Cirrus Logic codec support"
	depends on SND_HDA_INTEL
	default y
	select SND_HDA_GENERIC
	help
	  Say Y here to include Cirrus Logic codec support in
	  snd-hda-intel driver, such as CS4206.
@@ -161,6 +165,7 @@ config SND_HDA_CODEC_CIRRUS
config SND_HDA_CODEC_CONEXANT
	bool "Build Conexant HD-audio codec support"
	default y
	select SND_HDA_GENERIC
	help
	  Say Y here to include Conexant HD-audio codec support in
	  snd-hda-intel driver, such as CX20549.
@@ -172,8 +177,8 @@ config SND_HDA_CODEC_CONEXANT

config SND_HDA_CODEC_CA0110
	bool "Build Creative CA0110-IBG codec support"
	depends on SND_HDA_INTEL
	default y
	select SND_HDA_GENERIC
	help
	  Say Y here to include Creative CA0110-IBG codec support in
	  snd-hda-intel driver, found on some Creative X-Fi cards.
@@ -185,7 +190,6 @@ config SND_HDA_CODEC_CA0110

config SND_HDA_CODEC_CA0132
	bool "Build Creative CA0132 codec support"
	depends on SND_HDA_INTEL
	default y
	help
	  Say Y here to include Creative CA0132 codec support in
@@ -199,6 +203,7 @@ config SND_HDA_CODEC_CA0132
config SND_HDA_CODEC_CMEDIA
	bool "Build C-Media HD-audio codec support"
	default y
	select SND_HDA_GENERIC
	help
	  Say Y here to include C-Media HD-audio codec support in
	  snd-hda-intel driver, such as CMI9880.
+82 −33
Original line number Diff line number Diff line
@@ -97,6 +97,28 @@ static void reorder_outputs(unsigned int nums, hda_nid_t *pins)
	}
}

/* check whether the given pin has a proper pin I/O capability bit */
static bool check_pincap_validity(struct hda_codec *codec, hda_nid_t pin,
				  unsigned int dev)
{
	unsigned int pincap = snd_hda_query_pin_caps(codec, pin);

	/* some old hardware don't return the proper pincaps */
	if (!pincap)
		return true;

	switch (dev) {
	case AC_JACK_LINE_OUT:
	case AC_JACK_SPEAKER:
	case AC_JACK_HP_OUT:
	case AC_JACK_SPDIF_OUT:
	case AC_JACK_DIG_OTHER_OUT:
		return !!(pincap & AC_PINCAP_OUT);
	default:
		return !!(pincap & AC_PINCAP_IN);
	}
}

/*
 * Parse all pin widgets and store the useful pin nids to cfg
 *
@@ -126,6 +148,9 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec,
	struct auto_out_pin hp_out[ARRAY_SIZE(cfg->hp_pins)];
	int i;

	if (!snd_hda_get_int_hint(codec, "parser_flags", &i))
		cond_flags = i;

	memset(cfg, 0, sizeof(*cfg));

	memset(line_out, 0, sizeof(line_out));
@@ -156,10 +181,14 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec,

		/* workaround for buggy BIOS setups */
		if (dev == AC_JACK_LINE_OUT) {
			if (conn == AC_JACK_PORT_FIXED)
			if (conn == AC_JACK_PORT_FIXED ||
			    conn == AC_JACK_PORT_BOTH)
				dev = AC_JACK_SPEAKER;
		}

		if (!check_pincap_validity(codec, nid, dev))
			continue;

		switch (dev) {
		case AC_JACK_LINE_OUT:
			seq = get_defcfg_sequence(def_conf);
@@ -363,7 +392,7 @@ static const char *hda_get_input_pin_label(struct hda_codec *codec,
{
	unsigned int def_conf;
	static const char * const mic_names[] = {
		"Internal Mic", "Dock Mic", "Mic", "Front Mic", "Rear Mic",
		"Internal Mic", "Dock Mic", "Mic", "Rear Mic", "Front Mic"
	};
	int attr;

@@ -394,6 +423,8 @@ static const char *hda_get_input_pin_label(struct hda_codec *codec,
		return "SPDIF In";
	case AC_JACK_DIG_OTHER_IN:
		return "Digital In";
	case AC_JACK_HP_OUT:
		return "Headphone Mic";
	default:
		return "Misc";
	}
@@ -552,6 +583,9 @@ static int fill_audio_out_name(struct hda_codec *codec, hda_nid_t nid,
	return 1;
}

#define is_hdmi_cfg(conf) \
	(get_defcfg_location(conf) == AC_JACK_LOC_HDMI)

/**
 * snd_hda_get_pin_label - Get a label for the given I/O pin
 *
@@ -572,6 +606,7 @@ int snd_hda_get_pin_label(struct hda_codec *codec, hda_nid_t nid,
	unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid);
	const char *name = NULL;
	int i;
	bool hdmi;

	if (indexp)
		*indexp = 0;
@@ -590,15 +625,17 @@ int snd_hda_get_pin_label(struct hda_codec *codec, hda_nid_t nid,
					   label, maxlen, indexp);
	case AC_JACK_SPDIF_OUT:
	case AC_JACK_DIG_OTHER_OUT:
		if (get_defcfg_location(def_conf) == AC_JACK_LOC_HDMI)
			name = "HDMI";
		else
			name = "SPDIF";
		if (cfg && indexp) {
			i = find_idx_in_nid_list(nid, cfg->dig_out_pins,
						 cfg->dig_outs);
			if (i >= 0)
				*indexp = i;
		hdmi = is_hdmi_cfg(def_conf);
		name = hdmi ? "HDMI" : "SPDIF";
		if (cfg && indexp)
			for (i = 0; i < cfg->dig_outs; i++) {
				hda_nid_t pin = cfg->dig_out_pins[i];
				unsigned int c;
				if (pin == nid)
					break;
				c = snd_hda_codec_get_pincfg(codec, pin);
				if (hdmi == is_hdmi_cfg(c))
					(*indexp)++;
			}
		break;
	default:
@@ -622,28 +659,27 @@ int snd_hda_get_pin_label(struct hda_codec *codec, hda_nid_t nid,
}
EXPORT_SYMBOL_HDA(snd_hda_get_pin_label);

int snd_hda_gen_add_verbs(struct hda_gen_spec *spec,
int snd_hda_add_verbs(struct hda_codec *codec,
		      const struct hda_verb *list)
{
	const struct hda_verb **v;
	v = snd_array_new(&spec->verbs);
	v = snd_array_new(&codec->verbs);
	if (!v)
		return -ENOMEM;
	*v = list;
	return 0;
}
EXPORT_SYMBOL_HDA(snd_hda_gen_add_verbs);
EXPORT_SYMBOL_HDA(snd_hda_add_verbs);

void snd_hda_gen_apply_verbs(struct hda_codec *codec)
void snd_hda_apply_verbs(struct hda_codec *codec)
{
	struct hda_gen_spec *spec = codec->spec;
	int i;
	for (i = 0; i < spec->verbs.used; i++) {
		struct hda_verb **v = snd_array_elem(&spec->verbs, i);
	for (i = 0; i < codec->verbs.used; i++) {
		struct hda_verb **v = snd_array_elem(&codec->verbs, i);
		snd_hda_sequence_write(codec, *v);
	}
}
EXPORT_SYMBOL_HDA(snd_hda_gen_apply_verbs);
EXPORT_SYMBOL_HDA(snd_hda_apply_verbs);

void snd_hda_apply_pincfgs(struct hda_codec *codec,
			   const struct hda_pintbl *cfg)
@@ -653,20 +689,26 @@ void snd_hda_apply_pincfgs(struct hda_codec *codec,
}
EXPORT_SYMBOL_HDA(snd_hda_apply_pincfgs);

static void set_pin_targets(struct hda_codec *codec,
			    const struct hda_pintbl *cfg)
{
	for (; cfg->nid; cfg++)
		snd_hda_set_pin_ctl_cache(codec, cfg->nid, cfg->val);
}

void snd_hda_apply_fixup(struct hda_codec *codec, int action)
{
	struct hda_gen_spec *spec = codec->spec;
	int id = spec->fixup_id;
	int id = codec->fixup_id;
#ifdef CONFIG_SND_DEBUG_VERBOSE
	const char *modelname = spec->fixup_name;
	const char *modelname = codec->fixup_name;
#endif
	int depth = 0;

	if (!spec->fixup_list)
	if (!codec->fixup_list)
		return;

	while (id >= 0) {
		const struct hda_fixup *fix = spec->fixup_list + id;
		const struct hda_fixup *fix = codec->fixup_list + id;

		switch (fix->type) {
		case HDA_FIXUP_PINS:
@@ -683,7 +725,7 @@ void snd_hda_apply_fixup(struct hda_codec *codec, int action)
			snd_printdd(KERN_INFO SFX
				    "%s: Apply fix-verbs for %s\n",
				    codec->chip_name, modelname);
			snd_hda_gen_add_verbs(codec->spec, fix->v.verbs);
			snd_hda_add_verbs(codec, fix->v.verbs);
			break;
		case HDA_FIXUP_FUNC:
			if (!fix->v.func)
@@ -693,6 +735,14 @@ void snd_hda_apply_fixup(struct hda_codec *codec, int action)
				    codec->chip_name, modelname);
			fix->v.func(codec, fix, action);
			break;
		case HDA_FIXUP_PINCTLS:
			if (action != HDA_FIXUP_ACT_PROBE || !fix->v.pins)
				break;
			snd_printdd(KERN_INFO SFX
				    "%s: Apply pinctl for %s\n",
				    codec->chip_name, modelname);
			set_pin_targets(codec, fix->v.pins);
			break;
		default:
			snd_printk(KERN_ERR SFX
				   "%s: Invalid fixup type %d\n",
@@ -713,15 +763,14 @@ void snd_hda_pick_fixup(struct hda_codec *codec,
			const struct snd_pci_quirk *quirk,
			const struct hda_fixup *fixlist)
{
	struct hda_gen_spec *spec = codec->spec;
	const struct snd_pci_quirk *q;
	int id = -1;
	const char *name = NULL;

	/* when model=nofixup is given, don't pick up any fixups */
	if (codec->modelname && !strcmp(codec->modelname, "nofixup")) {
		spec->fixup_list = NULL;
		spec->fixup_id = -1;
		codec->fixup_list = NULL;
		codec->fixup_id = -1;
		return;
	}

@@ -759,10 +808,10 @@ void snd_hda_pick_fixup(struct hda_codec *codec,
		}
	}

	spec->fixup_id = id;
	codec->fixup_id = id;
	if (id >= 0) {
		spec->fixup_list = fixlist;
		spec->fixup_name = name;
		codec->fixup_list = fixlist;
		codec->fixup_name = name;
	}
}
EXPORT_SYMBOL_HDA(snd_hda_pick_fixup);
+2 −79
Original line number Diff line number Diff line
@@ -51,8 +51,9 @@ enum {
	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_FRONT,	/* mic/line-in jack in front */
	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);
@@ -89,82 +90,4 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec,
#define snd_hda_parse_pin_def_config(codec, cfg, ignore) \
	snd_hda_parse_pin_defcfg(codec, cfg, ignore, 0)

/*
 */

struct hda_gen_spec {
	/* fix-up list */
	int fixup_id;
	const struct hda_fixup *fixup_list;
	const char *fixup_name;

	/* additional init verbs */
	struct snd_array verbs;
};


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

/* fixup types */
enum {
	HDA_FIXUP_INVALID,
	HDA_FIXUP_PINS,
	HDA_FIXUP_VERBS,
	HDA_FIXUP_FUNC,
};

/* fixup action definitions */
enum {
	HDA_FIXUP_ACT_PRE_PROBE,
	HDA_FIXUP_ACT_PROBE,
	HDA_FIXUP_ACT_INIT,
	HDA_FIXUP_ACT_BUILD,
};

int snd_hda_gen_add_verbs(struct hda_gen_spec *spec,
			  const struct hda_verb *list);
void snd_hda_gen_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_pick_fixup(struct hda_codec *codec,
			const struct hda_model_fixup *models,
			const struct snd_pci_quirk *quirk,
			const struct hda_fixup *fixlist);

static inline void snd_hda_gen_init(struct hda_gen_spec *spec)
{
	snd_array_init(&spec->verbs, sizeof(struct hda_verb *), 8);
}

static inline void snd_hda_gen_free(struct hda_gen_spec *spec)
{
	snd_array_free(&spec->verbs);
}

#endif /* __SOUND_HDA_AUTO_PARSER_H */
+340 −129

File changed.

Preview size limit exceeded, changes collapsed.

+22 −11
Original line number Diff line number Diff line
@@ -719,9 +719,10 @@ struct hda_codec_ops {

/* record for amp information cache */
struct hda_cache_head {
	u32 key;		/* hash key */
	u32 key:31;		/* hash key */
	u32 dirty:1;
	u16 val;		/* assigned value */
	u16 next;		/* next link; -1 = terminal */
	u16 next;
};

struct hda_amp_info {
@@ -830,7 +831,7 @@ struct hda_codec {
	struct hda_cache_rec amp_cache;	/* cache for amp access */
	struct hda_cache_rec cmd_cache;	/* cache for other commands */

	struct snd_array conn_lists;	/* connection-list array */
	struct list_head conn_list;	/* linked-list of connection-list */

	struct mutex spdif_mutex;
	struct mutex control_mutex;
@@ -844,6 +845,7 @@ struct hda_codec {
	struct snd_array cvt_setups;	/* audio convert setups */

#ifdef CONFIG_SND_HDA_HWDEP
	struct mutex user_mutex;
	struct snd_hwdep *hwdep;	/* assigned hwdep device */
	struct snd_array init_verbs;	/* additional init verbs */
	struct snd_array hints;		/* additional hints */
@@ -865,8 +867,11 @@ struct hda_codec {
	unsigned int pins_shutup:1;	/* pins are shut up */
	unsigned int no_trigger_sense:1; /* don't trigger at pin-sensing */
	unsigned int no_jack_detect:1;	/* Machine has no jack-detection */
	unsigned int inv_eapd:1; /* broken h/w: inverted EAPD control */
	unsigned int inv_jack_detect:1;	/* broken h/w: inverted detection bit */
	unsigned int pcm_format_first:1; /* PCM format must be set first */
	unsigned int epss:1;		/* supporting EPSS? */
	unsigned int cached_write:1;	/* write only to caches */
#ifdef CONFIG_PM
	unsigned int power_on :1;	/* current (global) power-state */
	unsigned int d3_stop_clk:1;	/* support D3 operation without BCLK */
@@ -894,6 +899,14 @@ struct hda_codec {
	/* jack detection */
	struct snd_array jacks;
#endif

	/* fix-up list */
	int fixup_id;
	const struct hda_fixup *fixup_list;
	const char *fixup_name;

	/* additional init verbs */
	struct snd_array verbs;
};

/* direction */
@@ -932,6 +945,8 @@ snd_hda_get_num_conns(struct hda_codec *codec, hda_nid_t nid)
}
int snd_hda_get_raw_connections(struct hda_codec *codec, hda_nid_t nid,
			    hda_nid_t *conn_list, int max_conns);
int snd_hda_get_conn_list(struct hda_codec *codec, hda_nid_t nid,
			  const hda_nid_t **listp);
int snd_hda_override_conn_list(struct hda_codec *codec, hda_nid_t nid, int nums,
			  const hda_nid_t *list);
int snd_hda_get_conn_index(struct hda_codec *codec, hda_nid_t mux,
@@ -952,7 +967,6 @@ void snd_hda_sequence_write(struct hda_codec *codec,
int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex);

/* cached write */
#ifdef CONFIG_PM
int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
			      int direct, unsigned int verb, unsigned int parm);
void snd_hda_sequence_write_cache(struct hda_codec *codec,
@@ -960,17 +974,14 @@ void snd_hda_sequence_write_cache(struct hda_codec *codec,
int snd_hda_codec_update_cache(struct hda_codec *codec, hda_nid_t nid,
			      int direct, unsigned int verb, unsigned int parm);
void snd_hda_codec_resume_cache(struct hda_codec *codec);
#else
#define snd_hda_codec_write_cache	snd_hda_codec_write
#define snd_hda_codec_update_cache	snd_hda_codec_write
#define snd_hda_sequence_write_cache	snd_hda_sequence_write
#endif
/* both for cmd & amp caches */
void snd_hda_codec_flush_cache(struct hda_codec *codec);

/* the struct for codec->pin_configs */
struct hda_pincfg {
	hda_nid_t nid;
	unsigned char ctrl;	/* current pin control value */
	unsigned char pad;	/* reserved */
	unsigned char ctrl;	/* original pin control value */
	unsigned char target;	/* target pin control value */
	unsigned int cfg;	/* default configuration */
};

Loading