0079-media-cadence-Add-support-for-external-dphy.patch 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. From e97eb58b321b5b25b7d5c40880e6eb133d381581 Mon Sep 17 00:00:00 2001
  2. From: Jack Zhu <[email protected]>
  3. Date: Tue, 23 May 2023 16:56:25 +0800
  4. Subject: [PATCH 079/122] media: cadence: Add support for external dphy
  5. Add support for external MIPI D-PHY.
  6. Reviewed-by: Laurent Pinchart <[email protected]>
  7. Signed-off-by: Jack Zhu <[email protected]>
  8. ---
  9. drivers/media/platform/cadence/cdns-csi2rx.c | 66 +++++++++++++++++---
  10. 1 file changed, 56 insertions(+), 10 deletions(-)
  11. --- a/drivers/media/platform/cadence/cdns-csi2rx.c
  12. +++ b/drivers/media/platform/cadence/cdns-csi2rx.c
  13. @@ -31,6 +31,12 @@
  14. #define CSI2RX_STATIC_CFG_DLANE_MAP(llane, plane) ((plane) << (16 + (llane) * 4))
  15. #define CSI2RX_STATIC_CFG_LANES_MASK GENMASK(11, 8)
  16. +#define CSI2RX_DPHY_LANE_CTRL_REG 0x40
  17. +#define CSI2RX_DPHY_CL_RST BIT(16)
  18. +#define CSI2RX_DPHY_DL_RST(i) BIT((i) + 12)
  19. +#define CSI2RX_DPHY_CL_EN BIT(4)
  20. +#define CSI2RX_DPHY_DL_EN(i) BIT(i)
  21. +
  22. #define CSI2RX_STREAM_BASE(n) (((n) + 1) * 0x100)
  23. #define CSI2RX_STREAM_CTRL_REG(n) (CSI2RX_STREAM_BASE(n) + 0x000)
  24. @@ -105,6 +111,24 @@ static void csi2rx_reset(struct csi2rx_p
  25. writel(0, csi2rx->base + CSI2RX_SOFT_RESET_REG);
  26. }
  27. +static int csi2rx_configure_ext_dphy(struct csi2rx_priv *csi2rx)
  28. +{
  29. + union phy_configure_opts opts = { };
  30. + int ret;
  31. +
  32. + ret = phy_power_on(csi2rx->dphy);
  33. + if (ret)
  34. + return ret;
  35. +
  36. + ret = phy_configure(csi2rx->dphy, &opts);
  37. + if (ret) {
  38. + phy_power_off(csi2rx->dphy);
  39. + return ret;
  40. + }
  41. +
  42. + return 0;
  43. +}
  44. +
  45. static int csi2rx_start(struct csi2rx_priv *csi2rx)
  46. {
  47. unsigned int i;
  48. @@ -144,6 +168,17 @@ static int csi2rx_start(struct csi2rx_pr
  49. if (ret)
  50. goto err_disable_pclk;
  51. + /* Enable DPHY clk and data lanes. */
  52. + if (csi2rx->dphy) {
  53. + reg = CSI2RX_DPHY_CL_EN | CSI2RX_DPHY_CL_RST;
  54. + for (i = 0; i < csi2rx->num_lanes; i++) {
  55. + reg |= CSI2RX_DPHY_DL_EN(csi2rx->lanes[i] - 1);
  56. + reg |= CSI2RX_DPHY_DL_RST(csi2rx->lanes[i] - 1);
  57. + }
  58. +
  59. + writel(reg, csi2rx->base + CSI2RX_DPHY_LANE_CTRL_REG);
  60. + }
  61. +
  62. /*
  63. * Create a static mapping between the CSI virtual channels
  64. * and the output stream.
  65. @@ -177,10 +212,22 @@ static int csi2rx_start(struct csi2rx_pr
  66. goto err_disable_pixclk;
  67. reset_control_deassert(csi2rx->sys_rst);
  68. +
  69. + if (csi2rx->dphy) {
  70. + ret = csi2rx_configure_ext_dphy(csi2rx);
  71. + if (ret) {
  72. + dev_err(csi2rx->dev,
  73. + "Failed to configure external DPHY: %d\n", ret);
  74. + goto err_disable_sysclk;
  75. + }
  76. + }
  77. +
  78. clk_disable_unprepare(csi2rx->p_clk);
  79. return 0;
  80. +err_disable_sysclk:
  81. + clk_disable_unprepare(csi2rx->sys_clk);
  82. err_disable_pixclk:
  83. for (; i > 0; i--) {
  84. reset_control_assert(csi2rx->pixel_rst[i - 1]);
  85. @@ -213,6 +260,13 @@ static void csi2rx_stop(struct csi2rx_pr
  86. if (v4l2_subdev_call(csi2rx->source_subdev, video, s_stream, false))
  87. dev_warn(csi2rx->dev, "Couldn't disable our subdev\n");
  88. +
  89. + if (csi2rx->dphy) {
  90. + writel(0, csi2rx->base + CSI2RX_DPHY_LANE_CTRL_REG);
  91. +
  92. + if (phy_power_off(csi2rx->dphy))
  93. + dev_warn(csi2rx->dev, "Couldn't power off DPHY\n");
  94. + }
  95. }
  96. static int csi2rx_s_stream(struct v4l2_subdev *subdev, int enable)
  97. @@ -328,15 +382,6 @@ static int csi2rx_get_resources(struct c
  98. return PTR_ERR(csi2rx->dphy);
  99. }
  100. - /*
  101. - * FIXME: Once we'll have external D-PHY support, the check
  102. - * will need to be removed.
  103. - */
  104. - if (csi2rx->dphy) {
  105. - dev_err(&pdev->dev, "External D-PHY not supported yet\n");
  106. - return -EINVAL;
  107. - }
  108. -
  109. ret = clk_prepare_enable(csi2rx->p_clk);
  110. if (ret) {
  111. dev_err(&pdev->dev, "Couldn't prepare and enable P clock\n");
  112. @@ -366,7 +411,7 @@ static int csi2rx_get_resources(struct c
  113. * FIXME: Once we'll have internal D-PHY support, the check
  114. * will need to be removed.
  115. */
  116. - if (csi2rx->has_internal_dphy) {
  117. + if (!csi2rx->dphy && csi2rx->has_internal_dphy) {
  118. dev_err(&pdev->dev, "Internal D-PHY not supported yet\n");
  119. return -EINVAL;
  120. }
  121. @@ -494,6 +539,7 @@ static int csi2rx_probe(struct platform_
  122. dev_info(&pdev->dev,
  123. "Probed CSI2RX with %u/%u lanes, %u streams, %s D-PHY\n",
  124. csi2rx->num_lanes, csi2rx->max_lanes, csi2rx->max_streams,
  125. + csi2rx->dphy ? "external" :
  126. csi2rx->has_internal_dphy ? "internal" : "no");
  127. return 0;