omap3_dss.c revision 1.2 1 1.2 skrll /* $NetBSD: omap3_dss.c,v 1.2 2020/06/28 12:43:00 skrll Exp $ */
2 1.1 jmcneill
3 1.1 jmcneill /*
4 1.1 jmcneill * Copyright (c) 2010 Michael Lorenz
5 1.1 jmcneill * All rights reserved.
6 1.1 jmcneill *
7 1.1 jmcneill * Redistribution and use in source and binary forms, with or without
8 1.1 jmcneill * modification, are permitted provided that the following conditions
9 1.1 jmcneill * are met:
10 1.1 jmcneill * 1. Redistributions of source code must retain the above copyright
11 1.1 jmcneill * notice, this list of conditions and the following disclaimer.
12 1.1 jmcneill * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 jmcneill * notice, this list of conditions and the following disclaimer in the
14 1.1 jmcneill * documentation and/or other materials provided with the distribution.
15 1.1 jmcneill *
16 1.1 jmcneill * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 1.1 jmcneill * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 1.1 jmcneill * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 1.1 jmcneill * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 1.1 jmcneill * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 1.1 jmcneill * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 1.1 jmcneill * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 1.1 jmcneill * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 1.1 jmcneill * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 1.1 jmcneill * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 1.1 jmcneill */
27 1.1 jmcneill
28 1.1 jmcneill /*
29 1.1 jmcneill * A console driver for OMAP 3530's built-in video controller
30 1.1 jmcneill * tested on beagleboard only so far
31 1.1 jmcneill */
32 1.1 jmcneill
33 1.1 jmcneill #include "opt_wsdisplay_compat.h"
34 1.1 jmcneill
35 1.1 jmcneill #include <sys/cdefs.h>
36 1.2 skrll __KERNEL_RCSID(0, "$NetBSD: omap3_dss.c,v 1.2 2020/06/28 12:43:00 skrll Exp $");
37 1.1 jmcneill
38 1.1 jmcneill #include <sys/param.h>
39 1.1 jmcneill #include <sys/systm.h>
40 1.1 jmcneill #include <sys/kernel.h>
41 1.1 jmcneill #include <sys/device.h>
42 1.1 jmcneill #include <sys/malloc.h>
43 1.1 jmcneill #include <sys/lwp.h>
44 1.1 jmcneill #include <sys/kauth.h>
45 1.1 jmcneill #include <sys/bus.h>
46 1.1 jmcneill
47 1.1 jmcneill #include <uvm/uvm_extern.h>
48 1.1 jmcneill
49 1.1 jmcneill #include <dev/videomode/videomode.h>
50 1.1 jmcneill #include <dev/videomode/edidvar.h>
51 1.1 jmcneill
52 1.1 jmcneill #include <dev/fdt/fdtvar.h>
53 1.1 jmcneill
54 1.1 jmcneill #include <arm/ti/omap3_dssreg.h>
55 1.1 jmcneill
56 1.1 jmcneill #include <dev/wscons/wsdisplayvar.h>
57 1.1 jmcneill #include <dev/wscons/wsconsio.h>
58 1.1 jmcneill #include <dev/wsfont/wsfont.h>
59 1.1 jmcneill #include <dev/rasops/rasops.h>
60 1.1 jmcneill #include <dev/wscons/wsdisplay_vconsvar.h>
61 1.1 jmcneill
62 1.1 jmcneill struct omapfb_softc {
63 1.1 jmcneill device_t sc_dev;
64 1.1 jmcneill
65 1.1 jmcneill bus_space_tag_t sc_iot;
66 1.1 jmcneill bus_dma_tag_t sc_dmat;
67 1.1 jmcneill bus_space_handle_t sc_regh;
68 1.1 jmcneill bus_dmamap_t sc_dmamap;
69 1.1 jmcneill bus_dma_segment_t sc_dmamem[1];
70 1.1 jmcneill size_t sc_vramsize;
71 1.1 jmcneill
72 1.1 jmcneill int sc_width, sc_height, sc_depth, sc_stride;
73 1.1 jmcneill int sc_locked;
74 1.1 jmcneill void *sc_fbaddr, *sc_vramaddr;
75 1.1 jmcneill
76 1.1 jmcneill int sc_cursor_offset;
77 1.1 jmcneill uint32_t *sc_cursor_img;
78 1.1 jmcneill int sc_cursor_x, sc_cursor_y;
79 1.1 jmcneill int sc_hot_x, sc_hot_y;
80 1.1 jmcneill uint8_t sc_cursor_bitmap[8 * 64];
81 1.1 jmcneill uint8_t sc_cursor_mask[8 * 64];
82 1.1 jmcneill uint32_t sc_cursor_cmap[4];
83 1.1 jmcneill
84 1.1 jmcneill bus_addr_t sc_fbhwaddr;
85 1.1 jmcneill uint32_t *sc_clut;
86 1.1 jmcneill uint32_t sc_dispc_config;
87 1.1 jmcneill int sc_video_is_on;
88 1.1 jmcneill struct vcons_screen sc_console_screen;
89 1.1 jmcneill struct wsscreen_descr sc_defaultscreen_descr;
90 1.1 jmcneill const struct wsscreen_descr *sc_screens[1];
91 1.1 jmcneill struct wsscreen_list sc_screenlist;
92 1.1 jmcneill struct vcons_data vd;
93 1.1 jmcneill int sc_mode;
94 1.1 jmcneill uint8_t sc_cmap_red[256], sc_cmap_green[256], sc_cmap_blue[256];
95 1.1 jmcneill void (*sc_putchar)(void *, int, int, u_int, long);
96 1.1 jmcneill
97 1.1 jmcneill uint8_t sc_edid_data[1024];
98 1.1 jmcneill size_t sc_edid_size;
99 1.1 jmcneill };
100 1.1 jmcneill
101 1.1 jmcneill static int omapfb_match(device_t, cfdata_t, void *);
102 1.1 jmcneill static void omapfb_attach(device_t, device_t, void *);
103 1.1 jmcneill
104 1.1 jmcneill CFATTACH_DECL_NEW(omap3_dss, sizeof(struct omapfb_softc),
105 1.1 jmcneill omapfb_match, omapfb_attach, NULL, NULL);
106 1.1 jmcneill
107 1.1 jmcneill static int omapfb_ioctl(void *, void *, u_long, void *, int,
108 1.1 jmcneill struct lwp *);
109 1.1 jmcneill static paddr_t omapfb_mmap(void *, void *, off_t, int);
110 1.1 jmcneill static void omapfb_init_screen(void *, struct vcons_screen *, int, long *);
111 1.1 jmcneill
112 1.1 jmcneill static int omapfb_putcmap(struct omapfb_softc *, struct wsdisplay_cmap *);
113 1.1 jmcneill static int omapfb_getcmap(struct omapfb_softc *, struct wsdisplay_cmap *);
114 1.1 jmcneill static void omapfb_restore_palette(struct omapfb_softc *);
115 1.1 jmcneill static void omapfb_putpalreg(struct omapfb_softc *, int, uint8_t,
116 1.1 jmcneill uint8_t, uint8_t);
117 1.1 jmcneill
118 1.1 jmcneill static int omapfb_set_depth(struct omapfb_softc *, int);
119 1.1 jmcneill static void omapfb_set_video(struct omapfb_softc *, int);
120 1.1 jmcneill
121 1.1 jmcneill static void omapfb_move_cursor(struct omapfb_softc *, int, int);
122 1.1 jmcneill static int omapfb_do_cursor(struct omapfb_softc *,
123 1.1 jmcneill struct wsdisplay_cursor *);
124 1.1 jmcneill
125 1.1 jmcneill #if NOMAPDMA > 0
126 1.1 jmcneill static void omapfb_init(struct omapfb_softc *);
127 1.1 jmcneill static void omapfb_wait_idle(struct omapfb_softc *);
128 1.1 jmcneill static void omapfb_rectfill(struct omapfb_softc *, int, int, int, int,
129 1.1 jmcneill uint32_t);
130 1.1 jmcneill static void omapfb_bitblt(struct omapfb_softc *, int, int, int, int, int,
131 1.1 jmcneill int, int);
132 1.1 jmcneill
133 1.1 jmcneill static void omapfb_cursor(void *, int, int, int);
134 1.1 jmcneill static void omapfb_putchar(void *, int, int, u_int, long);
135 1.1 jmcneill static void omapfb_copycols(void *, int, int, int, int);
136 1.1 jmcneill static void omapfb_erasecols(void *, int, int, int, long);
137 1.1 jmcneill static void omapfb_copyrows(void *, int, int, int);
138 1.1 jmcneill static void omapfb_eraserows(void *, int, int, long);
139 1.1 jmcneill #endif /* NOMAPDMA > 0 */
140 1.1 jmcneill
141 1.1 jmcneill struct wsdisplay_accessops omapfb_accessops = {
142 1.1 jmcneill omapfb_ioctl,
143 1.1 jmcneill omapfb_mmap,
144 1.1 jmcneill NULL, /* alloc_screen */
145 1.1 jmcneill NULL, /* free_screen */
146 1.1 jmcneill NULL, /* show_screen */
147 1.1 jmcneill NULL, /* load_font */
148 1.1 jmcneill NULL, /* pollc */
149 1.1 jmcneill NULL /* scroll */
150 1.1 jmcneill };
151 1.1 jmcneill
152 1.1 jmcneill uint32_t venc_mode_ntsc[] = {
153 1.1 jmcneill 0x00000000, 0x00000001, 0x00008040, 0x00000359,
154 1.1 jmcneill 0x0000020c, 0x00000000, 0x043f2631, 0x00000000,
155 1.1 jmcneill 0x00000102, 0x0000016c, 0x0000012f, 0x00000043,
156 1.1 jmcneill 0x00000038, 0x00000007, 0x00000001, 0x00000038,
157 1.1 jmcneill 0x21f07c1f, 0x00000000, 0x01310011, 0x0000f003,
158 1.1 jmcneill 0x00000000, 0x069300f4, 0x0016020c, 0x00060107,
159 1.1 jmcneill 0x008e0350, 0x000f0359, 0x01a00000, 0x020701a0,
160 1.1 jmcneill 0x01ac0024, 0x020d01ac, 0x00000006, 0x03480078,
161 1.1 jmcneill 0x02060024, 0x0001008a, 0x01ac0106, 0x01060006,
162 1.1 jmcneill 0x00140001, 0x00010001, 0x00f90000, 0x0000000d,
163 1.1 jmcneill 0x00000000};
164 1.1 jmcneill
165 1.1 jmcneill extern const u_char rasops_cmap[768];
166 1.1 jmcneill
167 1.1 jmcneill static const char * const compatible[] = {
168 1.1 jmcneill "ti,omap3-dss",
169 1.1 jmcneill NULL
170 1.1 jmcneill };
171 1.1 jmcneill
172 1.1 jmcneill static int omapfb_console_phandle = -1;
173 1.1 jmcneill
174 1.1 jmcneill static int
175 1.1 jmcneill omapfb_match(device_t parent, cfdata_t match, void *aux)
176 1.1 jmcneill {
177 1.1 jmcneill struct fdt_attach_args * const faa = aux;
178 1.1 jmcneill
179 1.1 jmcneill return of_match_compatible(faa->faa_phandle, compatible);
180 1.1 jmcneill }
181 1.1 jmcneill
182 1.1 jmcneill static void
183 1.1 jmcneill omapfb_attach(device_t parent, device_t self, void *aux)
184 1.1 jmcneill {
185 1.1 jmcneill struct omapfb_softc *sc = device_private(self);
186 1.1 jmcneill struct fdt_attach_args *faa = aux;
187 1.1 jmcneill const int phandle = faa->faa_phandle;
188 1.1 jmcneill struct rasops_info *ri;
189 1.1 jmcneill struct wsemuldisplaydev_attach_args aa;
190 1.1 jmcneill prop_dictionary_t dict;
191 1.1 jmcneill prop_data_t edid_data;
192 1.1 jmcneill unsigned long defattr;
193 1.1 jmcneill #ifdef WSDISPLAY_MULTICONS
194 1.1 jmcneill bool is_console = true;
195 1.1 jmcneill #else
196 1.1 jmcneill bool is_console = phandle == omapfb_console_phandle;
197 1.1 jmcneill #endif
198 1.1 jmcneill uint32_t sz, reg;
199 1.1 jmcneill int segs, i, j;
200 1.1 jmcneill bus_addr_t addr;
201 1.1 jmcneill bus_size_t size;
202 1.1 jmcneill
203 1.1 jmcneill if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
204 1.1 jmcneill aprint_error(": couldn't get registers\n");
205 1.1 jmcneill return;
206 1.1 jmcneill }
207 1.1 jmcneill
208 1.1 jmcneill sc->sc_dev = self;
209 1.1 jmcneill sc->sc_iot = faa->faa_bst;
210 1.1 jmcneill sc->sc_dmat = faa->faa_dmat;
211 1.1 jmcneill
212 1.1 jmcneill if (bus_space_map(sc->sc_iot, addr, size, 0, &sc->sc_regh) != 0) {
213 1.1 jmcneill aprint_error(": couldn't map registers\n");
214 1.1 jmcneill return;
215 1.1 jmcneill }
216 1.1 jmcneill
217 1.1 jmcneill aprint_naive("\n");
218 1.1 jmcneill aprint_normal(": OMAP onboard video\n");
219 1.1 jmcneill
220 1.1 jmcneill sc->sc_video_is_on = 1;
221 1.1 jmcneill
222 1.1 jmcneill /*
223 1.1 jmcneill * XXX
224 1.1 jmcneill * different u-boot versions initialize the graphics controller in
225 1.1 jmcneill * different ways, so we look for the display resolution in a few
226 1.1 jmcneill * different places...
227 1.1 jmcneill */
228 1.1 jmcneill sz = bus_space_read_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GFX_SIZE);
229 1.1 jmcneill if (sz == 0) {
230 1.1 jmcneill sz = bus_space_read_4(sc->sc_iot, sc->sc_regh,
231 1.1 jmcneill OMAPFB_DISPC_SIZE_LCD);
232 1.1 jmcneill }
233 1.1 jmcneill if (sz == 0) {
234 1.1 jmcneill sz = bus_space_read_4(sc->sc_iot, sc->sc_regh,
235 1.1 jmcneill OMAPFB_DISPC_SIZE_DIG);
236 1.1 jmcneill }
237 1.1 jmcneill
238 1.1 jmcneill /* ... and make sure it ends up where we need it */
239 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GFX_SIZE, sz);
240 1.1 jmcneill
241 1.1 jmcneill sc->sc_width = (sz & 0xfff) + 1;
242 1.1 jmcneill sc->sc_height = ((sz & 0x0fff0000 ) >> 16) + 1;
243 1.1 jmcneill sc->sc_depth = 16;
244 1.1 jmcneill sc->sc_stride = sc->sc_width << 1;
245 1.1 jmcneill
246 1.1 jmcneill if (sc->sc_width == 1 || sc->sc_height == 1) {
247 1.1 jmcneill aprint_error_dev(self, "bogus display size, not attaching\n");
248 1.1 jmcneill return;
249 1.1 jmcneill }
250 1.1 jmcneill
251 1.1 jmcneill printf("%s: firmware set up %d x %d\n", device_xname(self),
252 1.1 jmcneill sc->sc_width, sc->sc_height);
253 1.1 jmcneill #if 0
254 1.1 jmcneill printf("DSS revision: %08x\n",
255 1.1 jmcneill bus_space_read_4(sc->sc_iot, sc->sc_regh, OMAPFB_DSS_REVISION));
256 1.1 jmcneill #endif
257 1.1 jmcneill dict = device_properties(self);
258 1.1 jmcneill edid_data = prop_dictionary_get(dict, "EDID");
259 1.1 jmcneill
260 1.1 jmcneill if (edid_data != NULL) {
261 1.1 jmcneill struct edid_info ei;
262 1.1 jmcneill
263 1.1 jmcneill sc->sc_edid_size = uimin(prop_data_size(edid_data), 1024);
264 1.1 jmcneill memset(sc->sc_edid_data, 0, sizeof(sc->sc_edid_data));
265 1.2 skrll memcpy(sc->sc_edid_data, prop_data_value(edid_data), sc->sc_edid_size);
266 1.1 jmcneill
267 1.1 jmcneill edid_parse(sc->sc_edid_data, &ei);
268 1.1 jmcneill edid_print(&ei);
269 1.1 jmcneill }
270 1.1 jmcneill
271 1.1 jmcneill /* setup video DMA */
272 1.1 jmcneill sc->sc_vramsize = (12 << 20) + PAGE_SIZE; /* 12MB + CLUT */
273 1.1 jmcneill
274 1.1 jmcneill if (bus_dmamem_alloc(sc->sc_dmat, sc->sc_vramsize, 0, 0,
275 1.1 jmcneill sc->sc_dmamem, 1, &segs, BUS_DMA_NOWAIT) != 0) {
276 1.1 jmcneill panic("boo!\n");
277 1.1 jmcneill aprint_error_dev(sc->sc_dev,
278 1.1 jmcneill "failed to allocate video memory\n");
279 1.1 jmcneill return;
280 1.1 jmcneill }
281 1.1 jmcneill
282 1.1 jmcneill if (bus_dmamem_map(sc->sc_dmat, sc->sc_dmamem, 1, sc->sc_vramsize,
283 1.1 jmcneill &sc->sc_vramaddr, BUS_DMA_NOWAIT | BUS_DMA_COHERENT) != 0) {
284 1.1 jmcneill aprint_error_dev(sc->sc_dev, "failed to map video RAM\n");
285 1.1 jmcneill return;
286 1.1 jmcneill }
287 1.1 jmcneill sc->sc_fbaddr = (uint8_t *)sc->sc_vramaddr + PAGE_SIZE;
288 1.1 jmcneill sc->sc_clut = sc->sc_vramaddr;
289 1.1 jmcneill
290 1.1 jmcneill if (bus_dmamap_create(sc->sc_dmat, sc->sc_vramsize, 1, sc->sc_vramsize,
291 1.1 jmcneill 0, BUS_DMA_NOWAIT, &sc->sc_dmamap) != 0) {
292 1.1 jmcneill aprint_error_dev(sc->sc_dev, "failed to create DMA map\n");
293 1.1 jmcneill return;
294 1.1 jmcneill }
295 1.1 jmcneill
296 1.1 jmcneill if (bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap, sc->sc_vramaddr,
297 1.1 jmcneill sc->sc_vramsize, NULL, BUS_DMA_NOWAIT) != 0) {
298 1.1 jmcneill aprint_error_dev(sc->sc_dev, "failed to load DMA map\n");
299 1.1 jmcneill return;
300 1.1 jmcneill }
301 1.1 jmcneill
302 1.1 jmcneill if (sc->sc_depth == 8) {
303 1.1 jmcneill j = 0;
304 1.1 jmcneill for (i = 0; i < 256; i++) {
305 1.1 jmcneill sc->sc_cmap_red[i] = rasops_cmap[j];
306 1.1 jmcneill sc->sc_cmap_green[i] = rasops_cmap[j + 1];
307 1.1 jmcneill sc->sc_cmap_blue[i] = rasops_cmap[j + 2];
308 1.1 jmcneill j += 3;
309 1.1 jmcneill }
310 1.1 jmcneill } else {
311 1.1 jmcneill for (i = 0; i < 256; i++) {
312 1.1 jmcneill sc->sc_cmap_red[i] = i;
313 1.1 jmcneill sc->sc_cmap_green[i] = i;
314 1.1 jmcneill sc->sc_cmap_blue[i] = i;
315 1.1 jmcneill }
316 1.1 jmcneill }
317 1.1 jmcneill omapfb_restore_palette(sc);
318 1.1 jmcneill
319 1.1 jmcneill /* now that we have video memory, stick it to the video controller */
320 1.1 jmcneill
321 1.1 jmcneill reg = bus_space_read_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_SYSCONFIG);
322 1.1 jmcneill reg &= ~(OMAP_DISPC_SYSC_STANDBY_MASK | OMAP_DISPC_SYSC_IDLE_MASK);
323 1.1 jmcneill reg |= OMAP_DISPC_SYSC_SMART_STANDBY | OMAP_DISPC_SYSC_SMART_IDLE |
324 1.1 jmcneill OMAP_DISPC_SYSC_WAKEUP_ENABLE | OMAP_SYSCONF_AUTOIDLE;
325 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_SYSCONFIG, reg);
326 1.1 jmcneill
327 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DSS_SYSCONFIG,
328 1.1 jmcneill OMAP_SYSCONF_AUTOIDLE);
329 1.1 jmcneill
330 1.1 jmcneill reg = OMAP_DISPC_CFG_TV_ALPHA_EN | OMAP_DISPC_CFG_LCD_ALPHA_EN;
331 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONFIG, reg);
332 1.1 jmcneill sc->sc_dispc_config = reg;
333 1.1 jmcneill
334 1.1 jmcneill /* we use overlay 1 for the console and X */
335 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GLOBAL_ALPHA,
336 1.1 jmcneill 0x00ff00ff);
337 1.1 jmcneill sc->sc_fbhwaddr = sc->sc_dmamem->ds_addr + PAGE_SIZE;
338 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_VID1_BASE_0,
339 1.1 jmcneill sc->sc_fbhwaddr);
340 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh,
341 1.1 jmcneill OMAPFB_DISPC_VID1_POSITION, 0);
342 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_VID1_SIZE,
343 1.1 jmcneill ((sc->sc_height - 1) << 16) | (sc->sc_width - 1));
344 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh,
345 1.1 jmcneill OMAPFB_DISPC_VID1_PICTURE_SIZE,
346 1.1 jmcneill ((sc->sc_height - 1) << 16) | (sc->sc_width - 1));
347 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh,
348 1.1 jmcneill OMAPFB_DISPC_VID1_ROW_INC, 1);
349 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh,
350 1.1 jmcneill OMAPFB_DISPC_VID1_PIXEL_INC, 1);
351 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh,
352 1.1 jmcneill OMAPFB_DISPC_VID1_PRELOAD, 0x60);
353 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_VID1_ATTRIBUTES,
354 1.1 jmcneill OMAP_VID_ATTR_ENABLE |
355 1.1 jmcneill OMAP_VID_ATTR_BURST_16x32 |
356 1.1 jmcneill OMAP_VID_ATTR_RGB16 |
357 1.1 jmcneill OMAP_VID_ATTR_REPLICATION);
358 1.1 jmcneill
359 1.1 jmcneill /* turn off overlay 2 */
360 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh,
361 1.1 jmcneill OMAPFB_DISPC_VID2_ATTRIBUTES, 0);
362 1.1 jmcneill
363 1.1 jmcneill /* initialize the gfx layer for use as hardware cursor */
364 1.1 jmcneill sc->sc_cursor_cmap[0] = 0;
365 1.1 jmcneill sc->sc_cursor_offset = (12 << 20) - (64 * 64 * 4);
366 1.1 jmcneill sc->sc_cursor_img =
367 1.1 jmcneill (uint32_t *)((uint8_t *)sc->sc_fbaddr + sc->sc_cursor_offset);
368 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GFX_BASE_0,
369 1.1 jmcneill sc->sc_fbhwaddr + sc->sc_cursor_offset);
370 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GFX_TABLE_BASE,
371 1.1 jmcneill sc->sc_dmamem->ds_addr);
372 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GFX_SIZE,
373 1.1 jmcneill 0x003f003f);
374 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GFX_POSITION,
375 1.1 jmcneill 0x00100010);
376 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh,
377 1.1 jmcneill OMAPFB_DISPC_GFX_PRELOAD, 0x60);
378 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GFX_ATTRIBUTES,
379 1.1 jmcneill /*OMAP_DISPC_ATTR_ENABLE |*/
380 1.1 jmcneill OMAP_DISPC_ATTR_BURST_16x32 |
381 1.1 jmcneill OMAP_DISPC_ATTR_ARGB32 |
382 1.1 jmcneill OMAP_DISPC_ATTR_REPLICATION);
383 1.1 jmcneill
384 1.1 jmcneill #if 0
385 1.1 jmcneill printf("dss_control: %08x\n", bus_space_read_4(sc->sc_iot, sc->sc_regh,
386 1.1 jmcneill OMAPFB_DSS_CONTROL));
387 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DSS_CONTROL,
388 1.1 jmcneill /*OMAP_DSSCTRL_DISPC_CLK_SWITCH |*/
389 1.1 jmcneill OMAP_DSSCTRL_CLOCK_MODE |
390 1.1 jmcneill OMAP_DSSCTRL_VENC_CLOCK_4X |
391 1.1 jmcneill OMAP_DSSCTRL_DAC_DEMEN);
392 1.1 jmcneill #endif
393 1.1 jmcneill
394 1.1 jmcneill #if 0
395 1.1 jmcneill /* VENC to NTSC mode */
396 1.1 jmcneill int adr = OMAPFB_VENC_F_CONTROL;
397 1.1 jmcneill for (i = 0; i < __arraycount(venc_mode_ntsc); i++) {
398 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, adr,
399 1.1 jmcneill venc_mode_ntsc[i]);
400 1.1 jmcneill adr += 4;
401 1.1 jmcneill }
402 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_VENC_F_CONTROL,
403 1.1 jmcneill venc_mode_ntsc[0]);
404 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_VENC_SYNC_CTRL,
405 1.1 jmcneill venc_mode_ntsc[2]);
406 1.1 jmcneill
407 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_DEFAULT_COLOR_1,
408 1.1 jmcneill 0x00ff0000);
409 1.1 jmcneill #endif
410 1.1 jmcneill
411 1.1 jmcneill /* now we make sure the video output is actually running */
412 1.1 jmcneill reg = bus_space_read_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONTROL);
413 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONTROL,
414 1.1 jmcneill reg | OMAP_DISPC_CTRL_GO_LCD | OMAP_DISPC_CTRL_GO_DIGITAL);
415 1.1 jmcneill
416 1.1 jmcneill #ifdef OMAPFB_DEBUG
417 1.1 jmcneill printf("attr: %08x\n", bus_space_read_4(sc->sc_iot, sc->sc_regh,
418 1.1 jmcneill OMAPFB_DISPC_GFX_ATTRIBUTES));
419 1.1 jmcneill printf("preload: %08x\n", bus_space_read_4(sc->sc_iot, sc->sc_regh,
420 1.1 jmcneill OMAPFB_DISPC_GFX_PRELOAD));
421 1.1 jmcneill printf("config: %08x\n", bus_space_read_4(sc->sc_iot, sc->sc_regh,
422 1.1 jmcneill OMAPFB_DISPC_CONFIG));
423 1.1 jmcneill printf("control: %08x\n", bus_space_read_4(sc->sc_iot, sc->sc_regh,
424 1.1 jmcneill OMAPFB_DISPC_CONTROL));
425 1.1 jmcneill printf("dss_control: %08x\n", bus_space_read_4(sc->sc_iot, sc->sc_regh,
426 1.1 jmcneill OMAPFB_DSS_CONTROL));
427 1.1 jmcneill printf("threshold: %08x\n", bus_space_read_4(sc->sc_iot, sc->sc_regh,
428 1.1 jmcneill OMAPFB_DISPC_GFX_FIFO_THRESH));
429 1.1 jmcneill printf("GFX size: %08x\n", bus_space_read_4(sc->sc_iot, sc->sc_regh,
430 1.1 jmcneill OMAPFB_DISPC_GFX_SIZE));
431 1.1 jmcneill printf("row inc: %08x\n", bus_space_read_4(sc->sc_iot, sc->sc_regh,
432 1.1 jmcneill OMAPFB_DISPC_GFX_ROW_INC));
433 1.1 jmcneill printf("pixel inc: %08x\n", bus_space_read_4(sc->sc_iot, sc->sc_regh,
434 1.1 jmcneill OMAPFB_DISPC_GFX_PIXEL_INC));
435 1.1 jmcneill #endif
436 1.1 jmcneill
437 1.1 jmcneill sc->sc_defaultscreen_descr = (struct wsscreen_descr){
438 1.1 jmcneill "default",
439 1.1 jmcneill 0, 0,
440 1.1 jmcneill NULL,
441 1.1 jmcneill 8, 16,
442 1.1 jmcneill WSSCREEN_WSCOLORS | WSSCREEN_HILIT,
443 1.1 jmcneill NULL
444 1.1 jmcneill };
445 1.1 jmcneill sc->sc_screens[0] = &sc->sc_defaultscreen_descr;
446 1.1 jmcneill sc->sc_screenlist = (struct wsscreen_list){1, sc->sc_screens};
447 1.1 jmcneill sc->sc_mode = WSDISPLAYIO_MODE_EMUL;
448 1.1 jmcneill sc->sc_locked = 0;
449 1.1 jmcneill
450 1.1 jmcneill vcons_init(&sc->vd, sc, &sc->sc_defaultscreen_descr,
451 1.1 jmcneill &omapfb_accessops);
452 1.1 jmcneill sc->vd.init_screen = omapfb_init_screen;
453 1.1 jmcneill
454 1.1 jmcneill /* init engine here */
455 1.1 jmcneill #if NOMAPDMA > 0
456 1.1 jmcneill omapfb_init(sc);
457 1.1 jmcneill #endif
458 1.1 jmcneill
459 1.1 jmcneill ri = &sc->sc_console_screen.scr_ri;
460 1.1 jmcneill vcons_init_screen(&sc->vd, &sc->sc_console_screen, 1, &defattr);
461 1.1 jmcneill sc->sc_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC;
462 1.1 jmcneill #if NOMAPDMA > 0
463 1.1 jmcneill omapfb_rectfill(sc, 0, 0, sc->sc_width, sc->sc_height,
464 1.1 jmcneill ri->ri_devcmap[(defattr >> 16) & 0xff]);
465 1.1 jmcneill #endif
466 1.1 jmcneill sc->sc_defaultscreen_descr.textops = &ri->ri_ops;
467 1.1 jmcneill sc->sc_defaultscreen_descr.capabilities = ri->ri_caps;
468 1.1 jmcneill sc->sc_defaultscreen_descr.nrows = ri->ri_rows;
469 1.1 jmcneill sc->sc_defaultscreen_descr.ncols = ri->ri_cols;
470 1.1 jmcneill
471 1.1 jmcneill if (is_console)
472 1.1 jmcneill wsdisplay_cnattach(&sc->sc_defaultscreen_descr, ri, 0, 0,
473 1.1 jmcneill defattr);
474 1.1 jmcneill
475 1.1 jmcneill vcons_replay_msgbuf(&sc->sc_console_screen);
476 1.1 jmcneill
477 1.1 jmcneill aa.console = is_console;
478 1.1 jmcneill aa.scrdata = &sc->sc_screenlist;
479 1.1 jmcneill aa.accessops = &omapfb_accessops;
480 1.1 jmcneill aa.accesscookie = &sc->vd;
481 1.1 jmcneill
482 1.1 jmcneill config_found(sc->sc_dev, &aa, wsemuldisplaydevprint);
483 1.1 jmcneill #ifdef OMAPFB_DEBUG
484 1.1 jmcneill #if NOMAPDMA > 0
485 1.1 jmcneill omapfb_rectfill(sc, 100, 100, 100, 100, 0xe000);
486 1.1 jmcneill omapfb_rectfill(sc, 100, 200, 100, 100, 0x01f8);
487 1.1 jmcneill omapfb_rectfill(sc, 200, 100, 100, 100, 0x01f8);
488 1.1 jmcneill omapfb_rectfill(sc, 200, 200, 100, 100, 0xe000);
489 1.1 jmcneill omapfb_bitblt(sc, 100, 100, 400, 100, 200, 200, 0);
490 1.1 jmcneill /* let's see if we can draw something */
491 1.1 jmcneill printf("OMAPDMAC_CDAC: %08x\n", omapdma_read_ch_reg(0, OMAPDMAC_CDAC));
492 1.1 jmcneill printf("OMAPDMAC_CSR: %08x\n", omapdma_read_ch_reg(0, OMAPDMAC_CSR));
493 1.1 jmcneill printf("OMAPDMAC_CCR: %08x\n", omapdma_read_ch_reg(0, OMAPDMAC_CCR));
494 1.1 jmcneill #endif
495 1.1 jmcneill #endif
496 1.1 jmcneill }
497 1.1 jmcneill
498 1.1 jmcneill static int
499 1.1 jmcneill omapfb_ioctl(void *v, void *vs, u_long cmd, void *data, int flag,
500 1.1 jmcneill struct lwp *l)
501 1.1 jmcneill {
502 1.1 jmcneill struct vcons_data *vd = v;
503 1.1 jmcneill struct omapfb_softc *sc = vd->cookie;
504 1.1 jmcneill struct wsdisplay_fbinfo *wdf;
505 1.1 jmcneill struct vcons_screen *ms = vd->active;
506 1.1 jmcneill
507 1.1 jmcneill switch (cmd) {
508 1.1 jmcneill
509 1.1 jmcneill case WSDISPLAYIO_GTYPE:
510 1.1 jmcneill *(u_int *)data = WSDISPLAY_TYPE_OMAP3;
511 1.1 jmcneill return 0;
512 1.1 jmcneill
513 1.1 jmcneill case WSDISPLAYIO_GET_BUSID:
514 1.1 jmcneill {
515 1.1 jmcneill struct wsdisplayio_bus_id *busid;
516 1.1 jmcneill
517 1.1 jmcneill busid = data;
518 1.1 jmcneill busid->bus_type = WSDISPLAYIO_BUS_SOC;
519 1.1 jmcneill return 0;
520 1.1 jmcneill }
521 1.1 jmcneill
522 1.1 jmcneill case WSDISPLAYIO_GINFO:
523 1.1 jmcneill if (ms == NULL)
524 1.1 jmcneill return ENODEV;
525 1.1 jmcneill wdf = (void *)data;
526 1.1 jmcneill wdf->height = ms->scr_ri.ri_height;
527 1.1 jmcneill wdf->width = ms->scr_ri.ri_width;
528 1.1 jmcneill wdf->depth = 32;
529 1.1 jmcneill wdf->cmsize = 256;
530 1.1 jmcneill return 0;
531 1.1 jmcneill
532 1.1 jmcneill case WSDISPLAYIO_GETCMAP:
533 1.1 jmcneill return omapfb_getcmap(sc,
534 1.1 jmcneill (struct wsdisplay_cmap *)data);
535 1.1 jmcneill
536 1.1 jmcneill case WSDISPLAYIO_PUTCMAP:
537 1.1 jmcneill return omapfb_putcmap(sc,
538 1.1 jmcneill (struct wsdisplay_cmap *)data);
539 1.1 jmcneill
540 1.1 jmcneill case WSDISPLAYIO_LINEBYTES:
541 1.1 jmcneill *(u_int *)data = sc->sc_width * 4;
542 1.1 jmcneill return 0;
543 1.1 jmcneill
544 1.1 jmcneill case WSDISPLAYIO_SMODE:
545 1.1 jmcneill {
546 1.1 jmcneill int new_mode = *(int*)data;
547 1.1 jmcneill
548 1.1 jmcneill if (new_mode != sc->sc_mode) {
549 1.1 jmcneill sc->sc_mode = new_mode;
550 1.1 jmcneill if (new_mode == WSDISPLAYIO_MODE_EMUL) {
551 1.1 jmcneill omapfb_set_depth(sc, 16);
552 1.1 jmcneill vcons_redraw_screen(ms);
553 1.1 jmcneill } else {
554 1.1 jmcneill omapfb_set_depth(sc, 32);
555 1.1 jmcneill }
556 1.1 jmcneill }
557 1.1 jmcneill }
558 1.1 jmcneill return 0;
559 1.1 jmcneill
560 1.1 jmcneill case WSDISPLAYIO_GET_FBINFO:
561 1.1 jmcneill {
562 1.1 jmcneill struct wsdisplayio_fbinfo *fbi = data;
563 1.1 jmcneill
564 1.1 jmcneill fbi->fbi_width = sc->sc_width;
565 1.1 jmcneill fbi->fbi_height = sc->sc_height;
566 1.1 jmcneill fbi->fbi_stride = sc->sc_width << 2;
567 1.1 jmcneill fbi->fbi_bitsperpixel = 32;
568 1.1 jmcneill fbi->fbi_pixeltype = WSFB_RGB;
569 1.1 jmcneill fbi->fbi_subtype.fbi_rgbmasks.red_offset = 16;
570 1.1 jmcneill fbi->fbi_subtype.fbi_rgbmasks.red_size = 8;
571 1.1 jmcneill fbi->fbi_subtype.fbi_rgbmasks.green_offset = 8;
572 1.1 jmcneill fbi->fbi_subtype.fbi_rgbmasks.green_size = 8;
573 1.1 jmcneill fbi->fbi_subtype.fbi_rgbmasks.blue_offset = 0;
574 1.1 jmcneill fbi->fbi_subtype.fbi_rgbmasks.blue_size = 8;
575 1.1 jmcneill fbi->fbi_subtype.fbi_rgbmasks.alpha_offset = 0;
576 1.1 jmcneill fbi->fbi_subtype.fbi_rgbmasks.alpha_size = 0;
577 1.1 jmcneill fbi->fbi_flags = 0;
578 1.1 jmcneill fbi->fbi_fbsize = sc->sc_vramsize;
579 1.1 jmcneill fbi->fbi_fboffset = 0;
580 1.1 jmcneill fbi->fbi_flags = WSFB_VRAM_IS_RAM;
581 1.1 jmcneill
582 1.1 jmcneill }
583 1.1 jmcneill return 0;
584 1.1 jmcneill
585 1.1 jmcneill case WSDISPLAYIO_GVIDEO:
586 1.1 jmcneill {
587 1.1 jmcneill int *on = data;
588 1.1 jmcneill *on = sc->sc_video_is_on;
589 1.1 jmcneill }
590 1.1 jmcneill return 0;
591 1.1 jmcneill
592 1.1 jmcneill case WSDISPLAYIO_SVIDEO:
593 1.1 jmcneill {
594 1.1 jmcneill int *on = data;
595 1.1 jmcneill omapfb_set_video(sc, *on);
596 1.1 jmcneill }
597 1.1 jmcneill return 0;
598 1.1 jmcneill
599 1.1 jmcneill case WSDISPLAYIO_GCURPOS:
600 1.1 jmcneill {
601 1.1 jmcneill struct wsdisplay_curpos *cp = (void *)data;
602 1.1 jmcneill
603 1.1 jmcneill cp->x = sc->sc_cursor_x;
604 1.1 jmcneill cp->y = sc->sc_cursor_y;
605 1.1 jmcneill }
606 1.1 jmcneill return 0;
607 1.1 jmcneill case WSDISPLAYIO_SCURPOS:
608 1.1 jmcneill {
609 1.1 jmcneill struct wsdisplay_curpos *cp = (void *)data;
610 1.1 jmcneill
611 1.1 jmcneill omapfb_move_cursor(sc, cp->x, cp->y);
612 1.1 jmcneill }
613 1.1 jmcneill return 0;
614 1.1 jmcneill case WSDISPLAYIO_GCURMAX:
615 1.1 jmcneill {
616 1.1 jmcneill struct wsdisplay_curpos *cp = (void *)data;
617 1.1 jmcneill
618 1.1 jmcneill cp->x = 64;
619 1.1 jmcneill cp->y = 64;
620 1.1 jmcneill }
621 1.1 jmcneill return 0;
622 1.1 jmcneill case WSDISPLAYIO_SCURSOR:
623 1.1 jmcneill {
624 1.1 jmcneill struct wsdisplay_cursor *cursor = (void *)data;
625 1.1 jmcneill
626 1.1 jmcneill return omapfb_do_cursor(sc, cursor);
627 1.1 jmcneill }
628 1.1 jmcneill }
629 1.1 jmcneill return EPASSTHROUGH;
630 1.1 jmcneill }
631 1.1 jmcneill
632 1.1 jmcneill static paddr_t
633 1.1 jmcneill omapfb_mmap(void *v, void *vs, off_t offset, int prot)
634 1.1 jmcneill {
635 1.1 jmcneill paddr_t pa = -1;
636 1.1 jmcneill struct vcons_data *vd = v;
637 1.1 jmcneill struct omapfb_softc *sc = vd->cookie;
638 1.1 jmcneill
639 1.1 jmcneill /* 'regular' framebuffer mmap()ing */
640 1.1 jmcneill if (offset < sc->sc_vramsize) {
641 1.1 jmcneill pa = bus_dmamem_mmap(sc->sc_dmat, sc->sc_dmamem, 1,
642 1.1 jmcneill offset + PAGE_SIZE, prot, BUS_DMA_PREFETCHABLE);
643 1.1 jmcneill return pa;
644 1.1 jmcneill }
645 1.1 jmcneill return pa;
646 1.1 jmcneill }
647 1.1 jmcneill
648 1.1 jmcneill static void
649 1.1 jmcneill omapfb_init_screen(void *cookie, struct vcons_screen *scr,
650 1.1 jmcneill int existing, long *defattr)
651 1.1 jmcneill {
652 1.1 jmcneill struct omapfb_softc *sc = cookie;
653 1.1 jmcneill struct rasops_info *ri = &scr->scr_ri;
654 1.1 jmcneill
655 1.1 jmcneill ri->ri_depth = sc->sc_depth;
656 1.1 jmcneill ri->ri_width = sc->sc_width;
657 1.1 jmcneill ri->ri_height = sc->sc_height;
658 1.1 jmcneill ri->ri_stride = sc->sc_stride;
659 1.1 jmcneill ri->ri_flg = RI_CENTER | RI_FULLCLEAR;
660 1.1 jmcneill
661 1.1 jmcneill ri->ri_bits = (char *)sc->sc_fbaddr;
662 1.1 jmcneill
663 1.1 jmcneill #if NOMAPDMA < 1
664 1.1 jmcneill scr->scr_flags |= VCONS_DONT_READ;
665 1.1 jmcneill #endif
666 1.1 jmcneill
667 1.1 jmcneill if (existing) {
668 1.1 jmcneill ri->ri_flg |= RI_CLEAR;
669 1.1 jmcneill }
670 1.1 jmcneill
671 1.1 jmcneill rasops_init(ri, sc->sc_height / 8, sc->sc_width / 8);
672 1.1 jmcneill ri->ri_caps = WSSCREEN_WSCOLORS;
673 1.1 jmcneill
674 1.1 jmcneill rasops_reconfig(ri, sc->sc_height / ri->ri_font->fontheight,
675 1.1 jmcneill sc->sc_width / ri->ri_font->fontwidth);
676 1.1 jmcneill
677 1.1 jmcneill ri->ri_hw = scr;
678 1.1 jmcneill
679 1.1 jmcneill #if NOMAPDMA > 0
680 1.1 jmcneill ri->ri_ops.copyrows = omapfb_copyrows;
681 1.1 jmcneill ri->ri_ops.copycols = omapfb_copycols;
682 1.1 jmcneill ri->ri_ops.eraserows = omapfb_eraserows;
683 1.1 jmcneill ri->ri_ops.erasecols = omapfb_erasecols;
684 1.1 jmcneill ri->ri_ops.cursor = omapfb_cursor;
685 1.1 jmcneill sc->sc_putchar = ri->ri_ops.putchar;
686 1.1 jmcneill ri->ri_ops.putchar = omapfb_putchar;
687 1.1 jmcneill #endif
688 1.1 jmcneill }
689 1.1 jmcneill
690 1.1 jmcneill static int
691 1.1 jmcneill omapfb_putcmap(struct omapfb_softc *sc, struct wsdisplay_cmap *cm)
692 1.1 jmcneill {
693 1.1 jmcneill u_char *r, *g, *b;
694 1.1 jmcneill u_int index = cm->index;
695 1.1 jmcneill u_int count = cm->count;
696 1.1 jmcneill int i, error;
697 1.1 jmcneill u_char rbuf[256], gbuf[256], bbuf[256];
698 1.1 jmcneill
699 1.1 jmcneill if (cm->index >= 256 || cm->count > 256 ||
700 1.1 jmcneill (cm->index + cm->count) > 256)
701 1.1 jmcneill return EINVAL;
702 1.1 jmcneill error = copyin(cm->red, &rbuf[index], count);
703 1.1 jmcneill if (error)
704 1.1 jmcneill return error;
705 1.1 jmcneill error = copyin(cm->green, &gbuf[index], count);
706 1.1 jmcneill if (error)
707 1.1 jmcneill return error;
708 1.1 jmcneill error = copyin(cm->blue, &bbuf[index], count);
709 1.1 jmcneill if (error)
710 1.1 jmcneill return error;
711 1.1 jmcneill
712 1.1 jmcneill memcpy(&sc->sc_cmap_red[index], &rbuf[index], count);
713 1.1 jmcneill memcpy(&sc->sc_cmap_green[index], &gbuf[index], count);
714 1.1 jmcneill memcpy(&sc->sc_cmap_blue[index], &bbuf[index], count);
715 1.1 jmcneill
716 1.1 jmcneill r = &sc->sc_cmap_red[index];
717 1.1 jmcneill g = &sc->sc_cmap_green[index];
718 1.1 jmcneill b = &sc->sc_cmap_blue[index];
719 1.1 jmcneill
720 1.1 jmcneill for (i = 0; i < count; i++) {
721 1.1 jmcneill omapfb_putpalreg(sc, index, *r, *g, *b);
722 1.1 jmcneill index++;
723 1.1 jmcneill r++, g++, b++;
724 1.1 jmcneill }
725 1.1 jmcneill return 0;
726 1.1 jmcneill }
727 1.1 jmcneill
728 1.1 jmcneill static int
729 1.1 jmcneill omapfb_getcmap(struct omapfb_softc *sc, struct wsdisplay_cmap *cm)
730 1.1 jmcneill {
731 1.1 jmcneill u_int index = cm->index;
732 1.1 jmcneill u_int count = cm->count;
733 1.1 jmcneill int error;
734 1.1 jmcneill
735 1.1 jmcneill if (index >= 255 || count > 256 || index + count > 256)
736 1.1 jmcneill return EINVAL;
737 1.1 jmcneill
738 1.1 jmcneill error = copyout(&sc->sc_cmap_red[index], cm->red, count);
739 1.1 jmcneill if (error)
740 1.1 jmcneill return error;
741 1.1 jmcneill error = copyout(&sc->sc_cmap_green[index], cm->green, count);
742 1.1 jmcneill if (error)
743 1.1 jmcneill return error;
744 1.1 jmcneill error = copyout(&sc->sc_cmap_blue[index], cm->blue, count);
745 1.1 jmcneill if (error)
746 1.1 jmcneill return error;
747 1.1 jmcneill
748 1.1 jmcneill return 0;
749 1.1 jmcneill }
750 1.1 jmcneill
751 1.1 jmcneill static void
752 1.1 jmcneill omapfb_restore_palette(struct omapfb_softc *sc)
753 1.1 jmcneill {
754 1.1 jmcneill int i;
755 1.1 jmcneill
756 1.1 jmcneill for (i = 0; i < 256; i++) {
757 1.1 jmcneill omapfb_putpalreg(sc, i, sc->sc_cmap_red[i],
758 1.1 jmcneill sc->sc_cmap_green[i], sc->sc_cmap_blue[i]);
759 1.1 jmcneill }
760 1.1 jmcneill }
761 1.1 jmcneill
762 1.1 jmcneill static void
763 1.1 jmcneill omapfb_putpalreg(struct omapfb_softc *sc, int idx, uint8_t r, uint8_t g,
764 1.1 jmcneill uint8_t b)
765 1.1 jmcneill {
766 1.1 jmcneill uint32_t reg;
767 1.1 jmcneill
768 1.1 jmcneill if ((idx < 0) || (idx > 255))
769 1.1 jmcneill return;
770 1.1 jmcneill /* whack the DAC */
771 1.1 jmcneill reg = (r << 16) | (g << 8) | b;
772 1.1 jmcneill sc->sc_clut[idx] = reg;
773 1.1 jmcneill }
774 1.1 jmcneill
775 1.1 jmcneill static int
776 1.1 jmcneill omapfb_set_depth(struct omapfb_softc *sc, int d)
777 1.1 jmcneill {
778 1.1 jmcneill uint32_t reg;
779 1.1 jmcneill
780 1.1 jmcneill reg = OMAP_VID_ATTR_ENABLE |
781 1.1 jmcneill OMAP_VID_ATTR_BURST_16x32 |
782 1.1 jmcneill OMAP_VID_ATTR_REPLICATION;
783 1.1 jmcneill switch (d) {
784 1.1 jmcneill case 16:
785 1.1 jmcneill reg |= OMAP_VID_ATTR_RGB16;
786 1.1 jmcneill break;
787 1.1 jmcneill case 32:
788 1.1 jmcneill reg |= OMAP_VID_ATTR_RGB24;
789 1.1 jmcneill break;
790 1.1 jmcneill default:
791 1.1 jmcneill aprint_error_dev(sc->sc_dev,
792 1.1 jmcneill "unsupported depth (%d)\n", d);
793 1.1 jmcneill return EINVAL;
794 1.1 jmcneill }
795 1.1 jmcneill
796 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh,
797 1.1 jmcneill OMAPFB_DISPC_VID1_ATTRIBUTES, reg);
798 1.1 jmcneill
799 1.1 jmcneill /*
800 1.1 jmcneill * now tell the video controller that we're done mucking around and
801 1.1 jmcneill * actually update its settings
802 1.1 jmcneill */
803 1.1 jmcneill reg = bus_space_read_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONTROL);
804 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONTROL,
805 1.1 jmcneill reg | OMAP_DISPC_CTRL_GO_LCD | OMAP_DISPC_CTRL_GO_DIGITAL);
806 1.1 jmcneill
807 1.1 jmcneill sc->sc_depth = d;
808 1.1 jmcneill sc->sc_stride = sc->sc_width * (sc->sc_depth >> 3);
809 1.1 jmcneill
810 1.1 jmcneill /* clear the screen here */
811 1.1 jmcneill #if NOMAPDMA > 0
812 1.1 jmcneill omapfb_rectfill(sc, 0, 0, sc->sc_width, sc->sc_height, 0);
813 1.1 jmcneill #else
814 1.1 jmcneill memset(sc->sc_fbaddr, 0, sc->sc_stride * sc->sc_height);
815 1.1 jmcneill #endif
816 1.1 jmcneill return 0;
817 1.1 jmcneill }
818 1.1 jmcneill
819 1.1 jmcneill static void
820 1.1 jmcneill omapfb_set_video(struct omapfb_softc *sc, int on)
821 1.1 jmcneill {
822 1.1 jmcneill uint32_t reg;
823 1.1 jmcneill
824 1.1 jmcneill if (on == sc->sc_video_is_on)
825 1.1 jmcneill return;
826 1.1 jmcneill if (on) {
827 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh,
828 1.1 jmcneill OMAPFB_DISPC_CONFIG, sc->sc_dispc_config);
829 1.1 jmcneill on = 1;
830 1.1 jmcneill } else {
831 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh,
832 1.1 jmcneill OMAPFB_DISPC_CONFIG, sc->sc_dispc_config |
833 1.1 jmcneill OMAP_DISPC_CFG_VSYNC_GATED | OMAP_DISPC_CFG_HSYNC_GATED |
834 1.1 jmcneill OMAP_DISPC_CFG_PIXELCLK_GATED |
835 1.1 jmcneill OMAP_DISPC_CFG_PIXELDATA_GATED);
836 1.1 jmcneill }
837 1.1 jmcneill
838 1.1 jmcneill /*
839 1.1 jmcneill * now tell the video controller that we're done mucking around and
840 1.1 jmcneill * actually update its settings
841 1.1 jmcneill */
842 1.1 jmcneill reg = bus_space_read_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONTROL);
843 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONTROL,
844 1.1 jmcneill reg | OMAP_DISPC_CTRL_GO_LCD | OMAP_DISPC_CTRL_GO_DIGITAL);
845 1.1 jmcneill
846 1.1 jmcneill aprint_debug_dev(sc->sc_dev, "%s %08x\n", __func__,
847 1.1 jmcneill bus_space_read_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONFIG));
848 1.1 jmcneill sc->sc_video_is_on = on;
849 1.1 jmcneill }
850 1.1 jmcneill
851 1.1 jmcneill #if NOMAPDMA > 0
852 1.1 jmcneill static void
853 1.1 jmcneill omapfb_init(struct omapfb_softc *sc)
854 1.1 jmcneill {
855 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CLNK_CTRL, 0);
856 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CICRI, 0);
857 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CSDPI,
858 1.1 jmcneill CSDPI_SRC_BURST_64 | CSDPI_DST_BURST_64 |
859 1.1 jmcneill CSDPI_WRITE_POSTED | CSDPI_DATA_TYPE_16);
860 1.1 jmcneill }
861 1.1 jmcneill
862 1.1 jmcneill static void
863 1.1 jmcneill omapfb_wait_idle(struct omapfb_softc *sc)
864 1.1 jmcneill {
865 1.1 jmcneill while ((omapdma_read_ch_reg(0, OMAPDMAC_CCR) & CCR_WR_ACTIVE) != 0);
866 1.1 jmcneill }
867 1.1 jmcneill
868 1.1 jmcneill static void
869 1.1 jmcneill omapfb_rectfill(struct omapfb_softc *sc, int x, int y, int wi, int he,
870 1.1 jmcneill uint32_t colour)
871 1.1 jmcneill {
872 1.1 jmcneill int bpp = sc->sc_depth >> 3; /* bytes per pixel */
873 1.1 jmcneill int width_in_bytes = wi * bpp;
874 1.1 jmcneill uint32_t daddr;
875 1.1 jmcneill
876 1.1 jmcneill daddr = sc->sc_fbhwaddr + sc->sc_stride * y + x * bpp;
877 1.1 jmcneill omapfb_wait_idle(sc);
878 1.1 jmcneill
879 1.1 jmcneill /*
880 1.1 jmcneill * stupid hardware
881 1.1 jmcneill * in 32bit mode the DMA controller always writes 0 into the upper
882 1.1 jmcneill * byte, so we can use this mode only if we actually want that
883 1.1 jmcneill */
884 1.1 jmcneill if (((colour & 0xff00) == 0) &&
885 1.1 jmcneill (((daddr | width_in_bytes) & 3) == 0)) {
886 1.1 jmcneill /*
887 1.1 jmcneill * everything is properly aligned so we can copy stuff in
888 1.1 jmcneill * 32bit chunks instead of pixel by pixel
889 1.1 jmcneill */
890 1.1 jmcneill wi = wi >> 1;
891 1.1 jmcneill
892 1.1 jmcneill /* just in case */
893 1.1 jmcneill colour |= colour << 16;
894 1.1 jmcneill
895 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CSDPI,
896 1.1 jmcneill CSDPI_SRC_BURST_64 | CSDPI_DST_BURST_64 |
897 1.1 jmcneill CSDPI_DST_PACKED | CSDPI_WRITE_POSTED_EXCEPT_LAST |
898 1.1 jmcneill CSDPI_DATA_TYPE_32);
899 1.1 jmcneill } else {
900 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CSDPI,
901 1.1 jmcneill CSDPI_SRC_BURST_64 | CSDPI_DST_BURST_64 |
902 1.1 jmcneill CSDPI_DST_PACKED | CSDPI_WRITE_POSTED_EXCEPT_LAST |
903 1.1 jmcneill CSDPI_DATA_TYPE_16);
904 1.1 jmcneill }
905 1.1 jmcneill
906 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CEN, wi);
907 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CFN, he);
908 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CDSA, daddr);
909 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CCR,
910 1.1 jmcneill CCR_CONST_FILL_ENABLE | CCR_DST_AMODE_DOUBLE_INDEX |
911 1.1 jmcneill CCR_SRC_AMODE_CONST_ADDR);
912 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CDEI, 1);
913 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CDFI,
914 1.1 jmcneill (sc->sc_stride - width_in_bytes) + 1);
915 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_COLOR, colour);
916 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CCR,
917 1.1 jmcneill CCR_CONST_FILL_ENABLE | CCR_DST_AMODE_DOUBLE_INDEX |
918 1.1 jmcneill CCR_SRC_AMODE_CONST_ADDR | CCR_ENABLE);
919 1.1 jmcneill }
920 1.1 jmcneill
921 1.1 jmcneill static void
922 1.1 jmcneill omapfb_bitblt(struct omapfb_softc *sc, int xs, int ys, int xd, int yd,
923 1.1 jmcneill int wi, int he, int rop)
924 1.1 jmcneill {
925 1.1 jmcneill int bpp = sc->sc_depth >> 3; /* bytes per pixel */
926 1.1 jmcneill int width_in_bytes = wi * bpp;
927 1.1 jmcneill
928 1.1 jmcneill int hstep, vstep;
929 1.1 jmcneill uint32_t saddr, daddr;
930 1.1 jmcneill
931 1.1 jmcneill saddr = sc->sc_fbhwaddr + sc->sc_stride * ys + xs * bpp;
932 1.1 jmcneill daddr = sc->sc_fbhwaddr + sc->sc_stride * yd + xd * bpp;
933 1.1 jmcneill
934 1.1 jmcneill if (ys < yd) {
935 1.1 jmcneill /* need to go vertically backwards */
936 1.1 jmcneill vstep = 1 - (sc->sc_stride + width_in_bytes);
937 1.1 jmcneill saddr += sc->sc_stride * (he - 1);
938 1.1 jmcneill daddr += sc->sc_stride * (he - 1);
939 1.1 jmcneill } else
940 1.1 jmcneill vstep = (sc->sc_stride - width_in_bytes) + 1;
941 1.1 jmcneill if ((xs < xd) && (ys == yd)) {
942 1.1 jmcneill /*
943 1.1 jmcneill * need to go horizontally backwards, only needed if source
944 1.1 jmcneill * and destination pixels are on the same line
945 1.1 jmcneill */
946 1.1 jmcneill hstep = 1 - (sc->sc_depth >> 2);
947 1.1 jmcneill vstep = sc->sc_stride + bpp * (wi - 1) + 1;
948 1.1 jmcneill saddr += bpp * (wi - 1);
949 1.1 jmcneill daddr += bpp * (wi - 1);
950 1.1 jmcneill } else
951 1.1 jmcneill hstep = 1;
952 1.1 jmcneill
953 1.1 jmcneill omapfb_wait_idle(sc);
954 1.1 jmcneill if (((saddr | daddr | width_in_bytes) & 3) == 0) {
955 1.1 jmcneill /*
956 1.1 jmcneill * everything is properly aligned so we can copy stuff in
957 1.1 jmcneill * 32bit chunks instead of pixel by pixel
958 1.1 jmcneill */
959 1.1 jmcneill wi = wi >> 1;
960 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CSDPI,
961 1.1 jmcneill CSDPI_SRC_BURST_64 | CSDPI_DST_BURST_64 |
962 1.1 jmcneill CSDPI_DST_PACKED | CSDPI_WRITE_POSTED_EXCEPT_LAST |
963 1.1 jmcneill CSDPI_DATA_TYPE_32);
964 1.1 jmcneill } else {
965 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CSDPI,
966 1.1 jmcneill CSDPI_SRC_BURST_64 | CSDPI_DST_BURST_64 |
967 1.1 jmcneill CSDPI_DST_PACKED | CSDPI_WRITE_POSTED_EXCEPT_LAST |
968 1.1 jmcneill CSDPI_DATA_TYPE_16);
969 1.1 jmcneill }
970 1.1 jmcneill
971 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CEN, wi);
972 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CFN, he);
973 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CSSA, saddr);
974 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CDSA, daddr);
975 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CCR,
976 1.1 jmcneill CCR_DST_AMODE_DOUBLE_INDEX |
977 1.1 jmcneill CCR_SRC_AMODE_DOUBLE_INDEX);
978 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CSEI, hstep);
979 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CSFI, vstep);
980 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CDEI, hstep);
981 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CDFI, vstep);
982 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CCR,
983 1.1 jmcneill CCR_DST_AMODE_DOUBLE_INDEX |
984 1.1 jmcneill CCR_SRC_AMODE_DOUBLE_INDEX | CCR_ENABLE);
985 1.1 jmcneill }
986 1.1 jmcneill
987 1.1 jmcneill static void
988 1.1 jmcneill omapfb_cursor(void *cookie, int on, int row, int col)
989 1.1 jmcneill {
990 1.1 jmcneill struct rasops_info *ri = cookie;
991 1.1 jmcneill struct vcons_screen *scr = ri->ri_hw;
992 1.1 jmcneill struct omapfb_softc *sc = scr->scr_cookie;
993 1.1 jmcneill int pos;
994 1.1 jmcneill
995 1.1 jmcneill pos = col + row * ri->ri_cols;
996 1.1 jmcneill #ifdef WSDISPLAY_SCROLLSUPPORT
997 1.1 jmcneill pos += scr->scr_offset_to_zero;
998 1.1 jmcneill #endif
999 1.1 jmcneill if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) {
1000 1.1 jmcneill if (ri->ri_flg & RI_CURSOR) {
1001 1.1 jmcneill omapfb_putchar(cookie, row, col, scr->scr_chars[pos],
1002 1.1 jmcneill scr->scr_attrs[pos]);
1003 1.1 jmcneill ri->ri_flg &= ~RI_CURSOR;
1004 1.1 jmcneill }
1005 1.1 jmcneill ri->ri_crow = row;
1006 1.1 jmcneill ri->ri_ccol = col;
1007 1.1 jmcneill if (on) {
1008 1.1 jmcneill omapfb_putchar(cookie, row, col, scr->scr_chars[pos],
1009 1.1 jmcneill scr->scr_attrs[pos] ^ 0x0f0f0000);
1010 1.1 jmcneill ri->ri_flg |= RI_CURSOR;
1011 1.1 jmcneill }
1012 1.1 jmcneill } else {
1013 1.1 jmcneill scr->scr_ri.ri_crow = row;
1014 1.1 jmcneill scr->scr_ri.ri_ccol = col;
1015 1.1 jmcneill scr->scr_ri.ri_flg &= ~RI_CURSOR;
1016 1.1 jmcneill }
1017 1.1 jmcneill }
1018 1.1 jmcneill
1019 1.1 jmcneill static void
1020 1.1 jmcneill omapfb_putchar(void *cookie, int row, int col, u_int c, long attr)
1021 1.1 jmcneill {
1022 1.1 jmcneill struct rasops_info *ri = cookie;
1023 1.1 jmcneill struct vcons_screen *scr = ri->ri_hw;
1024 1.1 jmcneill struct omapfb_softc *sc = scr->scr_cookie;
1025 1.1 jmcneill
1026 1.1 jmcneill if (c == 0x20) {
1027 1.1 jmcneill uint32_t fg, bg, ul;
1028 1.1 jmcneill rasops_unpack_attr(attr, &fg, &bg, &ul);
1029 1.1 jmcneill omapfb_rectfill(sc,
1030 1.1 jmcneill ri->ri_xorigin + ri->ri_font->fontwidth * col,
1031 1.1 jmcneill ri->ri_yorigin + ri->ri_font->fontheight * row,
1032 1.1 jmcneill ri->ri_font->fontwidth,
1033 1.1 jmcneill ri->ri_font->fontheight,
1034 1.1 jmcneill ri->ri_devcmap[bg]);
1035 1.1 jmcneill return;
1036 1.1 jmcneill }
1037 1.1 jmcneill omapfb_wait_idle(sc);
1038 1.1 jmcneill sc->sc_putchar(cookie, row, col, c, attr);
1039 1.1 jmcneill }
1040 1.1 jmcneill
1041 1.1 jmcneill static void
1042 1.1 jmcneill omapfb_copycols(void *cookie, int row, int srccol, int dstcol, int ncols)
1043 1.1 jmcneill {
1044 1.1 jmcneill struct rasops_info *ri = cookie;
1045 1.1 jmcneill struct vcons_screen *scr = ri->ri_hw;
1046 1.1 jmcneill struct omapfb_softc *sc = scr->scr_cookie;
1047 1.1 jmcneill int32_t xs, xd, y, width, height;
1048 1.1 jmcneill
1049 1.1 jmcneill if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
1050 1.1 jmcneill xs = ri->ri_xorigin + ri->ri_font->fontwidth * srccol;
1051 1.1 jmcneill xd = ri->ri_xorigin + ri->ri_font->fontwidth * dstcol;
1052 1.1 jmcneill y = ri->ri_yorigin + ri->ri_font->fontheight * row;
1053 1.1 jmcneill width = ri->ri_font->fontwidth * ncols;
1054 1.1 jmcneill height = ri->ri_font->fontheight;
1055 1.1 jmcneill omapfb_bitblt(sc, xs, y, xd, y, width, height, 12);
1056 1.1 jmcneill }
1057 1.1 jmcneill }
1058 1.1 jmcneill
1059 1.1 jmcneill static void
1060 1.1 jmcneill omapfb_erasecols(void *cookie, int row, int startcol, int ncols, long fillattr)
1061 1.1 jmcneill {
1062 1.1 jmcneill struct rasops_info *ri = cookie;
1063 1.1 jmcneill struct vcons_screen *scr = ri->ri_hw;
1064 1.1 jmcneill struct omapfb_softc *sc = scr->scr_cookie;
1065 1.1 jmcneill int32_t x, y, width, height, fg, bg, ul;
1066 1.1 jmcneill
1067 1.1 jmcneill if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
1068 1.1 jmcneill x = ri->ri_xorigin + ri->ri_font->fontwidth * startcol;
1069 1.1 jmcneill y = ri->ri_yorigin + ri->ri_font->fontheight * row;
1070 1.1 jmcneill width = ri->ri_font->fontwidth * ncols;
1071 1.1 jmcneill height = ri->ri_font->fontheight;
1072 1.1 jmcneill rasops_unpack_attr(fillattr, &fg, &bg, &ul);
1073 1.1 jmcneill
1074 1.1 jmcneill omapfb_rectfill(sc, x, y, width, height, ri->ri_devcmap[bg]);
1075 1.1 jmcneill }
1076 1.1 jmcneill }
1077 1.1 jmcneill
1078 1.1 jmcneill static void
1079 1.1 jmcneill omapfb_copyrows(void *cookie, int srcrow, int dstrow, int nrows)
1080 1.1 jmcneill {
1081 1.1 jmcneill struct rasops_info *ri = cookie;
1082 1.1 jmcneill struct vcons_screen *scr = ri->ri_hw;
1083 1.1 jmcneill struct omapfb_softc *sc = scr->scr_cookie;
1084 1.1 jmcneill int32_t x, ys, yd, width, height;
1085 1.1 jmcneill
1086 1.1 jmcneill if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
1087 1.1 jmcneill x = ri->ri_xorigin;
1088 1.1 jmcneill ys = ri->ri_yorigin + ri->ri_font->fontheight * srcrow;
1089 1.1 jmcneill yd = ri->ri_yorigin + ri->ri_font->fontheight * dstrow;
1090 1.1 jmcneill width = ri->ri_emuwidth;
1091 1.1 jmcneill height = ri->ri_font->fontheight * nrows;
1092 1.1 jmcneill omapfb_bitblt(sc, x, ys, x, yd, width, height, 12);
1093 1.1 jmcneill }
1094 1.1 jmcneill }
1095 1.1 jmcneill
1096 1.1 jmcneill static void
1097 1.1 jmcneill omapfb_eraserows(void *cookie, int row, int nrows, long fillattr)
1098 1.1 jmcneill {
1099 1.1 jmcneill struct rasops_info *ri = cookie;
1100 1.1 jmcneill struct vcons_screen *scr = ri->ri_hw;
1101 1.1 jmcneill struct omapfb_softc *sc = scr->scr_cookie;
1102 1.1 jmcneill int32_t x, y, width, height, fg, bg, ul;
1103 1.1 jmcneill
1104 1.1 jmcneill if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
1105 1.1 jmcneill x = ri->ri_xorigin;
1106 1.1 jmcneill y = ri->ri_yorigin + ri->ri_font->fontheight * row;
1107 1.1 jmcneill width = ri->ri_emuwidth;
1108 1.1 jmcneill height = ri->ri_font->fontheight * nrows;
1109 1.1 jmcneill rasops_unpack_attr(fillattr, &fg, &bg, &ul);
1110 1.1 jmcneill
1111 1.1 jmcneill omapfb_rectfill(sc, x, y, width, height, ri->ri_devcmap[bg]);
1112 1.1 jmcneill }
1113 1.1 jmcneill }
1114 1.1 jmcneill #endif /* NOMAPDMA > 0 */
1115 1.1 jmcneill
1116 1.1 jmcneill static void
1117 1.1 jmcneill omapfb_move_cursor(struct omapfb_softc *sc, int x, int y)
1118 1.1 jmcneill {
1119 1.1 jmcneill uint32_t pos, reg, addr;
1120 1.1 jmcneill int xx, yy, wi = 64, he = 64;
1121 1.1 jmcneill
1122 1.1 jmcneill /*
1123 1.1 jmcneill * we need to special case anything and everything where the cursor
1124 1.1 jmcneill * may be partially off screen
1125 1.1 jmcneill */
1126 1.1 jmcneill
1127 1.1 jmcneill addr = sc->sc_fbhwaddr + sc->sc_cursor_offset;
1128 1.1 jmcneill xx = x - sc->sc_hot_x;
1129 1.1 jmcneill yy = y - sc->sc_hot_y;
1130 1.1 jmcneill
1131 1.1 jmcneill /*
1132 1.1 jmcneill * if we're off to the top or left we need to shif the start address
1133 1.1 jmcneill * and shrink the gfx layer size
1134 1.1 jmcneill */
1135 1.1 jmcneill if (xx < 0) {
1136 1.1 jmcneill wi += xx;
1137 1.1 jmcneill addr -= xx * 4;
1138 1.1 jmcneill xx = 0;
1139 1.1 jmcneill }
1140 1.1 jmcneill if (yy < 0) {
1141 1.1 jmcneill he += yy;
1142 1.1 jmcneill addr -= yy * 64 * 4;
1143 1.1 jmcneill yy = 0;
1144 1.1 jmcneill }
1145 1.1 jmcneill if (xx > (sc->sc_width - 64)) {
1146 1.1 jmcneill wi -= (xx + 64 - sc->sc_width);
1147 1.1 jmcneill }
1148 1.1 jmcneill if (yy > (sc->sc_height - 64)) {
1149 1.1 jmcneill he -= (yy + 64 - sc->sc_height);
1150 1.1 jmcneill }
1151 1.1 jmcneill pos = (yy << 16) | xx;
1152 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GFX_BASE_0,
1153 1.1 jmcneill addr);
1154 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GFX_POSITION,
1155 1.1 jmcneill pos);
1156 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GFX_SIZE,
1157 1.1 jmcneill ((he - 1) << 16) | (wi - 1));
1158 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GFX_ROW_INC,
1159 1.1 jmcneill (64 - wi) * 4 + 1);
1160 1.1 jmcneill /*
1161 1.1 jmcneill * now tell the video controller that we're done mucking around and
1162 1.1 jmcneill * actually update its settings
1163 1.1 jmcneill */
1164 1.1 jmcneill reg = bus_space_read_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONTROL);
1165 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONTROL,
1166 1.1 jmcneill reg | OMAP_DISPC_CTRL_GO_LCD | OMAP_DISPC_CTRL_GO_DIGITAL);
1167 1.1 jmcneill }
1168 1.1 jmcneill
1169 1.1 jmcneill static int
1170 1.1 jmcneill omapfb_do_cursor(struct omapfb_softc * sc,
1171 1.1 jmcneill struct wsdisplay_cursor *cur)
1172 1.1 jmcneill {
1173 1.1 jmcneill int whack = 0;
1174 1.1 jmcneill int shape = 0;
1175 1.1 jmcneill
1176 1.1 jmcneill if (cur->which & WSDISPLAY_CURSOR_DOCUR) {
1177 1.1 jmcneill uint32_t attr = OMAP_DISPC_ATTR_BURST_16x32 |
1178 1.1 jmcneill OMAP_DISPC_ATTR_ARGB32 |
1179 1.1 jmcneill OMAP_DISPC_ATTR_REPLICATION;
1180 1.1 jmcneill
1181 1.1 jmcneill if (cur->enable) attr |= OMAP_DISPC_ATTR_ENABLE;
1182 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh,
1183 1.1 jmcneill OMAPFB_DISPC_GFX_ATTRIBUTES, attr);
1184 1.1 jmcneill whack = 1;
1185 1.1 jmcneill }
1186 1.1 jmcneill if (cur->which & WSDISPLAY_CURSOR_DOHOT) {
1187 1.1 jmcneill
1188 1.1 jmcneill sc->sc_hot_x = cur->hot.x;
1189 1.1 jmcneill sc->sc_hot_y = cur->hot.y;
1190 1.1 jmcneill cur->which |= WSDISPLAY_CURSOR_DOPOS;
1191 1.1 jmcneill }
1192 1.1 jmcneill if (cur->which & WSDISPLAY_CURSOR_DOPOS) {
1193 1.1 jmcneill
1194 1.1 jmcneill omapfb_move_cursor(sc, cur->pos.x, cur->pos.y);
1195 1.1 jmcneill }
1196 1.1 jmcneill if (cur->which & WSDISPLAY_CURSOR_DOCMAP) {
1197 1.1 jmcneill int i;
1198 1.1 jmcneill uint32_t val;
1199 1.1 jmcneill
1200 1.1 jmcneill for (i = 0; i < uimin(cur->cmap.count, 3); i++) {
1201 1.1 jmcneill val = (cur->cmap.red[i] << 16 ) |
1202 1.1 jmcneill (cur->cmap.green[i] << 8) |
1203 1.1 jmcneill (cur->cmap.blue[i] ) |
1204 1.1 jmcneill 0xff000000;
1205 1.1 jmcneill sc->sc_cursor_cmap[i + cur->cmap.index + 2] = val;
1206 1.1 jmcneill }
1207 1.1 jmcneill shape = 1;
1208 1.1 jmcneill }
1209 1.1 jmcneill if (cur->which & WSDISPLAY_CURSOR_DOSHAPE) {
1210 1.1 jmcneill
1211 1.1 jmcneill copyin(cur->mask, sc->sc_cursor_mask, 64 * 8);
1212 1.1 jmcneill copyin(cur->image, sc->sc_cursor_bitmap, 64 * 8);
1213 1.1 jmcneill shape = 1;
1214 1.1 jmcneill }
1215 1.1 jmcneill if (shape) {
1216 1.1 jmcneill int i, j, idx;
1217 1.1 jmcneill uint8_t mask;
1218 1.1 jmcneill
1219 1.1 jmcneill for (i = 0; i < 64 * 8; i++) {
1220 1.1 jmcneill mask = 0x01;
1221 1.1 jmcneill for (j = 0; j < 8; j++) {
1222 1.1 jmcneill idx = ((sc->sc_cursor_mask[i] & mask) ? 2 : 0) |
1223 1.1 jmcneill ((sc->sc_cursor_bitmap[i] & mask) ? 1 : 0);
1224 1.1 jmcneill sc->sc_cursor_img[i * 8 + j] =
1225 1.1 jmcneill sc->sc_cursor_cmap[idx];
1226 1.1 jmcneill mask = mask << 1;
1227 1.1 jmcneill }
1228 1.1 jmcneill }
1229 1.1 jmcneill }
1230 1.1 jmcneill if (whack) {
1231 1.1 jmcneill uint32_t reg;
1232 1.1 jmcneill
1233 1.1 jmcneill reg = bus_space_read_4(sc->sc_iot, sc->sc_regh,
1234 1.1 jmcneill OMAPFB_DISPC_CONTROL);
1235 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONTROL,
1236 1.1 jmcneill reg | OMAP_DISPC_CTRL_GO_LCD | OMAP_DISPC_CTRL_GO_DIGITAL);
1237 1.1 jmcneill }
1238 1.1 jmcneill return 0;
1239 1.1 jmcneill
1240 1.1 jmcneill }
1241 1.1 jmcneill
1242 1.1 jmcneill static int
1243 1.1 jmcneill omapfb_console_match(int phandle)
1244 1.1 jmcneill {
1245 1.1 jmcneill return of_match_compatible(phandle, compatible);
1246 1.1 jmcneill }
1247 1.1 jmcneill
1248 1.1 jmcneill static void
1249 1.1 jmcneill omapfb_console_consinit(struct fdt_attach_args *faa, u_int uart_freq)
1250 1.1 jmcneill {
1251 1.1 jmcneill omapfb_console_phandle = faa->faa_phandle;
1252 1.1 jmcneill }
1253 1.1 jmcneill
1254 1.1 jmcneill static const struct fdt_console omapfb_fdt_console = {
1255 1.1 jmcneill .match = omapfb_console_match,
1256 1.1 jmcneill .consinit = omapfb_console_consinit,
1257 1.1 jmcneill };
1258 1.1 jmcneill
1259 1.1 jmcneill FDT_CONSOLE(omapfb, &omapfb_fdt_console);
1260