sde_edid_parser.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
  4. * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
  5. */
  6. #define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__
  7. #include <drm/drm_edid.h>
  8. #include <linux/hdmi.h>
  9. #include "sde_kms.h"
  10. #include "sde_edid_parser.h"
  11. #include "sde/sde_connector.h"
  12. #define DBC_START_OFFSET 4
  13. #define EDID_DTD_LEN 18
  14. enum data_block_types {
  15. RESERVED,
  16. AUDIO_DATA_BLOCK,
  17. VIDEO_DATA_BLOCK,
  18. VENDOR_SPECIFIC_DATA_BLOCK,
  19. SPEAKER_ALLOCATION_DATA_BLOCK,
  20. VESA_DTC_DATA_BLOCK,
  21. RESERVED2,
  22. USE_EXTENDED_TAG
  23. };
  24. #if defined(CONFIG_SECDP)
  25. bool secdp_panel_hdr_supported(void);
  26. void secdp_logger_hex_dump(void *buf, void *pref, size_t size);
  27. #endif
  28. static u8 *sde_find_edid_extension(struct edid *edid, int ext_id)
  29. {
  30. u8 *edid_ext = NULL;
  31. int i;
  32. /* No EDID or EDID extensions */
  33. if (edid == NULL || edid->extensions == 0)
  34. return NULL;
  35. /* Find CEA extension */
  36. for (i = 0; i < edid->extensions; i++) {
  37. edid_ext = (u8 *)edid + EDID_LENGTH * (i + 1);
  38. if (edid_ext[0] == ext_id)
  39. break;
  40. }
  41. if (i == edid->extensions)
  42. return NULL;
  43. return edid_ext;
  44. }
  45. static u8 *sde_find_cea_extension(struct edid *edid)
  46. {
  47. return sde_find_edid_extension(edid, SDE_CEA_EXT);
  48. }
  49. static int
  50. sde_cea_db_payload_len(const u8 *db)
  51. {
  52. return db[0] & 0x1f;
  53. }
  54. static int
  55. sde_cea_db_tag(const u8 *db)
  56. {
  57. return db[0] >> 5;
  58. }
  59. static int
  60. sde_cea_revision(const u8 *cea)
  61. {
  62. return cea[1];
  63. }
  64. static int
  65. sde_cea_db_offsets(const u8 *cea, int *start, int *end)
  66. {
  67. /* Data block offset in CEA extension block */
  68. *start = 4;
  69. *end = cea[2];
  70. if (*end == 0)
  71. *end = 127;
  72. if (*end < 4 || *end > 127)
  73. return -ERANGE;
  74. return 0;
  75. }
  76. #define sde_for_each_cea_db(cea, i, start, end) \
  77. for ((i) = (start); \
  78. (i) < (end) && (i) + sde_cea_db_payload_len(&(cea)[(i)]) < (end); \
  79. (i) += sde_cea_db_payload_len(&(cea)[(i)]) + 1)
  80. static const u8 *_sde_edid_find_block(const u8 *in_buf, u32 start_offset,
  81. u8 type, u8 *len)
  82. {
  83. /* the start of data block collection, start of Video Data Block */
  84. u32 offset = start_offset;
  85. u32 dbc_offset = in_buf[2];
  86. SDE_EDID_DEBUG("%s +", __func__);
  87. /*
  88. * * edid buffer 1, byte 2 being 4 means no non-DTD/Data block
  89. * collection present.
  90. * * edid buffer 1, byte 2 being 0 means no non-DTD/DATA block
  91. * collection present and no DTD data present.
  92. */
  93. if ((dbc_offset == 0) || (dbc_offset == 4)) {
  94. SDE_EDID_DEBUG("EDID: no DTD or non-DTD data present\n");
  95. return NULL;
  96. }
  97. while (offset < dbc_offset) {
  98. u8 block_len = in_buf[offset] & 0x1F;
  99. if ((offset + block_len <= dbc_offset) &&
  100. (in_buf[offset] >> 5) == type) {
  101. *len = block_len;
  102. SDE_EDID_DEBUG("block=%d found @ 0x%x w/ len=%d\n",
  103. type, offset, block_len);
  104. return in_buf + offset;
  105. }
  106. offset += 1 + block_len;
  107. }
  108. return NULL;
  109. }
  110. static void sde_edid_extract_vendor_id(struct sde_edid_ctrl *edid_ctrl)
  111. {
  112. char *vendor_id;
  113. u32 id_codes;
  114. SDE_EDID_DEBUG("%s +", __func__);
  115. if (!edid_ctrl) {
  116. SDE_ERROR("%s: invalid input\n", __func__);
  117. return;
  118. }
  119. vendor_id = edid_ctrl->vendor_id;
  120. id_codes = ((u32)edid_ctrl->edid->mfg_id[0] << 8) +
  121. edid_ctrl->edid->mfg_id[1];
  122. vendor_id[0] = 'A' - 1 + ((id_codes >> 10) & 0x1F);
  123. vendor_id[1] = 'A' - 1 + ((id_codes >> 5) & 0x1F);
  124. vendor_id[2] = 'A' - 1 + (id_codes & 0x1F);
  125. vendor_id[3] = 0;
  126. SDE_EDID_DEBUG("vendor id is %s ", vendor_id);
  127. SDE_EDID_DEBUG("%s -", __func__);
  128. }
  129. #if defined(CONFIG_SECDP_SWITCH)
  130. static struct sde_edid_ctrl *g_edid_ctrl;
  131. int secdp_get_audio_ch(void)
  132. {
  133. if (g_edid_ctrl)
  134. return g_edid_ctrl->audio_channel_info;
  135. return 0;
  136. }
  137. EXPORT_SYMBOL(secdp_get_audio_ch);
  138. #endif
  139. #if defined(CONFIG_SECDP)
  140. static int secdp_copy_lpcm_audio_data_only(struct sde_edid_ctrl *edid_ctrl,
  141. u8 *lpcm_adb, const u8 *adb_no_header, int len)
  142. {
  143. u16 audio_ch = 0;
  144. u32 bit_rate = 0;
  145. int lpcm_size = 0;
  146. const int one_adb_size = 3;
  147. int adb_count;
  148. if (len <= 0)
  149. return 0;
  150. adb_count = len / one_adb_size;
  151. while(adb_count > 0) {
  152. if ((adb_no_header[0] >> 3) == 1) {
  153. /* to support legacy audio info */
  154. audio_ch |= (1 << (adb_no_header[0] & 0x7));
  155. if ((adb_no_header[0] & 0x7) > 0x04)
  156. audio_ch |= 0x20;
  157. bit_rate = adb_no_header[2] & 0x7;
  158. bit_rate |= (adb_no_header[1] & 0x7F) << 3;
  159. /* copy LPCM codec */
  160. memcpy(lpcm_adb + lpcm_size,
  161. adb_no_header, one_adb_size);
  162. lpcm_size += one_adb_size;
  163. }
  164. adb_no_header += one_adb_size;
  165. adb_count--;
  166. }
  167. edid_ctrl->audio_channel_info |= (bit_rate << 16);
  168. edid_ctrl->audio_channel_info |= audio_ch;
  169. return lpcm_size;
  170. }
  171. #endif
  172. static void _sde_edid_extract_audio_data_blocks(
  173. struct sde_edid_ctrl *edid_ctrl)
  174. {
  175. u8 len = 0;
  176. u8 adb_max = 0;
  177. const u8 *adb = NULL;
  178. u32 offset = DBC_START_OFFSET;
  179. u8 *cea = NULL;
  180. #if defined(CONFIG_SECDP)
  181. u8 *in_buf;
  182. int lpcm_size = 0;
  183. #endif
  184. if (!edid_ctrl) {
  185. SDE_ERROR("invalid edid_ctrl\n");
  186. return;
  187. }
  188. #if defined(CONFIG_SECDP)
  189. in_buf = (u8 *)edid_ctrl->edid;
  190. if (in_buf[3] & (1<<6)) {
  191. pr_info("default audio\n");
  192. edid_ctrl->audio_channel_info |= 2;
  193. }
  194. #endif
  195. SDE_EDID_DEBUG("%s +", __func__);
  196. cea = sde_find_cea_extension(edid_ctrl->edid);
  197. if (!cea) {
  198. SDE_DEBUG("CEA extension not found\n");
  199. return;
  200. }
  201. edid_ctrl->adb_size = 0;
  202. memset(edid_ctrl->audio_data_block, 0,
  203. sizeof(edid_ctrl->audio_data_block));
  204. do {
  205. len = 0;
  206. adb = _sde_edid_find_block(cea, offset, AUDIO_DATA_BLOCK,
  207. &len);
  208. if ((adb == NULL) || (len > MAX_AUDIO_DATA_BLOCK_SIZE ||
  209. adb_max >= MAX_NUMBER_ADB)) {
  210. if (!edid_ctrl->adb_size) {
  211. SDE_DEBUG("No/Invalid Audio Data Block\n");
  212. return;
  213. }
  214. continue;
  215. }
  216. #if !defined(CONFIG_SECDP)
  217. memcpy(edid_ctrl->audio_data_block + edid_ctrl->adb_size,
  218. adb + 1, len);
  219. #else
  220. lpcm_size += secdp_copy_lpcm_audio_data_only(edid_ctrl, edid_ctrl->audio_data_block + lpcm_size,
  221. adb + 1, len);
  222. #endif
  223. offset = (adb - cea) + 1 + len;
  224. edid_ctrl->adb_size += len;
  225. adb_max++;
  226. } while (adb);
  227. #if defined(CONFIG_SECDP)
  228. edid_ctrl->adb_size = lpcm_size;
  229. pr_info("DP Audio info: 0x%x\n", edid_ctrl->audio_channel_info);
  230. #endif
  231. SDE_EDID_DEBUG("%s -", __func__);
  232. }
  233. static void sde_edid_parse_hdr_plus_info(struct drm_connector *connector,
  234. const u8 *db)
  235. {
  236. struct sde_connector *c_conn;
  237. c_conn = to_sde_connector(connector);
  238. c_conn->hdr_plus_app_ver = db[5] & VSVDB_HDR10_PLUS_APP_VER_MASK;
  239. }
  240. static void sde_edid_parse_vsvdb_info(struct drm_connector *connector,
  241. const u8 *db)
  242. {
  243. u8 db_len = 0;
  244. u32 ieee_code = 0;
  245. SDE_EDID_DEBUG("%s +\n", __func__);
  246. db_len = sde_cea_db_payload_len(db);
  247. if (db_len < 5)
  248. return;
  249. /* Bytes 2-4: IEEE 24-bit code, LSB first */
  250. ieee_code = db[2] | (db[3] << 8) | (db[4] << 16);
  251. if (ieee_code == VSVDB_HDR10_PLUS_IEEE_CODE)
  252. sde_edid_parse_hdr_plus_info(connector, db);
  253. SDE_EDID_DEBUG("%s -\n", __func__);
  254. }
  255. static bool sde_edid_is_luminance_value_present(u32 block_length,
  256. enum luminance_value value)
  257. {
  258. return block_length > NO_LUMINANCE_DATA && value <= block_length;
  259. }
  260. /*
  261. * sde_edid_parse_hdr_db - Parse the HDR extended block
  262. * @connector: connector for the external sink
  263. * @db: start of the HDR extended block
  264. *
  265. * Parses the HDR extended block to extract sink info for @connector.
  266. */
  267. static void
  268. sde_edid_parse_hdr_db(struct drm_connector *connector, const u8 *db)
  269. {
  270. u8 len = 0;
  271. struct sde_connector *c_conn;
  272. c_conn = to_sde_connector(connector);
  273. if (!db)
  274. return;
  275. #if defined(CONFIG_SECDP)
  276. if (!secdp_panel_hdr_supported()) {
  277. SDE_EDID_DEBUG("connected dongle does not support HDR\n");
  278. return;
  279. }
  280. #endif
  281. len = db[0] & 0x1f;
  282. /* Byte 3: Electro-Optical Transfer Functions */
  283. c_conn->hdr_eotf = db[2] & 0x3F;
  284. /* Byte 4: Static Metadata Descriptor Type 1 */
  285. c_conn->hdr_metadata_type_one = (db[3] & BIT(0));
  286. /* Byte 5: Desired Content Maximum Luminance */
  287. if (sde_edid_is_luminance_value_present(len, MAXIMUM_LUMINANCE))
  288. c_conn->hdr_max_luminance = db[MAXIMUM_LUMINANCE];
  289. /* Byte 6: Desired Content Max Frame-average Luminance */
  290. if (sde_edid_is_luminance_value_present(len, FRAME_AVERAGE_LUMINANCE))
  291. c_conn->hdr_avg_luminance = db[FRAME_AVERAGE_LUMINANCE];
  292. /* Byte 7: Desired Content Min Luminance */
  293. if (sde_edid_is_luminance_value_present(len, MINIMUM_LUMINANCE))
  294. c_conn->hdr_min_luminance = db[MINIMUM_LUMINANCE];
  295. c_conn->hdr_supported = true;
  296. SDE_EDID_DEBUG("HDR electro-optical %d\n", c_conn->hdr_eotf);
  297. SDE_EDID_DEBUG("metadata desc 1 %d\n", c_conn->hdr_metadata_type_one);
  298. SDE_EDID_DEBUG("max luminance %d\n", c_conn->hdr_max_luminance);
  299. SDE_EDID_DEBUG("avg luminance %d\n", c_conn->hdr_avg_luminance);
  300. SDE_EDID_DEBUG("min luminance %d\n", c_conn->hdr_min_luminance);
  301. }
  302. /*
  303. * drm_extract_clrmetry_db - Parse the HDMI colorimetry extended block
  304. * @connector: connector corresponding to the HDMI sink
  305. * @db: start of the HDMI colorimetry extended block
  306. *
  307. * Parses the HDMI colorimetry block to extract sink info for @connector.
  308. */
  309. static void
  310. sde_parse_clrmetry_db(struct drm_connector *connector, const u8 *db)
  311. {
  312. struct sde_connector *c_conn;
  313. c_conn = to_sde_connector(connector);
  314. if (!db) {
  315. DRM_ERROR("invalid db\n");
  316. return;
  317. }
  318. /* Byte 3 Bit 0: xvYCC_601 */
  319. if (db[2] & BIT(0))
  320. c_conn->color_enc_fmt |= DRM_EDID_CLRMETRY_xvYCC_601;
  321. /* Byte 3 Bit 1: xvYCC_709 */
  322. if (db[2] & BIT(1))
  323. c_conn->color_enc_fmt |= DRM_EDID_CLRMETRY_xvYCC_709;
  324. /* Byte 3 Bit 2: sYCC_601 */
  325. if (db[2] & BIT(2))
  326. c_conn->color_enc_fmt |= DRM_EDID_CLRMETRY_sYCC_601;
  327. /* Byte 3 Bit 3: ADOBE_YCC_601 */
  328. if (db[2] & BIT(3))
  329. c_conn->color_enc_fmt |= DRM_EDID_CLRMETRY_ADOBE_YCC_601;
  330. /* Byte 3 Bit 4: ADOBE_RGB */
  331. if (db[2] & BIT(4))
  332. c_conn->color_enc_fmt |= DRM_EDID_CLRMETRY_ADOBE_RGB;
  333. /* Byte 3 Bit 5: BT2020_CYCC */
  334. if (db[2] & BIT(5))
  335. c_conn->color_enc_fmt |= DRM_EDID_CLRMETRY_BT2020_CYCC;
  336. /* Byte 3 Bit 6: BT2020_YCC */
  337. if (db[2] & BIT(6))
  338. c_conn->color_enc_fmt |= DRM_EDID_CLRMETRY_BT2020_YCC;
  339. /* Byte 3 Bit 7: BT2020_RGB */
  340. if (db[2] & BIT(7))
  341. c_conn->color_enc_fmt |= DRM_EDID_CLRMETRY_BT2020_RGB;
  342. /* Byte 4 Bit 7: DCI-P3 */
  343. if (db[3] & BIT(7))
  344. c_conn->color_enc_fmt |= DRM_EDID_CLRMETRY_DCI_P3;
  345. DRM_DEBUG_KMS("colorimetry fmts = 0x%x\n", c_conn->color_enc_fmt);
  346. }
  347. /*
  348. * sde_edid_parse_extended_blk_info - Parse the HDMI extended tag blocks
  349. * @connector: connector corresponding to external sink
  350. * @edid: handle to the EDID structure
  351. * Parses the all extended tag blocks extract sink info for @connector.
  352. */
  353. static void
  354. sde_edid_parse_extended_blk_info(struct drm_connector *connector,
  355. struct edid *edid)
  356. {
  357. const u8 *cea = sde_find_cea_extension(edid);
  358. const u8 *db = NULL;
  359. if (cea && sde_cea_revision(cea) >= 3) {
  360. int i, start, end;
  361. if (sde_cea_db_offsets(cea, &start, &end))
  362. return;
  363. sde_for_each_cea_db(cea, i, start, end) {
  364. db = &cea[i];
  365. if (sde_cea_db_tag(db) == USE_EXTENDED_TAG) {
  366. SDE_EDID_DEBUG("found ext tag block = %d\n",
  367. db[1]);
  368. switch (db[1]) {
  369. case VENDOR_SPECIFIC_VIDEO_DATA_BLOCK:
  370. sde_edid_parse_vsvdb_info(connector,
  371. db);
  372. break;
  373. case HDR_STATIC_METADATA_DATA_BLOCK:
  374. sde_edid_parse_hdr_db(connector, db);
  375. break;
  376. case COLORIMETRY_EXTENDED_DATA_BLOCK:
  377. sde_parse_clrmetry_db(connector, db);
  378. break;
  379. default:
  380. break;
  381. }
  382. }
  383. }
  384. }
  385. }
  386. static void _sde_edid_extract_speaker_allocation_data(
  387. struct sde_edid_ctrl *edid_ctrl)
  388. {
  389. u8 len;
  390. const u8 *sadb = NULL;
  391. u8 *cea = NULL;
  392. #if defined(CONFIG_SECDP)
  393. u16 speaker_allocation = 0;
  394. #endif
  395. if (!edid_ctrl) {
  396. SDE_ERROR("invalid edid_ctrl\n");
  397. return;
  398. }
  399. SDE_EDID_DEBUG("%s +", __func__);
  400. cea = sde_find_cea_extension(edid_ctrl->edid);
  401. if (!cea) {
  402. SDE_DEBUG("CEA extension not found\n");
  403. return;
  404. }
  405. sadb = _sde_edid_find_block(cea, DBC_START_OFFSET,
  406. SPEAKER_ALLOCATION_DATA_BLOCK, &len);
  407. if ((sadb == NULL) || (len != MAX_SPKR_ALLOC_DATA_BLOCK_SIZE)) {
  408. SDE_DEBUG("No/Invalid Speaker Allocation Data Block\n");
  409. return;
  410. }
  411. memcpy(edid_ctrl->spkr_alloc_data_block, sadb + 1, len);
  412. edid_ctrl->sadb_size = len;
  413. #if defined(CONFIG_SECDP)
  414. speaker_allocation |= (sadb[1] & 0x7F);
  415. #endif
  416. SDE_EDID_DEBUG("speaker alloc data SP byte = %08x %s%s%s%s%s%s%s\n",
  417. sadb[1],
  418. (sadb[1] & BIT(0)) ? "FL/FR," : "",
  419. (sadb[1] & BIT(1)) ? "LFE," : "",
  420. (sadb[1] & BIT(2)) ? "FC," : "",
  421. (sadb[1] & BIT(3)) ? "RL/RR," : "",
  422. (sadb[1] & BIT(4)) ? "RC," : "",
  423. (sadb[1] & BIT(5)) ? "FLC/FRC," : "",
  424. (sadb[1] & BIT(6)) ? "RLC/RRC," : "");
  425. SDE_EDID_DEBUG("%s -", __func__);
  426. #if defined(CONFIG_SECDP)
  427. edid_ctrl->audio_channel_info |= (speaker_allocation << 8);
  428. #endif
  429. }
  430. struct sde_edid_ctrl *sde_edid_init(void)
  431. {
  432. struct sde_edid_ctrl *edid_ctrl = NULL;
  433. SDE_EDID_DEBUG("%s +\n", __func__);
  434. edid_ctrl = kzalloc(sizeof(*edid_ctrl), GFP_KERNEL);
  435. if (!edid_ctrl) {
  436. SDE_ERROR("edid_ctrl alloc failed\n");
  437. return NULL;
  438. }
  439. memset((edid_ctrl), 0, sizeof(*edid_ctrl));
  440. SDE_EDID_DEBUG("%s -\n", __func__);
  441. return edid_ctrl;
  442. }
  443. void sde_free_edid(void **input)
  444. {
  445. struct sde_edid_ctrl *edid_ctrl = (struct sde_edid_ctrl *)(*input);
  446. SDE_EDID_DEBUG("%s +", __func__);
  447. kfree(edid_ctrl->edid);
  448. edid_ctrl->edid = NULL;
  449. }
  450. void sde_edid_deinit(void **input)
  451. {
  452. struct sde_edid_ctrl *edid_ctrl = (struct sde_edid_ctrl *)(*input);
  453. SDE_EDID_DEBUG("%s +", __func__);
  454. sde_free_edid((void *)&edid_ctrl);
  455. kfree(edid_ctrl);
  456. SDE_EDID_DEBUG("%s -", __func__);
  457. }
  458. int _sde_edid_update_modes(struct drm_connector *connector,
  459. void *input)
  460. {
  461. int rc = 0;
  462. struct sde_edid_ctrl *edid_ctrl = (struct sde_edid_ctrl *)(input);
  463. SDE_EDID_DEBUG("%s +", __func__);
  464. if (edid_ctrl->edid) {
  465. drm_connector_update_edid_property(connector,
  466. edid_ctrl->edid);
  467. rc = drm_add_edid_modes(connector, edid_ctrl->edid);
  468. sde_edid_parse_extended_blk_info(connector,
  469. edid_ctrl->edid);
  470. SDE_EDID_DEBUG("%s -", __func__);
  471. return rc;
  472. }
  473. drm_connector_update_edid_property(connector, NULL);
  474. SDE_EDID_DEBUG("%s null edid -", __func__);
  475. return rc;
  476. }
  477. u8 sde_get_edid_checksum(void *input)
  478. {
  479. struct sde_edid_ctrl *edid_ctrl = (struct sde_edid_ctrl *)(input);
  480. struct edid *edid = NULL, *last_block = NULL;
  481. u8 *raw_edid = NULL;
  482. if (!edid_ctrl || !edid_ctrl->edid) {
  483. SDE_ERROR("invalid edid input\n");
  484. return 0;
  485. }
  486. edid = edid_ctrl->edid;
  487. raw_edid = (u8 *)edid;
  488. #if !defined(CONFIG_SECDP)
  489. raw_edid += (edid->extensions * EDID_LENGTH);
  490. #else
  491. /* fix Prevent_CXX Major defect.
  492. * Dangerous cast: Pointer "raw_edid"( 8 ) to int( 4 ).
  493. */
  494. raw_edid = raw_edid + (edid->extensions * EDID_LENGTH);
  495. #endif
  496. last_block = (struct edid *)raw_edid;
  497. if (last_block)
  498. return last_block->checksum;
  499. SDE_ERROR("Invalid block, no checksum\n");
  500. return 0;
  501. }
  502. bool sde_detect_hdmi_monitor(void *input)
  503. {
  504. struct sde_edid_ctrl *edid_ctrl = (struct sde_edid_ctrl *)(input);
  505. return drm_detect_hdmi_monitor(edid_ctrl->edid);
  506. }
  507. void sde_parse_edid(void *input)
  508. {
  509. struct sde_edid_ctrl *edid_ctrl;
  510. if (!input) {
  511. SDE_ERROR("Invalid input\n");
  512. return;
  513. }
  514. edid_ctrl = (struct sde_edid_ctrl *)(input);
  515. if (edid_ctrl->edid) {
  516. #if defined(CONFIG_SECDP)
  517. edid_ctrl->audio_channel_info = 1 << 26;
  518. #endif
  519. sde_edid_extract_vendor_id(edid_ctrl);
  520. _sde_edid_extract_audio_data_blocks(edid_ctrl);
  521. _sde_edid_extract_speaker_allocation_data(edid_ctrl);
  522. } else {
  523. SDE_ERROR("edid not present\n");
  524. }
  525. }
  526. void sde_get_edid(struct drm_connector *connector,
  527. struct i2c_adapter *adapter, void **input)
  528. {
  529. struct sde_edid_ctrl *edid_ctrl = (struct sde_edid_ctrl *)(*input);
  530. edid_ctrl->edid = drm_get_edid(connector, adapter);
  531. #if defined(CONFIG_SECDP)
  532. if (edid_ctrl->edid) {
  533. u8 i, num_extension;
  534. num_extension = edid_ctrl->edid->extensions;
  535. for (i = 0; i <= num_extension; i++) {
  536. print_hex_dump(KERN_DEBUG, "EDID: ",
  537. DUMP_PREFIX_NONE, 16, 1, edid_ctrl->edid + i,
  538. EDID_LENGTH, false);
  539. secdp_logger_hex_dump(edid_ctrl->edid + i,
  540. "EDID:", EDID_LENGTH);
  541. }
  542. }
  543. #if defined(CONFIG_SECDP_SWITCH)
  544. g_edid_ctrl = edid_ctrl;
  545. #endif
  546. #endif/*CONFIG_SECDP*/
  547. SDE_EDID_DEBUG("%s +\n", __func__);
  548. if (!edid_ctrl->edid)
  549. SDE_ERROR("EDID read failed\n");
  550. if (edid_ctrl->edid)
  551. sde_parse_edid(edid_ctrl);
  552. SDE_EDID_DEBUG("%s -\n", __func__);
  553. };