Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
raspberrypi-kernel
提交
037983e6
R
raspberrypi-kernel
项目概览
openeuler
/
raspberrypi-kernel
通知
13
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
raspberrypi-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
037983e6
编写于
5月 11, 2012
作者:
T
Tomi Valkeinen
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'omapdss-hdmi-audio'
Merge OMAP DSS HDMI audio patches from Ricardo Neri
上级
38137c8f
f3a97491
变更
10
隐藏空白更改
内联
并排
Showing
10 changed file
with
710 addition
and
436 deletion
+710
-436
Documentation/arm/OMAP/DSS
Documentation/arm/OMAP/DSS
+45
-0
drivers/video/omap2/dss/Kconfig
drivers/video/omap2/dss/Kconfig
+4
-0
drivers/video/omap2/dss/dss.h
drivers/video/omap2/dss/dss.h
+8
-0
drivers/video/omap2/dss/dss_features.c
drivers/video/omap2/dss/dss_features.c
+6
-2
drivers/video/omap2/dss/hdmi.c
drivers/video/omap2/dss/hdmi.c
+135
-224
drivers/video/omap2/dss/hdmi_panel.c
drivers/video/omap2/dss/hdmi_panel.c
+213
-23
drivers/video/omap2/dss/ti_hdmi.h
drivers/video/omap2/dss/ti_hdmi.h
+24
-8
drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
+240
-76
drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h
drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h
+1
-103
include/video/omapdss.h
include/video/omapdss.h
+34
-0
未找到文件。
Documentation/arm/OMAP/DSS
浏览文件 @
037983e6
...
...
@@ -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
----------------------------
...
...
drivers/video/omap2/dss/Kconfig
浏览文件 @
037983e6
...
...
@@ -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
...
...
drivers/video/omap2/dss/dss.h
浏览文件 @
037983e6
...
...
@@ -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
;
...
...
drivers/video/omap2/dss/dss_features.c
浏览文件 @
037983e6
...
...
@@ -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
};
...
...
drivers/video/omap2/dss/hdmi.c
浏览文件 @
037983e6
...
...
@@ -33,12 +33,6 @@
#include <linux/pm_runtime.h>
#include <linux/clk.h>
#include <video/omapdss.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>
#include "ti_hdmi_4xxx_ip.h"
#endif
#include "ti_hdmi.h"
#include "dss.h"
...
...
@@ -324,7 +318,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
hdmi_compute_pll
(
dssdev
,
phy
,
&
hdmi
.
ip_data
.
pll_data
);
hdmi
.
ip_data
.
ops
->
video_
enable
(
&
hdmi
.
ip_data
,
0
);
hdmi
.
ip_data
.
ops
->
video_
disable
(
&
hdmi
.
ip_data
);
/* config the PLL and PHY hdmi_set_pll_pwrfirst */
r
=
hdmi
.
ip_data
.
ops
->
pll_enable
(
&
hdmi
.
ip_data
);
...
...
@@ -358,7 +352,9 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
/* tv size */
dss_mgr_set_timings
(
dssdev
->
manager
,
&
dssdev
->
panel
.
timings
);
hdmi
.
ip_data
.
ops
->
video_enable
(
&
hdmi
.
ip_data
,
1
);
r
=
hdmi
.
ip_data
.
ops
->
video_enable
(
&
hdmi
.
ip_data
);
if
(
r
)
goto
err_vid_enable
;
r
=
dss_mgr_enable
(
dssdev
->
manager
);
if
(
r
)
...
...
@@ -367,7 +363,8 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
return
0
;
err_mgr_enable:
hdmi
.
ip_data
.
ops
->
video_enable
(
&
hdmi
.
ip_data
,
0
);
hdmi
.
ip_data
.
ops
->
video_disable
(
&
hdmi
.
ip_data
);
err_vid_enable:
hdmi
.
ip_data
.
ops
->
phy_disable
(
&
hdmi
.
ip_data
);
hdmi
.
ip_data
.
ops
->
pll_disable
(
&
hdmi
.
ip_data
);
err:
...
...
@@ -379,7 +376,7 @@ static void hdmi_power_off(struct omap_dss_device *dssdev)
{
dss_mgr_disable
(
dssdev
->
manager
);
hdmi
.
ip_data
.
ops
->
video_
enable
(
&
hdmi
.
ip_data
,
0
);
hdmi
.
ip_data
.
ops
->
video_
disable
(
&
hdmi
.
ip_data
);
hdmi
.
ip_data
.
ops
->
phy_disable
(
&
hdmi
.
ip_data
);
hdmi
.
ip_data
.
ops
->
pll_disable
(
&
hdmi
.
ip_data
);
hdmi_runtime_put
();
...
...
@@ -536,241 +533,171 @@ void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev)
mutex_unlock
(
&
hdmi
.
lock
);
}
#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
static
int
hdmi_audio_trigger
(
struct
snd_pcm_substream
*
substream
,
int
cmd
,
struct
snd_soc_dai
*
dai
)
static
int
hdmi_get_clocks
(
struct
platform_device
*
pdev
)
{
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
snd_soc_codec
*
codec
=
rtd
->
codec
;
struct
platform_device
*
pdev
=
to_platform_device
(
codec
->
dev
);
struct
hdmi_ip_data
*
ip_data
=
snd_soc_codec_get_drvdata
(
codec
);
int
err
=
0
;
struct
clk
*
clk
;
if
(
!
(
ip_data
->
ops
)
&&
!
(
ip_data
->
ops
->
audio_enable
))
{
dev_err
(
&
pdev
->
dev
,
"Cannot enable/disable audio
\n
"
);
return
-
ENODEV
;
clk
=
clk_get
(
&
pdev
->
dev
,
"sys_clk"
);
if
(
IS_ERR
(
clk
))
{
DSSERR
(
"can't get sys_clk
\n
"
);
return
PTR_ERR
(
clk
);
}
switch
(
cmd
)
{
case
SNDRV_PCM_TRIGGER_START
:
case
SNDRV_PCM_TRIGGER_RESUME
:
case
SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
ip_data
->
ops
->
audio_enable
(
ip_data
,
true
);
break
;
case
SNDRV_PCM_TRIGGER_STOP
:
case
SNDRV_PCM_TRIGGER_SUSPEND
:
case
SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
ip_data
->
ops
->
audio_enable
(
ip_data
,
false
);
break
;
default:
err
=
-
EINVAL
;
}
return
err
;
}
static
int
hdmi_audio_hw_params
(
struct
snd_pcm_substream
*
substream
,
struct
snd_pcm_hw_params
*
params
,
struct
snd_soc_dai
*
dai
)
{
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
snd_soc_codec
*
codec
=
rtd
->
codec
;
struct
hdmi_ip_data
*
ip_data
=
snd_soc_codec_get_drvdata
(
codec
);
struct
hdmi_audio_format
audio_format
;
struct
hdmi_audio_dma
audio_dma
;
struct
hdmi_core_audio_config
core_cfg
;
struct
hdmi_core_infoframe_audio
aud_if_cfg
;
int
err
,
n
,
cts
;
enum
hdmi_core_audio_sample_freq
sample_freq
;
switch
(
params_format
(
params
))
{
case
SNDRV_PCM_FORMAT_S16_LE
:
core_cfg
.
i2s_cfg
.
word_max_length
=
HDMI_AUDIO_I2S_MAX_WORD_20BITS
;
core_cfg
.
i2s_cfg
.
word_length
=
HDMI_AUDIO_I2S_CHST_WORD_16_BITS
;
core_cfg
.
i2s_cfg
.
in_length_bits
=
HDMI_AUDIO_I2S_INPUT_LENGTH_16
;
core_cfg
.
i2s_cfg
.
justification
=
HDMI_AUDIO_JUSTIFY_LEFT
;
audio_format
.
samples_per_word
=
HDMI_AUDIO_ONEWORD_TWOSAMPLES
;
audio_format
.
sample_size
=
HDMI_AUDIO_SAMPLE_16BITS
;
audio_format
.
justification
=
HDMI_AUDIO_JUSTIFY_LEFT
;
audio_dma
.
transfer_size
=
0x10
;
break
;
case
SNDRV_PCM_FORMAT_S24_LE
:
core_cfg
.
i2s_cfg
.
word_max_length
=
HDMI_AUDIO_I2S_MAX_WORD_24BITS
;
core_cfg
.
i2s_cfg
.
word_length
=
HDMI_AUDIO_I2S_CHST_WORD_24_BITS
;
core_cfg
.
i2s_cfg
.
in_length_bits
=
HDMI_AUDIO_I2S_INPUT_LENGTH_24
;
audio_format
.
samples_per_word
=
HDMI_AUDIO_ONEWORD_ONESAMPLE
;
audio_format
.
sample_size
=
HDMI_AUDIO_SAMPLE_24BITS
;
audio_format
.
justification
=
HDMI_AUDIO_JUSTIFY_RIGHT
;
core_cfg
.
i2s_cfg
.
justification
=
HDMI_AUDIO_JUSTIFY_RIGHT
;
audio_dma
.
transfer_size
=
0x20
;
break
;
default:
hdmi
.
sys_clk
=
clk
;
return
0
;
}
static
void
hdmi_put_clocks
(
void
)
{
if
(
hdmi
.
sys_clk
)
clk_put
(
hdmi
.
sys_clk
);
}
#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
int
hdmi_compute_acr
(
u32
sample_freq
,
u32
*
n
,
u32
*
cts
)
{
u32
deep_color
;
bool
deep_color_correct
=
false
;
u32
pclk
=
hdmi
.
ip_data
.
cfg
.
timings
.
pixel_clock
;
if
(
n
==
NULL
||
cts
==
NULL
)
return
-
EINVAL
;
}
switch
(
params_rate
(
params
))
{
/* TODO: When implemented, query deep color mode here. */
deep_color
=
100
;
/*
* When using deep color, the default N value (as in the HDMI
* specification) yields to an non-integer CTS. Hence, we
* modify it while keeping the restrictions described in
* section 7.2.1 of the HDMI 1.4a specification.
*/
switch
(
sample_freq
)
{
case
32000
:
sample_freq
=
HDMI_AUDIO_FS_32000
;
case
48000
:
case
96000
:
case
192000
:
if
(
deep_color
==
125
)
if
(
pclk
==
27027
||
pclk
==
74250
)
deep_color_correct
=
true
;
if
(
deep_color
==
150
)
if
(
pclk
==
27027
)
deep_color_correct
=
true
;
break
;
case
44100
:
sample_freq
=
HDMI_AUDIO_FS_44100
;
break
;
case
48000
:
sample_freq
=
HDMI_AUDIO_FS_48000
;
case
88200
:
case
176400
:
if
(
deep_color
==
125
)
if
(
pclk
==
27027
)
deep_color_correct
=
true
;
break
;
default:
return
-
EINVAL
;
}
err
=
hdmi_config_audio_acr
(
ip_data
,
params_rate
(
params
),
&
n
,
&
cts
);
if
(
err
<
0
)
return
err
;
/* Audio wrapper config */
audio_format
.
stereo_channels
=
HDMI_AUDIO_STEREO_ONECHANNEL
;
audio_format
.
active_chnnls_msk
=
0x03
;
audio_format
.
type
=
HDMI_AUDIO_TYPE_LPCM
;
audio_format
.
sample_order
=
HDMI_AUDIO_SAMPLE_LEFT_FIRST
;
/* Disable start/stop signals of IEC 60958 blocks */
audio_format
.
en_sig_blk_strt_end
=
HDMI_AUDIO_BLOCK_SIG_STARTEND_OFF
;
audio_dma
.
block_size
=
0xC0
;
audio_dma
.
mode
=
HDMI_AUDIO_TRANSF_DMA
;
audio_dma
.
fifo_threshold
=
0x20
;
/* in number of samples */
hdmi_wp_audio_config_dma
(
ip_data
,
&
audio_dma
);
hdmi_wp_audio_config_format
(
ip_data
,
&
audio_format
);
/*
* I2S config
*/
core_cfg
.
i2s_cfg
.
en_high_bitrate_aud
=
false
;
/* Only used with high bitrate audio */
core_cfg
.
i2s_cfg
.
cbit_order
=
false
;
/* Serial data and word select should change on sck rising edge */
core_cfg
.
i2s_cfg
.
sck_edge_mode
=
HDMI_AUDIO_I2S_SCK_EDGE_RISING
;
core_cfg
.
i2s_cfg
.
vbit
=
HDMI_AUDIO_I2S_VBIT_FOR_PCM
;
/* Set I2S word select polarity */
core_cfg
.
i2s_cfg
.
ws_polarity
=
HDMI_AUDIO_I2S_WS_POLARITY_LOW_IS_LEFT
;
core_cfg
.
i2s_cfg
.
direction
=
HDMI_AUDIO_I2S_MSB_SHIFTED_FIRST
;
/* Set serial data to word select shift. See Phillips spec. */
core_cfg
.
i2s_cfg
.
shift
=
HDMI_AUDIO_I2S_FIRST_BIT_SHIFT
;
/* Enable one of the four available serial data channels */
core_cfg
.
i2s_cfg
.
active_sds
=
HDMI_AUDIO_I2S_SD0_EN
;
/* Core audio config */
core_cfg
.
freq_sample
=
sample_freq
;
core_cfg
.
n
=
n
;
core_cfg
.
cts
=
cts
;
if
(
dss_has_feature
(
FEAT_HDMI_CTS_SWMODE
))
{
core_cfg
.
aud_par_busclk
=
0
;
core_cfg
.
cts_mode
=
HDMI_AUDIO_CTS_MODE_SW
;
core_cfg
.
use_mclk
=
dss_has_feature
(
FEAT_HDMI_AUDIO_USE_MCLK
);
if
(
deep_color_correct
)
{
switch
(
sample_freq
)
{
case
32000
:
*
n
=
8192
;
break
;
case
44100
:
*
n
=
12544
;
break
;
case
48000
:
*
n
=
8192
;
break
;
case
88200
:
*
n
=
25088
;
break
;
case
96000
:
*
n
=
16384
;
break
;
case
176400
:
*
n
=
50176
;
break
;
case
192000
:
*
n
=
32768
;
break
;
default:
return
-
EINVAL
;
}
}
else
{
core_cfg
.
aud_par_busclk
=
(((
128
*
31
)
-
1
)
<<
8
);
core_cfg
.
cts_mode
=
HDMI_AUDIO_CTS_MODE_HW
;
core_cfg
.
use_mclk
=
true
;
switch
(
sample_freq
)
{
case
32000
:
*
n
=
4096
;
break
;
case
44100
:
*
n
=
6272
;
break
;
case
48000
:
*
n
=
6144
;
break
;
case
88200
:
*
n
=
12544
;
break
;
case
96000
:
*
n
=
12288
;
break
;
case
176400
:
*
n
=
25088
;
break
;
case
192000
:
*
n
=
24576
;
break
;
default:
return
-
EINVAL
;
}
}
/* Calculate CTS. See HDMI 1.3a or 1.4a specifications */
*
cts
=
pclk
*
(
*
n
/
128
)
*
deep_color
/
(
sample_freq
/
10
);
if
(
core_cfg
.
use_mclk
)
core_cfg
.
mclk_mode
=
HDMI_AUDIO_MCLK_128FS
;
core_cfg
.
layout
=
HDMI_AUDIO_LAYOUT_2CH
;
core_cfg
.
en_spdif
=
false
;
/* Use sample frequency from channel status word */
core_cfg
.
fs_override
=
true
;
/* Enable ACR packets */
core_cfg
.
en_acr_pkt
=
true
;
/* Disable direct streaming digital audio */
core_cfg
.
en_dsd_audio
=
false
;
/* Use parallel audio interface */
core_cfg
.
en_parallel_aud_input
=
true
;
hdmi_core_audio_config
(
ip_data
,
&
core_cfg
);
/*
* Configure packet
* info frame audio see doc CEA861-D page 74
*/
aud_if_cfg
.
db1_coding_type
=
HDMI_INFOFRAME_AUDIO_DB1CT_FROM_STREAM
;
aud_if_cfg
.
db1_channel_count
=
2
;
aud_if_cfg
.
db2_sample_freq
=
HDMI_INFOFRAME_AUDIO_DB2SF_FROM_STREAM
;
aud_if_cfg
.
db2_sample_size
=
HDMI_INFOFRAME_AUDIO_DB2SS_FROM_STREAM
;
aud_if_cfg
.
db4_channel_alloc
=
0x00
;
aud_if_cfg
.
db5_downmix_inh
=
false
;
aud_if_cfg
.
db5_lsv
=
0
;
hdmi_core_audio_infoframe_config
(
ip_data
,
&
aud_if_cfg
);
return
0
;
}
static
int
hdmi_audio_startup
(
struct
snd_pcm_substream
*
substream
,
struct
snd_soc_dai
*
dai
)
int
hdmi_audio_enable
(
void
)
{
if
(
!
hdmi
.
ip_data
.
cfg
.
cm
.
mode
)
{
pr_err
(
"Current video settings do not support audio.
\n
"
);
return
-
EIO
;
}
return
0
;
DSSDBG
(
"audio_enable
\n
"
);
return
hdmi
.
ip_data
.
ops
->
audio_enable
(
&
hdmi
.
ip_data
);
}
static
int
hdmi_audio_codec_probe
(
struct
snd_soc_codec
*
codec
)
void
hdmi_audio_disable
(
void
)
{
struct
hdmi_ip_data
*
priv
=
&
hdmi
.
ip_data
;
DSSDBG
(
"audio_disable
\n
"
)
;
snd_soc_codec_set_drvdata
(
codec
,
priv
);
return
0
;
hdmi
.
ip_data
.
ops
->
audio_disable
(
&
hdmi
.
ip_data
);
}
static
struct
snd_soc_codec_driver
hdmi_audio_codec_drv
=
{
.
probe
=
hdmi_audio_codec_probe
,
};
static
struct
snd_soc_dai_ops
hdmi_audio_codec_ops
=
{
.
hw_params
=
hdmi_audio_hw_params
,
.
trigger
=
hdmi_audio_trigger
,
.
startup
=
hdmi_audio_startup
,
};
int
hdmi_audio_start
(
void
)
{
DSSDBG
(
"audio_start
\n
"
);
static
struct
snd_soc_dai_driver
hdmi_codec_dai_drv
=
{
.
name
=
"hdmi-audio-codec"
,
.
playback
=
{
.
channels_min
=
2
,
.
channels_max
=
2
,
.
rates
=
SNDRV_PCM_RATE_32000
|
SNDRV_PCM_RATE_44100
|
SNDRV_PCM_RATE_48000
,
.
formats
=
SNDRV_PCM_FMTBIT_S16_LE
|
SNDRV_PCM_FMTBIT_S24_LE
,
},
.
ops
=
&
hdmi_audio_codec_ops
,
};
#endif
return
hdmi
.
ip_data
.
ops
->
audio_start
(
&
hdmi
.
ip_data
);
}
static
int
hdmi_get_clocks
(
struct
platform_device
*
pdev
)
void
hdmi_audio_stop
(
void
)
{
struct
clk
*
clk
;
DSSDBG
(
"audio_stop
\n
"
)
;
clk
=
clk_get
(
&
pdev
->
dev
,
"sys_clk"
);
if
(
IS_ERR
(
clk
))
{
DSSERR
(
"can't get sys_clk
\n
"
);
return
PTR_ERR
(
clk
);
}
hdmi
.
sys_clk
=
clk
;
hdmi
.
ip_data
.
ops
->
audio_stop
(
&
hdmi
.
ip_data
);
}
return
0
;
bool
hdmi_mode_has_audio
(
void
)
{
if
(
hdmi
.
ip_data
.
cfg
.
cm
.
mode
==
HDMI_HDMI
)
return
true
;
else
return
false
;
}
static
void
hdmi_put_clocks
(
void
)
int
hdmi_audio_config
(
struct
omap_dss_audio
*
audio
)
{
if
(
hdmi
.
sys_clk
)
clk_put
(
hdmi
.
sys_clk
);
return
hdmi
.
ip_data
.
ops
->
audio_config
(
&
hdmi
.
ip_data
,
audio
);
}
#endif
static
void
__init
hdmi_probe_pdata
(
struct
platform_device
*
pdev
)
{
struct
omap_dss_board_info
*
pdata
=
pdev
->
dev
.
platform_data
;
...
...
@@ -838,17 +765,6 @@ static int __init omapdss_hdmihw_probe(struct platform_device *pdev)
hdmi_probe_pdata
(
pdev
);
#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
/* Register ASoC codec DAI */
r
=
snd_soc_register_codec
(
&
pdev
->
dev
,
&
hdmi_audio_codec_drv
,
&
hdmi_codec_dai_drv
,
1
);
if
(
r
)
{
DSSERR
(
"can't register ASoC HDMI audio codec
\n
"
);
return
r
;
}
#endif
return
0
;
}
...
...
@@ -858,11 +774,6 @@ static int __exit omapdss_hdmihw_remove(struct platform_device *pdev)
hdmi_panel_exit
();
#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
snd_soc_unregister_codec
(
&
pdev
->
dev
);
#endif
pm_runtime_disable
(
&
pdev
->
dev
);
hdmi_put_clocks
();
...
...
drivers/video/omap2/dss/hdmi_panel.c
浏览文件 @
037983e6
...
...
@@ -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
);
...
...
drivers/video/omap2/dss/ti_hdmi.h
浏览文件 @
037983e6
...
...
@@ -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
drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
浏览文件 @
037983e6
...
...
@@ -29,9 +29,14 @@
#include <linux/string.h>
#include <linux/seq_file.h>
#include <linux/gpio.h>
#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
#include <sound/asound.h>
#include <sound/asoundef.h>
#endif
#include "ti_hdmi_4xxx_ip.h"
#include "dss.h"
#include "dss_features.h"
static
inline
void
hdmi_write_reg
(
void
__iomem
*
base_addr
,
const
u16
idx
,
u32
val
)
...
...
@@ -699,9 +704,15 @@ static void hdmi_wp_init(struct omap_video_timings *timings,
}
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
)
{
REG_FLD_MOD
(
hdmi_wp_base
(
ip_data
),
HDMI_WP_VIDEO_CFG
,
true
,
31
,
31
);
return
0
;
}
void
ti_hdmi_4xxx_wp_video_stop
(
struct
hdmi_ip_data
*
ip_data
)
{
REG_FLD_MOD
(
hdmi_wp_base
(
ip_data
),
HDMI_WP_VIDEO_CFG
,
start
,
31
,
31
);
REG_FLD_MOD
(
hdmi_wp_base
(
ip_data
),
HDMI_WP_VIDEO_CFG
,
false
,
31
,
31
);
}
static
void
hdmi_wp_video_init_format
(
struct
hdmi_video_format
*
video_fmt
,
...
...
@@ -1014,9 +1025,8 @@ void ti_hdmi_4xxx_phy_dump(struct hdmi_ip_data *ip_data, struct seq_file *s)
DUMPPHY
(
HDMI_TXPHY_PAD_CFG_CTRL
);
}
#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
void
hdmi_wp_audio_config_format
(
struct
hdmi_ip_data
*
ip_data
,
#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
static
void
ti_hdmi_4xxx_wp_audio_config_format
(
struct
hdmi_ip_data
*
ip_data
,
struct
hdmi_audio_format
*
aud_fmt
)
{
u32
r
;
...
...
@@ -1035,7 +1045,7 @@ void hdmi_wp_audio_config_format(struct hdmi_ip_data *ip_data,
hdmi_write_reg
(
hdmi_wp_base
(
ip_data
),
HDMI_WP_AUDIO_CFG
,
r
);
}
void
hdmi
_wp_audio_config_dma
(
struct
hdmi_ip_data
*
ip_data
,
static
void
ti_hdmi_4xxx
_wp_audio_config_dma
(
struct
hdmi_ip_data
*
ip_data
,
struct
hdmi_audio_dma
*
aud_dma
)
{
u32
r
;
...
...
@@ -1053,7 +1063,7 @@ void hdmi_wp_audio_config_dma(struct hdmi_ip_data *ip_data,
hdmi_write_reg
(
hdmi_wp_base
(
ip_data
),
HDMI_WP_AUDIO_CTRL
,
r
);
}
void
hdmi
_core_audio_config
(
struct
hdmi_ip_data
*
ip_data
,
static
void
ti_hdmi_4xxx
_core_audio_config
(
struct
hdmi_ip_data
*
ip_data
,
struct
hdmi_core_audio_config
*
cfg
)
{
u32
r
;
...
...
@@ -1104,27 +1114,33 @@ void hdmi_core_audio_config(struct hdmi_ip_data *ip_data,
REG_FLD_MOD
(
av_base
,
HDMI_CORE_AV_SPDIF_CTRL
,
cfg
->
fs_override
,
1
,
1
);
/* I2S parameters */
REG_FLD_MOD
(
av_base
,
HDMI_CORE_AV_I2S_CHST4
,
cfg
->
freq_sample
,
3
,
0
);
/*
* Set IEC-60958-3 channel status word. It is passed to the IP
* just as it is received. The user of the driver is responsible
* for its contents.
*/
hdmi_write_reg
(
av_base
,
HDMI_CORE_AV_I2S_CHST0
,
cfg
->
iec60958_cfg
->
status
[
0
]);
hdmi_write_reg
(
av_base
,
HDMI_CORE_AV_I2S_CHST1
,
cfg
->
iec60958_cfg
->
status
[
1
]);
hdmi_write_reg
(
av_base
,
HDMI_CORE_AV_I2S_CHST2
,
cfg
->
iec60958_cfg
->
status
[
2
]);
/* yes, this is correct: status[3] goes to CHST4 register */
hdmi_write_reg
(
av_base
,
HDMI_CORE_AV_I2S_CHST4
,
cfg
->
iec60958_cfg
->
status
[
3
]);
/* yes, this is correct: status[4] goes to CHST5 register */
hdmi_write_reg
(
av_base
,
HDMI_CORE_AV_I2S_CHST5
,
cfg
->
iec60958_cfg
->
status
[
4
]);
/* set I2S parameters */
r
=
hdmi_read_reg
(
av_base
,
HDMI_CORE_AV_I2S_IN_CTRL
);
r
=
FLD_MOD
(
r
,
cfg
->
i2s_cfg
.
en_high_bitrate_aud
,
7
,
7
);
r
=
FLD_MOD
(
r
,
cfg
->
i2s_cfg
.
sck_edge_mode
,
6
,
6
);
r
=
FLD_MOD
(
r
,
cfg
->
i2s_cfg
.
cbit_order
,
5
,
5
);
r
=
FLD_MOD
(
r
,
cfg
->
i2s_cfg
.
vbit
,
4
,
4
);
r
=
FLD_MOD
(
r
,
cfg
->
i2s_cfg
.
ws_polarity
,
3
,
3
);
r
=
FLD_MOD
(
r
,
cfg
->
i2s_cfg
.
justification
,
2
,
2
);
r
=
FLD_MOD
(
r
,
cfg
->
i2s_cfg
.
direction
,
1
,
1
);
r
=
FLD_MOD
(
r
,
cfg
->
i2s_cfg
.
shift
,
0
,
0
);
hdmi_write_reg
(
av_base
,
HDMI_CORE_AV_I2S_IN_CTRL
,
r
);
r
=
hdmi_read_reg
(
av_base
,
HDMI_CORE_AV_I2S_CHST5
);
r
=
FLD_MOD
(
r
,
cfg
->
freq_sample
,
7
,
4
);
r
=
FLD_MOD
(
r
,
cfg
->
i2s_cfg
.
word_length
,
3
,
1
);
r
=
FLD_MOD
(
r
,
cfg
->
i2s_cfg
.
word_max_length
,
0
,
0
);
hdmi_write_reg
(
av_base
,
HDMI_CORE_AV_I2S_CHST5
,
r
);
REG_FLD_MOD
(
av_base
,
HDMI_CORE_AV_I2S_IN_LEN
,
cfg
->
i2s_cfg
.
in_length_bits
,
3
,
0
);
...
...
@@ -1136,12 +1152,19 @@ void hdmi_core_audio_config(struct hdmi_ip_data *ip_data,
r
=
FLD_MOD
(
r
,
cfg
->
en_parallel_aud_input
,
2
,
2
);
r
=
FLD_MOD
(
r
,
cfg
->
en_spdif
,
1
,
1
);
hdmi_write_reg
(
av_base
,
HDMI_CORE_AV_AUD_MODE
,
r
);
/* Audio channel mappings */
/* TODO: Make channel mapping dynamic. For now, map channels
* in the ALSA order: FL/FR/RL/RR/C/LFE/SL/SR. Remapping is needed as
* HDMI speaker order is different. See CEA-861 Section 6.6.2.
*/
hdmi_write_reg
(
av_base
,
HDMI_CORE_AV_I2S_IN_MAP
,
0x78
);
REG_FLD_MOD
(
av_base
,
HDMI_CORE_AV_SWAP_I2S
,
1
,
5
,
5
);
}
void
hdmi_core_audio_infoframe_confi
g
(
struct
hdmi_ip_data
*
ip_data
,
struct
hdmi_core_infoframe_audio
*
info_aud
)
static
void
ti_hdmi_4xxx_core_audio_infoframe_cf
g
(
struct
hdmi_ip_data
*
ip_data
,
struct
snd_cea_861_aud_if
*
info_aud
)
{
u8
val
;
u8
sum
=
0
,
checksum
=
0
;
void
__iomem
*
av_base
=
hdmi_av_base
(
ip_data
);
...
...
@@ -1155,24 +1178,23 @@ void hdmi_core_audio_infoframe_config(struct hdmi_ip_data *ip_data,
hdmi_write_reg
(
av_base
,
HDMI_CORE_AV_AUDIO_LEN
,
0x0a
);
sum
+=
0x84
+
0x001
+
0x00a
;
val
=
(
info_aud
->
db1_coding_type
<<
4
)
|
(
info_aud
->
db1_channel_count
-
1
);
hdmi_write_reg
(
av_base
,
HDMI_CORE_AV_AUD_DBYTE
(
0
),
val
);
sum
+=
val
;
hdmi_write_reg
(
av_base
,
HDMI_CORE_AV_AUD_DBYTE
(
0
),
info_aud
->
db1_ct_cc
);
sum
+=
info_aud
->
db1_ct_cc
;
val
=
(
info_aud
->
db2_sample_freq
<<
2
)
|
info_aud
->
db2_sample_size
;
hdmi_write_reg
(
av_base
,
HDMI_CORE_AV_AUD_DBYTE
(
1
),
val
);
sum
+=
val
;
hdmi_write_reg
(
av_base
,
HDMI_CORE_AV_AUD_DBYTE
(
1
),
info_aud
->
db2_sf_ss
);
sum
+=
info_aud
->
db2_sf_ss
;
hdmi_write_reg
(
av_base
,
HDMI_CORE_AV_AUD_DBYTE
(
2
),
0x00
);
hdmi_write_reg
(
av_base
,
HDMI_CORE_AV_AUD_DBYTE
(
2
),
info_aud
->
db3
);
sum
+=
info_aud
->
db3
;
val
=
info_aud
->
db4_channel_alloc
;
hdmi_write_reg
(
av_base
,
HDMI_CORE_AV_AUD_DBYTE
(
3
),
val
);
sum
+=
val
;
hdmi_write_reg
(
av_base
,
HDMI_CORE_AV_AUD_DBYTE
(
3
),
info_aud
->
db4_ca
);
sum
+=
info_aud
->
db4_ca
;
val
=
(
info_aud
->
db5_downmix_inh
<<
7
)
|
(
info_aud
->
db5_lsv
<<
3
);
hdmi_write_reg
(
av_base
,
HDMI_CORE_AV_AUD_DBYTE
(
4
),
val
);
sum
+=
val
;
hdmi_write_reg
(
av_base
,
HDMI_CORE_AV_AUD_DBYTE
(
4
),
info_aud
->
db5_dminh_lsv
);
sum
+=
info_aud
->
db5_dminh_lsv
;
hdmi_write_reg
(
av_base
,
HDMI_CORE_AV_AUD_DBYTE
(
5
),
0x00
);
hdmi_write_reg
(
av_base
,
HDMI_CORE_AV_AUD_DBYTE
(
6
),
0x00
);
...
...
@@ -1190,70 +1212,212 @@ void hdmi_core_audio_infoframe_config(struct hdmi_ip_data *ip_data,
*/
}
int
hdmi_config_audio_acr
(
struct
hdmi_ip_data
*
ip_data
,
u32
sample_freq
,
u32
*
n
,
u32
*
cts
)
int
ti_hdmi_4xxx_audio_config
(
struct
hdmi_ip_data
*
ip_data
,
struct
omap_dss_audio
*
audio
)
{
u32
r
;
u32
deep_color
=
0
;
u32
pclk
=
ip_data
->
cfg
.
timings
.
pixel_clock
;
if
(
n
==
NULL
||
cts
==
NULL
)
struct
hdmi_audio_format
audio_format
;
struct
hdmi_audio_dma
audio_dma
;
struct
hdmi_core_audio_config
core
;
int
err
,
n
,
cts
,
channel_count
;
unsigned
int
fs_nr
;
bool
word_length_16b
=
false
;
if
(
!
audio
||
!
audio
->
iec
||
!
audio
->
cea
||
!
ip_data
)
return
-
EINVAL
;
core
.
iec60958_cfg
=
audio
->
iec
;
/*
* In the IEC-60958 status word, check if the audio sample word length
* is 16-bit as several optimizations can be performed in such case.
*/
if
(
!
(
audio
->
iec
->
status
[
4
]
&
IEC958_AES4_CON_MAX_WORDLEN_24
))
if
(
audio
->
iec
->
status
[
4
]
&
IEC958_AES4_CON_WORDLEN_20_16
)
word_length_16b
=
true
;
/* I2S configuration. See Phillips' specification */
if
(
word_length_16b
)
core
.
i2s_cfg
.
justification
=
HDMI_AUDIO_JUSTIFY_LEFT
;
else
core
.
i2s_cfg
.
justification
=
HDMI_AUDIO_JUSTIFY_RIGHT
;
/*
* Obtain current deep color configuration. This needed
* to calculate the TMDS clock based on the pixel clock.
* The I2S input word length is twice the lenght given in the IEC-60958
* status word. If the word size is greater than
* 20 bits, increment by one.
*/
r
=
REG_GET
(
hdmi_wp_base
(
ip_data
),
HDMI_WP_VIDEO_CFG
,
1
,
0
);
switch
(
r
)
{
case
1
:
/* No deep color selected */
deep_color
=
100
;
core
.
i2s_cfg
.
in_length_bits
=
audio
->
iec
->
status
[
4
]
&
IEC958_AES4_CON_WORDLEN
;
if
(
audio
->
iec
->
status
[
4
]
&
IEC958_AES4_CON_MAX_WORDLEN_24
)
core
.
i2s_cfg
.
in_length_bits
++
;
core
.
i2s_cfg
.
sck_edge_mode
=
HDMI_AUDIO_I2S_SCK_EDGE_RISING
;
core
.
i2s_cfg
.
vbit
=
HDMI_AUDIO_I2S_VBIT_FOR_PCM
;
core
.
i2s_cfg
.
direction
=
HDMI_AUDIO_I2S_MSB_SHIFTED_FIRST
;
core
.
i2s_cfg
.
shift
=
HDMI_AUDIO_I2S_FIRST_BIT_SHIFT
;
/* convert sample frequency to a number */
switch
(
audio
->
iec
->
status
[
3
]
&
IEC958_AES3_CON_FS
)
{
case
IEC958_AES3_CON_FS_32000
:
fs_nr
=
32000
;
break
;
case
IEC958_AES3_CON_FS_44100
:
fs_nr
=
44100
;
break
;
case
IEC958_AES3_CON_FS_48000
:
fs_nr
=
48000
;
break
;
case
2
:
/* 10-bit deep color selected */
deep_color
=
125
;
case
IEC958_AES3_CON_FS_88200
:
fs_nr
=
88200
;
break
;
case
3
:
/* 12-bit deep color selected */
deep_color
=
150
;
case
IEC958_AES3_CON_FS_96000
:
fs_nr
=
96000
;
break
;
case
IEC958_AES3_CON_FS_176400
:
fs_nr
=
176400
;
break
;
case
IEC958_AES3_CON_FS_192000
:
fs_nr
=
192000
;
break
;
default:
return
-
EINVAL
;
}
switch
(
sample_freq
)
{
case
32000
:
if
((
deep_color
==
125
)
&&
((
pclk
==
54054
)
||
(
pclk
==
74250
)))
*
n
=
8192
;
else
*
n
=
4096
;
err
=
hdmi_compute_acr
(
fs_nr
,
&
n
,
&
cts
);
/* Audio clock regeneration settings */
core
.
n
=
n
;
core
.
cts
=
cts
;
if
(
dss_has_feature
(
FEAT_HDMI_CTS_SWMODE
))
{
core
.
aud_par_busclk
=
0
;
core
.
cts_mode
=
HDMI_AUDIO_CTS_MODE_SW
;
core
.
use_mclk
=
dss_has_feature
(
FEAT_HDMI_AUDIO_USE_MCLK
);
}
else
{
core
.
aud_par_busclk
=
(((
128
*
31
)
-
1
)
<<
8
);
core
.
cts_mode
=
HDMI_AUDIO_CTS_MODE_HW
;
core
.
use_mclk
=
true
;
}
if
(
core
.
use_mclk
)
core
.
mclk_mode
=
HDMI_AUDIO_MCLK_128FS
;
/* Audio channels settings */
channel_count
=
(
audio
->
cea
->
db1_ct_cc
&
CEA861_AUDIO_INFOFRAME_DB1CC
)
+
1
;
switch
(
channel_count
)
{
case
2
:
audio_format
.
active_chnnls_msk
=
0x03
;
break
;
case
3
:
audio_format
.
active_chnnls_msk
=
0x07
;
break
;
case
4
:
audio_format
.
active_chnnls_msk
=
0x0f
;
break
;
case
5
:
audio_format
.
active_chnnls_msk
=
0x1f
;
break
;
case
44100
:
*
n
=
6272
;
case
6
:
audio_format
.
active_chnnls_msk
=
0x3f
;
break
;
case
48000
:
if
((
deep_color
==
125
)
&&
((
pclk
==
54054
)
||
(
pclk
==
74250
)))
*
n
=
8192
;
else
*
n
=
6144
;
case
7
:
audio_format
.
active_chnnls_msk
=
0x7f
;
break
;
case
8
:
audio_format
.
active_chnnls_msk
=
0xff
;
break
;
default:
*
n
=
0
;
return
-
EINVAL
;
}
/* Calculate CTS. See HDMI 1.3a or 1.4a specifications */
*
cts
=
pclk
*
(
*
n
/
128
)
*
deep_color
/
(
sample_freq
/
10
);
/*
* the HDMI IP needs to enable four stereo channels when transmitting
* more than 2 audio channels
*/
if
(
channel_count
==
2
)
{
audio_format
.
stereo_channels
=
HDMI_AUDIO_STEREO_ONECHANNEL
;
core
.
i2s_cfg
.
active_sds
=
HDMI_AUDIO_I2S_SD0_EN
;
core
.
layout
=
HDMI_AUDIO_LAYOUT_2CH
;
}
else
{
audio_format
.
stereo_channels
=
HDMI_AUDIO_STEREO_FOURCHANNELS
;
core
.
i2s_cfg
.
active_sds
=
HDMI_AUDIO_I2S_SD0_EN
|
HDMI_AUDIO_I2S_SD1_EN
|
HDMI_AUDIO_I2S_SD2_EN
|
HDMI_AUDIO_I2S_SD3_EN
;
core
.
layout
=
HDMI_AUDIO_LAYOUT_8CH
;
}
core
.
en_spdif
=
false
;
/* use sample frequency from channel status word */
core
.
fs_override
=
true
;
/* enable ACR packets */
core
.
en_acr_pkt
=
true
;
/* disable direct streaming digital audio */
core
.
en_dsd_audio
=
false
;
/* use parallel audio interface */
core
.
en_parallel_aud_input
=
true
;
/* DMA settings */
if
(
word_length_16b
)
audio_dma
.
transfer_size
=
0x10
;
else
audio_dma
.
transfer_size
=
0x20
;
audio_dma
.
block_size
=
0xC0
;
audio_dma
.
mode
=
HDMI_AUDIO_TRANSF_DMA
;
audio_dma
.
fifo_threshold
=
0x20
;
/* in number of samples */
/* audio FIFO format settings */
if
(
word_length_16b
)
{
audio_format
.
samples_per_word
=
HDMI_AUDIO_ONEWORD_TWOSAMPLES
;
audio_format
.
sample_size
=
HDMI_AUDIO_SAMPLE_16BITS
;
audio_format
.
justification
=
HDMI_AUDIO_JUSTIFY_LEFT
;
}
else
{
audio_format
.
samples_per_word
=
HDMI_AUDIO_ONEWORD_ONESAMPLE
;
audio_format
.
sample_size
=
HDMI_AUDIO_SAMPLE_24BITS
;
audio_format
.
justification
=
HDMI_AUDIO_JUSTIFY_RIGHT
;
}
audio_format
.
type
=
HDMI_AUDIO_TYPE_LPCM
;
audio_format
.
sample_order
=
HDMI_AUDIO_SAMPLE_LEFT_FIRST
;
/* disable start/stop signals of IEC 60958 blocks */
audio_format
.
en_sig_blk_strt_end
=
HDMI_AUDIO_BLOCK_SIG_STARTEND_ON
;
/* configure DMA and audio FIFO format*/
ti_hdmi_4xxx_wp_audio_config_dma
(
ip_data
,
&
audio_dma
);
ti_hdmi_4xxx_wp_audio_config_format
(
ip_data
,
&
audio_format
);
/* configure the core*/
ti_hdmi_4xxx_core_audio_config
(
ip_data
,
&
core
);
/* configure CEA 861 audio infoframe*/
ti_hdmi_4xxx_core_audio_infoframe_cfg
(
ip_data
,
audio
->
cea
);
return
0
;
}
int
ti_hdmi_4xxx_wp_audio_enable
(
struct
hdmi_ip_data
*
ip_data
)
{
REG_FLD_MOD
(
hdmi_wp_base
(
ip_data
),
HDMI_WP_AUDIO_CTRL
,
true
,
31
,
31
);
return
0
;
}
void
ti_hdmi_4xxx_wp_audio_enable
(
struct
hdmi_ip_data
*
ip_data
,
bool
enable
)
void
ti_hdmi_4xxx_wp_audio_disable
(
struct
hdmi_ip_data
*
ip_data
)
{
REG_FLD_MOD
(
hdmi_wp_base
(
ip_data
),
HDMI_WP_AUDIO_CTRL
,
false
,
31
,
31
);
}
int
ti_hdmi_4xxx_audio_start
(
struct
hdmi_ip_data
*
ip_data
)
{
REG_FLD_MOD
(
hdmi_av_base
(
ip_data
),
HDMI_CORE_AV_AUD_MODE
,
enabl
e
,
0
,
0
);
HDMI_CORE_AV_AUD_MODE
,
tru
e
,
0
,
0
);
REG_FLD_MOD
(
hdmi_wp_base
(
ip_data
),
HDMI_WP_AUDIO_CTRL
,
enable
,
31
,
31
);
HDMI_WP_AUDIO_CTRL
,
true
,
30
,
30
);
return
0
;
}
void
ti_hdmi_4xxx_audio_stop
(
struct
hdmi_ip_data
*
ip_data
)
{
REG_FLD_MOD
(
hdmi_av_base
(
ip_data
),
HDMI_CORE_AV_AUD_MODE
,
false
,
0
,
0
);
REG_FLD_MOD
(
hdmi_wp_base
(
ip_data
),
HDMI_WP_AUDIO_CTRL
,
enabl
e
,
30
,
30
);
HDMI_WP_AUDIO_CTRL
,
fals
e
,
30
,
30
);
}
#endif
drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h
浏览文件 @
037983e6
...
...
@@ -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
include/video/omapdss.h
浏览文件 @
037983e6
...
...
@@ -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%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录