dp_audio.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
  4. */
  5. #include <linux/of_platform.h>
  6. #include <linux/soc/qcom/msm_ext_display.h>
  7. #include <drm/drm_dp_helper.h>
  8. #include "dp_catalog.h"
  9. #include "dp_audio.h"
  10. #include "dp_panel.h"
  11. #include "dp_debug.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. atomic_t 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. DP_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. DP_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. DP_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. DP_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. DP_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. DP_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. DP_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. DP_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. DP_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. DP_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. DP_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. DP_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. DP_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. DP_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. if (!atomic_read(&audio->session_on)) {
  249. DP_WARN("session inactive\n");
  250. return;
  251. }
  252. /* always program stream 0 first before actual stream cfg */
  253. audio->catalog->stream_id = DP_STREAM_0;
  254. audio->catalog->config_sdp(audio->catalog);
  255. if (audio->panel->stream_id == DP_STREAM_1) {
  256. audio->catalog->stream_id = DP_STREAM_1;
  257. audio->catalog->config_sdp(audio->catalog);
  258. }
  259. dp_audio_stream_sdp(audio);
  260. dp_audio_timestamp_sdp(audio);
  261. dp_audio_infoframe_sdp(audio);
  262. dp_audio_copy_management_sdp(audio);
  263. dp_audio_isrc_sdp(audio);
  264. }
  265. static void dp_audio_setup_acr(struct dp_audio_private *audio)
  266. {
  267. u32 select = 0;
  268. struct dp_catalog_audio *catalog = audio->catalog;
  269. if (!atomic_read(&audio->session_on)) {
  270. DP_WARN("session inactive\n");
  271. return;
  272. }
  273. switch (audio->dp_audio.bw_code) {
  274. case DP_LINK_BW_1_62:
  275. select = 0;
  276. break;
  277. case DP_LINK_BW_2_7:
  278. select = 1;
  279. break;
  280. case DP_LINK_BW_5_4:
  281. select = 2;
  282. break;
  283. case DP_LINK_BW_8_1:
  284. select = 3;
  285. break;
  286. default:
  287. DP_DEBUG("Unknown link rate\n");
  288. select = 0;
  289. break;
  290. }
  291. catalog->data = select;
  292. catalog->config_acr(catalog);
  293. }
  294. static void dp_audio_enable(struct dp_audio_private *audio, bool enable)
  295. {
  296. struct dp_catalog_audio *catalog = audio->catalog;
  297. audio->engine_on = enable;
  298. if (!atomic_read(&audio->session_on)) {
  299. DP_WARN("session inactive. enable=%d\n", enable);
  300. return;
  301. }
  302. catalog->data = enable;
  303. catalog->enable(catalog);
  304. }
  305. static struct dp_audio_private *dp_audio_get_data(struct platform_device *pdev)
  306. {
  307. struct msm_ext_disp_data *ext_data;
  308. struct dp_audio *dp_audio;
  309. if (!pdev) {
  310. DP_ERR("invalid input\n");
  311. return ERR_PTR(-ENODEV);
  312. }
  313. ext_data = platform_get_drvdata(pdev);
  314. if (!ext_data) {
  315. DP_ERR("invalid ext disp data\n");
  316. return ERR_PTR(-EINVAL);
  317. }
  318. dp_audio = ext_data->intf_data;
  319. if (!dp_audio) {
  320. DP_ERR("invalid intf data\n");
  321. return ERR_PTR(-EINVAL);
  322. }
  323. return container_of(dp_audio, struct dp_audio_private, dp_audio);
  324. }
  325. static int dp_audio_info_setup(struct platform_device *pdev,
  326. struct msm_ext_disp_audio_setup_params *params)
  327. {
  328. int rc = 0;
  329. struct dp_audio_private *audio;
  330. audio = dp_audio_get_data(pdev);
  331. if (IS_ERR(audio)) {
  332. rc = PTR_ERR(audio);
  333. return rc;
  334. }
  335. if (audio->dp_audio.tui_active) {
  336. DP_DEBUG("TUI session active\n");
  337. return 0;
  338. }
  339. mutex_lock(&audio->ops_lock);
  340. audio->channels = params->num_of_channels;
  341. if (audio->panel->stream_id >= DP_STREAM_MAX) {
  342. DP_ERR("invalid stream id: %d\n",
  343. audio->panel->stream_id);
  344. rc = -EINVAL;
  345. mutex_unlock(&audio->ops_lock);
  346. return rc;
  347. }
  348. dp_audio_setup_sdp(audio);
  349. dp_audio_setup_acr(audio);
  350. dp_audio_enable(audio, true);
  351. mutex_unlock(&audio->ops_lock);
  352. DP_DEBUG("audio stream configured\n");
  353. return rc;
  354. }
  355. static int dp_audio_get_edid_blk(struct platform_device *pdev,
  356. struct msm_ext_disp_audio_edid_blk *blk)
  357. {
  358. int rc = 0;
  359. struct dp_audio_private *audio;
  360. struct sde_edid_ctrl *edid;
  361. if (!blk) {
  362. DP_ERR("invalid input\n");
  363. return -EINVAL;
  364. }
  365. audio = dp_audio_get_data(pdev);
  366. if (IS_ERR(audio)) {
  367. rc = PTR_ERR(audio);
  368. goto end;
  369. }
  370. if (!audio->panel || !audio->panel->edid_ctrl) {
  371. DP_ERR("invalid panel data\n");
  372. rc = -EINVAL;
  373. goto end;
  374. }
  375. edid = audio->panel->edid_ctrl;
  376. blk->audio_data_blk = edid->audio_data_block;
  377. blk->audio_data_blk_size = edid->adb_size;
  378. blk->spk_alloc_data_blk = edid->spkr_alloc_data_block;
  379. blk->spk_alloc_data_blk_size = edid->sadb_size;
  380. end:
  381. return rc;
  382. }
  383. static int dp_audio_get_cable_status(struct platform_device *pdev, u32 vote)
  384. {
  385. int rc = 0;
  386. struct dp_audio_private *audio;
  387. audio = dp_audio_get_data(pdev);
  388. if (IS_ERR(audio)) {
  389. rc = PTR_ERR(audio);
  390. goto end;
  391. }
  392. return atomic_read(&audio->session_on);
  393. end:
  394. return rc;
  395. }
  396. static int dp_audio_get_intf_id(struct platform_device *pdev)
  397. {
  398. int rc = 0;
  399. struct dp_audio_private *audio;
  400. audio = dp_audio_get_data(pdev);
  401. if (IS_ERR(audio)) {
  402. rc = PTR_ERR(audio);
  403. goto end;
  404. }
  405. return EXT_DISPLAY_TYPE_DP;
  406. end:
  407. return rc;
  408. }
  409. static void dp_audio_teardown_done(struct platform_device *pdev)
  410. {
  411. struct dp_audio_private *audio;
  412. audio = dp_audio_get_data(pdev);
  413. if (IS_ERR(audio))
  414. return;
  415. if (audio->dp_audio.tui_active) {
  416. DP_DEBUG("TUI session active\n");
  417. return;
  418. }
  419. mutex_lock(&audio->ops_lock);
  420. dp_audio_enable(audio, false);
  421. mutex_unlock(&audio->ops_lock);
  422. atomic_set(&audio->acked, 1);
  423. complete_all(&audio->hpd_comp);
  424. DP_DEBUG("audio engine disabled\n");
  425. }
  426. static int dp_audio_ack_done(struct platform_device *pdev, u32 ack)
  427. {
  428. int rc = 0, ack_hpd;
  429. struct dp_audio_private *audio;
  430. audio = dp_audio_get_data(pdev);
  431. if (IS_ERR(audio)) {
  432. rc = PTR_ERR(audio);
  433. goto end;
  434. }
  435. if (ack & AUDIO_ACK_SET_ENABLE) {
  436. audio->ack_enabled = ack & AUDIO_ACK_ENABLE ?
  437. true : false;
  438. DP_DEBUG("audio ack feature %s\n",
  439. audio->ack_enabled ? "enabled" : "disabled");
  440. goto end;
  441. }
  442. if (!audio->ack_enabled)
  443. goto end;
  444. ack_hpd = ack & AUDIO_ACK_CONNECT;
  445. DP_DEBUG("acknowledging audio (%d)\n", ack_hpd);
  446. if (!audio->engine_on) {
  447. atomic_set(&audio->acked, 1);
  448. complete_all(&audio->hpd_comp);
  449. }
  450. end:
  451. return rc;
  452. }
  453. static int dp_audio_codec_ready(struct platform_device *pdev)
  454. {
  455. int rc = 0;
  456. struct dp_audio_private *audio;
  457. audio = dp_audio_get_data(pdev);
  458. if (IS_ERR(audio)) {
  459. DP_ERR("invalid input\n");
  460. rc = PTR_ERR(audio);
  461. goto end;
  462. }
  463. queue_delayed_work(audio->notify_workqueue,
  464. &audio->notify_delayed_work, HZ/4);
  465. end:
  466. return rc;
  467. }
  468. static int dp_audio_register_ext_disp(struct dp_audio_private *audio)
  469. {
  470. int rc = 0;
  471. struct device_node *pd = NULL;
  472. const char *phandle = "qcom,ext-disp";
  473. struct msm_ext_disp_init_data *ext;
  474. struct msm_ext_disp_audio_codec_ops *ops;
  475. ext = &audio->ext_audio_data;
  476. ops = &ext->codec_ops;
  477. ext->codec.type = EXT_DISPLAY_TYPE_DP;
  478. ext->codec.ctrl_id = 0;
  479. ext->codec.stream_id = audio->panel->stream_id;
  480. ext->pdev = audio->pdev;
  481. ext->intf_data = &audio->dp_audio;
  482. ops->audio_info_setup = dp_audio_info_setup;
  483. ops->get_audio_edid_blk = dp_audio_get_edid_blk;
  484. ops->cable_status = dp_audio_get_cable_status;
  485. ops->get_intf_id = dp_audio_get_intf_id;
  486. ops->teardown_done = dp_audio_teardown_done;
  487. ops->acknowledge = dp_audio_ack_done;
  488. ops->ready = dp_audio_codec_ready;
  489. if (!audio->pdev->dev.of_node) {
  490. DP_ERR("cannot find audio dev.of_node\n");
  491. rc = -ENODEV;
  492. goto end;
  493. }
  494. pd = of_parse_phandle(audio->pdev->dev.of_node, phandle, 0);
  495. if (!pd) {
  496. DP_ERR("cannot parse %s handle\n", phandle);
  497. rc = -ENODEV;
  498. goto end;
  499. }
  500. audio->ext_pdev = of_find_device_by_node(pd);
  501. if (!audio->ext_pdev) {
  502. DP_ERR("cannot find %s pdev\n", phandle);
  503. rc = -ENODEV;
  504. goto end;
  505. }
  506. #if defined(CONFIG_MSM_EXT_DISPLAY)
  507. rc = msm_ext_disp_register_intf(audio->ext_pdev, ext);
  508. if (rc)
  509. DP_ERR("failed to register disp\n");
  510. #endif
  511. end:
  512. if (pd)
  513. of_node_put(pd);
  514. return rc;
  515. }
  516. static int dp_audio_deregister_ext_disp(struct dp_audio_private *audio)
  517. {
  518. int rc = 0;
  519. struct device_node *pd = NULL;
  520. const char *phandle = "qcom,ext-disp";
  521. struct msm_ext_disp_init_data *ext;
  522. ext = &audio->ext_audio_data;
  523. if (!audio->pdev->dev.of_node) {
  524. DP_ERR("cannot find audio dev.of_node\n");
  525. rc = -ENODEV;
  526. goto end;
  527. }
  528. pd = of_parse_phandle(audio->pdev->dev.of_node, phandle, 0);
  529. if (!pd) {
  530. DP_ERR("cannot parse %s handle\n", phandle);
  531. rc = -ENODEV;
  532. goto end;
  533. }
  534. audio->ext_pdev = of_find_device_by_node(pd);
  535. if (!audio->ext_pdev) {
  536. DP_ERR("cannot find %s pdev\n", phandle);
  537. rc = -ENODEV;
  538. goto end;
  539. }
  540. #if defined(CONFIG_MSM_EXT_DISPLAY)
  541. rc = msm_ext_disp_deregister_intf(audio->ext_pdev, ext);
  542. if (rc)
  543. DP_ERR("failed to deregister disp\n");
  544. #endif
  545. end:
  546. return rc;
  547. }
  548. static int dp_audio_notify(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. atomic_set(&audio->acked, 0);
  553. if (!ext->intf_ops.audio_notify) {
  554. DP_ERR("audio notify not defined\n");
  555. goto end;
  556. }
  557. reinit_completion(&audio->hpd_comp);
  558. rc = ext->intf_ops.audio_notify(audio->ext_pdev,
  559. &ext->codec, state);
  560. if (rc)
  561. goto end;
  562. if (atomic_read(&audio->acked))
  563. goto end;
  564. if (state == EXT_DISPLAY_CABLE_DISCONNECT && !audio->engine_on)
  565. goto end;
  566. if (state == EXT_DISPLAY_CABLE_CONNECT)
  567. goto end;
  568. rc = wait_for_completion_timeout(&audio->hpd_comp, HZ * 4);
  569. if (!rc) {
  570. DP_ERR("timeout. state=%d err=%d\n", state, rc);
  571. rc = -ETIMEDOUT;
  572. goto end;
  573. }
  574. DP_DEBUG("success\n");
  575. end:
  576. return rc;
  577. }
  578. static int dp_audio_config(struct dp_audio_private *audio, u32 state)
  579. {
  580. int rc = 0;
  581. struct msm_ext_disp_init_data *ext = &audio->ext_audio_data;
  582. if (!ext || !ext->intf_ops.audio_config) {
  583. DP_ERR("audio_config not defined\n");
  584. goto end;
  585. }
  586. /*
  587. * DP Audio sets default STREAM_0 only, other streams are
  588. * set by audio driver based on the hardware/software support.
  589. */
  590. if (audio->panel->stream_id == DP_STREAM_0) {
  591. rc = ext->intf_ops.audio_config(audio->ext_pdev,
  592. &ext->codec, state);
  593. if (rc)
  594. DP_ERR("failed to config audio, err=%d\n",
  595. rc);
  596. }
  597. end:
  598. return rc;
  599. }
  600. static int dp_audio_on(struct dp_audio *dp_audio)
  601. {
  602. int rc = 0;
  603. struct dp_audio_private *audio;
  604. struct msm_ext_disp_init_data *ext;
  605. if (!dp_audio) {
  606. DP_ERR("invalid input\n");
  607. return -EINVAL;
  608. }
  609. audio = container_of(dp_audio, struct dp_audio_private, dp_audio);
  610. if (IS_ERR(audio)) {
  611. DP_ERR("invalid input\n");
  612. return -EINVAL;
  613. }
  614. dp_audio_register_ext_disp(audio);
  615. ext = &audio->ext_audio_data;
  616. atomic_set(&audio->session_on, 1);
  617. rc = dp_audio_config(audio, EXT_DISPLAY_CABLE_CONNECT);
  618. if (rc)
  619. goto end;
  620. rc = dp_audio_notify(audio, EXT_DISPLAY_CABLE_CONNECT);
  621. if (rc)
  622. goto end;
  623. DP_DEBUG("success\n");
  624. end:
  625. return rc;
  626. }
  627. static int dp_audio_off(struct dp_audio *dp_audio)
  628. {
  629. int rc = 0;
  630. struct dp_audio_private *audio;
  631. struct msm_ext_disp_init_data *ext;
  632. bool work_pending = false;
  633. if (!dp_audio) {
  634. DP_ERR("invalid input\n");
  635. return -EINVAL;
  636. }
  637. audio = container_of(dp_audio, struct dp_audio_private, dp_audio);
  638. if (!atomic_read(&audio->session_on)) {
  639. DP_DEBUG("audio already off\n");
  640. return rc;
  641. }
  642. ext = &audio->ext_audio_data;
  643. work_pending = cancel_delayed_work_sync(&audio->notify_delayed_work);
  644. if (work_pending)
  645. DP_DEBUG("pending notification work completed\n");
  646. rc = dp_audio_notify(audio, EXT_DISPLAY_CABLE_DISCONNECT);
  647. if (rc)
  648. goto end;
  649. DP_DEBUG("success\n");
  650. end:
  651. dp_audio_config(audio, EXT_DISPLAY_CABLE_DISCONNECT);
  652. atomic_set(&audio->session_on, 0);
  653. audio->engine_on = false;
  654. dp_audio_deregister_ext_disp(audio);
  655. return rc;
  656. }
  657. static void dp_audio_notify_work_fn(struct work_struct *work)
  658. {
  659. struct dp_audio_private *audio;
  660. struct delayed_work *dw = to_delayed_work(work);
  661. audio = container_of(dw, struct dp_audio_private, notify_delayed_work);
  662. dp_audio_notify(audio, EXT_DISPLAY_CABLE_CONNECT);
  663. }
  664. static int dp_audio_create_notify_workqueue(struct dp_audio_private *audio)
  665. {
  666. audio->notify_workqueue = create_workqueue("sdm_dp_audio_notify");
  667. if (IS_ERR_OR_NULL(audio->notify_workqueue)) {
  668. DP_ERR("Error creating notify_workqueue\n");
  669. return -EPERM;
  670. }
  671. INIT_DELAYED_WORK(&audio->notify_delayed_work, dp_audio_notify_work_fn);
  672. return 0;
  673. }
  674. static void dp_audio_destroy_notify_workqueue(struct dp_audio_private *audio)
  675. {
  676. if (audio->notify_workqueue)
  677. destroy_workqueue(audio->notify_workqueue);
  678. }
  679. struct dp_audio *dp_audio_get(struct platform_device *pdev,
  680. struct dp_panel *panel,
  681. struct dp_catalog_audio *catalog)
  682. {
  683. int rc = 0;
  684. struct dp_audio_private *audio;
  685. struct dp_audio *dp_audio;
  686. if (!pdev || !panel || !catalog) {
  687. DP_ERR("invalid input\n");
  688. rc = -EINVAL;
  689. goto error;
  690. }
  691. audio = devm_kzalloc(&pdev->dev, sizeof(*audio), GFP_KERNEL);
  692. if (!audio) {
  693. rc = -ENOMEM;
  694. goto error;
  695. }
  696. rc = dp_audio_create_notify_workqueue(audio);
  697. if (rc)
  698. goto error_notify_workqueue;
  699. init_completion(&audio->hpd_comp);
  700. audio->pdev = pdev;
  701. audio->panel = panel;
  702. audio->catalog = catalog;
  703. atomic_set(&audio->acked, 0);
  704. dp_audio = &audio->dp_audio;
  705. mutex_init(&audio->ops_lock);
  706. dp_audio->on = dp_audio_on;
  707. dp_audio->off = dp_audio_off;
  708. catalog->init(catalog);
  709. return dp_audio;
  710. error_notify_workqueue:
  711. devm_kfree(&pdev->dev, audio);
  712. error:
  713. return ERR_PTR(rc);
  714. }
  715. void dp_audio_put(struct dp_audio *dp_audio)
  716. {
  717. struct dp_audio_private *audio;
  718. if (!dp_audio)
  719. return;
  720. audio = container_of(dp_audio, struct dp_audio_private, dp_audio);
  721. mutex_destroy(&audio->ops_lock);
  722. dp_audio_destroy_notify_workqueue(audio);
  723. devm_kfree(&audio->pdev->dev, audio);
  724. }