pl111_connector.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. /*
  2. * (C) COPYRIGHT 2012-2013 ARM Limited. All rights reserved.
  3. *
  4. * Parts of this file were based on sources as follows:
  5. *
  6. * Copyright (c) 2006-2008 Intel Corporation
  7. * Copyright (c) 2007 Dave Airlie <airlied@linux.ie>
  8. * Copyright (C) 2011 Texas Instruments
  9. *
  10. * This program is free software and is provided to you under the terms of the
  11. * GNU General Public License version 2 as published by the Free Software
  12. * Foundation, and any use by you of this program is subject to the terms of
  13. * such GNU licence.
  14. *
  15. */
  16. /**
  17. * pl111_drm_connector.c
  18. * Implementation of the connector functions for PL111 DRM
  19. */
  20. #include <linux/amba/clcd-regs.h>
  21. #include <linux/version.h>
  22. #include <linux/shmem_fs.h>
  23. #include <linux/dma-buf.h>
  24. #include <drm/drmP.h>
  25. #include <drm/drm_atomic_helper.h>
  26. #include <drm/drm_crtc_helper.h>
  27. #include <drm/drm_of.h>
  28. #include <drm/drm_panel.h>
  29. #include "pl111_drm.h"
  30. static void pl111_connector_destroy(struct drm_connector *connector)
  31. {
  32. struct pl111_drm_connector *pl111_connector =
  33. to_pl111_connector(connector);
  34. if (pl111_connector->panel)
  35. drm_panel_detach(pl111_connector->panel);
  36. drm_connector_unregister(connector);
  37. drm_connector_cleanup(connector);
  38. }
  39. static enum drm_connector_status pl111_connector_detect(struct drm_connector
  40. *connector, bool force)
  41. {
  42. struct pl111_drm_connector *pl111_connector =
  43. to_pl111_connector(connector);
  44. return (pl111_connector->panel ?
  45. connector_status_connected :
  46. connector_status_disconnected);
  47. }
  48. static int pl111_connector_helper_get_modes(struct drm_connector *connector)
  49. {
  50. struct pl111_drm_connector *pl111_connector =
  51. to_pl111_connector(connector);
  52. if (!pl111_connector->panel)
  53. return 0;
  54. return drm_panel_get_modes(pl111_connector->panel);
  55. }
  56. const struct drm_connector_funcs connector_funcs = {
  57. .fill_modes = drm_helper_probe_single_connector_modes,
  58. .destroy = pl111_connector_destroy,
  59. .detect = pl111_connector_detect,
  60. .reset = drm_atomic_helper_connector_reset,
  61. .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
  62. .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
  63. };
  64. const struct drm_connector_helper_funcs connector_helper_funcs = {
  65. .get_modes = pl111_connector_helper_get_modes,
  66. };
  67. /* Walks the OF graph to find the panel node and then asks DRM to look
  68. * up the panel.
  69. */
  70. static struct drm_panel *pl111_get_panel(struct device *dev)
  71. {
  72. struct device_node *endpoint, *panel_node;
  73. struct device_node *np = dev->of_node;
  74. struct drm_panel *panel;
  75. endpoint = of_graph_get_next_endpoint(np, NULL);
  76. if (!endpoint) {
  77. dev_err(dev, "no endpoint to fetch panel\n");
  78. return NULL;
  79. }
  80. /* don't proceed if we have an endpoint but no panel_node tied to it */
  81. panel_node = of_graph_get_remote_port_parent(endpoint);
  82. of_node_put(endpoint);
  83. if (!panel_node) {
  84. dev_err(dev, "no valid panel node\n");
  85. return NULL;
  86. }
  87. panel = of_drm_find_panel(panel_node);
  88. of_node_put(panel_node);
  89. return panel;
  90. }
  91. int pl111_connector_init(struct drm_device *dev)
  92. {
  93. struct pl111_drm_dev_private *priv = dev->dev_private;
  94. struct pl111_drm_connector *pl111_connector = &priv->connector;
  95. struct drm_connector *connector = &pl111_connector->connector;
  96. drm_connector_init(dev, connector, &connector_funcs,
  97. DRM_MODE_CONNECTOR_DPI);
  98. drm_connector_helper_add(connector, &connector_helper_funcs);
  99. pl111_connector->panel = pl111_get_panel(dev->dev);
  100. if (pl111_connector->panel)
  101. drm_panel_attach(pl111_connector->panel, connector);
  102. return 0;
  103. }