]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/dev/terasic/mtl/terasic_mtl_syscons.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / dev / terasic / mtl / terasic_mtl_syscons.c
1 /*-
2  * Copyright (c) 2012 Robert N. M. Watson
3  * All rights reserved.
4  *
5  * This software was developed by SRI International and the University of
6  * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
7  * ("CTSRD"), as part of the DARPA CRASH research programme.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
33
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
81 terasic_mtl_syscons_configure(int flags)
82 {
83
84         printf("%s: not yet\n", __func__);
85         return (0);
86 }
87
88 static int
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 /*
408  * XXXRW: For historical reasons, syscons can't register video consoles
409  * without a keyboard implementation.  Provide a dummy.
410  */
411 static keyboard_switch_t        terasic_mtl_keyboard_switch;
412
413 static int
414 terasic_mtl_kbd_configure(int flags)
415 {
416
417         return (0);
418 }
419
420 KEYBOARD_DRIVER(mtl_kbd, terasic_mtl_keyboard_switch,
421     terasic_mtl_kbd_configure);
422
423 int
424 terasic_mtl_syscons_attach(struct terasic_mtl_softc *sc)
425 {
426         int error;
427
428         sc->mtl_text_soft  =
429             malloc(sizeof(uint16_t) * TERASIC_MTL_ROWS * TERASIC_MTL_COLS,
430             M_TERASIC_MTL, M_WAITOK | M_ZERO);
431         error = terasic_mtl_vidsw_init(0, &sc->mtl_va, 0);
432         if (error)
433                 goto out;
434         error = sc_attach_unit(sc->mtl_unit, device_get_flags(sc->mtl_dev) |
435             SC_AUTODETECT_KBD);
436         if (error)
437                 device_printf(sc->mtl_dev, "%s: sc_attach_unit failed (%d)\n",
438                     __func__, error);
439 out:
440         if (error)
441                 free(sc->mtl_text_soft, M_TERASIC_MTL);
442         return (error);
443 }
444
445 void
446 terasic_mtl_syscons_detach(struct terasic_mtl_softc *sc)
447 {
448
449         free(sc->mtl_text_soft, M_TERASIC_MTL);
450         panic("%s: not supported by syscons", __func__);
451 }
452
453 static video_switch_t terasic_mtl_vidsw = {
454         .probe =                        terasic_mtl_vidsw_probe,
455         .init =                         terasic_mtl_vidsw_init,
456         .get_info =                     terasic_mtl_vidsw_get_info,
457         .query_mode =                   terasic_mtl_vidsw_query_mode,
458         .set_mode =                     terasic_mtl_vidsw_set_mode,
459         .save_font =                    terasic_mtl_vidsw_save_font,
460         .load_font =                    terasic_mtl_vidsw_load_font,
461         .show_font =                    terasic_mtl_vidsw_show_font,
462         .save_palette =                 terasic_mtl_vidsw_save_palette,
463         .load_palette =                 terasic_mtl_vidsw_load_palette,
464         .set_border =                   terasic_mtl_vidsw_set_border,
465         .save_state =                   terasic_mtl_vidsw_save_state,
466         .load_state =                   terasic_mtl_vidsw_load_state,
467         .set_win_org =                  terasic_mtl_vidsw_set_win_org,
468         .read_hw_cursor =               terasic_mtl_vidsw_read_hw_cursor,
469         .set_hw_cursor =                terasic_mtl_vidsw_set_hw_cursor,
470         .set_hw_cursor_shape =          terasic_mtl_vidsw_set_hw_cursor_shape,
471         .blank_display =                terasic_mtl_vidsw_blank_display,
472         .mmap =                         terasic_mtl_vidsw_mmap,
473         .ioctl =                        terasic_mtl_vidsw_ioctl,
474         .clear =                        terasic_mtl_vidsw_clear,
475         .fill_rect =                    terasic_mtl_vidsw_fill_rect,
476         .bitblt =                       terasic_mtl_vidsw_bitblt,
477         .diag =                         terasic_mtl_vidsw_diag,
478         .save_cursor_palette =          terasic_mtl_vidsw_save_cursor_palette,
479         .load_cursor_palette =          terasic_mtl_vidsw_load_cursor_palette,
480         .copy =                         terasic_mtl_vidsw_copy,
481         .putp =                         terasic_mtl_vidsw_putp,
482         .putc =                         terasic_mtl_vidsw_putc,
483         .puts =                         terasic_mtl_vidsw_puts,
484         .putm =                         terasic_mtl_vidsw_putm,
485 };
486 VIDEO_DRIVER(terasic_mtl_syscons, terasic_mtl_vidsw,
487     terasic_mtl_syscons_configure);
488 extern sc_rndr_sw_t txtrndrsw;
489 RENDERER(terasic_mtl_syscons, 0, txtrndrsw, gfb_set);
490 RENDERER_MODULE(terasic_mtl_syscons, gfb_set);