diff options
| -rw-r--r-- | Documentation/sound/alsa/HD-Audio.txt | 8 | ||||
| -rw-r--r-- | sound/pci/hda/hda_eld.c | 13 | ||||
| -rw-r--r-- | sound/pci/hda/hda_local.h | 3 | ||||
| -rw-r--r-- | sound/pci/hda/patch_cirrus.c | 23 | ||||
| -rw-r--r-- | sound/pci/hda/patch_hdmi.c | 55 | ||||
| -rw-r--r-- | sound/pci/hda/patch_realtek.c | 2 | ||||
| -rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 33 | 
7 files changed, 72 insertions, 65 deletions
| diff --git a/Documentation/sound/alsa/HD-Audio.txt b/Documentation/sound/alsa/HD-Audio.txt index 03e2771ddeef..91fee3b45fb8 100644 --- a/Documentation/sound/alsa/HD-Audio.txt +++ b/Documentation/sound/alsa/HD-Audio.txt @@ -579,7 +579,7 @@ Development Tree  ~~~~~~~~~~~~~~~~  The latest development codes for HD-audio are found on sound git tree: -- git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6.git +- git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git  The master branch or for-next branches can be used as the main  development branches in general while the HD-audio specific patches @@ -594,7 +594,7 @@ is, installed via the usual spells: configure, make and make  install(-modules).  See INSTALL in the package.  The snapshot tarballs  are found at: -- ftp://ftp.kernel.org/pub/linux/kernel/people/tiwai/snapshot/ +- ftp://ftp.suse.com/pub/people/tiwai/snapshot/  Sending a Bug Report @@ -696,7 +696,7 @@ via hda-verb won't change the mixer value.  The hda-verb program is found in the ftp directory: -- ftp://ftp.kernel.org/pub/linux/kernel/people/tiwai/misc/ +- ftp://ftp.suse.com/pub/people/tiwai/misc/  Also a git repository is available: @@ -764,7 +764,7 @@ operation, the jack plugging simulation, etc.  The package is found in: -- ftp://ftp.kernel.org/pub/linux/kernel/people/tiwai/misc/ +- ftp://ftp.suse.com/pub/people/tiwai/misc/  A git repository is available: diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c index 1c8ddf547a2d..7ae7578bdcc0 100644 --- a/sound/pci/hda/hda_eld.c +++ b/sound/pci/hda/hda_eld.c @@ -297,10 +297,18 @@ static int hdmi_update_eld(struct hdmi_eld *e,  					buf + ELD_FIXED_BYTES + mnl + 3 * i);  	} +	/* +	 * HDMI sink's ELD info cannot always be retrieved for now, e.g. +	 * in console or for audio devices. Assume the highest speakers +	 * configuration, to _not_ prohibit multi-channel audio playback. +	 */ +	if (!e->spk_alloc) +		e->spk_alloc = 0xffff; + +	e->eld_valid = true;  	return 0;  out_fail: -	e->eld_ver = 0;  	return -EINVAL;  } @@ -323,9 +331,6 @@ int snd_hdmi_get_eld(struct hdmi_eld *eld,  	 * ELD is valid, actual eld_size is assigned in hdmi_update_eld()  	 */ -	if (!eld->eld_valid) -		return -ENOENT; -  	size = snd_hdmi_get_eld_size(codec, nid);  	if (size == 0) {  		/* wfg: workaround for ASUS P5E-VM HDMI board */ diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 6579e0f2bb57..618ddad17236 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h @@ -653,6 +653,9 @@ struct hdmi_eld {  	int	spk_alloc;  	int	sad_count;  	struct cea_sad sad[ELD_MAX_SAD]; +	/* +	 * all fields above eld_buffer will be cleared before updating ELD +	 */  	char    eld_buffer[ELD_MAX_SIZE];  #ifdef CONFIG_PROC_FS  	struct snd_info_entry *proc_entry; diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index 2a2d8645ba09..2fbab8e29576 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c @@ -237,6 +237,15 @@ static int cs_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,  	return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);  } +static void cs_update_input_select(struct hda_codec *codec) +{ +	struct cs_spec *spec = codec->spec; +	if (spec->cur_adc) +		snd_hda_codec_write(codec, spec->cur_adc, 0, +				    AC_VERB_SET_CONNECT_SEL, +				    spec->adc_idx[spec->cur_input]); +} +  /*   * Analog capture   */ @@ -250,6 +259,7 @@ static int cs_capture_pcm_prepare(struct hda_pcm_stream *hinfo,  	spec->cur_adc = spec->adc_nid[spec->cur_input];  	spec->cur_adc_stream_tag = stream_tag;  	spec->cur_adc_format = format; +	cs_update_input_select(codec);  	snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format);  	return 0;  } @@ -689,10 +699,8 @@ static int change_cur_input(struct hda_codec *codec, unsigned int idx,  					   spec->cur_adc_stream_tag, 0,  					   spec->cur_adc_format);  	} -	snd_hda_codec_write(codec, spec->cur_adc, 0, -			    AC_VERB_SET_CONNECT_SEL, -			    spec->adc_idx[idx]);  	spec->cur_input = idx; +	cs_update_input_select(codec);  	return 1;  } @@ -973,10 +981,7 @@ static void cs_automic(struct hda_codec *codec)  		} 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]); +		cs_update_input_select(codec);  	} else {  		if (present)  			change_cur_input(codec, spec->automic_idx, 0); @@ -1073,9 +1078,7 @@ static void init_input(struct hda_codec *codec)  			cs_automic(codec);  		else  {  			spec->cur_adc = spec->adc_nid[spec->cur_input]; -			snd_hda_codec_write(codec, spec->cur_adc, 0, -					AC_VERB_SET_CONNECT_SEL, -					spec->adc_idx[spec->cur_input]); +			cs_update_input_select(codec);  		}  	} else {  		change_cur_input(codec, spec->cur_input, 1); diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 81b7b791b3c3..9850c5b481ea 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -65,7 +65,10 @@ struct hdmi_spec_per_pin {  	hda_nid_t pin_nid;  	int num_mux_nids;  	hda_nid_t mux_nids[HDA_MAX_CONNECTIONS]; + +	struct hda_codec *codec;  	struct hdmi_eld sink_eld; +	struct delayed_work work;  };  struct hdmi_spec { @@ -745,8 +748,7 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, int pin_idx,   * Unsolicited events   */ -static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid, -			       struct hdmi_eld *eld); +static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, bool retry);  static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)  { @@ -755,7 +757,6 @@ static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)  	int pd = !!(res & AC_UNSOL_RES_PD);  	int eldv = !!(res & AC_UNSOL_RES_ELDV);  	int pin_idx; -	struct hdmi_eld *eld;  	printk(KERN_INFO  		"HDMI hot plug event: Codec=%d Pin=%d Presence_Detect=%d ELD_Valid=%d\n", @@ -764,17 +765,8 @@ static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)  	pin_idx = pin_nid_to_pin_index(spec, pin_nid);  	if (pin_idx < 0)  		return; -	eld = &spec->pins[pin_idx].sink_eld; - -	hdmi_present_sense(codec, pin_nid, eld); -	/* -	 * HDMI sink's ELD info cannot always be retrieved for now, e.g. -	 * in console or for audio devices. Assume the highest speakers -	 * configuration, to _not_ prohibit multi-channel audio playback. -	 */ -	if (!eld->spk_alloc) -		eld->spk_alloc = 0xffff; +	hdmi_present_sense(&spec->pins[pin_idx], true);  }  static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res) @@ -968,9 +960,11 @@ static int hdmi_read_pin_conn(struct hda_codec *codec, int pin_idx)  	return 0;  } -static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid, -			       struct hdmi_eld *eld) +static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, bool retry)  { +	struct hda_codec *codec = per_pin->codec; +	struct hdmi_eld *eld = &per_pin->sink_eld; +	hda_nid_t pin_nid = per_pin->pin_nid;  	/*  	 * Always execute a GetPinSense verb here, even when called from  	 * hdmi_intrinsic_event; for some NVIDIA HW, the unsolicited @@ -980,26 +974,39 @@ static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid,  	 * the unsolicited response to avoid custom WARs.  	 */  	int present = snd_hda_pin_sense(codec, pin_nid); +	bool eld_valid = false; -	memset(eld, 0, sizeof(*eld)); +	memset(eld, 0, offsetof(struct hdmi_eld, eld_buffer));  	eld->monitor_present	= !!(present & AC_PINSENSE_PRESENCE);  	if (eld->monitor_present) -		eld->eld_valid	= !!(present & AC_PINSENSE_ELDV); -	else -		eld->eld_valid	= 0; +		eld_valid	= !!(present & AC_PINSENSE_ELDV);  	printk(KERN_INFO  		"HDMI status: Codec=%d Pin=%d Presence_Detect=%d ELD_Valid=%d\n", -		codec->addr, pin_nid, eld->monitor_present, eld->eld_valid); +		codec->addr, pin_nid, eld->monitor_present, eld_valid); -	if (eld->eld_valid) +	if (eld_valid) {  		if (!snd_hdmi_get_eld(eld, codec, pin_nid))  			snd_hdmi_show_eld(eld); +		else if (retry) { +			queue_delayed_work(codec->bus->workq, +					   &per_pin->work, +					   msecs_to_jiffies(300)); +		} +	}  	snd_hda_input_jack_report(codec, pin_nid);  } +static void hdmi_repoll_eld(struct work_struct *work) +{ +	struct hdmi_spec_per_pin *per_pin = +	container_of(to_delayed_work(work), struct hdmi_spec_per_pin, work); + +	hdmi_present_sense(per_pin, false); +} +  static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)  {  	struct hdmi_spec *spec = codec->spec; @@ -1228,7 +1235,7 @@ static int generic_hdmi_build_jack(struct hda_codec *codec, int pin_idx)  	if (err < 0)  		return err; -	hdmi_present_sense(codec, per_pin->pin_nid, &per_pin->sink_eld); +	hdmi_present_sense(per_pin, false);  	return 0;  } @@ -1279,6 +1286,8 @@ static int generic_hdmi_init(struct hda_codec *codec)  				    AC_VERB_SET_UNSOLICITED_ENABLE,  				    AC_USRSP_EN | pin_nid); +		per_pin->codec = codec; +		INIT_DELAYED_WORK(&per_pin->work, hdmi_repoll_eld);  		snd_hda_eld_proc_new(codec, eld, pin_idx);  	}  	return 0; @@ -1293,10 +1302,12 @@ static void generic_hdmi_free(struct hda_codec *codec)  		struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx];  		struct hdmi_eld *eld = &per_pin->sink_eld; +		cancel_delayed_work(&per_pin->work);  		snd_hda_eld_proc_free(codec, eld);  	}  	snd_hda_input_jack_free(codec); +	flush_workqueue(codec->bus->workq);  	kfree(spec);  } diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 308bb575bc06..336d14eb72af 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -1452,7 +1452,7 @@ static void alc_apply_fixup(struct hda_codec *codec, int action)  		switch (fix->type) {  		case ALC_FIXUP_SKU:  			if (action != ALC_FIXUP_ACT_PRE_PROBE || !fix->v.sku) -				break;; +				break;  			snd_printdd(KERN_INFO "hda_codec: %s: "  				    "Apply sku override for %s\n",  				    codec->chip_name, modelname); diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index edc2b7bc177c..470f6f286e81 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -227,7 +227,6 @@ struct sigmatel_spec {  	/* power management */  	unsigned int num_pwrs; -	const unsigned int *pwr_mapping;  	const hda_nid_t *pwr_nids;  	const hda_nid_t *dac_list; @@ -374,18 +373,15 @@ static const unsigned long stac92hd73xx_capvols[] = {  #define STAC92HD83_DAC_COUNT 3 -static const hda_nid_t stac92hd83xxx_pwr_nids[4] = { -	0xa, 0xb, 0xd, 0xe, +static const hda_nid_t stac92hd83xxx_pwr_nids[7] = { +	0x0a, 0x0b, 0x0c, 0xd, 0x0e, +	0x0f, 0x10  };  static const hda_nid_t stac92hd83xxx_slave_dig_outs[2] = {  	0x1e, 0,  }; -static const unsigned int stac92hd83xxx_pwr_mapping[4] = { -	0x03, 0x0c, 0x20, 0x40, -}; -  static const hda_nid_t stac92hd83xxx_dmic_nids[] = {  		0x11, 0x20,  }; @@ -4470,8 +4466,12 @@ static int stac92xx_init(struct hda_codec *codec)  				stac_toggle_power_map(codec, nid, 1);  			continue;  		} -		if (enable_pin_detect(codec, nid, STAC_PWR_EVENT)) +		if (enable_pin_detect(codec, nid, STAC_PWR_EVENT)) {  			stac_issue_unsol_event(codec, nid); +			continue; +		} +		/* none of the above, turn the port OFF */ +		stac_toggle_power_map(codec, nid, 0);  	}  	/* sync mute LED */ @@ -4727,11 +4727,7 @@ static void stac_toggle_power_map(struct hda_codec *codec, hda_nid_t nid,  	if (idx >= spec->num_pwrs)  		return; -	/* several codecs have two power down bits */ -	if (spec->pwr_mapping) -		idx = spec->pwr_mapping[idx]; -	else -		idx = 1 << idx; +	idx = 1 << idx;  	val = snd_hda_codec_read(codec, codec->afg, 0, 0x0fec, 0x0) & 0xff;  	if (enable) @@ -5629,9 +5625,6 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)  		snd_hda_codec_set_pincfg(codec, 0xf, 0x2181205e);  	} -	/* reset pin power-down; Windows may leave these bits after reboot */ -	snd_hda_codec_write_cache(codec, codec->afg, 0, 0x7EC, 0); -	snd_hda_codec_write_cache(codec, codec->afg, 0, 0x7ED, 0);  	codec->no_trigger_sense = 1;  	codec->spec = spec; @@ -5641,7 +5634,6 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)  	codec->slave_dig_outs = stac92hd83xxx_slave_dig_outs;  	spec->digbeep_nid = 0x21;  	spec->pwr_nids = stac92hd83xxx_pwr_nids; -	spec->pwr_mapping = stac92hd83xxx_pwr_mapping;  	spec->num_pwrs = ARRAY_SIZE(stac92hd83xxx_pwr_nids);  	spec->multiout.dac_nids = spec->dac_nids;  	spec->init = stac92hd83xxx_core_init; @@ -5658,9 +5650,6 @@ again:  		stac92xx_set_config_regs(codec,  				stac92hd83xxx_brd_tbl[spec->board_config]); -	if (spec->board_config != STAC_92HD83XXX_PWR_REF) -		spec->num_pwrs = 0; -  	codec->patch_ops = stac92xx_patch_ops;  	if (find_mute_led_gpio(codec, 0)) @@ -5869,8 +5858,6 @@ again:  		    (codec->revision_id & 0xf) == 1)  			spec->stream_delay = 40; /* 40 milliseconds */ -		/* no output amps */ -		spec->num_pwrs = 0;  		/* disable VSW */  		spec->init = stac92hd71bxx_core_init;  		unmute_init++; @@ -5885,8 +5872,6 @@ again:  		if ((codec->revision_id & 0xf) == 1)  			spec->stream_delay = 40; /* 40 milliseconds */ -		/* no output amps */ -		spec->num_pwrs = 0;  		/* fallthru */  	default:  		spec->init = stac92hd71bxx_core_init; | 
