summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChen Liangjun <b36089@freescale.com>2012-08-21 17:25:36 +0800
committerChen Liangjun <b36089@freescale.com>2012-08-29 14:22:55 +0800
commit7227ff69e142764b73a7998df6059697e7788d0e (patch)
tree92db3a2b33b455284476e94c4230739eaa45ffce
parent4630c97b33a135026560d4d17c6b0b8e14253ff5 (diff)
ENGR00182456-1 HDMI: Add interface for HDMI audio management
In this patch, add support for: 1. Interface for HDMI audio to register PCM into HDMI core driver. 2. Interface for HDMI video driver to stop HDMI audio 3. Interface for HDMI video driver to inform the state of HDMI cable and state of HDMI blank. Signed-off-by: Chen Liangjun <b36089@freescale.com>
-rw-r--r--drivers/mfd/mxc-hdmi-core.c116
-rw-r--r--include/linux/mfd/mxc-hdmi-core.h10
2 files changed, 126 insertions, 0 deletions
diff --git a/drivers/mfd/mxc-hdmi-core.c b/drivers/mfd/mxc-hdmi-core.c
index 332843661d98..e9322477ff6d 100644
--- a/drivers/mfd/mxc-hdmi-core.c
+++ b/drivers/mfd/mxc-hdmi-core.c
@@ -63,6 +63,104 @@ int mxc_hdmi_disp_id;
static struct mxc_edid_cfg hdmi_core_edid_cfg;
static int hdmi_core_init;
static unsigned int hdmi_dma_running;
+static struct snd_pcm_substream *hdmi_audio_stream_playback;
+static unsigned int hdmi_cable_state;
+static unsigned int hdmi_blank_state;
+static spinlock_t hdmi_audio_lock, hdmi_blank_state_lock, hdmi_cable_state_lock;
+
+
+unsigned int hdmi_set_cable_state(unsigned int state)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&hdmi_cable_state_lock, flags);
+ hdmi_cable_state = state;
+ spin_unlock_irqrestore(&hdmi_cable_state_lock, flags);
+
+ return 0;
+}
+
+unsigned int hdmi_set_blank_state(unsigned int state)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&hdmi_blank_state_lock, flags);
+ hdmi_blank_state = state;
+ spin_unlock_irqrestore(&hdmi_blank_state_lock, flags);
+
+ return 0;
+}
+
+static void hdmi_audio_abort_stream(struct snd_pcm_substream *substream)
+{
+ unsigned long flags;
+
+ snd_pcm_stream_lock_irqsave(substream, flags);
+
+ if (snd_pcm_running(substream))
+ snd_pcm_stop(substream, SNDRV_PCM_STATE_DISCONNECTED);
+
+ snd_pcm_stream_unlock_irqrestore(substream, flags);
+}
+
+int mxc_hdmi_abort_stream(void)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&hdmi_audio_lock, flags);
+ if (hdmi_audio_stream_playback)
+ hdmi_audio_abort_stream(hdmi_audio_stream_playback);
+ spin_unlock_irqrestore(&hdmi_audio_lock, flags);
+
+ return 0;
+}
+
+static int check_hdmi_state(void)
+{
+ unsigned long flags1, flags2;
+ unsigned int ret;
+
+ spin_lock_irqsave(&hdmi_cable_state_lock, flags1);
+ spin_lock_irqsave(&hdmi_blank_state_lock, flags2);
+
+ ret = hdmi_cable_state && hdmi_blank_state;
+
+ spin_unlock_irqrestore(&hdmi_blank_state_lock, flags2);
+ spin_unlock_irqrestore(&hdmi_cable_state_lock, flags1);
+
+ return ret;
+}
+
+int mxc_hdmi_register_audio(struct snd_pcm_substream *substream)
+{
+ unsigned long flags, flags1;
+ int ret = 0;
+
+ snd_pcm_stream_lock_irqsave(substream, flags);
+
+ if (substream && check_hdmi_state()) {
+ spin_lock_irqsave(&hdmi_audio_lock, flags1);
+ if (hdmi_audio_stream_playback) {
+ pr_err("%s unconsist hdmi auido stream!\n", __func__);
+ ret = -EINVAL;
+ }
+ hdmi_audio_stream_playback = substream;
+ spin_unlock_irqrestore(&hdmi_audio_lock, flags1);
+ } else
+ ret = -EINVAL;
+
+ snd_pcm_stream_unlock_irqrestore(substream, flags);
+
+ return ret;
+}
+
+void mxc_hdmi_unregister_audio(struct snd_pcm_substream *substream)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&hdmi_audio_lock, flags);
+ hdmi_audio_stream_playback = NULL;
+ spin_unlock_irqrestore(&hdmi_audio_lock, flags);
+}
u8 hdmi_readb(unsigned int reg)
{
@@ -466,6 +564,7 @@ static int mxc_hdmi_core_probe(struct platform_device *pdev)
struct fsl_mxc_hdmi_core_platform_data *pdata = pdev->dev.platform_data;
struct mxc_hdmi_data *hdmi_data;
struct resource *res;
+ unsigned long flags;
int ret = 0;
#ifdef DEBUG
@@ -495,6 +594,23 @@ static int mxc_hdmi_core_probe(struct platform_device *pdev)
spin_lock_init(&irq_spinlock);
spin_lock_init(&edid_spinlock);
+
+ spin_lock_init(&hdmi_cable_state_lock);
+ spin_lock_init(&hdmi_blank_state_lock);
+ spin_lock_init(&hdmi_audio_lock);
+
+ spin_lock_irqsave(&hdmi_cable_state_lock, flags);
+ hdmi_cable_state = 0;
+ spin_unlock_irqrestore(&hdmi_cable_state_lock, flags);
+
+ spin_lock_irqsave(&hdmi_blank_state_lock, flags);
+ hdmi_blank_state = 0;
+ spin_unlock_irqrestore(&hdmi_blank_state_lock, flags);
+
+ spin_lock_irqsave(&hdmi_audio_lock, flags);
+ hdmi_audio_stream_playback = NULL;
+ spin_unlock_irqrestore(&hdmi_audio_lock, flags);
+
isfr_clk = clk_get(&hdmi_data->pdev->dev, "hdmi_isfr_clk");
if (IS_ERR(isfr_clk)) {
ret = PTR_ERR(isfr_clk);
diff --git a/include/linux/mfd/mxc-hdmi-core.h b/include/linux/mfd/mxc-hdmi-core.h
index 8ddea5a040cc..f16b11cb5cf4 100644
--- a/include/linux/mfd/mxc-hdmi-core.h
+++ b/include/linux/mfd/mxc-hdmi-core.h
@@ -21,6 +21,11 @@
#include <mach/mxc_edid.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
#define IRQ_DISABLE_SUCCEED 0
#define IRQ_DISABLE_FAIL 1
@@ -50,5 +55,10 @@ extern int mxc_hdmi_disp_id;
void hdmi_set_registered(int registered);
int hdmi_get_registered(void);
unsigned int hdmi_SDMA_check(void);
+int mxc_hdmi_abort_stream(void);
+int mxc_hdmi_register_audio(struct snd_pcm_substream *substream);
+void mxc_hdmi_unregister_audio(struct snd_pcm_substream *substream);
+unsigned int hdmi_set_cable_state(unsigned int state);
+unsigned int hdmi_set_blank_state(unsigned int state);
#endif