aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_fb.c
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2010-03-30 01:34:14 -0400
committerDave Airlie <airlied@redhat.com>2010-04-06 20:24:56 -0400
commit8be48d924c307e72e3797ab5bde81b07a1ccc52d (patch)
tree7d2fec8d40b0a6e9f7bd8a5aef5bb100783ecd44 /drivers/gpu/drm/i915/intel_fb.c
parent386516744ba45d50f42c6999151cc210cb4f96e4 (diff)
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: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_fb.c')
-rw-r--r--drivers/gpu/drm/i915/intel_fb.c93
1 files changed, 43 insertions, 50 deletions
diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c
index b0de9bbde34a..ff6912edf0c6 100644
--- a/drivers/gpu/drm/i915/intel_fb.c
+++ b/drivers/gpu/drm/i915/intel_fb.c
@@ -45,7 +45,7 @@
45#include "i915_drm.h" 45#include "i915_drm.h"
46#include "i915_drv.h" 46#include "i915_drv.h"
47 47
48struct intel_kernel_fbdev { 48struct intel_fbdev {
49 struct drm_fb_helper helper; 49 struct drm_fb_helper helper;
50 struct intel_framebuffer ifb; 50 struct intel_framebuffer ifb;
51 struct list_head fbdev_list; 51 struct list_head fbdev_list;
@@ -71,14 +71,12 @@ static struct drm_fb_helper_funcs intel_fb_helper_funcs = {
71}; 71};
72 72
73 73
74static int intelfb_create(struct drm_device *dev, 74static int intelfb_create(struct intel_fbdev *ifbdev,
75 struct drm_fb_helper_surface_size *sizes, 75 struct drm_fb_helper_surface_size *sizes)
76 struct intel_kernel_fbdev **ifbdev_p)
77{ 76{
77 struct drm_device *dev = ifbdev->helper.dev;
78 struct fb_info *info; 78 struct fb_info *info;
79 struct intel_kernel_fbdev *ifbdev;
80 struct drm_framebuffer *fb; 79 struct drm_framebuffer *fb;
81 struct intel_framebuffer *intel_fb;
82 struct drm_mode_fb_cmd mode_cmd; 80 struct drm_mode_fb_cmd mode_cmd;
83 struct drm_gem_object *fbo = NULL; 81 struct drm_gem_object *fbo = NULL;
84 struct drm_i915_gem_object *obj_priv; 82 struct drm_i915_gem_object *obj_priv;
@@ -117,13 +115,14 @@ static int intelfb_create(struct drm_device *dev,
117 /* Flush everything out, we'll be doing GTT only from now on */ 115 /* Flush everything out, we'll be doing GTT only from now on */
118 i915_gem_object_set_to_gtt_domain(fbo, 1); 116 i915_gem_object_set_to_gtt_domain(fbo, 1);
119 117
120 info = framebuffer_alloc(sizeof(struct intel_kernel_fbdev), device); 118 info = framebuffer_alloc(0, device);
121 if (!info) { 119 if (!info) {
122 ret = -ENOMEM; 120 ret = -ENOMEM;
123 goto out_unpin; 121 goto out_unpin;
124 } 122 }
125 123
126 ifbdev = info->par; 124 info->par = ifbdev;
125
127 intel_framebuffer_init(dev, &ifbdev->ifb, &mode_cmd, fbo); 126 intel_framebuffer_init(dev, &ifbdev->ifb, &mode_cmd, fbo);
128 127
129 fb = &ifbdev->ifb.base; 128 fb = &ifbdev->ifb.base;
@@ -131,22 +130,12 @@ static int intelfb_create(struct drm_device *dev,
131 ifbdev->helper.fb = fb; 130 ifbdev->helper.fb = fb;
132 ifbdev->helper.fbdev = info; 131 ifbdev->helper.fbdev = info;
133 ifbdev->helper.funcs = &intel_fb_helper_funcs; 132 ifbdev->helper.funcs = &intel_fb_helper_funcs;
134 ifbdev->helper.dev = dev;
135
136 *ifbdev_p = ifbdev;
137
138 ret = drm_fb_helper_init_crtc_count(&ifbdev->helper, 2,
139 INTELFB_CONN_LIMIT);
140 if (ret)
141 goto out_unref;
142 133
143 strcpy(info->fix.id, "inteldrmfb"); 134 strcpy(info->fix.id, "inteldrmfb");
144 135
145 info->flags = FBINFO_DEFAULT; 136 info->flags = FBINFO_DEFAULT;
146
147 info->fbops = &intelfb_ops; 137 info->fbops = &intelfb_ops;
148 138
149
150 /* setup aperture base/size for vesafb takeover */ 139 /* setup aperture base/size for vesafb takeover */
151 info->aperture_base = dev->mode_config.fb_base; 140 info->aperture_base = dev->mode_config.fb_base;
152 if (IS_I9XX(dev)) 141 if (IS_I9XX(dev))
@@ -183,8 +172,8 @@ static int intelfb_create(struct drm_device *dev,
183 info->pixmap.scan_align = 1; 172 info->pixmap.scan_align = 1;
184 173
185 DRM_DEBUG_KMS("allocated %dx%d fb: 0x%08x, bo %p\n", 174 DRM_DEBUG_KMS("allocated %dx%d fb: 0x%08x, bo %p\n",
186 intel_fb->base.width, intel_fb->base.height, 175 fb->width, fb->height,
187 obj_priv->gtt_offset, fbo); 176 obj_priv->gtt_offset, fbo);
188 177
189 178
190 mutex_unlock(&dev->struct_mutex); 179 mutex_unlock(&dev->struct_mutex);
@@ -200,76 +189,80 @@ out:
200 return ret; 189 return ret;
201} 190}
202 191
203static int intel_fb_find_or_create_single(struct drm_device *dev, 192static int intel_fb_find_or_create_single(struct drm_fb_helper *helper,
204 struct drm_fb_helper_surface_size *sizes, 193 struct drm_fb_helper_surface_size *sizes)
205 struct drm_fb_helper **fb_ptr)
206{ 194{
207 drm_i915_private_t *dev_priv = dev->dev_private; 195 struct intel_fbdev *ifbdev = (struct intel_fbdev *)helper;
208 struct intel_kernel_fbdev *ifbdev = NULL;
209 int new_fb = 0; 196 int new_fb = 0;
210 int ret; 197 int ret;
211 198
212 if (!dev_priv->fbdev) { 199 if (!helper->fb) {
213 ret = intelfb_create(dev, sizes, 200 ret = intelfb_create(ifbdev, sizes);
214 &ifbdev);
215 if (ret) 201 if (ret)
216 return ret; 202 return ret;
217
218 dev_priv->fbdev = ifbdev;
219 new_fb = 1; 203 new_fb = 1;
220 } else {
221 ifbdev = dev_priv->fbdev;
222 if (ifbdev->ifb.base.width < sizes->surface_width ||
223 ifbdev->ifb.base.height < sizes->surface_height) {
224 DRM_ERROR("Framebuffer not large enough to scale console onto.\n");
225 return -EINVAL;
226 }
227 } 204 }
228
229 *fb_ptr = &ifbdev->helper;
230 return new_fb; 205 return new_fb;
231} 206}
232 207
233static int intelfb_probe(struct drm_device *dev) 208static int intelfb_probe(struct intel_fbdev *ifbdev)
234{ 209{
235 int ret; 210 int ret;
236 211
237 DRM_DEBUG_KMS("\n"); 212 DRM_DEBUG_KMS("\n");
238 ret = drm_fb_helper_single_fb_probe(dev, 32, intel_fb_find_or_create_single); 213 ret = drm_fb_helper_single_fb_probe(&ifbdev->helper, 32);
239 return ret; 214 return ret;
240} 215}
241 216
242int intel_fbdev_destroy(struct drm_device *dev, 217int intel_fbdev_destroy(struct drm_device *dev,
243 struct intel_kernel_fbdev *ifbdev) 218 struct intel_fbdev *ifbdev)
244{ 219{
245 struct fb_info *info; 220 struct fb_info *info;
246 struct intel_framebuffer *ifb = &ifbdev->ifb; 221 struct intel_framebuffer *ifb = &ifbdev->ifb;
247 222
248 info = ifbdev->helper.fbdev; 223 if (ifbdev->helper.fbdev) {
224 info = ifbdev->helper.fbdev;
225 unregister_framebuffer(info);
226 iounmap(info->screen_base);
227 framebuffer_release(info);
228 }
249 229
250 unregister_framebuffer(info);
251 iounmap(info->screen_base);
252 drm_fb_helper_free(&ifbdev->helper); 230 drm_fb_helper_free(&ifbdev->helper);
253 231
254 drm_framebuffer_cleanup(&ifb->base); 232 drm_framebuffer_cleanup(&ifb->base);
255 drm_gem_object_unreference_unlocked(ifb->obj); 233 if (ifb->obj)
256 234 drm_gem_object_unreference_unlocked(ifb->obj);
257 framebuffer_release(info);
258 235
259 return 0; 236 return 0;
260} 237}
261 238
262int intel_fbdev_init(struct drm_device *dev) 239int intel_fbdev_init(struct drm_device *dev)
263{ 240{
264 drm_helper_initial_config(dev); 241 struct intel_fbdev *ifbdev;
265 intelfb_probe(dev); 242 drm_i915_private_t *dev_priv = dev->dev_private;
243
244 ifbdev = kzalloc(sizeof(struct intel_fbdev), GFP_KERNEL);
245 if (!ifbdev)
246 return -ENOMEM;
247
248 dev_priv->fbdev = ifbdev;
249
250 drm_fb_helper_init_crtc_count(dev, &ifbdev->helper, 2,
251 INTELFB_CONN_LIMIT);
252 ifbdev->helper.fb_probe = intel_fb_find_or_create_single;
253 drm_fb_helper_initial_config(&ifbdev->helper);
254 intelfb_probe(ifbdev);
266 return 0; 255 return 0;
267} 256}
268 257
269void intel_fbdev_fini(struct drm_device *dev) 258void intel_fbdev_fini(struct drm_device *dev)
270{ 259{
271 drm_i915_private_t *dev_priv = dev->dev_private; 260 drm_i915_private_t *dev_priv = dev->dev_private;
261 if (!dev_priv->fbdev)
262 return;
263
272 intel_fbdev_destroy(dev, dev_priv->fbdev); 264 intel_fbdev_destroy(dev, dev_priv->fbdev);
265 kfree(dev_priv->fbdev);
273 dev_priv->fbdev = NULL; 266 dev_priv->fbdev = NULL;
274} 267}
275MODULE_LICENSE("GPL and additional rights"); 268MODULE_LICENSE("GPL and additional rights");