1 /* $NetBSD: j720lcd.c,v 1.1 2006/03/04 14:09:36 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.1 2006/03/04 14:09:36 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 int i, s; 140 141 switch (type) { 142 case CONFIG_HOOK_GET: 143 switch (id) { 144 case CONFIG_HOOK_BRIGHTNESS_MAX: 145 case CONFIG_HOOK_CONTRAST_MAX: 146 *(int *)msg = 255; 147 return 1; 148 case CONFIG_HOOK_BRIGHTNESS: 149 data[0] = 0x6b00; 150 data[1] = 0x8800; 151 len = 2; 152 break; 153 case CONFIG_HOOK_CONTRAST: 154 data[0] = 0x2b00; 155 data[1] = 0x8800; 156 len = 2; 157 break; 158 default: 159 return 0; 160 } 161 break; 162 163 case CONFIG_HOOK_SET: 164 switch (id) { 165 case CONFIG_HOOK_BRIGHTNESS: 166 if (*(int *)msg >= 0) { 167 data[0] = 0xcb00; 168 data[1] = *(int *)msg; 169 J720SSP_INVERT(data[1]); 170 data[1] <<= 8; 171 len = 2; 172 } else { 173 /* XXX hack */ 174 data[0] = 0xfb00; 175 len = 1; 176 } 177 break; 178 case CONFIG_HOOK_CONTRAST: 179 data[0] = 0x8b00; 180 data[1] = *(int *)msg; 181 J720SSP_INVERT(data[1]); 182 data[1] <<= 8; 183 len = 2; 184 break; 185 default: 186 return 0; 187 } 188 break; 189 190 default: 191 return 0; 192 } 193 194 s = splbio(); 195 bus_space_write_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_PCR, 0x2000000); 196 197 for (i = 0; i < len; i++) { 198 if (j720ssp_readwrite(ssp, 1, data[i], &data[i], 500) < 0) 199 goto out; 200 } 201 bus_space_write_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_PSR, 0x2000000); 202 splx(s); 203 204 if (type == CONFIG_HOOK_SET) 205 return 1; 206 207 J720SSP_INVERT(data[1]); 208 *(int *)msg = data[1]; 209 210 return 1; 211 212 out: 213 bus_space_write_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_PSR, 0x2000000); 214 215 /* reset SSP */ 216 bus_space_write_4(ssp->sc_iot, ssp->sc_ssph, SASSP_CR0, 0x307); 217 delay(100); 218 bus_space_write_4(ssp->sc_iot, ssp->sc_ssph, SASSP_CR0, 0x387); 219 220 splx(s); 221 222 DPRINTF(("j720lcd_param: error %x %x\n", data[0], data[1])); 223 return 0; 224 225 } 226 227 int 228 j720lcd_power(void *ctx, int type, long id, void *msg) 229 { 230 struct sed1356_softc *sc = ctx; 231 struct sa11x0_softc *psc = sc->sc_parent; 232 uint32_t reg; 233 int val; 234 235 if (type != CONFIG_HOOK_POWERCONTROL || 236 id != CONFIG_HOOK_POWERCONTROL_LCDLIGHT) 237 return 0; 238 239 sed1356_init_brightness(sc, 0); 240 sed1356_init_contrast(sc, 0); 241 242 if (msg) { 243 bus_space_write_1(sc->sc_iot, sc->sc_regh, 0x1f0, 0); 244 245 reg = bus_space_read_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR); 246 reg |= 0x1; 247 bus_space_write_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR, reg); 248 delay(50000); 249 250 val = sc->sc_contrast; 251 config_hook_call(CONFIG_HOOK_SET, CONFIG_HOOK_CONTRAST, &val); 252 delay(100000); 253 254 reg = bus_space_read_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR); 255 reg |= 0x4; 256 bus_space_write_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR, reg); 257 258 val = sc->sc_brightness; 259 config_hook_call(CONFIG_HOOK_SET, CONFIG_HOOK_BRIGHTNESS, &val); 260 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 } else { 265 reg = bus_space_read_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR); 266 reg &= ~0x2; 267 bus_space_write_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR, reg); 268 reg &= ~0x4; 269 bus_space_write_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR, reg); 270 delay(100000); 271 272 val = -2; 273 config_hook_call(CONFIG_HOOK_SET, CONFIG_HOOK_BRIGHTNESS, &val); 274 275 bus_space_write_1(sc->sc_iot, sc->sc_regh, 0x1f0, 1); 276 277 delay(100000); 278 reg = bus_space_read_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR); 279 reg &= ~0x1; 280 bus_space_write_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR, reg); 281 } 282 283 return 1; 284 } 285