Enable HDMI audio routing and signaling to user-space and HDMI audio driver.
authorArun Kannan <arun.kannan@intel.com>
Tue, 14 Feb 2012 22:06:52 +0000 (14:06 -0800)
committerMarkus Lehtonen <markus.lehtonen@linux.intel.com>
Tue, 3 Jul 2012 09:30:13 +0000 (12:30 +0300)
We use the Android switch class driver to signal an HDMI state change to frameworks.
It is also important to notify the state change to HDMI audio driver.

Signed-off-by: Arun Kannan <arun.kannan@intel.com>
Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
drivers/gpu/drm/drm_crtc_helper.c
drivers/staging/mrst/drv/psb_intel_hdmi.c
drivers/staging/mrst/drv/psb_intel_hdmi.h

index 1844849..4d4c11b 100644 (file)
@@ -972,6 +972,7 @@ static void output_poll_execute(struct work_struct *work)
        struct drm_connector *connector;
        enum drm_connector_status old_status;
        bool repoll = false, changed = false;
+       struct drm_property property;
 
        if (!drm_kms_helper_poll)
                return;
@@ -1013,6 +1014,18 @@ static void output_poll_execute(struct work_struct *work)
                        dev->mode_config.funcs->output_poll_changed(dev);
        }
 
+       list_for_each_entry(connector,
+                           &dev->mode_config.connector_list,
+                           head) {
+               if (connector->funcs->set_property) {
+                       strncpy(property.name, "hdmi-send-uevent",
+                               sizeof("hdmi-send-uevent"));
+                       connector->funcs->set_property(connector,
+                                                      &property,
+                                                      connector->status);
+               }
+       }
+
        if (repoll)
                queue_delayed_work(system_nrt_wq, delayed_work, DRM_OUTPUT_POLL_PERIOD);
 }
index 02912ca..d782b34 100644 (file)
@@ -755,7 +755,12 @@ static int mdfld_hdmi_set_property(struct drm_connector *connector,
                                       struct drm_property *property,
                                       uint64_t value)
 {
+       struct drm_device *dev = connector->dev;
+       struct drm_psb_private *dev_priv = dev->dev_private;
        struct drm_encoder *pEncoder = connector->encoder;
+       struct android_hdmi_priv *hdmi_priv = NULL;
+       static int prev_state;
+       int state = 0, audio_notify = 0;
 
        PSB_DEBUG_ENTRY("connector info, type = %d, type_id=%d, base=0x%p, base.id=0x%x. \n", connector->connector_type, connector->connector_type_id, &connector->base, connector->base.id);
        PSB_DEBUG_ENTRY("encoder info, base.id=%d, encoder_type=%d, dev=0x%p, base=0x%p, possible_clones=0x%x. \n", pEncoder->base.id, pEncoder->encoder_type, pEncoder->dev, &pEncoder->base, pEncoder->possible_clones);
@@ -769,6 +774,41 @@ static int mdfld_hdmi_set_property(struct drm_connector *connector,
                PSB_DEBUG_ENTRY("DPMS \n");
        }
 
+       if (!strcmp(property->name, "hdmi-send-uevent")) {
+               hdmi_priv = to_psb_intel_output(connector)->dev_priv;
+               if (hdmi_priv != NULL) {
+                       /* user space expects:
+                        * '0' for disconnected, '1' for connected.
+                        * whereas: connector_status_connected is '1' and
+                        * connector_status_disconnected is '2'.
+                        * so, make proper conversion.
+                        */
+                       state = (value == connector_status_connected) ? 1 : 0;
+
+                       /* TODO: Use get/set attribute to get monitor_type */
+                       if (hdmi_priv->monitor_type == MONITOR_TYPE_HDMI) {
+                               /*
+                                * Notify the audio driver only if there is
+                                * a change in state.
+                                */
+                               audio_notify = state ? HAD_EVENT_HOT_PLUG :
+                                       HAD_EVENT_HOT_UNPLUG;
+
+                               if (state != prev_state &&
+                                   dev_priv->mdfld_had_event_callbacks) {
+                                       (*dev_priv->mdfld_had_event_callbacks)
+                                               (audio_notify,
+                                                dev_priv->had_pvt_data);
+                               }
+
+                               switch_set_state(&g_switch_hdmi_dev, state);
+                       } else
+                               switch_set_state(&g_switch_dvi_dev, state);
+
+                       prev_state = state;
+               }
+       }
+
        if (!strcmp(property->name, "scaling mode") && pEncoder) {
                struct psb_intel_crtc *pPsbCrtc = to_psb_intel_crtc(pEncoder->crtc);
                bool bTransitionFromToCentered;
index 0cd2946..bc97fe2 100644 (file)
@@ -105,6 +105,13 @@ typedef enum
 #define HDMI_CEA_EXTENSION_BLOCK_BYTE_3            3
 #define HDMI_FL_AND_FR_SPEAKERS_CONNECTED        0x1
 
+/*
+* HDMI Monitor Type
+* TODO: Use get/set attribute to get these values
+*/
+#define MONITOR_TYPE_HDMI 0x01
+#define MONITOR_TYPE_DVI  0x02
+
 //
 // HDMI buffer/information types
 //