/*
* Copyright 2006 Dave Airlie <airlied@linux.ie>
* Copyright © 2006-2009 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Authors:
* Eric Anholt <eric@anholt.net>
* Jesse Barnes <jesse.barnes@intel.com>
*/
#include <linux/i2c.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <drm/drmP.h>
#include <drm/drm_crtc.h>
#include <drm/drm_edid.h>
#include "intel_drv.h"
#include <drm/i915_drm.h>
#include "i915_drv.h"
static struct drm_device *intel_hdmi_to_dev(struct intel_hdmi *intel_hdmi)
{
return hdmi_to_dig_port(intel_hdmi)->base.base.dev;
}
static void
assert_hdmi_port_disabled(struct intel_hdmi *intel_hdmi)
{
struct drm_device *dev = intel_hdmi_to_dev(intel_hdmi);
struct drm_i915_private *dev_priv = dev->dev_private;
uint32_t enabled_bits;
enabled_bits = HAS_DDI(dev) ? DDI_BUF_CTL_ENABLE : SDVO_ENABLE;
WARN(I915_READ(intel_hdmi->sdvox_reg) & enabled_bits,
"HDMI port enabled, expecting disabled\n");
}
struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder)
{
struct intel_digital_port *intel_dig_port =
container_of(encoder, struct intel_digital_port, base.base);
return &intel_dig_port->hdmi;
}
static struct intel_hdmi *intel_attached_hdmi(struct drm_connector *connector)
{
return enc_to_intel_hdmi(&intel_attached_encoder(connector)->base);
}
void intel_dip_infoframe_csum(struct dip_infoframe *frame)
{
uint8_t *data = (uint8_t *)frame;
uint8_t sum = 0;
unsigned i;
frame->checksum = 0;
frame->ecc = 0;
for (i = 0; i < frame->len + DIP_HEADER_SIZE; i++)
sum += data[i];
frame->checksum = 0x100 - sum;
}
static u32 g4x_infoframe_index(struct dip_infoframe *frame)
{
switch (frame->type) {
case DIP_TYPE_AVI:
return VIDEO_DIP_SELECT_AVI;
case DIP_TYPE_SPD:
return VIDEO_DIP_SELECT_SPD;
default:
DRM_DEBUG_DRIVER("unknown info frame type %d\n", frame->type);
return 0;
}
}
static u32 g4x_infoframe_enable(struct dip_infoframe *frame)
{
switch (frame->type) {
case DIP_TYPE_AVI:
return VIDEO_DIP_ENABLE_AVI;
case DIP_TYPE_SPD:
return VIDEO_DIP_ENABLE_SPD;
default:
DRM_DEBUG_DRIVER("unknown info frame type %d\n", frame->type);
return 0;
}
}
static u32 hsw_infoframe_enable(struct dip_infoframe *frame)
{
switch (frame->type) {
case DIP_TYPE_AVI:
return VIDEO_DIP_ENABLE_AVI_HSW;
case DIP_TYPE_SPD:
return VIDEO_DIP_ENABLE_SPD_HSW;
default:
DRM_DEBUG_DRIVER("unknown info frame type %d\n", frame->type);
return 0;
}
}
static u32 hsw_infoframe_data_reg(struct dip_infoframe *frame, enum pipe pipe)
{
switch (frame->type) {
case DIP_TYPE_AVI:
return HSW_TVIDEO_DIP_AVI_DATA(pipe);
case DIP_TYPE_SPD:
return HSW_TVIDEO_DIP_SPD_DATA(pipe);
default:
DRM_DEBUG_DRIVER("unknown info frame type %d\n", frame->type);
return 0;
}
}
static void