dp_aux.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2012-2021, The Linux Foundation. All rights reserved.
  4. */
  5. #include <linux/soc/qcom/fsa4480-i2c.h>
  6. #include <linux/delay.h>
  7. #include "dp_aux.h"
  8. #include "dp_hpd.h"
  9. #include "dp_debug.h"
  10. #define DP_AUX_ENUM_STR(x) #x
  11. enum {
  12. DP_AUX_DATA_INDEX_WRITE = BIT(31),
  13. };
  14. struct dp_aux_private {
  15. struct device *dev;
  16. struct dp_aux dp_aux;
  17. struct dp_catalog_aux *catalog;
  18. struct dp_aux_cfg *cfg;
  19. struct device_node *aux_switch_node;
  20. struct mutex mutex;
  21. struct completion comp;
  22. struct drm_dp_aux drm_aux;
  23. struct dp_aux_bridge *aux_bridge;
  24. struct dp_aux_bridge *sim_bridge;
  25. bool bridge_in_transfer;
  26. bool sim_in_transfer;
  27. bool cmd_busy;
  28. bool native;
  29. bool read;
  30. bool no_send_addr;
  31. bool no_send_stop;
  32. bool enabled;
  33. u32 offset;
  34. u32 segment;
  35. u32 aux_error_num;
  36. u32 retry_cnt;
  37. atomic_t aborted;
  38. };
  39. #ifdef CONFIG_DYNAMIC_DEBUG
  40. static void dp_aux_hex_dump(struct drm_dp_aux *drm_aux,
  41. struct drm_dp_aux_msg *msg)
  42. {
  43. char prefix[64];
  44. int i, linelen, remaining = msg->size;
  45. const int rowsize = 16;
  46. u8 linebuf[64];
  47. struct dp_aux_private *aux = container_of(drm_aux,
  48. struct dp_aux_private, drm_aux);
  49. snprintf(prefix, sizeof(prefix), "%s %s %4xh(%2zu): ",
  50. aux->native ? "NAT" : "I2C",
  51. aux->read ? "RD" : "WR",
  52. msg->address, msg->size);
  53. for (i = 0; i < msg->size; i += rowsize) {
  54. linelen = min(remaining, rowsize);
  55. remaining -= rowsize;
  56. hex_dump_to_buffer(msg->buffer + i, linelen, rowsize, 1,
  57. linebuf, sizeof(linebuf), false);
  58. DP_DEBUG("%s%s\n", prefix, linebuf);
  59. }
  60. }
  61. #else
  62. static void dp_aux_hex_dump(struct drm_dp_aux *drm_aux,
  63. struct drm_dp_aux_msg *msg)
  64. {
  65. }
  66. #endif
  67. static char *dp_aux_get_error(u32 aux_error)
  68. {
  69. switch (aux_error) {
  70. case DP_AUX_ERR_NONE:
  71. return DP_AUX_ENUM_STR(DP_AUX_ERR_NONE);
  72. case DP_AUX_ERR_ADDR:
  73. return DP_AUX_ENUM_STR(DP_AUX_ERR_ADDR);
  74. case DP_AUX_ERR_TOUT:
  75. return DP_AUX_ENUM_STR(DP_AUX_ERR_TOUT);
  76. case DP_AUX_ERR_NACK:
  77. return DP_AUX_ENUM_STR(DP_AUX_ERR_NACK);
  78. case DP_AUX_ERR_DEFER:
  79. return DP_AUX_ENUM_STR(DP_AUX_ERR_DEFER);
  80. case DP_AUX_ERR_NACK_DEFER:
  81. return DP_AUX_ENUM_STR(DP_AUX_ERR_NACK_DEFER);
  82. default:
  83. return "unknown";
  84. }
  85. }
  86. static u32 dp_aux_write(struct dp_aux_private *aux,
  87. struct drm_dp_aux_msg *msg)
  88. {
  89. u32 data[4], reg, len;
  90. u8 *msgdata = msg->buffer;
  91. int const aux_cmd_fifo_len = 128;
  92. int i = 0;
  93. if (aux->read)
  94. len = 4;
  95. else
  96. len = msg->size + 4;
  97. /*
  98. * cmd fifo only has depth of 144 bytes
  99. * limit buf length to 128 bytes here
  100. */
  101. if (len > aux_cmd_fifo_len) {
  102. DP_ERR("buf len error\n");
  103. return 0;
  104. }
  105. /* Pack cmd and write to HW */
  106. data[0] = (msg->address >> 16) & 0xf; /* addr[19:16] */
  107. if (aux->read)
  108. data[0] |= BIT(4); /* R/W */
  109. data[1] = (msg->address >> 8) & 0xff; /* addr[15:8] */
  110. data[2] = msg->address & 0xff; /* addr[7:0] */
  111. data[3] = (msg->size - 1) & 0xff; /* len[7:0] */
  112. for (i = 0; i < len; i++) {
  113. reg = (i < 4) ? data[i] : msgdata[i - 4];
  114. reg = ((reg) << 8) & 0x0000ff00; /* index = 0, write */
  115. if (i == 0)
  116. reg |= DP_AUX_DATA_INDEX_WRITE;
  117. aux->catalog->data = reg;
  118. aux->catalog->write_data(aux->catalog);
  119. }
  120. aux->catalog->clear_trans(aux->catalog, false);
  121. aux->catalog->clear_hw_interrupts(aux->catalog);
  122. reg = 0; /* Transaction number == 1 */
  123. if (!aux->native) { /* i2c */
  124. reg |= BIT(8);
  125. if (aux->no_send_addr)
  126. reg |= BIT(10);
  127. if (aux->no_send_stop)
  128. reg |= BIT(11);
  129. }
  130. reg |= BIT(9);
  131. aux->catalog->data = reg;
  132. aux->catalog->write_trans(aux->catalog);
  133. return len;
  134. }
  135. static int dp_aux_cmd_fifo_tx(struct dp_aux_private *aux,
  136. struct drm_dp_aux_msg *msg)
  137. {
  138. u32 ret = 0, len = 0, timeout;
  139. int const aux_timeout_ms = HZ/4;
  140. reinit_completion(&aux->comp);
  141. len = dp_aux_write(aux, msg);
  142. if (len == 0) {
  143. DP_ERR("DP AUX write failed\n");
  144. return -EINVAL;
  145. }
  146. timeout = wait_for_completion_timeout(&aux->comp, aux_timeout_ms);
  147. if (!timeout) {
  148. DP_ERR("aux %s timeout\n", (aux->read ? "read" : "write"));
  149. return -ETIMEDOUT;
  150. }
  151. if (aux->aux_error_num == DP_AUX_ERR_NONE) {
  152. ret = len;
  153. } else {
  154. pr_err_ratelimited("aux err: %s\n",
  155. dp_aux_get_error(aux->aux_error_num));
  156. ret = -EINVAL;
  157. }
  158. return ret;
  159. }
  160. static void dp_aux_cmd_fifo_rx(struct dp_aux_private *aux,
  161. struct drm_dp_aux_msg *msg)
  162. {
  163. u32 data;
  164. u8 *dp;
  165. u32 i, actual_i;
  166. u32 len = msg->size;
  167. aux->catalog->clear_trans(aux->catalog, true);
  168. data = 0;
  169. data |= DP_AUX_DATA_INDEX_WRITE; /* INDEX_WRITE */
  170. data |= BIT(0); /* read */
  171. aux->catalog->data = data;
  172. aux->catalog->write_data(aux->catalog);
  173. dp = msg->buffer;
  174. /* discard first byte */
  175. data = aux->catalog->read_data(aux->catalog);
  176. for (i = 0; i < len; i++) {
  177. data = aux->catalog->read_data(aux->catalog);
  178. *dp++ = (u8)((data >> 8) & 0xff);
  179. actual_i = (data >> 16) & 0xFF;
  180. if (i != actual_i)
  181. DP_WARN("Index mismatch: expected %d, found %d\n",
  182. i, actual_i);
  183. }
  184. }
  185. static void dp_aux_native_handler(struct dp_aux_private *aux)
  186. {
  187. u32 isr = aux->catalog->isr;
  188. if (isr & DP_INTR_AUX_I2C_DONE)
  189. aux->aux_error_num = DP_AUX_ERR_NONE;
  190. else if (isr & DP_INTR_WRONG_ADDR)
  191. aux->aux_error_num = DP_AUX_ERR_ADDR;
  192. else if (isr & DP_INTR_TIMEOUT)
  193. aux->aux_error_num = DP_AUX_ERR_TOUT;
  194. if (isr & DP_INTR_NACK_DEFER)
  195. aux->aux_error_num = DP_AUX_ERR_NACK;
  196. if (isr & DP_INTR_AUX_ERROR) {
  197. aux->aux_error_num = DP_AUX_ERR_PHY;
  198. aux->catalog->clear_hw_interrupts(aux->catalog);
  199. }
  200. complete(&aux->comp);
  201. }
  202. static void dp_aux_i2c_handler(struct dp_aux_private *aux)
  203. {
  204. u32 isr = aux->catalog->isr;
  205. if (isr & DP_INTR_AUX_I2C_DONE) {
  206. if (isr & (DP_INTR_I2C_NACK | DP_INTR_I2C_DEFER))
  207. aux->aux_error_num = DP_AUX_ERR_NACK;
  208. else
  209. aux->aux_error_num = DP_AUX_ERR_NONE;
  210. } else {
  211. if (isr & DP_INTR_WRONG_ADDR)
  212. aux->aux_error_num = DP_AUX_ERR_ADDR;
  213. else if (isr & DP_INTR_TIMEOUT)
  214. aux->aux_error_num = DP_AUX_ERR_TOUT;
  215. if (isr & DP_INTR_NACK_DEFER)
  216. aux->aux_error_num = DP_AUX_ERR_NACK_DEFER;
  217. if (isr & DP_INTR_I2C_NACK)
  218. aux->aux_error_num = DP_AUX_ERR_NACK;
  219. if (isr & DP_INTR_I2C_DEFER)
  220. aux->aux_error_num = DP_AUX_ERR_DEFER;
  221. if (isr & DP_INTR_AUX_ERROR) {
  222. aux->aux_error_num = DP_AUX_ERR_PHY;
  223. aux->catalog->clear_hw_interrupts(aux->catalog);
  224. }
  225. }
  226. complete(&aux->comp);
  227. }
  228. static void dp_aux_isr(struct dp_aux *dp_aux)
  229. {
  230. struct dp_aux_private *aux;
  231. if (!dp_aux) {
  232. DP_ERR("invalid input\n");
  233. return;
  234. }
  235. aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
  236. aux->catalog->get_irq(aux->catalog, aux->cmd_busy);
  237. if (!aux->cmd_busy)
  238. return;
  239. if (aux->native)
  240. dp_aux_native_handler(aux);
  241. else
  242. dp_aux_i2c_handler(aux);
  243. }
  244. static void dp_aux_reconfig(struct dp_aux *dp_aux)
  245. {
  246. struct dp_aux_private *aux;
  247. if (!dp_aux) {
  248. DP_ERR("invalid input\n");
  249. return;
  250. }
  251. aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
  252. aux->catalog->update_aux_cfg(aux->catalog,
  253. aux->cfg, PHY_AUX_CFG1);
  254. aux->catalog->reset(aux->catalog);
  255. }
  256. static void dp_aux_abort_transaction(struct dp_aux *dp_aux, bool abort)
  257. {
  258. struct dp_aux_private *aux;
  259. if (!dp_aux) {
  260. DP_ERR("invalid input\n");
  261. return;
  262. }
  263. aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
  264. atomic_set(&aux->aborted, abort);
  265. }
  266. static void dp_aux_update_offset_and_segment(struct dp_aux_private *aux,
  267. struct drm_dp_aux_msg *input_msg)
  268. {
  269. u32 const edid_address = 0x50;
  270. u32 const segment_address = 0x30;
  271. bool i2c_read = input_msg->request &
  272. (DP_AUX_I2C_READ & DP_AUX_NATIVE_READ);
  273. u8 *data = NULL;
  274. if (aux->native || i2c_read || ((input_msg->address != edid_address) &&
  275. (input_msg->address != segment_address)))
  276. return;
  277. data = input_msg->buffer;
  278. if (input_msg->address == segment_address)
  279. aux->segment = *data;
  280. else
  281. aux->offset = *data;
  282. }
  283. /**
  284. * dp_aux_transfer_helper() - helper function for EDID read transactions
  285. *
  286. * @aux: DP AUX private structure
  287. * @input_msg: input message from DRM upstream APIs
  288. * @send_seg: send the seg to sink
  289. *
  290. * return: void
  291. *
  292. * This helper function is used to fix EDID reads for non-compliant
  293. * sinks that do not handle the i2c middle-of-transaction flag correctly.
  294. */
  295. static void dp_aux_transfer_helper(struct dp_aux_private *aux,
  296. struct drm_dp_aux_msg *input_msg, bool send_seg)
  297. {
  298. struct drm_dp_aux_msg helper_msg;
  299. u32 const message_size = 0x10;
  300. u32 const segment_address = 0x30;
  301. u32 const edid_block_length = 0x80;
  302. bool i2c_mot = input_msg->request & DP_AUX_I2C_MOT;
  303. bool i2c_read = input_msg->request &
  304. (DP_AUX_I2C_READ & DP_AUX_NATIVE_READ);
  305. if (!i2c_mot || !i2c_read || (input_msg->size == 0))
  306. return;
  307. /*
  308. * Sending the segment value and EDID offset will be performed
  309. * from the DRM upstream EDID driver for each block. Avoid
  310. * duplicate AUX transactions related to this while reading the
  311. * first 16 bytes of each block.
  312. */
  313. if (!(aux->offset % edid_block_length) || !send_seg)
  314. goto end;
  315. aux->read = false;
  316. aux->cmd_busy = true;
  317. aux->no_send_addr = true;
  318. aux->no_send_stop = true;
  319. /*
  320. * Send the segment address for i2c reads for segment > 0 and for which
  321. * the middle-of-transaction flag is set. This is required to support
  322. * EDID reads of more than 2 blocks as the segment address is reset to 0
  323. * since we are overriding the middle-of-transaction flag for read
  324. * transactions.
  325. */
  326. if (aux->segment) {
  327. memset(&helper_msg, 0, sizeof(helper_msg));
  328. helper_msg.address = segment_address;
  329. helper_msg.buffer = &aux->segment;
  330. helper_msg.size = 1;
  331. dp_aux_cmd_fifo_tx(aux, &helper_msg);
  332. }
  333. /*
  334. * Send the offset address for every i2c read in which the
  335. * middle-of-transaction flag is set. This will ensure that the sink
  336. * will update its read pointer and return the correct portion of the
  337. * EDID buffer in the subsequent i2c read trasntion triggered in the
  338. * native AUX transfer function.
  339. */
  340. memset(&helper_msg, 0, sizeof(helper_msg));
  341. helper_msg.address = input_msg->address;
  342. helper_msg.buffer = &aux->offset;
  343. helper_msg.size = 1;
  344. dp_aux_cmd_fifo_tx(aux, &helper_msg);
  345. end:
  346. aux->offset += message_size;
  347. if (aux->offset == 0x80 || aux->offset == 0x100)
  348. aux->segment = 0x0; /* reset segment at end of block */
  349. }
  350. static int dp_aux_transfer_ready(struct dp_aux_private *aux,
  351. struct drm_dp_aux_msg *msg, bool send_seg)
  352. {
  353. int ret = 0;
  354. int const aux_cmd_native_max = 16;
  355. int const aux_cmd_i2c_max = 128;
  356. if (atomic_read(&aux->aborted)) {
  357. ret = -ETIMEDOUT;
  358. goto error;
  359. }
  360. aux->native = msg->request & (DP_AUX_NATIVE_WRITE & DP_AUX_NATIVE_READ);
  361. /* Ignore address only message */
  362. if ((msg->size == 0) || (msg->buffer == NULL)) {
  363. msg->reply = aux->native ?
  364. DP_AUX_NATIVE_REPLY_ACK : DP_AUX_I2C_REPLY_ACK;
  365. goto error;
  366. }
  367. /* msg sanity check */
  368. if ((aux->native && (msg->size > aux_cmd_native_max)) ||
  369. (msg->size > aux_cmd_i2c_max)) {
  370. DP_ERR("%s: invalid msg: size(%zu), request(%x)\n",
  371. __func__, msg->size, msg->request);
  372. ret = -EINVAL;
  373. goto error;
  374. }
  375. dp_aux_update_offset_and_segment(aux, msg);
  376. dp_aux_transfer_helper(aux, msg, send_seg);
  377. aux->read = msg->request & (DP_AUX_I2C_READ & DP_AUX_NATIVE_READ);
  378. if (aux->read) {
  379. aux->no_send_addr = true;
  380. aux->no_send_stop = false;
  381. } else {
  382. aux->no_send_addr = true;
  383. aux->no_send_stop = true;
  384. }
  385. aux->cmd_busy = true;
  386. error:
  387. return ret;
  388. }
  389. static inline bool dp_aux_is_sideband_msg(u32 address, size_t size)
  390. {
  391. return (address >= 0x1000 && address + size < 0x1800) ||
  392. (address >= 0x2000 && address + size < 0x2200);
  393. }
  394. /*
  395. * This function does the real job to process an AUX transaction.
  396. * It will call aux_reset() function to reset the AUX channel,
  397. * if the waiting is timeout.
  398. */
  399. static ssize_t dp_aux_transfer(struct drm_dp_aux *drm_aux,
  400. struct drm_dp_aux_msg *msg)
  401. {
  402. ssize_t ret;
  403. int const retry_count = 5;
  404. struct dp_aux_private *aux = container_of(drm_aux,
  405. struct dp_aux_private, drm_aux);
  406. mutex_lock(&aux->mutex);
  407. ret = dp_aux_transfer_ready(aux, msg, true);
  408. if (ret)
  409. goto unlock_exit;
  410. if (!aux->cmd_busy) {
  411. ret = msg->size;
  412. goto unlock_exit;
  413. }
  414. ret = dp_aux_cmd_fifo_tx(aux, msg);
  415. if ((ret < 0) && !atomic_read(&aux->aborted)) {
  416. aux->retry_cnt++;
  417. if (!(aux->retry_cnt % retry_count))
  418. aux->catalog->update_aux_cfg(aux->catalog,
  419. aux->cfg, PHY_AUX_CFG1);
  420. aux->catalog->reset(aux->catalog);
  421. goto unlock_exit;
  422. } else if (ret < 0) {
  423. goto unlock_exit;
  424. }
  425. if (aux->aux_error_num == DP_AUX_ERR_NONE) {
  426. if (aux->read)
  427. dp_aux_cmd_fifo_rx(aux, msg);
  428. dp_aux_hex_dump(drm_aux, msg);
  429. msg->reply = aux->native ?
  430. DP_AUX_NATIVE_REPLY_ACK : DP_AUX_I2C_REPLY_ACK;
  431. } else {
  432. /* Reply defer to retry */
  433. msg->reply = aux->native ?
  434. DP_AUX_NATIVE_REPLY_DEFER : DP_AUX_I2C_REPLY_DEFER;
  435. }
  436. /* Return requested size for success or retry */
  437. ret = msg->size;
  438. aux->retry_cnt = 0;
  439. unlock_exit:
  440. aux->cmd_busy = false;
  441. mutex_unlock(&aux->mutex);
  442. return ret;
  443. }
  444. static ssize_t dp_aux_bridge_transfer(struct drm_dp_aux *drm_aux,
  445. struct drm_dp_aux_msg *msg)
  446. {
  447. struct dp_aux_private *aux = container_of(drm_aux,
  448. struct dp_aux_private, drm_aux);
  449. ssize_t size;
  450. if (aux->bridge_in_transfer) {
  451. size = dp_aux_transfer(drm_aux, msg);
  452. } else {
  453. aux->bridge_in_transfer = true;
  454. size = aux->aux_bridge->transfer(aux->aux_bridge,
  455. drm_aux, msg);
  456. aux->bridge_in_transfer = false;
  457. }
  458. return size;
  459. }
  460. static ssize_t dp_aux_transfer_debug(struct drm_dp_aux *drm_aux,
  461. struct drm_dp_aux_msg *msg)
  462. {
  463. struct dp_aux_private *aux = container_of(drm_aux,
  464. struct dp_aux_private, drm_aux);
  465. ssize_t size;
  466. if (aux->sim_in_transfer) {
  467. if (aux->aux_bridge && aux->aux_bridge->transfer)
  468. size = dp_aux_bridge_transfer(drm_aux, msg);
  469. else
  470. size = dp_aux_transfer(drm_aux, msg);
  471. } else {
  472. aux->sim_in_transfer = true;
  473. size = aux->sim_bridge->transfer(aux->sim_bridge,
  474. drm_aux, msg);
  475. aux->sim_in_transfer = false;
  476. }
  477. return size;
  478. }
  479. static void dp_aux_reset_phy_config_indices(struct dp_aux_cfg *aux_cfg)
  480. {
  481. int i = 0;
  482. for (i = 0; i < PHY_AUX_CFG_MAX; i++)
  483. aux_cfg[i].current_index = 0;
  484. }
  485. static void dp_aux_init(struct dp_aux *dp_aux, struct dp_aux_cfg *aux_cfg)
  486. {
  487. struct dp_aux_private *aux;
  488. if (!dp_aux || !aux_cfg) {
  489. DP_ERR("invalid input\n");
  490. return;
  491. }
  492. aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
  493. if (aux->enabled)
  494. return;
  495. dp_aux_reset_phy_config_indices(aux_cfg);
  496. aux->catalog->setup(aux->catalog, aux_cfg);
  497. aux->catalog->reset(aux->catalog);
  498. aux->catalog->enable(aux->catalog, true);
  499. atomic_set(&aux->aborted, 0);
  500. aux->retry_cnt = 0;
  501. aux->enabled = true;
  502. }
  503. static void dp_aux_deinit(struct dp_aux *dp_aux)
  504. {
  505. struct dp_aux_private *aux;
  506. if (!dp_aux) {
  507. DP_ERR("invalid input\n");
  508. return;
  509. }
  510. aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
  511. if (!aux->enabled)
  512. return;
  513. atomic_set(&aux->aborted, 1);
  514. aux->catalog->enable(aux->catalog, false);
  515. aux->enabled = false;
  516. }
  517. static int dp_aux_register(struct dp_aux *dp_aux)
  518. {
  519. struct dp_aux_private *aux;
  520. int ret = 0;
  521. if (!dp_aux) {
  522. DP_ERR("invalid input\n");
  523. ret = -EINVAL;
  524. goto exit;
  525. }
  526. aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
  527. aux->drm_aux.name = "sde_dp_aux";
  528. aux->drm_aux.dev = aux->dev;
  529. aux->drm_aux.transfer = dp_aux_transfer;
  530. atomic_set(&aux->aborted, 1);
  531. ret = drm_dp_aux_register(&aux->drm_aux);
  532. if (ret) {
  533. DP_ERR("%s: failed to register drm aux: %d\n", __func__, ret);
  534. goto exit;
  535. }
  536. dp_aux->drm_aux = &aux->drm_aux;
  537. /* if bridge is defined, override transfer function */
  538. if (aux->aux_bridge && aux->aux_bridge->transfer)
  539. aux->drm_aux.transfer = dp_aux_bridge_transfer;
  540. exit:
  541. return ret;
  542. }
  543. static void dp_aux_deregister(struct dp_aux *dp_aux)
  544. {
  545. struct dp_aux_private *aux;
  546. if (!dp_aux) {
  547. DP_ERR("invalid input\n");
  548. return;
  549. }
  550. aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
  551. drm_dp_aux_unregister(&aux->drm_aux);
  552. }
  553. static void dp_aux_set_sim_mode(struct dp_aux *dp_aux,
  554. struct dp_aux_bridge *sim_bridge)
  555. {
  556. struct dp_aux_private *aux;
  557. if (!dp_aux) {
  558. DP_ERR("invalid input\n");
  559. return;
  560. }
  561. aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
  562. mutex_lock(&aux->mutex);
  563. aux->sim_bridge = sim_bridge;
  564. if (sim_bridge) {
  565. atomic_set(&aux->aborted, 0);
  566. aux->drm_aux.transfer = dp_aux_transfer_debug;
  567. } else if (aux->aux_bridge && aux->aux_bridge->transfer) {
  568. aux->drm_aux.transfer = dp_aux_bridge_transfer;
  569. } else {
  570. aux->drm_aux.transfer = dp_aux_transfer;
  571. }
  572. mutex_unlock(&aux->mutex);
  573. }
  574. static int dp_aux_configure_aux_switch(struct dp_aux *dp_aux,
  575. bool enable, int orientation)
  576. {
  577. struct dp_aux_private *aux;
  578. int rc = 0;
  579. enum fsa_function event = FSA_USBC_DISPLAYPORT_DISCONNECTED;
  580. if (!dp_aux) {
  581. DP_ERR("invalid input\n");
  582. rc = -EINVAL;
  583. goto end;
  584. }
  585. aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
  586. if (!aux->aux_switch_node) {
  587. DP_DEBUG("undefined fsa4480 handle\n");
  588. rc = -EINVAL;
  589. goto end;
  590. }
  591. if (enable) {
  592. switch (orientation) {
  593. case ORIENTATION_CC1:
  594. event = FSA_USBC_ORIENTATION_CC1;
  595. break;
  596. case ORIENTATION_CC2:
  597. event = FSA_USBC_ORIENTATION_CC2;
  598. break;
  599. default:
  600. DP_ERR("invalid orientation\n");
  601. rc = -EINVAL;
  602. goto end;
  603. }
  604. }
  605. DP_DEBUG("enable=%d, orientation=%d, event=%d\n",
  606. enable, orientation, event);
  607. rc = fsa4480_switch_event(aux->aux_switch_node, event);
  608. if (rc)
  609. DP_ERR("failed to configure fsa4480 i2c device (%d)\n", rc);
  610. end:
  611. return rc;
  612. }
  613. struct dp_aux *dp_aux_get(struct device *dev, struct dp_catalog_aux *catalog,
  614. struct dp_parser *parser, struct device_node *aux_switch,
  615. struct dp_aux_bridge *aux_bridge)
  616. {
  617. int rc = 0;
  618. struct dp_aux_private *aux;
  619. struct dp_aux *dp_aux;
  620. if (!catalog || !parser ||
  621. (!parser->no_aux_switch &&
  622. !aux_switch &&
  623. !parser->gpio_aux_switch)) {
  624. DP_ERR("invalid input\n");
  625. rc = -ENODEV;
  626. goto error;
  627. }
  628. aux = devm_kzalloc(dev, sizeof(*aux), GFP_KERNEL);
  629. if (!aux) {
  630. rc = -ENOMEM;
  631. goto error;
  632. }
  633. init_completion(&aux->comp);
  634. aux->cmd_busy = false;
  635. mutex_init(&aux->mutex);
  636. aux->dev = dev;
  637. aux->catalog = catalog;
  638. aux->cfg = parser->aux_cfg;
  639. aux->aux_switch_node = aux_switch;
  640. aux->aux_bridge = aux_bridge;
  641. dp_aux = &aux->dp_aux;
  642. aux->retry_cnt = 0;
  643. dp_aux->isr = dp_aux_isr;
  644. dp_aux->init = dp_aux_init;
  645. dp_aux->deinit = dp_aux_deinit;
  646. dp_aux->drm_aux_register = dp_aux_register;
  647. dp_aux->drm_aux_deregister = dp_aux_deregister;
  648. dp_aux->reconfig = dp_aux_reconfig;
  649. dp_aux->abort = dp_aux_abort_transaction;
  650. dp_aux->set_sim_mode = dp_aux_set_sim_mode;
  651. dp_aux->aux_switch = dp_aux_configure_aux_switch;
  652. return dp_aux;
  653. error:
  654. return ERR_PTR(rc);
  655. }
  656. void dp_aux_put(struct dp_aux *dp_aux)
  657. {
  658. struct dp_aux_private *aux;
  659. if (!dp_aux)
  660. return;
  661. aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
  662. mutex_destroy(&aux->mutex);
  663. devm_kfree(aux->dev, aux);
  664. }