Subject: port-i386/32276: Brightness control not working on Sony Vaio VGN-BX197XP
To: None <port-i386-maintainer@netbsd.org, gnats-admin@netbsd.org,>
From: None <sami.kantoluoto@embedtronics.fi>
List: netbsd-bugs
Date: 12/10/2005 23:55:00
>Number: 32276
>Category: port-i386
>Synopsis: Brightness control not working on Sony Vaio VGN-BX197XP
>Confidential: no
>Severity: critical
>Priority: high
>Responsible: port-i386-maintainer
>State: open
>Class: support
>Submitter-Id: net
>Arrival-Date: Sat Dec 10 23:55:00 +0000 2005
>Originator: Sami Kantoluoto
>Release: NetBSD 3.99.13
>Organization:
Embedtronics Oy
>Environment:
System: NetBSD gondor 3.99.13 NetBSD 3.99.13 (GONDOR) #13: Sun Dec 11 00:52:58 EET 2005 root@gondor:/s/nb/current/src/sys/arch/i386/compile/GONDOR i386
Architecture: i386
Machine: i386
>Description:
Can't control the brightness of the LCD of Sony Vaio VGN-BX197XP.
This is quite a problem because the initial brightness is so bright
you really cannot watch it without getting a headache.
>How-To-Repeat:
>Fix:
Here's a quick dirty hack to i386/acpi/spic_acpi.c that adds
'machdep.spic.*' 'sysctl entries making it possible to tweak
values. Remember to add 'spic* at acpi?' to configuration file.
After installing the patch and getting new kernel running you
can control the brightness with 'sysctl -w machdep.spic.BRT=<x>'
(or adding "machdep.spic.BRT=<x>" to /etc/sysctl.conf), where <x>
seems to be from (darkest) 0-8 (brightest), except that 2 does
nothing (?).
Brigthtness control ACPI methods/functions (whatever they're called)
were figured out from http://popies.net/sonypi/2.6-sony_acpi4.patch
NOTE: Use at your own risk!
Index: arch/i386/acpi/spic_acpi.c
===================================================================
RCS file: /netbsd/cvs/src/sys/arch/i386/acpi/spic_acpi.c,v
retrieving revision 1.12
diff -r1.12 spic_acpi.c
47a48
> #include <sys/sysctl.h>
64a66
> "SNY5001", /* XXX */
74a77,79
> #ifdef ACPI_DEBUG
> /*#define SPIC_ACPI_DEBUG*/
> #endif
86a92,208
> ACPI_HANDLE spic_acpi_hnd; /* XXX */
> ACPI_STATUS
> acpi_eval_set_integer(ACPI_HANDLE, const char *, ACPI_INTEGER, ACPI_INTEGER *);
>
> static int spic_sysctl_helper(SYSCTLFN_ARGS)
> {
> struct sysctlnode node;
> ACPI_INTEGER acpi_val;
> ACPI_STATUS rv;
> int val, old_val, error;
> char buf[SYSCTL_NAMELEN+1];
>
> snprintf(buf, sizeof(buf), "G%s", rnode->sysctl_name);
>
> rv = acpi_eval_integer(spic_acpi_hnd, buf, &acpi_val);
> if (ACPI_FAILURE(rv)) {
> printf("%s: couldn't read '%s'\n", __FUNCTION__, buf);
> return EIO;
> }
> val = old_val = acpi_val;
>
> node = *rnode;
> node.sysctl_data = &val;
>
> error = sysctl_lookup(SYSCTLFN_CALL(&node));
> if (error || newp == NULL)
> return error;
>
> if (val != old_val) {
> snprintf(buf, sizeof(buf), "S%s", rnode->sysctl_name);
> acpi_val = val;
> rv = acpi_eval_set_integer(spic_acpi_hnd, buf, acpi_val, NULL);
> if (ACPI_FAILURE(rv)) {
> printf("%s: couldn't write '%s' to %d\n",
> __FUNCTION__, buf, val);
> return EIO;
> }
> }
>
> return 0;
> }
>
> static ACPI_STATUS spic_walk_cb(ACPI_HANDLE hnd, UINT32 v, void *context, void **status)
> {
> #ifdef SPIC_ACPI_DEBUG
> struct spic_acpi_softc *sc = (void*)context;
> #endif
> const struct sysctlnode *node, *ssnode, *sssnode;
> const char *name = acpi_name(hnd), *ptr;
> int rv;
>
> if ((ptr = strrchr(name, '.')) == NULL)
> goto done;
>
> ptr++;
> #ifdef SPIC_ACPI_DEBUG
> printf("%s: found method: %s\n", sc->sc_spic.sc_dev.dv_xname, ptr);
> #endif
>
> if ((*ptr != 'G') && (*ptr != 'S'))
> goto done;
> #ifdef SPIC_ACPI_DEBUG
> printf("%s: adding machdep.%s.%s\n", sc->sc_spic.sc_dev.dv_xname,
> sc->sc_spic.sc_dev.dv_xname, ptr+1);
> #endif
> if ((rv = sysctl_createv(NULL, 0, NULL, &node,
> CTLFLAG_PERMANENT, CTLTYPE_NODE, "machdep", NULL,
> NULL, 0, NULL, 0, CTL_MACHDEP, CTL_EOL)) != 0)
> goto err;
>
> if ((rv = sysctl_createv(NULL, 0, &node, &ssnode,
> 0, CTLTYPE_NODE, "spic", NULL,
> NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL)) != 0)
> goto err;
>
> if ((rv = sysctl_createv(NULL, 0, &ssnode, &sssnode,
> CTLFLAG_READWRITE, CTLTYPE_INT, ptr + 1, NULL,
> spic_sysctl_helper, 0, NULL, 0, CTL_CREATE,
> CTL_EOL)) != 0)
> goto err;
>
> done:
> return AE_OK;
> err:
> aprint_normal("%s: sysctl_createv failed (rv = %d)\n", __func__, rv);
> return AE_OK;
> }
>
> ACPI_STATUS
> acpi_eval_set_integer(ACPI_HANDLE handle, const char *path, ACPI_INTEGER val, ACPI_INTEGER *valp)
> {
> ACPI_STATUS rv;
> ACPI_BUFFER buf;
> ACPI_OBJECT param, ret_val;
> ACPI_OBJECT_LIST params;
>
> if (handle == NULL)
> handle = ACPI_ROOT_OBJECT;
>
> params.Count = 1;
> params.Pointer = ¶m;
>
> param.Type = ACPI_TYPE_INTEGER;
> param.Integer.Value = val;
>
> buf.Pointer = &ret_val;
> buf.Length = sizeof(ret_val);
>
> rv = AcpiEvaluateObjectTyped(handle, path, ¶ms, &buf, ACPI_TYPE_INTEGER);
>
> if (ACPI_SUCCESS(rv) && valp) {
> *valp = ret_val.Integer.Value;
> }
>
> return rv;
> }
>
100a223,235
>
> /* install sysctl nodes.. */
> /* XXX protection of spic_acpi_hnd??? XXX */
> if (!spic_acpi_hnd) {
> printf("%s: installing sysctl hooks...\n",
> sc->sc_spic.sc_dev.dv_xname);
> rv = AcpiWalkNamespace(ACPI_TYPE_METHOD, sc->sc_node->ad_handle, 1,
> spic_walk_cb, sc, NULL);
> if (ACPI_FAILURE(rv))
> goto out;
>
> spic_acpi_hnd = sc->sc_node->ad_handle;
> }