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