1 1.1 macallan /* 2 1.1 macallan * Redistribution and use in source and binary forms, with or without 3 1.1 macallan * modification, are permitted provided that the following conditions 4 1.1 macallan * are met: 5 1.1 macallan * 1. Redistributions of source code must retain the above copyright 6 1.1 macallan * notice, this list of conditions and the following disclaimer. 7 1.1 macallan * 2. Redistributions in binary form must reproduce the above copyright 8 1.1 macallan * notice, this list of conditions and the following disclaimer in the 9 1.1 macallan * documentation and/or other materials provided with the distribution. 10 1.1 macallan * 11 1.1 macallan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 12 1.1 macallan * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 13 1.1 macallan * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 14 1.1 macallan * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 15 1.1 macallan * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 16 1.1 macallan * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 17 1.1 macallan * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 18 1.1 macallan * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 19 1.1 macallan * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 20 1.1 macallan * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 21 1.1 macallan */ 22 1.1 macallan 23 1.1 macallan /* A console driver for Apple's Platinum onboard video controller, 24 1.1 macallan * found in (all?) Catalyst logic boards including the Powermac 7200. 25 1.1 macallan * 26 1.1 macallan * Used valkyriefb.c from NetBSD, and platinumfb.c/platinumfb.h from 27 1.1 macallan * Linux sources as templates. 28 1.1 macallan * 29 1.1 macallan * Platinum is broken regarding openfirmware video variables. In OF, 30 1.1 macallan * for a powermac 7200, doing "dev /platinum .properties" results in: 31 1.1 macallan * 32 1.1 macallan * name platinum 33 1.1 macallan * device_type display 34 1.1 macallan * model AAPL,343S1184 35 1.1 macallan * AAPL,connector monitor 36 1.1 macallan * reg F8000000 00000800 37 1.1 macallan * F1000000 01000000 38 1.1 macallan * AAPL,interrupts 0000001E 39 1.1 macallan * 40 1.1 macallan * The first reg is the register set, and the second is for the 41 1.1 macallan * framebuffer. There is also a set of colormap registers hardcoded 42 1.1 macallan * in platinumfbreg.h that (I think) aren't in openfirmware. 43 1.1 macallan * 44 1.1 macallan * powermac 7200 VRAM min and max limits are 1 and 4 Mb respectively. 45 1.1 macallan * OF claims 16M so we don't use that value. If other machines can 46 1.1 macallan * can have more or less VRAM this code will need to be modified 47 1.1 macallan */ 48 1.1 macallan 49 1.1 macallan #include <sys/cdefs.h> 50 1.6 thorpej __KERNEL_RCSID(0, "$NetBSD: platinumfb.c,v 1.6 2021/08/07 16:18:57 thorpej Exp $"); 51 1.1 macallan 52 1.1 macallan #include <sys/param.h> 53 1.1 macallan #include <sys/systm.h> 54 1.1 macallan #include <sys/kernel.h> 55 1.1 macallan #include <sys/device.h> 56 1.1 macallan 57 1.1 macallan #include <uvm/uvm_param.h> 58 1.1 macallan 59 1.1 macallan #include <dev/ofw/openfirm.h> 60 1.1 macallan 61 1.1 macallan #include <machine/autoconf.h> 62 1.1 macallan #include <machine/pio.h> 63 1.1 macallan 64 1.1 macallan #include <dev/wscons/wsdisplayvar.h> 65 1.1 macallan #include <dev/wscons/wsconsio.h> 66 1.1 macallan #include <dev/wsfont/wsfont.h> 67 1.1 macallan #include <dev/rasops/rasops.h> 68 1.1 macallan #include <dev/wscons/wsdisplay_vconsvar.h> 69 1.1 macallan 70 1.1 macallan #include <dev/videomode/videomode.h> 71 1.1 macallan 72 1.1 macallan #include <arch/macppc/dev/platinumfbreg.h> 73 1.1 macallan 74 1.1 macallan #include <sys/sysctl.h> 75 1.1 macallan 76 1.1 macallan #include "opt_wsemul.h" 77 1.1 macallan 78 1.1 macallan /* 79 1.1 macallan * here is a link of supported modes and resolutions: 80 1.1 macallan * https://support.apple.com/kb/SP343?locale=en_US 81 1.1 macallan * 82 1.1 macallan * default console and X bpp/depth for built-in X config file, 83 1.1 macallan * select 8 or 16 or 32. 84 1.1 macallan * 85 1.1 macallan */ 86 1.1 macallan #define PLATINUM_CONSOLE_DEPTH 8 87 1.1 macallan #define PLATINUM_FB_DEPTH 16 88 1.1 macallan 89 1.1 macallan /* 90 1.3 scole * XXX 16 bit console not working without this patch to rasops15.c, 91 1.3 scole * http://mail-index.netbsd.org/current-users/2016/09/14/msg030132.html 92 1.3 scole * see thread, but rasops may need separate flags for host byte order 93 1.3 scole * and video hw byte order 94 1.3 scole */ 95 1.3 scole 96 1.3 scole /* 97 1.1 macallan * resolution, from one of platinumfb_setting vmode_name's. 98 1.1 macallan */ 99 1.1 macallan #define PLATINUM_FB_VMODE "1024x768x60" 100 1.1 macallan 101 1.1 macallan struct platinumfb_setting { 102 1.1 macallan char vmode_name[24]; 103 1.1 macallan int32_t width; 104 1.1 macallan int32_t height; 105 1.1 macallan uint8_t freq; 106 1.1 macallan uint8_t macmode; 107 1.1 macallan 108 1.1 macallan int32_t pitch[3]; 109 1.1 macallan uint32_t regs[26]; 110 1.1 macallan uint8_t offset[3]; 111 1.1 macallan uint8_t mode[3]; 112 1.1 macallan uint8_t dacula_ctrl[3]; 113 1.1 macallan uint8_t clock_params[2][2]; 114 1.1 macallan }; 115 1.1 macallan 116 1.1 macallan struct platinumfb_softc { 117 1.1 macallan device_t sc_dev; 118 1.1 macallan int sc_node; 119 1.1 macallan 120 1.1 macallan uint8_t *sc_reg; 121 1.1 macallan uint32_t sc_reg_size; 122 1.1 macallan 123 1.1 macallan uint8_t *sc_cmap; 124 1.1 macallan uint32_t sc_cmap_size; 125 1.1 macallan 126 1.1 macallan uint8_t *sc_fb; 127 1.1 macallan uint32_t sc_fb_size; 128 1.1 macallan 129 1.1 macallan int sc_depth; 130 1.1 macallan int sc_width, sc_height, sc_linebytes; 131 1.1 macallan const struct videomode *sc_videomode; 132 1.1 macallan uint8_t sc_modereg; 133 1.1 macallan 134 1.1 macallan int sc_mode; 135 1.1 macallan 136 1.1 macallan u_char sc_cmap_red[256]; 137 1.1 macallan u_char sc_cmap_green[256]; 138 1.1 macallan u_char sc_cmap_blue[256]; 139 1.1 macallan 140 1.1 macallan struct vcons_data vd; 141 1.1 macallan 142 1.1 macallan uint8_t sc_cmode; 143 1.1 macallan uint8_t sc_dac_type; 144 1.1 macallan uint32_t sc_vram; 145 1.1 macallan int sc_on; 146 1.1 macallan struct platinumfb_setting *sc_pfs; 147 1.1 macallan }; 148 1.1 macallan 149 1.1 macallan #define DIV2 0x20 150 1.1 macallan #define DIV4 0x40 151 1.1 macallan #define DIV8 0x60 152 1.1 macallan #define DIV16 0x80 153 1.1 macallan 154 1.1 macallan static struct platinumfb_setting platinum_5 = { 155 1.1 macallan "640x480x60", 156 1.1 macallan 640, 480, 60, 5, 157 1.1 macallan { 672, 1312, 2592 }, 158 1.1 macallan { 0xff0, 4, 0, 0, 0, 0, 0x320, 0, 159 1.1 macallan 0, 0x15e, 0xc8, 0x18, 0x18f, 0x2f, 0x35, 0x3e, 160 1.1 macallan 0x42, 0x182, 0x18e, 0x41a, 0x418, 2, 7, 0x44, 161 1.1 macallan 0x404, 0x408 }, { 0x34, 0x3c, 0x41 }, 162 1.1 macallan { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, 163 1.1 macallan {{ 26, 0 + DIV8 }, { 14, 2 + DIV4 }} 164 1.1 macallan }; 165 1.1 macallan 166 1.1 macallan static struct platinumfb_setting platinum_12 = { 167 1.1 macallan "800x600x75", 168 1.1 macallan 800, 600, 75, 12, 169 1.1 macallan { 832, 1632, 3232 }, 170 1.1 macallan { 0xff0, 4, 0, 0, 0, 0, 0x320, 0, 171 1.1 macallan 0, 0x1ce, 0x108, 0x14, 0x20f, 0x27, 0x30, 0x39, 172 1.1 macallan 0x72, 0x202, 0x20e, 0x4e2, 0x4e0, 4, 9, 0x2e, 173 1.1 macallan 0x4de, 0x4df }, { 0x64, 0x6c, 0x71 }, 174 1.1 macallan { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, 175 1.1 macallan {{ 122, 7 + DIV4 }, { 62, 9 + DIV2 }} 176 1.1 macallan }; 177 1.1 macallan 178 1.1 macallan static struct platinumfb_setting platinum_14 = { 179 1.1 macallan "1024x768x60", 180 1.1 macallan 1024, 768, 60, 14, 181 1.1 macallan { 1056, 2080, 4128 }, 182 1.1 macallan { 0xff0, 4, 0, 0, 0, 0, 0x320, 0, 183 1.1 macallan 0, 0x25a, 0x14f, 0x22, 0x29f, 0x43, 0x49, 0x5b, 184 1.1 macallan 0x8e, 0x28e, 0x29e, 0x64c, 0x64a, 0xa, 0xf, 0x44, 185 1.1 macallan 0x644, 0x646 }, { 0x80, 0x88, 0x8d }, 186 1.1 macallan { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, 187 1.1 macallan {{ 71, 6 + DIV2 }, { 118, 13 + DIV2 }} 188 1.1 macallan }; 189 1.1 macallan 190 1.1 macallan static struct platinumfb_setting platinum_20 = { 191 1.1 macallan "1280x1024x75", 192 1.1 macallan 1280, 1024, 75, 20, 193 1.1 macallan { 1312, 2592, 2592 }, 194 1.1 macallan { 0xffc, 4, 0, 0, 0, 0, 0x428, 0, 195 1.1 macallan 0, 0xb3, 0xd3, 0x12, 0x1a5, 0x23, 0x28, 0x2d, 196 1.1 macallan 0x5e, 0x19e, 0x1a4, 0x854, 0x852, 4, 9, 0x50, 197 1.1 macallan 0x850, 0x851 }, { 0x58, 0x5d, 0x5d }, 198 1.1 macallan { 0, 0xff, 0xff }, { 0x51, 0x55, 0x55 }, 199 1.1 macallan {{ 45, 3 }, { 66, 7 }} 200 1.1 macallan }; 201 1.1 macallan 202 1.1 macallan static struct platinumfb_setting *pfb_setting[] = { 203 1.1 macallan &platinum_5, 204 1.1 macallan &platinum_12, 205 1.1 macallan &platinum_14, 206 1.1 macallan &platinum_20 207 1.1 macallan }; 208 1.1 macallan 209 1.1 macallan static struct vcons_screen platinumfb_console_screen; 210 1.1 macallan 211 1.1 macallan static int platinumfb_match(device_t, cfdata_t, void *); 212 1.1 macallan static void platinumfb_attach(device_t, device_t, void *); 213 1.1 macallan 214 1.1 macallan CFATTACH_DECL_NEW(platinumfb, sizeof(struct platinumfb_softc), 215 1.1 macallan platinumfb_match, platinumfb_attach, NULL, NULL); 216 1.1 macallan 217 1.1 macallan static int platinumfb_init(device_t); 218 1.1 macallan static int platinumfb_set_mode(struct platinumfb_softc *, 219 1.1 macallan const struct videomode *, int); 220 1.1 macallan static void platinumfb_set_rasops(struct platinumfb_softc *, 221 1.1 macallan struct rasops_info *, int); 222 1.1 macallan static int platinumfb_ioctl(void *, void *, u_long, void *, int, 223 1.1 macallan struct lwp *); 224 1.1 macallan static paddr_t platinumfb_mmap(void *, void *, off_t, int); 225 1.1 macallan static void platinumfb_init_screen(void *, struct vcons_screen *, int, 226 1.1 macallan long *); 227 1.1 macallan static int platinumfb_putcmap(struct platinumfb_softc *, 228 1.1 macallan struct wsdisplay_cmap *); 229 1.1 macallan static int platinumfb_getcmap(struct platinumfb_softc *, 230 1.1 macallan struct wsdisplay_cmap *); 231 1.1 macallan static void platinumfb_init_cmap(struct platinumfb_softc *); 232 1.1 macallan static void platinumfb_restore_palette(struct platinumfb_softc *); 233 1.1 macallan static void platinumfb_putpalreg(struct platinumfb_softc *, 234 1.1 macallan uint8_t, uint8_t, uint8_t, uint8_t); 235 1.1 macallan static uint32_t platinumfb_line_tweak(struct platinumfb_softc *); 236 1.1 macallan static paddr_t platinumfb_page_align_up(struct platinumfb_softc *); 237 1.1 macallan static void platinumfb_set_clock(struct platinumfb_softc *); 238 1.1 macallan static void platinumfb_dac_type(struct platinumfb_softc *); 239 1.1 macallan static void platinumfb_memory_size(struct platinumfb_softc *); 240 1.1 macallan static void platinumfb_set_hardware(struct platinumfb_softc *); 241 1.1 macallan 242 1.1 macallan static inline void platinumfb_write_reg(struct platinumfb_softc *, 243 1.1 macallan int, uint32_t); 244 1.2 macallan 245 1.2 macallan #ifdef notyet 246 1.1 macallan static inline uint32_t platinumfb_read_reg(struct platinumfb_softc *, int); 247 1.2 macallan #endif 248 1.1 macallan static inline void platinumfb_write_cmap_reg(struct platinumfb_softc *, 249 1.1 macallan int, uint8_t); 250 1.1 macallan static inline uint8_t platinumfb_read_cmap_reg(struct platinumfb_softc *, int); 251 1.1 macallan static inline void platinumfb_store_d2(struct platinumfb_softc *, 252 1.1 macallan uint8_t, uint8_t); 253 1.1 macallan 254 1.1 macallan struct wsscreen_descr platinumfb_defaultscreen = { 255 1.1 macallan "default", 256 1.1 macallan 0, 0, 257 1.1 macallan NULL, 258 1.1 macallan 8, 16, 259 1.1 macallan WSSCREEN_WSCOLORS | WSSCREEN_HILIT, 260 1.1 macallan NULL, 261 1.1 macallan }; 262 1.1 macallan 263 1.1 macallan const struct wsscreen_descr *_platinumfb_scrlist[] = { 264 1.1 macallan &platinumfb_defaultscreen, 265 1.1 macallan /* XXX other formats, graphics screen? */ 266 1.1 macallan }; 267 1.1 macallan 268 1.1 macallan struct wsscreen_list platinumfb_screenlist = { 269 1.1 macallan sizeof(_platinumfb_scrlist) / sizeof(struct wsscreen_descr *), 270 1.1 macallan _platinumfb_scrlist 271 1.1 macallan }; 272 1.1 macallan 273 1.1 macallan struct wsdisplay_accessops platinumfb_accessops = { 274 1.1 macallan platinumfb_ioctl, 275 1.1 macallan platinumfb_mmap, 276 1.1 macallan NULL, 277 1.1 macallan NULL, 278 1.1 macallan NULL, 279 1.1 macallan NULL, /* load_font */ 280 1.1 macallan NULL, /* polls */ 281 1.1 macallan NULL, /* scroll */ 282 1.1 macallan }; 283 1.1 macallan 284 1.1 macallan static inline void 285 1.1 macallan platinumfb_write_reg(struct platinumfb_softc *sc, int reg, uint32_t val) 286 1.1 macallan { 287 1.1 macallan out32(sc->sc_reg + PLATINUM_REG_OFFSET_ADDR(reg), val); 288 1.1 macallan } 289 1.1 macallan 290 1.2 macallan #ifdef notyet 291 1.1 macallan static inline uint32_t 292 1.1 macallan platinumfb_read_reg(struct platinumfb_softc *sc, int reg) 293 1.1 macallan { 294 1.1 macallan return in32(sc->sc_reg + PLATINUM_REG_OFFSET_ADDR(reg)); 295 1.1 macallan } 296 1.2 macallan #endif 297 1.1 macallan 298 1.1 macallan static inline void 299 1.1 macallan platinumfb_write_cmap_reg(struct platinumfb_softc *sc, 300 1.1 macallan int reg_offset, uint8_t val) 301 1.1 macallan { 302 1.1 macallan out8(sc->sc_cmap + reg_offset, val); 303 1.1 macallan } 304 1.1 macallan 305 1.1 macallan static inline uint8_t 306 1.1 macallan platinumfb_read_cmap_reg(struct platinumfb_softc *sc, int reg_offset) 307 1.1 macallan { 308 1.1 macallan return in8(sc->sc_cmap + reg_offset); 309 1.1 macallan } 310 1.1 macallan 311 1.1 macallan static inline void 312 1.1 macallan platinumfb_store_d2(struct platinumfb_softc *sc, 313 1.1 macallan uint8_t a, uint8_t d) 314 1.1 macallan { 315 1.1 macallan platinumfb_write_cmap_reg(sc, PLATINUM_CMAP_ADDR_OFFSET, a + 32); 316 1.1 macallan platinumfb_write_cmap_reg(sc, PLATINUM_CMAP_D2_OFFSET, d); 317 1.1 macallan } 318 1.1 macallan 319 1.1 macallan static void 320 1.1 macallan platinumfb_putpalreg(struct platinumfb_softc *sc, 321 1.1 macallan uint8_t reg, uint8_t r, uint8_t g, uint8_t b) 322 1.1 macallan { 323 1.1 macallan platinumfb_write_cmap_reg(sc, PLATINUM_CMAP_ADDR_OFFSET, reg); 324 1.1 macallan platinumfb_write_cmap_reg(sc, PLATINUM_CMAP_LUT_OFFSET, r); 325 1.1 macallan platinumfb_write_cmap_reg(sc, PLATINUM_CMAP_LUT_OFFSET, g); 326 1.1 macallan platinumfb_write_cmap_reg(sc, PLATINUM_CMAP_LUT_OFFSET, b); 327 1.1 macallan } 328 1.1 macallan 329 1.1 macallan static uint32_t 330 1.1 macallan platinumfb_line_tweak(struct platinumfb_softc *sc) 331 1.1 macallan { 332 1.1 macallan /* bytes per line adjustment depending on resolution and depth */ 333 1.1 macallan if (sc->sc_cmode > PLATINUM_CMODE_8 && 334 1.1 macallan strcmp(sc->sc_pfs->vmode_name, "832x624x75") == 0) 335 1.1 macallan return 0x10; 336 1.1 macallan else 337 1.1 macallan return 0x20; 338 1.1 macallan } 339 1.1 macallan 340 1.1 macallan static paddr_t 341 1.1 macallan platinumfb_page_align_up(struct platinumfb_softc *sc) 342 1.1 macallan { 343 1.1 macallan /* round up framebuffer address to the next highest page */ 344 1.1 macallan paddr_t addr = (paddr_t)sc->sc_fb; 345 1.1 macallan paddr_t ret = round_page(addr); 346 1.1 macallan 347 1.1 macallan if (ret == addr) 348 1.1 macallan ret = round_page(addr + 1); 349 1.1 macallan 350 1.1 macallan return ret; 351 1.1 macallan } 352 1.1 macallan 353 1.1 macallan /* 2 versions of platinum clock, older one uses clock[1] and 354 1.1 macallan * freq = 14.3Mhz * c0 / (c1 & 0x1f) / (1 << (c1 >> 5)) 355 1.1 macallan * newer one uses clock[0] and 356 1.1 macallan * freq = 15Mhz * c0 / ((c1 & 0x1f) + 2) / (1 << (c1 >> 5)) 357 1.1 macallan */ 358 1.1 macallan static void 359 1.1 macallan platinumfb_set_clock(struct platinumfb_softc *sc) 360 1.1 macallan { 361 1.1 macallan uint8_t clk_idx = sc->sc_dac_type == PLATINUM_DAC_1 ? 1 : 0; 362 1.1 macallan uint8_t d2; 363 1.1 macallan 364 1.1 macallan platinumfb_store_d2(sc, 6, 0xc6); 365 1.1 macallan 366 1.1 macallan platinumfb_write_cmap_reg(sc, PLATINUM_CMAP_ADDR_OFFSET, 3+32); 367 1.1 macallan d2 = platinumfb_read_cmap_reg(sc, PLATINUM_CMAP_D2_OFFSET); 368 1.1 macallan 369 1.1 macallan if (d2 == 2) { 370 1.1 macallan platinumfb_store_d2(sc, 7, sc->sc_pfs->clock_params[clk_idx][0]); 371 1.1 macallan platinumfb_store_d2(sc, 8, sc->sc_pfs->clock_params[clk_idx][1]); 372 1.1 macallan platinumfb_store_d2(sc, 3, 3); 373 1.1 macallan } else { 374 1.1 macallan platinumfb_store_d2(sc, 4, sc->sc_pfs->clock_params[clk_idx][0]); 375 1.1 macallan platinumfb_store_d2(sc, 5, sc->sc_pfs->clock_params[clk_idx][1]); 376 1.1 macallan platinumfb_store_d2(sc, 3, 2); 377 1.1 macallan } 378 1.1 macallan 379 1.1 macallan delay(5000); 380 1.1 macallan platinumfb_store_d2(sc, 9, 0xa6); 381 1.1 macallan } 382 1.1 macallan 383 1.1 macallan static void 384 1.1 macallan platinumfb_dac_type(struct platinumfb_softc *sc) 385 1.1 macallan { 386 1.1 macallan uint8_t dtype = 0; 387 1.1 macallan 388 1.1 macallan platinumfb_write_cmap_reg(sc, PLATINUM_CMAP_ADDR_OFFSET, 0x40); 389 1.1 macallan dtype = platinumfb_read_cmap_reg(sc, PLATINUM_CMAP_D2_OFFSET); 390 1.1 macallan 391 1.1 macallan switch (dtype) { 392 1.1 macallan case PLATINUM_DAC_0: 393 1.1 macallan case PLATINUM_DAC_1: 394 1.1 macallan /* do nothing */ 395 1.1 macallan break; 396 1.1 macallan default: 397 1.1 macallan aprint_error_dev(sc->sc_dev, "unknown dac 0x%x, using 0x%x\n", 398 1.1 macallan dtype, PLATINUM_DAC_0); 399 1.1 macallan dtype = PLATINUM_DAC_0; 400 1.1 macallan break; 401 1.1 macallan } 402 1.1 macallan 403 1.1 macallan /* save type */ 404 1.1 macallan sc->sc_dac_type = dtype; 405 1.1 macallan } 406 1.1 macallan 407 1.1 macallan static void 408 1.1 macallan platinumfb_memory_size(struct platinumfb_softc *sc) 409 1.1 macallan { 410 1.1 macallan int i; 411 1.1 macallan off_t offset = PLATINUM_FB_BANK_SIZE; 412 1.1 macallan paddr_t total_vram = PLATINUM_FB_MIN_SIZE; 413 1.1 macallan 414 1.1 macallan uint8_t test_val[] = {0x34, 0x56, 0x78}; 415 1.1 macallan uint8_t bank[] = {0, 0, 0}; 416 1.1 macallan uint8_t num_elems = sizeof(test_val)/sizeof(test_val[0]); 417 1.1 macallan 418 1.1 macallan volatile uint8_t *fbuffer = mapiodev((paddr_t)sc->sc_fb, sc->sc_fb_size, false); 419 1.1 macallan 420 1.1 macallan if (fbuffer == NULL) 421 1.1 macallan panic("platinumfb could not mapiodev"); 422 1.1 macallan 423 1.1 macallan /* turn on all banks of RAM */ 424 1.1 macallan platinumfb_write_reg(sc, 16, (paddr_t)sc->sc_fb); 425 1.1 macallan platinumfb_write_reg(sc, 20, 0x1011); 426 1.1 macallan platinumfb_write_reg(sc, 24, 0); 427 1.1 macallan 428 1.1 macallan /* 429 1.1 macallan * write "unique" value to each bank of memory and read value 430 1.1 macallan * back. if match assumes VRAM bank exists. On the powermac 7200, 431 1.1 macallan * bank0 is always there and soldered to motherboard, don't know 432 1.1 macallan * if that is the case for others 433 1.1 macallan */ 434 1.1 macallan for (i = 0 ; i < num_elems; i++) { 435 1.1 macallan out8(fbuffer + offset, test_val[i]); 436 1.1 macallan out8(fbuffer + offset + 0x8, 0x0); 437 1.1 macallan 438 1.1 macallan __asm volatile ("eieio; dcbf 0,%0"::"r"(&fbuffer[offset]):"memory"); 439 1.1 macallan 440 1.1 macallan bank[i] = fbuffer[offset] == test_val[i]; 441 1.1 macallan total_vram += bank[i] * PLATINUM_FB_BANK_SIZE; 442 1.1 macallan offset += PLATINUM_FB_BANK_SIZE; 443 1.1 macallan } 444 1.1 macallan 445 1.1 macallan /* save total vram or minimum */ 446 1.1 macallan if (total_vram >= PLATINUM_FB_MIN_SIZE && total_vram <= PLATINUM_FB_MAX_SIZE) { 447 1.1 macallan sc->sc_vram = total_vram; 448 1.1 macallan } else { 449 1.1 macallan aprint_error_dev(sc->sc_dev, 450 1.1 macallan "invalid VRAM size 0x%lx, using min 0x%x\n", 451 1.1 macallan total_vram, PLATINUM_FB_MIN_SIZE); 452 1.1 macallan sc->sc_vram = PLATINUM_FB_MIN_SIZE; 453 1.1 macallan } 454 1.1 macallan 455 1.1 macallan unmapiodev((paddr_t)fbuffer, sc->sc_fb_size); 456 1.1 macallan } 457 1.1 macallan 458 1.1 macallan static int 459 1.1 macallan platinumfb_match(device_t parent, cfdata_t cf, void *aux) 460 1.1 macallan { 461 1.1 macallan struct confargs *ca = aux; 462 1.1 macallan 463 1.1 macallan return (strcmp(ca->ca_name, "platinum") == 0); 464 1.1 macallan } 465 1.1 macallan 466 1.1 macallan static void 467 1.1 macallan platinumfb_attach(device_t parent, device_t self, void *aux) 468 1.1 macallan { 469 1.1 macallan struct platinumfb_softc *sc = device_private(self); 470 1.1 macallan struct confargs *ca = aux; 471 1.1 macallan u_int *reg = ca->ca_reg; 472 1.1 macallan 473 1.1 macallan sc->sc_dev = self; 474 1.1 macallan sc->sc_node = ca->ca_node; 475 1.1 macallan 476 1.1 macallan sc->sc_reg = (uint8_t *)reg[0]; 477 1.1 macallan sc->sc_reg_size = reg[1]; 478 1.1 macallan 479 1.1 macallan sc->sc_fb = (uint8_t *)reg[2]; 480 1.1 macallan sc->sc_fb_size = PLATINUM_FB_MAX_SIZE; 481 1.1 macallan 482 1.1 macallan sc->sc_cmap = (uint8_t *)PLATINUM_CMAP_BASE_ADDR; 483 1.1 macallan sc->sc_cmap_size = PLATINUM_CMAP_SIZE; 484 1.1 macallan 485 1.1 macallan aprint_normal(" reg-addr 0x%08lx fb-addr 0x%08lx cmap-addr 0x%08lx\n", 486 1.1 macallan (paddr_t)sc->sc_reg, 487 1.1 macallan (paddr_t)sc->sc_fb, 488 1.1 macallan (paddr_t)sc->sc_cmap); 489 1.1 macallan 490 1.1 macallan config_finalize_register(sc->sc_dev, platinumfb_init); 491 1.1 macallan } 492 1.1 macallan 493 1.1 macallan static void 494 1.1 macallan platinumfb_init_cmap(struct platinumfb_softc *sc) 495 1.1 macallan { 496 1.1 macallan int i; 497 1.1 macallan uint8_t tmp; 498 1.1 macallan 499 1.1 macallan switch (sc->sc_cmode) { 500 1.1 macallan case PLATINUM_CMODE_8: 501 1.1 macallan default: 502 1.1 macallan /* R3G3B2 colormap */ 503 1.1 macallan for (i = 0; i < 256; i++) { 504 1.1 macallan tmp = i & 0xe0; 505 1.1 macallan /* 506 1.1 macallan * replicate bits so 0xe0 maps to a red value of 0xff 507 1.1 macallan * in order to make white look actually white 508 1.1 macallan */ 509 1.1 macallan tmp |= (tmp >> 3) | (tmp >> 6); 510 1.1 macallan sc->sc_cmap_red[i] = tmp; 511 1.1 macallan 512 1.1 macallan tmp = (i & 0x1c) << 3; 513 1.1 macallan tmp |= (tmp >> 3) | (tmp >> 6); 514 1.1 macallan sc->sc_cmap_green[i] = tmp; 515 1.1 macallan 516 1.1 macallan tmp = (i & 0x03) << 6; 517 1.1 macallan tmp |= tmp >> 2; 518 1.1 macallan tmp |= tmp >> 4; 519 1.1 macallan sc->sc_cmap_blue[i] = tmp; 520 1.1 macallan } 521 1.1 macallan break; 522 1.1 macallan 523 1.1 macallan case PLATINUM_CMODE_16: 524 1.1 macallan for (i = 0; i < 32; i++) { 525 1.1 macallan tmp = 255 * i / 32; 526 1.1 macallan sc->sc_cmap_red[i] = tmp; 527 1.1 macallan sc->sc_cmap_green[i] = tmp; 528 1.1 macallan sc->sc_cmap_blue[i] = tmp; 529 1.1 macallan } 530 1.1 macallan for (i = 32; i < 256; i++) { 531 1.1 macallan sc->sc_cmap_red[i] = 0; 532 1.1 macallan sc->sc_cmap_blue[i] = 0; 533 1.1 macallan sc->sc_cmap_green[i] = 0; 534 1.1 macallan } 535 1.1 macallan break; 536 1.1 macallan 537 1.1 macallan case PLATINUM_CMODE_32: 538 1.1 macallan for (i = 0; i < 256; i++) { 539 1.1 macallan sc->sc_cmap_red[i] = i; 540 1.1 macallan sc->sc_cmap_green[i] = i; 541 1.1 macallan sc->sc_cmap_blue[i] = i; 542 1.1 macallan } 543 1.1 macallan break; 544 1.1 macallan } 545 1.1 macallan } 546 1.1 macallan 547 1.1 macallan static void 548 1.1 macallan platinumfb_restore_palette(struct platinumfb_softc *sc) 549 1.1 macallan { 550 1.1 macallan int i; 551 1.1 macallan 552 1.1 macallan for (i = 0; i < 256; i++) { 553 1.1 macallan platinumfb_putpalreg(sc, i, sc->sc_cmap_red[i], 554 1.1 macallan sc->sc_cmap_green[i], sc->sc_cmap_blue[i]); 555 1.1 macallan } 556 1.1 macallan } 557 1.1 macallan 558 1.1 macallan static int 559 1.1 macallan platinumfb_init(device_t self) 560 1.1 macallan { 561 1.1 macallan struct platinumfb_softc *sc = device_private(self); 562 1.1 macallan const struct videomode *mode = NULL; 563 1.1 macallan struct rasops_info *ri; 564 1.1 macallan 565 1.1 macallan struct wsemuldisplaydev_attach_args aa; 566 1.1 macallan bool is_console = FALSE; 567 1.1 macallan long defattr; 568 1.1 macallan 569 1.1 macallan int i; 570 1.1 macallan 571 1.1 macallan /* 572 1.4 scole * become console if OF variable "output-device" contains "platinum", 573 1.4 scole * since normal OF video variables are unavailable 574 1.1 macallan */ 575 1.1 macallan int options; 576 1.1 macallan char output_device[128]; 577 1.1 macallan options = OF_finddevice("/options"); 578 1.1 macallan if (options == 0 || 579 1.1 macallan options == -1 || 580 1.1 macallan OF_getprop(options, "output-device", output_device, 581 1.1 macallan sizeof(output_device)) == 0 ) { 582 1.1 macallan aprint_error_dev(sc->sc_dev, 583 1.1 macallan "could not get output-device prop, assuming not console\n"); 584 1.1 macallan } else { 585 1.4 scole if (strstr(output_device,"platinum")) { 586 1.1 macallan is_console = TRUE; 587 1.1 macallan } 588 1.1 macallan } 589 1.1 macallan 590 1.1 macallan sc->sc_pfs = NULL; 591 1.1 macallan sc->sc_mode = WSDISPLAYIO_MODE_EMUL; 592 1.1 macallan sc->sc_on = WSDISPLAYIO_VIDEO_ON; 593 1.1 macallan 594 1.1 macallan /* determine vram memory and dac clock type */ 595 1.1 macallan platinumfb_memory_size(sc); 596 1.1 macallan platinumfb_dac_type(sc); 597 1.1 macallan 598 1.1 macallan aprint_normal_dev(sc->sc_dev,"is_console %d dac 0x%x vram 0x%x\n", 599 1.1 macallan is_console, sc->sc_dac_type, sc->sc_vram); 600 1.1 macallan 601 1.1 macallan for (i=0; i < sizeof(pfb_setting)/sizeof(pfb_setting[0]); i++) { 602 1.1 macallan if (strcmp(PLATINUM_FB_VMODE, pfb_setting[i]->vmode_name)==0) { 603 1.1 macallan mode = pick_mode_by_ref(pfb_setting[i]->width, 604 1.1 macallan pfb_setting[i]->height, 605 1.1 macallan pfb_setting[i]->freq); 606 1.1 macallan break; 607 1.1 macallan } 608 1.1 macallan } 609 1.1 macallan 610 1.1 macallan if (!mode) { 611 1.1 macallan aprint_error_dev(sc->sc_dev, 612 1.1 macallan "pick_mode_by_ref failed, using default\n"); 613 1.1 macallan mode = pick_mode_by_ref(800, 600, 75); 614 1.1 macallan } 615 1.1 macallan 616 1.1 macallan if (platinumfb_set_mode(sc, mode, PLATINUM_CONSOLE_DEPTH) != 0) { 617 1.1 macallan aprint_error_dev(sc->sc_dev, "platinumfb_set_mode failed\n"); 618 1.1 macallan return 0; 619 1.1 macallan } 620 1.1 macallan 621 1.1 macallan vcons_init(&sc->vd, sc, &platinumfb_defaultscreen, 622 1.1 macallan &platinumfb_accessops); 623 1.1 macallan sc->vd.init_screen = platinumfb_init_screen; 624 1.1 macallan 625 1.1 macallan ri = &platinumfb_console_screen.scr_ri; 626 1.1 macallan vcons_init_screen(&sc->vd, &platinumfb_console_screen, 1, &defattr); 627 1.1 macallan 628 1.1 macallan platinumfb_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC; 629 1.1 macallan 630 1.1 macallan platinumfb_defaultscreen.textops = &ri->ri_ops; 631 1.1 macallan platinumfb_defaultscreen.capabilities = ri->ri_caps; 632 1.1 macallan platinumfb_defaultscreen.nrows = ri->ri_rows; 633 1.1 macallan platinumfb_defaultscreen.ncols = ri->ri_cols; 634 1.1 macallan 635 1.1 macallan if (is_console) { 636 1.1 macallan wsdisplay_cnattach(&platinumfb_defaultscreen, ri, 0, 0, 637 1.1 macallan defattr); 638 1.1 macallan vcons_replay_msgbuf(&platinumfb_console_screen); 639 1.1 macallan } 640 1.1 macallan 641 1.1 macallan aa.console = is_console; 642 1.1 macallan aa.scrdata = &platinumfb_screenlist; 643 1.1 macallan aa.accessops = &platinumfb_accessops; 644 1.1 macallan aa.accesscookie = &sc->vd; 645 1.1 macallan 646 1.6 thorpej config_found(self, &aa, wsemuldisplaydevprint, CFARGS_NONE); 647 1.1 macallan 648 1.1 macallan return 0; 649 1.1 macallan } 650 1.1 macallan 651 1.1 macallan static void 652 1.1 macallan platinumfb_set_hardware(struct platinumfb_softc *sc) 653 1.1 macallan { 654 1.1 macallan int i; 655 1.1 macallan bool one_bank = sc->sc_vram == PLATINUM_FB_BANK_SIZE; 656 1.1 macallan 657 1.1 macallan /* now start programming the chip */ 658 1.1 macallan platinumfb_write_reg(sc, 24, 7); /* turn off display */ 659 1.1 macallan 660 1.1 macallan for (i = 0; i < 26; ++i) 661 1.1 macallan platinumfb_write_reg(sc, i+32, sc->sc_pfs->regs[i]); 662 1.1 macallan 663 1.1 macallan platinumfb_write_reg(sc, 26+32, one_bank ? 664 1.1 macallan sc->sc_pfs->offset[sc->sc_cmode] + 4 - sc->sc_cmode : 665 1.1 macallan sc->sc_pfs->offset[sc->sc_cmode]); 666 1.1 macallan 667 1.1 macallan /* 668 1.1 macallan * reg 16 apparently needs an address 0x10 less the where frame 669 1.1 macallan * buffer/ri_bits start for console text to be aligned. In 670 1.1 macallan * addition, X memory maps (mmap) the frame buffer starting on 671 1.1 macallan * page boundaries. So to get both X and console text aligned we 672 1.1 macallan * start at the first page up from sc_fb[0]. Starting at sc_fb[0] 673 1.1 macallan * did work on my machine but not sure if this negative offset 674 1.1 macallan * would be problematic elsewhere. 675 1.1 macallan * 676 1.1 macallan * Not sure why linux used different fb offsets for each mode, as 677 1.1 macallan * any addresses seemed to work as long as relative difference was 678 1.1 macallan * 0x10. 679 1.1 macallan */ 680 1.1 macallan platinumfb_write_reg(sc, 16, platinumfb_page_align_up(sc) - 0x10); 681 1.1 macallan 682 1.1 macallan platinumfb_write_reg(sc, 18, sc->sc_pfs->pitch[sc->sc_cmode]); 683 1.1 macallan 684 1.1 macallan /* 685 1.1 macallan * XXX register 19 setting looks wrong for 1 bank & 32 bpp. 686 1.1 macallan * 512x384 is only resolution that would use such a setting, but 687 1.1 macallan * that is not currently in videomodes.c 688 1.1 macallan */ 689 1.1 macallan if (sc->sc_cmode == PLATINUM_CMODE_32 && 690 1.1 macallan (sc->sc_pfs->macmode == 1 || sc->sc_pfs->macmode == 2)) 691 1.1 macallan aprint_error_dev(sc->sc_dev, 692 1.1 macallan "platinumfb reg19 array out-of-bounds"); 693 1.1 macallan 694 1.1 macallan platinumfb_write_reg(sc, 19, one_bank ? 695 1.1 macallan sc->sc_pfs->mode[sc->sc_cmode+1] : /* XXX fix this for 32 bpp */ 696 1.1 macallan sc->sc_pfs->mode[sc->sc_cmode]); 697 1.1 macallan 698 1.1 macallan platinumfb_write_reg(sc, 20, one_bank ? 0x11 : 0x1011); 699 1.1 macallan platinumfb_write_reg(sc, 21, 0x100); 700 1.1 macallan platinumfb_write_reg(sc, 22, 1); 701 1.1 macallan platinumfb_write_reg(sc, 23, 1); 702 1.1 macallan platinumfb_write_reg(sc, 26, 0xc00); 703 1.1 macallan platinumfb_write_reg(sc, 27, 0x235); 704 1.1 macallan /* platinumfb_write_reg(sc, 27, 0x2aa); */ 705 1.1 macallan 706 1.1 macallan platinumfb_store_d2(sc, 0, 707 1.1 macallan one_bank ? sc->sc_pfs->dacula_ctrl[sc->sc_cmode] & 0xf : 708 1.1 macallan sc->sc_pfs->dacula_ctrl[sc->sc_cmode]); 709 1.1 macallan platinumfb_store_d2(sc, 1, 4); 710 1.1 macallan platinumfb_store_d2(sc, 2, 0); 711 1.1 macallan 712 1.1 macallan platinumfb_set_clock(sc); 713 1.1 macallan 714 1.1 macallan platinumfb_write_reg(sc, 24, 0); /* turn display on */ 715 1.1 macallan } 716 1.1 macallan 717 1.1 macallan static int 718 1.1 macallan platinumfb_set_mode(struct platinumfb_softc *sc, 719 1.1 macallan const struct videomode *mode, int depth) 720 1.1 macallan { 721 1.1 macallan int i; 722 1.1 macallan 723 1.1 macallan /* first find the parameter for the mode register */ 724 1.1 macallan i = 0; 725 1.1 macallan while((i < __arraycount(pfb_setting)) && 726 1.1 macallan (strcmp(mode->name, pfb_setting[i]->vmode_name) != 0)) 727 1.1 macallan i++; 728 1.1 macallan 729 1.1 macallan if (i >= __arraycount(pfb_setting)) { 730 1.1 macallan aprint_error_dev(sc->sc_dev, 731 1.1 macallan "Can't find a mode register value for %s\n", 732 1.1 macallan mode->name); 733 1.1 macallan return EINVAL; 734 1.1 macallan } 735 1.1 macallan 736 1.1 macallan /* found a mode */ 737 1.1 macallan sc->sc_pfs = pfb_setting[i]; 738 1.1 macallan 739 1.1 macallan /* determine depth settings */ 740 1.1 macallan switch (depth) { 741 1.1 macallan case 8: 742 1.1 macallan default: 743 1.1 macallan sc->sc_depth = 8; 744 1.1 macallan sc->sc_cmode = PLATINUM_CMODE_8; 745 1.1 macallan break; 746 1.1 macallan case 15: 747 1.1 macallan case 16: 748 1.1 macallan /* 15 bpp but use 16 so X/wsfb works */ 749 1.1 macallan sc->sc_depth = 16; 750 1.1 macallan sc->sc_cmode = PLATINUM_CMODE_16; 751 1.1 macallan break; 752 1.1 macallan case 24: 753 1.1 macallan case 32: 754 1.1 macallan /* 24 bpp but use 32 so X/wsfb works */ 755 1.1 macallan sc->sc_depth = 32; 756 1.1 macallan sc->sc_cmode = PLATINUM_CMODE_32; 757 1.1 macallan break; 758 1.1 macallan } 759 1.1 macallan 760 1.1 macallan sc->sc_modereg = sc->sc_pfs->macmode; 761 1.1 macallan sc->sc_videomode = mode; 762 1.1 macallan sc->sc_height = mode->vdisplay; 763 1.1 macallan sc->sc_width = mode->hdisplay; 764 1.1 macallan sc->sc_linebytes = sc->sc_width * (1 << sc->sc_cmode) + platinumfb_line_tweak(sc); 765 1.1 macallan 766 1.1 macallan /* check if we have enough video memory */ 767 1.1 macallan if (sc->sc_height * sc->sc_linebytes > sc->sc_vram - PAGE_SIZE) { 768 1.1 macallan aprint_error_dev(sc->sc_dev, "Not enough video RAM for %s\n", 769 1.1 macallan mode->name); 770 1.1 macallan return EINVAL; 771 1.1 macallan } 772 1.1 macallan 773 1.1 macallan /* set up and write colormap */ 774 1.1 macallan platinumfb_init_cmap(sc); 775 1.1 macallan platinumfb_restore_palette(sc); 776 1.1 macallan 777 1.1 macallan /* set hardware registers */ 778 1.1 macallan platinumfb_set_hardware(sc); 779 1.1 macallan 780 1.1 macallan aprint_normal_dev(sc->sc_dev, "switched to %s in %d bit color\n", 781 1.1 macallan sc->sc_pfs->vmode_name, sc->sc_depth); 782 1.1 macallan return 0; 783 1.1 macallan } 784 1.1 macallan 785 1.1 macallan static int 786 1.1 macallan platinumfb_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, 787 1.1 macallan struct lwp *l) 788 1.1 macallan { 789 1.1 macallan struct vcons_data *vd = v; 790 1.1 macallan struct platinumfb_softc *sc = vd->cookie; 791 1.1 macallan struct wsdisplay_fbinfo *wdf; 792 1.1 macallan struct vcons_screen *ms = vd->active; 793 1.1 macallan int i; 794 1.1 macallan 795 1.1 macallan switch (cmd) { 796 1.1 macallan case WSDISPLAYIO_GTYPE: 797 1.1 macallan *(u_int *)data = WSDISPLAY_TYPE_PLATINUM; 798 1.1 macallan return 0; 799 1.1 macallan 800 1.1 macallan case WSDISPLAYIO_GINFO: 801 1.1 macallan wdf = (void *)data; 802 1.1 macallan wdf->height = ms->scr_ri.ri_height; 803 1.1 macallan wdf->width = ms->scr_ri.ri_width; 804 1.1 macallan wdf->depth = ms->scr_ri.ri_depth; 805 1.1 macallan wdf->cmsize = 256; 806 1.1 macallan return 0; 807 1.1 macallan 808 1.1 macallan case WSDISPLAYIO_GVIDEO: 809 1.1 macallan *(int *)data = sc->sc_on; 810 1.1 macallan return 0; 811 1.1 macallan 812 1.1 macallan case WSDISPLAYIO_SVIDEO: 813 1.1 macallan /* 814 1.1 macallan * poor man's screen blanking, just write zeros to colormap 815 1.1 macallan * registers but don't save in softc. 816 1.1 macallan */ 817 1.1 macallan if (*(int *)data != sc->sc_on) { 818 1.1 macallan sc->sc_on = (sc->sc_on == WSDISPLAYIO_VIDEO_ON ? 819 1.1 macallan WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON); 820 1.1 macallan 821 1.1 macallan /* XXX need to lock colormap? */ 822 1.1 macallan if (sc->sc_on == WSDISPLAYIO_VIDEO_OFF) { 823 1.1 macallan for (i=0; i < 256; i++) 824 1.1 macallan platinumfb_putpalreg(sc, i, 0, 0, 0); 825 1.1 macallan } else { 826 1.1 macallan platinumfb_restore_palette(sc); 827 1.1 macallan } 828 1.1 macallan } 829 1.1 macallan return 0; 830 1.1 macallan 831 1.1 macallan case WSDISPLAYIO_GETCMAP: 832 1.1 macallan if (sc->sc_cmode == PLATINUM_CMODE_8) { 833 1.1 macallan return platinumfb_getcmap(sc, 834 1.1 macallan (struct wsdisplay_cmap *)data); 835 1.1 macallan } else 836 1.1 macallan return 0; 837 1.1 macallan 838 1.1 macallan case WSDISPLAYIO_PUTCMAP: 839 1.1 macallan if (sc->sc_cmode == PLATINUM_CMODE_8) { 840 1.1 macallan return platinumfb_putcmap(sc, 841 1.1 macallan (struct wsdisplay_cmap *)data); 842 1.1 macallan } else 843 1.1 macallan return 0; 844 1.1 macallan 845 1.1 macallan case WSDISPLAYIO_SMODE: { 846 1.1 macallan int new_mode = *(int*)data; 847 1.1 macallan 848 1.1 macallan if (new_mode != sc->sc_mode) { 849 1.1 macallan int new_depth = new_mode == WSDISPLAYIO_MODE_EMUL ? 850 1.1 macallan PLATINUM_CONSOLE_DEPTH : PLATINUM_FB_DEPTH; 851 1.1 macallan 852 1.1 macallan switch(new_mode) { 853 1.1 macallan /* 854 1.1 macallan * XXX - not sure how this is supposed to work for 855 1.1 macallan * switching bpp between console and X, but cases with 856 1.1 macallan * (EMUL MAPPED) or (EMUL MAPPED DUMBFB) work, but 857 1.1 macallan * (EMUL DUMBFB) garbles screen for some reason. 858 1.1 macallan */ 859 1.1 macallan case WSDISPLAYIO_MODE_EMUL: 860 1.1 macallan case WSDISPLAYIO_MODE_MAPPED: 861 1.1 macallan /* case WSDISPLAYIO_MODE_DUMBFB: XXX */ 862 1.1 macallan 863 1.1 macallan /* in case screen is "blanked" */ 864 1.1 macallan platinumfb_restore_palette(sc); 865 1.1 macallan 866 1.1 macallan sc->sc_mode = new_mode; 867 1.1 macallan 868 1.1 macallan platinumfb_set_mode(sc, sc->sc_videomode, new_depth); 869 1.1 macallan platinumfb_set_rasops(sc, &ms->scr_ri, true); 870 1.1 macallan 871 1.1 macallan if (new_mode == WSDISPLAYIO_MODE_EMUL) 872 1.1 macallan vcons_redraw_screen(ms); 873 1.1 macallan } 874 1.1 macallan } 875 1.1 macallan 876 1.1 macallan return 0; 877 1.1 macallan } 878 1.1 macallan 879 1.1 macallan case WSDISPLAYIO_LINEBYTES: 880 1.1 macallan *(u_int *)data = sc->sc_linebytes; 881 1.1 macallan return 0; 882 1.1 macallan 883 1.1 macallan case WSDISPLAYIO_GET_FBINFO: { 884 1.1 macallan struct wsdisplayio_fbinfo *fbi = data; 885 1.1 macallan return wsdisplayio_get_fbinfo(&ms->scr_ri, fbi); 886 1.1 macallan } 887 1.1 macallan 888 1.1 macallan } 889 1.1 macallan return EPASSTHROUGH; 890 1.1 macallan } 891 1.1 macallan 892 1.1 macallan static paddr_t 893 1.1 macallan platinumfb_mmap(void *v, void *vs, off_t offset, int prot) 894 1.1 macallan { 895 1.1 macallan struct vcons_data *vd = v; 896 1.1 macallan struct platinumfb_softc *sc = vd->cookie; 897 1.1 macallan paddr_t pa = -1; 898 1.1 macallan paddr_t fb_aligned = platinumfb_page_align_up(sc); 899 1.1 macallan paddr_t fb_vram = sc->sc_vram - (fb_aligned - (paddr_t)sc->sc_fb); 900 1.1 macallan 901 1.1 macallan /* XXX need to worry about superuser or mapping other registers? */ 902 1.1 macallan 903 1.1 macallan if (offset >= 0 && offset < fb_vram) 904 1.1 macallan pa = fb_aligned + offset; 905 1.1 macallan 906 1.1 macallan return pa; 907 1.1 macallan } 908 1.1 macallan 909 1.1 macallan static void platinumfb_set_rasops(struct platinumfb_softc *sc, 910 1.1 macallan struct rasops_info *ri, 911 1.1 macallan int existing) 912 1.1 macallan { 913 1.1 macallan memset(ri, 0, sizeof(struct rasops_info)); 914 1.1 macallan 915 1.1 macallan ri->ri_depth = sc->sc_depth; 916 1.1 macallan ri->ri_width = sc->sc_width; 917 1.1 macallan ri->ri_height = sc->sc_height; 918 1.1 macallan ri->ri_stride = sc->sc_linebytes; 919 1.1 macallan ri->ri_bits = (u_char*)platinumfb_page_align_up(sc); 920 1.1 macallan ri->ri_flg = RI_FULLCLEAR; 921 1.1 macallan 922 1.1 macallan if (existing) 923 1.1 macallan ri->ri_flg |= RI_CLEAR; 924 1.1 macallan 925 1.1 macallan switch (sc->sc_cmode) { 926 1.1 macallan case PLATINUM_CMODE_8: 927 1.1 macallan default: 928 1.1 macallan ri->ri_flg |= RI_ENABLE_ALPHA | RI_8BIT_IS_RGB; 929 1.1 macallan 930 1.1 macallan break; 931 1.1 macallan case PLATINUM_CMODE_16: 932 1.1 macallan if (strcmp(sc->sc_pfs->vmode_name, "640x480x60") == 0 || 933 1.1 macallan strcmp(sc->sc_pfs->vmode_name, "800x600x75") == 0 ) 934 1.1 macallan ri->ri_flg |= RI_ENABLE_ALPHA; 935 1.1 macallan 936 1.1 macallan ri->ri_rnum = 5; 937 1.1 macallan ri->ri_rpos = 10; 938 1.1 macallan ri->ri_gnum = 5; 939 1.1 macallan ri->ri_gpos = 5; 940 1.1 macallan ri->ri_bnum = 5; 941 1.1 macallan ri->ri_bpos = 0; 942 1.1 macallan 943 1.1 macallan break; 944 1.1 macallan case PLATINUM_CMODE_32: 945 1.1 macallan if (strcmp(sc->sc_pfs->vmode_name, "640x480x60") == 0 || 946 1.1 macallan strcmp(sc->sc_pfs->vmode_name, "800x600x75") == 0 ) 947 1.1 macallan ri->ri_flg |= RI_ENABLE_ALPHA; 948 1.1 macallan 949 1.1 macallan ri->ri_rnum = 8; 950 1.1 macallan ri->ri_rpos = 16; 951 1.1 macallan ri->ri_gnum = 8; 952 1.1 macallan ri->ri_gpos = 8; 953 1.1 macallan ri->ri_bnum = 8; 954 1.1 macallan ri->ri_bpos = 0; 955 1.1 macallan 956 1.1 macallan break; 957 1.1 macallan } 958 1.1 macallan 959 1.1 macallan rasops_init(ri, 0, 0); 960 1.1 macallan ri->ri_caps = WSSCREEN_WSCOLORS; 961 1.1 macallan 962 1.1 macallan rasops_reconfig(ri, sc->sc_height / ri->ri_font->fontheight, 963 1.1 macallan sc->sc_width / ri->ri_font->fontwidth); 964 1.1 macallan 965 1.1 macallan } 966 1.1 macallan 967 1.1 macallan static void 968 1.1 macallan platinumfb_init_screen(void *cookie, struct vcons_screen *scr, 969 1.1 macallan int existing, long *defattr) 970 1.1 macallan { 971 1.1 macallan struct platinumfb_softc *sc = cookie; 972 1.1 macallan struct rasops_info *ri = &scr->scr_ri; 973 1.1 macallan 974 1.1 macallan scr->scr_flags |= VCONS_DONT_READ; 975 1.1 macallan 976 1.1 macallan platinumfb_set_rasops(sc, ri, existing); 977 1.1 macallan 978 1.1 macallan ri->ri_hw = scr; 979 1.1 macallan } 980 1.1 macallan 981 1.1 macallan static int 982 1.1 macallan platinumfb_putcmap(struct platinumfb_softc *sc, struct wsdisplay_cmap *cm) 983 1.1 macallan { 984 1.1 macallan u_char *r, *g, *b; 985 1.1 macallan u_int index = cm->index; 986 1.1 macallan u_int count = cm->count; 987 1.1 macallan int i, error; 988 1.1 macallan u_char rbuf[256], gbuf[256], bbuf[256]; 989 1.1 macallan 990 1.1 macallan if (cm->index >= 256 || cm->count > 256 || 991 1.1 macallan (cm->index + cm->count) > 256) 992 1.1 macallan return EINVAL; 993 1.1 macallan error = copyin(cm->red, &rbuf[index], count); 994 1.1 macallan if (error) 995 1.1 macallan return error; 996 1.1 macallan error = copyin(cm->green, &gbuf[index], count); 997 1.1 macallan if (error) 998 1.1 macallan return error; 999 1.1 macallan error = copyin(cm->blue, &bbuf[index], count); 1000 1.1 macallan if (error) 1001 1.1 macallan return error; 1002 1.1 macallan 1003 1.1 macallan memcpy(&sc->sc_cmap_red[index], &rbuf[index], count); 1004 1.1 macallan memcpy(&sc->sc_cmap_green[index], &gbuf[index], count); 1005 1.1 macallan memcpy(&sc->sc_cmap_blue[index], &bbuf[index], count); 1006 1.1 macallan 1007 1.1 macallan /* write colormap registers if not currently blanked */ 1008 1.1 macallan if (sc->sc_on == WSDISPLAYIO_VIDEO_ON) { 1009 1.1 macallan r = &sc->sc_cmap_red[index]; 1010 1.1 macallan g = &sc->sc_cmap_green[index]; 1011 1.1 macallan b = &sc->sc_cmap_blue[index]; 1012 1.1 macallan 1013 1.1 macallan for (i = 0; i < count; i++) { 1014 1.1 macallan platinumfb_putpalreg(sc, index, *r, *g, *b); 1015 1.1 macallan index++; 1016 1.1 macallan r++, g++, b++; 1017 1.1 macallan } 1018 1.1 macallan } 1019 1.1 macallan 1020 1.1 macallan return 0; 1021 1.1 macallan } 1022 1.1 macallan 1023 1.1 macallan static int 1024 1.1 macallan platinumfb_getcmap(struct platinumfb_softc *sc, struct wsdisplay_cmap *cm) 1025 1.1 macallan { 1026 1.1 macallan u_int index = cm->index; 1027 1.1 macallan u_int count = cm->count; 1028 1.1 macallan int error; 1029 1.1 macallan 1030 1.1 macallan if (index >= 255 || count > 256 || index + count > 256) 1031 1.1 macallan return EINVAL; 1032 1.1 macallan 1033 1.1 macallan error = copyout(&sc->sc_cmap_red[index], cm->red, count); 1034 1.1 macallan if (error) 1035 1.1 macallan return error; 1036 1.1 macallan error = copyout(&sc->sc_cmap_green[index], cm->green, count); 1037 1.1 macallan if (error) 1038 1.1 macallan return error; 1039 1.1 macallan error = copyout(&sc->sc_cmap_blue[index], cm->blue, count); 1040 1.1 macallan if (error) 1041 1.1 macallan return error; 1042 1.1 macallan 1043 1.1 macallan return 0; 1044 1.1 macallan } 1045