dp_audio.c 21 KB

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