summaryrefslogtreecommitdiff
path: root/drivers/staging/gma500/psb_intel_display.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/gma500/psb_intel_display.c')
-rw-r--r--drivers/staging/gma500/psb_intel_display.c171
1 files changed, 56 insertions, 115 deletions
diff --git a/drivers/staging/gma500/psb_intel_display.c b/drivers/staging/gma500/psb_intel_display.c
index 09e378d5ddcb..4afa671f9747 100644
--- a/drivers/staging/gma500/psb_intel_display.c
+++ b/drivers/staging/gma500/psb_intel_display.c
@@ -1,5 +1,5 @@
/*
- * Copyright © 2006-2007 Intel Corporation
+ * Copyright © 2006-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,
@@ -22,13 +22,14 @@
#include <linux/pm_runtime.h>
#include <drm/drmP.h>
-#include "psb_fb.h"
+#include "framebuffer.h"
#include "psb_drv.h"
#include "psb_intel_drv.h"
#include "psb_intel_reg.h"
#include "psb_intel_display.h"
-#include "psb_powermgmt.h"
+#include "power.h"
+#include "mdfld_output.h"
struct psb_intel_clock_t {
/* given values */
@@ -350,17 +351,15 @@ int psb_intel_pipe_set_base(struct drm_crtc *crtc,
u32 dspcntr;
int ret = 0;
- PSB_DEBUG_ENTRY("\n");
+ if (!gma_power_begin(dev, true))
+ return 0;
/* no fb bound */
if (!crtc->fb) {
- DRM_DEBUG("No FB bound\n");
- return 0;
+ dev_dbg(dev->dev, "No FB bound\n");
+ goto psb_intel_pipe_cleaner;
}
- if (!gma_power_begin(dev, true))
- return 0;
-
/* We are displaying this buffer, make sure it is actually loaded
into the GTT */
ret = psb_gtt_pin(psbfb->gtt);
@@ -390,7 +389,7 @@ int psb_intel_pipe_set_base(struct drm_crtc *crtc,
dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
break;
default:
- DRM_ERROR("Unknown color depth\n");
+ dev_err(dev->dev, "Unknown color depth\n");
ret = -EINVAL;
psb_gtt_unpin(psbfb->gtt);
goto psb_intel_pipe_set_base_exit;
@@ -398,7 +397,6 @@ int psb_intel_pipe_set_base(struct drm_crtc *crtc,
REG_WRITE(dspcntr_reg, dspcntr);
- DRM_DEBUG("Writing base %08lX %08lX %d %d\n", start, offset, x, y);
if (0 /* FIXMEAC - check what PSB needs */) {
REG_WRITE(dspbase, offset);
REG_READ(dspbase);
@@ -409,6 +407,7 @@ int psb_intel_pipe_set_base(struct drm_crtc *crtc,
REG_READ(dspbase);
}
+psb_intel_pipe_cleaner:
/* If there was a previous display we can now unpin it */
if (old_fb)
psb_gtt_unpin(to_psb_fb(old_fb)->gtt);
@@ -588,6 +587,7 @@ static int psb_intel_crtc_mode_set(struct drm_crtc *crtc,
{
struct drm_device *dev = crtc->dev;
struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+ struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
int pipe = psb_intel_crtc->pipe;
int fp_reg = (pipe == 0) ? FPA0 : FPB0;
int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
@@ -610,6 +610,12 @@ static int psb_intel_crtc_mode_set(struct drm_crtc *crtc,
struct drm_mode_config *mode_config = &dev->mode_config;
struct drm_connector *connector;
+ /* No scan out no play */
+ if (crtc->fb == NULL) {
+ crtc_funcs->mode_set_base(crtc, x, y, old_fb);
+ return 0;
+ }
+
list_for_each_entry(connector, &mode_config->connector_list, head) {
struct psb_intel_output *psb_intel_output =
to_psb_intel_output(connector);
@@ -642,7 +648,7 @@ static int psb_intel_crtc_mode_set(struct drm_crtc *crtc,
ok = psb_intel_find_best_PLL(crtc, adjusted_mode->clock, refclk,
&clock);
if (!ok) {
- DRM_ERROR("Couldn't find PLL settings for mode!\n");
+ dev_err(dev->dev, "Couldn't find PLL settings for mode!\n");
return 0;
}
@@ -706,7 +712,6 @@ static int psb_intel_crtc_mode_set(struct drm_crtc *crtc,
if (psb_intel_panel_fitter_pipe(dev) == pipe)
REG_WRITE(PFIT_CONTROL, 0);
- DRM_DEBUG("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
drm_mode_debug_printmodeline(mode);
if (dpll & DPLL_VCO_ENABLE) {
@@ -723,17 +728,18 @@ static int psb_intel_crtc_mode_set(struct drm_crtc *crtc,
if (is_lvds) {
u32 lvds = REG_READ(LVDS);
- lvds |=
- LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP |
- LVDS_PIPEB_SELECT;
+ lvds &= ~LVDS_PIPEB_SELECT;
+ if (pipe == 1)
+ lvds |= LVDS_PIPEB_SELECT;
+
+ lvds |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;
/* Set the B0-B3 data pairs corresponding to
* whether we're going to
* set the DPLLs for dual-channel mode or not.
*/
+ lvds &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP);
if (clock.p2 == 7)
lvds |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP;
- else
- lvds &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP);
/* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP)
* appropriately here, but we need to look more
@@ -785,11 +791,7 @@ static int psb_intel_crtc_mode_set(struct drm_crtc *crtc,
REG_WRITE(dspcntr_reg, dspcntr);
/* Flush the plane changes */
- {
- struct drm_crtc_helper_funcs *crtc_funcs =
- crtc->helper_private;
- crtc_funcs->mode_set_base(crtc, x, y, old_fb);
- }
+ crtc_funcs->mode_set_base(crtc, x, y, old_fb);
psb_intel_wait_for_vblank(dev);
@@ -820,7 +822,7 @@ void psb_intel_crtc_load_lut(struct drm_crtc *crtc)
palreg = PALETTE_C;
break;
default:
- DRM_ERROR("Illegal Pipe Number.\n");
+ dev_err(dev->dev, "Illegal Pipe Number.\n");
return;
}
@@ -863,10 +865,8 @@ static void psb_intel_crtc_save(struct drm_crtc *crtc)
uint32_t paletteReg;
int i;
- DRM_DEBUG("\n");
-
if (!crtc_state) {
- DRM_DEBUG("No CRTC state found\n");
+ dev_err(dev->dev, "No CRTC state found\n");
return;
}
@@ -890,25 +890,6 @@ static void psb_intel_crtc_save(struct drm_crtc *crtc)
crtc_state->saveDSPBASE = REG_READ(pipeA ? DSPABASE : DSPBBASE);
- DRM_DEBUG("(%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x)\n",
- crtc_state->saveDSPCNTR,
- crtc_state->savePIPECONF,
- crtc_state->savePIPESRC,
- crtc_state->saveFP0,
- crtc_state->saveFP1,
- crtc_state->saveDPLL,
- crtc_state->saveHTOTAL,
- crtc_state->saveHBLANK,
- crtc_state->saveHSYNC,
- crtc_state->saveVTOTAL,
- crtc_state->saveVBLANK,
- crtc_state->saveVSYNC,
- crtc_state->saveDSPSTRIDE,
- crtc_state->saveDSPSIZE,
- crtc_state->saveDSPPOS,
- crtc_state->saveDSPBASE
- );
-
paletteReg = pipeA ? PALETTE_A : PALETTE_B;
for (i = 0; i < 256; ++i)
crtc_state->savePalette[i] = REG_READ(paletteReg + (i << 2));
@@ -929,60 +910,15 @@ static void psb_intel_crtc_restore(struct drm_crtc *crtc)
uint32_t paletteReg;
int i;
- DRM_DEBUG("\n");
-
if (!crtc_state) {
- DRM_DEBUG("No crtc state\n");
+ dev_err(dev->dev, "No crtc state\n");
return;
}
- DRM_DEBUG(
- "current:(%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x)\n",
- REG_READ(pipeA ? DSPACNTR : DSPBCNTR),
- REG_READ(pipeA ? PIPEACONF : PIPEBCONF),
- REG_READ(pipeA ? PIPEASRC : PIPEBSRC),
- REG_READ(pipeA ? FPA0 : FPB0),
- REG_READ(pipeA ? FPA1 : FPB1),
- REG_READ(pipeA ? DPLL_A : DPLL_B),
- REG_READ(pipeA ? HTOTAL_A : HTOTAL_B),
- REG_READ(pipeA ? HBLANK_A : HBLANK_B),
- REG_READ(pipeA ? HSYNC_A : HSYNC_B),
- REG_READ(pipeA ? VTOTAL_A : VTOTAL_B),
- REG_READ(pipeA ? VBLANK_A : VBLANK_B),
- REG_READ(pipeA ? VSYNC_A : VSYNC_B),
- REG_READ(pipeA ? DSPASTRIDE : DSPBSTRIDE),
- REG_READ(pipeA ? DSPASIZE : DSPBSIZE),
- REG_READ(pipeA ? DSPAPOS : DSPBPOS),
- REG_READ(pipeA ? DSPABASE : DSPBBASE)
- );
-
- DRM_DEBUG(
- "saved: (%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x)\n",
- crtc_state->saveDSPCNTR,
- crtc_state->savePIPECONF,
- crtc_state->savePIPESRC,
- crtc_state->saveFP0,
- crtc_state->saveFP1,
- crtc_state->saveDPLL,
- crtc_state->saveHTOTAL,
- crtc_state->saveHBLANK,
- crtc_state->saveHSYNC,
- crtc_state->saveVTOTAL,
- crtc_state->saveVBLANK,
- crtc_state->saveVSYNC,
- crtc_state->saveDSPSTRIDE,
- crtc_state->saveDSPSIZE,
- crtc_state->saveDSPPOS,
- crtc_state->saveDSPBASE
- );
-
-
if (crtc_state->saveDPLL & DPLL_VCO_ENABLE) {
REG_WRITE(pipeA ? DPLL_A : DPLL_B,
crtc_state->saveDPLL & ~DPLL_VCO_ENABLE);
REG_READ(pipeA ? DPLL_A : DPLL_B);
- DRM_DEBUG("write dpll: %x\n",
- REG_READ(pipeA ? DPLL_A : DPLL_B));
udelay(150);
}
@@ -1039,11 +975,8 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc,
struct drm_gem_object *obj;
int ret;
- DRM_DEBUG("\n");
-
/* if we want to turn of the cursor ignore width and height */
if (!handle) {
- DRM_DEBUG("cursor off\n");
/* turn off the cursor */
temp = CURSOR_MODE_DISABLE;
@@ -1067,7 +1000,7 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc,
/* Currently we only support 64x64 cursors */
if (width != 64 || height != 64) {
- DRM_ERROR("we currently only support 64x64 cursors\n");
+ dev_dbg(dev->dev, "we currently only support 64x64 cursors\n");
return -EINVAL;
}
@@ -1076,7 +1009,7 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc,
return -ENOENT;
if (obj->size < width * height * 4) {
- DRM_ERROR("buffer is to small\n");
+ dev_dbg(dev->dev, "buffer is to small\n");
return -ENOMEM;
}
@@ -1085,7 +1018,7 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc,
/* Pin the memory into the GTT */
ret = psb_gtt_pin(gt);
if (ret) {
- DRM_ERROR("Can not pin down handle 0x%x\n", handle);
+ dev_err(dev->dev, "Can not pin down handle 0x%x\n", handle);
return ret;
}
@@ -1106,14 +1039,13 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc,
}
/* unpin the old bo */
- if (psb_intel_crtc->cursor_obj && psb_intel_crtc->cursor_obj != obj) {
+ if (psb_intel_crtc->cursor_obj) {
gt = container_of(psb_intel_crtc->cursor_obj,
struct gtt_range, gem);
psb_gtt_unpin(gt);
drm_gem_object_unreference(psb_intel_crtc->cursor_obj);
psb_intel_crtc->cursor_obj = obj;
}
-
return 0;
}
@@ -1148,7 +1080,7 @@ static int psb_intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
return 0;
}
-static void psb_intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red,
+void psb_intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red,
u16 *green, u16 *blue, uint32_t type, uint32_t size)
{
struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
@@ -1309,7 +1241,7 @@ struct drm_display_mode *psb_intel_crtc_mode_get(struct drm_device *dev,
return mode;
}
-static void psb_intel_crtc_destroy(struct drm_crtc *crtc)
+void psb_intel_crtc_destroy(struct drm_crtc *crtc)
{
struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
struct gtt_range *gt;
@@ -1327,7 +1259,7 @@ static void psb_intel_crtc_destroy(struct drm_crtc *crtc)
kfree(psb_intel_crtc);
}
-static const struct drm_crtc_helper_funcs psb_intel_helper_funcs = {
+const struct drm_crtc_helper_funcs psb_intel_helper_funcs = {
.dpms = psb_intel_crtc_dpms,
.mode_fixup = psb_intel_crtc_mode_fixup,
.mode_set = psb_intel_crtc_mode_set,
@@ -1346,6 +1278,19 @@ const struct drm_crtc_funcs psb_intel_crtc_funcs = {
.destroy = psb_intel_crtc_destroy,
};
+/*
+ * Set the default value of cursor control and base register
+ * to zero. This is a workaround for h/w defect on Oaktrail
+ */
+static void psb_intel_cursor_init(struct drm_device *dev, int pipe)
+{
+ u32 control[3] = { CURACNTR, CURBCNTR, CURCCNTR };
+ u32 base[3] = { CURABASE, CURBBASE, CURCBASE };
+
+ REG_WRITE(control[pipe], 0);
+ REG_WRITE(base[pipe], 0);
+}
+
void psb_intel_crtc_init(struct drm_device *dev, int pipe,
struct psb_intel_mode_device *mode_dev)
{
@@ -1354,8 +1299,6 @@ void psb_intel_crtc_init(struct drm_device *dev, int pipe,
int i;
uint16_t *r_base, *g_base, *b_base;
- PSB_DEBUG_ENTRY("\n");
-
/* We allocate a extra array of drm_connector pointers
* for fbdev after the crtc */
psb_intel_crtc =
@@ -1368,12 +1311,13 @@ void psb_intel_crtc_init(struct drm_device *dev, int pipe,
psb_intel_crtc->crtc_state =
kzalloc(sizeof(struct psb_intel_crtc_state), GFP_KERNEL);
if (!psb_intel_crtc->crtc_state) {
- DRM_INFO("Crtc state error: No memory\n");
+ dev_err(dev->dev, "Crtc state error: No memory\n");
kfree(psb_intel_crtc);
return;
}
- drm_crtc_init(dev, &psb_intel_crtc->base, &psb_intel_crtc_funcs);
+ /* Set the CRTC operations from the chip specific data */
+ drm_crtc_init(dev, &psb_intel_crtc->base, dev_priv->ops->crtc_funcs);
drm_mode_crtc_set_gamma_size(&psb_intel_crtc->base, 256);
psb_intel_crtc->pipe = pipe;
@@ -1396,12 +1340,8 @@ void psb_intel_crtc_init(struct drm_device *dev, int pipe,
psb_intel_crtc->mode_dev = mode_dev;
psb_intel_crtc->cursor_addr = 0;
- if (IS_MRST(dev))
- drm_crtc_helper_add(&psb_intel_crtc->base,
- &mrst_helper_funcs);
- else
- drm_crtc_helper_add(&psb_intel_crtc->base,
- &psb_intel_helper_funcs);
+ drm_crtc_helper_add(&psb_intel_crtc->base,
+ dev_priv->ops->crtc_helper);
/* Setup the array of drm_connector pointer array */
psb_intel_crtc->mode_set.crtc = &psb_intel_crtc->base;
@@ -1414,6 +1354,7 @@ void psb_intel_crtc_init(struct drm_device *dev, int pipe,
psb_intel_crtc->mode_set.connectors =
(struct drm_connector **) (psb_intel_crtc + 1);
psb_intel_crtc->mode_set.num_connectors = 0;
+ psb_intel_cursor_init(dev, pipe);
}
int psb_intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
@@ -1425,7 +1366,7 @@ int psb_intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
struct psb_intel_crtc *crtc;
if (!dev_priv) {
- DRM_ERROR("called with no initialization\n");
+ dev_err(dev->dev, "called with no initialization\n");
return -EINVAL;
}
@@ -1433,7 +1374,7 @@ int psb_intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
DRM_MODE_OBJECT_CRTC);
if (!drmmode_obj) {
- DRM_ERROR("no such CRTC id\n");
+ dev_err(dev->dev, "no such CRTC id\n");
return -EINVAL;
}