/*
* Copyright (c) 2012 Michael Lorenz
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* A console driver for Apple's Valkyrie onboard video controller, found in
* for example the Performa 6360
* This should be easy enough to adapt to mac68k but I don't have the hardware
*/
struct valkyriefb_mode {
int width;
int height;
uint8_t mode;
};
/*
* Translate screen resolutions to values for Valkyrie's mode register.
* These numbers seem to roughly correspond to MacOS video mode numbers
* there are many numbers that result in the same resolution which in MacOS
* only differ by the display refresh rate, which isn't set by Valkyrie at
* all, instead there's a PLL chip hooked to cuda's i2c bus. It doesn't seem
* to matter which number we use as long as the resolution is right and we
* program the PLL for the right pixel clock
*/
static struct valkyriefb_mode modetab[] = {
{ 640, 480, 6 },
{ 800, 600, 12 },
{ 832, 624, 9 },
{ 1024, 768, 14},
};
static int
valkyriefb_set_mode(struct valkyriefb_softc *sc,
const struct videomode *mode, int depth)
{
int i;
uint8_t modereg, tmp;
/* first find the parameter for the mode register */
i = 0;
while ((i < __arraycount(modetab)) &&
(modetab[i].width != mode->hdisplay) &&
(modetab[i].height != mode->vdisplay))
i++;
if (i >= __arraycount(modetab)) {
aprint_error_dev(sc->sc_dev,
"Can't find a mode register value for %s\n", mode->name);
return EINVAL;
} else
modereg = modetab[i].mode;
/* check if we have enough video memory */
if ((mode->hdisplay * mode->vdisplay * (depth >> 3)) > 0x100000) {
aprint_error_dev(sc->sc_dev, "Not enough video RAM for %s\n",
mode->name);
return EINVAL;
}
/* reject depths other than 8 or 16 */
if ((depth != 8) && (depth != 16)) {
aprint_error_dev(sc->sc_dev,
"Depth [%d] is unsupported for %s\n", depth, mode->name);
return EINVAL;
}
/* now start programming the chip */
valkyriefb_write_reg(sc, VAL_STATUS, 0);
delay(100);
valkyriefb_write_reg(sc, VAL_MODE, modereg | VAL_MODE_STOP);
if (depth == 8) {
sc->sc_depth = 8;
valkyriefb_write_reg(sc, VAL_DEPTH, VAL_DEPTH_8);
for (i = 0; i < 256; i++) {
tmp = i & 0xe0;
/*
* replicate bits so 0xe0 maps to a red value of 0xff
* in order to make white look actually white
*/
tmp |= (tmp >> 3) | (tmp >> 6);
sc->sc_cmap_red[i] = tmp;
valkyriefb_write_cmap(sc, i, sc->sc_cmap_red[i],
sc->sc_cmap_green[i], sc->sc_cmap_blue[i]);
}
} else if (depth == 16) {
sc->sc_depth = 16;
valkyriefb_write_reg(sc, VAL_DEPTH, VAL_DEPTH_16);
/* does the palette have any effect in 16bit? */
}