0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
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
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
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
0102
0103
0104
0105
0106
0107
0108
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
0133
0134
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
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
0392
0393
0394
0395
0396
0397
0398
0399
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
0414
0415
0416
0417
0418
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
0439
0440
0441
0442
0443
0444
0445
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
0504
0505
0506
0507
0508
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
0522
0523
0524
0525
0526
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);