From owner-svn-src-stable-10@FreeBSD.ORG Mon Mar 23 13:38:36 2015 Return-Path: Delivered-To: svn-src-stable-10@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 29BB3142; Mon, 23 Mar 2015 13:38:36 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 12459C37; Mon, 23 Mar 2015 13:38:36 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id t2NDca0h077574; Mon, 23 Mar 2015 13:38:36 GMT (envelope-from kib@FreeBSD.org) Received: (from kib@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id t2NDcYS9077563; Mon, 23 Mar 2015 13:38:34 GMT (envelope-from kib@FreeBSD.org) Message-Id: <201503231338.t2NDcYS9077563@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: kib set sender to kib@FreeBSD.org using -f From: Konstantin Belousov Date: Mon, 23 Mar 2015 13:38:34 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r280369 - in stable/10/sys: dev/drm2 dev/drm2/i915 dev/drm2/radeon modules/drm2/i915kms X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-10@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: SVN commit messages for only the 10-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 23 Mar 2015 13:38:36 -0000 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 ***