xref: /netbsd-src/sys/arch/arm/clps711x/clpslcd.c (revision c7fb772b85b2b5d4cfb282f868f454b4701534fd)
1 /*      $NetBSD: clpslcd.c,v 1.3 2021/08/07 16:18:43 thorpej Exp $      */
2 /*
3  * Copyright (c) 2013 KIYOHARA Takashi
4  * All rights reserved.
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  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
19  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
23  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
24  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  * POSSIBILITY OF SUCH DAMAGE.
26  */
27 #include <sys/cdefs.h>
28 __KERNEL_RCSID(0, "$NetBSD: clpslcd.c,v 1.3 2021/08/07 16:18:43 thorpej Exp $");
29 
30 #include "rnd.h"
31 
32 #include <sys/param.h>
33 #include <sys/bus.h>
34 #include <sys/device.h>
35 #include <sys/errno.h>
36 
37 #include <uvm/uvm_extern.h>
38 
39 #include <arm/clps711x/clps711xreg.h>
40 #include <arm/clps711x/clpssocvar.h>
41 
42 #include <dev/cons.h>
43 #include <dev/wscons/wsconsio.h>
44 #include <dev/wscons/wsdisplayvar.h>
45 #include <dev/rasops/rasops.h>
46 
47 #include "locators.h"
48 
49 #define CLPSLCD_DEFAULT_DEPTH	4
50 
51 static int is_console;
52 struct clpslcd_softc {
53 	device_t sc_dev;
54 
55 	bus_space_tag_t sc_iot;
56 	bus_space_handle_t sc_ioh;
57 
58 	vaddr_t sc_buffer;
59 
60 	struct rasops_info sc_ri;
61 };
62 
63 static int clpslcd_match(device_t, cfdata_t, void *);
64 static void clpslcd_attach(device_t, device_t, void *);
65 
66 /* wsdisplay functions */
67 static int clpslcd_ioctl(void *, void *, u_long, void *, int, struct lwp *);
68 static paddr_t clpslcd_mmap(void *, void *, off_t, int);
69 static int clpslcd_alloc_screen(void *, const struct wsscreen_descr *, void **,
70 				int *, int *, long *);
71 static void clpslcd_free_screen(void *, void *);
72 static int clpslcd_show_screen(void *, void *, int,
73 			       void (*)(void *, int, int), void *);
74 
75 CFATTACH_DECL_NEW(clpslcd, sizeof(struct clpslcd_softc),
76     clpslcd_match, clpslcd_attach, NULL, NULL);
77 
78 
79 static struct wsscreen_descr clpslcd_descr = {
80 	.name = "clpslcd",
81 	.fontwidth = 8,
82 	.fontheight = 16,
83 	.capabilities = WSSCREEN_WSCOLORS,
84 };
85 static const struct wsscreen_descr *clpslcd_descrs[] = {
86 	&clpslcd_descr
87 };
88 
89 static const struct wsscreen_list clpslcd_screen_list = {
90 	.nscreens = __arraycount(clpslcd_descrs),
91 	.screens = clpslcd_descrs,
92 };
93 
94 struct wsdisplay_accessops clpslcd_accessops = {
95 	clpslcd_ioctl,
96 	clpslcd_mmap,
97 	clpslcd_alloc_screen,
98 	clpslcd_free_screen,
99 	clpslcd_show_screen,
100 	NULL,
101 	NULL,
102 	NULL,
103 };
104 
105 /* ARGSUSED */
106 static int
clpslcd_match(device_t parent,cfdata_t match,void * aux)107 clpslcd_match(device_t parent, cfdata_t match, void *aux)
108 {
109 
110 	return 1;
111 }
112 
113 /* ARGSUSED */
114 static void
clpslcd_attach(device_t parent,device_t self,void * aux)115 clpslcd_attach(device_t parent, device_t self, void *aux)
116 {
117 	struct clpslcd_softc *sc = device_private(self);
118 	struct clpssoc_attach_args *aa = aux;
119 	struct wsemuldisplaydev_attach_args waa;
120 	prop_dictionary_t dict = device_properties(self);
121 	struct rasops_info *ri;
122 	uint32_t syscon, lcdcon, depth, width, height, addr;
123 	int i;
124 
125 	aprint_naive("\n");
126 	aprint_normal("\n");
127 
128 	sc->sc_dev = self;
129 	sc->sc_iot = aa->aa_iot;
130 	sc->sc_ioh = *aa->aa_ioh;
131 
132 	if (!prop_dictionary_get_uint32(dict, "width", &width) ||
133 	    !prop_dictionary_get_uint32(dict, "height", &height) ||
134 	    !prop_dictionary_get_uint32(dict, "addr", &addr)) {
135 		aprint_error_dev(self, "can't get properties\n");
136 		return;
137 	}
138 	KASSERT(addr == 0xc0000000);
139 
140 	sc->sc_buffer = addr;
141 
142 	depth = CLPSLCD_DEFAULT_DEPTH;
143 	lcdcon =
144 	    LCDCON_GSEN |
145 	    LCDCON_ACP(13) |
146 	    LCDCON_PP(width * height) |
147 	    LCDCON_LL(width) |
148 	    LCDCON_VBS(width * height * depth);
149 	if (depth == 4)
150 		lcdcon |= LCDCON_GSMD;
151 
152 	syscon = bus_space_read_4(sc->sc_iot, sc->sc_ioh, PS711X_SYSCON);
153 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, PS711X_SYSCON,
154 	    syscon | SYSCON_LCDEN);
155 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, PS711X_LCDCON, lcdcon);
156 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, PS711X_PALLSW, 0x54321fc0);
157 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, PS711X_PALMSW, 0xedba9876);
158 
159 	aprint_normal_dev(self,
160 	    ": %dx%d pixels, %d bpp mono\n", width, height, depth);
161 
162 	ri = &sc->sc_ri;
163 	ri->ri_depth = depth;
164 	ri->ri_bits = (void *)addr;
165 	ri->ri_width = width;
166 	ri->ri_height = height;
167 	ri->ri_stride = width * ri->ri_depth / 8/*bits*/;
168 	ri->ri_flg = RI_FORCEMONO | RI_CLEAR | RI_CENTER;
169 
170 	if (is_console) {
171 		long defattr;
172 
173 		if (rasops_init(ri, 0, 0) < 0)
174 			panic("rasops_init failed");
175 
176 		if (ri->ri_depth == 4) {
177 			/* XXXXX: Create color map. */
178 			ri->ri_devcmap[0] = 0;
179 			for (i = 1; i < 15; i++) {
180 				ri->ri_devcmap[i] =
181 				    i | (i << 8) | (i << 16) | (i << 24);
182 			}
183 		}
184 		ri->ri_devcmap[15] = -1;
185 
186 		clpslcd_descr.ncols = ri->ri_cols;
187 		clpslcd_descr.nrows = ri->ri_rows;
188 		clpslcd_descr.textops = &ri->ri_ops;
189 		clpslcd_descr.capabilities = ri->ri_caps;
190 
191 		if ((ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr) != 0)
192 			panic("allocattr failed");
193 		wsdisplay_cnattach(&clpslcd_descr, ri, ri->ri_ccol, ri->ri_crow,
194 		    defattr);
195 	}
196 
197 	waa.console = is_console;
198 	waa.scrdata = &clpslcd_screen_list;
199 	waa.accessops = &clpslcd_accessops;
200 	waa.accesscookie = sc;
201 
202 	config_found(self, &waa, wsemuldisplaydevprint, CFARGS_NONE);
203 }
204 
205 static int
clpslcd_ioctl(void * v,void * vs,u_long cmd,void * data,int flag,struct lwp * l)206 clpslcd_ioctl(void *v, void *vs, u_long cmd, void *data, int flag,
207 	      struct lwp *l)
208 {
209 	struct clpslcd_softc *sc = v;
210 	struct wsdisplay_fbinfo *wsdisp_info;
211 
212 	switch (cmd) {
213 	case WSDISPLAYIO_GTYPE:
214 		*(int *)data = WSDISPLAY_TYPE_CLPS711X;
215 		return 0;
216 
217 	case WSDISPLAYIO_GINFO:
218 		wsdisp_info = (struct wsdisplay_fbinfo *)data;
219 		wsdisp_info->height = sc->sc_ri.ri_height;
220 		wsdisp_info->width = sc->sc_ri.ri_width;
221 		wsdisp_info->depth = sc->sc_ri.ri_depth;
222 		wsdisp_info->cmsize = 0;
223 		return 0;
224 
225 	case WSDISPLAYIO_GVIDEO:
226 		if (1)	/* XXXX */
227 			*(int *)data = WSDISPLAYIO_VIDEO_ON;
228 		else
229 			*(int *)data = WSDISPLAYIO_VIDEO_OFF;
230 		return 0;
231 
232 	case WSDISPLAYIO_SVIDEO:
233 		if (*(int *)data == WSDISPLAYIO_VIDEO_ON) {
234 			/* XXXX: turn on */
235 		} else {
236 			/* XXXX: turn off */
237 		}
238 		return 0;
239 
240 	case WSDISPLAYIO_LINEBYTES:
241 		*(int *)data = sc->sc_ri.ri_stride;
242 		return 0;
243 	}
244 
245 	return EPASSTHROUGH;
246 }
247 
248 static paddr_t
clpslcd_mmap(void * v,void * vs,off_t off,int prot)249 clpslcd_mmap(void *v, void *vs, off_t off, int prot)
250 {
251 	struct clpslcd_softc *sc = v;
252 
253 	if (off < 0 || sc->sc_ri.ri_stride * sc->sc_ri.ri_height <= off)
254 		return -1;
255 
256 	return (paddr_t)sc->sc_ri.ri_bits + off;
257 }
258 
259 static int
clpslcd_alloc_screen(void * v,const struct wsscreen_descr * scr,void ** cookiep,int * curxp,int * curyp,long * attrp)260 clpslcd_alloc_screen(void *v, const struct wsscreen_descr *scr, void **cookiep,
261 		   int *curxp, int *curyp, long *attrp)
262 {
263 printf("%s\n", __func__);
264 return -1;
265 }
266 
267 static void
clpslcd_free_screen(void * v,void * cookie)268 clpslcd_free_screen(void *v, void *cookie)
269 {
270 printf("%s\n", __func__);
271 }
272 
273 static int
clpslcd_show_screen(void * v,void * cookie,int waitok,void (* func)(void *,int,int),void * arg)274 clpslcd_show_screen(void *v, void *cookie, int waitok,
275 		  void (*func)(void *, int, int), void *arg)
276 {
277 printf("%s\n", __func__);
278 return -1;
279 }
280 
281 int
clpslcd_cnattach(void)282 clpslcd_cnattach(void)
283 {
284 
285 	is_console = 1;
286 	return 0;
287 }
288