aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2016-08-29 04:27:55 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2016-08-29 09:37:34 -0400
commit59e71ee746a37fe077b73cecf189de1d27efd6eb (patch)
tree4c31aab686d6d4c3cca5410b8a6d5b42ead9c840
parentec5e304747241823435b160d3eabf1295c06d2e3 (diff)
drm: Extract drm_property.[hc]
This just contains the base property classes and all the code to handle blobs. I think for any kind of standardized/shared properties it's better to have separate files - this is fairly big already as-is. v2: resurrect misplaced hunk (Daniel Stone) Cc: Daniel Stone <daniel@fooishbar.org> Reviewed-by: Archit Taneja <architt@codeaurora.org> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/20160829082757.17913-7-daniel.vetter@ffwll.ch
-rw-r--r--Documentation/gpu/drm-kms.rst9
-rw-r--r--drivers/gpu/drm/Makefile2
-rw-r--r--drivers/gpu/drm/drm_crtc.c926
-rw-r--r--drivers/gpu/drm/drm_crtc_internal.h32
-rw-r--r--drivers/gpu/drm/drm_property.c953
-rw-r--r--include/drm/drm_crtc.h88
-rw-r--r--include/drm/drm_property.h120
7 files changed, 1102 insertions, 1028 deletions
diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst
index b164472f2157..e07a2667ab61 100644
--- a/Documentation/gpu/drm-kms.rst
+++ b/Documentation/gpu/drm-kms.rst
@@ -389,6 +389,15 @@ connector and plane objects by calling the
389pointer to the target object, a pointer to the previously created 389pointer to the target object, a pointer to the previously created
390property and an initial instance value. 390property and an initial instance value.
391 391
392Property Types and Blob Property Support
393----------------------------------------
394
395.. kernel-doc:: include/drm/drm_property.h
396 :internal:
397
398.. kernel-doc:: drivers/gpu/drm/drm_property.c
399 :export:
400
392Blending and Z-Position properties 401Blending and Z-Position properties
393---------------------------------- 402----------------------------------
394 403
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 59979f3f3648..12a966ec7298 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -14,7 +14,7 @@ drm-y := drm_auth.o drm_bufs.o drm_cache.o \
14 drm_rect.o drm_vma_manager.o drm_flip_work.o \ 14 drm_rect.o drm_vma_manager.o drm_flip_work.o \
15 drm_modeset_lock.o drm_atomic.o drm_bridge.o \ 15 drm_modeset_lock.o drm_atomic.o drm_bridge.o \
16 drm_framebuffer.o drm_connector.o drm_blend.o \ 16 drm_framebuffer.o drm_connector.o drm_blend.o \
17 drm_encoder.o drm_mode_object.o 17 drm_encoder.o drm_mode_object.o drm_property.o
18 18
19drm-$(CONFIG_COMPAT) += drm_ioc32.o 19drm-$(CONFIG_COMPAT) += drm_ioc32.o
20drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o 20drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 9ff58e6b51c4..b95c48acfa5b 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -1671,932 +1671,6 @@ int drm_mode_cursor2_ioctl(struct drm_device *dev,
1671 return drm_mode_cursor_common(dev, req, file_priv); 1671 return drm_mode_cursor_common(dev, req, file_priv);
1672} 1672}
1673 1673
1674static bool drm_property_type_valid(struct drm_property *property)
1675{
1676 if (property->flags & DRM_MODE_PROP_EXTENDED_TYPE)
1677 return !(property->flags & DRM_MODE_PROP_LEGACY_TYPE);
1678 return !!(property->flags & DRM_MODE_PROP_LEGACY_TYPE);
1679}
1680
1681/**
1682 * drm_property_create - create a new property type
1683 * @dev: drm device
1684 * @flags: flags specifying the property type
1685 * @name: name of the property
1686 * @num_values: number of pre-defined values
1687 *
1688 * This creates a new generic drm property which can then be attached to a drm
1689 * object with drm_object_attach_property. The returned property object must be
1690 * freed with drm_property_destroy.
1691 *
1692 * Note that the DRM core keeps a per-device list of properties and that, if
1693 * drm_mode_config_cleanup() is called, it will destroy all properties created
1694 * by the driver.
1695 *
1696 * Returns:
1697 * A pointer to the newly created property on success, NULL on failure.
1698 */
1699struct drm_property *drm_property_create(struct drm_device *dev, int flags,
1700 const char *name, int num_values)
1701{
1702 struct drm_property *property = NULL;
1703 int ret;
1704
1705 property = kzalloc(sizeof(struct drm_property), GFP_KERNEL);
1706 if (!property)
1707 return NULL;
1708
1709 property->dev = dev;
1710
1711 if (num_values) {
1712 property->values = kcalloc(num_values, sizeof(uint64_t),
1713 GFP_KERNEL);
1714 if (!property->values)
1715 goto fail;
1716 }
1717
1718 ret = drm_mode_object_get(dev, &property->base, DRM_MODE_OBJECT_PROPERTY);
1719 if (ret)
1720 goto fail;
1721
1722 property->flags = flags;
1723 property->num_values = num_values;
1724 INIT_LIST_HEAD(&property->enum_list);
1725
1726 if (name) {
1727 strncpy(property->name, name, DRM_PROP_NAME_LEN);
1728 property->name[DRM_PROP_NAME_LEN-1] = '\0';
1729 }
1730
1731 list_add_tail(&property->head, &dev->mode_config.property_list);
1732
1733 WARN_ON(!drm_property_type_valid(property));
1734
1735 return property;
1736fail:
1737 kfree(property->values);
1738 kfree(property);
1739 return NULL;
1740}
1741EXPORT_SYMBOL(drm_property_create);
1742
1743/**
1744 * drm_property_create_enum - create a new enumeration property type
1745 * @dev: drm device
1746 * @flags: flags specifying the property type
1747 * @name: name of the property
1748 * @props: enumeration lists with property values
1749 * @num_values: number of pre-defined values
1750 *
1751 * This creates a new generic drm property which can then be attached to a drm
1752 * object with drm_object_attach_property. The returned property object must be
1753 * freed with drm_property_destroy.
1754 *
1755 * Userspace is only allowed to set one of the predefined values for enumeration
1756 * properties.
1757 *
1758 * Returns:
1759 * A pointer to the newly created property on success, NULL on failure.
1760 */
1761struct drm_property *drm_property_create_enum(struct drm_device *dev, int flags,
1762 const char *name,
1763 const struct drm_prop_enum_list *props,
1764 int num_values)
1765{
1766 struct drm_property *property;
1767 int i, ret;
1768
1769 flags |= DRM_MODE_PROP_ENUM;
1770
1771 property = drm_property_create(dev, flags, name, num_values);
1772 if (!property)
1773 return NULL;
1774
1775 for (i = 0; i < num_values; i++) {
1776 ret = drm_property_add_enum(property, i,
1777 props[i].type,
1778 props[i].name);
1779 if (ret) {
1780 drm_property_destroy(dev, property);
1781 return NULL;
1782 }
1783 }
1784
1785 return property;
1786}
1787EXPORT_SYMBOL(drm_property_create_enum);
1788
1789/**
1790 * drm_property_create_bitmask - create a new bitmask property type
1791 * @dev: drm device
1792 * @flags: flags specifying the property type
1793 * @name: name of the property
1794 * @props: enumeration lists with property bitflags
1795 * @num_props: size of the @props array
1796 * @supported_bits: bitmask of all supported enumeration values
1797 *
1798 * This creates a new bitmask drm property which can then be attached to a drm
1799 * object with drm_object_attach_property. The returned property object must be
1800 * freed with drm_property_destroy.
1801 *
1802 * Compared to plain enumeration properties userspace is allowed to set any
1803 * or'ed together combination of the predefined property bitflag values
1804 *
1805 * Returns:
1806 * A pointer to the newly created property on success, NULL on failure.
1807 */
1808struct drm_property *drm_property_create_bitmask(struct drm_device *dev,
1809 int flags, const char *name,
1810 const struct drm_prop_enum_list *props,
1811 int num_props,
1812 uint64_t supported_bits)
1813{
1814 struct drm_property *property;
1815 int i, ret, index = 0;
1816 int num_values = hweight64(supported_bits);
1817
1818 flags |= DRM_MODE_PROP_BITMASK;
1819
1820 property = drm_property_create(dev, flags, name, num_values);
1821 if (!property)
1822 return NULL;
1823 for (i = 0; i < num_props; i++) {
1824 if (!(supported_bits & (1ULL << props[i].type)))
1825 continue;
1826
1827 if (WARN_ON(index >= num_values)) {
1828 drm_property_destroy(dev, property);
1829 return NULL;
1830 }
1831
1832 ret = drm_property_add_enum(property, index++,
1833 props[i].type,
1834 props[i].name);
1835 if (ret) {
1836 drm_property_destroy(dev, property);
1837 return NULL;
1838 }
1839 }
1840
1841 return property;
1842}
1843EXPORT_SYMBOL(drm_property_create_bitmask);
1844
1845static struct drm_property *property_create_range(struct drm_device *dev,
1846 int flags, const char *name,
1847 uint64_t min, uint64_t max)
1848{
1849 struct drm_property *property;
1850
1851 property = drm_property_create(dev, flags, name, 2);
1852 if (!property)
1853 return NULL;
1854
1855 property->values[0] = min;
1856 property->values[1] = max;
1857
1858 return property;
1859}
1860
1861/**
1862 * drm_property_create_range - create a new unsigned ranged property type
1863 * @dev: drm device
1864 * @flags: flags specifying the property type
1865 * @name: name of the property
1866 * @min: minimum value of the property
1867 * @max: maximum value of the property
1868 *
1869 * This creates a new generic drm property which can then be attached to a drm
1870 * object with drm_object_attach_property. The returned property object must be
1871 * freed with drm_property_destroy.
1872 *
1873 * Userspace is allowed to set any unsigned integer value in the (min, max)
1874 * range inclusive.
1875 *
1876 * Returns:
1877 * A pointer to the newly created property on success, NULL on failure.
1878 */
1879struct drm_property *drm_property_create_range(struct drm_device *dev, int flags,
1880 const char *name,
1881 uint64_t min, uint64_t max)
1882{
1883 return property_create_range(dev, DRM_MODE_PROP_RANGE | flags,
1884 name, min, max);
1885}
1886EXPORT_SYMBOL(drm_property_create_range);
1887
1888/**
1889 * drm_property_create_signed_range - create a new signed ranged property type
1890 * @dev: drm device
1891 * @flags: flags specifying the property type
1892 * @name: name of the property
1893 * @min: minimum value of the property
1894 * @max: maximum value of the property
1895 *
1896 * This creates a new generic drm property which can then be attached to a drm
1897 * object with drm_object_attach_property. The returned property object must be
1898 * freed with drm_property_destroy.
1899 *
1900 * Userspace is allowed to set any signed integer value in the (min, max)
1901 * range inclusive.
1902 *
1903 * Returns:
1904 * A pointer to the newly created property on success, NULL on failure.
1905 */
1906struct drm_property *drm_property_create_signed_range(struct drm_device *dev,
1907 int flags, const char *name,
1908 int64_t min, int64_t max)
1909{
1910 return property_create_range(dev, DRM_MODE_PROP_SIGNED_RANGE | flags,
1911 name, I642U64(min), I642U64(max));
1912}
1913EXPORT_SYMBOL(drm_property_create_signed_range);
1914
1915/**
1916 * drm_property_create_object - create a new object property type
1917 * @dev: drm device
1918 * @flags: flags specifying the property type
1919 * @name: name of the property
1920 * @type: object type from DRM_MODE_OBJECT_* defines
1921 *
1922 * This creates a new generic drm property which can then be attached to a drm
1923 * object with drm_object_attach_property. The returned property object must be
1924 * freed with drm_property_destroy.
1925 *
1926 * Userspace is only allowed to set this to any property value of the given
1927 * @type. Only useful for atomic properties, which is enforced.
1928 *
1929 * Returns:
1930 * A pointer to the newly created property on success, NULL on failure.
1931 */
1932struct drm_property *drm_property_create_object(struct drm_device *dev,
1933 int flags, const char *name, uint32_t type)
1934{
1935 struct drm_property *property;
1936
1937 flags |= DRM_MODE_PROP_OBJECT;
1938
1939 if (WARN_ON(!(flags & DRM_MODE_PROP_ATOMIC)))
1940 return NULL;
1941
1942 property = drm_property_create(dev, flags, name, 1);
1943 if (!property)
1944 return NULL;
1945
1946 property->values[0] = type;
1947
1948 return property;
1949}
1950EXPORT_SYMBOL(drm_property_create_object);
1951
1952/**
1953 * drm_property_create_bool - create a new boolean property type
1954 * @dev: drm device
1955 * @flags: flags specifying the property type
1956 * @name: name of the property
1957 *
1958 * This creates a new generic drm property which can then be attached to a drm
1959 * object with drm_object_attach_property. The returned property object must be
1960 * freed with drm_property_destroy.
1961 *
1962 * This is implemented as a ranged property with only {0, 1} as valid values.
1963 *
1964 * Returns:
1965 * A pointer to the newly created property on success, NULL on failure.
1966 */
1967struct drm_property *drm_property_create_bool(struct drm_device *dev, int flags,
1968 const char *name)
1969{
1970 return drm_property_create_range(dev, flags, name, 0, 1);
1971}
1972EXPORT_SYMBOL(drm_property_create_bool);
1973
1974/**
1975 * drm_property_add_enum - add a possible value to an enumeration property
1976 * @property: enumeration property to change
1977 * @index: index of the new enumeration
1978 * @value: value of the new enumeration
1979 * @name: symbolic name of the new enumeration
1980 *
1981 * This functions adds enumerations to a property.
1982 *
1983 * It's use is deprecated, drivers should use one of the more specific helpers
1984 * to directly create the property with all enumerations already attached.
1985 *
1986 * Returns:
1987 * Zero on success, error code on failure.
1988 */
1989int drm_property_add_enum(struct drm_property *property, int index,
1990 uint64_t value, const char *name)
1991{
1992 struct drm_property_enum *prop_enum;
1993
1994 if (!(drm_property_type_is(property, DRM_MODE_PROP_ENUM) ||
1995 drm_property_type_is(property, DRM_MODE_PROP_BITMASK)))
1996 return -EINVAL;
1997
1998 /*
1999 * Bitmask enum properties have the additional constraint of values
2000 * from 0 to 63
2001 */
2002 if (drm_property_type_is(property, DRM_MODE_PROP_BITMASK) &&
2003 (value > 63))
2004 return -EINVAL;
2005
2006 if (!list_empty(&property->enum_list)) {
2007 list_for_each_entry(prop_enum, &property->enum_list, head) {
2008 if (prop_enum->value == value) {
2009 strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN);
2010 prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0';
2011 return 0;
2012 }
2013 }
2014 }
2015
2016 prop_enum = kzalloc(sizeof(struct drm_property_enum), GFP_KERNEL);
2017 if (!prop_enum)
2018 return -ENOMEM;
2019
2020 strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN);
2021 prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0';
2022 prop_enum->value = value;
2023
2024 property->values[index] = value;
2025 list_add_tail(&prop_enum->head, &property->enum_list);
2026 return 0;
2027}
2028EXPORT_SYMBOL(drm_property_add_enum);
2029
2030/**
2031 * drm_property_destroy - destroy a drm property
2032 * @dev: drm device
2033 * @property: property to destry
2034 *
2035 * This function frees a property including any attached resources like
2036 * enumeration values.
2037 */
2038void drm_property_destroy(struct drm_device *dev, struct drm_property *property)
2039{
2040 struct drm_property_enum *prop_enum, *pt;
2041
2042 list_for_each_entry_safe(prop_enum, pt, &property->enum_list, head) {
2043 list_del(&prop_enum->head);
2044 kfree(prop_enum);
2045 }
2046
2047 if (property->num_values)
2048 kfree(property->values);
2049 drm_mode_object_unregister(dev, &property->base);
2050 list_del(&property->head);
2051 kfree(property);
2052}
2053EXPORT_SYMBOL(drm_property_destroy);
2054
2055/**
2056 * drm_mode_getproperty_ioctl - get the property metadata
2057 * @dev: DRM device
2058 * @data: ioctl data
2059 * @file_priv: DRM file info
2060 *
2061 * This function retrieves the metadata for a given property, like the different
2062 * possible values for an enum property or the limits for a range property.
2063 *
2064 * Blob properties are special
2065 *
2066 * Called by the user via ioctl.
2067 *
2068 * Returns:
2069 * Zero on success, negative errno on failure.
2070 */
2071int drm_mode_getproperty_ioctl(struct drm_device *dev,
2072 void *data, struct drm_file *file_priv)
2073{
2074 struct drm_mode_get_property *out_resp = data;
2075 struct drm_property *property;
2076 int enum_count = 0;
2077 int value_count = 0;
2078 int ret = 0, i;
2079 int copied;
2080 struct drm_property_enum *prop_enum;
2081 struct drm_mode_property_enum __user *enum_ptr;
2082 uint64_t __user *values_ptr;
2083
2084 if (!drm_core_check_feature(dev, DRIVER_MODESET))
2085 return -EINVAL;
2086
2087 drm_modeset_lock_all(dev);
2088 property = drm_property_find(dev, out_resp->prop_id);
2089 if (!property) {
2090 ret = -ENOENT;
2091 goto done;
2092 }
2093
2094 if (drm_property_type_is(property, DRM_MODE_PROP_ENUM) ||
2095 drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) {
2096 list_for_each_entry(prop_enum, &property->enum_list, head)
2097 enum_count++;
2098 }
2099
2100 value_count = property->num_values;
2101
2102 strncpy(out_resp->name, property->name, DRM_PROP_NAME_LEN);
2103 out_resp->name[DRM_PROP_NAME_LEN-1] = 0;
2104 out_resp->flags = property->flags;
2105
2106 if ((out_resp->count_values >= value_count) && value_count) {
2107 values_ptr = (uint64_t __user *)(unsigned long)out_resp->values_ptr;
2108 for (i = 0; i < value_count; i++) {
2109 if (copy_to_user(values_ptr + i, &property->values[i], sizeof(uint64_t))) {
2110 ret = -EFAULT;
2111 goto done;
2112 }
2113 }
2114 }
2115 out_resp->count_values = value_count;
2116
2117 if (drm_property_type_is(property, DRM_MODE_PROP_ENUM) ||
2118 drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) {
2119 if ((out_resp->count_enum_blobs >= enum_count) && enum_count) {
2120 copied = 0;
2121 enum_ptr = (struct drm_mode_property_enum __user *)(unsigned long)out_resp->enum_blob_ptr;
2122 list_for_each_entry(prop_enum, &property->enum_list, head) {
2123
2124 if (copy_to_user(&enum_ptr[copied].value, &prop_enum->value, sizeof(uint64_t))) {
2125 ret = -EFAULT;
2126 goto done;
2127 }
2128
2129 if (copy_to_user(&enum_ptr[copied].name,
2130 &prop_enum->name, DRM_PROP_NAME_LEN)) {
2131 ret = -EFAULT;
2132 goto done;
2133 }
2134 copied++;
2135 }
2136 }
2137 out_resp->count_enum_blobs = enum_count;
2138 }
2139
2140 /*
2141 * NOTE: The idea seems to have been to use this to read all the blob
2142 * property values. But nothing ever added them to the corresponding
2143 * list, userspace always used the special-purpose get_blob ioctl to
2144 * read the value for a blob property. It also doesn't make a lot of
2145 * sense to return values here when everything else is just metadata for
2146 * the property itself.
2147 */
2148 if (drm_property_type_is(property, DRM_MODE_PROP_BLOB))
2149 out_resp->count_enum_blobs = 0;
2150done:
2151 drm_modeset_unlock_all(dev);
2152 return ret;
2153}
2154
2155static void drm_property_free_blob(struct kref *kref)
2156{
2157 struct drm_property_blob *blob =
2158 container_of(kref, struct drm_property_blob, base.refcount);
2159
2160 mutex_lock(&blob->dev->mode_config.blob_lock);
2161 list_del(&blob->head_global);
2162 mutex_unlock(&blob->dev->mode_config.blob_lock);
2163
2164 drm_mode_object_unregister(blob->dev, &blob->base);
2165
2166 kfree(blob);
2167}
2168
2169/**
2170 * drm_property_create_blob - Create new blob property
2171 *
2172 * Creates a new blob property for a specified DRM device, optionally
2173 * copying data.
2174 *
2175 * @dev: DRM device to create property for
2176 * @length: Length to allocate for blob data
2177 * @data: If specified, copies data into blob
2178 *
2179 * Returns:
2180 * New blob property with a single reference on success, or an ERR_PTR
2181 * value on failure.
2182 */
2183struct drm_property_blob *
2184drm_property_create_blob(struct drm_device *dev, size_t length,
2185 const void *data)
2186{
2187 struct drm_property_blob *blob;
2188 int ret;
2189
2190 if (!length || length > ULONG_MAX - sizeof(struct drm_property_blob))
2191 return ERR_PTR(-EINVAL);
2192
2193 blob = kzalloc(sizeof(struct drm_property_blob)+length, GFP_KERNEL);
2194 if (!blob)
2195 return ERR_PTR(-ENOMEM);
2196
2197 /* This must be explicitly initialised, so we can safely call list_del
2198 * on it in the removal handler, even if it isn't in a file list. */
2199 INIT_LIST_HEAD(&blob->head_file);
2200 blob->length = length;
2201 blob->dev = dev;
2202
2203 if (data)
2204 memcpy(blob->data, data, length);
2205
2206 ret = drm_mode_object_get_reg(dev, &blob->base, DRM_MODE_OBJECT_BLOB,
2207 true, drm_property_free_blob);
2208 if (ret) {
2209 kfree(blob);
2210 return ERR_PTR(-EINVAL);
2211 }
2212
2213 mutex_lock(&dev->mode_config.blob_lock);
2214 list_add_tail(&blob->head_global,
2215 &dev->mode_config.property_blob_list);
2216 mutex_unlock(&dev->mode_config.blob_lock);
2217
2218 return blob;
2219}
2220EXPORT_SYMBOL(drm_property_create_blob);
2221
2222/**
2223 * drm_property_unreference_blob - Unreference a blob property
2224 *
2225 * Drop a reference on a blob property. May free the object.
2226 *
2227 * @blob: Pointer to blob property
2228 */
2229void drm_property_unreference_blob(struct drm_property_blob *blob)
2230{
2231 if (!blob)
2232 return;
2233
2234 drm_mode_object_unreference(&blob->base);
2235}
2236EXPORT_SYMBOL(drm_property_unreference_blob);
2237
2238/**
2239 * drm_property_destroy_user_blobs - destroy all blobs created by this client
2240 * @dev: DRM device
2241 * @file_priv: destroy all blobs owned by this file handle
2242 */
2243void drm_property_destroy_user_blobs(struct drm_device *dev,
2244 struct drm_file *file_priv)
2245{
2246 struct drm_property_blob *blob, *bt;
2247
2248 /*
2249 * When the file gets released that means no one else can access the
2250 * blob list any more, so no need to grab dev->blob_lock.
2251 */
2252 list_for_each_entry_safe(blob, bt, &file_priv->blobs, head_file) {
2253 list_del_init(&blob->head_file);
2254 drm_property_unreference_blob(blob);
2255 }
2256}
2257
2258/**
2259 * drm_property_reference_blob - Take a reference on an existing property
2260 *
2261 * Take a new reference on an existing blob property.
2262 *
2263 * @blob: Pointer to blob property
2264 */
2265struct drm_property_blob *drm_property_reference_blob(struct drm_property_blob *blob)
2266{
2267 drm_mode_object_reference(&blob->base);
2268 return blob;
2269}
2270EXPORT_SYMBOL(drm_property_reference_blob);
2271
2272/**
2273 * drm_property_lookup_blob - look up a blob property and take a reference
2274 * @dev: drm device
2275 * @id: id of the blob property
2276 *
2277 * If successful, this takes an additional reference to the blob property.
2278 * callers need to make sure to eventually unreference the returned property
2279 * again, using @drm_property_unreference_blob.
2280 */
2281struct drm_property_blob *drm_property_lookup_blob(struct drm_device *dev,
2282 uint32_t id)
2283{
2284 struct drm_mode_object *obj;
2285 struct drm_property_blob *blob = NULL;
2286
2287 obj = __drm_mode_object_find(dev, id, DRM_MODE_OBJECT_BLOB);
2288 if (obj)
2289 blob = obj_to_blob(obj);
2290 return blob;
2291}
2292EXPORT_SYMBOL(drm_property_lookup_blob);
2293
2294/**
2295 * drm_property_replace_global_blob - atomically replace existing blob property
2296 * @dev: drm device
2297 * @replace: location of blob property pointer to be replaced
2298 * @length: length of data for new blob, or 0 for no data
2299 * @data: content for new blob, or NULL for no data
2300 * @obj_holds_id: optional object for property holding blob ID
2301 * @prop_holds_id: optional property holding blob ID
2302 * @return 0 on success or error on failure
2303 *
2304 * This function will atomically replace a global property in the blob list,
2305 * optionally updating a property which holds the ID of that property. It is
2306 * guaranteed to be atomic: no caller will be allowed to see intermediate
2307 * results, and either the entire operation will succeed and clean up the
2308 * previous property, or it will fail and the state will be unchanged.
2309 *
2310 * If length is 0 or data is NULL, no new blob will be created, and the holding
2311 * property, if specified, will be set to 0.
2312 *
2313 * Access to the replace pointer is assumed to be protected by the caller, e.g.
2314 * by holding the relevant modesetting object lock for its parent.
2315 *
2316 * For example, a drm_connector has a 'PATH' property, which contains the ID
2317 * of a blob property with the value of the MST path information. Calling this
2318 * function with replace pointing to the connector's path_blob_ptr, length and
2319 * data set for the new path information, obj_holds_id set to the connector's
2320 * base object, and prop_holds_id set to the path property name, will perform
2321 * a completely atomic update. The access to path_blob_ptr is protected by the
2322 * caller holding a lock on the connector.
2323 */
2324int drm_property_replace_global_blob(struct drm_device *dev,
2325 struct drm_property_blob **replace,
2326 size_t length,
2327 const void *data,
2328 struct drm_mode_object *obj_holds_id,
2329 struct drm_property *prop_holds_id)
2330{
2331 struct drm_property_blob *new_blob = NULL;
2332 struct drm_property_blob *old_blob = NULL;
2333 int ret;
2334
2335 WARN_ON(replace == NULL);
2336
2337 old_blob = *replace;
2338
2339 if (length && data) {
2340 new_blob = drm_property_create_blob(dev, length, data);
2341 if (IS_ERR(new_blob))
2342 return PTR_ERR(new_blob);
2343 }
2344
2345 /* This does not need to be synchronised with blob_lock, as the
2346 * get_properties ioctl locks all modesetting objects, and
2347 * obj_holds_id must be locked before calling here, so we cannot
2348 * have its value out of sync with the list membership modified
2349 * below under blob_lock. */
2350 if (obj_holds_id) {
2351 ret = drm_object_property_set_value(obj_holds_id,
2352 prop_holds_id,
2353 new_blob ?
2354 new_blob->base.id : 0);
2355 if (ret != 0)
2356 goto err_created;
2357 }
2358
2359 drm_property_unreference_blob(old_blob);
2360 *replace = new_blob;
2361
2362 return 0;
2363
2364err_created:
2365 drm_property_unreference_blob(new_blob);
2366 return ret;
2367}
2368EXPORT_SYMBOL(drm_property_replace_global_blob);
2369
2370/**
2371 * drm_mode_getblob_ioctl - get the contents of a blob property value
2372 * @dev: DRM device
2373 * @data: ioctl data
2374 * @file_priv: DRM file info
2375 *
2376 * This function retrieves the contents of a blob property. The value stored in
2377 * an object's blob property is just a normal modeset object id.
2378 *
2379 * Called by the user via ioctl.
2380 *
2381 * Returns:
2382 * Zero on success, negative errno on failure.
2383 */
2384int drm_mode_getblob_ioctl(struct drm_device *dev,
2385 void *data, struct drm_file *file_priv)
2386{
2387 struct drm_mode_get_blob *out_resp = data;
2388 struct drm_property_blob *blob;
2389 int ret = 0;
2390 void __user *blob_ptr;
2391
2392 if (!drm_core_check_feature(dev, DRIVER_MODESET))
2393 return -EINVAL;
2394
2395 blob = drm_property_lookup_blob(dev, out_resp->blob_id);
2396 if (!blob)
2397 return -ENOENT;
2398
2399 if (out_resp->length == blob->length) {
2400 blob_ptr = (void __user *)(unsigned long)out_resp->data;
2401 if (copy_to_user(blob_ptr, blob->data, blob->length)) {
2402 ret = -EFAULT;
2403 goto unref;
2404 }
2405 }
2406 out_resp->length = blob->length;
2407unref:
2408 drm_property_unreference_blob(blob);
2409
2410 return ret;
2411}
2412
2413/**
2414 * drm_mode_createblob_ioctl - create a new blob property
2415 * @dev: DRM device
2416 * @data: ioctl data
2417 * @file_priv: DRM file info
2418 *
2419 * This function creates a new blob property with user-defined values. In order
2420 * to give us sensible validation and checking when creating, rather than at
2421 * every potential use, we also require a type to be provided upfront.
2422 *
2423 * Called by the user via ioctl.
2424 *
2425 * Returns:
2426 * Zero on success, negative errno on failure.
2427 */
2428int drm_mode_createblob_ioctl(struct drm_device *dev,
2429 void *data, struct drm_file *file_priv)
2430{
2431 struct drm_mode_create_blob *out_resp = data;
2432 struct drm_property_blob *blob;
2433 void __user *blob_ptr;
2434 int ret = 0;
2435
2436 if (!drm_core_check_feature(dev, DRIVER_MODESET))
2437 return -EINVAL;
2438
2439 blob = drm_property_create_blob(dev, out_resp->length, NULL);
2440 if (IS_ERR(blob))
2441 return PTR_ERR(blob);
2442
2443 blob_ptr = (void __user *)(unsigned long)out_resp->data;
2444 if (copy_from_user(blob->data, blob_ptr, out_resp->length)) {
2445 ret = -EFAULT;
2446 goto out_blob;
2447 }
2448
2449 /* Dropping the lock between create_blob and our access here is safe
2450 * as only the same file_priv can remove the blob; at this point, it is
2451 * not associated with any file_priv. */
2452 mutex_lock(&dev->mode_config.blob_lock);
2453 out_resp->blob_id = blob->base.id;
2454 list_add_tail(&blob->head_file, &file_priv->blobs);
2455 mutex_unlock(&dev->mode_config.blob_lock);
2456
2457 return 0;
2458
2459out_blob:
2460 drm_property_unreference_blob(blob);
2461 return ret;
2462}
2463
2464/**
2465 * drm_mode_destroyblob_ioctl - destroy a user blob property
2466 * @dev: DRM device
2467 * @data: ioctl data
2468 * @file_priv: DRM file info
2469 *
2470 * Destroy an existing user-defined blob property.
2471 *
2472 * Called by the user via ioctl.
2473 *
2474 * Returns:
2475 * Zero on success, negative errno on failure.
2476 */
2477int drm_mode_destroyblob_ioctl(struct drm_device *dev,
2478 void *data, struct drm_file *file_priv)
2479{
2480 struct drm_mode_destroy_blob *out_resp = data;
2481 struct drm_property_blob *blob = NULL, *bt;
2482 bool found = false;
2483 int ret = 0;
2484
2485 if (!drm_core_check_feature(dev, DRIVER_MODESET))
2486 return -EINVAL;
2487
2488 blob = drm_property_lookup_blob(dev, out_resp->blob_id);
2489 if (!blob)
2490 return -ENOENT;
2491
2492 mutex_lock(&dev->mode_config.blob_lock);
2493 /* Ensure the property was actually created by this user. */
2494 list_for_each_entry(bt, &file_priv->blobs, head_file) {
2495 if (bt == blob) {
2496 found = true;
2497 break;
2498 }
2499 }
2500
2501 if (!found) {
2502 ret = -EPERM;
2503 goto err;
2504 }
2505
2506 /* We must drop head_file here, because we may not be the last
2507 * reference on the blob. */
2508 list_del_init(&blob->head_file);
2509 mutex_unlock(&dev->mode_config.blob_lock);
2510
2511 /* One reference from lookup, and one from the filp. */
2512 drm_property_unreference_blob(blob);
2513 drm_property_unreference_blob(blob);
2514
2515 return 0;
2516
2517err:
2518 mutex_unlock(&dev->mode_config.blob_lock);
2519 drm_property_unreference_blob(blob);
2520
2521 return ret;
2522}
2523
2524/* Some properties could refer to dynamic refcnt'd objects, or things that
2525 * need special locking to handle lifetime issues (ie. to ensure the prop
2526 * value doesn't become invalid part way through the property update due to
2527 * race). The value returned by reference via 'obj' should be passed back
2528 * to drm_property_change_valid_put() after the property is set (and the
2529 * object to which the property is attached has a chance to take it's own
2530 * reference).
2531 */
2532bool drm_property_change_valid_get(struct drm_property *property,
2533 uint64_t value, struct drm_mode_object **ref)
2534{
2535 int i;
2536
2537 if (property->flags & DRM_MODE_PROP_IMMUTABLE)
2538 return false;
2539
2540 *ref = NULL;
2541
2542 if (drm_property_type_is(property, DRM_MODE_PROP_RANGE)) {
2543 if (value < property->values[0] || value > property->values[1])
2544 return false;
2545 return true;
2546 } else if (drm_property_type_is(property, DRM_MODE_PROP_SIGNED_RANGE)) {
2547 int64_t svalue = U642I64(value);
2548
2549 if (svalue < U642I64(property->values[0]) ||
2550 svalue > U642I64(property->values[1]))
2551 return false;
2552 return true;
2553 } else if (drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) {
2554 uint64_t valid_mask = 0;
2555
2556 for (i = 0; i < property->num_values; i++)
2557 valid_mask |= (1ULL << property->values[i]);
2558 return !(value & ~valid_mask);
2559 } else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB)) {
2560 struct drm_property_blob *blob;
2561
2562 if (value == 0)
2563 return true;
2564
2565 blob = drm_property_lookup_blob(property->dev, value);
2566 if (blob) {
2567 *ref = &blob->base;
2568 return true;
2569 } else {
2570 return false;
2571 }
2572 } else if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) {
2573 /* a zero value for an object property translates to null: */
2574 if (value == 0)
2575 return true;
2576
2577 *ref = __drm_mode_object_find(property->dev, value,
2578 property->values[0]);
2579 return *ref != NULL;
2580 }
2581
2582 for (i = 0; i < property->num_values; i++)
2583 if (property->values[i] == value)
2584 return true;
2585 return false;
2586}
2587
2588void drm_property_change_valid_put(struct drm_property *property,
2589 struct drm_mode_object *ref)
2590{
2591 if (!ref)
2592 return;
2593
2594 if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) {
2595 drm_mode_object_unreference(ref);
2596 } else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB))
2597 drm_property_unreference_blob(obj_to_blob(ref));
2598}
2599
2600int drm_mode_crtc_set_obj_prop(struct drm_mode_object *obj, 1674int drm_mode_crtc_set_obj_prop(struct drm_mode_object *obj,
2601 struct drm_property *property, 1675 struct drm_property *property,
2602 uint64_t value) 1676 uint64_t value)
diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h
index 2eb1d941ea70..a3622644bccf 100644
--- a/drivers/gpu/drm/drm_crtc_internal.h
+++ b/drivers/gpu/drm/drm_crtc_internal.h
@@ -36,11 +36,6 @@
36int drm_mode_crtc_set_obj_prop(struct drm_mode_object *obj, 36int drm_mode_crtc_set_obj_prop(struct drm_mode_object *obj,
37 struct drm_property *property, 37 struct drm_property *property,
38 uint64_t value); 38 uint64_t value);
39bool drm_property_change_valid_get(struct drm_property *property,
40 uint64_t value,
41 struct drm_mode_object **ref);
42void drm_property_change_valid_put(struct drm_property *property,
43 struct drm_mode_object *ref);
44int drm_plane_check_pixel_format(const struct drm_plane *plane, 39int drm_plane_check_pixel_format(const struct drm_plane *plane,
45 u32 format); 40 u32 format);
46int drm_crtc_check_viewport(const struct drm_crtc *crtc, 41int drm_crtc_check_viewport(const struct drm_crtc *crtc,
@@ -49,8 +44,6 @@ int drm_crtc_check_viewport(const struct drm_crtc *crtc,
49 const struct drm_framebuffer *fb); 44 const struct drm_framebuffer *fb);
50 45
51void drm_fb_release(struct drm_file *file_priv); 46void drm_fb_release(struct drm_file *file_priv);
52void drm_property_destroy_user_blobs(struct drm_device *dev,
53 struct drm_file *file_priv);
54 47
55/* dumb buffer support IOCTLs */ 48/* dumb buffer support IOCTLs */
56int drm_mode_create_dumb_ioctl(struct drm_device *dev, 49int drm_mode_create_dumb_ioctl(struct drm_device *dev,
@@ -77,6 +70,24 @@ int drm_mode_cursor_ioctl(struct drm_device *dev,
77 void *data, struct drm_file *file_priv); 70 void *data, struct drm_file *file_priv);
78int drm_mode_cursor2_ioctl(struct drm_device *dev, 71int drm_mode_cursor2_ioctl(struct drm_device *dev,
79 void *data, struct drm_file *file_priv); 72 void *data, struct drm_file *file_priv);
73int drm_mode_gamma_get_ioctl(struct drm_device *dev,
74 void *data, struct drm_file *file_priv);
75int drm_mode_gamma_set_ioctl(struct drm_device *dev,
76 void *data, struct drm_file *file_priv);
77
78int drm_mode_page_flip_ioctl(struct drm_device *dev,
79 void *data, struct drm_file *file_priv);
80
81/* drm_property.c */
82void drm_property_destroy_user_blobs(struct drm_device *dev,
83 struct drm_file *file_priv);
84bool drm_property_change_valid_get(struct drm_property *property,
85 uint64_t value,
86 struct drm_mode_object **ref);
87void drm_property_change_valid_put(struct drm_property *property,
88 struct drm_mode_object *ref);
89
90/* IOCTL */
80int drm_mode_getproperty_ioctl(struct drm_device *dev, 91int drm_mode_getproperty_ioctl(struct drm_device *dev,
81 void *data, struct drm_file *file_priv); 92 void *data, struct drm_file *file_priv);
82int drm_mode_getblob_ioctl(struct drm_device *dev, 93int drm_mode_getblob_ioctl(struct drm_device *dev,
@@ -85,13 +96,6 @@ int drm_mode_createblob_ioctl(struct drm_device *dev,
85 void *data, struct drm_file *file_priv); 96 void *data, struct drm_file *file_priv);
86int drm_mode_destroyblob_ioctl(struct drm_device *dev, 97int drm_mode_destroyblob_ioctl(struct drm_device *dev,
87 void *data, struct drm_file *file_priv); 98 void *data, struct drm_file *file_priv);
88int drm_mode_gamma_get_ioctl(struct drm_device *dev,
89 void *data, struct drm_file *file_priv);
90int drm_mode_gamma_set_ioctl(struct drm_device *dev,
91 void *data, struct drm_file *file_priv);
92
93int drm_mode_page_flip_ioctl(struct drm_device *dev,
94 void *data, struct drm_file *file_priv);
95 99
96/* drm_mode_object.c */ 100/* drm_mode_object.c */
97int drm_mode_object_get_reg(struct drm_device *dev, 101int drm_mode_object_get_reg(struct drm_device *dev,
diff --git a/drivers/gpu/drm/drm_property.c b/drivers/gpu/drm/drm_property.c
new file mode 100644
index 000000000000..162cc9032ae5
--- /dev/null
+++ b/drivers/gpu/drm/drm_property.c
@@ -0,0 +1,953 @@
1/*
2 * Copyright (c) 2016 Intel Corporation
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting documentation, and
8 * that the name of the copyright holders not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission. The copyright holders make no representations
11 * about the suitability of this software for any purpose. It is provided "as
12 * is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20 * OF THIS SOFTWARE.
21 */
22
23#include <linux/export.h>
24#include <drm/drmP.h>
25#include <drm/drm_property.h>
26
27#include "drm_crtc_internal.h"
28
29static bool drm_property_type_valid(struct drm_property *property)
30{
31 if (property->flags & DRM_MODE_PROP_EXTENDED_TYPE)
32 return !(property->flags & DRM_MODE_PROP_LEGACY_TYPE);
33 return !!(property->flags & DRM_MODE_PROP_LEGACY_TYPE);
34}
35
36/**
37 * drm_property_create - create a new property type
38 * @dev: drm device
39 * @flags: flags specifying the property type
40 * @name: name of the property
41 * @num_values: number of pre-defined values
42 *
43 * This creates a new generic drm property which can then be attached to a drm
44 * object with drm_object_attach_property. The returned property object must be
45 * freed with drm_property_destroy.
46 *
47 * Note that the DRM core keeps a per-device list of properties and that, if
48 * drm_mode_config_cleanup() is called, it will destroy all properties created
49 * by the driver.
50 *
51 * Returns:
52 * A pointer to the newly created property on success, NULL on failure.
53 */
54struct drm_property *drm_property_create(struct drm_device *dev, int flags,
55 const char *name, int num_values)
56{
57 struct drm_property *property = NULL;
58 int ret;
59
60 property = kzalloc(sizeof(struct drm_property), GFP_KERNEL);
61 if (!property)
62 return NULL;
63
64 property->dev = dev;
65
66 if (num_values) {
67 property->values = kcalloc(num_values, sizeof(uint64_t),
68 GFP_KERNEL);
69 if (!property->values)
70 goto fail;
71 }
72
73 ret = drm_mode_object_get(dev, &property->base, DRM_MODE_OBJECT_PROPERTY);
74 if (ret)
75 goto fail;
76
77 property->flags = flags;
78 property->num_values = num_values;
79 INIT_LIST_HEAD(&property->enum_list);
80
81 if (name) {
82 strncpy(property->name, name, DRM_PROP_NAME_LEN);
83 property->name[DRM_PROP_NAME_LEN-1] = '\0';
84 }
85
86 list_add_tail(&property->head, &dev->mode_config.property_list);
87
88 WARN_ON(!drm_property_type_valid(property));
89
90 return property;
91fail:
92 kfree(property->values);
93 kfree(property);
94 return NULL;
95}
96EXPORT_SYMBOL(drm_property_create);
97
98/**
99 * drm_property_create_enum - create a new enumeration property type
100 * @dev: drm device
101 * @flags: flags specifying the property type
102 * @name: name of the property
103 * @props: enumeration lists with property values
104 * @num_values: number of pre-defined values
105 *
106 * This creates a new generic drm property which can then be attached to a drm
107 * object with drm_object_attach_property. The returned property object must be
108 * freed with drm_property_destroy.
109 *
110 * Userspace is only allowed to set one of the predefined values for enumeration
111 * properties.
112 *
113 * Returns:
114 * A pointer to the newly created property on success, NULL on failure.
115 */
116struct drm_property *drm_property_create_enum(struct drm_device *dev, int flags,
117 const char *name,
118 const struct drm_prop_enum_list *props,
119 int num_values)
120{
121 struct drm_property *property;
122 int i, ret;
123
124 flags |= DRM_MODE_PROP_ENUM;
125
126 property = drm_property_create(dev, flags, name, num_values);
127 if (!property)
128 return NULL;
129
130 for (i = 0; i < num_values; i++) {
131 ret = drm_property_add_enum(property, i,
132 props[i].type,
133 props[i].name);
134 if (ret) {
135 drm_property_destroy(dev, property);
136 return NULL;
137 }
138 }
139
140 return property;
141}
142EXPORT_SYMBOL(drm_property_create_enum);
143
144/**
145 * drm_property_create_bitmask - create a new bitmask property type
146 * @dev: drm device
147 * @flags: flags specifying the property type
148 * @name: name of the property
149 * @props: enumeration lists with property bitflags
150 * @num_props: size of the @props array
151 * @supported_bits: bitmask of all supported enumeration values
152 *
153 * This creates a new bitmask drm property which can then be attached to a drm
154 * object with drm_object_attach_property. The returned property object must be
155 * freed with drm_property_destroy.
156 *
157 * Compared to plain enumeration properties userspace is allowed to set any
158 * or'ed together combination of the predefined property bitflag values
159 *
160 * Returns:
161 * A pointer to the newly created property on success, NULL on failure.
162 */
163struct drm_property *drm_property_create_bitmask(struct drm_device *dev,
164 int flags, const char *name,
165 const struct drm_prop_enum_list *props,
166 int num_props,
167 uint64_t supported_bits)
168{
169 struct drm_property *property;
170 int i, ret, index = 0;
171 int num_values = hweight64(supported_bits);
172
173 flags |= DRM_MODE_PROP_BITMASK;
174
175 property = drm_property_create(dev, flags, name, num_values);
176 if (!property)
177 return NULL;
178 for (i = 0; i < num_props; i++) {
179 if (!(supported_bits & (1ULL << props[i].type)))
180 continue;
181
182 if (WARN_ON(index >= num_values)) {
183 drm_property_destroy(dev, property);
184 return NULL;
185 }
186
187 ret = drm_property_add_enum(property, index++,
188 props[i].type,
189 props[i].name);
190 if (ret) {
191 drm_property_destroy(dev, property);
192 return NULL;
193 }
194 }
195
196 return property;
197}
198EXPORT_SYMBOL(drm_property_create_bitmask);
199
200static struct drm_property *property_create_range(struct drm_device *dev,
201 int flags, const char *name,
202 uint64_t min, uint64_t max)
203{
204 struct drm_property *property;
205
206 property = drm_property_create(dev, flags, name, 2);
207 if (!property)
208 return NULL;
209
210 property->values[0] = min;
211 property->values[1] = max;
212
213 return property;
214}
215
216/**
217 * drm_property_create_range - create a new unsigned ranged property type
218 * @dev: drm device
219 * @flags: flags specifying the property type
220 * @name: name of the property
221 * @min: minimum value of the property
222 * @max: maximum value of the property
223 *
224 * This creates a new generic drm property which can then be attached to a drm
225 * object with drm_object_attach_property. The returned property object must be
226 * freed with drm_property_destroy.
227 *
228 * Userspace is allowed to set any unsigned integer value in the (min, max)
229 * range inclusive.
230 *
231 * Returns:
232 * A pointer to the newly created property on success, NULL on failure.
233 */
234struct drm_property *drm_property_create_range(struct drm_device *dev, int flags,
235 const char *name,
236 uint64_t min, uint64_t max)
237{
238 return property_create_range(dev, DRM_MODE_PROP_RANGE | flags,
239 name, min, max);
240}
241EXPORT_SYMBOL(drm_property_create_range);
242
243/**
244 * drm_property_create_signed_range - create a new signed ranged property type
245 * @dev: drm device
246 * @flags: flags specifying the property type
247 * @name: name of the property
248 * @min: minimum value of the property
249 * @max: maximum value of the property
250 *
251 * This creates a new generic drm property which can then be attached to a drm
252 * object with drm_object_attach_property. The returned property object must be
253 * freed with drm_property_destroy.
254 *
255 * Userspace is allowed to set any signed integer value in the (min, max)
256 * range inclusive.
257 *
258 * Returns:
259 * A pointer to the newly created property on success, NULL on failure.
260 */
261struct drm_property *drm_property_create_signed_range(struct drm_device *dev,
262 int flags, const char *name,
263 int64_t min, int64_t max)
264{
265 return property_create_range(dev, DRM_MODE_PROP_SIGNED_RANGE | flags,
266 name, I642U64(min), I642U64(max));
267}
268EXPORT_SYMBOL(drm_property_create_signed_range);
269
270/**
271 * drm_property_create_object - create a new object property type
272 * @dev: drm device
273 * @flags: flags specifying the property type
274 * @name: name of the property
275 * @type: object type from DRM_MODE_OBJECT_* defines
276 *
277 * This creates a new generic drm property which can then be attached to a drm
278 * object with drm_object_attach_property. The returned property object must be
279 * freed with drm_property_destroy.
280 *
281 * Userspace is only allowed to set this to any property value of the given
282 * @type. Only useful for atomic properties, which is enforced.
283 *
284 * Returns:
285 * A pointer to the newly created property on success, NULL on failure.
286 */
287struct drm_property *drm_property_create_object(struct drm_device *dev,
288 int flags, const char *name, uint32_t type)
289{
290 struct drm_property *property;
291
292 flags |= DRM_MODE_PROP_OBJECT;
293
294 if (WARN_ON(!(flags & DRM_MODE_PROP_ATOMIC)))
295 return NULL;
296
297 property = drm_property_create(dev, flags, name, 1);
298 if (!property)
299 return NULL;
300
301 property->values[0] = type;
302
303 return property;
304}
305EXPORT_SYMBOL(drm_property_create_object);
306
307/**
308 * drm_property_create_bool - create a new boolean property type
309 * @dev: drm device
310 * @flags: flags specifying the property type
311 * @name: name of the property
312 *
313 * This creates a new generic drm property which can then be attached to a drm
314 * object with drm_object_attach_property. The returned property object must be
315 * freed with drm_property_destroy.
316 *
317 * This is implemented as a ranged property with only {0, 1} as valid values.
318 *
319 * Returns:
320 * A pointer to the newly created property on success, NULL on failure.
321 */
322struct drm_property *drm_property_create_bool(struct drm_device *dev, int flags,
323 const char *name)
324{
325 return drm_property_create_range(dev, flags, name, 0, 1);
326}
327EXPORT_SYMBOL(drm_property_create_bool);
328
329/**
330 * drm_property_add_enum - add a possible value to an enumeration property
331 * @property: enumeration property to change
332 * @index: index of the new enumeration
333 * @value: value of the new enumeration
334 * @name: symbolic name of the new enumeration
335 *
336 * This functions adds enumerations to a property.
337 *
338 * It's use is deprecated, drivers should use one of the more specific helpers
339 * to directly create the property with all enumerations already attached.
340 *
341 * Returns:
342 * Zero on success, error code on failure.
343 */
344int drm_property_add_enum(struct drm_property *property, int index,
345 uint64_t value, const char *name)
346{
347 struct drm_property_enum *prop_enum;
348
349 if (!(drm_property_type_is(property, DRM_MODE_PROP_ENUM) ||
350 drm_property_type_is(property, DRM_MODE_PROP_BITMASK)))
351 return -EINVAL;
352
353 /*
354 * Bitmask enum properties have the additional constraint of values
355 * from 0 to 63
356 */
357 if (drm_property_type_is(property, DRM_MODE_PROP_BITMASK) &&
358 (value > 63))
359 return -EINVAL;
360
361 if (!list_empty(&property->enum_list)) {
362 list_for_each_entry(prop_enum, &property->enum_list, head) {
363 if (prop_enum->value == value) {
364 strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN);
365 prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0';
366 return 0;
367 }
368 }
369 }
370
371 prop_enum = kzalloc(sizeof(struct drm_property_enum), GFP_KERNEL);
372 if (!prop_enum)
373 return -ENOMEM;
374
375 strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN);
376 prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0';
377 prop_enum->value = value;
378
379 property->values[index] = value;
380 list_add_tail(&prop_enum->head, &property->enum_list);
381 return 0;
382}
383EXPORT_SYMBOL(drm_property_add_enum);
384
385/**
386 * drm_property_destroy - destroy a drm property
387 * @dev: drm device
388 * @property: property to destry
389 *
390 * This function frees a property including any attached resources like
391 * enumeration values.
392 */
393void drm_property_destroy(struct drm_device *dev, struct drm_property *property)
394{
395 struct drm_property_enum *prop_enum, *pt;
396
397 list_for_each_entry_safe(prop_enum, pt, &property->enum_list, head) {
398 list_del(&prop_enum->head);
399 kfree(prop_enum);
400 }
401
402 if (property->num_values)
403 kfree(property->values);
404 drm_mode_object_unregister(dev, &property->base);
405 list_del(&property->head);
406 kfree(property);
407}
408EXPORT_SYMBOL(drm_property_destroy);
409
410/**
411 * drm_mode_getproperty_ioctl - get the property metadata
412 * @dev: DRM device
413 * @data: ioctl data
414 * @file_priv: DRM file info
415 *
416 * This function retrieves the metadata for a given property, like the different
417 * possible values for an enum property or the limits for a range property.
418 *
419 * Blob properties are special
420 *
421 * Called by the user via ioctl.
422 *
423 * Returns:
424 * Zero on success, negative errno on failure.
425 */
426int drm_mode_getproperty_ioctl(struct drm_device *dev,
427 void *data, struct drm_file *file_priv)
428{
429 struct drm_mode_get_property *out_resp = data;
430 struct drm_property *property;
431 int enum_count = 0;
432 int value_count = 0;
433 int ret = 0, i;
434 int copied;
435 struct drm_property_enum *prop_enum;
436 struct drm_mode_property_enum __user *enum_ptr;
437 uint64_t __user *values_ptr;
438
439 if (!drm_core_check_feature(dev, DRIVER_MODESET))
440 return -EINVAL;
441
442 drm_modeset_lock_all(dev);
443 property = drm_property_find(dev, out_resp->prop_id);
444 if (!property) {
445 ret = -ENOENT;
446 goto done;
447 }
448
449 if (drm_property_type_is(property, DRM_MODE_PROP_ENUM) ||
450 drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) {
451 list_for_each_entry(prop_enum, &property->enum_list, head)
452 enum_count++;
453 }
454
455 value_count = property->num_values;
456
457 strncpy(out_resp->name, property->name, DRM_PROP_NAME_LEN);
458 out_resp->name[DRM_PROP_NAME_LEN-1] = 0;
459 out_resp->flags = property->flags;
460
461 if ((out_resp->count_values >= value_count) && value_count) {
462 values_ptr = (uint64_t __user *)(unsigned long)out_resp->values_ptr;
463 for (i = 0; i < value_count; i++) {
464 if (copy_to_user(values_ptr + i, &property->values[i], sizeof(uint64_t))) {
465 ret = -EFAULT;
466 goto done;
467 }
468 }
469 }
470 out_resp->count_values = value_count;
471
472 if (drm_property_type_is(property, DRM_MODE_PROP_ENUM) ||
473 drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) {
474 if ((out_resp->count_enum_blobs >= enum_count) && enum_count) {
475 copied = 0;
476 enum_ptr = (struct drm_mode_property_enum __user *)(unsigned long)out_resp->enum_blob_ptr;
477 list_for_each_entry(prop_enum, &property->enum_list, head) {
478
479 if (copy_to_user(&enum_ptr[copied].value, &prop_enum->value, sizeof(uint64_t))) {
480 ret = -EFAULT;
481 goto done;
482 }
483
484 if (copy_to_user(&enum_ptr[copied].name,
485 &prop_enum->name, DRM_PROP_NAME_LEN)) {
486 ret = -EFAULT;
487 goto done;
488 }
489 copied++;
490 }
491 }
492 out_resp->count_enum_blobs = enum_count;
493 }
494
495 /*
496 * NOTE: The idea seems to have been to use this to read all the blob
497 * property values. But nothing ever added them to the corresponding
498 * list, userspace always used the special-purpose get_blob ioctl to
499 * read the value for a blob property. It also doesn't make a lot of
500 * sense to return values here when everything else is just metadata for
501 * the property itself.
502 */
503 if (drm_property_type_is(property, DRM_MODE_PROP_BLOB))
504 out_resp->count_enum_blobs = 0;
505done:
506 drm_modeset_unlock_all(dev);
507 return ret;
508}
509
510static void drm_property_free_blob(struct kref *kref)
511{
512 struct drm_property_blob *blob =
513 container_of(kref, struct drm_property_blob, base.refcount);
514
515 mutex_lock(&blob->dev->mode_config.blob_lock);
516 list_del(&blob->head_global);
517 mutex_unlock(&blob->dev->mode_config.blob_lock);
518
519 drm_mode_object_unregister(blob->dev, &blob->base);
520
521 kfree(blob);
522}
523
524/**
525 * drm_property_create_blob - Create new blob property
526 *
527 * Creates a new blob property for a specified DRM device, optionally
528 * copying data.
529 *
530 * @dev: DRM device to create property for
531 * @length: Length to allocate for blob data
532 * @data: If specified, copies data into blob
533 *
534 * Returns:
535 * New blob property with a single reference on success, or an ERR_PTR
536 * value on failure.
537 */
538struct drm_property_blob *
539drm_property_create_blob(struct drm_device *dev, size_t length,
540 const void *data)
541{
542 struct drm_property_blob *blob;
543 int ret;
544
545 if (!length || length > ULONG_MAX - sizeof(struct drm_property_blob))
546 return ERR_PTR(-EINVAL);
547
548 blob = kzalloc(sizeof(struct drm_property_blob)+length, GFP_KERNEL);
549 if (!blob)
550 return ERR_PTR(-ENOMEM);
551
552 /* This must be explicitly initialised, so we can safely call list_del
553 * on it in the removal handler, even if it isn't in a file list. */
554 INIT_LIST_HEAD(&blob->head_file);
555 blob->length = length;
556 blob->dev = dev;
557
558 if (data)
559 memcpy(blob->data, data, length);
560
561 ret = drm_mode_object_get_reg(dev, &blob->base, DRM_MODE_OBJECT_BLOB,
562 true, drm_property_free_blob);
563 if (ret) {
564 kfree(blob);
565 return ERR_PTR(-EINVAL);
566 }
567
568 mutex_lock(&dev->mode_config.blob_lock);
569 list_add_tail(&blob->head_global,
570 &dev->mode_config.property_blob_list);
571 mutex_unlock(&dev->mode_config.blob_lock);
572
573 return blob;
574}
575EXPORT_SYMBOL(drm_property_create_blob);
576
577/**
578 * drm_property_unreference_blob - Unreference a blob property
579 *
580 * Drop a reference on a blob property. May free the object.
581 *
582 * @blob: Pointer to blob property
583 */
584void drm_property_unreference_blob(struct drm_property_blob *blob)
585{
586 if (!blob)
587 return;
588
589 drm_mode_object_unreference(&blob->base);
590}
591EXPORT_SYMBOL(drm_property_unreference_blob);
592
593/**
594 * drm_property_destroy_user_blobs - destroy all blobs created by this client
595 * @dev: DRM device
596 * @file_priv: destroy all blobs owned by this file handle
597 */
598void drm_property_destroy_user_blobs(struct drm_device *dev,
599 struct drm_file *file_priv)
600{
601 struct drm_property_blob *blob, *bt;
602
603 /*
604 * When the file gets released that means no one else can access the
605 * blob list any more, so no need to grab dev->blob_lock.
606 */
607 list_for_each_entry_safe(blob, bt, &file_priv->blobs, head_file) {
608 list_del_init(&blob->head_file);
609 drm_property_unreference_blob(blob);
610 }
611}
612
613/**
614 * drm_property_reference_blob - Take a reference on an existing property
615 *
616 * Take a new reference on an existing blob property.
617 *
618 * @blob: Pointer to blob property
619 */
620struct drm_property_blob *drm_property_reference_blob(struct drm_property_blob *blob)
621{
622 drm_mode_object_reference(&blob->base);
623 return blob;
624}
625EXPORT_SYMBOL(drm_property_reference_blob);
626
627/**
628 * drm_property_lookup_blob - look up a blob property and take a reference
629 * @dev: drm device
630 * @id: id of the blob property
631 *
632 * If successful, this takes an additional reference to the blob property.
633 * callers need to make sure to eventually unreference the returned property
634 * again, using @drm_property_unreference_blob.
635 */
636struct drm_property_blob *drm_property_lookup_blob(struct drm_device *dev,
637 uint32_t id)
638{
639 struct drm_mode_object *obj;
640 struct drm_property_blob *blob = NULL;
641
642 obj = __drm_mode_object_find(dev, id, DRM_MODE_OBJECT_BLOB);
643 if (obj)
644 blob = obj_to_blob(obj);
645 return blob;
646}
647EXPORT_SYMBOL(drm_property_lookup_blob);
648
649/**
650 * drm_property_replace_global_blob - atomically replace existing blob property
651 * @dev: drm device
652 * @replace: location of blob property pointer to be replaced
653 * @length: length of data for new blob, or 0 for no data
654 * @data: content for new blob, or NULL for no data
655 * @obj_holds_id: optional object for property holding blob ID
656 * @prop_holds_id: optional property holding blob ID
657 * @return 0 on success or error on failure
658 *
659 * This function will atomically replace a global property in the blob list,
660 * optionally updating a property which holds the ID of that property. It is
661 * guaranteed to be atomic: no caller will be allowed to see intermediate
662 * results, and either the entire operation will succeed and clean up the
663 * previous property, or it will fail and the state will be unchanged.
664 *
665 * If length is 0 or data is NULL, no new blob will be created, and the holding
666 * property, if specified, will be set to 0.
667 *
668 * Access to the replace pointer is assumed to be protected by the caller, e.g.
669 * by holding the relevant modesetting object lock for its parent.
670 *
671 * For example, a drm_connector has a 'PATH' property, which contains the ID
672 * of a blob property with the value of the MST path information. Calling this
673 * function with replace pointing to the connector's path_blob_ptr, length and
674 * data set for the new path information, obj_holds_id set to the connector's
675 * base object, and prop_holds_id set to the path property name, will perform
676 * a completely atomic update. The access to path_blob_ptr is protected by the
677 * caller holding a lock on the connector.
678 */
679int drm_property_replace_global_blob(struct drm_device *dev,
680 struct drm_property_blob **replace,
681 size_t length,
682 const void *data,
683 struct drm_mode_object *obj_holds_id,
684 struct drm_property *prop_holds_id)
685{
686 struct drm_property_blob *new_blob = NULL;
687 struct drm_property_blob *old_blob = NULL;
688 int ret;
689
690 WARN_ON(replace == NULL);
691
692 old_blob = *replace;
693
694 if (length && data) {
695 new_blob = drm_property_create_blob(dev, length, data);
696 if (IS_ERR(new_blob))
697 return PTR_ERR(new_blob);
698 }
699
700 /* This does not need to be synchronised with blob_lock, as the
701 * get_properties ioctl locks all modesetting objects, and
702 * obj_holds_id must be locked before calling here, so we cannot
703 * have its value out of sync with the list membership modified
704 * below under blob_lock. */
705 if (obj_holds_id) {
706 ret = drm_object_property_set_value(obj_holds_id,
707 prop_holds_id,
708 new_blob ?
709 new_blob->base.id : 0);
710 if (ret != 0)
711 goto err_created;
712 }
713
714 drm_property_unreference_blob(old_blob);
715 *replace = new_blob;
716
717 return 0;
718
719err_created:
720 drm_property_unreference_blob(new_blob);
721 return ret;
722}
723EXPORT_SYMBOL(drm_property_replace_global_blob);
724
725/**
726 * drm_mode_getblob_ioctl - get the contents of a blob property value
727 * @dev: DRM device
728 * @data: ioctl data
729 * @file_priv: DRM file info
730 *
731 * This function retrieves the contents of a blob property. The value stored in
732 * an object's blob property is just a normal modeset object id.
733 *
734 * Called by the user via ioctl.
735 *
736 * Returns:
737 * Zero on success, negative errno on failure.
738 */
739int drm_mode_getblob_ioctl(struct drm_device *dev,
740 void *data, struct drm_file *file_priv)
741{
742 struct drm_mode_get_blob *out_resp = data;
743 struct drm_property_blob *blob;
744 int ret = 0;
745 void __user *blob_ptr;
746
747 if (!drm_core_check_feature(dev, DRIVER_MODESET))
748 return -EINVAL;
749
750 blob = drm_property_lookup_blob(dev, out_resp->blob_id);
751 if (!blob)
752 return -ENOENT;
753
754 if (out_resp->length == blob->length) {
755 blob_ptr = (void __user *)(unsigned long)out_resp->data;
756 if (copy_to_user(blob_ptr, blob->data, blob->length)) {
757 ret = -EFAULT;
758 goto unref;
759 }
760 }
761 out_resp->length = blob->length;
762unref:
763 drm_property_unreference_blob(blob);
764
765 return ret;
766}
767
768/**
769 * drm_mode_createblob_ioctl - create a new blob property
770 * @dev: DRM device
771 * @data: ioctl data
772 * @file_priv: DRM file info
773 *
774 * This function creates a new blob property with user-defined values. In order
775 * to give us sensible validation and checking when creating, rather than at
776 * every potential use, we also require a type to be provided upfront.
777 *
778 * Called by the user via ioctl.
779 *
780 * Returns:
781 * Zero on success, negative errno on failure.
782 */
783int drm_mode_createblob_ioctl(struct drm_device *dev,
784 void *data, struct drm_file *file_priv)
785{
786 struct drm_mode_create_blob *out_resp = data;
787 struct drm_property_blob *blob;
788 void __user *blob_ptr;
789 int ret = 0;
790
791 if (!drm_core_check_feature(dev, DRIVER_MODESET))
792 return -EINVAL;
793
794 blob = drm_property_create_blob(dev, out_resp->length, NULL);
795 if (IS_ERR(blob))
796 return PTR_ERR(blob);
797
798 blob_ptr = (void __user *)(unsigned long)out_resp->data;
799 if (copy_from_user(blob->data, blob_ptr, out_resp->length)) {
800 ret = -EFAULT;
801 goto out_blob;
802 }
803
804 /* Dropping the lock between create_blob and our access here is safe
805 * as only the same file_priv can remove the blob; at this point, it is
806 * not associated with any file_priv. */
807 mutex_lock(&dev->mode_config.blob_lock);
808 out_resp->blob_id = blob->base.id;
809 list_add_tail(&blob->head_file, &file_priv->blobs);
810 mutex_unlock(&dev->mode_config.blob_lock);
811
812 return 0;
813
814out_blob:
815 drm_property_unreference_blob(blob);
816 return ret;
817}
818
819/**
820 * drm_mode_destroyblob_ioctl - destroy a user blob property
821 * @dev: DRM device
822 * @data: ioctl data
823 * @file_priv: DRM file info
824 *
825 * Destroy an existing user-defined blob property.
826 *
827 * Called by the user via ioctl.
828 *
829 * Returns:
830 * Zero on success, negative errno on failure.
831 */
832int drm_mode_destroyblob_ioctl(struct drm_device *dev,
833 void *data, struct drm_file *file_priv)
834{
835 struct drm_mode_destroy_blob *out_resp = data;
836 struct drm_property_blob *blob = NULL, *bt;
837 bool found = false;
838 int ret = 0;
839
840 if (!drm_core_check_feature(dev, DRIVER_MODESET))
841 return -EINVAL;
842
843 blob = drm_property_lookup_blob(dev, out_resp->blob_id);
844 if (!blob)
845 return -ENOENT;
846
847 mutex_lock(&dev->mode_config.blob_lock);
848 /* Ensure the property was actually created by this user. */
849 list_for_each_entry(bt, &file_priv->blobs, head_file) {
850 if (bt == blob) {
851 found = true;
852 break;
853 }
854 }
855
856 if (!found) {
857 ret = -EPERM;
858 goto err;
859 }
860
861 /* We must drop head_file here, because we may not be the last
862 * reference on the blob. */
863 list_del_init(&blob->head_file);
864 mutex_unlock(&dev->mode_config.blob_lock);
865
866 /* One reference from lookup, and one from the filp. */
867 drm_property_unreference_blob(blob);
868 drm_property_unreference_blob(blob);
869
870 return 0;
871
872err:
873 mutex_unlock(&dev->mode_config.blob_lock);
874 drm_property_unreference_blob(blob);
875
876 return ret;
877}
878
879/* Some properties could refer to dynamic refcnt'd objects, or things that
880 * need special locking to handle lifetime issues (ie. to ensure the prop
881 * value doesn't become invalid part way through the property update due to
882 * race). The value returned by reference via 'obj' should be passed back
883 * to drm_property_change_valid_put() after the property is set (and the
884 * object to which the property is attached has a chance to take it's own
885 * reference).
886 */
887bool drm_property_change_valid_get(struct drm_property *property,
888 uint64_t value, struct drm_mode_object **ref)
889{
890 int i;
891
892 if (property->flags & DRM_MODE_PROP_IMMUTABLE)
893 return false;
894
895 *ref = NULL;
896
897 if (drm_property_type_is(property, DRM_MODE_PROP_RANGE)) {
898 if (value < property->values[0] || value > property->values[1])
899 return false;
900 return true;
901 } else if (drm_property_type_is(property, DRM_MODE_PROP_SIGNED_RANGE)) {
902 int64_t svalue = U642I64(value);
903
904 if (svalue < U642I64(property->values[0]) ||
905 svalue > U642I64(property->values[1]))
906 return false;
907 return true;
908 } else if (drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) {
909 uint64_t valid_mask = 0;
910
911 for (i = 0; i < property->num_values; i++)
912 valid_mask |= (1ULL << property->values[i]);
913 return !(value & ~valid_mask);
914 } else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB)) {
915 struct drm_property_blob *blob;
916
917 if (value == 0)
918 return true;
919
920 blob = drm_property_lookup_blob(property->dev, value);
921 if (blob) {
922 *ref = &blob->base;
923 return true;
924 } else {
925 return false;
926 }
927 } else if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) {
928 /* a zero value for an object property translates to null: */
929 if (value == 0)
930 return true;
931
932 *ref = __drm_mode_object_find(property->dev, value,
933 property->values[0]);
934 return *ref != NULL;
935 }
936
937 for (i = 0; i < property->num_values; i++)
938 if (property->values[i] == value)
939 return true;
940 return false;
941}
942
943void drm_property_change_valid_put(struct drm_property *property,
944 struct drm_mode_object *ref)
945{
946 if (!ref)
947 return;
948
949 if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) {
950 drm_mode_object_unreference(ref);
951 } else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB))
952 drm_property_unreference_blob(obj_to_blob(ref));
953}
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 63f03490e987..3d33c90da9e5 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -41,6 +41,7 @@
41#include <drm/drm_modes.h> 41#include <drm/drm_modes.h>
42#include <drm/drm_connector.h> 42#include <drm/drm_connector.h>
43#include <drm/drm_encoder.h> 43#include <drm/drm_encoder.h>
44#include <drm/drm_property.h>
44 45
45struct drm_device; 46struct drm_device;
46struct drm_mode_set; 47struct drm_mode_set;
@@ -82,33 +83,6 @@ struct drm_tile_group {
82 u8 group_data[8]; 83 u8 group_data[8];
83}; 84};
84 85
85struct drm_property_blob {
86 struct drm_mode_object base;
87 struct drm_device *dev;
88 struct list_head head_global;
89 struct list_head head_file;
90 size_t length;
91 unsigned char data[];
92};
93
94struct drm_property_enum {
95 uint64_t value;
96 struct list_head head;
97 char name[DRM_PROP_NAME_LEN];
98};
99
100struct drm_property {
101 struct list_head head;
102 struct drm_mode_object base;
103 uint32_t flags;
104 char name[DRM_PROP_NAME_LEN];
105 uint32_t num_values;
106 uint64_t *values;
107 struct drm_device *dev;
108
109 struct list_head enum_list;
110};
111
112struct drm_crtc; 86struct drm_crtc;
113struct drm_encoder; 87struct drm_encoder;
114struct drm_pending_vblank_event; 88struct drm_pending_vblank_event;
@@ -2026,15 +2000,9 @@ struct drm_mode_config {
2026#define obj_to_crtc(x) container_of(x, struct drm_crtc, base) 2000#define obj_to_crtc(x) container_of(x, struct drm_crtc, base)
2027#define obj_to_mode(x) container_of(x, struct drm_display_mode, base) 2001#define obj_to_mode(x) container_of(x, struct drm_display_mode, base)
2028#define obj_to_fb(x) container_of(x, struct drm_framebuffer, base) 2002#define obj_to_fb(x) container_of(x, struct drm_framebuffer, base)
2029#define obj_to_property(x) container_of(x, struct drm_property, base)
2030#define obj_to_blob(x) container_of(x, struct drm_property_blob, base) 2003#define obj_to_blob(x) container_of(x, struct drm_property_blob, base)
2031#define obj_to_plane(x) container_of(x, struct drm_plane, base) 2004#define obj_to_plane(x) container_of(x, struct drm_plane, base)
2032 2005
2033struct drm_prop_enum_list {
2034 int type;
2035 char *name;
2036};
2037
2038extern __printf(6, 7) 2006extern __printf(6, 7)
2039int drm_crtc_init_with_planes(struct drm_device *dev, 2007int drm_crtc_init_with_planes(struct drm_device *dev,
2040 struct drm_crtc *crtc, 2008 struct drm_crtc *crtc,
@@ -2107,52 +2075,6 @@ extern void drm_mode_config_init(struct drm_device *dev);
2107extern void drm_mode_config_reset(struct drm_device *dev); 2075extern void drm_mode_config_reset(struct drm_device *dev);
2108extern void drm_mode_config_cleanup(struct drm_device *dev); 2076extern void drm_mode_config_cleanup(struct drm_device *dev);
2109 2077
2110static inline bool drm_property_type_is(struct drm_property *property,
2111 uint32_t type)
2112{
2113 /* instanceof for props.. handles extended type vs original types: */
2114 if (property->flags & DRM_MODE_PROP_EXTENDED_TYPE)
2115 return (property->flags & DRM_MODE_PROP_EXTENDED_TYPE) == type;
2116 return property->flags & type;
2117}
2118
2119extern struct drm_property *drm_property_create(struct drm_device *dev, int flags,
2120 const char *name, int num_values);
2121extern struct drm_property *drm_property_create_enum(struct drm_device *dev, int flags,
2122 const char *name,
2123 const struct drm_prop_enum_list *props,
2124 int num_values);
2125struct drm_property *drm_property_create_bitmask(struct drm_device *dev,
2126 int flags, const char *name,
2127 const struct drm_prop_enum_list *props,
2128 int num_props,
2129 uint64_t supported_bits);
2130struct drm_property *drm_property_create_range(struct drm_device *dev, int flags,
2131 const char *name,
2132 uint64_t min, uint64_t max);
2133struct drm_property *drm_property_create_signed_range(struct drm_device *dev,
2134 int flags, const char *name,
2135 int64_t min, int64_t max);
2136struct drm_property *drm_property_create_object(struct drm_device *dev,
2137 int flags, const char *name, uint32_t type);
2138struct drm_property *drm_property_create_bool(struct drm_device *dev, int flags,
2139 const char *name);
2140struct drm_property_blob *drm_property_create_blob(struct drm_device *dev,
2141 size_t length,
2142 const void *data);
2143struct drm_property_blob *drm_property_lookup_blob(struct drm_device *dev,
2144 uint32_t id);
2145int drm_property_replace_global_blob(struct drm_device *dev,
2146 struct drm_property_blob **replace,
2147 size_t length,
2148 const void *data,
2149 struct drm_mode_object *obj_holds_id,
2150 struct drm_property *prop_holds_id);
2151struct drm_property_blob *drm_property_reference_blob(struct drm_property_blob *blob);
2152void drm_property_unreference_blob(struct drm_property_blob *blob);
2153extern void drm_property_destroy(struct drm_device *dev, struct drm_property *property);
2154extern int drm_property_add_enum(struct drm_property *property, int index,
2155 uint64_t value, const char *name);
2156extern int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc, 2078extern int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc,
2157 int gamma_size); 2079 int gamma_size);
2158 2080
@@ -2202,14 +2124,6 @@ static inline struct drm_crtc *drm_crtc_find(struct drm_device *dev,
2202 return mo ? obj_to_crtc(mo) : NULL; 2124 return mo ? obj_to_crtc(mo) : NULL;
2203} 2125}
2204 2126
2205static inline struct drm_property *drm_property_find(struct drm_device *dev,
2206 uint32_t id)
2207{
2208 struct drm_mode_object *mo;
2209 mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_PROPERTY);
2210 return mo ? obj_to_property(mo) : NULL;
2211}
2212
2213/* 2127/*
2214 * Extract a degamma/gamma LUT value provided by user and round it to the 2128 * Extract a degamma/gamma LUT value provided by user and round it to the
2215 * precision supported by the hardware. 2129 * precision supported by the hardware.
diff --git a/include/drm/drm_property.h b/include/drm/drm_property.h
new file mode 100644
index 000000000000..ac40069358c7
--- /dev/null
+++ b/include/drm/drm_property.h
@@ -0,0 +1,120 @@
1/*
2 * Copyright (c) 2016 Intel Corporation
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting documentation, and
8 * that the name of the copyright holders not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission. The copyright holders make no representations
11 * about the suitability of this software for any purpose. It is provided "as
12 * is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20 * OF THIS SOFTWARE.
21 */
22
23#ifndef __DRM_PROPERTY_H__
24#define __DRM_PROPERTY_H__
25
26#include <linux/list.h>
27#include <linux/ctype.h>
28#include <drm/drm_mode_object.h>
29
30struct drm_property_blob {
31 struct drm_mode_object base;
32 struct drm_device *dev;
33 struct list_head head_global;
34 struct list_head head_file;
35 size_t length;
36 unsigned char data[];
37};
38
39struct drm_property_enum {
40 uint64_t value;
41 struct list_head head;
42 char name[DRM_PROP_NAME_LEN];
43};
44
45struct drm_property {
46 struct list_head head;
47 struct drm_mode_object base;
48 uint32_t flags;
49 char name[DRM_PROP_NAME_LEN];
50 uint32_t num_values;
51 uint64_t *values;
52 struct drm_device *dev;
53
54 struct list_head enum_list;
55};
56
57struct drm_prop_enum_list {
58 int type;
59 char *name;
60};
61
62#define obj_to_property(x) container_of(x, struct drm_property, base)
63
64static inline bool drm_property_type_is(struct drm_property *property,
65 uint32_t type)
66{
67 /* instanceof for props.. handles extended type vs original types: */
68 if (property->flags & DRM_MODE_PROP_EXTENDED_TYPE)
69 return (property->flags & DRM_MODE_PROP_EXTENDED_TYPE) == type;
70 return property->flags & type;
71}
72
73struct drm_property *drm_property_create(struct drm_device *dev, int flags,
74 const char *name, int num_values);
75struct drm_property *drm_property_create_enum(struct drm_device *dev, int flags,
76 const char *name,
77 const struct drm_prop_enum_list *props,
78 int num_values);
79struct drm_property *drm_property_create_bitmask(struct drm_device *dev,
80 int flags, const char *name,
81 const struct drm_prop_enum_list *props,
82 int num_props,
83 uint64_t supported_bits);
84struct drm_property *drm_property_create_range(struct drm_device *dev, int flags,
85 const char *name,
86 uint64_t min, uint64_t max);
87struct drm_property *drm_property_create_signed_range(struct drm_device *dev,
88 int flags, const char *name,
89 int64_t min, int64_t max);
90struct drm_property *drm_property_create_object(struct drm_device *dev,
91 int flags, const char *name, uint32_t type);
92struct drm_property *drm_property_create_bool(struct drm_device *dev, int flags,
93 const char *name);
94int drm_property_add_enum(struct drm_property *property, int index,
95 uint64_t value, const char *name);
96void drm_property_destroy(struct drm_device *dev, struct drm_property *property);
97
98struct drm_property_blob *drm_property_create_blob(struct drm_device *dev,
99 size_t length,
100 const void *data);
101struct drm_property_blob *drm_property_lookup_blob(struct drm_device *dev,
102 uint32_t id);
103int drm_property_replace_global_blob(struct drm_device *dev,
104 struct drm_property_blob **replace,
105 size_t length,
106 const void *data,
107 struct drm_mode_object *obj_holds_id,
108 struct drm_property *prop_holds_id);
109struct drm_property_blob *drm_property_reference_blob(struct drm_property_blob *blob);
110void drm_property_unreference_blob(struct drm_property_blob *blob);
111
112static inline struct drm_property *drm_property_find(struct drm_device *dev,
113 uint32_t id)
114{
115 struct drm_mode_object *mo;
116 mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_PROPERTY);
117 return mo ? obj_to_property(mo) : NULL;
118}
119
120#endif