fixup numerous issues with adding framebuffer support

This still isn't perfect but it fixes a few oopses and cleans up
some of the tabs and bugs in the original fb limit code
This commit is contained in:
David Airlie 2007-04-10 14:49:49 +10:00
parent eb9bdc2787
commit 65f465ed5a
6 changed files with 83 additions and 46 deletions

View file

@ -311,11 +311,9 @@ err_allocs:
}
int drmModeSetCrtc(
int fd, uint32_t crtcId, uint32_t bufferId,
uint32_t x, uint32_t y, uint32_t modeId,
uint32_t *outputs, int count
)
int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId,
uint32_t x, uint32_t y, uint32_t modeId,
uint32_t *outputs, int count)
{
struct drm_mode_crtc crtc;

View file

@ -214,14 +214,12 @@ extern drmModeFrameBufferPtr drmModeGetFramebuffer(int fd,
/**
* Creates a new framebuffer with an buffer object as its scanout buffer.
*/
extern uint32_t drmModeNewFrameBuffer(int fd,
uint32_t width, uint32_t height,
uint8_t bbp, uint32_t pitch, drmBO *bo);
extern int drmModeAddFB(int fd, uint32_t width, uint32_t height,
uint8_t bpp, uint32_t pitch, drmBO *bo, uint32_t *buf_id);
/**
* Destroies the given framebuffer.
*/
extern int drmModeDesFrameBuffer(int fd, uint32_t bufferId);
extern int drmModeRmFB(int fd, uint32_t bufferId);
/**
* Changes the scanout buffer to the given buffer object.

View file

@ -371,7 +371,7 @@ struct drm_output *drm_output_create(drm_device_t *dev,
{
struct drm_output *output = NULL;
output = kmalloc(sizeof(struct drm_output), GFP_KERNEL);
output = kzalloc(sizeof(struct drm_output), GFP_KERNEL);
if (!output)
return NULL;
@ -471,13 +471,13 @@ static int drm_get_buffer_object(drm_device_t *dev, struct drm_buffer_object **b
drm_hash_item_t *hash;
int ret;
*bo = NULL;
*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;
ret = -EINVAL;
goto out_err;
}
@ -486,7 +486,7 @@ static int drm_get_buffer_object(drm_device_t *dev, struct drm_buffer_object **b
ret = -EINVAL;
goto out_err;
}
*bo = drm_user_object_entry(uo, drm_buffer_object_t, base);
ret = 0;
out_err:
@ -517,7 +517,7 @@ bool drm_initial_config(drm_device_t *dev, bool can_grow)
/* bind both CRTCs to this fb */
/* only initialise one crtc to enabled state */
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
crtc->fb = fb;
// crtc->fb = fb;
if (!vga_crtc) {
vga_crtc = crtc;
crtc->enabled = 1;
@ -699,15 +699,14 @@ int drm_mode_getresources(struct inode *inode, struct file *filp,
int output_count = 0;
int crtc_count = 0;
int copied = 0;
memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo));
list_for_each(lh, &dev->mode_config.crtc_list)
crtc_count++;
list_for_each_entry(output, &dev->mode_config.output_list,
head)
{
head) {
output_count++;
list_for_each(lh, &output->modes)
mode_count++;
@ -716,6 +715,16 @@ int drm_mode_getresources(struct inode *inode, struct file *filp,
if (copy_from_user(&card_res, argp, sizeof(card_res)))
return -EFAULT;
if (card_res.count_modes == 0) {
DRM_DEBUG("probing modes %dx%d\n", dev->mode_config.max_width, dev->mode_config.max_height);
drm_crtc_probe_output_modes(dev, dev->mode_config.max_width, dev->mode_config.max_height);
mode_count = 0;
list_for_each_entry(output, &dev->mode_config.output_list, head) {
list_for_each(lh, &output->modes)
mode_count++;
}
}
/* handle this in 3 parts */
/* CRTCs */
if (card_res.count_crtcs >= crtc_count) {
@ -829,13 +838,16 @@ int drm_mode_getoutput(struct inode *inode, struct file *filp,
if (copy_from_user(&out_resp, argp, sizeof(out_resp)))
return -EFAULT;
DRM_DEBUG("output id %d\n", out_resp.output);
output= idr_find(&dev->mode_config.crtc_idr, out_resp.output);
if (!output || (output->id != out_resp.output))
return -EINVAL;
DRM_DEBUG("about to count modes\n");
list_for_each_entry(mode, &output->modes, head)
mode_count++;
DRM_DEBUG("about to count modes %d %d %p\n", mode_count, out_resp.count_modes, output->crtc);
out_resp.mm_width = output->mm_width;
out_resp.mm_height = output->mm_height;
out_resp.subpixel = output->subpixel_order;
@ -845,7 +857,7 @@ int drm_mode_getoutput(struct inode *inode, struct file *filp,
else
out_resp.crtc = 0;
if (out_resp.count_modes >= mode_count) {
if ((out_resp.count_modes >= mode_count) && mode_count) {
copied = 0;
list_for_each_entry(mode, &output->modes, head) {
if (put_user(mode->mode_id, &out_resp.modes[copied++])) {
@ -882,20 +894,40 @@ int drm_mode_setcrtc(struct inode *inode, struct file *filp,
crtc = idr_find(&dev->mode_config.crtc_idr, crtc_req.crtc_id);
if (!crtc || (crtc->id != crtc_req.crtc_id))
{
DRM_DEBUG("Unknown CRTC ID %d\n", crtc_req.crtc_id);
return -EINVAL;
}
if (crtc_req.mode) {
mode = idr_find(&dev->mode_config.crtc_idr, crtc_req.mode);
if (!mode || (mode->mode_id != crtc_req.mode))
{
{
struct drm_output *output;
list_for_each_entry(output, &dev->mode_config.output_list, head) {
list_for_each_entry(mode, &output->modes, head) {
drm_mode_debug_printmodeline(dev, mode);
}
}
}
DRM_DEBUG("Unknown mode id %d, %p\n", crtc_req.mode, mode);
return -EINVAL;
}
} else
mode = NULL;
if (crtc_req.count_outputs == 0 && mode)
if (crtc_req.count_outputs == 0 && mode) {
DRM_DEBUG("Count outputs is 0 but mode set\n");
return -EINVAL;
}
if (crtc_req.count_outputs > 0 && !mode)
if (crtc_req.count_outputs > 0 && !mode) {
DRM_DEBUG("Count outputs is %d but no mode set\n", crtc_req.count_outputs);
return -EINVAL;
}
if (crtc_req.count_outputs > 0) {
u32 out_id;
@ -903,14 +935,15 @@ int drm_mode_setcrtc(struct inode *inode, struct file *filp,
if (!output_set)
return -ENOMEM;
for (i = 0; i < crtc_req.count_outputs; i++)
{
for (i = 0; i < crtc_req.count_outputs; i++) {
if (get_user(out_id, &crtc_req.set_outputs[i]))
return -EFAULT;
output = idr_find(&dev->mode_config.crtc_idr, out_id);
if (!output || (out_id != output->id))
if (!output || (out_id != output->id)) {
DRM_DEBUG("Output id %d unknown\n", out_id);
return -EINVAL;
}
output_set[i] = output;
}
@ -922,16 +955,16 @@ int drm_mode_setcrtc(struct inode *inode, struct file *filp,
/* Add framebuffer ioctl */
int drm_mode_addfb(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
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_mode_config *config = &dev->mode_config;
struct drm_mode_config *config = &dev->mode_config;
struct drm_framebuffer *fb;
struct drm_buffer_object *bo;
int ret;
int ret;
if (copy_from_user(&r, argp, sizeof(r)))
return -EFAULT;
@ -939,16 +972,16 @@ int drm_mode_addfb(struct inode *inode, struct file *filp,
if ((config->min_width > r.width) || (r.width > config->max_width)) {
DRM_ERROR("mode new framebuffer width not within limits\n");
return -EINVAL;
}
}
if ((config->min_height > r.height) || (r.height > config->max_height)) {
DRM_ERROR("mode new framebuffer height not within limits\n");
return -EINVAL;
}
/* TODO check limits are okay */
ret = drm_get_buffer_object(dev, &bo, r.handle);
if (ret || !bo)
return -EINVAL;
ret = drm_get_buffer_object(dev, &bo, r.handle);
if (ret || !bo)
return -EINVAL;
/* TODO check buffer is sufficently large */
/* TODO setup destructor callback */
@ -957,22 +990,30 @@ int drm_mode_addfb(struct inode *inode, struct file *filp,
if(!fb)
return -EINVAL;;
fb->width = r.width;
fb->height = r.height;
fb->pitch = r.pitch;
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;
fb->offset = bo->offset;
fb->bo = bo;
r.buffer_id = fb->id;
if (copy_to_user(argp, &r, sizeof(r)))
return -EFAULT;
r.buffer_id = fb->id;
/* bind the fb to the crtc for now */
{
struct drm_crtc *crtc;
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
crtc->fb = fb;
}
}
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)
unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;

View file

@ -178,7 +178,7 @@ struct drm_framebuffer {
unsigned int depth;
int bits_per_pixel;
int flags;
struct drm_buffer_object *bo;
struct drm_buffer_object *bo;
};
struct drm_crtc;
struct drm_output;
@ -456,8 +456,8 @@ extern int drm_mode_getoutput(struct inode *inode, struct file *filp,
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);
unsigned int cmd, unsigned long arg);
extern int drm_mode_rmfb(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
unsigned int cmd, unsigned long arg);
#endif /* __DRM_CRTC_H__ */

View file

@ -36,8 +36,8 @@
void drm_mode_debug_printmodeline(struct drm_device *dev,
struct drm_display_mode *mode)
{
DRM_DEBUG("Modeline \"%s\" %d %d %d %d %d %d %d %d %d %d\n",
mode->name, mode->vrefresh / 1000, mode->clock,
DRM_DEBUG("Modeline %d:\"%s\" %d %d %d %d %d %d %d %d %d %d\n",
mode->mode_id, mode->name, mode->vrefresh / 1000, mode->clock,
mode->hdisplay, mode->hsync_start,
mode->hsync_end, mode->htotal,
mode->vdisplay, mode->vsync_start,

View file

@ -171,7 +171,7 @@ static int i915_initialize(drm_device_t * dev,
I915_WRITE(0x02080, dev_priv->dma_status_page);
DRM_DEBUG("Enabled hardware status page\n");
drm_set_desired_modes(dev);
//drm_set_desired_modes(dev);
return 0;
}