Example #1
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);
}
Example #2
0
/**
 * snd_hda_jack_detect_enable - enable the jack-detection
 *
 * In the case of error, the return value will be a pointer embedded with
 * errno.  Check and handle the return value appropriately with standard
 * macros such as @IS_ERR() and @PTR_ERR().
 */
struct hda_jack_callback *
snd_hda_jack_detect_enable_callback(struct hda_codec *codec, hda_nid_t nid,
				    hda_jack_callback_fn func)
{
	struct hda_jack_tbl *jack;
	struct hda_jack_callback *callback = NULL;
	int err;

	jack = snd_hda_jack_tbl_new(codec, nid);
	if (!jack)
		return ERR_PTR(-ENOMEM);
	if (func) {
		callback = kzalloc(sizeof(*callback), GFP_KERNEL);
		if (!callback)
			return ERR_PTR(-ENOMEM);
		callback->func = func;
		callback->tbl = jack;
		callback->next = jack->callback;
		jack->callback = callback;
	}

	if (jack->jack_detect)
		return callback; /* already registered */
	jack->jack_detect = 1;
	if (codec->jackpoll_interval > 0)
		return callback; /* No unsol if we're polling instead */
	err = snd_hda_codec_write_cache(codec, nid, 0,
					 AC_VERB_SET_UNSOLICITED_ENABLE,
					 AC_USRSP_EN | jack->tag);
	if (err < 0)
		return ERR_PTR(err);
	return callback;
}
Example #3
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);
	}
}
Example #4
0
/**
 * snd_hda_attach_beep_device - Attach a beep input device
 * @codec: the HDA codec
 * @nid: beep NID
 *
 * Attach a beep object to the given widget.  If beep hint is turned off
 * explicitly or beep_mode of the codec is turned off, this doesn't nothing.
 *
 * The attached beep device has to be registered via
 * snd_hda_register_beep_device() and released via snd_hda_detach_beep_device()
 * appropriately.
 *
 * Currently, only one beep device is allowed to each codec.
 */
int snd_hda_attach_beep_device(struct hda_codec *codec, int nid)
{
	struct hda_beep *beep;
	int err;

	if (!snd_hda_get_bool_hint(codec, "beep"))
		return 0; /* disabled explicitly by hints */
	if (codec->beep_mode == HDA_BEEP_MODE_OFF)
		return 0; /* disabled by module option */

	beep = kzalloc(sizeof(*beep), GFP_KERNEL);
	if (beep == NULL)
		return -ENOMEM;
	snprintf(beep->phys, sizeof(beep->phys),
		"card%d/codec#%d/beep0", codec->card->number, codec->addr);
	/* enable linear scale */
	snd_hda_codec_write_cache(codec, nid, 0,
		AC_VERB_SET_DIGI_CONVERT_2, 0x01);

	beep->nid = nid;
	beep->codec = codec;
	codec->beep = beep;

	INIT_WORK(&beep->beep_work, &snd_hda_generate_beep);
	mutex_init(&beep->mutex);

	err = snd_hda_do_attach(beep);
	if (err < 0) {
		kfree(beep);
		codec->beep = NULL;
		return err;
	}

	return 0;
}
Example #5
0
/* follow EAPD via vmaster hook */
static void ad_vmaster_eapd_hook(void *private_data, int enabled)
{
	struct hda_codec *codec = private_data;
	struct ad198x_spec *spec = codec->spec;

	if (!spec->eapd_nid)
		return;
	if (codec->inv_eapd)
		enabled = !enabled;
	snd_hda_codec_write_cache(codec, spec->eapd_nid, 0,
				   AC_VERB_SET_EAPD_BTLENABLE,
				   enabled ? 0x02 : 0x00);
}
/**
 * snd_hda_jack_detect_enable - enable the jack-detection
 */
int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid,
			       unsigned char action)
{
	struct hda_jack_tbl *jack = snd_hda_jack_tbl_new(codec, nid);
	if (!jack)
		return -ENOMEM;
	if (jack->jack_detect)
		return 0; /* already registered */
	jack->jack_detect = 1;
	if (action)
		jack->action = action;
	return snd_hda_codec_write_cache(codec, nid, 0,
					 AC_VERB_SET_UNSOLICITED_ENABLE,
					 AC_USRSP_EN | jack->tag);
}
Example #7
0
static int ad1983_auto_smux_enum_put(struct snd_kcontrol *kcontrol,
				     struct snd_ctl_elem_value *ucontrol)
{
	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
	struct ad198x_spec *spec = codec->spec;
	unsigned int val = ucontrol->value.enumerated.item[0];
	hda_nid_t dig_out = spec->gen.multiout.dig_out_nid;
	int num_conns = snd_hda_get_num_conns(codec, dig_out);

	if (val >= num_conns)
		return -EINVAL;
	if (spec->cur_smux == val)
		return 0;
	spec->cur_smux = val;
	snd_hda_codec_write_cache(codec, dig_out, 0,
				  AC_VERB_SET_CONNECT_SEL, val);
	return 1;
}
Example #8
0
static int ad198x_eapd_put(struct snd_kcontrol *kcontrol,
			   struct snd_ctl_elem_value *ucontrol)
{
	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
	struct ad198x_spec *spec = codec->spec;
	hda_nid_t nid = kcontrol->private_value & 0xff;
	unsigned int eapd;
	eapd = !!ucontrol->value.integer.value[0];
	if (codec->inv_eapd)
		eapd = !eapd;
	if (eapd == spec->cur_eapd)
		return 0;
	spec->cur_eapd = eapd;
	snd_hda_codec_write_cache(codec, nid,
				  0, AC_VERB_SET_EAPD_BTLENABLE,
				  eapd ? 0x02 : 0x00);
	return 1;
}
/**
 * snd_hda_jack_detect_enable - enable the jack-detection
 */
int snd_hda_jack_detect_enable_callback(struct hda_codec *codec, hda_nid_t nid,
                                        unsigned char action,
                                        hda_jack_callback cb)
{
    struct hda_jack_tbl *jack = snd_hda_jack_tbl_new(codec, nid);
    if (!jack)
        return -ENOMEM;
    if (jack->jack_detect)
        return 0; /* already registered */
    jack->jack_detect = 1;
    if (action)
        jack->action = action;
    if (cb)
        jack->callback = cb;
    if (codec->jackpoll_interval > 0)
        return 0; /* No unsol if we're polling instead */
    return snd_hda_codec_write_cache(codec, nid, 0,
                                     AC_VERB_SET_UNSOLICITED_ENABLE,
                                     AC_USRSP_EN | jack->tag);
}
Example #10
0
/**
 * snd_hda_attach_beep_device - Attach a beep input device
 * @codec: the HDA codec
 * @nid: beep NID
 *
 * Attach a beep object to the given widget.  If beep hint is turned off
 * explicitly or beep_mode of the codec is turned off, this doesn't nothing.
 *
 * Currently, only one beep device is allowed to each codec.
 */
int snd_hda_attach_beep_device(struct hda_codec *codec, int nid)
{
	static struct snd_device_ops ops = {
		.dev_register = beep_dev_register,
		.dev_disconnect = beep_dev_disconnect,
		.dev_free = beep_dev_free,
	};
	struct input_dev *input_dev;
	struct hda_beep *beep;
	int err;

	if (!snd_hda_get_bool_hint(codec, "beep"))
		return 0; /* disabled explicitly by hints */
	if (codec->beep_mode == HDA_BEEP_MODE_OFF)
		return 0; /* disabled by module option */

	beep = kzalloc(sizeof(*beep), GFP_KERNEL);
	if (beep == NULL)
		return -ENOMEM;
	snprintf(beep->phys, sizeof(beep->phys),
		"card%d/codec#%d/beep0", codec->card->number, codec->addr);
	/* enable linear scale */
	snd_hda_codec_write_cache(codec, nid, 0,
		AC_VERB_SET_DIGI_CONVERT_2, 0x01);

	beep->nid = nid;
	beep->codec = codec;
	codec->beep = beep;

	INIT_WORK(&beep->beep_work, &snd_hda_generate_beep);
	mutex_init(&beep->mutex);

	input_dev = input_allocate_device();
	if (!input_dev) {
		err = -ENOMEM;
		goto err_free;
	}

	/* setup digital beep device */
	input_dev->name = "HDA Digital PCBeep";
	input_dev->phys = beep->phys;
	input_dev->id.bustype = BUS_PCI;
	input_dev->dev.parent = &codec->card->card_dev;

	input_dev->id.vendor = codec->core.vendor_id >> 16;
	input_dev->id.product = codec->core.vendor_id & 0xffff;
	input_dev->id.version = 0x01;

	input_dev->evbit[0] = BIT_MASK(EV_SND);
	input_dev->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE);
	input_dev->event = snd_hda_beep_event;
	input_set_drvdata(input_dev, beep);

	beep->dev = input_dev;

	err = snd_device_new(codec->card, SNDRV_DEV_JACK, beep, &ops);
	if (err < 0)
		goto err_input;

	return 0;

 err_input:
	input_free_device(beep->dev);
 err_free:
	kfree(beep);
	codec->beep = NULL;
	return err;
}