summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--linux-core/drmP.h2
-rw-r--r--linux-core/drm_crtc.c22
-rw-r--r--linux-core/drm_crtc.h1
-rw-r--r--linux-core/intel_drv.h2
-rw-r--r--linux-core/intel_fb.c70
-rw-r--r--linux-core/radeon_ms_fb.c2
-rw-r--r--shared-core/radeon_ms.h2
7 files changed, 55 insertions, 46 deletions
diff --git a/linux-core/drmP.h b/linux-core/drmP.h
index f5e794e5..52d2782a 100644
--- a/linux-core/drmP.h
+++ b/linux-core/drmP.h
@@ -743,7 +743,7 @@ struct drm_driver {
struct drm_set_version *sv);
/* FB routines, if present */
- int (*fb_probe)(struct drm_device *dev, struct drm_crtc *crtc);
+ int (*fb_probe)(struct drm_device *dev, struct drm_crtc *crtc, struct drm_output *output);
int (*fb_remove)(struct drm_device *dev, struct drm_crtc *crtc);
int (*fb_resize)(struct drm_device *dev, struct drm_crtc *crtc);
diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c
index bdcf5f9b..2bc1c4e3 100644
--- a/linux-core/drm_crtc.c
+++ b/linux-core/drm_crtc.c
@@ -540,8 +540,8 @@ done:
crtc->mode = saved_mode;
crtc->x = saved_x;
crtc->y = saved_y;
- }
-
+ }
+
return ret;
}
EXPORT_SYMBOL(drm_crtc_set_mode);
@@ -1036,16 +1036,6 @@ bool drm_initial_config(struct drm_device *dev, bool can_grow)
drm_pick_crtcs(dev);
- list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-
- /* can't setup the crtc if there's no assigned mode */
- if (!crtc->desired_mode)
- continue;
-
- /* Now setup the fbdev for attached crtcs */
- dev->driver->fb_probe(dev, crtc);
- }
-
/* This is a little screwy, as we've already walked the outputs
* above, but it's a little bit of magic too. There's the potential
* for things not to get setup above if an existing device gets
@@ -1058,6 +1048,8 @@ bool drm_initial_config(struct drm_device *dev, bool can_grow)
if (!output->crtc || !output->crtc->desired_mode)
continue;
+ dev->driver->fb_probe(dev, output->crtc, output);
+
/* and needs an attached fb */
if (output->crtc->fb)
drm_crtc_set_mode(output->crtc, output->crtc->desired_mode, 0, 0);
@@ -1140,12 +1132,15 @@ int drm_crtc_set_config(struct drm_mode_set *set)
struct drm_output *output;
int count = 0, ro;
+ DRM_DEBUG("\n");
+
if (!set)
return -EINVAL;
if (!set->crtc)
return -EINVAL;
+ DRM_DEBUG("crtc: %p fb: %p outputs: %p num_outputs: %i (x, y) (%i, %i)\n", set->crtc, set->fb, set->outputs, set->num_outputs, set->x, set->y);
dev = set->crtc->dev;
/* save previous config */
@@ -1223,6 +1218,7 @@ int drm_crtc_set_config(struct drm_mode_set *set)
kfree(save_crtcs);
return 0;
}
+EXPORT_SYMBOL(drm_crtc_set_config);
/**
* drm_hotplug_stage_two
@@ -1267,7 +1263,7 @@ int drm_hotplug_stage_two(struct drm_device *dev, struct drm_output *output,
/* We should really check if there is a fb using this crtc */
if (!has_config)
- dev->driver->fb_probe(dev, output->crtc);
+ dev->driver->fb_probe(dev, output->crtc, output);
else {
dev->driver->fb_resize(dev, output->crtc);
diff --git a/linux-core/drm_crtc.h b/linux-core/drm_crtc.h
index abe8f3f3..1d36dcd4 100644
--- a/linux-core/drm_crtc.h
+++ b/linux-core/drm_crtc.h
@@ -605,6 +605,7 @@ extern struct drm_framebuffer *drm_framebuffer_create(struct drm_device *dev);
extern void drm_framebuffer_destroy(struct drm_framebuffer *fb);
extern int drmfb_probe(struct drm_device *dev, struct drm_crtc *crtc);
extern int drmfb_remove(struct drm_device *dev, struct drm_framebuffer *fb);
+extern int drm_crtc_set_config(struct drm_mode_set *set);
extern bool drm_crtc_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode,
int x, int y);
extern bool drm_crtc_in_use(struct drm_crtc *crtc);
diff --git a/linux-core/intel_drv.h b/linux-core/intel_drv.h
index e0e6b797..6b89c000 100644
--- a/linux-core/intel_drv.h
+++ b/linux-core/intel_drv.h
@@ -90,7 +90,7 @@ extern struct drm_output* intel_sdvo_find(struct drm_device *dev, int sdvoB);
extern int intel_sdvo_supports_hotplug(struct drm_output *output);
extern void intel_sdvo_set_hotplug(struct drm_output *output, int enable);
-extern int intelfb_probe(struct drm_device *dev, struct drm_crtc *crtc);
+extern int intelfb_probe(struct drm_device *dev, struct drm_crtc *crtc, struct drm_output *output);
extern int intelfb_remove(struct drm_device *dev, struct drm_crtc *crtc);
extern int intelfb_resize(struct drm_device *dev, struct drm_crtc *crtc);
diff --git a/linux-core/intel_fb.c b/linux-core/intel_fb.c
index 73ad35c7..50c24a75 100644
--- a/linux-core/intel_fb.c
+++ b/linux-core/intel_fb.c
@@ -46,10 +46,14 @@
struct intelfb_par {
struct drm_device *dev;
+/*
struct drm_crtc *crtc;
struct drm_display_mode *fb_mode;
struct drm_framebuffer *fb;
+*/
+ struct drm_display_mode *our_mode;
struct drm_mode_set set;
+ struct drm_output *hack;
};
/*
static int
@@ -68,8 +72,8 @@ static int intelfb_setcolreg(unsigned regno, unsigned red, unsigned green,
struct fb_info *info)
{
struct intelfb_par *par = info->par;
- struct drm_framebuffer *fb = par->fb;
- struct drm_crtc *crtc = par->crtc;
+ struct drm_framebuffer *fb = par->set.fb;
+ struct drm_crtc *crtc = par->set.crtc;
if (regno > 255)
return 1;
@@ -109,7 +113,7 @@ static int intelfb_check_var(struct fb_var_screeninfo *var,
{
struct intelfb_par *par = info->par;
/*struct drm_device *dev = par->dev;*/
- struct drm_framebuffer *fb = par->fb;
+ struct drm_framebuffer *fb = par->set.fb;
/*struct drm_output *output;*/
int depth/*, found = 0*/;
@@ -223,13 +227,12 @@ static int intelfb_check_var(struct fb_var_screeninfo *var,
static int intelfb_set_par(struct fb_info *info)
{
struct intelfb_par *par = info->par;
- struct drm_framebuffer *fb = par->fb;
+ struct drm_framebuffer *fb = par->set.fb;
struct drm_device *dev = par->dev;
struct drm_display_mode *drm_mode, *search_mode;
struct drm_output *output = NULL;
struct fb_var_screeninfo *var = &info->var;
int found = 0;
- int changed = 0;
DRM_DEBUG("\n");
@@ -274,7 +277,7 @@ static int intelfb_set_par(struct fb_info *info)
found = 0;
list_for_each_entry(output, &dev->mode_config.output_list, head) {
- if (output->crtc == par->crtc){
+ if (output->crtc == par->set.crtc){
found = 1;
break;
}
@@ -300,17 +303,24 @@ static int intelfb_set_par(struct fb_info *info)
* create a new attachment for the incoming user specified mode
*/
if (!found) {
- if (par->fb_mode) {
+ if (par->our_mode) {
/* this also destroys the mode */
- drm_mode_detachmode_crtc(dev, par->fb_mode);
+ drm_mode_detachmode_crtc(dev, par->our_mode);
}
- par->fb_mode = drm_mode;
+ par->set.mode = drm_mode;
+ par->our_mode = drm_mode;
drm_mode_debug_printmodeline(dev, drm_mode);
/* attach mode */
- drm_mode_attachmode_crtc(dev, par->crtc, par->fb_mode);
+ drm_mode_attachmode_crtc(dev, par->set.crtc, par->set.mode);
+ } else {
+ par->set.mode = drm_mode;
+ if (par->our_mode)
+ drm_mode_detachmode_crtc(dev, par->our_mode);
+ par->our_mode = NULL;
}
+#if 0
/* re-attach fb */
if (!par->crtc->fb) {
par->crtc->fb = par->fb;
@@ -330,6 +340,9 @@ static int intelfb_set_par(struct fb_info *info)
return -EINVAL;
return 0;
+#else
+ return drm_crtc_set_config(&par->set);
+#endif
}
#if 0
@@ -481,27 +494,20 @@ static int intelfb_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info)
{
struct intelfb_par *par = info->par;
- struct drm_crtc *crtc = par->crtc;
- int changed = 0;
+ int ret;
DRM_DEBUG("\n");
- /* TODO add check size and pos*/
- if (par->crtc->x != var->xoffset || par->crtc->y != var->yoffset)
- changed = 1;
-
- /* re-attach fb */
- if (!crtc->fb) {
- crtc->fb = par->fb;
- changed = 1;
- }
+ par->set.x = var->xoffset;
+ par->set.y = var->yoffset;
- if (changed)
- drm_crtc_set_mode(crtc, &crtc->mode, var->xoffset, var->yoffset);
+ ret = drm_crtc_set_config(&par->set);
- info->var.xoffset = var->xoffset;
- info->var.yoffset = var->yoffset;
+ if (!ret) {
+ info->var.xoffset = var->xoffset;
+ info->var.yoffset = var->yoffset;
+ }
- return 0;
+ return ret;
}
static struct fb_ops intelfb_ops = {
@@ -560,7 +566,7 @@ int intelfb_resize(struct drm_device *dev, struct drm_crtc *crtc)
}
EXPORT_SYMBOL(intelfb_resize);
-int intelfb_probe(struct drm_device *dev, struct drm_crtc *crtc)
+int intelfb_probe(struct drm_device *dev, struct drm_crtc *crtc, struct drm_output *output)
{
struct fb_info *info;
struct intelfb_par *par;
@@ -575,6 +581,9 @@ int intelfb_probe(struct drm_device *dev, struct drm_crtc *crtc)
return -EINVAL;
}
+ if (!output)
+ return -EINVAL;
+
fb = drm_framebuffer_create(dev);
if (!fb) {
framebuffer_release(info);
@@ -616,8 +625,11 @@ int intelfb_probe(struct drm_device *dev, struct drm_crtc *crtc)
par = info->par;
par->dev = dev;
- par->crtc = crtc;
- par->fb = fb;
+ par->set.crtc = crtc;
+ par->set.fb = fb;
+ par->hack = output;
+ par->set.outputs = &par->hack;
+ par->set.num_outputs = 1;
info->fbops = &intelfb_ops;
diff --git a/linux-core/radeon_ms_fb.c b/linux-core/radeon_ms_fb.c
index dbbddaf4..ae4f2da5 100644
--- a/linux-core/radeon_ms_fb.c
+++ b/linux-core/radeon_ms_fb.c
@@ -270,7 +270,7 @@ static struct fb_ops radeonfb_ops = {
.fb_imageblit = cfb_imageblit,
};
-int radeonfb_probe(struct drm_device *dev, struct drm_crtc *crtc)
+int radeonfb_probe(struct drm_device *dev, struct drm_crtc *crtc, struct drm_output *output)
{
struct drm_radeon_private *dev_priv = dev->dev_private;
struct fb_info *info;
diff --git a/shared-core/radeon_ms.h b/shared-core/radeon_ms.h
index dd34683e..1fdcd0a1 100644
--- a/shared-core/radeon_ms.h
+++ b/shared-core/radeon_ms.h
@@ -435,7 +435,7 @@ int r3xx_fence_types(struct drm_buffer_object *bo,
uint32_t * class, uint32_t * type);
/* radeon_ms_fb.c */
-int radeonfb_probe(struct drm_device *dev, struct drm_crtc *crtc);
+int radeonfb_probe(struct drm_device *dev, struct drm_crtc *crtc, struct drm_output *output);
int radeonfb_remove(struct drm_device *dev, struct drm_crtc *crtc);
/* radeon_ms_gpu.c */