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