exynos_drm_dsi.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Samsung MIPI DSIM glue for Exynos SoCs.
  4. *
  5. * Copyright (c) 2014 Samsung Electronics Co., Ltd
  6. *
  7. * Contacts: Tomasz Figa <t.figa@samsung.com>
  8. */
  9. #include <linux/component.h>
  10. #include <linux/of.h>
  11. #include <linux/platform_device.h>
  12. #include <drm/bridge/samsung-dsim.h>
  13. #include <drm/drm_probe_helper.h>
  14. #include <drm/drm_simple_kms_helper.h>
  15. #include "exynos_drm_crtc.h"
  16. #include "exynos_drm_drv.h"
  17. struct exynos_dsi {
  18. struct drm_encoder encoder;
  19. };
  20. static irqreturn_t exynos_dsi_te_irq_handler(struct samsung_dsim *dsim)
  21. {
  22. struct exynos_dsi *dsi = dsim->priv;
  23. struct drm_encoder *encoder = &dsi->encoder;
  24. if (dsim->state & DSIM_STATE_VIDOUT_AVAILABLE)
  25. exynos_drm_crtc_te_handler(encoder->crtc);
  26. return IRQ_HANDLED;
  27. }
  28. static int exynos_dsi_host_attach(struct samsung_dsim *dsim,
  29. struct mipi_dsi_device *device)
  30. {
  31. struct exynos_dsi *dsi = dsim->priv;
  32. struct drm_encoder *encoder = &dsi->encoder;
  33. struct drm_device *drm = encoder->dev;
  34. drm_bridge_attach(encoder, &dsim->bridge,
  35. list_first_entry_or_null(&encoder->bridge_chain,
  36. struct drm_bridge,
  37. chain_node), 0);
  38. mutex_lock(&drm->mode_config.mutex);
  39. dsim->lanes = device->lanes;
  40. dsim->format = device->format;
  41. dsim->mode_flags = device->mode_flags;
  42. exynos_drm_crtc_get_by_type(drm, EXYNOS_DISPLAY_TYPE_LCD)->i80_mode =
  43. !(dsim->mode_flags & MIPI_DSI_MODE_VIDEO);
  44. mutex_unlock(&drm->mode_config.mutex);
  45. if (drm->mode_config.poll_enabled)
  46. drm_kms_helper_hotplug_event(drm);
  47. return 0;
  48. }
  49. static void exynos_dsi_host_detach(struct samsung_dsim *dsim,
  50. struct mipi_dsi_device *device)
  51. {
  52. struct exynos_dsi *dsi = dsim->priv;
  53. struct drm_device *drm = dsi->encoder.dev;
  54. if (drm->mode_config.poll_enabled)
  55. drm_kms_helper_hotplug_event(drm);
  56. }
  57. static int exynos_dsi_bind(struct device *dev, struct device *master, void *data)
  58. {
  59. struct samsung_dsim *dsim = dev_get_drvdata(dev);
  60. struct exynos_dsi *dsi = dsim->priv;
  61. struct drm_encoder *encoder = &dsi->encoder;
  62. struct drm_device *drm_dev = data;
  63. int ret;
  64. drm_simple_encoder_init(drm_dev, encoder, DRM_MODE_ENCODER_TMDS);
  65. ret = exynos_drm_set_possible_crtcs(encoder, EXYNOS_DISPLAY_TYPE_LCD);
  66. if (ret < 0)
  67. return ret;
  68. return mipi_dsi_host_register(&dsim->dsi_host);
  69. }
  70. static void exynos_dsi_unbind(struct device *dev, struct device *master, void *data)
  71. {
  72. struct samsung_dsim *dsim = dev_get_drvdata(dev);
  73. dsim->bridge.funcs->atomic_disable(&dsim->bridge, NULL);
  74. mipi_dsi_host_unregister(&dsim->dsi_host);
  75. }
  76. static const struct component_ops exynos_dsi_component_ops = {
  77. .bind = exynos_dsi_bind,
  78. .unbind = exynos_dsi_unbind,
  79. };
  80. static int exynos_dsi_register_host(struct samsung_dsim *dsim)
  81. {
  82. struct exynos_dsi *dsi;
  83. dsi = devm_kzalloc(dsim->dev, sizeof(*dsi), GFP_KERNEL);
  84. if (!dsi)
  85. return -ENOMEM;
  86. dsim->priv = dsi;
  87. dsim->bridge.pre_enable_prev_first = true;
  88. return component_add(dsim->dev, &exynos_dsi_component_ops);
  89. }
  90. static void exynos_dsi_unregister_host(struct samsung_dsim *dsim)
  91. {
  92. component_del(dsim->dev, &exynos_dsi_component_ops);
  93. }
  94. static const struct samsung_dsim_host_ops exynos_dsi_exynos_host_ops = {
  95. .register_host = exynos_dsi_register_host,
  96. .unregister_host = exynos_dsi_unregister_host,
  97. .attach = exynos_dsi_host_attach,
  98. .detach = exynos_dsi_host_detach,
  99. .te_irq_handler = exynos_dsi_te_irq_handler,
  100. };
  101. static const struct samsung_dsim_plat_data exynos3250_dsi_pdata = {
  102. .hw_type = DSIM_TYPE_EXYNOS3250,
  103. .host_ops = &exynos_dsi_exynos_host_ops,
  104. };
  105. static const struct samsung_dsim_plat_data exynos4210_dsi_pdata = {
  106. .hw_type = DSIM_TYPE_EXYNOS4210,
  107. .host_ops = &exynos_dsi_exynos_host_ops,
  108. };
  109. static const struct samsung_dsim_plat_data exynos5410_dsi_pdata = {
  110. .hw_type = DSIM_TYPE_EXYNOS5410,
  111. .host_ops = &exynos_dsi_exynos_host_ops,
  112. };
  113. static const struct samsung_dsim_plat_data exynos5422_dsi_pdata = {
  114. .hw_type = DSIM_TYPE_EXYNOS5422,
  115. .host_ops = &exynos_dsi_exynos_host_ops,
  116. };
  117. static const struct samsung_dsim_plat_data exynos5433_dsi_pdata = {
  118. .hw_type = DSIM_TYPE_EXYNOS5433,
  119. .host_ops = &exynos_dsi_exynos_host_ops,
  120. };
  121. static const struct of_device_id exynos_dsi_of_match[] = {
  122. {
  123. .compatible = "samsung,exynos3250-mipi-dsi",
  124. .data = &exynos3250_dsi_pdata,
  125. },
  126. {
  127. .compatible = "samsung,exynos4210-mipi-dsi",
  128. .data = &exynos4210_dsi_pdata,
  129. },
  130. {
  131. .compatible = "samsung,exynos5410-mipi-dsi",
  132. .data = &exynos5410_dsi_pdata,
  133. },
  134. {
  135. .compatible = "samsung,exynos5422-mipi-dsi",
  136. .data = &exynos5422_dsi_pdata,
  137. },
  138. {
  139. .compatible = "samsung,exynos5433-mipi-dsi",
  140. .data = &exynos5433_dsi_pdata,
  141. },
  142. { /* sentinel. */ }
  143. };
  144. MODULE_DEVICE_TABLE(of, exynos_dsi_of_match);
  145. struct platform_driver dsi_driver = {
  146. .probe = samsung_dsim_probe,
  147. .remove_new = samsung_dsim_remove,
  148. .driver = {
  149. .name = "exynos-dsi",
  150. .pm = &samsung_dsim_pm_ops,
  151. .of_match_table = exynos_dsi_of_match,
  152. },
  153. };
  154. MODULE_AUTHOR("Tomasz Figa <t.figa@samsung.com>");
  155. MODULE_AUTHOR("Andrzej Hajda <a.hajda@samsung.com>");
  156. MODULE_DESCRIPTION("Samsung SoC MIPI DSI Master");
  157. MODULE_LICENSE("GPL v2");