1 /* $OpenBSD: omdisplay.c,v 1.8 2020/05/25 09:55:48 jsg Exp $ */ 2 /* 3 * Copyright (c) 2007 Dale Rahn <drahn@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <sys/param.h> 19 #include <sys/systm.h> 20 #include <sys/queue.h> 21 #include <sys/malloc.h> 22 #include <sys/device.h> 23 #include <sys/evcount.h> 24 #include <sys/conf.h> 25 #include <sys/uio.h> 26 #include <machine/bus.h> 27 #include <armv7/omap/omgpiovar.h> 28 29 #include <dev/cons.h> 30 #include <dev/wscons/wsconsio.h> 31 #include <dev/wscons/wsdisplayvar.h> 32 #include <dev/wscons/wscons_callbacks.h> 33 34 #include <dev/rasops/rasops.h> 35 36 #include "splash16.h" 37 38 #define OMDISPLAY_SIZE 0x1000 39 /* registers */ 40 /* DSS */ 41 #define DSS_REVISIONNUMBER 0x00 42 #define DSS_CONTROL 0x40 43 #define DSS_PSA_LCD_REG_1 0x50 44 #define DSS_PSA_LCD_REG_2 0x54 45 #define DSS_PSA_VIDEO_REG 0x58 46 #define DSS_STATUS 0x5C 47 48 /* DCR */ 49 #define DISPC_REVISION 0x0000 50 #define DISPC_SYSCONFIG 0x0010 51 #define DISPC_SYSCONFIG_AUTOIDLE 0x00000001 52 #define DISPC_SYSCONFIG_SOFTRESET 0x00000002 53 #define DISPC_SYSCONFIG_SIDLEMODE_FORCE 0x00000000 54 #define DISPC_SYSCONFIG_SIDLEMODE_NONE 0x00000008 55 #define DISPC_SYSCONFIG_SIDLEMODE_SMART 0x00000010 56 #define DISPC_SYSCONFIG_MIDLEMODE_FORCE 0x00000000 57 #define DISPC_SYSCONFIG_MIDLEMODE_NONE 0x00001000 58 #define DISPC_SYSCONFIG_MIDLEMODE_SMART 0x00002000 59 #define DISPC_SYSSTATUS 0x0014 60 #define DISPC_SYSTATUS_RESETDONE 0x00000001 61 #define DISPC_IRQSTATUS 0x0018 62 #define DISPC_IRQSTATUS_FRAMEDONE 0x00000001 63 #define DISPC_IRQSTATUS_VSYNC 0x00000002 64 #define DISPC_IRQSTATUS_EVSYNCEVEN 0x00000004 65 #define DISPC_IRQSTATUS_EVSYNCODD 0x00000008 66 #define DISPC_IRQSTATUS_ACBIASCOUNT 0x00000010 67 #define DISPC_IRQSTATUS_PROGLINENUM 0x00000020 68 #define DISPC_IRQSTATUS_GFXFIFOUNDER 0x00000040 69 #define DISPC_IRQSTATUS_GFXENDWINDOW 0x00000080 70 #define DISPC_IRQSTATUS_PALGAMMA 0x00000100 71 #define DISPC_IRQSTATUS_OCPERROR 0x00000200 72 #define DISPC_IRQSTATUS_VID1FIFOUNDER 0x00000400 73 #define DISPC_IRQSTATUS_VID1ENDWIND 0x00000800 74 #define DISPC_IRQSTATUS_VID2FIFOUNDER 0x00001000 75 #define DISPC_IRQSTATUS_VID2ENDWIND 0x00002000 76 #define DISPC_IRQSTATUS_SYNCLOST 0x00004000 77 #define DISPC_IRQENABLE 0x001C 78 #define DISPC_IRQENABLE_FRAMEDONE 0x00000001 79 #define DISPC_IRQENABLE_VSYNC 0x00000002 80 #define DISPC_IRQENABLE_EVSYNCEVEN 0x00000004 81 #define DISPC_IRQENABLE_EVSYNCODD 0x00000008 82 #define DISPC_IRQENABLE_ACBIASCOUNT 0x00000010 83 #define DISPC_IRQENABLE_PROGLINENUM 0x00000020 84 #define DISPC_IRQENABLE_GFXFIFOUNDER 0x00000040 85 #define DISPC_IRQENABLE_GFXENDWINDOW 0x00000080 86 #define DISPC_IRQENABLE_PALGAMMA 0x00000100 87 #define DISPC_IRQENABLE_OCPERROR 0x00000200 88 #define DISPC_IRQENABLE_VID1FIFOUNDER 0x00000400 89 #define DISPC_IRQENABLE_VID1ENDWIND 0x00000800 90 #define DISPC_IRQENABLE_VID2FIFOUNDER 0x00001000 91 #define DISPC_IRQENABLE_VID2ENDWIND 0x00002000 92 #define DISPC_IRQENABLE_SYNCLOST 0x00004000 93 #define DISPC_CONTROL 0x0040 94 #define DISPC_CONTROL_LCDENABLE 0x00000001 95 #define DISPC_CONTROL_DIGITALENABLE 0x00000002 96 #define DISPC_CONTROL_MONOCOLOR 0x00000004 97 #define DISPC_CONTROL_STNTFT 0x00000008 98 #define DISPC_CONTROL_M8B 0x00000010 99 #define DISPC_CONTROL_GOLCD 0x00000020 100 #define DISPC_CONTROL_GODIGITAL 0x00000040 101 #define DISPC_CONTROL_TFTDITHEREN 0x00000080 102 #define DISPC_CONTROL_TFTDATALINES_12 0x00000000 103 #define DISPC_CONTROL_TFTDATALINES_16 0x00000100 104 #define DISPC_CONTROL_TFTDATALINES_18 0x00000200 105 #define DISPC_CONTROL_TFTDATALINES_24 0x00000300 106 #define DISPC_CONTROL_SECURE 0x00000400 107 #define DISPC_CONTROL_RFBIMODE 0x00000800 108 #define DISPC_CONTROL_OVERLAYOPT 0x00001000 109 #define DISPC_CONTROL_GPIN0 0x00002000 110 #define DISPC_CONTROL_GPIN1 0x00004000 111 #define DISPC_CONTROL_GPOUT0 0x00008000 112 #define DISPC_CONTROL_GPOUT1 0x00010000 113 #define DISPC_CONTROL_HT 0x00070000 114 #define DISPC_CONTROL_HT_s(x) ((x) << 17) 115 #define DISPC_CONTROL_TDMENABLE 0x00100000 116 #define DISPC_CONTROL_TDMPARALLEL_8 0x00000000 117 #define DISPC_CONTROL_TDMPARALLEL_9 0x00200000 118 #define DISPC_CONTROL_TDMPARALLEL_12 0x00400000 119 #define DISPC_CONTROL_TDMPARALLEL_16 0x00600000 120 #define DISPC_CONTROL_TDMCYCLE_1 0x00000000 121 #define DISPC_CONTROL_TDMCYCLE_2 0x00800000 122 #define DISPC_CONTROL_TDMCYCLE_3 0x00000000 123 #define DISPC_CONTROL_TDMCYCLE_3_2 0x01800000 124 #define DISPC_CONTROL_TDMUNUSED_0 0x00000000 125 #define DISPC_CONTROL_TDMUNUSED_1 0x02000000 126 #define DISPC_CONTROL_TDMUNUSED_M 0x04000000 127 #define DISPC_CONFIG 0x0044 128 #define DISPC_CONFIG_PIXELGATED 0x00000001 129 #define DISPC_CONFIG_LOADMODE_PGE 0x00000000 130 #define DISPC_CONFIG_LOADMODE_PG 0x00000002 131 #define DISPC_CONFIG_LOADMODE_DATA 0x00000004 132 #define DISPC_CONFIG_LOADMODE_DATA_PG 0x00000006 133 #define DISPC_CONFIG_PALETTEGAMMA 0x00000008 134 #define DISPC_CONFIG_PIXELDATAGATED 0x00000010 135 #define DISPC_CONFIG_PIXELCLOCKGATED 0x00000020 136 #define DISPC_CONFIG_HSYNCGATED 0x00000040 137 #define DISPC_CONFIG_VSYNCGATED 0x00000080 138 #define DISPC_CONFIG_ACBIAGATED 0x00000100 139 #define DISPC_CONFIG_FUNCGATED 0x00000200 140 #define DISPC_CONFIG_TCKLCDEN 0x00000400 141 #define DISPC_CONFIG_TCKLCDSEL 0x00000800 142 #define DISPC_CONFIG_TCKDIGEN 0x00001000 143 #define DISPC_CONFIG_TCKDIGSEL 0x00002000 144 #define DISPC_CAPABLE 0x0048 145 #define DISPC_DEFAULT_COLOR0 0x004C 146 #define DISPC_DEFAULT_COLOR1 0x0050 147 #define DISPC_TRANS_COLOR0 0x0054 148 #define DISPC_TRANS_COLOR1 0x0058 149 #define DISPC_LINE_STATUS 0x005C 150 #define DISPC_LINE_NUMBER 0x0060 151 #define DISPC_TIMING_H 0x0064 152 #define DISPC_TIMING_H_HSW_s(x) ((x) << 0) 153 #define DISPC_TIMING_H_HFP_s(x) ((x) << 8) 154 #define DISPC_TIMING_H_HBP_s(x) ((x) << 20) 155 #define DISPC_TIMING_V 0x0068 156 #define DISPC_TIMING_V_VSW_s(x) ((x) << 0) 157 #define DISPC_TIMING_V_VFP_s(x) ((x) << 8) 158 #define DISPC_TIMING_V_VBP_s(x) ((x) << 20) 159 #define DISPC_POL_FREQ 0x006C 160 #define DISPC_POL_FREQ_ACB_s(x) ((x) << 0) 161 #define DISPC_POL_FREQ_ACBI_s(x) ((x) << 8) 162 #define DISPC_POL_FREQ_IVS 0x00001000 163 #define DISPC_POL_FREQ_IHS 0x00002000 164 #define DISPC_POL_FREQ_IPC 0x00004000 165 #define DISPC_POL_FREQ_IEO 0x00008000 166 #define DISPC_POL_FREQ_RF 0x00010000 167 #define DISPC_POL_FREQ_ONOFF 0x00020000 168 #define DISPC_DIVISOR 0x0070 169 #define DISPC_DIVISOR_PCD_s(x) ((x) << 0) 170 #define DISPC_DIVISOR_LCD_s(x) ((x) << 16) 171 #define DISPC_SIZE_DIG 0x0078 172 #define DISPC_SIZE_DIG_PPL_s(x) ((x) << 0) 173 #define DISPC_SIZE_DIG_LPP_s(x) ((x) << 16) 174 #define DISPC_SIZE_LCD 0x007C 175 #define DISPC_SIZE_LCD_PPL_s(x) ((x) << 0) 176 #define DISPC_SIZE_LCD_LPP_s(x) ((x) << 16) 177 #define DISPC_GFX_BA0 0x0080 178 #define DISPC_GFX_BA1 0x0084 179 #define DISPC_GFX_POSITION 0x0088 180 #define DISPC_GFX_SIZE 0x008C 181 #define DISPC_GFX_SIZE_X_s(x) ((x) << 0) 182 #define DISPC_GFX_SIZE_Y_s(x) ((x) << 16) 183 #define DISPC_GFX_ATTRIBUTES 0x00A0 184 #define DISPC_GFX_ATTRIBUTES_GFXENABLE 0x001 185 #define DISPC_GFX_ATTRIBUTES_GFXFMT_1 0x000 186 #define DISPC_GFX_ATTRIBUTES_GFXFMT_2 0x002 187 #define DISPC_GFX_ATTRIBUTES_GFXFMT_4 0x004 188 #define DISPC_GFX_ATTRIBUTES_GFXFMT_8 0x006 189 #define DISPC_GFX_ATTRIBUTES_GFXFMT_12 0x008 190 #define DISPC_GFX_ATTRIBUTES_GFXFMT_16 0x00c 191 #define DISPC_GFX_ATTRIBUTES_GFXFMT_24 0x010 192 #define DISPC_GFX_ATTRIBUTES_GFXREPLICATE 0x020 193 #define DISPC_GFX_ATTRIBUTES_BURST_4 0x000 194 #define DISPC_GFX_ATTRIBUTES_BURST_8 0x040 195 #define DISPC_GFX_ATTRIBUTES_BURST_16 0x080 196 #define DISPC_GFX_ATTRIBUTES_GFXCHANNELOUT 0x100 197 #define DISPC_GFX_ATTRIBUTES_NIBBLEMODE 0x200 198 #define DISPC_GFX_ATTRIBUTES_ENDIAN 0x400 199 #define DISPC_GFX_FIFO_THRESHOLD 0x00A4 200 #define DISPC_GFX_FIFO_THRESHOLD_HIGH_SHIFT 16 201 #define DISPC_GFX_FIFO_THRESHOLD_LOW_SHIFT 0 202 #define DISPC_GFX_FIFO_SIZE_STATUS 0x00A8 203 #define DISPC_GFX_ROW_INC 0x00AC 204 #define DISPC_GFX_PIXEL_INC 0x00B0 205 #define DISPC_GFX_WINDOW_SKIP 0x00B4 206 #define DISPC_GFX_TABLE_BA 0x00B8 207 #define DISPC_VID1_BA0 0x00BC 208 #define DISPC_VID1_BA1 0x00C0 209 #define DISPC_VID1_POSITION 0x00C4 210 #define DISPC_VID1_SIZE 0x00C8 211 #define DISPC_VID1_ATTRIBUTES 0x00CC 212 #define DISPC_VID1_FIFO_THRESHOLD 0x00D0 213 #define DISPC_VID1_FIFO_SIZE_STATUS 0x00D4 214 #define DISPC_VID1_ROW_INC 0x00D8 215 #define DISPC_VID1_PIXEL_INC 0x00DC 216 #define DISPC_VID1_FIR 0x00E0 217 #define DISPC_VID1_PICTURE_SIZE 0x00E4 218 #define DISPC_VID1_ACCU0 0x00E8 219 #define DISPC_VID1_ACCU1 0x00EC 220 #define DISPC_VID1_FIR_COEF_H0 0x00F0 221 #define DISPC_VID1_FIR_COEF_H1 0x00F8 222 #define DISPC_VID1_FIR_COEF_H2 0x0100 223 #define DISPC_VID1_FIR_COEF_H3 0x0108 224 #define DISPC_VID1_FIR_COEF_H4 0x0110 225 #define DISPC_VID1_FIR_COEF_H5 0x0118 226 #define DISPC_VID1_FIR_COEF_H6 0x0120 227 #define DISPC_VID1_FIR_COEF_H7 0x0128 228 #define DISPC_VID1_FIR_COEF_HV0 0x00F4 229 #define DISPC_VID1_FIR_COEF_HV1 0x00FC 230 #define DISPC_VID1_FIR_COEF_HV2 0x0104 231 #define DISPC_VID1_FIR_COEF_HV3 0x010C 232 #define DISPC_VID1_FIR_COEF_HV4 0x0114 233 #define DISPC_VID1_FIR_COEF_HV5 0x011C 234 #define DISPC_VID1_FIR_COEF_HV6 0x0124 235 #define DISPC_VID1_FIR_COEF_HV7 0x012C 236 #define DISPC_VID1_CONV_COEF0 0x0130 237 #define DISPC_VID1_CONV_COEF1 0x0134 238 #define DISPC_VID1_CONV_COEF2 0x0138 239 #define DISPC_VID1_CONV_COEF3 0x013C 240 #define DISPC_VID1_CONV_COEF4 0x0140 241 #define DISPC_VID2_BA0 0x014C 242 #define DISPC_VID2_BA1 0x0150 243 #define DISPC_VID2_POSITION 0x0154 244 #define DISPC_VID2_SIZE 0x0158 245 #define DISPC_VID2_ATTRIBUTES 0x015C 246 #define DISPC_VID2_FIFO_THRESHOLD 0x0160 247 #define DISPC_VID2_FIFO_SIZE_STATUS 0x0164 248 #define DISPC_VID2_ROW_INC 0x0168 249 #define DISPC_VID2_PIXEL_INC 0x016C 250 #define DISPC_VID2_FIR 0x0170 251 #define DISPC_VID2_PICTURE_SIZE 0x0174 252 #define DISPC_VID2_ACCU0 0x0178 253 #define DISPC_VID2_ACCU1 0x017C 254 #define DISPC_VID2_FIR_COEF_H0 0x0180 255 #define DISPC_VID2_FIR_COEF_H1 0x0188 256 #define DISPC_VID2_FIR_COEF_H2 0x0190 257 #define DISPC_VID2_FIR_COEF_H3 0x0198 258 #define DISPC_VID2_FIR_COEF_H4 0x01A0 259 #define DISPC_VID2_FIR_COEF_H5 0x01A8 260 #define DISPC_VID2_FIR_COEF_H6 0x01B0 261 #define DISPC_VID2_FIR_COEF_H7 0x01B8 262 #define DISPC_VID2_FIR_COEF_HV0 0x0184 263 #define DISPC_VID2_FIR_COEF_HV1 0x018C 264 #define DISPC_VID2_FIR_COEF_HV2 0x0194 265 #define DISPC_VID2_FIR_COEF_HV3 0x019C 266 #define DISPC_VID2_FIR_COEF_HV4 0x01A4 267 #define DISPC_VID2_FIR_COEF_HV5 0x01AC 268 #define DISPC_VID2_FIR_COEF_HV6 0x01B4 269 #define DISPC_VID2_FIR_COEF_HV7 0x01BC 270 #define DISPC_VID2_CONV_COEF0 0x01C0 271 #define DISPC_VID2_CONV_COEF1 0x01C4 272 #define DISPC_VID2_CONV_COEF2 0x01C8 273 #define DISPC_VID2_CONV_COEF3 0x01CC 274 #define DISPC_VID2_CONV_COEF4 0x01D0 275 #define DISPC_DATA_CYCLE1 0x01D4 276 #define DISPC_DATA_CYCLE2 0x01D8 277 #define DISPC_DATA_CYCLE3 0x01DC 278 #define DISPC_SIZE 0x0200 279 280 /* RFBI */ 281 #define RFBI_REVISION 0x0000 282 #define RFBI_SYSCONFIG 0x0010 283 #define RFBI_SYSSTATUS 0x0014 284 #define RFBI_CONTROL 0x0040 285 #define RFBI_PIXEL_CNT 0x0044 286 #define RFBI_LINE_NUMBER 0x0048 287 #define RFBI_CMD 0x004C 288 #define RFBI_PARAM 0x0050 289 #define RFBI_DATA 0x0054 290 #define RFBI_READ 0x0058 291 #define RFBI_STATUS 0x005C 292 #define RFBI_CONFIG0 0x0060 293 #define RFBI_CONFIG1 0x0078 294 #define RFBI_ONOFF_TIME0 0x0064 295 #define RFBI_ONOFF_TIME1 0x007C 296 #define RFBI_CYCLE_TIME0 0x0068 297 #define RFBI_CYCLE_TIME1 0x0080 298 #define RFBI_DATA_CYCLE1_0 0x006C 299 #define RFBI_DATA_CYCLE1_1 0x0084 300 #define RFBI_DATA_CYCLE2_0 0x0070 301 #define RFBI_DATA_CYCLE2_1 0x0088 302 #define RFBI_DATA_CYCLE3_0 0x0074 303 #define RFBI_DATA_CYCLE3_1 0x008C 304 #define RFBI_VSYNC_WIDTH 0x0090 305 #define RFBI_HSYNC_WIDTH 0x0094 306 307 /* VENC1 */ 308 #define REV_ID 0x0000 309 #define STATUS 0x0004 310 #define F_CONTROL 0x0008 311 #define VIDOUT_CTRL 0x0010 312 #define SYNC_CTRL 0x0014 313 #define LLEN 0x001C 314 #define FLENS 0x0020 315 #define HFLTR_CTRL 0x0024 316 #define CC_CARR_WSS_CARR 0x0028 317 #define C_PHASE 0x002C 318 #define GAIN_U 0x0030 319 #define GAIN_V 0x0034 320 #define GAIN_Y 0x0038 321 #define BLACK_LEVEL 0x003C 322 #define BLANK_LEVEL 0x0040 323 #define X_COLOR 0x0044 324 #define M_CONTROL 0x0048 325 #define BSTAMP_WSS_DATA 0x004C 326 #define S_CARR 0x0050 327 #define LINE21 0x0054 328 #define LN_SEL 0x0058 329 #define L21_WC_CTL 0x005C 330 #define HTRIGGER_VTRIGGER 0x0060 331 #define SAVID_EAVID 0x0064 332 #define FLEN_FAL 0x0068 333 #define LAL_PHASE_RESET 0x006C 334 #define HS_INT_START_STOP_X 0x0070 335 #define HS_EXT_START_STOP_X 0x0074 336 #define VS_INT_START_X 0x0078 337 #define VS_INT_STOP_X_VS_INT_START_Y 0x007C 338 #define VS_INT_STOP_Y_VS_EXT_START_X 0x0080 339 #define VS_EXT_STOP_X_VS_EXT_START_Y 0x0084 340 #define VS_EXT_STOP_Y 0x0088 341 #define AVID_START_STOP_X 0x0090 342 #define AVID_START_STOP_Y 0x0094 343 #define FID_INT_START_X_FID_INT_START_Y 0x00A0 344 #define FID_INT_OFFSET_Y_FID_EXT_START_X 0x00A4 345 #define FID_EXT_START_Y_FID_EXT_OFFSET_Y 0x00A8 346 #define TVDETGP_INT_START_STOP_X 0x00B0 347 #define TVDETGP_INT_START_STOP_Y 0x00B4 348 #define GEN_CTRL 0x00B8 349 #define DAC_TST_DAC_A 0x00C4 350 #define DAC_B_DAC_C 0x00C8 351 352 353 /* NO CONSOLE SUPPORT */ 354 355 356 /* assumes 565 panel. */ 357 struct omdisplay_panel_data { 358 int width; 359 int height; 360 int horiz_sync_width; 361 int horiz_front_porch; 362 int horiz_back_porch; 363 int vert_sync_width; 364 int vert_front_porch; 365 int vert_back_porch; 366 int panel_flags; 367 int sync; 368 int depth; 369 #define PANEL_SYNC_H_ACTIVE_HIGH 1 370 #define PANEL_SYNC_V_ACTIVE_HIGH 2 371 int linebytes; 372 }; 373 374 #define PIXELDEPTH 16 375 #define PIXELWIDTH 2 376 377 struct omdisplay_panel_data default_panel = { 378 240, /* Width */ 379 322, /* Height */ 380 9, 9, 19, /* horiz sync, fp, bp */ 381 1, 2, 2, /* vert sync, fp, bp */ 382 0, /* flags */ 383 0, /* sync */ 384 PIXELDEPTH, 385 240*PIXELWIDTH 386 }; 387 388 struct omdisplay_screen { 389 LIST_ENTRY(omdisplay_screen) link; 390 391 /* Frame buffer */ 392 bus_dmamap_t dma; 393 bus_dma_segment_t segs[1]; 394 int nsegs; 395 size_t buf_size; 396 size_t map_size; 397 void *buf_va; 398 int depth; 399 400 /* rasterop */ 401 struct rasops_info rinfo; 402 }; 403 404 struct omdisplay_softc { 405 struct device sc_dev; 406 bus_space_tag_t sc_iot; 407 bus_space_handle_t sc_dsioh; 408 bus_space_handle_t sc_dcioh; 409 bus_space_handle_t sc_rfbioh; 410 bus_space_handle_t sc_venioh; 411 bus_dma_tag_t sc_dma_tag; 412 413 void *sc_ih; 414 415 int sc_nscreens; 416 LIST_HEAD(,omdisplay_screen) sc_screens; 417 418 struct omdisplay_panel_data *sc_geometry; 419 struct omdisplay_screen *sc_active; 420 }; 421 422 int omdisplay_match(struct device *parent, void *v, void *aux); 423 void omdisplay_attach(struct device *parent, struct device *self, void *args); 424 int omdisplay_activate(struct device *, int); 425 int omdisplay_ioctl(void *v, u_long cmd, caddr_t data, int flag, 426 struct proc *p); 427 void omdisplay_burner(void *v, u_int on, u_int flags); 428 int omdisplay_show_screen(void *v, void *cookie, int waitok, 429 void (*cb)(void *, int, int), void *cbarg); 430 int omdisplay_param(struct omdisplay_softc *sc, ulong cmd, 431 struct wsdisplay_param *dp); 432 int omdisplay_max_brightness(void); 433 int omdisplay_get_brightness(void); 434 void omdisplay_set_brightness(int newval); 435 void omdisplay_set_brightness_internal(int newval); 436 int omdisplay_get_backlight(void); 437 void omdisplay_set_backlight(int on); 438 void omdisplay_blank(int blank); 439 void omdisplay_suspend(struct omdisplay_softc *sc); 440 void omdisplay_resume(struct omdisplay_softc *sc); 441 void omdisplay_initialize(struct omdisplay_softc *sc, 442 struct omdisplay_panel_data *geom); 443 void omdisplay_setup_rasops(struct omdisplay_softc *sc, 444 struct rasops_info *rinfo); 445 int omdisplay_alloc_screen(void *v, const struct wsscreen_descr *_type, 446 void **cookiep, int *curxp, int *curyp, uint32_t *attrp); 447 int omdisplay_new_screen(struct omdisplay_softc *sc, 448 struct omdisplay_screen *scr, int depth); 449 paddr_t omdisplay_mmap(void *v, off_t offset, int prot); 450 int omdisplay_load_font(void *, void *, struct wsdisplay_font *); 451 int omdisplay_list_font(void *, struct wsdisplay_font *); 452 void omdisplay_free_screen(void *v, void *cookie); 453 void omdisplay_start(struct omdisplay_softc *sc); 454 void omdisplay_stop(struct omdisplay_softc *sc); 455 int omdisplay_intr(void *v); 456 void omdisplay_dumpreg(struct omdisplay_softc *sc); 457 458 struct cfattach omdisplay_ca = { 459 sizeof (struct omdisplay_softc), omdisplay_match, omdisplay_attach, 460 NULL, omdisplay_activate 461 }; 462 463 struct cfdriver omdisplay_cd = { 464 NULL, "omdisplay", DV_DULL 465 }; 466 467 struct wsdisplay_accessops omdisplay_accessops = { 468 .ioctl = omdisplay_ioctl, 469 .mmap = omdisplay_mmap, 470 .alloc_screen = omdisplay_alloc_screen, 471 .free_screen = omdisplay_free_screen, 472 .show_screen = omdisplay_show_screen, 473 .load_font = omdisplay_load_font, 474 .list_font = omdisplay_list_font, 475 .burn_screen = omdisplay_burner 476 477 }; 478 479 struct omdisplay_wsscreen_descr { 480 struct wsscreen_descr c; /* standard descriptor */ 481 int depth; /* bits per pixel */ 482 int flags; /* rasops flags */ 483 }; 484 485 struct omdisplay_wsscreen_descr omdisplay_screen = { 486 { 487 "std" 488 }, 489 16, /* bits per pixel */ 490 0 /* rotate */ 491 }; 492 493 const struct wsscreen_descr *omdisplay_scr_descr[] = { 494 &omdisplay_screen.c 495 }; 496 497 /* XXX - what about flip phones with CLI */ 498 const struct wsscreen_list omdisplay_screen_list = { 499 sizeof omdisplay_scr_descr / sizeof omdisplay_scr_descr[0], 500 omdisplay_scr_descr 501 }; 502 503 504 int 505 omdisplay_match(struct device *parent, void *v, void *aux) 506 { 507 /* XXX */ 508 return (1); 509 } 510 511 void 512 omdisplay_attach(struct device *parent, struct device *self, void *args) 513 { 514 struct ahb_attach_args *aa = args; 515 struct omdisplay_softc *sc = (struct omdisplay_softc *) self; 516 struct wsemuldisplaydev_attach_args wsaa; 517 518 519 sc->sc_iot = aa->aa_iot; 520 521 if (bus_space_map(sc->sc_iot, aa->aa_addr, OMDISPLAY_SIZE, 0, 522 &sc->sc_dsioh)) 523 panic("omdisplay_attach: bus_space_map failed!"); 524 525 if (bus_space_subregion(sc->sc_iot, sc->sc_dsioh, 0x400, 1024, 526 &sc->sc_dcioh)) 527 panic("omdisplay_attach: bus_space_submap failed!"); 528 529 if (bus_space_subregion(sc->sc_iot, sc->sc_dsioh, 0x800, 1024, 530 &sc->sc_rfbioh)) 531 panic("omdisplay_attach: bus_space_submap failed!"); 532 533 if (bus_space_subregion(sc->sc_iot, sc->sc_dsioh, 0xc00, 1024, 534 &sc->sc_venioh)) 535 panic("omdisplay_attach: bus_space_submap failed!"); 536 537 538 sc->sc_nscreens = 0; 539 LIST_INIT(&sc->sc_screens); 540 541 sc->sc_dma_tag = aa->aa_dmat; 542 543 sc->sc_ih = arm_intr_establish(aa->aa_intr, IPL_BIO /* XXX */, 544 omdisplay_intr, sc, sc->sc_dev.dv_xname); 545 546 printf ("\n"); 547 548 sc->sc_geometry = &default_panel; 549 550 { 551 /* XXX - dummy? */ 552 struct rasops_info dummy; 553 554 omdisplay_initialize(sc, sc->sc_geometry); 555 556 /* 557 * Initialize a dummy rasops_info to compute fontsize and 558 * the screen size in chars. 559 */ 560 bzero(&dummy, sizeof(dummy)); 561 omdisplay_setup_rasops(sc, &dummy); 562 } 563 564 wsaa.console = 0; 565 wsaa.scrdata = &omdisplay_screen_list; 566 wsaa.accessops = &omdisplay_accessops; 567 wsaa.accesscookie = sc; 568 wsaa.defaultscreens = 0; 569 570 (void)config_found(self, &wsaa, wsemuldisplaydevprint); 571 572 /* backlight? */ 573 } 574 575 576 int 577 omdisplay_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p) 578 { 579 struct omdisplay_softc *sc = v; 580 struct wsdisplay_fbinfo *wsdisp_info; 581 struct omdisplay_screen *scr = sc->sc_active; 582 int res = EINVAL; 583 584 switch (cmd) { 585 case WSDISPLAYIO_GETPARAM: 586 case WSDISPLAYIO_SETPARAM: 587 res = omdisplay_param(sc, cmd, (struct wsdisplay_param *)data); 588 break; 589 case WSDISPLAYIO_GTYPE: 590 *(u_int *)data = WSDISPLAY_TYPE_PXALCD; /* XXX */ 591 break; 592 593 case WSDISPLAYIO_GINFO: 594 wsdisp_info = (struct wsdisplay_fbinfo *)data; 595 596 wsdisp_info->height = sc->sc_geometry->height; 597 wsdisp_info->width = sc->sc_geometry->width; 598 wsdisp_info->depth = 16; /* XXX */ 599 wsdisp_info->cmsize = 0; 600 break; 601 602 case WSDISPLAYIO_GETCMAP: 603 case WSDISPLAYIO_PUTCMAP: 604 return EINVAL; /* XXX Colormap */ 605 606 case WSDISPLAYIO_SVIDEO: 607 case WSDISPLAYIO_GVIDEO: 608 break; 609 610 case WSDISPLAYIO_GCURPOS: 611 case WSDISPLAYIO_SCURPOS: 612 case WSDISPLAYIO_GCURMAX: 613 case WSDISPLAYIO_GCURSOR: 614 case WSDISPLAYIO_SCURSOR: 615 default: 616 return -1; /* not implemented */ 617 618 case WSDISPLAYIO_LINEBYTES: 619 if (scr != NULL) 620 *(u_int *)data = scr->rinfo.ri_stride; 621 else 622 *(u_int *)data = 0; 623 break; 624 625 } 626 627 if (res == EINVAL) 628 res = omdisplay_ioctl(v, cmd, data, flag, p); 629 630 return res; 631 } 632 633 void 634 omdisplay_burner(void *v, u_int on, u_int flags) 635 { 636 637 omdisplay_set_brightness(on ? omdisplay_get_brightness() : 0); 638 639 /* GPIO controls for appsliver */ 640 if (on) { 641 omgpio_set_bit(93); /* 1 enable backlight */ 642 omgpio_set_dir(93, OMGPIO_DIR_OUT); 643 omgpio_clear_bit(26); /* 0 enable LCD */ 644 omgpio_set_dir(26, OMGPIO_DIR_OUT); 645 } else { 646 omgpio_clear_bit(93); /* 0 disable backlt */ 647 omgpio_set_dir(93, OMGPIO_DIR_OUT); 648 omgpio_set_bit(26); /* 1 disable LCD */ 649 omgpio_set_dir(26, OMGPIO_DIR_OUT); 650 } 651 } 652 653 int 654 omdisplay_show_screen(void *v, void *cookie, int waitok, 655 void (*cb)(void *, int, int), void *cbarg) 656 { 657 struct omdisplay_softc *sc = v; 658 struct rasops_info *ri = cookie; 659 struct omdisplay_screen *scr = ri->ri_hw, *old; 660 661 old = sc->sc_active; 662 if (old == scr) 663 return 0; 664 665 if (old != NULL) 666 ; /* Stop old screen */ 667 668 sc->sc_active = scr; 669 omdisplay_initialize(sc, sc->sc_geometry); 670 671 /* Turn on LCD */ 672 omdisplay_burner(v, 1, 0); 673 674 return (0); 675 } 676 677 678 679 /* 680 * wsdisplay I/O controls 681 */ 682 int 683 omdisplay_param(struct omdisplay_softc *sc, ulong cmd, 684 struct wsdisplay_param *dp) 685 { 686 int res = EINVAL; 687 688 switch (dp->param) { 689 case WSDISPLAYIO_PARAM_BACKLIGHT: 690 if (cmd == WSDISPLAYIO_GETPARAM) { 691 dp->min = 0; 692 dp->max = 1; 693 dp->curval = omdisplay_get_backlight(); 694 res = 0; 695 } else if (cmd == WSDISPLAYIO_SETPARAM) { 696 /* XXX */ 697 // omdisplay_set_backlight(dp->curval); 698 res = 0; 699 } 700 break; 701 702 case WSDISPLAYIO_PARAM_CONTRAST: 703 /* unsupported */ 704 res = ENOTTY; 705 break; 706 707 case WSDISPLAYIO_PARAM_BRIGHTNESS: 708 if (cmd == WSDISPLAYIO_GETPARAM) { 709 dp->min = 1; 710 dp->max = omdisplay_max_brightness(); 711 dp->curval = omdisplay_get_brightness(); 712 res = 0; 713 } else if (cmd == WSDISPLAYIO_SETPARAM) { 714 /* XXX */ 715 // omdisplay_set_brightness(dp->curval); 716 res = 0; 717 } 718 break; 719 } 720 721 return res; 722 } 723 724 725 /* 726 * LCD backlight 727 */ 728 729 static int lcdbrightnesscurval = 1; 730 static int lcdislit = 1; 731 static int lcdisblank = 0; 732 733 struct lcd_backlight { 734 int duty; /* LZ9JG18 DAC value */ 735 int cont; /* BACKLIGHT_CONT signal */ 736 int on; /* BACKLIGHT_ON signal */ 737 }; 738 739 const struct lcd_backlight lcd_bl[] = { 740 { 0x00, 0, 0 }, /* 0: Off */ 741 { 0x00, 0, 1 }, /* 1: 0% */ 742 { 0x01, 0, 1 }, /* 2: 20% */ 743 { 0x07, 0, 1 }, /* 3: 40% */ 744 { 0x01, 1, 1 }, /* 4: 60% */ 745 { 0x07, 1, 1 }, /* 5: 80% */ 746 { 0x11, 1, 1 }, /* 6: 100% */ 747 { -1, -1, -1 } /* 7: Invalid */ 748 }; 749 #define CURRENT_BACKLIGHT lcd_bl 750 751 int 752 omdisplay_max_brightness(void) 753 { 754 int i; 755 756 for (i = 0; CURRENT_BACKLIGHT[i].duty != -1; i++) 757 ; 758 return i - 1; 759 } 760 761 int 762 omdisplay_get_brightness(void) 763 { 764 765 return lcdbrightnesscurval; 766 } 767 768 void 769 omdisplay_set_brightness(int newval) 770 { 771 int max; 772 773 max = omdisplay_max_brightness(); 774 if (newval < 0) 775 newval = 0; 776 else if (newval > max) 777 newval = max; 778 779 if (omdisplay_get_backlight() && !lcdisblank) 780 omdisplay_set_brightness_internal(newval); 781 782 if (newval > 0) 783 lcdbrightnesscurval = newval; 784 } 785 786 void 787 omdisplay_set_brightness_internal(int newval) 788 { 789 static int curval = 1; 790 int i; 791 792 /* 793 * It appears that the C3000 backlight can draw too much power if we 794 * switch it from a low to a high brightness. Increasing brightness 795 * in steps avoids this issue. 796 */ 797 if (newval > curval) { 798 for (i = curval + 1; i <= newval; i++) { 799 /* atlas controls */ 800 /* CURRENT_BACKLIGHT[newval].duty); */ 801 } 802 } else { 803 /* atlas controls */ 804 /* CURRENT_BACKLIGHT[newval].duty); */ 805 } 806 807 curval = newval; 808 } 809 810 int 811 omdisplay_get_backlight(void) 812 { 813 814 return lcdislit; 815 } 816 817 void 818 omdisplay_set_backlight(int on) 819 { 820 821 if (!on) { 822 omdisplay_set_brightness(0); 823 lcdislit = 0; 824 } else { 825 lcdislit = 1; 826 omdisplay_set_brightness(omdisplay_get_brightness()); 827 } 828 } 829 830 void 831 omdisplay_blank(int blank) 832 { 833 834 if (blank) { 835 omdisplay_set_brightness(0); 836 lcdisblank = 1; 837 } else { 838 lcdisblank = 0; 839 omdisplay_set_brightness(omdisplay_get_brightness()); 840 } 841 } 842 843 void 844 omdisplay_suspend(struct omdisplay_softc *sc) 845 { 846 if (sc->sc_active != NULL) { 847 omdisplay_stop(sc); 848 /* XXX disable clocks */ 849 } 850 } 851 852 void 853 omdisplay_resume(struct omdisplay_softc *sc) 854 { 855 if (sc->sc_active != NULL) { 856 /* XXX - clocks? */ 857 omdisplay_initialize(sc, sc->sc_geometry); 858 omdisplay_start(sc); 859 } 860 } 861 862 void 863 omdisplay_activate(struct device *self, int act) 864 { 865 struct omdisplay_softc *sc = (struct omdisplay_softc *)self; 866 867 switch (act) { 868 case DVACT_SUSPEND: 869 omdisplay_set_brightness(0); 870 omdisplay_suspend(sc); 871 break; 872 case DVACT_RESUME: 873 omdisplay_resume(sc); 874 omdisplay_set_brightness(omdisplay_get_brightness()); 875 break; 876 } 877 return 0; 878 } 879 880 void 881 omdisplay_initialize(struct omdisplay_softc *sc, 882 struct omdisplay_panel_data *geom) 883 { 884 struct omdisplay_screen *scr; 885 u_int32_t reg; 886 u_int32_t mode; 887 #if 0 888 int den, nom; /* pixel rate */ 889 #endif 890 891 892 reg = bus_space_read_4(sc->sc_iot, sc->sc_dcioh, DISPC_CONTROL); 893 894 scr = sc->sc_active; 895 896 if (reg & (DISPC_CONTROL_LCDENABLE|DISPC_CONTROL_DIGITALENABLE)) { 897 omdisplay_stop(sc); 898 } 899 900 /* XXX - enable clocks */ 901 902 /* disable all interrupts */ 903 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_IRQENABLE, 0); 904 905 /* GPIOs ? */ 906 907 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_CONFIG, 908 DISPC_CONFIG_LOADMODE_PG|DISPC_CONFIG_LOADMODE_DATA); 909 910 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_DEFAULT_COLOR0, 0); 911 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_DEFAULT_COLOR1, 0); 912 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_TRANS_COLOR0, 0); 913 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_TRANS_COLOR1, 0); 914 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_LINE_NUMBER, 0); 915 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_DATA_CYCLE1, 0); 916 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_DATA_CYCLE2, 0); 917 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_DATA_CYCLE3, 0); 918 919 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_SYSCONFIG, 920 DISPC_SYSCONFIG_SIDLEMODE_NONE| 921 DISPC_SYSCONFIG_MIDLEMODE_NONE); 922 923 #if 0 924 if (geom->panel_flags & LCDPANEL_TDM) { 925 nom = tdmflags >>8 & 0x3; 926 den = tdmflags & 0x3; 927 } else { 928 nom = 1; 929 den = 1; 930 } 931 hsync = geom->width*den/nom + geom->horiz_sync_width + 932 geom->horiz_front_porch + geom->horiz_back_porch; 933 #endif 934 935 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_TIMING_H, 936 DISPC_TIMING_H_HSW_s(geom->horiz_sync_width) | 937 DISPC_TIMING_H_HFP_s(geom->horiz_front_porch) | 938 DISPC_TIMING_H_HBP_s(geom->horiz_back_porch)); 939 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_TIMING_V, 940 DISPC_TIMING_V_VSW_s(geom->vert_sync_width) | 941 DISPC_TIMING_V_VFP_s(geom->vert_front_porch) | 942 DISPC_TIMING_V_VBP_s(geom->vert_back_porch)); 943 944 reg = 0; 945 if (geom->sync & PANEL_SYNC_H_ACTIVE_HIGH) 946 reg |= DISPC_POL_FREQ_IHS; 947 if (geom->sync & PANEL_SYNC_V_ACTIVE_HIGH) 948 reg |= DISPC_POL_FREQ_IVS; 949 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_POL_FREQ, reg); 950 951 952 /* clkdiv = pixclock/period; */ 953 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_SIZE_LCD, 954 DISPC_SIZE_LCD_PPL_s(geom->width-1) | 955 DISPC_SIZE_LCD_LPP_s(geom->height-1)); 956 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_SIZE_DIG, 957 DISPC_SIZE_LCD_PPL_s(geom->width-1) | 958 DISPC_SIZE_LCD_LPP_s(geom->height-1)); 959 960 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_GFX_SIZE, 961 DISPC_GFX_SIZE_X_s(geom->width-1) | 962 DISPC_GFX_SIZE_Y_s(geom->height-1)); 963 964 965 /* XXX!!! */ 966 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_DIVISOR, 967 DISPC_DIVISOR_LCD_s(1) | DISPC_DIVISOR_PCD_s(6)); 968 969 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_GFX_BA0, 970 scr->segs[0].ds_addr); 971 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_GFX_BA1, 972 scr->segs[0].ds_addr); 973 974 /* non-rotated */ 975 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_GFX_PIXEL_INC, 1); 976 977 978 /* XXX 24bit -> 32 pixels */ 979 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_GFX_ROW_INC, 980 1 + scr->rinfo.ri_stride - 981 (scr->rinfo.ri_width * scr->rinfo.ri_depth / 8)); 982 983 switch (geom->depth) { 984 case 1: 985 mode = DISPC_GFX_ATTRIBUTES_GFXFMT_1; 986 break; 987 case 2: 988 mode = DISPC_GFX_ATTRIBUTES_GFXFMT_2; 989 break; 990 case 4: 991 mode = DISPC_GFX_ATTRIBUTES_GFXFMT_4; 992 break; 993 case 8: 994 mode = DISPC_GFX_ATTRIBUTES_GFXFMT_8; 995 break; 996 case 12: 997 mode = DISPC_GFX_ATTRIBUTES_GFXFMT_12; 998 break; 999 case 16: 1000 mode = DISPC_GFX_ATTRIBUTES_GFXFMT_16; 1001 break; 1002 case 24: 1003 mode = DISPC_GFX_ATTRIBUTES_GFXFMT_24; 1004 break; 1005 default: 1006 panic("invalid depth %d", geom->depth); 1007 } 1008 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_GFX_ATTRIBUTES, 1009 DISPC_GFX_ATTRIBUTES_GFXENABLE | mode | 1010 DISPC_GFX_ATTRIBUTES_BURST_8); 1011 1012 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_GFX_POSITION, 0); 1013 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_GFX_WINDOW_SKIP, 0); 1014 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_GFX_FIFO_THRESHOLD, 1015 (0xfc << DISPC_GFX_FIFO_THRESHOLD_HIGH_SHIFT) | 1016 (0xc0 << DISPC_GFX_FIFO_THRESHOLD_LOW_SHIFT)); 1017 1018 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_GFX_ROW_INC, 1); 1019 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_GFX_PIXEL_INC, 1); 1020 1021 /* DISPC_CONFIG_PALETTEGAMMA not enabled */ 1022 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_GFX_TABLE_BA, 1023 scr->segs[0].ds_addr); 1024 1025 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_BA0, 0); 1026 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_BA1, 0); 1027 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_SIZE, 0); 1028 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_ATTRIBUTES, 0); 1029 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_FIFO_THRESHOLD, 1030 0xc00040); /* XXX */ 1031 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_FIFO_SIZE_STATUS, 1032 0); 1033 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_ROW_INC, 1); 1034 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_PIXEL_INC, 1); 1035 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_FIR, 0); 1036 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_PICTURE_SIZE, 0); 1037 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_ACCU0, 0); 1038 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_ACCU1, 0); 1039 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_FIR_COEF_H0, 0); 1040 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_FIR_COEF_H1, 0); 1041 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_FIR_COEF_H2, 0); 1042 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_FIR_COEF_H3, 0); 1043 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_FIR_COEF_H4, 0); 1044 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_FIR_COEF_H5, 0); 1045 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_FIR_COEF_H6, 0); 1046 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_FIR_COEF_H7, 0); 1047 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_FIR_COEF_HV0, 0); 1048 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_FIR_COEF_HV1, 0); 1049 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_FIR_COEF_HV2, 0); 1050 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_FIR_COEF_HV3, 0); 1051 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_FIR_COEF_HV4, 0); 1052 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_FIR_COEF_HV5, 0); 1053 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_FIR_COEF_HV6, 0); 1054 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_FIR_COEF_HV7, 0); 1055 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_CONV_COEF0, 0); 1056 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_CONV_COEF1, 0); 1057 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_CONV_COEF2, 0); 1058 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_CONV_COEF3, 0); 1059 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_CONV_COEF4, 0); 1060 1061 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_BA0, 0); 1062 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_BA1, 0); 1063 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_SIZE, 0); 1064 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_ATTRIBUTES, 0); 1065 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_FIFO_THRESHOLD, 1066 0xc00040); /* XXX */ 1067 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_FIFO_SIZE_STATUS, 1068 0); 1069 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_ROW_INC, 1); 1070 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_PIXEL_INC, 1); 1071 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_FIR, 0); 1072 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_PICTURE_SIZE, 0); 1073 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_ACCU0, 0); 1074 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_ACCU1, 0); 1075 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_FIR_COEF_H0, 0); 1076 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_FIR_COEF_H1, 0); 1077 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_FIR_COEF_H2, 0); 1078 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_FIR_COEF_H3, 0); 1079 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_FIR_COEF_H4, 0); 1080 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_FIR_COEF_H5, 0); 1081 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_FIR_COEF_H6, 0); 1082 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_FIR_COEF_H7, 0); 1083 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_FIR_COEF_HV0, 0); 1084 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_FIR_COEF_HV1, 0); 1085 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_FIR_COEF_HV2, 0); 1086 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_FIR_COEF_HV3, 0); 1087 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_FIR_COEF_HV4, 0); 1088 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_FIR_COEF_HV5, 0); 1089 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_FIR_COEF_HV6, 0); 1090 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_FIR_COEF_HV7, 0); 1091 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_CONV_COEF0, 0); 1092 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_CONV_COEF1, 0); 1093 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_CONV_COEF2, 0); 1094 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_CONV_COEF3, 0); 1095 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_CONV_COEF4, 0); 1096 1097 omdisplay_start(sc); 1098 } 1099 1100 void 1101 omdisplay_setup_rasops(struct omdisplay_softc *sc, struct rasops_info *rinfo) 1102 { 1103 struct omdisplay_wsscreen_descr *descr; 1104 struct omdisplay_panel_data *geom; 1105 1106 descr = &omdisplay_screen; 1107 geom = sc->sc_geometry; 1108 1109 rinfo->ri_flg = descr->flags; 1110 rinfo->ri_depth = descr->depth; 1111 rinfo->ri_width = geom->width; 1112 rinfo->ri_height = geom->height; 1113 rinfo->ri_stride = geom->linebytes; 1114 1115 /* pixel position */ 1116 if (descr->depth == 16) { 1117 rinfo->ri_rnum = 5; 1118 rinfo->ri_rpos = 11; 1119 rinfo->ri_gnum = 6; 1120 rinfo->ri_gpos = 5; 1121 rinfo->ri_bnum = 5; 1122 rinfo->ri_bpos = 0; 1123 } 1124 1125 if (descr->c.nrows == 0) { 1126 /* get rasops to compute screen size the first time */ 1127 rasops_init(rinfo, 100, 100); 1128 } else { 1129 if (descr->flags != 0) /* rotate */ 1130 rasops_init(rinfo, descr->c.ncols, descr->c.nrows); 1131 else 1132 rasops_init(rinfo, descr->c.nrows, descr->c.ncols); 1133 } 1134 1135 descr->c.nrows = rinfo->ri_rows; 1136 descr->c.ncols = rinfo->ri_cols; 1137 descr->c.capabilities = rinfo->ri_caps; 1138 descr->c.textops = &rinfo->ri_ops; 1139 1140 } 1141 1142 1143 int 1144 omdisplay_alloc_screen(void *v, const struct wsscreen_descr *_type, 1145 void **cookiep, int *curxp, int *curyp, uint32_t *attrp) 1146 { 1147 struct omdisplay_softc *sc = v; 1148 struct omdisplay_screen *scr; 1149 struct rasops_info *ri; 1150 struct omdisplay_wsscreen_descr *type = 1151 (struct omdisplay_wsscreen_descr *)_type; 1152 int error; 1153 1154 scr = malloc(sizeof *scr, M_DEVBUF, (cold ? M_NOWAIT : M_WAITOK)); 1155 if (scr == NULL) 1156 return (ENOMEM); 1157 1158 error = omdisplay_new_screen(sc, scr, type->depth); 1159 if (error != 0) { 1160 free(scr, M_DEVBUF, 0); 1161 return (error); 1162 } 1163 1164 /* 1165 * initialize raster operation for this screen. 1166 */ 1167 ri = &scr->rinfo; 1168 ri->ri_hw = (void *)scr; 1169 ri->ri_bits = scr->buf_va; 1170 omdisplay_setup_rasops(sc, ri); 1171 1172 /* assumes 16 bpp */ 1173 ri->ri_ops.pack_attr(ri, 0, 0, 0, attrp); 1174 1175 *cookiep = ri; 1176 *curxp = 0; 1177 *curyp = 0; 1178 1179 return 0; 1180 } 1181 1182 /* 1183 * Create and initialize a new screen buffer. 1184 */ 1185 int 1186 omdisplay_new_screen(struct omdisplay_softc *sc, 1187 struct omdisplay_screen *scr, int depth) 1188 { 1189 bus_space_tag_t iot; 1190 bus_space_handle_t ioh; 1191 bus_dma_tag_t dma_tag; 1192 struct omdisplay_panel_data *geometry; 1193 int width, height; 1194 bus_size_t size; 1195 int error, palette_size; 1196 int busdma_flag = (cold ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK); 1197 1198 if (sc != NULL) { 1199 iot = sc->sc_iot; 1200 ioh = sc->sc_dcioh; 1201 dma_tag = sc->sc_dma_tag; 1202 geometry = sc->sc_geometry; 1203 } else { 1204 /* We are creating the console screen. */ 1205 #if 0 1206 iot = omdisplay_console.iot; 1207 ioh = omdisplay_console.ioh; 1208 dma_tag = omdisplay_console.dma_tag; 1209 geometry = omdisplay_console.geometry; 1210 #endif 1211 } 1212 1213 width = geometry->width; 1214 height = geometry->height; 1215 palette_size = 0; 1216 1217 switch (depth) { 1218 case 1: 1219 case 2: 1220 case 4: 1221 case 8: 1222 palette_size = (1 << depth) * sizeof (uint16_t); 1223 /* FALLTHROUGH */ 1224 case 16: 1225 case 24: 1226 size = geometry->height * geometry->linebytes; 1227 break; 1228 default: 1229 printf("%s: Unknown depth (%d)\n", 1230 sc != NULL ? sc->sc_dev.dv_xname : "console", depth); 1231 return (EINVAL); 1232 } 1233 1234 bzero(scr, sizeof *scr); 1235 1236 scr->nsegs = 0; 1237 scr->depth = depth; 1238 scr->buf_size = size; 1239 scr->buf_va = NULL; 1240 size = roundup(size, 16); 1241 #if 0 1242 + 3 * sizeof (struct lcd_dma_descriptor) 1243 + palette_size; 1244 #endif 1245 1246 error = bus_dmamem_alloc(dma_tag, size, 0x100000, 0, 1247 scr->segs, 1, &(scr->nsegs), busdma_flag); 1248 if (error != 0 || scr->nsegs != 1) { 1249 /* XXX: Actually we can handle nsegs > 1 case by means 1250 of multiple DMA descriptors for a panel. It would 1251 make code here a bit hairy */ 1252 if (error == 0) 1253 error = E2BIG; 1254 goto bad; 1255 } 1256 1257 error = bus_dmamem_map(dma_tag, scr->segs, scr->nsegs, 1258 size, (caddr_t *)&(scr->buf_va), busdma_flag | BUS_DMA_COHERENT); 1259 if (error != 0) 1260 goto bad; 1261 1262 memset(scr->buf_va, 0, scr->buf_size); 1263 bcopy(splash, scr->buf_va, 1264 sizeof (splash) > scr->buf_size ? scr->buf_size : sizeof (splash)); 1265 1266 /* map memory for DMA */ 1267 if (bus_dmamap_create(dma_tag, 1024 * 1024 * 2, 1, 1268 1024 * 1024 * 2, 0, busdma_flag, &scr->dma)) 1269 goto bad; 1270 error = bus_dmamap_load(dma_tag, scr->dma, 1271 scr->buf_va, size, NULL, busdma_flag); 1272 if (error != 0) { 1273 goto bad; 1274 } 1275 1276 scr->map_size = size; /* used when unmap this. */ 1277 1278 if (sc != NULL) { 1279 LIST_INSERT_HEAD(&(sc->sc_screens), scr, link); 1280 sc->sc_nscreens++; 1281 } 1282 1283 omdisplay_initialize(sc, geometry); 1284 1285 return (0); 1286 1287 bad: 1288 if (scr->buf_va) 1289 bus_dmamem_unmap(dma_tag, scr->buf_va, size); 1290 if (scr->nsegs) 1291 bus_dmamem_free(dma_tag, scr->segs, scr->nsegs); 1292 return (error); 1293 } 1294 paddr_t 1295 omdisplay_mmap(void *v, off_t offset, int prot) 1296 { 1297 struct omdisplay_softc *sc = v; 1298 struct omdisplay_screen *screen = sc->sc_active; /* ??? */ 1299 1300 if ((offset & PAGE_MASK) != 0) 1301 return (-1); 1302 1303 if (screen == NULL) 1304 return (-1); 1305 1306 if (offset < 0 || 1307 offset >= screen->rinfo.ri_stride * screen->rinfo.ri_height) 1308 return (-1); 1309 1310 return (bus_dmamem_mmap(sc->sc_dma_tag, screen->segs, screen->nsegs, 1311 offset, prot, BUS_DMA_WAITOK | BUS_DMA_COHERENT)); 1312 } 1313 1314 void 1315 omdisplay_free_screen(void *v, void *cookie) 1316 { 1317 struct omdisplay_softc *sc = v; 1318 struct rasops_info *ri = cookie; 1319 struct omdisplay_screen *scr = ri->ri_hw; 1320 1321 LIST_REMOVE(scr, link); 1322 sc->sc_nscreens--; 1323 if (scr == sc->sc_active) { 1324 /* at first, we need to stop LCD DMA */ 1325 sc->sc_active = NULL; 1326 1327 #ifdef DEBUG 1328 printf("lcd_free on active screen\n"); 1329 #endif 1330 1331 omdisplay_stop(sc); 1332 } 1333 1334 if (scr->buf_va) 1335 bus_dmamem_unmap(sc->sc_dma_tag, scr->buf_va, scr->map_size); 1336 1337 if (scr->nsegs > 0) 1338 bus_dmamem_free(sc->sc_dma_tag, scr->segs, scr->nsegs); 1339 1340 free(scr, M_DEVBUF, 0); 1341 } 1342 1343 int 1344 omdisplay_load_font(void *v, void *emulcookie, struct wsdisplay_font *font) 1345 { 1346 struct omdisplay_softc *sc = v; 1347 struct omdisplay_screen *scr = sc->sc_active; 1348 1349 if (scr == NULL) 1350 return ENXIO; 1351 1352 return rasops_load_font(scr->rinfo, emulcookie, font); 1353 } 1354 1355 int 1356 omdisplay_list_font(void *v, struct wsdisplay_font *font) 1357 { 1358 struct omdisplay_softc *sc = v; 1359 struct omdisplay_screen *scr = sc->sc_active; 1360 1361 if (scr == NULL) 1362 return ENXIO; 1363 1364 return rasops_list_font(scr->rinfo, font); 1365 } 1366 1367 void 1368 omdisplay_start(struct omdisplay_softc *sc) 1369 { 1370 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_CONTROL, 1371 DISPC_CONTROL_GPOUT0 | DISPC_CONTROL_GPOUT1 | 1372 DISPC_CONTROL_TFTDATALINES_18 /*XXX 18? */ | 1373 DISPC_CONTROL_STNTFT | 1374 DISPC_CONTROL_GOLCD | 1375 DISPC_CONTROL_LCDENABLE); 1376 } 1377 1378 void 1379 omdisplay_stop(struct omdisplay_softc *sc) 1380 { 1381 bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_CONTROL, 1382 bus_space_read_4(sc->sc_iot, sc->sc_dcioh, DISPC_CONTROL) & 1383 ~(DISPC_CONTROL_DIGITALENABLE|DISPC_CONTROL_LCDENABLE)); 1384 1385 /* XXX - wait for end of frame? */ 1386 } 1387 1388 int 1389 omdisplay_intr(void *v) 1390 { 1391 /* XXX */ 1392 return 1; 1393 } 1394 1395