xref: /freebsd-13-stable/sys/dev/terasic/mtl/terasic_mtl_syscons.c (revision 3bc80996974a61a4223eae4c1ccd47b6ee32a48a)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2012 Robert N. M. Watson
5  * All rights reserved.
6  *
7  * This software was developed by SRI International and the University of
8  * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
9  * ("CTSRD"), as part of the DARPA CRASH research programme.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  */
32 
33 #include <sys/cdefs.h>
34 #include <sys/param.h>
35 #include <sys/bus.h>
36 #include <sys/conf.h>
37 #include <sys/consio.h>
38 #include <sys/fbio.h>
39 #include <sys/kbio.h>
40 #include <sys/kernel.h>
41 #include <sys/lock.h>
42 #include <sys/malloc.h>
43 #include <sys/mutex.h>
44 #include <sys/module.h>
45 #include <sys/rman.h>
46 #include <sys/systm.h>
47 #include <sys/uio.h>
48 
49 #include <machine/bus.h>
50 #include <machine/resource.h>
51 #include <machine/vm.h>
52 
53 #include <dev/fb/fbreg.h>
54 
55 #include <dev/kbd/kbdreg.h>
56 
57 #include <dev/syscons/syscons.h>
58 
59 #include <dev/terasic/mtl/terasic_mtl.h>
60 
61 /*
62  * Terasic Multitouch LCD (MTL) syscons driver.  Implement syscons(4)'s
63  * video_switch_t KPI using MTL's text frame buffer.  In principle, we could
64  * actually implement sc_rndr_sw_t, since the MTL text frame buffer implements
65  * a VGA-like memory mapping.  However, this requires a lot more book-keeping
66  * with only minor performance improvements (avoiding indirection), as well as
67  * introducing potential endianness issues.  Instead we accept one additional
68  * memory copy between a software frame buffer and the hardware frame buffer
69  * and the generic frame buffer (gfb) framework.
70  */
71 
72 MALLOC_DEFINE(M_TERASIC_MTL, "mtl_syscons", "MTL syscons frame buffer");
73 
74 /*
75  * Run early so that boot-time console support can be initialised before
76  * newbus gets around to configuring syscons.
77  *
78  * XXXRW: We may need to do more here in order to see earlier boot messages.
79  */
80 static int
terasic_mtl_syscons_configure(int flags)81 terasic_mtl_syscons_configure(int flags)
82 {
83 
84 	printf("%s: not yet\n", __func__);
85 	return (0);
86 }
87 
88 static int
terasic_mtl_vidsw_probe(int unit,video_adapter_t ** adp,void * args,int flags)89 terasic_mtl_vidsw_probe(int unit, video_adapter_t **adp, void *args,
90     int flags)
91 {
92 
93 	printf("%s: not yet\n", __func__);
94 	return (0);
95 }
96 
97 static int
terasic_mtl_vidsw_init(int unit,video_adapter_t * adp,int flags)98 terasic_mtl_vidsw_init(int unit, video_adapter_t *adp, int flags)
99 {
100 	struct terasic_mtl_softc *sc;
101 	video_info_t *vi;
102 
103 	sc = (struct terasic_mtl_softc *)adp;
104 
105 	vi = &adp->va_info;
106 	vid_init_struct(adp, "terasic_mtl_syscons", -1, unit);
107 
108 	vi->vi_width = TERASIC_MTL_COLS;
109 	if (vi->vi_width > COL)
110 		vi->vi_width = COL;
111 	vi->vi_height = TERASIC_MTL_ROWS;
112 	if (vi->vi_height > ROW)
113 		vi->vi_height = ROW;
114 
115 	/*
116 	 * XXXRW: It's not quite clear how these should be initialised.
117 	 */
118 	vi->vi_cwidth = 0;
119 	vi->vi_cheight = 0;
120 	vi->vi_flags = V_INFO_COLOR;
121 	vi->vi_mem_model = V_INFO_MM_OTHER;
122 
123 	/*
124 	 * Software text frame buffer from which we update the actual MTL
125 	 * frame buffer when asked to.
126 	 */
127 	adp->va_window = (vm_offset_t)sc->mtl_text_soft;
128 
129 	/*
130 	 * Declare video adapter capabilities -- at this point, simply color
131 	 * support, as MTL doesn't support screen borders, font loading, or
132 	 * mode changes.
133 	 *
134 	 * XXXRW: It's unclear if V_ADP_INITIALIZED is needed here; other
135 	 * syscons(4) drivers are inconsistent about this and
136 	 * V_ADP_REGISTERED.
137 	 */
138 	adp->va_flags |= V_ADP_COLOR | V_ADP_INITIALIZED;
139 	if (vid_register(adp) < 0) {
140 		device_printf(sc->mtl_dev, "%s: vid_register failed\n",
141 		    __func__);
142 		return (ENXIO);
143 	}
144 	adp->va_flags |= V_ADP_REGISTERED;
145 	return (0);
146 }
147 
148 static int
terasic_mtl_vidsw_get_info(video_adapter_t * adp,int mode,video_info_t * info)149 terasic_mtl_vidsw_get_info(video_adapter_t *adp, int mode, video_info_t *info)
150 {
151 
152 	bcopy(&adp->va_info, info, sizeof(*info));
153 	return (0);
154 }
155 
156 static int
terasic_mtl_vidsw_query_mode(video_adapter_t * adp,video_info_t * info)157 terasic_mtl_vidsw_query_mode(video_adapter_t *adp, video_info_t *info)
158 {
159 
160 	printf("%s: not yet\n", __func__);
161 	return (ENODEV);
162 }
163 
164 static int
terasic_mtl_vidsw_set_mode(video_adapter_t * adp,int mode)165 terasic_mtl_vidsw_set_mode(video_adapter_t *adp, int mode)
166 {
167 
168 	printf("%s: not yet\n", __func__);
169 	return (ENODEV);
170 }
171 
172 static int
terasic_mtl_vidsw_save_font(video_adapter_t * adp,int page,int size,int width,u_char * data,int c,int count)173 terasic_mtl_vidsw_save_font(video_adapter_t *adp, int page, int size,
174     int width, u_char *data, int c, int count)
175 {
176 
177 	printf("%s: not yet\n", __func__);
178 	return (ENODEV);
179 }
180 
181 static int
terasic_mtl_vidsw_load_font(video_adapter_t * adp,int page,int size,int width,u_char * data,int c,int count)182 terasic_mtl_vidsw_load_font(video_adapter_t *adp, int page, int size,
183     int width, u_char *data, int c, int count)
184 {
185 
186 	printf("%s: not yet\n", __func__);
187 	return (ENODEV);
188 }
189 
190 static int
terasic_mtl_vidsw_show_font(video_adapter_t * adp,int page)191 terasic_mtl_vidsw_show_font(video_adapter_t *adp, int page)
192 {
193 
194 	printf("%s: not yet\n", __func__);
195 	return (ENODEV);
196 }
197 
198 static int
terasic_mtl_vidsw_save_palette(video_adapter_t * adp,u_char * palette)199 terasic_mtl_vidsw_save_palette(video_adapter_t *adp, u_char *palette)
200 {
201 
202 	printf("%s: not yet\n", __func__);
203 	return (ENODEV);
204 }
205 
206 static int
terasic_mtl_vidsw_load_palette(video_adapter_t * adp,u_char * palette)207 terasic_mtl_vidsw_load_palette(video_adapter_t *adp, u_char *palette)
208 {
209 
210 	printf("%s: not yet\n", __func__);
211 	return (ENODEV);
212 }
213 
214 static int
terasic_mtl_vidsw_set_border(video_adapter_t * adp,int border)215 terasic_mtl_vidsw_set_border(video_adapter_t *adp, int border)
216 {
217 
218 	printf("%s: not yet\n", __func__);
219 	return (ENODEV);
220 }
221 
222 static int
terasic_mtl_vidsw_save_state(video_adapter_t * adp,void * p,size_t size)223 terasic_mtl_vidsw_save_state(video_adapter_t *adp, void *p, size_t size)
224 {
225 
226 	printf("%s: not yet\n", __func__);
227 	return (ENODEV);
228 }
229 
230 static int
terasic_mtl_vidsw_load_state(video_adapter_t * adp,void * p)231 terasic_mtl_vidsw_load_state(video_adapter_t *adp, void *p)
232 {
233 
234 	printf("%s: not yet\n", __func__);
235 	return (ENODEV);
236 }
237 
238 static int
terasic_mtl_vidsw_set_win_org(video_adapter_t * adp,off_t offset)239 terasic_mtl_vidsw_set_win_org(video_adapter_t *adp, off_t offset)
240 {
241 
242 	printf("%s: not yet\n", __func__);
243 	return (ENODEV);
244 }
245 
246 static int
terasic_mtl_vidsw_read_hw_cursor(video_adapter_t * adp,int * colp,int * rowp)247 terasic_mtl_vidsw_read_hw_cursor(video_adapter_t *adp, int *colp, int *rowp)
248 {
249 	struct terasic_mtl_softc *sc;
250 	uint8_t col, row;
251 
252 	sc = (struct terasic_mtl_softc *)adp;
253 	terasic_mtl_reg_textcursor_get(sc, &col, &row);
254 	*colp = col;
255 	*rowp = row;
256 	return (0);
257 }
258 
259 static int
terasic_mtl_vidsw_set_hw_cursor(video_adapter_t * adp,int col,int row)260 terasic_mtl_vidsw_set_hw_cursor(video_adapter_t *adp, int col, int row)
261 {
262 	struct terasic_mtl_softc *sc;
263 
264 	sc = (struct terasic_mtl_softc *)adp;
265 	terasic_mtl_reg_textcursor_set(sc, col, row);
266 	return (0);
267 }
268 
269 static int
terasic_mtl_vidsw_set_hw_cursor_shape(video_adapter_t * adp,int base,int height,int celsize,int blink)270 terasic_mtl_vidsw_set_hw_cursor_shape(video_adapter_t *adp, int base,
271     int height, int celsize, int blink)
272 {
273 
274 	printf("%s: not yet\n", __func__);
275 	return (ENODEV);
276 }
277 
278 static int
terasic_mtl_vidsw_blank_display(video_adapter_t * adp,int mode)279 terasic_mtl_vidsw_blank_display(video_adapter_t *adp, int mode)
280 {
281 	struct terasic_mtl_softc *sc;
282 
283 	sc = (struct terasic_mtl_softc *)adp;
284 	terasic_mtl_reg_blank(sc);
285 	return (0);
286 }
287 
288 static int
terasic_mtl_vidsw_mmap(video_adapter_t * adp,vm_ooffset_t offset,vm_paddr_t * paddr,int prot,vm_memattr_t * memattr)289 terasic_mtl_vidsw_mmap(video_adapter_t *adp, vm_ooffset_t offset,
290     vm_paddr_t *paddr, int prot, vm_memattr_t *memattr)
291 {
292 
293 	printf("%s: not yet\n", __func__);
294 	return (ENODEV);
295 }
296 
297 static int
terasic_mtl_vidsw_ioctl(video_adapter_t * adp,u_long cmd,caddr_t data)298 terasic_mtl_vidsw_ioctl(video_adapter_t *adp, u_long cmd, caddr_t data)
299 {
300 
301 	return (fb_commonioctl(adp, cmd, data));
302 }
303 
304 static int
terasic_mtl_vidsw_clear(video_adapter_t * adp)305 terasic_mtl_vidsw_clear(video_adapter_t *adp)
306 {
307 	struct terasic_mtl_softc *sc;
308 
309 	sc = (struct terasic_mtl_softc *)adp;
310 	printf("%s: not yet terasic_mtl_io_clear(sc);\n", __func__);
311 	return (0);
312 }
313 
314 static int
terasic_mtl_vidsw_fill_rect(video_adapter_t * adp,int val,int x,int y,int cx,int cy)315 terasic_mtl_vidsw_fill_rect(video_adapter_t *adp, int val, int x, int y,
316     int cx, int cy)
317 {
318 
319 	printf("%s: not yet\n", __func__);
320 	return (ENODEV);
321 }
322 
323 static int
terasic_mtl_vidsw_bitblt(video_adapter_t * adp,...)324 terasic_mtl_vidsw_bitblt(video_adapter_t *adp, ...)
325 {
326 
327 	printf("%s: not yet\n", __func__);
328 	return (ENODEV);
329 }
330 
331 static int
terasic_mtl_vidsw_diag(video_adapter_t * adp,int level)332 terasic_mtl_vidsw_diag(video_adapter_t *adp, int level)
333 {
334 
335 	printf("%s: not yet\n", __func__);
336 	return (ENODEV);
337 }
338 
339 static int
terasic_mtl_vidsw_save_cursor_palette(video_adapter_t * adp,u_char * palette)340 terasic_mtl_vidsw_save_cursor_palette(video_adapter_t *adp, u_char *palette)
341 {
342 
343 	printf("%s: not yet\n", __func__);
344 	return (ENODEV);
345 }
346 
347 static int
terasic_mtl_vidsw_load_cursor_palette(video_adapter_t * adp,u_char * palette)348 terasic_mtl_vidsw_load_cursor_palette(video_adapter_t *adp, u_char *palette)
349 {
350 
351 	printf("%s: not yet\n", __func__);
352 	return (ENODEV);
353 }
354 
355 static int
terasic_mtl_vidsw_copy(video_adapter_t * adp,vm_offset_t src,vm_offset_t dst,int n)356 terasic_mtl_vidsw_copy(video_adapter_t *adp, vm_offset_t src, vm_offset_t dst,
357     int n)
358 {
359 
360 	printf("%s: not yet\n", __func__);
361 	return (ENODEV);
362 }
363 
364 static int
terasic_mtl_vidsw_putp(video_adapter_t * adp,vm_offset_t off,uint32_t p,uint32_t a,int size,int bpp,int bit_ltor,int byte_ltor)365 terasic_mtl_vidsw_putp(video_adapter_t *adp, vm_offset_t off, uint32_t p,
366     uint32_t a, int size, int bpp, int bit_ltor, int byte_ltor)
367 {
368 
369 	printf("%s: not yet\n", __func__);
370 	return (ENODEV);
371 }
372 
373 static int
terasic_mtl_vidsw_putc(video_adapter_t * adp,vm_offset_t off,uint8_t c,uint8_t a)374 terasic_mtl_vidsw_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c,
375     uint8_t a)
376 {
377 	struct terasic_mtl_softc *sc;
378 	u_int col, row;
379 
380 	sc = (struct terasic_mtl_softc *)adp;
381 	col = (off % adp->va_info.vi_width);
382 	row = (off / adp->va_info.vi_width);
383 	terasic_mtl_text_putc(sc, col, row, c, a);
384 	return (0);
385 }
386 
387 static int
terasic_mtl_vidsw_puts(video_adapter_t * adp,vm_offset_t off,u_int16_t * s,int len)388 terasic_mtl_vidsw_puts(video_adapter_t *adp, vm_offset_t off, u_int16_t *s,
389     int len)
390 {
391 	int i;
392 
393 	for (i = 0; i < len; i++)
394 		vidd_putc(adp, off + i, s[i] & 0xff, (s[i] & 0xff00) >> 8);
395 	return (0);
396 }
397 
398 static int
terasic_mtl_vidsw_putm(video_adapter_t * adp,int x,int y,uint8_t * pixel_image,uint32_t pixel_mask,int size,int width)399 terasic_mtl_vidsw_putm(video_adapter_t *adp, int x, int y,
400     uint8_t *pixel_image, uint32_t pixel_mask, int size, int width)
401 {
402 
403 	printf("%s: not yet\n", __func__);
404 	return (ENODEV);
405 }
406 
407 int
terasic_mtl_syscons_attach(struct terasic_mtl_softc * sc)408 terasic_mtl_syscons_attach(struct terasic_mtl_softc *sc)
409 {
410 	int error;
411 
412 	sc->mtl_text_soft  =
413 	    malloc(sizeof(uint16_t) * TERASIC_MTL_ROWS * TERASIC_MTL_COLS,
414 	    M_TERASIC_MTL, M_WAITOK | M_ZERO);
415 	error = terasic_mtl_vidsw_init(0, &sc->mtl_va, 0);
416 	if (error)
417 		goto out;
418 	error = sc_attach_unit(sc->mtl_unit, device_get_flags(sc->mtl_dev) |
419 	    SC_AUTODETECT_KBD);
420 	if (error)
421 		device_printf(sc->mtl_dev, "%s: sc_attach_unit failed (%d)\n",
422 		    __func__, error);
423 out:
424 	if (error)
425 		free(sc->mtl_text_soft, M_TERASIC_MTL);
426 	return (error);
427 }
428 
429 void
terasic_mtl_syscons_detach(struct terasic_mtl_softc * sc)430 terasic_mtl_syscons_detach(struct terasic_mtl_softc *sc)
431 {
432 
433 	free(sc->mtl_text_soft, M_TERASIC_MTL);
434 	panic("%s: not supported by syscons", __func__);
435 }
436 
437 static video_switch_t terasic_mtl_vidsw = {
438 	.probe =			terasic_mtl_vidsw_probe,
439 	.init =				terasic_mtl_vidsw_init,
440 	.get_info =			terasic_mtl_vidsw_get_info,
441 	.query_mode =			terasic_mtl_vidsw_query_mode,
442 	.set_mode =			terasic_mtl_vidsw_set_mode,
443 	.save_font =			terasic_mtl_vidsw_save_font,
444 	.load_font =			terasic_mtl_vidsw_load_font,
445 	.show_font =			terasic_mtl_vidsw_show_font,
446 	.save_palette =			terasic_mtl_vidsw_save_palette,
447 	.load_palette =			terasic_mtl_vidsw_load_palette,
448 	.set_border =			terasic_mtl_vidsw_set_border,
449 	.save_state =			terasic_mtl_vidsw_save_state,
450 	.load_state =			terasic_mtl_vidsw_load_state,
451 	.set_win_org =			terasic_mtl_vidsw_set_win_org,
452 	.read_hw_cursor =		terasic_mtl_vidsw_read_hw_cursor,
453 	.set_hw_cursor =		terasic_mtl_vidsw_set_hw_cursor,
454 	.set_hw_cursor_shape =		terasic_mtl_vidsw_set_hw_cursor_shape,
455 	.blank_display =		terasic_mtl_vidsw_blank_display,
456 	.mmap =				terasic_mtl_vidsw_mmap,
457 	.ioctl =			terasic_mtl_vidsw_ioctl,
458 	.clear =			terasic_mtl_vidsw_clear,
459 	.fill_rect =			terasic_mtl_vidsw_fill_rect,
460 	.bitblt =			terasic_mtl_vidsw_bitblt,
461 	.diag =				terasic_mtl_vidsw_diag,
462 	.save_cursor_palette =		terasic_mtl_vidsw_save_cursor_palette,
463 	.load_cursor_palette =		terasic_mtl_vidsw_load_cursor_palette,
464 	.copy =				terasic_mtl_vidsw_copy,
465 	.putp =				terasic_mtl_vidsw_putp,
466 	.putc =				terasic_mtl_vidsw_putc,
467 	.puts =				terasic_mtl_vidsw_puts,
468 	.putm =				terasic_mtl_vidsw_putm,
469 };
470 VIDEO_DRIVER(terasic_mtl_syscons, terasic_mtl_vidsw,
471     terasic_mtl_syscons_configure);
472 extern sc_rndr_sw_t txtrndrsw;
473 RENDERER(terasic_mtl_syscons, 0, txtrndrsw, gfb_set);
474 RENDERER_MODULE(terasic_mtl_syscons, gfb_set);
475