|
|
1.1.1.2 ! root 1: /* $Id: sun-fb.c,v 1.4 2007/03/29 01:56:40 fredette Exp $ */ 1.1 root 2: 3: /* machine/sun/sun-fb.c - Sun framebuffer emulation support: */ 4: 5: /* 1.1.1.2 ! root 6: * Copyright (c) 2004, 2006 Matt Fredette 1.1 root 7: * All rights reserved. 8: * 9: * Redistribution and use in source and binary forms, with or without 10: * modification, are permitted provided that the following conditions 11: * are met: 12: * 1. Redistributions of source code must retain the above copyright 13: * notice, this list of conditions and the following disclaimer. 14: * 2. Redistributions in binary form must reproduce the above copyright 15: * notice, this list of conditions and the following disclaimer in the 16: * documentation and/or other materials provided with the distribution. 17: * 3. All advertising materials mentioning features or use of this software 18: * must display the following acknowledgement: 19: * This product includes software developed by Matt Fredette. 20: * 4. The name of the author may not be used to endorse or promote products 21: * derived from this software without specific prior written permission. 22: * 23: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 24: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 25: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 26: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 27: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 28: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 29: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 31: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 32: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33: * POSSIBILITY OF SUCH DAMAGE. 34: */ 35: 36: #include <tme/common.h> 1.1.1.2 ! root 37: _TME_RCSID("$Id: sun-fb.c,v 1.4 2007/03/29 01:56:40 fredette Exp $"); 1.1 root 38: 39: /* includes: */ 40: #include "sun-fb.h" 41: 1.1.1.2 ! root 42: /* macros: */ ! 43: ! 44: /* P4 register framebuffer sizes: */ ! 45: #define TME_SUNFB_P4_SIZE_MASK (0x0f000000) ! 46: #define TME_SUNFB_P4_SIZE_1600_1280 (0x00000000) ! 47: #define TME_SUNFB_P4_SIZE_1152_900 (0x01000000) ! 48: #define TME_SUNFB_P4_SIZE_1024_1024 (0x02000000) ! 49: #define TME_SUNFB_P4_SIZE_1280_1024 (0x03000000) ! 50: #define TME_SUNFB_P4_SIZE_1440_1440 (0x04000000) ! 51: #define TME_SUNFB_P4_SIZE_640_480 (0x05000000) ! 52: ! 53: /* P4 register bits: */ ! 54: /* 0x00000080 is the diagnostic bit (?) */ ! 55: /* 0x00000040 is the readback bit (?) */ ! 56: #define TME_SUNFB_P4_REG_VIDEO_ENABLE (0x00000020) ! 57: #define TME_SUNFB_P4_REG_SYNC_RAMDAC (0x00000010) ! 58: #define TME_SUNFB_P4_REG_IN_VTRACE (0x00000008) ! 59: #define TME_SUNFB_P4_REG_INT_ACTIVE (0x00000004) ! 60: #define TME_SUNFB_P4_REG_INT_RESET (0x00000004) ! 61: #define TME_SUNFB_P4_REG_ENABLE_INT (0x00000002) ! 62: #define TME_SUNFB_P4_REG_IN_VTRACE_1H (0x00000001) ! 63: #define TME_SUNFB_P4_REG_RESET (0x00000001) ! 64: ! 65: /* P4 register read-only bits: */ ! 66: #define TME_SUNFB_P4_RO_MASK (TME_SUNFB_P4_ID_MASK \ ! 67: | TME_SUNFB_P4_SIZE_MASK \ ! 68: | TME_SUNFB_P4_REG_IN_VTRACE \ ! 69: | TME_SUNFB_P4_REG_INT_ACTIVE \ ! 70: | TME_SUNFB_P4_REG_IN_VTRACE_1H) ! 71: ! 72: /* S4 register offsets: */ ! 73: #define TME_SUNFB_S4_REG_BT458_ADDRESS (0) ! 74: #define TME_SUNFB_S4_REG_BT458_CMAP (4) ! 75: #define TME_SUNFB_S4_REG_BT458_CONTROL (8) ! 76: #define TME_SUNFB_S4_REG_BT458_OMAP (12) ! 77: #define TME_SUNFB_S4_SIZ_BT458 (16) ! 78: #define TME_SUNFB_S4_SIZ_REGS (32) ! 79: #define TME_SUNFB_S4_REG(x) \ ! 80: (TME_SUNFB_S4_SIZ_BT458 \ ! 81: + (&((struct tme_sunfb *) 0)->tme_sunfb_s4_regs.x \ ! 82: - &((struct tme_sunfb *) 0)->tme_sunfb_s4_regs.tme_sunfb_s4_regs_first)) ! 83: ! 84: /* S4 control register bits: */ ! 85: #define TME_SUNFB_S4_CONTROL_INT_ENABLE (0x80) ! 86: #define TME_SUNFB_S4_CONTROL_VIDEO_ENABLE (0x40) ! 87: ! 88: /* S4 status register bits: */ ! 89: #define TME_SUNFB_S4_STATUS_INT_PENDING (0x80) ! 90: #define TME_SUNFB_S4_STATUS_SIZE_MASK (0x70) ! 91: #define TME_SUNFB_S4_STATUS_SIZE_1024_768 (0x10) ! 92: #define TME_SUNFB_S4_STATUS_SIZE_1152_900 (0x30) ! 93: #define TME_SUNFB_S4_STATUS_SIZE_1280_1024 (0x40) ! 94: #define TME_SUNFB_S4_STATUS_SIZE_1600_1280 (0x50) ! 95: #define TME_SUNFB_S4_STATUS_ID_MASK (0x0f) ! 96: #define TME_SUNFB_S4_STATUS_ID_COLOR (0x01) ! 97: #define TME_SUNFB_S4_STATUS_ID_MONO (0x02) ! 98: #define TME_SUNFB_S4_STATUS_ID_MONO_ECL (0x03) ! 99: ! 100: /* these evaluate to nonzero for different kinds of framebuffers: */ ! 101: #define _TME_SUNFB_IS_BWTWO(sunfb) ((sunfb)->tme_sunfb_class == TME_FB_XLAT_CLASS_MONOCHROME) ! 102: #define _TME_SUNFB_IS_P4(sunfb) ((sunfb)->tme_sunfb_bus_handler_regs == tme_sunfb_bus_cycle_p4) ! 103: #define _TME_SUNFB_IS_S4(sunfb) ((sunfb)->tme_sunfb_bus_handler_regs == tme_sunfb_bus_cycle_s4) ! 104: #define _TME_SUNFB_HAS_BT458(sunfb) ((sunfb)->tme_sunfb_depth == 8) ! 105: ! 106: #if 0 ! 107: #define TME_SUNFB_DEBUG ! 108: #endif ! 109: ! 110: /* this returns the sunfb size value for the given resolution: */ ! 111: tme_uint32_t ! 112: tme_sunfb_size(const char *size) 1.1 root 113: { 114: if (TME_ARG_IS(size, "1600x1280")) { 1.1.1.2 ! root 115: return (TME_SUNFB_SIZE_1600_1280); 1.1 root 116: } 117: else if (TME_ARG_IS(size, "1152x900")) { 1.1.1.2 ! root 118: return (TME_SUNFB_SIZE_1152_900); 1.1 root 119: } 120: else if (TME_ARG_IS(size, "1024x1024")) { 1.1.1.2 ! root 121: return (TME_SUNFB_SIZE_1024_1024); 1.1 root 122: } 123: else if (TME_ARG_IS(size, "1280x1024")) { 1.1.1.2 ! root 124: return (TME_SUNFB_SIZE_1280_1024); 1.1 root 125: } 126: else if (TME_ARG_IS(size, "1440x1440")) { 1.1.1.2 ! root 127: return (TME_SUNFB_SIZE_1440_1440); 1.1 root 128: } 129: else if (TME_ARG_IS(size, "640x480")) { 1.1.1.2 ! root 130: return (TME_SUNFB_SIZE_640_480); ! 131: } ! 132: else if (TME_ARG_IS(size, "1024x768")) { ! 133: return (TME_SUNFB_SIZE_1024_768); 1.1 root 134: } 1.1.1.2 ! root 135: return (TME_SUNFB_SIZE_NULL); 1.1 root 136: } 137: 1.1.1.2 ! root 138: /* this returns the width for the given sunfb size: */ 1.1 root 139: tme_uint32_t 1.1.1.2 ! root 140: tme_sunfb_size_width(tme_uint32_t sunfb_size) 1.1 root 141: { 1.1.1.2 ! root 142: switch (sunfb_size) { ! 143: default: assert(FALSE); ! 144: case TME_SUNFB_SIZE_640_480: return (640); ! 145: case TME_SUNFB_SIZE_1024_768: /* FALLTHROUGH */ ! 146: case TME_SUNFB_SIZE_1024_1024: return (1024); ! 147: case TME_SUNFB_SIZE_1152_900: return (1152); ! 148: case TME_SUNFB_SIZE_1280_1024: return (1280); ! 149: case TME_SUNFB_SIZE_1600_1280: return (1600); ! 150: case TME_SUNFB_SIZE_1440_1440: return (1440); 1.1 root 151: } 152: } 153: 1.1.1.2 ! root 154: /* this returns the height for the given sunfb size: */ 1.1 root 155: tme_uint32_t 1.1.1.2 ! root 156: tme_sunfb_size_height(tme_uint32_t sunfb_size) ! 157: { ! 158: switch (sunfb_size) { ! 159: default: assert(FALSE); ! 160: case TME_SUNFB_SIZE_640_480: return (480); ! 161: case TME_SUNFB_SIZE_1024_768: return (768); ! 162: case TME_SUNFB_SIZE_1152_900: return (900); ! 163: case TME_SUNFB_SIZE_1024_1024: /* FALLTHROUGH */ ! 164: case TME_SUNFB_SIZE_1280_1024: return (1024); ! 165: case TME_SUNFB_SIZE_1600_1280: return (1280); ! 166: case TME_SUNFB_SIZE_1440_1440: return (1440); ! 167: } ! 168: } ! 169: ! 170: /* XXX FIXME - this should be in a tme/ic/bt458.c: */ ! 171: /* this determines the closest regular colormap indices for the ! 172: overlay map: */ ! 173: int ! 174: tme_bt458_omap_best(struct tme_bt458 *bt458) ! 175: { ! 176: unsigned int omap_i; ! 177: unsigned int cmap_i; ! 178: tme_int32_t score; ! 179: unsigned int cmap_i_best; ! 180: tme_int32_t score_best; ! 181: tme_int32_t score_part; ! 182: int changed; ! 183: ! 184: /* loop over the overlay map indices: */ ! 185: changed = FALSE; ! 186: for (omap_i = 0; ! 187: omap_i < TME_ARRAY_ELS(bt458->tme_bt458_omap_primaries[0]); ! 188: omap_i++) { ! 189: ! 190: /* silence gcc -Wuninitialized: */ ! 191: cmap_i_best = 0; ! 192: ! 193: /* loop over the regular colormap indices: */ ! 194: score_best = (256 * 256 * 256); ! 195: for (cmap_i = 0; ! 196: cmap_i < 256; ! 197: cmap_i++) { ! 198: ! 199: /* score this colormap entry, by taking the product of the ! 200: distances between this colormap entry's primaries and this ! 201: overlay map entry's primaries: */ ! 202: score = bt458->tme_bt458_omap_r[omap_i]; ! 203: score -= (bt458->tme_bt458_cmap_r)[cmap_i]; ! 204: score_part = bt458->tme_bt458_omap_g[omap_i]; ! 205: score_part -= (bt458->tme_bt458_cmap_g)[cmap_i]; ! 206: score *= score_part; ! 207: score_part = bt458->tme_bt458_omap_b[omap_i]; ! 208: score_part -= (bt458->tme_bt458_cmap_b)[cmap_i]; ! 209: score *= score_part; ! 210: if (score < 0) { ! 211: score = -score; ! 212: } ! 213: ! 214: /* update the best colormap entry: */ ! 215: if (score < score_best) { ! 216: score_best = score; ! 217: cmap_i_best = cmap_i; ! 218: } ! 219: } ! 220: ! 221: /* save the closest index: */ ! 222: changed |= bt458->tme_bt458_omap_cmap_indices[omap_i] - cmap_i_best; ! 223: bt458->tme_bt458_omap_cmap_indices[omap_i] = cmap_i_best; ! 224: } ! 225: ! 226: return (changed); ! 227: } ! 228: ! 229: /* this handles a mode change callout: */ ! 230: static int ! 231: _tme_sunfb_mode_change(struct tme_sunfb *sunfb) ! 232: { ! 233: struct tme_fb_connection *conn_fb_other; ! 234: struct tme_fb_connection *conn_fb; ! 235: int rc; ! 236: ! 237: /* if this framebuffer has a Bt458: */ ! 238: if (_TME_SUNFB_HAS_BT458(sunfb)) { ! 239: ! 240: /* update the best regular colormap indices for the colors in the ! 241: overlay map. if any of them have changed, we may have do to a ! 242: full update: */ ! 243: if (tme_bt458_omap_best(&sunfb->tme_sunfb_bt458)) { ! 244: ! 245: /* if this framebuffer has an update-full function, call it: */ ! 246: if (sunfb->tme_sunfb_update_full != NULL) { ! 247: (*sunfb->tme_sunfb_update_full)(sunfb); ! 248: } ! 249: } ! 250: } ! 251: ! 252: /* get both sides of the framebuffer connection: */ ! 253: conn_fb_other = sunfb->tme_sunfb_fb_connection; ! 254: conn_fb = (struct tme_fb_connection *) conn_fb_other->tme_fb_connection.tme_connection_other; ! 255: ! 256: /* unlock the mutex: */ ! 257: tme_mutex_unlock(&sunfb->tme_sunfb_mutex); ! 258: ! 259: /* do the callout: */ ! 260: rc = (conn_fb_other != NULL ! 261: ? ((*conn_fb_other->tme_fb_connection_mode_change) ! 262: (conn_fb_other)) ! 263: : TME_OK); ! 264: ! 265: /* lock the mutex: */ ! 266: tme_mutex_lock(&sunfb->tme_sunfb_mutex); ! 267: ! 268: return (rc); ! 269: } ! 270: ! 271: /* the sunfb callout function. it must be called with the mutex locked: */ ! 272: static void ! 273: _tme_sunfb_callout(struct tme_sunfb *sunfb) ! 274: { ! 275: struct tme_bus_connection *conn_bus; ! 276: int int_asserted; ! 277: int callouts_blocked; ! 278: int rc; ! 279: ! 280: /* if this function is already running in another thread, simply ! 281: return now. the other thread will do our work: */ ! 282: if (sunfb->tme_sunfb_callout_flags ! 283: & TME_SUNFB_CALLOUT_RUNNING) { ! 284: return; ! 285: } ! 286: ! 287: /* callouts are now running: */ ! 288: sunfb->tme_sunfb_callout_flags ! 289: |= TME_SUNFB_CALLOUT_RUNNING; ! 290: ! 291: /* initially, no callouts are blocked: */ ! 292: callouts_blocked = 0; ! 293: ! 294: /* loop forever: */ ! 295: for (;;) { ! 296: ! 297: /* any callout, successful or not, will clear this bit. if we get ! 298: to the bottom of the loop and this bit is still set, there are ! 299: no more (unblocked) callouts to make, so we can stop: */ ! 300: callouts_blocked |= TME_SUNFB_CALLOUT_RUNNING; ! 301: ! 302: /* we always clear the interrupt callout flag, because we only ! 303: need it to get callouts to run at all: */ ! 304: sunfb->tme_sunfb_callout_flags &= ~TME_SUNFB_CALLOUT_INT; ! 305: ! 306: /* if our interrupt signal has changed, and this callout isn't ! 307: blocked: */ ! 308: int_asserted ! 309: = (_TME_SUNFB_IS_S4(sunfb) ! 310: ? ((sunfb->tme_sunfb_s4_regs.tme_sunfb_s4_regs_control ! 311: & TME_SUNFB_S4_CONTROL_INT_ENABLE) ! 312: && (sunfb->tme_sunfb_s4_regs.tme_sunfb_s4_regs_status ! 313: & TME_SUNFB_S4_STATUS_INT_PENDING)) ! 314: : FALSE); ! 315: if ((!int_asserted != !sunfb->tme_sunfb_int_asserted) ! 316: && (callouts_blocked & TME_SUNFB_CALLOUT_INT) == 0) { ! 317: ! 318: /* get our bus connection: */ ! 319: conn_bus = tme_memory_atomic_pointer_read(struct tme_bus_connection *, ! 320: sunfb->tme_sunfb_device.tme_bus_device_connection, ! 321: &sunfb->tme_sunfb_device.tme_bus_device_connection_rwlock); ! 322: ! 323: /* unlock our mutex: */ ! 324: tme_mutex_unlock(&sunfb->tme_sunfb_mutex); ! 325: ! 326: /* call out the bus interrupt signal edge: */ ! 327: rc = (*conn_bus->tme_bus_signal) ! 328: (conn_bus, ! 329: TME_BUS_SIGNAL_INT_UNSPEC ! 330: | (int_asserted ! 331: ? TME_BUS_SIGNAL_LEVEL_ASSERTED ! 332: : TME_BUS_SIGNAL_LEVEL_NEGATED)); ! 333: ! 334: /* lock our mutex: */ ! 335: tme_mutex_lock(&sunfb->tme_sunfb_mutex); ! 336: ! 337: /* unblock all callouts: */ ! 338: callouts_blocked = 0; ! 339: ! 340: /* if this callout failed: */ ! 341: if (rc != TME_OK) { ! 342: ! 343: /* reschedule this callout but block it until some other ! 344: callout succeeds: */ ! 345: sunfb->tme_sunfb_callout_flags |= TME_SUNFB_CALLOUT_INT; ! 346: callouts_blocked |= TME_SUNFB_CALLOUT_INT; ! 347: continue; ! 348: } ! 349: ! 350: /* note the new state of the interrupt signal: */ ! 351: sunfb->tme_sunfb_int_asserted = int_asserted; ! 352: } ! 353: ! 354: /* if we need to call out a mode change, and this callout isn't ! 355: blocked: */ ! 356: if ((sunfb->tme_sunfb_callout_flags & TME_SUNFB_CALLOUT_MODE_CHANGE) ! 357: && (callouts_blocked & TME_SUNFB_CALLOUT_MODE_CHANGE) == 0) { ! 358: ! 359: /* clear this callout: */ ! 360: sunfb->tme_sunfb_callout_flags &= ~TME_SUNFB_CALLOUT_MODE_CHANGE; ! 361: ! 362: /* call out the mode change: */ ! 363: rc = _tme_sunfb_mode_change(sunfb); ! 364: ! 365: /* unblock all callouts: */ ! 366: callouts_blocked = 0; ! 367: ! 368: /* if the callout failed: */ ! 369: if (rc != TME_OK) { ! 370: ! 371: /* reschedule this callout but block it until some other ! 372: callout succeeds: */ ! 373: sunfb->tme_sunfb_callout_flags |= TME_SUNFB_CALLOUT_MODE_CHANGE; ! 374: callouts_blocked |= TME_SUNFB_CALLOUT_MODE_CHANGE; ! 375: continue; ! 376: } ! 377: } ! 378: ! 379: /* if no more (unblocked) callouts can run, we can stop: */ ! 380: if (callouts_blocked & TME_SUNFB_CALLOUT_RUNNING) { ! 381: break; ! 382: } ! 383: } ! 384: ! 385: /* clear that callouts are running: */ ! 386: sunfb->tme_sunfb_callout_flags &= ~TME_SUNFB_CALLOUT_RUNNING; ! 387: } ! 388: ! 389: /* the callout thread: */ ! 390: static void ! 391: _tme_sunfb_callout_thread(void *_sunfb) ! 392: { ! 393: struct tme_sunfb *sunfb; ! 394: ! 395: /* recover our data structure: */ ! 396: sunfb = _sunfb; ! 397: ! 398: /* lock the mutex: */ ! 399: tme_mutex_lock(&sunfb->tme_sunfb_mutex); ! 400: ! 401: /* loop forever: */ ! 402: for (;;) { ! 403: ! 404: /* make any callouts: */ ! 405: _tme_sunfb_callout(sunfb); ! 406: ! 407: /* wait on the condition: */ ! 408: tme_cond_wait_yield(&sunfb->tme_sunfb_callout_cond, ! 409: &sunfb->tme_sunfb_mutex); ! 410: } ! 411: /* NOTREACHED */ ! 412: } ! 413: ! 414: /* this is called before the framebuffer's display is updated: */ ! 415: int ! 416: tme_sunfb_memory_update(struct tme_fb_connection *conn_fb) ! 417: { ! 418: struct tme_sunfb *sunfb; ! 419: int int_asserted; ! 420: ! 421: /* recover our data structure: */ ! 422: sunfb = conn_fb->tme_fb_connection.tme_connection_element->tme_element_private; ! 423: ! 424: /* lock the mutex: */ ! 425: tme_mutex_lock(&sunfb->tme_sunfb_mutex); ! 426: ! 427: /* if this framebuffer supports interrupts, one is now pending. the ! 428: interrupt should also be asserted if it's enabled: */ ! 429: if (_TME_SUNFB_IS_S4(sunfb)) { ! 430: sunfb->tme_sunfb_s4_regs.tme_sunfb_s4_regs_status ! 431: |= TME_SUNFB_S4_STATUS_INT_PENDING; ! 432: int_asserted ! 433: = ((sunfb->tme_sunfb_s4_regs.tme_sunfb_s4_regs_control ! 434: & TME_SUNFB_S4_CONTROL_INT_ENABLE) != 0); ! 435: } ! 436: else { ! 437: int_asserted = FALSE; ! 438: } ! 439: ! 440: /* if this interrupt should be asserted and it isn't already, or if ! 441: we have other callouts to make, notify the callout thread: */ ! 442: if ((int_asserted && !sunfb->tme_sunfb_int_asserted) ! 443: || (sunfb->tme_sunfb_callout_flags & TME_SUNFB_CALLOUTS_MASK) != 0) { ! 444: tme_cond_notify(&sunfb->tme_sunfb_callout_cond, FALSE); ! 445: } ! 446: ! 447: /* unlock the mutex: */ ! 448: tme_mutex_unlock(&sunfb->tme_sunfb_mutex); ! 449: ! 450: return (TME_OK); ! 451: } ! 452: ! 453: /* the sunfb memory bus cycle handler: */ ! 454: static int ! 455: _tme_sunfb_bus_cycle_memory(void *_sunfb, struct tme_bus_cycle *cycle_init) ! 456: { ! 457: struct tme_sunfb *sunfb; ! 458: ! 459: /* recover our data structure: */ ! 460: sunfb = (struct tme_sunfb *) _sunfb; ! 461: ! 462: /* lock the mutex: */ ! 463: tme_mutex_lock(&sunfb->tme_sunfb_mutex); ! 464: ! 465: /* run the cycle: */ ! 466: assert (cycle_init->tme_bus_cycle_address ! 467: >= sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_first); ! 468: tme_bus_cycle_xfer_memory(cycle_init, ! 469: (sunfb->tme_sunfb_memory ! 470: - sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_first), ! 471: sunfb->tme_sunfb_memory_address_last_displayed); ! 472: ! 473: /* unlock the mutex: */ ! 474: tme_mutex_unlock(&sunfb->tme_sunfb_mutex); ! 475: ! 476: /* no faults: */ ! 477: return (TME_OK); ! 478: } ! 479: ! 480: /* the sunfb memory pad bus cycle handler: */ ! 481: static int ! 482: _tme_sunfb_bus_cycle_memory_pad(void *_sunfb, struct tme_bus_cycle *cycle_init) ! 483: { ! 484: struct tme_sunfb *sunfb; ! 485: ! 486: /* recover our data structure: */ ! 487: sunfb = (struct tme_sunfb *) _sunfb; ! 488: ! 489: /* lock the mutex: */ ! 490: tme_mutex_lock(&sunfb->tme_sunfb_mutex); ! 491: ! 492: /* run the cycle: */ ! 493: assert (cycle_init->tme_bus_cycle_address ! 494: > sunfb->tme_sunfb_memory_address_last_displayed); ! 495: tme_bus_cycle_xfer_memory(cycle_init, ! 496: (sunfb->tme_sunfb_memory_pad ! 497: - (sunfb->tme_sunfb_memory_address_last_displayed ! 498: + 1)), ! 499: sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_last); ! 500: ! 501: /* unlock the mutex: */ ! 502: tme_mutex_unlock(&sunfb->tme_sunfb_mutex); ! 503: ! 504: /* no faults: */ ! 505: return (TME_OK); ! 506: } ! 507: ! 508: /* the sunfb P4 bus cycle handler: */ ! 509: int ! 510: tme_sunfb_bus_cycle_p4(void *_sunfb, struct tme_bus_cycle *cycle_init) ! 511: { ! 512: struct tme_sunfb *sunfb; ! 513: tme_uint32_t p4_old, p4_new; ! 514: tme_bus_addr_t undecoded; ! 515: ! 516: /* recover our data structure: */ ! 517: sunfb = (struct tme_sunfb *) _sunfb; ! 518: ! 519: /* lock the mutex: */ ! 520: tme_mutex_lock(&sunfb->tme_sunfb_mutex); ! 521: ! 522: /* get the old P4 value: */ ! 523: p4_old = tme_betoh_u32(sunfb->tme_sunfb_p4); ! 524: ! 525: /* the entire register bus subregion is all decoded (or, rather, not ! 526: decoded) as the P4: */ ! 527: undecoded ! 528: = (cycle_init->tme_bus_cycle_address ! 529: & (sunfb->tme_sunfb_bus_subregion_regs.tme_bus_subregion_address_last ! 530: - sunfb->tme_sunfb_bus_subregion_regs.tme_bus_subregion_address_first ! 531: - sizeof(sunfb->tme_sunfb_p4))); ! 532: cycle_init->tme_bus_cycle_address ! 533: -= undecoded; ! 534: ! 535: /* run the cycle: */ ! 536: assert (cycle_init->tme_bus_cycle_address ! 537: >= sunfb->tme_sunfb_bus_subregion_regs.tme_bus_subregion_address_first); ! 538: tme_bus_cycle_xfer_memory(cycle_init, ! 539: (((tme_uint8_t *) &sunfb->tme_sunfb_p4) ! 540: - sunfb->tme_sunfb_bus_subregion_regs.tme_bus_subregion_address_first), ! 541: (sunfb->tme_sunfb_bus_subregion_regs.tme_bus_subregion_address_first ! 542: + sizeof(sunfb->tme_sunfb_p4) ! 543: - 1)); ! 544: cycle_init->tme_bus_cycle_address ! 545: += undecoded; ! 546: ! 547: /* get the new P4 value: */ ! 548: p4_new = tme_betoh_u32(sunfb->tme_sunfb_p4); ! 549: ! 550: /* put back the unchanging bits: */ ! 551: p4_new ! 552: = ((p4_new ! 553: & ~TME_SUNFB_P4_RO_MASK) ! 554: | (p4_old ! 555: & TME_SUNFB_P4_RO_MASK)); ! 556: ! 557: /* we do not support these bits: */ ! 558: if (p4_new ! 559: & (TME_SUNFB_P4_REG_SYNC_RAMDAC ! 560: | TME_SUNFB_P4_REG_ENABLE_INT)) { ! 561: abort(); ! 562: } ! 563: ! 564: /* set the new P4 value: */ ! 565: sunfb->tme_sunfb_p4 = tme_htobe_u32(p4_new); ! 566: ! 567: /* unlock the mutex: */ ! 568: tme_mutex_unlock(&sunfb->tme_sunfb_mutex); ! 569: ! 570: /* no faults: */ ! 571: return (TME_OK); ! 572: } ! 573: ! 574: /* the Brooktree BT458 bus cycle handler: */ ! 575: int ! 576: tme_sunfb_bus_cycle_bt458(void *_sunfb, struct tme_bus_cycle *cycle_init) ! 577: { ! 578: struct tme_sunfb *sunfb; ! 579: struct tme_bt458 *bt458; ! 580: unsigned int reg; ! 581: tme_uint32_t value_packed; ! 582: tme_uint8_t value; ! 583: unsigned int byte_count; ! 584: unsigned int bt458_address; ! 585: unsigned int bt458_rgb; ! 586: unsigned int map_count; ! 587: ! 588: /* recover our data structure: */ ! 589: sunfb = (struct tme_sunfb *) _sunfb; ! 590: ! 591: /* we only emulate 8-bit and aligned 32-bit accesses: */ ! 592: reg = cycle_init->tme_bus_cycle_address % TME_SUNFB_S4_SIZ_BT458; ! 593: if (cycle_init->tme_bus_cycle_size != sizeof(tme_uint8_t) ! 594: && (cycle_init->tme_bus_cycle_size != sizeof(tme_uint32_t) ! 595: || (reg % sizeof(tme_uint32_t)) != 0)) { ! 596: abort(); ! 597: } ! 598: reg &= (TME_SUNFB_S4_SIZ_BT458 - sizeof(tme_uint32_t)); ! 599: ! 600: /* lock the mutex: */ ! 601: tme_mutex_lock(&sunfb->tme_sunfb_mutex); ! 602: ! 603: /* get the Bt458 address registers: */ ! 604: bt458 = &sunfb->tme_sunfb_bt458; ! 605: bt458_address = bt458->tme_bt458_address; ! 606: bt458_rgb = bt458->tme_bt458_rgb; ! 607: ! 608: /* set the number of colormap values per read and write: */ ! 609: map_count = ((sunfb->tme_sunfb_flags & TME_SUNFB_FLAG_BT458_CMAP_PACKED) ! 610: ? cycle_init->tme_bus_cycle_size ! 611: : sizeof(tme_uint8_t)); ! 612: ! 613: /* if this is a write: */ ! 614: if (cycle_init->tme_bus_cycle_type == TME_BUS_CYCLE_WRITE) { ! 615: ! 616: /* run the bus cycle: */ ! 617: if (cycle_init->tme_bus_cycle_size == sizeof(tme_uint32_t)) { ! 618: tme_bus_cycle_xfer_reg(cycle_init, ! 619: &value_packed, ! 620: TME_BUS32_LOG2); ! 621: ! 622: /* for a 32-bit write to an 8-bit register, a framebuffer either ! 623: uses byte lane D24..D31 or byte lane D0..D7: */ ! 624: value ! 625: = (value_packed ! 626: >> (((sunfb->tme_sunfb_flags ! 627: & (TME_SUNFB_FLAG_BT458_BYTE_D0_D7 ! 628: | TME_SUNFB_FLAG_BT458_BYTE_D24_D31)) ! 629: == TME_SUNFB_FLAG_BT458_BYTE_D24_D31) ! 630: ? 24 ! 631: : 0)); ! 632: } ! 633: else { ! 634: tme_bus_cycle_xfer_reg(cycle_init, ! 635: &value, ! 636: TME_BUS8_LOG2); ! 637: value_packed = value; ! 638: value_packed <<= 24; ! 639: } ! 640: ! 641: /* if this is a write to the address register: */ ! 642: if (reg == TME_SUNFB_S4_REG_BT458_ADDRESS) { ! 643: ! 644: /* set the Bt458 address register: */ ! 645: bt458_address = value; ! 646: } ! 647: ! 648: /* if this is a write to the colormap register: */ ! 649: else if (reg == TME_SUNFB_S4_REG_BT458_CMAP) { ! 650: ! 651: /* write the colormap: */ ! 652: do { ! 653: ! 654: /* write one colormap primary: */ ! 655: (bt458->tme_bt458_cmap_primaries[bt458_rgb])[bt458_address] = value_packed >> 24; ! 656: ! 657: /* advance the packed value: */ ! 658: value_packed <<= 8; ! 659: ! 660: /* advance the Bt458 address registers: */ ! 661: bt458_rgb++; ! 662: if (bt458_rgb == TME_ARRAY_ELS(bt458->tme_bt458_cmap_primaries)) { ! 663: bt458_address++; ! 664: bt458_rgb = 0; ! 665: } ! 666: } while (--map_count > 0); ! 667: ! 668: /* calling out a mode change on every colormap register write is ! 669: expensive and unnecessary. instead, arrange for the update ! 670: function to eventually cause a mode change: */ ! 671: sunfb->tme_sunfb_callout_flags |= TME_SUNFB_CALLOUT_MODE_CHANGE; ! 672: } ! 673: ! 674: /* if this is a write to the control register: */ ! 675: else if (reg == TME_SUNFB_S4_REG_BT458_CONTROL) { ! 676: ! 677: /* dispatch on the address: */ ! 678: switch (bt458_address) { ! 679: ! 680: /* the read mask register: */ ! 681: case TME_BT458_REG_CONTROL_MASK_READ: ! 682: /* all planes must be on: */ ! 683: if (value != 0xff) { ! 684: abort(); ! 685: } ! 686: break; ! 687: ! 688: /* the blink mask register: */ ! 689: case TME_BT458_REG_CONTROL_MASK_BLINK: ! 690: /* no planes must be blinking: */ ! 691: if (value != 0x00) { ! 692: abort(); ! 693: } ! 694: break; ! 695: ! 696: /* the command register: */ ! 697: case TME_BT458_REG_CONTROL_COMMAND: ! 698: ! 699: /* XXX FIXME - we should validate values written to the ! 700: command register: */ ! 701: break; ! 702: ! 703: /* the test register: */ ! 704: case TME_BT458_REG_CONTROL_TEST: ! 705: break; ! 706: ! 707: default: ! 708: abort(); ! 709: } ! 710: ! 711: /* write this register: */ ! 712: bt458->tme_bt458_regs[bt458_address - TME_BT458_REG_CONTROL_FIRST] = value; ! 713: } ! 714: ! 715: /* this must be a write to the overlay map register: */ ! 716: else { ! 717: assert (reg == TME_SUNFB_S4_REG_BT458_OMAP); ! 718: ! 719: /* write the overlay map: */ ! 720: do { ! 721: ! 722: /* if the Bt458 address isn't in the overlay map: */ ! 723: if (bt458_address >= 4) { ! 724: abort(); ! 725: } ! 726: ! 727: /* write one overlay map primary: */ ! 728: bt458->tme_bt458_omap_primaries[bt458_rgb][bt458_address] = value_packed >> 24; ! 729: ! 730: /* advance the packed value: */ ! 731: value_packed <<= 8; ! 732: ! 733: /* advance the Bt458 address registers: */ ! 734: bt458_rgb++; ! 735: if (bt458_rgb == TME_ARRAY_ELS(bt458->tme_bt458_omap_primaries)) { ! 736: bt458_address++; ! 737: bt458_rgb = 0; ! 738: } ! 739: } while (--map_count > 0); ! 740: ! 741: /* calling out a mode change on every overlap map register write ! 742: is expensive and unnecessary. instead, arrange for the ! 743: update function to eventually cause a mode change: */ ! 744: sunfb->tme_sunfb_callout_flags |= TME_SUNFB_CALLOUT_MODE_CHANGE; ! 745: } ! 746: } ! 747: ! 748: /* otherwise, this is a read: */ ! 749: else { ! 750: assert (cycle_init->tme_bus_cycle_type == TME_BUS_CYCLE_READ); ! 751: ! 752: /* zero the value read: */ ! 753: value_packed = 0; ! 754: ! 755: /* assume only one byte will be read: */ ! 756: byte_count = sizeof(tme_uint8_t); ! 757: ! 758: /* if this is a read of the address register: */ ! 759: if (reg == TME_SUNFB_S4_REG_BT458_ADDRESS) { ! 760: ! 761: /* read the Bt458 address register: */ ! 762: value_packed = bt458_address; ! 763: } ! 764: ! 765: /* if this is a read to the colormap register: */ ! 766: else if (reg == TME_SUNFB_S4_REG_BT458_CMAP) { ! 767: ! 768: /* read the colormap: */ ! 769: byte_count = map_count; ! 770: do { ! 771: ! 772: /* advance the packed value: */ ! 773: value_packed <<= 8; ! 774: ! 775: /* read one colormap primary: */ ! 776: value_packed |= (bt458->tme_bt458_cmap_primaries[bt458_rgb])[bt458_address]; ! 777: ! 778: /* advance the Bt458 address registers: */ ! 779: bt458_rgb++; ! 780: if (bt458_rgb == TME_ARRAY_ELS(bt458->tme_bt458_cmap_primaries)) { ! 781: bt458_address++; ! 782: bt458_rgb = 0; ! 783: } ! 784: } while (--map_count > 0); ! 785: } ! 786: ! 787: /* if this is a read of the control register: */ ! 788: else if (reg == TME_SUNFB_S4_REG_BT458_CONTROL) { ! 789: ! 790: if (bt458_address < TME_BT458_REG_CONTROL_FIRST ! 791: || bt458_address > TME_BT458_REG_CONTROL_LAST) { ! 792: abort(); ! 793: } ! 794: ! 795: /* read this register: */ ! 796: value_packed = bt458->tme_bt458_regs[bt458_address - TME_BT458_REG_CONTROL_FIRST]; ! 797: } ! 798: ! 799: /* this must be a read of the overlay map register: */ ! 800: else { ! 801: assert (reg == TME_SUNFB_S4_REG_BT458_OMAP); ! 802: ! 803: /* read the overlay map: */ ! 804: byte_count = map_count; ! 805: do { ! 806: ! 807: /* if the Bt458 address isn't in the overlay map: */ ! 808: if (bt458_address >= 4) { ! 809: abort(); ! 810: } ! 811: ! 812: /* advance the packed value: */ ! 813: value_packed <<= 8; ! 814: ! 815: /* read one overlay map primary: */ ! 816: value_packed |= bt458->tme_bt458_omap_primaries[bt458_rgb][bt458_address]; ! 817: ! 818: /* advance the Bt458 address registers: */ ! 819: bt458_rgb++; ! 820: if (bt458_rgb == TME_ARRAY_ELS(bt458->tme_bt458_omap_primaries)) { ! 821: bt458_address++; ! 822: bt458_rgb = 0; ! 823: } ! 824: } while (--map_count > 0); ! 825: } ! 826: ! 827: /* run the bus cycle: */ ! 828: if (cycle_init->tme_bus_cycle_size == sizeof(tme_uint32_t)) { ! 829: if (byte_count == sizeof(tme_uint8_t)) { ! 830: value_packed |= (value_packed << 8); ! 831: value_packed |= (value_packed << 16); ! 832: } ! 833: tme_bus_cycle_xfer_reg(cycle_init, ! 834: &value_packed, ! 835: TME_BUS32_LOG2); ! 836: } ! 837: else { ! 838: value = value_packed; ! 839: tme_bus_cycle_xfer_reg(cycle_init, ! 840: &value, ! 841: TME_BUS8_LOG2); ! 842: } ! 843: } ! 844: ! 845: /* update the Bt458 address registers: */ ! 846: bt458->tme_bt458_address = bt458_address; ! 847: bt458->tme_bt458_rgb = ((reg == TME_SUNFB_S4_REG_BT458_CMAP ! 848: || reg == TME_SUNFB_S4_REG_BT458_OMAP) ! 849: ? bt458_rgb ! 850: : 0); ! 851: ! 852: /* unlock the mutex: */ ! 853: tme_mutex_unlock(&sunfb->tme_sunfb_mutex); ! 854: ! 855: /* no faults: */ ! 856: return (TME_OK); ! 857: } ! 858: ! 859: /* the sunfb S4 bus cycle handler: */ ! 860: int ! 861: tme_sunfb_bus_cycle_s4(void *_sunfb, struct tme_bus_cycle *cycle_init) ! 862: { ! 863: struct tme_sunfb *sunfb; ! 864: tme_bus_addr_t undecoded; ! 865: tme_uint8_t sunfb_s4_status; ! 866: ! 867: /* if this bus cycle happened in the Bt458 registers: */ ! 868: if ((cycle_init->tme_bus_cycle_address % TME_SUNFB_S4_SIZ_REGS) ! 869: < TME_SUNFB_S4_SIZ_BT458) { ! 870: ! 871: /* call the Bt458 cycle handler: */ ! 872: return (tme_sunfb_bus_cycle_bt458(_sunfb, cycle_init)); ! 873: } ! 874: ! 875: /* recover our data structure: */ ! 876: sunfb = (struct tme_sunfb *) _sunfb; ! 877: ! 878: /* lock the mutex: */ ! 879: tme_mutex_lock(&sunfb->tme_sunfb_mutex); ! 880: ! 881: /* the entire register bus subregion is all decoded (or, rather, not ! 882: decoded) as the S4 registers: */ ! 883: undecoded ! 884: = (cycle_init->tme_bus_cycle_address ! 885: & (((tme_bus_addr_t) 0) ! 886: - TME_SUNFB_S4_SIZ_REGS)); ! 887: ! 888: /* save the status register: */ ! 889: sunfb_s4_status = sunfb->tme_sunfb_s4_regs.tme_sunfb_s4_regs_status; ! 890: ! 891: /* if this is a write, and an interrupt is pending, and this write ! 892: covers the status register: */ ! 893: if (cycle_init->tme_bus_cycle_type == TME_BUS_CYCLE_WRITE ! 894: && (sunfb_s4_status & TME_SUNFB_S4_STATUS_INT_PENDING) ! 895: && (cycle_init->tme_bus_cycle_address ! 896: <= (undecoded ! 897: + TME_SUNFB_S4_REG(tme_sunfb_s4_regs_status))) ! 898: && (cycle_init->tme_bus_cycle_size ! 899: > ((undecoded ! 900: + TME_SUNFB_S4_REG(tme_sunfb_s4_regs_status)) ! 901: - cycle_init->tme_bus_cycle_address))) { ! 902: ! 903: /* clear the interrupt: */ ! 904: sunfb_s4_status &= ~TME_SUNFB_S4_STATUS_INT_PENDING; ! 905: } ! 906: ! 907: /* run the cycle: */ ! 908: assert (cycle_init->tme_bus_cycle_address ! 909: >= sunfb->tme_sunfb_bus_subregion_regs.tme_bus_subregion_address_first); ! 910: tme_bus_cycle_xfer_memory(cycle_init, ! 911: (((tme_uint8_t *) &sunfb->tme_sunfb_s4_regs) ! 912: - TME_SUNFB_S4_SIZ_BT458 ! 913: - undecoded), ! 914: (undecoded ! 915: | (TME_SUNFB_S4_SIZ_REGS - 1))); ! 916: ! 917: /* restore the status register: */ ! 918: sunfb->tme_sunfb_s4_regs.tme_sunfb_s4_regs_status = sunfb_s4_status; ! 919: ! 920: /* make any callouts: */ ! 921: _tme_sunfb_callout(sunfb); ! 922: ! 923: /* unlock the mutex: */ ! 924: tme_mutex_unlock(&sunfb->tme_sunfb_mutex); ! 925: ! 926: /* no faults: */ ! 927: return (TME_OK); ! 928: } ! 929: ! 930: /* the sunfb TLB filler: */ ! 931: static int ! 932: _tme_sunfb_tlb_fill(void *_sunfb, ! 933: struct tme_bus_tlb *tlb, ! 934: tme_bus_addr_t address, ! 935: unsigned int cycles) ! 936: { ! 937: struct tme_sunfb *sunfb; ! 938: unsigned int subregion_i; ! 939: ! 940: /* recover our data structure: */ ! 941: sunfb = (struct tme_sunfb *) _sunfb; ! 942: ! 943: /* initialize the TLB entry: */ ! 944: tme_bus_tlb_initialize(tlb); ! 945: ! 946: /* if this address falls in the bus subregion for memory: */ ! 947: if ((sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_first ! 948: <= address) ! 949: && (address ! 950: <= sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_last)) { ! 951: ! 952: /* if this address falls in the memory pad: */ ! 953: if (address > sunfb->tme_sunfb_memory_address_last_displayed) { ! 954: ! 955: /* this TLB entry covers this range: */ ! 956: tlb->tme_bus_tlb_addr_first = (sunfb->tme_sunfb_memory_address_last_displayed + 1); ! 957: tlb->tme_bus_tlb_addr_last = sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_last; ! 958: ! 959: /* bus cycles to this range are to the memory pad and can be ! 960: fast: */ ! 961: tlb->tme_bus_tlb_cycle = _tme_sunfb_bus_cycle_memory_pad; ! 962: tlb->tme_bus_tlb_emulator_off_write = sunfb->tme_sunfb_memory_pad; ! 963: } ! 964: ! 965: /* otherwise, this address does not fall in the memory pad: */ ! 966: else { ! 967: ! 968: /* this TLB entry covers this range: */ ! 969: tlb->tme_bus_tlb_addr_first = sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_first; ! 970: tlb->tme_bus_tlb_addr_last = sunfb->tme_sunfb_memory_address_last_displayed; ! 971: ! 972: /* bus cycles to this range are to the memory and can be fast: */ ! 973: tlb->tme_bus_tlb_cycle = _tme_sunfb_bus_cycle_memory; ! 974: tlb->tme_bus_tlb_emulator_off_write = sunfb->tme_sunfb_memory; ! 975: } ! 976: ! 977: /* this TLB entry allows fast reading and writing: */ ! 978: tlb->tme_bus_tlb_emulator_off_write -= tlb->tme_bus_tlb_addr_first; ! 979: tlb->tme_bus_tlb_emulator_off_read = tlb->tme_bus_tlb_emulator_off_write; ! 980: } ! 981: ! 982: /* otherwise, this address doesn't fall in the bus subregion for memory: */ ! 983: else { ! 984: ! 985: /* search the other bus subregions: */ ! 986: for (subregion_i = 0;; subregion_i++) { ! 987: ! 988: /* this address must be in some subregion: */ ! 989: assert (subregion_i < TME_SUNFB_BUS_SUBREGIONS_MAX); ! 990: ! 991: /* if this subregion is defined, and this address falls in it: */ ! 992: if (sunfb->tme_sunfb_bus_handlers[subregion_i] != NULL ! 993: && (sunfb->tme_sunfb_bus_subregions[subregion_i].tme_bus_subregion_address_first ! 994: <= address) ! 995: && (address ! 996: <= sunfb->tme_sunfb_bus_subregions[subregion_i].tme_bus_subregion_address_last)) { ! 997: ! 998: /* this TLB entry covers this range: */ ! 999: tlb->tme_bus_tlb_addr_first = sunfb->tme_sunfb_bus_subregions[subregion_i].tme_bus_subregion_address_first; ! 1000: tlb->tme_bus_tlb_addr_last = sunfb->tme_sunfb_bus_subregions[subregion_i].tme_bus_subregion_address_last; ! 1001: ! 1002: /* bus cycles to this range are handled by this handler: */ ! 1003: tlb->tme_bus_tlb_cycle = sunfb->tme_sunfb_bus_handlers[subregion_i]; ! 1004: ! 1005: break; ! 1006: } ! 1007: } ! 1008: } ! 1009: ! 1010: /* the fast reading and writing rwlock: */ ! 1011: tlb->tme_bus_tlb_rwlock = &sunfb->tme_sunfb_rwlock; ! 1012: ! 1013: /* allow reading and writing: */ ! 1014: tlb->tme_bus_tlb_cycles_ok = TME_BUS_CYCLE_READ | TME_BUS_CYCLE_WRITE; ! 1015: ! 1016: /* our bus cycle handler private data: */ ! 1017: tlb->tme_bus_tlb_cycle_private = _sunfb; ! 1018: ! 1019: return (TME_OK); ! 1020: } ! 1021: ! 1022: /* this makes a new framebuffer connection: */ ! 1023: static int ! 1024: _tme_sunfb_connection_make(struct tme_connection *conn, unsigned int state) 1.1 root 1025: { 1.1.1.2 ! root 1026: struct tme_sunfb *sunfb; ! 1027: struct tme_fb_connection *conn_fb; ! 1028: struct tme_fb_connection *conn_fb_other; ! 1029: int rc; ! 1030: ! 1031: /* recover our data structures: */ ! 1032: sunfb = conn->tme_connection_element->tme_element_private; ! 1033: conn_fb = (struct tme_fb_connection *) conn; ! 1034: conn_fb_other = (struct tme_fb_connection *) conn->tme_connection_other; ! 1035: ! 1036: /* both sides must be framebuffer connections: */ ! 1037: assert(conn->tme_connection_type == TME_CONNECTION_FRAMEBUFFER); ! 1038: assert(conn->tme_connection_other->tme_connection_type == TME_CONNECTION_FRAMEBUFFER); ! 1039: ! 1040: /* lock our mutex: */ ! 1041: tme_mutex_lock(&sunfb->tme_sunfb_mutex); ! 1042: ! 1043: /* we're always set up to answer calls across the connection, so we ! 1044: only have to do work when the connection has gone full, namely ! 1045: taking the other side of the connection: */ ! 1046: if (state == TME_CONNECTION_FULL) { ! 1047: ! 1048: /* if the other side of the connection is not supplying specific ! 1049: displayed memory that it wants us to use: */ ! 1050: if (conn_fb->tme_fb_connection_buffer == NULL) { ! 1051: ! 1052: /* allocate displayed memory: */ ! 1053: rc = tme_fb_xlat_alloc_src(conn_fb); ! 1054: assert (rc == TME_OK); ! 1055: } ! 1056: ! 1057: /* if this framebuffer just maps the displayed memory on the bus, ! 1058: do that: */ ! 1059: if (sunfb->tme_sunfb_memory == NULL) { ! 1060: sunfb->tme_sunfb_memory = conn_fb->tme_fb_connection_buffer; ! 1061: } ! 1062: ! 1063: /* save our connection: */ ! 1064: sunfb->tme_sunfb_fb_connection = conn_fb_other; 1.1 root 1065: } 1.1.1.2 ! root 1066: ! 1067: /* unlock our mutex: */ ! 1068: tme_mutex_unlock(&sunfb->tme_sunfb_mutex); ! 1069: ! 1070: return (TME_OK); ! 1071: } ! 1072: ! 1073: /* this breaks a connection: */ ! 1074: static int ! 1075: _tme_sunfb_connection_break(struct tme_connection *conn, unsigned int state) ! 1076: { ! 1077: abort(); ! 1078: } ! 1079: ! 1080: /* this makes a new connection side for a sunfb: */ ! 1081: static int ! 1082: _tme_sunfb_connections_new(struct tme_element *element, ! 1083: const char * const *args, ! 1084: struct tme_connection **_conns, ! 1085: char **_output) ! 1086: { ! 1087: struct tme_sunfb *sunfb; ! 1088: struct tme_fb_connection *conn_fb; ! 1089: struct tme_connection *conn; ! 1090: int rc; ! 1091: ! 1092: /* recover our data structure: */ ! 1093: sunfb = (struct tme_sunfb *) element->tme_element_private; ! 1094: ! 1095: /* make the generic bus device connection side: */ ! 1096: rc = tme_bus_device_connections_new(element, args, _conns, _output); ! 1097: if (rc != TME_OK) { ! 1098: return (rc); ! 1099: } ! 1100: ! 1101: /* if we don't have a framebuffer connection, make one: */ ! 1102: if (sunfb->tme_sunfb_fb_connection == NULL) { ! 1103: ! 1104: /* allocate the new framebuffer connection: */ ! 1105: conn_fb = tme_new0(struct tme_fb_connection, 1); ! 1106: conn = &conn_fb->tme_fb_connection; ! 1107: ! 1108: /* fill in the generic connection: */ ! 1109: conn->tme_connection_next = *_conns; ! 1110: conn->tme_connection_type = TME_CONNECTION_FRAMEBUFFER; ! 1111: conn->tme_connection_score = tme_fb_connection_score; ! 1112: conn->tme_connection_make = _tme_sunfb_connection_make; ! 1113: conn->tme_connection_break = _tme_sunfb_connection_break; ! 1114: ! 1115: /* fill in the framebuffer connection: */ ! 1116: conn_fb->tme_fb_connection_mode_change = NULL; ! 1117: conn_fb->tme_fb_connection_update = NULL; ! 1118: ! 1119: /* class: */ ! 1120: conn_fb->tme_fb_connection_class = sunfb->tme_sunfb_class; ! 1121: ! 1122: /* depth: */ ! 1123: conn_fb->tme_fb_connection_depth = sunfb->tme_sunfb_depth; ! 1124: ! 1125: /* width and height: */ ! 1126: conn_fb->tme_fb_connection_width = tme_sunfb_size_width(sunfb->tme_sunfb_size); ! 1127: conn_fb->tme_fb_connection_height = tme_sunfb_size_height(sunfb->tme_sunfb_size); ! 1128: ! 1129: /* we skip no pixels at the start of the scanline: */ ! 1130: conn_fb->tme_fb_connection_skipx = 0; ! 1131: ! 1132: /* we pad to 32-bit boundaries: */ ! 1133: conn_fb->tme_fb_connection_scanline_pad = 32; ! 1134: ! 1135: /* we are big-endian: */ ! 1136: conn_fb->tme_fb_connection_order = TME_ENDIAN_BIG; ! 1137: ! 1138: /* we don't allocate memory until the connection is made, in case ! 1139: the other side of the connection wants to provide us with a ! 1140: specific memory region to use (maybe we're on a system with ! 1141: real matching hardware and we can write directly to its buffer): */ ! 1142: conn_fb->tme_fb_connection_buffer = NULL; ! 1143: ! 1144: /* assume that bits per pixel is the same as depth: */ ! 1145: conn_fb->tme_fb_connection_bits_per_pixel = sunfb->tme_sunfb_depth; ! 1146: ! 1147: /* assume that our pixels don't have subfields: */ ! 1148: conn_fb->tme_fb_connection_mask_g = 0; ! 1149: conn_fb->tme_fb_connection_mask_r = 0; ! 1150: conn_fb->tme_fb_connection_mask_b = 0; ! 1151: ! 1152: /* set any update function: */ ! 1153: conn_fb->tme_fb_connection_update = sunfb->tme_sunfb_memory_update; ! 1154: ! 1155: /* if this is a bwtwo: */ ! 1156: if (_TME_SUNFB_IS_BWTWO(sunfb)) { ! 1157: ! 1158: /* intensities are a single bit, linearly mapped, but inverted: */ ! 1159: conn_fb->tme_fb_connection_map_bits = 1; ! 1160: conn_fb->tme_fb_connection_map_g = NULL; ! 1161: conn_fb->tme_fb_connection_map_r = NULL; ! 1162: conn_fb->tme_fb_connection_map_b = NULL; ! 1163: conn_fb->tme_fb_connection_inverted = TRUE; ! 1164: } ! 1165: ! 1166: /* otherwise, this is one of the eight-bit color framebuffers: */ ! 1167: else { ! 1168: ! 1169: /* intensities are eight bits and index mapped: */ ! 1170: conn_fb->tme_fb_connection_map_bits = 8; ! 1171: conn_fb->tme_fb_connection_map_g = sunfb->tme_sunfb_cmap_g; ! 1172: conn_fb->tme_fb_connection_map_r = sunfb->tme_sunfb_cmap_r; ! 1173: conn_fb->tme_fb_connection_map_b = sunfb->tme_sunfb_cmap_b; ! 1174: } ! 1175: ! 1176: /* return the connection side possibility: */ ! 1177: *_conns = conn; ! 1178: } ! 1179: ! 1180: /* done: */ ! 1181: return (TME_OK); ! 1182: } ! 1183: ! 1184: /* the new Sun framebuffer function: */ ! 1185: int ! 1186: tme_sunfb_new(struct tme_sunfb *sunfb, ! 1187: const char * const *args, ! 1188: char **_output) ! 1189: { ! 1190: struct tme_bus_subregion *subregion; ! 1191: const struct tme_bus_subregion **_subregion_prev; ! 1192: unsigned int subregion_i; ! 1193: const char *sunfb_type_string; ! 1194: const char *sunfb_size_string; ! 1195: tme_uint32_t sunfb_size; ! 1196: tme_bus_addr_t fb_size; ! 1197: tme_uint32_t sunfb_p4; ! 1198: tme_uint8_t sunfb_s4_status; ! 1199: int arg_i; ! 1200: int usage; ! 1201: ! 1202: /* check our arguments: */ ! 1203: usage = 0; ! 1204: sunfb_type_string = NULL; ! 1205: sunfb_size_string = NULL; ! 1206: arg_i = 1; ! 1207: for (;;) { ! 1208: ! 1209: /* the framebuffer type: */ ! 1210: if (TME_ARG_IS(args[arg_i + 0], "type") ! 1211: && sunfb_type_string == NULL ! 1212: && sunfb->tme_sunfb_type_set != NULL) { ! 1213: sunfb_type_string = args[arg_i + 1]; ! 1214: if (sunfb_type_string == NULL ! 1215: || (*sunfb->tme_sunfb_type_set)(sunfb, sunfb_type_string) != NULL) { ! 1216: usage = TRUE; ! 1217: break; ! 1218: } ! 1219: arg_i += 2; ! 1220: } ! 1221: ! 1222: /* the framebuffer size: */ ! 1223: else if (TME_ARG_IS(args[arg_i + 0], "size") ! 1224: && sunfb_size_string == NULL) { ! 1225: sunfb_size_string = args[arg_i + 1]; ! 1226: if (sunfb_size_string == NULL) { ! 1227: usage = TRUE; ! 1228: break; ! 1229: } ! 1230: arg_i += 2; ! 1231: } ! 1232: ! 1233: /* if we ran out of arguments: */ ! 1234: else if (args[arg_i] == NULL) { ! 1235: ! 1236: break; ! 1237: } ! 1238: ! 1239: /* otherwise this is a bad argument: */ ! 1240: else { ! 1241: tme_output_append_error(_output, ! 1242: "%s %s, ", ! 1243: args[arg_i], ! 1244: _("unexpected")); ! 1245: usage = TRUE; ! 1246: break; ! 1247: } ! 1248: } ! 1249: ! 1250: /* set some common defaults based on framebuffer type: */ ! 1251: ! 1252: /* if this is a P4 framebuffer: */ ! 1253: if (_TME_SUNFB_IS_P4(sunfb)) { ! 1254: ! 1255: /* default possible P4 sizes: */ ! 1256: if (sunfb->tme_sunfb_size == 0) { ! 1257: sunfb->tme_sunfb_size ! 1258: = (TME_SUNFB_SIZE_1600_1280 ! 1259: | TME_SUNFB_SIZE_1152_900 ! 1260: | TME_SUNFB_SIZE_1024_1024 ! 1261: | TME_SUNFB_SIZE_1280_1024 ! 1262: | TME_SUNFB_SIZE_1440_1440); ! 1263: } ! 1264: ! 1265: /* the memory address can't be zero: */ ! 1266: assert (sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_first != 0); ! 1267: ! 1268: /* the P4 register is always at the same offset: */ ! 1269: sunfb->tme_sunfb_bus_subregion_regs.tme_bus_subregion_address_first = TME_SUNFB_P4_OFFSET_P4; ! 1270: ! 1271: /* the default size of the P4 register bus subregion: */ ! 1272: if (sunfb->tme_sunfb_bus_subregion_regs.tme_bus_subregion_address_last == 0) { ! 1273: sunfb->tme_sunfb_bus_subregion_regs.tme_bus_subregion_address_last ! 1274: = (sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_first ! 1275: - 1); ! 1276: } ! 1277: } ! 1278: ! 1279: ! 1280: /* if this is an S4 framebuffer: */ ! 1281: if (_TME_SUNFB_IS_S4(sunfb)) { ! 1282: ! 1283: /* default possible S4 framebuffer sizes: */ ! 1284: if (sunfb->tme_sunfb_size == 0) { ! 1285: sunfb->tme_sunfb_size ! 1286: = (TME_SUNFB_SIZE_1024_768 ! 1287: | TME_SUNFB_SIZE_1152_900 ! 1288: | TME_SUNFB_SIZE_1280_1024 ! 1289: | TME_SUNFB_SIZE_1600_1280); ! 1290: } ! 1291: ! 1292: /* the default memory address: */ ! 1293: if (sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_first == 0) { ! 1294: sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_first = TME_SUNFB_S4_OFFSET_MEMORY; ! 1295: } ! 1296: ! 1297: /* the S4 registers are always at the same offset: */ ! 1298: sunfb->tme_sunfb_bus_subregion_regs.tme_bus_subregion_address_first = TME_SUNFB_S4_OFFSET_REGS; ! 1299: ! 1300: /* the default size of the S4 register bus subregion: */ ! 1301: if (sunfb->tme_sunfb_bus_subregion_regs.tme_bus_subregion_address_last == 0) { ! 1302: sunfb->tme_sunfb_bus_subregion_regs.tme_bus_subregion_address_last ! 1303: = (sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_first ! 1304: - 1); ! 1305: } ! 1306: } ! 1307: ! 1308: /* we must have some possible sizes: */ ! 1309: assert (sunfb->tme_sunfb_size != 0 || usage); ! 1310: ! 1311: /* if no specific size is given: */ ! 1312: if (sunfb_size_string == NULL) { ! 1313: ! 1314: /* use the first size supported by this framebuffer, which will ! 1315: usually be 1152x900: */ ! 1316: sunfb_size = sunfb->tme_sunfb_size; ! 1317: sunfb_size = (sunfb_size & ~(sunfb_size - 1)); ! 1318: } ! 1319: ! 1320: /* otherwise, convert the specific size: */ ! 1321: else { ! 1322: sunfb_size = tme_sunfb_size(sunfb_size_string); ! 1323: } ! 1324: ! 1325: /* if the size is not supported by this framebuffer: */ ! 1326: if ((sunfb->tme_sunfb_size & sunfb_size) == 0) { ! 1327: usage = TRUE; ! 1328: } ! 1329: ! 1330: if (usage) { ! 1331: ! 1332: /* start the usage message: */ ! 1333: tme_output_append_error(_output, ! 1334: "%s %s", ! 1335: _("usage"), ! 1336: args[0]); ! 1337: ! 1338: /* if this framebuffer has types, append a type argument to the ! 1339: usage message: */ ! 1340: if (sunfb->tme_sunfb_type_set != NULL) { ! 1341: sunfb_type_string = (*sunfb->tme_sunfb_type_set)(sunfb, NULL); ! 1342: tme_output_append_error(_output, " type { %s }", sunfb_type_string); ! 1343: } ! 1344: ! 1345: /* append the supported types to the usage message: */ ! 1346: tme_output_append_error(_output, ! 1347: " [ size {"); ! 1348: for (sunfb_size = sunfb->tme_sunfb_size; ! 1349: sunfb_size != 0; ! 1350: sunfb_size &= (sunfb_size - 1)) { ! 1351: switch (sunfb_size & ~(sunfb_size - 1)) { ! 1352: default: assert(FALSE); ! 1353: case TME_SUNFB_SIZE_1152_900: sunfb_size_string = "1152x900"; break; ! 1354: case TME_SUNFB_SIZE_1024_1024: sunfb_size_string = "1024x1024"; break; ! 1355: case TME_SUNFB_SIZE_1280_1024: sunfb_size_string = "1280x1024"; break; ! 1356: case TME_SUNFB_SIZE_1600_1280: sunfb_size_string = "1600x1280"; break; ! 1357: case TME_SUNFB_SIZE_1440_1440: sunfb_size_string = "1440x1440"; break; ! 1358: case TME_SUNFB_SIZE_1024_768: sunfb_size_string = "1024x768"; break; ! 1359: case TME_SUNFB_SIZE_640_480: sunfb_size_string = "640x480"; break; ! 1360: } ! 1361: tme_output_append_error(_output, " %s", sunfb_size_string); ! 1362: } ! 1363: tme_output_append_error(_output, " } ]"); ! 1364: ! 1365: /* return the error: */ ! 1366: return (EINVAL); ! 1367: } ! 1368: ! 1369: /* finish initializing the sunfb structure: */ ! 1370: tme_mutex_init(&sunfb->tme_sunfb_mutex); ! 1371: tme_rwlock_init(&sunfb->tme_sunfb_rwlock); ! 1372: ! 1373: /* set the size: */ ! 1374: sunfb->tme_sunfb_size = sunfb_size; ! 1375: ! 1376: /* calculate the number of bytes of displayed framebuffer memory: */ ! 1377: fb_size = tme_sunfb_size_width(sunfb->tme_sunfb_size); ! 1378: fb_size *= tme_sunfb_size_height(sunfb->tme_sunfb_size); ! 1379: if (_TME_SUNFB_IS_BWTWO(sunfb)) { ! 1380: fb_size /= 8; ! 1381: } ! 1382: ! 1383: /* set the (relative) bus address of the last byte of displayed ! 1384: memory: */ ! 1385: sunfb->tme_sunfb_memory_address_last_displayed ! 1386: = (sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_first ! 1387: + fb_size ! 1388: - 1); ! 1389: ! 1390: /* assume that the real number of bytes of memory is the number of ! 1391: bytes displayed, rounded up to the nearest power of two: */ ! 1392: if ((fb_size & (fb_size - 1)) != 0) { ! 1393: for (; (fb_size & (fb_size - 1)) != 0; fb_size &= (fb_size - 1)); ! 1394: fb_size <<= 1; ! 1395: } ! 1396: ! 1397: /* set the (relative) bus address of the last byte of memory: */ ! 1398: sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_last ! 1399: = (sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_first ! 1400: + fb_size ! 1401: - 1); ! 1402: ! 1403: /* if we need to, allocate pad (undisplayed) framebuffer memory: */ ! 1404: if (sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_last ! 1405: > sunfb->tme_sunfb_memory_address_last_displayed) { ! 1406: ! 1407: /* allocate the pad memory: */ ! 1408: sunfb->tme_sunfb_memory_pad ! 1409: = tme_new0(tme_uint8_t, ! 1410: (sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_last ! 1411: - sunfb->tme_sunfb_memory_address_last_displayed)); ! 1412: } ! 1413: ! 1414: /* if this is a P4 framebuffer: */ ! 1415: if (_TME_SUNFB_IS_P4(sunfb)) { ! 1416: ! 1417: /* get our initial P4 register: */ ! 1418: sunfb_p4 = tme_betoh_u32(sunfb->tme_sunfb_p4); ! 1419: ! 1420: /* if the P4 register doesn't already have something in the size ! 1421: field, add it: */ ! 1422: if ((sunfb_p4 & TME_SUNFB_P4_SIZE_MASK) == 0) { ! 1423: switch (sunfb_size) { ! 1424: default: assert(FALSE); ! 1425: case TME_SUNFB_SIZE_1152_900: sunfb_p4 |= TME_SUNFB_P4_SIZE_1152_900; break; ! 1426: case TME_SUNFB_SIZE_1024_1024: sunfb_p4 |= TME_SUNFB_P4_SIZE_1024_1024; break; ! 1427: case TME_SUNFB_SIZE_1280_1024: sunfb_p4 |= TME_SUNFB_P4_SIZE_1280_1024; break; ! 1428: case TME_SUNFB_SIZE_1600_1280: sunfb_p4 |= TME_SUNFB_P4_SIZE_1600_1280; break; ! 1429: case TME_SUNFB_SIZE_1440_1440: sunfb_p4 |= TME_SUNFB_P4_SIZE_1440_1440; break; ! 1430: case TME_SUNFB_SIZE_640_480: sunfb_p4 |= TME_SUNFB_P4_SIZE_640_480; break; ! 1431: } ! 1432: } ! 1433: ! 1434: /* set video as enabled: */ ! 1435: sunfb_p4 |= TME_SUNFB_P4_REG_VIDEO_ENABLE; ! 1436: ! 1437: /* set the initial P4 register: */ ! 1438: sunfb->tme_sunfb_p4 = tme_htobe_u32(sunfb_p4); ! 1439: } ! 1440: ! 1441: /* if this is an S4 framebuffer: */ ! 1442: if (_TME_SUNFB_IS_S4(sunfb)) { ! 1443: ! 1444: /* set the initial S4 control register: */ ! 1445: sunfb->tme_sunfb_s4_regs.tme_sunfb_s4_regs_control ! 1446: = (TME_SUNFB_S4_CONTROL_VIDEO_ENABLE); ! 1447: ! 1448: /* set the initial S4 status register: */ ! 1449: switch (sunfb_size) { ! 1450: default: assert(FALSE); ! 1451: case TME_SUNFB_SIZE_1152_900: sunfb_s4_status = TME_SUNFB_S4_STATUS_SIZE_1152_900; break; ! 1452: case TME_SUNFB_SIZE_1024_768: sunfb_s4_status = TME_SUNFB_S4_STATUS_SIZE_1024_768; break; ! 1453: case TME_SUNFB_SIZE_1280_1024: sunfb_s4_status = TME_SUNFB_S4_STATUS_SIZE_1280_1024; break; ! 1454: case TME_SUNFB_SIZE_1600_1280: sunfb_s4_status = TME_SUNFB_S4_STATUS_SIZE_1600_1280; break; ! 1455: } ! 1456: sunfb->tme_sunfb_s4_regs.tme_sunfb_s4_regs_status ! 1457: = (sunfb_s4_status ! 1458: | (_TME_SUNFB_IS_BWTWO(sunfb) ! 1459: ? TME_SUNFB_S4_STATUS_ID_MONO ! 1460: : TME_SUNFB_S4_STATUS_ID_COLOR)); ! 1461: } ! 1462: ! 1463: /* if this is a color framebuffer: */ ! 1464: if (!_TME_SUNFB_IS_BWTWO(sunfb)) { ! 1465: ! 1466: /* if we don't have a specific memory update function, use the ! 1467: default: */ ! 1468: if (sunfb->tme_sunfb_memory_update == NULL) { ! 1469: sunfb->tme_sunfb_memory_update = tme_sunfb_memory_update; ! 1470: } ! 1471: } ! 1472: ! 1473: /* make all of the defined subregions into a list. the memory ! 1474: subregion is always in the list, and it is first: */ ! 1475: _subregion_prev = &sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_next; ! 1476: for (subregion_i = 0; ! 1477: subregion_i < TME_SUNFB_BUS_SUBREGIONS_MAX; ! 1478: subregion_i++) { ! 1479: if (sunfb->tme_sunfb_bus_handlers[subregion_i] != NULL) { ! 1480: subregion = &sunfb->tme_sunfb_bus_subregions[subregion_i]; ! 1481: *_subregion_prev = subregion; ! 1482: _subregion_prev = &subregion->tme_bus_subregion_next; ! 1483: } ! 1484: } ! 1485: *_subregion_prev = NULL; ! 1486: ! 1487: /* initialize our simple bus device descriptor: */ ! 1488: sunfb->tme_sunfb_device.tme_bus_device_tlb_fill = _tme_sunfb_tlb_fill; ! 1489: ! 1490: /* fill the element: */ ! 1491: sunfb->tme_sunfb_element->tme_element_private = sunfb; ! 1492: sunfb->tme_sunfb_element->tme_element_connections_new = _tme_sunfb_connections_new; ! 1493: ! 1494: /* initialize the timeout thread condition: */ ! 1495: tme_cond_init(&sunfb->tme_sunfb_callout_cond); ! 1496: ! 1497: /* start the callout thread: */ ! 1498: tme_thread_create((tme_thread_t) _tme_sunfb_callout_thread, sunfb); ! 1499: ! 1500: return (TME_OK); ! 1501: } ! 1502: ! 1503: /* the new sun cgthree function: */ ! 1504: int ! 1505: tme_sun_cgthree(struct tme_element *element, const char * const *args, char **_output) ! 1506: { ! 1507: struct tme_sunfb *sunfb; ! 1508: tme_uint8_t *cmap; ! 1509: int rc; ! 1510: ! 1511: /* start the sunfb structure: */ ! 1512: sunfb = tme_new0(struct tme_sunfb, 1); ! 1513: sunfb->tme_sunfb_element = element; ! 1514: ! 1515: /* initialize the sunfb structure: */ ! 1516: sunfb->tme_sunfb_class = TME_FB_XLAT_CLASS_COLOR; ! 1517: sunfb->tme_sunfb_depth = 8; ! 1518: sunfb->tme_sunfb_bus_handler_regs = tme_sunfb_bus_cycle_s4; ! 1519: sunfb->tme_sunfb_flags ! 1520: |= (TME_SUNFB_FLAG_BT458_CMAP_PACKED ! 1521: | TME_SUNFB_FLAG_BT458_BYTE_D0_D7); ! 1522: ! 1523: /* if the generic initialization fails: */ ! 1524: rc = tme_sunfb_new(sunfb, args, _output); ! 1525: if (rc) { ! 1526: ! 1527: /* free the sunfb structure and return the error: */ ! 1528: tme_free(sunfb); ! 1529: return (rc); ! 1530: } ! 1531: ! 1532: /* allocate the colormap arrays: */ ! 1533: cmap = tme_new0(tme_uint8_t, 256 * 3); ! 1534: sunfb->tme_sunfb_cmap_g = &cmap[256 * 0]; ! 1535: sunfb->tme_sunfb_cmap_r = &cmap[256 * 1]; ! 1536: sunfb->tme_sunfb_cmap_b = &cmap[256 * 2]; ! 1537: sunfb->tme_sunfb_bt458.tme_bt458_cmap_g = sunfb->tme_sunfb_cmap_g; ! 1538: sunfb->tme_sunfb_bt458.tme_bt458_cmap_r = sunfb->tme_sunfb_cmap_r; ! 1539: sunfb->tme_sunfb_bt458.tme_bt458_cmap_b = sunfb->tme_sunfb_cmap_b; ! 1540: ! 1541: return (TME_OK); 1.1 root 1542: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.