gxlcd.c revision 1.2
1/*	$NetBSD: gxlcd.c,v 1.2 2009/11/21 08:33:50 kiyohara Exp $	*/
2
3/*
4 * Copyright (c) 2002, 2003  Genetec Corporation.  All rights reserved.
5 * Written by Hiroyuki Bessho for Genetec Corporation.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. The name of Genetec Corporation may not be used to endorse or
16 *    promote products derived from this software without specific prior
17 *    written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL GENETEC CORPORATION
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32/*
33 * LCD driver for Gumstix consoleLCD-vx and compatible.
34 * (based on the Intel Lubbock driver).
35 *
36 * Controlling LCD is almost completely done through PXA2X0's
37 * integrated LCD controller.  Codes for it is arm/xscale/pxa2x0_lcd.c.
38 *
39 * Codes in this file provide platform specific things including:
40 *   LCD on/off switch and backlight
41 *   LCD panel geometry
42 */
43
44#include <sys/cdefs.h>
45__KERNEL_RCSID(0, "$NetBSD: gxlcd.c,v 1.2 2009/11/21 08:33:50 kiyohara Exp $");
46
47#include <sys/param.h>
48#include <sys/systm.h>
49#include <sys/conf.h>
50#include <sys/uio.h>
51#include <sys/malloc.h>
52
53#include <dev/cons.h>
54#include <dev/wscons/wsconsio.h>
55#include <dev/wscons/wsdisplayvar.h>
56#include <dev/wscons/wscons_callbacks.h>
57
58#include <machine/bus.h>
59
60#include <arm/xscale/pxa2x0var.h>
61#include <arm/xscale/pxa2x0reg.h>
62#include <arm/xscale/pxa2x0_lcd.h>
63#include <arm/xscale/pxa2x0_gpio.h>
64
65
66#ifndef CURRENT_DISPLAY
67#define CURRENT_DISPLAY samsung_lte430wq_f0c
68#endif
69
70
71static int gxlcd_match(device_t, cfdata_t, void *);
72static void gxlcd_attach(device_t, device_t, void *);
73
74void gxlcd_cnattach(void);
75
76static int gxlcd_ioctl(void *, void *, u_long, void *, int, struct lwp *);
77static int gxlcd_show_screen(void *, void *, int,
78			     void (*)(void *, int, int), void *);
79
80
81/*
82 * wsdisplay glue
83 */
84static struct pxa2x0_wsscreen_descr gxlcd_std_screen = {
85	.c = {
86		.name = "std",
87		.textops = &pxa2x0_lcd_emulops,
88		.fontwidth = 8,
89		.fontheight = 16,
90		.capabilities = WSSCREEN_WSCOLORS,
91	},
92	.depth = 16,			/* bits per pixel */
93};
94
95static const struct wsscreen_descr *gxlcd_scr_descr[] = {
96	&gxlcd_std_screen.c
97};
98
99static const struct wsscreen_list gxlcd_screen_list = {
100	.nscreens = __arraycount(gxlcd_scr_descr),
101	.screens = gxlcd_scr_descr,
102};
103
104struct wsdisplay_accessops gxlcd_accessops = {
105	gxlcd_ioctl,
106	pxa2x0_lcd_mmap,
107	pxa2x0_lcd_alloc_screen,
108	pxa2x0_lcd_free_screen,
109	gxlcd_show_screen,
110	NULL,
111	NULL,
112	NULL,
113};
114
115const struct lcd_panel_geometry samsung_lte430wq_f0c =
116{
117	480,			/* Width */
118	272,			/* Height */
119	0,			/* No extra lines */
120
121	LCDPANEL_ACTIVE | LCDPANEL_PCP,
122	1,			/* clock divider */
123	0,			/* AC bias pin freq */
124
125	41,			/* horizontal sync pulse width */
126	4,			/* BLW */
127	8,			/* ELW */
128
129	10,			/* vertical sync pulse width */
130	2,			/* BFW */
131	4,			/* EFW */
132};
133
134static int gxlcd_console;
135
136
137CFATTACH_DECL_NEW(gxlcd, sizeof(struct pxa2x0_lcd_softc),
138    gxlcd_match, gxlcd_attach, NULL, NULL);
139
140
141static int
142gxlcd_match(device_t parent, cfdata_t match, void *aux)
143{
144	struct pxaip_attach_args *pxa = aux;
145
146	if (strcmp(pxa->pxa_name, match->cf_name) != 0)
147		return 0;
148
149	pxa->pxa_size = PXA2X0_LCDC_SIZE;
150	return 1;
151}
152
153static void
154gxlcd_attach(device_t parent, device_t self, void *aux)
155{
156	struct pxa2x0_lcd_softc *sc = device_private(self);
157	struct wsemuldisplaydev_attach_args aa;
158
159	sc->dev = self;
160	pxa2x0_lcd_attach_sub(sc, aux, &CURRENT_DISPLAY);
161
162	aa.console = gxlcd_console;
163	aa.scrdata = &gxlcd_screen_list;
164	aa.accessops = &gxlcd_accessops;
165	aa.accesscookie = sc;
166
167	pxa2x0_lcd_setup_wsscreen(&gxlcd_std_screen, &CURRENT_DISPLAY, NULL);
168
169	(void) config_found(self, &aa, wsemuldisplaydevprint);
170}
171
172void
173gxlcd_cnattach(void)
174{
175
176	pxa2x0_lcd_cnattach(&gxlcd_std_screen, &CURRENT_DISPLAY);
177
178	gxlcd_console = 1;
179}
180
181
182/*
183 * wsdisplay accessops overrides
184 */
185static int
186gxlcd_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l)
187{
188	int res = EINVAL;
189
190	switch (cmd) {
191	case WSDISPLAYIO_SVIDEO:
192		if (*(int *)data == WSDISPLAYIO_VIDEO_ON)
193			pxa2x0_gpio_set_function(17, GPIO_IN);
194		else
195			pxa2x0_gpio_set_function(17, GPIO_OUT | GPIO_CLR);
196		break;
197	}
198
199	if (res == EINVAL)
200		res = pxa2x0_lcd_ioctl(v, vs, cmd, data, flag, l);
201	return res;
202}
203
204static int
205gxlcd_show_screen(void *v, void *cookie, int waitok,
206		  void (*cb_func)(void *, int, int), void *cb_arg)
207{
208	int error;
209
210	error = pxa2x0_lcd_show_screen(v, cookie, waitok, cb_func, cb_arg);
211	if (error)
212		return (error);
213
214	/* Turn on LCD */
215	pxa2x0_gpio_set_function(17, GPIO_IN);
216
217	return 0;
218}
219