Skip to content

Commit

Permalink
drm/edid: add helper function to detect monitor audio capability
Browse files Browse the repository at this point in the history
To help to determine if digital display port needs to enable
audio output or not. This one adds a helper to get monitor's
audio capability via EDID CEA extension block.

Tested-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
Reviewed-by: Adam Jackson <ajax@redhat.com>
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
  • Loading branch information
Zhenyu Wang authored and Chris Wilson committed Oct 19, 2010
1 parent 6d139a8 commit 8fe9790
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 14 deletions.
92 changes: 78 additions & 14 deletions drivers/gpu/drm/drm_edid.c
Original file line number Diff line number Diff line change
Expand Up @@ -1267,34 +1267,51 @@ add_detailed_modes(struct drm_connector *connector, struct edid *edid,
}

#define HDMI_IDENTIFIER 0x000C03
#define AUDIO_BLOCK 0x01
#define VENDOR_BLOCK 0x03
#define EDID_BASIC_AUDIO (1 << 6)

/**
* drm_detect_hdmi_monitor - detect whether monitor is hdmi.
* @edid: monitor EDID information
*
* Parse the CEA extension according to CEA-861-B.
* Return true if HDMI, false if not or unknown.
* Search EDID for CEA extension block.
*/
bool drm_detect_hdmi_monitor(struct edid *edid)
static u8 *drm_find_cea_extension(struct edid *edid)
{
char *edid_ext = NULL;
int i, hdmi_id;
int start_offset, end_offset;
bool is_hdmi = false;
u8 *edid_ext = NULL;
int i;

/* No EDID or EDID extensions */
if (edid == NULL || edid->extensions == 0)
goto end;
return NULL;

/* Find CEA extension */
for (i = 0; i < edid->extensions; i++) {
edid_ext = (char *)edid + EDID_LENGTH * (i + 1);
/* This block is CEA extension */
if (edid_ext[0] == 0x02)
edid_ext = (u8 *)edid + EDID_LENGTH * (i + 1);
if (edid_ext[0] == CEA_EXT)
break;
}

if (i == edid->extensions)
return NULL;

return edid_ext;
}

/**
* drm_detect_hdmi_monitor - detect whether monitor is hdmi.
* @edid: monitor EDID information
*
* Parse the CEA extension according to CEA-861-B.
* Return true if HDMI, false if not or unknown.
*/
bool drm_detect_hdmi_monitor(struct edid *edid)
{
u8 *edid_ext;
int i, hdmi_id;
int start_offset, end_offset;
bool is_hdmi = false;

edid_ext = drm_find_cea_extension(edid);
if (!edid_ext)
goto end;

/* Data block offset in CEA extension block */
Expand Down Expand Up @@ -1324,6 +1341,53 @@ bool drm_detect_hdmi_monitor(struct edid *edid)
}
EXPORT_SYMBOL(drm_detect_hdmi_monitor);

/**
* drm_detect_monitor_audio - check monitor audio capability
*
* Monitor should have CEA extension block.
* If monitor has 'basic audio', but no CEA audio blocks, it's 'basic
* audio' only. If there is any audio extension block and supported
* audio format, assume at least 'basic audio' support, even if 'basic
* audio' is not defined in EDID.
*
*/
bool drm_detect_monitor_audio(struct edid *edid)
{
u8 *edid_ext;
int i, j;
bool has_audio = false;
int start_offset, end_offset;

edid_ext = drm_find_cea_extension(edid);
if (!edid_ext)
goto end;

has_audio = ((edid_ext[3] & EDID_BASIC_AUDIO) != 0);

if (has_audio) {
DRM_DEBUG_KMS("Monitor has basic audio support\n");
goto end;
}

/* Data block offset in CEA extension block */
start_offset = 4;
end_offset = edid_ext[2];

for (i = start_offset; i < end_offset;
i += ((edid_ext[i] & 0x1f) + 1)) {
if ((edid_ext[i] >> 5) == AUDIO_BLOCK) {
has_audio = true;
for (j = 1; j < (edid_ext[i] & 0x1f); j += 3)
DRM_DEBUG_KMS("CEA audio format %d\n",
(edid_ext[i + j] >> 3) & 0xf);
goto end;
}
}
end:
return has_audio;
}
EXPORT_SYMBOL(drm_detect_monitor_audio);

/**
* drm_add_edid_modes - add modes from EDID data, if available
* @connector: connector we're probing
Expand Down
1 change: 1 addition & 0 deletions include/drm/drm_crtc.h
Original file line number Diff line number Diff line change
Expand Up @@ -763,6 +763,7 @@ extern int drm_mode_gamma_get_ioctl(struct drm_device *dev,
extern int drm_mode_gamma_set_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv);
extern bool drm_detect_hdmi_monitor(struct edid *edid);
extern bool drm_detect_monitor_audio(struct edid *edid);
extern int drm_mode_page_flip_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv);
extern struct drm_display_mode *drm_cvt_mode(struct drm_device *dev,
Expand Down

0 comments on commit 8fe9790

Please sign in to comment.