1235783Skib/* 2235783Skib * Copyright 2006 Dave Airlie <airlied@linux.ie> 3235783Skib * Copyright �� 2006-2009 Intel Corporation 4235783Skib * 5235783Skib * Permission is hereby granted, free of charge, to any person obtaining a 6235783Skib * copy of this software and associated documentation files (the "Software"), 7235783Skib * to deal in the Software without restriction, including without limitation 8235783Skib * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9235783Skib * and/or sell copies of the Software, and to permit persons to whom the 10235783Skib * Software is furnished to do so, subject to the following conditions: 11235783Skib * 12235783Skib * The above copyright notice and this permission notice (including the next 13235783Skib * paragraph) shall be included in all copies or substantial portions of the 14235783Skib * Software. 15235783Skib * 16235783Skib * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17235783Skib * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18235783Skib * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19235783Skib * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20235783Skib * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21235783Skib * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22235783Skib * DEALINGS IN THE SOFTWARE. 23235783Skib * 24235783Skib * Authors: 25235783Skib * Eric Anholt <eric@anholt.net> 26235783Skib * Jesse Barnes <jesse.barnes@intel.com> 27235783Skib */ 28235783Skib 29235783Skib#include <sys/cdefs.h> 30235783Skib__FBSDID("$FreeBSD: releng/10.3/sys/dev/drm2/i915/intel_hdmi.c 282199 2015-04-28 19:35:05Z dumbbell $"); 31235783Skib 32235783Skib#include <dev/drm2/drmP.h> 33235783Skib#include <dev/drm2/drm.h> 34235783Skib#include <dev/drm2/drm_crtc.h> 35235783Skib#include <dev/drm2/drm_edid.h> 36235783Skib#include <dev/drm2/i915/i915_drm.h> 37235783Skib#include <dev/drm2/i915/i915_drv.h> 38235783Skib#include <dev/drm2/i915/intel_drv.h> 39235783Skib 40280369Skibstruct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder) 41235783Skib{ 42235783Skib return container_of(encoder, struct intel_hdmi, base.base); 43235783Skib} 44235783Skib 45235783Skibstatic struct intel_hdmi *intel_attached_hdmi(struct drm_connector *connector) 46235783Skib{ 47235783Skib return container_of(intel_attached_encoder(connector), 48235783Skib struct intel_hdmi, base); 49235783Skib} 50235783Skib 51235783Skibvoid intel_dip_infoframe_csum(struct dip_infoframe *frame) 52235783Skib{ 53235783Skib uint8_t *data = (uint8_t *)frame; 54235783Skib uint8_t sum = 0; 55235783Skib unsigned i; 56235783Skib 57235783Skib frame->checksum = 0; 58235783Skib frame->ecc = 0; 59235783Skib 60235783Skib for (i = 0; i < frame->len + DIP_HEADER_SIZE; i++) 61235783Skib sum += data[i]; 62235783Skib 63235783Skib frame->checksum = 0x100 - sum; 64235783Skib} 65235783Skib 66280369Skibstatic u32 g4x_infoframe_index(struct dip_infoframe *frame) 67235783Skib{ 68280369Skib switch (frame->type) { 69280369Skib case DIP_TYPE_AVI: 70280369Skib return VIDEO_DIP_SELECT_AVI; 71280369Skib case DIP_TYPE_SPD: 72280369Skib return VIDEO_DIP_SELECT_SPD; 73280369Skib default: 74280369Skib DRM_DEBUG_DRIVER("unknown info frame type %d\n", frame->type); 75280369Skib return 0; 76280369Skib } 77280369Skib} 78235783Skib 79280369Skibstatic u32 g4x_infoframe_enable(struct dip_infoframe *frame) 80280369Skib{ 81235783Skib switch (frame->type) { 82235783Skib case DIP_TYPE_AVI: 83280369Skib return VIDEO_DIP_ENABLE_AVI; 84235783Skib case DIP_TYPE_SPD: 85280369Skib return VIDEO_DIP_ENABLE_SPD; 86235783Skib default: 87280369Skib DRM_DEBUG_DRIVER("unknown info frame type %d\n", frame->type); 88280369Skib return 0; 89235783Skib } 90280369Skib} 91235783Skib 92280369Skibstatic u32 hsw_infoframe_enable(struct dip_infoframe *frame) 93280369Skib{ 94280369Skib switch (frame->type) { 95280369Skib case DIP_TYPE_AVI: 96280369Skib return VIDEO_DIP_ENABLE_AVI_HSW; 97280369Skib case DIP_TYPE_SPD: 98280369Skib return VIDEO_DIP_ENABLE_SPD_HSW; 99280369Skib default: 100280369Skib DRM_DEBUG_DRIVER("unknown info frame type %d\n", frame->type); 101280369Skib return 0; 102280369Skib } 103235783Skib} 104235783Skib 105280369Skibstatic u32 hsw_infoframe_data_reg(struct dip_infoframe *frame, enum pipe pipe) 106235783Skib{ 107235783Skib switch (frame->type) { 108235783Skib case DIP_TYPE_AVI: 109280369Skib return HSW_TVIDEO_DIP_AVI_DATA(pipe); 110235783Skib case DIP_TYPE_SPD: 111280369Skib return HSW_TVIDEO_DIP_SPD_DATA(pipe); 112235783Skib default: 113280369Skib DRM_DEBUG_DRIVER("unknown info frame type %d\n", frame->type); 114280369Skib return 0; 115235783Skib } 116235783Skib} 117235783Skib 118280369Skibstatic void g4x_write_infoframe(struct drm_encoder *encoder, 119280369Skib struct dip_infoframe *frame) 120235783Skib{ 121235783Skib uint32_t *data = (uint32_t *)frame; 122235783Skib struct drm_device *dev = encoder->dev; 123235783Skib struct drm_i915_private *dev_priv = dev->dev_private; 124235783Skib struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); 125280369Skib u32 val = I915_READ(VIDEO_DIP_CTL); 126235783Skib unsigned i, len = DIP_HEADER_SIZE + frame->len; 127235783Skib 128280369Skib val &= ~VIDEO_DIP_PORT_MASK; 129235783Skib if (intel_hdmi->sdvox_reg == SDVOB) 130280369Skib val |= VIDEO_DIP_PORT_B; 131235783Skib else if (intel_hdmi->sdvox_reg == SDVOC) 132280369Skib val |= VIDEO_DIP_PORT_C; 133235783Skib else 134235783Skib return; 135235783Skib 136280369Skib val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ 137280369Skib val |= g4x_infoframe_index(frame); 138235783Skib 139280369Skib val &= ~g4x_infoframe_enable(frame); 140280369Skib val |= VIDEO_DIP_ENABLE; 141235783Skib 142280369Skib I915_WRITE(VIDEO_DIP_CTL, val); 143235783Skib 144235783Skib for (i = 0; i < len; i += 4) { 145235783Skib I915_WRITE(VIDEO_DIP_DATA, *data); 146235783Skib data++; 147235783Skib } 148235783Skib 149280369Skib val |= g4x_infoframe_enable(frame); 150280369Skib val &= ~VIDEO_DIP_FREQ_MASK; 151280369Skib val |= VIDEO_DIP_FREQ_VSYNC; 152235783Skib 153280369Skib I915_WRITE(VIDEO_DIP_CTL, val); 154235783Skib} 155235783Skib 156280369Skibstatic void ibx_write_infoframe(struct drm_encoder *encoder, 157280369Skib struct dip_infoframe *frame) 158235783Skib{ 159235783Skib uint32_t *data = (uint32_t *)frame; 160235783Skib struct drm_device *dev = encoder->dev; 161235783Skib struct drm_i915_private *dev_priv = dev->dev_private; 162280369Skib struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); 163280369Skib struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); 164235783Skib int reg = TVIDEO_DIP_CTL(intel_crtc->pipe); 165235783Skib unsigned i, len = DIP_HEADER_SIZE + frame->len; 166280369Skib u32 val = I915_READ(reg); 167235783Skib 168280369Skib val &= ~VIDEO_DIP_PORT_MASK; 169280369Skib switch (intel_hdmi->sdvox_reg) { 170280369Skib case HDMIB: 171280369Skib val |= VIDEO_DIP_PORT_B; 172280369Skib break; 173280369Skib case HDMIC: 174280369Skib val |= VIDEO_DIP_PORT_C; 175280369Skib break; 176280369Skib case HDMID: 177280369Skib val |= VIDEO_DIP_PORT_D; 178280369Skib break; 179280369Skib default: 180280369Skib return; 181280369Skib } 182280369Skib 183235783Skib intel_wait_for_vblank(dev, intel_crtc->pipe); 184235783Skib 185280369Skib val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ 186280369Skib val |= g4x_infoframe_index(frame); 187235783Skib 188280369Skib val &= ~g4x_infoframe_enable(frame); 189280369Skib val |= VIDEO_DIP_ENABLE; 190280369Skib 191280369Skib I915_WRITE(reg, val); 192280369Skib 193280369Skib for (i = 0; i < len; i += 4) { 194280369Skib I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), *data); 195280369Skib data++; 196280369Skib } 197280369Skib 198280369Skib val |= g4x_infoframe_enable(frame); 199280369Skib val &= ~VIDEO_DIP_FREQ_MASK; 200280369Skib val |= VIDEO_DIP_FREQ_VSYNC; 201280369Skib 202280369Skib I915_WRITE(reg, val); 203280369Skib} 204280369Skib 205280369Skibstatic void cpt_write_infoframe(struct drm_encoder *encoder, 206280369Skib struct dip_infoframe *frame) 207280369Skib{ 208280369Skib uint32_t *data = (uint32_t *)frame; 209280369Skib struct drm_device *dev = encoder->dev; 210280369Skib struct drm_i915_private *dev_priv = dev->dev_private; 211280369Skib struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); 212280369Skib int reg = TVIDEO_DIP_CTL(intel_crtc->pipe); 213280369Skib unsigned i, len = DIP_HEADER_SIZE + frame->len; 214280369Skib u32 val = I915_READ(reg); 215280369Skib 216280369Skib intel_wait_for_vblank(dev, intel_crtc->pipe); 217280369Skib 218235783Skib val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ 219280369Skib val |= g4x_infoframe_index(frame); 220235783Skib 221280369Skib /* The DIP control register spec says that we need to update the AVI 222280369Skib * infoframe without clearing its enable bit */ 223280369Skib if (frame->type == DIP_TYPE_AVI) 224280369Skib val |= VIDEO_DIP_ENABLE_AVI; 225280369Skib else 226280369Skib val &= ~g4x_infoframe_enable(frame); 227235783Skib 228280369Skib val |= VIDEO_DIP_ENABLE; 229280369Skib 230280369Skib I915_WRITE(reg, val); 231280369Skib 232235783Skib for (i = 0; i < len; i += 4) { 233235783Skib I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), *data); 234235783Skib data++; 235235783Skib } 236235783Skib 237280369Skib val |= g4x_infoframe_enable(frame); 238280369Skib val &= ~VIDEO_DIP_FREQ_MASK; 239280369Skib val |= VIDEO_DIP_FREQ_VSYNC; 240235783Skib 241280369Skib I915_WRITE(reg, val); 242235783Skib} 243235783Skib 244280369Skibstatic void vlv_write_infoframe(struct drm_encoder *encoder, 245280369Skib struct dip_infoframe *frame) 246280369Skib{ 247280369Skib uint32_t *data = (uint32_t *)frame; 248280369Skib struct drm_device *dev = encoder->dev; 249280369Skib struct drm_i915_private *dev_priv = dev->dev_private; 250280369Skib struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); 251280369Skib int reg = VLV_TVIDEO_DIP_CTL(intel_crtc->pipe); 252280369Skib unsigned i, len = DIP_HEADER_SIZE + frame->len; 253280369Skib u32 val = I915_READ(reg); 254280369Skib 255280369Skib intel_wait_for_vblank(dev, intel_crtc->pipe); 256280369Skib 257280369Skib val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ 258280369Skib val |= g4x_infoframe_index(frame); 259280369Skib 260280369Skib val &= ~g4x_infoframe_enable(frame); 261280369Skib val |= VIDEO_DIP_ENABLE; 262280369Skib 263280369Skib I915_WRITE(reg, val); 264280369Skib 265280369Skib for (i = 0; i < len; i += 4) { 266280369Skib I915_WRITE(VLV_TVIDEO_DIP_DATA(intel_crtc->pipe), *data); 267280369Skib data++; 268280369Skib } 269280369Skib 270280369Skib val |= g4x_infoframe_enable(frame); 271280369Skib val &= ~VIDEO_DIP_FREQ_MASK; 272280369Skib val |= VIDEO_DIP_FREQ_VSYNC; 273280369Skib 274280369Skib I915_WRITE(reg, val); 275280369Skib} 276280369Skib 277280369Skibstatic void hsw_write_infoframe(struct drm_encoder *encoder, 278280369Skib struct dip_infoframe *frame) 279280369Skib{ 280280369Skib uint32_t *data = (uint32_t *)frame; 281280369Skib struct drm_device *dev = encoder->dev; 282280369Skib struct drm_i915_private *dev_priv = dev->dev_private; 283280369Skib struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); 284280369Skib u32 ctl_reg = HSW_TVIDEO_DIP_CTL(intel_crtc->pipe); 285280369Skib u32 data_reg = hsw_infoframe_data_reg(frame, intel_crtc->pipe); 286280369Skib unsigned int i, len = DIP_HEADER_SIZE + frame->len; 287280369Skib u32 val = I915_READ(ctl_reg); 288280369Skib 289280369Skib if (data_reg == 0) 290280369Skib return; 291280369Skib 292280369Skib intel_wait_for_vblank(dev, intel_crtc->pipe); 293280369Skib 294280369Skib val &= ~hsw_infoframe_enable(frame); 295280369Skib I915_WRITE(ctl_reg, val); 296280369Skib 297280369Skib for (i = 0; i < len; i += 4) { 298280369Skib I915_WRITE(data_reg + i, *data); 299280369Skib data++; 300280369Skib } 301280369Skib 302280369Skib val |= hsw_infoframe_enable(frame); 303280369Skib I915_WRITE(ctl_reg, val); 304280369Skib} 305280369Skib 306235783Skibstatic void intel_set_infoframe(struct drm_encoder *encoder, 307235783Skib struct dip_infoframe *frame) 308235783Skib{ 309235783Skib struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); 310235783Skib 311235783Skib if (!intel_hdmi->has_hdmi_sink) 312235783Skib return; 313235783Skib 314235783Skib intel_dip_infoframe_csum(frame); 315235783Skib intel_hdmi->write_infoframe(encoder, frame); 316235783Skib} 317235783Skib 318280369Skibvoid intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder, 319280369Skib struct drm_display_mode *adjusted_mode) 320235783Skib{ 321235783Skib struct dip_infoframe avi_if = { 322235783Skib .type = DIP_TYPE_AVI, 323235783Skib .ver = DIP_VERSION_AVI, 324235783Skib .len = DIP_LEN_AVI, 325235783Skib }; 326235783Skib 327280369Skib if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK) 328280369Skib avi_if.body.avi.YQ_CN_PR |= DIP_AVI_PR_2; 329280369Skib 330235783Skib intel_set_infoframe(encoder, &avi_if); 331235783Skib} 332235783Skib 333280369Skibvoid intel_hdmi_set_spd_infoframe(struct drm_encoder *encoder) 334235783Skib{ 335235783Skib struct dip_infoframe spd_if; 336235783Skib 337235783Skib memset(&spd_if, 0, sizeof(spd_if)); 338235783Skib spd_if.type = DIP_TYPE_SPD; 339235783Skib spd_if.ver = DIP_VERSION_SPD; 340235783Skib spd_if.len = DIP_LEN_SPD; 341235783Skib strcpy(spd_if.body.spd.vn, "Intel"); 342235783Skib strcpy(spd_if.body.spd.pd, "Integrated gfx"); 343235783Skib spd_if.body.spd.sdi = DIP_SPD_PC; 344235783Skib 345235783Skib intel_set_infoframe(encoder, &spd_if); 346235783Skib} 347235783Skib 348235783Skibstatic void intel_hdmi_mode_set(struct drm_encoder *encoder, 349235783Skib struct drm_display_mode *mode, 350235783Skib struct drm_display_mode *adjusted_mode) 351235783Skib{ 352235783Skib struct drm_device *dev = encoder->dev; 353235783Skib struct drm_i915_private *dev_priv = dev->dev_private; 354280369Skib struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); 355235783Skib struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); 356235783Skib u32 sdvox; 357235783Skib 358235783Skib sdvox = SDVO_ENCODING_HDMI | SDVO_BORDER_ENABLE; 359235783Skib if (!HAS_PCH_SPLIT(dev)) 360235783Skib sdvox |= intel_hdmi->color_range; 361235783Skib if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) 362235783Skib sdvox |= SDVO_VSYNC_ACTIVE_HIGH; 363235783Skib if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) 364235783Skib sdvox |= SDVO_HSYNC_ACTIVE_HIGH; 365235783Skib 366235783Skib if (intel_crtc->bpp > 24) 367235783Skib sdvox |= COLOR_FORMAT_12bpc; 368235783Skib else 369235783Skib sdvox |= COLOR_FORMAT_8bpc; 370235783Skib 371235783Skib /* Required on CPT */ 372235783Skib if (intel_hdmi->has_hdmi_sink && HAS_PCH_CPT(dev)) 373235783Skib sdvox |= HDMI_MODE_SELECT; 374235783Skib 375235783Skib if (intel_hdmi->has_audio) { 376235783Skib DRM_DEBUG_KMS("Enabling HDMI audio on pipe %c\n", 377235783Skib pipe_name(intel_crtc->pipe)); 378235783Skib sdvox |= SDVO_AUDIO_ENABLE; 379235783Skib sdvox |= SDVO_NULL_PACKETS_DURING_VSYNC; 380235783Skib intel_write_eld(encoder, adjusted_mode); 381235783Skib } 382235783Skib 383235783Skib if (HAS_PCH_CPT(dev)) 384235783Skib sdvox |= PORT_TRANS_SEL_CPT(intel_crtc->pipe); 385235783Skib else if (intel_crtc->pipe == 1) 386235783Skib sdvox |= SDVO_PIPE_B_SELECT; 387235783Skib 388235783Skib I915_WRITE(intel_hdmi->sdvox_reg, sdvox); 389235783Skib POSTING_READ(intel_hdmi->sdvox_reg); 390235783Skib 391280369Skib intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); 392235783Skib intel_hdmi_set_spd_infoframe(encoder); 393235783Skib} 394235783Skib 395235783Skibstatic void intel_hdmi_dpms(struct drm_encoder *encoder, int mode) 396235783Skib{ 397235783Skib struct drm_device *dev = encoder->dev; 398235783Skib struct drm_i915_private *dev_priv = dev->dev_private; 399235783Skib struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); 400235783Skib u32 temp; 401235783Skib u32 enable_bits = SDVO_ENABLE; 402235783Skib 403235783Skib if (intel_hdmi->has_audio) 404235783Skib enable_bits |= SDVO_AUDIO_ENABLE; 405235783Skib 406235783Skib temp = I915_READ(intel_hdmi->sdvox_reg); 407235783Skib 408235783Skib /* HW workaround, need to toggle enable bit off and on for 12bpc, but 409235783Skib * we do this anyway which shows more stable in testing. 410235783Skib */ 411235783Skib if (HAS_PCH_SPLIT(dev)) { 412235783Skib I915_WRITE(intel_hdmi->sdvox_reg, temp & ~SDVO_ENABLE); 413235783Skib POSTING_READ(intel_hdmi->sdvox_reg); 414235783Skib } 415235783Skib 416235783Skib if (mode != DRM_MODE_DPMS_ON) { 417235783Skib temp &= ~enable_bits; 418235783Skib } else { 419235783Skib temp |= enable_bits; 420235783Skib } 421235783Skib 422235783Skib I915_WRITE(intel_hdmi->sdvox_reg, temp); 423235783Skib POSTING_READ(intel_hdmi->sdvox_reg); 424235783Skib 425235783Skib /* HW workaround, need to write this twice for issue that may result 426235783Skib * in first write getting masked. 427235783Skib */ 428235783Skib if (HAS_PCH_SPLIT(dev)) { 429235783Skib I915_WRITE(intel_hdmi->sdvox_reg, temp); 430235783Skib POSTING_READ(intel_hdmi->sdvox_reg); 431235783Skib } 432235783Skib} 433235783Skib 434235783Skibstatic int intel_hdmi_mode_valid(struct drm_connector *connector, 435235783Skib struct drm_display_mode *mode) 436235783Skib{ 437235783Skib if (mode->clock > 165000) 438235783Skib return MODE_CLOCK_HIGH; 439235783Skib if (mode->clock < 20000) 440235783Skib return MODE_CLOCK_LOW; 441235783Skib 442235783Skib if (mode->flags & DRM_MODE_FLAG_DBLSCAN) 443235783Skib return MODE_NO_DBLESCAN; 444235783Skib 445235783Skib return MODE_OK; 446235783Skib} 447235783Skib 448235783Skibstatic bool intel_hdmi_mode_fixup(struct drm_encoder *encoder, 449282199Sdumbbell const struct drm_display_mode *mode, 450235783Skib struct drm_display_mode *adjusted_mode) 451235783Skib{ 452235783Skib return true; 453235783Skib} 454235783Skib 455235783Skibstatic enum drm_connector_status 456235783Skibintel_hdmi_detect(struct drm_connector *connector, bool force) 457235783Skib{ 458235783Skib struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); 459235783Skib struct drm_i915_private *dev_priv = connector->dev->dev_private; 460235783Skib struct edid *edid; 461235783Skib enum drm_connector_status status = connector_status_disconnected; 462235783Skib 463235783Skib intel_hdmi->has_hdmi_sink = false; 464235783Skib intel_hdmi->has_audio = false; 465280369Skib edid = drm_get_edid(connector, intel_gmbus_get_adapter(dev_priv, 466280369Skib intel_hdmi->ddc_bus)); 467235783Skib 468235783Skib if (edid) { 469235783Skib if (edid->input & DRM_EDID_INPUT_DIGITAL) { 470235783Skib status = connector_status_connected; 471235783Skib if (intel_hdmi->force_audio != HDMI_AUDIO_OFF_DVI) 472235783Skib intel_hdmi->has_hdmi_sink = 473235783Skib drm_detect_hdmi_monitor(edid); 474235783Skib intel_hdmi->has_audio = drm_detect_monitor_audio(edid); 475235783Skib } 476235783Skib free(edid, DRM_MEM_KMS); 477235783Skib } else { 478235783Skib DRM_DEBUG_KMS("[CONNECTOR:%d:%s] got no edid, ddc port %d\n", 479235783Skib connector->base.id, drm_get_connector_name(connector), 480235783Skib intel_hdmi->ddc_bus); 481235783Skib } 482235783Skib 483235783Skib if (status == connector_status_connected) { 484235783Skib if (intel_hdmi->force_audio != HDMI_AUDIO_AUTO) 485235783Skib intel_hdmi->has_audio = 486235783Skib (intel_hdmi->force_audio == HDMI_AUDIO_ON); 487235783Skib } 488235783Skib 489235783Skib return status; 490235783Skib} 491235783Skib 492235783Skibstatic int intel_hdmi_get_modes(struct drm_connector *connector) 493235783Skib{ 494235783Skib struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); 495235783Skib struct drm_i915_private *dev_priv = connector->dev->dev_private; 496235783Skib 497235783Skib /* We should parse the EDID data and find out if it's an HDMI sink so 498235783Skib * we can send audio to it. 499235783Skib */ 500235783Skib 501235783Skib return intel_ddc_get_modes(connector, 502280369Skib intel_gmbus_get_adapter(dev_priv, 503280369Skib intel_hdmi->ddc_bus)); 504235783Skib} 505235783Skib 506235783Skibstatic bool 507235783Skibintel_hdmi_detect_audio(struct drm_connector *connector) 508235783Skib{ 509235783Skib struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); 510235783Skib struct drm_i915_private *dev_priv = connector->dev->dev_private; 511235783Skib struct edid *edid; 512235783Skib bool has_audio = false; 513235783Skib 514280369Skib edid = drm_get_edid(connector, 515280369Skib intel_gmbus_get_adapter(dev_priv, 516280369Skib intel_hdmi->ddc_bus)); 517235783Skib if (edid) { 518235783Skib if (edid->input & DRM_EDID_INPUT_DIGITAL) 519235783Skib has_audio = drm_detect_monitor_audio(edid); 520235783Skib 521235783Skib free(edid, DRM_MEM_KMS); 522235783Skib } 523235783Skib 524235783Skib return has_audio; 525235783Skib} 526235783Skib 527235783Skibstatic int 528235783Skibintel_hdmi_set_property(struct drm_connector *connector, 529235783Skib struct drm_property *property, 530235783Skib uint64_t val) 531235783Skib{ 532235783Skib struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); 533235783Skib struct drm_i915_private *dev_priv = connector->dev->dev_private; 534235783Skib int ret; 535235783Skib 536282199Sdumbbell ret = drm_object_property_set_value(&connector->base, property, val); 537235783Skib if (ret) 538235783Skib return ret; 539235783Skib 540235783Skib if (property == dev_priv->force_audio_property) { 541235783Skib enum hdmi_force_audio i = val; 542235783Skib bool has_audio; 543235783Skib 544235783Skib if (i == intel_hdmi->force_audio) 545235783Skib return 0; 546235783Skib 547235783Skib intel_hdmi->force_audio = i; 548235783Skib 549235783Skib if (i == HDMI_AUDIO_AUTO) 550235783Skib has_audio = intel_hdmi_detect_audio(connector); 551235783Skib else 552235783Skib has_audio = (i == HDMI_AUDIO_ON); 553235783Skib 554235783Skib if (i == HDMI_AUDIO_OFF_DVI) 555235783Skib intel_hdmi->has_hdmi_sink = 0; 556235783Skib 557235783Skib intel_hdmi->has_audio = has_audio; 558235783Skib goto done; 559235783Skib } 560235783Skib 561235783Skib if (property == dev_priv->broadcast_rgb_property) { 562235783Skib if (val == !!intel_hdmi->color_range) 563235783Skib return 0; 564235783Skib 565235783Skib intel_hdmi->color_range = val ? SDVO_COLOR_RANGE_16_235 : 0; 566235783Skib goto done; 567235783Skib } 568235783Skib 569235783Skib return -EINVAL; 570235783Skib 571235783Skibdone: 572235783Skib if (intel_hdmi->base.base.crtc) { 573235783Skib struct drm_crtc *crtc = intel_hdmi->base.base.crtc; 574235783Skib drm_crtc_helper_set_mode(crtc, &crtc->mode, 575235783Skib crtc->x, crtc->y, 576235783Skib crtc->fb); 577235783Skib } 578235783Skib 579235783Skib return 0; 580235783Skib} 581235783Skib 582235783Skibstatic void intel_hdmi_destroy(struct drm_connector *connector) 583235783Skib{ 584235783Skib#if 0 585235783Skib drm_sysfs_connector_remove(connector); 586235783Skib#endif 587235783Skib drm_connector_cleanup(connector); 588235783Skib free(connector, DRM_MEM_KMS); 589235783Skib} 590235783Skib 591280369Skibstatic const struct drm_encoder_helper_funcs intel_hdmi_helper_funcs_hsw = { 592280369Skib .dpms = intel_ddi_dpms, 593280369Skib .mode_fixup = intel_hdmi_mode_fixup, 594280369Skib .prepare = intel_encoder_prepare, 595280369Skib .mode_set = intel_ddi_mode_set, 596280369Skib .commit = intel_encoder_commit, 597280369Skib}; 598280369Skib 599235783Skibstatic const struct drm_encoder_helper_funcs intel_hdmi_helper_funcs = { 600235783Skib .dpms = intel_hdmi_dpms, 601235783Skib .mode_fixup = intel_hdmi_mode_fixup, 602235783Skib .prepare = intel_encoder_prepare, 603235783Skib .mode_set = intel_hdmi_mode_set, 604235783Skib .commit = intel_encoder_commit, 605235783Skib}; 606235783Skib 607235783Skibstatic const struct drm_connector_funcs intel_hdmi_connector_funcs = { 608235783Skib .dpms = drm_helper_connector_dpms, 609235783Skib .detect = intel_hdmi_detect, 610235783Skib .fill_modes = drm_helper_probe_single_connector_modes, 611235783Skib .set_property = intel_hdmi_set_property, 612235783Skib .destroy = intel_hdmi_destroy, 613235783Skib}; 614235783Skib 615235783Skibstatic const struct drm_connector_helper_funcs intel_hdmi_connector_helper_funcs = { 616235783Skib .get_modes = intel_hdmi_get_modes, 617235783Skib .mode_valid = intel_hdmi_mode_valid, 618235783Skib .best_encoder = intel_best_encoder, 619235783Skib}; 620235783Skib 621235783Skibstatic const struct drm_encoder_funcs intel_hdmi_enc_funcs = { 622235783Skib .destroy = intel_encoder_destroy, 623235783Skib}; 624235783Skib 625235783Skibstatic void 626235783Skibintel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *connector) 627235783Skib{ 628235783Skib intel_attach_force_audio_property(connector); 629235783Skib intel_attach_broadcast_rgb_property(connector); 630235783Skib} 631235783Skib 632235783Skibvoid intel_hdmi_init(struct drm_device *dev, int sdvox_reg) 633235783Skib{ 634235783Skib struct drm_i915_private *dev_priv = dev->dev_private; 635235783Skib struct drm_connector *connector; 636235783Skib struct intel_encoder *intel_encoder; 637235783Skib struct intel_connector *intel_connector; 638235783Skib struct intel_hdmi *intel_hdmi; 639235783Skib int i; 640235783Skib 641235783Skib intel_hdmi = malloc(sizeof(struct intel_hdmi), DRM_MEM_KMS, 642235783Skib M_WAITOK | M_ZERO); 643235783Skib intel_connector = malloc(sizeof(struct intel_connector), DRM_MEM_KMS, 644235783Skib M_WAITOK | M_ZERO); 645235783Skib 646235783Skib intel_encoder = &intel_hdmi->base; 647235783Skib drm_encoder_init(dev, &intel_encoder->base, &intel_hdmi_enc_funcs, 648235783Skib DRM_MODE_ENCODER_TMDS); 649235783Skib 650235783Skib connector = &intel_connector->base; 651235783Skib drm_connector_init(dev, connector, &intel_hdmi_connector_funcs, 652235783Skib DRM_MODE_CONNECTOR_HDMIA); 653235783Skib drm_connector_helper_add(connector, &intel_hdmi_connector_helper_funcs); 654235783Skib 655235783Skib intel_encoder->type = INTEL_OUTPUT_HDMI; 656235783Skib 657235783Skib connector->polled = DRM_CONNECTOR_POLL_HPD; 658235783Skib connector->interlace_allowed = 1; 659235783Skib connector->doublescan_allowed = 0; 660235783Skib intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); 661235783Skib 662235783Skib /* Set up the DDC bus. */ 663235783Skib if (sdvox_reg == SDVOB) { 664235783Skib intel_encoder->clone_mask = (1 << INTEL_HDMIB_CLONE_BIT); 665235783Skib intel_hdmi->ddc_bus = GMBUS_PORT_DPB; 666235783Skib dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS; 667235783Skib } else if (sdvox_reg == SDVOC) { 668235783Skib intel_encoder->clone_mask = (1 << INTEL_HDMIC_CLONE_BIT); 669235783Skib intel_hdmi->ddc_bus = GMBUS_PORT_DPC; 670235783Skib dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS; 671235783Skib } else if (sdvox_reg == HDMIB) { 672235783Skib intel_encoder->clone_mask = (1 << INTEL_HDMID_CLONE_BIT); 673235783Skib intel_hdmi->ddc_bus = GMBUS_PORT_DPB; 674235783Skib dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS; 675235783Skib } else if (sdvox_reg == HDMIC) { 676235783Skib intel_encoder->clone_mask = (1 << INTEL_HDMIE_CLONE_BIT); 677235783Skib intel_hdmi->ddc_bus = GMBUS_PORT_DPC; 678235783Skib dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS; 679235783Skib } else if (sdvox_reg == HDMID) { 680235783Skib intel_encoder->clone_mask = (1 << INTEL_HDMIF_CLONE_BIT); 681235783Skib intel_hdmi->ddc_bus = GMBUS_PORT_DPD; 682235783Skib dev_priv->hotplug_supported_mask |= HDMID_HOTPLUG_INT_STATUS; 683280369Skib } else if (sdvox_reg == DDI_BUF_CTL(PORT_B)) { 684280369Skib DRM_DEBUG_DRIVER("LPT: detected output on DDI B\n"); 685280369Skib intel_encoder->clone_mask = (1 << INTEL_HDMIB_CLONE_BIT); 686280369Skib intel_hdmi->ddc_bus = GMBUS_PORT_DPB; 687280369Skib intel_hdmi->ddi_port = PORT_B; 688280369Skib dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS; 689280369Skib } else if (sdvox_reg == DDI_BUF_CTL(PORT_C)) { 690280369Skib DRM_DEBUG_DRIVER("LPT: detected output on DDI C\n"); 691280369Skib intel_encoder->clone_mask = (1 << INTEL_HDMIC_CLONE_BIT); 692280369Skib intel_hdmi->ddc_bus = GMBUS_PORT_DPC; 693280369Skib intel_hdmi->ddi_port = PORT_C; 694280369Skib dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS; 695280369Skib } else if (sdvox_reg == DDI_BUF_CTL(PORT_D)) { 696280369Skib DRM_DEBUG_DRIVER("LPT: detected output on DDI D\n"); 697280369Skib intel_encoder->clone_mask = (1 << INTEL_HDMID_CLONE_BIT); 698280369Skib intel_hdmi->ddc_bus = GMBUS_PORT_DPD; 699280369Skib intel_hdmi->ddi_port = PORT_D; 700280369Skib dev_priv->hotplug_supported_mask |= HDMID_HOTPLUG_INT_STATUS; 701280369Skib } else { 702280369Skib /* If we got an unknown sdvox_reg, things are pretty much broken 703280369Skib * in a way that we should let the kernel know about it */ 704280369Skib DRM_DEBUG_KMS("unknown sdvox_reg %d\n", sdvox_reg); 705235783Skib } 706235783Skib 707235783Skib intel_hdmi->sdvox_reg = sdvox_reg; 708235783Skib if (!HAS_PCH_SPLIT(dev)) { 709280369Skib intel_hdmi->write_infoframe = g4x_write_infoframe; 710235783Skib I915_WRITE(VIDEO_DIP_CTL, 0); 711280369Skib } else if (IS_VALLEYVIEW(dev)) { 712280369Skib intel_hdmi->write_infoframe = vlv_write_infoframe; 713280369Skib for_each_pipe(i) 714280369Skib I915_WRITE(VLV_TVIDEO_DIP_CTL(i), 0); 715280369Skib } else if (IS_HASWELL(dev)) { 716280369Skib /* FIXME: Haswell has a new set of DIP frame registers, but we are 717280369Skib * just doing the minimal required for HDMI to work at this stage. 718280369Skib */ 719280369Skib intel_hdmi->write_infoframe = hsw_write_infoframe; 720280369Skib for_each_pipe(i) 721280369Skib I915_WRITE(HSW_TVIDEO_DIP_CTL(i), 0); 722280369Skib } else if (HAS_PCH_IBX(dev)) { 723280369Skib intel_hdmi->write_infoframe = ibx_write_infoframe; 724280369Skib for_each_pipe(i) 725280369Skib I915_WRITE(TVIDEO_DIP_CTL(i), 0); 726235783Skib } else { 727280369Skib intel_hdmi->write_infoframe = cpt_write_infoframe; 728235783Skib for_each_pipe(i) 729235783Skib I915_WRITE(TVIDEO_DIP_CTL(i), 0); 730235783Skib } 731235783Skib 732280369Skib if (IS_HASWELL(dev)) 733280369Skib drm_encoder_helper_add(&intel_encoder->base, &intel_hdmi_helper_funcs_hsw); 734280369Skib else 735280369Skib drm_encoder_helper_add(&intel_encoder->base, &intel_hdmi_helper_funcs); 736235783Skib 737235783Skib intel_hdmi_add_properties(intel_hdmi, connector); 738235783Skib 739235783Skib intel_connector_attach_encoder(intel_connector, intel_encoder); 740235783Skib#if 0 741235783Skib drm_sysfs_connector_add(connector); 742235783Skib#endif 743235783Skib 744235783Skib /* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written 745235783Skib * 0xd. Failure to do so will result in spurious interrupts being 746235783Skib * generated on the port when a cable is not attached. 747235783Skib */ 748235783Skib if (IS_G4X(dev) && !IS_GM45(dev)) { 749235783Skib u32 temp = I915_READ(PEG_BAND_GAP_DATA); 750235783Skib I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd); 751235783Skib } 752235783Skib} 753