dp_audio.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
  4. */
  5. #define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__
  6. #include <linux/of_platform.h>
  7. #include <linux/msm_ext_display.h>
  8. #include <drm/drm_dp_helper.h>
  9. #include "dp_catalog.h"
  10. #include "dp_audio.h"
  11. #include "dp_panel.h"
  12. struct dp_audio_private {
  13. struct platform_device *ext_pdev;
  14. struct platform_device *pdev;
  15. struct dp_catalog_audio *catalog;
  16. struct msm_ext_disp_init_data ext_audio_data;
  17. struct dp_panel *panel;
  18. bool ack_enabled;
  19. bool session_on;
  20. bool engine_on;
  21. u32 channels;
  22. struct completion hpd_comp;
  23. struct workqueue_struct *notify_workqueue;
  24. struct delayed_work notify_delayed_work;
  25. struct mutex ops_lock;
  26. struct dp_audio dp_audio;
  27. atomic_t acked;
  28. };
  29. static u32 dp_audio_get_header(struct dp_catalog_audio *catalog,
  30. enum dp_catalog_audio_sdp_type sdp,
  31. enum dp_catalog_audio_header_type header)
  32. {
  33. catalog->sdp_type = sdp;
  34. catalog->sdp_header = header;
  35. catalog->get_header(catalog);
  36. return catalog->data;
  37. }
  38. static void dp_audio_set_header(struct dp_catalog_audio *catalog,
  39. u32 data,
  40. enum dp_catalog_audio_sdp_type sdp,
  41. enum dp_catalog_audio_header_type header)
  42. {
  43. catalog->sdp_type = sdp;
  44. catalog->sdp_header = header;
  45. catalog->data = data;
  46. catalog->set_header(catalog);
  47. }
  48. static void dp_audio_stream_sdp(struct dp_audio_private *audio)
  49. {
  50. struct dp_catalog_audio *catalog = audio->catalog;
  51. u32 value, new_value;
  52. u8 parity_byte;
  53. /* Config header and parity byte 1 */
  54. value = dp_audio_get_header(catalog,
  55. DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_1);
  56. value &= 0x0000ffff;
  57. new_value = 0x02;
  58. parity_byte = dp_header_get_parity(new_value);
  59. value |= ((new_value << HEADER_BYTE_1_BIT)
  60. | (parity_byte << PARITY_BYTE_1_BIT));
  61. pr_debug("Header Byte 1: value = 0x%x, parity_byte = 0x%x\n",
  62. value, parity_byte);
  63. dp_audio_set_header(catalog, value,
  64. DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_1);
  65. /* Config header and parity byte 2 */
  66. value = dp_audio_get_header(catalog,
  67. DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_2);
  68. value &= 0xffff0000;
  69. new_value = 0x0;
  70. parity_byte = dp_header_get_parity(new_value);
  71. value |= ((new_value << HEADER_BYTE_2_BIT)
  72. | (parity_byte << PARITY_BYTE_2_BIT));
  73. pr_debug("Header Byte 2: value = 0x%x, parity_byte = 0x%x\n",
  74. value, parity_byte);
  75. dp_audio_set_header(catalog, value,
  76. DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_2);
  77. /* Config header and parity byte 3 */
  78. value = dp_audio_get_header(catalog,
  79. DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_3);
  80. value &= 0x0000ffff;
  81. new_value = audio->channels - 1;
  82. parity_byte = dp_header_get_parity(new_value);
  83. value |= ((new_value << HEADER_BYTE_3_BIT)
  84. | (parity_byte << PARITY_BYTE_3_BIT));
  85. pr_debug("Header Byte 3: value = 0x%x, parity_byte = 0x%x\n",
  86. value, parity_byte);
  87. dp_audio_set_header(catalog, value,
  88. DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_3);
  89. }
  90. static void dp_audio_timestamp_sdp(struct dp_audio_private *audio)
  91. {
  92. struct dp_catalog_audio *catalog = audio->catalog;
  93. u32 value, new_value;
  94. u8 parity_byte;
  95. /* Config header and parity byte 1 */
  96. value = dp_audio_get_header(catalog,
  97. DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_1);
  98. value &= 0x0000ffff;
  99. new_value = 0x1;
  100. parity_byte = dp_header_get_parity(new_value);
  101. value |= ((new_value << HEADER_BYTE_1_BIT)
  102. | (parity_byte << PARITY_BYTE_1_BIT));
  103. pr_debug("Header Byte 1: value = 0x%x, parity_byte = 0x%x\n",
  104. value, parity_byte);
  105. dp_audio_set_header(catalog, value,
  106. DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_1);
  107. /* Config header and parity byte 2 */
  108. value = dp_audio_get_header(catalog,
  109. DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_2);
  110. value &= 0xffff0000;
  111. new_value = 0x17;
  112. parity_byte = dp_header_get_parity(new_value);
  113. value |= ((new_value << HEADER_BYTE_2_BIT)
  114. | (parity_byte << PARITY_BYTE_2_BIT));
  115. pr_debug("Header Byte 2: value = 0x%x, parity_byte = 0x%x\n",
  116. value, parity_byte);
  117. dp_audio_set_header(catalog, value,
  118. DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_2);
  119. /* Config header and parity byte 3 */
  120. value = dp_audio_get_header(catalog,
  121. DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_3);
  122. value &= 0x0000ffff;
  123. new_value = (0x0 | (0x11 << 2));
  124. parity_byte = dp_header_get_parity(new_value);
  125. value |= ((new_value << HEADER_BYTE_3_BIT)
  126. | (parity_byte << PARITY_BYTE_3_BIT));
  127. pr_debug("Header Byte 3: value = 0x%x, parity_byte = 0x%x\n",
  128. value, parity_byte);
  129. dp_audio_set_header(catalog, value,
  130. DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_3);
  131. }
  132. static void dp_audio_infoframe_sdp(struct dp_audio_private *audio)
  133. {
  134. struct dp_catalog_audio *catalog = audio->catalog;
  135. u32 value, new_value;
  136. u8 parity_byte;
  137. /* Config header and parity byte 1 */
  138. value = dp_audio_get_header(catalog,
  139. DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_1);
  140. value &= 0x0000ffff;
  141. new_value = 0x84;
  142. parity_byte = dp_header_get_parity(new_value);
  143. value |= ((new_value << HEADER_BYTE_1_BIT)
  144. | (parity_byte << PARITY_BYTE_1_BIT));
  145. pr_debug("Header Byte 1: value = 0x%x, parity_byte = 0x%x\n",
  146. value, parity_byte);
  147. dp_audio_set_header(catalog, value,
  148. DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_1);
  149. /* Config header and parity byte 2 */
  150. value = dp_audio_get_header(catalog,
  151. DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_2);
  152. value &= 0xffff0000;
  153. new_value = 0x1b;
  154. parity_byte = dp_header_get_parity(new_value);
  155. value |= ((new_value << HEADER_BYTE_2_BIT)
  156. | (parity_byte << PARITY_BYTE_2_BIT));
  157. pr_debug("Header Byte 2: value = 0x%x, parity_byte = 0x%x\n",
  158. value, parity_byte);
  159. dp_audio_set_header(catalog, value,
  160. DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_2);
  161. /* Config header and parity byte 3 */
  162. value = dp_audio_get_header(catalog,
  163. DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_3);
  164. value &= 0x0000ffff;
  165. new_value = (0x0 | (0x11 << 2));
  166. parity_byte = dp_header_get_parity(new_value);
  167. value |= ((new_value << HEADER_BYTE_3_BIT)
  168. | (parity_byte << PARITY_BYTE_3_BIT));
  169. pr_debug("Header Byte 3: value = 0x%x, parity_byte = 0x%x\n",
  170. new_value, parity_byte);
  171. dp_audio_set_header(catalog, value,
  172. DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_3);
  173. }
  174. static void dp_audio_copy_management_sdp(struct dp_audio_private *audio)
  175. {
  176. struct dp_catalog_audio *catalog = audio->catalog;
  177. u32 value, new_value;
  178. u8 parity_byte;
  179. /* Config header and parity byte 1 */
  180. value = dp_audio_get_header(catalog,
  181. DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_1);
  182. value &= 0x0000ffff;
  183. new_value = 0x05;
  184. parity_byte = dp_header_get_parity(new_value);
  185. value |= ((new_value << HEADER_BYTE_1_BIT)
  186. | (parity_byte << PARITY_BYTE_1_BIT));
  187. pr_debug("Header Byte 1: value = 0x%x, parity_byte = 0x%x\n",
  188. value, parity_byte);
  189. dp_audio_set_header(catalog, value,
  190. DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_1);
  191. /* Config header and parity byte 2 */
  192. value = dp_audio_get_header(catalog,
  193. DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_2);
  194. value &= 0xffff0000;
  195. new_value = 0x0F;
  196. parity_byte = dp_header_get_parity(new_value);
  197. value |= ((new_value << HEADER_BYTE_2_BIT)
  198. | (parity_byte << PARITY_BYTE_2_BIT));
  199. pr_debug("Header Byte 2: value = 0x%x, parity_byte = 0x%x\n",
  200. value, parity_byte);
  201. dp_audio_set_header(catalog, value,
  202. DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_2);
  203. /* Config header and parity byte 3 */
  204. value = dp_audio_get_header(catalog,
  205. DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_3);
  206. value &= 0x0000ffff;
  207. new_value = 0x0;
  208. parity_byte = dp_header_get_parity(new_value);
  209. value |= ((new_value << HEADER_BYTE_3_BIT)
  210. | (parity_byte << PARITY_BYTE_3_BIT));
  211. pr_debug("Header Byte 3: value = 0x%x, parity_byte = 0x%x\n",
  212. value, parity_byte);
  213. dp_audio_set_header(catalog, value,
  214. DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_3);
  215. }
  216. static void dp_audio_isrc_sdp(struct dp_audio_private *audio)
  217. {
  218. struct dp_catalog_audio *catalog = audio->catalog;
  219. u32 value, new_value;
  220. u8 parity_byte;
  221. /* Config header and parity byte 1 */
  222. value = dp_audio_get_header(catalog,
  223. DP_AUDIO_SDP_ISRC, DP_AUDIO_SDP_HEADER_1);
  224. value &= 0x0000ffff;
  225. new_value = 0x06;
  226. parity_byte = dp_header_get_parity(new_value);
  227. value |= ((new_value << HEADER_BYTE_1_BIT)
  228. | (parity_byte << PARITY_BYTE_1_BIT));
  229. pr_debug("Header Byte 1: value = 0x%x, parity_byte = 0x%x\n",
  230. value, parity_byte);
  231. dp_audio_set_header(catalog, value,
  232. DP_AUDIO_SDP_ISRC, DP_AUDIO_SDP_HEADER_1);
  233. /* Config header and parity byte 2 */
  234. value = dp_audio_get_header(catalog,
  235. DP_AUDIO_SDP_ISRC, DP_AUDIO_SDP_HEADER_2);
  236. value &= 0xffff0000;
  237. new_value = 0x0F;
  238. parity_byte = dp_header_get_parity(new_value);
  239. value |= ((new_value << HEADER_BYTE_2_BIT)
  240. | (parity_byte << PARITY_BYTE_2_BIT));
  241. pr_debug("Header Byte 2: value = 0x%x, parity_byte = 0x%x\n",
  242. value, parity_byte);
  243. dp_audio_set_header(catalog, value,
  244. DP_AUDIO_SDP_ISRC, DP_AUDIO_SDP_HEADER_2);
  245. }
  246. static void dp_audio_setup_sdp(struct dp_audio_private *audio)
  247. {
  248. /* always program stream 0 first before actual stream cfg */
  249. audio->catalog->stream_id = DP_STREAM_0;
  250. audio->catalog->config_sdp(audio->catalog);
  251. if (audio->panel->stream_id == DP_STREAM_1) {
  252. audio->catalog->stream_id = DP_STREAM_1;
  253. audio->catalog->config_sdp(audio->catalog);
  254. }
  255. dp_audio_stream_sdp(audio);
  256. dp_audio_timestamp_sdp(audio);
  257. dp_audio_infoframe_sdp(audio);
  258. dp_audio_copy_management_sdp(audio);
  259. dp_audio_isrc_sdp(audio);
  260. }
  261. static void dp_audio_setup_acr(struct dp_audio_private *audio)
  262. {
  263. u32 select = 0;
  264. struct dp_catalog_audio *catalog = audio->catalog;
  265. switch (audio->dp_audio.bw_code) {
  266. case DP_LINK_BW_1_62:
  267. select = 0;
  268. break;
  269. case DP_LINK_BW_2_7:
  270. select = 1;
  271. break;
  272. case DP_LINK_BW_5_4:
  273. select = 2;
  274. break;
  275. case DP_LINK_BW_8_1:
  276. select = 3;
  277. break;
  278. default:
  279. pr_debug("Unknown link rate\n");
  280. select = 0;
  281. break;
  282. }
  283. catalog->data = select;
  284. catalog->config_acr(catalog);
  285. }
  286. static void dp_audio_enable(struct dp_audio_private *audio, bool enable)
  287. {
  288. struct dp_catalog_audio *catalog = audio->catalog;
  289. catalog->data = enable;
  290. catalog->enable(catalog);
  291. audio->engine_on = enable;
  292. }
  293. static struct dp_audio_private *dp_audio_get_data(struct platform_device *pdev)
  294. {
  295. struct msm_ext_disp_data *ext_data;
  296. struct dp_audio *dp_audio;
  297. if (!pdev) {
  298. pr_err("invalid input\n");
  299. return ERR_PTR(-ENODEV);
  300. }
  301. ext_data = platform_get_drvdata(pdev);
  302. if (!ext_data) {
  303. pr_err("invalid ext disp data\n");
  304. return ERR_PTR(-EINVAL);
  305. }
  306. dp_audio = ext_data->intf_data;
  307. if (!ext_data) {
  308. pr_err("invalid intf data\n");
  309. return ERR_PTR(-EINVAL);
  310. }
  311. return container_of(dp_audio, struct dp_audio_private, dp_audio);
  312. }
  313. static int dp_audio_info_setup(struct platform_device *pdev,
  314. struct msm_ext_disp_audio_setup_params *params)
  315. {
  316. int rc = 0;
  317. struct dp_audio_private *audio;
  318. audio = dp_audio_get_data(pdev);
  319. if (IS_ERR(audio)) {
  320. rc = PTR_ERR(audio);
  321. return rc;
  322. }
  323. mutex_lock(&audio->ops_lock);
  324. audio->channels = params->num_of_channels;
  325. if (audio->panel->stream_id >= DP_STREAM_MAX) {
  326. pr_err("invalid stream id: %d\n", audio->panel->stream_id);
  327. rc = -EINVAL;
  328. mutex_unlock(&audio->ops_lock);
  329. return rc;
  330. }
  331. dp_audio_setup_sdp(audio);
  332. dp_audio_setup_acr(audio);
  333. dp_audio_enable(audio, true);
  334. mutex_unlock(&audio->ops_lock);
  335. return rc;
  336. }
  337. static int dp_audio_get_edid_blk(struct platform_device *pdev,
  338. struct msm_ext_disp_audio_edid_blk *blk)
  339. {
  340. int rc = 0;
  341. struct dp_audio_private *audio;
  342. struct sde_edid_ctrl *edid;
  343. audio = dp_audio_get_data(pdev);
  344. if (IS_ERR(audio)) {
  345. rc = PTR_ERR(audio);
  346. goto end;
  347. }
  348. if (!audio->panel || !audio->panel->edid_ctrl) {
  349. pr_err("invalid panel data\n");
  350. rc = -EINVAL;
  351. goto end;
  352. }
  353. edid = audio->panel->edid_ctrl;
  354. blk->audio_data_blk = edid->audio_data_block;
  355. blk->audio_data_blk_size = edid->adb_size;
  356. blk->spk_alloc_data_blk = edid->spkr_alloc_data_block;
  357. blk->spk_alloc_data_blk_size = edid->sadb_size;
  358. end:
  359. return rc;
  360. }
  361. static int dp_audio_get_cable_status(struct platform_device *pdev, u32 vote)
  362. {
  363. int rc = 0;
  364. struct dp_audio_private *audio;
  365. audio = dp_audio_get_data(pdev);
  366. if (IS_ERR(audio)) {
  367. rc = PTR_ERR(audio);
  368. goto end;
  369. }
  370. return audio->session_on;
  371. end:
  372. return rc;
  373. }
  374. static int dp_audio_get_intf_id(struct platform_device *pdev)
  375. {
  376. int rc = 0;
  377. struct dp_audio_private *audio;
  378. audio = dp_audio_get_data(pdev);
  379. if (IS_ERR(audio)) {
  380. rc = PTR_ERR(audio);
  381. goto end;
  382. }
  383. return EXT_DISPLAY_TYPE_DP;
  384. end:
  385. return rc;
  386. }
  387. static void dp_audio_teardown_done(struct platform_device *pdev)
  388. {
  389. struct dp_audio_private *audio;
  390. audio = dp_audio_get_data(pdev);
  391. if (IS_ERR(audio))
  392. return;
  393. mutex_lock(&audio->ops_lock);
  394. dp_audio_enable(audio, false);
  395. mutex_unlock(&audio->ops_lock);
  396. atomic_set(&audio->acked, 1);
  397. complete_all(&audio->hpd_comp);
  398. pr_debug("audio engine disabled\n");
  399. }
  400. static int dp_audio_ack_done(struct platform_device *pdev, u32 ack)
  401. {
  402. int rc = 0, ack_hpd;
  403. struct dp_audio_private *audio;
  404. audio = dp_audio_get_data(pdev);
  405. if (IS_ERR(audio)) {
  406. rc = PTR_ERR(audio);
  407. goto end;
  408. }
  409. if (ack & AUDIO_ACK_SET_ENABLE) {
  410. audio->ack_enabled = ack & AUDIO_ACK_ENABLE ?
  411. true : false;
  412. pr_debug("audio ack feature %s\n",
  413. audio->ack_enabled ? "enabled" : "disabled");
  414. goto end;
  415. }
  416. if (!audio->ack_enabled)
  417. goto end;
  418. ack_hpd = ack & AUDIO_ACK_CONNECT;
  419. pr_debug("acknowledging audio (%d)\n", ack_hpd);
  420. if (!audio->engine_on) {
  421. atomic_set(&audio->acked, 1);
  422. complete_all(&audio->hpd_comp);
  423. }
  424. end:
  425. return rc;
  426. }
  427. static int dp_audio_codec_ready(struct platform_device *pdev)
  428. {
  429. int rc = 0;
  430. struct dp_audio_private *audio;
  431. audio = dp_audio_get_data(pdev);
  432. if (IS_ERR(audio)) {
  433. pr_err("invalid input\n");
  434. rc = PTR_ERR(audio);
  435. goto end;
  436. }
  437. queue_delayed_work(audio->notify_workqueue,
  438. &audio->notify_delayed_work, HZ/4);
  439. end:
  440. return rc;
  441. }
  442. static int dp_audio_register_ext_disp(struct dp_audio_private *audio)
  443. {
  444. int rc = 0;
  445. struct device_node *pd = NULL;
  446. const char *phandle = "qcom,ext-disp";
  447. struct msm_ext_disp_init_data *ext;
  448. struct msm_ext_disp_audio_codec_ops *ops;
  449. ext = &audio->ext_audio_data;
  450. ops = &ext->codec_ops;
  451. ext->codec.type = EXT_DISPLAY_TYPE_DP;
  452. ext->codec.ctrl_id = 0;
  453. ext->codec.stream_id = audio->panel->stream_id;
  454. ext->pdev = audio->pdev;
  455. ext->intf_data = &audio->dp_audio;
  456. ops->audio_info_setup = dp_audio_info_setup;
  457. ops->get_audio_edid_blk = dp_audio_get_edid_blk;
  458. ops->cable_status = dp_audio_get_cable_status;
  459. ops->get_intf_id = dp_audio_get_intf_id;
  460. ops->teardown_done = dp_audio_teardown_done;
  461. ops->acknowledge = dp_audio_ack_done;
  462. ops->ready = dp_audio_codec_ready;
  463. if (!audio->pdev->dev.of_node) {
  464. pr_err("cannot find audio dev.of_node\n");
  465. rc = -ENODEV;
  466. goto end;
  467. }
  468. pd = of_parse_phandle(audio->pdev->dev.of_node, phandle, 0);
  469. if (!pd) {
  470. pr_err("cannot parse %s handle\n", phandle);
  471. rc = -ENODEV;
  472. goto end;
  473. }
  474. audio->ext_pdev = of_find_device_by_node(pd);
  475. if (!audio->ext_pdev) {
  476. pr_err("cannot find %s pdev\n", phandle);
  477. rc = -ENODEV;
  478. goto end;
  479. }
  480. #if defined(CONFIG_MSM_EXT_DISPLAY)
  481. rc = msm_ext_disp_register_intf(audio->ext_pdev, ext);
  482. if (rc)
  483. pr_err("failed to register disp\n");
  484. #endif
  485. end:
  486. if (pd)
  487. of_node_put(pd);
  488. return rc;
  489. }
  490. static int dp_audio_deregister_ext_disp(struct dp_audio_private *audio)
  491. {
  492. int rc = 0;
  493. struct device_node *pd = NULL;
  494. const char *phandle = "qcom,ext-disp";
  495. struct msm_ext_disp_init_data *ext;
  496. ext = &audio->ext_audio_data;
  497. if (!audio->pdev->dev.of_node) {
  498. pr_err("cannot find audio dev.of_node\n");
  499. rc = -ENODEV;
  500. goto end;
  501. }
  502. pd = of_parse_phandle(audio->pdev->dev.of_node, phandle, 0);
  503. if (!pd) {
  504. pr_err("cannot parse %s handle\n", phandle);
  505. rc = -ENODEV;
  506. goto end;
  507. }
  508. audio->ext_pdev = of_find_device_by_node(pd);
  509. if (!audio->ext_pdev) {
  510. pr_err("cannot find %s pdev\n", phandle);
  511. rc = -ENODEV;
  512. goto end;
  513. }
  514. #if defined(CONFIG_MSM_EXT_DISPLAY)
  515. rc = msm_ext_disp_deregister_intf(audio->ext_pdev, ext);
  516. if (rc)
  517. pr_err("failed to deregister disp\n");
  518. #endif
  519. end:
  520. return rc;
  521. }
  522. static int dp_audio_notify(struct dp_audio_private *audio, u32 state)
  523. {
  524. int rc = 0;
  525. struct msm_ext_disp_init_data *ext = &audio->ext_audio_data;
  526. atomic_set(&audio->acked, 0);
  527. if (!ext->intf_ops.audio_notify) {
  528. pr_err("audio notify not defined\n");
  529. goto end;
  530. }
  531. reinit_completion(&audio->hpd_comp);
  532. rc = ext->intf_ops.audio_notify(audio->ext_pdev,
  533. &ext->codec, state);
  534. if (rc)
  535. goto end;
  536. if (atomic_read(&audio->acked))
  537. goto end;
  538. rc = wait_for_completion_timeout(&audio->hpd_comp, HZ * 4);
  539. if (!rc) {
  540. pr_err("timeout. state=%d err=%d\n", state, rc);
  541. rc = -ETIMEDOUT;
  542. goto end;
  543. }
  544. pr_debug("success\n");
  545. end:
  546. return rc;
  547. }
  548. static int dp_audio_config(struct dp_audio_private *audio, u32 state)
  549. {
  550. int rc = 0;
  551. struct msm_ext_disp_init_data *ext = &audio->ext_audio_data;
  552. if (!ext || !ext->intf_ops.audio_config) {
  553. pr_err("audio_config not defined\n");
  554. goto end;
  555. }
  556. /*
  557. * DP Audio sets default STREAM_0 only, other streams are
  558. * set by audio driver based on the hardware/software support.
  559. */
  560. if (audio->panel->stream_id == DP_STREAM_0) {
  561. rc = ext->intf_ops.audio_config(audio->ext_pdev,
  562. &ext->codec, state);
  563. if (rc)
  564. pr_err("failed to config audio, err=%d\n", rc);
  565. }
  566. end:
  567. return rc;
  568. }
  569. static int dp_audio_on(struct dp_audio *dp_audio)
  570. {
  571. int rc = 0;
  572. struct dp_audio_private *audio;
  573. struct msm_ext_disp_init_data *ext;
  574. if (!dp_audio) {
  575. pr_err("invalid input\n");
  576. return -EINVAL;
  577. }
  578. audio = container_of(dp_audio, struct dp_audio_private, dp_audio);
  579. if (IS_ERR(audio)) {
  580. pr_err("invalid input\n");
  581. return -EINVAL;
  582. }
  583. dp_audio_register_ext_disp(audio);
  584. ext = &audio->ext_audio_data;
  585. audio->session_on = true;
  586. rc = dp_audio_config(audio, EXT_DISPLAY_CABLE_CONNECT);
  587. if (rc)
  588. goto end;
  589. rc = dp_audio_notify(audio, EXT_DISPLAY_CABLE_CONNECT);
  590. if (rc)
  591. goto end;
  592. pr_debug("success\n");
  593. end:
  594. return rc;
  595. }
  596. static int dp_audio_off(struct dp_audio *dp_audio)
  597. {
  598. int rc = 0;
  599. struct dp_audio_private *audio;
  600. struct msm_ext_disp_init_data *ext;
  601. bool work_pending = false;
  602. if (!dp_audio) {
  603. pr_err("invalid input\n");
  604. return -EINVAL;
  605. }
  606. audio = container_of(dp_audio, struct dp_audio_private, dp_audio);
  607. ext = &audio->ext_audio_data;
  608. work_pending = cancel_delayed_work_sync(&audio->notify_delayed_work);
  609. if (work_pending)
  610. pr_debug("pending notification work completed\n");
  611. rc = dp_audio_notify(audio, EXT_DISPLAY_CABLE_DISCONNECT);
  612. if (rc)
  613. goto end;
  614. pr_debug("success\n");
  615. end:
  616. dp_audio_config(audio, EXT_DISPLAY_CABLE_DISCONNECT);
  617. audio->session_on = false;
  618. audio->engine_on = false;
  619. dp_audio_deregister_ext_disp(audio);
  620. return rc;
  621. }
  622. static void dp_audio_notify_work_fn(struct work_struct *work)
  623. {
  624. struct dp_audio_private *audio;
  625. struct delayed_work *dw = to_delayed_work(work);
  626. audio = container_of(dw, struct dp_audio_private, notify_delayed_work);
  627. dp_audio_notify(audio, EXT_DISPLAY_CABLE_CONNECT);
  628. }
  629. static int dp_audio_create_notify_workqueue(struct dp_audio_private *audio)
  630. {
  631. audio->notify_workqueue = create_workqueue("sdm_dp_audio_notify");
  632. if (IS_ERR_OR_NULL(audio->notify_workqueue)) {
  633. pr_err("Error creating notify_workqueue\n");
  634. return -EPERM;
  635. }
  636. INIT_DELAYED_WORK(&audio->notify_delayed_work, dp_audio_notify_work_fn);
  637. return 0;
  638. }
  639. static void dp_audio_destroy_notify_workqueue(struct dp_audio_private *audio)
  640. {
  641. if (audio->notify_workqueue)
  642. destroy_workqueue(audio->notify_workqueue);
  643. }
  644. struct dp_audio *dp_audio_get(struct platform_device *pdev,
  645. struct dp_panel *panel,
  646. struct dp_catalog_audio *catalog)
  647. {
  648. int rc = 0;
  649. struct dp_audio_private *audio;
  650. struct dp_audio *dp_audio;
  651. if (!pdev || !panel || !catalog) {
  652. pr_err("invalid input\n");
  653. rc = -EINVAL;
  654. goto error;
  655. }
  656. audio = devm_kzalloc(&pdev->dev, sizeof(*audio), GFP_KERNEL);
  657. if (!audio) {
  658. rc = -ENOMEM;
  659. goto error;
  660. }
  661. rc = dp_audio_create_notify_workqueue(audio);
  662. if (rc)
  663. goto error_notify_workqueue;
  664. init_completion(&audio->hpd_comp);
  665. audio->pdev = pdev;
  666. audio->panel = panel;
  667. audio->catalog = catalog;
  668. atomic_set(&audio->acked, 0);
  669. dp_audio = &audio->dp_audio;
  670. mutex_init(&audio->ops_lock);
  671. dp_audio->on = dp_audio_on;
  672. dp_audio->off = dp_audio_off;
  673. catalog->init(catalog);
  674. return dp_audio;
  675. error_notify_workqueue:
  676. devm_kfree(&pdev->dev, audio);
  677. error:
  678. return ERR_PTR(rc);
  679. }
  680. void dp_audio_put(struct dp_audio *dp_audio)
  681. {
  682. struct dp_audio_private *audio;
  683. if (!dp_audio)
  684. return;
  685. audio = container_of(dp_audio, struct dp_audio_private, dp_audio);
  686. mutex_destroy(&audio->ops_lock);
  687. dp_audio_destroy_notify_workqueue(audio);
  688. devm_kfree(&audio->pdev->dev, audio);
  689. }