Deleted Added
full compact
vt_early_fb.c (257726) vt_early_fb.c (259016)
1/*-
2 * Copyright (c) 2013 The FreeBSD Foundation
3 * All rights reserved.
4 *
5 * This software was developed by Aleksandr Rybalko under sponsorship from the
6 * FreeBSD Foundation.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
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.
16 *
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
27 * SUCH DAMAGE.
28 *
1/*-
2 * Copyright (c) 2013 The FreeBSD Foundation
3 * All rights reserved.
4 *
5 * This software was developed by Aleksandr Rybalko under sponsorship from the
6 * FreeBSD Foundation.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
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.
16 *
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
27 * SUCH DAMAGE.
28 *
29 * $FreeBSD: user/ed/newcons/sys/dev/vt/hw/fb/vt_early_fb.c 257726 2013-11-05 23:09:36Z ray $
29 * $FreeBSD: head/sys/dev/vt/hw/fb/vt_early_fb.c 257726 2013-11-05 23:09:36Z ray $
30 */
31
32#include <sys/cdefs.h>
30 */
31
32#include <sys/cdefs.h>
33__FBSDID("$FreeBSD: user/ed/newcons/sys/dev/vt/hw/fb/vt_early_fb.c 257726 2013-11-05 23:09:36Z ray $");
33__FBSDID("$FreeBSD: head/sys/dev/vt/hw/fb/vt_early_fb.c 257726 2013-11-05 23:09:36Z ray $");
34
35#include <sys/param.h>
36#include <sys/systm.h>
37#include <sys/kernel.h>
38#include <sys/fbio.h>
39
40#include "opt_platform.h"
41
42#ifdef FDT
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#endif
48
49#include <dev/vt/vt.h>
50#include <dev/vt/hw/fb/vt_fb.h>
51#include <dev/vt/colors/vt_termcolors.h>
52
53static vd_init_t vt_efb_init;
54
55static struct vt_driver vt_fb_early_driver = {
56 .vd_init = vt_efb_init,
57 .vd_blank = vt_fb_blank,
58 .vd_bitbltchr = vt_fb_bitbltchr,
59 .vd_priority = VD_PRIORITY_GENERIC,
60};
61
62static struct fb_info info;
63VT_CONSDEV_DECLARE(vt_fb_early_driver,
64 MAX(80, PIXEL_WIDTH(VT_FB_DEFAULT_WIDTH)),
65 MAX(25, PIXEL_HEIGHT(VT_FB_DEFAULT_HEIGHT)), &info);
66
67static void
68#ifdef FDT
69vt_efb_initialize(struct fb_info *info, phandle_t node)
70#else
71vt_efb_initialize(struct fb_info *info)
72#endif
73{
74#ifdef FDT
75 char name[64];
76 cell_t retval;
77 ihandle_t ih;
78 int i;
79
80 /* Open display device, thereby initializing it */
81 memset(name, 0, sizeof(name));
82 OF_package_to_path(node, name, sizeof(name));
83 ih = OF_open(name);
84#endif
85
86 /*
87 * Set up the color map
88 */
89 switch (info->fb_depth) {
90 case 8:
91 vt_generate_vga_palette(info->fb_cmap, COLOR_FORMAT_RGB,
92 0x7, 5, 0x7, 2, 0x3, 0);
93 break;
94 case 15:
95 vt_generate_vga_palette(info->fb_cmap, COLOR_FORMAT_RGB,
96 0x1f, 10, 0x1f, 5, 0x1f, 0);
97 break;
98 case 16:
99 vt_generate_vga_palette(info->fb_cmap, COLOR_FORMAT_RGB,
100 0x1f, 11, 0x3f, 5, 0x1f, 0);
101 break;
102 case 24:
103 case 32:
104#if BYTE_ORDER == BIG_ENDIAN
105 vt_generate_vga_palette(info->fb_cmap,
106 COLOR_FORMAT_RGB, 255, 16, 255, 8, 255, 0);
107#else
108 vt_generate_vga_palette(info->fb_cmap,
109 COLOR_FORMAT_RGB, 255, 0, 255, 8, 255, 16);
110#endif
111#ifdef FDT
112 for (i = 0; i < 16; i++) {
113 OF_call_method("color!", ih, 4, 1,
114 (cell_t)((info->fb_cmap[i] >> 16) & 0xff),
115 (cell_t)((info->fb_cmap[i] >> 8) & 0xff),
116 (cell_t)((info->fb_cmap[i] >> 0) & 0xff),
117 (cell_t)i, &retval);
118 }
119#endif
120 break;
121
122 default:
123 panic("Unknown color space fb_depth %d", info->fb_depth);
124 break;
125 }
126}
127
128static int
129vt_efb_init(struct vt_device *vd)
130{
131 struct ofw_pci_register pciaddrs[8];
132 struct fb_info *info;
133 int i, len, n_pciaddrs;
134 phandle_t chosen, node;
135 ihandle_t stdout;
136 char type[64];
137
138 info = vd->vd_softc;
139
140 chosen = OF_finddevice("/chosen");
141 OF_getprop(chosen, "stdout", &stdout, sizeof(stdout));
142 node = OF_instance_to_package(stdout);
143 if (node == -1) {
144 /*
145 * The "/chosen/stdout" does not exist try
146 * using "screen" directly.
147 */
148 node = OF_finddevice("screen");
149 }
150 OF_getprop(node, "device_type", type, sizeof(type));
151 if (strcmp(type, "display") != 0)
152 return (CN_DEAD);
153
154#define GET(name, var) \
155 if (OF_getproplen(node, (name)) != sizeof(info->fb_##var)) \
156 return (CN_DEAD); \
157 OF_getencprop(node, (name), &info->fb_##var, sizeof(info->fb_##var)); \
158 if (info->fb_##var == 0) \
159 return (CN_DEAD);
160
161 GET("height", height)
162 GET("width", width)
163 GET("depth", depth)
164 GET("linebytes", stride)
165#undef GET
166
167 info->fb_size = info->fb_height * info->fb_stride;
168
169 /*
170 * Get the PCI addresses of the adapter, if present. The node may be the
171 * child of the PCI device: in that case, try the parent for
172 * the assigned-addresses property.
173 */
174 len = OF_getprop(node, "assigned-addresses", pciaddrs,
175 sizeof(pciaddrs));
176 if (len == -1) {
177 len = OF_getprop(OF_parent(node), "assigned-addresses",
178 pciaddrs, sizeof(pciaddrs));
179 }
180 if (len == -1)
181 len = 0;
182 n_pciaddrs = len / sizeof(struct ofw_pci_register);
183
184 /*
185 * Grab the physical address of the framebuffer, and then map it
186 * into our memory space. If the MMU is not yet up, it will be
187 * remapped for us when relocation turns on.
188 */
189 if (OF_getproplen(node, "address") == sizeof(info->fb_pbase)) {
190 /* XXX We assume #address-cells is 1 at this point. */
191 OF_getencprop(node, "address", &info->fb_pbase,
192 sizeof(info->fb_pbase));
193
194 #if defined(__powerpc__)
195 sc->sc_memt = &bs_be_tag;
196 bus_space_map(sc->sc_memt, info->fb_pbase, info->fb_size,
197 BUS_SPACE_MAP_PREFETCHABLE, &info->fb_vbase);
198 #elif defined(__sparc64__)
199 OF_decode_addr(node, 0, &space, &phys);
200 sc->sc_memt = &vt_efb_memt[0];
201 info->addr = sparc64_fake_bustag(space, fb_phys, sc->sc_memt);
202 #else
203 bus_space_map(fdtbus_bs_tag, info->fb_pbase, info->fb_size,
204 BUS_SPACE_MAP_PREFETCHABLE,
205 (bus_space_handle_t *)&info->fb_vbase);
206 #endif
207 } else {
208 /*
209 * Some IBM systems don't have an address property. Try to
210 * guess the framebuffer region from the assigned addresses.
211 * This is ugly, but there doesn't seem to be an alternative.
212 * Linux does the same thing.
213 */
214
215 info->fb_pbase = n_pciaddrs;
216 for (i = 0; i < n_pciaddrs; i++) {
217 /* If it is too small, not the framebuffer */
218 if (pciaddrs[i].size_lo < info->fb_size)
219 continue;
220 /* If it is not memory, it isn't either */
221 if (!(pciaddrs[i].phys_hi &
222 OFW_PCI_PHYS_HI_SPACE_MEM32))
223 continue;
224
225 /* This could be the framebuffer */
226 info->fb_pbase = i;
227
228 /* If it is prefetchable, it certainly is */
229 if (pciaddrs[i].phys_hi & OFW_PCI_PHYS_HI_PREFETCHABLE)
230 break;
231 }
232
233 if (info->fb_pbase == n_pciaddrs) /* No candidates found */
234 return (CN_DEAD);
235
236 #if defined(__powerpc__)
237 OF_decode_addr(node, info->fb_pbase, &sc->sc_memt,
238 &info->fb_vbase);
239 #elif defined(__sparc64__)
240 OF_decode_addr(node, info->fb_pbase, &space, &info->fb_pbase);
241 sc->sc_memt = &vt_efb_memt[0];
242 info->fb_vbase = sparc64_fake_bustag(space, info->fb_pbase,
243 sc->sc_memt);
244 #else
245 bus_space_map(fdtbus_bs_tag, info->fb_pbase, info->fb_size,
246 BUS_SPACE_MAP_PREFETCHABLE,
247 (bus_space_handle_t *)&info->fb_vbase);
248 #endif
249 }
250
251
252 /* blank full size */
253 len = info->fb_size / 4;
254 for (i = 0; i < len; i++) {
255 ((uint32_t *)info->fb_vbase)[i] = 0;
256 }
257
258 /* Get pixel storage size. */
259 info->fb_bpp = info->fb_stride / info->fb_width * 8;
260
261 /*
262 * Early FB driver work with static window buffer 80x25, so reduce
263 * size to 640x480.
264 */
265 info->fb_width = VT_FB_DEFAULT_WIDTH;
266 info->fb_height = VT_FB_DEFAULT_HEIGHT;
267
268#ifdef FDT
269 vt_efb_initialize(info, node);
270#else
271 vt_efb_initialize(info);
272#endif
273 fb_probe(info);
274 vt_fb_init(vd);
275
276
277 return (CN_INTERNAL);
278}
34
35#include <sys/param.h>
36#include <sys/systm.h>
37#include <sys/kernel.h>
38#include <sys/fbio.h>
39
40#include "opt_platform.h"
41
42#ifdef FDT
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#endif
48
49#include <dev/vt/vt.h>
50#include <dev/vt/hw/fb/vt_fb.h>
51#include <dev/vt/colors/vt_termcolors.h>
52
53static vd_init_t vt_efb_init;
54
55static struct vt_driver vt_fb_early_driver = {
56 .vd_init = vt_efb_init,
57 .vd_blank = vt_fb_blank,
58 .vd_bitbltchr = vt_fb_bitbltchr,
59 .vd_priority = VD_PRIORITY_GENERIC,
60};
61
62static struct fb_info info;
63VT_CONSDEV_DECLARE(vt_fb_early_driver,
64 MAX(80, PIXEL_WIDTH(VT_FB_DEFAULT_WIDTH)),
65 MAX(25, PIXEL_HEIGHT(VT_FB_DEFAULT_HEIGHT)), &info);
66
67static void
68#ifdef FDT
69vt_efb_initialize(struct fb_info *info, phandle_t node)
70#else
71vt_efb_initialize(struct fb_info *info)
72#endif
73{
74#ifdef FDT
75 char name[64];
76 cell_t retval;
77 ihandle_t ih;
78 int i;
79
80 /* Open display device, thereby initializing it */
81 memset(name, 0, sizeof(name));
82 OF_package_to_path(node, name, sizeof(name));
83 ih = OF_open(name);
84#endif
85
86 /*
87 * Set up the color map
88 */
89 switch (info->fb_depth) {
90 case 8:
91 vt_generate_vga_palette(info->fb_cmap, COLOR_FORMAT_RGB,
92 0x7, 5, 0x7, 2, 0x3, 0);
93 break;
94 case 15:
95 vt_generate_vga_palette(info->fb_cmap, COLOR_FORMAT_RGB,
96 0x1f, 10, 0x1f, 5, 0x1f, 0);
97 break;
98 case 16:
99 vt_generate_vga_palette(info->fb_cmap, COLOR_FORMAT_RGB,
100 0x1f, 11, 0x3f, 5, 0x1f, 0);
101 break;
102 case 24:
103 case 32:
104#if BYTE_ORDER == BIG_ENDIAN
105 vt_generate_vga_palette(info->fb_cmap,
106 COLOR_FORMAT_RGB, 255, 16, 255, 8, 255, 0);
107#else
108 vt_generate_vga_palette(info->fb_cmap,
109 COLOR_FORMAT_RGB, 255, 0, 255, 8, 255, 16);
110#endif
111#ifdef FDT
112 for (i = 0; i < 16; i++) {
113 OF_call_method("color!", ih, 4, 1,
114 (cell_t)((info->fb_cmap[i] >> 16) & 0xff),
115 (cell_t)((info->fb_cmap[i] >> 8) & 0xff),
116 (cell_t)((info->fb_cmap[i] >> 0) & 0xff),
117 (cell_t)i, &retval);
118 }
119#endif
120 break;
121
122 default:
123 panic("Unknown color space fb_depth %d", info->fb_depth);
124 break;
125 }
126}
127
128static int
129vt_efb_init(struct vt_device *vd)
130{
131 struct ofw_pci_register pciaddrs[8];
132 struct fb_info *info;
133 int i, len, n_pciaddrs;
134 phandle_t chosen, node;
135 ihandle_t stdout;
136 char type[64];
137
138 info = vd->vd_softc;
139
140 chosen = OF_finddevice("/chosen");
141 OF_getprop(chosen, "stdout", &stdout, sizeof(stdout));
142 node = OF_instance_to_package(stdout);
143 if (node == -1) {
144 /*
145 * The "/chosen/stdout" does not exist try
146 * using "screen" directly.
147 */
148 node = OF_finddevice("screen");
149 }
150 OF_getprop(node, "device_type", type, sizeof(type));
151 if (strcmp(type, "display") != 0)
152 return (CN_DEAD);
153
154#define GET(name, var) \
155 if (OF_getproplen(node, (name)) != sizeof(info->fb_##var)) \
156 return (CN_DEAD); \
157 OF_getencprop(node, (name), &info->fb_##var, sizeof(info->fb_##var)); \
158 if (info->fb_##var == 0) \
159 return (CN_DEAD);
160
161 GET("height", height)
162 GET("width", width)
163 GET("depth", depth)
164 GET("linebytes", stride)
165#undef GET
166
167 info->fb_size = info->fb_height * info->fb_stride;
168
169 /*
170 * Get the PCI addresses of the adapter, if present. The node may be the
171 * child of the PCI device: in that case, try the parent for
172 * the assigned-addresses property.
173 */
174 len = OF_getprop(node, "assigned-addresses", pciaddrs,
175 sizeof(pciaddrs));
176 if (len == -1) {
177 len = OF_getprop(OF_parent(node), "assigned-addresses",
178 pciaddrs, sizeof(pciaddrs));
179 }
180 if (len == -1)
181 len = 0;
182 n_pciaddrs = len / sizeof(struct ofw_pci_register);
183
184 /*
185 * Grab the physical address of the framebuffer, and then map it
186 * into our memory space. If the MMU is not yet up, it will be
187 * remapped for us when relocation turns on.
188 */
189 if (OF_getproplen(node, "address") == sizeof(info->fb_pbase)) {
190 /* XXX We assume #address-cells is 1 at this point. */
191 OF_getencprop(node, "address", &info->fb_pbase,
192 sizeof(info->fb_pbase));
193
194 #if defined(__powerpc__)
195 sc->sc_memt = &bs_be_tag;
196 bus_space_map(sc->sc_memt, info->fb_pbase, info->fb_size,
197 BUS_SPACE_MAP_PREFETCHABLE, &info->fb_vbase);
198 #elif defined(__sparc64__)
199 OF_decode_addr(node, 0, &space, &phys);
200 sc->sc_memt = &vt_efb_memt[0];
201 info->addr = sparc64_fake_bustag(space, fb_phys, sc->sc_memt);
202 #else
203 bus_space_map(fdtbus_bs_tag, info->fb_pbase, info->fb_size,
204 BUS_SPACE_MAP_PREFETCHABLE,
205 (bus_space_handle_t *)&info->fb_vbase);
206 #endif
207 } else {
208 /*
209 * Some IBM systems don't have an address property. Try to
210 * guess the framebuffer region from the assigned addresses.
211 * This is ugly, but there doesn't seem to be an alternative.
212 * Linux does the same thing.
213 */
214
215 info->fb_pbase = n_pciaddrs;
216 for (i = 0; i < n_pciaddrs; i++) {
217 /* If it is too small, not the framebuffer */
218 if (pciaddrs[i].size_lo < info->fb_size)
219 continue;
220 /* If it is not memory, it isn't either */
221 if (!(pciaddrs[i].phys_hi &
222 OFW_PCI_PHYS_HI_SPACE_MEM32))
223 continue;
224
225 /* This could be the framebuffer */
226 info->fb_pbase = i;
227
228 /* If it is prefetchable, it certainly is */
229 if (pciaddrs[i].phys_hi & OFW_PCI_PHYS_HI_PREFETCHABLE)
230 break;
231 }
232
233 if (info->fb_pbase == n_pciaddrs) /* No candidates found */
234 return (CN_DEAD);
235
236 #if defined(__powerpc__)
237 OF_decode_addr(node, info->fb_pbase, &sc->sc_memt,
238 &info->fb_vbase);
239 #elif defined(__sparc64__)
240 OF_decode_addr(node, info->fb_pbase, &space, &info->fb_pbase);
241 sc->sc_memt = &vt_efb_memt[0];
242 info->fb_vbase = sparc64_fake_bustag(space, info->fb_pbase,
243 sc->sc_memt);
244 #else
245 bus_space_map(fdtbus_bs_tag, info->fb_pbase, info->fb_size,
246 BUS_SPACE_MAP_PREFETCHABLE,
247 (bus_space_handle_t *)&info->fb_vbase);
248 #endif
249 }
250
251
252 /* blank full size */
253 len = info->fb_size / 4;
254 for (i = 0; i < len; i++) {
255 ((uint32_t *)info->fb_vbase)[i] = 0;
256 }
257
258 /* Get pixel storage size. */
259 info->fb_bpp = info->fb_stride / info->fb_width * 8;
260
261 /*
262 * Early FB driver work with static window buffer 80x25, so reduce
263 * size to 640x480.
264 */
265 info->fb_width = VT_FB_DEFAULT_WIDTH;
266 info->fb_height = VT_FB_DEFAULT_HEIGHT;
267
268#ifdef FDT
269 vt_efb_initialize(info, node);
270#else
271 vt_efb_initialize(info);
272#endif
273 fb_probe(info);
274 vt_fb_init(vd);
275
276
277 return (CN_INTERNAL);
278}