Home | History | Annotate | Line # | Download | only in dev
      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  */
     70 static 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 
     82 static const struct wsscreen_descr *w100lcd_scr_descr[] = {
     83 	&w100lcd_std_screen.c
     84 };
     85 
     86 static const struct wsscreen_list w100lcd_screen_list = {
     87 	.nscreens = __arraycount(w100lcd_scr_descr),
     88 	.screens = w100lcd_scr_descr,
     89 };
     90 
     91 static int	w100lcd_ioctl(void *, void *, u_long, void *, int,
     92 		    struct lwp *);
     93 static int	w100lcd_show_screen(void *, void *, int,
     94 		    void (*)(void *, int, int), void *);
     95 
     96 struct 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 
    107 const struct w100_panel_geometry lcd_panel_geometry_c700 =
    108 {
    109 	480,			/* Width */
    110 	640,			/* Height */
    111 	W100_PANEL_ROTATE_CW,   /* Rotate */
    112 };
    113 
    114 static int	w100lcd_match(device_t, cfdata_t, void *);
    115 static void	w100lcd_attach(device_t, device_t, void *);
    116 
    117 CFATTACH_DECL_NEW(w100lcd, sizeof(struct w100_softc),
    118     w100lcd_match, w100lcd_attach, NULL, NULL);
    119 
    120 static bool	w100lcd_suspend(device_t, const pmf_qual_t *);
    121 static bool	w100lcd_resume(device_t, const pmf_qual_t *);
    122 
    123 static int
    124 w100lcd_match(device_t parent, cfdata_t cf, void *aux)
    125 {
    126 
    127 	if (ZAURUS_ISC860)
    128 		return 1;
    129 	return 0;
    130 }
    131 
    132 static void
    133 w100lcd_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 
    154 void
    155 w100lcd_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  */
    165 static bool
    166 w100lcd_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 
    178 static bool
    179 w100lcd_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  */
    194 static int
    195 w100lcd_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 
    327 static int
    328 w100lcd_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