summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornjl <njl@FreeBSD.org>2004-04-14 00:23:58 +0000
committernjl <njl@FreeBSD.org>2004-04-14 00:23:58 +0000
commit36be62a85e57cc41d82b559f10f52e78a1272f4e (patch)
tree34714c9da56a83f3e76045607c1b518e4a645376
parent2d6a22a91ddcf2e70275c468b19b9ef2b8f58e70 (diff)
downloadFreeBSD-src-36be62a85e57cc41d82b559f10f52e78a1272f4e.zip
FreeBSD-src-36be62a85e57cc41d82b559f10f52e78a1272f4e.tar.gz
Add support for video output switching. It appears no systems use HCI to
change the video output but use a separate device with a DSSX method and a HID of "TOS6201" instead. We use a pseudo-driver to get the handle for this object and pass it to the acpi_toshiba driver. This is untested but seems to match the Linux Toshiba driver.
-rw-r--r--share/man/man4/man4.i386/acpi_toshiba.47
-rw-r--r--sys/dev/acpi_support/acpi_toshiba.c88
-rw-r--r--sys/i386/acpica/acpi_toshiba.c88
3 files changed, 163 insertions, 20 deletions
diff --git a/share/man/man4/man4.i386/acpi_toshiba.4 b/share/man/man4/man4.i386/acpi_toshiba.4
index 4818fcd..fc6d9ee 100644
--- a/share/man/man4/man4.i386/acpi_toshiba.4
+++ b/share/man/man4/man4.i386/acpi_toshiba.4
@@ -64,6 +64,12 @@ CRT
.It Li 4
TV-Out
.El
+.Pp
+Only some systems (i.e., the Libretto L5) support video switching via
+this hardware-specific driver.
+Use the
+.Xr acpi_video 4
+driver for generic video output support.
.It Va hw.acpi.toshiba.lcd_brightness
Makes the LCD backlight brighter or dimmer (higher values are brighter).
.It Va hw.acpi.toshiba.lcd_backlight
@@ -91,6 +97,7 @@ prompt or in
.Xr loader.conf 5 .
.Sh SEE ALSO
.Xr acpi 4 ,
+.Xr acpi_video 4 ,
.Xr loader.conf 5 ,
.Xr sysctl.conf 5 ,
.Xr sysctl 8
diff --git a/sys/dev/acpi_support/acpi_toshiba.c b/sys/dev/acpi_support/acpi_toshiba.c
index ad17aad..4f8eb46 100644
--- a/sys/dev/acpi_support/acpi_toshiba.c
+++ b/sys/dev/acpi_support/acpi_toshiba.c
@@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$");
#define METHOD_HCI "GHCI"
#define METHOD_HCI_ENABLE "ENAB"
+#define METHOD_VIDEO "DSSX"
/* Operations */
#define HCI_SET 0xFF00
@@ -120,6 +121,7 @@ __FBSDID("$FreeBSD$");
struct acpi_toshiba_softc {
device_t dev;
ACPI_HANDLE handle;
+ ACPI_HANDLE video_handle;
struct sysctl_ctx_list sysctl_ctx;
struct sysctl_oid *sysctl_tree;
};
@@ -137,9 +139,12 @@ static hci_fn_t hci_lcd_brightness;
static hci_fn_t hci_lcd_backlight;
static hci_fn_t hci_cpu_speed;
static int hci_call(ACPI_HANDLE h, int op, int function, UINT32 *arg);
-static void hci_key_action(ACPI_HANDLE h, UINT32 key);
+static void hci_key_action(struct acpi_toshiba_softc *sc, ACPI_HANDLE h,
+ UINT32 key);
static void acpi_toshiba_notify(ACPI_HANDLE h, UINT32 notify,
- void *context);
+ void *context);
+static int acpi_toshiba_video_probe(device_t dev);
+static int acpi_toshiba_video_attach(device_t dev);
/* Table of sysctl names and HCI functions to call. */
static struct {
@@ -171,9 +176,27 @@ static driver_t acpi_toshiba_driver = {
static devclass_t acpi_toshiba_devclass;
DRIVER_MODULE(acpi_toshiba, acpi, acpi_toshiba_driver, acpi_toshiba_devclass,
- 0, 0);
+ 0, 0);
MODULE_DEPEND(acpi_toshiba, acpi, 1, 1, 1);
+static device_method_t acpi_toshiba_video_methods[] = {
+ DEVMETHOD(device_probe, acpi_toshiba_video_probe),
+ DEVMETHOD(device_attach, acpi_toshiba_video_attach),
+
+ {0, 0}
+};
+
+static driver_t acpi_toshiba_video_driver = {
+ "acpi_toshiba_video",
+ acpi_toshiba_video_methods,
+ 0,
+};
+
+static devclass_t acpi_toshiba_video_devclass;
+DRIVER_MODULE(acpi_toshiba_video, acpi, acpi_toshiba_video_driver,
+ acpi_toshiba_video_devclass, 0, 0);
+MODULE_DEPEND(acpi_toshiba_video, acpi, 1, 1, 1);
+
static int enable_fn_keys = 1;
TUNABLE_INT("hw.acpi.toshiba.enable_fn_keys", &enable_fn_keys);
@@ -306,15 +329,25 @@ static int
hci_video_output(ACPI_HANDLE h, int op, UINT32 *video_output)
{
int ret;
+ ACPI_STATUS status;
if (op == HCI_SET) {
if (*video_output < 1 || *video_output > 7)
return (EINVAL);
+ if (h == NULL)
+ return (ENXIO);
*video_output |= HCI_VIDEO_OUTPUT_FLAG;
+ status = acpi_SetInteger(h, "DSSX", *video_output);
+ if (ACPI_SUCCESS(status))
+ ret = 0;
+ else
+ ret = ENXIO;
+ } else {
+ ret = hci_call(h, op, HCI_REG_VIDEO_OUTPUT, video_output);
+ if (ret == 0)
+ *video_output &= 0xff;
}
- ret = hci_call(h, op, HCI_REG_VIDEO_OUTPUT, video_output);
- if (ret == 0 && op == HCI_GET)
- *video_output &= 0xff;
+
return (ret);
}
@@ -419,7 +452,7 @@ end:
* functionality by reading the keystrokes we send to devd(8).
*/
static void
-hci_key_action(ACPI_HANDLE h, UINT32 key)
+hci_key_action(struct acpi_toshiba_softc *sc, ACPI_HANDLE h, UINT32 key)
{
UINT32 arg;
@@ -444,7 +477,7 @@ hci_key_action(ACPI_HANDLE h, UINT32 key)
/* Cycle through video outputs. */
hci_video_output(h, HCI_GET, &arg);
arg = (arg + 1) % 7;
- hci_video_output(h, HCI_SET, &arg);
+ hci_video_output(sc->video_handle, HCI_SET, &arg);
break;
case FN_F8_RELEASE:
/* Toggle LCD backlight. */
@@ -471,10 +504,45 @@ acpi_toshiba_notify(ACPI_HANDLE h, UINT32 notify, void *context)
if (notify == 0x80) {
while (hci_call(h, HCI_GET, HCI_REG_SYSTEM_EVENT, &key) == 0) {
- hci_key_action(h, key);
+ hci_key_action(sc, h, key);
acpi_UserNotify("TOSHIBA", h, (uint8_t)key);
}
- } else {
+ } else
device_printf(sc->dev, "unknown notify: 0x%x\n", notify);
+}
+
+/*
+ * Toshiba video pseudo-device to provide the DSSX method.
+ *
+ * HID Model
+ * -------------------------------------
+ * TOS6201 Libretto L Series
+ */
+static int
+acpi_toshiba_video_probe(device_t dev)
+{
+ int ret = ENXIO;
+
+ if (!acpi_disabled("toshiba") &&
+ acpi_get_type(dev) == ACPI_TYPE_DEVICE &&
+ device_get_unit(dev) == 0 &&
+ acpi_MatchHid(dev, "TOS6201")) {
+ device_quiet(dev);
+ device_set_desc(dev, "Toshiba Video");
+ ret = 0;
}
+
+ return (ret);
+}
+
+static int
+acpi_toshiba_video_attach(device_t dev)
+{
+ struct acpi_toshiba_softc *sc;
+
+ sc = devclass_get_softc(acpi_toshiba_devclass, 0);
+ if (sc == NULL)
+ return (ENXIO);
+ sc->video_handle = acpi_get_handle(dev);
+ return (0);
}
diff --git a/sys/i386/acpica/acpi_toshiba.c b/sys/i386/acpica/acpi_toshiba.c
index ad17aad..4f8eb46 100644
--- a/sys/i386/acpica/acpi_toshiba.c
+++ b/sys/i386/acpica/acpi_toshiba.c
@@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$");
#define METHOD_HCI "GHCI"
#define METHOD_HCI_ENABLE "ENAB"
+#define METHOD_VIDEO "DSSX"
/* Operations */
#define HCI_SET 0xFF00
@@ -120,6 +121,7 @@ __FBSDID("$FreeBSD$");
struct acpi_toshiba_softc {
device_t dev;
ACPI_HANDLE handle;
+ ACPI_HANDLE video_handle;
struct sysctl_ctx_list sysctl_ctx;
struct sysctl_oid *sysctl_tree;
};
@@ -137,9 +139,12 @@ static hci_fn_t hci_lcd_brightness;
static hci_fn_t hci_lcd_backlight;
static hci_fn_t hci_cpu_speed;
static int hci_call(ACPI_HANDLE h, int op, int function, UINT32 *arg);
-static void hci_key_action(ACPI_HANDLE h, UINT32 key);
+static void hci_key_action(struct acpi_toshiba_softc *sc, ACPI_HANDLE h,
+ UINT32 key);
static void acpi_toshiba_notify(ACPI_HANDLE h, UINT32 notify,
- void *context);
+ void *context);
+static int acpi_toshiba_video_probe(device_t dev);
+static int acpi_toshiba_video_attach(device_t dev);
/* Table of sysctl names and HCI functions to call. */
static struct {
@@ -171,9 +176,27 @@ static driver_t acpi_toshiba_driver = {
static devclass_t acpi_toshiba_devclass;
DRIVER_MODULE(acpi_toshiba, acpi, acpi_toshiba_driver, acpi_toshiba_devclass,
- 0, 0);
+ 0, 0);
MODULE_DEPEND(acpi_toshiba, acpi, 1, 1, 1);
+static device_method_t acpi_toshiba_video_methods[] = {
+ DEVMETHOD(device_probe, acpi_toshiba_video_probe),
+ DEVMETHOD(device_attach, acpi_toshiba_video_attach),
+
+ {0, 0}
+};
+
+static driver_t acpi_toshiba_video_driver = {
+ "acpi_toshiba_video",
+ acpi_toshiba_video_methods,
+ 0,
+};
+
+static devclass_t acpi_toshiba_video_devclass;
+DRIVER_MODULE(acpi_toshiba_video, acpi, acpi_toshiba_video_driver,
+ acpi_toshiba_video_devclass, 0, 0);
+MODULE_DEPEND(acpi_toshiba_video, acpi, 1, 1, 1);
+
static int enable_fn_keys = 1;
TUNABLE_INT("hw.acpi.toshiba.enable_fn_keys", &enable_fn_keys);
@@ -306,15 +329,25 @@ static int
hci_video_output(ACPI_HANDLE h, int op, UINT32 *video_output)
{
int ret;
+ ACPI_STATUS status;
if (op == HCI_SET) {
if (*video_output < 1 || *video_output > 7)
return (EINVAL);
+ if (h == NULL)
+ return (ENXIO);
*video_output |= HCI_VIDEO_OUTPUT_FLAG;
+ status = acpi_SetInteger(h, "DSSX", *video_output);
+ if (ACPI_SUCCESS(status))
+ ret = 0;
+ else
+ ret = ENXIO;
+ } else {
+ ret = hci_call(h, op, HCI_REG_VIDEO_OUTPUT, video_output);
+ if (ret == 0)
+ *video_output &= 0xff;
}
- ret = hci_call(h, op, HCI_REG_VIDEO_OUTPUT, video_output);
- if (ret == 0 && op == HCI_GET)
- *video_output &= 0xff;
+
return (ret);
}
@@ -419,7 +452,7 @@ end:
* functionality by reading the keystrokes we send to devd(8).
*/
static void
-hci_key_action(ACPI_HANDLE h, UINT32 key)
+hci_key_action(struct acpi_toshiba_softc *sc, ACPI_HANDLE h, UINT32 key)
{
UINT32 arg;
@@ -444,7 +477,7 @@ hci_key_action(ACPI_HANDLE h, UINT32 key)
/* Cycle through video outputs. */
hci_video_output(h, HCI_GET, &arg);
arg = (arg + 1) % 7;
- hci_video_output(h, HCI_SET, &arg);
+ hci_video_output(sc->video_handle, HCI_SET, &arg);
break;
case FN_F8_RELEASE:
/* Toggle LCD backlight. */
@@ -471,10 +504,45 @@ acpi_toshiba_notify(ACPI_HANDLE h, UINT32 notify, void *context)
if (notify == 0x80) {
while (hci_call(h, HCI_GET, HCI_REG_SYSTEM_EVENT, &key) == 0) {
- hci_key_action(h, key);
+ hci_key_action(sc, h, key);
acpi_UserNotify("TOSHIBA", h, (uint8_t)key);
}
- } else {
+ } else
device_printf(sc->dev, "unknown notify: 0x%x\n", notify);
+}
+
+/*
+ * Toshiba video pseudo-device to provide the DSSX method.
+ *
+ * HID Model
+ * -------------------------------------
+ * TOS6201 Libretto L Series
+ */
+static int
+acpi_toshiba_video_probe(device_t dev)
+{
+ int ret = ENXIO;
+
+ if (!acpi_disabled("toshiba") &&
+ acpi_get_type(dev) == ACPI_TYPE_DEVICE &&
+ device_get_unit(dev) == 0 &&
+ acpi_MatchHid(dev, "TOS6201")) {
+ device_quiet(dev);
+ device_set_desc(dev, "Toshiba Video");
+ ret = 0;
}
+
+ return (ret);
+}
+
+static int
+acpi_toshiba_video_attach(device_t dev)
+{
+ struct acpi_toshiba_softc *sc;
+
+ sc = devclass_get_softc(acpi_toshiba_devclass, 0);
+ if (sc == NULL)
+ return (ENXIO);
+ sc->video_handle = acpi_get_handle(dev);
+ return (0);
}
OpenPOWER on IntegriCloud