^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * drm_sysfs.c - Modifications to drm_sysfs_class.c to support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * extra sysfs attribute from DRM. Normal drm_sysfs_class
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * does not allow adding attributes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (c) 2004 Jon Smirl <jonsmirl@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Copyright (c) 2003-2004 Greg Kroah-Hartman <greg@kroah.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Copyright (c) 2003-2004 IBM Corp.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/gfp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/kdev_t.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <drm/drm_connector.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <drm/drm_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <drm/drm_file.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <drm/drm_modes.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <drm/drm_print.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <drm/drm_property.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <drm/drm_sysfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include "drm_internal.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include "drm_crtc_internal.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define to_drm_minor(d) dev_get_drvdata(d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define to_drm_connector(d) dev_get_drvdata(d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * DOC: overview
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * DRM provides very little additional support to drivers for sysfs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * interactions, beyond just all the standard stuff. Drivers who want to expose
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * additional sysfs properties and property groups can attach them at either
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * &drm_device.dev or &drm_connector.kdev.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * Registration is automatically handled when calling drm_dev_register(), or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * drm_connector_register() in case of hot-plugged connectors. Unregistration is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * also automatically handled by drm_dev_unregister() and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * drm_connector_unregister().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) static struct device_type drm_sysfs_device_minor = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) .name = "drm_minor"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) struct class *drm_class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) static char *drm_devnode(struct device *dev, umode_t *mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) return kasprintf(GFP_KERNEL, "dri/%s", dev_name(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) static CLASS_ATTR_STRING(version, S_IRUGO, "drm 1.1.0 20060810");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * drm_sysfs_init - initialize sysfs helpers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) * This is used to create the DRM class, which is the implicit parent of any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * other top-level DRM sysfs objects.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * You must call drm_sysfs_destroy() to release the allocated resources.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * Return: 0 on success, negative error code on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) int drm_sysfs_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) drm_class = class_create(THIS_MODULE, "drm");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) if (IS_ERR(drm_class))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) return PTR_ERR(drm_class);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) err = class_create_file(drm_class, &class_attr_version.attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) class_destroy(drm_class);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) drm_class = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) drm_class->devnode = drm_devnode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) * drm_sysfs_destroy - destroys DRM class
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) * Destroy the DRM device class.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) void drm_sysfs_destroy(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) if (IS_ERR_OR_NULL(drm_class))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) class_remove_file(drm_class, &class_attr_version.attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) class_destroy(drm_class);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) drm_class = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) * Connector properties
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) static ssize_t status_store(struct device *device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) struct drm_connector *connector = to_drm_connector(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) struct drm_device *dev = connector->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) enum drm_connector_force old_force;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) ret = mutex_lock_interruptible(&dev->mode_config.mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) old_force = connector->force;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) if (sysfs_streq(buf, "detect"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) connector->force = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) else if (sysfs_streq(buf, "on"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) connector->force = DRM_FORCE_ON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) else if (sysfs_streq(buf, "on-digital"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) connector->force = DRM_FORCE_ON_DIGITAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) else if (sysfs_streq(buf, "off"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) connector->force = DRM_FORCE_OFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) if (old_force != connector->force || !connector->force) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) DRM_DEBUG_KMS("[CONNECTOR:%d:%s] force updated from %d to %d or reprobing\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) connector->base.id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) connector->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) old_force, connector->force);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) connector->funcs->fill_modes(connector,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) dev->mode_config.max_width,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) dev->mode_config.max_height);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) mutex_unlock(&dev->mode_config.mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) return ret ? ret : count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) static ssize_t status_show(struct device *device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) struct drm_connector *connector = to_drm_connector(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) enum drm_connector_status status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) status = READ_ONCE(connector->status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) return snprintf(buf, PAGE_SIZE, "%s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) drm_get_connector_status_name(status));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) static ssize_t dpms_show(struct device *device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) struct drm_connector *connector = to_drm_connector(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) int dpms;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) dpms = READ_ONCE(connector->dpms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) return snprintf(buf, PAGE_SIZE, "%s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) drm_get_dpms_name(dpms));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) static ssize_t enabled_show(struct device *device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) struct drm_connector *connector = to_drm_connector(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) bool enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) enabled = READ_ONCE(connector->encoder);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) return snprintf(buf, PAGE_SIZE, enabled ? "enabled\n" : "disabled\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) static ssize_t edid_show(struct file *filp, struct kobject *kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) struct bin_attribute *attr, char *buf, loff_t off,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) struct device *connector_dev = kobj_to_dev(kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) struct drm_connector *connector = to_drm_connector(connector_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) unsigned char *edid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) size_t size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) ssize_t ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) mutex_lock(&connector->dev->mode_config.mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) if (!connector->edid_blob_ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) edid = connector->edid_blob_ptr->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) size = connector->edid_blob_ptr->length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) if (!edid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) if (off >= size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) if (off + count > size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) count = size - off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) memcpy(buf, edid + off, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) ret = count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) mutex_unlock(&connector->dev->mode_config.mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) static ssize_t modes_show(struct device *device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) struct drm_connector *connector = to_drm_connector(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) struct drm_display_mode *mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) int written = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) mutex_lock(&connector->dev->mode_config.mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) list_for_each_entry(mode, &connector->modes, head) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) written += scnprintf(buf + written, PAGE_SIZE - written, "%s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) mode->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) mutex_unlock(&connector->dev->mode_config.mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) return written;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) static DEVICE_ATTR_RW(status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) static DEVICE_ATTR_RO(enabled);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) static DEVICE_ATTR_RO(dpms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) static DEVICE_ATTR_RO(modes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) static struct attribute *connector_dev_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) &dev_attr_status.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) &dev_attr_enabled.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) &dev_attr_dpms.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) &dev_attr_modes.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) static struct bin_attribute edid_attr = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) .attr.name = "edid",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) .attr.mode = 0444,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) .size = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) .read = edid_show,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) static struct bin_attribute *connector_bin_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) &edid_attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) static const struct attribute_group connector_dev_group = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) .attrs = connector_dev_attrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) .bin_attrs = connector_bin_attrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) static const struct attribute_group *connector_dev_groups[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) &connector_dev_group,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) int drm_sysfs_connector_add(struct drm_connector *connector)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) struct drm_device *dev = connector->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if (connector->kdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) connector->kdev =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) device_create_with_groups(drm_class, dev->primary->kdev, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) connector, connector_dev_groups,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) "card%d-%s", dev->primary->index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) connector->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) DRM_DEBUG("adding \"%s\" to sysfs\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) connector->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) if (IS_ERR(connector->kdev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) DRM_ERROR("failed to register connector device: %ld\n", PTR_ERR(connector->kdev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) return PTR_ERR(connector->kdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) if (connector->ddc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) return sysfs_create_link(&connector->kdev->kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) &connector->ddc->dev.kobj, "ddc");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) void drm_sysfs_connector_remove(struct drm_connector *connector)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) if (!connector->kdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) if (connector->ddc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) sysfs_remove_link(&connector->kdev->kobj, "ddc");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) DRM_DEBUG("removing \"%s\" from sysfs\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) connector->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) device_unregister(connector->kdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) connector->kdev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) void drm_sysfs_lease_event(struct drm_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) char *event_string = "LEASE=1";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) char *envp[] = { event_string, NULL };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) DRM_DEBUG("generating lease event\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) kobject_uevent_env(&dev->primary->kdev->kobj, KOBJ_CHANGE, envp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) * drm_sysfs_hotplug_event - generate a DRM uevent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) * @dev: DRM device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) * Send a uevent for the DRM device specified by @dev. Currently we only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) * set HOTPLUG=1 in the uevent environment, but this could be expanded to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) * deal with other types of events.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) * Any new uapi should be using the drm_sysfs_connector_status_event()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) * for uevents on connector status change.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) void drm_sysfs_hotplug_event(struct drm_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) char *event_string = "HOTPLUG=1";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) char *envp[] = { event_string, NULL };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) DRM_DEBUG("generating hotplug event\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) kobject_uevent_env(&dev->primary->kdev->kobj, KOBJ_CHANGE, envp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) EXPORT_SYMBOL(drm_sysfs_hotplug_event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) * drm_sysfs_connector_status_event - generate a DRM uevent for connector
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) * property status change
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) * @connector: connector on which property status changed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) * @property: connector property whose status changed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) * Send a uevent for the DRM device specified by @dev. Currently we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) * set HOTPLUG=1 and connector id along with the attached property id
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) * related to the status change.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) void drm_sysfs_connector_status_event(struct drm_connector *connector,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) struct drm_property *property)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) struct drm_device *dev = connector->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) char hotplug_str[] = "HOTPLUG=1", conn_id[21], prop_id[21];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) char *envp[4] = { hotplug_str, conn_id, prop_id, NULL };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) WARN_ON(!drm_mode_obj_find_prop_id(&connector->base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) property->base.id));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) snprintf(conn_id, ARRAY_SIZE(conn_id),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) "CONNECTOR=%u", connector->base.id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) snprintf(prop_id, ARRAY_SIZE(prop_id),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) "PROPERTY=%u", property->base.id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) DRM_DEBUG("generating connector status event\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) kobject_uevent_env(&dev->primary->kdev->kobj, KOBJ_CHANGE, envp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) EXPORT_SYMBOL(drm_sysfs_connector_status_event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) static void drm_sysfs_release(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) kfree(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) struct device *drm_sysfs_minor_alloc(struct drm_minor *minor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) const char *minor_str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) struct device *kdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) int r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) if (minor->type == DRM_MINOR_RENDER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) minor_str = "renderD%d";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) minor_str = "card%d";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) kdev = kzalloc(sizeof(*kdev), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) if (!kdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) device_initialize(kdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) kdev->devt = MKDEV(DRM_MAJOR, minor->index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) kdev->class = drm_class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) kdev->type = &drm_sysfs_device_minor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) kdev->parent = minor->dev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) kdev->release = drm_sysfs_release;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) dev_set_drvdata(kdev, minor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) r = dev_set_name(kdev, minor_str, minor->index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) if (r < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) goto err_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) return kdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) err_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) put_device(kdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) return ERR_PTR(r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) * drm_class_device_register - register new device with the DRM sysfs class
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) * @dev: device to register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) * Registers a new &struct device within the DRM sysfs class. Essentially only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) * used by ttm to have a place for its global settings. Drivers should never use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) * this.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) int drm_class_device_register(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) if (!drm_class || IS_ERR(drm_class))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) dev->class = drm_class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) return device_register(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) EXPORT_SYMBOL_GPL(drm_class_device_register);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) * drm_class_device_unregister - unregister device with the DRM sysfs class
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) * @dev: device to unregister
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) * Unregisters a &struct device from the DRM sysfs class. Essentially only used
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) * by ttm to have a place for its global settings. Drivers should never use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) * this.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) void drm_class_device_unregister(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) return device_unregister(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) EXPORT_SYMBOL_GPL(drm_class_device_unregister);