linux/drivers/video/fbdev/sis/initextlfb.c
<<
>>
Prefs
   1/*
   2 * SiS 300/540/630[S]/730[S]
   3 * SiS 315[E|PRO]/550/[M]65x/[M]66x[F|M|G]X/[M]74x[GX]/330/[M]76x[GX]
   4 * XGI V3XT/V5/V8, Z7
   5 * frame buffer driver for Linux kernels >= 2.4.14 and >=2.6.3
   6 *
   7 * Linux kernel specific extensions to init.c/init301.c
   8 *
   9 * Copyright (C) 2001-2005 Thomas Winischhofer, Vienna, Austria.
  10 *
  11 * This program is free software; you can redistribute it and/or modify
  12 * it under the terms of the GNU General Public License as published by
  13 * the Free Software Foundation; either version 2 of the named License,
  14 * or any later version.
  15 *
  16 * This program is distributed in the hope that it will be useful,
  17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19 * GNU General Public License for more details.
  20 *
  21 * You should have received a copy of the GNU General Public License
  22 * along with this program; if not, write to the Free Software
  23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
  24 *
  25 * Author:      Thomas Winischhofer <thomas@winischhofer.net>
  26 */
  27
  28#include "initdef.h"
  29#include "vgatypes.h"
  30#include "vstruct.h"
  31
  32#include <linux/types.h>
  33#include <linux/fb.h>
  34
  35int             sisfb_mode_rate_to_dclock(struct SiS_Private *SiS_Pr,
  36                        unsigned char modeno, unsigned char rateindex);
  37int             sisfb_mode_rate_to_ddata(struct SiS_Private *SiS_Pr, unsigned char modeno,
  38                        unsigned char rateindex, struct fb_var_screeninfo *var);
  39bool            sisfb_gettotalfrommode(struct SiS_Private *SiS_Pr, unsigned char modeno,
  40                        int *htotal, int *vtotal, unsigned char rateindex);
  41
  42extern bool     SiSInitPtr(struct SiS_Private *SiS_Pr);
  43extern bool     SiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo,
  44                        unsigned short *ModeIdIndex);
  45extern void     SiS_Generic_ConvertCRData(struct SiS_Private *SiS_Pr, unsigned char *crdata,
  46                        int xres, int yres, struct fb_var_screeninfo *var, bool writeres);
  47
  48int
  49sisfb_mode_rate_to_dclock(struct SiS_Private *SiS_Pr, unsigned char modeno,
  50                        unsigned char rateindex)
  51{
  52    unsigned short ModeNo = modeno;
  53    unsigned short ModeIdIndex = 0, ClockIndex = 0;
  54    unsigned short RRTI = 0;
  55    int Clock;
  56
  57    if(!SiSInitPtr(SiS_Pr)) return 65000;
  58
  59    if(rateindex > 0) rateindex--;
  60
  61#ifdef CONFIG_FB_SIS_315
  62    switch(ModeNo) {
  63    case 0x5a: ModeNo = 0x50; break;
  64    case 0x5b: ModeNo = 0x56;
  65    }
  66#endif
  67
  68    if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) {
  69       printk(KERN_ERR "Could not find mode %x\n", ModeNo);
  70       return 65000;
  71    }
  72
  73    RRTI = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
  74
  75    if(SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag & HaveWideTiming) {
  76       if(SiS_Pr->SiS_UseWide == 1) {
  77          /* Wide screen: Ignore rateindex */
  78          ClockIndex = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRTVCLK_WIDE;
  79       } else {
  80          RRTI += rateindex;
  81          ClockIndex = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRTVCLK_NORM;
  82       }
  83    } else {
  84       RRTI += rateindex;
  85       ClockIndex = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRTVCLK;
  86    }
  87
  88    Clock = SiS_Pr->SiS_VCLKData[ClockIndex].CLOCK * 1000;
  89
  90    return Clock;
  91}
  92
  93int
  94sisfb_mode_rate_to_ddata(struct SiS_Private *SiS_Pr, unsigned char modeno,
  95                        unsigned char rateindex, struct fb_var_screeninfo *var)
  96{
  97    unsigned short ModeNo = modeno;
  98    unsigned short ModeIdIndex = 0, index = 0, RRTI = 0;
  99    int            j;
 100
 101    if(!SiSInitPtr(SiS_Pr)) return 0;
 102
 103    if(rateindex > 0) rateindex--;
 104
 105#ifdef CONFIG_FB_SIS_315
 106    switch(ModeNo) {
 107       case 0x5a: ModeNo = 0x50; break;
 108       case 0x5b: ModeNo = 0x56;
 109    }
 110#endif
 111
 112    if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return 0;
 113
 114    RRTI = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
 115    if(SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag & HaveWideTiming) {
 116       if(SiS_Pr->SiS_UseWide == 1) {
 117          /* Wide screen: Ignore rateindex */
 118          index = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRT1CRTC_WIDE;
 119       } else {
 120          RRTI += rateindex;
 121          index = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRT1CRTC_NORM;
 122       }
 123    } else {
 124       RRTI += rateindex;
 125       index = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRT1CRTC;
 126    }
 127
 128    SiS_Generic_ConvertCRData(SiS_Pr,
 129                        (unsigned char *)&SiS_Pr->SiS_CRT1Table[index].CR[0],
 130                        SiS_Pr->SiS_RefIndex[RRTI].XRes,
 131                        SiS_Pr->SiS_RefIndex[RRTI].YRes,
 132                        var, false);
 133
 134    if(SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag & 0x8000)
 135       var->sync &= ~FB_SYNC_VERT_HIGH_ACT;
 136    else
 137       var->sync |= FB_SYNC_VERT_HIGH_ACT;
 138
 139    if(SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag & 0x4000)
 140       var->sync &= ~FB_SYNC_HOR_HIGH_ACT;
 141    else
 142       var->sync |= FB_SYNC_HOR_HIGH_ACT;
 143
 144    var->vmode = FB_VMODE_NONINTERLACED;
 145    if(SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag & 0x0080)
 146       var->vmode = FB_VMODE_INTERLACED;
 147    else {
 148       j = 0;
 149       while(SiS_Pr->SiS_EModeIDTable[j].Ext_ModeID != 0xff) {
 150          if(SiS_Pr->SiS_EModeIDTable[j].Ext_ModeID ==
 151                          SiS_Pr->SiS_RefIndex[RRTI].ModeID) {
 152              if(SiS_Pr->SiS_EModeIDTable[j].Ext_ModeFlag & DoubleScanMode) {
 153                  var->vmode = FB_VMODE_DOUBLE;
 154              }
 155              break;
 156          }
 157          j++;
 158       }
 159    }
 160
 161    if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
 162#if 0  /* Do this? */
 163       var->upper_margin <<= 1;
 164       var->lower_margin <<= 1;
 165       var->vsync_len <<= 1;
 166#endif
 167    } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
 168       var->upper_margin >>= 1;
 169       var->lower_margin >>= 1;
 170       var->vsync_len >>= 1;
 171    }
 172
 173    return 1;
 174}
 175
 176bool
 177sisfb_gettotalfrommode(struct SiS_Private *SiS_Pr, unsigned char modeno, int *htotal,
 178                        int *vtotal, unsigned char rateindex)
 179{
 180    unsigned short ModeNo = modeno;
 181    unsigned short ModeIdIndex = 0, CRT1Index = 0;
 182    unsigned short RRTI = 0;
 183    unsigned char  sr_data, cr_data, cr_data2;
 184
 185    if(!SiSInitPtr(SiS_Pr)) return false;
 186
 187    if(rateindex > 0) rateindex--;
 188
 189#ifdef CONFIG_FB_SIS_315
 190    switch(ModeNo) {
 191       case 0x5a: ModeNo = 0x50; break;
 192       case 0x5b: ModeNo = 0x56;
 193    }
 194#endif
 195
 196    if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return false;
 197
 198    RRTI = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
 199    if(SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag & HaveWideTiming) {
 200       if(SiS_Pr->SiS_UseWide == 1) {
 201          /* Wide screen: Ignore rateindex */
 202          CRT1Index = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRT1CRTC_WIDE;
 203       } else {
 204          RRTI += rateindex;
 205          CRT1Index = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRT1CRTC_NORM;
 206       }
 207    } else {
 208       RRTI += rateindex;
 209       CRT1Index = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRT1CRTC;
 210    }
 211
 212    sr_data = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[14];
 213    cr_data = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[0];
 214    *htotal = (((cr_data & 0xff) | ((unsigned short) (sr_data & 0x03) << 8)) + 5) * 8;
 215
 216    sr_data = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[13];
 217    cr_data = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[6];
 218    cr_data2 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[7];
 219    *vtotal = ((cr_data & 0xFF) |
 220               ((unsigned short)(cr_data2 & 0x01) <<  8) |
 221               ((unsigned short)(cr_data2 & 0x20) <<  4) |
 222               ((unsigned short)(sr_data  & 0x01) << 10)) + 2;
 223
 224    if(SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag & InterlaceMode)
 225       *vtotal *= 2;
 226
 227    return true;
 228}
 229
 230
 231
 232