/* FB routines, if present */
int (*fb_probe)(struct drm_device *dev, struct drm_crtc *crtc, struct drm_connector *connector);
- int (*fb_remove)(struct drm_device *dev, struct drm_framebuffer *fb);
int (*fb_resize)(struct drm_device *dev, struct drm_crtc *crtc);
/* Master routines */
* RETURNS:
* Pointer to new framebuffer or NULL on error.
*/
-struct drm_framebuffer *drm_framebuffer_create(struct drm_device *dev)
+struct drm_framebuffer *drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb,
+ const struct drm_framebuffer_funcs *funcs)
{
- struct drm_framebuffer *fb;
-
- fb = kzalloc(sizeof(struct drm_framebuffer), GFP_KERNEL);
- if (!fb)
- return NULL;
-
drm_mode_object_get(dev, &fb->base, DRM_MODE_OBJECT_FB);
fb->dev = dev;
+ fb->funcs = funcs;
dev->mode_config.num_fb++;
list_add(&fb->head, &dev->mode_config.fb_list);
return fb;
}
-EXPORT_SYMBOL(drm_framebuffer_create);
+EXPORT_SYMBOL(drm_framebuffer_init);
/**
- * drm_framebuffer_destroy - remove a framebuffer object
+ * drm_framebuffer_cleanup - remove a framebuffer object
* @fb: framebuffer to remove
*
* LOCKING:
* Scans all the CRTCs in @dev's mode_config. If they're using @fb, removes
* it, setting it to NULL.
*/
-void drm_framebuffer_destroy(struct drm_framebuffer *fb)
+void drm_framebuffer_cleanup(struct drm_framebuffer *fb)
{
struct drm_device *dev = fb->dev;
struct drm_crtc *crtc;
drm_mode_object_put(dev, &fb->base);
list_del(&fb->head);
dev->mode_config.num_fb--;
-
- kfree(fb);
}
-EXPORT_SYMBOL(drm_framebuffer_destroy);
+EXPORT_SYMBOL(drm_framebuffer_cleanup);
/**
* drm_crtc_init - Initialise a new CRTC object
}
list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) {
- /* there should only be bo of kernel type left */
- if (fb->bo->type != drm_bo_type_kernel)
- drm_framebuffer_destroy(fb);
- else
- dev->driver->fb_remove(dev, fb);
+ fb->funcs->destroy(fb);
}
list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) {
struct drm_mode_fb_cmd *r = data;
struct drm_mode_config *config = &dev->mode_config;
struct drm_framebuffer *fb;
- struct drm_buffer_object *bo;
int ret = 0;
if ((config->min_width > r->width) || (r->width > config->max_width)) {
}
mutex_lock(&dev->mode_config.mutex);
- /* TODO check limits are okay */
- ret = drm_get_buffer_object(dev, &bo, r->handle);
- if (ret || !bo) {
- DRM_ERROR("BO handle not valid\n");
- ret = -EINVAL;
- goto out;
- }
/* TODO check buffer is sufficently large */
/* TODO setup destructor callback */
- fb = drm_framebuffer_create(dev);
+ fb = dev->mode_config.funcs->fb_create(dev, file_priv, r);
if (!fb) {
DRM_ERROR("could not create framebuffer\n");
ret = -EINVAL;
goto out;
}
- fb->width = r->width;
- fb->height = r->height;
- fb->pitch = r->pitch;
- fb->bits_per_pixel = r->bpp;
- fb->depth = r->depth;
- fb->bo = bo;
-
r->buffer_id = fb->base.id;
-
list_add(&fb->filp_head, &file_priv->fbs);
out:
/* TODO release all crtc connected to the framebuffer */
/* TODO unhock the destructor from the buffer object */
- if (fb->bo->type == drm_bo_type_kernel)
- DRM_ERROR("the bo type should not be of kernel type\n");
-
list_del(&fb->filp_head);
- drm_framebuffer_destroy(fb);
+ fb->funcs->destroy(fb);
out:
mutex_unlock(&dev->mode_config.mutex);
r->width = fb->width;
r->depth = fb->depth;
r->bpp = fb->bits_per_pixel;
- r->handle = fb->bo->base.hash.key;
+ r->handle = fb->mm_handle;
r->pitch = fb->pitch;
out:
mutex_lock(&dev->mode_config.mutex);
list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) {
list_del(&fb->filp_head);
- if (fb->bo->type == drm_bo_type_kernel)
- DRM_ERROR("the bo type should not be of kernel_type, the kernel will probably explode, why Dave\n");
-
- drm_framebuffer_destroy(fb);
+ fb->funcs->destroy(fb);
}
mutex_unlock(&dev->mode_config.mutex);
}
struct drm_mode_fb_cmd *r = data;
struct drm_mode_object *obj;
struct drm_framebuffer *fb;
- struct drm_buffer_object *bo;
int found = 0;
struct drm_framebuffer *fbl = NULL;
int ret = 0;
+
/* right replace the current bo attached to this fb with a new bo */
mutex_lock(&dev->mode_config.mutex);
- ret = drm_get_buffer_object(dev, &bo, r->handle);
- if (ret || !bo) {
- ret = -EINVAL;
- goto out;
- }
obj = drm_mode_object_find(dev, r->buffer_id, DRM_MODE_OBJECT_FB);
if (!obj) {
ret = -EINVAL;
goto out;
}
- if (fb->bo->type == drm_bo_type_kernel)
- DRM_ERROR("the bo should not be a kernel bo\n");
-
fb->width = r->width;
fb->height = r->height;
fb->pitch = r->pitch;
fb->bits_per_pixel = r->bpp;
fb->depth = r->depth;
- fb->bo = bo;
+ fb->mm_handle = r->handle;
if (dev->mode_config.funcs->resize_fb)
dev->mode_config.funcs->resize_fb(dev, fb);
struct drm_device;
struct drm_mode_set;
+struct drm_framebuffer;
#define DRM_MODE_OBJECT_CRTC 0xcccccccc
char *raw_edid; /* if any */
};
+struct drm_framebuffer_funcs {
+ void (*destroy)(struct drm_framebuffer *framebuffer);
+};
+
struct drm_framebuffer {
struct drm_device *dev;
struct list_head head;
struct drm_mode_object base;
+ const struct drm_framebuffer_funcs *funcs;
unsigned int pitch;
unsigned int width;
unsigned int height;
unsigned int depth;
int bits_per_pixel;
int flags;
- struct drm_buffer_object *bo;
void *fbdev;
u32 pseudo_palette[17];
- struct drm_bo_kmap_obj kmap;
struct list_head filp_head;
+ uint32_t mm_handle;
};
struct drm_property_blob {
*/
struct drm_mode_config_funcs {
bool (*resize_fb)(struct drm_device *dev, struct drm_framebuffer *fb);
+ struct drm_framebuffer *(*fb_create)(struct drm_device *dev, struct drm_file *file_priv, struct drm_mode_fb_cmd *mode_cmd);
};
struct drm_mode_group {
extern struct drm_display_mode *drm_crtc_mode_create(struct drm_device *dev);
extern void drm_framebuffer_set_object(struct drm_device *dev,
unsigned long handle);
-extern struct drm_framebuffer *drm_framebuffer_create(struct drm_device *dev);
-extern void drm_framebuffer_destroy(struct drm_framebuffer *fb);
+extern struct drm_framebuffer *drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb,
+ const struct drm_framebuffer_funcs *funcs);
+extern void drm_framebuffer_cleanup(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 void drm_crtc_probe_connector_modes(struct drm_device *dev, int maxX, int maxY);
}
EXPORT_SYMBOL(drm_helper_hotplug_stage_two);
+
+int drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb,
+ struct drm_mode_fb_cmd *mode_cmd)
+{
+ fb->width = mode_cmd->width;
+ fb->height = mode_cmd->height;
+ fb->pitch = mode_cmd->pitch;
+ fb->bits_per_pixel = mode_cmd->bpp;
+ fb->depth = mode_cmd->depth;
+ fb->mm_handle = mode_cmd->handle;
+
+ return 0;
+}
+EXPORT_SYMBOL(drm_helper_mode_fill_fb_struct);
extern bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode,
int x, int y);
extern bool drm_helper_crtc_in_use(struct drm_crtc *crtc);
+
+extern int drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb,
+ struct drm_mode_fb_cmd *mode_cmd);
+
static inline void drm_crtc_helper_add(struct drm_crtc *crtc, const struct drm_crtc_helper_funcs *funcs)
{
crtc->helper_private = (void *)funcs;
.get_map_ofs = drm_core_get_map_ofs,
.get_reg_ofs = drm_core_get_reg_ofs,
.fb_probe = intelfb_probe,
- .fb_remove = intelfb_remove,
.fb_resize = intelfb_resize,
.master_create = i915_master_create,
.master_destroy = i915_master_destroy,
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_master_private *master_priv;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+ struct intel_framebuffer *intel_fb;
int pipe = intel_crtc->pipe;
unsigned long Start, Offset;
int dspbase = (pipe == 0 ? DSPAADDR : DSPBADDR);
return;
}
- Start = crtc->fb->bo->offset;
+ intel_fb = to_intel_framebuffer(crtc->fb);
+
+ Start = intel_fb->bo->offset;
Offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8);
I915_WRITE(dspstride, crtc->fb->pitch);
}
}
+static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb)
+{
+ struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
+ struct drm_device *dev = fb->dev;
+ if (fb->fbdev)
+ intelfb_remove(dev, fb);
+
+ drm_framebuffer_cleanup(fb);
+
+ kfree(intel_fb);
+}
+
+static const struct drm_framebuffer_funcs intel_fb_funcs = {
+ .destroy = intel_user_framebuffer_destroy,
+};
+
+struct drm_framebuffer *intel_user_framebuffer_create(struct drm_device *dev,
+ struct drm_file *file_priv,
+ struct drm_mode_fb_cmd *mode_cmd)
+{
+ struct intel_framebuffer *intel_fb;
+
+ intel_fb = kmalloc(sizeof(*intel_fb), GFP_KERNEL);
+ if (!intel_fb)
+ return NULL;
+
+ drm_framebuffer_init(dev, &intel_fb->base, &intel_fb_funcs);
+ drm_helper_mode_fill_fb_struct(&intel_fb->base, mode_cmd);
+
+ if (file_priv) {
+ mutex_lock(&dev->struct_mutex);
+ intel_fb->bo = drm_lookup_buffer_object(file_priv, intel_fb->base.mm_handle, 0);
+ mutex_unlock(&dev->struct_mutex);
+ if (!intel_fb->bo) {
+ kfree(intel_fb);
+ return NULL;
+ }
+ }
+ return &intel_fb->base;
+}
+
static const struct drm_mode_config_funcs intel_mode_funcs = {
.resize_fb = NULL,
+ .fb_create = intel_user_framebuffer_create,
};
void intel_modeset_init(struct drm_device *dev)
u8 slave_addr;
};
+struct intel_framebuffer {
+ struct drm_framebuffer base;
+ struct drm_buffer_object *bo;
+ struct drm_bo_kmap_obj kmap;
+};
+
struct intel_output {
struct drm_connector base;
#define to_intel_crtc(x) container_of(x, struct intel_crtc, base)
#define to_intel_output(x) container_of(x, struct intel_output, base)
#define enc_to_intel_output(x) container_of(x, struct intel_output, enc)
+#define to_intel_framebuffer(x) container_of(x, struct intel_framebuffer, base)
struct intel_i2c_chan *intel_i2c_create(struct drm_device *dev, const u32 reg,
const char *name);
extern int intelfb_resize(struct drm_device *dev, struct drm_crtc *crtc);
extern void intel_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
u16 blue, int regno);
+
+extern struct drm_framebuffer *intel_user_framebuffer_create(struct drm_device *dev,
+ struct drm_file *file_priv,
+ struct drm_mode_fb_cmd *mode_cmd);
#endif /* __INTEL_DRV_H__ */
struct intelfb_par *par;
struct device *device = &dev->pdev->dev;
struct drm_framebuffer *fb;
+ struct intel_framebuffer *intel_fb;
struct drm_display_mode *mode = crtc->desired_mode;
+ struct drm_mode_fb_cmd mode_cmd;
+
struct drm_buffer_object *fbo = NULL;
int ret;
if (!connector)
return -EINVAL;
- fb = drm_framebuffer_create(dev);
- if (!fb) {
- framebuffer_release(info);
- DRM_ERROR("failed to allocate fb.\n");
- return -EINVAL;
- }
- crtc->fb = fb;
-
- /* To allow resizeing without swapping buffers */
- fb->width = 2048;/* crtc->desired_mode->hdisplay; */
- fb->height = 2048;/* crtc->desired_mode->vdisplay; */
+ mode_cmd.width = 2048;/* crtc->desired_mode->hdisplay; */
+ mode_cmd.height = 2048;/* crtc->desired_mode->vdisplay; */
+
+ mode_cmd.bpp = 32;
+ mode_cmd.pitch = mode_cmd.width * ((mode_cmd.bpp + 1) / 8);
+ mode_cmd.depth = 24;
- fb->bits_per_pixel = 32;
- fb->pitch = fb->width * ((fb->bits_per_pixel + 1) / 8);
- fb->depth = 24;
- ret = drm_buffer_object_create(dev, fb->pitch * fb->height,
+ ret = drm_buffer_object_create(dev, mode_cmd.pitch * mode_cmd.height,
drm_bo_type_kernel,
DRM_BO_FLAG_READ |
DRM_BO_FLAG_WRITE |
&fbo);
if (ret || !fbo) {
printk(KERN_ERR "failed to allocate framebuffer\n");
- drm_framebuffer_destroy(fb);
framebuffer_release(info);
return -EINVAL;
}
+
- fb->bo = fbo;
- printk("allocated %dx%d fb: 0x%08lx, bo %p\n", fb->width,
- fb->height, fbo->offset, fbo);
+ fb = intel_user_framebuffer_create(dev, NULL, &mode_cmd);
+ if (!fb) {
+ framebuffer_release(info);
+ drm_bo_usage_deref_unlocked(&fbo);
+ DRM_ERROR("failed to allocate fb.\n");
+ return -EINVAL;
+ }
+
+ intel_fb = to_intel_framebuffer(fb);
+
+ intel_fb->bo = fbo;
+ crtc->fb = fb;
+
+ /* To allow resizeing without swapping buffers */
+ printk("allocated %dx%d fb: 0x%08lx, bo %p\n", intel_fb->base.width,
+ intel_fb->base.height, intel_fb->bo->offset, fbo);
fb->fbdev = info;
}
info->fix.line_length = fb->pitch;
- info->fix.smem_start = fb->bo->offset + dev->mode_config.fb_base;
+ info->fix.smem_start = intel_fb->bo->offset + dev->mode_config.fb_base;
info->fix.smem_len = info->fix.line_length * fb->height;
info->flags = FBINFO_DEFAULT;
- ret = drm_bo_kmap(fb->bo, 0, fb->bo->num_pages, &fb->kmap);
+ ret = drm_bo_kmap(intel_fb->bo, 0, intel_fb->bo->num_pages, &intel_fb->kmap);
if (ret)
DRM_ERROR("error mapping fb: %d\n", ret);
- info->screen_base = fb->kmap.virtual;
+ info->screen_base = intel_fb->kmap.virtual;
info->screen_size = info->fix.smem_len; /* FIXME */
info->pseudo_palette = fb->pseudo_palette;
info->var.xres_virtual = fb->width;
int intelfb_remove(struct drm_device *dev, struct drm_framebuffer *fb)
{
struct fb_info *info;
+ struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
if (!fb)
return -EINVAL;
if (info) {
unregister_framebuffer(info);
- drm_bo_kunmap(&fb->kmap);
- drm_bo_usage_deref_unlocked(&fb->bo);
- drm_framebuffer_destroy(fb);
+ drm_bo_kunmap(&intel_fb->kmap);
+ drm_bo_usage_deref_unlocked(&intel_fb->bo);
framebuffer_release(info);
}
return 0;