Commit 037983e6 authored by Tomi Valkeinen's avatar Tomi Valkeinen

Merge branch 'omapdss-hdmi-audio'

Merge OMAP DSS HDMI audio patches from Ricardo Neri
parents 38137c8f f3a97491
......@@ -47,6 +47,51 @@ flexible way to enable non-common multi-display configuration. In addition to
modelling the hardware overlays, omapdss supports virtual overlays and overlay
managers. These can be used when updating a display with CPU or system DMA.
omapdss driver support for audio
--------------------------------
There exist several display technologies and standards that support audio as
well. Hence, it is relevant to update the DSS device driver to provide an audio
interface that may be used by an audio driver or any other driver interested in
the functionality.
The audio_enable function is intended to prepare the relevant
IP for playback (e.g., enabling an audio FIFO, taking in/out of reset
some IP, enabling companion chips, etc). It is intended to be called before
audio_start. The audio_disable function performs the reverse operation and is
intended to be called after audio_stop.
While a given DSS device driver may support audio, it is possible that for
certain configurations audio is not supported (e.g., an HDMI display using a
VESA video timing). The audio_supported function is intended to query whether
the current configuration of the display supports audio.
The audio_config function is intended to configure all the relevant audio
parameters of the display. In order to make the function independent of any
specific DSS device driver, a struct omap_dss_audio is defined. Its purpose
is to contain all the required parameters for audio configuration. At the
moment, such structure contains pointers to IEC-60958 channel status word
and CEA-861 audio infoframe structures. This should be enough to support
HDMI and DisplayPort, as both are based on CEA-861 and IEC-60958.
The audio_enable/disable, audio_config and audio_supported functions could be
implemented as functions that may sleep. Hence, they should not be called
while holding a spinlock or a readlock.
The audio_start/audio_stop function is intended to effectively start/stop audio
playback after the configuration has taken place. These functions are designed
to be used in an atomic context. Hence, audio_start should return quickly and be
called only after all the needed resources for audio playback (audio FIFOs,
DMA channels, companion chips, etc) have been enabled to begin data transfers.
audio_stop is designed to only stop the audio transfers. The resources used
for playback are released using audio_disable.
The enum omap_dss_audio_state may be used to help the implementations of
the interface to keep track of the audio state. The initial state is _DISABLED;
then, the state transitions to _CONFIGURED, and then, when it is ready to
play audio, to _ENABLED. The state _PLAYING is used when the audio is being
rendered.
Panel and controller drivers
----------------------------
......
......@@ -68,6 +68,10 @@ config OMAP4_DSS_HDMI
HDMI Interface. This adds the High Definition Multimedia Interface.
See http://www.hdmi.org/ for HDMI specification.
config OMAP4_DSS_HDMI_AUDIO
bool
depends on OMAP4_DSS_HDMI
config OMAP2_DSS_SDI
bool "SDI support"
depends on ARCH_OMAP3
......
......@@ -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;
......
......@@ -568,13 +568,17 @@ static const struct ti_hdmi_ip_ops omap4_hdmi_functions = {
.pll_enable = ti_hdmi_4xxx_pll_enable,
.pll_disable = ti_hdmi_4xxx_pll_disable,
.video_enable = ti_hdmi_4xxx_wp_video_start,
.video_disable = ti_hdmi_4xxx_wp_video_stop,
.dump_wrapper = ti_hdmi_4xxx_wp_dump,
.dump_core = ti_hdmi_4xxx_core_dump,
.dump_pll = ti_hdmi_4xxx_pll_dump,
.dump_phy = ti_hdmi_4xxx_phy_dump,
#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
.audio_enable = ti_hdmi_4xxx_wp_audio_enable,
.audio_disable = ti_hdmi_4xxx_wp_audio_disable,
.audio_start = ti_hdmi_4xxx_audio_start,
.audio_stop = ti_hdmi_4xxx_audio_stop,
.audio_config = ti_hdmi_4xxx_audio_config,
#endif
};
......
This diff is collapsed.
......@@ -30,7 +30,12 @@
#include "dss.h"
static struct {
struct mutex hdmi_lock;
/* 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;
......@@ -54,12 +59,168 @@ 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;
DSSDBG("ENTER hdmi_panel_enable\n");
mutex_lock(&hdmi.hdmi_lock);
mutex_lock(&hdmi.lock);
if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
r = -EINVAL;
......@@ -75,40 +236,52 @@ static int hdmi_panel_enable(struct omap_dss_device *dssdev)
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
err:
mutex_unlock(&hdmi.hdmi_lock);
mutex_unlock(&hdmi.lock);
return r;
}
static void hdmi_panel_disable(struct omap_dss_device *dssdev)
{
mutex_lock(&hdmi.hdmi_lock);
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
mutex_lock(&hdmi.lock);
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;
mutex_unlock(&hdmi.hdmi_lock);
mutex_unlock(&hdmi.lock);
}
static int hdmi_panel_suspend(struct omap_dss_device *dssdev)
{
int r = 0;
mutex_lock(&hdmi.hdmi_lock);
mutex_lock(&hdmi.lock);
if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
r = -EINVAL;
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:
mutex_unlock(&hdmi.hdmi_lock);
mutex_unlock(&hdmi.lock);
return r;
}
......@@ -117,7 +290,7 @@ static int hdmi_panel_resume(struct omap_dss_device *dssdev)
{
int r = 0;
mutex_lock(&hdmi.hdmi_lock);
mutex_lock(&hdmi.lock);
if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) {
r = -EINVAL;
......@@ -129,11 +302,12 @@ 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;
err:
mutex_unlock(&hdmi.hdmi_lock);
mutex_unlock(&hdmi.lock);
return r;
}
......@@ -141,11 +315,11 @@ static int hdmi_panel_resume(struct omap_dss_device *dssdev)
static void hdmi_get_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
mutex_lock(&hdmi.hdmi_lock);
mutex_lock(&hdmi.lock);
*timings = dssdev->panel.timings;
mutex_unlock(&hdmi.hdmi_lock);
mutex_unlock(&hdmi.lock);
}
static void hdmi_set_timings(struct omap_dss_device *dssdev,
......@@ -153,12 +327,18 @@ static void hdmi_set_timings(struct omap_dss_device *dssdev,
{
DSSDBG("hdmi_set_timings\n");
mutex_lock(&hdmi.hdmi_lock);
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);
mutex_unlock(&hdmi.hdmi_lock);
mutex_unlock(&hdmi.lock);
}
static int hdmi_check_timings(struct omap_dss_device *dssdev,
......@@ -168,11 +348,11 @@ static int hdmi_check_timings(struct omap_dss_device *dssdev,
DSSDBG("hdmi_check_timings\n");
mutex_lock(&hdmi.hdmi_lock);
mutex_lock(&hdmi.lock);
r = omapdss_hdmi_display_check_timing(dssdev, timings);
mutex_unlock(&hdmi.hdmi_lock);
mutex_unlock(&hdmi.lock);
return r;
}
......@@ -180,7 +360,7 @@ static int hdmi_read_edid(struct omap_dss_device *dssdev, u8 *buf, int len)
{
int r;
mutex_lock(&hdmi.hdmi_lock);
mutex_lock(&hdmi.lock);
if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
r = omapdss_hdmi_display_enable(dssdev);
......@@ -194,7 +374,7 @@ static int hdmi_read_edid(struct omap_dss_device *dssdev, u8 *buf, int len)
dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
omapdss_hdmi_display_disable(dssdev);
err:
mutex_unlock(&hdmi.hdmi_lock);
mutex_unlock(&hdmi.lock);
return r;
}
......@@ -203,7 +383,7 @@ static bool hdmi_detect(struct omap_dss_device *dssdev)
{
int r;
mutex_lock(&hdmi.hdmi_lock);
mutex_lock(&hdmi.lock);
if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
r = omapdss_hdmi_display_enable(dssdev);
......@@ -217,7 +397,7 @@ static bool hdmi_detect(struct omap_dss_device *dssdev)
dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
omapdss_hdmi_display_disable(dssdev);
err:
mutex_unlock(&hdmi.hdmi_lock);
mutex_unlock(&hdmi.lock);
return r;
}
......@@ -234,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,
......@@ -242,7 +428,11 @@ static struct omap_dss_driver hdmi_driver = {
int hdmi_panel_init(void)
{
mutex_init(&hdmi.hdmi_lock);
mutex_init(&hdmi.lock);
#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
spin_lock_init(&hdmi.audio_lock);
#endif
omap_dss_register_driver(&hdmi_driver);
......
......@@ -96,7 +96,9 @@ struct ti_hdmi_ip_ops {
void (*pll_disable)(struct hdmi_ip_data *ip_data);
void (*video_enable)(struct hdmi_ip_data *ip_data, bool start);
int (*video_enable)(struct hdmi_ip_data *ip_data);
void (*video_disable)(struct hdmi_ip_data *ip_data);
void (*dump_wrapper)(struct hdmi_ip_data *ip_data, struct seq_file *s);
......@@ -106,9 +108,17 @@ struct ti_hdmi_ip_ops {
void (*dump_phy)(struct hdmi_ip_data *ip_data, struct seq_file *s);
#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
void (*audio_enable)(struct hdmi_ip_data *ip_data, bool start);
#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
int (*audio_enable)(struct hdmi_ip_data *ip_data);
void (*audio_disable)(struct hdmi_ip_data *ip_data);
int (*audio_start)(struct hdmi_ip_data *ip_data);
void (*audio_stop)(struct hdmi_ip_data *ip_data);
int (*audio_config)(struct hdmi_ip_data *ip_data,
struct omap_dss_audio *audio);
#endif
};
......@@ -173,7 +183,8 @@ int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data);
void ti_hdmi_4xxx_phy_disable(struct hdmi_ip_data *ip_data);
int ti_hdmi_4xxx_read_edid(struct hdmi_ip_data *ip_data, u8 *edid, int len);
bool ti_hdmi_4xxx_detect(struct hdmi_ip_data *ip_data);
void ti_hdmi_4xxx_wp_video_start(struct hdmi_ip_data *ip_data, bool start);
int ti_hdmi_4xxx_wp_video_start(struct hdmi_ip_data *ip_data);
void ti_hdmi_4xxx_wp_video_stop(struct hdmi_ip_data *ip_data);
int ti_hdmi_4xxx_pll_enable(struct hdmi_ip_data *ip_data);
void ti_hdmi_4xxx_pll_disable(struct hdmi_ip_data *ip_data);
void ti_hdmi_4xxx_basic_configure(struct hdmi_ip_data *ip_data);
......@@ -181,8 +192,13 @@ void ti_hdmi_4xxx_wp_dump(struct hdmi_ip_data *ip_data, struct seq_file *s);
void ti_hdmi_4xxx_pll_dump(struct hdmi_ip_data *ip_data, struct seq_file *s);
void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s);
void ti_hdmi_4xxx_phy_dump(struct hdmi_ip_data *ip_data, struct seq_file *s);
#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
void ti_hdmi_4xxx_wp_audio_enable(struct hdmi_ip_data *ip_data, bool enable);
#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
int hdmi_compute_acr(u32 sample_freq, u32 *n, u32 *cts);
int ti_hdmi_4xxx_wp_audio_enable(struct hdmi_ip_data *ip_data);
void ti_hdmi_4xxx_wp_audio_disable(struct hdmi_ip_data *ip_data);
int ti_hdmi_4xxx_audio_start(struct hdmi_ip_data *ip_data);
void ti_hdmi_4xxx_audio_stop(struct hdmi_ip_data *ip_data);
int ti_hdmi_4xxx_audio_config(struct hdmi_ip_data *ip_data,
struct omap_dss_audio *audio);
#endif
#endif
This diff is collapsed.
......@@ -24,11 +24,6 @@
#include <linux/string.h>
#include <video/omapdss.h>
#include "ti_hdmi.h"
#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
#include <sound/soc.h>
#include <sound/pcm_params.h>
#endif
/* HDMI Wrapper */
......@@ -279,35 +274,6 @@ enum hdmi_core_infoframe {
HDMI_INFOFRAME_AVI_DB5PR_8 = 7,
HDMI_INFOFRAME_AVI_DB5PR_9 = 8,
HDMI_INFOFRAME_AVI_DB5PR_10 = 9,
HDMI_INFOFRAME_AUDIO_DB1CT_FROM_STREAM = 0,
HDMI_INFOFRAME_AUDIO_DB1CT_IEC60958 = 1,
HDMI_INFOFRAME_AUDIO_DB1CT_AC3 = 2,
HDMI_INFOFRAME_AUDIO_DB1CT_MPEG1 = 3,
HDMI_INFOFRAME_AUDIO_DB1CT_MP3 = 4,
HDMI_INFOFRAME_AUDIO_DB1CT_MPEG2_MULTICH = 5,
HDMI_INFOFRAME_AUDIO_DB1CT_AAC = 6,
HDMI_INFOFRAME_AUDIO_DB1CT_DTS = 7,
HDMI_INFOFRAME_AUDIO_DB1CT_ATRAC = 8,
HDMI_INFOFRAME_AUDIO_DB1CT_ONEBIT = 9,
HDMI_INFOFRAME_AUDIO_DB1CT_DOLBY_DIGITAL_PLUS = 10,
HDMI_INFOFRAME_AUDIO_DB1CT_DTS_HD = 11,
HDMI_INFOFRAME_AUDIO_DB1CT_MAT = 12,
HDMI_INFOFRAME_AUDIO_DB1CT_DST = 13,
HDMI_INFOFRAME_AUDIO_DB1CT_WMA_PRO = 14,
HDMI_INFOFRAME_AUDIO_DB2SF_FROM_STREAM = 0,
HDMI_INFOFRAME_AUDIO_DB2SF_32000 = 1,
HDMI_INFOFRAME_AUDIO_DB2SF_44100 = 2,
HDMI_INFOFRAME_AUDIO_DB2SF_48000 = 3,
HDMI_INFOFRAME_AUDIO_DB2SF_88200 = 4,
HDMI_INFOFRAME_AUDIO_DB2SF_96000 = 5,
HDMI_INFOFRAME_AUDIO_DB2SF_176400 = 6,
HDMI_INFOFRAME_AUDIO_DB2SF_192000 = 7,
HDMI_INFOFRAME_AUDIO_DB2SS_FROM_STREAM = 0,
HDMI_INFOFRAME_AUDIO_DB2SS_16BIT = 1,
HDMI_INFOFRAME_AUDIO_DB2SS_20BIT = 2,
HDMI_INFOFRAME_AUDIO_DB2SS_24BIT = 3,
HDMI_INFOFRAME_AUDIO_DB5_DM_INH_PERMITTED = 0,
HDMI_INFOFRAME_AUDIO_DB5_DM_INH_PROHIBITED = 1
};
enum hdmi_packing_mode {
......@@ -317,17 +283,6 @@ enum hdmi_packing_mode {
HDMI_PACK_ALREADYPACKED = 7
};
enum hdmi_core_audio_sample_freq {
HDMI_AUDIO_FS_32000 = 0x3,
HDMI_AUDIO_FS_44100 = 0x0,
HDMI_AUDIO_FS_48000 = 0x2,
HDMI_AUDIO_FS_88200 = 0x8,
HDMI_AUDIO_FS_96000 = 0xA,
HDMI_AUDIO_FS_176400 = 0xC,
HDMI_AUDIO_FS_192000 = 0xE,
HDMI_AUDIO_FS_NOT_INDICATED = 0x1
};
enum hdmi_core_audio_layout {
HDMI_AUDIO_LAYOUT_2CH = 0,
HDMI_AUDIO_LAYOUT_8CH = 1
......@@ -382,37 +337,12 @@ enum hdmi_audio_blk_strt_end_sig {
};
enum hdmi_audio_i2s_config {
HDMI_AUDIO_I2S_WS_POLARITY_LOW_IS_LEFT = 0,
HDMI_AUDIO_I2S_WS_POLARIT_YLOW_IS_RIGHT = 1,
HDMI_AUDIO_I2S_MSB_SHIFTED_FIRST = 0,
HDMI_AUDIO_I2S_LSB_SHIFTED_FIRST = 1,
HDMI_AUDIO_I2S_MAX_WORD_20BITS = 0,
HDMI_AUDIO_I2S_MAX_WORD_24BITS = 1,
HDMI_AUDIO_I2S_CHST_WORD_NOT_SPECIFIED = 0,
HDMI_AUDIO_I2S_CHST_WORD_16_BITS = 1,
HDMI_AUDIO_I2S_CHST_WORD_17_BITS = 6,
HDMI_AUDIO_I2S_CHST_WORD_18_BITS = 2,
HDMI_AUDIO_I2S_CHST_WORD_19_BITS = 4,
HDMI_AUDIO_I2S_CHST_WORD_20_BITS_20MAX = 5,
HDMI_AUDIO_I2S_CHST_WORD_20_BITS_24MAX = 1,
HDMI_AUDIO_I2S_CHST_WORD_21_BITS = 6,
HDMI_AUDIO_I2S_CHST_WORD_22_BITS = 2,
HDMI_AUDIO_I2S_CHST_WORD_23_BITS = 4,
HDMI_AUDIO_I2S_CHST_WORD_24_BITS = 5,
HDMI_AUDIO_I2S_SCK_EDGE_FALLING = 0,
HDMI_AUDIO_I2S_SCK_EDGE_RISING = 1,
HDMI_AUDIO_I2S_VBIT_FOR_PCM = 0,
HDMI_AUDIO_I2S_VBIT_FOR_COMPRESSED = 1,
HDMI_AUDIO_I2S_INPUT_LENGTH_NA = 0,
HDMI_AUDIO_I2S_INPUT_LENGTH_16 = 2,
HDMI_AUDIO_I2S_INPUT_LENGTH_17 = 12,
HDMI_AUDIO_I2S_INPUT_LENGTH_18 = 4,
HDMI_AUDIO_I2S_INPUT_LENGTH_19 = 8,
HDMI_AUDIO_I2S_INPUT_LENGTH_20 = 10,
HDMI_AUDIO_I2S_INPUT_LENGTH_21 = 13,
HDMI_AUDIO_I2S_INPUT_LENGTH_22 = 5,
HDMI_AUDIO_I2S_INPUT_LENGTH_23 = 9,
HDMI_AUDIO_I2S_INPUT_LENGTH_24 = 11,
HDMI_AUDIO_I2S_FIRST_BIT_SHIFT = 0,
HDMI_AUDIO_I2S_FIRST_BIT_NO_SHIFT = 1,
HDMI_AUDIO_I2S_SD0_EN = 1,
......@@ -441,20 +371,6 @@ struct hdmi_core_video_config {
enum hdmi_core_tclkselclkmult tclk_sel_clkmult;
};
/*
* Refer to section 8.2 in HDMI 1.3 specification for
* details about infoframe databytes
*/
struct hdmi_core_infoframe_audio {
u8 db1_coding_type;
u8 db1_channel_count;
u8 db2_sample_freq;
u8 db2_sample_size;
u8 db4_channel_alloc;
bool db5_downmix_inh;
u8 db5_lsv; /* Level shift values for downmix */
};
struct hdmi_core_packet_enable_repeat {
u32 audio_pkt;
u32 audio_pkt_repeat;
......@@ -491,15 +407,10 @@ struct hdmi_audio_dma {
};
struct hdmi_core_audio_i2s_config {
u8 word_max_length;
u8 word_length;
u8 in_length_bits;
u8 justification;
u8 en_high_bitrate_aud;
u8 sck_edge_mode;
u8 cbit_order;
u8 vbit;
u8 ws_polarity;
u8 direction;
u8 shift;
u8 active_sds;
......@@ -507,7 +418,7 @@ struct hdmi_core_audio_i2s_config {
struct hdmi_core_audio_config {
struct hdmi_core_audio_i2s_config i2s_cfg;
enum hdmi_core_audio_sample_freq freq_sample;
struct snd_aes_iec958 *iec60958_cfg;
bool fs_override;
u32 n;
u32 cts;
......@@ -522,17 +433,4 @@ struct hdmi_core_audio_config {
bool en_spdif;
};
#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
int hdmi_config_audio_acr(struct hdmi_ip_data *ip_data,
u32 sample_freq, u32 *n, u32 *cts);
void hdmi_core_audio_infoframe_config(struct hdmi_ip_data *ip_data,
struct hdmi_core_infoframe_audio *info_aud);
void hdmi_core_audio_config(struct hdmi_ip_data *ip_data,
struct hdmi_core_audio_config *cfg);
void hdmi_wp_audio_config_dma(struct hdmi_ip_data *ip_data,
struct hdmi_audio_dma *aud_dma);
void hdmi_wp_audio_config_format(struct hdmi_ip_data *ip_data,
struct hdmi_audio_format *aud_fmt);
#endif
#endif
......@@ -51,6 +51,8 @@
struct omap_dss_device;
struct omap_overlay_manager;
struct snd_aes_iec958;
struct snd_cea_861_aud_if;
enum omap_display_type {
OMAP_DISPLAY_TYPE_NONE = 0,
......@@ -158,6 +160,13 @@ enum omap_dss_display_state {
OMAP_DSS_DISPLAY_SUSPENDED,
};
enum omap_dss_audio_state {
OMAP_DSS_AUDIO_DISABLED = 0,
OMAP_DSS_AUDIO_ENABLED,
OMAP_DSS_AUDIO_CONFIGURED,
OMAP_DSS_AUDIO_PLAYING,
};
/* XXX perhaps this should be removed */
enum omap_dss_overlay_managers {
OMAP_DSS_OVL_MGR_LCD,
......@@ -583,6 +592,8 @@ struct omap_dss_device {
enum omap_dss_display_state state;
enum omap_dss_audio_state audio_state;
/* platform specific */
int (*platform_enable)(struct omap_dss_device *dssdev);
void (*platform_disable)(struct omap_dss_device *dssdev);
......@@ -595,6 +606,11 @@ struct omap_dss_hdmi_data
int hpd_gpio;
};
struct omap_dss_audio {
struct snd_aes_iec958 *iec;
struct snd_cea_861_aud_if *cea;
};
struct omap_dss_driver {
struct device_driver driver;
......@@ -642,6 +658,24 @@ struct omap_dss_driver {
int (*read_edid)(struct omap_dss_device *dssdev, u8 *buf, int len);
bool (*detect)(struct omap_dss_device *dssdev);
/*
* For display drivers that support audio. This encompasses
* HDMI and DisplayPort at the moment.
*/
/*
* Note: These functions might sleep. Do not call while
* holding a spinlock/readlock.
*/
int (*audio_enable)(struct omap_dss_device *dssdev);
void (*audio_disable)(struct omap_dss_device *dssdev);
bool (*audio_supported)(struct omap_dss_device *dssdev);
int (*audio_config)(struct omap_dss_device *dssdev,
struct omap_dss_audio *audio);
/* Note: These functions may not sleep */
int (*audio_start)(struct omap_dss_device *dssdev);
void (*audio_stop)(struct omap_dss_device *dssdev);
};
int omap_dss_register_driver(struct omap_dss_driver *);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment