// SPDX-License-Identifier: GPL-2.0-only
/*
*
* Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200, G400 and G450.
*
* (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
*
* Portions Copyright (c) 2001 Matrox Graphics Inc.
*
* Version: 1.65 2002/08/14
*
* See matroxfb_base.c for contributors.
*
*/
#include "matroxfb_DAC1064.h"
#include "matroxfb_misc.h"
#include "matroxfb_accel.h"
#include "g450_pll.h"
#include <linux/matroxfb.h>
#ifdef NEED_DAC1064
#define outDAC1064 matroxfb_DAC_out
#define inDAC1064 matroxfb_DAC_in
#define DAC1064_OPT_SCLK_PCI 0x00
#define DAC1064_OPT_SCLK_PLL 0x01
#define DAC1064_OPT_SCLK_EXT 0x02
#define DAC1064_OPT_SCLK_MASK 0x03
#define DAC1064_OPT_GDIV1 0x04 /* maybe it is GDIV2 on G100 ?! */
#define DAC1064_OPT_GDIV3 0x00
#define DAC1064_OPT_MDIV1 0x08
#define DAC1064_OPT_MDIV2 0x00
#define DAC1064_OPT_RESERVED 0x10
static void DAC1064_calcclock(const struct matrox_fb_info *minfo,
unsigned int freq, unsigned int fmax,
unsigned int *in, unsigned int *feed,
unsigned int *post)
{
unsigned int fvco;
unsigned int p;
DBG(__func__)
/* only for devices older than G450 */
fvco = PLL_calcclock(minfo, freq, fmax, in, feed, &p);
p = (1 << p) - 1;
if (fvco <= 100000)
;
else if (fvco <= 140000)
p |= 0x08;
else if (fvco <= 180000)
p |= 0x10;
else
p |= 0x18;
*post = p;
}
/* they must be in POS order */
static const unsigned char MGA1064_DAC_regs[] = {
M1064_XCURADDL, M1064_XCURADDH, M1064_XCURCTRL,
M1064_XCURCOL0RED, M1064_XCURCOL0GREEN, M1064_XCURCOL0BLUE,
M1064_XCURCOL1RED, M1064_XCURCOL1GREEN, M1064_XCURCOL1BLUE,
M1064_XCURCOL2RED, M1064_XCURCOL2GREEN, M1064_XCURCOL2BLUE,
DAC1064_XVREFCTRL, M1064_XMULCTRL, M1064_XPIXCLKCTRL, M1064_XGENCTRL,
M1064_XMISCCTRL,
M1064_XGENIOCTRL, M1064_XGENIODATA, M1064_XZOOMCTRL, M1064_XSENSETEST,
M1064_XCRCBITSEL,
M1064_XCOLKEYMASKL, M1064_XCOLKEYMASKH, M1064_XCOLKEYL, M1064_XCOLKEYH };
static const unsigned char MGA1064_DAC[] = {
0x00, 0x00, M1064_XCURCTRL_DIS,
0x00, 0x00, 0x00, /* black */
0xFF, 0xFF, 0xFF, /* white */
0xFF, 0x00, 0x00, /* red */
0x00, 0,
M1064_XPIXCLKCTRL_PLL_UP | M1064_XPIXCLKCTRL_EN | M1064_XPIXCLKCTRL_SRC_PLL,
M1064_XGENCTRL_VS_0 | M1064_XGENCTRL_ALPHA_DIS | M1064_XGENCTRL_BLACK_0IRE | M1064_XGENCTRL_NO_SYNC_ON_GREEN,
M1064_XMISCCTRL_DAC_8BIT,
0x00, 0x00, M1064_XZOOMCTRL_1, M1064_XSENSETEST_BCOMP | M1064_XSENSETEST_GCOMP | M1064_XSENSETEST_RCOMP | M1064_XSENSETEST_PDOWN,
0x00,
0x00, 0x00, 0xFF, 0xFF};
static void DAC1064_setpclk(struct matrox_fb_info *minfo, unsigned long fout)
{
unsigned int m, n, p;
DBG(__func__)
DAC1064_calcclock(minfo, fout, minfo->max_pixel_clock, &m, &n, &p);
minfo->hw.DACclk[0] = m;
minfo->hw.DACclk[1] = n;
minfo->hw.DACclk[2] = p;
}
static void DAC1064_setmclk(struct matrox_fb_info *minfo, int oscinfo,
unsigned long fmem)
{
u_int32_t mx;
struct matrox_hw_state *hw = &minfo->hw;
DBG(__func__)
if (minfo->devflags.noinit) {
/* read MCLK and give up... */
hw->DACclk[3] = inDAC1064(minfo, DAC1064_XSYSPLLM);
hw->DACclk[4] = inDAC1064(minfo, DAC1064_XSYSPLLN);
hw->DACclk[5] = inDAC1064(minfo, DAC1064_XSYSPLLP);
return;