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

Commit 10a20af7 authored by Takashi Iwai's avatar Takashi Iwai
Browse files

ALSA: hda - Improve the input source name labels



This patch improves the input-source label strings to be generated from
the pin information instead of fixed strings per AUTO_PIN_* type.
This gives more suitable labels, especially for mic and line-in pins.

Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 86e2959a
Loading
Loading
Loading
Loading
+75 −16
Original line number Diff line number Diff line
@@ -4607,7 +4607,7 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
	snd_printd("   inputs:");
	for (i = 0; i < cfg->num_inputs; i++) {
		snd_printdd(" %s=0x%x",
			    auto_pin_cfg_labels[cfg->inputs[i].type],
			    hda_get_autocfg_input_label(codec, cfg, i),
			    cfg->inputs[i].pin);
	}
	snd_printd("\n");
@@ -4618,28 +4618,87 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
}
EXPORT_SYMBOL_HDA(snd_hda_parse_pin_def_config);

/* labels for input pins - for obsoleted config stuff */
const char *auto_pin_cfg_labels[AUTO_PIN_LAST] = {
	"Mic", "Line", "CD", "Aux"
};
EXPORT_SYMBOL_HDA(auto_pin_cfg_labels);
const char *hda_get_input_pin_label(struct hda_codec *codec, hda_nid_t pin,
					int check_location)
{
	unsigned int def_conf, loc;

	def_conf = snd_hda_codec_get_pincfg(codec, pin);
	loc = get_defcfg_location(def_conf);

void snd_hda_get_input_pin_label(const struct auto_pin_cfg *cfg,
				 int input, char *str)
	switch (get_defcfg_device(def_conf)) {
	case AC_JACK_MIC_IN:
		if (!check_location)
			return "Mic";
		if (get_defcfg_connect(def_conf) == AC_JACK_PORT_FIXED ||
		    (loc & 0x30) == AC_JACK_LOC_INTERNAL)
			return "Internal Mic";
		if ((loc & 0x30) == AC_JACK_LOC_SEPARATE)
			return "Dock Mic";
		if (loc == AC_JACK_LOC_REAR)
			return "Rear Mic";
		return "Mic";
	case AC_JACK_LINE_IN:
		if (!check_location)
			return "Line";
		if ((loc & 0xf0) == AC_JACK_LOC_SEPARATE)
			return "Dock Line";
		return "Line";
	case AC_JACK_AUX:
		return "Aux";
	case AC_JACK_CD:
		return "CD";
	case AC_JACK_SPDIF_IN:
		return "SPDIF In";
	case AC_JACK_DIG_OTHER_IN:
		return "Digital In";
	default:
		return "Misc";
	}
}
EXPORT_SYMBOL_HDA(hda_get_input_pin_label);

const char *hda_get_autocfg_input_label(struct hda_codec *codec,
					const struct auto_pin_cfg *cfg,
					int input)
{
	int type = cfg->inputs[input].type;
	int idx;
	int has_multiple_pins = 0;

	for  (idx = 0; idx < 3 && --input >= 0; idx++) {
		if (type != cfg->inputs[input].type)
			break;
	if ((input > 0 && cfg->inputs[input - 1].type == type) ||
	    (input < cfg->num_inputs - 1 && cfg->inputs[input + 1].type == type))
		has_multiple_pins = 1;
	return hda_get_input_pin_label(codec, cfg->inputs[input].pin,
				       has_multiple_pins);
}
	if (idx > 0)
		sprintf(str, "%s %d", auto_pin_cfg_labels[type], idx);
EXPORT_SYMBOL_HDA(hda_get_autocfg_input_label);

int snd_hda_add_imux_item(struct hda_input_mux *imux, const char *label,
			  int index, int *type_idx)
{
	int i, label_idx = 0;
	if (imux->num_items >= HDA_MAX_NUM_INPUTS) {
		snd_printd(KERN_ERR "hda_codec: Too many imux items!\n");
		return -EINVAL;
	}
	for (i = 0; i < imux->num_items; i++) {
		if (!strncmp(label, imux->items[i].label, strlen(label)))
			label_idx++;
	}
	if (type_idx)
		*type_idx = label_idx;
	if (label_idx > 0)
		snprintf(imux->items[imux->num_items].label,
			 sizeof(imux->items[imux->num_items].label),
			 "%s %d", label, label_idx);
	else
		strcpy(str, auto_pin_cfg_labels[type]);
		strlcpy(imux->items[imux->num_items].label, label,
			sizeof(imux->items[imux->num_items].label));
	imux->items[imux->num_items].index = index;
	imux->num_items++;
	return 0;
}
EXPORT_SYMBOL_HDA(snd_hda_get_input_pin_label);
EXPORT_SYMBOL_HDA(snd_hda_add_imux_item);


#ifdef CONFIG_PM
+5 −36
Original line number Diff line number Diff line
@@ -61,7 +61,6 @@ struct hda_gspec {
	struct hda_gnode *cap_vol_node;	/* Node for capture volume */
	unsigned int cur_cap_src;	/* current capture source */
	struct hda_input_mux input_mux;
	char cap_labels[HDA_MAX_NUM_INPUTS][16];

	unsigned int def_amp_in_caps;
	unsigned int def_amp_out_caps;
@@ -506,11 +505,10 @@ static const char *get_input_type(struct hda_gnode *node, unsigned int *pinctl)
 * returns 0 if not found, 1 if found, or a negative error code.
 */
static int parse_adc_sub_nodes(struct hda_codec *codec, struct hda_gspec *spec,
			       struct hda_gnode *node)
			       struct hda_gnode *node, int idx)
{
	int i, err;
	unsigned int pinctl;
	char *label;
	const char *type;

	if (node->checked)
@@ -523,7 +521,7 @@ static int parse_adc_sub_nodes(struct hda_codec *codec, struct hda_gspec *spec,
			child = hda_get_node(spec, node->conn_list[i]);
			if (! child)
				continue;
			err = parse_adc_sub_nodes(codec, spec, child);
			err = parse_adc_sub_nodes(codec, spec, child, idx);
			if (err < 0)
				return err;
			if (err > 0) {
@@ -564,9 +562,7 @@ static int parse_adc_sub_nodes(struct hda_codec *codec, struct hda_gspec *spec,
			return 0;
		type = "Input";
	}
	label = spec->cap_labels[spec->input_mux.num_items];
	strcpy(label, type);
	strcpy(spec->input_mux.items[spec->input_mux.num_items].label, label);
	snd_hda_add_imux_item(&spec->input_mux, type, idx, NULL);

	/* unmute the PIN external input */
	unmute_input(codec, node, 0); /* index = 0? */
@@ -577,29 +573,6 @@ static int parse_adc_sub_nodes(struct hda_codec *codec, struct hda_gspec *spec,
	return 1; /* found */
}

/* add a capture source element */
static void add_cap_src(struct hda_gspec *spec, int idx)
{
	struct hda_input_mux_item *csrc;
	char *buf;
	int num, ocap;

	num = spec->input_mux.num_items;
	csrc = &spec->input_mux.items[num];
	buf = spec->cap_labels[num];
	for (ocap = 0; ocap < num; ocap++) {
		if (! strcmp(buf, spec->cap_labels[ocap])) {
			/* same label already exists,
			 * put the index number to be unique
			 */
			sprintf(buf, "%s %d", spec->cap_labels[ocap], num);
			break;
		}
	}
	csrc->index = idx;
	spec->input_mux.num_items++;
}

/*
 * parse input
 */
@@ -624,22 +597,18 @@ static int parse_input_path(struct hda_codec *codec, struct hda_gnode *adc_node)
	for (i = 0; i < adc_node->nconns; i++) {
		node = hda_get_node(spec, adc_node->conn_list[i]);
		if (node && node->type == AC_WID_PIN) {
			err = parse_adc_sub_nodes(codec, spec, node);
			err = parse_adc_sub_nodes(codec, spec, node, i);
			if (err < 0)
				return err;
			else if (err > 0)
				add_cap_src(spec, i);
		}
	}
	/* ... then check the rests, more complicated connections */
	for (i = 0; i < adc_node->nconns; i++) {
		node = hda_get_node(spec, adc_node->conn_list[i]);
		if (node && node->type != AC_WID_PIN) {
			err = parse_adc_sub_nodes(codec, spec, node);
			err = parse_adc_sub_nodes(codec, spec, node, i);
			if (err < 0)
				return err;
			else if (err > 0)
				add_cap_src(spec, i);
		}
	}

+7 −4
Original line number Diff line number Diff line
@@ -378,8 +378,6 @@ enum {
	AUTO_PIN_HP_OUT
};

extern const char *auto_pin_cfg_labels[AUTO_PIN_LAST];

#define AUTO_CFG_MAX_OUTS	5
#define AUTO_CFG_MAX_INS	8

@@ -389,8 +387,13 @@ struct auto_pin_cfg_item {
};

struct auto_pin_cfg;
void snd_hda_get_input_pin_label(const struct auto_pin_cfg *cfg,
				 int input, char *label);
const char *hda_get_input_pin_label(struct hda_codec *codec, hda_nid_t pin,
				    int check_location);
const char *hda_get_autocfg_input_label(struct hda_codec *codec,
					const struct auto_pin_cfg *cfg,
					int input);
int snd_hda_add_imux_item(struct hda_input_mux *imux, const char *label,
			  int index, int *type_index_ret);

struct auto_pin_cfg {
	int line_outs;
+11 −16
Original line number Diff line number Diff line
@@ -2909,32 +2909,27 @@ static int new_analog_input(struct ad198x_spec *spec, hda_nid_t pin,
}

/* create playback/capture controls for input pins */
static int ad1988_auto_create_analog_input_ctls(struct ad198x_spec *spec,
static int ad1988_auto_create_analog_input_ctls(struct hda_codec *codec,
						const struct auto_pin_cfg *cfg)
{
	struct ad198x_spec *spec = codec->spec;
	struct hda_input_mux *imux = &spec->private_imux;
	int i, err, type, type_idx = 0;
	int i, err, type, type_idx;

	for (i = 0; i < cfg->num_inputs; i++) {
		const char *label;
		type = cfg->inputs[i].type;
		if (i > 0 && type != cfg->inputs[i - 1].type)
			type_idx++;
		else
			type_idx = 0;
		label = hda_get_autocfg_input_label(codec, cfg, i);
		snd_hda_add_imux_item(imux, label,
				      ad1988_pin_to_adc_idx(cfg->inputs[i].pin),
				      &type_idx);
		err = new_analog_input(spec, cfg->inputs[i].pin,
				       auto_pin_cfg_labels[type], type_idx,
				       label, type_idx,
				       type == AUTO_PIN_MIC);
		if (err < 0)
			return err;
		snd_hda_get_input_pin_label(cfg, i,
			imux->items[imux->num_items].label);
		imux->items[imux->num_items].index =
			ad1988_pin_to_adc_idx(cfg->inputs[i].pin);
		imux->num_items++;
	}
	strcpy(imux->items[imux->num_items].label, "Mix");
	imux->items[imux->num_items].index = 9;
	imux->num_items++;
	snd_hda_add_imux_item(imux, "Mix", 9, NULL);

	if ((err = add_control(spec, AD_CTL_WIDGET_VOL,
			       "Analog Mix Playback Volume",
@@ -3046,7 +3041,7 @@ static int ad1988_parse_auto_config(struct hda_codec *codec)
						"Speaker")) < 0 ||
	    (err = ad1988_auto_create_extra_out(codec, spec->autocfg.hp_pins[0],
						"Headphone")) < 0 ||
	    (err = ad1988_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
	    (err = ad1988_auto_create_analog_input_ctls(codec, &spec->autocfg)) < 0)
		return err;

	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
+1 −2
Original line number Diff line number Diff line
@@ -474,8 +474,7 @@ static void parse_input(struct hda_codec *codec)
		if (j >= cfg->num_inputs)
			continue;
		spec->input_pins[n] = pin;
		spec->input_labels[n] =
			auto_pin_cfg_labels[cfg->inputs[j].type];
		spec->input_labels[n] = hda_get_input_pin_label(codec, pin, 1);
		spec->adcs[n] = nid;
		n++;
	}
Loading