Sun Apr 12 20:00:42 2015 UTC ()
flushing the framebuffer from interrupt has several problems:
- As pointed out by Jared McNeill, this doesn't work for cold
  or ddb. Some specific handing for these cases would be needed,
  but there's no easy way to know if we're in ddb or not.
- periodic bus_dmamap_sync() of the whole framebuffer isn't cheap (about
  3% CPU constant on the beaglebone back).

instead map the framebuffer BUS_DMA_PREFETCHABLE (undocumented flag, but
is MI and properly handled by arm). This allows write-combining,
which, in addition with a shadow framebuffer for rasops(9) gives
a good performance boost too (difference with the cached+sync from intr
isn't noticeable on a boot sequence).
For X11, the framebuffer was already mapped BUS_DMA_PREFETCHABLE.
A few tests shows that mapping it fully cached doesn't make a noticeable
difference either (with or without xorg's shadow framebuffer).


(bouyer)
diff -r1.4 -r1.5 src/sys/arch/arm/omap/tifb.c

cvs diff -r1.4 -r1.5 src/sys/arch/arm/omap/Attic/tifb.c (switch to unified diff)

--- src/sys/arch/arm/omap/Attic/tifb.c 2015/04/11 13:44:14 1.4
+++ src/sys/arch/arm/omap/Attic/tifb.c 2015/04/12 20:00:42 1.5
@@ -1,1093 +1,1103 @@ @@ -1,1093 +1,1103 @@
1/* $NetBSD: tifb.c,v 1.4 2015/04/11 13:44:14 bouyer Exp $ */ 1/* $NetBSD: tifb.c,v 1.5 2015/04/12 20:00:42 bouyer Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2010 Michael Lorenz 4 * Copyright (c) 2010 Michael Lorenz
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28/* 28/*
29 * Copyright 2013 Oleksandr Tymoshenko <gonzo@freebsd.org> 29 * Copyright 2013 Oleksandr Tymoshenko <gonzo@freebsd.org>
30 * All rights reserved. 30 * All rights reserved.
31 * 31 *
32 * Redistribution and use in source and binary forms, with or without 32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions 33 * modification, are permitted provided that the following conditions
34 * are met: 34 * are met:
35 * 1. Redistributions of source code must retain the above copyright 35 * 1. Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer. 36 * notice, this list of conditions and the following disclaimer.
37 * 2. Redistributions in binary form must reproduce the above copyright 37 * 2. Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the 38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution. 39 * documentation and/or other materials provided with the distribution.
40 * 40 *
41 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 41 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 44 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51 * SUCH DAMAGE. 51 * SUCH DAMAGE.
52 */ 52 */
53 53
54/* 54/*
55 * A framebuffer driver for TI 35xx built-in video controller 55 * A framebuffer driver for TI 35xx built-in video controller
56 * tested on beaglebone 56 * tested on beaglebone
57 */ 57 */
58 58
59#include <sys/cdefs.h> 59#include <sys/cdefs.h>
60__KERNEL_RCSID(0, "$NetBSD: tifb.c,v 1.4 2015/04/11 13:44:14 bouyer Exp $"); 60__KERNEL_RCSID(0, "$NetBSD: tifb.c,v 1.5 2015/04/12 20:00:42 bouyer Exp $");
61 61
62#include "opt_omap.h" 62#include "opt_omap.h"
63 63
64#include <sys/param.h> 64#include <sys/param.h>
65#include <sys/systm.h> 65#include <sys/systm.h>
66#include <sys/kernel.h> 66#include <sys/kernel.h>
67#include <sys/device.h> 67#include <sys/device.h>
68#include <sys/malloc.h> 68#include <sys/malloc.h>
69#include <sys/lwp.h> 69#include <sys/lwp.h>
70#include <sys/kauth.h> 70#include <sys/kauth.h>
 71#include <sys/kmem.h>
71 72
72#include <uvm/uvm_extern.h> 73#include <uvm/uvm_extern.h>
73 74
74#include <dev/videomode/videomode.h> 75#include <dev/videomode/videomode.h>
75 76
76#include <sys/bus.h> 77#include <sys/bus.h>
77#include <arm/omap/tifbreg.h> 78#include <arm/omap/tifbreg.h>
78#include <arm/omap/omap_var.h> 79#include <arm/omap/omap_var.h>
79#include <arm/omap/omap2_obiovar.h> 80#include <arm/omap/omap2_obiovar.h>
80#include <arm/omap/omap2_obioreg.h> 81#include <arm/omap/omap2_obioreg.h>
81#ifdef TI_AM335X 82#ifdef TI_AM335X
82# include <arm/omap/am335x_prcm.h> 83# include <arm/omap/am335x_prcm.h>
83# include <arm/omap/omap2_prcm.h> 84# include <arm/omap/omap2_prcm.h>
84# include <arm/omap/sitara_cm.h> 85# include <arm/omap/sitara_cm.h>
85# include <arm/omap/sitara_cmreg.h> 86# include <arm/omap/sitara_cmreg.h>
86#endif 87#endif
87 88
88#include <dev/wscons/wsdisplayvar.h> 89#include <dev/wscons/wsdisplayvar.h>
89#include <dev/wscons/wsconsio.h> 90#include <dev/wscons/wsconsio.h>
90#include <dev/wsfont/wsfont.h> 91#include <dev/wsfont/wsfont.h>
91#include <dev/rasops/rasops.h> 92#include <dev/rasops/rasops.h>
92#include <dev/wscons/wsdisplay_vconsvar.h> 93#include <dev/wscons/wsdisplay_vconsvar.h>
93 94
94#include <dev/videomode/edidvar.h> 95#include <dev/videomode/edidvar.h>
95 96
96#include "locators.h" 97#include "locators.h"
97 98
98struct panel_info { 99struct panel_info {
99 uint32_t panel_width; 100 uint32_t panel_width;
100 uint32_t panel_height; 101 uint32_t panel_height;
101 uint32_t panel_hfp; 102 uint32_t panel_hfp;
102 uint32_t panel_hbp; 103 uint32_t panel_hbp;
103 uint32_t panel_hsw; 104 uint32_t panel_hsw;
104 uint32_t panel_vfp; 105 uint32_t panel_vfp;
105 uint32_t panel_vbp; 106 uint32_t panel_vbp;
106 uint32_t panel_vsw; 107 uint32_t panel_vsw;
107 uint32_t ac_bias; 108 uint32_t ac_bias;
108 uint32_t ac_bias_intrpt; 109 uint32_t ac_bias_intrpt;
109 uint32_t dma_burst_sz; 110 uint32_t dma_burst_sz;
110 uint32_t bpp; 111 uint32_t bpp;
111 uint32_t fdd; 112 uint32_t fdd;
112 uint32_t invert_line_clock; 113 uint32_t invert_line_clock;
113 uint32_t invert_frm_clock; 114 uint32_t invert_frm_clock;
114 uint32_t sync_edge; 115 uint32_t sync_edge;
115 uint32_t sync_ctrl; 116 uint32_t sync_ctrl;
116 uint32_t panel_pxl_clk; 117 uint32_t panel_pxl_clk;
117 uint32_t panel_invert_pxl_clk; 118 uint32_t panel_invert_pxl_clk;
118}; 119};
119 120
120/* for chalk elec cape with 12" panel */ 121/* for chalk elec cape with 12" panel */
121struct panel_info default_panel_info = { 122struct panel_info default_panel_info = {
122 .panel_width = 1280, 123 .panel_width = 1280,
123 .panel_height = 800, 124 .panel_height = 800,
124 .panel_hfp = 48, 125 .panel_hfp = 48,
125 .panel_hbp = 80, 126 .panel_hbp = 80,
126 .panel_hsw = 32, 127 .panel_hsw = 32,
127 .panel_vfp = 2, 128 .panel_vfp = 2,
128 .panel_vbp = 15, 129 .panel_vbp = 15,
129 .panel_vsw = 6, 130 .panel_vsw = 6,
130 .ac_bias = 255, 131 .ac_bias = 255,
131 .ac_bias_intrpt = 0, 132 .ac_bias_intrpt = 0,
132 .dma_burst_sz = 16, 133 .dma_burst_sz = 16,
133 .bpp = 16, 134 .bpp = 16,
134 .fdd = 16, 135 .fdd = 16,
135 .invert_line_clock = 0, 136 .invert_line_clock = 0,
136 .invert_frm_clock = 0, 137 .invert_frm_clock = 0,
137 .sync_edge = 0, 138 .sync_edge = 0,
138 .sync_ctrl = 1, 139 .sync_ctrl = 1,
139 .panel_pxl_clk = 69300000, 140 .panel_pxl_clk = 69300000,
140 .panel_invert_pxl_clk = 0, 141 .panel_invert_pxl_clk = 0,
141}; 142};
142 143
143struct tifb_softc { 144struct tifb_softc {
144 device_t sc_dev; 145 device_t sc_dev;
145 146
146 void *sc_ih; 147 void *sc_ih;
147 bus_space_tag_t sc_iot; 148 bus_space_tag_t sc_iot;
148 bus_dma_tag_t sc_dmat; 149 bus_dma_tag_t sc_dmat;
149 bus_space_handle_t sc_regh; 150 bus_space_handle_t sc_regh;
150 bus_dmamap_t sc_dmamap; 151 bus_dmamap_t sc_dmamap;
151 bus_dma_segment_t sc_dmamem[1]; 152 bus_dma_segment_t sc_dmamem[1];
152 size_t sc_vramsize; 153 size_t sc_vramsize;
153 size_t sc_palettesize; 154 size_t sc_palettesize;
154 155
155 int sc_stride; 156 int sc_stride;
156 int sc_locked; 157 int sc_locked;
157 void *sc_fbaddr, *sc_vramaddr; 158 void *sc_fbaddr, *sc_vramaddr;
 159 void *sc_shadowfb;
158 160
159 bus_addr_t sc_fbhwaddr; 161 bus_addr_t sc_fbhwaddr;
160 uint16_t *sc_palette; 162 uint16_t *sc_palette;
161 uint32_t sc_dispc_config; 163 uint32_t sc_dispc_config;
162 struct vcons_screen sc_console_screen; 164 struct vcons_screen sc_console_screen;
163 struct wsscreen_descr sc_defaultscreen_descr; 165 struct wsscreen_descr sc_defaultscreen_descr;
164 const struct wsscreen_descr *sc_screens[1]; 166 const struct wsscreen_descr *sc_screens[1];
165 struct wsscreen_list sc_screenlist; 167 struct wsscreen_list sc_screenlist;
166 struct vcons_data vd; 168 struct vcons_data vd;
167 int sc_mode; 169 int sc_mode;
168 uint8_t sc_cmap_red[256], sc_cmap_green[256], sc_cmap_blue[256]; 170 uint8_t sc_cmap_red[256], sc_cmap_green[256], sc_cmap_blue[256];
169 void (*sc_putchar)(void *, int, int, u_int, long); 171 void (*sc_putchar)(void *, int, int, u_int, long);
170 172
171 uint8_t sc_edid_data[1024]; 173 uint8_t sc_edid_data[1024];
172 size_t sc_edid_size; 174 size_t sc_edid_size;
173 175
174 struct panel_info *sc_panel; 176 struct panel_info *sc_panel;
175}; 177};
176 178
177#define TIFB_READ(sc, reg) bus_space_read_4(sc->sc_iot, sc->sc_regh, reg) 179#define TIFB_READ(sc, reg) bus_space_read_4(sc->sc_iot, sc->sc_regh, reg)
178#define TIFB_WRITE(sc, reg, val) bus_space_write_4(sc->sc_iot, sc->sc_regh, reg, val) 180#define TIFB_WRITE(sc, reg, val) bus_space_write_4(sc->sc_iot, sc->sc_regh, reg, val)
179 181
180static int tifb_match(device_t, cfdata_t, void *); 182static int tifb_match(device_t, cfdata_t, void *);
181static void tifb_attach(device_t, device_t, void *); 183static void tifb_attach(device_t, device_t, void *);
182static int tifb_intr(void *); 184static int tifb_intr(void *);
183 185
184 186
185#ifdef TI_AM335X 187#ifdef TI_AM335X
186static void am335x_clk_lcdc_activate(void); 188static void am335x_clk_lcdc_activate(void);
187static int am335x_clk_get_arm_disp_freq(unsigned int *); 189static int am335x_clk_get_arm_disp_freq(unsigned int *);
188#endif 190#endif
189 191
190 192
191CFATTACH_DECL_NEW(tifb, sizeof(struct tifb_softc), 193CFATTACH_DECL_NEW(tifb, sizeof(struct tifb_softc),
192 tifb_match, tifb_attach, NULL, NULL); 194 tifb_match, tifb_attach, NULL, NULL);
193 195
194static int tifb_ioctl(void *, void *, u_long, void *, int, 196static int tifb_ioctl(void *, void *, u_long, void *, int,
195 struct lwp *); 197 struct lwp *);
196static paddr_t tifb_mmap(void *, void *, off_t, int); 198static paddr_t tifb_mmap(void *, void *, off_t, int);
197static void tifb_init_screen(void *, struct vcons_screen *, int, long *); 199static void tifb_init_screen(void *, struct vcons_screen *, int, long *);
198 200
199static int tifb_putcmap(struct tifb_softc *, struct wsdisplay_cmap *); 201static int tifb_putcmap(struct tifb_softc *, struct wsdisplay_cmap *);
200static int tifb_getcmap(struct tifb_softc *, struct wsdisplay_cmap *); 202static int tifb_getcmap(struct tifb_softc *, struct wsdisplay_cmap *);
201#if 0 203#if 0
202static void tifb_restore_palette(struct tifb_softc *); 204static void tifb_restore_palette(struct tifb_softc *);
203static void tifb_putpalreg(struct tifb_softc *, int, uint8_t, 205static void tifb_putpalreg(struct tifb_softc *, int, uint8_t,
204 uint8_t, uint8_t); 206 uint8_t, uint8_t);
205 207
206static int tifb_set_depth(struct tifb_softc *, int); 208static int tifb_set_depth(struct tifb_softc *, int);
207#endif 209#endif
208static void tifb_set_video(struct tifb_softc *, int); 210static void tifb_set_video(struct tifb_softc *, int);
209 211
210struct wsdisplay_accessops tifb_accessops = { 212struct wsdisplay_accessops tifb_accessops = {
211 tifb_ioctl, 213 tifb_ioctl,
212 tifb_mmap, 214 tifb_mmap,
213 NULL, /* alloc_screen */ 215 NULL, /* alloc_screen */
214 NULL, /* free_screen */ 216 NULL, /* free_screen */
215 NULL, /* show_screen */ 217 NULL, /* show_screen */
216 NULL, /* load_font */ 218 NULL, /* load_font */
217 NULL, /* pollc */ 219 NULL, /* pollc */
218 NULL /* scroll */ 220 NULL /* scroll */
219}; 221};
220 222
221extern const u_char rasops_cmap[768]; 223extern const u_char rasops_cmap[768];
222 224
223static struct evcnt ev_sync_lost; 225static struct evcnt ev_sync_lost;
224static struct evcnt ev_palette; 226static struct evcnt ev_palette;
225static struct evcnt ev_eof0; 227static struct evcnt ev_eof0;
226static struct evcnt ev_eof1; 228static struct evcnt ev_eof1;
227static struct evcnt ev_fifo_underflow; 229static struct evcnt ev_fifo_underflow;
228static struct evcnt ev_ac_bias; 230static struct evcnt ev_ac_bias;
229static struct evcnt ev_frame_done; 231static struct evcnt ev_frame_done;
230static struct evcnt ev_others; 232static struct evcnt ev_others;
231 233
232 234
233static uint32_t 235static uint32_t
234am335x_lcd_calc_divisor(uint32_t reference, uint32_t freq) 236am335x_lcd_calc_divisor(uint32_t reference, uint32_t freq)
235{ 237{
236 uint32_t div; 238 uint32_t div;
237 /* Raster mode case: divisors are in range from 2 to 255 */ 239 /* Raster mode case: divisors are in range from 2 to 255 */
238 for (div = 2; div < 255; div++) 240 for (div = 2; div < 255; div++)
239 if (reference/div <= freq) 241 if (reference/div <= freq)
240 return (div); 242 return (div);
241 243
242 return (255); 244 return (255);
243} 245}
244 246
245static int 247static int
246tifb_match(device_t parent, cfdata_t match, void *aux) 248tifb_match(device_t parent, cfdata_t match, void *aux)
247{ 249{
248 struct obio_attach_args *obio = aux; 250 struct obio_attach_args *obio = aux;
249 251
250 if ((obio->obio_addr == -1) || (obio->obio_size == 0)) 252 if ((obio->obio_addr == -1) || (obio->obio_size == 0))
251 return 0; 253 return 0;
252 return 1; 254 return 1;
253} 255}
254 256
255static void 257static void
256tifb_attach(device_t parent, device_t self, void *aux) 258tifb_attach(device_t parent, device_t self, void *aux)
257{ 259{
258 struct tifb_softc *sc = device_private(self); 260 struct tifb_softc *sc = device_private(self);
259 struct obio_attach_args *obio = aux; 261 struct obio_attach_args *obio = aux;
260 struct rasops_info *ri; 262 struct rasops_info *ri;
261 struct wsemuldisplaydev_attach_args aa; 263 struct wsemuldisplaydev_attach_args aa;
262 prop_dictionary_t dict; 264 prop_dictionary_t dict;
263 /* prop_data_t edid_data; XXX */ 265 /* prop_data_t edid_data; XXX */
264 unsigned long defattr; 266 unsigned long defattr;
265 bool is_console = false; 267 bool is_console = false;
266 uint32_t reg, timing0, timing1, timing2, burst_log; 268 uint32_t reg, timing0, timing1, timing2, burst_log;
267 int segs, i, div, ref_freq; 269 int segs, i, div, ref_freq;
268 270
269#ifdef TI_AM335X 271#ifdef TI_AM335X
270 int ret; 272 int ret;
271 const char *mode; 273 const char *mode;
272 u_int state; 274 u_int state;
273 struct tifb_padconf { 275 struct tifb_padconf {
274 const char *padname; 276 const char *padname;
275 const char *padmode; 277 const char *padmode;
276 }; 278 };
277 const struct tifb_padconf tifb_padconf_data[] = { 279 const struct tifb_padconf tifb_padconf_data[] = {
278 {"LCD_DATA0", "lcd_data0"}, 280 {"LCD_DATA0", "lcd_data0"},
279 {"LCD_DATA1", "lcd_data1"}, 281 {"LCD_DATA1", "lcd_data1"},
280 {"LCD_DATA2", "lcd_data2"}, 282 {"LCD_DATA2", "lcd_data2"},
281 {"LCD_DATA3", "lcd_data3"}, 283 {"LCD_DATA3", "lcd_data3"},
282 {"LCD_DATA4", "lcd_data4"}, 284 {"LCD_DATA4", "lcd_data4"},
283 {"LCD_DATA5", "lcd_data5"}, 285 {"LCD_DATA5", "lcd_data5"},
284 {"LCD_DATA6", "lcd_data6"}, 286 {"LCD_DATA6", "lcd_data6"},
285 {"LCD_DATA7", "lcd_data7"}, 287 {"LCD_DATA7", "lcd_data7"},
286 {"LCD_DATA8", "lcd_data8"}, 288 {"LCD_DATA8", "lcd_data8"},
287 {"LCD_DATA9", "lcd_data9"}, 289 {"LCD_DATA9", "lcd_data9"},
288 {"LCD_DATA10", "lcd_data10"}, 290 {"LCD_DATA10", "lcd_data10"},
289 {"LCD_DATA11", "lcd_data11"}, 291 {"LCD_DATA11", "lcd_data11"},
290 {"LCD_DATA12", "lcd_data12"}, 292 {"LCD_DATA12", "lcd_data12"},
291 {"LCD_DATA13", "lcd_data13"}, 293 {"LCD_DATA13", "lcd_data13"},
292 {"LCD_DATA14", "lcd_data14"}, 294 {"LCD_DATA14", "lcd_data14"},
293 {"LCD_DATA15", "lcd_data15"}, 295 {"LCD_DATA15", "lcd_data15"},
294 {"GPMC_AD15", "lcd_data16"}, 296 {"GPMC_AD15", "lcd_data16"},
295 {"GPMC_AD14", "lcd_data17"}, 297 {"GPMC_AD14", "lcd_data17"},
296 {"GPMC_AD13", "lcd_data18"}, 298 {"GPMC_AD13", "lcd_data18"},
297 {"GPMC_AD12", "lcd_data19"}, 299 {"GPMC_AD12", "lcd_data19"},
298 {"GPMC_AD11", "lcd_data20"}, 300 {"GPMC_AD11", "lcd_data20"},
299 {"GPMC_AD10", "lcd_data21"}, 301 {"GPMC_AD10", "lcd_data21"},
300 {"GPMC_AD9", "lcd_data22"}, 302 {"GPMC_AD9", "lcd_data22"},
301 {"GPMC_AD8", "lcd_data23"}, 303 {"GPMC_AD8", "lcd_data23"},
302 }; 304 };
303 const struct tifb_padconf tifb_padconf_ctrl[] = { 305 const struct tifb_padconf tifb_padconf_ctrl[] = {
304 {"LCD_VSYNC", "lcd_vsync"}, 306 {"LCD_VSYNC", "lcd_vsync"},
305 {"LCD_HSYNC", "lcd_hsync"}, 307 {"LCD_HSYNC", "lcd_hsync"},
306 {"LCD_PCLK", "lcd_pclk"}, 308 {"LCD_PCLK", "lcd_pclk"},
307 {"LCD_AC_BIAS_EN", "lcd_ac_bias_en"}, 309 {"LCD_AC_BIAS_EN", "lcd_ac_bias_en"},
308 }; 310 };
309#endif 311#endif
310 312
311 evcnt_attach_dynamic(&ev_sync_lost, EVCNT_TYPE_MISC, NULL, 313 evcnt_attach_dynamic(&ev_sync_lost, EVCNT_TYPE_MISC, NULL,
312 "lcd", "sync lost"); 314 "lcd", "sync lost");
313 evcnt_attach_dynamic(&ev_palette, EVCNT_TYPE_MISC, NULL, 315 evcnt_attach_dynamic(&ev_palette, EVCNT_TYPE_MISC, NULL,
314 "lcd", "palette loaded"); 316 "lcd", "palette loaded");
315 evcnt_attach_dynamic(&ev_eof0, EVCNT_TYPE_MISC, NULL, 317 evcnt_attach_dynamic(&ev_eof0, EVCNT_TYPE_MISC, NULL,
316 "lcd", "eof0"); 318 "lcd", "eof0");
317 evcnt_attach_dynamic(&ev_eof1, EVCNT_TYPE_MISC, NULL, 319 evcnt_attach_dynamic(&ev_eof1, EVCNT_TYPE_MISC, NULL,
318 "lcd", "eof1"); 320 "lcd", "eof1");
319 evcnt_attach_dynamic(&ev_fifo_underflow, EVCNT_TYPE_MISC, NULL, 321 evcnt_attach_dynamic(&ev_fifo_underflow, EVCNT_TYPE_MISC, NULL,
320 "lcd", "fifo underflow"); 322 "lcd", "fifo underflow");
321 evcnt_attach_dynamic(&ev_ac_bias, EVCNT_TYPE_MISC, NULL, 323 evcnt_attach_dynamic(&ev_ac_bias, EVCNT_TYPE_MISC, NULL,
322 "lcd", "ac bias"); 324 "lcd", "ac bias");
323 evcnt_attach_dynamic(&ev_frame_done, EVCNT_TYPE_MISC, NULL, 325 evcnt_attach_dynamic(&ev_frame_done, EVCNT_TYPE_MISC, NULL,
324 "lcd", "frame_done"); 326 "lcd", "frame_done");
325 evcnt_attach_dynamic(&ev_others, EVCNT_TYPE_MISC, NULL, 327 evcnt_attach_dynamic(&ev_others, EVCNT_TYPE_MISC, NULL,
326 "lcd", "others"); 328 "lcd", "others");
327 329
328 sc->sc_iot = obio->obio_iot; 330 sc->sc_iot = obio->obio_iot;
329 sc->sc_dev = self; 331 sc->sc_dev = self;
330 sc->sc_dmat = obio->obio_dmat; 332 sc->sc_dmat = obio->obio_dmat;
331 333
332 if (bus_space_map(obio->obio_iot, obio->obio_addr, obio->obio_size, 0, 334 if (bus_space_map(obio->obio_iot, obio->obio_addr, obio->obio_size, 0,
333 &sc->sc_regh)) { 335 &sc->sc_regh)) {
334 aprint_error(": couldn't map register space\n"); 336 aprint_error(": couldn't map register space\n");
335 return; 337 return;
336 } 338 }
337 339
338 sc->sc_panel = &default_panel_info;/* XXX */ 340 sc->sc_panel = &default_panel_info;/* XXX */
339 341
340 switch(sc->sc_panel->bpp) { 342 switch(sc->sc_panel->bpp) {
341 case 16: 343 case 16:
342 case 24: 344 case 24:
343 case 32: 345 case 32:
344 break; 346 break;
345 default: 347 default:
346 aprint_error_dev(self, "bogus display bpp, not attaching\n"); 348 aprint_error_dev(self, "bogus display bpp, not attaching\n");
347 return; 349 return;
348 } 350 }
349 351
350 sc->sc_stride = sc->sc_panel->panel_width * sc->sc_panel->bpp / 8; 352 sc->sc_stride = sc->sc_panel->panel_width * sc->sc_panel->bpp / 8;
351 353
352 if (sc->sc_panel->panel_width == 0 || 354 if (sc->sc_panel->panel_width == 0 ||
353 sc->sc_panel->panel_height == 0) { 355 sc->sc_panel->panel_height == 0) {
354 aprint_error_dev(self, "bogus display size, not attaching\n"); 356 aprint_error_dev(self, "bogus display size, not attaching\n");
355 return; 357 return;
356 } 358 }
357 359
358 if (obio->obio_intr == OBIOCF_INTR_DEFAULT) { 360 if (obio->obio_intr == OBIOCF_INTR_DEFAULT) {
359 aprint_error(": no interrupt\n"); 361 aprint_error(": no interrupt\n");
360 bus_space_unmap(obio->obio_iot, sc->sc_regh, 362 bus_space_unmap(obio->obio_iot, sc->sc_regh,
361 obio->obio_size); 363 obio->obio_size);
362 return; 364 return;
363 } 365 }
364 sc->sc_ih = intr_establish(obio->obio_intr, IPL_NET, IST_LEVEL, 366 sc->sc_ih = intr_establish(obio->obio_intr, IPL_NET, IST_LEVEL,
365 tifb_intr, sc); 367 tifb_intr, sc);
366 KASSERT(sc->sc_ih != NULL); 368 KASSERT(sc->sc_ih != NULL);
367 369
368 dict = device_properties(self); 370 dict = device_properties(self);
369 prop_dictionary_get_bool(dict, "is_console", &is_console); 371 prop_dictionary_get_bool(dict, "is_console", &is_console);
370#if 0 372#if 0
371 edid_data = prop_dictionary_get(dict, "EDID"); 373 edid_data = prop_dictionary_get(dict, "EDID");
372 if (edid_data != NULL) { 374 if (edid_data != NULL) {
373 struct edid_info ei; 375 struct edid_info ei;
374 376
375 sc->sc_edid_size = min(prop_data_size(edid_data), 1024); 377 sc->sc_edid_size = min(prop_data_size(edid_data), 1024);
376 memset(sc->sc_edid_data, 0, sizeof(sc->sc_edid_data)); 378 memset(sc->sc_edid_data, 0, sizeof(sc->sc_edid_data));
377 memcpy(sc->sc_edid_data, prop_data_data_nocopy(edid_data), 379 memcpy(sc->sc_edid_data, prop_data_data_nocopy(edid_data),
378 sc->sc_edid_size); 380 sc->sc_edid_size);
379 381
380 edid_parse(sc->sc_edid_data, &ei); 382 edid_parse(sc->sc_edid_data, &ei);
381 edid_print(&ei); 383 edid_print(&ei);
382 } 384 }
383#endif 385#endif
384 386
385 /* setup video DMA */ 387 /* setup video DMA */
386 switch(sc->sc_panel->bpp) { 388 switch(sc->sc_panel->bpp) {
387 case 8: 389 case 8:
388 sc->sc_palettesize = 512; 390 sc->sc_palettesize = 512;
389 break; 391 break;
390 default: 392 default:
391 sc->sc_palettesize = 32; 393 sc->sc_palettesize = 32;
392 break; 394 break;
393 } 395 }
394 396
395 sc->sc_vramsize = sc->sc_palettesize + 397 sc->sc_vramsize = sc->sc_palettesize +
396 sc->sc_stride * sc->sc_panel->panel_height; 398 sc->sc_stride * sc->sc_panel->panel_height;
397 399
 400 sc->sc_shadowfb = kmem_alloc(sc->sc_vramsize - sc->sc_palettesize,
 401 KM_NOSLEEP);
 402 if (sc->sc_shadowfb == NULL) {
 403 aprint_error_dev(sc->sc_dev,
 404 "warning: failed to allocate shadow framebuffer\n");
 405 }
398 if (bus_dmamem_alloc(sc->sc_dmat, sc->sc_vramsize, 0, 0, 406 if (bus_dmamem_alloc(sc->sc_dmat, sc->sc_vramsize, 0, 0,
399 sc->sc_dmamem, 1, &segs, BUS_DMA_NOWAIT) != 0) { 407 sc->sc_dmamem, 1, &segs, BUS_DMA_NOWAIT) != 0) {
400 aprint_error_dev(sc->sc_dev, 408 aprint_error_dev(sc->sc_dev,
401 "failed to allocate video memory\n"); 409 "failed to allocate video memory\n");
402 return; 410 return;
403 } 411 }
404 412
405 if (bus_dmamem_map(sc->sc_dmat, sc->sc_dmamem, 1, sc->sc_vramsize, 413 if (bus_dmamem_map(sc->sc_dmat, sc->sc_dmamem, 1, sc->sc_vramsize,
406 &sc->sc_vramaddr, BUS_DMA_NOWAIT) != 0) { 414 &sc->sc_vramaddr, BUS_DMA_NOWAIT | BUS_DMA_PREFETCHABLE) != 0) {
407 aprint_error_dev(sc->sc_dev, "failed to map video RAM\n"); 415 aprint_error_dev(sc->sc_dev, "failed to map video RAM\n");
408 return; 416 return;
409 } 417 }
410 sc->sc_fbaddr = (uint8_t *)sc->sc_vramaddr + sc->sc_palettesize; 418 sc->sc_fbaddr = (uint8_t *)sc->sc_vramaddr + sc->sc_palettesize;
411 sc->sc_palette = sc->sc_vramaddr; 419 sc->sc_palette = sc->sc_vramaddr;
412 420
413 if (bus_dmamap_create(sc->sc_dmat, sc->sc_vramsize, 1, sc->sc_vramsize, 421 if (bus_dmamap_create(sc->sc_dmat, sc->sc_vramsize, 1, sc->sc_vramsize,
414 0, BUS_DMA_NOWAIT, &sc->sc_dmamap) != 0) { 422 0, BUS_DMA_NOWAIT, &sc->sc_dmamap) != 0) {
415 aprint_error_dev(sc->sc_dev, "failed to create DMA map\n"); 423 aprint_error_dev(sc->sc_dev, "failed to create DMA map\n");
416 return; 424 return;
417 } 425 }
418 426
419 if (bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap, sc->sc_vramaddr, 427 if (bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap, sc->sc_vramaddr,
420 sc->sc_vramsize, NULL, BUS_DMA_NOWAIT) != 0) { 428 sc->sc_vramsize, NULL, BUS_DMA_NOWAIT) != 0) {
421 aprint_error_dev(sc->sc_dev, "failed to load DMA map\n"); 429 aprint_error_dev(sc->sc_dev, "failed to load DMA map\n");
422 return; 430 return;
423 } 431 }
424 432
425 memset((void *)sc->sc_vramaddr, 0, sc->sc_vramsize); 433 memset((void *)sc->sc_vramaddr, 0, sc->sc_vramsize);
426 434
427 sc->sc_palette[0] = 0x4000; 435 sc->sc_palette[0] = 0x4000;
428#if 0 /* XXX */ 436#if 0 /* XXX */
429 if (sc->sc_panel->bpp == 8) { 437 if (sc->sc_panel->bpp == 8) {
430 j = 0; 438 j = 0;
431 for (i = 0; i < 256; i++) { 439 for (i = 0; i < 256; i++) {
432 sc->sc_cmap_red[i] = rasops_cmap[j]; 440 sc->sc_cmap_red[i] = rasops_cmap[j];
433 sc->sc_cmap_green[i] = rasops_cmap[j + 1]; 441 sc->sc_cmap_green[i] = rasops_cmap[j + 1];
434 sc->sc_cmap_blue[i] = rasops_cmap[j + 2]; 442 sc->sc_cmap_blue[i] = rasops_cmap[j + 2];
435 j += 3; 443 j += 3;
436 } 444 }
437 } else { 445 } else {
438 for (i = 0; i < 256; i++) { 446 for (i = 0; i < 256; i++) {
439 sc->sc_cmap_red[i] = i; 447 sc->sc_cmap_red[i] = i;
440 sc->sc_cmap_green[i] = i; 448 sc->sc_cmap_green[i] = i;
441 sc->sc_cmap_blue[i] = i; 449 sc->sc_cmap_blue[i] = i;
442 } 450 }
443 } 451 }
444 tifb_restore_palette(sc); 452 tifb_restore_palette(sc);
445#endif 453#endif
446 454
447#ifdef TI_AM335X 455#ifdef TI_AM335X
448 /* configure output pins */ 456 /* configure output pins */
449 for (i = 0; i < ((sc->sc_panel->bpp == 16) ? 16 : 24); i++) { 457 for (i = 0; i < ((sc->sc_panel->bpp == 16) ? 16 : 24); i++) {
450 if (sitara_cm_padconf_get(tifb_padconf_data[i].padname, 458 if (sitara_cm_padconf_get(tifb_padconf_data[i].padname,
451 &mode, &state) == 0) { 459 &mode, &state) == 0) {
452 aprint_debug(": %s mode %s state %d ", 460 aprint_debug(": %s mode %s state %d ",
453 tifb_padconf_data[i].padname, mode, state); 461 tifb_padconf_data[i].padname, mode, state);
454 } 462 }
455 if (sitara_cm_padconf_set(tifb_padconf_data[i].padname, 463 if (sitara_cm_padconf_set(tifb_padconf_data[i].padname,
456 tifb_padconf_data[i].padmode, 0) != 0) { 464 tifb_padconf_data[i].padmode, 0) != 0) {
457 aprint_error(": can't switch %s pad from %s to %s\n", tifb_padconf_data[i].padname, mode, tifb_padconf_data[i].padmode); 465 aprint_error(": can't switch %s pad from %s to %s\n", tifb_padconf_data[i].padname, mode, tifb_padconf_data[i].padmode);
458 return; 466 return;
459 } 467 }
460 } 468 }
461 for (i = 0; i < __arraycount(tifb_padconf_ctrl); i++) { 469 for (i = 0; i < __arraycount(tifb_padconf_ctrl); i++) {
462 if (sitara_cm_padconf_get(tifb_padconf_ctrl[i].padname, 470 if (sitara_cm_padconf_get(tifb_padconf_ctrl[i].padname,
463 &mode, &state) == 0) { 471 &mode, &state) == 0) {
464 aprint_debug(": %s mode %s state %d ", 472 aprint_debug(": %s mode %s state %d ",
465 tifb_padconf_ctrl[i].padname, mode, state); 473 tifb_padconf_ctrl[i].padname, mode, state);
466 } 474 }
467 if (sitara_cm_padconf_set(tifb_padconf_ctrl[i].padname, 475 if (sitara_cm_padconf_set(tifb_padconf_ctrl[i].padname,
468 tifb_padconf_ctrl[i].padmode, 0) != 0) { 476 tifb_padconf_ctrl[i].padmode, 0) != 0) {
469 aprint_error(": can't switch %s pad from %s to %s\n", tifb_padconf_ctrl[i].padname, mode, tifb_padconf_ctrl[i].padmode); 477 aprint_error(": can't switch %s pad from %s to %s\n", tifb_padconf_ctrl[i].padname, mode, tifb_padconf_ctrl[i].padmode);
470 return; 478 return;
471 } 479 }
472 } 480 }
473 am335x_clk_lcdc_activate(); 481 am335x_clk_lcdc_activate();
474 /* get reference clk freq */ 482 /* get reference clk freq */
475 ret = am335x_clk_get_arm_disp_freq(&ref_freq); 483 ret = am335x_clk_get_arm_disp_freq(&ref_freq);
476 if (ret != 0) { 484 if (ret != 0) {
477 aprint_error_dev(self, "display clock not enabled\n"); 485 aprint_error_dev(self, "display clock not enabled\n");
478 return; 486 return;
479 } 487 }
480#endif 488#endif
481 aprint_normal(": TI LCD controller\n"); 489 aprint_normal(": TI LCD controller\n");
482 aprint_debug_dev(self, ": fb@%p, palette@%p\n", sc->sc_fbaddr, 490 aprint_debug_dev(self, ": fb@%p, palette@%p\n", sc->sc_fbaddr,
483 sc->sc_palette); 491 sc->sc_palette);
484 /* Only raster mode is supported */ 492 /* Only raster mode is supported */
485 reg = CTRL_RASTER_MODE; 493 reg = CTRL_RASTER_MODE;
486 div = am335x_lcd_calc_divisor(ref_freq, sc->sc_panel->panel_pxl_clk); 494 div = am335x_lcd_calc_divisor(ref_freq, sc->sc_panel->panel_pxl_clk);
487 reg |= (div << CTRL_DIV_SHIFT); 495 reg |= (div << CTRL_DIV_SHIFT);
488 TIFB_WRITE(sc, LCD_CTRL, reg); 496 TIFB_WRITE(sc, LCD_CTRL, reg);
489 aprint_debug_dev(self, ": ref_freq %d div %d\n", ref_freq, div); 497 aprint_debug_dev(self, ": ref_freq %d div %d\n", ref_freq, div);
490 498
491 /* Set timing */ 499 /* Set timing */
492 timing0 = timing1 = timing2 = 0; 500 timing0 = timing1 = timing2 = 0;
493 501
494 /* Horizontal back porch */ 502 /* Horizontal back porch */
495 timing0 |= (sc->sc_panel->panel_hbp & 0xff) << RASTER_TIMING_0_HBP_SHIFT; 503 timing0 |= (sc->sc_panel->panel_hbp & 0xff) << RASTER_TIMING_0_HBP_SHIFT;
496 timing2 |= ((sc->sc_panel->panel_hbp >> 8) & 3) << RASTER_TIMING_2_HBPHI_SHIFT; 504 timing2 |= ((sc->sc_panel->panel_hbp >> 8) & 3) << RASTER_TIMING_2_HBPHI_SHIFT;
497 /* Horizontal front porch */ 505 /* Horizontal front porch */
498 timing0 |= (sc->sc_panel->panel_hfp & 0xff) << RASTER_TIMING_0_HFP_SHIFT; 506 timing0 |= (sc->sc_panel->panel_hfp & 0xff) << RASTER_TIMING_0_HFP_SHIFT;
499 timing2 |= ((sc->sc_panel->panel_hfp >> 8) & 3) << RASTER_TIMING_2_HFPHI_SHIFT; 507 timing2 |= ((sc->sc_panel->panel_hfp >> 8) & 3) << RASTER_TIMING_2_HFPHI_SHIFT;
500 /* Horizontal sync width */  508 /* Horizontal sync width */
501 timing0 |= (sc->sc_panel->panel_hsw & 0x3f) << RASTER_TIMING_0_HSW_SHIFT; 509 timing0 |= (sc->sc_panel->panel_hsw & 0x3f) << RASTER_TIMING_0_HSW_SHIFT;
502 timing2 |= ((sc->sc_panel->panel_hsw >> 6) & 0xf) << RASTER_TIMING_2_HSWHI_SHIFT 510 timing2 |= ((sc->sc_panel->panel_hsw >> 6) & 0xf) << RASTER_TIMING_2_HSWHI_SHIFT
503; 511;
504 512
505 /* Vertical back porch, front porch, sync width */ 513 /* Vertical back porch, front porch, sync width */
506 timing1 |= (sc->sc_panel->panel_vbp & 0xff) << RASTER_TIMING_1_VBP_SHIFT; 514 timing1 |= (sc->sc_panel->panel_vbp & 0xff) << RASTER_TIMING_1_VBP_SHIFT;
507 timing1 |= (sc->sc_panel->panel_vfp & 0xff) << RASTER_TIMING_1_VFP_SHIFT; 515 timing1 |= (sc->sc_panel->panel_vfp & 0xff) << RASTER_TIMING_1_VFP_SHIFT;
508 timing1 |= (sc->sc_panel->panel_vsw & 0x3f) << RASTER_TIMING_1_VSW_SHIFT; 516 timing1 |= (sc->sc_panel->panel_vsw & 0x3f) << RASTER_TIMING_1_VSW_SHIFT;
509 /* Pixels per line */ 517 /* Pixels per line */
510 timing0 |= (((sc->sc_panel->panel_width - 1) >> 10) & 1) 518 timing0 |= (((sc->sc_panel->panel_width - 1) >> 10) & 1)
511 << RASTER_TIMING_0_PPLMSB_SHIFT; 519 << RASTER_TIMING_0_PPLMSB_SHIFT;
512 timing0 |= (((sc->sc_panel->panel_width - 1) >> 4) & 0x3f) 520 timing0 |= (((sc->sc_panel->panel_width - 1) >> 4) & 0x3f)
513 << RASTER_TIMING_0_PPLLSB_SHIFT; 521 << RASTER_TIMING_0_PPLLSB_SHIFT;
514 522
515 /* Lines per panel */ 523 /* Lines per panel */
516 timing1 |= ((sc->sc_panel->panel_height - 1) & 0x3ff) 524 timing1 |= ((sc->sc_panel->panel_height - 1) & 0x3ff)
517 << RASTER_TIMING_1_LPP_SHIFT; 525 << RASTER_TIMING_1_LPP_SHIFT;
518 timing2 |= (((sc->sc_panel->panel_height - 1) >> 10 ) & 1) 526 timing2 |= (((sc->sc_panel->panel_height - 1) >> 10 ) & 1)
519 << RASTER_TIMING_2_LPP_B10_SHIFT; 527 << RASTER_TIMING_2_LPP_B10_SHIFT;
520 528
521 /* clock signal settings */  529 /* clock signal settings */
522 if (sc->sc_panel->sync_ctrl) 530 if (sc->sc_panel->sync_ctrl)
523 timing2 |= RASTER_TIMING_2_PHSVS; 531 timing2 |= RASTER_TIMING_2_PHSVS;
524 if (sc->sc_panel->sync_edge) 532 if (sc->sc_panel->sync_edge)
525 timing2 |= RASTER_TIMING_2_PHSVS_RISE; 533 timing2 |= RASTER_TIMING_2_PHSVS_RISE;
526 else 534 else
527 timing2 |= RASTER_TIMING_2_PHSVS_FALL; 535 timing2 |= RASTER_TIMING_2_PHSVS_FALL;
528 if (sc->sc_panel->invert_line_clock)  536 if (sc->sc_panel->invert_line_clock)
529 timing2 |= RASTER_TIMING_2_IHS; 537 timing2 |= RASTER_TIMING_2_IHS;
530 if (sc->sc_panel->invert_frm_clock)  538 if (sc->sc_panel->invert_frm_clock)
531 timing2 |= RASTER_TIMING_2_IVS; 539 timing2 |= RASTER_TIMING_2_IVS;
532 if (sc->sc_panel->panel_invert_pxl_clk) 540 if (sc->sc_panel->panel_invert_pxl_clk)
533 timing2 |= RASTER_TIMING_2_IPC; 541 timing2 |= RASTER_TIMING_2_IPC;
534 542
535 /* AC bias */ 543 /* AC bias */
536 timing2 |= (sc->sc_panel->ac_bias << RASTER_TIMING_2_ACB_SHIFT); 544 timing2 |= (sc->sc_panel->ac_bias << RASTER_TIMING_2_ACB_SHIFT);
537 timing2 |= (sc->sc_panel->ac_bias_intrpt << RASTER_TIMING_2_ACBI_SHIFT); 545 timing2 |= (sc->sc_panel->ac_bias_intrpt << RASTER_TIMING_2_ACBI_SHIFT);
538 546
539 TIFB_WRITE(sc, LCD_RASTER_TIMING_0, timing0); 547 TIFB_WRITE(sc, LCD_RASTER_TIMING_0, timing0);
540 TIFB_WRITE(sc, LCD_RASTER_TIMING_1, timing1); 548 TIFB_WRITE(sc, LCD_RASTER_TIMING_1, timing1);
541 TIFB_WRITE(sc, LCD_RASTER_TIMING_2, timing2); 549 TIFB_WRITE(sc, LCD_RASTER_TIMING_2, timing2);
542 aprint_debug_dev(self, ": timings 0x%x 0x%x 0x%x\n", 550 aprint_debug_dev(self, ": timings 0x%x 0x%x 0x%x\n",
543 timing0, timing1, timing2); 551 timing0, timing1, timing2);
544 552
545 /* DMA settings */ 553 /* DMA settings */
546 reg = LCDDMA_CTRL_FB0_FB1;  554 reg = 0;
547 /* Find power of 2 for current burst size */ 555 /* Find power of 2 for current burst size */
548 switch (sc->sc_panel->dma_burst_sz) {  556 switch (sc->sc_panel->dma_burst_sz) {
549 case 1: 557 case 1:
550 burst_log = 0; 558 burst_log = 0;
551 break; 559 break;
552 case 2: 560 case 2:
553 burst_log = 1; 561 burst_log = 1;
554 break; 562 break;
555 case 4: 563 case 4:
556 burst_log = 2; 564 burst_log = 2;
557 break; 565 break;
558 case 8: 566 case 8:
559 burst_log = 3; 567 burst_log = 3;
560 break; 568 break;
561 case 16: 569 case 16:
562 default: 570 default:
563 burst_log = 4; 571 burst_log = 4;
564 break; 572 break;
565 } 573 }
566 reg |= (burst_log << LCDDMA_CTRL_BURST_SIZE_SHIFT); 574 reg |= (burst_log << LCDDMA_CTRL_BURST_SIZE_SHIFT);
567 /* XXX: FIFO TH */ 575 /* XXX: FIFO TH */
568 reg |= (0 << LCDDMA_CTRL_TH_FIFO_RDY_SHIFT); 576 reg |= (0 << LCDDMA_CTRL_TH_FIFO_RDY_SHIFT);
569 TIFB_WRITE(sc, LCD_LCDDMA_CTRL, reg); 577 TIFB_WRITE(sc, LCD_LCDDMA_CTRL, reg);
570 aprint_debug_dev(self, ": LCD_LCDDMA_CTRL 0x%x\n", reg); 578 aprint_debug_dev(self, ": LCD_LCDDMA_CTRL 0x%x\n", reg);
571 579
572 TIFB_WRITE(sc, LCD_LCDDMA_FB0_BASE, sc->sc_dmamem->ds_addr); 580 TIFB_WRITE(sc, LCD_LCDDMA_FB0_BASE, sc->sc_dmamem->ds_addr);
573 TIFB_WRITE(sc, LCD_LCDDMA_FB0_CEILING, 581 TIFB_WRITE(sc, LCD_LCDDMA_FB0_CEILING,
574 sc->sc_dmamem->ds_addr + sc->sc_vramsize - 1); 582 sc->sc_dmamem->ds_addr + sc->sc_vramsize - 1);
575 TIFB_WRITE(sc, LCD_LCDDMA_FB1_BASE, sc->sc_dmamem->ds_addr); 583 TIFB_WRITE(sc, LCD_LCDDMA_FB1_BASE, sc->sc_dmamem->ds_addr);
576 TIFB_WRITE(sc, LCD_LCDDMA_FB1_CEILING, 584 TIFB_WRITE(sc, LCD_LCDDMA_FB1_CEILING,
577 sc->sc_dmamem->ds_addr + sc->sc_vramsize - 1); 585 sc->sc_dmamem->ds_addr + sc->sc_vramsize - 1);
578 aprint_debug_dev(self, ": LCD_LCDDMA 0x%x 0x%x\n", 586 aprint_debug_dev(self, ": LCD_LCDDMA 0x%x 0x%x\n",
579 (u_int)sc->sc_dmamem->ds_addr, (u_int)(sc->sc_dmamem->ds_addr + sc->sc_vramsize - 1)); 587 (u_int)sc->sc_dmamem->ds_addr, (u_int)(sc->sc_dmamem->ds_addr + sc->sc_vramsize - 1));
580 588
581 /* Enable LCD */ 589 /* Enable LCD */
582 reg = RASTER_CTRL_LCDTFT;  590 reg = RASTER_CTRL_LCDTFT;
583 reg |= (sc->sc_panel->fdd << RASTER_CTRL_REQDLY_SHIFT); 591 reg |= (sc->sc_panel->fdd << RASTER_CTRL_REQDLY_SHIFT);
584 reg |= (PALETTE_DATA_ONLY << RASTER_CTRL_PALMODE_SHIFT); 592 reg |= (PALETTE_DATA_ONLY << RASTER_CTRL_PALMODE_SHIFT);
585 if (sc->sc_panel->bpp >= 24) 593 if (sc->sc_panel->bpp >= 24)
586 reg |= RASTER_CTRL_TFT24; 594 reg |= RASTER_CTRL_TFT24;
587 if (sc->sc_panel->bpp == 32) 595 if (sc->sc_panel->bpp == 32)
588 reg |= RASTER_CTRL_TFT24_UNPACKED; 596 reg |= RASTER_CTRL_TFT24_UNPACKED;
589 TIFB_WRITE(sc, LCD_RASTER_CTRL, reg); 597 TIFB_WRITE(sc, LCD_RASTER_CTRL, reg);
590 aprint_debug_dev(self, ": LCD_RASTER_CTRL 0x%x\n", reg); 598 aprint_debug_dev(self, ": LCD_RASTER_CTRL 0x%x\n", reg);
591 599
592 TIFB_WRITE(sc, LCD_CLKC_ENABLE, 600 TIFB_WRITE(sc, LCD_CLKC_ENABLE,
593 CLKC_ENABLE_DMA | CLKC_ENABLE_LDID | CLKC_ENABLE_CORE);  601 CLKC_ENABLE_DMA | CLKC_ENABLE_LDID | CLKC_ENABLE_CORE);
594 602
595 TIFB_WRITE(sc, LCD_CLKC_RESET, CLKC_RESET_MAIN); 603 TIFB_WRITE(sc, LCD_CLKC_RESET, CLKC_RESET_MAIN);
596 DELAY(100); 604 DELAY(100);
597 TIFB_WRITE(sc, LCD_CLKC_RESET, 0); 605 TIFB_WRITE(sc, LCD_CLKC_RESET, 0);
598 aprint_debug_dev(self, ": LCD_CLKC_ENABLE 0x%x\n", TIFB_READ(sc, LCD_CLKC_ENABLE)); 606 aprint_debug_dev(self, ": LCD_CLKC_ENABLE 0x%x\n", TIFB_READ(sc, LCD_CLKC_ENABLE));
599 607
600 reg = IRQ_EOF1 | IRQ_EOF0 | IRQ_FUF | IRQ_PL | 608 reg = IRQ_FUF | IRQ_PL | IRQ_ACB | IRQ_SYNC_LOST;
601 IRQ_ACB | IRQ_SYNC_LOST | IRQ_RASTER_DONE | 
602 IRQ_FRAME_DONE; 
603 TIFB_WRITE(sc, LCD_IRQENABLE_SET, reg); 609 TIFB_WRITE(sc, LCD_IRQENABLE_SET, reg);
604 610
605 reg = TIFB_READ(sc, LCD_RASTER_CTRL); 611 reg = TIFB_READ(sc, LCD_RASTER_CTRL);
606 reg |= RASTER_CTRL_LCDEN;  612 reg |= RASTER_CTRL_LCDEN;
607 TIFB_WRITE(sc, LCD_RASTER_CTRL, reg); 613 TIFB_WRITE(sc, LCD_RASTER_CTRL, reg);
608 aprint_debug_dev(self, ": LCD_RASTER_CTRL 0x%x\n", TIFB_READ(sc, LCD_RASTER_CTRL)); 614 aprint_debug_dev(self, ": LCD_RASTER_CTRL 0x%x\n", TIFB_READ(sc, LCD_RASTER_CTRL));
609 615
610 TIFB_WRITE(sc, LCD_SYSCONFIG,  616 TIFB_WRITE(sc, LCD_SYSCONFIG,
611 SYSCONFIG_STANDBY_SMART | SYSCONFIG_IDLE_SMART); 617 SYSCONFIG_STANDBY_SMART | SYSCONFIG_IDLE_SMART);
612 aprint_debug_dev(self, ": LCD_SYSCONFIG 0x%x\n", TIFB_READ(sc, LCD_SYSCONFIG)); 618 aprint_debug_dev(self, ": LCD_SYSCONFIG 0x%x\n", TIFB_READ(sc, LCD_SYSCONFIG));
613 619
614 /* attach wscons */ 620 /* attach wscons */
615 sc->sc_defaultscreen_descr = (struct wsscreen_descr){ 621 sc->sc_defaultscreen_descr = (struct wsscreen_descr){
616 "default", 622 "default",
617 0, 0, 623 0, 0,
618 NULL, 624 NULL,
619 8, 16, 625 8, 16,
620 WSSCREEN_WSCOLORS | WSSCREEN_HILIT, 626 WSSCREEN_WSCOLORS | WSSCREEN_HILIT,
621 NULL 627 NULL
622 }; 628 };
623 sc->sc_screens[0] = &sc->sc_defaultscreen_descr; 629 sc->sc_screens[0] = &sc->sc_defaultscreen_descr;
624 sc->sc_screenlist = (struct wsscreen_list){1, sc->sc_screens}; 630 sc->sc_screenlist = (struct wsscreen_list){1, sc->sc_screens};
625 sc->sc_mode = WSDISPLAYIO_MODE_EMUL; 631 sc->sc_mode = WSDISPLAYIO_MODE_EMUL;
626 sc->sc_locked = 0; 632 sc->sc_locked = 0;
627 633
628 vcons_init(&sc->vd, sc, &sc->sc_defaultscreen_descr, 634 vcons_init(&sc->vd, sc, &sc->sc_defaultscreen_descr,
629 &tifb_accessops); 635 &tifb_accessops);
630 sc->vd.init_screen = tifb_init_screen; 636 sc->vd.init_screen = tifb_init_screen;
631 637
632 /* init engine here */ 638 /* init engine here */
633 639
634 ri = &sc->sc_console_screen.scr_ri; 640 ri = &sc->sc_console_screen.scr_ri;
635 641
636 vcons_init_screen(&sc->vd, &sc->sc_console_screen, 1, &defattr); 642 vcons_init_screen(&sc->vd, &sc->sc_console_screen, 1, &defattr);
637 sc->sc_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC; 643 sc->sc_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC;
638 sc->sc_defaultscreen_descr.textops = &ri->ri_ops; 644 sc->sc_defaultscreen_descr.textops = &ri->ri_ops;
639 sc->sc_defaultscreen_descr.capabilities = ri->ri_caps; 645 sc->sc_defaultscreen_descr.capabilities = ri->ri_caps;
640 sc->sc_defaultscreen_descr.nrows = ri->ri_rows; 646 sc->sc_defaultscreen_descr.nrows = ri->ri_rows;
641 sc->sc_defaultscreen_descr.ncols = ri->ri_cols; 647 sc->sc_defaultscreen_descr.ncols = ri->ri_cols;
642 if (is_console) { 648 if (is_console) {
643 wsdisplay_cnattach(&sc->sc_defaultscreen_descr, ri, 0, 0, 649 wsdisplay_cnattach(&sc->sc_defaultscreen_descr, ri, 0, 0,
644 defattr); 650 defattr);
645 vcons_replay_msgbuf(&sc->sc_console_screen); 651 vcons_replay_msgbuf(&sc->sc_console_screen);
646 } 652 }
647 653
648 aa.console = is_console; 654 aa.console = is_console;
649 aa.scrdata = &sc->sc_screenlist; 655 aa.scrdata = &sc->sc_screenlist;
650 aa.accessops = &tifb_accessops; 656 aa.accessops = &tifb_accessops;
651 aa.accesscookie = &sc->vd; 657 aa.accesscookie = &sc->vd;
652 658
653 config_found(sc->sc_dev, &aa, wsemuldisplaydevprint); 659 config_found(sc->sc_dev, &aa, wsemuldisplaydevprint);
654} 660}
655 661
 662uint32_t tifb_intr_unh = 0;
 663
656static int 664static int
657tifb_intr(void *v) 665tifb_intr(void *v)
658{ 666{
659 struct tifb_softc *sc = v; 667 struct tifb_softc *sc = v;
660 uint32_t reg; 668 uint32_t reg;
661 669
662 reg = TIFB_READ(sc, LCD_IRQSTATUS); 670 reg = TIFB_READ(sc, LCD_IRQSTATUS);
663 TIFB_WRITE(sc, LCD_IRQSTATUS, reg); 671 TIFB_WRITE(sc, LCD_IRQSTATUS, reg);
664 672
665 if (reg & IRQ_SYNC_LOST) { 673 if (reg & IRQ_SYNC_LOST) {
666 ev_sync_lost.ev_count ++; 674 ev_sync_lost.ev_count ++;
667 reg = TIFB_READ(sc, LCD_RASTER_CTRL); 675 reg = TIFB_READ(sc, LCD_RASTER_CTRL);
668 reg &= ~RASTER_CTRL_LCDEN; 676 reg &= ~RASTER_CTRL_LCDEN;
669 TIFB_WRITE(sc, LCD_RASTER_CTRL, reg); 677 TIFB_WRITE(sc, LCD_RASTER_CTRL, reg);
670 678
671 reg = TIFB_READ(sc, LCD_RASTER_CTRL); 679 reg = TIFB_READ(sc, LCD_RASTER_CTRL);
672 reg |= RASTER_CTRL_LCDEN; 680 reg |= RASTER_CTRL_LCDEN;
673 TIFB_WRITE(sc, LCD_RASTER_CTRL, reg); 681 TIFB_WRITE(sc, LCD_RASTER_CTRL, reg);
674 return 0; 682 return 0;
675 } 683 }
676 684
677 if (reg & IRQ_PL) { 685 if (reg & IRQ_PL) {
678 ev_palette.ev_count ++; 686 ev_palette.ev_count ++;
679 reg = TIFB_READ(sc, LCD_RASTER_CTRL); 687 reg = TIFB_READ(sc, LCD_RASTER_CTRL);
680 reg &= ~RASTER_CTRL_LCDEN; 688 reg &= ~RASTER_CTRL_LCDEN;
681 TIFB_WRITE(sc, LCD_RASTER_CTRL, reg); 689 TIFB_WRITE(sc, LCD_RASTER_CTRL, reg);
682 690
683 reg = TIFB_READ(sc, LCD_RASTER_CTRL); 691 reg = TIFB_READ(sc, LCD_RASTER_CTRL);
684 reg |= RASTER_CTRL_LCDEN; 692 reg |= RASTER_CTRL_LCDEN;
685 TIFB_WRITE(sc, LCD_RASTER_CTRL, reg); 693 TIFB_WRITE(sc, LCD_RASTER_CTRL, reg);
686 return 0; 694 return 0;
687 } 695 }
688 696
689 if (reg & (IRQ_FRAME_DONE|IRQ_EOF0|IRQ_EOF1)) { 
690 /* flush the write-back cache */ 
691 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 
692 0, sc->sc_vramsize, BUS_DMASYNC_PREWRITE); 
693 } 
694 
695 if (reg & IRQ_FRAME_DONE) { 697 if (reg & IRQ_FRAME_DONE) {
696 ev_frame_done.ev_count ++; 698 ev_frame_done.ev_count ++;
697 reg &= ~IRQ_FRAME_DONE; 699 reg &= ~IRQ_FRAME_DONE;
698 } 700 }
699 701
700 if (reg & IRQ_EOF0) { 702 if (reg & IRQ_EOF0) {
701 ev_eof0.ev_count ++; 703 ev_eof0.ev_count ++;
702 TIFB_WRITE(sc, LCD_LCDDMA_FB0_BASE, sc->sc_dmamem->ds_addr); 704 TIFB_WRITE(sc, LCD_LCDDMA_FB0_BASE, sc->sc_dmamem->ds_addr);
703 TIFB_WRITE(sc, LCD_LCDDMA_FB0_CEILING, 705 TIFB_WRITE(sc, LCD_LCDDMA_FB0_CEILING,
704 sc->sc_dmamem->ds_addr + sc->sc_vramsize - 1); 706 sc->sc_dmamem->ds_addr + sc->sc_vramsize - 1);
705 reg &= ~IRQ_EOF0; 707 reg &= ~IRQ_EOF0;
706 } 708 }
707 709
708 if (reg & IRQ_EOF1) { 710 if (reg & IRQ_EOF1) {
709 ev_eof1.ev_count ++; 711 ev_eof1.ev_count ++;
710 TIFB_WRITE(sc, LCD_LCDDMA_FB1_BASE, sc->sc_dmamem->ds_addr); 712 TIFB_WRITE(sc, LCD_LCDDMA_FB1_BASE, sc->sc_dmamem->ds_addr);
711 TIFB_WRITE(sc, LCD_LCDDMA_FB1_CEILING, 713 TIFB_WRITE(sc, LCD_LCDDMA_FB1_CEILING,
712 sc->sc_dmamem->ds_addr + sc->sc_vramsize - 1); 714 sc->sc_dmamem->ds_addr + sc->sc_vramsize - 1);
713 reg &= ~IRQ_EOF1;  715 reg &= ~IRQ_EOF1;
714 } 716 }
715 717
716 if (reg & IRQ_FUF) { 718 if (reg & IRQ_FUF) {
717 ev_fifo_underflow.ev_count ++; 719 ev_fifo_underflow.ev_count ++;
718 /* TODO: Handle FUF */ 720 /* TODO: Handle FUF */
719 reg =~ IRQ_FUF; 721 reg =~ IRQ_FUF;
720 } 722 }
721 723
722 if (reg & IRQ_ACB) { 724 if (reg & IRQ_ACB) {
723 ev_ac_bias.ev_count ++; 725 ev_ac_bias.ev_count ++;
724 /* TODO: Handle ACB */ 726 /* TODO: Handle ACB */
725 reg =~ IRQ_ACB; 727 reg =~ IRQ_ACB;
726 } 728 }
727 if (reg) 729 if (reg) {
728 ev_others.ev_count ++; 730 ev_others.ev_count ++;
 731 tifb_intr_unh = reg;
 732 }
729 return 0; 733 return 0;
730} 734}
731 735
732static int 736static int
733tifb_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, 737tifb_ioctl(void *v, void *vs, u_long cmd, void *data, int flag,
734 struct lwp *l) 738 struct lwp *l)
735{ 739{
736 struct vcons_data *vd = v; 740 struct vcons_data *vd = v;
737 struct tifb_softc *sc = vd->cookie; 741 struct tifb_softc *sc = vd->cookie;
738 struct wsdisplay_fbinfo *wdf; 742 struct wsdisplay_fbinfo *wdf;
739 struct vcons_screen *ms = vd->active; 743 struct vcons_screen *ms = vd->active;
740 744
741 switch (cmd) { 745 switch (cmd) {
742 746
743 case WSDISPLAYIO_GTYPE: 747 case WSDISPLAYIO_GTYPE:
744 *(u_int *)data = WSDISPLAY_TYPE_GENFB; 748 *(u_int *)data = WSDISPLAY_TYPE_GENFB;
745 return 0; 749 return 0;
746 750
747 case WSDISPLAYIO_GET_BUSID: 751 case WSDISPLAYIO_GET_BUSID:
748 { 752 {
749 struct wsdisplayio_bus_id *busid; 753 struct wsdisplayio_bus_id *busid;
750 754
751 busid = data; 755 busid = data;
752 busid->bus_type = WSDISPLAYIO_BUS_SOC; 756 busid->bus_type = WSDISPLAYIO_BUS_SOC;
753 return 0; 757 return 0;
754 } 758 }
755 759
756 case WSDISPLAYIO_GINFO: 760 case WSDISPLAYIO_GINFO:
757 if (ms == NULL) 761 if (ms == NULL)
758 return ENODEV; 762 return ENODEV;
759 wdf = (void *)data; 763 wdf = (void *)data;
760 wdf->height = ms->scr_ri.ri_height; 764 wdf->height = ms->scr_ri.ri_height;
761 wdf->width = ms->scr_ri.ri_width; 765 wdf->width = ms->scr_ri.ri_width;
762 wdf->depth = ms->scr_ri.ri_depth; 766 wdf->depth = ms->scr_ri.ri_depth;
763 wdf->cmsize = 256; 767 wdf->cmsize = 256;
764 return 0; 768 return 0;
765 769
766 case WSDISPLAYIO_GETCMAP: 770 case WSDISPLAYIO_GETCMAP:
767 return tifb_getcmap(sc, 771 return tifb_getcmap(sc,
768 (struct wsdisplay_cmap *)data); 772 (struct wsdisplay_cmap *)data);
769 773
770 case WSDISPLAYIO_PUTCMAP: 774 case WSDISPLAYIO_PUTCMAP:
771 return tifb_putcmap(sc, 775 return tifb_putcmap(sc,
772 (struct wsdisplay_cmap *)data); 776 (struct wsdisplay_cmap *)data);
773 777
774 case WSDISPLAYIO_LINEBYTES: 778 case WSDISPLAYIO_LINEBYTES:
775 *(u_int *)data = sc->sc_stride; 779 *(u_int *)data = sc->sc_stride;
776 return 0; 780 return 0;
777 781
778 case WSDISPLAYIO_SMODE: 782 case WSDISPLAYIO_SMODE:
779 { 783 {
780 int new_mode = *(int*)data; 784 int new_mode = *(int*)data;
781 785
782 if (new_mode != sc->sc_mode) { 786 if (new_mode != sc->sc_mode) {
783 sc->sc_mode = new_mode; 787 sc->sc_mode = new_mode;
784#if 0 788#if 0
785 if (new_mode == WSDISPLAYIO_MODE_EMUL) { 789 if (new_mode == WSDISPLAYIO_MODE_EMUL) {
786 tifb_set_depth(sc, 16); 790 tifb_set_depth(sc, 16);
787 vcons_redraw_screen(ms); 791 vcons_redraw_screen(ms);
788 } else { 792 } else {
789 tifb_set_depth(sc, 32); 793 tifb_set_depth(sc, 32);
790 } 794 }
791#endif 795#endif
792 } 796 }
793 } 797 }
794 return 0; 798 return 0;
795 799
796 case WSDISPLAYIO_GET_FBINFO: 800 case WSDISPLAYIO_GET_FBINFO:
797 { 801 {
798 struct wsdisplayio_fbinfo *fbi = data; 802 struct wsdisplayio_fbinfo *fbi = data;
799 int ret; 803 int ret;
800  804
801 ret = wsdisplayio_get_fbinfo(&ms->scr_ri, fbi); 805 ret = wsdisplayio_get_fbinfo(&ms->scr_ri, fbi);
802 fbi->fbi_flags |= WSFB_VRAM_IS_RAM; 806 fbi->fbi_flags |= WSFB_VRAM_IS_RAM;
803 fbi->fbi_fboffset = sc->sc_palettesize; 807 fbi->fbi_fboffset = sc->sc_palettesize;
804 return ret; 808 return ret;
805 } 809 }
806 810
807 case WSDISPLAYIO_GVIDEO: 811 case WSDISPLAYIO_GVIDEO:
808 { 812 {
809 int *on = data; 813 int *on = data;
810 *on = 1; /* XXX sc->sc_video_is_on; */ 814 *on = 1; /* XXX sc->sc_video_is_on; */
811 } 815 }
812 return 0; 816 return 0;
813 817
814 case WSDISPLAYIO_SVIDEO: 818 case WSDISPLAYIO_SVIDEO:
815 { 819 {
816 int *on = data; 820 int *on = data;
817 tifb_set_video(sc, *on); 821 tifb_set_video(sc, *on);
818 } 822 }
819 return 0; 823 return 0;
820 824
821 } 825 }
822 return EPASSTHROUGH; 826 return EPASSTHROUGH;
823} 827}
824 828
825static paddr_t 829static paddr_t
826tifb_mmap(void *v, void *vs, off_t offset, int prot) 830tifb_mmap(void *v, void *vs, off_t offset, int prot)
827{ 831{
828 paddr_t pa = -1; 832 paddr_t pa = -1;
829 struct vcons_data *vd = v; 833 struct vcons_data *vd = v;
830 struct tifb_softc *sc = vd->cookie; 834 struct tifb_softc *sc = vd->cookie;
831 835
832 /* 'regular' framebuffer mmap()ing */ 836 /* 'regular' framebuffer mmap()ing */
833 if (offset < sc->sc_stride * sc->sc_panel->panel_height) { 837 if (offset < sc->sc_stride * sc->sc_panel->panel_height) {
834 pa = bus_dmamem_mmap(sc->sc_dmat, sc->sc_dmamem, 1, 838 pa = bus_dmamem_mmap(sc->sc_dmat, sc->sc_dmamem, 1,
835 offset, prot, BUS_DMA_PREFETCHABLE); 839 offset, prot, BUS_DMA_PREFETCHABLE);
836 return pa; 840 return pa;
837 } 841 }
838 return pa; 842 return pa;
839} 843}
840 844
841static void 845static void
842tifb_init_screen(void *cookie, struct vcons_screen *scr, 846tifb_init_screen(void *cookie, struct vcons_screen *scr,
843 int existing, long *defattr) 847 int existing, long *defattr)
844{ 848{
845 struct tifb_softc *sc = cookie; 849 struct tifb_softc *sc = cookie;
846 struct rasops_info *ri = &scr->scr_ri; 850 struct rasops_info *ri = &scr->scr_ri;
847 851
848 ri->ri_depth = sc->sc_panel->bpp; 852 ri->ri_depth = sc->sc_panel->bpp;
849 ri->ri_width = sc->sc_panel->panel_width; 853 ri->ri_width = sc->sc_panel->panel_width;
850 ri->ri_height = sc->sc_panel->panel_height; 854 ri->ri_height = sc->sc_panel->panel_height;
851 ri->ri_stride = sc->sc_stride; 855 ri->ri_stride = sc->sc_stride;
852 ri->ri_flg = RI_CENTER | RI_FULLCLEAR; 856 ri->ri_flg = RI_CENTER | RI_FULLCLEAR;
853 857
854 ri->ri_bits = (char *)sc->sc_fbaddr; 858 if (sc->sc_shadowfb != NULL) {
 859 ri->ri_bits = (char *)sc->sc_shadowfb;
 860 ri->ri_hwbits = (char *)sc->sc_fbaddr;
 861 } else {
 862 ri->ri_bits = (char *)sc->sc_fbaddr;
 863 ri->ri_hwbits = NULL;
 864 }
855 865
856 if (existing) { 866 if (existing) {
857 ri->ri_flg |= RI_CLEAR; 867 ri->ri_flg |= RI_CLEAR;
858 } 868 }
859 869
860 rasops_init(ri, sc->sc_panel->panel_height / 8, sc->sc_panel->panel_width / 8); 870 rasops_init(ri, sc->sc_panel->panel_height / 8, sc->sc_panel->panel_width / 8);
861 ri->ri_caps = WSSCREEN_WSCOLORS; 871 ri->ri_caps = WSSCREEN_WSCOLORS;
862 872
863 rasops_reconfig(ri, sc->sc_panel->panel_height / ri->ri_font->fontheight, 873 rasops_reconfig(ri, sc->sc_panel->panel_height / ri->ri_font->fontheight,
864 sc->sc_panel->panel_width / ri->ri_font->fontwidth); 874 sc->sc_panel->panel_width / ri->ri_font->fontwidth);
865 875
866 ri->ri_hw = scr; 876 ri->ri_hw = scr;
867} 877}
868 878
869static int 879static int
870tifb_putcmap(struct tifb_softc *sc, struct wsdisplay_cmap *cm) 880tifb_putcmap(struct tifb_softc *sc, struct wsdisplay_cmap *cm)
871{ 881{
872 return EINVAL; /* XXX */ 882 return EINVAL; /* XXX */
873#if 0 883#if 0
874 u_char *r, *g, *b; 884 u_char *r, *g, *b;
875 u_int index = cm->index; 885 u_int index = cm->index;
876 u_int count = cm->count; 886 u_int count = cm->count;
877 int i, error; 887 int i, error;
878 u_char rbuf[256], gbuf[256], bbuf[256]; 888 u_char rbuf[256], gbuf[256], bbuf[256];
879 889
880 if (cm->index >= 256 || cm->count > 256 || 890 if (cm->index >= 256 || cm->count > 256 ||
881 (cm->index + cm->count) > 256) 891 (cm->index + cm->count) > 256)
882 return EINVAL; 892 return EINVAL;
883 error = copyin(cm->red, &rbuf[index], count); 893 error = copyin(cm->red, &rbuf[index], count);
884 if (error) 894 if (error)
885 return error; 895 return error;
886 error = copyin(cm->green, &gbuf[index], count); 896 error = copyin(cm->green, &gbuf[index], count);
887 if (error) 897 if (error)
888 return error; 898 return error;
889 error = copyin(cm->blue, &bbuf[index], count); 899 error = copyin(cm->blue, &bbuf[index], count);
890 if (error) 900 if (error)
891 return error; 901 return error;
892 902
893 memcpy(&sc->sc_cmap_red[index], &rbuf[index], count); 903 memcpy(&sc->sc_cmap_red[index], &rbuf[index], count);
894 memcpy(&sc->sc_cmap_green[index], &gbuf[index], count); 904 memcpy(&sc->sc_cmap_green[index], &gbuf[index], count);
895 memcpy(&sc->sc_cmap_blue[index], &bbuf[index], count); 905 memcpy(&sc->sc_cmap_blue[index], &bbuf[index], count);
896 906
897 r = &sc->sc_cmap_red[index]; 907 r = &sc->sc_cmap_red[index];
898 g = &sc->sc_cmap_green[index]; 908 g = &sc->sc_cmap_green[index];
899 b = &sc->sc_cmap_blue[index]; 909 b = &sc->sc_cmap_blue[index];
900 910
901 for (i = 0; i < count; i++) { 911 for (i = 0; i < count; i++) {
902 tifb_putpalreg(sc, index, *r, *g, *b); 912 tifb_putpalreg(sc, index, *r, *g, *b);
903 index++; 913 index++;
904 r++, g++, b++; 914 r++, g++, b++;
905 } 915 }
906 return 0; 916 return 0;
907#endif 917#endif
908} 918}
909 919
910static int 920static int
911tifb_getcmap(struct tifb_softc *sc, struct wsdisplay_cmap *cm) 921tifb_getcmap(struct tifb_softc *sc, struct wsdisplay_cmap *cm)
912{ 922{
913 return EINVAL; /* XXX */ 923 return EINVAL; /* XXX */
914#if 0 924#if 0
915 u_int index = cm->index; 925 u_int index = cm->index;
916 u_int count = cm->count; 926 u_int count = cm->count;
917 int error; 927 int error;
918 928
919 if (index >= 255 || count > 256 || index + count > 256) 929 if (index >= 255 || count > 256 || index + count > 256)
920 return EINVAL; 930 return EINVAL;
921 931
922 error = copyout(&sc->sc_cmap_red[index], cm->red, count); 932 error = copyout(&sc->sc_cmap_red[index], cm->red, count);
923 if (error) 933 if (error)
924 return error; 934 return error;
925 error = copyout(&sc->sc_cmap_green[index], cm->green, count); 935 error = copyout(&sc->sc_cmap_green[index], cm->green, count);
926 if (error) 936 if (error)
927 return error; 937 return error;
928 error = copyout(&sc->sc_cmap_blue[index], cm->blue, count); 938 error = copyout(&sc->sc_cmap_blue[index], cm->blue, count);
929 if (error) 939 if (error)
930 return error; 940 return error;
931 941
932 return 0; 942 return 0;
933#endif 943#endif
934} 944}
935 945
936#if 0 946#if 0
937static void 947static void
938tifb_restore_palette(struct tifb_softc *sc) 948tifb_restore_palette(struct tifb_softc *sc)
939{ 949{
940 int i; 950 int i;
941 951
942 for (i = 0; i < 256; i++) { 952 for (i = 0; i < 256; i++) {
943 tifb_putpalreg(sc, i, sc->sc_cmap_red[i], 953 tifb_putpalreg(sc, i, sc->sc_cmap_red[i],
944 sc->sc_cmap_green[i], sc->sc_cmap_blue[i]); 954 sc->sc_cmap_green[i], sc->sc_cmap_blue[i]);
945 } 955 }
946} 956}
947 957
948static void 958static void
949tifb_putpalreg(struct tifb_softc *sc, int idx, uint8_t r, uint8_t g, 959tifb_putpalreg(struct tifb_softc *sc, int idx, uint8_t r, uint8_t g,
950 uint8_t b) 960 uint8_t b)
951{ 961{
952 uint32_t reg; 962 uint32_t reg;
953 963
954 if ((idx < 0) || (idx > 255)) 964 if ((idx < 0) || (idx > 255))
955 return; 965 return;
956 /* whack the DAC */ 966 /* whack the DAC */
957 reg = (r << 16) | (g << 8) | b; 967 reg = (r << 16) | (g << 8) | b;
958 sc->sc_clut[idx] = reg; 968 sc->sc_clut[idx] = reg;
959} 969}
960 970
961static int 971static int
962tifb_set_depth(struct tifb_softc *sc, int d) 972tifb_set_depth(struct tifb_softc *sc, int d)
963{ 973{
964 uint32_t reg; 974 uint32_t reg;
965 975
966 reg = OMAP_VID_ATTR_ENABLE | 976 reg = OMAP_VID_ATTR_ENABLE |
967 OMAP_VID_ATTR_BURST_16x32 | 977 OMAP_VID_ATTR_BURST_16x32 |
968 OMAP_VID_ATTR_REPLICATION; 978 OMAP_VID_ATTR_REPLICATION;
969 switch (d) { 979 switch (d) {
970 case 16: 980 case 16:
971 reg |= OMAP_VID_ATTR_RGB16; 981 reg |= OMAP_VID_ATTR_RGB16;
972 break; 982 break;
973 case 32: 983 case 32:
974 reg |= OMAP_VID_ATTR_RGB24; 984 reg |= OMAP_VID_ATTR_RGB24;
975 break; 985 break;
976 default: 986 default:
977 aprint_error_dev(sc->sc_dev, 987 aprint_error_dev(sc->sc_dev,
978 "unsupported depth (%d)\n", d); 988 "unsupported depth (%d)\n", d);
979 return EINVAL; 989 return EINVAL;
980 } 990 }
981 991
982 bus_space_write_4(sc->sc_iot, sc->sc_regh, 992 bus_space_write_4(sc->sc_iot, sc->sc_regh,
983 OMAPFB_DISPC_VID1_ATTRIBUTES, reg); 993 OMAPFB_DISPC_VID1_ATTRIBUTES, reg);
984 994
985 /* 995 /*
986 * now tell the video controller that we're done mucking around and 996 * now tell the video controller that we're done mucking around and
987 * actually update its settings 997 * actually update its settings
988 */ 998 */
989 reg = bus_space_read_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONTROL); 999 reg = bus_space_read_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONTROL);
990 bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONTROL, 1000 bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONTROL,
991 reg | OMAP_DISPC_CTRL_GO_LCD | OMAP_DISPC_CTRL_GO_DIGITAL); 1001 reg | OMAP_DISPC_CTRL_GO_LCD | OMAP_DISPC_CTRL_GO_DIGITAL);
992 1002
993 sc->sc_panel->bpp = d; 1003 sc->sc_panel->bpp = d;
994 sc->sc_stride = sc->sc_panel->panel_width * (sc->sc_panel->bpp >> 3); 1004 sc->sc_stride = sc->sc_panel->panel_width * (sc->sc_panel->bpp >> 3);
995 1005
996 /* clear the screen here */ 1006 /* clear the screen here */
997 memset(sc->sc_fbaddr, 0, sc->sc_stride * sc->sc_panel->panel_height); 1007 memset(sc->sc_fbaddr, 0, sc->sc_stride * sc->sc_panel->panel_height);
998 return 0; 1008 return 0;
999} 1009}
1000#endif /* 0 */ 1010#endif /* 0 */
1001 1011
1002static void 1012static void
1003tifb_set_video(struct tifb_softc *sc, int on) 1013tifb_set_video(struct tifb_softc *sc, int on)
1004{ 1014{
1005#if 0 1015#if 0
1006 uint32_t reg; 1016 uint32_t reg;
1007 1017
1008 if (on == sc->sc_video_is_on) 1018 if (on == sc->sc_video_is_on)
1009 return; 1019 return;
1010 if (on) { 1020 if (on) {
1011 bus_space_write_4(sc->sc_iot, sc->sc_regh, 1021 bus_space_write_4(sc->sc_iot, sc->sc_regh,
1012 OMAPFB_DISPC_CONFIG, sc->sc_dispc_config); 1022 OMAPFB_DISPC_CONFIG, sc->sc_dispc_config);
1013 on = 1; 1023 on = 1;
1014 } else { 1024 } else {
1015 bus_space_write_4(sc->sc_iot, sc->sc_regh, 1025 bus_space_write_4(sc->sc_iot, sc->sc_regh,
1016 OMAPFB_DISPC_CONFIG, sc->sc_dispc_config | 1026 OMAPFB_DISPC_CONFIG, sc->sc_dispc_config |
1017 OMAP_DISPC_CFG_VSYNC_GATED | OMAP_DISPC_CFG_HSYNC_GATED | 1027 OMAP_DISPC_CFG_VSYNC_GATED | OMAP_DISPC_CFG_HSYNC_GATED |
1018 OMAP_DISPC_CFG_PIXELCLK_GATED | 1028 OMAP_DISPC_CFG_PIXELCLK_GATED |
1019 OMAP_DISPC_CFG_PIXELDATA_GATED); 1029 OMAP_DISPC_CFG_PIXELDATA_GATED);
1020 } 1030 }
1021 1031
1022 /* 1032 /*
1023 * now tell the video controller that we're done mucking around and 1033 * now tell the video controller that we're done mucking around and
1024 * actually update its settings 1034 * actually update its settings
1025 */ 1035 */
1026 reg = bus_space_read_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONTROL); 1036 reg = bus_space_read_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONTROL);
1027 bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONTROL, 1037 bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONTROL,
1028 reg | OMAP_DISPC_CTRL_GO_LCD | OMAP_DISPC_CTRL_GO_DIGITAL); 1038 reg | OMAP_DISPC_CTRL_GO_LCD | OMAP_DISPC_CTRL_GO_DIGITAL);
1029 1039
1030 aprint_debug_dev(sc->sc_dev, "%s %08x\n", __func__, 1040 aprint_debug_dev(sc->sc_dev, "%s %08x\n", __func__,
1031 bus_space_read_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONFIG)); 1041 bus_space_read_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONFIG));
1032 sc->sc_video_is_on = on; 1042 sc->sc_video_is_on = on;
1033#endif 1043#endif
1034} 1044}
1035 1045
1036#ifdef TI_AM335X 1046#ifdef TI_AM335X
1037static void 1047static void
1038am335x_clk_lcdc_activate(void) 1048am335x_clk_lcdc_activate(void)
1039{ 1049{
1040 /* Bypass mode */ 1050 /* Bypass mode */
1041 prcm_write_4(AM335X_PRCM_CM_WKUP, CM_WKUP_CM_CLKMODE_DPLL_DISP, 1051 prcm_write_4(AM335X_PRCM_CM_WKUP, CM_WKUP_CM_CLKMODE_DPLL_DISP,
1042 AM335X_PRCM_CM_CLKMODE_DPLL_MN_BYP_MODE); 1052 AM335X_PRCM_CM_CLKMODE_DPLL_MN_BYP_MODE);
1043 1053
1044 /* Make sure it's in bypass mode */ 1054 /* Make sure it's in bypass mode */
1045 while (!(prcm_read_4(AM335X_PRCM_CM_WKUP, CM_WKUP_CM_IDLEST_DPLL_DISP) 1055 while (!(prcm_read_4(AM335X_PRCM_CM_WKUP, CM_WKUP_CM_IDLEST_DPLL_DISP)
1046 & (1 << 8))) 1056 & (1 << 8)))
1047 DELAY(10); 1057 DELAY(10);
1048 1058
1049 /* 1059 /*
1050 * For now set frequency to 5xSYSFREQ 1060 * For now set frequency to 5xSYSFREQ
1051 * More flexible control might be required 1061 * More flexible control might be required
1052 */ 1062 */
1053 prcm_write_4(AM335X_PRCM_CM_WKUP, CM_WKUP_CM_CLKSEL_DPLL_DISP, 1063 prcm_write_4(AM335X_PRCM_CM_WKUP, CM_WKUP_CM_CLKSEL_DPLL_DISP,
1054 (5 << 8) | 0); 1064 (5 << 8) | 0);
1055 1065
1056 /* Locked mode */ 1066 /* Locked mode */
1057 prcm_write_4(AM335X_PRCM_CM_WKUP, CM_WKUP_CM_CLKMODE_DPLL_DISP, 0x7); 1067 prcm_write_4(AM335X_PRCM_CM_WKUP, CM_WKUP_CM_CLKMODE_DPLL_DISP, 0x7);
1058 1068
1059 int timeout = 10000; 1069 int timeout = 10000;
1060 while ((!(prcm_read_4(AM335X_PRCM_CM_WKUP, CM_WKUP_CM_IDLEST_DPLL_DISP) 1070 while ((!(prcm_read_4(AM335X_PRCM_CM_WKUP, CM_WKUP_CM_IDLEST_DPLL_DISP)
1061 & (1 << 0))) && timeout--) 1071 & (1 << 0))) && timeout--)
1062 DELAY(10); 1072 DELAY(10);
1063 1073
1064 /*set MODULEMODE to ENABLE(2) */ 1074 /*set MODULEMODE to ENABLE(2) */
1065 prcm_write_4(AM335X_PRCM_CM_PER, CM_PER_LCDC_CLKCTRL, 2); 1075 prcm_write_4(AM335X_PRCM_CM_PER, CM_PER_LCDC_CLKCTRL, 2);
1066 1076
1067 /* wait for MODULEMODE to become ENABLE(2) */ 1077 /* wait for MODULEMODE to become ENABLE(2) */
1068 while ((prcm_read_4(AM335X_PRCM_CM_PER, CM_PER_LCDC_CLKCTRL) & 0x3) != 2) 1078 while ((prcm_read_4(AM335X_PRCM_CM_PER, CM_PER_LCDC_CLKCTRL) & 0x3) != 2)
1069 DELAY(10); 1079 DELAY(10);
1070 1080
1071 /* wait for IDLEST to become Func(0) */ 1081 /* wait for IDLEST to become Func(0) */
1072 while(prcm_read_4(AM335X_PRCM_CM_PER, CM_PER_LCDC_CLKCTRL) & (3<<16)) 1082 while(prcm_read_4(AM335X_PRCM_CM_PER, CM_PER_LCDC_CLKCTRL) & (3<<16))
1073 DELAY(10); 1083 DELAY(10);
1074} 1084}
1075 1085
1076static int 1086static int
1077am335x_clk_get_arm_disp_freq(unsigned int *freq) 1087am335x_clk_get_arm_disp_freq(unsigned int *freq)
1078{ 1088{
1079 uint32_t reg; 1089 uint32_t reg;
1080#define DPLL_BYP_CLKSEL(reg) ((reg>>23) & 1) 1090#define DPLL_BYP_CLKSEL(reg) ((reg>>23) & 1)
1081#define DPLL_DIV(reg) ((reg & 0x7f)+1) 1091#define DPLL_DIV(reg) ((reg & 0x7f)+1)
1082#define DPLL_MULT(reg) ((reg>>8) & 0x7FF) 1092#define DPLL_MULT(reg) ((reg>>8) & 0x7FF)
1083  1093
1084 reg = prcm_read_4(AM335X_PRCM_CM_WKUP, CM_WKUP_CM_CLKSEL_DPLL_DISP); 1094 reg = prcm_read_4(AM335X_PRCM_CM_WKUP, CM_WKUP_CM_CLKSEL_DPLL_DISP);
1085  1095
1086 /*Check if we are running in bypass */ 1096 /*Check if we are running in bypass */
1087 if (DPLL_BYP_CLKSEL(reg)) 1097 if (DPLL_BYP_CLKSEL(reg))
1088 return ENXIO; 1098 return ENXIO;
1089  1099
1090 *freq = DPLL_MULT(reg) * (omap_sys_clk / DPLL_DIV(reg)); 1100 *freq = DPLL_MULT(reg) * (omap_sys_clk / DPLL_DIV(reg));
1091 return(0); 1101 return(0);
1092} 1102}
1093#endif 1103#endif