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

Commit b8495995 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull sound fixes from Takashi Iwai:
 "Quite a few HD-Audio fixes, a WUSB audio fix and a fix for FireWire
  audio.  The HD-audio part contains a couple of fixes for the generic
  parser, and these are the only intrusive fixes.  The rest are mostly
  device-specific fixes"

* tag 'sound-3.13-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound:
  ALSA: hda - Add LFE chmap to ASUS ET2700
  ALSA: hda - Initialize missing bass speaker pin for ASUS AIO ET2700
  ALSA: hda - limit mic boost on Asus UX31[A,E]
  ALSA: hda - Check leaf nodes to find aamix amps
  ALSA: hda - Fix hp-mic mode without VREF bits
  ALSA: hda - Create Headhpone Mic Jack Mode when really needed
  ALSA: usb: use multiple packets per urb for Wireless USB inbound audio
  ALSA: hda - Enable mute/mic-mute LEDs for more Thinkpads with Conexant codec
  ALSA: hda - Drop bus->avoid_link_reset flag
  ALSA: hda/realtek - Set pcbeep amp for ALC668
  ALSA: hda/realtek - Add support of ALC231 codec
  ALSA: firewire-lib: fix wrong value for FDF field as an empty packet
parents b01537bf eb9ca3ab
Loading
Loading
Loading
Loading
+6 −9
Original line number Original line Diff line number Diff line
@@ -434,17 +434,14 @@ static void queue_out_packet(struct amdtp_out_stream *s, unsigned int cycle)
		return;
		return;
	index = s->packet_index;
	index = s->packet_index;


	/* this module generate empty packet for 'no data' */
	syt = calculate_syt(s, cycle);
	syt = calculate_syt(s, cycle);
	if (!(s->flags & CIP_BLOCKING)) {
	if (!(s->flags & CIP_BLOCKING))
		data_blocks = calculate_data_blocks(s);
		data_blocks = calculate_data_blocks(s);
	} else {
	else if (syt != 0xffff)
		if (syt != 0xffff) {
		data_blocks = s->syt_interval;
		data_blocks = s->syt_interval;
		} else {
	else
		data_blocks = 0;
		data_blocks = 0;
			syt = 0xffffff;
		}
	}


	buffer = s->buffer.packets[index].buffer;
	buffer = s->buffer.packets[index].buffer;
	buffer[0] = cpu_to_be32(ACCESS_ONCE(s->source_node_id_field) |
	buffer[0] = cpu_to_be32(ACCESS_ONCE(s->source_node_id_field) |
+0 −1
Original line number Original line Diff line number Diff line
@@ -698,7 +698,6 @@ struct hda_bus {
	unsigned int in_reset:1;	/* during reset operation */
	unsigned int in_reset:1;	/* during reset operation */
	unsigned int power_keep_link_on:1; /* don't power off HDA link */
	unsigned int power_keep_link_on:1; /* don't power off HDA link */
	unsigned int no_response_fallback:1; /* don't fallback at RIRB error */
	unsigned int no_response_fallback:1; /* don't fallback at RIRB error */
	unsigned int avoid_link_reset:1; /* don't reset link at runtime PM */


	int primary_dig_out_type;	/* primary digital out PCM type */
	int primary_dig_out_type;	/* primary digital out PCM type */
};
};
+58 −21
Original line number Original line Diff line number Diff line
@@ -2506,12 +2506,8 @@ static int create_out_jack_modes(struct hda_codec *codec, int num_pins,


	for (i = 0; i < num_pins; i++) {
	for (i = 0; i < num_pins; i++) {
		hda_nid_t pin = pins[i];
		hda_nid_t pin = pins[i];
		if (pin == spec->hp_mic_pin) {
		if (pin == spec->hp_mic_pin)
			int ret = create_hp_mic_jack_mode(codec, pin);
			if (ret < 0)
				return ret;
			continue;
			continue;
		}
		if (get_out_jack_num_items(codec, pin) > 1) {
		if (get_out_jack_num_items(codec, pin) > 1) {
			struct snd_kcontrol_new *knew;
			struct snd_kcontrol_new *knew;
			char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
			char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
@@ -2764,7 +2760,7 @@ static int hp_mic_jack_mode_put(struct snd_kcontrol *kcontrol,
			val &= ~(AC_PINCTL_VREFEN | PIN_HP);
			val &= ~(AC_PINCTL_VREFEN | PIN_HP);
			val |= get_vref_idx(vref_caps, idx) | PIN_IN;
			val |= get_vref_idx(vref_caps, idx) | PIN_IN;
		} else
		} else
			val = snd_hda_get_default_vref(codec, nid);
			val = snd_hda_get_default_vref(codec, nid) | PIN_IN;
	}
	}
	snd_hda_set_pin_ctl_cache(codec, nid, val);
	snd_hda_set_pin_ctl_cache(codec, nid, val);
	call_hp_automute(codec, NULL);
	call_hp_automute(codec, NULL);
@@ -2784,9 +2780,6 @@ static int create_hp_mic_jack_mode(struct hda_codec *codec, hda_nid_t pin)
	struct hda_gen_spec *spec = codec->spec;
	struct hda_gen_spec *spec = codec->spec;
	struct snd_kcontrol_new *knew;
	struct snd_kcontrol_new *knew;


	if (get_out_jack_num_items(codec, pin) <= 1 &&
	    get_in_jack_num_items(codec, pin) <= 1)
		return 0; /* no need */
	knew = snd_hda_gen_add_kctl(spec, "Headphone Mic Jack Mode",
	knew = snd_hda_gen_add_kctl(spec, "Headphone Mic Jack Mode",
				    &hp_mic_jack_mode_enum);
				    &hp_mic_jack_mode_enum);
	if (!knew)
	if (!knew)
@@ -2815,6 +2808,42 @@ static int add_loopback_list(struct hda_gen_spec *spec, hda_nid_t mix, int idx)
	return 0;
	return 0;
}
}


/* return true if either a volume or a mute amp is found for the given
 * aamix path; the amp has to be either in the mixer node or its direct leaf
 */
static bool look_for_mix_leaf_ctls(struct hda_codec *codec, hda_nid_t mix_nid,
				   hda_nid_t pin, unsigned int *mix_val,
				   unsigned int *mute_val)
{
	int idx, num_conns;
	const hda_nid_t *list;
	hda_nid_t nid;

	idx = snd_hda_get_conn_index(codec, mix_nid, pin, true);
	if (idx < 0)
		return false;

	*mix_val = *mute_val = 0;
	if (nid_has_volume(codec, mix_nid, HDA_INPUT))
		*mix_val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT);
	if (nid_has_mute(codec, mix_nid, HDA_INPUT))
		*mute_val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT);
	if (*mix_val && *mute_val)
		return true;

	/* check leaf node */
	num_conns = snd_hda_get_conn_list(codec, mix_nid, &list);
	if (num_conns < idx)
		return false;
	nid = list[idx];
	if (!*mix_val && nid_has_volume(codec, nid, HDA_OUTPUT))
		*mix_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
	if (!*mute_val && nid_has_mute(codec, nid, HDA_OUTPUT))
		*mute_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);

	return *mix_val || *mute_val;
}

/* create input playback/capture controls for the given pin */
/* create input playback/capture controls for the given pin */
static int new_analog_input(struct hda_codec *codec, int input_idx,
static int new_analog_input(struct hda_codec *codec, int input_idx,
			    hda_nid_t pin, const char *ctlname, int ctlidx,
			    hda_nid_t pin, const char *ctlname, int ctlidx,
@@ -2822,12 +2851,11 @@ static int new_analog_input(struct hda_codec *codec, int input_idx,
{
{
	struct hda_gen_spec *spec = codec->spec;
	struct hda_gen_spec *spec = codec->spec;
	struct nid_path *path;
	struct nid_path *path;
	unsigned int val;
	unsigned int mix_val, mute_val;
	int err, idx;
	int err, idx;


	if (!nid_has_volume(codec, mix_nid, HDA_INPUT) &&
	if (!look_for_mix_leaf_ctls(codec, mix_nid, pin, &mix_val, &mute_val))
	    !nid_has_mute(codec, mix_nid, HDA_INPUT))
		return 0;
		return 0; /* no need for analog loopback */


	path = snd_hda_add_new_path(codec, pin, mix_nid, 0);
	path = snd_hda_add_new_path(codec, pin, mix_nid, 0);
	if (!path)
	if (!path)
@@ -2836,20 +2864,18 @@ static int new_analog_input(struct hda_codec *codec, int input_idx,
	spec->loopback_paths[input_idx] = snd_hda_get_path_idx(codec, path);
	spec->loopback_paths[input_idx] = snd_hda_get_path_idx(codec, path);


	idx = path->idx[path->depth - 1];
	idx = path->idx[path->depth - 1];
	if (nid_has_volume(codec, mix_nid, HDA_INPUT)) {
	if (mix_val) {
		val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT);
		err = __add_pb_vol_ctrl(spec, HDA_CTL_WIDGET_VOL, ctlname, ctlidx, mix_val);
		err = __add_pb_vol_ctrl(spec, HDA_CTL_WIDGET_VOL, ctlname, ctlidx, val);
		if (err < 0)
		if (err < 0)
			return err;
			return err;
		path->ctls[NID_PATH_VOL_CTL] = val;
		path->ctls[NID_PATH_VOL_CTL] = mix_val;
	}
	}


	if (nid_has_mute(codec, mix_nid, HDA_INPUT)) {
	if (mute_val) {
		val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT);
		err = __add_pb_sw_ctrl(spec, HDA_CTL_WIDGET_MUTE, ctlname, ctlidx, mute_val);
		err = __add_pb_sw_ctrl(spec, HDA_CTL_WIDGET_MUTE, ctlname, ctlidx, val);
		if (err < 0)
		if (err < 0)
			return err;
			return err;
		path->ctls[NID_PATH_MUTE_CTL] = val;
		path->ctls[NID_PATH_MUTE_CTL] = mute_val;
	}
	}


	path->active = true;
	path->active = true;
@@ -4383,6 +4409,17 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
	if (err < 0)
	if (err < 0)
		return err;
		return err;


	/* create "Headphone Mic Jack Mode" if no input selection is
	 * available (or user specifies add_jack_modes hint)
	 */
	if (spec->hp_mic_pin &&
	    (spec->auto_mic || spec->input_mux.num_items == 1 ||
	     spec->add_jack_modes)) {
		err = create_hp_mic_jack_mode(codec, spec->hp_mic_pin);
		if (err < 0)
			return err;
	}

	if (spec->add_jack_modes) {
	if (spec->add_jack_modes) {
		if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
		if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
			err = create_out_jack_modes(codec, cfg->line_outs,
			err = create_out_jack_modes(codec, cfg->line_outs,
+1 −2
Original line number Original line Diff line number Diff line
@@ -2994,7 +2994,6 @@ static int azx_runtime_suspend(struct device *dev)
		  STATESTS_INT_MASK);
		  STATESTS_INT_MASK);


	azx_stop_chip(chip);
	azx_stop_chip(chip);
	if (!chip->bus->avoid_link_reset)
	azx_enter_link_reset(chip);
	azx_enter_link_reset(chip);
	azx_clear_irq_pending(chip);
	azx_clear_irq_pending(chip);
	if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL)
	if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL)
+23 −0
Original line number Original line Diff line number Diff line
@@ -3244,9 +3244,29 @@ enum {
#if IS_ENABLED(CONFIG_THINKPAD_ACPI)
#if IS_ENABLED(CONFIG_THINKPAD_ACPI)


#include <linux/thinkpad_acpi.h>
#include <linux/thinkpad_acpi.h>
#include <acpi/acpi.h>


static int (*led_set_func)(int, bool);
static int (*led_set_func)(int, bool);


static acpi_status acpi_check_cb(acpi_handle handle, u32 lvl, void *context,
				 void **rv)
{
	bool *found = context;
	*found = true;
	return AE_OK;
}

static bool is_thinkpad(struct hda_codec *codec)
{
	bool found = false;
	if (codec->subsystem_id >> 16 != 0x17aa)
		return false;
	if (ACPI_SUCCESS(acpi_get_devices("LEN0068", acpi_check_cb, &found, NULL)) && found)
		return true;
	found = false;
	return ACPI_SUCCESS(acpi_get_devices("IBM0068", acpi_check_cb, &found, NULL)) && found;
}

static void update_tpacpi_mute_led(void *private_data, int enabled)
static void update_tpacpi_mute_led(void *private_data, int enabled)
{
{
	struct hda_codec *codec = private_data;
	struct hda_codec *codec = private_data;
@@ -3279,6 +3299,8 @@ static void cxt_fixup_thinkpad_acpi(struct hda_codec *codec,
	bool removefunc = false;
	bool removefunc = false;


	if (action == HDA_FIXUP_ACT_PROBE) {
	if (action == HDA_FIXUP_ACT_PROBE) {
		if (!is_thinkpad(codec))
			return;
		if (!led_set_func)
		if (!led_set_func)
			led_set_func = symbol_request(tpacpi_led_set);
			led_set_func = symbol_request(tpacpi_led_set);
		if (!led_set_func) {
		if (!led_set_func) {
@@ -3494,6 +3516,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = {
	SND_PCI_QUIRK(0x17aa, 0x3975, "Lenovo U300s", CXT_FIXUP_STEREO_DMIC),
	SND_PCI_QUIRK(0x17aa, 0x3975, "Lenovo U300s", CXT_FIXUP_STEREO_DMIC),
	SND_PCI_QUIRK(0x17aa, 0x3977, "Lenovo IdeaPad U310", CXT_FIXUP_STEREO_DMIC),
	SND_PCI_QUIRK(0x17aa, 0x3977, "Lenovo IdeaPad U310", CXT_FIXUP_STEREO_DMIC),
	SND_PCI_QUIRK(0x17aa, 0x397b, "Lenovo S205", CXT_FIXUP_STEREO_DMIC),
	SND_PCI_QUIRK(0x17aa, 0x397b, "Lenovo S205", CXT_FIXUP_STEREO_DMIC),
	SND_PCI_QUIRK_VENDOR(0x17aa, "Thinkpad", CXT_FIXUP_THINKPAD_ACPI),
	SND_PCI_QUIRK(0x1c06, 0x2011, "Lemote A1004", CXT_PINCFG_LEMOTE_A1004),
	SND_PCI_QUIRK(0x1c06, 0x2011, "Lemote A1004", CXT_PINCFG_LEMOTE_A1004),
	SND_PCI_QUIRK(0x1c06, 0x2012, "Lemote A1205", CXT_PINCFG_LEMOTE_A1205),
	SND_PCI_QUIRK(0x1c06, 0x2012, "Lemote A1205", CXT_PINCFG_LEMOTE_A1205),
	{}
	{}
Loading