forked from KolibriOS/kolibrios
305 lines
8.2 KiB
C
305 lines
8.2 KiB
C
|
/*
|
||
|
* Copyright 2007-2008 Luc Verhaegen <lverhaegen@novell.com>
|
||
|
* Copyright 2007-2008 Matthias Hopf <mhopf@novell.com>
|
||
|
* Copyright 2007-2008 Egbert Eich <eich@novell.com>
|
||
|
*
|
||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||
|
* copy of this software and associated documentation files (the "Software"),
|
||
|
* to deal in the Software without restriction, including without limitation
|
||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||
|
* Software is furnished to do so, subject to the following conditions:
|
||
|
*
|
||
|
* The above copyright notice and this permission notice shall be included in
|
||
|
* all copies or substantial portions of the Software.
|
||
|
*
|
||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||
|
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||
|
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||
|
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||
|
* OTHER DEALINGS IN THE SOFTWARE.
|
||
|
*/
|
||
|
|
||
|
#ifdef HAVE_CONFIG_H
|
||
|
#include "config.h"
|
||
|
#endif
|
||
|
|
||
|
#include "xf86.h"
|
||
|
|
||
|
#include "rhd.h"
|
||
|
#include "rhd_lut.h"
|
||
|
#include "rhd_regs.h"
|
||
|
|
||
|
#define RHD_REGOFFSET_LUTA 0x000
|
||
|
#define RHD_REGOFFSET_LUTB 0x800
|
||
|
|
||
|
/*
|
||
|
*
|
||
|
*/
|
||
|
static void
|
||
|
LUTxSave(struct rhdLUT *LUT)
|
||
|
{
|
||
|
CARD16 RegOff;
|
||
|
int i;
|
||
|
RHDFUNC(LUT);
|
||
|
|
||
|
if (LUT->Id == RHD_LUT_A)
|
||
|
RegOff = RHD_REGOFFSET_LUTA;
|
||
|
else
|
||
|
RegOff = RHD_REGOFFSET_LUTB;
|
||
|
|
||
|
LUT->StoreControl = RHDRegRead(LUT, RegOff + DC_LUTA_CONTROL);
|
||
|
|
||
|
LUT->StoreBlackBlue = RHDRegRead(LUT, RegOff + DC_LUTA_BLACK_OFFSET_BLUE);
|
||
|
LUT->StoreBlackGreen = RHDRegRead(LUT, RegOff + DC_LUTA_BLACK_OFFSET_GREEN);
|
||
|
LUT->StoreBlackRed = RHDRegRead(LUT, RegOff + DC_LUTA_BLACK_OFFSET_RED);
|
||
|
|
||
|
LUT->StoreWhiteBlue = RHDRegRead(LUT, RegOff + DC_LUTA_WHITE_OFFSET_BLUE);
|
||
|
LUT->StoreWhiteGreen = RHDRegRead(LUT, RegOff + DC_LUTA_WHITE_OFFSET_GREEN);
|
||
|
LUT->StoreWhiteRed = RHDRegRead(LUT, RegOff + DC_LUTA_WHITE_OFFSET_RED);
|
||
|
|
||
|
RHDRegWrite(LUT, DC_LUT_RW_MODE, 0); /* Table */
|
||
|
if (LUT->Id == RHD_LUT_A)
|
||
|
RHDRegWrite(LUT, DC_LUT_READ_PIPE_SELECT, 0);
|
||
|
else
|
||
|
RHDRegWrite(LUT, DC_LUT_READ_PIPE_SELECT, 1);
|
||
|
|
||
|
RHDRegWrite(LUT, DC_LUT_RW_INDEX, 0);
|
||
|
for (i = 0; i < 0x300; i++)
|
||
|
LUT->StoreEntry[i] = RHDRegRead(LUT, DC_LUT_SEQ_COLOR);
|
||
|
|
||
|
LUT->Stored = TRUE;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
*
|
||
|
*/
|
||
|
static void
|
||
|
LUTxRestore(struct rhdLUT *LUT)
|
||
|
{
|
||
|
CARD16 RegOff;
|
||
|
int i;
|
||
|
RHDFUNC(LUT);
|
||
|
|
||
|
if (!LUT->Stored) {
|
||
|
xf86DrvMsg(LUT->scrnIndex, X_ERROR, "%s: %s: nothing stored!\n",
|
||
|
__func__, LUT->Name);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (LUT->Id == RHD_LUT_A)
|
||
|
RegOff = RHD_REGOFFSET_LUTA;
|
||
|
else
|
||
|
RegOff = RHD_REGOFFSET_LUTB;
|
||
|
|
||
|
RHDRegWrite(LUT, RegOff + DC_LUTA_BLACK_OFFSET_BLUE, LUT->StoreBlackBlue);
|
||
|
RHDRegWrite(LUT, RegOff + DC_LUTA_BLACK_OFFSET_GREEN, LUT->StoreBlackGreen);
|
||
|
RHDRegWrite(LUT, RegOff + DC_LUTA_BLACK_OFFSET_RED, LUT->StoreBlackRed);
|
||
|
|
||
|
RHDRegWrite(LUT, RegOff + DC_LUTA_WHITE_OFFSET_BLUE, LUT->StoreWhiteBlue);
|
||
|
RHDRegWrite(LUT, RegOff + DC_LUTA_WHITE_OFFSET_GREEN, LUT->StoreWhiteGreen);
|
||
|
RHDRegWrite(LUT, RegOff + DC_LUTA_WHITE_OFFSET_RED, LUT->StoreWhiteRed);
|
||
|
|
||
|
if (LUT->Id == RHD_LUT_A)
|
||
|
RHDRegWrite(LUT, DC_LUT_RW_SELECT, 0);
|
||
|
else
|
||
|
RHDRegWrite(LUT, DC_LUT_RW_SELECT, 1);
|
||
|
|
||
|
RHDRegWrite(LUT, DC_LUT_RW_MODE, 0); /* Table */
|
||
|
RHDRegWrite(LUT, DC_LUT_WRITE_EN_MASK, 0x0000003F);
|
||
|
RHDRegWrite(LUT, DC_LUT_RW_INDEX, 0);
|
||
|
for (i = 0; i < 0x300; i++)
|
||
|
RHDRegWrite(LUT, DC_LUT_SEQ_COLOR, LUT->StoreEntry[i]);
|
||
|
|
||
|
RHDRegWrite(LUT, RegOff + DC_LUTA_CONTROL, LUT->StoreControl);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
*
|
||
|
*/
|
||
|
static void
|
||
|
LUTxSet(struct rhdLUT *LUT, int numColors, int *indices, LOCO *colors)
|
||
|
{
|
||
|
//ScrnInfoPtr pScrn = xf86Screens[LUT->scrnIndex];
|
||
|
CARD16 RegOff;
|
||
|
int i, index;
|
||
|
|
||
|
LUT->Initialised = TRUE; /* thank you RandR */
|
||
|
|
||
|
if (LUT->Id == RHD_LUT_A)
|
||
|
RegOff = RHD_REGOFFSET_LUTA;
|
||
|
else
|
||
|
RegOff = RHD_REGOFFSET_LUTB;
|
||
|
|
||
|
RHDRegWrite(LUT, RegOff + DC_LUTA_CONTROL, 0);
|
||
|
|
||
|
RHDRegWrite(LUT, RegOff + DC_LUTA_BLACK_OFFSET_BLUE, 0);
|
||
|
RHDRegWrite(LUT, RegOff + DC_LUTA_BLACK_OFFSET_GREEN, 0);
|
||
|
RHDRegWrite(LUT, RegOff + DC_LUTA_BLACK_OFFSET_RED, 0);
|
||
|
|
||
|
RHDRegWrite(LUT, RegOff + DC_LUTA_WHITE_OFFSET_BLUE, 0x0000FFFF);
|
||
|
RHDRegWrite(LUT, RegOff + DC_LUTA_WHITE_OFFSET_GREEN, 0x0000FFFF);
|
||
|
RHDRegWrite(LUT, RegOff + DC_LUTA_WHITE_OFFSET_RED, 0x0000FFFF);
|
||
|
|
||
|
if (LUT->Id == RHD_LUT_A)
|
||
|
RHDRegWrite(LUT, DC_LUT_RW_SELECT, 0);
|
||
|
else
|
||
|
RHDRegWrite(LUT, DC_LUT_RW_SELECT, 1);
|
||
|
|
||
|
RHDRegWrite(LUT, DC_LUT_RW_MODE, 0); /* table */
|
||
|
RHDRegWrite(LUT, DC_LUT_WRITE_EN_MASK, 0x0000003F);
|
||
|
|
||
|
int depth = 32;
|
||
|
|
||
|
switch (depth) {
|
||
|
case 8:
|
||
|
case 24:
|
||
|
case 32:
|
||
|
for (i = 0; i < numColors; i++) {
|
||
|
index = indices[i];
|
||
|
RHDRegWrite(LUT, DC_LUT_RW_INDEX, index);
|
||
|
RHDRegWrite(LUT, DC_LUT_30_COLOR, (colors[index].red << 22) |
|
||
|
(colors[index].green << 12) | (colors[index].blue << 2));
|
||
|
}
|
||
|
break;
|
||
|
case 16:
|
||
|
for (i = 0; i < numColors; i++) {
|
||
|
int j;
|
||
|
|
||
|
index = indices[i];
|
||
|
RHDRegWrite(LUT, DC_LUT_RW_INDEX, 4 * index);
|
||
|
|
||
|
for (j = 0; j < 4; j++)
|
||
|
RHDRegWrite(LUT, DC_LUT_30_COLOR, (colors[index/2].red << 24) |
|
||
|
(colors[index].green << 14) | (colors[index/2].blue << 4));
|
||
|
}
|
||
|
break;
|
||
|
case 15:
|
||
|
for (i = 0; i < numColors; i++) {
|
||
|
int j;
|
||
|
|
||
|
index = indices[i];
|
||
|
RHDRegWrite(LUT, DC_LUT_RW_INDEX, 8 * index);
|
||
|
|
||
|
for (j = 0; j < 8; j++)
|
||
|
RHDRegWrite(LUT, DC_LUT_30_COLOR, (colors[index].red << 25) |
|
||
|
(colors[index].green << 15) | (colors[index].blue << 5));
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
*
|
||
|
*/
|
||
|
void
|
||
|
RHDLUTsInit(RHDPtr rhdPtr)
|
||
|
{
|
||
|
struct rhdLUT *LUT;
|
||
|
|
||
|
RHDFUNC(rhdPtr);
|
||
|
|
||
|
LUT = xnfcalloc(sizeof(struct rhdLUT), 1);
|
||
|
|
||
|
LUT->scrnIndex = rhdPtr->scrnIndex;
|
||
|
LUT->Name = "LUT A";
|
||
|
LUT->Id = RHD_LUT_A;
|
||
|
|
||
|
LUT->Save = LUTxSave;
|
||
|
LUT->Restore = LUTxRestore;
|
||
|
LUT->Set = LUTxSet;
|
||
|
|
||
|
rhdPtr->LUT[0] = LUT;
|
||
|
|
||
|
LUT = xnfcalloc(sizeof(struct rhdLUT), 1);
|
||
|
|
||
|
LUT->scrnIndex = rhdPtr->scrnIndex;
|
||
|
LUT->Name = "LUT B";
|
||
|
LUT->Id = RHD_LUT_B;
|
||
|
|
||
|
LUT->Save = LUTxSave;
|
||
|
LUT->Restore = LUTxRestore;
|
||
|
LUT->Set = LUTxSet;
|
||
|
|
||
|
rhdPtr->LUT[1] = LUT;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
*
|
||
|
*/
|
||
|
struct rhdLUTStore {
|
||
|
CARD32 Select;
|
||
|
CARD32 Mode;
|
||
|
CARD32 Index;
|
||
|
CARD32 Color;
|
||
|
CARD32 ReadPipe;
|
||
|
CARD32 WriteMask;
|
||
|
};
|
||
|
|
||
|
/*
|
||
|
*
|
||
|
*/
|
||
|
void
|
||
|
RHDLUTsSave(RHDPtr rhdPtr)
|
||
|
{
|
||
|
struct rhdLUTStore *Store = rhdPtr->LUTStore;
|
||
|
|
||
|
RHDFUNC(rhdPtr);
|
||
|
|
||
|
if (!Store) {
|
||
|
Store = xnfcalloc(sizeof(struct rhdLUTStore), 1);
|
||
|
rhdPtr->LUTStore = Store;
|
||
|
}
|
||
|
|
||
|
Store->Select = _RHDRegRead(rhdPtr, DC_LUT_RW_SELECT);
|
||
|
Store->Mode = _RHDRegRead(rhdPtr, DC_LUT_RW_MODE);
|
||
|
Store->Index = _RHDRegRead(rhdPtr, DC_LUT_RW_INDEX);
|
||
|
Store->Color = _RHDRegRead(rhdPtr, DC_LUT_30_COLOR);
|
||
|
Store->ReadPipe = _RHDRegRead(rhdPtr, DC_LUT_READ_PIPE_SELECT);
|
||
|
Store->WriteMask = _RHDRegRead(rhdPtr, DC_LUT_WRITE_EN_MASK);
|
||
|
|
||
|
rhdPtr->LUT[0]->Save(rhdPtr->LUT[0]);
|
||
|
rhdPtr->LUT[1]->Save(rhdPtr->LUT[1]);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
*
|
||
|
*/
|
||
|
void
|
||
|
RHDLUTsRestore(RHDPtr rhdPtr)
|
||
|
{
|
||
|
struct rhdLUTStore *Store = rhdPtr->LUTStore;
|
||
|
|
||
|
RHDFUNC(rhdPtr);
|
||
|
|
||
|
rhdPtr->LUT[0]->Restore(rhdPtr->LUT[0]);
|
||
|
rhdPtr->LUT[1]->Restore(rhdPtr->LUT[1]);
|
||
|
|
||
|
if (!Store) {
|
||
|
xf86DrvMsg(rhdPtr->scrnIndex, X_ERROR, "%s: nothing stored!\n", __func__);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
_RHDRegWrite(rhdPtr, DC_LUT_RW_SELECT, Store->Select);
|
||
|
_RHDRegWrite(rhdPtr, DC_LUT_RW_MODE, Store->Mode);
|
||
|
_RHDRegWrite(rhdPtr, DC_LUT_RW_INDEX, Store->Index);
|
||
|
_RHDRegWrite(rhdPtr, DC_LUT_30_COLOR, Store->Color);
|
||
|
_RHDRegWrite(rhdPtr, DC_LUT_READ_PIPE_SELECT, Store->ReadPipe);
|
||
|
_RHDRegWrite(rhdPtr, DC_LUT_WRITE_EN_MASK, Store->WriteMask);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
*
|
||
|
*/
|
||
|
void
|
||
|
RHDLUTsDestroy(RHDPtr rhdPtr)
|
||
|
{
|
||
|
RHDFUNC(rhdPtr);
|
||
|
|
||
|
xfree(rhdPtr->LUT[0]);
|
||
|
xfree(rhdPtr->LUT[1]);
|
||
|
xfree(rhdPtr->LUTStore);
|
||
|
}
|