creator_vt.c revision 271120
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: stable/10/sys/dev/fb/creator_vt.c 271120 2014-09-04 19:13:07Z emaste $");
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
45static vd_probe_t	creatorfb_probe;
46static vd_init_t	creatorfb_init;
47static vd_blank_t	creatorfb_blank;
48static vd_bitbltchr_t	creatorfb_bitbltchr;
49
50static const struct vt_driver vt_creatorfb_driver = {
51	.vd_name	= "creatorfb",
52	.vd_probe	= creatorfb_probe,
53	.vd_init	= creatorfb_init,
54	.vd_blank	= creatorfb_blank,
55	.vd_bitbltchr	= creatorfb_bitbltchr,
56	.vd_fb_ioctl	= vt_fb_ioctl,
57	.vd_fb_mmap	= vt_fb_mmap,
58	.vd_priority	= VD_PRIORITY_SPECIFIC
59};
60
61struct creatorfb_softc {
62	struct fb_info fb;
63	struct bus_space_tag memt[1];
64	bus_space_handle_t memh;
65};
66
67static struct creatorfb_softc creatorfb_conssoftc;
68VT_DRIVER_DECLARE(vt_creatorfb, vt_creatorfb_driver);
69
70static int
71creatorfb_probe(struct vt_device *vd)
72{
73	phandle_t chosen, node;
74	ihandle_t stdout;
75	char type[64], name[64];
76
77	chosen = OF_finddevice("/chosen");
78	OF_getprop(chosen, "stdout", &stdout, sizeof(stdout));
79	node = OF_instance_to_package(stdout);
80	if (node == -1) {
81		/*
82		 * The "/chosen/stdout" does not exist try
83		 * using "screen" directly.
84		 */
85		node = OF_finddevice("screen");
86	}
87	OF_getprop(node, "device_type", type, sizeof(type));
88	if (strcmp(type, "display") != 0)
89		return (CN_DEAD);
90
91	OF_getprop(node, "name", name, sizeof(name));
92	if (strcmp(name, "SUNW,ffb") != 0 && strcmp(name, "SUNW,afb") != 0)
93		return (CN_DEAD);
94
95	/* Looks OK... */
96	return (CN_INTERNAL);
97}
98
99static int
100creatorfb_init(struct vt_device *vd)
101{
102	struct creatorfb_softc *sc;
103	phandle_t chosen;
104	phandle_t node;
105	ihandle_t handle;
106	uint32_t height, width;
107	char type[64], name[64];
108	bus_addr_t phys;
109	int space;
110
111	/* Initialize softc */
112	vd->vd_softc = sc = &creatorfb_conssoftc;
113
114	chosen = OF_finddevice("/chosen");
115	OF_getprop(chosen, "stdout", &handle, sizeof(ihandle_t));
116	node = OF_instance_to_package(handle);
117	if (node == -1) {
118		/*
119		 * The "/chosen/stdout" does not exist try
120		 * using "screen" directly.
121		 */
122		node = OF_finddevice("screen");
123		handle = OF_open("screen");
124	}
125	OF_getprop(node, "device_type", type, sizeof(type));
126	if (strcmp(type, "display") != 0)
127		return (CN_DEAD);
128
129	OF_getprop(node, "name", name, sizeof(name));
130	if (strcmp(name, "SUNW,ffb") != 0 && strcmp(name, "SUNW,afb") != 0)
131		return (CN_DEAD);
132
133	/* Make sure we have needed properties */
134	if (OF_getproplen(node, "height") != sizeof(height) ||
135	    OF_getproplen(node, "width") != sizeof(width))
136		return (CN_DEAD);
137
138	OF_getprop(node, "height", &height, sizeof(height));
139	OF_getprop(node, "width", &width, sizeof(width));
140
141	sc->fb.fb_height = height;
142	sc->fb.fb_width = width;
143	sc->fb.fb_bpp = sc->fb.fb_depth = 32;
144	sc->fb.fb_stride = 8192; /* Fixed */
145	sc->fb.fb_size = sc->fb.fb_height * sc->fb.fb_stride;
146
147	/* Map linear framebuffer */
148	if (OF_decode_addr(node, FFB_DFB24, &space, &phys) != 0)
149		return (CN_DEAD);
150	sc->fb.fb_pbase = phys;
151	sc->memh = sparc64_fake_bustag(space, phys, &sc->memt[0]);
152
153	/* 32-bit VGA palette */
154	vt_generate_cons_palette(sc->fb.fb_cmap, COLOR_FORMAT_RGB,
155	    255, 0, 255, 8, 255, 16);
156	sc->fb.fb_cmsize = 16;
157
158	vt_fb_init(vd);
159
160	return (CN_INTERNAL);
161}
162
163static void
164creatorfb_blank(struct vt_device *vd, term_color_t color)
165{
166	struct creatorfb_softc *sc;
167	uint32_t c;
168	int i;
169
170	sc = vd->vd_softc;
171	c = sc->fb.fb_cmap[color];
172
173	for (i = 0; i < sc->fb.fb_height; i++)
174		bus_space_set_region_4(sc->memt, sc->memh, i*sc->fb.fb_stride,
175		    c, sc->fb.fb_width);
176}
177
178static void
179creatorfb_bitbltchr(struct vt_device *vd, const uint8_t *src,
180    const uint8_t *mask, int bpl, vt_axis_t top, vt_axis_t left,
181    unsigned int width, unsigned int height, term_color_t fg, term_color_t bg)
182{
183	struct creatorfb_softc *sc = vd->vd_softc;
184	u_long line;
185	uint32_t fgc, bgc;
186	int c;
187	uint8_t b, m;
188
189	fgc = sc->fb.fb_cmap[fg];
190	bgc = sc->fb.fb_cmap[bg];
191	b = m = 0;
192
193	/* Don't try to put off screen pixels */
194	if (((left + width) > vd->vd_width) || ((top + height) >
195	    vd->vd_height))
196		return;
197
198	line = (sc->fb.fb_stride * top) + 4*left;
199	for (; height > 0; height--) {
200		for (c = 0; c < width; c++) {
201			if (c % 8 == 0)
202				b = *src++;
203			else
204				b <<= 1;
205			if (mask != NULL) {
206				if (c % 8 == 0)
207					m = *mask++;
208				else
209					m <<= 1;
210				/* Skip pixel write if mask not set. */
211				if ((m & 0x80) == 0)
212					continue;
213			}
214			bus_space_write_4(sc->memt, sc->memh, line + 4*c,
215			    (b & 0x80) ? fgc : bgc);
216		}
217		line += sc->fb.fb_stride;
218	}
219}
220
221