analogix-i2c-dptx.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. /* SPDX-License-Identifier: GPL-2.0-only */
  2. /*
  3. * Copyright(c) 2016, Analogix Semiconductor.
  4. *
  5. * Based on anx7808 driver obtained from chromeos with copyright:
  6. * Copyright(c) 2013, Google Inc.
  7. */
  8. #include <linux/regmap.h>
  9. #include <drm/display/drm_dp_helper.h>
  10. #include <drm/drm.h>
  11. #include <drm/drm_print.h>
  12. #include "analogix-i2c-dptx.h"
  13. #define AUX_WAIT_TIMEOUT_MS 15
  14. #define AUX_CH_BUFFER_SIZE 16
  15. static int anx_i2c_dp_clear_bits(struct regmap *map, u8 reg, u8 mask)
  16. {
  17. return regmap_update_bits(map, reg, mask, 0);
  18. }
  19. static bool anx_dp_aux_op_finished(struct regmap *map_dptx)
  20. {
  21. unsigned int value;
  22. int err;
  23. err = regmap_read(map_dptx, SP_DP_AUX_CH_CTRL2_REG, &value);
  24. if (err < 0)
  25. return false;
  26. return (value & SP_AUX_EN) == 0;
  27. }
  28. static int anx_dp_aux_wait(struct regmap *map_dptx)
  29. {
  30. unsigned long timeout;
  31. unsigned int status;
  32. int err;
  33. timeout = jiffies + msecs_to_jiffies(AUX_WAIT_TIMEOUT_MS) + 1;
  34. while (!anx_dp_aux_op_finished(map_dptx)) {
  35. if (time_after(jiffies, timeout)) {
  36. if (!anx_dp_aux_op_finished(map_dptx)) {
  37. DRM_ERROR("Timed out waiting AUX to finish\n");
  38. return -ETIMEDOUT;
  39. }
  40. break;
  41. }
  42. usleep_range(1000, 2000);
  43. }
  44. /* Read the AUX channel access status */
  45. err = regmap_read(map_dptx, SP_AUX_CH_STATUS_REG, &status);
  46. if (err < 0) {
  47. DRM_ERROR("Failed to read from AUX channel: %d\n", err);
  48. return err;
  49. }
  50. if (status & SP_AUX_STATUS) {
  51. DRM_ERROR("Failed to wait for AUX channel (status: %02x)\n",
  52. status);
  53. return -ETIMEDOUT;
  54. }
  55. return 0;
  56. }
  57. static int anx_dp_aux_address(struct regmap *map_dptx, unsigned int addr)
  58. {
  59. int err;
  60. err = regmap_write(map_dptx, SP_AUX_ADDR_7_0_REG, addr & 0xff);
  61. if (err)
  62. return err;
  63. err = regmap_write(map_dptx, SP_AUX_ADDR_15_8_REG,
  64. (addr & 0xff00) >> 8);
  65. if (err)
  66. return err;
  67. /*
  68. * DP AUX CH Address Register #2, only update bits[3:0]
  69. * [7:4] RESERVED
  70. * [3:0] AUX_ADDR[19:16], Register control AUX CH address.
  71. */
  72. err = regmap_update_bits(map_dptx, SP_AUX_ADDR_19_16_REG,
  73. SP_AUX_ADDR_19_16_MASK,
  74. (addr & 0xf0000) >> 16);
  75. if (err)
  76. return err;
  77. return 0;
  78. }
  79. ssize_t anx_dp_aux_transfer(struct regmap *map_dptx,
  80. struct drm_dp_aux_msg *msg)
  81. {
  82. u8 ctrl1 = msg->request;
  83. u8 ctrl2 = SP_AUX_EN;
  84. u8 *buffer = msg->buffer;
  85. int err;
  86. /* The DP AUX transmit and receive buffer has 16 bytes. */
  87. if (WARN_ON(msg->size > AUX_CH_BUFFER_SIZE))
  88. return -E2BIG;
  89. /* Zero-sized messages specify address-only transactions. */
  90. if (msg->size < 1)
  91. ctrl2 |= SP_ADDR_ONLY;
  92. else /* For non-zero-sized set the length field. */
  93. ctrl1 |= (msg->size - 1) << SP_AUX_LENGTH_SHIFT;
  94. if ((msg->size > 0) && ((msg->request & DP_AUX_I2C_READ) == 0)) {
  95. /* When WRITE | MOT write values to data buffer */
  96. err = regmap_bulk_write(map_dptx,
  97. SP_DP_BUF_DATA0_REG, buffer,
  98. msg->size);
  99. if (err)
  100. return err;
  101. }
  102. /* Write address and request */
  103. err = anx_dp_aux_address(map_dptx, msg->address);
  104. if (err)
  105. return err;
  106. err = regmap_write(map_dptx, SP_DP_AUX_CH_CTRL1_REG, ctrl1);
  107. if (err)
  108. return err;
  109. /* Start transaction */
  110. err = regmap_update_bits(map_dptx, SP_DP_AUX_CH_CTRL2_REG,
  111. SP_ADDR_ONLY | SP_AUX_EN, ctrl2);
  112. if (err)
  113. return err;
  114. err = anx_dp_aux_wait(map_dptx);
  115. if (err)
  116. return err;
  117. msg->reply = DP_AUX_I2C_REPLY_ACK;
  118. if ((msg->size > 0) && (msg->request & DP_AUX_I2C_READ)) {
  119. /* Read values from data buffer */
  120. err = regmap_bulk_read(map_dptx,
  121. SP_DP_BUF_DATA0_REG, buffer,
  122. msg->size);
  123. if (err)
  124. return err;
  125. }
  126. err = anx_i2c_dp_clear_bits(map_dptx, SP_DP_AUX_CH_CTRL2_REG,
  127. SP_ADDR_ONLY);
  128. if (err)
  129. return err;
  130. return msg->size;
  131. }
  132. EXPORT_SYMBOL_GPL(anx_dp_aux_transfer);