1 /* $NetBSD: s3c24x0_lcd.c,v 1.6 2007/12/15 00:39:15 perry Exp $ */ 2 3 /* 4 * Copyright (c) 2004 Genetec Corporation. All rights reserved. 5 * Written by Hiroyuki Bessho for Genetec Corporation. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of Genetec Corporation may not be used to endorse or 16 * promote products derived from this software without specific prior 17 * written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND 20 * 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 GENETEC CORPORATION 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 /* 33 * Support S3C24[10]0's integrated LCD controller. 34 */ 35 36 #include <sys/cdefs.h> 37 __KERNEL_RCSID(0, "$NetBSD: s3c24x0_lcd.c,v 1.6 2007/12/15 00:39:15 perry Exp $"); 38 39 #include <sys/param.h> 40 #include <sys/systm.h> 41 #include <sys/conf.h> 42 #include <sys/uio.h> 43 #include <sys/malloc.h> 44 #include <sys/kernel.h> /* for cold */ 45 46 #include <uvm/uvm_extern.h> 47 48 #include <dev/cons.h> 49 #include <dev/wscons/wsconsio.h> 50 #include <dev/wscons/wsdisplayvar.h> 51 #include <dev/wscons/wscons_callbacks.h> 52 #include <dev/rasops/rasops.h> 53 #include <dev/wsfont/wsfont.h> 54 55 #include <machine/bus.h> 56 #include <machine/cpu.h> 57 #include <arm/cpufunc.h> 58 59 #include <arm/s3c2xx0/s3c24x0var.h> 60 #include <arm/s3c2xx0/s3c24x0reg.h> 61 #include <arm/s3c2xx0/s3c24x0_lcd.h> 62 63 #include "wsdisplay.h" 64 65 int lcdintr(void *); 66 static void init_palette(struct s3c24x0_lcd_softc *, 67 struct s3c24x0_lcd_screen *); 68 69 #ifdef LCD_DEBUG 70 static void 71 dump_lcdcon(const char *title, bus_space_tag_t iot, bus_space_handle_t ioh) 72 { 73 int i; 74 75 printf("%s\n", title); 76 for(i=LCDC_LCDCON1; i <= LCDC_LCDSADDR3; i+=4) { 77 if (i%16 == 0) 78 printf("\n%03x: ", i); 79 printf("%08x ", bus_space_read_4(iot, ioh, i)); 80 } 81 82 printf("\n"); 83 } 84 85 void draw_test_pattern(struct s3c24x0_lcd_softc *, 86 struct s3c24x0_lcd_screen *scr); 87 88 #endif 89 90 void 91 s3c24x0_set_lcd_panel_info(struct s3c24x0_lcd_softc *sc, 92 const struct s3c24x0_lcd_panel_info *info) 93 { 94 bus_space_tag_t iot = sc->iot; 95 bus_space_handle_t ioh = sc->ioh; 96 uint32_t reg; 97 int clkval; 98 int tft = s3c24x0_lcd_panel_tft(info); 99 int hclk = s3c2xx0_softc->sc_hclk; 100 101 sc->panel_info = info; 102 103 /* Set LCDCON1. BPPMODE and ENVID are set later */ 104 if (tft) 105 clkval = (hclk / info->pixel_clock / 2) - 1; 106 else { 107 /* STN display */ 108 clkval = max(2, hclk / info->pixel_clock / 2); 109 } 110 111 reg = (info->lcdcon1 & ~LCDCON1_CLKVAL_MASK) | 112 (clkval << LCDCON1_CLKVAL_SHIFT); 113 reg &= ~LCDCON1_ENVID; 114 bus_space_write_4(iot, ioh, LCDC_LCDCON1, reg); 115 116 #if 0 117 printf("hclk=%d pixel clock=%d, clkval = %x lcdcon1=%x\n", 118 hclk, info->pixel_clock, clkval, reg); 119 #endif 120 121 bus_space_write_4(iot, ioh, LCDC_LCDCON2, info->lcdcon2); 122 bus_space_write_4(iot, ioh, LCDC_LCDCON3, info->lcdcon3); 123 bus_space_write_4(iot, ioh, LCDC_LCDCON4, info->lcdcon4); 124 bus_space_write_4(iot, ioh, LCDC_LCDCON5, info->lcdcon5); 125 bus_space_write_4(iot, ioh, LCDC_LPCSEL, info->lpcsel); 126 } 127 128 void 129 s3c24x0_lcd_attach_sub(struct s3c24x0_lcd_softc *sc, 130 struct s3c2xx0_attach_args *sa, 131 const struct s3c24x0_lcd_panel_info *panel_info) 132 { 133 bus_space_tag_t iot = sa->sa_iot; 134 bus_space_handle_t ioh; 135 int error; 136 137 sc->n_screens = 0; 138 LIST_INIT(&sc->screens); 139 140 /* map controller registers */ 141 error = bus_space_map(iot, sa->sa_addr, S3C24X0_LCDC_SIZE, 0, &ioh); 142 if (error) { 143 printf(": failed to map registers %d", error); 144 return; 145 } 146 147 sc->iot = iot; 148 sc->ioh = ioh; 149 sc->dma_tag = sa->sa_dmat; 150 151 #ifdef notyet 152 sc->ih = s3c24x0_intr_establish(sa->sa_intr, IPL_BIO, lcdintr, sc); 153 if (sc->ih == NULL) 154 printf("%s: unable to establish interrupt at irq %d", 155 sc->dev.dv_xname, sa->sa_intr); 156 #endif 157 158 /* mask LCD interrupts */ 159 bus_space_write_4(iot, ioh, LCDC_LCDINTMSK, LCDINT_FICNT|LCDINT_FRSYN); 160 161 /* Initialize controller registers based on panel geometry*/ 162 s3c24x0_set_lcd_panel_info(sc, panel_info); 163 164 /* XXX: enable clock to LCD controller */ 165 } 166 167 168 #ifdef notyet 169 int 170 lcdintr(void *arg) 171 { 172 struct s3c24x0_lcd_softc *sc = arg; 173 bus_space_tag_t iot = sc->iot; 174 bus_space_handle_t ioh = sc->ioh; 175 176 static uint32_t status; 177 178 return 1; 179 } 180 #endif 181 182 int 183 s3c24x0_lcd_start_dma(struct s3c24x0_lcd_softc *sc, 184 struct s3c24x0_lcd_screen *scr) 185 { 186 bus_space_tag_t iot = sc->iot; 187 bus_space_handle_t ioh = sc->ioh; 188 const struct s3c24x0_lcd_panel_info *info = sc->panel_info; 189 int tft = s3c24x0_lcd_panel_tft(info); 190 int dual_panel = 191 (info->lcdcon1 & LCDCON1_PNRMODE_MASK) == LCDCON1_PNRMODE_DUALSTN4; 192 uint32_t lcdcon1, val; 193 paddr_t pa; 194 int depth = scr->depth; 195 int stride = scr->stride; 196 int panel_height = info->panel_height; 197 int panel_width = info->panel_width; 198 int offsize; 199 200 switch (depth) { 201 case 1: val = LCDCON1_BPPMODE_STN1; break; 202 case 2: val = LCDCON1_BPPMODE_STN2; break; 203 case 4: val = LCDCON1_BPPMODE_STN4; break; 204 case 8: val = LCDCON1_BPPMODE_STN8; break; 205 case 12: 206 if (tft) 207 return -1; 208 val = LCDCON1_BPPMODE_STN12; 209 break; 210 case 16: 211 if (!tft) 212 return -1; 213 val = LCDCON1_BPPMODE_TFT16; 214 break; 215 case 24: 216 if (!tft) 217 return -1; 218 val = LCDCON1_BPPMODE_TFT24; 219 break; 220 default: 221 return -1; 222 } 223 224 if (tft) 225 val |= LCDCON1_BPPMODE_TFTX; 226 227 lcdcon1 = bus_space_read_4(iot, ioh, LCDC_LCDCON1); 228 lcdcon1 &= ~(LCDCON1_BPPMODE_MASK|LCDCON1_ENVID); 229 lcdcon1 |= val; 230 bus_space_write_4(iot, ioh, LCDC_LCDCON1, lcdcon1); 231 232 /* Adjust LCDCON3.HOZVAL to meet with restriction */ 233 val = roundup(panel_width, 16 / depth); 234 bus_space_write_4(iot, ioh, LCDC_LCDCON3, 235 (info->lcdcon3 & ~LCDCON3_HOZVAL_MASK) | 236 (val - 1) << LCDCON3_HOZVAL_SHIFT); 237 238 pa = scr->segs[0].ds_addr; 239 bus_space_write_4(iot, ioh, LCDC_LCDSADDR1, pa >> 1); 240 241 if (dual_panel) { 242 /* XXX */ 243 } 244 else { 245 pa += stride * panel_height; 246 bus_space_write_4(iot, ioh, LCDC_LCDSADDR2, pa >> 1); 247 } 248 249 offsize = stride / sizeof (uint16_t) - (panel_width * depth / 16); 250 bus_space_write_4(iot, ioh, LCDC_LCDSADDR3, 251 (offsize << LCDSADDR3_OFFSIZE_SHIFT) | 252 (panel_width * depth / 16)); 253 254 /* set byte- or halfword- swap based on the depth */ 255 val = bus_space_read_4(iot, ioh, LCDC_LCDCON5); 256 val &= ~(LCDCON5_BSWP|LCDCON5_HWSWP); 257 switch(depth) { 258 case 2: 259 case 4: 260 case 8: 261 val |= LCDCON5_BSWP; 262 break; 263 case 16: 264 val |= LCDCON5_HWSWP; 265 break; 266 } 267 bus_space_write_4(iot, ioh, LCDC_LCDCON5, val); 268 269 270 init_palette(sc, scr); 271 272 #if 0 273 bus_space_write_4(iot, ioh, LCDC_TPAL, TPAL_TPALEN| 274 (0xff<<TPAL_BLUE_SHIFT)); 275 #endif 276 277 /* Enable LCDC */ 278 bus_space_write_4(iot, ioh, LCDC_LCDCON1, lcdcon1 | LCDCON1_ENVID); 279 280 sc->lcd_on = 1; 281 282 #ifdef LCD_DEBUG 283 dump_lcdcon(__func__, iot, ioh); 284 #endif 285 286 return 0; 287 } 288 289 void 290 s3c24x0_lcd_power(struct s3c24x0_lcd_softc *sc, int on) 291 { 292 bus_space_tag_t iot = sc->iot; 293 bus_space_handle_t ioh = sc->ioh; 294 uint32_t reg; 295 296 reg = bus_space_read_4(iot, ioh, LCDC_LCDCON5); 297 298 if (on) 299 reg |= LCDCON5_PWREN; 300 else 301 reg &= ~LCDCON5_PWREN; 302 303 bus_space_write_4(iot, ioh, LCDC_LCDCON5, reg); 304 } 305 306 struct s3c24x0_lcd_screen * 307 s3c24x0_lcd_new_screen(struct s3c24x0_lcd_softc *sc, 308 int virtual_width, int virtual_height, int depth) 309 { 310 struct s3c24x0_lcd_screen *scr = NULL; 311 int width, height; 312 bus_size_t size; 313 int error, pallet_size; 314 int busdma_flag = (cold ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK) | 315 BUS_DMA_WRITE; 316 paddr_t align; 317 const struct s3c24x0_lcd_panel_info *panel_info = sc->panel_info; 318 319 320 #ifdef DIAGNOSTIC 321 if (size > 1 << 22) { 322 aprint_error("%s: too big screen size\n", sc->dev.dv_xname); 323 return NULL; 324 } 325 #endif 326 327 width = panel_info->panel_width; 328 height = panel_info->panel_height; 329 pallet_size = 0; 330 331 switch (depth) { 332 case 1: case 2: case 4: case 8: 333 virtual_width = roundup(virtual_width, 16 / depth); 334 break; 335 case 16: 336 break; 337 case 12: case 24: 338 default: 339 aprint_error("%s: Unknown depth (%d)\n", 340 sc->dev.dv_xname, depth); 341 return NULL; 342 } 343 344 scr = malloc(sizeof *scr, M_DEVBUF, 345 M_ZERO | (cold ? M_NOWAIT : M_WAITOK)); 346 347 if (scr == NULL) 348 return NULL; 349 350 scr->nsegs = 0; 351 scr->depth = depth; 352 scr->stride = virtual_width * depth / 8; 353 scr->buf_size = size = scr->stride * virtual_height; 354 scr->buf_va = NULL; 355 356 /* calculate the alignment for LCD frame buffer. 357 the buffer can't across 4MB boundary */ 358 align = 1 << 20; 359 while (align < size) 360 align <<= 1; 361 362 error = bus_dmamem_alloc(sc->dma_tag, size, align, 0, 363 scr->segs, 1, &(scr->nsegs), busdma_flag); 364 365 if (error || scr->nsegs != 1) 366 goto bad; 367 368 error = bus_dmamem_map(sc->dma_tag, scr->segs, scr->nsegs, 369 size, (void **)&(scr->buf_va), busdma_flag | BUS_DMA_COHERENT); 370 if (error) 371 goto bad; 372 373 374 memset (scr->buf_va, 0, scr->buf_size); 375 376 /* map memory for DMA */ 377 if (bus_dmamap_create(sc->dma_tag, 1024*1024*2, 1, 378 1024*1024*2, 0, busdma_flag, &scr->dma)) 379 goto bad; 380 error = bus_dmamap_load(sc->dma_tag, scr->dma, 381 scr->buf_va, size, NULL, busdma_flag); 382 if (error) 383 goto bad; 384 385 LIST_INSERT_HEAD(&(sc->screens), scr, link); 386 sc->n_screens++; 387 388 #ifdef LCD_DEBUG 389 draw_test_pattern(sc, scr); 390 dump_lcdcon(__func__, sc->iot, sc->ioh); 391 #endif 392 return scr; 393 394 bad: 395 if (scr) { 396 if (scr->buf_va) 397 bus_dmamem_unmap(sc->dma_tag, scr->buf_va, size); 398 if (scr->nsegs) 399 bus_dmamem_free(sc->dma_tag, scr->segs, scr->nsegs); 400 free(scr, M_DEVBUF); 401 } 402 return NULL; 403 } 404 405 406 #define _rgb(r,g,b) (((r)<<11) | ((g)<<5) | b) 407 #define rgb(r,g,b) _rgb((r)>>1,g,(b)>>1) 408 409 #define L 0x30 /* low intensity */ 410 #define H 0x3f /* hight intensity */ 411 412 static const uint16_t basic_color_map[] = { 413 rgb( 0, 0, 0), /* black */ 414 rgb( L, 0, 0), /* red */ 415 rgb( 0, L, 0), /* green */ 416 rgb( L, L, 0), /* brown */ 417 rgb( 0, 0, L), /* blue */ 418 rgb( L, 0, L), /* magenta */ 419 rgb( 0, L, L), /* cyan */ 420 _rgb(0x1c,0x38,0x1c), /* white */ 421 422 rgb( L, L, L), /* black */ 423 rgb( H, 0, 0), /* red */ 424 rgb( 0, H, 0), /* green */ 425 rgb( H, H, 0), /* brown */ 426 rgb( 0, 0, H), /* blue */ 427 rgb( H, 0, H), /* magenta */ 428 rgb( 0, H, H), /* cyan */ 429 rgb( H, H, H), /* white */ 430 }; 431 432 #define COLORMAP_LEN (sizeof basic_color_map / sizeof basic_color_map[0]) 433 434 #undef H 435 #undef L 436 437 static void 438 init_palette(struct s3c24x0_lcd_softc *sc, struct s3c24x0_lcd_screen *scr) 439 { 440 int depth = scr->depth; 441 bus_space_tag_t iot = sc->iot; 442 bus_space_handle_t ioh = sc->ioh; 443 int i; 444 445 i = 0; 446 447 switch(depth) { 448 default: 449 case 16: /* not using palette */ 450 return; 451 case 8: 452 while (i < COLORMAP_LEN) { 453 bus_space_write_4(iot, ioh, LCDC_PALETTE + 4*i, 454 basic_color_map[i]); 455 ++i; 456 } 457 break; 458 case 4: 459 case 2: 460 /* XXX */ 461 break; 462 case 1: 463 bus_space_write_4(iot, ioh, LCDC_PALETTE + 4 * i, 464 basic_color_map[i]); /* black */ 465 ++i; 466 bus_space_write_4(iot, ioh, LCDC_PALETTE + 4 * i, 467 basic_color_map[7]); /* white */ 468 break; 469 } 470 471 #ifdef DIAGNOSTIC 472 /* Fill unused entries */ 473 for ( ; i < 256; ++i ) 474 bus_space_write_4(iot, ioh, LCDC_PALETTE + 4 * i, 475 basic_color_map[1]); /* red */ 476 #endif 477 } 478 479 480 #if NWSDISPLAY > 0 481 482 static void 483 s3c24x0_lcd_stop_dma(struct s3c24x0_lcd_softc *sc) 484 { 485 /* Stop LCD output */ 486 bus_space_write_4(sc->iot, sc->ioh, LCDC_LCDCON1, 487 ~LCDCON1_ENVID & 488 bus_space_read_4(sc->iot, sc->ioh, LCDC_LCDCON1)); 489 490 491 sc->lcd_on = 0; 492 } 493 494 int 495 s3c24x0_lcd_show_screen(void *v, void *cookie, int waitok, 496 void (*cb)(void *, int, int), void *cbarg) 497 { 498 struct s3c24x0_lcd_softc *sc = v; 499 struct s3c24x0_lcd_screen *scr = cookie, *old; 500 501 /* XXX: make sure the clock is provided for LCD controller */ 502 503 old = sc->active; 504 if (old == scr && sc->lcd_on) 505 return 0; 506 507 if (old) 508 s3c24x0_lcd_stop_dma(sc); 509 510 s3c24x0_lcd_start_dma(sc, scr); 511 sc->active = scr; 512 s3c24x0_lcd_power(sc, 1); 513 514 /* XXX: callback */ 515 516 return 0; 517 } 518 519 int 520 s3c24x0_lcd_alloc_screen(void *v, const struct wsscreen_descr *_type, 521 void **cookiep, int *curxp, int *curyp, long *attrp) 522 { 523 struct s3c24x0_lcd_softc *sc = v; 524 struct s3c24x0_lcd_screen *scr; 525 const struct s3c24x0_wsscreen_descr *type = 526 (const struct s3c24x0_wsscreen_descr *)_type; 527 528 int width, height; 529 530 width = type->c.ncols * type->c.fontwidth; 531 height = type->c.nrows * type->c.fontwidth; 532 533 if (width < sc->panel_info->panel_width) 534 width = sc->panel_info->panel_width; 535 if (height < sc->panel_info->panel_height) 536 height = sc->panel_info->panel_height; 537 538 539 scr = s3c24x0_lcd_new_screen(sc, width, height, type->depth); 540 if (scr == NULL) 541 return -1; 542 543 /* 544 * initialize raster operation for this screen. 545 */ 546 scr->rinfo.ri_flg = 0; 547 scr->rinfo.ri_depth = type->depth; 548 scr->rinfo.ri_bits = scr->buf_va; 549 scr->rinfo.ri_width = width; 550 scr->rinfo.ri_height = height; 551 scr->rinfo.ri_stride = scr->stride; 552 553 if (type->c.fontwidth || type->c.fontheight) { 554 /* 555 * find a font with specified size 556 */ 557 int cookie; 558 559 wsfont_init(); 560 561 cookie = wsfont_find(NULL, type->c.fontwidth, 562 type->c.fontheight, 0, WSDISPLAY_FONTORDER_L2R, 563 WSDISPLAY_FONTORDER_L2R); 564 565 if (cookie > 0) { 566 if (wsfont_lock(cookie, &scr->rinfo.ri_font)) 567 scr->rinfo.ri_wsfcookie = cookie; 568 } 569 } 570 571 rasops_init(&scr->rinfo, type->c.nrows, type->c.ncols); 572 573 (* scr->rinfo.ri_ops.allocattr)(&scr->rinfo, 0, 0, 0, attrp); 574 575 if (type->c.nrows != scr->rinfo.ri_rows || 576 type->c.ncols != scr->rinfo.ri_cols) { 577 578 aprint_error("%s: can't allocate a screen with requested size:" 579 "%d x %d -> %d x %d\n", 580 sc->dev.dv_xname, 581 type->c.ncols, type->c.nrows, 582 scr->rinfo.ri_cols, scr->rinfo.ri_rows); 583 } 584 585 *cookiep = scr; 586 *curxp = 0; 587 *curyp = 0; 588 589 return 0; 590 } 591 592 593 void 594 s3c24x0_lcd_free_screen(void *v, void *cookie) 595 { 596 struct s3c24x0_lcd_softc *sc = v; 597 struct s3c24x0_lcd_screen *scr = cookie; 598 599 LIST_REMOVE(scr, link); 600 sc->n_screens--; 601 if (scr == sc->active) { 602 sc->active = NULL; 603 604 /* XXX: We need a good procedure to shutdown the LCD. */ 605 606 s3c24x0_lcd_stop_dma(sc); 607 s3c24x0_lcd_power(sc, 0); 608 } 609 610 if (scr->buf_va) 611 bus_dmamem_unmap(sc->dma_tag, scr->buf_va, scr->map_size); 612 613 if (scr->nsegs > 0) 614 bus_dmamem_free(sc->dma_tag, scr->segs, scr->nsegs); 615 616 free(scr, M_DEVBUF); 617 } 618 619 int 620 s3c24x0_lcd_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, 621 struct lwp *l) 622 { 623 struct s3c24x0_lcd_softc *sc = v; 624 struct wsdisplay_fbinfo *wsdisp_info; 625 struct s3c24x0_lcd_screen *scr; 626 627 628 switch (cmd) { 629 case WSDISPLAYIO_GTYPE: 630 *(u_int *)data = WSDISPLAY_TYPE_UNKNOWN; /* XXX */ 631 return 0; 632 633 case WSDISPLAYIO_GINFO: 634 wsdisp_info = (struct wsdisplay_fbinfo *)data; 635 636 wsdisp_info->height = sc->panel_info->panel_height; 637 wsdisp_info->width = sc->panel_info->panel_width; 638 wsdisp_info->depth = 16; /* XXX */ 639 wsdisp_info->cmsize = 0; 640 return 0; 641 642 case WSDISPLAYIO_GETCMAP: 643 case WSDISPLAYIO_PUTCMAP: 644 return EPASSTHROUGH; /* XXX Colormap */ 645 646 case WSDISPLAYIO_SVIDEO: 647 if (*(int *)data == WSDISPLAYIO_VIDEO_ON) { 648 scr = sc->active; 649 if (scr == NULL) 650 scr = LIST_FIRST(&sc->screens); 651 652 if (scr == NULL) 653 return ENXIO; 654 655 s3c24x0_lcd_show_screen(sc, scr, 1, NULL, NULL); 656 } 657 else { 658 s3c24x0_lcd_stop_dma(sc); 659 s3c24x0_lcd_power(sc, 0); 660 } 661 return 0; 662 663 case WSDISPLAYIO_GVIDEO: 664 *(u_int *)data = sc->lcd_on; 665 return 0; 666 667 case WSDISPLAYIO_GCURPOS: 668 case WSDISPLAYIO_SCURPOS: 669 case WSDISPLAYIO_GCURMAX: 670 case WSDISPLAYIO_GCURSOR: 671 case WSDISPLAYIO_SCURSOR: 672 return EPASSTHROUGH; /* XXX */ 673 } 674 675 return EPASSTHROUGH; 676 } 677 678 paddr_t 679 s3c24x0_lcd_mmap(void *v, void *vs, off_t offset, int prot) 680 { 681 struct s3c24x0_lcd_softc *sc = v; 682 struct s3c24x0_lcd_screen *screen = sc->active; /* ??? */ 683 684 if (screen == NULL) 685 return -1; 686 687 return bus_dmamem_mmap(sc->dma_tag, screen->segs, screen->nsegs, 688 offset, prot, BUS_DMA_WAITOK|BUS_DMA_COHERENT); 689 return -1; 690 } 691 692 693 static void 694 s3c24x0_lcd_cursor(void *cookie, int on, int row, int col) 695 { 696 struct s3c24x0_lcd_screen *scr = cookie; 697 698 (* scr->rinfo.ri_ops.cursor)(&scr->rinfo, on, row, col); 699 } 700 701 static int 702 s3c24x0_lcd_mapchar(void *cookie, int c, unsigned int *cp) 703 { 704 struct s3c24x0_lcd_screen *scr = cookie; 705 706 return (* scr->rinfo.ri_ops.mapchar)(&scr->rinfo, c, cp); 707 } 708 709 static void 710 s3c24x0_lcd_putchar(void *cookie, int row, int col, u_int uc, long attr) 711 { 712 struct s3c24x0_lcd_screen *scr = cookie; 713 714 (* scr->rinfo.ri_ops.putchar)(&scr->rinfo, 715 row, col, uc, attr); 716 } 717 718 static void 719 s3c24x0_lcd_copycols(void *cookie, int row, int src, int dst, int num) 720 { 721 struct s3c24x0_lcd_screen *scr = cookie; 722 723 (* scr->rinfo.ri_ops.copycols)(&scr->rinfo, 724 row, src, dst, num); 725 } 726 727 static void 728 s3c24x0_lcd_erasecols(void *cookie, int row, int col, int num, long attr) 729 { 730 struct s3c24x0_lcd_screen *scr = cookie; 731 732 (* scr->rinfo.ri_ops.erasecols)(&scr->rinfo, 733 row, col, num, attr); 734 } 735 736 static void 737 s3c24x0_lcd_copyrows(void *cookie, int src, int dst, int num) 738 { 739 struct s3c24x0_lcd_screen *scr = cookie; 740 741 (* scr->rinfo.ri_ops.copyrows)(&scr->rinfo, 742 src, dst, num); 743 } 744 745 static void 746 s3c24x0_lcd_eraserows(void *cookie, int row, int num, long attr) 747 { 748 struct s3c24x0_lcd_screen *scr = cookie; 749 750 (* scr->rinfo.ri_ops.eraserows)(&scr->rinfo, 751 row, num, attr); 752 } 753 754 static int 755 s3c24x0_lcd_alloc_attr(void *cookie, int fg, int bg, int flg, long *attr) 756 { 757 struct s3c24x0_lcd_screen *scr = cookie; 758 759 return (* scr->rinfo.ri_ops.allocattr)(&scr->rinfo, 760 fg, bg, flg, attr); 761 } 762 763 764 const struct wsdisplay_emulops s3c24x0_lcd_emulops = { 765 s3c24x0_lcd_cursor, 766 s3c24x0_lcd_mapchar, 767 s3c24x0_lcd_putchar, 768 s3c24x0_lcd_copycols, 769 s3c24x0_lcd_erasecols, 770 s3c24x0_lcd_copyrows, 771 s3c24x0_lcd_eraserows, 772 s3c24x0_lcd_alloc_attr 773 }; 774 775 #endif /* NWSDISPLAY > 0 */ 776