1 /* $NetBSD: vidc20config.c,v 1.15 2002/10/01 12:09:49 reinoud Exp $ */ 2 3 /* 4 * Copyright (c) 2001 Reinoud Zandijk 5 * Copyright (c) 1996 Mark Brinicombe 6 * Copyright (c) 1996 Robert Black 7 * Copyright (c) 1994-1995 Melvyn Tang-Richardson 8 * Copyright (c) 1994-1995 RiscBSD kernel team 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the RiscBSD kernel team 22 * 4. The name of the company nor the name of the author may be used to 23 * endorse or promote products derived from this software without specific 24 * prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE RISCBSD TEAM ``AS IS'' AND ANY EXPRESS 27 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 28 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE 30 * 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 36 * THE POSSIBILITY OF SUCH DAMAGE. 37 * 38 * NetBSD kernel project 39 * 40 * vidcvideo.c 41 * 42 * This file is the lower basis of the wscons driver for VIDC based ARM machines. 43 * It features the initialisation and all VIDC writing and keeps in internal state 44 * copy. 45 * Its currenly set up as a library file and not as a device; it could be named 46 * vidcvideo0 eventually. 47 */ 48 49 #include <sys/cdefs.h> 50 51 __KERNEL_RCSID(0, "$NetBSD: vidc20config.c,v 1.15 2002/10/01 12:09:49 reinoud Exp $"); 52 53 #include <sys/types.h> 54 #include <sys/param.h> 55 #include <arm/iomd/vidc.h> 56 #include <arm/arm32/katelib.h> 57 #include <machine/bootconfig.h> 58 #include <machine/intr.h> 59 60 #include <sys/systm.h> 61 #include <sys/device.h> 62 #include <uvm/uvm_extern.h> 63 64 #include <arm/iomd/iomdreg.h> 65 #include <arm/iomd/iomdvar.h> 66 #include <arm/iomd/vidc20config.h> 67 68 69 /* 70 * A structure containing ALL the information required to restore 71 * the VIDC20 to any given state. ALL vidc transactions should 72 * go through these procedures, which record the vidc's state. 73 * it may be an idea to set the permissions of the vidc base address 74 * so we get a fault, so the fault routine can record the state but 75 * I guess that's not really necessary for the time being, since we 76 * can make the kernel more secure later on. Also, it is possible 77 * to write a routine to allow 'reading' of the vidc registers. 78 */ 79 80 static struct vidc_state vidc_lookup = { 81 { 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 82 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 83 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 84 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 85 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 86 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 87 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 88 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0 89 }, 90 91 VIDC_PALREG, 92 VIDC_BCOL, 93 VIDC_CP1 , 94 VIDC_CP2, 95 VIDC_CP3, 96 VIDC_HCR, 97 VIDC_HSWR, 98 VIDC_HBSR, 99 VIDC_HDSR, 100 VIDC_HDER, 101 VIDC_HBER, 102 VIDC_HCSR, 103 VIDC_HIR, 104 VIDC_VCR, 105 VIDC_VSWR, 106 VIDC_VBSR, 107 VIDC_VDSR, 108 VIDC_VDER, 109 VIDC_VBER, 110 VIDC_VCSR, 111 VIDC_VCER, 112 VIDC_EREG, 113 VIDC_FSYNREG, 114 VIDC_CONREG, 115 VIDC_DCTL 116 }; 117 118 struct vidc_state vidc_current[1]; 119 120 121 /* 122 * XXX global display variables XXX ... should be a structure 123 */ 124 static int cold_init = 0; /* flags initialisation */ 125 extern videomemory_t videomemory; 126 127 static struct vidc_mode vidc_initialmode; 128 static struct vidc_mode *vidc_currentmode; 129 130 unsigned int dispstart; 131 unsigned int dispsize; 132 unsigned int dispbase; 133 unsigned int dispend; 134 unsigned int ptov; 135 unsigned int vmem_base; 136 unsigned int phys_base; 137 unsigned int transfersize; 138 139 140 /* cursor stuff */ 141 char *cursor_normal; 142 char *cursor_transparent; 143 int p_cursor_normal; 144 int p_cursor_transparent; 145 int cursor_width; 146 int cursor_height; 147 148 149 /* 150 * VIDC mode definitions 151 * generated from RISC OS mode definition file by an `awk' script 152 */ 153 extern struct vidc_mode vidcmodes[]; 154 155 156 /* 157 * configuration printing 158 * 159 */ 160 161 void 162 vidcvideo_printdetails(void) 163 { 164 printf(": refclk=%dMHz %dKB %s ", (vidc_fref / 1000000), 165 videomemory.vidm_size / 1024, 166 (videomemory.vidm_type == VIDEOMEM_TYPE_VRAM) ? "VRAM" : "DRAM"); 167 } 168 169 170 /* 171 * Common functions to directly access VIDC registers 172 */ 173 int 174 vidcvideo_write(reg, value) 175 u_int reg; 176 int value; 177 { 178 int counter; 179 180 int *current; 181 int *tab; 182 183 tab = (int *)&vidc_lookup; 184 current = (int *)vidc_current; 185 186 187 /* 188 * OK, the VIDC_PALETTE register is handled differently 189 * to the others on the VIDC, so take that into account here 190 */ 191 if (reg==VIDC_PALREG) { 192 vidc_current->palreg = 0; 193 WriteWord(vidc_base, reg | value); 194 return 0; 195 } 196 197 if (reg==VIDC_PALETTE) { 198 WriteWord(vidc_base, reg | value); 199 vidc_current->palette[vidc_current->palreg] = value; 200 vidc_current->palreg++; 201 vidc_current->palreg = vidc_current->palreg & 0xff; 202 return 0; 203 } 204 205 /* 206 * Undefine SAFER if you wish to speed things up (a little) 207 * although this means the function will assume things abou 208 * the structure of vidc_state. i.e. the first 256 words are 209 * the palette array 210 */ 211 212 #define SAFER 213 214 #ifdef SAFER 215 #define INITVALUE 0 216 #else 217 #define INITVALUE 256 218 #endif 219 220 for ( counter=INITVALUE; counter<= sizeof(struct vidc_state); counter++ ) { 221 if ( reg==tab[counter] ) { 222 WriteWord ( vidc_base, reg | value ); 223 current[counter] = value; 224 return 0; 225 } 226 } 227 return -1; 228 } 229 230 231 void 232 vidcvideo_setpalette(vidc) 233 struct vidc_state *vidc; 234 { 235 int counter = 0; 236 237 vidcvideo_write(VIDC_PALREG, 0x00000000); 238 for (counter = 0; counter <= 255; counter++) 239 vidcvideo_write(VIDC_PALETTE, vidc->palette[counter]); 240 } 241 242 243 void 244 vidcvideo_setstate(vidc) 245 struct vidc_state *vidc; 246 { 247 vidcvideo_write ( VIDC_PALREG, vidc->palreg ); 248 vidcvideo_write ( VIDC_BCOL, vidc->bcol ); 249 vidcvideo_write ( VIDC_CP1, vidc->cp1 ); 250 vidcvideo_write ( VIDC_CP2, vidc->cp2 ); 251 vidcvideo_write ( VIDC_CP3, vidc->cp3 ); 252 vidcvideo_write ( VIDC_HCR, vidc->hcr ); 253 vidcvideo_write ( VIDC_HSWR, vidc->hswr ); 254 vidcvideo_write ( VIDC_HBSR, vidc->hbsr ); 255 vidcvideo_write ( VIDC_HDSR, vidc->hdsr ); 256 vidcvideo_write ( VIDC_HDER, vidc->hder ); 257 vidcvideo_write ( VIDC_HBER, vidc->hber ); 258 vidcvideo_write ( VIDC_HCSR, vidc->hcsr ); 259 vidcvideo_write ( VIDC_HIR, vidc->hir ); 260 vidcvideo_write ( VIDC_VCR, vidc->vcr ); 261 vidcvideo_write ( VIDC_VSWR, vidc->vswr ); 262 vidcvideo_write ( VIDC_VBSR, vidc->vbsr ); 263 vidcvideo_write ( VIDC_VDSR, vidc->vdsr ); 264 vidcvideo_write ( VIDC_VDER, vidc->vder ); 265 vidcvideo_write ( VIDC_VBER, vidc->vber ); 266 vidcvideo_write ( VIDC_VCSR, vidc->vcsr ); 267 vidcvideo_write ( VIDC_VCER, vidc->vcer ); 268 /* 269 * Right, dunno what to set these to yet, but let's keep RiscOS's 270 * ones for now, until the time is right to finish this code 271 */ 272 273 /* vidcvideo_write ( VIDC_EREG, vidc->ereg ); */ 274 /* vidcvideo_write ( VIDC_FSYNREG, vidc->fsynreg ); */ 275 /* vidcvideo_write ( VIDC_CONREG, vidc->conreg ); */ 276 /* vidcvideo_write ( VIDC_DCTL, vidc->dctl ); */ 277 278 vidcvideo_setpalette(vidc); 279 } 280 281 282 void 283 vidcvideo_getstate(vidc) 284 struct vidc_state *vidc; 285 { 286 *vidc = *vidc_current; 287 } 288 289 290 void 291 vidcvideo_getmode(mode) 292 struct vidc_mode *mode; 293 { 294 *mode = *vidc_currentmode; 295 } 296 297 298 static int 299 vidcvideo_coldinit(void) 300 { 301 int found; 302 int loop; 303 304 /* Blank out the cursor */ 305 306 vidcvideo_write(VIDC_CP1, 0x0); 307 vidcvideo_write(VIDC_CP2, 0x0); 308 vidcvideo_write(VIDC_CP3, 0x0); 309 310 /* Try to determine the current mode */ 311 vidc_initialmode.hder = bootconfig.width+1; 312 vidc_initialmode.vder = bootconfig.height+1; 313 vidc_initialmode.log2_bpp = bootconfig.log2_bpp; 314 315 dispbase = vmem_base = dispstart = videomemory.vidm_vbase; 316 phys_base = videomemory.vidm_pbase; 317 318 /* Nut - should be using videomemory.vidm_size - mark */ 319 if (videomemory.vidm_type == VIDEOMEM_TYPE_DRAM) { 320 dispsize = videomemory.vidm_size; 321 transfersize = 16; 322 } else { 323 dispsize = bootconfig.vram[0].pages * NBPG; 324 transfersize = dispsize >> 10; 325 }; 326 327 ptov = dispbase - phys_base; 328 329 dispend = dispstart+dispsize; 330 331 /* try to find the current mode from the bootloader in my table */ 332 vidc_currentmode = &vidcmodes[0]; 333 loop = 0; 334 found = 0; 335 while (vidcmodes[loop].pixel_rate != 0) { 336 if (vidcmodes[loop].hder == (bootconfig.width + 1) 337 && vidcmodes[loop].vder == (bootconfig.height + 1) 338 && vidcmodes[loop].frame_rate == bootconfig.framerate) { 339 vidc_currentmode = &vidcmodes[loop]; 340 found = 1; 341 } 342 ++loop; 343 } 344 345 /* if not found choose first mode but dont be picky on the framerate */ 346 if (!found) { 347 vidc_currentmode = &vidcmodes[0]; 348 loop = 0; 349 found = 0; 350 351 while (vidcmodes[loop].pixel_rate != 0) { 352 if (vidcmodes[loop].hder == (bootconfig.width + 1) 353 && vidcmodes[loop].vder == (bootconfig.height + 1)) { 354 vidc_currentmode = &vidcmodes[loop]; 355 found = 1; 356 } 357 ++loop; 358 } 359 } 360 361 vidc_currentmode->log2_bpp = bootconfig.log2_bpp; 362 363 dispstart = dispbase; 364 dispend = dispstart+dispsize; 365 366 IOMD_WRITE_WORD(IOMD_VIDINIT, dispstart-ptov); 367 IOMD_WRITE_WORD(IOMD_VIDSTART, dispstart-ptov); 368 IOMD_WRITE_WORD(IOMD_VIDEND, (dispend-transfersize)-ptov); 369 return 0; 370 } 371 372 373 /* simple function to abstract vidc variables ; returns virt start address of screen */ 374 /* XXX asumption that video memory is mapped in twice */ 375 void *vidcvideo_hwscroll(int bytes) { 376 dispstart += bytes; 377 if (dispstart >= dispbase + dispsize) dispstart -= dispsize; 378 if (dispstart < dispbase) dispstart += dispsize; 379 dispend = dispstart+dispsize; 380 381 /* return the start of the bit map of the screen (left top) */ 382 return (void *) dispstart; 383 } 384 385 386 /* reset the HW scroll to be at the start for the benefit of f.e. X */ 387 void *vidcvideo_hwscroll_reset(void) { 388 void *cookie = (void *) dispstart; 389 390 dispstart = dispbase; 391 dispend = dispstart + dispsize; 392 return cookie; 393 } 394 395 396 /* put HW scroll back to where it was */ 397 void *vidcvideo_hwscroll_back(void *cookie) { 398 dispstart = (int) cookie; 399 dispend = dispstart + dispsize; 400 return cookie; 401 } 402 403 404 /* this function is to be called perferably at vsync */ 405 void vidcvideo_progr_scroll(void) { 406 IOMD_WRITE_WORD(IOMD_VIDINIT, dispstart-ptov); 407 IOMD_WRITE_WORD(IOMD_VIDSTART, dispstart-ptov); 408 IOMD_WRITE_WORD(IOMD_VIDEND, (dispend-transfersize)-ptov); 409 } 410 411 412 /* 413 * Select a new mode by reprogramming the VIDC chip 414 * XXX this part is known not to work for 32bpp 415 */ 416 417 struct vidc_mode newmode; 418 419 static const int bpp_mask_table[] = { 420 0, /* 1bpp */ 421 1, /* 2bpp */ 422 2, /* 4bpp */ 423 3, /* 8bpp */ 424 4, /* 16bpp */ 425 6 /* 32bpp */ 426 }; 427 428 429 void 430 vidcvideo_setmode(struct vidc_mode *mode) 431 { 432 register int acc; 433 int bpp_mask; 434 int ereg; 435 int best_r, best_v; 436 int least_error; 437 int r, v, f; 438 439 /* 440 * Find out what bit mask we need to or with the vidc20 control register 441 * in order to generate the desired number of bits per pixel. 442 * log_bpp is log base 2 of the number of bits per pixel. 443 */ 444 445 bpp_mask = bpp_mask_table[mode->log2_bpp]; 446 447 newmode = *mode; 448 vidc_currentmode = &newmode; 449 450 least_error = INT_MAX; 451 best_r = 0; best_v = 0; 452 453 for (v = 63; v > 0; v--) { 454 for (r = 63; r > 0; r--) { 455 f = ((v * vidc_fref) /1000) / r; 456 if (least_error >= 457 abs(f - vidc_currentmode->pixel_rate)) { 458 least_error = 459 abs(f - vidc_currentmode->pixel_rate); 460 best_r = r; 461 best_v = v; 462 } 463 } 464 } 465 466 if (best_r > 63) best_r=63; 467 if (best_v > 63) best_v=63; 468 if (best_r < 1) best_r= 1; 469 if (best_v < 1) best_v= 1; 470 471 vidcvideo_write(VIDC_FSYNREG, (best_v-1)<<8 | (best_r-1)<<0); 472 473 acc=0; 474 acc+=vidc_currentmode->hswr; vidcvideo_write(VIDC_HSWR, (acc - 8 ) & (~1)); 475 acc+=vidc_currentmode->hbsr; vidcvideo_write(VIDC_HBSR, (acc - 12) & (~1)); 476 acc+=vidc_currentmode->hdsr; vidcvideo_write(VIDC_HDSR, (acc - 18) & (~1)); 477 acc+=vidc_currentmode->hder; vidcvideo_write(VIDC_HDER, (acc - 18) & (~1)); 478 acc+=vidc_currentmode->hber; vidcvideo_write(VIDC_HBER, (acc - 12) & (~1)); 479 acc+=vidc_currentmode->hcr; vidcvideo_write(VIDC_HCR, (acc - 8 ) & (~3)); 480 481 acc=0; 482 acc+=vidc_currentmode->vswr; vidcvideo_write(VIDC_VSWR, (acc - 1)); 483 acc+=vidc_currentmode->vbsr; vidcvideo_write(VIDC_VBSR, (acc - 1)); 484 acc+=vidc_currentmode->vdsr; vidcvideo_write(VIDC_VDSR, (acc - 1)); 485 acc+=vidc_currentmode->vder; vidcvideo_write(VIDC_VDER, (acc - 1)); 486 acc+=vidc_currentmode->vber; vidcvideo_write(VIDC_VBER, (acc - 1)); 487 acc+=vidc_currentmode->vcr; vidcvideo_write(VIDC_VCR, (acc - 1)); 488 489 IOMD_WRITE_WORD(IOMD_FSIZE, vidc_currentmode->vcr 490 + vidc_currentmode->vswr 491 + vidc_currentmode->vber 492 + vidc_currentmode->vbsr - 1); 493 494 if (dispsize <= 1024*1024) 495 vidcvideo_write(VIDC_DCTL, vidc_currentmode->hder>>2 | 1<<16 | 1<<12); 496 else 497 vidcvideo_write(VIDC_DCTL, vidc_currentmode->hder>>2 | 3<<16 | 1<<12); 498 499 ereg = 1<<12; 500 if (vidc_currentmode->sync_pol & 0x01) 501 ereg |= 1<<16; 502 if (vidc_currentmode->sync_pol & 0x02) 503 ereg |= 1<<18; 504 vidcvideo_write(VIDC_EREG, ereg); 505 if (dispsize > 1024*1024) { 506 if (vidc_currentmode->hder >= 800) 507 vidcvideo_write(VIDC_CONREG, 7<<8 | bpp_mask<<5); 508 else 509 vidcvideo_write(VIDC_CONREG, 6<<8 | bpp_mask<<5); 510 } else { 511 vidcvideo_write(VIDC_CONREG, 7<<8 | bpp_mask<<5); 512 } 513 } 514 515 516 #if 0 517 /* not used for now */ 518 void 519 vidcvideo_set_display_base(base) 520 u_int base; 521 { 522 dispstart = dispstart-dispbase + base; 523 dispbase = vmem_base = base; 524 dispend = base + dispsize; 525 ptov = dispbase - phys_base; 526 } 527 #endif 528 529 530 /* 531 * Main initialisation routine for now 532 */ 533 534 static int cursor_init = 0; 535 536 int 537 vidcvideo_init(void) 538 { 539 vidcvideo_coldinit(); 540 if (cold_init && (cursor_init == 0)) 541 /* vidcvideo_flash_go() */; 542 543 /* setting a mode goes wrong in 32 bpp ... 8 and 16 seem OK */ 544 vidcvideo_setmode(vidc_currentmode); 545 vidcvideo_blank(0); /* display on */ 546 547 vidcvideo_stdpalette(); 548 549 if (cold_init == 0) { 550 vidcvideo_write(VIDC_CP1, 0x0); 551 vidcvideo_write(VIDC_CP2, 0x0); 552 vidcvideo_write(VIDC_CP3, 0x0); 553 } else { 554 vidcvideo_cursor_init(CURSOR_MAX_WIDTH, CURSOR_MAX_HEIGHT); 555 }; 556 557 cold_init=1; 558 return 0; 559 } 560 561 562 /* reinitialise the vidcvideo */ 563 void 564 vidcvideo_reinit() 565 { 566 vidcvideo_coldinit(); 567 vidcvideo_setmode(vidc_currentmode); 568 } 569 570 571 int 572 vidcvideo_cursor_init(int width, int height) 573 { 574 static char *cursor_data = NULL; 575 int counter; 576 int line; 577 paddr_t pa; 578 579 cursor_width = width; 580 cursor_height = height; 581 582 if (!cursor_data) { 583 /* Allocate cursor memory first time round */ 584 cursor_data = (char *)uvm_km_zalloc(kernel_map, NBPG); 585 if (!cursor_data) 586 panic("Cannot allocate memory for hardware cursor"); 587 (void) pmap_extract(pmap_kernel(), (vaddr_t)cursor_data, &pa); 588 IOMD_WRITE_WORD(IOMD_CURSINIT, pa); 589 } 590 591 /* Blank the cursor while initialising it's sprite */ 592 593 vidcvideo_write ( VIDC_CP1, 0x0 ); 594 vidcvideo_write ( VIDC_CP2, 0x0 ); 595 vidcvideo_write ( VIDC_CP3, 0x0 ); 596 597 cursor_normal = cursor_data; 598 cursor_transparent = cursor_data + (height * width); 599 600 cursor_transparent += 32; /* ALIGN */ 601 cursor_transparent = (char *)((int)cursor_transparent & (~31) ); 602 603 for ( line = 0; line<height; ++ line ) 604 { 605 for ( counter=0; counter<width/4;counter++ ) 606 cursor_normal[line * width + counter]=0x55; /* why 0x55 ? */ 607 for ( ; counter<8; counter++ ) 608 cursor_normal[line * width + counter]=0; 609 } 610 611 for ( line = 0; line<height; ++ line ) 612 { 613 for ( counter=0; counter<width/4;counter++ ) 614 cursor_transparent[line * width + counter]=0x00; 615 for ( ; counter<8; counter++ ) 616 cursor_transparent[line * width + counter]=0; 617 } 618 619 620 (void) pmap_extract(pmap_kernel(), (vaddr_t)cursor_normal, 621 (paddr_t *)&p_cursor_normal); 622 (void) pmap_extract(pmap_kernel(), (vaddr_t)cursor_transparent, 623 (paddr_t *)&p_cursor_transparent); 624 625 memset ( cursor_normal, 0x55, width*height ); /* white? */ 626 memset ( cursor_transparent, 0x00, width*height ); /* to see the diffence */ 627 628 /* Ok, now program the cursor; should be blank */ 629 vidcvideo_enablecursor(0); 630 631 return 0; 632 } 633 634 635 void 636 vidcvideo_updatecursor(xcur, ycur) 637 int xcur, ycur; 638 { 639 int frontporch = vidc_currentmode->hswr + vidc_currentmode->hbsr + vidc_currentmode->hdsr; 640 int topporch = vidc_currentmode->vswr + vidc_currentmode->vbsr + vidc_currentmode->vdsr; 641 642 vidcvideo_write(VIDC_HCSR, frontporch -17 + xcur); 643 vidcvideo_write(VIDC_VCSR, topporch -2 + (ycur+1)-2 + 3 - cursor_height); 644 vidcvideo_write(VIDC_VCER, topporch -2 + (ycur+3)+2 + 3 ); 645 return; 646 } 647 648 649 void 650 vidcvideo_enablecursor(on) 651 int on; 652 { 653 if (on) { 654 IOMD_WRITE_WORD(IOMD_CURSINIT,p_cursor_normal); 655 } else { 656 IOMD_WRITE_WORD(IOMD_CURSINIT,p_cursor_transparent); 657 }; 658 vidcvideo_write ( VIDC_CP1, 0xffffff ); /* enable */ 659 660 return; 661 } 662 663 664 void 665 vidcvideo_stdpalette() 666 { 667 int i; 668 669 switch (vidc_currentmode->log2_bpp) { 670 case 0: /* 1 bpp */ 671 case 1: /* 2 bpp */ 672 case 2: /* 4 bpp */ 673 case 3: /* 8 bpp */ 674 vidcvideo_write(VIDC_PALREG, 0x00000000); 675 vidcvideo_write(VIDC_PALETTE, VIDC_COL( 0, 0, 0)); 676 vidcvideo_write(VIDC_PALETTE, VIDC_COL(255, 0, 0)); 677 vidcvideo_write(VIDC_PALETTE, VIDC_COL( 0, 255, 0)); 678 vidcvideo_write(VIDC_PALETTE, VIDC_COL(255, 255, 0)); 679 vidcvideo_write(VIDC_PALETTE, VIDC_COL( 0, 0, 255)); 680 vidcvideo_write(VIDC_PALETTE, VIDC_COL(255, 0, 255)); 681 vidcvideo_write(VIDC_PALETTE, VIDC_COL( 0, 255, 255)); 682 vidcvideo_write(VIDC_PALETTE, VIDC_COL(255, 255, 255)); 683 vidcvideo_write(VIDC_PALETTE, VIDC_COL(128, 128, 128)); 684 vidcvideo_write(VIDC_PALETTE, VIDC_COL(255, 128, 128)); 685 vidcvideo_write(VIDC_PALETTE, VIDC_COL(128, 255, 128)); 686 vidcvideo_write(VIDC_PALETTE, VIDC_COL(255, 255, 128)); 687 vidcvideo_write(VIDC_PALETTE, VIDC_COL(128, 128, 255)); 688 vidcvideo_write(VIDC_PALETTE, VIDC_COL(255, 128, 255)); 689 vidcvideo_write(VIDC_PALETTE, VIDC_COL(255, 255, 255)); 690 break; 691 case 4: /* 16 bpp */ 692 /* 693 * The use of the palette in 16-bit modes is quite 694 * fun. Comments in linux/drivers/video/acornfb.c 695 * imply that it goes something like this: 696 * 697 * red = LUT[pixel[7:0]].red 698 * green = LUT[pixel[11:4]].green 699 * blue = LUT[pixel[15:8]].blue 700 * 701 * We use 6:5:5 R:G:B cos that's what Xarm32VIDC wants. 702 */ 703 #define RBITS 6 704 #define GBITS 5 705 #define BBITS 5 706 vidcvideo_write(VIDC_PALREG, 0x00000000); 707 for (i = 0; i < 256; i++) { 708 int r, g, b; 709 710 r = i & ((1 << RBITS) - 1); 711 g = (i >> (RBITS - 4)) & ((1 << GBITS) - 1); 712 b = (i >> (RBITS + GBITS - 8)) & ((1 << BBITS) - 1); 713 vidcvideo_write(VIDC_PALETTE, 714 VIDC_COL(r << (8 - RBITS) | r >> (2 * RBITS - 8), 715 g << (8 - GBITS) | g >> (2 * GBITS - 8), 716 b << (8 - BBITS) | b >> (2 * BBITS - 8))); 717 } 718 break; 719 case 5: /* 32 bpp */ 720 vidcvideo_write(VIDC_PALREG, 0x00000000); 721 for (i = 0; i < 256; i++) 722 vidcvideo_write(VIDC_PALETTE, VIDC_COL(i, i, i)); 723 break; 724 } 725 726 } 727 728 int 729 vidcvideo_blank(video_off) 730 int video_off; 731 { 732 int ereg; 733 734 ereg = 1<<12; 735 if (vidc_currentmode->sync_pol & 0x01) 736 ereg |= 1<<16; 737 if (vidc_currentmode->sync_pol & 0x02) 738 ereg |= 1<<18; 739 740 if (!video_off) { 741 vidcvideo_write(VIDC_EREG, ereg); 742 } else { 743 vidcvideo_write(VIDC_EREG, 0); 744 }; 745 return 0; 746 } 747 748 /* end of vidc20config.c */ 749