xref: /freebsd-12.1/sys/dev/fb/creator_vt.c (revision 84d623c6)
1 /*-
2  * Copyright (c) 2014 Nathan Whitehorn
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26 
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29 
30 #include <sys/param.h>
31 #include <sys/kernel.h>
32 #include <sys/systm.h>
33 #include <sys/fbio.h>
34 
35 #include <dev/vt/vt.h>
36 #include <dev/vt/hw/fb/vt_fb.h>
37 #include <dev/vt/colors/vt_termcolors.h>
38 
39 #include <machine/bus.h>
40 #include <machine/bus_private.h>
41 
42 #include <dev/ofw/openfirm.h>
43 #include "creatorreg.h"
44 
45 static vd_probe_t	creatorfb_probe;
46 static vd_init_t	creatorfb_init;
47 static vd_blank_t	creatorfb_blank;
48 static vd_bitblt_text_t	creatorfb_bitblt_text;
49 static vd_bitblt_bmp_t	creatorfb_bitblt_bitmap;
50 
51 static const struct vt_driver vt_creatorfb_driver = {
52 	.vd_name	= "creatorfb",
53 	.vd_probe	= creatorfb_probe,
54 	.vd_init	= creatorfb_init,
55 	.vd_blank	= creatorfb_blank,
56 	.vd_bitblt_text	= creatorfb_bitblt_text,
57 	.vd_bitblt_bmp	= creatorfb_bitblt_bitmap,
58 	.vd_fb_ioctl	= vt_fb_ioctl,
59 	.vd_fb_mmap	= vt_fb_mmap,
60 	.vd_priority	= VD_PRIORITY_SPECIFIC
61 };
62 
63 struct creatorfb_softc {
64 	struct fb_info fb;
65 	struct bus_space_tag memt[1];
66 	bus_space_handle_t memh;
67 };
68 
69 static struct creatorfb_softc creatorfb_conssoftc;
70 VT_DRIVER_DECLARE(vt_creatorfb, vt_creatorfb_driver);
71 
72 static int
creatorfb_probe(struct vt_device * vd)73 creatorfb_probe(struct vt_device *vd)
74 {
75 	phandle_t chosen, node;
76 	ihandle_t stdout;
77 	char type[64], name[64];
78 
79 	chosen = OF_finddevice("/chosen");
80 	OF_getprop(chosen, "stdout", &stdout, sizeof(stdout));
81 	node = OF_instance_to_package(stdout);
82 	if (node == -1) {
83 		/*
84 		 * The "/chosen/stdout" does not exist try
85 		 * using "screen" directly.
86 		 */
87 		node = OF_finddevice("screen");
88 	}
89 	OF_getprop(node, "device_type", type, sizeof(type));
90 	if (strcmp(type, "display") != 0)
91 		return (CN_DEAD);
92 
93 	OF_getprop(node, "name", name, sizeof(name));
94 	if (strcmp(name, "SUNW,ffb") != 0 && strcmp(name, "SUNW,afb") != 0)
95 		return (CN_DEAD);
96 
97 	/* Looks OK... */
98 	return (CN_INTERNAL);
99 }
100 
101 static int
creatorfb_init(struct vt_device * vd)102 creatorfb_init(struct vt_device *vd)
103 {
104 	struct creatorfb_softc *sc;
105 	phandle_t chosen;
106 	phandle_t node;
107 	ihandle_t handle;
108 	uint32_t height, width;
109 	char type[64], name[64];
110 	bus_addr_t phys;
111 	int space;
112 
113 	/* Initialize softc */
114 	vd->vd_softc = sc = &creatorfb_conssoftc;
115 
116 	chosen = OF_finddevice("/chosen");
117 	OF_getprop(chosen, "stdout", &handle, sizeof(ihandle_t));
118 	node = OF_instance_to_package(handle);
119 	if (node == -1) {
120 		/*
121 		 * The "/chosen/stdout" does not exist try
122 		 * using "screen" directly.
123 		 */
124 		node = OF_finddevice("screen");
125 		handle = OF_open("screen");
126 	}
127 	OF_getprop(node, "device_type", type, sizeof(type));
128 	if (strcmp(type, "display") != 0)
129 		return (CN_DEAD);
130 
131 	OF_getprop(node, "name", name, sizeof(name));
132 	if (strcmp(name, "SUNW,ffb") != 0 && strcmp(name, "SUNW,afb") != 0)
133 		return (CN_DEAD);
134 
135 	/* Make sure we have needed properties */
136 	if (OF_getproplen(node, "height") != sizeof(height) ||
137 	    OF_getproplen(node, "width") != sizeof(width))
138 		return (CN_DEAD);
139 
140 	OF_getprop(node, "height", &height, sizeof(height));
141 	OF_getprop(node, "width", &width, sizeof(width));
142 
143 	sc->fb.fb_height = height;
144 	sc->fb.fb_width = width;
145 	sc->fb.fb_bpp = sc->fb.fb_depth = 32;
146 	sc->fb.fb_stride = 8192; /* Fixed */
147 	sc->fb.fb_size = sc->fb.fb_height * sc->fb.fb_stride;
148 
149 	/* Map linear framebuffer */
150 	if (OF_decode_addr(node, FFB_DFB24, &space, &phys) != 0)
151 		return (CN_DEAD);
152 	sc->fb.fb_pbase = phys;
153 	sc->memh = sparc64_fake_bustag(space, phys, &sc->memt[0]);
154 
155 	/* 32-bit VGA palette */
156 	vt_generate_cons_palette(sc->fb.fb_cmap, COLOR_FORMAT_RGB,
157 	    255, 0, 255, 8, 255, 16);
158 	sc->fb.fb_cmsize = 16;
159 
160 	vt_fb_init(vd);
161 
162 	return (CN_INTERNAL);
163 }
164 
165 static void
creatorfb_blank(struct vt_device * vd,term_color_t color)166 creatorfb_blank(struct vt_device *vd, term_color_t color)
167 {
168 	struct creatorfb_softc *sc;
169 	uint32_t c;
170 	int i;
171 
172 	sc = vd->vd_softc;
173 	c = sc->fb.fb_cmap[color];
174 
175 	for (i = 0; i < sc->fb.fb_height; i++)
176 		bus_space_set_region_4(sc->memt, sc->memh, i*sc->fb.fb_stride,
177 		    c, sc->fb.fb_width);
178 }
179 
180 static void
creatorfb_bitblt_bitmap(struct vt_device * vd,const struct vt_window * vw,const uint8_t * pattern,const uint8_t * mask,unsigned int width,unsigned int height,unsigned int x,unsigned int y,term_color_t fg,term_color_t bg)181 creatorfb_bitblt_bitmap(struct vt_device *vd, const struct vt_window *vw,
182     const uint8_t *pattern, const uint8_t *mask,
183     unsigned int width, unsigned int height,
184     unsigned int x, unsigned int y, term_color_t fg, term_color_t bg)
185 {
186 	struct creatorfb_softc *sc = vd->vd_softc;
187 	u_long line;
188 	uint32_t fgc, bgc;
189 	int c, l;
190 	uint8_t b, m;
191 
192 	fgc = sc->fb.fb_cmap[fg];
193 	bgc = sc->fb.fb_cmap[bg];
194 	b = m = 0;
195 
196 	line = (sc->fb.fb_stride * y) + 4*x;
197 	for (l = 0;
198 	    l < height && y + l < vw->vw_draw_area.tr_end.tp_row;
199 	    l++) {
200 		for (c = 0;
201 		    c < width && x + c < vw->vw_draw_area.tr_end.tp_col;
202 		    c++) {
203 			if (c % 8 == 0)
204 				b = *pattern++;
205 			else
206 				b <<= 1;
207 			if (mask != NULL) {
208 				if (c % 8 == 0)
209 					m = *mask++;
210 				else
211 					m <<= 1;
212 				/* Skip pixel write if mask not set. */
213 				if ((m & 0x80) == 0)
214 					continue;
215 			}
216 			bus_space_write_4(sc->memt, sc->memh, line + 4*c,
217 			    (b & 0x80) ? fgc : bgc);
218 		}
219 		line += sc->fb.fb_stride;
220 	}
221 }
222 
223 void
creatorfb_bitblt_text(struct vt_device * vd,const struct vt_window * vw,const term_rect_t * area)224 creatorfb_bitblt_text(struct vt_device *vd, const struct vt_window *vw,
225     const term_rect_t *area)
226 {
227 	unsigned int col, row, x, y;
228 	struct vt_font *vf;
229 	term_char_t c;
230 	term_color_t fg, bg;
231 	const uint8_t *pattern;
232 
233 	vf = vw->vw_font;
234 
235 	for (row = area->tr_begin.tp_row; row < area->tr_end.tp_row; ++row) {
236 		for (col = area->tr_begin.tp_col; col < area->tr_end.tp_col;
237 		    ++col) {
238 			x = col * vf->vf_width +
239 			    vw->vw_draw_area.tr_begin.tp_col;
240 			y = row * vf->vf_height +
241 			    vw->vw_draw_area.tr_begin.tp_row;
242 
243 			c = VTBUF_GET_FIELD(&vw->vw_buf, row, col);
244 			pattern = vtfont_lookup(vf, c);
245 			vt_determine_colors(c,
246 			    VTBUF_ISCURSOR(&vw->vw_buf, row, col), &fg, &bg);
247 
248 			creatorfb_bitblt_bitmap(vd, vw,
249 			    pattern, NULL, vf->vf_width, vf->vf_height,
250 			    x, y, fg, bg);
251 		}
252 	}
253 
254 #ifndef SC_NO_CUTPASTE
255 	if (!vd->vd_mshown)
256 		return;
257 
258 	term_rect_t drawn_area;
259 
260 	drawn_area.tr_begin.tp_col = area->tr_begin.tp_col * vf->vf_width;
261 	drawn_area.tr_begin.tp_row = area->tr_begin.tp_row * vf->vf_height;
262 	drawn_area.tr_end.tp_col = area->tr_end.tp_col * vf->vf_width;
263 	drawn_area.tr_end.tp_row = area->tr_end.tp_row * vf->vf_height;
264 
265 	if (vt_is_cursor_in_area(vd, &drawn_area)) {
266 		creatorfb_bitblt_bitmap(vd, vw,
267 		    vd->vd_mcursor->map, vd->vd_mcursor->mask,
268 		    vd->vd_mcursor->width, vd->vd_mcursor->height,
269 		    vd->vd_mx_drawn + vw->vw_draw_area.tr_begin.tp_col,
270 		    vd->vd_my_drawn + vw->vw_draw_area.tr_begin.tp_row,
271 		    vd->vd_mcursor_fg, vd->vd_mcursor_bg);
272 	}
273 #endif
274 }
275