aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/vga
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2012-06-09 02:46:42 -0400
committerTakashi Iwai <tiwai@suse.de>2012-06-09 06:14:43 -0400
commitc91c3faea500da34d42a14735f1f67bb137b6413 (patch)
treebd475cbbc47c2fa527b1e4dbe0b9028a7a2a15d4 /drivers/gpu/vga
parent8393ec4a13889339bacfb8b038fb13716eef7a2b (diff)
vga_switcheroo: Enable/disable audio clients at the right time
The audio clients have to be disabled before disabling the VGA and switching. Similarly, enabling the audio client should be done at last. Otherwise the audio-side operation stalls, eventually leading to Oops or lockups. Tested-by: Jörg-Volker Peetz <jvpeetz@web.de> Acked-by: Dave Airlie <airlied@redhat.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'drivers/gpu/vga')
-rw-r--r--drivers/gpu/vga/vga_switcheroo.c14
1 files changed, 8 insertions, 6 deletions
diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c
index eb4f64f0a565..5b3c7d135dc9 100644
--- a/drivers/gpu/vga/vga_switcheroo.c
+++ b/drivers/gpu/vga/vga_switcheroo.c
@@ -304,8 +304,6 @@ static int vga_switchto_stage1(struct vga_switcheroo_client *new_client)
304 vga_switchon(new_client); 304 vga_switchon(new_client);
305 305
306 vga_set_default_device(new_client->pdev); 306 vga_set_default_device(new_client->pdev);
307 set_audio_state(new_client->id, VGA_SWITCHEROO_ON);
308
309 return 0; 307 return 0;
310} 308}
311 309
@@ -321,6 +319,8 @@ static int vga_switchto_stage2(struct vga_switcheroo_client *new_client)
321 319
322 active->active = false; 320 active->active = false;
323 321
322 set_audio_state(active->id, VGA_SWITCHEROO_OFF);
323
324 if (new_client->fb_info) { 324 if (new_client->fb_info) {
325 struct fb_event event; 325 struct fb_event event;
326 event.info = new_client->fb_info; 326 event.info = new_client->fb_info;
@@ -334,11 +334,11 @@ static int vga_switchto_stage2(struct vga_switcheroo_client *new_client)
334 if (new_client->ops->reprobe) 334 if (new_client->ops->reprobe)
335 new_client->ops->reprobe(new_client->pdev); 335 new_client->ops->reprobe(new_client->pdev);
336 336
337 set_audio_state(active->id, VGA_SWITCHEROO_OFF);
338
339 if (active->pwr_state == VGA_SWITCHEROO_ON) 337 if (active->pwr_state == VGA_SWITCHEROO_ON)
340 vga_switchoff(active); 338 vga_switchoff(active);
341 339
340 set_audio_state(new_client->id, VGA_SWITCHEROO_ON);
341
342 new_client->active = true; 342 new_client->active = true;
343 return 0; 343 return 0;
344} 344}
@@ -384,8 +384,9 @@ vga_switcheroo_debugfs_write(struct file *filp, const char __user *ubuf,
384 /* pwr off the device not in use */ 384 /* pwr off the device not in use */
385 if (strncmp(usercmd, "OFF", 3) == 0) { 385 if (strncmp(usercmd, "OFF", 3) == 0) {
386 list_for_each_entry(client, &vgasr_priv.clients, list) { 386 list_for_each_entry(client, &vgasr_priv.clients, list) {
387 if (client->active) 387 if (client->active || client_is_audio(client))
388 continue; 388 continue;
389 set_audio_state(client->id, VGA_SWITCHEROO_OFF);
389 if (client->pwr_state == VGA_SWITCHEROO_ON) 390 if (client->pwr_state == VGA_SWITCHEROO_ON)
390 vga_switchoff(client); 391 vga_switchoff(client);
391 } 392 }
@@ -394,10 +395,11 @@ vga_switcheroo_debugfs_write(struct file *filp, const char __user *ubuf,
394 /* pwr on the device not in use */ 395 /* pwr on the device not in use */
395 if (strncmp(usercmd, "ON", 2) == 0) { 396 if (strncmp(usercmd, "ON", 2) == 0) {
396 list_for_each_entry(client, &vgasr_priv.clients, list) { 397 list_for_each_entry(client, &vgasr_priv.clients, list) {
397 if (client->active) 398 if (client->active || client_is_audio(client))
398 continue; 399 continue;
399 if (client->pwr_state == VGA_SWITCHEROO_OFF) 400 if (client->pwr_state == VGA_SWITCHEROO_OFF)
400 vga_switchon(client); 401 vga_switchon(client);
402 set_audio_state(client->id, VGA_SWITCHEROO_ON);
401 } 403 }
402 goto out; 404 goto out;
403 } 405 }