drm_bridge_connector.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (C) 2019 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
  4. */
  5. #include <linux/kernel.h>
  6. #include <linux/module.h>
  7. #include <linux/slab.h>
  8. #include <drm/drm_atomic_state_helper.h>
  9. #include <drm/drm_bridge.h>
  10. #include <drm/drm_bridge_connector.h>
  11. #include <drm/drm_connector.h>
  12. #include <drm/drm_device.h>
  13. #include <drm/drm_edid.h>
  14. #include <drm/drm_modeset_helper_vtables.h>
  15. #include <drm/drm_probe_helper.h>
  16. /**
  17. * DOC: overview
  18. *
  19. * The DRM bridge connector helper object provides a DRM connector
  20. * implementation that wraps a chain of &struct drm_bridge. The connector
  21. * operations are fully implemented based on the operations of the bridges in
  22. * the chain, and don't require any intervention from the display controller
  23. * driver at runtime.
  24. *
  25. * To use the helper, display controller drivers create a bridge connector with
  26. * a call to drm_bridge_connector_init(). This associates the newly created
  27. * connector with the chain of bridges passed to the function and registers it
  28. * with the DRM device. At that point the connector becomes fully usable, no
  29. * further operation is needed.
  30. *
  31. * The DRM bridge connector operations are implemented based on the operations
  32. * provided by the bridges in the chain. Each connector operation is delegated
  33. * to the bridge closest to the connector (at the end of the chain) that
  34. * provides the relevant functionality.
  35. *
  36. * To make use of this helper, all bridges in the chain shall report bridge
  37. * operation flags (&drm_bridge->ops) and bridge output type
  38. * (&drm_bridge->type), as well as the DRM_BRIDGE_ATTACH_NO_CONNECTOR attach
  39. * flag (none of the bridges shall create a DRM connector directly).
  40. */
  41. /**
  42. * struct drm_bridge_connector - A connector backed by a chain of bridges
  43. */
  44. struct drm_bridge_connector {
  45. /**
  46. * @base: The base DRM connector
  47. */
  48. struct drm_connector base;
  49. /**
  50. * @encoder:
  51. *
  52. * The encoder at the start of the bridges chain.
  53. */
  54. struct drm_encoder *encoder;
  55. /**
  56. * @bridge_edid:
  57. *
  58. * The last bridge in the chain (closest to the connector) that provides
  59. * EDID read support, if any (see &DRM_BRIDGE_OP_EDID).
  60. */
  61. struct drm_bridge *bridge_edid;
  62. /**
  63. * @bridge_hpd:
  64. *
  65. * The last bridge in the chain (closest to the connector) that provides
  66. * hot-plug detection notification, if any (see &DRM_BRIDGE_OP_HPD).
  67. */
  68. struct drm_bridge *bridge_hpd;
  69. /**
  70. * @bridge_detect:
  71. *
  72. * The last bridge in the chain (closest to the connector) that provides
  73. * connector detection, if any (see &DRM_BRIDGE_OP_DETECT).
  74. */
  75. struct drm_bridge *bridge_detect;
  76. /**
  77. * @bridge_modes:
  78. *
  79. * The last bridge in the chain (closest to the connector) that provides
  80. * connector modes detection, if any (see &DRM_BRIDGE_OP_MODES).
  81. */
  82. struct drm_bridge *bridge_modes;
  83. };
  84. #define to_drm_bridge_connector(x) \
  85. container_of(x, struct drm_bridge_connector, base)
  86. /* -----------------------------------------------------------------------------
  87. * Bridge Connector Hot-Plug Handling
  88. */
  89. static void drm_bridge_connector_hpd_notify(struct drm_connector *connector,
  90. enum drm_connector_status status)
  91. {
  92. struct drm_bridge_connector *bridge_connector =
  93. to_drm_bridge_connector(connector);
  94. struct drm_bridge *bridge;
  95. /* Notify all bridges in the pipeline of hotplug events. */
  96. drm_for_each_bridge_in_chain(bridge_connector->encoder, bridge) {
  97. if (bridge->funcs->hpd_notify)
  98. bridge->funcs->hpd_notify(bridge, status);
  99. }
  100. }
  101. static void drm_bridge_connector_hpd_cb(void *cb_data,
  102. enum drm_connector_status status)
  103. {
  104. struct drm_bridge_connector *drm_bridge_connector = cb_data;
  105. struct drm_connector *connector = &drm_bridge_connector->base;
  106. struct drm_device *dev = connector->dev;
  107. enum drm_connector_status old_status;
  108. mutex_lock(&dev->mode_config.mutex);
  109. old_status = connector->status;
  110. connector->status = status;
  111. mutex_unlock(&dev->mode_config.mutex);
  112. if (old_status == status)
  113. return;
  114. drm_bridge_connector_hpd_notify(connector, status);
  115. drm_kms_helper_hotplug_event(dev);
  116. }
  117. /**
  118. * drm_bridge_connector_enable_hpd - Enable hot-plug detection for the connector
  119. * @connector: The DRM bridge connector
  120. *
  121. * This function enables hot-plug detection for the given bridge connector.
  122. * This is typically used by display drivers in their resume handler.
  123. */
  124. void drm_bridge_connector_enable_hpd(struct drm_connector *connector)
  125. {
  126. struct drm_bridge_connector *bridge_connector =
  127. to_drm_bridge_connector(connector);
  128. struct drm_bridge *hpd = bridge_connector->bridge_hpd;
  129. if (hpd)
  130. drm_bridge_hpd_enable(hpd, drm_bridge_connector_hpd_cb,
  131. bridge_connector);
  132. }
  133. EXPORT_SYMBOL_GPL(drm_bridge_connector_enable_hpd);
  134. /**
  135. * drm_bridge_connector_disable_hpd - Disable hot-plug detection for the
  136. * connector
  137. * @connector: The DRM bridge connector
  138. *
  139. * This function disables hot-plug detection for the given bridge connector.
  140. * This is typically used by display drivers in their suspend handler.
  141. */
  142. void drm_bridge_connector_disable_hpd(struct drm_connector *connector)
  143. {
  144. struct drm_bridge_connector *bridge_connector =
  145. to_drm_bridge_connector(connector);
  146. struct drm_bridge *hpd = bridge_connector->bridge_hpd;
  147. if (hpd)
  148. drm_bridge_hpd_disable(hpd);
  149. }
  150. EXPORT_SYMBOL_GPL(drm_bridge_connector_disable_hpd);
  151. /* -----------------------------------------------------------------------------
  152. * Bridge Connector Functions
  153. */
  154. static enum drm_connector_status
  155. drm_bridge_connector_detect(struct drm_connector *connector, bool force)
  156. {
  157. struct drm_bridge_connector *bridge_connector =
  158. to_drm_bridge_connector(connector);
  159. struct drm_bridge *detect = bridge_connector->bridge_detect;
  160. enum drm_connector_status status;
  161. if (detect) {
  162. status = detect->funcs->detect(detect);
  163. drm_bridge_connector_hpd_notify(connector, status);
  164. } else {
  165. switch (connector->connector_type) {
  166. case DRM_MODE_CONNECTOR_DPI:
  167. case DRM_MODE_CONNECTOR_LVDS:
  168. case DRM_MODE_CONNECTOR_DSI:
  169. case DRM_MODE_CONNECTOR_eDP:
  170. status = connector_status_connected;
  171. break;
  172. default:
  173. status = connector_status_unknown;
  174. break;
  175. }
  176. }
  177. return status;
  178. }
  179. static void drm_bridge_connector_destroy(struct drm_connector *connector)
  180. {
  181. struct drm_bridge_connector *bridge_connector =
  182. to_drm_bridge_connector(connector);
  183. if (bridge_connector->bridge_hpd) {
  184. struct drm_bridge *hpd = bridge_connector->bridge_hpd;
  185. drm_bridge_hpd_disable(hpd);
  186. }
  187. drm_connector_unregister(connector);
  188. drm_connector_cleanup(connector);
  189. kfree(bridge_connector);
  190. }
  191. static const struct drm_connector_funcs drm_bridge_connector_funcs = {
  192. .reset = drm_atomic_helper_connector_reset,
  193. .detect = drm_bridge_connector_detect,
  194. .fill_modes = drm_helper_probe_single_connector_modes,
  195. .destroy = drm_bridge_connector_destroy,
  196. .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
  197. .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
  198. };
  199. /* -----------------------------------------------------------------------------
  200. * Bridge Connector Helper Functions
  201. */
  202. static int drm_bridge_connector_get_modes_edid(struct drm_connector *connector,
  203. struct drm_bridge *bridge)
  204. {
  205. enum drm_connector_status status;
  206. struct edid *edid;
  207. int n;
  208. status = drm_bridge_connector_detect(connector, false);
  209. if (status != connector_status_connected)
  210. goto no_edid;
  211. edid = bridge->funcs->get_edid(bridge, connector);
  212. if (!edid || !drm_edid_is_valid(edid)) {
  213. kfree(edid);
  214. goto no_edid;
  215. }
  216. drm_connector_update_edid_property(connector, edid);
  217. n = drm_add_edid_modes(connector, edid);
  218. kfree(edid);
  219. return n;
  220. no_edid:
  221. drm_connector_update_edid_property(connector, NULL);
  222. return 0;
  223. }
  224. static int drm_bridge_connector_get_modes(struct drm_connector *connector)
  225. {
  226. struct drm_bridge_connector *bridge_connector =
  227. to_drm_bridge_connector(connector);
  228. struct drm_bridge *bridge;
  229. /*
  230. * If display exposes EDID, then we parse that in the normal way to
  231. * build table of supported modes.
  232. */
  233. bridge = bridge_connector->bridge_edid;
  234. if (bridge)
  235. return drm_bridge_connector_get_modes_edid(connector, bridge);
  236. /*
  237. * Otherwise if the display pipeline reports modes (e.g. with a fixed
  238. * resolution panel or an analog TV output), query it.
  239. */
  240. bridge = bridge_connector->bridge_modes;
  241. if (bridge)
  242. return bridge->funcs->get_modes(bridge, connector);
  243. /*
  244. * We can't retrieve modes, which can happen for instance for a DVI or
  245. * VGA output with the DDC bus unconnected. The KMS core will add the
  246. * default modes.
  247. */
  248. return 0;
  249. }
  250. static const struct drm_connector_helper_funcs drm_bridge_connector_helper_funcs = {
  251. .get_modes = drm_bridge_connector_get_modes,
  252. /* No need for .mode_valid(), the bridges are checked by the core. */
  253. };
  254. /* -----------------------------------------------------------------------------
  255. * Bridge Connector Initialisation
  256. */
  257. /**
  258. * drm_bridge_connector_init - Initialise a connector for a chain of bridges
  259. * @drm: the DRM device
  260. * @encoder: the encoder where the bridge chain starts
  261. *
  262. * Allocate, initialise and register a &drm_bridge_connector with the @drm
  263. * device. The connector is associated with a chain of bridges that starts at
  264. * the @encoder. All bridges in the chain shall report bridge operation flags
  265. * (&drm_bridge->ops) and bridge output type (&drm_bridge->type), and none of
  266. * them may create a DRM connector directly.
  267. *
  268. * Returns a pointer to the new connector on success, or a negative error
  269. * pointer otherwise.
  270. */
  271. struct drm_connector *drm_bridge_connector_init(struct drm_device *drm,
  272. struct drm_encoder *encoder)
  273. {
  274. struct drm_bridge_connector *bridge_connector;
  275. struct drm_connector *connector;
  276. struct i2c_adapter *ddc = NULL;
  277. struct drm_bridge *bridge;
  278. int connector_type;
  279. bridge_connector = kzalloc(sizeof(*bridge_connector), GFP_KERNEL);
  280. if (!bridge_connector)
  281. return ERR_PTR(-ENOMEM);
  282. bridge_connector->encoder = encoder;
  283. /*
  284. * TODO: Handle doublescan_allowed, stereo_allowed and
  285. * ycbcr_420_allowed.
  286. */
  287. connector = &bridge_connector->base;
  288. connector->interlace_allowed = true;
  289. /*
  290. * Initialise connector status handling. First locate the furthest
  291. * bridges in the pipeline that support HPD and output detection. Then
  292. * initialise the connector polling mode, using HPD if available and
  293. * falling back to polling if supported. If neither HPD nor output
  294. * detection are available, we don't support hotplug detection at all.
  295. */
  296. connector_type = DRM_MODE_CONNECTOR_Unknown;
  297. drm_for_each_bridge_in_chain(encoder, bridge) {
  298. if (!bridge->interlace_allowed)
  299. connector->interlace_allowed = false;
  300. if (bridge->ops & DRM_BRIDGE_OP_EDID)
  301. bridge_connector->bridge_edid = bridge;
  302. if (bridge->ops & DRM_BRIDGE_OP_HPD)
  303. bridge_connector->bridge_hpd = bridge;
  304. if (bridge->ops & DRM_BRIDGE_OP_DETECT)
  305. bridge_connector->bridge_detect = bridge;
  306. if (bridge->ops & DRM_BRIDGE_OP_MODES)
  307. bridge_connector->bridge_modes = bridge;
  308. if (!drm_bridge_get_next_bridge(bridge))
  309. connector_type = bridge->type;
  310. if (bridge->ddc)
  311. ddc = bridge->ddc;
  312. }
  313. if (connector_type == DRM_MODE_CONNECTOR_Unknown) {
  314. kfree(bridge_connector);
  315. return ERR_PTR(-EINVAL);
  316. }
  317. drm_connector_init_with_ddc(drm, connector, &drm_bridge_connector_funcs,
  318. connector_type, ddc);
  319. drm_connector_helper_add(connector, &drm_bridge_connector_helper_funcs);
  320. if (bridge_connector->bridge_hpd)
  321. connector->polled = DRM_CONNECTOR_POLL_HPD;
  322. else if (bridge_connector->bridge_detect)
  323. connector->polled = DRM_CONNECTOR_POLL_CONNECT
  324. | DRM_CONNECTOR_POLL_DISCONNECT;
  325. return connector;
  326. }
  327. EXPORT_SYMBOL_GPL(drm_bridge_connector_init);