omap3_dss.c revision 1.1 1 1.1 jmcneill /* $NetBSD: omap3_dss.c,v 1.1 2019/10/31 17:08:54 jmcneill 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.1 jmcneill __KERNEL_RCSID(0, "$NetBSD: omap3_dss.c,v 1.1 2019/10/31 17:08:54 jmcneill 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.1 jmcneill memcpy(sc->sc_edid_data, prop_data_data_nocopy(edid_data),
266 1.1 jmcneill sc->sc_edid_size);
267 1.1 jmcneill
268 1.1 jmcneill edid_parse(sc->sc_edid_data, &ei);
269 1.1 jmcneill edid_print(&ei);
270 1.1 jmcneill }
271 1.1 jmcneill
272 1.1 jmcneill /* setup video DMA */
273 1.1 jmcneill sc->sc_vramsize = (12 << 20) + PAGE_SIZE; /* 12MB + CLUT */
274 1.1 jmcneill
275 1.1 jmcneill if (bus_dmamem_alloc(sc->sc_dmat, sc->sc_vramsize, 0, 0,
276 1.1 jmcneill sc->sc_dmamem, 1, &segs, BUS_DMA_NOWAIT) != 0) {
277 1.1 jmcneill panic("boo!\n");
278 1.1 jmcneill aprint_error_dev(sc->sc_dev,
279 1.1 jmcneill "failed to allocate video memory\n");
280 1.1 jmcneill return;
281 1.1 jmcneill }
282 1.1 jmcneill
283 1.1 jmcneill if (bus_dmamem_map(sc->sc_dmat, sc->sc_dmamem, 1, sc->sc_vramsize,
284 1.1 jmcneill &sc->sc_vramaddr, BUS_DMA_NOWAIT | BUS_DMA_COHERENT) != 0) {
285 1.1 jmcneill aprint_error_dev(sc->sc_dev, "failed to map video RAM\n");
286 1.1 jmcneill return;
287 1.1 jmcneill }
288 1.1 jmcneill sc->sc_fbaddr = (uint8_t *)sc->sc_vramaddr + PAGE_SIZE;
289 1.1 jmcneill sc->sc_clut = sc->sc_vramaddr;
290 1.1 jmcneill
291 1.1 jmcneill if (bus_dmamap_create(sc->sc_dmat, sc->sc_vramsize, 1, sc->sc_vramsize,
292 1.1 jmcneill 0, BUS_DMA_NOWAIT, &sc->sc_dmamap) != 0) {
293 1.1 jmcneill aprint_error_dev(sc->sc_dev, "failed to create DMA map\n");
294 1.1 jmcneill return;
295 1.1 jmcneill }
296 1.1 jmcneill
297 1.1 jmcneill if (bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap, sc->sc_vramaddr,
298 1.1 jmcneill sc->sc_vramsize, NULL, BUS_DMA_NOWAIT) != 0) {
299 1.1 jmcneill aprint_error_dev(sc->sc_dev, "failed to load DMA map\n");
300 1.1 jmcneill return;
301 1.1 jmcneill }
302 1.1 jmcneill
303 1.1 jmcneill if (sc->sc_depth == 8) {
304 1.1 jmcneill j = 0;
305 1.1 jmcneill for (i = 0; i < 256; i++) {
306 1.1 jmcneill sc->sc_cmap_red[i] = rasops_cmap[j];
307 1.1 jmcneill sc->sc_cmap_green[i] = rasops_cmap[j + 1];
308 1.1 jmcneill sc->sc_cmap_blue[i] = rasops_cmap[j + 2];
309 1.1 jmcneill j += 3;
310 1.1 jmcneill }
311 1.1 jmcneill } else {
312 1.1 jmcneill for (i = 0; i < 256; i++) {
313 1.1 jmcneill sc->sc_cmap_red[i] = i;
314 1.1 jmcneill sc->sc_cmap_green[i] = i;
315 1.1 jmcneill sc->sc_cmap_blue[i] = i;
316 1.1 jmcneill }
317 1.1 jmcneill }
318 1.1 jmcneill omapfb_restore_palette(sc);
319 1.1 jmcneill
320 1.1 jmcneill /* now that we have video memory, stick it to the video controller */
321 1.1 jmcneill
322 1.1 jmcneill reg = bus_space_read_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_SYSCONFIG);
323 1.1 jmcneill reg &= ~(OMAP_DISPC_SYSC_STANDBY_MASK | OMAP_DISPC_SYSC_IDLE_MASK);
324 1.1 jmcneill reg |= OMAP_DISPC_SYSC_SMART_STANDBY | OMAP_DISPC_SYSC_SMART_IDLE |
325 1.1 jmcneill OMAP_DISPC_SYSC_WAKEUP_ENABLE | OMAP_SYSCONF_AUTOIDLE;
326 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_SYSCONFIG, reg);
327 1.1 jmcneill
328 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DSS_SYSCONFIG,
329 1.1 jmcneill OMAP_SYSCONF_AUTOIDLE);
330 1.1 jmcneill
331 1.1 jmcneill reg = OMAP_DISPC_CFG_TV_ALPHA_EN | OMAP_DISPC_CFG_LCD_ALPHA_EN;
332 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONFIG, reg);
333 1.1 jmcneill sc->sc_dispc_config = reg;
334 1.1 jmcneill
335 1.1 jmcneill /* we use overlay 1 for the console and X */
336 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GLOBAL_ALPHA,
337 1.1 jmcneill 0x00ff00ff);
338 1.1 jmcneill sc->sc_fbhwaddr = sc->sc_dmamem->ds_addr + PAGE_SIZE;
339 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_VID1_BASE_0,
340 1.1 jmcneill sc->sc_fbhwaddr);
341 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh,
342 1.1 jmcneill OMAPFB_DISPC_VID1_POSITION, 0);
343 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_VID1_SIZE,
344 1.1 jmcneill ((sc->sc_height - 1) << 16) | (sc->sc_width - 1));
345 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh,
346 1.1 jmcneill OMAPFB_DISPC_VID1_PICTURE_SIZE,
347 1.1 jmcneill ((sc->sc_height - 1) << 16) | (sc->sc_width - 1));
348 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh,
349 1.1 jmcneill OMAPFB_DISPC_VID1_ROW_INC, 1);
350 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh,
351 1.1 jmcneill OMAPFB_DISPC_VID1_PIXEL_INC, 1);
352 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh,
353 1.1 jmcneill OMAPFB_DISPC_VID1_PRELOAD, 0x60);
354 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_VID1_ATTRIBUTES,
355 1.1 jmcneill OMAP_VID_ATTR_ENABLE |
356 1.1 jmcneill OMAP_VID_ATTR_BURST_16x32 |
357 1.1 jmcneill OMAP_VID_ATTR_RGB16 |
358 1.1 jmcneill OMAP_VID_ATTR_REPLICATION);
359 1.1 jmcneill
360 1.1 jmcneill /* turn off overlay 2 */
361 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh,
362 1.1 jmcneill OMAPFB_DISPC_VID2_ATTRIBUTES, 0);
363 1.1 jmcneill
364 1.1 jmcneill /* initialize the gfx layer for use as hardware cursor */
365 1.1 jmcneill sc->sc_cursor_cmap[0] = 0;
366 1.1 jmcneill sc->sc_cursor_offset = (12 << 20) - (64 * 64 * 4);
367 1.1 jmcneill sc->sc_cursor_img =
368 1.1 jmcneill (uint32_t *)((uint8_t *)sc->sc_fbaddr + sc->sc_cursor_offset);
369 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GFX_BASE_0,
370 1.1 jmcneill sc->sc_fbhwaddr + sc->sc_cursor_offset);
371 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GFX_TABLE_BASE,
372 1.1 jmcneill sc->sc_dmamem->ds_addr);
373 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GFX_SIZE,
374 1.1 jmcneill 0x003f003f);
375 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GFX_POSITION,
376 1.1 jmcneill 0x00100010);
377 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh,
378 1.1 jmcneill OMAPFB_DISPC_GFX_PRELOAD, 0x60);
379 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GFX_ATTRIBUTES,
380 1.1 jmcneill /*OMAP_DISPC_ATTR_ENABLE |*/
381 1.1 jmcneill OMAP_DISPC_ATTR_BURST_16x32 |
382 1.1 jmcneill OMAP_DISPC_ATTR_ARGB32 |
383 1.1 jmcneill OMAP_DISPC_ATTR_REPLICATION);
384 1.1 jmcneill
385 1.1 jmcneill #if 0
386 1.1 jmcneill printf("dss_control: %08x\n", bus_space_read_4(sc->sc_iot, sc->sc_regh,
387 1.1 jmcneill OMAPFB_DSS_CONTROL));
388 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DSS_CONTROL,
389 1.1 jmcneill /*OMAP_DSSCTRL_DISPC_CLK_SWITCH |*/
390 1.1 jmcneill OMAP_DSSCTRL_CLOCK_MODE |
391 1.1 jmcneill OMAP_DSSCTRL_VENC_CLOCK_4X |
392 1.1 jmcneill OMAP_DSSCTRL_DAC_DEMEN);
393 1.1 jmcneill #endif
394 1.1 jmcneill
395 1.1 jmcneill #if 0
396 1.1 jmcneill /* VENC to NTSC mode */
397 1.1 jmcneill int adr = OMAPFB_VENC_F_CONTROL;
398 1.1 jmcneill for (i = 0; i < __arraycount(venc_mode_ntsc); i++) {
399 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, adr,
400 1.1 jmcneill venc_mode_ntsc[i]);
401 1.1 jmcneill adr += 4;
402 1.1 jmcneill }
403 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_VENC_F_CONTROL,
404 1.1 jmcneill venc_mode_ntsc[0]);
405 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_VENC_SYNC_CTRL,
406 1.1 jmcneill venc_mode_ntsc[2]);
407 1.1 jmcneill
408 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_DEFAULT_COLOR_1,
409 1.1 jmcneill 0x00ff0000);
410 1.1 jmcneill #endif
411 1.1 jmcneill
412 1.1 jmcneill /* now we make sure the video output is actually running */
413 1.1 jmcneill reg = bus_space_read_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONTROL);
414 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONTROL,
415 1.1 jmcneill reg | OMAP_DISPC_CTRL_GO_LCD | OMAP_DISPC_CTRL_GO_DIGITAL);
416 1.1 jmcneill
417 1.1 jmcneill #ifdef OMAPFB_DEBUG
418 1.1 jmcneill printf("attr: %08x\n", bus_space_read_4(sc->sc_iot, sc->sc_regh,
419 1.1 jmcneill OMAPFB_DISPC_GFX_ATTRIBUTES));
420 1.1 jmcneill printf("preload: %08x\n", bus_space_read_4(sc->sc_iot, sc->sc_regh,
421 1.1 jmcneill OMAPFB_DISPC_GFX_PRELOAD));
422 1.1 jmcneill printf("config: %08x\n", bus_space_read_4(sc->sc_iot, sc->sc_regh,
423 1.1 jmcneill OMAPFB_DISPC_CONFIG));
424 1.1 jmcneill printf("control: %08x\n", bus_space_read_4(sc->sc_iot, sc->sc_regh,
425 1.1 jmcneill OMAPFB_DISPC_CONTROL));
426 1.1 jmcneill printf("dss_control: %08x\n", bus_space_read_4(sc->sc_iot, sc->sc_regh,
427 1.1 jmcneill OMAPFB_DSS_CONTROL));
428 1.1 jmcneill printf("threshold: %08x\n", bus_space_read_4(sc->sc_iot, sc->sc_regh,
429 1.1 jmcneill OMAPFB_DISPC_GFX_FIFO_THRESH));
430 1.1 jmcneill printf("GFX size: %08x\n", bus_space_read_4(sc->sc_iot, sc->sc_regh,
431 1.1 jmcneill OMAPFB_DISPC_GFX_SIZE));
432 1.1 jmcneill printf("row inc: %08x\n", bus_space_read_4(sc->sc_iot, sc->sc_regh,
433 1.1 jmcneill OMAPFB_DISPC_GFX_ROW_INC));
434 1.1 jmcneill printf("pixel inc: %08x\n", bus_space_read_4(sc->sc_iot, sc->sc_regh,
435 1.1 jmcneill OMAPFB_DISPC_GFX_PIXEL_INC));
436 1.1 jmcneill #endif
437 1.1 jmcneill
438 1.1 jmcneill sc->sc_defaultscreen_descr = (struct wsscreen_descr){
439 1.1 jmcneill "default",
440 1.1 jmcneill 0, 0,
441 1.1 jmcneill NULL,
442 1.1 jmcneill 8, 16,
443 1.1 jmcneill WSSCREEN_WSCOLORS | WSSCREEN_HILIT,
444 1.1 jmcneill NULL
445 1.1 jmcneill };
446 1.1 jmcneill sc->sc_screens[0] = &sc->sc_defaultscreen_descr;
447 1.1 jmcneill sc->sc_screenlist = (struct wsscreen_list){1, sc->sc_screens};
448 1.1 jmcneill sc->sc_mode = WSDISPLAYIO_MODE_EMUL;
449 1.1 jmcneill sc->sc_locked = 0;
450 1.1 jmcneill
451 1.1 jmcneill vcons_init(&sc->vd, sc, &sc->sc_defaultscreen_descr,
452 1.1 jmcneill &omapfb_accessops);
453 1.1 jmcneill sc->vd.init_screen = omapfb_init_screen;
454 1.1 jmcneill
455 1.1 jmcneill /* init engine here */
456 1.1 jmcneill #if NOMAPDMA > 0
457 1.1 jmcneill omapfb_init(sc);
458 1.1 jmcneill #endif
459 1.1 jmcneill
460 1.1 jmcneill ri = &sc->sc_console_screen.scr_ri;
461 1.1 jmcneill vcons_init_screen(&sc->vd, &sc->sc_console_screen, 1, &defattr);
462 1.1 jmcneill sc->sc_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC;
463 1.1 jmcneill #if NOMAPDMA > 0
464 1.1 jmcneill omapfb_rectfill(sc, 0, 0, sc->sc_width, sc->sc_height,
465 1.1 jmcneill ri->ri_devcmap[(defattr >> 16) & 0xff]);
466 1.1 jmcneill #endif
467 1.1 jmcneill sc->sc_defaultscreen_descr.textops = &ri->ri_ops;
468 1.1 jmcneill sc->sc_defaultscreen_descr.capabilities = ri->ri_caps;
469 1.1 jmcneill sc->sc_defaultscreen_descr.nrows = ri->ri_rows;
470 1.1 jmcneill sc->sc_defaultscreen_descr.ncols = ri->ri_cols;
471 1.1 jmcneill
472 1.1 jmcneill if (is_console)
473 1.1 jmcneill wsdisplay_cnattach(&sc->sc_defaultscreen_descr, ri, 0, 0,
474 1.1 jmcneill defattr);
475 1.1 jmcneill
476 1.1 jmcneill vcons_replay_msgbuf(&sc->sc_console_screen);
477 1.1 jmcneill
478 1.1 jmcneill aa.console = is_console;
479 1.1 jmcneill aa.scrdata = &sc->sc_screenlist;
480 1.1 jmcneill aa.accessops = &omapfb_accessops;
481 1.1 jmcneill aa.accesscookie = &sc->vd;
482 1.1 jmcneill
483 1.1 jmcneill config_found(sc->sc_dev, &aa, wsemuldisplaydevprint);
484 1.1 jmcneill #ifdef OMAPFB_DEBUG
485 1.1 jmcneill #if NOMAPDMA > 0
486 1.1 jmcneill omapfb_rectfill(sc, 100, 100, 100, 100, 0xe000);
487 1.1 jmcneill omapfb_rectfill(sc, 100, 200, 100, 100, 0x01f8);
488 1.1 jmcneill omapfb_rectfill(sc, 200, 100, 100, 100, 0x01f8);
489 1.1 jmcneill omapfb_rectfill(sc, 200, 200, 100, 100, 0xe000);
490 1.1 jmcneill omapfb_bitblt(sc, 100, 100, 400, 100, 200, 200, 0);
491 1.1 jmcneill /* let's see if we can draw something */
492 1.1 jmcneill printf("OMAPDMAC_CDAC: %08x\n", omapdma_read_ch_reg(0, OMAPDMAC_CDAC));
493 1.1 jmcneill printf("OMAPDMAC_CSR: %08x\n", omapdma_read_ch_reg(0, OMAPDMAC_CSR));
494 1.1 jmcneill printf("OMAPDMAC_CCR: %08x\n", omapdma_read_ch_reg(0, OMAPDMAC_CCR));
495 1.1 jmcneill #endif
496 1.1 jmcneill #endif
497 1.1 jmcneill }
498 1.1 jmcneill
499 1.1 jmcneill static int
500 1.1 jmcneill omapfb_ioctl(void *v, void *vs, u_long cmd, void *data, int flag,
501 1.1 jmcneill struct lwp *l)
502 1.1 jmcneill {
503 1.1 jmcneill struct vcons_data *vd = v;
504 1.1 jmcneill struct omapfb_softc *sc = vd->cookie;
505 1.1 jmcneill struct wsdisplay_fbinfo *wdf;
506 1.1 jmcneill struct vcons_screen *ms = vd->active;
507 1.1 jmcneill
508 1.1 jmcneill switch (cmd) {
509 1.1 jmcneill
510 1.1 jmcneill case WSDISPLAYIO_GTYPE:
511 1.1 jmcneill *(u_int *)data = WSDISPLAY_TYPE_OMAP3;
512 1.1 jmcneill return 0;
513 1.1 jmcneill
514 1.1 jmcneill case WSDISPLAYIO_GET_BUSID:
515 1.1 jmcneill {
516 1.1 jmcneill struct wsdisplayio_bus_id *busid;
517 1.1 jmcneill
518 1.1 jmcneill busid = data;
519 1.1 jmcneill busid->bus_type = WSDISPLAYIO_BUS_SOC;
520 1.1 jmcneill return 0;
521 1.1 jmcneill }
522 1.1 jmcneill
523 1.1 jmcneill case WSDISPLAYIO_GINFO:
524 1.1 jmcneill if (ms == NULL)
525 1.1 jmcneill return ENODEV;
526 1.1 jmcneill wdf = (void *)data;
527 1.1 jmcneill wdf->height = ms->scr_ri.ri_height;
528 1.1 jmcneill wdf->width = ms->scr_ri.ri_width;
529 1.1 jmcneill wdf->depth = 32;
530 1.1 jmcneill wdf->cmsize = 256;
531 1.1 jmcneill return 0;
532 1.1 jmcneill
533 1.1 jmcneill case WSDISPLAYIO_GETCMAP:
534 1.1 jmcneill return omapfb_getcmap(sc,
535 1.1 jmcneill (struct wsdisplay_cmap *)data);
536 1.1 jmcneill
537 1.1 jmcneill case WSDISPLAYIO_PUTCMAP:
538 1.1 jmcneill return omapfb_putcmap(sc,
539 1.1 jmcneill (struct wsdisplay_cmap *)data);
540 1.1 jmcneill
541 1.1 jmcneill case WSDISPLAYIO_LINEBYTES:
542 1.1 jmcneill *(u_int *)data = sc->sc_width * 4;
543 1.1 jmcneill return 0;
544 1.1 jmcneill
545 1.1 jmcneill case WSDISPLAYIO_SMODE:
546 1.1 jmcneill {
547 1.1 jmcneill int new_mode = *(int*)data;
548 1.1 jmcneill
549 1.1 jmcneill if (new_mode != sc->sc_mode) {
550 1.1 jmcneill sc->sc_mode = new_mode;
551 1.1 jmcneill if (new_mode == WSDISPLAYIO_MODE_EMUL) {
552 1.1 jmcneill omapfb_set_depth(sc, 16);
553 1.1 jmcneill vcons_redraw_screen(ms);
554 1.1 jmcneill } else {
555 1.1 jmcneill omapfb_set_depth(sc, 32);
556 1.1 jmcneill }
557 1.1 jmcneill }
558 1.1 jmcneill }
559 1.1 jmcneill return 0;
560 1.1 jmcneill
561 1.1 jmcneill case WSDISPLAYIO_GET_FBINFO:
562 1.1 jmcneill {
563 1.1 jmcneill struct wsdisplayio_fbinfo *fbi = data;
564 1.1 jmcneill
565 1.1 jmcneill fbi->fbi_width = sc->sc_width;
566 1.1 jmcneill fbi->fbi_height = sc->sc_height;
567 1.1 jmcneill fbi->fbi_stride = sc->sc_width << 2;
568 1.1 jmcneill fbi->fbi_bitsperpixel = 32;
569 1.1 jmcneill fbi->fbi_pixeltype = WSFB_RGB;
570 1.1 jmcneill fbi->fbi_subtype.fbi_rgbmasks.red_offset = 16;
571 1.1 jmcneill fbi->fbi_subtype.fbi_rgbmasks.red_size = 8;
572 1.1 jmcneill fbi->fbi_subtype.fbi_rgbmasks.green_offset = 8;
573 1.1 jmcneill fbi->fbi_subtype.fbi_rgbmasks.green_size = 8;
574 1.1 jmcneill fbi->fbi_subtype.fbi_rgbmasks.blue_offset = 0;
575 1.1 jmcneill fbi->fbi_subtype.fbi_rgbmasks.blue_size = 8;
576 1.1 jmcneill fbi->fbi_subtype.fbi_rgbmasks.alpha_offset = 0;
577 1.1 jmcneill fbi->fbi_subtype.fbi_rgbmasks.alpha_size = 0;
578 1.1 jmcneill fbi->fbi_flags = 0;
579 1.1 jmcneill fbi->fbi_fbsize = sc->sc_vramsize;
580 1.1 jmcneill fbi->fbi_fboffset = 0;
581 1.1 jmcneill fbi->fbi_flags = WSFB_VRAM_IS_RAM;
582 1.1 jmcneill
583 1.1 jmcneill }
584 1.1 jmcneill return 0;
585 1.1 jmcneill
586 1.1 jmcneill case WSDISPLAYIO_GVIDEO:
587 1.1 jmcneill {
588 1.1 jmcneill int *on = data;
589 1.1 jmcneill *on = sc->sc_video_is_on;
590 1.1 jmcneill }
591 1.1 jmcneill return 0;
592 1.1 jmcneill
593 1.1 jmcneill case WSDISPLAYIO_SVIDEO:
594 1.1 jmcneill {
595 1.1 jmcneill int *on = data;
596 1.1 jmcneill omapfb_set_video(sc, *on);
597 1.1 jmcneill }
598 1.1 jmcneill return 0;
599 1.1 jmcneill
600 1.1 jmcneill case WSDISPLAYIO_GCURPOS:
601 1.1 jmcneill {
602 1.1 jmcneill struct wsdisplay_curpos *cp = (void *)data;
603 1.1 jmcneill
604 1.1 jmcneill cp->x = sc->sc_cursor_x;
605 1.1 jmcneill cp->y = sc->sc_cursor_y;
606 1.1 jmcneill }
607 1.1 jmcneill return 0;
608 1.1 jmcneill case WSDISPLAYIO_SCURPOS:
609 1.1 jmcneill {
610 1.1 jmcneill struct wsdisplay_curpos *cp = (void *)data;
611 1.1 jmcneill
612 1.1 jmcneill omapfb_move_cursor(sc, cp->x, cp->y);
613 1.1 jmcneill }
614 1.1 jmcneill return 0;
615 1.1 jmcneill case WSDISPLAYIO_GCURMAX:
616 1.1 jmcneill {
617 1.1 jmcneill struct wsdisplay_curpos *cp = (void *)data;
618 1.1 jmcneill
619 1.1 jmcneill cp->x = 64;
620 1.1 jmcneill cp->y = 64;
621 1.1 jmcneill }
622 1.1 jmcneill return 0;
623 1.1 jmcneill case WSDISPLAYIO_SCURSOR:
624 1.1 jmcneill {
625 1.1 jmcneill struct wsdisplay_cursor *cursor = (void *)data;
626 1.1 jmcneill
627 1.1 jmcneill return omapfb_do_cursor(sc, cursor);
628 1.1 jmcneill }
629 1.1 jmcneill }
630 1.1 jmcneill return EPASSTHROUGH;
631 1.1 jmcneill }
632 1.1 jmcneill
633 1.1 jmcneill static paddr_t
634 1.1 jmcneill omapfb_mmap(void *v, void *vs, off_t offset, int prot)
635 1.1 jmcneill {
636 1.1 jmcneill paddr_t pa = -1;
637 1.1 jmcneill struct vcons_data *vd = v;
638 1.1 jmcneill struct omapfb_softc *sc = vd->cookie;
639 1.1 jmcneill
640 1.1 jmcneill /* 'regular' framebuffer mmap()ing */
641 1.1 jmcneill if (offset < sc->sc_vramsize) {
642 1.1 jmcneill pa = bus_dmamem_mmap(sc->sc_dmat, sc->sc_dmamem, 1,
643 1.1 jmcneill offset + PAGE_SIZE, prot, BUS_DMA_PREFETCHABLE);
644 1.1 jmcneill return pa;
645 1.1 jmcneill }
646 1.1 jmcneill return pa;
647 1.1 jmcneill }
648 1.1 jmcneill
649 1.1 jmcneill static void
650 1.1 jmcneill omapfb_init_screen(void *cookie, struct vcons_screen *scr,
651 1.1 jmcneill int existing, long *defattr)
652 1.1 jmcneill {
653 1.1 jmcneill struct omapfb_softc *sc = cookie;
654 1.1 jmcneill struct rasops_info *ri = &scr->scr_ri;
655 1.1 jmcneill
656 1.1 jmcneill ri->ri_depth = sc->sc_depth;
657 1.1 jmcneill ri->ri_width = sc->sc_width;
658 1.1 jmcneill ri->ri_height = sc->sc_height;
659 1.1 jmcneill ri->ri_stride = sc->sc_stride;
660 1.1 jmcneill ri->ri_flg = RI_CENTER | RI_FULLCLEAR;
661 1.1 jmcneill
662 1.1 jmcneill ri->ri_bits = (char *)sc->sc_fbaddr;
663 1.1 jmcneill
664 1.1 jmcneill #if NOMAPDMA < 1
665 1.1 jmcneill scr->scr_flags |= VCONS_DONT_READ;
666 1.1 jmcneill #endif
667 1.1 jmcneill
668 1.1 jmcneill if (existing) {
669 1.1 jmcneill ri->ri_flg |= RI_CLEAR;
670 1.1 jmcneill }
671 1.1 jmcneill
672 1.1 jmcneill rasops_init(ri, sc->sc_height / 8, sc->sc_width / 8);
673 1.1 jmcneill ri->ri_caps = WSSCREEN_WSCOLORS;
674 1.1 jmcneill
675 1.1 jmcneill rasops_reconfig(ri, sc->sc_height / ri->ri_font->fontheight,
676 1.1 jmcneill sc->sc_width / ri->ri_font->fontwidth);
677 1.1 jmcneill
678 1.1 jmcneill ri->ri_hw = scr;
679 1.1 jmcneill
680 1.1 jmcneill #if NOMAPDMA > 0
681 1.1 jmcneill ri->ri_ops.copyrows = omapfb_copyrows;
682 1.1 jmcneill ri->ri_ops.copycols = omapfb_copycols;
683 1.1 jmcneill ri->ri_ops.eraserows = omapfb_eraserows;
684 1.1 jmcneill ri->ri_ops.erasecols = omapfb_erasecols;
685 1.1 jmcneill ri->ri_ops.cursor = omapfb_cursor;
686 1.1 jmcneill sc->sc_putchar = ri->ri_ops.putchar;
687 1.1 jmcneill ri->ri_ops.putchar = omapfb_putchar;
688 1.1 jmcneill #endif
689 1.1 jmcneill }
690 1.1 jmcneill
691 1.1 jmcneill static int
692 1.1 jmcneill omapfb_putcmap(struct omapfb_softc *sc, struct wsdisplay_cmap *cm)
693 1.1 jmcneill {
694 1.1 jmcneill u_char *r, *g, *b;
695 1.1 jmcneill u_int index = cm->index;
696 1.1 jmcneill u_int count = cm->count;
697 1.1 jmcneill int i, error;
698 1.1 jmcneill u_char rbuf[256], gbuf[256], bbuf[256];
699 1.1 jmcneill
700 1.1 jmcneill if (cm->index >= 256 || cm->count > 256 ||
701 1.1 jmcneill (cm->index + cm->count) > 256)
702 1.1 jmcneill return EINVAL;
703 1.1 jmcneill error = copyin(cm->red, &rbuf[index], count);
704 1.1 jmcneill if (error)
705 1.1 jmcneill return error;
706 1.1 jmcneill error = copyin(cm->green, &gbuf[index], count);
707 1.1 jmcneill if (error)
708 1.1 jmcneill return error;
709 1.1 jmcneill error = copyin(cm->blue, &bbuf[index], count);
710 1.1 jmcneill if (error)
711 1.1 jmcneill return error;
712 1.1 jmcneill
713 1.1 jmcneill memcpy(&sc->sc_cmap_red[index], &rbuf[index], count);
714 1.1 jmcneill memcpy(&sc->sc_cmap_green[index], &gbuf[index], count);
715 1.1 jmcneill memcpy(&sc->sc_cmap_blue[index], &bbuf[index], count);
716 1.1 jmcneill
717 1.1 jmcneill r = &sc->sc_cmap_red[index];
718 1.1 jmcneill g = &sc->sc_cmap_green[index];
719 1.1 jmcneill b = &sc->sc_cmap_blue[index];
720 1.1 jmcneill
721 1.1 jmcneill for (i = 0; i < count; i++) {
722 1.1 jmcneill omapfb_putpalreg(sc, index, *r, *g, *b);
723 1.1 jmcneill index++;
724 1.1 jmcneill r++, g++, b++;
725 1.1 jmcneill }
726 1.1 jmcneill return 0;
727 1.1 jmcneill }
728 1.1 jmcneill
729 1.1 jmcneill static int
730 1.1 jmcneill omapfb_getcmap(struct omapfb_softc *sc, struct wsdisplay_cmap *cm)
731 1.1 jmcneill {
732 1.1 jmcneill u_int index = cm->index;
733 1.1 jmcneill u_int count = cm->count;
734 1.1 jmcneill int error;
735 1.1 jmcneill
736 1.1 jmcneill if (index >= 255 || count > 256 || index + count > 256)
737 1.1 jmcneill return EINVAL;
738 1.1 jmcneill
739 1.1 jmcneill error = copyout(&sc->sc_cmap_red[index], cm->red, count);
740 1.1 jmcneill if (error)
741 1.1 jmcneill return error;
742 1.1 jmcneill error = copyout(&sc->sc_cmap_green[index], cm->green, count);
743 1.1 jmcneill if (error)
744 1.1 jmcneill return error;
745 1.1 jmcneill error = copyout(&sc->sc_cmap_blue[index], cm->blue, count);
746 1.1 jmcneill if (error)
747 1.1 jmcneill return error;
748 1.1 jmcneill
749 1.1 jmcneill return 0;
750 1.1 jmcneill }
751 1.1 jmcneill
752 1.1 jmcneill static void
753 1.1 jmcneill omapfb_restore_palette(struct omapfb_softc *sc)
754 1.1 jmcneill {
755 1.1 jmcneill int i;
756 1.1 jmcneill
757 1.1 jmcneill for (i = 0; i < 256; i++) {
758 1.1 jmcneill omapfb_putpalreg(sc, i, sc->sc_cmap_red[i],
759 1.1 jmcneill sc->sc_cmap_green[i], sc->sc_cmap_blue[i]);
760 1.1 jmcneill }
761 1.1 jmcneill }
762 1.1 jmcneill
763 1.1 jmcneill static void
764 1.1 jmcneill omapfb_putpalreg(struct omapfb_softc *sc, int idx, uint8_t r, uint8_t g,
765 1.1 jmcneill uint8_t b)
766 1.1 jmcneill {
767 1.1 jmcneill uint32_t reg;
768 1.1 jmcneill
769 1.1 jmcneill if ((idx < 0) || (idx > 255))
770 1.1 jmcneill return;
771 1.1 jmcneill /* whack the DAC */
772 1.1 jmcneill reg = (r << 16) | (g << 8) | b;
773 1.1 jmcneill sc->sc_clut[idx] = reg;
774 1.1 jmcneill }
775 1.1 jmcneill
776 1.1 jmcneill static int
777 1.1 jmcneill omapfb_set_depth(struct omapfb_softc *sc, int d)
778 1.1 jmcneill {
779 1.1 jmcneill uint32_t reg;
780 1.1 jmcneill
781 1.1 jmcneill reg = OMAP_VID_ATTR_ENABLE |
782 1.1 jmcneill OMAP_VID_ATTR_BURST_16x32 |
783 1.1 jmcneill OMAP_VID_ATTR_REPLICATION;
784 1.1 jmcneill switch (d) {
785 1.1 jmcneill case 16:
786 1.1 jmcneill reg |= OMAP_VID_ATTR_RGB16;
787 1.1 jmcneill break;
788 1.1 jmcneill case 32:
789 1.1 jmcneill reg |= OMAP_VID_ATTR_RGB24;
790 1.1 jmcneill break;
791 1.1 jmcneill default:
792 1.1 jmcneill aprint_error_dev(sc->sc_dev,
793 1.1 jmcneill "unsupported depth (%d)\n", d);
794 1.1 jmcneill return EINVAL;
795 1.1 jmcneill }
796 1.1 jmcneill
797 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh,
798 1.1 jmcneill OMAPFB_DISPC_VID1_ATTRIBUTES, reg);
799 1.1 jmcneill
800 1.1 jmcneill /*
801 1.1 jmcneill * now tell the video controller that we're done mucking around and
802 1.1 jmcneill * actually update its settings
803 1.1 jmcneill */
804 1.1 jmcneill reg = bus_space_read_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONTROL);
805 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONTROL,
806 1.1 jmcneill reg | OMAP_DISPC_CTRL_GO_LCD | OMAP_DISPC_CTRL_GO_DIGITAL);
807 1.1 jmcneill
808 1.1 jmcneill sc->sc_depth = d;
809 1.1 jmcneill sc->sc_stride = sc->sc_width * (sc->sc_depth >> 3);
810 1.1 jmcneill
811 1.1 jmcneill /* clear the screen here */
812 1.1 jmcneill #if NOMAPDMA > 0
813 1.1 jmcneill omapfb_rectfill(sc, 0, 0, sc->sc_width, sc->sc_height, 0);
814 1.1 jmcneill #else
815 1.1 jmcneill memset(sc->sc_fbaddr, 0, sc->sc_stride * sc->sc_height);
816 1.1 jmcneill #endif
817 1.1 jmcneill return 0;
818 1.1 jmcneill }
819 1.1 jmcneill
820 1.1 jmcneill static void
821 1.1 jmcneill omapfb_set_video(struct omapfb_softc *sc, int on)
822 1.1 jmcneill {
823 1.1 jmcneill uint32_t reg;
824 1.1 jmcneill
825 1.1 jmcneill if (on == sc->sc_video_is_on)
826 1.1 jmcneill return;
827 1.1 jmcneill if (on) {
828 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh,
829 1.1 jmcneill OMAPFB_DISPC_CONFIG, sc->sc_dispc_config);
830 1.1 jmcneill on = 1;
831 1.1 jmcneill } else {
832 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh,
833 1.1 jmcneill OMAPFB_DISPC_CONFIG, sc->sc_dispc_config |
834 1.1 jmcneill OMAP_DISPC_CFG_VSYNC_GATED | OMAP_DISPC_CFG_HSYNC_GATED |
835 1.1 jmcneill OMAP_DISPC_CFG_PIXELCLK_GATED |
836 1.1 jmcneill OMAP_DISPC_CFG_PIXELDATA_GATED);
837 1.1 jmcneill }
838 1.1 jmcneill
839 1.1 jmcneill /*
840 1.1 jmcneill * now tell the video controller that we're done mucking around and
841 1.1 jmcneill * actually update its settings
842 1.1 jmcneill */
843 1.1 jmcneill reg = bus_space_read_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONTROL);
844 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONTROL,
845 1.1 jmcneill reg | OMAP_DISPC_CTRL_GO_LCD | OMAP_DISPC_CTRL_GO_DIGITAL);
846 1.1 jmcneill
847 1.1 jmcneill aprint_debug_dev(sc->sc_dev, "%s %08x\n", __func__,
848 1.1 jmcneill bus_space_read_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONFIG));
849 1.1 jmcneill sc->sc_video_is_on = on;
850 1.1 jmcneill }
851 1.1 jmcneill
852 1.1 jmcneill #if NOMAPDMA > 0
853 1.1 jmcneill static void
854 1.1 jmcneill omapfb_init(struct omapfb_softc *sc)
855 1.1 jmcneill {
856 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CLNK_CTRL, 0);
857 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CICRI, 0);
858 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CSDPI,
859 1.1 jmcneill CSDPI_SRC_BURST_64 | CSDPI_DST_BURST_64 |
860 1.1 jmcneill CSDPI_WRITE_POSTED | CSDPI_DATA_TYPE_16);
861 1.1 jmcneill }
862 1.1 jmcneill
863 1.1 jmcneill static void
864 1.1 jmcneill omapfb_wait_idle(struct omapfb_softc *sc)
865 1.1 jmcneill {
866 1.1 jmcneill while ((omapdma_read_ch_reg(0, OMAPDMAC_CCR) & CCR_WR_ACTIVE) != 0);
867 1.1 jmcneill }
868 1.1 jmcneill
869 1.1 jmcneill static void
870 1.1 jmcneill omapfb_rectfill(struct omapfb_softc *sc, int x, int y, int wi, int he,
871 1.1 jmcneill uint32_t colour)
872 1.1 jmcneill {
873 1.1 jmcneill int bpp = sc->sc_depth >> 3; /* bytes per pixel */
874 1.1 jmcneill int width_in_bytes = wi * bpp;
875 1.1 jmcneill uint32_t daddr;
876 1.1 jmcneill
877 1.1 jmcneill daddr = sc->sc_fbhwaddr + sc->sc_stride * y + x * bpp;
878 1.1 jmcneill omapfb_wait_idle(sc);
879 1.1 jmcneill
880 1.1 jmcneill /*
881 1.1 jmcneill * stupid hardware
882 1.1 jmcneill * in 32bit mode the DMA controller always writes 0 into the upper
883 1.1 jmcneill * byte, so we can use this mode only if we actually want that
884 1.1 jmcneill */
885 1.1 jmcneill if (((colour & 0xff00) == 0) &&
886 1.1 jmcneill (((daddr | width_in_bytes) & 3) == 0)) {
887 1.1 jmcneill /*
888 1.1 jmcneill * everything is properly aligned so we can copy stuff in
889 1.1 jmcneill * 32bit chunks instead of pixel by pixel
890 1.1 jmcneill */
891 1.1 jmcneill wi = wi >> 1;
892 1.1 jmcneill
893 1.1 jmcneill /* just in case */
894 1.1 jmcneill colour |= colour << 16;
895 1.1 jmcneill
896 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CSDPI,
897 1.1 jmcneill CSDPI_SRC_BURST_64 | CSDPI_DST_BURST_64 |
898 1.1 jmcneill CSDPI_DST_PACKED | CSDPI_WRITE_POSTED_EXCEPT_LAST |
899 1.1 jmcneill CSDPI_DATA_TYPE_32);
900 1.1 jmcneill } else {
901 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CSDPI,
902 1.1 jmcneill CSDPI_SRC_BURST_64 | CSDPI_DST_BURST_64 |
903 1.1 jmcneill CSDPI_DST_PACKED | CSDPI_WRITE_POSTED_EXCEPT_LAST |
904 1.1 jmcneill CSDPI_DATA_TYPE_16);
905 1.1 jmcneill }
906 1.1 jmcneill
907 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CEN, wi);
908 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CFN, he);
909 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CDSA, daddr);
910 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CCR,
911 1.1 jmcneill CCR_CONST_FILL_ENABLE | CCR_DST_AMODE_DOUBLE_INDEX |
912 1.1 jmcneill CCR_SRC_AMODE_CONST_ADDR);
913 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CDEI, 1);
914 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CDFI,
915 1.1 jmcneill (sc->sc_stride - width_in_bytes) + 1);
916 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_COLOR, colour);
917 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CCR,
918 1.1 jmcneill CCR_CONST_FILL_ENABLE | CCR_DST_AMODE_DOUBLE_INDEX |
919 1.1 jmcneill CCR_SRC_AMODE_CONST_ADDR | CCR_ENABLE);
920 1.1 jmcneill }
921 1.1 jmcneill
922 1.1 jmcneill static void
923 1.1 jmcneill omapfb_bitblt(struct omapfb_softc *sc, int xs, int ys, int xd, int yd,
924 1.1 jmcneill int wi, int he, int rop)
925 1.1 jmcneill {
926 1.1 jmcneill int bpp = sc->sc_depth >> 3; /* bytes per pixel */
927 1.1 jmcneill int width_in_bytes = wi * bpp;
928 1.1 jmcneill
929 1.1 jmcneill int hstep, vstep;
930 1.1 jmcneill uint32_t saddr, daddr;
931 1.1 jmcneill
932 1.1 jmcneill saddr = sc->sc_fbhwaddr + sc->sc_stride * ys + xs * bpp;
933 1.1 jmcneill daddr = sc->sc_fbhwaddr + sc->sc_stride * yd + xd * bpp;
934 1.1 jmcneill
935 1.1 jmcneill if (ys < yd) {
936 1.1 jmcneill /* need to go vertically backwards */
937 1.1 jmcneill vstep = 1 - (sc->sc_stride + width_in_bytes);
938 1.1 jmcneill saddr += sc->sc_stride * (he - 1);
939 1.1 jmcneill daddr += sc->sc_stride * (he - 1);
940 1.1 jmcneill } else
941 1.1 jmcneill vstep = (sc->sc_stride - width_in_bytes) + 1;
942 1.1 jmcneill if ((xs < xd) && (ys == yd)) {
943 1.1 jmcneill /*
944 1.1 jmcneill * need to go horizontally backwards, only needed if source
945 1.1 jmcneill * and destination pixels are on the same line
946 1.1 jmcneill */
947 1.1 jmcneill hstep = 1 - (sc->sc_depth >> 2);
948 1.1 jmcneill vstep = sc->sc_stride + bpp * (wi - 1) + 1;
949 1.1 jmcneill saddr += bpp * (wi - 1);
950 1.1 jmcneill daddr += bpp * (wi - 1);
951 1.1 jmcneill } else
952 1.1 jmcneill hstep = 1;
953 1.1 jmcneill
954 1.1 jmcneill omapfb_wait_idle(sc);
955 1.1 jmcneill if (((saddr | daddr | width_in_bytes) & 3) == 0) {
956 1.1 jmcneill /*
957 1.1 jmcneill * everything is properly aligned so we can copy stuff in
958 1.1 jmcneill * 32bit chunks instead of pixel by pixel
959 1.1 jmcneill */
960 1.1 jmcneill wi = wi >> 1;
961 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CSDPI,
962 1.1 jmcneill CSDPI_SRC_BURST_64 | CSDPI_DST_BURST_64 |
963 1.1 jmcneill CSDPI_DST_PACKED | CSDPI_WRITE_POSTED_EXCEPT_LAST |
964 1.1 jmcneill CSDPI_DATA_TYPE_32);
965 1.1 jmcneill } else {
966 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CSDPI,
967 1.1 jmcneill CSDPI_SRC_BURST_64 | CSDPI_DST_BURST_64 |
968 1.1 jmcneill CSDPI_DST_PACKED | CSDPI_WRITE_POSTED_EXCEPT_LAST |
969 1.1 jmcneill CSDPI_DATA_TYPE_16);
970 1.1 jmcneill }
971 1.1 jmcneill
972 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CEN, wi);
973 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CFN, he);
974 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CSSA, saddr);
975 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CDSA, daddr);
976 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CCR,
977 1.1 jmcneill CCR_DST_AMODE_DOUBLE_INDEX |
978 1.1 jmcneill CCR_SRC_AMODE_DOUBLE_INDEX);
979 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CSEI, hstep);
980 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CSFI, vstep);
981 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CDEI, hstep);
982 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CDFI, vstep);
983 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CCR,
984 1.1 jmcneill CCR_DST_AMODE_DOUBLE_INDEX |
985 1.1 jmcneill CCR_SRC_AMODE_DOUBLE_INDEX | CCR_ENABLE);
986 1.1 jmcneill }
987 1.1 jmcneill
988 1.1 jmcneill static void
989 1.1 jmcneill omapfb_cursor(void *cookie, int on, int row, int col)
990 1.1 jmcneill {
991 1.1 jmcneill struct rasops_info *ri = cookie;
992 1.1 jmcneill struct vcons_screen *scr = ri->ri_hw;
993 1.1 jmcneill struct omapfb_softc *sc = scr->scr_cookie;
994 1.1 jmcneill int pos;
995 1.1 jmcneill
996 1.1 jmcneill pos = col + row * ri->ri_cols;
997 1.1 jmcneill #ifdef WSDISPLAY_SCROLLSUPPORT
998 1.1 jmcneill pos += scr->scr_offset_to_zero;
999 1.1 jmcneill #endif
1000 1.1 jmcneill if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) {
1001 1.1 jmcneill if (ri->ri_flg & RI_CURSOR) {
1002 1.1 jmcneill omapfb_putchar(cookie, row, col, scr->scr_chars[pos],
1003 1.1 jmcneill scr->scr_attrs[pos]);
1004 1.1 jmcneill ri->ri_flg &= ~RI_CURSOR;
1005 1.1 jmcneill }
1006 1.1 jmcneill ri->ri_crow = row;
1007 1.1 jmcneill ri->ri_ccol = col;
1008 1.1 jmcneill if (on) {
1009 1.1 jmcneill omapfb_putchar(cookie, row, col, scr->scr_chars[pos],
1010 1.1 jmcneill scr->scr_attrs[pos] ^ 0x0f0f0000);
1011 1.1 jmcneill ri->ri_flg |= RI_CURSOR;
1012 1.1 jmcneill }
1013 1.1 jmcneill } else {
1014 1.1 jmcneill scr->scr_ri.ri_crow = row;
1015 1.1 jmcneill scr->scr_ri.ri_ccol = col;
1016 1.1 jmcneill scr->scr_ri.ri_flg &= ~RI_CURSOR;
1017 1.1 jmcneill }
1018 1.1 jmcneill }
1019 1.1 jmcneill
1020 1.1 jmcneill static void
1021 1.1 jmcneill omapfb_putchar(void *cookie, int row, int col, u_int c, long attr)
1022 1.1 jmcneill {
1023 1.1 jmcneill struct rasops_info *ri = cookie;
1024 1.1 jmcneill struct vcons_screen *scr = ri->ri_hw;
1025 1.1 jmcneill struct omapfb_softc *sc = scr->scr_cookie;
1026 1.1 jmcneill
1027 1.1 jmcneill if (c == 0x20) {
1028 1.1 jmcneill uint32_t fg, bg, ul;
1029 1.1 jmcneill rasops_unpack_attr(attr, &fg, &bg, &ul);
1030 1.1 jmcneill omapfb_rectfill(sc,
1031 1.1 jmcneill ri->ri_xorigin + ri->ri_font->fontwidth * col,
1032 1.1 jmcneill ri->ri_yorigin + ri->ri_font->fontheight * row,
1033 1.1 jmcneill ri->ri_font->fontwidth,
1034 1.1 jmcneill ri->ri_font->fontheight,
1035 1.1 jmcneill ri->ri_devcmap[bg]);
1036 1.1 jmcneill return;
1037 1.1 jmcneill }
1038 1.1 jmcneill omapfb_wait_idle(sc);
1039 1.1 jmcneill sc->sc_putchar(cookie, row, col, c, attr);
1040 1.1 jmcneill }
1041 1.1 jmcneill
1042 1.1 jmcneill static void
1043 1.1 jmcneill omapfb_copycols(void *cookie, int row, int srccol, int dstcol, int ncols)
1044 1.1 jmcneill {
1045 1.1 jmcneill struct rasops_info *ri = cookie;
1046 1.1 jmcneill struct vcons_screen *scr = ri->ri_hw;
1047 1.1 jmcneill struct omapfb_softc *sc = scr->scr_cookie;
1048 1.1 jmcneill int32_t xs, xd, y, width, height;
1049 1.1 jmcneill
1050 1.1 jmcneill if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
1051 1.1 jmcneill xs = ri->ri_xorigin + ri->ri_font->fontwidth * srccol;
1052 1.1 jmcneill xd = ri->ri_xorigin + ri->ri_font->fontwidth * dstcol;
1053 1.1 jmcneill y = ri->ri_yorigin + ri->ri_font->fontheight * row;
1054 1.1 jmcneill width = ri->ri_font->fontwidth * ncols;
1055 1.1 jmcneill height = ri->ri_font->fontheight;
1056 1.1 jmcneill omapfb_bitblt(sc, xs, y, xd, y, width, height, 12);
1057 1.1 jmcneill }
1058 1.1 jmcneill }
1059 1.1 jmcneill
1060 1.1 jmcneill static void
1061 1.1 jmcneill omapfb_erasecols(void *cookie, int row, int startcol, int ncols, long fillattr)
1062 1.1 jmcneill {
1063 1.1 jmcneill struct rasops_info *ri = cookie;
1064 1.1 jmcneill struct vcons_screen *scr = ri->ri_hw;
1065 1.1 jmcneill struct omapfb_softc *sc = scr->scr_cookie;
1066 1.1 jmcneill int32_t x, y, width, height, fg, bg, ul;
1067 1.1 jmcneill
1068 1.1 jmcneill if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
1069 1.1 jmcneill x = ri->ri_xorigin + ri->ri_font->fontwidth * startcol;
1070 1.1 jmcneill y = ri->ri_yorigin + ri->ri_font->fontheight * row;
1071 1.1 jmcneill width = ri->ri_font->fontwidth * ncols;
1072 1.1 jmcneill height = ri->ri_font->fontheight;
1073 1.1 jmcneill rasops_unpack_attr(fillattr, &fg, &bg, &ul);
1074 1.1 jmcneill
1075 1.1 jmcneill omapfb_rectfill(sc, x, y, width, height, ri->ri_devcmap[bg]);
1076 1.1 jmcneill }
1077 1.1 jmcneill }
1078 1.1 jmcneill
1079 1.1 jmcneill static void
1080 1.1 jmcneill omapfb_copyrows(void *cookie, int srcrow, int dstrow, int nrows)
1081 1.1 jmcneill {
1082 1.1 jmcneill struct rasops_info *ri = cookie;
1083 1.1 jmcneill struct vcons_screen *scr = ri->ri_hw;
1084 1.1 jmcneill struct omapfb_softc *sc = scr->scr_cookie;
1085 1.1 jmcneill int32_t x, ys, yd, width, height;
1086 1.1 jmcneill
1087 1.1 jmcneill if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
1088 1.1 jmcneill x = ri->ri_xorigin;
1089 1.1 jmcneill ys = ri->ri_yorigin + ri->ri_font->fontheight * srcrow;
1090 1.1 jmcneill yd = ri->ri_yorigin + ri->ri_font->fontheight * dstrow;
1091 1.1 jmcneill width = ri->ri_emuwidth;
1092 1.1 jmcneill height = ri->ri_font->fontheight * nrows;
1093 1.1 jmcneill omapfb_bitblt(sc, x, ys, x, yd, width, height, 12);
1094 1.1 jmcneill }
1095 1.1 jmcneill }
1096 1.1 jmcneill
1097 1.1 jmcneill static void
1098 1.1 jmcneill omapfb_eraserows(void *cookie, int row, int nrows, long fillattr)
1099 1.1 jmcneill {
1100 1.1 jmcneill struct rasops_info *ri = cookie;
1101 1.1 jmcneill struct vcons_screen *scr = ri->ri_hw;
1102 1.1 jmcneill struct omapfb_softc *sc = scr->scr_cookie;
1103 1.1 jmcneill int32_t x, y, width, height, fg, bg, ul;
1104 1.1 jmcneill
1105 1.1 jmcneill if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
1106 1.1 jmcneill x = ri->ri_xorigin;
1107 1.1 jmcneill y = ri->ri_yorigin + ri->ri_font->fontheight * row;
1108 1.1 jmcneill width = ri->ri_emuwidth;
1109 1.1 jmcneill height = ri->ri_font->fontheight * nrows;
1110 1.1 jmcneill rasops_unpack_attr(fillattr, &fg, &bg, &ul);
1111 1.1 jmcneill
1112 1.1 jmcneill omapfb_rectfill(sc, x, y, width, height, ri->ri_devcmap[bg]);
1113 1.1 jmcneill }
1114 1.1 jmcneill }
1115 1.1 jmcneill #endif /* NOMAPDMA > 0 */
1116 1.1 jmcneill
1117 1.1 jmcneill static void
1118 1.1 jmcneill omapfb_move_cursor(struct omapfb_softc *sc, int x, int y)
1119 1.1 jmcneill {
1120 1.1 jmcneill uint32_t pos, reg, addr;
1121 1.1 jmcneill int xx, yy, wi = 64, he = 64;
1122 1.1 jmcneill
1123 1.1 jmcneill /*
1124 1.1 jmcneill * we need to special case anything and everything where the cursor
1125 1.1 jmcneill * may be partially off screen
1126 1.1 jmcneill */
1127 1.1 jmcneill
1128 1.1 jmcneill addr = sc->sc_fbhwaddr + sc->sc_cursor_offset;
1129 1.1 jmcneill xx = x - sc->sc_hot_x;
1130 1.1 jmcneill yy = y - sc->sc_hot_y;
1131 1.1 jmcneill
1132 1.1 jmcneill /*
1133 1.1 jmcneill * if we're off to the top or left we need to shif the start address
1134 1.1 jmcneill * and shrink the gfx layer size
1135 1.1 jmcneill */
1136 1.1 jmcneill if (xx < 0) {
1137 1.1 jmcneill wi += xx;
1138 1.1 jmcneill addr -= xx * 4;
1139 1.1 jmcneill xx = 0;
1140 1.1 jmcneill }
1141 1.1 jmcneill if (yy < 0) {
1142 1.1 jmcneill he += yy;
1143 1.1 jmcneill addr -= yy * 64 * 4;
1144 1.1 jmcneill yy = 0;
1145 1.1 jmcneill }
1146 1.1 jmcneill if (xx > (sc->sc_width - 64)) {
1147 1.1 jmcneill wi -= (xx + 64 - sc->sc_width);
1148 1.1 jmcneill }
1149 1.1 jmcneill if (yy > (sc->sc_height - 64)) {
1150 1.1 jmcneill he -= (yy + 64 - sc->sc_height);
1151 1.1 jmcneill }
1152 1.1 jmcneill pos = (yy << 16) | xx;
1153 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GFX_BASE_0,
1154 1.1 jmcneill addr);
1155 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GFX_POSITION,
1156 1.1 jmcneill pos);
1157 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GFX_SIZE,
1158 1.1 jmcneill ((he - 1) << 16) | (wi - 1));
1159 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GFX_ROW_INC,
1160 1.1 jmcneill (64 - wi) * 4 + 1);
1161 1.1 jmcneill /*
1162 1.1 jmcneill * now tell the video controller that we're done mucking around and
1163 1.1 jmcneill * actually update its settings
1164 1.1 jmcneill */
1165 1.1 jmcneill reg = bus_space_read_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONTROL);
1166 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONTROL,
1167 1.1 jmcneill reg | OMAP_DISPC_CTRL_GO_LCD | OMAP_DISPC_CTRL_GO_DIGITAL);
1168 1.1 jmcneill }
1169 1.1 jmcneill
1170 1.1 jmcneill static int
1171 1.1 jmcneill omapfb_do_cursor(struct omapfb_softc * sc,
1172 1.1 jmcneill struct wsdisplay_cursor *cur)
1173 1.1 jmcneill {
1174 1.1 jmcneill int whack = 0;
1175 1.1 jmcneill int shape = 0;
1176 1.1 jmcneill
1177 1.1 jmcneill if (cur->which & WSDISPLAY_CURSOR_DOCUR) {
1178 1.1 jmcneill uint32_t attr = OMAP_DISPC_ATTR_BURST_16x32 |
1179 1.1 jmcneill OMAP_DISPC_ATTR_ARGB32 |
1180 1.1 jmcneill OMAP_DISPC_ATTR_REPLICATION;
1181 1.1 jmcneill
1182 1.1 jmcneill if (cur->enable) attr |= OMAP_DISPC_ATTR_ENABLE;
1183 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh,
1184 1.1 jmcneill OMAPFB_DISPC_GFX_ATTRIBUTES, attr);
1185 1.1 jmcneill whack = 1;
1186 1.1 jmcneill }
1187 1.1 jmcneill if (cur->which & WSDISPLAY_CURSOR_DOHOT) {
1188 1.1 jmcneill
1189 1.1 jmcneill sc->sc_hot_x = cur->hot.x;
1190 1.1 jmcneill sc->sc_hot_y = cur->hot.y;
1191 1.1 jmcneill cur->which |= WSDISPLAY_CURSOR_DOPOS;
1192 1.1 jmcneill }
1193 1.1 jmcneill if (cur->which & WSDISPLAY_CURSOR_DOPOS) {
1194 1.1 jmcneill
1195 1.1 jmcneill omapfb_move_cursor(sc, cur->pos.x, cur->pos.y);
1196 1.1 jmcneill }
1197 1.1 jmcneill if (cur->which & WSDISPLAY_CURSOR_DOCMAP) {
1198 1.1 jmcneill int i;
1199 1.1 jmcneill uint32_t val;
1200 1.1 jmcneill
1201 1.1 jmcneill for (i = 0; i < uimin(cur->cmap.count, 3); i++) {
1202 1.1 jmcneill val = (cur->cmap.red[i] << 16 ) |
1203 1.1 jmcneill (cur->cmap.green[i] << 8) |
1204 1.1 jmcneill (cur->cmap.blue[i] ) |
1205 1.1 jmcneill 0xff000000;
1206 1.1 jmcneill sc->sc_cursor_cmap[i + cur->cmap.index + 2] = val;
1207 1.1 jmcneill }
1208 1.1 jmcneill shape = 1;
1209 1.1 jmcneill }
1210 1.1 jmcneill if (cur->which & WSDISPLAY_CURSOR_DOSHAPE) {
1211 1.1 jmcneill
1212 1.1 jmcneill copyin(cur->mask, sc->sc_cursor_mask, 64 * 8);
1213 1.1 jmcneill copyin(cur->image, sc->sc_cursor_bitmap, 64 * 8);
1214 1.1 jmcneill shape = 1;
1215 1.1 jmcneill }
1216 1.1 jmcneill if (shape) {
1217 1.1 jmcneill int i, j, idx;
1218 1.1 jmcneill uint8_t mask;
1219 1.1 jmcneill
1220 1.1 jmcneill for (i = 0; i < 64 * 8; i++) {
1221 1.1 jmcneill mask = 0x01;
1222 1.1 jmcneill for (j = 0; j < 8; j++) {
1223 1.1 jmcneill idx = ((sc->sc_cursor_mask[i] & mask) ? 2 : 0) |
1224 1.1 jmcneill ((sc->sc_cursor_bitmap[i] & mask) ? 1 : 0);
1225 1.1 jmcneill sc->sc_cursor_img[i * 8 + j] =
1226 1.1 jmcneill sc->sc_cursor_cmap[idx];
1227 1.1 jmcneill mask = mask << 1;
1228 1.1 jmcneill }
1229 1.1 jmcneill }
1230 1.1 jmcneill }
1231 1.1 jmcneill if (whack) {
1232 1.1 jmcneill uint32_t reg;
1233 1.1 jmcneill
1234 1.1 jmcneill reg = bus_space_read_4(sc->sc_iot, sc->sc_regh,
1235 1.1 jmcneill OMAPFB_DISPC_CONTROL);
1236 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONTROL,
1237 1.1 jmcneill reg | OMAP_DISPC_CTRL_GO_LCD | OMAP_DISPC_CTRL_GO_DIGITAL);
1238 1.1 jmcneill }
1239 1.1 jmcneill return 0;
1240 1.1 jmcneill
1241 1.1 jmcneill }
1242 1.1 jmcneill
1243 1.1 jmcneill static int
1244 1.1 jmcneill omapfb_console_match(int phandle)
1245 1.1 jmcneill {
1246 1.1 jmcneill return of_match_compatible(phandle, compatible);
1247 1.1 jmcneill }
1248 1.1 jmcneill
1249 1.1 jmcneill static void
1250 1.1 jmcneill omapfb_console_consinit(struct fdt_attach_args *faa, u_int uart_freq)
1251 1.1 jmcneill {
1252 1.1 jmcneill omapfb_console_phandle = faa->faa_phandle;
1253 1.1 jmcneill }
1254 1.1 jmcneill
1255 1.1 jmcneill static const struct fdt_console omapfb_fdt_console = {
1256 1.1 jmcneill .match = omapfb_console_match,
1257 1.1 jmcneill .consinit = omapfb_console_consinit,
1258 1.1 jmcneill };
1259 1.1 jmcneill
1260 1.1 jmcneill FDT_CONSOLE(omapfb, &omapfb_fdt_console);
1261