initial userspace interface to get modes
parent
52f9028c84
commit
5bffbd6e27
|
@ -23,9 +23,9 @@ libdrm_ladir = $(libdir)
|
|||
libdrm_la_LDFLAGS = -version-number 2:3:0 -no-undefined
|
||||
|
||||
AM_CFLAGS = -I$(top_srcdir)/shared-core
|
||||
libdrm_la_SOURCES = xf86drm.c xf86drmHash.c xf86drmRandom.c xf86drmSL.c
|
||||
libdrm_la_SOURCES = xf86drm.c xf86drmHash.c xf86drmRandom.c xf86drmSL.c xf86drmMode.c
|
||||
|
||||
libdrmincludedir = ${includedir}
|
||||
libdrminclude_HEADERS = xf86drm.h xf86mm.h
|
||||
libdrminclude_HEADERS = xf86drm.h xf86mm.h xf86drmMode.h
|
||||
|
||||
EXTRA_DIST = ChangeLog TODO
|
||||
|
|
|
@ -154,7 +154,7 @@ bool drm_crtc_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode,
|
|||
bool ret = false;
|
||||
struct drm_output *output;
|
||||
|
||||
adjusted_mode = drm_mode_duplicate(mode);
|
||||
adjusted_mode = drm_mode_duplicate(dev, mode);
|
||||
|
||||
crtc->enabled = drm_crtc_in_use(crtc);
|
||||
|
||||
|
@ -230,6 +230,7 @@ bool drm_crtc_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode,
|
|||
}
|
||||
|
||||
/* XXX free adjustedmode */
|
||||
drm_crtc_mode_destroy(dev, adjusted_mode);
|
||||
ret = TRUE;
|
||||
/* TODO */
|
||||
// if (scrn->pScreen)
|
||||
|
@ -401,12 +402,48 @@ bool drm_output_rename(struct drm_output *output, const char *name)
|
|||
}
|
||||
EXPORT_SYMBOL(drm_output_rename);
|
||||
|
||||
struct drm_display_mode *drm_crtc_mode_create(struct drm_device *dev)
|
||||
{
|
||||
int ret;
|
||||
struct drm_display_mode *nmode;
|
||||
|
||||
nmode = kzalloc(sizeof(struct drm_display_mode), GFP_KERNEL);
|
||||
if (!nmode)
|
||||
return NULL;
|
||||
|
||||
again:
|
||||
if (idr_pre_get(&dev->crtc_config.mode_idr, GFP_KERNEL) == 0) {
|
||||
DRM_ERROR("Ran out memory getting a mode number\n");
|
||||
kfree(nmode);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
spin_lock(&dev->crtc_config.config_lock);
|
||||
|
||||
ret = idr_get_new(&dev->crtc_config.mode_idr, nmode, &nmode->mode_id);
|
||||
if (ret == -EAGAIN) {
|
||||
udelay(1);
|
||||
spin_unlock(&dev->crtc_config.config_lock);
|
||||
goto again;
|
||||
}
|
||||
spin_unlock(&dev->crtc_config.config_lock);
|
||||
return nmode;
|
||||
}
|
||||
|
||||
void drm_crtc_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode)
|
||||
{
|
||||
idr_remove(&dev->crtc_config.mode_idr, mode->mode_id);
|
||||
|
||||
kfree(mode);
|
||||
}
|
||||
|
||||
void drm_crtc_config_init(drm_device_t *dev)
|
||||
{
|
||||
spin_lock_init(&dev->crtc_config.config_lock);
|
||||
INIT_LIST_HEAD(&dev->crtc_config.fb_list);
|
||||
INIT_LIST_HEAD(&dev->crtc_config.crtc_list);
|
||||
INIT_LIST_HEAD(&dev->crtc_config.output_list);
|
||||
idr_init(&dev->crtc_config.mode_idr);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_crtc_config_init);
|
||||
|
||||
|
@ -441,7 +478,7 @@ void drm_framebuffer_set_object(drm_device_t *dev, unsigned long handle)
|
|||
ret = 0;
|
||||
out_err:
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
return ret;
|
||||
return;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_framebuffer_set_object);
|
||||
|
||||
|
@ -538,3 +575,86 @@ void drm_crtc_config_cleanup(drm_device_t *dev)
|
|||
}
|
||||
EXPORT_SYMBOL(drm_crtc_config_cleanup);
|
||||
|
||||
void drm_crtc_convert_to_umode(struct drm_mode_modeinfo *out, struct drm_display_mode *in)
|
||||
{
|
||||
|
||||
out->id = in->mode_id;
|
||||
out->clock = in->clock;
|
||||
out->hdisplay = in->hdisplay;
|
||||
out->hsync_start = in->hsync_start;
|
||||
out->hsync_end = in->hsync_end;
|
||||
out->htotal = in->htotal;
|
||||
out->hskew = in->hskew;
|
||||
out->vdisplay = in->vdisplay;
|
||||
out->vsync_start = in->vsync_start;
|
||||
out->vsync_end = in->vsync_end;
|
||||
out->vtotal = in->vtotal;
|
||||
out->vscan = in->vscan;
|
||||
|
||||
out->flags = in->flags;
|
||||
}
|
||||
|
||||
|
||||
/* IOCTL code from userspace */
|
||||
int drm_mode_getresources(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_card_res __user *argp = (void __user *)arg;
|
||||
struct drm_mode_card_res card_res;
|
||||
struct list_head *lh;
|
||||
struct drm_output *output;
|
||||
struct drm_mode_modeinfo u_mode;
|
||||
struct drm_display_mode *mode;
|
||||
int retcode = 0;
|
||||
int mode_count= 0;
|
||||
|
||||
memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo));
|
||||
list_for_each_entry(output, &dev->crtc_config.output_list,
|
||||
head)
|
||||
{
|
||||
list_for_each(lh, &output->modes)
|
||||
mode_count++;
|
||||
}
|
||||
|
||||
if (copy_from_user(&card_res, argp, sizeof(card_res)))
|
||||
return -EFAULT;
|
||||
|
||||
if (card_res.count_modes >= mode_count) {
|
||||
int copied = 0;
|
||||
list_for_each_entry(output, &dev->crtc_config.output_list,
|
||||
head) {
|
||||
list_for_each_entry(mode, &output->modes, head) {
|
||||
drm_crtc_convert_to_umode(&u_mode, mode);
|
||||
if (copy_to_user(&card_res.modes[copied++], &u_mode, sizeof(struct drm_mode_modeinfo))) {
|
||||
retcode = -EFAULT;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
list_for_each(lh, &dev->crtc_config.crtc_list)
|
||||
card_res.count_crtcs++;
|
||||
|
||||
list_for_each_entry(output, &dev->crtc_config.output_list,
|
||||
head)
|
||||
{
|
||||
list_for_each(lh, &output->modes)
|
||||
card_res.count_modes++;
|
||||
card_res.count_outputs++;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
DRM_DEBUG("Counted %d %d %d\n", card_res.count_crtcs,
|
||||
card_res.count_outputs,
|
||||
card_res.count_modes);
|
||||
|
||||
if (copy_to_user(argp, &card_res, sizeof(card_res)))
|
||||
return -EFAULT;
|
||||
|
||||
return retcode;
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <linux/i2c.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/idr.h>
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
|
||||
|
@ -86,6 +87,7 @@ struct drm_display_mode {
|
|||
/* Header */
|
||||
struct list_head head;
|
||||
char name[DRM_DISPLAY_MODE_LEN];
|
||||
int mode_id;
|
||||
enum drm_mode_status status;
|
||||
int type;
|
||||
|
||||
|
@ -392,6 +394,7 @@ struct drm_crtc_config_funcs {
|
|||
*/
|
||||
struct drm_crtc_config {
|
||||
spinlock_t config_lock;
|
||||
struct idr mode_idr;
|
||||
/* this is limited to one for now */
|
||||
int num_fb;
|
||||
struct list_head fb_list;
|
||||
|
@ -419,10 +422,20 @@ int drm_add_edid_modes(struct drm_output *output,
|
|||
struct i2c_adapter *adapter);
|
||||
void drm_mode_probed_add(struct drm_output *output, struct drm_display_mode *mode);
|
||||
void drm_mode_remove(struct drm_output *output, struct drm_display_mode *mode);
|
||||
extern struct drm_display_mode *drm_mode_duplicate(struct drm_display_mode *mode);
|
||||
extern struct drm_display_mode *drm_mode_duplicate(struct drm_device *dev,
|
||||
struct drm_display_mode *mode);
|
||||
extern void drm_mode_debug_printmodeline(struct drm_device *dev,
|
||||
struct drm_display_mode *mode);
|
||||
extern void drm_crtc_config_init(struct drm_device *dev);
|
||||
extern void drm_crtc_config_cleanup(struct drm_device *dev);
|
||||
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);
|
||||
|
||||
#endif /* __DRM_CRTC_H__ */
|
||||
|
||||
|
|
|
@ -123,6 +123,7 @@ static drm_ioctl_desc_t drm_ioctls[] = {
|
|||
DRM_AUTH },
|
||||
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_UPDATE_DRAW)] = {drm_update_drawable_info, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_MODE_GETRESOURCES)] = {drm_mode_getresources, DRM_ROOT_ONLY},
|
||||
};
|
||||
|
||||
#define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls )
|
||||
|
|
|
@ -212,7 +212,8 @@ bad:
|
|||
*
|
||||
* Punts for now.
|
||||
*/
|
||||
struct drm_display_mode *drm_mode_std(struct std_timing *t)
|
||||
struct drm_display_mode *drm_mode_std(struct drm_device *dev,
|
||||
struct std_timing *t)
|
||||
{
|
||||
// struct fb_videomode mode;
|
||||
|
||||
|
@ -221,7 +222,7 @@ struct drm_display_mode *drm_mode_std(struct std_timing *t)
|
|||
struct drm_display_mode *mode;
|
||||
int hsize = t->hsize * 8 + 248, vsize;
|
||||
|
||||
mode = kzalloc(sizeof(struct drm_display_mode), GFP_KERNEL);
|
||||
mode = drm_crtc_mode_create(dev);
|
||||
if (!mode)
|
||||
return NULL;
|
||||
|
||||
|
@ -239,7 +240,8 @@ struct drm_display_mode *drm_mode_std(struct std_timing *t)
|
|||
return mode;
|
||||
}
|
||||
|
||||
struct drm_display_mode *drm_mode_detailed(struct detailed_timing *timing,
|
||||
struct drm_display_mode *drm_mode_detailed(drm_device_t *dev,
|
||||
struct detailed_timing *timing,
|
||||
bool preferred)
|
||||
{
|
||||
struct drm_display_mode *mode;
|
||||
|
@ -254,7 +256,7 @@ struct drm_display_mode *drm_mode_detailed(struct detailed_timing *timing,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
mode = kzalloc(sizeof(struct drm_display_mode), GFP_KERNEL);
|
||||
mode = drm_crtc_mode_create(dev);
|
||||
if (!mode)
|
||||
return NULL;
|
||||
|
||||
|
@ -357,6 +359,7 @@ static struct drm_display_mode established_modes[] = {
|
|||
*/
|
||||
static int add_established_modes(struct drm_output *output, struct edid *edid)
|
||||
{
|
||||
struct drm_device *dev = output->dev;
|
||||
unsigned long est_bits = edid->established_timings.t1 |
|
||||
(edid->established_timings.t2 << 8) |
|
||||
((edid->established_timings.mfg_rsvd & 0x80) << 9);
|
||||
|
@ -365,7 +368,7 @@ static int add_established_modes(struct drm_output *output, struct edid *edid)
|
|||
for (i = 0; i <= EDID_EST_TIMINGS; i++)
|
||||
if (est_bits & (1<<i)) {
|
||||
drm_mode_probed_add(output,
|
||||
drm_mode_duplicate(&established_modes[i]));
|
||||
drm_mode_duplicate(dev, &established_modes[i]));
|
||||
modes++;
|
||||
}
|
||||
|
||||
|
@ -382,6 +385,7 @@ static int add_established_modes(struct drm_output *output, struct edid *edid)
|
|||
static int add_standard_modes(struct drm_output *output, struct edid *edid)
|
||||
{
|
||||
int i, modes = 0;
|
||||
struct drm_device *dev = output->dev;
|
||||
|
||||
for (i = 0; i < EDID_STD_TIMINGS; i++) {
|
||||
struct std_timing *t = &edid->standard_timings[i];
|
||||
|
@ -391,7 +395,7 @@ static int add_standard_modes(struct drm_output *output, struct edid *edid)
|
|||
continue;
|
||||
|
||||
drm_mode_probed_add(output,
|
||||
drm_mode_std(&edid->standard_timings[i]));
|
||||
drm_mode_std(dev, &edid->standard_timings[i]));
|
||||
modes++;
|
||||
}
|
||||
|
||||
|
@ -409,6 +413,7 @@ static int add_detailed_info(struct drm_output *output, struct edid *edid)
|
|||
{
|
||||
int i, j, modes = 0;
|
||||
bool preferred = 0;
|
||||
struct drm_device *dev = output->dev;
|
||||
|
||||
for (i = 0; i < EDID_DETAILED_TIMINGS; i++) {
|
||||
struct detailed_timing *timing = &edid->detailed_timings[i];
|
||||
|
@ -423,7 +428,7 @@ static int add_detailed_info(struct drm_output *output, struct edid *edid)
|
|||
if (i == 0 && edid->preferred_timing)
|
||||
preferred = 1;
|
||||
drm_mode_probed_add(output,
|
||||
drm_mode_detailed(timing, preferred));
|
||||
drm_mode_detailed(dev, timing, preferred));
|
||||
modes++;
|
||||
continue;
|
||||
}
|
||||
|
@ -446,7 +451,7 @@ static int add_detailed_info(struct drm_output *output, struct edid *edid)
|
|||
struct std_timing *std;
|
||||
|
||||
std = &data->data.timings[j];
|
||||
drm_mode_probed_add(output, drm_mode_std(std));
|
||||
drm_mode_probed_add(output, drm_mode_std(dev, std));
|
||||
modes++;
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -115,15 +115,18 @@ void drm_mode_set_crtcinfo(struct drm_display_mode *p, int adjust_flags)
|
|||
EXPORT_SYMBOL(drm_mode_set_crtcinfo);
|
||||
|
||||
|
||||
struct drm_display_mode *drm_mode_duplicate(struct drm_display_mode *mode)
|
||||
struct drm_display_mode *drm_mode_duplicate(struct drm_device *dev, struct drm_display_mode *mode)
|
||||
{
|
||||
struct drm_display_mode *nmode;
|
||||
int new_id;
|
||||
|
||||
nmode = kzalloc(sizeof(struct drm_display_mode), GFP_KERNEL);
|
||||
nmode = drm_crtc_mode_create(dev);
|
||||
if (!nmode)
|
||||
return NULL;
|
||||
|
||||
new_id = nmode->mode_id;
|
||||
*nmode = *mode;
|
||||
nmode->mode_id = new_id;
|
||||
INIT_LIST_HEAD(&nmode->head);
|
||||
return nmode;
|
||||
}
|
||||
|
|
|
@ -888,6 +888,74 @@ typedef union drm_mm_init_arg{
|
|||
} rep;
|
||||
} drm_mm_init_arg_t;
|
||||
|
||||
/*
|
||||
* Drm mode setting
|
||||
*/
|
||||
|
||||
struct drm_mode_modeinfo {
|
||||
|
||||
unsigned int id;
|
||||
|
||||
unsigned int clock;
|
||||
unsigned short hdisplay, hsync_start, hsync_end, htotal, hskew;
|
||||
unsigned short vdisplay, vsync_start, vsync_end, vtotal, vscan;
|
||||
|
||||
unsigned int flags;
|
||||
// int count_flag;
|
||||
// unsigned int __user *modeFlags;
|
||||
};
|
||||
|
||||
struct drm_mode_card_res {
|
||||
|
||||
unsigned int fb_id;
|
||||
|
||||
int count_crtcs;
|
||||
int count_outputs;
|
||||
int count_modes;
|
||||
struct drm_mode_modeinfo __user *modes;
|
||||
|
||||
};
|
||||
|
||||
struct drm_mode_crtc {
|
||||
unsigned int crtc_id; /**< Id */
|
||||
unsigned int buffer_id; /**< Id of framebuffer */
|
||||
|
||||
int x, y; /**< Position on the frameuffer */
|
||||
unsigned int width, height;
|
||||
unsigned int mode; /**< Current mode used */
|
||||
|
||||
int count_outputs;
|
||||
unsigned int outputs; /**< Outputs that are connected */
|
||||
|
||||
int count_possibles;
|
||||
unsigned int possibles; /**< Outputs that can be connected */
|
||||
|
||||
unsigned int __user *set_outputs; /**< Outputs to be connected */
|
||||
|
||||
int gamma_size;
|
||||
|
||||
};
|
||||
|
||||
struct drm_mode_get_output {
|
||||
|
||||
unsigned int output; /**< Id */
|
||||
unsigned int crtc; /**< Id of crtc */
|
||||
|
||||
unsigned int connection;
|
||||
unsigned int width, height; /**< HxW in millimeters */
|
||||
unsigned int subpixel;
|
||||
|
||||
int count_crtcs;
|
||||
unsigned int crtcs; /**< possible crtc to connect to */
|
||||
|
||||
int count_clones;
|
||||
unsigned int clones; /**< list of clones */
|
||||
|
||||
int count_modes;
|
||||
unsigned int __user *modes; /**< list of modes it supports */
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* \name Ioctls Definitions
|
||||
*/
|
||||
|
@ -959,6 +1027,10 @@ typedef union drm_mm_init_arg{
|
|||
|
||||
#define DRM_IOCTL_UPDATE_DRAW DRM_IOW(0x3f, drm_update_draw_t)
|
||||
|
||||
#define DRM_IOCTL_MODE_GETRESOURCES DRM_IOWR(0xA0, struct drm_mode_card_res)
|
||||
#define DRM_IOCTL_MODE_GETCRTC DRM_IOWR(0xA1, drm_mode_crtc_t)
|
||||
#define DRM_IOCTL_MODE_GETOUTPUT DRM_IOWR(0xA2, drm_mode_get_output_t)
|
||||
|
||||
/*@}*/
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue