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 --- drivers/gpu/drm/drm_edid.c | 85 ++++++++++++++++++++++++++++++++++++++----- include/drm/drm_crtc.h | 1 + 2 files changed, 76 insertions(+), 10 deletions(-)
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 96e9631..e34e0d1 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -1268,24 +1268,21 @@ 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 char *drm_find_cea_extension(struct edid *edid) { char *edid_ext = NULL; - int i, hdmi_id; - int start_offset, end_offset; - bool is_hdmi = false; + 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++) { @@ -1296,6 +1293,27 @@ bool drm_detect_hdmi_monitor(struct edid *edid) }
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) +{ + char *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 */ @@ -1326,6 +1344,53 @@ end: 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) +{ + char *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 * @edid: edid data diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index c9f3cc5..284ca90 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -754,6 +754,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,
This will turn on DP audio output by checking monitor's audio capability.
Signed-off-by: Zhenyu Wang zhenyuw@linux.intel.com --- drivers/gpu/drm/i915/intel_dp.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 208a4ec..4a14727 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1485,6 +1485,7 @@ static int intel_dp_get_modes(struct drm_connector *connector) struct intel_dp *intel_dp = intel_attached_dp(connector); struct drm_device *dev = intel_dp->base.base.dev; struct drm_i915_private *dev_priv = dev->dev_private; + struct edid *edid; int ret;
/* We should parse the EDID data and find out if it has an audio sink @@ -1505,6 +1506,9 @@ static int intel_dp_get_modes(struct drm_connector *connector) } }
+ edid = (struct edid *)connector->display_info.raw_edid; + intel_dp->has_audio = drm_detect_monitor_audio(edid); + return ret; }
On 2010.09.16 14:31:31 +0800, Zhenyu Wang wrote:
This will turn on DP audio output by checking monitor's audio capability.
oops, please ignore this one. Check EDID data after it's already freed...
Signed-off-by: Zhenyu Wang zhenyuw@linux.intel.com
drivers/gpu/drm/i915/intel_dp.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 208a4ec..4a14727 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1485,6 +1485,7 @@ static int intel_dp_get_modes(struct drm_connector *connector) struct intel_dp *intel_dp = intel_attached_dp(connector); struct drm_device *dev = intel_dp->base.base.dev; struct drm_i915_private *dev_priv = dev->dev_private;
struct edid *edid; int ret;
/* We should parse the EDID data and find out if it has an audio sink
@@ -1505,6 +1506,9 @@ static int intel_dp_get_modes(struct drm_connector *connector) } }
edid = (struct edid *)connector->display_info.raw_edid;
intel_dp->has_audio = drm_detect_monitor_audio(edid);
- return ret; }
-- 1.7.1
dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
Rely on monitor's audio capability to turn on audio output for HDMI.
Tested-by: Wu Fengguang fengguang.wu@intel.com Signed-off-by: Zhenyu Wang zhenyuw@linux.intel.com --- drivers/gpu/drm/i915/intel_hdmi.c | 12 ++++++++---- 1 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 783924c..90184e6 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -41,6 +41,7 @@ struct intel_hdmi { struct intel_encoder base; u32 sdvox_reg; bool has_hdmi_sink; + bool has_audio; };
static struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder) @@ -71,11 +72,12 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder, if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) sdvox |= SDVO_HSYNC_ACTIVE_HIGH;
- if (intel_hdmi->has_hdmi_sink) { + /* Required on CPT */ + if (intel_hdmi->has_hdmi_sink && HAS_PCH_CPT(dev)) + sdvox |= HDMI_MODE_SELECT; + + if (intel_hdmi->has_audio) sdvox |= SDVO_AUDIO_ENABLE; - if (HAS_PCH_CPT(dev)) - sdvox |= HDMI_MODE_SELECT; - }
if (intel_crtc->pipe == 1) { if (HAS_PCH_CPT(dev)) @@ -152,12 +154,14 @@ intel_hdmi_detect(struct drm_connector *connector) enum drm_connector_status status = connector_status_disconnected;
intel_hdmi->has_hdmi_sink = false; + intel_hdmi->has_audio = false; edid = drm_get_edid(connector, intel_hdmi->base.ddc_bus);
if (edid) { if (edid->input & DRM_EDID_INPUT_DIGITAL) { status = connector_status_connected; intel_hdmi->has_hdmi_sink = drm_detect_hdmi_monitor(edid); + intel_hdmi->has_audio = drm_detect_monitor_audio(edid); } connector->display_info.raw_edid = NULL; kfree(edid);
On Thu, 2010-09-16 at 14:31 +0800, Zhenyu Wang wrote:
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
- ajax
dri-devel@lists.freedesktop.org