[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: backlight control via openfirmware



>>	macppc-020615.tar.gzを拝見しましたが、バックライト制御については
>>	旧機種の場合のif文が多いくらいであとは大体同じことをしていますね。
>はい。set-contrast を使うというアイデアは OpenBSD から盗んで
>きましたから。ただ ioctl を直接呼ぶんじゃなくて hpcmips みたい
>にやるべきなんだと思います。

	このくらいで許して貰えますか? abtn.cからofb.cの中の関数を呼んでいる
	のだけ反則です。

itojun


Index: abtn.c
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/macppc/dev/abtn.c,v
retrieving revision 1.3
diff -u -r1.3 abtn.c
--- abtn.c	2001/06/08 00:32:01	1.3
+++ abtn.c	2002/06/18 10:39:40
@@ -31,11 +31,12 @@
 #include <sys/systm.h>
 
 #include <macppc/dev/adbvar.h>
-#include <macppc/dev/pm_direct.h>
 
-#define NVRAM_BRIGHTNESS 0x140e
 #define ABTN_HANDLER_ID 31
+#define STEP_BRIGHTNESS                8
 
+extern int ofb_setbrightness_console __P((int));
+
 struct abtn_softc {
 	struct device sc_dev;
 
@@ -43,7 +44,6 @@
 	int adbaddr;		/* current ADB address */
 	int handler_id;
 
-	int brightness;		/* backlight brightness */
 	int volume;		/* speaker volume (not yet) */
 };
 
@@ -78,15 +78,9 @@
 	struct abtn_softc *sc = (struct abtn_softc *)self;
 	struct adb_attach_args *aa = aux;
 	ADBSetInfoBlock adbinfo;
-	int bright;
 
 	printf("brightness/volume button\n");
 
-	bright = pm_read_nvram(NVRAM_BRIGHTNESS);
-	if (bright != 0)
-		pm_set_brightness(bright);
-	sc->brightness = bright;
-
 	sc->origaddr = aa->origaddr;
 	sc->adbaddr = aa->adbaddr;
 	sc->handler_id = aa->handler_id;
@@ -102,26 +96,17 @@
 	caddr_t buffer, data;
 	int adb_command;
 {
-	struct abtn_softc *sc = (struct abtn_softc *)data;
 	u_int cmd;
 
 	cmd = buffer[1];
 
 	switch (cmd) {
 	case 0x0a:
-		sc->brightness -= 8;
-		if (sc->brightness < 8)
-			sc->brightness = 8;
-		pm_set_brightness(sc->brightness);
-		pm_write_nvram(NVRAM_BRIGHTNESS, sc->brightness);
+		ofb_setbrightness_console(STEP_BRIGHTNESS);
 		break;
 
 	case 0x09:
-		sc->brightness += 8;
-		if (sc->brightness > 0x78)
-			sc->brightness = 0x78;
-		pm_set_brightness(sc->brightness);
-		pm_write_nvram(NVRAM_BRIGHTNESS, sc->brightness);
+		ofb_setbrightness_console(-STEP_BRIGHTNESS);
 		break;
 	}
 }
Index: ofb.c
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/macppc/dev/ofb.c,v
retrieving revision 1.26
diff -u -r1.26 ofb.c
--- ofb.c	2002/03/17 19:40:44	1.26
+++ ofb.c	2002/06/18 10:39:41
@@ -55,6 +55,7 @@
 #include <machine/grfioctl.h>
 
 #include <macppc/dev/ofbvar.h>
+#include <macppc/dev/pm_direct.h>
 
 #if OFB_ENABLE_CACHE
 int ofb_enable_cache = 1;
@@ -62,6 +63,8 @@
 int ofb_enable_cache = 0;
 #endif
 
+#define NVRAM_BRIGHTNESS 0x140e
+
 int	ofbmatch __P((struct device *, struct cfdata *, void *));
 void	ofbattach __P((struct device *, struct device *, void *));
 int	ofbprint __P((void *, const char *));
@@ -97,6 +100,8 @@
 static int ofb_show_screen __P((void *, void *, int,
 				void (*) (void *, int, int), void *));
 static int copy_rom_font __P((void));
+static int ofb_setbrightness __P((struct ofb_devconfig *, int));
+static int ofb_burn __P((struct ofb_devconfig *, int));
 
 struct wsdisplay_accessops ofb_accessops = {
 	ofb_ioctl,
@@ -213,6 +218,7 @@
 {
 	struct rasops_info *ri = &dc->dc_ri;
 	int32_t addr, width, height, linebytes, depth;
+	int32_t backlight_control[2];
 
 	dc->dc_node = node;
 	if (dc->dc_ih == 0) {
@@ -235,6 +241,11 @@
 		depth = 8;				/* XXX */
 	if (OF_getprop(node, "address", &addr, 4) != 4)
 		OF_interpret("frame-buffer-adr", 1, &addr);
+	if (OF_getprop(node, "backlight-control", backlight_control,
+	    sizeof(backlight_control)) > 0)
+		dc->dc_flags |= DC_BACKLIGHT_AVAIL;
+	if (OF_finddevice("/uni-n") == -1)
+		dc->dc_flags |= DC_BRIGHTNESS_PMU;
 
 	if (width == -1 || height == -1 || addr == 0 || addr == -1)
 		return;
@@ -290,6 +301,14 @@
 	ofb_stdscreen.ncols = ri->ri_cols;
 	ofb_stdscreen.textops = &ri->ri_ops;
 	ofb_stdscreen.capabilities = ri->ri_caps;
+
+	if ((dc->dc_flags & DC_BACKLIGHT_AVAIL) != 0) {
+		if ((dc->dc_flags & DC_BRIGHTNESS_PMU) == 0)
+			(void)ofb_setbrightness(dc, 0xff);	/*XXX*/
+		else
+			(void)ofb_setbrightness(dc,
+			    pm_read_nvram(NVRAM_BRIGHTNESS));
+	}
 }
 
 int
@@ -320,6 +339,7 @@
 	struct ofb_devconfig *dc = sc->sc_dc;
 	struct wsdisplay_fbinfo *wdf;
 	struct grfinfo *gm;
+	struct wsdisplay_param *dp;
 
 	switch (cmd) {
 	case WSDISPLAYIO_GTYPE:
@@ -347,6 +367,17 @@
 		gm->gd_fbaddr = (caddr_t)dc->dc_paddr;
 		gm->gd_fbrowbytes = dc->dc_ri.ri_stride;
 		return 0;
+
+	case WSDISPLAYIO_SETPARAM:
+		dp = (struct wsdisplay_param *)data;
+		switch (dp->param) {
+		case WSDISPLAYIO_PARAM_BRIGHTNESS:
+			return ofb_setbrightness(dc, dp->curval);
+		case WSDISPLAYIO_PARAM_BACKLIGHT:
+			return ofb_burn(dc, dp->curval ? WSDISPLAYIO_VIDEO_ON :
+			    WSDISPLAYIO_VIDEO_OFF);
+		}
+		break;
 	}
 	return EPASSTHROUGH;
 }
@@ -561,5 +592,74 @@
 		r++, g++, b++, index++;
 	}
 
+       return 0;
+}
+
+int
+ofb_setbrightness_console(step)
+       int step;
+{
+
+       return ofb_setbrightness(&ofb_console_dc,
+           ofb_console_dc.dc_brightness + step);
+}
+
+static int
+ofb_setbrightness(dc, brightness)
+       struct ofb_devconfig *dc;
+       int brightness;
+{
+
+	if ((dc->dc_flags & DC_BRIGHTNESS_PMU) == 0) {
+		/*
+		 * For some reason, setting the brightness under 0x29 from OF
+		 * switches the backlight off, and it won't be switched on
+		 * again until you set the brightness above 0x33.  All hail
+		 * hysteresis! -- miod
+		 */
+		if (brightness < 0x30)
+			brightness = 0x30;
+		else if (brightness > 0xf0)
+			brightness = 0xf0;
+	} else {
+		if (brightness < 8)
+			brightness = 8;
+		else if (brightness > 0x78)
+			brightness = 0x78;
+	}
+
+	dc->dc_brightness = brightness;
+
+	if ((dc->dc_flags & DC_BRIGHTNESS_PMU) == 0) {
+		/*
+		 * The OF method is called "set-contrast" but affects
+		 * brightness. Don't ask.
+		 */
+		OF_call_method_1("set-contrast", dc->dc_node, 1,
+		    dc->dc_brightness);
+	} else {
+		pm_set_brightness(dc->dc_brightness);
+		pm_write_nvram(NVRAM_BRIGHTNESS, dc->dc_brightness);
+	}
+
+	return 0;
+}
+
+static int
+ofb_burn(dc, on)
+       struct ofb_devconfig *dc;
+       int on;
+{
+
+	if ((dc->dc_flags & DC_BACKLIGHT_AVAIL) == 0)
+		return EOPNOTSUPP;
+
+	if (dc->dc_backlight_on != on) {
+		if (on == WSDISPLAYIO_VIDEO_ON)
+			OF_call_method_1("backlight-on", dc->dc_ih, 0);
+		else
+			OF_call_method_1("backlight-off", dc->dc_ih, 0);
+		dc->dc_backlight_on = on;
+	}
 	return 0;
 }
Index: ofbvar.h
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/macppc/dev/ofbvar.h,v
retrieving revision 1.5
diff -u -r1.5 ofbvar.h
--- ofbvar.h	2001/06/10 13:56:13	1.5
+++ ofbvar.h	2002/06/18 10:39:41
@@ -32,6 +32,12 @@
 	int	dc_node;		/* phandle of this node */
 	int	dc_ih;			/* ihandle of this node */
 	struct rasops_info dc_ri;
+
+	int dc_flags;
+#define DC_BACKLIGHT_AVAIL	0x01
+#define DC_BRIGHTNESS_PMU	0x02
+	int dc_brightness;
+	int dc_backlight_on;
 };
 
 struct ofb_softc {
@@ -44,3 +50,5 @@
 	u_char sc_cmap_green[256];
 	u_char sc_cmap_blue[256];
 };
+
+int ofb_setbrightness_console __P((int));