Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 329528
b: refs/heads/master
c: f372873
h: refs/heads/master
v: v3
  • Loading branch information
Alex Deucher committed Sep 20, 2012
1 parent 8f9c050 commit 8d3e161
Show file tree
Hide file tree
Showing 4 changed files with 249 additions and 17 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 910308802c528f8afe864b694d5456fedd0bb18f
refs/heads/master: f3728734ba78310525bf4a361c7787c7c6fa5d40
231 changes: 231 additions & 0 deletions trunk/drivers/gpu/drm/radeon/atombios_encoders.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,238 @@
#include "radeon_drm.h"
#include "radeon.h"
#include "atom.h"
#include <linux/backlight.h>

extern int atom_debug;

#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)

static u8
radeon_atom_get_backlight_level_from_reg(struct radeon_device *rdev)
{
u8 backlight_level;
u32 bios_2_scratch;

if (rdev->family >= CHIP_R600)
bios_2_scratch = RREG32(R600_BIOS_2_SCRATCH);
else
bios_2_scratch = RREG32(RADEON_BIOS_2_SCRATCH);

backlight_level = ((bios_2_scratch & ATOM_S2_CURRENT_BL_LEVEL_MASK) >>
ATOM_S2_CURRENT_BL_LEVEL_SHIFT);

return backlight_level;
}

static void
radeon_atom_set_backlight_level_to_reg(struct radeon_device *rdev,
u8 backlight_level)
{
u32 bios_2_scratch;

if (rdev->family >= CHIP_R600)
bios_2_scratch = RREG32(R600_BIOS_2_SCRATCH);
else
bios_2_scratch = RREG32(RADEON_BIOS_2_SCRATCH);

bios_2_scratch &= ~ATOM_S2_CURRENT_BL_LEVEL_MASK;
bios_2_scratch |= ((backlight_level << ATOM_S2_CURRENT_BL_LEVEL_SHIFT) &
ATOM_S2_CURRENT_BL_LEVEL_MASK);

if (rdev->family >= CHIP_R600)
WREG32(R600_BIOS_2_SCRATCH, bios_2_scratch);
else
WREG32(RADEON_BIOS_2_SCRATCH, bios_2_scratch);
}

static void
atombios_set_panel_brightness(struct radeon_encoder *radeon_encoder)
{
struct drm_encoder *encoder = &radeon_encoder->base;
struct drm_device *dev = radeon_encoder->base.dev;
struct radeon_device *rdev = dev->dev_private;
struct radeon_encoder_atom_dig *dig;
DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args;
int index;

if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
dig = radeon_encoder->enc_priv;
radeon_atom_set_backlight_level_to_reg(rdev, dig->backlight_level);

switch (radeon_encoder->encoder_id) {
case ENCODER_OBJECT_ID_INTERNAL_LVDS:
case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
if (dig->backlight_level == 0) {
args.ucAction = ATOM_LCD_BLOFF;
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
} else {
args.ucAction = ATOM_LCD_BL_BRIGHTNESS_CONTROL;
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
args.ucAction = ATOM_LCD_BLON;
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
}
break;
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
if (dig->backlight_level == 0)
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLOFF, 0, 0);
else {
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_BL_BRIGHTNESS_CONTROL, 0, 0);
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLON, 0, 0);
}
break;
default:
break;
}
}
}

static u8 radeon_atom_bl_level(struct backlight_device *bd)
{
u8 level;

/* Convert brightness to hardware level */
if (bd->props.brightness < 0)
level = 0;
else if (bd->props.brightness > RADEON_MAX_BL_LEVEL)
level = RADEON_MAX_BL_LEVEL;
else
level = bd->props.brightness;

return level;
}

static int radeon_atom_backlight_update_status(struct backlight_device *bd)
{
struct radeon_backlight_privdata *pdata = bl_get_data(bd);
struct radeon_encoder *radeon_encoder = pdata->encoder;

if (radeon_encoder->enc_priv) {
struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
dig->backlight_level = radeon_atom_bl_level(bd);
atombios_set_panel_brightness(radeon_encoder);
}

return 0;
}

static int radeon_atom_backlight_get_brightness(struct backlight_device *bd)
{
struct radeon_backlight_privdata *pdata = bl_get_data(bd);
struct radeon_encoder *radeon_encoder = 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);
}

static const struct backlight_ops radeon_atom_backlight_ops = {
.get_brightness = radeon_atom_backlight_get_brightness,
.update_status = radeon_atom_backlight_update_status,
};

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 backlight_properties props;
struct radeon_backlight_privdata *pdata;
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;

pdata = kmalloc(sizeof(struct radeon_backlight_privdata), GFP_KERNEL);
if (!pdata) {
DRM_ERROR("Memory allocation failed\n");
goto error;
}

memset(&props, 0, sizeof(props));
props.max_brightness = RADEON_MAX_BL_LEVEL;
props.type = BACKLIGHT_RAW;
bd = backlight_device_register("radeon_bl", &drm_connector->kdev,
pdata, &radeon_atom_backlight_ops, &props);
if (IS_ERR(bd)) {
DRM_ERROR("Backlight registration failed\n");
goto error;
}

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);
bd->props.power = FB_BLANK_UNBLANK;
backlight_update_status(bd);

DRM_INFO("radeon atom DIG backlight initialized\n");

return;

error:
kfree(pdata);
return;
}

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) {
struct radeon_legacy_backlight_privdata *pdata;

pdata = bl_get_data(bd);
backlight_device_unregister(bd);
kfree(pdata);

DRM_INFO("radeon atom LVDS backlight unloaded\n");
}
}

#else /* !CONFIG_BACKLIGHT_CLASS_DEVICE */

void radeon_atom_backlight_init(struct radeon_encoder *encoder)
{
}

static void radeon_atom_backlight_exit(struct radeon_encoder *encoder)
{
}

#endif

/* evil but including atombios.h is much worse */
bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index,
struct drm_display_mode *mode);
Expand Down Expand Up @@ -2286,6 +2515,8 @@ static const struct drm_encoder_helper_funcs radeon_atom_dac_helper_funcs = {
void radeon_enc_destroy(struct drm_encoder *encoder)
{
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
radeon_atom_backlight_exit(radeon_encoder);
kfree(radeon_encoder->enc_priv);
drm_encoder_cleanup(encoder);
kfree(radeon_encoder);
Expand Down
15 changes: 0 additions & 15 deletions trunk/drivers/gpu/drm/radeon/radeon_connectors.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,6 @@ radeon_atombios_connected_scratch_regs(struct drm_connector *connector,
struct drm_encoder *encoder,
bool connected);

extern void
radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder,
struct drm_connector *drm_connector);

void radeon_connector_hotplug(struct drm_connector *connector)
{
struct drm_device *dev = connector->dev;
Expand Down Expand Up @@ -2008,15 +2004,4 @@ radeon_add_legacy_connector(struct drm_device *dev,
connector->polled = DRM_CONNECTOR_POLL_HPD;
connector->display_info.subpixel_order = subpixel_order;
drm_sysfs_connector_add(connector);
if (connector_type == DRM_MODE_CONNECTOR_LVDS) {
struct drm_encoder *drm_encoder;

list_for_each_entry(drm_encoder, &dev->mode_config.encoder_list, head) {
struct radeon_encoder *radeon_encoder;

radeon_encoder = to_radeon_encoder(drm_encoder);
if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_LVDS)
radeon_legacy_backlight_init(radeon_encoder, connector);
}
}
}
18 changes: 17 additions & 1 deletion trunk/drivers/gpu/drm/radeon/radeon_encoders.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,14 @@
#include "radeon.h"
#include "atom.h"

extern void
radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder,
struct drm_connector *drm_connector);
extern void
radeon_atom_backlight_init(struct radeon_encoder *radeon_encoder,
struct drm_connector *drm_connector);


static uint32_t radeon_encoder_clones(struct drm_encoder *encoder)
{
struct drm_device *dev = encoder->dev;
Expand Down Expand Up @@ -153,6 +161,7 @@ radeon_get_encoder_enum(struct drm_device *dev, uint32_t supported_device, uint8
void
radeon_link_encoder_connector(struct drm_device *dev)
{
struct radeon_device *rdev = dev->dev_private;
struct drm_connector *connector;
struct radeon_connector *radeon_connector;
struct drm_encoder *encoder;
Expand All @@ -163,8 +172,15 @@ radeon_link_encoder_connector(struct drm_device *dev)
radeon_connector = to_radeon_connector(connector);
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
radeon_encoder = to_radeon_encoder(encoder);
if (radeon_encoder->devices & radeon_connector->devices)
if (radeon_encoder->devices & radeon_connector->devices) {
drm_mode_connector_attach_encoder(connector, encoder);
if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
if (rdev->is_atom_bios)
radeon_atom_backlight_init(radeon_encoder, connector);
else
radeon_legacy_backlight_init(radeon_encoder, connector);
}
}
}
}
}
Expand Down

0 comments on commit 8d3e161

Please sign in to comment.