* [PATCH 2/12] viafb: Framebuffer driver for VIA UniChrome/Chrome9 HC (fwd)
@ 2007-04-30 8:36 Geert Uytterhoeven
0 siblings, 0 replies; only message in thread
From: Geert Uytterhoeven @ 2007-04-30 8:36 UTC (permalink / raw)
To: Linux Frame Buffer Device Development
---------- Forwarded message ----------
Date: Mon, 30 Apr 2007 13:20:06 +0800
From: EddyFu@via.com.tw
To: linux-fbdev-devel-bounces@lists.sourceforge.net
Subject: [Linux-fbdev-devel] [PATCH 2/12] viafb: Framebuffer driver for VIA
UniChrome/Chrome9 HC
Dear All,
Here is the part 2/12 of viafb.
Best Regards,
Eddy Fu
diff -Nur linux-2.6.21-rc7/drivers/video/via/hw.c linux-2.6.21-rc7.viafb/drivers/video/via/hw.c
--- linux-2.6.21-rc7/drivers/video/via/hw.c 1969-12-31 19:00:00.000000000 -0500
+++ linux-2.6.21-rc7.viafb/drivers/video/via/hw.c 2007-04-26 19:52:32.000000000 -0400
@@ -0,0 +1,3098 @@
+/*
+ * Copyright 1998-2007 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2007 S3 Graphics, Inc. All Rights Reserved.
+ *
+ * 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, sub license,
+ * 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 (including the
+ * next paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) OR COPYRIGHT HOLDER(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.
+ */
+
+#include <linux/version.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
+#include <linux/config.h>
+#endif
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+#include <linux/fb.h>
+
+
+#include "viafbdev.h"
+#include "hw.h"
+#include "hwcfig.h"
+#include "share.h"
+#include "debug.h"
+#include "chip.h"
+#include "viamode.h"
+#include "lcd.h"
+#include "ioctl.h"
+#include "accel.h"
+
+/* External Function */
+extern int tmds_trasmitter_identify(void);
+extern void init_dvi_size(void);
+extern int lvds_trasmitter_identify(void);
+extern void init_lcd_size(void);
+extern void tv_set_mode(int video_index);
+extern void lcd_set_mode(struct crt_mode_table *mode_crt_table, struct lvds_setting_information *plvds_setting_info, struct lvds_chip_information *plvds_chip_info);
+extern void dvi_set_mode(struct crt_mode_table *dvi_crt_timing, int video_index, int mode_bpp, int set_iga);
+extern void dvi_disable(void);
+extern void dvi_enable(void);
+extern void lcd_disable(void);
+extern void lcd_enable(void);
+extern void init_lvds_output_interface(struct lvds_chip_information *plvds_chip_info, struct lvds_setting_information* plvds_setting_info);
+extern unsigned int get_memsize(void);
+extern bool lcd_get_mobile_state(bool* mobile);
+
+/* External struct */
+
+extern struct chip_information chip_info;
+extern struct crt_setting_information crt_setting_info;
+extern struct tv_setting_information tv_setting_info;
+extern struct tmds_setting_information tmds_setting_info;
+extern struct lvds_setting_information lvds_setting_info;
+extern struct lvds_setting_information lvds_setting_info2;
+
+static struct VPITTable VPIT = {
+ /* Msic */
+ 0xC7,
+ /* Sequencer */
+ {0x01,0x0F,0x00,0x0E },
+ /* Graphic Controller */
+ {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0F,0xFF},
+ /* Attribute Controller */
+ {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+ 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
+ 0x01,0x00,0x0F,0x00}
+};
+
+/* Mode:1024X768 */
+static struct io_reg PM1024x768[] = {
+ {VIASR,0x16,0xBF,0x0C},
+ {VIASR,0x18,0xFF,0x4C}
+};
+
+static struct patch_table res_patch_table[]= {
+ {VIA_RES_1024X768, ARRAY_SIZE(PM1024x768), PM1024x768}
+};
+#define NUM_TOTAL_PATCH_MODE ARRAY_SIZE(res_patch_table)
+
+static struct res_map_refresh res_map_refresh_tbl[] = {
+/*hres, vres, vclock, vmode_refresh */
+ {640, 480, RES_640X480_60HZ_PIXCLOCK, 60},
+ {640, 480, RES_640X480_75HZ_PIXCLOCK, 75},
+ {640, 480, RES_640X480_85HZ_PIXCLOCK, 85},
+ {640, 480, RES_640X480_100HZ_PIXCLOCK, 100},
+ {640, 480, RES_640X480_120HZ_PIXCLOCK, 120},
+ {720, 480, RES_720X480_60HZ_PIXCLOCK, 60},
+ {720, 576, RES_720X576_60HZ_PIXCLOCK, 60},
+ {800, 480, RES_800X480_60HZ_PIXCLOCK, 60},
+ {800, 600, RES_800X600_60HZ_PIXCLOCK, 60},
+ {800, 600, RES_800X600_75HZ_PIXCLOCK, 75},
+ {800, 600, RES_800X600_85HZ_PIXCLOCK, 85},
+ {800, 600, RES_800X600_100HZ_PIXCLOCK, 100},
+ {800, 600, RES_800X600_120HZ_PIXCLOCK, 120},
+ {848, 480, RES_848X480_60HZ_PIXCLOCK, 60},
+ {856, 480, RES_856X480_60HZ_PIXCLOCK, 60},
+ {1024,512, RES_1024X512_60HZ_PIXCLOCK, 60},
+ {1024,768, RES_1024X768_60HZ_PIXCLOCK, 60},
+ {1024,768, RES_1024X768_75HZ_PIXCLOCK, 75},
+ {1024,768, RES_1024X768_85HZ_PIXCLOCK, 85},
+ {1024,768, RES_1024X768_100HZ_PIXCLOCK, 100},
+ {1152,864, RES_1152X864_70HZ_PIXCLOCK, 70},
+ {1152,864, RES_1152X864_75HZ_PIXCLOCK, 75},
+ {1280,768, RES_1280X768_60HZ_PIXCLOCK, 60},
+ {1280,960, RES_1280X960_60HZ_PIXCLOCK, 60},
+ {1280,1024,RES_1280X1024_60HZ_PIXCLOCK, 60},
+ {1280,1024,RES_1280X1024_75HZ_PIXCLOCK, 75},
+ {1280,1024,RES_1280X768_85HZ_PIXCLOCK, 85},
+ {1440,1050,RES_1440X1050_60HZ_PIXCLOCK, 60},
+ {1600,1200,RES_1600X1200_60HZ_PIXCLOCK, 60},
+ {1600,1200,RES_1600X1200_75HZ_PIXCLOCK, 75},
+ {1280,720, RES_1280X720_60HZ_PIXCLOCK, 60},
+ {1920,1080,RES_1920X1080_60HZ_PIXCLOCK, 60},
+ {1400,1050,RES_1400X1050_60HZ_PIXCLOCK, 60},
+ {1368,768, RES_1368X768_60HZ_PIXCLOCK,60}
+};
+#define NUM_TOTAL_RES_MAP_REFRESH ARRAY_SIZE(res_map_refresh_tbl)
+
+/* Video Mode Table */
+/* Common Setting for Video Mode */
+static struct io_reg CLE266_ModeXregs[] = {
+ {VIASR,SR1E,0xF0,0xF0},
+ {VIASR,SR2A,0x0F,0x0F},
+ {VIASR,SR15,0x02,0x02},
+ {VIASR,SR16,0xBF,0x08},
+ {VIASR,SR17,0xFF,0x1F},
+ {VIASR,SR18,0xFF,0x4E},
+ {VIASR,SR1A,0xFB,0x08},
+
+ {VIACR,CR32,0xFF,0x00},
+/* {VIACR,CR33,0xFF,0x08}, for K800 prefetch mode */
+ {VIACR,CR34,0xFF,0x00},
+ {VIACR,CR35,0xFF,0x00},
+ {VIACR,CR36,0x08,0x00},
+ {VIACR,CR6A,0xFF,0x80},
+ {VIACR,CR6A,0xFF,0xC0},
+
+ {VIACR,CR55,0x80,0x00},
+ {VIACR,CR5D,0x80,0x00},
+
+ {VIAGR,GR20,0xFF,0x00},
+ {VIAGR,GR21,0xFF,0x00},
+ {VIAGR,GR22,0xFF,0x00},
+ /* LCD Parameters */
+ {VIACR,CR7A,0xFF,0x01}, /* LCD Parameter 1 */
+ {VIACR,CR7B,0xFF,0x02}, /* LCD Parameter 2 */
+ {VIACR,CR7C,0xFF,0x03}, /* LCD Parameter 3 */
+ {VIACR,CR7D,0xFF,0x04}, /* LCD Parameter 4 */
+ {VIACR,CR7E,0xFF,0x07}, /* LCD Parameter 5 */
+ {VIACR,CR7F,0xFF,0x0A}, /* LCD Parameter 6 */
+ {VIACR,CR80,0xFF,0x0D}, /* LCD Parameter 7 */
+ {VIACR,CR81,0xFF,0x13}, /* LCD Parameter 8 */
+ {VIACR,CR82,0xFF,0x16}, /* LCD Parameter 9 */
+ {VIACR,CR83,0xFF,0x19}, /* LCD Parameter 10 */
+ {VIACR,CR84,0xFF,0x1C}, /* LCD Parameter 11 */
+ {VIACR,CR85,0xFF,0x1D}, /* LCD Parameter 12 */
+ {VIACR,CR86,0xFF,0x1E}, /* LCD Parameter 13 */
+ {VIACR,CR87,0xFF,0x1F}, /* LCD Parameter 14 */
+
+};
+
+static struct io_reg KM400_ModeXregs[] = {
+ {VIASR, SR10, 0xFF, 0x01}, /* Unlock Register */
+ {VIASR, SR16, 0xFF, 0x08}, /* Display FIFO threshold Control */
+ {VIASR, SR17, 0xFF, 0x1F}, /* Display FIFO Control */
+ {VIASR, SR18, 0xFF, 0x4E}, /* GFX PREQ threshold */
+ {VIASR, SR1A, 0xFF, 0x0a}, /* GFX PREQ threshold */
+ {VIASR, SR1F, 0xFF, 0x00}, /* Memory Control 0 */
+ {VIASR, SR1B, 0xFF, 0xF0}, /* Power Management Control 0 */
+ {VIASR, SR1E, 0x0F, 0x01}, /* Power Management Control */
+ {VIASR, SR20, 0xFF, 0x00}, /* Sequencer Arbiter Control 0 */
+ {VIASR, SR21, 0xFF, 0x00}, /* Sequencer Arbiter Control 1 */
+ {VIASR, SR22, 0xFF, 0x1F}, /* Display Arbiter Control 1 */
+ {VIASR, SR2A, 0xF0, 0x00}, /* Power Management Control 5 */
+ {VIASR, SR2D, 0xFF, 0xFF}, /* Power Management Control 1 */
+ {VIASR, SR2E, 0xFF, 0xFF}, /* Power Management Control 2 */
+ {VIACR, CR0A, 0xFF, 0x1E}, /* Cursor Start */
+ {VIACR, CR0B, 0xFF, 0x00}, /* Cursor End */
+ {VIACR, CR0E, 0xFF, 0x00}, /* Cursor Location High */
+ {VIACR, CR0F, 0xFF, 0x00}, /* Cursor Localtion Low */
+ {VIACR, CR33, 0xFF, 0x00},
+ {VIACR, CR55, 0x80, 0x00},
+ {VIACR, CR5D, 0x80, 0x00},
+ {VIACR, CR36, 0xFF, 0x01}, /* Power Mangement 3 */
+ {VIACR, CR62, 0xFF, 0x00}, /* Secondary Display Starting Address */
+ {VIACR, CR63, 0xFF, 0x00}, /* Secondary Display Starting Address */
+ {VIACR, CR64, 0xFF, 0x00}, /* Secondary Display Starting Address */
+ {VIACR, CR68, 0xFF, 0x67}, /* Default FIFO For IGA2 */
+ {VIACR, CR6A, 0x20, 0x20}, /* Extended FIFO On */
+ {VIACR, CR7A, 0xFF, 0x01}, /* LCD Scaling Parameter 1 */
+ {VIACR, CR7B, 0xFF, 0x02}, /* LCD Scaling Parameter 2 */
+ {VIACR, CR7C, 0xFF, 0x03}, /* LCD Scaling Parameter 3 */
+ {VIACR, CR7D, 0xFF, 0x04}, /* LCD Scaling Parameter 4 */
+ {VIACR, CR7E, 0xFF, 0x07}, /* LCD Scaling Parameter 5 */
+ {VIACR, CR7F, 0xFF, 0x0A}, /* LCD Scaling Parameter 6 */
+ {VIACR, CR80, 0xFF, 0x0D}, /* LCD Scaling Parameter 7 */
+ {VIACR, CR81, 0xFF, 0x13}, /* LCD Scaling Parameter 8 */
+ {VIACR, CR82, 0xFF, 0x16}, /* LCD Scaling Parameter 9 */
+ {VIACR, CR83, 0xFF, 0x19}, /* LCD Scaling Parameter 10 */
+ {VIACR, CR84, 0xFF, 0x1C}, /* LCD Scaling Parameter 11 */
+ {VIACR, CR85, 0xFF, 0x1D}, /* LCD Scaling Parameter 12 */
+ {VIACR, CR86, 0xFF, 0x1E}, /* LCD Scaling Parameter 13 */
+ {VIACR, CR87, 0xFF, 0x1F}, /* LCD Scaling Parameter 14 */
+ {VIACR, CR88, 0xFF, 0x40}, /* LCD Panel Type */
+ {VIACR, CR89, 0xFF, 0x00}, /* LCD Timing Control 0 */
+ {VIACR, CR8A, 0xFF, 0x88}, /* LCD Timing Control 1 */
+ {VIACR, CR8B, 0xFF, 0x2D}, /* LCD Power Sequence Control 0 */
+ {VIACR, CR8C, 0xFF, 0x2D}, /* LCD Power Sequence Control 1 */
+ {VIACR, CR8D, 0xFF, 0xC8}, /* LCD Power Sequence Control 2 */
+ {VIACR, CR8E, 0xFF, 0x36}, /* LCD Power Sequence Control 3 */
+ {VIACR, CR8F, 0xFF, 0x00}, /* LCD Power Sequence Control 4 */
+ {VIACR, CR90, 0xFF, 0x10}, /* LCD Power Sequence Control 5 */
+ {VIACR, CR91, 0xFF, 0xA0}, /* 24/12 bit LVDS Data off */
+ {VIACR, CR96, 0xFF, 0x03}, /* TV on DVP0 ; DVP0 Clock Skew */
+ {VIACR, CR97, 0xFF, 0x03}, /* TV on DFP high ; DFPH Clock Skew */
+ {VIACR, CR99, 0xFF, 0x03}, /* DFP low ; DFPL Clock Skew */
+ {VIACR, CR9B, 0xFF, 0x07} /* DVI on DVP1 ; DVP1 Clock Skew */
+};
+#define NUM_TOTAL_KM400_ModeXregs ARRAY_SIZE(KM400_ModeXregs)
+
+static struct io_reg CN400_ModeXregs[] = {
+ {VIASR, SR10, 0xFF, 0x01},
+ {VIASR, SR15, 0x02, 0x02},
+ {VIASR, SR16, 0xBF, 0x08},
+ {VIASR, SR17, 0xFF, 0x1F},
+ {VIASR, SR18, 0xFF, 0x4E},
+ {VIASR, SR1A, 0xFB, 0x08},
+ {VIASR, SR1E, 0x0F, 0x01},
+ {VIASR, SR2A, 0xF0, 0x00},
+ {VIACR, CR0A, 0xFF, 0x1E}, /* Cursor Start */
+ {VIACR, CR0B, 0xFF, 0x00}, /* Cursor End */
+ {VIACR, CR0E, 0xFF, 0x00}, /* Cursor Location High */
+ {VIACR, CR0F, 0xFF, 0x00}, /* Cursor Localtion Low */
+ {VIACR, CR32, 0xFF, 0x00},
+ {VIACR, CR33, 0xFF, 0x00},
+ {VIACR, CR34, 0xFF, 0x00},
+ {VIACR, CR35, 0xFF, 0x00},
+ {VIACR, CR36, 0x08, 0x00},
+ {VIACR, CR62, 0xFF, 0x00}, /* Secondary Display Starting Address */
+ {VIACR, CR63, 0xFF, 0x00}, /* Secondary Display Starting Address */
+ {VIACR, CR64, 0xFF, 0x00}, /* Secondary Display Starting Address */
+ {VIACR, CR69, 0xFF, 0x00},
+ {VIACR, CR6A, 0xFF, 0x40},
+ {VIACR, CR6B, 0xFF, 0x00},
+ {VIACR, CR6C, 0xFF, 0x00},
+ {VIACR, CR7A, 0xFF, 0x01}, /* LCD Scaling Parameter 1 */
+ {VIACR, CR7B, 0xFF, 0x02}, /* LCD Scaling Parameter 2 */
+ {VIACR, CR7C, 0xFF, 0x03}, /* LCD Scaling Parameter 3 */
+ {VIACR, CR7D, 0xFF, 0x04}, /* LCD Scaling Parameter 4 */
+ {VIACR, CR7E, 0xFF, 0x07}, /* LCD Scaling Parameter 5 */
+ {VIACR, CR7F, 0xFF, 0x0A}, /* LCD Scaling Parameter 6 */
+ {VIACR, CR80, 0xFF, 0x0D}, /* LCD Scaling Parameter 7 */
+ {VIACR, CR81, 0xFF, 0x13}, /* LCD Scaling Parameter 8 */
+ {VIACR, CR82, 0xFF, 0x16}, /* LCD Scaling Parameter 9 */
+ {VIACR, CR83, 0xFF, 0x19}, /* LCD Scaling Parameter 10 */
+ {VIACR, CR84, 0xFF, 0x1C}, /* LCD Scaling Parameter 11 */
+ {VIACR, CR85, 0xFF, 0x1D}, /* LCD Scaling Parameter 12 */
+ {VIACR, CR86, 0xFF, 0x1E}, /* LCD Scaling Parameter 13 */
+ {VIACR, CR87, 0xFF, 0x1F}, /* LCD Scaling Parameter 14 */
+ {VIACR, CR88, 0xFF, 0x40}, /* LCD Panel Type */
+ {VIACR, CR89, 0xFF, 0x00}, /* LCD Timing Control 0 */
+ {VIACR, CR8A, 0xFF, 0x88}, /* LCD Timing Control 1 */
+ {VIACR, CR8B, 0xFF, 0x69}, /* LCD Power Sequence Control 0 */
+ {VIACR, CR8C, 0xFF, 0x57}, /* LCD Power Sequence Control 1 */
+ {VIACR, CR8D, 0xFF, 0x00}, /* LCD Power Sequence Control 2 */
+ {VIACR, CR8E, 0xFF, 0x7B}, /* LCD Power Sequence Control 3 */
+ {VIACR, CR8F, 0xFF, 0x03}, /* LCD Power Sequence Control 4 */
+ {VIACR, CR90, 0xFF, 0x30}, /* LCD Power Sequence Control 5 */
+ {VIACR, CR91, 0xFF, 0xA0}, /* 24/12 bit LVDS Data off */
+ {VIACR, CR96, 0xFF, 0x00},
+ {VIACR, CR97, 0xFF, 0x00},
+ {VIACR, CR99, 0xFF, 0x00},
+ {VIACR, CR9B, 0xFF, 0x00}
+};
+#define NUM_TOTAL_CN400_ModeXregs ARRAY_SIZE(CN400_ModeXregs)
+
+/* Video Mode Table for VT3314 chipset*/
+/* Common Setting for Video Mode */
+static struct io_reg CN900_ModeXregs[] = {
+ {VIASR,SR10,0xFF,0x01},
+ {VIASR,SR15,0x02,0x02},
+ {VIASR,SR16,0xBF,0x08},
+ {VIASR,SR17,0xFF,0x1F},
+ {VIASR,SR18,0xFF,0x4E},
+ {VIASR,SR1A,0xFB,0x82},
+ {VIASR,SR1B,0xFF,0xF0},
+ {VIASR,SR1F,0xFF,0x00},
+ {VIASR,SR1E,0xFF,0xF1},
+ {VIASR,SR22,0xFF,0x1F},
+ {VIASR,SR2A,0x0F,0x0F},
+ {VIASR,SR2E,0xFF,0xFF},
+ {VIASR,SR3F,0xFF,0xFF},
+ {VIASR,SR40,0xFF,0x00},
+ {VIASR,CR30,0xFF,0x04},
+ {VIACR,CR32,0xFF,0x00},
+ {VIACR,CR33,0x7F,0x00},
+ {VIACR,CR34,0xFF,0x00},
+ {VIACR,CR35,0xFF,0x00},
+ {VIACR,CR36,0xFF,0x31},
+ {VIACR,CR41,0xFF,0x80},
+ {VIACR,CR42,0xFF,0x00},
+ {VIACR,CR55,0x80,0x00},
+ {VIACR,CR5D,0x80,0x00}, /*Horizontal Retrace Start bit[11] should be 0*/
+ {VIACR,CR62,0xFF,0x00}, /* Secondary Display Starting Address*/
+ {VIACR,CR63,0xFF,0x00}, /* Secondary Display Starting Address*/
+ {VIACR,CR64,0xFF,0x00}, /* Secondary Display Starting Address*/
+ {VIACR,CR68,0xFF,0x67}, /* Default FIFO For IGA2 */
+ {VIACR,CR69,0xFF,0x00},
+ {VIACR,CR6A,0xFD,0x40},
+ {VIACR,CR6B,0xFF,0x00},
+ {VIACR,CR6C,0xFF,0x00},
+ {VIACR,CR77,0xFF,0x00}, /* LCD scaling Factor*/
+ {VIACR,CR78,0xFF,0x00}, /* LCD scaling Factor */
+ {VIACR,CR79,0xFF,0x00}, /* LCD scaling Factor*/
+ {VIACR,CR9F,0x03,0x00}, /* LCD scaling Factor */
+ {VIACR,CR7A,0xFF,0x01}, /* LCD Scaling Parameter 1*/
+ {VIACR,CR7B,0xFF,0x02}, /* LCD Scaling Parameter 2*/
+ {VIACR,CR7C,0xFF,0x03}, /* LCD Scaling Parameter 3 */
+ {VIACR,CR7D,0xFF,0x04}, /* LCD Scaling Parameter 4*/
+ {VIACR,CR7E,0xFF,0x07}, /* LCD Scaling Parameter 5*/
+ {VIACR,CR7F,0xFF,0x0A}, /* LCD Scaling Parameter 6*/
+ {VIACR,CR80,0xFF,0x0D}, /* LCD Scaling Parameter 7*/
+ {VIACR,CR81,0xFF,0x13}, /* LCD Scaling Parameter 8*/
+ {VIACR,CR82,0xFF,0x16}, /* LCD Scaling Parameter 9*/
+ {VIACR,CR83,0xFF,0x19}, /* LCD Scaling Parameter 10*/
+ {VIACR,CR84,0xFF,0x1C}, /* LCD Scaling Parameter 11*/
+ {VIACR,CR85,0xFF,0x1D}, /* LCD Scaling Parameter 12*/
+ {VIACR,CR86,0xFF,0x1E}, /* LCD Scaling Parameter 13*/
+ {VIACR,CR87,0xFF,0x1F}, /* LCD Scaling Parameter 14*/
+ {VIACR,CR88,0xFF,0x40}, /* LCD Panel Type */
+ {VIACR,CR89,0xFF,0x00}, /* LCD Timing Control 0 */
+ {VIACR,CR8A,0xFF,0x88}, /* LCD Timing Control 1*/
+ {VIACR,CR8B,0xFF,0x5D}, /* LCD Power Sequence Control 0*/
+ {VIACR,CR8C,0xFF,0x2B}, /* LCD Power Sequence Control 1*/
+ {VIACR,CR8D,0xFF,0x6F}, /* LCD Power Sequence Control 2*/
+ {VIACR,CR8E,0xFF,0x2B}, /* LCD Power Sequence Control 3*/
+ {VIACR,CR8F,0xFF,0x01}, /* LCD Power Sequence Control 4*/
+ {VIACR,CR90,0xFF,0x01}, /* LCD Power Sequence Control 5*/
+ {VIACR,CR91,0xFF,0xA0}, /* 24/12 bit LVDS Data off*/
+ {VIACR,CR96,0xFF,0x00},
+ {VIACR,CR97,0xFF,0x00},
+ {VIACR,CR99,0xFF,0x00},
+ {VIACR,CR9B,0xFF,0x00},
+ {VIACR,CR9D,0xFF,0x80},
+ {VIACR,CR9E,0xFF,0x80}
+};
+#define NUM_TOTAL_CN900_ModeXregs ARRAY_SIZE(CN900_ModeXregs)
+
+/* For VT3324: Common Setting for Video Mode */
+static struct io_reg CX700_ModeXregs [] = {
+ {VIASR, SR10, 0xFF, 0x01},
+ {VIASR, SR15, 0x02, 0x02},
+ {VIASR, SR16, 0xBF, 0x08},
+ {VIASR, SR17, 0xFF, 0x1F},
+ {VIASR, SR18, 0xFF, 0x4E},
+ {VIASR, SR1A, 0xFB, 0x08},
+ {VIASR, SR1B, 0xFF, 0xF0},
+ {VIASR, SR1E, 0x0F, 0x01},
+ {VIASR, SR2A, 0xF0, 0x00},
+ {VIACR, CR0A, 0xFF, 0x1E}, /* Cursor Start */
+ {VIACR, CR0B, 0xFF, 0x00}, /* Cursor End */
+ {VIACR, CR0E, 0xFF, 0x00}, /* Cursor Location High */
+ {VIACR, CR0F, 0xFF, 0x00}, /* Cursor Localtion Low */
+ {VIACR, CR32, 0xFF, 0x00},
+ {VIACR, CR33, 0xFF, 0x00},
+ {VIACR, CR34, 0xFF, 0x00},
+ {VIACR, CR35, 0xFF, 0x00},
+ {VIACR, CR36, 0x08, 0x00},
+ {VIACR, CR47, 0xC8, 0x00}, /* Clear VCK Plus. */
+ {VIACR, CR62, 0xFF, 0x00}, /* Secondary Display Starting Address */
+ {VIACR, CR63, 0xFF, 0x00}, /* Secondary Display Starting Address */
+ {VIACR, CR64, 0xFF, 0x00}, /* Secondary Display Starting Address */
+ {VIACR, CRA3, 0xFF, 0x00}, /* Secondary Display Starting Address */
+ {VIACR, CR69, 0xFF, 0x00},
+ {VIACR, CR6A, 0xFF, 0x40},
+ {VIACR, CR6B, 0xFF, 0x00},
+ {VIACR, CR6C, 0xFF, 0x00},
+ {VIACR, CR7A, 0xFF, 0x01}, /* LCD Scaling Parameter 1 */
+ {VIACR, CR7B, 0xFF, 0x02}, /* LCD Scaling Parameter 2 */
+ {VIACR, CR7C, 0xFF, 0x03}, /* LCD Scaling Parameter 3 */
+ {VIACR, CR7D, 0xFF, 0x04}, /* LCD Scaling Parameter 4 */
+ {VIACR, CR7E, 0xFF, 0x07}, /* LCD Scaling Parameter 5 */
+ {VIACR, CR7F, 0xFF, 0x0A}, /* LCD Scaling Parameter 6 */
+ {VIACR, CR80, 0xFF, 0x0D}, /* LCD Scaling Parameter 7 */
+ {VIACR, CR81, 0xFF, 0x13}, /* LCD Scaling Parameter 8 */
+ {VIACR, CR82, 0xFF, 0x16}, /* LCD Scaling Parameter 9 */
+ {VIACR, CR83, 0xFF, 0x19}, /* LCD Scaling Parameter 10 */
+ {VIACR, CR84, 0xFF, 0x1C}, /* LCD Scaling Parameter 11 */
+ {VIACR, CR85, 0xFF, 0x1D}, /* LCD Scaling Parameter 12 */
+ {VIACR, CR86, 0xFF, 0x1E}, /* LCD Scaling Parameter 13 */
+ {VIACR, CR87, 0xFF, 0x1F}, /* LCD Scaling Parameter 14 */
+ {VIACR, CR88, 0xFF, 0x40}, /* LCD Panel Type */
+ {VIACR, CR89, 0xFF, 0x00}, /* LCD Timing Control 0 */
+ {VIACR, CR8A, 0xFF, 0x88}, /* LCD Timing Control 1 */
+ {VIACR, CRD4, 0xFF, 0x81}, /* Second power sequence control */
+ {VIACR, CR8B, 0xFF, 0x5D}, /* LCD Power Sequence Control 0 */
+ {VIACR, CR8C, 0xFF, 0x2B}, /* LCD Power Sequence Control 1 */
+ {VIACR, CR8D, 0xFF, 0x6F}, /* LCD Power Sequence Control 2 */
+ {VIACR, CR8E, 0xFF, 0x2B}, /* LCD Power Sequence Control 3 */
+ {VIACR, CR8F, 0xFF, 0x01}, /* LCD Power Sequence Control 4 */
+ {VIACR, CR90, 0xFF, 0x01}, /* LCD Power Sequence Control 5 */
+ {VIACR, CR91, 0xFF, 0x80}, /* 24/12 bit LVDS Data off */
+ {VIACR, CR96, 0xFF, 0x00},
+ {VIACR, CR97, 0xFF, 0x00},
+ {VIACR, CR99, 0xFF, 0x00},
+ {VIACR, CR9B, 0xFF, 0x00},
+ {VIACR, CRD2, 0xFF, 0xFF} /* TMDS/LVDS control register. */
+};
+#define NUM_TOTAL_CX700_ModeXregs ARRAY_SIZE(CX700_ModeXregs)
+
+extern int refresh;
+extern int tv_level;
+extern int tv_system;
+extern int tv_out_signal;
+extern int tv_dedotcrawl;
+extern int lcd_dsp_method;
+extern int lcd_mode;
+extern int second_virtual_xres;
+extern int bpp1;
+
+extern int accel;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+extern struct viafb_info viafbinfo;
+extern struct viafb_info viafbinfo1;
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+extern struct viafb_par parinfo;
+extern struct viafb_par parinfo1;
+#endif
+
+extern int CRT_ON, TV_ON, DVI_ON, LCD_ON, LCD2_ON, SAMM_ON,dual_fb;
+extern int lcd_panel_id;
+extern int HotPlug, DeviceStatus;
+extern int HotPlug_Xres, HotPlug_Yres, HotPlug_bpp, HotPlug_refresh;
+extern unsigned int second_offset;
+extern int second_size;
+extern int primary_dev;
+extern int display_hardware_layout;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)
+ extern void __iomem *FB_MM;
+#else
+ extern unsigned long FB_MM;
+#endif
+
+/* Access I/O Function */
+inline void write_reg(u8 index, u16 io_port, u8 data);
+void write_reg_mask(u8 index, int io_port, u8 data, u8 mask);
+inline u8 read_reg(int io_port, u8 index);
+inline void lock_crt(void);
+inline void unlock_crt(void);
+
+void set_crt_output_path(int set_iga);
+void set_tv_output_path(int set_iga, int output_interface);
+void set_dvi_output_path(int set_iga, int output_interface);
+void set_lcd_output_path(int set_iga, int output_interface);
+void SetVCLK( u32 CLK, int set_iga );
+void init_gfx_chip_info(void);
+void init_tv_chip_info(void);
+void init_tmds_chip_info(void);
+void init_lvds_chip_info(void);
+void load_reg(int timing_value, int load_reg_num, struct io_register *reg, int io_type);
+void device_off(void);
+void device_on(void);
+void crt_disable(void);
+void crt_enable(void);
+void enable_second_display_channel(void);
+void disable_second_display_channel(void);
+void lcd_patch_skew(struct lvds_setting_information *plvds_setting_info, struct lvds_chip_information *plvds_chip_info);
+int get_fb_size_from_pci(void);
+
+
+
+inline void write_reg(u8 index, u16 io_port, u8 data)
+{
+ outb(index, io_port);
+ outb(data, io_port+1);
+}
+
+void write_reg_mask(u8 index, int io_port, u8 data, u8 mask)
+{
+ u8 tmp;
+
+ outb(index, io_port);
+ tmp = inb(io_port+1);
+ outb((data & mask) | (tmp & (~mask)), io_port+1);
+}
+
+void write_dac_reg(u8 index, u8 r, u8 g, u8 b)
+{
+ outb(index, LUT_INDEX_WRITE);
+ outb(r, LUT_DATA);
+ outb(g, LUT_DATA);
+ outb(b, LUT_DATA);
+}
+
+inline u8 read_reg(int io_port, u8 index)
+{
+ outb(index, io_port);
+ return(inb(io_port+1));
+}
+
+inline void lock_crt(void)
+{
+ write_reg_mask(CR11, VIACR, BIT7, BIT7);
+}
+
+inline void unlock_crt(void)
+{
+ write_reg_mask(CR11, VIACR, 0, BIT7);
+ write_reg_mask(CR47, VIACR, 0, BIT0);
+}
+
+/* Set IGA path for each device */
+void set_iga_path(void)
+{
+
+ if (SAMM_ON == 1)
+ {
+ /* We can specify iga path by device order:
+ primary device uses IGA1, secondary device uses IGA2. */
+
+ if (CRT_ON)
+ {
+ if (primary_dev == CRT_Device)
+ {
+ crt_setting_info.iga_path = IGA1;
+ }
+ else
+ {
+ crt_setting_info.iga_path = IGA2;
+ }
+ }
+
+ if (TV_ON)
+ {
+ if (primary_dev == TV_Device)
+ {
+ tv_setting_info.iga_path = IGA1;
+ }
+ else
+ {
+ tv_setting_info.iga_path = IGA2;
+ }
+ }
+
+ if (DVI_ON)
+ {
+ if (primary_dev == DVI_Device)
+ {
+ tmds_setting_info.iga_path = IGA1;
+ }
+ else
+ {
+ tmds_setting_info.iga_path = IGA2;
+ }
+ }
+
+ if (LCD_ON)
+ {
+ if (primary_dev == LCD_Device)
+ {
+ /* Primary device LCD still use IGA2 on CLE266. */
+ if(dual_fb && (chip_info.gfx_chip_name==UNICHROME_CLE266)) {
+ lvds_setting_info.iga_path = IGA2;
+ crt_setting_info.iga_path = IGA1;
+ tv_setting_info.iga_path = IGA1;
+ tmds_setting_info.iga_path = IGA1;
+ }
+ else
+ lvds_setting_info.iga_path = IGA1;
+ }
+ else
+ {
+ lvds_setting_info.iga_path = IGA2;
+ }
+ }
+ if(LCD2_ON)
+ {
+ if(LCD2_Device == primary_dev)
+ {
+ lvds_setting_info2.iga_path = IGA1;
+ }else
+ {
+ lvds_setting_info2.iga_path = IGA2;
+ }
+ }
+ }
+ else
+ {
+ /* Use DuoView instead of Simultaneous. */
+
+ SAMM_ON =0;
+
+ if (CRT_ON && LCD_ON)
+ {
+ crt_setting_info.iga_path = IGA1;
+ lvds_setting_info.iga_path = IGA2;
+ }
+ else if (CRT_ON && DVI_ON)
+ {
+ crt_setting_info.iga_path = IGA1;
+ tmds_setting_info.iga_path = IGA2;
+ }
+ else if (CRT_ON && TV_ON)
+ {
+ crt_setting_info.iga_path = IGA1;
+ tv_setting_info.iga_path = IGA2;
+ }
+ else if (DVI_ON && TV_ON)
+ {
+ tmds_setting_info.iga_path = IGA1;
+ tv_setting_info.iga_path = IGA2;
+ }
+ else if (LCD_ON && TV_ON)
+ {
+ tv_setting_info.iga_path = IGA1;
+ lvds_setting_info.iga_path = IGA2;
+ }
+ else if (LCD_ON && DVI_ON)
+ {
+ tmds_setting_info.iga_path = IGA1;
+ lvds_setting_info.iga_path = IGA2;
+ }else if(LCD_ON&&LCD2_ON)
+ {
+ lvds_setting_info.iga_path = IGA2;
+ lvds_setting_info2.iga_path = IGA2;
+ }
+ else if (CRT_ON)
+ {
+ crt_setting_info.iga_path = IGA1;
+ }
+ else if (TV_ON)
+ {
+ tv_setting_info.iga_path = IGA1;
+ }
+ else if (LCD_ON)
+ {
+ lvds_setting_info.iga_path = IGA2;
+ }
+ else if (DVI_ON)
+ {
+ tmds_setting_info.iga_path = IGA1;
+ }
+ }
+}
+
+void set_start_addr(void)
+{
+ DEBUG_MSG(KERN_INFO "set_start_addr!\n" );
+ unlock_crt();
+
+ /* Update starting address */
+ write_reg(CR0C, VIACR, 0x00); /* Initial starting address */
+ write_reg(CR0D, VIACR, 0x00);
+ write_reg(CR34, VIACR, 0x00);
+ write_reg_mask(CR48, VIACR, 0x00, BIT0+BIT1);
+
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+ if(dual_fb) {
+ /* This setting is for HW accel in dual-fb */
+ parinfo.iga_path = IGA1;
+ parinfo1.iga_path = IGA2;
+ }
+ #endif
+
+ if(SAMM_ON==1)
+ {
+ unsigned long offset,tmp,size;
+ unsigned long length;
+ if(!dual_fb) {
+ /* When no dual-fb, can dynamic set second_size */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+ if(second_size && (second_size*1024*1024 >= (viafbinfo.memsize - (16*1024*1024))))
+ second_size = (viafbinfo.memsize>>20) - 16;
+
+ if(second_size && (second_size*1024*1024 <= (16*1024*1024)) && (second_size > 0))
+ second_size = 16;
+
+ if(second_size)
+ {
+ second_offset = viafbinfo.memsize - second_size*1024*1024;
+ size=second_size*1024*1024;
+ }
+ else
+ {
+ second_offset = viafbinfo.memsize >> 1;
+ size== viafbinfo.memsize >> 1;
+ }
+#else
+ if(second_size && (second_size*1024*1024 >= (parinfo.memsize - (16*1024*1024))))
+ second_size = (parinfo.memsize>>20) - 16;
+
+ if(second_size && (second_size *1024*1024<= (16*1024*1024)) && (second_size > 0))
+ second_size = 16;
+
+ if(second_size)
+ {
+ second_offset = parinfo.memsize - second_size*1024*1024;
+ size=second_size*1024*1024;
+ }
+ else
+ {
+ second_offset = parinfo.memsize >> 1;
+ size=parinfo.memsize >> 1;
+ }
+#endif
+ }
+ else { /* dual-fb is enabled */
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+ size = viafbinfo1.memsize;
+ #else
+ size = parinfo1.memsize;
+ #endif
+ }
+ offset = second_offset;
+ DEBUG_MSG(KERN_INFO"second_size=%x, second start_adddress=%x\n",size,offset);
+ offset=offset>>3;
+
+ tmp = read_reg(VIACR, 0x62) & 0x01;
+ tmp |= (offset & 0x7F) << 1;
+ write_reg(CR62, VIACR, tmp);
+ write_reg(CR63, VIACR, ((offset & 0x7F80) >> 7));
+ write_reg(CR64, VIACR, ((offset & 0x7F8000) >> 15));
+ write_reg(CRA3, VIACR, ((offset & 0x3800000) >> 23));
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+ length =size;
+#else
+ if(accel) {
+ if(!dual_fb)
+ length = size - parinfo.fbmem_used;
+ else
+ length = size - parinfo1.fbmem_used;
+ }
+ else
+ length = size;
+#endif
+
+ offset=(unsigned long)(void *)FB_MM+second_offset;
+ memset_io((void *)offset, 0, length);
+ }
+ else
+ {
+ /* Update starting address */
+ write_reg(CR62, VIACR, 0x00);
+ write_reg(CR63, VIACR, 0x00);
+ write_reg(CR64, VIACR, 0x00);
+ write_reg(CRA3, VIACR, 0x00);
+ }
+
+ lock_crt();
+}
+
+void set_output_path(int device, int set_iga, int output_interface)
+{
+ switch(device) {
+ case DEVICE_CRT:
+ set_crt_output_path(set_iga);
+ break;
+ case DEVICE_TV:
+ set_tv_output_path(set_iga, output_interface);
+ break;
+ case DEVICE_DVI:
+ set_dvi_output_path(set_iga, output_interface);
+ break;
+ case DEVICE_LCD:
+ set_lcd_output_path(set_iga, output_interface);
+ break;
+ }
+}
+
+void set_crt_output_path(int set_iga)
+{
+ write_reg_mask(CR36, VIACR, 0x00, BIT4+BIT5);
+
+ switch(set_iga) {
+ case IGA1:
+ write_reg_mask(SR16, VIASR, 0x00, BIT6);
+ break;
+ case IGA2:
+ case IGA1_IGA2:
+ write_reg_mask(CR6A, VIACR, 0xC0, BIT6+BIT7);
+ write_reg_mask(SR16, VIASR, 0x40, BIT6);
+ if (set_iga == IGA1_IGA2)
+ write_reg_mask(CR6B, VIACR, 0x08, BIT3);
+ break;
+ }
+}
+
+void set_tv_output_path(int set_iga, int output_interface)
+{
+ DEBUG_MSG(KERN_INFO "set_tv_output_path, iga:%d,out_interface:%d\n", set_iga, output_interface);
+ switch(set_iga)
+ {
+ case IGA1:
+ /* Set IGA1 display channel to normal case beside CLE266.AX chip
+ and disable simultaneous display. */
+ if ((chip_info.gfx_chip_name == UNICHROME_CLE266) && (chip_info.gfx_chip_revision == CLE266_REVISION_AX))
+ {
+ SetVCLK(0x471c, IGA1);
+ write_reg_mask(CR6B, VIACR, 0xC0, BIT3+BIT6+BIT7);
+ }
+ else
+ {
+ write_reg_mask(CR6B, VIACR, 0x00, BIT3+BIT6+BIT7);
+ }
+
+ /* TV path selection: */
+ write_reg_mask(CR6C, VIACR, 0x00, BIT7);
+
+ break;
+ case IGA2:
+ /* Set IGA2 display channel to normal case beside CLE266.AX chip
+ and disable simultaneous display. Modify for sequence issue. */
+ enable_second_display_channel();
+
+ if (chip_info.gfx_chip_name == UNICHROME_CLE266 && chip_info.gfx_chip_revision == CLE266_REVISION_AX)
+ {
+ write_reg_mask(CR6B, VIACR, 0x30, BIT3+BIT4+BIT5);
+ }
+ else
+ {
+ write_reg_mask(CR6B, VIACR, 0x00, BIT3+BIT6+BIT7);
+ }
+
+ /* Disable LCD Scaling */
+ write_reg_mask(CR79, VIACR, 0x00, BIT0);
+
+ /* TV path selection: */
+ write_reg_mask(CR6C, VIACR, 0x80, BIT7);
+
+ break;
+ case IGA1_IGA2:
+ /* Set IGA1_IGA2 display channel to normal case beside CLE266.AX chip
+ and enable simultaneous display. Modify for sequence issue. */
+ enable_second_display_channel();
+
+ if (chip_info.gfx_chip_name == UNICHROME_CLE266 && chip_info.gfx_chip_revision == CLE266_REVISION_AX)
+ {
+ write_reg_mask(CR6B, VIACR, 0xC0, BIT3+BIT6+BIT7);
+ }
+ else
+ {
+ write_reg_mask(CR6B, VIACR, 0x00, BIT3+BIT6+BIT7);
+ }
+
+ /* TV path selection: */
+ write_reg_mask(CR6C, VIACR, 0x80, BIT7);
+
+ break;
+ }
+
+ switch(output_interface)
+ {
+ case INTERFACE_DVP0:
+ if (set_iga == IGA1)
+ {
+ /* Except CLE266, we also need to set CR96[4] for DVP0 Data Source Selection. */
+ if (chip_info.gfx_chip_name != UNICHROME_CLE266)
+ {
+ write_reg_mask(CR96, VIACR, 0x00, BIT4);
+ }
+ }
+ else
+ {
+ write_reg(CR91, VIACR, 0x00);
+
+ /* Except CLE266, we also need to set CR96[4] for DVP0 Data Source Selection. */
+ if (chip_info.gfx_chip_name != UNICHROME_CLE266)
+ {
+ write_reg_mask(CR96, VIACR, 0x10, BIT4);
+ }
+ }
+
+ if (chip_info.gfx_chip_name == UNICHROME_CLE266 && chip_info.gfx_chip_revision == CLE266_REVISION_AX)
+ {
+ write_reg_mask(CR6B, VIACR, 0x01, BIT0);
+ }
+ else
+ {
+ write_reg_mask(CR6B, VIACR, 0x00, BIT0);
+ }
+
+ write_reg_mask(SR1E, VIASR, 0xC0, BIT6+BIT7);
+ break;
+
+ case INTERFACE_DVP1:
+ if (set_iga== IGA1)
+ {
+ write_reg_mask(CR9B, VIACR, 0x00, BIT4);
+ }
+ else
+ {
+ write_reg(CR91, VIACR, 0x00);
+ write_reg_mask(CR9B, VIACR, 0x10, BIT4);
+ }
+
+ write_reg_mask(SR1E, VIASR, 0x30, BIT4+BIT5);
+ break;
+
+ case INTERFACE_DFP_HIGH:
+ if (set_iga== IGA1)
+ {
+ write_reg_mask(CR96, VIACR, 0x00, BIT4);
+ write_reg_mask(CR97, VIACR, 0x00, BIT4);
+ }
+ else
+ {
+ write_reg(CR91, VIACR, 0x00);
+ write_reg_mask(CR96, VIACR, 0x10, BIT4);
+ write_reg_mask(CR97, VIACR, 0x10, BIT4);
+ }
+
+ write_reg_mask(SR2A, VIASR, 0x0C, BIT2+BIT3);
+ break;
+
+ case INTERFACE_DFP_LOW:
+ if (set_iga== IGA1)
+ {
+ write_reg_mask(CR9B, VIACR, 0x00, BIT4);
+ write_reg_mask(CR99, VIACR, 0x00, BIT4);
+ }
+ else
+ {
+ write_reg(CR91, VIACR, 0x00);
+ write_reg_mask(CR9B, VIACR, 0x10, BIT4);
+ write_reg_mask(CR99, VIACR, 0x10, BIT4);
+ }
+
+ write_reg_mask(SR2A, VIASR, 0x03, BIT0+BIT1);
+ break;
+ }
+
+ set_tv_clock_source();
+}
+
+/* Add for adjusting clock skew. Modified from X driver code */
+void dvi_patch_skew_dvp0(void)
+{
+ /* Reset data driving first: */
+ write_reg_mask(SR1B, VIASR, 0, BIT1);
+ write_reg_mask(SR2A, VIASR, 0, BIT4);
+
+ switch (chip_info.gfx_chip_name)
+ {
+ case UNICHROME_P4M890:
+ {
+ if(( tmds_setting_info.h_active == 1600)&&( tmds_setting_info.v_active == 1200))
+ write_reg_mask(CR96, VIACR, 0x03, BIT0+BIT1+BIT2);
+ else
+ write_reg_mask(CR96, VIACR, 0x07, BIT0+BIT1+BIT2);
+ break;
+ }
+
+ case UNICHROME_P4M900:
+ {
+ write_reg_mask(CR96, VIACR, 0x07, BIT0+BIT1+BIT2+BIT3);
+ write_reg_mask(SR1B, VIASR, 0x02, BIT1);
+ write_reg_mask(SR2A, VIASR, 0x10, BIT4);
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+ }
+}
+
+void dvi_patch_skew_dvp_low(void)
+{
+ switch (chip_info.gfx_chip_name)
+ {
+ case UNICHROME_K8M890:
+ {
+ write_reg_mask(CR99, VIACR, 0x03, BIT0+BIT1);
+ break;
+ }
+
+ case UNICHROME_P4M900:
+ {
+ write_reg_mask(CR99, VIACR, 0x08, BIT0+BIT1+BIT2+BIT3);
+ break;
+ }
+
+ case UNICHROME_P4M890:
+ {
+ write_reg_mask(CR99, VIACR, 0x0F, BIT0+BIT1+BIT2+BIT3);
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+ }
+}
+
+void set_dvi_output_path(int set_iga, int output_interface)
+{
+ switch(output_interface)
+ {
+ case INTERFACE_DVP0:
+ write_reg_mask(CR6B, VIACR, 0x01, BIT0);
+
+ if (set_iga== IGA1)
+ {
+ write_reg_mask(CR96, VIACR, 0x00, BIT4);
+ write_reg_mask(CR6C, VIACR, 0x21, BIT0+BIT5+BIT7);
+ }
+ else
+ {
+ write_reg_mask(CR96, VIACR, 0x10, BIT4);
+ write_reg_mask(CR6C, VIACR, 0xA1, BIT0+BIT5+BIT7);
+ }
+
+ write_reg_mask(SR1E, VIASR, 0xC0, BIT7+BIT6);
+
+ /* Adjust clock skew to meet VT1632 chip. */
+ dvi_patch_skew_dvp0();
+ break;
+
+ case INTERFACE_DVP1:
+ if (chip_info.gfx_chip_name == UNICHROME_CLE266)
+ {
+ if (set_iga== IGA1)
+ write_reg_mask(CR93, VIACR, 0x21, BIT0+BIT5+BIT7);
+ else
+ write_reg_mask(CR93, VIACR, 0xA1, BIT0+BIT5+BIT7);
+ }
+ else
+ {
+ if (set_iga== IGA1)
+ write_reg_mask(CR9B, VIACR, 0x00, BIT4);
+ else
+ write_reg_mask(CR9B, VIACR, 0x10, BIT4);
+ }
+
+ write_reg_mask(SR1E, VIASR, 0x30, BIT4+BIT5);
+ break;
+ /* Add to support VT3327 VT3336 VT3364*/
+ case INTERFACE_DFP_HIGH:
+ if (chip_info.gfx_chip_name != UNICHROME_CLE266)
+ {
+ if (set_iga== IGA1)
+ {
+ write_reg_mask(CR96, VIACR, 0x00, BIT4);
+ write_reg_mask(CR97, VIACR, 0x03, BIT0+BIT1+BIT4);
+ }
+ else
+ {
+ write_reg_mask(CR96, VIACR, 0x10, BIT4);
+ write_reg_mask(CR97, VIACR, 0x13, BIT0+BIT1+BIT4);
+ }
+ }
+ write_reg_mask(SR2A, VIASR, 0x0C, BIT2+BIT3);
+ break;
+
+ case INTERFACE_DFP_LOW:
+ if (chip_info.gfx_chip_name == UNICHROME_CLE266)
+ {
+ break;
+ }
+
+ if (set_iga == IGA1)
+ {
+ write_reg_mask(CR99, VIACR, 0x00, BIT4);
+ write_reg_mask(CR9B, VIACR, 0x00, BIT4);
+ }
+ else
+ {
+ write_reg_mask(CR99, VIACR, 0x10, BIT4);
+ write_reg_mask(CR9B, VIACR, 0x10, BIT4);
+ }
+
+ write_reg_mask(SR2A, VIASR, 0x03, BIT0+BIT1);
+ dvi_patch_skew_dvp_low();
+ break;
+
+ case INTERFACE_TMDS:
+ if (set_iga == IGA1)
+ {
+ write_reg_mask(CR99, VIACR, 0x00, BIT4);
+ }
+ else
+ {
+ write_reg_mask(CR99, VIACR, 0x10, BIT4);
+ }
+ break;
+ }
+
+ if (set_iga == IGA2)
+ {
+ enable_second_display_channel();
+ /* Disable LCD Scaling */
+ write_reg_mask(CR79, VIACR, 0x00, BIT0);
+ }
+}
+
+void set_lcd_output_path(int set_iga, int output_interface)
+{
+ DEBUG_MSG(KERN_INFO "set_lcd_output_path, iga:%d,out_interface:%d\n", set_iga, output_interface);
+ switch(set_iga)
+ {
+ case IGA1:
+ write_reg_mask(CR6B, VIACR, 0x00, BIT3);
+ write_reg_mask(CR6A, VIACR, 0x08, BIT3);
+
+ /* Modify for sequence issue. */
+ disable_second_display_channel();
+ break;
+
+ case IGA2:
+ write_reg_mask(CR6B, VIACR, 0x00, BIT3);
+ write_reg_mask(CR6A, VIACR, 0x08, BIT3);
+
+ /* Modify for sequence issue. */
+ enable_second_display_channel();
+ break;
+
+ case IGA1_IGA2:
+ write_reg_mask(CR6B, VIACR, 0x08, BIT3);
+ write_reg_mask(CR6A, VIACR, 0x08, BIT3);
+
+ /* Modify for sequence issue. */
+ disable_second_display_channel();
+ break;
+ }
+
+ switch(output_interface)
+ {
+ case INTERFACE_DVP0:
+ if (set_iga == IGA1)
+ {
+ write_reg_mask(CR96, VIACR, 0x00, BIT4);
+ }
+ else
+ {
+ write_reg(CR91, VIACR, 0x00);
+ write_reg_mask(CR96, VIACR, 0x10, BIT4);
+ }
+ break;
+
+ case INTERFACE_DVP1:
+ if (set_iga== IGA1)
+ write_reg_mask(CR9B, VIACR, 0x00, BIT4);
+ else
+ {
+ write_reg(CR91, VIACR, 0x00);
+ write_reg_mask(CR9B, VIACR, 0x10, BIT4);
+ }
+ break;
+
+ case INTERFACE_DFP_HIGH:
+ if (set_iga== IGA1)
+ write_reg_mask(CR97, VIACR, 0x00, BIT4);
+ else
+ {
+ write_reg(CR91, VIACR, 0x00);
+ write_reg_mask(CR97, VIACR, 0x10, BIT4);
+ write_reg_mask(CR96, VIACR, 0x10, BIT4);
+ }
+ break;
+
+ case INTERFACE_DFP_LOW:
+ if (set_iga== IGA1)
+ write_reg_mask(CR99, VIACR, 0x00, BIT4);
+ else
+ {
+ write_reg(CR91, VIACR, 0x00);
+ write_reg_mask(CR99, VIACR, 0x10, BIT4);
+ write_reg_mask(CR9B, VIACR, 0x10, BIT4);
+ }
+
+ break;
+
+ case INTERFACE_DFP:
+ if((UNICHROME_K8M890 == chip_info.gfx_chip_name) ||(UNICHROME_P4M890 == chip_info.gfx_chip_name))
+ write_reg_mask(CR97, VIACR, 0x84, BIT7+BIT2+BIT1+BIT0);
+ if (set_iga== IGA1)
+ {
+ write_reg_mask(CR97, VIACR, 0x00, BIT4);
+ write_reg_mask(CR99, VIACR, 0x00, BIT4);
+ }
+ else
+ {
+ write_reg(CR91, VIACR, 0x00);
+ write_reg_mask(CR97, VIACR, 0x10, BIT4);
+ write_reg_mask(CR99, VIACR, 0x10, BIT4);
+ }
+ break;
+
+ /* Add for VT3324 integrated LVDS. */
+ case INTERFACE_LVDS0:
+ case INTERFACE_LVDS0LVDS1:
+ if (set_iga == IGA1)
+ {
+ write_reg_mask(CR99, VIACR, 0x00, BIT4);
+ }
+ else
+ {
+ write_reg_mask(CR99, VIACR, 0x10, BIT4);
+ }
+
+ break;
+
+ case INTERFACE_LVDS1:
+ if (set_iga == IGA1)
+ {
+ write_reg_mask(CR97, VIACR, 0x00, BIT4);
+ }
+ else
+ {
+ write_reg_mask(CR97, VIACR, 0x10, BIT4);
+ }
+
+ break;
+ }
+}
+
+/* Search Mode Index */
+int SearchModeSetting(int ModeInfoIndex)
+{
+ int i=0;
+
+ while ( ( i<NUM_TOTAL_MODETABLE ) && ( ModeInfoIndex != CLE266Modes[i].ModeIndex) ){i++;}
+ if( ( i >= NUM_TOTAL_MODETABLE ) ) i=0;
+ return i;
+
+}
+
+void load_fix_bit_crtc_reg(void)
+{
+ write_reg_mask(CR03, VIACR, 0x80, BIT7); /* always set to 1 */
+ write_reg(CR18, VIACR, 0xff); /* line compare should set all bits = 1 (extend modes) */
+ write_reg_mask(CR07, VIACR, 0x10, BIT4); /* line compare should set all bits = 1 (extend modes) */
+ write_reg_mask(CR09, VIACR, 0x40, BIT6); /* line compare should set all bits = 1 (extend modes) */
+ write_reg_mask(CR35, VIACR, 0x10, BIT4); /* line compare should set all bits = 1 (extend modes) */
+ write_reg_mask(CR33, VIACR, 0x06, BIT0+BIT1+BIT2); /* line compare should set all bits = 1 (extend modes) */
+ write_reg(CR17, VIACR, 0xe3); /* extend mode always set to e3h */
+ write_reg(CR08, VIACR, 0x00); /* extend mode always set to 0h */
+ write_reg(CR14, VIACR, 0x00); /* extend mode always set to 0h */
+
+ /* If K8M800, enable Prefetch Mode. */
+ if((chip_info.gfx_chip_name == UNICHROME_K800) || (chip_info.gfx_chip_name == UNICHROME_K8M890))
+ {
+ write_reg_mask(CR33, VIACR, 0x08, BIT3);
+ }
+ /* Fix the bug: linux video driver conflict with via frame buffer diver on EPIA-M board */
+ if ((chip_info.gfx_chip_name == UNICHROME_CLE266) && (chip_info.gfx_chip_revision == CLE266_REVISION_AX))
+ write_reg_mask(SR1A, VIASR, 0x02, BIT1);
+
+}
+
+void load_reg(int timing_value, int load_reg_num, struct io_register *reg, int io_type)
+{
+ int reg_mask;
+ int bit_num=0;
+ int data;
+ int i,j;
+ int shift_next_reg;
+ int start_index, end_index, cr_index;
+ u16 get_bit;
+
+
+
+ for (i=0; i<load_reg_num; i++)
+ {
+ reg_mask = 0;
+ data=0;
+ start_index = reg[i].start_bit;
+ end_index = reg[i].end_bit;
+ cr_index = reg[i].io_addr;
+
+ shift_next_reg = bit_num;
+ for(j=start_index;j<=end_index;j++)
+ {
+ reg_mask = reg_mask | (BIT0 << j);
+ get_bit = (timing_value & (BIT0 << bit_num));
+ data = data | ((get_bit >> shift_next_reg)<< start_index);
+ bit_num ++;
+ }
+ if (io_type == VIACR)
+ {
+ write_reg_mask(cr_index, VIACR, data, reg_mask);
+
+ }
+ else
+ {
+ write_reg_mask(cr_index, VIASR, data, reg_mask);
+ }
+
+ }
+
+}
+
+/* Write Registers */
+void write_regx(struct io_reg RegTable[],int ItemNum)
+{
+ int i;
+ unsigned char RegTemp;
+
+ for( i=0; i< ItemNum; i++ ){
+ outb( RegTable[i].index, RegTable[i].port );
+ RegTemp = inb(RegTable[i].port+1 );
+ RegTemp = ( RegTemp & ( ~RegTable[i].mask ) ) | RegTable[i].value ;
+ outb( RegTemp, RegTable[i].port+1 );
+ }
+}
+
+void load_offset_reg(int h_addr, int bpp_byte, int set_iga)
+{
+ int reg_value;
+ int load_reg_num;
+ struct io_register *reg;
+
+
+ switch(set_iga) {
+ case IGA1_IGA2:
+ case IGA1:
+ reg_value = IGA1_OFFSET_FORMULA(h_addr, bpp_byte);
+ load_reg_num = offset_reg.iga1_offset_reg.reg_num;
+ reg = offset_reg.iga1_offset_reg.reg;
+ load_reg(reg_value, load_reg_num, reg, VIACR);
+ if (set_iga == IGA1)
+ break;
+ case IGA2:
+ reg_value = IGA2_OFFSET_FORMULA(h_addr, bpp_byte);
+ load_reg_num = offset_reg.iga2_offset_reg.reg_num;
+ reg = offset_reg.iga2_offset_reg.reg;
+ load_reg(reg_value, load_reg_num, reg, VIACR);
+ break;
+ }
+}
+
+void load_fetch_count_reg(int h_addr, int bpp_byte, int set_iga)
+{
+ int reg_value;
+ int load_reg_num;
+ struct io_register *reg=NULL;
+
+ switch(set_iga) {
+ case IGA1_IGA2:
+ case IGA1:
+ reg_value = IGA1_FETCH_COUNT_FORMULA(h_addr, bpp_byte);
+ load_reg_num = fetch_count_reg.iga1_fetch_count_reg.reg_num;
+ reg = fetch_count_reg.iga1_fetch_count_reg.reg;
+ load_reg(reg_value, load_reg_num, reg, VIASR);
+ if (set_iga == IGA1)
+ break;
+ case IGA2:
+ reg_value = IGA2_FETCH_COUNT_FORMULA(h_addr, bpp_byte);
+ load_reg_num = fetch_count_reg.iga2_fetch_count_reg.reg_num;
+ reg = fetch_count_reg.iga2_fetch_count_reg.reg;
+ load_reg(reg_value, load_reg_num, reg, VIACR);
+ break;
+ }
+
+}
+
+
+void load_FIFO_reg(int set_iga, int hor_active, int ver_active)
+{
+ int reg_value;
+ int load_reg_num;
+ struct io_register *reg=NULL;
+ int iga1_fifo_max_depth=0, iga1_fifo_threshold=0, iga1_fifo_high_threshold=0, iga1_display_queue_expire_num=0;
+ int iga2_fifo_max_depth=0, iga2_fifo_threshold=0, iga2_fifo_high_threshold=0, iga2_display_queue_expire_num=0;
+
+
+ if (set_iga == IGA1)
+ {
+ if (chip_info.gfx_chip_name == UNICHROME_K800)
+ {
+ iga1_fifo_max_depth = K800_IGA1_FIFO_MAX_DEPTH;
+ iga1_fifo_threshold = K800_IGA1_FIFO_THRESHOLD;
+ iga1_fifo_high_threshold = K800_IGA1_FIFO_HIGH_THRESHOLD;
+ /* If resolution > 1280x1024, expire length = 64, else expire length = 128 */
+ if ((hor_active > 1280) && (ver_active > 1024))
+ iga1_display_queue_expire_num = 16;
+ else
+ iga1_display_queue_expire_num = K800_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
+
+ }
+
+ if (chip_info.gfx_chip_name == UNICHROME_P880)
+ {
+ iga1_fifo_max_depth = P880_IGA1_FIFO_MAX_DEPTH;
+ iga1_fifo_threshold = P880_IGA1_FIFO_THRESHOLD;
+ iga1_fifo_high_threshold = P880_IGA1_FIFO_HIGH_THRESHOLD;
+ iga1_display_queue_expire_num = P880_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
+
+ /* If resolution > 1280x1024, expire length = 64, else expire length = 128 */
+ if ((hor_active > 1280) && (ver_active > 1024))
+ iga1_display_queue_expire_num = 16;
+ else
+ iga1_display_queue_expire_num = P880_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
+ }
+
+ if (chip_info.gfx_chip_name == UNICHROME_CN900)
+ {
+ iga1_fifo_max_depth = CN900_IGA1_FIFO_MAX_DEPTH;
+ iga1_fifo_threshold = CN900_IGA1_FIFO_THRESHOLD;
+ iga1_fifo_high_threshold = CN900_IGA1_FIFO_HIGH_THRESHOLD;
+
+ /* If resolution > 1280x1024, expire length = 64, else expire length = 128 */
+ if ((hor_active > 1280) && (ver_active > 1024))
+ iga1_display_queue_expire_num = 16;
+ else
+ iga1_display_queue_expire_num = CN900_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
+ }
+
+ /* Add for VT3324. */
+ if (chip_info.gfx_chip_name == UNICHROME_CX700)
+ {
+ iga1_fifo_max_depth = CX700_IGA1_FIFO_MAX_DEPTH;
+ iga1_fifo_threshold = CX700_IGA1_FIFO_THRESHOLD;
+ iga1_fifo_high_threshold = CX700_IGA1_FIFO_HIGH_THRESHOLD;
+ iga1_display_queue_expire_num = CX700_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
+ }
+
+ /* Add for VT3327 VT3336 VT3364 */
+ if (chip_info.gfx_chip_name == UNICHROME_K8M890)
+ {
+ iga1_fifo_max_depth = K8M890_IGA1_FIFO_MAX_DEPTH;
+ iga1_fifo_threshold = K8M890_IGA1_FIFO_THRESHOLD;
+ iga1_fifo_high_threshold = K8M890_IGA1_FIFO_HIGH_THRESHOLD;
+ iga1_display_queue_expire_num = K8M890_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
+ }
+
+ if (chip_info.gfx_chip_name == UNICHROME_P4M890)
+ {
+ iga1_fifo_max_depth = P4M890_IGA1_FIFO_MAX_DEPTH;
+ iga1_fifo_threshold = P4M890_IGA1_FIFO_THRESHOLD;
+ iga1_fifo_high_threshold = P4M890_IGA1_FIFO_HIGH_THRESHOLD;
+ iga1_display_queue_expire_num = P4M890_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
+ }
+
+ if (chip_info.gfx_chip_name == UNICHROME_P4M900)
+ {
+ iga1_fifo_max_depth = P4M900_IGA1_FIFO_MAX_DEPTH;
+ iga1_fifo_threshold =P4M900_IGA1_FIFO_THRESHOLD;
+ iga1_fifo_high_threshold = P4M900_IGA1_FIFO_HIGH_THRESHOLD;
+ iga1_display_queue_expire_num = P4M900_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
+ }
+
+ /* Set Display FIFO Depath Select */
+ reg_value = IGA1_FIFO_DEPTH_SELECT_FORMULA(iga1_fifo_max_depth);
+ load_reg_num = display_fifo_depth_reg.iga1_fifo_depth_select_reg.reg_num;
+ reg = display_fifo_depth_reg.iga1_fifo_depth_select_reg.reg;
+ load_reg(reg_value, load_reg_num, reg, VIASR);
+
+ /* Set Display FIFO Threshold Select */
+ reg_value = IGA1_FIFO_THRESHOLD_FORMULA(iga1_fifo_threshold);
+ load_reg_num = fifo_threshold_select_reg.iga1_fifo_threshold_select_reg.reg_num;
+ reg = fifo_threshold_select_reg.iga1_fifo_threshold_select_reg.reg;
+ load_reg(reg_value, load_reg_num, reg, VIASR);
+
+ /* Set FIFO High Threshold Select */
+ reg_value = IGA1_FIFO_HIGH_THRESHOLD_FORMULA(iga1_fifo_high_threshold);
+ load_reg_num = fifo_high_threshold_select_reg.iga1_fifo_high_threshold_select_reg.reg_num;
+ reg = fifo_high_threshold_select_reg.iga1_fifo_high_threshold_select_reg.reg;
+ load_reg(reg_value, load_reg_num, reg, VIASR);
+
+ /* Set Display Queue Expire Num */
+ reg_value = IGA1_DISPLAY_QUEUE_EXPIRE_NUM_FORMULA(iga1_display_queue_expire_num);
+ load_reg_num = display_queue_expire_num_reg.iga1_display_queue_expire_num_reg.reg_num;
+ reg = display_queue_expire_num_reg.iga1_display_queue_expire_num_reg.reg;
+ load_reg(reg_value, load_reg_num, reg, VIASR);
+
+ }
+ else
+ {
+ if (chip_info.gfx_chip_name == UNICHROME_K800)
+ {
+ iga2_fifo_max_depth = K800_IGA2_FIFO_MAX_DEPTH;
+ iga2_fifo_threshold = K800_IGA2_FIFO_THRESHOLD;
+ iga2_fifo_high_threshold = K800_IGA2_FIFO_HIGH_THRESHOLD;
+
+ /* If resolution > 1280x1024, expire length = 64, else expire length = 128 */
+ if ((hor_active > 1280) && (ver_active > 1024))
+ iga2_display_queue_expire_num = 16;
+ else
+ iga2_display_queue_expire_num = K800_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
+ }
+
+ if (chip_info.gfx_chip_name == UNICHROME_P880)
+ {
+ iga2_fifo_max_depth = P880_IGA2_FIFO_MAX_DEPTH;
+ iga2_fifo_threshold = P880_IGA2_FIFO_THRESHOLD;
+ iga2_fifo_high_threshold = P880_IGA2_FIFO_HIGH_THRESHOLD;
+
+ /* If resolution > 1280x1024, expire length = 64, else expire length = 128 */
+ if ((hor_active > 1280) && (ver_active > 1024))
+ iga2_display_queue_expire_num = 16;
+ else
+ iga2_display_queue_expire_num = P880_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
+ }
+
+ if (chip_info.gfx_chip_name == UNICHROME_CN900)
+ {
+ iga2_fifo_max_depth = CN900_IGA2_FIFO_MAX_DEPTH;
+ iga2_fifo_threshold = CN900_IGA2_FIFO_THRESHOLD;
+ iga2_fifo_high_threshold = CN900_IGA2_FIFO_HIGH_THRESHOLD;
+
+ /* If resolution > 1280x1024, expire length = 64, else expire length = 128 */
+ if ((hor_active > 1280) && (ver_active > 1024))
+ iga2_display_queue_expire_num = 16;
+ else
+ iga2_display_queue_expire_num = CN900_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
+ }
+
+ /* Add for VT3324. */
+ if (chip_info.gfx_chip_name == UNICHROME_CX700)
+ {
+ iga2_fifo_max_depth = CX700_IGA2_FIFO_MAX_DEPTH;
+ iga2_fifo_threshold = CX700_IGA2_FIFO_THRESHOLD;
+ iga2_fifo_high_threshold = CX700_IGA2_FIFO_HIGH_THRESHOLD;
+ iga2_display_queue_expire_num = CX700_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
+ }
+
+ /* Add for VT3327 VT3336 VT3364 */
+ if (chip_info.gfx_chip_name == UNICHROME_K8M890)
+ {
+ iga2_fifo_max_depth = K8M890_IGA2_FIFO_MAX_DEPTH;
+ iga2_fifo_threshold = K8M890_IGA2_FIFO_THRESHOLD;
+ iga2_fifo_high_threshold = K8M890_IGA2_FIFO_HIGH_THRESHOLD;
+ iga2_display_queue_expire_num = K8M890_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
+ }
+
+ if (chip_info.gfx_chip_name == UNICHROME_P4M890)
+ {
+ iga2_fifo_max_depth = P4M890_IGA2_FIFO_MAX_DEPTH;
+ iga2_fifo_threshold = P4M890_IGA2_FIFO_THRESHOLD;
+ iga2_fifo_high_threshold = P4M890_IGA2_FIFO_HIGH_THRESHOLD;
+ iga2_display_queue_expire_num = P4M890_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
+ }
+
+ if (chip_info.gfx_chip_name == UNICHROME_P4M900)
+ {
+ iga2_fifo_max_depth = P4M900_IGA2_FIFO_MAX_DEPTH;
+ iga2_fifo_threshold = P4M900_IGA2_FIFO_THRESHOLD;
+ iga2_fifo_high_threshold = P4M900_IGA2_FIFO_HIGH_THRESHOLD;
+ iga2_display_queue_expire_num = P4M900_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
+ }
+
+ if (chip_info.gfx_chip_name == UNICHROME_K800)
+ {
+ /* Set Display FIFO Depath Select */
+ reg_value = IGA2_FIFO_DEPTH_SELECT_FORMULA(iga2_fifo_max_depth)-1; /* Patch LCD in IGA2 case */
+ load_reg_num = display_fifo_depth_reg.iga2_fifo_depth_select_reg.reg_num;
+ reg = display_fifo_depth_reg.iga2_fifo_depth_select_reg.reg;
+ load_reg(reg_value, load_reg_num, reg, VIACR);
+ }
+ else
+ {
+
+ /* Set Display FIFO Depath Select */
+ reg_value = IGA2_FIFO_DEPTH_SELECT_FORMULA(iga2_fifo_max_depth);
+ load_reg_num = display_fifo_depth_reg.iga2_fifo_depth_select_reg.reg_num;
+ reg = display_fifo_depth_reg.iga2_fifo_depth_select_reg.reg;
+ load_reg(reg_value, load_reg_num, reg, VIACR);
+ }
+
+ /* Set Display FIFO Threshold Select */
+ reg_value = IGA2_FIFO_THRESHOLD_FORMULA(iga2_fifo_threshold);
+ load_reg_num = fifo_threshold_select_reg.iga2_fifo_threshold_select_reg.reg_num;
+ reg = fifo_threshold_select_reg.iga2_fifo_threshold_select_reg.reg;
+ load_reg(reg_value, load_reg_num, reg, VIACR);
+
+ /* Set FIFO High Threshold Select */
+ reg_value = IGA2_FIFO_HIGH_THRESHOLD_FORMULA(iga2_fifo_high_threshold);
+ load_reg_num = fifo_high_threshold_select_reg.iga2_fifo_high_threshold_select_reg.reg_num;
+ reg = fifo_high_threshold_select_reg.iga2_fifo_high_threshold_select_reg.reg;
+ load_reg(reg_value, load_reg_num, reg, VIACR);
+
+ /* Set Display Queue Expire Num */
+ reg_value = IGA2_DISPLAY_QUEUE_EXPIRE_NUM_FORMULA(iga2_display_queue_expire_num);
+ load_reg_num = display_queue_expire_num_reg.iga2_display_queue_expire_num_reg.reg_num;
+ reg = display_queue_expire_num_reg.iga2_display_queue_expire_num_reg.reg;
+ load_reg(reg_value, load_reg_num, reg, VIACR);
+
+ }
+
+}
+
+u32 get_clk_value(int clk)
+{
+ int i;
+
+ for(i=0; i<NUM_TOTAL_PLL_TABLE; i++)
+ {
+ if(clk==pll_value[i].clk)
+ {
+ switch(chip_info.gfx_chip_name)
+ {
+ case UNICHROME_CLE266:
+ case UNICHROME_K400:
+ return(pll_value[i].cle266_pll);
+
+ case UNICHROME_K800:
+ case UNICHROME_P880:
+ case UNICHROME_CN900:
+ return(pll_value[i].k800_pll);
+
+ /* Add for VT3324 VT3327 VT3336 VT3364 */
+ case UNICHROME_CX700:
+ case UNICHROME_K8M890:
+ case UNICHROME_P4M890:
+ case UNICHROME_P4M900:
+ return (pll_value[i].cx700_pll);
+ }
+ }
+ }
+
+ DEBUG_MSG(KERN_INFO "Can't find match PLL value\n\n");
+ return(0);
+}
+
+/* Set VCLK */
+void SetVCLK( u32 CLK, int set_iga )
+{
+ unsigned char RegTemp;
+
+ /* H.W. Reset : ON */
+ write_reg_mask(CR17, VIACR, 0x00, BIT7);
+
+ if ((set_iga==IGA1) || (set_iga==IGA1_IGA2))
+ {
+ /* Change D,N FOR VCLK */
+ switch(chip_info.gfx_chip_name)
+ {
+ case UNICHROME_CLE266:
+ case UNICHROME_K400:
+ write_reg(SR46, VIASR, CLK/0x100);
+ write_reg(SR47, VIASR, CLK%0x100);
+ break;
+
+ case UNICHROME_K800:
+ case UNICHROME_P880:
+ case UNICHROME_CN900:
+ case UNICHROME_CX700: /* Add for VT3324 */
+ case UNICHROME_K8M890: /* Add for VT3336 */
+ case UNICHROME_P4M890: /* Add for VT3327 */
+ case UNICHROME_P4M900: /* Add for VT3364 */
+ write_reg(SR44, VIASR, CLK/0x10000);
+ DEBUG_MSG(KERN_INFO "\nSR44=%x", CLK/0x10000);
+ write_reg(SR45, VIASR, (CLK&0xFFFF)/0x100);
+ DEBUG_MSG(KERN_INFO "\nSR45=%x", (CLK&0xFFFF)/0x100);
+ write_reg(SR46, VIASR, CLK%0x100);
+ DEBUG_MSG(KERN_INFO "\nSR46=%x", CLK%0x100);
+ break;
+ }
+ }
+
+ if ((set_iga==IGA2) || (set_iga==IGA1_IGA2))
+ {
+ /* Change D,N FOR LCK */
+ switch(chip_info.gfx_chip_name)
+ {
+ case UNICHROME_CLE266:
+ case UNICHROME_K400:
+ write_reg(SR44, VIASR, CLK/0x100);
+ write_reg(SR45, VIASR, CLK%0x100);
+ break;
+
+ case UNICHROME_K800:
+ case UNICHROME_P880:
+ case UNICHROME_CN900:
+ case UNICHROME_CX700: /* Add for VT3324 */
+ case UNICHROME_K8M890: /* Add for VT3336 */
+ case UNICHROME_P4M890: /* Add for VT3327 */
+ case UNICHROME_P4M900: /* Add for VT3364 */
+ write_reg(SR4A, VIASR, CLK/0x10000);
+ write_reg(SR4B, VIASR, (CLK&0xFFFF)/0x100);
+ write_reg(SR4C, VIASR, CLK%0x100);
+ break;
+ }
+ }
+
+ /* H.W. Reset : OFF */
+ write_reg_mask(CR17, VIACR, 0x80, BIT7);
+
+ /* Reset PLL */
+ if ((set_iga==IGA1) || (set_iga==IGA1_IGA2))
+ {
+ write_reg_mask(SR40, VIASR, 0x02, BIT1);
+ write_reg_mask(SR40, VIASR, 0x00, BIT1);
+ }
+
+ if ((set_iga==IGA2) || (set_iga==IGA1_IGA2))
+ {
+ write_reg_mask(SR40, VIASR, 0x01, BIT0);
+ write_reg_mask(SR40, VIASR, 0x00, BIT0);
+ }
+
+ /* Fire! */
+ RegTemp = inb(VIARMisc);
+ outb(RegTemp | (BIT2+BIT3),VIAWMisc);
+}
+
+void load_crtc_timing(struct display_timing device_timing, int set_iga)
+{
+ int i;
+ int load_reg_num=0;
+ int reg_value=0;
+ struct io_register *reg=NULL;
+
+ unlock_crt();
+
+ for (i=0;i<12;i++)
+ {
+ if (set_iga == IGA1)
+ {
+ switch(i) {
+ case H_TOTAL_INDEX:
+ reg_value = IGA1_HOR_TOTAL_FORMULA(device_timing.hor_total);
+ load_reg_num = iga1_crtc_reg.hor_total.reg_num;
+ reg = iga1_crtc_reg.hor_total.reg;
+ break;
+ case H_ADDR_INDEX:
+ reg_value = IGA1_HOR_ADDR_FORMULA(device_timing.hor_addr);
+ load_reg_num = iga1_crtc_reg.hor_addr.reg_num;
+ reg = iga1_crtc_reg.hor_addr.reg;
+ break;
+ case H_BLANK_START_INDEX:
+ reg_value = IGA1_HOR_BLANK_START_FORMULA(device_timing.hor_blank_start);
+ load_reg_num = iga1_crtc_reg.hor_blank_start.reg_num;
+ reg = iga1_crtc_reg.hor_blank_start.reg;
+ break;
+ case H_BLANK_END_INDEX:
+ reg_value = IGA1_HOR_BLANK_END_FORMULA(device_timing.hor_blank_start, device_timing.hor_blank_end);
+ load_reg_num = iga1_crtc_reg.hor_blank_end.reg_num;
+ reg = iga1_crtc_reg.hor_blank_end.reg;
+ break;
+ case H_SYNC_START_INDEX:
+ reg_value = IGA1_HOR_SYNC_START_FORMULA(device_timing.hor_sync_start);
+ load_reg_num = iga1_crtc_reg.hor_sync_start.reg_num;
+ reg = iga1_crtc_reg.hor_sync_start.reg;
+ break;
+ case H_SYNC_END_INDEX:
+ reg_value = IGA1_HOR_SYNC_END_FORMULA(device_timing.hor_sync_start, device_timing.hor_sync_end);
+ load_reg_num = iga1_crtc_reg.hor_sync_end.reg_num;
+ reg = iga1_crtc_reg.hor_sync_end.reg;
+ break;
+ case V_TOTAL_INDEX:
+ reg_value = IGA1_VER_TOTAL_FORMULA(device_timing.ver_total);
+ load_reg_num = iga1_crtc_reg.ver_total.reg_num;
+ reg = iga1_crtc_reg.ver_total.reg;
+ break;
+ case V_ADDR_INDEX:
+ reg_value = IGA1_VER_ADDR_FORMULA(device_timing.ver_addr);
+ load_reg_num = iga1_crtc_reg.ver_addr.reg_num;
+ reg = iga1_crtc_reg.ver_addr.reg;
+ break;
+ case V_BLANK_START_INDEX:
+ reg_value = IGA1_VER_BLANK_START_FORMULA(device_timing.ver_blank_start);
+ load_reg_num = iga1_crtc_reg.ver_blank_start.reg_num;
+ reg = iga1_crtc_reg.ver_blank_start.reg;
+ break;
+ case V_BLANK_END_INDEX:
+ reg_value = IGA1_VER_BLANK_END_FORMULA(device_timing.ver_blank_start, device_timing.ver_blank_end);
+ load_reg_num = iga1_crtc_reg.ver_blank_end.reg_num;
+ reg = iga1_crtc_reg.ver_blank_end.reg;
+ break;
+ case V_SYNC_START_INDEX:
+ reg_value = IGA1_VER_SYNC_START_FORMULA(device_timing.ver_sync_start);
+ load_reg_num = iga1_crtc_reg.ver_sync_start.reg_num;
+ reg = iga1_crtc_reg.ver_sync_start.reg;
+ break;
+ case V_SYNC_END_INDEX:
+ reg_value = IGA1_VER_SYNC_END_FORMULA(device_timing.ver_sync_start, device_timing.ver_sync_end);
+ load_reg_num = iga1_crtc_reg.ver_sync_end.reg_num;
+ reg = iga1_crtc_reg.ver_sync_end.reg;
+ break;
+
+ }
+ }
+
+ if (set_iga == IGA2)
+ {
+ switch(i) {
+ case H_TOTAL_INDEX:
+ reg_value = IGA2_HOR_TOTAL_FORMULA(device_timing.hor_total);
+ load_reg_num = iga2_crtc_reg.hor_total.reg_num;
+ reg = iga2_crtc_reg.hor_total.reg;
+ break;
+ case H_ADDR_INDEX:
+ reg_value = IGA2_HOR_ADDR_FORMULA(device_timing.hor_addr);
+ load_reg_num = iga2_crtc_reg.hor_addr.reg_num;
+ reg = iga2_crtc_reg.hor_addr.reg;
+ break;
+ case H_BLANK_START_INDEX:
+ reg_value = IGA2_HOR_BLANK_START_FORMULA(device_timing.hor_blank_start);
+ load_reg_num = iga2_crtc_reg.hor_blank_start.reg_num;
+ reg = iga2_crtc_reg.hor_blank_start.reg;
+ break;
+ case H_BLANK_END_INDEX:
+ reg_value = IGA2_HOR_BLANK_END_FORMULA(device_timing.hor_blank_start, device_timing.hor_blank_end);
+ load_reg_num = iga2_crtc_reg.hor_blank_end.reg_num;
+ reg = iga2_crtc_reg.hor_blank_end.reg;
+ break;
+ case H_SYNC_START_INDEX:
+ reg_value = IGA2_HOR_SYNC_START_FORMULA(device_timing.hor_sync_start);
+ if(UNICHROME_CN900 <= chip_info.gfx_chip_name)
+ {
+ load_reg_num = iga2_crtc_reg.hor_sync_start.reg_num;
+ }
+ else
+ {
+ /* We should not set CR5D[7] for VT3123, VT3204, VT3205 and VT3259,
+ because HW didn't define this bit as Horizontal Retrace Start bit[11]
+ until VT3314 and later chip. */
+ load_reg_num = 3;
+ }
+ reg = iga2_crtc_reg.hor_sync_start.reg;
+ break;
+ case H_SYNC_END_INDEX:
+ reg_value = IGA2_HOR_SYNC_END_FORMULA(device_timing.hor_sync_start, device_timing.hor_sync_end);
+ load_reg_num = iga2_crtc_reg.hor_sync_end.reg_num;
+ reg = iga2_crtc_reg.hor_sync_end.reg;
+ break;
+ case V_TOTAL_INDEX:
+ reg_value = IGA2_VER_TOTAL_FORMULA(device_timing.ver_total);
+ load_reg_num = iga2_crtc_reg.ver_total.reg_num;
+ reg = iga2_crtc_reg.ver_total.reg;
+ break;
+ case V_ADDR_INDEX:
+ reg_value = IGA2_VER_ADDR_FORMULA(device_timing.ver_addr);
+ load_reg_num = iga2_crtc_reg.ver_addr.reg_num;
+ reg = iga2_crtc_reg.ver_addr.reg;
+ break;
+ case V_BLANK_START_INDEX:
+ reg_value = IGA2_VER_BLANK_START_FORMULA(device_timing.ver_blank_start);
+ load_reg_num = iga2_crtc_reg.ver_blank_start.reg_num;
+ reg = iga2_crtc_reg.ver_blank_start.reg;
+ break;
+ case V_BLANK_END_INDEX:
+ reg_value = IGA2_VER_BLANK_END_FORMULA(device_timing.ver_blank_start, device_timing.ver_blank_end);
+ load_reg_num = iga2_crtc_reg.ver_blank_end.reg_num;
+ reg = iga2_crtc_reg.ver_blank_end.reg;
+ break;
+ case V_SYNC_START_INDEX:
+ reg_value = IGA2_VER_SYNC_START_FORMULA(device_timing.ver_sync_start);
+ load_reg_num = iga2_crtc_reg.ver_sync_start.reg_num;
+ reg = iga2_crtc_reg.ver_sync_start.reg;
+ break;
+ case V_SYNC_END_INDEX:
+ reg_value = IGA2_VER_SYNC_END_FORMULA(device_timing.ver_sync_start, device_timing.ver_sync_end);
+ load_reg_num = iga2_crtc_reg.ver_sync_end.reg_num;
+ reg = iga2_crtc_reg.ver_sync_end.reg;
+ break;
+
+ }
+ }
+ load_reg(reg_value, load_reg_num, reg, VIACR);
+ }
+
+ lock_crt();
+}
+
+void set_color_depth(int bpp_byte, int set_iga)
+{
+ if (set_iga == IGA1)
+ {
+ switch(bpp_byte)
+ {
+ case MODE_8BPP:
+ write_reg_mask(SR15, VIASR, 0x22, 0x7E);
+ break;
+ case MODE_16BPP:
+ write_reg_mask(SR15, VIASR, 0xB6, 0xFE);
+ break;
+ case MODE_32BPP:
+ write_reg_mask(SR15, VIASR, 0xAE, 0xFE);
+ break;
+ }
+ }
+ else
+ {
+ switch(bpp_byte)
+ {
+ case MODE_8BPP:
+ write_reg_mask(CR67, VIACR, 0x00, BIT6+BIT7);
+ break;
+ case MODE_16BPP:
+ write_reg_mask(CR67, VIACR, 0x40, BIT6+BIT7);
+ break;
+ case MODE_32BPP:
+ write_reg_mask(CR67, VIACR, 0xC0, BIT6+BIT7);
+ break;
+ }
+ }
+}
+
+void fill_crtc_timing(struct crt_mode_table *crt_table, int mode_index, int bpp_byte, int set_iga)
+{
+ struct VideoModeTable *video_mode;
+ struct display_timing crt_reg;
+ int i;
+ int index=0;
+ int h_addr,v_addr;
+ u32 pll_D_N;
+
+
+ video_mode = &CLE266Modes[SearchModeSetting(mode_index)];
+
+ for(i=0;i<video_mode->mode_array;i++)
+ {
+ index = i;
+
+ if (crt_table[i].refresh_rate == crt_setting_info.refresh_rate)
+ break;
+ }
+
+ crt_reg = crt_table[index].crtc;
+
+ /* Mode 640x480 has border, but LCD/DFP didn't have border. */
+ /* So we would delete border. */
+ if ((LCD_ON | DVI_ON) && (mode_index == VIA_RES_640X480) && (crt_setting_info.refresh_rate == 60))
+ {
+ /* The border is 8 pixels. */
+ crt_reg.hor_blank_start = crt_reg.hor_blank_start - 8;
+
+ /* Blanking time should add left and right borders. */
+ crt_reg.hor_blank_end = crt_reg.hor_blank_end + 16;
+ }
+
+ h_addr = crt_reg.hor_addr;
+ v_addr = crt_reg.ver_addr;
+
+ /* update polarity for CRT timing */
+ if (crt_table[index].h_sync_polarity == NEGATIVE)
+ {
+ if (crt_table[index].v_sync_polarity == NEGATIVE)
+ outb((inb(VIARMisc) & (~(BIT6+BIT7))) | (BIT6+BIT7),VIAWMisc);
+ else
+ outb((inb(VIARMisc) & (~(BIT6+BIT7))) | (BIT6),VIAWMisc);
+ }
+ else
+ {
+ if (crt_table[index].v_sync_polarity == NEGATIVE)
+ outb((inb(VIARMisc) & (~(BIT6+BIT7))) | (BIT7),VIAWMisc);
+ else
+ outb((inb(VIARMisc) & (~(BIT6+BIT7))) ,VIAWMisc);
+ }
+
+ if (set_iga == IGA1)
+ {
+ unlock_crt();
+ write_reg(CR09, VIACR, 0x00); /* initial CR09=0 */
+ write_reg_mask(CR11, VIACR, 0x00, BIT4+BIT5+BIT6);
+ write_reg_mask(CR17, VIACR, 0x00, BIT7);
+ }
+
+ switch(set_iga) {
+ case IGA1:
+ load_crtc_timing(crt_reg, IGA1);
+ break;
+ case IGA2:
+ load_crtc_timing(crt_reg, IGA2);
+ break;
+ }
+
+ load_fix_bit_crtc_reg();
+ lock_crt();
+ write_reg_mask(CR17, VIACR, 0x80, BIT7);
+ load_offset_reg(h_addr, bpp_byte, set_iga);
+ load_fetch_count_reg(h_addr, bpp_byte, set_iga);
+
+ /* load FIFO */
+ if ( (chip_info.gfx_chip_name != UNICHROME_CLE266) && (chip_info.gfx_chip_name != UNICHROME_K400))
+ load_FIFO_reg(set_iga, h_addr, v_addr);
+
+ /* load SR Register About Memory and Color part */
+ set_color_depth(bpp_byte, set_iga);
+
+ pll_D_N = get_clk_value(crt_table[index].clk);
+ DEBUG_MSG( KERN_INFO "PLL=%x", pll_D_N);
+ SetVCLK(pll_D_N, set_iga);
+
+}
+
+struct display_timing get_timing_value(struct crt_mode_table *crt_table, int mode_index)
+{
+ struct VideoModeTable *video_mode;
+ struct display_timing crt_reg;
+ int i;
+ int index=0;
+
+ video_mode = &CLE266Modes[SearchModeSetting(mode_index)];
+
+ for(i=0;i<video_mode->mode_array;i++)
+ {
+ index = i;
+
+ if (crt_table[i].refresh_rate == crt_setting_info.refresh_rate)
+ break;
+ }
+
+ crt_reg = crt_table[index].crtc;
+ return(crt_reg);
+}
+
+void init_chip_info(void)
+{
+ init_gfx_chip_info();
+ init_tv_chip_info();
+ init_tmds_chip_info();
+ init_lvds_chip_info();
+
+ crt_setting_info.iga_path = IGA1;
+ crt_setting_info.refresh_rate = refresh;
+
+
+ /* Set IGA path for each device */
+ set_iga_path();
+ if(tv_level > 2)
+ {
+ tv_level = 0;
+ WARN_MSG(KERN_WARNING "Invalid tv_level value, will use defalt value 0\n");
+ }
+ tv_setting_info.level = tv_level;
+ tv_setting_info.system = tv_system;
+ tv_setting_info.out_signal = tv_out_signal;
+ tv_setting_info.dedotcrawl = tv_dedotcrawl;
+
+
+ lvds_setting_info.display_method=lcd_dsp_method;
+ lvds_setting_info.get_lcd_size_method = GET_LCD_SIZE_BY_USER_SETTING;
+ lvds_setting_info.lcd_mode=lcd_mode;
+ lvds_setting_info2.display_method = lvds_setting_info.display_method; /* default */
+ lvds_setting_info2.lcd_mode = lvds_setting_info.lcd_mode;
+
+ DEBUG_MSG(KERN_INFO "TV= %2d\n", chip_info.tv_chip_info.tv_chip_name);
+ DEBUG_MSG(KERN_INFO "TV_SLAVE_ADDR= %2d\n", chip_info.tv_chip_info.tv_chip_slave_addr);
+}
+
+void update_device_setting(int hres, int vres, int bpp, int vmode_refresh,int flag)
+{
+ if(flag==0)
+ {
+ crt_setting_info.h_active = hres;
+ crt_setting_info.v_active = vres;
+ crt_setting_info.bpp = bpp;
+ crt_setting_info.refresh_rate = vmode_refresh;
+
+ tv_setting_info.h_active = hres;
+ tv_setting_info.v_active = vres;
+ tv_setting_info.bpp = bpp;
+
+ tmds_setting_info.h_active = hres;
+ tmds_setting_info.v_active = vres;
+ tmds_setting_info.bpp = bpp;
+ tmds_setting_info.refresh_rate = vmode_refresh;
+
+ lvds_setting_info.h_active = hres;
+ lvds_setting_info.v_active = vres;
+ lvds_setting_info.bpp = bpp;
+ lvds_setting_info.refresh_rate = vmode_refresh;
+ lvds_setting_info2.h_active = hres;
+ lvds_setting_info2.v_active = vres;
+ lvds_setting_info2.bpp = bpp;
+ lvds_setting_info2.refresh_rate = vmode_refresh;
+ }
+ else
+ {
+ if(tv_setting_info.iga_path == IGA2)
+ {
+ tv_setting_info.h_active = hres;
+ tv_setting_info.v_active = vres;
+ tv_setting_info.bpp = bpp;
+ }
+
+ if(tmds_setting_info.iga_path == IGA2)
+ {
+ tmds_setting_info.h_active = hres;
+ tmds_setting_info.v_active = vres;
+ tmds_setting_info.bpp = bpp;
+ tmds_setting_info.refresh_rate = vmode_refresh;
+ }
+
+ if(lvds_setting_info.iga_path == IGA2)
+ {
+ lvds_setting_info.h_active = hres;
+ lvds_setting_info.v_active = vres;
+ lvds_setting_info.bpp = bpp;
+ lvds_setting_info.refresh_rate = vmode_refresh;
+ }
+ if(IGA2 == lvds_setting_info2.iga_path)
+ {
+ lvds_setting_info2.h_active = hres;
+ lvds_setting_info2.v_active = vres;
+ lvds_setting_info2.bpp = bpp;
+ lvds_setting_info2.refresh_rate = vmode_refresh;
+ }
+ }
+}
+
+void init_gfx_chip_info(void)
+{
+ struct pci_dev *pdev=NULL;
+ u8 tmp;
+
+ /* Indentify GFX Chip Name */
+ pdev = (struct pci_dev *)pci_find_device(PCI_VIA_VENDOR_ID, UNICHROME_CLE266_DID, NULL);
+ if (pdev != NULL)
+ chip_info.gfx_chip_name = UNICHROME_CLE266;
+
+ pdev = (struct pci_dev *)pci_find_device(PCI_VIA_VENDOR_ID, UNICHROME_K400_DID, NULL);
+ if (pdev != NULL)
+ chip_info.gfx_chip_name = UNICHROME_K400;
+
+ pdev = (struct pci_dev *)pci_find_device(PCI_VIA_VENDOR_ID, UNICHROME_K800_DID, NULL);
+ if (pdev != NULL)
+ chip_info.gfx_chip_name = UNICHROME_K800;
+
+ pdev = (struct pci_dev *)pci_find_device(PCI_VIA_VENDOR_ID, UNICHROME_P880_DID, NULL);
+ if (pdev != NULL)
+ chip_info.gfx_chip_name = UNICHROME_P880;
+
+ pdev = (struct pci_dev *)pci_find_device(PCI_VIA_VENDOR_ID, UNICHROME_CN900_DID, NULL);
+ if (pdev != NULL)
+ chip_info.gfx_chip_name = UNICHROME_CN900;
+
+ /* Add for VT3324. */
+ pdev = (struct pci_dev *)pci_find_device(PCI_VIA_VENDOR_ID, UNICHROME_CX700_DID, NULL);
+ if (pdev != NULL)
+ {
+ chip_info.gfx_chip_name = UNICHROME_CX700;
+ }
+
+ /* Add for VT3327 VT3336 VT3364 */
+ pdev = (struct pci_dev *)pci_find_device(PCI_VIA_VENDOR_ID, UNICHROME_K8M890_DID, NULL);
+ if (pdev != NULL)
+ {
+ chip_info.gfx_chip_name = UNICHROME_K8M890;
+ }
+
+ pdev = (struct pci_dev *)pci_find_device(PCI_VIA_VENDOR_ID, UNICHROME_P4M890_DID, NULL);
+ if (pdev != NULL)
+ {
+ chip_info.gfx_chip_name = UNICHROME_P4M890;
+ }
+
+ pdev = (struct pci_dev *)pci_find_device(PCI_VIA_VENDOR_ID, UNICHROME_P4M900_DID, NULL);
+ if (pdev != NULL)
+ {
+ chip_info.gfx_chip_name = UNICHROME_P4M900;
+ }
+
+ /* Check revision of CLE266 Chip */
+ if (chip_info.gfx_chip_name == UNICHROME_CLE266)
+ {
+ /* CR4F only define in CLE266.CX chip */
+ tmp = read_reg(VIACR, CR4F);
+ write_reg(CR4F, VIACR, 0x55);
+ if (read_reg(VIACR,CR4F)!=0x55)
+ chip_info.gfx_chip_revision = CLE266_REVISION_AX;
+ else
+ chip_info.gfx_chip_revision = CLE266_REVISION_CX;
+
+ write_reg(CR4F, VIACR, tmp); /* restore orignal CR4F value */
+ }
+
+ /* Check revision of CX700 Chip */
+ if (UNICHROME_CX700 == chip_info.gfx_chip_name)
+ {
+ tmp = read_reg(VIASR, SR43);
+ DEBUG_MSG(KERN_INFO "SR43:%X\n", tmp);
+ if(tmp & 0x02)
+ {
+ chip_info.gfx_chip_revision = CX700_REVISION_700M2;
+ }
+ else if(tmp & 0x40)
+ {
+ chip_info.gfx_chip_revision = CX700_REVISION_700M;
+ }
+ else
+ {
+ chip_info.gfx_chip_revision = CX700_REVISION_700;
+ }
+ }
+}
+
+
+
+void init_tv_chip_info(void)
+{
+ u8 data;
+ bool IsMobile = FALSE;
+
+ data = read_reg(VIASR, SR12) & BIT5; /* HW strapping: 0: TV on AMR 1: TV on AGP */
+
+ if (chip_info.tv_chip_info.output_interface == INTERFACE_NONE)
+ {
+ /* To know if current chip are mobile. */
+ lcd_get_mobile_state(&IsMobile);
+
+ /* External TV on VT3324 uses AMR slot. */
+ if ((chip_info.gfx_chip_name == UNICHROME_CLE266) ||
+ (chip_info.gfx_chip_name == UNICHROME_CX700) ||
+ (data == 0x20))
+ {
+ chip_info.tv_chip_info.tv_chip_on_slot = TV_ON_AMR;
+ switch(chip_info.gfx_chip_name)
+ {
+ case UNICHROME_CX700:
+ chip_info.tv_chip_info.output_interface = INTERFACE_DVP1;
+ break;
+ default:
+ chip_info.tv_chip_info.output_interface = INTERFACE_DVP0;
+ break;
+ }
+ }
+ else if(chip_info.gfx_chip_name == UNICHROME_CX700)
+ {
+ chip_info.tv_chip_info.output_interface = INTERFACE_NONE;
+ }
+ else
+ {
+ chip_info.tv_chip_info.tv_chip_on_slot = TV_ON_AGP;
+
+ if (IsMobile)
+ chip_info.tv_chip_info.output_interface = INTERFACE_DVP1;
+ else
+ chip_info.tv_chip_info.output_interface = INTERFACE_DFP_HIGH;
+ }
+ }
+ else
+ {
+ if ((chip_info.gfx_chip_name == UNICHROME_CLE266) ||
+ (chip_info.gfx_chip_name == UNICHROME_CX700) ||
+ (data == 0x20))
+ {
+ chip_info.tv_chip_info.tv_chip_on_slot = TV_ON_AMR;
+ }
+ else
+ {
+ chip_info.tv_chip_info.tv_chip_on_slot = TV_ON_AGP;
+ }
+ }
+
+ tv_encoder_identify();
+ DEBUG_MSG(KERN_INFO "init_tv_chip_info, chip_name:%d,out_interface:%d\n", chip_info.tv_chip_info.tv_chip_name, chip_info.tv_chip_info.output_interface);
+}
+
+void init_tmds_chip_info(void)
+{
+ if(INTERFACE_NONE == chip_info.tmds_chip_info.output_interface)
+ {
+ switch(chip_info.gfx_chip_name)
+ {
+ /* Add for VT3324 integrated TMDS. */
+ case UNICHROME_CX700:
+ /* Not always support intergrated TMDS now,
+ we should check support by hardware layout. */
+ if ((display_hardware_layout == HW_LAYOUT_DVI_ONLY) ||
+ (display_hardware_layout == HW_LAYOUT_LCD_DVI))
+ {
+ chip_info.tmds_chip_info.output_interface = INTERFACE_TMDS;
+ }
+ else
+ {
+ chip_info.tmds_chip_info.output_interface = INTERFACE_NONE;
+ }
+ break;
+ /* Add for support VT3327 VT3336 VT3364 */
+ case UNICHROME_K8M890:
+ case UNICHROME_P4M900:
+ case UNICHROME_P4M890:
+ /* TMDS on PCIE, we set DFPLOW as default. */
+ chip_info.tmds_chip_info.output_interface = INTERFACE_DFP_LOW;
+ break;
+ default:
+ chip_info.tmds_chip_info.output_interface = INTERFACE_DVP1;
+ }
+ }
+ tmds_trasmitter_identify();
+ DEBUG_MSG(KERN_INFO "TMDS Chip = %d\n", chip_info.tmds_chip_info.tmds_chip_name);
+ init_dvi_size();
+}
+
+void init_lvds_chip_info(void)
+{
+ if(lcd_panel_id > LCD_PANEL_ID_MAXIMUM)
+ lvds_setting_info.get_lcd_size_method = GET_LCD_SIZE_BY_VGA_BIOS;
+ else
+ lvds_setting_info.get_lcd_size_method = GET_LCD_SIZE_BY_USER_SETTING;
+
+ lvds_trasmitter_identify();
+ init_lcd_size();
+ init_lvds_output_interface(&chip_info.lvds_chip_info, &lvds_setting_info);
+ if(chip_info.lvds_chip_info2.lvds_chip_name)
+ {
+ init_lvds_output_interface(&chip_info.lvds_chip_info2, &lvds_setting_info2);
+ }
+ /* If CX700,two singel LCD, we need to reassign LCD interface to different LVDS port */
+ if((UNICHROME_CX700 == chip_info.gfx_chip_name) && (HW_LAYOUT_LCD1_LCD2 == display_hardware_layout))
+ {
+ if((INTEGRATED_LVDS == chip_info.lvds_chip_info.lvds_chip_name) && (INTEGRATED_LVDS == chip_info.lvds_chip_info2.lvds_chip_name))
+ {
+ chip_info.lvds_chip_info.output_interface = INTERFACE_LVDS0;
+ chip_info.lvds_chip_info2.output_interface = INTERFACE_LVDS1;
+ }
+ }
+
+ DEBUG_MSG(KERN_INFO "LVDS Chip = %d\n", chip_info.lvds_chip_info.lvds_chip_name);
+ DEBUG_MSG(KERN_INFO "LVDS1 output_interface = %d\n", chip_info.lvds_chip_info.output_interface);
+ DEBUG_MSG(KERN_INFO "LVDS2 output_interface = %d\n", chip_info.lvds_chip_info2.output_interface);
+}
+
+void init_dac(int set_iga)
+{
+ int i;
+ u8 tmp;
+
+ if (set_iga == IGA1)
+ {
+ write_reg_mask(SR1A, VIASR, 0x00, BIT0); /* access Primary Display's LUT */
+ write_reg_mask(SR1B, VIASR, 0x00, BIT7+BIT6); /* turn off LCK */
+ for(i=0; i<256; i++)
+ {
+ write_dac_reg(i, palLUT_table[i].red, palLUT_table[i].green, palLUT_table[i].blue);
+ }
+
+ write_reg_mask(SR1B, VIASR, 0xC0, BIT7+BIT6); /* turn on LCK */
+ }
+ else
+ {
+ tmp=read_reg(VIACR, CR6A);
+ write_reg_mask(CR6A, VIACR, 0x40, BIT6);
+ write_reg_mask(SR1A, VIASR, 0x01, BIT0); /* access Secondary Display's LUT */
+ for(i=0; i<256; i++)
+ {
+ write_dac_reg(i, palLUT_table[i].red, palLUT_table[i].green, palLUT_table[i].blue);
+ }
+ write_reg_mask(SR1A, VIASR, 0x00, BIT0); /* set IGA1 DAC for default */
+ write_reg(CR6A, VIACR, tmp);
+ }
+}
+
+
+void device_screen_off(void)
+{
+ write_reg_mask(SR01, VIASR, 0x20, BIT5); /* turn off CRT screen (IGA1) */
+}
+
+void device_screen_on(void)
+{
+ write_reg_mask(SR01, VIASR, 0x00, BIT5); /* turn on CRT screen (IGA1) */
+}
+
+void set_display_channel(void)
+{
+ /* If LCD2_ON, on cx700, internal lvds's information is keeped on lvds_setting_info2 */
+ if(LCD2_ON && lvds_setting_info2.LCDDualEdge)
+ {
+ /* For dual channel LCD: */
+ /* Set to Dual LVDS channel. */
+ write_reg_mask(CRD2, VIACR, 0x20, BIT4+BIT5);
+ }
+ else if (LCD_ON && DVI_ON)
+ {
+ /* For LCD+DFP: */
+ /* Set to LVDS1 + TMDS channel. */
+ write_reg_mask(CRD2, VIACR, 0x10, BIT4+BIT5);
+ }
+ else if (DVI_ON)
+ {
+ /* Set to single TMDS channel. */
+ write_reg_mask(CRD2, VIACR, 0x30, BIT4+BIT5);
+ }
+ else if (LCD_ON)
+ {
+ if (lvds_setting_info.LCDDualEdge)
+ {
+ /* For dual channel LCD: */
+ /* Set to Dual LVDS channel. */
+ write_reg_mask(CRD2, VIACR, 0x20, BIT4+BIT5);
+ }
+ else
+ {
+ /* Set to LVDS0 + LVDS1 channel. */
+ write_reg_mask(CRD2, VIACR, 0x00, BIT4+BIT5);
+ }
+ }
+}
+
+#define NUM_TOTAL_CLE266_ModeXregs ARRAY_SIZE(CLE266_ModeXregs)
+
+int setmode(int vmode_index,int hor_res,int ver_res,int video_bpp,
+ int vmode_index1,int hor_res1,int ver_res1,int video_bpp1)
+{
+ int i,j;
+ int port;
+ u8 value,index,mask;
+ struct VideoModeTable *vmode_tbl;
+ struct crt_mode_table *crt_timing;
+ struct VideoModeTable *vmode_tbl1=NULL;
+ struct crt_mode_table *crt_timing1=NULL;
+
+ DEBUG_MSG(KERN_INFO "Set Mode!!\n");
+ DEBUG_MSG(KERN_INFO "vmode_index=%d hor_res=%d ver_res=%d video_bpp=%d\n", vmode_index, hor_res, ver_res, video_bpp);
+
+ device_screen_off();
+ vmode_tbl = &CLE266Modes[SearchModeSetting(vmode_index)];
+ crt_timing = vmode_tbl->crtc;
+
+ if(SAMM_ON==1)
+ {
+ vmode_tbl1 = &CLE266Modes[SearchModeSetting(vmode_index1)];
+ crt_timing1 = vmode_tbl1->crtc;
+ }
+
+ inb(VIAStatus);
+ outb(0x00,VIAAR);
+
+ /* Write Common Setting for Video Mode */
+ switch(chip_info.gfx_chip_name)
+ {
+ case UNICHROME_CLE266:
+ write_regx(CLE266_ModeXregs, NUM_TOTAL_CLE266_ModeXregs);
+ break;
+
+ case UNICHROME_K400:
+ write_regx(KM400_ModeXregs, NUM_TOTAL_KM400_ModeXregs);
+ break;
+
+ case UNICHROME_K800:
+ case UNICHROME_P880:
+ write_regx(CN400_ModeXregs, NUM_TOTAL_CN400_ModeXregs);
+ break;
+
+ case UNICHROME_CN900:
+ case UNICHROME_K8M890:/* Add for VT3336*/
+ case UNICHROME_P4M890:/* Add for VT3327*/
+ case UNICHROME_P4M900:/* Add for VT3364*/
+ write_regx(CN900_ModeXregs, NUM_TOTAL_CN900_ModeXregs);
+ break;
+
+ /* Add for VT3324 */
+ case UNICHROME_CX700:
+ write_regx(CX700_ModeXregs, NUM_TOTAL_CX700_ModeXregs);
+ break;
+ }
+
+ device_off();
+
+ /* Fill VPIT Parameters */
+ /* Write Misc Register */
+ outb(VPIT.Misc, VIAWMisc);
+
+ /* Write Sequencer */
+ for ( i=1; i<=StdSR ; i++ )
+ {
+ outb(i, VIASR);
+ outb(VPIT.SR[i-1], VIASR+1);
+ }
+
+ set_start_addr();
+ set_iga_path();
+
+ /* Write CRTC */
+ fill_crtc_timing(crt_timing, vmode_index, video_bpp/8, IGA1);
+
+ /* Write Graphic Controller */
+ for ( i=0; i<StdGR ; i++ )
+ {
+ outb(i, VIAGR);
+ outb(VPIT.GR[i], VIAGR+1);
+ }
+
+ /* Write Attribute Controller */
+ for ( i=0; i<StdAR ; i++ )
+ {
+ inb(VIAStatus);
+ outb(i, VIAAR);
+ outb(VPIT.AR[i], VIAAR);
+ }
+
+ inb(VIAStatus);
+ outb(0x20,VIAAR);
+
+ /* Update Patch Register */
+
+ if ((chip_info.gfx_chip_name == UNICHROME_CLE266) || (chip_info.gfx_chip_name == UNICHROME_K400))
+ {
+ for( i=0; i< NUM_TOTAL_PATCH_MODE; i++ )
+ {
+ if (res_patch_table[i].mode_index==vmode_index)
+ {
+ for(j=0; j<res_patch_table[i].table_length; j++)
+ {
+ index = res_patch_table[i].io_reg_table[j].index;
+ port = res_patch_table[i].io_reg_table[j].port;
+ value = res_patch_table[i].io_reg_table[j].value;
+ mask = res_patch_table[i].io_reg_table[j].mask ;
+ write_reg_mask(index, port, value, mask);
+ }
+ }
+ }
+ }
+
+ if(SAMM_ON == 1)
+ {
+ if ((chip_info.gfx_chip_name == UNICHROME_CLE266) || (chip_info.gfx_chip_name == UNICHROME_K400))
+ {
+ for( i=0; i< NUM_TOTAL_PATCH_MODE; i++ )
+ {
+ if (res_patch_table[i].mode_index==vmode_index1)
+ {
+ for(j=0; j<res_patch_table[i].table_length; j++)
+ {
+ index = res_patch_table[i].io_reg_table[j].index;
+ port = res_patch_table[i].io_reg_table[j].port;
+ value = res_patch_table[i].io_reg_table[j].value;
+ mask = res_patch_table[i].io_reg_table[j].mask ;
+ write_reg_mask(index, port, value, mask);
+ }
+ }
+ }
+ }
+ }
+
+ /* Update Refresh Rate Setting */
+
+ /* Clear On Screen */
+
+ /* CRT set mode */
+ if (CRT_ON)
+ {
+ if (SAMM_ON && (crt_setting_info.iga_path == IGA2))
+ {
+ fill_crtc_timing(crt_timing1, vmode_index1, video_bpp1/8, crt_setting_info.iga_path);
+ }
+ else
+ {
+ fill_crtc_timing(crt_timing, vmode_index, video_bpp/8, crt_setting_info.iga_path);
+ }
+
+ set_crt_output_path(crt_setting_info.iga_path);
+
+ /* Patch if set_hres is not 8 alignment (1366) to setmode to 8 alignment (1368),
+ there is several pixels (2 pixels) on right side of screen. */
+ if (hor_res%8)
+ {
+ unlock_crt();
+ write_reg(CR02, VIACR, read_reg(VIACR, CR02)-1);
+ lock_crt();
+ }
+ }
+
+ if (TV_ON)
+ {
+ if(SAMM_ON && (tv_setting_info.iga_path == IGA2))
+ {
+ tv_set_mode(vmode_index1);
+ }
+ else
+ {
+ tv_set_mode(vmode_index);
+ }
+ }
+
+ if (DVI_ON)
+ {
+ if(SAMM_ON && (tmds_setting_info.iga_path == IGA2))
+ {
+ dvi_set_mode(crt_timing1, vmode_index1, video_bpp1, tmds_setting_info.iga_path);
+ }
+ else
+ {
+ dvi_set_mode(crt_timing, vmode_index, video_bpp, tmds_setting_info.iga_path);
+ }
+ }
+
+ if (LCD_ON)
+ {
+ if(SAMM_ON && (lvds_setting_info.iga_path == IGA2))
+ {
+ lvds_setting_info.bpp = video_bpp1;
+ lcd_set_mode(crt_timing1, &lvds_setting_info, &chip_info.lvds_chip_info);
+ }
+ else
+ {
+ /* IGA1 doesn't have LCD scaling, so set it as centering. */
+ if (lvds_setting_info.iga_path == IGA1)
+ {
+ lvds_setting_info.display_method = LCD_CENTERING;
+ }
+ lvds_setting_info.bpp = video_bpp;
+ lcd_set_mode(crt_timing, &lvds_setting_info, &chip_info.lvds_chip_info);
+ }
+ }
+ if(LCD2_ON)
+ {
+ if(SAMM_ON && (lvds_setting_info2.iga_path == IGA2))
+ {
+ lvds_setting_info2.bpp = video_bpp1;
+ lcd_set_mode(crt_timing1, &lvds_setting_info2, &chip_info.lvds_chip_info2);
+ }
+ else
+ {
+ /* IGA1 doesn't have LCD scaling, so set it as centering. */
+ if (lvds_setting_info2.iga_path == IGA1)
+ {
+ lvds_setting_info2.display_method = LCD_CENTERING;
+ }
+ lvds_setting_info2.bpp = video_bpp;
+ lcd_set_mode(crt_timing, &lvds_setting_info2, &chip_info.lvds_chip_info2);
+ }
+ }
+
+ /* Add for VT3324 */
+ if ((chip_info.gfx_chip_name == UNICHROME_CX700) && (LCD_ON || DVI_ON))
+ {
+ set_display_channel();
+ }
+
+ /* If set mode normally, save resolution information for hot-plug using. */
+ if(!HotPlug)
+ {
+ HotPlug_Xres = hor_res;
+ HotPlug_Yres = ver_res;
+ HotPlug_bpp = video_bpp;
+ HotPlug_refresh = refresh;
+
+ if(DVI_ON)
+ {
+ DeviceStatus = DVI_Device;
+ }
+ else if(TV_ON)
+ {
+ DeviceStatus = TV_Device;
+ }
+ else
+ {
+ DeviceStatus = CRT_Device;
+ }
+ }
+
+ device_on();
+
+ if(SAMM_ON == 1)
+ {
+ write_reg_mask(CR6A, VIACR, 0xC0, BIT6+BIT7);
+ }
+
+ device_screen_on();
+
+ return 1;
+}
+
+int get_pixclock(int hres, int vres, int vmode_refresh)
+{
+ int i;
+
+ for(i=0; i<NUM_TOTAL_RES_MAP_REFRESH; i++)
+ {
+ if((hres==res_map_refresh_tbl[i].hres) && (vres==res_map_refresh_tbl[i].vres) && (vmode_refresh == res_map_refresh_tbl[i].vmode_refresh))
+ return(res_map_refresh_tbl[i].pixclock);
+ }
+ return(RES_640X480_60HZ_PIXCLOCK);
+
+}
+
+int get_refresh(int hres, int vres, int pixclock)
+{
+ int i;
+ for(i=0; i<NUM_TOTAL_RES_MAP_REFRESH; i++)
+ {
+ if((hres==res_map_refresh_tbl[i].hres) && (vres==res_map_refresh_tbl[i].vres) && (pixclock == res_map_refresh_tbl[i].pixclock))
+ return(res_map_refresh_tbl[i].vmode_refresh);
+ }
+ return(60);
+}
+
+void device_off(void)
+{
+ crt_disable();
+ tv_disable();
+ dvi_disable();
+ lcd_disable();
+}
+
+void device_on(void)
+{
+ if (CRT_ON==1){
+ crt_enable();
+ }
+ if (TV_ON==1){
+ tv_enable();
+ }
+ if (DVI_ON==1){
+ dvi_enable();
+ }
+ if (LCD_ON==1){
+ lcd_enable();
+ }
+}
+
+void crt_disable(void)
+{
+ write_reg_mask(CR36, VIACR, BIT5+BIT4, BIT5+BIT4);
+}
+
+void crt_enable(void)
+{
+ write_reg_mask(CR36, VIACR, 0x0, BIT5+BIT4);
+}
+
+void get_mmio_info(unsigned long *mmio_base, unsigned long *mmio_len)
+{
+ struct pci_dev *pdev = NULL;
+
+ switch(chip_info.gfx_chip_name)
+ {
+ case UNICHROME_CLE266:
+ pdev = (struct pci_dev *)pci_find_device(PCI_VIA_VENDOR_ID, UNICHROME_CLE266_DID, NULL);
+ break;
+
+ case UNICHROME_K400:
+ pdev = (struct pci_dev *)pci_find_device(PCI_VIA_VENDOR_ID, UNICHROME_K400_DID, NULL);
+ break;
+
+ case UNICHROME_K800:
+ pdev = (struct pci_dev *)pci_find_device(PCI_VIA_VENDOR_ID, UNICHROME_K800_DID, NULL);
+ break;
+
+ case UNICHROME_P880:
+ pdev = (struct pci_dev *)pci_find_device(PCI_VIA_VENDOR_ID, UNICHROME_P880_DID, NULL);
+ break;
+
+ case UNICHROME_CN900:
+ pdev = (struct pci_dev *)pci_find_device(PCI_VIA_VENDOR_ID, UNICHROME_CN900_DID, NULL);
+ break;
+
+ case UNICHROME_CX700: /* Add for VT3324. */
+ pdev = (struct pci_dev *)pci_find_device(PCI_VIA_VENDOR_ID, UNICHROME_CX700_DID, NULL);
+ break;
+
+ /* Add for VT3327 VT3336 VT3364 */
+ case UNICHROME_K8M890:
+ pdev = (struct pci_dev *)pci_find_device(PCI_VIA_VENDOR_ID, UNICHROME_K8M890_DID, NULL);
+ break;
+
+ case UNICHROME_P4M890:
+ pdev = (struct pci_dev *)pci_find_device(PCI_VIA_VENDOR_ID, UNICHROME_P4M890_DID, NULL);
+ break;
+
+ case UNICHROME_P4M900:
+ pdev = (struct pci_dev *)pci_find_device(PCI_VIA_VENDOR_ID, UNICHROME_P4M900_DID, NULL);
+ break;
+ }
+
+ if(pdev != NULL)
+ {
+ *mmio_base = pci_resource_start(pdev, 1);
+ *mmio_len = pci_resource_len(pdev, 1);
+ }
+ else
+ {
+ *mmio_base = 0;
+ *mmio_len = 0;
+ }
+
+}
+
+void enable_second_display_channel(void)
+{
+ /* It's better to use the following sequence to enable second display channel. */
+ write_reg_mask(CR6A, VIACR, 0x00, BIT6);
+ write_reg_mask(CR6A, VIACR, BIT7, BIT7);
+ write_reg_mask(CR6A, VIACR, BIT6, BIT6);
+}
+
+void disable_second_display_channel(void)
+{
+ /* It's better to use the following sequence to disable second display channel. */
+ write_reg_mask(CR6A, VIACR, 0x00, BIT6);
+ write_reg_mask(CR6A, VIACR, 0x00, BIT7);
+ write_reg_mask(CR6A, VIACR, BIT6, BIT6);
+}
+
+void plus_vck_to_iga1_timing(unsigned long h_total)
+{
+ /* Clear first. */
+ write_reg_mask (CR47, VIACR, 0x00, BIT7+BIT6+BIT3);
+
+ switch (h_total % 8)
+ {
+ case 2:
+ {
+ write_reg_mask (CR47, VIACR, BIT7, BIT7);
+ break;
+ }
+
+ case 4:
+ {
+ write_reg_mask (CR47, VIACR, BIT6, BIT6);
+ break;
+ }
+
+ case 6:
+ {
+ write_reg_mask (CR47, VIACR, BIT3, BIT3);
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+ }
+}
+
+/* Add for get FB info from PCI system */
+void get_fb_info(unsigned int *fb_base, unsigned int *fb_len)
+{
+struct pci_dev *pdev = NULL;
+
+ switch(chip_info.gfx_chip_name)
+ {
+ case UNICHROME_CLE266:
+ pdev = (struct pci_dev *)pci_find_device(PCI_VIA_VENDOR_ID, UNICHROME_CLE266_DID, NULL);
+ break;
+
+ case UNICHROME_K400:
+ pdev = (struct pci_dev *)pci_find_device(PCI_VIA_VENDOR_ID, UNICHROME_K400_DID, NULL);
+ break;
+
+ case UNICHROME_K800:
+ pdev = (struct pci_dev *)pci_find_device(PCI_VIA_VENDOR_ID, UNICHROME_K800_DID, NULL);
+ break;
+
+ case UNICHROME_P880:
+ pdev = (struct pci_dev *)pci_find_device(PCI_VIA_VENDOR_ID, UNICHROME_P880_DID, NULL);
+ break;
+
+ case UNICHROME_CN900:
+ pdev = (struct pci_dev *)pci_find_device(PCI_VIA_VENDOR_ID, UNICHROME_CN900_DID, NULL);
+ break;
+
+ case UNICHROME_CX700:
+ pdev = (struct pci_dev *)pci_find_device(PCI_VIA_VENDOR_ID, UNICHROME_CX700_DID, NULL);
+ break;
+
+ case UNICHROME_K8M890:
+ pdev = (struct pci_dev *)pci_find_device(PCI_VIA_VENDOR_ID, UNICHROME_K8M890_DID, NULL);
+ break;
+
+ case UNICHROME_P4M890:
+ pdev = (struct pci_dev *)pci_find_device(PCI_VIA_VENDOR_ID, UNICHROME_P4M890_DID, NULL);
+ break;
+
+ case UNICHROME_P4M900:
+ pdev = (struct pci_dev *)pci_find_device(PCI_VIA_VENDOR_ID, UNICHROME_P4M900_DID, NULL);
+ break;
+ }
+
+ if(pdev != NULL)
+ {
+ *fb_base =(unsigned int) pci_resource_start(pdev, 0);
+ *fb_len =get_fb_size_from_pci();
+ DEBUG_MSG(KERN_INFO "Get FB info from PCI system!\n");
+ DEBUG_MSG(KERN_INFO "fb_base = %08x\n", *fb_base);
+ DEBUG_MSG(KERN_INFO "fb_len = %08x\n", *fb_len);
+ }
+ else
+ {
+ *fb_base = read_reg(VIASR, SR30) << 24;
+ *fb_len = get_memsize();
+ DEBUG_MSG(KERN_INFO "Get FB info from SR30!\n");
+ DEBUG_MSG(KERN_INFO "fb_base = %08x\n", *fb_base);
+ DEBUG_MSG(KERN_INFO "fb_len = %08x\n", *fb_len);
+ }
+}
+
+/* Port from X code to get FB size from PCI system */
+int get_fb_size_from_pci()
+{
+ unsigned long configid,deviceid,FBSize = 0;
+ int VideoMemSize;
+ int DeviceFound = FALSE;
+
+ for ( configid = 0x80000000; configid < 0x80010800; configid += 0x100 )
+ {
+ outl(configid, (unsigned long)0xCF8);
+ deviceid = (inl((unsigned long)0xCFC)>>16) & 0xffff;
+
+ /* Add KM800 case */
+ switch (deviceid)
+ {
+ case CLE266:
+ case KM400:
+ outl(configid+0xE0, (unsigned long)0xCF8);
+ FBSize = inl((unsigned long)0xCFC);
+ DeviceFound = TRUE; /* Found device id */
+ break;
+
+ case CN400_FUNCTION3:
+ case CN900_FUNCTION3:
+ case CX700_FUNCTION3:
+ case KM800_FUNCTION3:
+ case KM890_FUNCTION3:
+ case P4M890_FUNCTION3:
+ case P4M900_FUNCTION3:
+ /* (Need to Fix)
+ The value of CN750_FUNCTION3 is duplicate with CN900_FUNCTION3 in VT3293_A0.
+ This value maybe change in the next version. */
+ /*case CN750_FUNCTION3:*/
+ outl(configid+0xA0, (unsigned long)0xCF8);
+ FBSize = inl((unsigned long)0xCFC);
+ DeviceFound = TRUE; /* Found device id */
+ break;
+
+ /* Can't set default, otherwise FBSize will be modified incorrectly */
+ default:
+ break;
+ }
+
+ if (DeviceFound)
+ {
+ break; /* Found device id, so exit for loop */
+ }
+ }
+
+ DEBUG_MSG(KERN_INFO "Device ID = %x\n", deviceid);
+
+ FBSize = FBSize & 0x00007000;
+ DEBUG_MSG(KERN_INFO "FB Size = %x\n", FBSize);
+
+ if (chip_info.gfx_chip_name < UNICHROME_CX700)
+ {
+ switch(FBSize)
+ {
+ case 0x00004000:
+ VideoMemSize = (16 << 20); /*16M*/
+ break;
+
+ case 0x00005000:
+ VideoMemSize = (32 << 20); /*32M*/
+ break;
+
+ case 0x00006000:
+ VideoMemSize = (64 << 20); /*64M*/
+ break;
+
+ default:
+ VideoMemSize = (32 << 20); /*32M*/
+ break;
+ }
+ }
+ else
+ {
+ switch(FBSize)
+ {
+ case 0x00001000:
+ VideoMemSize = (8 << 20); /*8M*/
+ break;
+
+ case 0x00002000:
+ VideoMemSize = (16 << 20); /*16M*/
+ break;
+
+ case 0x00003000:
+ VideoMemSize = (32 << 20); /*32M*/
+ break;
+
+ case 0x00004000:
+ VideoMemSize = (64 << 20); /*64M*/
+ break;
+
+ case 0x00005000:
+ VideoMemSize = (128 << 20); /*128M*/
+ break;
+
+ case 0x00006000:
+ VideoMemSize = (256 << 20); /*256M*/
+ break;
+
+ default:
+ VideoMemSize = (32 << 20); /*32M*/
+ break;
+ }
+ }
+
+ return VideoMemSize;
+}
+
+void set_dpa_gfx(int output_interface, GFXDPASETTINGPTR p_gfx_dpa_setting)
+{
+ switch (output_interface)
+ {
+ case INTERFACE_DVP0:
+ {
+ /* DVP0 Clock Polarity and Adjust: */
+ write_reg_mask(CR96, VIACR, p_gfx_dpa_setting->DVP0, 0x0F);
+
+ /* DVP0 Clock and Data Pads Driving: */
+ write_reg_mask(SR1E, VIASR, p_gfx_dpa_setting->DVP0ClockDri_S, BIT2);
+ write_reg_mask(SR2A, VIASR, p_gfx_dpa_setting->DVP0ClockDri_S1, BIT4);
+ write_reg_mask(SR1B, VIASR, p_gfx_dpa_setting->DVP0DataDri_S, BIT1);
+ write_reg_mask(SR2A, VIASR, p_gfx_dpa_setting->DVP0DataDri_S1, BIT5);
+ break;
+ }
+
+ case INTERFACE_DVP1:
+ {
+ /* DVP1 Clock Polarity and Adjust: */
+ write_reg_mask(CR9B, VIACR, p_gfx_dpa_setting->DVP1, 0x0F);
+
+ /* DVP1 Clock and Data Pads Driving: */
+ write_reg_mask(SR65, VIASR, p_gfx_dpa_setting->DVP1Driving, 0x0F);
+ break;
+ }
+
+ case INTERFACE_DFP_HIGH:
+ {
+ write_reg_mask(CR97, VIACR, p_gfx_dpa_setting->DFPHigh, 0x0F);
+ break;
+ }
+
+ case INTERFACE_DFP_LOW:
+ {
+ write_reg_mask(CR99, VIACR, p_gfx_dpa_setting->DFPLow, 0x0F);
+ break;
+ }
+
+ case INTERFACE_DFP:
+ {
+ write_reg_mask(CR97, VIACR, p_gfx_dpa_setting->DFPHigh, 0x0F);
+ write_reg_mask(CR99, VIACR, p_gfx_dpa_setting->DFPLow, 0x0F);
+ break;
+ }
+ }
+}
+
+void memory_pitch_patch(struct fb_info *info)
+{
+ if(info->var.xres != info->var.xres_virtual)
+ {
+ if(SAMM_ON)
+ {
+ load_offset_reg(info->var.xres_virtual, info->var.bits_per_pixel>>3, IGA1);
+ load_offset_reg(second_virtual_xres, bpp1>>3, IGA2);
+ }else
+ {
+ load_offset_reg(info->var.xres_virtual, info->var.bits_per_pixel>>3, IGA1);
+ load_offset_reg(info->var.xres_virtual, info->var.bits_per_pixel>>3, IGA2);
+ }
+ }
+
+}
+
+/* According var's xres, yres fill var's other timing information */
+/* Fix me: TV use separate timing table, this function can't cover TV case */
+void fill_var_timing_info(struct fb_var_screeninfo* var, int refresh, int mode_index)
+{
+ struct VideoModeTable *vmode_tbl = NULL;
+ struct crt_mode_table *crt_timing = NULL;
+ struct display_timing crt_reg;
+ int i = 0, index = 0;
+ vmode_tbl = &CLE266Modes[SearchModeSetting(mode_index)];
+ crt_timing = vmode_tbl->crtc;
+ for(i=0;i<vmode_tbl->mode_array;i++)
+ {
+ index = i;
+
+ if (crt_timing[i].refresh_rate == refresh)
+ break;
+ }
+ crt_reg = crt_timing[index].crtc;
+ var->left_margin = crt_reg.hor_total - (crt_reg.hor_sync_start + crt_reg.hor_sync_end);
+ var->right_margin = crt_reg.hor_sync_start - crt_reg.hor_addr;
+ var->hsync_len = crt_reg.hor_sync_end;
+ var->upper_margin = crt_reg.ver_total - (crt_reg.ver_sync_start + crt_reg.ver_sync_end);
+ var->lower_margin = crt_reg.ver_sync_start - crt_reg.ver_addr;
+ var->vsync_len = crt_reg.ver_sync_end;
+ var->pixclock = get_pixclock(var->xres, var->yres, refresh);
+}
+
-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2007-04-30 8:36 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-04-30 8:36 [PATCH 2/12] viafb: Framebuffer driver for VIA UniChrome/Chrome9 HC (fwd) Geert Uytterhoeven
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox