1 /* $NetBSD: hd64461video.c,v 1.16 2002/10/02 15:45:20 thorpej Exp $ */ 2 3 /*- 4 * Copyright (c) 2001, 2002 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 #include "debug_hpcsh.h" 40 // #define HD64461VIDEO_HWACCEL 41 42 #include <sys/param.h> 43 #include <sys/systm.h> 44 #include <sys/device.h> 45 #include <sys/malloc.h> 46 47 #include <sys/conf.h> /* cdev_decl */ 48 #include <dev/cons.h> /* consdev */ 49 50 /* ioctl */ 51 #include <sys/ioctl.h> 52 #include <sys/buf.h> 53 #include <uvm/uvm_extern.h> 54 55 #include <machine/bus.h> 56 #include <machine/intr.h> 57 58 #include <hpcsh/dev/hd64461/hd64461var.h> 59 #include <hpcsh/dev/hd64461/hd64461reg.h> 60 #include <hpcsh/dev/hd64461/hd64461videoreg.h> 61 62 #include <dev/wscons/wsdisplayvar.h> 63 #include <dev/rasops/rasops.h> 64 65 #include <dev/wscons/wsconsio.h> 66 #include <dev/hpc/hpcfbvar.h> 67 #include <dev/hpc/hpcfbio.h> 68 #include <dev/hpc/video_subr.h> 69 70 #include <machine/bootinfo.h> 71 72 #ifdef HD64461VIDEO_DEBUG 73 #define DPRINTF_ENABLE 74 #define DPRINTF_DEBUG hd64461video_debug 75 #endif 76 #include <machine/debug.h> 77 78 struct hd64461video_chip; 79 struct hd64461video_font { 80 struct wsdisplay_font wsfont; 81 int c, cw, cstep; 82 int loaded; 83 }; 84 85 struct hd64461video_softc { 86 struct device sc_dev; 87 enum hd64461_module_id sc_module_id; 88 struct hd64461video_chip *sc_vc; 89 90 struct hd64461video_font sc_font; 91 }; 92 93 STATIC struct hd64461video_chip { 94 struct video_chip vc; 95 enum hd64461video_display_mode { 96 LCD256_C, 97 LCD64K_C, 98 LCD64_MONO, 99 LCD16_MONO, 100 LCD4_MONO, 101 LCD2_MONO, 102 CRT256_C, 103 LCDCRT 104 }; 105 enum hd64461video_display_mode mode; 106 struct hpcfb_dspconf hd; 107 struct hpcfb_fbconf hf; 108 u_int8_t *off_screen_addr; 109 size_t off_screen_size; 110 111 int console; 112 } hd64461video_chip; 113 114 void hd64461video_cnprobe(struct consdev *); 115 void hd64461video_cninit(struct consdev *); 116 117 STATIC int hd64461video_match(struct device *, struct cfdata *, void *); 118 STATIC void hd64461video_attach(struct device *, struct device *, void *); 119 120 STATIC void hd64461video_setup_hpcfbif(struct hd64461video_chip *); 121 STATIC void hd64461video_update_videochip_status(struct hd64461video_chip *); 122 STATIC size_t hd64461video_frame_buffer_size(struct hd64461video_chip *); 123 STATIC void hd64461video_hwaccel_init(struct hd64461video_chip *); 124 125 STATIC void hd64461video_set_clut(struct hd64461video_chip *, int, int, 126 u_int8_t *, u_int8_t *, u_int8_t *); 127 STATIC void hd64461video_get_clut(struct hd64461video_chip *, int, int, 128 u_int8_t *, u_int8_t *, u_int8_t *); 129 #if notyet 130 STATIC void hd64461video_set_display_mode(struct hd64461video_chip *); 131 STATIC void hd64461video_set_display_mode_lcdc(struct hd64461video_chip *); 132 STATIC void hd64461video_set_display_mode_crtc(struct hd64461video_chip *); 133 #endif 134 135 #ifdef HD64461VIDEO_DEBUG 136 STATIC void hd64461video_info(struct hd64461video_softc *); 137 STATIC void hd64461video_dump(void) __attribute__((__unused__)); 138 #endif 139 140 CFATTACH_DECL(hd64461video, sizeof(struct hd64461video_softc), 141 hd64461video_match, hd64461video_attach, NULL, NULL); 142 143 int hd64461video_ioctl(void *, u_long, caddr_t, int, struct proc *); 144 paddr_t hd64461video_mmap(void *, off_t, int); 145 void hd64461video_cursor(void *, int, int, int, int, int); 146 void hd64461video_bitblit(void *, int, int, int, int, int, int); 147 void hd64461video_erase(void *, int, int, int, int, int); 148 void hd64461video_putchar(void *, int, int, struct wsdisplay_font *, int, int, 149 u_int, int); 150 void hd64461video_setclut(void *, struct rasops_info *); 151 void hd64461video_font(void *, struct wsdisplay_font *); 152 void hd64461video_iodone(void *); 153 154 struct hpcfb_accessops hd64461video_ha = { 155 .ioctl = hd64461video_ioctl, 156 .mmap = hd64461video_mmap, 157 #ifdef HD64461VIDEO_HWACCEL 158 .cursor = hd64461video_cursor, 159 .bitblit= hd64461video_bitblit, 160 .erase = hd64461video_erase, 161 .putchar= hd64461video_putchar, 162 .setclut= hd64461video_setclut, 163 .font = hd64461video_font, 164 .iodone = hd64461video_iodone 165 #endif /* HD64461VIDEO_HWACCEL */ 166 }; 167 168 /* font */ 169 STATIC void hd64461video_font_load_16bpp(u_int16_t *, u_int8_t *, int, int, int); 170 STATIC void hd64461video_font_load_8bpp(u_int8_t *, u_int8_t *, int, int, int); 171 STATIC void hd64461video_font_set_attr(struct hd64461video_softc *, 172 struct wsdisplay_font *); 173 STATIC void hd64461video_font_load(struct hd64461video_softc *); 174 STATIC vaddr_t hd64461video_font_start_addr(struct hd64461video_softc *, int); 175 176 int 177 hd64461video_match(struct device *parent, struct cfdata *cf, void *aux) 178 { 179 struct hd64461_attach_args *ha = aux; 180 181 return (ha->ha_module_id == HD64461_MODULE_VIDEO); 182 } 183 184 void 185 hd64461video_attach(struct device *parent, struct device *self, void *aux) 186 { 187 struct hd64461_attach_args *ha = aux; 188 struct hd64461video_softc *sc = (struct hd64461video_softc *)self; 189 struct hpcfb_attach_args hfa; 190 struct video_chip *vc = &hd64461video_chip.vc; 191 char pbuf[9]; 192 size_t fbsize, on_screen_size; 193 194 sc->sc_module_id = ha->ha_module_id; 195 sc->sc_vc = &hd64461video_chip; 196 printf(": "); 197 198 /* detect frame buffer size */ 199 fbsize = hd64461video_frame_buffer_size(&hd64461video_chip); 200 format_bytes(pbuf, sizeof(pbuf), fbsize); 201 printf("frame buffer = %s ", pbuf); 202 203 /* update chip status */ 204 hd64461video_update_videochip_status(&hd64461video_chip); 205 // hd64461video_set_display_mode(&hd64461video_chip); 206 207 if (hd64461video_chip.console) 208 printf(", console"); 209 210 printf("\n"); 211 #ifdef HD64461VIDEO_DEBUG 212 hd64461video_info(sc); 213 hd64461video_dump(); 214 #endif 215 216 217 /* setup hpcfb interface */ 218 hd64461video_setup_hpcfbif(&hd64461video_chip); 219 220 /* setup off-screen buffer */ 221 on_screen_size = (vc->vc_fbwidth * vc->vc_fbheight * vc->vc_fbdepth) / 222 NBBY; 223 hd64461video_chip.off_screen_addr = (u_int8_t *)vc->vc_fbvaddr + 224 on_screen_size; 225 hd64461video_chip.off_screen_size = fbsize - on_screen_size; 226 /* clean up off-screen area */ 227 { 228 u_int8_t *p = hd64461video_chip.off_screen_addr; 229 u_int8_t *end = p + hd64461video_chip.off_screen_size; 230 while (p < end) 231 *p++ = 0xff; 232 } 233 234 /* initialize hardware acceralation */ 235 hd64461video_hwaccel_init(&hd64461video_chip); 236 237 /* register interface to hpcfb */ 238 hfa.ha_console = hd64461video_chip.console; 239 hfa.ha_accessops = &hd64461video_ha; 240 hfa.ha_accessctx = sc; 241 hfa.ha_curfbconf = 0; 242 hfa.ha_nfbconf = 1; 243 hfa.ha_fbconflist = &hd64461video_chip.hf; 244 hfa.ha_curdspconf = 0; 245 hfa.ha_ndspconf = 1; 246 hfa.ha_dspconflist = &hd64461video_chip.hd; 247 248 config_found(self, &hfa, hpcfbprint); 249 } 250 251 /* console support */ 252 void 253 hd64461video_cninit(struct consdev *cndev) 254 { 255 hd64461video_chip.console = 1; 256 hd64461video_chip.vc.vc_reverse = video_reverse_color(); 257 258 hd64461video_update_videochip_status(&hd64461video_chip); 259 hd64461video_setup_hpcfbif(&hd64461video_chip); 260 hpcfb_cnattach(&hd64461video_chip.hf); 261 262 cn_tab->cn_pri = CN_INTERNAL; 263 } 264 265 void 266 hd64461video_cnprobe(struct consdev *cndev) 267 { 268 #if NWSDISPLAY > 0 269 extern const struct cdevsw wsdisplay_cdevsw; 270 int maj, unit; 271 #endif 272 cndev->cn_dev = NODEV; 273 cndev->cn_pri = CN_NORMAL; 274 275 #if NWSDISPLAY > 0 276 unit = 0; 277 maj = cdevsw_lookup_major(&wsdisplay_cdevsw); 278 279 if (maj != -1) { 280 cndev->cn_pri = CN_INTERNAL; 281 cndev->cn_dev = makedev(maj, unit); 282 } 283 #endif /* NWSDISPLAY > 0 */ 284 } 285 286 /* hpcfb support */ 287 void 288 hd64461video_setup_hpcfbif(struct hd64461video_chip *hvc) 289 { 290 struct video_chip *vc = &hvc->vc; 291 struct hpcfb_fbconf *fb = &hvc->hf; 292 vaddr_t fbvaddr = vc->vc_fbvaddr; 293 int height = vc->vc_fbheight; 294 int width = vc->vc_fbwidth; 295 int depth = vc->vc_fbdepth; 296 297 memset(fb, 0, sizeof(struct hpcfb_fbconf)); 298 299 fb->hf_conf_index = 0; /* configuration index */ 300 fb->hf_nconfs = 1; /* how many configurations */ 301 strncpy(fb->hf_name, "HD64461 video module", HPCFB_MAXNAMELEN); 302 303 /* frame buffer name */ 304 strncpy(fb->hf_conf_name, "LCD", HPCFB_MAXNAMELEN); 305 306 /* configuration name */ 307 fb->hf_height = height; 308 fb->hf_width = width; 309 fb->hf_baseaddr = (u_long)fbvaddr; 310 fb->hf_offset = (u_long)fbvaddr - 311 sh3_ptob(sh3_btop(fbvaddr)); 312 313 /* frame buffer start offset */ 314 fb->hf_bytes_per_line = (width * depth) / NBBY; 315 fb->hf_nplanes = 1; 316 fb->hf_bytes_per_plane = height * fb->hf_bytes_per_line; 317 318 fb->hf_access_flags |= HPCFB_ACCESS_BYTE; 319 fb->hf_access_flags |= HPCFB_ACCESS_WORD; 320 fb->hf_access_flags |= HPCFB_ACCESS_DWORD; 321 if (vc->vc_reverse) 322 fb->hf_access_flags |= HPCFB_ACCESS_REVERSE; 323 324 switch (depth) { 325 default: 326 panic("%s: not supported color depth", __FUNCTION__); 327 /* NOTREACHED */ 328 case 16: 329 fb->hf_class = HPCFB_CLASS_RGBCOLOR; 330 fb->hf_access_flags |= HPCFB_ACCESS_STATIC; 331 fb->hf_pack_width = 16; 332 fb->hf_pixels_per_pack = 1; 333 fb->hf_pixel_width = 16; 334 335 fb->hf_class_data_length = sizeof(struct hf_rgb_tag); 336 /* reserved for future use */ 337 fb->hf_u.hf_rgb.hf_flags = 0; 338 339 fb->hf_u.hf_rgb.hf_red_width = 5; 340 fb->hf_u.hf_rgb.hf_red_shift = 11; 341 fb->hf_u.hf_rgb.hf_green_width = 6; 342 fb->hf_u.hf_rgb.hf_green_shift = 5; 343 fb->hf_u.hf_rgb.hf_blue_width = 5; 344 fb->hf_u.hf_rgb.hf_blue_shift = 0; 345 fb->hf_u.hf_rgb.hf_alpha_width = 0; 346 fb->hf_u.hf_rgb.hf_alpha_shift = 0; 347 break; 348 349 case 8: 350 fb->hf_class = HPCFB_CLASS_INDEXCOLOR; 351 fb->hf_access_flags |= HPCFB_ACCESS_STATIC; 352 fb->hf_pack_width = 8; 353 fb->hf_pixels_per_pack = 1; 354 fb->hf_pixel_width = 8; 355 fb->hf_class_data_length = sizeof(struct hf_indexed_tag); 356 /* reserved for future use */ 357 fb->hf_u.hf_indexed.hf_flags = 0; 358 break; 359 } 360 } 361 362 void 363 hd64461video_hwaccel_init(struct hd64461video_chip *hvc) 364 { 365 u_int16_t r; 366 367 r = HD64461_LCDGRCFGR_ACCRESET; 368 switch (hvc->vc.vc_fbdepth) { 369 default: 370 panic("no bitblit acceralation."); 371 case 16: 372 break; 373 case 8: 374 r |= HD64461_LCDGRCFGR_COLORDEPTH_8BPP; 375 break; 376 } 377 hd64461_reg_write_2(HD64461_LCDGRCFGR_REG16, r); 378 379 while ((hd64461_reg_read_2(HD64461_LCDGRCFGR_REG16) & 380 HD64461_LCDGRCFGR_ACCSTATUS) != 0) 381 /* busy loop */; 382 r &= ~HD64461_LCDGRCFGR_ACCRESET; 383 hd64461_reg_write_2(HD64461_LCDGRCFGR_REG16, r); 384 385 while ((hd64461_reg_read_2(HD64461_LCDGRCFGR_REG16) & 386 HD64461_LCDGRCFGR_ACCSTATUS) != 0) 387 /* busy loop */; 388 389 hd64461_reg_write_2(HD64461_LCDGRDOR_REG16, 390 (hvc->vc.vc_fbwidth - 1) & HD64461_LCDGRDOR_MASK); 391 } 392 393 /* hpcfb ops */ 394 int 395 hd64461video_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p) 396 { 397 struct hd64461video_softc *sc = (struct hd64461video_softc *)v; 398 struct hpcfb_fbconf *hf = &sc->sc_vc->hf; 399 struct hpcfb_fbconf *fbconf; 400 struct hpcfb_dspconf *dspconf; 401 struct wsdisplay_cmap *cmap; 402 u_int8_t *r, *g, *b; 403 int error; 404 size_t idx, cnt; 405 406 switch (cmd) { 407 case WSDISPLAYIO_GETCMAP: 408 cmap = (struct wsdisplay_cmap*)data; 409 cnt = cmap->count; 410 idx = cmap->index; 411 412 if (hf->hf_class != HPCFB_CLASS_INDEXCOLOR || 413 hf->hf_pack_width != 8 || 414 !LEGAL_CLUT_INDEX(idx) || 415 !LEGAL_CLUT_INDEX(idx + cnt -1)) { 416 return (EINVAL); 417 } 418 419 if (!uvm_useracc(cmap->red, cnt, B_WRITE) || 420 !uvm_useracc(cmap->green, cnt, B_WRITE) || 421 !uvm_useracc(cmap->blue, cnt, B_WRITE)) { 422 return (EFAULT); 423 } 424 425 error = cmap_work_alloc(&r, &g, &b, 0, cnt); 426 if (error != 0) { 427 cmap_work_free(r, g, b, 0); 428 return (ENOMEM); 429 } 430 431 hd64461video_get_clut(sc->sc_vc, idx, cnt, r, g, b); 432 copyout(r, cmap->red, cnt); 433 copyout(g, cmap->green,cnt); 434 copyout(b, cmap->blue, cnt); 435 cmap_work_free(r, g, b, 0); 436 437 return (0); 438 439 case WSDISPLAYIO_PUTCMAP: 440 cmap = (struct wsdisplay_cmap *)data; 441 cnt = cmap->count; 442 idx = cmap->index; 443 444 if (hf->hf_class != HPCFB_CLASS_INDEXCOLOR || 445 hf->hf_pack_width != 8 || 446 !LEGAL_CLUT_INDEX(idx) || 447 !LEGAL_CLUT_INDEX(idx + cnt -1)) { 448 return (EINVAL); 449 } 450 451 if (!uvm_useracc(cmap->red, cnt, B_WRITE) || 452 !uvm_useracc(cmap->green, cnt, B_WRITE) || 453 !uvm_useracc(cmap->blue, cnt, B_WRITE)) { 454 return (EFAULT); 455 } 456 457 error = cmap_work_alloc(&r, &g, &b, 0, cnt); 458 if (error != 0) { 459 cmap_work_free(r, g, b, 0); 460 return (ENOMEM); 461 } 462 463 copyin(cmap->red, r, cnt); 464 copyin(cmap->green,g, cnt); 465 copyin(cmap->blue, b, cnt); 466 hd64461video_set_clut(sc->sc_vc, idx, cnt, r, g, b); 467 cmap_work_free(r, g, b, 0); 468 469 return (0); 470 471 case HPCFBIO_GCONF: 472 fbconf = (struct hpcfb_fbconf *)data; 473 if (fbconf->hf_conf_index != 0 && 474 fbconf->hf_conf_index != HPCFB_CURRENT_CONFIG) { 475 return (EINVAL); 476 } 477 *fbconf = *hf; /* structure assignment */ 478 return (0); 479 480 case HPCFBIO_SCONF: 481 fbconf = (struct hpcfb_fbconf *)data; 482 if (fbconf->hf_conf_index != 0 && 483 fbconf->hf_conf_index != HPCFB_CURRENT_CONFIG) { 484 return (EINVAL); 485 } 486 /* 487 * nothing to do because we have only one configration 488 */ 489 return (0); 490 491 case HPCFBIO_GDSPCONF: 492 dspconf = (struct hpcfb_dspconf *)data; 493 if ((dspconf->hd_unit_index != 0 && 494 dspconf->hd_unit_index != HPCFB_CURRENT_UNIT) || 495 (dspconf->hd_conf_index != 0 && 496 dspconf->hd_conf_index != HPCFB_CURRENT_CONFIG)) { 497 return (EINVAL); 498 } 499 *dspconf = sc->sc_vc->hd; /* structure assignment */ 500 return (0); 501 502 case HPCFBIO_SDSPCONF: 503 dspconf = (struct hpcfb_dspconf *)data; 504 if ((dspconf->hd_unit_index != 0 && 505 dspconf->hd_unit_index != HPCFB_CURRENT_UNIT) || 506 (dspconf->hd_conf_index != 0 && 507 dspconf->hd_conf_index != HPCFB_CURRENT_CONFIG)) { 508 return (EINVAL); 509 } 510 /* 511 * nothing to do 512 * because we have only one unit and one configration 513 */ 514 return (0); 515 516 case HPCFBIO_GOP: 517 case HPCFBIO_SOP: 518 /* XXX not implemented yet */ 519 return (EINVAL); 520 } 521 522 return (EPASSTHROUGH); 523 } 524 525 paddr_t 526 hd64461video_mmap(void *ctx, off_t offset, int prot) 527 { 528 struct hd64461video_softc *sc = (struct hd64461video_softc *)ctx; 529 struct hpcfb_fbconf *hf = &sc->sc_vc->hf; 530 531 if (offset < 0 || (hf->hf_bytes_per_plane + hf->hf_offset) < offset) 532 return (-1); 533 534 return (sh3_btop(HD64461_FBBASE + offset)); 535 } 536 537 void 538 hd64461video_cursor(void *ctx, int on, int xd, int yd, int w, int h) 539 { 540 struct hd64461video_softc *sc = (struct hd64461video_softc *)ctx; 541 int xw, yh, width, bpp, adr; 542 u_int16_t r; 543 544 width = sc->sc_vc->vc.vc_fbwidth; 545 bpp = sc->sc_vc->vc.vc_fbdepth; 546 xw = w - 1; 547 yh = h - 1; 548 549 /* Wait until previous command done. */ 550 hd64461video_iodone(ctx); 551 552 /* Destination addr */ 553 adr = width * yd + xd; 554 if (bpp == 16) 555 adr *= 2; 556 hd64461_reg_write_2(HD64461_LCDBBTDSARH_REG16, 557 HD64461_LCDBBTDSARH(adr)); 558 hd64461_reg_write_2(HD64461_LCDBBTDSARL_REG16, 559 HD64461_LCDBBTDSARL(adr)); 560 561 // Width 562 hd64461_reg_write_2(HD64461_LCDBBTDWR_REG16, 563 xw & HD64461_LCDBBTDWR_MASK); 564 565 // Height 566 hd64461_reg_write_2(HD64461_LCDBBTDHR_REG16, 567 yh & HD64461_LCDBBTDHR_MASK); 568 569 // Operation (Destination Invert) 570 hd64461_reg_write_2(HD64461_LCDBBTROPR_REG16, 571 HD64461_LCDC_BITBLT_DSTINVERT); 572 573 // BitBLT mode (Destination Invert) 574 hd64461_reg_write_2(HD64461_LCDBBTMDR_REG16, 0); 575 576 // Kick. 577 r = hd64461_reg_read_2(HD64461_LCDGRCFGR_REG16); 578 r &= ~HD64461_LCDGRCFGR_ACCSTART_MASK; 579 r |= HD64461_LCDGRCFGR_ACCSTART_BITBLT; 580 hd64461_reg_write_2(HD64461_LCDGRCFGR_REG16, r); 581 } 582 583 void 584 hd64461video_bitblit(void *ctx, int xs, int ys, int xd, int yd, int h, int w) 585 { 586 struct hd64461video_softc *sc = (struct hd64461video_softc *)ctx; 587 int xw, yh, width, bpp, condition_a, adr; 588 u_int16_t r; 589 590 xw = w - 1; 591 yh = h - 1; 592 width = sc->sc_vc->vc.vc_fbwidth; 593 bpp = sc->sc_vc->vc.vc_fbdepth; 594 condition_a = ((ys == yd) && (xs <= xd)) || (ys < yd); 595 596 hd64461video_iodone(ctx); 597 598 // Source addr 599 if (condition_a) 600 adr = (width * (ys + yh)) + (xs + xw); 601 else 602 adr = width * ys + xs; 603 if (bpp == 16) 604 adr *= 2; 605 606 hd64461_reg_write_2(HD64461_LCDBBTSSARH_REG16, 607 HD64461_LCDBBTSSARH(adr)); 608 hd64461_reg_write_2(HD64461_LCDBBTSSARL_REG16, 609 HD64461_LCDBBTSSARL(adr)); 610 611 // Destination addr 612 if (condition_a) 613 adr = (width * (yd + yh)) + (xd + xw); 614 else 615 adr = width * yd + xd; 616 if (bpp == 16) 617 adr *= 2; 618 619 hd64461_reg_write_2(HD64461_LCDBBTDSARH_REG16, 620 HD64461_LCDBBTDSARH(adr)); 621 hd64461_reg_write_2(HD64461_LCDBBTDSARL_REG16, 622 HD64461_LCDBBTDSARL(adr)); 623 624 // Width 625 hd64461_reg_write_2(HD64461_LCDBBTDWR_REG16, 626 xw & HD64461_LCDBBTDWR_MASK); 627 628 // Height 629 hd64461_reg_write_2(HD64461_LCDBBTDHR_REG16, 630 yh & HD64461_LCDBBTDHR_MASK); 631 632 // Operation (source copy) 633 hd64461_reg_write_2(HD64461_LCDBBTROPR_REG16, 634 HD64461_LCDC_BITBLT_SRCCOPY); 635 636 // BitBLT mode (on screen to on screen) 637 r = HD64461_LCDBBTMDR_SET(0, 638 HD64461_LCDBBTMDR_ON_SCREEN_TO_ON_SCREEN); 639 hd64461_reg_write_2(HD64461_LCDBBTMDR_REG16, r); 640 641 // Kick. 642 r = hd64461_reg_read_2(HD64461_LCDGRCFGR_REG16); 643 r &= ~HD64461_LCDGRCFGR_ACCSTART_MASK; 644 r |= HD64461_LCDGRCFGR_ACCSTART_BITBLT; 645 hd64461_reg_write_2(HD64461_LCDGRCFGR_REG16, r); 646 } 647 648 void 649 hd64461video_erase(void *ctx, int xd, int yd, int h, int w, int attr) 650 { 651 struct hd64461video_softc *sc = (struct hd64461video_softc *)ctx; 652 int xw, yh, width, bpp, adr; 653 u_int16_t r; 654 655 width = sc->sc_vc->vc.vc_fbwidth; 656 bpp = sc->sc_vc->vc.vc_fbdepth; 657 xw = w - 1; 658 yh = h - 1; 659 660 /* Wait until previous command done. */ 661 hd64461video_iodone(ctx); 662 663 /* Destination addr */ 664 adr = width * yd + xd; 665 if (bpp == 16) 666 adr *= 2; 667 hd64461_reg_write_2(HD64461_LCDBBTDSARH_REG16, 668 HD64461_LCDBBTDSARH(adr)); 669 hd64461_reg_write_2(HD64461_LCDBBTDSARL_REG16, 670 HD64461_LCDBBTDSARL(adr)); 671 672 // Width 673 hd64461_reg_write_2(HD64461_LCDBBTDWR_REG16, 674 xw & HD64461_LCDBBTDWR_MASK); 675 676 // Height 677 hd64461_reg_write_2(HD64461_LCDBBTDHR_REG16, 678 yh & HD64461_LCDBBTDHR_MASK); 679 680 // Color 681 hd64461_reg_write_2(HD64461_LCDGRSCR_REG16, 0); //XXX black only 682 683 // Operation (Solid Color Fill) 684 hd64461_reg_write_2(HD64461_LCDBBTROPR_REG16, 685 HD64461_LCDC_BITBLT_PATCOPY); 686 687 // BitBLT mode (Solid Color) 688 hd64461_reg_write_2(HD64461_LCDBBTMDR_REG16, 689 HD64461_LCDBBTMDR_PATSELECT_SOLIDCOLOR); 690 691 // Kick. 692 r = hd64461_reg_read_2(HD64461_LCDGRCFGR_REG16); 693 r &= ~HD64461_LCDGRCFGR_ACCSTART_MASK; 694 r |= HD64461_LCDGRCFGR_ACCSTART_BITBLT; 695 hd64461_reg_write_2(HD64461_LCDGRCFGR_REG16, r); 696 } 697 698 void 699 hd64461video_putchar(void *ctx, int row, int col, struct wsdisplay_font *font, 700 int fclr, int uclr, u_int uc, int attr) 701 { 702 struct hd64461video_softc *sc = (struct hd64461video_softc *)ctx; 703 int w, h, cw; 704 705 w = font->fontwidth; 706 h = font->fontheight; 707 cw = sc->sc_font.cw; 708 hd64461video_bitblit(ctx, (uc % cw) * w, 709 sc->sc_vc->vc.vc_fbheight + (uc / cw) * h, row, col, h, w); 710 } 711 712 void 713 hd64461video_setclut(void *ctx, struct rasops_info *info) 714 { 715 struct hd64461video_softc *sc = (struct hd64461video_softc *)ctx; 716 717 if (sc->sc_vc->vc.vc_fbdepth != 8) 718 return; 719 } 720 721 void 722 hd64461video_font(void *ctx, struct wsdisplay_font *font) 723 { 724 struct hd64461video_softc *sc = (struct hd64461video_softc *)ctx; 725 726 hd64461video_font_set_attr(sc, font); 727 hd64461video_font_load(sc); 728 } 729 730 void 731 hd64461video_iodone(void *ctx) 732 { 733 while ((hd64461_reg_read_2(HD64461_LCDGRCFGR_REG16) & 734 HD64461_LCDGRCFGR_ACCSTATUS) != 0) 735 /* busy loop */; 736 } 737 738 /* internal */ 739 void 740 hd64461video_font_load_16bpp(u_int16_t *d, u_int8_t *s, int w, int h, int step) 741 { 742 int i, j, n; 743 n = step / sizeof(u_int16_t); 744 745 for (i = 0; i < h; i++, d += n) { 746 for (j = 0; j < w; j++) { 747 d[j] = *s & (1 << (w - j - 1)) ? 0xffff : 0x0000; 748 } 749 s++; 750 } 751 } 752 753 void 754 hd64461video_font_load_8bpp(u_int8_t *d, u_int8_t *s, int w, int h, int step) 755 { 756 int i, j, n; 757 n = step / sizeof(u_int8_t); 758 759 for (i = 0; i < h; i++, d += n) { 760 for (j = 0; j < w; j++) { 761 d[j] = *s & (1 << (w - j - 1)) ? 0xff : 0x00; 762 } 763 s++; 764 } 765 } 766 767 void 768 hd64461video_font_set_attr(struct hd64461video_softc *sc, 769 struct wsdisplay_font *f) 770 { 771 struct hd64461video_chip *hvc = sc->sc_vc; 772 struct wsdisplay_font *font = (struct wsdisplay_font *)&sc->sc_font; 773 int w, h, bpp; 774 775 w = f->fontwidth; 776 h = f->fontheight; 777 bpp = hvc->vc.vc_fbdepth; 778 779 *font = *f; 780 sc->sc_font.c = (w * bpp) / NBBY; 781 sc->sc_font.cw = hvc->hf.hf_width / w; 782 sc->sc_font.cstep = ((w * h * bpp) / NBBY) * sc->sc_font.cw; 783 784 DPRINTF("c = %d cw = %d cstep = %d\n", sc->sc_font.c, 785 sc->sc_font.cw, sc->sc_font.cstep); 786 787 } 788 789 /* return frame buffer virtual address of charcter #n */ 790 vaddr_t 791 hd64461video_font_start_addr(struct hd64461video_softc *sc, int n) 792 { 793 struct hd64461video_chip *hvc = sc->sc_vc; 794 struct hd64461video_font *font = &sc->sc_font; 795 vaddr_t base; 796 797 base = (vaddr_t)hvc->off_screen_addr; 798 base += (n / font->cw) * font->cstep + font->c * (n % font->cw); 799 800 return base; 801 } 802 803 void 804 hd64461video_font_load(struct hd64461video_softc *sc) 805 { 806 struct hd64461video_chip *hvc = sc->sc_vc; 807 struct wsdisplay_font *font = (struct wsdisplay_font *)&sc->sc_font; 808 u_int8_t *q; 809 int w, h, step, i, n; 810 811 if (sc->sc_font.loaded) { 812 printf("reload font\n"); 813 } 814 815 w = font->fontwidth; 816 h = font->fontheight; 817 step = sc->sc_font.cw * sc->sc_font.c; 818 n = (w * h) / NBBY; 819 q = font->data; 820 821 DPRINTF("%s (%dx%d) %d+%d\n", font->name, w, h, font->firstchar, 822 font->numchars); 823 DPRINTF("bitorder %d byteorder %d stride %d\n", font->bitorder, 824 font->byteorder, font->stride); 825 826 switch (hvc->vc.vc_fbdepth) { 827 case 8: 828 for (i = font->firstchar; i < font->numchars; i++) { 829 hd64461video_font_load_8bpp 830 ((u_int8_t *)hd64461video_font_start_addr(sc, i), 831 q, w, h, step); 832 q += n; 833 } 834 break; 835 case 16: 836 for (i = font->firstchar; i < font->numchars; i++) { 837 hd64461video_font_load_16bpp 838 ((u_int16_t *)hd64461video_font_start_addr(sc, i), 839 q, w, h, step); 840 q += n; 841 } 842 break; 843 } 844 845 sc->sc_font.loaded = TRUE; 846 } 847 848 void 849 hd64461video_update_videochip_status(struct hd64461video_chip *hvc) 850 { 851 struct video_chip *vc = &hvc->vc; 852 u_int16_t r; 853 int i; 854 int depth, width, height; 855 856 /* display mode */ 857 r = hd64461_reg_read_2(HD64461_LCDLDR3_REG16); 858 i = HD64461_LCDLDR3_CG(r); 859 switch (i) { 860 case HD64461_LCDLDR3_CG_COLOR16: 861 depth = 16; 862 hvc->mode = LCD64K_C; 863 break; 864 case HD64461_LCDLDR3_CG_COLOR8: 865 depth = 8; 866 hvc->mode = LCD256_C; 867 break; 868 case HD64461_LCDLDR3_CG_GRAY6: 869 depth = 6; 870 hvc->mode = LCD64_MONO; 871 break; 872 case HD64461_LCDLDR3_CG_GRAY4: 873 depth = 4; 874 hvc->mode = LCD16_MONO; 875 break; 876 case HD64461_LCDLDR3_CG_GRAY2: 877 depth = 2; 878 hvc->mode = LCD4_MONO; 879 break; 880 case HD64461_LCDLDR3_CG_GRAY1: 881 depth = 1; 882 hvc->mode = LCD2_MONO; 883 break; 884 } 885 886 r = hd64461_reg_read_2(HD64461_LCDCCR_REG16); 887 i = HD64461_LCDCCR_DSPSEL(i); 888 switch (i) { 889 case HD64461_LCDCCR_DSPSEL_LCD_CRT: 890 depth = 8; 891 hvc->mode = LCDCRT; 892 break; 893 case HD64461_LCDCCR_DSPSEL_CRT: 894 depth = 8; 895 hvc->mode = CRT256_C; 896 break; 897 case HD64461_LCDCCR_DSPSEL_LCD: 898 /* nothing to do */ 899 break; 900 } 901 902 width = bootinfo->fb_width; 903 height = bootinfo->fb_height; 904 905 vc->vc_fbvaddr = HD64461_FBBASE; 906 vc->vc_fbpaddr = HD64461_FBBASE; 907 vc->vc_fbdepth = depth; 908 vc->vc_fbsize = (width * height * depth) / NBBY; 909 vc->vc_fbwidth = width; 910 vc->vc_fbheight = height; 911 } 912 913 #if notyet 914 void 915 hd64461video_set_display_mode(struct hd64461video_chip *hvc) 916 { 917 918 if (hvc->mode == LCDCRT || hvc->mode == CRT256_C) 919 hd64461video_set_display_mode_crtc(hvc); 920 921 hd64461video_set_display_mode_lcdc(hvc); 922 } 923 924 void 925 hd64461video_set_display_mode_lcdc(struct hd64461video_chip *hvc) 926 { 927 struct { 928 u_int16_t clor; /* display size 640 x 240 */ 929 u_int16_t ldr3; 930 const char *name; 931 } disp_conf[] = { 932 [LCD256_C] = { 0x280 , HD64461_LCDLDR3_CG_COLOR8 , 933 "8bit color" }, 934 [LCD64K_C] = { 0x500 , HD64461_LCDLDR3_CG_COLOR16 , 935 "16bit color" }, 936 [LCD64_MONO] = { 0x280 , HD64461_LCDLDR3_CG_GRAY6 , 937 "6bit gray scale" }, 938 [LCD16_MONO] = { 0x140 , HD64461_LCDLDR3_CG_GRAY4 , 939 "4bit gray scale" }, 940 [LCD4_MONO] = { 0x0a0 , HD64461_LCDLDR3_CG_GRAY2 , 941 "2bit gray scale" }, 942 [LCD2_MONO] = { 0x050 , HD64461_LCDLDR3_CG_GRAY1 , 943 "mono chrome" }, 944 }, *conf; 945 u_int16_t r; 946 int omode; 947 948 conf = &disp_conf[hvc->mode]; 949 950 hd64461_reg_write_2(HD64461_LCDCLOR_REG16, conf->clor); 951 r = hd64461_reg_read_2(HD64461_LCDLDR3_REG16); 952 omode = HD64461_LCDLDR3_CG(r); 953 r = HD64461_LCDLDR3_CG_CLR(r); 954 r = HD64461_LCDLDR3_CG_SET(r, conf->ldr3); 955 hd64461_reg_write_2(HD64461_LCDLDR3_REG16, r); 956 957 printf("%s ", conf->name); 958 } 959 960 void 961 hd64461video_set_display_mode_crtc(struct hd64461video_chip *hvc) 962 { 963 /* not yet */ 964 } 965 #endif /* notyet */ 966 967 size_t 968 hd64461video_frame_buffer_size(struct hd64461video_chip *hvc) 969 { 970 vaddr_t page, startaddr, endaddr; 971 int x; 972 973 startaddr = HD64461_FBBASE; 974 endaddr = startaddr + HD64461_FBSIZE - 1; 975 976 page = startaddr; 977 978 x = random(); 979 *(volatile int *)(page + 0) = x; 980 *(volatile int *)(page + 4) = ~x; 981 982 if (*(volatile int *)(page + 0) != x || 983 *(volatile int *)(page + 4) != ~x) 984 return (0); 985 986 for (page += HD64461_FBPAGESIZE; page < endaddr; 987 page += HD64461_FBPAGESIZE) { 988 if (*(volatile int *)(page + 0) == x && 989 *(volatile int *)(page + 4) == ~x) 990 goto fbend_found; 991 } 992 993 page -= HD64461_FBPAGESIZE; 994 *(volatile int *)(page + 0) = x; 995 *(volatile int *)(page + 4) = ~x; 996 997 if (*(volatile int *)(page + 0) != x || 998 *(volatile int *)(page + 4) != ~x) 999 return (0); 1000 1001 fbend_found: 1002 return (page - startaddr); 1003 } 1004 1005 void 1006 hd64461video_set_clut(struct hd64461video_chip *vc, int idx, int cnt, 1007 u_int8_t *r, u_int8_t *g, u_int8_t *b) 1008 { 1009 KASSERT(r && g && b); 1010 1011 /* index pallete */ 1012 hd64461_reg_write_2(HD64461_LCDCPTWAR_REG16, 1013 HD64461_LCDCPTWAR_SET(0, idx)); 1014 /* set data */ 1015 while (cnt && LEGAL_CLUT_INDEX(idx)) { 1016 u_int16_t v; 1017 #define HD64461VIDEO_SET_CLUT(x) \ 1018 v = (x >> 2) & 0x3f; \ 1019 hd64461_reg_write_2(HD64461_LCDCPTWDR_REG16, v) 1020 HD64461VIDEO_SET_CLUT(*r); 1021 HD64461VIDEO_SET_CLUT(*g); 1022 HD64461VIDEO_SET_CLUT(*b); 1023 #undef HD64461VIDEO_SET_CLUT 1024 r++, g++, b++; 1025 idx++, cnt--; 1026 } 1027 } 1028 1029 void 1030 hd64461video_get_clut(struct hd64461video_chip *vc, int idx, int cnt, 1031 u_int8_t *r, u_int8_t *g, u_int8_t *b) 1032 { 1033 KASSERT(r && g && b); 1034 1035 /* index pallete */ 1036 hd64461_reg_write_2(HD64461_LCDCPTRAR_REG16, 1037 HD64461_LCDCPTRAR_SET(0, idx)); 1038 1039 /* get data */ 1040 while (cnt && LEGAL_CLUT_INDEX(idx)) { 1041 u_int16_t v; 1042 #define HD64461VIDEO_GET_CLUT(x) \ 1043 v = hd64461_reg_read_2(HD64461_LCDCPTWDR_REG16); \ 1044 x = HD64461_LCDCPTRDR(v); \ 1045 x <<= 2 1046 HD64461VIDEO_GET_CLUT(*r); 1047 HD64461VIDEO_GET_CLUT(*g); 1048 HD64461VIDEO_GET_CLUT(*b); 1049 #undef HD64461VIDEO_GET_CLUT 1050 r++, g++, b++; 1051 idx++, cnt--; 1052 } 1053 } 1054 1055 #ifdef HD64461VIDEO_DEBUG 1056 void 1057 hd64461video_info(struct hd64461video_softc *sc) 1058 { 1059 u_int16_t r; 1060 int color; 1061 int i; 1062 1063 dbg_banner_function(); 1064 printf("---[LCD]---\n"); 1065 /* Base Address Register */ 1066 r = hd64461_reg_read_2(HD64461_LCDCBAR_REG16); 1067 printf("LCDCBAR Frame buffer base address (4k Byte align): 0x%08x\n", 1068 HD64461_LCDCBAR_BASEADDR(r)); 1069 1070 /* Line Address Offset Register */ 1071 r = hd64461_reg_read_2(HD64461_LCDCLOR_REG16); 1072 printf("LCDCLOR Line address offset: %d\n", HD64461_LCDCLOR(r)); 1073 1074 /* LCDC Control Register */ 1075 r = hd64461_reg_read_2(HD64461_LCDCCR_REG16); 1076 i = HD64461_LCDCCR_DSPSEL(r); 1077 #define DBG_BITMASK_PRINT(r, m) dbg_bitmask_print(r, HD64461_LCDCCR_##m, #m) 1078 printf("LCDCCR (LCD Control Register)\n"); 1079 DBG_BITMASK_PRINT(r, STBAK); 1080 DBG_BITMASK_PRINT(r, STREQ); 1081 DBG_BITMASK_PRINT(r, MOFF); 1082 DBG_BITMASK_PRINT(r, REFSEL); 1083 DBG_BITMASK_PRINT(r, EPON); 1084 DBG_BITMASK_PRINT(r, SPON); 1085 printf("\n"); 1086 #undef DBG_BITMASK_PRINT 1087 printf("LCDCCR Display selct LCD[%c] CRT[%c]\n", 1088 i == HD64461_LCDCCR_DSPSEL_LCD_CRT || 1089 i == HD64461_LCDCCR_DSPSEL_LCD ? 'x' : '_', 1090 i == HD64461_LCDCCR_DSPSEL_LCD_CRT || 1091 i == HD64461_LCDCCR_DSPSEL_CRT ? 'x' : '_'); 1092 1093 /* LCD Display Register */ 1094 /* 1 */ 1095 r = hd64461_reg_read_2(HD64461_LCDLDR1_REG16); 1096 printf("(LCD Display Register)\n"); 1097 #define DBG_BITMASK_PRINT(r, m) dbg_bitmask_print(r, HD64461_LCDLDR1_##m, #m) 1098 printf("LCDLDR1: "); 1099 DBG_BITMASK_PRINT(r, DINV); 1100 DBG_BITMASK_PRINT(r, DON); 1101 printf("\n"); 1102 #undef DBG_BITMASK_PRINT 1103 /* 2 */ 1104 r = hd64461_reg_read_2(HD64461_LCDLDR2_REG16); 1105 i = HD64461_LCDLDR2_LM(r); 1106 #define DBG_BITMASK_PRINT(r, m) dbg_bitmask_print(r, HD64461_LCDLDR2_##m, #m) 1107 printf("LCDLDR2: "); 1108 DBG_BITMASK_PRINT(r, CC1); 1109 DBG_BITMASK_PRINT(r, CC2); 1110 #undef DBG_BITMASK_PRINT 1111 color = 0; 1112 switch (i) { 1113 default: 1114 panic("unknown unknown LCD interface."); 1115 break; 1116 case HD64461_LCDLDR2_LM_COLOR: 1117 color = 1; 1118 printf("Color"); 1119 break; 1120 case HD64461_LCDLDR2_LM_GRAY8: 1121 printf("8-bit grayscale"); 1122 break; 1123 case HD64461_LCDLDR2_LM_GRAY4: 1124 printf("8-bit grayscale"); 1125 break; 1126 } 1127 printf(" LCD interface\n"); 1128 /* 3 */ 1129 printf("LCDLDR3: "); 1130 r = hd64461_reg_read_2(HD64461_LCDLDR3_REG16); 1131 i = HD64461_LCDLDR3_CS(r); 1132 printf("CS "); 1133 switch (i) { 1134 case 0: 1135 printf("15"); 1136 break; 1137 case 1: 1138 printf("2.5"); 1139 break; 1140 case 2: 1141 printf("3.75"); 1142 break; 1143 case 4: 1144 printf("5"); 1145 break; 1146 case 8: 1147 printf("7.5"); 1148 break; 1149 case 16: 1150 printf("10"); 1151 break; 1152 } 1153 printf("%s MHz ", color ? "" : "/2"); 1154 i = HD64461_LCDLDR3_CG(r); 1155 switch (i) { 1156 case HD64461_LCDLDR3_CG_COLOR16: 1157 printf("Color 64K colors\n"); 1158 break; 1159 case HD64461_LCDLDR3_CG_COLOR8: 1160 printf("Color 256 colors\n"); 1161 break; 1162 case HD64461_LCDLDR3_CG_GRAY6: 1163 printf("6-bit Grayscale\n"); 1164 break; 1165 case HD64461_LCDLDR3_CG_GRAY4: 1166 printf("4-bit Grayscale\n"); 1167 break; 1168 case HD64461_LCDLDR3_CG_GRAY2: 1169 printf("2-bit Grayscale\n"); 1170 break; 1171 case HD64461_LCDLDR3_CG_GRAY1: 1172 printf("1-bit Grayscale\n"); 1173 break; 1174 } 1175 1176 /* LCD Number of Characters in Horizontal Register */ 1177 r = hd64461_reg_read_2(HD64461_LCDLDHNCR_REG16); 1178 printf("LDHNCR: NHD %d NHT %d (# of horizontal characters)\n", 1179 HD64461_LCDLDHNCR_NHD(r), HD64461_LCDLDHNCR_NHT(r)); 1180 1181 /* Start Position of Horizontal Register */ 1182 r = hd64461_reg_read_2(HD64461_LCDLDHNSR_REG16); 1183 printf("LDHNSR: HSW %d HSP %d (start position of horizontal)\n", 1184 HD64461_LCDLDHNSR_HSW(r), HD64461_LCDLDHNSR_HSP(r)); 1185 1186 /* Total Vertical Lines Register */ 1187 r = hd64461_reg_read_2(HD64461_LCDLDVNTR_REG16); 1188 printf("LDVNTR: %d (total vertical lines)\n", 1189 HD64461_LCDLDVNTR_VTL(r)); 1190 1191 /* Display Vertical Lines Register */ 1192 r = hd64461_reg_read_2(HD64461_LCDLDVNDR_REG16); 1193 printf("LDVNDR: %d (display vertical lines)\n", 1194 HD64461_LCDLDVSPR_VSP(r)); 1195 1196 /* Vertical Synchronization Position Register */ 1197 r = hd64461_reg_read_2(HD64461_LCDLDVSPR_REG16); 1198 printf("LDVSPR: %d (vertical synchronization position)\n", 1199 HD64461_LCDLDVSPR_VSP(r)); 1200 1201 /* 1202 * CRT Control Register 1203 */ 1204 printf("---[CRT]---\n"); 1205 r = hd64461_reg_read_2(HD64461_LCDCRTVTR_REG16); 1206 printf("CRTVTR: %d (CRTC total vertical lines)\n", 1207 HD64461_LCDCRTVTR(r)); 1208 r = hd64461_reg_read_2(HD64461_LCDCRTVRSR_REG16); 1209 printf("CRTVRSR: %d (CRTC vertical retrace start line)\n", 1210 HD64461_LCDCRTVRSR(r)); 1211 r = hd64461_reg_read_2(HD64461_LCDCRTVRER_REG16); 1212 printf("CRTVRER: %d (CRTC vertical retrace end line)\n", 1213 HD64461_LCDCRTVRER(r)); 1214 1215 } 1216 1217 void 1218 hd64461video_dump() 1219 { 1220 u_int16_t r; 1221 printf("---[Display Mode Setting]---\n"); 1222 #define DUMPREG(x) \ 1223 r = hd64461_reg_read_2(HD64461_LCD ## x ## _REG16); \ 1224 __dbg_bit_print(r, sizeof(u_int16_t), 0, 0, #x, DBG_BIT_PRINT_COUNT) 1225 DUMPREG(CBAR); 1226 DUMPREG(CLOR); 1227 DUMPREG(CCR); 1228 DUMPREG(LDR1); 1229 DUMPREG(LDR2); 1230 DUMPREG(LDHNCR); 1231 DUMPREG(LDHNSR); 1232 DUMPREG(LDVNTR); 1233 DUMPREG(LDVNDR); 1234 DUMPREG(LDVSPR); 1235 DUMPREG(LDR3); 1236 DUMPREG(CRTVTR); 1237 DUMPREG(CRTVRSR); 1238 DUMPREG(CRTVRER); 1239 #undef DUMPREG 1240 dbg_banner_line(); 1241 } 1242 1243 #endif /* HD64461VIDEO_DEBUG */ 1244