1/* $NetBSD: w100lcd.c,v 1.6 2022/05/28 10:36:23 andvar Exp $ */ 2/* 3 * Copyright (c) 2002, 2003 Genetec Corporation. All rights reserved. 4 * Written by Hiroyuki Bessho for Genetec Corporation. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of Genetec Corporation may not be used to endorse or 15 * promote products derived from this software without specific prior 16 * written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENETEC CORPORATION 22 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31/* 32 * LCD driver for Sharp Zaurus SL-C7x0/860, based on zlcd.c. 33 * 34 * Controlling LCD is done in w100.c. 35 * 36 * Codes in this file provide platform specific things including: 37 * LCD panel geometry 38 * 39 * LCD on/off switch and backlight brightness are done in lcdctl.c. 40 */ 41#include <sys/cdefs.h> 42__KERNEL_RCSID(0, "$NetBSD: w100lcd.c,v 1.6 2022/05/28 10:36:23 andvar Exp $"); 43 44#include "lcdctl.h" 45 46#include <sys/param.h> 47#include <sys/systm.h> 48#include <sys/bus.h> 49 50#include <dev/cons.h> 51#include <dev/wscons/wsconsio.h> 52#include <dev/wscons/wsdisplayvar.h> 53#include <dev/rasops/rasops.h> 54#include <dev/wsfont/wsfont.h> 55 56#include <dev/hpc/hpcfbio.h> 57 58#include <arm/xscale/pxa2x0var.h> 59#include <zaurus/dev/w100var.h> 60 61#include <zaurus/zaurus/zaurus_var.h> 62#include <zaurus/dev/w100lcdvar.h> 63#if NLCDCTL > 0 64#include <zaurus/dev/lcdctlvar.h> 65#endif 66 67/* 68 * wsdisplay glue 69 */ 70static struct w100_wsscreen_descr w100lcd_std_screen = { 71 .c = { 72 .name = "std", 73 .textops = &w100_emulops, 74 .fontwidth = 8, 75 .fontheight = 16, 76 .capabilities = WSSCREEN_WSCOLORS, 77 }, 78 .depth = 16, /* bits per pixel */ 79 .flags = 0, 80}; 81 82static const struct wsscreen_descr *w100lcd_scr_descr[] = { 83 &w100lcd_std_screen.c 84}; 85 86static const struct wsscreen_list w100lcd_screen_list = { 87 .nscreens = __arraycount(w100lcd_scr_descr), 88 .screens = w100lcd_scr_descr, 89}; 90 91static int w100lcd_ioctl(void *, void *, u_long, void *, int, 92 struct lwp *); 93static int w100lcd_show_screen(void *, void *, int, 94 void (*)(void *, int, int), void *); 95 96struct wsdisplay_accessops w100lcd_accessops = { 97 w100lcd_ioctl, 98 w100_mmap, 99 w100_alloc_screen, 100 w100_free_screen, 101 w100lcd_show_screen, 102 NULL, 103 NULL, 104 NULL, 105}; 106 107const struct w100_panel_geometry lcd_panel_geometry_c700 = 108{ 109 480, /* Width */ 110 640, /* Height */ 111 W100_PANEL_ROTATE_CW, /* Rotate */ 112}; 113 114static int w100lcd_match(device_t, cfdata_t, void *); 115static void w100lcd_attach(device_t, device_t, void *); 116 117CFATTACH_DECL_NEW(w100lcd, sizeof(struct w100_softc), 118 w100lcd_match, w100lcd_attach, NULL, NULL); 119 120static bool w100lcd_suspend(device_t, const pmf_qual_t *); 121static bool w100lcd_resume(device_t, const pmf_qual_t *); 122 123static int 124w100lcd_match(device_t parent, cfdata_t cf, void *aux) 125{ 126 127 if (ZAURUS_ISC860) 128 return 1; 129 return 0; 130} 131 132static void 133w100lcd_attach(device_t parent, device_t self, void *aux) 134{ 135 struct w100_softc *sc = device_private(self); 136 struct pxaip_attach_args *pxa = (struct pxaip_attach_args *)aux; 137 struct wsemuldisplaydev_attach_args aa; 138 139 sc->dev = self; 140 141 w100_attach_subr(sc, pxa->pxa_iot, &lcd_panel_geometry_c700); 142 143 aa.console = glass_console; 144 aa.scrdata = &w100lcd_screen_list; 145 aa.accessops = &w100lcd_accessops; 146 aa.accesscookie = sc; 147 148 (void)config_found(self, &aa, wsemuldisplaydevprint, CFARGS_NONE); 149 150 if (!pmf_device_register(self, w100lcd_suspend, w100lcd_resume)) 151 aprint_error_dev(self, "couldn't establish power handler\n"); 152} 153 154void 155w100lcd_cnattach(void) 156{ 157 158 if (ZAURUS_ISC860) 159 w100_cnattach(&w100lcd_std_screen, &lcd_panel_geometry_c700); 160} 161 162/* 163 * power management 164 */ 165static bool 166w100lcd_suspend(device_t dv, const pmf_qual_t *qual) 167{ 168 struct w100_softc *sc = device_private(dv); 169 170#if NLCDCTL > 0 171 lcdctl_onoff(false); 172#endif 173 w100_suspend(sc); 174 175 return true; 176} 177 178static bool 179w100lcd_resume(device_t dv, const pmf_qual_t *qual) 180{ 181 struct w100_softc *sc = device_private(dv); 182 183 w100_resume(sc); 184#if NLCDCTL > 0 185 lcdctl_onoff(true); 186#endif 187 188 return true; 189} 190 191/* 192 * wsdisplay accessops overrides 193 */ 194static int 195w100lcd_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, 196 struct lwp *l) 197{ 198 struct w100_softc *sc = (struct w100_softc *)v; 199 struct hpcfb_fbconf *fbconf; 200 struct hpcfb_dspconf *dspconf; 201 int res = EINVAL; 202 203 switch (cmd) { 204#if NLCDCTL > 0 205 case WSDISPLAYIO_GETPARAM: 206 case WSDISPLAYIO_SETPARAM: 207 res = lcdctl_param(cmd, (struct wsdisplay_param *)data); 208 break; 209#endif 210 case HPCFBIO_GCONF: 211 fbconf = (struct hpcfb_fbconf *)data; 212 if (fbconf->hf_conf_index != 0 && 213 fbconf->hf_conf_index != HPCFB_CURRENT_CONFIG) { 214 break; 215 } 216 217 fbconf->hf_conf_index = 0; 218 fbconf->hf_nconfs = 1; 219 fbconf->hf_class = HPCFB_CLASS_RGBCOLOR; 220 strlcpy(fbconf->hf_name, "Sharp Zaurus frame buffer", 221 sizeof(fbconf->hf_name)); 222 strlcpy(fbconf->hf_conf_name, "default", 223 sizeof(fbconf->hf_conf_name)); 224 fbconf->hf_width = sc->display_width; 225 fbconf->hf_height = sc->display_height; 226 fbconf->hf_baseaddr = (u_long)sc->active->buf_va; 227 fbconf->hf_offset = 0; 228 fbconf->hf_bytes_per_line = sc->display_width * 229 sc->active->depth / 8; 230 fbconf->hf_nplanes = 1; 231 fbconf->hf_bytes_per_plane = sc->display_width * 232 sc->display_height * sc->active->depth / 8; 233 fbconf->hf_pack_width = sc->active->depth; 234 fbconf->hf_pixels_per_pack = 1; 235 fbconf->hf_pixel_width = sc->active->depth; 236 fbconf->hf_access_flags = (0 237 | HPCFB_ACCESS_BYTE 238 | HPCFB_ACCESS_WORD 239 | HPCFB_ACCESS_DWORD); 240 fbconf->hf_order_flags = 0; 241 fbconf->hf_reg_offset = 0; 242 243 fbconf->hf_class_data_length = sizeof(struct hf_rgb_tag); 244 fbconf->hf_u.hf_rgb.hf_flags = 0; 245 fbconf->hf_u.hf_rgb.hf_red_width = 5; 246 fbconf->hf_u.hf_rgb.hf_red_shift = 11; 247 fbconf->hf_u.hf_rgb.hf_green_width = 6; 248 fbconf->hf_u.hf_rgb.hf_green_shift = 5; 249 fbconf->hf_u.hf_rgb.hf_blue_width = 5; 250 fbconf->hf_u.hf_rgb.hf_blue_shift = 0; 251 fbconf->hf_u.hf_rgb.hf_alpha_width = 0; 252 fbconf->hf_u.hf_rgb.hf_alpha_shift = 0; 253 254 fbconf->hf_ext_size = 0; 255 fbconf->hf_ext_data = NULL; 256 257 res = 0; 258 break; 259 260 case HPCFBIO_SCONF: 261 fbconf = (struct hpcfb_fbconf *)data; 262 if (fbconf->hf_conf_index != 0 && 263 fbconf->hf_conf_index != HPCFB_CURRENT_CONFIG) { 264 break; 265 } 266 /* nothing to do because we have only one configuration */ 267 res = 0; 268 break; 269 270 case HPCFBIO_GDSPCONF: 271 dspconf = (struct hpcfb_dspconf *)data; 272 if ((dspconf->hd_unit_index != 0 && 273 dspconf->hd_unit_index != HPCFB_CURRENT_UNIT) || 274 (dspconf->hd_conf_index != 0 && 275 dspconf->hd_conf_index != HPCFB_CURRENT_CONFIG)) { 276 break; 277 } 278 279 dspconf->hd_unit_index = 0; 280 dspconf->hd_nunits = 1; 281 dspconf->hd_class = HPCFB_DSP_CLASS_COLORLCD; 282 strlcpy(dspconf->hd_name, "Sharp Zaurus LCD", 283 sizeof(dspconf->hd_name)); 284 dspconf->hd_op_flags = 0; 285 dspconf->hd_conf_index = 0; 286 dspconf->hd_nconfs = 1; 287 strlcpy(dspconf->hd_conf_name, "default", 288 sizeof(dspconf->hd_conf_name)); 289 dspconf->hd_width = sc->display_width; 290 dspconf->hd_height = sc->display_height; 291 dspconf->hd_xdpi = HPCFB_DSP_DPI_UNKNOWN; 292 dspconf->hd_ydpi = HPCFB_DSP_DPI_UNKNOWN; 293 294 res = 0; 295 break; 296 297 case HPCFBIO_SDSPCONF: 298 dspconf = (struct hpcfb_dspconf *)data; 299 if ((dspconf->hd_unit_index != 0 && 300 dspconf->hd_unit_index != HPCFB_CURRENT_UNIT) || 301 (dspconf->hd_conf_index != 0 && 302 dspconf->hd_conf_index != HPCFB_CURRENT_CONFIG)) { 303 break; 304 } 305 /* 306 * nothing to do 307 * because we have only one unit and one configuration 308 */ 309 res = 0; 310 break; 311 312 case HPCFBIO_GOP: 313 case HPCFBIO_SOP: 314 /* currently not implemented... */ 315 break; 316 317 default: 318 break; 319 } 320 321 if (res == EINVAL) 322 res = w100_ioctl(v, vs, cmd, data, flag, l); 323 324 return res; 325} 326 327static int 328w100lcd_show_screen(void *v, void *cookie, int waitok, 329 void (*cb_func)(void *, int, int), void *cb_arg) 330{ 331 int error; 332 333 error = w100_show_screen(v, cookie, waitok, cb_func, cb_arg); 334 if (error) 335 return (error); 336 337 /* Turn on LCD */ 338#if NLCDCTL > 0 339 lcdctl_onoff(true); 340#endif 341 342 return 0; 343} 344