diff options
author | Takashi Iwai <tiwai@suse.de> | 2012-05-10 04:21:29 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2012-05-10 08:56:15 -0400 |
commit | e3245cddcf56ccd810b73d0a2918e02560da93ab (patch) | |
tree | 95deb25015d48b4706a7972d2f88bf235e3d8177 /sound/pci/hda | |
parent | 61d648fb4726f8a89c07cd1904f9c2e11bf26df5 (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.c | 35 | ||||
-rw-r--r-- | sound/pci/hda/patch_hdmi.c | 4 |
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 | } |
3098 | EXPORT_SYMBOL_HDA(snd_hda_create_spdif_out_ctls); | 3108 | EXPORT_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 | */ | ||
3100 | struct hda_spdif_out *snd_hda_spdif_out_of_nid(struct hda_codec *codec, | 3113 | struct 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 | ||
3114 | void snd_hda_spdif_ctls_unassign(struct hda_codec *codec, int idx) | 3127 | void 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 | ||
3124 | void snd_hda_spdif_ctls_assign(struct hda_codec *codec, int idx, hda_nid_t nid) | 3138 | void 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 | ||