Author: kib
Date: Mon Mar 23 13:38:33 2015
New Revision: 280369
URL: https://svnweb.freebsd.org/changeset/base/280369

Log:
  MFC r277487:
  An update for the i915 GPU driver, which brings the code up to Linux
  commit 4d93914ae3db4a897ead4b.
  
  MFC r277959 (by adrian):
  Fix backlight for ivybridge based laptops (and whatever else comes through
  this codepath.)
  
  MFC r278146:
  Do not attach to the unsupported chipsets, unless magic tunable is
  frobbed.
  
  MFC r278147, r278148:
  Fix sign for the error code returned from the driver-specific code.
  
  MFC r278152:
  Do not access gmbus_ports array past its end.
  
  MFC r278159 (by emaste):
  Remove duplicate intel_fbc_enabled prototype.

Added:
  stable/10/sys/dev/drm2/i915/i915_gem_stolen.c
     - copied unchanged from r277487, head/sys/dev/drm2/i915/i915_gem_stolen.c
  stable/10/sys/dev/drm2/i915/intel_ddi.c
     - copied unchanged from r277487, head/sys/dev/drm2/i915/intel_ddi.c
  stable/10/sys/dev/drm2/i915/intel_pm.c
     - copied unchanged from r277487, head/sys/dev/drm2/i915/intel_pm.c
Modified:
  stable/10/sys/dev/drm2/drm.h
  stable/10/sys/dev/drm2/drmP.h
  stable/10/sys/dev/drm2/drm_crtc.c
  stable/10/sys/dev/drm2/drm_crtc.h
  stable/10/sys/dev/drm2/drm_crtc_helper.c
  stable/10/sys/dev/drm2/drm_crtc_helper.h
  stable/10/sys/dev/drm2/drm_drv.c
  stable/10/sys/dev/drm2/drm_edid.c
  stable/10/sys/dev/drm2/drm_edid.h
  stable/10/sys/dev/drm2/drm_edid_modes.h
  stable/10/sys/dev/drm2/drm_fb_helper.c
  stable/10/sys/dev/drm2/drm_ioctl.c
  stable/10/sys/dev/drm2/drm_irq.c
  stable/10/sys/dev/drm2/drm_memory.c
  stable/10/sys/dev/drm2/drm_mode.h
  stable/10/sys/dev/drm2/drm_pciids.h
  stable/10/sys/dev/drm2/drm_stub.c
  stable/10/sys/dev/drm2/i915/i915_debug.c
  stable/10/sys/dev/drm2/i915/i915_dma.c
  stable/10/sys/dev/drm2/i915/i915_drm.h
  stable/10/sys/dev/drm2/i915/i915_drv.c
  stable/10/sys/dev/drm2/i915/i915_drv.h
  stable/10/sys/dev/drm2/i915/i915_gem.c
  stable/10/sys/dev/drm2/i915/i915_gem_context.c
  stable/10/sys/dev/drm2/i915/i915_gem_evict.c
  stable/10/sys/dev/drm2/i915/i915_gem_execbuffer.c
  stable/10/sys/dev/drm2/i915/i915_gem_gtt.c
  stable/10/sys/dev/drm2/i915/i915_gem_tiling.c
  stable/10/sys/dev/drm2/i915/i915_irq.c
  stable/10/sys/dev/drm2/i915/i915_reg.h
  stable/10/sys/dev/drm2/i915/i915_suspend.c
  stable/10/sys/dev/drm2/i915/intel_bios.c
  stable/10/sys/dev/drm2/i915/intel_crt.c
  stable/10/sys/dev/drm2/i915/intel_display.c
  stable/10/sys/dev/drm2/i915/intel_dp.c
  stable/10/sys/dev/drm2/i915/intel_drv.h
  stable/10/sys/dev/drm2/i915/intel_fb.c
  stable/10/sys/dev/drm2/i915/intel_hdmi.c
  stable/10/sys/dev/drm2/i915/intel_iic.c
  stable/10/sys/dev/drm2/i915/intel_lvds.c
  stable/10/sys/dev/drm2/i915/intel_modes.c
  stable/10/sys/dev/drm2/i915/intel_overlay.c
  stable/10/sys/dev/drm2/i915/intel_panel.c
  stable/10/sys/dev/drm2/i915/intel_ringbuffer.c
  stable/10/sys/dev/drm2/i915/intel_ringbuffer.h
  stable/10/sys/dev/drm2/i915/intel_sdvo.c
  stable/10/sys/dev/drm2/i915/intel_sprite.c
  stable/10/sys/dev/drm2/i915/intel_tv.c
  stable/10/sys/dev/drm2/radeon/atombios_encoders.c
  stable/10/sys/dev/drm2/radeon/radeon_legacy_encoders.c
  stable/10/sys/modules/drm2/i915kms/Makefile
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/dev/drm2/drm.h
==============================================================================
--- stable/10/sys/dev/drm2/drm.h        Mon Mar 23 13:05:02 2015        
(r280368)
+++ stable/10/sys/dev/drm2/drm.h        Mon Mar 23 13:38:33 2015        
(r280369)
@@ -1018,6 +1018,9 @@ struct drm_event_vblank {
 #define DRM_CAP_PRIME 0x5
 #define DRM_CAP_TIMESTAMP_MONOTONIC 0x6
 
+#define DRM_PRIME_CAP_IMPORT 0x1
+#define DRM_PRIME_CAP_EXPORT 0x2
+
 #include "drm_mode.h"
 
 /**
@@ -1126,6 +1129,8 @@ struct drm_event_vblank {
 #define DRM_IOCTL_MODE_GETPLANE                DRM_IOWR(0xB6, struct 
drm_mode_get_plane)
 #define DRM_IOCTL_MODE_SETPLANE                DRM_IOWR(0xB7, struct 
drm_mode_set_plane)
 #define DRM_IOCTL_MODE_ADDFB2          DRM_IOWR(0xB8, struct drm_mode_fb_cmd2)
+#define DRM_IOCTL_MODE_OBJ_GETPROPERTIES       DRM_IOWR(0xB9, struct 
drm_mode_obj_get_properties)
+#define DRM_IOCTL_MODE_OBJ_SETPROPERTY DRM_IOWR(0xBA, struct 
drm_mode_obj_set_property)
 
 #define DRM_IOCTL_MM_INIT               DRM_IOWR(0xc0, struct drm_mm_init_arg)
 #define DRM_IOCTL_MM_TAKEDOWN           DRM_IOWR(0xc1, struct drm_mm_type_arg)

Modified: stable/10/sys/dev/drm2/drmP.h
==============================================================================
--- stable/10/sys/dev/drm2/drmP.h       Mon Mar 23 13:05:02 2015        
(r280368)
+++ stable/10/sys/dev/drm2/drmP.h       Mon Mar 23 13:38:33 2015        
(r280369)
@@ -1246,6 +1246,7 @@ int       drm_ati_pcigart_cleanup(struct drm_d
 
 /* Cache management (drm_memory.c) */
 void   drm_clflush_pages(vm_page_t *pages, unsigned long num_pages);
+void   drm_clflush_virt_range(char *addr, unsigned long length);
 
 /* Locking IOCTL support (drm_drv.c) */
 int    drm_lock(struct drm_device *dev, void *data,

Modified: stable/10/sys/dev/drm2/drm_crtc.c
==============================================================================
--- stable/10/sys/dev/drm2/drm_crtc.c   Mon Mar 23 13:05:02 2015        
(r280368)
+++ stable/10/sys/dev/drm2/drm_crtc.c   Mon Mar 23 13:38:33 2015        
(r280369)
@@ -352,7 +352,7 @@ void drm_framebuffer_cleanup(struct drm_
  * @funcs: callbacks for the new CRTC
  *
  * LOCKING:
- * Caller must hold mode config lock.
+ * Takes mode_config lock.
  *
  * Inits a new object created as base part of an driver crtc object.
  *
@@ -372,8 +372,11 @@ int drm_crtc_init(struct drm_device *dev
        if (ret)
                goto out;
 
+       crtc->base.properties = &crtc->properties;
+
        list_add_tail(&crtc->head, &dev->mode_config.crtc_list);
        dev->mode_config.num_crtc++;
+
 out:
        sx_xunlock(&dev->mode_config.mutex);
 
@@ -474,6 +477,7 @@ int drm_connector_init(struct drm_device
        if (ret)
                goto out;
 
+       connector->base.properties = &connector->properties;
        connector->dev = dev;
        connector->funcs = funcs;
        connector->connector_type = connector_type;
@@ -582,6 +586,7 @@ int drm_plane_init(struct drm_device *de
        if (ret)
                goto out;
 
+       plane->base.properties = &plane->properties;
        plane->dev = dev;
        plane->funcs = funcs;
        plane->format_types = malloc(sizeof(uint32_t) * format_count,
@@ -1399,11 +1404,7 @@ int drm_mode_getconnector(struct drm_dev
        }
        connector = obj_to_connector(obj);
 
-       for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) {
-               if (connector->property_ids[i] != 0) {
-                       props_count++;
-               }
-       }
+       props_count = connector->properties.count;
 
        for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
                if (connector->encoder_ids[i] != 0) {
@@ -1456,21 +1457,19 @@ int drm_mode_getconnector(struct drm_dev
                copied = 0;
                prop_ptr = (uint32_t *)(uintptr_t)(out_resp->props_ptr);
                prop_values = (uint64_t 
*)(uintptr_t)(out_resp->prop_values_ptr);
-               for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) {
-                       if (connector->property_ids[i] != 0) {
-                               if (copyout(&connector->property_ids[i],
-                                   prop_ptr + copied, sizeof(uint32_t))) {
-                                       ret = EFAULT;
-                                       goto out;
-                               }
+               for (i = 0; i < connector->properties.count; i++) {
+                       if (copyout(&connector->properties.ids[i],
+                           prop_ptr + copied, sizeof(uint32_t))) {
+                               ret = EFAULT;
+                               goto out;
+                       }
 
-                               if (copyout(&connector->property_values[i],
-                                   prop_values + copied, sizeof(uint64_t))) {
-                                       ret = EFAULT;
-                                       goto out;
-                               }
-                               copied++;
+                       if (copyout(&connector->properties.values[i],
+                           prop_values + copied, sizeof(uint64_t))) {
+                               ret = EFAULT;
+                               goto out;
                        }
+                       copied++;
                }
        }
        out_resp->count_props = props_count;
@@ -1808,7 +1807,7 @@ int drm_mode_setcrtc(struct drm_device *
        struct drm_display_mode *mode = NULL;
        struct drm_mode_set set;
        uint32_t *set_connectors_ptr;
-       int ret = 0;
+       int ret;
        int i;
 
        if (!drm_core_check_feature(dev, DRIVER_MODESET))
@@ -2070,7 +2069,7 @@ int drm_mode_addfb(struct drm_device *de
 
        ret = -dev->mode_config.funcs->fb_create(dev, file_priv, &r, &fb);
        if (ret != 0) {
-               DRM_ERROR("could not create framebuffer, error %d\n", ret);
+               DRM_DEBUG_KMS("could not create framebuffer, error %d\n", ret);
                goto out;
        }
 
@@ -2152,6 +2151,47 @@ static int format_check(struct drm_mode_
        }
 }
 
+static int framebuffer_check(struct drm_mode_fb_cmd2 *r)
+{
+       int ret, hsub, vsub, num_planes, i;
+
+       ret = format_check(r);
+       if (ret) {
+               DRM_DEBUG_KMS("bad framebuffer format 0x%08x\n", 
r->pixel_format);
+               return ret;
+       }
+
+       hsub = drm_format_horz_chroma_subsampling(r->pixel_format);
+       vsub = drm_format_vert_chroma_subsampling(r->pixel_format);
+       num_planes = drm_format_num_planes(r->pixel_format);
+
+       if (r->width == 0 || r->width % hsub) {
+               DRM_DEBUG_KMS("bad framebuffer width %u\n", r->height);
+               return -EINVAL;
+       }
+
+       if (r->height == 0 || r->height % vsub) {
+               DRM_DEBUG_KMS("bad framebuffer height %u\n", r->height);
+               return -EINVAL;
+       }
+
+       for (i = 0; i < num_planes; i++) {
+               unsigned int width = r->width / (i != 0 ? hsub : 1);
+
+               if (!r->handles[i]) {
+                       DRM_DEBUG_KMS("no buffer object handle for plane %d\n", 
i);
+                       return -EINVAL;
+               }
+
+               if (r->pitches[i] < drm_format_plane_cpp(r->pixel_format, i) * 
width) {
+                       DRM_DEBUG_KMS("bad pitch %u for plane %d\n", 
r->pitches[i], i);
+                       return -EINVAL;
+               }
+       }
+
+       return 0;
+}
+
 /**
  * drm_mode_addfb2 - add an FB to the graphics configuration
  * @inode: inode from the ioctl
@@ -2181,21 +2221,19 @@ int drm_mode_addfb2(struct drm_device *d
                return (EINVAL);
 
        if ((config->min_width > r->width) || (r->width > config->max_width)) {
-               DRM_ERROR("bad framebuffer width %d, should be >= %d && <= 
%d\n",
+               DRM_DEBUG_KMS("bad framebuffer width %d, should be >= %d && <= 
%d\n",
                          r->width, config->min_width, config->max_width);
                return (EINVAL);
        }
        if ((config->min_height > r->height) || (r->height > 
config->max_height)) {
-               DRM_ERROR("bad framebuffer height %d, should be >= %d && <= 
%d\n",
+               DRM_DEBUG_KMS("bad framebuffer height %d, should be >= %d && <= 
%d\n",
                          r->height, config->min_height, config->max_height);
                return (EINVAL);
        }
 
-       ret = format_check(r);
-       if (ret) {
-               DRM_ERROR("bad framebuffer format 0x%08x\n", r->pixel_format);
-               return ret;
-       }
+       ret = framebuffer_check(r);
+       if (ret)
+               return -ret;
 
        sx_xlock(&dev->mode_config.mutex);
 
@@ -2204,7 +2242,7 @@ int drm_mode_addfb2(struct drm_device *d
 
        ret = -dev->mode_config.funcs->fb_create(dev, file_priv, r, &fb);
        if (ret != 0) {
-               DRM_ERROR("could not create framebuffer, error %d\n", ret);
+               DRM_DEBUG_KMS("could not create framebuffer, error %d\n", ret);
                goto out;
        }
 
@@ -2335,7 +2373,7 @@ int drm_mode_dirtyfb_ioctl(struct drm_de
        struct drm_framebuffer *fb;
        unsigned flags;
        int num_clips;
-       int ret = 0;
+       int ret;
 
        if (!drm_core_check_feature(dev, DRIVER_MODESET))
                return (EINVAL);
@@ -2530,7 +2568,7 @@ int drm_mode_attachmode_ioctl(struct drm
        struct drm_display_mode *mode;
        struct drm_mode_object *obj;
        struct drm_mode_modeinfo *umode = &mode_cmd->mode;
-       int ret = 0;
+       int ret;
 
        if (!drm_core_check_feature(dev, DRIVER_MODESET))
                return -EINVAL;
@@ -2584,7 +2622,7 @@ int drm_mode_detachmode_ioctl(struct drm
        struct drm_connector *connector;
        struct drm_display_mode mode;
        struct drm_mode_modeinfo *umode = &mode_cmd->mode;
-       int ret = 0;
+       int ret;
 
        if (!drm_core_check_feature(dev, DRIVER_MODESET))
                return -EINVAL;
@@ -2672,6 +2710,33 @@ struct drm_property *drm_property_create
        return property;
 }
 
+struct drm_property *drm_property_create_bitmask(struct drm_device *dev,
+                                        int flags, const char *name,
+                                        const struct drm_prop_enum_list *props,
+                                        int num_values)
+{
+       struct drm_property *property;
+       int i, ret;
+
+       flags |= DRM_MODE_PROP_BITMASK;
+
+       property = drm_property_create(dev, flags, name, num_values);
+       if (!property)
+               return NULL;
+
+       for (i = 0; i < num_values; i++) {
+               ret = drm_property_add_enum(property, i,
+                                     props[i].type,
+                                     props[i].name);
+               if (ret) {
+                       drm_property_destroy(dev, property);
+                       return NULL;
+               }
+       }
+
+       return property;
+}
+
 struct drm_property *drm_property_create_range(struct drm_device *dev, int 
flags,
                                         const char *name,
                                         uint64_t min, uint64_t max)
@@ -2695,7 +2760,14 @@ int drm_property_add_enum(struct drm_pro
 {
        struct drm_property_enum *prop_enum;
 
-       if (!(property->flags & DRM_MODE_PROP_ENUM))
+       if (!(property->flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)))
+               return -EINVAL;
+
+       /*
+        * Bitmask enum properties have the additional constraint of values
+        * from 0 to 63
+        */
+       if ((property->flags & DRM_MODE_PROP_BITMASK) && (value > 63))
                return -EINVAL;
 
        if (!list_empty(&property->enum_blob_list)) {
@@ -2736,56 +2808,71 @@ void drm_property_destroy(struct drm_dev
        free(property, DRM_MEM_KMS);
 }
 
-int drm_connector_attach_property(struct drm_connector *connector,
+void drm_connector_attach_property(struct drm_connector *connector,
                               struct drm_property *property, uint64_t init_val)
 {
-       int i;
-
-       for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) {
-               if (connector->property_ids[i] == 0) {
-                       connector->property_ids[i] = property->base.id;
-                       connector->property_values[i] = init_val;
-                       break;
-               }
-       }
-
-       if (i == DRM_CONNECTOR_MAX_PROPERTY)
-               return -EINVAL;
-       return 0;
+       drm_object_attach_property(&connector->base, property, init_val);
 }
 
 int drm_connector_property_set_value(struct drm_connector *connector,
                                  struct drm_property *property, uint64_t value)
 {
+       return drm_object_property_set_value(&connector->base, property, value);
+}
+
+int drm_connector_property_get_value(struct drm_connector *connector,
+                                 struct drm_property *property, uint64_t *val)
+{
+       return drm_object_property_get_value(&connector->base, property, val);
+}
+
+void drm_object_attach_property(struct drm_mode_object *obj,
+                               struct drm_property *property,
+                               uint64_t init_val)
+{
+       int count = obj->properties->count;
+
+       if (count == DRM_OBJECT_MAX_PROPERTY) {
+               printf("Failed to attach object property (type: 0x%x). Please "
+                       "increase DRM_OBJECT_MAX_PROPERTY by 1 for each time "
+                       "you see this message on the same object type.\n",
+                       obj->type);
+               return;
+       }
+
+       obj->properties->ids[count] = property->base.id;
+       obj->properties->values[count] = init_val;
+       obj->properties->count++;
+}
+
+int drm_object_property_set_value(struct drm_mode_object *obj,
+                                 struct drm_property *property, uint64_t val)
+{
        int i;
 
-       for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) {
-               if (connector->property_ids[i] == property->base.id) {
-                       connector->property_values[i] = value;
-                       break;
+       for (i = 0; i < obj->properties->count; i++) {
+               if (obj->properties->ids[i] == property->base.id) {
+                       obj->properties->values[i] = val;
+                       return 0;
                }
        }
 
-       if (i == DRM_CONNECTOR_MAX_PROPERTY)
-               return -EINVAL;
-       return 0;
+       return -EINVAL;
 }
 
-int drm_connector_property_get_value(struct drm_connector *connector,
+int drm_object_property_get_value(struct drm_mode_object *obj,
                                  struct drm_property *property, uint64_t *val)
 {
        int i;
 
-       for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) {
-               if (connector->property_ids[i] == property->base.id) {
-                       *val = connector->property_values[i];
-                       break;
+       for (i = 0; i < obj->properties->count; i++) {
+               if (obj->properties->ids[i] == property->base.id) {
+                       *val = obj->properties->values[i];
+                       return 0;
                }
        }
 
-       if (i == DRM_CONNECTOR_MAX_PROPERTY)
-               return -EINVAL;
-       return 0;
+       return -EINVAL;
 }
 
 int drm_mode_getproperty_ioctl(struct drm_device *dev,
@@ -2817,7 +2904,7 @@ int drm_mode_getproperty_ioctl(struct dr
        }
        property = obj_to_property(obj);
 
-       if (property->flags & DRM_MODE_PROP_ENUM) {
+       if (property->flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)) {
                list_for_each_entry(prop_enum, &property->enum_blob_list, head)
                        enum_count++;
        } else if (property->flags & DRM_MODE_PROP_BLOB) {
@@ -2842,7 +2929,7 @@ int drm_mode_getproperty_ioctl(struct dr
        }
        out_resp->count_values = value_count;
 
-       if (property->flags & DRM_MODE_PROP_ENUM) {
+       if (property->flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)) {
                if ((out_resp->count_enum_blobs >= enum_count) && enum_count) {
                        copied = 0;
                        enum_ptr = (struct drm_mode_property_enum 
*)(uintptr_t)out_resp->enum_blob_ptr;
@@ -2965,7 +3052,7 @@ int drm_mode_connector_update_edid_prope
                                            struct edid *edid)
 {
        struct drm_device *dev = connector->dev;
-       int ret = 0, size;
+       int ret, size;
 
        if (connector->edid_blob_ptr)
                drm_property_destroy_blob(dev, connector->edid_blob_ptr);
@@ -2988,75 +3075,202 @@ int drm_mode_connector_update_edid_prope
        return ret;
 }
 
+static bool drm_property_change_is_valid(struct drm_property *property,
+                                        u64 value)
+{
+       if (property->flags & DRM_MODE_PROP_IMMUTABLE)
+               return false;
+       if (property->flags & DRM_MODE_PROP_RANGE) {
+               if (value < property->values[0] || value > property->values[1])
+                       return false;
+               return true;
+       } else if (property->flags & DRM_MODE_PROP_BITMASK) {
+               int i;
+               u64 valid_mask = 0;
+               for (i = 0; i < property->num_values; i++)
+                       valid_mask |= (1ULL << property->values[i]);
+               return !(value & ~valid_mask);
+       } else {
+               int i;
+               for (i = 0; i < property->num_values; i++)
+                       if (property->values[i] == value)
+                               return true;
+               return false;
+       }
+}
+
 int drm_mode_connector_property_set_ioctl(struct drm_device *dev,
                                       void *data, struct drm_file *file_priv)
 {
-       struct drm_mode_connector_set_property *out_resp = data;
-       struct drm_mode_object *obj;
-       struct drm_property *property;
-       struct drm_connector *connector;
+       struct drm_mode_connector_set_property *conn_set_prop = data;
+       struct drm_mode_obj_set_property obj_set_prop = {
+               .value = conn_set_prop->value,
+               .prop_id = conn_set_prop->prop_id,
+               .obj_id = conn_set_prop->connector_id,
+               .obj_type = DRM_MODE_OBJECT_CONNECTOR
+       };
+
+       /* It does all the locking and checking we need */
+       return drm_mode_obj_set_property_ioctl(dev, &obj_set_prop, file_priv);
+}
+
+static int drm_mode_connector_set_obj_prop(struct drm_mode_object *obj,
+                                          struct drm_property *property,
+                                          uint64_t value)
+{
+       int ret = -EINVAL;
+       struct drm_connector *connector = obj_to_connector(obj);
+
+       /* Do DPMS ourselves */
+       if (property == connector->dev->mode_config.dpms_property) {
+               if (connector->funcs->dpms)
+                       (*connector->funcs->dpms)(connector, (int)value);
+               ret = 0;
+       } else if (connector->funcs->set_property)
+               ret = connector->funcs->set_property(connector, property, 
value);
+
+       /* store the property value if successful */
+       if (!ret)
+               drm_connector_property_set_value(connector, property, value);
+       return ret;
+}
+
+static int drm_mode_crtc_set_obj_prop(struct drm_mode_object *obj,
+                                     struct drm_property *property,
+                                     uint64_t value)
+{
        int ret = -EINVAL;
+       struct drm_crtc *crtc = obj_to_crtc(obj);
+
+       if (crtc->funcs->set_property)
+               ret = crtc->funcs->set_property(crtc, property, value);
+       if (!ret)
+               drm_object_property_set_value(obj, property, value);
+
+       return ret;
+}
+
+static int drm_mode_plane_set_obj_prop(struct drm_mode_object *obj,
+                                     struct drm_property *property,
+                                     uint64_t value)
+{
+       int ret = -EINVAL;
+       struct drm_plane *plane = obj_to_plane(obj);
+
+       if (plane->funcs->set_property)
+               ret = plane->funcs->set_property(plane, property, value);
+       if (!ret)
+               drm_object_property_set_value(obj, property, value);
+
+       return ret;
+}
+
+int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data,
+                                     struct drm_file *file_priv)
+{
+       struct drm_mode_obj_get_properties *arg = data;
+       struct drm_mode_object *obj;
+       int ret = 0;
        int i;
+       int copied = 0;
+       int props_count = 0;
+       uint32_t __user *props_ptr;
+       uint64_t __user *prop_values_ptr;
 
        if (!drm_core_check_feature(dev, DRIVER_MODESET))
                return -EINVAL;
 
        sx_xlock(&dev->mode_config.mutex);
 
-       obj = drm_mode_object_find(dev, out_resp->connector_id, 
DRM_MODE_OBJECT_CONNECTOR);
+       obj = drm_mode_object_find(dev, arg->obj_id, arg->obj_type);
        if (!obj) {
+               ret = -EINVAL;
+               goto out;
+       }
+       if (!obj->properties) {
+               ret = -EINVAL;
                goto out;
        }
-       connector = obj_to_connector(obj);
 
-       for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) {
-               if (connector->property_ids[i] == out_resp->prop_id)
-                       break;
+       props_count = obj->properties->count;
+
+       /* This ioctl is called twice, once to determine how much space is
+        * needed, and the 2nd time to fill it. */
+       if ((arg->count_props >= props_count) && props_count) {
+               copied = 0;
+               props_ptr = (uint32_t __user *)(unsigned long)(arg->props_ptr);
+               prop_values_ptr = (uint64_t __user *)(unsigned long)
+                                 (arg->prop_values_ptr);
+               for (i = 0; i < props_count; i++) {
+                       if (copyout(props_ptr + copied,
+                           &obj->properties->ids[i], sizeof(uint32_t))) {
+                               ret = -EFAULT;
+                               goto out;
+                       }
+                       if (copyout(prop_values_ptr + copied,
+                           &obj->properties->values[i], sizeof(uint64_t))) {
+                               ret = -EFAULT;
+                               goto out;
+                       }
+                       copied++;
+               }
        }
+       arg->count_props = props_count;
+out:
+       sx_xunlock(&dev->mode_config.mutex);
+       return ret;
+}
 
-       if (i == DRM_CONNECTOR_MAX_PROPERTY) {
+int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data,
+                                   struct drm_file *file_priv)
+{
+       struct drm_mode_obj_set_property *arg = data;
+       struct drm_mode_object *arg_obj;
+       struct drm_mode_object *prop_obj;
+       struct drm_property *property;
+       int ret = -EINVAL;
+       int i;
+
+       if (!drm_core_check_feature(dev, DRIVER_MODESET))
+               return -EINVAL;
+
+       sx_xlock(&dev->mode_config.mutex);
+
+       arg_obj = drm_mode_object_find(dev, arg->obj_id, arg->obj_type);
+       if (!arg_obj)
+               goto out;
+       if (!arg_obj->properties)
                goto out;
-       }
 
-       obj = drm_mode_object_find(dev, out_resp->prop_id, 
DRM_MODE_OBJECT_PROPERTY);
-       if (!obj) {
+       for (i = 0; i < arg_obj->properties->count; i++)
+               if (arg_obj->properties->ids[i] == arg->prop_id)
+                       break;
+
+       if (i == arg_obj->properties->count)
                goto out;
-       }
-       property = obj_to_property(obj);
 
-       if (property->flags & DRM_MODE_PROP_IMMUTABLE)
+       prop_obj = drm_mode_object_find(dev, arg->prop_id,
+                                       DRM_MODE_OBJECT_PROPERTY);
+       if (!prop_obj)
                goto out;
+       property = obj_to_property(prop_obj);
 
-       if (property->flags & DRM_MODE_PROP_RANGE) {
-               if (out_resp->value < property->values[0])
-                       goto out;
+       if (!drm_property_change_is_valid(property, arg->value))
+               goto out;
 
-               if (out_resp->value > property->values[1])
-                       goto out;
-       } else {
-               int found = 0;
-               for (i = 0; i < property->num_values; i++) {
-                       if (property->values[i] == out_resp->value) {
-                               found = 1;
-                               break;
-                       }
-               }
-               if (!found) {
-                       goto out;
-               }
+       switch (arg_obj->type) {
+       case DRM_MODE_OBJECT_CONNECTOR:
+               ret = drm_mode_connector_set_obj_prop(arg_obj, property,
+                                                     arg->value);
+               break;
+       case DRM_MODE_OBJECT_CRTC:
+               ret = drm_mode_crtc_set_obj_prop(arg_obj, property, arg->value);
+               break;
+       case DRM_MODE_OBJECT_PLANE:
+               ret = drm_mode_plane_set_obj_prop(arg_obj, property, 
arg->value);
+               break;
        }
 
-       /* Do DPMS ourselves */
-       if (property == connector->dev->mode_config.dpms_property) {
-               if (connector->funcs->dpms)
-                       (*connector->funcs->dpms)(connector, (int) 
out_resp->value);
-               ret = 0;
-       } else if (connector->funcs->set_property)
-               ret = connector->funcs->set_property(connector, property, 
out_resp->value);
-
-       /* store the property value if successful */
-       if (!ret)
-               drm_connector_property_set_value(connector, property, 
out_resp->value);
 out:
        sx_xunlock(&dev->mode_config.mutex);
        return ret;
@@ -3176,6 +3390,11 @@ int drm_mode_gamma_get_ioctl(struct drm_
        }
        crtc = obj_to_crtc(obj);
 
+       if (crtc->funcs->gamma_set == NULL) {
+               ret = -ENOSYS;
+               goto out;
+       }
+
        /* memcpy into gamma store */
        if (crtc_lut->gamma_size != crtc->gamma_size) {
                ret = -EINVAL;
@@ -3417,3 +3636,136 @@ void drm_fb_get_bpp_depth(uint32_t forma
                break;
        }
 }
+
+/**
+ * drm_format_num_planes - get the number of planes for format
+ * @format: pixel format (DRM_FORMAT_*)
+ *
+ * RETURNS:
+ * The number of planes used by the specified pixel format.
+ */
+int drm_format_num_planes(uint32_t format)
+{
+       switch (format) {
+       case DRM_FORMAT_YUV410:
+       case DRM_FORMAT_YVU410:
+       case DRM_FORMAT_YUV411:
+       case DRM_FORMAT_YVU411:
+       case DRM_FORMAT_YUV420:
+       case DRM_FORMAT_YVU420:
+       case DRM_FORMAT_YUV422:
+       case DRM_FORMAT_YVU422:
+       case DRM_FORMAT_YUV444:
+       case DRM_FORMAT_YVU444:
+               return 3;
+       case DRM_FORMAT_NV12:
+       case DRM_FORMAT_NV21:
+       case DRM_FORMAT_NV16:
+       case DRM_FORMAT_NV61:
+               return 2;
+       default:
+               return 1;
+       }
+}
+
+/**
+ * drm_format_plane_cpp - determine the bytes per pixel value
+ * @format: pixel format (DRM_FORMAT_*)
+ * @plane: plane index
+ *
+ * RETURNS:
+ * The bytes per pixel value for the specified plane.
+ */
+int drm_format_plane_cpp(uint32_t format, int plane)
+{
+       unsigned int depth;
+       int bpp;
+
+       if (plane >= drm_format_num_planes(format))
+               return 0;
+
+       switch (format) {
+       case DRM_FORMAT_YUYV:
+       case DRM_FORMAT_YVYU:
+       case DRM_FORMAT_UYVY:
+       case DRM_FORMAT_VYUY:
+               return 2;
+       case DRM_FORMAT_NV12:
+       case DRM_FORMAT_NV21:
+       case DRM_FORMAT_NV16:
+       case DRM_FORMAT_NV61:
+               return plane ? 2 : 1;
+       case DRM_FORMAT_YUV410:
+       case DRM_FORMAT_YVU410:
+       case DRM_FORMAT_YUV411:
+       case DRM_FORMAT_YVU411:
+       case DRM_FORMAT_YUV420:
+       case DRM_FORMAT_YVU420:
+       case DRM_FORMAT_YUV422:
+       case DRM_FORMAT_YVU422:
+       case DRM_FORMAT_YUV444:
+       case DRM_FORMAT_YVU444:
+               return 1;
+       default:
+               drm_fb_get_bpp_depth(format, &depth, &bpp);
+               return bpp >> 3;
+       }
+}
+
+/**
+ * drm_format_horz_chroma_subsampling - get the horizontal chroma subsampling 
factor
+ * @format: pixel format (DRM_FORMAT_*)
+ *
+ * RETURNS:
+ * The horizontal chroma subsampling factor for the
+ * specified pixel format.
+ */
+int drm_format_horz_chroma_subsampling(uint32_t format)
+{
+       switch (format) {
+       case DRM_FORMAT_YUV411:
+       case DRM_FORMAT_YVU411:
+       case DRM_FORMAT_YUV410:
+       case DRM_FORMAT_YVU410:
+               return 4;
+       case DRM_FORMAT_YUYV:
+       case DRM_FORMAT_YVYU:
+       case DRM_FORMAT_UYVY:
+       case DRM_FORMAT_VYUY:
+       case DRM_FORMAT_NV12:
+       case DRM_FORMAT_NV21:
+       case DRM_FORMAT_NV16:
+       case DRM_FORMAT_NV61:
+       case DRM_FORMAT_YUV422:
+       case DRM_FORMAT_YVU422:
+       case DRM_FORMAT_YUV420:
+       case DRM_FORMAT_YVU420:
+               return 2;
+       default:
+               return 1;
+       }
+}
+
+/**
+ * drm_format_vert_chroma_subsampling - get the vertical chroma subsampling 
factor
+ * @format: pixel format (DRM_FORMAT_*)
+ *
+ * RETURNS:
+ * The vertical chroma subsampling factor for the
+ * specified pixel format.
+ */
+int drm_format_vert_chroma_subsampling(uint32_t format)
+{
+       switch (format) {
+       case DRM_FORMAT_YUV410:
+       case DRM_FORMAT_YVU410:
+               return 4;
+       case DRM_FORMAT_YUV420:
+       case DRM_FORMAT_YVU420:
+       case DRM_FORMAT_NV12:
+       case DRM_FORMAT_NV21:
+               return 2;
+       default:
+               return 1;
+       }
+}

Modified: stable/10/sys/dev/drm2/drm_crtc.h
==============================================================================
--- stable/10/sys/dev/drm2/drm_crtc.h   Mon Mar 23 13:05:02 2015        
(r280368)
+++ stable/10/sys/dev/drm2/drm_crtc.h   Mon Mar 23 13:38:33 2015        
(r280369)
@@ -47,6 +47,14 @@ struct i2c_adapter;
 struct drm_mode_object {
        uint32_t id;
        uint32_t type;
+       struct drm_object_properties *properties;
+};
+
+#define DRM_OBJECT_MAX_PROPERTY 16
+struct drm_object_properties {
+       int count;
+       uint32_t ids[DRM_OBJECT_MAX_PROPERTY];
+       uint64_t values[DRM_OBJECT_MAX_PROPERTY];
 };
 
 /*
@@ -295,7 +303,8 @@ struct drm_plane;
  * @mode_fixup: fixup proposed mode
  * @mode_set: set the desired mode on the CRTC
  * @gamma_set: specify color ramp for CRTC
- * @destroy: deinit and free object.
+ * @destroy: deinit and free object
+ * @set_property: called when a property is changed
  *
  * The drm_crtc_funcs structure is the central CRTC management structure
  * in the DRM.  Each CRTC controls one or more connectors (note that the name
@@ -339,6 +348,8 @@ struct drm_crtc_funcs {
        int (*page_flip)(struct drm_crtc *crtc,
                         struct drm_framebuffer *fb,
                         struct drm_pending_vblank_event *event);
+       int (*set_property)(struct drm_crtc *crtc,
+                           struct drm_property *property, uint64_t val);
 };
 
 /**
@@ -347,6 +358,7 @@ struct drm_crtc_funcs {
  * @x: x position on screen
  * @y: y position on screen
  * @funcs: CRTC control functions
+ * @properties: property tracking for this CRTC
  *
  * Each CRTC may have one or more connectors associated with it.  This 
structure
  * allows the CRTC to be controlled.
@@ -382,6 +394,8 @@ struct drm_crtc {
 
        /* if you are using the helper */
        void *helper_private;
+
+       struct drm_object_properties properties;
 };
 
 
@@ -431,7 +445,6 @@ struct drm_encoder_funcs {
 };
 
 #define DRM_CONNECTOR_MAX_UMODES 16
-#define DRM_CONNECTOR_MAX_PROPERTY 16
 #define DRM_CONNECTOR_LEN 32
 #define DRM_CONNECTOR_MAX_ENCODER 2
 
@@ -511,8 +524,7 @@ struct drm_connector {
 
        struct list_head user_modes;
        struct drm_property_blob *edid_blob_ptr;
-       u32 property_ids[DRM_CONNECTOR_MAX_PROPERTY];
-       uint64_t property_values[DRM_CONNECTOR_MAX_PROPERTY];
+       struct drm_object_properties properties;
 
        uint8_t polled; /* DRM_CONNECTOR_POLL_* */
 
@@ -543,6 +555,7 @@ struct drm_connector {
  * @update_plane: update the plane configuration
  * @disable_plane: shut down the plane
  * @destroy: clean up plane resources
+ * @set_property: called when a property is changed
  */
 struct drm_plane_funcs {
        int (*update_plane)(struct drm_plane *plane,
@@ -553,6 +566,8 @@ struct drm_plane_funcs {
                            uint32_t src_w, uint32_t src_h);
        int (*disable_plane)(struct drm_plane *plane);
        void (*destroy)(struct drm_plane *plane);
+       int (*set_property)(struct drm_plane *plane,
+                           struct drm_property *property, uint64_t val);
 };
 
 /**
@@ -570,6 +585,7 @@ struct drm_plane_funcs {
  * @enabled: enabled flag
  * @funcs: helper functions
  * @helper_private: storage for drver layer
+ @properties: property tracking for this plane
  */
 struct drm_plane {
        struct drm_device *dev;
@@ -592,6 +608,8 @@ struct drm_plane {
 
        const struct drm_plane_funcs *funcs;
        void *helper_private;
+
+       struct drm_object_properties properties;
 };
 
 /**
@@ -806,6 +824,15 @@ extern int drm_connector_property_set_va
 extern int drm_connector_property_get_value(struct drm_connector *connector,
                                         struct drm_property *property,
                                         uint64_t *value);
+void drm_object_attach_property(struct drm_mode_object *obj,
+                               struct drm_property *property,
+                               uint64_t init_val);
+extern int drm_object_property_set_value(struct drm_mode_object *obj,
+                                        struct drm_property *property,
+                                        uint64_t val);
+extern int drm_object_property_get_value(struct drm_mode_object *obj,
+                                        struct drm_property *property,
+                                        uint64_t *value);
 extern struct drm_display_mode *drm_crtc_mode_create(struct drm_device *dev);
 extern void drm_framebuffer_set_object(struct drm_device *dev,
                                       unsigned long handle);
@@ -818,7 +845,7 @@ extern int drmfb_remove(struct drm_devic
 extern void drm_crtc_probe_connector_modes(struct drm_device *dev, int maxX, 
int maxY);
 extern bool drm_crtc_in_use(struct drm_crtc *crtc);
 
-extern int drm_connector_attach_property(struct drm_connector *connector,
+extern void drm_connector_attach_property(struct drm_connector *connector,
                                      struct drm_property *property, uint64_t 
init_val);
 extern struct drm_property *drm_property_create(struct drm_device *dev, int 
flags,
                                                const char *name, int 
num_values);
@@ -826,6 +853,10 @@ extern struct drm_property *drm_property
                                         const char *name,
                                         const struct drm_prop_enum_list *props,
                                         int num_values);
+struct drm_property *drm_property_create_bitmask(struct drm_device *dev,
+                                                int flags, const char *name,
+                                                const struct 
drm_prop_enum_list *props,
+                                                int num_values);
 struct drm_property *drm_property_create_range(struct drm_device *dev, int 
flags,
                                         const char *name,
                                         uint64_t min, uint64_t max);
@@ -921,7 +952,8 @@ extern int drm_add_modes_noedid(struct d
 extern int drm_edid_header_is_valid(const u8 *raw_edid);
 extern bool drm_edid_is_valid(struct edid *edid);
 struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev,
-                                          int hsize, int vsize, int fresh);
+                                          int hsize, int vsize, int fresh,
+                                          bool rb);
 
 extern int drm_mode_create_dumb_ioctl(struct drm_device *dev,
                                      void *data, struct drm_file *file_priv);
@@ -929,7 +961,16 @@ extern int drm_mode_mmap_dumb_ioctl(stru
                                    void *data, struct drm_file *file_priv);
 extern int drm_mode_destroy_dumb_ioctl(struct drm_device *dev,
                                      void *data, struct drm_file *file_priv);
+extern int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void 
*data,
+                                            struct drm_file *file_priv);
+extern int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data,
+                                          struct drm_file *file_priv);
 
 extern void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth,
                                 int *bpp);
+extern int drm_format_num_planes(uint32_t format);
+extern int drm_format_plane_cpp(uint32_t format, int plane);
+extern int drm_format_horz_chroma_subsampling(uint32_t format);
+extern int drm_format_vert_chroma_subsampling(uint32_t format);
+
 #endif /* __DRM_CRTC_H__ */

Modified: stable/10/sys/dev/drm2/drm_crtc_helper.c
==============================================================================
--- stable/10/sys/dev/drm2/drm_crtc_helper.c    Mon Mar 23 13:05:02 2015        
(r280368)
+++ stable/10/sys/dev/drm2/drm_crtc_helper.c    Mon Mar 23 13:38:33 2015        
(r280369)
@@ -549,7 +549,7 @@ int drm_crtc_helper_set_config(struct dr
        int count = 0, ro, fail = 0;
        struct drm_crtc_helper_funcs *crtc_funcs;
        struct drm_mode_set save_set;
-       int ret = 0;
+       int ret;
        int i;
 
        DRM_DEBUG_KMS("\n");

Modified: stable/10/sys/dev/drm2/drm_crtc_helper.h
==============================================================================
--- stable/10/sys/dev/drm2/drm_crtc_helper.h    Mon Mar 23 13:05:02 2015        
(r280368)
+++ stable/10/sys/dev/drm2/drm_crtc_helper.h    Mon Mar 23 13:38:33 2015        
(r280369)
@@ -78,7 +78,7 @@ struct drm_encoder_helper_funcs {

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to