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