Subject: apm fix for jornada 720
To: None <port-hpcarm@NetBSD.org>
From: Peter Postma <peter@pointless.nl>
List: port-hpcarm
Date: 09/18/2005 15:37:59
--J2SCkAp4GZ/dPZZf
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Hi all,

I noticed that this message[1] indicates that we're interpreting battery
values wrong. I've also found another document[2] which states that
pmdata[2] contains the combined data bits for both batterys and we're
currently ignoring this.

Bit 0 & 1 = bit 8 & 9 for the main battery and bit 2 & 3 = bit 8 & 9
for the backup battery. I've checked this and it seems to be true.

I also noticed that when the main battery is removed, bit 0 & 1 will both
set high. When the backup battery is removed, bit 2 & 3 will both set low.

The main battery data is usually between 425 and 680 on my j720 but it only
peaks around 680 when AC is online.

The attached patch should fix the battery status and it also adds AC and
battery charge status. It all works for me but I'd appreciate it if someone
can also verify/review this. I'll commit it if it turns out to be a real
improvement.

[1] http://mail-index.netbsd.org/port-hpcarm/2005/01/06/0000.html
[2] http://www.handhelds.org/download/projects/jornada/720/jornada720.txt

-- 
Peter Postma

--J2SCkAp4GZ/dPZZf
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="apm.diff"

Index: j720ssp.c
===================================================================
RCS file: /cvsroot/src/sys/arch/hpcarm/dev/j720ssp.c,v
retrieving revision 1.24
diff -u -c -r1.24 j720ssp.c
***************
*** 913,947 ****
  		BIT_INVERT(pmdata[i]);
  	}
  
  	bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PSR, 0x2000000);
  
! 	bzero(api, sizeof(struct apm_power_info));
! 	api->ac_state = APM_AC_UNKNOWN;
  
! 	/*
! 	 * pmdata[0] is the main battery level
! 	 * pmdata[1] is the backup battery level
! 	 * pmdata[2] tells which battery is present
! 	 */
! 	switch(pmdata[2]) {
! 	case 14: /* backup battery present */
! 	case 2:  /* backup battery absent */
! 		api->battery_state = APM_BATT_CHARGING;
! 		api->minutes_left = (pmdata[0] * 840) / 170;
! 		api->battery_life = (pmdata[0] * 100) / 170;
! 		api->nbattery = 1;
! 		break;
! 	case 15: /* backup battery present */
! 	case 3:  /* backup battery absent */
  		api->battery_state = APM_BATT_ABSENT;
  		api->battery_life = 0;
  		api->nbattery = 0;
! 		break;
! 	default:
! 		api->battery_state = APM_BATT_UNKNOWN;
! 		break;
  	}
  
  	return 0;
  
  out:
--- 910,952 ----
  		BIT_INVERT(pmdata[i]);
  	}
  
+ 	data = bus_space_read_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PLR);
+ 
  	bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PSR, 0x2000000);
  
! 	memset(api, 0, sizeof(struct apm_power_info));
  
! 	pmdata[0] |= (pmdata[2] & 3) << 8;	/* Main battery. */
! 	pmdata[1] |= (pmdata[2] & 12) << 6;	/* Backup battery. */
! 
! 	/* XXX */
! 	printf("pmdata[0]=%d pmdata[1]=%d pmdata[2]=%d\n",
! 	    pmdata[0], pmdata[1], pmdata[2]);
! 
! 	/* If bit 0 and 1 are both set, the main battery is absent. */
! 	if ((pmdata[2] & 3) == 3) {
  		api->battery_state = APM_BATT_ABSENT;
  		api->battery_life = 0;
  		api->nbattery = 0;
! 	} else {
! 		/* Main battery data seems to be between 425 and 680. */
! 		api->battery_life = ((pmdata[0] - 425) * 100) / 255;
! 		api->minutes_left = (api->battery_life * 54) / 10;
! 		api->nbattery = 1;
! 
! 		if (data & (1 << 26))
! 			api->battery_state = (api->battery_life > 50) ?
! 			    APM_BATT_HIGH : (api->battery_life > 15) ?
! 			    APM_BATT_LOW : APM_BATT_CRITICAL;
! 		else
! 			api->battery_state = APM_BATT_CHARGING;
  	}
  
+ 	if (data & (1 << 4))
+ 		api->ac_state = APM_AC_OFF;
+ 	else
+ 		api->ac_state = APM_AC_ON;
+ 
  	return 0;
  
  out:

--J2SCkAp4GZ/dPZZf--