svn commit: r280369 - in stable/10/sys: dev/drm2 dev/drm2/i915 dev/drm2/radeon modules/drm2/i915kms
Konstantin Belousov
kib at FreeBSD.org
Mon Mar 23 13:38:36 UTC 2015
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 ***
More information about the svn-src-stable-10
mailing list