checkpoint commit: implement SetCrtc so modes can in theory be set from user

This hooks up the userspace mode set it "seems" to work.
main
Dave Airlie 2007-04-05 18:01:02 +10:00
parent 7bb112feca
commit b4094864f1
5 changed files with 133 additions and 11 deletions

View File

@ -286,7 +286,7 @@ err_allocs:
return 0;
}
#if 0
int drmModeSetCrtc(
int fd, uint32_t crtcId, uint32_t bufferId,
uint32_t x, uint32_t y, uint32_t modeId,
@ -302,15 +302,16 @@ int drmModeSetCrtc(
crtc.x = x;
crtc.y = y;
crtc.crtcId = crtcId;
crtc.bufferId = bufferId;
crtc.crtc_id = crtcId;
crtc.fb_id = bufferId;
crtc.set_outputs = outputs;
crtc.count_outputs = count;
crtc.mode = modeId;
// return ioctl(fd, DRM_IOCTL_MODE_SETCRTC, &crtc);
return ioctl(fd, DRM_IOCTL_MODE_SETCRTC, &crtc);
}
#if 0
drmModeGammaTriplePtr drmModeGetCrtcGamma(int fd, uint32_t crtc, int *count)
{
/* TODO impl */

View File

@ -302,10 +302,10 @@ bool drm_set_desired_modes(struct drm_device *dev)
continue;
memset(&crtc->mode, 0, sizeof(crtc->mode));
if (!crtc->desired_mode.crtc_hdisplay) {
if (!crtc->desired_mode->crtc_hdisplay) {
}
if (!drm_crtc_set_mode(crtc, &crtc->desired_mode,
if (!drm_crtc_set_mode(crtc, crtc->desired_mode,
crtc->desired_x, crtc->desired_y))
return false;
}
@ -556,7 +556,7 @@ bool drm_initial_config(drm_device_t *dev, bool can_grow)
break;
DRM_DEBUG("Setting desired mode for output %s\n", output->name);
drm_mode_debug_printmodeline(dev, des_mode);
output->crtc->desired_mode = *des_mode;
output->crtc->desired_mode = des_mode;
output->initial_x = 0;
output->initial_y = 0;
use_output = output;
@ -568,7 +568,7 @@ bool drm_initial_config(drm_device_t *dev, bool can_grow)
break;
DRM_DEBUG("Setting desired mode for output %s\n", output->name);
drm_mode_debug_printmodeline(dev, des_mode);
output->crtc->desired_mode = *des_mode;
output->crtc->desired_mode = des_mode;
#endif
output->initial_x = 0;
output->initial_y = 0;
@ -596,6 +596,68 @@ void drm_crtc_config_cleanup(drm_device_t *dev)
}
EXPORT_SYMBOL(drm_crtc_config_cleanup);
int drm_crtc_set_config(struct drm_crtc *crtc, struct drm_mode_crtc *crtc_info, struct drm_display_mode *new_mode, struct drm_output **output_set)
{
drm_device_t *dev = crtc->dev;
struct drm_crtc **save_crtcs, *new_crtc;
bool save_enabled = crtc->enabled;
bool changed;
struct drm_output *output;
int count = 0, ro;
save_crtcs = kzalloc(dev->crtc_config.num_crtc * sizeof(struct drm_crtc *), GFP_KERNEL);
if (!save_crtcs)
return -ENOMEM;
if (crtc_info->x != crtc->x || crtc_info->y != crtc->y)
changed = true;
if (crtc->mode.mode_id != new_mode->mode_id)
changed = true;
list_for_each_entry(output, &dev->crtc_config.output_list, head) {
save_crtcs[count++] = output->crtc;
if (output->crtc == crtc)
new_crtc = NULL;
else
new_crtc = output->crtc;
for (ro = 0; ro < crtc_info->count_outputs; ro++)
{
if (output_set[ro] == output)
new_crtc = crtc;
}
if (new_crtc != output->crtc) {
changed = true;
output->crtc = new_crtc;
}
}
if (changed) {
crtc->enabled = new_mode != NULL;
if (new_mode) {
DRM_DEBUG("attempting to set mode from userspace\n");
drm_mode_debug_printmodeline(dev, new_mode);
if (!drm_crtc_set_mode(crtc, new_mode, crtc_info->x,
crtc_info->y)) {
crtc->enabled = save_enabled;
count = 0;
list_for_each_entry(output, &dev->crtc_config.output_list, head)
output->crtc = save_crtcs[count++];
kfree(save_crtcs);
return -EINVAL;
}
crtc->desired_x = crtc_info->x;
crtc->desired_y = crtc_info->y;
crtc->desired_mode = new_mode;
}
drm_disable_unused_functions(dev);
}
kfree(save_crtcs);
return 0;
}
void drm_crtc_convert_to_umode(struct drm_mode_modeinfo *out, struct drm_display_mode *in)
{
@ -757,7 +819,6 @@ int drm_mode_getoutput(struct inode *inode, struct file *filp,
drm_device_t *dev = priv->head->dev;
struct drm_mode_get_output __user *argp = (void __user *)arg;
struct drm_mode_get_output out_resp;
struct drm_crtc *crtc;
struct drm_output *output;
struct drm_display_mode *mode;
int mode_count = 0;
@ -800,3 +861,60 @@ done:
return retcode;
}
int drm_mode_setcrtc(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_mode_crtc __user *argp = (void __user *)arg;
struct drm_mode_crtc crtc_req;
struct drm_crtc *crtc;
struct drm_output **output_set = NULL, *output;
struct drm_display_mode *mode;
int retcode = 0;
int i;
if (copy_from_user(&crtc_req, argp, sizeof(crtc_req)))
return -EFAULT;
crtc = idr_find(&dev->crtc_config.crtc_idr, crtc_req.crtc_id);
if (!crtc || (crtc->id != crtc_req.crtc_id))
return -EINVAL;
if (crtc_req.mode) {
mode = idr_find(&dev->crtc_config.crtc_idr, crtc_req.mode);
if (!mode || (mode->mode_id != crtc_req.mode))
return -EINVAL;
} else
mode = NULL;
if (crtc_req.count_outputs == 0 && mode)
return -EINVAL;
if (crtc_req.count_outputs > 0 && !mode)
return -EINVAL;
if (crtc_req.count_outputs > 0) {
u32 out_id;
output_set = kmalloc(crtc_req.count_outputs * sizeof(struct drm_output *), GFP_KERNEL);
if (!output_set)
return -ENOMEM;
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->crtc_config.crtc_idr, out_id);
if (!output || (out_id != output->id))
return -EINVAL;
output_set[i] = output;
}
}
retcode = drm_crtc_set_config(crtc, &crtc_req, mode, output_set);
return retcode;
}

View File

@ -272,7 +272,7 @@ struct drm_crtc {
struct drm_display_mode mode;
int x, y;
struct drm_display_mode desired_mode;
struct drm_display_mode *desired_mode;
int desired_x, desired_y;
const struct drm_crtc_funcs *funcs;
void *driver_private;
@ -443,5 +443,7 @@ 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);
#endif /* __DRM_CRTC_H__ */

View File

@ -126,6 +126,7 @@ static drm_ioctl_desc_t drm_ioctls[] = {
[DRM_IOCTL_NR(DRM_IOCTL_MODE_GETRESOURCES)] = {drm_mode_getresources, DRM_MASTER|DRM_ROOT_ONLY},
[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},
};
#define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls )

View File

@ -1036,7 +1036,7 @@ struct drm_mode_get_output {
#define DRM_IOCTL_MODE_GETRESOURCES DRM_IOWR(0xA0, struct drm_mode_card_res)
#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)
/*@}*/
/**