vga_switcheroo: Enable/disable audio clients at the right time
authorTakashi Iwai <tiwai@suse.de>
Sat, 9 Jun 2012 06:46:42 +0000 (08:46 +0200)
committerTakashi Iwai <tiwai@suse.de>
Sat, 9 Jun 2012 10:14:43 +0000 (12:14 +0200)
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>
drivers/gpu/vga/vga_switcheroo.c

index eb4f64f0a56525e46bfc97a9eab4dda5bfde43fe..5b3c7d135dc91c407fc9b2bf19b2e3e912ccfed5 100644 (file)
@@ -304,8 +304,6 @@ static int vga_switchto_stage1(struct vga_switcheroo_client *new_client)
                vga_switchon(new_client);
 
        vga_set_default_device(new_client->pdev);
-       set_audio_state(new_client->id, VGA_SWITCHEROO_ON);
-
        return 0;
 }
 
@@ -321,6 +319,8 @@ static int vga_switchto_stage2(struct vga_switcheroo_client *new_client)
 
        active->active = false;
 
+       set_audio_state(active->id, VGA_SWITCHEROO_OFF);
+
        if (new_client->fb_info) {
                struct fb_event event;
                event.info = new_client->fb_info;
@@ -334,11 +334,11 @@ static int vga_switchto_stage2(struct vga_switcheroo_client *new_client)
        if (new_client->ops->reprobe)
                new_client->ops->reprobe(new_client->pdev);
 
-       set_audio_state(active->id, VGA_SWITCHEROO_OFF);
-
        if (active->pwr_state == VGA_SWITCHEROO_ON)
                vga_switchoff(active);
 
+       set_audio_state(new_client->id, VGA_SWITCHEROO_ON);
+
        new_client->active = true;
        return 0;
 }
@@ -384,8 +384,9 @@ vga_switcheroo_debugfs_write(struct file *filp, const char __user *ubuf,
        /* pwr off the device not in use */
        if (strncmp(usercmd, "OFF", 3) == 0) {
                list_for_each_entry(client, &vgasr_priv.clients, list) {
-                       if (client->active)
+                       if (client->active || client_is_audio(client))
                                continue;
+                       set_audio_state(client->id, VGA_SWITCHEROO_OFF);
                        if (client->pwr_state == VGA_SWITCHEROO_ON)
                                vga_switchoff(client);
                }
@@ -394,10 +395,11 @@ vga_switcheroo_debugfs_write(struct file *filp, const char __user *ubuf,
        /* pwr on the device not in use */
        if (strncmp(usercmd, "ON", 2) == 0) {
                list_for_each_entry(client, &vgasr_priv.clients, list) {
-                       if (client->active)
+                       if (client->active || client_is_audio(client))
                                continue;
                        if (client->pwr_state == VGA_SWITCHEROO_OFF)
                                vga_switchon(client);
+                       set_audio_state(client->id, VGA_SWITCHEROO_ON);
                }
                goto out;
        }