mirror of
https://gitlab.freedesktop.org/mesa/drm.git
synced 2026-05-09 07:28:42 +02:00
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:
parent
eb9bdc2787
commit
65f465ed5a
6 changed files with 83 additions and 46 deletions
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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__ */
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue