Commit 8be48d92 authored by Dave Airlie's avatar Dave Airlie

drm/kms/fb: move to using fb helper crtc grouping instead of core crtc list

This move to using the list of crtcs in the fb helper and cleans up the
whole picking code, now we store the crtc/connectors we want directly
into the modeset and we use the modeset directly to set the mode.

Fixes from James Simmons and Ben Skeggs.
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 38651674
......@@ -625,10 +625,6 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
ret = -EINVAL;
goto fail;
}
/* TODO are these needed? */
set->crtc->desired_x = set->x;
set->crtc->desired_y = set->y;
set->crtc->desired_mode = set->mode;
}
drm_helper_disable_unused_functions(dev);
} else if (fb_changed) {
......
This diff is collapsed.
......@@ -220,7 +220,7 @@ enum no_fbc_reason {
FBC_NOT_TILED, /* buffer not tiled */
};
struct intel_kernel_fbdev;
struct intel_fbdev;
typedef struct drm_i915_private {
struct drm_device *dev;
......@@ -630,7 +630,8 @@ typedef struct drm_i915_private {
enum no_fbc_reason no_fbc_reason;
struct intel_kernel_fbdev *fbdev;
/* list of fbdev register on this device */
struct intel_fbdev *fbdev;
} drm_i915_private_t;
/** driver private structure attached to each drm_gem_object */
......
......@@ -45,7 +45,7 @@
#include "i915_drm.h"
#include "i915_drv.h"
struct intel_kernel_fbdev {
struct intel_fbdev {
struct drm_fb_helper helper;
struct intel_framebuffer ifb;
struct list_head fbdev_list;
......@@ -71,14 +71,12 @@ static struct drm_fb_helper_funcs intel_fb_helper_funcs = {
};
static int intelfb_create(struct drm_device *dev,
struct drm_fb_helper_surface_size *sizes,
struct intel_kernel_fbdev **ifbdev_p)
static int intelfb_create(struct intel_fbdev *ifbdev,
struct drm_fb_helper_surface_size *sizes)
{
struct drm_device *dev = ifbdev->helper.dev;
struct fb_info *info;
struct intel_kernel_fbdev *ifbdev;
struct drm_framebuffer *fb;
struct intel_framebuffer *intel_fb;
struct drm_mode_fb_cmd mode_cmd;
struct drm_gem_object *fbo = NULL;
struct drm_i915_gem_object *obj_priv;
......@@ -117,13 +115,14 @@ static int intelfb_create(struct drm_device *dev,
/* Flush everything out, we'll be doing GTT only from now on */
i915_gem_object_set_to_gtt_domain(fbo, 1);
info = framebuffer_alloc(sizeof(struct intel_kernel_fbdev), device);
info = framebuffer_alloc(0, device);
if (!info) {
ret = -ENOMEM;
goto out_unpin;
}
ifbdev = info->par;
info->par = ifbdev;
intel_framebuffer_init(dev, &ifbdev->ifb, &mode_cmd, fbo);
fb = &ifbdev->ifb.base;
......@@ -131,22 +130,12 @@ static int intelfb_create(struct drm_device *dev,
ifbdev->helper.fb = fb;
ifbdev->helper.fbdev = info;
ifbdev->helper.funcs = &intel_fb_helper_funcs;
ifbdev->helper.dev = dev;
*ifbdev_p = ifbdev;
ret = drm_fb_helper_init_crtc_count(&ifbdev->helper, 2,
INTELFB_CONN_LIMIT);
if (ret)
goto out_unref;
strcpy(info->fix.id, "inteldrmfb");
info->flags = FBINFO_DEFAULT;
info->fbops = &intelfb_ops;
/* setup aperture base/size for vesafb takeover */
info->aperture_base = dev->mode_config.fb_base;
if (IS_I9XX(dev))
......@@ -183,8 +172,8 @@ static int intelfb_create(struct drm_device *dev,
info->pixmap.scan_align = 1;
DRM_DEBUG_KMS("allocated %dx%d fb: 0x%08x, bo %p\n",
intel_fb->base.width, intel_fb->base.height,
obj_priv->gtt_offset, fbo);
fb->width, fb->height,
obj_priv->gtt_offset, fbo);
mutex_unlock(&dev->struct_mutex);
......@@ -200,76 +189,80 @@ static int intelfb_create(struct drm_device *dev,
return ret;
}
static int intel_fb_find_or_create_single(struct drm_device *dev,
struct drm_fb_helper_surface_size *sizes,
struct drm_fb_helper **fb_ptr)
static int intel_fb_find_or_create_single(struct drm_fb_helper *helper,
struct drm_fb_helper_surface_size *sizes)
{
drm_i915_private_t *dev_priv = dev->dev_private;
struct intel_kernel_fbdev *ifbdev = NULL;
struct intel_fbdev *ifbdev = (struct intel_fbdev *)helper;
int new_fb = 0;
int ret;
if (!dev_priv->fbdev) {
ret = intelfb_create(dev, sizes,
&ifbdev);
if (!helper->fb) {
ret = intelfb_create(ifbdev, sizes);
if (ret)
return ret;
dev_priv->fbdev = ifbdev;
new_fb = 1;
} else {
ifbdev = dev_priv->fbdev;
if (ifbdev->ifb.base.width < sizes->surface_width ||
ifbdev->ifb.base.height < sizes->surface_height) {
DRM_ERROR("Framebuffer not large enough to scale console onto.\n");
return -EINVAL;
}
}
*fb_ptr = &ifbdev->helper;
return new_fb;
}
static int intelfb_probe(struct drm_device *dev)
static int intelfb_probe(struct intel_fbdev *ifbdev)
{
int ret;
DRM_DEBUG_KMS("\n");
ret = drm_fb_helper_single_fb_probe(dev, 32, intel_fb_find_or_create_single);
ret = drm_fb_helper_single_fb_probe(&ifbdev->helper, 32);
return ret;
}
int intel_fbdev_destroy(struct drm_device *dev,
struct intel_kernel_fbdev *ifbdev)
struct intel_fbdev *ifbdev)
{
struct fb_info *info;
struct intel_framebuffer *ifb = &ifbdev->ifb;
info = ifbdev->helper.fbdev;
if (ifbdev->helper.fbdev) {
info = ifbdev->helper.fbdev;
unregister_framebuffer(info);
iounmap(info->screen_base);
framebuffer_release(info);
}
unregister_framebuffer(info);
iounmap(info->screen_base);
drm_fb_helper_free(&ifbdev->helper);
drm_framebuffer_cleanup(&ifb->base);
drm_gem_object_unreference_unlocked(ifb->obj);
framebuffer_release(info);
if (ifb->obj)
drm_gem_object_unreference_unlocked(ifb->obj);
return 0;
}
int intel_fbdev_init(struct drm_device *dev)
{
drm_helper_initial_config(dev);
intelfb_probe(dev);
struct intel_fbdev *ifbdev;
drm_i915_private_t *dev_priv = dev->dev_private;
ifbdev = kzalloc(sizeof(struct intel_fbdev), GFP_KERNEL);
if (!ifbdev)
return -ENOMEM;
dev_priv->fbdev = ifbdev;
drm_fb_helper_init_crtc_count(dev, &ifbdev->helper, 2,
INTELFB_CONN_LIMIT);
ifbdev->helper.fb_probe = intel_fb_find_or_create_single;
drm_fb_helper_initial_config(&ifbdev->helper);
intelfb_probe(ifbdev);
return 0;
}
void intel_fbdev_fini(struct drm_device *dev)
{
drm_i915_private_t *dev_priv = dev->dev_private;
if (!dev_priv->fbdev)
return;
intel_fbdev_destroy(dev, dev_priv->fbdev);
kfree(dev_priv->fbdev);
dev_priv->fbdev = NULL;
}
MODULE_LICENSE("GPL and additional rights");
......@@ -627,7 +627,7 @@ struct drm_nouveau_private {
struct dentry *channel_root;
} debugfs;
struct nouveau_fbcon_par *nfbdev;
struct nouveau_fbdev *nfbdev;
};
static inline struct drm_nouveau_private *
......
......@@ -53,8 +53,8 @@
static int
nouveau_fbcon_sync(struct fb_info *info)
{
struct nouveau_fbcon_par *par = info->par;
struct drm_device *dev = par->dev;
struct nouveau_fbdev *nfbdev = info->par;
struct drm_device *dev = nfbdev->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_channel *chan = dev_priv->channel;
int ret, i;
......@@ -200,9 +200,9 @@ nouveau_fbcon_has_vesafb_or_efifb(struct drm_device *dev)
#endif
static void
nouveau_fbcon_zfill(struct drm_device *dev, struct nouveau_fbcon_par *fbpar)
nouveau_fbcon_zfill(struct drm_device *dev, struct nouveau_fbdev *nfbdev)
{
struct fb_info *info = fbpar->helper.fbdev;
struct fb_info *info = nfbdev->helper.fbdev;
struct fb_fillrect rect;
/* Clear the entire fbcon. The drm will program every connector
......@@ -218,13 +218,12 @@ nouveau_fbcon_zfill(struct drm_device *dev, struct nouveau_fbcon_par *fbpar)
}
static int
nouveau_fbcon_create(struct drm_device *dev,
struct drm_fb_helper_surface_size *sizes,
struct nouveau_fbcon_par **fbpar_p)
nouveau_fbcon_create(struct nouveau_fbdev *nfbdev,
struct drm_fb_helper_surface_size *sizes)
{
struct drm_device *dev = nfbdev->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct fb_info *info;
struct nouveau_fbcon_par *par;
struct drm_framebuffer *fb;
struct nouveau_framebuffer *nouveau_fb;
struct nouveau_bo *nvbo;
......@@ -267,27 +266,23 @@ nouveau_fbcon_create(struct drm_device *dev,
mutex_lock(&dev->struct_mutex);
info = framebuffer_alloc(sizeof(struct nouveau_fbcon_par), device);
info = framebuffer_alloc(0, device);
if (!info) {
ret = -ENOMEM;
goto out_unref;
}
par = info->par;
nouveau_framebuffer_init(dev, &par->nouveau_fb, &mode_cmd, nvbo);
info->par = nfbdev;
fb = &par->nouveau_fb.base;
/* setup helper */
par->helper.fb = fb;
par->helper.fbdev = info;
par->helper.funcs = &nouveau_fbcon_helper_funcs;
par->helper.dev = dev;
nouveau_framebuffer_init(dev, &nfbdev->nouveau_fb, &mode_cmd, nvbo);
*fbpar_p = par;
nouveau_fb = &nfbdev->nouveau_fb;
fb = &nouveau_fb->base;
ret = drm_fb_helper_init_crtc_count(&par->helper, 2, 4);
if (ret)
goto out_unref;
/* setup helper */
nfbdev->helper.fb = fb;
nfbdev->helper.fbdev = info;
nfbdev->helper.funcs = &nouveau_fbcon_helper_funcs;
strcpy(info->fix.id, "nouveaufb");
if (nouveau_nofbaccel)
......@@ -305,7 +300,7 @@ nouveau_fbcon_create(struct drm_device *dev,
info->screen_size = size;
drm_fb_helper_fill_fix(info, fb->pitch, fb->depth);
drm_fb_helper_fill_var(info, &par->helper, sizes->fb_width, sizes->fb_height);
drm_fb_helper_fill_var(info, &nfbdev->helper, sizes->fb_width, sizes->fb_height);
/* FIXME: we really shouldn't expose mmio space at all */
info->fix.mmio_start = pci_resource_start(dev->pdev, 1);
......@@ -338,8 +333,6 @@ nouveau_fbcon_create(struct drm_device *dev,
info->pixmap.flags = FB_PIXMAP_SYSTEM;
info->pixmap.scan_align = 1;
par->dev = dev;
if (dev_priv->channel && !nouveau_nofbaccel) {
switch (dev_priv->card_type) {
case NV_50:
......@@ -353,7 +346,7 @@ nouveau_fbcon_create(struct drm_device *dev,
};
}
nouveau_fbcon_zfill(dev, par);
nouveau_fbcon_zfill(dev, nfbdev);
/* To allow resizeing without swapping buffers */
NV_INFO(dev, "allocated %dx%d fb: 0x%lx, bo %p\n",
......@@ -372,66 +365,56 @@ nouveau_fbcon_create(struct drm_device *dev,
}
static int
nouveau_fbcon_find_or_create_single(struct drm_device *dev,
struct drm_fb_helper_surface_size *sizes,
struct drm_fb_helper **fb_ptr)
nouveau_fbcon_find_or_create_single(struct drm_fb_helper *helper,
struct drm_fb_helper_surface_size *sizes)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_fbcon_par *fbpar;
struct nouveau_fbdev *nfbdev = (struct nouveau_fbdev *)helper;
int new_fb = 0;
int ret;
if (!dev_priv->nfbdev) {
ret = nouveau_fbcon_create(dev, sizes,
&fbpar);
if (!helper->fb) {
ret = nouveau_fbcon_create(nfbdev, sizes);
if (ret)
return ret;
dev_priv->nfbdev = fbpar;
new_fb = 1;
} else {
fbpar = dev_priv->nfbdev;
if (fbpar->nouveau_fb.base.width < sizes->surface_width ||
fbpar->nouveau_fb.base.height < sizes->surface_height) {
DRM_ERROR("Framebuffer not large enough to scale console onto.\n");
return -EINVAL;
}
}
*fb_ptr = &fbpar->helper;
return new_fb;
}
static int
nouveau_fbcon_probe(struct drm_device *dev)
nouveau_fbcon_probe(struct nouveau_fbdev *nfbdev)
{
NV_DEBUG_KMS(dev, "\n");
NV_DEBUG_KMS(nfbdev->dev, "\n");
return drm_fb_helper_single_fb_probe(dev, 32, nouveau_fbcon_find_or_create_single);
return drm_fb_helper_single_fb_probe(&nfbdev->helper, 32);
}
int
nouveau_fbcon_destroy(struct drm_device *dev, struct nouveau_fbcon_par *fbpar)
nouveau_fbcon_destroy(struct drm_device *dev, struct nouveau_fbdev *nfbdev)
{
struct nouveau_framebuffer *nouveau_fb = &fbpar->nouveau_fb;
struct nouveau_framebuffer *nouveau_fb = &nfbdev->nouveau_fb;
struct fb_info *info;
info = fbpar->helper.fbdev;
unregister_framebuffer(info);
nouveau_bo_unmap(nouveau_fb->nvbo);
drm_gem_object_unreference_unlocked(nouveau_fb->nvbo->gem);
nouveau_fb->nvbo = NULL;
drm_fb_helper_free(&fbpar->helper);
if (nfbdev->helper.fbdev) {
info = nfbdev->helper.fbdev;
unregister_framebuffer(info);
framebuffer_release(info);
}
if (nouveau_fb->nvbo) {
nouveau_bo_unmap(nouveau_fb->nvbo);
drm_gem_object_unreference_unlocked(nouveau_fb->nvbo->gem);
nouveau_fb->nvbo = NULL;
}
drm_fb_helper_free(&nfbdev->helper);
drm_framebuffer_cleanup(&nouveau_fb->base);
framebuffer_release(info);
return 0;
}
void nouveau_fbcon_gpu_lockup(struct fb_info *info)
{
struct nouveau_fbcon_par *par = info->par;
struct drm_device *dev = par->dev;
struct nouveau_fbdev *nfbdev = info->par;
struct drm_device *dev = nfbdev->dev;
NV_ERROR(dev, "GPU lockup - switching to software fbcon\n");
info->flags |= FBINFO_HWACCEL_DISABLED;
......@@ -439,15 +422,33 @@ void nouveau_fbcon_gpu_lockup(struct fb_info *info)
int nouveau_fbcon_init(struct drm_device *dev)
{
drm_helper_initial_config(dev);
nouveau_fbcon_probe(dev);
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_fbdev *nfbdev;
nfbdev = kzalloc(sizeof(struct nouveau_fbdev), GFP_KERNEL);
if (!nfbdev)
return -ENOMEM;
nfbdev->dev = dev;
dev_priv->nfbdev = nfbdev;
drm_fb_helper_init_crtc_count(dev, &nfbdev->helper,
2, 4);
nfbdev->helper.fb_probe = nouveau_fbcon_find_or_create_single;
drm_fb_helper_initial_config(&nfbdev->helper);
nouveau_fbcon_probe(nfbdev);
return 0;
}
void nouveau_fbcon_fini(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
if (!dev_priv->nfbdev)
return;
nouveau_fbcon_destroy(dev, dev_priv->nfbdev);
kfree(dev_priv->nfbdev);
dev_priv->nfbdev = NULL;
}
......
......@@ -30,7 +30,7 @@
#include "drm_fb_helper.h"
#include "nouveau_fb.h"
struct nouveau_fbcon_par {
struct nouveau_fbdev {
struct drm_fb_helper helper;
struct nouveau_framebuffer nouveau_fb;
struct list_head fbdev_list;
......
......@@ -30,8 +30,8 @@
void
nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region)
{
struct nouveau_fbcon_par *par = info->par;
struct drm_device *dev = par->dev;
struct nouveau_fbdev *nfbdev = info->par;
struct drm_device *dev = nfbdev->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_channel *chan = dev_priv->channel;
......@@ -57,8 +57,8 @@ nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region)
void
nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
{
struct nouveau_fbcon_par *par = info->par;
struct drm_device *dev = par->dev;
struct nouveau_fbdev *nfbdev = info->par;
struct drm_device *dev = nfbdev->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_channel *chan = dev_priv->channel;
......@@ -91,8 +91,8 @@ nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
void
nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
{
struct nouveau_fbcon_par *par = info->par;
struct drm_device *dev = par->dev;
struct nouveau_fbdev *nfbdev = info->par;
struct drm_device *dev = nfbdev->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_channel *chan = dev_priv->channel;
uint32_t fg;
......@@ -179,8 +179,8 @@ nv04_fbcon_grobj_new(struct drm_device *dev, int class, uint32_t handle)
int
nv04_fbcon_accel_init(struct fb_info *info)
{
struct nouveau_fbcon_par *par = info->par;
struct drm_device *dev = par->dev;
struct nouveau_fbdev *nfbdev = info->par;
struct drm_device *dev = nfbdev->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_channel *chan = dev_priv->channel;
const int sub = NvSubCtxSurf2D;
......
......@@ -6,8 +6,8 @@
void
nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
{
struct nouveau_fbcon_par *par = info->par;
struct drm_device *dev = par->dev;
struct nouveau_fbdev *nfbdev = info->par;
struct drm_device *dev = nfbdev->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_channel *chan = dev_priv->channel;
......@@ -49,8 +49,8 @@ nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
void
nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region)
{
struct nouveau_fbcon_par *par = info->par;
struct drm_device *dev = par->dev;
struct nouveau_fbdev *nfbdev = info->par;
struct drm_device *dev = nfbdev->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_channel *chan = dev_priv->channel;
......@@ -84,8 +84,8 @@ nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region)
void
nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
{
struct nouveau_fbcon_par *par = info->par;
struct drm_device *dev = par->dev;
struct nouveau_fbdev *nfbdev = info->par;
struct drm_device *dev = nfbdev->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_channel *chan = dev_priv->channel;
uint32_t width, dwords, *data = (uint32_t *)image->data;
......@@ -152,8 +152,8 @@ nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
int
nv50_fbcon_accel_init(struct fb_info *info)
{
struct nouveau_fbcon_par *par = info->par;
struct drm_device *dev = par->dev;
struct nouveau_fbdev *nfbdev = info->par;
struct drm_device *dev = nfbdev->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_channel *chan = dev_priv->channel;
struct nouveau_gpuobj *eng2d = NULL;
......
This diff is collapsed.
......@@ -203,7 +203,7 @@ enum radeon_dvo_chip {
DVO_SIL1178,
};
struct radeon_kernel_fbdev;
struct radeon_fbdev;
struct radeon_mode_info {
struct atom_context *atom_context;
......@@ -223,7 +223,7 @@ struct radeon_mode_info {
struct edid *bios_hardcoded_edid;
/* pointer to fbdev info structure */
struct radeon_kernel_fbdev *rfbdev;
struct radeon_fbdev *rfbdev;
};
#define MAX_H_CODE_TIMING_LEN 32
......
......@@ -367,9 +367,6 @@ struct drm_crtc_funcs {
* @enabled: is this CRTC enabled?
* @x: x position on screen
* @y: y position on screen
* @desired_mode: new desired mode
* @desired_x: desired x for desired_mode
* @desired_y: desired y for desired_mode
* @funcs: CRTC control functions
*
* Each CRTC may have one or more connectors associated with it. This structure
......@@ -389,8 +386,6 @@ struct drm_crtc {
struct drm_display_mode mode;
int x, y;
struct drm_display_mode *desired_mode;
int desired_x, desired_y;
const struct drm_crtc_funcs *funcs;
/* CRTC gamma size for reporting to userspace */
......
......@@ -33,6 +33,7 @@
struct drm_fb_helper_crtc {
uint32_t crtc_id;
struct drm_mode_set mode_set;
struct drm_display_mode *desired_mode;
};
......@@ -81,14 +82,16 @@ struct drm_fb_helper {
struct fb_info *fbdev;
u32 pseudo_palette[17];
struct list_head kernel_fb_list;
int (*fb_probe)(struct drm_fb_helper *helper,
struct drm_fb_helper_surface_size *sizes);
};
int drm_fb_helper_single_fb_probe(struct drm_device *dev,
int preferred_bpp,
int (*fb_create)(struct drm_device *dev,
struct drm_fb_helper_surface_size *sizes,
struct drm_fb_helper **fb_ptr));
int drm_fb_helper_init_crtc_count(struct drm_fb_helper *helper, int crtc_count,
int drm_fb_helper_single_fb_probe(struct drm_fb_helper *helper,
int preferred_bpp);
int drm_fb_helper_init_crtc_count(struct drm_device *dev,
struct drm_fb_helper *helper, int crtc_count,
int max_conn);
void drm_fb_helper_free(struct drm_fb_helper *helper);
int drm_fb_helper_blank(int blank, struct fb_info *info);
......@@ -114,6 +117,8 @@ int drm_fb_helper_add_connector(struct drm_connector *connector);
int drm_fb_helper_parse_command_line(struct drm_device *dev);
int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info);
bool drm_helper_fb_hotplug_event(struct drm_device *dev);
bool drm_helper_initial_config(struct drm_device *dev);
bool drm_helper_fb_hotplug_event(struct drm_fb_helper *fb_helper, u32 max_width,
u32 max_height);
bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper);
#endif
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