diff options
Diffstat (limited to 'sound/pci/hda/hda_codec.c')
| -rw-r--r-- | sound/pci/hda/hda_codec.c | 79 | 
1 files changed, 46 insertions, 33 deletions
| diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 5bc3a7468e17..20a171ac4bb2 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -158,7 +158,7 @@ static int read_and_add_raw_conns(struct hda_codec *codec, hda_nid_t nid)  	len = snd_hda_get_raw_connections(codec, nid, list, ARRAY_SIZE(list));  	if (len == -ENOSPC) {  		len = snd_hda_get_num_raw_conns(codec, nid); -		result = kmalloc(sizeof(hda_nid_t) * len, GFP_KERNEL); +		result = kmalloc_array(len, sizeof(hda_nid_t), GFP_KERNEL);  		if (!result)  			return -ENOMEM;  		len = snd_hda_get_raw_connections(codec, nid, result, len); @@ -438,7 +438,7 @@ static int read_widget_caps(struct hda_codec *codec, hda_nid_t fg_node)  	int i;  	hda_nid_t nid; -	codec->wcaps = kmalloc(codec->core.num_nodes * 4, GFP_KERNEL); +	codec->wcaps = kmalloc_array(codec->core.num_nodes, 4, GFP_KERNEL);  	if (!codec->wcaps)  		return -ENOMEM;  	nid = codec->core.start_nid; @@ -481,9 +481,10 @@ static struct hda_pincfg *look_up_pincfg(struct hda_codec *codec,  					 struct snd_array *array,  					 hda_nid_t nid)  { +	struct hda_pincfg *pin;  	int i; -	for (i = 0; i < array->used; i++) { -		struct hda_pincfg *pin = snd_array_elem(array, i); + +	snd_array_for_each(array, i, pin) {  		if (pin->nid == nid)  			return pin;  	} @@ -618,14 +619,15 @@ EXPORT_SYMBOL_GPL(snd_hda_codec_get_pin_target);   */  void snd_hda_shutup_pins(struct hda_codec *codec)  { +	const struct hda_pincfg *pin;  	int i; +  	/* don't shut up pins when unloading the driver; otherwise it breaks  	 * the default pin setup at the next load of the driver  	 */  	if (codec->bus->shutdown)  		return; -	for (i = 0; i < codec->init_pins.used; i++) { -		struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i); +	snd_array_for_each(&codec->init_pins, i, pin) {  		/* use read here for syncing after issuing each verb */  		snd_hda_codec_read(codec, pin->nid, 0,  				   AC_VERB_SET_PIN_WIDGET_CONTROL, 0); @@ -638,13 +640,14 @@ EXPORT_SYMBOL_GPL(snd_hda_shutup_pins);  /* Restore the pin controls cleared previously via snd_hda_shutup_pins() */  static void restore_shutup_pins(struct hda_codec *codec)  { +	const struct hda_pincfg *pin;  	int i; +  	if (!codec->pins_shutup)  		return;  	if (codec->bus->shutdown)  		return; -	for (i = 0; i < codec->init_pins.used; i++) { -		struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i); +	snd_array_for_each(&codec->init_pins, i, pin) {  		snd_hda_codec_write(codec, pin->nid, 0,  				    AC_VERB_SET_PIN_WIDGET_CONTROL,  				    pin->ctrl); @@ -697,8 +700,7 @@ get_hda_cvt_setup(struct hda_codec *codec, hda_nid_t nid)  	struct hda_cvt_setup *p;  	int i; -	for (i = 0; i < codec->cvt_setups.used; i++) { -		p = snd_array_elem(&codec->cvt_setups, i); +	snd_array_for_each(&codec->cvt_setups, i, p) {  		if (p->nid == nid)  			return p;  	} @@ -1076,8 +1078,7 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,  	/* make other inactive cvts with the same stream-tag dirty */  	type = get_wcaps_type(get_wcaps(codec, nid));  	list_for_each_codec(c, codec->bus) { -		for (i = 0; i < c->cvt_setups.used; i++) { -			p = snd_array_elem(&c->cvt_setups, i); +		snd_array_for_each(&c->cvt_setups, i, p) {  			if (!p->active && p->stream_tag == stream_tag &&  			    get_wcaps_type(get_wcaps(c, p->nid)) == type)  				p->dirty = 1; @@ -1140,12 +1141,11 @@ static void really_cleanup_stream(struct hda_codec *codec,  static void purify_inactive_streams(struct hda_codec *codec)  {  	struct hda_codec *c; +	struct hda_cvt_setup *p;  	int i;  	list_for_each_codec(c, codec->bus) { -		for (i = 0; i < c->cvt_setups.used; i++) { -			struct hda_cvt_setup *p; -			p = snd_array_elem(&c->cvt_setups, i); +		snd_array_for_each(&c->cvt_setups, i, p) {  			if (p->dirty)  				really_cleanup_stream(c, p);  		} @@ -1156,10 +1156,10 @@ static void purify_inactive_streams(struct hda_codec *codec)  /* clean up all streams; called from suspend */  static void hda_cleanup_all_streams(struct hda_codec *codec)  { +	struct hda_cvt_setup *p;  	int i; -	for (i = 0; i < codec->cvt_setups.used; i++) { -		struct hda_cvt_setup *p = snd_array_elem(&codec->cvt_setups, i); +	snd_array_for_each(&codec->cvt_setups, i, p) {  		if (p->stream_tag)  			really_cleanup_stream(codec, p);  	} @@ -1493,10 +1493,10 @@ static void get_ctl_amp_tlv(struct snd_kcontrol *kcontrol, unsigned int *tlv)  	val1 = ((int)val1) * ((int)val2);  	if (min_mute || (caps & AC_AMPCAP_MIN_MUTE))  		val2 |= TLV_DB_SCALE_MUTE; -	tlv[0] = SNDRV_CTL_TLVT_DB_SCALE; -	tlv[1] = 2 * sizeof(unsigned int); -	tlv[2] = val1; -	tlv[3] = val2; +	tlv[SNDRV_CTL_TLVO_TYPE] = SNDRV_CTL_TLVT_DB_SCALE; +	tlv[SNDRV_CTL_TLVO_LEN] = 2 * sizeof(unsigned int); +	tlv[SNDRV_CTL_TLVO_DB_SCALE_MIN] = val1; +	tlv[SNDRV_CTL_TLVO_DB_SCALE_MUTE_AND_STEP] = val2;  }  /** @@ -1544,10 +1544,10 @@ void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir,  	nums = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;  	step = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;  	step = (step + 1) * 25; -	tlv[0] = SNDRV_CTL_TLVT_DB_SCALE; -	tlv[1] = 2 * sizeof(unsigned int); -	tlv[2] = -nums * step; -	tlv[3] = step; +	tlv[SNDRV_CTL_TLVO_TYPE] = SNDRV_CTL_TLVT_DB_SCALE; +	tlv[SNDRV_CTL_TLVO_LEN] = 2 * sizeof(unsigned int); +	tlv[SNDRV_CTL_TLVO_DB_SCALE_MIN] = -nums * step; +	tlv[SNDRV_CTL_TLVO_DB_SCALE_MUTE_AND_STEP] = step;  }  EXPORT_SYMBOL_GPL(snd_hda_set_vmaster_tlv); @@ -1845,10 +1845,10 @@ static int init_slave_0dB(struct snd_kcontrol *slave,  	} else if (kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_READ)  		tlv = kctl->tlv.p; -	if (!tlv || tlv[0] != SNDRV_CTL_TLVT_DB_SCALE) +	if (!tlv || tlv[SNDRV_CTL_TLVO_TYPE] != SNDRV_CTL_TLVT_DB_SCALE)  		return 0; -	step = tlv[3]; +	step = tlv[SNDRV_CTL_TLVO_DB_SCALE_MUTE_AND_STEP];  	step &= ~TLV_DB_SCALE_MUTE;  	if (!step)  		return 0; @@ -1860,7 +1860,7 @@ static int init_slave_0dB(struct snd_kcontrol *slave,  	}  	arg->step = step; -	val = -tlv[2] / step; +	val = -tlv[SNDRV_CTL_TLVO_DB_SCALE_MIN] / step;  	if (val > 0) {  		put_kctl_with_value(slave, val);  		return val; @@ -2175,6 +2175,8 @@ static int snd_hda_spdif_default_get(struct snd_kcontrol *kcontrol,  	int idx = kcontrol->private_value;  	struct hda_spdif_out *spdif; +	if (WARN_ON(codec->spdif_out.used <= idx)) +		return -EINVAL;  	mutex_lock(&codec->spdif_mutex);  	spdif = snd_array_elem(&codec->spdif_out, idx);  	ucontrol->value.iec958.status[0] = spdif->status & 0xff; @@ -2282,6 +2284,8 @@ static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol,  	unsigned short val;  	int change; +	if (WARN_ON(codec->spdif_out.used <= idx)) +		return -EINVAL;  	mutex_lock(&codec->spdif_mutex);  	spdif = snd_array_elem(&codec->spdif_out, idx);  	nid = spdif->nid; @@ -2308,6 +2312,8 @@ static int snd_hda_spdif_out_switch_get(struct snd_kcontrol *kcontrol,  	int idx = kcontrol->private_value;  	struct hda_spdif_out *spdif; +	if (WARN_ON(codec->spdif_out.used <= idx)) +		return -EINVAL;  	mutex_lock(&codec->spdif_mutex);  	spdif = snd_array_elem(&codec->spdif_out, idx);  	ucontrol->value.integer.value[0] = spdif->ctls & AC_DIG1_ENABLE; @@ -2336,6 +2342,8 @@ static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol,  	unsigned short val;  	int change; +	if (WARN_ON(codec->spdif_out.used <= idx)) +		return -EINVAL;  	mutex_lock(&codec->spdif_mutex);  	spdif = snd_array_elem(&codec->spdif_out, idx);  	nid = spdif->nid; @@ -2461,10 +2469,10 @@ EXPORT_SYMBOL_GPL(snd_hda_create_dig_out_ctls);  struct hda_spdif_out *snd_hda_spdif_out_of_nid(struct hda_codec *codec,  					       hda_nid_t nid)  { +	struct hda_spdif_out *spdif;  	int i; -	for (i = 0; i < codec->spdif_out.used; i++) { -		struct hda_spdif_out *spdif = -				snd_array_elem(&codec->spdif_out, i); + +	snd_array_for_each(&codec->spdif_out, i, spdif) {  		if (spdif->nid == nid)  			return spdif;  	} @@ -2483,6 +2491,8 @@ void snd_hda_spdif_ctls_unassign(struct hda_codec *codec, int idx)  {  	struct hda_spdif_out *spdif; +	if (WARN_ON(codec->spdif_out.used <= idx)) +		return;  	mutex_lock(&codec->spdif_mutex);  	spdif = snd_array_elem(&codec->spdif_out, idx);  	spdif->nid = (u16)-1; @@ -2503,6 +2513,8 @@ void snd_hda_spdif_ctls_assign(struct hda_codec *codec, int idx, hda_nid_t nid)  	struct hda_spdif_out *spdif;  	unsigned short val; +	if (WARN_ON(codec->spdif_out.used <= idx)) +		return;  	mutex_lock(&codec->spdif_mutex);  	spdif = snd_array_elem(&codec->spdif_out, idx);  	if (spdif->nid != nid) { @@ -2887,8 +2899,9 @@ static int hda_codec_runtime_suspend(struct device *dev)  	list_for_each_entry(pcm, &codec->pcm_list_head, list)  		snd_pcm_suspend_all(pcm->pcm);  	state = hda_call_codec_suspend(codec); -	if (codec_has_clkstop(codec) && codec_has_epss(codec) && -	    (state & AC_PWRST_CLK_STOP_OK)) +	if (codec->link_down_at_suspend || +	    (codec_has_clkstop(codec) && codec_has_epss(codec) && +	     (state & AC_PWRST_CLK_STOP_OK)))  		snd_hdac_codec_link_down(&codec->core);  	snd_hdac_link_power(&codec->core, false);  	return 0; |