summaryrefslogtreecommitdiff
path: root/drivers/staging/gma500/mrst_lvds.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/gma500/mrst_lvds.c')
-rw-r--r--drivers/staging/gma500/mrst_lvds.c92
1 files changed, 64 insertions, 28 deletions
diff --git a/drivers/staging/gma500/mrst_lvds.c b/drivers/staging/gma500/mrst_lvds.c
index 4a08b74f5ff9..e7999a2a3796 100644
--- a/drivers/staging/gma500/mrst_lvds.c
+++ b/drivers/staging/gma500/mrst_lvds.c
@@ -24,11 +24,11 @@
#include <drm/drmP.h>
#include <asm/mrst.h>
-#include "psb_intel_bios.h"
+#include "intel_bios.h"
#include "psb_drv.h"
#include "psb_intel_drv.h"
#include "psb_intel_reg.h"
-#include "psb_powermgmt.h"
+#include "power.h"
#include <linux/pm_runtime.h>
/* The max/min PWM frequency in BPCR[31:17] - */
@@ -46,8 +46,7 @@ static void mrst_lvds_set_power(struct drm_device *dev,
struct psb_intel_output *output, bool on)
{
u32 pp_status;
- DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private;
- PSB_DEBUG_ENTRY("\n");
+ struct drm_psb_private *dev_priv = dev->dev_private;
if (!gma_power_begin(dev, true))
return;
@@ -59,7 +58,11 @@ static void mrst_lvds_set_power(struct drm_device *dev,
pp_status = REG_READ(PP_STATUS);
} while ((pp_status & (PP_ON | PP_READY)) == PP_READY);
dev_priv->is_lvds_on = true;
+ if (dev_priv->ops->lvds_bl_power)
+ dev_priv->ops->lvds_bl_power(dev, true);
} else {
+ if (dev_priv->ops->lvds_bl_power)
+ dev_priv->ops->lvds_bl_power(dev, false);
REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) &
~POWER_TARGET_ON);
do {
@@ -68,7 +71,6 @@ static void mrst_lvds_set_power(struct drm_device *dev,
dev_priv->is_lvds_on = false;
pm_request_idle(&dev->pdev->dev);
}
-
gma_power_end(dev);
}
@@ -77,8 +79,6 @@ static void mrst_lvds_dpms(struct drm_encoder *encoder, int mode)
struct drm_device *dev = encoder->dev;
struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
- PSB_DEBUG_ENTRY("\n");
-
if (mode == DRM_MODE_DPMS_ON)
mrst_lvds_set_power(dev, output, true);
else
@@ -94,11 +94,10 @@ static void mrst_lvds_mode_set(struct drm_encoder *encoder,
struct psb_intel_mode_device *mode_dev =
enc_to_psb_intel_output(encoder)->mode_dev;
struct drm_device *dev = encoder->dev;
+ struct drm_psb_private *dev_priv = dev->dev_private;
u32 lvds_port;
uint64_t v = DRM_MODE_SCALE_FULLSCREEN;
- PSB_DEBUG_ENTRY("\n");
-
if (!gma_power_begin(dev, true))
return;
@@ -112,7 +111,9 @@ static void mrst_lvds_mode_set(struct drm_encoder *encoder,
LVDS_PORT_EN |
LVDS_BORDER_EN;
- if (mode_dev->panel_wants_dither)
+ /* If the firmware says dither on Moorestown, or the BIOS does
+ on Oaktrail then enable dithering */
+ if (mode_dev->panel_wants_dither || dev_priv->lvds_dither)
lvds_port |= MRST_PANEL_8TO6_DITHER_ENABLE;
REG_WRITE(LVDS, lvds_port);
@@ -146,13 +147,59 @@ static void mrst_lvds_mode_set(struct drm_encoder *encoder,
gma_power_end(dev);
}
+static void mrst_lvds_prepare(struct drm_encoder *encoder)
+{
+ struct drm_device *dev = encoder->dev;
+ struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
+ struct psb_intel_mode_device *mode_dev = output->mode_dev;
+
+ if (!gma_power_begin(dev, true))
+ return;
+
+ mode_dev->saveBLC_PWM_CTL = REG_READ(BLC_PWM_CTL);
+ mode_dev->backlight_duty_cycle = (mode_dev->saveBLC_PWM_CTL &
+ BACKLIGHT_DUTY_CYCLE_MASK);
+ mrst_lvds_set_power(dev, output, false);
+ gma_power_end(dev);
+}
+
+static u32 mrst_lvds_get_max_backlight(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ u32 ret;
+
+ if (gma_power_begin(dev, false)) {
+ ret = ((REG_READ(BLC_PWM_CTL) &
+ BACKLIGHT_MODULATION_FREQ_MASK) >>
+ BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
+
+ gma_power_end(dev);
+ } else
+ ret = ((dev_priv->saveBLC_PWM_CTL &
+ BACKLIGHT_MODULATION_FREQ_MASK) >>
+ BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
+
+ return ret;
+}
+
+static void mrst_lvds_commit(struct drm_encoder *encoder)
+{
+ struct drm_device *dev = encoder->dev;
+ struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
+ struct psb_intel_mode_device *mode_dev = output->mode_dev;
+
+ if (mode_dev->backlight_duty_cycle == 0)
+ mode_dev->backlight_duty_cycle =
+ mrst_lvds_get_max_backlight(dev);
+ mrst_lvds_set_power(dev, output, true);
+}
static const struct drm_encoder_helper_funcs mrst_lvds_helper_funcs = {
.dpms = mrst_lvds_dpms,
.mode_fixup = psb_intel_lvds_mode_fixup,
- .prepare = psb_intel_lvds_prepare,
+ .prepare = mrst_lvds_prepare,
.mode_set = mrst_lvds_mode_set,
- .commit = psb_intel_lvds_commit,
+ .commit = mrst_lvds_commit,
};
static struct drm_display_mode lvds_configuration_modes[] = {
@@ -252,8 +299,6 @@ void mrst_lvds_init(struct drm_device *dev,
struct i2c_adapter *i2c_adap;
struct drm_display_mode *scan; /* *modes, *bios_mode; */
- PSB_DEBUG_ENTRY("\n");
-
psb_intel_output = kzalloc(sizeof(struct psb_intel_output), GFP_KERNEL);
if (!psb_intel_output)
return;
@@ -302,16 +347,10 @@ void mrst_lvds_init(struct drm_device *dev,
* if closed, act like it's not there for now
*/
- /* This ifdef can go once the cpu ident stuff is cleaned up in arch */
-#if defined(CONFIG_X86_MRST)
- if (mrst_identify_cpu())
- i2c_adap = i2c_get_adapter(2);
- else /* Oaktrail uses I2C 1 */
-#endif
- i2c_adap = i2c_get_adapter(1);
+ i2c_adap = i2c_get_adapter(dev_priv->ops->i2c_bus);
if (i2c_adap == NULL)
- printk(KERN_ALERT "No ddc adapter available!\n");
+ dev_err(dev->dev, "No ddc adapter available!\n");
/*
* Attempt to get the fixed panel mode from DDC. Assume that the
* preferred mode is the right one.
@@ -333,7 +372,6 @@ void mrst_lvds_init(struct drm_device *dev,
}
}
}
-
/*
* If we didn't get EDID, try geting panel timing
* from configuration data
@@ -341,15 +379,13 @@ void mrst_lvds_init(struct drm_device *dev,
mode_dev->panel_fixed_mode = mrst_lvds_get_configuration_mode(dev);
if (mode_dev->panel_fixed_mode) {
- mode_dev->panel_fixed_mode->type |=
- DRM_MODE_TYPE_PREFERRED;
+ mode_dev->panel_fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
goto out; /* FIXME: check for quirks */
}
/* If we still don't have a mode after all that, give up. */
if (!mode_dev->panel_fixed_mode) {
- DRM_DEBUG
- ("Found no modes on the lvds, ignoring the LVDS\n");
+ dev_err(dev->dev, "Found no modes on the lvds, ignoring the LVDS\n");
goto failed_find;
}
@@ -358,7 +394,7 @@ out:
return;
failed_find:
- DRM_DEBUG("No LVDS modes found, disabling.\n");
+ dev_dbg(dev->dev, "No LVDS modes found, disabling.\n");
if (psb_intel_output->ddc_bus)
psb_intel_i2c_destroy(psb_intel_output->ddc_bus);