cdns-mhdp-common.c 25 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
  4. * Author: Chris Zhong <zyw@rock-chips.com>
  5. *
  6. * This software is licensed under the terms of the GNU General Public
  7. * License version 2, as published by the Free Software Foundation, and
  8. * may be copied, distributed, and modified under those terms.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. */
  15. #include <linux/clk.h>
  16. #include <linux/delay.h>
  17. #include <linux/device.h>
  18. #include <linux/io.h>
  19. #include <linux/iopoll.h>
  20. #include <linux/reset.h>
  21. #include <asm/unaligned.h>
  22. #include <drm/bridge/cdns-mhdp-common.h>
  23. #include <drm/drm_modes.h>
  24. #include <drm/drm_print.h>
  25. #define CDNS_DP_SPDIF_CLK 200000000
  26. #define FW_ALIVE_TIMEOUT_US 1000000
  27. #define MAILBOX_RETRY_US 1000
  28. #define MAILBOX_TIMEOUT_US 5000000
  29. #define LINK_TRAINING_RETRY_MS 20
  30. #define LINK_TRAINING_TIMEOUT_MS 500
  31. static inline u32 get_unaligned_be24(const void *p)
  32. {
  33. const u8 *_p = p;
  34. return _p[0] << 16 | _p[1] << 8 | _p[2];
  35. }
  36. static inline void put_unaligned_be24(u32 val, void *p)
  37. {
  38. u8 *_p = p;
  39. _p[0] = val >> 16;
  40. _p[1] = val >> 8;
  41. _p[2] = val;
  42. }
  43. void cdns_mhdp_set_fw_clk(struct cdns_mhdp_device *mhdp, unsigned long clk)
  44. {
  45. writel(clk / 1000000, mhdp->regs + SW_CLK_H);
  46. }
  47. EXPORT_SYMBOL(cdns_mhdp_set_fw_clk);
  48. void cdns_mhdp_clock_reset(struct cdns_mhdp_device *mhdp)
  49. {
  50. u32 val;
  51. val = DPTX_FRMR_DATA_CLK_RSTN_EN |
  52. DPTX_FRMR_DATA_CLK_EN |
  53. DPTX_PHY_DATA_RSTN_EN |
  54. DPTX_PHY_DATA_CLK_EN |
  55. DPTX_PHY_CHAR_RSTN_EN |
  56. DPTX_PHY_CHAR_CLK_EN |
  57. SOURCE_AUX_SYS_CLK_RSTN_EN |
  58. SOURCE_AUX_SYS_CLK_EN |
  59. DPTX_SYS_CLK_RSTN_EN |
  60. DPTX_SYS_CLK_EN |
  61. CFG_DPTX_VIF_CLK_RSTN_EN |
  62. CFG_DPTX_VIF_CLK_EN;
  63. writel(val, mhdp->regs + SOURCE_DPTX_CAR);
  64. val = SOURCE_PHY_RSTN_EN | SOURCE_PHY_CLK_EN;
  65. writel(val, mhdp->regs + SOURCE_PHY_CAR);
  66. val = SOURCE_PKT_SYS_RSTN_EN |
  67. SOURCE_PKT_SYS_CLK_EN |
  68. SOURCE_PKT_DATA_RSTN_EN |
  69. SOURCE_PKT_DATA_CLK_EN;
  70. writel(val, mhdp->regs + SOURCE_PKT_CAR);
  71. val = SPDIF_CDR_CLK_RSTN_EN |
  72. SPDIF_CDR_CLK_EN |
  73. SOURCE_AIF_SYS_RSTN_EN |
  74. SOURCE_AIF_SYS_CLK_EN |
  75. SOURCE_AIF_CLK_RSTN_EN |
  76. SOURCE_AIF_CLK_EN;
  77. writel(val, mhdp->regs + SOURCE_AIF_CAR);
  78. val = SOURCE_CIPHER_SYSTEM_CLK_RSTN_EN |
  79. SOURCE_CIPHER_SYS_CLK_EN |
  80. SOURCE_CIPHER_CHAR_CLK_RSTN_EN |
  81. SOURCE_CIPHER_CHAR_CLK_EN;
  82. writel(val, mhdp->regs + SOURCE_CIPHER_CAR);
  83. val = SOURCE_CRYPTO_SYS_CLK_RSTN_EN |
  84. SOURCE_CRYPTO_SYS_CLK_EN;
  85. writel(val, mhdp->regs + SOURCE_CRYPTO_CAR);
  86. /* enable Mailbox and PIF interrupt */
  87. writel(0, mhdp->regs + APB_INT_MASK);
  88. }
  89. EXPORT_SYMBOL(cdns_mhdp_clock_reset);
  90. static int cdns_mhdp_mailbox_read(struct cdns_mhdp_device *mhdp)
  91. {
  92. int val, ret;
  93. ret = readx_poll_timeout(readl, mhdp->regs + MAILBOX_EMPTY_ADDR,
  94. val, !val, MAILBOX_RETRY_US,
  95. MAILBOX_TIMEOUT_US);
  96. if (ret < 0)
  97. return ret;
  98. return readl(mhdp->regs + MAILBOX0_RD_DATA) & 0xff;
  99. }
  100. static int cdp_dp_mailbox_write(struct cdns_mhdp_device *mhdp, u8 val)
  101. {
  102. int ret, full;
  103. ret = readx_poll_timeout(readl, mhdp->regs + MAILBOX_FULL_ADDR,
  104. full, !full, MAILBOX_RETRY_US,
  105. MAILBOX_TIMEOUT_US);
  106. if (ret < 0)
  107. return ret;
  108. writel(val, mhdp->regs + MAILBOX0_WR_DATA);
  109. return 0;
  110. }
  111. static int cdns_mhdp_mailbox_validate_receive(struct cdns_mhdp_device *mhdp,
  112. u8 module_id, u8 opcode,
  113. u16 req_size)
  114. {
  115. u32 mbox_size, i;
  116. u8 header[4];
  117. int ret;
  118. /* read the header of the message */
  119. for (i = 0; i < 4; i++) {
  120. ret = cdns_mhdp_mailbox_read(mhdp);
  121. if (ret < 0)
  122. return ret;
  123. header[i] = ret;
  124. }
  125. mbox_size = get_unaligned_be16(header + 2);
  126. if (opcode != header[0] || module_id != header[1] ||
  127. req_size != mbox_size) {
  128. /*
  129. * If the message in mailbox is not what we want, we need to
  130. * clear the mailbox by reading its contents.
  131. */
  132. for (i = 0; i < mbox_size; i++)
  133. if (cdns_mhdp_mailbox_read(mhdp) < 0)
  134. break;
  135. return -EINVAL;
  136. }
  137. return 0;
  138. }
  139. static int cdns_mhdp_mailbox_read_receive(struct cdns_mhdp_device *mhdp,
  140. u8 *buff, u16 buff_size)
  141. {
  142. u32 i;
  143. int ret;
  144. for (i = 0; i < buff_size; i++) {
  145. ret = cdns_mhdp_mailbox_read(mhdp);
  146. if (ret < 0)
  147. return ret;
  148. buff[i] = ret;
  149. }
  150. return 0;
  151. }
  152. static int cdns_mhdp_mailbox_send(struct cdns_mhdp_device *mhdp, u8 module_id,
  153. u8 opcode, u16 size, u8 *message)
  154. {
  155. u8 header[4];
  156. int ret, i;
  157. header[0] = opcode;
  158. header[1] = module_id;
  159. put_unaligned_be16(size, header + 2);
  160. for (i = 0; i < 4; i++) {
  161. ret = cdp_dp_mailbox_write(mhdp, header[i]);
  162. if (ret)
  163. return ret;
  164. }
  165. for (i = 0; i < size; i++) {
  166. ret = cdp_dp_mailbox_write(mhdp, message[i]);
  167. if (ret)
  168. return ret;
  169. }
  170. return 0;
  171. }
  172. int cdns_mhdp_reg_read(struct cdns_mhdp_device *mhdp, u32 addr, u32 *value)
  173. {
  174. u8 msg[4], resp[8];
  175. int ret;
  176. if (addr == 0) {
  177. ret = -EINVAL;
  178. goto err_reg_read;
  179. }
  180. put_unaligned_be32(addr, msg);
  181. ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_GENERAL,
  182. GENERAL_REGISTER_READ,
  183. sizeof(msg), msg);
  184. if (ret)
  185. goto err_reg_read;
  186. ret = cdns_mhdp_mailbox_validate_receive(mhdp, MB_MODULE_ID_GENERAL,
  187. GENERAL_REGISTER_READ,
  188. sizeof(resp));
  189. if (ret)
  190. goto err_reg_read;
  191. ret = cdns_mhdp_mailbox_read_receive(mhdp, resp, sizeof(resp));
  192. if (ret)
  193. goto err_reg_read;
  194. /* Returned address value should be the same as requested */
  195. if (memcmp(msg, resp, sizeof(msg))) {
  196. ret = -EINVAL;
  197. goto err_reg_read;
  198. }
  199. *value = get_unaligned_be32(resp + 4);
  200. err_reg_read:
  201. if (ret) {
  202. DRM_DEV_ERROR(mhdp->dev, "Failed to read register.\n");
  203. *value = 0;
  204. }
  205. return ret;
  206. }
  207. EXPORT_SYMBOL(cdns_mhdp_reg_read);
  208. int cdns_mhdp_reg_write(struct cdns_mhdp_device *mhdp, u16 addr, u32 val)
  209. {
  210. u8 msg[6];
  211. put_unaligned_be16(addr, msg);
  212. put_unaligned_be32(val, msg + 2);
  213. return cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_DP_TX,
  214. DPTX_WRITE_REGISTER, sizeof(msg), msg);
  215. }
  216. EXPORT_SYMBOL(cdns_mhdp_reg_write);
  217. int cdns_mhdp_reg_write_bit(struct cdns_mhdp_device *mhdp, u16 addr,
  218. u8 start_bit, u8 bits_no, u32 val)
  219. {
  220. u8 field[8];
  221. put_unaligned_be16(addr, field);
  222. field[2] = start_bit;
  223. field[3] = bits_no;
  224. put_unaligned_be32(val, field + 4);
  225. return cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_DP_TX,
  226. DPTX_WRITE_FIELD, sizeof(field), field);
  227. }
  228. EXPORT_SYMBOL(cdns_mhdp_reg_write_bit);
  229. int cdns_mhdp_dpcd_read(struct cdns_mhdp_device *mhdp,
  230. u32 addr, u8 *data, u16 len)
  231. {
  232. u8 msg[5], reg[5];
  233. int ret;
  234. put_unaligned_be16(len, msg);
  235. put_unaligned_be24(addr, msg + 2);
  236. ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_DP_TX,
  237. DPTX_READ_DPCD, sizeof(msg), msg);
  238. if (ret)
  239. goto err_dpcd_read;
  240. ret = cdns_mhdp_mailbox_validate_receive(mhdp, MB_MODULE_ID_DP_TX,
  241. DPTX_READ_DPCD,
  242. sizeof(reg) + len);
  243. if (ret)
  244. goto err_dpcd_read;
  245. ret = cdns_mhdp_mailbox_read_receive(mhdp, reg, sizeof(reg));
  246. if (ret)
  247. goto err_dpcd_read;
  248. ret = cdns_mhdp_mailbox_read_receive(mhdp, data, len);
  249. err_dpcd_read:
  250. return ret;
  251. }
  252. EXPORT_SYMBOL(cdns_mhdp_dpcd_read);
  253. int cdns_mhdp_dpcd_write(struct cdns_mhdp_device *mhdp, u32 addr, u8 value)
  254. {
  255. u8 msg[6], reg[5];
  256. int ret;
  257. put_unaligned_be16(1, msg);
  258. put_unaligned_be24(addr, msg + 2);
  259. msg[5] = value;
  260. ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_DP_TX,
  261. DPTX_WRITE_DPCD, sizeof(msg), msg);
  262. if (ret)
  263. goto err_dpcd_write;
  264. ret = cdns_mhdp_mailbox_validate_receive(mhdp, MB_MODULE_ID_DP_TX,
  265. DPTX_WRITE_DPCD, sizeof(reg));
  266. if (ret)
  267. goto err_dpcd_write;
  268. ret = cdns_mhdp_mailbox_read_receive(mhdp, reg, sizeof(reg));
  269. if (ret)
  270. goto err_dpcd_write;
  271. if (addr != get_unaligned_be24(reg + 2))
  272. ret = -EINVAL;
  273. err_dpcd_write:
  274. if (ret)
  275. DRM_DEV_ERROR(mhdp->dev, "dpcd write failed: %d\n", ret);
  276. return ret;
  277. }
  278. EXPORT_SYMBOL(cdns_mhdp_dpcd_write);
  279. int cdns_mhdp_load_firmware(struct cdns_mhdp_device *mhdp, const u32 *i_mem,
  280. u32 i_size, const u32 *d_mem, u32 d_size)
  281. {
  282. u32 reg;
  283. int i, ret;
  284. /* reset ucpu before load firmware*/
  285. writel(APB_IRAM_PATH | APB_DRAM_PATH | APB_XT_RESET,
  286. mhdp->regs + APB_CTRL);
  287. for (i = 0; i < i_size; i += 4)
  288. writel(*i_mem++, mhdp->regs + ADDR_IMEM + i);
  289. for (i = 0; i < d_size; i += 4)
  290. writel(*d_mem++, mhdp->regs + ADDR_DMEM + i);
  291. /* un-reset ucpu */
  292. writel(0, mhdp->regs + APB_CTRL);
  293. /* check the keep alive register to make sure fw working */
  294. ret = readx_poll_timeout(readl, mhdp->regs + KEEP_ALIVE,
  295. reg, reg, 2000, FW_ALIVE_TIMEOUT_US);
  296. if (ret < 0) {
  297. DRM_DEV_ERROR(mhdp->dev, "failed to loaded the FW reg = %x\n",
  298. reg);
  299. return -EINVAL;
  300. }
  301. reg = readl(mhdp->regs + VER_L) & 0xff;
  302. mhdp->fw_version = reg;
  303. reg = readl(mhdp->regs + VER_H) & 0xff;
  304. mhdp->fw_version |= reg << 8;
  305. reg = readl(mhdp->regs + VER_LIB_L_ADDR) & 0xff;
  306. mhdp->fw_version |= reg << 16;
  307. reg = readl(mhdp->regs + VER_LIB_H_ADDR) & 0xff;
  308. mhdp->fw_version |= reg << 24;
  309. DRM_DEV_DEBUG(mhdp->dev, "firmware version: %x\n", mhdp->fw_version);
  310. return 0;
  311. }
  312. EXPORT_SYMBOL(cdns_mhdp_load_firmware);
  313. int cdns_mhdp_set_firmware_active(struct cdns_mhdp_device *mhdp, bool enable)
  314. {
  315. u8 msg[5];
  316. int ret, i;
  317. msg[0] = GENERAL_MAIN_CONTROL;
  318. msg[1] = MB_MODULE_ID_GENERAL;
  319. msg[2] = 0;
  320. msg[3] = 1;
  321. msg[4] = enable ? FW_ACTIVE : FW_STANDBY;
  322. for (i = 0; i < sizeof(msg); i++) {
  323. ret = cdp_dp_mailbox_write(mhdp, msg[i]);
  324. if (ret)
  325. goto err_set_firmware_active;
  326. }
  327. /* read the firmware state */
  328. for (i = 0; i < sizeof(msg); i++) {
  329. ret = cdns_mhdp_mailbox_read(mhdp);
  330. if (ret < 0)
  331. goto err_set_firmware_active;
  332. msg[i] = ret;
  333. }
  334. ret = 0;
  335. err_set_firmware_active:
  336. if (ret < 0)
  337. DRM_DEV_ERROR(mhdp->dev, "set firmware active failed\n");
  338. return ret;
  339. }
  340. EXPORT_SYMBOL(cdns_mhdp_set_firmware_active);
  341. int cdns_mhdp_set_host_cap(struct cdns_mhdp_device *mhdp, u8 lanes, bool flip)
  342. {
  343. u8 msg[8];
  344. int ret;
  345. msg[0] = CDNS_DP_MAX_LINK_RATE;
  346. msg[1] = lanes | SCRAMBLER_EN;
  347. msg[2] = VOLTAGE_LEVEL_2;
  348. msg[3] = PRE_EMPHASIS_LEVEL_3;
  349. msg[4] = PTS1 | PTS2 | PTS3 | PTS4;
  350. msg[5] = FAST_LT_NOT_SUPPORT;
  351. msg[6] = flip ? LANE_MAPPING_FLIPPED : LANE_MAPPING_NORMAL;
  352. msg[7] = ENHANCED;
  353. ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_DP_TX,
  354. DPTX_SET_HOST_CAPABILITIES,
  355. sizeof(msg), msg);
  356. if (ret)
  357. goto err_set_host_cap;
  358. ret = cdns_mhdp_reg_write(mhdp, DP_AUX_SWAP_INVERSION_CONTROL,
  359. AUX_HOST_INVERT);
  360. err_set_host_cap:
  361. if (ret)
  362. DRM_DEV_ERROR(mhdp->dev, "set host cap failed: %d\n", ret);
  363. return ret;
  364. }
  365. EXPORT_SYMBOL(cdns_mhdp_set_host_cap);
  366. int cdns_mhdp_event_config(struct cdns_mhdp_device *mhdp)
  367. {
  368. u8 msg[5];
  369. int ret;
  370. memset(msg, 0, sizeof(msg));
  371. msg[0] = DPTX_EVENT_ENABLE_HPD | DPTX_EVENT_ENABLE_TRAINING;
  372. ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_DP_TX,
  373. DPTX_ENABLE_EVENT, sizeof(msg), msg);
  374. if (ret)
  375. DRM_DEV_ERROR(mhdp->dev, "set event config failed: %d\n", ret);
  376. return ret;
  377. }
  378. EXPORT_SYMBOL(cdns_mhdp_event_config);
  379. u32 cdns_mhdp_get_event(struct cdns_mhdp_device *mhdp)
  380. {
  381. return readl(mhdp->regs + SW_EVENTS0);
  382. }
  383. EXPORT_SYMBOL(cdns_mhdp_get_event);
  384. int cdns_mhdp_get_hpd_status(struct cdns_mhdp_device *mhdp)
  385. {
  386. u8 status;
  387. int ret;
  388. ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_DP_TX,
  389. DPTX_HPD_STATE, 0, NULL);
  390. if (ret)
  391. goto err_get_hpd;
  392. ret = cdns_mhdp_mailbox_validate_receive(mhdp, MB_MODULE_ID_DP_TX,
  393. DPTX_HPD_STATE,
  394. sizeof(status));
  395. if (ret)
  396. goto err_get_hpd;
  397. ret = cdns_mhdp_mailbox_read_receive(mhdp, &status, sizeof(status));
  398. if (ret)
  399. goto err_get_hpd;
  400. return status;
  401. err_get_hpd:
  402. DRM_DEV_ERROR(mhdp->dev, "get hpd status failed: %d\n", ret);
  403. return ret;
  404. }
  405. EXPORT_SYMBOL(cdns_mhdp_get_hpd_status);
  406. int cdns_mhdp_get_edid_block(void *data, u8 *edid,
  407. unsigned int block, size_t length)
  408. {
  409. struct cdns_mhdp_device *mhdp = data;
  410. u8 msg[2], reg[2], i;
  411. int ret;
  412. for (i = 0; i < 4; i++) {
  413. msg[0] = block / 2;
  414. msg[1] = block % 2;
  415. ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_DP_TX,
  416. DPTX_GET_EDID, sizeof(msg), msg);
  417. if (ret)
  418. continue;
  419. ret = cdns_mhdp_mailbox_validate_receive(mhdp,
  420. MB_MODULE_ID_DP_TX,
  421. DPTX_GET_EDID,
  422. sizeof(reg) + length);
  423. if (ret)
  424. continue;
  425. ret = cdns_mhdp_mailbox_read_receive(mhdp, reg, sizeof(reg));
  426. if (ret)
  427. continue;
  428. ret = cdns_mhdp_mailbox_read_receive(mhdp, edid, length);
  429. if (ret)
  430. continue;
  431. if (reg[0] == length && reg[1] == block / 2)
  432. break;
  433. }
  434. if (ret)
  435. DRM_DEV_ERROR(mhdp->dev, "get block[%d] edid failed: %d\n",
  436. block, ret);
  437. return ret;
  438. }
  439. EXPORT_SYMBOL(cdns_mhdp_get_edid_block);
  440. static int cdns_mhdp_training_start(struct cdns_mhdp_device *mhdp)
  441. {
  442. unsigned long timeout;
  443. u8 msg, event[2];
  444. int ret;
  445. msg = LINK_TRAINING_RUN;
  446. /* start training */
  447. ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_DP_TX,
  448. DPTX_TRAINING_CONTROL, sizeof(msg), &msg);
  449. if (ret)
  450. goto err_training_start;
  451. timeout = jiffies + msecs_to_jiffies(LINK_TRAINING_TIMEOUT_MS);
  452. while (time_before(jiffies, timeout)) {
  453. msleep(LINK_TRAINING_RETRY_MS);
  454. ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_DP_TX,
  455. DPTX_READ_EVENT, 0, NULL);
  456. if (ret)
  457. goto err_training_start;
  458. ret = cdns_mhdp_mailbox_validate_receive(mhdp,
  459. MB_MODULE_ID_DP_TX,
  460. DPTX_READ_EVENT,
  461. sizeof(event));
  462. if (ret)
  463. goto err_training_start;
  464. ret = cdns_mhdp_mailbox_read_receive(mhdp, event,
  465. sizeof(event));
  466. if (ret)
  467. goto err_training_start;
  468. if (event[1] & EQ_PHASE_FINISHED)
  469. return 0;
  470. }
  471. ret = -ETIMEDOUT;
  472. err_training_start:
  473. DRM_DEV_ERROR(mhdp->dev, "training failed: %d\n", ret);
  474. return ret;
  475. }
  476. static int cdns_mhdp_get_training_status(struct cdns_mhdp_device *mhdp)
  477. {
  478. u8 status[10];
  479. int ret;
  480. ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_DP_TX,
  481. DPTX_READ_LINK_STAT, 0, NULL);
  482. if (ret)
  483. goto err_get_training_status;
  484. ret = cdns_mhdp_mailbox_validate_receive(mhdp, MB_MODULE_ID_DP_TX,
  485. DPTX_READ_LINK_STAT,
  486. sizeof(status));
  487. if (ret)
  488. goto err_get_training_status;
  489. ret = cdns_mhdp_mailbox_read_receive(mhdp, status, sizeof(status));
  490. if (ret)
  491. goto err_get_training_status;
  492. mhdp->link.rate = status[0];
  493. mhdp->link.num_lanes = status[1];
  494. err_get_training_status:
  495. if (ret)
  496. DRM_DEV_ERROR(mhdp->dev, "get training status failed: %d\n",
  497. ret);
  498. return ret;
  499. }
  500. int cdns_mhdp_train_link(struct cdns_mhdp_device *mhdp)
  501. {
  502. int ret;
  503. ret = cdns_mhdp_training_start(mhdp);
  504. if (ret) {
  505. DRM_DEV_ERROR(mhdp->dev, "Failed to start training %d\n",
  506. ret);
  507. return ret;
  508. }
  509. ret = cdns_mhdp_get_training_status(mhdp);
  510. if (ret) {
  511. DRM_DEV_ERROR(mhdp->dev, "Failed to get training stat %d\n",
  512. ret);
  513. return ret;
  514. }
  515. DRM_DEV_DEBUG_KMS(mhdp->dev, "rate:0x%x, lanes:%d\n", mhdp->link.rate,
  516. mhdp->link.num_lanes);
  517. return ret;
  518. }
  519. EXPORT_SYMBOL(cdns_mhdp_train_link);
  520. int cdns_mhdp_set_video_status(struct cdns_mhdp_device *mhdp, int active)
  521. {
  522. u8 msg;
  523. int ret;
  524. msg = !!active;
  525. ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_DP_TX,
  526. DPTX_SET_VIDEO, sizeof(msg), &msg);
  527. if (ret)
  528. DRM_DEV_ERROR(mhdp->dev, "set video status failed: %d\n", ret);
  529. return ret;
  530. }
  531. EXPORT_SYMBOL(cdns_mhdp_set_video_status);
  532. static int cdns_mhdp_get_msa_misc(struct video_info *video,
  533. struct drm_display_mode *mode)
  534. {
  535. u32 msa_misc;
  536. u8 val[2] = {0};
  537. switch (video->color_fmt) {
  538. case PXL_RGB:
  539. case Y_ONLY:
  540. val[0] = 0;
  541. break;
  542. /* set YUV default color space conversion to BT601 */
  543. case YCBCR_4_4_4:
  544. val[0] = 6 + BT_601 * 8;
  545. break;
  546. case YCBCR_4_2_2:
  547. val[0] = 5 + BT_601 * 8;
  548. break;
  549. case YCBCR_4_2_0:
  550. val[0] = 5;
  551. break;
  552. }
  553. switch (video->color_depth) {
  554. case 6:
  555. val[1] = 0;
  556. break;
  557. case 8:
  558. val[1] = 1;
  559. break;
  560. case 10:
  561. val[1] = 2;
  562. break;
  563. case 12:
  564. val[1] = 3;
  565. break;
  566. case 16:
  567. val[1] = 4;
  568. break;
  569. }
  570. msa_misc = 2 * val[0] + 32 * val[1] +
  571. ((video->color_fmt == Y_ONLY) ? (1 << 14) : 0);
  572. return msa_misc;
  573. }
  574. int cdns_mhdp_config_video(struct cdns_mhdp_device *mhdp)
  575. {
  576. struct video_info *video = &mhdp->video_info;
  577. struct drm_display_mode *mode = &mhdp->mode;
  578. u64 symbol;
  579. u32 val, link_rate, rem;
  580. u8 bit_per_pix, tu_size_reg = TU_SIZE;
  581. int ret;
  582. bit_per_pix = (video->color_fmt == YCBCR_4_2_2) ?
  583. (video->color_depth * 2) : (video->color_depth * 3);
  584. link_rate = drm_dp_bw_code_to_link_rate(mhdp->link.rate) / 1000;
  585. ret = cdns_mhdp_reg_write(mhdp, BND_HSYNC2VSYNC, VIF_BYPASS_INTERLACE);
  586. if (ret)
  587. goto err_config_video;
  588. ret = cdns_mhdp_reg_write(mhdp, HSYNC2VSYNC_POL_CTRL, 0);
  589. if (ret)
  590. goto err_config_video;
  591. /*
  592. * get a best tu_size and valid symbol:
  593. * 1. chose Lclk freq(162Mhz, 270Mhz, 540Mhz), set TU to 32
  594. * 2. calculate VS(valid symbol) = TU * Pclk * Bpp / (Lclk * Lanes)
  595. * 3. if VS > *.85 or VS < *.1 or VS < 2 or TU < VS + 4, then set
  596. * TU += 2 and repeat 2nd step.
  597. */
  598. do {
  599. tu_size_reg += 2;
  600. symbol = tu_size_reg * mode->clock * bit_per_pix;
  601. do_div(symbol, mhdp->link.num_lanes * link_rate * 8);
  602. rem = do_div(symbol, 1000);
  603. if (tu_size_reg > 64) {
  604. ret = -EINVAL;
  605. DRM_DEV_ERROR(mhdp->dev,
  606. "tu error, clk:%d, lanes:%d, rate:%d\n",
  607. mode->clock, mhdp->link.num_lanes,
  608. link_rate);
  609. goto err_config_video;
  610. }
  611. } while ((symbol <= 1) || (tu_size_reg - symbol < 4) ||
  612. (rem > 850) || (rem < 100));
  613. val = symbol + (tu_size_reg << 8);
  614. val |= TU_CNT_RST_EN;
  615. ret = cdns_mhdp_reg_write(mhdp, DP_FRAMER_TU, val);
  616. if (ret)
  617. goto err_config_video;
  618. /* set the FIFO Buffer size */
  619. val = div_u64(mode->clock * (symbol + 1), 1000) + link_rate;
  620. val /= (mhdp->link.num_lanes * link_rate);
  621. val = div_u64(8 * (symbol + 1), bit_per_pix) - val;
  622. val += 2;
  623. ret = cdns_mhdp_reg_write(mhdp, DP_VC_TABLE(15), val);
  624. switch (video->color_depth) {
  625. case 6:
  626. val = BCS_6;
  627. break;
  628. case 8:
  629. val = BCS_8;
  630. break;
  631. case 10:
  632. val = BCS_10;
  633. break;
  634. case 12:
  635. val = BCS_12;
  636. break;
  637. case 16:
  638. val = BCS_16;
  639. break;
  640. }
  641. val += video->color_fmt << 8;
  642. ret = cdns_mhdp_reg_write(mhdp, DP_FRAMER_PXL_REPR, val);
  643. if (ret)
  644. goto err_config_video;
  645. val = video->h_sync_polarity ? DP_FRAMER_SP_HSP : 0;
  646. val |= video->v_sync_polarity ? DP_FRAMER_SP_VSP : 0;
  647. ret = cdns_mhdp_reg_write(mhdp, DP_FRAMER_SP, val);
  648. if (ret)
  649. goto err_config_video;
  650. val = (mode->hsync_start - mode->hdisplay) << 16;
  651. val |= mode->htotal - mode->hsync_end;
  652. ret = cdns_mhdp_reg_write(mhdp, DP_FRONT_BACK_PORCH, val);
  653. if (ret)
  654. goto err_config_video;
  655. val = mode->hdisplay * bit_per_pix / 8;
  656. ret = cdns_mhdp_reg_write(mhdp, DP_BYTE_COUNT, val);
  657. if (ret)
  658. goto err_config_video;
  659. val = mode->htotal | ((mode->htotal - mode->hsync_start) << 16);
  660. ret = cdns_mhdp_reg_write(mhdp, MSA_HORIZONTAL_0, val);
  661. if (ret)
  662. goto err_config_video;
  663. val = mode->hsync_end - mode->hsync_start;
  664. val |= (mode->hdisplay << 16) | (video->h_sync_polarity << 15);
  665. ret = cdns_mhdp_reg_write(mhdp, MSA_HORIZONTAL_1, val);
  666. if (ret)
  667. goto err_config_video;
  668. val = mode->vtotal;
  669. val |= (mode->vtotal - mode->vsync_start) << 16;
  670. ret = cdns_mhdp_reg_write(mhdp, MSA_VERTICAL_0, val);
  671. if (ret)
  672. goto err_config_video;
  673. val = mode->vsync_end - mode->vsync_start;
  674. val |= (mode->vdisplay << 16) | (video->v_sync_polarity << 15);
  675. ret = cdns_mhdp_reg_write(mhdp, MSA_VERTICAL_1, val);
  676. if (ret)
  677. goto err_config_video;
  678. val = cdns_mhdp_get_msa_misc(video, mode);
  679. ret = cdns_mhdp_reg_write(mhdp, MSA_MISC, val);
  680. if (ret)
  681. goto err_config_video;
  682. ret = cdns_mhdp_reg_write(mhdp, STREAM_CONFIG, 1);
  683. if (ret)
  684. goto err_config_video;
  685. val = mode->hsync_end - mode->hsync_start;
  686. val |= mode->hdisplay << 16;
  687. ret = cdns_mhdp_reg_write(mhdp, DP_HORIZONTAL, val);
  688. if (ret)
  689. goto err_config_video;
  690. val = mode->vdisplay;
  691. val |= (mode->vtotal - mode->vsync_start) << 16;
  692. ret = cdns_mhdp_reg_write(mhdp, DP_VERTICAL_0, val);
  693. if (ret)
  694. goto err_config_video;
  695. val = mode->vtotal;
  696. ret = cdns_mhdp_reg_write(mhdp, DP_VERTICAL_1, val);
  697. if (ret)
  698. goto err_config_video;
  699. ret = cdns_mhdp_reg_write_bit(mhdp, DP_VB_ID, 2, 1, 0);
  700. err_config_video:
  701. if (ret)
  702. DRM_DEV_ERROR(mhdp->dev, "config video failed: %d\n", ret);
  703. return ret;
  704. }
  705. EXPORT_SYMBOL(cdns_mhdp_config_video);
  706. int cdns_mhdp_audio_stop(struct cdns_mhdp_device *mhdp,
  707. struct audio_info *audio)
  708. {
  709. int ret;
  710. ret = cdns_mhdp_reg_write(mhdp, AUDIO_PACK_CONTROL, 0);
  711. if (ret) {
  712. DRM_DEV_ERROR(mhdp->dev, "audio stop failed: %d\n", ret);
  713. return ret;
  714. }
  715. writel(0, mhdp->regs + SPDIF_CTRL_ADDR);
  716. /* clearn the audio config and reset */
  717. writel(0, mhdp->regs + AUDIO_SRC_CNTL);
  718. writel(0, mhdp->regs + AUDIO_SRC_CNFG);
  719. writel(AUDIO_SW_RST, mhdp->regs + AUDIO_SRC_CNTL);
  720. writel(0, mhdp->regs + AUDIO_SRC_CNTL);
  721. /* reset smpl2pckt component */
  722. writel(0, mhdp->regs + SMPL2PKT_CNTL);
  723. writel(AUDIO_SW_RST, mhdp->regs + SMPL2PKT_CNTL);
  724. writel(0, mhdp->regs + SMPL2PKT_CNTL);
  725. /* reset FIFO */
  726. writel(AUDIO_SW_RST, mhdp->regs + FIFO_CNTL);
  727. writel(0, mhdp->regs + FIFO_CNTL);
  728. if (audio->format == AFMT_SPDIF)
  729. clk_disable_unprepare(mhdp->spdif_clk);
  730. return 0;
  731. }
  732. EXPORT_SYMBOL(cdns_mhdp_audio_stop);
  733. int cdns_mhdp_audio_mute(struct cdns_mhdp_device *mhdp, bool enable)
  734. {
  735. int ret;
  736. ret = cdns_mhdp_reg_write_bit(mhdp, DP_VB_ID, 4, 1, enable);
  737. if (ret)
  738. DRM_DEV_ERROR(mhdp->dev, "audio mute failed: %d\n", ret);
  739. return ret;
  740. }
  741. EXPORT_SYMBOL(cdns_mhdp_audio_mute);
  742. static void cdns_mhdp_audio_config_i2s(struct cdns_mhdp_device *mhdp,
  743. struct audio_info *audio)
  744. {
  745. int sub_pckt_num = 1, i2s_port_en_val = 0xf, i;
  746. u32 val;
  747. if (audio->channels == 2) {
  748. if (mhdp->link.num_lanes == 1)
  749. sub_pckt_num = 2;
  750. else
  751. sub_pckt_num = 4;
  752. i2s_port_en_val = 1;
  753. } else if (audio->channels == 4) {
  754. i2s_port_en_val = 3;
  755. }
  756. writel(0x0, mhdp->regs + SPDIF_CTRL_ADDR);
  757. writel(SYNC_WR_TO_CH_ZERO, mhdp->regs + FIFO_CNTL);
  758. val = MAX_NUM_CH(audio->channels);
  759. val |= NUM_OF_I2S_PORTS(audio->channels);
  760. val |= AUDIO_TYPE_LPCM;
  761. val |= CFG_SUB_PCKT_NUM(sub_pckt_num);
  762. writel(val, mhdp->regs + SMPL2PKT_CNFG);
  763. if (audio->sample_width == 16)
  764. val = 0;
  765. else if (audio->sample_width == 24)
  766. val = 1 << 9;
  767. else
  768. val = 2 << 9;
  769. val |= AUDIO_CH_NUM(audio->channels);
  770. val |= I2S_DEC_PORT_EN(i2s_port_en_val);
  771. val |= TRANS_SMPL_WIDTH_32;
  772. writel(val, mhdp->regs + AUDIO_SRC_CNFG);
  773. for (i = 0; i < (audio->channels + 1) / 2; i++) {
  774. if (audio->sample_width == 16)
  775. val = (0x02 << 8) | (0x02 << 20);
  776. else if (audio->sample_width == 24)
  777. val = (0x0b << 8) | (0x0b << 20);
  778. val |= ((2 * i) << 4) | ((2 * i + 1) << 16);
  779. writel(val, mhdp->regs + STTS_BIT_CH(i));
  780. }
  781. switch (audio->sample_rate) {
  782. case 32000:
  783. val = SAMPLING_FREQ(3) |
  784. ORIGINAL_SAMP_FREQ(0xc);
  785. break;
  786. case 44100:
  787. val = SAMPLING_FREQ(0) |
  788. ORIGINAL_SAMP_FREQ(0xf);
  789. break;
  790. case 48000:
  791. val = SAMPLING_FREQ(2) |
  792. ORIGINAL_SAMP_FREQ(0xd);
  793. break;
  794. case 88200:
  795. val = SAMPLING_FREQ(8) |
  796. ORIGINAL_SAMP_FREQ(0x7);
  797. break;
  798. case 96000:
  799. val = SAMPLING_FREQ(0xa) |
  800. ORIGINAL_SAMP_FREQ(5);
  801. break;
  802. case 176400:
  803. val = SAMPLING_FREQ(0xc) |
  804. ORIGINAL_SAMP_FREQ(3);
  805. break;
  806. case 192000:
  807. val = SAMPLING_FREQ(0xe) |
  808. ORIGINAL_SAMP_FREQ(1);
  809. break;
  810. }
  811. val |= 4;
  812. writel(val, mhdp->regs + COM_CH_STTS_BITS);
  813. writel(SMPL2PKT_EN, mhdp->regs + SMPL2PKT_CNTL);
  814. writel(I2S_DEC_START, mhdp->regs + AUDIO_SRC_CNTL);
  815. }
  816. static void cdns_mhdp_audio_config_spdif(struct cdns_mhdp_device *mhdp)
  817. {
  818. u32 val;
  819. writel(SYNC_WR_TO_CH_ZERO, mhdp->regs + FIFO_CNTL);
  820. val = MAX_NUM_CH(2) | AUDIO_TYPE_LPCM | CFG_SUB_PCKT_NUM(4);
  821. writel(val, mhdp->regs + SMPL2PKT_CNFG);
  822. writel(SMPL2PKT_EN, mhdp->regs + SMPL2PKT_CNTL);
  823. val = SPDIF_ENABLE | SPDIF_AVG_SEL | SPDIF_JITTER_BYPASS;
  824. writel(val, mhdp->regs + SPDIF_CTRL_ADDR);
  825. clk_prepare_enable(mhdp->spdif_clk);
  826. clk_set_rate(mhdp->spdif_clk, CDNS_DP_SPDIF_CLK);
  827. }
  828. int cdns_mhdp_audio_config(struct cdns_mhdp_device *mhdp,
  829. struct audio_info *audio)
  830. {
  831. int ret;
  832. /* reset the spdif clk before config */
  833. if (audio->format == AFMT_SPDIF) {
  834. reset_control_assert(mhdp->spdif_rst);
  835. reset_control_deassert(mhdp->spdif_rst);
  836. }
  837. ret = cdns_mhdp_reg_write(mhdp, CM_LANE_CTRL, LANE_REF_CYC);
  838. if (ret)
  839. goto err_audio_config;
  840. ret = cdns_mhdp_reg_write(mhdp, CM_CTRL, 0);
  841. if (ret)
  842. goto err_audio_config;
  843. if (audio->format == AFMT_I2S)
  844. cdns_mhdp_audio_config_i2s(mhdp, audio);
  845. else if (audio->format == AFMT_SPDIF)
  846. cdns_mhdp_audio_config_spdif(mhdp);
  847. ret = cdns_mhdp_reg_write(mhdp, AUDIO_PACK_CONTROL, AUDIO_PACK_EN);
  848. err_audio_config:
  849. if (ret)
  850. DRM_DEV_ERROR(mhdp->dev, "audio config failed: %d\n", ret);
  851. return ret;
  852. }
  853. EXPORT_SYMBOL(cdns_mhdp_audio_config);
  854. int cdns_mhdp_adjust_lt(struct cdns_mhdp_device *mhdp,
  855. u8 nlanes, u16 udelay, u8 *lanes_data, u8 *dpcd)
  856. {
  857. u8 payload[7];
  858. u8 hdr[5]; /* For DPCD read response header */
  859. u32 addr;
  860. u8 const nregs = 6; /* Registers 0x202-0x207 */
  861. int ret;
  862. if (nlanes != 4 && nlanes != 2 && nlanes != 1) {
  863. DRM_DEV_ERROR(mhdp->dev, "invalid number of lanes: %d\n",
  864. nlanes);
  865. ret = -EINVAL;
  866. goto err_adjust_lt;
  867. }
  868. payload[0] = nlanes;
  869. put_unaligned_be16(udelay, payload + 1);
  870. memcpy(payload + 3, lanes_data, nlanes);
  871. ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_DP_TX,
  872. DPTX_ADJUST_LT,
  873. sizeof(payload), payload);
  874. if (ret)
  875. goto err_adjust_lt;
  876. /* Yes, read the DPCD read command response */
  877. ret = cdns_mhdp_mailbox_validate_receive(mhdp, MB_MODULE_ID_DP_TX,
  878. DPTX_READ_DPCD,
  879. sizeof(hdr) + nregs);
  880. if (ret)
  881. goto err_adjust_lt;
  882. ret = cdns_mhdp_mailbox_read_receive(mhdp, hdr, sizeof(hdr));
  883. if (ret)
  884. goto err_adjust_lt;
  885. addr = get_unaligned_be24(hdr + 2);
  886. if (addr != DP_LANE0_1_STATUS)
  887. goto err_adjust_lt;
  888. ret = cdns_mhdp_mailbox_read_receive(mhdp, dpcd, nregs);
  889. err_adjust_lt:
  890. if (ret)
  891. DRM_DEV_ERROR(mhdp->dev, "Failed to adjust Link Training.\n");
  892. return ret;
  893. }
  894. EXPORT_SYMBOL(cdns_mhdp_adjust_lt);