1 /* $NetBSD: vidc20config.c,v 1.37 2024/05/18 19:04:45 andvar 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 currently 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.37 2024/05/18 19:04:45 andvar Exp $"); 52 53 #include <sys/types.h> 54 #include <sys/param.h> 55 #include <arm/iomd/vidc.h> 56 #include <machine/bootconfig.h> 57 #include <machine/intr.h> 58 59 #include <sys/systm.h> 60 #include <sys/device.h> 61 #include <uvm/uvm_extern.h> 62 63 #include <arm/iomd/iomdreg.h> 64 #include <arm/iomd/iomdvar.h> 65 #include <arm/iomd/vidc20config.h> 66 67 #define WriteWord(a, b) \ 68 *((volatile unsigned int *)(a)) = (b) 69 70 #define ReadWord(a) \ 71 (*((volatile unsigned int *)(a))) 72 73 /* 74 * A structure containing ALL the information required to restore 75 * the VIDC20 to any given state. ALL vidc transactions should 76 * go through these procedures, which record the vidc's state. 77 * it may be an idea to set the permissions of the vidc base address 78 * so we get a fault, so the fault routine can record the state but 79 * I guess that's not really necessary for the time being, since we 80 * can make the kernel more secure later on. Also, it is possible 81 * to write a routine to allow 'reading' of the vidc registers. 82 */ 83 84 static struct vidc_state vidc_lookup = { 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 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, 90 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, 91 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, 92 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 93 }, 94 95 VIDC_PALREG, 96 VIDC_BCOL, 97 VIDC_CP1 , 98 VIDC_CP2, 99 VIDC_CP3, 100 VIDC_HCR, 101 VIDC_HSWR, 102 VIDC_HBSR, 103 VIDC_HDSR, 104 VIDC_HDER, 105 VIDC_HBER, 106 VIDC_HCSR, 107 VIDC_HIR, 108 VIDC_VCR, 109 VIDC_VSWR, 110 VIDC_VBSR, 111 VIDC_VDSR, 112 VIDC_VDER, 113 VIDC_VBER, 114 VIDC_VCSR, 115 VIDC_VCER, 116 VIDC_EREG, 117 VIDC_FSYNREG, 118 VIDC_CONREG, 119 VIDC_DCTL 120 }; 121 122 struct vidc_state vidc_current[1]; 123 124 125 /* 126 * XXX global display variables XXX ... should be a structure 127 */ 128 static int cold_init = 0; /* flags initialisation */ 129 extern videomemory_t videomemory; 130 131 static struct vidc_mode vidc_currentmode; 132 133 unsigned int dispstart; 134 unsigned int dispsize; 135 unsigned int dispbase; 136 unsigned int dispend; 137 unsigned int ptov; 138 unsigned int vmem_base; 139 unsigned int phys_base; 140 unsigned int transfersize; 141 142 143 /* cursor stuff */ 144 char *cursor_normal; 145 char *cursor_transparent; 146 int p_cursor_normal; 147 int p_cursor_transparent; 148 int cursor_width; 149 int cursor_height; 150 151 152 /* 153 * VIDC mode definitions 154 * generated from RISC OS mode definition file by an `awk' script 155 */ 156 extern const struct videomode vidc_videomode_list[]; 157 extern const int vidc_videomode_count; 158 159 160 /* 161 * configuration printing 162 * 163 */ 164 165 void 166 vidcvideo_printdetails(void) 167 { 168 printf(": refclk=%dMHz %dKB %s ", (vidc_fref / 1000000), 169 videomemory.vidm_size / 1024, 170 (videomemory.vidm_type == VIDEOMEM_TYPE_VRAM) ? "VRAM" : "DRAM"); 171 } 172 173 174 /* 175 * Common functions to directly access VIDC registers 176 */ 177 int 178 vidcvideo_write(u_int reg, int value) 179 { 180 int counter; 181 182 int *current; 183 int *tab; 184 185 tab = (int *)&vidc_lookup; 186 current = (int *)vidc_current; 187 188 189 /* 190 * OK, the VIDC_PALETTE register is handled differently 191 * to the others on the VIDC, so take that into account here 192 */ 193 if (reg == VIDC_PALREG) { 194 vidc_current->palreg = 0; 195 WriteWord(vidc_base, reg | value); 196 return 0; 197 } 198 199 if (reg == VIDC_PALETTE) { 200 WriteWord(vidc_base, reg | value); 201 vidc_current->palette[vidc_current->palreg] = value; 202 vidc_current->palreg++; 203 vidc_current->palreg = vidc_current->palreg & 0xff; 204 return 0; 205 } 206 207 /* 208 * Undefine SAFER if you wish to speed things up (a little) 209 * although this means the function will assume things about 210 * the structure of vidc_state. i.e. the first 256 words are 211 * the palette array 212 */ 213 214 #define SAFER 215 216 #ifdef SAFER 217 #define INITVALUE 0 218 #else 219 #define INITVALUE 256 220 #endif 221 222 for (counter = INITVALUE; 223 counter <= sizeof(struct vidc_state); 224 counter++) { 225 if (reg == tab[counter]) { 226 WriteWord ( vidc_base, reg | value ); 227 current[counter] = value; 228 return 0; 229 } 230 } 231 return -1; 232 } 233 234 235 void 236 vidcvideo_setpalette(struct vidc_state *vidc) 237 { 238 int counter = 0; 239 240 vidcvideo_write(VIDC_PALREG, 0x00000000); 241 for (counter = 0; counter <= 255; counter++) 242 vidcvideo_write(VIDC_PALETTE, vidc->palette[counter]); 243 } 244 245 246 void 247 vidcvideo_setstate(struct vidc_state *vidc) 248 { 249 vidcvideo_write ( VIDC_PALREG, vidc->palreg ); 250 vidcvideo_write ( VIDC_BCOL, vidc->bcol ); 251 vidcvideo_write ( VIDC_CP1, vidc->cp1 ); 252 vidcvideo_write ( VIDC_CP2, vidc->cp2 ); 253 vidcvideo_write ( VIDC_CP3, vidc->cp3 ); 254 vidcvideo_write ( VIDC_HCR, vidc->hcr ); 255 vidcvideo_write ( VIDC_HSWR, vidc->hswr ); 256 vidcvideo_write ( VIDC_HBSR, vidc->hbsr ); 257 vidcvideo_write ( VIDC_HDSR, vidc->hdsr ); 258 vidcvideo_write ( VIDC_HDER, vidc->hder ); 259 vidcvideo_write ( VIDC_HBER, vidc->hber ); 260 vidcvideo_write ( VIDC_HCSR, vidc->hcsr ); 261 vidcvideo_write ( VIDC_HIR, vidc->hir ); 262 vidcvideo_write ( VIDC_VCR, vidc->vcr ); 263 vidcvideo_write ( VIDC_VSWR, vidc->vswr ); 264 vidcvideo_write ( VIDC_VBSR, vidc->vbsr ); 265 vidcvideo_write ( VIDC_VDSR, vidc->vdsr ); 266 vidcvideo_write ( VIDC_VDER, vidc->vder ); 267 vidcvideo_write ( VIDC_VBER, vidc->vber ); 268 vidcvideo_write ( VIDC_VCSR, vidc->vcsr ); 269 vidcvideo_write ( VIDC_VCER, vidc->vcer ); 270 /* 271 * Right, dunno what to set these to yet, but let's keep RiscOS's 272 * ones for now, until the time is right to finish this code 273 */ 274 275 /* vidcvideo_write ( VIDC_EREG, vidc->ereg ); */ 276 /* vidcvideo_write ( VIDC_FSYNREG, vidc->fsynreg ); */ 277 /* vidcvideo_write ( VIDC_CONREG, vidc->conreg ); */ 278 /* vidcvideo_write ( VIDC_DCTL, vidc->dctl ); */ 279 280 vidcvideo_setpalette(vidc); 281 } 282 283 284 void 285 vidcvideo_getstate(struct vidc_state *vidc) 286 { 287 288 *vidc = *vidc_current; 289 } 290 291 292 void 293 vidcvideo_getmode(struct vidc_mode *mode) 294 { 295 296 *mode = vidc_currentmode; 297 } 298 299 300 static int 301 vidcvideo_coldinit(void) 302 { 303 struct videomode const *modes; 304 unsigned besterror; 305 int count; 306 int i; 307 unsigned framerate; 308 309 /* Blank out the cursor */ 310 311 vidcvideo_write(VIDC_CP1, 0x0); 312 vidcvideo_write(VIDC_CP2, 0x0); 313 vidcvideo_write(VIDC_CP3, 0x0); 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 * PAGE_SIZE; 324 transfersize = dispsize >> 10; 325 } 326 327 ptov = dispbase - phys_base; 328 329 dispend = dispstart+dispsize; 330 331 if (vidc_videomode_count > 0) { 332 modes = vidc_videomode_list; 333 count = vidc_videomode_count; 334 } else { 335 modes = videomode_list; 336 count = videomode_count; 337 } 338 339 /* try to find the current mode from the bootloader in my table */ 340 vidc_currentmode.timings = modes[0]; 341 besterror = 1000000; 342 for (i = 0; i < count; i++) { 343 /* We don't support interlace or doublescan */ 344 if (modes[i].flags & (VID_INTERLACE | VID_DBLSCAN)) 345 continue; 346 /* 347 * We jump through a few hoops here to ensure that we 348 * round roughly to the nearest integer without too 349 * much danger of overflow. 350 */ 351 framerate = (modes[i].dot_clock * 1000 / 352 modes[i].htotal * 2 / modes[i].vtotal + 1) / 2; 353 if (modes[i].hdisplay == bootconfig.width + 1 354 && modes[i].vdisplay == bootconfig.height + 1 355 && abs(framerate - bootconfig.framerate) < besterror) { 356 vidc_currentmode.timings = modes[i]; 357 besterror = abs(framerate - bootconfig.framerate); 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 assumption that video memory is mapped in twice */ 375 void *vidcvideo_hwscroll(int bytes) 376 { 377 378 dispstart += bytes; 379 if (dispstart >= dispbase + dispsize) dispstart -= dispsize; 380 if (dispstart < dispbase) dispstart += dispsize; 381 dispend = dispstart+dispsize; 382 383 /* return the start of the bit map of the screen (left top) */ 384 return (void *)dispstart; 385 } 386 387 388 /* reset the HW scroll to be at the start for the benefit of f.e. X */ 389 void *vidcvideo_hwscroll_reset(void) 390 { 391 void *cookie = (void *)dispstart; 392 393 dispstart = dispbase; 394 dispend = dispstart + dispsize; 395 return cookie; 396 } 397 398 399 /* put HW scroll back to where it was */ 400 void *vidcvideo_hwscroll_back(void *cookie) 401 { 402 403 dispstart = (int)cookie; 404 dispend = dispstart + dispsize; 405 return cookie; 406 } 407 408 409 /* this function is to be called preferably at vsync */ 410 void vidcvideo_progr_scroll(void) 411 { 412 413 IOMD_WRITE_WORD(IOMD_VIDINIT, dispstart-ptov); 414 IOMD_WRITE_WORD(IOMD_VIDSTART, dispstart-ptov); 415 IOMD_WRITE_WORD(IOMD_VIDEND, (dispend-transfersize)-ptov); 416 } 417 418 419 /* 420 * Select a new mode by reprogramming the VIDC chip 421 * XXX this part is known not to work for 32bpp 422 */ 423 424 struct vidc_mode newmode; 425 426 static const int bpp_mask_table[] = { 427 0, /* 1bpp */ 428 1, /* 2bpp */ 429 2, /* 4bpp */ 430 3, /* 8bpp */ 431 4, /* 16bpp */ 432 6 /* 32bpp */ 433 }; 434 435 436 void 437 vidcvideo_setmode(struct vidc_mode *mode) 438 { 439 struct videomode *vm; 440 int bpp_mask; 441 int ereg; 442 int best_r, best_v; 443 int least_error; 444 int r, v, f; 445 446 /* 447 * Find out what bit mask we need to or with the vidc20 448 * control register in order to generate the desired number of 449 * bits per pixel. log_bpp is log base 2 of the number of 450 * bits per pixel. 451 */ 452 453 bpp_mask = bpp_mask_table[mode->log2_bpp]; 454 455 vidc_currentmode = *mode; 456 vm = &vidc_currentmode.timings; 457 458 least_error = INT_MAX; 459 best_r = 0; best_v = 0; 460 461 for (v = 63; v > 0; v--) { 462 for (r = 63; r > 0; r--) { 463 f = ((v * vidc_fref) /1000) / r; 464 if (least_error >= abs(f - vm->dot_clock)) { 465 least_error = abs(f - vm->dot_clock); 466 best_r = r; 467 best_v = v; 468 } 469 } 470 } 471 472 if (best_r > 63) best_r=63; 473 if (best_v > 63) best_v=63; 474 if (best_r < 1) best_r= 1; 475 if (best_v < 1) best_v= 1; 476 477 vidcvideo_write(VIDC_FSYNREG, (best_v-1)<<8 | (best_r-1)<<0); 478 479 /* 480 * The translation from struct videomode to VIDC timings is made 481 * fun by the fact that the VIDC counts from the start of the sync 482 * pulse while struct videomode counts from the start of the display. 483 */ 484 vidcvideo_write(VIDC_HSWR, (vm->hsync_end - vm->hsync_start - 8) & ~1); 485 vidcvideo_write(VIDC_HBSR, (vm->htotal - vm->hsync_start - 12) & ~1); 486 vidcvideo_write(VIDC_HDSR, (vm->htotal - vm->hsync_start - 18) & ~1); 487 vidcvideo_write(VIDC_HDER, 488 (vm->htotal - vm->hsync_start + vm->hdisplay - 18) & ~1); 489 vidcvideo_write(VIDC_HBER, 490 (vm->htotal - vm->hsync_start + vm->hdisplay - 12) & ~1); 491 vidcvideo_write(VIDC_HCR, (vm->htotal - 8) & ~3); 492 493 vidcvideo_write(VIDC_VSWR, vm->vsync_end - vm->vsync_start - 1); 494 vidcvideo_write(VIDC_VBSR, vm->vtotal - vm->vsync_start - 1); 495 vidcvideo_write(VIDC_VDSR, vm->vtotal - vm->vsync_start - 1); 496 vidcvideo_write(VIDC_VDER, 497 vm->vtotal - vm->vsync_start + vm->vdisplay - 1); 498 vidcvideo_write(VIDC_VBER, 499 vm->vtotal - vm->vsync_start + vm->vdisplay - 1); 500 /* XXX VIDC20 data sheet say to subtract 2 */ 501 vidcvideo_write(VIDC_VCR, vm->vtotal - 1); 502 503 IOMD_WRITE_WORD(IOMD_FSIZE, vm->vtotal - vm->vdisplay - 1); 504 505 if (dispsize <= 1024*1024) 506 vidcvideo_write(VIDC_DCTL, vm->hdisplay>>2 | 1<<16 | 1<<12); 507 else 508 vidcvideo_write(VIDC_DCTL, vm->hdisplay>>2 | 3<<16 | 1<<12); 509 510 ereg = 1<<12; 511 if (vm->flags & VID_NHSYNC) 512 ereg |= 1<<16; 513 if (vm->flags & VID_NVSYNC) 514 ereg |= 1<<18; 515 vidcvideo_write(VIDC_EREG, ereg); 516 517 /* 518 * Set the video FIFO preload value and bit depth. Chapter 6 519 * of the VIDC20 Data Sheet has full details of the FIFO 520 * preload, but we don't do anything clever and just use the 521 * largest possible value, which is 7 when the VIDC20 is in 522 * 32-bit mode (0MB or 1MB VRAM) and 6 when it is in 64-bit 523 * mode (2MB VRAM). 524 */ 525 if (dispsize > 1024*1024) 526 vidcvideo_write(VIDC_CONREG, 6<<8 | bpp_mask<<5); 527 else 528 vidcvideo_write(VIDC_CONREG, 7<<8 | bpp_mask<<5); 529 } 530 531 532 #if 0 533 /* not used for now */ 534 void 535 vidcvideo_set_display_base(u_int base) 536 { 537 dispstart = dispstart-dispbase + base; 538 dispbase = vmem_base = base; 539 dispend = base + dispsize; 540 ptov = dispbase - phys_base; 541 } 542 #endif 543 544 545 /* 546 * Main initialisation routine for now 547 */ 548 549 static int cursor_init = 0; 550 551 int 552 vidcvideo_init(void) 553 { 554 vidcvideo_coldinit(); 555 if (cold_init && (cursor_init == 0)) 556 /* vidcvideo_flash_go() */; 557 558 /* setting a mode goes wrong in 32 bpp ... 8 and 16 seem OK */ 559 vidcvideo_setmode(&vidc_currentmode); 560 vidcvideo_blank(0); /* display on */ 561 562 vidcvideo_stdpalette(); 563 564 if (cold_init == 0) { 565 vidcvideo_write(VIDC_CP1, 0x0); 566 vidcvideo_write(VIDC_CP2, 0x0); 567 vidcvideo_write(VIDC_CP3, 0x0); 568 } else 569 vidcvideo_cursor_init(CURSOR_MAX_WIDTH, CURSOR_MAX_HEIGHT); 570 571 cold_init = 1; 572 return 0; 573 } 574 575 576 /* reinitialise the vidcvideo */ 577 void 578 vidcvideo_reinit(void) 579 { 580 581 vidcvideo_coldinit(); 582 vidcvideo_setmode(&vidc_currentmode); 583 } 584 585 586 int 587 vidcvideo_cursor_init(int width, int height) 588 { 589 static char *cursor_data = NULL; 590 int counter; 591 int line; 592 paddr_t pa; 593 594 cursor_width = width; 595 cursor_height = height; 596 597 if (!cursor_data) { 598 /* Allocate cursor memory first time round */ 599 cursor_data = (char *)uvm_km_alloc(kernel_map, PAGE_SIZE, 0, 600 UVM_KMF_WIRED | UVM_KMF_ZERO); 601 if (!cursor_data) 602 panic("Cannot allocate memory for hardware cursor"); 603 (void) pmap_extract(pmap_kernel(), (vaddr_t)cursor_data, &pa); 604 IOMD_WRITE_WORD(IOMD_CURSINIT, pa); 605 } 606 607 /* Blank the cursor while initialising its sprite */ 608 609 vidcvideo_write ( VIDC_CP1, 0x0 ); 610 vidcvideo_write ( VIDC_CP2, 0x0 ); 611 vidcvideo_write ( VIDC_CP3, 0x0 ); 612 613 cursor_normal = cursor_data; 614 cursor_transparent = cursor_data + (height * width); 615 616 cursor_transparent += 32; /* ALIGN */ 617 cursor_transparent = (char *)((int)cursor_transparent & (~31) ); 618 619 for ( line = 0; line<height; ++line ) { 620 for ( counter=0; counter<width/4;counter++ ) 621 cursor_normal[line * width + counter]=0x55; /* why 0x55 ? */ 622 for ( ; counter<8; counter++ ) 623 cursor_normal[line * width + counter]=0; 624 } 625 626 for ( line = 0; line<height; ++line ) { 627 for ( counter=0; counter<width/4;counter++ ) 628 cursor_transparent[line * width + counter]=0x00; 629 for ( ; counter<8; counter++ ) 630 cursor_transparent[line * width + counter]=0; 631 } 632 633 634 (void) pmap_extract(pmap_kernel(), (vaddr_t)cursor_normal, 635 (void *)&p_cursor_normal); 636 (void) pmap_extract(pmap_kernel(), (vaddr_t)cursor_transparent, 637 (void *)&p_cursor_transparent); 638 639 memset(cursor_normal, 0x55, width*height); /* white? */ 640 memset(cursor_transparent, 0x00, width*height);/* to see the diffence */ 641 642 /* Ok, now program the cursor; should be blank */ 643 vidcvideo_enablecursor(0); 644 645 return 0; 646 } 647 648 649 void 650 vidcvideo_updatecursor(int xcur, int ycur) 651 { 652 int frontporch = vidc_currentmode.timings.htotal - 653 vidc_currentmode.timings.hsync_start; 654 int topporch = vidc_currentmode.timings.vtotal - 655 vidc_currentmode.timings.vsync_start; 656 657 vidcvideo_write(VIDC_HCSR, frontporch -17 + xcur); 658 vidcvideo_write(VIDC_VCSR, topporch -2 + (ycur+1)-2 + 3 - 659 cursor_height); 660 vidcvideo_write(VIDC_VCER, topporch -2 + (ycur+3)+2 + 3 ); 661 } 662 663 664 void 665 vidcvideo_enablecursor(int on) 666 { 667 668 if (on) 669 IOMD_WRITE_WORD(IOMD_CURSINIT,p_cursor_normal); 670 else 671 IOMD_WRITE_WORD(IOMD_CURSINIT,p_cursor_transparent); 672 vidcvideo_write ( VIDC_CP1, 0xffffff ); /* enable */ 673 } 674 675 676 void 677 vidcvideo_stdpalette(void) 678 { 679 int i; 680 681 switch (vidc_currentmode.log2_bpp) { 682 case 0: /* 1 bpp */ 683 case 1: /* 2 bpp */ 684 case 2: /* 4 bpp */ 685 case 3: /* 8 bpp */ 686 vidcvideo_write(VIDC_PALREG, 0x00000000); 687 vidcvideo_write(VIDC_PALETTE, VIDC_COL( 0, 0, 0)); 688 vidcvideo_write(VIDC_PALETTE, VIDC_COL(255, 0, 0)); 689 vidcvideo_write(VIDC_PALETTE, VIDC_COL( 0, 255, 0)); 690 vidcvideo_write(VIDC_PALETTE, VIDC_COL(255, 255, 0)); 691 vidcvideo_write(VIDC_PALETTE, VIDC_COL( 0, 0, 255)); 692 vidcvideo_write(VIDC_PALETTE, VIDC_COL(255, 0, 255)); 693 vidcvideo_write(VIDC_PALETTE, VIDC_COL( 0, 255, 255)); 694 vidcvideo_write(VIDC_PALETTE, VIDC_COL(255, 255, 255)); 695 vidcvideo_write(VIDC_PALETTE, VIDC_COL(128, 128, 128)); 696 vidcvideo_write(VIDC_PALETTE, VIDC_COL(255, 128, 128)); 697 vidcvideo_write(VIDC_PALETTE, VIDC_COL(128, 255, 128)); 698 vidcvideo_write(VIDC_PALETTE, VIDC_COL(255, 255, 128)); 699 vidcvideo_write(VIDC_PALETTE, VIDC_COL(128, 128, 255)); 700 vidcvideo_write(VIDC_PALETTE, VIDC_COL(255, 128, 255)); 701 vidcvideo_write(VIDC_PALETTE, VIDC_COL(255, 255, 255)); 702 break; 703 case 4: /* 16 bpp */ 704 /* 705 * The use of the palette in 16-bit modes is quite 706 * fun. Comments in linux/drivers/video/acornfb.c 707 * imply that it goes something like this: 708 * 709 * red = LUT[pixel[7:0]].red 710 * green = LUT[pixel[11:4]].green 711 * blue = LUT[pixel[15:8]].blue 712 * 713 * We use 6:5:5 R:G:B cos that's what Xarm32VIDC wants. 714 */ 715 #define RBITS 6 716 #define GBITS 5 717 #define BBITS 5 718 vidcvideo_write(VIDC_PALREG, 0x00000000); 719 for (i = 0; i < 256; i++) { 720 int r, g, b; 721 722 r = i & ((1 << RBITS) - 1); 723 g = (i >> (RBITS - 4)) & ((1 << GBITS) - 1); 724 b = (i >> (RBITS + GBITS - 8)) & ((1 << BBITS) - 1); 725 vidcvideo_write(VIDC_PALETTE, 726 VIDC_COL(r << (8 - RBITS) | r >> (2 * RBITS - 8), 727 g << (8 - GBITS) | g >> (2 * GBITS - 8), 728 b << (8 - BBITS) | b >> (2 * BBITS - 8))); 729 } 730 break; 731 case 5: /* 32 bpp */ 732 vidcvideo_write(VIDC_PALREG, 0x00000000); 733 for (i = 0; i < 256; i++) 734 vidcvideo_write(VIDC_PALETTE, VIDC_COL(i, i, i)); 735 break; 736 } 737 } 738 739 int 740 vidcvideo_blank(int video_off) 741 { 742 int ereg; 743 744 ereg = 1<<12; 745 if (vidc_currentmode.timings.flags & VID_NHSYNC) 746 ereg |= 1<<16; 747 if (vidc_currentmode.timings.flags & VID_NVSYNC) 748 ereg |= 1<<18; 749 750 if (!video_off) 751 vidcvideo_write(VIDC_EREG, ereg); 752 else 753 vidcvideo_write(VIDC_EREG, 0); 754 return 0; 755 } 756 757 /* end of vidc20config.c */ 758