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