Commit 8fe9790d authored by Zhenyu Wang's avatar Zhenyu Wang Committed by Chris Wilson

drm/edid: add helper function to detect monitor audio capability

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: default avatarWu Fengguang <fengguang.wu@intel.com>
Signed-off-by: default avatarZhenyu Wang <zhenyuw@linux.intel.com>
Reviewed-by: default avatarAdam Jackson <ajax@redhat.com>
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
parent 6d139a87
...@@ -1267,34 +1267,51 @@ add_detailed_modes(struct drm_connector *connector, struct edid *edid, ...@@ -1267,34 +1267,51 @@ add_detailed_modes(struct drm_connector *connector, struct edid *edid,
} }
#define HDMI_IDENTIFIER 0x000C03 #define HDMI_IDENTIFIER 0x000C03
#define AUDIO_BLOCK 0x01
#define VENDOR_BLOCK 0x03 #define VENDOR_BLOCK 0x03
#define EDID_BASIC_AUDIO (1 << 6)
/** /**
* drm_detect_hdmi_monitor - detect whether monitor is hdmi. * Search EDID for CEA extension block.
* @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) static u8 *drm_find_cea_extension(struct edid *edid)
{ {
char *edid_ext = NULL; u8 *edid_ext = NULL;
int i, hdmi_id; int i;
int start_offset, end_offset;
bool is_hdmi = false;
/* No EDID or EDID extensions */ /* No EDID or EDID extensions */
if (edid == NULL || edid->extensions == 0) if (edid == NULL || edid->extensions == 0)
goto end; return NULL;
/* Find CEA extension */ /* Find CEA extension */
for (i = 0; i < edid->extensions; i++) { for (i = 0; i < edid->extensions; i++) {
edid_ext = (char *)edid + EDID_LENGTH * (i + 1); edid_ext = (u8 *)edid + EDID_LENGTH * (i + 1);
/* This block is CEA extension */ if (edid_ext[0] == CEA_EXT)
if (edid_ext[0] == 0x02)
break; break;
} }
if (i == edid->extensions) 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; goto end;
/* Data block offset in CEA extension block */ /* Data block offset in CEA extension block */
...@@ -1324,6 +1341,53 @@ bool drm_detect_hdmi_monitor(struct edid *edid) ...@@ -1324,6 +1341,53 @@ bool drm_detect_hdmi_monitor(struct edid *edid)
} }
EXPORT_SYMBOL(drm_detect_hdmi_monitor); 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 * drm_add_edid_modes - add modes from EDID data, if available
* @connector: connector we're probing * @connector: connector we're probing
......
...@@ -763,6 +763,7 @@ extern int drm_mode_gamma_get_ioctl(struct drm_device *dev, ...@@ -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, extern int drm_mode_gamma_set_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv); void *data, struct drm_file *file_priv);
extern bool drm_detect_hdmi_monitor(struct edid *edid); 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, extern int drm_mode_page_flip_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv); void *data, struct drm_file *file_priv);
extern struct drm_display_mode *drm_cvt_mode(struct drm_device *dev, extern struct drm_display_mode *drm_cvt_mode(struct drm_device *dev,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment