This commit was manufactured by cvs2svn to create tag
[linux-2.6.git] / drivers / video / aty / radeon_base.c
index 22c6e90..4581379 100644 (file)
@@ -61,7 +61,6 @@
 #include <linux/tty.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
-#include <linux/time.h>
 #include <linux/fb.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
@@ -528,7 +527,8 @@ static int __devinit radeon_probe_pll_params(struct radeonfb_info *rinfo)
         break;
        }
 
-       ppll_div_sel = INREG(CLOCK_CNTL_INDEX + 1) & 0x3;
+       OUTREG8(CLOCK_CNTL_INDEX, 1);
+       ppll_div_sel = INREG8(CLOCK_CNTL_DATA + 1) & 0x3;
 
        n = (INPLL(PPLL_DIV_0 + ppll_div_sel) & 0x7ff);
        m = (INPLL(PPLL_REF_DIV) & 0x3ff);
@@ -595,10 +595,53 @@ static int __devinit radeon_probe_pll_params(struct radeonfb_info *rinfo)
  */
 static void __devinit radeon_get_pllinfo(struct radeonfb_info *rinfo)
 {
+#ifdef CONFIG_PPC_OF
+       /*
+        * Retreive PLL infos from Open Firmware first
+        */
+               if (!force_measure_pll && radeon_read_xtal_OF(rinfo) == 0) {
+                       printk(KERN_INFO "radeonfb: Retreived PLL infos from Open Firmware\n");
+                       rinfo->pll.ref_div = INPLL(PPLL_REF_DIV) & 0x3ff;
+               /* FIXME: Max clock may be higher on newer chips */
+                       rinfo->pll.ppll_min = 12000;
+                       rinfo->pll.ppll_max = 35000;
+               goto found;
+       }
+#endif /* CONFIG_PPC_OF */
+
+       /*
+        * Check out if we have an X86 which gave us some PLL informations
+        * and if yes, retreive them
+        */
+       if (!force_measure_pll && rinfo->bios_seg) {
+               u16 pll_info_block = BIOS_IN16(rinfo->fp_bios_start + 0x30);
+
+               rinfo->pll.sclk         = BIOS_IN16(pll_info_block + 0x08);
+               rinfo->pll.mclk         = BIOS_IN16(pll_info_block + 0x0a);
+               rinfo->pll.ref_clk      = BIOS_IN16(pll_info_block + 0x0e);
+               rinfo->pll.ref_div      = BIOS_IN16(pll_info_block + 0x10);
+               rinfo->pll.ppll_min     = BIOS_IN32(pll_info_block + 0x12);
+               rinfo->pll.ppll_max     = BIOS_IN32(pll_info_block + 0x16);
+
+               printk(KERN_INFO "radeonfb: Retreived PLL infos from BIOS\n");
+               goto found;
+       }
+
        /*
-        * In the case nothing works, these are defaults; they are mostly
-        * incomplete, however.  It does provide ppll_max and _min values
-        * even for most other methods, however.
+        * We didn't get PLL parameters from either OF or BIOS, we try to
+        * probe them
+        */
+       if (radeon_probe_pll_params(rinfo) == 0) {
+               printk(KERN_INFO "radeonfb: Retreived PLL infos from registers\n");
+               /* FIXME: Max clock may be higher on newer chips */
+                       rinfo->pll.ppll_min = 12000;
+                       rinfo->pll.ppll_max = 35000;
+               goto found;
+       }
+
+       /*
+        * Neither of the above worked, we have a few default values, though
+        * that's mostly incomplete
         */
        switch (rinfo->chipset) {
        case PCI_DEVICE_ID_ATI_RADEON_QW:
@@ -654,47 +697,6 @@ static void __devinit radeon_get_pllinfo(struct radeonfb_info *rinfo)
        }
        rinfo->pll.ref_div = INPLL(PPLL_REF_DIV) & 0x3ff;
 
-
-#ifdef CONFIG_PPC_OF
-       /*
-        * Retreive PLL infos from Open Firmware first
-        */
-               if (!force_measure_pll && radeon_read_xtal_OF(rinfo) == 0) {
-                       printk(KERN_INFO "radeonfb: Retreived PLL infos from Open Firmware\n");
-               goto found;
-       }
-#endif /* CONFIG_PPC_OF */
-
-       /*
-        * Check out if we have an X86 which gave us some PLL informations
-        * and if yes, retreive them
-        */
-       if (!force_measure_pll && rinfo->bios_seg) {
-               u16 pll_info_block = BIOS_IN16(rinfo->fp_bios_start + 0x30);
-
-               rinfo->pll.sclk         = BIOS_IN16(pll_info_block + 0x08);
-               rinfo->pll.mclk         = BIOS_IN16(pll_info_block + 0x0a);
-               rinfo->pll.ref_clk      = BIOS_IN16(pll_info_block + 0x0e);
-               rinfo->pll.ref_div      = BIOS_IN16(pll_info_block + 0x10);
-               rinfo->pll.ppll_min     = BIOS_IN32(pll_info_block + 0x12);
-               rinfo->pll.ppll_max     = BIOS_IN32(pll_info_block + 0x16);
-
-               printk(KERN_INFO "radeonfb: Retreived PLL infos from BIOS\n");
-               goto found;
-       }
-
-       /*
-        * We didn't get PLL parameters from either OF or BIOS, we try to
-        * probe them
-        */
-       if (radeon_probe_pll_params(rinfo) == 0) {
-               printk(KERN_INFO "radeonfb: Retreived PLL infos from registers\n");
-               goto found;
-       }
-
-       /*
-        * Fall back to already-set defaults...
-        */
                printk(KERN_INFO "radeonfb: Used default PLL infos\n");
 
 found:
@@ -713,7 +715,6 @@ found:
               rinfo->pll.ref_div,
               rinfo->pll.mclk / 100, rinfo->pll.mclk % 100,
               rinfo->pll.sclk / 100, rinfo->pll.sclk % 100);
-       printk("radeonfb: PLL min %d max %d\n", rinfo->pll.ppll_min, rinfo->pll.ppll_max);
 }
 
 static int radeonfb_check_var (struct fb_var_screeninfo *var, struct fb_info *info)
@@ -933,101 +934,46 @@ static int radeonfb_ioctl (struct inode *inode, struct file *file, unsigned int
 }
 
 
-static int radeon_screen_blank (struct radeonfb_info *rinfo, int blank, int mode_switch)
+static int radeon_screen_blank (struct radeonfb_info *rinfo, int blank)
 {
-        u32 val;
-       u32 tmp_pix_clks;
-
-       if (rinfo->lock_blank)
-               return 0;
-
-       radeon_engine_idle();
+        u32 val = INREG(CRTC_EXT_CNTL);
+       u32 val2 = 0;
 
-       val = INREG(CRTC_EXT_CNTL);
+       if (rinfo->mon1_type == MT_LCD)
+               val2 = INREG(LVDS_GEN_CNTL) & ~LVDS_DISPLAY_DIS;
+       
+        /* reset it */
         val &= ~(CRTC_DISPLAY_DIS | CRTC_HSYNC_DIS |
                  CRTC_VSYNC_DIS);
+
         switch (blank) {
-       case FB_BLANK_UNBLANK:
-       case FB_BLANK_NORMAL:
-               break;
-       case FB_BLANK_VSYNC_SUSPEND:
-               val |= (CRTC_DISPLAY_DIS | CRTC_VSYNC_DIS);
-               break;
-       case FB_BLANK_HSYNC_SUSPEND:
-               val |= (CRTC_DISPLAY_DIS | CRTC_HSYNC_DIS);
-               break;
-       case FB_BLANK_POWERDOWN:
-               val |= (CRTC_DISPLAY_DIS | CRTC_VSYNC_DIS |
-                       CRTC_HSYNC_DIS);
-               break;
+                case VESA_NO_BLANKING:
+                        break;
+                case VESA_VSYNC_SUSPEND:
+                        val |= (CRTC_DISPLAY_DIS | CRTC_VSYNC_DIS);
+                        break;
+                case VESA_HSYNC_SUSPEND:
+                        val |= (CRTC_DISPLAY_DIS | CRTC_HSYNC_DIS);
+                        break;
+                case VESA_POWERDOWN:
+                        val |= (CRTC_DISPLAY_DIS | CRTC_VSYNC_DIS | 
+                                CRTC_HSYNC_DIS);
+                       val2 |= (LVDS_DISPLAY_DIS);
+                        break;
         }
-       OUTREG(CRTC_EXT_CNTL, val);
-
 
+       radeon_fifo_wait(1);
        switch (rinfo->mon1_type) {
-       case MT_DFP:
-               if (mode_switch)
+               case MT_LCD:
+                       OUTREG(LVDS_GEN_CNTL, val2);
+                       break;
+               case MT_CRT:
+               default:
+                       OUTREG(CRTC_EXT_CNTL, val);
                        break;
-               if (blank == FB_BLANK_UNBLANK ||
-                   blank == FB_BLANK_NORMAL)
-                       OUTREGP(FP_GEN_CNTL, (FP_FPON | FP_TMDS_EN),
-                               ~(FP_FPON | FP_TMDS_EN));
-               else
-                       OUTREGP(FP_GEN_CNTL, 0, ~(FP_FPON | FP_TMDS_EN));
-               break;
-       case MT_LCD:
-               val = INREG(LVDS_GEN_CNTL);
-               if (blank == FB_BLANK_UNBLANK ||
-                   blank == FB_BLANK_NORMAL) {
-                       u32 target_val = (val & ~LVDS_DISPLAY_DIS) | LVDS_BLON | LVDS_ON
-                               | LVDS_ON | (rinfo->init_state.lvds_gen_cntl & LVDS_DIGON);
-                       if ((val ^ target_val) == LVDS_DISPLAY_DIS)
-                               OUTREG(LVDS_GEN_CNTL, target_val);
-                       else if ((val ^ target_val) != 0) {
-                               del_timer_sync(&rinfo->lvds_timer);
-                               OUTREG(LVDS_GEN_CNTL, target_val & ~LVDS_ON);
-                               rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK;
-                               rinfo->init_state.lvds_gen_cntl |= target_val & LVDS_STATE_MASK;
-                               if (mode_switch) {
-                                       msleep(rinfo->panel_info.pwr_delay);
-                                       OUTREG(LVDS_GEN_CNTL, target_val);
-                               }
-                               else {
-                                       rinfo->pending_lvds_gen_cntl = target_val;
-                                       mod_timer(&rinfo->lvds_timer,
-                                               jiffies + msecs_to_jiffies(rinfo->panel_info.pwr_delay));
-                               }
-                       }
-               } else {
-                       val |= LVDS_DISPLAY_DIS;
-                       OUTREG(LVDS_GEN_CNTL, val);
-
-                       /* We don't do a full switch-off on a simple mode switch */
-                       if (mode_switch)
-                               break;
-
-                       /* Asic bug, when turning off LVDS_ON, we have to make sure
-                        * RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off
-                        */
-                       tmp_pix_clks = INPLL(PIXCLKS_CNTL);
-                       if (rinfo->is_mobility || rinfo->is_IGP)
-                               OUTPLLP(PIXCLKS_CNTL, 0, ~PIXCLK_LVDS_ALWAYS_ONb);
-                       val &= ~(LVDS_BLON | LVDS_ON);
-                       OUTREG(LVDS_GEN_CNTL, val);
-                       rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK;
-                       rinfo->init_state.lvds_gen_cntl |= val & LVDS_STATE_MASK;
-                       if (rinfo->is_mobility || rinfo->is_IGP)
-                               OUTPLL(PIXCLKS_CNTL, tmp_pix_clks);
-               }
-               break;
-       case MT_CRT:
-               // todo: powerdown DAC
-       default:
-               break;
        }
 
-       /* let fbcon do a soft blank for us */
-       return (blank == FB_BLANK_NORMAL) ? -EINVAL : 0;
+       return 0;
 }
 
 int radeonfb_blank (int blank, struct fb_info *info)
@@ -1037,7 +983,17 @@ int radeonfb_blank (int blank, struct fb_info *info)
        if (rinfo->asleep)
                return 0;
                
-       radeon_screen_blank(rinfo, blank, 0);
+#ifdef CONFIG_PMAC_BACKLIGHT
+       if (rinfo->mon1_type == MT_LCD && _machine == _MACH_Pmac && blank)
+               set_backlight_enable(0);
+#endif
+                        
+       radeon_screen_blank(rinfo, blank);
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+       if (rinfo->mon1_type == MT_LCD && _machine == _MACH_Pmac && !blank)
+               set_backlight_enable(1);
+#endif
 
        return 0;
 }
@@ -1269,8 +1225,7 @@ static void radeon_write_mode (struct radeonfb_info *rinfo,
 
        del_timer_sync(&rinfo->lvds_timer);
 
-       radeon_screen_blank(rinfo, FB_BLANK_POWERDOWN, 1);
-       msleep(100);
+       radeon_screen_blank(rinfo, VESA_POWERDOWN);
 
        radeon_fifo_wait(31);
        for (i=0; i<10; i++)
@@ -1310,9 +1265,35 @@ static void radeon_write_mode (struct radeonfb_info *rinfo,
                OUTREG(FP_GEN_CNTL, mode->fp_gen_cntl);
                OUTREG(TMDS_CRC, mode->tmds_crc);
                OUTREG(TMDS_TRANSMITTER_CNTL, mode->tmds_transmitter_cntl);
+
+               if (primary_mon == MT_LCD) {
+                       unsigned int tmp = INREG(LVDS_GEN_CNTL);
+
+                       /* HACK: The backlight control code may have modified init_state.lvds_gen_cntl,
+                        * so we update ourselves
+                        */
+                       mode->lvds_gen_cntl &= ~LVDS_STATE_MASK;
+                       mode->lvds_gen_cntl |= (rinfo->init_state.lvds_gen_cntl & LVDS_STATE_MASK);
+
+                       if ((tmp & (LVDS_ON | LVDS_BLON)) ==
+                           (mode->lvds_gen_cntl & (LVDS_ON | LVDS_BLON))) {
+                               OUTREG(LVDS_GEN_CNTL, mode->lvds_gen_cntl);
+                       } else {
+                               rinfo->pending_pixclks_cntl = INPLL(PIXCLKS_CNTL);
+                               if (rinfo->is_mobility || rinfo->is_IGP)
+                                       OUTPLLP(PIXCLKS_CNTL, 0, ~PIXCLK_LVDS_ALWAYS_ONb);
+                               if (!(tmp & (LVDS_ON | LVDS_BLON)))
+                                       OUTREG(LVDS_GEN_CNTL, mode->lvds_gen_cntl | LVDS_BLON);
+                               rinfo->pending_lvds_gen_cntl = mode->lvds_gen_cntl;
+                               mod_timer(&rinfo->lvds_timer,
+                                         jiffies + MS_TO_HZ(rinfo->panel_info.pwr_delay));
+                       }
+               }
        }
 
-       radeon_screen_blank(rinfo, FB_BLANK_UNBLANK, 1);
+       RTRACE("lvds_gen_cntl: %08x\n", INREG(LVDS_GEN_CNTL));
+
+       radeon_screen_blank(rinfo, VESA_NO_BLANKING);
 
        radeon_fifo_wait(2);
        OUTPLL(VCLK_ECP_CNTL, mode->vclk_ecp_cntl);
@@ -1348,7 +1329,7 @@ static void radeon_calc_pll_regs(struct radeonfb_info *rinfo, struct radeon_regs
         * not sure which model starts having FP2_GEN_CNTL, I assume anything more
         * recent than an r(v)100...
         */
-#if 1
+#if 0
        /* XXX I had reports of flicker happening with the cinema display
         * on TMDS1 that seem to be fixed if I also forbit odd dividers in
         * this case. This could just be a bandwidth calculation issue, I
@@ -1398,8 +1379,6 @@ static void radeon_calc_pll_regs(struct radeonfb_info *rinfo, struct radeon_regs
                freq = rinfo->pll.ppll_max;
        if (freq*12 < rinfo->pll.ppll_min)
                freq = rinfo->pll.ppll_min / 12;
-       RTRACE("freq = %lu, PLL min = %u, PLL max = %u\n",
-              freq, rinfo->pll.ppll_min, rinfo->pll.ppll_max);
 
        for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
                pll_output_freq = post_div->divider * freq;
@@ -1413,16 +1392,6 @@ static void radeon_calc_pll_regs(struct radeonfb_info *rinfo, struct radeon_regs
                        break;
        }
 
-       /* If we fall through the bottom, try the "default value"
-          given by the terminal post_div->bitvalue */
-       if ( !post_div->divider ) {
-               post_div = &post_divs[post_div->bitvalue];
-               pll_output_freq = post_div->divider * freq;
-       }
-       RTRACE("ref_div = %d, ref_clk = %d, output_freq = %d\n",
-              rinfo->pll.ref_div, rinfo->pll.ref_clk,
-              pll_output_freq);
-
        fb_div = round_div(rinfo->pll.ref_div*pll_output_freq,
                                  rinfo->pll.ref_clk);
        regs->ppll_ref_div = rinfo->pll.ref_div;
@@ -1758,6 +1727,7 @@ static int __devinit radeon_set_fbinfo (struct radeonfb_info *rinfo)
 {
        struct fb_info *info = rinfo->info;
 
+       info->currcon = -1;
        info->par = rinfo;
        info->pseudo_palette = rinfo->pseudo_palette;
        info->flags = FBINFO_DEFAULT
@@ -1815,7 +1785,8 @@ static int backlight_conv_m7[] = {
 static int radeon_set_backlight_enable(int on, int level, void *data)
 {
        struct radeonfb_info *rinfo = (struct radeonfb_info *)data;
-       u32 lvds_gen_cntl, tmpPixclksCntl;
+       unsigned int lvds_gen_cntl = INREG(LVDS_GEN_CNTL);
+       unsigned long tmpPixclksCntl = INPLL(PIXCLKS_CNTL);
        int* conv_table;
 
        if (rinfo->mon1_type != MT_LCD)
@@ -1837,47 +1808,42 @@ static int radeon_set_backlight_enable(int on, int level, void *data)
                conv_table = backlight_conv_m6;
 
        del_timer_sync(&rinfo->lvds_timer);
-       radeon_engine_idle();
 
-       lvds_gen_cntl = INREG(LVDS_GEN_CNTL);
+       lvds_gen_cntl |= (LVDS_BL_MOD_EN | LVDS_BLON);
+       radeon_fifo_wait(3);
        if (on && (level > BACKLIGHT_OFF)) {
-               lvds_gen_cntl &= ~LVDS_DISPLAY_DIS;
-               if (!(lvds_gen_cntl & LVDS_BLON) || !(lvds_gen_cntl & LVDS_ON)) {
-                       lvds_gen_cntl |= LVDS_BLON /* | LVDS_EN | LVDS_DIGON */;
+               lvds_gen_cntl |= LVDS_DIGON;
+               if (!(lvds_gen_cntl & LVDS_ON)) {
+                       lvds_gen_cntl &= ~LVDS_BLON;
                        OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
-                       lvds_gen_cntl &= ~LVDS_BL_MOD_LEVEL_MASK;
-                       lvds_gen_cntl |= (conv_table[level] <<
-                                         LVDS_BL_MOD_LEVEL_SHIFT);
-                       lvds_gen_cntl |= LVDS_ON;
-                       rinfo->pending_lvds_gen_cntl = lvds_gen_cntl;
-                       mod_timer(&rinfo->lvds_timer,
-                                 jiffies + msecs_to_jiffies(rinfo->panel_info.pwr_delay));
-               } else {
-                       lvds_gen_cntl &= ~LVDS_BL_MOD_LEVEL_MASK;
-                       lvds_gen_cntl |= (conv_table[level] <<
-                                         LVDS_BL_MOD_LEVEL_SHIFT);
+                       (void)INREG(LVDS_GEN_CNTL);
+                       mdelay(rinfo->panel_info.pwr_delay);/* OUCH !!! FIXME */
+                       lvds_gen_cntl |= LVDS_BLON;
                        OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
                }
-               rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK;
-               rinfo->init_state.lvds_gen_cntl |= rinfo->pending_lvds_gen_cntl
-                       & LVDS_STATE_MASK;
+               lvds_gen_cntl &= ~LVDS_BL_MOD_LEVEL_MASK;
+               lvds_gen_cntl |= (conv_table[level] <<
+                                 LVDS_BL_MOD_LEVEL_SHIFT);
+               lvds_gen_cntl |= (LVDS_ON | LVDS_EN);
+               lvds_gen_cntl &= ~LVDS_DISPLAY_DIS;
        } else {
                /* Asic bug, when turning off LVDS_ON, we have to make sure
                   RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off
                */
-               tmpPixclksCntl = INPLL(PIXCLKS_CNTL);
                if (rinfo->is_mobility || rinfo->is_IGP)
                        OUTPLLP(PIXCLKS_CNTL, 0, ~PIXCLK_LVDS_ALWAYS_ONb);
                lvds_gen_cntl &= ~LVDS_BL_MOD_LEVEL_MASK;
                lvds_gen_cntl |= (conv_table[0] <<
                                  LVDS_BL_MOD_LEVEL_SHIFT);
-               lvds_gen_cntl |= LVDS_DISPLAY_DIS;
+               lvds_gen_cntl |= LVDS_DISPLAY_DIS | LVDS_BLON;
                OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
-               lvds_gen_cntl &= ~(LVDS_ON | LVDS_BLON /* | LVDS_EN | LVDS_DIGON */);
-               OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
-               if (rinfo->is_mobility || rinfo->is_IGP)
-                       OUTPLL(PIXCLKS_CNTL, tmpPixclksCntl);
+               mdelay(rinfo->panel_info.pwr_delay);/* OUCH !!! FIXME */
+               lvds_gen_cntl &= ~(LVDS_ON | LVDS_EN | LVDS_BLON | LVDS_DIGON);
        }
+
+       OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
+       if (rinfo->is_mobility || rinfo->is_IGP)
+               OUTPLL(PIXCLKS_CNTL, tmpPixclksCntl);
        rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK;
        rinfo->init_state.lvds_gen_cntl |= (lvds_gen_cntl & LVDS_STATE_MASK);
 
@@ -2194,9 +2160,7 @@ static int radeonfb_pci_register (struct pci_dev *pdev,
                        rinfo->video_ram = 8192 * 1024;
                        break;
                default:
-                       printk (KERN_ERR "radeonfb: no video RAM reported\n");
-                       ret = -ENXIO;
-                       goto err_unmap_rom;
+                       break;
                }
        }