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