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