[PATCH 25/29] gma500: continue abstracting platform specific code

From: Alan Cox
Date: Thu Jun 16 2011 - 12:53:59 EST


From: Alan Cox <alan@xxxxxxxxxxxxxxx>

Next obvious target - backlight support

Signed-off-by: Alan Cox <alan@xxxxxxxxxxxxxxx>
---

drivers/staging/gma500/Makefile | 2
drivers/staging/gma500/backlight.c | 46 +++++
drivers/staging/gma500/mdfld_device.c | 94 ++++++++++
drivers/staging/gma500/mdfld_dsi_output.c | 11 +
drivers/staging/gma500/mrst_device.c | 137 ++++++++++++++
drivers/staging/gma500/psb_bl.c | 283 -----------------------------
drivers/staging/gma500/psb_device.c | 125 +++++++++++++
drivers/staging/gma500/psb_drv.c | 20 +-
drivers/staging/gma500/psb_drv.h | 15 +-
drivers/staging/gma500/psb_intel_lvds.c | 31 ++-
10 files changed, 445 insertions(+), 319 deletions(-)
create mode 100644 drivers/staging/gma500/backlight.c
delete mode 100644 drivers/staging/gma500/psb_bl.c

diff --git a/drivers/staging/gma500/Makefile b/drivers/staging/gma500/Makefile
index e93cbe3..dc02b2f 100644
--- a/drivers/staging/gma500/Makefile
+++ b/drivers/staging/gma500/Makefile
@@ -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 \
diff --git a/drivers/staging/gma500/backlight.c b/drivers/staging/gma500/backlight.c
new file mode 100644
index 0000000..47681c9
--- /dev/null
+++ b/drivers/staging/gma500/backlight.c
@@ -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
+}
diff --git a/drivers/staging/gma500/mdfld_device.c b/drivers/staging/gma500/mdfld_device.c
index 7caa7cd..e86e476 100644
--- a/drivers/staging/gma500/mdfld_device.c
+++ b/drivers/staging/gma500/mdfld_device.c
@@ -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,
diff --git a/drivers/staging/gma500/mdfld_dsi_output.c b/drivers/staging/gma500/mdfld_dsi_output.c
index 44ee3f6..b88dfc2 100644
--- a/drivers/staging/gma500/mdfld_dsi_output.c
+++ b/drivers/staging/gma500/mdfld_dsi_output.c
@@ -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);
diff --git a/drivers/staging/gma500/mrst_device.c b/drivers/staging/gma500/mrst_device.c
index 5cd8283..daeeb18 100644
--- a/drivers/staging/gma500/mrst_device.c
+++ b/drivers/staging/gma500/mrst_device.c
@@ -17,6 +17,7 @@
*
**************************************************************************/

+#include <linux/backlight.h>
#include <drm/drmP.h>
#include <drm/drm.h>
#include "psb_drm.h"
@@ -42,7 +43,138 @@ static int mrst_output_init(struct drm_device *dev)
}

/*
+ * 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,
diff --git a/drivers/staging/gma500/psb_bl.c b/drivers/staging/gma500/psb_bl.c
deleted file mode 100644
index c84d261..0000000
--- a/drivers/staging/gma500/psb_bl.c
+++ /dev/null
@@ -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;
-}
diff --git a/drivers/staging/gma500/psb_device.c b/drivers/staging/gma500/psb_device.c
index 97e25ab..4a3c516 100644
--- a/drivers/staging/gma500/psb_device.c
+++ b/drivers/staging/gma500/psb_device.c
@@ -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,
};

diff --git a/drivers/staging/gma500/psb_drv.c b/drivers/staging/gma500/psb_drv.c
index 6c57234..bb6b68f 100644
--- a/drivers/staging/gma500/psb_drv.c
+++ b/drivers/staging/gma500/psb_drv.c
@@ -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;
}
diff --git a/drivers/staging/gma500/psb_drv.h b/drivers/staging/gma500/psb_drv.h
index d1c49e7..b0908f2 100644
--- a/drivers/staging/gma500/psb_drv.h
+++ b/drivers/staging/gma500/psb_drv.h
@@ -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;
diff --git a/drivers/staging/gma500/psb_intel_lvds.c b/drivers/staging/gma500/psb_intel_lvds.c
index 850d07d..41b96d2 100644
--- a/drivers/staging/gma500/psb_intel_lvds.c
+++ b/drivers/staging/gma500/psb_intel_lvds.c
@@ -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:

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/