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