Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
kernel_linux
提交
3315764e
K
kernel_linux
项目概览
OpenHarmony
/
kernel_linux
上一次同步 4 年多
通知
15
Star
8
Fork
2
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
kernel_linux
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
3315764e
编写于
12月 08, 2014
作者:
T
Tomi Valkeinen
浏览文件
操作
浏览文件
下载
差异文件
Merge branches '3.19/omapdss' and '3.19/simplefb' into fbdev
Merge fbdev topic branches.
上级
34685627
f3b7d0ef
b14c9929
变更
39
显示空白变更内容
内联
并排
Showing
39 changed file
with
2352 addition
and
1709 deletion
+2352
-1709
Documentation/devicetree/bindings/video/simple-framebuffer-sunxi.txt
...on/devicetree/bindings/video/simple-framebuffer-sunxi.txt
+33
-0
Documentation/devicetree/bindings/video/simple-framebuffer.txt
...entation/devicetree/bindings/video/simple-framebuffer.txt
+64
-4
MAINTAINERS
MAINTAINERS
+8
-0
drivers/video/console/fbcon.c
drivers/video/console/fbcon.c
+1
-1
drivers/video/fbdev/omap2/displays-new/connector-hdmi.c
drivers/video/fbdev/omap2/displays-new/connector-hdmi.c
+0
-99
drivers/video/fbdev/omap2/displays-new/encoder-tfp410.c
drivers/video/fbdev/omap2/displays-new/encoder-tfp410.c
+1
-0
drivers/video/fbdev/omap2/displays-new/encoder-tpd12s015.c
drivers/video/fbdev/omap2/displays-new/encoder-tpd12s015.c
+1
-56
drivers/video/fbdev/omap2/dss/Kconfig
drivers/video/fbdev/omap2/dss/Kconfig
+0
-7
drivers/video/fbdev/omap2/dss/Makefile
drivers/video/fbdev/omap2/dss/Makefile
+1
-1
drivers/video/fbdev/omap2/dss/dispc.c
drivers/video/fbdev/omap2/dss/dispc.c
+10
-10
drivers/video/fbdev/omap2/dss/dpi.c
drivers/video/fbdev/omap2/dss/dpi.c
+202
-125
drivers/video/fbdev/omap2/dss/dsi.c
drivers/video/fbdev/omap2/dss/dsi.c
+240
-419
drivers/video/fbdev/omap2/dss/dss-of.c
drivers/video/fbdev/omap2/dss/dss-of.c
+40
-18
drivers/video/fbdev/omap2/dss/dss.c
drivers/video/fbdev/omap2/dss/dss.c
+86
-37
drivers/video/fbdev/omap2/dss/dss.h
drivers/video/fbdev/omap2/dss/dss.h
+117
-108
drivers/video/fbdev/omap2/dss/dss_features.c
drivers/video/fbdev/omap2/dss/dss_features.c
+0
-42
drivers/video/fbdev/omap2/dss/dss_features.h
drivers/video/fbdev/omap2/dss/dss_features.h
+0
-12
drivers/video/fbdev/omap2/dss/hdmi.h
drivers/video/fbdev/omap2/dss/hdmi.h
+42
-29
drivers/video/fbdev/omap2/dss/hdmi4.c
drivers/video/fbdev/omap2/dss/hdmi4.c
+160
-178
drivers/video/fbdev/omap2/dss/hdmi4_core.c
drivers/video/fbdev/omap2/dss/hdmi4_core.c
+0
-14
drivers/video/fbdev/omap2/dss/hdmi4_core.h
drivers/video/fbdev/omap2/dss/hdmi4_core.h
+0
-4
drivers/video/fbdev/omap2/dss/hdmi5.c
drivers/video/fbdev/omap2/dss/hdmi5.c
+165
-173
drivers/video/fbdev/omap2/dss/hdmi5_core.c
drivers/video/fbdev/omap2/dss/hdmi5_core.c
+4
-7
drivers/video/fbdev/omap2/dss/hdmi5_core.h
drivers/video/fbdev/omap2/dss/hdmi5_core.h
+0
-2
drivers/video/fbdev/omap2/dss/hdmi_common.c
drivers/video/fbdev/omap2/dss/hdmi_common.c
+0
-2
drivers/video/fbdev/omap2/dss/hdmi_phy.c
drivers/video/fbdev/omap2/dss/hdmi_phy.c
+11
-20
drivers/video/fbdev/omap2/dss/hdmi_pll.c
drivers/video/fbdev/omap2/dss/hdmi_pll.c
+137
-176
drivers/video/fbdev/omap2/dss/hdmi_wp.c
drivers/video/fbdev/omap2/dss/hdmi_wp.c
+12
-4
drivers/video/fbdev/omap2/dss/output.c
drivers/video/fbdev/omap2/dss/output.c
+16
-3
drivers/video/fbdev/omap2/dss/pll.c
drivers/video/fbdev/omap2/dss/pll.c
+378
-0
drivers/video/fbdev/omap2/dss/sdi.c
drivers/video/fbdev/omap2/dss/sdi.c
+1
-1
drivers/video/fbdev/simplefb.c
drivers/video/fbdev/simplefb.c
+151
-11
include/linux/of.h
include/linux/of.h
+1
-2
include/sound/omap-hdmi-audio.h
include/sound/omap-hdmi-audio.h
+43
-0
include/video/omapdss.h
include/video/omapdss.h
+4
-41
sound/soc/omap/Kconfig
sound/soc/omap/Kconfig
+14
-12
sound/soc/omap/Makefile
sound/soc/omap/Makefile
+2
-4
sound/soc/omap/omap-hdmi-audio.c
sound/soc/omap/omap-hdmi-audio.c
+407
-0
sound/soc/omap/omap-hdmi-card.c
sound/soc/omap/omap-hdmi-card.c
+0
-87
未找到文件。
Documentation/devicetree/bindings/video/simple-framebuffer-sunxi.txt
0 → 100644
浏览文件 @
3315764e
Sunxi specific Simple Framebuffer bindings
This binding documents sunxi specific extensions to the simple-framebuffer
bindings. The sunxi simplefb u-boot code relies on the devicetree containing
pre-populated simplefb nodes.
These extensions are intended so that u-boot can select the right node based
on which pipeline is being used. As such they are solely intended for
firmware / bootloader use, and the OS should ignore them.
Required properties:
- compatible: "allwinner,simple-framebuffer"
- allwinner,pipeline, one of:
"de_be0-lcd0"
"de_be1-lcd1"
"de_be0-lcd0-hdmi"
"de_be1-lcd1-hdmi"
Example:
chosen {
#address-cells = <1>;
#size-cells = <1>;
ranges;
framebuffer@0 {
compatible = "allwinner,simple-framebuffer", "simple-framebuffer";
allwinner,pipeline = "de_be0-lcd0-hdmi";
clocks = <&pll5 1>, <&ahb_gates 36>, <&ahb_gates 43>,
<&ahb_gates 44>;
status = "disabled";
};
};
Documentation/devicetree/bindings/video/simple-framebuffer.txt
浏览文件 @
3315764e
Simple Framebuffer
A simple frame-buffer describes a raw memory region that may be rendered to,
with the assumption that the display hardware has already been set up to scan
out from that buffer.
A simple frame-buffer describes a frame-buffer setup by firmware or
the bootloader, with the assumption that the display hardware has already
been set up to scan out from the memory pointed to by the reg property.
Since simplefb nodes represent runtime information they must be sub-nodes of
the chosen node (*). Simplefb nodes must be named "framebuffer@<address>".
If the devicetree contains nodes for the display hardware used by a simplefb,
then the simplefb node must contain a property called "display", which
contains a phandle pointing to the primary display hw node, so that the OS
knows which simplefb to disable when handing over control to a driver for the
real hardware. The bindings for the hw nodes must specify which node is
considered the primary node.
It is advised to add display# aliases to help the OS determine how to number
things. If display# aliases are used, then if the simplefb node contains a
"display" property then the /aliases/display# path must point to the display
hw node the "display" property points to, otherwise it must point directly
to the simplefb node.
If a simplefb node represents the preferred console for user interaction,
then the chosen node's stdout-path property should point to it, or to the
primary display hw node, as with display# aliases. If display aliases are
used then it should be set to the alias instead.
It is advised that devicetree files contain pre-filled, disabled framebuffer
nodes, so that the firmware only needs to update the mode information and
enable them. This way if e.g. later on support for more display clocks get
added, the simplefb nodes will already contain this info and the firmware
does not need to be updated.
If pre-filled framebuffer nodes are used, the firmware may need extra
information to find the right node. In that case an extra platform specific
compatible and platform specific properties should be used and documented,
see e.g. simple-framebuffer-sunxi.txt .
Required properties:
- compatible: "simple-framebuffer"
...
...
@@ -14,13 +46,41 @@ Required properties:
- r5g6b5 (16-bit pixels, d[15:11]=r, d[10:5]=g, d[4:0]=b).
- a8b8g8r8 (32-bit pixels, d[31:24]=a, d[23:16]=b, d[15:8]=g, d[7:0]=r).
Optional properties:
- clocks : List of clocks used by the framebuffer. Clocks listed here
are expected to already be configured correctly. The OS must
ensure these clocks are not modified or disabled while the
simple framebuffer remains active.
- display : phandle pointing to the primary display hardware node
Example:
framebuffer {
aliases {
display0 = &lcdc0;
}
chosen {
framebuffer0: framebuffer@1d385000 {
compatible = "simple-framebuffer";
reg = <0x1d385000 (1600 * 1200 * 2)>;
width = <1600>;
height = <1200>;
stride = <(1600 * 2)>;
format = "r5g6b5";
clocks = <&ahb_gates 36>, <&ahb_gates 43>, <&ahb_gates 44>;
display = <&lcdc0>;
};
stdout-path = "display0";
};
soc@01c00000 {
lcdc0: lcdc@1c0c000 {
compatible = "allwinner,sun4i-a10-lcdc";
...
};
};
*) Older devicetree files may have a compatible = "simple-framebuffer" node
in a different place, operating systems must first enumerate any compatible
nodes found under chosen and then check for other compatible nodes.
MAINTAINERS
浏览文件 @
3315764e
...
...
@@ -8442,6 +8442,14 @@ F: drivers/media/usb/siano/
F: drivers/media/usb/siano/
F: drivers/media/mmc/siano/
SIMPLEFB FB DRIVER
M: Hans de Goede <hdegoede@redhat.com>
L: linux-fbdev@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/video/simple-framebuffer.txt
F: drivers/video/fbdev/simplefb.c
F: include/linux/platform_data/simplefb.h
SH_VEU V4L2 MEM2MEM DRIVER
L: linux-media@vger.kernel.org
S: Orphan
...
...
drivers/video/console/fbcon.c
浏览文件 @
3315764e
...
...
@@ -3624,7 +3624,7 @@ static int __init fb_console_init(void)
return
0
;
}
module_init
(
fb_console_init
);
fs_initcall
(
fb_console_init
);
#ifdef MODULE
...
...
drivers/video/fbdev/omap2/displays-new/connector-hdmi.c
浏览文件 @
3315764e
...
...
@@ -170,98 +170,6 @@ static bool hdmic_detect(struct omap_dss_device *dssdev)
return
in
->
ops
.
hdmi
->
detect
(
in
);
}
static
int
hdmic_audio_enable
(
struct
omap_dss_device
*
dssdev
)
{
struct
panel_drv_data
*
ddata
=
to_panel_data
(
dssdev
);
struct
omap_dss_device
*
in
=
ddata
->
in
;
int
r
;
/* enable audio only if the display is active */
if
(
!
omapdss_device_is_enabled
(
dssdev
))
return
-
EPERM
;
r
=
in
->
ops
.
hdmi
->
audio_enable
(
in
);
if
(
r
)
return
r
;
dssdev
->
audio_state
=
OMAP_DSS_AUDIO_ENABLED
;
return
0
;
}
static
void
hdmic_audio_disable
(
struct
omap_dss_device
*
dssdev
)
{
struct
panel_drv_data
*
ddata
=
to_panel_data
(
dssdev
);
struct
omap_dss_device
*
in
=
ddata
->
in
;
in
->
ops
.
hdmi
->
audio_disable
(
in
);
dssdev
->
audio_state
=
OMAP_DSS_AUDIO_DISABLED
;
}
static
int
hdmic_audio_start
(
struct
omap_dss_device
*
dssdev
)
{
struct
panel_drv_data
*
ddata
=
to_panel_data
(
dssdev
);
struct
omap_dss_device
*
in
=
ddata
->
in
;
int
r
;
/*
* No need to check the panel state. It was checked when trasitioning
* to AUDIO_ENABLED.
*/
if
(
dssdev
->
audio_state
!=
OMAP_DSS_AUDIO_ENABLED
)
return
-
EPERM
;
r
=
in
->
ops
.
hdmi
->
audio_start
(
in
);
if
(
r
)
return
r
;
dssdev
->
audio_state
=
OMAP_DSS_AUDIO_PLAYING
;
return
0
;
}
static
void
hdmic_audio_stop
(
struct
omap_dss_device
*
dssdev
)
{
struct
panel_drv_data
*
ddata
=
to_panel_data
(
dssdev
);
struct
omap_dss_device
*
in
=
ddata
->
in
;
in
->
ops
.
hdmi
->
audio_stop
(
in
);
dssdev
->
audio_state
=
OMAP_DSS_AUDIO_ENABLED
;
}
static
bool
hdmic_audio_supported
(
struct
omap_dss_device
*
dssdev
)
{
struct
panel_drv_data
*
ddata
=
to_panel_data
(
dssdev
);
struct
omap_dss_device
*
in
=
ddata
->
in
;
if
(
!
omapdss_device_is_enabled
(
dssdev
))
return
false
;
return
in
->
ops
.
hdmi
->
audio_supported
(
in
);
}
static
int
hdmic_audio_config
(
struct
omap_dss_device
*
dssdev
,
struct
omap_dss_audio
*
audio
)
{
struct
panel_drv_data
*
ddata
=
to_panel_data
(
dssdev
);
struct
omap_dss_device
*
in
=
ddata
->
in
;
int
r
;
/* config audio only if the display is active */
if
(
!
omapdss_device_is_enabled
(
dssdev
))
return
-
EPERM
;
r
=
in
->
ops
.
hdmi
->
audio_config
(
in
,
audio
);
if
(
r
)
return
r
;
dssdev
->
audio_state
=
OMAP_DSS_AUDIO_CONFIGURED
;
return
0
;
}
static
int
hdmic_set_hdmi_mode
(
struct
omap_dss_device
*
dssdev
,
bool
hdmi_mode
)
{
struct
panel_drv_data
*
ddata
=
to_panel_data
(
dssdev
);
...
...
@@ -296,13 +204,6 @@ static struct omap_dss_driver hdmic_driver = {
.
detect
=
hdmic_detect
,
.
set_hdmi_mode
=
hdmic_set_hdmi_mode
,
.
set_hdmi_infoframe
=
hdmic_set_infoframe
,
.
audio_enable
=
hdmic_audio_enable
,
.
audio_disable
=
hdmic_audio_disable
,
.
audio_start
=
hdmic_audio_start
,
.
audio_stop
=
hdmic_audio_stop
,
.
audio_supported
=
hdmic_audio_supported
,
.
audio_config
=
hdmic_audio_config
,
};
static
int
hdmic_probe_pdata
(
struct
platform_device
*
pdev
)
...
...
drivers/video/fbdev/omap2/displays-new/encoder-tfp410.c
浏览文件 @
3315764e
...
...
@@ -249,6 +249,7 @@ static int tfp410_probe(struct platform_device *pdev)
dssdev
->
output_type
=
OMAP_DISPLAY_TYPE_DVI
;
dssdev
->
owner
=
THIS_MODULE
;
dssdev
->
phy
.
dpi
.
data_lines
=
ddata
->
data_lines
;
dssdev
->
port_num
=
1
;
r
=
omapdss_register_output
(
dssdev
);
if
(
r
)
{
...
...
drivers/video/fbdev/omap2/displays-new/encoder-tpd12s015.c
浏览文件 @
3315764e
...
...
@@ -193,55 +193,6 @@ static bool tpd_detect(struct omap_dss_device *dssdev)
return
gpio_get_value_cansleep
(
ddata
->
hpd_gpio
);
}
static
int
tpd_audio_enable
(
struct
omap_dss_device
*
dssdev
)
{
struct
panel_drv_data
*
ddata
=
to_panel_data
(
dssdev
);
struct
omap_dss_device
*
in
=
ddata
->
in
;
return
in
->
ops
.
hdmi
->
audio_enable
(
in
);
}
static
void
tpd_audio_disable
(
struct
omap_dss_device
*
dssdev
)
{
struct
panel_drv_data
*
ddata
=
to_panel_data
(
dssdev
);
struct
omap_dss_device
*
in
=
ddata
->
in
;
in
->
ops
.
hdmi
->
audio_disable
(
in
);
}
static
int
tpd_audio_start
(
struct
omap_dss_device
*
dssdev
)
{
struct
panel_drv_data
*
ddata
=
to_panel_data
(
dssdev
);
struct
omap_dss_device
*
in
=
ddata
->
in
;
return
in
->
ops
.
hdmi
->
audio_start
(
in
);
}
static
void
tpd_audio_stop
(
struct
omap_dss_device
*
dssdev
)
{
struct
panel_drv_data
*
ddata
=
to_panel_data
(
dssdev
);
struct
omap_dss_device
*
in
=
ddata
->
in
;
in
->
ops
.
hdmi
->
audio_stop
(
in
);
}
static
bool
tpd_audio_supported
(
struct
omap_dss_device
*
dssdev
)
{
struct
panel_drv_data
*
ddata
=
to_panel_data
(
dssdev
);
struct
omap_dss_device
*
in
=
ddata
->
in
;
return
in
->
ops
.
hdmi
->
audio_supported
(
in
);
}
static
int
tpd_audio_config
(
struct
omap_dss_device
*
dssdev
,
struct
omap_dss_audio
*
audio
)
{
struct
panel_drv_data
*
ddata
=
to_panel_data
(
dssdev
);
struct
omap_dss_device
*
in
=
ddata
->
in
;
return
in
->
ops
.
hdmi
->
audio_config
(
in
,
audio
);
}
static
int
tpd_set_infoframe
(
struct
omap_dss_device
*
dssdev
,
const
struct
hdmi_avi_infoframe
*
avi
)
{
...
...
@@ -275,13 +226,6 @@ static const struct omapdss_hdmi_ops tpd_hdmi_ops = {
.
detect
=
tpd_detect
,
.
set_infoframe
=
tpd_set_infoframe
,
.
set_hdmi_mode
=
tpd_set_hdmi_mode
,
.
audio_enable
=
tpd_audio_enable
,
.
audio_disable
=
tpd_audio_disable
,
.
audio_start
=
tpd_audio_start
,
.
audio_stop
=
tpd_audio_stop
,
.
audio_supported
=
tpd_audio_supported
,
.
audio_config
=
tpd_audio_config
,
};
static
int
tpd_probe_pdata
(
struct
platform_device
*
pdev
)
...
...
@@ -409,6 +353,7 @@ static int tpd_probe(struct platform_device *pdev)
dssdev
->
type
=
OMAP_DISPLAY_TYPE_HDMI
;
dssdev
->
output_type
=
OMAP_DISPLAY_TYPE_HDMI
;
dssdev
->
owner
=
THIS_MODULE
;
dssdev
->
port_num
=
1
;
in
=
ddata
->
in
;
...
...
drivers/video/fbdev/omap2/dss/Kconfig
浏览文件 @
3315764e
...
...
@@ -74,9 +74,6 @@ config OMAP4_DSS_HDMI
help
HDMI support for OMAP4 based SoCs.
config OMAP4_DSS_HDMI_AUDIO
bool
config OMAP5_DSS_HDMI
bool "HDMI support for OMAP5"
default n
...
...
@@ -86,10 +83,6 @@ config OMAP5_DSS_HDMI
Definition Multimedia Interface. See http://www.hdmi.org/ for HDMI
specification.
config OMAP5_DSS_HDMI_AUDIO
depends on OMAP5_DSS_HDMI
bool
config OMAP2_DSS_SDI
bool "SDI support"
default n
...
...
drivers/video/fbdev/omap2/dss/Makefile
浏览文件 @
3315764e
...
...
@@ -2,7 +2,7 @@ obj-$(CONFIG_OMAP2_DSS_INIT) += omapdss-boot-init.o
obj-$(CONFIG_OMAP2_DSS)
+=
omapdss.o
# Core DSS files
omapdss-y
:=
core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o
\
output.o dss-of.o
output.o dss-of.o
pll.o
# DSS compat layer files
omapdss-y
+=
manager.o manager-sysfs.o overlay.o overlay-sysfs.o apply.o
\
dispc-compat.o display-sysfs.o
...
...
drivers/video/fbdev/omap2/dss/dispc.c
浏览文件 @
3315764e
...
...
@@ -3028,7 +3028,7 @@ static void dispc_mgr_get_lcd_divisor(enum omap_channel channel, int *lck_div,
unsigned
long
dispc_fclk_rate
(
void
)
{
struct
platform_device
*
dsidev
;
struct
dss_pll
*
pll
;
unsigned
long
r
=
0
;
switch
(
dss_get_dispc_clk_source
())
{
...
...
@@ -3036,12 +3036,12 @@ unsigned long dispc_fclk_rate(void)
r
=
dss_get_dispc_clk_rate
();
break
;
case
OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC
:
dsidev
=
dsi_get_dsidev_from_id
(
0
);
r
=
dsi_get_pll_hsdiv_dispc_rate
(
dsidev
)
;
pll
=
dss_pll_find
(
"dsi0"
);
r
=
pll
->
cinfo
.
clkout
[
0
]
;
break
;
case
OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC
:
dsidev
=
dsi_get_dsidev_from_id
(
1
);
r
=
dsi_get_pll_hsdiv_dispc_rate
(
dsidev
)
;
pll
=
dss_pll_find
(
"dsi1"
);
r
=
pll
->
cinfo
.
clkout
[
0
]
;
break
;
default:
BUG
();
...
...
@@ -3053,7 +3053,7 @@ unsigned long dispc_fclk_rate(void)
unsigned
long
dispc_mgr_lclk_rate
(
enum
omap_channel
channel
)
{
struct
platform_device
*
dsidev
;
struct
dss_pll
*
pll
;
int
lcd
;
unsigned
long
r
;
u32
l
;
...
...
@@ -3068,12 +3068,12 @@ unsigned long dispc_mgr_lclk_rate(enum omap_channel channel)
r
=
dss_get_dispc_clk_rate
();
break
;
case
OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC
:
dsidev
=
dsi_get_dsidev_from_id
(
0
);
r
=
dsi_get_pll_hsdiv_dispc_rate
(
dsidev
)
;
pll
=
dss_pll_find
(
"dsi0"
);
r
=
pll
->
cinfo
.
clkout
[
0
]
;
break
;
case
OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC
:
dsidev
=
dsi_get_dsidev_from_id
(
1
);
r
=
dsi_get_pll_hsdiv_dispc_rate
(
dsidev
)
;
pll
=
dss_pll_find
(
"dsi1"
);
r
=
pll
->
cinfo
.
clkout
[
0
]
;
break
;
default:
BUG
();
...
...
drivers/video/fbdev/omap2/dss/dpi.c
浏览文件 @
3315764e
...
...
@@ -31,17 +31,20 @@
#include <linux/regulator/consumer.h>
#include <linux/string.h>
#include <linux/of.h>
#include <linux/clk.h>
#include <video/omapdss.h>
#include "dss.h"
#include "dss_features.h"
static
struct
{
#define HSDIV_DISPC 0
struct
dpi_data
{
struct
platform_device
*
pdev
;
struct
regulator
*
vdds_dsi_reg
;
struct
platform_device
*
dsidev
;
struct
dss_pll
*
pll
;
struct
mutex
lock
;
...
...
@@ -52,9 +55,20 @@ static struct {
struct
omap_dss_device
output
;
bool
port_initialized
;
}
dpi
;
};
static
struct
dpi_data
*
dpi_get_data_from_dssdev
(
struct
omap_dss_device
*
dssdev
)
{
return
container_of
(
dssdev
,
struct
dpi_data
,
output
);
}
/* only used in non-DT mode */
static
struct
dpi_data
*
dpi_get_data_from_pdev
(
struct
platform_device
*
pdev
)
{
return
dev_get_drvdata
(
&
pdev
->
dev
);
}
static
struct
platform_device
*
dpi_get_dsidev
(
enum
omap_channel
channel
)
static
struct
dss_pll
*
dpi_get_pll
(
enum
omap_channel
channel
)
{
/*
* XXX we can't currently use DSI PLL for DPI with OMAP3, as the DSI PLL
...
...
@@ -75,9 +89,9 @@ static struct platform_device *dpi_get_dsidev(enum omap_channel channel)
case
OMAPDSS_VER_OMAP4
:
switch
(
channel
)
{
case
OMAP_DSS_CHANNEL_LCD
:
return
ds
i_get_dsidev_from_id
(
0
);
return
ds
s_pll_find
(
"dsi0"
);
case
OMAP_DSS_CHANNEL_LCD2
:
return
ds
i_get_dsidev_from_id
(
1
);
return
ds
s_pll_find
(
"dsi1"
);
default:
return
NULL
;
}
...
...
@@ -85,9 +99,9 @@ static struct platform_device *dpi_get_dsidev(enum omap_channel channel)
case
OMAPDSS_VER_OMAP5
:
switch
(
channel
)
{
case
OMAP_DSS_CHANNEL_LCD
:
return
ds
i_get_dsidev_from_id
(
0
);
return
ds
s_pll_find
(
"dsi0"
);
case
OMAP_DSS_CHANNEL_LCD3
:
return
ds
i_get_dsidev_from_id
(
1
);
return
ds
s_pll_find
(
"dsi1"
);
default:
return
NULL
;
}
...
...
@@ -114,7 +128,7 @@ static enum omap_dss_clk_source dpi_get_alt_clk_src(enum omap_channel channel)
}
struct
dpi_clk_calc_ctx
{
struct
platform_device
*
dsidev
;
struct
dss_pll
*
pll
;
/* inputs */
...
...
@@ -122,7 +136,7 @@ struct dpi_clk_calc_ctx {
/* outputs */
struct
ds
i
_clock_info
dsi_cinfo
;
struct
ds
s_pll
_clock_info
dsi_cinfo
;
unsigned
long
fck
;
struct
dispc_clock_info
dispc_cinfo
;
};
...
...
@@ -154,7 +168,7 @@ static bool dpi_calc_dispc_cb(int lckd, int pckd, unsigned long lck,
}
static
bool
dpi_calc_hsdiv_cb
(
int
reg
m_dispc
,
unsigned
long
dispc
,
static
bool
dpi_calc_hsdiv_cb
(
int
m_dispc
,
unsigned
long
dispc
,
void
*
data
)
{
struct
dpi_clk_calc_ctx
*
ctx
=
data
;
...
...
@@ -164,29 +178,30 @@ static bool dpi_calc_hsdiv_cb(int regm_dispc, unsigned long dispc,
* shifted. So skip all odd dividers when the pixel clock is on the
* higher side.
*/
if
(
regm_dispc
>
1
&&
reg
m_dispc
%
2
!=
0
&&
ctx
->
pck_min
>=
100000000
)
if
(
m_dispc
>
1
&&
m_dispc
%
2
!=
0
&&
ctx
->
pck_min
>=
100000000
)
return
false
;
ctx
->
dsi_cinfo
.
regm_dispc
=
reg
m_dispc
;
ctx
->
dsi_cinfo
.
dsi_pll_hsdiv_dispc_clk
=
dispc
;
ctx
->
dsi_cinfo
.
mX
[
HSDIV_DISPC
]
=
m_dispc
;
ctx
->
dsi_cinfo
.
clkout
[
HSDIV_DISPC
]
=
dispc
;
return
dispc_div_calc
(
dispc
,
ctx
->
pck_min
,
ctx
->
pck_max
,
dpi_calc_dispc_cb
,
ctx
);
}
static
bool
dpi_calc_pll_cb
(
int
regn
,
int
reg
m
,
unsigned
long
fint
,
unsigned
long
pll
,
static
bool
dpi_calc_pll_cb
(
int
n
,
int
m
,
unsigned
long
fint
,
unsigned
long
clkdco
,
void
*
data
)
{
struct
dpi_clk_calc_ctx
*
ctx
=
data
;
ctx
->
dsi_cinfo
.
regn
=
reg
n
;
ctx
->
dsi_cinfo
.
regm
=
reg
m
;
ctx
->
dsi_cinfo
.
n
=
n
;
ctx
->
dsi_cinfo
.
m
=
m
;
ctx
->
dsi_cinfo
.
fint
=
fint
;
ctx
->
dsi_cinfo
.
clk
in4ddr
=
pll
;
ctx
->
dsi_cinfo
.
clk
dco
=
clkdco
;
return
dsi_hsdiv_calc
(
ctx
->
dsidev
,
pll
,
ctx
->
pck_min
,
return
dss_pll_hsdiv_calc
(
ctx
->
pll
,
clkdco
,
ctx
->
pck_min
,
dss_feat_get_param_max
(
FEAT_PARAM_DSS_FCK
),
dpi_calc_hsdiv_cb
,
ctx
);
}
...
...
@@ -200,23 +215,23 @@ static bool dpi_calc_dss_cb(unsigned long fck, void *data)
dpi_calc_dispc_cb
,
ctx
);
}
static
bool
dpi_dsi_clk_calc
(
unsigned
long
pck
,
struct
dpi_clk_calc_ctx
*
ctx
)
static
bool
dpi_dsi_clk_calc
(
struct
dpi_data
*
dpi
,
unsigned
long
pck
,
struct
dpi_clk_calc_ctx
*
ctx
)
{
unsigned
long
clkin
;
unsigned
long
pll_min
,
pll_max
;
clkin
=
dsi_get_pll_clkin
(
dpi
.
dsidev
);
memset
(
ctx
,
0
,
sizeof
(
*
ctx
));
ctx
->
dsidev
=
dpi
.
dsidev
;
ctx
->
pll
=
dpi
->
pll
;
ctx
->
pck_min
=
pck
-
1000
;
ctx
->
pck_max
=
pck
+
1000
;
ctx
->
dsi_cinfo
.
clkin
=
clkin
;
pll_min
=
0
;
pll_max
=
0
;
return
dsi_pll_calc
(
dpi
.
dsidev
,
clkin
,
clkin
=
clk_get_rate
(
ctx
->
pll
->
clkin
);
return
dss_pll_calc
(
ctx
->
pll
,
clkin
,
pll_min
,
pll_max
,
dpi_calc_pll_cb
,
ctx
);
}
...
...
@@ -252,7 +267,7 @@ static bool dpi_dss_clk_calc(unsigned long pck, struct dpi_clk_calc_ctx *ctx)
static
int
dpi_set_dsi_clk
(
enum
omap_channel
channel
,
static
int
dpi_set_dsi_clk
(
struct
dpi_data
*
dpi
,
enum
omap_channel
channel
,
unsigned
long
pck_req
,
unsigned
long
*
fck
,
int
*
lck_div
,
int
*
pck_div
)
{
...
...
@@ -260,28 +275,28 @@ static int dpi_set_dsi_clk(enum omap_channel channel,
int
r
;
bool
ok
;
ok
=
dpi_dsi_clk_calc
(
pck_req
,
&
ctx
);
ok
=
dpi_dsi_clk_calc
(
dpi
,
pck_req
,
&
ctx
);
if
(
!
ok
)
return
-
EINVAL
;
r
=
ds
i_pll_set_clock_div
(
dpi
.
dsidev
,
&
ctx
.
dsi_cinfo
);
r
=
ds
s_pll_set_config
(
dpi
->
pll
,
&
ctx
.
dsi_cinfo
);
if
(
r
)
return
r
;
dss_select_lcd_clk_source
(
channel
,
dpi_get_alt_clk_src
(
channel
));
dpi
.
mgr_config
.
clock_info
=
ctx
.
dispc_cinfo
;
dpi
->
mgr_config
.
clock_info
=
ctx
.
dispc_cinfo
;
*
fck
=
ctx
.
dsi_cinfo
.
dsi_pll_hsdiv_dispc_clk
;
*
fck
=
ctx
.
dsi_cinfo
.
clkout
[
HSDIV_DISPC
]
;
*
lck_div
=
ctx
.
dispc_cinfo
.
lck_div
;
*
pck_div
=
ctx
.
dispc_cinfo
.
pck_div
;
return
0
;
}
static
int
dpi_set_dispc_clk
(
unsigned
long
pck_req
,
unsigned
long
*
fck
,
int
*
lck_div
,
int
*
pck_div
)
static
int
dpi_set_dispc_clk
(
struct
dpi_data
*
dpi
,
unsigned
long
pck_req
,
unsigned
long
*
fck
,
int
*
lck_div
,
int
*
pck_div
)
{
struct
dpi_clk_calc_ctx
ctx
;
int
r
;
...
...
@@ -295,7 +310,7 @@ static int dpi_set_dispc_clk(unsigned long pck_req, unsigned long *fck,
if
(
r
)
return
r
;
dpi
.
mgr_config
.
clock_info
=
ctx
.
dispc_cinfo
;
dpi
->
mgr_config
.
clock_info
=
ctx
.
dispc_cinfo
;
*
fck
=
ctx
.
fck
;
*
lck_div
=
ctx
.
dispc_cinfo
.
lck_div
;
...
...
@@ -304,19 +319,21 @@ static int dpi_set_dispc_clk(unsigned long pck_req, unsigned long *fck,
return
0
;
}
static
int
dpi_set_mode
(
struct
omap_overlay_manager
*
mgr
)
static
int
dpi_set_mode
(
struct
dpi_data
*
dpi
)
{
struct
omap_video_timings
*
t
=
&
dpi
.
timings
;
struct
omap_dss_device
*
out
=
&
dpi
->
output
;
struct
omap_overlay_manager
*
mgr
=
out
->
manager
;
struct
omap_video_timings
*
t
=
&
dpi
->
timings
;
int
lck_div
=
0
,
pck_div
=
0
;
unsigned
long
fck
=
0
;
unsigned
long
pck
;
int
r
=
0
;
if
(
dpi
.
dsidev
)
r
=
dpi_set_dsi_clk
(
mgr
->
id
,
t
->
pixelclock
,
&
fck
,
if
(
dpi
->
pll
)
r
=
dpi_set_dsi_clk
(
dpi
,
mgr
->
id
,
t
->
pixelclock
,
&
fck
,
&
lck_div
,
&
pck_div
);
else
r
=
dpi_set_dispc_clk
(
t
->
pixelclock
,
&
fck
,
r
=
dpi_set_dispc_clk
(
dpi
,
t
->
pixelclock
,
&
fck
,
&
lck_div
,
&
pck_div
);
if
(
r
)
return
r
;
...
...
@@ -335,28 +352,32 @@ static int dpi_set_mode(struct omap_overlay_manager *mgr)
return
0
;
}
static
void
dpi_config_lcd_manager
(
struct
omap_overlay_manager
*
mgr
)
static
void
dpi_config_lcd_manager
(
struct
dpi_data
*
dpi
)
{
dpi
.
mgr_config
.
io_pad_mode
=
DSS_IO_PAD_MODE_BYPASS
;
struct
omap_dss_device
*
out
=
&
dpi
->
output
;
struct
omap_overlay_manager
*
mgr
=
out
->
manager
;
dpi
->
mgr_config
.
io_pad_mode
=
DSS_IO_PAD_MODE_BYPASS
;
dpi
.
mgr_config
.
stallmode
=
false
;
dpi
.
mgr_config
.
fifohandcheck
=
false
;
dpi
->
mgr_config
.
stallmode
=
false
;
dpi
->
mgr_config
.
fifohandcheck
=
false
;
dpi
.
mgr_config
.
video_port_width
=
dpi
.
data_lines
;
dpi
->
mgr_config
.
video_port_width
=
dpi
->
data_lines
;
dpi
.
mgr_config
.
lcden_sig_polarity
=
0
;
dpi
->
mgr_config
.
lcden_sig_polarity
=
0
;
dss_mgr_set_lcd_config
(
mgr
,
&
dpi
.
mgr_config
);
dss_mgr_set_lcd_config
(
mgr
,
&
dpi
->
mgr_config
);
}
static
int
dpi_display_enable
(
struct
omap_dss_device
*
dssdev
)
{
struct
omap_dss_device
*
out
=
&
dpi
.
output
;
struct
dpi_data
*
dpi
=
dpi_get_data_from_dssdev
(
dssdev
);
struct
omap_dss_device
*
out
=
&
dpi
->
output
;
int
r
;
mutex_lock
(
&
dpi
.
lock
);
mutex_lock
(
&
dpi
->
lock
);
if
(
dss_has_feature
(
FEAT_DPI_USES_VDDS_DSI
)
&&
!
dpi
.
vdds_dsi_reg
)
{
if
(
dss_has_feature
(
FEAT_DPI_USES_VDDS_DSI
)
&&
!
dpi
->
vdds_dsi_reg
)
{
DSSERR
(
"no VDSS_DSI regulator
\n
"
);
r
=
-
ENODEV
;
goto
err_no_reg
;
...
...
@@ -369,7 +390,7 @@ static int dpi_display_enable(struct omap_dss_device *dssdev)
}
if
(
dss_has_feature
(
FEAT_DPI_USES_VDDS_DSI
))
{
r
=
regulator_enable
(
dpi
.
vdds_dsi_reg
);
r
=
regulator_enable
(
dpi
->
vdds_dsi_reg
);
if
(
r
)
goto
err_reg_enable
;
}
...
...
@@ -378,25 +399,21 @@ static int dpi_display_enable(struct omap_dss_device *dssdev)
if
(
r
)
goto
err_get_dispc
;
r
=
dss_dpi_select_source
(
out
->
manager
->
id
);
r
=
dss_dpi_select_source
(
out
->
port_num
,
out
->
manager
->
id
);
if
(
r
)
goto
err_src_sel
;
if
(
dpi
.
dsidev
)
{
r
=
dsi_runtime_get
(
dpi
.
dsidev
);
if
(
r
)
goto
err_get_dsi
;
r
=
dsi_pll_init
(
dpi
.
dsidev
,
0
,
1
);
if
(
dpi
->
pll
)
{
r
=
dss_pll_enable
(
dpi
->
pll
);
if
(
r
)
goto
err_dsi_pll_init
;
}
r
=
dpi_set_mode
(
out
->
manager
);
r
=
dpi_set_mode
(
dpi
);
if
(
r
)
goto
err_set_mode
;
dpi_config_lcd_manager
(
out
->
manager
);
dpi_config_lcd_manager
(
dpi
);
mdelay
(
2
);
...
...
@@ -404,78 +421,80 @@ static int dpi_display_enable(struct omap_dss_device *dssdev)
if
(
r
)
goto
err_mgr_enable
;
mutex_unlock
(
&
dpi
.
lock
);
mutex_unlock
(
&
dpi
->
lock
);
return
0
;
err_mgr_enable:
err_set_mode:
if
(
dpi
.
dsidev
)
ds
i_pll_uninit
(
dpi
.
dsidev
,
true
);
if
(
dpi
->
pll
)
ds
s_pll_disable
(
dpi
->
pll
);
err_dsi_pll_init:
if
(
dpi
.
dsidev
)
dsi_runtime_put
(
dpi
.
dsidev
);
err_get_dsi:
err_src_sel:
dispc_runtime_put
();
err_get_dispc:
if
(
dss_has_feature
(
FEAT_DPI_USES_VDDS_DSI
))
regulator_disable
(
dpi
.
vdds_dsi_reg
);
regulator_disable
(
dpi
->
vdds_dsi_reg
);
err_reg_enable:
err_no_out_mgr:
err_no_reg:
mutex_unlock
(
&
dpi
.
lock
);
mutex_unlock
(
&
dpi
->
lock
);
return
r
;
}
static
void
dpi_display_disable
(
struct
omap_dss_device
*
dssdev
)
{
struct
omap_overlay_manager
*
mgr
=
dpi
.
output
.
manager
;
struct
dpi_data
*
dpi
=
dpi_get_data_from_dssdev
(
dssdev
);
struct
omap_overlay_manager
*
mgr
=
dpi
->
output
.
manager
;
mutex_lock
(
&
dpi
.
lock
);
mutex_lock
(
&
dpi
->
lock
);
dss_mgr_disable
(
mgr
);
if
(
dpi
.
dsidev
)
{
if
(
dpi
->
pll
)
{
dss_select_lcd_clk_source
(
mgr
->
id
,
OMAP_DSS_CLK_SRC_FCK
);
dsi_pll_uninit
(
dpi
.
dsidev
,
true
);
dsi_runtime_put
(
dpi
.
dsidev
);
dss_pll_disable
(
dpi
->
pll
);
}
dispc_runtime_put
();
if
(
dss_has_feature
(
FEAT_DPI_USES_VDDS_DSI
))
regulator_disable
(
dpi
.
vdds_dsi_reg
);
regulator_disable
(
dpi
->
vdds_dsi_reg
);
mutex_unlock
(
&
dpi
.
lock
);
mutex_unlock
(
&
dpi
->
lock
);
}
static
void
dpi_set_timings
(
struct
omap_dss_device
*
dssdev
,
struct
omap_video_timings
*
timings
)
{
struct
dpi_data
*
dpi
=
dpi_get_data_from_dssdev
(
dssdev
);
DSSDBG
(
"dpi_set_timings
\n
"
);
mutex_lock
(
&
dpi
.
lock
);
mutex_lock
(
&
dpi
->
lock
);
dpi
.
timings
=
*
timings
;
dpi
->
timings
=
*
timings
;
mutex_unlock
(
&
dpi
.
lock
);
mutex_unlock
(
&
dpi
->
lock
);
}
static
void
dpi_get_timings
(
struct
omap_dss_device
*
dssdev
,
struct
omap_video_timings
*
timings
)
{
mutex_lock
(
&
dpi
.
lock
);
struct
dpi_data
*
dpi
=
dpi_get_data_from_dssdev
(
dssdev
);
mutex_lock
(
&
dpi
->
lock
);
*
timings
=
dpi
.
timings
;
*
timings
=
dpi
->
timings
;
mutex_unlock
(
&
dpi
.
lock
);
mutex_unlock
(
&
dpi
->
lock
);
}
static
int
dpi_check_timings
(
struct
omap_dss_device
*
dssdev
,
struct
omap_video_timings
*
timings
)
{
struct
omap_overlay_manager
*
mgr
=
dpi
.
output
.
manager
;
struct
dpi_data
*
dpi
=
dpi_get_data_from_dssdev
(
dssdev
);
struct
omap_overlay_manager
*
mgr
=
dpi
->
output
.
manager
;
int
lck_div
,
pck_div
;
unsigned
long
fck
;
unsigned
long
pck
;
...
...
@@ -488,12 +507,12 @@ static int dpi_check_timings(struct omap_dss_device *dssdev,
if
(
timings
->
pixelclock
==
0
)
return
-
EINVAL
;
if
(
dpi
.
dsidev
)
{
ok
=
dpi_dsi_clk_calc
(
timings
->
pixelclock
,
&
ctx
);
if
(
dpi
->
pll
)
{
ok
=
dpi_dsi_clk_calc
(
dpi
,
timings
->
pixelclock
,
&
ctx
);
if
(
!
ok
)
return
-
EINVAL
;
fck
=
ctx
.
dsi_cinfo
.
dsi_pll_hsdiv_dispc_clk
;
fck
=
ctx
.
dsi_cinfo
.
clkout
[
HSDIV_DISPC
]
;
}
else
{
ok
=
dpi_dss_clk_calc
(
timings
->
pixelclock
,
&
ctx
);
if
(
!
ok
)
...
...
@@ -514,74 +533,69 @@ static int dpi_check_timings(struct omap_dss_device *dssdev,
static
void
dpi_set_data_lines
(
struct
omap_dss_device
*
dssdev
,
int
data_lines
)
{
mutex_lock
(
&
dpi
.
lock
);
struct
dpi_data
*
dpi
=
dpi_get_data_from_dssdev
(
dssdev
);
dpi
.
data_lines
=
data_lines
;
mutex_lock
(
&
dpi
->
lock
)
;
mutex_unlock
(
&
dpi
.
lock
);
dpi
->
data_lines
=
data_lines
;
mutex_unlock
(
&
dpi
->
lock
);
}
static
int
dpi_verify_dsi_pll
(
struct
platform_device
*
dsidev
)
static
int
dpi_verify_dsi_pll
(
struct
dss_pll
*
pll
)
{
int
r
;
/* do initial setup with the PLL to see if it is operational */
r
=
ds
i_runtime_get
(
dsidev
);
r
=
ds
s_pll_enable
(
pll
);
if
(
r
)
return
r
;
r
=
dsi_pll_init
(
dsidev
,
0
,
1
);
if
(
r
)
{
dsi_runtime_put
(
dsidev
);
return
r
;
}
dsi_pll_uninit
(
dsidev
,
true
);
dsi_runtime_put
(
dsidev
);
dss_pll_disable
(
pll
);
return
0
;
}
static
int
dpi_init_regulator
(
void
)
static
int
dpi_init_regulator
(
struct
dpi_data
*
dpi
)
{
struct
regulator
*
vdds_dsi
;
if
(
!
dss_has_feature
(
FEAT_DPI_USES_VDDS_DSI
))
return
0
;
if
(
dpi
.
vdds_dsi_reg
)
if
(
dpi
->
vdds_dsi_reg
)
return
0
;
vdds_dsi
=
devm_regulator_get
(
&
dpi
.
pdev
->
dev
,
"vdds_dsi"
);
vdds_dsi
=
devm_regulator_get
(
&
dpi
->
pdev
->
dev
,
"vdds_dsi"
);
if
(
IS_ERR
(
vdds_dsi
))
{
if
(
PTR_ERR
(
vdds_dsi
)
!=
-
EPROBE_DEFER
)
DSSERR
(
"can't get VDDS_DSI regulator
\n
"
);
return
PTR_ERR
(
vdds_dsi
);
}
dpi
.
vdds_dsi_reg
=
vdds_dsi
;
dpi
->
vdds_dsi_reg
=
vdds_dsi
;
return
0
;
}
static
void
dpi_init_pll
(
void
)
static
void
dpi_init_pll
(
struct
dpi_data
*
dpi
)
{
struct
platform_device
*
dsidev
;
struct
dss_pll
*
pll
;
if
(
dpi
.
dsidev
)
if
(
dpi
->
pll
)
return
;
dsidev
=
dpi_get_dsidev
(
dpi
.
output
.
dispc_channel
);
if
(
!
dsidev
)
pll
=
dpi_get_pll
(
dpi
->
output
.
dispc_channel
);
if
(
!
pll
)
return
;
if
(
dpi_verify_dsi_pll
(
dsidev
))
{
if
(
dpi_verify_dsi_pll
(
pll
))
{
DSSWARN
(
"DSI PLL not operational
\n
"
);
return
;
}
dpi
.
dsidev
=
dsidev
;
dpi
->
pll
=
pll
;
}
/*
...
...
@@ -590,7 +604,7 @@ static void dpi_init_pll(void)
* the channel in some more dynamic manner, or get the channel as a user
* parameter.
*/
static
enum
omap_channel
dpi_get_channel
(
void
)
static
enum
omap_channel
dpi_get_channel
(
int
port_num
)
{
switch
(
omapdss_get_version
())
{
case
OMAPDSS_VER_OMAP24xx
:
...
...
@@ -618,14 +632,15 @@ static enum omap_channel dpi_get_channel(void)
static
int
dpi_connect
(
struct
omap_dss_device
*
dssdev
,
struct
omap_dss_device
*
dst
)
{
struct
dpi_data
*
dpi
=
dpi_get_data_from_dssdev
(
dssdev
);
struct
omap_overlay_manager
*
mgr
;
int
r
;
r
=
dpi_init_regulator
();
r
=
dpi_init_regulator
(
dpi
);
if
(
r
)
return
r
;
dpi_init_pll
();
dpi_init_pll
(
dpi
);
mgr
=
omap_dss_get_overlay_manager
(
dssdev
->
dispc_channel
);
if
(
!
mgr
)
...
...
@@ -676,13 +691,14 @@ static const struct omapdss_dpi_ops dpi_ops = {
static
void
dpi_init_output
(
struct
platform_device
*
pdev
)
{
struct
omap_dss_device
*
out
=
&
dpi
.
output
;
struct
dpi_data
*
dpi
=
dpi_get_data_from_pdev
(
pdev
);
struct
omap_dss_device
*
out
=
&
dpi
->
output
;
out
->
dev
=
&
pdev
->
dev
;
out
->
id
=
OMAP_DSS_OUTPUT_DPI
;
out
->
output_type
=
OMAP_DISPLAY_TYPE_DPI
;
out
->
name
=
"dpi.0"
;
out
->
dispc_channel
=
dpi_get_channel
();
out
->
dispc_channel
=
dpi_get_channel
(
0
);
out
->
ops
.
dpi
=
&
dpi_ops
;
out
->
owner
=
THIS_MODULE
;
...
...
@@ -691,16 +707,69 @@ static void dpi_init_output(struct platform_device *pdev)
static
void
__exit
dpi_uninit_output
(
struct
platform_device
*
pdev
)
{
struct
omap_dss_device
*
out
=
&
dpi
.
output
;
struct
dpi_data
*
dpi
=
dpi_get_data_from_pdev
(
pdev
);
struct
omap_dss_device
*
out
=
&
dpi
->
output
;
omapdss_unregister_output
(
out
);
}
static
void
dpi_init_output_port
(
struct
platform_device
*
pdev
,
struct
device_node
*
port
)
{
struct
dpi_data
*
dpi
=
port
->
data
;
struct
omap_dss_device
*
out
=
&
dpi
->
output
;
int
r
;
u32
port_num
;
r
=
of_property_read_u32
(
port
,
"reg"
,
&
port_num
);
if
(
r
)
port_num
=
0
;
switch
(
port_num
)
{
case
2
:
out
->
name
=
"dpi.2"
;
break
;
case
1
:
out
->
name
=
"dpi.1"
;
break
;
case
0
:
default:
out
->
name
=
"dpi.0"
;
break
;
}
out
->
dev
=
&
pdev
->
dev
;
out
->
id
=
OMAP_DSS_OUTPUT_DPI
;
out
->
output_type
=
OMAP_DISPLAY_TYPE_DPI
;
out
->
dispc_channel
=
dpi_get_channel
(
port_num
);
out
->
port_num
=
port_num
;
out
->
ops
.
dpi
=
&
dpi_ops
;
out
->
owner
=
THIS_MODULE
;
omapdss_register_output
(
out
);
}
static
void
__exit
dpi_uninit_output_port
(
struct
device_node
*
port
)
{
struct
dpi_data
*
dpi
=
port
->
data
;
struct
omap_dss_device
*
out
=
&
dpi
->
output
;
omapdss_unregister_output
(
out
);
}
static
int
omap_dpi_probe
(
struct
platform_device
*
pdev
)
{
dpi
.
pdev
=
pdev
;
struct
dpi_data
*
dpi
;
mutex_init
(
&
dpi
.
lock
);
dpi
=
devm_kzalloc
(
&
pdev
->
dev
,
sizeof
(
*
dpi
),
GFP_KERNEL
);
if
(
!
dpi
)
return
-
ENOMEM
;
dpi
->
pdev
=
pdev
;
dev_set_drvdata
(
&
pdev
->
dev
,
dpi
);
mutex_init
(
&
dpi
->
lock
);
dpi_init_output
(
pdev
);
...
...
@@ -736,10 +805,15 @@ void __exit dpi_uninit_platform_driver(void)
int
__init
dpi_init_port
(
struct
platform_device
*
pdev
,
struct
device_node
*
port
)
{
struct
dpi_data
*
dpi
;
struct
device_node
*
ep
;
u32
datalines
;
int
r
;
dpi
=
devm_kzalloc
(
&
pdev
->
dev
,
sizeof
(
*
dpi
),
GFP_KERNEL
);
if
(
!
dpi
)
return
-
ENOMEM
;
ep
=
omapdss_of_get_next_endpoint
(
port
,
NULL
);
if
(
!
ep
)
return
0
;
...
...
@@ -750,17 +824,18 @@ int __init dpi_init_port(struct platform_device *pdev, struct device_node *port)
goto
err_datalines
;
}
dpi
.
data_lines
=
datalines
;
dpi
->
data_lines
=
datalines
;
of_node_put
(
ep
);
dpi
.
pdev
=
pdev
;
dpi
->
pdev
=
pdev
;
port
->
data
=
dpi
;
mutex_init
(
&
dpi
.
lock
);
mutex_init
(
&
dpi
->
lock
);
dpi_init_output
(
pdev
);
dpi_init_output
_port
(
pdev
,
port
);
dpi
.
port_initialized
=
true
;
dpi
->
port_initialized
=
true
;
return
0
;
...
...
@@ -770,10 +845,12 @@ int __init dpi_init_port(struct platform_device *pdev, struct device_node *port)
return
r
;
}
void
__exit
dpi_uninit_port
(
void
)
void
__exit
dpi_uninit_port
(
struct
device_node
*
port
)
{
if
(
!
dpi
.
port_initialized
)
struct
dpi_data
*
dpi
=
port
->
data
;
if
(
!
dpi
->
port_initialized
)
return
;
dpi_uninit_output
(
dpi
.
pdev
);
dpi_uninit_output
_port
(
port
);
}
drivers/video/fbdev/omap2/dss/dsi.c
浏览文件 @
3315764e
...
...
@@ -219,6 +219,10 @@ static void dsi_display_uninit_dispc(struct platform_device *dsidev,
static
int
dsi_vc_send_null
(
struct
omap_dss_device
*
dssdev
,
int
channel
);
/* DSI PLL HSDIV indices */
#define HSDIV_DISPC 0
#define HSDIV_DSI 1
#define DSI_MAX_NR_ISRS 2
#define DSI_MAX_NR_LANES 5
...
...
@@ -271,6 +275,7 @@ struct dsi_isr_tables {
struct
dsi_clk_calc_ctx
{
struct
platform_device
*
dsidev
;
struct
dss_pll
*
pll
;
/* inputs */
...
...
@@ -280,13 +285,18 @@ struct dsi_clk_calc_ctx {
/* outputs */
struct
ds
i
_clock_info
dsi_cinfo
;
struct
ds
s_pll
_clock_info
dsi_cinfo
;
struct
dispc_clock_info
dispc_cinfo
;
struct
omap_video_timings
dispc_vm
;
struct
omap_dss_dsi_videomode_timings
dsi_vm
;
};
struct
dsi_lp_clock_info
{
unsigned
long
lp_clk
;
u16
lp_clk_div
;
};
struct
dsi_data
{
struct
platform_device
*
pdev
;
void
__iomem
*
proto_base
;
...
...
@@ -300,12 +310,14 @@ struct dsi_data {
bool
is_enabled
;
struct
clk
*
dss_clk
;
struct
clk
*
sys_clk
;
struct
dispc_clock_info
user_dispc_cinfo
;
struct
dsi_clock_info
user_dsi_cinfo
;
struct
dss_pll_clock_info
user_dsi_cinfo
;
struct
dsi_lp_clock_info
user_lp_cinfo
;
struct
dsi_lp_clock_info
current_lp_cinfo
;
struct
ds
i_clock_info
current_cinfo
;
struct
ds
s_pll
pll
;
bool
vdds_dsi_enabled
;
struct
regulator
*
vdds_dsi_reg
;
...
...
@@ -321,8 +333,6 @@ struct dsi_data {
struct
mutex
lock
;
struct
semaphore
bus_lock
;
unsigned
pll_locked
;
spinlock_t
irq_lock
;
struct
dsi_isr_tables
isr_tables
;
/* space for a copy used by the interrupt handler */
...
...
@@ -347,7 +357,7 @@ struct dsi_data {
unsigned
long
cache_req_pck
;
unsigned
long
cache_clk_freq
;
struct
ds
i
_clock_info
cache_cinfo
;
struct
ds
s_pll
_clock_info
cache_cinfo
;
u32
errors
;
spinlock_t
errors_lock
;
...
...
@@ -362,11 +372,6 @@ struct dsi_data {
spinlock_t
irq_stats_lock
;
struct
dsi_irq_stats
irq_stats
;
#endif
/* DSI PLL Parameter Ranges */
unsigned
long
regm_max
,
regn_max
;
unsigned
long
regm_dispc_max
,
regm_dsi_max
;
unsigned
long
fint_min
,
fint_max
;
unsigned
long
lpdiv_max
;
unsigned
num_lanes_supported
;
unsigned
line_buffer_size
;
...
...
@@ -412,7 +417,7 @@ static inline struct platform_device *dsi_get_dsidev_from_dssdev(struct omap_dss
return
to_platform_device
(
dssdev
->
dev
);
}
struct
platform_device
*
dsi_get_dsidev_from_id
(
int
module
)
st
atic
st
ruct
platform_device
*
dsi_get_dsidev_from_id
(
int
module
)
{
struct
omap_dss_device
*
out
;
enum
omap_dss_output_id
id
;
...
...
@@ -1134,7 +1139,7 @@ static u32 dsi_get_errors(struct platform_device *dsidev)
return
e
;
}
int
dsi_runtime_get
(
struct
platform_device
*
dsidev
)
static
int
dsi_runtime_get
(
struct
platform_device
*
dsidev
)
{
int
r
;
struct
dsi_data
*
dsi
=
dsi_get_dsidrv_data
(
dsidev
);
...
...
@@ -1146,7 +1151,7 @@ int dsi_runtime_get(struct platform_device *dsidev)
return
r
<
0
?
r
:
0
;
}
void
dsi_runtime_put
(
struct
platform_device
*
dsidev
)
static
void
dsi_runtime_put
(
struct
platform_device
*
dsidev
)
{
struct
dsi_data
*
dsi
=
dsi_get_dsidrv_data
(
dsidev
);
int
r
;
...
...
@@ -1188,23 +1193,6 @@ static int dsi_regulator_init(struct platform_device *dsidev)
return
0
;
}
/* source clock for DSI PLL. this could also be PCLKFREE */
static
inline
void
dsi_enable_pll_clock
(
struct
platform_device
*
dsidev
,
bool
enable
)
{
struct
dsi_data
*
dsi
=
dsi_get_dsidrv_data
(
dsidev
);
if
(
enable
)
clk_prepare_enable
(
dsi
->
sys_clk
);
else
clk_disable_unprepare
(
dsi
->
sys_clk
);
if
(
enable
&&
dsi
->
pll_locked
)
{
if
(
wait_for_bit_change
(
dsidev
,
DSI_PLL_STATUS
,
1
,
1
)
!=
1
)
DSSERR
(
"cannot lock PLL when enabling clocks
\n
"
);
}
}
static
void
_dsi_print_reset_status
(
struct
platform_device
*
dsidev
)
{
u32
l
;
...
...
@@ -1256,25 +1244,25 @@ static inline int dsi_if_enable(struct platform_device *dsidev, bool enable)
return
0
;
}
unsigned
long
dsi_get_pll_hsdiv_dispc_rate
(
struct
platform_device
*
dsidev
)
static
unsigned
long
dsi_get_pll_hsdiv_dispc_rate
(
struct
platform_device
*
dsidev
)
{
struct
dsi_data
*
dsi
=
dsi_get_dsidrv_data
(
dsidev
);
return
dsi
->
current_cinfo
.
dsi_pll_hsdiv_dispc_clk
;
return
dsi
->
pll
.
cinfo
.
clkout
[
HSDIV_DISPC
]
;
}
static
unsigned
long
dsi_get_pll_hsdiv_dsi_rate
(
struct
platform_device
*
dsidev
)
{
struct
dsi_data
*
dsi
=
dsi_get_dsidrv_data
(
dsidev
);
return
dsi
->
current_cinfo
.
dsi_pll_hsdiv_dsi_clk
;
return
dsi
->
pll
.
cinfo
.
clkout
[
HSDIV_DSI
]
;
}
static
unsigned
long
dsi_get_txbyteclkhs
(
struct
platform_device
*
dsidev
)
{
struct
dsi_data
*
dsi
=
dsi_get_dsidrv_data
(
dsidev
);
return
dsi
->
current_cinfo
.
clkin4ddr
/
16
;
return
dsi
->
pll
.
cinfo
.
clkdco
/
16
;
}
static
unsigned
long
dsi_fclk_rate
(
struct
platform_device
*
dsidev
)
...
...
@@ -1293,10 +1281,10 @@ static unsigned long dsi_fclk_rate(struct platform_device *dsidev)
return
r
;
}
static
int
dsi_lp_clock_calc
(
struct
dsi_clock_info
*
cinfo
,
unsigned
long
lp_clk_min
,
unsigned
long
lp_clk_max
)
static
int
dsi_lp_clock_calc
(
unsigned
long
dsi_fclk
,
unsigned
long
lp_clk_min
,
unsigned
long
lp_clk_max
,
struct
dsi_lp_clock_info
*
lp_cinfo
)
{
unsigned
long
dsi_fclk
=
cinfo
->
dsi_pll_hsdiv_dsi_clk
;
unsigned
lp_clk_div
;
unsigned
long
lp_clk
;
...
...
@@ -1306,8 +1294,8 @@ static int dsi_lp_clock_calc(struct dsi_clock_info *cinfo,
if
(
lp_clk
<
lp_clk_min
||
lp_clk
>
lp_clk_max
)
return
-
EINVAL
;
cinfo
->
lp_clk_div
=
lp_clk_div
;
cinfo
->
lp_clk
=
lp_clk
;
lp_
cinfo
->
lp_clk_div
=
lp_clk_div
;
lp_
cinfo
->
lp_clk
=
lp_clk
;
return
0
;
}
...
...
@@ -1318,10 +1306,12 @@ static int dsi_set_lp_clk_divisor(struct platform_device *dsidev)
unsigned
long
dsi_fclk
;
unsigned
lp_clk_div
;
unsigned
long
lp_clk
;
unsigned
lpdiv_max
=
dss_feat_get_param_max
(
FEAT_PARAM_DSIPLL_LPDIV
);
lp_clk_div
=
dsi
->
user_dsi_cinfo
.
lp_clk_div
;
if
(
lp_clk_div
==
0
||
lp_clk_div
>
dsi
->
lpdiv_max
)
lp_clk_div
=
dsi
->
user_lp_cinfo
.
lp_clk_div
;
if
(
lp_clk_div
==
0
||
lp_clk_div
>
lpdiv_max
)
return
-
EINVAL
;
dsi_fclk
=
dsi_fclk_rate
(
dsidev
);
...
...
@@ -1329,8 +1319,8 @@ static int dsi_set_lp_clk_divisor(struct platform_device *dsidev)
lp_clk
=
dsi_fclk
/
2
/
lp_clk_div
;
DSSDBG
(
"LP_CLK_DIV %u, LP_CLK %lu
\n
"
,
lp_clk_div
,
lp_clk
);
dsi
->
current_cinfo
.
lp_clk
=
lp_clk
;
dsi
->
current_cinfo
.
lp_clk_div
=
lp_clk_div
;
dsi
->
current_
lp_
cinfo
.
lp_clk
=
lp_clk
;
dsi
->
current_
lp_
cinfo
.
lp_clk_div
=
lp_clk_div
;
/* LP_CLK_DIVISOR */
REG_FLD_MOD
(
dsidev
,
DSI_CLK_CTRL
,
lp_clk_div
,
12
,
0
);
...
...
@@ -1391,286 +1381,33 @@ static int dsi_pll_power(struct platform_device *dsidev,
return
0
;
}
unsigned
long
dsi_get_pll_clkin
(
struct
platform_device
*
dsidev
)
{
struct
dsi_data
*
dsi
=
dsi_get_dsidrv_data
(
dsidev
);
return
clk_get_rate
(
dsi
->
sys_clk
);
}
bool
dsi_hsdiv_calc
(
struct
platform_device
*
dsidev
,
unsigned
long
pll
,
unsigned
long
out_min
,
dsi_hsdiv_calc_func
func
,
void
*
data
)
{
struct
dsi_data
*
dsi
=
dsi_get_dsidrv_data
(
dsidev
);
int
regm
,
regm_start
,
regm_stop
;
unsigned
long
out_max
;
unsigned
long
out
;
out_min
=
out_min
?
out_min
:
1
;
out_max
=
dss_feat_get_param_max
(
FEAT_PARAM_DSS_FCK
);
regm_start
=
max
(
DIV_ROUND_UP
(
pll
,
out_max
),
1ul
);
regm_stop
=
min
(
pll
/
out_min
,
dsi
->
regm_dispc_max
);
for
(
regm
=
regm_start
;
regm
<=
regm_stop
;
++
regm
)
{
out
=
pll
/
regm
;
if
(
func
(
regm
,
out
,
data
))
return
true
;
}
return
false
;
}
bool
dsi_pll_calc
(
struct
platform_device
*
dsidev
,
unsigned
long
clkin
,
unsigned
long
pll_min
,
unsigned
long
pll_max
,
dsi_pll_calc_func
func
,
void
*
data
)
{
struct
dsi_data
*
dsi
=
dsi_get_dsidrv_data
(
dsidev
);
int
regn
,
regn_start
,
regn_stop
;
int
regm
,
regm_start
,
regm_stop
;
unsigned
long
fint
,
pll
;
const
unsigned
long
pll_hw_max
=
1800000000
;
unsigned
long
fint_hw_min
,
fint_hw_max
;
fint_hw_min
=
dsi
->
fint_min
;
fint_hw_max
=
dsi
->
fint_max
;
regn_start
=
max
(
DIV_ROUND_UP
(
clkin
,
fint_hw_max
),
1ul
);
regn_stop
=
min
(
clkin
/
fint_hw_min
,
dsi
->
regn_max
);
pll_max
=
pll_max
?
pll_max
:
ULONG_MAX
;
for
(
regn
=
regn_start
;
regn
<=
regn_stop
;
++
regn
)
{
fint
=
clkin
/
regn
;
regm_start
=
max
(
DIV_ROUND_UP
(
DIV_ROUND_UP
(
pll_min
,
fint
),
2
),
1ul
);
regm_stop
=
min3
(
pll_max
/
fint
/
2
,
pll_hw_max
/
fint
/
2
,
dsi
->
regm_max
);
for
(
regm
=
regm_start
;
regm
<=
regm_stop
;
++
regm
)
{
pll
=
2
*
regm
*
fint
;
if
(
func
(
regn
,
regm
,
fint
,
pll
,
data
))
return
true
;
}
}
return
false
;
}
/* calculate clock rates using dividers in cinfo */
static
int
dsi_calc_clock_rates
(
struct
platform_device
*
dsidev
,
struct
dsi_clock_info
*
cinfo
)
{
struct
dsi_data
*
dsi
=
dsi_get_dsidrv_data
(
dsidev
);
if
(
cinfo
->
regn
==
0
||
cinfo
->
regn
>
dsi
->
regn_max
)
return
-
EINVAL
;
if
(
cinfo
->
regm
==
0
||
cinfo
->
regm
>
dsi
->
regm_max
)
return
-
EINVAL
;
if
(
cinfo
->
regm_dispc
>
dsi
->
regm_dispc_max
)
return
-
EINVAL
;
if
(
cinfo
->
regm_dsi
>
dsi
->
regm_dsi_max
)
return
-
EINVAL
;
cinfo
->
clkin
=
clk_get_rate
(
dsi
->
sys_clk
);
cinfo
->
fint
=
cinfo
->
clkin
/
cinfo
->
regn
;
if
(
cinfo
->
fint
>
dsi
->
fint_max
||
cinfo
->
fint
<
dsi
->
fint_min
)
return
-
EINVAL
;
cinfo
->
clkin4ddr
=
2
*
cinfo
->
regm
*
cinfo
->
fint
;
if
(
cinfo
->
clkin4ddr
>
1800
*
1000
*
1000
)
return
-
EINVAL
;
if
(
cinfo
->
regm_dispc
>
0
)
cinfo
->
dsi_pll_hsdiv_dispc_clk
=
cinfo
->
clkin4ddr
/
cinfo
->
regm_dispc
;
else
cinfo
->
dsi_pll_hsdiv_dispc_clk
=
0
;
if
(
cinfo
->
regm_dsi
>
0
)
cinfo
->
dsi_pll_hsdiv_dsi_clk
=
cinfo
->
clkin4ddr
/
cinfo
->
regm_dsi
;
else
cinfo
->
dsi_pll_hsdiv_dsi_clk
=
0
;
return
0
;
}
static
void
dsi_pll_calc_dsi_fck
(
struct
dsi_clock_info
*
cinfo
)
static
void
dsi_pll_calc_dsi_fck
(
struct
dss_pll_clock_info
*
cinfo
)
{
unsigned
long
max_dsi_fck
;
max_dsi_fck
=
dss_feat_get_param_max
(
FEAT_PARAM_DSI_FCK
);
cinfo
->
regm_dsi
=
DIV_ROUND_UP
(
cinfo
->
clkin4ddr
,
max_dsi_fck
);
cinfo
->
dsi_pll_hsdiv_dsi_clk
=
cinfo
->
clkin4ddr
/
cinfo
->
regm_dsi
;
}
int
dsi_pll_set_clock_div
(
struct
platform_device
*
dsidev
,
struct
dsi_clock_info
*
cinfo
)
{
struct
dsi_data
*
dsi
=
dsi_get_dsidrv_data
(
dsidev
);
int
r
=
0
;
u32
l
;
int
f
=
0
;
u8
regn_start
,
regn_end
,
regm_start
,
regm_end
;
u8
regm_dispc_start
,
regm_dispc_end
,
regm_dsi_start
,
regm_dsi_end
;
DSSDBG
(
"DSI PLL clock config starts"
);
dsi
->
current_cinfo
.
clkin
=
cinfo
->
clkin
;
dsi
->
current_cinfo
.
fint
=
cinfo
->
fint
;
dsi
->
current_cinfo
.
clkin4ddr
=
cinfo
->
clkin4ddr
;
dsi
->
current_cinfo
.
dsi_pll_hsdiv_dispc_clk
=
cinfo
->
dsi_pll_hsdiv_dispc_clk
;
dsi
->
current_cinfo
.
dsi_pll_hsdiv_dsi_clk
=
cinfo
->
dsi_pll_hsdiv_dsi_clk
;
dsi
->
current_cinfo
.
regn
=
cinfo
->
regn
;
dsi
->
current_cinfo
.
regm
=
cinfo
->
regm
;
dsi
->
current_cinfo
.
regm_dispc
=
cinfo
->
regm_dispc
;
dsi
->
current_cinfo
.
regm_dsi
=
cinfo
->
regm_dsi
;
DSSDBG
(
"DSI Fint %ld
\n
"
,
cinfo
->
fint
);
DSSDBG
(
"clkin rate %ld
\n
"
,
cinfo
->
clkin
);
/* DSIPHY == CLKIN4DDR */
DSSDBG
(
"CLKIN4DDR = 2 * %d / %d * %lu = %lu
\n
"
,
cinfo
->
regm
,
cinfo
->
regn
,
cinfo
->
clkin
,
cinfo
->
clkin4ddr
);
DSSDBG
(
"Data rate on 1 DSI lane %ld Mbps
\n
"
,
cinfo
->
clkin4ddr
/
1000
/
1000
/
2
);
DSSDBG
(
"Clock lane freq %ld Hz
\n
"
,
cinfo
->
clkin4ddr
/
4
);
DSSDBG
(
"regm_dispc = %d, %s (%s) = %lu
\n
"
,
cinfo
->
regm_dispc
,
dss_get_generic_clk_source_name
(
OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC
),
dss_feat_get_clk_source_name
(
OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC
),
cinfo
->
dsi_pll_hsdiv_dispc_clk
);
DSSDBG
(
"regm_dsi = %d, %s (%s) = %lu
\n
"
,
cinfo
->
regm_dsi
,
dss_get_generic_clk_source_name
(
OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI
),
dss_feat_get_clk_source_name
(
OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI
),
cinfo
->
dsi_pll_hsdiv_dsi_clk
);
dss_feat_get_reg_field
(
FEAT_REG_DSIPLL_REGN
,
&
regn_start
,
&
regn_end
);
dss_feat_get_reg_field
(
FEAT_REG_DSIPLL_REGM
,
&
regm_start
,
&
regm_end
);
dss_feat_get_reg_field
(
FEAT_REG_DSIPLL_REGM_DISPC
,
&
regm_dispc_start
,
&
regm_dispc_end
);
dss_feat_get_reg_field
(
FEAT_REG_DSIPLL_REGM_DSI
,
&
regm_dsi_start
,
&
regm_dsi_end
);
/* DSI_PLL_AUTOMODE = manual */
REG_FLD_MOD
(
dsidev
,
DSI_PLL_CONTROL
,
0
,
0
,
0
);
l
=
dsi_read_reg
(
dsidev
,
DSI_PLL_CONFIGURATION1
);
l
=
FLD_MOD
(
l
,
1
,
0
,
0
);
/* DSI_PLL_STOPMODE */
/* DSI_PLL_REGN */
l
=
FLD_MOD
(
l
,
cinfo
->
regn
-
1
,
regn_start
,
regn_end
);
/* DSI_PLL_REGM */
l
=
FLD_MOD
(
l
,
cinfo
->
regm
,
regm_start
,
regm_end
);
/* DSI_CLOCK_DIV */
l
=
FLD_MOD
(
l
,
cinfo
->
regm_dispc
>
0
?
cinfo
->
regm_dispc
-
1
:
0
,
regm_dispc_start
,
regm_dispc_end
);
/* DSIPROTO_CLOCK_DIV */
l
=
FLD_MOD
(
l
,
cinfo
->
regm_dsi
>
0
?
cinfo
->
regm_dsi
-
1
:
0
,
regm_dsi_start
,
regm_dsi_end
);
dsi_write_reg
(
dsidev
,
DSI_PLL_CONFIGURATION1
,
l
);
BUG_ON
(
cinfo
->
fint
<
dsi
->
fint_min
||
cinfo
->
fint
>
dsi
->
fint_max
);
l
=
dsi_read_reg
(
dsidev
,
DSI_PLL_CONFIGURATION2
);
if
(
dss_has_feature
(
FEAT_DSI_PLL_FREQSEL
))
{
f
=
cinfo
->
fint
<
1000000
?
0x3
:
cinfo
->
fint
<
1250000
?
0x4
:
cinfo
->
fint
<
1500000
?
0x5
:
cinfo
->
fint
<
1750000
?
0x6
:
0x7
;
l
=
FLD_MOD
(
l
,
f
,
4
,
1
);
/* DSI_PLL_FREQSEL */
}
else
if
(
dss_has_feature
(
FEAT_DSI_PLL_SELFREQDCO
))
{
f
=
cinfo
->
clkin4ddr
<
1000000000
?
0x2
:
0x4
;
l
=
FLD_MOD
(
l
,
f
,
3
,
1
);
/* PLL_SELFREQDCO */
}
l
=
FLD_MOD
(
l
,
1
,
13
,
13
);
/* DSI_PLL_REFEN */
l
=
FLD_MOD
(
l
,
0
,
14
,
14
);
/* DSIPHY_CLKINEN */
l
=
FLD_MOD
(
l
,
1
,
20
,
20
);
/* DSI_HSDIVBYPASS */
if
(
dss_has_feature
(
FEAT_DSI_PLL_REFSEL
))
l
=
FLD_MOD
(
l
,
3
,
22
,
21
);
/* REF_SYSCLK = sysclk */
dsi_write_reg
(
dsidev
,
DSI_PLL_CONFIGURATION2
,
l
);
REG_FLD_MOD
(
dsidev
,
DSI_PLL_GO
,
1
,
0
,
0
);
/* DSI_PLL_GO */
if
(
wait_for_bit_change
(
dsidev
,
DSI_PLL_GO
,
0
,
0
)
!=
0
)
{
DSSERR
(
"dsi pll go bit not going down.
\n
"
);
r
=
-
EIO
;
goto
err
;
}
if
(
wait_for_bit_change
(
dsidev
,
DSI_PLL_STATUS
,
1
,
1
)
!=
1
)
{
DSSERR
(
"cannot lock PLL
\n
"
);
r
=
-
EIO
;
goto
err
;
}
dsi
->
pll_locked
=
1
;
l
=
dsi_read_reg
(
dsidev
,
DSI_PLL_CONFIGURATION2
);
l
=
FLD_MOD
(
l
,
0
,
0
,
0
);
/* DSI_PLL_IDLE */
l
=
FLD_MOD
(
l
,
0
,
5
,
5
);
/* DSI_PLL_PLLLPMODE */
l
=
FLD_MOD
(
l
,
0
,
6
,
6
);
/* DSI_PLL_LOWCURRSTBY */
l
=
FLD_MOD
(
l
,
0
,
7
,
7
);
/* DSI_PLL_TIGHTPHASELOCK */
l
=
FLD_MOD
(
l
,
0
,
8
,
8
);
/* DSI_PLL_DRIFTGUARDEN */
l
=
FLD_MOD
(
l
,
0
,
10
,
9
);
/* DSI_PLL_LOCKSEL */
l
=
FLD_MOD
(
l
,
1
,
13
,
13
);
/* DSI_PLL_REFEN */
l
=
FLD_MOD
(
l
,
1
,
14
,
14
);
/* DSIPHY_CLKINEN */
l
=
FLD_MOD
(
l
,
0
,
15
,
15
);
/* DSI_BYPASSEN */
l
=
FLD_MOD
(
l
,
1
,
16
,
16
);
/* DSS_CLOCK_EN */
l
=
FLD_MOD
(
l
,
0
,
17
,
17
);
/* DSS_CLOCK_PWDN */
l
=
FLD_MOD
(
l
,
1
,
18
,
18
);
/* DSI_PROTO_CLOCK_EN */
l
=
FLD_MOD
(
l
,
0
,
19
,
19
);
/* DSI_PROTO_CLOCK_PWDN */
l
=
FLD_MOD
(
l
,
0
,
20
,
20
);
/* DSI_HSDIVBYPASS */
dsi_write_reg
(
dsidev
,
DSI_PLL_CONFIGURATION2
,
l
);
DSSDBG
(
"PLL config done
\n
"
);
err:
return
r
;
cinfo
->
mX
[
HSDIV_DSI
]
=
DIV_ROUND_UP
(
cinfo
->
clkdco
,
max_dsi_fck
);
cinfo
->
clkout
[
HSDIV_DSI
]
=
cinfo
->
clkdco
/
cinfo
->
mX
[
HSDIV_DSI
];
}
int
dsi_pll_init
(
struct
platform_device
*
dsidev
,
bool
enable_hsclk
,
bool
enable_hsdiv
)
static
int
dsi_pll_enable
(
struct
dss_pll
*
pll
)
{
struct
dsi_data
*
dsi
=
dsi_get_dsidrv_data
(
dsidev
);
struct
dsi_data
*
dsi
=
container_of
(
pll
,
struct
dsi_data
,
pll
);
struct
platform_device
*
dsidev
=
dsi
->
pdev
;
int
r
=
0
;
enum
dsi_pll_power_state
pwstate
;
DSSDBG
(
"PLL init
\n
"
);
/*
* It seems that on many OMAPs we need to enable both to have a
* functional HSDivider.
*/
enable_hsclk
=
enable_hsdiv
=
true
;
r
=
dsi_regulator_init
(
dsidev
);
if
(
r
)
return
r
;
dsi_enable_pll_clock
(
dsidev
,
1
);
r
=
dsi_runtime_get
(
dsidev
);
if
(
r
)
return
r
;
/*
* Note: SCP CLK is not required on OMAP3, but it is required on OMAP4.
*/
...
...
@@ -1697,16 +1434,7 @@ int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk,
* fill the whole display. No idea about this */
dispc_pck_free_enable
(
0
);
if
(
enable_hsclk
&&
enable_hsdiv
)
pwstate
=
DSI_PLL_POWER_ON_ALL
;
else
if
(
enable_hsclk
)
pwstate
=
DSI_PLL_POWER_ON_HSCLK
;
else
if
(
enable_hsdiv
)
pwstate
=
DSI_PLL_POWER_ON_DIV
;
else
pwstate
=
DSI_PLL_POWER_OFF
;
r
=
dsi_pll_power
(
dsidev
,
pwstate
);
r
=
dsi_pll_power
(
dsidev
,
DSI_PLL_POWER_ON_ALL
);
if
(
r
)
goto
err1
;
...
...
@@ -1721,15 +1449,14 @@ int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk,
}
err0:
dsi_disable_scp_clk
(
dsidev
);
dsi_
enable_pll_clock
(
dsidev
,
0
);
dsi_
runtime_put
(
dsidev
);
return
r
;
}
void
dsi_pll_uninit
(
struct
platform_device
*
dsidev
,
bool
disconnect_lanes
)
static
void
dsi_pll_uninit
(
struct
platform_device
*
dsidev
,
bool
disconnect_lanes
)
{
struct
dsi_data
*
dsi
=
dsi_get_dsidrv_data
(
dsidev
);
dsi
->
pll_locked
=
0
;
dsi_pll_power
(
dsidev
,
DSI_PLL_POWER_OFF
);
if
(
disconnect_lanes
)
{
WARN_ON
(
!
dsi
->
vdds_dsi_enabled
);
...
...
@@ -1738,18 +1465,27 @@ void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes)
}
dsi_disable_scp_clk
(
dsidev
);
dsi_
enable_pll_clock
(
dsidev
,
0
);
dsi_
runtime_put
(
dsidev
);
DSSDBG
(
"PLL uninit done
\n
"
);
}
static
void
dsi_pll_disable
(
struct
dss_pll
*
pll
)
{
struct
dsi_data
*
dsi
=
container_of
(
pll
,
struct
dsi_data
,
pll
);
struct
platform_device
*
dsidev
=
dsi
->
pdev
;
dsi_pll_uninit
(
dsidev
,
true
);
}
static
void
dsi_dump_dsidev_clocks
(
struct
platform_device
*
dsidev
,
struct
seq_file
*
s
)
{
struct
dsi_data
*
dsi
=
dsi_get_dsidrv_data
(
dsidev
);
struct
ds
i_clock_info
*
cinfo
=
&
dsi
->
current_
cinfo
;
struct
ds
s_pll_clock_info
*
cinfo
=
&
dsi
->
pll
.
cinfo
;
enum
omap_dss_clk_source
dispc_clk_src
,
dsi_clk_src
;
int
dsi_module
=
dsi
->
module_id
;
struct
dss_pll
*
pll
=
&
dsi
->
pll
;
dispc_clk_src
=
dss_get_dispc_clk_source
();
dsi_clk_src
=
dss_get_dsi_clk_source
(
dsi_module
);
...
...
@@ -1759,28 +1495,28 @@ static void dsi_dump_dsidev_clocks(struct platform_device *dsidev,
seq_printf
(
s
,
"- DSI%d PLL -
\n
"
,
dsi_module
+
1
);
seq_printf
(
s
,
"dsi pll clkin
\t
%lu
\n
"
,
c
info
->
clkin
);
seq_printf
(
s
,
"dsi pll clkin
\t
%lu
\n
"
,
c
lk_get_rate
(
pll
->
clkin
)
);
seq_printf
(
s
,
"Fint
\t\t
%-16lu
regn %u
\n
"
,
cinfo
->
fint
,
cinfo
->
reg
n
);
seq_printf
(
s
,
"Fint
\t\t
%-16lu
n %u
\n
"
,
cinfo
->
fint
,
cinfo
->
n
);
seq_printf
(
s
,
"CLKIN4DDR
\t
%-16lu
reg
m %u
\n
"
,
cinfo
->
clk
in4ddr
,
cinfo
->
reg
m
);
seq_printf
(
s
,
"CLKIN4DDR
\t
%-16lum %u
\n
"
,
cinfo
->
clk
dco
,
cinfo
->
m
);
seq_printf
(
s
,
"DSI_PLL_HSDIV_DISPC (%s)
\t
%-16lu
reg
m_dispc %u
\t
(%s)
\n
"
,
seq_printf
(
s
,
"DSI_PLL_HSDIV_DISPC (%s)
\t
%-16lum_dispc %u
\t
(%s)
\n
"
,
dss_feat_get_clk_source_name
(
dsi_module
==
0
?
OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC
:
OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC
),
cinfo
->
dsi_pll_hsdiv_dispc_clk
,
cinfo
->
regm_dispc
,
cinfo
->
clkout
[
HSDIV_DISPC
]
,
cinfo
->
mX
[
HSDIV_DISPC
]
,
dispc_clk_src
==
OMAP_DSS_CLK_SRC_FCK
?
"off"
:
"on"
);
seq_printf
(
s
,
"DSI_PLL_HSDIV_DSI (%s)
\t
%-16lu
reg
m_dsi %u
\t
(%s)
\n
"
,
seq_printf
(
s
,
"DSI_PLL_HSDIV_DSI (%s)
\t
%-16lum_dsi %u
\t
(%s)
\n
"
,
dss_feat_get_clk_source_name
(
dsi_module
==
0
?
OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI
:
OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI
),
cinfo
->
dsi_pll_hsdiv_dsi_clk
,
cinfo
->
regm_dsi
,
cinfo
->
clkout
[
HSDIV_DSI
]
,
cinfo
->
mX
[
HSDIV_DSI
]
,
dsi_clk_src
==
OMAP_DSS_CLK_SRC_FCK
?
"off"
:
"on"
);
...
...
@@ -1793,11 +1529,11 @@ static void dsi_dump_dsidev_clocks(struct platform_device *dsidev,
seq_printf
(
s
,
"DSI_FCLK
\t
%lu
\n
"
,
dsi_fclk_rate
(
dsidev
));
seq_printf
(
s
,
"DDR_CLK
\t\t
%lu
\n
"
,
cinfo
->
clk
in4ddr
/
4
);
cinfo
->
clk
dco
/
4
);
seq_printf
(
s
,
"TxByteClkHS
\t
%lu
\n
"
,
dsi_get_txbyteclkhs
(
dsidev
));
seq_printf
(
s
,
"LP_CLK
\t\t
%lu
\n
"
,
cinfo
->
lp_clk
);
seq_printf
(
s
,
"LP_CLK
\t\t
%lu
\n
"
,
dsi
->
current_lp_cinfo
.
lp_clk
);
dsi_runtime_put
(
dsidev
);
}
...
...
@@ -2132,7 +1868,7 @@ static inline unsigned ns2ddr(struct platform_device *dsidev, unsigned ns)
struct
dsi_data
*
dsi
=
dsi_get_dsidrv_data
(
dsidev
);
/* convert time in ns to ddr ticks, rounding up */
unsigned
long
ddr_clk
=
dsi
->
current_cinfo
.
clkin4ddr
/
4
;
unsigned
long
ddr_clk
=
dsi
->
pll
.
cinfo
.
clkdco
/
4
;
return
(
ns
*
(
ddr_clk
/
1000
/
1000
)
+
999
)
/
1000
;
}
...
...
@@ -2140,7 +1876,7 @@ static inline unsigned ddr2ns(struct platform_device *dsidev, unsigned ddr)
{
struct
dsi_data
*
dsi
=
dsi_get_dsidrv_data
(
dsidev
);
unsigned
long
ddr_clk
=
dsi
->
current_cinfo
.
clkin4ddr
/
4
;
unsigned
long
ddr_clk
=
dsi
->
pll
.
cinfo
.
clkdco
/
4
;
return
ddr
*
1000
*
1000
/
(
ddr_clk
/
1000
);
}
...
...
@@ -3730,7 +3466,7 @@ static void dsi_config_cmd_mode_interleaving(struct platform_device *dsidev)
struct
omap_video_timings
*
timings
=
&
dsi
->
timings
;
int
bpp
=
dsi_get_pixel_size
(
dsi
->
pix_fmt
);
int
ndl
=
dsi
->
num_lanes_used
-
1
;
int
dsi_fclk_hsdiv
=
dsi
->
user_dsi_cinfo
.
regm_dsi
+
1
;
int
dsi_fclk_hsdiv
=
dsi
->
user_dsi_cinfo
.
mX
[
HSDIV_DSI
]
+
1
;
int
hsa_interleave_hs
=
0
,
hsa_interleave_lp
=
0
;
int
hfp_interleave_hs
=
0
,
hfp_interleave_lp
=
0
;
int
hbp_interleave_hs
=
0
,
hbp_interleave_lp
=
0
;
...
...
@@ -4441,18 +4177,12 @@ static void dsi_display_uninit_dispc(struct platform_device *dsidev,
static
int
dsi_configure_dsi_clocks
(
struct
platform_device
*
dsidev
)
{
struct
dsi_data
*
dsi
=
dsi_get_dsidrv_data
(
dsidev
);
struct
ds
i
_clock_info
cinfo
;
struct
ds
s_pll
_clock_info
cinfo
;
int
r
;
cinfo
=
dsi
->
user_dsi_cinfo
;
r
=
dsi_calc_clock_rates
(
dsidev
,
&
cinfo
);
if
(
r
)
{
DSSERR
(
"Failed to calc dsi clocks
\n
"
);
return
r
;
}
r
=
dsi_pll_set_clock_div
(
dsidev
,
&
cinfo
);
r
=
dss_pll_set_config
(
&
dsi
->
pll
,
&
cinfo
);
if
(
r
)
{
DSSERR
(
"Failed to set dsi clocks
\n
"
);
return
r
;
...
...
@@ -4466,7 +4196,7 @@ static int dsi_display_init_dsi(struct platform_device *dsidev)
struct
dsi_data
*
dsi
=
dsi_get_dsidrv_data
(
dsidev
);
int
r
;
r
=
ds
i_pll_init
(
dsidev
,
true
,
true
);
r
=
ds
s_pll_enable
(
&
dsi
->
pll
);
if
(
r
)
goto
err0
;
...
...
@@ -4510,7 +4240,7 @@ static int dsi_display_init_dsi(struct platform_device *dsidev)
err2:
dss_select_dsi_clk_source
(
dsi
->
module_id
,
OMAP_DSS_CLK_SRC_FCK
);
err1:
ds
i_pll_uninit
(
dsidev
,
true
);
ds
s_pll_disable
(
&
dsi
->
pll
);
err0:
return
r
;
}
...
...
@@ -4551,8 +4281,6 @@ static int dsi_display_enable(struct omap_dss_device *dssdev)
if
(
r
)
goto
err_get_dsi
;
dsi_enable_pll_clock
(
dsidev
,
1
);
_dsi_initialize_irq
(
dsidev
);
r
=
dsi_display_init_dsi
(
dsidev
);
...
...
@@ -4564,7 +4292,6 @@ static int dsi_display_enable(struct omap_dss_device *dssdev)
return
0
;
err_init_dsi:
dsi_enable_pll_clock
(
dsidev
,
0
);
dsi_runtime_put
(
dsidev
);
err_get_dsi:
mutex_unlock
(
&
dsi
->
lock
);
...
...
@@ -4592,7 +4319,6 @@ static void dsi_display_disable(struct omap_dss_device *dssdev,
dsi_display_uninit_dsi
(
dsidev
,
disconnect_lanes
,
enter_ulps
);
dsi_runtime_put
(
dsidev
);
dsi_enable_pll_clock
(
dsidev
,
0
);
mutex_unlock
(
&
dsi
->
lock
);
}
...
...
@@ -4713,29 +4439,30 @@ static bool dsi_cm_calc_dispc_cb(int lckd, int pckd, unsigned long lck,
return
true
;
}
static
bool
dsi_cm_calc_hsdiv_cb
(
int
reg
m_dispc
,
unsigned
long
dispc
,
static
bool
dsi_cm_calc_hsdiv_cb
(
int
m_dispc
,
unsigned
long
dispc
,
void
*
data
)
{
struct
dsi_clk_calc_ctx
*
ctx
=
data
;
ctx
->
dsi_cinfo
.
regm_dispc
=
reg
m_dispc
;
ctx
->
dsi_cinfo
.
dsi_pll_hsdiv_dispc_clk
=
dispc
;
ctx
->
dsi_cinfo
.
mX
[
HSDIV_DISPC
]
=
m_dispc
;
ctx
->
dsi_cinfo
.
clkout
[
HSDIV_DISPC
]
=
dispc
;
return
dispc_div_calc
(
dispc
,
ctx
->
req_pck_min
,
ctx
->
req_pck_max
,
dsi_cm_calc_dispc_cb
,
ctx
);
}
static
bool
dsi_cm_calc_pll_cb
(
int
regn
,
int
reg
m
,
unsigned
long
fint
,
unsigned
long
pll
,
void
*
data
)
static
bool
dsi_cm_calc_pll_cb
(
int
n
,
int
m
,
unsigned
long
fint
,
unsigned
long
clkdco
,
void
*
data
)
{
struct
dsi_clk_calc_ctx
*
ctx
=
data
;
ctx
->
dsi_cinfo
.
regn
=
reg
n
;
ctx
->
dsi_cinfo
.
regm
=
reg
m
;
ctx
->
dsi_cinfo
.
n
=
n
;
ctx
->
dsi_cinfo
.
m
=
m
;
ctx
->
dsi_cinfo
.
fint
=
fint
;
ctx
->
dsi_cinfo
.
clk
in4ddr
=
pll
;
ctx
->
dsi_cinfo
.
clk
dco
=
clkdco
;
return
dsi_hsdiv_calc
(
ctx
->
dsidev
,
pll
,
ctx
->
req_pck_min
,
return
dss_pll_hsdiv_calc
(
ctx
->
pll
,
clkdco
,
ctx
->
req_pck_min
,
dss_feat_get_param_max
(
FEAT_PARAM_DSS_FCK
),
dsi_cm_calc_hsdiv_cb
,
ctx
);
}
...
...
@@ -4748,7 +4475,7 @@ static bool dsi_cm_calc(struct dsi_data *dsi,
unsigned
long
pll_min
,
pll_max
;
unsigned
long
pck
,
txbyteclk
;
clkin
=
clk_get_rate
(
dsi
->
sys_clk
);
clkin
=
clk_get_rate
(
dsi
->
pll
.
clkin
);
bitspp
=
dsi_get_pixel_size
(
cfg
->
pixel_format
);
ndl
=
dsi
->
num_lanes_used
-
1
;
...
...
@@ -4764,16 +4491,16 @@ static bool dsi_cm_calc(struct dsi_data *dsi,
memset
(
ctx
,
0
,
sizeof
(
*
ctx
));
ctx
->
dsidev
=
dsi
->
pdev
;
ctx
->
pll
=
&
dsi
->
pll
;
ctx
->
config
=
cfg
;
ctx
->
req_pck_min
=
pck
;
ctx
->
req_pck_nom
=
pck
;
ctx
->
req_pck_max
=
pck
*
3
/
2
;
ctx
->
dsi_cinfo
.
clkin
=
clkin
;
pll_min
=
max
(
cfg
->
hs_clk_min
*
4
,
txbyteclk
*
4
*
4
);
pll_max
=
cfg
->
hs_clk_max
*
4
;
return
ds
i_pll_calc
(
dsi
->
pdev
,
clkin
,
return
ds
s_pll_calc
(
ctx
->
pll
,
clkin
,
pll_min
,
pll_max
,
dsi_cm_calc_pll_cb
,
ctx
);
}
...
...
@@ -4784,7 +4511,7 @@ static bool dsi_vm_calc_blanking(struct dsi_clk_calc_ctx *ctx)
const
struct
omap_dss_dsi_config
*
cfg
=
ctx
->
config
;
int
bitspp
=
dsi_get_pixel_size
(
cfg
->
pixel_format
);
int
ndl
=
dsi
->
num_lanes_used
-
1
;
unsigned
long
hsclk
=
ctx
->
dsi_cinfo
.
clk
in4ddr
/
4
;
unsigned
long
hsclk
=
ctx
->
dsi_cinfo
.
clk
dco
/
4
;
unsigned
long
byteclk
=
hsclk
/
4
;
unsigned
long
dispc_pck
,
req_pck_min
,
req_pck_nom
,
req_pck_max
;
...
...
@@ -4999,14 +4726,14 @@ static bool dsi_vm_calc_dispc_cb(int lckd, int pckd, unsigned long lck,
return
true
;
}
static
bool
dsi_vm_calc_hsdiv_cb
(
int
reg
m_dispc
,
unsigned
long
dispc
,
static
bool
dsi_vm_calc_hsdiv_cb
(
int
m_dispc
,
unsigned
long
dispc
,
void
*
data
)
{
struct
dsi_clk_calc_ctx
*
ctx
=
data
;
unsigned
long
pck_max
;
ctx
->
dsi_cinfo
.
regm_dispc
=
reg
m_dispc
;
ctx
->
dsi_cinfo
.
dsi_pll_hsdiv_dispc_clk
=
dispc
;
ctx
->
dsi_cinfo
.
mX
[
HSDIV_DISPC
]
=
m_dispc
;
ctx
->
dsi_cinfo
.
clkout
[
HSDIV_DISPC
]
=
dispc
;
/*
* In burst mode we can let the dispc pck be arbitrarily high, but it
...
...
@@ -5022,17 +4749,18 @@ static bool dsi_vm_calc_hsdiv_cb(int regm_dispc, unsigned long dispc,
dsi_vm_calc_dispc_cb
,
ctx
);
}
static
bool
dsi_vm_calc_pll_cb
(
int
regn
,
int
reg
m
,
unsigned
long
fint
,
unsigned
long
pll
,
void
*
data
)
static
bool
dsi_vm_calc_pll_cb
(
int
n
,
int
m
,
unsigned
long
fint
,
unsigned
long
clkdco
,
void
*
data
)
{
struct
dsi_clk_calc_ctx
*
ctx
=
data
;
ctx
->
dsi_cinfo
.
regn
=
reg
n
;
ctx
->
dsi_cinfo
.
regm
=
reg
m
;
ctx
->
dsi_cinfo
.
n
=
n
;
ctx
->
dsi_cinfo
.
m
=
m
;
ctx
->
dsi_cinfo
.
fint
=
fint
;
ctx
->
dsi_cinfo
.
clk
in4ddr
=
pll
;
ctx
->
dsi_cinfo
.
clk
dco
=
clkdco
;
return
dsi_hsdiv_calc
(
ctx
->
dsidev
,
pll
,
ctx
->
req_pck_min
,
return
dss_pll_hsdiv_calc
(
ctx
->
pll
,
clkdco
,
ctx
->
req_pck_min
,
dss_feat_get_param_max
(
FEAT_PARAM_DSS_FCK
),
dsi_vm_calc_hsdiv_cb
,
ctx
);
}
...
...
@@ -5048,14 +4776,13 @@ static bool dsi_vm_calc(struct dsi_data *dsi,
int
bitspp
=
dsi_get_pixel_size
(
cfg
->
pixel_format
);
unsigned
long
byteclk_min
;
clkin
=
clk_get_rate
(
dsi
->
sys_clk
);
clkin
=
clk_get_rate
(
dsi
->
pll
.
clkin
);
memset
(
ctx
,
0
,
sizeof
(
*
ctx
));
ctx
->
dsidev
=
dsi
->
pdev
;
ctx
->
pll
=
&
dsi
->
pll
;
ctx
->
config
=
cfg
;
ctx
->
dsi_cinfo
.
clkin
=
clkin
;
/* these limits should come from the panel driver */
ctx
->
req_pck_min
=
t
->
pixelclock
-
1000
;
ctx
->
req_pck_nom
=
t
->
pixelclock
;
...
...
@@ -5074,7 +4801,7 @@ static bool dsi_vm_calc(struct dsi_data *dsi,
pll_max
=
byteclk_max
*
4
*
4
;
}
return
ds
i_pll_calc
(
dsi
->
pdev
,
clkin
,
return
ds
s_pll_calc
(
ctx
->
pll
,
clkin
,
pll_min
,
pll_max
,
dsi_vm_calc_pll_cb
,
ctx
);
}
...
...
@@ -5106,8 +4833,8 @@ static int dsi_set_config(struct omap_dss_device *dssdev,
dsi_pll_calc_dsi_fck
(
&
ctx
.
dsi_cinfo
);
r
=
dsi_lp_clock_calc
(
&
ctx
.
dsi_cinfo
,
config
->
lp_clk_min
,
config
->
lp_clk_max
);
r
=
dsi_lp_clock_calc
(
ctx
.
dsi_cinfo
.
clkout
[
HSDIV_DSI
]
,
config
->
lp_clk_min
,
config
->
lp_clk_max
,
&
dsi
->
user_lp_cinfo
);
if
(
r
)
{
DSSERR
(
"failed to find suitable DSI LP clock settings
\n
"
);
goto
err
;
...
...
@@ -5234,35 +4961,6 @@ static void dsi_release_vc(struct omap_dss_device *dssdev, int channel)
}
}
void
dsi_wait_pll_hsdiv_dispc_active
(
struct
platform_device
*
dsidev
)
{
if
(
wait_for_bit_change
(
dsidev
,
DSI_PLL_STATUS
,
7
,
1
)
!=
1
)
DSSERR
(
"%s (%s) not active
\n
"
,
dss_get_generic_clk_source_name
(
OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC
),
dss_feat_get_clk_source_name
(
OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC
));
}
void
dsi_wait_pll_hsdiv_dsi_active
(
struct
platform_device
*
dsidev
)
{
if
(
wait_for_bit_change
(
dsidev
,
DSI_PLL_STATUS
,
8
,
1
)
!=
1
)
DSSERR
(
"%s (%s) not active
\n
"
,
dss_get_generic_clk_source_name
(
OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI
),
dss_feat_get_clk_source_name
(
OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI
));
}
static
void
dsi_calc_clock_param_ranges
(
struct
platform_device
*
dsidev
)
{
struct
dsi_data
*
dsi
=
dsi_get_dsidrv_data
(
dsidev
);
dsi
->
regn_max
=
dss_feat_get_param_max
(
FEAT_PARAM_DSIPLL_REGN
);
dsi
->
regm_max
=
dss_feat_get_param_max
(
FEAT_PARAM_DSIPLL_REGM
);
dsi
->
regm_dispc_max
=
dss_feat_get_param_max
(
FEAT_PARAM_DSIPLL_REGM_DISPC
);
dsi
->
regm_dsi_max
=
dss_feat_get_param_max
(
FEAT_PARAM_DSIPLL_REGM_DSI
);
dsi
->
fint_min
=
dss_feat_get_param_min
(
FEAT_PARAM_DSIPLL_FINT
);
dsi
->
fint_max
=
dss_feat_get_param_max
(
FEAT_PARAM_DSIPLL_FINT
);
dsi
->
lpdiv_max
=
dss_feat_get_param_max
(
FEAT_PARAM_DSIPLL_LPDIV
);
}
static
int
dsi_get_clocks
(
struct
platform_device
*
dsidev
)
{
...
...
@@ -5277,14 +4975,6 @@ static int dsi_get_clocks(struct platform_device *dsidev)
dsi
->
dss_clk
=
clk
;
clk
=
devm_clk_get
(
&
dsidev
->
dev
,
"sys_clk"
);
if
(
IS_ERR
(
clk
))
{
DSSERR
(
"can't get sys_clk
\n
"
);
return
PTR_ERR
(
clk
);
}
dsi
->
sys_clk
=
clk
;
return
0
;
}
...
...
@@ -5453,6 +5143,135 @@ static int dsi_probe_of(struct platform_device *pdev)
return
r
;
}
static
const
struct
dss_pll_ops
dsi_pll_ops
=
{
.
enable
=
dsi_pll_enable
,
.
disable
=
dsi_pll_disable
,
.
set_config
=
dss_pll_write_config_type_a
,
};
static
const
struct
dss_pll_hw
dss_omap3_dsi_pll_hw
=
{
.
n_max
=
(
1
<<
7
)
-
1
,
.
m_max
=
(
1
<<
11
)
-
1
,
.
mX_max
=
(
1
<<
4
)
-
1
,
.
fint_min
=
750000
,
.
fint_max
=
2100000
,
.
clkdco_low
=
1000000000
,
.
clkdco_max
=
1800000000
,
.
n_msb
=
7
,
.
n_lsb
=
1
,
.
m_msb
=
18
,
.
m_lsb
=
8
,
.
mX_msb
[
0
]
=
22
,
.
mX_lsb
[
0
]
=
19
,
.
mX_msb
[
1
]
=
26
,
.
mX_lsb
[
1
]
=
23
,
.
has_stopmode
=
true
,
.
has_freqsel
=
true
,
.
has_selfreqdco
=
false
,
.
has_refsel
=
false
,
};
static
const
struct
dss_pll_hw
dss_omap4_dsi_pll_hw
=
{
.
n_max
=
(
1
<<
8
)
-
1
,
.
m_max
=
(
1
<<
12
)
-
1
,
.
mX_max
=
(
1
<<
5
)
-
1
,
.
fint_min
=
500000
,
.
fint_max
=
2500000
,
.
clkdco_low
=
1000000000
,
.
clkdco_max
=
1800000000
,
.
n_msb
=
8
,
.
n_lsb
=
1
,
.
m_msb
=
20
,
.
m_lsb
=
9
,
.
mX_msb
[
0
]
=
25
,
.
mX_lsb
[
0
]
=
21
,
.
mX_msb
[
1
]
=
30
,
.
mX_lsb
[
1
]
=
26
,
.
has_stopmode
=
true
,
.
has_freqsel
=
false
,
.
has_selfreqdco
=
false
,
.
has_refsel
=
false
,
};
static
const
struct
dss_pll_hw
dss_omap5_dsi_pll_hw
=
{
.
n_max
=
(
1
<<
8
)
-
1
,
.
m_max
=
(
1
<<
12
)
-
1
,
.
mX_max
=
(
1
<<
5
)
-
1
,
.
fint_min
=
150000
,
.
fint_max
=
52000000
,
.
clkdco_low
=
1000000000
,
.
clkdco_max
=
1800000000
,
.
n_msb
=
8
,
.
n_lsb
=
1
,
.
m_msb
=
20
,
.
m_lsb
=
9
,
.
mX_msb
[
0
]
=
25
,
.
mX_lsb
[
0
]
=
21
,
.
mX_msb
[
1
]
=
30
,
.
mX_lsb
[
1
]
=
26
,
.
has_stopmode
=
true
,
.
has_freqsel
=
false
,
.
has_selfreqdco
=
true
,
.
has_refsel
=
true
,
};
static
int
dsi_init_pll_data
(
struct
platform_device
*
dsidev
)
{
struct
dsi_data
*
dsi
=
dsi_get_dsidrv_data
(
dsidev
);
struct
dss_pll
*
pll
=
&
dsi
->
pll
;
struct
clk
*
clk
;
int
r
;
clk
=
devm_clk_get
(
&
dsidev
->
dev
,
"sys_clk"
);
if
(
IS_ERR
(
clk
))
{
DSSERR
(
"can't get sys_clk
\n
"
);
return
PTR_ERR
(
clk
);
}
pll
->
name
=
dsi
->
module_id
==
0
?
"dsi0"
:
"dsi1"
;
pll
->
clkin
=
clk
;
pll
->
base
=
dsi
->
pll_base
;
switch
(
omapdss_get_version
())
{
case
OMAPDSS_VER_OMAP34xx_ES1
:
case
OMAPDSS_VER_OMAP34xx_ES3
:
case
OMAPDSS_VER_OMAP3630
:
case
OMAPDSS_VER_AM35xx
:
pll
->
hw
=
&
dss_omap3_dsi_pll_hw
;
break
;
case
OMAPDSS_VER_OMAP4430_ES1
:
case
OMAPDSS_VER_OMAP4430_ES2
:
case
OMAPDSS_VER_OMAP4
:
pll
->
hw
=
&
dss_omap4_dsi_pll_hw
;
break
;
case
OMAPDSS_VER_OMAP5
:
pll
->
hw
=
&
dss_omap5_dsi_pll_hw
;
break
;
default:
return
-
ENODEV
;
}
pll
->
ops
=
&
dsi_pll_ops
;
r
=
dss_pll_register
(
pll
);
if
(
r
)
return
r
;
return
0
;
}
/* DSI1 HW IP initialisation */
static
int
omap_dsihw_probe
(
struct
platform_device
*
dsidev
)
{
...
...
@@ -5598,12 +5417,12 @@ static int omap_dsihw_probe(struct platform_device *dsidev)
dsi
->
vc
[
i
].
vc_id
=
0
;
}
dsi_calc_clock_param_ranges
(
dsidev
);
r
=
dsi_get_clocks
(
dsidev
);
if
(
r
)
return
r
;
dsi_init_pll_data
(
dsidev
);
pm_runtime_enable
(
&
dsidev
->
dev
);
r
=
dsi_runtime_get
(
dsidev
);
...
...
@@ -5672,6 +5491,8 @@ static int __exit omap_dsihw_remove(struct platform_device *dsidev)
WARN_ON
(
dsi
->
scp_clk_refcount
>
0
);
dss_pll_unregister
(
&
dsi
->
pll
);
dsi_uninit_output
(
dsidev
);
pm_runtime_disable
(
&
dsidev
->
dev
);
...
...
drivers/video/fbdev/omap2/dss/dss-of.c
浏览文件 @
3315764e
...
...
@@ -20,6 +20,8 @@
#include <video/omapdss.h>
#include "dss.h"
struct
device_node
*
omapdss_of_get_next_port
(
const
struct
device_node
*
parent
,
struct
device_node
*
prev
)
...
...
@@ -84,20 +86,17 @@ omapdss_of_get_next_endpoint(const struct device_node *parent,
}
EXPORT_SYMBOL_GPL
(
omapdss_of_get_next_endpoint
);
static
struct
device_node
*
omapdss_of_get_remote_device_node
(
const
struct
device_node
*
node
)
struct
device_node
*
dss_of_port_get_parent_device
(
struct
device_node
*
port
)
{
struct
device_node
*
np
;
int
i
;
np
=
of_parse_phandle
(
node
,
"remote-endpoint"
,
0
);
if
(
!
np
)
if
(
!
port
)
return
NULL
;
np
=
of_get_next_parent
(
np
);
np
=
of_get_next_parent
(
port
);
for
(
i
=
0
;
i
<
3
&&
np
;
++
i
)
{
for
(
i
=
0
;
i
<
2
&&
np
;
++
i
)
{
struct
property
*
prop
;
prop
=
of_find_property
(
np
,
"compatible"
,
NULL
);
...
...
@@ -111,6 +110,31 @@ omapdss_of_get_remote_device_node(const struct device_node *node)
return
NULL
;
}
u32
dss_of_port_get_port_number
(
struct
device_node
*
port
)
{
int
r
;
u32
reg
;
r
=
of_property_read_u32
(
port
,
"reg"
,
&
reg
);
if
(
r
)
reg
=
0
;
return
reg
;
}
static
struct
device_node
*
omapdss_of_get_remote_port
(
const
struct
device_node
*
node
)
{
struct
device_node
*
np
;
np
=
of_parse_phandle
(
node
,
"remote-endpoint"
,
0
);
if
(
!
np
)
return
NULL
;
np
=
of_get_next_parent
(
np
);
return
np
;
}
struct
device_node
*
omapdss_of_get_first_endpoint
(
const
struct
device_node
*
parent
)
{
...
...
@@ -133,27 +157,25 @@ struct omap_dss_device *
omapdss_of_find_source_for_first_ep
(
struct
device_node
*
node
)
{
struct
device_node
*
ep
;
struct
device_node
*
src_
node
;
struct
device_node
*
src_
port
;
struct
omap_dss_device
*
src
;
ep
=
omapdss_of_get_first_endpoint
(
node
);
if
(
!
ep
)
return
ERR_PTR
(
-
EINVAL
);
src_
node
=
omapdss_of_get_remote_device_node
(
ep
);
src_
port
=
omapdss_of_get_remote_port
(
ep
);
if
(
!
src_port
)
{
of_node_put
(
ep
);
if
(
!
src_node
)
return
ERR_PTR
(
-
EINVAL
);
}
src
=
omap_dss_find_output_by_node
(
src_node
);
of_node_put
(
ep
);
of_node_put
(
src_node
);
src
=
omap_dss_find_output_by_port_node
(
src_port
);
if
(
!
src
)
return
ERR_PTR
(
-
EPROBE_DEFER
);
of_node_put
(
src_port
);
return
src
;
return
src
?
src
:
ERR_PTR
(
-
EPROBE_DEFER
)
;
}
EXPORT_SYMBOL_GPL
(
omapdss_of_find_source_for_first_ep
);
drivers/video/fbdev/omap2/dss/dss.c
浏览文件 @
3315764e
...
...
@@ -70,7 +70,9 @@ struct dss_features {
u8
fck_div_max
;
u8
dss_fck_multiplier
;
const
char
*
parent_clk_name
;
int
(
*
dpi_select_source
)(
enum
omap_channel
channel
);
enum
omap_display_type
*
ports
;
int
num_ports
;
int
(
*
dpi_select_source
)(
int
port
,
enum
omap_channel
channel
);
};
static
struct
{
...
...
@@ -294,7 +296,6 @@ static void dss_dump_regs(struct seq_file *s)
static
void
dss_select_dispc_clk_source
(
enum
omap_dss_clk_source
clk_src
)
{
struct
platform_device
*
dsidev
;
int
b
;
u8
start
,
end
;
...
...
@@ -304,13 +305,9 @@ static void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src)
break
;
case
OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC
:
b
=
1
;
dsidev
=
dsi_get_dsidev_from_id
(
0
);
dsi_wait_pll_hsdiv_dispc_active
(
dsidev
);
break
;
case
OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC
:
b
=
2
;
dsidev
=
dsi_get_dsidev_from_id
(
1
);
dsi_wait_pll_hsdiv_dispc_active
(
dsidev
);
break
;
default:
BUG
();
...
...
@@ -327,7 +324,6 @@ static void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src)
void
dss_select_dsi_clk_source
(
int
dsi_module
,
enum
omap_dss_clk_source
clk_src
)
{
struct
platform_device
*
dsidev
;
int
b
,
pos
;
switch
(
clk_src
)
{
...
...
@@ -337,14 +333,10 @@ void dss_select_dsi_clk_source(int dsi_module,
case
OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI
:
BUG_ON
(
dsi_module
!=
0
);
b
=
1
;
dsidev
=
dsi_get_dsidev_from_id
(
0
);
dsi_wait_pll_hsdiv_dsi_active
(
dsidev
);
break
;
case
OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI
:
BUG_ON
(
dsi_module
!=
1
);
b
=
1
;
dsidev
=
dsi_get_dsidev_from_id
(
1
);
dsi_wait_pll_hsdiv_dsi_active
(
dsidev
);
break
;
default:
BUG
();
...
...
@@ -360,7 +352,6 @@ void dss_select_dsi_clk_source(int dsi_module,
void
dss_select_lcd_clk_source
(
enum
omap_channel
channel
,
enum
omap_dss_clk_source
clk_src
)
{
struct
platform_device
*
dsidev
;
int
b
,
ix
,
pos
;
if
(
!
dss_has_feature
(
FEAT_LCD_CLK_SRC
))
{
...
...
@@ -375,15 +366,11 @@ void dss_select_lcd_clk_source(enum omap_channel channel,
case
OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC
:
BUG_ON
(
channel
!=
OMAP_DSS_CHANNEL_LCD
);
b
=
1
;
dsidev
=
dsi_get_dsidev_from_id
(
0
);
dsi_wait_pll_hsdiv_dispc_active
(
dsidev
);
break
;
case
OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC
:
BUG_ON
(
channel
!=
OMAP_DSS_CHANNEL_LCD2
&&
channel
!=
OMAP_DSS_CHANNEL_LCD3
);
b
=
1
;
dsidev
=
dsi_get_dsidev_from_id
(
1
);
dsi_wait_pll_hsdiv_dispc_active
(
dsidev
);
break
;
default:
BUG
();
...
...
@@ -564,7 +551,7 @@ enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void)
return
REG_GET
(
DSS_CONTROL
,
15
,
15
);
}
static
int
dss_dpi_select_source_omap2_omap3
(
enum
omap_channel
channel
)
static
int
dss_dpi_select_source_omap2_omap3
(
int
port
,
enum
omap_channel
channel
)
{
if
(
channel
!=
OMAP_DSS_CHANNEL_LCD
)
return
-
EINVAL
;
...
...
@@ -572,7 +559,7 @@ static int dss_dpi_select_source_omap2_omap3(enum omap_channel channel)
return
0
;
}
static
int
dss_dpi_select_source_omap4
(
enum
omap_channel
channel
)
static
int
dss_dpi_select_source_omap4
(
int
port
,
enum
omap_channel
channel
)
{
int
val
;
...
...
@@ -592,7 +579,7 @@ static int dss_dpi_select_source_omap4(enum omap_channel channel)
return
0
;
}
static
int
dss_dpi_select_source_omap5
(
enum
omap_channel
channel
)
static
int
dss_dpi_select_source_omap5
(
int
port
,
enum
omap_channel
channel
)
{
int
val
;
...
...
@@ -618,9 +605,9 @@ static int dss_dpi_select_source_omap5(enum omap_channel channel)
return
0
;
}
int
dss_dpi_select_source
(
enum
omap_channel
channel
)
int
dss_dpi_select_source
(
int
port
,
enum
omap_channel
channel
)
{
return
dss
.
feat
->
dpi_select_source
(
channel
);
return
dss
.
feat
->
dpi_select_source
(
port
,
channel
);
}
static
int
dss_get_clocks
(
void
)
...
...
@@ -689,6 +676,16 @@ void dss_debug_dump_clocks(struct seq_file *s)
}
#endif
static
enum
omap_display_type
omap2plus_ports
[]
=
{
OMAP_DISPLAY_TYPE_DPI
,
};
static
enum
omap_display_type
omap34xx_ports
[]
=
{
OMAP_DISPLAY_TYPE_DPI
,
OMAP_DISPLAY_TYPE_SDI
,
};
static
const
struct
dss_features
omap24xx_dss_feats
__initconst
=
{
/*
* fck div max is really 16, but the divider range has gaps. The range
...
...
@@ -698,6 +695,8 @@ static const struct dss_features omap24xx_dss_feats __initconst = {
.
dss_fck_multiplier
=
2
,
.
parent_clk_name
=
"core_ck"
,
.
dpi_select_source
=
&
dss_dpi_select_source_omap2_omap3
,
.
ports
=
omap2plus_ports
,
.
num_ports
=
ARRAY_SIZE
(
omap2plus_ports
),
};
static
const
struct
dss_features
omap34xx_dss_feats
__initconst
=
{
...
...
@@ -705,6 +704,8 @@ static const struct dss_features omap34xx_dss_feats __initconst = {
.
dss_fck_multiplier
=
2
,
.
parent_clk_name
=
"dpll4_ck"
,
.
dpi_select_source
=
&
dss_dpi_select_source_omap2_omap3
,
.
ports
=
omap34xx_ports
,
.
num_ports
=
ARRAY_SIZE
(
omap34xx_ports
),
};
static
const
struct
dss_features
omap3630_dss_feats
__initconst
=
{
...
...
@@ -712,6 +713,8 @@ static const struct dss_features omap3630_dss_feats __initconst = {
.
dss_fck_multiplier
=
1
,
.
parent_clk_name
=
"dpll4_ck"
,
.
dpi_select_source
=
&
dss_dpi_select_source_omap2_omap3
,
.
ports
=
omap2plus_ports
,
.
num_ports
=
ARRAY_SIZE
(
omap2plus_ports
),
};
static
const
struct
dss_features
omap44xx_dss_feats
__initconst
=
{
...
...
@@ -719,6 +722,8 @@ static const struct dss_features omap44xx_dss_feats __initconst = {
.
dss_fck_multiplier
=
1
,
.
parent_clk_name
=
"dpll_per_x2_ck"
,
.
dpi_select_source
=
&
dss_dpi_select_source_omap4
,
.
ports
=
omap2plus_ports
,
.
num_ports
=
ARRAY_SIZE
(
omap2plus_ports
),
};
static
const
struct
dss_features
omap54xx_dss_feats
__initconst
=
{
...
...
@@ -726,6 +731,8 @@ static const struct dss_features omap54xx_dss_feats __initconst = {
.
dss_fck_multiplier
=
1
,
.
parent_clk_name
=
"dpll_per_x2_ck"
,
.
dpi_select_source
=
&
dss_dpi_select_source_omap5
,
.
ports
=
omap2plus_ports
,
.
num_ports
=
ARRAY_SIZE
(
omap2plus_ports
),
};
static
const
struct
dss_features
am43xx_dss_feats
__initconst
=
{
...
...
@@ -733,6 +740,8 @@ static const struct dss_features am43xx_dss_feats __initconst = {
.
dss_fck_multiplier
=
0
,
.
parent_clk_name
=
NULL
,
.
dpi_select_source
=
&
dss_dpi_select_source_omap2_omap3
,
.
ports
=
omap2plus_ports
,
.
num_ports
=
ARRAY_SIZE
(
omap2plus_ports
),
};
static
int
__init
dss_init_features
(
struct
platform_device
*
pdev
)
...
...
@@ -798,37 +807,77 @@ static int __init dss_init_ports(struct platform_device *pdev)
if
(
!
port
)
return
0
;
if
(
dss
.
feat
->
num_ports
==
0
)
return
0
;
do
{
enum
omap_display_type
port_type
;
u32
reg
;
r
=
of_property_read_u32
(
port
,
"reg"
,
&
reg
);
if
(
r
)
reg
=
0
;
#ifdef CONFIG_OMAP2_DSS_DPI
if
(
reg
==
0
)
dpi_init_port
(
pdev
,
port
);
#endif
if
(
reg
>=
dss
.
feat
->
num_ports
)
continue
;
#ifdef CONFIG_OMAP2_DSS_SDI
if
(
reg
==
1
)
sdi_init_port
(
pdev
,
port
);
#endif
port_type
=
dss
.
feat
->
ports
[
reg
];
switch
(
port_type
)
{
case
OMAP_DISPLAY_TYPE_DPI
:
dpi_init_port
(
pdev
,
port
);
break
;
case
OMAP_DISPLAY_TYPE_SDI
:
sdi_init_port
(
pdev
,
port
);
break
;
default:
break
;
}
}
while
((
port
=
omapdss_of_get_next_port
(
parent
,
port
))
!=
NULL
);
return
0
;
}
static
void
__exit
dss_uninit_ports
(
void
)
static
void
__exit
dss_uninit_ports
(
struct
platform_device
*
pdev
)
{
#ifdef CONFIG_OMAP2_DSS_DPI
dpi_uninit_port
();
#endif
struct
device_node
*
parent
=
pdev
->
dev
.
of_node
;
struct
device_node
*
port
;
#ifdef CONFIG_OMAP2_DSS_SDI
sdi_uninit_port
();
#endif
if
(
parent
==
NULL
)
return
;
port
=
omapdss_of_get_next_port
(
parent
,
NULL
);
if
(
!
port
)
return
;
if
(
dss
.
feat
->
num_ports
==
0
)
return
;
do
{
enum
omap_display_type
port_type
;
u32
reg
;
int
r
;
r
=
of_property_read_u32
(
port
,
"reg"
,
&
reg
);
if
(
r
)
reg
=
0
;
if
(
reg
>=
dss
.
feat
->
num_ports
)
continue
;
port_type
=
dss
.
feat
->
ports
[
reg
];
switch
(
port_type
)
{
case
OMAP_DISPLAY_TYPE_DPI
:
dpi_uninit_port
(
port
);
break
;
case
OMAP_DISPLAY_TYPE_SDI
:
sdi_uninit_port
(
port
);
break
;
default:
break
;
}
}
while
((
port
=
omapdss_of_get_next_port
(
parent
,
port
))
!=
NULL
);
}
/* DSS HW IP initialisation */
...
...
@@ -910,7 +959,7 @@ static int __init omap_dsshw_probe(struct platform_device *pdev)
static
int
__exit
omap_dsshw_remove
(
struct
platform_device
*
pdev
)
{
dss_uninit_ports
();
dss_uninit_ports
(
pdev
);
pm_runtime_disable
(
&
pdev
->
dev
);
...
...
drivers/video/fbdev/omap2/dss/dss.h
浏览文件 @
3315764e
...
...
@@ -100,35 +100,77 @@ enum dss_writeback_channel {
DSS_WB_LCD3_MGR
=
7
,
};
struct
dispc_clock_info
{
struct
dss_pll
;
#define DSS_PLL_MAX_HSDIVS 4
/*
* Type-A PLLs: clkout[]/mX[] refer to hsdiv outputs m4, m5, m6, m7.
* Type-B PLLs: clkout[0] refers to m2.
*/
struct
dss_pll_clock_info
{
/* rates that we get with dividers below */
unsigned
long
lck
;
unsigned
long
pck
;
unsigned
long
fint
;
unsigned
long
clkdco
;
unsigned
long
clkout
[
DSS_PLL_MAX_HSDIVS
];
/* dividers */
u16
lck_div
;
u16
pck_div
;
u16
n
;
u16
m
;
u32
mf
;
u16
mX
[
DSS_PLL_MAX_HSDIVS
];
u16
sd
;
};
struct
dss_pll_ops
{
int
(
*
enable
)(
struct
dss_pll
*
pll
);
void
(
*
disable
)(
struct
dss_pll
*
pll
);
int
(
*
set_config
)(
struct
dss_pll
*
pll
,
const
struct
dss_pll_clock_info
*
cinfo
);
};
struct
dss_pll_hw
{
unsigned
n_max
;
unsigned
m_min
;
unsigned
m_max
;
unsigned
mX_max
;
unsigned
long
fint_min
,
fint_max
;
unsigned
long
clkdco_min
,
clkdco_low
,
clkdco_max
;
u8
n_msb
,
n_lsb
;
u8
m_msb
,
m_lsb
;
u8
mX_msb
[
DSS_PLL_MAX_HSDIVS
],
mX_lsb
[
DSS_PLL_MAX_HSDIVS
];
bool
has_stopmode
;
bool
has_freqsel
;
bool
has_selfreqdco
;
bool
has_refsel
;
};
struct
dss_pll
{
const
char
*
name
;
struct
clk
*
clkin
;
struct
regulator
*
regulator
;
void
__iomem
*
base
;
const
struct
dss_pll_hw
*
hw
;
const
struct
dss_pll_ops
*
ops
;
struct
dss_pll_clock_info
cinfo
;
};
struct
d
si
_clock_info
{
struct
d
ispc
_clock_info
{
/* rates that we get with dividers below */
unsigned
long
fint
;
unsigned
long
clkin4ddr
;
unsigned
long
clkin
;
unsigned
long
dsi_pll_hsdiv_dispc_clk
;
/* OMAP3: DSI1_PLL_CLK
* OMAP4: PLLx_CLK1 */
unsigned
long
dsi_pll_hsdiv_dsi_clk
;
/* OMAP3: DSI2_PLL_CLK
* OMAP4: PLLx_CLK2 */
unsigned
long
lp_clk
;
unsigned
long
lck
;
unsigned
long
pck
;
/* dividers */
u16
regn
;
u16
regm
;
u16
regm_dispc
;
/* OMAP3: REGM3
* OMAP4: REGM4 */
u16
regm_dsi
;
/* OMAP3: REGM4
* OMAP4: REGM5 */
u16
lp_clk_div
;
u16
lck_div
;
u16
pck_div
;
};
struct
dss_lcd_mgr_config
{
...
...
@@ -209,12 +251,16 @@ int dss_init_platform_driver(void) __init;
void
dss_uninit_platform_driver
(
void
);
unsigned
long
dss_get_dispc_clk_rate
(
void
);
int
dss_dpi_select_source
(
enum
omap_channel
channel
);
int
dss_dpi_select_source
(
int
port
,
enum
omap_channel
channel
);
void
dss_select_hdmi_venc_clk_source
(
enum
dss_hdmi_venc_clk_source_select
);
enum
dss_hdmi_venc_clk_source_select
dss_get_hdmi_venc_clk_source
(
void
);
const
char
*
dss_get_generic_clk_source_name
(
enum
omap_dss_clk_source
clk_src
);
void
dss_dump_clocks
(
struct
seq_file
*
s
);
/* dss-of */
struct
device_node
*
dss_of_port_get_parent_device
(
struct
device_node
*
port
);
u32
dss_of_port_get_port_number
(
struct
device_node
*
port
);
#if defined(CONFIG_OMAP2_DSS_DEBUGFS)
void
dss_debug_dump_clocks
(
struct
seq_file
*
s
);
#endif
...
...
@@ -244,16 +290,22 @@ bool dss_div_calc(unsigned long pck, unsigned long fck_min,
int
sdi_init_platform_driver
(
void
)
__init
;
void
sdi_uninit_platform_driver
(
void
)
__exit
;
#ifdef CONFIG_OMAP2_DSS_SDI
int
sdi_init_port
(
struct
platform_device
*
pdev
,
struct
device_node
*
port
)
__init
;
void
sdi_uninit_port
(
void
)
__exit
;
void
sdi_uninit_port
(
struct
device_node
*
port
)
__exit
;
#else
static
inline
int
__init
sdi_init_port
(
struct
platform_device
*
pdev
,
struct
device_node
*
port
)
{
return
0
;
}
static
inline
void
__exit
sdi_uninit_port
(
struct
device_node
*
port
)
{
}
#endif
/* DSI */
typedef
bool
(
*
dsi_pll_calc_func
)(
int
regn
,
int
regm
,
unsigned
long
fint
,
unsigned
long
pll
,
void
*
data
);
typedef
bool
(
*
dsi_hsdiv_calc_func
)(
int
regm_dispc
,
unsigned
long
dispc
,
void
*
data
);
#ifdef CONFIG_OMAP2_DSS_DSI
struct
dentry
;
...
...
@@ -262,104 +314,36 @@ struct file_operations;
int
dsi_init_platform_driver
(
void
)
__init
;
void
dsi_uninit_platform_driver
(
void
)
__exit
;
int
dsi_runtime_get
(
struct
platform_device
*
dsidev
);
void
dsi_runtime_put
(
struct
platform_device
*
dsidev
);
void
dsi_dump_clocks
(
struct
seq_file
*
s
);
void
dsi_irq_handler
(
void
);
u8
dsi_get_pixel_size
(
enum
omap_dss_dsi_pixel_format
fmt
);
unsigned
long
dsi_get_pll_clkin
(
struct
platform_device
*
dsidev
);
bool
dsi_hsdiv_calc
(
struct
platform_device
*
dsidev
,
unsigned
long
pll
,
unsigned
long
out_min
,
dsi_hsdiv_calc_func
func
,
void
*
data
);
bool
dsi_pll_calc
(
struct
platform_device
*
dsidev
,
unsigned
long
clkin
,
unsigned
long
pll_min
,
unsigned
long
pll_max
,
dsi_pll_calc_func
func
,
void
*
data
);
unsigned
long
dsi_get_pll_hsdiv_dispc_rate
(
struct
platform_device
*
dsidev
);
int
dsi_pll_set_clock_div
(
struct
platform_device
*
dsidev
,
struct
dsi_clock_info
*
cinfo
);
int
dsi_pll_init
(
struct
platform_device
*
dsidev
,
bool
enable_hsclk
,
bool
enable_hsdiv
);
void
dsi_pll_uninit
(
struct
platform_device
*
dsidev
,
bool
disconnect_lanes
);
void
dsi_wait_pll_hsdiv_dispc_active
(
struct
platform_device
*
dsidev
);
void
dsi_wait_pll_hsdiv_dsi_active
(
struct
platform_device
*
dsidev
);
struct
platform_device
*
dsi_get_dsidev_from_id
(
int
module
);
#else
static
inline
int
dsi_runtime_get
(
struct
platform_device
*
dsidev
)
{
return
0
;
}
static
inline
void
dsi_runtime_put
(
struct
platform_device
*
dsidev
)
{
}
static
inline
u8
dsi_get_pixel_size
(
enum
omap_dss_dsi_pixel_format
fmt
)
{
WARN
(
"%s: DSI not compiled in, returning pixel_size as 0
\n
"
,
__func__
);
return
0
;
}
static
inline
unsigned
long
dsi_get_pll_hsdiv_dispc_rate
(
struct
platform_device
*
dsidev
)
{
WARN
(
"%s: DSI not compiled in, returning rate as 0
\n
"
,
__func__
);
return
0
;
}
static
inline
int
dsi_pll_set_clock_div
(
struct
platform_device
*
dsidev
,
struct
dsi_clock_info
*
cinfo
)
{
WARN
(
"%s: DSI not compiled in
\n
"
,
__func__
);
return
-
ENODEV
;
}
static
inline
int
dsi_pll_init
(
struct
platform_device
*
dsidev
,
bool
enable_hsclk
,
bool
enable_hsdiv
)
{
WARN
(
"%s: DSI not compiled in
\n
"
,
__func__
);
return
-
ENODEV
;
}
static
inline
void
dsi_pll_uninit
(
struct
platform_device
*
dsidev
,
bool
disconnect_lanes
)
{
}
static
inline
void
dsi_wait_pll_hsdiv_dispc_active
(
struct
platform_device
*
dsidev
)
{
}
static
inline
void
dsi_wait_pll_hsdiv_dsi_active
(
struct
platform_device
*
dsidev
)
{
}
static
inline
struct
platform_device
*
dsi_get_dsidev_from_id
(
int
module
)
{
return
NULL
;
}
static
inline
unsigned
long
dsi_get_pll_clkin
(
struct
platform_device
*
dsidev
)
{
return
0
;
}
static
inline
bool
dsi_hsdiv_calc
(
struct
platform_device
*
dsidev
,
unsigned
long
pll
,
unsigned
long
out_min
,
dsi_hsdiv_calc_func
func
,
void
*
data
)
{
return
false
;
}
static
inline
bool
dsi_pll_calc
(
struct
platform_device
*
dsidev
,
unsigned
long
clkin
,
unsigned
long
pll_min
,
unsigned
long
pll_max
,
dsi_pll_calc_func
func
,
void
*
data
)
{
return
false
;
}
#endif
/* DPI */
int
dpi_init_platform_driver
(
void
)
__init
;
void
dpi_uninit_platform_driver
(
void
)
__exit
;
#ifdef CONFIG_OMAP2_DSS_DPI
int
dpi_init_port
(
struct
platform_device
*
pdev
,
struct
device_node
*
port
)
__init
;
void
dpi_uninit_port
(
void
)
__exit
;
void
dpi_uninit_port
(
struct
device_node
*
port
)
__exit
;
#else
static
inline
int
__init
dpi_init_port
(
struct
platform_device
*
pdev
,
struct
device_node
*
port
)
{
return
0
;
}
static
inline
void
__exit
dpi_uninit_port
(
struct
device_node
*
port
)
{
}
#endif
/* DISPC */
int
dispc_init_platform_driver
(
void
)
__init
;
...
...
@@ -438,4 +422,29 @@ static inline void dss_collect_irq_stats(u32 irqstatus, unsigned *irq_arr)
}
#endif
/* PLL */
typedef
bool
(
*
dss_pll_calc_func
)(
int
n
,
int
m
,
unsigned
long
fint
,
unsigned
long
clkdco
,
void
*
data
);
typedef
bool
(
*
dss_hsdiv_calc_func
)(
int
m_dispc
,
unsigned
long
dispc
,
void
*
data
);
int
dss_pll_register
(
struct
dss_pll
*
pll
);
void
dss_pll_unregister
(
struct
dss_pll
*
pll
);
struct
dss_pll
*
dss_pll_find
(
const
char
*
name
);
int
dss_pll_enable
(
struct
dss_pll
*
pll
);
void
dss_pll_disable
(
struct
dss_pll
*
pll
);
int
dss_pll_set_config
(
struct
dss_pll
*
pll
,
const
struct
dss_pll_clock_info
*
cinfo
);
bool
dss_pll_hsdiv_calc
(
const
struct
dss_pll
*
pll
,
unsigned
long
clkdco
,
unsigned
long
out_min
,
unsigned
long
out_max
,
dss_hsdiv_calc_func
func
,
void
*
data
);
bool
dss_pll_calc
(
const
struct
dss_pll
*
pll
,
unsigned
long
clkin
,
unsigned
long
pll_min
,
unsigned
long
pll_max
,
dss_pll_calc_func
func
,
void
*
data
);
int
dss_pll_write_config_type_a
(
struct
dss_pll
*
pll
,
const
struct
dss_pll_clock_info
*
cinfo
);
int
dss_pll_write_config_type_b
(
struct
dss_pll
*
pll
,
const
struct
dss_pll_clock_info
*
cinfo
);
#endif
drivers/video/fbdev/omap2/dss/dss_features.c
浏览文件 @
3315764e
...
...
@@ -72,10 +72,6 @@ static const struct dss_reg_field omap2_dss_reg_fields[] = {
[
FEAT_REG_HORIZONTALACCU
]
=
{
9
,
0
},
[
FEAT_REG_VERTICALACCU
]
=
{
25
,
16
},
[
FEAT_REG_DISPC_CLK_SWITCH
]
=
{
0
,
0
},
[
FEAT_REG_DSIPLL_REGN
]
=
{
0
,
0
},
[
FEAT_REG_DSIPLL_REGM
]
=
{
0
,
0
},
[
FEAT_REG_DSIPLL_REGM_DISPC
]
=
{
0
,
0
},
[
FEAT_REG_DSIPLL_REGM_DSI
]
=
{
0
,
0
},
};
static
const
struct
dss_reg_field
omap3_dss_reg_fields
[]
=
{
...
...
@@ -87,10 +83,6 @@ static const struct dss_reg_field omap3_dss_reg_fields[] = {
[
FEAT_REG_HORIZONTALACCU
]
=
{
9
,
0
},
[
FEAT_REG_VERTICALACCU
]
=
{
25
,
16
},
[
FEAT_REG_DISPC_CLK_SWITCH
]
=
{
0
,
0
},
[
FEAT_REG_DSIPLL_REGN
]
=
{
7
,
1
},
[
FEAT_REG_DSIPLL_REGM
]
=
{
18
,
8
},
[
FEAT_REG_DSIPLL_REGM_DISPC
]
=
{
22
,
19
},
[
FEAT_REG_DSIPLL_REGM_DSI
]
=
{
26
,
23
},
};
static
const
struct
dss_reg_field
am43xx_dss_reg_fields
[]
=
{
...
...
@@ -113,10 +105,6 @@ static const struct dss_reg_field omap4_dss_reg_fields[] = {
[
FEAT_REG_HORIZONTALACCU
]
=
{
10
,
0
},
[
FEAT_REG_VERTICALACCU
]
=
{
26
,
16
},
[
FEAT_REG_DISPC_CLK_SWITCH
]
=
{
9
,
8
},
[
FEAT_REG_DSIPLL_REGN
]
=
{
8
,
1
},
[
FEAT_REG_DSIPLL_REGM
]
=
{
20
,
9
},
[
FEAT_REG_DSIPLL_REGM_DISPC
]
=
{
25
,
21
},
[
FEAT_REG_DSIPLL_REGM_DSI
]
=
{
30
,
26
},
};
static
const
struct
dss_reg_field
omap5_dss_reg_fields
[]
=
{
...
...
@@ -128,10 +116,6 @@ static const struct dss_reg_field omap5_dss_reg_fields[] = {
[
FEAT_REG_HORIZONTALACCU
]
=
{
10
,
0
},
[
FEAT_REG_VERTICALACCU
]
=
{
26
,
16
},
[
FEAT_REG_DISPC_CLK_SWITCH
]
=
{
9
,
7
},
[
FEAT_REG_DSIPLL_REGN
]
=
{
8
,
1
},
[
FEAT_REG_DSIPLL_REGM
]
=
{
20
,
9
},
[
FEAT_REG_DSIPLL_REGM_DISPC
]
=
{
25
,
21
},
[
FEAT_REG_DSIPLL_REGM_DSI
]
=
{
30
,
26
},
};
static
const
enum
omap_display_type
omap2_dss_supported_displays
[]
=
{
...
...
@@ -437,12 +421,6 @@ static const char * const omap5_dss_clk_source_names[] = {
static
const
struct
dss_param_range
omap2_dss_param_range
[]
=
{
[
FEAT_PARAM_DSS_FCK
]
=
{
0
,
133000000
},
[
FEAT_PARAM_DSS_PCD
]
=
{
2
,
255
},
[
FEAT_PARAM_DSIPLL_REGN
]
=
{
0
,
0
},
[
FEAT_PARAM_DSIPLL_REGM
]
=
{
0
,
0
},
[
FEAT_PARAM_DSIPLL_REGM_DISPC
]
=
{
0
,
0
},
[
FEAT_PARAM_DSIPLL_REGM_DSI
]
=
{
0
,
0
},
[
FEAT_PARAM_DSIPLL_FINT
]
=
{
0
,
0
},
[
FEAT_PARAM_DSIPLL_LPDIV
]
=
{
0
,
0
},
[
FEAT_PARAM_DOWNSCALE
]
=
{
1
,
2
},
/*
* Assuming the line width buffer to be 768 pixels as OMAP2 DISPC
...
...
@@ -454,11 +432,6 @@ static const struct dss_param_range omap2_dss_param_range[] = {
static
const
struct
dss_param_range
omap3_dss_param_range
[]
=
{
[
FEAT_PARAM_DSS_FCK
]
=
{
0
,
173000000
},
[
FEAT_PARAM_DSS_PCD
]
=
{
1
,
255
},
[
FEAT_PARAM_DSIPLL_REGN
]
=
{
0
,
(
1
<<
7
)
-
1
},
[
FEAT_PARAM_DSIPLL_REGM
]
=
{
0
,
(
1
<<
11
)
-
1
},
[
FEAT_PARAM_DSIPLL_REGM_DISPC
]
=
{
0
,
(
1
<<
4
)
-
1
},
[
FEAT_PARAM_DSIPLL_REGM_DSI
]
=
{
0
,
(
1
<<
4
)
-
1
},
[
FEAT_PARAM_DSIPLL_FINT
]
=
{
750000
,
2100000
},
[
FEAT_PARAM_DSIPLL_LPDIV
]
=
{
1
,
(
1
<<
13
)
-
1
},
[
FEAT_PARAM_DSI_FCK
]
=
{
0
,
173000000
},
[
FEAT_PARAM_DOWNSCALE
]
=
{
1
,
4
},
...
...
@@ -475,11 +448,6 @@ static const struct dss_param_range am43xx_dss_param_range[] = {
static
const
struct
dss_param_range
omap4_dss_param_range
[]
=
{
[
FEAT_PARAM_DSS_FCK
]
=
{
0
,
186000000
},
[
FEAT_PARAM_DSS_PCD
]
=
{
1
,
255
},
[
FEAT_PARAM_DSIPLL_REGN
]
=
{
0
,
(
1
<<
8
)
-
1
},
[
FEAT_PARAM_DSIPLL_REGM
]
=
{
0
,
(
1
<<
12
)
-
1
},
[
FEAT_PARAM_DSIPLL_REGM_DISPC
]
=
{
0
,
(
1
<<
5
)
-
1
},
[
FEAT_PARAM_DSIPLL_REGM_DSI
]
=
{
0
,
(
1
<<
5
)
-
1
},
[
FEAT_PARAM_DSIPLL_FINT
]
=
{
500000
,
2500000
},
[
FEAT_PARAM_DSIPLL_LPDIV
]
=
{
0
,
(
1
<<
13
)
-
1
},
[
FEAT_PARAM_DSI_FCK
]
=
{
0
,
170000000
},
[
FEAT_PARAM_DOWNSCALE
]
=
{
1
,
4
},
...
...
@@ -489,11 +457,6 @@ static const struct dss_param_range omap4_dss_param_range[] = {
static
const
struct
dss_param_range
omap5_dss_param_range
[]
=
{
[
FEAT_PARAM_DSS_FCK
]
=
{
0
,
209250000
},
[
FEAT_PARAM_DSS_PCD
]
=
{
1
,
255
},
[
FEAT_PARAM_DSIPLL_REGN
]
=
{
0
,
(
1
<<
8
)
-
1
},
[
FEAT_PARAM_DSIPLL_REGM
]
=
{
0
,
(
1
<<
12
)
-
1
},
[
FEAT_PARAM_DSIPLL_REGM_DISPC
]
=
{
0
,
(
1
<<
5
)
-
1
},
[
FEAT_PARAM_DSIPLL_REGM_DSI
]
=
{
0
,
(
1
<<
5
)
-
1
},
[
FEAT_PARAM_DSIPLL_FINT
]
=
{
150000
,
52000000
},
[
FEAT_PARAM_DSIPLL_LPDIV
]
=
{
0
,
(
1
<<
13
)
-
1
},
[
FEAT_PARAM_DSI_FCK
]
=
{
0
,
209250000
},
[
FEAT_PARAM_DOWNSCALE
]
=
{
1
,
4
},
...
...
@@ -517,7 +480,6 @@ static const enum dss_feat_id omap3430_dss_feat_list[] = {
FEAT_LINEBUFFERSPLIT
,
FEAT_ROWREPEATENABLE
,
FEAT_RESIZECONF
,
FEAT_DSI_PLL_FREQSEL
,
FEAT_DSI_REVERSE_TXCLKESC
,
FEAT_VENC_REQUIRES_TV_DAC_CLK
,
FEAT_CPR
,
...
...
@@ -537,7 +499,6 @@ static const enum dss_feat_id am35xx_dss_feat_list[] = {
FEAT_LINEBUFFERSPLIT
,
FEAT_ROWREPEATENABLE
,
FEAT_RESIZECONF
,
FEAT_DSI_PLL_FREQSEL
,
FEAT_DSI_REVERSE_TXCLKESC
,
FEAT_VENC_REQUIRES_TV_DAC_CLK
,
FEAT_CPR
,
...
...
@@ -572,7 +533,6 @@ static const enum dss_feat_id omap3630_dss_feat_list[] = {
FEAT_ROWREPEATENABLE
,
FEAT_RESIZECONF
,
FEAT_DSI_PLL_PWR_BUG
,
FEAT_DSI_PLL_FREQSEL
,
FEAT_CPR
,
FEAT_PRELOAD
,
FEAT_FIR_COEF_V
,
...
...
@@ -654,8 +614,6 @@ static const enum dss_feat_id omap5_dss_feat_list[] = {
FEAT_ALPHA_FREE_ZORDER
,
FEAT_FIFO_MERGE
,
FEAT_BURST_2D
,
FEAT_DSI_PLL_SELFREQDCO
,
FEAT_DSI_PLL_REFSEL
,
FEAT_DSI_PHY_DCC
,
FEAT_MFLAG
,
};
...
...
drivers/video/fbdev/omap2/dss/dss_features.h
浏览文件 @
3315764e
...
...
@@ -41,7 +41,6 @@ enum dss_feat_id {
FEAT_LCD_CLK_SRC
,
/* DSI-PLL power command 0x3 is not working */
FEAT_DSI_PLL_PWR_BUG
,
FEAT_DSI_PLL_FREQSEL
,
FEAT_DSI_DCS_CMD_CONFIG_VC
,
FEAT_DSI_VC_OCP_WIDTH
,
FEAT_DSI_REVERSE_TXCLKESC
,
...
...
@@ -61,8 +60,6 @@ enum dss_feat_id {
/* An unknown HW bug causing the normal FIFO thresholds not to work */
FEAT_OMAP3_DSI_FIFO_BUG
,
FEAT_BURST_2D
,
FEAT_DSI_PLL_SELFREQDCO
,
FEAT_DSI_PLL_REFSEL
,
FEAT_DSI_PHY_DCC
,
FEAT_MFLAG
,
};
...
...
@@ -77,20 +74,11 @@ enum dss_feat_reg_field {
FEAT_REG_HORIZONTALACCU
,
FEAT_REG_VERTICALACCU
,
FEAT_REG_DISPC_CLK_SWITCH
,
FEAT_REG_DSIPLL_REGN
,
FEAT_REG_DSIPLL_REGM
,
FEAT_REG_DSIPLL_REGM_DISPC
,
FEAT_REG_DSIPLL_REGM_DSI
,
};
enum
dss_range_param
{
FEAT_PARAM_DSS_FCK
,
FEAT_PARAM_DSS_PCD
,
FEAT_PARAM_DSIPLL_REGN
,
FEAT_PARAM_DSIPLL_REGM
,
FEAT_PARAM_DSIPLL_REGM_DISPC
,
FEAT_PARAM_DSIPLL_REGM_DSI
,
FEAT_PARAM_DSIPLL_FINT
,
FEAT_PARAM_DSIPLL_LPDIV
,
FEAT_PARAM_DSI_FCK
,
FEAT_PARAM_DOWNSCALE
,
...
...
drivers/video/fbdev/omap2/dss/hdmi.h
浏览文件 @
3315764e
...
...
@@ -101,13 +101,6 @@ enum hdmi_core_hdmi_dvi {
HDMI_HDMI
=
1
};
enum
hdmi_clk_refsel
{
HDMI_REFSEL_PCLK
=
0
,
HDMI_REFSEL_REF1
=
1
,
HDMI_REFSEL_REF2
=
2
,
HDMI_REFSEL_SYSCLK
=
3
};
enum
hdmi_packing_mode
{
HDMI_PACK_10b_RGB_YUV444
=
0
,
HDMI_PACK_24b_RGB_YUV444_YUV422
=
1
,
...
...
@@ -160,7 +153,8 @@ enum hdmi_audio_blk_strt_end_sig {
enum
hdmi_core_audio_layout
{
HDMI_AUDIO_LAYOUT_2CH
=
0
,
HDMI_AUDIO_LAYOUT_8CH
=
1
HDMI_AUDIO_LAYOUT_8CH
=
1
,
HDMI_AUDIO_LAYOUT_6CH
=
2
};
enum
hdmi_core_cts_mode
{
...
...
@@ -191,17 +185,6 @@ struct hdmi_config {
enum
hdmi_core_hdmi_dvi
hdmi_dvi_mode
;
};
/* HDMI PLL structure */
struct
hdmi_pll_info
{
u16
regn
;
u16
regm
;
u32
regmf
;
u16
regm2
;
u16
regsd
;
u16
dcofreq
;
enum
hdmi_clk_refsel
refsel
;
};
struct
hdmi_audio_format
{
enum
hdmi_stereo_channels
stereo_channels
;
u8
active_chnnls_msk
;
...
...
@@ -249,12 +232,15 @@ struct hdmi_core_audio_config {
struct
hdmi_wp_data
{
void
__iomem
*
base
;
phys_addr_t
phys_base
;
};
struct
hdmi_pll_data
{
struct
dss_pll
pll
;
void
__iomem
*
base
;
struct
hdmi_
pll_info
info
;
struct
hdmi_
wp_data
*
wp
;
};
struct
hdmi_phy_data
{
...
...
@@ -316,16 +302,19 @@ void hdmi_wp_video_config_timing(struct hdmi_wp_data *wp,
void
hdmi_wp_init_vid_fmt_timings
(
struct
hdmi_video_format
*
video_fmt
,
struct
omap_video_timings
*
timings
,
struct
hdmi_config
*
param
);
int
hdmi_wp_init
(
struct
platform_device
*
pdev
,
struct
hdmi_wp_data
*
wp
);
phys_addr_t
hdmi_wp_get_audio_dma_addr
(
struct
hdmi_wp_data
*
wp
);
/* HDMI PLL funcs */
int
hdmi_pll_enable
(
struct
hdmi_pll_data
*
pll
,
struct
hdmi_wp_data
*
wp
);
void
hdmi_pll_disable
(
struct
hdmi_pll_data
*
pll
,
struct
hdmi_wp_data
*
wp
);
void
hdmi_pll_dump
(
struct
hdmi_pll_data
*
pll
,
struct
seq_file
*
s
);
void
hdmi_pll_compute
(
struct
hdmi_pll_data
*
pll
,
unsigned
long
clkin
,
int
phy
);
int
hdmi_pll_init
(
struct
platform_device
*
pdev
,
struct
hdmi_pll_data
*
pll
);
void
hdmi_pll_compute
(
struct
hdmi_pll_data
*
pll
,
unsigned
long
target_tmds
,
struct
dss_pll_clock_info
*
pi
);
int
hdmi_pll_init
(
struct
platform_device
*
pdev
,
struct
hdmi_pll_data
*
pll
,
struct
hdmi_wp_data
*
wp
);
void
hdmi_pll_uninit
(
struct
hdmi_pll_data
*
hpll
);
/* HDMI PHY funcs */
int
hdmi_phy_configure
(
struct
hdmi_phy_data
*
phy
,
struct
hdmi_config
*
cfg
);
int
hdmi_phy_configure
(
struct
hdmi_phy_data
*
phy
,
unsigned
long
hfbitclk
,
unsigned
long
lfbitclk
);
void
hdmi_phy_dump
(
struct
hdmi_phy_data
*
phy
,
struct
seq_file
*
s
);
int
hdmi_phy_init
(
struct
platform_device
*
pdev
,
struct
hdmi_phy_data
*
phy
);
int
hdmi_phy_parse_lanes
(
struct
hdmi_phy_data
*
phy
,
const
u32
*
lanes
);
...
...
@@ -334,7 +323,7 @@ int hdmi_phy_parse_lanes(struct hdmi_phy_data *phy, const u32 *lanes);
int
hdmi_parse_lanes_of
(
struct
platform_device
*
pdev
,
struct
device_node
*
ep
,
struct
hdmi_phy_data
*
phy
);
#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) || defined(CONFIG_OMAP5_DSS_HDMI_AUDIO)
/* Audio funcs */
int
hdmi_compute_acr
(
u32
pclk
,
u32
sample_freq
,
u32
*
n
,
u32
*
cts
);
int
hdmi_wp_audio_enable
(
struct
hdmi_wp_data
*
wp
,
bool
enable
);
int
hdmi_wp_audio_core_req_enable
(
struct
hdmi_wp_data
*
wp
,
bool
enable
);
...
...
@@ -342,9 +331,33 @@ void hdmi_wp_audio_config_format(struct hdmi_wp_data *wp,
struct
hdmi_audio_format
*
aud_fmt
);
void
hdmi_wp_audio_config_dma
(
struct
hdmi_wp_data
*
wp
,
struct
hdmi_audio_dma
*
aud_dma
);
static
inline
bool
hdmi_mode_has_audio
(
int
mode
)
static
inline
bool
hdmi_mode_has_audio
(
struct
hdmi_config
*
cfg
)
{
return
mode
==
HDMI_HDMI
?
true
:
false
;
return
cfg
->
hdmi_dvi_
mode
==
HDMI_HDMI
?
true
:
false
;
}
#endif
/* HDMI DRV data */
struct
omap_hdmi
{
struct
mutex
lock
;
struct
platform_device
*
pdev
;
struct
hdmi_wp_data
wp
;
struct
hdmi_pll_data
pll
;
struct
hdmi_phy_data
phy
;
struct
hdmi_core_data
core
;
struct
hdmi_config
cfg
;
struct
regulator
*
vdda_reg
;
bool
core_enabled
;
bool
display_enabled
;
struct
omap_dss_device
output
;
struct
platform_device
*
audio_pdev
;
void
(
*
audio_abort_cb
)(
struct
device
*
dev
);
int
wp_idlemode
;
};
#endif
drivers/video/fbdev/omap2/dss/hdmi4.c
浏览文件 @
3315764e
...
...
@@ -33,29 +33,14 @@
#include <linux/gpio.h>
#include <linux/regulator/consumer.h>
#include <video/omapdss.h>
#include <sound/omap-hdmi-audio.h>
#include "hdmi4_core.h"
#include "dss.h"
#include "dss_features.h"
#include "hdmi.h"
static
struct
{
struct
mutex
lock
;
struct
platform_device
*
pdev
;
struct
hdmi_wp_data
wp
;
struct
hdmi_pll_data
pll
;
struct
hdmi_phy_data
phy
;
struct
hdmi_core_data
core
;
struct
hdmi_config
cfg
;
struct
clk
*
sys_clk
;
struct
regulator
*
vdda_hdmi_dac_reg
;
bool
core_enabled
;
struct
omap_dss_device
output
;
}
hdmi
;
static
struct
omap_hdmi
hdmi
;
static
int
hdmi_runtime_get
(
void
)
{
...
...
@@ -117,7 +102,7 @@ static int hdmi_init_regulator(void)
int
r
;
struct
regulator
*
reg
;
if
(
hdmi
.
vdda_
hdmi_dac_
reg
!=
NULL
)
if
(
hdmi
.
vdda_reg
!=
NULL
)
return
0
;
reg
=
devm_regulator_get
(
&
hdmi
.
pdev
->
dev
,
"vdda"
);
...
...
@@ -137,7 +122,7 @@ static int hdmi_init_regulator(void)
}
}
hdmi
.
vdda_
hdmi_dac_
reg
=
reg
;
hdmi
.
vdda_reg
=
reg
;
return
0
;
}
...
...
@@ -146,7 +131,7 @@ static int hdmi_power_on_core(struct omap_dss_device *dssdev)
{
int
r
;
r
=
regulator_enable
(
hdmi
.
vdda_
hdmi_dac_
reg
);
r
=
regulator_enable
(
hdmi
.
vdda_reg
);
if
(
r
)
return
r
;
...
...
@@ -162,7 +147,7 @@ static int hdmi_power_on_core(struct omap_dss_device *dssdev)
return
0
;
err_runtime_get:
regulator_disable
(
hdmi
.
vdda_
hdmi_dac_
reg
);
regulator_disable
(
hdmi
.
vdda_reg
);
return
r
;
}
...
...
@@ -172,7 +157,7 @@ static void hdmi_power_off_core(struct omap_dss_device *dssdev)
hdmi
.
core_enabled
=
false
;
hdmi_runtime_put
();
regulator_disable
(
hdmi
.
vdda_
hdmi_dac_
reg
);
regulator_disable
(
hdmi
.
vdda_reg
);
}
static
int
hdmi_power_on_full
(
struct
omap_dss_device
*
dssdev
)
...
...
@@ -180,8 +165,8 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev)
int
r
;
struct
omap_video_timings
*
p
;
struct
omap_overlay_manager
*
mgr
=
hdmi
.
output
.
manager
;
unsigned
long
phy
;
struct
hdmi_wp_data
*
wp
=
&
hdmi
.
wp
;
struct
dss_pll_clock_info
hdmi_cinfo
=
{
0
};
r
=
hdmi_power_on_core
(
dssdev
);
if
(
r
)
...
...
@@ -195,19 +180,22 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev)
DSSDBG
(
"hdmi_power_on x_res= %d y_res = %d
\n
"
,
p
->
x_res
,
p
->
y_res
);
/* the functions below use kHz pixel clock. TODO: change to Hz */
phy
=
p
->
pixelclock
/
1000
;
hdmi_pll_compute
(
&
hdmi
.
pll
,
clk_get_rate
(
hdmi
.
sys_clk
),
phy
);
hdmi_pll_compute
(
&
hdmi
.
pll
,
p
->
pixelclock
,
&
hdmi_cinfo
);
/* config the PLL and PHY hdmi_set_pll_pwrfirst */
r
=
hdmi_pll_enable
(
&
hdmi
.
pll
,
&
hdmi
.
wp
);
r
=
dss_pll_enable
(
&
hdmi
.
pll
.
pll
);
if
(
r
)
{
DSS
DBG
(
"Failed to lock
PLL
\n
"
);
DSS
ERR
(
"Failed to enable
PLL
\n
"
);
goto
err_pll_enable
;
}
r
=
hdmi_phy_configure
(
&
hdmi
.
phy
,
&
hdmi
.
cfg
);
r
=
dss_pll_set_config
(
&
hdmi
.
pll
.
pll
,
&
hdmi_cinfo
);
if
(
r
)
{
DSSERR
(
"Failed to configure PLL
\n
"
);
goto
err_pll_cfg
;
}
r
=
hdmi_phy_configure
(
&
hdmi
.
phy
,
hdmi_cinfo
.
clkdco
,
hdmi_cinfo
.
clkout
[
0
]);
if
(
r
)
{
DSSDBG
(
"Failed to configure PHY
\n
"
);
goto
err_phy_cfg
;
...
...
@@ -244,7 +232,8 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev)
err_phy_cfg:
hdmi_wp_set_phy_pwr
(
&
hdmi
.
wp
,
HDMI_PHYPWRCMD_OFF
);
err_phy_pwr:
hdmi_pll_disable
(
&
hdmi
.
pll
,
&
hdmi
.
wp
);
err_pll_cfg:
dss_pll_disable
(
&
hdmi
.
pll
.
pll
);
err_pll_enable:
hdmi_power_off_core
(
dssdev
);
return
-
EIO
;
...
...
@@ -262,7 +251,7 @@ static void hdmi_power_off_full(struct omap_dss_device *dssdev)
hdmi_wp_set_phy_pwr
(
&
hdmi
.
wp
,
HDMI_PHYPWRCMD_OFF
);
hdmi_pll_disable
(
&
hdmi
.
pll
,
&
hdmi
.
wp
);
dss_pll_disable
(
&
hdmi
.
pll
.
pll
);
hdmi_power_off_core
(
dssdev
);
}
...
...
@@ -352,6 +341,8 @@ static int hdmi_display_enable(struct omap_dss_device *dssdev)
goto
err0
;
}
hdmi
.
display_enabled
=
true
;
mutex_unlock
(
&
hdmi
.
lock
);
return
0
;
...
...
@@ -366,8 +357,13 @@ static void hdmi_display_disable(struct omap_dss_device *dssdev)
mutex_lock
(
&
hdmi
.
lock
);
if
(
hdmi
.
audio_pdev
&&
hdmi
.
audio_abort_cb
)
hdmi
.
audio_abort_cb
(
&
hdmi
.
audio_pdev
->
dev
);
hdmi_power_off_full
(
dssdev
);
hdmi
.
display_enabled
=
false
;
mutex_unlock
(
&
hdmi
.
lock
);
}
...
...
@@ -404,21 +400,6 @@ static void hdmi_core_disable(struct omap_dss_device *dssdev)
mutex_unlock
(
&
hdmi
.
lock
);
}
static
int
hdmi_get_clocks
(
struct
platform_device
*
pdev
)
{
struct
clk
*
clk
;
clk
=
devm_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
;
return
0
;
}
static
int
hdmi_connect
(
struct
omap_dss_device
*
dssdev
,
struct
omap_dss_device
*
dst
)
{
...
...
@@ -484,112 +465,6 @@ static int hdmi_read_edid(struct omap_dss_device *dssdev,
return
r
;
}
#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
static
int
hdmi_audio_enable
(
struct
omap_dss_device
*
dssdev
)
{
int
r
;
mutex_lock
(
&
hdmi
.
lock
);
if
(
!
hdmi_mode_has_audio
(
hdmi
.
cfg
.
hdmi_dvi_mode
))
{
r
=
-
EPERM
;
goto
err
;
}
r
=
hdmi_wp_audio_enable
(
&
hdmi
.
wp
,
true
);
if
(
r
)
goto
err
;
mutex_unlock
(
&
hdmi
.
lock
);
return
0
;
err:
mutex_unlock
(
&
hdmi
.
lock
);
return
r
;
}
static
void
hdmi_audio_disable
(
struct
omap_dss_device
*
dssdev
)
{
hdmi_wp_audio_enable
(
&
hdmi
.
wp
,
false
);
}
static
int
hdmi_audio_start
(
struct
omap_dss_device
*
dssdev
)
{
return
hdmi4_audio_start
(
&
hdmi
.
core
,
&
hdmi
.
wp
);
}
static
void
hdmi_audio_stop
(
struct
omap_dss_device
*
dssdev
)
{
hdmi4_audio_stop
(
&
hdmi
.
core
,
&
hdmi
.
wp
);
}
static
bool
hdmi_audio_supported
(
struct
omap_dss_device
*
dssdev
)
{
bool
r
;
mutex_lock
(
&
hdmi
.
lock
);
r
=
hdmi_mode_has_audio
(
hdmi
.
cfg
.
hdmi_dvi_mode
);
mutex_unlock
(
&
hdmi
.
lock
);
return
r
;
}
static
int
hdmi_audio_config
(
struct
omap_dss_device
*
dssdev
,
struct
omap_dss_audio
*
audio
)
{
int
r
;
u32
pclk
=
hdmi
.
cfg
.
timings
.
pixelclock
;
mutex_lock
(
&
hdmi
.
lock
);
if
(
!
hdmi_mode_has_audio
(
hdmi
.
cfg
.
hdmi_dvi_mode
))
{
r
=
-
EPERM
;
goto
err
;
}
r
=
hdmi4_audio_config
(
&
hdmi
.
core
,
&
hdmi
.
wp
,
audio
,
pclk
);
if
(
r
)
goto
err
;
mutex_unlock
(
&
hdmi
.
lock
);
return
0
;
err:
mutex_unlock
(
&
hdmi
.
lock
);
return
r
;
}
#else
static
int
hdmi_audio_enable
(
struct
omap_dss_device
*
dssdev
)
{
return
-
EPERM
;
}
static
void
hdmi_audio_disable
(
struct
omap_dss_device
*
dssdev
)
{
}
static
int
hdmi_audio_start
(
struct
omap_dss_device
*
dssdev
)
{
return
-
EPERM
;
}
static
void
hdmi_audio_stop
(
struct
omap_dss_device
*
dssdev
)
{
}
static
bool
hdmi_audio_supported
(
struct
omap_dss_device
*
dssdev
)
{
return
false
;
}
static
int
hdmi_audio_config
(
struct
omap_dss_device
*
dssdev
,
struct
omap_dss_audio
*
audio
)
{
return
-
EPERM
;
}
#endif
static
int
hdmi_set_infoframe
(
struct
omap_dss_device
*
dssdev
,
const
struct
hdmi_avi_infoframe
*
avi
)
{
...
...
@@ -618,13 +493,6 @@ static const struct omapdss_hdmi_ops hdmi_ops = {
.
read_edid
=
hdmi_read_edid
,
.
set_infoframe
=
hdmi_set_infoframe
,
.
set_hdmi_mode
=
hdmi_set_hdmi_mode
,
.
audio_enable
=
hdmi_audio_enable
,
.
audio_disable
=
hdmi_audio_disable
,
.
audio_start
=
hdmi_audio_start
,
.
audio_stop
=
hdmi_audio_stop
,
.
audio_supported
=
hdmi_audio_supported
,
.
audio_config
=
hdmi_audio_config
,
};
static
void
hdmi_init_output
(
struct
platform_device
*
pdev
)
...
...
@@ -642,7 +510,7 @@ static void hdmi_init_output(struct platform_device *pdev)
omapdss_register_output
(
out
);
}
static
void
__exit
hdmi_uninit_output
(
struct
platform_device
*
pdev
)
static
void
hdmi_uninit_output
(
struct
platform_device
*
pdev
)
{
struct
omap_dss_device
*
out
=
&
hdmi
.
output
;
...
...
@@ -671,6 +539,112 @@ static int hdmi_probe_of(struct platform_device *pdev)
return
r
;
}
/* Audio callbacks */
static
int
hdmi_audio_startup
(
struct
device
*
dev
,
void
(
*
abort_cb
)(
struct
device
*
dev
))
{
struct
omap_hdmi
*
hd
=
dev_get_drvdata
(
dev
);
int
ret
=
0
;
mutex_lock
(
&
hd
->
lock
);
if
(
!
hdmi_mode_has_audio
(
&
hd
->
cfg
)
||
!
hd
->
display_enabled
)
{
ret
=
-
EPERM
;
goto
out
;
}
hd
->
audio_abort_cb
=
abort_cb
;
out:
mutex_unlock
(
&
hd
->
lock
);
return
ret
;
}
static
int
hdmi_audio_shutdown
(
struct
device
*
dev
)
{
struct
omap_hdmi
*
hd
=
dev_get_drvdata
(
dev
);
mutex_lock
(
&
hd
->
lock
);
hd
->
audio_abort_cb
=
NULL
;
mutex_unlock
(
&
hd
->
lock
);
return
0
;
}
static
int
hdmi_audio_start
(
struct
device
*
dev
)
{
struct
omap_hdmi
*
hd
=
dev_get_drvdata
(
dev
);
WARN_ON
(
!
hdmi_mode_has_audio
(
&
hd
->
cfg
));
WARN_ON
(
!
hd
->
display_enabled
);
hdmi_wp_audio_enable
(
&
hd
->
wp
,
true
);
hdmi4_audio_start
(
&
hd
->
core
,
&
hd
->
wp
);
return
0
;
}
static
void
hdmi_audio_stop
(
struct
device
*
dev
)
{
struct
omap_hdmi
*
hd
=
dev_get_drvdata
(
dev
);
WARN_ON
(
!
hdmi_mode_has_audio
(
&
hd
->
cfg
));
WARN_ON
(
!
hd
->
display_enabled
);
hdmi4_audio_stop
(
&
hd
->
core
,
&
hd
->
wp
);
hdmi_wp_audio_enable
(
&
hd
->
wp
,
false
);
}
static
int
hdmi_audio_config
(
struct
device
*
dev
,
struct
omap_dss_audio
*
dss_audio
)
{
struct
omap_hdmi
*
hd
=
dev_get_drvdata
(
dev
);
int
ret
;
mutex_lock
(
&
hd
->
lock
);
if
(
!
hdmi_mode_has_audio
(
&
hd
->
cfg
)
||
!
hd
->
display_enabled
)
{
ret
=
-
EPERM
;
goto
out
;
}
ret
=
hdmi4_audio_config
(
&
hd
->
core
,
&
hd
->
wp
,
dss_audio
,
hd
->
cfg
.
timings
.
pixelclock
);
out:
mutex_unlock
(
&
hd
->
lock
);
return
ret
;
}
static
const
struct
omap_hdmi_audio_ops
hdmi_audio_ops
=
{
.
audio_startup
=
hdmi_audio_startup
,
.
audio_shutdown
=
hdmi_audio_shutdown
,
.
audio_start
=
hdmi_audio_start
,
.
audio_stop
=
hdmi_audio_stop
,
.
audio_config
=
hdmi_audio_config
,
};
static
int
hdmi_audio_register
(
struct
device
*
dev
)
{
struct
omap_hdmi_audio_pdata
pdata
=
{
.
dev
=
dev
,
.
dss_version
=
omapdss_get_version
(),
.
audio_dma_addr
=
hdmi_wp_get_audio_dma_addr
(
&
hdmi
.
wp
),
.
ops
=
&
hdmi_audio_ops
,
};
hdmi
.
audio_pdev
=
platform_device_register_data
(
dev
,
"omap-hdmi-audio"
,
PLATFORM_DEVID_AUTO
,
&
pdata
,
sizeof
(
pdata
));
if
(
IS_ERR
(
hdmi
.
audio_pdev
))
return
PTR_ERR
(
hdmi
.
audio_pdev
);
return
0
;
}
/* HDMI HW IP initialisation */
static
int
omapdss_hdmihw_probe
(
struct
platform_device
*
pdev
)
{
...
...
@@ -678,6 +652,7 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev)
int
irq
;
hdmi
.
pdev
=
pdev
;
dev_set_drvdata
(
&
pdev
->
dev
,
&
hdmi
);
mutex_init
(
&
hdmi
.
lock
);
...
...
@@ -691,28 +666,23 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev)
if
(
r
)
return
r
;
r
=
hdmi_pll_init
(
pdev
,
&
hdmi
.
pll
);
r
=
hdmi_pll_init
(
pdev
,
&
hdmi
.
pll
,
&
hdmi
.
wp
);
if
(
r
)
return
r
;
r
=
hdmi_phy_init
(
pdev
,
&
hdmi
.
phy
);
if
(
r
)
return
r
;
goto
er
r
;
r
=
hdmi4_core_init
(
pdev
,
&
hdmi
.
core
);
if
(
r
)
return
r
;
r
=
hdmi_get_clocks
(
pdev
);
if
(
r
)
{
DSSERR
(
"can't get clocks
\n
"
);
return
r
;
}
goto
err
;
irq
=
platform_get_irq
(
pdev
,
0
);
if
(
irq
<
0
)
{
DSSERR
(
"platform_get_irq failed
\n
"
);
return
-
ENODEV
;
r
=
-
ENODEV
;
goto
err
;
}
r
=
devm_request_threaded_irq
(
&
pdev
->
dev
,
irq
,
...
...
@@ -720,22 +690,38 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev)
IRQF_ONESHOT
,
"OMAP HDMI"
,
&
hdmi
.
wp
);
if
(
r
)
{
DSSERR
(
"HDMI IRQ request failed
\n
"
);
return
r
;
goto
er
r
;
}
pm_runtime_enable
(
&
pdev
->
dev
);
hdmi_init_output
(
pdev
);
r
=
hdmi_audio_register
(
&
pdev
->
dev
);
if
(
r
)
{
DSSERR
(
"Registering HDMI audio failed
\n
"
);
hdmi_uninit_output
(
pdev
);
pm_runtime_disable
(
&
pdev
->
dev
);
return
r
;
}
dss_debugfs_create_file
(
"hdmi"
,
hdmi_dump_regs
);
return
0
;
err:
hdmi_pll_uninit
(
&
hdmi
.
pll
);
return
r
;
}
static
int
__exit
omapdss_hdmihw_remove
(
struct
platform_device
*
pdev
)
{
if
(
hdmi
.
audio_pdev
)
platform_device_unregister
(
hdmi
.
audio_pdev
);
hdmi_uninit_output
(
pdev
);
hdmi_pll_uninit
(
&
hdmi
.
pll
);
pm_runtime_disable
(
&
pdev
->
dev
);
return
0
;
...
...
@@ -743,8 +729,6 @@ static int __exit omapdss_hdmihw_remove(struct platform_device *pdev)
static
int
hdmi_runtime_suspend
(
struct
device
*
dev
)
{
clk_disable_unprepare
(
hdmi
.
sys_clk
);
dispc_runtime_put
();
return
0
;
...
...
@@ -758,8 +742,6 @@ static int hdmi_runtime_resume(struct device *dev)
if
(
r
<
0
)
return
r
;
clk_prepare_enable
(
hdmi
.
sys_clk
);
return
0
;
}
...
...
drivers/video/fbdev/omap2/dss/hdmi4_core.c
浏览文件 @
3315764e
...
...
@@ -31,10 +31,8 @@
#include <linux/platform_device.h>
#include <linux/string.h>
#include <linux/seq_file.h>
#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
#include <sound/asound.h>
#include <sound/asoundef.h>
#endif
#include "hdmi4_core.h"
#include "dss_features.h"
...
...
@@ -530,7 +528,6 @@ void hdmi4_core_dump(struct hdmi_core_data *core, struct seq_file *s)
DUMPCOREAV
(
HDMI_CORE_AV_CEC_ADDR_ID
);
}
#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
static
void
hdmi_core_audio_config
(
struct
hdmi_core_data
*
core
,
struct
hdmi_core_audio_config
*
cfg
)
{
...
...
@@ -877,17 +874,6 @@ void hdmi4_audio_stop(struct hdmi_core_data *core, struct hdmi_wp_data *wp)
hdmi_wp_audio_core_req_enable
(
wp
,
false
);
}
int
hdmi4_audio_get_dma_port
(
u32
*
offset
,
u32
*
size
)
{
if
(
!
offset
||
!
size
)
return
-
EINVAL
;
*
offset
=
HDMI_WP_AUDIO_DATA
;
*
size
=
4
;
return
0
;
}
#endif
int
hdmi4_core_init
(
struct
platform_device
*
pdev
,
struct
hdmi_core_data
*
core
)
{
struct
resource
*
res
;
...
...
drivers/video/fbdev/omap2/dss/hdmi4_core.h
浏览文件 @
3315764e
...
...
@@ -266,12 +266,8 @@ void hdmi4_configure(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
void
hdmi4_core_dump
(
struct
hdmi_core_data
*
core
,
struct
seq_file
*
s
);
int
hdmi4_core_init
(
struct
platform_device
*
pdev
,
struct
hdmi_core_data
*
core
);
#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
int
hdmi4_audio_start
(
struct
hdmi_core_data
*
core
,
struct
hdmi_wp_data
*
wp
);
void
hdmi4_audio_stop
(
struct
hdmi_core_data
*
core
,
struct
hdmi_wp_data
*
wp
);
int
hdmi4_audio_config
(
struct
hdmi_core_data
*
core
,
struct
hdmi_wp_data
*
wp
,
struct
omap_dss_audio
*
audio
,
u32
pclk
);
int
hdmi4_audio_get_dma_port
(
u32
*
offset
,
u32
*
size
);
#endif
#endif
drivers/video/fbdev/omap2/dss/hdmi5.c
浏览文件 @
3315764e
...
...
@@ -38,29 +38,13 @@
#include <linux/gpio.h>
#include <linux/regulator/consumer.h>
#include <video/omapdss.h>
#include <sound/omap-hdmi-audio.h>
#include "hdmi5_core.h"
#include "dss.h"
#include "dss_features.h"
static
struct
{
struct
mutex
lock
;
struct
platform_device
*
pdev
;
struct
hdmi_wp_data
wp
;
struct
hdmi_pll_data
pll
;
struct
hdmi_phy_data
phy
;
struct
hdmi_core_data
core
;
struct
hdmi_config
cfg
;
struct
clk
*
sys_clk
;
struct
regulator
*
vdda_reg
;
bool
core_enabled
;
struct
omap_dss_device
output
;
}
hdmi
;
static
struct
omap_hdmi
hdmi
;
static
int
hdmi_runtime_get
(
void
)
{
...
...
@@ -198,7 +182,7 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev)
int
r
;
struct
omap_video_timings
*
p
;
struct
omap_overlay_manager
*
mgr
=
hdmi
.
output
.
manager
;
unsigned
long
phy
;
struct
dss_pll_clock_info
hdmi_cinfo
=
{
0
}
;
r
=
hdmi_power_on_core
(
dssdev
);
if
(
r
)
...
...
@@ -208,24 +192,27 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev)
DSSDBG
(
"hdmi_power_on x_res= %d y_res = %d
\n
"
,
p
->
x_res
,
p
->
y_res
);
/* the functions below use kHz pixel clock. TODO: change to Hz */
phy
=
p
->
pixelclock
/
1000
;
hdmi_pll_compute
(
&
hdmi
.
pll
,
clk_get_rate
(
hdmi
.
sys_clk
),
phy
);
hdmi_pll_compute
(
&
hdmi
.
pll
,
p
->
pixelclock
,
&
hdmi_cinfo
);
/* disable and clear irqs */
hdmi_wp_clear_irqenable
(
&
hdmi
.
wp
,
0xffffffff
);
hdmi_wp_set_irqstatus
(
&
hdmi
.
wp
,
hdmi_wp_get_irqstatus
(
&
hdmi
.
wp
));
/* config the PLL and PHY hdmi_set_pll_pwrfirst */
r
=
hdmi_pll_enable
(
&
hdmi
.
pll
,
&
hdmi
.
wp
);
r
=
dss_pll_enable
(
&
hdmi
.
pll
.
pll
);
if
(
r
)
{
DSS
DBG
(
"Failed to lock
PLL
\n
"
);
DSS
ERR
(
"Failed to enable
PLL
\n
"
);
goto
err_pll_enable
;
}
r
=
hdmi_phy_configure
(
&
hdmi
.
phy
,
&
hdmi
.
cfg
);
r
=
dss_pll_set_config
(
&
hdmi
.
pll
.
pll
,
&
hdmi_cinfo
);
if
(
r
)
{
DSSERR
(
"Failed to configure PLL
\n
"
);
goto
err_pll_cfg
;
}
r
=
hdmi_phy_configure
(
&
hdmi
.
phy
,
hdmi_cinfo
.
clkdco
,
hdmi_cinfo
.
clkout
[
0
]);
if
(
r
)
{
DSSDBG
(
"Failed to start PHY
\n
"
);
goto
err_phy_cfg
;
...
...
@@ -262,7 +249,8 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev)
hdmi_wp_set_phy_pwr
(
&
hdmi
.
wp
,
HDMI_PHYPWRCMD_OFF
);
err_phy_pwr:
err_phy_cfg:
hdmi_pll_disable
(
&
hdmi
.
pll
,
&
hdmi
.
wp
);
err_pll_cfg:
dss_pll_disable
(
&
hdmi
.
pll
.
pll
);
err_pll_enable:
hdmi_power_off_core
(
dssdev
);
return
-
EIO
;
...
...
@@ -280,7 +268,7 @@ static void hdmi_power_off_full(struct omap_dss_device *dssdev)
hdmi_wp_set_phy_pwr
(
&
hdmi
.
wp
,
HDMI_PHYPWRCMD_OFF
);
hdmi_pll_disable
(
&
hdmi
.
pll
,
&
hdmi
.
wp
);
dss_pll_disable
(
&
hdmi
.
pll
.
pll
);
hdmi_power_off_core
(
dssdev
);
}
...
...
@@ -290,6 +278,10 @@ static int hdmi_display_check_timing(struct omap_dss_device *dssdev,
{
struct
omap_dss_device
*
out
=
&
hdmi
.
output
;
/* TODO: proper interlace support */
if
(
timings
->
interlace
)
return
-
EINVAL
;
if
(
!
dispc_mgr_timings_ok
(
out
->
dispc_channel
,
timings
))
return
-
EINVAL
;
...
...
@@ -377,6 +369,8 @@ static int hdmi_display_enable(struct omap_dss_device *dssdev)
goto
err0
;
}
hdmi
.
display_enabled
=
true
;
mutex_unlock
(
&
hdmi
.
lock
);
return
0
;
...
...
@@ -391,8 +385,13 @@ static void hdmi_display_disable(struct omap_dss_device *dssdev)
mutex_lock
(
&
hdmi
.
lock
);
if
(
hdmi
.
audio_pdev
&&
hdmi
.
audio_abort_cb
)
hdmi
.
audio_abort_cb
(
&
hdmi
.
audio_pdev
->
dev
);
hdmi_power_off_full
(
dssdev
);
hdmi
.
display_enabled
=
false
;
mutex_unlock
(
&
hdmi
.
lock
);
}
...
...
@@ -429,21 +428,6 @@ static void hdmi_core_disable(struct omap_dss_device *dssdev)
mutex_unlock
(
&
hdmi
.
lock
);
}
static
int
hdmi_get_clocks
(
struct
platform_device
*
pdev
)
{
struct
clk
*
clk
;
clk
=
devm_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
;
return
0
;
}
static
int
hdmi_connect
(
struct
omap_dss_device
*
dssdev
,
struct
omap_dss_device
*
dst
)
{
...
...
@@ -509,112 +493,6 @@ static int hdmi_read_edid(struct omap_dss_device *dssdev,
return
r
;
}
#if defined(CONFIG_OMAP5_DSS_HDMI_AUDIO)
static
int
hdmi_audio_enable
(
struct
omap_dss_device
*
dssdev
)
{
int
r
;
mutex_lock
(
&
hdmi
.
lock
);
if
(
!
hdmi_mode_has_audio
(
hdmi
.
cfg
.
hdmi_dvi_mode
))
{
r
=
-
EPERM
;
goto
err
;
}
r
=
hdmi_wp_audio_enable
(
&
hdmi
.
wp
,
true
);
if
(
r
)
goto
err
;
mutex_unlock
(
&
hdmi
.
lock
);
return
0
;
err:
mutex_unlock
(
&
hdmi
.
lock
);
return
r
;
}
static
void
hdmi_audio_disable
(
struct
omap_dss_device
*
dssdev
)
{
hdmi_wp_audio_enable
(
&
hdmi
.
wp
,
false
);
}
static
int
hdmi_audio_start
(
struct
omap_dss_device
*
dssdev
)
{
return
hdmi_wp_audio_core_req_enable
(
&
hdmi
.
wp
,
true
);
}
static
void
hdmi_audio_stop
(
struct
omap_dss_device
*
dssdev
)
{
hdmi_wp_audio_core_req_enable
(
&
hdmi
.
wp
,
false
);
}
static
bool
hdmi_audio_supported
(
struct
omap_dss_device
*
dssdev
)
{
bool
r
;
mutex_lock
(
&
hdmi
.
lock
);
r
=
hdmi_mode_has_audio
(
hdmi
.
cfg
.
hdmi_dvi_mode
);
mutex_unlock
(
&
hdmi
.
lock
);
return
r
;
}
static
int
hdmi_audio_config
(
struct
omap_dss_device
*
dssdev
,
struct
omap_dss_audio
*
audio
)
{
int
r
;
u32
pclk
=
hdmi
.
cfg
.
timings
.
pixelclock
;
mutex_lock
(
&
hdmi
.
lock
);
if
(
!
hdmi_mode_has_audio
(
hdmi
.
cfg
.
hdmi_dvi_mode
))
{
r
=
-
EPERM
;
goto
err
;
}
r
=
hdmi5_audio_config
(
&
hdmi
.
core
,
&
hdmi
.
wp
,
audio
,
pclk
);
if
(
r
)
goto
err
;
mutex_unlock
(
&
hdmi
.
lock
);
return
0
;
err:
mutex_unlock
(
&
hdmi
.
lock
);
return
r
;
}
#else
static
int
hdmi_audio_enable
(
struct
omap_dss_device
*
dssdev
)
{
return
-
EPERM
;
}
static
void
hdmi_audio_disable
(
struct
omap_dss_device
*
dssdev
)
{
}
static
int
hdmi_audio_start
(
struct
omap_dss_device
*
dssdev
)
{
return
-
EPERM
;
}
static
void
hdmi_audio_stop
(
struct
omap_dss_device
*
dssdev
)
{
}
static
bool
hdmi_audio_supported
(
struct
omap_dss_device
*
dssdev
)
{
return
false
;
}
static
int
hdmi_audio_config
(
struct
omap_dss_device
*
dssdev
,
struct
omap_dss_audio
*
audio
)
{
return
-
EPERM
;
}
#endif
static
int
hdmi_set_infoframe
(
struct
omap_dss_device
*
dssdev
,
const
struct
hdmi_avi_infoframe
*
avi
)
{
...
...
@@ -643,13 +521,6 @@ static const struct omapdss_hdmi_ops hdmi_ops = {
.
read_edid
=
hdmi_read_edid
,
.
set_infoframe
=
hdmi_set_infoframe
,
.
set_hdmi_mode
=
hdmi_set_hdmi_mode
,
.
audio_enable
=
hdmi_audio_enable
,
.
audio_disable
=
hdmi_audio_disable
,
.
audio_start
=
hdmi_audio_start
,
.
audio_stop
=
hdmi_audio_stop
,
.
audio_supported
=
hdmi_audio_supported
,
.
audio_config
=
hdmi_audio_config
,
};
static
void
hdmi_init_output
(
struct
platform_device
*
pdev
)
...
...
@@ -667,7 +538,7 @@ static void hdmi_init_output(struct platform_device *pdev)
omapdss_register_output
(
out
);
}
static
void
__exit
hdmi_uninit_output
(
struct
platform_device
*
pdev
)
static
void
hdmi_uninit_output
(
struct
platform_device
*
pdev
)
{
struct
omap_dss_device
*
out
=
&
hdmi
.
output
;
...
...
@@ -696,6 +567,119 @@ static int hdmi_probe_of(struct platform_device *pdev)
return
r
;
}
/* Audio callbacks */
static
int
hdmi_audio_startup
(
struct
device
*
dev
,
void
(
*
abort_cb
)(
struct
device
*
dev
))
{
struct
omap_hdmi
*
hd
=
dev_get_drvdata
(
dev
);
int
ret
=
0
;
mutex_lock
(
&
hd
->
lock
);
if
(
!
hdmi_mode_has_audio
(
&
hd
->
cfg
)
||
!
hd
->
display_enabled
)
{
ret
=
-
EPERM
;
goto
out
;
}
hd
->
audio_abort_cb
=
abort_cb
;
out:
mutex_unlock
(
&
hd
->
lock
);
return
ret
;
}
static
int
hdmi_audio_shutdown
(
struct
device
*
dev
)
{
struct
omap_hdmi
*
hd
=
dev_get_drvdata
(
dev
);
mutex_lock
(
&
hd
->
lock
);
hd
->
audio_abort_cb
=
NULL
;
mutex_unlock
(
&
hd
->
lock
);
return
0
;
}
static
int
hdmi_audio_start
(
struct
device
*
dev
)
{
struct
omap_hdmi
*
hd
=
dev_get_drvdata
(
dev
);
WARN_ON
(
!
hdmi_mode_has_audio
(
&
hd
->
cfg
));
WARN_ON
(
!
hd
->
display_enabled
);
/* No-idle while playing audio, store the old value */
hd
->
wp_idlemode
=
REG_GET
(
hdmi
.
wp
.
base
,
HDMI_WP_SYSCONFIG
,
3
,
2
);
REG_FLD_MOD
(
hdmi
.
wp
.
base
,
HDMI_WP_SYSCONFIG
,
1
,
3
,
2
);
hdmi_wp_audio_enable
(
&
hd
->
wp
,
true
);
hdmi_wp_audio_core_req_enable
(
&
hd
->
wp
,
true
);
return
0
;
}
static
void
hdmi_audio_stop
(
struct
device
*
dev
)
{
struct
omap_hdmi
*
hd
=
dev_get_drvdata
(
dev
);
WARN_ON
(
!
hdmi_mode_has_audio
(
&
hd
->
cfg
));
WARN_ON
(
!
hd
->
display_enabled
);
hdmi_wp_audio_core_req_enable
(
&
hd
->
wp
,
false
);
hdmi_wp_audio_enable
(
&
hd
->
wp
,
false
);
/* Playback stopped, restore original idlemode */
REG_FLD_MOD
(
hdmi
.
wp
.
base
,
HDMI_WP_SYSCONFIG
,
hd
->
wp_idlemode
,
3
,
2
);
}
static
int
hdmi_audio_config
(
struct
device
*
dev
,
struct
omap_dss_audio
*
dss_audio
)
{
struct
omap_hdmi
*
hd
=
dev_get_drvdata
(
dev
);
int
ret
;
mutex_lock
(
&
hd
->
lock
);
if
(
!
hdmi_mode_has_audio
(
&
hd
->
cfg
)
||
!
hd
->
display_enabled
)
{
ret
=
-
EPERM
;
goto
out
;
}
ret
=
hdmi5_audio_config
(
&
hd
->
core
,
&
hd
->
wp
,
dss_audio
,
hd
->
cfg
.
timings
.
pixelclock
);
out:
mutex_unlock
(
&
hd
->
lock
);
return
ret
;
}
static
const
struct
omap_hdmi_audio_ops
hdmi_audio_ops
=
{
.
audio_startup
=
hdmi_audio_startup
,
.
audio_shutdown
=
hdmi_audio_shutdown
,
.
audio_start
=
hdmi_audio_start
,
.
audio_stop
=
hdmi_audio_stop
,
.
audio_config
=
hdmi_audio_config
,
};
static
int
hdmi_audio_register
(
struct
device
*
dev
)
{
struct
omap_hdmi_audio_pdata
pdata
=
{
.
dev
=
dev
,
.
dss_version
=
omapdss_get_version
(),
.
audio_dma_addr
=
hdmi_wp_get_audio_dma_addr
(
&
hdmi
.
wp
),
.
ops
=
&
hdmi_audio_ops
,
};
hdmi
.
audio_pdev
=
platform_device_register_data
(
dev
,
"omap-hdmi-audio"
,
PLATFORM_DEVID_AUTO
,
&
pdata
,
sizeof
(
pdata
));
if
(
IS_ERR
(
hdmi
.
audio_pdev
))
return
PTR_ERR
(
hdmi
.
audio_pdev
);
return
0
;
}
/* HDMI HW IP initialisation */
static
int
omapdss_hdmihw_probe
(
struct
platform_device
*
pdev
)
{
...
...
@@ -703,6 +687,7 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev)
int
irq
;
hdmi
.
pdev
=
pdev
;
dev_set_drvdata
(
&
pdev
->
dev
,
&
hdmi
);
mutex_init
(
&
hdmi
.
lock
);
...
...
@@ -716,28 +701,23 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev)
if
(
r
)
return
r
;
r
=
hdmi_pll_init
(
pdev
,
&
hdmi
.
pll
);
r
=
hdmi_pll_init
(
pdev
,
&
hdmi
.
pll
,
&
hdmi
.
wp
);
if
(
r
)
return
r
;
r
=
hdmi_phy_init
(
pdev
,
&
hdmi
.
phy
);
if
(
r
)
return
r
;
goto
er
r
;
r
=
hdmi5_core_init
(
pdev
,
&
hdmi
.
core
);
if
(
r
)
return
r
;
r
=
hdmi_get_clocks
(
pdev
);
if
(
r
)
{
DSSERR
(
"can't get clocks
\n
"
);
return
r
;
}
goto
err
;
irq
=
platform_get_irq
(
pdev
,
0
);
if
(
irq
<
0
)
{
DSSERR
(
"platform_get_irq failed
\n
"
);
return
-
ENODEV
;
r
=
-
ENODEV
;
goto
err
;
}
r
=
devm_request_threaded_irq
(
&
pdev
->
dev
,
irq
,
...
...
@@ -745,22 +725,38 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev)
IRQF_ONESHOT
,
"OMAP HDMI"
,
&
hdmi
.
wp
);
if
(
r
)
{
DSSERR
(
"HDMI IRQ request failed
\n
"
);
return
r
;
goto
er
r
;
}
pm_runtime_enable
(
&
pdev
->
dev
);
hdmi_init_output
(
pdev
);
r
=
hdmi_audio_register
(
&
pdev
->
dev
);
if
(
r
)
{
DSSERR
(
"Registering HDMI audio failed %d
\n
"
,
r
);
hdmi_uninit_output
(
pdev
);
pm_runtime_disable
(
&
pdev
->
dev
);
return
r
;
}
dss_debugfs_create_file
(
"hdmi"
,
hdmi_dump_regs
);
return
0
;
err:
hdmi_pll_uninit
(
&
hdmi
.
pll
);
return
r
;
}
static
int
__exit
omapdss_hdmihw_remove
(
struct
platform_device
*
pdev
)
{
if
(
hdmi
.
audio_pdev
)
platform_device_unregister
(
hdmi
.
audio_pdev
);
hdmi_uninit_output
(
pdev
);
hdmi_pll_uninit
(
&
hdmi
.
pll
);
pm_runtime_disable
(
&
pdev
->
dev
);
return
0
;
...
...
@@ -768,8 +764,6 @@ static int __exit omapdss_hdmihw_remove(struct platform_device *pdev)
static
int
hdmi_runtime_suspend
(
struct
device
*
dev
)
{
clk_disable_unprepare
(
hdmi
.
sys_clk
);
dispc_runtime_put
();
return
0
;
...
...
@@ -783,8 +777,6 @@ static int hdmi_runtime_resume(struct device *dev)
if
(
r
<
0
)
return
r
;
clk_prepare_enable
(
hdmi
.
sys_clk
);
return
0
;
}
...
...
drivers/video/fbdev/omap2/dss/hdmi5_core.c
浏览文件 @
3315764e
...
...
@@ -30,10 +30,8 @@
#include <linux/string.h>
#include <linux/seq_file.h>
#include <drm/drm_edid.h>
#if defined(CONFIG_OMAP5_DSS_HDMI_AUDIO)
#include <sound/asound.h>
#include <sound/asoundef.h>
#endif
#include "hdmi5_core.h"
...
...
@@ -644,9 +642,6 @@ void hdmi5_configure(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
hdmi_core_enable_interrupts
(
core
);
}
#if defined(CONFIG_OMAP5_DSS_HDMI_AUDIO)
static
void
hdmi5_core_audio_config
(
struct
hdmi_core_data
*
core
,
struct
hdmi_core_audio_config
*
cfg
)
{
...
...
@@ -721,7 +716,7 @@ static void hdmi5_core_audio_config(struct hdmi_core_data *core,
/* Source number */
val
=
cfg
->
iec60958_cfg
->
status
[
2
]
&
IEC958_AES2_CON_SOURCE
;
REG_FLD_MOD
(
base
,
HDMI_CORE_FC_AUDSCHNLS
(
2
),
val
,
3
,
4
);
REG_FLD_MOD
(
base
,
HDMI_CORE_FC_AUDSCHNLS
(
2
),
val
,
3
,
0
);
/* Channel number right 0 */
REG_FLD_MOD
(
base
,
HDMI_CORE_FC_AUDSCHNLS
(
3
),
2
,
3
,
0
);
...
...
@@ -879,6 +874,9 @@ int hdmi5_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
/* only LPCM atm */
audio_format
.
type
=
HDMI_AUDIO_TYPE_LPCM
;
/* only allowed option */
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
;
...
...
@@ -894,7 +892,6 @@ int hdmi5_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
return
0
;
}
#endif
int
hdmi5_core_init
(
struct
platform_device
*
pdev
,
struct
hdmi_core_data
*
core
)
{
...
...
drivers/video/fbdev/omap2/dss/hdmi5_core.h
浏览文件 @
3315764e
...
...
@@ -299,8 +299,6 @@ void hdmi5_configure(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
struct
hdmi_config
*
cfg
);
int
hdmi5_core_init
(
struct
platform_device
*
pdev
,
struct
hdmi_core_data
*
core
);
#if defined(CONFIG_OMAP5_DSS_HDMI_AUDIO)
int
hdmi5_audio_config
(
struct
hdmi_core_data
*
core
,
struct
hdmi_wp_data
*
wp
,
struct
omap_dss_audio
*
audio
,
u32
pclk
);
#endif
#endif
drivers/video/fbdev/omap2/dss/hdmi_common.c
浏览文件 @
3315764e
...
...
@@ -48,7 +48,6 @@ int hdmi_parse_lanes_of(struct platform_device *pdev, struct device_node *ep,
return
0
;
}
#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
int
hdmi_compute_acr
(
u32
pclk
,
u32
sample_freq
,
u32
*
n
,
u32
*
cts
)
{
u32
deep_color
;
...
...
@@ -147,4 +146,3 @@ int hdmi_compute_acr(u32 pclk, u32 sample_freq, u32 *n, u32 *cts)
return
0
;
}
#endif
drivers/video/fbdev/omap2/dss/hdmi_phy.c
浏览文件 @
3315764e
...
...
@@ -20,9 +20,7 @@
struct
hdmi_phy_features
{
bool
bist_ctrl
;
bool
calc_freqout
;
bool
ldo_voltage
;
unsigned
long
dcofreq_min
;
unsigned
long
max_phy
;
};
...
...
@@ -132,7 +130,8 @@ static void hdmi_phy_configure_lanes(struct hdmi_phy_data *phy)
REG_FLD_MOD
(
phy
->
base
,
HDMI_TXPHY_PAD_CFG_CTRL
,
pol_val
,
30
,
27
);
}
int
hdmi_phy_configure
(
struct
hdmi_phy_data
*
phy
,
struct
hdmi_config
*
cfg
)
int
hdmi_phy_configure
(
struct
hdmi_phy_data
*
phy
,
unsigned
long
hfbitclk
,
unsigned
long
lfbitclk
)
{
u8
freqout
;
...
...
@@ -149,20 +148,16 @@ int hdmi_phy_configure(struct hdmi_phy_data *phy, struct hdmi_config *cfg)
if
(
phy_feat
->
bist_ctrl
)
REG_FLD_MOD
(
phy
->
base
,
HDMI_TXPHY_BIST_CONTROL
,
1
,
11
,
11
);
if
(
phy_feat
->
calc_freqout
)
{
/* DCOCLK/10 is pixel clock, compare pclk with DCOCLK_MIN/10 */
u32
dco_min
=
phy_feat
->
dcofreq_min
/
10
;
u32
pclk
=
cfg
->
timings
.
pixelclock
;
if
(
pclk
<
dco_min
)
/*
* If the hfbitclk != lfbitclk, it means the lfbitclk was configured
* to be used for TMDS.
*/
if
(
hfbitclk
!=
lfbitclk
)
freqout
=
0
;
else
if
((
pclk
>=
dco_min
)
&&
(
pclk
<
phy_feat
->
max_phy
)
)
else
if
(
hfbitclk
/
10
<
phy_feat
->
max_phy
)
freqout
=
1
;
else
freqout
=
2
;
}
else
{
freqout
=
1
;
}
/*
* Write to phy address 0 to configure the clock
...
...
@@ -184,17 +179,13 @@ int hdmi_phy_configure(struct hdmi_phy_data *phy, struct hdmi_config *cfg)
static
const
struct
hdmi_phy_features
omap44xx_phy_feats
=
{
.
bist_ctrl
=
false
,
.
calc_freqout
=
false
,
.
ldo_voltage
=
true
,
.
dcofreq_min
=
500000000
,
.
max_phy
=
185675000
,
};
static
const
struct
hdmi_phy_features
omap54xx_phy_feats
=
{
.
bist_ctrl
=
true
,
.
calc_freqout
=
true
,
.
ldo_voltage
=
false
,
.
dcofreq_min
=
750000000
,
.
max_phy
=
186000000
,
};
...
...
drivers/video/fbdev/omap2/dss/hdmi_pll.c
浏览文件 @
3315764e
...
...
@@ -15,26 +15,13 @@
#include <linux/err.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <video/omapdss.h>
#include "dss.h"
#include "hdmi.h"
#define HDMI_DEFAULT_REGN 16
#define HDMI_DEFAULT_REGM2 1
struct
hdmi_pll_features
{
bool
sys_reset
;
/* this is a hack, need to replace it with a better computation of M2 */
bool
bound_dcofreq
;
unsigned
long
fint_min
,
fint_max
;
u16
regm_max
;
unsigned
long
dcofreq_low_min
,
dcofreq_low_max
;
unsigned
long
dcofreq_high_min
,
dcofreq_high_max
;
};
static
const
struct
hdmi_pll_features
*
pll_feat
;
void
hdmi_pll_dump
(
struct
hdmi_pll_data
*
pll
,
struct
seq_file
*
s
)
{
#define DUMPPLL(r) seq_printf(s, "%-35s %08x\n", #r,\
...
...
@@ -51,228 +38,189 @@ void hdmi_pll_dump(struct hdmi_pll_data *pll, struct seq_file *s)
DUMPPLL
(
PLLCTRL_CFG4
);
}
void
hdmi_pll_compute
(
struct
hdmi_pll_data
*
pll
,
unsigned
long
clkin
,
int
phy
)
void
hdmi_pll_compute
(
struct
hdmi_pll_data
*
pll
,
unsigned
long
target_tmds
,
struct
dss_pll_clock_info
*
pi
)
{
struct
hdmi_pll_info
*
pi
=
&
pll
->
info
;
unsigned
long
refclk
;
u32
mf
;
unsigned
long
fint
,
clkdco
,
clkout
;
unsigned
long
target_bitclk
,
target_clkdco
;
unsigned
long
min_dco
;
unsigned
n
,
m
,
mf
,
m2
,
sd
;
unsigned
long
clkin
;
const
struct
dss_pll_hw
*
hw
=
pll
->
pll
.
hw
;
/* use our funky units */
clkin
/=
10000
;
clkin
=
clk_get_rate
(
pll
->
pll
.
clkin
);
/*
* Input clock is predivided by N + 1
* out put of which is reference clk
*/
DSSDBG
(
"clkin %lu, target tmds %lu
\n
"
,
clkin
,
target_tmds
);
pi
->
regn
=
HDMI_DEFAULT_REGN
;
target_bitclk
=
target_tmds
*
10
;
refclk
=
clkin
/
pi
->
regn
;
/* Fint */
n
=
DIV_ROUND_UP
(
clkin
,
hw
->
fint_max
);
fint
=
clkin
/
n
;
/* temorary hack to make sure DCO freq isn't calculated too low */
if
(
pll_feat
->
bound_dcofreq
&&
phy
<=
65000
)
pi
->
regm2
=
3
;
else
pi
->
regm2
=
HDMI_DEFAULT_REGM2
;
/*
* multiplier is pixel_clk/ref_clk
* Multiplying by 100 to avoid fractional part removal
*/
pi
->
regm
=
phy
*
pi
->
regm2
/
refclk
;
/* adjust m2 so that the clkdco will be high enough */
min_dco
=
roundup
(
hw
->
clkdco_min
,
fint
);
m2
=
DIV_ROUND_UP
(
min_dco
,
target_bitclk
);
if
(
m2
==
0
)
m2
=
1
;
/*
* fractional multiplier is remainder of the difference between
* multiplier and actual phy(required pixel clock thus should be
* multiplied by 2^18(262144) divided by the reference clock
*/
mf
=
(
phy
-
pi
->
regm
/
pi
->
regm2
*
refclk
)
*
262144
;
pi
->
regmf
=
pi
->
regm2
*
mf
/
refclk
;
/*
* Dcofreq should be set to 1 if required pixel clock
* is greater than 1000MHz
*/
pi
->
dcofreq
=
phy
>
1000
*
100
;
pi
->
regsd
=
((
pi
->
regm
*
clkin
/
10
)
/
(
pi
->
regn
*
250
)
+
5
)
/
10
;
/* Set the reference clock to sysclk reference */
pi
->
refsel
=
HDMI_REFSEL_SYSCLK
;
DSSDBG
(
"M = %d Mf = %d
\n
"
,
pi
->
regm
,
pi
->
regmf
);
DSSDBG
(
"range = %d sd = %d
\n
"
,
pi
->
dcofreq
,
pi
->
regsd
);
}
static
int
hdmi_pll_config
(
struct
hdmi_pll_data
*
pll
)
{
u32
r
;
struct
hdmi_pll_info
*
fmt
=
&
pll
->
info
;
target_clkdco
=
target_bitclk
*
m2
;
m
=
target_clkdco
/
fint
;
/* PLL start always use manual mode */
REG_FLD_MOD
(
pll
->
base
,
PLLCTRL_PLL_CONTROL
,
0x0
,
0
,
0
);
clkdco
=
fint
*
m
;
r
=
hdmi_read_reg
(
pll
->
base
,
PLLCTRL_CFG1
);
r
=
FLD_MOD
(
r
,
fmt
->
regm
,
20
,
9
);
/* CFG1_PLL_REGM */
r
=
FLD_MOD
(
r
,
fmt
->
regn
-
1
,
8
,
1
);
/* CFG1_PLL_REGN */
hdmi_write_reg
(
pll
->
base
,
PLLCTRL_CFG1
,
r
);
r
=
hdmi_read_reg
(
pll
->
base
,
PLLCTRL_CFG2
);
r
=
FLD_MOD
(
r
,
0x0
,
12
,
12
);
/* PLL_HIGHFREQ divide by 2 */
r
=
FLD_MOD
(
r
,
0x1
,
13
,
13
);
/* PLL_REFEN */
r
=
FLD_MOD
(
r
,
0x0
,
14
,
14
);
/* PHY_CLKINEN de-assert during locking */
r
=
FLD_MOD
(
r
,
fmt
->
refsel
,
22
,
21
);
/* REFSEL */
if
(
fmt
->
dcofreq
)
r
=
FLD_MOD
(
r
,
0x4
,
3
,
1
);
/* 1000MHz and 2000MHz */
/* adjust clkdco with fractional mf */
if
(
WARN_ON
(
target_clkdco
-
clkdco
>
fint
))
mf
=
0
;
else
r
=
FLD_MOD
(
r
,
0x2
,
3
,
1
);
/* 500MHz and 1000MHz */
hdmi_write_reg
(
pll
->
base
,
PLLCTRL_CFG2
,
r
);
mf
=
(
u32
)
div_u64
(
262144ull
*
(
target_clkdco
-
clkdco
),
fint
);
REG_FLD_MOD
(
pll
->
base
,
PLLCTRL_CFG3
,
fmt
->
regsd
,
17
,
10
);
r
=
hdmi_read_reg
(
pll
->
base
,
PLLCTRL_CFG4
);
r
=
FLD_MOD
(
r
,
fmt
->
regm2
,
24
,
18
);
r
=
FLD_MOD
(
r
,
fmt
->
regmf
,
17
,
0
);
hdmi_write_reg
(
pll
->
base
,
PLLCTRL_CFG4
,
r
);
/* go now */
REG_FLD_MOD
(
pll
->
base
,
PLLCTRL_PLL_GO
,
0x1
,
0
,
0
);
/* wait for bit change */
if
(
hdmi_wait_for_bit_change
(
pll
->
base
,
PLLCTRL_PLL_GO
,
0
,
0
,
0
)
!=
0
)
{
DSSERR
(
"PLL GO bit not clearing
\n
"
);
return
-
ETIMEDOUT
;
}
if
(
mf
>
0
)
clkdco
+=
(
u32
)
div_u64
((
u64
)
mf
*
fint
,
262144
);
/* Wait till the lock bit is set in PLL status */
if
(
hdmi_wait_for_bit_change
(
pll
->
base
,
PLLCTRL_PLL_STATUS
,
1
,
1
,
1
)
!=
1
)
{
DSSERR
(
"cannot lock PLL
\n
"
);
DSSERR
(
"CFG1 0x%x
\n
"
,
hdmi_read_reg
(
pll
->
base
,
PLLCTRL_CFG1
));
DSSERR
(
"CFG2 0x%x
\n
"
,
hdmi_read_reg
(
pll
->
base
,
PLLCTRL_CFG2
));
DSSERR
(
"CFG4 0x%x
\n
"
,
hdmi_read_reg
(
pll
->
base
,
PLLCTRL_CFG4
));
return
-
ETIMEDOUT
;
}
clkout
=
clkdco
/
m2
;
DSSDBG
(
"PLL locked!
\n
"
);
/* sigma-delta */
sd
=
DIV_ROUND_UP
(
fint
*
m
,
250000000
);
return
0
;
}
DSSDBG
(
"N = %u, M = %u, M.f = %u, M2 = %u, SD = %u
\n
"
,
n
,
m
,
mf
,
m2
,
sd
);
DSSDBG
(
"Fint %lu, clkdco %lu, clkout %lu
\n
"
,
fint
,
clkdco
,
clkout
);
static
int
hdmi_pll_reset
(
struct
hdmi_pll_data
*
pll
)
{
/* SYSRESET controlled by power FSM */
REG_FLD_MOD
(
pll
->
base
,
PLLCTRL_PLL_CONTROL
,
pll_feat
->
sys_reset
,
3
,
3
);
/* READ 0x0 reset is in progress */
if
(
hdmi_wait_for_bit_change
(
pll
->
base
,
PLLCTRL_PLL_STATUS
,
0
,
0
,
1
)
!=
1
)
{
DSSERR
(
"Failed to sysreset PLL
\n
"
);
return
-
ETIMEDOUT
;
}
pi
->
n
=
n
;
pi
->
m
=
m
;
pi
->
mf
=
mf
;
pi
->
mX
[
0
]
=
m2
;
pi
->
sd
=
sd
;
return
0
;
pi
->
fint
=
fint
;
pi
->
clkdco
=
clkdco
;
pi
->
clkout
[
0
]
=
clkout
;
}
int
hdmi_pll_enable
(
struct
hdmi_pll_data
*
pll
,
struct
hdmi_wp_data
*
wp
)
static
int
hdmi_pll_enable
(
struct
dss_pll
*
dsspll
)
{
struct
hdmi_pll_data
*
pll
=
container_of
(
dsspll
,
struct
hdmi_pll_data
,
pll
);
struct
hdmi_wp_data
*
wp
=
pll
->
wp
;
u16
r
=
0
;
r
=
hdmi_wp_set_pll_pwr
(
wp
,
HDMI_PLLPWRCMD_ALLOFF
);
if
(
r
)
return
r
;
r
=
hdmi_wp_set_pll_pwr
(
wp
,
HDMI_PLLPWRCMD_BOTHON_ALLCLKS
);
if
(
r
)
return
r
;
r
=
hdmi_pll_reset
(
pll
);
if
(
r
)
return
r
;
r
=
hdmi_pll_config
(
pll
);
if
(
r
)
return
r
;
return
0
;
}
void
hdmi_pll_disable
(
struct
hdmi_pll_data
*
pll
,
struct
hdmi_wp_data
*
wp
)
static
void
hdmi_pll_disable
(
struct
dss_pll
*
dsspll
)
{
struct
hdmi_pll_data
*
pll
=
container_of
(
dsspll
,
struct
hdmi_pll_data
,
pll
);
struct
hdmi_wp_data
*
wp
=
pll
->
wp
;
hdmi_wp_set_pll_pwr
(
wp
,
HDMI_PLLPWRCMD_ALLOFF
);
}
static
const
struct
hdmi_pll_features
omap44xx_pll_feats
=
{
.
sys_reset
=
false
,
.
bound_dcofreq
=
false
,
static
const
struct
dss_pll_ops
dsi_pll_ops
=
{
.
enable
=
hdmi_pll_enable
,
.
disable
=
hdmi_pll_disable
,
.
set_config
=
dss_pll_write_config_type_b
,
};
static
const
struct
dss_pll_hw
dss_omap4_hdmi_pll_hw
=
{
.
n_max
=
255
,
.
m_min
=
20
,
.
m_max
=
4095
,
.
mX_max
=
127
,
.
fint_min
=
500000
,
.
fint_max
=
2500000
,
.
regm_max
=
4095
,
.
dcofreq_low_min
=
500000000
,
.
dcofreq_low_max
=
1000000000
,
.
dcofreq_high_min
=
1000000000
,
.
dcofreq_high_max
=
2000000000
,
.
clkdco_max
=
1800000000
,
.
clkdco_min
=
500000000
,
.
clkdco_low
=
1000000000
,
.
clkdco_max
=
2000000000
,
.
n_msb
=
8
,
.
n_lsb
=
1
,
.
m_msb
=
20
,
.
m_lsb
=
9
,
.
mX_msb
[
0
]
=
24
,
.
mX_lsb
[
0
]
=
18
,
.
has_selfreqdco
=
true
,
};
static
const
struct
hdmi_pll_features
omap54xx_pll_feats
=
{
.
sys_reset
=
true
,
.
bound_dcofreq
=
true
,
static
const
struct
dss_pll_hw
dss_omap5_hdmi_pll_hw
=
{
.
n_max
=
255
,
.
m_min
=
20
,
.
m_max
=
2045
,
.
mX_max
=
127
,
.
fint_min
=
620000
,
.
fint_max
=
2500000
,
.
regm_max
=
2046
,
.
dcofreq_low_min
=
750000000
,
.
dcofreq_low_max
=
1500000000
,
.
dcofreq_high_min
=
1250000000
,
.
dcofreq_high_max
=
2500000000UL
,
.
clkdco_max
=
1800000000
,
.
clkdco_min
=
750000000
,
.
clkdco_low
=
1500000000
,
.
clkdco_max
=
2500000000UL
,
.
n_msb
=
8
,
.
n_lsb
=
1
,
.
m_msb
=
20
,
.
m_lsb
=
9
,
.
mX_msb
[
0
]
=
24
,
.
mX_lsb
[
0
]
=
18
,
.
has_selfreqdco
=
true
,
.
has_refsel
=
true
,
};
static
int
hdmi_pll_init_features
(
struct
platform_device
*
pdev
)
static
int
dsi_init_pll_data
(
struct
platform_device
*
pdev
,
struct
hdmi_pll_data
*
hpll
)
{
struct
hdmi_pll_features
*
dst
;
const
struct
hdmi_pll_features
*
src
;
struct
dss_pll
*
pll
=
&
hpll
->
pll
;
struct
clk
*
clk
;
int
r
;
dst
=
devm_kzalloc
(
&
pdev
->
dev
,
sizeof
(
*
dst
),
GFP_KERNEL
);
if
(
!
dst
)
{
dev_err
(
&
pdev
->
dev
,
"Failed to allocate HDMI PHY Features
\n
"
);
return
-
ENOMEM
;
clk
=
devm_clk_get
(
&
pdev
->
dev
,
"sys_clk"
);
if
(
IS_ERR
(
clk
)
)
{
DSSERR
(
"can't get sys_clk
\n
"
);
return
PTR_ERR
(
clk
)
;
}
pll
->
name
=
"hdmi"
;
pll
->
base
=
hpll
->
base
;
pll
->
clkin
=
clk
;
switch
(
omapdss_get_version
())
{
case
OMAPDSS_VER_OMAP4430_ES1
:
case
OMAPDSS_VER_OMAP4430_ES2
:
case
OMAPDSS_VER_OMAP4
:
src
=
&
omap44xx_pll_feats
;
pll
->
hw
=
&
dss_omap4_hdmi_pll_hw
;
break
;
case
OMAPDSS_VER_OMAP5
:
src
=
&
omap54xx_pll_feats
;
pll
->
hw
=
&
dss_omap5_hdmi_pll_hw
;
break
;
default:
return
-
ENODEV
;
}
memcpy
(
dst
,
src
,
sizeof
(
*
dst
));
pll_feat
=
dst
;
pll
->
ops
=
&
dsi_pll_ops
;
r
=
dss_pll_register
(
pll
);
if
(
r
)
return
r
;
return
0
;
}
int
hdmi_pll_init
(
struct
platform_device
*
pdev
,
struct
hdmi_pll_data
*
pll
)
int
hdmi_pll_init
(
struct
platform_device
*
pdev
,
struct
hdmi_pll_data
*
pll
,
struct
hdmi_wp_data
*
wp
)
{
int
r
;
struct
resource
*
res
;
r
=
hdmi_pll_init_features
(
pdev
);
if
(
r
)
return
r
;
pll
->
wp
=
wp
;
res
=
platform_get_resource_byname
(
pdev
,
IORESOURCE_MEM
,
"pll"
);
if
(
!
res
)
{
...
...
@@ -286,5 +234,18 @@ int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll)
return
PTR_ERR
(
pll
->
base
);
}
r
=
dsi_init_pll_data
(
pdev
,
pll
);
if
(
r
)
{
DSSERR
(
"failed to init HDMI PLL
\n
"
);
return
r
;
}
return
0
;
}
void
hdmi_pll_uninit
(
struct
hdmi_pll_data
*
hpll
)
{
struct
dss_pll
*
pll
=
&
hpll
->
pll
;
dss_pll_unregister
(
pll
);
}
drivers/video/fbdev/omap2/dss/hdmi_wp.c
浏览文件 @
3315764e
...
...
@@ -185,7 +185,6 @@ void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt,
timings
->
interlace
=
param
->
timings
.
interlace
;
}
#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) || defined(CONFIG_OMAP5_DSS_HDMI_AUDIO)
void
hdmi_wp_audio_config_format
(
struct
hdmi_wp_data
*
wp
,
struct
hdmi_audio_format
*
aud_fmt
)
{
...
...
@@ -194,8 +193,12 @@ void hdmi_wp_audio_config_format(struct hdmi_wp_data *wp,
DSSDBG
(
"Enter hdmi_wp_audio_config_format
\n
"
);
r
=
hdmi_read_reg
(
wp
->
base
,
HDMI_WP_AUDIO_CFG
);
if
(
omapdss_get_version
()
==
OMAPDSS_VER_OMAP4430_ES1
||
omapdss_get_version
()
==
OMAPDSS_VER_OMAP4430_ES2
||
omapdss_get_version
()
==
OMAPDSS_VER_OMAP4
)
{
r
=
FLD_MOD
(
r
,
aud_fmt
->
stereo_channels
,
26
,
24
);
r
=
FLD_MOD
(
r
,
aud_fmt
->
active_chnnls_msk
,
23
,
16
);
}
r
=
FLD_MOD
(
r
,
aud_fmt
->
en_sig_blk_strt_end
,
5
,
5
);
r
=
FLD_MOD
(
r
,
aud_fmt
->
type
,
4
,
4
);
r
=
FLD_MOD
(
r
,
aud_fmt
->
justification
,
3
,
3
);
...
...
@@ -236,7 +239,6 @@ int hdmi_wp_audio_core_req_enable(struct hdmi_wp_data *wp, bool enable)
return
0
;
}
#endif
int
hdmi_wp_init
(
struct
platform_device
*
pdev
,
struct
hdmi_wp_data
*
wp
)
{
...
...
@@ -247,6 +249,7 @@ int hdmi_wp_init(struct platform_device *pdev, struct hdmi_wp_data *wp)
DSSERR
(
"can't get WP mem resource
\n
"
);
return
-
EINVAL
;
}
wp
->
phys_base
=
res
->
start
;
wp
->
base
=
devm_ioremap_resource
(
&
pdev
->
dev
,
res
);
if
(
IS_ERR
(
wp
->
base
))
{
...
...
@@ -256,3 +259,8 @@ int hdmi_wp_init(struct platform_device *pdev, struct hdmi_wp_data *wp)
return
0
;
}
phys_addr_t
hdmi_wp_get_audio_dma_addr
(
struct
hdmi_wp_data
*
wp
)
{
return
wp
->
phys_base
+
HDMI_WP_AUDIO_DATA
;
}
drivers/video/fbdev/omap2/dss/output.c
浏览文件 @
3315764e
...
...
@@ -19,6 +19,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/of.h>
#include <video/omapdss.h>
...
...
@@ -131,18 +132,30 @@ struct omap_dss_device *omap_dss_find_output(const char *name)
}
EXPORT_SYMBOL
(
omap_dss_find_output
);
struct
omap_dss_device
*
omap_dss_find_output_by_
node
(
struct
device_node
*
node
)
struct
omap_dss_device
*
omap_dss_find_output_by_
port_node
(
struct
device_node
*
port
)
{
struct
device_node
*
src_node
;
struct
omap_dss_device
*
out
;
u32
reg
;
src_node
=
dss_of_port_get_parent_device
(
port
);
if
(
!
src_node
)
return
NULL
;
reg
=
dss_of_port_get_port_number
(
port
);
list_for_each_entry
(
out
,
&
output_list
,
list
)
{
if
(
out
->
dev
->
of_node
==
node
)
if
(
out
->
dev
->
of_node
==
src_node
&&
out
->
port_num
==
reg
)
{
of_node_put
(
src_node
);
return
omap_dss_get_device
(
out
);
}
}
of_node_put
(
src_node
);
return
NULL
;
}
EXPORT_SYMBOL
(
omap_dss_find_output_by_node
);
EXPORT_SYMBOL
(
omap_dss_find_output_by_
port_
node
);
struct
omap_dss_device
*
omapdss_find_output_from_display
(
struct
omap_dss_device
*
dssdev
)
{
...
...
drivers/video/fbdev/omap2/dss/pll.c
0 → 100644
浏览文件 @
3315764e
/*
* Copyright (C) 2014 Texas Instruments Incorporated
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define DSS_SUBSYS_NAME "PLL"
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/regulator/consumer.h>
#include <linux/sched.h>
#include <video/omapdss.h>
#include "dss.h"
#define PLL_CONTROL 0x0000
#define PLL_STATUS 0x0004
#define PLL_GO 0x0008
#define PLL_CONFIGURATION1 0x000C
#define PLL_CONFIGURATION2 0x0010
#define PLL_CONFIGURATION3 0x0014
#define PLL_SSC_CONFIGURATION1 0x0018
#define PLL_SSC_CONFIGURATION2 0x001C
#define PLL_CONFIGURATION4 0x0020
static
struct
dss_pll
*
dss_plls
[
4
];
int
dss_pll_register
(
struct
dss_pll
*
pll
)
{
int
i
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
dss_plls
);
++
i
)
{
if
(
!
dss_plls
[
i
])
{
dss_plls
[
i
]
=
pll
;
return
0
;
}
}
return
-
EBUSY
;
}
void
dss_pll_unregister
(
struct
dss_pll
*
pll
)
{
int
i
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
dss_plls
);
++
i
)
{
if
(
dss_plls
[
i
]
==
pll
)
{
dss_plls
[
i
]
=
NULL
;
return
;
}
}
}
struct
dss_pll
*
dss_pll_find
(
const
char
*
name
)
{
int
i
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
dss_plls
);
++
i
)
{
if
(
dss_plls
[
i
]
&&
strcmp
(
dss_plls
[
i
]
->
name
,
name
)
==
0
)
return
dss_plls
[
i
];
}
return
NULL
;
}
int
dss_pll_enable
(
struct
dss_pll
*
pll
)
{
int
r
;
r
=
clk_prepare_enable
(
pll
->
clkin
);
if
(
r
)
return
r
;
if
(
pll
->
regulator
)
{
r
=
regulator_enable
(
pll
->
regulator
);
if
(
r
)
goto
err_reg
;
}
r
=
pll
->
ops
->
enable
(
pll
);
if
(
r
)
goto
err_enable
;
return
0
;
err_enable:
regulator_disable
(
pll
->
regulator
);
err_reg:
clk_disable_unprepare
(
pll
->
clkin
);
return
r
;
}
void
dss_pll_disable
(
struct
dss_pll
*
pll
)
{
pll
->
ops
->
disable
(
pll
);
if
(
pll
->
regulator
)
regulator_disable
(
pll
->
regulator
);
clk_disable_unprepare
(
pll
->
clkin
);
memset
(
&
pll
->
cinfo
,
0
,
sizeof
(
pll
->
cinfo
));
}
int
dss_pll_set_config
(
struct
dss_pll
*
pll
,
const
struct
dss_pll_clock_info
*
cinfo
)
{
int
r
;
r
=
pll
->
ops
->
set_config
(
pll
,
cinfo
);
if
(
r
)
return
r
;
pll
->
cinfo
=
*
cinfo
;
return
0
;
}
bool
dss_pll_hsdiv_calc
(
const
struct
dss_pll
*
pll
,
unsigned
long
clkdco
,
unsigned
long
out_min
,
unsigned
long
out_max
,
dss_hsdiv_calc_func
func
,
void
*
data
)
{
const
struct
dss_pll_hw
*
hw
=
pll
->
hw
;
int
m
,
m_start
,
m_stop
;
unsigned
long
out
;
out_min
=
out_min
?
out_min
:
1
;
out_max
=
out_max
?
out_max
:
ULONG_MAX
;
m_start
=
max
(
DIV_ROUND_UP
(
clkdco
,
out_max
),
1ul
);
m_stop
=
min
((
unsigned
)(
clkdco
/
out_min
),
hw
->
mX_max
);
for
(
m
=
m_start
;
m
<=
m_stop
;
++
m
)
{
out
=
clkdco
/
m
;
if
(
func
(
m
,
out
,
data
))
return
true
;
}
return
false
;
}
bool
dss_pll_calc
(
const
struct
dss_pll
*
pll
,
unsigned
long
clkin
,
unsigned
long
pll_min
,
unsigned
long
pll_max
,
dss_pll_calc_func
func
,
void
*
data
)
{
const
struct
dss_pll_hw
*
hw
=
pll
->
hw
;
int
n
,
n_start
,
n_stop
;
int
m
,
m_start
,
m_stop
;
unsigned
long
fint
,
clkdco
;
unsigned
long
pll_hw_max
;
unsigned
long
fint_hw_min
,
fint_hw_max
;
pll_hw_max
=
hw
->
clkdco_max
;
fint_hw_min
=
hw
->
fint_min
;
fint_hw_max
=
hw
->
fint_max
;
n_start
=
max
(
DIV_ROUND_UP
(
clkin
,
fint_hw_max
),
1ul
);
n_stop
=
min
((
unsigned
)(
clkin
/
fint_hw_min
),
hw
->
n_max
);
pll_max
=
pll_max
?
pll_max
:
ULONG_MAX
;
for
(
n
=
n_start
;
n
<=
n_stop
;
++
n
)
{
fint
=
clkin
/
n
;
m_start
=
max
(
DIV_ROUND_UP
(
DIV_ROUND_UP
(
pll_min
,
fint
),
2
),
1ul
);
m_stop
=
min3
((
unsigned
)(
pll_max
/
fint
/
2
),
(
unsigned
)(
pll_hw_max
/
fint
/
2
),
hw
->
m_max
);
for
(
m
=
m_start
;
m
<=
m_stop
;
++
m
)
{
clkdco
=
2
*
m
*
fint
;
if
(
func
(
n
,
m
,
fint
,
clkdco
,
data
))
return
true
;
}
}
return
false
;
}
static
int
wait_for_bit_change
(
void
__iomem
*
reg
,
int
bitnum
,
int
value
)
{
unsigned
long
timeout
;
ktime_t
wait
;
int
t
;
/* first busyloop to see if the bit changes right away */
t
=
100
;
while
(
t
--
>
0
)
{
if
(
FLD_GET
(
readl_relaxed
(
reg
),
bitnum
,
bitnum
)
==
value
)
return
value
;
}
/* then loop for 500ms, sleeping for 1ms in between */
timeout
=
jiffies
+
msecs_to_jiffies
(
500
);
while
(
time_before
(
jiffies
,
timeout
))
{
if
(
FLD_GET
(
readl_relaxed
(
reg
),
bitnum
,
bitnum
)
==
value
)
return
value
;
wait
=
ns_to_ktime
(
1000
*
1000
);
set_current_state
(
TASK_UNINTERRUPTIBLE
);
schedule_hrtimeout
(
&
wait
,
HRTIMER_MODE_REL
);
}
return
!
value
;
}
static
int
dss_wait_hsdiv_ack
(
struct
dss_pll
*
pll
,
u32
hsdiv_ack_mask
)
{
int
t
=
100
;
while
(
t
--
>
0
)
{
u32
v
=
readl_relaxed
(
pll
->
base
+
PLL_STATUS
);
v
&=
hsdiv_ack_mask
;
if
(
v
==
hsdiv_ack_mask
)
return
0
;
}
return
-
ETIMEDOUT
;
}
int
dss_pll_write_config_type_a
(
struct
dss_pll
*
pll
,
const
struct
dss_pll_clock_info
*
cinfo
)
{
const
struct
dss_pll_hw
*
hw
=
pll
->
hw
;
void
__iomem
*
base
=
pll
->
base
;
int
r
=
0
;
u32
l
;
l
=
0
;
if
(
hw
->
has_stopmode
)
l
=
FLD_MOD
(
l
,
1
,
0
,
0
);
/* PLL_STOPMODE */
l
=
FLD_MOD
(
l
,
cinfo
->
n
-
1
,
hw
->
n_msb
,
hw
->
n_lsb
);
/* PLL_REGN */
l
=
FLD_MOD
(
l
,
cinfo
->
m
,
hw
->
m_msb
,
hw
->
m_lsb
);
/* PLL_REGM */
/* M4 */
l
=
FLD_MOD
(
l
,
cinfo
->
mX
[
0
]
?
cinfo
->
mX
[
0
]
-
1
:
0
,
hw
->
mX_msb
[
0
],
hw
->
mX_lsb
[
0
]);
/* M5 */
l
=
FLD_MOD
(
l
,
cinfo
->
mX
[
1
]
?
cinfo
->
mX
[
1
]
-
1
:
0
,
hw
->
mX_msb
[
1
],
hw
->
mX_lsb
[
1
]);
writel_relaxed
(
l
,
base
+
PLL_CONFIGURATION1
);
l
=
0
;
/* M6 */
l
=
FLD_MOD
(
l
,
cinfo
->
mX
[
2
]
?
cinfo
->
mX
[
2
]
-
1
:
0
,
hw
->
mX_msb
[
2
],
hw
->
mX_lsb
[
2
]);
/* M7 */
l
=
FLD_MOD
(
l
,
cinfo
->
mX
[
3
]
?
cinfo
->
mX
[
3
]
-
1
:
0
,
hw
->
mX_msb
[
3
],
hw
->
mX_lsb
[
3
]);
writel_relaxed
(
l
,
base
+
PLL_CONFIGURATION3
);
l
=
readl_relaxed
(
base
+
PLL_CONFIGURATION2
);
if
(
hw
->
has_freqsel
)
{
u32
f
=
cinfo
->
fint
<
1000000
?
0x3
:
cinfo
->
fint
<
1250000
?
0x4
:
cinfo
->
fint
<
1500000
?
0x5
:
cinfo
->
fint
<
1750000
?
0x6
:
0x7
;
l
=
FLD_MOD
(
l
,
f
,
4
,
1
);
/* PLL_FREQSEL */
}
else
if
(
hw
->
has_selfreqdco
)
{
u32
f
=
cinfo
->
clkdco
<
hw
->
clkdco_low
?
0x2
:
0x4
;
l
=
FLD_MOD
(
l
,
f
,
3
,
1
);
/* PLL_SELFREQDCO */
}
l
=
FLD_MOD
(
l
,
1
,
13
,
13
);
/* PLL_REFEN */
l
=
FLD_MOD
(
l
,
0
,
14
,
14
);
/* PHY_CLKINEN */
l
=
FLD_MOD
(
l
,
0
,
16
,
16
);
/* M4_CLOCK_EN */
l
=
FLD_MOD
(
l
,
0
,
18
,
18
);
/* M5_CLOCK_EN */
l
=
FLD_MOD
(
l
,
1
,
20
,
20
);
/* HSDIVBYPASS */
if
(
hw
->
has_refsel
)
l
=
FLD_MOD
(
l
,
3
,
22
,
21
);
/* REFSEL = sysclk */
l
=
FLD_MOD
(
l
,
0
,
23
,
23
);
/* M6_CLOCK_EN */
l
=
FLD_MOD
(
l
,
0
,
25
,
25
);
/* M7_CLOCK_EN */
writel_relaxed
(
l
,
base
+
PLL_CONFIGURATION2
);
writel_relaxed
(
1
,
base
+
PLL_GO
);
/* PLL_GO */
if
(
wait_for_bit_change
(
base
+
PLL_GO
,
0
,
0
)
!=
0
)
{
DSSERR
(
"DSS DPLL GO bit not going down.
\n
"
);
r
=
-
EIO
;
goto
err
;
}
if
(
wait_for_bit_change
(
base
+
PLL_STATUS
,
1
,
1
)
!=
1
)
{
DSSERR
(
"cannot lock DSS DPLL
\n
"
);
r
=
-
EIO
;
goto
err
;
}
l
=
readl_relaxed
(
base
+
PLL_CONFIGURATION2
);
l
=
FLD_MOD
(
l
,
1
,
14
,
14
);
/* PHY_CLKINEN */
l
=
FLD_MOD
(
l
,
cinfo
->
mX
[
0
]
?
1
:
0
,
16
,
16
);
/* M4_CLOCK_EN */
l
=
FLD_MOD
(
l
,
cinfo
->
mX
[
1
]
?
1
:
0
,
18
,
18
);
/* M5_CLOCK_EN */
l
=
FLD_MOD
(
l
,
0
,
20
,
20
);
/* HSDIVBYPASS */
l
=
FLD_MOD
(
l
,
cinfo
->
mX
[
2
]
?
1
:
0
,
23
,
23
);
/* M6_CLOCK_EN */
l
=
FLD_MOD
(
l
,
cinfo
->
mX
[
3
]
?
1
:
0
,
25
,
25
);
/* M7_CLOCK_EN */
writel_relaxed
(
l
,
base
+
PLL_CONFIGURATION2
);
r
=
dss_wait_hsdiv_ack
(
pll
,
(
cinfo
->
mX
[
0
]
?
BIT
(
7
)
:
0
)
|
(
cinfo
->
mX
[
1
]
?
BIT
(
8
)
:
0
)
|
(
cinfo
->
mX
[
2
]
?
BIT
(
10
)
:
0
)
|
(
cinfo
->
mX
[
3
]
?
BIT
(
11
)
:
0
));
if
(
r
)
{
DSSERR
(
"failed to enable HSDIV clocks
\n
"
);
goto
err
;
}
err:
return
r
;
}
int
dss_pll_write_config_type_b
(
struct
dss_pll
*
pll
,
const
struct
dss_pll_clock_info
*
cinfo
)
{
const
struct
dss_pll_hw
*
hw
=
pll
->
hw
;
void
__iomem
*
base
=
pll
->
base
;
u32
l
;
l
=
0
;
l
=
FLD_MOD
(
l
,
cinfo
->
m
,
20
,
9
);
/* PLL_REGM */
l
=
FLD_MOD
(
l
,
cinfo
->
n
-
1
,
8
,
1
);
/* PLL_REGN */
writel_relaxed
(
l
,
base
+
PLL_CONFIGURATION1
);
l
=
readl_relaxed
(
base
+
PLL_CONFIGURATION2
);
l
=
FLD_MOD
(
l
,
0x0
,
12
,
12
);
/* PLL_HIGHFREQ divide by 2 */
l
=
FLD_MOD
(
l
,
0x1
,
13
,
13
);
/* PLL_REFEN */
l
=
FLD_MOD
(
l
,
0x0
,
14
,
14
);
/* PHY_CLKINEN */
if
(
hw
->
has_refsel
)
l
=
FLD_MOD
(
l
,
0x3
,
22
,
21
);
/* REFSEL = SYSCLK */
/* PLL_SELFREQDCO */
if
(
cinfo
->
clkdco
>
hw
->
clkdco_low
)
l
=
FLD_MOD
(
l
,
0x4
,
3
,
1
);
else
l
=
FLD_MOD
(
l
,
0x2
,
3
,
1
);
writel_relaxed
(
l
,
base
+
PLL_CONFIGURATION2
);
l
=
readl_relaxed
(
base
+
PLL_CONFIGURATION3
);
l
=
FLD_MOD
(
l
,
cinfo
->
sd
,
17
,
10
);
/* PLL_REGSD */
writel_relaxed
(
l
,
base
+
PLL_CONFIGURATION3
);
l
=
readl_relaxed
(
base
+
PLL_CONFIGURATION4
);
l
=
FLD_MOD
(
l
,
cinfo
->
mX
[
0
],
24
,
18
);
/* PLL_REGM2 */
l
=
FLD_MOD
(
l
,
cinfo
->
mf
,
17
,
0
);
/* PLL_REGM_F */
writel_relaxed
(
l
,
base
+
PLL_CONFIGURATION4
);
writel_relaxed
(
1
,
base
+
PLL_GO
);
/* PLL_GO */
if
(
wait_for_bit_change
(
base
+
PLL_GO
,
0
,
0
)
!=
0
)
{
DSSERR
(
"DSS DPLL GO bit not going down.
\n
"
);
return
-
EIO
;
}
if
(
wait_for_bit_change
(
base
+
PLL_STATUS
,
1
,
1
)
!=
1
)
{
DSSERR
(
"cannot lock DSS DPLL
\n
"
);
return
-
ETIMEDOUT
;
}
return
0
;
}
drivers/video/fbdev/omap2/dss/sdi.c
浏览文件 @
3315764e
...
...
@@ -425,7 +425,7 @@ int __init sdi_init_port(struct platform_device *pdev, struct device_node *port)
return
r
;
}
void
__exit
sdi_uninit_port
(
void
)
void
__exit
sdi_uninit_port
(
struct
device_node
*
port
)
{
if
(
!
sdi
.
port_initialized
)
return
;
...
...
drivers/video/fbdev/simplefb.c
浏览文件 @
3315764e
...
...
@@ -26,6 +26,8 @@
#include <linux/module.h>
#include <linux/platform_data/simplefb.h>
#include <linux/platform_device.h>
#include <linux/clk-provider.h>
#include <linux/of_platform.h>
static
struct
fb_fix_screeninfo
simplefb_fix
=
{
.
id
=
"simple"
,
...
...
@@ -41,6 +43,8 @@ static struct fb_var_screeninfo simplefb_var = {
.
vmode
=
FB_VMODE_NONINTERLACED
,
};
#define PSEUDO_PALETTE_SIZE 16
static
int
simplefb_setcolreg
(
u_int
regno
,
u_int
red
,
u_int
green
,
u_int
blue
,
u_int
transp
,
struct
fb_info
*
info
)
{
...
...
@@ -50,7 +54,7 @@ static int simplefb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u32
cb
=
blue
>>
(
16
-
info
->
var
.
blue
.
length
);
u32
value
;
if
(
regno
>=
16
)
if
(
regno
>=
PSEUDO_PALETTE_SIZE
)
return
-
EINVAL
;
value
=
(
cr
<<
info
->
var
.
red
.
offset
)
|
...
...
@@ -163,11 +167,113 @@ static int simplefb_parse_pd(struct platform_device *pdev,
return
0
;
}
struct
simplefb_par
{
u32
palette
[
PSEUDO_PALETTE_SIZE
];
#if defined CONFIG_OF && defined CONFIG_COMMON_CLK
int
clk_count
;
struct
clk
**
clks
;
#endif
};
#if defined CONFIG_OF && defined CONFIG_COMMON_CLK
/*
* Clock handling code.
*
* Here we handle the clocks property of our "simple-framebuffer" dt node.
* This is necessary so that we can make sure that any clocks needed by
* the display engine that the bootloader set up for us (and for which it
* provided a simplefb dt node), stay up, for the life of the simplefb
* driver.
*
* When the driver unloads, we cleanly disable, and then release the clocks.
*
* We only complain about errors here, no action is taken as the most likely
* error can only happen due to a mismatch between the bootloader which set
* up simplefb, and the clock definitions in the device tree. Chances are
* that there are no adverse effects, and if there are, a clean teardown of
* the fb probe will not help us much either. So just complain and carry on,
* and hope that the user actually gets a working fb at the end of things.
*/
static
int
simplefb_clocks_init
(
struct
simplefb_par
*
par
,
struct
platform_device
*
pdev
)
{
struct
device_node
*
np
=
pdev
->
dev
.
of_node
;
struct
clk
*
clock
;
int
i
,
ret
;
if
(
dev_get_platdata
(
&
pdev
->
dev
)
||
!
np
)
return
0
;
par
->
clk_count
=
of_clk_get_parent_count
(
np
);
if
(
par
->
clk_count
<=
0
)
return
0
;
par
->
clks
=
kcalloc
(
par
->
clk_count
,
sizeof
(
struct
clk
*
),
GFP_KERNEL
);
if
(
!
par
->
clks
)
return
-
ENOMEM
;
for
(
i
=
0
;
i
<
par
->
clk_count
;
i
++
)
{
clock
=
of_clk_get
(
np
,
i
);
if
(
IS_ERR
(
clock
))
{
if
(
PTR_ERR
(
clock
)
==
-
EPROBE_DEFER
)
{
while
(
--
i
>=
0
)
{
if
(
par
->
clks
[
i
])
clk_put
(
par
->
clks
[
i
]);
}
kfree
(
par
->
clks
);
return
-
EPROBE_DEFER
;
}
dev_err
(
&
pdev
->
dev
,
"%s: clock %d not found: %ld
\n
"
,
__func__
,
i
,
PTR_ERR
(
clock
));
continue
;
}
par
->
clks
[
i
]
=
clock
;
}
for
(
i
=
0
;
i
<
par
->
clk_count
;
i
++
)
{
if
(
par
->
clks
[
i
])
{
ret
=
clk_prepare_enable
(
par
->
clks
[
i
]);
if
(
ret
)
{
dev_err
(
&
pdev
->
dev
,
"%s: failed to enable clock %d: %d
\n
"
,
__func__
,
i
,
ret
);
clk_put
(
par
->
clks
[
i
]);
par
->
clks
[
i
]
=
NULL
;
}
}
}
return
0
;
}
static
void
simplefb_clocks_destroy
(
struct
simplefb_par
*
par
)
{
int
i
;
if
(
!
par
->
clks
)
return
;
for
(
i
=
0
;
i
<
par
->
clk_count
;
i
++
)
{
if
(
par
->
clks
[
i
])
{
clk_disable_unprepare
(
par
->
clks
[
i
]);
clk_put
(
par
->
clks
[
i
]);
}
}
kfree
(
par
->
clks
);
}
#else
static
int
simplefb_clocks_init
(
struct
simplefb_par
*
par
,
struct
platform_device
*
pdev
)
{
return
0
;
}
static
void
simplefb_clocks_destroy
(
struct
simplefb_par
*
par
)
{
}
#endif
static
int
simplefb_probe
(
struct
platform_device
*
pdev
)
{
int
ret
;
struct
simplefb_params
params
;
struct
fb_info
*
info
;
struct
simplefb_par
*
par
;
struct
resource
*
mem
;
if
(
fb_get_options
(
"simplefb"
,
NULL
))
...
...
@@ -188,11 +294,13 @@ static int simplefb_probe(struct platform_device *pdev)
return
-
EINVAL
;
}
info
=
framebuffer_alloc
(
sizeof
(
u32
)
*
16
,
&
pdev
->
dev
);
info
=
framebuffer_alloc
(
sizeof
(
struct
simplefb_par
)
,
&
pdev
->
dev
);
if
(
!
info
)
return
-
ENOMEM
;
platform_set_drvdata
(
pdev
,
info
);
par
=
info
->
par
;
info
->
fix
=
simplefb_fix
;
info
->
fix
.
smem_start
=
mem
->
start
;
info
->
fix
.
smem_len
=
resource_size
(
mem
);
...
...
@@ -211,8 +319,8 @@ static int simplefb_probe(struct platform_device *pdev)
info
->
apertures
=
alloc_apertures
(
1
);
if
(
!
info
->
apertures
)
{
framebuffer_release
(
info
)
;
return
-
ENOMEM
;
ret
=
-
ENOMEM
;
goto
error_fb_release
;
}
info
->
apertures
->
ranges
[
0
].
base
=
info
->
fix
.
smem_start
;
info
->
apertures
->
ranges
[
0
].
size
=
info
->
fix
.
smem_len
;
...
...
@@ -222,10 +330,14 @@ static int simplefb_probe(struct platform_device *pdev)
info
->
screen_base
=
ioremap_wc
(
info
->
fix
.
smem_start
,
info
->
fix
.
smem_len
);
if
(
!
info
->
screen_base
)
{
framebuffer_release
(
info
)
;
return
-
ENODEV
;
ret
=
-
ENOMEM
;
goto
error_fb_release
;
}
info
->
pseudo_palette
=
(
void
*
)(
info
+
1
);
info
->
pseudo_palette
=
par
->
palette
;
ret
=
simplefb_clocks_init
(
par
,
pdev
);
if
(
ret
<
0
)
goto
error_unmap
;
dev_info
(
&
pdev
->
dev
,
"framebuffer at 0x%lx, 0x%x bytes, mapped to 0x%p
\n
"
,
info
->
fix
.
smem_start
,
info
->
fix
.
smem_len
,
...
...
@@ -238,21 +350,29 @@ static int simplefb_probe(struct platform_device *pdev)
ret
=
register_framebuffer
(
info
);
if
(
ret
<
0
)
{
dev_err
(
&
pdev
->
dev
,
"Unable to register simplefb: %d
\n
"
,
ret
);
iounmap
(
info
->
screen_base
);
framebuffer_release
(
info
);
return
ret
;
goto
error_clocks
;
}
dev_info
(
&
pdev
->
dev
,
"fb%d: simplefb registered!
\n
"
,
info
->
node
);
return
0
;
error_clocks:
simplefb_clocks_destroy
(
par
);
error_unmap:
iounmap
(
info
->
screen_base
);
error_fb_release:
framebuffer_release
(
info
);
return
ret
;
}
static
int
simplefb_remove
(
struct
platform_device
*
pdev
)
{
struct
fb_info
*
info
=
platform_get_drvdata
(
pdev
);
struct
simplefb_par
*
par
=
info
->
par
;
unregister_framebuffer
(
info
);
simplefb_clocks_destroy
(
par
);
framebuffer_release
(
info
);
return
0
;
...
...
@@ -273,7 +393,27 @@ static struct platform_driver simplefb_driver = {
.
probe
=
simplefb_probe
,
.
remove
=
simplefb_remove
,
};
module_platform_driver
(
simplefb_driver
);
static
int
__init
simplefb_init
(
void
)
{
int
ret
;
struct
device_node
*
np
;
ret
=
platform_driver_register
(
&
simplefb_driver
);
if
(
ret
)
return
ret
;
if
(
IS_ENABLED
(
CONFIG_OF
)
&&
of_chosen
)
{
for_each_child_of_node
(
of_chosen
,
np
)
{
if
(
of_device_is_compatible
(
np
,
"simple-framebuffer"
))
of_platform_device_create
(
np
,
NULL
,
NULL
);
}
}
return
0
;
}
fs_initcall
(
simplefb_init
);
MODULE_AUTHOR
(
"Stephen Warren <swarren@wwwdotorg.org>"
);
MODULE_DESCRIPTION
(
"Simple framebuffer driver"
);
...
...
include/linux/of.h
浏览文件 @
3315764e
...
...
@@ -105,8 +105,6 @@ static inline struct device_node *of_node_get(struct device_node *node)
static
inline
void
of_node_put
(
struct
device_node
*
node
)
{
}
#endif
/* !CONFIG_OF_DYNAMIC */
#ifdef CONFIG_OF
/* Pointer for first entry in chain of all nodes. */
extern
struct
device_node
*
of_allnodes
;
extern
struct
device_node
*
of_chosen
;
...
...
@@ -114,6 +112,7 @@ extern struct device_node *of_aliases;
extern
struct
device_node
*
of_stdout
;
extern
raw_spinlock_t
devtree_lock
;
#ifdef CONFIG_OF
static
inline
bool
of_have_populated_dt
(
void
)
{
return
of_allnodes
!=
NULL
;
...
...
sound/soc/omap/omap-hdmi
.h
→
include/sound/omap-hdmi-audio
.h
浏览文件 @
3315764e
/*
*
omap-hdmi.h
*
hdmi-audio.c -- OMAP4+ DSS HDMI audio support library
*
* Definitions for OMAP ALSA SoC DAI driver for HDMI audio on OMAP4 processors.
* Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
* Authors: Jorge Candelaria <jorge.candelaria@ti.com>
* Ricardo Neri <ricardo.neri@ti.com>
* Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com
*
* Author: Jyri Sarha <jsarha@ti.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
...
...
@@ -15,24 +14,30 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#ifndef __OMAP_HDMI_H__
#define __OMAP_HDMI_H__
#include <video/omapdss.h>
#ifndef __OMAP_HDMI_AUDIO_H__
#define __OMAP_HDMI_AUDIO_H__
#define OMAP_HDMI_AUDIO_DMA_PORT 0x8c
struct
omap_hdmi_audio_ops
{
int
(
*
audio_startup
)(
struct
device
*
dev
,
void
(
*
abort_cb
)(
struct
device
*
dev
));
int
(
*
audio_shutdown
)(
struct
device
*
dev
);
int
(
*
audio_start
)(
struct
device
*
dev
);
void
(
*
audio_stop
)(
struct
device
*
dev
);
int
(
*
audio_config
)(
struct
device
*
dev
,
struct
omap_dss_audio
*
dss_audio
);
};
#define OMAP_HDMI_RATES (SNDRV_PCM_RATE_32000 | \
SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | \
SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | \
SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000)
/* HDMI audio initalization data */
struct
omap_hdmi_audio_pdata
{
struct
device
*
dev
;
enum
omapdss_version
dss_version
;
phys_addr_t
audio_dma_addr
;
#define OMAP_HDMI_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
SNDRV_PCM_FMTBIT_S24_LE)
const
struct
omap_hdmi_audio_ops
*
ops
;
};
#endif
#endif
/* __OMAP_HDMI_AUDIO_H__ */
include/video/omapdss.h
浏览文件 @
3315764e
...
...
@@ -166,13 +166,6 @@ enum omap_dss_display_state {
OMAP_DSS_DISPLAY_ACTIVE
,
};
enum
omap_dss_audio_state
{
OMAP_DSS_AUDIO_DISABLED
=
0
,
OMAP_DSS_AUDIO_ENABLED
,
OMAP_DSS_AUDIO_CONFIGURED
,
OMAP_DSS_AUDIO_PLAYING
,
};
struct
omap_dss_audio
{
struct
snd_aes_iec958
*
iec
;
struct
snd_cea_861_aud_if
*
cea
;
...
...
@@ -635,19 +628,6 @@ struct omapdss_hdmi_ops {
int
(
*
set_hdmi_mode
)(
struct
omap_dss_device
*
dssdev
,
bool
hdmi_mode
);
int
(
*
set_infoframe
)(
struct
omap_dss_device
*
dssdev
,
const
struct
hdmi_avi_infoframe
*
avi
);
/*
* 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
);
};
struct
omapdss_dsi_ops
{
...
...
@@ -783,8 +763,6 @@ struct omap_dss_device {
enum
omap_dss_display_state
state
;
enum
omap_dss_audio_state
audio_state
;
/* OMAP DSS output specific fields */
struct
list_head
list
;
...
...
@@ -795,6 +773,9 @@ struct omap_dss_device {
/* output instance */
enum
omap_dss_output_id
id
;
/* the port number in the DT node */
int
port_num
;
/* dynamic fields */
struct
omap_overlay_manager
*
manager
;
...
...
@@ -858,24 +839,6 @@ struct omap_dss_driver {
int
(
*
set_hdmi_mode
)(
struct
omap_dss_device
*
dssdev
,
bool
hdmi_mode
);
int
(
*
set_hdmi_infoframe
)(
struct
omap_dss_device
*
dssdev
,
const
struct
hdmi_avi_infoframe
*
avi
);
/*
* 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
);
};
enum
omapdss_version
omapdss_get_version
(
void
);
...
...
@@ -918,7 +881,7 @@ int omapdss_register_output(struct omap_dss_device *output);
void
omapdss_unregister_output
(
struct
omap_dss_device
*
output
);
struct
omap_dss_device
*
omap_dss_get_output
(
enum
omap_dss_output_id
id
);
struct
omap_dss_device
*
omap_dss_find_output
(
const
char
*
name
);
struct
omap_dss_device
*
omap_dss_find_output_by_
node
(
struct
device_node
*
node
);
struct
omap_dss_device
*
omap_dss_find_output_by_
port_node
(
struct
device_node
*
port
);
int
omapdss_output_set_device
(
struct
omap_dss_device
*
out
,
struct
omap_dss_device
*
dssdev
);
int
omapdss_output_unset_device
(
struct
omap_dss_device
*
out
);
...
...
sound/soc/omap/Kconfig
浏览文件 @
3315764e
...
...
@@ -12,8 +12,20 @@ config SND_OMAP_SOC_MCBSP
config SND_OMAP_SOC_MCPDM
tristate
config SND_OMAP_SOC_HDMI
tristate
config SND_OMAP_SOC_HDMI_AUDIO
tristate "HDMI audio support for OMAP4+ based SoCs"
depends on SND_OMAP_SOC
help
For HDMI audio to work OMAPDSS HDMI support should be
enabled.
The hdmi audio driver implements cpu-dai component using the
callbacks provided by OMAPDSS and registers the component
under DSS HDMI device. Omap-pcm is registered for platform
component also under DSS HDMI device. Dummy codec is used as
as codec component. The hdmi audio driver implements also
the card and registers it under its own platform device.
The device for the dirver is registered by OMAPDSS hdmi
driver.
config SND_OMAP_SOC_N810
tristate "SoC Audio support for Nokia N810"
...
...
@@ -100,16 +112,6 @@ config SND_OMAP_SOC_OMAP_ABE_TWL6040
- PandaBoard (4430)
- PandaBoardES (4460)
config SND_OMAP_SOC_OMAP_HDMI
tristate "SoC Audio support for Texas Instruments OMAP HDMI"
depends on SND_OMAP_SOC && OMAP4_DSS_HDMI && OMAP2_DSS
select SND_OMAP_SOC_HDMI
select SND_SOC_HDMI_CODEC
select OMAP4_DSS_HDMI_AUDIO
help
Say Y if you want to add support for SoC HDMI audio on Texas Instruments
OMAP4 chips
config SND_OMAP_SOC_OMAP3_PANDORA
tristate "SoC Audio support for OMAP3 Pandora"
depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP3_PANDORA
...
...
sound/soc/omap/Makefile
浏览文件 @
3315764e
...
...
@@ -3,13 +3,13 @@ snd-soc-omap-objs := omap-pcm.o
snd-soc-omap-dmic-objs
:=
omap-dmic.o
snd-soc-omap-mcbsp-objs
:=
omap-mcbsp.o mcbsp.o
snd-soc-omap-mcpdm-objs
:=
omap-mcpdm.o
snd-soc-omap-hdmi-
objs
:=
omap-hdmi
.o
snd-soc-omap-hdmi-
audio-objs
:=
omap-hdmi-audio
.o
obj-$(CONFIG_SND_OMAP_SOC)
+=
snd-soc-omap.o
obj-$(CONFIG_SND_OMAP_SOC_DMIC)
+=
snd-soc-omap-dmic.o
obj-$(CONFIG_SND_OMAP_SOC_MCBSP)
+=
snd-soc-omap-mcbsp.o
obj-$(CONFIG_SND_OMAP_SOC_MCPDM)
+=
snd-soc-omap-mcpdm.o
obj-$(CONFIG_SND_OMAP_SOC_HDMI
)
+=
snd-soc-omap-hdmi
.o
obj-$(CONFIG_SND_OMAP_SOC_HDMI
_AUDIO)
+=
snd-soc-omap-hdmi-audio
.o
# OMAP Machine Support
snd-soc-n810-objs
:=
n810.o
...
...
@@ -20,7 +20,6 @@ snd-soc-am3517evm-objs := am3517evm.o
snd-soc-omap-abe-twl6040-objs
:=
omap-abe-twl6040.o
snd-soc-omap-twl4030-objs
:=
omap-twl4030.o
snd-soc-omap3pandora-objs
:=
omap3pandora.o
snd-soc-omap-hdmi-card-objs
:=
omap-hdmi-card.o
obj-$(CONFIG_SND_OMAP_SOC_N810)
+=
snd-soc-n810.o
obj-$(CONFIG_SND_OMAP_SOC_RX51)
+=
snd-soc-rx51.o
...
...
@@ -30,4 +29,3 @@ obj-$(CONFIG_SND_OMAP_SOC_AM3517EVM) += snd-soc-am3517evm.o
obj-$(CONFIG_SND_OMAP_SOC_OMAP_ABE_TWL6040)
+=
snd-soc-omap-abe-twl6040.o
obj-$(CONFIG_SND_OMAP_SOC_OMAP_TWL4030)
+=
snd-soc-omap-twl4030.o
obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA)
+=
snd-soc-omap3pandora.o
obj-$(CONFIG_SND_OMAP_SOC_OMAP_HDMI)
+=
snd-soc-omap-hdmi-card.o
sound/soc/omap/omap-hdmi.c
→
sound/soc/omap/omap-hdmi
-audio
.c
浏览文件 @
3315764e
/*
* omap-hdmi
.c
* omap-hdmi
-audio.c -- OMAP4+ DSS HDMI audio support library
*
* OMAP ALSA SoC DAI driver for HDMI audio on OMAP4 processors.
* Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
* Authors: Jorge Candelaria <jorge.candelaria@ti.com>
* Ricardo Neri <ricardo.neri@ti.com>
* Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com
*
* Author: Jyri Sarha <jsarha@ti.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
...
...
@@ -15,95 +14,118 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#include <linux/
init
.h>
#include <linux/
kernel
.h>
#include <linux/module.h>
#include <linux/device.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/initval.h>
#include <linux/err.h>
#include <linux/string.h>
#include <linux/platform_device.h>
#include <sound/soc.h>
#include <sound/asound.h>
#include <sound/asoundef.h>
#include <sound/pcm_params.h>
#include <sound/dmaengine_pcm.h>
#include <video/omapdss.h>
#include <uapi/sound/asound.h>
#include <sound/asoundef.h>
#include <sound/omap-pcm.h>
#include <sound/omap-hdmi-audio.h>
#include <video/omapdss.h>
#
include "omap-hdmi.h
"
#
define DRV_NAME "omap-hdmi-audio
"
#define DRV_NAME "omap-hdmi-audio-dai"
struct
hdmi_audio_data
{
struct
snd_soc_card
*
card
;
struct
hdmi_priv
{
const
struct
omap_hdmi_audio_ops
*
ops
;
struct
device
*
dssdev
;
struct
snd_dmaengine_dai_dma_data
dma_data
;
unsigned
int
dma_req
;
struct
omap_dss_audio
dss_audio
;
struct
snd_aes_iec958
iec
;
struct
snd_cea_861_aud_if
cea
;
struct
omap_dss_device
*
dssdev
;
struct
mutex
current_stream_lock
;
struct
snd_pcm_substream
*
current_stream
;
};
static
int
omap_hdmi_dai_startup
(
struct
snd_pcm_substream
*
substream
,
static
struct
hdmi_audio_data
*
card_drvdata_substream
(
struct
snd_pcm_substream
*
ss
)
{
struct
snd_soc_pcm_runtime
*
rtd
=
ss
->
private_data
;
return
snd_soc_card_get_drvdata
(
rtd
->
card
);
}
static
void
hdmi_dai_abort
(
struct
device
*
dev
)
{
struct
hdmi_audio_data
*
ad
=
dev_get_drvdata
(
dev
);
mutex_lock
(
&
ad
->
current_stream_lock
);
if
(
ad
->
current_stream
&&
ad
->
current_stream
->
runtime
&&
snd_pcm_running
(
ad
->
current_stream
))
{
dev_err
(
dev
,
"HDMI display disabled, aborting playback
\n
"
);
snd_pcm_stream_lock_irq
(
ad
->
current_stream
);
snd_pcm_stop
(
ad
->
current_stream
,
SNDRV_PCM_STATE_DISCONNECTED
);
snd_pcm_stream_unlock_irq
(
ad
->
current_stream
);
}
mutex_unlock
(
&
ad
->
current_stream_lock
);
}
static
int
hdmi_dai_startup
(
struct
snd_pcm_substream
*
substream
,
struct
snd_soc_dai
*
dai
)
{
struct
hdmi_
priv
*
priv
=
snd_soc_dai_get_drvdata
(
dai
);
int
err
;
struct
hdmi_
audio_data
*
ad
=
card_drvdata_substream
(
substream
);
int
ret
;
/*
* Make sure that the period bytes are multiple of the DMA packet size.
* Largest packet size we use is 32 32-bit words = 128 bytes
*/
err
=
snd_pcm_hw_constraint_step
(
substream
->
runtime
,
0
,
ret
=
snd_pcm_hw_constraint_step
(
substream
->
runtime
,
0
,
SNDRV_PCM_HW_PARAM_PERIOD_BYTES
,
128
);
if
(
err
<
0
)
{
if
(
ret
<
0
)
{
dev_err
(
dai
->
dev
,
"could not apply constraint
\n
"
);
return
err
;
return
ret
;
}
if
(
!
priv
->
dssdev
->
driver
->
audio_supported
(
priv
->
dssdev
))
{
dev_err
(
dai
->
dev
,
"audio not supported
\n
"
);
return
-
ENODEV
;
}
snd_soc_dai_set_dma_data
(
dai
,
substream
,
&
ad
->
dma_data
);
snd_soc_dai_set_dma_data
(
dai
,
substream
,
&
priv
->
dma_data
);
mutex_lock
(
&
ad
->
current_stream_lock
);
ad
->
current_stream
=
substream
;
mutex_unlock
(
&
ad
->
current_stream_lock
);
return
0
;
}
ret
=
ad
->
ops
->
audio_startup
(
ad
->
dssdev
,
hdmi_dai_abort
);
static
int
omap_hdmi_dai_prepare
(
struct
snd_pcm_substream
*
substream
,
struct
snd_soc_dai
*
dai
)
{
struct
hdmi_priv
*
priv
=
snd_soc_dai_get_drvdata
(
dai
);
if
(
ret
)
{
mutex_lock
(
&
ad
->
current_stream_lock
);
ad
->
current_stream
=
NULL
;
mutex_unlock
(
&
ad
->
current_stream_lock
);
}
return
priv
->
dssdev
->
driver
->
audio_enable
(
priv
->
dssdev
)
;
return
ret
;
}
static
int
omap_
hdmi_dai_hw_params
(
struct
snd_pcm_substream
*
substream
,
static
int
hdmi_dai_hw_params
(
struct
snd_pcm_substream
*
substream
,
struct
snd_pcm_hw_params
*
params
,
struct
snd_soc_dai
*
dai
)
{
struct
hdmi_priv
*
priv
=
snd_soc_dai_get_drvdata
(
dai
);
struct
snd_aes_iec958
*
iec
=
&
priv
->
iec
;
struct
snd_cea_861_aud_if
*
cea
=
&
priv
->
cea
;
int
err
=
0
;
struct
hdmi_audio_data
*
ad
=
card_drvdata_substream
(
substream
);
struct
snd_aes_iec958
*
iec
=
&
ad
->
iec
;
struct
snd_cea_861_aud_if
*
cea
=
&
ad
->
cea
;
WARN_ON
(
ad
->
current_stream
!=
substream
);
switch
(
params_format
(
params
))
{
case
SNDRV_PCM_FORMAT_S16_LE
:
priv
->
dma_data
.
maxburst
=
16
;
ad
->
dma_data
.
maxburst
=
16
;
break
;
case
SNDRV_PCM_FORMAT_S24_LE
:
priv
->
dma_data
.
maxburst
=
32
;
ad
->
dma_data
.
maxburst
=
32
;
break
;
default:
dev_err
(
dai
->
dev
,
"format not supported!
\n
"
);
return
-
EINVAL
;
}
ad
->
dss_audio
.
iec
=
iec
;
ad
->
dss_audio
.
cea
=
cea
;
/*
* fill the IEC-60958 channel status word
*/
...
...
@@ -203,31 +225,27 @@ static int omap_hdmi_dai_hw_params(struct snd_pcm_substream *substream,
/* the expression is trivial but makes clear what we are doing */
cea
->
db5_dminh_lsv
|=
(
0
&
CEA861_AUDIO_INFOFRAME_DB5_LSV
);
priv
->
dss_audio
.
iec
=
iec
;
priv
->
dss_audio
.
cea
=
cea
;
err
=
priv
->
dssdev
->
driver
->
audio_config
(
priv
->
dssdev
,
&
priv
->
dss_audio
);
return
err
;
return
ad
->
ops
->
audio_config
(
ad
->
dssdev
,
&
ad
->
dss_audio
);
}
static
int
omap_
hdmi_dai_trigger
(
struct
snd_pcm_substream
*
substream
,
int
cmd
,
static
int
hdmi_dai_trigger
(
struct
snd_pcm_substream
*
substream
,
int
cmd
,
struct
snd_soc_dai
*
dai
)
{
struct
hdmi_
priv
*
priv
=
snd_soc_dai_get_drvdata
(
dai
);
struct
hdmi_
audio_data
*
ad
=
card_drvdata_substream
(
substream
);
int
err
=
0
;
WARN_ON
(
ad
->
current_stream
!=
substream
);
switch
(
cmd
)
{
case
SNDRV_PCM_TRIGGER_START
:
case
SNDRV_PCM_TRIGGER_RESUME
:
case
SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
err
=
priv
->
dssdev
->
driver
->
audio_start
(
priv
->
dssdev
);
err
=
ad
->
ops
->
audio_start
(
ad
->
dssdev
);
break
;
case
SNDRV_PCM_TRIGGER_STOP
:
case
SNDRV_PCM_TRIGGER_SUSPEND
:
case
SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
priv
->
dssdev
->
driver
->
audio_stop
(
priv
->
dssdev
);
ad
->
ops
->
audio_stop
(
ad
->
dssdev
);
break
;
default:
err
=
-
EINVAL
;
...
...
@@ -235,130 +253,155 @@ static int omap_hdmi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
return
err
;
}
static
void
omap_
hdmi_dai_shutdown
(
struct
snd_pcm_substream
*
substream
,
static
void
hdmi_dai_shutdown
(
struct
snd_pcm_substream
*
substream
,
struct
snd_soc_dai
*
dai
)
{
struct
hdmi_
priv
*
priv
=
snd_soc_dai_get_drvdata
(
dai
);
struct
hdmi_
audio_data
*
ad
=
card_drvdata_substream
(
substream
);
priv
->
dssdev
->
driver
->
audio_disable
(
priv
->
dssdev
);
WARN_ON
(
ad
->
current_stream
!=
substream
);
ad
->
ops
->
audio_shutdown
(
ad
->
dssdev
);
mutex_lock
(
&
ad
->
current_stream_lock
);
ad
->
current_stream
=
NULL
;
mutex_unlock
(
&
ad
->
current_stream_lock
);
}
static
const
struct
snd_soc_dai_ops
omap_hdmi_dai_ops
=
{
.
startup
=
omap_hdmi_dai_startup
,
.
hw_params
=
omap_hdmi_dai_hw_params
,
.
prepare
=
omap_hdmi_dai_prepare
,
.
trigger
=
omap_hdmi_dai_trigger
,
.
shutdown
=
omap_hdmi_dai_shutdown
,
static
const
struct
snd_soc_dai_ops
hdmi_dai_ops
=
{
.
startup
=
hdmi_dai_startup
,
.
hw_params
=
hdmi_dai_hw_params
,
.
trigger
=
hdmi_dai_trigger
,
.
shutdown
=
hdmi_dai_shutdown
,
};
static
const
struct
snd_soc_component_driver
omap_hdmi_component
=
{
.
name
=
"omapdss_hdmi"
,
};
static
struct
snd_soc_dai_driver
omap_hdmi_dai
=
{
static
struct
snd_soc_dai_driver
omap5_hdmi_dai
=
{
.
name
=
"omap5-hdmi-dai"
,
.
playback
=
{
.
channels_min
=
2
,
.
channels_max
=
8
,
.
rates
=
OMAP_HDMI_RATES
,
.
formats
=
OMAP_HDMI_FORMATS
,
.
rates
=
(
SNDRV_PCM_RATE_32000
|
SNDRV_PCM_RATE_44100
|
SNDRV_PCM_RATE_48000
|
SNDRV_PCM_RATE_88200
|
SNDRV_PCM_RATE_96000
|
SNDRV_PCM_RATE_176400
|
SNDRV_PCM_RATE_192000
),
.
formats
=
SNDRV_PCM_FMTBIT_S16_LE
,
},
.
ops
=
&
omap_
hdmi_dai_ops
,
.
ops
=
&
hdmi_dai_ops
,
};
static
const
struct
snd_soc_component_driver
omap_hdmi_component
=
{
.
name
=
DRV_NAME
,
static
struct
snd_soc_dai_driver
omap4_hdmi_dai
=
{
.
name
=
"omap4-hdmi-dai"
,
.
playback
=
{
.
channels_min
=
2
,
.
channels_max
=
8
,
.
rates
=
(
SNDRV_PCM_RATE_32000
|
SNDRV_PCM_RATE_44100
|
SNDRV_PCM_RATE_48000
|
SNDRV_PCM_RATE_88200
|
SNDRV_PCM_RATE_96000
|
SNDRV_PCM_RATE_176400
|
SNDRV_PCM_RATE_192000
),
.
formats
=
SNDRV_PCM_FMTBIT_S16_LE
|
SNDRV_PCM_FMTBIT_S24_LE
,
},
.
ops
=
&
hdmi_dai_ops
,
};
static
int
omap_hdmi_probe
(
struct
platform_device
*
pdev
)
static
int
omap_hdmi_
audio_
probe
(
struct
platform_device
*
pdev
)
{
struct
omap_hdmi_audio_pdata
*
ha
=
pdev
->
dev
.
platform_data
;
struct
device
*
dev
=
&
pdev
->
dev
;
struct
hdmi_audio_data
*
ad
;
struct
snd_soc_dai_driver
*
dai_drv
;
struct
snd_soc_card
*
card
;
int
ret
;
struct
resource
*
hdmi_rsrc
;
struct
hdmi_priv
*
hdmi_data
;
bool
hdmi_dev_found
=
false
;
hdmi_data
=
devm_kzalloc
(
&
pdev
->
dev
,
sizeof
(
*
hdmi_data
),
GFP_KERNEL
);
if
(
hdmi_data
==
NULL
)
{
dev_err
(
&
pdev
->
dev
,
"Cannot allocate memory for HDMI data
\n
"
);
return
-
ENOMEM
;
}
hdmi_rsrc
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
0
);
if
(
!
hdmi_rsrc
)
{
dev_err
(
&
pdev
->
dev
,
"Cannot obtain IORESOURCE_MEM HDMI
\n
"
);
return
-
ENODEV
;
}
hdmi_data
->
dma_data
.
addr
=
hdmi_rsrc
->
start
+
OMAP_HDMI_AUDIO_DMA_PORT
;
hdmi_rsrc
=
platform_get_resource
(
pdev
,
IORESOURCE_DMA
,
0
);
if
(
!
hdmi_rsrc
)
{
dev_err
(
&
pdev
->
dev
,
"Cannot obtain IORESOURCE_DMA HDMI
\n
"
);
return
-
ENODEV
;
}
hdmi_data
->
dma_req
=
hdmi_rsrc
->
start
;
hdmi_data
->
dma_data
.
filter_data
=
&
hdmi_data
->
dma_req
;
hdmi_data
->
dma_data
.
addr_width
=
DMA_SLAVE_BUSWIDTH_4_BYTES
;
/*
* TODO: We assume that there is only one DSS HDMI device. Future
* OMAP implementations may support more than one HDMI devices and
* we should provided separate audio support for all of them.
*/
/* Find an HDMI device. */
for_each_dss_dev
(
hdmi_data
->
dssdev
)
{
omap_dss_get_device
(
hdmi_data
->
dssdev
);
if
(
!
hdmi_data
->
dssdev
->
driver
)
{
omap_dss_put_device
(
hdmi_data
->
dssdev
);
continue
;
if
(
!
ha
)
{
dev_err
(
dev
,
"No platform data
\n
"
);
return
-
EINVAL
;
}
if
(
hdmi_data
->
dssdev
->
type
==
OMAP_DISPLAY_TYPE_HDMI
)
{
hdmi_dev_found
=
true
;
ad
=
devm_kzalloc
(
dev
,
sizeof
(
*
ad
),
GFP_KERNEL
);
if
(
!
ad
)
return
-
ENOMEM
;
ad
->
dssdev
=
ha
->
dev
;
ad
->
ops
=
ha
->
ops
;
ad
->
dma_data
.
addr
=
ha
->
audio_dma_addr
;
ad
->
dma_data
.
filter_data
=
"audio_tx"
;
ad
->
dma_data
.
addr_width
=
DMA_SLAVE_BUSWIDTH_4_BYTES
;
mutex_init
(
&
ad
->
current_stream_lock
);
switch
(
ha
->
dss_version
)
{
case
OMAPDSS_VER_OMAP4430_ES1
:
case
OMAPDSS_VER_OMAP4430_ES2
:
case
OMAPDSS_VER_OMAP4
:
dai_drv
=
&
omap4_hdmi_dai
;
break
;
case
OMAPDSS_VER_OMAP5
:
dai_drv
=
&
omap5_hdmi_dai
;
break
;
default:
return
-
EINVAL
;
}
}
ret
=
snd_soc_register_component
(
ad
->
dssdev
,
&
omap_hdmi_component
,
dai_drv
,
1
);
if
(
ret
)
return
ret
;
ret
=
omap_pcm_platform_register
(
ad
->
dssdev
);
if
(
ret
)
return
ret
;
if
(
!
hdmi_dev_found
)
{
dev_err
(
&
pdev
->
dev
,
"no driver for HDMI display found
\n
"
);
return
-
ENODEV
;
card
=
devm_kzalloc
(
dev
,
sizeof
(
*
card
),
GFP_KERNEL
);
card
->
name
=
devm_kasprintf
(
dev
,
GFP_KERNEL
,
"HDMI %s"
,
dev_name
(
ad
->
dssdev
));
card
->
owner
=
THIS_MODULE
;
card
->
dai_link
=
devm_kzalloc
(
dev
,
sizeof
(
*
(
card
->
dai_link
)),
GFP_KERNEL
);
card
->
dai_link
->
name
=
card
->
name
;
card
->
dai_link
->
stream_name
=
card
->
name
;
card
->
dai_link
->
cpu_dai_name
=
dev_name
(
ad
->
dssdev
);
card
->
dai_link
->
platform_name
=
dev_name
(
ad
->
dssdev
);
card
->
dai_link
->
codec_name
=
"snd-soc-dummy"
;
card
->
dai_link
->
codec_dai_name
=
"snd-soc-dummy-dai"
;
card
->
num_links
=
1
;
card
->
dev
=
dev
;
ret
=
snd_soc_register_card
(
card
);
if
(
ret
)
{
dev_err
(
dev
,
"snd_soc_register_card failed (%d)
\n
"
,
ret
);
snd_soc_unregister_component
(
ad
->
dssdev
);
return
ret
;
}
dev_set_drvdata
(
&
pdev
->
dev
,
hdmi_data
);
ret
=
snd_soc_register_component
(
&
pdev
->
dev
,
&
omap_hdmi_component
,
&
omap_hdmi_dai
,
1
);
ad
->
card
=
card
;
snd_soc_card_set_drvdata
(
card
,
ad
);
if
(
ret
)
return
ret
;
dev_set_drvdata
(
dev
,
ad
);
return
omap_pcm_platform_register
(
&
pdev
->
dev
)
;
return
0
;
}
static
int
omap_hdmi_remove
(
struct
platform_device
*
pdev
)
static
int
omap_hdmi_
audio_
remove
(
struct
platform_device
*
pdev
)
{
struct
hdmi_priv
*
hdmi_data
=
dev_get_drvdata
(
&
pdev
->
dev
);
snd_soc_unregister_component
(
&
pdev
->
dev
);
if
(
hdmi_data
==
NULL
)
{
dev_err
(
&
pdev
->
dev
,
"cannot obtain HDMi data
\n
"
);
return
-
ENODEV
;
}
struct
hdmi_audio_data
*
ad
=
platform_get_drvdata
(
pdev
);
omap_dss_put_device
(
hdmi_data
->
dssdev
);
snd_soc_unregister_card
(
ad
->
card
);
snd_soc_unregister_component
(
ad
->
dssdev
);
return
0
;
}
static
struct
platform_driver
hdmi_
dai
_driver
=
{
static
struct
platform_driver
hdmi_
audio
_driver
=
{
.
driver
=
{
.
name
=
DRV_NAME
,
.
owner
=
THIS_MODULE
,
},
.
probe
=
omap_hdmi_probe
,
.
remove
=
omap_hdmi_remove
,
.
probe
=
omap_hdmi_
audio_
probe
,
.
remove
=
omap_hdmi_
audio_
remove
,
};
module_platform_driver
(
hdmi_
dai
_driver
);
module_platform_driver
(
hdmi_
audio
_driver
);
MODULE_AUTHOR
(
"Jorge Candelaria <jorge.candelaria@ti.com>"
);
MODULE_AUTHOR
(
"Ricardo Neri <ricardo.neri@ti.com>"
);
MODULE_DESCRIPTION
(
"OMAP HDMI SoC Interface"
);
MODULE_AUTHOR
(
"Jyri Sarha <jsarha@ti.com>"
);
MODULE_DESCRIPTION
(
"OMAP HDMI Audio Driver"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_ALIAS
(
"platform:"
DRV_NAME
);
sound/soc/omap/omap-hdmi-card.c
已删除
100644 → 0
浏览文件 @
34685627
/*
* omap-hdmi-card.c
*
* OMAP ALSA SoC machine driver for TI OMAP HDMI
* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
* Author: Ricardo Neri <ricardo.neri@ti.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#include <linux/module.h>
#include <sound/pcm.h>
#include <sound/soc.h>
#include <asm/mach-types.h>
#include <video/omapdss.h>
#define DRV_NAME "omap-hdmi-audio"
static
struct
snd_soc_dai_link
omap_hdmi_dai
=
{
.
name
=
"HDMI"
,
.
stream_name
=
"HDMI"
,
.
cpu_dai_name
=
"omap-hdmi-audio-dai"
,
.
platform_name
=
"omap-hdmi-audio-dai"
,
.
codec_name
=
"hdmi-audio-codec"
,
.
codec_dai_name
=
"hdmi-hifi"
,
};
static
struct
snd_soc_card
snd_soc_omap_hdmi
=
{
.
name
=
"OMAPHDMI"
,
.
owner
=
THIS_MODULE
,
.
dai_link
=
&
omap_hdmi_dai
,
.
num_links
=
1
,
};
static
int
omap_hdmi_probe
(
struct
platform_device
*
pdev
)
{
struct
snd_soc_card
*
card
=
&
snd_soc_omap_hdmi
;
int
ret
;
card
->
dev
=
&
pdev
->
dev
;
ret
=
snd_soc_register_card
(
card
);
if
(
ret
)
{
dev_err
(
&
pdev
->
dev
,
"snd_soc_register_card failed (%d)
\n
"
,
ret
);
card
->
dev
=
NULL
;
return
ret
;
}
return
0
;
}
static
int
omap_hdmi_remove
(
struct
platform_device
*
pdev
)
{
struct
snd_soc_card
*
card
=
platform_get_drvdata
(
pdev
);
snd_soc_unregister_card
(
card
);
card
->
dev
=
NULL
;
return
0
;
}
static
struct
platform_driver
omap_hdmi_driver
=
{
.
driver
=
{
.
name
=
DRV_NAME
,
.
owner
=
THIS_MODULE
,
},
.
probe
=
omap_hdmi_probe
,
.
remove
=
omap_hdmi_remove
,
};
module_platform_driver
(
omap_hdmi_driver
);
MODULE_AUTHOR
(
"Ricardo Neri <ricardo.neri@ti.com>"
);
MODULE_DESCRIPTION
(
"OMAP HDMI machine ASoC driver"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_ALIAS
(
"platform:"
DRV_NAME
);
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录