| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: acpi_display.c,v 1.3 2010/10/26 22:27:44 gsutre Exp $ */ | | 1 | /* $NetBSD: acpi_display.c,v 1.4 2010/10/28 21:45:02 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.3 2010/10/26 22:27:44 gsutre Exp $"); | | 69 | __KERNEL_RCSID(0, "$NetBSD: acpi_display.c,v 1.4 2010/10/28 21:45:02 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> |
| @@ -337,27 +337,30 @@ static void acpidisp_out_print_capabilit | | | @@ -337,27 +337,30 @@ static void acpidisp_out_print_capabilit |
337 | | | 337 | |
338 | static void acpidisp_vga_notify_handler(ACPI_HANDLE, uint32_t, void *); | | 338 | static void acpidisp_vga_notify_handler(ACPI_HANDLE, uint32_t, void *); |
339 | static void acpidisp_out_notify_handler(ACPI_HANDLE, uint32_t, void *); | | 339 | static void acpidisp_out_notify_handler(ACPI_HANDLE, uint32_t, void *); |
340 | | | 340 | |
341 | static void acpidisp_vga_cycle_output_device_callback(void *); | | 341 | static void acpidisp_vga_cycle_output_device_callback(void *); |
342 | static void acpidisp_vga_output_device_change_callback(void *); | | 342 | static void acpidisp_vga_output_device_change_callback(void *); |
343 | static void acpidisp_out_increase_brightness_callback(void *); | | 343 | static void acpidisp_out_increase_brightness_callback(void *); |
344 | static void acpidisp_out_decrease_brightness_callback(void *); | | 344 | static void acpidisp_out_decrease_brightness_callback(void *); |
345 | static void acpidisp_out_cycle_brightness_callback(void *); | | 345 | static void acpidisp_out_cycle_brightness_callback(void *); |
346 | static void acpidisp_out_zero_brightness_callback(void *); | | 346 | static void acpidisp_out_zero_brightness_callback(void *); |
347 | | | 347 | |
348 | static void acpidisp_vga_sysctl_setup(struct acpidisp_vga_softc *); | | 348 | static void acpidisp_vga_sysctl_setup(struct acpidisp_vga_softc *); |
349 | static void acpidisp_out_sysctl_setup(struct acpidisp_out_softc *); | | 349 | static void acpidisp_out_sysctl_setup(struct acpidisp_out_softc *); |
| | | 350 | #ifdef ACPI_DEBUG |
350 | static int acpidisp_vga_sysctl_policy(SYSCTLFN_PROTO); | | 351 | static int acpidisp_vga_sysctl_policy(SYSCTLFN_PROTO); |
| | | 352 | #endif |
| | | 353 | static int acpidisp_vga_sysctl_policy_output(SYSCTLFN_PROTO); |
351 | #ifdef ACPI_DISP_SWITCH_SYSCTLS | | 354 | #ifdef ACPI_DISP_SWITCH_SYSCTLS |
352 | static int acpidisp_out_sysctl_status(SYSCTLFN_PROTO); | | 355 | static int acpidisp_out_sysctl_status(SYSCTLFN_PROTO); |
353 | static int acpidisp_out_sysctl_state(SYSCTLFN_PROTO); | | 356 | static int acpidisp_out_sysctl_state(SYSCTLFN_PROTO); |
354 | #endif | | 357 | #endif |
355 | static int acpidisp_out_sysctl_brightness(SYSCTLFN_PROTO); | | 358 | static int acpidisp_out_sysctl_brightness(SYSCTLFN_PROTO); |
356 | | | 359 | |
357 | static struct acpidisp_odinfo * | | 360 | static struct acpidisp_odinfo * |
358 | acpidisp_init_odinfo(const struct acpidisp_vga_softc *); | | 361 | acpidisp_init_odinfo(const struct acpidisp_vga_softc *); |
359 | static void acpidisp_vga_bind_outdevs(struct acpidisp_vga_softc *); | | 362 | static void acpidisp_vga_bind_outdevs(struct acpidisp_vga_softc *); |
360 | static struct acpidisp_brctl * | | 363 | static struct acpidisp_brctl * |
361 | acpidisp_init_brctl(const struct acpidisp_out_softc *); | | 364 | acpidisp_init_brctl(const struct acpidisp_out_softc *); |
362 | | | 365 | |
363 | static int acpidisp_set_policy(const struct acpidisp_vga_softc *, | | 366 | static int acpidisp_set_policy(const struct acpidisp_vga_softc *, |
| @@ -1104,31 +1107,39 @@ acpidisp_vga_sysctl_setup(struct acpidis | | | @@ -1104,31 +1107,39 @@ acpidisp_vga_sysctl_setup(struct acpidis |
1104 | if ((sysctl_createv(&asc->sc_log, 0, &rnode, &rnode, | | 1107 | if ((sysctl_createv(&asc->sc_log, 0, &rnode, &rnode, |
1105 | 0, CTLTYPE_NODE, "acpi", NULL, | | 1108 | 0, CTLTYPE_NODE, "acpi", NULL, |
1106 | NULL, 0, NULL, 0, | | 1109 | NULL, 0, NULL, 0, |
1107 | CTL_CREATE, CTL_EOL)) != 0) | | 1110 | CTL_CREATE, CTL_EOL)) != 0) |
1108 | goto fail; | | 1111 | goto fail; |
1109 | | | 1112 | |
1110 | if ((sysctl_createv(&asc->sc_log, 0, &rnode, &rnode, | | 1113 | if ((sysctl_createv(&asc->sc_log, 0, &rnode, &rnode, |
1111 | 0, CTLTYPE_NODE, device_xname(asc->sc_dev), | | 1114 | 0, CTLTYPE_NODE, device_xname(asc->sc_dev), |
1112 | SYSCTL_DESCR("ACPI display adapter controls"), | | 1115 | SYSCTL_DESCR("ACPI display adapter controls"), |
1113 | NULL, 0, NULL, 0, | | 1116 | NULL, 0, NULL, 0, |
1114 | CTL_CREATE, CTL_EOL)) != 0) | | 1117 | CTL_CREATE, CTL_EOL)) != 0) |
1115 | goto fail; | | 1118 | goto fail; |
1116 | | | 1119 | |
| | | 1120 | #ifdef ACPI_DEBUG |
1117 | (void)sysctl_createv(&asc->sc_log, 0, &rnode, NULL, | | 1121 | (void)sysctl_createv(&asc->sc_log, 0, &rnode, NULL, |
1118 | CTLFLAG_READWRITE | CTLFLAG_HEX, CTLTYPE_INT, "policy", | | 1122 | CTLFLAG_READWRITE | CTLFLAG_HEX, CTLTYPE_INT, "bios_policy", |
1119 | SYSCTL_DESCR("Current BIOS switch policy"), | | 1123 | SYSCTL_DESCR("Current BIOS switch policies (debug)"), |
1120 | acpidisp_vga_sysctl_policy, 0, asc, 0, | | 1124 | acpidisp_vga_sysctl_policy, 0, asc, 0, |
1121 | CTL_CREATE, CTL_EOL); | | 1125 | CTL_CREATE, CTL_EOL); |
| | | 1126 | #endif |
| | | 1127 | |
| | | 1128 | (void)sysctl_createv(&asc->sc_log, 0, &rnode, NULL, |
| | | 1129 | CTLFLAG_READWRITE, CTLTYPE_BOOL, "bios_switch", |
| | | 1130 | SYSCTL_DESCR("Current BIOS output switching policy"), |
| | | 1131 | acpidisp_vga_sysctl_policy_output, 0, asc, 0, |
| | | 1132 | CTL_CREATE, CTL_EOL); |
1122 | } | | 1133 | } |
1123 | | | 1134 | |
1124 | return; | | 1135 | return; |
1125 | | | 1136 | |
1126 | fail: | | 1137 | fail: |
1127 | aprint_error_dev(asc->sc_dev, "couldn't add sysctl nodes\n"); | | 1138 | aprint_error_dev(asc->sc_dev, "couldn't add sysctl nodes\n"); |
1128 | } | | 1139 | } |
1129 | | | 1140 | |
1130 | static void | | 1141 | static void |
1131 | acpidisp_out_sysctl_setup(struct acpidisp_out_softc *osc) | | 1142 | acpidisp_out_sysctl_setup(struct acpidisp_out_softc *osc) |
1132 | { | | 1143 | { |
1133 | const struct sysctlnode *rnode; | | 1144 | const struct sysctlnode *rnode; |
1134 | | | 1145 | |
| @@ -1192,26 +1203,27 @@ acpidisp_out_sysctl_setup(struct acpidis | | | @@ -1192,26 +1203,27 @@ acpidisp_out_sysctl_setup(struct acpidis |
1192 | } | | 1203 | } |
1193 | #endif | | 1204 | #endif |
1194 | | | 1205 | |
1195 | return; | | 1206 | return; |
1196 | | | 1207 | |
1197 | fail: | | 1208 | fail: |
1198 | aprint_error_dev(osc->sc_dev, "couldn't add sysctl nodes\n"); | | 1209 | aprint_error_dev(osc->sc_dev, "couldn't add sysctl nodes\n"); |
1199 | } | | 1210 | } |
1200 | | | 1211 | |
1201 | /* | | 1212 | /* |
1202 | * Sysctl callbacks. | | 1213 | * Sysctl callbacks. |
1203 | */ | | 1214 | */ |
1204 | | | 1215 | |
| | | 1216 | #ifdef ACPI_DEBUG |
1205 | static int | | 1217 | static int |
1206 | acpidisp_vga_sysctl_policy(SYSCTLFN_ARGS) | | 1218 | acpidisp_vga_sysctl_policy(SYSCTLFN_ARGS) |
1207 | { | | 1219 | { |
1208 | struct sysctlnode node; | | 1220 | struct sysctlnode node; |
1209 | struct acpidisp_vga_softc *asc; | | 1221 | struct acpidisp_vga_softc *asc; |
1210 | uint32_t val; | | 1222 | uint32_t val; |
1211 | int error; | | 1223 | int error; |
1212 | | | 1224 | |
1213 | node = *rnode; | | 1225 | node = *rnode; |
1214 | asc = (struct acpidisp_vga_softc *)node.sysctl_data; | | 1226 | asc = (struct acpidisp_vga_softc *)node.sysctl_data; |
1215 | | | 1227 | |
1216 | mutex_enter(&asc->sc_mtx); | | 1228 | mutex_enter(&asc->sc_mtx); |
1217 | val = (uint32_t)asc->sc_policy.raw; | | 1229 | val = (uint32_t)asc->sc_policy.raw; |
| @@ -1222,26 +1234,58 @@ acpidisp_vga_sysctl_policy(SYSCTLFN_ARGS | | | @@ -1222,26 +1234,58 @@ acpidisp_vga_sysctl_policy(SYSCTLFN_ARGS |
1222 | if (error || newp == NULL) | | 1234 | if (error || newp == NULL) |
1223 | return error; | | 1235 | return error; |
1224 | | | 1236 | |
1225 | if (val > 0x7) | | 1237 | if (val > 0x7) |
1226 | return EINVAL; | | 1238 | return EINVAL; |
1227 | | | 1239 | |
1228 | mutex_enter(&asc->sc_mtx); | | 1240 | mutex_enter(&asc->sc_mtx); |
1229 | asc->sc_policy.raw = (uint8_t)val; | | 1241 | asc->sc_policy.raw = (uint8_t)val; |
1230 | error = acpidisp_set_policy(asc, asc->sc_policy.raw); | | 1242 | error = acpidisp_set_policy(asc, asc->sc_policy.raw); |
1231 | mutex_exit(&asc->sc_mtx); | | 1243 | mutex_exit(&asc->sc_mtx); |
1232 | | | 1244 | |
1233 | return error; | | 1245 | return error; |
1234 | } | | 1246 | } |
| | | 1247 | #endif |
| | | 1248 | |
| | | 1249 | static int |
| | | 1250 | acpidisp_vga_sysctl_policy_output(SYSCTLFN_ARGS) |
| | | 1251 | { |
| | | 1252 | struct sysctlnode node; |
| | | 1253 | struct acpidisp_vga_softc *asc; |
| | | 1254 | bool val; |
| | | 1255 | int error; |
| | | 1256 | |
| | | 1257 | node = *rnode; |
| | | 1258 | asc = (struct acpidisp_vga_softc *)node.sysctl_data; |
| | | 1259 | |
| | | 1260 | mutex_enter(&asc->sc_mtx); |
| | | 1261 | val = (asc->sc_policy.fmt.output == ACPI_DISP_POLICY_OUTPUT_AUTO); |
| | | 1262 | mutex_exit(&asc->sc_mtx); |
| | | 1263 | |
| | | 1264 | node.sysctl_data = &val; |
| | | 1265 | error = sysctl_lookup(SYSCTLFN_CALL(&node)); |
| | | 1266 | if (error || newp == NULL) |
| | | 1267 | return error; |
| | | 1268 | |
| | | 1269 | mutex_enter(&asc->sc_mtx); |
| | | 1270 | if (val) |
| | | 1271 | asc->sc_policy.fmt.output = ACPI_DISP_POLICY_OUTPUT_AUTO; |
| | | 1272 | else |
| | | 1273 | asc->sc_policy.fmt.output = ACPI_DISP_POLICY_OUTPUT_NORMAL; |
| | | 1274 | error = acpidisp_set_policy(asc, asc->sc_policy.raw); |
| | | 1275 | mutex_exit(&asc->sc_mtx); |
| | | 1276 | |
| | | 1277 | return error; |
| | | 1278 | } |
1235 | | | 1279 | |
1236 | #ifdef ACPI_DISP_SWITCH_SYSCTLS | | 1280 | #ifdef ACPI_DISP_SWITCH_SYSCTLS |
1237 | static int | | 1281 | static int |
1238 | acpidisp_out_sysctl_status(SYSCTLFN_ARGS) | | 1282 | acpidisp_out_sysctl_status(SYSCTLFN_ARGS) |
1239 | { | | 1283 | { |
1240 | struct sysctlnode node; | | 1284 | struct sysctlnode node; |
1241 | struct acpidisp_out_softc *osc; | | 1285 | struct acpidisp_out_softc *osc; |
1242 | uint32_t val; | | 1286 | uint32_t val; |
1243 | int error; | | 1287 | int error; |
1244 | | | 1288 | |
1245 | node = *rnode; | | 1289 | node = *rnode; |
1246 | osc = (struct acpidisp_out_softc *)node.sysctl_data; | | 1290 | osc = (struct acpidisp_out_softc *)node.sysctl_data; |
1247 | | | 1291 | |