[Intel-gfx] [PATCH] drm/i915: fixup TV load detect
Daniel Vetter
daniel.vetter at ffwll.ch
Tue Nov 13 14:23:17 CET 2012
The docs recommend that we use one high sense to detect composite and
S-Video, and low/inverted sense for component (or general output
detection, but we don't bother with that).
This might or might not finally clear up the confusion around TV
detection. Historically we've flip-flopped an aweful lot between high
and low sense, with varying amounts of justification (usually none
that would have survived scrunitation). The last just change was
commit d42c9e2c24f7e7897405b85816bdf4ac924881c0
Author: Daniel Vetter <daniel.vetter at ffwll.ch>
Date: Sun Mar 25 22:56:14 2012 +0200
drm/i915: reinstate GM45 TV detection fix
Motivated by the last TV detection bug I could find in our bugzilla.
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=31519
Signed-off-by: Daniel Vetter <daniel.vetter at ffwll.ch>
---
drivers/gpu/drm/i915/intel_tv.c | 56 ++++++++++++++++++++++++---------------
1 file changed, 34 insertions(+), 22 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
index 62bb048..b8d783f 100644
--- a/drivers/gpu/drm/i915/intel_tv.c
+++ b/drivers/gpu/drm/i915/intel_tv.c
@@ -1167,7 +1167,8 @@ static const struct drm_display_mode reported_modes[] = {
*/
static int
intel_tv_detect_type(struct intel_tv *intel_tv,
- struct drm_connector *connector)
+ struct drm_connector *connector,
+ bool invert_sense)
{
struct drm_encoder *encoder = &intel_tv->base.base;
struct drm_crtc *crtc = encoder->crtc;
@@ -1201,9 +1202,6 @@ intel_tv_detect_type(struct intel_tv *intel_tv,
tv_dac &= ~(TVDAC_SENSE_MASK | DAC_A_MASK | DAC_B_MASK | DAC_C_MASK);
tv_dac |= (TVDAC_STATE_CHG_EN |
- TVDAC_A_SENSE_CTL |
- TVDAC_B_SENSE_CTL |
- TVDAC_C_SENSE_CTL |
DAC_CTL_OVERRIDE |
DAC_A_0_7_V |
DAC_B_0_7_V |
@@ -1211,12 +1209,13 @@ intel_tv_detect_type(struct intel_tv *intel_tv,
/*
- * The TV sense state should be cleared to zero on cantiga platform. Otherwise
- * the TV is misdetected. This is hardware requirement.
+ * We need to have two runs with opposite sense, since otherwise we
+ * won't be able to differentiate
*/
- if (IS_GM45(dev))
- tv_dac &= ~(TVDAC_STATE_CHG_EN | TVDAC_A_SENSE_CTL |
- TVDAC_B_SENSE_CTL | TVDAC_C_SENSE_CTL);
+ if (invert_sense)
+ tv_dac &= ~(TVDAC_A_SENSE_CTL | TVDAC_B_SENSE_CTL | TVDAC_C_SENSE_CTL);
+ else
+ tv_dac |= TVDAC_A_SENSE_CTL | TVDAC_B_SENSE_CTL | TVDAC_C_SENSE_CTL;
I915_WRITE(TV_CTL, tv_ctl);
I915_WRITE(TV_DAC, tv_dac);
@@ -1229,23 +1228,28 @@ intel_tv_detect_type(struct intel_tv *intel_tv,
tv_dac = I915_READ(TV_DAC);
DRM_DEBUG_KMS("TV detected: %x, %x\n", tv_ctl, tv_dac);
/*
+ * TV sense for non-inverted sense controls ...
+ *
* A B C
* 0 1 1 Composite
* 1 0 X svideo
- * 0 0 0 Component
+ * 0 0 0 Component (test with inverted sense)
*/
- if ((tv_dac & TVDAC_SENSE_MASK) == (TVDAC_B_SENSE | TVDAC_C_SENSE)) {
- DRM_DEBUG_KMS("Detected Composite TV connection\n");
- type = DRM_MODE_CONNECTOR_Composite;
- } else if ((tv_dac & (TVDAC_A_SENSE|TVDAC_B_SENSE)) == TVDAC_A_SENSE) {
- DRM_DEBUG_KMS("Detected S-Video TV connection\n");
- type = DRM_MODE_CONNECTOR_SVIDEO;
- } else if ((tv_dac & TVDAC_SENSE_MASK) == 0) {
- DRM_DEBUG_KMS("Detected Component TV connection\n");
- type = DRM_MODE_CONNECTOR_Component;
+ if (invert_sense) {
+ if ((tv_dac & TVDAC_SENSE_MASK) == TVDAC_SENSE_MASK) {
+ DRM_DEBUG_KMS("Detected Component TV connection\n");
+ type = DRM_MODE_CONNECTOR_Component;
+ }
} else {
- DRM_DEBUG_KMS("Unrecognised TV connection\n");
- type = -1;
+ if ((tv_dac & TVDAC_SENSE_MASK) ==
+ (TVDAC_B_SENSE | TVDAC_C_SENSE)) {
+ DRM_DEBUG_KMS("Detected Composite TV connection\n");
+ type = DRM_MODE_CONNECTOR_Composite;
+ } else if ((tv_dac & (TVDAC_A_SENSE|TVDAC_B_SENSE)) ==
+ TVDAC_A_SENSE) {
+ DRM_DEBUG_KMS("Detected S-Video TV connection\n");
+ type = DRM_MODE_CONNECTOR_SVIDEO;
+ }
}
I915_WRITE(TV_DAC, save_tv_dac & ~TVDAC_STATE_CHG_EN);
@@ -1315,7 +1319,15 @@ intel_tv_detect(struct drm_connector *connector, bool force)
struct intel_load_detect_pipe tmp;
if (intel_get_load_detect_pipe(connector, &mode, &tmp)) {
- type = intel_tv_detect_type(intel_tv, connector);
+ /*
+ * We need to run the load detection twice, since we
+ * can't detect all output types correctly with just one
+ * run.
+ */
+ type = intel_tv_detect_type(intel_tv, connector, false);
+ if (type == -1)
+ type = intel_tv_detect_type(intel_tv, connector,
+ true);
intel_release_load_detect_pipe(connector, &tmp);
} else
return connector_status_unknown;
--
1.7.10.4
More information about the Intel-gfx
mailing list