Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 310363
b: refs/heads/master
c: f3a9749
h: refs/heads/master
i:
  310361: 8c25fc3
  310359: 1075e74
v: v3
  • Loading branch information
Ricardo Neri authored and Tomi Valkeinen committed May 11, 2012
1 parent 358d3a2 commit b79bdf7
Show file tree
Hide file tree
Showing 4 changed files with 242 additions and 3 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: b7dea05aec8b6421500929d5003866655d6d9dab
refs/heads/master: f3a97491f2c54e5239663f8f147b34c280cf7db5
8 changes: 8 additions & 0 deletions trunk/drivers/video/omap2/dss/dss.h
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,14 @@ int omapdss_hdmi_read_edid(u8 *buf, int len);
bool omapdss_hdmi_detect(void);
int hdmi_panel_init(void);
void hdmi_panel_exit(void);
#ifdef CONFIG_OMAP4_DSS_HDMI_AUDIO
int hdmi_audio_enable(void);
void hdmi_audio_disable(void);
int hdmi_audio_start(void);
void hdmi_audio_stop(void);
bool hdmi_mode_has_audio(void);
int hdmi_audio_config(struct omap_dss_audio *audio);
#endif

/* RFBI */
int rfbi_init_platform_driver(void) __init;
Expand Down
42 changes: 42 additions & 0 deletions trunk/drivers/video/omap2/dss/hdmi.c
Original file line number Diff line number Diff line change
Expand Up @@ -654,6 +654,48 @@ int hdmi_compute_acr(u32 sample_freq, u32 *n, u32 *cts)

return 0;
}

int hdmi_audio_enable(void)
{
DSSDBG("audio_enable\n");

return hdmi.ip_data.ops->audio_enable(&hdmi.ip_data);
}

void hdmi_audio_disable(void)
{
DSSDBG("audio_disable\n");

hdmi.ip_data.ops->audio_disable(&hdmi.ip_data);
}

int hdmi_audio_start(void)
{
DSSDBG("audio_start\n");

return hdmi.ip_data.ops->audio_start(&hdmi.ip_data);
}

void hdmi_audio_stop(void)
{
DSSDBG("audio_stop\n");

hdmi.ip_data.ops->audio_stop(&hdmi.ip_data);
}

bool hdmi_mode_has_audio(void)
{
if (hdmi.ip_data.cfg.cm.mode == HDMI_HDMI)
return true;
else
return false;
}

int hdmi_audio_config(struct omap_dss_audio *audio)
{
return hdmi.ip_data.ops->audio_config(&hdmi.ip_data, audio);
}

#endif

static void __init hdmi_probe_pdata(struct platform_device *pdev)
Expand Down
193 changes: 191 additions & 2 deletions trunk/drivers/video/omap2/dss/hdmi_panel.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@
static struct {
/* This protects the panel ops, mainly when accessing the HDMI IP. */
struct mutex lock;
#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
/* This protects the audio ops, specifically. */
spinlock_t audio_lock;
#endif
} hdmi;


Expand All @@ -55,6 +59,162 @@ static void hdmi_panel_remove(struct omap_dss_device *dssdev)

}

#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
static int hdmi_panel_audio_enable(struct omap_dss_device *dssdev)
{
unsigned long flags;
int r;

mutex_lock(&hdmi.lock);
spin_lock_irqsave(&hdmi.audio_lock, flags);

/* enable audio only if the display is active and supports audio */
if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE ||
!hdmi_mode_has_audio()) {
DSSERR("audio not supported or display is off\n");
r = -EPERM;
goto err;
}

r = hdmi_audio_enable();

if (!r)
dssdev->audio_state = OMAP_DSS_AUDIO_ENABLED;

err:
spin_unlock_irqrestore(&hdmi.audio_lock, flags);
mutex_unlock(&hdmi.lock);
return r;
}

static void hdmi_panel_audio_disable(struct omap_dss_device *dssdev)
{
unsigned long flags;

spin_lock_irqsave(&hdmi.audio_lock, flags);

hdmi_audio_disable();

dssdev->audio_state = OMAP_DSS_AUDIO_DISABLED;

spin_unlock_irqrestore(&hdmi.audio_lock, flags);
}

static int hdmi_panel_audio_start(struct omap_dss_device *dssdev)
{
unsigned long flags;
int r;

spin_lock_irqsave(&hdmi.audio_lock, flags);
/*
* No need to check the panel state. It was checked when trasitioning
* to AUDIO_ENABLED.
*/
if (dssdev->audio_state != OMAP_DSS_AUDIO_ENABLED) {
DSSERR("audio start from invalid state\n");
r = -EPERM;
goto err;
}

r = hdmi_audio_start();

if (!r)
dssdev->audio_state = OMAP_DSS_AUDIO_PLAYING;

err:
spin_unlock_irqrestore(&hdmi.audio_lock, flags);
return r;
}

static void hdmi_panel_audio_stop(struct omap_dss_device *dssdev)
{
unsigned long flags;

spin_lock_irqsave(&hdmi.audio_lock, flags);

hdmi_audio_stop();
dssdev->audio_state = OMAP_DSS_AUDIO_ENABLED;

spin_unlock_irqrestore(&hdmi.audio_lock, flags);
}

static bool hdmi_panel_audio_supported(struct omap_dss_device *dssdev)
{
bool r = false;

mutex_lock(&hdmi.lock);

if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
goto err;

if (!hdmi_mode_has_audio())
goto err;

r = true;
err:
mutex_unlock(&hdmi.lock);
return r;
}

static int hdmi_panel_audio_config(struct omap_dss_device *dssdev,
struct omap_dss_audio *audio)
{
unsigned long flags;
int r;

mutex_lock(&hdmi.lock);
spin_lock_irqsave(&hdmi.audio_lock, flags);

/* config audio only if the display is active and supports audio */
if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE ||
!hdmi_mode_has_audio()) {
DSSERR("audio not supported or display is off\n");
r = -EPERM;
goto err;
}

r = hdmi_audio_config(audio);

if (!r)
dssdev->audio_state = OMAP_DSS_AUDIO_CONFIGURED;

err:
spin_unlock_irqrestore(&hdmi.audio_lock, flags);
mutex_unlock(&hdmi.lock);
return r;
}

#else
static int hdmi_panel_audio_enable(struct omap_dss_device *dssdev)
{
return -EPERM;
}

static void hdmi_panel_audio_disable(struct omap_dss_device *dssdev)
{
}

static int hdmi_panel_audio_start(struct omap_dss_device *dssdev)
{
return -EPERM;
}

static void hdmi_panel_audio_stop(struct omap_dss_device *dssdev)
{
}

static bool hdmi_panel_audio_supported(struct omap_dss_device *dssdev)
{
return false;
}

static int hdmi_panel_audio_config(struct omap_dss_device *dssdev,
struct omap_dss_audio *audio)
{
return -EPERM;
}
#endif

static int hdmi_panel_enable(struct omap_dss_device *dssdev)
{
int r = 0;
Expand Down Expand Up @@ -85,8 +245,15 @@ static void hdmi_panel_disable(struct omap_dss_device *dssdev)
{
mutex_lock(&hdmi.lock);

if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
/*
* TODO: notify audio users that the display was disabled. For
* now, disable audio locally to not break our audio state
* machine.
*/
hdmi_panel_audio_disable(dssdev);
omapdss_hdmi_display_disable(dssdev);
}

dssdev->state = OMAP_DSS_DISPLAY_DISABLED;

Expand All @@ -104,8 +271,13 @@ static int hdmi_panel_suspend(struct omap_dss_device *dssdev)
goto err;
}

dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
/*
* TODO: notify audio users that the display was suspended. For now,
* disable audio locally to not break our audio state machine.
*/
hdmi_panel_audio_disable(dssdev);

dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
omapdss_hdmi_display_disable(dssdev);

err:
Expand All @@ -130,6 +302,7 @@ static int hdmi_panel_resume(struct omap_dss_device *dssdev)
DSSERR("failed to power on\n");
goto err;
}
/* TODO: notify audio users that the panel resumed. */

dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;

Expand All @@ -156,6 +329,12 @@ static void hdmi_set_timings(struct omap_dss_device *dssdev,

mutex_lock(&hdmi.lock);

/*
* TODO: notify audio users that there was a timings change. For
* now, disable audio locally to not break our audio state machine.
*/
hdmi_panel_audio_disable(dssdev);

dssdev->panel.timings = *timings;
omapdss_hdmi_display_set_timing(dssdev);

Expand Down Expand Up @@ -235,6 +414,12 @@ static struct omap_dss_driver hdmi_driver = {
.check_timings = hdmi_check_timings,
.read_edid = hdmi_read_edid,
.detect = hdmi_detect,
.audio_enable = hdmi_panel_audio_enable,
.audio_disable = hdmi_panel_audio_disable,
.audio_start = hdmi_panel_audio_start,
.audio_stop = hdmi_panel_audio_stop,
.audio_supported = hdmi_panel_audio_supported,
.audio_config = hdmi_panel_audio_config,
.driver = {
.name = "hdmi_panel",
.owner = THIS_MODULE,
Expand All @@ -245,6 +430,10 @@ int hdmi_panel_init(void)
{
mutex_init(&hdmi.lock);

#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
spin_lock_init(&hdmi.audio_lock);
#endif

omap_dss_register_driver(&hdmi_driver);

return 0;
Expand Down

0 comments on commit b79bdf7

Please sign in to comment.