Well, now driver can set resolution to 1024x768 on the Sandybridge GPU. This is cool but useless.

git-svn-id: svn://kolibrios.org@2336 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
Sergey Semyonov (Serge) 2012-01-23 00:47:18 +00:00
parent 14a185a759
commit 294e540225
4 changed files with 257 additions and 51 deletions

View File

@ -53,7 +53,7 @@ unsigned int i915_powersave __read_mostly = 0;
unsigned int i915_enable_rc6 __read_mostly = 0; unsigned int i915_enable_rc6 __read_mostly = 0;
unsigned int i915_enable_fbc __read_mostly = 1; unsigned int i915_enable_fbc __read_mostly = 0;
unsigned int i915_lvds_downclock __read_mostly = 0; unsigned int i915_lvds_downclock __read_mostly = 0;
@ -268,9 +268,165 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent)
mutex_init(&dev->struct_mutex); mutex_init(&dev->struct_mutex);
mutex_init(&dev->ctxlist_mutex); mutex_init(&dev->ctxlist_mutex);
ret = i915_driver_load(dev, ent->driver_data ); ret = i915_driver_load(dev, ent->driver_data );
{
struct drm_connector *connector;
struct drm_connector_helper_funcs *connector_funcs;
struct drm_connector *def_connector = NULL;
struct drm_encoder *encoder;
struct drm_crtc *crtc;
struct drm_framebuffer *fb;
char *con_name;
char *enc_name;
list_for_each_entry(connector, &dev->mode_config.connector_list, head)
{
if( connector->status != connector_status_connected)
continue;
connector_funcs = connector->helper_private;
encoder = connector_funcs->best_encoder(connector);
if( encoder == NULL)
{
dbgprintf("CONNECTOR %x ID: %d no active encoders\n",
connector, connector->base.id);
continue;
}
connector->encoder = encoder;
dbgprintf("CONNECTOR %x ID: %d status %d encoder %x\n crtc %x\n",
connector, connector->base.id,
connector->status, connector->encoder,
encoder->crtc);
def_connector = connector;
crtc = encoder->crtc;
break;
};
if(crtc == NULL)
{
struct drm_crtc *tmp_crtc;
int crtc_mask = 1;
list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head)
{
if (encoder->possible_crtcs & crtc_mask)
{
crtc = tmp_crtc;
encoder->crtc = crtc;
break;
};
crtc_mask <<= 1;
};
if(crtc == NULL)
{
dbgprintf("No CRTC for encoder %d\n", encoder->base.id);
goto out;
}
};
DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
drm_i915_private_t *dev_priv = dev->dev_private;
struct drm_fb_helper *fb_helper = &dev_priv->fbdev->helper;
struct drm_display_mode *mode = NULL, *tmpmode;
list_for_each_entry(tmpmode, &connector->modes, head)
{
if( (drm_mode_width(tmpmode) == 1024) &&
(drm_mode_height(tmpmode) == 768) &&
(drm_mode_vrefresh(tmpmode) == 60) )
{
mode = tmpmode;
goto do_set;
}
};
if( (mode == NULL) )
{
list_for_each_entry(tmpmode, &connector->modes, head)
{
if( (drm_mode_width(tmpmode) == 1024) &&
(drm_mode_height(tmpmode) == 768) )
{
mode = tmpmode;
goto do_set;
}
};
};
goto out;
do_set:
{
typedef struct tag_display display_t;
struct tag_display
{
int x;
int y;
int width;
int height;
int bpp;
int vrefresh;
int pitch;
int lfb;
int supported_modes;
struct drm_device *ddev;
struct drm_connector *connector;
struct drm_crtc *crtc;
};
display_t *rdisplay;
rdisplay = GetDisplay();
con_name = drm_get_connector_name(connector);
enc_name = drm_get_encoder_name(encoder);
dbgprintf("set mode %d %d connector %s encoder %s\n",
1024, 768, con_name, enc_name);
fb = fb_helper->fb;
fb->width = 1024;
fb->height = 768;
fb->pitch = ALIGN(1024* ((32 + 7) / 8), 64);
fb->bits_per_pixel = 32;
fb->depth == 24;
crtc->fb = fb;
crtc->enabled = true;
ret = drm_crtc_helper_set_mode(crtc, mode, 0, 0, fb);
if (ret == true)
{
rdisplay->width = fb->width;
rdisplay->height = fb->height;
rdisplay->pitch = fb->pitch;
rdisplay->vrefresh = drm_mode_vrefresh(mode);
sysSetScreen(fb->width, fb->height, fb->pitch);
dbgprintf("new mode %d x %d pitch %d\n",
fb->width, fb->height, fb->pitch);
}
else
DRM_ERROR("failed to set mode %d_%d on crtc %p\n",
fb->width, fb->height, crtc);
};
};
out:
// if (ret) // if (ret)
// goto err_g4; // goto err_g4;

View File

@ -268,7 +268,6 @@ enum intel_pch {
struct intel_fbdev; struct intel_fbdev;
struct intel_fbc_work; struct intel_fbc_work;
typedef struct drm_i915_private { typedef struct drm_i915_private {
struct drm_device *dev; struct drm_device *dev;
@ -714,7 +713,7 @@ typedef struct drm_i915_private {
u8 corr; u8 corr;
spinlock_t *mchdev_lock; spinlock_t *mchdev_lock;
// enum no_fbc_reason no_fbc_reason; enum no_fbc_reason no_fbc_reason;
// struct drm_mm_node *compressed_fb; // struct drm_mm_node *compressed_fb;
// struct drm_mm_node *compressed_llb; // struct drm_mm_node *compressed_llb;

View File

@ -1809,7 +1809,7 @@ static void intel_update_fbc(struct drm_device *dev)
if (tmp_crtc->enabled && tmp_crtc->fb) { if (tmp_crtc->enabled && tmp_crtc->fb) {
if (crtc) { if (crtc) {
DRM_DEBUG_KMS("more than one pipe active, disabling compression\n"); DRM_DEBUG_KMS("more than one pipe active, disabling compression\n");
// dev_priv->no_fbc_reason = FBC_MULTIPLE_PIPES; dev_priv->no_fbc_reason = FBC_MULTIPLE_PIPES;
goto out_disable; goto out_disable;
} }
crtc = tmp_crtc; crtc = tmp_crtc;
@ -1818,7 +1818,7 @@ static void intel_update_fbc(struct drm_device *dev)
if (!crtc || crtc->fb == NULL) { if (!crtc || crtc->fb == NULL) {
DRM_DEBUG_KMS("no output, disabling\n"); DRM_DEBUG_KMS("no output, disabling\n");
// dev_priv->no_fbc_reason = FBC_NO_OUTPUT; dev_priv->no_fbc_reason = FBC_NO_OUTPUT;
goto out_disable; goto out_disable;
} }
@ -1829,31 +1829,31 @@ static void intel_update_fbc(struct drm_device *dev)
if (!i915_enable_fbc) { if (!i915_enable_fbc) {
DRM_DEBUG_KMS("fbc disabled per module param (default off)\n"); DRM_DEBUG_KMS("fbc disabled per module param (default off)\n");
// dev_priv->no_fbc_reason = FBC_MODULE_PARAM; dev_priv->no_fbc_reason = FBC_MODULE_PARAM;
goto out_disable; goto out_disable;
} }
if (intel_fb->obj->base.size > dev_priv->cfb_size) { if (intel_fb->obj->base.size > dev_priv->cfb_size) {
DRM_DEBUG_KMS("framebuffer too large, disabling " DRM_DEBUG_KMS("framebuffer too large, disabling "
"compression\n"); "compression\n");
// dev_priv->no_fbc_reason = FBC_STOLEN_TOO_SMALL; dev_priv->no_fbc_reason = FBC_STOLEN_TOO_SMALL;
goto out_disable; goto out_disable;
} }
if ((crtc->mode.flags & DRM_MODE_FLAG_INTERLACE) || if ((crtc->mode.flags & DRM_MODE_FLAG_INTERLACE) ||
(crtc->mode.flags & DRM_MODE_FLAG_DBLSCAN)) { (crtc->mode.flags & DRM_MODE_FLAG_DBLSCAN)) {
DRM_DEBUG_KMS("mode incompatible with compression, " DRM_DEBUG_KMS("mode incompatible with compression, "
"disabling\n"); "disabling\n");
// dev_priv->no_fbc_reason = FBC_UNSUPPORTED_MODE; dev_priv->no_fbc_reason = FBC_UNSUPPORTED_MODE;
goto out_disable; goto out_disable;
} }
if ((crtc->mode.hdisplay > 2048) || if ((crtc->mode.hdisplay > 2048) ||
(crtc->mode.vdisplay > 1536)) { (crtc->mode.vdisplay > 1536)) {
DRM_DEBUG_KMS("mode too large for compression, disabling\n"); DRM_DEBUG_KMS("mode too large for compression, disabling\n");
// dev_priv->no_fbc_reason = FBC_MODE_TOO_LARGE; dev_priv->no_fbc_reason = FBC_MODE_TOO_LARGE;
goto out_disable; goto out_disable;
} }
if ((IS_I915GM(dev) || IS_I945GM(dev)) && intel_crtc->plane != 0) { if ((IS_I915GM(dev) || IS_I945GM(dev)) && intel_crtc->plane != 0) {
DRM_DEBUG_KMS("plane not 0, disabling compression\n"); DRM_DEBUG_KMS("plane not 0, disabling compression\n");
// dev_priv->no_fbc_reason = FBC_BAD_PLANE; dev_priv->no_fbc_reason = FBC_BAD_PLANE;
goto out_disable; goto out_disable;
} }
@ -2112,8 +2112,8 @@ static int ironlake_update_plane(struct drm_crtc *crtc,
I915_WRITE(reg, dspcntr); I915_WRITE(reg, dspcntr);
// Start = obj->gtt_offset; Start = obj->gtt_offset;
// Offset = y * fb->pitch + x * (fb->bits_per_pixel / 8); Offset = y * fb->pitch + x * (fb->bits_per_pixel / 8);
DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d %d\n", DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d %d\n",
Start, Offset, x, y, fb->pitch); Start, Offset, x, y, fb->pitch);
@ -2135,12 +2135,18 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb,
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
int ret; int ret;
ENTER();
ret = dev_priv->display.update_plane(crtc, fb, x, y); ret = dev_priv->display.update_plane(crtc, fb, x, y);
if (ret) if (ret)
{
LEAVE();
return ret; return ret;
};
intel_update_fbc(dev); intel_update_fbc(dev);
intel_increase_pllclock(crtc); intel_increase_pllclock(crtc);
LEAVE();
return 0; return 0;
} }
@ -2152,7 +2158,9 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
struct drm_device *dev = crtc->dev; struct drm_device *dev = crtc->dev;
struct drm_i915_master_private *master_priv; struct drm_i915_master_private *master_priv;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int ret; int ret = 0;
ENTER();
/* no fb bound */ /* no fb bound */
if (!crtc->fb) { if (!crtc->fb) {
@ -2170,57 +2178,40 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
} }
mutex_lock(&dev->struct_mutex); mutex_lock(&dev->struct_mutex);
// ret = intel_pin_and_fence_fb_obj(dev,
// to_intel_framebuffer(crtc->fb)->obj,
// NULL);
if (ret != 0) {
mutex_unlock(&dev->struct_mutex);
DRM_ERROR("pin & fence failed\n");
return ret;
}
if (old_fb) { ret = intel_pipe_set_base_atomic(crtc, crtc->fb, x, y,
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_gem_object *obj = to_intel_framebuffer(old_fb)->obj;
// wait_event(dev_priv->pending_flip_queue,
// atomic_read(&dev_priv->mm.wedged) ||
// atomic_read(&obj->pending_flip) == 0);
/* Big Hammer, we also need to ensure that any pending
* MI_WAIT_FOR_EVENT inside a user batch buffer on the
* current scanout is retired before unpinning the old
* framebuffer.
*
* This should only fail upon a hung GPU, in which case we
* can safely continue.
*/
// ret = i915_gem_object_finish_gpu(obj);
(void) ret;
}
ret = intel_pipe_set_base_atomic(crtc, crtc->fb, x, y,
LEAVE_ATOMIC_MODE_SET); LEAVE_ATOMIC_MODE_SET);
dbgprintf("set base atomic done ret= %d\n", ret);
if (ret) { if (ret) {
// i915_gem_object_unpin(to_intel_framebuffer(crtc->fb)->obj); // i915_gem_object_unpin(to_intel_framebuffer(crtc->fb)->obj);
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
DRM_ERROR("failed to update base address\n"); DRM_ERROR("failed to update base address\n");
LEAVE();
return ret; return ret;
} }
if (old_fb) {
// intel_wait_for_vblank(dev, intel_crtc->pipe);
// i915_gem_object_unpin(to_intel_framebuffer(old_fb)->obj);
}
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
LEAVE();
return 0;
#if 0 #if 0
if (!dev->primary->master) if (!dev->primary->master)
{
LEAVE();
return 0; return 0;
};
master_priv = dev->primary->master->driver_priv; master_priv = dev->primary->master->driver_priv;
if (!master_priv->sarea_priv) if (!master_priv->sarea_priv)
{
LEAVE();
return 0; return 0;
};
if (intel_crtc->pipe) { if (intel_crtc->pipe) {
master_priv->sarea_priv->pipeB_x = x; master_priv->sarea_priv->pipeB_x = x;
@ -2229,8 +2220,11 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
master_priv->sarea_priv->pipeA_x = x; master_priv->sarea_priv->pipeA_x = x;
master_priv->sarea_priv->pipeA_y = y; master_priv->sarea_priv->pipeA_y = y;
} }
#endif LEAVE();
return 0; return 0;
#endif
} }
static void ironlake_set_pll_edp(struct drm_crtc *crtc, int clock) static void ironlake_set_pll_edp(struct drm_crtc *crtc, int clock)
@ -2987,6 +2981,8 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
if (!intel_crtc->active) if (!intel_crtc->active)
return; return;
ENTER();
intel_crtc_wait_for_pending_flips(crtc); intel_crtc_wait_for_pending_flips(crtc);
// drm_vblank_off(dev, pipe); // drm_vblank_off(dev, pipe);
// intel_crtc_update_cursor(crtc, false); // intel_crtc_update_cursor(crtc, false);
@ -3071,6 +3067,9 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
intel_update_fbc(dev); intel_update_fbc(dev);
intel_clear_scanline_wait(dev); intel_clear_scanline_wait(dev);
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
LEAVE();
} }
static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode) static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
@ -4433,6 +4432,8 @@ static void sandybridge_update_wm(struct drm_device *dev)
int fbc_wm, plane_wm, cursor_wm; int fbc_wm, plane_wm, cursor_wm;
unsigned int enabled; unsigned int enabled;
ENTER();
enabled = 0; enabled = 0;
if (g4x_compute_wm0(dev, 0, if (g4x_compute_wm0(dev, 0,
&sandybridge_display_wm_info, latency, &sandybridge_display_wm_info, latency,
@ -4473,9 +4474,15 @@ static void sandybridge_update_wm(struct drm_device *dev)
I915_WRITE(WM1_LP_ILK, 0); I915_WRITE(WM1_LP_ILK, 0);
if (!single_plane_enabled(enabled)) if (!single_plane_enabled(enabled))
{
LEAVE();
return; return;
};
enabled = ffs(enabled) - 1; enabled = ffs(enabled) - 1;
dbgprintf("compute wm1\n");
/* WM1 */ /* WM1 */
if (!ironlake_compute_srwm(dev, 1, enabled, if (!ironlake_compute_srwm(dev, 1, enabled,
SNB_READ_WM1_LATENCY() * 500, SNB_READ_WM1_LATENCY() * 500,
@ -4491,6 +4498,8 @@ static void sandybridge_update_wm(struct drm_device *dev)
(plane_wm << WM1_LP_SR_SHIFT) | (plane_wm << WM1_LP_SR_SHIFT) |
cursor_wm); cursor_wm);
dbgprintf("compute wm2\n");
/* WM2 */ /* WM2 */
if (!ironlake_compute_srwm(dev, 2, enabled, if (!ironlake_compute_srwm(dev, 2, enabled,
SNB_READ_WM2_LATENCY() * 500, SNB_READ_WM2_LATENCY() * 500,
@ -4506,6 +4515,8 @@ static void sandybridge_update_wm(struct drm_device *dev)
(plane_wm << WM1_LP_SR_SHIFT) | (plane_wm << WM1_LP_SR_SHIFT) |
cursor_wm); cursor_wm);
dbgprintf("compute wm3\n");
/* WM3 */ /* WM3 */
if (!ironlake_compute_srwm(dev, 3, enabled, if (!ironlake_compute_srwm(dev, 3, enabled,
SNB_READ_WM3_LATENCY() * 500, SNB_READ_WM3_LATENCY() * 500,
@ -4520,6 +4531,9 @@ static void sandybridge_update_wm(struct drm_device *dev)
(fbc_wm << WM1_LP_FBC_SHIFT) | (fbc_wm << WM1_LP_FBC_SHIFT) |
(plane_wm << WM1_LP_SR_SHIFT) | (plane_wm << WM1_LP_SR_SHIFT) |
cursor_wm); cursor_wm);
LEAVE();
} }
/** /**
@ -4557,9 +4571,10 @@ static void sandybridge_update_wm(struct drm_device *dev)
static void intel_update_watermarks(struct drm_device *dev) static void intel_update_watermarks(struct drm_device *dev)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
ENTER();
if (dev_priv->display.update_wm) if (dev_priv->display.update_wm)
dev_priv->display.update_wm(dev); dev_priv->display.update_wm(dev);
LEAVE();
} }
static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv) static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv)
@ -5188,6 +5203,8 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
unsigned int pipe_bpp; unsigned int pipe_bpp;
bool dither; bool dither;
ENTER();
list_for_each_entry(encoder, &mode_config->encoder_list, base.head) { list_for_each_entry(encoder, &mode_config->encoder_list, base.head) {
if (encoder->base.crtc != crtc) if (encoder->base.crtc != crtc)
continue; continue;
@ -5626,8 +5643,12 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
ret = intel_pipe_set_base(crtc, x, y, old_fb); ret = intel_pipe_set_base(crtc, x, y, old_fb);
dbgprintf("Set base\n");
intel_update_watermarks(dev); intel_update_watermarks(dev);
LEAVE();
return ret; return ret;
} }
@ -5644,6 +5665,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
int ret; int ret;
// drm_vblank_pre_modeset(dev, pipe); // drm_vblank_pre_modeset(dev, pipe);
ENTER();
ret = dev_priv->display.crtc_mode_set(crtc, mode, adjusted_mode, ret = dev_priv->display.crtc_mode_set(crtc, mode, adjusted_mode,
x, y, old_fb); x, y, old_fb);
@ -5651,6 +5673,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
// drm_vblank_post_modeset(dev, pipe); // drm_vblank_post_modeset(dev, pipe);
intel_crtc->dpms_mode = DRM_MODE_DPMS_ON; intel_crtc->dpms_mode = DRM_MODE_DPMS_ON;
LEAVE();
return ret; return ret;
} }
@ -6124,6 +6147,8 @@ static void intel_increase_pllclock(struct drm_crtc *crtc)
int dpll_reg = DPLL(pipe); int dpll_reg = DPLL(pipe);
int dpll; int dpll;
ENTER();
if (HAS_PCH_SPLIT(dev)) if (HAS_PCH_SPLIT(dev))
return; return;
@ -6150,6 +6175,8 @@ static void intel_increase_pllclock(struct drm_crtc *crtc)
I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) & 0x3); I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) & 0x3);
} }
LEAVE();
/* Schedule downclock */ /* Schedule downclock */
// mod_timer(&intel_crtc->idle_timer, jiffies + // mod_timer(&intel_crtc->idle_timer, jiffies +
// msecs_to_jiffies(CRTC_IDLE_TIMEOUT)); // msecs_to_jiffies(CRTC_IDLE_TIMEOUT));
@ -6436,6 +6463,8 @@ static void intel_setup_outputs(struct drm_device *dev)
bool dpd_is_edp = false; bool dpd_is_edp = false;
bool has_lvds = false; bool has_lvds = false;
ENTER();
if (IS_MOBILE(dev) && !IS_I830(dev)) if (IS_MOBILE(dev) && !IS_I830(dev))
has_lvds = intel_lvds_init(dev); has_lvds = intel_lvds_init(dev);
if (!has_lvds && !HAS_PCH_SPLIT(dev)) { if (!has_lvds && !HAS_PCH_SPLIT(dev)) {
@ -6534,6 +6563,8 @@ static void intel_setup_outputs(struct drm_device *dev)
/* disable all the possible outputs/crtcs before entering KMS mode */ /* disable all the possible outputs/crtcs before entering KMS mode */
// drm_helper_disable_unused_functions(dev); // drm_helper_disable_unused_functions(dev);
LEAVE();
} }

View File

@ -120,12 +120,32 @@ static int intelfb_create(struct intel_fbdev *ifbdev,
mutex_lock(&dev->struct_mutex); mutex_lock(&dev->struct_mutex);
#if 0
// skip this part and use existing framebiffer
/* Flush everything out, we'll be doing GTT only from now on */ /* Flush everything out, we'll be doing GTT only from now on */
ret = intel_pin_and_fence_fb_obj(dev, obj, false); ret = intel_pin_and_fence_fb_obj(dev, obj, false);
if (ret) { if (ret) {
DRM_ERROR("failed to pin fb: %d\n", ret); DRM_ERROR("failed to pin fb: %d\n", ret);
goto out_unref; goto out_unref;
} }
#endif
/***********************************************************************/
{
#define LFB_SIZE 0xC00000
static struct drm_mm_node lfb_vm_node;
lfb_vm_node.size = LFB_SIZE;
lfb_vm_node.start = 0;
lfb_vm_node.mm = NULL;
obj->gtt_space = &lfb_vm_node;
obj->gtt_offset = 0;
obj->pin_count = 1;
}
/***********************************************************************/
info = framebuffer_alloc(0, device); info = framebuffer_alloc(0, device);
if (!info) { if (!info) {