Skip to content

Commit

Permalink
Merge branch 'drm-core-next' into drm-linus
Browse files Browse the repository at this point in the history
Bring all core drm changes into 2.6.32 tree and resolve
the conflict that occurs.

Conflicts:
	drivers/gpu/drm/drm_fb_helper.c
  • Loading branch information
Dave Airlie committed Dec 8, 2009
2 parents 22763c5 + b0a007d commit 1bd049f
Show file tree
Hide file tree
Showing 39 changed files with 2,509 additions and 289 deletions.
2 changes: 1 addition & 1 deletion drivers/gpu/drm/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ drm-y := drm_auth.o drm_bufs.o drm_cache.o \

drm-$(CONFIG_COMPAT) += drm_ioc32.o

drm_kms_helper-y := drm_fb_helper.o drm_crtc_helper.o
drm_kms_helper-y := drm_fb_helper.o drm_crtc_helper.o drm_dp_i2c_helper.o

obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o

Expand Down
173 changes: 173 additions & 0 deletions drivers/gpu/drm/drm_crtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,15 @@ static struct drm_prop_enum_list drm_tv_subconnector_enum_list[] =
DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name,
drm_tv_subconnector_enum_list)

static struct drm_prop_enum_list drm_dirty_info_enum_list[] = {
{ DRM_MODE_DIRTY_OFF, "Off" },
{ DRM_MODE_DIRTY_ON, "On" },
{ DRM_MODE_DIRTY_ANNOTATE, "Annotate" },
};

DRM_ENUM_NAME_FN(drm_get_dirty_info_name,
drm_dirty_info_enum_list)

struct drm_conn_prop_enum_list {
int type;
char *name;
Expand Down Expand Up @@ -801,6 +810,36 @@ int drm_mode_create_dithering_property(struct drm_device *dev)
}
EXPORT_SYMBOL(drm_mode_create_dithering_property);

/**
* drm_mode_create_dirty_property - create dirty property
* @dev: DRM device
*
* Called by a driver the first time it's needed, must be attached to desired
* connectors.
*/
int drm_mode_create_dirty_info_property(struct drm_device *dev)
{
struct drm_property *dirty_info;
int i;

if (dev->mode_config.dirty_info_property)
return 0;

dirty_info =
drm_property_create(dev, DRM_MODE_PROP_ENUM |
DRM_MODE_PROP_IMMUTABLE,
"dirty",
ARRAY_SIZE(drm_dirty_info_enum_list));
for (i = 0; i < ARRAY_SIZE(drm_dirty_info_enum_list); i++)
drm_property_add_enum(dirty_info, i,
drm_dirty_info_enum_list[i].type,
drm_dirty_info_enum_list[i].name);
dev->mode_config.dirty_info_property = dirty_info;

return 0;
}
EXPORT_SYMBOL(drm_mode_create_dirty_info_property);

/**
* drm_mode_config_init - initialize DRM mode_configuration structure
* @dev: DRM device
Expand Down Expand Up @@ -1753,6 +1792,71 @@ int drm_mode_getfb(struct drm_device *dev,
return ret;
}

int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv)
{
struct drm_clip_rect __user *clips_ptr;
struct drm_clip_rect *clips = NULL;
struct drm_mode_fb_dirty_cmd *r = data;
struct drm_mode_object *obj;
struct drm_framebuffer *fb;
unsigned flags;
int num_clips;
int ret = 0;

mutex_lock(&dev->mode_config.mutex);
obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB);
if (!obj) {
DRM_ERROR("invalid framebuffer id\n");
ret = -EINVAL;
goto out_err1;
}
fb = obj_to_fb(obj);

num_clips = r->num_clips;
clips_ptr = (struct drm_clip_rect *)(unsigned long)r->clips_ptr;

if (!num_clips != !clips_ptr) {
ret = -EINVAL;
goto out_err1;
}

flags = DRM_MODE_FB_DIRTY_FLAGS & r->flags;

/* If userspace annotates copy, clips must come in pairs */
if (flags & DRM_MODE_FB_DIRTY_ANNOTATE_COPY && (num_clips % 2)) {
ret = -EINVAL;
goto out_err1;
}

if (num_clips && clips_ptr) {
clips = kzalloc(num_clips * sizeof(*clips), GFP_KERNEL);
if (!clips) {
ret = -ENOMEM;
goto out_err1;
}

ret = copy_from_user(clips, clips_ptr,
num_clips * sizeof(*clips));
if (ret)
goto out_err2;
}

if (fb->funcs->dirty) {
ret = fb->funcs->dirty(fb, flags, r->color, clips, num_clips);
} else {
ret = -ENOSYS;
goto out_err2;
}

out_err2:
kfree(clips);
out_err1:
mutex_unlock(&dev->mode_config.mutex);
return ret;
}


/**
* drm_fb_release - remove and free the FBs on this file
* @filp: file * from the ioctl
Expand Down Expand Up @@ -2478,3 +2582,72 @@ int drm_mode_gamma_get_ioctl(struct drm_device *dev,
mutex_unlock(&dev->mode_config.mutex);
return ret;
}

int drm_mode_page_flip_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv)
{
struct drm_mode_crtc_page_flip *page_flip = data;
struct drm_mode_object *obj;
struct drm_crtc *crtc;
struct drm_framebuffer *fb;
struct drm_pending_vblank_event *e = NULL;
unsigned long flags;
int ret = -EINVAL;

if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS ||
page_flip->reserved != 0)
return -EINVAL;

mutex_lock(&dev->mode_config.mutex);
obj = drm_mode_object_find(dev, page_flip->crtc_id, DRM_MODE_OBJECT_CRTC);
if (!obj)
goto out;
crtc = obj_to_crtc(obj);

if (crtc->funcs->page_flip == NULL)
goto out;

obj = drm_mode_object_find(dev, page_flip->fb_id, DRM_MODE_OBJECT_FB);
if (!obj)
goto out;
fb = obj_to_fb(obj);

if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) {
ret = -ENOMEM;
spin_lock_irqsave(&dev->event_lock, flags);
if (file_priv->event_space < sizeof e->event) {
spin_unlock_irqrestore(&dev->event_lock, flags);
goto out;
}
file_priv->event_space -= sizeof e->event;
spin_unlock_irqrestore(&dev->event_lock, flags);

e = kzalloc(sizeof *e, GFP_KERNEL);
if (e == NULL) {
spin_lock_irqsave(&dev->event_lock, flags);
file_priv->event_space += sizeof e->event;
spin_unlock_irqrestore(&dev->event_lock, flags);
goto out;
}

e->event.base.type = DRM_EVENT_VBLANK;
e->event.base.length = sizeof e->event;
e->event.user_data = page_flip->user_data;
e->base.event = &e->event.base;
e->base.file_priv = file_priv;
e->base.destroy =
(void (*) (struct drm_pending_event *)) kfree;
}

ret = crtc->funcs->page_flip(crtc, fb, e);
if (ret) {
spin_lock_irqsave(&dev->event_lock, flags);
file_priv->event_space += sizeof e->event;
spin_unlock_irqrestore(&dev->event_lock, flags);
kfree(e);
}

out:
mutex_unlock(&dev->mode_config.mutex);
return ret;
}
2 changes: 1 addition & 1 deletion drivers/gpu/drm/drm_crtc_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,

count = (*connector_funcs->get_modes)(connector);
if (!count) {
count = drm_add_modes_noedid(connector, 800, 600);
count = drm_add_modes_noedid(connector, 1024, 768);
if (!count)
return 0;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,84 +28,20 @@
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/i2c.h>
#include "intel_dp.h"
#include "drm_dp_helper.h"
#include "drmP.h"

/* Run a single AUX_CH I2C transaction, writing/reading data as necessary */

#define MODE_I2C_START 1
#define MODE_I2C_WRITE 2
#define MODE_I2C_READ 4
#define MODE_I2C_STOP 8

static int
i2c_algo_dp_aux_transaction(struct i2c_adapter *adapter, int mode,
uint8_t write_byte, uint8_t *read_byte)
{
struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
uint16_t address = algo_data->address;
uint8_t msg[5];
uint8_t reply[2];
int msg_bytes;
int reply_bytes;
int ret;

/* Set up the command byte */
if (mode & MODE_I2C_READ)
msg[0] = AUX_I2C_READ << 4;
else
msg[0] = AUX_I2C_WRITE << 4;

if (!(mode & MODE_I2C_STOP))
msg[0] |= AUX_I2C_MOT << 4;

msg[1] = address >> 8;
msg[2] = address;

switch (mode) {
case MODE_I2C_WRITE:
msg[3] = 0;
msg[4] = write_byte;
msg_bytes = 5;
reply_bytes = 1;
break;
case MODE_I2C_READ:
msg[3] = 0;
msg_bytes = 4;
reply_bytes = 2;
break;
default:
msg_bytes = 3;
reply_bytes = 1;
break;
}

for (;;) {
ret = (*algo_data->aux_ch)(adapter,
msg, msg_bytes,
reply, reply_bytes);
if (ret < 0) {
DRM_DEBUG("aux_ch failed %d\n", ret);
return ret;
}
switch (reply[0] & AUX_I2C_REPLY_MASK) {
case AUX_I2C_REPLY_ACK:
if (mode == MODE_I2C_READ) {
*read_byte = reply[1];
}
return reply_bytes - 1;
case AUX_I2C_REPLY_NACK:
DRM_DEBUG("aux_ch nack\n");
return -EREMOTEIO;
case AUX_I2C_REPLY_DEFER:
DRM_DEBUG("aux_ch defer\n");
udelay(100);
break;
default:
DRM_ERROR("aux_ch invalid reply 0x%02x\n", reply[0]);
return -EREMOTEIO;
}
}

ret = (*algo_data->aux_ch)(adapter, mode,
write_byte, read_byte);
return ret;
}

/*
Expand Down
42 changes: 36 additions & 6 deletions drivers/gpu/drm/drm_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ static struct drm_ioctl_desc drm_ioctls[] = {
DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_MASTER|DRM_CONTROL_ALLOW),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_MASTER|DRM_CONTROL_ALLOW),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_MASTER|DRM_CONTROL_ALLOW),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW)
};

#define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls )
Expand Down Expand Up @@ -365,6 +367,29 @@ static void __exit drm_core_exit(void)
module_init(drm_core_init);
module_exit(drm_core_exit);

/**
* Copy and IOCTL return string to user space
*/
static int drm_copy_field(char *buf, size_t *buf_len, const char *value)
{
int len;

/* don't overflow userbuf */
len = strlen(value);
if (len > *buf_len)
len = *buf_len;

/* let userspace know exact length of driver value (which could be
* larger than the userspace-supplied buffer) */
*buf_len = strlen(value);

/* finally, try filling in the userbuf */
if (len && buf)
if (copy_to_user(buf, value, len))
return -EFAULT;
return 0;
}

/**
* Get version information
*
Expand All @@ -380,16 +405,21 @@ static int drm_version(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct drm_version *version = data;
int len;
int err;

version->version_major = dev->driver->major;
version->version_minor = dev->driver->minor;
version->version_patchlevel = dev->driver->patchlevel;
DRM_COPY(version->name, dev->driver->name);
DRM_COPY(version->date, dev->driver->date);
DRM_COPY(version->desc, dev->driver->desc);

return 0;
err = drm_copy_field(version->name, &version->name_len,
dev->driver->name);
if (!err)
err = drm_copy_field(version->date, &version->date_len,
dev->driver->date);
if (!err)
err = drm_copy_field(version->desc, &version->desc_len,
dev->driver->desc);

return err;
}

/**
Expand Down
Loading

0 comments on commit 1bd049f

Please sign in to comment.