#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>
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);
*/
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:
}
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:
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)
}
-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)
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;
}
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++)
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);
* 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
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;
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;
{
struct fb_info *info = rinfo->info;
+ info->currcon = -1;
info->par = rinfo;
info->pseudo_palette = rinfo->pseudo_palette;
info->flags = FBINFO_DEFAULT
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)
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);
rinfo->video_ram = 8192 * 1024;
break;
default:
- printk (KERN_ERR "radeonfb: no video RAM reported\n");
- ret = -ENXIO;
- goto err_unmap_rom;
+ break;
}
}