1239691Srwatson/*-
2239691Srwatson * Copyright (c) 2012 Robert N. M. Watson
3239691Srwatson * All rights reserved.
4239691Srwatson *
5239691Srwatson * This software was developed by SRI International and the University of
6239691Srwatson * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
7239691Srwatson * ("CTSRD"), as part of the DARPA CRASH research programme.
8239691Srwatson *
9239691Srwatson * Redistribution and use in source and binary forms, with or without
10239691Srwatson * modification, are permitted provided that the following conditions
11239691Srwatson * are met:
12239691Srwatson * 1. Redistributions of source code must retain the above copyright
13239691Srwatson *    notice, this list of conditions and the following disclaimer.
14239691Srwatson * 2. Redistributions in binary form must reproduce the above copyright
15239691Srwatson *    notice, this list of conditions and the following disclaimer in the
16239691Srwatson *    documentation and/or other materials provided with the distribution.
17239691Srwatson *
18239691Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19239691Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20239691Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21239691Srwatson * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22239691Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23239691Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24239691Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25239691Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26239691Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27239691Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28239691Srwatson * SUCH DAMAGE.
29239691Srwatson */
30239691Srwatson
31239691Srwatson#include <sys/cdefs.h>
32239691Srwatson__FBSDID("$FreeBSD$");
33239691Srwatson
34239691Srwatson#include <sys/param.h>
35239691Srwatson#include <sys/bus.h>
36239691Srwatson#include <sys/conf.h>
37239691Srwatson#include <sys/consio.h>
38239691Srwatson#include <sys/fbio.h>
39239691Srwatson#include <sys/kbio.h>
40239691Srwatson#include <sys/kernel.h>
41239691Srwatson#include <sys/lock.h>
42239691Srwatson#include <sys/malloc.h>
43239691Srwatson#include <sys/mutex.h>
44239691Srwatson#include <sys/module.h>
45239691Srwatson#include <sys/rman.h>
46239691Srwatson#include <sys/systm.h>
47239691Srwatson#include <sys/uio.h>
48239691Srwatson
49239691Srwatson#include <machine/bus.h>
50239691Srwatson#include <machine/resource.h>
51239691Srwatson#include <machine/vm.h>
52239691Srwatson
53239691Srwatson#include <dev/fb/fbreg.h>
54239691Srwatson
55239691Srwatson#include <dev/kbd/kbdreg.h>
56239691Srwatson
57239691Srwatson#include <dev/syscons/syscons.h>
58239691Srwatson
59239691Srwatson#include <dev/terasic/mtl/terasic_mtl.h>
60239691Srwatson
61239691Srwatson/*
62239691Srwatson * Terasic Multitouch LCD (MTL) syscons driver.  Implement syscons(4)'s
63239691Srwatson * video_switch_t KPI using MTL's text frame buffer.  In principle, we could
64239691Srwatson * actually implement sc_rndr_sw_t, since the MTL text frame buffer implements
65239691Srwatson * a VGA-like memory mapping.  However, this requires a lot more book-keeping
66239691Srwatson * with only minor performance improvements (avoiding indirection), as well as
67239691Srwatson * introducing potential endianness issues.  Instead we accept one additional
68239691Srwatson * memory copy between a software frame buffer and the hardware frame buffer
69239691Srwatson * and the generic frame buffer (gfb) framework.
70239691Srwatson */
71239691Srwatson
72239691SrwatsonMALLOC_DEFINE(M_TERASIC_MTL, "mtl_syscons", "MTL syscons frame buffer");
73239691Srwatson
74239691Srwatson/*
75239691Srwatson * Run early so that boot-time console support can be initialised before
76239691Srwatson * newbus gets around to configuring syscons.
77239691Srwatson *
78239691Srwatson * XXXRW: We may need to do more here in order to see earlier boot messages.
79239691Srwatson */
80239691Srwatsonstatic int
81239691Srwatsonterasic_mtl_syscons_configure(int flags)
82239691Srwatson{
83239691Srwatson
84239691Srwatson	printf("%s: not yet\n", __func__);
85239691Srwatson	return (0);
86239691Srwatson}
87239691Srwatson
88239691Srwatsonstatic int
89239691Srwatsonterasic_mtl_vidsw_probe(int unit, video_adapter_t **adp, void *args,
90239691Srwatson    int flags)
91239691Srwatson{
92239691Srwatson
93239691Srwatson	printf("%s: not yet\n", __func__);
94239691Srwatson	return (0);
95239691Srwatson}
96239691Srwatson
97239691Srwatsonstatic int
98239691Srwatsonterasic_mtl_vidsw_init(int unit, video_adapter_t *adp, int flags)
99239691Srwatson{
100239691Srwatson	struct terasic_mtl_softc *sc;
101239691Srwatson	video_info_t *vi;
102239691Srwatson
103239691Srwatson	sc = (struct terasic_mtl_softc *)adp;
104239691Srwatson
105239691Srwatson	vi = &adp->va_info;
106239691Srwatson	vid_init_struct(adp, "terasic_mtl_syscons", -1, unit);
107239691Srwatson
108239691Srwatson	vi->vi_width = TERASIC_MTL_COLS;
109239691Srwatson	if (vi->vi_width > COL)
110239691Srwatson		vi->vi_width = COL;
111239691Srwatson	vi->vi_height = TERASIC_MTL_ROWS;
112239691Srwatson	if (vi->vi_height > ROW)
113239691Srwatson		vi->vi_height = ROW;
114239691Srwatson
115239691Srwatson	/*
116239691Srwatson	 * XXXRW: It's not quite clear how these should be initialised.
117239691Srwatson	 */
118239691Srwatson	vi->vi_cwidth = 0;
119239691Srwatson	vi->vi_cheight = 0;
120239691Srwatson	vi->vi_flags = V_INFO_COLOR;
121239691Srwatson	vi->vi_mem_model = V_INFO_MM_OTHER;
122239691Srwatson
123239691Srwatson	/*
124239691Srwatson	 * Software text frame buffer from which we update the actual MTL
125239691Srwatson	 * frame buffer when asked to.
126239691Srwatson	 */
127239691Srwatson	adp->va_window = (vm_offset_t)sc->mtl_text_soft;
128239691Srwatson
129239691Srwatson	/*
130239691Srwatson	 * Declare video adapter capabilities -- at this point, simply color
131239691Srwatson	 * support, as MTL doesn't support screen borders, font loading, or
132239691Srwatson	 * mode changes.
133239691Srwatson	 *
134239691Srwatson	 * XXXRW: It's unclear if V_ADP_INITIALIZED is needed here; other
135239691Srwatson	 * syscons(4) drivers are inconsistent about this and
136239691Srwatson	 * V_ADP_REGISTERED.
137239691Srwatson	 */
138239691Srwatson	adp->va_flags |= V_ADP_COLOR | V_ADP_INITIALIZED;
139239691Srwatson	if (vid_register(adp) < 0) {
140239691Srwatson		device_printf(sc->mtl_dev, "%s: vid_register failed\n",
141239691Srwatson		    __func__);
142239691Srwatson		return (ENXIO);
143239691Srwatson	}
144239691Srwatson	adp->va_flags |= V_ADP_REGISTERED;
145239691Srwatson	return (0);
146239691Srwatson}
147239691Srwatson
148239691Srwatsonstatic int
149239691Srwatsonterasic_mtl_vidsw_get_info(video_adapter_t *adp, int mode, video_info_t *info)
150239691Srwatson{
151239691Srwatson
152239691Srwatson	bcopy(&adp->va_info, info, sizeof(*info));
153239691Srwatson	return (0);
154239691Srwatson}
155239691Srwatson
156239691Srwatsonstatic int
157239691Srwatsonterasic_mtl_vidsw_query_mode(video_adapter_t *adp, video_info_t *info)
158239691Srwatson{
159239691Srwatson
160239691Srwatson	printf("%s: not yet\n", __func__);
161239691Srwatson	return (ENODEV);
162239691Srwatson}
163239691Srwatson
164239691Srwatsonstatic int
165239691Srwatsonterasic_mtl_vidsw_set_mode(video_adapter_t *adp, int mode)
166239691Srwatson{
167239691Srwatson
168239691Srwatson	printf("%s: not yet\n", __func__);
169239691Srwatson	return (ENODEV);
170239691Srwatson}
171239691Srwatson
172239691Srwatsonstatic int
173239691Srwatsonterasic_mtl_vidsw_save_font(video_adapter_t *adp, int page, int size,
174239691Srwatson    int width, u_char *data, int c, int count)
175239691Srwatson{
176239691Srwatson
177239691Srwatson	printf("%s: not yet\n", __func__);
178239691Srwatson	return (ENODEV);
179239691Srwatson}
180239691Srwatson
181239691Srwatsonstatic int
182239691Srwatsonterasic_mtl_vidsw_load_font(video_adapter_t *adp, int page, int size,
183239691Srwatson    int width, u_char *data, int c, int count)
184239691Srwatson{
185239691Srwatson
186239691Srwatson	printf("%s: not yet\n", __func__);
187239691Srwatson	return (ENODEV);
188239691Srwatson}
189239691Srwatson
190239691Srwatsonstatic int
191239691Srwatsonterasic_mtl_vidsw_show_font(video_adapter_t *adp, int page)
192239691Srwatson{
193239691Srwatson
194239691Srwatson	printf("%s: not yet\n", __func__);
195239691Srwatson	return (ENODEV);
196239691Srwatson}
197239691Srwatson
198239691Srwatsonstatic int
199239691Srwatsonterasic_mtl_vidsw_save_palette(video_adapter_t *adp, u_char *palette)
200239691Srwatson{
201239691Srwatson
202239691Srwatson	printf("%s: not yet\n", __func__);
203239691Srwatson	return (ENODEV);
204239691Srwatson}
205239691Srwatson
206239691Srwatsonstatic int
207239691Srwatsonterasic_mtl_vidsw_load_palette(video_adapter_t *adp, u_char *palette)
208239691Srwatson{
209239691Srwatson
210239691Srwatson	printf("%s: not yet\n", __func__);
211239691Srwatson	return (ENODEV);
212239691Srwatson}
213239691Srwatson
214239691Srwatsonstatic int
215239691Srwatsonterasic_mtl_vidsw_set_border(video_adapter_t *adp, int border)
216239691Srwatson{
217239691Srwatson
218239691Srwatson	printf("%s: not yet\n", __func__);
219239691Srwatson	return (ENODEV);
220239691Srwatson}
221239691Srwatson
222239691Srwatsonstatic int
223239691Srwatsonterasic_mtl_vidsw_save_state(video_adapter_t *adp, void *p, size_t size)
224239691Srwatson{
225239691Srwatson
226239691Srwatson	printf("%s: not yet\n", __func__);
227239691Srwatson	return (ENODEV);
228239691Srwatson}
229239691Srwatson
230239691Srwatsonstatic int
231239691Srwatsonterasic_mtl_vidsw_load_state(video_adapter_t *adp, void *p)
232239691Srwatson{
233239691Srwatson
234239691Srwatson	printf("%s: not yet\n", __func__);
235239691Srwatson	return (ENODEV);
236239691Srwatson}
237239691Srwatson
238239691Srwatsonstatic int
239239691Srwatsonterasic_mtl_vidsw_set_win_org(video_adapter_t *adp, off_t offset)
240239691Srwatson{
241239691Srwatson
242239691Srwatson	printf("%s: not yet\n", __func__);
243239691Srwatson	return (ENODEV);
244239691Srwatson}
245239691Srwatson
246239691Srwatsonstatic int
247239691Srwatsonterasic_mtl_vidsw_read_hw_cursor(video_adapter_t *adp, int *colp, int *rowp)
248239691Srwatson{
249239691Srwatson	struct terasic_mtl_softc *sc;
250239691Srwatson	uint8_t col, row;
251239691Srwatson
252239691Srwatson	sc = (struct terasic_mtl_softc *)adp;
253239691Srwatson	terasic_mtl_reg_textcursor_get(sc, &col, &row);
254239691Srwatson	*colp = col;
255239691Srwatson	*rowp = row;
256239691Srwatson	return (0);
257239691Srwatson}
258239691Srwatson
259239691Srwatsonstatic int
260239691Srwatsonterasic_mtl_vidsw_set_hw_cursor(video_adapter_t *adp, int col, int row)
261239691Srwatson{
262239691Srwatson	struct terasic_mtl_softc *sc;
263239691Srwatson
264239691Srwatson	sc = (struct terasic_mtl_softc *)adp;
265239691Srwatson	terasic_mtl_reg_textcursor_set(sc, col, row);
266239691Srwatson	return (0);
267239691Srwatson}
268239691Srwatson
269239691Srwatsonstatic int
270239691Srwatsonterasic_mtl_vidsw_set_hw_cursor_shape(video_adapter_t *adp, int base,
271239691Srwatson    int height, int celsize, int blink)
272239691Srwatson{
273239691Srwatson
274239691Srwatson	printf("%s: not yet\n", __func__);
275239691Srwatson	return (ENODEV);
276239691Srwatson}
277239691Srwatson
278239691Srwatsonstatic int
279239691Srwatsonterasic_mtl_vidsw_blank_display(video_adapter_t *adp, int mode)
280239691Srwatson{
281239691Srwatson	struct terasic_mtl_softc *sc;
282239691Srwatson
283239691Srwatson	sc = (struct terasic_mtl_softc *)adp;
284239691Srwatson	terasic_mtl_reg_blank(sc);
285239691Srwatson	return (0);
286239691Srwatson}
287239691Srwatson
288239691Srwatsonstatic int
289239691Srwatsonterasic_mtl_vidsw_mmap(video_adapter_t *adp, vm_ooffset_t offset,
290239691Srwatson    vm_paddr_t *paddr, int prot, vm_memattr_t *memattr)
291239691Srwatson{
292239691Srwatson
293239691Srwatson	printf("%s: not yet\n", __func__);
294239691Srwatson	return (ENODEV);
295239691Srwatson}
296239691Srwatson
297239691Srwatsonstatic int
298239691Srwatsonterasic_mtl_vidsw_ioctl(video_adapter_t *adp, u_long cmd, caddr_t data)
299239691Srwatson{
300239691Srwatson
301239691Srwatson	return (fb_commonioctl(adp, cmd, data));
302239691Srwatson}
303239691Srwatson
304239691Srwatsonstatic int
305239691Srwatsonterasic_mtl_vidsw_clear(video_adapter_t *adp)
306239691Srwatson{
307239691Srwatson	struct terasic_mtl_softc *sc;
308239691Srwatson
309239691Srwatson	sc = (struct terasic_mtl_softc *)adp;
310239691Srwatson	printf("%s: not yet terasic_mtl_io_clear(sc);\n", __func__);
311239691Srwatson	return (0);
312239691Srwatson}
313239691Srwatson
314239691Srwatsonstatic int
315239691Srwatsonterasic_mtl_vidsw_fill_rect(video_adapter_t *adp, int val, int x, int y,
316239691Srwatson    int cx, int cy)
317239691Srwatson{
318239691Srwatson
319239691Srwatson	printf("%s: not yet\n", __func__);
320239691Srwatson	return (ENODEV);
321239691Srwatson}
322239691Srwatson
323239691Srwatsonstatic int
324239691Srwatsonterasic_mtl_vidsw_bitblt(video_adapter_t *adp, ...)
325239691Srwatson{
326239691Srwatson
327239691Srwatson	printf("%s: not yet\n", __func__);
328239691Srwatson	return (ENODEV);
329239691Srwatson}
330239691Srwatson
331239691Srwatsonstatic int
332239691Srwatsonterasic_mtl_vidsw_diag(video_adapter_t *adp, int level)
333239691Srwatson{
334239691Srwatson
335239691Srwatson	printf("%s: not yet\n", __func__);
336239691Srwatson	return (ENODEV);
337239691Srwatson}
338239691Srwatson
339239691Srwatsonstatic int
340239691Srwatsonterasic_mtl_vidsw_save_cursor_palette(video_adapter_t *adp, u_char *palette)
341239691Srwatson{
342239691Srwatson
343239691Srwatson	printf("%s: not yet\n", __func__);
344239691Srwatson	return (ENODEV);
345239691Srwatson}
346239691Srwatson
347239691Srwatsonstatic int
348239691Srwatsonterasic_mtl_vidsw_load_cursor_palette(video_adapter_t *adp, u_char *palette)
349239691Srwatson{
350239691Srwatson
351239691Srwatson	printf("%s: not yet\n", __func__);
352239691Srwatson	return (ENODEV);
353239691Srwatson}
354239691Srwatson
355239691Srwatsonstatic int
356239691Srwatsonterasic_mtl_vidsw_copy(video_adapter_t *adp, vm_offset_t src, vm_offset_t dst,
357239691Srwatson    int n)
358239691Srwatson{
359239691Srwatson
360239691Srwatson	printf("%s: not yet\n", __func__);
361239691Srwatson	return (ENODEV);
362239691Srwatson}
363239691Srwatson
364239691Srwatsonstatic int
365239691Srwatsonterasic_mtl_vidsw_putp(video_adapter_t *adp, vm_offset_t off, uint32_t p,
366239691Srwatson    uint32_t a, int size, int bpp, int bit_ltor, int byte_ltor)
367239691Srwatson{
368239691Srwatson
369239691Srwatson	printf("%s: not yet\n", __func__);
370239691Srwatson	return (ENODEV);
371239691Srwatson}
372239691Srwatson
373239691Srwatsonstatic int
374239691Srwatsonterasic_mtl_vidsw_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c,
375239691Srwatson    uint8_t a)
376239691Srwatson{
377239691Srwatson	struct terasic_mtl_softc *sc;
378239691Srwatson	u_int col, row;
379239691Srwatson
380239691Srwatson	sc = (struct terasic_mtl_softc *)adp;
381239691Srwatson	col = (off % adp->va_info.vi_width);
382239691Srwatson	row = (off / adp->va_info.vi_width);
383239691Srwatson	terasic_mtl_text_putc(sc, col, row, c, a);
384239691Srwatson	return (0);
385239691Srwatson}
386239691Srwatson
387239691Srwatsonstatic int
388239691Srwatsonterasic_mtl_vidsw_puts(video_adapter_t *adp, vm_offset_t off, u_int16_t *s,
389239691Srwatson    int len)
390239691Srwatson{
391239691Srwatson	int i;
392239691Srwatson
393239691Srwatson	for (i = 0; i < len; i++)
394239691Srwatson		vidd_putc(adp, off + i, s[i] & 0xff, (s[i] & 0xff00) >> 8);
395239691Srwatson	return (0);
396239691Srwatson}
397239691Srwatson
398239691Srwatsonstatic int
399239691Srwatsonterasic_mtl_vidsw_putm(video_adapter_t *adp, int x, int y,
400239691Srwatson    uint8_t *pixel_image, uint32_t pixel_mask, int size, int width)
401239691Srwatson{
402239691Srwatson
403239691Srwatson	printf("%s: not yet\n", __func__);
404239691Srwatson	return (ENODEV);
405239691Srwatson}
406239691Srwatson
407239691Srwatson/*
408239691Srwatson * XXXRW: For historical reasons, syscons can't register video consoles
409239691Srwatson * without a keyboard implementation.  Provide a dummy.
410239691Srwatson */
411239691Srwatsonstatic keyboard_switch_t	terasic_mtl_keyboard_switch;
412239691Srwatson
413239691Srwatsonstatic int
414239691Srwatsonterasic_mtl_kbd_configure(int flags)
415239691Srwatson{
416239691Srwatson
417239691Srwatson	return (0);
418239691Srwatson}
419239691Srwatson
420239691SrwatsonKEYBOARD_DRIVER(mtl_kbd, terasic_mtl_keyboard_switch,
421239691Srwatson    terasic_mtl_kbd_configure);
422239691Srwatson
423239691Srwatsonint
424239691Srwatsonterasic_mtl_syscons_attach(struct terasic_mtl_softc *sc)
425239691Srwatson{
426239691Srwatson	int error;
427239691Srwatson
428239691Srwatson	sc->mtl_text_soft  =
429239691Srwatson	    malloc(sizeof(uint16_t) * TERASIC_MTL_ROWS * TERASIC_MTL_COLS,
430239691Srwatson	    M_TERASIC_MTL, M_WAITOK | M_ZERO);
431239691Srwatson	error = terasic_mtl_vidsw_init(0, &sc->mtl_va, 0);
432239691Srwatson	if (error)
433239691Srwatson		goto out;
434239691Srwatson	error = sc_attach_unit(sc->mtl_unit, device_get_flags(sc->mtl_dev) |
435239691Srwatson	    SC_AUTODETECT_KBD);
436239691Srwatson	if (error)
437239691Srwatson		device_printf(sc->mtl_dev, "%s: sc_attach_unit failed (%d)\n",
438239691Srwatson		    __func__, error);
439239691Srwatsonout:
440239691Srwatson	if (error)
441239691Srwatson		free(sc->mtl_text_soft, M_TERASIC_MTL);
442239691Srwatson	return (error);
443239691Srwatson}
444239691Srwatson
445239691Srwatsonvoid
446239691Srwatsonterasic_mtl_syscons_detach(struct terasic_mtl_softc *sc)
447239691Srwatson{
448239691Srwatson
449239691Srwatson	free(sc->mtl_text_soft, M_TERASIC_MTL);
450239691Srwatson	panic("%s: not supported by syscons", __func__);
451239691Srwatson}
452239691Srwatson
453239691Srwatsonstatic video_switch_t terasic_mtl_vidsw = {
454239691Srwatson	.probe =			terasic_mtl_vidsw_probe,
455239691Srwatson	.init =				terasic_mtl_vidsw_init,
456239691Srwatson	.get_info =			terasic_mtl_vidsw_get_info,
457239691Srwatson	.query_mode =			terasic_mtl_vidsw_query_mode,
458239691Srwatson	.set_mode =			terasic_mtl_vidsw_set_mode,
459239691Srwatson	.save_font =			terasic_mtl_vidsw_save_font,
460239691Srwatson	.load_font =			terasic_mtl_vidsw_load_font,
461239691Srwatson	.show_font =			terasic_mtl_vidsw_show_font,
462239691Srwatson	.save_palette =			terasic_mtl_vidsw_save_palette,
463239691Srwatson	.load_palette =			terasic_mtl_vidsw_load_palette,
464239691Srwatson	.set_border =			terasic_mtl_vidsw_set_border,
465239691Srwatson	.save_state =			terasic_mtl_vidsw_save_state,
466239691Srwatson	.load_state =			terasic_mtl_vidsw_load_state,
467239691Srwatson	.set_win_org =			terasic_mtl_vidsw_set_win_org,
468239691Srwatson	.read_hw_cursor =		terasic_mtl_vidsw_read_hw_cursor,
469239691Srwatson	.set_hw_cursor =		terasic_mtl_vidsw_set_hw_cursor,
470239691Srwatson	.set_hw_cursor_shape =		terasic_mtl_vidsw_set_hw_cursor_shape,
471239691Srwatson	.blank_display =		terasic_mtl_vidsw_blank_display,
472239691Srwatson	.mmap =				terasic_mtl_vidsw_mmap,
473239691Srwatson	.ioctl =			terasic_mtl_vidsw_ioctl,
474239691Srwatson	.clear =			terasic_mtl_vidsw_clear,
475239691Srwatson	.fill_rect =			terasic_mtl_vidsw_fill_rect,
476239691Srwatson	.bitblt =			terasic_mtl_vidsw_bitblt,
477239691Srwatson	.diag =				terasic_mtl_vidsw_diag,
478239691Srwatson	.save_cursor_palette =		terasic_mtl_vidsw_save_cursor_palette,
479239691Srwatson	.load_cursor_palette =		terasic_mtl_vidsw_load_cursor_palette,
480239691Srwatson	.copy =				terasic_mtl_vidsw_copy,
481239691Srwatson	.putp =				terasic_mtl_vidsw_putp,
482239691Srwatson	.putc =				terasic_mtl_vidsw_putc,
483239691Srwatson	.puts =				terasic_mtl_vidsw_puts,
484239691Srwatson	.putm =				terasic_mtl_vidsw_putm,
485239691Srwatson};
486239691SrwatsonVIDEO_DRIVER(terasic_mtl_syscons, terasic_mtl_vidsw,
487239691Srwatson    terasic_mtl_syscons_configure);
488239691Srwatsonextern sc_rndr_sw_t txtrndrsw;
489239691SrwatsonRENDERER(terasic_mtl_syscons, 0, txtrndrsw, gfb_set);
490239691SrwatsonRENDERER_MODULE(terasic_mtl_syscons, gfb_set);
491