1 /* 2 * Created: Sun Dec 21 13:08:50 2008 by bgamari@gmail.com 3 * 4 * Copyright 2008 Ben Gamari <bgamari@gmail.com> 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the next 14 * paragraph) shall be included in all copies or substantial portions of the 15 * Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 * OTHER DEALINGS IN THE SOFTWARE. 24 */ 25 26 #include <linux/debugfs.h> 27 #include <linux/export.h> 28 #include <linux/seq_file.h> 29 #include <linux/slab.h> 30 #include <linux/uaccess.h> 31 32 #include <drm/drm_atomic.h> 33 #include <drm/drm_auth.h> 34 #include <drm/drm_bridge.h> 35 #include <drm/drm_client.h> 36 #include <drm/drm_debugfs.h> 37 #include <drm/drm_device.h> 38 #include <drm/drm_drv.h> 39 #include <drm/drm_edid.h> 40 #include <drm/drm_file.h> 41 #include <drm/drm_gem.h> 42 #include <drm/drm_managed.h> 43 #include <drm/drm_gpuvm.h> 44 45 #include "drm_crtc_internal.h" 46 #include "drm_internal.h" 47 48 /*************************************************** 49 * Initialization, etc. 50 **************************************************/ 51 52 static int drm_name_info(struct seq_file *m, void *data) 53 { 54 struct drm_debugfs_entry *entry = m->private; 55 struct drm_device *dev = entry->dev; 56 struct drm_master *master; 57 58 mutex_lock(&dev->master_mutex); 59 master = dev->master; 60 seq_printf(m, "%s", dev->driver->name); 61 if (dev->dev) 62 seq_printf(m, " dev=%s", dev_name(dev->dev)); 63 if (master && master->unique) 64 seq_printf(m, " master=%s", master->unique); 65 if (dev->unique) 66 seq_printf(m, " unique=%s", dev->unique); 67 seq_printf(m, "\n"); 68 mutex_unlock(&dev->master_mutex); 69 70 return 0; 71 } 72 73 static int drm_clients_info(struct seq_file *m, void *data) 74 { 75 struct drm_debugfs_entry *entry = m->private; 76 struct drm_device *dev = entry->dev; 77 struct drm_file *priv; 78 kuid_t uid; 79 80 seq_printf(m, 81 "%20s %5s %3s master a %5s %10s %*s\n", 82 "command", 83 "tgid", 84 "dev", 85 "uid", 86 "magic", 87 DRM_CLIENT_NAME_MAX_LEN, 88 "name"); 89 90 /* dev->filelist is sorted youngest first, but we want to present 91 * oldest first (i.e. kernel, servers, clients), so walk backwardss. 92 */ 93 mutex_lock(&dev->filelist_mutex); 94 list_for_each_entry_reverse(priv, &dev->filelist, lhead) { 95 bool is_current_master = drm_is_current_master(priv); 96 struct task_struct *task; 97 struct pid *pid; 98 99 mutex_lock(&priv->client_name_lock); 100 rcu_read_lock(); /* Locks priv->pid and pid_task()->comm! */ 101 pid = rcu_dereference(priv->pid); 102 task = pid_task(pid, PIDTYPE_TGID); 103 uid = task ? __task_cred(task)->euid : GLOBAL_ROOT_UID; 104 seq_printf(m, "%20s %5d %3d %c %c %5d %10u %*s\n", 105 task ? task->comm : "<unknown>", 106 pid_vnr(pid), 107 priv->minor->index, 108 is_current_master ? 'y' : 'n', 109 priv->authenticated ? 'y' : 'n', 110 from_kuid_munged(seq_user_ns(m), uid), 111 priv->magic, 112 DRM_CLIENT_NAME_MAX_LEN, 113 priv->client_name ? priv->client_name : "<unset>"); 114 rcu_read_unlock(); 115 mutex_unlock(&priv->client_name_lock); 116 } 117 mutex_unlock(&dev->filelist_mutex); 118 return 0; 119 } 120 121 static int drm_gem_one_name_info(int id, void *ptr, void *data) 122 { 123 struct drm_gem_object *obj = ptr; 124 struct seq_file *m = data; 125 126 seq_printf(m, "%6d %8zd %7d %8d\n", 127 obj->name, obj->size, 128 obj->handle_count, 129 kref_read(&obj->refcount)); 130 return 0; 131 } 132 133 static int drm_gem_name_info(struct seq_file *m, void *data) 134 { 135 struct drm_debugfs_entry *entry = m->private; 136 struct drm_device *dev = entry->dev; 137 138 seq_printf(m, " name size handles refcount\n"); 139 140 mutex_lock(&dev->object_name_lock); 141 idr_for_each(&dev->object_name_idr, drm_gem_one_name_info, m); 142 mutex_unlock(&dev->object_name_lock); 143 144 return 0; 145 } 146 147 static const struct drm_debugfs_info drm_debugfs_list[] = { 148 {"name", drm_name_info, 0}, 149 {"clients", drm_clients_info, 0}, 150 {"gem_names", drm_gem_name_info, DRIVER_GEM}, 151 }; 152 #define DRM_DEBUGFS_ENTRIES ARRAY_SIZE(drm_debugfs_list) 153 154 155 static int drm_debugfs_open(struct inode *inode, struct file *file) 156 { 157 struct drm_info_node *node = inode->i_private; 158 159 if (!device_is_registered(node->minor->kdev)) 160 return -ENODEV; 161 162 return single_open(file, node->info_ent->show, node); 163 } 164 165 static int drm_debugfs_entry_open(struct inode *inode, struct file *file) 166 { 167 struct drm_debugfs_entry *entry = inode->i_private; 168 struct drm_debugfs_info *node = &entry->file; 169 struct drm_minor *minor = entry->dev->primary ?: entry->dev->accel; 170 171 if (!device_is_registered(minor->kdev)) 172 return -ENODEV; 173 174 return single_open(file, node->show, entry); 175 } 176 177 static const struct file_operations drm_debugfs_entry_fops = { 178 .owner = THIS_MODULE, 179 .open = drm_debugfs_entry_open, 180 .read = seq_read, 181 .llseek = seq_lseek, 182 .release = single_release, 183 }; 184 185 static const struct file_operations drm_debugfs_fops = { 186 .owner = THIS_MODULE, 187 .open = drm_debugfs_open, 188 .read = seq_read, 189 .llseek = seq_lseek, 190 .release = single_release, 191 }; 192 193 /** 194 * drm_debugfs_gpuva_info - dump the given DRM GPU VA space 195 * @m: pointer to the &seq_file to write 196 * @gpuvm: the &drm_gpuvm representing the GPU VA space 197 * 198 * Dumps the GPU VA mappings of a given DRM GPU VA manager. 199 * 200 * For each DRM GPU VA space drivers should call this function from their 201 * &drm_info_list's show callback. 202 * 203 * Returns: 0 on success, -ENODEV if the &gpuvm is not initialized 204 */ 205 int drm_debugfs_gpuva_info(struct seq_file *m, 206 struct drm_gpuvm *gpuvm) 207 { 208 struct drm_gpuva *va, *kva = &gpuvm->kernel_alloc_node; 209 210 if (!gpuvm->name) 211 return -ENODEV; 212 213 seq_printf(m, "DRM GPU VA space (%s) [0x%016llx;0x%016llx]\n", 214 gpuvm->name, gpuvm->mm_start, gpuvm->mm_start + gpuvm->mm_range); 215 seq_printf(m, "Kernel reserved node [0x%016llx;0x%016llx]\n", 216 kva->va.addr, kva->va.addr + kva->va.range); 217 seq_puts(m, "\n"); 218 seq_puts(m, " VAs | start | range | end | object | object offset\n"); 219 seq_puts(m, "-------------------------------------------------------------------------------------------------------------\n"); 220 drm_gpuvm_for_each_va(va, gpuvm) { 221 if (unlikely(va == kva)) 222 continue; 223 224 seq_printf(m, " | 0x%016llx | 0x%016llx | 0x%016llx | 0x%016llx | 0x%016llx\n", 225 va->va.addr, va->va.range, va->va.addr + va->va.range, 226 (u64)(uintptr_t)va->gem.obj, va->gem.offset); 227 } 228 229 return 0; 230 } 231 EXPORT_SYMBOL(drm_debugfs_gpuva_info); 232 233 /** 234 * drm_debugfs_create_files - Initialize a given set of debugfs files for DRM 235 * minor 236 * @files: The array of files to create 237 * @count: The number of files given 238 * @root: DRI debugfs dir entry. 239 * @minor: device minor number 240 * 241 * Create a given set of debugfs files represented by an array of 242 * &struct drm_info_list in the given root directory. These files will be removed 243 * automatically on drm_debugfs_dev_fini(). 244 */ 245 void drm_debugfs_create_files(const struct drm_info_list *files, int count, 246 struct dentry *root, struct drm_minor *minor) 247 { 248 struct drm_device *dev = minor->dev; 249 struct drm_info_node *tmp; 250 int i; 251 252 for (i = 0; i < count; i++) { 253 u32 features = files[i].driver_features; 254 255 if (features && !drm_core_check_all_features(dev, features)) 256 continue; 257 258 tmp = drmm_kzalloc(dev, sizeof(*tmp), GFP_KERNEL); 259 if (tmp == NULL) 260 continue; 261 262 tmp->minor = minor; 263 tmp->dent = debugfs_create_file(files[i].name, 264 0444, root, tmp, 265 &drm_debugfs_fops); 266 tmp->info_ent = &files[i]; 267 } 268 } 269 EXPORT_SYMBOL(drm_debugfs_create_files); 270 271 int drm_debugfs_remove_files(const struct drm_info_list *files, int count, 272 struct dentry *root, struct drm_minor *minor) 273 { 274 int i; 275 276 for (i = 0; i < count; i++) { 277 struct dentry *dent = debugfs_lookup(files[i].name, root); 278 279 if (!dent) 280 continue; 281 282 drmm_kfree(minor->dev, d_inode(dent)->i_private); 283 debugfs_remove(dent); 284 } 285 return 0; 286 } 287 EXPORT_SYMBOL(drm_debugfs_remove_files); 288 289 /** 290 * drm_debugfs_dev_init - create debugfs directory for the device 291 * @dev: the device which we want to create the directory for 292 * @root: the parent directory depending on the device type 293 * 294 * Creates the debugfs directory for the device under the given root directory. 295 */ 296 void drm_debugfs_dev_init(struct drm_device *dev, struct dentry *root) 297 { 298 dev->debugfs_root = debugfs_create_dir(dev->unique, root); 299 } 300 301 /** 302 * drm_debugfs_dev_fini - cleanup debugfs directory 303 * @dev: the device to cleanup the debugfs stuff 304 * 305 * Remove the debugfs directory, might be called multiple times. 306 */ 307 void drm_debugfs_dev_fini(struct drm_device *dev) 308 { 309 debugfs_remove_recursive(dev->debugfs_root); 310 dev->debugfs_root = NULL; 311 } 312 313 void drm_debugfs_dev_register(struct drm_device *dev) 314 { 315 drm_debugfs_add_files(dev, drm_debugfs_list, DRM_DEBUGFS_ENTRIES); 316 317 if (drm_core_check_feature(dev, DRIVER_MODESET)) { 318 drm_framebuffer_debugfs_init(dev); 319 drm_client_debugfs_init(dev); 320 } 321 if (drm_drv_uses_atomic_modeset(dev)) 322 drm_atomic_debugfs_init(dev); 323 } 324 325 int drm_debugfs_register(struct drm_minor *minor, int minor_id, 326 struct dentry *root) 327 { 328 struct drm_device *dev = minor->dev; 329 char name[64]; 330 331 sprintf(name, "%d", minor_id); 332 minor->debugfs_symlink = debugfs_create_symlink(name, root, 333 dev->unique); 334 335 /* TODO: Only for compatibility with drivers */ 336 minor->debugfs_root = dev->debugfs_root; 337 338 if (dev->driver->debugfs_init && dev->render != minor) 339 dev->driver->debugfs_init(minor); 340 341 return 0; 342 } 343 344 void drm_debugfs_unregister(struct drm_minor *minor) 345 { 346 debugfs_remove(minor->debugfs_symlink); 347 minor->debugfs_symlink = NULL; 348 } 349 350 /** 351 * drm_debugfs_add_file - Add a given file to the DRM device debugfs file list 352 * @dev: drm device for the ioctl 353 * @name: debugfs file name 354 * @show: show callback 355 * @data: driver-private data, should not be device-specific 356 * 357 * Add a given file entry to the DRM device debugfs file list to be created on 358 * drm_debugfs_init. 359 */ 360 void drm_debugfs_add_file(struct drm_device *dev, const char *name, 361 int (*show)(struct seq_file*, void*), void *data) 362 { 363 struct drm_debugfs_entry *entry = drmm_kzalloc(dev, sizeof(*entry), GFP_KERNEL); 364 365 if (!entry) 366 return; 367 368 entry->file.name = name; 369 entry->file.show = show; 370 entry->file.data = data; 371 entry->dev = dev; 372 373 debugfs_create_file(name, 0444, dev->debugfs_root, entry, 374 &drm_debugfs_entry_fops); 375 } 376 EXPORT_SYMBOL(drm_debugfs_add_file); 377 378 /** 379 * drm_debugfs_add_files - Add an array of files to the DRM device debugfs file list 380 * @dev: drm device for the ioctl 381 * @files: The array of files to create 382 * @count: The number of files given 383 * 384 * Add a given set of debugfs files represented by an array of 385 * &struct drm_debugfs_info in the DRM device debugfs file list. 386 */ 387 void drm_debugfs_add_files(struct drm_device *dev, const struct drm_debugfs_info *files, int count) 388 { 389 int i; 390 391 for (i = 0; i < count; i++) 392 drm_debugfs_add_file(dev, files[i].name, files[i].show, files[i].data); 393 } 394 EXPORT_SYMBOL(drm_debugfs_add_files); 395 396 static int connector_show(struct seq_file *m, void *data) 397 { 398 struct drm_connector *connector = m->private; 399 400 seq_printf(m, "%s\n", drm_get_connector_force_name(connector->force)); 401 402 return 0; 403 } 404 405 static int connector_open(struct inode *inode, struct file *file) 406 { 407 struct drm_connector *dev = inode->i_private; 408 409 return single_open(file, connector_show, dev); 410 } 411 412 static ssize_t connector_write(struct file *file, const char __user *ubuf, 413 size_t len, loff_t *offp) 414 { 415 struct seq_file *m = file->private_data; 416 struct drm_connector *connector = m->private; 417 char buf[12]; 418 419 if (len > sizeof(buf) - 1) 420 return -EINVAL; 421 422 if (copy_from_user(buf, ubuf, len)) 423 return -EFAULT; 424 425 buf[len] = '\0'; 426 427 if (sysfs_streq(buf, "on")) 428 connector->force = DRM_FORCE_ON; 429 else if (sysfs_streq(buf, "digital")) 430 connector->force = DRM_FORCE_ON_DIGITAL; 431 else if (sysfs_streq(buf, "off")) 432 connector->force = DRM_FORCE_OFF; 433 else if (sysfs_streq(buf, "unspecified")) 434 connector->force = DRM_FORCE_UNSPECIFIED; 435 else 436 return -EINVAL; 437 438 return len; 439 } 440 441 static int edid_show(struct seq_file *m, void *data) 442 { 443 return drm_edid_override_show(m->private, m); 444 } 445 446 static int edid_open(struct inode *inode, struct file *file) 447 { 448 struct drm_connector *dev = inode->i_private; 449 450 return single_open(file, edid_show, dev); 451 } 452 453 static ssize_t edid_write(struct file *file, const char __user *ubuf, 454 size_t len, loff_t *offp) 455 { 456 struct seq_file *m = file->private_data; 457 struct drm_connector *connector = m->private; 458 char *buf; 459 int ret; 460 461 buf = memdup_user(ubuf, len); 462 if (IS_ERR(buf)) 463 return PTR_ERR(buf); 464 465 if (len == 5 && !strncmp(buf, "reset", 5)) 466 ret = drm_edid_override_reset(connector); 467 else 468 ret = drm_edid_override_set(connector, buf, len); 469 470 kfree(buf); 471 472 return ret ? ret : len; 473 } 474 475 /* 476 * Returns the min and max vrr vfreq through the connector's debugfs file. 477 * Example usage: cat /sys/kernel/debug/dri/0/DP-1/vrr_range 478 */ 479 static int vrr_range_show(struct seq_file *m, void *data) 480 { 481 struct drm_connector *connector = m->private; 482 483 if (connector->status != connector_status_connected) 484 return -ENODEV; 485 486 seq_printf(m, "Min: %u\n", connector->display_info.monitor_range.min_vfreq); 487 seq_printf(m, "Max: %u\n", connector->display_info.monitor_range.max_vfreq); 488 489 return 0; 490 } 491 DEFINE_SHOW_ATTRIBUTE(vrr_range); 492 493 /* 494 * Returns Connector's max supported bpc through debugfs file. 495 * Example usage: cat /sys/kernel/debug/dri/0/DP-1/output_bpc 496 */ 497 static int output_bpc_show(struct seq_file *m, void *data) 498 { 499 struct drm_connector *connector = m->private; 500 501 if (connector->status != connector_status_connected) 502 return -ENODEV; 503 504 seq_printf(m, "Maximum: %u\n", connector->display_info.bpc); 505 506 return 0; 507 } 508 DEFINE_SHOW_ATTRIBUTE(output_bpc); 509 510 static const struct file_operations drm_edid_fops = { 511 .owner = THIS_MODULE, 512 .open = edid_open, 513 .read = seq_read, 514 .llseek = seq_lseek, 515 .release = single_release, 516 .write = edid_write 517 }; 518 519 520 static const struct file_operations drm_connector_fops = { 521 .owner = THIS_MODULE, 522 .open = connector_open, 523 .read = seq_read, 524 .llseek = seq_lseek, 525 .release = single_release, 526 .write = connector_write 527 }; 528 529 static ssize_t 530 audio_infoframe_read(struct file *filp, char __user *ubuf, size_t count, loff_t *ppos) 531 { 532 struct drm_connector_hdmi_infoframe *infoframe; 533 struct drm_connector *connector; 534 union hdmi_infoframe *frame; 535 u8 buf[HDMI_INFOFRAME_SIZE(AUDIO)]; 536 ssize_t len = 0; 537 538 connector = filp->private_data; 539 mutex_lock(&connector->hdmi.infoframes.lock); 540 541 infoframe = &connector->hdmi.infoframes.audio; 542 if (!infoframe->set) 543 goto out; 544 545 frame = &infoframe->data; 546 len = hdmi_infoframe_pack(frame, buf, sizeof(buf)); 547 if (len < 0) 548 goto out; 549 550 len = simple_read_from_buffer(ubuf, count, ppos, buf, len); 551 552 out: 553 mutex_unlock(&connector->hdmi.infoframes.lock); 554 return len; 555 } 556 557 static const struct file_operations audio_infoframe_fops = { 558 .owner = THIS_MODULE, 559 .open = simple_open, 560 .read = audio_infoframe_read, 561 }; 562 563 static int create_hdmi_audio_infoframe_file(struct drm_connector *connector, 564 struct dentry *parent) 565 { 566 struct dentry *file; 567 568 file = debugfs_create_file("audio", 0400, parent, connector, &audio_infoframe_fops); 569 if (IS_ERR(file)) 570 return PTR_ERR(file); 571 572 return 0; 573 } 574 575 #define DEFINE_INFOFRAME_FILE(_f) \ 576 static ssize_t _f##_read_infoframe(struct file *filp, \ 577 char __user *ubuf, \ 578 size_t count, \ 579 loff_t *ppos) \ 580 { \ 581 struct drm_connector_hdmi_infoframe *infoframe; \ 582 struct drm_connector_state *conn_state; \ 583 struct drm_connector *connector; \ 584 union hdmi_infoframe *frame; \ 585 struct drm_device *dev; \ 586 u8 buf[HDMI_INFOFRAME_SIZE(MAX)]; \ 587 ssize_t len = 0; \ 588 \ 589 connector = filp->private_data; \ 590 dev = connector->dev; \ 591 \ 592 drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); \ 593 \ 594 conn_state = connector->state; \ 595 infoframe = &conn_state->hdmi.infoframes._f; \ 596 if (!infoframe->set) \ 597 goto out; \ 598 \ 599 frame = &infoframe->data; \ 600 len = hdmi_infoframe_pack(frame, buf, sizeof(buf)); \ 601 if (len < 0) \ 602 goto out; \ 603 \ 604 len = simple_read_from_buffer(ubuf, count, ppos, buf, len); \ 605 \ 606 out: \ 607 drm_modeset_unlock(&dev->mode_config.connection_mutex); \ 608 return len; \ 609 } \ 610 \ 611 static const struct file_operations _f##_infoframe_fops = { \ 612 .owner = THIS_MODULE, \ 613 .open = simple_open, \ 614 .read = _f##_read_infoframe, \ 615 }; \ 616 \ 617 static int create_hdmi_## _f ## _infoframe_file(struct drm_connector *connector, \ 618 struct dentry *parent) \ 619 { \ 620 struct dentry *file; \ 621 \ 622 file = debugfs_create_file(#_f, 0400, parent, connector, &_f ## _infoframe_fops); \ 623 if (IS_ERR(file)) \ 624 return PTR_ERR(file); \ 625 \ 626 return 0; \ 627 } 628 629 DEFINE_INFOFRAME_FILE(avi); 630 DEFINE_INFOFRAME_FILE(hdmi); 631 DEFINE_INFOFRAME_FILE(hdr_drm); 632 DEFINE_INFOFRAME_FILE(spd); 633 634 static int create_hdmi_infoframe_files(struct drm_connector *connector, 635 struct dentry *parent) 636 { 637 int ret; 638 639 ret = create_hdmi_audio_infoframe_file(connector, parent); 640 if (ret) 641 return ret; 642 643 ret = create_hdmi_avi_infoframe_file(connector, parent); 644 if (ret) 645 return ret; 646 647 ret = create_hdmi_hdmi_infoframe_file(connector, parent); 648 if (ret) 649 return ret; 650 651 ret = create_hdmi_hdr_drm_infoframe_file(connector, parent); 652 if (ret) 653 return ret; 654 655 ret = create_hdmi_spd_infoframe_file(connector, parent); 656 if (ret) 657 return ret; 658 659 return 0; 660 } 661 662 static void hdmi_debugfs_add(struct drm_connector *connector) 663 { 664 struct dentry *dir; 665 666 if (!(connector->connector_type == DRM_MODE_CONNECTOR_HDMIA || 667 connector->connector_type == DRM_MODE_CONNECTOR_HDMIB)) 668 return; 669 670 dir = debugfs_create_dir("infoframes", connector->debugfs_entry); 671 if (IS_ERR(dir)) 672 return; 673 674 create_hdmi_infoframe_files(connector, dir); 675 } 676 677 void drm_debugfs_connector_add(struct drm_connector *connector) 678 { 679 struct drm_device *dev = connector->dev; 680 struct dentry *root; 681 682 if (!dev->debugfs_root) 683 return; 684 685 root = debugfs_create_dir(connector->name, dev->debugfs_root); 686 connector->debugfs_entry = root; 687 688 /* force */ 689 debugfs_create_file("force", 0644, root, connector, 690 &drm_connector_fops); 691 692 /* edid */ 693 debugfs_create_file("edid_override", 0644, root, connector, 694 &drm_edid_fops); 695 696 /* vrr range */ 697 debugfs_create_file("vrr_range", 0444, root, connector, 698 &vrr_range_fops); 699 700 /* max bpc */ 701 debugfs_create_file("output_bpc", 0444, root, connector, 702 &output_bpc_fops); 703 704 hdmi_debugfs_add(connector); 705 706 if (connector->funcs->debugfs_init) 707 connector->funcs->debugfs_init(connector, root); 708 } 709 710 void drm_debugfs_connector_remove(struct drm_connector *connector) 711 { 712 if (!connector->debugfs_entry) 713 return; 714 715 debugfs_remove_recursive(connector->debugfs_entry); 716 717 connector->debugfs_entry = NULL; 718 } 719 720 void drm_debugfs_crtc_add(struct drm_crtc *crtc) 721 { 722 struct drm_device *dev = crtc->dev; 723 struct dentry *root; 724 char *name; 725 726 name = kasprintf(GFP_KERNEL, "crtc-%d", crtc->index); 727 if (!name) 728 return; 729 730 root = debugfs_create_dir(name, dev->debugfs_root); 731 kfree(name); 732 733 crtc->debugfs_entry = root; 734 735 drm_debugfs_crtc_crc_add(crtc); 736 } 737 738 void drm_debugfs_crtc_remove(struct drm_crtc *crtc) 739 { 740 debugfs_remove_recursive(crtc->debugfs_entry); 741 crtc->debugfs_entry = NULL; 742 } 743 744 static int bridges_show(struct seq_file *m, void *data) 745 { 746 struct drm_encoder *encoder = m->private; 747 struct drm_printer p = drm_seq_file_printer(m); 748 struct drm_bridge *bridge; 749 unsigned int idx = 0; 750 751 drm_for_each_bridge_in_chain(encoder, bridge) { 752 drm_printf(&p, "bridge[%d]: %ps\n", idx++, bridge->funcs); 753 drm_printf(&p, "\ttype: [%d] %s\n", 754 bridge->type, 755 drm_get_connector_type_name(bridge->type)); 756 757 if (bridge->of_node) 758 drm_printf(&p, "\tOF: %pOFfc\n", bridge->of_node); 759 760 drm_printf(&p, "\tops: [0x%x]", bridge->ops); 761 if (bridge->ops & DRM_BRIDGE_OP_DETECT) 762 drm_puts(&p, " detect"); 763 if (bridge->ops & DRM_BRIDGE_OP_EDID) 764 drm_puts(&p, " edid"); 765 if (bridge->ops & DRM_BRIDGE_OP_HPD) 766 drm_puts(&p, " hpd"); 767 if (bridge->ops & DRM_BRIDGE_OP_MODES) 768 drm_puts(&p, " modes"); 769 if (bridge->ops & DRM_BRIDGE_OP_HDMI) 770 drm_puts(&p, " hdmi"); 771 drm_puts(&p, "\n"); 772 } 773 774 return 0; 775 } 776 DEFINE_SHOW_ATTRIBUTE(bridges); 777 778 void drm_debugfs_encoder_add(struct drm_encoder *encoder) 779 { 780 struct drm_minor *minor = encoder->dev->primary; 781 struct dentry *root; 782 char *name; 783 784 name = kasprintf(GFP_KERNEL, "encoder-%d", encoder->index); 785 if (!name) 786 return; 787 788 root = debugfs_create_dir(name, minor->debugfs_root); 789 kfree(name); 790 791 encoder->debugfs_entry = root; 792 793 /* bridges list */ 794 debugfs_create_file("bridges", 0444, root, encoder, 795 &bridges_fops); 796 797 if (encoder->funcs && encoder->funcs->debugfs_init) 798 encoder->funcs->debugfs_init(encoder, root); 799 } 800 801 void drm_debugfs_encoder_remove(struct drm_encoder *encoder) 802 { 803 debugfs_remove_recursive(encoder->debugfs_entry); 804 encoder->debugfs_entry = NULL; 805 } 806