Ejemplo n.º 1
0
/* update the cached value and notification flag if needed */
static void jack_detect_update(struct hda_codec *codec,
			       struct hda_jack_tbl *jack)
{
	if (!jack->jack_dirty)
		return;

	if (jack->phantom_jack)
		jack->pin_sense = AC_PINSENSE_PRESENCE;
	else
		jack->pin_sense = read_pin_sense(codec, jack->nid);

	/* A gating jack indicates the jack is invalid if gating is unplugged */
	if (jack->gating_jack && !snd_hda_jack_detect(codec, jack->gating_jack))
		jack->pin_sense &= ~AC_PINSENSE_PRESENCE;

	jack->jack_dirty = 0;

	/* If a jack is gated by this one update it. */
	if (jack->gated_jack) {
		struct hda_jack_tbl *gated =
			snd_hda_jack_tbl_get(codec, jack->gated_jack);
		if (gated) {
			gated->jack_dirty = 1;
			jack_detect_update(codec, gated);
		}
	}
}
Ejemplo n.º 2
0
/**
 * snd_hda_jack_add_kctl - Add a kctl for the given pin
 *
 * This assigns a jack-detection kctl to the given pin.  The kcontrol
 * will have the given name and index.
 */
int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid,
			  const char *name, int idx)
{
	struct hda_jack_tbl *jack;
	struct snd_kcontrol *kctl;
	int err, state;

	jack = snd_hda_jack_tbl_new(codec, nid);
	if (!jack)
		return 0;
	if (jack->kctl)
		return 0; /* already created */
	kctl = snd_kctl_jack_new(name, idx, codec);
	if (!kctl)
		return -ENOMEM;
	err = snd_hda_ctl_add(codec, nid, kctl);
	if (err < 0)
		return err;
	jack->kctl = kctl;
	state = snd_hda_jack_detect(codec, nid);
	snd_kctl_jack_report(codec->bus->card, kctl, state);
#ifdef CONFIG_SND_HDA_INPUT_JACK
	jack->type = get_input_jack_type(codec, nid);
	err = snd_jack_new(codec->bus->card, name, jack->type, &jack->jack);
	if (err < 0)
		return err;
	jack->jack->private_data = jack;
	jack->jack->private_free = hda_free_jack_priv;
	snd_jack_report(jack->jack, state ? jack->type : 0);
#endif
	return 0;
}
Ejemplo n.º 3
0
static void cxt_update_headset_mode(struct hda_codec *codec)
{
	/* The verbs used in this function were tested on a Conexant CX20751/2 codec. */
	int i;
	bool mic_mode = false;
	struct conexant_spec *spec = codec->spec;
	struct auto_pin_cfg *cfg = &spec->gen.autocfg;

	hda_nid_t mux_pin = spec->gen.imux_pins[spec->gen.cur_mux[0]];

	for (i = 0; i < cfg->num_inputs; i++)
		if (cfg->inputs[i].pin == mux_pin) {
			mic_mode = !!cfg->inputs[i].is_headphone_mic;
			break;
		}

	if (mic_mode) {
		snd_hda_codec_write_cache(codec, 0x1c, 0, 0x410, 0x7c); /* enable merged mode for analog int-mic */
		spec->gen.hp_jack_present = false;
	} else {
		snd_hda_codec_write_cache(codec, 0x1c, 0, 0x410, 0x54); /* disable merged mode for analog int-mic */
		spec->gen.hp_jack_present = snd_hda_jack_detect(codec, spec->gen.autocfg.hp_pins[0]);
	}

	snd_hda_gen_update_outputs(codec);
}
Ejemplo n.º 4
0
static void cs_automic(struct hda_codec *codec)
{
	struct cs_spec *spec = codec->spec;
	struct auto_pin_cfg *cfg = &spec->autocfg;
	hda_nid_t nid;
	unsigned int present;

	nid = cfg->inputs[spec->automic_idx].pin;
	present = snd_hda_jack_detect(codec, nid);

	/* specific to CS421x, single ADC */
	if (spec->vendor_nid == CS421X_VENDOR_NID) {
		if (present) {
			spec->last_input = spec->cur_input;
			spec->cur_input = spec->automic_idx;
		} else  {
			spec->cur_input = spec->last_input;
		}

		snd_hda_codec_write_cache(codec, spec->cur_adc, 0,
					AC_VERB_SET_CONNECT_SEL,
					spec->adc_idx[spec->cur_input]);
	} else {
		if (present)
			change_cur_input(codec, spec->automic_idx, 0);
		else
			change_cur_input(codec, !spec->automic_idx, 0);
	}
}
Ejemplo n.º 5
0
static void cs_automute(struct hda_codec *codec)
{
	struct cs_spec *spec = codec->spec;
	struct auto_pin_cfg *cfg = &spec->autocfg;
	unsigned int caps, hp_present;
	hda_nid_t nid;
	int i;

	hp_present = 0;
	for (i = 0; i < cfg->hp_outs; i++) {
		nid = cfg->hp_pins[i];
		caps = snd_hda_query_pin_caps(codec, nid);
		if (!(caps & AC_PINCAP_PRES_DETECT))
			continue;
		hp_present = snd_hda_jack_detect(codec, nid);
		if (hp_present)
			break;
	}
	for (i = 0; i < cfg->speaker_outs; i++) {
		nid = cfg->speaker_pins[i];
		snd_hda_codec_write(codec, nid, 0,
				    AC_VERB_SET_PIN_WIDGET_CONTROL,
				    hp_present ? 0 : PIN_OUT);
	}
	if (spec->board_config == CS420X_MBP55 ||
	    spec->board_config == CS420X_IMAC27) {
		unsigned int gpio = hp_present ? 0x02 : 0x08;
		snd_hda_codec_write(codec, 0x01, 0,
				    AC_VERB_SET_GPIO_DATA, gpio);
	}
}
Ejemplo n.º 6
0
static void cs_automic(struct hda_codec *codec)
{
	struct cs_spec *spec = codec->spec;
	struct auto_pin_cfg *cfg = &spec->autocfg;
	hda_nid_t nid;
	unsigned int present;
	
	nid = cfg->inputs[spec->automic_idx].pin;
	present = snd_hda_jack_detect(codec, nid);
	if (present)
		change_cur_input(codec, spec->automic_idx, 0);
	else
		change_cur_input(codec, !spec->automic_idx, 0);
}
Ejemplo n.º 7
0
static void cs_automic(struct hda_codec *codec)
{
	struct cs_spec *spec = codec->spec;
	struct auto_pin_cfg *cfg = &spec->autocfg;
	hda_nid_t nid;
	unsigned int present;
	
	nid = cfg->input_pins[spec->automic_idx];
	present = snd_hda_jack_detect(codec, nid);
	if (present)
		change_cur_input(codec, spec->automic_idx, 0);
	else {
		unsigned int imic = (spec->automic_idx == AUTO_PIN_MIC) ?
			AUTO_PIN_FRONT_MIC : AUTO_PIN_MIC;
		change_cur_input(codec, imic, 0);
	}
}
Ejemplo n.º 8
0
/**
 * 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.
 */
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)
{
	struct hda_jack_tbl *jack;
	const struct hda_jack_keymap *map;
	int err, state, buttons;

	jack = snd_hda_jack_tbl_new(codec, nid);
	if (!jack)
		return 0;
	if (jack->jack)
		return 0; /* already created */

	if (!type)
		type = get_input_jack_type(codec, nid);

	buttons = 0;
	if (keymap) {
		for (map = keymap; map->type; map++)
			buttons |= map->type;
	}

	err = snd_jack_new(codec->card, name, type | buttons,
			   &jack->jack, true, phantom_jack);
	if (err < 0)
		return err;

	jack->phantom_jack = !!phantom_jack;
	jack->type = type;
	jack->button_state = 0;
	jack->jack->private_data = jack;
	jack->jack->private_free = hda_free_jack_priv;
	if (keymap) {
		for (map = keymap; map->type; map++)
			snd_jack_set_key(jack->jack, map->type, map->key);
	}

	state = snd_hda_jack_detect(codec, nid);
	snd_jack_report(jack->jack, state ? jack->type : 0);

	return 0;
}
Ejemplo n.º 9
0
static void cs4210_spdif_automute(struct hda_codec *codec,
				  struct hda_jack_callback *tbl)
{
	struct cs_spec *spec = codec->spec;
	bool spdif_present = false;
	hda_nid_t spdif_pin = spec->gen.autocfg.dig_out_pins[0];

	/* detect on spdif is specific to CS4210 */
	if (!spec->spdif_detect ||
	    spec->vendor_nid != CS4210_VENDOR_NID)
		return;

	spdif_present = snd_hda_jack_detect(codec, spdif_pin);
	if (spdif_present == spec->spdif_present)
		return;

	spec->spdif_present = spdif_present;
	/* SPDIF TX on/off */
	snd_hda_set_pin_ctl(codec, spdif_pin, spdif_present ? PIN_OUT : 0);

	cs_automute(codec);
}
Ejemplo n.º 10
0
static void cs_automute(struct hda_codec *codec)
{
	struct cs_spec *spec = codec->spec;
	struct auto_pin_cfg *cfg = &spec->autocfg;
	unsigned int hp_present;
	unsigned int spdif_present;
	hda_nid_t nid;
	int i;

	spdif_present = 0;
	if (cfg->dig_outs) {
		nid = cfg->dig_out_pins[0];
		if (is_jack_detectable(codec, nid)) {
			/*
			TODO: SPDIF output redirect when SENSE_B is enabled.
			Shared (SENSE_A) jack (e.g HP/mini-TOSLINK)
			assumed.
			*/
			if (snd_hda_jack_detect(codec, nid)
				/* && spec->sense_b */)
				spdif_present = 1;
		}
	}

	hp_present = 0;
	for (i = 0; i < cfg->hp_outs; i++) {
		nid = cfg->hp_pins[i];
		if (!is_jack_detectable(codec, nid))
			continue;
		hp_present = snd_hda_jack_detect(codec, nid);
		if (hp_present)
			break;
	}

	/* mute speakers if spdif or hp jack is plugged in */
	for (i = 0; i < cfg->speaker_outs; i++) {
		nid = cfg->speaker_pins[i];
		snd_hda_codec_write(codec, nid, 0,
				    AC_VERB_SET_PIN_WIDGET_CONTROL,
				    hp_present ? 0 : PIN_OUT);
		/* detect on spdif is specific to CS421x */
		if (spec->vendor_nid == CS421X_VENDOR_NID) {
			snd_hda_codec_write(codec, nid, 0,
					AC_VERB_SET_PIN_WIDGET_CONTROL,
					spdif_present ? 0 : PIN_OUT);
		}
	}
	if (spec->board_config == CS420X_MBP53 ||
	    spec->board_config == CS420X_MBP55 ||
	    spec->board_config == CS420X_IMAC27) {
		unsigned int gpio = hp_present ? 0x02 : 0x08;
		snd_hda_codec_write(codec, 0x01, 0,
				    AC_VERB_SET_GPIO_DATA, gpio);
	}

	/* specific to CS421x */
	if (spec->vendor_nid == CS421X_VENDOR_NID) {
		/* mute HPs if spdif jack (SENSE_B) is present */
		for (i = 0; i < cfg->hp_outs; i++) {
			nid = cfg->hp_pins[i];
			snd_hda_codec_write(codec, nid, 0,
				AC_VERB_SET_PIN_WIDGET_CONTROL,
				(spdif_present && spec->sense_b) ? 0 : PIN_HP);
		}

		/* SPDIF TX on/off */
		if (cfg->dig_outs) {
			nid = cfg->dig_out_pins[0];
			snd_hda_codec_write(codec, nid, 0,
				AC_VERB_SET_PIN_WIDGET_CONTROL,
				spdif_present ? PIN_OUT : 0);

		}
		/* Update board GPIOs if neccessary ... */
	}
}