1 1.39 rin /* $NetBSD: pxa2x0_lcd.c,v 1.39 2021/11/20 00:15:04 rin Exp $ */ 2 1.1 bsh 3 1.1 bsh /* 4 1.1 bsh * Copyright (c) 2002 Genetec Corporation. All rights reserved. 5 1.1 bsh * Written by Hiroyuki Bessho for Genetec Corporation. 6 1.1 bsh * 7 1.1 bsh * Redistribution and use in source and binary forms, with or without 8 1.1 bsh * modification, are permitted provided that the following conditions 9 1.1 bsh * are met: 10 1.1 bsh * 1. Redistributions of source code must retain the above copyright 11 1.1 bsh * notice, this list of conditions and the following disclaimer. 12 1.1 bsh * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 bsh * notice, this list of conditions and the following disclaimer in the 14 1.1 bsh * documentation and/or other materials provided with the distribution. 15 1.1 bsh * 3. All advertising materials mentioning features or use of this software 16 1.1 bsh * must display the following acknowledgement: 17 1.1 bsh * This product includes software developed for the NetBSD Project by 18 1.1 bsh * Genetec Corporation. 19 1.1 bsh * 4. The name of Genetec Corporation may not be used to endorse or 20 1.1 bsh * promote products derived from this software without specific prior 21 1.1 bsh * written permission. 22 1.1 bsh * 23 1.1 bsh * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND 24 1.1 bsh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 25 1.1 bsh * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 26 1.1 bsh * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENETEC CORPORATION 27 1.1 bsh * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 28 1.1 bsh * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 29 1.1 bsh * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 30 1.1 bsh * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 31 1.1 bsh * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 32 1.1 bsh * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33 1.1 bsh * POSSIBILITY OF SUCH DAMAGE. 34 1.1 bsh */ 35 1.1 bsh 36 1.1 bsh /* 37 1.1 bsh * Support PXA2[15]0's integrated LCD controller. 38 1.1 bsh */ 39 1.6 lukem 40 1.6 lukem #include <sys/cdefs.h> 41 1.39 rin __KERNEL_RCSID(0, "$NetBSD: pxa2x0_lcd.c,v 1.39 2021/11/20 00:15:04 rin Exp $"); 42 1.31 nonaka 43 1.31 nonaka #include "opt_pxa2x0_lcd.h" 44 1.6 lukem 45 1.1 bsh #include <sys/param.h> 46 1.1 bsh #include <sys/systm.h> 47 1.1 bsh #include <sys/conf.h> 48 1.1 bsh #include <sys/uio.h> 49 1.38 thorpej #include <sys/kmem.h> 50 1.1 bsh #include <sys/kernel.h> /* for cold */ 51 1.1 bsh 52 1.2 thorpej #include <uvm/uvm_extern.h> 53 1.2 thorpej 54 1.1 bsh #include <dev/cons.h> 55 1.1 bsh #include <dev/wscons/wsconsio.h> 56 1.1 bsh #include <dev/wscons/wsdisplayvar.h> 57 1.1 bsh #include <dev/wscons/wscons_callbacks.h> 58 1.1 bsh #include <dev/rasops/rasops.h> 59 1.1 bsh #include <dev/wsfont/wsfont.h> 60 1.1 bsh 61 1.32 dyoung #include <sys/bus.h> 62 1.1 bsh #include <machine/cpu.h> 63 1.1 bsh #include <arm/cpufunc.h> 64 1.1 bsh 65 1.10 bsh #include <arm/xscale/pxa2x0cpu.h> 66 1.1 bsh #include <arm/xscale/pxa2x0var.h> 67 1.1 bsh #include <arm/xscale/pxa2x0reg.h> 68 1.1 bsh #include <arm/xscale/pxa2x0_lcd.h> 69 1.5 bsh #include <arm/xscale/pxa2x0_gpio.h> 70 1.1 bsh 71 1.1 bsh #include "wsdisplay.h" 72 1.1 bsh 73 1.16 nonaka /* 74 1.16 nonaka * Console variables. These are necessary since console is setup very early, 75 1.16 nonaka * before devices get attached. 76 1.16 nonaka */ 77 1.16 nonaka struct { 78 1.24 nonaka int is_console; 79 1.16 nonaka struct pxa2x0_wsscreen_descr *descr; 80 1.16 nonaka const struct lcd_panel_geometry *geom; 81 1.16 nonaka } pxa2x0_lcd_console; 82 1.16 nonaka 83 1.30 tsutsui #ifdef PXA2X0_LCD_WRITETHROUGH 84 1.30 tsutsui int pxa2x0_lcd_writethrough = 1; /* patchable */ 85 1.30 tsutsui #else 86 1.30 tsutsui int pxa2x0_lcd_writethrough = 0; 87 1.30 tsutsui #endif 88 1.30 tsutsui 89 1.15 peter int lcdintr(void *); 90 1.15 peter 91 1.15 peter static void pxa2x0_lcd_initialize(struct pxa2x0_lcd_softc *, 92 1.15 peter const struct lcd_panel_geometry *); 93 1.28 bsh #if NWSDISPLAY > 0 94 1.15 peter static void pxa2x0_lcd_setup_rasops(struct pxa2x0_lcd_softc *, 95 1.15 peter struct rasops_info *, struct pxa2x0_wsscreen_descr *, 96 1.15 peter const struct lcd_panel_geometry *); 97 1.28 bsh #endif 98 1.1 bsh 99 1.1 bsh void 100 1.4 bsh pxa2x0_lcd_geometry(struct pxa2x0_lcd_softc *sc, 101 1.4 bsh const struct lcd_panel_geometry *info) 102 1.1 bsh { 103 1.14 ober bus_space_tag_t iot; 104 1.14 ober bus_space_handle_t ioh; 105 1.14 ober uint32_t ccr0; 106 1.1 bsh int lines; 107 1.1 bsh 108 1.15 peter iot = sc->iot; 109 1.15 peter ioh = sc->ioh; 110 1.15 peter sc->geometry = info; 111 1.1 bsh 112 1.1 bsh ccr0 = LCCR0_IMASK; 113 1.22 nonaka if (CPU_IS_PXA270) 114 1.23 nonaka ccr0 |= LCCR0_CMDIM|LCCR0_RDSTM|LCCR0_LDDALT; 115 1.4 bsh if (info->panel_info & LCDPANEL_ACTIVE) 116 1.4 bsh ccr0 |= LCCR0_PAS; /* active mode */ 117 1.4 bsh if ((info->panel_info & (LCDPANEL_DUAL|LCDPANEL_ACTIVE)) 118 1.4 bsh == LCDPANEL_DUAL) 119 1.1 bsh ccr0 |= LCCR0_SDS; /* dual panel */ 120 1.4 bsh if (info->panel_info & LCDPANEL_MONOCHROME) 121 1.1 bsh ccr0 |= LCCR0_CMS; 122 1.4 bsh bus_space_write_4(iot, ioh, LCDC_LCCR0, ccr0); 123 1.1 bsh 124 1.4 bsh bus_space_write_4(iot, ioh, LCDC_LCCR1, 125 1.1 bsh (info->panel_width-1) 126 1.1 bsh | ((info->hsync_pulse_width-1)<<10) 127 1.1 bsh | ((info->end_line_wait-1)<<16) 128 1.4 bsh | ((info->beg_line_wait-1)<<24)); 129 1.1 bsh 130 1.4 bsh if (info->panel_info & LCDPANEL_DUAL) 131 1.1 bsh lines = info->panel_height/2 + info->extra_lines; 132 1.1 bsh else 133 1.1 bsh lines = info->panel_height + info->extra_lines; 134 1.1 bsh 135 1.4 bsh bus_space_write_4(iot, ioh, LCDC_LCCR2, 136 1.1 bsh (lines-1) 137 1.1 bsh | (info->vsync_pulse_width<<10) 138 1.1 bsh | (info->end_frame_wait<<16) 139 1.4 bsh | (info->beg_frame_wait<<24)); 140 1.1 bsh 141 1.4 bsh bus_space_write_4(iot, ioh, LCDC_LCCR3, 142 1.1 bsh (info->pixel_clock_div<<0) 143 1.1 bsh | (info->ac_bias << 8) 144 1.1 bsh | ((info->panel_info & 145 1.1 bsh (LCDPANEL_VSP|LCDPANEL_HSP|LCDPANEL_PCP|LCDPANEL_OEP)) 146 1.1 bsh <<20) 147 1.4 bsh | (4 << 24) /* 16bpp */ 148 1.1 bsh | ((info->panel_info & LCDPANEL_DPC) ? (1<<27) : 0) 149 1.1 bsh ); 150 1.27 nonaka 151 1.27 nonaka bus_space_write_4(iot, ioh, LCDC_LCCR4, (info->pcd_div << 31)); 152 1.1 bsh } 153 1.1 bsh 154 1.14 ober /* 155 1.14 ober * Initialize the LCD controller. 156 1.14 ober */ 157 1.1 bsh void 158 1.14 ober pxa2x0_lcd_initialize(struct pxa2x0_lcd_softc *sc, 159 1.14 ober const struct lcd_panel_geometry *geom) 160 1.1 bsh { 161 1.14 ober bus_space_tag_t iot; 162 1.1 bsh bus_space_handle_t ioh; 163 1.14 ober uint32_t lccr0, lscr; 164 1.14 ober int nldd; 165 1.1 bsh 166 1.15 peter iot = sc->iot; 167 1.15 peter ioh = sc->ioh; 168 1.1 bsh 169 1.14 ober /* Check if LCD is enabled before programming, it should not 170 1.14 ober * be enabled while it is being reprogrammed, therefore disable 171 1.14 ober * it first. 172 1.14 ober */ 173 1.14 ober lccr0 = bus_space_read_4(iot, ioh, LCDC_LCCR0); 174 1.14 ober if (lccr0 & LCCR0_ENB) { 175 1.14 ober lccr0 |= LCCR0_LDM; 176 1.14 ober bus_space_write_4(iot, ioh, LCDC_LCCR0, lccr0); 177 1.14 ober lccr0 = bus_space_read_4(iot, ioh, LCDC_LCCR0); /* paranoia */ 178 1.14 ober lccr0 |= LCCR0_DIS; 179 1.14 ober bus_space_write_4(iot, ioh, LCDC_LCCR0, lccr0); 180 1.14 ober do { 181 1.14 ober lscr = bus_space_read_4(iot, ioh, LCDC_LCSR); 182 1.14 ober } while (!(lscr & LCSR_LDD)); 183 1.1 bsh } 184 1.1 bsh 185 1.1 bsh /* enable clock */ 186 1.5 bsh pxa2x0_clkman_config(CKEN_LCD, 1); 187 1.1 bsh 188 1.22 nonaka lccr0 = LCCR0_IMASK; 189 1.22 nonaka if (CPU_IS_PXA270) 190 1.22 nonaka lccr0 |= LCCR0_CMDIM|LCCR0_RDSTM; 191 1.22 nonaka bus_space_write_4(iot, ioh, LCDC_LCCR0, lccr0); 192 1.1 bsh 193 1.1 bsh /* 194 1.1 bsh * setup GP[77:58] for LCD 195 1.1 bsh */ 196 1.3 scw /* Always use [FLP]CLK, ACBIAS */ 197 1.3 scw pxa2x0_gpio_set_function(74, GPIO_ALT_FN_2_OUT); 198 1.3 scw pxa2x0_gpio_set_function(75, GPIO_ALT_FN_2_OUT); 199 1.3 scw pxa2x0_gpio_set_function(76, GPIO_ALT_FN_2_OUT); 200 1.27 nonaka if (!ISSET(sc->flags, FLAG_NOUSE_ACBIAS)) 201 1.27 nonaka pxa2x0_gpio_set_function(77, GPIO_ALT_FN_2_OUT); 202 1.3 scw 203 1.3 scw if ((geom->panel_info & LCDPANEL_ACTIVE) || 204 1.3 scw ((geom->panel_info & (LCDPANEL_MONOCHROME|LCDPANEL_DUAL)) == 205 1.3 scw LCDPANEL_DUAL)) { 206 1.3 scw /* active and color dual panel need L_DD[15:0] */ 207 1.3 scw nldd = 16; 208 1.14 ober } else if ((geom->panel_info & LCDPANEL_DUAL) || 209 1.3 scw !(geom->panel_info & LCDPANEL_MONOCHROME)) { 210 1.3 scw /* dual or color need L_DD[7:0] */ 211 1.3 scw nldd = 8; 212 1.3 scw } else { 213 1.3 scw /* Otherwise just L_DD[3:0] */ 214 1.3 scw nldd = 4; 215 1.1 bsh } 216 1.1 bsh 217 1.3 scw while (nldd--) 218 1.3 scw pxa2x0_gpio_set_function(58 + nldd, GPIO_ALT_FN_2_OUT); 219 1.1 bsh 220 1.4 bsh pxa2x0_lcd_geometry(sc, geom); 221 1.1 bsh } 222 1.1 bsh 223 1.14 ober /* 224 1.14 ober * Common driver attachment code. 225 1.14 ober */ 226 1.14 ober void 227 1.14 ober pxa2x0_lcd_attach_sub(struct pxa2x0_lcd_softc *sc, 228 1.16 nonaka struct pxaip_attach_args *pxa, const struct lcd_panel_geometry *geom) 229 1.14 ober { 230 1.14 ober bus_space_tag_t iot = pxa->pxa_iot; 231 1.14 ober bus_space_handle_t ioh; 232 1.14 ober int error; 233 1.14 ober 234 1.27 nonaka aprint_normal(": PXA2x0 LCD controller\n"); 235 1.27 nonaka aprint_naive("\n"); 236 1.27 nonaka 237 1.14 ober sc->n_screens = 0; 238 1.14 ober LIST_INIT(&sc->screens); 239 1.1 bsh 240 1.14 ober /* map controller registers */ 241 1.27 nonaka error = bus_space_map(iot, PXA2X0_LCDC_BASE, PXA2X0_LCDC_SIZE, 0, &ioh); 242 1.15 peter if (error) { 243 1.27 nonaka aprint_error_dev(sc->dev, 244 1.27 nonaka "failed to map registers (errno=%d)\n", error); 245 1.15 peter return; 246 1.15 peter } 247 1.15 peter 248 1.15 peter sc->iot = iot; 249 1.15 peter sc->ioh = ioh; 250 1.15 peter sc->dma_tag = &pxa2x0_bus_dma_tag; 251 1.15 peter 252 1.15 peter sc->ih = pxa2x0_intr_establish(PXA2X0_INT_LCD, IPL_BIO, lcdintr, sc); 253 1.15 peter if (sc->ih == NULL) { 254 1.27 nonaka aprint_error_dev(sc->dev, 255 1.27 nonaka "unable to establish interrupt at irq %d\n", 256 1.15 peter PXA2X0_INT_LCD); 257 1.15 peter return; 258 1.15 peter } 259 1.15 peter 260 1.29 kiyohara /* Must disable LCD Controller here, if already enabled. */ 261 1.29 kiyohara bus_space_write_4(iot, ioh, LCDC_LCCR0, 0); 262 1.29 kiyohara 263 1.15 peter pxa2x0_lcd_initialize(sc, geom); 264 1.15 peter 265 1.28 bsh #if NWSDISPLAY > 0 266 1.16 nonaka if (pxa2x0_lcd_console.is_console) { 267 1.16 nonaka struct pxa2x0_wsscreen_descr *descr = pxa2x0_lcd_console.descr; 268 1.15 peter struct pxa2x0_lcd_screen *scr; 269 1.15 peter struct rasops_info *ri; 270 1.15 peter long defattr; 271 1.15 peter 272 1.15 peter error = pxa2x0_lcd_new_screen(sc, descr->depth, &scr); 273 1.14 ober if (error) { 274 1.27 nonaka aprint_error_dev(sc->dev, 275 1.27 nonaka "unable to create new screen (errno=%d)", error); 276 1.14 ober return; 277 1.14 ober } 278 1.14 ober 279 1.15 peter ri = &scr->rinfo; 280 1.15 peter ri->ri_hw = (void *)scr; 281 1.15 peter ri->ri_bits = scr->buf_va; 282 1.15 peter pxa2x0_lcd_setup_rasops(sc, ri, descr, geom); 283 1.15 peter 284 1.15 peter /* assumes 16 bpp */ 285 1.15 peter (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr); 286 1.15 peter 287 1.15 peter pxa2x0_lcd_start_dma(sc, scr); 288 1.15 peter sc->active = scr; 289 1.15 peter 290 1.15 peter wsdisplay_cnattach(&descr->c, ri, ri->ri_ccol, ri->ri_crow, 291 1.15 peter defattr); 292 1.14 ober 293 1.27 nonaka aprint_normal_dev(sc->dev, "console\n"); 294 1.16 nonaka } 295 1.28 bsh #endif 296 1.16 nonaka } 297 1.16 nonaka 298 1.16 nonaka int 299 1.16 nonaka pxa2x0_lcd_cnattach(struct pxa2x0_wsscreen_descr *descr, 300 1.16 nonaka const struct lcd_panel_geometry *geom) 301 1.16 nonaka { 302 1.16 nonaka 303 1.16 nonaka pxa2x0_lcd_console.descr = descr; 304 1.16 nonaka pxa2x0_lcd_console.geom = geom; 305 1.16 nonaka pxa2x0_lcd_console.is_console = 1; 306 1.14 ober 307 1.16 nonaka return 0; 308 1.14 ober } 309 1.14 ober 310 1.14 ober /* 311 1.14 ober * Interrupt handler. 312 1.14 ober */ 313 1.1 bsh int 314 1.1 bsh lcdintr(void *arg) 315 1.1 bsh { 316 1.15 peter struct pxa2x0_lcd_softc *sc = (struct pxa2x0_lcd_softc *)arg; 317 1.1 bsh bus_space_tag_t iot = sc->iot; 318 1.1 bsh bus_space_handle_t ioh = sc->ioh; 319 1.15 peter uint32_t status; 320 1.1 bsh 321 1.4 bsh status = bus_space_read_4(iot, ioh, LCDC_LCSR); 322 1.1 bsh /* Clear stickey status bits */ 323 1.4 bsh bus_space_write_4(iot, ioh, LCDC_LCSR, status); 324 1.1 bsh 325 1.1 bsh return 1; 326 1.1 bsh } 327 1.1 bsh 328 1.14 ober /* 329 1.14 ober * Enable DMA to cause the display to be refreshed periodically. 330 1.14 ober * This brings the screen to life... 331 1.14 ober */ 332 1.1 bsh void 333 1.4 bsh pxa2x0_lcd_start_dma(struct pxa2x0_lcd_softc *sc, 334 1.4 bsh struct pxa2x0_lcd_screen *scr) 335 1.1 bsh { 336 1.14 ober bus_space_tag_t iot; 337 1.14 ober bus_space_handle_t ioh; 338 1.1 bsh uint32_t tmp; 339 1.1 bsh int val, save; 340 1.1 bsh 341 1.15 peter iot = sc->iot; 342 1.15 peter ioh = sc->ioh; 343 1.14 ober 344 1.30 tsutsui bus_dmamap_sync(sc->dma_tag, scr->dma, 0, scr->buf_size, 345 1.30 tsutsui BUS_DMASYNC_PREWRITE); 346 1.30 tsutsui 347 1.4 bsh save = disable_interrupts(I32_bit); 348 1.1 bsh 349 1.4 bsh switch (scr->depth) { 350 1.1 bsh case 1: val = 0; break; 351 1.1 bsh case 2: val = 1; break; 352 1.1 bsh case 4: val = 2; break; 353 1.1 bsh case 8: val = 3; break; 354 1.10 bsh case 16: val = 4; break; 355 1.10 bsh case 18: val = 5; break; 356 1.10 bsh case 24: val = 33; break; 357 1.1 bsh default: 358 1.1 bsh val = 4; break; 359 1.1 bsh } 360 1.1 bsh 361 1.4 bsh tmp = bus_space_read_4(iot, ioh, LCDC_LCCR3); 362 1.15 peter if (CPU_IS_PXA270) { 363 1.10 bsh bus_space_write_4(iot, ioh, LCDC_LCCR3, 364 1.23 nonaka (tmp & ~(LCCR3_BPP|LCCR3_BPP3)) | (val << LCCR3_BPP_SHIFT)); 365 1.15 peter } else { 366 1.10 bsh bus_space_write_4(iot, ioh, LCDC_LCCR3, 367 1.10 bsh (tmp & ~LCCR3_BPP) | (val << LCCR3_BPP_SHIFT)); 368 1.15 peter } 369 1.1 bsh 370 1.4 bsh bus_space_write_4(iot, ioh, LCDC_FDADR0, 371 1.10 bsh scr->depth >= 16 ? scr->dma_desc_pa : 372 1.4 bsh scr->dma_desc_pa + 2 * sizeof (struct lcd_dma_descriptor)); 373 1.4 bsh bus_space_write_4(iot, ioh, LCDC_FDADR1, 374 1.4 bsh scr->dma_desc_pa + 1 * sizeof (struct lcd_dma_descriptor)); 375 1.1 bsh 376 1.1 bsh /* clear status */ 377 1.4 bsh bus_space_write_4(iot, ioh, LCDC_LCSR, 0); 378 1.1 bsh 379 1.1 bsh delay(1000); /* ??? */ 380 1.1 bsh 381 1.1 bsh /* Enable LCDC */ 382 1.4 bsh tmp = bus_space_read_4(iot, ioh, LCDC_LCCR0); 383 1.1 bsh /*tmp &= ~LCCR0_SFM;*/ 384 1.4 bsh bus_space_write_4(iot, ioh, LCDC_LCCR0, tmp | LCCR0_ENB); 385 1.1 bsh 386 1.4 bsh restore_interrupts(save); 387 1.1 bsh } 388 1.1 bsh 389 1.14 ober /* 390 1.14 ober * Disable screen refresh. 391 1.14 ober */ 392 1.1 bsh static void 393 1.4 bsh pxa2x0_lcd_stop_dma(struct pxa2x0_lcd_softc *sc) 394 1.1 bsh { 395 1.15 peter 396 1.1 bsh /* Stop LCD DMA after current frame */ 397 1.4 bsh bus_space_write_4(sc->iot, sc->ioh, LCDC_LCCR0, 398 1.1 bsh LCCR0_DIS | 399 1.4 bsh bus_space_read_4(sc->iot, sc->ioh, LCDC_LCCR0)); 400 1.1 bsh 401 1.1 bsh /* wait for disabling done. 402 1.1 bsh XXX: use interrupt. */ 403 1.4 bsh while (LCCR0_ENB & 404 1.4 bsh bus_space_read_4(sc->iot, sc->ioh, LCDC_LCCR0)) 405 1.15 peter continue; 406 1.1 bsh 407 1.4 bsh bus_space_write_4(sc->iot, sc->ioh, LCDC_LCCR0, 408 1.1 bsh ~LCCR0_DIS & 409 1.4 bsh bus_space_read_4(sc->iot, sc->ioh, LCDC_LCCR0)); 410 1.1 bsh } 411 1.1 bsh 412 1.1 bsh #define _rgb(r,g,b) (((r)<<11) | ((g)<<5) | b) 413 1.1 bsh #define rgb(r,g,b) _rgb((r)>>1,g,(b)>>1) 414 1.1 bsh 415 1.1 bsh #define L 0x1f /* low intensity */ 416 1.24 nonaka #define H 0x3f /* high intensity */ 417 1.1 bsh 418 1.1 bsh static uint16_t basic_color_map[] = { 419 1.1 bsh rgb( 0, 0, 0), /* black */ 420 1.1 bsh rgb( L, 0, 0), /* red */ 421 1.1 bsh rgb( 0, L, 0), /* green */ 422 1.1 bsh rgb( L, L, 0), /* brown */ 423 1.1 bsh rgb( 0, 0, L), /* blue */ 424 1.1 bsh rgb( L, 0, L), /* magenta */ 425 1.1 bsh rgb( 0, L, L), /* cyan */ 426 1.1 bsh _rgb(0x1c,0x38,0x1c), /* white */ 427 1.1 bsh 428 1.1 bsh rgb( L, L, L), /* black */ 429 1.1 bsh rgb( H, 0, 0), /* red */ 430 1.1 bsh rgb( 0, H, 0), /* green */ 431 1.1 bsh rgb( H, H, 0), /* brown */ 432 1.1 bsh rgb( 0, 0, H), /* blue */ 433 1.1 bsh rgb( H, 0, H), /* magenta */ 434 1.1 bsh rgb( 0, H, H), /* cyan */ 435 1.1 bsh rgb( H, H, H) 436 1.1 bsh }; 437 1.1 bsh 438 1.1 bsh #undef H 439 1.1 bsh #undef L 440 1.1 bsh 441 1.1 bsh static void 442 1.24 nonaka init_palette(uint16_t *buf, int depth) 443 1.1 bsh { 444 1.1 bsh int i; 445 1.1 bsh 446 1.1 bsh /* convert RGB332 to RGB565 */ 447 1.4 bsh switch (depth) { 448 1.1 bsh case 8: 449 1.1 bsh case 4: 450 1.1 bsh #if 0 451 1.4 bsh for (i=0; i <= 255; ++i) { 452 1.1 bsh buf[i] = ((9 * ((i>>5) & 0x07)) <<11) | 453 1.1 bsh ((9 * ((i>>2) & 0x07)) << 5) | 454 1.4 bsh ((21 * (i & 0x03))/2); 455 1.1 bsh } 456 1.1 bsh #else 457 1.4 bsh memcpy(buf, basic_color_map, sizeof basic_color_map); 458 1.4 bsh for (i=16; i < (1<<depth); ++i) 459 1.1 bsh buf[i] = 0xffff; 460 1.1 bsh #endif 461 1.1 bsh break; 462 1.8 bsh case 16: 463 1.24 nonaka /* palette is not needed */ 464 1.8 bsh break; 465 1.1 bsh default: 466 1.8 bsh /* other depths are not supported */ 467 1.8 bsh break; 468 1.1 bsh } 469 1.1 bsh } 470 1.1 bsh 471 1.14 ober /* 472 1.14 ober * Create and initialize a new screen buffer. 473 1.14 ober */ 474 1.14 ober int 475 1.15 peter pxa2x0_lcd_new_screen(struct pxa2x0_lcd_softc *sc, int depth, 476 1.15 peter struct pxa2x0_lcd_screen **scrpp) 477 1.1 bsh { 478 1.14 ober bus_dma_tag_t dma_tag; 479 1.14 ober const struct lcd_panel_geometry *geometry; 480 1.15 peter struct pxa2x0_lcd_screen *scr = NULL; 481 1.1 bsh int width, height; 482 1.1 bsh bus_size_t size; 483 1.24 nonaka int error, palette_size; 484 1.1 bsh int busdma_flag = (cold ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK); 485 1.1 bsh struct lcd_dma_descriptor *desc; 486 1.1 bsh paddr_t buf_pa, desc_pa; 487 1.1 bsh 488 1.15 peter dma_tag = sc->dma_tag; 489 1.15 peter geometry = sc->geometry; 490 1.14 ober 491 1.14 ober width = geometry->panel_width; 492 1.14 ober height = geometry->panel_height; 493 1.24 nonaka palette_size = 0; 494 1.1 bsh 495 1.4 bsh switch (depth) { 496 1.1 bsh case 1: 497 1.1 bsh case 2: 498 1.1 bsh case 4: 499 1.1 bsh case 8: 500 1.24 nonaka palette_size = (1<<depth) * sizeof (uint16_t); 501 1.1 bsh /* FALLTHROUGH */ 502 1.1 bsh case 16: 503 1.24 nonaka size = roundup(width,4) * 2 * height; 504 1.1 bsh break; 505 1.10 bsh case 18: 506 1.10 bsh case 24: 507 1.10 bsh size = roundup(width,4) * 4 * height; 508 1.10 bsh break; 509 1.10 bsh case 19: 510 1.10 bsh case 25: 511 1.27 nonaka aprint_error_dev(sc->dev, "Not supported depth (%d)\n", depth); 512 1.14 ober return EINVAL; 513 1.1 bsh default: 514 1.27 nonaka aprint_error_dev(sc->dev, "Unknown depth (%d)\n", depth); 515 1.14 ober return EINVAL; 516 1.1 bsh } 517 1.1 bsh 518 1.38 thorpej scr = kmem_zalloc(sizeof(*scr), KM_SLEEP); 519 1.1 bsh scr->nsegs = 0; 520 1.1 bsh scr->depth = depth; 521 1.1 bsh scr->buf_size = size; 522 1.1 bsh scr->buf_va = NULL; 523 1.24 nonaka size = roundup(size,16) + 3 * sizeof(struct lcd_dma_descriptor) 524 1.24 nonaka + palette_size; 525 1.1 bsh 526 1.15 peter error = bus_dmamem_alloc(dma_tag, size, 16, 0, scr->segs, 1, 527 1.15 peter &scr->nsegs, busdma_flag); 528 1.1 bsh 529 1.12 simonb if (error || scr->nsegs != 1) { 530 1.12 simonb /* XXX: 531 1.12 simonb * Actually we can handle nsegs>1 case by means 532 1.12 simonb * of multiple DMA descriptors for a panel. It 533 1.12 simonb * will make code here a bit hairly. 534 1.12 simonb */ 535 1.14 ober if (error == 0) 536 1.14 ober error = E2BIG; 537 1.1 bsh goto bad; 538 1.12 simonb } 539 1.1 bsh 540 1.15 peter error = bus_dmamem_map(dma_tag, scr->segs, scr->nsegs, size, 541 1.30 tsutsui (void **)&scr->buf_va, 542 1.30 tsutsui busdma_flag | (pxa2x0_lcd_writethrough ? 0 : BUS_DMA_COHERENT)); 543 1.4 bsh if (error) 544 1.1 bsh goto bad; 545 1.1 bsh 546 1.30 tsutsui /* XXX: should we have BUS_DMA_WRITETHROUGH in MI bus_dma(9) API? */ 547 1.30 tsutsui if (pxa2x0_lcd_writethrough) { 548 1.30 tsutsui vaddr_t va, eva; 549 1.30 tsutsui 550 1.30 tsutsui va = (vaddr_t)scr->buf_va; 551 1.30 tsutsui eva = va + size; 552 1.30 tsutsui while (va < eva) { 553 1.30 tsutsui /* taken from arm/arm32/bus_dma.c:_bus_dmamem_map() */ 554 1.30 tsutsui cpu_dcache_wbinv_range(va, PAGE_SIZE); 555 1.30 tsutsui cpu_drain_writebuf(); 556 1.35 matt pt_entry_t * const ptep = vtopte(va); 557 1.35 matt const pt_entry_t opte = *ptep; 558 1.35 matt const pt_entry_t npte = (opte & ~L2_S_CACHE_MASK) 559 1.35 matt | L2_C; 560 1.35 matt l2pte_set(ptep, npte, opte); 561 1.30 tsutsui PTE_SYNC(ptep); 562 1.30 tsutsui va += PAGE_SIZE; 563 1.30 tsutsui } 564 1.36 jmcneill cpu_tlb_flushID(); 565 1.30 tsutsui } 566 1.30 tsutsui 567 1.15 peter memset(scr->buf_va, 0, scr->buf_size); 568 1.1 bsh 569 1.1 bsh /* map memory for DMA */ 570 1.15 peter error = bus_dmamap_create(dma_tag, 1024*1024*2, 1, 1024*1024*2, 0, 571 1.15 peter busdma_flag, &scr->dma); 572 1.15 peter if (error) 573 1.1 bsh goto bad; 574 1.15 peter 575 1.15 peter error = bus_dmamap_load(dma_tag, scr->dma, scr->buf_va, size, 576 1.15 peter NULL, busdma_flag); 577 1.15 peter if (error) 578 1.1 bsh goto bad; 579 1.1 bsh 580 1.1 bsh buf_pa = scr->segs[0].ds_addr; 581 1.24 nonaka desc_pa = buf_pa + roundup(size, PAGE_SIZE) - 3 * sizeof(*desc); 582 1.1 bsh 583 1.1 bsh /* make descriptors at the top of mapped memory */ 584 1.1 bsh desc = (struct lcd_dma_descriptor *)( 585 1.18 nonaka (char *)(scr->buf_va) + roundup(size, PAGE_SIZE) - 586 1.24 nonaka 3 * sizeof(*desc)); 587 1.1 bsh 588 1.1 bsh desc[0].fdadr = desc_pa; 589 1.1 bsh desc[0].fsadr = buf_pa; 590 1.1 bsh desc[0].ldcmd = scr->buf_size; 591 1.1 bsh 592 1.24 nonaka if (palette_size) { 593 1.24 nonaka init_palette((uint16_t *)((char *)desc - palette_size), depth); 594 1.1 bsh 595 1.1 bsh desc[2].fdadr = desc_pa; /* chain to panel 0 */ 596 1.24 nonaka desc[2].fsadr = desc_pa - palette_size; 597 1.24 nonaka desc[2].ldcmd = palette_size | LDCMD_PAL; 598 1.1 bsh } 599 1.1 bsh 600 1.15 peter if (geometry->panel_info & LCDPANEL_DUAL) { 601 1.1 bsh /* Dual panel */ 602 1.1 bsh desc[1].fdadr = desc_pa + sizeof *desc; 603 1.1 bsh desc[1].fsadr = buf_pa + scr->buf_size/2; 604 1.1 bsh desc[0].ldcmd = desc[1].ldcmd = scr->buf_size/2; 605 1.1 bsh 606 1.1 bsh } 607 1.1 bsh 608 1.1 bsh #if 0 609 1.1 bsh desc[0].ldcmd |= LDCMD_SOFINT; 610 1.1 bsh desc[1].ldcmd |= LDCMD_SOFINT; 611 1.1 bsh #endif 612 1.1 bsh 613 1.1 bsh scr->dma_desc = desc; 614 1.1 bsh scr->dma_desc_pa = desc_pa; 615 1.1 bsh scr->map_size = size; /* used when unmap this. */ 616 1.1 bsh 617 1.15 peter LIST_INSERT_HEAD(&sc->screens, scr, link); 618 1.1 bsh sc->n_screens++; 619 1.1 bsh 620 1.15 peter *scrpp = scr; 621 1.15 peter 622 1.14 ober return 0; 623 1.1 bsh 624 1.1 bsh bad: 625 1.4 bsh if (scr) { 626 1.4 bsh if (scr->buf_va) 627 1.15 peter bus_dmamem_unmap(dma_tag, scr->buf_va, size); 628 1.4 bsh if (scr->nsegs) 629 1.15 peter bus_dmamem_free(dma_tag, scr->segs, scr->nsegs); 630 1.38 thorpej kmem_free(scr, sizeof(*scr)); 631 1.1 bsh } 632 1.15 peter *scrpp = NULL; 633 1.14 ober return error; 634 1.14 ober } 635 1.14 ober 636 1.28 bsh #if NWSDISPLAY > 0 637 1.14 ober /* 638 1.14 ober * Initialize rasops for a screen, as well as struct wsscreen_descr if this 639 1.14 ober * is the first screen creation. 640 1.14 ober */ 641 1.15 peter static void 642 1.15 peter pxa2x0_lcd_setup_rasops(struct pxa2x0_lcd_softc *sc, struct rasops_info *rinfo, 643 1.14 ober struct pxa2x0_wsscreen_descr *descr, 644 1.14 ober const struct lcd_panel_geometry *geom) 645 1.14 ober { 646 1.14 ober 647 1.39 rin rinfo->ri_flg = descr->flags | RI_ENABLE_ALPHA; 648 1.14 ober rinfo->ri_depth = descr->depth; 649 1.14 ober rinfo->ri_width = geom->panel_width; 650 1.14 ober rinfo->ri_height = geom->panel_height; 651 1.14 ober rinfo->ri_stride = rinfo->ri_width * rinfo->ri_depth / 8; 652 1.14 ober #ifdef notyet 653 1.14 ober rinfo->ri_wsfcookie = -1; /* XXX */ 654 1.14 ober #endif 655 1.14 ober 656 1.14 ober /* swap B and R */ 657 1.14 ober if (descr->depth == 16) { 658 1.14 ober rinfo->ri_rnum = 5; 659 1.14 ober rinfo->ri_rpos = 11; 660 1.14 ober rinfo->ri_gnum = 6; 661 1.14 ober rinfo->ri_gpos = 5; 662 1.14 ober rinfo->ri_bnum = 5; 663 1.14 ober rinfo->ri_bpos = 0; 664 1.14 ober } 665 1.14 ober 666 1.14 ober if (descr->c.nrows == 0) { 667 1.14 ober /* get rasops to compute screen size the first time */ 668 1.14 ober rasops_init(rinfo, 100, 100); 669 1.15 peter } else { 670 1.14 ober rasops_init(rinfo, descr->c.nrows, descr->c.ncols); 671 1.15 peter } 672 1.14 ober 673 1.14 ober descr->c.nrows = rinfo->ri_rows; 674 1.14 ober descr->c.ncols = rinfo->ri_cols; 675 1.14 ober descr->c.capabilities = rinfo->ri_caps; 676 1.14 ober descr->c.textops = &rinfo->ri_ops; 677 1.14 ober } 678 1.28 bsh #endif 679 1.14 ober 680 1.14 ober /* 681 1.14 ober * Power management 682 1.14 ober */ 683 1.14 ober void 684 1.14 ober pxa2x0_lcd_suspend(struct pxa2x0_lcd_softc *sc) 685 1.14 ober { 686 1.14 ober 687 1.15 peter if (sc->active) { 688 1.14 ober pxa2x0_lcd_stop_dma(sc); 689 1.14 ober pxa2x0_clkman_config(CKEN_LCD, 0); 690 1.14 ober } 691 1.14 ober } 692 1.14 ober 693 1.14 ober void 694 1.14 ober pxa2x0_lcd_resume(struct pxa2x0_lcd_softc *sc) 695 1.14 ober { 696 1.14 ober 697 1.15 peter if (sc->active) { 698 1.14 ober pxa2x0_lcd_initialize(sc, sc->geometry); 699 1.14 ober pxa2x0_lcd_start_dma(sc, sc->active); 700 1.14 ober } 701 1.1 bsh } 702 1.1 bsh 703 1.14 ober void 704 1.14 ober pxa2x0_lcd_power(int why, void *v) 705 1.14 ober { 706 1.14 ober struct pxa2x0_lcd_softc *sc = v; 707 1.14 ober 708 1.14 ober switch (why) { 709 1.14 ober case PWR_SUSPEND: 710 1.14 ober case PWR_STANDBY: 711 1.14 ober pxa2x0_lcd_suspend(sc); 712 1.14 ober break; 713 1.14 ober 714 1.14 ober case PWR_RESUME: 715 1.14 ober pxa2x0_lcd_resume(sc); 716 1.14 ober break; 717 1.14 ober } 718 1.14 ober } 719 1.1 bsh 720 1.1 bsh #if NWSDISPLAY > 0 721 1.1 bsh /* 722 1.1 bsh * Initialize struct wsscreen_descr based on values calculated by 723 1.1 bsh * raster operation subsystem. 724 1.1 bsh */ 725 1.1 bsh int 726 1.1 bsh pxa2x0_lcd_setup_wsscreen(struct pxa2x0_wsscreen_descr *descr, 727 1.1 bsh const struct lcd_panel_geometry *geom, 728 1.4 bsh const char *fontname) 729 1.1 bsh { 730 1.1 bsh int width = geom->panel_width; 731 1.1 bsh int height = geom->panel_height; 732 1.1 bsh int cookie = -1; 733 1.1 bsh struct rasops_info rinfo; 734 1.1 bsh 735 1.4 bsh memset(&rinfo, 0, sizeof rinfo); 736 1.1 bsh 737 1.4 bsh if (fontname) { 738 1.1 bsh wsfont_init(); 739 1.9 he cookie = wsfont_find(fontname, 0, 0, 0, 740 1.33 macallan WSDISPLAY_FONTORDER_L2R, WSDISPLAY_FONTORDER_L2R, 741 1.33 macallan WSFONT_FIND_BITMAP); 742 1.4 bsh if (cookie < 0 || 743 1.4 bsh wsfont_lock(cookie, &rinfo.ri_font)) 744 1.1 bsh return -1; 745 1.1 bsh } 746 1.1 bsh else { 747 1.1 bsh /* let rasops_init() choose any font */ 748 1.1 bsh } 749 1.1 bsh 750 1.1 bsh /* let rasops_init calculate # of cols and rows in character */ 751 1.39 rin rinfo.ri_flg = RI_ENABLE_ALPHA; 752 1.1 bsh rinfo.ri_depth = descr->depth; 753 1.1 bsh rinfo.ri_bits = NULL; 754 1.1 bsh rinfo.ri_width = width; 755 1.1 bsh rinfo.ri_height = height; 756 1.1 bsh rinfo.ri_stride = width * rinfo.ri_depth / 8; 757 1.10 bsh #ifdef CPU_XSCALE_PXA270 758 1.15 peter if (rinfo.ri_depth > 16) 759 1.15 peter rinfo.ri_stride = width * 4; 760 1.10 bsh #endif 761 1.1 bsh rinfo.ri_wsfcookie = cookie; 762 1.1 bsh 763 1.4 bsh rasops_init(&rinfo, 100, 100); 764 1.1 bsh 765 1.1 bsh descr->c.nrows = rinfo.ri_rows; 766 1.1 bsh descr->c.ncols = rinfo.ri_cols; 767 1.1 bsh descr->c.capabilities = rinfo.ri_caps; 768 1.1 bsh 769 1.1 bsh return cookie; 770 1.1 bsh } 771 1.1 bsh 772 1.1 bsh int 773 1.1 bsh pxa2x0_lcd_show_screen(void *v, void *cookie, int waitok, 774 1.1 bsh void (*cb)(void *, int, int), void *cbarg) 775 1.1 bsh { 776 1.1 bsh struct pxa2x0_lcd_softc *sc = v; 777 1.1 bsh struct pxa2x0_lcd_screen *scr = cookie, *old; 778 1.1 bsh 779 1.1 bsh old = sc->active; 780 1.4 bsh if (old == scr) 781 1.1 bsh return 0; 782 1.1 bsh 783 1.4 bsh if (old) 784 1.4 bsh pxa2x0_lcd_stop_dma(sc); 785 1.1 bsh 786 1.4 bsh pxa2x0_lcd_start_dma(sc, scr); 787 1.1 bsh 788 1.1 bsh sc->active = scr; 789 1.1 bsh return 0; 790 1.1 bsh } 791 1.1 bsh 792 1.1 bsh int 793 1.1 bsh pxa2x0_lcd_alloc_screen(void *v, const struct wsscreen_descr *_type, 794 1.1 bsh void **cookiep, int *curxp, int *curyp, long *attrp) 795 1.1 bsh { 796 1.1 bsh struct pxa2x0_lcd_softc *sc = v; 797 1.1 bsh struct pxa2x0_lcd_screen *scr; 798 1.9 he const struct pxa2x0_wsscreen_descr *type = 799 1.9 he (const struct pxa2x0_wsscreen_descr *)_type; 800 1.14 ober int error; 801 1.1 bsh 802 1.15 peter error = pxa2x0_lcd_new_screen(sc, type->depth, &scr); 803 1.15 peter if (error) 804 1.15 peter return error; 805 1.14 ober 806 1.1 bsh /* 807 1.1 bsh * initialize raster operation for this screen. 808 1.1 bsh */ 809 1.39 rin scr->rinfo.ri_flg = RI_ENABLE_ALPHA; 810 1.1 bsh scr->rinfo.ri_depth = type->depth; 811 1.1 bsh scr->rinfo.ri_bits = scr->buf_va; 812 1.1 bsh scr->rinfo.ri_width = sc->geometry->panel_width; 813 1.1 bsh scr->rinfo.ri_height = sc->geometry->panel_height; 814 1.1 bsh scr->rinfo.ri_stride = scr->rinfo.ri_width * scr->rinfo.ri_depth / 8; 815 1.10 bsh #ifdef CPU_XSCALE_PXA270 816 1.10 bsh if (scr->rinfo.ri_depth > 16) 817 1.10 bsh scr->rinfo.ri_stride = scr->rinfo.ri_width * 4; 818 1.10 bsh #endif 819 1.1 bsh scr->rinfo.ri_wsfcookie = -1; /* XXX */ 820 1.1 bsh 821 1.4 bsh rasops_init(&scr->rinfo, type->c.nrows, type->c.ncols); 822 1.1 bsh 823 1.24 nonaka (*scr->rinfo.ri_ops.allocattr)(&scr->rinfo, 0, 0, 0, attrp); 824 1.1 bsh 825 1.1 bsh *cookiep = scr; 826 1.1 bsh *curxp = 0; 827 1.1 bsh *curyp = 0; 828 1.1 bsh 829 1.1 bsh return 0; 830 1.1 bsh } 831 1.1 bsh 832 1.1 bsh void 833 1.1 bsh pxa2x0_lcd_free_screen(void *v, void *cookie) 834 1.1 bsh { 835 1.1 bsh struct pxa2x0_lcd_softc *sc = v; 836 1.1 bsh struct pxa2x0_lcd_screen *scr = cookie; 837 1.1 bsh 838 1.4 bsh LIST_REMOVE(scr, link); 839 1.1 bsh sc->n_screens--; 840 1.4 bsh if (scr == sc->active) { 841 1.1 bsh /* at first, we need to stop LCD DMA */ 842 1.1 bsh sc->active = NULL; 843 1.1 bsh 844 1.4 bsh printf("lcd_free on active screen\n"); 845 1.1 bsh 846 1.1 bsh pxa2x0_lcd_stop_dma(sc); 847 1.1 bsh } 848 1.1 bsh 849 1.4 bsh if (scr->buf_va) 850 1.4 bsh bus_dmamem_unmap(sc->dma_tag, scr->buf_va, scr->map_size); 851 1.4 bsh if (scr->nsegs > 0) 852 1.4 bsh bus_dmamem_free(sc->dma_tag, scr->segs, scr->nsegs); 853 1.38 thorpej kmem_free(scr, sizeof(*scr)); 854 1.1 bsh } 855 1.1 bsh 856 1.1 bsh int 857 1.17 christos pxa2x0_lcd_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, 858 1.13 jmmv struct lwp *l) 859 1.1 bsh { 860 1.1 bsh struct pxa2x0_lcd_softc *sc = v; 861 1.21 nonaka struct pxa2x0_lcd_screen *scr = sc->active; /* ??? */ 862 1.1 bsh struct wsdisplay_fbinfo *wsdisp_info; 863 1.1 bsh uint32_t ccr0; 864 1.1 bsh 865 1.1 bsh switch (cmd) { 866 1.1 bsh case WSDISPLAYIO_GTYPE: 867 1.25 nonaka *(int *)data = WSDISPLAY_TYPE_PXALCD; 868 1.1 bsh return 0; 869 1.1 bsh 870 1.1 bsh case WSDISPLAYIO_GINFO: 871 1.1 bsh wsdisp_info = (struct wsdisplay_fbinfo *)data; 872 1.1 bsh wsdisp_info->height = sc->geometry->panel_height; 873 1.1 bsh wsdisp_info->width = sc->geometry->panel_width; 874 1.21 nonaka wsdisp_info->depth = scr->depth; 875 1.1 bsh wsdisp_info->cmsize = 0; 876 1.1 bsh return 0; 877 1.1 bsh 878 1.21 nonaka case WSDISPLAYIO_LINEBYTES: 879 1.21 nonaka *(u_int *)data = scr->rinfo.ri_stride; 880 1.21 nonaka return 0; 881 1.21 nonaka 882 1.1 bsh case WSDISPLAYIO_GETCMAP: 883 1.1 bsh case WSDISPLAYIO_PUTCMAP: 884 1.1 bsh return EPASSTHROUGH; /* XXX Colormap */ 885 1.1 bsh 886 1.1 bsh case WSDISPLAYIO_SVIDEO: 887 1.4 bsh if (*(int *)data == WSDISPLAYIO_VIDEO_ON) { 888 1.1 bsh /* turn it on */ 889 1.1 bsh } 890 1.1 bsh else { 891 1.1 bsh /* start LCD shutdown */ 892 1.1 bsh /* sleep until interrupt */ 893 1.1 bsh } 894 1.1 bsh return 0; 895 1.1 bsh 896 1.1 bsh case WSDISPLAYIO_GVIDEO: 897 1.4 bsh ccr0 = bus_space_read_4(sc->iot, sc->ioh, LCDC_LCCR0); 898 1.1 bsh *(u_int *)data = (ccr0 & (LCCR0_ENB|LCCR0_DIS)) == LCCR0_ENB ? 899 1.1 bsh WSDISPLAYIO_VIDEO_ON : WSDISPLAYIO_VIDEO_OFF; 900 1.1 bsh return 0; 901 1.1 bsh 902 1.1 bsh case WSDISPLAYIO_GCURPOS: 903 1.1 bsh case WSDISPLAYIO_SCURPOS: 904 1.1 bsh case WSDISPLAYIO_GCURMAX: 905 1.1 bsh case WSDISPLAYIO_GCURSOR: 906 1.1 bsh case WSDISPLAYIO_SCURSOR: 907 1.1 bsh return EPASSTHROUGH; /* XXX */ 908 1.1 bsh } 909 1.1 bsh 910 1.1 bsh return EPASSTHROUGH; 911 1.1 bsh } 912 1.1 bsh 913 1.1 bsh paddr_t 914 1.13 jmmv pxa2x0_lcd_mmap(void *v, void *vs, off_t offset, int prot) 915 1.1 bsh { 916 1.1 bsh struct pxa2x0_lcd_softc *sc = v; 917 1.20 nonaka struct pxa2x0_lcd_screen *scr = sc->active; /* ??? */ 918 1.1 bsh 919 1.20 nonaka if (scr == NULL) 920 1.20 nonaka return -1; 921 1.20 nonaka 922 1.20 nonaka if (offset < 0 || 923 1.20 nonaka offset >= scr->rinfo.ri_stride * scr->rinfo.ri_height) 924 1.1 bsh return -1; 925 1.1 bsh 926 1.20 nonaka return bus_dmamem_mmap(sc->dma_tag, scr->segs, scr->nsegs, 927 1.30 tsutsui offset, prot, 928 1.30 tsutsui BUS_DMA_WAITOK | (pxa2x0_lcd_writethrough ? 0 : BUS_DMA_COHERENT)); 929 1.1 bsh } 930 1.1 bsh 931 1.1 bsh 932 1.1 bsh static void 933 1.4 bsh pxa2x0_lcd_cursor(void *cookie, int on, int row, int col) 934 1.1 bsh { 935 1.1 bsh struct pxa2x0_lcd_screen *scr = cookie; 936 1.1 bsh 937 1.15 peter (*scr->rinfo.ri_ops.cursor)(&scr->rinfo, on, row, col); 938 1.1 bsh } 939 1.1 bsh 940 1.1 bsh static int 941 1.4 bsh pxa2x0_lcd_mapchar(void *cookie, int c, unsigned int *cp) 942 1.1 bsh { 943 1.1 bsh struct pxa2x0_lcd_screen *scr = cookie; 944 1.1 bsh 945 1.15 peter return (*scr->rinfo.ri_ops.mapchar)(&scr->rinfo, c, cp); 946 1.1 bsh } 947 1.1 bsh 948 1.1 bsh static void 949 1.4 bsh pxa2x0_lcd_putchar(void *cookie, int row, int col, u_int uc, long attr) 950 1.1 bsh { 951 1.1 bsh struct pxa2x0_lcd_screen *scr = cookie; 952 1.1 bsh 953 1.15 peter (*scr->rinfo.ri_ops.putchar)(&scr->rinfo, row, col, uc, attr); 954 1.1 bsh } 955 1.1 bsh 956 1.1 bsh static void 957 1.4 bsh pxa2x0_lcd_copycols(void *cookie, int row, int src, int dst, int num) 958 1.1 bsh { 959 1.1 bsh struct pxa2x0_lcd_screen *scr = cookie; 960 1.1 bsh 961 1.15 peter (*scr->rinfo.ri_ops.copycols)(&scr->rinfo, row, src, dst, num); 962 1.1 bsh } 963 1.1 bsh 964 1.1 bsh static void 965 1.4 bsh pxa2x0_lcd_erasecols(void *cookie, int row, int col, int num, long attr) 966 1.1 bsh { 967 1.1 bsh struct pxa2x0_lcd_screen *scr = cookie; 968 1.1 bsh 969 1.15 peter (*scr->rinfo.ri_ops.erasecols)(&scr->rinfo, row, col, num, attr); 970 1.1 bsh } 971 1.1 bsh 972 1.1 bsh static void 973 1.4 bsh pxa2x0_lcd_copyrows(void *cookie, int src, int dst, int num) 974 1.1 bsh { 975 1.1 bsh struct pxa2x0_lcd_screen *scr = cookie; 976 1.1 bsh 977 1.15 peter (*scr->rinfo.ri_ops.copyrows)(&scr->rinfo, src, dst, num); 978 1.1 bsh } 979 1.1 bsh 980 1.1 bsh static void 981 1.4 bsh pxa2x0_lcd_eraserows(void *cookie, int row, int num, long attr) 982 1.1 bsh { 983 1.1 bsh struct pxa2x0_lcd_screen *scr = cookie; 984 1.1 bsh 985 1.15 peter (*scr->rinfo.ri_ops.eraserows)(&scr->rinfo, row, num, attr); 986 1.1 bsh } 987 1.1 bsh 988 1.1 bsh static int 989 1.4 bsh pxa2x0_lcd_alloc_attr(void *cookie, int fg, int bg, int flg, long *attr) 990 1.1 bsh { 991 1.1 bsh struct pxa2x0_lcd_screen *scr = cookie; 992 1.1 bsh 993 1.15 peter return (*scr->rinfo.ri_ops.allocattr)(&scr->rinfo, fg, bg, flg, attr); 994 1.1 bsh } 995 1.1 bsh 996 1.1 bsh const struct wsdisplay_emulops pxa2x0_lcd_emulops = { 997 1.1 bsh pxa2x0_lcd_cursor, 998 1.1 bsh pxa2x0_lcd_mapchar, 999 1.1 bsh pxa2x0_lcd_putchar, 1000 1.1 bsh pxa2x0_lcd_copycols, 1001 1.1 bsh pxa2x0_lcd_erasecols, 1002 1.1 bsh pxa2x0_lcd_copyrows, 1003 1.1 bsh pxa2x0_lcd_eraserows, 1004 1.1 bsh pxa2x0_lcd_alloc_attr 1005 1.1 bsh }; 1006 1.1 bsh 1007 1.1 bsh #endif /* NWSDISPLAY > 0 */ 1008