aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2012-05-10 04:21:29 -0400
committerTakashi Iwai <tiwai@suse.de>2012-05-10 08:56:15 -0400
commite3245cddcf56ccd810b73d0a2918e02560da93ab (patch)
tree95deb25015d48b4706a7972d2f88bf235e3d8177 /sound/pci/hda
parent61d648fb4726f8a89c07cd1904f9c2e11bf26df5 (diff)
ALSA: hda - Protect SPDIF-related stuff via spdif_mutex
Add the missing mutex protection or move into the protected part for SPDIF access codes for codecs. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda')
-rw-r--r--sound/pci/hda/hda_codec.c35
-rw-r--r--sound/pci/hda/patch_hdmi.c4
2 files changed, 27 insertions, 12 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 731f8500a23a..5e7c4bf83abe 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -2864,12 +2864,15 @@ static int snd_hda_spdif_default_get(struct snd_kcontrol *kcontrol,
2864{ 2864{
2865 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 2865 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2866 int idx = kcontrol->private_value; 2866 int idx = kcontrol->private_value;
2867 struct hda_spdif_out *spdif = snd_array_elem(&codec->spdif_out, idx); 2867 struct hda_spdif_out *spdif;
2868 2868
2869 mutex_lock(&codec->spdif_mutex);
2870 spdif = snd_array_elem(&codec->spdif_out, idx);
2869 ucontrol->value.iec958.status[0] = spdif->status & 0xff; 2871 ucontrol->value.iec958.status[0] = spdif->status & 0xff;
2870 ucontrol->value.iec958.status[1] = (spdif->status >> 8) & 0xff; 2872 ucontrol->value.iec958.status[1] = (spdif->status >> 8) & 0xff;
2871 ucontrol->value.iec958.status[2] = (spdif->status >> 16) & 0xff; 2873 ucontrol->value.iec958.status[2] = (spdif->status >> 16) & 0xff;
2872 ucontrol->value.iec958.status[3] = (spdif->status >> 24) & 0xff; 2874 ucontrol->value.iec958.status[3] = (spdif->status >> 24) & 0xff;
2875 mutex_unlock(&codec->spdif_mutex);
2873 2876
2874 return 0; 2877 return 0;
2875} 2878}
@@ -2955,12 +2958,14 @@ static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol,
2955{ 2958{
2956 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 2959 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2957 int idx = kcontrol->private_value; 2960 int idx = kcontrol->private_value;
2958 struct hda_spdif_out *spdif = snd_array_elem(&codec->spdif_out, idx); 2961 struct hda_spdif_out *spdif;
2959 hda_nid_t nid = spdif->nid; 2962 hda_nid_t nid;
2960 unsigned short val; 2963 unsigned short val;
2961 int change; 2964 int change;
2962 2965
2963 mutex_lock(&codec->spdif_mutex); 2966 mutex_lock(&codec->spdif_mutex);
2967 spdif = snd_array_elem(&codec->spdif_out, idx);
2968 nid = spdif->nid;
2964 spdif->status = ucontrol->value.iec958.status[0] | 2969 spdif->status = ucontrol->value.iec958.status[0] |
2965 ((unsigned int)ucontrol->value.iec958.status[1] << 8) | 2970 ((unsigned int)ucontrol->value.iec958.status[1] << 8) |
2966 ((unsigned int)ucontrol->value.iec958.status[2] << 16) | 2971 ((unsigned int)ucontrol->value.iec958.status[2] << 16) |
@@ -2982,9 +2987,12 @@ static int snd_hda_spdif_out_switch_get(struct snd_kcontrol *kcontrol,
2982{ 2987{
2983 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 2988 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2984 int idx = kcontrol->private_value; 2989 int idx = kcontrol->private_value;
2985 struct hda_spdif_out *spdif = snd_array_elem(&codec->spdif_out, idx); 2990 struct hda_spdif_out *spdif;
2986 2991
2992 mutex_lock(&codec->spdif_mutex);
2993 spdif = snd_array_elem(&codec->spdif_out, idx);
2987 ucontrol->value.integer.value[0] = spdif->ctls & AC_DIG1_ENABLE; 2994 ucontrol->value.integer.value[0] = spdif->ctls & AC_DIG1_ENABLE;
2995 mutex_unlock(&codec->spdif_mutex);
2988 return 0; 2996 return 0;
2989} 2997}
2990 2998
@@ -3004,12 +3012,14 @@ static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol,
3004{ 3012{
3005 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 3013 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3006 int idx = kcontrol->private_value; 3014 int idx = kcontrol->private_value;
3007 struct hda_spdif_out *spdif = snd_array_elem(&codec->spdif_out, idx); 3015 struct hda_spdif_out *spdif;
3008 hda_nid_t nid = spdif->nid; 3016 hda_nid_t nid;
3009 unsigned short val; 3017 unsigned short val;
3010 int change; 3018 int change;
3011 3019
3012 mutex_lock(&codec->spdif_mutex); 3020 mutex_lock(&codec->spdif_mutex);
3021 spdif = snd_array_elem(&codec->spdif_out, idx);
3022 nid = spdif->nid;
3013 val = spdif->ctls & ~AC_DIG1_ENABLE; 3023 val = spdif->ctls & ~AC_DIG1_ENABLE;
3014 if (ucontrol->value.integer.value[0]) 3024 if (ucontrol->value.integer.value[0])
3015 val |= AC_DIG1_ENABLE; 3025 val |= AC_DIG1_ENABLE;
@@ -3097,6 +3107,9 @@ int snd_hda_create_spdif_out_ctls(struct hda_codec *codec,
3097} 3107}
3098EXPORT_SYMBOL_HDA(snd_hda_create_spdif_out_ctls); 3108EXPORT_SYMBOL_HDA(snd_hda_create_spdif_out_ctls);
3099 3109
3110/* get the hda_spdif_out entry from the given NID
3111 * call within spdif_mutex lock
3112 */
3100struct hda_spdif_out *snd_hda_spdif_out_of_nid(struct hda_codec *codec, 3113struct hda_spdif_out *snd_hda_spdif_out_of_nid(struct hda_codec *codec,
3101 hda_nid_t nid) 3114 hda_nid_t nid)
3102{ 3115{
@@ -3113,9 +3126,10 @@ EXPORT_SYMBOL_HDA(snd_hda_spdif_out_of_nid);
3113 3126
3114void snd_hda_spdif_ctls_unassign(struct hda_codec *codec, int idx) 3127void snd_hda_spdif_ctls_unassign(struct hda_codec *codec, int idx)
3115{ 3128{
3116 struct hda_spdif_out *spdif = snd_array_elem(&codec->spdif_out, idx); 3129 struct hda_spdif_out *spdif;
3117 3130
3118 mutex_lock(&codec->spdif_mutex); 3131 mutex_lock(&codec->spdif_mutex);
3132 spdif = snd_array_elem(&codec->spdif_out, idx);
3119 spdif->nid = (u16)-1; 3133 spdif->nid = (u16)-1;
3120 mutex_unlock(&codec->spdif_mutex); 3134 mutex_unlock(&codec->spdif_mutex);
3121} 3135}
@@ -3123,10 +3137,11 @@ EXPORT_SYMBOL_HDA(snd_hda_spdif_ctls_unassign);
3123 3137
3124void snd_hda_spdif_ctls_assign(struct hda_codec *codec, int idx, hda_nid_t nid) 3138void snd_hda_spdif_ctls_assign(struct hda_codec *codec, int idx, hda_nid_t nid)
3125{ 3139{
3126 struct hda_spdif_out *spdif = snd_array_elem(&codec->spdif_out, idx); 3140 struct hda_spdif_out *spdif;
3127 unsigned short val; 3141 unsigned short val;
3128 3142
3129 mutex_lock(&codec->spdif_mutex); 3143 mutex_lock(&codec->spdif_mutex);
3144 spdif = snd_array_elem(&codec->spdif_out, idx);
3130 if (spdif->nid != nid) { 3145 if (spdif->nid != nid) {
3131 spdif->nid = nid; 3146 spdif->nid = nid;
3132 val = spdif->ctls; 3147 val = spdif->ctls;
@@ -4747,11 +4762,11 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
4747{ 4762{
4748 const hda_nid_t *nids = mout->dac_nids; 4763 const hda_nid_t *nids = mout->dac_nids;
4749 int chs = substream->runtime->channels; 4764 int chs = substream->runtime->channels;
4750 struct hda_spdif_out *spdif = 4765 struct hda_spdif_out *spdif;
4751 snd_hda_spdif_out_of_nid(codec, mout->dig_out_nid);
4752 int i; 4766 int i;
4753 4767
4754 mutex_lock(&codec->spdif_mutex); 4768 mutex_lock(&codec->spdif_mutex);
4769 spdif = snd_hda_spdif_out_of_nid(codec, mout->dig_out_nid);
4755 if (mout->dig_out_nid && mout->share_spdif && 4770 if (mout->dig_out_nid && mout->share_spdif &&
4756 mout->dig_out_used != HDA_DIG_EXCLUSIVE) { 4771 mout->dig_out_used != HDA_DIG_EXCLUSIVE) {
4757 if (chs == 2 && 4772 if (chs == 2 &&
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index 83f345f3c961..ad319d4dc32f 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -1592,10 +1592,10 @@ static int nvhdmi_8ch_7x_pcm_prepare(struct hda_pcm_stream *hinfo,
1592 unsigned int dataDCC2, channel_id; 1592 unsigned int dataDCC2, channel_id;
1593 int i; 1593 int i;
1594 struct hdmi_spec *spec = codec->spec; 1594 struct hdmi_spec *spec = codec->spec;
1595 struct hda_spdif_out *spdif = 1595 struct hda_spdif_out *spdif;
1596 snd_hda_spdif_out_of_nid(codec, spec->cvts[0].cvt_nid);
1597 1596
1598 mutex_lock(&codec->spdif_mutex); 1597 mutex_lock(&codec->spdif_mutex);
1598 spdif = snd_hda_spdif_out_of_nid(codec, spec->cvts[0].cvt_nid);
1599 1599
1600 chs = substream->runtime->channels; 1600 chs = substream->runtime->channels;
1601 1601