On Wed, Aug 14, 2013 at 12:08:13PM -0400, Alex Deucher wrote: > This adds a helper function to extract the speaker allocation > data block from the EDID. This data block describes what speakers > are present on the display device. > > v2: update per Ville Syrjälä's comments > > Signed-off-by: Alex Deucher <alexander.deucher@xxxxxxx> > --- > drivers/gpu/drm/drm_edid.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++ > include/drm/drm_edid.h | 1 + > 2 files changed, 53 insertions(+) > > diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c > index 70fc133..2e36d28 100644 > --- a/drivers/gpu/drm/drm_edid.c > +++ b/drivers/gpu/drm/drm_edid.c > @@ -2735,6 +2735,58 @@ int drm_edid_to_sad(struct edid *edid, struct cea_sad **sads) > EXPORT_SYMBOL(drm_edid_to_sad); > > /** > + * drm_edid_to_speaker_allocation - extracts Speaker Allocation Data Blocks from EDID > + * @edid: EDID to parse > + * @sadb: pointer to the speaker block > + * > + * Looks for CEA EDID block and extracts the Speaker Allocation Data Block from it. > + * Note: returned pointer needs to be kfreed > + * > + * Return number of found Speaker Allocation Blocks or negative number on error. > + */ > +int drm_edid_to_speaker_allocation(struct edid *edid, u8 **sadb) > +{ > + int count = 0; > + int i, start, end, dbl; > + const u8 *cea; > + > + cea = drm_find_cea_extension(edid); > + if (!cea) { > + DRM_DEBUG_KMS("SAD: no CEA Extension found\n"); > + return -ENOENT; > + } > + > + if (cea_revision(cea) < 3) { > + DRM_DEBUG_KMS("SAD: wrong CEA revision\n"); > + return -ENOTSUPP; > + } > + > + if (cea_db_offsets(cea, &start, &end)) { > + DRM_DEBUG_KMS("SAD: invalid data block offsets\n"); > + return -EPROTO; > + } > + > + for_each_cea_db(cea, i, start, end) { > + const u8 *db = &cea[i]; > + > + if (cea_db_tag(db) == SPEAKER_BLOCK) { > + dbl = cea_db_payload_len(db); > + > + /* Speaker Allocation Data Block */ > + if (dbl == 3) { > + *sadb = kcalloc(count, dbl, GFP_KERNEL); 'count' not initialized yet. I suppose it was supposed to be just kmalloc(dbl, GFP_KERNEL). But since it's just three bytes, making the user just pass in a pointer to u32 would work just as well w/o requiring the dynamic alloc/free. > + memcpy(*sadb, &db[1], dbl); > + count = dbl; > + break; > + } > + } > + } > + > + return count; > +} > +EXPORT_SYMBOL(drm_edid_to_speaker_allocation); > + > +/** > * drm_av_sync_delay - HDMI/DP sink audio-video sync delay in millisecond > * @connector: connector associated with the HDMI/DP sink > * @mode: the display mode > diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h > index fc481fc..c76a129 100644 > --- a/include/drm/drm_edid.h > +++ b/include/drm/drm_edid.h > @@ -259,6 +259,7 @@ struct hdmi_avi_infoframe; > > void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid); > int drm_edid_to_sad(struct edid *edid, struct cea_sad **sads); > +int drm_edid_to_speaker_allocation(struct edid *edid, u8 **sadb); > int drm_av_sync_delay(struct drm_connector *connector, > struct drm_display_mode *mode); > struct drm_connector *drm_select_eld(struct drm_encoder *encoder, > -- > 1.8.3.1 > > _______________________________________________ > dri-devel mailing list > dri-devel@xxxxxxxxxxxxxxxxxxxxx > http://lists.freedesktop.org/mailman/listinfo/dri-devel -- Ville Syrjälä Intel OTC _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel