Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 
0003 /*
0004  * drm_sysfs.c - Modifications to drm_sysfs_class.c to support
0005  *               extra sysfs attribute from DRM. Normal drm_sysfs_class
0006  *               does not allow adding attributes.
0007  *
0008  * Copyright (c) 2004 Jon Smirl <jonsmirl@gmail.com>
0009  * Copyright (c) 2003-2004 Greg Kroah-Hartman <greg@kroah.com>
0010  * Copyright (c) 2003-2004 IBM Corp.
0011  */
0012 
0013 #include <linux/acpi.h>
0014 #include <linux/device.h>
0015 #include <linux/err.h>
0016 #include <linux/export.h>
0017 #include <linux/gfp.h>
0018 #include <linux/i2c.h>
0019 #include <linux/kdev_t.h>
0020 #include <linux/slab.h>
0021 
0022 #include <drm/drm_connector.h>
0023 #include <drm/drm_device.h>
0024 #include <drm/drm_file.h>
0025 #include <drm/drm_modes.h>
0026 #include <drm/drm_print.h>
0027 #include <drm/drm_property.h>
0028 #include <drm/drm_sysfs.h>
0029 
0030 #include "drm_internal.h"
0031 #include "drm_crtc_internal.h"
0032 
0033 #define to_drm_minor(d) dev_get_drvdata(d)
0034 #define to_drm_connector(d) dev_get_drvdata(d)
0035 
0036 /**
0037  * DOC: overview
0038  *
0039  * DRM provides very little additional support to drivers for sysfs
0040  * interactions, beyond just all the standard stuff. Drivers who want to expose
0041  * additional sysfs properties and property groups can attach them at either
0042  * &drm_device.dev or &drm_connector.kdev.
0043  *
0044  * Registration is automatically handled when calling drm_dev_register(), or
0045  * drm_connector_register() in case of hot-plugged connectors. Unregistration is
0046  * also automatically handled by drm_dev_unregister() and
0047  * drm_connector_unregister().
0048  */
0049 
0050 static struct device_type drm_sysfs_device_minor = {
0051     .name = "drm_minor"
0052 };
0053 
0054 static struct device_type drm_sysfs_device_connector = {
0055     .name = "drm_connector",
0056 };
0057 
0058 struct class *drm_class;
0059 
0060 #ifdef CONFIG_ACPI
0061 static bool drm_connector_acpi_bus_match(struct device *dev)
0062 {
0063     return dev->type == &drm_sysfs_device_connector;
0064 }
0065 
0066 static struct acpi_device *drm_connector_acpi_find_companion(struct device *dev)
0067 {
0068     struct drm_connector *connector = to_drm_connector(dev);
0069 
0070     return to_acpi_device_node(connector->fwnode);
0071 }
0072 
0073 static struct acpi_bus_type drm_connector_acpi_bus = {
0074     .name = "drm_connector",
0075     .match = drm_connector_acpi_bus_match,
0076     .find_companion = drm_connector_acpi_find_companion,
0077 };
0078 
0079 static void drm_sysfs_acpi_register(void)
0080 {
0081     register_acpi_bus_type(&drm_connector_acpi_bus);
0082 }
0083 
0084 static void drm_sysfs_acpi_unregister(void)
0085 {
0086     unregister_acpi_bus_type(&drm_connector_acpi_bus);
0087 }
0088 #else
0089 static void drm_sysfs_acpi_register(void) { }
0090 static void drm_sysfs_acpi_unregister(void) { }
0091 #endif
0092 
0093 static char *drm_devnode(struct device *dev, umode_t *mode)
0094 {
0095     return kasprintf(GFP_KERNEL, "dri/%s", dev_name(dev));
0096 }
0097 
0098 static CLASS_ATTR_STRING(version, S_IRUGO, "drm 1.1.0 20060810");
0099 
0100 /**
0101  * drm_sysfs_init - initialize sysfs helpers
0102  *
0103  * This is used to create the DRM class, which is the implicit parent of any
0104  * other top-level DRM sysfs objects.
0105  *
0106  * You must call drm_sysfs_destroy() to release the allocated resources.
0107  *
0108  * Return: 0 on success, negative error code on failure.
0109  */
0110 int drm_sysfs_init(void)
0111 {
0112     int err;
0113 
0114     drm_class = class_create(THIS_MODULE, "drm");
0115     if (IS_ERR(drm_class))
0116         return PTR_ERR(drm_class);
0117 
0118     err = class_create_file(drm_class, &class_attr_version.attr);
0119     if (err) {
0120         class_destroy(drm_class);
0121         drm_class = NULL;
0122         return err;
0123     }
0124 
0125     drm_class->devnode = drm_devnode;
0126 
0127     drm_sysfs_acpi_register();
0128     return 0;
0129 }
0130 
0131 /**
0132  * drm_sysfs_destroy - destroys DRM class
0133  *
0134  * Destroy the DRM device class.
0135  */
0136 void drm_sysfs_destroy(void)
0137 {
0138     if (IS_ERR_OR_NULL(drm_class))
0139         return;
0140     drm_sysfs_acpi_unregister();
0141     class_remove_file(drm_class, &class_attr_version.attr);
0142     class_destroy(drm_class);
0143     drm_class = NULL;
0144 }
0145 
0146 static void drm_sysfs_release(struct device *dev)
0147 {
0148     kfree(dev);
0149 }
0150 
0151 /*
0152  * Connector properties
0153  */
0154 static ssize_t status_store(struct device *device,
0155                struct device_attribute *attr,
0156                const char *buf, size_t count)
0157 {
0158     struct drm_connector *connector = to_drm_connector(device);
0159     struct drm_device *dev = connector->dev;
0160     enum drm_connector_force old_force;
0161     int ret;
0162 
0163     ret = mutex_lock_interruptible(&dev->mode_config.mutex);
0164     if (ret)
0165         return ret;
0166 
0167     old_force = connector->force;
0168 
0169     if (sysfs_streq(buf, "detect"))
0170         connector->force = 0;
0171     else if (sysfs_streq(buf, "on"))
0172         connector->force = DRM_FORCE_ON;
0173     else if (sysfs_streq(buf, "on-digital"))
0174         connector->force = DRM_FORCE_ON_DIGITAL;
0175     else if (sysfs_streq(buf, "off"))
0176         connector->force = DRM_FORCE_OFF;
0177     else
0178         ret = -EINVAL;
0179 
0180     if (old_force != connector->force || !connector->force) {
0181         DRM_DEBUG_KMS("[CONNECTOR:%d:%s] force updated from %d to %d or reprobing\n",
0182                   connector->base.id,
0183                   connector->name,
0184                   old_force, connector->force);
0185 
0186         connector->funcs->fill_modes(connector,
0187                          dev->mode_config.max_width,
0188                          dev->mode_config.max_height);
0189     }
0190 
0191     mutex_unlock(&dev->mode_config.mutex);
0192 
0193     return ret ? ret : count;
0194 }
0195 
0196 static ssize_t status_show(struct device *device,
0197                struct device_attribute *attr,
0198                char *buf)
0199 {
0200     struct drm_connector *connector = to_drm_connector(device);
0201     enum drm_connector_status status;
0202 
0203     status = READ_ONCE(connector->status);
0204 
0205     return sysfs_emit(buf, "%s\n",
0206               drm_get_connector_status_name(status));
0207 }
0208 
0209 static ssize_t dpms_show(struct device *device,
0210                struct device_attribute *attr,
0211                char *buf)
0212 {
0213     struct drm_connector *connector = to_drm_connector(device);
0214     int dpms;
0215 
0216     dpms = READ_ONCE(connector->dpms);
0217 
0218     return sysfs_emit(buf, "%s\n", drm_get_dpms_name(dpms));
0219 }
0220 
0221 static ssize_t enabled_show(struct device *device,
0222                 struct device_attribute *attr,
0223                char *buf)
0224 {
0225     struct drm_connector *connector = to_drm_connector(device);
0226     bool enabled;
0227 
0228     enabled = READ_ONCE(connector->encoder);
0229 
0230     return sysfs_emit(buf, enabled ? "enabled\n" : "disabled\n");
0231 }
0232 
0233 static ssize_t edid_show(struct file *filp, struct kobject *kobj,
0234              struct bin_attribute *attr, char *buf, loff_t off,
0235              size_t count)
0236 {
0237     struct device *connector_dev = kobj_to_dev(kobj);
0238     struct drm_connector *connector = to_drm_connector(connector_dev);
0239     unsigned char *edid;
0240     size_t size;
0241     ssize_t ret = 0;
0242 
0243     mutex_lock(&connector->dev->mode_config.mutex);
0244     if (!connector->edid_blob_ptr)
0245         goto unlock;
0246 
0247     edid = connector->edid_blob_ptr->data;
0248     size = connector->edid_blob_ptr->length;
0249     if (!edid)
0250         goto unlock;
0251 
0252     if (off >= size)
0253         goto unlock;
0254 
0255     if (off + count > size)
0256         count = size - off;
0257     memcpy(buf, edid + off, count);
0258 
0259     ret = count;
0260 unlock:
0261     mutex_unlock(&connector->dev->mode_config.mutex);
0262 
0263     return ret;
0264 }
0265 
0266 static ssize_t modes_show(struct device *device,
0267                struct device_attribute *attr,
0268                char *buf)
0269 {
0270     struct drm_connector *connector = to_drm_connector(device);
0271     struct drm_display_mode *mode;
0272     int written = 0;
0273 
0274     mutex_lock(&connector->dev->mode_config.mutex);
0275     list_for_each_entry(mode, &connector->modes, head) {
0276         written += scnprintf(buf + written, PAGE_SIZE - written, "%s\n",
0277                     mode->name);
0278     }
0279     mutex_unlock(&connector->dev->mode_config.mutex);
0280 
0281     return written;
0282 }
0283 
0284 static DEVICE_ATTR_RW(status);
0285 static DEVICE_ATTR_RO(enabled);
0286 static DEVICE_ATTR_RO(dpms);
0287 static DEVICE_ATTR_RO(modes);
0288 
0289 static struct attribute *connector_dev_attrs[] = {
0290     &dev_attr_status.attr,
0291     &dev_attr_enabled.attr,
0292     &dev_attr_dpms.attr,
0293     &dev_attr_modes.attr,
0294     NULL
0295 };
0296 
0297 static struct bin_attribute edid_attr = {
0298     .attr.name = "edid",
0299     .attr.mode = 0444,
0300     .size = 0,
0301     .read = edid_show,
0302 };
0303 
0304 static struct bin_attribute *connector_bin_attrs[] = {
0305     &edid_attr,
0306     NULL
0307 };
0308 
0309 static const struct attribute_group connector_dev_group = {
0310     .attrs = connector_dev_attrs,
0311     .bin_attrs = connector_bin_attrs,
0312 };
0313 
0314 static const struct attribute_group *connector_dev_groups[] = {
0315     &connector_dev_group,
0316     NULL
0317 };
0318 
0319 int drm_sysfs_connector_add(struct drm_connector *connector)
0320 {
0321     struct drm_device *dev = connector->dev;
0322     struct device *kdev;
0323     int r;
0324 
0325     if (connector->kdev)
0326         return 0;
0327 
0328     kdev = kzalloc(sizeof(*kdev), GFP_KERNEL);
0329     if (!kdev)
0330         return -ENOMEM;
0331 
0332     device_initialize(kdev);
0333     kdev->class = drm_class;
0334     kdev->type = &drm_sysfs_device_connector;
0335     kdev->parent = dev->primary->kdev;
0336     kdev->groups = connector_dev_groups;
0337     kdev->release = drm_sysfs_release;
0338     dev_set_drvdata(kdev, connector);
0339 
0340     r = dev_set_name(kdev, "card%d-%s", dev->primary->index, connector->name);
0341     if (r)
0342         goto err_free;
0343 
0344     DRM_DEBUG("adding \"%s\" to sysfs\n",
0345           connector->name);
0346 
0347     r = device_add(kdev);
0348     if (r) {
0349         drm_err(dev, "failed to register connector device: %d\n", r);
0350         goto err_free;
0351     }
0352 
0353     connector->kdev = kdev;
0354 
0355     if (connector->ddc)
0356         return sysfs_create_link(&connector->kdev->kobj,
0357                  &connector->ddc->dev.kobj, "ddc");
0358     return 0;
0359 
0360 err_free:
0361     put_device(kdev);
0362     return r;
0363 }
0364 
0365 void drm_sysfs_connector_remove(struct drm_connector *connector)
0366 {
0367     if (!connector->kdev)
0368         return;
0369 
0370     if (connector->ddc)
0371         sysfs_remove_link(&connector->kdev->kobj, "ddc");
0372 
0373     DRM_DEBUG("removing \"%s\" from sysfs\n",
0374           connector->name);
0375 
0376     device_unregister(connector->kdev);
0377     connector->kdev = NULL;
0378 }
0379 
0380 void drm_sysfs_lease_event(struct drm_device *dev)
0381 {
0382     char *event_string = "LEASE=1";
0383     char *envp[] = { event_string, NULL };
0384 
0385     DRM_DEBUG("generating lease event\n");
0386 
0387     kobject_uevent_env(&dev->primary->kdev->kobj, KOBJ_CHANGE, envp);
0388 }
0389 
0390 /**
0391  * drm_sysfs_hotplug_event - generate a DRM uevent
0392  * @dev: DRM device
0393  *
0394  * Send a uevent for the DRM device specified by @dev.  Currently we only
0395  * set HOTPLUG=1 in the uevent environment, but this could be expanded to
0396  * deal with other types of events.
0397  *
0398  * Any new uapi should be using the drm_sysfs_connector_status_event()
0399  * for uevents on connector status change.
0400  */
0401 void drm_sysfs_hotplug_event(struct drm_device *dev)
0402 {
0403     char *event_string = "HOTPLUG=1";
0404     char *envp[] = { event_string, NULL };
0405 
0406     DRM_DEBUG("generating hotplug event\n");
0407 
0408     kobject_uevent_env(&dev->primary->kdev->kobj, KOBJ_CHANGE, envp);
0409 }
0410 EXPORT_SYMBOL(drm_sysfs_hotplug_event);
0411 
0412 /**
0413  * drm_sysfs_connector_hotplug_event - generate a DRM uevent for any connector
0414  * change
0415  * @connector: connector which has changed
0416  *
0417  * Send a uevent for the DRM connector specified by @connector. This will send
0418  * a uevent with the properties HOTPLUG=1 and CONNECTOR.
0419  */
0420 void drm_sysfs_connector_hotplug_event(struct drm_connector *connector)
0421 {
0422     struct drm_device *dev = connector->dev;
0423     char hotplug_str[] = "HOTPLUG=1", conn_id[21];
0424     char *envp[] = { hotplug_str, conn_id, NULL };
0425 
0426     snprintf(conn_id, sizeof(conn_id),
0427          "CONNECTOR=%u", connector->base.id);
0428 
0429     drm_dbg_kms(connector->dev,
0430             "[CONNECTOR:%d:%s] generating connector hotplug event\n",
0431             connector->base.id, connector->name);
0432 
0433     kobject_uevent_env(&dev->primary->kdev->kobj, KOBJ_CHANGE, envp);
0434 }
0435 EXPORT_SYMBOL(drm_sysfs_connector_hotplug_event);
0436 
0437 /**
0438  * drm_sysfs_connector_status_event - generate a DRM uevent for connector
0439  * property status change
0440  * @connector: connector on which property status changed
0441  * @property: connector property whose status changed.
0442  *
0443  * Send a uevent for the DRM device specified by @dev.  Currently we
0444  * set HOTPLUG=1 and connector id along with the attached property id
0445  * related to the status change.
0446  */
0447 void drm_sysfs_connector_status_event(struct drm_connector *connector,
0448                       struct drm_property *property)
0449 {
0450     struct drm_device *dev = connector->dev;
0451     char hotplug_str[] = "HOTPLUG=1", conn_id[21], prop_id[21];
0452     char *envp[4] = { hotplug_str, conn_id, prop_id, NULL };
0453 
0454     WARN_ON(!drm_mode_obj_find_prop_id(&connector->base,
0455                        property->base.id));
0456 
0457     snprintf(conn_id, ARRAY_SIZE(conn_id),
0458          "CONNECTOR=%u", connector->base.id);
0459     snprintf(prop_id, ARRAY_SIZE(prop_id),
0460          "PROPERTY=%u", property->base.id);
0461 
0462     DRM_DEBUG("generating connector status event\n");
0463 
0464     kobject_uevent_env(&dev->primary->kdev->kobj, KOBJ_CHANGE, envp);
0465 }
0466 EXPORT_SYMBOL(drm_sysfs_connector_status_event);
0467 
0468 struct device *drm_sysfs_minor_alloc(struct drm_minor *minor)
0469 {
0470     const char *minor_str;
0471     struct device *kdev;
0472     int r;
0473 
0474     if (minor->type == DRM_MINOR_RENDER)
0475         minor_str = "renderD%d";
0476     else
0477         minor_str = "card%d";
0478 
0479     kdev = kzalloc(sizeof(*kdev), GFP_KERNEL);
0480     if (!kdev)
0481         return ERR_PTR(-ENOMEM);
0482 
0483     device_initialize(kdev);
0484     kdev->devt = MKDEV(DRM_MAJOR, minor->index);
0485     kdev->class = drm_class;
0486     kdev->type = &drm_sysfs_device_minor;
0487     kdev->parent = minor->dev->dev;
0488     kdev->release = drm_sysfs_release;
0489     dev_set_drvdata(kdev, minor);
0490 
0491     r = dev_set_name(kdev, minor_str, minor->index);
0492     if (r < 0)
0493         goto err_free;
0494 
0495     return kdev;
0496 
0497 err_free:
0498     put_device(kdev);
0499     return ERR_PTR(r);
0500 }
0501 
0502 /**
0503  * drm_class_device_register - register new device with the DRM sysfs class
0504  * @dev: device to register
0505  *
0506  * Registers a new &struct device within the DRM sysfs class. Essentially only
0507  * used by ttm to have a place for its global settings. Drivers should never use
0508  * this.
0509  */
0510 int drm_class_device_register(struct device *dev)
0511 {
0512     if (!drm_class || IS_ERR(drm_class))
0513         return -ENOENT;
0514 
0515     dev->class = drm_class;
0516     return device_register(dev);
0517 }
0518 EXPORT_SYMBOL_GPL(drm_class_device_register);
0519 
0520 /**
0521  * drm_class_device_unregister - unregister device with the DRM sysfs class
0522  * @dev: device to unregister
0523  *
0524  * Unregisters a &struct device from the DRM sysfs class. Essentially only used
0525  * by ttm to have a place for its global settings. Drivers should never use
0526  * this.
0527  */
0528 void drm_class_device_unregister(struct device *dev)
0529 {
0530     return device_unregister(dev);
0531 }
0532 EXPORT_SYMBOL_GPL(drm_class_device_unregister);