提交 fea0f9ff 编写于 作者: L Linus Torvalds

Merge branch 'drm-next' of git://people.freedesktop.org/~airlied/linux

Pull drm fixes from Dave Airlie:
 "Just a few straggling fixes I hoovered up, and an intel fixes pull
  from Daniel which fixes some regressions, and some mgag200 fixes from
  Matrox."

* 'drm-next' of git://people.freedesktop.org/~airlied/linux:
  drm/mgag200: Fix framebuffer base address programming
  drm/mgag200: Convert counter delays to jiffies
  drm/mgag200: Fix writes into MGA1064_PIX_CLK_CTL register
  drm/mgag200: Don't change unrelated registers during modeset
  drm: Only print a debug message when the polled connector has changed
  drm: Make the HPD status updates debug logs more readable
  drm: Use names of ioctls in debug traces
  drm: Remove pointless '-' characters from drm_fb_helper documentation
  drm: Add kernel-doc for drm_fb_helper_funcs->initial_config
  drm: refactor call to request_module
  drm: Don't prune modes loudly when a connector is disconnected
  drm: Add missing break in the command line mode parsing code
  drm/i915: clear the stolen fb before resuming
  Revert "drm/i915: Calculate correct stolen size for GEN7+"
  drm/i915: hsw: fix link training for eDP on port-A
  Revert "drm/i915: revert eDP bpp clamping code changes"
  drm: don't check modeset locks in panic handler
  drm/i915: Fix pipe enabled mask for pipe C in WM calculations
  drm/mm: fix dump table BUG
  drm/i915: Always normalize return timeout for wait_timeout_ioctl
...@@ -78,6 +78,10 @@ void drm_warn_on_modeset_not_all_locked(struct drm_device *dev) ...@@ -78,6 +78,10 @@ void drm_warn_on_modeset_not_all_locked(struct drm_device *dev)
{ {
struct drm_crtc *crtc; struct drm_crtc *crtc;
/* Locking is currently fubar in the panic handler. */
if (oops_in_progress)
return;
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
WARN_ON(!mutex_is_locked(&crtc->mutex)); WARN_ON(!mutex_is_locked(&crtc->mutex));
...@@ -246,6 +250,7 @@ char *drm_get_connector_status_name(enum drm_connector_status status) ...@@ -246,6 +250,7 @@ char *drm_get_connector_status_name(enum drm_connector_status status)
else else
return "unknown"; return "unknown";
} }
EXPORT_SYMBOL(drm_get_connector_status_name);
/** /**
* drm_mode_object_get - allocate a new modeset identifier * drm_mode_object_get - allocate a new modeset identifier
......
...@@ -121,6 +121,7 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector, ...@@ -121,6 +121,7 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
connector->helper_private; connector->helper_private;
int count = 0; int count = 0;
int mode_flags = 0; int mode_flags = 0;
bool verbose_prune = true;
DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id, DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id,
drm_get_connector_name(connector)); drm_get_connector_name(connector));
...@@ -149,6 +150,7 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector, ...@@ -149,6 +150,7 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] disconnected\n", DRM_DEBUG_KMS("[CONNECTOR:%d:%s] disconnected\n",
connector->base.id, drm_get_connector_name(connector)); connector->base.id, drm_get_connector_name(connector));
drm_mode_connector_update_edid_property(connector, NULL); drm_mode_connector_update_edid_property(connector, NULL);
verbose_prune = false;
goto prune; goto prune;
} }
...@@ -182,7 +184,7 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector, ...@@ -182,7 +184,7 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
} }
prune: prune:
drm_mode_prune_invalid(dev, &connector->modes, true); drm_mode_prune_invalid(dev, &connector->modes, verbose_prune);
if (list_empty(&connector->modes)) if (list_empty(&connector->modes))
return 0; return 0;
...@@ -1005,12 +1007,20 @@ static void output_poll_execute(struct work_struct *work) ...@@ -1005,12 +1007,20 @@ static void output_poll_execute(struct work_struct *work)
continue; continue;
connector->status = connector->funcs->detect(connector, false); connector->status = connector->funcs->detect(connector, false);
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %d to %d\n", if (old_status != connector->status) {
connector->base.id, const char *old, *new;
drm_get_connector_name(connector),
old_status, connector->status); old = drm_get_connector_status_name(old_status);
if (old_status != connector->status) new = drm_get_connector_status_name(connector->status);
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] "
"status updated from %s to %s\n",
connector->base.id,
drm_get_connector_name(connector),
old, new);
changed = true; changed = true;
}
} }
mutex_unlock(&dev->mode_config.mutex); mutex_unlock(&dev->mode_config.mutex);
...@@ -1083,10 +1093,11 @@ void drm_helper_hpd_irq_event(struct drm_device *dev) ...@@ -1083,10 +1093,11 @@ void drm_helper_hpd_irq_event(struct drm_device *dev)
old_status = connector->status; old_status = connector->status;
connector->status = connector->funcs->detect(connector, false); connector->status = connector->funcs->detect(connector, false);
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %d to %d\n", DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %s to %s\n",
connector->base.id, connector->base.id,
drm_get_connector_name(connector), drm_get_connector_name(connector),
old_status, connector->status); drm_get_connector_status_name(old_status),
drm_get_connector_status_name(connector->status));
if (old_status != connector->status) if (old_status != connector->status)
changed = true; changed = true;
} }
......
...@@ -57,7 +57,7 @@ static int drm_version(struct drm_device *dev, void *data, ...@@ -57,7 +57,7 @@ static int drm_version(struct drm_device *dev, void *data,
struct drm_file *file_priv); struct drm_file *file_priv);
#define DRM_IOCTL_DEF(ioctl, _func, _flags) \ #define DRM_IOCTL_DEF(ioctl, _func, _flags) \
[DRM_IOCTL_NR(ioctl)] = {.cmd = ioctl, .func = _func, .flags = _flags, .cmd_drv = 0} [DRM_IOCTL_NR(ioctl)] = {.cmd = ioctl, .func = _func, .flags = _flags, .cmd_drv = 0, .name = #ioctl}
/** Ioctl table */ /** Ioctl table */
static const struct drm_ioctl_desc drm_ioctls[] = { static const struct drm_ioctl_desc drm_ioctls[] = {
...@@ -375,7 +375,7 @@ long drm_ioctl(struct file *filp, ...@@ -375,7 +375,7 @@ long drm_ioctl(struct file *filp,
{ {
struct drm_file *file_priv = filp->private_data; struct drm_file *file_priv = filp->private_data;
struct drm_device *dev; struct drm_device *dev;
const struct drm_ioctl_desc *ioctl; const struct drm_ioctl_desc *ioctl = NULL;
drm_ioctl_t *func; drm_ioctl_t *func;
unsigned int nr = DRM_IOCTL_NR(cmd); unsigned int nr = DRM_IOCTL_NR(cmd);
int retcode = -EINVAL; int retcode = -EINVAL;
...@@ -392,11 +392,6 @@ long drm_ioctl(struct file *filp, ...@@ -392,11 +392,6 @@ long drm_ioctl(struct file *filp,
atomic_inc(&dev->counts[_DRM_STAT_IOCTLS]); atomic_inc(&dev->counts[_DRM_STAT_IOCTLS]);
++file_priv->ioctl_count; ++file_priv->ioctl_count;
DRM_DEBUG("pid=%d, cmd=0x%02x, nr=0x%02x, dev 0x%lx, auth=%d\n",
task_pid_nr(current), cmd, nr,
(long)old_encode_dev(file_priv->minor->device),
file_priv->authenticated);
if ((nr >= DRM_CORE_IOCTL_COUNT) && if ((nr >= DRM_CORE_IOCTL_COUNT) &&
((nr < DRM_COMMAND_BASE) || (nr >= DRM_COMMAND_END))) ((nr < DRM_COMMAND_BASE) || (nr >= DRM_COMMAND_END)))
goto err_i1; goto err_i1;
...@@ -417,6 +412,11 @@ long drm_ioctl(struct file *filp, ...@@ -417,6 +412,11 @@ long drm_ioctl(struct file *filp,
} else } else
goto err_i1; goto err_i1;
DRM_DEBUG("pid=%d, dev=0x%lx, auth=%d, %s\n",
task_pid_nr(current),
(long)old_encode_dev(file_priv->minor->device),
file_priv->authenticated, ioctl->name);
/* Do not trust userspace, use our own definition */ /* Do not trust userspace, use our own definition */
func = ioctl->func; func = ioctl->func;
/* is there a local override? */ /* is there a local override? */
...@@ -471,6 +471,12 @@ long drm_ioctl(struct file *filp, ...@@ -471,6 +471,12 @@ long drm_ioctl(struct file *filp,
} }
err_i1: err_i1:
if (!ioctl)
DRM_DEBUG("invalid iotcl: pid=%d, dev=0x%lx, auth=%d, cmd=0x%02x, nr=0x%02x\n",
task_pid_nr(current),
(long)old_encode_dev(file_priv->minor->device),
file_priv->authenticated, cmd, nr);
if (kdata != stack_kdata) if (kdata != stack_kdata)
kfree(kdata); kfree(kdata);
atomic_dec(&dev->ioctl_count); atomic_dec(&dev->ioctl_count);
......
...@@ -54,16 +54,12 @@ int drm_i2c_encoder_init(struct drm_device *dev, ...@@ -54,16 +54,12 @@ int drm_i2c_encoder_init(struct drm_device *dev,
struct i2c_adapter *adap, struct i2c_adapter *adap,
const struct i2c_board_info *info) const struct i2c_board_info *info)
{ {
char modalias[sizeof(I2C_MODULE_PREFIX)
+ I2C_NAME_SIZE];
struct module *module = NULL; struct module *module = NULL;
struct i2c_client *client; struct i2c_client *client;
struct drm_i2c_encoder_driver *encoder_drv; struct drm_i2c_encoder_driver *encoder_drv;
int err = 0; int err = 0;
snprintf(modalias, sizeof(modalias), request_module("%s%s", I2C_MODULE_PREFIX, info->type);
"%s%s", I2C_MODULE_PREFIX, info->type);
request_module(modalias);
client = i2c_new_device(adap, info); client = i2c_new_device(adap, info);
if (!client) { if (!client) {
......
...@@ -755,33 +755,35 @@ void drm_mm_debug_table(struct drm_mm *mm, const char *prefix) ...@@ -755,33 +755,35 @@ void drm_mm_debug_table(struct drm_mm *mm, const char *prefix)
EXPORT_SYMBOL(drm_mm_debug_table); EXPORT_SYMBOL(drm_mm_debug_table);
#if defined(CONFIG_DEBUG_FS) #if defined(CONFIG_DEBUG_FS)
int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm) static unsigned long drm_mm_dump_hole(struct seq_file *m, struct drm_mm_node *entry)
{ {
struct drm_mm_node *entry;
unsigned long total_used = 0, total_free = 0, total = 0;
unsigned long hole_start, hole_end, hole_size; unsigned long hole_start, hole_end, hole_size;
hole_start = drm_mm_hole_node_start(&mm->head_node); if (entry->hole_follows) {
hole_end = drm_mm_hole_node_end(&mm->head_node); hole_start = drm_mm_hole_node_start(entry);
hole_size = hole_end - hole_start; hole_end = drm_mm_hole_node_end(entry);
if (hole_size) hole_size = hole_end - hole_start;
seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: free\n", seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: free\n",
hole_start, hole_end, hole_size); hole_start, hole_end, hole_size);
total_free += hole_size; return hole_size;
}
return 0;
}
int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm)
{
struct drm_mm_node *entry;
unsigned long total_used = 0, total_free = 0, total = 0;
total_free += drm_mm_dump_hole(m, &mm->head_node);
drm_mm_for_each_node(entry, mm) { drm_mm_for_each_node(entry, mm) {
seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: used\n", seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: used\n",
entry->start, entry->start + entry->size, entry->start, entry->start + entry->size,
entry->size); entry->size);
total_used += entry->size; total_used += entry->size;
if (entry->hole_follows) { total_free += drm_mm_dump_hole(m, entry);
hole_start = drm_mm_hole_node_start(entry);
hole_end = drm_mm_hole_node_end(entry);
hole_size = hole_end - hole_start;
seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: free\n",
hole_start, hole_end, hole_size);
total_free += hole_size;
}
} }
total = total_free + total_used; total = total_free + total_used;
......
...@@ -1143,6 +1143,7 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, ...@@ -1143,6 +1143,7 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
was_digit = false; was_digit = false;
} else } else
goto done; goto done;
break;
case '0' ... '9': case '0' ... '9':
was_digit = true; was_digit = true;
break; break;
......
...@@ -1045,6 +1045,8 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno, ...@@ -1045,6 +1045,8 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno,
if (timeout) { if (timeout) {
struct timespec sleep_time = timespec_sub(now, before); struct timespec sleep_time = timespec_sub(now, before);
*timeout = timespec_sub(*timeout, sleep_time); *timeout = timespec_sub(*timeout, sleep_time);
if (!timespec_valid(timeout)) /* i.e. negative time remains */
set_normalized_timespec(timeout, 0, 0);
} }
switch (end) { switch (end) {
...@@ -1053,8 +1055,6 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno, ...@@ -1053,8 +1055,6 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno,
case -ERESTARTSYS: /* Signal */ case -ERESTARTSYS: /* Signal */
return (int)end; return (int)end;
case 0: /* Timeout */ case 0: /* Timeout */
if (timeout)
set_normalized_timespec(timeout, 0, 0);
return -ETIME; return -ETIME;
default: /* Completed */ default: /* Completed */
WARN_ON(end < 0); /* We're not aware of other errors */ WARN_ON(end < 0); /* We're not aware of other errors */
...@@ -2377,10 +2377,8 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file) ...@@ -2377,10 +2377,8 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
ret = __wait_seqno(ring, seqno, reset_counter, true, timeout); ret = __wait_seqno(ring, seqno, reset_counter, true, timeout);
if (timeout) { if (timeout)
WARN_ON(!timespec_valid(timeout));
args->timeout_ns = timespec_to_ns(timeout); args->timeout_ns = timespec_to_ns(timeout);
}
return ret; return ret;
out: out:
......
...@@ -709,15 +709,6 @@ static inline size_t gen6_get_stolen_size(u16 snb_gmch_ctl) ...@@ -709,15 +709,6 @@ static inline size_t gen6_get_stolen_size(u16 snb_gmch_ctl)
return snb_gmch_ctl << 25; /* 32 MB units */ return snb_gmch_ctl << 25; /* 32 MB units */
} }
static inline size_t gen7_get_stolen_size(u16 snb_gmch_ctl)
{
static const int stolen_decoder[] = {
0, 0, 0, 0, 0, 32, 48, 64, 128, 256, 96, 160, 224, 352};
snb_gmch_ctl >>= IVB_GMCH_GMS_SHIFT;
snb_gmch_ctl &= IVB_GMCH_GMS_MASK;
return stolen_decoder[snb_gmch_ctl] << 20;
}
static int gen6_gmch_probe(struct drm_device *dev, static int gen6_gmch_probe(struct drm_device *dev,
size_t *gtt_total, size_t *gtt_total,
size_t *stolen, size_t *stolen,
...@@ -747,11 +738,7 @@ static int gen6_gmch_probe(struct drm_device *dev, ...@@ -747,11 +738,7 @@ static int gen6_gmch_probe(struct drm_device *dev,
pci_read_config_word(dev->pdev, SNB_GMCH_CTRL, &snb_gmch_ctl); pci_read_config_word(dev->pdev, SNB_GMCH_CTRL, &snb_gmch_ctl);
gtt_size = gen6_get_total_gtt_size(snb_gmch_ctl); gtt_size = gen6_get_total_gtt_size(snb_gmch_ctl);
if (IS_GEN7(dev) && !IS_VALLEYVIEW(dev)) *stolen = gen6_get_stolen_size(snb_gmch_ctl);
*stolen = gen7_get_stolen_size(snb_gmch_ctl);
else
*stolen = gen6_get_stolen_size(snb_gmch_ctl);
*gtt_total = (gtt_size / sizeof(gen6_gtt_pte_t)) << PAGE_SHIFT; *gtt_total = (gtt_size / sizeof(gen6_gtt_pte_t)) << PAGE_SHIFT;
/* For Modern GENs the PTEs and register space are split in the BAR */ /* For Modern GENs the PTEs and register space are split in the BAR */
......
...@@ -46,8 +46,6 @@ ...@@ -46,8 +46,6 @@
#define SNB_GMCH_GGMS_MASK 0x3 #define SNB_GMCH_GGMS_MASK 0x3
#define SNB_GMCH_GMS_SHIFT 3 /* Graphics Mode Select */ #define SNB_GMCH_GMS_SHIFT 3 /* Graphics Mode Select */
#define SNB_GMCH_GMS_MASK 0x1f #define SNB_GMCH_GMS_MASK 0x1f
#define IVB_GMCH_GMS_SHIFT 4
#define IVB_GMCH_GMS_MASK 0xf
/* PCI config space */ /* PCI config space */
......
...@@ -1265,6 +1265,8 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder) ...@@ -1265,6 +1265,8 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)
intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
intel_dp_start_link_train(intel_dp); intel_dp_start_link_train(intel_dp);
intel_dp_complete_link_train(intel_dp); intel_dp_complete_link_train(intel_dp);
if (port != PORT_A)
intel_dp_stop_link_train(intel_dp);
} }
} }
...@@ -1326,6 +1328,9 @@ static void intel_enable_ddi(struct intel_encoder *intel_encoder) ...@@ -1326,6 +1328,9 @@ static void intel_enable_ddi(struct intel_encoder *intel_encoder)
} else if (type == INTEL_OUTPUT_EDP) { } else if (type == INTEL_OUTPUT_EDP) {
struct intel_dp *intel_dp = enc_to_intel_dp(encoder); struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
if (port == PORT_A)
intel_dp_stop_link_train(intel_dp);
ironlake_edp_backlight_on(intel_dp); ironlake_edp_backlight_on(intel_dp);
} }
......
...@@ -702,6 +702,9 @@ intel_dp_compute_config(struct intel_encoder *encoder, ...@@ -702,6 +702,9 @@ intel_dp_compute_config(struct intel_encoder *encoder,
/* Walk through all bpp values. Luckily they're all nicely spaced with 2 /* Walk through all bpp values. Luckily they're all nicely spaced with 2
* bpc in between. */ * bpc in between. */
bpp = min_t(int, 8*3, pipe_config->pipe_bpp); bpp = min_t(int, 8*3, pipe_config->pipe_bpp);
if (is_edp(intel_dp) && dev_priv->edp.bpp)
bpp = min_t(int, bpp, dev_priv->edp.bpp);
for (; bpp >= 6*3; bpp -= 2*3) { for (; bpp >= 6*3; bpp -= 2*3) {
mode_rate = intel_dp_link_required(target_clock, bpp); mode_rate = intel_dp_link_required(target_clock, bpp);
...@@ -739,6 +742,7 @@ intel_dp_compute_config(struct intel_encoder *encoder, ...@@ -739,6 +742,7 @@ intel_dp_compute_config(struct intel_encoder *encoder,
intel_dp->link_bw = bws[clock]; intel_dp->link_bw = bws[clock];
intel_dp->lane_count = lane_count; intel_dp->lane_count = lane_count;
adjusted_mode->clock = drm_dp_bw_code_to_link_rate(intel_dp->link_bw); adjusted_mode->clock = drm_dp_bw_code_to_link_rate(intel_dp->link_bw);
pipe_config->pipe_bpp = bpp;
pipe_config->pixel_target_clock = target_clock; pipe_config->pixel_target_clock = target_clock;
DRM_DEBUG_KMS("DP link bw %02x lane count %d clock %d bpp %d\n", DRM_DEBUG_KMS("DP link bw %02x lane count %d clock %d bpp %d\n",
...@@ -751,20 +755,6 @@ intel_dp_compute_config(struct intel_encoder *encoder, ...@@ -751,20 +755,6 @@ intel_dp_compute_config(struct intel_encoder *encoder,
target_clock, adjusted_mode->clock, target_clock, adjusted_mode->clock,
&pipe_config->dp_m_n); &pipe_config->dp_m_n);
/*
* XXX: We have a strange regression where using the vbt edp bpp value
* for the link bw computation results in black screens, the panel only
* works when we do the computation at the usual 24bpp (but still
* requires us to use 18bpp). Until that's fully debugged, stay
* bug-for-bug compatible with the old code.
*/
if (is_edp(intel_dp) && dev_priv->edp.bpp) {
DRM_DEBUG_KMS("clamping display bpc (was %d) to eDP (%d)\n",
bpp, dev_priv->edp.bpp);
bpp = min_t(int, bpp, dev_priv->edp.bpp);
}
pipe_config->pipe_bpp = bpp;
return true; return true;
} }
...@@ -1389,6 +1379,7 @@ static void intel_enable_dp(struct intel_encoder *encoder) ...@@ -1389,6 +1379,7 @@ static void intel_enable_dp(struct intel_encoder *encoder)
ironlake_edp_panel_on(intel_dp); ironlake_edp_panel_on(intel_dp);
ironlake_edp_panel_vdd_off(intel_dp, true); ironlake_edp_panel_vdd_off(intel_dp, true);
intel_dp_complete_link_train(intel_dp); intel_dp_complete_link_train(intel_dp);
intel_dp_stop_link_train(intel_dp);
ironlake_edp_backlight_on(intel_dp); ironlake_edp_backlight_on(intel_dp);
} }
...@@ -1711,10 +1702,9 @@ intel_dp_set_link_train(struct intel_dp *intel_dp, ...@@ -1711,10 +1702,9 @@ intel_dp_set_link_train(struct intel_dp *intel_dp,
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
enum port port = intel_dig_port->port; enum port port = intel_dig_port->port;
int ret; int ret;
uint32_t temp;
if (HAS_DDI(dev)) { if (HAS_DDI(dev)) {
temp = I915_READ(DP_TP_CTL(port)); uint32_t temp = I915_READ(DP_TP_CTL(port));
if (dp_train_pat & DP_LINK_SCRAMBLING_DISABLE) if (dp_train_pat & DP_LINK_SCRAMBLING_DISABLE)
temp |= DP_TP_CTL_SCRAMBLE_DISABLE; temp |= DP_TP_CTL_SCRAMBLE_DISABLE;
...@@ -1724,18 +1714,6 @@ intel_dp_set_link_train(struct intel_dp *intel_dp, ...@@ -1724,18 +1714,6 @@ intel_dp_set_link_train(struct intel_dp *intel_dp,
temp &= ~DP_TP_CTL_LINK_TRAIN_MASK; temp &= ~DP_TP_CTL_LINK_TRAIN_MASK;
switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) { switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) {
case DP_TRAINING_PATTERN_DISABLE: case DP_TRAINING_PATTERN_DISABLE:
if (port != PORT_A) {
temp |= DP_TP_CTL_LINK_TRAIN_IDLE;
I915_WRITE(DP_TP_CTL(port), temp);
if (wait_for((I915_READ(DP_TP_STATUS(port)) &
DP_TP_STATUS_IDLE_DONE), 1))
DRM_ERROR("Timed out waiting for DP idle patterns\n");
temp &= ~DP_TP_CTL_LINK_TRAIN_MASK;
}
temp |= DP_TP_CTL_LINK_TRAIN_NORMAL; temp |= DP_TP_CTL_LINK_TRAIN_NORMAL;
break; break;
...@@ -1811,6 +1789,37 @@ intel_dp_set_link_train(struct intel_dp *intel_dp, ...@@ -1811,6 +1789,37 @@ intel_dp_set_link_train(struct intel_dp *intel_dp,
return true; return true;
} }
static void intel_dp_set_idle_link_train(struct intel_dp *intel_dp)
{
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
struct drm_device *dev = intel_dig_port->base.base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
enum port port = intel_dig_port->port;
uint32_t val;
if (!HAS_DDI(dev))
return;
val = I915_READ(DP_TP_CTL(port));
val &= ~DP_TP_CTL_LINK_TRAIN_MASK;
val |= DP_TP_CTL_LINK_TRAIN_IDLE;
I915_WRITE(DP_TP_CTL(port), val);
/*
* On PORT_A we can have only eDP in SST mode. There the only reason
* we need to set idle transmission mode is to work around a HW issue
* where we enable the pipe while not in idle link-training mode.
* In this case there is requirement to wait for a minimum number of
* idle patterns to be sent.
*/
if (port == PORT_A)
return;
if (wait_for((I915_READ(DP_TP_STATUS(port)) & DP_TP_STATUS_IDLE_DONE),
1))
DRM_ERROR("Timed out waiting for DP idle patterns\n");
}
/* Enable corresponding port and start training pattern 1 */ /* Enable corresponding port and start training pattern 1 */
void void
intel_dp_start_link_train(struct intel_dp *intel_dp) intel_dp_start_link_train(struct intel_dp *intel_dp)
...@@ -1953,10 +1962,19 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp) ...@@ -1953,10 +1962,19 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
++tries; ++tries;
} }
intel_dp_set_idle_link_train(intel_dp);
intel_dp->DP = DP;
if (channel_eq) if (channel_eq)
DRM_DEBUG_KMS("Channel EQ done. DP Training successful\n"); DRM_DEBUG_KMS("Channel EQ done. DP Training successful\n");
intel_dp_set_link_train(intel_dp, DP, DP_TRAINING_PATTERN_DISABLE); }
void intel_dp_stop_link_train(struct intel_dp *intel_dp)
{
intel_dp_set_link_train(intel_dp, intel_dp->DP,
DP_TRAINING_PATTERN_DISABLE);
} }
static void static void
...@@ -2164,6 +2182,7 @@ intel_dp_check_link_status(struct intel_dp *intel_dp) ...@@ -2164,6 +2182,7 @@ intel_dp_check_link_status(struct intel_dp *intel_dp)
drm_get_encoder_name(&intel_encoder->base)); drm_get_encoder_name(&intel_encoder->base));
intel_dp_start_link_train(intel_dp); intel_dp_start_link_train(intel_dp);
intel_dp_complete_link_train(intel_dp); intel_dp_complete_link_train(intel_dp);
intel_dp_stop_link_train(intel_dp);
} }
} }
......
...@@ -499,6 +499,7 @@ extern void intel_dp_init_connector(struct intel_digital_port *intel_dig_port, ...@@ -499,6 +499,7 @@ extern void intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
extern void intel_dp_init_link_config(struct intel_dp *intel_dp); extern void intel_dp_init_link_config(struct intel_dp *intel_dp);
extern void intel_dp_start_link_train(struct intel_dp *intel_dp); extern void intel_dp_start_link_train(struct intel_dp *intel_dp);
extern void intel_dp_complete_link_train(struct intel_dp *intel_dp); extern void intel_dp_complete_link_train(struct intel_dp *intel_dp);
extern void intel_dp_stop_link_train(struct intel_dp *intel_dp);
extern void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode); extern void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode);
extern void intel_dp_encoder_destroy(struct drm_encoder *encoder); extern void intel_dp_encoder_destroy(struct drm_encoder *encoder);
extern void intel_dp_check_link_status(struct intel_dp *intel_dp); extern void intel_dp_check_link_status(struct intel_dp *intel_dp);
......
...@@ -262,10 +262,22 @@ void intel_fbdev_fini(struct drm_device *dev) ...@@ -262,10 +262,22 @@ void intel_fbdev_fini(struct drm_device *dev)
void intel_fbdev_set_suspend(struct drm_device *dev, int state) void intel_fbdev_set_suspend(struct drm_device *dev, int state)
{ {
drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_private_t *dev_priv = dev->dev_private;
if (!dev_priv->fbdev) struct intel_fbdev *ifbdev = dev_priv->fbdev;
struct fb_info *info;
if (!ifbdev)
return; return;
fb_set_suspend(dev_priv->fbdev->helper.fbdev, state); info = ifbdev->helper.fbdev;
/* On resume from hibernation: If the object is shmemfs backed, it has
* been restored from swap. If the object is stolen however, it will be
* full of whatever garbage was left in there.
*/
if (!state && ifbdev->ifb.obj->stolen)
memset_io(info->screen_base, 0, info->screen_size);
fb_set_suspend(info, state);
} }
MODULE_LICENSE("GPL and additional rights"); MODULE_LICENSE("GPL and additional rights");
......
...@@ -1301,17 +1301,17 @@ static void valleyview_update_wm(struct drm_device *dev) ...@@ -1301,17 +1301,17 @@ static void valleyview_update_wm(struct drm_device *dev)
vlv_update_drain_latency(dev); vlv_update_drain_latency(dev);
if (g4x_compute_wm0(dev, 0, if (g4x_compute_wm0(dev, PIPE_A,
&valleyview_wm_info, latency_ns, &valleyview_wm_info, latency_ns,
&valleyview_cursor_wm_info, latency_ns, &valleyview_cursor_wm_info, latency_ns,
&planea_wm, &cursora_wm)) &planea_wm, &cursora_wm))
enabled |= 1; enabled |= 1 << PIPE_A;
if (g4x_compute_wm0(dev, 1, if (g4x_compute_wm0(dev, PIPE_B,
&valleyview_wm_info, latency_ns, &valleyview_wm_info, latency_ns,
&valleyview_cursor_wm_info, latency_ns, &valleyview_cursor_wm_info, latency_ns,
&planeb_wm, &cursorb_wm)) &planeb_wm, &cursorb_wm))
enabled |= 2; enabled |= 1 << PIPE_B;
if (single_plane_enabled(enabled) && if (single_plane_enabled(enabled) &&
g4x_compute_srwm(dev, ffs(enabled) - 1, g4x_compute_srwm(dev, ffs(enabled) - 1,
...@@ -1357,17 +1357,17 @@ static void g4x_update_wm(struct drm_device *dev) ...@@ -1357,17 +1357,17 @@ static void g4x_update_wm(struct drm_device *dev)
int plane_sr, cursor_sr; int plane_sr, cursor_sr;
unsigned int enabled = 0; unsigned int enabled = 0;
if (g4x_compute_wm0(dev, 0, if (g4x_compute_wm0(dev, PIPE_A,
&g4x_wm_info, latency_ns, &g4x_wm_info, latency_ns,
&g4x_cursor_wm_info, latency_ns, &g4x_cursor_wm_info, latency_ns,
&planea_wm, &cursora_wm)) &planea_wm, &cursora_wm))
enabled |= 1; enabled |= 1 << PIPE_A;
if (g4x_compute_wm0(dev, 1, if (g4x_compute_wm0(dev, PIPE_B,
&g4x_wm_info, latency_ns, &g4x_wm_info, latency_ns,
&g4x_cursor_wm_info, latency_ns, &g4x_cursor_wm_info, latency_ns,
&planeb_wm, &cursorb_wm)) &planeb_wm, &cursorb_wm))
enabled |= 2; enabled |= 1 << PIPE_B;
if (single_plane_enabled(enabled) && if (single_plane_enabled(enabled) &&
g4x_compute_srwm(dev, ffs(enabled) - 1, g4x_compute_srwm(dev, ffs(enabled) - 1,
...@@ -1716,7 +1716,7 @@ static void ironlake_update_wm(struct drm_device *dev) ...@@ -1716,7 +1716,7 @@ static void ironlake_update_wm(struct drm_device *dev)
unsigned int enabled; unsigned int enabled;
enabled = 0; enabled = 0;
if (g4x_compute_wm0(dev, 0, if (g4x_compute_wm0(dev, PIPE_A,
&ironlake_display_wm_info, &ironlake_display_wm_info,
ILK_LP0_PLANE_LATENCY, ILK_LP0_PLANE_LATENCY,
&ironlake_cursor_wm_info, &ironlake_cursor_wm_info,
...@@ -1727,10 +1727,10 @@ static void ironlake_update_wm(struct drm_device *dev) ...@@ -1727,10 +1727,10 @@ static void ironlake_update_wm(struct drm_device *dev)
DRM_DEBUG_KMS("FIFO watermarks For pipe A -" DRM_DEBUG_KMS("FIFO watermarks For pipe A -"
" plane %d, " "cursor: %d\n", " plane %d, " "cursor: %d\n",
plane_wm, cursor_wm); plane_wm, cursor_wm);
enabled |= 1; enabled |= 1 << PIPE_A;
} }
if (g4x_compute_wm0(dev, 1, if (g4x_compute_wm0(dev, PIPE_B,
&ironlake_display_wm_info, &ironlake_display_wm_info,
ILK_LP0_PLANE_LATENCY, ILK_LP0_PLANE_LATENCY,
&ironlake_cursor_wm_info, &ironlake_cursor_wm_info,
...@@ -1741,7 +1741,7 @@ static void ironlake_update_wm(struct drm_device *dev) ...@@ -1741,7 +1741,7 @@ static void ironlake_update_wm(struct drm_device *dev)
DRM_DEBUG_KMS("FIFO watermarks For pipe B -" DRM_DEBUG_KMS("FIFO watermarks For pipe B -"
" plane %d, cursor: %d\n", " plane %d, cursor: %d\n",
plane_wm, cursor_wm); plane_wm, cursor_wm);
enabled |= 2; enabled |= 1 << PIPE_B;
} }
/* /*
...@@ -1801,7 +1801,7 @@ static void sandybridge_update_wm(struct drm_device *dev) ...@@ -1801,7 +1801,7 @@ static void sandybridge_update_wm(struct drm_device *dev)
unsigned int enabled; unsigned int enabled;
enabled = 0; enabled = 0;
if (g4x_compute_wm0(dev, 0, if (g4x_compute_wm0(dev, PIPE_A,
&sandybridge_display_wm_info, latency, &sandybridge_display_wm_info, latency,
&sandybridge_cursor_wm_info, latency, &sandybridge_cursor_wm_info, latency,
&plane_wm, &cursor_wm)) { &plane_wm, &cursor_wm)) {
...@@ -1812,10 +1812,10 @@ static void sandybridge_update_wm(struct drm_device *dev) ...@@ -1812,10 +1812,10 @@ static void sandybridge_update_wm(struct drm_device *dev)
DRM_DEBUG_KMS("FIFO watermarks For pipe A -" DRM_DEBUG_KMS("FIFO watermarks For pipe A -"
" plane %d, " "cursor: %d\n", " plane %d, " "cursor: %d\n",
plane_wm, cursor_wm); plane_wm, cursor_wm);
enabled |= 1; enabled |= 1 << PIPE_A;
} }
if (g4x_compute_wm0(dev, 1, if (g4x_compute_wm0(dev, PIPE_B,
&sandybridge_display_wm_info, latency, &sandybridge_display_wm_info, latency,
&sandybridge_cursor_wm_info, latency, &sandybridge_cursor_wm_info, latency,
&plane_wm, &cursor_wm)) { &plane_wm, &cursor_wm)) {
...@@ -1826,7 +1826,7 @@ static void sandybridge_update_wm(struct drm_device *dev) ...@@ -1826,7 +1826,7 @@ static void sandybridge_update_wm(struct drm_device *dev)
DRM_DEBUG_KMS("FIFO watermarks For pipe B -" DRM_DEBUG_KMS("FIFO watermarks For pipe B -"
" plane %d, cursor: %d\n", " plane %d, cursor: %d\n",
plane_wm, cursor_wm); plane_wm, cursor_wm);
enabled |= 2; enabled |= 1 << PIPE_B;
} }
/* /*
...@@ -1904,7 +1904,7 @@ static void ivybridge_update_wm(struct drm_device *dev) ...@@ -1904,7 +1904,7 @@ static void ivybridge_update_wm(struct drm_device *dev)
unsigned int enabled; unsigned int enabled;
enabled = 0; enabled = 0;
if (g4x_compute_wm0(dev, 0, if (g4x_compute_wm0(dev, PIPE_A,
&sandybridge_display_wm_info, latency, &sandybridge_display_wm_info, latency,
&sandybridge_cursor_wm_info, latency, &sandybridge_cursor_wm_info, latency,
&plane_wm, &cursor_wm)) { &plane_wm, &cursor_wm)) {
...@@ -1915,10 +1915,10 @@ static void ivybridge_update_wm(struct drm_device *dev) ...@@ -1915,10 +1915,10 @@ static void ivybridge_update_wm(struct drm_device *dev)
DRM_DEBUG_KMS("FIFO watermarks For pipe A -" DRM_DEBUG_KMS("FIFO watermarks For pipe A -"
" plane %d, " "cursor: %d\n", " plane %d, " "cursor: %d\n",
plane_wm, cursor_wm); plane_wm, cursor_wm);
enabled |= 1; enabled |= 1 << PIPE_A;
} }
if (g4x_compute_wm0(dev, 1, if (g4x_compute_wm0(dev, PIPE_B,
&sandybridge_display_wm_info, latency, &sandybridge_display_wm_info, latency,
&sandybridge_cursor_wm_info, latency, &sandybridge_cursor_wm_info, latency,
&plane_wm, &cursor_wm)) { &plane_wm, &cursor_wm)) {
...@@ -1929,10 +1929,10 @@ static void ivybridge_update_wm(struct drm_device *dev) ...@@ -1929,10 +1929,10 @@ static void ivybridge_update_wm(struct drm_device *dev)
DRM_DEBUG_KMS("FIFO watermarks For pipe B -" DRM_DEBUG_KMS("FIFO watermarks For pipe B -"
" plane %d, cursor: %d\n", " plane %d, cursor: %d\n",
plane_wm, cursor_wm); plane_wm, cursor_wm);
enabled |= 2; enabled |= 1 << PIPE_B;
} }
if (g4x_compute_wm0(dev, 2, if (g4x_compute_wm0(dev, PIPE_C,
&sandybridge_display_wm_info, latency, &sandybridge_display_wm_info, latency,
&sandybridge_cursor_wm_info, latency, &sandybridge_cursor_wm_info, latency,
&plane_wm, &cursor_wm)) { &plane_wm, &cursor_wm)) {
...@@ -1943,7 +1943,7 @@ static void ivybridge_update_wm(struct drm_device *dev) ...@@ -1943,7 +1943,7 @@ static void ivybridge_update_wm(struct drm_device *dev)
DRM_DEBUG_KMS("FIFO watermarks For pipe C -" DRM_DEBUG_KMS("FIFO watermarks For pipe C -"
" plane %d, cursor: %d\n", " plane %d, cursor: %d\n",
plane_wm, cursor_wm); plane_wm, cursor_wm);
enabled |= 3; enabled |= 1 << PIPE_C;
} }
/* /*
......
...@@ -46,29 +46,26 @@ static void mga_crtc_load_lut(struct drm_crtc *crtc) ...@@ -46,29 +46,26 @@ static void mga_crtc_load_lut(struct drm_crtc *crtc)
static inline void mga_wait_vsync(struct mga_device *mdev) static inline void mga_wait_vsync(struct mga_device *mdev)
{ {
unsigned int count = 0; unsigned long timeout = jiffies + HZ/10;
unsigned int status = 0; unsigned int status = 0;
do { do {
status = RREG32(MGAREG_Status); status = RREG32(MGAREG_Status);
count++; } while ((status & 0x08) && time_before(jiffies, timeout));
} while ((status & 0x08) && (count < 250000)); timeout = jiffies + HZ/10;
count = 0;
status = 0; status = 0;
do { do {
status = RREG32(MGAREG_Status); status = RREG32(MGAREG_Status);
count++; } while (!(status & 0x08) && time_before(jiffies, timeout));
} while (!(status & 0x08) && (count < 250000));
} }
static inline void mga_wait_busy(struct mga_device *mdev) static inline void mga_wait_busy(struct mga_device *mdev)
{ {
unsigned int count = 0; unsigned long timeout = jiffies + HZ;
unsigned int status = 0; unsigned int status = 0;
do { do {
status = RREG8(MGAREG_Status + 2); status = RREG8(MGAREG_Status + 2);
count++; } while ((status & 0x01) && time_before(jiffies, timeout));
} while ((status & 0x01) && (count < 500000));
} }
/* /*
...@@ -189,12 +186,12 @@ static int mga_g200wb_set_plls(struct mga_device *mdev, long clock) ...@@ -189,12 +186,12 @@ static int mga_g200wb_set_plls(struct mga_device *mdev, long clock)
WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
tmp = RREG8(DAC_DATA); tmp = RREG8(DAC_DATA);
tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS; tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
WREG_DAC(MGA1064_PIX_CLK_CTL_CLK_DIS, tmp); WREG8(DAC_DATA, tmp);
WREG8(DAC_INDEX, MGA1064_REMHEADCTL); WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
tmp = RREG8(DAC_DATA); tmp = RREG8(DAC_DATA);
tmp |= MGA1064_REMHEADCTL_CLKDIS; tmp |= MGA1064_REMHEADCTL_CLKDIS;
WREG_DAC(MGA1064_REMHEADCTL, tmp); WREG8(DAC_DATA, tmp);
/* select PLL Set C */ /* select PLL Set C */
tmp = RREG8(MGAREG_MEM_MISC_READ); tmp = RREG8(MGAREG_MEM_MISC_READ);
...@@ -204,7 +201,7 @@ static int mga_g200wb_set_plls(struct mga_device *mdev, long clock) ...@@ -204,7 +201,7 @@ static int mga_g200wb_set_plls(struct mga_device *mdev, long clock)
WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
tmp = RREG8(DAC_DATA); tmp = RREG8(DAC_DATA);
tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN | 0x80; tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN | 0x80;
WREG_DAC(MGA1064_PIX_CLK_CTL, tmp); WREG8(DAC_DATA, tmp);
udelay(500); udelay(500);
...@@ -212,7 +209,7 @@ static int mga_g200wb_set_plls(struct mga_device *mdev, long clock) ...@@ -212,7 +209,7 @@ static int mga_g200wb_set_plls(struct mga_device *mdev, long clock)
WREG8(DAC_INDEX, MGA1064_VREF_CTL); WREG8(DAC_INDEX, MGA1064_VREF_CTL);
tmp = RREG8(DAC_DATA); tmp = RREG8(DAC_DATA);
tmp &= ~0x04; tmp &= ~0x04;
WREG_DAC(MGA1064_VREF_CTL, tmp); WREG8(DAC_DATA, tmp);
udelay(50); udelay(50);
...@@ -236,13 +233,13 @@ static int mga_g200wb_set_plls(struct mga_device *mdev, long clock) ...@@ -236,13 +233,13 @@ static int mga_g200wb_set_plls(struct mga_device *mdev, long clock)
tmp = RREG8(DAC_DATA); tmp = RREG8(DAC_DATA);
tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK; tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK;
tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL; tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL;
WREG_DAC(MGA1064_PIX_CLK_CTL, tmp); WREG8(DAC_DATA, tmp);
WREG8(DAC_INDEX, MGA1064_REMHEADCTL); WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
tmp = RREG8(DAC_DATA); tmp = RREG8(DAC_DATA);
tmp &= ~MGA1064_REMHEADCTL_CLKSL_MSK; tmp &= ~MGA1064_REMHEADCTL_CLKSL_MSK;
tmp |= MGA1064_REMHEADCTL_CLKSL_PLL; tmp |= MGA1064_REMHEADCTL_CLKSL_PLL;
WREG_DAC(MGA1064_REMHEADCTL, tmp); WREG8(DAC_DATA, tmp);
/* reset dotclock rate bit */ /* reset dotclock rate bit */
WREG8(MGAREG_SEQ_INDEX, 1); WREG8(MGAREG_SEQ_INDEX, 1);
...@@ -253,7 +250,7 @@ static int mga_g200wb_set_plls(struct mga_device *mdev, long clock) ...@@ -253,7 +250,7 @@ static int mga_g200wb_set_plls(struct mga_device *mdev, long clock)
WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
tmp = RREG8(DAC_DATA); tmp = RREG8(DAC_DATA);
tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS; tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
WREG_DAC(MGA1064_PIX_CLK_CTL, tmp); WREG8(DAC_DATA, tmp);
vcount = RREG8(MGAREG_VCOUNT); vcount = RREG8(MGAREG_VCOUNT);
...@@ -318,7 +315,7 @@ static int mga_g200ev_set_plls(struct mga_device *mdev, long clock) ...@@ -318,7 +315,7 @@ static int mga_g200ev_set_plls(struct mga_device *mdev, long clock)
WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
tmp = RREG8(DAC_DATA); tmp = RREG8(DAC_DATA);
tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS; tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
WREG_DAC(MGA1064_PIX_CLK_CTL_CLK_DIS, tmp); WREG8(DAC_DATA, tmp);
tmp = RREG8(MGAREG_MEM_MISC_READ); tmp = RREG8(MGAREG_MEM_MISC_READ);
tmp |= 0x3 << 2; tmp |= 0x3 << 2;
...@@ -326,12 +323,12 @@ static int mga_g200ev_set_plls(struct mga_device *mdev, long clock) ...@@ -326,12 +323,12 @@ static int mga_g200ev_set_plls(struct mga_device *mdev, long clock)
WREG8(DAC_INDEX, MGA1064_PIX_PLL_STAT); WREG8(DAC_INDEX, MGA1064_PIX_PLL_STAT);
tmp = RREG8(DAC_DATA); tmp = RREG8(DAC_DATA);
WREG_DAC(MGA1064_PIX_PLL_STAT, tmp & ~0x40); WREG8(DAC_DATA, tmp & ~0x40);
WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
tmp = RREG8(DAC_DATA); tmp = RREG8(DAC_DATA);
tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
WREG_DAC(MGA1064_PIX_CLK_CTL, tmp); WREG8(DAC_DATA, tmp);
WREG_DAC(MGA1064_EV_PIX_PLLC_M, m); WREG_DAC(MGA1064_EV_PIX_PLLC_M, m);
WREG_DAC(MGA1064_EV_PIX_PLLC_N, n); WREG_DAC(MGA1064_EV_PIX_PLLC_N, n);
...@@ -342,7 +339,7 @@ static int mga_g200ev_set_plls(struct mga_device *mdev, long clock) ...@@ -342,7 +339,7 @@ static int mga_g200ev_set_plls(struct mga_device *mdev, long clock)
WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
tmp = RREG8(DAC_DATA); tmp = RREG8(DAC_DATA);
tmp &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; tmp &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
WREG_DAC(MGA1064_PIX_CLK_CTL, tmp); WREG8(DAC_DATA, tmp);
udelay(500); udelay(500);
...@@ -350,11 +347,11 @@ static int mga_g200ev_set_plls(struct mga_device *mdev, long clock) ...@@ -350,11 +347,11 @@ static int mga_g200ev_set_plls(struct mga_device *mdev, long clock)
tmp = RREG8(DAC_DATA); tmp = RREG8(DAC_DATA);
tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK; tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK;
tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL; tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL;
WREG_DAC(MGA1064_PIX_CLK_CTL, tmp); WREG8(DAC_DATA, tmp);
WREG8(DAC_INDEX, MGA1064_PIX_PLL_STAT); WREG8(DAC_INDEX, MGA1064_PIX_PLL_STAT);
tmp = RREG8(DAC_DATA); tmp = RREG8(DAC_DATA);
WREG_DAC(MGA1064_PIX_PLL_STAT, tmp | 0x40); WREG8(DAC_DATA, tmp | 0x40);
tmp = RREG8(MGAREG_MEM_MISC_READ); tmp = RREG8(MGAREG_MEM_MISC_READ);
tmp |= (0x3 << 2); tmp |= (0x3 << 2);
...@@ -363,7 +360,7 @@ static int mga_g200ev_set_plls(struct mga_device *mdev, long clock) ...@@ -363,7 +360,7 @@ static int mga_g200ev_set_plls(struct mga_device *mdev, long clock)
WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
tmp = RREG8(DAC_DATA); tmp = RREG8(DAC_DATA);
tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS; tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
WREG_DAC(MGA1064_PIX_CLK_CTL, tmp); WREG8(DAC_DATA, tmp);
return 0; return 0;
} }
...@@ -416,7 +413,7 @@ static int mga_g200eh_set_plls(struct mga_device *mdev, long clock) ...@@ -416,7 +413,7 @@ static int mga_g200eh_set_plls(struct mga_device *mdev, long clock)
WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
tmp = RREG8(DAC_DATA); tmp = RREG8(DAC_DATA);
tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS; tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
WREG_DAC(MGA1064_PIX_CLK_CTL_CLK_DIS, tmp); WREG8(DAC_DATA, tmp);
tmp = RREG8(MGAREG_MEM_MISC_READ); tmp = RREG8(MGAREG_MEM_MISC_READ);
tmp |= 0x3 << 2; tmp |= 0x3 << 2;
...@@ -425,7 +422,7 @@ static int mga_g200eh_set_plls(struct mga_device *mdev, long clock) ...@@ -425,7 +422,7 @@ static int mga_g200eh_set_plls(struct mga_device *mdev, long clock)
WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
tmp = RREG8(DAC_DATA); tmp = RREG8(DAC_DATA);
tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
WREG_DAC(MGA1064_PIX_CLK_CTL, tmp); WREG8(DAC_DATA, tmp);
udelay(500); udelay(500);
...@@ -439,13 +436,13 @@ static int mga_g200eh_set_plls(struct mga_device *mdev, long clock) ...@@ -439,13 +436,13 @@ static int mga_g200eh_set_plls(struct mga_device *mdev, long clock)
tmp = RREG8(DAC_DATA); tmp = RREG8(DAC_DATA);
tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK; tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK;
tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL; tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL;
WREG_DAC(MGA1064_PIX_CLK_CTL, tmp); WREG8(DAC_DATA, tmp);
WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
tmp = RREG8(DAC_DATA); tmp = RREG8(DAC_DATA);
tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS; tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
tmp &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; tmp &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
WREG_DAC(MGA1064_PIX_CLK_CTL, tmp); WREG8(DAC_DATA, tmp);
vcount = RREG8(MGAREG_VCOUNT); vcount = RREG8(MGAREG_VCOUNT);
...@@ -515,12 +512,12 @@ static int mga_g200er_set_plls(struct mga_device *mdev, long clock) ...@@ -515,12 +512,12 @@ static int mga_g200er_set_plls(struct mga_device *mdev, long clock)
WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
tmp = RREG8(DAC_DATA); tmp = RREG8(DAC_DATA);
tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS; tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
WREG_DAC(MGA1064_PIX_CLK_CTL_CLK_DIS, tmp); WREG8(DAC_DATA, tmp);
WREG8(DAC_INDEX, MGA1064_REMHEADCTL); WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
tmp = RREG8(DAC_DATA); tmp = RREG8(DAC_DATA);
tmp |= MGA1064_REMHEADCTL_CLKDIS; tmp |= MGA1064_REMHEADCTL_CLKDIS;
WREG_DAC(MGA1064_REMHEADCTL, tmp); WREG8(DAC_DATA, tmp);
tmp = RREG8(MGAREG_MEM_MISC_READ); tmp = RREG8(MGAREG_MEM_MISC_READ);
tmp |= (0x3<<2) | 0xc0; tmp |= (0x3<<2) | 0xc0;
...@@ -530,7 +527,7 @@ static int mga_g200er_set_plls(struct mga_device *mdev, long clock) ...@@ -530,7 +527,7 @@ static int mga_g200er_set_plls(struct mga_device *mdev, long clock)
tmp = RREG8(DAC_DATA); tmp = RREG8(DAC_DATA);
tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS; tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
WREG_DAC(MGA1064_PIX_CLK_CTL, tmp); WREG8(DAC_DATA, tmp);
udelay(500); udelay(500);
...@@ -657,12 +654,26 @@ static void mga_g200wb_commit(struct drm_crtc *crtc) ...@@ -657,12 +654,26 @@ static void mga_g200wb_commit(struct drm_crtc *crtc)
WREG_DAC(MGA1064_GEN_IO_DATA, tmp); WREG_DAC(MGA1064_GEN_IO_DATA, tmp);
} }
/*
This is how the framebuffer base address is stored in g200 cards:
* Assume @offset is the gpu_addr variable of the framebuffer object
* Then addr is the number of _pixels_ (not bytes) from the start of
VRAM to the first pixel we want to display. (divided by 2 for 32bit
framebuffers)
* addr is stored in the CRTCEXT0, CRTCC and CRTCD registers
addr<20> -> CRTCEXT0<6>
addr<19-16> -> CRTCEXT0<3-0>
addr<15-8> -> CRTCC<7-0>
addr<7-0> -> CRTCD<7-0>
CRTCEXT0 has to be programmed last to trigger an update and make the
new addr variable take effect.
*/
void mga_set_start_address(struct drm_crtc *crtc, unsigned offset) void mga_set_start_address(struct drm_crtc *crtc, unsigned offset)
{ {
struct mga_device *mdev = crtc->dev->dev_private; struct mga_device *mdev = crtc->dev->dev_private;
u32 addr; u32 addr;
int count; int count;
u8 crtcext0;
while (RREG8(0x1fda) & 0x08); while (RREG8(0x1fda) & 0x08);
while (!(RREG8(0x1fda) & 0x08)); while (!(RREG8(0x1fda) & 0x08));
...@@ -670,10 +681,17 @@ void mga_set_start_address(struct drm_crtc *crtc, unsigned offset) ...@@ -670,10 +681,17 @@ void mga_set_start_address(struct drm_crtc *crtc, unsigned offset)
count = RREG8(MGAREG_VCOUNT) + 2; count = RREG8(MGAREG_VCOUNT) + 2;
while (RREG8(MGAREG_VCOUNT) < count); while (RREG8(MGAREG_VCOUNT) < count);
addr = offset >> 2; WREG8(MGAREG_CRTCEXT_INDEX, 0);
crtcext0 = RREG8(MGAREG_CRTCEXT_DATA);
crtcext0 &= 0xB0;
addr = offset / 8;
/* Can't store addresses any higher than that...
but we also don't have more than 16MB of memory, so it should be fine. */
WARN_ON(addr > 0x1fffff);
crtcext0 |= (!!(addr & (1<<20)))<<6;
WREG_CRT(0x0d, (u8)(addr & 0xff)); WREG_CRT(0x0d, (u8)(addr & 0xff));
WREG_CRT(0x0c, (u8)(addr >> 8) & 0xff); WREG_CRT(0x0c, (u8)(addr >> 8) & 0xff);
WREG_CRT(0xaf, (u8)(addr >> 16) & 0xf); WREG_ECRT(0x0, ((u8)(addr >> 16) & 0xf) | crtcext0);
} }
...@@ -829,11 +847,7 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc, ...@@ -829,11 +847,7 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc,
for (i = 0; i < sizeof(dacvalue); i++) { for (i = 0; i < sizeof(dacvalue); i++) {
if ((i <= 0x03) || if ((i <= 0x17) ||
(i == 0x07) ||
(i == 0x0b) ||
(i == 0x0f) ||
((i >= 0x13) && (i <= 0x17)) ||
(i == 0x1b) || (i == 0x1b) ||
(i == 0x1c) || (i == 0x1c) ||
((i >= 0x1f) && (i <= 0x29)) || ((i >= 0x1f) && (i <= 0x29)) ||
......
...@@ -316,6 +316,7 @@ struct drm_ioctl_desc { ...@@ -316,6 +316,7 @@ struct drm_ioctl_desc {
int flags; int flags;
drm_ioctl_t *func; drm_ioctl_t *func;
unsigned int cmd_drv; unsigned int cmd_drv;
const char *name;
}; };
/** /**
...@@ -324,7 +325,7 @@ struct drm_ioctl_desc { ...@@ -324,7 +325,7 @@ struct drm_ioctl_desc {
*/ */
#define DRM_IOCTL_DEF_DRV(ioctl, _func, _flags) \ #define DRM_IOCTL_DEF_DRV(ioctl, _func, _flags) \
[DRM_IOCTL_NR(DRM_##ioctl)] = {.cmd = DRM_##ioctl, .func = _func, .flags = _flags, .cmd_drv = DRM_IOCTL_##ioctl} [DRM_IOCTL_NR(DRM_##ioctl)] = {.cmd = DRM_##ioctl, .func = _func, .flags = _flags, .cmd_drv = DRM_IOCTL_##ioctl, .name = #ioctl}
struct drm_magic_entry { struct drm_magic_entry {
struct list_head head; struct list_head head;
......
...@@ -50,13 +50,14 @@ struct drm_fb_helper_surface_size { ...@@ -50,13 +50,14 @@ struct drm_fb_helper_surface_size {
/** /**
* struct drm_fb_helper_funcs - driver callbacks for the fbdev emulation library * struct drm_fb_helper_funcs - driver callbacks for the fbdev emulation library
* @gamma_set: - Set the given gamma lut register on the given crtc. * @gamma_set: Set the given gamma lut register on the given crtc.
* @gamma_get: - Read the given gamma lut register on the given crtc, used to * @gamma_get: Read the given gamma lut register on the given crtc, used to
* save the current lut when force-restoring the fbdev for e.g. * save the current lut when force-restoring the fbdev for e.g.
* kdbg. * kdbg.
* @fb_probe: - Driver callback to allocate and initialize the fbdev info * @fb_probe: Driver callback to allocate and initialize the fbdev info
* structure. Futhermore it also needs to allocate the drm * structure. Futhermore it also needs to allocate the drm
* framebuffer used to back the fbdev. * framebuffer used to back the fbdev.
* @initial_config: Setup an initial fbdev display configuration
* *
* Driver callbacks used by the fbdev emulation helper library. * Driver callbacks used by the fbdev emulation helper library.
*/ */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册