mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 12:28:41 +08:00
Topic branch for drm-misc / drm-intel for OOB hotplug support for Type-C connectors
-----BEGIN PGP SIGNATURE----- iQFIBAABCAAyFiEEuvA7XScYQRpenhd+kuxHeUQDJ9wFAmEf5msUHGhkZWdvZWRl QHJlZGhhdC5jb20ACgkQkuxHeUQDJ9xUFQgAtBkpLk/oBn6uRcIXCc8KIGs5NqWG orVB7c1Ilsd8jdsap6uD2fVVlS7fn5I6hkiyjdRz5A96aLxkF7oCGLATmxGtYd1k lZTUOLXGdl2ye798vuwaO8UzpN7s2yiIaI44GCGLT5Qwrpq9D1tykY3ggXH/03t2 Z8xOB+XLKbcibnWVQL/4Fz+cQ3KzJ8lo10oiZ131b1ytwf/zdKx0fA3yrPA9C0Kv V3dbWxYMWfkO+IUieZgMzl2LrbChp8fC6zmPJYdvlpB7AZXrOKD+4K8JdlKPMZNE hi5xF4X1tPeTiOo1jju5JN2hnjsc30JuBLemDcV7CLeL01Y4VLdAwHPwyw== =Zar+ -----END PGP SIGNATURE----- gpgsig -----BEGIN PGP SIGNATURE----- iHUEABYIAB0WIQRcEzekXsqa64kGDp7j7w1vZxhRxQUCYSdNKwAKCRDj7w1vZxhR xfR3AP9wwCUfYfionj6GRSLfxtzLPlhu9j8S0NKNeBuERG5S4gEAxJfrHt7EdeSI iafuRpfc/6cOoCslYOEBIzXXnM2EkAI= =Xd1C -----END PGP SIGNATURE----- Merge tag 'drm-misc-intel-oob-hotplug-v1' of git://git.kernel.org/pub/scm/linux/kernel/git/hansg/linux into drm-misc-next Topic branch for drm-misc / drm-intel for OOB hotplug support for Type-C connectors Signed-off-by: Maxime Ripard <maxime@cerno.tech> # -----BEGIN PGP SIGNATURE----- # # iQFIBAABCAAyFiEEuvA7XScYQRpenhd+kuxHeUQDJ9wFAmEf5msUHGhkZWdvZWRl # QHJlZGhhdC5jb20ACgkQkuxHeUQDJ9xUFQgAtBkpLk/oBn6uRcIXCc8KIGs5NqWG # orVB7c1Ilsd8jdsap6uD2fVVlS7fn5I6hkiyjdRz5A96aLxkF7oCGLATmxGtYd1k # lZTUOLXGdl2ye798vuwaO8UzpN7s2yiIaI44GCGLT5Qwrpq9D1tykY3ggXH/03t2 # Z8xOB+XLKbcibnWVQL/4Fz+cQ3KzJ8lo10oiZ131b1ytwf/zdKx0fA3yrPA9C0Kv # V3dbWxYMWfkO+IUieZgMzl2LrbChp8fC6zmPJYdvlpB7AZXrOKD+4K8JdlKPMZNE # hi5xF4X1tPeTiOo1jju5JN2hnjsc30JuBLemDcV7CLeL01Y4VLdAwHPwyw== # =Zar+ # -----END PGP SIGNATURE----- # gpg: Signature made Fri 20 Aug 2021 07:29:15 PM CEST # gpg: using RSA key BAF03B5D2718411A5E9E177E92EC4779440327DC # gpg: issuer "hdegoede@redhat.com" # gpg: Can't check signature: No public key From: Hans de Goede <hdegoede@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/34f13e21-9b1a-5f54-7e03-9705a6b51428@redhat.com
This commit is contained in:
commit
08994edbb8
@ -65,6 +65,14 @@
|
||||
* support can instead use e.g. drm_helper_hpd_irq_event().
|
||||
*/
|
||||
|
||||
/*
|
||||
* Global connector list for drm_connector_find_by_fwnode().
|
||||
* Note drm_connector_[un]register() first take connector->lock and then
|
||||
* take the connector_list_lock.
|
||||
*/
|
||||
static DEFINE_MUTEX(connector_list_lock);
|
||||
static LIST_HEAD(connector_list);
|
||||
|
||||
struct drm_conn_prop_enum_list {
|
||||
int type;
|
||||
const char *name;
|
||||
@ -267,6 +275,7 @@ int drm_connector_init(struct drm_device *dev,
|
||||
goto out_put_type_id;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&connector->global_connector_list_entry);
|
||||
INIT_LIST_HEAD(&connector->probed_modes);
|
||||
INIT_LIST_HEAD(&connector->modes);
|
||||
mutex_init(&connector->mutex);
|
||||
@ -474,6 +483,8 @@ void drm_connector_cleanup(struct drm_connector *connector)
|
||||
drm_mode_object_unregister(dev, &connector->base);
|
||||
kfree(connector->name);
|
||||
connector->name = NULL;
|
||||
fwnode_handle_put(connector->fwnode);
|
||||
connector->fwnode = NULL;
|
||||
spin_lock_irq(&dev->mode_config.connector_list_lock);
|
||||
list_del(&connector->head);
|
||||
dev->mode_config.num_connector--;
|
||||
@ -532,6 +543,9 @@ int drm_connector_register(struct drm_connector *connector)
|
||||
/* Let userspace know we have a new connector */
|
||||
drm_sysfs_hotplug_event(connector->dev);
|
||||
|
||||
mutex_lock(&connector_list_lock);
|
||||
list_add_tail(&connector->global_connector_list_entry, &connector_list);
|
||||
mutex_unlock(&connector_list_lock);
|
||||
goto unlock;
|
||||
|
||||
err_debugfs:
|
||||
@ -560,6 +574,10 @@ void drm_connector_unregister(struct drm_connector *connector)
|
||||
return;
|
||||
}
|
||||
|
||||
mutex_lock(&connector_list_lock);
|
||||
list_del_init(&connector->global_connector_list_entry);
|
||||
mutex_unlock(&connector_list_lock);
|
||||
|
||||
if (connector->funcs->early_unregister)
|
||||
connector->funcs->early_unregister(connector);
|
||||
|
||||
@ -2543,6 +2561,67 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_connector_find_by_fwnode - Find a connector based on the associated fwnode
|
||||
* @fwnode: fwnode for which to find the matching drm_connector
|
||||
*
|
||||
* This functions looks up a drm_connector based on its associated fwnode. When
|
||||
* a connector is found a reference to the connector is returned. The caller must
|
||||
* call drm_connector_put() to release this reference when it is done with the
|
||||
* connector.
|
||||
*
|
||||
* Returns: A reference to the found connector or an ERR_PTR().
|
||||
*/
|
||||
struct drm_connector *drm_connector_find_by_fwnode(struct fwnode_handle *fwnode)
|
||||
{
|
||||
struct drm_connector *connector, *found = ERR_PTR(-ENODEV);
|
||||
|
||||
if (!fwnode)
|
||||
return ERR_PTR(-ENODEV);
|
||||
|
||||
mutex_lock(&connector_list_lock);
|
||||
|
||||
list_for_each_entry(connector, &connector_list, global_connector_list_entry) {
|
||||
if (connector->fwnode == fwnode ||
|
||||
(connector->fwnode && connector->fwnode->secondary == fwnode)) {
|
||||
drm_connector_get(connector);
|
||||
found = connector;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&connector_list_lock);
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_connector_oob_hotplug_event - Report out-of-band hotplug event to connector
|
||||
* @connector: connector to report the event on
|
||||
*
|
||||
* On some hardware a hotplug event notification may come from outside the display
|
||||
* driver / device. An example of this is some USB Type-C setups where the hardware
|
||||
* muxes the DisplayPort data and aux-lines but does not pass the altmode HPD
|
||||
* status bit to the GPU's DP HPD pin.
|
||||
*
|
||||
* This function can be used to report these out-of-band events after obtaining
|
||||
* a drm_connector reference through calling drm_connector_find_by_fwnode().
|
||||
*/
|
||||
void drm_connector_oob_hotplug_event(struct fwnode_handle *connector_fwnode)
|
||||
{
|
||||
struct drm_connector *connector;
|
||||
|
||||
connector = drm_connector_find_by_fwnode(connector_fwnode);
|
||||
if (IS_ERR(connector))
|
||||
return;
|
||||
|
||||
if (connector->funcs->oob_hotplug_event)
|
||||
connector->funcs->oob_hotplug_event(connector);
|
||||
|
||||
drm_connector_put(connector);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_connector_oob_hotplug_event);
|
||||
|
||||
|
||||
/**
|
||||
* DOC: Tile group
|
||||
|
@ -58,6 +58,7 @@ struct drm_property;
|
||||
struct edid;
|
||||
struct kref;
|
||||
struct work_struct;
|
||||
struct fwnode_handle;
|
||||
|
||||
/* drm_crtc.c */
|
||||
int drm_mode_crtc_set_obj_prop(struct drm_mode_object *obj,
|
||||
@ -186,6 +187,7 @@ int drm_connector_set_obj_prop(struct drm_mode_object *obj,
|
||||
int drm_connector_create_standard_properties(struct drm_device *dev);
|
||||
const char *drm_get_connector_force_name(enum drm_connector_force force);
|
||||
void drm_connector_free_work_fn(struct work_struct *work);
|
||||
struct drm_connector *drm_connector_find_by_fwnode(struct fwnode_handle *fwnode);
|
||||
|
||||
/* IOCTL */
|
||||
int drm_connector_property_set_ioctl(struct drm_device *dev,
|
||||
|
@ -10,6 +10,7 @@
|
||||
* Copyright (c) 2003-2004 IBM Corp.
|
||||
*/
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/export.h>
|
||||
@ -50,8 +51,45 @@ static struct device_type drm_sysfs_device_minor = {
|
||||
.name = "drm_minor"
|
||||
};
|
||||
|
||||
static struct device_type drm_sysfs_device_connector = {
|
||||
.name = "drm_connector",
|
||||
};
|
||||
|
||||
struct class *drm_class;
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
static bool drm_connector_acpi_bus_match(struct device *dev)
|
||||
{
|
||||
return dev->type == &drm_sysfs_device_connector;
|
||||
}
|
||||
|
||||
static struct acpi_device *drm_connector_acpi_find_companion(struct device *dev)
|
||||
{
|
||||
struct drm_connector *connector = to_drm_connector(dev);
|
||||
|
||||
return to_acpi_device_node(connector->fwnode);
|
||||
}
|
||||
|
||||
static struct acpi_bus_type drm_connector_acpi_bus = {
|
||||
.name = "drm_connector",
|
||||
.match = drm_connector_acpi_bus_match,
|
||||
.find_companion = drm_connector_acpi_find_companion,
|
||||
};
|
||||
|
||||
static void drm_sysfs_acpi_register(void)
|
||||
{
|
||||
register_acpi_bus_type(&drm_connector_acpi_bus);
|
||||
}
|
||||
|
||||
static void drm_sysfs_acpi_unregister(void)
|
||||
{
|
||||
unregister_acpi_bus_type(&drm_connector_acpi_bus);
|
||||
}
|
||||
#else
|
||||
static void drm_sysfs_acpi_register(void) { }
|
||||
static void drm_sysfs_acpi_unregister(void) { }
|
||||
#endif
|
||||
|
||||
static char *drm_devnode(struct device *dev, umode_t *mode)
|
||||
{
|
||||
return kasprintf(GFP_KERNEL, "dri/%s", dev_name(dev));
|
||||
@ -85,6 +123,8 @@ int drm_sysfs_init(void)
|
||||
}
|
||||
|
||||
drm_class->devnode = drm_devnode;
|
||||
|
||||
drm_sysfs_acpi_register();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -97,11 +137,17 @@ void drm_sysfs_destroy(void)
|
||||
{
|
||||
if (IS_ERR_OR_NULL(drm_class))
|
||||
return;
|
||||
drm_sysfs_acpi_unregister();
|
||||
class_remove_file(drm_class, &class_attr_version.attr);
|
||||
class_destroy(drm_class);
|
||||
drm_class = NULL;
|
||||
}
|
||||
|
||||
static void drm_sysfs_release(struct device *dev)
|
||||
{
|
||||
kfree(dev);
|
||||
}
|
||||
|
||||
/*
|
||||
* Connector properties
|
||||
*/
|
||||
@ -273,27 +319,47 @@ static const struct attribute_group *connector_dev_groups[] = {
|
||||
int drm_sysfs_connector_add(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct device *kdev;
|
||||
int r;
|
||||
|
||||
if (connector->kdev)
|
||||
return 0;
|
||||
|
||||
connector->kdev =
|
||||
device_create_with_groups(drm_class, dev->primary->kdev, 0,
|
||||
connector, connector_dev_groups,
|
||||
"card%d-%s", dev->primary->index,
|
||||
connector->name);
|
||||
kdev = kzalloc(sizeof(*kdev), GFP_KERNEL);
|
||||
if (!kdev)
|
||||
return -ENOMEM;
|
||||
|
||||
device_initialize(kdev);
|
||||
kdev->class = drm_class;
|
||||
kdev->type = &drm_sysfs_device_connector;
|
||||
kdev->parent = dev->primary->kdev;
|
||||
kdev->groups = connector_dev_groups;
|
||||
kdev->release = drm_sysfs_release;
|
||||
dev_set_drvdata(kdev, connector);
|
||||
|
||||
r = dev_set_name(kdev, "card%d-%s", dev->primary->index, connector->name);
|
||||
if (r)
|
||||
goto err_free;
|
||||
|
||||
DRM_DEBUG("adding \"%s\" to sysfs\n",
|
||||
connector->name);
|
||||
|
||||
if (IS_ERR(connector->kdev)) {
|
||||
DRM_ERROR("failed to register connector device: %ld\n", PTR_ERR(connector->kdev));
|
||||
return PTR_ERR(connector->kdev);
|
||||
r = device_add(kdev);
|
||||
if (r) {
|
||||
drm_err(dev, "failed to register connector device: %d\n", r);
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
connector->kdev = kdev;
|
||||
|
||||
if (connector->ddc)
|
||||
return sysfs_create_link(&connector->kdev->kobj,
|
||||
&connector->ddc->dev.kobj, "ddc");
|
||||
return 0;
|
||||
|
||||
err_free:
|
||||
put_device(kdev);
|
||||
return r;
|
||||
}
|
||||
|
||||
void drm_sysfs_connector_remove(struct drm_connector *connector)
|
||||
@ -374,11 +440,6 @@ void drm_sysfs_connector_status_event(struct drm_connector *connector,
|
||||
}
|
||||
EXPORT_SYMBOL(drm_sysfs_connector_status_event);
|
||||
|
||||
static void drm_sysfs_release(struct device *dev)
|
||||
{
|
||||
kfree(dev);
|
||||
}
|
||||
|
||||
struct device *drm_sysfs_minor_alloc(struct drm_minor *minor)
|
||||
{
|
||||
const char *minor_str;
|
||||
|
@ -4,6 +4,7 @@ menu "USB Type-C Alternate Mode drivers"
|
||||
|
||||
config TYPEC_DP_ALTMODE
|
||||
tristate "DisplayPort Alternate Mode driver"
|
||||
depends on DRM
|
||||
help
|
||||
DisplayPort USB Type-C Alternate Mode allows DisplayPort
|
||||
displays and adapters to be attached to the USB Type-C
|
||||
|
@ -11,8 +11,10 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/usb/pd_vdo.h>
|
||||
#include <linux/usb/typec_dp.h>
|
||||
#include <drm/drm_connector.h>
|
||||
#include "displayport.h"
|
||||
|
||||
#define DP_HEADER(_dp, ver, cmd) (VDO((_dp)->alt->svid, 1, ver, cmd) \
|
||||
@ -57,19 +59,28 @@ struct dp_altmode {
|
||||
struct typec_displayport_data data;
|
||||
|
||||
enum dp_state state;
|
||||
bool hpd;
|
||||
|
||||
struct mutex lock; /* device lock */
|
||||
struct work_struct work;
|
||||
struct typec_altmode *alt;
|
||||
const struct typec_altmode *port;
|
||||
struct fwnode_handle *connector_fwnode;
|
||||
};
|
||||
|
||||
static int dp_altmode_notify(struct dp_altmode *dp)
|
||||
{
|
||||
u8 state = get_count_order(DP_CONF_GET_PIN_ASSIGN(dp->data.conf));
|
||||
unsigned long conf;
|
||||
u8 state;
|
||||
|
||||
return typec_altmode_notify(dp->alt, TYPEC_MODAL_STATE(state),
|
||||
&dp->data);
|
||||
if (dp->data.conf) {
|
||||
state = get_count_order(DP_CONF_GET_PIN_ASSIGN(dp->data.conf));
|
||||
conf = TYPEC_MODAL_STATE(state);
|
||||
} else {
|
||||
conf = TYPEC_STATE_USB;
|
||||
}
|
||||
|
||||
return typec_altmode_notify(dp->alt, conf, &dp->data);
|
||||
}
|
||||
|
||||
static int dp_altmode_configure(struct dp_altmode *dp, u8 con)
|
||||
@ -118,6 +129,7 @@ static int dp_altmode_configure(struct dp_altmode *dp, u8 con)
|
||||
static int dp_altmode_status_update(struct dp_altmode *dp)
|
||||
{
|
||||
bool configured = !!DP_CONF_GET_PIN_ASSIGN(dp->data.conf);
|
||||
bool hpd = !!(dp->data.status & DP_STATUS_HPD_STATE);
|
||||
u8 con = DP_STATUS_CONNECTION(dp->data.status);
|
||||
int ret = 0;
|
||||
|
||||
@ -130,6 +142,11 @@ static int dp_altmode_status_update(struct dp_altmode *dp)
|
||||
ret = dp_altmode_configure(dp, con);
|
||||
if (!ret)
|
||||
dp->state = DP_STATE_CONFIGURE;
|
||||
} else {
|
||||
if (dp->hpd != hpd) {
|
||||
drm_connector_oob_hotplug_event(dp->connector_fwnode);
|
||||
dp->hpd = hpd;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -137,21 +154,10 @@ static int dp_altmode_status_update(struct dp_altmode *dp)
|
||||
|
||||
static int dp_altmode_configured(struct dp_altmode *dp)
|
||||
{
|
||||
int ret;
|
||||
|
||||
sysfs_notify(&dp->alt->dev.kobj, "displayport", "configuration");
|
||||
|
||||
if (!dp->data.conf)
|
||||
return typec_altmode_notify(dp->alt, TYPEC_STATE_USB,
|
||||
&dp->data);
|
||||
|
||||
ret = dp_altmode_notify(dp);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
sysfs_notify(&dp->alt->dev.kobj, "displayport", "pin_assignment");
|
||||
|
||||
return 0;
|
||||
return dp_altmode_notify(dp);
|
||||
}
|
||||
|
||||
static int dp_altmode_configure_vdm(struct dp_altmode *dp, u32 conf)
|
||||
@ -172,13 +178,8 @@ static int dp_altmode_configure_vdm(struct dp_altmode *dp, u32 conf)
|
||||
}
|
||||
|
||||
ret = typec_altmode_vdm(dp->alt, header, &conf, 2);
|
||||
if (ret) {
|
||||
if (DP_CONF_GET_PIN_ASSIGN(dp->data.conf))
|
||||
dp_altmode_notify(dp);
|
||||
else
|
||||
typec_altmode_notify(dp->alt, TYPEC_STATE_USB,
|
||||
&dp->data);
|
||||
}
|
||||
if (ret)
|
||||
dp_altmode_notify(dp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -521,6 +522,7 @@ static const struct attribute_group dp_altmode_group = {
|
||||
int dp_altmode_probe(struct typec_altmode *alt)
|
||||
{
|
||||
const struct typec_altmode *port = typec_altmode_get_partner(alt);
|
||||
struct fwnode_handle *fwnode;
|
||||
struct dp_altmode *dp;
|
||||
int ret;
|
||||
|
||||
@ -549,6 +551,11 @@ int dp_altmode_probe(struct typec_altmode *alt)
|
||||
alt->desc = "DisplayPort";
|
||||
alt->ops = &dp_altmode_ops;
|
||||
|
||||
fwnode = dev_fwnode(alt->dev.parent->parent); /* typec_port fwnode */
|
||||
dp->connector_fwnode = fwnode_find_reference(fwnode, "displayport", 0);
|
||||
if (IS_ERR(dp->connector_fwnode))
|
||||
dp->connector_fwnode = NULL;
|
||||
|
||||
typec_altmode_set_drvdata(alt, dp);
|
||||
|
||||
dp->state = DP_STATE_ENTER;
|
||||
@ -564,6 +571,13 @@ void dp_altmode_remove(struct typec_altmode *alt)
|
||||
|
||||
sysfs_remove_group(&alt->dev.kobj, &dp_altmode_group);
|
||||
cancel_work_sync(&dp->work);
|
||||
|
||||
if (dp->connector_fwnode) {
|
||||
if (dp->hpd)
|
||||
drm_connector_oob_hotplug_event(dp->connector_fwnode);
|
||||
|
||||
fwnode_handle_put(dp->connector_fwnode);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dp_altmode_remove);
|
||||
|
||||
|
@ -1084,6 +1084,14 @@ struct drm_connector_funcs {
|
||||
*/
|
||||
void (*atomic_print_state)(struct drm_printer *p,
|
||||
const struct drm_connector_state *state);
|
||||
|
||||
/**
|
||||
* @oob_hotplug_event:
|
||||
*
|
||||
* This will get called when a hotplug-event for a drm-connector
|
||||
* has been received from a source outside the display driver / device.
|
||||
*/
|
||||
void (*oob_hotplug_event)(struct drm_connector *connector);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1228,6 +1236,14 @@ struct drm_connector {
|
||||
struct device *kdev;
|
||||
/** @attr: sysfs attributes */
|
||||
struct device_attribute *attr;
|
||||
/**
|
||||
* @fwnode: associated fwnode supplied by platform firmware
|
||||
*
|
||||
* Drivers can set this to associate a fwnode with a connector, drivers
|
||||
* are expected to get a reference on the fwnode when setting this.
|
||||
* drm_connector_cleanup() will call fwnode_handle_put() on this.
|
||||
*/
|
||||
struct fwnode_handle *fwnode;
|
||||
|
||||
/**
|
||||
* @head:
|
||||
@ -1239,6 +1255,14 @@ struct drm_connector {
|
||||
*/
|
||||
struct list_head head;
|
||||
|
||||
/**
|
||||
* @global_connector_list_entry:
|
||||
*
|
||||
* Connector entry in the global connector-list, used by
|
||||
* drm_connector_find_by_fwnode().
|
||||
*/
|
||||
struct list_head global_connector_list_entry;
|
||||
|
||||
/** @base: base KMS object */
|
||||
struct drm_mode_object base;
|
||||
|
||||
@ -1650,6 +1674,7 @@ drm_connector_is_unregistered(struct drm_connector *connector)
|
||||
DRM_CONNECTOR_UNREGISTERED;
|
||||
}
|
||||
|
||||
void drm_connector_oob_hotplug_event(struct fwnode_handle *connector_fwnode);
|
||||
const char *drm_get_connector_type_name(unsigned int connector_type);
|
||||
const char *drm_get_connector_status_name(enum drm_connector_status status);
|
||||
const char *drm_get_subpixel_order_name(enum subpixel_order order);
|
||||
|
Loading…
Reference in New Issue
Block a user