Commit b4eca0a8 authored by Benjamin Herrenschmidt's avatar Benjamin Herrenschmidt Committed by Linus Torvalds

[PATCH] radeonfb update

It adds the sleep support for newer powermacs, improve power saving on some
laptops, makes use of the new fbdev modelist management routines, and fixes
a few backlight related issues.

I tested it on a thinkpad T30 and a few PPC boxes with success.  It should
be less invasive than the previous one (I don't try to restore the mode on
exit, that is what breaks the thinkpad and possibly other stuffs that boot
in VGA text mode), plus fixed a couple of bugs in the mode detection code. 
I also reverted the memory map fix on ppc since it doesn't work properly on
some recent laptops where the firmware sets a tiled display.  I'll rework
that completely to update the memory map as part of the mode setting later.
That should fix various issues when switching with X/DRI on x86.
Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent bcbfc29d
......@@ -4,6 +4,18 @@
* radeonfb
*/
#define PCI_CHIP_RV380_3150 0x3150
#define PCI_CHIP_RV380_3151 0x3151
#define PCI_CHIP_RV380_3152 0x3152
#define PCI_CHIP_RV380_3153 0x3153
#define PCI_CHIP_RV380_3154 0x3154
#define PCI_CHIP_RV380_3156 0x3156
#define PCI_CHIP_RV380_3E50 0x3E50
#define PCI_CHIP_RV380_3E51 0x3E51
#define PCI_CHIP_RV380_3E52 0x3E52
#define PCI_CHIP_RV380_3E53 0x3E53
#define PCI_CHIP_RV380_3E54 0x3E54
#define PCI_CHIP_RV380_3E56 0x3E56
#define PCI_CHIP_RS100_4136 0x4136
#define PCI_CHIP_RS200_4137 0x4137
#define PCI_CHIP_R300_AD 0x4144
......@@ -52,6 +64,14 @@
#define PCI_CHIP_RV250_Ie 0x4965
#define PCI_CHIP_RV250_If 0x4966
#define PCI_CHIP_RV250_Ig 0x4967
#define PCI_CHIP_R420_JH 0x4A48
#define PCI_CHIP_R420_JI 0x4A49
#define PCI_CHIP_R420_JJ 0x4A4A
#define PCI_CHIP_R420_JK 0x4A4B
#define PCI_CHIP_R420_JL 0x4A4C
#define PCI_CHIP_R420_JM 0x4A4D
#define PCI_CHIP_R420_JN 0x4A4E
#define PCI_CHIP_R420_JP 0x4A50
#define PCI_CHIP_MACH64LB 0x4C42
#define PCI_CHIP_MACH64LD 0x4C44
#define PCI_CHIP_RAGE128LE 0x4C45
......@@ -73,6 +93,7 @@
#define PCI_CHIP_RV250_Le 0x4C65
#define PCI_CHIP_RV250_Lf 0x4C66
#define PCI_CHIP_RV250_Lg 0x4C67
#define PCI_CHIP_RV250_Ln 0x4C6E
#define PCI_CHIP_RAGE128MF 0x4D46
#define PCI_CHIP_RAGE128ML 0x4D4C
#define PCI_CHIP_R300_ND 0x4E44
......@@ -148,6 +169,21 @@
#define PCI_CHIP_RAGE128TS 0x5453
#define PCI_CHIP_RAGE128TT 0x5454
#define PCI_CHIP_RAGE128TU 0x5455
#define PCI_CHIP_RV370_5460 0x5460
#define PCI_CHIP_RV370_5461 0x5461
#define PCI_CHIP_RV370_5462 0x5462
#define PCI_CHIP_RV370_5463 0x5463
#define PCI_CHIP_RV370_5464 0x5464
#define PCI_CHIP_RV370_5465 0x5465
#define PCI_CHIP_RV370_5466 0x5466
#define PCI_CHIP_RV370_5467 0x5467
#define PCI_CHIP_R423_UH 0x5548
#define PCI_CHIP_R423_UI 0x5549
#define PCI_CHIP_R423_UJ 0x554A
#define PCI_CHIP_R423_UK 0x554B
#define PCI_CHIP_R423_UQ 0x5551
#define PCI_CHIP_R423_UR 0x5552
#define PCI_CHIP_R423_UT 0x5554
#define PCI_CHIP_MACH64VT 0x5654
#define PCI_CHIP_MACH64VU 0x5655
#define PCI_CHIP_MACH64VV 0x5656
......@@ -155,14 +191,21 @@
#define PCI_CHIP_RS300_5835 0x5835
#define PCI_CHIP_RS300_5836 0x5836
#define PCI_CHIP_RS300_5837 0x5837
#define PCI_CHIP_RV370_5B60 0x5B60
#define PCI_CHIP_RV370_5B61 0x5B61
#define PCI_CHIP_RV370_5B62 0x5B62
#define PCI_CHIP_RV370_5B63 0x5B63
#define PCI_CHIP_RV370_5B64 0x5B64
#define PCI_CHIP_RV370_5B65 0x5B65
#define PCI_CHIP_RV370_5B66 0x5B66
#define PCI_CHIP_RV370_5B67 0x5B67
#define PCI_CHIP_RV280_5960 0x5960
#define PCI_CHIP_RV280_5961 0x5961
#define PCI_CHIP_RV280_5962 0x5962
#define PCI_CHIP_RV280_5963 0x5963
#define PCI_CHIP_RV280_5964 0x5964
#define PCI_CHIP_RV280_5968 0x5968
#define PCI_CHIP_RV280_5969 0x5969
#define PCI_CHIP_RV280_596A 0x596A
#define PCI_CHIP_RV280_596B 0x596B
#define PCI_CHIP_RV280_5C61 0x5C61
#define PCI_CHIP_RV280_5C63 0x5C63
#define PCI_CHIP_R423_5D57 0x5D57
#define PCI_CHIP_RS350_7834 0x7834
#define PCI_CHIP_RS350_7835 0x7835
This diff is collapsed.
#include "radeonfb.h"
#include "../edid.h"
#ifdef CONFIG_PPC_OF
#include <asm/prom.h>
#include <asm/pci-bridge.h>
#endif /* CONFIG_PPC_OF */
static struct fb_var_screeninfo radeonfb_default_var = {
.xres = 640,
.yres = 480,
......@@ -64,9 +59,11 @@ static char *radeon_get_mon_name(int type)
* models with broken OF probing by hard-coding known EDIDs for some Mac
* laptops internal LVDS panel. (XXX: not done yet)
*/
static int __devinit radeon_parse_montype_prop(struct device_node *dp, u8 **out_EDID, int hdno)
static int __devinit radeon_parse_montype_prop(struct device_node *dp, u8 **out_EDID,
int hdno)
{
static char *propnames[] = { "DFP,EDID", "LCD,EDID", "EDID", "EDID1", "EDID2", NULL };
static char *propnames[] = { "DFP,EDID", "LCD,EDID", "EDID",
"EDID1", "EDID2", NULL };
u8 *pedid = NULL;
u8 *pmt = NULL;
u8 *tmp;
......@@ -122,7 +119,7 @@ static int __devinit radeon_probe_OF_head(struct radeonfb_info *rinfo, int head_
RTRACE("radeon_probe_OF_head\n");
dp = pci_device_to_OF_node(rinfo->pdev);
dp = rinfo->of_node;
while (dp == NULL)
return MT_NONE;
......@@ -502,8 +499,9 @@ void __devinit radeon_probe_screens(struct radeonfb_info *rinfo,
#endif /* CONFIG_PPC_OF */
#ifdef CONFIG_FB_RADEON_I2C
if (rinfo->mon1_type == MT_NONE)
rinfo->mon1_type = radeon_probe_i2c_connector(rinfo, ddc_dvi,
&rinfo->mon1_EDID);
rinfo->mon1_type =
radeon_probe_i2c_connector(rinfo, ddc_dvi,
&rinfo->mon1_EDID);
if (rinfo->mon1_type == MT_NONE)
rinfo->mon1_type =
radeon_probe_i2c_connector(rinfo, ddc_vga,
......@@ -545,7 +543,8 @@ void __devinit radeon_probe_screens(struct radeonfb_info *rinfo,
*/
#ifdef CONFIG_PPC_OF
if (rinfo->mon1_type == MT_NONE)
rinfo->mon1_type = radeon_probe_OF_head(rinfo, 0, &rinfo->mon1_EDID);
rinfo->mon1_type = radeon_probe_OF_head(rinfo, 0,
&rinfo->mon1_EDID);
#endif /* CONFIG_PPC_OF */
#ifdef CONFIG_FB_RADEON_I2C
if (rinfo->mon1_type == MT_NONE)
......@@ -572,7 +571,8 @@ void __devinit radeon_probe_screens(struct radeonfb_info *rinfo,
*/
#ifdef CONFIG_PPC_OF
if (rinfo->mon2_type == MT_NONE)
rinfo->mon2_type = radeon_probe_OF_head(rinfo, 1, &rinfo->mon2_EDID);
rinfo->mon2_type = radeon_probe_OF_head(rinfo, 1,
&rinfo->mon2_EDID);
#endif /* CONFIG_PPC_OF */
#ifdef CONFIG_FB_RADEON_I2C
if (rinfo->mon2_type == MT_NONE)
......@@ -648,10 +648,10 @@ void __devinit radeon_probe_screens(struct radeonfb_info *rinfo,
*/
static void radeon_fixup_panel_info(struct radeonfb_info *rinfo)
{
#ifdef CONFIG_PPC_OF
#ifdef CONFIG_PPC_OF
/*
* LCD Flat panels should use fixed dividers, we enfore that on
* PowerMac only for now...
* PPC only for now...
*/
if (!rinfo->panel_info.use_bios_dividers && rinfo->mon1_type == MT_LCD
&& rinfo->is_mobility) {
......@@ -702,40 +702,24 @@ static void radeon_var_to_panel_info(struct radeonfb_info *rinfo, struct fb_var_
rinfo->panel_info.pwr_delay = 200;
}
static void radeon_var_to_videomode(struct fb_videomode *mode,
const struct fb_var_screeninfo *var)
{
mode->xres = var->xres;
mode->yres = var->yres;
mode->pixclock = var->pixclock;
mode->left_margin = var->left_margin;
mode->right_margin = var->right_margin;
mode->upper_margin = var->upper_margin;
mode->lower_margin = var->lower_margin;
mode->hsync_len = var->hsync_len;
mode->vsync_len = var->vsync_len;
mode->sync = var->sync;
mode->vmode = var->vmode;
}
static void radeon_videomode_to_var(struct fb_var_screeninfo *var,
const struct fb_videomode *mode)
{
var->xres = mode->xres;
var->yres = mode->yres;
var->xres_virtual = mode->xres;
var->yres_virtual = mode->yres;
var->xoffset = 0;
var->yoffset = 0;
var->pixclock = mode->pixclock;
var->left_margin = mode->left_margin;
var->right_margin = mode->right_margin;
var->upper_margin = mode->upper_margin;
var->lower_margin = mode->lower_margin;
var->hsync_len = mode->hsync_len;
var->vsync_len = mode->vsync_len;
var->sync = mode->sync;
var->vmode = mode->vmode;
var->xres = mode->xres;
var->yres = mode->yres;
var->xres_virtual = mode->xres;
var->yres_virtual = mode->yres;
var->xoffset = 0;
var->yoffset = 0;
var->pixclock = mode->pixclock;
var->left_margin = mode->left_margin;
var->right_margin = mode->right_margin;
var->upper_margin = mode->upper_margin;
var->lower_margin = mode->lower_margin;
var->hsync_len = mode->hsync_len;
var->vsync_len = mode->vsync_len;
var->sync = mode->sync;
var->vmode = mode->vmode;
}
/*
......@@ -744,12 +728,14 @@ static void radeon_videomode_to_var(struct fb_var_screeninfo *var,
*/
void __devinit radeon_check_modes(struct radeonfb_info *rinfo, const char *mode_option)
{
struct fb_info * info = rinfo->info;
int has_default_mode = 0;
/*
* Fill default var first
*/
rinfo->info->var = radeonfb_default_var;
info->var = radeonfb_default_var;
INIT_LIST_HEAD(&info->modelist);
/*
* First check out what BIOS has to say
......@@ -783,7 +769,7 @@ void __devinit radeon_check_modes(struct radeonfb_info *rinfo, const char *mode_
* those
*/
if (rinfo->mon1_type != MT_CRT && rinfo->panel_info.valid) {
struct fb_var_screeninfo *var = &rinfo->info->var;
struct fb_var_screeninfo *var = &info->var;
RTRACE("Setting up default mode based on panel info\n");
var->xres = rinfo->panel_info.xres;
......@@ -814,9 +800,12 @@ void __devinit radeon_check_modes(struct radeonfb_info *rinfo, const char *mode_
* Now build modedb from EDID
*/
if (rinfo->mon1_EDID) {
rinfo->mon1_modedb = fb_create_modedb(rinfo->mon1_EDID,
&rinfo->mon1_dbsize);
fb_get_monitor_limits(rinfo->mon1_EDID, &rinfo->info->monspecs);
fb_edid_to_monspecs(rinfo->mon1_EDID, &info->monspecs);
fb_videomode_to_modelist(info->monspecs.modedb,
info->monspecs.modedb_len,
&info->modelist);
rinfo->mon1_modedb = info->monspecs.modedb;
rinfo->mon1_dbsize = info->monspecs.modedb_len;
}
......@@ -847,31 +836,62 @@ void __devinit radeon_check_modes(struct radeonfb_info *rinfo, const char *mode_
modedb = rinfo->mon1_modedb;
dbsize = rinfo->mon1_dbsize;
snprintf(modename, 31, "%dx%d", rinfo->panel_info.xres, rinfo->panel_info.yres);
if (fb_find_mode(&rinfo->info->var, rinfo->info, modename,
if (fb_find_mode(&info->var, info, modename,
modedb, dbsize, NULL, 8) == 0) {
printk(KERN_WARNING "radeonfb: Can't find mode for panel size, going back to CRT\n");
rinfo->mon1_type = MT_CRT;
goto pickup_default;
}
has_default_mode = 1;
radeon_var_to_panel_info(rinfo, &rinfo->info->var);
radeon_var_to_panel_info(rinfo, &info->var);
}
pickup_default:
/*
* Pick up a random default mode
* Apply passed-in mode option if any
*/
if (!has_default_mode || mode_option) {
struct fb_videomode default_mode;
if (has_default_mode)
radeon_var_to_videomode(&default_mode, &rinfo->info->var);
else
radeon_var_to_videomode(&default_mode, &radeonfb_default_var);
if (fb_find_mode(&rinfo->info->var, rinfo->info, mode_option,
rinfo->mon1_modedb, rinfo->mon1_dbsize, &default_mode, 8) == 0)
rinfo->info->var = radeonfb_default_var;
}
if (mode_option) {
if (fb_find_mode(&info->var, info, mode_option,
info->monspecs.modedb,
info->monspecs.modedb_len, NULL, 8) != 0)
has_default_mode = 1;
}
/*
* Still no mode, let's pick up a default from the db
*/
if (!has_default_mode && info->monspecs.modedb != NULL) {
struct fb_monspecs *specs = &info->monspecs;
struct fb_videomode *modedb = NULL;
/* get preferred timing */
if (specs->misc & FB_MISC_1ST_DETAIL) {
int i;
for (i = 0; i < specs->modedb_len; i++) {
if (specs->modedb[i].flag & FB_MODE_IS_FIRST) {
modedb = &specs->modedb[i];
break;
}
}
} else {
/* otherwise, get first mode in database */
modedb = &specs->modedb[0];
}
if (modedb != NULL) {
info->var.bits_per_pixel = 8;
radeon_videomode_to_var(&info->var, modedb);
has_default_mode = 1;
}
}
if (1) {
struct fb_videomode mode;
/* Make sure that whatever mode got selected is actually in the
* modelist or the kernel may die
*/
fb_var_to_videomode(&mode, &info->var);
fb_add_videomode(&mode, &info->modelist);
}
}
/*
......
This diff is collapsed.
This diff is collapsed.
......@@ -814,7 +814,7 @@ static void radeon_get_pllinfo(struct radeonfb_info *rinfo, void __iomem *bios_s
if (radeon_read_OF(rinfo)) {
unsigned int tmp, Nx, M, ref_div, xclk;
tmp = INPLL(X_MPLL_REF_FB_DIV);
tmp = INPLL(M_SPLL_REF_FB_DIV);
ref_div = INPLL(PPLL_REF_DIV) & 0x3ff;
Nx = (tmp & 0xff00) >> 8;
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment