1dbbd9e4bSmacallan/* 2dbbd9e4bSmacallan * Acceleration for the Creator and Creator3D framebuffer - WID pool management. 3dbbd9e4bSmacallan * 4dbbd9e4bSmacallan * Copyright (C) 2000 David S. Miller (davem@redhat.com) 5dbbd9e4bSmacallan * 6dbbd9e4bSmacallan * Permission is hereby granted, free of charge, to any person obtaining a copy 7dbbd9e4bSmacallan * of this software and associated documentation files (the "Software"), to deal 8dbbd9e4bSmacallan * in the Software without restriction, including without limitation the rights 9dbbd9e4bSmacallan * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10dbbd9e4bSmacallan * copies of the Software, and to permit persons to whom the Software is 11dbbd9e4bSmacallan * furnished to do so, subject to the following conditions: 12dbbd9e4bSmacallan * 13dbbd9e4bSmacallan * The above copyright notice and this permission notice shall be included in 14dbbd9e4bSmacallan * all copies or substantial portions of the Software. 15dbbd9e4bSmacallan * 16dbbd9e4bSmacallan * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17dbbd9e4bSmacallan * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18dbbd9e4bSmacallan * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19dbbd9e4bSmacallan * DAVID MILLER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20dbbd9e4bSmacallan * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21dbbd9e4bSmacallan * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22dbbd9e4bSmacallan * 23dbbd9e4bSmacallan */ 24dbbd9e4bSmacallan 25dbbd9e4bSmacallan#ifdef HAVE_CONFIG_H 26dbbd9e4bSmacallan#include "config.h" 27dbbd9e4bSmacallan#endif 28dbbd9e4bSmacallan 29dbbd9e4bSmacallan#include "ffb.h" 30dbbd9e4bSmacallan 31dbbd9e4bSmacallanstatic void 32dbbd9e4bSmacallandetermine_numwids(FFBPtr pFfb) 33dbbd9e4bSmacallan{ 34dbbd9e4bSmacallan ffb_dac_info_t *p = &pFfb->dac_info; 35dbbd9e4bSmacallan 36dbbd9e4bSmacallan if (p->flags & FFB_DAC_PAC1) 37dbbd9e4bSmacallan p->wid_table.num_wids = 32; 38dbbd9e4bSmacallan else 39dbbd9e4bSmacallan p->wid_table.num_wids = 64; 40dbbd9e4bSmacallan} 41dbbd9e4bSmacallan 42dbbd9e4bSmacallanstatic void 43dbbd9e4bSmacallanmake_wlut_regval(ffb_dac_info_t *p, ffb_wid_info_t *wid) 44dbbd9e4bSmacallan{ 45dbbd9e4bSmacallan wid->wlut_regval = 0; 46dbbd9e4bSmacallan 47dbbd9e4bSmacallan if (p->flags & FFB_DAC_PAC1) { 48dbbd9e4bSmacallan unsigned int color_model_bits; 49dbbd9e4bSmacallan 50dbbd9e4bSmacallan /* Pacifica1 format */ 51dbbd9e4bSmacallan if (wid->buffer != 0) 52dbbd9e4bSmacallan wid->wlut_regval |= FFBDAC_PAC1_WLUT_DB; 53dbbd9e4bSmacallan 54dbbd9e4bSmacallan if (wid->depth == 8) { 55dbbd9e4bSmacallan if (wid->greyscale) { 56dbbd9e4bSmacallan if (wid->linear) 57dbbd9e4bSmacallan color_model_bits = FFBDAC_PAC1_WLUT_C_8LG; 58dbbd9e4bSmacallan else 59dbbd9e4bSmacallan color_model_bits = FFBDAC_PAC1_WLUT_C_8NG; 60dbbd9e4bSmacallan } else { 61dbbd9e4bSmacallan color_model_bits = FFBDAC_PAC1_WLUT_C_8P; 62dbbd9e4bSmacallan } 63dbbd9e4bSmacallan } else { 64dbbd9e4bSmacallan if (wid->direct) { 65dbbd9e4bSmacallan color_model_bits = FFBDAC_PAC1_WLUT_C_24D; 66dbbd9e4bSmacallan } else { 67dbbd9e4bSmacallan if (wid->linear) 68dbbd9e4bSmacallan color_model_bits = FFBDAC_PAC1_WLUT_C_24LT; 69dbbd9e4bSmacallan else 70dbbd9e4bSmacallan color_model_bits = FFBDAC_PAC1_WLUT_C_24NT; 71dbbd9e4bSmacallan } 72dbbd9e4bSmacallan } 73dbbd9e4bSmacallan 74dbbd9e4bSmacallan wid->wlut_regval |= color_model_bits; 75dbbd9e4bSmacallan 76dbbd9e4bSmacallan switch (wid->channel) { 77dbbd9e4bSmacallan default: 78dbbd9e4bSmacallan case 0: 79dbbd9e4bSmacallan wid->wlut_regval |= FFBDAC_PAC1_WLUT_P_XO; 80dbbd9e4bSmacallan break; 81dbbd9e4bSmacallan case 1: 82dbbd9e4bSmacallan wid->wlut_regval |= FFBDAC_PAC1_WLUT_P_R; 83dbbd9e4bSmacallan break; 84dbbd9e4bSmacallan case 2: 85dbbd9e4bSmacallan wid->wlut_regval |= FFBDAC_PAC1_WLUT_P_G; 86dbbd9e4bSmacallan break; 87dbbd9e4bSmacallan case 3: 88dbbd9e4bSmacallan wid->wlut_regval |= FFBDAC_PAC1_WLUT_P_B; 89dbbd9e4bSmacallan break; 90dbbd9e4bSmacallan }; 91dbbd9e4bSmacallan } else { 92dbbd9e4bSmacallan /* Pacifica2 format */ 93dbbd9e4bSmacallan if (wid->buffer != 0) 94dbbd9e4bSmacallan wid->wlut_regval |= FFBDAC_PAC2_WLUT_DB; 95dbbd9e4bSmacallan 96dbbd9e4bSmacallan if (wid->depth == 24) 97dbbd9e4bSmacallan wid->wlut_regval |= FFBDAC_PAC2_WLUT_DEPTH; 98dbbd9e4bSmacallan 99dbbd9e4bSmacallan switch (wid->channel) { 100dbbd9e4bSmacallan default: 101dbbd9e4bSmacallan case 0: 102dbbd9e4bSmacallan wid->wlut_regval |= FFBDAC_PAC2_WLUT_P_XO; 103dbbd9e4bSmacallan break; 104dbbd9e4bSmacallan case 1: 105dbbd9e4bSmacallan wid->wlut_regval |= FFBDAC_PAC2_WLUT_P_R; 106dbbd9e4bSmacallan break; 107dbbd9e4bSmacallan case 2: 108dbbd9e4bSmacallan wid->wlut_regval |= FFBDAC_PAC2_WLUT_P_G; 109dbbd9e4bSmacallan break; 110dbbd9e4bSmacallan case 3: 111dbbd9e4bSmacallan wid->wlut_regval |= FFBDAC_PAC2_WLUT_P_B; 112dbbd9e4bSmacallan break; 113dbbd9e4bSmacallan }; 114dbbd9e4bSmacallan 115dbbd9e4bSmacallan if ((wid->depth == 8 && wid->greyscale == 0) || 116dbbd9e4bSmacallan (wid->depth == 24 && wid->direct != 0)) 117dbbd9e4bSmacallan wid->wlut_regval |= FFBDAC_PAC2_WLUT_LKUP; 118dbbd9e4bSmacallan 119dbbd9e4bSmacallan if (wid->palette != -1) 120dbbd9e4bSmacallan wid->wlut_regval |= 121dbbd9e4bSmacallan ((wid->palette << 4) & FFBDAC_PAC2_WLUT_PTBL); 122dbbd9e4bSmacallan } 123dbbd9e4bSmacallan} 124dbbd9e4bSmacallan 125dbbd9e4bSmacallanstatic void 126dbbd9e4bSmacallaninit_wid_table(FFBPtr pFfb) 127dbbd9e4bSmacallan{ 128dbbd9e4bSmacallan ffb_dac_info_t *p = &pFfb->dac_info; 129dbbd9e4bSmacallan ffb_wid_pool_t *table = &p->wid_table; 130dbbd9e4bSmacallan int i; 131dbbd9e4bSmacallan 132dbbd9e4bSmacallan for (i = 0; i < table->num_wids; i++) { 133dbbd9e4bSmacallan table->wid_pool[i].InUse = FALSE; 134dbbd9e4bSmacallan table->wid_pool[i].buffer = 0; 135dbbd9e4bSmacallan table->wid_pool[i].depth = 24; 136dbbd9e4bSmacallan table->wid_pool[i].greyscale = 0; 137dbbd9e4bSmacallan table->wid_pool[i].linear = 0; 138dbbd9e4bSmacallan table->wid_pool[i].direct = 0; 139dbbd9e4bSmacallan table->wid_pool[i].channel = 0; 140dbbd9e4bSmacallan table->wid_pool[i].palette = -1; 141dbbd9e4bSmacallan make_wlut_regval(p, &table->wid_pool[i]); 142dbbd9e4bSmacallan } 143dbbd9e4bSmacallan 144dbbd9e4bSmacallan table->wid_pool[table->num_wids - 1].InUse = TRUE; 145dbbd9e4bSmacallan table->wid_pool[table->num_wids - 1].canshare = FALSE; 146dbbd9e4bSmacallan} 147dbbd9e4bSmacallan 148dbbd9e4bSmacallanstatic void 149dbbd9e4bSmacallaninit_hw_wids(FFBPtr pFfb) 150dbbd9e4bSmacallan{ 151dbbd9e4bSmacallan ffb_dac_info_t *p = &pFfb->dac_info; 152dbbd9e4bSmacallan ffb_dacPtr dac = pFfb->dac; 153dbbd9e4bSmacallan ffb_wid_pool_t *table = &p->wid_table; 154dbbd9e4bSmacallan int i; 155dbbd9e4bSmacallan 156dbbd9e4bSmacallan if (p->flags & FFB_DAC_PAC1) 157dbbd9e4bSmacallan dac->cfg = FFBDAC_PAC1_APWLUT_BASE; 158dbbd9e4bSmacallan else 159dbbd9e4bSmacallan dac->cfg = FFBDAC_PAC2_APWLUT_BASE; 160dbbd9e4bSmacallan for (i = 0; i < table->num_wids; i++) 161dbbd9e4bSmacallan dac->cfgdata = table->wid_pool[i].wlut_regval; 162dbbd9e4bSmacallan 163dbbd9e4bSmacallan if (p->flags & FFB_DAC_PAC1) 164dbbd9e4bSmacallan dac->cfg = FFBDAC_PAC1_SPWLUT_BASE; 165dbbd9e4bSmacallan else 166dbbd9e4bSmacallan dac->cfg = FFBDAC_PAC2_SPWLUT_BASE; 167dbbd9e4bSmacallan for (i = 0; i < table->num_wids; i++) 168dbbd9e4bSmacallan dac->cfgdata = table->wid_pool[i].wlut_regval; 169dbbd9e4bSmacallan} 170dbbd9e4bSmacallan 171dbbd9e4bSmacallanstatic void 172dbbd9e4bSmacallaninit_hw_widmode(FFBPtr pFfb) 173dbbd9e4bSmacallan{ 174dbbd9e4bSmacallan ffb_dacPtr dac = pFfb->dac; 175dbbd9e4bSmacallan ffb_dac_info_t *p = &pFfb->dac_info; 176dbbd9e4bSmacallan unsigned int uctrl; 177dbbd9e4bSmacallan 178dbbd9e4bSmacallan /* For now we use the Combined WID mode until I figure 179dbbd9e4bSmacallan * out exactly how Seperate4 and Seperate8 work. We 180dbbd9e4bSmacallan * also disable overlays for the time being. 181dbbd9e4bSmacallan */ 182dbbd9e4bSmacallan p->wid_table.wid_shift = 0; 183dbbd9e4bSmacallan 184dbbd9e4bSmacallan dac->cfg = FFBDAC_CFG_UCTRL; 185dbbd9e4bSmacallan uctrl = dac->cfgdata; 186dbbd9e4bSmacallan uctrl &= ~FFBDAC_UCTRL_WMODE; 187dbbd9e4bSmacallan uctrl |= FFBDAC_UCTRL_WM_COMB; 188dbbd9e4bSmacallan uctrl &= ~FFBDAC_UCTRL_OVENAB; 189dbbd9e4bSmacallan dac->cfg = FFBDAC_CFG_UCTRL; 190dbbd9e4bSmacallan dac->cfgdata = uctrl; 191dbbd9e4bSmacallan} 192dbbd9e4bSmacallan 193dbbd9e4bSmacallanvoid 194dbbd9e4bSmacallanFFBWidPoolInit(FFBPtr pFfb) 195dbbd9e4bSmacallan{ 196dbbd9e4bSmacallan determine_numwids(pFfb); 197dbbd9e4bSmacallan init_wid_table(pFfb); 198dbbd9e4bSmacallan init_hw_wids(pFfb); 199dbbd9e4bSmacallan init_hw_widmode(pFfb); 200dbbd9e4bSmacallan} 201dbbd9e4bSmacallan 202dbbd9e4bSmacallanstatic void 203dbbd9e4bSmacallanupdate_wids(FFBPtr pFfb, int index) 204dbbd9e4bSmacallan{ 205dbbd9e4bSmacallan ffb_dac_info_t *p = &pFfb->dac_info; 206dbbd9e4bSmacallan ffb_dacPtr dac = pFfb->dac; 207dbbd9e4bSmacallan unsigned int base; 208dbbd9e4bSmacallan int limit; 209dbbd9e4bSmacallan 210dbbd9e4bSmacallan if (pFfb->vtSema) 211dbbd9e4bSmacallan return; 212dbbd9e4bSmacallan 213dbbd9e4bSmacallan if (p->flags & FFB_DAC_PAC1) 214dbbd9e4bSmacallan base = FFBDAC_PAC1_SPWLUT(index); 215dbbd9e4bSmacallan else 216dbbd9e4bSmacallan base = FFBDAC_PAC2_SPWLUT(index); 217dbbd9e4bSmacallan DACCFG_WRITE(dac, base, p->wid_table.wid_pool[index].wlut_regval); 218dbbd9e4bSmacallan 219dbbd9e4bSmacallan /* Schedule the window transfer. */ 220dbbd9e4bSmacallan DACCFG_WRITE(dac, FFBDAC_CFG_WTCTRL, 221dbbd9e4bSmacallan (FFBDAC_CFG_WTCTRL_TCMD | FFBDAC_CFG_WTCTRL_TE)); 222dbbd9e4bSmacallan 223dbbd9e4bSmacallan limit = 1000000; 224dbbd9e4bSmacallan while (limit--) { 225dbbd9e4bSmacallan unsigned int wtctrl = DACCFG_READ(dac, FFBDAC_CFG_WTCTRL); 226dbbd9e4bSmacallan 227dbbd9e4bSmacallan if ((wtctrl & FFBDAC_CFG_WTCTRL_DS) == 0) 228dbbd9e4bSmacallan break; 229dbbd9e4bSmacallan } 230dbbd9e4bSmacallan} 231dbbd9e4bSmacallan 232dbbd9e4bSmacallanunsigned int 233dbbd9e4bSmacallanFFBWidAlloc(FFBPtr pFfb, int visclass, int cmap, Bool canshare) 234dbbd9e4bSmacallan{ 235dbbd9e4bSmacallan ffb_dac_info_t *p = &pFfb->dac_info; 236dbbd9e4bSmacallan ffb_wid_pool_t *table = &p->wid_table; 237dbbd9e4bSmacallan int i, depth, direct, static_greyscale, palette, channel; 238dbbd9e4bSmacallan 239dbbd9e4bSmacallan direct = 0; 240dbbd9e4bSmacallan static_greyscale = 0; 241dbbd9e4bSmacallan switch (visclass) { 242dbbd9e4bSmacallan case StaticGray: 243dbbd9e4bSmacallan static_greyscale = 1; 244dbbd9e4bSmacallan /* Fallthrough... */ 245dbbd9e4bSmacallan case StaticColor: 246dbbd9e4bSmacallan case GrayScale: 247dbbd9e4bSmacallan case PseudoColor: 248dbbd9e4bSmacallan depth = 8; 249dbbd9e4bSmacallan channel = 1; 250dbbd9e4bSmacallan break; 251dbbd9e4bSmacallan 252dbbd9e4bSmacallan case DirectColor: 253dbbd9e4bSmacallan direct = 1; 254dbbd9e4bSmacallan /* Fallthrough... */ 255dbbd9e4bSmacallan case TrueColor: 256dbbd9e4bSmacallan depth = 24; 257dbbd9e4bSmacallan channel = 0; 258dbbd9e4bSmacallan break; 259dbbd9e4bSmacallan 260dbbd9e4bSmacallan default: 261dbbd9e4bSmacallan return (unsigned int) -1; 262dbbd9e4bSmacallan }; 263dbbd9e4bSmacallan 264dbbd9e4bSmacallan palette = -1; 265dbbd9e4bSmacallan if (p->flags & FFB_DAC_PAC1) { 266dbbd9e4bSmacallan if (visclass == PseudoColor || 267dbbd9e4bSmacallan visclass == GrayScale || 268dbbd9e4bSmacallan visclass == DirectColor) 269dbbd9e4bSmacallan palette = 0; 270dbbd9e4bSmacallan } else { 271dbbd9e4bSmacallan if (visclass == PseudoColor) 272dbbd9e4bSmacallan palette = 0; 273dbbd9e4bSmacallan if (visclass == GrayScale) 274dbbd9e4bSmacallan palette = 1; 275dbbd9e4bSmacallan if (visclass == DirectColor) 276dbbd9e4bSmacallan palette = 2; 277dbbd9e4bSmacallan } 278dbbd9e4bSmacallan 279dbbd9e4bSmacallan if (canshare) { 280dbbd9e4bSmacallan for (i = 0; i < table->num_wids; i++) { 281dbbd9e4bSmacallan if (table->wid_pool[i].InUse == TRUE && 282dbbd9e4bSmacallan table->wid_pool[i].canshare == TRUE && 283dbbd9e4bSmacallan table->wid_pool[i].palette == palette && 284dbbd9e4bSmacallan table->wid_pool[i].direct == direct && 285dbbd9e4bSmacallan table->wid_pool[i].greyscale == static_greyscale && 286dbbd9e4bSmacallan table->wid_pool[i].channel == channel && 287dbbd9e4bSmacallan table->wid_pool[i].depth == depth) { 288dbbd9e4bSmacallan table->wid_pool[i].refcount++; 289dbbd9e4bSmacallan return i << table->wid_shift; 290dbbd9e4bSmacallan } 291dbbd9e4bSmacallan } 292dbbd9e4bSmacallan } 293dbbd9e4bSmacallan 294dbbd9e4bSmacallan for (i = 0; i < table->num_wids; i++) { 295dbbd9e4bSmacallan if (table->wid_pool[i].InUse == FALSE) 296dbbd9e4bSmacallan break; 297dbbd9e4bSmacallan } 298dbbd9e4bSmacallan 299dbbd9e4bSmacallan if (i != table->num_wids) { 300dbbd9e4bSmacallan table->wid_pool[i].InUse = TRUE; 301dbbd9e4bSmacallan table->wid_pool[i].buffer = 0; 302dbbd9e4bSmacallan table->wid_pool[i].depth = depth; 303dbbd9e4bSmacallan table->wid_pool[i].palette = palette; 304dbbd9e4bSmacallan table->wid_pool[i].direct = direct; 305dbbd9e4bSmacallan table->wid_pool[i].greyscale = static_greyscale; 306dbbd9e4bSmacallan if (depth == 8) 307dbbd9e4bSmacallan table->wid_pool[i].channel = 1; 308dbbd9e4bSmacallan else 309dbbd9e4bSmacallan table->wid_pool[i].channel = 0; 310dbbd9e4bSmacallan table->wid_pool[i].refcount = 1; 311dbbd9e4bSmacallan table->wid_pool[i].canshare = canshare; 312dbbd9e4bSmacallan make_wlut_regval(p, &table->wid_pool[i]); 313dbbd9e4bSmacallan update_wids(pFfb, i); 314dbbd9e4bSmacallan return i << table->wid_shift; 315dbbd9e4bSmacallan } 316dbbd9e4bSmacallan 317dbbd9e4bSmacallan return (unsigned int) -1; 318dbbd9e4bSmacallan} 319dbbd9e4bSmacallan 320dbbd9e4bSmacallanvoid 321dbbd9e4bSmacallanFFBWidFree(FFBPtr pFfb, unsigned int wid) 322dbbd9e4bSmacallan{ 323dbbd9e4bSmacallan ffb_dac_info_t *p = &pFfb->dac_info; 324dbbd9e4bSmacallan ffb_wid_pool_t *table = &p->wid_table; 325dbbd9e4bSmacallan int index = wid >> table->wid_shift; 326dbbd9e4bSmacallan 327dbbd9e4bSmacallan if (index < 0 || index >= table->num_wids) { 328dbbd9e4bSmacallan return; 329dbbd9e4bSmacallan } 330dbbd9e4bSmacallan 331dbbd9e4bSmacallan if (--table->wid_pool[index].refcount == 0) { 332dbbd9e4bSmacallan table->wid_pool[index].InUse = FALSE; 333dbbd9e4bSmacallan } 334dbbd9e4bSmacallan} 335dbbd9e4bSmacallan 336dbbd9e4bSmacallan/* Double Buffering support. */ 337dbbd9e4bSmacallan 338dbbd9e4bSmacallanunsigned int 339dbbd9e4bSmacallanFFBWidUnshare(FFBPtr pFfb, unsigned int wid) 340dbbd9e4bSmacallan{ 341dbbd9e4bSmacallan ffb_dac_info_t *p = &pFfb->dac_info; 342dbbd9e4bSmacallan ffb_wid_pool_t *table = &p->wid_table; 343dbbd9e4bSmacallan int index = wid >> table->wid_shift; 344dbbd9e4bSmacallan int i; 345dbbd9e4bSmacallan 346dbbd9e4bSmacallan if (index < 0 || index >= table->num_wids) { 347dbbd9e4bSmacallan return (unsigned int) -1; 348dbbd9e4bSmacallan } 349dbbd9e4bSmacallan 350dbbd9e4bSmacallan for (i = 0; i < table->num_wids; i++) { 351dbbd9e4bSmacallan if (table->wid_pool[i].InUse == FALSE) 352dbbd9e4bSmacallan break; 353dbbd9e4bSmacallan } 354dbbd9e4bSmacallan 355dbbd9e4bSmacallan if (i == table->num_wids) { 356dbbd9e4bSmacallan return (unsigned int) -1; 357dbbd9e4bSmacallan } 358dbbd9e4bSmacallan 359dbbd9e4bSmacallan table->wid_pool[i].InUse = TRUE; 360dbbd9e4bSmacallan table->wid_pool[i].buffer = 0; 361dbbd9e4bSmacallan table->wid_pool[i].depth = table->wid_pool[index].depth; 362dbbd9e4bSmacallan table->wid_pool[i].palette = table->wid_pool[index].palette; 363dbbd9e4bSmacallan table->wid_pool[i].direct = table->wid_pool[index].direct; 364dbbd9e4bSmacallan table->wid_pool[i].greyscale = table->wid_pool[index].greyscale; 365dbbd9e4bSmacallan table->wid_pool[i].channel = table->wid_pool[index].channel; 366dbbd9e4bSmacallan table->wid_pool[i].refcount = 1; 367dbbd9e4bSmacallan table->wid_pool[i].canshare = FALSE; 368dbbd9e4bSmacallan make_wlut_regval(p, &table->wid_pool[i]); 369dbbd9e4bSmacallan update_wids(pFfb, i); 370dbbd9e4bSmacallan 371dbbd9e4bSmacallan /* Now free the original WID. */ 372dbbd9e4bSmacallan if (--table->wid_pool[index].refcount == 0) { 373dbbd9e4bSmacallan table->wid_pool[index].InUse = FALSE; 374dbbd9e4bSmacallan } 375dbbd9e4bSmacallan 376dbbd9e4bSmacallan return i << table->wid_shift; 377dbbd9e4bSmacallan} 378dbbd9e4bSmacallan 379dbbd9e4bSmacallanunsigned int 380dbbd9e4bSmacallanFFBWidReshare(FFBPtr pFfb, unsigned int wid) 381dbbd9e4bSmacallan{ 382dbbd9e4bSmacallan ffb_dac_info_t *p = &pFfb->dac_info; 383dbbd9e4bSmacallan ffb_wid_pool_t *table = &p->wid_table; 384dbbd9e4bSmacallan int index = wid >> table->wid_shift; 385dbbd9e4bSmacallan int i; 386dbbd9e4bSmacallan 387dbbd9e4bSmacallan if (index < 0 || index >= table->num_wids) { 388dbbd9e4bSmacallan return wid; 389dbbd9e4bSmacallan } 390dbbd9e4bSmacallan 391dbbd9e4bSmacallan for (i = 0; i < table->num_wids; i++) { 392dbbd9e4bSmacallan if (table->wid_pool[i].InUse == TRUE && 393dbbd9e4bSmacallan table->wid_pool[i].canshare == TRUE && 394dbbd9e4bSmacallan table->wid_pool[i].depth == table->wid_pool[index].depth && 395dbbd9e4bSmacallan table->wid_pool[i].palette == table->wid_pool[index].palette && 396dbbd9e4bSmacallan table->wid_pool[i].direct == table->wid_pool[index].direct && 397dbbd9e4bSmacallan table->wid_pool[i].greyscale == table->wid_pool[index].greyscale && 398dbbd9e4bSmacallan table->wid_pool[i].channel == table->wid_pool[index].channel) 399dbbd9e4bSmacallan break; 400dbbd9e4bSmacallan } 401dbbd9e4bSmacallan 402dbbd9e4bSmacallan if (i == table->num_wids) { 403dbbd9e4bSmacallan /* OK, very simple, just make the old one shared. */ 404dbbd9e4bSmacallan table->wid_pool[index].canshare = TRUE; 405dbbd9e4bSmacallan table->wid_pool[index].buffer = 0; 406dbbd9e4bSmacallan make_wlut_regval(p, &table->wid_pool[index]); 407dbbd9e4bSmacallan update_wids(pFfb, index); 408dbbd9e4bSmacallan return wid; 409dbbd9e4bSmacallan } 410dbbd9e4bSmacallan 411dbbd9e4bSmacallan /* Ok, free the original WID. */ 412dbbd9e4bSmacallan if (--table->wid_pool[index].refcount == 0) { 413dbbd9e4bSmacallan table->wid_pool[index].InUse = FALSE; 414dbbd9e4bSmacallan } 415dbbd9e4bSmacallan 416dbbd9e4bSmacallan /* And grab a reference to the new one. */ 417dbbd9e4bSmacallan table->wid_pool[i].refcount++; 418dbbd9e4bSmacallan 419dbbd9e4bSmacallan /* And return the shared one. */ 420dbbd9e4bSmacallan return i << table->wid_shift; 421dbbd9e4bSmacallan} 422dbbd9e4bSmacallan 423dbbd9e4bSmacallanvoid 424dbbd9e4bSmacallanFFBWidChangeBuffer(FFBPtr pFfb, unsigned int wid, int visible) 425dbbd9e4bSmacallan{ 426dbbd9e4bSmacallan ffb_dac_info_t *p = &pFfb->dac_info; 427dbbd9e4bSmacallan ffb_wid_pool_t *table = &p->wid_table; 428dbbd9e4bSmacallan int index = wid >> table->wid_shift; 429dbbd9e4bSmacallan int buffer; 430dbbd9e4bSmacallan 431dbbd9e4bSmacallan if (index < 0 || index >= table->num_wids) 432dbbd9e4bSmacallan return; 433dbbd9e4bSmacallan 434dbbd9e4bSmacallan buffer = (table->wid_pool[index].buffer ^= 1); 435dbbd9e4bSmacallan if (visible) { 436dbbd9e4bSmacallan unsigned int bit; 437dbbd9e4bSmacallan 438dbbd9e4bSmacallan if (p->flags & FFB_DAC_PAC1) 439dbbd9e4bSmacallan bit = FFBDAC_PAC1_WLUT_DB; 440dbbd9e4bSmacallan else 441dbbd9e4bSmacallan bit = FFBDAC_PAC2_WLUT_DB; 442dbbd9e4bSmacallan 443dbbd9e4bSmacallan if (buffer) 444dbbd9e4bSmacallan table->wid_pool[index].wlut_regval |= bit; 445dbbd9e4bSmacallan else 446dbbd9e4bSmacallan table->wid_pool[index].wlut_regval &= ~bit; 447dbbd9e4bSmacallan 448dbbd9e4bSmacallan update_wids(pFfb, index); 449dbbd9e4bSmacallan } 450dbbd9e4bSmacallan} 451