Loading drivers/gpu/drm/Makefile +1 −1 Original line number Original line Diff line number Diff line Loading @@ -15,7 +15,7 @@ drm-y := drm_auth.o drm_bufs.o drm_cache.o \ drm-$(CONFIG_COMPAT) += drm_ioc32.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 obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o Loading drivers/gpu/drm/drm_crtc.c +173 −0 Original line number Original line Diff line number Diff line Loading @@ -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_ENUM_NAME_FN(drm_get_tv_subconnector_name, drm_tv_subconnector_enum_list) 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 { struct drm_conn_prop_enum_list { int type; int type; char *name; char *name; Loading Loading @@ -801,6 +810,36 @@ int drm_mode_create_dithering_property(struct drm_device *dev) } } EXPORT_SYMBOL(drm_mode_create_dithering_property); 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 * drm_mode_config_init - initialize DRM mode_configuration structure * @dev: DRM device * @dev: DRM device Loading Loading @@ -1753,6 +1792,71 @@ out: return ret; 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 * drm_fb_release - remove and free the FBs on this file * @filp: file * from the ioctl * @filp: file * from the ioctl Loading Loading @@ -2478,3 +2582,72 @@ out: mutex_unlock(&dev->mode_config.mutex); mutex_unlock(&dev->mode_config.mutex); return ret; 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; } drivers/gpu/drm/drm_crtc_helper.c +1 −1 Original line number Original line Diff line number Diff line Loading @@ -109,7 +109,7 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector, count = (*connector_funcs->get_modes)(connector); count = (*connector_funcs->get_modes)(connector); if (!count) { if (!count) { count = drm_add_modes_noedid(connector, 800, 600); count = drm_add_modes_noedid(connector, 1024, 768); if (!count) if (!count) return 0; return 0; } } Loading drivers/gpu/drm/i915/intel_dp_i2c.c→drivers/gpu/drm/drm_dp_i2c_helper.c +5 −69 Original line number Original line Diff line number Diff line Loading @@ -28,85 +28,21 @@ #include <linux/errno.h> #include <linux/errno.h> #include <linux/sched.h> #include <linux/sched.h> #include <linux/i2c.h> #include <linux/i2c.h> #include "intel_dp.h" #include "drm_dp_helper.h" #include "drmP.h" #include "drmP.h" /* Run a single AUX_CH I2C transaction, writing/reading data as necessary */ /* 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 static int i2c_algo_dp_aux_transaction(struct i2c_adapter *adapter, int mode, i2c_algo_dp_aux_transaction(struct i2c_adapter *adapter, int mode, uint8_t write_byte, uint8_t *read_byte) uint8_t write_byte, uint8_t *read_byte) { { struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; 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; int ret; /* Set up the command byte */ ret = (*algo_data->aux_ch)(adapter, mode, if (mode & MODE_I2C_READ) write_byte, read_byte); 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; 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; } } } /* /* * I2C over AUX CH * I2C over AUX CH Loading drivers/gpu/drm/drm_drv.c +36 −6 Original line number Original line Diff line number Diff line Loading @@ -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_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_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_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 ) #define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls ) Loading Loading @@ -365,6 +367,29 @@ static void __exit drm_core_exit(void) module_init(drm_core_init); module_init(drm_core_init); module_exit(drm_core_exit); 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 * Get version information * * Loading @@ -380,16 +405,21 @@ static int drm_version(struct drm_device *dev, void *data, struct drm_file *file_priv) struct drm_file *file_priv) { { struct drm_version *version = data; struct drm_version *version = data; int len; int err; version->version_major = dev->driver->major; version->version_major = dev->driver->major; version->version_minor = dev->driver->minor; version->version_minor = dev->driver->minor; version->version_patchlevel = dev->driver->patchlevel; version->version_patchlevel = dev->driver->patchlevel; DRM_COPY(version->name, dev->driver->name); err = drm_copy_field(version->name, &version->name_len, DRM_COPY(version->date, dev->driver->date); dev->driver->name); DRM_COPY(version->desc, dev->driver->desc); if (!err) err = drm_copy_field(version->date, &version->date_len, return 0; dev->driver->date); if (!err) err = drm_copy_field(version->desc, &version->desc_len, dev->driver->desc); return err; } } /** /** Loading Loading
drivers/gpu/drm/Makefile +1 −1 Original line number Original line Diff line number Diff line Loading @@ -15,7 +15,7 @@ drm-y := drm_auth.o drm_bufs.o drm_cache.o \ drm-$(CONFIG_COMPAT) += drm_ioc32.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 obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o Loading
drivers/gpu/drm/drm_crtc.c +173 −0 Original line number Original line Diff line number Diff line Loading @@ -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_ENUM_NAME_FN(drm_get_tv_subconnector_name, drm_tv_subconnector_enum_list) 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 { struct drm_conn_prop_enum_list { int type; int type; char *name; char *name; Loading Loading @@ -801,6 +810,36 @@ int drm_mode_create_dithering_property(struct drm_device *dev) } } EXPORT_SYMBOL(drm_mode_create_dithering_property); 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 * drm_mode_config_init - initialize DRM mode_configuration structure * @dev: DRM device * @dev: DRM device Loading Loading @@ -1753,6 +1792,71 @@ out: return ret; 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 * drm_fb_release - remove and free the FBs on this file * @filp: file * from the ioctl * @filp: file * from the ioctl Loading Loading @@ -2478,3 +2582,72 @@ out: mutex_unlock(&dev->mode_config.mutex); mutex_unlock(&dev->mode_config.mutex); return ret; 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; }
drivers/gpu/drm/drm_crtc_helper.c +1 −1 Original line number Original line Diff line number Diff line Loading @@ -109,7 +109,7 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector, count = (*connector_funcs->get_modes)(connector); count = (*connector_funcs->get_modes)(connector); if (!count) { if (!count) { count = drm_add_modes_noedid(connector, 800, 600); count = drm_add_modes_noedid(connector, 1024, 768); if (!count) if (!count) return 0; return 0; } } Loading
drivers/gpu/drm/i915/intel_dp_i2c.c→drivers/gpu/drm/drm_dp_i2c_helper.c +5 −69 Original line number Original line Diff line number Diff line Loading @@ -28,85 +28,21 @@ #include <linux/errno.h> #include <linux/errno.h> #include <linux/sched.h> #include <linux/sched.h> #include <linux/i2c.h> #include <linux/i2c.h> #include "intel_dp.h" #include "drm_dp_helper.h" #include "drmP.h" #include "drmP.h" /* Run a single AUX_CH I2C transaction, writing/reading data as necessary */ /* 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 static int i2c_algo_dp_aux_transaction(struct i2c_adapter *adapter, int mode, i2c_algo_dp_aux_transaction(struct i2c_adapter *adapter, int mode, uint8_t write_byte, uint8_t *read_byte) uint8_t write_byte, uint8_t *read_byte) { { struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; 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; int ret; /* Set up the command byte */ ret = (*algo_data->aux_ch)(adapter, mode, if (mode & MODE_I2C_READ) write_byte, read_byte); 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; 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; } } } /* /* * I2C over AUX CH * I2C over AUX CH Loading
drivers/gpu/drm/drm_drv.c +36 −6 Original line number Original line Diff line number Diff line Loading @@ -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_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_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_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 ) #define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls ) Loading Loading @@ -365,6 +367,29 @@ static void __exit drm_core_exit(void) module_init(drm_core_init); module_init(drm_core_init); module_exit(drm_core_exit); 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 * Get version information * * Loading @@ -380,16 +405,21 @@ static int drm_version(struct drm_device *dev, void *data, struct drm_file *file_priv) struct drm_file *file_priv) { { struct drm_version *version = data; struct drm_version *version = data; int len; int err; version->version_major = dev->driver->major; version->version_major = dev->driver->major; version->version_minor = dev->driver->minor; version->version_minor = dev->driver->minor; version->version_patchlevel = dev->driver->patchlevel; version->version_patchlevel = dev->driver->patchlevel; DRM_COPY(version->name, dev->driver->name); err = drm_copy_field(version->name, &version->name_len, DRM_COPY(version->date, dev->driver->date); dev->driver->name); DRM_COPY(version->desc, dev->driver->desc); if (!err) err = drm_copy_field(version->date, &version->date_len, return 0; dev->driver->date); if (!err) err = drm_copy_field(version->desc, &version->desc_len, dev->driver->desc); return err; } } /** /** Loading