2 * Copyright (c) 2013 The FreeBSD Foundation
5 * This software was developed by Aleksandr Rybalko under sponsorship from the
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/cdefs.h>
33 __FBSDID("$FreeBSD$");
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/kernel.h>
40 #include "opt_platform.h"
43 #include <dev/fdt/fdt_common.h>
44 #include <dev/ofw/ofw_bus.h>
45 #include <dev/ofw/ofw_bus_subr.h>
46 #include <dev/ofw/ofw_pci.h>
47 #include <machine/fdt.h>
50 #include <dev/vt/vt.h>
51 #include <dev/vt/hw/fb/vt_fb.h>
52 #include <dev/vt/colors/vt_termcolors.h>
54 static vd_init_t vt_efb_init;
55 static vd_probe_t vt_efb_probe;
57 static struct vt_driver vt_fb_early_driver = {
59 .vd_probe = vt_efb_probe,
60 .vd_init = vt_efb_init,
61 .vd_blank = vt_fb_blank,
62 .vd_bitbltchr = vt_fb_bitbltchr,
63 .vd_priority = VD_PRIORITY_GENERIC,
66 static struct fb_info local_info;
67 VT_DRIVER_DECLARE(vt_efb, vt_fb_early_driver);
71 vt_efb_initialize(struct fb_info *info, phandle_t node)
73 vt_efb_initialize(struct fb_info *info)
82 /* Open display device, thereby initializing it */
83 memset(name, 0, sizeof(name));
84 OF_package_to_path(node, name, sizeof(name));
89 * Set up the color map
91 switch (info->fb_depth) {
93 vt_generate_cons_palette(info->fb_cmap, COLOR_FORMAT_RGB,
94 0x7, 5, 0x7, 2, 0x3, 0);
97 vt_generate_cons_palette(info->fb_cmap, COLOR_FORMAT_RGB,
98 0x1f, 10, 0x1f, 5, 0x1f, 0);
101 vt_generate_cons_palette(info->fb_cmap, COLOR_FORMAT_RGB,
102 0x1f, 11, 0x3f, 5, 0x1f, 0);
106 #if BYTE_ORDER == BIG_ENDIAN
107 vt_generate_cons_palette(info->fb_cmap,
108 COLOR_FORMAT_RGB, 255, 0, 255, 8, 255, 16);
110 vt_generate_cons_palette(info->fb_cmap,
111 COLOR_FORMAT_RGB, 255, 16, 255, 8, 255, 0);
114 for (i = 0; i < 16; i++) {
115 OF_call_method("color!", ih, 4, 1,
116 (cell_t)((info->fb_cmap[i] >> 16) & 0xff),
117 (cell_t)((info->fb_cmap[i] >> 8) & 0xff),
118 (cell_t)((info->fb_cmap[i] >> 0) & 0xff),
125 panic("Unknown color space fb_depth %d", info->fb_depth);
133 phandle_t chosen, node;
137 chosen = OF_finddevice("/chosen");
138 OF_getprop(chosen, "stdout", &stdout, sizeof(stdout));
139 node = OF_instance_to_package(stdout);
141 /* The "/chosen/stdout" present. */
142 OF_getprop(node, "device_type", type, sizeof(type));
143 /* Check if it has "display" type. */
144 if (strcmp(type, "display") == 0)
147 /* Try device with name "screen". */
148 node = OF_finddevice("screen");
154 vt_efb_probe(struct vt_device *vd)
158 node = vt_efb_get_fbnode();
162 if ((OF_getproplen(node, "height") <= 0) ||
163 (OF_getproplen(node, "width") <= 0) ||
164 (OF_getproplen(node, "depth") <= 0) ||
165 (OF_getproplen(node, "linebytes") <= 0))
168 return (CN_INTERNAL);
172 vt_efb_init(struct vt_device *vd)
174 struct ofw_pci_register pciaddrs[8];
175 struct fb_info *info;
176 int i, len, n_pciaddrs;
179 if (vd->vd_softc == NULL)
180 vd->vd_softc = (void *)&local_info;
184 node = vt_efb_get_fbnode();
188 #define GET(name, var) \
189 if (OF_getproplen(node, (name)) != sizeof(info->fb_##var)) \
191 OF_getencprop(node, (name), &info->fb_##var, sizeof(info->fb_##var)); \
192 if (info->fb_##var == 0) \
195 GET("height", height)
198 GET("linebytes", stride)
201 info->fb_size = info->fb_height * info->fb_stride;
204 * Get the PCI addresses of the adapter, if present. The node may be the
205 * child of the PCI device: in that case, try the parent for
206 * the assigned-addresses property.
208 len = OF_getprop(node, "assigned-addresses", pciaddrs,
211 len = OF_getprop(OF_parent(node), "assigned-addresses",
212 pciaddrs, sizeof(pciaddrs));
216 n_pciaddrs = len / sizeof(struct ofw_pci_register);
219 * Grab the physical address of the framebuffer, and then map it
220 * into our memory space. If the MMU is not yet up, it will be
221 * remapped for us when relocation turns on.
223 if (OF_getproplen(node, "address") == sizeof(info->fb_pbase)) {
224 /* XXX We assume #address-cells is 1 at this point. */
225 OF_getencprop(node, "address", &info->fb_pbase,
226 sizeof(info->fb_pbase));
228 #if defined(__powerpc__)
229 sc->sc_memt = &bs_be_tag;
230 bus_space_map(sc->sc_memt, info->fb_pbase, info->fb_size,
231 BUS_SPACE_MAP_PREFETCHABLE, &info->fb_vbase);
232 #elif defined(__sparc64__)
233 OF_decode_addr(node, 0, &space, &phys);
234 sc->sc_memt = &vt_efb_memt[0];
235 info->addr = sparc64_fake_bustag(space, fb_phys, sc->sc_memt);
237 bus_space_map(fdtbus_bs_tag, info->fb_pbase, info->fb_size,
238 BUS_SPACE_MAP_PREFETCHABLE,
239 (bus_space_handle_t *)&info->fb_vbase);
243 * Some IBM systems don't have an address property. Try to
244 * guess the framebuffer region from the assigned addresses.
245 * This is ugly, but there doesn't seem to be an alternative.
246 * Linux does the same thing.
249 info->fb_pbase = n_pciaddrs;
250 for (i = 0; i < n_pciaddrs; i++) {
251 /* If it is too small, not the framebuffer */
252 if (pciaddrs[i].size_lo < info->fb_size)
254 /* If it is not memory, it isn't either */
255 if (!(pciaddrs[i].phys_hi &
256 OFW_PCI_PHYS_HI_SPACE_MEM32))
259 /* This could be the framebuffer */
262 /* If it is prefetchable, it certainly is */
263 if (pciaddrs[i].phys_hi & OFW_PCI_PHYS_HI_PREFETCHABLE)
267 if (info->fb_pbase == n_pciaddrs) /* No candidates found */
270 #if defined(__powerpc__)
271 OF_decode_addr(node, info->fb_pbase, &sc->sc_memt,
273 #elif defined(__sparc64__)
274 OF_decode_addr(node, info->fb_pbase, &space, &info->fb_pbase);
275 sc->sc_memt = &vt_efb_memt[0];
276 info->fb_vbase = sparc64_fake_bustag(space, info->fb_pbase,
279 bus_space_map(fdtbus_bs_tag, info->fb_pbase, info->fb_size,
280 BUS_SPACE_MAP_PREFETCHABLE,
281 (bus_space_handle_t *)&info->fb_vbase);
285 /* blank full size */
286 len = info->fb_size / 4;
287 for (i = 0; i < len; i++) {
288 ((uint32_t *)info->fb_vbase)[i] = 0;
291 /* Get pixel storage size. */
292 info->fb_bpp = info->fb_stride / info->fb_width * 8;
295 vt_efb_initialize(info, node);
297 vt_efb_initialize(info);
302 return (CN_INTERNAL);