1 /* $NetBSD: ga.c,v 1.3 2007/02/22 05:31:52 thorpej Exp $ */ 2 3 /*- 4 * Copyright (c) 2004, 2005 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by UCHIYAMA Yasushi. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 /* Graphic Adaptor (350, 360) */ 40 41 #include <sys/cdefs.h> 42 __KERNEL_RCSID(0, "$NetBSD: ga.c,v 1.3 2007/02/22 05:31:52 thorpej Exp $"); 43 44 #include <sys/param.h> 45 #include <sys/systm.h> 46 47 #ifdef _STANDALONE 48 #include <lib/libsa/stand.h> 49 #include <lib/libkern/libkern.h> 50 #include "local.h" 51 #endif 52 #ifdef _KERNEL 53 #include <uvm/uvm_extern.h> 54 #include <machine/vmparam.h> 55 #endif 56 #include <machine/gareg.h> 57 #include <machine/gavar.h> 58 59 bool ga_map(struct ga *); 60 void ga_clut_init(struct ga *); 61 void ga_vblank_start(const struct ga *); 62 void ga_bt463_reg(const struct ga *, int); 63 void ga_bt463_data(const struct ga *, int); 64 void ga_bt463_reg_data(const struct ga *, int, int); 65 #ifdef _STANDALONE 66 void ga_dda_busy(const struct ga *); 67 void ga_ovl_init(const struct ga *); 68 void ga_id_init(const struct ga *); 69 void ga_block_clear(const struct ga *); 70 void ga_plane_mask_test(const struct ga *); 71 #endif 72 73 #define ga_reg_write(ga, ofs, val) \ 74 (*(volatile uint32_t *)((ga)->reg_addr + (ofs)) = (val)) 75 #define ga_reg_read(ga, ofs) \ 76 (*(volatile uint32_t *)((ga)->reg_addr + (ofs))) 77 78 bool 79 ga_init(struct ga *ga) 80 { 81 int i; 82 83 /* Map GA register and buffers */ 84 if (ga->reg_addr == 0 && ga_map(ga) != 0) 85 return false; 86 87 /* This is 350 GA-ROM initialization sequence. */ 88 if (ga->flags == 0x0000) { 89 ga_bt463_reg_data(ga, 0x201, 0x40); 90 ga_bt463_reg_data(ga, 0x202, 0x40); 91 ga_bt463_reg_data(ga, 0x203, 92 ((ga_reg_read(ga, 0xe00) & 2) << 6) | 0x40); 93 } else if (ga->flags == 0x0001) { 94 ga_bt463_reg_data(ga, 0x201, 0x40); 95 ga_bt463_reg_data(ga, 0x202, 0); 96 ga_bt463_reg_data(ga, 0x203, 97 ((ga_reg_read(ga, 0xe00) & 2) << 6) | 0x40); 98 ga_bt463_reg_data(ga, 0x204, 0xff); /* Display ON/OFF ? */ 99 ga_bt463_reg_data(ga, 0x206, 0); 100 ga_bt463_reg_data(ga, 0x20a, 0); 101 } 102 103 /* Window type table */ 104 ga_bt463_reg(ga, 0x300); 105 for (i = 0; i < 16; i++) { 106 ga_bt463_data(ga, 0x00); 107 ga_bt463_data(ga, 0xe1); 108 ga_bt463_data(ga, 0x01); 109 } 110 111 ga_vblank_start(ga); 112 113 /* ??? */ 114 ga_bt463_reg(ga, 0x302); 115 for (i = 0; i < 2; i++) { 116 ga_bt463_data(ga, 0x00); 117 ga_bt463_data(ga, 0xe3); 118 ga_bt463_data(ga, 0x21); 119 } 120 121 /* Read mask P0-P7 */ 122 if (ga->flags != 0x0001) { 123 /* TR2A display blinks if this was done.. */ 124 ga_bt463_reg(ga, 0x205); 125 for (i = 0; i < 4; i++) 126 ga_bt463_data(ga, 0xff); 127 } 128 129 /* Blink mask P0-P7 */ 130 ga_bt463_reg(ga, 0x209); 131 for (i = 0; i < 4; i++) 132 ga_bt463_data(ga, 0x00); 133 134 ga_clut_init(ga); 135 136 /* ??? */ 137 ga_bt463_reg(ga, 0x200); 138 for (i = 0; i < 0xff; i++) { 139 ga_reg_write(ga, 0xc8c, 0); 140 ga_reg_write(ga, 0xc8c, 0); 141 ga_reg_write(ga, 0xc8c, 0); 142 } 143 144 if (ga_reg_read(ga, 0xe00) & 2) 145 ga_reg_write(ga, 0xe08, 0x790); /* 71Hz */ 146 else 147 ga_reg_write(ga, 0xe08, 0x670); /* 60Hz */ 148 #ifdef _STANDALONE 149 ga_block_clear(ga); 150 ga_ovl_init(ga); 151 ga_id_init(ga); 152 #endif 153 /* Cursor RAM clear */ 154 ga_reg_write(ga, 0xc90, 0); 155 ga_reg_write(ga, 0xc94, 0); 156 ga_reg_write(ga, 0xca0, 0); 157 ga_reg_write(ga, 0xca4, 0); 158 for (i = 0; i < 512; i++) { 159 ga_reg_write(ga, 0xc98, 0); 160 ga_reg_write(ga, 0xca8, 0); 161 } 162 163 return true; 164 } 165 166 bool 167 ga_map(struct ga *ga) 168 { 169 #ifdef _STANDALONE 170 /* IPL maps register region using 16Mpage */ 171 ga->reg_addr = GA_REG_ADDR; 172 #endif 173 #ifdef _KERNEL 174 paddr_t pa, epa; 175 vaddr_t va, tva; 176 177 pa = (paddr_t)GA_REG_ADDR; 178 epa = pa + GA_REG_SIZE; 179 180 if (!(va = uvm_km_alloc(kernel_map, epa - pa, 0, UVM_KMF_VAONLY))) { 181 printf("can't map GA register.\n"); 182 return false; 183 } 184 185 for (tva = va; pa < epa; pa += PAGE_SIZE, tva += PAGE_SIZE) 186 pmap_kenter_pa(tva, pa, VM_PROT_READ | VM_PROT_WRITE); 187 188 pmap_update(pmap_kernel()); 189 190 ga->reg_addr = (uint32_t)va; 191 #endif 192 193 return true; 194 } 195 196 void 197 ga_vblank_start(const struct ga *ga) 198 { 199 200 while ((ga_reg_read(ga, 0xe00) & 0x1) == 0) /* V-blank */ 201 ; 202 while ((ga_reg_read(ga, 0xe00) & 0x1) == 1) 203 ; 204 /* V-blank start */ 205 } 206 207 /* Bt463 utils */ 208 void 209 ga_bt463_reg(const struct ga *ga, int r) 210 { 211 212 ga_reg_write(ga, 0xc80, r & 0xff); 213 ga_reg_write(ga, 0xc84, (r >> 8) & 0xff); 214 } 215 216 void 217 ga_bt463_data(const struct ga *ga, int v) 218 { 219 220 ga_reg_write(ga, 0xc88, v & 0xff); 221 } 222 223 void 224 ga_bt463_reg_data(const struct ga *ga, int r, int v) 225 { 226 227 ga_bt463_reg(ga, r); 228 ga_bt463_data(ga, v); 229 } 230 231 /* CLUT */ 232 void 233 ga_clut_init(struct ga *ga) 234 { 235 const uint8_t compo6[6] = { 0, 51, 102, 153, 204, 255 }; 236 const uint8_t ansi_color[16][3] = { 237 { 0x00, 0x00, 0x00 }, 238 { 0xff, 0x00, 0x00 }, 239 { 0x00, 0xff, 0x00 }, 240 { 0xff, 0xff, 0x00 }, 241 { 0x00, 0x00, 0xff }, 242 { 0xff, 0x00, 0xff }, 243 { 0x00, 0xff, 0xff }, 244 { 0xff, 0xff, 0xff }, 245 { 0x00, 0x00, 0x00 }, 246 { 0x80, 0x00, 0x00 }, 247 { 0x00, 0x80, 0x00 }, 248 { 0x80, 0x80, 0x00 }, 249 { 0x00, 0x00, 0x80 }, 250 { 0x80, 0x00, 0x80 }, 251 { 0x00, 0x80, 0x80 }, 252 { 0x80, 0x80, 0x80 }, 253 }; 254 int i, j, r, g, b; 255 256 ga_bt463_reg(ga, 0); 257 /* ANSI escape sequence */ 258 for (i = 0; i < 16; i++) { 259 ga_reg_write(ga, 0xc8c, ga->clut[i][0] = ansi_color[i][0]); 260 ga_reg_write(ga, 0xc8c, ga->clut[i][1] = ansi_color[i][1]); 261 ga_reg_write(ga, 0xc8c, ga->clut[i][2] = ansi_color[i][2]); 262 } 263 264 /* 16 - 31, gray scale */ 265 for ( ; i < 32; i++) { 266 j = (i - 16) * 17; 267 ga_reg_write(ga, 0xc8c, ga->clut[i][0] = j); 268 ga_reg_write(ga, 0xc8c, ga->clut[i][1] = j); 269 ga_reg_write(ga, 0xc8c, ga->clut[i][2] = j); 270 } 271 272 /* 32 - 247, RGB color */ 273 for (r = 0; r < 6; r++) { 274 for (g = 0; g < 6; g++) { 275 for (b = 0; b < 6; b++, i++) { 276 ga_reg_write(ga, 0xc8c, 277 ga->clut[i][0] = compo6[r]); 278 ga_reg_write(ga, 0xc8c, 279 ga->clut[i][1] = compo6[g]); 280 ga_reg_write(ga, 0xc8c, 281 ga->clut[i][2] = compo6[b]); 282 } 283 } 284 } 285 286 /* 248 - 256, white */ 287 for ( ; i < 256; i++) { 288 ga_reg_write(ga, 0xc8c, ga->clut[i][0] = 0xff); 289 ga_reg_write(ga, 0xc8c, ga->clut[i][1] = 0xff); 290 ga_reg_write(ga, 0xc8c, ga->clut[i][2] = 0xff); 291 } 292 293 /* 257 - 528, black */ 294 for ( ; i < 528; i++) { 295 ga_reg_write(ga, 0xc8c, 0); 296 ga_reg_write(ga, 0xc8c, 0); 297 ga_reg_write(ga, 0xc8c, 0); 298 } 299 } 300 301 void 302 ga_clut_get(struct ga *ga) 303 { 304 int i; 305 306 ga_bt463_reg(ga, 0); 307 for (i = 0; i < 256; i++) { 308 ga->clut[i][0] = ga_reg_read(ga, 0xc8c); 309 ga->clut[i][1] = ga_reg_read(ga, 0xc8c); 310 ga->clut[i][2] = ga_reg_read(ga, 0xc8c); 311 } 312 } 313 314 void 315 ga_clut_set(const struct ga *ga) 316 { 317 int i; 318 319 ga_bt463_reg(ga, 0); 320 for (i = 0; i < 256; i++) { 321 ga_reg_write(ga, 0xc8c, ga->clut[i][0]); 322 ga_reg_write(ga, 0xc8c, ga->clut[i][1]); 323 ga_reg_write(ga, 0xc8c, ga->clut[i][2]); 324 } 325 } 326 327 /* Not yet analyzed. */ 328 #ifdef _STANDALONE 329 void 330 ga_dda_busy(const struct ga *ga) 331 { 332 333 while ((ga_reg_read(ga, 0xf00) & 0x8000) == 0) 334 ; 335 } 336 337 void 338 ga_ovl_init(const struct ga *ga) 339 { 340 uint32_t *p0, *p1; 341 342 ga_reg_write(ga, 0x400, 0xffffffff); 343 p0 = (uint32_t *)0xf2000000; 344 p1 = (uint32_t *)0xf2200000; 345 while (p0 < p1) 346 *p0++ = 0; 347 } 348 349 void 350 ga_id_init(const struct ga *ga) 351 { 352 uint32_t *p0, *p1; 353 354 p0 = (uint32_t *)0xf3000000; 355 p1 = (uint32_t *)0xf3040000; 356 while (p0 < p1) 357 *p0++ = 0; 358 } 359 360 void 361 ga_block_clear(const struct ga *ga) 362 { 363 uint32_t *p0, *p1; 364 365 ga_reg_write(ga, 0xe80, 0); 366 ga_reg_write(ga, 0x400, 0xffffff); 367 368 p0 = (uint32_t *)0xf0c00000; 369 p1 = (uint32_t *)0xf0c80000; 370 while (p0 < p1) 371 *p0++ = 0xffffffff; 372 } 373 374 void 375 ga_plane_mask_test(const struct ga *ga) 376 { 377 int i; 378 379 ga_reg_write(ga, 0x400, 0xffffff); 380 *(volatile uint32_t *)0xf1000000 = 0; 381 382 ga_reg_write(ga, 0x400, 0xaaaaaa); 383 *(volatile uint32_t *)0xf1000000 = 0xffffff; 384 385 if ((*(volatile uint32_t *)0xf1000000 & 0xffffff) != 0xaaaaaa) 386 goto err; 387 ga_reg_write(ga, 0x400, 0xffffff); 388 *(volatile uint32_t *)0xf1000000 = 0; 389 390 391 *(volatile uint32_t *)0xf1080008 = 0; 392 ga_reg_write(ga, 0x400, 0x555555); 393 *(volatile uint32_t *)0xf1080008 = 0xffffff; 394 if ((*(volatile uint32_t *)0xf1080008 & 0xffffff) != 0x555555) 395 goto err; 396 ga_reg_write(ga, 0x400, 0xffffff); 397 *(volatile uint32_t *)0xf1080008 = 0; 398 399 *(volatile uint32_t *)0xf1100000 = 0; 400 *(volatile uint32_t *)0xf1100000 = 0xffffff; 401 if ((*(volatile uint32_t *)0xf1100000 & 0xffffff) != 0xffffff) 402 goto err; 403 404 ga_reg_write(ga, 0x400, 0xaaaaaa); 405 *(volatile uint32_t *)0xf1100000 = 0; 406 if ((*(volatile uint32_t *)0xf1100000 & 0xffffff) != 0x555555) 407 goto err; 408 409 ga_reg_write(ga, 0x400, 0); 410 *(volatile uint32_t *)0xf1100000 = 0xffffff; 411 if ((*(volatile uint32_t *)0xf1100000 & 0xffffff) != 0x555555) 412 goto err; 413 414 ga_reg_write(ga, 0x400, 0xffffff); 415 *(volatile uint32_t *)0xf1100000 = 0; 416 417 ga_reg_write(ga, 0xe80, 0xffffff); 418 ga_reg_write(ga, 0x400, 0xffffff); 419 *(volatile uint32_t *)0xf0c00000 = 0xffffffff; 420 for (i = 0; i < 32; i++) 421 if ((*(volatile uint32_t *)(0xf1000000 + i * 4) & 0xffffff) != 422 0xffffff) 423 goto err; 424 425 ga_reg_write(ga, 0xe80, 0); 426 ga_reg_write(ga, 0x400, 0xaaaaaa); 427 *(volatile uint32_t *)0xf0c00000 = 0xffffffff; 428 for (i = 0; i < 32; i++) 429 if ((*(volatile uint32_t *)(0xf1000000 + i * 4) & 0xffffff) != 430 0x555555) 431 goto err; 432 ga_reg_write(ga, 0x400, 0x555555); 433 *(volatile uint32_t *)0xf0c00000 = 0xffffffff; 434 for (i = 0; i < 32; i++) 435 if ((*(volatile uint32_t *)(0xf1000000 + i * 4) & 0xffffff) != 436 0x0) 437 goto err; 438 439 printf("SUCCESS\n"); 440 return; 441 err: 442 printf("ERROR\n"); 443 } 444 #endif /* _STANDALONE */ 445