--- b/sys/dev/drm2/radeon/atombios_encoders.c +++ b/sys/dev/drm2/radeon/atombios_encoders.c @@ -134,8 +134,17 @@ atombios_set_backlight_level(struct radeon_encoder *radeon_encoder, u8 level) } } -#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) +#if !defined(CONFIG_BACKLIGHT_CLASS_DEVICE) && !defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) +struct backlight_device { + struct backlight_properties { + int brightness; + int max_brightness; + } props; + struct radeon_backlight_privdata pdata; +}; +#endif +#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) static u8 radeon_atom_bl_level(struct backlight_device *bd) { u8 level; @@ -268,13 +277,83 @@ static void radeon_atom_backlight_exit(struct radeon_encoder *radeon_encoder) #else /* !CONFIG_BACKLIGHT_CLASS_DEVICE */ +static int radeon_atom_backlight_get_brightness(struct backlight_device *bd) +{ + struct radeon_encoder *radeon_encoder = bd->pdata.encoder; + struct drm_device *dev = radeon_encoder->base.dev; + struct radeon_device *rdev = dev->dev_private; + + return radeon_atom_get_backlight_level_from_reg(rdev); +} + void radeon_atom_backlight_init(struct radeon_encoder *radeon_encoder, struct drm_connector *drm_connector) { + struct drm_device *dev = radeon_encoder->base.dev; + struct radeon_device *rdev = dev->dev_private; + struct backlight_device *bd; + struct radeon_encoder_atom_dig *dig; + u8 backlight_level; + + if (!radeon_encoder->enc_priv) { + return; + } + + if (!rdev->is_atom_bios) { + return; + } + + if (!(rdev->mode_info.firmware_flags & ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU)) { + return; + } + + bd = malloc(sizeof(struct backlight_device), DRM_MEM_DRIVER, M_WAITOK); + if (!bd) { + DRM_ERROR("Backlight memory allocation failed (%zu bytes)\n", sizeof(struct backlight_device)); + return; + } + + memset(&bd->props, 0, sizeof(bd->props)); + bd->props.max_brightness = RADEON_MAX_BL_LEVEL; + + bd->pdata.encoder = radeon_encoder; + + backlight_level = radeon_atom_get_backlight_level_from_reg(rdev); + + dig = radeon_encoder->enc_priv; + dig->bl_dev = bd; + + bd->props.brightness = radeon_atom_backlight_get_brightness(bd); + + DRM_INFO("radeon atom DIG backlight initialized\n"); + + return; } -static void radeon_atom_backlight_exit(struct radeon_encoder *encoder) +static void radeon_atom_backlight_exit(struct radeon_encoder *radeon_encoder) { + struct drm_device *dev = radeon_encoder->base.dev; + struct radeon_device *rdev = dev->dev_private; + struct backlight_device *bd = NULL; + struct radeon_encoder_atom_dig *dig; + + if (!radeon_encoder->enc_priv) + return; + + if (!rdev->is_atom_bios) + return; + + if (!(rdev->mode_info.firmware_flags & ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU)) + return; + + dig = radeon_encoder->enc_priv; + bd = dig->bl_dev; + dig->bl_dev = NULL; + + if (bd) { + free(bd, DRM_MEM_DRIVER); + DRM_INFO("radeon atom LVDS backlight unloaded\n"); + } } #endif --- b/sys/dev/drm2/radeon/radeon_legacy_encoders.c +++ b/sys/dev/drm2/radeon/radeon_legacy_encoders.c @@ -483,13 +483,115 @@ static void radeon_legacy_backlight_exit(struct radeon_encoder *radeon_encoder) #else /* !CONFIG_BACKLIGHT_CLASS_DEVICE */ -void radeon_legacy_backlight_init(struct radeon_encoder *encoder, +struct backlight_device { + struct backlight_properties { + int brightness; + int max_brightness; + } props; + struct radeon_backlight_privdata pdata; +}; + +static int radeon_legacy_backlight_get_brightness(struct backlight_device *bd) +{ + struct radeon_encoder *radeon_encoder = bd->pdata.encoder; + struct drm_device *dev = radeon_encoder->base.dev; + struct radeon_device *rdev = dev->dev_private; + uint8_t backlight_level; + + backlight_level = (RREG32(RADEON_LVDS_GEN_CNTL) >> + RADEON_LVDS_BL_MOD_LEVEL_SHIFT) & 0xff; + + return bd->pdata.negative ? RADEON_MAX_BL_LEVEL - backlight_level : backlight_level; +} + +void radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder, struct drm_connector *drm_connector) { + struct drm_device *dev = radeon_encoder->base.dev; + struct radeon_device *rdev = dev->dev_private; + struct backlight_device *bd; + uint8_t backlight_level; + + if (!radeon_encoder->enc_priv) + return; + +#ifdef CONFIG_PMAC_BACKLIGHT + if (!pmac_has_backlight_type("ati") && + !pmac_has_backlight_type("mnca")) + return; +#endif + + bd = malloc(sizeof(struct backlight_device), DRM_MEM_DRIVER, M_WAITOK); + if (!bd) { + DRM_ERROR("Memory allocation failed\n"); + return; + } + bd->pdata.encoder = radeon_encoder; + + backlight_level = (RREG32(RADEON_LVDS_GEN_CNTL) >> + RADEON_LVDS_BL_MOD_LEVEL_SHIFT) & 0xff; + + /* First, try to detect backlight level sense based on the assumption + * that firmware set it up at full brightness + */ + if (backlight_level == 0) + bd->pdata.negative = true; + else if (backlight_level == 0xff) + bd->pdata.negative = false; + else { + /* XXX hack... maybe some day we can figure out in what direction + * backlight should work on a given panel? + */ + bd->pdata.negative = (rdev->family != CHIP_RV200 && + rdev->family != CHIP_RV250 && + rdev->family != CHIP_RV280 && + rdev->family != CHIP_RV350); + +#ifdef CONFIG_PMAC_BACKLIGHT + bd->pdata.negative = (bd->pdata.negative || + of_machine_is_compatible("PowerBook4,3") || + of_machine_is_compatible("PowerBook6,3") || + of_machine_is_compatible("PowerBook6,5")); +#endif + } + + if (rdev->is_atom_bios) { + struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv; + lvds->bl_dev = bd; + } else { + struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv; + lvds->bl_dev = bd; + } + + bd->props.brightness = radeon_legacy_backlight_get_brightness(bd); + + DRM_INFO("radeon legacy LVDS backlight initialized\n"); + return; } -static void radeon_legacy_backlight_exit(struct radeon_encoder *encoder) +static void radeon_legacy_backlight_exit(struct radeon_encoder *radeon_encoder) { + struct drm_device *dev = radeon_encoder->base.dev; + struct radeon_device *rdev = dev->dev_private; + struct backlight_device *bd = NULL; + + if (!radeon_encoder->enc_priv) + return; + + if (rdev->is_atom_bios) { + struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv; + bd = lvds->bl_dev; + lvds->bl_dev = NULL; + } else { + struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv; + bd = lvds->bl_dev; + lvds->bl_dev = NULL; + } + + if (bd) { + free(bd, DRM_MEM_DRIVER); + DRM_INFO("radeon legacy LVDS backlight unloaded\n"); + } } #endif --- b/sys/dev/drm2/radeon/radeon_mode.h +++ b/sys/dev/drm2/radeon/radeon_mode.h @@ -259,15 +259,11 @@ struct radeon_mode_info { #define RADEON_MAX_BL_LEVEL 0xFF -#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) - struct radeon_backlight_privdata { struct radeon_encoder *encoder; uint8_t negative; }; -#endif - #define MAX_H_CODE_TIMING_LEN 32 #define MAX_V_CODE_TIMING_LEN 32