Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/hpcsh/dev Support HP 620LX. On/off and brightness ...
details: https://anonhg.NetBSD.org/src/rev/a79ead8713e9
branches: trunk
changeset: 583382:a79ead8713e9
user: uwe <uwe%NetBSD.org@localhost>
date: Wed Aug 03 22:25:17 2005 +0000
description:
Support HP 620LX. On/off and brightness are the same as in 680.
Contrast control is different but similar enough, so refactor the code
to support both. Tested by Christer Andersson.
XXX: platid_mask_MACH_HP_LX also matches 360LX. It's not confirmed
whether touch panel in 360LX is connected in the same way. We may
need to regroup platid masks.
diffstat:
sys/arch/hpcsh/dev/j6x0lcd.c | 228 ++++++++++++++++++++++++++++--------------
1 files changed, 150 insertions(+), 78 deletions(-)
diffs (truncated from 352 to 300 lines):
diff -r 324c0c670015 -r a79ead8713e9 sys/arch/hpcsh/dev/j6x0lcd.c
--- a/sys/arch/hpcsh/dev/j6x0lcd.c Wed Aug 03 21:18:07 2005 +0000
+++ b/sys/arch/hpcsh/dev/j6x0lcd.c Wed Aug 03 22:25:17 2005 +0000
@@ -1,7 +1,7 @@
-/* $NetBSD: j6x0lcd.c,v 1.6 2005/02/28 16:57:56 uwe Exp $ */
+/* $NetBSD: j6x0lcd.c,v 1.7 2005/08/03 22:25:17 uwe Exp $ */
/*
- * Copyright (c) 2004 Valeriy E. Ushakov
+ * Copyright (c) 2004, 2005 Valeriy E. Ushakov
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: j6x0lcd.c,v 1.6 2005/02/28 16:57:56 uwe Exp $");
+__KERNEL_RCSID(0, "$NetBSD: j6x0lcd.c,v 1.7 2005/08/03 22:25:17 uwe Exp $");
#include <sys/param.h>
#include <sys/kernel.h>
@@ -48,16 +48,18 @@
#include <hpcsh/dev/hd64461/hd64461reg.h>
#include <hpcsh/dev/hd64461/hd64461gpioreg.h>
+#define arraysize(ary) (sizeof(ary) / sizeof(ary[0]))
+
/*
* LCD power: controlled by pin 0 in HD64461 GPIO port B.
* 0 - power on
* 1 - power off
*/
-#define HD64461_GPBDR_J6X0LCD_OFF 0x01
+#define HD64461_GPBDR_J6X0_LCD_OFF 0x01
-#define HD64461_GPBCR_J6X0LCD_OFF_MASK 0xfffc
-#define HD64461_GPBCR_J6X0LCD_OFF_BITS 0x0001
+#define HD64461_GPBCR_J6X0_LCD_OFF_MASK 0xfffc
+#define HD64461_GPBCR_J6X0_LCD_OFF_BITS 0x0001
/*
@@ -82,55 +84,60 @@
/*
- * LCD contrast: controlled by pins 6,5,4,3 HD64461 GPIO port B.
- * 6th is the least significant bit, 3rd is the most significant.
- * The bits are inverted: .1111... = 0, .0111... = 1, etc.
- *
- * We control the contrast value by setting bits in the data register
- * to all ones, and changing the mode of the bits in the control
- * register, keeping "ones" in gpio output mode (1), and switching
- * "zeros" to input mode (3). This is what WinCE also does.
- *
- * Alternative method is to set the mode of all bits to gpio output
- * mode and then change the bits in the data register. This method
- * results in significantly less contrast screen for the same values.
- * E.g., WinCE default contrast value is 11 (in our numbering, 23 in
- * WinCE's) - which is fine in the "tweak the control register"
- * method, but is very blurry in the "tweak the data register" method.
- * Subjectively, 15 in the "tweak control" method looks like 7 in the
- * "tweak data" method.
+ * LCD contrast in 680 is controlled by pins 6..3 of HD64461 GPIO
+ * port B. 6th pin is the least significant bit, 3rd pin is the most
+ * significant. The bits are inverted: 0 = .1111...; 1 = .0111...;
+ * etc. Larger values mean "blacker".
*
- * May be it's possible to control a wider range of contrast by
- * combining the two methods, but values above 7 in the "tweak data"
- * method are so blurry that they are next to unusable in practice.
+ * The contrast value is programmed by setting bits in the data
+ * register to all ones, and changing the mode of the pins in the
+ * control register, setting logical "ones" to GPIO output mode (1),
+ * and switching "zeroes" to input mode (3).
*/
-#define J6X0LCD_CONTRAST_MAX 15
-
-#define HD64461_GPBDR_J6X0LCD_CONTRAST_MASK 0x87
-#define HD64461_GPBDR_J6X0LCD_CONTRAST_BITS 0x78
+#define HD64461_GPBDR_J680_CONTRAST_BITS 0x78 /* set */
+#define HD64461_GPBCR_J680_CONTRAST_MASK 0xc03f
-#if 0
-/* "tweak data" */
-static uint8_t j6x0lcd_contrast_data_bits[] = {
- 0x78, 0x38, 0x58, 0x18, 0x68, 0x28, 0x48, 0x08,
- 0x70, 0x30, 0x50, 0x10, 0x60, 0x20, 0x40, 0x00
-};
-#endif
+static const uint8_t j6x0lcd_contrast680_pins[] = { 6, 5, 4, 3 };
-#define HD64461_GPBCR_J6X0LCD_CONTRAST_MASK 0xc03f
-#define HD64461_GPBCR_J6X0LCD_CONTRAST_BITS 0x1540
-
-/* "tweak control" */
-static uint16_t j6x0lcd_contrast_control_bits[] = {
+static const uint16_t j6x0lcd_contrast680_control_bits[] = {
0x1540, 0x3540, 0x1d40, 0x3d40, 0x1740, 0x3740, 0x1f40, 0x3f40,
0x15c0, 0x35c0, 0x1dc0, 0x3dc0, 0x17c0, 0x37c0, 0x1fc0, 0x3fc0
};
+/*
+ * LCD contrast in 620lx is controlled by pins 7,6,3,4,5 of HD64461
+ * GPIO port B (in the order from the least significant to the most
+ * significant). The bits are inverted: 0 = 11111...; 5 = 01110...;
+ * etc. Larger values mean "whiter".
+ *
+ * The contrast value is programmed by setting bits in the data
+ * register to all zeroes, and changing the mode of the pins in the
+ * control register, setting logical "ones" to GPIO output mode (1),
+ * and switching "zeroes" to input mode (3).
+ */
+#define HD64461_GPBDR_J620LX_CONTRAST_BITS 0xf8 /* clear */
+#define HD64461_GPBCR_J620LX_CONTRAST_MASK 0x003f
+
+static const uint8_t j6x0lcd_contrast620lx_pins[] = { 7, 6, 3, 4, 5 };
+
+static const uint16_t j6x0lcd_contrast620lx_control_bits[] = {
+ 0xffc0, 0x7fc0, 0xdfc0, 0x5fc0, 0xff40, 0x7f40, 0xdf40, 0x5f40,
+ 0xfdc0, 0x7dc0, 0xddc0, 0x5dc0, 0xfd40, 0x7d40, 0xdd40, 0x5d40,
+ 0xf7c0, 0x77c0, 0xd7c0, 0x57c0, 0xf740, 0x7740, 0xd740, 0x5740,
+ 0xf5c0, 0x75c0, 0xd5c0, 0x55c0, 0xf540, 0x7540, 0xd540, 0x5540
+};
+
+
+
struct j6x0lcd_softc {
struct device sc_dev;
int sc_brightness;
int sc_contrast;
+
+ int sc_contrast_max;
+ uint16_t sc_contrast_mask;
+ const uint16_t *sc_contrast_control_bits;
};
static int j6x0lcd_match(struct device *, struct cfdata *, void *);
@@ -143,16 +150,22 @@
static int j6x0lcd_param(void *, int, long, void *);
static int j6x0lcd_power(void *, int, long, void *);
+static int j6x0lcd_contrast_raw(uint16_t, int, const uint8_t *);
+static void j6x0lcd_contrast_set(struct j6x0lcd_softc *, int);
+
+
static int
j6x0lcd_match(struct device *parent, struct cfdata *cfp, void *aux)
{
/*
- * XXX: does platid_mask_MACH_HP_LX matches _JORNADA_6XX too?
- * Is 620 wired similarly?
+ * XXX: platid_mask_MACH_HP_LX also matches 360LX. It's not
+ * confirmed whether touch panel in 360LX is connected this
+ * way. We may need to regroup platid masks.
*/
- if (!platid_match(&platid, &platid_mask_MACH_HP_JORNADA_6XX))
+ if (!platid_match(&platid, &platid_mask_MACH_HP_JORNADA_6XX)
+ && !platid_match(&platid, &platid_mask_MACH_HP_LX))
return (0);
if (strcmp(cfp->cf_name, "j6x0lcd") != 0)
@@ -166,7 +179,6 @@
j6x0lcd_attach(struct device *parent, struct device *self, void *aux)
{
struct j6x0lcd_softc *sc = (struct j6x0lcd_softc *)self;
- int contrast, i;
uint16_t bcr, bdr;
uint8_t dcr, ddr;
@@ -181,36 +193,56 @@
ddr = DAC_(DR0);
sc->sc_brightness = J6X0LCD_DA_TO_BRIGHTNESS(ddr);
-
/*
* Contrast and power are controlled by HD64461 GPIO port B.
*/
bcr = hd64461_reg_read_2(HD64461_GPBCR_REG16);
bdr = hd64461_reg_read_2(HD64461_GPBDR_REG16);
- contrast = 0xf; /* bits are inverted */
- for (i = 0; i < 4; ++i) {
- unsigned int c, v;
- c = (bcr >> ((6 - i) << 1)) & 0x3;
- if (c == 1) /* gpio mode? */
- v = 1;
- else
- v = 0;
- contrast &= ~(v << i);
+ /*
+ * Make sure LCD is turned on.
+ */
+ bcr &= HD64461_GPBCR_J6X0_LCD_OFF_MASK;
+ bcr |= HD64461_GPBCR_J6X0_LCD_OFF_BITS; /* output mode */
+
+ bdr &= ~HD64461_GPBDR_J6X0_LCD_OFF;
+
+ /*
+ * 620LX and 680 have different contrast control.
+ */
+ if (platid_match(&platid, &platid_mask_MACH_HP_JORNADA_6XX)) {
+ bdr |= HD64461_GPBDR_J680_CONTRAST_BITS;
+
+ sc->sc_contrast_mask =
+ HD64461_GPBCR_J680_CONTRAST_MASK;
+ sc->sc_contrast_control_bits =
+ j6x0lcd_contrast680_control_bits;
+ sc->sc_contrast_max =
+ arraysize(j6x0lcd_contrast680_control_bits) - 1;
+
+ sc->sc_contrast = sc->sc_contrast_max
+ - j6x0lcd_contrast_raw(bcr,
+ arraysize(j6x0lcd_contrast680_pins),
+ j6x0lcd_contrast680_pins);
+ } else {
+ bdr &= ~HD64461_GPBDR_J620LX_CONTRAST_BITS;
+
+ sc->sc_contrast_mask =
+ HD64461_GPBCR_J620LX_CONTRAST_MASK;
+ sc->sc_contrast_control_bits =
+ j6x0lcd_contrast620lx_control_bits;
+ sc->sc_contrast_max =
+ arraysize(j6x0lcd_contrast620lx_control_bits) - 1;
+
+ sc->sc_contrast =
+ j6x0lcd_contrast_raw(bcr,
+ arraysize(j6x0lcd_contrast620lx_pins),
+ j6x0lcd_contrast620lx_pins);
}
- sc->sc_contrast = contrast;
-
- bdr &= ~HD64461_GPBDR_J6X0LCD_OFF;
- bdr |= HD64461_GPBDR_J6X0LCD_CONTRAST_BITS;
+ hd64461_reg_write_2(HD64461_GPBCR_REG16, bcr);
hd64461_reg_write_2(HD64461_GPBDR_REG16, bdr);
- bcr &= HD64461_GPBCR_J6X0LCD_OFF_MASK
- & HD64461_GPBCR_J6X0LCD_CONTRAST_MASK;
- bcr |= HD64461_GPBCR_J6X0LCD_OFF_BITS
- | j6x0lcd_contrast_control_bits[contrast];
- hd64461_reg_write_2(HD64461_GPBCR_REG16, bcr);
-
printf(": brightness %d, contrast %d\n",
sc->sc_brightness, sc->sc_contrast);
@@ -245,6 +277,52 @@
}
+/*
+ * Get raw contrast value programmed in GPIO port B control register.
+ * Used only at attach time to get initial contrast.
+ */
+static int
+j6x0lcd_contrast_raw(uint16_t bcr, int width, const uint8_t *pin)
+{
+ int contrast;
+ int bit;
+
+ contrast = 0;
+ for (bit = 0; bit < width; ++bit) {
+ unsigned int c, v;
+
+ c = (bcr >> (pin[bit] << 1)) & 0x3;
+ if (c == 1) /* output mode? */
+ v = 1;
+ else
+ v = 0;
+ contrast |= (v << bit);
+ }
+
+ return contrast;
+}
+
+
+/*
+ * Set contrast by programming GPIO port B control register.
+ * Data register has been initialized at attach time.
+ */
+static void
+j6x0lcd_contrast_set(struct j6x0lcd_softc *sc, int contrast)
+{
+ uint16_t bcr;
+
+ sc->sc_contrast = contrast;
+
+ bcr = hd64461_reg_read_2(HD64461_GPBCR_REG16);
+
+ bcr &= sc->sc_contrast_mask;
+ bcr |= sc->sc_contrast_control_bits[contrast];
+
+ hd64461_reg_write_2(HD64461_GPBCR_REG16, bcr);
+}
Home |
Main Index |
Thread Index |
Old Index