1269601Snwhitehorn/*-
2269601Snwhitehorn * Copyright (c) 2014 Nathan Whitehorn
3269601Snwhitehorn * All rights reserved.
4269601Snwhitehorn *
5269601Snwhitehorn * Redistribution and use in source and binary forms, with or without
6269601Snwhitehorn * modification, are permitted provided that the following conditions
7269601Snwhitehorn * are met:
8269601Snwhitehorn * 1. Redistributions of source code must retain the above copyright
9269601Snwhitehorn *    notice, this list of conditions and the following disclaimer.
10269601Snwhitehorn * 2. Redistributions in binary form must reproduce the above copyright
11269601Snwhitehorn *    notice, this list of conditions and the following disclaimer in the
12269601Snwhitehorn *    documentation and/or other materials provided with the distribution.
13269601Snwhitehorn *
14269601Snwhitehorn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15269601Snwhitehorn * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16269601Snwhitehorn * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17269601Snwhitehorn * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18269601Snwhitehorn * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19269601Snwhitehorn * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20269601Snwhitehorn * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21269601Snwhitehorn * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22269601Snwhitehorn * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23269601Snwhitehorn * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24269601Snwhitehorn * SUCH DAMAGE.
25269601Snwhitehorn */
26269601Snwhitehorn
27269601Snwhitehorn#include <sys/cdefs.h>
28269601Snwhitehorn__FBSDID("$FreeBSD: releng/10.2/sys/dev/fb/creator_vt.c 271128 2014-09-04 20:18:08Z emaste $");
29269601Snwhitehorn
30269601Snwhitehorn#include <sys/param.h>
31269601Snwhitehorn#include <sys/kernel.h>
32269601Snwhitehorn#include <sys/systm.h>
33269601Snwhitehorn#include <sys/fbio.h>
34269601Snwhitehorn
35269601Snwhitehorn#include <dev/vt/vt.h>
36269601Snwhitehorn#include <dev/vt/hw/fb/vt_fb.h>
37269601Snwhitehorn#include <dev/vt/colors/vt_termcolors.h>
38269601Snwhitehorn
39269601Snwhitehorn#include <machine/bus.h>
40269601Snwhitehorn#include <machine/bus_private.h>
41269601Snwhitehorn
42269601Snwhitehorn#include <dev/ofw/openfirm.h>
43269601Snwhitehorn#include "creatorreg.h"
44269601Snwhitehorn
45269601Snwhitehornstatic vd_probe_t	creatorfb_probe;
46269601Snwhitehornstatic vd_init_t	creatorfb_init;
47269601Snwhitehornstatic vd_blank_t	creatorfb_blank;
48271128Semastestatic vd_bitblt_text_t	creatorfb_bitblt_text;
49271128Semastestatic vd_bitblt_bmp_t	creatorfb_bitblt_bitmap;
50269601Snwhitehorn
51269601Snwhitehornstatic const struct vt_driver vt_creatorfb_driver = {
52269601Snwhitehorn	.vd_name	= "creatorfb",
53269601Snwhitehorn	.vd_probe	= creatorfb_probe,
54269601Snwhitehorn	.vd_init	= creatorfb_init,
55269601Snwhitehorn	.vd_blank	= creatorfb_blank,
56271128Semaste	.vd_bitblt_text	= creatorfb_bitblt_text,
57271128Semaste	.vd_bitblt_bmp	= creatorfb_bitblt_bitmap,
58269601Snwhitehorn	.vd_fb_ioctl	= vt_fb_ioctl,
59269601Snwhitehorn	.vd_fb_mmap	= vt_fb_mmap,
60269601Snwhitehorn	.vd_priority	= VD_PRIORITY_SPECIFIC
61269601Snwhitehorn};
62269601Snwhitehorn
63269601Snwhitehornstruct creatorfb_softc {
64269601Snwhitehorn	struct fb_info fb;
65269601Snwhitehorn	struct bus_space_tag memt[1];
66269601Snwhitehorn	bus_space_handle_t memh;
67269601Snwhitehorn};
68269601Snwhitehorn
69269601Snwhitehornstatic struct creatorfb_softc creatorfb_conssoftc;
70269601SnwhitehornVT_DRIVER_DECLARE(vt_creatorfb, vt_creatorfb_driver);
71269601Snwhitehorn
72269601Snwhitehornstatic int
73269601Snwhitehorncreatorfb_probe(struct vt_device *vd)
74269601Snwhitehorn{
75269601Snwhitehorn	phandle_t chosen, node;
76269601Snwhitehorn	ihandle_t stdout;
77269601Snwhitehorn	char type[64], name[64];
78269601Snwhitehorn
79269601Snwhitehorn	chosen = OF_finddevice("/chosen");
80269601Snwhitehorn	OF_getprop(chosen, "stdout", &stdout, sizeof(stdout));
81269601Snwhitehorn	node = OF_instance_to_package(stdout);
82269601Snwhitehorn	if (node == -1) {
83269601Snwhitehorn		/*
84269601Snwhitehorn		 * The "/chosen/stdout" does not exist try
85269601Snwhitehorn		 * using "screen" directly.
86269601Snwhitehorn		 */
87269601Snwhitehorn		node = OF_finddevice("screen");
88269601Snwhitehorn	}
89269601Snwhitehorn	OF_getprop(node, "device_type", type, sizeof(type));
90269601Snwhitehorn	if (strcmp(type, "display") != 0)
91269601Snwhitehorn		return (CN_DEAD);
92269601Snwhitehorn
93269601Snwhitehorn	OF_getprop(node, "name", name, sizeof(name));
94269601Snwhitehorn	if (strcmp(name, "SUNW,ffb") != 0 && strcmp(name, "SUNW,afb") != 0)
95269601Snwhitehorn		return (CN_DEAD);
96269601Snwhitehorn
97269601Snwhitehorn	/* Looks OK... */
98269601Snwhitehorn	return (CN_INTERNAL);
99269601Snwhitehorn}
100269601Snwhitehorn
101269601Snwhitehornstatic int
102269601Snwhitehorncreatorfb_init(struct vt_device *vd)
103269601Snwhitehorn{
104269601Snwhitehorn	struct creatorfb_softc *sc;
105269601Snwhitehorn	phandle_t chosen;
106269601Snwhitehorn	phandle_t node;
107269601Snwhitehorn	ihandle_t handle;
108269601Snwhitehorn	uint32_t height, width;
109269601Snwhitehorn	char type[64], name[64];
110269601Snwhitehorn	bus_addr_t phys;
111269601Snwhitehorn	int space;
112269601Snwhitehorn
113269601Snwhitehorn	/* Initialize softc */
114269601Snwhitehorn	vd->vd_softc = sc = &creatorfb_conssoftc;
115269601Snwhitehorn
116269601Snwhitehorn	chosen = OF_finddevice("/chosen");
117269601Snwhitehorn	OF_getprop(chosen, "stdout", &handle, sizeof(ihandle_t));
118269601Snwhitehorn	node = OF_instance_to_package(handle);
119269601Snwhitehorn	if (node == -1) {
120269601Snwhitehorn		/*
121269601Snwhitehorn		 * The "/chosen/stdout" does not exist try
122269601Snwhitehorn		 * using "screen" directly.
123269601Snwhitehorn		 */
124269601Snwhitehorn		node = OF_finddevice("screen");
125269601Snwhitehorn		handle = OF_open("screen");
126269601Snwhitehorn	}
127269601Snwhitehorn	OF_getprop(node, "device_type", type, sizeof(type));
128269601Snwhitehorn	if (strcmp(type, "display") != 0)
129269601Snwhitehorn		return (CN_DEAD);
130269601Snwhitehorn
131269601Snwhitehorn	OF_getprop(node, "name", name, sizeof(name));
132269601Snwhitehorn	if (strcmp(name, "SUNW,ffb") != 0 && strcmp(name, "SUNW,afb") != 0)
133269601Snwhitehorn		return (CN_DEAD);
134269601Snwhitehorn
135269601Snwhitehorn	/* Make sure we have needed properties */
136269601Snwhitehorn	if (OF_getproplen(node, "height") != sizeof(height) ||
137269601Snwhitehorn	    OF_getproplen(node, "width") != sizeof(width))
138269601Snwhitehorn		return (CN_DEAD);
139269601Snwhitehorn
140269601Snwhitehorn	OF_getprop(node, "height", &height, sizeof(height));
141269601Snwhitehorn	OF_getprop(node, "width", &width, sizeof(width));
142269601Snwhitehorn
143269601Snwhitehorn	sc->fb.fb_height = height;
144269601Snwhitehorn	sc->fb.fb_width = width;
145269601Snwhitehorn	sc->fb.fb_bpp = sc->fb.fb_depth = 32;
146269601Snwhitehorn	sc->fb.fb_stride = 8192; /* Fixed */
147269601Snwhitehorn	sc->fb.fb_size = sc->fb.fb_height * sc->fb.fb_stride;
148269601Snwhitehorn
149269601Snwhitehorn	/* Map linear framebuffer */
150269601Snwhitehorn	if (OF_decode_addr(node, FFB_DFB24, &space, &phys) != 0)
151269601Snwhitehorn		return (CN_DEAD);
152269601Snwhitehorn	sc->fb.fb_pbase = phys;
153269601Snwhitehorn	sc->memh = sparc64_fake_bustag(space, phys, &sc->memt[0]);
154269601Snwhitehorn
155269601Snwhitehorn	/* 32-bit VGA palette */
156271112Semaste	vt_generate_cons_palette(sc->fb.fb_cmap, COLOR_FORMAT_RGB,
157271112Semaste	    255, 0, 255, 8, 255, 16);
158271112Semaste	sc->fb.fb_cmsize = 16;
159269601Snwhitehorn
160269601Snwhitehorn	vt_fb_init(vd);
161269601Snwhitehorn
162269601Snwhitehorn	return (CN_INTERNAL);
163269601Snwhitehorn}
164269601Snwhitehorn
165269601Snwhitehornstatic void
166269601Snwhitehorncreatorfb_blank(struct vt_device *vd, term_color_t color)
167269601Snwhitehorn{
168269601Snwhitehorn	struct creatorfb_softc *sc;
169269601Snwhitehorn	uint32_t c;
170269601Snwhitehorn	int i;
171269601Snwhitehorn
172269601Snwhitehorn	sc = vd->vd_softc;
173269601Snwhitehorn	c = sc->fb.fb_cmap[color];
174269601Snwhitehorn
175269601Snwhitehorn	for (i = 0; i < sc->fb.fb_height; i++)
176269601Snwhitehorn		bus_space_set_region_4(sc->memt, sc->memh, i*sc->fb.fb_stride,
177269601Snwhitehorn		    c, sc->fb.fb_width);
178269601Snwhitehorn}
179269601Snwhitehorn
180269601Snwhitehornstatic void
181271128Semastecreatorfb_bitblt_bitmap(struct vt_device *vd, const struct vt_window *vw,
182271128Semaste    const uint8_t *pattern, const uint8_t *mask,
183271128Semaste    unsigned int width, unsigned int height,
184271128Semaste    unsigned int x, unsigned int y, term_color_t fg, term_color_t bg)
185269601Snwhitehorn{
186269601Snwhitehorn	struct creatorfb_softc *sc = vd->vd_softc;
187269601Snwhitehorn	u_long line;
188269601Snwhitehorn	uint32_t fgc, bgc;
189271128Semaste	int c, l;
190269601Snwhitehorn	uint8_t b, m;
191269601Snwhitehorn
192269601Snwhitehorn	fgc = sc->fb.fb_cmap[fg];
193269601Snwhitehorn	bgc = sc->fb.fb_cmap[bg];
194269601Snwhitehorn	b = m = 0;
195269601Snwhitehorn
196271128Semaste	line = (sc->fb.fb_stride * y) + 4*x;
197271128Semaste	for (l = 0;
198271128Semaste	    l < height && y + l < vw->vw_draw_area.tr_end.tp_row;
199271128Semaste	    l++) {
200271128Semaste		for (c = 0;
201271128Semaste		    c < width && x + c < vw->vw_draw_area.tr_end.tp_col;
202271128Semaste		    c++) {
203269601Snwhitehorn			if (c % 8 == 0)
204271128Semaste				b = *pattern++;
205269601Snwhitehorn			else
206269601Snwhitehorn				b <<= 1;
207269601Snwhitehorn			if (mask != NULL) {
208269601Snwhitehorn				if (c % 8 == 0)
209269601Snwhitehorn					m = *mask++;
210269601Snwhitehorn				else
211269601Snwhitehorn					m <<= 1;
212269601Snwhitehorn				/* Skip pixel write if mask not set. */
213269601Snwhitehorn				if ((m & 0x80) == 0)
214269601Snwhitehorn					continue;
215269601Snwhitehorn			}
216269601Snwhitehorn			bus_space_write_4(sc->memt, sc->memh, line + 4*c,
217269601Snwhitehorn			    (b & 0x80) ? fgc : bgc);
218269601Snwhitehorn		}
219269601Snwhitehorn		line += sc->fb.fb_stride;
220269601Snwhitehorn	}
221269601Snwhitehorn}
222269601Snwhitehorn
223271128Semastevoid
224271128Semastecreatorfb_bitblt_text(struct vt_device *vd, const struct vt_window *vw,
225271128Semaste    const term_rect_t *area)
226271128Semaste{
227271128Semaste	unsigned int col, row, x, y;
228271128Semaste	struct vt_font *vf;
229271128Semaste	term_char_t c;
230271128Semaste	term_color_t fg, bg;
231271128Semaste	const uint8_t *pattern;
232271128Semaste
233271128Semaste	vf = vw->vw_font;
234271128Semaste
235271128Semaste	for (row = area->tr_begin.tp_row; row < area->tr_end.tp_row; ++row) {
236271128Semaste		for (col = area->tr_begin.tp_col; col < area->tr_end.tp_col;
237271128Semaste		    ++col) {
238271128Semaste			x = col * vf->vf_width +
239271128Semaste			    vw->vw_draw_area.tr_begin.tp_col;
240271128Semaste			y = row * vf->vf_height +
241271128Semaste			    vw->vw_draw_area.tr_begin.tp_row;
242271128Semaste
243271128Semaste			c = VTBUF_GET_FIELD(&vw->vw_buf, row, col);
244271128Semaste			pattern = vtfont_lookup(vf, c);
245271128Semaste			vt_determine_colors(c,
246271128Semaste			    VTBUF_ISCURSOR(&vw->vw_buf, row, col), &fg, &bg);
247271128Semaste
248271128Semaste			creatorfb_bitblt_bitmap(vd, vw,
249271128Semaste			    pattern, NULL, vf->vf_width, vf->vf_height,
250271128Semaste			    x, y, fg, bg);
251271128Semaste		}
252271128Semaste	}
253271128Semaste
254271128Semaste#ifndef SC_NO_CUTPASTE
255271128Semaste	if (!vd->vd_mshown)
256271128Semaste		return;
257271128Semaste
258271128Semaste	term_rect_t drawn_area;
259271128Semaste
260271128Semaste	drawn_area.tr_begin.tp_col = area->tr_begin.tp_col * vf->vf_width;
261271128Semaste	drawn_area.tr_begin.tp_row = area->tr_begin.tp_row * vf->vf_height;
262271128Semaste	drawn_area.tr_end.tp_col = area->tr_end.tp_col * vf->vf_width;
263271128Semaste	drawn_area.tr_end.tp_row = area->tr_end.tp_row * vf->vf_height;
264271128Semaste
265271128Semaste	if (vt_is_cursor_in_area(vd, &drawn_area)) {
266271128Semaste		creatorfb_bitblt_bitmap(vd, vw,
267271128Semaste		    vd->vd_mcursor->map, vd->vd_mcursor->mask,
268271128Semaste		    vd->vd_mcursor->width, vd->vd_mcursor->height,
269271128Semaste		    vd->vd_mx_drawn + vw->vw_draw_area.tr_begin.tp_col,
270271128Semaste		    vd->vd_my_drawn + vw->vw_draw_area.tr_begin.tp_row,
271271128Semaste		    vd->vd_mcursor_fg, vd->vd_mcursor_bg);
272271128Semaste	}
273271128Semaste#endif
274271128Semaste}
275