HAD_GET_AUDIO_STATUS,
HAD_SET_ENABLE_AUDIO,
HAD_SET_DISABLE_AUDIO,
- HAD_SET_ENABLE_AUDIO_INT,
- HAD_SET_DISABLE_AUDIO_INT,
+ HAD_SET_ENABLE_AUDIO_INT,
+ HAD_SET_DISABLE_AUDIO_INT,
OTHERS_TBD,
};
HAD_EVENT_PM_CHANGING,
HAD_EVENT_AUDIO_BUFFER_DONE,
HAD_EVENT_AUDIO_BUFFER_UNDERRUN,
+ HAD_EVENT_QUERY_IS_AUDIO_BUSY,
+ HAD_EVENT_QUERY_IS_AUDIO_SUSPENDED,
};
/**
int (*hdmi_audio_set_caps)(enum had_caps_list set_element , void *capabilties);
};
-typedef struct pm_event {
- int event;
-} pm_event_t;
-struct snd_intel_had_interface {
- const char *name;
- int (*suspend) (void *had_data, pm_event_t event);
- int (*resume) (void *had_data);
+typedef struct hdmi_audio_event {
+ int type;
+} hdmi_audio_event_t;
+struct snd_intel_had_interface {
+ const char *name;
+ int (*query) (void *had_data, hdmi_audio_event_t event);
+ int (*suspend) (void *had_data, hdmi_audio_event_t event);
+ int (*resume) (void *had_data);
};
extern int intel_hdmi_audio_query_capabilities (had_event_call_back audio_callbacks, struct hdmi_audio_registers_ops *reg_ops,struct hdmi_audio_query_set_ops *query_ops);
#define DRM_PSB_DISP_PLANEB_DISABLE 4
#define DRM_PSB_DISP_PLANEB_ENABLE 5
#define DRM_PSB_HDMI_OSPM_ISLAND_DOWN 6
+#define DRM_PSB_HDMI_NOTIFY_HOTPLUG_TO_AUDIO 7
/*csc gamma setting*/
typedef enum {
DISP_PLANEB_STATUS = ~DISPLAY_PLANE_ENABLE;
release_ospm_lock();
}
+ } else if (dp_ctrl->cmd == DRM_PSB_HDMI_NOTIFY_HOTPLUG_TO_AUDIO) {
+ if (dp_ctrl->u.data == 0) {
+ /* notify audio with HDMI unplug event */
+ if (dev_priv->mdfld_had_event_callbacks
+ && !dev_priv->bDVIport) {
+ DRM_INFO("HDMI plug out to audio driver\n");
+ (*dev_priv->mdfld_had_event_callbacks)
+ (HAD_EVENT_HOT_UNPLUG, dev_priv->had_pvt_data);
+ }
+ } else {
+ /* notify audio with HDMI plug event */
+ if (dev_priv->mdfld_had_event_callbacks
+ && !dev_priv->bDVIport) {
+ DRM_INFO("HDMI plug in to audio driver\n");
+ (*dev_priv->mdfld_had_event_callbacks)
+ (HAD_EVENT_HOT_PLUG, dev_priv->had_pvt_data);
+ }
+ }
}
+
exit:
return ret;
}
struct drm_device * dev = connector->dev;
struct drm_psb_private * dev_priv = dev->dev_private;
int hdmi_audio_busy = 0;
- pm_event_t hdmi_audio_event;
+ hdmi_audio_event_t hdmi_audio_event;
u32 dspcntr_val;
#ifdef CONFIG_PM_RUNTIME
bool panel_on, panel_on2;
/*first, execute dpms*/
/* using suspend to judge whether hdmi audio is playing */
- hdmi_audio_event.event = 0;
+ hdmi_audio_event.type = 0;
if (dev_priv->had_interface && dev_priv->had_pvt_data)
hdmi_audio_busy =
dev_priv->had_interface->suspend(dev_priv->had_pvt_data,
defined(CONFIG_SND_INTELMID_HDMI_AUDIO_MODULE))
struct drm_psb_private *dev_priv = gpDrmDevice->dev_private;
struct snd_intel_had_interface *had_interface = dev_priv->had_interface;
- pm_event_t hdmi_audio_event;
+ hdmi_audio_event_t hdmi_audio_event;
if (dev_priv->had_pvt_data && hdmi_state) {
- hdmi_audio_event.event = 0;
+ hdmi_audio_event.type = HAD_EVENT_QUERY_IS_AUDIO_BUSY;
dev_priv->hdmi_audio_busy =
- had_interface->suspend(dev_priv->had_pvt_data,
+ had_interface->query(dev_priv->had_pvt_data,
hdmi_audio_event);
}
#endif
#if (defined(CONFIG_SND_INTELMID_HDMI_AUDIO) || \
defined(CONFIG_SND_INTELMID_HDMI_AUDIO_MODULE))
struct snd_intel_had_interface *had_interface = dev_priv->had_interface;
- int hdmi_audio_busy = 0;
- pm_event_t hdmi_audio_event;
+ bool hdmi_audio_suspend = false;
+ hdmi_audio_event_t hdmi_audio_event;
#endif
if(gbSuspendInProgress || gbResumeInProgress)
{
#if (defined(CONFIG_SND_INTELMID_HDMI_AUDIO) || \
defined(CONFIG_SND_INTELMID_HDMI_AUDIO_MODULE))
if (dev_priv->had_pvt_data && hdmi_state) {
- hdmi_audio_event.event = 0;
- hdmi_audio_busy =
- had_interface->suspend(dev_priv->had_pvt_data,
+ hdmi_audio_event.type = 0;
+ ret = had_interface->suspend(dev_priv->had_pvt_data,
hdmi_audio_event);
+ hdmi_audio_suspend = (ret == 0) ? true : false;
}
#endif
|| display_access_count
#if (defined(CONFIG_SND_INTELMID_HDMI_AUDIO) || \
defined(CONFIG_SND_INTELMID_HDMI_AUDIO_MODULE))
- || hdmi_audio_busy
+ || !hdmi_audio_suspend
#endif
)
ret = -EBUSY;
defined(CONFIG_SND_INTELMID_HDMI_AUDIO_MODULE))
struct snd_intel_had_interface *had_interface = dev_priv->had_interface;
int hdmi_audio_busy = 0;
- pm_event_t hdmi_audio_event;
+ hdmi_audio_event_t hdmi_audio_event;
if (dev_priv->had_pvt_data && hdmi_state) {
- hdmi_audio_event.event = 0;
+ hdmi_audio_event.type = HAD_EVENT_QUERY_IS_AUDIO_BUSY;
hdmi_audio_busy =
- had_interface->suspend(dev_priv->had_pvt_data,
+ had_interface->query(dev_priv->had_pvt_data,
hdmi_audio_event);
}
#endif
static struct snd_intel_had_interface had_interface = {
.name = "hdmi-audio",
+ .query = hdmi_audio_query,
.suspend = hdmi_audio_suspend,
.resume = hdmi_audio_resume,
};
int had_event_handler(enum had_event_type event_type, void *data);
-int hdmi_audio_suspend(void *drv_data, pm_event_t event);
+int hdmi_audio_query(void *drv_data, hdmi_audio_event_t event);
+int hdmi_audio_suspend(void *drv_data, hdmi_audio_event_t event);
int hdmi_audio_resume(void *drv_data);
int hdmi_audio_mode_change(struct snd_pcm_substream *substream);
extern struct snd_pcm_ops snd_intelhad_playback_ops;
static int flag_en_allbufs;
/**
+ * hdmi_audio_query - hdmi audio query function
+ *
+ *@haddata: pointer to HAD private data
+ *@event: audio event for which this method is invoked
+ *
+ * This function is called by client driver to query the
+ * hdmi audio.
+ */
+int hdmi_audio_query(void *haddata, hdmi_audio_event_t event)
+{
+ struct snd_pcm_substream *substream;
+ struct had_pvt_data *had_stream;
+ unsigned long flag_irqs;
+ struct snd_intelhad *intelhaddata = (struct snd_intelhad *)haddata;
+
+ if (intelhaddata->stream_info.had_substream)
+ substream = intelhaddata->stream_info.had_substream;
+ had_stream = intelhaddata->private_data;
+ switch (event.type) {
+ case HAD_EVENT_QUERY_IS_AUDIO_BUSY:
+ spin_lock_irqsave(&intelhaddata->had_spinlock, flag_irqs);
+
+ if ((had_stream->stream_status > HAD_RUNNING_SILENCE) ||
+ substream) {
+ spin_unlock_irqrestore(&intelhaddata->had_spinlock,
+ flag_irqs);
+ pr_debug("Audio stream active\n");
+ return -EBUSY;
+ }
+ spin_unlock_irqrestore(&intelhaddata->had_spinlock, flag_irqs);
+ break;
+
+ case HAD_EVENT_QUERY_IS_AUDIO_SUSPENDED:
+ spin_lock_irqsave(&intelhaddata->had_spinlock, flag_irqs);
+ if (intelhaddata->drv_status == HAD_DRV_SUSPENDED) {
+ spin_unlock_irqrestore(&intelhaddata->had_spinlock,
+ flag_irqs);
+ pr_debug("Audio is suspended\n");
+ return 1;
+ }
+ spin_unlock_irqrestore(&intelhaddata->had_spinlock, flag_irqs);
+ break;
+
+ default:
+ pr_debug("error un-handled event !!\n");
+ return -EINVAL;
+ break;
+
+ }
+
+ return 0;
+}
+
+/**
* hdmi_audio_suspend - power management suspend function
*
*@haddata: pointer to HAD private data
* This function is called by client driver to suspend the
* hdmi audio.
*/
-int hdmi_audio_suspend(void *haddata, pm_event_t event)
+int hdmi_audio_suspend(void *haddata, hdmi_audio_event_t event)
{
int caps, retval = 0;
struct had_pvt_data *had_stream;