summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libdrm/xf86drmMode.c22
-rw-r--r--libdrm/xf86drmMode.h6
-rw-r--r--linux-core/drm_crtc.c95
-rw-r--r--linux-core/drm_crtc.h27
-rw-r--r--linux-core/drm_drv.c2
-rw-r--r--shared-core/drm.h10
-rw-r--r--shared-core/i915_dma.c2
7 files changed, 135 insertions, 29 deletions
diff --git a/libdrm/xf86drmMode.c b/libdrm/xf86drmMode.c
index c4403b1c..55a9d91c 100644
--- a/libdrm/xf86drmMode.c
+++ b/libdrm/xf86drmMode.c
@@ -192,6 +192,28 @@ err_allocs:
return 0;
}
+uint32_t drmModeAddFB(int fd, uint32_t width, uint32_t height,
+ uint8_t bpp, uint32_t pitch, drmBO *bo)
+{
+ struct drm_mode_fb_cmd f;
+
+ f.width = width;
+ f.height = height;
+ f.pitch = pitch;
+ f.bpp = bpp;
+ f.handle = bo->handle;
+
+ if (ioctl(fd, DRM_IOCTL_MODE_ADDFB, &f))
+ return 0;
+
+ return f.buffer_id;
+}
+
+int drmModeRmFB(int fd, uint32_t bufferId)
+{
+ return ioctl(fd, DRM_IOCTL_MODE_RMFB, bufferId);
+}
+
#if 0
int drmModeForceProbe(int fd, uint32_t outputId)
{
diff --git a/libdrm/xf86drmMode.h b/libdrm/xf86drmMode.h
index c027a16d..45b157a8 100644
--- a/libdrm/xf86drmMode.h
+++ b/libdrm/xf86drmMode.h
@@ -77,8 +77,10 @@ typedef struct _drmModeRes {
typedef struct _drmModeFrameBuffer {
- uint32_t minWidth, maxWidth;
- uint32_t minHeight, maxHeight;
+ uint32_t width;
+ uint32_t height;
+ uint32_t pitch;
+ uint8_t bpp;
} drmModeFrameBuffer, *drmModeFrameBufferPtr;
diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c
index fe27e386..a02124f3 100644
--- a/linux-core/drm_crtc.c
+++ b/linux-core/drm_crtc.c
@@ -465,18 +465,19 @@ void drm_crtc_config_init(drm_device_t *dev)
}
EXPORT_SYMBOL(drm_crtc_config_init);
-void drm_framebuffer_set_object(drm_device_t *dev, unsigned long handle)
+static int drm_get_buffer_object(drm_device_t *dev, struct drm_buffer_object **bo, unsigned long handle)
{
- struct drm_framebuffer *fb;
drm_user_object_t *uo;
drm_hash_item_t *hash;
- drm_buffer_object_t *bo;
int ret;
+ *bo = NULL;
+
mutex_lock(&dev->struct_mutex);
ret = drm_ht_find_item(&dev->object_hash, handle, &hash);
if (ret) {
DRM_ERROR("Couldn't find handle.\n");
+ ret = -EINVAL;
goto out_err;
}
@@ -485,20 +486,13 @@ void drm_framebuffer_set_object(drm_device_t *dev, unsigned long handle)
ret = -EINVAL;
goto out_err;
}
-
- bo = drm_user_object_entry(uo, drm_buffer_object_t, base);
-
- /* get the first fb */
- list_for_each_entry(fb, &dev->crtc_config.fb_list, head) {
- fb->offset = bo->offset;
- break;
- }
+
+ *bo = drm_user_object_entry(uo, drm_buffer_object_t, base);
ret = 0;
out_err:
mutex_unlock(&dev->struct_mutex);
- return;
+ return ret;
}
-EXPORT_SYMBOL(drm_framebuffer_set_object);
bool drm_initial_config(drm_device_t *dev, bool can_grow)
{
@@ -923,3 +917,78 @@ int drm_mode_setcrtc(struct inode *inode, struct file *filp,
retcode = drm_crtc_set_config(crtc, &crtc_req, mode, output_set);
return retcode;
}
+
+/* Add framebuffer ioctl */
+int drm_mode_addfb(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
+ struct drm_mode_fb_cmd __user *argp = (void __user *)arg;
+ struct drm_mode_fb_cmd r;
+ struct drm_crtc_config *config = &dev->crtc_config;
+ struct drm_framebuffer *fb;
+ struct drm_buffer_object *bo;
+ int ret;
+
+ if (!copy_from_user(&r, argp, sizeof(r)))
+ return -EFAULT;
+
+ if (config->min_width > r.width || r.width > config->max_width) {
+ DRM_ERROR("mode new framebuffer width not within limits");
+ return -EINVAL;
+ }
+ if (config->min_height > r.height || r.height > config->min_height) {
+ DRM_ERROR("mode new framebuffer height not within limits");
+ return -EINVAL;
+ }
+
+ /* TODO check limits are okay */
+ ret = drm_get_buffer_object(dev, &bo, r.handle);
+ if (ret || !bo)
+ return -EINVAL;
+
+ /* TODO check buffer is sufficently large */
+ /* TODO setup destructor callback */
+
+ fb = drm_framebuffer_create(dev);
+ if(!fb)
+ return -EINVAL;;
+
+ fb->width = r.width;
+ fb->height = r.height;
+ fb->pitch = r.pitch;
+ fb->bits_per_pixel = r.bpp;
+ fb->offset = bo->offset;
+ fb->bo = bo;
+
+ r.buffer_id = fb->id;
+ if (!copy_to_user(argp, &r, sizeof(r)))
+ return -EFAULT;
+
+ return 0;
+}
+
+int drm_mode_rmfb(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+ struct drm_framebuffer *fb = 0;
+ uint32_t id = arg;
+
+ fb = idr_find(&dev->crtc_config.crtc_idr, id);
+ /* TODO check that we realy get a framebuffer back. */
+ if (!fb || (id != fb->id)) {
+ DRM_ERROR("mode invalid framebuffer id\n");
+ return -EINVAL;
+ }
+
+ /* TODO check if we own the buffer */
+ /* TODO release all crtc connected to the framebuffer */
+ /* TODO unhock the destructor from the buffer object */
+
+ drm_framebuffer_destroy(fb);
+
+ return 0;
+}
diff --git a/linux-core/drm_crtc.h b/linux-core/drm_crtc.h
index 21908f0c..36d5f316 100644
--- a/linux-core/drm_crtc.h
+++ b/linux-core/drm_crtc.h
@@ -178,6 +178,7 @@ struct drm_framebuffer {
unsigned int depth;
int bits_per_pixel;
int flags;
+ struct drm_buffer_object *bo;
};
struct drm_crtc;
struct drm_output;
@@ -432,17 +433,6 @@ extern void drm_disable_unused_functions(struct drm_device *dev);
extern struct drm_display_mode *drm_crtc_mode_create(struct drm_device *dev);
extern void drm_crtc_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode);
-
-/* IOCTLs */
-extern int drm_mode_getresources(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-
-extern int drm_mode_getcrtc(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-extern int drm_mode_getoutput(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-extern int drm_mode_setcrtc(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
extern void drm_mode_list_concat(struct list_head *head,
struct list_head *new);
extern void drm_mode_validate_size(struct drm_device *dev,
@@ -454,7 +444,20 @@ extern void drm_mode_sort(struct list_head *mode_list);
extern int drm_mode_vrefresh(struct drm_display_mode *mode);
extern void drm_mode_set_crtcinfo(struct drm_display_mode *p,
int adjust_flags);
-extern struct drm_display_mode *drm_crtc_mode_create(struct drm_device *dev);
+/* IOCTLs */
+extern int drm_mode_getresources(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+
+extern int drm_mode_getcrtc(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_mode_getoutput(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_mode_setcrtc(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_mode_addfb(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_mode_rmfb(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
#endif /* __DRM_CRTC_H__ */
diff --git a/linux-core/drm_drv.c b/linux-core/drm_drv.c
index c8ee054f..80007170 100644
--- a/linux-core/drm_drv.c
+++ b/linux-core/drm_drv.c
@@ -127,6 +127,8 @@ static drm_ioctl_desc_t drm_ioctls[] = {
[DRM_IOCTL_NR(DRM_IOCTL_MODE_GETCRTC)] = {drm_mode_getcrtc, DRM_MASTER|DRM_ROOT_ONLY},
[DRM_IOCTL_NR(DRM_IOCTL_MODE_GETOUTPUT)] = {drm_mode_getoutput, DRM_MASTER|DRM_ROOT_ONLY},
[DRM_IOCTL_NR(DRM_IOCTL_MODE_SETCRTC)] = {drm_mode_setcrtc, DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_IOCTL_MODE_ADDFB)] = {drm_mode_addfb, DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_IOCTL_MODE_RMFB)] = {drm_mode_rmfb, DRM_MASTER|DRM_ROOT_ONLY},
};
#define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls )
diff --git a/shared-core/drm.h b/shared-core/drm.h
index 49bc41bc..8329609f 100644
--- a/shared-core/drm.h
+++ b/shared-core/drm.h
@@ -962,6 +962,14 @@ struct drm_mode_get_output {
};
+struct drm_mode_fb_cmd {
+ unsigned int buffer_id;
+ unsigned int width, height;
+ unsigned int pitch;
+ unsigned int bpp;
+ unsigned int handle;
+};
+
/**
* \name Ioctls Definitions
*/
@@ -1037,6 +1045,8 @@ struct drm_mode_get_output {
#define DRM_IOCTL_MODE_GETCRTC DRM_IOWR(0xA1, struct drm_mode_crtc)
#define DRM_IOCTL_MODE_GETOUTPUT DRM_IOWR(0xA2, struct drm_mode_get_output)
#define DRM_IOCTL_MODE_SETCRTC DRM_IOWR(0xA3, struct drm_mode_crtc)
+#define DRM_IOCTL_MODE_ADDFB DRM_IOWR(0xA4, struct drm_mode_fb_cmd)
+#define DRM_IOCTL_MODE_RMFB DRM_IOWR(0xA5, unsigned int)
/*@}*/
/**
diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c
index a5f1473a..811e4bb9 100644
--- a/shared-core/i915_dma.c
+++ b/shared-core/i915_dma.c
@@ -171,8 +171,6 @@ static int i915_initialize(drm_device_t * dev,
I915_WRITE(0x02080, dev_priv->dma_status_page);
DRM_DEBUG("Enabled hardware status page\n");
- /* this probably doesn't belong here - TODO */
- drm_framebuffer_set_object(dev, dev_priv->sarea_priv->front_handle);
drm_set_desired_modes(dev);
return 0;