Attached patch allows the backlight to be manipulated under gnome on apple powerpc based <NV30 machines. It works fine on my powerbook, and should also work for older NV17/NV18 machines. Questions/Comments/critisism welcome (plz cc me).
Note that older powerpc specific tools (pbbuttonsd) have some problems with this implementation (because the device is not yet there at the start time of the daemon, and the code makes incorrect assumptions about the max brightness values). However, IMHO these things can and should be addressed in the daemon. The patch also addresses the swab32 problem in master that nobody cared about. Danny
diff --git a/linux-core/nouveau_backlight.c b/linux-core/nouveau_backlight.c index 51c747a..b7bfcb1 100644 --- a/linux-core/nouveau_backlight.c +++ b/linux-core/nouveau_backlight.c @@ -27,6 +27,11 @@ * Authors: * Matthew Garrett <[email protected]> * + * PowerPC specific stuff: + * Danny Tholen <[email protected]> + * (mainly based on info from nvidiafb) + * + * * Register locations derived from NVClock by Roderick Colenbrander */ @@ -39,6 +44,54 @@ #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE +#ifdef CONFIG_PMAC_BACKLIGHT +#include <asm/backlight.h> +#endif + +static int ppc_get_intensity(struct backlight_device *bd) +{ + struct drm_device *dev = bl_get_data(bd); + struct drm_nouveau_private *dev_priv = dev->dev_private; + int tmp_pmc = NV_READ(NV_PBUS_DEBUG_DUALHEAD_CTL); + int max_brightness = tmp_pmc & 0x0000FFFF; + + tmp_pmc = (tmp_pmc & ~(1 << 31)) >> 16; + + return (tmp_pmc - (max_brightness >> 2)); + +} + +static int ppc_set_intensity(struct backlight_device *bd) +{ + struct drm_device *dev = bl_get_data(bd); + struct drm_nouveau_private *dev_priv = dev->dev_private; + + int val = bd->props.brightness - 1; + int tmp_pmc = NV_READ(NV_PBUS_DEBUG_DUALHEAD_CTL) & 0x0000FFFF; + int tmp_pcrt = NV_READ(NV_CRTC_GPIO_EXT) & 0xFFFFFFFC; + + if (val > 0) { + tmp_pcrt |= 0x1; + tmp_pmc |= (val + (tmp_pmc >> 2)) << 16; + tmp_pmc |= (1 << 31); /* backlight bit on */ + } else + bd->props.brightness = val = 0; + + NV_WRITE(NV_CRTC_GPIO_EXT, tmp_pcrt); + NV_WRITE(NV_PBUS_DEBUG_DUALHEAD_CTL, tmp_pmc); + + return 0; +} + +static struct backlight_ops ppc_bl_ops = { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)) + .options = BL_CORE_SUSPENDRESUME, +#endif + .get_brightness = ppc_get_intensity, + .update_status = ppc_set_intensity, +}; + + static int nv40_get_intensity(struct backlight_device *bd) { struct drm_device *dev = bl_get_data(bd); @@ -96,6 +149,46 @@ static struct backlight_ops nv50_bl_ops = { .update_status = nv50_set_intensity, }; + +static int nouveau_ppc_backlight_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct backlight_device *bd; + int max_brightness = 0; + + if (!machine_is(powermac) || + !pmac_has_backlight_type("mnca")) + return -ENODEV; + + /* "nv_bl0", some old powerpc userland tools rely on this */ + bd = backlight_device_register("nv_bl0", &dev->pdev->dev, dev, + &ppc_bl_ops); + if (IS_ERR(bd)) + return PTR_ERR(bd); + + dev_priv->backlight = bd; + + /* the least significant 15 bits of NV_PBUS_DEBUG_DUALHEAD_CTL + * set the maximum backlight level, OF sets it to 0x535 on my + * powerbook. however, posting the card sets this to 0x7FFF. + * Below 25% the blacklight turns off. + * + * NOTE: pbbuttonsd limits brightness values < 255, and thus + * will not work well with this. + */ + + /*FIXME: do we want to fix this reg to 0x535 for consistency?*/ + max_brightness = NV_READ(NV_PBUS_DEBUG_DUALHEAD_CTL) + & 0x0000FFFF; + bd->props.max_brightness = max_brightness - + (max_brightness >> 2); + bd->props.power = FB_BLANK_UNBLANK; + bd->props.brightness = ppc_get_intensity(bd); + backlight_update_status(bd); + + return 0; +} + static int nouveau_nv40_backlight_init(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; @@ -142,6 +235,11 @@ int nouveau_backlight_init(struct drm_device *dev) struct drm_nouveau_private *dev_priv = dev->dev_private; switch (dev_priv->card_type) { +#ifdef CONFIG_PMAC_BACKLIGHT + case NV_17: + case NV_30: + return nouveau_ppc_backlight_init(dev); +#endif case NV_40: case NV_44: return nouveau_nv40_backlight_init(dev); diff --git a/shared-core/nouveau_reg.h b/shared-core/nouveau_reg.h index 060abe0..3949268 100644 --- a/shared-core/nouveau_reg.h +++ b/shared-core/nouveau_reg.h @@ -99,6 +99,9 @@ * the card will hang early on in the X init process. */ # define NV_PMC_ENABLE_UNK13 (1<<13) +#define NV_PBUS_DEBUG_DUALHEAD_CTL 0x000010F0 +#define NV_CRTC_GPIO_EXT 0x0060081C +#define NV_RAMDAC_FP_CONTROL 0x00680848 #define NV40_PMC_BACKLIGHT 0x000015f0 # define NV40_PMC_BACKLIGHT_MASK 0x001f0000 #define NV40_PMC_1700 0x00001700 diff --git a/shared-core/nouveau_state.c b/shared-core/nouveau_state.c index c9f4329..b2ad747 100644 --- a/shared-core/nouveau_state.c +++ b/shared-core/nouveau_state.c @@ -496,7 +496,7 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) reg1 = readl(regs+NV03_PMC_BOOT_1); #if defined(__powerpc__) if (reg1) - reg0=___swab32(reg0); + reg0=__swab32(reg0); #endif /* We're dealing with >=NV10 */
_______________________________________________ Nouveau mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/nouveau
