| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: acpi_display.c,v 1.4 2010/10/28 21:45:02 gsutre Exp $ */ | | 1 | /* $NetBSD: acpi_display.c,v 1.5 2010/10/29 09:04:38 gsutre Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2010 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 2010 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Gregoire Sutre. | | 8 | * by Gregoire Sutre. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
| @@ -56,27 +56,27 @@ | | | @@ -56,27 +56,27 @@ |
56 | * (sysctl). The ACPI display adapter's mutex is shared with all ACPI display | | 56 | * (sysctl). The ACPI display adapter's mutex is shared with all ACPI display |
57 | * output devices attached to it. | | 57 | * output devices attached to it. |
58 | * | | 58 | * |
59 | * The mutex only prevents undesired interleavings of ACPI notify handlers, | | 59 | * The mutex only prevents undesired interleavings of ACPI notify handlers, |
60 | * sysctl callbacks, and pmf(9) suspend/resume routines. Race conditions with | | 60 | * sysctl callbacks, and pmf(9) suspend/resume routines. Race conditions with |
61 | * autoconf(9) detachment routines could, in theory, still occur. | | 61 | * autoconf(9) detachment routines could, in theory, still occur. |
62 | * | | 62 | * |
63 | * The array of connected output devices (sc_odinfo) is, after attachment, only | | 63 | * The array of connected output devices (sc_odinfo) is, after attachment, only |
64 | * used in ACPI notify handler callbacks. Since two such callbacks cannot be | | 64 | * used in ACPI notify handler callbacks. Since two such callbacks cannot be |
65 | * running simultaneously, this information does not need protection. | | 65 | * running simultaneously, this information does not need protection. |
66 | */ | | 66 | */ |
67 | | | 67 | |
68 | #include <sys/cdefs.h> | | 68 | #include <sys/cdefs.h> |
69 | __KERNEL_RCSID(0, "$NetBSD: acpi_display.c,v 1.4 2010/10/28 21:45:02 gsutre Exp $"); | | 69 | __KERNEL_RCSID(0, "$NetBSD: acpi_display.c,v 1.5 2010/10/29 09:04:38 gsutre Exp $"); |
70 | | | 70 | |
71 | #include <sys/param.h> | | 71 | #include <sys/param.h> |
72 | #include <sys/device.h> | | 72 | #include <sys/device.h> |
73 | #include <sys/kmem.h> | | 73 | #include <sys/kmem.h> |
74 | #include <sys/module.h> | | 74 | #include <sys/module.h> |
75 | #include <sys/mutex.h> | | 75 | #include <sys/mutex.h> |
76 | #include <sys/sysctl.h> | | 76 | #include <sys/sysctl.h> |
77 | #include <sys/systm.h> | | 77 | #include <sys/systm.h> |
78 | | | 78 | |
79 | #include <dev/pci/pcireg.h> | | 79 | #include <dev/pci/pcireg.h> |
80 | #include <dev/pci/pcidevs.h> | | 80 | #include <dev/pci/pcidevs.h> |
81 | | | 81 | |
82 | #include <dev/acpi/acpireg.h> | | 82 | #include <dev/acpi/acpireg.h> |
| @@ -901,34 +901,40 @@ acpidisp_out_notify_handler(ACPI_HANDLE | | | @@ -901,34 +901,40 @@ acpidisp_out_notify_handler(ACPI_HANDLE |
901 | * (b) ACPI display notify callbacks are scheduled with AcpiOsExecute, | | 901 | * (b) ACPI display notify callbacks are scheduled with AcpiOsExecute, |
902 | * (c) callbacks scheduled with AcpiOsExecute are executed sequentially. | | 902 | * (c) callbacks scheduled with AcpiOsExecute are executed sequentially. |
903 | */ | | 903 | */ |
904 | | | 904 | |
905 | static void | | 905 | static void |
906 | acpidisp_vga_cycle_output_device_callback(void *arg) | | 906 | acpidisp_vga_cycle_output_device_callback(void *arg) |
907 | { | | 907 | { |
908 | struct acpidisp_vga_softc *asc = arg; | | 908 | struct acpidisp_vga_softc *asc = arg; |
909 | struct acpidisp_odinfo *oi = asc->sc_odinfo; | | 909 | struct acpidisp_odinfo *oi = asc->sc_odinfo; |
910 | struct acpidisp_outdev *od; | | 910 | struct acpidisp_outdev *od; |
911 | struct acpidisp_out_softc *osc, *last_osc; | | 911 | struct acpidisp_out_softc *osc, *last_osc; |
912 | acpidisp_od_state_t state, last_state; | | 912 | acpidisp_od_state_t state, last_state; |
913 | acpidisp_od_status_t status; | | 913 | acpidisp_od_status_t status; |
| | | 914 | acpidisp_bios_policy_t lock_policy; |
914 | uint32_t i; | | 915 | uint32_t i; |
915 | | | 916 | |
916 | if (oi == NULL) | | 917 | if (oi == NULL) |
917 | return; | | 918 | return; |
918 | | | 919 | |
919 | /* Mutual exclusion with callbacks of connected output devices. */ | | 920 | /* Mutual exclusion with callbacks of connected output devices. */ |
920 | mutex_enter(&asc->sc_mtx); | | 921 | mutex_enter(&asc->sc_mtx); |
921 | | | 922 | |
| | | 923 | /* Lock the _DGS values. */ |
| | | 924 | lock_policy = asc->sc_policy; |
| | | 925 | lock_policy.fmt.output = ACPI_DISP_POLICY_OUTPUT_LOCKED; |
| | | 926 | (void)acpidisp_set_policy(asc, lock_policy.raw); |
| | | 927 | |
922 | last_osc = NULL; | | 928 | last_osc = NULL; |
923 | for (i = 0, od = oi->oi_dev; i < oi->oi_dev_count; i++, od++) { | | 929 | for (i = 0, od = oi->oi_dev; i < oi->oi_dev_count; i++, od++) { |
924 | if (od->od_device == NULL) | | 930 | if (od->od_device == NULL) |
925 | continue; | | 931 | continue; |
926 | osc = device_private(od->od_device); | | 932 | osc = device_private(od->od_device); |
927 | | | 933 | |
928 | if (!(osc->sc_caps & ACPI_DISP_OUT_CAP__DSS)) | | 934 | if (!(osc->sc_caps & ACPI_DISP_OUT_CAP__DSS)) |
929 | continue; | | 935 | continue; |
930 | if (acpidisp_get_state(osc, &state.raw)) | | 936 | if (acpidisp_get_state(osc, &state.raw)) |
931 | continue; | | 937 | continue; |
932 | | | 938 | |
933 | if (acpidisp_get_status(osc, &status.raw)) { | | 939 | if (acpidisp_get_status(osc, &status.raw)) { |
934 | state.fmt.no_switch = 0; | | 940 | state.fmt.no_switch = 0; |
| @@ -945,26 +951,29 @@ acpidisp_vga_cycle_output_device_callbac | | | @@ -945,26 +951,29 @@ acpidisp_vga_cycle_output_device_callbac |
945 | | | 951 | |
946 | if (last_osc != NULL) | | 952 | if (last_osc != NULL) |
947 | (void)acpidisp_set_state(last_osc, last_state.raw); | | 953 | (void)acpidisp_set_state(last_osc, last_state.raw); |
948 | | | 954 | |
949 | last_osc = osc; | | 955 | last_osc = osc; |
950 | last_state = state; | | 956 | last_state = state; |
951 | } | | 957 | } |
952 | | | 958 | |
953 | if (last_osc != NULL) { | | 959 | if (last_osc != NULL) { |
954 | last_state.fmt.commit = 1; | | 960 | last_state.fmt.commit = 1; |
955 | (void)acpidisp_set_state(last_osc, last_state.raw); | | 961 | (void)acpidisp_set_state(last_osc, last_state.raw); |
956 | } | | 962 | } |
957 | | | 963 | |
| | | 964 | /* Restore the original BIOS policy. */ |
| | | 965 | (void)acpidisp_set_policy(asc, asc->sc_policy.raw); |
| | | 966 | |
958 | mutex_exit(&asc->sc_mtx); | | 967 | mutex_exit(&asc->sc_mtx); |
959 | } | | 968 | } |
960 | | | 969 | |
961 | static void | | 970 | static void |
962 | acpidisp_vga_output_device_change_callback(void *arg) | | 971 | acpidisp_vga_output_device_change_callback(void *arg) |
963 | { | | 972 | { |
964 | struct acpidisp_vga_softc *asc = arg; | | 973 | struct acpidisp_vga_softc *asc = arg; |
965 | struct acpidisp_odinfo *oi = asc->sc_odinfo; | | 974 | struct acpidisp_odinfo *oi = asc->sc_odinfo; |
966 | bool switch_outputs; | | 975 | bool switch_outputs; |
967 | | | 976 | |
968 | if (oi != NULL) { | | 977 | if (oi != NULL) { |
969 | kmem_free(oi->oi_dev, | | 978 | kmem_free(oi->oi_dev, |
970 | oi->oi_dev_count * sizeof(*oi->oi_dev)); | | 979 | oi->oi_dev_count * sizeof(*oi->oi_dev)); |