1a6b33934Smacallan/*
2a6b33934Smacallan * SBus Weitek P9100 driver
3a6b33934Smacallan *
4a6b33934Smacallan * Copyright (C) 2005, 2006 Michael Lorenz
5a6b33934Smacallan *
6a6b33934Smacallan * Permission is hereby granted, free of charge, to any person obtaining a copy
7a6b33934Smacallan * of this software and associated documentation files (the "Software"), to deal
8a6b33934Smacallan * in the Software without restriction, including without limitation the rights
9a6b33934Smacallan * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10a6b33934Smacallan * copies of the Software, and to permit persons to whom the Software is
11a6b33934Smacallan * furnished to do so, subject to the following conditions:
12a6b33934Smacallan *
13a6b33934Smacallan * The above copyright notice and this permission notice shall be included in
14a6b33934Smacallan * all copies or substantial portions of the Software.
15a6b33934Smacallan *
16a6b33934Smacallan * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17a6b33934Smacallan * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18a6b33934Smacallan * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19a6b33934Smacallan * MICHAEL LORENZ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20a6b33934Smacallan * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21a6b33934Smacallan * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22a6b33934Smacallan */
23f55eacdeSjdc/* $NetBSD: pnozz_driver.c,v 1.7 2021/05/27 04:48:10 jdc Exp $ */
24a6b33934Smacallan
25a6b33934Smacallan/*
26a6b33934Smacallan * this driver has been tested on SPARCbook 3GX and 3TX, it supports full
27a6b33934Smacallan * acceleration in 8, 16 and 24 bit colour
28a6b33934Smacallan */
29a6b33934Smacallan
30f55eacdeSjdc#ifdef HAVE_CONFIG_H
31f55eacdeSjdc#include "config.h"
32f55eacdeSjdc#endif
33f55eacdeSjdc
34d046d9f8Smacallan#include <sys/ioctl.h>
35a6b33934Smacallan
36f55eacdeSjdc#include "pnozz.h"
37a6b33934Smacallan#include "xf86.h"
38a6b33934Smacallan#include "xf86_OSproc.h"
39a6b33934Smacallan#include "mipointer.h"
40a6b33934Smacallan#include "micmap.h"
41a6b33934Smacallan
42f55eacdeSjdc#define DEBUG 1
43a6b33934Smacallan
44a6b33934Smacallan#include "fb.h"
45a6b33934Smacallan#include "xf86cmap.h"
46a6b33934Smacallan
47f55eacdeSjdc#include "compat-api.h"
481b41fcf5Smrg
49a6b33934Smacallanstatic const OptionInfoRec * PnozzAvailableOptions(int chipid, int busid);
50a6b33934Smacallanstatic void	PnozzIdentify(int flags);
51a6b33934Smacallanstatic Bool	PnozzProbe(DriverPtr drv, int flags);
52a6b33934Smacallanstatic Bool	PnozzPreInit(ScrnInfoPtr pScrn, int flags);
53f55eacdeSjdcstatic Bool	PnozzScreenInit(SCREEN_INIT_ARGS_DECL);
54f55eacdeSjdcstatic Bool	PnozzEnterVT(VT_FUNC_ARGS_DECL);
55f55eacdeSjdcstatic void	PnozzLeaveVT(VT_FUNC_ARGS_DECL);
56f55eacdeSjdcstatic Bool	PnozzCloseScreen(CLOSE_SCREEN_ARGS_DECL);
57a6b33934Smacallanstatic Bool	PnozzSaveScreen(ScreenPtr pScreen, int mode);
58a6b33934Smacallan
59a6b33934Smacallan/* Required if the driver supports mode switching */
60f55eacdeSjdcstatic Bool	PnozzSwitchMode(SWITCH_MODE_ARGS_DECL);
61a6b33934Smacallan/* Required if the driver supports moving the viewport */
62f55eacdeSjdcstatic void	PnozzAdjustFrame(ADJUST_FRAME_ARGS_DECL);
63a6b33934Smacallan
64a6b33934Smacallan/* Optional functions */
65f55eacdeSjdcstatic void	PnozzFreeScreen(FREE_SCREEN_ARGS_DECL);
66f55eacdeSjdcstatic ModeStatus PnozzValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode,
67a6b33934Smacallan			       Bool verbose, int flags);
68a6b33934Smacallan
69a6b33934Smacallanvoid PnozzSync(ScrnInfoPtr);
70a6b33934Smacallanvoid PnozzSave(PnozzPtr);
71a6b33934Smacallanvoid PnozzRestore(PnozzPtr);
72a6b33934Smacallanint PnozzSetDepth(PnozzPtr, int);	/* return true or false */
73a6b33934Smacallanvoid DumpSCR(unsigned int);
74a6b33934Smacallan
75a6b33934Smacallanstatic void PnozzLoadPalette(ScrnInfoPtr, int, int *, LOCO *, VisualPtr);
76a6b33934Smacallan
77a6b33934Smacallan#define VERSION 4000
78a6b33934Smacallan#define PNOZZ_NAME "p9100"
79a6b33934Smacallan#define PNOZZ_DRIVER_NAME "pnozz"
80f55eacdeSjdc#define PNOZZ_MAJOR_VERSION 2
81a6b33934Smacallan#define PNOZZ_MINOR_VERSION 0
82a6b33934Smacallan#define PNOZZ_PATCHLEVEL 0
83a6b33934Smacallan
84a6b33934Smacallan/*
85a6b33934Smacallan * This contains the functions needed by the server after loading the driver
86a6b33934Smacallan * module.  It must be supplied, and gets passed back by the SetupProc
87a6b33934Smacallan * function in the dynamic case.  In the static case, a reference to this
88a6b33934Smacallan * is compiled in, and this requires that the name of this DriverRec be
89a6b33934Smacallan * an upper-case version of the driver name.
90a6b33934Smacallan */
91a6b33934Smacallan
92a6b33934SmacallanDriverRec PNOZZ = {
93a6b33934Smacallan    VERSION,
94a6b33934Smacallan    PNOZZ_DRIVER_NAME,
95a6b33934Smacallan    PnozzIdentify,
96a6b33934Smacallan    PnozzProbe,
97a6b33934Smacallan    PnozzAvailableOptions,
98a6b33934Smacallan    NULL,
99a6b33934Smacallan    0
100a6b33934Smacallan};
101a6b33934Smacallan
102a6b33934Smacallantypedef enum {
103a6b33934Smacallan    OPTION_SW_CURSOR,
104a6b33934Smacallan    OPTION_HW_CURSOR,
105f55eacdeSjdc    OPTION_NOACCEL,
106f55eacdeSjdc    OPTION_ACCELMETHOD
107a6b33934Smacallan} PnozzOpts;
108a6b33934Smacallan
109a6b33934Smacallanstatic const OptionInfoRec PnozzOptions[] = {
110a6b33934Smacallan    { OPTION_SW_CURSOR,		"SWcursor",	OPTV_BOOLEAN,	{0}, FALSE },
111a6b33934Smacallan    { OPTION_HW_CURSOR,		"HWcursor",	OPTV_BOOLEAN,	{0}, FALSE },
112a6b33934Smacallan    { OPTION_NOACCEL,		"NoAccel",	OPTV_BOOLEAN,	{0}, FALSE },
113f55eacdeSjdc    { OPTION_ACCELMETHOD,	"AccelMethod",	OPTV_STRING,	{0}, FALSE },
114a6b33934Smacallan    { -1,			NULL,		OPTV_NONE,	{0}, FALSE }
115a6b33934Smacallan};
116a6b33934Smacallan
117a6b33934Smacallanstatic const char *ramdacSymbols[] = {
118a6b33934Smacallan    "xf86CreateCursorInfoRec",
119a6b33934Smacallan    "xf86DestroyCursorInfoRec",
120a6b33934Smacallan    "xf86InitCursor",
121a6b33934Smacallan    NULL
122a6b33934Smacallan};
123a6b33934Smacallan
124a6b33934Smacallanstatic const char *fbSymbols[] = {
125a6b33934Smacallan    "fbScreenInit",
126a6b33934Smacallan    "fbPictureInit",
127a6b33934Smacallan    NULL
128a6b33934Smacallan};
129a6b33934Smacallan
130a6b33934Smacallanstatic MODULESETUPPROTO(PnozzSetup);
131a6b33934Smacallan
132a6b33934Smacallanstatic XF86ModuleVersionInfo PnozzVersRec =
133a6b33934Smacallan{
134a6b33934Smacallan	"pnozz",
135a6b33934Smacallan	MODULEVENDORSTRING,
136a6b33934Smacallan	MODINFOSTRING1,
137a6b33934Smacallan	MODINFOSTRING2,
138a6b33934Smacallan	XORG_VERSION_CURRENT,
139a6b33934Smacallan	PNOZZ_MAJOR_VERSION, PNOZZ_MINOR_VERSION, PNOZZ_PATCHLEVEL,
140a6b33934Smacallan	ABI_CLASS_VIDEODRV,
141a6b33934Smacallan	ABI_VIDEODRV_VERSION,
142a6b33934Smacallan	MOD_CLASS_VIDEODRV,
143a6b33934Smacallan	{0,0,0,0}
144a6b33934Smacallan};
145a6b33934Smacallan
146a6b33934SmacallanXF86ModuleData pnozzModuleData = { &PnozzVersRec, PnozzSetup, NULL };
147a6b33934Smacallan
148a6b33934Smacallanpointer
149a6b33934SmacallanPnozzSetup(pointer module, pointer opts, int *errmaj, int *errmin)
150a6b33934Smacallan{
151a6b33934Smacallan    static Bool setupDone = FALSE;
152a6b33934Smacallan
153a6b33934Smacallan    if (!setupDone) {
154a6b33934Smacallan	setupDone = TRUE;
155a6b33934Smacallan	xf86AddDriver(&PNOZZ, module, 0);
156a6b33934Smacallan
157a6b33934Smacallan	/*
158a6b33934Smacallan	 * Modules that this driver always requires can be loaded here
159a6b33934Smacallan	 * by calling LoadSubModule().
160a6b33934Smacallan	 */
161a6b33934Smacallan
162a6b33934Smacallan	/*
163a6b33934Smacallan	 * The return value must be non-NULL on success even though there
164a6b33934Smacallan	 * is no TearDownProc.
165a6b33934Smacallan	 */
166a6b33934Smacallan	return (pointer)TRUE;
167a6b33934Smacallan    } else {
168a6b33934Smacallan	if (errmaj) *errmaj = LDR_ONCEONLY;
169a6b33934Smacallan	return NULL;
170a6b33934Smacallan    }
171a6b33934Smacallan}
172a6b33934Smacallan
173a6b33934Smacallanstatic volatile unsigned int scratch32;
174a6b33934Smacallan
175a6b33934Smacallanvoid pnozz_write_4(PnozzPtr p, int offset, unsigned int value)
176a6b33934Smacallan{
177a6b33934Smacallan	if ((offset & 0xffffff80) != p->offset_mask) {
178a6b33934Smacallan		p->offset_mask = offset & 0xffffff80;
179a6b33934Smacallan		scratch32 = *(volatile unsigned int *)(p->fb + offset);
180a6b33934Smacallan	}
181a6b33934Smacallan	*((volatile unsigned int *)(p->fbc + offset)) = value;
182a6b33934Smacallan}
183a6b33934Smacallan
184a6b33934Smacallanunsigned int pnozz_read_4(PnozzPtr p, int offset)
185a6b33934Smacallan{
186a6b33934Smacallan	if ((offset & 0xffffff80) != p->offset_mask) {
187a6b33934Smacallan		p->offset_mask = offset & 0xffffff80;
188a6b33934Smacallan		scratch32 = *(volatile unsigned int *)(p->fb + offset);
189a6b33934Smacallan	}
190a6b33934Smacallan	return *(volatile unsigned int *)(p->fbc + offset);
191a6b33934Smacallan}
192a6b33934Smacallan
193a6b33934Smacallanvoid pnozz_write_dac(PnozzPtr p, int offset, unsigned char value)
194a6b33934Smacallan{
195a6b33934Smacallan	CARD32 val = ((CARD32)value) << 16;
196a6b33934Smacallan
197a6b33934Smacallan	scratch32 = pnozz_read_4(p, PWRUP_CNFG);
198a6b33934Smacallan	if ((offset != DAC_INDX_DATA) && (offset != DAC_CMAP_DATA)) {
199a6b33934Smacallan		do {
200a6b33934Smacallan			pnozz_write_4(p, offset, val);
201a6b33934Smacallan		} while (pnozz_read_4(p, offset) != val);
202a6b33934Smacallan	} else {
203a6b33934Smacallan		pnozz_write_4(p, offset, val);
204a6b33934Smacallan	}
205a6b33934Smacallan}
206a6b33934Smacallan
207a6b33934Smacallanunsigned char pnozz_read_dac(PnozzPtr p, int offset)
208a6b33934Smacallan{
209a6b33934Smacallan	scratch32 = pnozz_read_4(p, PWRUP_CNFG);
210a6b33934Smacallan	return ((pnozz_read_4(p, offset) >> 16) & 0xff);
211a6b33934Smacallan}
212a6b33934Smacallan
213a6b33934Smacallanvoid pnozz_write_dac_ctl_reg(PnozzPtr p, int offset, unsigned char val)
214a6b33934Smacallan{
215a6b33934Smacallan
216a6b33934Smacallan	pnozz_write_dac(p, DAC_INDX_HI, (offset & 0xff00) >> 8);
217a6b33934Smacallan	pnozz_write_dac(p, DAC_INDX_LO, (offset & 0xff));
218a6b33934Smacallan	pnozz_write_dac(p, DAC_INDX_DATA, val);
219a6b33934Smacallan}
220a6b33934Smacallan
221a6b33934Smacallanvoid pnozz_write_dac_ctl_reg_2(PnozzPtr p, int offset, unsigned short val)
222a6b33934Smacallan{
223a6b33934Smacallan
224a6b33934Smacallan	pnozz_write_dac(p, DAC_INDX_HI, (offset & 0xff00) >> 8);
225a6b33934Smacallan	pnozz_write_dac(p, DAC_INDX_LO, (offset & 0xff));
226a6b33934Smacallan	pnozz_write_dac(p, DAC_INDX_CTL, DAC_INDX_AUTOINCR);
227a6b33934Smacallan	pnozz_write_dac(p, DAC_INDX_DATA, val & 0xff);
228a6b33934Smacallan	pnozz_write_dac(p, DAC_INDX_DATA, (val & 0xff00) >> 8);
229a6b33934Smacallan}
230a6b33934Smacallan
231a6b33934Smacallanunsigned char pnozz_read_dac_ctl_reg(PnozzPtr p, int offset)
232a6b33934Smacallan{
233a6b33934Smacallan	pnozz_write_dac(p, DAC_INDX_HI, (offset & 0xff00) >> 8);
234a6b33934Smacallan	pnozz_write_dac(p, DAC_INDX_LO, (offset & 0xff));
235a6b33934Smacallan	return pnozz_read_dac(p, DAC_INDX_DATA);
236a6b33934Smacallan}
237a6b33934Smacallan
238a6b33934Smacallanvoid pnozz_write_dac_cmap_reg(PnozzPtr p, int offset, unsigned int val)
239a6b33934Smacallan{
240a6b33934Smacallan	pnozz_write_dac(p, DAC_CMAP_WRIDX,(offset & 0xff));
241a6b33934Smacallan	pnozz_write_dac(p, DAC_CMAP_DATA,(val & 0xff));
242a6b33934Smacallan	pnozz_write_dac(p, DAC_CMAP_DATA,(val & 0xff00) >> 8);
243a6b33934Smacallan	pnozz_write_dac(p, DAC_CMAP_DATA,(val & 0xff0000) >> 16);
244a6b33934Smacallan}
245a6b33934Smacallan
246a6b33934Smacallanstatic void
247a6b33934SmacallanPnozzLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors,
248a6b33934Smacallan    VisualPtr pVisual)
249a6b33934Smacallan{
250a6b33934Smacallan    PnozzPtr pPnozz = GET_PNOZZ_FROM_SCRN(pScrn);
251a6b33934Smacallan    int i, index;
252a6b33934Smacallan
253a6b33934Smacallan    PnozzSync(pScrn);
254a6b33934Smacallan    pnozz_write_dac(pPnozz, DAC_INDX_CTL, DAC_INDX_AUTOINCR);
255a6b33934Smacallan
256a6b33934Smacallan    for (i = 0; i < numColors; i++)
257a6b33934Smacallan    {
258a6b33934Smacallan    	index = indices[i];
259a6b33934Smacallan	if (index >= 0) {
260a6b33934Smacallan    	    pnozz_write_dac(pPnozz, DAC_CMAP_WRIDX, index);
261a6b33934Smacallan	    pnozz_write_dac(pPnozz, DAC_CMAP_DATA, colors[index].red);
262a6b33934Smacallan	    pnozz_write_dac(pPnozz, DAC_CMAP_DATA, colors[index].green);
263a6b33934Smacallan	    pnozz_write_dac(pPnozz, DAC_CMAP_DATA, colors[index].blue);
264a6b33934Smacallan	}
265a6b33934Smacallan    }
266a6b33934Smacallan    PnozzSync(pScrn);
267a6b33934Smacallan}
268a6b33934Smacallan
269a6b33934Smacallanstatic Bool
270a6b33934SmacallanPnozzGetRec(ScrnInfoPtr pScrn)
271a6b33934Smacallan{
272a6b33934Smacallan    /*
273a6b33934Smacallan     * Allocate an PnozzRec, and hook it into pScrn->driverPrivate.
274a6b33934Smacallan     * pScrn->driverPrivate is initialised to NULL, so we can check if
275a6b33934Smacallan     * the allocation has already been done.
276a6b33934Smacallan     */
277a6b33934Smacallan    if (pScrn->driverPrivate != NULL)
278a6b33934Smacallan	return TRUE;
279a6b33934Smacallan
280a6b33934Smacallan    pScrn->driverPrivate = xnfcalloc(sizeof(PnozzRec), 1);
281a6b33934Smacallan    return TRUE;
282a6b33934Smacallan}
283a6b33934Smacallan
284a6b33934Smacallanstatic void
285a6b33934SmacallanPnozzFreeRec(ScrnInfoPtr pScrn)
286a6b33934Smacallan{
287a6b33934Smacallan    PnozzPtr pPnozz;
288a6b33934Smacallan
289a6b33934Smacallan    if (pScrn->driverPrivate == NULL)
290a6b33934Smacallan	return;
291a6b33934Smacallan
292a6b33934Smacallan    pPnozz = GET_PNOZZ_FROM_SCRN(pScrn);
293a6b33934Smacallan
294f55eacdeSjdc    free(pScrn->driverPrivate);
295a6b33934Smacallan    pScrn->driverPrivate = NULL;
296a6b33934Smacallan
297a6b33934Smacallan    return;
298a6b33934Smacallan}
299a6b33934Smacallan
300a6b33934Smacallanstatic const OptionInfoRec *
301a6b33934SmacallanPnozzAvailableOptions(int chipid, int busid)
302a6b33934Smacallan{
303a6b33934Smacallan    return PnozzOptions;
304a6b33934Smacallan}
305a6b33934Smacallan
306a6b33934Smacallan/* Mandatory */
307a6b33934Smacallanstatic void
308a6b33934SmacallanPnozzIdentify(int flags)
309a6b33934Smacallan{
310a6b33934Smacallan    xf86Msg(X_INFO, "%s: driver for Weitek P9100 found in Tadpole SPARCbook 3GX and others\n", PNOZZ_NAME);
311a6b33934Smacallan}
312a6b33934Smacallan
313a6b33934Smacallan
314a6b33934Smacallan/* Mandatory */
315a6b33934Smacallanstatic Bool
316a6b33934SmacallanPnozzProbe(DriverPtr drv, int flags)
317a6b33934Smacallan{
318a6b33934Smacallan    int i;
319a6b33934Smacallan    GDevPtr *devSections;
320a6b33934Smacallan    int *usedChips;
321a6b33934Smacallan    int numDevSections;
322a6b33934Smacallan    int numUsed;
323a6b33934Smacallan    Bool foundScreen = FALSE;
324a6b33934Smacallan    EntityInfoPtr pEnt;
325a6b33934Smacallan
326a6b33934Smacallan    /*
327a6b33934Smacallan     * The aim here is to find all cards that this driver can handle,
328a6b33934Smacallan     * and for the ones not already claimed by another driver, claim the
329a6b33934Smacallan     * slot, and allocate a ScrnInfoRec.
330a6b33934Smacallan     *
331a6b33934Smacallan     * This should be a minimal probe, and it should under no circumstances
332a6b33934Smacallan     * change the state of the hardware.  Because a device is found, don't
333a6b33934Smacallan     * assume that it will be used.  Don't do any initialisations other than
334a6b33934Smacallan     * the required ScrnInfoRec initialisations.  Don't allocate any new
335a6b33934Smacallan     * data structures.
336a6b33934Smacallan     */
337a6b33934Smacallan
338a6b33934Smacallan    /*
339a6b33934Smacallan     * Next we check, if there has been a chipset override in the config file.
340a6b33934Smacallan     * For this we must find out if there is an active device section which
341a6b33934Smacallan     * is relevant, i.e., which has no driver specified or has THIS driver
342a6b33934Smacallan     * specified.
343a6b33934Smacallan     */
344a6b33934Smacallan
345a6b33934Smacallan    if ((numDevSections = xf86MatchDevice(PNOZZ_DRIVER_NAME,
346a6b33934Smacallan					  &devSections)) <= 0) {
347a6b33934Smacallan	/*
348a6b33934Smacallan	 * There's no matching device section in the config file, so quit
349a6b33934Smacallan	 * now.
350a6b33934Smacallan	 */
351a6b33934Smacallan	return FALSE;
352a6b33934Smacallan    }
353a6b33934Smacallan
354a6b33934Smacallan    /*
355a6b33934Smacallan     * We need to probe the hardware first.  We then need to see how this
356a6b33934Smacallan     * fits in with what is given in the config file, and allow the config
357a6b33934Smacallan     * file info to override any contradictions.
358a6b33934Smacallan     */
359a6b33934Smacallan
360a6b33934Smacallan    numUsed = xf86MatchSbusInstances(PNOZZ_NAME, SBUS_DEVICE_P9100,
361a6b33934Smacallan		   devSections, numDevSections,
362a6b33934Smacallan		   drv, &usedChips);
363a6b33934Smacallan
364f55eacdeSjdc    free(devSections);
365a6b33934Smacallan    if (numUsed <= 0)
366a6b33934Smacallan	return FALSE;
367a6b33934Smacallan
368a6b33934Smacallan    if (flags & PROBE_DETECT)
369a6b33934Smacallan	foundScreen = TRUE;
370a6b33934Smacallan    else
371a6b33934Smacallan	for (i = 0; i < numUsed; i++) {
372a6b33934Smacallan	    pEnt = xf86GetEntityInfo(usedChips[i]);
373a6b33934Smacallan
374a6b33934Smacallan	    /*
375a6b33934Smacallan	     * Check that nothing else has claimed the slots.
376a6b33934Smacallan	     */
377a6b33934Smacallan	    if(pEnt->active) {
378a6b33934Smacallan		ScrnInfoPtr pScrn;
379a6b33934Smacallan
380a6b33934Smacallan		/* Allocate a ScrnInfoRec and claim the slot */
381a6b33934Smacallan		pScrn = xf86AllocateScreen(drv, 0);
382a6b33934Smacallan
383a6b33934Smacallan		/* Fill in what we can of the ScrnInfoRec */
384a6b33934Smacallan		pScrn->driverVersion = VERSION;
385a6b33934Smacallan		pScrn->driverName	 = PNOZZ_DRIVER_NAME;
386a6b33934Smacallan		pScrn->name		 = PNOZZ_NAME;
387a6b33934Smacallan		pScrn->Probe	 	 = PnozzProbe;
388a6b33934Smacallan		pScrn->PreInit	 	 = PnozzPreInit;
389a6b33934Smacallan		pScrn->ScreenInit	 = PnozzScreenInit;
390a6b33934Smacallan  		pScrn->SwitchMode	 = PnozzSwitchMode;
391a6b33934Smacallan  		pScrn->AdjustFrame	 = PnozzAdjustFrame;
392a6b33934Smacallan		pScrn->EnterVT		 = PnozzEnterVT;
393a6b33934Smacallan		pScrn->LeaveVT		 = PnozzLeaveVT;
394a6b33934Smacallan		pScrn->FreeScreen	 = PnozzFreeScreen;
395a6b33934Smacallan		pScrn->ValidMode	 = PnozzValidMode;
396a6b33934Smacallan		xf86AddEntityToScreen(pScrn, pEnt->index);
397a6b33934Smacallan		foundScreen = TRUE;
398a6b33934Smacallan	    }
399f55eacdeSjdc	    free(pEnt);
400a6b33934Smacallan    	}
401f55eacdeSjdc    free(usedChips);
402a6b33934Smacallan    return foundScreen;
403a6b33934Smacallan}
404a6b33934Smacallan
405a6b33934Smacallan/* Mandatory */
406a6b33934Smacallanstatic Bool
407a6b33934SmacallanPnozzPreInit(ScrnInfoPtr pScrn, int flags)
408a6b33934Smacallan{
409a6b33934Smacallan    PnozzPtr pPnozz;
410a6b33934Smacallan    sbusDevicePtr psdp;
411a6b33934Smacallan    MessageType from;
412a6b33934Smacallan    rgb defaultWeight = {0, 0, 0};
413a6b33934Smacallan    int i;
414a6b33934Smacallan
415a6b33934Smacallan    if (flags & PROBE_DETECT) return FALSE;
416a6b33934Smacallan
417a6b33934Smacallan    /*
418a6b33934Smacallan     * Note: This function is only called once at server startup, and
419a6b33934Smacallan     * not at the start of each server generation.  This means that
420a6b33934Smacallan     * only things that are persistent across server generations can
421a6b33934Smacallan     * be initialised here.  xf86Screens[] is (pScrn is a pointer to one
422a6b33934Smacallan     * of these).  Privates allocated using xf86AllocateScrnInfoPrivateIndex()
423a6b33934Smacallan     * are too, and should be used for data that must persist across
424a6b33934Smacallan     * server generations.
425a6b33934Smacallan     *
426a6b33934Smacallan     * Per-generation data should be allocated with
427a6b33934Smacallan     * AllocateScreenPrivateIndex() from the ScreenInit() function.
428a6b33934Smacallan     */
429a6b33934Smacallan
430a6b33934Smacallan    /* Allocate the PnozzRec driverPrivate */
431a6b33934Smacallan    if (!PnozzGetRec(pScrn)) {
432a6b33934Smacallan	return FALSE;
433a6b33934Smacallan    }
434a6b33934Smacallan    pPnozz = GET_PNOZZ_FROM_SCRN(pScrn);
435a6b33934Smacallan
436a6b33934Smacallan    /* always mismatch on first access */
437a6b33934Smacallan    pPnozz->offset_mask = 0xffffffff;
438a6b33934Smacallan
439a6b33934Smacallan    /* Set pScrn->monitor */
440a6b33934Smacallan    pScrn->monitor = pScrn->confScreen->monitor;
441a6b33934Smacallan
442a6b33934Smacallan    /* This driver doesn't expect more than one entity per screen */
443a6b33934Smacallan    if (pScrn->numEntities > 1)
444a6b33934Smacallan	return FALSE;
445a6b33934Smacallan    /* This is the general case */
446a6b33934Smacallan    for (i = 0; i < pScrn->numEntities; i++) {
447a6b33934Smacallan	EntityInfoPtr pEnt = xf86GetEntityInfo(pScrn->entityList[i]);
448a6b33934Smacallan
449a6b33934Smacallan	/* PNOZZ is purely SBUS */
450a6b33934Smacallan	if (pEnt->location.type == BUS_SBUS) {
451a6b33934Smacallan	    psdp = xf86GetSbusInfoForEntity(pEnt->index);
452a6b33934Smacallan	    pPnozz->psdp = psdp;
453a6b33934Smacallan	} else
454a6b33934Smacallan	    return FALSE;
455a6b33934Smacallan    }
456a6b33934Smacallan
457a6b33934Smacallan    /*********************
458a6b33934Smacallan    deal with depth
459a6b33934Smacallan    *********************/
460a6b33934Smacallan    if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support32bppFb)) {
461a6b33934Smacallan	return FALSE;
462a6b33934Smacallan    } else {
463a6b33934Smacallan	/* Check that the returned depth is one we support */
464a6b33934Smacallan#ifdef DEBUG
465a6b33934Smacallan	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
466a6b33934Smacallan	    "Depth requested: %d\n", pScrn->depth);
467a6b33934Smacallan#endif
468a6b33934Smacallan	switch (pScrn->depth) {
469a6b33934Smacallan	case 8:
470a6b33934Smacallan	case 16:
471a6b33934Smacallan	case 24:
472a6b33934Smacallan	    /* OK */
473a6b33934Smacallan	    break;
474a6b33934Smacallan	default:
475a6b33934Smacallan	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
476a6b33934Smacallan		       "Given depth (%d) is not supported by this driver\n",
477a6b33934Smacallan		       pScrn->depth);
478a6b33934Smacallan	    return FALSE;
479a6b33934Smacallan	}
480a6b33934Smacallan    }
481a6b33934Smacallan    xf86PrintDepthBpp(pScrn);
482a6b33934Smacallan
483a6b33934Smacallan    /* We use a programmable clock */
484a6b33934Smacallan    pScrn->progClock = TRUE;
485a6b33934Smacallan
486a6b33934Smacallan    /* Set the bits per RGB for 8bpp mode */
487a6b33934Smacallan    if (pScrn->depth == 8)
488a6b33934Smacallan	pScrn->rgbBits = 8;
489a6b33934Smacallan
490a6b33934Smacallan    if (pScrn->depth > 8) {
491a6b33934Smacallan      if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight))
492a6b33934Smacallan        return FALSE;
493a6b33934Smacallan    }
494a6b33934Smacallan
495a6b33934Smacallan    if (!xf86SetDefaultVisual(pScrn, -1)) {
496a6b33934Smacallan      return FALSE;
497a6b33934Smacallan    } else {
498a6b33934Smacallan      /* We don't currently support DirectColor at > 8bpp */
499a6b33934Smacallan      if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) {
500a6b33934Smacallan        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual"
501a6b33934Smacallan		 " (%s) is not supported at depth %d\n",
502a6b33934Smacallan		 xf86GetVisualName(pScrn->defaultVisual), pScrn->depth);
503a6b33934Smacallan        return FALSE;
504a6b33934Smacallan      }
505a6b33934Smacallan    }
506a6b33934Smacallan
507a6b33934Smacallan    /* Collect all of the relevant option flags (fill in pScrn->options) */
508a6b33934Smacallan    xf86CollectOptions(pScrn, NULL);
509a6b33934Smacallan
510a6b33934Smacallan    /* Process the options */
511f55eacdeSjdc    if (!(pPnozz->Options = malloc(sizeof(PnozzOptions))))
512a6b33934Smacallan	return FALSE;
513a6b33934Smacallan
514a6b33934Smacallan    memcpy(pPnozz->Options, PnozzOptions, sizeof(PnozzOptions));
515a6b33934Smacallan    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pPnozz->Options);
516a6b33934Smacallan
517a6b33934Smacallan    /*
518a6b33934Smacallan     * The new cmap code requires this to be initialised.
519a6b33934Smacallan     */
520a6b33934Smacallan
521a6b33934Smacallan    {
522a6b33934Smacallan	Gamma zeros = {0.0, 0.0, 0.0};
523a6b33934Smacallan
524a6b33934Smacallan	if (!xf86SetGamma(pScrn, zeros)) {
525a6b33934Smacallan	    return FALSE;
526a6b33934Smacallan	}
527a6b33934Smacallan    }
528a6b33934Smacallan
529a6b33934Smacallan    /* Set the bits per RGB for 8bpp mode */
530a6b33934Smacallan    from = X_DEFAULT;
531a6b33934Smacallan
532a6b33934Smacallan    /* determine whether we use hardware or software cursor */
533a6b33934Smacallan    pPnozz->HWCursor = TRUE;
534a6b33934Smacallan    if (xf86GetOptValBool(pPnozz->Options, OPTION_HW_CURSOR, &pPnozz->HWCursor))
535a6b33934Smacallan	from = X_CONFIG;
536a6b33934Smacallan    if (xf86ReturnOptValBool(pPnozz->Options, OPTION_SW_CURSOR, FALSE)) {
537a6b33934Smacallan	from = X_CONFIG;
538a6b33934Smacallan	pPnozz->HWCursor = FALSE;
539a6b33934Smacallan    }
540a6b33934Smacallan
541a6b33934Smacallan    xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n",
542a6b33934Smacallan		pPnozz->HWCursor ? "HW" : "SW");
543a6b33934Smacallan
544a6b33934Smacallan    if (xf86ReturnOptValBool(pPnozz->Options, OPTION_NOACCEL, FALSE)) {
545a6b33934Smacallan	pPnozz->NoAccel = TRUE;
546a6b33934Smacallan	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Acceleration disabled\n");
547a6b33934Smacallan    }
548f55eacdeSjdc
549f55eacdeSjdc    pPnozz->useXAA = FALSE;
550f55eacdeSjdc
551f55eacdeSjdc    char *optstr;
552f55eacdeSjdc    optstr = (char *)xf86GetOptValString(pPnozz->Options, OPTION_ACCELMETHOD);
553f55eacdeSjdc    if (optstr == NULL) optstr = "exa";
554f55eacdeSjdc    if (xf86NameCmp(optstr, "xaa") == 0)
555f55eacdeSjdc	pPnozz->useXAA = TRUE;
556a6b33934Smacallan
557a6b33934Smacallan    if (xf86LoadSubModule(pScrn, "fb") == NULL) {
558a6b33934Smacallan	PnozzFreeRec(pScrn);
559a6b33934Smacallan	return FALSE;
560a6b33934Smacallan    }
561a6b33934Smacallan
562a6b33934Smacallan    if (xf86LoadSubModule(pScrn, "ramdac") == NULL) {
563a6b33934Smacallan	PnozzFreeRec(pScrn);
564a6b33934Smacallan	return FALSE;
565a6b33934Smacallan    }
566a6b33934Smacallan
567a6b33934Smacallan    /*********************
568a6b33934Smacallan    set up clock and mode stuff
569a6b33934Smacallan    *********************/
570a6b33934Smacallan
571a6b33934Smacallan    pScrn->progClock = TRUE;
572a6b33934Smacallan
573a6b33934Smacallan    if(pScrn->display->virtualX || pScrn->display->virtualY) {
574a6b33934Smacallan	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
575a6b33934Smacallan		   "Pnozz does not support a virtual desktop\n");
576a6b33934Smacallan	pScrn->display->virtualX = 0;
577a6b33934Smacallan	pScrn->display->virtualY = 0;
578a6b33934Smacallan    }
579a6b33934Smacallan
580a6b33934Smacallan    xf86SbusUseBuiltinMode(pScrn, pPnozz->psdp);
581a6b33934Smacallan    pScrn->currentMode = pScrn->modes;
582a6b33934Smacallan    pScrn->displayWidth = pScrn->virtualX;
583a6b33934Smacallan
584a6b33934Smacallan    /* Set display resolution */
585a6b33934Smacallan    xf86SetDpi(pScrn, 0, 0);
586a6b33934Smacallan
587a6b33934Smacallan    return TRUE;
588a6b33934Smacallan}
589a6b33934Smacallan
590a6b33934Smacallan/* Mandatory */
591a6b33934Smacallan
592a6b33934Smacallan/* This gets called at the start of each server generation */
593a6b33934Smacallan
594a6b33934Smacallanstatic Bool
595f55eacdeSjdcPnozzScreenInit(SCREEN_INIT_ARGS_DECL)
596a6b33934Smacallan{
597f55eacdeSjdc    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
598a6b33934Smacallan    PnozzPtr pPnozz;
599a6b33934Smacallan    VisualPtr visual;
600a6b33934Smacallan    int ret,len=0,i;
601a6b33934Smacallan    unsigned int *regs, pctl, pfb, *fb;
602a6b33934Smacallan
603a6b33934Smacallan    /*
604a6b33934Smacallan     * First get the ScrnInfoRec
605a6b33934Smacallan     */
606a6b33934Smacallan    pScrn = xf86Screens[pScreen->myNum];
607a6b33934Smacallan
608a6b33934Smacallan    pPnozz = GET_PNOZZ_FROM_SCRN(pScrn);
609a6b33934Smacallan
610a6b33934Smacallan    /*
611a6b33934Smacallan     * XXX
612a6b33934Smacallan     * figure out how much video RAM we really have - 2MB is just by far the
613a6b33934Smacallan     * most common size
614a6b33934Smacallan     */
615f55eacdeSjdc    pPnozz->vidmem = 0x200000;	/* map 2MB */
616a6b33934Smacallan    pPnozz->fb =
617f55eacdeSjdc	xf86MapSbusMem (pPnozz->psdp, 0, pPnozz->vidmem);
618a6b33934Smacallan    fb=(unsigned int *)pPnozz->fb;
619a6b33934Smacallan
620a6b33934Smacallan    pPnozz->fbc =
621f55eacdeSjdc	xf86MapSbusMem (pPnozz->psdp, pPnozz->vidmem,0x8000);	/* map registers */
622f55eacdeSjdc
623f55eacdeSjdc    if (! pPnozz->fbc) {
624f55eacdeSjdc	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
625f55eacdeSjdc		"xf86MapSbusMem failed fbc:%p fb:%p\n",
626f55eacdeSjdc		pPnozz->fbc, pPnozz->fb);
627f55eacdeSjdc
628f55eacdeSjdc	if (pPnozz->fb) {
629f55eacdeSjdc            xf86UnmapSbusMem(pPnozz->psdp, pPnozz->fb, pPnozz->vidmem);
630f55eacdeSjdc            pPnozz->fb = NULL;
631f55eacdeSjdc	}
632a6b33934Smacallan
633a6b33934Smacallan	return FALSE;
634f55eacdeSjdc    }
635a6b33934Smacallan
636a6b33934Smacallan    /*
637a6b33934Smacallan     * The next step is to setup the screen's visuals, and initialise the
638a6b33934Smacallan     * framebuffer code.  In cases where the framebuffer's default
639a6b33934Smacallan     * choices for things like visual layouts and bits per RGB are OK,
640a6b33934Smacallan     * this may be as simple as calling the framebuffer's ScreenInit()
641a6b33934Smacallan     * function.  If not, the visuals will need to be setup before calling
642a6b33934Smacallan     * a fb ScreenInit() function and fixed up after.
643a6b33934Smacallan     */
644a6b33934Smacallan
645a6b33934Smacallan    /*
646a6b33934Smacallan     * Reset visual list.
647a6b33934Smacallan     */
648a6b33934Smacallan    miClearVisualTypes();
649a6b33934Smacallan
650a6b33934Smacallan#ifdef DEBUG
651a6b33934Smacallan    xf86Msg(X_ERROR, "depth: %d, bpp: %d\n", pScrn->depth, pScrn->bitsPerPixel);
652a6b33934Smacallan#endif
653a6b33934Smacallan    switch (pScrn->bitsPerPixel) {
654a6b33934Smacallan    	case 8:
655a6b33934Smacallan	    pPnozz->depthshift = 0;
656a6b33934Smacallan	    break;
657a6b33934Smacallan    	case 16:
658a6b33934Smacallan	    pPnozz->depthshift = 1;
659a6b33934Smacallan	    break;
660a6b33934Smacallan    	case 32:
661a6b33934Smacallan	    pPnozz->depthshift = 2;
662a6b33934Smacallan	    break;
663a6b33934Smacallan	default:
664a6b33934Smacallan	    return FALSE;
665a6b33934Smacallan    }
666a6b33934Smacallan    pPnozz->width = pScrn->virtualX;
667a6b33934Smacallan    pPnozz->height = pScrn->virtualY;
668a6b33934Smacallan    pPnozz->scanlinesize = pScrn->virtualX << pPnozz->depthshift;
669a6b33934Smacallan
670a6b33934Smacallan    PnozzSave(pPnozz);
671a6b33934Smacallan
672a6b33934Smacallan    /*
673a6b33934Smacallan     * ok, let's switch to whatever depth That Guy Out There wants.
674a6b33934Smacallan     * We won't switch video mode, only colour depth -
675a6b33934Smacallan     */
676a6b33934Smacallan    if(!PnozzSetDepth(pPnozz, pScrn->bitsPerPixel))
677a6b33934Smacallan    	return FALSE;
678a6b33934Smacallan
679a6b33934Smacallan    /* Setup the visuals we support. */
680a6b33934Smacallan
681a6b33934Smacallan    if (!miSetVisualTypes(pScrn->depth, miGetDefaultVisualMask(pScrn->depth),
682a6b33934Smacallan			  pScrn->rgbBits, pScrn->defaultVisual))
683a6b33934Smacallan	return FALSE;
684a6b33934Smacallan
685a6b33934Smacallan    miSetPixmapDepths();
686a6b33934Smacallan
687a6b33934Smacallan    /*
688a6b33934Smacallan     * Call the framebuffer layer's ScreenInit function, and fill in other
689a6b33934Smacallan     * pScreen fields.
690a6b33934Smacallan     */
691a6b33934Smacallan#if DEBUG
692a6b33934Smacallan    xf86Msg(X_ERROR, "sls: %d\n", pPnozz->scanlinesize);
693a6b33934Smacallan#endif
694a6b33934Smacallan    ret = fbScreenInit(pScreen, pPnozz->fb, pScrn->virtualX,
695a6b33934Smacallan		       pScrn->virtualY, pScrn->xDpi, pScrn->yDpi,
696a6b33934Smacallan		       pScrn->displayWidth, pScrn->bitsPerPixel);
697a6b33934Smacallan
698a6b33934Smacallan    /* should be set by PnozzSetDepth() */
699f55eacdeSjdc    pPnozz->maxheight = (pPnozz->vidmem / pPnozz->scanlinesize) & 0xffff;
700a6b33934Smacallan#if DEBUG
701a6b33934Smacallan    xf86Msg(X_ERROR, "max scanlines: %d\n", pPnozz->maxheight);
702a6b33934Smacallan#endif
703a6b33934Smacallan    if (!ret)
704a6b33934Smacallan	return FALSE;
705a6b33934Smacallan
706a6b33934Smacallan    if (pScrn->bitsPerPixel > 8) {
707a6b33934Smacallan      visual = pScreen->visuals + pScreen->numVisuals;
708a6b33934Smacallan      while (--visual >= pScreen->visuals) {
709a6b33934Smacallan        if ((visual->class | DynamicClass) == DirectColor) {
710a6b33934Smacallan	  visual->offsetRed = pScrn->offset.red;
711a6b33934Smacallan	  visual->offsetGreen = pScrn->offset.green;
712a6b33934Smacallan	  visual->offsetBlue = pScrn->offset.blue;
713a6b33934Smacallan	  visual->redMask = pScrn->mask.red;
714a6b33934Smacallan	  visual->greenMask = pScrn->mask.green;
715a6b33934Smacallan	  visual->blueMask = pScrn->mask.blue;
716a6b33934Smacallan        }
717a6b33934Smacallan      }
718a6b33934Smacallan    }
719a6b33934Smacallan
720a6b33934Smacallan    fbPictureInit(pScreen, 0, 0);
721a6b33934Smacallan
722a6b33934Smacallan    xf86SetBackingStore(pScreen);
723a6b33934Smacallan    xf86SetSilkenMouse(pScreen);
724a6b33934Smacallan    xf86SetBlackWhitePixels(pScreen);
725a6b33934Smacallan
726a6b33934Smacallan    if (!pPnozz->NoAccel) {
727f55eacdeSjdc#ifdef HAVE_XAA_H
728f55eacdeSjdc	if (pPnozz->useXAA) {
729f55eacdeSjdc            BoxRec bx;
730f55eacdeSjdc            pPnozz->pXAA = XAACreateInfoRec();
731f55eacdeSjdc            PnozzAccelInit(pScrn);
732f55eacdeSjdc            bx.x1 = bx.y1 = 0;
733f55eacdeSjdc            bx.x2 = pPnozz->width;
734f55eacdeSjdc            bx.y2 = pPnozz->maxheight;
735f55eacdeSjdc            xf86InitFBManager(pScreen, &bx);
736f55eacdeSjdc            if(!XAAInit(pScreen, pPnozz->pXAA))
737f55eacdeSjdc                return FALSE;
738f55eacdeSjdc            xf86Msg(X_INFO, "%s: Using XAA acceleration\n", pPnozz->psdp->device);
739f55eacdeSjdc	} else
740f55eacdeSjdc#endif /* HAVE_XAA_H */
741f55eacdeSjdc	{
742f55eacdeSjdc            /* EXA */
743f55eacdeSjdc            XF86ModReqInfo req;
744f55eacdeSjdc            int errmaj, errmin;
745f55eacdeSjdc
746f55eacdeSjdc            memset(&req, 0, sizeof(XF86ModReqInfo));
747f55eacdeSjdc            req.majorversion = EXA_VERSION_MAJOR;
748f55eacdeSjdc            req.minorversion = EXA_VERSION_MINOR;
749f55eacdeSjdc            if (!LoadSubModule(pScrn->module, "exa", NULL, NULL, NULL, &req,
750f55eacdeSjdc		&errmaj, &errmin)) {
751f55eacdeSjdc		LoaderErrorMsg(NULL, "exa", errmaj, errmin);
752f55eacdeSjdc		return FALSE;
753f55eacdeSjdc            }
754f55eacdeSjdc            if (!PnozzEXAInit(pScreen))
755f55eacdeSjdc		return FALSE;
756f55eacdeSjdc
757f55eacdeSjdc            xf86Msg(X_INFO, "%s: Using EXA acceleration\n", pPnozz->psdp->device);
758f55eacdeSjdc	}
759a6b33934Smacallan    }
760a6b33934Smacallan
761a6b33934Smacallan    /* Initialise cursor functions */
762a6b33934Smacallan    miDCInitialize (pScreen, xf86GetPointerScreenFuncs());
763a6b33934Smacallan
764a6b33934Smacallan    /*
765a6b33934Smacallan     * Initialize HW cursor layer.
766a6b33934Smacallan     * Must follow software cursor initialization
767a6b33934Smacallan     */
768a6b33934Smacallan    xf86SbusHideOsHwCursor(pPnozz->psdp);
769a6b33934Smacallan    if (pPnozz->HWCursor) {
770a6b33934Smacallan	extern Bool PnozzHWCursorInit(ScreenPtr pScreen);
771a6b33934Smacallan
772a6b33934Smacallan	if(!PnozzHWCursorInit(pScreen)) {
773a6b33934Smacallan	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
774a6b33934Smacallan		       "Hardware cursor initialization failed\n");
775a6b33934Smacallan	    return(FALSE);
776a6b33934Smacallan	}
777a6b33934Smacallan    }
778a6b33934Smacallan
779a6b33934Smacallan    /* Initialise default colourmap */
780a6b33934Smacallan    if (!miCreateDefColormap(pScreen))
781a6b33934Smacallan	return FALSE;
782a6b33934Smacallan#if 1
783a6b33934Smacallan    if(!xf86SbusHandleColormaps(pScreen, pPnozz->psdp))
784a6b33934Smacallan#else
785a6b33934Smacallan    if(!xf86HandleColormaps(pScreen, 256, pScrn->rgbBits, PnozzLoadPalette, NULL,
786a6b33934Smacallan        /*CMAP_PALETTED_TRUECOLOR|*/CMAP_RELOAD_ON_MODE_SWITCH))
787a6b33934Smacallan#endif
788a6b33934Smacallan	return FALSE;
789a6b33934Smacallan    pPnozz->CloseScreen = pScreen->CloseScreen;
790a6b33934Smacallan    pScreen->CloseScreen = PnozzCloseScreen;
791a6b33934Smacallan    pScreen->SaveScreen = PnozzSaveScreen;
792a6b33934Smacallan
793a6b33934Smacallan    /* Report any unused options (only for the first generation) */
794a6b33934Smacallan    if (serverGeneration == 1) {
795a6b33934Smacallan	xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
796a6b33934Smacallan    }
797a6b33934Smacallan
798a6b33934Smacallan    /* unblank the screen */
799a6b33934Smacallan    PnozzSaveScreen(pScreen, SCREEN_SAVER_OFF);
800a6b33934Smacallan
801a6b33934Smacallan    /* Done */
802a6b33934Smacallan    return TRUE;
803a6b33934Smacallan}
804a6b33934Smacallan
805a6b33934Smacallan
806a6b33934Smacallan/* Usually mandatory */
807a6b33934Smacallanstatic Bool
808f55eacdeSjdcPnozzSwitchMode(SWITCH_MODE_ARGS_DECL)
809a6b33934Smacallan{
810a6b33934Smacallan    xf86Msg(X_ERROR, "SwitchMode: %d %d %d %d\n", mode->CrtcHTotal,
811a6b33934Smacallan        mode->CrtcHSyncStart, mode->CrtcHSyncEnd, mode->CrtcHDisplay);
812a6b33934Smacallan    return TRUE;
813a6b33934Smacallan}
814a6b33934Smacallan
815a6b33934Smacallan
816a6b33934Smacallan/*
817a6b33934Smacallan * This function is used to initialize the Start Address - the first
818a6b33934Smacallan * displayed location in the video memory.
819a6b33934Smacallan */
820a6b33934Smacallan/* Usually mandatory */
821a6b33934Smacallanstatic void
822f55eacdeSjdcPnozzAdjustFrame(ADJUST_FRAME_ARGS_DECL)
823a6b33934Smacallan{
824a6b33934Smacallan    /* we don't support virtual desktops for now */
825a6b33934Smacallan    return;
826a6b33934Smacallan}
827a6b33934Smacallan
828a6b33934Smacallan/*
829a6b33934Smacallan * This is called when VT switching back to the X server.  Its job is
830a6b33934Smacallan * to reinitialise the video mode.
831a6b33934Smacallan */
832a6b33934Smacallan
833a6b33934Smacallan/* Mandatory */
834a6b33934Smacallanstatic Bool
835f55eacdeSjdcPnozzEnterVT(VT_FUNC_ARGS_DECL)
836a6b33934Smacallan{
837f55eacdeSjdc    SCRN_INFO_PTR(arg);
838a6b33934Smacallan    PnozzPtr pPnozz = GET_PNOZZ_FROM_SCRN(pScrn);
839a6b33934Smacallan
840a6b33934Smacallan    xf86SbusHideOsHwCursor (pPnozz->psdp);
841a6b33934Smacallan    return TRUE;
842a6b33934Smacallan}
843a6b33934Smacallan
844a6b33934Smacallan
845a6b33934Smacallan/*
846a6b33934Smacallan * This is called when VT switching away from the X server.
847a6b33934Smacallan */
848a6b33934Smacallan
849a6b33934Smacallan/* Mandatory */
850a6b33934Smacallanstatic void
851f55eacdeSjdcPnozzLeaveVT(VT_FUNC_ARGS_DECL)
852a6b33934Smacallan{
853a6b33934Smacallan    return;
854a6b33934Smacallan}
855a6b33934Smacallan
856a6b33934Smacallan
857a6b33934Smacallan/*
858a6b33934Smacallan * This is called at the end of each server generation.  It restores the
859a6b33934Smacallan * original (text) mode.  It should really also unmap the video memory too.
860a6b33934Smacallan */
861a6b33934Smacallan
862a6b33934Smacallan/* Mandatory */
863a6b33934Smacallanstatic Bool
864f55eacdeSjdcPnozzCloseScreen(CLOSE_SCREEN_ARGS_DECL)
865a6b33934Smacallan{
866f55eacdeSjdc    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
867a6b33934Smacallan    PnozzPtr pPnozz = GET_PNOZZ_FROM_SCRN(pScrn);
868a6b33934Smacallan    int state = 1;
869a6b33934Smacallan
870a6b33934Smacallan    pScrn->vtSema = FALSE;
871a6b33934Smacallan
872a6b33934Smacallan    if (pPnozz->HWCursor)
873a6b33934Smacallan    	PnozzHideCursor(pScrn);
874a6b33934Smacallan
875a6b33934Smacallan    PnozzRestore(pPnozz);	/* restore colour depth */
876a6b33934Smacallan
877f55eacdeSjdc    xf86UnmapSbusMem(pPnozz->psdp, pPnozz->fb,pPnozz->vidmem);
878a6b33934Smacallan    xf86UnmapSbusMem(pPnozz->psdp, pPnozz->fbc,0x8000);
879a6b33934Smacallan
880a6b33934Smacallan    /* make sure video is turned on */
881a6b33934Smacallan    ioctl(pPnozz->psdp->fd, FBIOSVIDEO, &state);
882a6b33934Smacallan
883a6b33934Smacallan    pScreen->CloseScreen = pPnozz->CloseScreen;
884f55eacdeSjdc    return (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS);
885a6b33934Smacallan}
886a6b33934Smacallan
887a6b33934Smacallan
888a6b33934Smacallan/* Free up any per-generation data structures */
889a6b33934Smacallan
890a6b33934Smacallan/* Optional */
891a6b33934Smacallanstatic void
892f55eacdeSjdcPnozzFreeScreen(FREE_SCREEN_ARGS_DECL)
893a6b33934Smacallan{
894f55eacdeSjdc    SCRN_INFO_PTR(arg);
895f55eacdeSjdc    PnozzFreeRec(pScrn);
896a6b33934Smacallan}
897a6b33934Smacallan
898a6b33934Smacallan
899a6b33934Smacallan/* Checks if a mode is suitable for the selected chipset. */
900a6b33934Smacallan
901a6b33934Smacallan/* Optional */
902a6b33934Smacallanstatic ModeStatus
903f55eacdeSjdcPnozzValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags)
904a6b33934Smacallan{
905a6b33934Smacallan    if (mode->Flags & V_INTERLACE)
906a6b33934Smacallan	return(MODE_BAD);
907a6b33934Smacallan
908a6b33934Smacallan    return(MODE_OK);
909a6b33934Smacallan}
910a6b33934Smacallan
911a6b33934Smacallan/* Do screen blanking */
912a6b33934Smacallan
913a6b33934Smacallan/* Mandatory */
914a6b33934Smacallanstatic Bool
915a6b33934SmacallanPnozzSaveScreen(ScreenPtr pScreen, int mode)
916a6b33934Smacallan{
917a6b33934Smacallan    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
918a6b33934Smacallan    PnozzPtr pPnozz = GET_PNOZZ_FROM_SCRN(pScrn);
919a6b33934Smacallan    int fd = pPnozz->psdp->fd, state;
920a6b33934Smacallan
921a6b33934Smacallan    /*
922a6b33934Smacallan     * we're using ioctl() instead of just whacking the DAC because the
923a6b33934Smacallan     * underlying driver will also turn off the backlight which we couldn't do
924a6b33934Smacallan     * from here without adding lots more hardware dependencies
925a6b33934Smacallan     */
926a6b33934Smacallan    switch(mode)
927a6b33934Smacallan    {
928a6b33934Smacallan	case SCREEN_SAVER_ON:
929a6b33934Smacallan	case SCREEN_SAVER_CYCLE:
930a6b33934Smacallan    		state = 0;
931a6b33934Smacallan		if(ioctl(fd, FBIOSVIDEO, &state) == -1)
932a6b33934Smacallan		{
933a6b33934Smacallan			/* complain */
934a6b33934Smacallan		}
935a6b33934Smacallan		break;
936a6b33934Smacallan	case SCREEN_SAVER_OFF:
937a6b33934Smacallan	case SCREEN_SAVER_FORCER:
938a6b33934Smacallan    		state = 1;
939a6b33934Smacallan		if(ioctl(fd, FBIOSVIDEO, &state) == -1)
940a6b33934Smacallan		{
941a6b33934Smacallan			/* complain */
942a6b33934Smacallan		}
943a6b33934Smacallan		break;
944a6b33934Smacallan	default:
945a6b33934Smacallan		return FALSE;
946a6b33934Smacallan    }
947a6b33934Smacallan    return TRUE;
948a6b33934Smacallan}
949a6b33934Smacallan
950a6b33934Smacallanint shift_1(int b)
951a6b33934Smacallan{
952a6b33934Smacallan    if (b > 0)
953a6b33934Smacallan	return (16 << b);
954a6b33934Smacallan    return 0;
955a6b33934Smacallan}
956a6b33934Smacallan
957a6b33934Smacallanint shift_2(int b)
958a6b33934Smacallan{
959a6b33934Smacallan    if (b > 0)
960a6b33934Smacallan	return (512 << b);
961a6b33934Smacallan    return 0;
962a6b33934Smacallan}
963a6b33934Smacallan
964a6b33934Smacallanvoid
965a6b33934SmacallanPnozzSave(PnozzPtr pPnozz)
966a6b33934Smacallan{
967a6b33934Smacallan	int i;
968a6b33934Smacallan	pPnozz->SvSysConf = pnozz_read_4(pPnozz, SYS_CONF);
969a6b33934Smacallan	pPnozz->SvDAC_MC3 = pnozz_read_dac_ctl_reg(pPnozz, DAC_MISC_3);
970a6b33934Smacallan	pPnozz->SvDAC_MCCR = pnozz_read_dac_ctl_reg(pPnozz, DAC_MISC_CLK);
971a6b33934Smacallan	pPnozz->SvDAC_PF = pnozz_read_dac_ctl_reg(pPnozz, DAC_PIXEL_FMT);
972a6b33934Smacallan	pPnozz->SvPLL = pnozz_read_dac_ctl_reg(pPnozz, DAC_PLL0);
973a6b33934Smacallan	pPnozz->SvVCO = pnozz_read_dac_ctl_reg(pPnozz, DAC_VCO_DIV);
974a6b33934Smacallan	pPnozz->SvMemCtl = pnozz_read_4(pPnozz, VID_MEM_CONFIG);
975a6b33934Smacallan	for (i = 0; i < 4; i++)
976a6b33934Smacallan		pPnozz->CRTC[i] = pnozz_read_4(pPnozz, VID_HTOTAL + (i << 2));
977a6b33934Smacallan	pPnozz->DidSave = 1;
978a6b33934Smacallan#if DEBUG
979a6b33934Smacallan	xf86Msg(X_ERROR, "Saved: %x %x %x %x\n", pPnozz->SvSysConf,
980a6b33934Smacallan	    pPnozz->SvDAC_MCCR, pPnozz->SvDAC_PF, pPnozz->SvDAC_MC3);
981a6b33934Smacallan	DumpSCR(pPnozz->SvSysConf);
982a6b33934Smacallan#endif
983a6b33934Smacallan}
984a6b33934Smacallan
985a6b33934Smacallanvoid DumpSCR(unsigned int scr)
986a6b33934Smacallan{
987a6b33934Smacallan#if DEBUG
988a6b33934Smacallan	int s0, s1, s2, s3, ps;
989a6b33934Smacallan	int width;
990a6b33934Smacallan	ps = (scr >> PIXEL_SHIFT) & 7;
991a6b33934Smacallan	s0 = (scr >> SHIFT_0) & 7;
992a6b33934Smacallan	s1 = (scr >> SHIFT_1) & 7;
993a6b33934Smacallan	s2 = (scr >> SHIFT_2) & 7;
994a6b33934Smacallan	s3 = (scr >> SHIFT_3) & 3;
995a6b33934Smacallan	width = shift_1(s0) + shift_1(s1) + shift_1(s2) + shift_2(s3);
996a6b33934Smacallan	xf86Msg(X_ERROR, "ps: %d wi: %d\n", ps, width);
997a6b33934Smacallan#endif
998a6b33934Smacallan}
999a6b33934Smacallan
1000a6b33934Smacallanvoid DumpDAC(PnozzPtr pPnozz)
1001a6b33934Smacallan{
1002a6b33934Smacallan#if DEBUG
1003a6b33934Smacallan    int addr, i, val;
1004a6b33934Smacallan    char line[256], buffer[16];
1005a6b33934Smacallan    pnozz_write_dac(pPnozz, DAC_INDX_LO, 0);
1006a6b33934Smacallan    pnozz_write_dac(pPnozz, DAC_INDX_HI, 0);
1007a6b33934Smacallan    for (addr = 0; addr < 0x100; addr += 16) {
1008a6b33934Smacallan    	snprintf(line, 16, "%02x:", addr);
1009a6b33934Smacallan	for (i=0;i<16;i++) {
1010a6b33934Smacallan	    val = pnozz_read_dac(pPnozz, DAC_INDX_DATA);
1011a6b33934Smacallan	    snprintf(buffer, 16, " %02x", val);
1012a6b33934Smacallan	    strcat(line, buffer);
1013a6b33934Smacallan	}
1014a6b33934Smacallan	xf86Msg(X_ERROR, "%s\n", line);
1015a6b33934Smacallan    }
1016a6b33934Smacallan#endif
1017a6b33934Smacallan}
1018a6b33934Smacallan
1019a6b33934Smacallanvoid DumpCRTC(PnozzPtr pPnozz)
1020a6b33934Smacallan{
1021a6b33934Smacallan#if DEBUG
1022a6b33934Smacallan    int i;
1023a6b33934Smacallan    unsigned int reg;
1024a6b33934Smacallan    for (i = 0x108; i<0x140; i += 4) {
1025a6b33934Smacallan        reg = pnozz_read_4(pPnozz, i);
1026a6b33934Smacallan	xf86Msg(X_ERROR, "%x / %d ", reg, reg);
1027a6b33934Smacallan    }
1028a6b33934Smacallan    reg = pnozz_read_4(pPnozz, VID_MEM_CONFIG);
1029a6b33934Smacallan    xf86Msg(X_ERROR, "memcfg: %08x\n", reg);
1030a6b33934Smacallan    xf86Msg(X_ERROR, "shiftclk:  %x\n", (reg >> 10) & 7);
1031a6b33934Smacallan    xf86Msg(X_ERROR, "shiftmode: %x\n", (reg >> 22) & 3);
1032a6b33934Smacallan    xf86Msg(X_ERROR, "crtc_clk:  %x\n", (reg >> 13) & 7);
1033a6b33934Smacallan#endif
1034a6b33934Smacallan}
1035a6b33934Smacallan
1036a6b33934Smacallanvoid
1037a6b33934SmacallanPnozzRestore(PnozzPtr pPnozz)
1038a6b33934Smacallan{
1039a6b33934Smacallan    int i;
1040a6b33934Smacallan    if(pPnozz->DidSave == 1) {
1041a6b33934Smacallan	pnozz_write_4(pPnozz, SYS_CONF, pPnozz->SvSysConf);
1042a6b33934Smacallan	pnozz_write_4(pPnozz, VID_MEM_CONFIG, pPnozz->SvMemCtl);
1043a6b33934Smacallan	for (i = 0; i < 4; i++)
1044a6b33934Smacallan	    pnozz_write_4(pPnozz, VID_HTOTAL + (i << 2), pPnozz->CRTC[i]);
1045a6b33934Smacallan
1046a6b33934Smacallan        pnozz_write_dac_ctl_reg(pPnozz, DAC_PLL0, pPnozz->SvPLL);
1047a6b33934Smacallan        pnozz_write_dac_ctl_reg(pPnozz, DAC_MISC_3, pPnozz->SvDAC_MC3);
1048a6b33934Smacallan        pnozz_write_dac_ctl_reg(pPnozz, DAC_MISC_CLK, pPnozz->SvDAC_MCCR);
1049a6b33934Smacallan	pnozz_write_dac_ctl_reg(pPnozz, DAC_PIXEL_FMT, pPnozz->SvDAC_PF);
1050a6b33934Smacallan	pnozz_write_dac_ctl_reg(pPnozz, DAC_VCO_DIV, pPnozz->SvVCO);
1051a6b33934Smacallan    }
1052a6b33934Smacallan}
1053a6b33934Smacallan
1054a6b33934Smacallanunsigned int upper_bit(unsigned int b)
1055a6b33934Smacallan{
1056a6b33934Smacallan	unsigned int mask=0x80000000;
1057a6b33934Smacallan	int cnt = 31;
1058a6b33934Smacallan	if (b == 0)
1059a6b33934Smacallan		return -1;
1060a6b33934Smacallan	while ((mask != 0) && ((b & mask) == 0)) {
1061a6b33934Smacallan		mask = mask >> 1;
1062a6b33934Smacallan		cnt--;
1063a6b33934Smacallan	}
1064a6b33934Smacallan	return cnt;
1065a6b33934Smacallan}
1066a6b33934Smacallan
1067a6b33934Smacallan/*
1068a6b33934Smacallan * To switch colour depth we need to:
1069a6b33934Smacallan * - double or quadruple both crtc and shift clock ( for 16 or 32 bit )
1070a6b33934Smacallan * - double or quadruple scanline length
1071a6b33934Smacallan * - switch the DAC to the appropriate pixel format
1072a6b33934Smacallan * - tell the drawing engine about new line length / pixel size
1073a6b33934Smacallan */
1074a6b33934Smacallan
1075a6b33934Smacallanint
1076a6b33934SmacallanPnozzSetDepth(PnozzPtr pPnozz, int depth)
1077a6b33934Smacallan{
1078a6b33934Smacallan    int new_sls;
1079a6b33934Smacallan    unsigned int bits, scr, sscr, memctl, mem;
1080a6b33934Smacallan    int s0, s1, s2, s3, ps, crtcline;
1081a6b33934Smacallan    unsigned char pf, mc3, es;
1082a6b33934Smacallan
1083f55eacdeSjdc#ifdef DEBUG
1084f55eacdeSjdc    xf86Msg(X_ERROR, "SetDepth: %d\n", depth);
1085a6b33934Smacallan    DumpDAC(pPnozz);
1086a6b33934Smacallan    DumpCRTC(pPnozz);
1087a6b33934Smacallan#endif
1088a6b33934Smacallan
1089a6b33934Smacallan    switch (depth) {
1090a6b33934Smacallan	case 8:
1091a6b33934Smacallan	    pPnozz->depthshift = 0;
1092a6b33934Smacallan	    ps = 2;
1093a6b33934Smacallan	    pf = 3;
1094a6b33934Smacallan	    mc3 = 0;
1095a6b33934Smacallan	    es = 0;	/* no swapping */
1096a6b33934Smacallan	    memctl = 3;
1097a6b33934Smacallan	    break;
1098a6b33934Smacallan	case 16:
1099a6b33934Smacallan	    pPnozz->depthshift = 1;
1100a6b33934Smacallan	    ps = 3;
1101a6b33934Smacallan	    pf = 4;
1102a6b33934Smacallan	    mc3 = 0;
1103a6b33934Smacallan	    es = 2;	/* swap bytes in 16bit words */
1104a6b33934Smacallan	    memctl = 2;
1105a6b33934Smacallan	    break;
1106a6b33934Smacallan	case 24:
1107a6b33934Smacallan	    /* boo */
1108a6b33934Smacallan	    xf86Msg(X_ERROR, "We don't DO 24bit pixels dammit!\n");
1109a6b33934Smacallan	    return 0;
1110a6b33934Smacallan	case 32:
1111a6b33934Smacallan	    pPnozz->depthshift = 2;
1112a6b33934Smacallan	    ps = 5;
1113a6b33934Smacallan	    pf = 6;
1114a6b33934Smacallan	    mc3 = 0;
1115a6b33934Smacallan	    es = 6;	/* swap both half-words and bytes */
1116a6b33934Smacallan	    memctl = 1;	/* 0 */
1117a6b33934Smacallan	    break;
1118a6b33934Smacallan    }
1119a6b33934Smacallan    /*
1120a6b33934Smacallan     * this could be done a lot shorter and faster but then nobody would
1121a6b33934Smacallan     * understand what the hell we're doing here without getting a major
1122a6b33934Smacallan     * headache. Scanline size is encoded as 4 shift values, 3 of them 3 bits
1123a6b33934Smacallan     * wide, 16 << n for n>0, one 2 bits, 512 << n for n>0. n==0 means 0
1124a6b33934Smacallan     */
1125a6b33934Smacallan    new_sls = pPnozz->width << pPnozz->depthshift;
1126a6b33934Smacallan    pPnozz->scanlinesize = new_sls;
1127a6b33934Smacallan    bits = new_sls;
1128a6b33934Smacallan    s3 = upper_bit(bits);
1129a6b33934Smacallan    if (s3 > 9) {
1130a6b33934Smacallan	bits &= ~(1 << s3);
1131a6b33934Smacallan	s3 -= 9;
1132a6b33934Smacallan    } else s3 = 0;
1133a6b33934Smacallan    s2 = upper_bit(bits);
1134a6b33934Smacallan    if (s2 > 0) {
1135a6b33934Smacallan	bits &= ~(1 << s2);
1136a6b33934Smacallan	s2 -= 4;
1137a6b33934Smacallan    } else s2 = 0;
1138a6b33934Smacallan    s1 = upper_bit(bits);
1139a6b33934Smacallan    if (s1 > 0) {
1140a6b33934Smacallan        bits &= ~(1 << s1);
1141a6b33934Smacallan        s1 -= 4;
1142a6b33934Smacallan    } else s1 = 0;
1143a6b33934Smacallan    s0 = upper_bit(bits);
1144a6b33934Smacallan    if (s0 > 0) {
1145a6b33934Smacallan        bits &= ~(1 << s0);
1146a6b33934Smacallan        s0 -= 4;
1147a6b33934Smacallan    } else s0 = 0;
1148a6b33934Smacallan
1149a6b33934Smacallan#if DEBUG
1150a6b33934Smacallan    xf86Msg(X_ERROR, "sls: %x sh: %d %d %d %d leftover: %x\n", new_sls, s0, s1,
1151a6b33934Smacallan        s2, s3, bits);
1152a6b33934Smacallan#endif
1153a6b33934Smacallan
1154a6b33934Smacallan    /*
1155a6b33934Smacallan     * now let's put these values into the System Config Register. No need to
1156a6b33934Smacallan     * read it here since we (hopefully) just saved the content
1157a6b33934Smacallan     */
1158a6b33934Smacallan    scr = pnozz_read_4(pPnozz, SYS_CONF);
1159a6b33934Smacallan    scr = (s0 << SHIFT_0) | (s1 << SHIFT_1) | (s2 << SHIFT_2) |
1160a6b33934Smacallan        (s3 << SHIFT_3) | (ps << PIXEL_SHIFT) | (es << SWAP_SHIFT);
1161a6b33934Smacallan#if DEBUG
1162a6b33934Smacallan    xf86Msg(X_ERROR, "new scr: %x DAC %x %x\n", scr, pf, mc3);
1163a6b33934Smacallan    DumpSCR(scr);
1164a6b33934Smacallan#endif
1165a6b33934Smacallan
1166a6b33934Smacallan    mem = pnozz_read_4(pPnozz, VID_MEM_CONFIG);
1167a6b33934Smacallan#if DEBUG
1168a6b33934Smacallan    xf86Msg(X_ERROR, "old memctl: %08x\n", mem);
1169a6b33934Smacallan#endif
1170a6b33934Smacallan    /* set shift and crtc clock */
1171a6b33934Smacallan    mem &= ~(0x0000fc00);
1172a6b33934Smacallan    mem |= (memctl << 10) | (memctl << 13);
1173a6b33934Smacallan    pnozz_write_4(pPnozz, VID_MEM_CONFIG, mem);
1174a6b33934Smacallan#if DEBUG
1175a6b33934Smacallan    xf86Msg(X_ERROR, "new memctl: %08x\n", mem);
1176a6b33934Smacallan#endif
1177a6b33934Smacallan    /* whack the engine... */
1178a6b33934Smacallan    pnozz_write_4(pPnozz, SYS_CONF, scr);
1179a6b33934Smacallan
1180a6b33934Smacallan    /* ok, whack the DAC */
1181a6b33934Smacallan    pnozz_write_dac_ctl_reg(pPnozz, DAC_MISC_1, 0x11);
1182a6b33934Smacallan    pnozz_write_dac_ctl_reg(pPnozz, DAC_MISC_2, 0x45);
1183a6b33934Smacallan    pnozz_write_dac_ctl_reg(pPnozz, DAC_MISC_3, mc3);
1184a6b33934Smacallan    /*
1185a6b33934Smacallan     * despite the 3GX manual saying otherwise we don't need to mess with any
1186a6b33934Smacallan     * clock dividers here
1187a6b33934Smacallan     */
1188a6b33934Smacallan    pnozz_write_dac_ctl_reg(pPnozz, DAC_MISC_CLK, 1);
1189a6b33934Smacallan    pnozz_write_dac_ctl_reg(pPnozz, 3, 0);
1190a6b33934Smacallan    pnozz_write_dac_ctl_reg(pPnozz, 4, 0);
1191a6b33934Smacallan
1192a6b33934Smacallan    pnozz_write_dac_ctl_reg(pPnozz, DAC_POWER_MGT, 0);
1193a6b33934Smacallan    pnozz_write_dac_ctl_reg(pPnozz, DAC_OPERATION, 0);
1194a6b33934Smacallan    pnozz_write_dac_ctl_reg(pPnozz, DAC_PALETTE_CTRL, 0);
1195a6b33934Smacallan
1196a6b33934Smacallan    pnozz_write_dac_ctl_reg(pPnozz, DAC_PIXEL_FMT, pf);
1197a6b33934Smacallan
1198a6b33934Smacallan    /* TODO: distinguish between 15 and 16 bit */
1199a6b33934Smacallan    pnozz_write_dac_ctl_reg(pPnozz, DAC_8BIT_CTRL, 0);
1200a6b33934Smacallan    /* direct colour, linear, 565 */
1201a6b33934Smacallan    pnozz_write_dac_ctl_reg(pPnozz, DAC_16BIT_CTRL, 0xc6);
1202a6b33934Smacallan    /* direct colour */
1203a6b33934Smacallan    pnozz_write_dac_ctl_reg(pPnozz, DAC_32BIT_CTRL, 3);
1204a6b33934Smacallan
1205a6b33934Smacallan    pnozz_write_dac_ctl_reg(pPnozz, 0x10, 2);
1206a6b33934Smacallan    pnozz_write_dac_ctl_reg(pPnozz, 0x11, 0);
1207a6b33934Smacallan    pnozz_write_dac_ctl_reg(pPnozz, 0x14, 5);
1208a6b33934Smacallan    pnozz_write_dac_ctl_reg(pPnozz, 0x08, 1);
1209a6b33934Smacallan    pnozz_write_dac_ctl_reg(pPnozz, 0x15, 5);
1210a6b33934Smacallan    pnozz_write_dac_ctl_reg(pPnozz, 0x16, 0x63);
1211a6b33934Smacallan
1212a6b33934Smacallan    /* whack the CRTC */
1213a6b33934Smacallan    /* we always transfer 64bit in one go */
1214a6b33934Smacallan    crtcline = pPnozz->scanlinesize >> 3;
1215a6b33934Smacallan#if DEBUG
1216a6b33934Smacallan    xf86Msg(X_ERROR, "crtcline: %d\n", crtcline);
1217a6b33934Smacallan#endif
1218a6b33934Smacallan    pnozz_write_4(pPnozz, VID_HTOTAL, (24 << pPnozz->depthshift) + crtcline);
1219a6b33934Smacallan    pnozz_write_4(pPnozz, VID_HSRE, 8 << pPnozz->depthshift);
1220a6b33934Smacallan    pnozz_write_4(pPnozz, VID_HBRE, 18 << pPnozz->depthshift);
1221a6b33934Smacallan    pnozz_write_4(pPnozz, VID_HBFE, (18 << pPnozz->depthshift) + crtcline);
1222a6b33934Smacallan
1223a6b33934Smacallan#if DEBUG
1224a6b33934Smacallan    sscr = pnozz_read_4(pPnozz, SYS_CONF);
1225a6b33934Smacallan    xf86Msg(X_ERROR, "scr: %x\n", sscr);
1226a6b33934Smacallan#endif
1227a6b33934Smacallan    return TRUE;
1228a6b33934Smacallan}
1229