mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-15 23:25:07 +00:00
gma500/cdv: add the bits that don't need the new code
Based on bits from Yakui <yakui.zhao@intel.com> We can import various little bits of code before we plumb it all in and hopefully this way catch any regressions more easily. Signed-off-by: Alan Cox <alan@linux.intel.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
parent
8695b61294
commit
220801bdb5
4 changed files with 161 additions and 3 deletions
|
@ -488,6 +488,65 @@ static void cdv_hotplug_enable(struct drm_device *dev, bool on)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *force_audio_names[] = {
|
||||||
|
"off",
|
||||||
|
"auto",
|
||||||
|
"on",
|
||||||
|
};
|
||||||
|
|
||||||
|
void cdv_intel_attach_force_audio_property(struct drm_connector *connector)
|
||||||
|
{
|
||||||
|
struct drm_device *dev = connector->dev;
|
||||||
|
struct drm_psb_private *dev_priv = dev->dev_private;
|
||||||
|
struct drm_property *prop;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
prop = dev_priv->force_audio_property;
|
||||||
|
if (prop == NULL) {
|
||||||
|
prop = drm_property_create(dev, DRM_MODE_PROP_ENUM,
|
||||||
|
"audio",
|
||||||
|
ARRAY_SIZE(force_audio_names));
|
||||||
|
if (prop == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(force_audio_names); i++)
|
||||||
|
drm_property_add_enum(prop, i, i-1, force_audio_names[i]);
|
||||||
|
|
||||||
|
dev_priv->force_audio_property = prop;
|
||||||
|
}
|
||||||
|
drm_connector_attach_property(connector, prop, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const char *broadcast_rgb_names[] = {
|
||||||
|
"Full",
|
||||||
|
"Limited 16:235",
|
||||||
|
};
|
||||||
|
|
||||||
|
void cdv_intel_attach_broadcast_rgb_property(struct drm_connector *connector)
|
||||||
|
{
|
||||||
|
struct drm_device *dev = connector->dev;
|
||||||
|
struct drm_psb_private *dev_priv = dev->dev_private;
|
||||||
|
struct drm_property *prop;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
prop = dev_priv->broadcast_rgb_property;
|
||||||
|
if (prop == NULL) {
|
||||||
|
prop = drm_property_create(dev, DRM_MODE_PROP_ENUM,
|
||||||
|
"Broadcast RGB",
|
||||||
|
ARRAY_SIZE(broadcast_rgb_names));
|
||||||
|
if (prop == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(broadcast_rgb_names); i++)
|
||||||
|
drm_property_add_enum(prop, i, i, broadcast_rgb_names[i]);
|
||||||
|
|
||||||
|
dev_priv->broadcast_rgb_property = prop;
|
||||||
|
}
|
||||||
|
|
||||||
|
drm_connector_attach_property(connector, prop, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/* Cedarview */
|
/* Cedarview */
|
||||||
static const struct psb_offset cdv_regmap[2] = {
|
static const struct psb_offset cdv_regmap[2] = {
|
||||||
{
|
{
|
||||||
|
|
|
@ -64,11 +64,16 @@ struct cdv_intel_limit_t {
|
||||||
static bool cdv_intel_find_best_PLL(const struct cdv_intel_limit_t *limit,
|
static bool cdv_intel_find_best_PLL(const struct cdv_intel_limit_t *limit,
|
||||||
struct drm_crtc *crtc, int target, int refclk,
|
struct drm_crtc *crtc, int target, int refclk,
|
||||||
struct cdv_intel_clock_t *best_clock);
|
struct cdv_intel_clock_t *best_clock);
|
||||||
|
static bool cdv_intel_find_dp_pll(const struct cdv_intel_limit_t *limit, struct drm_crtc *crtc, int target,
|
||||||
|
int refclk,
|
||||||
|
struct cdv_intel_clock_t *best_clock);
|
||||||
|
|
||||||
#define CDV_LIMIT_SINGLE_LVDS_96 0
|
#define CDV_LIMIT_SINGLE_LVDS_96 0
|
||||||
#define CDV_LIMIT_SINGLE_LVDS_100 1
|
#define CDV_LIMIT_SINGLE_LVDS_100 1
|
||||||
#define CDV_LIMIT_DAC_HDMI_27 2
|
#define CDV_LIMIT_DAC_HDMI_27 2
|
||||||
#define CDV_LIMIT_DAC_HDMI_96 3
|
#define CDV_LIMIT_DAC_HDMI_96 3
|
||||||
|
#define CDV_LIMIT_DP_27 4
|
||||||
|
#define CDV_LIMIT_DP_100 5
|
||||||
|
|
||||||
static const struct cdv_intel_limit_t cdv_intel_limits[] = {
|
static const struct cdv_intel_limit_t cdv_intel_limits[] = {
|
||||||
{ /* CDV_SIGNLE_LVDS_96MHz */
|
{ /* CDV_SIGNLE_LVDS_96MHz */
|
||||||
|
@ -123,6 +128,30 @@ static const struct cdv_intel_limit_t cdv_intel_limits[] = {
|
||||||
.p2 = {.dot_limit = 225000, .p2_slow = 10, .p2_fast = 5},
|
.p2 = {.dot_limit = 225000, .p2_slow = 10, .p2_fast = 5},
|
||||||
.find_pll = cdv_intel_find_best_PLL,
|
.find_pll = cdv_intel_find_best_PLL,
|
||||||
},
|
},
|
||||||
|
{ /* CDV_DP_27MHz */
|
||||||
|
.dot = {.min = 160000, .max = 272000},
|
||||||
|
.vco = {.min = 1809000, .max = 3564000},
|
||||||
|
.n = {.min = 1, .max = 1},
|
||||||
|
.m = {.min = 67, .max = 132},
|
||||||
|
.m1 = {.min = 0, .max = 0},
|
||||||
|
.m2 = {.min = 65, .max = 130},
|
||||||
|
.p = {.min = 5, .max = 90},
|
||||||
|
.p1 = {.min = 1, .max = 9},
|
||||||
|
.p2 = {.dot_limit = 225000, .p2_slow = 10, .p2_fast = 10},
|
||||||
|
.find_pll = cdv_intel_find_dp_pll,
|
||||||
|
},
|
||||||
|
{ /* CDV_DP_100MHz */
|
||||||
|
.dot = {.min = 160000, .max = 272000},
|
||||||
|
.vco = {.min = 1800000, .max = 3600000},
|
||||||
|
.n = {.min = 2, .max = 6},
|
||||||
|
.m = {.min = 60, .max = 164},
|
||||||
|
.m1 = {.min = 0, .max = 0},
|
||||||
|
.m2 = {.min = 58, .max = 162},
|
||||||
|
.p = {.min = 5, .max = 100},
|
||||||
|
.p1 = {.min = 1, .max = 10},
|
||||||
|
.p2 = {.dot_limit = 225000, .p2_slow = 10, .p2_fast = 10},
|
||||||
|
.find_pll = cdv_intel_find_dp_pll,
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#define _wait_for(COND, MS, W) ({ \
|
#define _wait_for(COND, MS, W) ({ \
|
||||||
|
@ -269,7 +298,7 @@ cdv_dpll_set_clock_cdv(struct drm_device *dev, struct drm_crtc *crtc,
|
||||||
ref_value &= ~(REF_CLK_MASK);
|
ref_value &= ~(REF_CLK_MASK);
|
||||||
|
|
||||||
/* use DPLL_A for pipeB on CRT/HDMI */
|
/* use DPLL_A for pipeB on CRT/HDMI */
|
||||||
if (pipe == 1 && !is_lvds) {
|
if (pipe == 1 && !is_lvds && !(ddi_select & DP_MASK)) {
|
||||||
DRM_DEBUG_KMS("use DPLLA for pipe B\n");
|
DRM_DEBUG_KMS("use DPLLA for pipe B\n");
|
||||||
ref_value |= REF_CLK_DPLLA;
|
ref_value |= REF_CLK_DPLLA;
|
||||||
} else {
|
} else {
|
||||||
|
@ -409,6 +438,11 @@ static const struct cdv_intel_limit_t *cdv_intel_limit(struct drm_crtc *crtc,
|
||||||
limit = &cdv_intel_limits[CDV_LIMIT_SINGLE_LVDS_96];
|
limit = &cdv_intel_limits[CDV_LIMIT_SINGLE_LVDS_96];
|
||||||
else
|
else
|
||||||
limit = &cdv_intel_limits[CDV_LIMIT_SINGLE_LVDS_100];
|
limit = &cdv_intel_limits[CDV_LIMIT_SINGLE_LVDS_100];
|
||||||
|
} else if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) {
|
||||||
|
if (refclk == 27000)
|
||||||
|
limit = &cdv_intel_limits[CDV_LIMIT_DP_27];
|
||||||
|
else
|
||||||
|
limit = &cdv_intel_limits[CDV_LIMIT_DP_100];
|
||||||
} else {
|
} else {
|
||||||
if (refclk == 27000)
|
if (refclk == 27000)
|
||||||
limit = &cdv_intel_limits[CDV_LIMIT_DAC_HDMI_27];
|
limit = &cdv_intel_limits[CDV_LIMIT_DAC_HDMI_27];
|
||||||
|
@ -510,6 +544,49 @@ static bool cdv_intel_find_best_PLL(const struct cdv_intel_limit_t *limit,
|
||||||
return err != target;
|
return err != target;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool cdv_intel_find_dp_pll(const struct cdv_intel_limit_t *limit, struct drm_crtc *crtc, int target,
|
||||||
|
int refclk,
|
||||||
|
struct cdv_intel_clock_t *best_clock)
|
||||||
|
{
|
||||||
|
struct cdv_intel_clock_t clock;
|
||||||
|
if (refclk == 27000) {
|
||||||
|
if (target < 200000) {
|
||||||
|
clock.p1 = 2;
|
||||||
|
clock.p2 = 10;
|
||||||
|
clock.n = 1;
|
||||||
|
clock.m1 = 0;
|
||||||
|
clock.m2 = 118;
|
||||||
|
} else {
|
||||||
|
clock.p1 = 1;
|
||||||
|
clock.p2 = 10;
|
||||||
|
clock.n = 1;
|
||||||
|
clock.m1 = 0;
|
||||||
|
clock.m2 = 98;
|
||||||
|
}
|
||||||
|
} else if (refclk == 100000) {
|
||||||
|
if (target < 200000) {
|
||||||
|
clock.p1 = 2;
|
||||||
|
clock.p2 = 10;
|
||||||
|
clock.n = 5;
|
||||||
|
clock.m1 = 0;
|
||||||
|
clock.m2 = 160;
|
||||||
|
} else {
|
||||||
|
clock.p1 = 1;
|
||||||
|
clock.p2 = 10;
|
||||||
|
clock.n = 5;
|
||||||
|
clock.m1 = 0;
|
||||||
|
clock.m2 = 133;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
return false;
|
||||||
|
clock.m = clock.m2 + 2;
|
||||||
|
clock.p = clock.p1 * clock.p2;
|
||||||
|
clock.vco = (refclk * clock.m) / clock.n;
|
||||||
|
clock.dot = clock.vco / clock.p;
|
||||||
|
memcpy(best_clock, &clock, sizeof(struct cdv_intel_clock_t));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static int cdv_intel_pipe_set_base(struct drm_crtc *crtc,
|
static int cdv_intel_pipe_set_base(struct drm_crtc *crtc,
|
||||||
int x, int y, struct drm_framebuffer *old_fb)
|
int x, int y, struct drm_framebuffer *old_fb)
|
||||||
{
|
{
|
||||||
|
@ -963,7 +1040,7 @@ static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc,
|
||||||
u32 dpll = 0, dspcntr, pipeconf;
|
u32 dpll = 0, dspcntr, pipeconf;
|
||||||
bool ok;
|
bool ok;
|
||||||
bool is_crt = false, is_lvds = false, is_tv = false;
|
bool is_crt = false, is_lvds = false, is_tv = false;
|
||||||
bool is_hdmi = false;
|
bool is_hdmi = false, is_dp = false;
|
||||||
struct drm_mode_config *mode_config = &dev->mode_config;
|
struct drm_mode_config *mode_config = &dev->mode_config;
|
||||||
struct drm_connector *connector;
|
struct drm_connector *connector;
|
||||||
const struct cdv_intel_limit_t *limit;
|
const struct cdv_intel_limit_t *limit;
|
||||||
|
@ -991,6 +1068,9 @@ static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc,
|
||||||
case INTEL_OUTPUT_HDMI:
|
case INTEL_OUTPUT_HDMI:
|
||||||
is_hdmi = true;
|
is_hdmi = true;
|
||||||
break;
|
break;
|
||||||
|
case INTEL_OUTPUT_DISPLAYPORT:
|
||||||
|
is_dp = true;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
DRM_ERROR("invalid output type.\n");
|
DRM_ERROR("invalid output type.\n");
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1003,6 +1083,12 @@ static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc,
|
||||||
else
|
else
|
||||||
/* high-end sku, 27/100 mhz */
|
/* high-end sku, 27/100 mhz */
|
||||||
refclk = 27000;
|
refclk = 27000;
|
||||||
|
if (is_dp) {
|
||||||
|
if (pipe == 0)
|
||||||
|
refclk = 27000;
|
||||||
|
else
|
||||||
|
refclk = 100000;
|
||||||
|
}
|
||||||
|
|
||||||
if (is_lvds && dev_priv->lvds_use_ssc) {
|
if (is_lvds && dev_priv->lvds_use_ssc) {
|
||||||
refclk = dev_priv->lvds_ssc_freq * 1000;
|
refclk = dev_priv->lvds_ssc_freq * 1000;
|
||||||
|
@ -1028,6 +1114,15 @@ static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc,
|
||||||
}
|
}
|
||||||
/* dpll |= PLL_REF_INPUT_DREFCLK; */
|
/* dpll |= PLL_REF_INPUT_DREFCLK; */
|
||||||
|
|
||||||
|
if (is_dp) {
|
||||||
|
/*FIXME cdv_intel_dp_set_m_n(crtc, mode, adjusted_mode); */
|
||||||
|
} else {
|
||||||
|
REG_WRITE(PIPE_GMCH_DATA_M(pipe), 0);
|
||||||
|
REG_WRITE(PIPE_GMCH_DATA_N(pipe), 0);
|
||||||
|
REG_WRITE(PIPE_DP_LINK_M(pipe), 0);
|
||||||
|
REG_WRITE(PIPE_DP_LINK_N(pipe), 0);
|
||||||
|
}
|
||||||
|
|
||||||
dpll |= DPLL_SYNCLOCK_ENABLE;
|
dpll |= DPLL_SYNCLOCK_ENABLE;
|
||||||
/* if (is_lvds)
|
/* if (is_lvds)
|
||||||
dpll |= DPLLB_MODE_LVDS;
|
dpll |= DPLLB_MODE_LVDS;
|
||||||
|
|
|
@ -764,6 +764,10 @@ static void psb_setup_outputs(struct drm_device *dev)
|
||||||
crtc_mask = dev_priv->ops->hdmi_mask;
|
crtc_mask = dev_priv->ops->hdmi_mask;
|
||||||
clone_mask = (1 << INTEL_OUTPUT_HDMI);
|
clone_mask = (1 << INTEL_OUTPUT_HDMI);
|
||||||
break;
|
break;
|
||||||
|
case INTEL_OUTPUT_DISPLAYPORT:
|
||||||
|
crtc_mask = (1 << 0) | (1 << 1);
|
||||||
|
clone_mask = (1 << INTEL_OUTPUT_DISPLAYPORT);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
encoder->possible_crtcs = crtc_mask;
|
encoder->possible_crtcs = crtc_mask;
|
||||||
encoder->possible_clones =
|
encoder->possible_clones =
|
||||||
|
|
|
@ -134,7 +134,7 @@ struct psb_intel_encoder {
|
||||||
u32 ddi_select; /* Channel info */
|
u32 ddi_select; /* Channel info */
|
||||||
#define DDI0_SELECT 0x01
|
#define DDI0_SELECT 0x01
|
||||||
#define DDI1_SELECT 0x02
|
#define DDI1_SELECT 0x02
|
||||||
#define DP_MASK 0x8000;
|
#define DP_MASK 0x8000
|
||||||
#define DDI_MASK 0x03
|
#define DDI_MASK 0x03
|
||||||
void *dev_priv; /* For sdvo_priv, lvds_priv, etc... */
|
void *dev_priv; /* For sdvo_priv, lvds_priv, etc... */
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue