1 /* $NetBSD: j720lcd.c,v 1.3 2006/06/27 14:36:50 peter Exp $ */ 2 3 /*- 4 * Copyright (c) 2006 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by IWAMOTO Toshihiro. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 /* Jornada 720 LCD screen driver. */ 40 41 #include <sys/cdefs.h> 42 __KERNEL_RCSID(0, "$NetBSD: j720lcd.c,v 1.3 2006/06/27 14:36:50 peter Exp $"); 43 44 #include <sys/param.h> 45 #include <sys/systm.h> 46 #include <sys/device.h> 47 #include <sys/kernel.h> 48 49 #include <machine/config_hook.h> 50 #include <machine/platid.h> 51 #include <machine/platid_mask.h> 52 53 #include <arm/sa11x0/sa11x0_var.h> 54 #include <arm/sa11x0/sa11x0_gpioreg.h> 55 #include <arm/sa11x0/sa11x0_ppcreg.h> 56 #include <arm/sa11x0/sa11x0_sspreg.h> 57 58 #include <hpcarm/dev/j720sspvar.h> 59 #include <hpcarm/dev/sed1356var.h> 60 61 #ifdef DEBUG 62 #define DPRINTF(arg) printf arg 63 #else 64 #define DPRINTF(arg) /* nothing */ 65 #endif 66 67 struct j720lcd_softc { 68 struct device sc_dev; 69 70 struct j720ssp_softc *sc_ssp; 71 }; 72 73 static int j720lcd_match(struct device *, struct cfdata *, void *); 74 static void j720lcd_attach(struct device *, struct device *, void *); 75 76 static int j720lcd_param(void *, int, long, void *); 77 int j720lcd_power(void *, int, long, void *); 78 79 CFATTACH_DECL(j720lcd, sizeof(struct j720lcd_softc), 80 j720lcd_match, j720lcd_attach, NULL, NULL); 81 82 83 static int 84 j720lcd_match(struct device *parent, struct cfdata *cf, void *aux) 85 { 86 87 if (!platid_match(&platid, &platid_mask_MACH_HP_JORNADA_7XX)) 88 return 0; 89 if (strcmp(cf->cf_name, "j720lcd") != 0) 90 return 0; 91 92 return 1; 93 } 94 95 static void 96 j720lcd_attach(struct device *parent, struct device *self, void *aux) 97 { 98 struct j720lcd_softc *sc = (struct j720lcd_softc *)self; 99 int brightness, contrast; 100 101 sc->sc_ssp = (struct j720ssp_softc *)parent; 102 103 /* LCD brightness hooks. */ 104 config_hook(CONFIG_HOOK_SET, CONFIG_HOOK_BRIGHTNESS, 105 CONFIG_HOOK_SHARE, j720lcd_param, sc); 106 config_hook(CONFIG_HOOK_GET, CONFIG_HOOK_BRIGHTNESS, 107 CONFIG_HOOK_SHARE, j720lcd_param, sc); 108 config_hook(CONFIG_HOOK_GET, CONFIG_HOOK_BRIGHTNESS_MAX, 109 CONFIG_HOOK_SHARE, j720lcd_param, sc); 110 111 /* LCD contrast hooks. */ 112 config_hook(CONFIG_HOOK_SET, CONFIG_HOOK_CONTRAST, 113 CONFIG_HOOK_SHARE, j720lcd_param, sc); 114 config_hook(CONFIG_HOOK_GET, CONFIG_HOOK_CONTRAST, 115 CONFIG_HOOK_SHARE, j720lcd_param, sc); 116 config_hook(CONFIG_HOOK_GET, CONFIG_HOOK_CONTRAST_MAX, 117 CONFIG_HOOK_SHARE, j720lcd_param, sc); 118 119 /* LCD power hook. */ 120 #if 0 121 config_hook(CONFIG_HOOK_POWERCONTROL, 122 CONFIG_HOOK_POWERCONTROL_LCDLIGHT, 123 CONFIG_HOOK_SHARE, j720lcd_power, sc); 124 #endif 125 126 /* Get default brightness/contrast values. */ 127 config_hook_call(CONFIG_HOOK_GET, CONFIG_HOOK_BRIGHTNESS, &brightness); 128 config_hook_call(CONFIG_HOOK_GET, CONFIG_HOOK_CONTRAST, &contrast); 129 130 printf(": brightness %d, contrast %d\n", brightness, contrast); 131 } 132 133 static int 134 j720lcd_param(void *ctx, int type, long id, void *msg) 135 { 136 struct j720lcd_softc *sc = ctx; 137 struct j720ssp_softc *ssp = sc->sc_ssp; 138 uint32_t data[2], len; 139 const int maxval = 255; 140 int i, s; 141 142 switch (type) { 143 case CONFIG_HOOK_GET: 144 switch (id) { 145 case CONFIG_HOOK_BRIGHTNESS_MAX: 146 case CONFIG_HOOK_CONTRAST_MAX: 147 *(int *)msg = maxval; 148 return 1; 149 case CONFIG_HOOK_BRIGHTNESS: 150 data[0] = 0xd6; 151 data[1] = 0x11; 152 len = 2; 153 break; 154 case CONFIG_HOOK_CONTRAST: 155 data[0] = 0xd4; 156 data[1] = 0x11; 157 len = 2; 158 break; 159 default: 160 return 0; 161 } 162 break; 163 164 case CONFIG_HOOK_SET: 165 switch (id) { 166 case CONFIG_HOOK_BRIGHTNESS: 167 if (*(int *)msg >= 0) { 168 data[0] = 0xd3; 169 data[1] = maxval - *(int *)msg; 170 len = 2; 171 } else { 172 /* XXX hack */ 173 data[0] = 0xdf; 174 len = 1; 175 } 176 break; 177 case CONFIG_HOOK_CONTRAST: 178 data[0] = 0xd1; 179 data[1] = maxval - *(int *)msg; 180 len = 2; 181 break; 182 default: 183 return 0; 184 } 185 break; 186 187 default: 188 return 0; 189 } 190 191 s = splbio(); 192 bus_space_write_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_PCR, 0x2000000); 193 194 for (i = 0; i < len; i++) { 195 if (j720ssp_readwrite(ssp, 1, data[i], &data[i], 500) < 0) 196 goto out; 197 } 198 bus_space_write_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_PSR, 0x2000000); 199 splx(s); 200 201 if (type == CONFIG_HOOK_SET) 202 return 1; 203 204 *(int *)msg = maxval - data[1]; 205 206 return 1; 207 208 out: 209 bus_space_write_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_PSR, 0x2000000); 210 211 /* reset SSP */ 212 bus_space_write_4(ssp->sc_iot, ssp->sc_ssph, SASSP_CR0, 0x307); 213 delay(100); 214 bus_space_write_4(ssp->sc_iot, ssp->sc_ssph, SASSP_CR0, 0x387); 215 216 splx(s); 217 218 DPRINTF(("j720lcd_param: error %x %x\n", data[0], data[1])); 219 return 0; 220 221 } 222 223 int 224 j720lcd_power(void *ctx, int type, long id, void *msg) 225 { 226 struct sed1356_softc *sc = ctx; 227 struct sa11x0_softc *psc = sc->sc_parent; 228 uint32_t reg; 229 int val; 230 231 if (type != CONFIG_HOOK_POWERCONTROL || 232 id != CONFIG_HOOK_POWERCONTROL_LCDLIGHT) 233 return 0; 234 235 sed1356_init_brightness(sc, 0); 236 sed1356_init_contrast(sc, 0); 237 238 if (msg) { 239 bus_space_write_1(sc->sc_iot, sc->sc_regh, 0x1f0, 0); 240 241 reg = bus_space_read_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR); 242 reg |= 0x1; 243 bus_space_write_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR, reg); 244 delay(50000); 245 246 val = sc->sc_contrast; 247 config_hook_call(CONFIG_HOOK_SET, CONFIG_HOOK_CONTRAST, &val); 248 delay(100000); 249 250 reg = bus_space_read_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR); 251 reg |= 0x4; 252 bus_space_write_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR, reg); 253 254 val = sc->sc_brightness; 255 config_hook_call(CONFIG_HOOK_SET, CONFIG_HOOK_BRIGHTNESS, &val); 256 257 reg = bus_space_read_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR); 258 reg |= 0x2; 259 bus_space_write_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR, reg); 260 } else { 261 reg = bus_space_read_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR); 262 reg &= ~0x2; 263 bus_space_write_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR, reg); 264 reg &= ~0x4; 265 bus_space_write_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR, reg); 266 delay(100000); 267 268 val = -2; 269 config_hook_call(CONFIG_HOOK_SET, CONFIG_HOOK_BRIGHTNESS, &val); 270 271 bus_space_write_1(sc->sc_iot, sc->sc_regh, 0x1f0, 1); 272 273 delay(100000); 274 reg = bus_space_read_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR); 275 reg &= ~0x1; 276 bus_space_write_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR, reg); 277 } 278 279 return 1; 280 } 281