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