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 | |
| 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>
| -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 | ||
