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