Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 307450
b: refs/heads/master
c: 72662e1
h: refs/heads/master
v: v3
  • Loading branch information
Eugeni Dodonov authored and Daniel Vetter committed May 19, 2012
1 parent e9e1a91 commit ab3d295
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 2 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: f5bbfca3e5aedc7e7b299b48b8ec2509b1052acf
refs/heads/master: 72662e103c7dd305725dcf4aabcbd8f69483dfbc
116 changes: 116 additions & 0 deletions trunk/drivers/gpu/drm/i915/intel_ddi.c
Original file line number Diff line number Diff line change
Expand Up @@ -637,3 +637,119 @@ static const struct wrpll_tmds_clock wrpll_tmds_clock_table[] = {
{297000, 2, 22, 20},
{298000, 2, 21, 19},
};

void intel_ddi_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_crtc *crtc = encoder->crtc;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
int port = intel_hdmi->ddi_port;
int pipe = intel_crtc->pipe;
int p, n2, r2, valid=0;
u32 temp, i;

/* On Haswell, we need to enable the clocks and prepare DDI function to
* work in HDMI mode for this pipe.
*/
DRM_DEBUG_KMS("Preparing HDMI DDI mode for Haswell on port %c, pipe %c\n", port_name(port), pipe_name(pipe));

for (i=0; i < ARRAY_SIZE(wrpll_tmds_clock_table); i++) {
if (crtc->mode.clock == wrpll_tmds_clock_table[i].clock) {
p = wrpll_tmds_clock_table[i].p;
n2 = wrpll_tmds_clock_table[i].n2;
r2 = wrpll_tmds_clock_table[i].r2;

DRM_DEBUG_KMS("WR PLL clock: found settings for %dKHz refresh rate: p=%d, n2=%d, r2=%d\n",
crtc->mode.clock,
p, n2, r2);

valid = 1;
break;
}
}

if (!valid) {
DRM_ERROR("Unable to find WR PLL clock settings for %dKHz refresh rate\n",
crtc->mode.clock);
return;
}

/* Enable LCPLL if disabled */
temp = I915_READ(LCPLL_CTL);
if (temp & LCPLL_PLL_DISABLE)
I915_WRITE(LCPLL_CTL,
temp & ~LCPLL_PLL_DISABLE);

/* Configure WR PLL 1, program the correct divider values for
* the desired frequency and wait for warmup */
I915_WRITE(WRPLL_CTL1,
WRPLL_PLL_ENABLE |
WRPLL_PLL_SELECT_LCPLL_2700 |
WRPLL_DIVIDER_REFERENCE(r2) |
WRPLL_DIVIDER_FEEDBACK(n2) |
WRPLL_DIVIDER_POST(p));

udelay(20);

/* Use WRPLL1 clock to drive the output to the port, and tell the pipe to use
* this port for connection.
*/
I915_WRITE(PORT_CLK_SEL(port),
PORT_CLK_SEL_WRPLL1);
I915_WRITE(PIPE_CLK_SEL(pipe),
PIPE_CLK_SEL_PORT(port));

udelay(20);

if (intel_hdmi->has_audio) {
/* Proper support for digital audio needs a new logic and a new set
* of registers, so we leave it for future patch bombing.
*/
DRM_DEBUG_DRIVER("HDMI audio on pipe %c not yet supported on DDI\n",
pipe_name(intel_crtc->pipe));
}

/* Enable PIPE_DDI_FUNC_CTL for the pipe to work in HDMI mode */
temp = I915_READ(DDI_FUNC_CTL(pipe));
temp &= ~PIPE_DDI_PORT_MASK;
temp &= ~PIPE_DDI_BPC_12;
temp |= PIPE_DDI_SELECT_PORT(port) |
PIPE_DDI_MODE_SELECT_HDMI |
((intel_crtc->bpp > 24) ?
PIPE_DDI_BPC_12 :
PIPE_DDI_BPC_8) |
PIPE_DDI_FUNC_ENABLE;

I915_WRITE(DDI_FUNC_CTL(pipe), temp);

intel_hdmi_set_avi_infoframe(encoder, adjusted_mode);
intel_hdmi_set_spd_infoframe(encoder);
}

void intel_ddi_dpms(struct drm_encoder *encoder, int mode)
{
struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
int port = intel_hdmi->ddi_port;
u32 temp;

temp = I915_READ(DDI_BUF_CTL(port));

if (mode != DRM_MODE_DPMS_ON) {
temp &= ~DDI_BUF_CTL_ENABLE;
} else {
temp |= DDI_BUF_CTL_ENABLE;
}

/* Enable DDI_BUF_CTL. In HDMI/DVI mode, the port width,
* and swing/emphasis values are ignored so nothing special needs
* to be done besides enabling the port.
*/
I915_WRITE(DDI_BUF_CTL(port),
temp);
}
5 changes: 5 additions & 0 deletions trunk/drivers/gpu/drm/i915/intel_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -497,4 +497,9 @@ extern void gen6_update_ring_freq(struct drm_i915_private *dev_priv);
extern void gen6_disable_rps(struct drm_device *dev);
extern void intel_init_emon(struct drm_device *dev);

extern void intel_ddi_dpms(struct drm_encoder *encoder, int mode);
extern void intel_ddi_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode);

#endif /* __INTEL_DRV_H__ */
13 changes: 12 additions & 1 deletion trunk/drivers/gpu/drm/i915/intel_hdmi.c
Original file line number Diff line number Diff line change
Expand Up @@ -560,6 +560,14 @@ static void intel_hdmi_destroy(struct drm_connector *connector)
kfree(connector);
}

static const struct drm_encoder_helper_funcs intel_hdmi_helper_funcs_hsw = {
.dpms = intel_ddi_dpms,
.mode_fixup = intel_hdmi_mode_fixup,
.prepare = intel_encoder_prepare,
.mode_set = intel_ddi_mode_set,
.commit = intel_encoder_commit,
};

static const struct drm_encoder_helper_funcs intel_hdmi_helper_funcs = {
.dpms = intel_hdmi_dpms,
.mode_fixup = intel_hdmi_mode_fixup,
Expand Down Expand Up @@ -699,7 +707,10 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
I915_WRITE(TVIDEO_DIP_CTL(i), 0);
}

drm_encoder_helper_add(&intel_encoder->base, &intel_hdmi_helper_funcs);
if (IS_HASWELL(dev))
drm_encoder_helper_add(&intel_encoder->base, &intel_hdmi_helper_funcs_hsw);
else
drm_encoder_helper_add(&intel_encoder->base, &intel_hdmi_helper_funcs);

intel_hdmi_add_properties(intel_hdmi, connector);

Expand Down

0 comments on commit ab3d295

Please sign in to comment.