Skip to content

Commit 7c01878

Browse files
vsyrjaladanvet
authored andcommitted
drm/edid: Extract SADs properly from multiple audio data blocks
SADs may span multiple CEA audio data blocks in the EDID. CEA-861-E says: "The order of the Data Blocks is not constrained. It is also possible to have more than one of a specific type of data block if necessary to include all of the descriptors needed to describe the sink’s capabilities." Each audio data block can carry up to 10 SADs, whereas the ELD SAD limit is 15 according to HDA 1.0a spec. So we should support at least two data blocks. And apparently some devices take a more liberal interpretation and stuff only one SAD per data block even when they would fit into one. So let's try to extract all the SADs we can fit into the ELD even when they span multiple data blocks. While at it, toss in a comment to explain the 13 byte monitor name string limit which confused me at first. Cc: Arturo Pérez <artur999555@gmail.com> Tested-by: Arturo Pérez <artur999555@gmail.com> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=94197 Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Jani Nikula <jani.nikula@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: http://patchwork.freedesktop.org/patch/msgid/1457554066-8739-1-git-send-email-ville.syrjala@linux.intel.com
1 parent 562c5b4 commit 7c01878

File tree

1 file changed

+11
-6
lines changed

1 file changed

+11
-6
lines changed

drivers/gpu/drm/drm_edid.c

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3308,7 +3308,7 @@ void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid)
33083308
u8 *cea;
33093309
u8 *name;
33103310
u8 *db;
3311-
int sad_count = 0;
3311+
int total_sad_count = 0;
33123312
int mnl;
33133313
int dbl;
33143314

@@ -3322,6 +3322,7 @@ void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid)
33223322

33233323
name = NULL;
33243324
drm_for_each_detailed_block((u8 *)edid, monitor_name, &name);
3325+
/* max: 13 bytes EDID, 16 bytes ELD */
33253326
for (mnl = 0; name && mnl < 13; mnl++) {
33263327
if (name[mnl] == 0x0a)
33273328
break;
@@ -3350,11 +3351,15 @@ void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid)
33503351
dbl = cea_db_payload_len(db);
33513352

33523353
switch (cea_db_tag(db)) {
3354+
int sad_count;
3355+
33533356
case AUDIO_BLOCK:
33543357
/* Audio Data Block, contains SADs */
3355-
sad_count = dbl / 3;
3356-
if (dbl >= 1)
3357-
memcpy(eld + 20 + mnl, &db[1], dbl);
3358+
sad_count = min(dbl / 3, 15 - total_sad_count);
3359+
if (sad_count >= 1)
3360+
memcpy(eld + 20 + mnl + total_sad_count * 3,
3361+
&db[1], sad_count * 3);
3362+
total_sad_count += sad_count;
33583363
break;
33593364
case SPEAKER_BLOCK:
33603365
/* Speaker Allocation Data Block */
@@ -3371,13 +3376,13 @@ void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid)
33713376
}
33723377
}
33733378
}
3374-
eld[5] |= sad_count << 4;
3379+
eld[5] |= total_sad_count << 4;
33753380

33763381
eld[DRM_ELD_BASELINE_ELD_LEN] =
33773382
DIV_ROUND_UP(drm_eld_calc_baseline_block_size(eld), 4);
33783383

33793384
DRM_DEBUG_KMS("ELD size %d, SAD count %d\n",
3380-
drm_eld_size(eld), sad_count);
3385+
drm_eld_size(eld), total_sad_count);
33813386
}
33823387
EXPORT_SYMBOL(drm_edid_to_eld);
33833388

0 commit comments

Comments
 (0)