/*
* 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,
* 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 "framebuffer.h"
#include "psb_drv.h"
#include "psb_intel_drv.h"
#include "psb_intel_reg.h"
#include "psb_intel_display.h"
#include "power.h"
struct psb_intel_clock_t {
/* given values */
int n;
int m1, m2;
int p1, p2;
/* derived values */
int dot;
int vco;
int m;
int p;
};
struct psb_intel_range_t {
int min, max;
};
struct psb_intel_p2_t {
int dot_limit;
int p2_slow, p2_fast;
};
#define INTEL_P2_NUM 2
struct psb_intel_limit_t {
struct psb_intel_range_t dot, vco, n, m, m1, m2, p, p1;
struct psb_intel_p2_t p2;
};
#define I8XX_DOT_MIN 25000
#define I8XX_DOT_MAX 350000
#define I8XX_VCO_MIN 930000
#define I8XX_VCO_MAX 1400000
#define I8XX_N_MIN 3
#define I8XX_N_MAX 16
#define I8XX_M_MIN 96
#define I8XX_M_MAX 140
#define I8XX_M1_MIN 18
#define I8XX_M1_MAX 26
#define I8XX_M2_MIN 6
#define I8XX_M2_MAX 16
#define I8XX_P_MIN 4
#define I8XX_P_MAX 128
#define I8XX_P1_MIN 2
#define I8XX_P1_MAX 33
#define I8XX_P1_LVDS_MIN 1
#define I8XX_P1_LVDS_MAX 6
#define I8XX_P2_SLOW 4
#define I8XX_P2_FAST 2
#define I8XX_P2_LVDS_SLOW 14
#define I8XX_P2_LVDS_FAST 14 /* No fast option */
#define I8XX_P2_SLOW_LIMIT 165000
#define I9XX_DOT_MIN 20000
#define I9XX_DOT_MAX 400000
#define I9XX_VCO_MIN 1400000
#define I9XX_VCO_MAX 2800000
#define I9XX_N_MIN 3
#define I9XX_N_MAX 8
#define I9XX_M_MIN 70
#define I9XX_M_MAX 120
#define I9XX_M1_MIN 10
#define I9XX_M1_MAX 20
#define I9XX_M2_MIN 5
#define I9XX_M2_MAX 9
#define I9XX_P_SDVO_DAC_MIN 5
#define I9XX_P_SDVO_DAC_MAX 80
#define I9XX_P_LVDS_MIN 7
#define I9XX_P_LVDS_MAX 98
#define I9XX_P1_MIN 1
#define I9XX_P1_MAX 8
#define I9XX_P2_SDVO_DAC_SLOW 10
#define I9XX_P2_SDVO_DAC_FAST 5
#define I9XX_P2_SDVO_DAC_SLOW_LIMIT 200000
#define I9XX_P2_LVDS_SLOW 14
#define I9XX_P2_LVDS_FAST 7
#define I9XX_P2_LVDS_SLOW_LIMIT 112000
#define INTEL_LIMIT_I8XX_DVO_DAC 0
#define INTEL_LIMIT_I8XX_LVDS 1
#define INTEL_LIMIT_I9XX_SDVO_DAC 2
#define INTEL_LIMIT_I9XX_LVDS 3
static const struct psb_intel_limit_t psb_intel_limits[] = {
{ /* INTEL_LIMIT_I8XX_DVO_DAC */
.dot = {.min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX},
.vco = {.min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX},
.n = {.min = I8XX_N_MIN, .max = I8XX_N_MAX},
.m = {.min = I8XX_M_MIN, .max = I8XX_M_MAX},
.m1 = {.min = I8XX_M1_MIN, .max = I8XX_M1_MAX},
.m2 = {.min = I8XX_M2_MIN, .max = I8XX_M2_MAX},
.p = {.min = I8XX_P_MIN, .max = I8XX_P_MAX},
.p1 = {.min = I8XX_P1_MIN, .max = I8XX_P1_MAX},
.p2 = {.dot_limit = I8XX_P2_SLOW_LIMIT,
.p2_slow = I8XX_P2_SLOW, .p2_fast = I8XX_P2_FAST},
},
{ /* INTEL_LIMIT_I8XX_LVDS */
.dot = {.min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX},
.vco = {.min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX},
.n = {.min = I8XX_N_MIN, .max = I8XX_N_MAX},
.m = {.min = I8XX_M_MIN, .max = I8XX_M_MAX},
.m1 = {.min = I8XX_M1_MIN, .max = I8XX_M1_M
|