Commit 5259c522 authored by Dave Airlie's avatar Dave Airlie

Merge branch 'drm-intel-next' of git://people.freedesktop.org/~danvet/drm-intel into drm-next

New feature pile for 3.12! Highlights:
- Stereo/3d support for hdmi from Damien, both the drm core bits and
  the i915 integration.
- Manual boost/deboost logic for gpu turbo (Chris)
- Fixed up clock readout support for vlv (Chris).
- Tons of little fixes and improvements for vlv in general (Chon Minng
  Lee and Jesse Barnes).
- Power well support for the legacy vga plane (Ville).
- DP impromevents from Jani.
- Improvements to the Haswell modeset sequence (Ville+Paulo).
- Haswell DDI improvements, using the VBT for some tuning values and
  to check the configuration (Paulo).
- Tons of other small improvements and fixups.

* 'drm-intel-next' of git://people.freedesktop.org/~danvet/drm-intel: (92 commits)
  drm/i915: Use adjusted_mode in the fastboot hack to disable pfit
  drm/i915: Add a more detailed comment about the set_base() fastboot hack
  drm/i915/vlv: Turn off power gate for BIOS-less system.
  drm/i915/vlv: reset DPIO on load and resume v2
  drm/i915: Simplify PSR debugfs
  drm/i915: Tweak RPS thresholds to more aggressively downclock
  drm/i915: Boost RPS frequency for CPU stalls
  drm/i915: Fix __wait_seqno to use true infinite timeouts
  drm/i915: Add some missing steps to i915_driver_load error path
  drm/i915: Clean up the ring scaling calculations
  drm/i915: Don't populate pipe_src_{w,h} multiple times
  drm/i915: implement the Haswell mode set sequence workaround
  drm/i915: Disable/enable planes as the first/last thing during modeset on HSW
  i915/vlv: untangle integrated clock source handling v4
  drm/i915: fix typo s/PatherPoint/PantherPoint/
  drm/i915: Make intel_resume_power_well() static
  drm/i915: destroy connector sysfs files earlier
  drm/i915/dp: do not write DP_TRAINING_PATTERN_SET all the time
  drm/i915/dp: retry i2c-over-aux seven times on AUX DEFER
  drm/i915/vlv: reduce GT FIFO error info to a debug message
  ...
parents 6aba5b6c 967ad7f1
...@@ -1319,6 +1319,9 @@ static int drm_crtc_convert_umode(struct drm_display_mode *out, ...@@ -1319,6 +1319,9 @@ static int drm_crtc_convert_umode(struct drm_display_mode *out,
if (in->clock > INT_MAX || in->vrefresh > INT_MAX) if (in->clock > INT_MAX || in->vrefresh > INT_MAX)
return -ERANGE; return -ERANGE;
if ((in->flags & DRM_MODE_FLAG_3D_MASK) > DRM_MODE_FLAG_3D_MAX)
return -EINVAL;
out->clock = in->clock; out->clock = in->clock;
out->hdisplay = in->hdisplay; out->hdisplay = in->hdisplay;
out->hsync_start = in->hsync_start; out->hsync_start = in->hsync_start;
...@@ -1581,6 +1584,19 @@ int drm_mode_getcrtc(struct drm_device *dev, ...@@ -1581,6 +1584,19 @@ int drm_mode_getcrtc(struct drm_device *dev,
return ret; return ret;
} }
static bool drm_mode_expose_to_userspace(const struct drm_display_mode *mode,
const struct drm_file *file_priv)
{
/*
* If user-space hasn't configured the driver to expose the stereo 3D
* modes, don't expose them.
*/
if (!file_priv->stereo_allowed && drm_mode_is_stereo(mode))
return false;
return true;
}
/** /**
* drm_mode_getconnector - get connector configuration * drm_mode_getconnector - get connector configuration
* @dev: drm device for the ioctl * @dev: drm device for the ioctl
...@@ -1646,7 +1662,8 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, ...@@ -1646,7 +1662,8 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
/* delayed so we get modes regardless of pre-fill_modes state */ /* delayed so we get modes regardless of pre-fill_modes state */
list_for_each_entry(mode, &connector->modes, head) list_for_each_entry(mode, &connector->modes, head)
mode_count++; if (drm_mode_expose_to_userspace(mode, file_priv))
mode_count++;
out_resp->connector_id = connector->base.id; out_resp->connector_id = connector->base.id;
out_resp->connector_type = connector->connector_type; out_resp->connector_type = connector->connector_type;
...@@ -1668,6 +1685,9 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, ...@@ -1668,6 +1685,9 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
copied = 0; copied = 0;
mode_ptr = (struct drm_mode_modeinfo __user *)(unsigned long)out_resp->modes_ptr; mode_ptr = (struct drm_mode_modeinfo __user *)(unsigned long)out_resp->modes_ptr;
list_for_each_entry(mode, &connector->modes, head) { list_for_each_entry(mode, &connector->modes, head) {
if (!drm_mode_expose_to_userspace(mode, file_priv))
continue;
drm_crtc_convert_to_umode(&u_mode, mode); drm_crtc_convert_to_umode(&u_mode, mode);
if (copy_to_user(mode_ptr + copied, if (copy_to_user(mode_ptr + copied,
&u_mode, sizeof(u_mode))) { &u_mode, sizeof(u_mode))) {
...@@ -2042,6 +2062,45 @@ int drm_mode_set_config_internal(struct drm_mode_set *set) ...@@ -2042,6 +2062,45 @@ int drm_mode_set_config_internal(struct drm_mode_set *set)
} }
EXPORT_SYMBOL(drm_mode_set_config_internal); EXPORT_SYMBOL(drm_mode_set_config_internal);
/*
* Checks that the framebuffer is big enough for the CRTC viewport
* (x, y, hdisplay, vdisplay)
*/
static int drm_crtc_check_viewport(const struct drm_crtc *crtc,
int x, int y,
const struct drm_display_mode *mode,
const struct drm_framebuffer *fb)
{
int hdisplay, vdisplay;
hdisplay = mode->hdisplay;
vdisplay = mode->vdisplay;
if (drm_mode_is_stereo(mode)) {
struct drm_display_mode adjusted = *mode;
drm_mode_set_crtcinfo(&adjusted, CRTC_STEREO_DOUBLE);
hdisplay = adjusted.crtc_hdisplay;
vdisplay = adjusted.crtc_vdisplay;
}
if (crtc->invert_dimensions)
swap(hdisplay, vdisplay);
if (hdisplay > fb->width ||
vdisplay > fb->height ||
x > fb->width - hdisplay ||
y > fb->height - vdisplay) {
DRM_DEBUG_KMS("Invalid fb size %ux%u for CRTC viewport %ux%u+%d+%d%s.\n",
fb->width, fb->height, hdisplay, vdisplay, x, y,
crtc->invert_dimensions ? " (inverted)" : "");
return -ENOSPC;
}
return 0;
}
/** /**
* drm_mode_setcrtc - set CRTC configuration * drm_mode_setcrtc - set CRTC configuration
* @dev: drm device for the ioctl * @dev: drm device for the ioctl
...@@ -2089,7 +2148,6 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, ...@@ -2089,7 +2148,6 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id); DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
if (crtc_req->mode_valid) { if (crtc_req->mode_valid) {
int hdisplay, vdisplay;
/* If we have a mode we need a framebuffer. */ /* If we have a mode we need a framebuffer. */
/* If we pass -1, set the mode with the currently bound fb */ /* If we pass -1, set the mode with the currently bound fb */
if (crtc_req->fb_id == -1) { if (crtc_req->fb_id == -1) {
...@@ -2125,23 +2183,11 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, ...@@ -2125,23 +2183,11 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
hdisplay = mode->hdisplay; ret = drm_crtc_check_viewport(crtc, crtc_req->x, crtc_req->y,
vdisplay = mode->vdisplay; mode, fb);
if (ret)
if (crtc->invert_dimensions)
swap(hdisplay, vdisplay);
if (hdisplay > fb->width ||
vdisplay > fb->height ||
crtc_req->x > fb->width - hdisplay ||
crtc_req->y > fb->height - vdisplay) {
DRM_DEBUG_KMS("Invalid fb size %ux%u for CRTC viewport %ux%u+%d+%d%s.\n",
fb->width, fb->height,
hdisplay, vdisplay, crtc_req->x, crtc_req->y,
crtc->invert_dimensions ? " (inverted)" : "");
ret = -ENOSPC;
goto out; goto out;
}
} }
if (crtc_req->count_connectors == 0 && mode) { if (crtc_req->count_connectors == 0 && mode) {
...@@ -3558,7 +3604,6 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, ...@@ -3558,7 +3604,6 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
struct drm_framebuffer *fb = NULL, *old_fb = NULL; struct drm_framebuffer *fb = NULL, *old_fb = NULL;
struct drm_pending_vblank_event *e = NULL; struct drm_pending_vblank_event *e = NULL;
unsigned long flags; unsigned long flags;
int hdisplay, vdisplay;
int ret = -EINVAL; int ret = -EINVAL;
if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS || if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS ||
...@@ -3590,22 +3635,9 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, ...@@ -3590,22 +3635,9 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
if (!fb) if (!fb)
goto out; goto out;
hdisplay = crtc->mode.hdisplay; ret = drm_crtc_check_viewport(crtc, crtc->x, crtc->y, &crtc->mode, fb);
vdisplay = crtc->mode.vdisplay; if (ret)
if (crtc->invert_dimensions)
swap(hdisplay, vdisplay);
if (hdisplay > fb->width ||
vdisplay > fb->height ||
crtc->x > fb->width - hdisplay ||
crtc->y > fb->height - vdisplay) {
DRM_DEBUG_KMS("Invalid fb size %ux%u for CRTC viewport %ux%u+%d+%d%s.\n",
fb->width, fb->height, hdisplay, vdisplay, crtc->x, crtc->y,
crtc->invert_dimensions ? " (inverted)" : "");
ret = -ENOSPC;
goto out; goto out;
}
if (crtc->fb->pixel_format != fb->pixel_format) { if (crtc->fb->pixel_format != fb->pixel_format) {
DRM_DEBUG_KMS("Page flip is not allowed to change frame buffer format.\n"); DRM_DEBUG_KMS("Page flip is not allowed to change frame buffer format.\n");
......
...@@ -76,7 +76,8 @@ static void drm_mode_validate_flag(struct drm_connector *connector, ...@@ -76,7 +76,8 @@ static void drm_mode_validate_flag(struct drm_connector *connector,
{ {
struct drm_display_mode *mode; struct drm_display_mode *mode;
if (flags == (DRM_MODE_FLAG_DBLSCAN | DRM_MODE_FLAG_INTERLACE)) if (flags == (DRM_MODE_FLAG_DBLSCAN | DRM_MODE_FLAG_INTERLACE |
DRM_MODE_FLAG_3D_MASK))
return; return;
list_for_each_entry(mode, &connector->modes, head) { list_for_each_entry(mode, &connector->modes, head) {
...@@ -86,6 +87,9 @@ static void drm_mode_validate_flag(struct drm_connector *connector, ...@@ -86,6 +87,9 @@ static void drm_mode_validate_flag(struct drm_connector *connector,
if ((mode->flags & DRM_MODE_FLAG_DBLSCAN) && if ((mode->flags & DRM_MODE_FLAG_DBLSCAN) &&
!(flags & DRM_MODE_FLAG_DBLSCAN)) !(flags & DRM_MODE_FLAG_DBLSCAN))
mode->status = MODE_NO_DBLESCAN; mode->status = MODE_NO_DBLESCAN;
if ((mode->flags & DRM_MODE_FLAG_3D_MASK) &&
!(flags & DRM_MODE_FLAG_3D_MASK))
mode->status = MODE_NO_STEREO;
} }
return; return;
...@@ -175,6 +179,8 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector, ...@@ -175,6 +179,8 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
mode_flags |= DRM_MODE_FLAG_INTERLACE; mode_flags |= DRM_MODE_FLAG_INTERLACE;
if (connector->doublescan_allowed) if (connector->doublescan_allowed)
mode_flags |= DRM_MODE_FLAG_DBLSCAN; mode_flags |= DRM_MODE_FLAG_DBLSCAN;
if (connector->stereo_allowed)
mode_flags |= DRM_MODE_FLAG_3D_MASK;
drm_mode_validate_flag(connector, mode_flags); drm_mode_validate_flag(connector, mode_flags);
list_for_each_entry(mode, &connector->modes, head) { list_for_each_entry(mode, &connector->modes, head) {
......
...@@ -69,6 +69,7 @@ static const struct drm_ioctl_desc drm_ioctls[] = { ...@@ -69,6 +69,7 @@ static const struct drm_ioctl_desc drm_ioctls[] = {
DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_GET_CAP, drm_getcap, DRM_UNLOCKED|DRM_RENDER_ALLOW), DRM_IOCTL_DEF(DRM_IOCTL_GET_CAP, drm_getcap, DRM_UNLOCKED|DRM_RENDER_ALLOW),
DRM_IOCTL_DEF(DRM_IOCTL_SET_CLIENT_CAP, drm_setclientcap, 0),
DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER), DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER),
DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE, drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE, drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
......
...@@ -2416,7 +2416,7 @@ u8 drm_match_cea_mode(const struct drm_display_mode *to_match) ...@@ -2416,7 +2416,7 @@ u8 drm_match_cea_mode(const struct drm_display_mode *to_match)
if ((KHZ2PICOS(to_match->clock) == KHZ2PICOS(clock1) || if ((KHZ2PICOS(to_match->clock) == KHZ2PICOS(clock1) ||
KHZ2PICOS(to_match->clock) == KHZ2PICOS(clock2)) && KHZ2PICOS(to_match->clock) == KHZ2PICOS(clock2)) &&
drm_mode_equal_no_clocks(to_match, cea_mode)) drm_mode_equal_no_clocks_no_stereo(to_match, cea_mode))
return mode + 1; return mode + 1;
} }
return 0; return 0;
...@@ -2465,7 +2465,7 @@ static u8 drm_match_hdmi_mode(const struct drm_display_mode *to_match) ...@@ -2465,7 +2465,7 @@ static u8 drm_match_hdmi_mode(const struct drm_display_mode *to_match)
if ((KHZ2PICOS(to_match->clock) == KHZ2PICOS(clock1) || if ((KHZ2PICOS(to_match->clock) == KHZ2PICOS(clock1) ||
KHZ2PICOS(to_match->clock) == KHZ2PICOS(clock2)) && KHZ2PICOS(to_match->clock) == KHZ2PICOS(clock2)) &&
drm_mode_equal_no_clocks(to_match, hdmi_mode)) drm_mode_equal_no_clocks_no_stereo(to_match, hdmi_mode))
return mode + 1; return mode + 1;
} }
return 0; return 0;
...@@ -2519,6 +2519,9 @@ add_alternate_cea_modes(struct drm_connector *connector, struct edid *edid) ...@@ -2519,6 +2519,9 @@ add_alternate_cea_modes(struct drm_connector *connector, struct edid *edid)
if (!newmode) if (!newmode)
continue; continue;
/* Carry over the stereo flags */
newmode->flags |= mode->flags & DRM_MODE_FLAG_3D_MASK;
/* /*
* The current mode could be either variant. Make * The current mode could be either variant. Make
* sure to pick the "other" clock for the new mode. * sure to pick the "other" clock for the new mode.
...@@ -2565,18 +2568,102 @@ do_cea_modes(struct drm_connector *connector, const u8 *db, u8 len) ...@@ -2565,18 +2568,102 @@ do_cea_modes(struct drm_connector *connector, const u8 *db, u8 len)
return modes; return modes;
} }
struct stereo_mandatory_mode {
int width, height, vrefresh;
unsigned int flags;
};
static const struct stereo_mandatory_mode stereo_mandatory_modes[] = {
{ 1920, 1080, 24, DRM_MODE_FLAG_3D_TOP_AND_BOTTOM },
{ 1920, 1080, 24, DRM_MODE_FLAG_3D_FRAME_PACKING },
{ 1920, 1080, 50,
DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF },
{ 1920, 1080, 60,
DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF },
{ 1280, 720, 50, DRM_MODE_FLAG_3D_TOP_AND_BOTTOM },
{ 1280, 720, 50, DRM_MODE_FLAG_3D_FRAME_PACKING },
{ 1280, 720, 60, DRM_MODE_FLAG_3D_TOP_AND_BOTTOM },
{ 1280, 720, 60, DRM_MODE_FLAG_3D_FRAME_PACKING }
};
static bool
stereo_match_mandatory(const struct drm_display_mode *mode,
const struct stereo_mandatory_mode *stereo_mode)
{
unsigned int interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE;
return mode->hdisplay == stereo_mode->width &&
mode->vdisplay == stereo_mode->height &&
interlaced == (stereo_mode->flags & DRM_MODE_FLAG_INTERLACE) &&
drm_mode_vrefresh(mode) == stereo_mode->vrefresh;
}
static int add_hdmi_mandatory_stereo_modes(struct drm_connector *connector)
{
struct drm_device *dev = connector->dev;
const struct drm_display_mode *mode;
struct list_head stereo_modes;
int modes = 0, i;
INIT_LIST_HEAD(&stereo_modes);
list_for_each_entry(mode, &connector->probed_modes, head) {
for (i = 0; i < ARRAY_SIZE(stereo_mandatory_modes); i++) {
const struct stereo_mandatory_mode *mandatory;
struct drm_display_mode *new_mode;
if (!stereo_match_mandatory(mode,
&stereo_mandatory_modes[i]))
continue;
mandatory = &stereo_mandatory_modes[i];
new_mode = drm_mode_duplicate(dev, mode);
if (!new_mode)
continue;
new_mode->flags |= mandatory->flags;
list_add_tail(&new_mode->head, &stereo_modes);
modes++;
}
}
list_splice_tail(&stereo_modes, &connector->probed_modes);
return modes;
}
static int add_hdmi_mode(struct drm_connector *connector, u8 vic)
{
struct drm_device *dev = connector->dev;
struct drm_display_mode *newmode;
vic--; /* VICs start at 1 */
if (vic >= ARRAY_SIZE(edid_4k_modes)) {
DRM_ERROR("Unknown HDMI VIC: %d\n", vic);
return 0;
}
newmode = drm_mode_duplicate(dev, &edid_4k_modes[vic]);
if (!newmode)
return 0;
drm_mode_probed_add(connector, newmode);
return 1;
}
/* /*
* do_hdmi_vsdb_modes - Parse the HDMI Vendor Specific data block * do_hdmi_vsdb_modes - Parse the HDMI Vendor Specific data block
* @connector: connector corresponding to the HDMI sink * @connector: connector corresponding to the HDMI sink
* @db: start of the CEA vendor specific block * @db: start of the CEA vendor specific block
* @len: length of the CEA block payload, ie. one can access up to db[len] * @len: length of the CEA block payload, ie. one can access up to db[len]
* *
* Parses the HDMI VSDB looking for modes to add to @connector. * Parses the HDMI VSDB looking for modes to add to @connector. This function
* also adds the stereo 3d modes when applicable.
*/ */
static int static int
do_hdmi_vsdb_modes(struct drm_connector *connector, const u8 *db, u8 len) do_hdmi_vsdb_modes(struct drm_connector *connector, const u8 *db, u8 len)
{ {
struct drm_device *dev = connector->dev;
int modes = 0, offset = 0, i; int modes = 0, offset = 0, i;
u8 vic_len; u8 vic_len;
...@@ -2597,30 +2684,22 @@ do_hdmi_vsdb_modes(struct drm_connector *connector, const u8 *db, u8 len) ...@@ -2597,30 +2684,22 @@ do_hdmi_vsdb_modes(struct drm_connector *connector, const u8 *db, u8 len)
/* the declared length is not long enough for the 2 first bytes /* the declared length is not long enough for the 2 first bytes
* of additional video format capabilities */ * of additional video format capabilities */
offset += 2; if (len < (8 + offset + 2))
if (len < (8 + offset))
goto out; goto out;
/* 3D_Present */
offset++;
if (db[8 + offset] & (1 << 7))
modes += add_hdmi_mandatory_stereo_modes(connector);
offset++;
vic_len = db[8 + offset] >> 5; vic_len = db[8 + offset] >> 5;
for (i = 0; i < vic_len && len >= (9 + offset + i); i++) { for (i = 0; i < vic_len && len >= (9 + offset + i); i++) {
struct drm_display_mode *newmode;
u8 vic; u8 vic;
vic = db[9 + offset + i]; vic = db[9 + offset + i];
modes += add_hdmi_mode(connector, vic);
vic--; /* VICs start at 1 */
if (vic >= ARRAY_SIZE(edid_4k_modes)) {
DRM_ERROR("Unknown HDMI VIC: %d\n", vic);
continue;
}
newmode = drm_mode_duplicate(dev, &edid_4k_modes[vic]);
if (!newmode)
continue;
drm_mode_probed_add(connector, newmode);
modes++;
} }
out: out:
...@@ -2680,8 +2759,8 @@ static int ...@@ -2680,8 +2759,8 @@ static int
add_cea_modes(struct drm_connector *connector, struct edid *edid) add_cea_modes(struct drm_connector *connector, struct edid *edid)
{ {
const u8 *cea = drm_find_cea_extension(edid); const u8 *cea = drm_find_cea_extension(edid);
const u8 *db; const u8 *db, *hdmi = NULL;
u8 dbl; u8 dbl, hdmi_len;
int modes = 0; int modes = 0;
if (cea && cea_revision(cea) >= 3) { if (cea && cea_revision(cea) >= 3) {
...@@ -2696,11 +2775,20 @@ add_cea_modes(struct drm_connector *connector, struct edid *edid) ...@@ -2696,11 +2775,20 @@ add_cea_modes(struct drm_connector *connector, struct edid *edid)
if (cea_db_tag(db) == VIDEO_BLOCK) if (cea_db_tag(db) == VIDEO_BLOCK)
modes += do_cea_modes(connector, db + 1, dbl); modes += do_cea_modes(connector, db + 1, dbl);
else if (cea_db_is_hdmi_vsdb(db)) else if (cea_db_is_hdmi_vsdb(db)) {
modes += do_hdmi_vsdb_modes(connector, db, dbl); hdmi = db;
hdmi_len = dbl;
}
} }
} }
/*
* We parse the HDMI VSDB after having added the cea modes as we will
* be patching their flags when the sink supports stereo 3D.
*/
if (hdmi)
modes += do_hdmi_vsdb_modes(connector, hdmi, hdmi_len);
return modes; return modes;
} }
...@@ -3333,6 +3421,33 @@ drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame, ...@@ -3333,6 +3421,33 @@ drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
} }
EXPORT_SYMBOL(drm_hdmi_avi_infoframe_from_display_mode); EXPORT_SYMBOL(drm_hdmi_avi_infoframe_from_display_mode);
static enum hdmi_3d_structure
s3d_structure_from_display_mode(const struct drm_display_mode *mode)
{
u32 layout = mode->flags & DRM_MODE_FLAG_3D_MASK;
switch (layout) {
case DRM_MODE_FLAG_3D_FRAME_PACKING:
return HDMI_3D_STRUCTURE_FRAME_PACKING;
case DRM_MODE_FLAG_3D_FIELD_ALTERNATIVE:
return HDMI_3D_STRUCTURE_FIELD_ALTERNATIVE;
case DRM_MODE_FLAG_3D_LINE_ALTERNATIVE:
return HDMI_3D_STRUCTURE_LINE_ALTERNATIVE;
case DRM_MODE_FLAG_3D_SIDE_BY_SIDE_FULL:
return HDMI_3D_STRUCTURE_SIDE_BY_SIDE_FULL;
case DRM_MODE_FLAG_3D_L_DEPTH:
return HDMI_3D_STRUCTURE_L_DEPTH;
case DRM_MODE_FLAG_3D_L_DEPTH_GFX_GFX_DEPTH:
return HDMI_3D_STRUCTURE_L_DEPTH_GFX_GFX_DEPTH;
case DRM_MODE_FLAG_3D_TOP_AND_BOTTOM:
return HDMI_3D_STRUCTURE_TOP_AND_BOTTOM;
case DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF:
return HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF;
default:
return HDMI_3D_STRUCTURE_INVALID;
}
}
/** /**
* drm_hdmi_vendor_infoframe_from_display_mode() - fill an HDMI infoframe with * drm_hdmi_vendor_infoframe_from_display_mode() - fill an HDMI infoframe with
* data from a DRM display mode * data from a DRM display mode
...@@ -3350,20 +3465,29 @@ drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame, ...@@ -3350,20 +3465,29 @@ drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame,
const struct drm_display_mode *mode) const struct drm_display_mode *mode)
{ {
int err; int err;
u32 s3d_flags;
u8 vic; u8 vic;
if (!frame || !mode) if (!frame || !mode)
return -EINVAL; return -EINVAL;
vic = drm_match_hdmi_mode(mode); vic = drm_match_hdmi_mode(mode);
if (!vic) s3d_flags = mode->flags & DRM_MODE_FLAG_3D_MASK;
if (!vic && !s3d_flags)
return -EINVAL;
if (vic && s3d_flags)
return -EINVAL; return -EINVAL;
err = hdmi_vendor_infoframe_init(frame); err = hdmi_vendor_infoframe_init(frame);
if (err < 0) if (err < 0)
return err; return err;
frame->vic = vic; if (vic)
frame->vic = vic;
else
frame->s3d_struct = s3d_structure_from_display_mode(mode);
return 0; return 0;
} }
......
...@@ -302,6 +302,27 @@ int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_priv) ...@@ -302,6 +302,27 @@ int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_priv)
return 0; return 0;
} }
/**
* Set device/driver capabilities
*/
int
drm_setclientcap(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
struct drm_set_client_cap *req = data;
switch (req->capability) {
case DRM_CLIENT_CAP_STEREO_3D:
if (req->value > 1)
return -EINVAL;
file_priv->stereo_allowed = req->value;
break;
default:
return -EINVAL;
}
return 0;
}
/** /**
* Setversion ioctl. * Setversion ioctl.
* *
......
...@@ -707,18 +707,25 @@ EXPORT_SYMBOL(drm_mode_vrefresh); ...@@ -707,18 +707,25 @@ EXPORT_SYMBOL(drm_mode_vrefresh);
/** /**
* drm_mode_set_crtcinfo - set CRTC modesetting parameters * drm_mode_set_crtcinfo - set CRTC modesetting parameters
* @p: mode * @p: mode
* @adjust_flags: unused? (FIXME) * @adjust_flags: a combination of adjustment flags
* *
* LOCKING: * LOCKING:
* None. * None.
* *
* Setup the CRTC modesetting parameters for @p, adjusting if necessary. * Setup the CRTC modesetting parameters for @p, adjusting if necessary.
*
* - The CRTC_INTERLACE_HALVE_V flag can be used to halve vertical timings of
* interlaced modes.
* - The CRTC_STEREO_DOUBLE flag can be used to compute the timings for
* buffers containing two eyes (only adjust the timings when needed, eg. for
* "frame packing" or "side by side full").
*/ */
void drm_mode_set_crtcinfo(struct drm_display_mode *p, int adjust_flags) void drm_mode_set_crtcinfo(struct drm_display_mode *p, int adjust_flags)
{ {
if ((p == NULL) || ((p->type & DRM_MODE_TYPE_CRTC_C) == DRM_MODE_TYPE_BUILTIN)) if ((p == NULL) || ((p->type & DRM_MODE_TYPE_CRTC_C) == DRM_MODE_TYPE_BUILTIN))
return; return;
p->crtc_clock = p->clock;
p->crtc_hdisplay = p->hdisplay; p->crtc_hdisplay = p->hdisplay;
p->crtc_hsync_start = p->hsync_start; p->crtc_hsync_start = p->hsync_start;
p->crtc_hsync_end = p->hsync_end; p->crtc_hsync_end = p->hsync_end;
...@@ -752,6 +759,20 @@ void drm_mode_set_crtcinfo(struct drm_display_mode *p, int adjust_flags) ...@@ -752,6 +759,20 @@ void drm_mode_set_crtcinfo(struct drm_display_mode *p, int adjust_flags)
p->crtc_vtotal *= p->vscan; p->crtc_vtotal *= p->vscan;
} }
if (adjust_flags & CRTC_STEREO_DOUBLE) {
unsigned int layout = p->flags & DRM_MODE_FLAG_3D_MASK;
switch (layout) {
case DRM_MODE_FLAG_3D_FRAME_PACKING:
p->crtc_clock *= 2;
p->crtc_vdisplay += p->crtc_vtotal;
p->crtc_vsync_start += p->crtc_vtotal;
p->crtc_vsync_end += p->crtc_vtotal;
p->crtc_vtotal += p->crtc_vtotal;
break;
}
}
p->crtc_vblank_start = min(p->crtc_vsync_start, p->crtc_vdisplay); p->crtc_vblank_start = min(p->crtc_vsync_start, p->crtc_vdisplay);
p->crtc_vblank_end = max(p->crtc_vsync_end, p->crtc_vtotal); p->crtc_vblank_end = max(p->crtc_vsync_end, p->crtc_vtotal);
p->crtc_hblank_start = min(p->crtc_hsync_start, p->crtc_hdisplay); p->crtc_hblank_start = min(p->crtc_hsync_start, p->crtc_hdisplay);
...@@ -830,12 +851,16 @@ bool drm_mode_equal(const struct drm_display_mode *mode1, const struct drm_displ ...@@ -830,12 +851,16 @@ bool drm_mode_equal(const struct drm_display_mode *mode1, const struct drm_displ
} else if (mode1->clock != mode2->clock) } else if (mode1->clock != mode2->clock)
return false; return false;
return drm_mode_equal_no_clocks(mode1, mode2); if ((mode1->flags & DRM_MODE_FLAG_3D_MASK) !=
(mode2->flags & DRM_MODE_FLAG_3D_MASK))
return false;
return drm_mode_equal_no_clocks_no_stereo(mode1, mode2);
} }
EXPORT_SYMBOL(drm_mode_equal); EXPORT_SYMBOL(drm_mode_equal);
/** /**
* drm_mode_equal_no_clocks - test modes for equality * drm_mode_equal_no_clocks_no_stereo - test modes for equality
* @mode1: first mode * @mode1: first mode
* @mode2: second mode * @mode2: second mode
* *
...@@ -843,12 +868,13 @@ EXPORT_SYMBOL(drm_mode_equal); ...@@ -843,12 +868,13 @@ EXPORT_SYMBOL(drm_mode_equal);
* None. * None.
* *
* Check to see if @mode1 and @mode2 are equivalent, but * Check to see if @mode1 and @mode2 are equivalent, but
* don't check the pixel clocks. * don't check the pixel clocks nor the stereo layout.
* *
* RETURNS: * RETURNS:
* True if the modes are equal, false otherwise. * True if the modes are equal, false otherwise.
*/ */
bool drm_mode_equal_no_clocks(const struct drm_display_mode *mode1, const struct drm_display_mode *mode2) bool drm_mode_equal_no_clocks_no_stereo(const struct drm_display_mode *mode1,
const struct drm_display_mode *mode2)
{ {
if (mode1->hdisplay == mode2->hdisplay && if (mode1->hdisplay == mode2->hdisplay &&
mode1->hsync_start == mode2->hsync_start && mode1->hsync_start == mode2->hsync_start &&
...@@ -860,12 +886,13 @@ bool drm_mode_equal_no_clocks(const struct drm_display_mode *mode1, const struct ...@@ -860,12 +886,13 @@ bool drm_mode_equal_no_clocks(const struct drm_display_mode *mode1, const struct
mode1->vsync_end == mode2->vsync_end && mode1->vsync_end == mode2->vsync_end &&
mode1->vtotal == mode2->vtotal && mode1->vtotal == mode2->vtotal &&
mode1->vscan == mode2->vscan && mode1->vscan == mode2->vscan &&
mode1->flags == mode2->flags) (mode1->flags & ~DRM_MODE_FLAG_3D_MASK) ==
(mode2->flags & ~DRM_MODE_FLAG_3D_MASK))
return true; return true;
return false; return false;
} }
EXPORT_SYMBOL(drm_mode_equal_no_clocks); EXPORT_SYMBOL(drm_mode_equal_no_clocks_no_stereo);
/** /**
* drm_mode_validate_size - make sure modes adhere to size constraints * drm_mode_validate_size - make sure modes adhere to size constraints
......
...@@ -1666,126 +1666,20 @@ static int i915_edp_psr_status(struct seq_file *m, void *data) ...@@ -1666,126 +1666,20 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
struct drm_info_node *node = m->private; struct drm_info_node *node = m->private;
struct drm_device *dev = node->minor->dev; struct drm_device *dev = node->minor->dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
u32 psrstat, psrperf; u32 psrperf = 0;
bool enabled = false;
if (!IS_HASWELL(dev)) { seq_printf(m, "Sink_Support: %s\n", yesno(dev_priv->psr.sink_support));
seq_puts(m, "PSR not supported on this platform\n"); seq_printf(m, "Source_OK: %s\n", yesno(dev_priv->psr.source_ok));
} else if (IS_HASWELL(dev) && I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE) {
seq_puts(m, "PSR enabled\n");
} else {
seq_puts(m, "PSR disabled: ");
switch (dev_priv->no_psr_reason) {
case PSR_NO_SOURCE:
seq_puts(m, "not supported on this platform");
break;
case PSR_NO_SINK:
seq_puts(m, "not supported by panel");
break;
case PSR_MODULE_PARAM:
seq_puts(m, "disabled by flag");
break;
case PSR_CRTC_NOT_ACTIVE:
seq_puts(m, "crtc not active");
break;
case PSR_PWR_WELL_ENABLED:
seq_puts(m, "power well enabled");
break;
case PSR_NOT_TILED:
seq_puts(m, "not tiled");
break;
case PSR_SPRITE_ENABLED:
seq_puts(m, "sprite enabled");
break;
case PSR_S3D_ENABLED:
seq_puts(m, "stereo 3d enabled");
break;
case PSR_INTERLACED_ENABLED:
seq_puts(m, "interlaced enabled");
break;
case PSR_HSW_NOT_DDIA:
seq_puts(m, "HSW ties PSR to DDI A (eDP)");
break;
default:
seq_puts(m, "unknown reason");
}
seq_puts(m, "\n");
return 0;
}
psrstat = I915_READ(EDP_PSR_STATUS_CTL);
seq_puts(m, "PSR Current State: ");
switch (psrstat & EDP_PSR_STATUS_STATE_MASK) {
case EDP_PSR_STATUS_STATE_IDLE:
seq_puts(m, "Reset state\n");
break;
case EDP_PSR_STATUS_STATE_SRDONACK:
seq_puts(m, "Wait for TG/Stream to send on frame of data after SRD conditions are met\n");
break;
case EDP_PSR_STATUS_STATE_SRDENT:
seq_puts(m, "SRD entry\n");
break;
case EDP_PSR_STATUS_STATE_BUFOFF:
seq_puts(m, "Wait for buffer turn off\n");
break;
case EDP_PSR_STATUS_STATE_BUFON:
seq_puts(m, "Wait for buffer turn on\n");
break;
case EDP_PSR_STATUS_STATE_AUXACK:
seq_puts(m, "Wait for AUX to acknowledge on SRD exit\n");
break;
case EDP_PSR_STATUS_STATE_SRDOFFACK:
seq_puts(m, "Wait for TG/Stream to acknowledge the SRD VDM exit\n");
break;
default:
seq_puts(m, "Unknown\n");
break;
}
seq_puts(m, "Link Status: ");
switch (psrstat & EDP_PSR_STATUS_LINK_MASK) {
case EDP_PSR_STATUS_LINK_FULL_OFF:
seq_puts(m, "Link is fully off\n");
break;
case EDP_PSR_STATUS_LINK_FULL_ON:
seq_puts(m, "Link is fully on\n");
break;
case EDP_PSR_STATUS_LINK_STANDBY:
seq_puts(m, "Link is in standby\n");
break;
default:
seq_puts(m, "Unknown\n");
break;
}
seq_printf(m, "PSR Entry Count: %u\n",
psrstat >> EDP_PSR_STATUS_COUNT_SHIFT &
EDP_PSR_STATUS_COUNT_MASK);
seq_printf(m, "Max Sleep Timer Counter: %u\n",
psrstat >> EDP_PSR_STATUS_MAX_SLEEP_TIMER_SHIFT &
EDP_PSR_STATUS_MAX_SLEEP_TIMER_MASK);
seq_printf(m, "Had AUX error: %s\n",
yesno(psrstat & EDP_PSR_STATUS_AUX_ERROR));
seq_printf(m, "Sending AUX: %s\n",
yesno(psrstat & EDP_PSR_STATUS_AUX_SENDING));
seq_printf(m, "Sending Idle: %s\n", enabled = HAS_PSR(dev) &&
yesno(psrstat & EDP_PSR_STATUS_SENDING_IDLE)); I915_READ(EDP_PSR_CTL(dev)) & EDP_PSR_ENABLE;
seq_printf(m, "Enabled: %s\n", yesno(enabled));
seq_printf(m, "Sending TP2 TP3: %s\n", if (HAS_PSR(dev))
yesno(psrstat & EDP_PSR_STATUS_SENDING_TP2_TP3)); psrperf = I915_READ(EDP_PSR_PERF_CNT(dev)) &
EDP_PSR_PERF_CNT_MASK;
seq_printf(m, "Sending TP1: %s\n", seq_printf(m, "Performance_Counter: %u\n", psrperf);
yesno(psrstat & EDP_PSR_STATUS_SENDING_TP1));
seq_printf(m, "Idle Count: %u\n",
psrstat & EDP_PSR_STATUS_IDLE_MASK);
psrperf = (I915_READ(EDP_PSR_PERF_CNT)) & EDP_PSR_PERF_CNT_MASK;
seq_printf(m, "Performance Counter: %u\n", psrperf);
return 0; return 0;
} }
...@@ -1896,6 +1790,72 @@ DEFINE_SIMPLE_ATTRIBUTE(i915_ring_stop_fops, ...@@ -1896,6 +1790,72 @@ DEFINE_SIMPLE_ATTRIBUTE(i915_ring_stop_fops,
i915_ring_stop_get, i915_ring_stop_set, i915_ring_stop_get, i915_ring_stop_set,
"0x%08llx\n"); "0x%08llx\n");
static int
i915_ring_missed_irq_get(void *data, u64 *val)
{
struct drm_device *dev = data;
struct drm_i915_private *dev_priv = dev->dev_private;
*val = dev_priv->gpu_error.missed_irq_rings;
return 0;
}
static int
i915_ring_missed_irq_set(void *data, u64 val)
{
struct drm_device *dev = data;
struct drm_i915_private *dev_priv = dev->dev_private;
int ret;
/* Lock against concurrent debugfs callers */
ret = mutex_lock_interruptible(&dev->struct_mutex);
if (ret)
return ret;
dev_priv->gpu_error.missed_irq_rings = val;
mutex_unlock(&dev->struct_mutex);
return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(i915_ring_missed_irq_fops,
i915_ring_missed_irq_get, i915_ring_missed_irq_set,
"0x%08llx\n");
static int
i915_ring_test_irq_get(void *data, u64 *val)
{
struct drm_device *dev = data;
struct drm_i915_private *dev_priv = dev->dev_private;
*val = dev_priv->gpu_error.test_irq_rings;
return 0;
}
static int
i915_ring_test_irq_set(void *data, u64 val)
{
struct drm_device *dev = data;
struct drm_i915_private *dev_priv = dev->dev_private;
int ret;
DRM_DEBUG_DRIVER("Masking interrupts on rings 0x%08llx\n", val);
/* Lock against concurrent debugfs callers */
ret = mutex_lock_interruptible(&dev->struct_mutex);
if (ret)
return ret;
dev_priv->gpu_error.test_irq_rings = val;
mutex_unlock(&dev->struct_mutex);
return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(i915_ring_test_irq_fops,
i915_ring_test_irq_get, i915_ring_test_irq_set,
"0x%08llx\n");
#define DROP_UNBOUND 0x1 #define DROP_UNBOUND 0x1
#define DROP_BOUND 0x2 #define DROP_BOUND 0x2
#define DROP_RETIRE 0x4 #define DROP_RETIRE 0x4
...@@ -2156,7 +2116,7 @@ drm_add_fake_info_node(struct drm_minor *minor, ...@@ -2156,7 +2116,7 @@ drm_add_fake_info_node(struct drm_minor *minor,
{ {
struct drm_info_node *node; struct drm_info_node *node;
node = kmalloc(sizeof(struct drm_info_node), GFP_KERNEL); node = kmalloc(sizeof(*node), GFP_KERNEL);
if (node == NULL) { if (node == NULL) {
debugfs_remove(ent); debugfs_remove(ent);
return -ENOMEM; return -ENOMEM;
...@@ -2289,6 +2249,8 @@ static struct i915_debugfs_files { ...@@ -2289,6 +2249,8 @@ static struct i915_debugfs_files {
{"i915_min_freq", &i915_min_freq_fops}, {"i915_min_freq", &i915_min_freq_fops},
{"i915_cache_sharing", &i915_cache_sharing_fops}, {"i915_cache_sharing", &i915_cache_sharing_fops},
{"i915_ring_stop", &i915_ring_stop_fops}, {"i915_ring_stop", &i915_ring_stop_fops},
{"i915_ring_missed_irq", &i915_ring_missed_irq_fops},
{"i915_ring_test_irq", &i915_ring_test_irq_fops},
{"i915_gem_drop_caches", &i915_drop_caches_fops}, {"i915_gem_drop_caches", &i915_drop_caches_fops},
{"i915_error_state", &i915_error_state_fops}, {"i915_error_state", &i915_error_state_fops},
{"i915_next_seqno", &i915_next_seqno_fops}, {"i915_next_seqno", &i915_next_seqno_fops},
......
...@@ -641,7 +641,7 @@ static int i915_batchbuffer(struct drm_device *dev, void *data, ...@@ -641,7 +641,7 @@ static int i915_batchbuffer(struct drm_device *dev, void *data,
if (batch->num_cliprects) { if (batch->num_cliprects) {
cliprects = kcalloc(batch->num_cliprects, cliprects = kcalloc(batch->num_cliprects,
sizeof(struct drm_clip_rect), sizeof(*cliprects),
GFP_KERNEL); GFP_KERNEL);
if (cliprects == NULL) if (cliprects == NULL)
return -ENOMEM; return -ENOMEM;
...@@ -703,7 +703,7 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data, ...@@ -703,7 +703,7 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
if (cmdbuf->num_cliprects) { if (cmdbuf->num_cliprects) {
cliprects = kcalloc(cmdbuf->num_cliprects, cliprects = kcalloc(cmdbuf->num_cliprects,
sizeof(struct drm_clip_rect), GFP_KERNEL); sizeof(*cliprects), GFP_KERNEL);
if (cliprects == NULL) { if (cliprects == NULL) {
ret = -ENOMEM; ret = -ENOMEM;
goto fail_batch_free; goto fail_batch_free;
...@@ -1314,25 +1314,30 @@ static int i915_load_modeset_init(struct drm_device *dev) ...@@ -1314,25 +1314,30 @@ static int i915_load_modeset_init(struct drm_device *dev)
if (ret) if (ret)
goto cleanup_gem_stolen; goto cleanup_gem_stolen;
intel_init_power_well(dev);
/* Keep VGA alive until i915_disable_vga_mem() */
intel_display_power_get(dev, POWER_DOMAIN_VGA);
/* Important: The output setup functions called by modeset_init need /* Important: The output setup functions called by modeset_init need
* working irqs for e.g. gmbus and dp aux transfers. */ * working irqs for e.g. gmbus and dp aux transfers. */
intel_modeset_init(dev); intel_modeset_init(dev);
ret = i915_gem_init(dev); ret = i915_gem_init(dev);
if (ret) if (ret)
goto cleanup_irq; goto cleanup_power;
INIT_WORK(&dev_priv->console_resume_work, intel_console_resume); INIT_WORK(&dev_priv->console_resume_work, intel_console_resume);
intel_init_power_well(dev);
intel_modeset_gem_init(dev); intel_modeset_gem_init(dev);
/* Always safe in the mode setting case. */ /* Always safe in the mode setting case. */
/* FIXME: do pre/post-mode set stuff in core KMS code */ /* FIXME: do pre/post-mode set stuff in core KMS code */
dev->vblank_disable_allowed = true; dev->vblank_disable_allowed = true;
if (INTEL_INFO(dev)->num_pipes == 0) if (INTEL_INFO(dev)->num_pipes == 0) {
intel_display_power_put(dev, POWER_DOMAIN_VGA);
return 0; return 0;
}
ret = intel_fbdev_init(dev); ret = intel_fbdev_init(dev);
if (ret) if (ret)
...@@ -1358,6 +1363,7 @@ static int i915_load_modeset_init(struct drm_device *dev) ...@@ -1358,6 +1363,7 @@ static int i915_load_modeset_init(struct drm_device *dev)
* vgacon_save_screen() works during the handover. * vgacon_save_screen() works during the handover.
*/ */
i915_disable_vga_mem(dev); i915_disable_vga_mem(dev);
intel_display_power_put(dev, POWER_DOMAIN_VGA);
/* Only enable hotplug handling once the fbdev is fully set up. */ /* Only enable hotplug handling once the fbdev is fully set up. */
dev_priv->enable_hotplug_processing = true; dev_priv->enable_hotplug_processing = true;
...@@ -1373,7 +1379,8 @@ static int i915_load_modeset_init(struct drm_device *dev) ...@@ -1373,7 +1379,8 @@ static int i915_load_modeset_init(struct drm_device *dev)
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
i915_gem_cleanup_aliasing_ppgtt(dev); i915_gem_cleanup_aliasing_ppgtt(dev);
drm_mm_takedown(&dev_priv->gtt.base.mm); drm_mm_takedown(&dev_priv->gtt.base.mm);
cleanup_irq: cleanup_power:
intel_display_power_put(dev, POWER_DOMAIN_VGA);
drm_irq_uninstall(dev); drm_irq_uninstall(dev);
cleanup_gem_stolen: cleanup_gem_stolen:
i915_gem_cleanup_stolen(dev); i915_gem_cleanup_stolen(dev);
...@@ -1473,7 +1480,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) ...@@ -1473,7 +1480,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
if (info->gen >= 6 && !drm_core_check_feature(dev, DRIVER_MODESET)) if (info->gen >= 6 && !drm_core_check_feature(dev, DRIVER_MODESET))
return -ENODEV; return -ENODEV;
dev_priv = kzalloc(sizeof(drm_i915_private_t), GFP_KERNEL); dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL);
if (dev_priv == NULL) if (dev_priv == NULL)
return -ENOMEM; return -ENOMEM;
...@@ -1547,7 +1554,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) ...@@ -1547,7 +1554,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
ret = i915_gem_gtt_init(dev); ret = i915_gem_gtt_init(dev);
if (ret) if (ret)
goto put_bridge; goto out_regs;
if (drm_core_check_feature(dev, DRIVER_MODESET)) if (drm_core_check_feature(dev, DRIVER_MODESET))
i915_kick_out_firmware_fb(dev_priv); i915_kick_out_firmware_fb(dev_priv);
...@@ -1576,7 +1583,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) ...@@ -1576,7 +1583,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
aperture_size); aperture_size);
if (dev_priv->gtt.mappable == NULL) { if (dev_priv->gtt.mappable == NULL) {
ret = -EIO; ret = -EIO;
goto out_rmmap; goto out_gtt;
} }
dev_priv->gtt.mtrr = arch_phys_wc_add(dev_priv->gtt.mappable_base, dev_priv->gtt.mtrr = arch_phys_wc_add(dev_priv->gtt.mappable_base,
...@@ -1650,7 +1657,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) ...@@ -1650,7 +1657,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
ret = i915_load_modeset_init(dev); ret = i915_load_modeset_init(dev);
if (ret < 0) { if (ret < 0) {
DRM_ERROR("failed to init modeset\n"); DRM_ERROR("failed to init modeset\n");
goto out_gem_unload; goto out_power_well;
} }
} else { } else {
/* Start out suspended in ums mode. */ /* Start out suspended in ums mode. */
...@@ -1670,6 +1677,10 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) ...@@ -1670,6 +1677,10 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
return 0; return 0;
out_power_well:
if (HAS_POWER_WELL(dev))
i915_remove_power_well(dev);
drm_vblank_cleanup(dev);
out_gem_unload: out_gem_unload:
if (dev_priv->mm.inactive_shrinker.scan_objects) if (dev_priv->mm.inactive_shrinker.scan_objects)
unregister_shrinker(&dev_priv->mm.inactive_shrinker); unregister_shrinker(&dev_priv->mm.inactive_shrinker);
...@@ -1683,12 +1694,17 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) ...@@ -1683,12 +1694,17 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
out_mtrrfree: out_mtrrfree:
arch_phys_wc_del(dev_priv->gtt.mtrr); arch_phys_wc_del(dev_priv->gtt.mtrr);
io_mapping_free(dev_priv->gtt.mappable); io_mapping_free(dev_priv->gtt.mappable);
out_gtt:
list_del(&dev_priv->gtt.base.global_link);
drm_mm_takedown(&dev_priv->gtt.base.mm);
dev_priv->gtt.base.cleanup(&dev_priv->gtt.base); dev_priv->gtt.base.cleanup(&dev_priv->gtt.base);
out_rmmap: out_regs:
pci_iounmap(dev->pdev, dev_priv->regs); pci_iounmap(dev->pdev, dev_priv->regs);
put_bridge: put_bridge:
pci_dev_put(dev_priv->bridge_dev); pci_dev_put(dev_priv->bridge_dev);
free_priv: free_priv:
if (dev_priv->slab)
kmem_cache_destroy(dev_priv->slab);
kfree(dev_priv); kfree(dev_priv);
return ret; return ret;
} }
...@@ -1778,8 +1794,8 @@ int i915_driver_unload(struct drm_device *dev) ...@@ -1778,8 +1794,8 @@ int i915_driver_unload(struct drm_device *dev)
list_del(&dev_priv->gtt.base.global_link); list_del(&dev_priv->gtt.base.global_link);
WARN_ON(!list_empty(&dev_priv->vm_list)); WARN_ON(!list_empty(&dev_priv->vm_list));
drm_mm_takedown(&dev_priv->gtt.base.mm); drm_mm_takedown(&dev_priv->gtt.base.mm);
if (dev_priv->regs != NULL)
pci_iounmap(dev->pdev, dev_priv->regs); drm_vblank_cleanup(dev);
intel_teardown_gmbus(dev); intel_teardown_gmbus(dev);
intel_teardown_mchbar(dev); intel_teardown_mchbar(dev);
...@@ -1789,6 +1805,10 @@ int i915_driver_unload(struct drm_device *dev) ...@@ -1789,6 +1805,10 @@ int i915_driver_unload(struct drm_device *dev)
dev_priv->gtt.base.cleanup(&dev_priv->gtt.base); dev_priv->gtt.base.cleanup(&dev_priv->gtt.base);
intel_uncore_fini(dev);
if (dev_priv->regs != NULL)
pci_iounmap(dev->pdev, dev_priv->regs);
if (dev_priv->slab) if (dev_priv->slab)
kmem_cache_destroy(dev_priv->slab); kmem_cache_destroy(dev_priv->slab);
...@@ -1800,19 +1820,11 @@ int i915_driver_unload(struct drm_device *dev) ...@@ -1800,19 +1820,11 @@ int i915_driver_unload(struct drm_device *dev)
int i915_driver_open(struct drm_device *dev, struct drm_file *file) int i915_driver_open(struct drm_device *dev, struct drm_file *file)
{ {
struct drm_i915_file_private *file_priv; int ret;
DRM_DEBUG_DRIVER("\n");
file_priv = kzalloc(sizeof(*file_priv), GFP_KERNEL);
if (!file_priv)
return -ENOMEM;
file->driver_priv = file_priv;
spin_lock_init(&file_priv->mm.lock);
INIT_LIST_HEAD(&file_priv->mm.request_list);
idr_init(&file_priv->context_idr); ret = i915_gem_open(dev, file);
if (ret)
return ret;
return 0; return 0;
} }
......
...@@ -416,7 +416,7 @@ void intel_detect_pch(struct drm_device *dev) ...@@ -416,7 +416,7 @@ void intel_detect_pch(struct drm_device *dev)
} else if (id == INTEL_PCH_PPT_DEVICE_ID_TYPE) { } else if (id == INTEL_PCH_PPT_DEVICE_ID_TYPE) {
/* PantherPoint is CPT compatible */ /* PantherPoint is CPT compatible */
dev_priv->pch_type = PCH_CPT; dev_priv->pch_type = PCH_CPT;
DRM_DEBUG_KMS("Found PatherPoint PCH\n"); DRM_DEBUG_KMS("Found PantherPoint PCH\n");
WARN_ON(!(IS_GEN6(dev) || IS_IVYBRIDGE(dev))); WARN_ON(!(IS_GEN6(dev) || IS_IVYBRIDGE(dev)));
} else if (id == INTEL_PCH_LPT_DEVICE_ID_TYPE) { } else if (id == INTEL_PCH_LPT_DEVICE_ID_TYPE) {
dev_priv->pch_type = PCH_LPT; dev_priv->pch_type = PCH_LPT;
...@@ -581,6 +581,8 @@ static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings) ...@@ -581,6 +581,8 @@ static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings)
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
int error = 0; int error = 0;
intel_uncore_early_sanitize(dev);
intel_uncore_sanitize(dev); intel_uncore_sanitize(dev);
if (drm_core_check_feature(dev, DRIVER_MODESET) && if (drm_core_check_feature(dev, DRIVER_MODESET) &&
...@@ -590,6 +592,8 @@ static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings) ...@@ -590,6 +592,8 @@ static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings)
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
} }
intel_init_power_well(dev);
i915_restore_state(dev); i915_restore_state(dev);
intel_opregion_setup(dev); intel_opregion_setup(dev);
...@@ -605,8 +609,6 @@ static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings) ...@@ -605,8 +609,6 @@ static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings)
/* We need working interrupts for modeset enabling ... */ /* We need working interrupts for modeset enabling ... */
drm_irq_install(dev); drm_irq_install(dev);
intel_init_power_well(dev);
intel_modeset_init_hw(dev); intel_modeset_init_hw(dev);
drm_modeset_lock_all(dev); drm_modeset_lock_all(dev);
......
...@@ -324,7 +324,7 @@ struct drm_i915_error_state { ...@@ -324,7 +324,7 @@ struct drm_i915_error_state {
u32 dirty:1; u32 dirty:1;
u32 purgeable:1; u32 purgeable:1;
s32 ring:4; s32 ring:4;
u32 cache_level:2; u32 cache_level:3;
} **active_bo, **pinned_bo; } **active_bo, **pinned_bo;
u32 *active_bo_count, *pinned_bo_count; u32 *active_bo_count, *pinned_bo_count;
struct intel_overlay_error_state *overlay; struct intel_overlay_error_state *overlay;
...@@ -408,6 +408,8 @@ struct intel_uncore { ...@@ -408,6 +408,8 @@ struct intel_uncore {
unsigned fifo_count; unsigned fifo_count;
unsigned forcewake_count; unsigned forcewake_count;
struct delayed_work force_wake_work;
}; };
#define DEV_INFO_FOR_EACH_FLAG(func, sep) \ #define DEV_INFO_FOR_EACH_FLAG(func, sep) \
...@@ -642,17 +644,9 @@ struct i915_fbc { ...@@ -642,17 +644,9 @@ struct i915_fbc {
} no_fbc_reason; } no_fbc_reason;
}; };
enum no_psr_reason { struct i915_psr {
PSR_NO_SOURCE, /* Not supported on platform */ bool sink_support;
PSR_NO_SINK, /* Not supported by panel */ bool source_ok;
PSR_MODULE_PARAM,
PSR_CRTC_NOT_ACTIVE,
PSR_PWR_WELL_ENABLED,
PSR_NOT_TILED,
PSR_SPRITE_ENABLED,
PSR_S3D_ENABLED,
PSR_INTERLACED_ENABLED,
PSR_HSW_NOT_DDIA,
}; };
enum intel_pch { enum intel_pch {
...@@ -842,17 +836,19 @@ struct intel_gen6_power_mgmt { ...@@ -842,17 +836,19 @@ struct intel_gen6_power_mgmt {
struct work_struct work; struct work_struct work;
u32 pm_iir; u32 pm_iir;
/* On vlv we need to manually drop to Vmin with a delayed work. */
struct delayed_work vlv_work;
/* The below variables an all the rps hw state are protected by /* The below variables an all the rps hw state are protected by
* dev->struct mutext. */ * dev->struct mutext. */
u8 cur_delay; u8 cur_delay;
u8 min_delay; u8 min_delay;
u8 max_delay; u8 max_delay;
u8 rpe_delay; u8 rpe_delay;
u8 rp1_delay;
u8 rp0_delay;
u8 hw_max; u8 hw_max;
int last_adj;
enum { LOW_POWER, BETWEEN, HIGH_POWER } power;
struct delayed_work delayed_resume_work; struct delayed_work delayed_resume_work;
/* /*
...@@ -962,6 +958,15 @@ struct i915_gem_mm { ...@@ -962,6 +958,15 @@ struct i915_gem_mm {
*/ */
struct delayed_work retire_work; struct delayed_work retire_work;
/**
* When we detect an idle GPU, we want to turn on
* powersaving features. So once we see that there
* are no more requests outstanding and no more
* arrive within a small period of time, we fire
* off the idle_work.
*/
struct delayed_work idle_work;
/** /**
* Are we in a non-interruptible section of code like * Are we in a non-interruptible section of code like
* modesetting? * modesetting?
...@@ -1011,6 +1016,9 @@ struct i915_gpu_error { ...@@ -1011,6 +1016,9 @@ struct i915_gpu_error {
struct drm_i915_error_state *first_error; struct drm_i915_error_state *first_error;
struct work_struct work; struct work_struct work;
unsigned long missed_irq_rings;
/** /**
* State variable and reset counter controlling the reset flow * State variable and reset counter controlling the reset flow
* *
...@@ -1049,6 +1057,9 @@ struct i915_gpu_error { ...@@ -1049,6 +1057,9 @@ struct i915_gpu_error {
/* For gpu hang simulation. */ /* For gpu hang simulation. */
unsigned int stop_rings; unsigned int stop_rings;
/* For missed irq/seqno simulation. */
unsigned int test_irq_rings;
}; };
enum modeset_restore { enum modeset_restore {
...@@ -1057,6 +1068,14 @@ enum modeset_restore { ...@@ -1057,6 +1068,14 @@ enum modeset_restore {
MODESET_SUSPENDED, MODESET_SUSPENDED,
}; };
struct ddi_vbt_port_info {
uint8_t hdmi_level_shift;
uint8_t supports_dvi:1;
uint8_t supports_hdmi:1;
uint8_t supports_dp:1;
};
struct intel_vbt_data { struct intel_vbt_data {
struct drm_display_mode *lfp_lvds_vbt_mode; /* if any */ struct drm_display_mode *lfp_lvds_vbt_mode; /* if any */
struct drm_display_mode *sdvo_lvds_vbt_mode; /* if any */ struct drm_display_mode *sdvo_lvds_vbt_mode; /* if any */
...@@ -1090,7 +1109,9 @@ struct intel_vbt_data { ...@@ -1090,7 +1109,9 @@ struct intel_vbt_data {
int crt_ddc_pin; int crt_ddc_pin;
int child_dev_num; int child_dev_num;
struct child_device_config *child_dev; union child_device_config *child_dev;
struct ddi_vbt_port_info ddi_port_info[I915_MAX_PORTS];
}; };
enum intel_ddb_partitioning { enum intel_ddb_partitioning {
...@@ -1327,7 +1348,7 @@ typedef struct drm_i915_private { ...@@ -1327,7 +1348,7 @@ typedef struct drm_i915_private {
/* Haswell power well */ /* Haswell power well */
struct i915_power_well power_well; struct i915_power_well power_well;
enum no_psr_reason no_psr_reason; struct i915_psr psr;
struct i915_gpu_error gpu_error; struct i915_gpu_error gpu_error;
...@@ -1579,13 +1600,17 @@ struct drm_i915_gem_request { ...@@ -1579,13 +1600,17 @@ struct drm_i915_gem_request {
}; };
struct drm_i915_file_private { struct drm_i915_file_private {
struct drm_i915_private *dev_priv;
struct { struct {
spinlock_t lock; spinlock_t lock;
struct list_head request_list; struct list_head request_list;
struct delayed_work idle_work;
} mm; } mm;
struct idr context_idr; struct idr context_idr;
struct i915_ctx_hang_stats hang_stats; struct i915_ctx_hang_stats hang_stats;
atomic_t rps_wait_boost;
}; };
#define INTEL_INFO(dev) (to_i915(dev)->info) #define INTEL_INFO(dev) (to_i915(dev)->info)
...@@ -1662,7 +1687,6 @@ struct drm_i915_file_private { ...@@ -1662,7 +1687,6 @@ struct drm_i915_file_private {
#define SUPPORTS_DIGITAL_OUTPUTS(dev) (!IS_GEN2(dev) && !IS_PINEVIEW(dev)) #define SUPPORTS_DIGITAL_OUTPUTS(dev) (!IS_GEN2(dev) && !IS_PINEVIEW(dev))
#define SUPPORTS_INTEGRATED_HDMI(dev) (IS_G4X(dev) || IS_GEN5(dev)) #define SUPPORTS_INTEGRATED_HDMI(dev) (IS_G4X(dev) || IS_GEN5(dev))
#define SUPPORTS_INTEGRATED_DP(dev) (IS_G4X(dev) || IS_GEN5(dev)) #define SUPPORTS_INTEGRATED_DP(dev) (IS_G4X(dev) || IS_GEN5(dev))
#define SUPPORTS_EDP(dev) (IS_IRONLAKE_M(dev))
#define SUPPORTS_TV(dev) (INTEL_INFO(dev)->supports_tv) #define SUPPORTS_TV(dev) (INTEL_INFO(dev)->supports_tv)
#define I915_HAS_HOTPLUG(dev) (INTEL_INFO(dev)->has_hotplug) #define I915_HAS_HOTPLUG(dev) (INTEL_INFO(dev)->has_hotplug)
...@@ -1675,6 +1699,7 @@ struct drm_i915_file_private { ...@@ -1675,6 +1699,7 @@ struct drm_i915_file_private {
#define HAS_DDI(dev) (INTEL_INFO(dev)->has_ddi) #define HAS_DDI(dev) (INTEL_INFO(dev)->has_ddi)
#define HAS_POWER_WELL(dev) (IS_HASWELL(dev)) #define HAS_POWER_WELL(dev) (IS_HASWELL(dev))
#define HAS_FPGA_DBG_UNCLAIMED(dev) (INTEL_INFO(dev)->has_fpga_dbg) #define HAS_FPGA_DBG_UNCLAIMED(dev) (INTEL_INFO(dev)->has_fpga_dbg)
#define HAS_PSR(dev) (IS_HASWELL(dev))
#define INTEL_PCH_DEVICE_ID_MASK 0xff00 #define INTEL_PCH_DEVICE_ID_MASK 0xff00
#define INTEL_PCH_IBX_DEVICE_ID_TYPE 0x3b00 #define INTEL_PCH_IBX_DEVICE_ID_TYPE 0x3b00
...@@ -1791,6 +1816,7 @@ extern void intel_uncore_early_sanitize(struct drm_device *dev); ...@@ -1791,6 +1816,7 @@ extern void intel_uncore_early_sanitize(struct drm_device *dev);
extern void intel_uncore_init(struct drm_device *dev); extern void intel_uncore_init(struct drm_device *dev);
extern void intel_uncore_clear_errors(struct drm_device *dev); extern void intel_uncore_clear_errors(struct drm_device *dev);
extern void intel_uncore_check_errors(struct drm_device *dev); extern void intel_uncore_check_errors(struct drm_device *dev);
extern void intel_uncore_fini(struct drm_device *dev);
void void
i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask); i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask);
...@@ -1891,9 +1917,8 @@ static inline void i915_gem_object_unpin_pages(struct drm_i915_gem_object *obj) ...@@ -1891,9 +1917,8 @@ static inline void i915_gem_object_unpin_pages(struct drm_i915_gem_object *obj)
int __must_check i915_mutex_lock_interruptible(struct drm_device *dev); int __must_check i915_mutex_lock_interruptible(struct drm_device *dev);
int i915_gem_object_sync(struct drm_i915_gem_object *obj, int i915_gem_object_sync(struct drm_i915_gem_object *obj,
struct intel_ring_buffer *to); struct intel_ring_buffer *to);
void i915_gem_object_move_to_active(struct drm_i915_gem_object *obj, void i915_vma_move_to_active(struct i915_vma *vma,
struct intel_ring_buffer *ring); struct intel_ring_buffer *ring);
int i915_gem_dumb_create(struct drm_file *file_priv, int i915_gem_dumb_create(struct drm_file *file_priv,
struct drm_device *dev, struct drm_device *dev,
struct drm_mode_create_dumb *args); struct drm_mode_create_dumb *args);
...@@ -1934,7 +1959,7 @@ i915_gem_object_unpin_fence(struct drm_i915_gem_object *obj) ...@@ -1934,7 +1959,7 @@ i915_gem_object_unpin_fence(struct drm_i915_gem_object *obj)
} }
} }
void i915_gem_retire_requests(struct drm_device *dev); bool i915_gem_retire_requests(struct drm_device *dev);
void i915_gem_retire_requests_ring(struct intel_ring_buffer *ring); void i915_gem_retire_requests_ring(struct intel_ring_buffer *ring);
int __must_check i915_gem_check_wedge(struct i915_gpu_error *error, int __must_check i915_gem_check_wedge(struct i915_gpu_error *error,
bool interruptible); bool interruptible);
...@@ -1985,6 +2010,7 @@ int i915_gem_attach_phys_object(struct drm_device *dev, ...@@ -1985,6 +2010,7 @@ int i915_gem_attach_phys_object(struct drm_device *dev,
void i915_gem_detach_phys_object(struct drm_device *dev, void i915_gem_detach_phys_object(struct drm_device *dev,
struct drm_i915_gem_object *obj); struct drm_i915_gem_object *obj);
void i915_gem_free_all_phys_object(struct drm_device *dev); void i915_gem_free_all_phys_object(struct drm_device *dev);
int i915_gem_open(struct drm_device *dev, struct drm_file *file);
void i915_gem_release(struct drm_device *dev, struct drm_file *file); void i915_gem_release(struct drm_device *dev, struct drm_file *file);
uint32_t uint32_t
...@@ -2016,6 +2042,9 @@ struct i915_vma *i915_gem_obj_to_vma(struct drm_i915_gem_object *obj, ...@@ -2016,6 +2042,9 @@ struct i915_vma *i915_gem_obj_to_vma(struct drm_i915_gem_object *obj,
struct i915_vma * struct i915_vma *
i915_gem_obj_lookup_or_create_vma(struct drm_i915_gem_object *obj, i915_gem_obj_lookup_or_create_vma(struct drm_i915_gem_object *obj,
struct i915_address_space *vm); struct i915_address_space *vm);
struct i915_vma *i915_gem_obj_to_ggtt(struct drm_i915_gem_object *obj);
/* Some GGTT VM helpers */ /* Some GGTT VM helpers */
#define obj_to_ggtt(obj) \ #define obj_to_ggtt(obj) \
(&((struct drm_i915_private *)(obj)->base.dev->dev_private)->gtt.base) (&((struct drm_i915_private *)(obj)->base.dev->dev_private)->gtt.base)
...@@ -2052,7 +2081,6 @@ i915_gem_obj_ggtt_pin(struct drm_i915_gem_object *obj, ...@@ -2052,7 +2081,6 @@ i915_gem_obj_ggtt_pin(struct drm_i915_gem_object *obj,
return i915_gem_object_pin(obj, obj_to_ggtt(obj), alignment, return i915_gem_object_pin(obj, obj_to_ggtt(obj), alignment,
map_and_fenceable, nonblocking); map_and_fenceable, nonblocking);
} }
#undef obj_to_ggtt
/* i915_gem_context.c */ /* i915_gem_context.c */
void i915_gem_context_init(struct drm_device *dev); void i915_gem_context_init(struct drm_device *dev);
......
This diff is collapsed.
...@@ -453,11 +453,8 @@ static int do_switch(struct i915_hw_context *to) ...@@ -453,11 +453,8 @@ static int do_switch(struct i915_hw_context *to)
* MI_SET_CONTEXT instead of when the next seqno has completed. * MI_SET_CONTEXT instead of when the next seqno has completed.
*/ */
if (from != NULL) { if (from != NULL) {
struct drm_i915_private *dev_priv = from->obj->base.dev->dev_private;
struct i915_address_space *ggtt = &dev_priv->gtt.base;
from->obj->base.read_domains = I915_GEM_DOMAIN_INSTRUCTION; from->obj->base.read_domains = I915_GEM_DOMAIN_INSTRUCTION;
list_move_tail(&i915_gem_obj_to_vma(from->obj, ggtt)->mm_list, &ggtt->active_list); i915_vma_move_to_active(i915_gem_obj_to_ggtt(from->obj), ring);
i915_gem_object_move_to_active(from->obj, ring);
/* As long as MI_SET_CONTEXT is serializing, ie. it flushes the /* As long as MI_SET_CONTEXT is serializing, ie. it flushes the
* whole damn pipeline, we don't need to explicitly mark the * whole damn pipeline, we don't need to explicitly mark the
* object dirty. The only exception is that the context must be * object dirty. The only exception is that the context must be
......
...@@ -175,6 +175,8 @@ int i915_gem_evict_vm(struct i915_address_space *vm, bool do_idle) ...@@ -175,6 +175,8 @@ int i915_gem_evict_vm(struct i915_address_space *vm, bool do_idle)
struct i915_vma *vma, *next; struct i915_vma *vma, *next;
int ret; int ret;
trace_i915_gem_evict_vm(vm);
if (do_idle) { if (do_idle) {
ret = i915_gpu_idle(vm->dev); ret = i915_gpu_idle(vm->dev);
if (ret) if (ret)
......
...@@ -48,15 +48,15 @@ eb_create(struct drm_i915_gem_execbuffer2 *args, struct i915_address_space *vm) ...@@ -48,15 +48,15 @@ eb_create(struct drm_i915_gem_execbuffer2 *args, struct i915_address_space *vm)
struct eb_vmas *eb = NULL; struct eb_vmas *eb = NULL;
if (args->flags & I915_EXEC_HANDLE_LUT) { if (args->flags & I915_EXEC_HANDLE_LUT) {
int size = args->buffer_count; unsigned size = args->buffer_count;
size *= sizeof(struct i915_vma *); size *= sizeof(struct i915_vma *);
size += sizeof(struct eb_vmas); size += sizeof(struct eb_vmas);
eb = kmalloc(size, GFP_TEMPORARY | __GFP_NOWARN | __GFP_NORETRY); eb = kmalloc(size, GFP_TEMPORARY | __GFP_NOWARN | __GFP_NORETRY);
} }
if (eb == NULL) { if (eb == NULL) {
int size = args->buffer_count; unsigned size = args->buffer_count;
int count = PAGE_SIZE / sizeof(struct hlist_head) / 2; unsigned count = PAGE_SIZE / sizeof(struct hlist_head) / 2;
BUILD_BUG_ON_NOT_POWER_OF_2(PAGE_SIZE / sizeof(struct hlist_head)); BUILD_BUG_ON_NOT_POWER_OF_2(PAGE_SIZE / sizeof(struct hlist_head));
while (count > 2*size) while (count > 2*size)
count >>= 1; count >>= 1;
...@@ -667,7 +667,7 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev, ...@@ -667,7 +667,7 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev,
bool need_relocs; bool need_relocs;
int *reloc_offset; int *reloc_offset;
int i, total, ret; int i, total, ret;
int count = args->buffer_count; unsigned count = args->buffer_count;
if (WARN_ON(list_empty(&eb->vmas))) if (WARN_ON(list_empty(&eb->vmas)))
return 0; return 0;
...@@ -818,8 +818,8 @@ validate_exec_list(struct drm_i915_gem_exec_object2 *exec, ...@@ -818,8 +818,8 @@ validate_exec_list(struct drm_i915_gem_exec_object2 *exec,
int count) int count)
{ {
int i; int i;
int relocs_total = 0; unsigned relocs_total = 0;
int relocs_max = INT_MAX / sizeof(struct drm_i915_gem_relocation_entry); unsigned relocs_max = UINT_MAX / sizeof(struct drm_i915_gem_relocation_entry);
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
char __user *ptr = to_user_ptr(exec[i].relocs_ptr); char __user *ptr = to_user_ptr(exec[i].relocs_ptr);
...@@ -872,8 +872,7 @@ i915_gem_execbuffer_move_to_active(struct list_head *vmas, ...@@ -872,8 +872,7 @@ i915_gem_execbuffer_move_to_active(struct list_head *vmas,
obj->base.read_domains = obj->base.pending_read_domains; obj->base.read_domains = obj->base.pending_read_domains;
obj->fenced_gpu_access = obj->pending_fenced_gpu_access; obj->fenced_gpu_access = obj->pending_fenced_gpu_access;
list_move_tail(&vma->mm_list, &vma->vm->active_list); i915_vma_move_to_active(vma, ring);
i915_gem_object_move_to_active(obj, ring);
if (obj->base.write_domain) { if (obj->base.write_domain) {
obj->dirty = 1; obj->dirty = 1;
obj->last_write_seqno = intel_ring_get_seqno(ring); obj->last_write_seqno = intel_ring_get_seqno(ring);
...@@ -1047,7 +1046,8 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, ...@@ -1047,7 +1046,8 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
return -EINVAL; return -EINVAL;
} }
cliprects = kmalloc(args->num_cliprects * sizeof(*cliprects), cliprects = kcalloc(args->num_cliprects,
sizeof(*cliprects),
GFP_KERNEL); GFP_KERNEL);
if (cliprects == NULL) { if (cliprects == NULL) {
ret = -ENOMEM; ret = -ENOMEM;
......
...@@ -336,7 +336,7 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt) ...@@ -336,7 +336,7 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
ppgtt->base.insert_entries = gen6_ppgtt_insert_entries; ppgtt->base.insert_entries = gen6_ppgtt_insert_entries;
ppgtt->base.cleanup = gen6_ppgtt_cleanup; ppgtt->base.cleanup = gen6_ppgtt_cleanup;
ppgtt->base.scratch = dev_priv->gtt.base.scratch; ppgtt->base.scratch = dev_priv->gtt.base.scratch;
ppgtt->pt_pages = kzalloc(sizeof(struct page *)*ppgtt->num_pd_entries, ppgtt->pt_pages = kcalloc(ppgtt->num_pd_entries, sizeof(struct page *),
GFP_KERNEL); GFP_KERNEL);
if (!ppgtt->pt_pages) if (!ppgtt->pt_pages)
return -ENOMEM; return -ENOMEM;
...@@ -347,7 +347,7 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt) ...@@ -347,7 +347,7 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
goto err_pt_alloc; goto err_pt_alloc;
} }
ppgtt->pt_dma_addr = kzalloc(sizeof(dma_addr_t) *ppgtt->num_pd_entries, ppgtt->pt_dma_addr = kcalloc(ppgtt->num_pd_entries, sizeof(dma_addr_t),
GFP_KERNEL); GFP_KERNEL);
if (!ppgtt->pt_dma_addr) if (!ppgtt->pt_dma_addr)
goto err_pt_alloc; goto err_pt_alloc;
......
...@@ -393,7 +393,7 @@ i915_gem_set_tiling(struct drm_device *dev, void *data, ...@@ -393,7 +393,7 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
/* Try to preallocate memory required to save swizzling on put-pages */ /* Try to preallocate memory required to save swizzling on put-pages */
if (i915_gem_object_needs_bit17_swizzle(obj)) { if (i915_gem_object_needs_bit17_swizzle(obj)) {
if (obj->bit_17 == NULL) { if (obj->bit_17 == NULL) {
obj->bit_17 = kmalloc(BITS_TO_LONGS(obj->base.size >> PAGE_SHIFT) * obj->bit_17 = kcalloc(BITS_TO_LONGS(obj->base.size >> PAGE_SHIFT),
sizeof(long), GFP_KERNEL); sizeof(long), GFP_KERNEL);
} }
} else { } else {
...@@ -504,8 +504,8 @@ i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj) ...@@ -504,8 +504,8 @@ i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj)
int i; int i;
if (obj->bit_17 == NULL) { if (obj->bit_17 == NULL) {
obj->bit_17 = kmalloc(BITS_TO_LONGS(page_count) * obj->bit_17 = kcalloc(BITS_TO_LONGS(page_count),
sizeof(long), GFP_KERNEL); sizeof(long), GFP_KERNEL);
if (obj->bit_17 == NULL) { if (obj->bit_17 == NULL) {
DRM_ERROR("Failed to allocate memory for bit 17 " DRM_ERROR("Failed to allocate memory for bit 17 "
"record\n"); "record\n");
......
...@@ -311,6 +311,7 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, ...@@ -311,6 +311,7 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
err_printf(m, "FORCEWAKE: 0x%08x\n", error->forcewake); err_printf(m, "FORCEWAKE: 0x%08x\n", error->forcewake);
err_printf(m, "DERRMR: 0x%08x\n", error->derrmr); err_printf(m, "DERRMR: 0x%08x\n", error->derrmr);
err_printf(m, "CCID: 0x%08x\n", error->ccid); err_printf(m, "CCID: 0x%08x\n", error->ccid);
err_printf(m, "Missed interrupts: 0x%08lx\n", dev_priv->gpu_error.missed_irq_rings);
for (i = 0; i < dev_priv->num_fence_regs; i++) for (i = 0; i < dev_priv->num_fence_regs; i++)
err_printf(m, " fence[%d] = %08llx\n", i, error->fence[i]); err_printf(m, " fence[%d] = %08llx\n", i, error->fence[i]);
...@@ -793,7 +794,7 @@ static void i915_gem_record_rings(struct drm_device *dev, ...@@ -793,7 +794,7 @@ static void i915_gem_record_rings(struct drm_device *dev,
error->ring[i].num_requests = count; error->ring[i].num_requests = count;
error->ring[i].requests = error->ring[i].requests =
kmalloc(count*sizeof(struct drm_i915_error_request), kcalloc(count, sizeof(*error->ring[i].requests),
GFP_ATOMIC); GFP_ATOMIC);
if (error->ring[i].requests == NULL) { if (error->ring[i].requests == NULL) {
error->ring[i].num_requests = 0; error->ring[i].num_requests = 0;
...@@ -835,7 +836,7 @@ static void i915_gem_capture_vm(struct drm_i915_private *dev_priv, ...@@ -835,7 +836,7 @@ static void i915_gem_capture_vm(struct drm_i915_private *dev_priv,
error->pinned_bo_count[ndx] = i - error->active_bo_count[ndx]; error->pinned_bo_count[ndx] = i - error->active_bo_count[ndx];
if (i) { if (i) {
active_bo = kmalloc(sizeof(*active_bo)*i, GFP_ATOMIC); active_bo = kcalloc(i, sizeof(*active_bo), GFP_ATOMIC);
if (active_bo) if (active_bo)
pinned_bo = active_bo + error->active_bo_count[ndx]; pinned_bo = active_bo + error->active_bo_count[ndx];
} }
...@@ -1012,6 +1013,7 @@ const char *i915_cache_level_str(int type) ...@@ -1012,6 +1013,7 @@ const char *i915_cache_level_str(int type)
case I915_CACHE_NONE: return " uncached"; case I915_CACHE_NONE: return " uncached";
case I915_CACHE_LLC: return " snooped or LLC"; case I915_CACHE_LLC: return " snooped or LLC";
case I915_CACHE_L3_LLC: return " L3+LLC"; case I915_CACHE_L3_LLC: return " L3+LLC";
case I915_CACHE_WT: return " WT";
default: return ""; default: return "";
} }
} }
......
...@@ -807,7 +807,7 @@ static void notify_ring(struct drm_device *dev, ...@@ -807,7 +807,7 @@ static void notify_ring(struct drm_device *dev,
if (ring->obj == NULL) if (ring->obj == NULL)
return; return;
trace_i915_gem_request_complete(ring, ring->get_seqno(ring, false)); trace_i915_gem_request_complete(ring);
wake_up_all(&ring->irq_queue); wake_up_all(&ring->irq_queue);
i915_queue_hangcheck(dev); i915_queue_hangcheck(dev);
...@@ -818,7 +818,7 @@ static void gen6_pm_rps_work(struct work_struct *work) ...@@ -818,7 +818,7 @@ static void gen6_pm_rps_work(struct work_struct *work)
drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t, drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t,
rps.work); rps.work);
u32 pm_iir; u32 pm_iir;
u8 new_delay; int new_delay, adj;
spin_lock_irq(&dev_priv->irq_lock); spin_lock_irq(&dev_priv->irq_lock);
pm_iir = dev_priv->rps.pm_iir; pm_iir = dev_priv->rps.pm_iir;
...@@ -835,40 +835,49 @@ static void gen6_pm_rps_work(struct work_struct *work) ...@@ -835,40 +835,49 @@ static void gen6_pm_rps_work(struct work_struct *work)
mutex_lock(&dev_priv->rps.hw_lock); mutex_lock(&dev_priv->rps.hw_lock);
adj = dev_priv->rps.last_adj;
if (pm_iir & GEN6_PM_RP_UP_THRESHOLD) { if (pm_iir & GEN6_PM_RP_UP_THRESHOLD) {
new_delay = dev_priv->rps.cur_delay + 1; if (adj > 0)
adj *= 2;
else
adj = 1;
new_delay = dev_priv->rps.cur_delay + adj;
/* /*
* For better performance, jump directly * For better performance, jump directly
* to RPe if we're below it. * to RPe if we're below it.
*/ */
if (IS_VALLEYVIEW(dev_priv->dev) && if (new_delay < dev_priv->rps.rpe_delay)
dev_priv->rps.cur_delay < dev_priv->rps.rpe_delay)
new_delay = dev_priv->rps.rpe_delay; new_delay = dev_priv->rps.rpe_delay;
} else } else if (pm_iir & GEN6_PM_RP_DOWN_TIMEOUT) {
new_delay = dev_priv->rps.cur_delay - 1; if (dev_priv->rps.cur_delay > dev_priv->rps.rpe_delay)
new_delay = dev_priv->rps.rpe_delay;
else
new_delay = dev_priv->rps.min_delay;
adj = 0;
} else if (pm_iir & GEN6_PM_RP_DOWN_THRESHOLD) {
if (adj < 0)
adj *= 2;
else
adj = -1;
new_delay = dev_priv->rps.cur_delay + adj;
} else { /* unknown event */
new_delay = dev_priv->rps.cur_delay;
}
/* sysfs frequency interfaces may have snuck in while servicing the /* sysfs frequency interfaces may have snuck in while servicing the
* interrupt * interrupt
*/ */
if (new_delay >= dev_priv->rps.min_delay && if (new_delay < (int)dev_priv->rps.min_delay)
new_delay <= dev_priv->rps.max_delay) { new_delay = dev_priv->rps.min_delay;
if (IS_VALLEYVIEW(dev_priv->dev)) if (new_delay > (int)dev_priv->rps.max_delay)
valleyview_set_rps(dev_priv->dev, new_delay); new_delay = dev_priv->rps.max_delay;
else dev_priv->rps.last_adj = new_delay - dev_priv->rps.cur_delay;
gen6_set_rps(dev_priv->dev, new_delay);
} if (IS_VALLEYVIEW(dev_priv->dev))
valleyview_set_rps(dev_priv->dev, new_delay);
if (IS_VALLEYVIEW(dev_priv->dev)) { else
/* gen6_set_rps(dev_priv->dev, new_delay);
* On VLV, when we enter RC6 we may not be at the minimum
* voltage level, so arm a timer to check. It should only
* fire when there's activity or once after we've entered
* RC6, and then won't be re-armed until the next RPS interrupt.
*/
mod_delayed_work(dev_priv->wq, &dev_priv->rps.vlv_work,
msecs_to_jiffies(100));
}
mutex_unlock(&dev_priv->rps.hw_lock); mutex_unlock(&dev_priv->rps.hw_lock);
} }
...@@ -2039,10 +2048,13 @@ static void i915_hangcheck_elapsed(unsigned long data) ...@@ -2039,10 +2048,13 @@ static void i915_hangcheck_elapsed(unsigned long data)
if (waitqueue_active(&ring->irq_queue)) { if (waitqueue_active(&ring->irq_queue)) {
/* Issue a wake-up to catch stuck h/w. */ /* Issue a wake-up to catch stuck h/w. */
DRM_ERROR("Hangcheck timer elapsed... %s idle\n", if (!test_and_set_bit(ring->id, &dev_priv->gpu_error.missed_irq_rings)) {
ring->name); DRM_ERROR("Hangcheck timer elapsed... %s idle\n",
wake_up_all(&ring->irq_queue); ring->name);
ring->hangcheck.score += HUNG; wake_up_all(&ring->irq_queue);
}
/* Safeguard against driver failure */
ring->hangcheck.score += BUSY;
} else } else
busy = false; busy = false;
} else { } else {
......
...@@ -361,6 +361,15 @@ ...@@ -361,6 +361,15 @@
#define PUNIT_OPCODE_REG_READ 6 #define PUNIT_OPCODE_REG_READ 6
#define PUNIT_OPCODE_REG_WRITE 7 #define PUNIT_OPCODE_REG_WRITE 7
#define PUNIT_REG_PWRGT_CTRL 0x60
#define PUNIT_REG_PWRGT_STATUS 0x61
#define PUNIT_CLK_GATE 1
#define PUNIT_PWR_RESET 2
#define PUNIT_PWR_GATE 3
#define RENDER_PWRGT (PUNIT_PWR_GATE << 0)
#define MEDIA_PWRGT (PUNIT_PWR_GATE << 2)
#define DISP2D_PWRGT (PUNIT_PWR_GATE << 6)
#define PUNIT_REG_GPU_LFM 0xd3 #define PUNIT_REG_GPU_LFM 0xd3
#define PUNIT_REG_GPU_FREQ_REQ 0xd4 #define PUNIT_REG_GPU_FREQ_REQ 0xd4
#define PUNIT_REG_GPU_FREQ_STS 0xd8 #define PUNIT_REG_GPU_FREQ_STS 0xd8
...@@ -382,6 +391,8 @@ ...@@ -382,6 +391,8 @@
#define FB_FMAX_VMIN_FREQ_LO_MASK 0xf8000000 #define FB_FMAX_VMIN_FREQ_LO_MASK 0xf8000000
/* vlv2 north clock has */ /* vlv2 north clock has */
#define CCK_FUSE_REG 0x8
#define CCK_FUSE_HPLL_FREQ_MASK 0x3
#define CCK_REG_DSI_PLL_FUSE 0x44 #define CCK_REG_DSI_PLL_FUSE 0x44
#define CCK_REG_DSI_PLL_CONTROL 0x48 #define CCK_REG_DSI_PLL_CONTROL 0x48
#define DSI_PLL_VCO_EN (1 << 31) #define DSI_PLL_VCO_EN (1 << 31)
...@@ -428,7 +439,7 @@ ...@@ -428,7 +439,7 @@
#define DPIO_MODSEL1 (1<<3) /* if ref clk b == 27 */ #define DPIO_MODSEL1 (1<<3) /* if ref clk b == 27 */
#define DPIO_MODSEL0 (1<<2) /* if ref clk a == 27 */ #define DPIO_MODSEL0 (1<<2) /* if ref clk a == 27 */
#define DPIO_SFR_BYPASS (1<<1) #define DPIO_SFR_BYPASS (1<<1)
#define DPIO_RESET (1<<0) #define DPIO_CMNRST (1<<0)
#define _DPIO_TX3_SWING_CTL4_A 0x690 #define _DPIO_TX3_SWING_CTL4_A 0x690
#define _DPIO_TX3_SWING_CTL4_B 0x2a90 #define _DPIO_TX3_SWING_CTL4_B 0x2a90
...@@ -940,7 +951,7 @@ ...@@ -940,7 +951,7 @@
#define GT_PARITY_ERROR(dev) \ #define GT_PARITY_ERROR(dev) \
(GT_RENDER_L3_PARITY_ERROR_INTERRUPT | \ (GT_RENDER_L3_PARITY_ERROR_INTERRUPT | \
IS_HASWELL(dev) ? GT_RENDER_L3_PARITY_ERROR_INTERRUPT_S1 : 0) (IS_HASWELL(dev) ? GT_RENDER_L3_PARITY_ERROR_INTERRUPT_S1 : 0))
/* These are all the "old" interrupts */ /* These are all the "old" interrupts */
#define ILK_BSD_USER_INTERRUPT (1<<5) #define ILK_BSD_USER_INTERRUPT (1<<5)
...@@ -1429,6 +1440,12 @@ ...@@ -1429,6 +1440,12 @@
#define MI_ARB_VLV (VLV_DISPLAY_BASE + 0x6504) #define MI_ARB_VLV (VLV_DISPLAY_BASE + 0x6504)
#define CZCLK_CDCLK_FREQ_RATIO (VLV_DISPLAY_BASE + 0x6508)
#define CDCLK_FREQ_SHIFT 4
#define CDCLK_FREQ_MASK (0x1f << CDCLK_FREQ_SHIFT)
#define CZCLK_FREQ_MASK 0xf
#define GMBUSFREQ_VLV (VLV_DISPLAY_BASE + 0x6510)
/* /*
* Palette regs * Palette regs
*/ */
...@@ -1797,6 +1814,9 @@ ...@@ -1797,6 +1814,9 @@
*/ */
#define HSW_CXT_TOTAL_SIZE (17 * PAGE_SIZE) #define HSW_CXT_TOTAL_SIZE (17 * PAGE_SIZE)
#define VLV_CLK_CTL2 0x101104
#define CLK_CTL2_CZCOUNT_30NS_SHIFT 28
/* /*
* Overlay regs * Overlay regs
*/ */
...@@ -1848,7 +1868,8 @@ ...@@ -1848,7 +1868,8 @@
#define VSYNCSHIFT(trans) _TRANSCODER(trans, _VSYNCSHIFT_A, _VSYNCSHIFT_B) #define VSYNCSHIFT(trans) _TRANSCODER(trans, _VSYNCSHIFT_A, _VSYNCSHIFT_B)
/* HSW eDP PSR registers */ /* HSW eDP PSR registers */
#define EDP_PSR_CTL 0x64800 #define EDP_PSR_BASE(dev) 0x64800
#define EDP_PSR_CTL(dev) (EDP_PSR_BASE(dev) + 0)
#define EDP_PSR_ENABLE (1<<31) #define EDP_PSR_ENABLE (1<<31)
#define EDP_PSR_LINK_DISABLE (0<<27) #define EDP_PSR_LINK_DISABLE (0<<27)
#define EDP_PSR_LINK_STANDBY (1<<27) #define EDP_PSR_LINK_STANDBY (1<<27)
...@@ -1871,16 +1892,16 @@ ...@@ -1871,16 +1892,16 @@
#define EDP_PSR_TP1_TIME_0us (3<<4) #define EDP_PSR_TP1_TIME_0us (3<<4)
#define EDP_PSR_IDLE_FRAME_SHIFT 0 #define EDP_PSR_IDLE_FRAME_SHIFT 0
#define EDP_PSR_AUX_CTL 0x64810 #define EDP_PSR_AUX_CTL(dev) (EDP_PSR_BASE(dev) + 0x10)
#define EDP_PSR_AUX_DATA1 0x64814 #define EDP_PSR_AUX_DATA1(dev) (EDP_PSR_BASE(dev) + 0x14)
#define EDP_PSR_DPCD_COMMAND 0x80060000 #define EDP_PSR_DPCD_COMMAND 0x80060000
#define EDP_PSR_AUX_DATA2 0x64818 #define EDP_PSR_AUX_DATA2(dev) (EDP_PSR_BASE(dev) + 0x18)
#define EDP_PSR_DPCD_NORMAL_OPERATION (1<<24) #define EDP_PSR_DPCD_NORMAL_OPERATION (1<<24)
#define EDP_PSR_AUX_DATA3 0x6481c #define EDP_PSR_AUX_DATA3(dev) (EDP_PSR_BASE(dev) + 0x1c)
#define EDP_PSR_AUX_DATA4 0x64820 #define EDP_PSR_AUX_DATA4(dev) (EDP_PSR_BASE(dev) + 0x20)
#define EDP_PSR_AUX_DATA5 0x64824 #define EDP_PSR_AUX_DATA5(dev) (EDP_PSR_BASE(dev) + 0x24)
#define EDP_PSR_STATUS_CTL 0x64840 #define EDP_PSR_STATUS_CTL(dev) (EDP_PSR_BASE(dev) + 0x40)
#define EDP_PSR_STATUS_STATE_MASK (7<<29) #define EDP_PSR_STATUS_STATE_MASK (7<<29)
#define EDP_PSR_STATUS_STATE_IDLE (0<<29) #define EDP_PSR_STATUS_STATE_IDLE (0<<29)
#define EDP_PSR_STATUS_STATE_SRDONACK (1<<29) #define EDP_PSR_STATUS_STATE_SRDONACK (1<<29)
...@@ -1904,10 +1925,10 @@ ...@@ -1904,10 +1925,10 @@
#define EDP_PSR_STATUS_SENDING_TP1 (1<<4) #define EDP_PSR_STATUS_SENDING_TP1 (1<<4)
#define EDP_PSR_STATUS_IDLE_MASK 0xf #define EDP_PSR_STATUS_IDLE_MASK 0xf
#define EDP_PSR_PERF_CNT 0x64844 #define EDP_PSR_PERF_CNT(dev) (EDP_PSR_BASE(dev) + 0x44)
#define EDP_PSR_PERF_CNT_MASK 0xffffff #define EDP_PSR_PERF_CNT_MASK 0xffffff
#define EDP_PSR_DEBUG_CTL 0x64860 #define EDP_PSR_DEBUG_CTL(dev) (EDP_PSR_BASE(dev) + 0x60)
#define EDP_PSR_DEBUG_MASK_LPSP (1<<27) #define EDP_PSR_DEBUG_MASK_LPSP (1<<27)
#define EDP_PSR_DEBUG_MASK_MEMUP (1<<26) #define EDP_PSR_DEBUG_MASK_MEMUP (1<<26)
#define EDP_PSR_DEBUG_MASK_HPD (1<<25) #define EDP_PSR_DEBUG_MASK_HPD (1<<25)
...@@ -4675,7 +4696,7 @@ ...@@ -4675,7 +4696,7 @@
#define GEN6_RP_UP_IDLE_MIN (0x1<<3) #define GEN6_RP_UP_IDLE_MIN (0x1<<3)
#define GEN6_RP_UP_BUSY_AVG (0x2<<3) #define GEN6_RP_UP_BUSY_AVG (0x2<<3)
#define GEN6_RP_UP_BUSY_CONT (0x4<<3) #define GEN6_RP_UP_BUSY_CONT (0x4<<3)
#define GEN7_RP_DOWN_IDLE_AVG (0x2<<0) #define GEN6_RP_DOWN_IDLE_AVG (0x2<<0)
#define GEN6_RP_DOWN_IDLE_CONT (0x1<<0) #define GEN6_RP_DOWN_IDLE_CONT (0x1<<0)
#define GEN6_RP_UP_THRESHOLD 0xA02C #define GEN6_RP_UP_THRESHOLD 0xA02C
#define GEN6_RP_DOWN_THRESHOLD 0xA030 #define GEN6_RP_DOWN_THRESHOLD 0xA030
...@@ -4720,6 +4741,10 @@ ...@@ -4720,6 +4741,10 @@
GEN6_PM_RP_DOWN_TIMEOUT) GEN6_PM_RP_DOWN_TIMEOUT)
#define GEN6_GT_GFX_RC6_LOCKED 0x138104 #define GEN6_GT_GFX_RC6_LOCKED 0x138104
#define VLV_COUNTER_CONTROL 0x138104
#define VLV_COUNT_RANGE_HIGH (1<<15)
#define VLV_MEDIA_RC6_COUNT_EN (1<<1)
#define VLV_RENDER_RC6_COUNT_EN (1<<0)
#define GEN6_GT_GFX_RC6 0x138108 #define GEN6_GT_GFX_RC6 0x138108
#define GEN6_GT_GFX_RC6p 0x13810C #define GEN6_GT_GFX_RC6p 0x13810C
#define GEN6_GT_GFX_RC6pp 0x138110 #define GEN6_GT_GFX_RC6pp 0x138110
......
...@@ -37,12 +37,30 @@ static u32 calc_residency(struct drm_device *dev, const u32 reg) ...@@ -37,12 +37,30 @@ static u32 calc_residency(struct drm_device *dev, const u32 reg)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
u64 raw_time; /* 32b value may overflow during fixed point math */ u64 raw_time; /* 32b value may overflow during fixed point math */
u64 units = 128ULL, div = 100000ULL, bias = 100ULL;
if (!intel_enable_rc6(dev)) if (!intel_enable_rc6(dev))
return 0; return 0;
raw_time = I915_READ(reg) * 128ULL; /* On VLV, residency time is in CZ units rather than 1.28us */
return DIV_ROUND_UP_ULL(raw_time, 100000); if (IS_VALLEYVIEW(dev)) {
u32 clkctl2;
clkctl2 = I915_READ(VLV_CLK_CTL2) >>
CLK_CTL2_CZCOUNT_30NS_SHIFT;
if (!clkctl2) {
WARN(!clkctl2, "bogus CZ count value");
return 0;
}
units = DIV_ROUND_UP_ULL(30ULL * bias, (u64)clkctl2);
if (I915_READ(VLV_COUNTER_CONTROL) & VLV_COUNT_RANGE_HIGH)
units <<= 8;
div = 1000000ULL * bias;
}
raw_time = I915_READ(reg) * units;
return DIV_ROUND_UP_ULL(raw_time, div);
} }
static ssize_t static ssize_t
......
...@@ -233,6 +233,47 @@ TRACE_EVENT(i915_gem_evict_everything, ...@@ -233,6 +233,47 @@ TRACE_EVENT(i915_gem_evict_everything,
TP_printk("dev=%d", __entry->dev) TP_printk("dev=%d", __entry->dev)
); );
TRACE_EVENT(i915_gem_evict_vm,
TP_PROTO(struct i915_address_space *vm),
TP_ARGS(vm),
TP_STRUCT__entry(
__field(struct i915_address_space *, vm)
),
TP_fast_assign(
__entry->vm = vm;
),
TP_printk("dev=%d, vm=%p", __entry->vm->dev->primary->index, __entry->vm)
);
TRACE_EVENT(i915_gem_ring_sync_to,
TP_PROTO(struct intel_ring_buffer *from,
struct intel_ring_buffer *to,
u32 seqno),
TP_ARGS(from, to, seqno),
TP_STRUCT__entry(
__field(u32, dev)
__field(u32, sync_from)
__field(u32, sync_to)
__field(u32, seqno)
),
TP_fast_assign(
__entry->dev = from->dev->primary->index;
__entry->sync_from = from->id;
__entry->sync_to = to->id;
__entry->seqno = seqno;
),
TP_printk("dev=%u, sync-from=%u, sync-to=%u, seqno=%u",
__entry->dev,
__entry->sync_from, __entry->sync_to,
__entry->seqno)
);
TRACE_EVENT(i915_gem_ring_dispatch, TRACE_EVENT(i915_gem_ring_dispatch,
TP_PROTO(struct intel_ring_buffer *ring, u32 seqno, u32 flags), TP_PROTO(struct intel_ring_buffer *ring, u32 seqno, u32 flags),
TP_ARGS(ring, seqno, flags), TP_ARGS(ring, seqno, flags),
...@@ -304,9 +345,24 @@ DEFINE_EVENT(i915_gem_request, i915_gem_request_add, ...@@ -304,9 +345,24 @@ DEFINE_EVENT(i915_gem_request, i915_gem_request_add,
TP_ARGS(ring, seqno) TP_ARGS(ring, seqno)
); );
DEFINE_EVENT(i915_gem_request, i915_gem_request_complete, TRACE_EVENT(i915_gem_request_complete,
TP_PROTO(struct intel_ring_buffer *ring, u32 seqno), TP_PROTO(struct intel_ring_buffer *ring),
TP_ARGS(ring, seqno) TP_ARGS(ring),
TP_STRUCT__entry(
__field(u32, dev)
__field(u32, ring)
__field(u32, seqno)
),
TP_fast_assign(
__entry->dev = ring->dev->primary->index;
__entry->ring = ring->id;
__entry->seqno = ring->get_seqno(ring, false);
),
TP_printk("dev=%u, ring=%u, seqno=%u",
__entry->dev, __entry->ring, __entry->seqno)
); );
DEFINE_EVENT(i915_gem_request, i915_gem_request_retire, DEFINE_EVENT(i915_gem_request, i915_gem_request_retire,
......
...@@ -389,7 +389,7 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, ...@@ -389,7 +389,7 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv,
{ {
struct sdvo_device_mapping *p_mapping; struct sdvo_device_mapping *p_mapping;
struct bdb_general_definitions *p_defs; struct bdb_general_definitions *p_defs;
struct child_device_config *p_child; union child_device_config *p_child;
int i, child_device_num, count; int i, child_device_num, count;
u16 block_size; u16 block_size;
...@@ -416,36 +416,36 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, ...@@ -416,36 +416,36 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv,
count = 0; count = 0;
for (i = 0; i < child_device_num; i++) { for (i = 0; i < child_device_num; i++) {
p_child = &(p_defs->devices[i]); p_child = &(p_defs->devices[i]);
if (!p_child->device_type) { if (!p_child->old.device_type) {
/* skip the device block if device type is invalid */ /* skip the device block if device type is invalid */
continue; continue;
} }
if (p_child->slave_addr != SLAVE_ADDR1 && if (p_child->old.slave_addr != SLAVE_ADDR1 &&
p_child->slave_addr != SLAVE_ADDR2) { p_child->old.slave_addr != SLAVE_ADDR2) {
/* /*
* If the slave address is neither 0x70 nor 0x72, * If the slave address is neither 0x70 nor 0x72,
* it is not a SDVO device. Skip it. * it is not a SDVO device. Skip it.
*/ */
continue; continue;
} }
if (p_child->dvo_port != DEVICE_PORT_DVOB && if (p_child->old.dvo_port != DEVICE_PORT_DVOB &&
p_child->dvo_port != DEVICE_PORT_DVOC) { p_child->old.dvo_port != DEVICE_PORT_DVOC) {
/* skip the incorrect SDVO port */ /* skip the incorrect SDVO port */
DRM_DEBUG_KMS("Incorrect SDVO port. Skip it\n"); DRM_DEBUG_KMS("Incorrect SDVO port. Skip it\n");
continue; continue;
} }
DRM_DEBUG_KMS("the SDVO device with slave addr %2x is found on" DRM_DEBUG_KMS("the SDVO device with slave addr %2x is found on"
" %s port\n", " %s port\n",
p_child->slave_addr, p_child->old.slave_addr,
(p_child->dvo_port == DEVICE_PORT_DVOB) ? (p_child->old.dvo_port == DEVICE_PORT_DVOB) ?
"SDVOB" : "SDVOC"); "SDVOB" : "SDVOC");
p_mapping = &(dev_priv->sdvo_mappings[p_child->dvo_port - 1]); p_mapping = &(dev_priv->sdvo_mappings[p_child->old.dvo_port - 1]);
if (!p_mapping->initialized) { if (!p_mapping->initialized) {
p_mapping->dvo_port = p_child->dvo_port; p_mapping->dvo_port = p_child->old.dvo_port;
p_mapping->slave_addr = p_child->slave_addr; p_mapping->slave_addr = p_child->old.slave_addr;
p_mapping->dvo_wiring = p_child->dvo_wiring; p_mapping->dvo_wiring = p_child->old.dvo_wiring;
p_mapping->ddc_pin = p_child->ddc_pin; p_mapping->ddc_pin = p_child->old.ddc_pin;
p_mapping->i2c_pin = p_child->i2c_pin; p_mapping->i2c_pin = p_child->old.i2c_pin;
p_mapping->initialized = 1; p_mapping->initialized = 1;
DRM_DEBUG_KMS("SDVO device: dvo=%x, addr=%x, wiring=%d, ddc_pin=%d, i2c_pin=%d\n", DRM_DEBUG_KMS("SDVO device: dvo=%x, addr=%x, wiring=%d, ddc_pin=%d, i2c_pin=%d\n",
p_mapping->dvo_port, p_mapping->dvo_port,
...@@ -457,7 +457,7 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, ...@@ -457,7 +457,7 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv,
DRM_DEBUG_KMS("Maybe one SDVO port is shared by " DRM_DEBUG_KMS("Maybe one SDVO port is shared by "
"two SDVO device.\n"); "two SDVO device.\n");
} }
if (p_child->slave2_addr) { if (p_child->old.slave2_addr) {
/* Maybe this is a SDVO device with multiple inputs */ /* Maybe this is a SDVO device with multiple inputs */
/* And the mapping info is not added */ /* And the mapping info is not added */
DRM_DEBUG_KMS("there exists the slave2_addr. Maybe this" DRM_DEBUG_KMS("there exists the slave2_addr. Maybe this"
...@@ -477,15 +477,13 @@ static void ...@@ -477,15 +477,13 @@ static void
parse_driver_features(struct drm_i915_private *dev_priv, parse_driver_features(struct drm_i915_private *dev_priv,
struct bdb_header *bdb) struct bdb_header *bdb)
{ {
struct drm_device *dev = dev_priv->dev;
struct bdb_driver_features *driver; struct bdb_driver_features *driver;
driver = find_section(bdb, BDB_DRIVER_FEATURES); driver = find_section(bdb, BDB_DRIVER_FEATURES);
if (!driver) if (!driver)
return; return;
if (SUPPORTS_EDP(dev) && if (driver->lvds_config == BDB_DRIVER_FEATURE_EDP)
driver->lvds_config == BDB_DRIVER_FEATURE_EDP)
dev_priv->vbt.edp_support = 1; dev_priv->vbt.edp_support = 1;
if (driver->dual_frequency) if (driver->dual_frequency)
...@@ -501,7 +499,7 @@ parse_edp(struct drm_i915_private *dev_priv, struct bdb_header *bdb) ...@@ -501,7 +499,7 @@ parse_edp(struct drm_i915_private *dev_priv, struct bdb_header *bdb)
edp = find_section(bdb, BDB_EDP); edp = find_section(bdb, BDB_EDP);
if (!edp) { if (!edp) {
if (SUPPORTS_EDP(dev_priv->dev) && dev_priv->vbt.edp_support) if (dev_priv->vbt.edp_support)
DRM_DEBUG_KMS("No eDP BDB found but eDP panel supported.\n"); DRM_DEBUG_KMS("No eDP BDB found but eDP panel supported.\n");
return; return;
} }
...@@ -583,12 +581,135 @@ parse_mipi(struct drm_i915_private *dev_priv, struct bdb_header *bdb) ...@@ -583,12 +581,135 @@ parse_mipi(struct drm_i915_private *dev_priv, struct bdb_header *bdb)
dev_priv->vbt.dsi.panel_id = mipi->panel_id; dev_priv->vbt.dsi.panel_id = mipi->panel_id;
} }
static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port,
struct bdb_header *bdb)
{
union child_device_config *it, *child = NULL;
struct ddi_vbt_port_info *info = &dev_priv->vbt.ddi_port_info[port];
uint8_t hdmi_level_shift;
int i, j;
bool is_dvi, is_hdmi, is_dp, is_edp, is_crt;
uint8_t aux_channel;
/* Each DDI port can have more than one value on the "DVO Port" field,
* so look for all the possible values for each port and abort if more
* than one is found. */
int dvo_ports[][2] = {
{DVO_PORT_HDMIA, DVO_PORT_DPA},
{DVO_PORT_HDMIB, DVO_PORT_DPB},
{DVO_PORT_HDMIC, DVO_PORT_DPC},
{DVO_PORT_HDMID, DVO_PORT_DPD},
{DVO_PORT_CRT, -1 /* Port E can only be DVO_PORT_CRT */ },
};
/* Find the child device to use, abort if more than one found. */
for (i = 0; i < dev_priv->vbt.child_dev_num; i++) {
it = dev_priv->vbt.child_dev + i;
for (j = 0; j < 2; j++) {
if (dvo_ports[port][j] == -1)
break;
if (it->common.dvo_port == dvo_ports[port][j]) {
if (child) {
DRM_DEBUG_KMS("More than one child device for port %c in VBT.\n",
port_name(port));
return;
}
child = it;
}
}
}
if (!child)
return;
aux_channel = child->raw[25];
is_dvi = child->common.device_type & (1 << 4);
is_dp = child->common.device_type & (1 << 2);
is_crt = child->common.device_type & (1 << 0);
is_hdmi = is_dvi && (child->common.device_type & (1 << 11)) == 0;
is_edp = is_dp && (child->common.device_type & (1 << 12));
info->supports_dvi = is_dvi;
info->supports_hdmi = is_hdmi;
info->supports_dp = is_dp;
DRM_DEBUG_KMS("Port %c VBT info: DP:%d HDMI:%d DVI:%d EDP:%d CRT:%d\n",
port_name(port), is_dp, is_hdmi, is_dvi, is_edp, is_crt);
if (is_edp && is_dvi)
DRM_DEBUG_KMS("Internal DP port %c is TMDS compatible\n",
port_name(port));
if (is_crt && port != PORT_E)
DRM_DEBUG_KMS("Port %c is analog\n", port_name(port));
if (is_crt && (is_dvi || is_dp))
DRM_DEBUG_KMS("Analog port %c is also DP or TMDS compatible\n",
port_name(port));
if (is_dvi && (port == PORT_A || port == PORT_E))
DRM_DEBUG_KMS("Port %c is TMDS compabile\n", port_name(port));
if (!is_dvi && !is_dp && !is_crt)
DRM_DEBUG_KMS("Port %c is not DP/TMDS/CRT compatible\n",
port_name(port));
if (is_edp && (port == PORT_B || port == PORT_C || port == PORT_E))
DRM_DEBUG_KMS("Port %c is internal DP\n", port_name(port));
if (is_dvi) {
if (child->common.ddc_pin == 0x05 && port != PORT_B)
DRM_DEBUG_KMS("Unexpected DDC pin for port B\n");
if (child->common.ddc_pin == 0x04 && port != PORT_C)
DRM_DEBUG_KMS("Unexpected DDC pin for port C\n");
if (child->common.ddc_pin == 0x06 && port != PORT_D)
DRM_DEBUG_KMS("Unexpected DDC pin for port D\n");
}
if (is_dp) {
if (aux_channel == 0x40 && port != PORT_A)
DRM_DEBUG_KMS("Unexpected AUX channel for port A\n");
if (aux_channel == 0x10 && port != PORT_B)
DRM_DEBUG_KMS("Unexpected AUX channel for port B\n");
if (aux_channel == 0x20 && port != PORT_C)
DRM_DEBUG_KMS("Unexpected AUX channel for port C\n");
if (aux_channel == 0x30 && port != PORT_D)
DRM_DEBUG_KMS("Unexpected AUX channel for port D\n");
}
if (bdb->version >= 158) {
/* The VBT HDMI level shift values match the table we have. */
hdmi_level_shift = child->raw[7] & 0xF;
if (hdmi_level_shift < 0xC) {
DRM_DEBUG_KMS("VBT HDMI level shift for port %c: %d\n",
port_name(port),
hdmi_level_shift);
info->hdmi_level_shift = hdmi_level_shift;
}
}
}
static void parse_ddi_ports(struct drm_i915_private *dev_priv,
struct bdb_header *bdb)
{
struct drm_device *dev = dev_priv->dev;
enum port port;
if (!HAS_DDI(dev))
return;
if (!dev_priv->vbt.child_dev_num)
return;
if (bdb->version < 155)
return;
for (port = PORT_A; port < I915_MAX_PORTS; port++)
parse_ddi_port(dev_priv, port, bdb);
}
static void static void
parse_device_mapping(struct drm_i915_private *dev_priv, parse_device_mapping(struct drm_i915_private *dev_priv,
struct bdb_header *bdb) struct bdb_header *bdb)
{ {
struct bdb_general_definitions *p_defs; struct bdb_general_definitions *p_defs;
struct child_device_config *p_child, *child_dev_ptr; union child_device_config *p_child, *child_dev_ptr;
int i, child_device_num, count; int i, child_device_num, count;
u16 block_size; u16 block_size;
...@@ -616,7 +737,7 @@ parse_device_mapping(struct drm_i915_private *dev_priv, ...@@ -616,7 +737,7 @@ parse_device_mapping(struct drm_i915_private *dev_priv,
/* get the number of child device that is present */ /* get the number of child device that is present */
for (i = 0; i < child_device_num; i++) { for (i = 0; i < child_device_num; i++) {
p_child = &(p_defs->devices[i]); p_child = &(p_defs->devices[i]);
if (!p_child->device_type) { if (!p_child->common.device_type) {
/* skip the device block if device type is invalid */ /* skip the device block if device type is invalid */
continue; continue;
} }
...@@ -636,7 +757,7 @@ parse_device_mapping(struct drm_i915_private *dev_priv, ...@@ -636,7 +757,7 @@ parse_device_mapping(struct drm_i915_private *dev_priv,
count = 0; count = 0;
for (i = 0; i < child_device_num; i++) { for (i = 0; i < child_device_num; i++) {
p_child = &(p_defs->devices[i]); p_child = &(p_defs->devices[i]);
if (!p_child->device_type) { if (!p_child->common.device_type) {
/* skip the device block if device type is invalid */ /* skip the device block if device type is invalid */
continue; continue;
} }
...@@ -652,6 +773,7 @@ static void ...@@ -652,6 +773,7 @@ static void
init_vbt_defaults(struct drm_i915_private *dev_priv) init_vbt_defaults(struct drm_i915_private *dev_priv)
{ {
struct drm_device *dev = dev_priv->dev; struct drm_device *dev = dev_priv->dev;
enum port port;
dev_priv->vbt.crt_ddc_pin = GMBUS_PORT_VGADDC; dev_priv->vbt.crt_ddc_pin = GMBUS_PORT_VGADDC;
...@@ -670,6 +792,18 @@ init_vbt_defaults(struct drm_i915_private *dev_priv) ...@@ -670,6 +792,18 @@ init_vbt_defaults(struct drm_i915_private *dev_priv)
dev_priv->vbt.lvds_use_ssc = 1; dev_priv->vbt.lvds_use_ssc = 1;
dev_priv->vbt.lvds_ssc_freq = intel_bios_ssc_frequency(dev, 1); dev_priv->vbt.lvds_ssc_freq = intel_bios_ssc_frequency(dev, 1);
DRM_DEBUG_KMS("Set default to SSC at %dMHz\n", dev_priv->vbt.lvds_ssc_freq); DRM_DEBUG_KMS("Set default to SSC at %dMHz\n", dev_priv->vbt.lvds_ssc_freq);
for (port = PORT_A; port < I915_MAX_PORTS; port++) {
struct ddi_vbt_port_info *info =
&dev_priv->vbt.ddi_port_info[port];
/* Recommended BSpec default: 800mV 0dB. */
info->hdmi_level_shift = 6;
info->supports_dvi = (port != PORT_A && port != PORT_E);
info->supports_hdmi = info->supports_dvi;
info->supports_dp = (port != PORT_E);
}
} }
static int __init intel_no_opregion_vbt_callback(const struct dmi_system_id *id) static int __init intel_no_opregion_vbt_callback(const struct dmi_system_id *id)
...@@ -761,6 +895,7 @@ intel_parse_bios(struct drm_device *dev) ...@@ -761,6 +895,7 @@ intel_parse_bios(struct drm_device *dev)
parse_driver_features(dev_priv, bdb); parse_driver_features(dev_priv, bdb);
parse_edp(dev_priv, bdb); parse_edp(dev_priv, bdb);
parse_mipi(dev_priv, bdb); parse_mipi(dev_priv, bdb);
parse_ddi_ports(dev_priv, bdb);
if (bios) if (bios)
pci_unmap_rom(pdev, bios); pci_unmap_rom(pdev, bios);
......
...@@ -202,7 +202,10 @@ struct bdb_general_features { ...@@ -202,7 +202,10 @@ struct bdb_general_features {
#define DEVICE_PORT_DVOB 0x01 #define DEVICE_PORT_DVOB 0x01
#define DEVICE_PORT_DVOC 0x02 #define DEVICE_PORT_DVOC 0x02
struct child_device_config { /* We used to keep this struct but without any version control. We should avoid
* using it in the future, but it should be safe to keep using it in the old
* code. */
struct old_child_dev_config {
u16 handle; u16 handle;
u16 device_type; u16 device_type;
u8 device_id[10]; /* ascii string */ u8 device_id[10]; /* ascii string */
...@@ -224,6 +227,32 @@ struct child_device_config { ...@@ -224,6 +227,32 @@ struct child_device_config {
u8 dvo_function; u8 dvo_function;
} __attribute__((packed)); } __attribute__((packed));
/* This one contains field offsets that are known to be common for all BDB
* versions. Notice that the meaning of the contents contents may still change,
* but at least the offsets are consistent. */
struct common_child_dev_config {
u16 handle;
u16 device_type;
u8 not_common1[12];
u8 dvo_port;
u8 not_common2[2];
u8 ddc_pin;
u16 edid_ptr;
} __attribute__((packed));
/* This field changes depending on the BDB version, so the most reliable way to
* read it is by checking the BDB version and reading the raw pointer. */
union child_device_config {
/* This one is safe to be used anywhere, but the code should still check
* the BDB version. */
u8 raw[33];
/* This one should only be kept for legacy code. */
struct old_child_dev_config old;
/* This one should also be safe to use anywhere, even without version
* checks. */
struct common_child_dev_config common;
};
struct bdb_general_definitions { struct bdb_general_definitions {
/* DDC GPIO */ /* DDC GPIO */
u8 crt_ddc_gmbus_pin; u8 crt_ddc_gmbus_pin;
...@@ -249,7 +278,7 @@ struct bdb_general_definitions { ...@@ -249,7 +278,7 @@ struct bdb_general_definitions {
* number = (block_size - sizeof(bdb_general_definitions))/ * number = (block_size - sizeof(bdb_general_definitions))/
* sizeof(child_device_config); * sizeof(child_device_config);
*/ */
struct child_device_config devices[0]; union child_device_config devices[0];
} __attribute__((packed)); } __attribute__((packed));
struct bdb_lvds_options { struct bdb_lvds_options {
...@@ -619,6 +648,19 @@ int intel_parse_bios(struct drm_device *dev); ...@@ -619,6 +648,19 @@ int intel_parse_bios(struct drm_device *dev);
#define PORT_IDPC 8 #define PORT_IDPC 8
#define PORT_IDPD 9 #define PORT_IDPD 9
/* Possible values for the "DVO Port" field for versions >= 155: */
#define DVO_PORT_HDMIA 0
#define DVO_PORT_HDMIB 1
#define DVO_PORT_HDMIC 2
#define DVO_PORT_HDMID 3
#define DVO_PORT_LVDS 4
#define DVO_PORT_TV 5
#define DVO_PORT_CRT 6
#define DVO_PORT_DPB 7
#define DVO_PORT_DPC 8
#define DVO_PORT_DPD 9
#define DVO_PORT_DPA 10
/* MIPI DSI panel info */ /* MIPI DSI panel info */
struct bdb_mipi { struct bdb_mipi {
u16 panel_id; u16 panel_id;
......
...@@ -83,13 +83,11 @@ static bool intel_crt_get_hw_state(struct intel_encoder *encoder, ...@@ -83,13 +83,11 @@ static bool intel_crt_get_hw_state(struct intel_encoder *encoder,
return true; return true;
} }
static void intel_crt_get_config(struct intel_encoder *encoder, static unsigned int intel_crt_get_flags(struct intel_encoder *encoder)
struct intel_crtc_config *pipe_config)
{ {
struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
struct intel_crt *crt = intel_encoder_to_crt(encoder); struct intel_crt *crt = intel_encoder_to_crt(encoder);
u32 tmp, flags = 0; u32 tmp, flags = 0;
int dotclock;
tmp = I915_READ(crt->adpa_reg); tmp = I915_READ(crt->adpa_reg);
...@@ -103,14 +101,35 @@ static void intel_crt_get_config(struct intel_encoder *encoder, ...@@ -103,14 +101,35 @@ static void intel_crt_get_config(struct intel_encoder *encoder,
else else
flags |= DRM_MODE_FLAG_NVSYNC; flags |= DRM_MODE_FLAG_NVSYNC;
pipe_config->adjusted_mode.flags |= flags; return flags;
}
static void intel_crt_get_config(struct intel_encoder *encoder,
struct intel_crtc_config *pipe_config)
{
struct drm_device *dev = encoder->base.dev;
int dotclock;
pipe_config->adjusted_mode.flags |= intel_crt_get_flags(encoder);
dotclock = pipe_config->port_clock; dotclock = pipe_config->port_clock;
if (HAS_PCH_SPLIT(dev_priv->dev)) if (HAS_PCH_SPLIT(dev))
ironlake_check_encoder_dotclock(pipe_config, dotclock); ironlake_check_encoder_dotclock(pipe_config, dotclock);
pipe_config->adjusted_mode.clock = dotclock; pipe_config->adjusted_mode.crtc_clock = dotclock;
}
static void hsw_crt_get_config(struct intel_encoder *encoder,
struct intel_crtc_config *pipe_config)
{
intel_ddi_get_config(encoder, pipe_config);
pipe_config->adjusted_mode.flags &= ~(DRM_MODE_FLAG_PHSYNC |
DRM_MODE_FLAG_NHSYNC |
DRM_MODE_FLAG_PVSYNC |
DRM_MODE_FLAG_NVSYNC);
pipe_config->adjusted_mode.flags |= intel_crt_get_flags(encoder);
} }
/* Note: The caller is required to filter out dpms modes not supported by the /* Note: The caller is required to filter out dpms modes not supported by the
...@@ -658,7 +677,6 @@ intel_crt_detect(struct drm_connector *connector, bool force) ...@@ -658,7 +677,6 @@ intel_crt_detect(struct drm_connector *connector, bool force)
static void intel_crt_destroy(struct drm_connector *connector) static void intel_crt_destroy(struct drm_connector *connector)
{ {
drm_sysfs_connector_remove(connector);
drm_connector_cleanup(connector); drm_connector_cleanup(connector);
kfree(connector); kfree(connector);
} }
...@@ -764,7 +782,7 @@ void intel_crt_init(struct drm_device *dev) ...@@ -764,7 +782,7 @@ void intel_crt_init(struct drm_device *dev)
if (!crt) if (!crt)
return; return;
intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL); intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL);
if (!intel_connector) { if (!intel_connector) {
kfree(crt); kfree(crt);
return; return;
...@@ -804,7 +822,10 @@ void intel_crt_init(struct drm_device *dev) ...@@ -804,7 +822,10 @@ void intel_crt_init(struct drm_device *dev)
crt->base.mode_set = intel_crt_mode_set; crt->base.mode_set = intel_crt_mode_set;
crt->base.disable = intel_disable_crt; crt->base.disable = intel_disable_crt;
crt->base.enable = intel_enable_crt; crt->base.enable = intel_enable_crt;
crt->base.get_config = intel_crt_get_config; if (IS_HASWELL(dev))
crt->base.get_config = hsw_crt_get_config;
else
crt->base.get_config = intel_crt_get_config;
if (I915_HAS_HOTPLUG(dev)) if (I915_HAS_HOTPLUG(dev))
crt->base.hpd_pin = HPD_CRT; crt->base.hpd_pin = HPD_CRT;
if (HAS_DDI(dev)) if (HAS_DDI(dev))
......
...@@ -42,7 +42,6 @@ static const u32 hsw_ddi_translations_dp[] = { ...@@ -42,7 +42,6 @@ static const u32 hsw_ddi_translations_dp[] = {
0x80C30FFF, 0x000B0000, 0x80C30FFF, 0x000B0000,
0x00FFFFFF, 0x00040006, 0x00FFFFFF, 0x00040006,
0x80D75FFF, 0x000B0000, 0x80D75FFF, 0x000B0000,
0x00FFFFFF, 0x00040006 /* HDMI parameters */
}; };
static const u32 hsw_ddi_translations_fdi[] = { static const u32 hsw_ddi_translations_fdi[] = {
...@@ -55,7 +54,22 @@ static const u32 hsw_ddi_translations_fdi[] = { ...@@ -55,7 +54,22 @@ static const u32 hsw_ddi_translations_fdi[] = {
0x00C30FFF, 0x001E0000, 0x00C30FFF, 0x001E0000,
0x00FFFFFF, 0x00060006, 0x00FFFFFF, 0x00060006,
0x00D75FFF, 0x001E0000, 0x00D75FFF, 0x001E0000,
0x00FFFFFF, 0x00040006 /* HDMI parameters */ };
static const u32 hsw_ddi_translations_hdmi[] = {
/* Idx NT mV diff T mV diff db */
0x00FFFFFF, 0x0006000E, /* 0: 400 400 0 */
0x00E79FFF, 0x000E000C, /* 1: 400 500 2 */
0x00D75FFF, 0x0005000A, /* 2: 400 600 3.5 */
0x00FFFFFF, 0x0005000A, /* 3: 600 600 0 */
0x00E79FFF, 0x001D0007, /* 4: 600 750 2 */
0x00D75FFF, 0x000C0004, /* 5: 600 900 3.5 */
0x00FFFFFF, 0x00040006, /* 6: 800 800 0 */
0x80E79FFF, 0x00030002, /* 7: 800 1000 2 */
0x00FFFFFF, 0x00140005, /* 8: 850 850 0 */
0x00FFFFFF, 0x000C0004, /* 9: 900 900 0 */
0x00FFFFFF, 0x001C0003, /* 10: 950 950 0 */
0x80FFFFFF, 0x00030002, /* 11: 1000 1000 0 */
}; };
enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder) enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder)
...@@ -92,12 +106,18 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port) ...@@ -92,12 +106,18 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port)
const u32 *ddi_translations = (port == PORT_E) ? const u32 *ddi_translations = (port == PORT_E) ?
hsw_ddi_translations_fdi : hsw_ddi_translations_fdi :
hsw_ddi_translations_dp; hsw_ddi_translations_dp;
int hdmi_level = dev_priv->vbt.ddi_port_info[port].hdmi_level_shift;
for (i = 0, reg = DDI_BUF_TRANS(port); for (i = 0, reg = DDI_BUF_TRANS(port);
i < ARRAY_SIZE(hsw_ddi_translations_fdi); i++) { i < ARRAY_SIZE(hsw_ddi_translations_fdi); i++) {
I915_WRITE(reg, ddi_translations[i]); I915_WRITE(reg, ddi_translations[i]);
reg += 4; reg += 4;
} }
/* Entry 9 is for HDMI: */
for (i = 0; i < 2; i++) {
I915_WRITE(reg, hsw_ddi_translations_hdmi[hdmi_level * 2 + i]);
reg += 4;
}
} }
/* Program DDI buffers translations for DP. By default, program ports A-D in DP /* Program DDI buffers translations for DP. By default, program ports A-D in DP
...@@ -1246,8 +1266,8 @@ static void intel_ddi_hot_plug(struct intel_encoder *intel_encoder) ...@@ -1246,8 +1266,8 @@ static void intel_ddi_hot_plug(struct intel_encoder *intel_encoder)
intel_dp_check_link_status(intel_dp); intel_dp_check_link_status(intel_dp);
} }
static void intel_ddi_get_config(struct intel_encoder *encoder, void intel_ddi_get_config(struct intel_encoder *encoder,
struct intel_crtc_config *pipe_config) struct intel_crtc_config *pipe_config)
{ {
struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
...@@ -1333,12 +1353,23 @@ void intel_ddi_init(struct drm_device *dev, enum port port) ...@@ -1333,12 +1353,23 @@ void intel_ddi_init(struct drm_device *dev, enum port port)
struct drm_encoder *encoder; struct drm_encoder *encoder;
struct intel_connector *hdmi_connector = NULL; struct intel_connector *hdmi_connector = NULL;
struct intel_connector *dp_connector = NULL; struct intel_connector *dp_connector = NULL;
bool init_hdmi, init_dp;
init_hdmi = (dev_priv->vbt.ddi_port_info[port].supports_dvi ||
dev_priv->vbt.ddi_port_info[port].supports_hdmi);
init_dp = dev_priv->vbt.ddi_port_info[port].supports_dp;
if (!init_dp && !init_hdmi) {
DRM_DEBUG_KMS("VBT says port %c is not DVI/HDMI/DP compatible\n",
port_name(port));
init_hdmi = true;
init_dp = true;
}
intel_dig_port = kzalloc(sizeof(struct intel_digital_port), GFP_KERNEL); intel_dig_port = kzalloc(sizeof(*intel_dig_port), GFP_KERNEL);
if (!intel_dig_port) if (!intel_dig_port)
return; return;
dp_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL); dp_connector = kzalloc(sizeof(*dp_connector), GFP_KERNEL);
if (!dp_connector) { if (!dp_connector) {
kfree(intel_dig_port); kfree(intel_dig_port);
return; return;
...@@ -1370,19 +1401,20 @@ void intel_ddi_init(struct drm_device *dev, enum port port) ...@@ -1370,19 +1401,20 @@ void intel_ddi_init(struct drm_device *dev, enum port port)
intel_encoder->cloneable = false; intel_encoder->cloneable = false;
intel_encoder->hot_plug = intel_ddi_hot_plug; intel_encoder->hot_plug = intel_ddi_hot_plug;
if (!intel_dp_init_connector(intel_dig_port, dp_connector)) { if (init_dp && !intel_dp_init_connector(intel_dig_port, dp_connector)) {
drm_encoder_cleanup(encoder); drm_encoder_cleanup(encoder);
kfree(intel_dig_port); kfree(intel_dig_port);
kfree(dp_connector); kfree(dp_connector);
return; return;
} }
if (intel_encoder->type != INTEL_OUTPUT_EDP) { /* In theory we don't need the encoder->type check, but leave it just in
hdmi_connector = kzalloc(sizeof(struct intel_connector), * case we have some really bad VBTs... */
if (intel_encoder->type != INTEL_OUTPUT_EDP && init_hdmi) {
hdmi_connector = kzalloc(sizeof(*hdmi_connector),
GFP_KERNEL); GFP_KERNEL);
if (!hdmi_connector) { if (!hdmi_connector)
return; return;
}
intel_dig_port->hdmi.hdmi_reg = DDI_BUF_CTL(port); intel_dig_port->hdmi.hdmi_reg = DDI_BUF_CTL(port);
intel_hdmi_init_connector(intel_dig_port, hdmi_connector); intel_hdmi_init_connector(intel_dig_port, hdmi_connector);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -504,7 +504,6 @@ static void intel_dsi_destroy(struct drm_connector *connector) ...@@ -504,7 +504,6 @@ static void intel_dsi_destroy(struct drm_connector *connector)
DRM_DEBUG_KMS("\n"); DRM_DEBUG_KMS("\n");
intel_panel_fini(&intel_connector->panel); intel_panel_fini(&intel_connector->panel);
drm_sysfs_connector_remove(connector);
drm_connector_cleanup(connector); drm_connector_cleanup(connector);
kfree(connector); kfree(connector);
} }
......
...@@ -154,7 +154,7 @@ static void intel_dvo_get_config(struct intel_encoder *encoder, ...@@ -154,7 +154,7 @@ static void intel_dvo_get_config(struct intel_encoder *encoder,
pipe_config->adjusted_mode.flags |= flags; pipe_config->adjusted_mode.flags |= flags;
pipe_config->adjusted_mode.clock = pipe_config->port_clock; pipe_config->adjusted_mode.crtc_clock = pipe_config->port_clock;
} }
static void intel_disable_dvo(struct intel_encoder *encoder) static void intel_disable_dvo(struct intel_encoder *encoder)
...@@ -367,7 +367,6 @@ static int intel_dvo_get_modes(struct drm_connector *connector) ...@@ -367,7 +367,6 @@ static int intel_dvo_get_modes(struct drm_connector *connector)
static void intel_dvo_destroy(struct drm_connector *connector) static void intel_dvo_destroy(struct drm_connector *connector)
{ {
drm_sysfs_connector_remove(connector);
drm_connector_cleanup(connector); drm_connector_cleanup(connector);
kfree(connector); kfree(connector);
} }
...@@ -448,11 +447,11 @@ void intel_dvo_init(struct drm_device *dev) ...@@ -448,11 +447,11 @@ void intel_dvo_init(struct drm_device *dev)
int i; int i;
int encoder_type = DRM_MODE_ENCODER_NONE; int encoder_type = DRM_MODE_ENCODER_NONE;
intel_dvo = kzalloc(sizeof(struct intel_dvo), GFP_KERNEL); intel_dvo = kzalloc(sizeof(*intel_dvo), GFP_KERNEL);
if (!intel_dvo) if (!intel_dvo)
return; return;
intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL); intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL);
if (!intel_connector) { if (!intel_connector) {
kfree(intel_dvo); kfree(intel_dvo);
return; return;
......
...@@ -184,6 +184,27 @@ static int intelfb_create(struct drm_fb_helper *helper, ...@@ -184,6 +184,27 @@ static int intelfb_create(struct drm_fb_helper *helper,
return ret; return ret;
} }
/** Sets the color ramps on behalf of RandR */
static void intel_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
u16 blue, int regno)
{
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
intel_crtc->lut_r[regno] = red >> 8;
intel_crtc->lut_g[regno] = green >> 8;
intel_crtc->lut_b[regno] = blue >> 8;
}
static void intel_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
u16 *blue, int regno)
{
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
*red = intel_crtc->lut_r[regno] << 8;
*green = intel_crtc->lut_g[regno] << 8;
*blue = intel_crtc->lut_b[regno] << 8;
}
static struct drm_fb_helper_funcs intel_fb_helper_funcs = { static struct drm_fb_helper_funcs intel_fb_helper_funcs = {
.gamma_set = intel_crtc_fb_gamma_set, .gamma_set = intel_crtc_fb_gamma_set,
.gamma_get = intel_crtc_fb_gamma_get, .gamma_get = intel_crtc_fb_gamma_get,
...@@ -216,7 +237,7 @@ int intel_fbdev_init(struct drm_device *dev) ...@@ -216,7 +237,7 @@ int intel_fbdev_init(struct drm_device *dev)
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
int ret; int ret;
ifbdev = kzalloc(sizeof(struct intel_fbdev), GFP_KERNEL); ifbdev = kzalloc(sizeof(*ifbdev), GFP_KERNEL);
if (!ifbdev) if (!ifbdev)
return -ENOMEM; return -ENOMEM;
...@@ -225,7 +246,7 @@ int intel_fbdev_init(struct drm_device *dev) ...@@ -225,7 +246,7 @@ int intel_fbdev_init(struct drm_device *dev)
ret = drm_fb_helper_init(dev, &ifbdev->helper, ret = drm_fb_helper_init(dev, &ifbdev->helper,
INTEL_INFO(dev)->num_pipes, INTEL_INFO(dev)->num_pipes,
INTELFB_CONN_LIMIT); 4);
if (ret) { if (ret) {
kfree(ifbdev); kfree(ifbdev);
return ret; return ret;
......
...@@ -737,7 +737,7 @@ static void intel_hdmi_get_config(struct intel_encoder *encoder, ...@@ -737,7 +737,7 @@ static void intel_hdmi_get_config(struct intel_encoder *encoder,
if (HAS_PCH_SPLIT(dev_priv->dev)) if (HAS_PCH_SPLIT(dev_priv->dev))
ironlake_check_encoder_dotclock(pipe_config, dotclock); ironlake_check_encoder_dotclock(pipe_config, dotclock);
pipe_config->adjusted_mode.clock = dotclock; pipe_config->adjusted_mode.crtc_clock = dotclock;
} }
static void intel_enable_hdmi(struct intel_encoder *encoder) static void intel_enable_hdmi(struct intel_encoder *encoder)
...@@ -873,7 +873,7 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder, ...@@ -873,7 +873,7 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder,
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
struct drm_device *dev = encoder->base.dev; struct drm_device *dev = encoder->base.dev;
struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode; struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
int clock_12bpc = pipe_config->adjusted_mode.clock * 3 / 2; int clock_12bpc = pipe_config->adjusted_mode.crtc_clock * 3 / 2;
int portclock_limit = hdmi_portclock_limit(intel_hdmi); int portclock_limit = hdmi_portclock_limit(intel_hdmi);
int desired_bpp; int desired_bpp;
...@@ -915,7 +915,7 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder, ...@@ -915,7 +915,7 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder,
pipe_config->pipe_bpp = desired_bpp; pipe_config->pipe_bpp = desired_bpp;
} }
if (adjusted_mode->clock > portclock_limit) { if (adjusted_mode->crtc_clock > portclock_limit) {
DRM_DEBUG_KMS("too high HDMI clock, rejecting mode\n"); DRM_DEBUG_KMS("too high HDMI clock, rejecting mode\n");
return false; return false;
} }
...@@ -1181,7 +1181,6 @@ static void intel_hdmi_post_disable(struct intel_encoder *encoder) ...@@ -1181,7 +1181,6 @@ static void intel_hdmi_post_disable(struct intel_encoder *encoder)
static void intel_hdmi_destroy(struct drm_connector *connector) static void intel_hdmi_destroy(struct drm_connector *connector)
{ {
drm_sysfs_connector_remove(connector);
drm_connector_cleanup(connector); drm_connector_cleanup(connector);
kfree(connector); kfree(connector);
} }
...@@ -1228,6 +1227,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, ...@@ -1228,6 +1227,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
connector->interlace_allowed = 1; connector->interlace_allowed = 1;
connector->doublescan_allowed = 0; connector->doublescan_allowed = 0;
connector->stereo_allowed = 1;
switch (port) { switch (port) {
case PORT_B: case PORT_B:
...@@ -1292,11 +1292,11 @@ void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port) ...@@ -1292,11 +1292,11 @@ void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port)
struct intel_encoder *intel_encoder; struct intel_encoder *intel_encoder;
struct intel_connector *intel_connector; struct intel_connector *intel_connector;
intel_dig_port = kzalloc(sizeof(struct intel_digital_port), GFP_KERNEL); intel_dig_port = kzalloc(sizeof(*intel_dig_port), GFP_KERNEL);
if (!intel_dig_port) if (!intel_dig_port)
return; return;
intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL); intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL);
if (!intel_connector) { if (!intel_connector) {
kfree(intel_dig_port); kfree(intel_dig_port);
return; return;
......
...@@ -34,6 +34,11 @@ ...@@ -34,6 +34,11 @@
#include <drm/i915_drm.h> #include <drm/i915_drm.h>
#include "i915_drv.h" #include "i915_drv.h"
enum disp_clk {
CDCLK,
CZCLK
};
struct gmbus_port { struct gmbus_port {
const char *name; const char *name;
int reg; int reg;
...@@ -58,10 +63,69 @@ to_intel_gmbus(struct i2c_adapter *i2c) ...@@ -58,10 +63,69 @@ to_intel_gmbus(struct i2c_adapter *i2c)
return container_of(i2c, struct intel_gmbus, adapter); return container_of(i2c, struct intel_gmbus, adapter);
} }
static int get_disp_clk_div(struct drm_i915_private *dev_priv,
enum disp_clk clk)
{
u32 reg_val;
int clk_ratio;
reg_val = I915_READ(CZCLK_CDCLK_FREQ_RATIO);
if (clk == CDCLK)
clk_ratio =
((reg_val & CDCLK_FREQ_MASK) >> CDCLK_FREQ_SHIFT) + 1;
else
clk_ratio = (reg_val & CZCLK_FREQ_MASK) + 1;
return clk_ratio;
}
static void gmbus_set_freq(struct drm_i915_private *dev_priv)
{
int vco_freq[] = { 800, 1600, 2000, 2400 };
int gmbus_freq = 0, cdclk_div, hpll_freq;
BUG_ON(!IS_VALLEYVIEW(dev_priv->dev));
/* Skip setting the gmbus freq if BIOS has already programmed it */
if (I915_READ(GMBUSFREQ_VLV) != 0xA0)
return;
/* Obtain SKU information */
mutex_lock(&dev_priv->dpio_lock);
hpll_freq =
vlv_cck_read(dev_priv, CCK_FUSE_REG) & CCK_FUSE_HPLL_FREQ_MASK;
mutex_unlock(&dev_priv->dpio_lock);
/* Get the CDCLK divide ratio */
cdclk_div = get_disp_clk_div(dev_priv, CDCLK);
/*
* Program the gmbus_freq based on the cdclk frequency.
* BSpec erroneously claims we should aim for 4MHz, but
* in fact 1MHz is the correct frequency.
*/
if (cdclk_div)
gmbus_freq = (vco_freq[hpll_freq] << 1) / cdclk_div;
if (WARN_ON(gmbus_freq == 0))
return;
I915_WRITE(GMBUSFREQ_VLV, gmbus_freq);
}
void void
intel_i2c_reset(struct drm_device *dev) intel_i2c_reset(struct drm_device *dev)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
/*
* In BIOS-less system, program the correct gmbus frequency
* before reading edid.
*/
if (IS_VALLEYVIEW(dev))
gmbus_set_freq(dev_priv);
I915_WRITE(dev_priv->gpio_mmio_base + GMBUS0, 0); I915_WRITE(dev_priv->gpio_mmio_base + GMBUS0, 0);
I915_WRITE(dev_priv->gpio_mmio_base + GMBUS4, 0); I915_WRITE(dev_priv->gpio_mmio_base + GMBUS4, 0);
} }
......
...@@ -123,7 +123,7 @@ static void intel_lvds_get_config(struct intel_encoder *encoder, ...@@ -123,7 +123,7 @@ static void intel_lvds_get_config(struct intel_encoder *encoder,
if (HAS_PCH_SPLIT(dev_priv->dev)) if (HAS_PCH_SPLIT(dev_priv->dev))
ironlake_check_encoder_dotclock(pipe_config, dotclock); ironlake_check_encoder_dotclock(pipe_config, dotclock);
pipe_config->adjusted_mode.clock = dotclock; pipe_config->adjusted_mode.crtc_clock = dotclock;
} }
/* The LVDS pin pair needs to be on before the DPLLs are enabled. /* The LVDS pin pair needs to be on before the DPLLs are enabled.
...@@ -474,7 +474,6 @@ static void intel_lvds_destroy(struct drm_connector *connector) ...@@ -474,7 +474,6 @@ static void intel_lvds_destroy(struct drm_connector *connector)
intel_panel_fini(&lvds_connector->base.panel); intel_panel_fini(&lvds_connector->base.panel);
drm_sysfs_connector_remove(connector);
drm_connector_cleanup(connector); drm_connector_cleanup(connector);
kfree(connector); kfree(connector);
} }
...@@ -794,7 +793,8 @@ static bool lvds_is_present_in_vbt(struct drm_device *dev, ...@@ -794,7 +793,8 @@ static bool lvds_is_present_in_vbt(struct drm_device *dev,
return true; return true;
for (i = 0; i < dev_priv->vbt.child_dev_num; i++) { for (i = 0; i < dev_priv->vbt.child_dev_num; i++) {
struct child_device_config *child = dev_priv->vbt.child_dev + i; union child_device_config *uchild = dev_priv->vbt.child_dev + i;
struct old_child_dev_config *child = &uchild->old;
/* If the device type is not LFP, continue. /* If the device type is not LFP, continue.
* We have to check both the new identifiers as well as the * We have to check both the new identifiers as well as the
...@@ -948,11 +948,11 @@ void intel_lvds_init(struct drm_device *dev) ...@@ -948,11 +948,11 @@ void intel_lvds_init(struct drm_device *dev)
} }
} }
lvds_encoder = kzalloc(sizeof(struct intel_lvds_encoder), GFP_KERNEL); lvds_encoder = kzalloc(sizeof(*lvds_encoder), GFP_KERNEL);
if (!lvds_encoder) if (!lvds_encoder)
return; return;
lvds_connector = kzalloc(sizeof(struct intel_lvds_connector), GFP_KERNEL); lvds_connector = kzalloc(sizeof(*lvds_connector), GFP_KERNEL);
if (!lvds_connector) { if (!lvds_connector) {
kfree(lvds_encoder); kfree(lvds_encoder);
return; return;
......
...@@ -1053,7 +1053,7 @@ int intel_overlay_put_image(struct drm_device *dev, void *data, ...@@ -1053,7 +1053,7 @@ int intel_overlay_put_image(struct drm_device *dev, void *data,
return ret; return ret;
} }
params = kmalloc(sizeof(struct put_image_params), GFP_KERNEL); params = kmalloc(sizeof(*params), GFP_KERNEL);
if (!params) if (!params)
return -ENOMEM; return -ENOMEM;
...@@ -1320,7 +1320,7 @@ void intel_setup_overlay(struct drm_device *dev) ...@@ -1320,7 +1320,7 @@ void intel_setup_overlay(struct drm_device *dev)
if (!HAS_OVERLAY(dev)) if (!HAS_OVERLAY(dev))
return; return;
overlay = kzalloc(sizeof(struct intel_overlay), GFP_KERNEL); overlay = kzalloc(sizeof(*overlay), GFP_KERNEL);
if (!overlay) if (!overlay)
return; return;
......
...@@ -329,7 +329,7 @@ static int is_backlight_combination_mode(struct drm_device *dev) ...@@ -329,7 +329,7 @@ static int is_backlight_combination_mode(struct drm_device *dev)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
if (INTEL_INFO(dev)->gen >= 4) if (IS_GEN4(dev))
return I915_READ(BLC_PWM_CTL2) & BLM_COMBINATION_MODE; return I915_READ(BLC_PWM_CTL2) & BLM_COMBINATION_MODE;
if (IS_GEN2(dev)) if (IS_GEN2(dev))
...@@ -372,6 +372,9 @@ static u32 i915_read_blc_pwm_ctl(struct drm_device *dev) ...@@ -372,6 +372,9 @@ static u32 i915_read_blc_pwm_ctl(struct drm_device *dev)
I915_WRITE(BLC_PWM_CTL2, I915_WRITE(BLC_PWM_CTL2,
dev_priv->regfile.saveBLC_PWM_CTL2); dev_priv->regfile.saveBLC_PWM_CTL2);
} }
if (IS_VALLEYVIEW(dev) && !val)
val = 0x0f42ffff;
} }
return val; return val;
...@@ -629,10 +632,24 @@ void intel_panel_enable_backlight(struct drm_device *dev, ...@@ -629,10 +632,24 @@ void intel_panel_enable_backlight(struct drm_device *dev,
spin_unlock_irqrestore(&dev_priv->backlight.lock, flags); spin_unlock_irqrestore(&dev_priv->backlight.lock, flags);
} }
/* FIXME: use VBT vals to init PWM_CTL and PWM_CTL2 correctly */
static void intel_panel_init_backlight_regs(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
if (IS_VALLEYVIEW(dev)) {
u32 cur_val = I915_READ(BLC_PWM_CTL) &
BACKLIGHT_DUTY_CYCLE_MASK;
I915_WRITE(BLC_PWM_CTL, (0xf42 << 16) | cur_val);
}
}
static void intel_panel_init_backlight(struct drm_device *dev) static void intel_panel_init_backlight(struct drm_device *dev)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
intel_panel_init_backlight_regs(dev);
dev_priv->backlight.level = intel_panel_get_backlight(dev); dev_priv->backlight.level = intel_panel_get_backlight(dev);
dev_priv->backlight.enabled = dev_priv->backlight.level != 0; dev_priv->backlight.enabled = dev_priv->backlight.level != 0;
} }
......
This diff is collapsed.
This diff is collapsed.
...@@ -1034,7 +1034,7 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) ...@@ -1034,7 +1034,7 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane)
if (INTEL_INFO(dev)->gen < 5) if (INTEL_INFO(dev)->gen < 5)
return -ENODEV; return -ENODEV;
intel_plane = kzalloc(sizeof(struct intel_plane), GFP_KERNEL); intel_plane = kzalloc(sizeof(*intel_plane), GFP_KERNEL);
if (!intel_plane) if (!intel_plane)
return -ENOMEM; return -ENOMEM;
......
This diff is collapsed.
This diff is collapsed.
...@@ -326,8 +326,6 @@ nv_crtc_mode_set_vga(struct drm_crtc *crtc, struct drm_display_mode *mode) ...@@ -326,8 +326,6 @@ nv_crtc_mode_set_vga(struct drm_crtc *crtc, struct drm_display_mode *mode)
regp->MiscOutReg = 0x23; /* +hsync +vsync */ regp->MiscOutReg = 0x23; /* +hsync +vsync */
} }
regp->MiscOutReg |= (mode->clock_index & 0x03) << 2;
/* /*
* Time Sequencer * Time Sequencer
*/ */
......
...@@ -433,6 +433,9 @@ struct drm_file { ...@@ -433,6 +433,9 @@ struct drm_file {
struct drm_master *master; /* master this node is currently associated with struct drm_master *master; /* master this node is currently associated with
N.B. not always minor->master */ N.B. not always minor->master */
/* true when the client has asked us to expose stereo 3D mode flags */
bool stereo_allowed;
/** /**
* fbs - List of framebuffers associated with this file. * fbs - List of framebuffers associated with this file.
* *
...@@ -1294,6 +1297,8 @@ extern int drm_getstats(struct drm_device *dev, void *data, ...@@ -1294,6 +1297,8 @@ extern int drm_getstats(struct drm_device *dev, void *data,
struct drm_file *file_priv); struct drm_file *file_priv);
extern int drm_getcap(struct drm_device *dev, void *data, extern int drm_getcap(struct drm_device *dev, void *data,
struct drm_file *file_priv); struct drm_file *file_priv);
extern int drm_setclientcap(struct drm_device *dev, void *data,
struct drm_file *file_priv);
extern int drm_setversion(struct drm_device *dev, void *data, extern int drm_setversion(struct drm_device *dev, void *data,
struct drm_file *file_priv); struct drm_file *file_priv);
extern int drm_noop(struct drm_device *dev, void *data, extern int drm_noop(struct drm_device *dev, void *data,
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment