mirror of https://gitee.com/openkylin/linux.git
gma500: continue abstracting platform specific code
Next obvious target - backlight support Signed-off-by: Alan Cox <alan@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
92367fe1bc
commit
6a7afe3acc
|
@ -4,8 +4,8 @@
|
|||
ccflags-y += -Iinclude/drm
|
||||
|
||||
psb_gfx-y += gem_glue.o \
|
||||
backlight.o \
|
||||
power.o \
|
||||
psb_bl.o \
|
||||
psb_drv.o \
|
||||
psb_gem.o \
|
||||
psb_fb.o \
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* GMA500 Backlight Interface
|
||||
*
|
||||
* Copyright (c) 2009-2011, Intel Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Authors: Eric Knopp
|
||||
*
|
||||
*/
|
||||
|
||||
#include "psb_drv.h"
|
||||
#include "psb_intel_reg.h"
|
||||
#include "psb_intel_drv.h"
|
||||
#include "psb_intel_bios.h"
|
||||
#include "psb_powermgmt.h"
|
||||
|
||||
int gma_backlight_init(struct drm_device *dev)
|
||||
{
|
||||
#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
|
||||
struct drm_psb_private *dev_priv = dev->dev_private;
|
||||
return dev_priv->ops->backlight_init(dev);
|
||||
#endif
|
||||
}
|
||||
|
||||
void gma_backlight_exit(struct drm_device *dev)
|
||||
{
|
||||
#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
|
||||
struct drm_psb_private *dev_priv = dev->dev_private;
|
||||
dev_priv->backlight_device->props.brightness = 0;
|
||||
backlight_update_status(dev_priv->backlight_device);
|
||||
if (dev_priv->backlight_device)
|
||||
backlight_device_unregister(dev_priv->backlight_device);
|
||||
#endif
|
||||
}
|
|
@ -17,6 +17,7 @@
|
|||
*
|
||||
**************************************************************************/
|
||||
|
||||
#include <linux/backlight.h>
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm.h>
|
||||
#include "psb_reg.h"
|
||||
|
@ -27,7 +28,93 @@
|
|||
#include "mdfld_dsi_output.h"
|
||||
|
||||
/*
|
||||
* Provide the Medfield specific chip logic and low level methods
|
||||
* Provide the Medfield specific backlight management
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
|
||||
|
||||
static int mdfld_brightness;
|
||||
struct backlight_device *mdfld_backlight_device;
|
||||
|
||||
static int mfld_set_brightness(struct backlight_device *bd)
|
||||
{
|
||||
struct drm_device *dev = bl_get_data(mdfld_backlight_device);
|
||||
struct drm_psb_private *dev_priv = dev->dev_private;
|
||||
int level = bd->props.brightness;
|
||||
|
||||
/* Percentage 1-100% being valid */
|
||||
if (level < 1)
|
||||
level = 1;
|
||||
|
||||
if (gma_power_begin(dev, 0)) {
|
||||
/* Calculate and set the brightness value */
|
||||
u32 adjusted_level;
|
||||
|
||||
/* Adjust the backlight level with the percent in
|
||||
* dev_priv->blc_adj2;
|
||||
*/
|
||||
adjusted_level = level * dev_priv->blc_adj2;
|
||||
adjusted_level = adjusted_level / 100;
|
||||
#if 0
|
||||
#ifndef CONFIG_MDFLD_DSI_DPU
|
||||
if(!(dev_priv->dsr_fb_update & MDFLD_DSR_MIPI_CONTROL) &&
|
||||
(dev_priv->dbi_panel_on || dev_priv->dbi_panel_on2)){
|
||||
mdfld_dsi_dbi_exit_dsr(dev,MDFLD_DSR_MIPI_CONTROL, 0, 0);
|
||||
dev_dbg(dev->dev, "Out of DSR before set brightness to %d.\n",adjusted_level);
|
||||
}
|
||||
#endif
|
||||
mdfld_dsi_brightness_control(dev, 0, adjusted_level);
|
||||
|
||||
if ((dev_priv->dbi_panel_on2) || (dev_priv->dpi_panel_on2))
|
||||
mdfld_dsi_brightness_control(dev, 2, adjusted_level);
|
||||
#endif
|
||||
gma_power_end(dev);
|
||||
}
|
||||
mdfld_brightness = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int psb_get_brightness(struct backlight_device *bd)
|
||||
{
|
||||
/* return locally cached var instead of HW read (due to DPST etc.) */
|
||||
/* FIXME: ideally return actual value in case firmware fiddled with
|
||||
it */
|
||||
return mdfld_brightness;
|
||||
}
|
||||
|
||||
static const struct backlight_ops mfld_ops = {
|
||||
.get_brightness = psb_get_brightness,
|
||||
.update_status = mfld_set_brightness,
|
||||
};
|
||||
|
||||
static int mdfld_backlight_init(struct drm_device *dev)
|
||||
{
|
||||
struct drm_psb_private *dev_priv = dev->dev_private;
|
||||
struct backlight_properties props;
|
||||
memset(&props, 0, sizeof(struct backlight_properties));
|
||||
props.max_brightness = 100;
|
||||
props.type = BACKLIGHT_PLATFORM;
|
||||
|
||||
mdfld_backlight_device = backlight_device_register("mfld-bl",
|
||||
NULL, (void *)dev, &mfld_ops, &props);
|
||||
|
||||
if (IS_ERR(mdfld_backlight_device))
|
||||
return PTR_ERR(mdfld_backlight_device);
|
||||
|
||||
dev_priv->blc_adj1 = 100;
|
||||
dev_priv->blc_adj2 = 100;
|
||||
mdfld_backlight_device->props.brightness = 100;
|
||||
mdfld_backlight_device->props.max_brightness = 100;
|
||||
backlight_update_status(mdfld_backlight_device);
|
||||
dev_priv->backlight_device = mdfld_backlight_device;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Provide the Medfield specific chip logic and low level methods for
|
||||
* power management.
|
||||
*/
|
||||
|
||||
static void mdfld_init_pm(struct drm_device *dev)
|
||||
|
@ -601,6 +688,11 @@ static int mdfld_power_up(struct drm_device *dev)
|
|||
|
||||
const struct psb_ops mdfld_chip_ops = {
|
||||
.output_init = mdfld_output_init,
|
||||
|
||||
#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
|
||||
.backlight_init = mdfld_backlight_init,
|
||||
#endif
|
||||
|
||||
.init_pm = mdfld_init_pm,
|
||||
.save_regs = mdfld_save_registers,
|
||||
.restore_regs = mdfld_restore_registers,
|
||||
|
|
|
@ -468,6 +468,7 @@ static int mdfld_dsi_connector_set_property(struct drm_connector * connector,
|
|||
{
|
||||
struct drm_encoder * encoder = connector->encoder;
|
||||
struct backlight_device * psb_bd;
|
||||
struct drm_psb_private * dev_priv = encoder->dev->dev_private;
|
||||
|
||||
if (!strcmp(property->name, "scaling mode") && encoder) {
|
||||
struct psb_intel_crtc * psb_crtc = to_psb_intel_crtc(encoder->crtc);
|
||||
|
@ -512,6 +513,7 @@ static int mdfld_dsi_connector_set_property(struct drm_connector * connector,
|
|||
&psb_crtc->saved_adjusted_mode);
|
||||
}
|
||||
}
|
||||
#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
|
||||
} else if (!strcmp(property->name, "backlight") && encoder) {
|
||||
dev_dbg(encoder->dev->dev, "backlight level = %d\n", (int)value);
|
||||
if (drm_connector_property_set_value(connector, property, value))
|
||||
|
@ -519,20 +521,21 @@ static int mdfld_dsi_connector_set_property(struct drm_connector * connector,
|
|||
else {
|
||||
dev_dbg(encoder->dev->dev,
|
||||
"set brightness to %d", (int)value);
|
||||
psb_bd = psb_get_backlight_device();
|
||||
if(psb_bd) {
|
||||
psb_bd = dev_priv->backlight_device;
|
||||
if (psb_bd) {
|
||||
psb_bd->props.brightness = value;
|
||||
psb_set_brightness(psb_bd);
|
||||
backlight_update_status(psb_bd);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
set_prop_done:
|
||||
return 0;
|
||||
set_prop_error:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void mdfld_dsi_connector_destroy(struct drm_connector * connector)
|
||||
static void mdfld_dsi_connector_destroy(struct drm_connector *connector)
|
||||
{
|
||||
struct psb_intel_output * psb_output = to_psb_intel_output(connector);
|
||||
struct mdfld_dsi_connector * dsi_connector = MDFLD_DSI_CONNECTOR(psb_output);
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
*
|
||||
**************************************************************************/
|
||||
|
||||
#include <linux/backlight.h>
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm.h>
|
||||
#include "psb_drm.h"
|
||||
|
@ -41,8 +42,139 @@ static int mrst_output_init(struct drm_device *dev)
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
/*
|
||||
* Provide the low level interfaces for the Moorestown backlight
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
|
||||
|
||||
#define MRST_BLC_MAX_PWM_REG_FREQ 0xFFFF
|
||||
#define BLC_PWM_PRECISION_FACTOR 100 /* 10000000 */
|
||||
#define BLC_PWM_FREQ_CALC_CONSTANT 32
|
||||
#define MHz 1000000
|
||||
#define BLC_ADJUSTMENT_MAX 100
|
||||
|
||||
static struct backlight_device *mrst_backlight_device;
|
||||
static int mrst_brightness;
|
||||
|
||||
static int mrst_set_brightness(struct backlight_device *bd)
|
||||
{
|
||||
struct drm_device *dev = bl_get_data(mrst_backlight_device);
|
||||
struct drm_psb_private *dev_priv = dev->dev_private;
|
||||
int level = bd->props.brightness;
|
||||
u32 blc_pwm_ctl;
|
||||
u32 max_pwm_blc;
|
||||
|
||||
/* Percentage 1-100% being valid */
|
||||
if (level < 1)
|
||||
level = 1;
|
||||
|
||||
if (gma_power_begin(dev, 0)) {
|
||||
/* Calculate and set the brightness value */
|
||||
max_pwm_blc = REG_READ(BLC_PWM_CTL) >> 16;
|
||||
blc_pwm_ctl = level * max_pwm_blc / 100;
|
||||
|
||||
/* Adjust the backlight level with the percent in
|
||||
* dev_priv->blc_adj1;
|
||||
*/
|
||||
blc_pwm_ctl = blc_pwm_ctl * dev_priv->blc_adj1;
|
||||
blc_pwm_ctl = blc_pwm_ctl / 100;
|
||||
|
||||
/* Adjust the backlight level with the percent in
|
||||
* dev_priv->blc_adj2;
|
||||
*/
|
||||
blc_pwm_ctl = blc_pwm_ctl * dev_priv->blc_adj2;
|
||||
blc_pwm_ctl = blc_pwm_ctl / 100;
|
||||
|
||||
/* force PWM bit on */
|
||||
REG_WRITE(BLC_PWM_CTL2, (0x80000000 | REG_READ(BLC_PWM_CTL2)));
|
||||
REG_WRITE(BLC_PWM_CTL, (max_pwm_blc << 16) | blc_pwm_ctl);
|
||||
gma_power_end(dev);
|
||||
}
|
||||
mrst_brightness = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mrst_get_brightness(struct backlight_device *bd)
|
||||
{
|
||||
/* return locally cached var instead of HW read (due to DPST etc.) */
|
||||
/* FIXME: ideally return actual value in case firmware fiddled with
|
||||
it */
|
||||
return mrst_brightness;
|
||||
}
|
||||
|
||||
static int device_backlight_init(struct drm_device *dev)
|
||||
{
|
||||
struct drm_psb_private *dev_priv = dev->dev_private;
|
||||
unsigned long core_clock;
|
||||
u16 bl_max_freq;
|
||||
uint32_t value;
|
||||
uint32_t blc_pwm_precision_factor;
|
||||
|
||||
dev_priv->blc_adj1 = BLC_ADJUSTMENT_MAX;
|
||||
dev_priv->blc_adj2 = BLC_ADJUSTMENT_MAX;
|
||||
bl_max_freq = 256;
|
||||
/* this needs to be set elsewhere */
|
||||
blc_pwm_precision_factor = BLC_PWM_PRECISION_FACTOR;
|
||||
|
||||
core_clock = dev_priv->core_freq;
|
||||
|
||||
value = (core_clock * MHz) / BLC_PWM_FREQ_CALC_CONSTANT;
|
||||
value *= blc_pwm_precision_factor;
|
||||
value /= bl_max_freq;
|
||||
value /= blc_pwm_precision_factor;
|
||||
|
||||
if (gma_power_begin(dev, false)) {
|
||||
if (value > (unsigned long long)MRST_BLC_MAX_PWM_REG_FREQ)
|
||||
return -ERANGE;
|
||||
else {
|
||||
REG_WRITE(BLC_PWM_CTL2,
|
||||
(0x80000000 | REG_READ(BLC_PWM_CTL2)));
|
||||
REG_WRITE(BLC_PWM_CTL, value | (value << 16));
|
||||
}
|
||||
gma_power_end(dev);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct backlight_ops mrst_ops = {
|
||||
.get_brightness = mrst_get_brightness,
|
||||
.update_status = mrst_set_brightness,
|
||||
};
|
||||
|
||||
int mrst_backlight_init(struct drm_device *dev)
|
||||
{
|
||||
struct drm_psb_private *dev_priv = dev->dev_private;
|
||||
int ret;
|
||||
struct backlight_properties props;
|
||||
|
||||
memset(&props, 0, sizeof(struct backlight_properties));
|
||||
props.max_brightness = 100;
|
||||
props.type = BACKLIGHT_PLATFORM;
|
||||
|
||||
mrst_backlight_device = backlight_device_register("mrst-bl",
|
||||
NULL, (void *)dev, &mrst_ops, &props);
|
||||
|
||||
if (IS_ERR(mrst_backlight_device))
|
||||
return PTR_ERR(mrst_backlight_device);
|
||||
|
||||
ret = device_backlight_init(dev);
|
||||
if (ret < 0) {
|
||||
backlight_device_unregister(mrst_backlight_device);
|
||||
return ret;
|
||||
}
|
||||
mrst_backlight_device->props.brightness = 100;
|
||||
mrst_backlight_device->props.max_brightness = 100;
|
||||
backlight_update_status(mrst_backlight_device);
|
||||
dev_priv->backlight_device = mrst_backlight_device;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Provide the Moorestown specific chip logic and low level methods
|
||||
* for power management
|
||||
*/
|
||||
|
||||
static void mrst_init_pm(struct drm_device *dev)
|
||||
|
@ -221,6 +353,11 @@ static int mrst_power_up(struct drm_device *dev)
|
|||
|
||||
const struct psb_ops mrst_chip_ops = {
|
||||
.output_init = mrst_output_init,
|
||||
|
||||
#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
|
||||
.backlight_init = mrst_backlight_init,
|
||||
#endif
|
||||
|
||||
.init_pm = mrst_init_pm,
|
||||
.save_regs = mrst_save_display_registers,
|
||||
.restore_regs = mrst_restore_display_registers,
|
||||
|
|
|
@ -1,283 +0,0 @@
|
|||
/*
|
||||
* GMA500 Backlight Interface
|
||||
*
|
||||
* Copyright (c) 2009-2011, Intel Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Authors: Eric Knopp
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/backlight.h>
|
||||
#include <linux/version.h>
|
||||
#include "psb_drv.h"
|
||||
#include "psb_intel_reg.h"
|
||||
#include "psb_intel_drv.h"
|
||||
#include "psb_intel_bios.h"
|
||||
#include "psb_powermgmt.h"
|
||||
|
||||
#define MRST_BLC_MAX_PWM_REG_FREQ 0xFFFF
|
||||
#define BLC_PWM_PRECISION_FACTOR 100 /* 10000000 */
|
||||
#define BLC_PWM_FREQ_CALC_CONSTANT 32
|
||||
#define MHz 1000000
|
||||
#define BRIGHTNESS_MIN_LEVEL 1
|
||||
#define BRIGHTNESS_MASK 0xFF
|
||||
#define BLC_POLARITY_NORMAL 0
|
||||
#define BLC_POLARITY_INVERSE 1
|
||||
#define BLC_ADJUSTMENT_MAX 100
|
||||
|
||||
#define PSB_BLC_PWM_PRECISION_FACTOR 10
|
||||
#define PSB_BLC_MAX_PWM_REG_FREQ 0xFFFE
|
||||
#define PSB_BLC_MIN_PWM_REG_FREQ 0x2
|
||||
|
||||
#define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE)
|
||||
#define PSB_BACKLIGHT_PWM_CTL_SHIFT (16)
|
||||
|
||||
static int psb_brightness;
|
||||
static struct backlight_device *psb_backlight_device;
|
||||
static u8 blc_brightnesscmd;
|
||||
static u8 blc_pol;
|
||||
static u8 blc_type;
|
||||
|
||||
int psb_set_brightness(struct backlight_device *bd)
|
||||
{
|
||||
struct drm_device *dev = bl_get_data(psb_backlight_device);
|
||||
int level = bd->props.brightness;
|
||||
|
||||
/* Percentage 1-100% being valid */
|
||||
if (level < 1)
|
||||
level = 1;
|
||||
|
||||
psb_intel_lvds_set_brightness(dev, level);
|
||||
psb_brightness = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mrst_set_brightness(struct backlight_device *bd)
|
||||
{
|
||||
struct drm_device *dev = bl_get_data(psb_backlight_device);
|
||||
struct drm_psb_private *dev_priv = dev->dev_private;
|
||||
int level = bd->props.brightness;
|
||||
u32 blc_pwm_ctl;
|
||||
u32 max_pwm_blc;
|
||||
|
||||
/* Percentage 1-100% being valid */
|
||||
if (level < 1)
|
||||
level = 1;
|
||||
|
||||
if (gma_power_begin(dev, 0)) {
|
||||
/* Calculate and set the brightness value */
|
||||
max_pwm_blc = REG_READ(BLC_PWM_CTL) >> 16;
|
||||
blc_pwm_ctl = level * max_pwm_blc / 100;
|
||||
|
||||
/* Adjust the backlight level with the percent in
|
||||
* dev_priv->blc_adj1;
|
||||
*/
|
||||
blc_pwm_ctl = blc_pwm_ctl * dev_priv->blc_adj1;
|
||||
blc_pwm_ctl = blc_pwm_ctl / 100;
|
||||
|
||||
/* Adjust the backlight level with the percent in
|
||||
* dev_priv->blc_adj2;
|
||||
*/
|
||||
blc_pwm_ctl = blc_pwm_ctl * dev_priv->blc_adj2;
|
||||
blc_pwm_ctl = blc_pwm_ctl / 100;
|
||||
|
||||
if (blc_pol == BLC_POLARITY_INVERSE)
|
||||
blc_pwm_ctl = max_pwm_blc - blc_pwm_ctl;
|
||||
/* force PWM bit on */
|
||||
REG_WRITE(BLC_PWM_CTL2, (0x80000000 | REG_READ(BLC_PWM_CTL2)));
|
||||
REG_WRITE(BLC_PWM_CTL, (max_pwm_blc << 16) | blc_pwm_ctl);
|
||||
gma_power_end(dev);
|
||||
}
|
||||
psb_brightness = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mfld_set_brightness(struct backlight_device *bd)
|
||||
{
|
||||
struct drm_device *dev = bl_get_data(psb_backlight_device);
|
||||
struct drm_psb_private *dev_priv = dev->dev_private;
|
||||
int level = bd->props.brightness;
|
||||
|
||||
DRM_DEBUG_DRIVER("backlight level set to %d\n", level);
|
||||
|
||||
/* Percentage 1-100% being valid */
|
||||
if (level < 1)
|
||||
level = 1;
|
||||
|
||||
if (gma_power_begin(dev, 0)) {
|
||||
/* Calculate and set the brightness value */
|
||||
u32 adjusted_level;
|
||||
|
||||
/* Adjust the backlight level with the percent in
|
||||
* dev_priv->blc_adj2;
|
||||
*/
|
||||
adjusted_level = level * dev_priv->blc_adj2;
|
||||
adjusted_level = adjusted_level / BLC_ADJUSTMENT_MAX;
|
||||
#if 0
|
||||
#ifndef CONFIG_MDFLD_DSI_DPU
|
||||
if(!(dev_priv->dsr_fb_update & MDFLD_DSR_MIPI_CONTROL) &&
|
||||
(dev_priv->dbi_panel_on || dev_priv->dbi_panel_on2)){
|
||||
mdfld_dsi_dbi_exit_dsr(dev,MDFLD_DSR_MIPI_CONTROL, 0, 0);
|
||||
dev_dbg(dev->dev, "Out of DSR before set brightness to %d.\n",adjusted_level);
|
||||
}
|
||||
#endif
|
||||
mdfld_dsi_brightness_control(dev, 0, adjusted_level);
|
||||
|
||||
if ((dev_priv->dbi_panel_on2) || (dev_priv->dpi_panel_on2))
|
||||
mdfld_dsi_brightness_control(dev, 2, adjusted_level);
|
||||
#endif
|
||||
gma_power_end(dev);
|
||||
}
|
||||
psb_brightness = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int psb_get_brightness(struct backlight_device *bd)
|
||||
{
|
||||
/* return locally cached var instead of HW read (due to DPST etc.) */
|
||||
/* FIXME: ideally return actual value in case firmware fiddled with
|
||||
it */
|
||||
return psb_brightness;
|
||||
}
|
||||
|
||||
static const struct backlight_ops psb_ops = {
|
||||
.get_brightness = psb_get_brightness,
|
||||
.update_status = psb_set_brightness,
|
||||
};
|
||||
|
||||
static const struct backlight_ops mrst_ops = {
|
||||
.get_brightness = psb_get_brightness,
|
||||
.update_status = mrst_set_brightness,
|
||||
};
|
||||
|
||||
static const struct backlight_ops mfld_ops = {
|
||||
.get_brightness = psb_get_brightness,
|
||||
.update_status = mfld_set_brightness,
|
||||
};
|
||||
|
||||
static int device_backlight_init(struct drm_device *dev)
|
||||
{
|
||||
struct drm_psb_private *dev_priv = dev->dev_private;
|
||||
unsigned long core_clock;
|
||||
/* u32 bl_max_freq; */
|
||||
/* unsigned long value; */
|
||||
u16 bl_max_freq;
|
||||
uint32_t value;
|
||||
uint32_t blc_pwm_precision_factor;
|
||||
|
||||
if (IS_MFLD(dev)) {
|
||||
dev_priv->blc_adj1 = BLC_ADJUSTMENT_MAX;
|
||||
dev_priv->blc_adj2 = BLC_ADJUSTMENT_MAX;
|
||||
return 0;
|
||||
} else if (IS_MRST(dev)) {
|
||||
dev_priv->blc_adj1 = BLC_ADJUSTMENT_MAX;
|
||||
dev_priv->blc_adj2 = BLC_ADJUSTMENT_MAX;
|
||||
bl_max_freq = 256;
|
||||
/* this needs to be set elsewhere */
|
||||
blc_pol = BLC_POLARITY_NORMAL;
|
||||
blc_pwm_precision_factor = BLC_PWM_PRECISION_FACTOR;
|
||||
} else {
|
||||
/* get bl_max_freq and pol from dev_priv*/
|
||||
if (!dev_priv->lvds_bl) {
|
||||
dev_err(dev->dev, "Has no valid LVDS backlight info\n");
|
||||
return 1;
|
||||
}
|
||||
bl_max_freq = dev_priv->lvds_bl->freq;
|
||||
blc_pol = dev_priv->lvds_bl->pol;
|
||||
blc_pwm_precision_factor = PSB_BLC_PWM_PRECISION_FACTOR;
|
||||
blc_brightnesscmd = dev_priv->lvds_bl->brightnesscmd;
|
||||
blc_type = dev_priv->lvds_bl->type;
|
||||
}
|
||||
|
||||
core_clock = dev_priv->core_freq;
|
||||
|
||||
value = (core_clock * MHz) / BLC_PWM_FREQ_CALC_CONSTANT;
|
||||
value *= blc_pwm_precision_factor;
|
||||
value /= bl_max_freq;
|
||||
value /= blc_pwm_precision_factor;
|
||||
|
||||
if (gma_power_begin(dev, false)) {
|
||||
if (IS_MRST(dev)) {
|
||||
if (value > (unsigned long long)MRST_BLC_MAX_PWM_REG_FREQ)
|
||||
return 2;
|
||||
else {
|
||||
REG_WRITE(BLC_PWM_CTL2,
|
||||
(0x80000000 | REG_READ(BLC_PWM_CTL2)));
|
||||
REG_WRITE(BLC_PWM_CTL, value | (value << 16));
|
||||
}
|
||||
} else {
|
||||
if (value > (unsigned long long)PSB_BLC_MAX_PWM_REG_FREQ ||
|
||||
value < (unsigned long long)PSB_BLC_MIN_PWM_REG_FREQ)
|
||||
return 2;
|
||||
else {
|
||||
value &= PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR;
|
||||
REG_WRITE(BLC_PWM_CTL,
|
||||
(value << PSB_BACKLIGHT_PWM_CTL_SHIFT) |
|
||||
(value));
|
||||
}
|
||||
}
|
||||
gma_power_end(dev);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int psb_backlight_init(struct drm_device *dev)
|
||||
{
|
||||
#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
|
||||
int ret = 0;
|
||||
|
||||
struct backlight_properties props;
|
||||
memset(&props, 0, sizeof(struct backlight_properties));
|
||||
props.max_brightness = 100;
|
||||
props.type = BACKLIGHT_PLATFORM;
|
||||
|
||||
if (IS_MFLD(dev))
|
||||
psb_backlight_device = backlight_device_register("mfld-bl",
|
||||
NULL, (void *)dev, &mfld_ops, &props);
|
||||
else if (IS_MRST(dev))
|
||||
psb_backlight_device = backlight_device_register("mrst-bl",
|
||||
NULL, (void *)dev, &psb_ops, &props);
|
||||
else
|
||||
psb_backlight_device = backlight_device_register("psb-bl",
|
||||
NULL, (void *)dev, &psb_ops, &props);
|
||||
|
||||
if (IS_ERR(psb_backlight_device))
|
||||
return PTR_ERR(psb_backlight_device);
|
||||
|
||||
ret = device_backlight_init(dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
psb_backlight_device->props.brightness = 100;
|
||||
psb_backlight_device->props.max_brightness = 100;
|
||||
backlight_update_status(psb_backlight_device);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
void psb_backlight_exit(void)
|
||||
{
|
||||
#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
|
||||
psb_backlight_device->props.brightness = 0;
|
||||
backlight_update_status(psb_backlight_device);
|
||||
backlight_device_unregister(psb_backlight_device);
|
||||
#endif
|
||||
}
|
||||
|
||||
struct backlight_device *psb_get_backlight_device(void)
|
||||
{
|
||||
return psb_backlight_device;
|
||||
}
|
|
@ -17,12 +17,15 @@
|
|||
*
|
||||
**************************************************************************/
|
||||
|
||||
#include <linux/backlight.h>
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm.h>
|
||||
#include "psb_drm.h"
|
||||
#include "psb_drv.h"
|
||||
#include "psb_reg.h"
|
||||
#include "psb_intel_reg.h"
|
||||
#include "psb_intel_bios.h"
|
||||
|
||||
|
||||
static int psb_output_init(struct drm_device *dev)
|
||||
{
|
||||
|
@ -32,8 +35,123 @@ static int psb_output_init(struct drm_device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
|
||||
|
||||
/*
|
||||
* Poulsbo Backlight Interfaces
|
||||
*/
|
||||
|
||||
#define BLC_PWM_PRECISION_FACTOR 100 /* 10000000 */
|
||||
#define BLC_PWM_FREQ_CALC_CONSTANT 32
|
||||
#define MHz 1000000
|
||||
|
||||
#define PSB_BLC_PWM_PRECISION_FACTOR 10
|
||||
#define PSB_BLC_MAX_PWM_REG_FREQ 0xFFFE
|
||||
#define PSB_BLC_MIN_PWM_REG_FREQ 0x2
|
||||
|
||||
#define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE)
|
||||
#define PSB_BACKLIGHT_PWM_CTL_SHIFT (16)
|
||||
|
||||
static int psb_brightness;
|
||||
static struct backlight_device *psb_backlight_device;
|
||||
|
||||
static int psb_get_brightness(struct backlight_device *bd)
|
||||
{
|
||||
/* return locally cached var instead of HW read (due to DPST etc.) */
|
||||
/* FIXME: ideally return actual value in case firmware fiddled with
|
||||
it */
|
||||
return psb_brightness;
|
||||
}
|
||||
|
||||
|
||||
static int psb_backlight_setup(struct drm_device *dev)
|
||||
{
|
||||
struct drm_psb_private *dev_priv = dev->dev_private;
|
||||
unsigned long core_clock;
|
||||
/* u32 bl_max_freq; */
|
||||
/* unsigned long value; */
|
||||
u16 bl_max_freq;
|
||||
uint32_t value;
|
||||
uint32_t blc_pwm_precision_factor;
|
||||
|
||||
/* get bl_max_freq and pol from dev_priv*/
|
||||
if (!dev_priv->lvds_bl) {
|
||||
dev_err(dev->dev, "Has no valid LVDS backlight info\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
bl_max_freq = dev_priv->lvds_bl->freq;
|
||||
blc_pwm_precision_factor = PSB_BLC_PWM_PRECISION_FACTOR;
|
||||
|
||||
core_clock = dev_priv->core_freq;
|
||||
|
||||
value = (core_clock * MHz) / BLC_PWM_FREQ_CALC_CONSTANT;
|
||||
value *= blc_pwm_precision_factor;
|
||||
value /= bl_max_freq;
|
||||
value /= blc_pwm_precision_factor;
|
||||
|
||||
if (value > (unsigned long long)PSB_BLC_MAX_PWM_REG_FREQ ||
|
||||
value < (unsigned long long)PSB_BLC_MIN_PWM_REG_FREQ)
|
||||
return -ERANGE;
|
||||
else {
|
||||
value &= PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR;
|
||||
REG_WRITE(BLC_PWM_CTL,
|
||||
(value << PSB_BACKLIGHT_PWM_CTL_SHIFT) | (value));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int psb_set_brightness(struct backlight_device *bd)
|
||||
{
|
||||
struct drm_device *dev = bl_get_data(psb_backlight_device);
|
||||
int level = bd->props.brightness;
|
||||
|
||||
/* Percentage 1-100% being valid */
|
||||
if (level < 1)
|
||||
level = 1;
|
||||
|
||||
psb_intel_lvds_set_brightness(dev, level);
|
||||
psb_brightness = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct backlight_ops psb_ops = {
|
||||
.get_brightness = psb_get_brightness,
|
||||
.update_status = psb_set_brightness,
|
||||
};
|
||||
|
||||
static int psb_backlight_init(struct drm_device *dev)
|
||||
{
|
||||
struct drm_psb_private *dev_priv = dev->dev_private;
|
||||
int ret;
|
||||
struct backlight_properties props;
|
||||
|
||||
memset(&props, 0, sizeof(struct backlight_properties));
|
||||
props.max_brightness = 100;
|
||||
props.type = BACKLIGHT_PLATFORM;
|
||||
|
||||
psb_backlight_device = backlight_device_register("psb-bl",
|
||||
NULL, (void *)dev, &psb_ops, &props);
|
||||
if (IS_ERR(psb_backlight_device))
|
||||
return PTR_ERR(psb_backlight_device);
|
||||
|
||||
ret = psb_backlight_setup(dev);
|
||||
if (ret < 0) {
|
||||
backlight_device_unregister(psb_backlight_device);
|
||||
psb_backlight_device = NULL;
|
||||
return ret;
|
||||
}
|
||||
psb_backlight_device->props.brightness = 100;
|
||||
psb_backlight_device->props.max_brightness = 100;
|
||||
backlight_update_status(psb_backlight_device);
|
||||
dev_priv->backlight_device = psb_backlight_device;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Provide the Poulsbo specific chip logic and low level methods
|
||||
* for power management
|
||||
*/
|
||||
|
||||
static void psb_init_pm(struct drm_device *dev)
|
||||
|
@ -165,10 +283,15 @@ int psb_power_up(struct drm_device *dev)
|
|||
|
||||
const struct psb_ops psb_chip_ops = {
|
||||
.output_init = psb_output_init,
|
||||
|
||||
#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
|
||||
.backlight_init = psb_backlight_init,
|
||||
#endif
|
||||
|
||||
.init_pm = psb_init_pm,
|
||||
.save_regs = psb_save_display_registers,
|
||||
.restore_regs = psb_restore_display_registers,
|
||||
.power_down = psb_power_down,
|
||||
.power_up = psb_power_up,
|
||||
.power_up = psb_power_up,
|
||||
};
|
||||
|
||||
|
|
|
@ -261,7 +261,7 @@ static int psb_driver_unload(struct drm_device *dev)
|
|||
|
||||
/* Kill vblank etc here */
|
||||
|
||||
psb_backlight_exit(); /*writes minimum value to backlight HW reg */
|
||||
gma_backlight_exit(dev);
|
||||
|
||||
if (drm_psb_no_fb == 0)
|
||||
psb_modeset_cleanup(dev);
|
||||
|
@ -455,7 +455,7 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
|
|||
|
||||
switch (psb_intel_output->type) {
|
||||
case INTEL_OUTPUT_LVDS:
|
||||
ret = psb_backlight_init(dev);
|
||||
ret = gma_backlight_init(dev);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -554,12 +554,14 @@ static int psb_dpst_bl_ioctl(struct drm_device *dev, void *data,
|
|||
{
|
||||
struct drm_psb_private *dev_priv = psb_priv(dev);
|
||||
uint32_t *arg = data;
|
||||
struct backlight_device bd;
|
||||
struct backlight_device *bd = dev_priv->backlight_device;
|
||||
dev_priv->blc_adj2 = *arg;
|
||||
|
||||
#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
|
||||
bd.props.brightness = psb_get_brightness(&bd);
|
||||
psb_set_brightness(&bd);
|
||||
if (bd) {
|
||||
bd->props.brightness = bd->ops->get_brightness(bd);
|
||||
backlight_update_status(bd);
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
@ -569,12 +571,14 @@ static int psb_adb_ioctl(struct drm_device *dev, void *data,
|
|||
{
|
||||
struct drm_psb_private *dev_priv = psb_priv(dev);
|
||||
uint32_t *arg = data;
|
||||
struct backlight_device bd;
|
||||
struct backlight_device *bd = dev_priv->backlight_device;
|
||||
dev_priv->blc_adj1 = *arg;
|
||||
|
||||
#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
|
||||
bd.props.brightness = psb_get_brightness(&bd);
|
||||
psb_set_brightness(&bd);
|
||||
if (bd) {
|
||||
bd->props.brightness = bd->ops->get_brightness(bd);
|
||||
backlight_update_status(bd);
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -588,12 +588,12 @@ struct drm_psb_private {
|
|||
* Used for modifying backlight from
|
||||
* xrandr -- consider removing and using HAL instead
|
||||
*/
|
||||
struct backlight_device *backlight_device;
|
||||
struct drm_property *backlight_property;
|
||||
uint32_t blc_adj1;
|
||||
uint32_t blc_adj2;
|
||||
|
||||
void *fbdev;
|
||||
|
||||
/* DPST state */
|
||||
uint32_t dsr_idle_count;
|
||||
bool is_in_idle;
|
||||
|
@ -625,6 +625,10 @@ struct psb_ops {
|
|||
int (*restore_regs)(struct drm_device *dev);
|
||||
int (*power_up)(struct drm_device *dev);
|
||||
int (*power_down)(struct drm_device *dev);
|
||||
#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
|
||||
/* Backlight */
|
||||
int (*backlight_init)(struct drm_device *dev);
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
@ -744,12 +748,9 @@ extern void psb_modeset_init(struct drm_device *dev);
|
|||
extern void psb_modeset_cleanup(struct drm_device *dev);
|
||||
extern int psb_fbdev_init(struct drm_device *dev);
|
||||
|
||||
/* psb_bl.c */
|
||||
int psb_backlight_init(struct drm_device *dev);
|
||||
void psb_backlight_exit(void);
|
||||
int psb_set_brightness(struct backlight_device *bd);
|
||||
int psb_get_brightness(struct backlight_device *bd);
|
||||
struct backlight_device *psb_get_backlight_device(void);
|
||||
/* backlight.c */
|
||||
int gma_backlight_init(struct drm_device *dev);
|
||||
void gma_backlight_exit(struct drm_device *dev);
|
||||
|
||||
/* mrst_crtc.c */
|
||||
extern const struct drm_crtc_helper_funcs mrst_helper_funcs;
|
||||
|
|
|
@ -575,11 +575,12 @@ int psb_intel_lvds_set_property(struct drm_connector *connector,
|
|||
struct drm_property *property,
|
||||
uint64_t value)
|
||||
{
|
||||
struct drm_encoder *pEncoder = connector->encoder;
|
||||
struct drm_encoder *encoder = connector->encoder;
|
||||
struct drm_psb_private *dev_priv = encoder->dev->dev_private;
|
||||
|
||||
if (!strcmp(property->name, "scaling mode") && pEncoder) {
|
||||
if (!strcmp(property->name, "scaling mode") && encoder) {
|
||||
struct psb_intel_crtc *pPsbCrtc =
|
||||
to_psb_intel_crtc(pEncoder->crtc);
|
||||
to_psb_intel_crtc(encoder->crtc);
|
||||
uint64_t curValue;
|
||||
|
||||
if (!pPsbCrtc)
|
||||
|
@ -611,29 +612,31 @@ int psb_intel_lvds_set_property(struct drm_connector *connector,
|
|||
|
||||
if (pPsbCrtc->saved_mode.hdisplay != 0 &&
|
||||
pPsbCrtc->saved_mode.vdisplay != 0) {
|
||||
if (!drm_crtc_helper_set_mode(pEncoder->crtc,
|
||||
if (!drm_crtc_helper_set_mode(encoder->crtc,
|
||||
&pPsbCrtc->saved_mode,
|
||||
pEncoder->crtc->x,
|
||||
pEncoder->crtc->y,
|
||||
pEncoder->crtc->fb))
|
||||
encoder->crtc->x,
|
||||
encoder->crtc->y,
|
||||
encoder->crtc->fb))
|
||||
goto set_prop_error;
|
||||
}
|
||||
} else if (!strcmp(property->name, "backlight") && pEncoder) {
|
||||
} else if (!strcmp(property->name, "backlight") && encoder) {
|
||||
if (drm_connector_property_set_value(connector,
|
||||
property,
|
||||
value))
|
||||
goto set_prop_error;
|
||||
else {
|
||||
#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
|
||||
struct backlight_device bd;
|
||||
bd.props.brightness = value;
|
||||
psb_set_brightness(&bd);
|
||||
struct backlight_device *bd = dev_priv->backlight_device;
|
||||
if (bd) {
|
||||
bd->props.brightness = value;
|
||||
backlight_update_status(bd);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
} else if (!strcmp(property->name, "DPMS") && pEncoder) {
|
||||
} else if (!strcmp(property->name, "DPMS") && encoder) {
|
||||
struct drm_encoder_helper_funcs *pEncHFuncs
|
||||
= pEncoder->helper_private;
|
||||
pEncHFuncs->dpms(pEncoder, value);
|
||||
= encoder->helper_private;
|
||||
pEncHFuncs->dpms(encoder, value);
|
||||
}
|
||||
|
||||
set_prop_done:
|
||||
|
|
Loading…
Reference in New Issue