1296548Sdumbbell/* 2296548Sdumbbell * Copyright 2006 Dave Airlie <airlied@linux.ie> 3296548Sdumbbell * Copyright �� 2006-2007 Intel Corporation 4296548Sdumbbell * 5296548Sdumbbell * Permission is hereby granted, free of charge, to any person obtaining a 6296548Sdumbbell * copy of this software and associated documentation files (the "Software"), 7296548Sdumbbell * to deal in the Software without restriction, including without limitation 8296548Sdumbbell * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9296548Sdumbbell * and/or sell copies of the Software, and to permit persons to whom the 10296548Sdumbbell * Software is furnished to do so, subject to the following conditions: 11296548Sdumbbell * 12296548Sdumbbell * The above copyright notice and this permission notice (including the next 13296548Sdumbbell * paragraph) shall be included in all copies or substantial portions of the 14296548Sdumbbell * Software. 15296548Sdumbbell * 16296548Sdumbbell * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17296548Sdumbbell * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18296548Sdumbbell * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19296548Sdumbbell * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20296548Sdumbbell * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21296548Sdumbbell * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22296548Sdumbbell * DEALINGS IN THE SOFTWARE. 23296548Sdumbbell * 24296548Sdumbbell * Authors: 25296548Sdumbbell * Eric Anholt <eric@anholt.net> 26296548Sdumbbell */ 27296548Sdumbbell 28296548Sdumbbell#include <sys/cdefs.h> 29296548Sdumbbell__FBSDID("$FreeBSD$"); 30296548Sdumbbell 31296548Sdumbbell#include <dev/drm2/drmP.h> 32296548Sdumbbell#include <dev/drm2/drm_crtc.h> 33296548Sdumbbell#include <dev/drm2/i915/intel_drv.h> 34296548Sdumbbell#include <dev/drm2/i915/i915_drm.h> 35296548Sdumbbell#include <dev/drm2/i915/i915_drv.h> 36296548Sdumbbell#include <dev/drm2/i915/dvo.h> 37296548Sdumbbell 38296548Sdumbbell#define SIL164_ADDR 0x38 39296548Sdumbbell#define CH7xxx_ADDR 0x76 40296548Sdumbbell#define TFP410_ADDR 0x38 41296548Sdumbbell#define NS2501_ADDR 0x38 42296548Sdumbbell 43296548Sdumbbellstatic const struct intel_dvo_device intel_dvo_devices[] = { 44296548Sdumbbell { 45296548Sdumbbell .type = INTEL_DVO_CHIP_TMDS, 46296548Sdumbbell .name = "sil164", 47296548Sdumbbell .dvo_reg = DVOC, 48296548Sdumbbell .slave_addr = SIL164_ADDR, 49296548Sdumbbell .dev_ops = &sil164_ops, 50296548Sdumbbell }, 51296548Sdumbbell { 52296548Sdumbbell .type = INTEL_DVO_CHIP_TMDS, 53296548Sdumbbell .name = "ch7xxx", 54296548Sdumbbell .dvo_reg = DVOC, 55296548Sdumbbell .slave_addr = CH7xxx_ADDR, 56296548Sdumbbell .dev_ops = &ch7xxx_ops, 57296548Sdumbbell }, 58296548Sdumbbell { 59296548Sdumbbell .type = INTEL_DVO_CHIP_LVDS, 60296548Sdumbbell .name = "ivch", 61296548Sdumbbell .dvo_reg = DVOA, 62296548Sdumbbell .slave_addr = 0x02, /* Might also be 0x44, 0x84, 0xc4 */ 63296548Sdumbbell .dev_ops = &ivch_ops, 64296548Sdumbbell }, 65296548Sdumbbell { 66296548Sdumbbell .type = INTEL_DVO_CHIP_TMDS, 67296548Sdumbbell .name = "tfp410", 68296548Sdumbbell .dvo_reg = DVOC, 69296548Sdumbbell .slave_addr = TFP410_ADDR, 70296548Sdumbbell .dev_ops = &tfp410_ops, 71296548Sdumbbell }, 72296548Sdumbbell { 73296548Sdumbbell .type = INTEL_DVO_CHIP_LVDS, 74296548Sdumbbell .name = "ch7017", 75296548Sdumbbell .dvo_reg = DVOC, 76296548Sdumbbell .slave_addr = 0x75, 77296548Sdumbbell .gpio = GMBUS_PORT_DPB, 78296548Sdumbbell .dev_ops = &ch7017_ops, 79296548Sdumbbell }, 80296548Sdumbbell { 81296548Sdumbbell .type = INTEL_DVO_CHIP_TMDS, 82296548Sdumbbell .name = "ns2501", 83296548Sdumbbell .dvo_reg = DVOC, 84296548Sdumbbell .slave_addr = NS2501_ADDR, 85296548Sdumbbell .dev_ops = &ns2501_ops, 86296548Sdumbbell } 87296548Sdumbbell}; 88296548Sdumbbell 89296548Sdumbbellstruct intel_dvo { 90296548Sdumbbell struct intel_encoder base; 91296548Sdumbbell 92296548Sdumbbell struct intel_dvo_device dev; 93296548Sdumbbell 94296548Sdumbbell struct drm_display_mode *panel_fixed_mode; 95296548Sdumbbell bool panel_wants_dither; 96296548Sdumbbell}; 97296548Sdumbbell 98296548Sdumbbellstatic struct intel_dvo *enc_to_intel_dvo(struct drm_encoder *encoder) 99296548Sdumbbell{ 100296548Sdumbbell return container_of(encoder, struct intel_dvo, base.base); 101296548Sdumbbell} 102296548Sdumbbell 103296548Sdumbbellstatic struct intel_dvo *intel_attached_dvo(struct drm_connector *connector) 104296548Sdumbbell{ 105296548Sdumbbell return container_of(intel_attached_encoder(connector), 106296548Sdumbbell struct intel_dvo, base); 107296548Sdumbbell} 108296548Sdumbbell 109296548Sdumbbellstatic bool intel_dvo_connector_get_hw_state(struct intel_connector *connector) 110296548Sdumbbell{ 111296548Sdumbbell struct intel_dvo *intel_dvo = intel_attached_dvo(&connector->base); 112296548Sdumbbell 113296548Sdumbbell return intel_dvo->dev.dev_ops->get_hw_state(&intel_dvo->dev); 114296548Sdumbbell} 115296548Sdumbbell 116296548Sdumbbellstatic bool intel_dvo_get_hw_state(struct intel_encoder *encoder, 117296548Sdumbbell enum pipe *pipe) 118296548Sdumbbell{ 119296548Sdumbbell struct drm_device *dev = encoder->base.dev; 120296548Sdumbbell struct drm_i915_private *dev_priv = dev->dev_private; 121296548Sdumbbell struct intel_dvo *intel_dvo = enc_to_intel_dvo(&encoder->base); 122296548Sdumbbell u32 tmp; 123296548Sdumbbell 124296548Sdumbbell tmp = I915_READ(intel_dvo->dev.dvo_reg); 125296548Sdumbbell 126296548Sdumbbell if (!(tmp & DVO_ENABLE)) 127296548Sdumbbell return false; 128296548Sdumbbell 129296548Sdumbbell *pipe = PORT_TO_PIPE(tmp); 130296548Sdumbbell 131296548Sdumbbell return true; 132296548Sdumbbell} 133296548Sdumbbell 134296548Sdumbbellstatic void intel_disable_dvo(struct intel_encoder *encoder) 135296548Sdumbbell{ 136296548Sdumbbell struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; 137296548Sdumbbell struct intel_dvo *intel_dvo = enc_to_intel_dvo(&encoder->base); 138296548Sdumbbell u32 dvo_reg = intel_dvo->dev.dvo_reg; 139296548Sdumbbell u32 temp = I915_READ(dvo_reg); 140296548Sdumbbell 141296548Sdumbbell intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, false); 142296548Sdumbbell I915_WRITE(dvo_reg, temp & ~DVO_ENABLE); 143296548Sdumbbell I915_READ(dvo_reg); 144296548Sdumbbell} 145296548Sdumbbell 146296548Sdumbbellstatic void intel_enable_dvo(struct intel_encoder *encoder) 147296548Sdumbbell{ 148296548Sdumbbell struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; 149296548Sdumbbell struct intel_dvo *intel_dvo = enc_to_intel_dvo(&encoder->base); 150296548Sdumbbell u32 dvo_reg = intel_dvo->dev.dvo_reg; 151296548Sdumbbell u32 temp = I915_READ(dvo_reg); 152296548Sdumbbell 153296548Sdumbbell I915_WRITE(dvo_reg, temp | DVO_ENABLE); 154296548Sdumbbell I915_READ(dvo_reg); 155296548Sdumbbell intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, true); 156296548Sdumbbell} 157296548Sdumbbell 158296548Sdumbbellstatic void intel_dvo_dpms(struct drm_connector *connector, int mode) 159296548Sdumbbell{ 160296548Sdumbbell struct intel_dvo *intel_dvo = intel_attached_dvo(connector); 161296548Sdumbbell struct drm_crtc *crtc; 162296548Sdumbbell 163296548Sdumbbell /* dvo supports only 2 dpms states. */ 164296548Sdumbbell if (mode != DRM_MODE_DPMS_ON) 165296548Sdumbbell mode = DRM_MODE_DPMS_OFF; 166296548Sdumbbell 167296548Sdumbbell if (mode == connector->dpms) 168296548Sdumbbell return; 169296548Sdumbbell 170296548Sdumbbell connector->dpms = mode; 171296548Sdumbbell 172296548Sdumbbell /* Only need to change hw state when actually enabled */ 173296548Sdumbbell crtc = intel_dvo->base.base.crtc; 174296548Sdumbbell if (!crtc) { 175296548Sdumbbell intel_dvo->base.connectors_active = false; 176296548Sdumbbell return; 177296548Sdumbbell } 178296548Sdumbbell 179296548Sdumbbell if (mode == DRM_MODE_DPMS_ON) { 180296548Sdumbbell intel_dvo->base.connectors_active = true; 181296548Sdumbbell 182296548Sdumbbell intel_crtc_update_dpms(crtc); 183296548Sdumbbell 184296548Sdumbbell intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, true); 185296548Sdumbbell } else { 186296548Sdumbbell intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, false); 187296548Sdumbbell 188296548Sdumbbell intel_dvo->base.connectors_active = false; 189296548Sdumbbell 190296548Sdumbbell intel_crtc_update_dpms(crtc); 191296548Sdumbbell } 192296548Sdumbbell 193296548Sdumbbell intel_modeset_check_state(connector->dev); 194296548Sdumbbell} 195296548Sdumbbell 196296548Sdumbbellstatic int intel_dvo_mode_valid(struct drm_connector *connector, 197296548Sdumbbell struct drm_display_mode *mode) 198296548Sdumbbell{ 199296548Sdumbbell struct intel_dvo *intel_dvo = intel_attached_dvo(connector); 200296548Sdumbbell 201296548Sdumbbell if (mode->flags & DRM_MODE_FLAG_DBLSCAN) 202296548Sdumbbell return MODE_NO_DBLESCAN; 203296548Sdumbbell 204296548Sdumbbell /* XXX: Validate clock range */ 205296548Sdumbbell 206296548Sdumbbell if (intel_dvo->panel_fixed_mode) { 207296548Sdumbbell if (mode->hdisplay > intel_dvo->panel_fixed_mode->hdisplay) 208296548Sdumbbell return MODE_PANEL; 209296548Sdumbbell if (mode->vdisplay > intel_dvo->panel_fixed_mode->vdisplay) 210296548Sdumbbell return MODE_PANEL; 211296548Sdumbbell } 212296548Sdumbbell 213296548Sdumbbell return intel_dvo->dev.dev_ops->mode_valid(&intel_dvo->dev, mode); 214296548Sdumbbell} 215296548Sdumbbell 216296548Sdumbbellstatic bool intel_dvo_mode_fixup(struct drm_encoder *encoder, 217296548Sdumbbell const struct drm_display_mode *mode, 218296548Sdumbbell struct drm_display_mode *adjusted_mode) 219296548Sdumbbell{ 220296548Sdumbbell struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder); 221296548Sdumbbell 222296548Sdumbbell /* If we have timings from the BIOS for the panel, put them in 223296548Sdumbbell * to the adjusted mode. The CRTC will be set up for this mode, 224296548Sdumbbell * with the panel scaling set up to source from the H/VDisplay 225296548Sdumbbell * of the original mode. 226296548Sdumbbell */ 227296548Sdumbbell if (intel_dvo->panel_fixed_mode != NULL) { 228296548Sdumbbell#define C(x) adjusted_mode->x = intel_dvo->panel_fixed_mode->x 229296548Sdumbbell C(hdisplay); 230296548Sdumbbell C(hsync_start); 231296548Sdumbbell C(hsync_end); 232296548Sdumbbell C(htotal); 233296548Sdumbbell C(vdisplay); 234296548Sdumbbell C(vsync_start); 235296548Sdumbbell C(vsync_end); 236296548Sdumbbell C(vtotal); 237296548Sdumbbell C(clock); 238296548Sdumbbell#undef C 239296548Sdumbbell } 240296548Sdumbbell 241296548Sdumbbell if (intel_dvo->dev.dev_ops->mode_fixup) 242296548Sdumbbell return intel_dvo->dev.dev_ops->mode_fixup(&intel_dvo->dev, mode, adjusted_mode); 243296548Sdumbbell 244296548Sdumbbell return true; 245296548Sdumbbell} 246296548Sdumbbell 247296548Sdumbbellstatic void intel_dvo_mode_set(struct drm_encoder *encoder, 248296548Sdumbbell struct drm_display_mode *mode, 249296548Sdumbbell struct drm_display_mode *adjusted_mode) 250296548Sdumbbell{ 251296548Sdumbbell struct drm_device *dev = encoder->dev; 252296548Sdumbbell struct drm_i915_private *dev_priv = dev->dev_private; 253296548Sdumbbell struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); 254296548Sdumbbell struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder); 255296548Sdumbbell int pipe = intel_crtc->pipe; 256296548Sdumbbell u32 dvo_val; 257296548Sdumbbell u32 dvo_reg = intel_dvo->dev.dvo_reg, dvo_srcdim_reg; 258296548Sdumbbell int dpll_reg = DPLL(pipe); 259296548Sdumbbell 260296548Sdumbbell switch (dvo_reg) { 261296548Sdumbbell case DVOA: 262296548Sdumbbell default: 263296548Sdumbbell dvo_srcdim_reg = DVOA_SRCDIM; 264296548Sdumbbell break; 265296548Sdumbbell case DVOB: 266296548Sdumbbell dvo_srcdim_reg = DVOB_SRCDIM; 267296548Sdumbbell break; 268296548Sdumbbell case DVOC: 269296548Sdumbbell dvo_srcdim_reg = DVOC_SRCDIM; 270296548Sdumbbell break; 271296548Sdumbbell } 272296548Sdumbbell 273296548Sdumbbell intel_dvo->dev.dev_ops->mode_set(&intel_dvo->dev, mode, adjusted_mode); 274296548Sdumbbell 275296548Sdumbbell /* Save the data order, since I don't know what it should be set to. */ 276296548Sdumbbell dvo_val = I915_READ(dvo_reg) & 277296548Sdumbbell (DVO_PRESERVE_MASK | DVO_DATA_ORDER_GBRG); 278296548Sdumbbell dvo_val |= DVO_DATA_ORDER_FP | DVO_BORDER_ENABLE | 279296548Sdumbbell DVO_BLANK_ACTIVE_HIGH; 280296548Sdumbbell 281296548Sdumbbell if (pipe == 1) 282296548Sdumbbell dvo_val |= DVO_PIPE_B_SELECT; 283296548Sdumbbell dvo_val |= DVO_PIPE_STALL; 284296548Sdumbbell if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) 285296548Sdumbbell dvo_val |= DVO_HSYNC_ACTIVE_HIGH; 286296548Sdumbbell if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) 287296548Sdumbbell dvo_val |= DVO_VSYNC_ACTIVE_HIGH; 288296548Sdumbbell 289296548Sdumbbell I915_WRITE(dpll_reg, I915_READ(dpll_reg) | DPLL_DVO_HIGH_SPEED); 290296548Sdumbbell 291296548Sdumbbell /*I915_WRITE(DVOB_SRCDIM, 292296548Sdumbbell (adjusted_mode->hdisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) | 293296548Sdumbbell (adjusted_mode->VDisplay << DVO_SRCDIM_VERTICAL_SHIFT));*/ 294296548Sdumbbell I915_WRITE(dvo_srcdim_reg, 295296548Sdumbbell (adjusted_mode->hdisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) | 296296548Sdumbbell (adjusted_mode->vdisplay << DVO_SRCDIM_VERTICAL_SHIFT)); 297296548Sdumbbell /*I915_WRITE(DVOB, dvo_val);*/ 298296548Sdumbbell I915_WRITE(dvo_reg, dvo_val); 299296548Sdumbbell} 300296548Sdumbbell 301296548Sdumbbell/** 302296548Sdumbbell * Detect the output connection on our DVO device. 303296548Sdumbbell * 304296548Sdumbbell * Unimplemented. 305296548Sdumbbell */ 306296548Sdumbbellstatic enum drm_connector_status 307296548Sdumbbellintel_dvo_detect(struct drm_connector *connector, bool force) 308296548Sdumbbell{ 309296548Sdumbbell struct intel_dvo *intel_dvo = intel_attached_dvo(connector); 310296548Sdumbbell return intel_dvo->dev.dev_ops->detect(&intel_dvo->dev); 311296548Sdumbbell} 312296548Sdumbbell 313296548Sdumbbellstatic int intel_dvo_get_modes(struct drm_connector *connector) 314296548Sdumbbell{ 315296548Sdumbbell struct intel_dvo *intel_dvo = intel_attached_dvo(connector); 316296548Sdumbbell struct drm_i915_private *dev_priv = connector->dev->dev_private; 317296548Sdumbbell 318296548Sdumbbell /* We should probably have an i2c driver get_modes function for those 319296548Sdumbbell * devices which will have a fixed set of modes determined by the chip 320296548Sdumbbell * (TV-out, for example), but for now with just TMDS and LVDS, 321296548Sdumbbell * that's not the case. 322296548Sdumbbell */ 323296548Sdumbbell intel_ddc_get_modes(connector, 324296548Sdumbbell intel_gmbus_get_adapter(dev_priv, GMBUS_PORT_DPC)); 325296548Sdumbbell if (!list_empty(&connector->probed_modes)) 326296548Sdumbbell return 1; 327296548Sdumbbell 328296548Sdumbbell if (intel_dvo->panel_fixed_mode != NULL) { 329296548Sdumbbell struct drm_display_mode *mode; 330296548Sdumbbell mode = drm_mode_duplicate(connector->dev, intel_dvo->panel_fixed_mode); 331296548Sdumbbell if (mode) { 332296548Sdumbbell drm_mode_probed_add(connector, mode); 333296548Sdumbbell return 1; 334296548Sdumbbell } 335296548Sdumbbell } 336296548Sdumbbell 337296548Sdumbbell return 0; 338296548Sdumbbell} 339296548Sdumbbell 340296548Sdumbbellstatic void intel_dvo_destroy(struct drm_connector *connector) 341296548Sdumbbell{ 342296548Sdumbbell drm_connector_cleanup(connector); 343296548Sdumbbell free(connector, DRM_MEM_KMS); 344296548Sdumbbell} 345296548Sdumbbell 346296548Sdumbbellstatic const struct drm_encoder_helper_funcs intel_dvo_helper_funcs = { 347296548Sdumbbell .mode_fixup = intel_dvo_mode_fixup, 348296548Sdumbbell .mode_set = intel_dvo_mode_set, 349296548Sdumbbell .disable = intel_encoder_noop, 350296548Sdumbbell}; 351296548Sdumbbell 352296548Sdumbbellstatic const struct drm_connector_funcs intel_dvo_connector_funcs = { 353296548Sdumbbell .dpms = intel_dvo_dpms, 354296548Sdumbbell .detect = intel_dvo_detect, 355296548Sdumbbell .destroy = intel_dvo_destroy, 356296548Sdumbbell .fill_modes = drm_helper_probe_single_connector_modes, 357296548Sdumbbell}; 358296548Sdumbbell 359296548Sdumbbellstatic const struct drm_connector_helper_funcs intel_dvo_connector_helper_funcs = { 360296548Sdumbbell .mode_valid = intel_dvo_mode_valid, 361296548Sdumbbell .get_modes = intel_dvo_get_modes, 362296548Sdumbbell .best_encoder = intel_best_encoder, 363296548Sdumbbell}; 364296548Sdumbbell 365296548Sdumbbellstatic void intel_dvo_enc_destroy(struct drm_encoder *encoder) 366296548Sdumbbell{ 367296548Sdumbbell struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder); 368296548Sdumbbell 369296548Sdumbbell if (intel_dvo->dev.dev_ops->destroy) 370296548Sdumbbell intel_dvo->dev.dev_ops->destroy(&intel_dvo->dev); 371296548Sdumbbell 372296548Sdumbbell free(intel_dvo->panel_fixed_mode, DRM_MEM_KMS); 373296548Sdumbbell 374296548Sdumbbell intel_encoder_destroy(encoder); 375296548Sdumbbell} 376296548Sdumbbell 377296548Sdumbbellstatic const struct drm_encoder_funcs intel_dvo_enc_funcs = { 378296548Sdumbbell .destroy = intel_dvo_enc_destroy, 379296548Sdumbbell}; 380296548Sdumbbell 381296548Sdumbbell/** 382296548Sdumbbell * Attempts to get a fixed panel timing for LVDS (currently only the i830). 383296548Sdumbbell * 384296548Sdumbbell * Other chips with DVO LVDS will need to extend this to deal with the LVDS 385296548Sdumbbell * chip being on DVOB/C and having multiple pipes. 386296548Sdumbbell */ 387296548Sdumbbellstatic struct drm_display_mode * 388296548Sdumbbellintel_dvo_get_current_mode(struct drm_connector *connector) 389296548Sdumbbell{ 390296548Sdumbbell struct drm_device *dev = connector->dev; 391296548Sdumbbell struct drm_i915_private *dev_priv = dev->dev_private; 392296548Sdumbbell struct intel_dvo *intel_dvo = intel_attached_dvo(connector); 393296548Sdumbbell uint32_t dvo_val = I915_READ(intel_dvo->dev.dvo_reg); 394296548Sdumbbell struct drm_display_mode *mode = NULL; 395296548Sdumbbell 396296548Sdumbbell /* If the DVO port is active, that'll be the LVDS, so we can pull out 397296548Sdumbbell * its timings to get how the BIOS set up the panel. 398296548Sdumbbell */ 399296548Sdumbbell if (dvo_val & DVO_ENABLE) { 400296548Sdumbbell struct drm_crtc *crtc; 401296548Sdumbbell int pipe = (dvo_val & DVO_PIPE_B_SELECT) ? 1 : 0; 402296548Sdumbbell 403296548Sdumbbell crtc = intel_get_crtc_for_pipe(dev, pipe); 404296548Sdumbbell if (crtc) { 405296548Sdumbbell mode = intel_crtc_mode_get(dev, crtc); 406296548Sdumbbell if (mode) { 407296548Sdumbbell mode->type |= DRM_MODE_TYPE_PREFERRED; 408296548Sdumbbell if (dvo_val & DVO_HSYNC_ACTIVE_HIGH) 409296548Sdumbbell mode->flags |= DRM_MODE_FLAG_PHSYNC; 410296548Sdumbbell if (dvo_val & DVO_VSYNC_ACTIVE_HIGH) 411296548Sdumbbell mode->flags |= DRM_MODE_FLAG_PVSYNC; 412296548Sdumbbell } 413296548Sdumbbell } 414296548Sdumbbell } 415296548Sdumbbell 416296548Sdumbbell return mode; 417296548Sdumbbell} 418296548Sdumbbell 419296548Sdumbbellvoid intel_dvo_init(struct drm_device *dev) 420296548Sdumbbell{ 421296548Sdumbbell struct drm_i915_private *dev_priv = dev->dev_private; 422296548Sdumbbell struct intel_encoder *intel_encoder; 423296548Sdumbbell struct intel_dvo *intel_dvo; 424296548Sdumbbell struct intel_connector *intel_connector; 425296548Sdumbbell int i; 426296548Sdumbbell int encoder_type = DRM_MODE_ENCODER_NONE; 427296548Sdumbbell 428296548Sdumbbell intel_dvo = malloc(sizeof(struct intel_dvo), DRM_MEM_KMS, M_WAITOK | M_ZERO); 429296548Sdumbbell if (!intel_dvo) 430296548Sdumbbell return; 431296548Sdumbbell 432296548Sdumbbell intel_connector = malloc(sizeof(struct intel_connector), DRM_MEM_KMS, M_WAITOK | M_ZERO); 433296548Sdumbbell if (!intel_connector) { 434296548Sdumbbell free(intel_dvo, DRM_MEM_KMS); 435296548Sdumbbell return; 436296548Sdumbbell } 437296548Sdumbbell 438296548Sdumbbell intel_encoder = &intel_dvo->base; 439296548Sdumbbell drm_encoder_init(dev, &intel_encoder->base, 440296548Sdumbbell &intel_dvo_enc_funcs, encoder_type); 441296548Sdumbbell 442296548Sdumbbell intel_encoder->disable = intel_disable_dvo; 443296548Sdumbbell intel_encoder->enable = intel_enable_dvo; 444296548Sdumbbell intel_encoder->get_hw_state = intel_dvo_get_hw_state; 445296548Sdumbbell intel_connector->get_hw_state = intel_dvo_connector_get_hw_state; 446296548Sdumbbell 447296548Sdumbbell /* Now, try to find a controller */ 448296548Sdumbbell for (i = 0; i < ARRAY_SIZE(intel_dvo_devices); i++) { 449296548Sdumbbell struct drm_connector *connector = &intel_connector->base; 450296548Sdumbbell const struct intel_dvo_device *dvo = &intel_dvo_devices[i]; 451296548Sdumbbell device_t i2c; 452296548Sdumbbell int gpio; 453296548Sdumbbell bool dvoinit; 454296548Sdumbbell 455296548Sdumbbell /* Allow the I2C driver info to specify the GPIO to be used in 456296548Sdumbbell * special cases, but otherwise default to what's defined 457296548Sdumbbell * in the spec. 458296548Sdumbbell */ 459296548Sdumbbell if (intel_gmbus_is_port_valid(dvo->gpio)) 460296548Sdumbbell gpio = dvo->gpio; 461296548Sdumbbell else if (dvo->type == INTEL_DVO_CHIP_LVDS) 462296548Sdumbbell gpio = GMBUS_PORT_SSC; 463296548Sdumbbell else 464296548Sdumbbell gpio = GMBUS_PORT_DPB; 465296548Sdumbbell 466296548Sdumbbell /* Set up the I2C bus necessary for the chip we're probing. 467296548Sdumbbell * It appears that everything is on GPIOE except for panels 468296548Sdumbbell * on i830 laptops, which are on GPIOB (DVOA). 469296548Sdumbbell */ 470296548Sdumbbell i2c = intel_gmbus_get_adapter(dev_priv, gpio); 471296548Sdumbbell 472296548Sdumbbell intel_dvo->dev = *dvo; 473296548Sdumbbell 474296548Sdumbbell /* GMBUS NAK handling seems to be unstable, hence let the 475296548Sdumbbell * transmitter detection run in bit banging mode for now. 476296548Sdumbbell */ 477296548Sdumbbell intel_gmbus_force_bit(i2c, true); 478296548Sdumbbell 479296548Sdumbbell dvoinit = dvo->dev_ops->init(&intel_dvo->dev, i2c); 480296548Sdumbbell 481296548Sdumbbell intel_gmbus_force_bit(i2c, false); 482296548Sdumbbell 483296548Sdumbbell if (!dvoinit) 484296548Sdumbbell continue; 485296548Sdumbbell 486296548Sdumbbell intel_encoder->type = INTEL_OUTPUT_DVO; 487296548Sdumbbell intel_encoder->crtc_mask = (1 << 0) | (1 << 1); 488296548Sdumbbell switch (dvo->type) { 489296548Sdumbbell case INTEL_DVO_CHIP_TMDS: 490296548Sdumbbell intel_encoder->cloneable = true; 491296548Sdumbbell drm_connector_init(dev, connector, 492296548Sdumbbell &intel_dvo_connector_funcs, 493296548Sdumbbell DRM_MODE_CONNECTOR_DVII); 494296548Sdumbbell encoder_type = DRM_MODE_ENCODER_TMDS; 495296548Sdumbbell break; 496296548Sdumbbell case INTEL_DVO_CHIP_LVDS: 497296548Sdumbbell intel_encoder->cloneable = false; 498296548Sdumbbell drm_connector_init(dev, connector, 499296548Sdumbbell &intel_dvo_connector_funcs, 500296548Sdumbbell DRM_MODE_CONNECTOR_LVDS); 501296548Sdumbbell encoder_type = DRM_MODE_ENCODER_LVDS; 502296548Sdumbbell break; 503296548Sdumbbell } 504296548Sdumbbell 505296548Sdumbbell drm_connector_helper_add(connector, 506296548Sdumbbell &intel_dvo_connector_helper_funcs); 507296548Sdumbbell connector->display_info.subpixel_order = SubPixelHorizontalRGB; 508296548Sdumbbell connector->interlace_allowed = false; 509296548Sdumbbell connector->doublescan_allowed = false; 510296548Sdumbbell 511296548Sdumbbell drm_encoder_helper_add(&intel_encoder->base, 512296548Sdumbbell &intel_dvo_helper_funcs); 513296548Sdumbbell 514296548Sdumbbell intel_connector_attach_encoder(intel_connector, intel_encoder); 515296548Sdumbbell if (dvo->type == INTEL_DVO_CHIP_LVDS) { 516296548Sdumbbell /* For our LVDS chipsets, we should hopefully be able 517296548Sdumbbell * to dig the fixed panel mode out of the BIOS data. 518296548Sdumbbell * However, it's in a different format from the BIOS 519296548Sdumbbell * data on chipsets with integrated LVDS (stored in AIM 520296548Sdumbbell * headers, likely), so for now, just get the current 521296548Sdumbbell * mode being output through DVO. 522296548Sdumbbell */ 523296548Sdumbbell intel_dvo->panel_fixed_mode = 524296548Sdumbbell intel_dvo_get_current_mode(connector); 525296548Sdumbbell intel_dvo->panel_wants_dither = true; 526296548Sdumbbell } 527296548Sdumbbell 528296548Sdumbbell return; 529296548Sdumbbell } 530296548Sdumbbell 531296548Sdumbbell drm_encoder_cleanup(&intel_encoder->base); 532296548Sdumbbell free(intel_dvo, DRM_MEM_KMS); 533296548Sdumbbell free(intel_connector, DRM_MEM_KMS); 534296548Sdumbbell} 535