diff options
author | Takashi Iwai <tiwai@suse.de> | 2009-05-26 10:07:57 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2009-05-26 11:23:46 -0400 |
commit | aa2936f5fe060e95ae06685149645b234085a468 (patch) | |
tree | c5f25beb1e9be3fc4560446992c7a021362b9c30 /sound/pci/hda | |
parent | 8174086167d43d0fd7b21928074145ae1d15bbab (diff) |
ALSA: hda - Support sync after writing a verb
This patch adds a debug mode to make the codec communication
synchronous. Define SND_HDA_SUPPORT_SYNC_WRITE in hda_codec.c,
and the call of snd_hda_codec_write*() will become synchronous,
i.e. wait for the reply from the codec at each time issuing a verb.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda')
-rw-r--r-- | sound/pci/hda/hda_codec.c | 113 |
1 files changed, 61 insertions, 52 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 77385de01744..d1d5fb9d7afb 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -158,6 +158,38 @@ make_codec_cmd(struct hda_codec *codec, hda_nid_t nid, int direct, | |||
158 | return val; | 158 | return val; |
159 | } | 159 | } |
160 | 160 | ||
161 | /* | ||
162 | * Send and receive a verb | ||
163 | */ | ||
164 | static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd, | ||
165 | unsigned int *res) | ||
166 | { | ||
167 | struct hda_bus *bus = codec->bus; | ||
168 | int err, repeated = 0; | ||
169 | |||
170 | if (res) | ||
171 | *res = -1; | ||
172 | snd_hda_power_up(codec); | ||
173 | mutex_lock(&bus->cmd_mutex); | ||
174 | again: | ||
175 | err = bus->ops.command(bus, cmd); | ||
176 | if (!err) { | ||
177 | if (res) { | ||
178 | *res = bus->ops.get_response(bus); | ||
179 | if (*res == -1 && bus->rirb_error) { | ||
180 | if (repeated++ < 1) { | ||
181 | snd_printd(KERN_WARNING "hda_codec: " | ||
182 | "Trying verb 0x%08x again\n", cmd); | ||
183 | goto again; | ||
184 | } | ||
185 | } | ||
186 | } | ||
187 | } | ||
188 | mutex_unlock(&bus->cmd_mutex); | ||
189 | snd_hda_power_down(codec); | ||
190 | return err; | ||
191 | } | ||
192 | |||
161 | /** | 193 | /** |
162 | * snd_hda_codec_read - send a command and get the response | 194 | * snd_hda_codec_read - send a command and get the response |
163 | * @codec: the HDA codec | 195 | * @codec: the HDA codec |
@@ -174,31 +206,18 @@ unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid, | |||
174 | int direct, | 206 | int direct, |
175 | unsigned int verb, unsigned int parm) | 207 | unsigned int verb, unsigned int parm) |
176 | { | 208 | { |
177 | struct hda_bus *bus = codec->bus; | 209 | unsigned cmd = make_codec_cmd(codec, nid, direct, verb, parm); |
178 | unsigned int cmd, res; | 210 | unsigned int res; |
179 | int repeated = 0; | 211 | codec_exec_verb(codec, cmd, &res); |
180 | |||
181 | cmd = make_codec_cmd(codec, nid, direct, verb, parm); | ||
182 | snd_hda_power_up(codec); | ||
183 | mutex_lock(&bus->cmd_mutex); | ||
184 | again: | ||
185 | if (!bus->ops.command(bus, cmd)) { | ||
186 | res = bus->ops.get_response(bus); | ||
187 | if (res == -1 && bus->rirb_error) { | ||
188 | if (repeated++ < 1) { | ||
189 | snd_printd(KERN_WARNING "hda_codec: " | ||
190 | "Trying verb 0x%08x again\n", cmd); | ||
191 | goto again; | ||
192 | } | ||
193 | } | ||
194 | } else | ||
195 | res = (unsigned int)-1; | ||
196 | mutex_unlock(&bus->cmd_mutex); | ||
197 | snd_hda_power_down(codec); | ||
198 | return res; | 212 | return res; |
199 | } | 213 | } |
200 | EXPORT_SYMBOL_HDA(snd_hda_codec_read); | 214 | EXPORT_SYMBOL_HDA(snd_hda_codec_read); |
201 | 215 | ||
216 | /* Define the below to send and receive verbs synchronously. | ||
217 | * If you often get any codec communication errors, this is worth to try. | ||
218 | */ | ||
219 | /* #define SND_HDA_SUPPORT_SYNC_WRITE */ | ||
220 | |||
202 | /** | 221 | /** |
203 | * snd_hda_codec_write - send a single command without waiting for response | 222 | * snd_hda_codec_write - send a single command without waiting for response |
204 | * @codec: the HDA codec | 223 | * @codec: the HDA codec |
@@ -214,17 +233,13 @@ EXPORT_SYMBOL_HDA(snd_hda_codec_read); | |||
214 | int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct, | 233 | int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct, |
215 | unsigned int verb, unsigned int parm) | 234 | unsigned int verb, unsigned int parm) |
216 | { | 235 | { |
217 | struct hda_bus *bus = codec->bus; | 236 | unsigned int cmd = make_codec_cmd(codec, nid, direct, verb, parm); |
237 | #ifdef SND_HDA_SUPPORT_SYNC_WRITE | ||
218 | unsigned int res; | 238 | unsigned int res; |
219 | int err; | 239 | return codec_exec_verb(codec, cmd, &res); |
220 | 240 | #else | |
221 | res = make_codec_cmd(codec, nid, direct, verb, parm); | 241 | return codec_exec_verb(codec, cmd, NULL); |
222 | snd_hda_power_up(codec); | 242 | #endif |
223 | mutex_lock(&bus->cmd_mutex); | ||
224 | err = bus->ops.command(bus, res); | ||
225 | mutex_unlock(&bus->cmd_mutex); | ||
226 | snd_hda_power_down(codec); | ||
227 | return err; | ||
228 | } | 243 | } |
229 | EXPORT_SYMBOL_HDA(snd_hda_codec_write); | 244 | EXPORT_SYMBOL_HDA(snd_hda_codec_write); |
230 | 245 | ||
@@ -2281,28 +2296,22 @@ EXPORT_SYMBOL_HDA(snd_hda_create_spdif_in_ctls); | |||
2281 | int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid, | 2296 | int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid, |
2282 | int direct, unsigned int verb, unsigned int parm) | 2297 | int direct, unsigned int verb, unsigned int parm) |
2283 | { | 2298 | { |
2284 | struct hda_bus *bus = codec->bus; | 2299 | int err = snd_hda_codec_write(codec, nid, direct, verb, parm); |
2285 | unsigned int res; | 2300 | struct hda_cache_head *c; |
2286 | int err; | 2301 | u32 key; |
2287 | 2302 | ||
2288 | res = make_codec_cmd(codec, nid, direct, verb, parm); | 2303 | if (err < 0) |
2289 | snd_hda_power_up(codec); | 2304 | return err; |
2290 | mutex_lock(&bus->cmd_mutex); | 2305 | /* parm may contain the verb stuff for get/set amp */ |
2291 | err = bus->ops.command(bus, res); | 2306 | verb = verb | (parm >> 8); |
2292 | if (!err) { | 2307 | parm &= 0xff; |
2293 | struct hda_cache_head *c; | 2308 | key = build_cmd_cache_key(nid, verb); |
2294 | u32 key; | 2309 | mutex_lock(&codec->bus->cmd_mutex); |
2295 | /* parm may contain the verb stuff for get/set amp */ | 2310 | c = get_alloc_hash(&codec->cmd_cache, key); |
2296 | verb = verb | (parm >> 8); | 2311 | if (c) |
2297 | parm &= 0xff; | 2312 | c->val = parm; |
2298 | key = build_cmd_cache_key(nid, verb); | 2313 | mutex_unlock(&codec->bus->cmd_mutex); |
2299 | c = get_alloc_hash(&codec->cmd_cache, key); | 2314 | return 0; |
2300 | if (c) | ||
2301 | c->val = parm; | ||
2302 | } | ||
2303 | mutex_unlock(&bus->cmd_mutex); | ||
2304 | snd_hda_power_down(codec); | ||
2305 | return err; | ||
2306 | } | 2315 | } |
2307 | EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache); | 2316 | EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache); |
2308 | 2317 | ||