Merge branch 'viafb-next' of git://github.com/schandinat/linux-2.6
[pandora-kernel.git] / drivers / video / via / dvi.c
index 39b040b..84e21b3 100644 (file)
 static void tmds_register_write(int index, u8 data);
 static int tmds_register_read(int index);
 static int tmds_register_read_bytes(int index, u8 *buff, int buff_len);
-static void dvi_get_panel_size_from_DDCv1(struct tmds_chip_information
-       *tmds_chip, struct tmds_setting_information *tmds_setting);
-static void dvi_get_panel_size_from_DDCv2(struct tmds_chip_information
-       *tmds_chip, struct tmds_setting_information *tmds_setting);
+static void __devinit dvi_get_panel_size_from_DDCv1(
+       struct tmds_chip_information *tmds_chip,
+       struct tmds_setting_information *tmds_setting);
+static void __devinit dvi_get_panel_size_from_DDCv2(
+       struct tmds_chip_information *tmds_chip,
+       struct tmds_setting_information *tmds_setting);
 static int viafb_dvi_query_EDID(void);
 
 static int check_tmds_chip(int device_id_subaddr, int device_id)
@@ -39,7 +41,7 @@ static int check_tmds_chip(int device_id_subaddr, int device_id)
                return FAIL;
 }
 
-void viafb_init_dvi_size(struct tmds_chip_information *tmds_chip,
+void __devinit viafb_init_dvi_size(struct tmds_chip_information *tmds_chip,
        struct tmds_setting_information *tmds_setting)
 {
        DEBUG_MSG(KERN_INFO "viafb_init_dvi_size()\n");
@@ -60,7 +62,7 @@ void viafb_init_dvi_size(struct tmds_chip_information *tmds_chip,
        return;
 }
 
-int viafb_tmds_trasmitter_identify(void)
+int __devinit viafb_tmds_trasmitter_identify(void)
 {
        unsigned char sr2a = 0, sr1e = 0, sr3e = 0;
 
@@ -208,8 +210,6 @@ void viafb_dvi_set_mode(struct VideoModeTable *mode, int mode_bpp,
                }
        }
        viafb_fill_crtc_timing(pDviTiming, mode, mode_bpp / 8, set_iga);
-       viafb_set_output_path(DEVICE_DVI, set_iga,
-                       viaparinfo->chip_info->tmds_chip_info.output_interface);
 }
 
 /* Sense DVI Connector */
@@ -313,8 +313,9 @@ static int viafb_dvi_query_EDID(void)
 }
 
 /* Get Panel Size Using EDID1 Table */
-static void dvi_get_panel_size_from_DDCv1(struct tmds_chip_information
-       *tmds_chip, struct tmds_setting_information *tmds_setting)
+static void __devinit dvi_get_panel_size_from_DDCv1(
+       struct tmds_chip_information *tmds_chip,
+       struct tmds_setting_information *tmds_setting)
 {
        int i, max_h = 0, tmp, restore;
        unsigned char rData;
@@ -418,8 +419,9 @@ static void dvi_get_panel_size_from_DDCv1(struct tmds_chip_information
 }
 
 /* Get Panel Size Using EDID2 Table */
-static void dvi_get_panel_size_from_DDCv2(struct tmds_chip_information
-       *tmds_chip, struct tmds_setting_information *tmds_setting)
+static void __devinit dvi_get_panel_size_from_DDCv2(
+       struct tmds_chip_information *tmds_chip,
+       struct tmds_setting_information *tmds_setting)
 {
        int restore;
        unsigned char R_Buffer[2];
@@ -467,26 +469,6 @@ static void dvi_get_panel_size_from_DDCv2(struct tmds_chip_information
 /* If Disable DVI, turn off pad */
 void viafb_dvi_disable(void)
 {
-       if (viaparinfo->chip_info->
-               tmds_chip_info.output_interface == INTERFACE_DVP0)
-               viafb_write_reg(SR1E, VIASR,
-               viafb_read_reg(VIASR, SR1E) & (~0xC0));
-
-       if (viaparinfo->chip_info->
-               tmds_chip_info.output_interface == INTERFACE_DVP1)
-               viafb_write_reg(SR1E, VIASR,
-               viafb_read_reg(VIASR, SR1E) & (~0x30));
-
-       if (viaparinfo->chip_info->
-               tmds_chip_info.output_interface == INTERFACE_DFP_HIGH)
-               viafb_write_reg(SR2A, VIASR,
-               viafb_read_reg(VIASR, SR2A) & (~0x0C));
-
-       if (viaparinfo->chip_info->
-               tmds_chip_info.output_interface == INTERFACE_DFP_LOW)
-               viafb_write_reg(SR2A, VIASR,
-               viafb_read_reg(VIASR, SR2A) & (~0x03));
-
        if (viaparinfo->chip_info->
                tmds_chip_info.output_interface == INTERFACE_TMDS)
                /* Turn off TMDS power. */
@@ -494,38 +476,101 @@ void viafb_dvi_disable(void)
                viafb_read_reg(VIACR, CRD2) | 0x08);
 }
 
+static void dvi_patch_skew_dvp0(void)
+{
+       /* Reset data driving first: */
+       viafb_write_reg_mask(SR1B, VIASR, 0, BIT1);
+       viafb_write_reg_mask(SR2A, VIASR, 0, BIT4);
+
+       switch (viaparinfo->chip_info->gfx_chip_name) {
+       case UNICHROME_P4M890:
+               {
+                       if ((viaparinfo->tmds_setting_info->h_active == 1600) &&
+                               (viaparinfo->tmds_setting_info->v_active ==
+                               1200))
+                               viafb_write_reg_mask(CR96, VIACR, 0x03,
+                                              BIT0 + BIT1 + BIT2);
+                       else
+                               viafb_write_reg_mask(CR96, VIACR, 0x07,
+                                              BIT0 + BIT1 + BIT2);
+                       break;
+               }
+
+       case UNICHROME_P4M900:
+               {
+                       viafb_write_reg_mask(CR96, VIACR, 0x07,
+                                      BIT0 + BIT1 + BIT2 + BIT3);
+                       viafb_write_reg_mask(SR1B, VIASR, 0x02, BIT1);
+                       viafb_write_reg_mask(SR2A, VIASR, 0x10, BIT4);
+                       break;
+               }
+
+       default:
+               {
+                       break;
+               }
+       }
+}
+
+static void dvi_patch_skew_dvp_low(void)
+{
+       switch (viaparinfo->chip_info->gfx_chip_name) {
+       case UNICHROME_K8M890:
+               {
+                       viafb_write_reg_mask(CR99, VIACR, 0x03, BIT0 + BIT1);
+                       break;
+               }
+
+       case UNICHROME_P4M900:
+               {
+                       viafb_write_reg_mask(CR99, VIACR, 0x08,
+                                      BIT0 + BIT1 + BIT2 + BIT3);
+                       break;
+               }
+
+       case UNICHROME_P4M890:
+               {
+                       viafb_write_reg_mask(CR99, VIACR, 0x0F,
+                                      BIT0 + BIT1 + BIT2 + BIT3);
+                       break;
+               }
+
+       default:
+               {
+                       break;
+               }
+       }
+}
+
 /* If Enable DVI, turn off pad */
 void viafb_dvi_enable(void)
 {
        u8 data;
 
-       if (viaparinfo->chip_info->
-               tmds_chip_info.output_interface == INTERFACE_DVP0) {
-               viafb_write_reg(SR1E, VIASR,
-                       viafb_read_reg(VIASR, SR1E) | 0xC0);
+       switch (viaparinfo->chip_info->tmds_chip_info.output_interface) {
+       case INTERFACE_DVP0:
+               viafb_write_reg_mask(CR6B, VIACR, 0x01, BIT0);
+               viafb_write_reg_mask(CR6C, VIACR, 0x21, BIT0 + BIT5);
+               dvi_patch_skew_dvp0();
                if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
                        tmds_register_write(0x88, 0x3b);
                else
                        /*clear CR91[5] to direct on display period
                           in the secondary diplay path */
-                       viafb_write_reg(CR91, VIACR,
-                       viafb_read_reg(VIACR, CR91) & 0xDF);
-       }
+                       via_write_reg_mask(VIACR, 0x91, 0x00, 0x20);
+               break;
 
-       if (viaparinfo->chip_info->
-               tmds_chip_info.output_interface == INTERFACE_DVP1) {
-               viafb_write_reg(SR1E, VIASR,
-                       viafb_read_reg(VIASR, SR1E) | 0x30);
+       case INTERFACE_DVP1:
+               if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
+                       viafb_write_reg_mask(CR93, VIACR, 0x21, BIT0 + BIT5);
 
                /*fix dvi cann't be enabled with MB VT5718C4 - Al Zhang */
-               if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
+               if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
                        tmds_register_write(0x88, 0x3b);
-               } else {
+               else
                        /*clear CR91[5] to direct on display period
                          in the secondary diplay path */
-                       viafb_write_reg(CR91, VIACR,
-                       viafb_read_reg(VIACR, CR91) & 0xDF);
-               }
+                       via_write_reg_mask(VIACR, 0x91, 0x00, 0x20);
 
                /*fix DVI cannot enable on EPIA-M board */
                if (viafb_platform_epia_dvi == 1) {
@@ -537,36 +582,40 @@ void viafb_dvi_enable(void)
                                else
                                        data = 0x37;
                                viafb_i2c_writebyte(viaparinfo->chip_info->
-                                                      tmds_chip_info.i2c_port,
-                                                   viaparinfo->chip_info->
-                                                      tmds_chip_info.tmds_chip_slave_addr,
-                                                   0x08, data);
+                                       tmds_chip_info.i2c_port,
+                                       viaparinfo->chip_info->
+                                       tmds_chip_info.tmds_chip_slave_addr,
+                                       0x08, data);
                        }
                }
-       }
+               break;
 
-       if (viaparinfo->chip_info->
-               tmds_chip_info.output_interface == INTERFACE_DFP_HIGH) {
-               viafb_write_reg(SR2A, VIASR,
-                       viafb_read_reg(VIASR, SR2A) | 0x0C);
-               viafb_write_reg(CR91, VIACR,
-                       viafb_read_reg(VIACR, CR91) & 0xDF);
-       }
+       case INTERFACE_DFP_HIGH:
+               if (viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266)
+                       via_write_reg_mask(VIACR, CR97, 0x03, 0x03);
 
-       if (viaparinfo->chip_info->
-               tmds_chip_info.output_interface == INTERFACE_DFP_LOW) {
-               viafb_write_reg(SR2A, VIASR,
-                       viafb_read_reg(VIASR, SR2A) | 0x03);
-               viafb_write_reg(CR91, VIACR,
-                       viafb_read_reg(VIACR, CR91) & 0xDF);
-       }
-       if (viaparinfo->chip_info->
-               tmds_chip_info.output_interface == INTERFACE_TMDS) {
+               via_write_reg_mask(VIACR, 0x91, 0x00, 0x20);
+               break;
+
+       case INTERFACE_DFP_LOW:
+               if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
+                       break;
+
+               dvi_patch_skew_dvp_low();
+               via_write_reg_mask(VIACR, 0x91, 0x00, 0x20);
+               break;
+
+       case INTERFACE_TMDS:
                /* Turn on Display period in the panel path. */
                viafb_write_reg_mask(CR91, VIACR, 0, BIT7);
 
                /* Turn on TMDS power. */
                viafb_write_reg_mask(CRD2, VIACR, 0, BIT3);
+               break;
        }
-}
 
+       if (viaparinfo->tmds_setting_info->iga_path == IGA2) {
+               /* Disable LCD Scaling */
+               viafb_write_reg_mask(CR79, VIACR, 0x00, BIT0);
+       }
+}