#define RADEON_VERSION "0.2.0"
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
+#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/time.h>
#include <asm/pci-bridge.h>
#include "../macmodes.h"
+#ifdef CONFIG_PMAC_BACKLIGHT
+#include <asm/backlight.h>
+#endif
+
#ifdef CONFIG_BOOTX_TEXT
#include <asm/btext.h>
#endif
#ifdef CONFIG_MTRR
static int nomtrr = 0;
#endif
-static int force_sleep;
-static int ignore_devlist;
/*
* prototypes
*/
+
+#ifdef CONFIG_PPC_OF
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+static int radeon_set_backlight_enable(int on, int level, void *data);
+static int radeon_set_backlight_level(int level, void *data);
+static struct backlight_controller radeon_backlight_controller = {
+ radeon_set_backlight_enable,
+ radeon_set_backlight_level
+};
+#endif /* CONFIG_PMAC_BACKLIGHT */
+
+#endif /* CONFIG_PPC_OF */
+
static void radeon_unmap_ROM(struct radeonfb_info *rinfo, struct pci_dev *dev)
{
if (!rinfo->bios_seg)
if (regno > 255)
- return -EINVAL;
+ return 1;
red >>= 8;
green >>= 8;
pindex = regno * 8;
if (rinfo->depth == 16 && regno > 63)
- return -EINVAL;
+ return 1;
if (rinfo->depth == 15 && regno > 31)
- return -EINVAL;
+ return 1;
/* For 565, the green component is mixed one order
* below
return 0;
}
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+
+/* TODO: Dbl check these tables, we don't go up to full ON backlight
+ * in these, possibly because we noticed MacOS doesn't, but I'd prefer
+ * having some more official numbers from ATI
+ */
+static int backlight_conv_m6[] = {
+ 0xff, 0xc0, 0xb5, 0xaa, 0x9f, 0x94, 0x89, 0x7e,
+ 0x73, 0x68, 0x5d, 0x52, 0x47, 0x3c, 0x31, 0x24
+};
+static int backlight_conv_m7[] = {
+ 0x00, 0x3f, 0x4a, 0x55, 0x60, 0x6b, 0x76, 0x81,
+ 0x8c, 0x97, 0xa2, 0xad, 0xb8, 0xc3, 0xce, 0xd9
+};
+
+#define BACKLIGHT_LVDS_OFF
+#undef BACKLIGHT_DAC_OFF
+
+/* We turn off the LCD completely instead of just dimming the backlight.
+ * This provides some greater power saving and the display is useless
+ * without backlight anyway.
+ */
+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;
+ int* conv_table;
+
+ if (rinfo->mon1_type != MT_LCD)
+ return 0;
+
+ /* Pardon me for that hack... maybe some day we can figure
+ * out in what direction backlight should work on a given
+ * panel ?
+ */
+ if ((rinfo->family == CHIP_FAMILY_RV200 ||
+ rinfo->family == CHIP_FAMILY_RV250 ||
+ rinfo->family == CHIP_FAMILY_RV280 ||
+ rinfo->family == CHIP_FAMILY_RV350) &&
+ !machine_is_compatible("PowerBook4,3") &&
+ !machine_is_compatible("PowerBook6,3") &&
+ !machine_is_compatible("PowerBook6,5"))
+ conv_table = backlight_conv_m7;
+ else
+ conv_table = backlight_conv_m6;
+
+ del_timer_sync(&rinfo->lvds_timer);
+ radeon_engine_idle();
+
+ lvds_gen_cntl = INREG(LVDS_GEN_CNTL);
+ 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 |= (rinfo->init_state.lvds_gen_cntl & LVDS_DIGON);
+ lvds_gen_cntl |= LVDS_BLON | LVDS_EN;
+ 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;
+ lvds_gen_cntl |= (rinfo->init_state.lvds_gen_cntl & LVDS_BL_MOD_EN);
+ 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);
+ 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;
+ } 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_BL_MOD_EN);
+ lvds_gen_cntl |= (conv_table[0] <<
+ LVDS_BL_MOD_LEVEL_SHIFT);
+ lvds_gen_cntl |= LVDS_DISPLAY_DIS;
+ OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
+ udelay(100);
+ lvds_gen_cntl &= ~(LVDS_ON | LVDS_EN);
+ OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
+ lvds_gen_cntl &= ~(LVDS_DIGON);
+ rinfo->pending_lvds_gen_cntl = lvds_gen_cntl;
+ mod_timer(&rinfo->lvds_timer,
+ jiffies + msecs_to_jiffies(rinfo->panel_info.pwr_delay));
+ 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);
+
+ return 0;
+}
+
+
+static int radeon_set_backlight_level(int level, void *data)
+{
+ return radeon_set_backlight_enable(1, level, data);
+}
+#endif /* CONFIG_PMAC_BACKLIGHT */
+
+
/*
* This reconfigure the card's internal memory map. In theory, we'd like
* to setup the card's memory at the same address as it's PCI bus address,
};
-static int __devinit radeonfb_pci_register (struct pci_dev *pdev,
+static int radeonfb_pci_register (struct pci_dev *pdev,
const struct pci_device_id *ent)
{
struct fb_info *info;
/* -2 is special: means ON on mobility chips and do not
* change on others
*/
- radeonfb_pm_init(rinfo, rinfo->is_mobility ? 1 : -1, ignore_devlist, force_sleep);
+ radeonfb_pm_init(rinfo, rinfo->is_mobility ? 1 : -1);
} else
- radeonfb_pm_init(rinfo, default_dynclk, ignore_devlist, force_sleep);
+ radeonfb_pm_init(rinfo, default_dynclk);
pci_set_drvdata(pdev, info);
MTRR_TYPE_WRCOMB, 1);
#endif
- radeonfb_bl_init(rinfo);
+#ifdef CONFIG_PMAC_BACKLIGHT
+ if (rinfo->mon1_type == MT_LCD) {
+ register_backlight_controller(&radeon_backlight_controller,
+ rinfo, "ati");
+ register_backlight_controller(&radeon_backlight_controller,
+ rinfo, "mnca");
+ }
+#endif
printk ("radeonfb (%s): %s\n", pci_name(rinfo->pdev), rinfo->name);
err_release_fb:
framebuffer_release(info);
err_disable:
+ pci_disable_device(pdev);
err_out:
return ret;
}
if (!rinfo)
return;
-
- radeonfb_bl_exit(rinfo);
+
radeonfb_pm_exit(rinfo);
if (rinfo->mon1_EDID)
#endif
fb_dealloc_cmap(&info->cmap);
framebuffer_release(info);
+ pci_disable_device(pdev);
}
force_measure_pll = 1;
} else if (!strncmp(this_opt, "ignore_edid", 11)) {
ignore_edid = 1;
-#if defined(CONFIG_PM) && defined(CONFIG_X86)
- } else if (!strncmp(this_opt, "force_sleep", 11)) {
- force_sleep = 1;
- } else if (!strncmp(this_opt, "ignore_devlist", 14)) {
- ignore_devlist = 1;
-#endif
} else
mode_option = this_opt;
}
MODULE_PARM_DESC(panel_yres, "int: set panel yres");
module_param(mode_option, charp, 0);
MODULE_PARM_DESC(mode_option, "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" ");
-#if defined(CONFIG_PM) && defined(CONFIG_X86)
-module_param(force_sleep, bool, 0);
-MODULE_PARM_DESC(force_sleep, "bool: force D2 sleep mode on all hardware");
-module_param(ignore_devlist, bool, 0);
-MODULE_PARM_DESC(ignore_devlist, "bool: ignore workarounds for bugs in specific laptops");
-#endif