xref: /freebsd/sys/dev/vt/hw/simplefb/simplefb.c (revision b93028d8cd3aafc883b5f0ecec65a8a2a30af7f3)
1d5035d91SAndrew Turner /*-
24d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
3d5035d91SAndrew Turner  *
4d5035d91SAndrew Turner  * Copyright (c) 2014 The FreeBSD Foundation
5d5035d91SAndrew Turner  * Copyright (c) 2021 Andrew Turner
6d5035d91SAndrew Turner  *
7d5035d91SAndrew Turner  * Portions of this software was developed by Aleksandr Rybalko under
8d5035d91SAndrew Turner  * sponsorship from the FreeBSD Foundation.
9d5035d91SAndrew Turner  *
10d5035d91SAndrew Turner  * Redistribution and use in source and binary forms, with or without
11d5035d91SAndrew Turner  * modification, are permitted provided that the following conditions
12d5035d91SAndrew Turner  * are met:
13d5035d91SAndrew Turner  * 1. Redistributions of source code must retain the above copyright
14d5035d91SAndrew Turner  *    notice, this list of conditions and the following disclaimer.
15d5035d91SAndrew Turner  * 2. Redistributions in binary form must reproduce the above copyright
16d5035d91SAndrew Turner  *    notice, this list of conditions and the following disclaimer in the
17d5035d91SAndrew Turner  *    documentation and/or other materials provided with the distribution.
18d5035d91SAndrew Turner  *
19d5035d91SAndrew Turner  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20d5035d91SAndrew Turner  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21d5035d91SAndrew Turner  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22d5035d91SAndrew Turner  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23d5035d91SAndrew Turner  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24d5035d91SAndrew Turner  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25d5035d91SAndrew Turner  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26d5035d91SAndrew Turner  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27d5035d91SAndrew Turner  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28d5035d91SAndrew Turner  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29d5035d91SAndrew Turner  * SUCH DAMAGE.
30d5035d91SAndrew Turner  */
31d5035d91SAndrew Turner 
32d5035d91SAndrew Turner #include <sys/param.h>
33d5035d91SAndrew Turner #include <sys/systm.h>
34d5035d91SAndrew Turner #include <sys/kernel.h>
35d5035d91SAndrew Turner #include <sys/fbio.h>
36d5035d91SAndrew Turner 
37d5035d91SAndrew Turner #include <vm/vm.h>
38d5035d91SAndrew Turner #include <vm/pmap.h>
39d5035d91SAndrew Turner 
40d5035d91SAndrew Turner #include <dev/vt/vt.h>
41d5035d91SAndrew Turner #include <dev/vt/hw/fb/vt_fb.h>
42d5035d91SAndrew Turner #include <dev/vt/colors/vt_termcolors.h>
43d5035d91SAndrew Turner 
44d5035d91SAndrew Turner #include <dev/ofw/openfirm.h>
45d5035d91SAndrew Turner #include <dev/ofw/ofw_bus.h>
46d5035d91SAndrew Turner #include <dev/ofw/ofw_subr.h>
47d5035d91SAndrew Turner #include <dev/ofw/ofw_bus_subr.h>
48d5035d91SAndrew Turner 
49d5035d91SAndrew Turner static vd_init_t vt_simplefb_init;
50d5035d91SAndrew Turner static vd_fini_t vt_simplefb_fini;
51d5035d91SAndrew Turner static vd_probe_t vt_simplefb_probe;
52*b93028d8SEmmanuel Vadot static vd_bitblt_argb_t	vt_simplefb_bitblt_argb;
53d5035d91SAndrew Turner 
54d5035d91SAndrew Turner static struct vt_driver vt_simplefb_driver = {
55d5035d91SAndrew Turner 	.vd_name = "simplefb",
56d5035d91SAndrew Turner 	.vd_probe = vt_simplefb_probe,
57d5035d91SAndrew Turner 	.vd_init = vt_simplefb_init,
58d5035d91SAndrew Turner 	.vd_fini = vt_simplefb_fini,
59d5035d91SAndrew Turner 	.vd_blank = vt_fb_blank,
60d5035d91SAndrew Turner 	.vd_bitblt_text = vt_fb_bitblt_text,
61d5035d91SAndrew Turner 	.vd_invalidate_text = vt_fb_invalidate_text,
62d5035d91SAndrew Turner 	.vd_bitblt_bmp = vt_fb_bitblt_bitmap,
63*b93028d8SEmmanuel Vadot 	.vd_bitblt_argb	= vt_simplefb_bitblt_argb,
64d5035d91SAndrew Turner 	.vd_drawrect = vt_fb_drawrect,
65d5035d91SAndrew Turner 	.vd_setpixel = vt_fb_setpixel,
66d5035d91SAndrew Turner 	.vd_fb_ioctl = vt_fb_ioctl,
67d5035d91SAndrew Turner 	.vd_fb_mmap = vt_fb_mmap,
68d5035d91SAndrew Turner 	.vd_suspend = vt_suspend,
69d5035d91SAndrew Turner 	.vd_resume = vt_resume,
70d5035d91SAndrew Turner 	/* Better than efifb, but still generic driver. */
71d5035d91SAndrew Turner 	.vd_priority = VD_PRIORITY_GENERIC + 2,
72d5035d91SAndrew Turner };
73d5035d91SAndrew Turner 
74d5035d91SAndrew Turner struct {
75d5035d91SAndrew Turner 	const char *name;
76d5035d91SAndrew Turner 	int rbits, rshift;
77d5035d91SAndrew Turner 	int gbits, gshift;
78d5035d91SAndrew Turner 	int bbits, bshift;
79d5035d91SAndrew Turner 	int depth;
80d5035d91SAndrew Turner 	enum vt_color_format format;
81d5035d91SAndrew Turner } simplefb_formats[] = {
82d5035d91SAndrew Turner 	{
83d5035d91SAndrew Turner 		.name = "r5g6b5",
84d5035d91SAndrew Turner 		.rbits = 5, .rshift = 11,
85d5035d91SAndrew Turner 		.gbits = 6, .gshift = 5,
86d5035d91SAndrew Turner 		.bbits = 5, .bshift = 0,
87d5035d91SAndrew Turner 		.depth = 16, .format = COLOR_FORMAT_RGB,
88d5035d91SAndrew Turner 	},
89d5035d91SAndrew Turner 	{
90d5035d91SAndrew Turner 		.name = "r8g8b8",
91d5035d91SAndrew Turner 		.rbits = 8, .rshift = 16,
92d5035d91SAndrew Turner 		.gbits = 8, .gshift = 8,
93d5035d91SAndrew Turner 		.bbits = 8, .bshift = 0,
94d5035d91SAndrew Turner 		.depth = 24, .format = COLOR_FORMAT_RGB,
95d5035d91SAndrew Turner 	},
96d5035d91SAndrew Turner 	{
97d5035d91SAndrew Turner 		.name = "a8r8g8b8",
98d5035d91SAndrew Turner 		.rbits = 8, .rshift = 16,
99d5035d91SAndrew Turner 		.gbits = 8, .gshift = 8,
100d5035d91SAndrew Turner 		.bbits = 8, .bshift = 0,
101d5035d91SAndrew Turner 		.depth = 32, .format = COLOR_FORMAT_RGB,
102d5035d91SAndrew Turner 	},
103d5035d91SAndrew Turner 	{
104d5035d91SAndrew Turner 		.name = "x8r8g8b8",
105d5035d91SAndrew Turner 		.rbits = 8, .rshift = 16,
106d5035d91SAndrew Turner 		.gbits = 8, .gshift = 8,
107d5035d91SAndrew Turner 		.bbits = 8, .bshift = 0,
108d5035d91SAndrew Turner 		.depth = 32, .format = COLOR_FORMAT_RGB,
109d5035d91SAndrew Turner 	},
110d5035d91SAndrew Turner 	{
111d5035d91SAndrew Turner 		.name = "x2r10g10b10",
112d5035d91SAndrew Turner 		.rbits = 10, .rshift = 20,
113d5035d91SAndrew Turner 		.gbits = 10, .gshift = 10,
114d5035d91SAndrew Turner 		.bbits = 10, .bshift = 0,
115d5035d91SAndrew Turner 		.depth = 32, .format = COLOR_FORMAT_RGB,
116d5035d91SAndrew Turner 	},
117d5035d91SAndrew Turner };
118d5035d91SAndrew Turner 
119d5035d91SAndrew Turner static struct fb_info local_info;
120d5035d91SAndrew Turner VT_DRIVER_DECLARE(vt_simplefb, vt_simplefb_driver);
121d5035d91SAndrew Turner 
122d5035d91SAndrew Turner static bool
123d5035d91SAndrew Turner vt_simplefb_node(phandle_t *nodep)
124d5035d91SAndrew Turner {
125d5035d91SAndrew Turner 	phandle_t chosen, node;
126d5035d91SAndrew Turner 
127d5035d91SAndrew Turner 	chosen = OF_finddevice("/chosen");
128d5035d91SAndrew Turner 	if (chosen == -1)
129d5035d91SAndrew Turner 		return (false);
130d5035d91SAndrew Turner 
131d5035d91SAndrew Turner 	for (node = OF_child(chosen); node != 0; node = OF_peer(node)) {
132d5035d91SAndrew Turner 		if (ofw_bus_node_is_compatible(node, "simple-framebuffer"))
133d5035d91SAndrew Turner 			break;
134d5035d91SAndrew Turner 	}
135d5035d91SAndrew Turner 	if (node == 0)
136d5035d91SAndrew Turner 		return (false);
137d5035d91SAndrew Turner 
138d5035d91SAndrew Turner 	if (nodep != NULL)
139d5035d91SAndrew Turner 		*nodep = node;
140d5035d91SAndrew Turner 
141d5035d91SAndrew Turner 	return (true);
142d5035d91SAndrew Turner }
143d5035d91SAndrew Turner 
144d5035d91SAndrew Turner static int
145d5035d91SAndrew Turner vt_simplefb_probe(struct vt_device *vd)
146d5035d91SAndrew Turner {
147d5035d91SAndrew Turner 	int disabled;
148d5035d91SAndrew Turner 
149d5035d91SAndrew Turner 	disabled = 0;
150d5035d91SAndrew Turner 	TUNABLE_INT_FETCH("hw.syscons.disable", &disabled);
151d5035d91SAndrew Turner 	if (disabled != 0)
152d5035d91SAndrew Turner 		return (CN_DEAD);
153d5035d91SAndrew Turner 
154d5035d91SAndrew Turner 	if (!vt_simplefb_node(NULL))
155d5035d91SAndrew Turner 		return (CN_DEAD);
156d5035d91SAndrew Turner 
157d5035d91SAndrew Turner 	return (CN_INTERNAL);
158d5035d91SAndrew Turner }
159d5035d91SAndrew Turner 
160d5035d91SAndrew Turner static int
161d5035d91SAndrew Turner vt_simplefb_init(struct vt_device *vd)
162d5035d91SAndrew Turner {
163d5035d91SAndrew Turner 	char format[16];
164d5035d91SAndrew Turner 	pcell_t height, width, stride;
165d5035d91SAndrew Turner 	struct fb_info *sc;
166d5035d91SAndrew Turner 	phandle_t node;
167d5035d91SAndrew Turner 	bus_size_t size;
168d5035d91SAndrew Turner 	int error;
169d5035d91SAndrew Turner 
170d5035d91SAndrew Turner 	/* Initialize softc */
171d5035d91SAndrew Turner 	vd->vd_softc = sc = &local_info;
172d5035d91SAndrew Turner 
173d5035d91SAndrew Turner 	if (!vt_simplefb_node(&node))
174d5035d91SAndrew Turner 		return (CN_DEAD);
175d5035d91SAndrew Turner 
176d5035d91SAndrew Turner 	if (OF_getencprop(node, "height", &height, sizeof(height)) == -1 ||
177d5035d91SAndrew Turner 	    OF_getencprop(node, "width", &width, sizeof(width)) == -1 ||
178d5035d91SAndrew Turner 	    OF_getencprop(node, "stride", &stride, sizeof(stride)) == -1 ||
179d5035d91SAndrew Turner 	    OF_getprop(node, "format", format, sizeof(format)) == -1) {
180d5035d91SAndrew Turner 		return (CN_DEAD);
181d5035d91SAndrew Turner 	}
182d5035d91SAndrew Turner 
183d5035d91SAndrew Turner 	sc->fb_height = height;
184d5035d91SAndrew Turner 	sc->fb_width = width;
185d5035d91SAndrew Turner 	sc->fb_stride = stride;
186d5035d91SAndrew Turner 	sc->fb_cmsize = NCOLORS;
187d5035d91SAndrew Turner 
188d5035d91SAndrew Turner 	error = 1;
189d5035d91SAndrew Turner 	for (int i = 0; i < nitems(simplefb_formats); i++) {
190d5035d91SAndrew Turner 		if (strcmp(format, simplefb_formats[i].name) == 0) {
191d5035d91SAndrew Turner 			vt_config_cons_colors(sc,
192d5035d91SAndrew Turner 			    simplefb_formats[i].format,
193d5035d91SAndrew Turner 			    (1 << simplefb_formats[i].rbits) - 1,
194d5035d91SAndrew Turner 			    simplefb_formats[i].rshift,
195d5035d91SAndrew Turner 			    (1 << simplefb_formats[i].gbits) - 1,
196d5035d91SAndrew Turner 			    simplefb_formats[i].gshift,
197d5035d91SAndrew Turner 			    (1 << simplefb_formats[i].bbits) - 1,
198d5035d91SAndrew Turner 			    simplefb_formats[i].bshift);
199d5035d91SAndrew Turner 			sc->fb_depth = sc->fb_bpp = simplefb_formats[i].depth;
200d5035d91SAndrew Turner 			error = 0;
201d5035d91SAndrew Turner 			break;
202d5035d91SAndrew Turner 		}
203d5035d91SAndrew Turner 	}
204d5035d91SAndrew Turner 	if (error != 0)
205d5035d91SAndrew Turner 		return (CN_DEAD);
206d5035d91SAndrew Turner 
207d5035d91SAndrew Turner 	ofw_reg_to_paddr(node, 0, &sc->fb_pbase, &size, NULL);
208d5035d91SAndrew Turner 	sc->fb_vbase = (intptr_t)pmap_mapdev_attr(sc->fb_pbase,
209d5035d91SAndrew Turner 	    size, VM_MEMATTR_WRITE_COMBINING);
210d5035d91SAndrew Turner 	sc->fb_size = size;
211d5035d91SAndrew Turner 
212d5035d91SAndrew Turner 	vt_fb_init(vd);
213d5035d91SAndrew Turner 
214d5035d91SAndrew Turner 	return (CN_INTERNAL);
215d5035d91SAndrew Turner }
216d5035d91SAndrew Turner 
217d5035d91SAndrew Turner static void
218d5035d91SAndrew Turner vt_simplefb_fini(struct vt_device *vd, void *softc)
219d5035d91SAndrew Turner {
220d5035d91SAndrew Turner 	struct fb_info *sc;
221d5035d91SAndrew Turner 
222d5035d91SAndrew Turner 	sc = softc;
223d5035d91SAndrew Turner 	vt_fb_fini(vd, softc);
224d5035d91SAndrew Turner 	pmap_unmapdev((void *)sc->fb_vbase, sc->fb_size);
225d5035d91SAndrew Turner }
226*b93028d8SEmmanuel Vadot 
227*b93028d8SEmmanuel Vadot static int
228*b93028d8SEmmanuel Vadot vt_simplefb_bitblt_argb(struct vt_device *vd, const struct vt_window *vw,
229*b93028d8SEmmanuel Vadot     const uint8_t *argb,
230*b93028d8SEmmanuel Vadot     unsigned int width, unsigned int height,
231*b93028d8SEmmanuel Vadot     unsigned int x, unsigned int y)
232*b93028d8SEmmanuel Vadot {
233*b93028d8SEmmanuel Vadot 
234*b93028d8SEmmanuel Vadot 	return (EOPNOTSUPP);
235*b93028d8SEmmanuel Vadot }
236