/*
* Copyright © 2006-2007 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 Anholt <eric@anholt.net>
*/
#include <linux/i2c.h>
#include <linux/pm_runtime.h>
#include <drm/drmP.h>
#include "psb_intel_reg.h"
#include "gma_display.h"
#include "framebuffer.h"
#include "mdfld_output.h"
#include "mdfld_dsi_output.h"
/* Hardcoded currently */
static int ksel = KSEL_CRYSTAL_19;
struct psb_intel_range_t {
int min, max;
};
struct mrst_limit_t {
struct psb_intel_range_t dot, m, p1;
};
struct mrst_clock_t {
/* derived values */
int dot;
int m;
int p1;
};
#define COUNT_MAX 0x10000000
void mdfldWaitForPipeDisable(struct drm_device *dev, int pipe)
{
struct drm_psb_private *dev_priv = dev->dev_private;
const struct psb_offset *map = &dev_priv->regmap[pipe];
int count, temp;
switch (pipe) {
case 0:
case 1:
case 2:
break;
default:
DRM_ERROR("Illegal Pipe Number.\n");
return;
}
/* FIXME JLIU7_PO */
gma_wait_for_vblank(dev);
return;
/* Wait for for the pipe disable to take effect. */
for (count = 0; count < COUNT_MAX; count++) {
temp = REG_READ(map->conf);
if ((temp & PIPEACONF_PIPE_STATE) == 0)
break;
}
}
void mdfldWaitForPipeEnable(struct drm_device *dev, int pipe)
{
struct drm_psb_private *dev_priv = dev->dev_private;
const struct psb_offset *map = &dev_priv->regmap[pipe];
int count, temp;
switch (pipe) {
case 0:
case 1:
case 2:
break;
default:
DRM_ERROR("Illegal Pipe Number.\n");
return;
}
/* FIXME JLIU7_PO */
gma_wait_for_vblank(dev);
return;
/* Wait for for the pipe enable to take effect. */
for (count = 0; count < COUNT_MAX; count++) {
temp = REG_READ(map->conf);
if (temp & PIPEACONF_PIPE_STATE)
break;
}
}
/**
* Return the pipe currently connected to the panel fitter,
* or -1 if the panel fitter is not present or not in use
*/
static int psb_intel_panel_fitter_pipe(struct drm_device *dev)
{
u32 pfit_control;
pfit_control = REG_READ(PFIT_CONTROL);
/* See if the panel fitter is in use */
if ((pfit_control & PFIT_ENABLE) == 0)
return -1;
/* 965 can place panel fitter on either pipe */
return (pfit_control >> 29) & 0x3;
}
static struct drm_device globle_dev;
void mdfld__intel_plane_set_alpha(int enable)
{
struct drm_device *dev = &globle_dev;
int dspcntr_reg = DSPACNTR;
u32 dspcntr;
dspcntr = REG_READ(dspcntr_reg);
if (enable) {
dspcntr &= ~DISPPLANE_32BPP_NO_ALPHA;
dspcntr |= DISPPLANE_32BPP;
} else {
dspcntr &= ~DISPPLANE_32BPP;
dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
}
REG_WRITE(dspcntr_reg, dspcntr);
}
static int check_fb(struct drm_framebuffer *fb)
{
if (!fb)
return 0;
switch (fb->format->cpp[0] * 8) {
case 8:
case 16:
case 24:
case 32:
return 0;
default:
DRM_ERROR("Unknown color depth\n");
return -EINVAL;
}
}
static int mdfld__intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
struct drm_framebuffer *old_fb)
{
struct drm_device *dev = crtc->dev;
struct drm_psb_private *dev_priv = dev->dev_private