Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
193984f4
Commit
193984f4
authored
Jan 08, 2012
by
Florian Tobias Schandinat
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'for-florian' of
git://gitorious.org/linux-omap-dss2/linux
into fbdev-next
parents
c5627f65
9a901683
Changes
42
Hide whitespace changes
Inline
Side-by-side
Showing
42 changed files
with
2883 additions
and
2254 deletions
+2883
-2254
arch/arm/mach-omap2/board-4430sdp.c
arch/arm/mach-omap2/board-4430sdp.c
+8
-15
arch/arm/mach-omap2/board-omap4panda.c
arch/arm/mach-omap2/board-omap4panda.c
+9
-16
arch/arm/mach-omap2/display.c
arch/arm/mach-omap2/display.c
+39
-0
drivers/media/video/omap/omap_vout.c
drivers/media/video/omap/omap_vout.c
+15
-18
drivers/video/omap/lcd_ams_delta.c
drivers/video/omap/lcd_ams_delta.c
+2
-13
drivers/video/omap/lcd_h3.c
drivers/video/omap/lcd_h3.c
+2
-14
drivers/video/omap/lcd_htcherald.c
drivers/video/omap/lcd_htcherald.c
+2
-14
drivers/video/omap/lcd_inn1510.c
drivers/video/omap/lcd_inn1510.c
+2
-14
drivers/video/omap/lcd_inn1610.c
drivers/video/omap/lcd_inn1610.c
+2
-14
drivers/video/omap/lcd_osk.c
drivers/video/omap/lcd_osk.c
+2
-14
drivers/video/omap/lcd_palmte.c
drivers/video/omap/lcd_palmte.c
+2
-14
drivers/video/omap/lcd_palmtt.c
drivers/video/omap/lcd_palmtt.c
+2
-13
drivers/video/omap/lcd_palmz71.c
drivers/video/omap/lcd_palmz71.c
+2
-13
drivers/video/omap2/displays/Kconfig
drivers/video/omap2/displays/Kconfig
+1
-1
drivers/video/omap2/displays/panel-generic-dpi.c
drivers/video/omap2/displays/panel-generic-dpi.c
+66
-0
drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
+52
-9
drivers/video/omap2/displays/panel-taal.c
drivers/video/omap2/displays/panel-taal.c
+14
-24
drivers/video/omap2/dss/Makefile
drivers/video/omap2/dss/Makefile
+2
-1
drivers/video/omap2/dss/apply.c
drivers/video/omap2/dss/apply.c
+1324
-0
drivers/video/omap2/dss/core.c
drivers/video/omap2/dss/core.c
+2
-0
drivers/video/omap2/dss/dispc.c
drivers/video/omap2/dss/dispc.c
+176
-231
drivers/video/omap2/dss/dispc.h
drivers/video/omap2/dss/dispc.h
+11
-0
drivers/video/omap2/dss/dispc_coefs.c
drivers/video/omap2/dss/dispc_coefs.c
+326
-0
drivers/video/omap2/dss/dpi.c
drivers/video/omap2/dss/dpi.c
+5
-2
drivers/video/omap2/dss/dsi.c
drivers/video/omap2/dss/dsi.c
+313
-299
drivers/video/omap2/dss/dss.h
drivers/video/omap2/dss/dss.h
+47
-27
drivers/video/omap2/dss/dss_features.c
drivers/video/omap2/dss/dss_features.c
+11
-0
drivers/video/omap2/dss/dss_features.h
drivers/video/omap2/dss/dss_features.h
+1
-0
drivers/video/omap2/dss/hdmi.c
drivers/video/omap2/dss/hdmi.c
+54
-5
drivers/video/omap2/dss/manager.c
drivers/video/omap2/dss/manager.c
+126
-1095
drivers/video/omap2/dss/overlay.c
drivers/video/omap2/dss/overlay.c
+144
-291
drivers/video/omap2/dss/rfbi.c
drivers/video/omap2/dss/rfbi.c
+0
-1
drivers/video/omap2/dss/sdi.c
drivers/video/omap2/dss/sdi.c
+6
-2
drivers/video/omap2/dss/ti_hdmi.h
drivers/video/omap2/dss/ti_hdmi.h
+9
-1
drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
+7
-30
drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h
drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h
+0
-3
drivers/video/omap2/dss/venc.c
drivers/video/omap2/dss/venc.c
+24
-4
drivers/video/omap2/omapfb/omapfb-ioctl.c
drivers/video/omap2/omapfb/omapfb-ioctl.c
+22
-20
drivers/video/omap2/omapfb/omapfb-main.c
drivers/video/omap2/omapfb/omapfb-main.c
+10
-4
drivers/video/omap2/omapfb/omapfb-sysfs.c
drivers/video/omap2/omapfb/omapfb-sysfs.c
+3
-1
drivers/video/omap2/omapfb/omapfb.h
drivers/video/omap2/omapfb/omapfb.h
+4
-7
include/video/omapdss.h
include/video/omapdss.h
+34
-24
No files found.
arch/arm/mach-omap2/board-4430sdp.c
View file @
193984f4
...
...
@@ -595,20 +595,6 @@ static void __init omap_sfh7741prox_init(void)
__func__
,
OMAP4_SFH7741_ENABLE_GPIO
,
error
);
}
static
void
sdp4430_hdmi_mux_init
(
void
)
{
/* PAD0_HDMI_HPD_PAD1_HDMI_CEC */
omap_mux_init_signal
(
"hdmi_hpd"
,
OMAP_PIN_INPUT_PULLUP
);
omap_mux_init_signal
(
"hdmi_cec"
,
OMAP_PIN_INPUT_PULLUP
);
/* PAD0_HDMI_DDC_SCL_PAD1_HDMI_DDC_SDA */
omap_mux_init_signal
(
"hdmi_ddc_scl"
,
OMAP_PIN_INPUT_PULLUP
);
omap_mux_init_signal
(
"hdmi_ddc_sda"
,
OMAP_PIN_INPUT_PULLUP
);
}
static
struct
gpio
sdp4430_hdmi_gpios
[]
=
{
{
HDMI_GPIO_HPD
,
GPIOF_OUT_INIT_HIGH
,
"hdmi_gpio_hpd"
},
{
HDMI_GPIO_LS_OE
,
GPIOF_OUT_INIT_HIGH
,
"hdmi_gpio_ls_oe"
},
...
...
@@ -826,9 +812,16 @@ static void omap_4430sdp_display_init(void)
pr_err
(
"%s: Could not get display_sel GPIO
\n
"
,
__func__
);
sdp4430_lcd_init
();
sdp4430_hdmi_mux_init
();
sdp4430_picodlp_init
();
omap_display_init
(
&
sdp4430_dss_data
);
/*
* OMAP4460SDP/Blaze and OMAP4430 ES2.3 SDP/Blaze boards and
* later have external pull up on the HDMI I2C lines
*/
if
(
cpu_is_omap446x
()
||
omap_rev
()
>
OMAP4430_REV_ES2_2
)
omap_hdmi_init
(
OMAP_HDMI_SDA_SCL_EXTERNAL_PULLUP
);
else
omap_hdmi_init
(
0
);
}
#ifdef CONFIG_OMAP_MUX
...
...
arch/arm/mach-omap2/board-omap4panda.c
View file @
193984f4
...
...
@@ -478,21 +478,6 @@ int __init omap4_panda_dvi_init(void)
return
r
;
}
static
void
omap4_panda_hdmi_mux_init
(
void
)
{
/* PAD0_HDMI_HPD_PAD1_HDMI_CEC */
omap_mux_init_signal
(
"hdmi_hpd"
,
OMAP_PIN_INPUT_PULLUP
);
omap_mux_init_signal
(
"hdmi_cec"
,
OMAP_PIN_INPUT_PULLUP
);
/* PAD0_HDMI_DDC_SCL_PAD1_HDMI_DDC_SDA */
omap_mux_init_signal
(
"hdmi_ddc_scl"
,
OMAP_PIN_INPUT_PULLUP
);
omap_mux_init_signal
(
"hdmi_ddc_sda"
,
OMAP_PIN_INPUT_PULLUP
);
}
static
struct
gpio
panda_hdmi_gpios
[]
=
{
{
HDMI_GPIO_HPD
,
GPIOF_OUT_INIT_HIGH
,
"hdmi_gpio_hpd"
},
{
HDMI_GPIO_LS_OE
,
GPIOF_OUT_INIT_HIGH
,
"hdmi_gpio_ls_oe"
},
...
...
@@ -544,8 +529,16 @@ void omap4_panda_display_init(void)
if
(
r
)
pr_err
(
"error initializing panda DVI
\n
"
);
omap4_panda_hdmi_mux_init
();
omap_display_init
(
&
omap4_panda_dss_data
);
/*
* OMAP4460SDP/Blaze and OMAP4430 ES2.3 SDP/Blaze boards and
* later have external pull up on the HDMI I2C lines
*/
if
(
cpu_is_omap446x
()
||
omap_rev
()
>
OMAP4430_REV_ES2_2
)
omap_hdmi_init
(
OMAP_HDMI_SDA_SCL_EXTERNAL_PULLUP
);
else
omap_hdmi_init
(
0
);
}
static
void
__init
omap4_panda_init
(
void
)
...
...
arch/arm/mach-omap2/display.c
View file @
193984f4
...
...
@@ -29,6 +29,7 @@
#include <plat/omap-pm.h>
#include <plat/common.h>
#include "mux.h"
#include "control.h"
#include "display.h"
...
...
@@ -96,6 +97,36 @@ static const struct omap_dss_hwmod_data omap4_dss_hwmod_data[] __initdata = {
{
"dss_hdmi"
,
"omapdss_hdmi"
,
-
1
},
};
static
void
omap4_hdmi_mux_pads
(
enum
omap_hdmi_flags
flags
)
{
u32
reg
;
u16
control_i2c_1
;
/* PAD0_HDMI_HPD_PAD1_HDMI_CEC */
omap_mux_init_signal
(
"hdmi_hpd"
,
OMAP_PIN_INPUT_PULLUP
);
omap_mux_init_signal
(
"hdmi_cec"
,
OMAP_PIN_INPUT_PULLUP
);
/* PAD0_HDMI_DDC_SCL_PAD1_HDMI_DDC_SDA */
omap_mux_init_signal
(
"hdmi_ddc_scl"
,
OMAP_PIN_INPUT_PULLUP
);
omap_mux_init_signal
(
"hdmi_ddc_sda"
,
OMAP_PIN_INPUT_PULLUP
);
/*
* CONTROL_I2C_1: HDMI_DDC_SDA_PULLUPRESX (bit 28) and
* HDMI_DDC_SCL_PULLUPRESX (bit 24) are set to disable
* internal pull up resistor.
*/
if
(
flags
&
OMAP_HDMI_SDA_SCL_EXTERNAL_PULLUP
)
{
control_i2c_1
=
OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_I2C_1
;
reg
=
omap4_ctrl_pad_readl
(
control_i2c_1
);
reg
|=
(
OMAP4_HDMI_DDC_SDA_PULLUPRESX_MASK
|
OMAP4_HDMI_DDC_SCL_PULLUPRESX_MASK
);
omap4_ctrl_pad_writel
(
reg
,
control_i2c_1
);
}
}
static
int
omap4_dsi_mux_pads
(
int
dsi_id
,
unsigned
lanes
)
{
u32
enable_mask
,
enable_shift
;
...
...
@@ -129,6 +160,14 @@ static int omap4_dsi_mux_pads(int dsi_id, unsigned lanes)
return
0
;
}
int
omap_hdmi_init
(
enum
omap_hdmi_flags
flags
)
{
if
(
cpu_is_omap44xx
())
omap4_hdmi_mux_pads
(
flags
);
return
0
;
}
static
int
omap_dsi_enable_pads
(
int
dsi_id
,
unsigned
lane_mask
)
{
if
(
cpu_is_omap44xx
())
...
...
drivers/media/video/omap/omap_vout.c
View file @
193984f4
...
...
@@ -423,7 +423,7 @@ static int omapvid_setup_overlay(struct omap_vout_device *vout,
"%s enable=%d addr=%x width=%d
\n
height=%d color_mode=%d
\n
"
"rotation=%d mirror=%d posx=%d posy=%d out_width = %d
\n
"
"out_height=%d rotation_type=%d screen_width=%d
\n
"
,
__func__
,
info
.
enabled
,
info
.
paddr
,
info
.
width
,
info
.
height
,
__func__
,
ovl
->
is_enabled
(
ovl
)
,
info
.
paddr
,
info
.
width
,
info
.
height
,
info
.
color_mode
,
info
.
rotation
,
info
.
mirror
,
info
.
pos_x
,
info
.
pos_y
,
info
.
out_width
,
info
.
out_height
,
info
.
rotation_type
,
info
.
screen_width
);
...
...
@@ -942,12 +942,8 @@ static int omap_vout_release(struct file *file)
/* Disable all the overlay managers connected with this interface */
for
(
i
=
0
;
i
<
ovid
->
num_overlays
;
i
++
)
{
struct
omap_overlay
*
ovl
=
ovid
->
overlays
[
i
];
if
(
ovl
->
manager
&&
ovl
->
manager
->
device
)
{
struct
omap_overlay_info
info
;
ovl
->
get_overlay_info
(
ovl
,
&
info
);
info
.
enabled
=
0
;
ovl
->
set_overlay_info
(
ovl
,
&
info
);
}
if
(
ovl
->
manager
&&
ovl
->
manager
->
device
)
ovl
->
disable
(
ovl
);
}
/* Turn off the pipeline */
ret
=
omapvid_apply_changes
(
vout
);
...
...
@@ -1667,7 +1663,6 @@ static int vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i)
if
(
ovl
->
manager
&&
ovl
->
manager
->
device
)
{
struct
omap_overlay_info
info
;
ovl
->
get_overlay_info
(
ovl
,
&
info
);
info
.
enabled
=
1
;
info
.
paddr
=
addr
;
if
(
ovl
->
set_overlay_info
(
ovl
,
&
info
))
{
ret
=
-
EINVAL
;
...
...
@@ -1686,6 +1681,16 @@ static int vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i)
if
(
ret
)
v4l2_err
(
&
vout
->
vid_dev
->
v4l2_dev
,
"failed to change mode
\n
"
);
for
(
j
=
0
;
j
<
ovid
->
num_overlays
;
j
++
)
{
struct
omap_overlay
*
ovl
=
ovid
->
overlays
[
j
];
if
(
ovl
->
manager
&&
ovl
->
manager
->
device
)
{
ret
=
ovl
->
enable
(
ovl
);
if
(
ret
)
goto
streamon_err1
;
}
}
ret
=
0
;
streamon_err1:
...
...
@@ -1715,16 +1720,8 @@ static int vidioc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i)
for
(
j
=
0
;
j
<
ovid
->
num_overlays
;
j
++
)
{
struct
omap_overlay
*
ovl
=
ovid
->
overlays
[
j
];
if
(
ovl
->
manager
&&
ovl
->
manager
->
device
)
{
struct
omap_overlay_info
info
;
ovl
->
get_overlay_info
(
ovl
,
&
info
);
info
.
enabled
=
0
;
ret
=
ovl
->
set_overlay_info
(
ovl
,
&
info
);
if
(
ret
)
v4l2_err
(
&
vout
->
vid_dev
->
v4l2_dev
,
"failed to update overlay info in streamoff
\n
"
);
}
if
(
ovl
->
manager
&&
ovl
->
manager
->
device
)
ovl
->
disable
(
ovl
);
}
/* Turn of the pipeline */
...
...
drivers/video/omap/lcd_ams_delta.c
View file @
193984f4
...
...
@@ -198,7 +198,7 @@ static int ams_delta_panel_resume(struct platform_device *pdev)
return
0
;
}
struct
platform_driver
ams_delta_panel_driver
=
{
st
atic
st
ruct
platform_driver
ams_delta_panel_driver
=
{
.
probe
=
ams_delta_panel_probe
,
.
remove
=
ams_delta_panel_remove
,
.
suspend
=
ams_delta_panel_suspend
,
...
...
@@ -209,15 +209,4 @@ struct platform_driver ams_delta_panel_driver = {
},
};
static
int
__init
ams_delta_panel_drv_init
(
void
)
{
return
platform_driver_register
(
&
ams_delta_panel_driver
);
}
static
void
__exit
ams_delta_panel_drv_cleanup
(
void
)
{
platform_driver_unregister
(
&
ams_delta_panel_driver
);
}
module_init
(
ams_delta_panel_drv_init
);
module_exit
(
ams_delta_panel_drv_cleanup
);
module_platform_driver
(
ams_delta_panel_driver
);
drivers/video/omap/lcd_h3.c
View file @
193984f4
...
...
@@ -113,7 +113,7 @@ static int h3_panel_resume(struct platform_device *pdev)
return
0
;
}
struct
platform_driver
h3_panel_driver
=
{
st
atic
st
ruct
platform_driver
h3_panel_driver
=
{
.
probe
=
h3_panel_probe
,
.
remove
=
h3_panel_remove
,
.
suspend
=
h3_panel_suspend
,
...
...
@@ -124,16 +124,4 @@ struct platform_driver h3_panel_driver = {
},
};
static
int
__init
h3_panel_drv_init
(
void
)
{
return
platform_driver_register
(
&
h3_panel_driver
);
}
static
void
__exit
h3_panel_drv_cleanup
(
void
)
{
platform_driver_unregister
(
&
h3_panel_driver
);
}
module_init
(
h3_panel_drv_init
);
module_exit
(
h3_panel_drv_cleanup
);
module_platform_driver
(
h3_panel_driver
);
drivers/video/omap/lcd_htcherald.c
View file @
193984f4
...
...
@@ -104,7 +104,7 @@ static int htcherald_panel_resume(struct platform_device *pdev)
return
0
;
}
struct
platform_driver
htcherald_panel_driver
=
{
st
atic
st
ruct
platform_driver
htcherald_panel_driver
=
{
.
probe
=
htcherald_panel_probe
,
.
remove
=
htcherald_panel_remove
,
.
suspend
=
htcherald_panel_suspend
,
...
...
@@ -115,16 +115,4 @@ struct platform_driver htcherald_panel_driver = {
},
};
static
int
__init
htcherald_panel_drv_init
(
void
)
{
return
platform_driver_register
(
&
htcherald_panel_driver
);
}
static
void
__exit
htcherald_panel_drv_cleanup
(
void
)
{
platform_driver_unregister
(
&
htcherald_panel_driver
);
}
module_init
(
htcherald_panel_drv_init
);
module_exit
(
htcherald_panel_drv_cleanup
);
module_platform_driver
(
htcherald_panel_driver
);
drivers/video/omap/lcd_inn1510.c
View file @
193984f4
...
...
@@ -98,7 +98,7 @@ static int innovator1510_panel_resume(struct platform_device *pdev)
return
0
;
}
struct
platform_driver
innovator1510_panel_driver
=
{
st
atic
st
ruct
platform_driver
innovator1510_panel_driver
=
{
.
probe
=
innovator1510_panel_probe
,
.
remove
=
innovator1510_panel_remove
,
.
suspend
=
innovator1510_panel_suspend
,
...
...
@@ -109,16 +109,4 @@ struct platform_driver innovator1510_panel_driver = {
},
};
static
int
__init
innovator1510_panel_drv_init
(
void
)
{
return
platform_driver_register
(
&
innovator1510_panel_driver
);
}
static
void
__exit
innovator1510_panel_drv_cleanup
(
void
)
{
platform_driver_unregister
(
&
innovator1510_panel_driver
);
}
module_init
(
innovator1510_panel_drv_init
);
module_exit
(
innovator1510_panel_drv_cleanup
);
module_platform_driver
(
innovator1510_panel_driver
);
drivers/video/omap/lcd_inn1610.c
View file @
193984f4
...
...
@@ -122,7 +122,7 @@ static int innovator1610_panel_resume(struct platform_device *pdev)
return
0
;
}
struct
platform_driver
innovator1610_panel_driver
=
{
st
atic
st
ruct
platform_driver
innovator1610_panel_driver
=
{
.
probe
=
innovator1610_panel_probe
,
.
remove
=
innovator1610_panel_remove
,
.
suspend
=
innovator1610_panel_suspend
,
...
...
@@ -133,16 +133,4 @@ struct platform_driver innovator1610_panel_driver = {
},
};
static
int
__init
innovator1610_panel_drv_init
(
void
)
{
return
platform_driver_register
(
&
innovator1610_panel_driver
);
}
static
void
__exit
innovator1610_panel_drv_cleanup
(
void
)
{
platform_driver_unregister
(
&
innovator1610_panel_driver
);
}
module_init
(
innovator1610_panel_drv_init
);
module_exit
(
innovator1610_panel_drv_cleanup
);
module_platform_driver
(
innovator1610_panel_driver
);
drivers/video/omap/lcd_osk.c
View file @
193984f4
...
...
@@ -116,7 +116,7 @@ static int osk_panel_resume(struct platform_device *pdev)
return
0
;
}
struct
platform_driver
osk_panel_driver
=
{
st
atic
st
ruct
platform_driver
osk_panel_driver
=
{
.
probe
=
osk_panel_probe
,
.
remove
=
osk_panel_remove
,
.
suspend
=
osk_panel_suspend
,
...
...
@@ -127,16 +127,4 @@ struct platform_driver osk_panel_driver = {
},
};
static
int
__init
osk_panel_drv_init
(
void
)
{
return
platform_driver_register
(
&
osk_panel_driver
);
}
static
void
__exit
osk_panel_drv_cleanup
(
void
)
{
platform_driver_unregister
(
&
osk_panel_driver
);
}
module_init
(
osk_panel_drv_init
);
module_exit
(
osk_panel_drv_cleanup
);
module_platform_driver
(
osk_panel_driver
);
drivers/video/omap/lcd_palmte.c
View file @
193984f4
...
...
@@ -97,7 +97,7 @@ static int palmte_panel_resume(struct platform_device *pdev)
return
0
;
}
struct
platform_driver
palmte_panel_driver
=
{
st
atic
st
ruct
platform_driver
palmte_panel_driver
=
{
.
probe
=
palmte_panel_probe
,
.
remove
=
palmte_panel_remove
,
.
suspend
=
palmte_panel_suspend
,
...
...
@@ -108,16 +108,4 @@ struct platform_driver palmte_panel_driver = {
},
};
static
int
__init
palmte_panel_drv_init
(
void
)
{
return
platform_driver_register
(
&
palmte_panel_driver
);
}
static
void
__exit
palmte_panel_drv_cleanup
(
void
)
{
platform_driver_unregister
(
&
palmte_panel_driver
);
}
module_init
(
palmte_panel_drv_init
);
module_exit
(
palmte_panel_drv_cleanup
);
module_platform_driver
(
palmte_panel_driver
);
drivers/video/omap/lcd_palmtt.c
View file @
193984f4
...
...
@@ -102,7 +102,7 @@ static int palmtt_panel_resume(struct platform_device *pdev)
return
0
;
}
struct
platform_driver
palmtt_panel_driver
=
{
st
atic
st
ruct
platform_driver
palmtt_panel_driver
=
{
.
probe
=
palmtt_panel_probe
,
.
remove
=
palmtt_panel_remove
,
.
suspend
=
palmtt_panel_suspend
,
...
...
@@ -113,15 +113,4 @@ struct platform_driver palmtt_panel_driver = {
},
};
static
int
__init
palmtt_panel_drv_init
(
void
)
{
return
platform_driver_register
(
&
palmtt_panel_driver
);
}
static
void
__exit
palmtt_panel_drv_cleanup
(
void
)
{
platform_driver_unregister
(
&
palmtt_panel_driver
);
}
module_init
(
palmtt_panel_drv_init
);
module_exit
(
palmtt_panel_drv_cleanup
);
module_platform_driver
(
palmtt_panel_driver
);
drivers/video/omap/lcd_palmz71.c
View file @
193984f4
...
...
@@ -98,7 +98,7 @@ static int palmz71_panel_resume(struct platform_device *pdev)
return
0
;
}
struct
platform_driver
palmz71_panel_driver
=
{
st
atic
st
ruct
platform_driver
palmz71_panel_driver
=
{
.
probe
=
palmz71_panel_probe
,
.
remove
=
palmz71_panel_remove
,
.
suspend
=
palmz71_panel_suspend
,
...
...
@@ -109,15 +109,4 @@ struct platform_driver palmz71_panel_driver = {
},
};
static
int
__init
palmz71_panel_drv_init
(
void
)
{
return
platform_driver_register
(
&
palmz71_panel_driver
);
}
static
void
__exit
palmz71_panel_drv_cleanup
(
void
)
{
platform_driver_unregister
(
&
palmz71_panel_driver
);
}
module_init
(
palmz71_panel_drv_init
);
module_exit
(
palmz71_panel_drv_cleanup
);
module_platform_driver
(
palmz71_panel_driver
);
drivers/video/omap2/displays/Kconfig
View file @
193984f4
...
...
@@ -41,7 +41,7 @@ config PANEL_NEC_NL8048HL11_01B
config PANEL_PICODLP
tristate "TI PICO DLP mini-projector"
depends on OMAP2_DSS && I2C
depends on OMAP2_DSS
_DPI
&& I2C
help
A mini-projector used in TI's SDP4430 and EVM boards
For more info please visit http://www.dlp.com/projector/
...
...
drivers/video/omap2/displays/panel-generic-dpi.c
View file @
193984f4
...
...
@@ -297,6 +297,72 @@ static struct panel_config generic_dpi_panels[] = {
.
name
=
"apollon"
,
},
/* FocalTech ETM070003DH6 */
{
{
.
x_res
=
800
,
.
y_res
=
480
,
.
pixel_clock
=
28000
,
.
hsw
=
48
,
.
hfp
=
40
,
.
hbp
=
40
,
.
vsw
=
3
,
.
vfp
=
13
,
.
vbp
=
29
,
},
.
config
=
OMAP_DSS_LCD_TFT
|
OMAP_DSS_LCD_IVS
|
OMAP_DSS_LCD_IHS
,
.
name
=
"focaltech_etm070003dh6"
,
},
/* Microtips Technologies - UMSH-8173MD */
{
{
.
x_res
=
800
,
.
y_res
=
480
,
.
pixel_clock
=
34560
,
.
hsw
=
13
,
.
hfp
=
101
,
.
hbp
=
101
,
.
vsw
=
23
,
.
vfp
=
1
,
.
vbp
=
1
,
},
.
acbi
=
0x0
,
.
acb
=
0x0
,
.
config
=
OMAP_DSS_LCD_TFT
|
OMAP_DSS_LCD_IVS
|
OMAP_DSS_LCD_IHS
|
OMAP_DSS_LCD_IPC
,
.
power_on_delay
=
0
,
.
power_off_delay
=
0
,
.
name
=
"microtips_umsh_8173md"
,
},
/* OrtusTech COM43H4M10XTC */
{
{
.
x_res
=
480
,
.
y_res
=
272
,
.
pixel_clock
=
8000
,
.
hsw
=
41
,
.
hfp
=
8
,
.
hbp
=
4
,
.
vsw
=
10
,
.
vfp
=
4
,
.
vbp
=
2
,
},
.
config
=
OMAP_DSS_LCD_TFT
,
.
name
=
"ortustech_com43h4m10xtc"
,
},
};
struct
panel_drv_data
{
...
...
drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
View file @
193984f4
...
...
@@ -163,50 +163,93 @@ static void nec_8048_panel_remove(struct omap_dss_device *dssdev)
kfree
(
necd
);
}
static
int
nec_8048_panel_
enable
(
struct
omap_dss_device
*
dssdev
)
static
int
nec_8048_panel_
power_on
(
struct
omap_dss_device
*
dssdev
)
{
int
r
=
0
;
int
r
;
struct
nec_8048_data
*
necd
=
dev_get_drvdata
(
&
dssdev
->
dev
);
struct
backlight_device
*
bl
=
necd
->
bl
;
if
(
dssdev
->
state
==
OMAP_DSS_DISPLAY_ACTIVE
)
return
0
;
r
=
omapdss_dpi_display_enable
(
dssdev
);
if
(
r
)
goto
err0
;
if
(
dssdev
->
platform_enable
)
{
r
=
dssdev
->
platform_enable
(
dssdev
);
if
(
r
)
return
r
;
goto
err1
;
}
r
=
nec_8048_bl_update_status
(
bl
);
if
(
r
<
0
)
dev_err
(
&
dssdev
->
dev
,
"failed to set lcd brightness
\n
"
);
r
=
omapdss_dpi_display_enable
(
dssdev
);
return
0
;
err1:
omapdss_dpi_display_disable
(
dssdev
);
err0:
return
r
;
}
static
void
nec_8048_panel_
disable
(
struct
omap_dss_device
*
dssdev
)
static
void
nec_8048_panel_
power_off
(
struct
omap_dss_device
*
dssdev
)
{
struct
nec_8048_data
*
necd
=
dev_get_drvdata
(
&
dssdev
->
dev
);
struct
backlight_device
*
bl
=
necd
->
bl
;
omapdss_dpi_display_disable
(
dssdev
);
if
(
dssdev
->
state
!=
OMAP_DSS_DISPLAY_ACTIVE
)
return
;
bl
->
props
.
brightness
=
0
;
nec_8048_bl_update_status
(
bl
);
if
(
dssdev
->
platform_disable
)
dssdev
->
platform_disable
(
dssdev
);
omapdss_dpi_display_disable
(
dssdev
);
}
static
int
nec_8048_panel_enable
(
struct
omap_dss_device
*
dssdev
)
{
int
r
;
r
=
nec_8048_panel_power_on
(
dssdev
);
if
(
r
)
return
r
;
dssdev
->
state
=
OMAP_DSS_DISPLAY_ACTIVE
;
return
0
;
}
static
void
nec_8048_panel_disable
(
struct
omap_dss_device
*
dssdev
)
{
nec_8048_panel_power_off
(
dssdev
);
dssdev
->
state
=
OMAP_DSS_DISPLAY_DISABLED
;
}
static
int
nec_8048_panel_suspend
(
struct
omap_dss_device
*
dssdev
)
{
nec_8048_panel_disable
(
dssdev
);
nec_8048_panel_power_off
(
dssdev
);
dssdev
->
state
=
OMAP_DSS_DISPLAY_SUSPENDED
;
return
0
;
}
static
int
nec_8048_panel_resume
(
struct
omap_dss_device
*
dssdev
)
{
return
nec_8048_panel_enable
(
dssdev
);
int
r
;
r
=
nec_8048_panel_power_on
(
dssdev
);
if
(
r
)
return
r
;
dssdev
->
state
=
OMAP_DSS_DISPLAY_ACTIVE
;
return
0
;
}
static
int
nec_8048_recommended_bpp
(
struct
omap_dss_device
*
dssdev
)
...
...
drivers/video/omap2/displays/panel-taal.c
View file @
193984f4
...
...
@@ -198,12 +198,6 @@ struct taal_data {
bool
te_enabled
;
atomic_t
do_update
;
struct
{
u16
x
;
u16
y
;
u16
w
;
u16
h
;
}
update_region
;
int
channel
;
struct
delayed_work
te_timeout_work
;
...
...
@@ -1188,6 +1182,10 @@ static int taal_power_on(struct omap_dss_device *dssdev)
if
(
r
)
goto
err
;
r
=
dsi_enable_video_output
(
dssdev
,
td
->
channel
);
if
(
r
)
goto
err
;
td
->
enabled
=
1
;
if
(
!
td
->
intro_printed
)
{
...
...
@@ -1217,6 +1215,8 @@ static void taal_power_off(struct omap_dss_device *dssdev)
struct
taal_data
*
td
=
dev_get_drvdata
(
&
dssdev
->
dev
);
int
r
;
dsi_disable_video_output
(
dssdev
,
td
->
channel
);
r
=
taal_dcs_write_0
(
td
,
MIPI_DCS_SET_DISPLAY_OFF
);
if
(
!
r
)
r
=
taal_sleep_in
(
td
);
...
...
@@ -1394,12 +1394,8 @@ static irqreturn_t taal_te_isr(int irq, void *data)
if
(
old
)
{
cancel_delayed_work
(
&
td
->
te_timeout_work
);
r
=
omap_dsi_update
(
dssdev
,
td
->
channel
,
td
->
update_region
.
x
,
td
->
update_region
.
y
,
td
->
update_region
.
w
,
td
->
update_region
.
h
,
taal_framedone_cb
,
dssdev
);
r
=
omap_dsi_update
(
dssdev
,
td
->
channel
,
taal_framedone_cb
,
dssdev
);
if
(
r
)
goto
err
;
}
...
...
@@ -1444,26 +1440,20 @@ static int taal_update(struct omap_dss_device *dssdev,
goto
err
;
}
r
=
omap_dsi_prepare_update
(
dssdev
,
&
x
,
&
y
,
&
w
,
&
h
,
true
);
if
(
r
)
goto
err
;
r
=
taal_set_update_window
(
td
,
x
,
y
,
w
,
h
);
/* XXX no need to send this every frame, but dsi break if not done */
r
=
taal_set_update_window
(
td
,
0
,
0
,
td
->
panel_config
->
timings
.
x_res
,
td
->
panel_config
->
timings
.
y_res
);
if
(
r
)
goto
err
;
if
(
td
->
te_enabled
&&
panel_data
->
use_ext_te
)
{
td
->
update_region
.
x
=
x
;
td
->
update_region
.
y
=
y
;
td
->
update_region
.
w
=
w
;
td
->
update_region
.
h
=
h
;
barrier
();
schedule_delayed_work
(
&
td
->
te_timeout_work
,
msecs_to_jiffies
(
250
));
atomic_set
(
&
td
->
do_update
,
1
);
}
else
{
r
=
omap_dsi_update
(
dssdev
,
td
->
channel
,
x
,
y
,
w
,
h
,
taal_framedone_cb
,
dssdev
);
r
=
omap_dsi_update
(
dssdev
,
td
->
channel
,
taal_framedone_cb
,
dssdev
);
if
(
r
)
goto
err
;
}
...
...
drivers/video/omap2/dss/Makefile
View file @
193984f4
obj-$(CONFIG_OMAP2_DSS)
+=
omapdss.o
omapdss-y
:=
core.o dss.o dss_features.o dispc.o display.o manager.o overlay.o
omapdss-y
:=
core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o
\
manager.o overlay.o apply.o
omapdss-$(CONFIG_OMAP2_DSS_DPI)
+=
dpi.o
omapdss-$(CONFIG_OMAP2_DSS_RFBI)
+=
rfbi.o
omapdss-$(CONFIG_OMAP2_DSS_VENC)
+=
venc.o
...
...
drivers/video/omap2/dss/apply.c
0 → 100644
View file @
193984f4
/*
* Copyright (C) 2011 Texas Instruments
* Author: Tomi Valkeinen <tomi.valkeinen@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, see <http://www.gnu.org/licenses/>.
*/
#define DSS_SUBSYS_NAME "APPLY"
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/jiffies.h>
#include <video/omapdss.h>
#include "dss.h"
#include "dss_features.h"
/*
* We have 4 levels of cache for the dispc settings. First two are in SW and
* the latter two in HW.
*
* set_info()
* v
* +--------------------+
* | user_info |
* +--------------------+
* v
* apply()
* v
* +--------------------+
* | info |
* +--------------------+
* v
* write_regs()
* v
* +--------------------+
* | shadow registers |
* +--------------------+
* v
* VFP or lcd/digit_enable
* v
* +--------------------+
* | registers |
* +--------------------+
*/
struct
ovl_priv_data
{
bool
user_info_dirty
;
struct
omap_overlay_info
user_info
;
bool
info_dirty
;
struct
omap_overlay_info
info
;
bool
shadow_info_dirty
;
bool
extra_info_dirty
;
bool
shadow_extra_info_dirty
;
bool
enabled
;
enum
omap_channel
channel
;
u32
fifo_low
,
fifo_high
;
/*
* True if overlay is to be enabled. Used to check and calculate configs
* for the overlay before it is enabled in the HW.
*/
bool
enabling
;
};
struct
mgr_priv_data
{
bool
user_info_dirty
;
struct
omap_overlay_manager_info
user_info
;
bool
info_dirty
;
struct
omap_overlay_manager_info
info
;
bool
shadow_info_dirty
;
/* If true, GO bit is up and shadow registers cannot be written.
* Never true for manual update displays */
bool
busy
;
/* If true, dispc output is enabled */
bool
updating
;
/* If true, a display is enabled using this manager */
bool
enabled
;
};
static
struct
{
struct
ovl_priv_data
ovl_priv_data_array
[
MAX_DSS_OVERLAYS
];
struct
mgr_priv_data
mgr_priv_data_array
[
MAX_DSS_MANAGERS
];
bool
irq_enabled
;
}
dss_data
;
/* protects dss_data */
static
spinlock_t
data_lock
;
/* lock for blocking functions */
static
DEFINE_MUTEX
(
apply_lock
);
static
DECLARE_COMPLETION
(
extra_updated_completion
);
static
void
dss_register_vsync_isr
(
void
);
static
struct
ovl_priv_data
*
get_ovl_priv
(
struct
omap_overlay
*
ovl
)
{
return
&
dss_data
.
ovl_priv_data_array
[
ovl
->
id
];
}
static
struct
mgr_priv_data
*
get_mgr_priv
(
struct
omap_overlay_manager
*
mgr
)
{
return
&
dss_data
.
mgr_priv_data_array
[
mgr
->
id
];
}
void
dss_apply_init
(
void
)
{
const
int
num_ovls
=
dss_feat_get_num_ovls
();
int
i
;
spin_lock_init
(
&
data_lock
);
for
(
i
=
0
;
i
<
num_ovls
;
++
i
)
{
struct
ovl_priv_data
*
op
;
op
=
&
dss_data
.
ovl_priv_data_array
[
i
];
op
->
info
.
global_alpha
=
255
;
switch
(
i
)
{
case
0
:
op
->
info
.
zorder
=
0
;
break
;
case
1
:
op
->
info
.
zorder
=
dss_has_feature
(
FEAT_ALPHA_FREE_ZORDER
)
?
3
:
0
;
break
;
case
2
:
op
->
info
.
zorder
=
dss_has_feature
(
FEAT_ALPHA_FREE_ZORDER
)
?
2
:
0
;
break
;
case
3
:
op
->
info
.
zorder
=
dss_has_feature
(
FEAT_ALPHA_FREE_ZORDER
)
?
1
:
0
;
break
;
}
op
->
user_info
=
op
->
info
;
}
}
static
bool
ovl_manual_update
(
struct
omap_overlay
*
ovl
)
{
return
ovl
->
manager
->
device
->
caps
&
OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE
;
}
static
bool
mgr_manual_update
(
struct
omap_overlay_manager
*
mgr
)
{
return
mgr
->
device
->
caps
&
OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE
;
}
static
int
dss_check_settings_low
(
struct
omap_overlay_manager
*
mgr
,
struct
omap_dss_device
*
dssdev
,
bool
applying
)
{
struct
omap_overlay_info
*
oi
;
struct
omap_overlay_manager_info
*
mi
;
struct
omap_overlay
*
ovl
;
struct
omap_overlay_info
*
ois
[
MAX_DSS_OVERLAYS
];
struct
ovl_priv_data
*
op
;
struct
mgr_priv_data
*
mp
;
mp
=
get_mgr_priv
(
mgr
);
if
(
applying
&&
mp
->
user_info_dirty
)
mi
=
&
mp
->
user_info
;
else
mi
=
&
mp
->
info
;
/* collect the infos to be tested into the array */
list_for_each_entry
(
ovl
,
&
mgr
->
overlays
,
list
)
{
op
=
get_ovl_priv
(
ovl
);
if
(
!
op
->
enabled
&&
!
op
->
enabling
)
oi
=
NULL
;
else
if
(
applying
&&
op
->
user_info_dirty
)
oi
=
&
op
->
user_info
;
else
oi
=
&
op
->
info
;
ois
[
ovl
->
id
]
=
oi
;
}
return
dss_mgr_check
(
mgr
,
dssdev
,
mi
,
ois
);
}
/*
* check manager and overlay settings using overlay_info from data->info
*/
static
int
dss_check_settings
(
struct
omap_overlay_manager
*
mgr
,
struct
omap_dss_device
*
dssdev
)
{
return
dss_check_settings_low
(
mgr
,
dssdev
,
false
);
}
/*
* check manager and overlay settings using overlay_info from ovl->info if
* dirty and from data->info otherwise
*/
static
int
dss_check_settings_apply
(
struct
omap_overlay_manager
*
mgr
,
struct
omap_dss_device
*
dssdev
)
{
return
dss_check_settings_low
(
mgr
,
dssdev
,
true
);
}
static
bool
need_isr
(
void
)
{
const
int
num_mgrs
=
dss_feat_get_num_mgrs
();
int
i
;
for
(
i
=
0
;
i
<
num_mgrs
;
++
i
)
{
struct
omap_overlay_manager
*
mgr
;
struct
mgr_priv_data
*
mp
;
struct
omap_overlay
*
ovl
;
mgr
=
omap_dss_get_overlay_manager
(
i
);
mp
=
get_mgr_priv
(
mgr
);
if
(
!
mp
->
enabled
)
continue
;
if
(
mgr_manual_update
(
mgr
))
{
/* to catch FRAMEDONE */
if
(
mp
->
updating
)
return
true
;
}
else
{
/* to catch GO bit going down */
if
(
mp
->
busy
)
return
true
;
/* to write new values to registers */
if
(
mp
->
info_dirty
)
return
true
;
/* to set GO bit */
if
(
mp
->
shadow_info_dirty
)
return
true
;
list_for_each_entry
(
ovl
,
&
mgr
->
overlays
,
list
)
{
struct
ovl_priv_data
*
op
;
op
=
get_ovl_priv
(
ovl
);
/*
* NOTE: we check extra_info flags even for
* disabled overlays, as extra_infos need to be
* always written.
*/
/* to write new values to registers */
if
(
op
->
extra_info_dirty
)
return
true
;
/* to set GO bit */
if
(
op
->
shadow_extra_info_dirty
)
return
true
;
if
(
!
op
->
enabled
)
continue
;
/* to write new values to registers */
if
(
op
->
info_dirty
)
return
true
;
/* to set GO bit */
if
(
op
->
shadow_info_dirty
)
return
true
;
}
}
}
return
false
;
}
static
bool
need_go
(
struct
omap_overlay_manager
*
mgr
)
{
struct
omap_overlay
*
ovl
;
struct
mgr_priv_data
*
mp
;
struct
ovl_priv_data
*
op
;
mp
=
get_mgr_priv
(
mgr
);
if
(
mp
->
shadow_info_dirty
)
return
true
;
list_for_each_entry
(
ovl
,
&
mgr
->
overlays
,
list
)
{
op
=
get_ovl_priv
(
ovl
);
if
(
op
->
shadow_info_dirty
||
op
->
shadow_extra_info_dirty
)
return
true
;
}
return
false
;
}
/* returns true if an extra_info field is currently being updated */
static
bool
extra_info_update_ongoing
(
void
)
{
const
int
num_ovls
=
omap_dss_get_num_overlays
();
struct
ovl_priv_data
*
op
;
struct
omap_overlay
*
ovl
;
struct
mgr_priv_data
*
mp
;
int
i
;
for
(
i
=
0
;
i
<
num_ovls
;
++
i
)
{
ovl
=
omap_dss_get_overlay
(
i
);
op
=
get_ovl_priv
(
ovl
);
if
(
!
ovl
->
manager
)
continue
;
mp
=
get_mgr_priv
(
ovl
->
manager
);
if
(
!
mp
->
enabled
)
continue
;
if
(
!
mp
->
updating
)
continue
;
if
(
op
->
extra_info_dirty
||
op
->
shadow_extra_info_dirty
)
return
true
;
}
return
false
;
}
/* wait until no extra_info updates are pending */
static
void
wait_pending_extra_info_updates
(
void
)
{
bool
updating
;
unsigned
long
flags
;
unsigned
long
t
;
spin_lock_irqsave
(
&
data_lock
,
flags
);
updating
=
extra_info_update_ongoing
();
if
(
!
updating
)
{
spin_unlock_irqrestore
(
&
data_lock
,
flags
);
return
;
}
init_completion
(
&
extra_updated_completion
);
spin_unlock_irqrestore
(
&
data_lock
,
flags
);
t
=
msecs_to_jiffies
(
500
);
wait_for_completion_timeout
(
&
extra_updated_completion
,
t
);
updating
=
extra_info_update_ongoing
();
WARN_ON
(
updating
);
}
int
dss_mgr_wait_for_go
(
struct
omap_overlay_manager
*
mgr
)
{
unsigned
long
timeout
=
msecs_to_jiffies
(
500
);
struct
mgr_priv_data
*
mp
;
u32
irq
;
int
r
;
int
i
;
struct
omap_dss_device
*
dssdev
=
mgr
->
device
;
if
(
!
dssdev
||
dssdev
->
state
!=
OMAP_DSS_DISPLAY_ACTIVE
)
return
0
;
if
(
mgr_manual_update
(
mgr
))
return
0
;
irq
=
dispc_mgr_get_vsync_irq
(
mgr
->
id
);
mp
=
get_mgr_priv
(
mgr
);
i
=
0
;
while
(
1
)
{
unsigned
long
flags
;
bool
shadow_dirty
,
dirty
;
spin_lock_irqsave
(
&
data_lock
,
flags
);
dirty
=
mp
->
info_dirty
;
shadow_dirty
=
mp
->
shadow_info_dirty
;
spin_unlock_irqrestore
(
&
data_lock
,
flags
);
if
(
!
dirty
&&
!
shadow_dirty
)
{
r
=
0
;
break
;
}
/* 4 iterations is the worst case:
* 1 - initial iteration, dirty = true (between VFP and VSYNC)
* 2 - first VSYNC, dirty = true
* 3 - dirty = false, shadow_dirty = true
* 4 - shadow_dirty = false */
if
(
i
++
==
3
)
{
DSSERR
(
"mgr(%d)->wait_for_go() not finishing
\n
"
,
mgr
->
id
);
r
=
0
;
break
;
}
r
=
omap_dispc_wait_for_irq_interruptible_timeout
(
irq
,
timeout
);
if
(
r
==
-
ERESTARTSYS
)
break
;
if
(
r
)
{
DSSERR
(
"mgr(%d)->wait_for_go() timeout
\n
"
,
mgr
->
id
);
break
;
}
}
return
r
;
}
int
dss_mgr_wait_for_go_ovl
(
struct
omap_overlay
*
ovl
)
{
unsigned
long
timeout
=
msecs_to_jiffies
(
500
);
struct
ovl_priv_data
*
op
;
struct
omap_dss_device
*
dssdev
;
u32
irq
;
int
r
;
int
i
;
if
(
!
ovl
->
manager
)
return
0
;
dssdev
=
ovl
->
manager
->
device
;
if
(
!
dssdev
||
dssdev
->
state
!=
OMAP_DSS_DISPLAY_ACTIVE
)
return
0
;
if
(
ovl_manual_update
(
ovl
))
return
0
;
irq
=
dispc_mgr_get_vsync_irq
(
ovl
->
manager
->
id
);
op
=
get_ovl_priv
(
ovl
);
i
=
0
;
while
(
1
)
{
unsigned
long
flags
;
bool
shadow_dirty
,
dirty
;
spin_lock_irqsave
(
&
data_lock
,
flags
);
dirty
=
op
->
info_dirty
;
shadow_dirty
=
op
->
shadow_info_dirty
;
spin_unlock_irqrestore
(
&
data_lock
,
flags
);
if
(
!
dirty
&&
!
shadow_dirty
)
{
r
=
0
;
break
;
}
/* 4 iterations is the worst case:
* 1 - initial iteration, dirty = true (between VFP and VSYNC)
* 2 - first VSYNC, dirty = true
* 3 - dirty = false, shadow_dirty = true
* 4 - shadow_dirty = false */
if
(
i
++
==
3
)
{
DSSERR
(
"ovl(%d)->wait_for_go() not finishing
\n
"
,
ovl
->
id
);
r
=
0
;
break
;
}
r
=
omap_dispc_wait_for_irq_interruptible_timeout
(
irq
,
timeout
);
if
(
r
==
-
ERESTARTSYS
)
break
;
if
(
r
)
{
DSSERR
(
"ovl(%d)->wait_for_go() timeout
\n
"
,
ovl
->
id
);
break
;
}
}
return
r
;
}
static
void
dss_ovl_write_regs
(
struct
omap_overlay
*
ovl
)
{
struct
ovl_priv_data
*
op
=
get_ovl_priv
(
ovl
);
struct
omap_overlay_info
*
oi
;
bool
ilace
,
replication
;
struct
mgr_priv_data
*
mp
;
int
r
;
DSSDBGF
(
"%d"
,
ovl
->
id
);
if
(
!
op
->
enabled
||
!
op
->
info_dirty
)
return
;
oi
=
&
op
->
info
;
replication
=
dss_use_replication
(
ovl
->
manager
->
device
,
oi
->
color_mode
);
ilace
=
ovl
->
manager
->
device
->
type
==
OMAP_DISPLAY_TYPE_VENC
;
r
=
dispc_ovl_setup
(
ovl
->
id
,
oi
,
ilace
,
replication
);
if
(
r
)
{
/*
* We can't do much here, as this function can be called from
* vsync interrupt.
*/
DSSERR
(
"dispc_ovl_setup failed for ovl %d
\n
"
,
ovl
->
id
);
/* This will leave fifo configurations in a nonoptimal state */
op
->
enabled
=
false
;
dispc_ovl_enable
(
ovl
->
id
,
false
);
return
;
}
mp
=
get_mgr_priv
(
ovl
->
manager
);
op
->
info_dirty
=
false
;
if
(
mp
->
updating
)
op
->
shadow_info_dirty
=
true
;
}
static
void
dss_ovl_write_regs_extra
(
struct
omap_overlay
*
ovl
)
{
struct
ovl_priv_data
*
op
=
get_ovl_priv
(
ovl
);
struct
mgr_priv_data
*
mp
;
DSSDBGF
(
"%d"
,
ovl
->
id
);
if
(
!
op
->
extra_info_dirty
)
return
;
/* note: write also when op->enabled == false, so that the ovl gets
* disabled */
dispc_ovl_enable
(
ovl
->
id
,
op
->
enabled
);
dispc_ovl_set_channel_out
(
ovl
->
id
,
op
->
channel
);
dispc_ovl_set_fifo_threshold
(
ovl
->
id
,
op
->
fifo_low
,
op
->
fifo_high
);
mp
=
get_mgr_priv
(
ovl
->
manager
);
op
->
extra_info_dirty
=
false
;
if
(
mp
->
updating
)
op
->
shadow_extra_info_dirty
=
true
;
}
static
void
dss_mgr_write_regs
(
struct
omap_overlay_manager
*
mgr
)
{
struct
mgr_priv_data
*
mp
=
get_mgr_priv
(
mgr
);
struct
omap_overlay
*
ovl
;
DSSDBGF
(
"%d"
,
mgr
->
id
);
if
(
!
mp
->
enabled
)
return
;
WARN_ON
(
mp
->
busy
);
/* Commit overlay settings */
list_for_each_entry
(
ovl
,
&
mgr
->
overlays
,
list
)
{
dss_ovl_write_regs
(
ovl
);
dss_ovl_write_regs_extra
(
ovl
);
}
if
(
mp
->
info_dirty
)
{
dispc_mgr_setup
(
mgr
->
id
,
&
mp
->
info
);
mp
->
info_dirty
=
false
;
if
(
mp
->
updating
)
mp
->
shadow_info_dirty
=
true
;
}
}
static
void
dss_write_regs
(
void
)
{
const
int
num_mgrs
=
omap_dss_get_num_overlay_managers
();
int
i
;
for
(
i
=
0
;
i
<
num_mgrs
;
++
i
)
{
struct
omap_overlay_manager
*
mgr
;
struct
mgr_priv_data
*
mp
;
int
r
;
mgr
=
omap_dss_get_overlay_manager
(
i
);
mp
=
get_mgr_priv
(
mgr
);
if
(
!
mp
->
enabled
||
mgr_manual_update
(
mgr
)
||
mp
->
busy
)
continue
;
r
=
dss_check_settings
(
mgr
,
mgr
->
device
);
if
(
r
)
{
DSSERR
(
"cannot write registers for manager %s: "
"illegal configuration
\n
"
,
mgr
->
name
);
continue
;
}
dss_mgr_write_regs
(
mgr
);
}
}
static
void
dss_set_go_bits
(
void
)
{
const
int
num_mgrs
=
omap_dss_get_num_overlay_managers
();
int
i
;
for
(
i
=
0
;
i
<
num_mgrs
;
++
i
)
{
struct
omap_overlay_manager
*
mgr
;
struct
mgr_priv_data
*
mp
;
mgr
=
omap_dss_get_overlay_manager
(
i
);
mp
=
get_mgr_priv
(
mgr
);
if
(
!
mp
->
enabled
||
mgr_manual_update
(
mgr
)
||
mp
->
busy
)
continue
;
if
(
!
need_go
(
mgr
))
continue
;
mp
->
busy
=
true
;
if
(
!
dss_data
.
irq_enabled
&&
need_isr
())
dss_register_vsync_isr
();
dispc_mgr_go
(
mgr
->
id
);
}
}
void
dss_mgr_start_update
(
struct
omap_overlay_manager
*
mgr
)
{
struct
mgr_priv_data
*
mp
=
get_mgr_priv
(
mgr
);
unsigned
long
flags
;
int
r
;
spin_lock_irqsave
(
&
data_lock
,
flags
);
WARN_ON
(
mp
->
updating
);
r
=
dss_check_settings
(
mgr
,
mgr
->
device
);
if
(
r
)
{
DSSERR
(
"cannot start manual update: illegal configuration
\n
"
);
spin_unlock_irqrestore
(
&
data_lock
,
flags
);
return
;
}
dss_mgr_write_regs
(
mgr
);
mp
->
updating
=
true
;
if
(
!
dss_data
.
irq_enabled
&&
need_isr
())
dss_register_vsync_isr
();
dispc_mgr_enable
(
mgr
->
id
,
true
);
spin_unlock_irqrestore
(
&
data_lock
,
flags
);
}
static
void
dss_apply_irq_handler
(
void
*
data
,
u32
mask
);
static
void
dss_register_vsync_isr
(
void
)
{
const
int
num_mgrs
=
dss_feat_get_num_mgrs
();
u32
mask
;
int
r
,
i
;
mask
=
0
;
for
(
i
=
0
;
i
<
num_mgrs
;
++
i
)
mask
|=
dispc_mgr_get_vsync_irq
(
i
);
for
(
i
=
0
;
i
<
num_mgrs
;
++
i
)
mask
|=
dispc_mgr_get_framedone_irq
(
i
);
r
=
omap_dispc_register_isr
(
dss_apply_irq_handler
,
NULL
,
mask
);
WARN_ON
(
r
);
dss_data
.
irq_enabled
=
true
;
}
static
void
dss_unregister_vsync_isr
(
void
)
{
const
int
num_mgrs
=
dss_feat_get_num_mgrs
();
u32
mask
;
int
r
,
i
;
mask
=
0
;
for
(
i
=
0
;
i
<
num_mgrs
;
++
i
)
mask
|=
dispc_mgr_get_vsync_irq
(
i
);
for
(
i
=
0
;
i
<
num_mgrs
;
++
i
)
mask
|=
dispc_mgr_get_framedone_irq
(
i
);
r
=
omap_dispc_unregister_isr
(
dss_apply_irq_handler
,
NULL
,
mask
);
WARN_ON
(
r
);
dss_data
.
irq_enabled
=
false
;
}
static
void
mgr_clear_shadow_dirty
(
struct
omap_overlay_manager
*
mgr
)
{
struct
omap_overlay
*
ovl
;
struct
mgr_priv_data
*
mp
;
struct
ovl_priv_data
*
op
;
mp
=
get_mgr_priv
(
mgr
);
mp
->
shadow_info_dirty
=
false
;
list_for_each_entry
(
ovl
,
&
mgr
->
overlays
,
list
)
{
op
=
get_ovl_priv
(
ovl
);
op
->
shadow_info_dirty
=
false
;
op
->
shadow_extra_info_dirty
=
false
;
}
}
static
void
dss_apply_irq_handler
(
void
*
data
,
u32
mask
)
{
const
int
num_mgrs
=
dss_feat_get_num_mgrs
();
int
i
;
bool
extra_updating
;
spin_lock
(
&
data_lock
);
/* clear busy, updating flags, shadow_dirty flags */
for
(
i
=
0
;
i
<
num_mgrs
;
i
++
)
{
struct
omap_overlay_manager
*
mgr
;
struct
mgr_priv_data
*
mp
;
bool
was_updating
;
mgr
=
omap_dss_get_overlay_manager
(
i
);
mp
=
get_mgr_priv
(
mgr
);
if
(
!
mp
->
enabled
)
continue
;
was_updating
=
mp
->
updating
;
mp
->
updating
=
dispc_mgr_is_enabled
(
i
);
if
(
!
mgr_manual_update
(
mgr
))
{
bool
was_busy
=
mp
->
busy
;
mp
->
busy
=
dispc_mgr_go_busy
(
i
);
if
(
was_busy
&&
!
mp
->
busy
)
mgr_clear_shadow_dirty
(
mgr
);
}
else
{
if
(
was_updating
&&
!
mp
->
updating
)
mgr_clear_shadow_dirty
(
mgr
);
}
}
dss_write_regs
();
dss_set_go_bits
();
extra_updating
=
extra_info_update_ongoing
();
if
(
!
extra_updating
)
complete_all
(
&
extra_updated_completion
);
if
(
!
need_isr
())
dss_unregister_vsync_isr
();
spin_unlock
(
&
data_lock
);
}
static
void
omap_dss_mgr_apply_ovl
(
struct
omap_overlay
*
ovl
)
{
struct
ovl_priv_data
*
op
;
op
=
get_ovl_priv
(
ovl
);
if
(
!
op
->
user_info_dirty
)
return
;
op
->
user_info_dirty
=
false
;
op
->
info_dirty
=
true
;
op
->
info
=
op
->
user_info
;
}
static
void
omap_dss_mgr_apply_mgr
(
struct
omap_overlay_manager
*
mgr
)
{
struct
mgr_priv_data
*
mp
;
mp
=
get_mgr_priv
(
mgr
);
if
(
!
mp
->
user_info_dirty
)
return
;
mp
->
user_info_dirty
=
false
;
mp
->
info_dirty
=
true
;
mp
->
info
=
mp
->
user_info
;
}
int
omap_dss_mgr_apply
(
struct
omap_overlay_manager
*
mgr
)
{
unsigned
long
flags
;
struct
omap_overlay
*
ovl
;
int
r
;
DSSDBG
(
"omap_dss_mgr_apply(%s)
\n
"
,
mgr
->
name
);
spin_lock_irqsave
(
&
data_lock
,
flags
);
r
=
dss_check_settings_apply
(
mgr
,
mgr
->
device
);
if
(
r
)
{
spin_unlock_irqrestore
(
&
data_lock
,
flags
);
DSSERR
(
"failed to apply settings: illegal configuration.
\n
"
);
return
r
;
}
/* Configure overlays */
list_for_each_entry
(
ovl
,
&
mgr
->
overlays
,
list
)
omap_dss_mgr_apply_ovl
(
ovl
);
/* Configure manager */
omap_dss_mgr_apply_mgr
(
mgr
);
dss_write_regs
();
dss_set_go_bits
();
spin_unlock_irqrestore
(
&
data_lock
,
flags
);
return
0
;
}
static
void
dss_apply_ovl_enable
(
struct
omap_overlay
*
ovl
,
bool
enable
)
{
struct
ovl_priv_data
*
op
;
op
=
get_ovl_priv
(
ovl
);
if
(
op
->
enabled
==
enable
)
return
;
op
->
enabled
=
enable
;
op
->
extra_info_dirty
=
true
;
}
static
void
dss_apply_ovl_fifo_thresholds
(
struct
omap_overlay
*
ovl
,
u32
fifo_low
,
u32
fifo_high
)
{
struct
ovl_priv_data
*
op
=
get_ovl_priv
(
ovl
);
if
(
op
->
fifo_low
==
fifo_low
&&
op
->
fifo_high
==
fifo_high
)
return
;
op
->
fifo_low
=
fifo_low
;
op
->
fifo_high
=
fifo_high
;
op
->
extra_info_dirty
=
true
;
}
static
void
dss_ovl_setup_fifo
(
struct
omap_overlay
*
ovl
)
{
struct
ovl_priv_data
*
op
=
get_ovl_priv
(
ovl
);
struct
omap_dss_device
*
dssdev
;
u32
size
,
burst_size
;
u32
fifo_low
,
fifo_high
;
if
(
!
op
->
enabled
&&
!
op
->
enabling
)
return
;
dssdev
=
ovl
->
manager
->
device
;
size
=
dispc_ovl_get_fifo_size
(
ovl
->
id
);
burst_size
=
dispc_ovl_get_burst_size
(
ovl
->
id
);
switch
(
dssdev
->
type
)
{
case
OMAP_DISPLAY_TYPE_DPI
:
case
OMAP_DISPLAY_TYPE_DBI
:
case
OMAP_DISPLAY_TYPE_SDI
:
case
OMAP_DISPLAY_TYPE_VENC
:
case
OMAP_DISPLAY_TYPE_HDMI
:
default_get_overlay_fifo_thresholds
(
ovl
->
id
,
size
,
burst_size
,
&
fifo_low
,
&
fifo_high
);
break
;
#ifdef CONFIG_OMAP2_DSS_DSI
case
OMAP_DISPLAY_TYPE_DSI
:
dsi_get_overlay_fifo_thresholds
(
ovl
->
id
,
size
,
burst_size
,
&
fifo_low
,
&
fifo_high
);
break
;
#endif
default:
BUG
();
}
dss_apply_ovl_fifo_thresholds
(
ovl
,
fifo_low
,
fifo_high
);
}
static
void
dss_mgr_setup_fifos
(
struct
omap_overlay_manager
*
mgr
)
{
struct
omap_overlay
*
ovl
;
struct
mgr_priv_data
*
mp
;
mp
=
get_mgr_priv
(
mgr
);
if
(
!
mp
->
enabled
)
return
;
list_for_each_entry
(
ovl
,
&
mgr
->
overlays
,
list
)
dss_ovl_setup_fifo
(
ovl
);
}
static
void
dss_setup_fifos
(
void
)
{
const
int
num_mgrs
=
omap_dss_get_num_overlay_managers
();
struct
omap_overlay_manager
*
mgr
;
int
i
;
for
(
i
=
0
;
i
<
num_mgrs
;
++
i
)
{
mgr
=
omap_dss_get_overlay_manager
(
i
);
dss_mgr_setup_fifos
(
mgr
);
}
}
int
dss_mgr_enable
(
struct
omap_overlay_manager
*
mgr
)
{
struct
mgr_priv_data
*
mp
=
get_mgr_priv
(
mgr
);
unsigned
long
flags
;
int
r
;
mutex_lock
(
&
apply_lock
);
if
(
mp
->
enabled
)
goto
out
;
spin_lock_irqsave
(
&
data_lock
,
flags
);
mp
->
enabled
=
true
;
r
=
dss_check_settings
(
mgr
,
mgr
->
device
);
if
(
r
)
{
DSSERR
(
"failed to enable manager %d: check_settings failed
\n
"
,
mgr
->
id
);
goto
err
;
}
dss_setup_fifos
();
dss_write_regs
();
dss_set_go_bits
();
if
(
!
mgr_manual_update
(
mgr
))
mp
->
updating
=
true
;
spin_unlock_irqrestore
(
&
data_lock
,
flags
);
if
(
!
mgr_manual_update
(
mgr
))
dispc_mgr_enable
(
mgr
->
id
,
true
);
out:
mutex_unlock
(
&
apply_lock
);
return
0
;
err:
mp
->
enabled
=
false
;
spin_unlock_irqrestore
(
&
data_lock
,
flags
);
mutex_unlock
(
&
apply_lock
);
return
r
;
}
void
dss_mgr_disable
(
struct
omap_overlay_manager
*
mgr
)
{
struct
mgr_priv_data
*
mp
=
get_mgr_priv
(
mgr
);
unsigned
long
flags
;
mutex_lock
(
&
apply_lock
);
if
(
!
mp
->
enabled
)
goto
out
;
if
(
!
mgr_manual_update
(
mgr
))
dispc_mgr_enable
(
mgr
->
id
,
false
);
spin_lock_irqsave
(
&
data_lock
,
flags
);
mp
->
updating
=
false
;
mp
->
enabled
=
false
;
spin_unlock_irqrestore
(
&
data_lock
,
flags
);
out:
mutex_unlock
(
&
apply_lock
);
}
int
dss_mgr_set_info
(
struct
omap_overlay_manager
*
mgr
,
struct
omap_overlay_manager_info
*
info
)
{
struct
mgr_priv_data
*
mp
=
get_mgr_priv
(
mgr
);
unsigned
long
flags
;
int
r
;
r
=
dss_mgr_simple_check
(
mgr
,
info
);
if
(
r
)
return
r
;
spin_lock_irqsave
(
&
data_lock
,
flags
);
mp
->
user_info
=
*
info
;
mp
->
user_info_dirty
=
true
;
spin_unlock_irqrestore
(
&
data_lock
,
flags
);
return
0
;
}
void
dss_mgr_get_info
(
struct
omap_overlay_manager
*
mgr
,
struct
omap_overlay_manager_info
*
info
)
{
struct
mgr_priv_data
*
mp
=
get_mgr_priv
(
mgr
);
unsigned
long
flags
;
spin_lock_irqsave
(
&
data_lock
,
flags
);
*
info
=
mp
->
user_info
;
spin_unlock_irqrestore
(
&
data_lock
,
flags
);
}
int
dss_mgr_set_device
(
struct
omap_overlay_manager
*
mgr
,
struct
omap_dss_device
*
dssdev
)
{
int
r
;
mutex_lock
(
&
apply_lock
);
if
(
dssdev
->
manager
)
{
DSSERR
(
"display '%s' already has a manager '%s'
\n
"
,
dssdev
->
name
,
dssdev
->
manager
->
name
);
r
=
-
EINVAL
;
goto
err
;
}
if
((
mgr
->
supported_displays
&
dssdev
->
type
)
==
0
)
{
DSSERR
(
"display '%s' does not support manager '%s'
\n
"
,
dssdev
->
name
,
mgr
->
name
);
r
=
-
EINVAL
;
goto
err
;
}
dssdev
->
manager
=
mgr
;
mgr
->
device
=
dssdev
;
mutex_unlock
(
&
apply_lock
);
return
0
;
err:
mutex_unlock
(
&
apply_lock
);
return
r
;
}
int
dss_mgr_unset_device
(
struct
omap_overlay_manager
*
mgr
)
{
int
r
;
mutex_lock
(
&
apply_lock
);
if
(
!
mgr
->
device
)
{
DSSERR
(
"failed to unset display, display not set.
\n
"
);
r
=
-
EINVAL
;
goto
err
;
}
/*
* Don't allow currently enabled displays to have the overlay manager
* pulled out from underneath them
*/
if
(
mgr
->
device
->
state
!=
OMAP_DSS_DISPLAY_DISABLED
)
{
r
=
-
EINVAL
;
goto
err
;
}
mgr
->
device
->
manager
=
NULL
;
mgr
->
device
=
NULL
;
mutex_unlock
(
&
apply_lock
);
return
0
;
err:
mutex_unlock
(
&
apply_lock
);
return
r
;
}
int
dss_ovl_set_info
(
struct
omap_overlay
*
ovl
,
struct
omap_overlay_info
*
info
)
{
struct
ovl_priv_data
*
op
=
get_ovl_priv
(
ovl
);
unsigned
long
flags
;
int
r
;
r
=
dss_ovl_simple_check
(
ovl
,
info
);
if
(
r
)
return
r
;
spin_lock_irqsave
(
&
data_lock
,
flags
);
op
->
user_info
=
*
info
;
op
->
user_info_dirty
=
true
;
spin_unlock_irqrestore
(
&
data_lock
,
flags
);
return
0
;
}
void
dss_ovl_get_info
(
struct
omap_overlay
*
ovl
,
struct
omap_overlay_info
*
info
)
{
struct
ovl_priv_data
*
op
=
get_ovl_priv
(
ovl
);
unsigned
long
flags
;
spin_lock_irqsave
(
&
data_lock
,
flags
);
*
info
=
op
->
user_info
;
spin_unlock_irqrestore
(
&
data_lock
,
flags
);
}
int
dss_ovl_set_manager
(
struct
omap_overlay
*
ovl
,
struct
omap_overlay_manager
*
mgr
)
{
struct
ovl_priv_data
*
op
=
get_ovl_priv
(
ovl
);
unsigned
long
flags
;
int
r
;
if
(
!
mgr
)
return
-
EINVAL
;
mutex_lock
(
&
apply_lock
);
if
(
ovl
->
manager
)
{
DSSERR
(
"overlay '%s' already has a manager '%s'
\n
"
,
ovl
->
name
,
ovl
->
manager
->
name
);
r
=
-
EINVAL
;
goto
err
;
}
spin_lock_irqsave
(
&
data_lock
,
flags
);
if
(
op
->
enabled
)
{
spin_unlock_irqrestore
(
&
data_lock
,
flags
);
DSSERR
(
"overlay has to be disabled to change the manager
\n
"
);
r
=
-
EINVAL
;
goto
err
;
}
op
->
channel
=
mgr
->
id
;
op
->
extra_info_dirty
=
true
;
ovl
->
manager
=
mgr
;
list_add_tail
(
&
ovl
->
list
,
&
mgr
->
overlays
);
spin_unlock_irqrestore
(
&
data_lock
,
flags
);
/* XXX: When there is an overlay on a DSI manual update display, and
* the overlay is first disabled, then moved to tv, and enabled, we
* seem to get SYNC_LOST_DIGIT error.
*
* Waiting doesn't seem to help, but updating the manual update display
* after disabling the overlay seems to fix this. This hints that the
* overlay is perhaps somehow tied to the LCD output until the output
* is updated.
*
* Userspace workaround for this is to update the LCD after disabling
* the overlay, but before moving the overlay to TV.
*/
mutex_unlock
(
&
apply_lock
);
return
0
;
err:
mutex_unlock
(
&
apply_lock
);
return
r
;
}
int
dss_ovl_unset_manager
(
struct
omap_overlay
*
ovl
)
{
struct
ovl_priv_data
*
op
=
get_ovl_priv
(
ovl
);
unsigned
long
flags
;
int
r
;
mutex_lock
(
&
apply_lock
);
if
(
!
ovl
->
manager
)
{
DSSERR
(
"failed to detach overlay: manager not set
\n
"
);
r
=
-
EINVAL
;
goto
err
;
}
spin_lock_irqsave
(
&
data_lock
,
flags
);
if
(
op
->
enabled
)
{
spin_unlock_irqrestore
(
&
data_lock
,
flags
);
DSSERR
(
"overlay has to be disabled to unset the manager
\n
"
);
r
=
-
EINVAL
;
goto
err
;
}
op
->
channel
=
-
1
;
ovl
->
manager
=
NULL
;
list_del
(
&
ovl
->
list
);
spin_unlock_irqrestore
(
&
data_lock
,
flags
);
mutex_unlock
(
&
apply_lock
);
return
0
;
err:
mutex_unlock
(
&
apply_lock
);
return
r
;
}
bool
dss_ovl_is_enabled
(
struct
omap_overlay
*
ovl
)
{
struct
ovl_priv_data
*
op
=
get_ovl_priv
(
ovl
);
unsigned
long
flags
;
bool
e
;
spin_lock_irqsave
(
&
data_lock
,
flags
);
e
=
op
->
enabled
;
spin_unlock_irqrestore
(
&
data_lock
,
flags
);
return
e
;
}
int
dss_ovl_enable
(
struct
omap_overlay
*
ovl
)
{
struct
ovl_priv_data
*
op
=
get_ovl_priv
(
ovl
);
unsigned
long
flags
;
int
r
;
mutex_lock
(
&
apply_lock
);
if
(
op
->
enabled
)
{
r
=
0
;
goto
err1
;
}
if
(
ovl
->
manager
==
NULL
||
ovl
->
manager
->
device
==
NULL
)
{
r
=
-
EINVAL
;
goto
err1
;
}
spin_lock_irqsave
(
&
data_lock
,
flags
);
op
->
enabling
=
true
;
r
=
dss_check_settings
(
ovl
->
manager
,
ovl
->
manager
->
device
);
if
(
r
)
{
DSSERR
(
"failed to enable overlay %d: check_settings failed
\n
"
,
ovl
->
id
);
goto
err2
;
}
dss_setup_fifos
();
op
->
enabling
=
false
;
dss_apply_ovl_enable
(
ovl
,
true
);
dss_write_regs
();
dss_set_go_bits
();
spin_unlock_irqrestore
(
&
data_lock
,
flags
);
mutex_unlock
(
&
apply_lock
);
return
0
;
err2:
op
->
enabling
=
false
;
spin_unlock_irqrestore
(
&
data_lock
,
flags
);
err1:
mutex_unlock
(
&
apply_lock
);
return
r
;
}
int
dss_ovl_disable
(
struct
omap_overlay
*
ovl
)
{
struct
ovl_priv_data
*
op
=
get_ovl_priv
(
ovl
);
unsigned
long
flags
;
int
r
;
mutex_lock
(
&
apply_lock
);
if
(
!
op
->
enabled
)
{
r
=
0
;
goto
err
;
}
if
(
ovl
->
manager
==
NULL
||
ovl
->
manager
->
device
==
NULL
)
{
r
=
-
EINVAL
;
goto
err
;
}
spin_lock_irqsave
(
&
data_lock
,
flags
);
dss_apply_ovl_enable
(
ovl
,
false
);
dss_write_regs
();
dss_set_go_bits
();
spin_unlock_irqrestore
(
&
data_lock
,
flags
);
mutex_unlock
(
&
apply_lock
);
return
0
;
err:
mutex_unlock
(
&
apply_lock
);
return
r
;
}
drivers/video/omap2/dss/core.c
View file @
193984f4
...
...
@@ -178,6 +178,8 @@ static int omap_dss_probe(struct platform_device *pdev)
dss_features_init
();
dss_apply_init
();
dss_init_overlay_managers
(
pdev
);
dss_init_overlays
(
pdev
);
...
...
drivers/video/omap2/dss/dispc.c
View file @
193984f4
...
...
@@ -64,22 +64,6 @@ struct omap_dispc_isr_data {
u32
mask
;
};
struct
dispc_h_coef
{
s8
hc4
;
s8
hc3
;
u8
hc2
;
s8
hc1
;
s8
hc0
;
};
struct
dispc_v_coef
{
s8
vc22
;
s8
vc2
;
u8
vc1
;
s8
vc0
;
s8
vc00
;
};
enum
omap_burst_size
{
BURST_SIZE_X2
=
0
,
BURST_SIZE_X4
=
1
,
...
...
@@ -438,6 +422,34 @@ static struct omap_dss_device *dispc_mgr_get_device(enum omap_channel channel)
return
mgr
?
mgr
->
device
:
NULL
;
}
u32
dispc_mgr_get_vsync_irq
(
enum
omap_channel
channel
)
{
switch
(
channel
)
{
case
OMAP_DSS_CHANNEL_LCD
:
return
DISPC_IRQ_VSYNC
;
case
OMAP_DSS_CHANNEL_LCD2
:
return
DISPC_IRQ_VSYNC2
;
case
OMAP_DSS_CHANNEL_DIGIT
:
return
DISPC_IRQ_EVSYNC_ODD
|
DISPC_IRQ_EVSYNC_EVEN
;
default:
BUG
();
}
}
u32
dispc_mgr_get_framedone_irq
(
enum
omap_channel
channel
)
{
switch
(
channel
)
{
case
OMAP_DSS_CHANNEL_LCD
:
return
DISPC_IRQ_FRAMEDONE
;
case
OMAP_DSS_CHANNEL_LCD2
:
return
DISPC_IRQ_FRAMEDONE2
;
case
OMAP_DSS_CHANNEL_DIGIT
:
return
0
;
default:
BUG
();
}
}
bool
dispc_mgr_go_busy
(
enum
omap_channel
channel
)
{
int
bit
;
...
...
@@ -533,105 +545,27 @@ static void dispc_ovl_write_firv2_reg(enum omap_plane plane, int reg, u32 value)
dispc_write_reg
(
DISPC_OVL_FIR_COEF_V2
(
plane
,
reg
),
value
);
}
static
void
dispc_ovl_set_scale_coef
(
enum
omap_plane
plane
,
int
hscaleup
,
int
vscaleup
,
int
five_taps
,
enum
omap_color_component
color_comp
)
{
/* Coefficients for horizontal up-sampling */
static
const
struct
dispc_h_coef
coef_hup
[
8
]
=
{
{
0
,
0
,
128
,
0
,
0
},
{
-
1
,
13
,
124
,
-
8
,
0
},
{
-
2
,
30
,
112
,
-
11
,
-
1
},
{
-
5
,
51
,
95
,
-
11
,
-
2
},
{
0
,
-
9
,
73
,
73
,
-
9
},
{
-
2
,
-
11
,
95
,
51
,
-
5
},
{
-
1
,
-
11
,
112
,
30
,
-
2
},
{
0
,
-
8
,
124
,
13
,
-
1
},
};
/* Coefficients for vertical up-sampling */
static
const
struct
dispc_v_coef
coef_vup_3tap
[
8
]
=
{
{
0
,
0
,
128
,
0
,
0
},
{
0
,
3
,
123
,
2
,
0
},
{
0
,
12
,
111
,
5
,
0
},
{
0
,
32
,
89
,
7
,
0
},
{
0
,
0
,
64
,
64
,
0
},
{
0
,
7
,
89
,
32
,
0
},
{
0
,
5
,
111
,
12
,
0
},
{
0
,
2
,
123
,
3
,
0
},
};
static
const
struct
dispc_v_coef
coef_vup_5tap
[
8
]
=
{
{
0
,
0
,
128
,
0
,
0
},
{
-
1
,
13
,
124
,
-
8
,
0
},
{
-
2
,
30
,
112
,
-
11
,
-
1
},
{
-
5
,
51
,
95
,
-
11
,
-
2
},
{
0
,
-
9
,
73
,
73
,
-
9
},
{
-
2
,
-
11
,
95
,
51
,
-
5
},
{
-
1
,
-
11
,
112
,
30
,
-
2
},
{
0
,
-
8
,
124
,
13
,
-
1
},
};
/* Coefficients for horizontal down-sampling */
static
const
struct
dispc_h_coef
coef_hdown
[
8
]
=
{
{
0
,
36
,
56
,
36
,
0
},
{
4
,
40
,
55
,
31
,
-
2
},
{
8
,
44
,
54
,
27
,
-
5
},
{
12
,
48
,
53
,
22
,
-
7
},
{
-
9
,
17
,
52
,
51
,
17
},
{
-
7
,
22
,
53
,
48
,
12
},
{
-
5
,
27
,
54
,
44
,
8
},
{
-
2
,
31
,
55
,
40
,
4
},
};
/* Coefficients for vertical down-sampling */
static
const
struct
dispc_v_coef
coef_vdown_3tap
[
8
]
=
{
{
0
,
36
,
56
,
36
,
0
},
{
0
,
40
,
57
,
31
,
0
},
{
0
,
45
,
56
,
27
,
0
},
{
0
,
50
,
55
,
23
,
0
},
{
0
,
18
,
55
,
55
,
0
},
{
0
,
23
,
55
,
50
,
0
},
{
0
,
27
,
56
,
45
,
0
},
{
0
,
31
,
57
,
40
,
0
},
};
static
const
struct
dispc_v_coef
coef_vdown_5tap
[
8
]
=
{
{
0
,
36
,
56
,
36
,
0
},
{
4
,
40
,
55
,
31
,
-
2
},
{
8
,
44
,
54
,
27
,
-
5
},
{
12
,
48
,
53
,
22
,
-
7
},
{
-
9
,
17
,
52
,
51
,
17
},
{
-
7
,
22
,
53
,
48
,
12
},
{
-
5
,
27
,
54
,
44
,
8
},
{
-
2
,
31
,
55
,
40
,
4
},
};
const
struct
dispc_h_coef
*
h_coef
;
const
struct
dispc_v_coef
*
v_coef
;
static
void
dispc_ovl_set_scale_coef
(
enum
omap_plane
plane
,
int
fir_hinc
,
int
fir_vinc
,
int
five_taps
,
enum
omap_color_component
color_comp
)
{
const
struct
dispc_coef
*
h_coef
,
*
v_coef
;
int
i
;
if
(
hscaleup
)
h_coef
=
coef_hup
;
else
h_coef
=
coef_hdown
;
if
(
vscaleup
)
v_coef
=
five_taps
?
coef_vup_5tap
:
coef_vup_3tap
;
else
v_coef
=
five_taps
?
coef_vdown_5tap
:
coef_vdown_3tap
;
h_coef
=
dispc_ovl_get_scale_coef
(
fir_hinc
,
true
);
v_coef
=
dispc_ovl_get_scale_coef
(
fir_vinc
,
five_taps
);
for
(
i
=
0
;
i
<
8
;
i
++
)
{
u32
h
,
hv
;
h
=
FLD_VAL
(
h_coef
[
i
].
hc0
,
7
,
0
)
|
FLD_VAL
(
h_coef
[
i
].
hc1
,
15
,
8
)
|
FLD_VAL
(
h_coef
[
i
].
hc2
,
23
,
16
)
|
FLD_VAL
(
h_coef
[
i
].
hc3
,
31
,
24
);
hv
=
FLD_VAL
(
h_coef
[
i
].
hc4
,
7
,
0
)
|
FLD_VAL
(
v_coef
[
i
].
vc0
,
15
,
8
)
|
FLD_VAL
(
v_coef
[
i
].
vc1
,
23
,
16
)
|
FLD_VAL
(
v_coef
[
i
].
vc2
,
31
,
24
);
h
=
FLD_VAL
(
h_coef
[
i
].
hc0
_vc00
,
7
,
0
)
|
FLD_VAL
(
h_coef
[
i
].
hc1
_vc0
,
15
,
8
)
|
FLD_VAL
(
h_coef
[
i
].
hc2
_vc1
,
23
,
16
)
|
FLD_VAL
(
h_coef
[
i
].
hc3
_vc2
,
31
,
24
);
hv
=
FLD_VAL
(
h_coef
[
i
].
hc4
_vc22
,
7
,
0
)
|
FLD_VAL
(
v_coef
[
i
].
hc1_
vc0
,
15
,
8
)
|
FLD_VAL
(
v_coef
[
i
].
hc2_
vc1
,
23
,
16
)
|
FLD_VAL
(
v_coef
[
i
].
hc3_
vc2
,
31
,
24
);
if
(
color_comp
==
DISPC_COLOR_COMPONENT_RGB_Y
)
{
dispc_ovl_write_firh_reg
(
plane
,
i
,
h
);
...
...
@@ -646,8 +580,8 @@ static void dispc_ovl_set_scale_coef(enum omap_plane plane, int hscaleup,
if
(
five_taps
)
{
for
(
i
=
0
;
i
<
8
;
i
++
)
{
u32
v
;
v
=
FLD_VAL
(
v_coef
[
i
].
vc00
,
7
,
0
)
|
FLD_VAL
(
v_coef
[
i
].
vc22
,
15
,
8
);
v
=
FLD_VAL
(
v_coef
[
i
].
hc0_
vc00
,
7
,
0
)
|
FLD_VAL
(
v_coef
[
i
].
hc4_
vc22
,
15
,
8
);
if
(
color_comp
==
DISPC_COLOR_COMPONENT_RGB_Y
)
dispc_ovl_write_firv_reg
(
plane
,
i
,
v
);
else
...
...
@@ -875,8 +809,7 @@ static void dispc_ovl_set_color_mode(enum omap_plane plane,
REG_FLD_MOD
(
DISPC_OVL_ATTRIBUTES
(
plane
),
m
,
4
,
1
);
}
static
void
dispc_ovl_set_channel_out
(
enum
omap_plane
plane
,
enum
omap_channel
channel
)
void
dispc_ovl_set_channel_out
(
enum
omap_plane
plane
,
enum
omap_channel
channel
)
{
int
shift
;
u32
val
;
...
...
@@ -923,6 +856,39 @@ static void dispc_ovl_set_channel_out(enum omap_plane plane,
dispc_write_reg
(
DISPC_OVL_ATTRIBUTES
(
plane
),
val
);
}
static
enum
omap_channel
dispc_ovl_get_channel_out
(
enum
omap_plane
plane
)
{
int
shift
;
u32
val
;
enum
omap_channel
channel
;
switch
(
plane
)
{
case
OMAP_DSS_GFX
:
shift
=
8
;
break
;
case
OMAP_DSS_VIDEO1
:
case
OMAP_DSS_VIDEO2
:
case
OMAP_DSS_VIDEO3
:
shift
=
16
;
break
;
default:
BUG
();
}
val
=
dispc_read_reg
(
DISPC_OVL_ATTRIBUTES
(
plane
));
if
(
dss_has_feature
(
FEAT_MGR_LCD2
))
{
if
(
FLD_GET
(
val
,
31
,
30
)
==
0
)
channel
=
FLD_GET
(
val
,
shift
,
shift
);
else
channel
=
OMAP_DSS_CHANNEL_LCD2
;
}
else
{
channel
=
FLD_GET
(
val
,
shift
,
shift
);
}
return
channel
;
}
static
void
dispc_ovl_set_burst_size
(
enum
omap_plane
plane
,
enum
omap_burst_size
burst_size
)
{
...
...
@@ -964,7 +930,7 @@ void dispc_enable_gamma_table(bool enable)
REG_FLD_MOD
(
DISPC_CONFIG
,
enable
,
9
,
9
);
}
void
dispc_mgr_enable_cpr
(
enum
omap_channel
channel
,
bool
enable
)
static
void
dispc_mgr_enable_cpr
(
enum
omap_channel
channel
,
bool
enable
)
{
u16
reg
;
...
...
@@ -978,7 +944,7 @@ void dispc_mgr_enable_cpr(enum omap_channel channel, bool enable)
REG_FLD_MOD
(
reg
,
enable
,
15
,
15
);
}
void
dispc_mgr_set_cpr_coef
(
enum
omap_channel
channel
,
static
void
dispc_mgr_set_cpr_coef
(
enum
omap_channel
channel
,
struct
omap_dss_cpr_coefs
*
coefs
)
{
u32
coef_r
,
coef_g
,
coef_b
;
...
...
@@ -1057,8 +1023,7 @@ u32 dispc_ovl_get_fifo_size(enum omap_plane plane)
return
dispc
.
fifo_size
[
plane
];
}
static
void
dispc_ovl_set_fifo_threshold
(
enum
omap_plane
plane
,
u32
low
,
u32
high
)
void
dispc_ovl_set_fifo_threshold
(
enum
omap_plane
plane
,
u32
low
,
u32
high
)
{
u8
hi_start
,
hi_end
,
lo_start
,
lo_end
;
u32
unit
;
...
...
@@ -1169,17 +1134,12 @@ static void dispc_ovl_set_scale_param(enum omap_plane plane,
enum
omap_color_component
color_comp
)
{
int
fir_hinc
,
fir_vinc
;
int
hscaleup
,
vscaleup
;
hscaleup
=
orig_width
<=
out_width
;
vscaleup
=
orig_height
<=
out_height
;
dispc_ovl_set_scale_coef
(
plane
,
hscaleup
,
vscaleup
,
five_taps
,
color_comp
);
fir_hinc
=
1024
*
orig_width
/
out_width
;
fir_vinc
=
1024
*
orig_height
/
out_height
;
dispc_ovl_set_scale_coef
(
plane
,
fir_hinc
,
fir_vinc
,
five_taps
,
color_comp
);
dispc_ovl_set_fir
(
plane
,
fir_hinc
,
fir_vinc
,
color_comp
);
}
...
...
@@ -1654,6 +1614,9 @@ static unsigned long calc_fclk_five_taps(enum omap_channel channel, u16 width,
u32
fclk
=
0
;
u64
tmp
,
pclk
=
dispc_mgr_pclk_rate
(
channel
);
if
(
height
<=
out_height
&&
width
<=
out_width
)
return
(
unsigned
long
)
pclk
;
if
(
height
>
out_height
)
{
struct
omap_dss_device
*
dssdev
=
dispc_mgr_get_device
(
channel
);
unsigned
int
ppl
=
dssdev
->
panel
.
timings
.
x_res
;
...
...
@@ -1708,7 +1671,16 @@ static unsigned long calc_fclk(enum omap_channel channel, u16 width,
else
vf
=
1
;
return
dispc_mgr_pclk_rate
(
channel
)
*
vf
*
hf
;
if
(
cpu_is_omap24xx
())
{
if
(
vf
>
1
&&
hf
>
1
)
return
dispc_mgr_pclk_rate
(
channel
)
*
4
;
else
return
dispc_mgr_pclk_rate
(
channel
)
*
2
;
}
else
if
(
cpu_is_omap34xx
())
{
return
dispc_mgr_pclk_rate
(
channel
)
*
vf
*
hf
;
}
else
{
return
dispc_mgr_pclk_rate
(
channel
)
*
hf
;
}
}
static
int
dispc_ovl_calc_scaling
(
enum
omap_plane
plane
,
...
...
@@ -1718,6 +1690,8 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
{
struct
omap_overlay
*
ovl
=
omap_dss_get_overlay
(
plane
);
const
int
maxdownscale
=
dss_feat_get_param_max
(
FEAT_PARAM_DOWNSCALE
);
const
int
maxsinglelinewidth
=
dss_feat_get_param_max
(
FEAT_PARAM_LINEWIDTH
);
unsigned
long
fclk
=
0
;
if
(
width
==
out_width
&&
height
==
out_height
)
...
...
@@ -1734,28 +1708,40 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
out_height
>
height
*
8
)
return
-
EINVAL
;
/* Must use 5-tap filter? */
*
five_taps
=
height
>
out_height
*
2
;
if
(
!*
five_taps
)
{
if
(
cpu_is_omap24xx
())
{
if
(
width
>
maxsinglelinewidth
)
DSSERR
(
"Cannot scale max input width exceeded"
);
*
five_taps
=
false
;
fclk
=
calc_fclk
(
channel
,
width
,
height
,
out_width
,
out_height
);
}
else
if
(
cpu_is_omap34xx
())
{
if
(
width
>
(
maxsinglelinewidth
*
2
))
{
DSSERR
(
"Cannot setup scaling"
);
DSSERR
(
"width exceeds maximum width possible"
);
return
-
EINVAL
;
}
fclk
=
calc_fclk_five_taps
(
channel
,
width
,
height
,
out_width
,
out_height
,
color_mode
);
if
(
width
>
maxsinglelinewidth
)
{
if
(
height
>
out_height
&&
height
<
out_height
*
2
)
*
five_taps
=
false
;
else
{
DSSERR
(
"cannot setup scaling with five taps"
);
return
-
EINVAL
;
}
}
if
(
!*
five_taps
)
fclk
=
calc_fclk
(
channel
,
width
,
height
,
out_width
,
out_height
);
}
else
{
if
(
width
>
maxsinglelinewidth
)
{
DSSERR
(
"Cannot scale width exceeds max line width"
);
return
-
EINVAL
;
}
fclk
=
calc_fclk
(
channel
,
width
,
height
,
out_width
,
out_height
);
/* Try 5-tap filter if 3-tap fclk is too high */
if
(
cpu_is_omap34xx
()
&&
height
>
out_height
&&
fclk
>
dispc_fclk_rate
())
*
five_taps
=
true
;
}
if
(
width
>
(
2048
>>
*
five_taps
))
{
DSSERR
(
"failed to set up scaling, fclk too low
\n
"
);
return
-
EINVAL
;
}
if
(
*
five_taps
)
fclk
=
calc_fclk_five_taps
(
channel
,
width
,
height
,
out_width
,
out_height
,
color_mode
);
DSSDBG
(
"required fclk rate = %lu Hz
\n
"
,
fclk
);
DSSDBG
(
"current fclk rate = %lu Hz
\n
"
,
dispc_fclk_rate
());
...
...
@@ -1771,11 +1757,10 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
}
int
dispc_ovl_setup
(
enum
omap_plane
plane
,
struct
omap_overlay_info
*
oi
,
bool
ilace
,
enum
omap_channel
channel
,
bool
replication
,
u32
fifo_low
,
u32
fifo_high
)
bool
ilace
,
bool
replication
)
{
struct
omap_overlay
*
ovl
=
omap_dss_get_overlay
(
plane
);
bool
five_taps
=
fals
e
;
bool
five_taps
=
tru
e
;
bool
fieldmode
=
0
;
int
r
,
cconv
=
0
;
unsigned
offset0
,
offset1
;
...
...
@@ -1783,36 +1768,43 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
s32
pix_inc
;
u16
frame_height
=
oi
->
height
;
unsigned
int
field_offset
=
0
;
u16
outw
,
outh
;
enum
omap_channel
channel
;
channel
=
dispc_ovl_get_channel_out
(
plane
);
DSSDBG
(
"dispc_ovl_setup %d, pa %x, pa_uv %x, sw %d, %d,%d, %dx%d -> "
"%dx%d, cmode %x, rot %d, mir %d, ilace %d chan %d repl %d
"
"fifo_low %d fifo high %d
\n
"
,
plane
,
oi
->
paddr
,
oi
->
p_uv_addr
,
"%dx%d, cmode %x, rot %d, mir %d, ilace %d chan %d repl %d
\n
"
,
plane
,
oi
->
paddr
,
oi
->
p_uv_addr
,
oi
->
screen_width
,
oi
->
pos_x
,
oi
->
pos_y
,
oi
->
width
,
oi
->
height
,
oi
->
out_width
,
oi
->
out_height
,
oi
->
color_mode
,
oi
->
rotation
,
oi
->
mirror
,
ilace
,
channel
,
replication
,
fifo_low
,
fifo_high
);
oi
->
mirror
,
ilace
,
channel
,
replication
);
if
(
oi
->
paddr
==
0
)
return
-
EINVAL
;
if
(
ilace
&&
oi
->
height
==
oi
->
out_height
)
outw
=
oi
->
out_width
==
0
?
oi
->
width
:
oi
->
out_width
;
outh
=
oi
->
out_height
==
0
?
oi
->
height
:
oi
->
out_height
;
if
(
ilace
&&
oi
->
height
==
outh
)
fieldmode
=
1
;
if
(
ilace
)
{
if
(
fieldmode
)
oi
->
height
/=
2
;
oi
->
pos_y
/=
2
;
o
i
->
out_height
/=
2
;
o
uth
/=
2
;
DSSDBG
(
"adjusting for ilace: height %d, pos_y %d, "
"out_height %d
\n
"
,
oi
->
height
,
oi
->
pos_y
,
o
i
->
out_height
);
oi
->
height
,
oi
->
pos_y
,
o
uth
);
}
if
(
!
dss_feat_color_mode_supported
(
plane
,
oi
->
color_mode
))
return
-
EINVAL
;
r
=
dispc_ovl_calc_scaling
(
plane
,
channel
,
oi
->
width
,
oi
->
height
,
o
i
->
out_width
,
oi
->
out_height
,
oi
->
color_mode
,
o
utw
,
outh
,
oi
->
color_mode
,
&
five_taps
);
if
(
r
)
return
r
;
...
...
@@ -1830,10 +1822,10 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
* so the integer part must be added to the base address of the
* bottom field.
*/
if
(
!
oi
->
height
||
oi
->
height
==
o
i
->
out_height
)
if
(
!
oi
->
height
||
oi
->
height
==
o
uth
)
field_offset
=
0
;
else
field_offset
=
oi
->
height
/
o
i
->
out_height
/
2
;
field_offset
=
oi
->
height
/
o
uth
/
2
;
}
/* Fields are independent but interleaved in memory. */
...
...
@@ -1869,7 +1861,7 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
dispc_ovl_set_pix_inc
(
plane
,
pix_inc
);
DSSDBG
(
"%d,%d %dx%d -> %dx%d
\n
"
,
oi
->
pos_x
,
oi
->
pos_y
,
oi
->
width
,
oi
->
height
,
o
i
->
out_width
,
oi
->
out_height
);
oi
->
height
,
o
utw
,
outh
);
dispc_ovl_set_pos
(
plane
,
oi
->
pos_x
,
oi
->
pos_y
);
...
...
@@ -1877,10 +1869,10 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
if
(
ovl
->
caps
&
OMAP_DSS_OVL_CAP_SCALE
)
{
dispc_ovl_set_scaling
(
plane
,
oi
->
width
,
oi
->
height
,
o
i
->
out_width
,
oi
->
out_height
,
o
utw
,
outh
,
ilace
,
five_taps
,
fieldmode
,
oi
->
color_mode
,
oi
->
rotation
);
dispc_ovl_set_vid_size
(
plane
,
o
i
->
out_width
,
oi
->
out_height
);
dispc_ovl_set_vid_size
(
plane
,
o
utw
,
outh
);
dispc_ovl_set_vid_color_conv
(
plane
,
cconv
);
}
...
...
@@ -1891,10 +1883,7 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
dispc_ovl_set_pre_mult_alpha
(
plane
,
oi
->
pre_mult_alpha
);
dispc_ovl_setup_global_alpha
(
plane
,
oi
->
global_alpha
);
dispc_ovl_set_channel_out
(
plane
,
channel
);
dispc_ovl_enable_replication
(
plane
,
replication
);
dispc_ovl_set_fifo_threshold
(
plane
,
fifo_low
,
fifo_high
);
return
0
;
}
...
...
@@ -1916,10 +1905,14 @@ static void dispc_disable_isr(void *data, u32 mask)
static
void
_enable_lcd_out
(
enum
omap_channel
channel
,
bool
enable
)
{
if
(
channel
==
OMAP_DSS_CHANNEL_LCD2
)
if
(
channel
==
OMAP_DSS_CHANNEL_LCD2
)
{
REG_FLD_MOD
(
DISPC_CONTROL2
,
enable
?
1
:
0
,
0
,
0
);
else
/* flush posted write */
dispc_read_reg
(
DISPC_CONTROL2
);
}
else
{
REG_FLD_MOD
(
DISPC_CONTROL
,
enable
?
1
:
0
,
0
,
0
);
dispc_read_reg
(
DISPC_CONTROL
);
}
}
static
void
dispc_mgr_enable_lcd_out
(
enum
omap_channel
channel
,
bool
enable
)
...
...
@@ -1967,6 +1960,8 @@ static void dispc_mgr_enable_lcd_out(enum omap_channel channel, bool enable)
static
void
_enable_digit_out
(
bool
enable
)
{
REG_FLD_MOD
(
DISPC_CONTROL
,
enable
?
1
:
0
,
1
,
1
);
/* flush posted write */
dispc_read_reg
(
DISPC_CONTROL
);
}
static
void
dispc_mgr_enable_digit_out
(
bool
enable
)
...
...
@@ -2124,25 +2119,12 @@ void dispc_set_loadmode(enum omap_dss_load_mode mode)
}
void
dispc_mgr_set_default_color
(
enum
omap_channel
channel
,
u32
color
)
static
void
dispc_mgr_set_default_color
(
enum
omap_channel
channel
,
u32
color
)
{
dispc_write_reg
(
DISPC_DEFAULT_COLOR
(
channel
),
color
);
}
u32
dispc_mgr_get_default_color
(
enum
omap_channel
channel
)
{
u32
l
;
BUG_ON
(
channel
!=
OMAP_DSS_CHANNEL_DIGIT
&&
channel
!=
OMAP_DSS_CHANNEL_LCD
&&
channel
!=
OMAP_DSS_CHANNEL_LCD2
);
l
=
dispc_read_reg
(
DISPC_DEFAULT_COLOR
(
channel
));
return
l
;
}
void
dispc_mgr_set_trans_key
(
enum
omap_channel
ch
,
static
void
dispc_mgr_set_trans_key
(
enum
omap_channel
ch
,
enum
omap_dss_trans_key_type
type
,
u32
trans_key
)
{
...
...
@@ -2156,26 +2138,7 @@ void dispc_mgr_set_trans_key(enum omap_channel ch,
dispc_write_reg
(
DISPC_TRANS_COLOR
(
ch
),
trans_key
);
}
void
dispc_mgr_get_trans_key
(
enum
omap_channel
ch
,
enum
omap_dss_trans_key_type
*
type
,
u32
*
trans_key
)
{
if
(
type
)
{
if
(
ch
==
OMAP_DSS_CHANNEL_LCD
)
*
type
=
REG_GET
(
DISPC_CONFIG
,
11
,
11
);
else
if
(
ch
==
OMAP_DSS_CHANNEL_DIGIT
)
*
type
=
REG_GET
(
DISPC_CONFIG
,
13
,
13
);
else
if
(
ch
==
OMAP_DSS_CHANNEL_LCD2
)
*
type
=
REG_GET
(
DISPC_CONFIG2
,
11
,
11
);
else
BUG
();
}
if
(
trans_key
)
*
trans_key
=
dispc_read_reg
(
DISPC_TRANS_COLOR
(
ch
));
}
void
dispc_mgr_enable_trans_key
(
enum
omap_channel
ch
,
bool
enable
)
static
void
dispc_mgr_enable_trans_key
(
enum
omap_channel
ch
,
bool
enable
)
{
if
(
ch
==
OMAP_DSS_CHANNEL_LCD
)
REG_FLD_MOD
(
DISPC_CONFIG
,
enable
,
10
,
10
);
...
...
@@ -2185,7 +2148,8 @@ void dispc_mgr_enable_trans_key(enum omap_channel ch, bool enable)
REG_FLD_MOD
(
DISPC_CONFIG2
,
enable
,
10
,
10
);
}
void
dispc_mgr_enable_alpha_fixed_zorder
(
enum
omap_channel
ch
,
bool
enable
)
static
void
dispc_mgr_enable_alpha_fixed_zorder
(
enum
omap_channel
ch
,
bool
enable
)
{
if
(
!
dss_has_feature
(
FEAT_ALPHA_FIXED_ZORDER
))
return
;
...
...
@@ -2196,40 +2160,20 @@ void dispc_mgr_enable_alpha_fixed_zorder(enum omap_channel ch, bool enable)
REG_FLD_MOD
(
DISPC_CONFIG
,
enable
,
19
,
19
);
}
bool
dispc_mgr_alpha_fixed_zorder_enabled
(
enum
omap_channel
ch
)
{
bool
enabled
;
if
(
!
dss_has_feature
(
FEAT_ALPHA_FIXED_ZORDER
))
return
false
;
if
(
ch
==
OMAP_DSS_CHANNEL_LCD
)
enabled
=
REG_GET
(
DISPC_CONFIG
,
18
,
18
);
else
if
(
ch
==
OMAP_DSS_CHANNEL_DIGIT
)
enabled
=
REG_GET
(
DISPC_CONFIG
,
19
,
19
);
else
BUG
();
return
enabled
;
}
bool
dispc_mgr_trans_key_enabled
(
enum
omap_channel
ch
)
void
dispc_mgr_setup
(
enum
omap_channel
channel
,
struct
omap_overlay_manager_info
*
info
)
{
bool
enabled
;
if
(
ch
==
OMAP_DSS_CHANNEL_LCD
)
enabled
=
REG_GET
(
DISPC_CONFIG
,
10
,
10
);
else
if
(
ch
==
OMAP_DSS_CHANNEL_DIGIT
)
enabled
=
REG_GET
(
DISPC_CONFIG
,
12
,
12
);
else
if
(
ch
==
OMAP_DSS_CHANNEL_LCD2
)
enabled
=
REG_GET
(
DISPC_CONFIG2
,
10
,
10
);
else
BUG
();
return
enabled
;
dispc_mgr_set_default_color
(
channel
,
info
->
default_color
);
dispc_mgr_set_trans_key
(
channel
,
info
->
trans_key_type
,
info
->
trans_key
);
dispc_mgr_enable_trans_key
(
channel
,
info
->
trans_enabled
);
dispc_mgr_enable_alpha_fixed_zorder
(
channel
,
info
->
partial_alpha_enabled
);
if
(
dss_has_feature
(
FEAT_CPR
))
{
dispc_mgr_enable_cpr
(
channel
,
info
->
cpr_enable
);
dispc_mgr_set_cpr_coef
(
channel
,
&
info
->
cpr_coefs
);
}
}
void
dispc_mgr_set_tft_data_lines
(
enum
omap_channel
channel
,
u8
data_lines
)
{
int
code
;
...
...
@@ -3184,7 +3128,8 @@ static void dispc_error_worker(struct work_struct *work)
for
(
i
=
0
;
i
<
omap_dss_get_num_overlay_managers
();
++
i
)
{
struct
omap_overlay_manager
*
mgr
;
mgr
=
omap_dss_get_overlay_manager
(
i
);
mgr
->
device
->
driver
->
disable
(
mgr
->
device
);
if
(
mgr
->
device
&&
mgr
->
device
->
driver
)
mgr
->
device
->
driver
->
disable
(
mgr
->
device
);
}
}
...
...
drivers/video/omap2/dss/dispc.h
View file @
193984f4
...
...
@@ -97,6 +97,17 @@
#define DISPC_OVL_PRELOAD(n) (DISPC_OVL_BASE(n) + \
DISPC_PRELOAD_OFFSET(n))
/* DISPC up/downsampling FIR filter coefficient structure */
struct
dispc_coef
{
s8
hc4_vc22
;
s8
hc3_vc2
;
u8
hc2_vc1
;
s8
hc1_vc0
;
s8
hc0_vc00
;
};
const
struct
dispc_coef
*
dispc_ovl_get_scale_coef
(
int
inc
,
int
five_taps
);
/* DISPC manager/channel specific registers */
static
inline
u16
DISPC_DEFAULT_COLOR
(
enum
omap_channel
channel
)
{
...
...
drivers/video/omap2/dss/dispc_coefs.c
0 → 100644
View file @
193984f4
/*
* linux/drivers/video/omap2/dss/dispc_coefs.c
*
* Copyright (C) 2011 Texas Instruments
* Author: Chandrabhanu Mahapatra <cmahapatra@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, see <http://www.gnu.org/licenses/>.
*/
#include <linux/kernel.h>
#include <video/omapdss.h>
#include "dispc.h"
#define ARRAY_LEN(array) (sizeof(array) / sizeof(array[0]))
static
const
struct
dispc_coef
coef3_M8
[
8
]
=
{
{
0
,
0
,
128
,
0
,
0
},
{
0
,
-
4
,
123
,
9
,
0
},
{
0
,
-
4
,
108
,
87
,
0
},
{
0
,
-
2
,
87
,
43
,
0
},
{
0
,
64
,
64
,
0
,
0
},
{
0
,
43
,
87
,
-
2
,
0
},
{
0
,
24
,
108
,
-
4
,
0
},
{
0
,
9
,
123
,
-
4
,
0
},
};
static
const
struct
dispc_coef
coef3_M9
[
8
]
=
{
{
0
,
6
,
116
,
6
,
0
},
{
0
,
0
,
112
,
16
,
0
},
{
0
,
-
2
,
100
,
30
,
0
},
{
0
,
-
2
,
83
,
47
,
0
},
{
0
,
64
,
64
,
0
,
0
},
{
0
,
47
,
83
,
-
2
,
0
},
{
0
,
30
,
100
,
-
2
,
0
},
{
0
,
16
,
112
,
0
,
0
},
};
static
const
struct
dispc_coef
coef3_M10
[
8
]
=
{
{
0
,
10
,
108
,
10
,
0
},
{
0
,
3
,
104
,
21
,
0
},
{
0
,
0
,
94
,
34
,
0
},
{
0
,
-
1
,
80
,
49
,
0
},
{
0
,
64
,
64
,
0
,
0
},
{
0
,
49
,
80
,
-
1
,
0
},
{
0
,
34
,
94
,
0
,
0
},
{
0
,
21
,
104
,
3
,
0
},
};
static
const
struct
dispc_coef
coef3_M11
[
8
]
=
{
{
0
,
14
,
100
,
14
,
0
},
{
0
,
6
,
98
,
24
,
0
},
{
0
,
2
,
90
,
36
,
0
},
{
0
,
0
,
78
,
50
,
0
},
{
0
,
64
,
64
,
0
,
0
},
{
0
,
50
,
78
,
0
,
0
},
{
0
,
36
,
90
,
2
,
0
},
{
0
,
24
,
98
,
6
,
0
},
};
static
const
struct
dispc_coef
coef3_M12
[
8
]
=
{
{
0
,
16
,
96
,
16
,
0
},
{
0
,
9
,
93
,
26
,
0
},
{
0
,
4
,
86
,
38
,
0
},
{
0
,
1
,
76
,
51
,
0
},
{
0
,
64
,
64
,
0
,
0
},
{
0
,
51
,
76
,
1
,
0
},
{
0
,
38
,
86
,
4
,
0
},
{
0
,
26
,
93
,
9
,
0
},
};
static
const
struct
dispc_coef
coef3_M13
[
8
]
=
{
{
0
,
18
,
92
,
18
,
0
},
{
0
,
10
,
90
,
28
,
0
},
{
0
,
5
,
83
,
40
,
0
},
{
0
,
1
,
75
,
52
,
0
},
{
0
,
64
,
64
,
0
,
0
},
{
0
,
52
,
75
,
1
,
0
},
{
0
,
40
,
83
,
5
,
0
},
{
0
,
28
,
90
,
10
,
0
},
};
static
const
struct
dispc_coef
coef3_M14
[
8
]
=
{
{
0
,
20
,
88
,
20
,
0
},
{
0
,
12
,
86
,
30
,
0
},
{
0
,
6
,
81
,
41
,
0
},
{
0
,
2
,
74
,
52
,
0
},
{
0
,
64
,
64
,
0
,
0
},
{
0
,
52
,
74
,
2
,
0
},
{
0
,
41
,
81
,
6
,
0
},
{
0
,
30
,
86
,
12
,
0
},
};
static
const
struct
dispc_coef
coef3_M16
[
8
]
=
{
{
0
,
22
,
84
,
22
,
0
},
{
0
,
14
,
82
,
32
,
0
},
{
0
,
8
,
78
,
42
,
0
},
{
0
,
3
,
72
,
53
,
0
},
{
0
,
64
,
64
,
0
,
0
},
{
0
,
53
,
72
,
3
,
0
},
{
0
,
42
,
78
,
8
,
0
},
{
0
,
32
,
82
,
14
,
0
},
};
static
const
struct
dispc_coef
coef3_M19
[
8
]
=
{
{
0
,
24
,
80
,
24
,
0
},
{
0
,
16
,
79
,
33
,
0
},
{
0
,
9
,
76
,
43
,
0
},
{
0
,
4
,
70
,
54
,
0
},
{
0
,
64
,
64
,
0
,
0
},
{
0
,
54
,
70
,
4
,
0
},
{
0
,
43
,
76
,
9
,
0
},
{
0
,
33
,
79
,
16
,
0
},
};
static
const
struct
dispc_coef
coef3_M22
[
8
]
=
{
{
0
,
25
,
78
,
25
,
0
},
{
0
,
17
,
77
,
34
,
0
},
{
0
,
10
,
74
,
44
,
0
},
{
0
,
5
,
69
,
54
,
0
},
{
0
,
64
,
64
,
0
,
0
},
{
0
,
54
,
69
,
5
,
0
},
{
0
,
44
,
74
,
10
,
0
},
{
0
,
34
,
77
,
17
,
0
},
};
static
const
struct
dispc_coef
coef3_M26
[
8
]
=
{
{
0
,
26
,
76
,
26
,
0
},
{
0
,
19
,
74
,
35
,
0
},
{
0
,
11
,
72
,
45
,
0
},
{
0
,
5
,
69
,
54
,
0
},
{
0
,
64
,
64
,
0
,
0
},
{
0
,
54
,
69
,
5
,
0
},
{
0
,
45
,
72
,
11
,
0
},
{
0
,
35
,
74
,
19
,
0
},
};
static
const
struct
dispc_coef
coef3_M32
[
8
]
=
{
{
0
,
27
,
74
,
27
,
0
},
{
0
,
19
,
73
,
36
,
0
},
{
0
,
12
,
71
,
45
,
0
},
{
0
,
6
,
68
,
54
,
0
},
{
0
,
64
,
64
,
0
,
0
},
{
0
,
54
,
68
,
6
,
0
},
{
0
,
45
,
71
,
12
,
0
},
{
0
,
36
,
73
,
19
,
0
},
};
static
const
struct
dispc_coef
coef5_M8
[
8
]
=
{
{
0
,
0
,
128
,
0
,
0
},
{
-
2
,
14
,
125
,
-
10
,
1
},
{
-
6
,
33
,
114
,
-
15
,
2
},
{
-
10
,
55
,
98
,
-
16
,
1
},
{
0
,
-
14
,
78
,
78
,
-
14
},
{
1
,
-
16
,
98
,
55
,
-
10
},
{
2
,
-
15
,
114
,
33
,
-
6
},
{
1
,
-
10
,
125
,
14
,
-
2
},
};
static
const
struct
dispc_coef
coef5_M9
[
8
]
=
{
{
-
3
,
10
,
114
,
10
,
-
3
},
{
-
6
,
24
,
110
,
0
,
-
1
},
{
-
8
,
40
,
103
,
-
7
,
0
},
{
-
11
,
58
,
91
,
-
11
,
1
},
{
0
,
-
12
,
76
,
76
,
-
12
},
{
1
,
-
11
,
91
,
58
,
-
11
},
{
0
,
-
7
,
103
,
40
,
-
8
},
{
-
1
,
0
,
111
,
24
,
-
6
},
};
static
const
struct
dispc_coef
coef5_M10
[
8
]
=
{
{
-
4
,
18
,
100
,
18
,
-
4
},
{
-
6
,
30
,
99
,
8
,
-
3
},
{
-
8
,
44
,
93
,
0
,
-
1
},
{
-
9
,
58
,
84
,
-
5
,
0
},
{
0
,
-
8
,
72
,
72
,
-
8
},
{
0
,
-
5
,
84
,
58
,
-
9
},
{
-
1
,
0
,
93
,
44
,
-
8
},
{
-
3
,
8
,
99
,
30
,
-
6
},
};
static
const
struct
dispc_coef
coef5_M11
[
8
]
=
{
{
-
5
,
23
,
92
,
23
,
-
5
},
{
-
6
,
34
,
90
,
13
,
-
3
},
{
-
6
,
45
,
85
,
6
,
-
2
},
{
-
6
,
57
,
78
,
0
,
-
1
},
{
0
,
-
4
,
68
,
68
,
-
4
},
{
-
1
,
0
,
78
,
57
,
-
6
},
{
-
2
,
6
,
85
,
45
,
-
6
},
{
-
3
,
13
,
90
,
34
,
-
6
},
};
static
const
struct
dispc_coef
coef5_M12
[
8
]
=
{
{
-
4
,
26
,
84
,
26
,
-
4
},
{
-
5
,
36
,
82
,
18
,
-
3
},
{
-
4
,
46
,
78
,
10
,
-
2
},
{
-
3
,
55
,
72
,
5
,
-
1
},
{
0
,
0
,
64
,
64
,
0
},
{
-
1
,
5
,
72
,
55
,
-
3
},
{
-
2
,
10
,
78
,
46
,
-
4
},
{
-
3
,
18
,
82
,
36
,
-
5
},
};
static
const
struct
dispc_coef
coef5_M13
[
8
]
=
{
{
-
3
,
28
,
78
,
28
,
-
3
},
{
-
3
,
37
,
76
,
21
,
-
3
},
{
-
2
,
45
,
73
,
14
,
-
2
},
{
0
,
53
,
68
,
8
,
-
1
},
{
0
,
3
,
61
,
61
,
3
},
{
-
1
,
8
,
68
,
53
,
0
},
{
-
2
,
14
,
73
,
45
,
-
2
},
{
-
3
,
21
,
76
,
37
,
-
3
},
};
static
const
struct
dispc_coef
coef5_M14
[
8
]
=
{
{
-
2
,
30
,
72
,
30
,
-
2
},
{
-
1
,
37
,
71
,
23
,
-
2
},
{
0
,
45
,
69
,
16
,
-
2
},
{
3
,
52
,
64
,
10
,
-
1
},
{
0
,
6
,
58
,
58
,
6
},
{
-
1
,
10
,
64
,
52
,
3
},
{
-
2
,
16
,
69
,
45
,
0
},
{
-
2
,
23
,
71
,
37
,
-
1
},
};
static
const
struct
dispc_coef
coef5_M16
[
8
]
=
{
{
0
,
31
,
66
,
31
,
0
},
{
1
,
38
,
65
,
25
,
-
1
},
{
3
,
44
,
62
,
20
,
-
1
},
{
6
,
49
,
59
,
14
,
0
},
{
0
,
10
,
54
,
54
,
10
},
{
0
,
14
,
59
,
49
,
6
},
{
-
1
,
20
,
62
,
44
,
3
},
{
-
1
,
25
,
65
,
38
,
1
},
};
static
const
struct
dispc_coef
coef5_M19
[
8
]
=
{
{
3
,
32
,
58
,
32
,
3
},
{
4
,
38
,
58
,
27
,
1
},
{
7
,
42
,
55
,
23
,
1
},
{
10
,
46
,
54
,
18
,
0
},
{
0
,
14
,
50
,
50
,
14
},
{
0
,
18
,
54
,
46
,
10
},
{
1
,
23
,
55
,
42
,
7
},
{
1
,
27
,
58
,
38
,
4
},
};
static
const
struct
dispc_coef
coef5_M22
[
8
]
=
{
{
4
,
33
,
54
,
33
,
4
},
{
6
,
37
,
54
,
28
,
3
},
{
9
,
41
,
53
,
24
,
1
},
{
12
,
45
,
51
,
20
,
0
},
{
0
,
16
,
48
,
48
,
16
},
{
0
,
20
,
51
,
45
,
12
},
{
1
,
24
,
53
,
41
,
9
},
{
3
,
28
,
54
,
37
,
6
},
};
static
const
struct
dispc_coef
coef5_M26
[
8
]
=
{
{
6
,
33
,
50
,
33
,
6
},
{
8
,
36
,
51
,
29
,
4
},
{
11
,
40
,
50
,
25
,
2
},
{
14
,
43
,
48
,
22
,
1
},
{
0
,
18
,
46
,
46
,
18
},
{
1
,
22
,
48
,
43
,
14
},
{
2
,
25
,
50
,
40
,
11
},
{
4
,
29
,
51
,
36
,
8
},
};
static
const
struct
dispc_coef
coef5_M32
[
8
]
=
{
{
7
,
33
,
48
,
33
,
7
},
{
10
,
36
,
48
,
29
,
5
},
{
13
,
39
,
47
,
26
,
3
},
{
16
,
42
,
46
,
23
,
1
},
{
0
,
19
,
45
,
45
,
19
},
{
1
,
23
,
46
,
42
,
16
},
{
3
,
26
,
47
,
39
,
13
},
{
5
,
29
,
48
,
36
,
10
},
};
const
struct
dispc_coef
*
dispc_ovl_get_scale_coef
(
int
inc
,
int
five_taps
)
{
int
i
;
static
const
struct
{
int
Mmin
;
int
Mmax
;
const
struct
dispc_coef
*
coef_3
;
const
struct
dispc_coef
*
coef_5
;
}
coefs
[]
=
{
{
27
,
32
,
coef3_M32
,
coef5_M32
},
{
23
,
26
,
coef3_M26
,
coef5_M26
},
{
20
,
22
,
coef3_M22
,
coef5_M22
},
{
17
,
19
,
coef3_M19
,
coef5_M19
},
{
15
,
16
,
coef3_M16
,
coef5_M16
},
{
14
,
14
,
coef3_M14
,
coef5_M14
},
{
13
,
13
,
coef3_M13
,
coef5_M13
},
{
12
,
12
,
coef3_M12
,
coef5_M12
},
{
11
,
11
,
coef3_M11
,
coef5_M11
},
{
10
,
10
,
coef3_M10
,
coef5_M10
},
{
9
,
9
,
coef3_M9
,
coef5_M9
},
{
4
,
8
,
coef3_M8
,
coef5_M8
},
/*
* When upscaling more than two times, blockiness and outlines
* around the image are observed when M8 tables are used. M11,
* M16 and M19 tables are used to prevent this.
*/
{
3
,
3
,
coef3_M11
,
coef5_M11
},
{
2
,
2
,
coef3_M16
,
coef5_M16
},
{
0
,
1
,
coef3_M19
,
coef5_M19
},
};
inc
/=
128
;
for
(
i
=
0
;
i
<
ARRAY_LEN
(
coefs
);
++
i
)
if
(
inc
>=
coefs
[
i
].
Mmin
&&
inc
<=
coefs
[
i
].
Mmax
)
return
five_taps
?
coefs
[
i
].
coef_5
:
coefs
[
i
].
coef_3
;
return
NULL
;
}
drivers/video/omap2/dss/dpi.c
View file @
193984f4
...
...
@@ -223,10 +223,13 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
mdelay
(
2
);
dssdev
->
manager
->
enable
(
dssdev
->
manager
);
r
=
dss_mgr_enable
(
dssdev
->
manager
);
if
(
r
)
goto
err_mgr_enable
;
return
0
;
err_mgr_enable:
err_set_mode:
if
(
dpi_use_dsi_pll
(
dssdev
))
dsi_pll_uninit
(
dpi
.
dsidev
,
true
);
...
...
@@ -249,7 +252,7 @@ EXPORT_SYMBOL(omapdss_dpi_display_enable);
void
omapdss_dpi_display_disable
(
struct
omap_dss_device
*
dssdev
)
{
dss
dev
->
manager
->
disable
(
dssdev
->
manager
);
dss
_mgr_
disable
(
dssdev
->
manager
);
if
(
dpi_use_dsi_pll
(
dssdev
))
{
dss_select_dispc_clk_source
(
OMAP_DSS_CLK_SRC_FCK
);
...
...
drivers/video/omap2/dss/dsi.c
View file @
193984f4
...
...
@@ -203,6 +203,21 @@ struct dsi_reg { u16 idx; };
typedef
void
(
*
omap_dsi_isr_t
)
(
void
*
arg
,
u32
mask
);
#define DSI_MAX_NR_ISRS 2
#define DSI_MAX_NR_LANES 5
enum
dsi_lane_function
{
DSI_LANE_UNUSED
=
0
,
DSI_LANE_CLK
,
DSI_LANE_DATA1
,
DSI_LANE_DATA2
,
DSI_LANE_DATA3
,
DSI_LANE_DATA4
,
};
struct
dsi_lane_config
{
enum
dsi_lane_function
function
;
u8
polarity
;
};
struct
dsi_isr_data
{
omap_dsi_isr_t
isr
;
...
...
@@ -223,24 +238,6 @@ enum dsi_vc_source {
DSI_VC_SOURCE_VP
,
};
enum
dsi_lane
{
DSI_CLK_P
=
1
<<
0
,
DSI_CLK_N
=
1
<<
1
,
DSI_DATA1_P
=
1
<<
2
,
DSI_DATA1_N
=
1
<<
3
,
DSI_DATA2_P
=
1
<<
4
,
DSI_DATA2_N
=
1
<<
5
,
DSI_DATA3_P
=
1
<<
6
,
DSI_DATA3_N
=
1
<<
7
,
DSI_DATA4_P
=
1
<<
8
,
DSI_DATA4_N
=
1
<<
9
,
};
struct
dsi_update_region
{
u16
x
,
y
,
w
,
h
;
struct
omap_dss_device
*
device
;
};
struct
dsi_irq_stats
{
unsigned
long
last_reset
;
unsigned
irq_count
;
...
...
@@ -290,7 +287,9 @@ struct dsi_data {
struct
dsi_isr_tables
isr_tables_copy
;
int
update_channel
;
struct
dsi_update_region
update_region
;
#ifdef DEBUG
unsigned
update_bytes
;
#endif
bool
te_enabled
;
bool
ulps_enabled
;
...
...
@@ -327,7 +326,10 @@ struct dsi_data {
unsigned
long
fint_min
,
fint_max
;
unsigned
long
lpdiv_max
;
int
num_data_lanes
;
unsigned
num_lanes_supported
;
struct
dsi_lane_config
lanes
[
DSI_MAX_NR_LANES
];
unsigned
num_lanes_used
;
unsigned
scp_clk_refcount
;
};
...
...
@@ -413,14 +415,29 @@ static void dsi_completion_handler(void *data, u32 mask)
static
inline
int
wait_for_bit_change
(
struct
platform_device
*
dsidev
,
const
struct
dsi_reg
idx
,
int
bitnum
,
int
value
)
{
int
t
=
100000
;
unsigned
long
timeout
;
ktime_t
wait
;
int
t
;
while
(
REG_GET
(
dsidev
,
idx
,
bitnum
,
bitnum
)
!=
value
)
{
if
(
--
t
==
0
)
return
!
value
;
/* first busyloop to see if the bit changes right away */
t
=
100
;
while
(
t
--
>
0
)
{
if
(
REG_GET
(
dsidev
,
idx
,
bitnum
,
bitnum
)
==
value
)
return
value
;
}
return
value
;
/* then loop for 500ms, sleeping for 1ms in between */
timeout
=
jiffies
+
msecs_to_jiffies
(
500
);
while
(
time_before
(
jiffies
,
timeout
))
{
if
(
REG_GET
(
dsidev
,
idx
,
bitnum
,
bitnum
)
==
value
)
return
value
;
wait
=
ns_to_ktime
(
1000
*
1000
);
set_current_state
(
TASK_UNINTERRUPTIBLE
);
schedule_hrtimeout
(
&
wait
,
HRTIMER_MODE_REL
);
}
return
!
value
;
}
u8
dsi_get_pixel_size
(
enum
omap_dss_dsi_pixel_format
fmt
)
...
...
@@ -454,7 +471,6 @@ static void dsi_perf_mark_start(struct platform_device *dsidev)
static
void
dsi_perf_show
(
struct
platform_device
*
dsidev
,
const
char
*
name
)
{
struct
dsi_data
*
dsi
=
dsi_get_dsidrv_data
(
dsidev
);
struct
omap_dss_device
*
dssdev
=
dsi
->
update_region
.
device
;
ktime_t
t
,
setup_time
,
trans_time
;
u32
total_bytes
;
u32
setup_us
,
trans_us
,
total_us
;
...
...
@@ -476,9 +492,7 @@ static void dsi_perf_show(struct platform_device *dsidev, const char *name)
total_us
=
setup_us
+
trans_us
;
total_bytes
=
dsi
->
update_region
.
w
*
dsi
->
update_region
.
h
*
dsi_get_pixel_size
(
dssdev
->
panel
.
dsi_pix_fmt
)
/
8
;
total_bytes
=
dsi
->
update_bytes
;
printk
(
KERN_INFO
"DSI(%s): %u us + %u us = %u us (%uHz), "
"%u bytes, %u kbytes/sec
\n
"
,
...
...
@@ -1720,17 +1734,19 @@ static void dsi_dump_dsidev_clocks(struct platform_device *dsidev,
seq_printf
(
s
,
"CLKIN4DDR
\t
%-16luregm %u
\n
"
,
cinfo
->
clkin4ddr
,
cinfo
->
regm
);
seq_printf
(
s
,
"%s (%s)
\t
%-16luregm_dispc %u
\t
(%s)
\n
"
,
dss_get_generic_clk_source_name
(
dispc_clk_src
),
dss_feat_get_clk_source_name
(
dispc_clk_src
),
seq_printf
(
s
,
"DSI_PLL_HSDIV_DISPC (%s)
\t
%-16luregm_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
,
dispc_clk_src
==
OMAP_DSS_CLK_SRC_FCK
?
"off"
:
"on"
);
seq_printf
(
s
,
"%s (%s)
\t
%-16luregm_dsi %u
\t
(%s)
\n
"
,
dss_get_generic_clk_source_name
(
dsi_clk_src
),
dss_feat_get_clk_source_name
(
dsi_clk_src
),
seq_printf
(
s
,
"DSI_PLL_HSDIV_DSI (%s)
\t
%-16luregm_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
,
dsi_clk_src
==
OMAP_DSS_CLK_SRC_FCK
?
...
...
@@ -2029,34 +2045,6 @@ static int dsi_cio_power(struct platform_device *dsidev,
return
0
;
}
/* Number of data lanes present on DSI interface */
static
inline
int
dsi_get_num_data_lanes
(
struct
platform_device
*
dsidev
)
{
/* DSI on OMAP3 doesn't have register DSI_GNQ, set number
* of data lanes as 2 by default */
if
(
dss_has_feature
(
FEAT_DSI_GNQ
))
return
REG_GET
(
dsidev
,
DSI_GNQ
,
11
,
9
);
/* NB_DATA_LANES */
else
return
2
;
}
/* Number of data lanes used by the dss device */
static
inline
int
dsi_get_num_data_lanes_dssdev
(
struct
omap_dss_device
*
dssdev
)
{
int
num_data_lanes
=
0
;
if
(
dssdev
->
phy
.
dsi
.
data1_lane
!=
0
)
num_data_lanes
++
;
if
(
dssdev
->
phy
.
dsi
.
data2_lane
!=
0
)
num_data_lanes
++
;
if
(
dssdev
->
phy
.
dsi
.
data3_lane
!=
0
)
num_data_lanes
++
;
if
(
dssdev
->
phy
.
dsi
.
data4_lane
!=
0
)
num_data_lanes
++
;
return
num_data_lanes
;
}
static
unsigned
dsi_get_line_buf_size
(
struct
platform_device
*
dsidev
)
{
int
val
;
...
...
@@ -2088,59 +2076,112 @@ static unsigned dsi_get_line_buf_size(struct platform_device *dsidev)
}
}
static
void
dsi_set
_lane_config
(
struct
omap_dss_device
*
dssdev
)
static
int
dsi_parse
_lane_config
(
struct
omap_dss_device
*
dssdev
)
{
struct
platform_device
*
dsidev
=
dsi_get_dsidev_from_dssdev
(
dssdev
);
u32
r
;
int
num_data_lanes_dssdev
=
dsi_get_num_data_lanes_dssdev
(
dssdev
);
struct
dsi_data
*
dsi
=
dsi_get_dsidrv_data
(
dsidev
);
u8
lanes
[
DSI_MAX_NR_LANES
];
u8
polarities
[
DSI_MAX_NR_LANES
];
int
num_lanes
,
i
;
static
const
enum
dsi_lane_function
functions
[]
=
{
DSI_LANE_CLK
,
DSI_LANE_DATA1
,
DSI_LANE_DATA2
,
DSI_LANE_DATA3
,
DSI_LANE_DATA4
,
};
lanes
[
0
]
=
dssdev
->
phy
.
dsi
.
clk_lane
;
lanes
[
1
]
=
dssdev
->
phy
.
dsi
.
data1_lane
;
lanes
[
2
]
=
dssdev
->
phy
.
dsi
.
data2_lane
;
lanes
[
3
]
=
dssdev
->
phy
.
dsi
.
data3_lane
;
lanes
[
4
]
=
dssdev
->
phy
.
dsi
.
data4_lane
;
polarities
[
0
]
=
dssdev
->
phy
.
dsi
.
clk_pol
;
polarities
[
1
]
=
dssdev
->
phy
.
dsi
.
data1_pol
;
polarities
[
2
]
=
dssdev
->
phy
.
dsi
.
data2_pol
;
polarities
[
3
]
=
dssdev
->
phy
.
dsi
.
data3_pol
;
polarities
[
4
]
=
dssdev
->
phy
.
dsi
.
data4_pol
;
int
clk_lane
=
dssdev
->
phy
.
dsi
.
clk_lane
;
int
data1_lane
=
dssdev
->
phy
.
dsi
.
data1_lane
;
int
data2_lane
=
dssdev
->
phy
.
dsi
.
data2_lane
;
int
clk_pol
=
dssdev
->
phy
.
dsi
.
clk_pol
;
int
data1_pol
=
dssdev
->
phy
.
dsi
.
data1_pol
;
int
data2_pol
=
dssdev
->
phy
.
dsi
.
data2_pol
;
num_lanes
=
0
;
for
(
i
=
0
;
i
<
dsi
->
num_lanes_supported
;
++
i
)
dsi
->
lanes
[
i
].
function
=
DSI_LANE_UNUSED
;
for
(
i
=
0
;
i
<
dsi
->
num_lanes_supported
;
++
i
)
{
int
num
;
if
(
lanes
[
i
]
==
DSI_LANE_UNUSED
)
break
;
num
=
lanes
[
i
]
-
1
;
if
(
num
>=
dsi
->
num_lanes_supported
)
return
-
EINVAL
;
if
(
dsi
->
lanes
[
num
].
function
!=
DSI_LANE_UNUSED
)
return
-
EINVAL
;
dsi
->
lanes
[
num
].
function
=
functions
[
i
];
dsi
->
lanes
[
num
].
polarity
=
polarities
[
i
];
num_lanes
++
;
}
if
(
num_lanes
<
2
||
num_lanes
>
dsi
->
num_lanes_supported
)
return
-
EINVAL
;
dsi
->
num_lanes_used
=
num_lanes
;
return
0
;
}
static
int
dsi_set_lane_config
(
struct
omap_dss_device
*
dssdev
)
{
struct
platform_device
*
dsidev
=
dsi_get_dsidev_from_dssdev
(
dssdev
);
struct
dsi_data
*
dsi
=
dsi_get_dsidrv_data
(
dsidev
);
static
const
u8
offsets
[]
=
{
0
,
4
,
8
,
12
,
16
};
static
const
enum
dsi_lane_function
functions
[]
=
{
DSI_LANE_CLK
,
DSI_LANE_DATA1
,
DSI_LANE_DATA2
,
DSI_LANE_DATA3
,
DSI_LANE_DATA4
,
};
u32
r
;
int
i
;
r
=
dsi_read_reg
(
dsidev
,
DSI_COMPLEXIO_CFG1
);
r
=
FLD_MOD
(
r
,
clk_lane
,
2
,
0
);
r
=
FLD_MOD
(
r
,
clk_pol
,
3
,
3
);
r
=
FLD_MOD
(
r
,
data1_lane
,
6
,
4
);
r
=
FLD_MOD
(
r
,
data1_pol
,
7
,
7
);
r
=
FLD_MOD
(
r
,
data2_lane
,
10
,
8
);
r
=
FLD_MOD
(
r
,
data2_pol
,
11
,
11
);
if
(
num_data_lanes_dssdev
>
2
)
{
int
data3_lane
=
dssdev
->
phy
.
dsi
.
data3_lane
;
int
data3_pol
=
dssdev
->
phy
.
dsi
.
data3_pol
;
r
=
FLD_MOD
(
r
,
data3_lane
,
14
,
12
);
r
=
FLD_MOD
(
r
,
data3_pol
,
15
,
15
);
for
(
i
=
0
;
i
<
dsi
->
num_lanes_used
;
++
i
)
{
unsigned
offset
=
offsets
[
i
];
unsigned
polarity
,
lane_number
;
unsigned
t
;
for
(
t
=
0
;
t
<
dsi
->
num_lanes_supported
;
++
t
)
if
(
dsi
->
lanes
[
t
].
function
==
functions
[
i
])
break
;
if
(
t
==
dsi
->
num_lanes_supported
)
return
-
EINVAL
;
lane_number
=
t
;
polarity
=
dsi
->
lanes
[
t
].
polarity
;
r
=
FLD_MOD
(
r
,
lane_number
+
1
,
offset
+
2
,
offset
);
r
=
FLD_MOD
(
r
,
polarity
,
offset
+
3
,
offset
+
3
);
}
if
(
num_data_lanes_dssdev
>
3
)
{
int
data4_lane
=
dssdev
->
phy
.
dsi
.
data4_lane
;
int
data4_pol
=
dssdev
->
phy
.
dsi
.
data4_pol
;
r
=
FLD_MOD
(
r
,
data4_lane
,
18
,
16
);
r
=
FLD_MOD
(
r
,
data4_pol
,
19
,
19
);
/* clear the unused lanes */
for
(;
i
<
dsi
->
num_lanes_supported
;
++
i
)
{
unsigned
offset
=
offsets
[
i
];
r
=
FLD_MOD
(
r
,
0
,
offset
+
2
,
offset
);
r
=
FLD_MOD
(
r
,
0
,
offset
+
3
,
offset
+
3
);
}
dsi_write_reg
(
dsidev
,
DSI_COMPLEXIO_CFG1
,
r
);
/* The configuration of the DSI complex I/O (number of data lanes,
position, differential order) should not be changed while
DSS.DSI_CLK_CRTRL[20] LP_CLK_ENABLE bit is set to 1. In order for
the hardware to take into account a new configuration of the complex
I/O (done in DSS.DSI_COMPLEXIO_CFG1 register), it is recommended to
follow this sequence: First set the DSS.DSI_CTRL[0] IF_EN bit to 1,
then reset the DSS.DSI_CTRL[0] IF_EN to 0, then set
DSS.DSI_CLK_CTRL[20] LP_CLK_ENABLE to 1 and finally set again the
DSS.DSI_CTRL[0] IF_EN bit to 1. If the sequence is not followed, the
DSI complex I/O configuration is unknown. */
dsi_write_reg
(
dsidev
,
DSI_COMPLEXIO_CFG1
,
r
);
/*
REG_FLD_MOD(dsidev, DSI_CTRL, 1, 0, 0);
REG_FLD_MOD(dsidev, DSI_CTRL, 0, 0, 0);
REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 1, 20, 20);
REG_FLD_MOD(dsidev, DSI_CTRL, 1, 0, 0);
*/
return
0
;
}
static
inline
unsigned
ns2ddr
(
struct
platform_device
*
dsidev
,
unsigned
ns
)
...
...
@@ -2230,49 +2271,28 @@ static void dsi_cio_timings(struct platform_device *dsidev)
dsi_write_reg
(
dsidev
,
DSI_DSIPHY_CFG2
,
r
);
}
/* lane masks have lane 0 at lsb. mask_p for positive lines, n for negative */
static
void
dsi_cio_enable_lane_override
(
struct
omap_dss_device
*
dssdev
,
enum
dsi_lane
lanes
)
unsigned
mask_p
,
unsigned
mask_n
)
{
struct
platform_device
*
dsidev
=
dsi_get_dsidev_from_dssdev
(
dssdev
);
struct
dsi_data
*
dsi
=
dsi_get_dsidrv_data
(
dsidev
);
int
clk_lane
=
dssdev
->
phy
.
dsi
.
clk_lane
;
int
data1_lane
=
dssdev
->
phy
.
dsi
.
data1_lane
;
int
data2_lane
=
dssdev
->
phy
.
dsi
.
data2_lane
;
int
data3_lane
=
dssdev
->
phy
.
dsi
.
data3_lane
;
int
data4_lane
=
dssdev
->
phy
.
dsi
.
data4_lane
;
int
clk_pol
=
dssdev
->
phy
.
dsi
.
clk_pol
;
int
data1_pol
=
dssdev
->
phy
.
dsi
.
data1_pol
;
int
data2_pol
=
dssdev
->
phy
.
dsi
.
data2_pol
;
int
data3_pol
=
dssdev
->
phy
.
dsi
.
data3_pol
;
int
data4_pol
=
dssdev
->
phy
.
dsi
.
data4_pol
;
u32
l
=
0
;
u8
lptxscp_start
=
dsi
->
num_data_lanes
==
2
?
22
:
26
;
if
(
lanes
&
DSI_CLK_P
)
l
|=
1
<<
((
clk_lane
-
1
)
*
2
+
(
clk_pol
?
0
:
1
));
if
(
lanes
&
DSI_CLK_N
)
l
|=
1
<<
((
clk_lane
-
1
)
*
2
+
(
clk_pol
?
1
:
0
));
if
(
lanes
&
DSI_DATA1_P
)
l
|=
1
<<
((
data1_lane
-
1
)
*
2
+
(
data1_pol
?
0
:
1
));
if
(
lanes
&
DSI_DATA1_N
)
l
|=
1
<<
((
data1_lane
-
1
)
*
2
+
(
data1_pol
?
1
:
0
));
if
(
lanes
&
DSI_DATA2_P
)
l
|=
1
<<
((
data2_lane
-
1
)
*
2
+
(
data2_pol
?
0
:
1
));
if
(
lanes
&
DSI_DATA2_N
)
l
|=
1
<<
((
data2_lane
-
1
)
*
2
+
(
data2_pol
?
1
:
0
));
if
(
lanes
&
DSI_DATA3_P
)
l
|=
1
<<
((
data3_lane
-
1
)
*
2
+
(
data3_pol
?
0
:
1
));
if
(
lanes
&
DSI_DATA3_N
)
l
|=
1
<<
((
data3_lane
-
1
)
*
2
+
(
data3_pol
?
1
:
0
));
if
(
lanes
&
DSI_DATA4_P
)
l
|=
1
<<
((
data4_lane
-
1
)
*
2
+
(
data4_pol
?
0
:
1
));
if
(
lanes
&
DSI_DATA4_N
)
l
|=
1
<<
((
data4_lane
-
1
)
*
2
+
(
data4_pol
?
1
:
0
));
int
i
;
u32
l
;
u8
lptxscp_start
=
dsi
->
num_lanes_supported
==
3
?
22
:
26
;
l
=
0
;
for
(
i
=
0
;
i
<
dsi
->
num_lanes_supported
;
++
i
)
{
unsigned
p
=
dsi
->
lanes
[
i
].
polarity
;
if
(
mask_p
&
(
1
<<
i
))
l
|=
1
<<
(
i
*
2
+
(
p
?
0
:
1
));
if
(
mask_n
&
(
1
<<
i
))
l
|=
1
<<
(
i
*
2
+
(
p
?
1
:
0
));
}
/*
* Bits in REGLPTXSCPDAT4TO0DXDY:
* 17: DY0 18: DX0
...
...
@@ -2305,51 +2325,40 @@ static void dsi_cio_disable_lane_override(struct platform_device *dsidev)
static
int
dsi_cio_wait_tx_clk_esc_reset
(
struct
omap_dss_device
*
dssdev
)
{
struct
platform_device
*
dsidev
=
dsi_get_dsidev_from_dssdev
(
dssdev
);
int
t
;
int
bits
[
3
];
bool
in_use
[
3
];
if
(
dss_has_feature
(
FEAT_DSI_REVERSE_TXCLKESC
))
{
bits
[
0
]
=
28
;
bits
[
1
]
=
27
;
bits
[
2
]
=
26
;
}
else
{
bits
[
0
]
=
24
;
bits
[
1
]
=
25
;
bits
[
2
]
=
26
;
}
in_use
[
0
]
=
false
;
in_use
[
1
]
=
false
;
in_use
[
2
]
=
false
;
struct
dsi_data
*
dsi
=
dsi_get_dsidrv_data
(
dsidev
);
int
t
,
i
;
bool
in_use
[
DSI_MAX_NR_LANES
];
static
const
u8
offsets_old
[]
=
{
28
,
27
,
26
};
static
const
u8
offsets_new
[]
=
{
24
,
25
,
26
,
27
,
28
};
const
u8
*
offsets
;
if
(
dss_has_feature
(
FEAT_DSI_REVERSE_TXCLKESC
))
offsets
=
offsets_old
;
else
offsets
=
offsets_new
;
if
(
dssdev
->
phy
.
dsi
.
clk_lane
!=
0
)
in_use
[
dssdev
->
phy
.
dsi
.
clk_lane
-
1
]
=
true
;
if
(
dssdev
->
phy
.
dsi
.
data1_lane
!=
0
)
in_use
[
dssdev
->
phy
.
dsi
.
data1_lane
-
1
]
=
true
;
if
(
dssdev
->
phy
.
dsi
.
data2_lane
!=
0
)
in_use
[
dssdev
->
phy
.
dsi
.
data2_lane
-
1
]
=
true
;
for
(
i
=
0
;
i
<
dsi
->
num_lanes_supported
;
++
i
)
in_use
[
i
]
=
dsi
->
lanes
[
i
].
function
!=
DSI_LANE_UNUSED
;
t
=
100000
;
while
(
true
)
{
u32
l
;
int
i
;
int
ok
;
l
=
dsi_read_reg
(
dsidev
,
DSI_DSIPHY_CFG5
);
ok
=
0
;
for
(
i
=
0
;
i
<
3
;
++
i
)
{
if
(
!
in_use
[
i
]
||
(
l
&
(
1
<<
bi
ts
[
i
])))
for
(
i
=
0
;
i
<
dsi
->
num_lanes_supported
;
++
i
)
{
if
(
!
in_use
[
i
]
||
(
l
&
(
1
<<
offse
ts
[
i
])))
ok
++
;
}
if
(
ok
==
3
)
if
(
ok
==
dsi
->
num_lanes_supported
)
break
;
if
(
--
t
==
0
)
{
for
(
i
=
0
;
i
<
3
;
++
i
)
{
if
(
!
in_use
[
i
]
||
(
l
&
(
1
<<
bi
ts
[
i
])))
for
(
i
=
0
;
i
<
dsi
->
num_lanes_supported
;
++
i
)
{
if
(
!
in_use
[
i
]
||
(
l
&
(
1
<<
offse
ts
[
i
])))
continue
;
DSSERR
(
"CIO TXCLKESC%d domain not coming "
\
...
...
@@ -2362,22 +2371,20 @@ static int dsi_cio_wait_tx_clk_esc_reset(struct omap_dss_device *dssdev)
return
0
;
}
/* return bitmask of enabled lanes, lane0 being the lsb */
static
unsigned
dsi_get_lane_mask
(
struct
omap_dss_device
*
dssdev
)
{
unsigned
lanes
=
0
;
struct
platform_device
*
dsidev
=
dsi_get_dsidev_from_dssdev
(
dssdev
);
struct
dsi_data
*
dsi
=
dsi_get_dsidrv_data
(
dsidev
);
unsigned
mask
=
0
;
int
i
;
if
(
dssdev
->
phy
.
dsi
.
clk_lane
!=
0
)
lanes
|=
1
<<
(
dssdev
->
phy
.
dsi
.
clk_lane
-
1
);
if
(
dssdev
->
phy
.
dsi
.
data1_lane
!=
0
)
lanes
|=
1
<<
(
dssdev
->
phy
.
dsi
.
data1_lane
-
1
);
if
(
dssdev
->
phy
.
dsi
.
data2_lane
!=
0
)
lanes
|=
1
<<
(
dssdev
->
phy
.
dsi
.
data2_lane
-
1
);
if
(
dssdev
->
phy
.
dsi
.
data3_lane
!=
0
)
lanes
|=
1
<<
(
dssdev
->
phy
.
dsi
.
data3_lane
-
1
);
if
(
dssdev
->
phy
.
dsi
.
data4_lane
!=
0
)
lanes
|=
1
<<
(
dssdev
->
phy
.
dsi
.
data4_lane
-
1
);
for
(
i
=
0
;
i
<
dsi
->
num_lanes_supported
;
++
i
)
{
if
(
dsi
->
lanes
[
i
].
function
!=
DSI_LANE_UNUSED
)
mask
|=
1
<<
i
;
}
return
lanes
;
return
mask
;
}
static
int
dsi_cio_init
(
struct
omap_dss_device
*
dssdev
)
...
...
@@ -2385,7 +2392,6 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)
struct
platform_device
*
dsidev
=
dsi_get_dsidev_from_dssdev
(
dssdev
);
struct
dsi_data
*
dsi
=
dsi_get_dsidrv_data
(
dsidev
);
int
r
;
int
num_data_lanes_dssdev
=
dsi_get_num_data_lanes_dssdev
(
dssdev
);
u32
l
;
DSSDBGF
();
...
...
@@ -2407,7 +2413,9 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)
goto
err_scp_clk_dom
;
}
dsi_set_lane_config
(
dssdev
);
r
=
dsi_set_lane_config
(
dssdev
);
if
(
r
)
goto
err_scp_clk_dom
;
/* set TX STOP MODE timer to maximum for this operation */
l
=
dsi_read_reg
(
dsidev
,
DSI_TIMING1
);
...
...
@@ -2418,7 +2426,8 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)
dsi_write_reg
(
dsidev
,
DSI_TIMING1
,
l
);
if
(
dsi
->
ulps_enabled
)
{
u32
lane_mask
=
DSI_CLK_P
|
DSI_DATA1_P
|
DSI_DATA2_P
;
unsigned
mask_p
;
int
i
;
DSSDBG
(
"manual ulps exit
\n
"
);
...
...
@@ -2427,16 +2436,19 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)
* ULPS exit sequence, as after reset the DSS HW thinks
* that we are not in ULPS mode, and refuses to send the
* sequence. So we need to send the ULPS exit sequence
* manually.
* manually by setting positive lines high and negative lines
* low for 1ms.
*/
if
(
num_data_lanes_dssdev
>
2
)
lane_mask
|=
DSI_DATA3_P
;
mask_p
=
0
;
if
(
num_data_lanes_dssdev
>
3
)
lane_mask
|=
DSI_DATA4_P
;
for
(
i
=
0
;
i
<
dsi
->
num_lanes_supported
;
++
i
)
{
if
(
dsi
->
lanes
[
i
].
function
==
DSI_LANE_UNUSED
)
continue
;
mask_p
|=
1
<<
i
;
}
dsi_cio_enable_lane_override
(
dssdev
,
lane_mask
);
dsi_cio_enable_lane_override
(
dssdev
,
mask_p
,
0
);
}
r
=
dsi_cio_power
(
dsidev
,
DSI_COMPLEXIO_POWER_ON
);
...
...
@@ -2913,6 +2925,9 @@ static int dsi_vc_send_bta(struct platform_device *dsidev, int channel)
REG_FLD_MOD
(
dsidev
,
DSI_VC_CTRL
(
channel
),
1
,
6
,
6
);
/* BTA_EN */
/* flush posted write */
dsi_read_reg
(
dsidev
,
DSI_VC_CTRL
(
channel
));
return
0
;
}
...
...
@@ -3513,7 +3528,8 @@ static int dsi_enter_ulps(struct platform_device *dsidev)
{
struct
dsi_data
*
dsi
=
dsi_get_dsidrv_data
(
dsidev
);
DECLARE_COMPLETION_ONSTACK
(
completion
);
int
r
;
int
r
,
i
;
unsigned
mask
;
DSSDBGF
();
...
...
@@ -3524,9 +3540,11 @@ static int dsi_enter_ulps(struct platform_device *dsidev)
if
(
dsi
->
ulps_enabled
)
return
0
;
/* DDR_CLK_ALWAYS_ON */
if
(
REG_GET
(
dsidev
,
DSI_CLK_CTRL
,
13
,
13
))
{
DSSERR
(
"DDR_CLK_ALWAYS_ON enabled when entering ULPS
\n
"
);
return
-
EIO
;
dsi_if_enable
(
dsidev
,
0
);
REG_FLD_MOD
(
dsidev
,
DSI_CLK_CTRL
,
0
,
13
,
13
);
dsi_if_enable
(
dsidev
,
1
);
}
dsi_sync_vc
(
dsidev
,
0
);
...
...
@@ -3556,10 +3574,19 @@ static int dsi_enter_ulps(struct platform_device *dsidev)
if
(
r
)
return
r
;
mask
=
0
;
for
(
i
=
0
;
i
<
dsi
->
num_lanes_supported
;
++
i
)
{
if
(
dsi
->
lanes
[
i
].
function
==
DSI_LANE_UNUSED
)
continue
;
mask
|=
1
<<
i
;
}
/* Assert TxRequestEsc for data lanes and TxUlpsClk for clk lane */
/* LANEx_ULPS_SIG2 */
REG_FLD_MOD
(
dsidev
,
DSI_COMPLEXIO_CFG2
,
(
1
<<
0
)
|
(
1
<<
1
)
|
(
1
<<
2
),
7
,
5
);
REG_FLD_MOD
(
dsidev
,
DSI_COMPLEXIO_CFG2
,
mask
,
9
,
5
);
/* flush posted write and wait for SCP interface to finish the write */
dsi_read_reg
(
dsidev
,
DSI_COMPLEXIO_CFG2
);
if
(
wait_for_completion_timeout
(
&
completion
,
msecs_to_jiffies
(
1000
))
==
0
)
{
...
...
@@ -3572,8 +3599,10 @@ static int dsi_enter_ulps(struct platform_device *dsidev)
DSI_CIO_IRQ_ULPSACTIVENOT_ALL0
);
/* Reset LANEx_ULPS_SIG2 */
REG_FLD_MOD
(
dsidev
,
DSI_COMPLEXIO_CFG2
,
(
0
<<
0
)
|
(
0
<<
1
)
|
(
0
<<
2
),
7
,
5
);
REG_FLD_MOD
(
dsidev
,
DSI_COMPLEXIO_CFG2
,
0
,
9
,
5
);
/* flush posted write and wait for SCP interface to finish the write */
dsi_read_reg
(
dsidev
,
DSI_COMPLEXIO_CFG2
);
dsi_cio_power
(
dsidev
,
DSI_COMPLEXIO_POWER_ULPS
);
...
...
@@ -3836,6 +3865,7 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)
static
void
dsi_proto_timings
(
struct
omap_dss_device
*
dssdev
)
{
struct
platform_device
*
dsidev
=
dsi_get_dsidev_from_dssdev
(
dssdev
);
struct
dsi_data
*
dsi
=
dsi_get_dsidrv_data
(
dsidev
);
unsigned
tlpx
,
tclk_zero
,
tclk_prepare
,
tclk_trail
;
unsigned
tclk_pre
,
tclk_post
;
unsigned
ths_prepare
,
ths_prepare_ths_zero
,
ths_zero
;
...
...
@@ -3843,7 +3873,7 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev)
unsigned
ddr_clk_pre
,
ddr_clk_post
;
unsigned
enter_hs_mode_lat
,
exit_hs_mode_lat
;
unsigned
ths_eot
;
int
ndl
=
dsi
_get_num_data_lanes_dssdev
(
dssdev
)
;
int
ndl
=
dsi
->
num_lanes_used
-
1
;
u32
r
;
r
=
dsi_read_reg
(
dsidev
,
DSI_DSIPHY_CFG0
);
...
...
@@ -3945,68 +3975,82 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev)
}
}
int
dsi_
video_mode_enable
(
struct
omap_dss_device
*
dssdev
,
int
channel
)
int
dsi_
enable_video_output
(
struct
omap_dss_device
*
dssdev
,
int
channel
)
{
struct
platform_device
*
dsidev
=
dsi_get_dsidev_from_dssdev
(
dssdev
);
int
bpp
=
dsi_get_pixel_size
(
dssdev
->
panel
.
dsi_pix_fmt
);
u8
data_type
;
u16
word_count
;
int
r
;
switch
(
dssdev
->
panel
.
dsi_pix_fmt
)
{
case
OMAP_DSS_DSI_FMT_RGB888
:
data_type
=
MIPI_DSI_PACKED_PIXEL_STREAM_24
;
break
;
case
OMAP_DSS_DSI_FMT_RGB666
:
data_type
=
MIPI_DSI_PIXEL_STREAM_3BYTE_18
;
break
;
case
OMAP_DSS_DSI_FMT_RGB666_PACKED
:
data_type
=
MIPI_DSI_PACKED_PIXEL_STREAM_18
;
break
;
case
OMAP_DSS_DSI_FMT_RGB565
:
data_type
=
MIPI_DSI_PACKED_PIXEL_STREAM_16
;
break
;
default:
BUG
();
};
if
(
dssdev
->
panel
.
dsi_mode
==
OMAP_DSS_DSI_VIDEO_MODE
)
{
switch
(
dssdev
->
panel
.
dsi_pix_fmt
)
{
case
OMAP_DSS_DSI_FMT_RGB888
:
data_type
=
MIPI_DSI_PACKED_PIXEL_STREAM_24
;
break
;
case
OMAP_DSS_DSI_FMT_RGB666
:
data_type
=
MIPI_DSI_PIXEL_STREAM_3BYTE_18
;
break
;
case
OMAP_DSS_DSI_FMT_RGB666_PACKED
:
data_type
=
MIPI_DSI_PACKED_PIXEL_STREAM_18
;
break
;
case
OMAP_DSS_DSI_FMT_RGB565
:
data_type
=
MIPI_DSI_PACKED_PIXEL_STREAM_16
;
break
;
default:
BUG
();
};
dsi_if_enable
(
dsidev
,
false
);
dsi_vc_enable
(
dsidev
,
channel
,
false
);
dsi_if_enable
(
dsidev
,
false
);
dsi_vc_enable
(
dsidev
,
channel
,
false
);
/* MODE, 1 = video mode */
REG_FLD_MOD
(
dsidev
,
DSI_VC_CTRL
(
channel
),
1
,
4
,
4
);
/* MODE, 1 = video mode */
REG_FLD_MOD
(
dsidev
,
DSI_VC_CTRL
(
channel
),
1
,
4
,
4
);
word_count
=
DIV_ROUND_UP
(
dssdev
->
panel
.
timings
.
x_res
*
bpp
,
8
);
word_count
=
DIV_ROUND_UP
(
dssdev
->
panel
.
timings
.
x_res
*
bpp
,
8
);
dsi_vc_write_long_header
(
dsidev
,
channel
,
data_type
,
word_count
,
0
);
dsi_vc_write_long_header
(
dsidev
,
channel
,
data_type
,
word_count
,
0
);
dsi_vc_enable
(
dsidev
,
channel
,
true
);
dsi_if_enable
(
dsidev
,
true
);
dsi_vc_enable
(
dsidev
,
channel
,
true
);
dsi_if_enable
(
dsidev
,
true
);
}
dssdev
->
manager
->
enable
(
dssdev
->
manager
);
r
=
dss_mgr_enable
(
dssdev
->
manager
);
if
(
r
)
{
if
(
dssdev
->
panel
.
dsi_mode
==
OMAP_DSS_DSI_VIDEO_MODE
)
{
dsi_if_enable
(
dsidev
,
false
);
dsi_vc_enable
(
dsidev
,
channel
,
false
);
}
return
r
;
}
return
0
;
}
EXPORT_SYMBOL
(
dsi_
video_mode_enable
);
EXPORT_SYMBOL
(
dsi_
enable_video_output
);
void
dsi_
video_mode_disable
(
struct
omap_dss_device
*
dssdev
,
int
channel
)
void
dsi_
disable_video_output
(
struct
omap_dss_device
*
dssdev
,
int
channel
)
{
struct
platform_device
*
dsidev
=
dsi_get_dsidev_from_dssdev
(
dssdev
);
dsi_if_enable
(
dsidev
,
false
);
dsi_vc_enable
(
dsidev
,
channel
,
false
);
if
(
dssdev
->
panel
.
dsi_mode
==
OMAP_DSS_DSI_VIDEO_MODE
)
{
dsi_if_enable
(
dsidev
,
false
);
dsi_vc_enable
(
dsidev
,
channel
,
false
);
/* MODE, 0 = command mode */
REG_FLD_MOD
(
dsidev
,
DSI_VC_CTRL
(
channel
),
0
,
4
,
4
);
/* MODE, 0 = command mode */
REG_FLD_MOD
(
dsidev
,
DSI_VC_CTRL
(
channel
),
0
,
4
,
4
);
dsi_vc_enable
(
dsidev
,
channel
,
true
);
dsi_if_enable
(
dsidev
,
true
);
dsi_vc_enable
(
dsidev
,
channel
,
true
);
dsi_if_enable
(
dsidev
,
true
);
}
dss
dev
->
manager
->
disable
(
dssdev
->
manager
);
dss
_mgr_
disable
(
dssdev
->
manager
);
}
EXPORT_SYMBOL
(
dsi_
video_mode_disable
);
EXPORT_SYMBOL
(
dsi_
disable_video_output
);
static
void
dsi_update_screen_dispc
(
struct
omap_dss_device
*
dssdev
,
u16
x
,
u16
y
,
u16
w
,
u16
h
)
u16
w
,
u16
h
)
{
struct
platform_device
*
dsidev
=
dsi_get_dsidev_from_dssdev
(
dssdev
);
struct
dsi_data
*
dsi
=
dsi_get_dsidrv_data
(
dsidev
);
...
...
@@ -4021,8 +4065,7 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
const
unsigned
channel
=
dsi
->
update_channel
;
const
unsigned
line_buf_size
=
dsi_get_line_buf_size
(
dsidev
);
DSSDBG
(
"dsi_update_screen_dispc(%d,%d %dx%d)
\n
"
,
x
,
y
,
w
,
h
);
DSSDBG
(
"dsi_update_screen_dispc(%dx%d)
\n
"
,
w
,
h
);
dsi_vc_config_source
(
dsidev
,
channel
,
DSI_VC_SOURCE_VP
);
...
...
@@ -4070,7 +4113,7 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
msecs_to_jiffies
(
250
));
BUG_ON
(
r
==
0
);
dss_
start_update
(
dssdev
);
dss_
mgr_start_update
(
dssdev
->
manager
);
if
(
dsi
->
te_enabled
)
{
/* disable LP_RX_TO, so that we can receive TE. Time to wait
...
...
@@ -4146,66 +4189,27 @@ static void dsi_framedone_irq_callback(void *data, u32 mask)
#endif
}
int
omap_dsi_prepare_update
(
struct
omap_dss_device
*
dssdev
,
u16
*
x
,
u16
*
y
,
u16
*
w
,
u16
*
h
,
bool
enlarge_update_area
)
int
omap_dsi_update
(
struct
omap_dss_device
*
dssdev
,
int
channel
,
void
(
*
callback
)(
int
,
void
*
),
void
*
data
)
{
struct
platform_device
*
dsidev
=
dsi_get_dsidev_from_dssdev
(
dssdev
);
struct
dsi_data
*
dsi
=
dsi_get_dsidrv_data
(
dsidev
);
u16
dw
,
dh
;
dssdev
->
driver
->
get_resolution
(
dssdev
,
&
dw
,
&
dh
);
if
(
*
x
>
dw
||
*
y
>
dh
)
return
-
EINVAL
;
if
(
*
x
+
*
w
>
dw
)
return
-
EINVAL
;
if
(
*
y
+
*
h
>
dh
)
return
-
EINVAL
;
if
(
*
w
==
1
)
return
-
EINVAL
;
if
(
*
w
==
0
||
*
h
==
0
)
return
-
EINVAL
;
dsi_perf_mark_setup
(
dsidev
);
dss_setup_partial_planes
(
dssdev
,
x
,
y
,
w
,
h
,
enlarge_update_area
);
dispc_mgr_set_lcd_size
(
dssdev
->
manager
->
id
,
*
w
,
*
h
);
return
0
;
}
EXPORT_SYMBOL
(
omap_dsi_prepare_update
);
int
omap_dsi_update
(
struct
omap_dss_device
*
dssdev
,
int
channel
,
u16
x
,
u16
y
,
u16
w
,
u16
h
,
void
(
*
callback
)(
int
,
void
*
),
void
*
data
)
{
struct
platform_device
*
dsidev
=
dsi_get_dsidev_from_dssdev
(
dssdev
);
struct
dsi_data
*
dsi
=
dsi_get_dsidrv_data
(
dsidev
);
dsi
->
update_channel
=
channel
;
/* OMAP DSS cannot send updates of odd widths.
* omap_dsi_prepare_update() makes the widths even, but add a BUG_ON
* here to make sure we catch erroneous updates. Otherwise we'll only
* see rather obscure HW error happening, as DSS halts. */
BUG_ON
(
x
%
2
==
1
);
dsi
->
framedone_callback
=
callback
;
dsi
->
framedone_data
=
data
;
dsi
->
update_region
.
x
=
x
;
dsi
->
update_region
.
y
=
y
;
dsi
->
update_region
.
w
=
w
;
dsi
->
update_region
.
h
=
h
;
dsi
->
update_region
.
device
=
dssdev
;
dssdev
->
driver
->
get_resolution
(
dssdev
,
&
dw
,
&
dh
);
dsi_update_screen_dispc
(
dssdev
,
x
,
y
,
w
,
h
);
#ifdef DEBUG
dsi
->
update_bytes
=
dw
*
dh
*
dsi_get_pixel_size
(
dssdev
->
panel
.
dsi_pix_fmt
)
/
8
;
#endif
dsi_update_screen_dispc
(
dssdev
,
dw
,
dh
);
return
0
;
}
...
...
@@ -4218,6 +4222,7 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
int
r
;
if
(
dssdev
->
panel
.
dsi_mode
==
OMAP_DSS_DSI_CMD_MODE
)
{
u16
dw
,
dh
;
u32
irq
;
struct
omap_video_timings
timings
=
{
.
hsw
=
1
,
...
...
@@ -4228,6 +4233,10 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
.
vbp
=
0
,
};
dssdev
->
driver
->
get_resolution
(
dssdev
,
&
dw
,
&
dh
);
timings
.
x_res
=
dw
;
timings
.
y_res
=
dh
;
irq
=
dssdev
->
manager
->
id
==
OMAP_DSS_CHANNEL_LCD
?
DISPC_IRQ_FRAMEDONE
:
DISPC_IRQ_FRAMEDONE2
;
...
...
@@ -4330,6 +4339,12 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
int
dsi_module
=
dsi_get_dsidev_id
(
dsidev
);
int
r
;
r
=
dsi_parse_lane_config
(
dssdev
);
if
(
r
)
{
DSSERR
(
"illegal lane config"
);
goto
err0
;
}
r
=
dsi_pll_init
(
dsidev
,
true
,
true
);
if
(
r
)
goto
err0
;
...
...
@@ -4521,7 +4536,6 @@ int dsi_init_display(struct omap_dss_device *dssdev)
{
struct
platform_device
*
dsidev
=
dsi_get_dsidev_from_dssdev
(
dssdev
);
struct
dsi_data
*
dsi
=
dsi_get_dsidrv_data
(
dsidev
);
int
dsi_module
=
dsi_get_dsidev_id
(
dsidev
);
DSSDBG
(
"DSI init
\n
"
);
...
...
@@ -4543,12 +4557,6 @@ int dsi_init_display(struct omap_dss_device *dssdev)
dsi
->
vdds_dsi_reg
=
vdds_dsi
;
}
if
(
dsi_get_num_data_lanes_dssdev
(
dssdev
)
>
dsi
->
num_data_lanes
)
{
DSSERR
(
"DSI%d can't support more than %d data lanes
\n
"
,
dsi_module
+
1
,
dsi
->
num_data_lanes
);
return
-
EINVAL
;
}
return
0
;
}
...
...
@@ -4771,7 +4779,13 @@ static int omap_dsihw_probe(struct platform_device *dsidev)
dev_dbg
(
&
dsidev
->
dev
,
"OMAP DSI rev %d.%d
\n
"
,
FLD_GET
(
rev
,
7
,
4
),
FLD_GET
(
rev
,
3
,
0
));
dsi
->
num_data_lanes
=
dsi_get_num_data_lanes
(
dsidev
);
/* DSI on OMAP3 doesn't have register DSI_GNQ, set number
* of data to 3 by default */
if
(
dss_has_feature
(
FEAT_DSI_GNQ
))
/* NB_DATA_LANES */
dsi
->
num_lanes_supported
=
1
+
REG_GET
(
dsidev
,
DSI_GNQ
,
11
,
9
);
else
dsi
->
num_lanes_supported
=
3
;
dsi_runtime_put
(
dsidev
);
...
...
drivers/video/omap2/dss/dss.h
View file @
193984f4
...
...
@@ -163,6 +163,34 @@ struct bus_type *dss_get_bus(void);
struct
regulator
*
dss_get_vdds_dsi
(
void
);
struct
regulator
*
dss_get_vdds_sdi
(
void
);
/* apply */
void
dss_apply_init
(
void
);
int
dss_mgr_wait_for_go
(
struct
omap_overlay_manager
*
mgr
);
int
dss_mgr_wait_for_go_ovl
(
struct
omap_overlay
*
ovl
);
void
dss_mgr_start_update
(
struct
omap_overlay_manager
*
mgr
);
int
omap_dss_mgr_apply
(
struct
omap_overlay_manager
*
mgr
);
int
dss_mgr_enable
(
struct
omap_overlay_manager
*
mgr
);
void
dss_mgr_disable
(
struct
omap_overlay_manager
*
mgr
);
int
dss_mgr_set_info
(
struct
omap_overlay_manager
*
mgr
,
struct
omap_overlay_manager_info
*
info
);
void
dss_mgr_get_info
(
struct
omap_overlay_manager
*
mgr
,
struct
omap_overlay_manager_info
*
info
);
int
dss_mgr_set_device
(
struct
omap_overlay_manager
*
mgr
,
struct
omap_dss_device
*
dssdev
);
int
dss_mgr_unset_device
(
struct
omap_overlay_manager
*
mgr
);
bool
dss_ovl_is_enabled
(
struct
omap_overlay
*
ovl
);
int
dss_ovl_enable
(
struct
omap_overlay
*
ovl
);
int
dss_ovl_disable
(
struct
omap_overlay
*
ovl
);
int
dss_ovl_set_info
(
struct
omap_overlay
*
ovl
,
struct
omap_overlay_info
*
info
);
void
dss_ovl_get_info
(
struct
omap_overlay
*
ovl
,
struct
omap_overlay_info
*
info
);
int
dss_ovl_set_manager
(
struct
omap_overlay
*
ovl
,
struct
omap_overlay_manager
*
mgr
);
int
dss_ovl_unset_manager
(
struct
omap_overlay
*
ovl
);
/* display */
int
dss_suspend_all_devices
(
void
);
int
dss_resume_all_devices
(
void
);
...
...
@@ -181,21 +209,22 @@ void default_get_overlay_fifo_thresholds(enum omap_plane plane,
/* manager */
int
dss_init_overlay_managers
(
struct
platform_device
*
pdev
);
void
dss_uninit_overlay_managers
(
struct
platform_device
*
pdev
);
int
dss_mgr_wait_for_go_ovl
(
struct
omap_overlay
*
ovl
);
void
dss_setup_partial_planes
(
struct
omap_dss_device
*
dssdev
,
u16
*
x
,
u16
*
y
,
u16
*
w
,
u16
*
h
,
bool
enlarge_update_area
);
void
dss_start_update
(
struct
omap_dss_device
*
dssdev
);
int
dss_mgr_simple_check
(
struct
omap_overlay_manager
*
mgr
,
const
struct
omap_overlay_manager_info
*
info
);
int
dss_mgr_check
(
struct
omap_overlay_manager
*
mgr
,
struct
omap_dss_device
*
dssdev
,
struct
omap_overlay_manager_info
*
info
,
struct
omap_overlay_info
**
overlay_infos
);
/* overlay */
void
dss_init_overlays
(
struct
platform_device
*
pdev
);
void
dss_uninit_overlays
(
struct
platform_device
*
pdev
);
int
dss_check_overlay
(
struct
omap_overlay
*
ovl
,
struct
omap_dss_device
*
dssdev
);
void
dss_overlay_setup_dispc_manager
(
struct
omap_overlay_manager
*
mgr
);
#ifdef L4_EXAMPLE
void
dss_overlay_setup_l4_manager
(
struct
omap_overlay_manager
*
mgr
);
#endif
void
dss_recheck_connections
(
struct
omap_dss_device
*
dssdev
,
bool
force
);
int
dss_ovl_simple_check
(
struct
omap_overlay
*
ovl
,
const
struct
omap_overlay_info
*
info
);
int
dss_ovl_check
(
struct
omap_overlay
*
ovl
,
struct
omap_overlay_info
*
info
,
struct
omap_dss_device
*
dssdev
);
/* DSS */
int
dss_init_platform_driver
(
void
);
...
...
@@ -399,21 +428,22 @@ int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
struct
dispc_clock_info
*
cinfo
);
void
dispc_ovl_set_fifo_threshold
(
enum
omap_plane
plane
,
u32
low
,
u32
high
);
u32
dispc_ovl_get_fifo_size
(
enum
omap_plane
plane
);
u32
dispc_ovl_get_burst_size
(
enum
omap_plane
plane
);
int
dispc_ovl_setup
(
enum
omap_plane
plane
,
struct
omap_overlay_info
*
oi
,
bool
ilace
,
enum
omap_channel
channel
,
bool
replication
,
u32
fifo_low
,
u32
fifo_high
);
bool
ilace
,
bool
replication
);
int
dispc_ovl_enable
(
enum
omap_plane
plane
,
bool
enable
);
void
dispc_ovl_set_channel_out
(
enum
omap_plane
plane
,
enum
omap_channel
channel
);
void
dispc_mgr_enable_fifohandcheck
(
enum
omap_channel
channel
,
bool
enable
);
void
dispc_mgr_set_lcd_size
(
enum
omap_channel
channel
,
u16
width
,
u16
height
);
void
dispc_mgr_enable_cpr
(
enum
omap_channel
channel
,
bool
enable
);
void
dispc_mgr_set_cpr_coef
(
enum
omap_channel
channel
,
struct
omap_dss_cpr_coefs
*
coefs
);
u32
dispc_mgr_get_vsync_irq
(
enum
omap_channel
channel
);
u32
dispc_mgr_get_framedone_irq
(
enum
omap_channel
channel
);
bool
dispc_mgr_go_busy
(
enum
omap_channel
channel
);
void
dispc_mgr_go
(
enum
omap_channel
channel
);
bool
dispc_mgr_is_enabled
(
enum
omap_channel
channel
);
void
dispc_mgr_enable
(
enum
omap_channel
channel
,
bool
enable
);
bool
dispc_mgr_is_channel_enabled
(
enum
omap_channel
channel
);
void
dispc_mgr_set_io_pad_mode
(
enum
dss_io_pad_mode
mode
);
...
...
@@ -421,18 +451,6 @@ void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable);
void
dispc_mgr_set_tft_data_lines
(
enum
omap_channel
channel
,
u8
data_lines
);
void
dispc_mgr_set_lcd_display_type
(
enum
omap_channel
channel
,
enum
omap_lcd_display_type
type
);
void
dispc_mgr_set_default_color
(
enum
omap_channel
channel
,
u32
color
);
u32
dispc_mgr_get_default_color
(
enum
omap_channel
channel
);
void
dispc_mgr_set_trans_key
(
enum
omap_channel
ch
,
enum
omap_dss_trans_key_type
type
,
u32
trans_key
);
void
dispc_mgr_get_trans_key
(
enum
omap_channel
ch
,
enum
omap_dss_trans_key_type
*
type
,
u32
*
trans_key
);
void
dispc_mgr_enable_trans_key
(
enum
omap_channel
ch
,
bool
enable
);
void
dispc_mgr_enable_alpha_fixed_zorder
(
enum
omap_channel
ch
,
bool
enable
);
bool
dispc_mgr_trans_key_enabled
(
enum
omap_channel
ch
);
bool
dispc_mgr_alpha_fixed_zorder_enabled
(
enum
omap_channel
ch
);
void
dispc_mgr_set_lcd_timings
(
enum
omap_channel
channel
,
struct
omap_video_timings
*
timings
);
void
dispc_mgr_set_pol_freq
(
enum
omap_channel
channel
,
...
...
@@ -443,6 +461,8 @@ int dispc_mgr_set_clock_div(enum omap_channel channel,
struct
dispc_clock_info
*
cinfo
);
int
dispc_mgr_get_clock_div
(
enum
omap_channel
channel
,
struct
dispc_clock_info
*
cinfo
);
void
dispc_mgr_setup
(
enum
omap_channel
channel
,
struct
omap_overlay_manager_info
*
info
);
/* VENC */
#ifdef CONFIG_OMAP2_DSS_VENC
...
...
drivers/video/omap2/dss/dss_features.c
View file @
193984f4
...
...
@@ -304,6 +304,11 @@ static const struct dss_param_range omap2_dss_param_range[] = {
[
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
* scaler cannot scale a image with width more than 768.
*/
[
FEAT_PARAM_LINEWIDTH
]
=
{
1
,
768
},
};
static
const
struct
dss_param_range
omap3_dss_param_range
[]
=
{
...
...
@@ -316,6 +321,7 @@ static const struct dss_param_range omap3_dss_param_range[] = {
[
FEAT_PARAM_DSIPLL_FINT
]
=
{
750000
,
2100000
},
[
FEAT_PARAM_DSIPLL_LPDIV
]
=
{
1
,
(
1
<<
13
)
-
1
},
[
FEAT_PARAM_DOWNSCALE
]
=
{
1
,
4
},
[
FEAT_PARAM_LINEWIDTH
]
=
{
1
,
1024
},
};
static
const
struct
dss_param_range
omap4_dss_param_range
[]
=
{
...
...
@@ -328,6 +334,7 @@ static const struct dss_param_range omap4_dss_param_range[] = {
[
FEAT_PARAM_DSIPLL_FINT
]
=
{
500000
,
2500000
},
[
FEAT_PARAM_DSIPLL_LPDIV
]
=
{
0
,
(
1
<<
13
)
-
1
},
[
FEAT_PARAM_DOWNSCALE
]
=
{
1
,
4
},
[
FEAT_PARAM_LINEWIDTH
]
=
{
1
,
2048
},
};
/* OMAP2 DSS Features */
...
...
@@ -465,6 +472,10 @@ static const struct ti_hdmi_ip_ops omap4_hdmi_functions = {
.
dump_core
=
ti_hdmi_4xxx_core_dump
,
.
dump_pll
=
ti_hdmi_4xxx_pll_dump
,
.
dump_phy
=
ti_hdmi_4xxx_phy_dump
,
#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
.
audio_enable
=
ti_hdmi_4xxx_wp_audio_enable
,
#endif
};
...
...
drivers/video/omap2/dss/dss_features.h
View file @
193984f4
...
...
@@ -86,6 +86,7 @@ enum dss_range_param {
FEAT_PARAM_DSIPLL_FINT
,
FEAT_PARAM_DSIPLL_LPDIV
,
FEAT_PARAM_DOWNSCALE
,
FEAT_PARAM_LINEWIDTH
,
};
/* DSS Feature Functions */
...
...
drivers/video/omap2/dss/hdmi.c
View file @
193984f4
...
...
@@ -333,7 +333,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
if
(
r
)
return
r
;
d
ispc_mgr_enable
(
OMAP_DSS_CHANNEL_DIGIT
,
0
);
d
ss_mgr_disable
(
dssdev
->
manager
);
p
=
&
dssdev
->
panel
.
timings
;
...
...
@@ -387,9 +387,16 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
hdmi
.
ip_data
.
ops
->
video_enable
(
&
hdmi
.
ip_data
,
1
);
dispc_mgr_enable
(
OMAP_DSS_CHANNEL_DIGIT
,
1
);
r
=
dss_mgr_enable
(
dssdev
->
manager
);
if
(
r
)
goto
err_mgr_enable
;
return
0
;
err_mgr_enable:
hdmi
.
ip_data
.
ops
->
video_enable
(
&
hdmi
.
ip_data
,
0
);
hdmi
.
ip_data
.
ops
->
phy_disable
(
&
hdmi
.
ip_data
);
hdmi
.
ip_data
.
ops
->
pll_disable
(
&
hdmi
.
ip_data
);
err:
hdmi_runtime_put
();
return
-
EIO
;
...
...
@@ -397,7 +404,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
static
void
hdmi_power_off
(
struct
omap_dss_device
*
dssdev
)
{
d
ispc_mgr_enable
(
OMAP_DSS_CHANNEL_DIGIT
,
0
);
d
ss_mgr_disable
(
dssdev
->
manager
);
hdmi
.
ip_data
.
ops
->
video_enable
(
&
hdmi
.
ip_data
,
0
);
hdmi
.
ip_data
.
ops
->
phy_disable
(
&
hdmi
.
ip_data
);
...
...
@@ -554,11 +561,44 @@ void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev)
#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
static
int
hdmi_audio_hw_params
(
struct
hdmi_ip_data
*
ip_data
,
struct
snd_pcm_substream
*
substream
,
static
int
hdmi_audio_trigger
(
struct
snd_pcm_substream
*
substream
,
int
cmd
,
struct
snd_soc_dai
*
dai
)
{
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
snd_soc_codec
*
codec
=
rtd
->
codec
;
struct
platform_device
*
pdev
=
to_platform_device
(
codec
->
dev
);
struct
hdmi_ip_data
*
ip_data
=
snd_soc_codec_get_drvdata
(
codec
);
int
err
=
0
;
if
(
!
(
ip_data
->
ops
)
&&
!
(
ip_data
->
ops
->
audio_enable
))
{
dev_err
(
&
pdev
->
dev
,
"Cannot enable/disable audio
\n
"
);
return
-
ENODEV
;
}
switch
(
cmd
)
{
case
SNDRV_PCM_TRIGGER_START
:
case
SNDRV_PCM_TRIGGER_RESUME
:
case
SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
ip_data
->
ops
->
audio_enable
(
ip_data
,
true
);
break
;
case
SNDRV_PCM_TRIGGER_STOP
:
case
SNDRV_PCM_TRIGGER_SUSPEND
:
case
SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
ip_data
->
ops
->
audio_enable
(
ip_data
,
false
);
break
;
default:
err
=
-
EINVAL
;
}
return
err
;
}
static
int
hdmi_audio_hw_params
(
struct
snd_pcm_substream
*
substream
,
struct
snd_pcm_hw_params
*
params
,
struct
snd_soc_dai
*
dai
)
{
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
snd_soc_codec
*
codec
=
rtd
->
codec
;
struct
hdmi_ip_data
*
ip_data
=
snd_soc_codec_get_drvdata
(
codec
);
struct
hdmi_audio_format
audio_format
;
struct
hdmi_audio_dma
audio_dma
;
struct
hdmi_core_audio_config
core_cfg
;
...
...
@@ -698,7 +738,16 @@ static int hdmi_audio_startup(struct snd_pcm_substream *substream,
return
0
;
}
static
int
hdmi_audio_codec_probe
(
struct
snd_soc_codec
*
codec
)
{
struct
hdmi_ip_data
*
priv
=
&
hdmi
.
ip_data
;
snd_soc_codec_set_drvdata
(
codec
,
priv
);
return
0
;
}
static
struct
snd_soc_codec_driver
hdmi_audio_codec_drv
=
{
.
probe
=
hdmi_audio_codec_probe
,
};
static
struct
snd_soc_dai_ops
hdmi_audio_codec_ops
=
{
...
...
drivers/video/omap2/dss/manager.c
View file @
193984f4
...
...
@@ -26,17 +26,15 @@
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/spinlock.h>
#include <linux/jiffies.h>
#include <video/omapdss.h>
#include <plat/cpu.h>
#include "dss.h"
#include "dss_features.h"
static
int
num_managers
;
static
struct
list_head
manager_list
;
static
struct
omap_overlay_manager
*
managers
;
static
ssize_t
manager_name_show
(
struct
omap_overlay_manager
*
mgr
,
char
*
buf
)
{
...
...
@@ -106,7 +104,11 @@ static ssize_t manager_display_store(struct omap_overlay_manager *mgr,
static
ssize_t
manager_default_color_show
(
struct
omap_overlay_manager
*
mgr
,
char
*
buf
)
{
return
snprintf
(
buf
,
PAGE_SIZE
,
"%#x
\n
"
,
mgr
->
info
.
default_color
);
struct
omap_overlay_manager_info
info
;
mgr
->
get_manager_info
(
mgr
,
&
info
);
return
snprintf
(
buf
,
PAGE_SIZE
,
"%#x
\n
"
,
info
.
default_color
);
}
static
ssize_t
manager_default_color_store
(
struct
omap_overlay_manager
*
mgr
,
...
...
@@ -144,8 +146,11 @@ static ssize_t manager_trans_key_type_show(struct omap_overlay_manager *mgr,
char
*
buf
)
{
enum
omap_dss_trans_key_type
key_type
;
struct
omap_overlay_manager_info
info
;
mgr
->
get_manager_info
(
mgr
,
&
info
);
key_type
=
mgr
->
info
.
trans_key_type
;
key_type
=
info
.
trans_key_type
;
BUG_ON
(
key_type
>=
ARRAY_SIZE
(
trans_key_type_str
));
return
snprintf
(
buf
,
PAGE_SIZE
,
"%s
\n
"
,
trans_key_type_str
[
key_type
]);
...
...
@@ -185,7 +190,11 @@ static ssize_t manager_trans_key_type_store(struct omap_overlay_manager *mgr,
static
ssize_t
manager_trans_key_value_show
(
struct
omap_overlay_manager
*
mgr
,
char
*
buf
)
{
return
snprintf
(
buf
,
PAGE_SIZE
,
"%#x
\n
"
,
mgr
->
info
.
trans_key
);
struct
omap_overlay_manager_info
info
;
mgr
->
get_manager_info
(
mgr
,
&
info
);
return
snprintf
(
buf
,
PAGE_SIZE
,
"%#x
\n
"
,
info
.
trans_key
);
}
static
ssize_t
manager_trans_key_value_store
(
struct
omap_overlay_manager
*
mgr
,
...
...
@@ -217,7 +226,11 @@ static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr,
static
ssize_t
manager_trans_key_enabled_show
(
struct
omap_overlay_manager
*
mgr
,
char
*
buf
)
{
return
snprintf
(
buf
,
PAGE_SIZE
,
"%d
\n
"
,
mgr
->
info
.
trans_enabled
);
struct
omap_overlay_manager_info
info
;
mgr
->
get_manager_info
(
mgr
,
&
info
);
return
snprintf
(
buf
,
PAGE_SIZE
,
"%d
\n
"
,
info
.
trans_enabled
);
}
static
ssize_t
manager_trans_key_enabled_store
(
struct
omap_overlay_manager
*
mgr
,
...
...
@@ -249,10 +262,14 @@ static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr,
static
ssize_t
manager_alpha_blending_enabled_show
(
struct
omap_overlay_manager
*
mgr
,
char
*
buf
)
{
struct
omap_overlay_manager_info
info
;
mgr
->
get_manager_info
(
mgr
,
&
info
);
WARN_ON
(
!
dss_has_feature
(
FEAT_ALPHA_FIXED_ZORDER
));
return
snprintf
(
buf
,
PAGE_SIZE
,
"%d
\n
"
,
mgr
->
info
.
partial_alpha_enabled
);
info
.
partial_alpha_enabled
);
}
static
ssize_t
manager_alpha_blending_enabled_store
(
...
...
@@ -287,7 +304,11 @@ static ssize_t manager_alpha_blending_enabled_store(
static
ssize_t
manager_cpr_enable_show
(
struct
omap_overlay_manager
*
mgr
,
char
*
buf
)
{
return
snprintf
(
buf
,
PAGE_SIZE
,
"%d
\n
"
,
mgr
->
info
.
cpr_enable
);
struct
omap_overlay_manager_info
info
;
mgr
->
get_manager_info
(
mgr
,
&
info
);
return
snprintf
(
buf
,
PAGE_SIZE
,
"%d
\n
"
,
info
.
cpr_enable
);
}
static
ssize_t
manager_cpr_enable_store
(
struct
omap_overlay_manager
*
mgr
,
...
...
@@ -469,143 +490,6 @@ static struct kobj_type manager_ktype = {
.
default_attrs
=
manager_sysfs_attrs
,
};
/*
* We have 4 levels of cache for the dispc settings. First two are in SW and
* the latter two in HW.
*
* +--------------------+
* |overlay/manager_info|
* +--------------------+
* v
* apply()
* v
* +--------------------+
* | dss_cache |
* +--------------------+
* v
* configure()
* v
* +--------------------+
* | shadow registers |
* +--------------------+
* v
* VFP or lcd/digit_enable
* v
* +--------------------+
* | registers |
* +--------------------+
*/
struct
overlay_cache_data
{
/* If true, cache changed, but not written to shadow registers. Set
* in apply(), cleared when registers written. */
bool
dirty
;
/* If true, shadow registers contain changed values not yet in real
* registers. Set when writing to shadow registers, cleared at
* VSYNC/EVSYNC */
bool
shadow_dirty
;
bool
enabled
;
struct
omap_overlay_info
info
;
enum
omap_channel
channel
;
bool
replication
;
bool
ilace
;
u32
fifo_low
;
u32
fifo_high
;
};
struct
manager_cache_data
{
/* If true, cache changed, but not written to shadow registers. Set
* in apply(), cleared when registers written. */
bool
dirty
;
/* If true, shadow registers contain changed values not yet in real
* registers. Set when writing to shadow registers, cleared at
* VSYNC/EVSYNC */
bool
shadow_dirty
;
struct
omap_overlay_manager_info
info
;
bool
manual_update
;
bool
do_manual_update
;
/* manual update region */
u16
x
,
y
,
w
,
h
;
/* enlarge the update area if the update area contains scaled
* overlays */
bool
enlarge_update_area
;
};
static
struct
{
spinlock_t
lock
;
struct
overlay_cache_data
overlay_cache
[
MAX_DSS_OVERLAYS
];
struct
manager_cache_data
manager_cache
[
MAX_DSS_MANAGERS
];
bool
irq_enabled
;
}
dss_cache
;
static
int
omap_dss_set_device
(
struct
omap_overlay_manager
*
mgr
,
struct
omap_dss_device
*
dssdev
)
{
int
i
;
int
r
;
if
(
dssdev
->
manager
)
{
DSSERR
(
"display '%s' already has a manager '%s'
\n
"
,
dssdev
->
name
,
dssdev
->
manager
->
name
);
return
-
EINVAL
;
}
if
((
mgr
->
supported_displays
&
dssdev
->
type
)
==
0
)
{
DSSERR
(
"display '%s' does not support manager '%s'
\n
"
,
dssdev
->
name
,
mgr
->
name
);
return
-
EINVAL
;
}
for
(
i
=
0
;
i
<
mgr
->
num_overlays
;
i
++
)
{
struct
omap_overlay
*
ovl
=
mgr
->
overlays
[
i
];
if
(
ovl
->
manager
!=
mgr
||
!
ovl
->
info
.
enabled
)
continue
;
r
=
dss_check_overlay
(
ovl
,
dssdev
);
if
(
r
)
return
r
;
}
dssdev
->
manager
=
mgr
;
mgr
->
device
=
dssdev
;
mgr
->
device_changed
=
true
;
return
0
;
}
static
int
omap_dss_unset_device
(
struct
omap_overlay_manager
*
mgr
)
{
if
(
!
mgr
->
device
)
{
DSSERR
(
"failed to unset display, display not set.
\n
"
);
return
-
EINVAL
;
}
/*
* Don't allow currently enabled displays to have the overlay manager
* pulled out from underneath them
*/
if
(
mgr
->
device
->
state
!=
OMAP_DSS_DISPLAY_DISABLED
)
return
-
EINVAL
;
mgr
->
device
->
manager
=
NULL
;
mgr
->
device
=
NULL
;
mgr
->
device_changed
=
true
;
return
0
;
}
static
int
dss_mgr_wait_for_vsync
(
struct
omap_overlay_manager
*
mgr
)
{
unsigned
long
timeout
=
msecs_to_jiffies
(
500
);
...
...
@@ -624,1022 +508,169 @@ static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr)
return
omap_dispc_wait_for_irq_interruptible_timeout
(
irq
,
timeout
);
}
static
int
dss_mgr_wait_for_go
(
struct
omap_overlay_manager
*
mgr
)
{
unsigned
long
timeout
=
msecs_to_jiffies
(
500
);
struct
manager_cache_data
*
mc
;
u32
irq
;
int
r
;
int
i
;
struct
omap_dss_device
*
dssdev
=
mgr
->
device
;
if
(
!
dssdev
||
dssdev
->
state
!=
OMAP_DSS_DISPLAY_ACTIVE
)
return
0
;
if
(
dssdev
->
caps
&
OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE
)
return
0
;
if
(
dssdev
->
type
==
OMAP_DISPLAY_TYPE_VENC
||
dssdev
->
type
==
OMAP_DISPLAY_TYPE_HDMI
)
{
irq
=
DISPC_IRQ_EVSYNC_ODD
|
DISPC_IRQ_EVSYNC_EVEN
;
}
else
{
irq
=
(
dssdev
->
manager
->
id
==
OMAP_DSS_CHANNEL_LCD
)
?
DISPC_IRQ_VSYNC
:
DISPC_IRQ_VSYNC2
;
}
mc
=
&
dss_cache
.
manager_cache
[
mgr
->
id
];
i
=
0
;
while
(
1
)
{
unsigned
long
flags
;
bool
shadow_dirty
,
dirty
;
spin_lock_irqsave
(
&
dss_cache
.
lock
,
flags
);
dirty
=
mc
->
dirty
;
shadow_dirty
=
mc
->
shadow_dirty
;
spin_unlock_irqrestore
(
&
dss_cache
.
lock
,
flags
);
if
(
!
dirty
&&
!
shadow_dirty
)
{
r
=
0
;
break
;
}
/* 4 iterations is the worst case:
* 1 - initial iteration, dirty = true (between VFP and VSYNC)
* 2 - first VSYNC, dirty = true
* 3 - dirty = false, shadow_dirty = true
* 4 - shadow_dirty = false */
if
(
i
++
==
3
)
{
DSSERR
(
"mgr(%d)->wait_for_go() not finishing
\n
"
,
mgr
->
id
);
r
=
0
;
break
;
}
r
=
omap_dispc_wait_for_irq_interruptible_timeout
(
irq
,
timeout
);
if
(
r
==
-
ERESTARTSYS
)
break
;
if
(
r
)
{
DSSERR
(
"mgr(%d)->wait_for_go() timeout
\n
"
,
mgr
->
id
);
break
;
}
}
return
r
;
}
int
dss_mgr_wait_for_go_ovl
(
struct
omap_overlay
*
ovl
)
{
unsigned
long
timeout
=
msecs_to_jiffies
(
500
);
struct
overlay_cache_data
*
oc
;
struct
omap_dss_device
*
dssdev
;
u32
irq
;
int
r
;
int
i
;
if
(
!
ovl
->
manager
)
return
0
;
dssdev
=
ovl
->
manager
->
device
;
if
(
!
dssdev
||
dssdev
->
state
!=
OMAP_DSS_DISPLAY_ACTIVE
)
return
0
;
if
(
dssdev
->
caps
&
OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE
)
return
0
;
if
(
dssdev
->
type
==
OMAP_DISPLAY_TYPE_VENC
||
dssdev
->
type
==
OMAP_DISPLAY_TYPE_HDMI
)
{
irq
=
DISPC_IRQ_EVSYNC_ODD
|
DISPC_IRQ_EVSYNC_EVEN
;
}
else
{
irq
=
(
dssdev
->
manager
->
id
==
OMAP_DSS_CHANNEL_LCD
)
?
DISPC_IRQ_VSYNC
:
DISPC_IRQ_VSYNC2
;
}
oc
=
&
dss_cache
.
overlay_cache
[
ovl
->
id
];
i
=
0
;
while
(
1
)
{
unsigned
long
flags
;
bool
shadow_dirty
,
dirty
;
spin_lock_irqsave
(
&
dss_cache
.
lock
,
flags
);
dirty
=
oc
->
dirty
;
shadow_dirty
=
oc
->
shadow_dirty
;
spin_unlock_irqrestore
(
&
dss_cache
.
lock
,
flags
);
if
(
!
dirty
&&
!
shadow_dirty
)
{
r
=
0
;
break
;
}
/* 4 iterations is the worst case:
* 1 - initial iteration, dirty = true (between VFP and VSYNC)
* 2 - first VSYNC, dirty = true
* 3 - dirty = false, shadow_dirty = true
* 4 - shadow_dirty = false */
if
(
i
++
==
3
)
{
DSSERR
(
"ovl(%d)->wait_for_go() not finishing
\n
"
,
ovl
->
id
);
r
=
0
;
break
;
}
r
=
omap_dispc_wait_for_irq_interruptible_timeout
(
irq
,
timeout
);
if
(
r
==
-
ERESTARTSYS
)
break
;
if
(
r
)
{
DSSERR
(
"ovl(%d)->wait_for_go() timeout
\n
"
,
ovl
->
id
);
break
;
}
}
return
r
;
}
static
int
overlay_enabled
(
struct
omap_overlay
*
ovl
)
{
return
ovl
->
info
.
enabled
&&
ovl
->
manager
&&
ovl
->
manager
->
device
;
}
/* Is rect1 a subset of rect2? */
static
bool
rectangle_subset
(
int
x1
,
int
y1
,
int
w1
,
int
h1
,
int
x2
,
int
y2
,
int
w2
,
int
h2
)
{
if
(
x1
<
x2
||
y1
<
y2
)
return
false
;
if
(
x1
+
w1
>
x2
+
w2
)
return
false
;
if
(
y1
+
h1
>
y2
+
h2
)
return
false
;
return
true
;
}
/* Do rect1 and rect2 overlap? */
static
bool
rectangle_intersects
(
int
x1
,
int
y1
,
int
w1
,
int
h1
,
int
x2
,
int
y2
,
int
w2
,
int
h2
)
{
if
(
x1
>=
x2
+
w2
)
return
false
;
if
(
x2
>=
x1
+
w1
)
return
false
;
if
(
y1
>=
y2
+
h2
)
return
false
;
if
(
y2
>=
y1
+
h1
)
return
false
;
return
true
;
}
static
bool
dispc_is_overlay_scaled
(
struct
overlay_cache_data
*
oc
)
{
struct
omap_overlay_info
*
oi
=
&
oc
->
info
;
if
(
oi
->
out_width
!=
0
&&
oi
->
width
!=
oi
->
out_width
)
return
true
;
if
(
oi
->
out_height
!=
0
&&
oi
->
height
!=
oi
->
out_height
)
return
true
;
return
false
;
}
static
int
configure_overlay
(
enum
omap_plane
plane
)
int
dss_init_overlay_managers
(
struct
platform_device
*
pdev
)
{
struct
overlay_cache_data
*
c
;
struct
manager_cache_data
*
mc
;
struct
omap_overlay_info
*
oi
,
new_oi
;
struct
omap_overlay_manager_info
*
mi
;
u16
outw
,
outh
;
u16
x
,
y
,
w
,
h
;
u32
paddr
;
int
r
;
u16
orig_w
,
orig_h
,
orig_outw
,
orig_outh
;
int
i
,
r
;
DSSDBGF
(
"%d"
,
plane
);
num_managers
=
dss_feat_get_num_mgrs
(
);
c
=
&
dss_cache
.
overlay_cache
[
plane
];
oi
=
&
c
->
info
;
managers
=
kzalloc
(
sizeof
(
struct
omap_overlay_manager
)
*
num_managers
,
GFP_KERNEL
)
;
if
(
!
c
->
enabled
)
{
dispc_ovl_enable
(
plane
,
0
);
return
0
;
}
BUG_ON
(
managers
==
NULL
);
mc
=
&
dss_cache
.
manager_cache
[
c
->
channel
];
mi
=
&
mc
->
info
;
x
=
oi
->
pos_x
;
y
=
oi
->
pos_y
;
w
=
oi
->
width
;
h
=
oi
->
height
;
outw
=
oi
->
out_width
==
0
?
oi
->
width
:
oi
->
out_width
;
outh
=
oi
->
out_height
==
0
?
oi
->
height
:
oi
->
out_height
;
paddr
=
oi
->
paddr
;
orig_w
=
w
;
orig_h
=
h
;
orig_outw
=
outw
;
orig_outh
=
outh
;
if
(
mc
->
manual_update
&&
mc
->
do_manual_update
)
{
unsigned
bpp
;
unsigned
scale_x_m
=
w
,
scale_x_d
=
outw
;
unsigned
scale_y_m
=
h
,
scale_y_d
=
outh
;
/* If the overlay is outside the update region, disable it */
if
(
!
rectangle_intersects
(
mc
->
x
,
mc
->
y
,
mc
->
w
,
mc
->
h
,
x
,
y
,
outw
,
outh
))
{
dispc_ovl_enable
(
plane
,
0
);
return
0
;
}
for
(
i
=
0
;
i
<
num_managers
;
++
i
)
{
struct
omap_overlay_manager
*
mgr
=
&
managers
[
i
];
switch
(
oi
->
color_mode
)
{
case
OMAP_DSS_COLOR_NV12
:
bpp
=
8
;
break
;
case
OMAP_DSS_COLOR_RGB16
:
case
OMAP_DSS_COLOR_ARGB16
:
case
OMAP_DSS_COLOR_YUV2
:
case
OMAP_DSS_COLOR_UYVY
:
case
OMAP_DSS_COLOR_RGBA16
:
case
OMAP_DSS_COLOR_RGBX16
:
case
OMAP_DSS_COLOR_ARGB16_1555
:
case
OMAP_DSS_COLOR_XRGB16_1555
:
bpp
=
16
;
switch
(
i
)
{
case
0
:
mgr
->
name
=
"lcd"
;
mgr
->
id
=
OMAP_DSS_CHANNEL_LCD
;
break
;
case
OMAP_DSS_COLOR_RGB24P
:
bpp
=
24
;
case
1
:
mgr
->
name
=
"tv"
;
mgr
->
id
=
OMAP_DSS_CHANNEL_DIGIT
;
break
;
case
OMAP_DSS_COLOR_RGB24U
:
case
OMAP_DSS_COLOR_ARGB32
:
case
OMAP_DSS_COLOR_RGBA32
:
case
OMAP_DSS_COLOR_RGBX32
:
bpp
=
32
;
case
2
:
mgr
->
name
=
"lcd2"
;
mgr
->
id
=
OMAP_DSS_CHANNEL_LCD2
;
break
;
default:
BUG
();
}
if
(
mc
->
x
>
oi
->
pos_x
)
{
x
=
0
;
outw
-=
(
mc
->
x
-
oi
->
pos_x
);
paddr
+=
(
mc
->
x
-
oi
->
pos_x
)
*
scale_x_m
/
scale_x_d
*
bpp
/
8
;
}
else
{
x
=
oi
->
pos_x
-
mc
->
x
;
}
if
(
mc
->
y
>
oi
->
pos_y
)
{
y
=
0
;
outh
-=
(
mc
->
y
-
oi
->
pos_y
);
paddr
+=
(
mc
->
y
-
oi
->
pos_y
)
*
scale_y_m
/
scale_y_d
*
oi
->
screen_width
*
bpp
/
8
;
}
else
{
y
=
oi
->
pos_y
-
mc
->
y
;
}
if
(
mc
->
w
<
(
x
+
outw
))
outw
-=
(
x
+
outw
)
-
(
mc
->
w
);
if
(
mc
->
h
<
(
y
+
outh
))
outh
-=
(
y
+
outh
)
-
(
mc
->
h
);
w
=
w
*
outw
/
orig_outw
;
h
=
h
*
outh
/
orig_outh
;
/* YUV mode overlay's input width has to be even and the
* algorithm above may adjust the width to be odd.
*
* Here we adjust the width if needed, preferring to increase
* the width if the original width was bigger.
*/
if
((
w
&
1
)
&&
(
oi
->
color_mode
==
OMAP_DSS_COLOR_YUV2
||
oi
->
color_mode
==
OMAP_DSS_COLOR_UYVY
))
{
if
(
orig_w
>
w
)
w
+=
1
;
else
w
-=
1
;
}
}
new_oi
=
*
oi
;
/* update new_oi members which could have been possibly updated */
new_oi
.
pos_x
=
x
;
new_oi
.
pos_y
=
y
;
new_oi
.
width
=
w
;
new_oi
.
height
=
h
;
new_oi
.
out_width
=
outw
;
new_oi
.
out_height
=
outh
;
new_oi
.
paddr
=
paddr
;
r
=
dispc_ovl_setup
(
plane
,
&
new_oi
,
c
->
ilace
,
c
->
channel
,
c
->
replication
,
c
->
fifo_low
,
c
->
fifo_high
);
if
(
r
)
{
/* this shouldn't happen */
DSSERR
(
"dispc_ovl_setup failed for ovl %d
\n
"
,
plane
);
dispc_ovl_enable
(
plane
,
0
);
return
r
;
}
dispc_ovl_enable
(
plane
,
1
);
return
0
;
}
static
void
configure_manager
(
enum
omap_channel
channel
)
{
struct
omap_overlay_manager_info
*
mi
;
DSSDBGF
(
"%d"
,
channel
);
/* picking info from the cache */
mi
=
&
dss_cache
.
manager_cache
[
channel
].
info
;
dispc_mgr_set_default_color
(
channel
,
mi
->
default_color
);
dispc_mgr_set_trans_key
(
channel
,
mi
->
trans_key_type
,
mi
->
trans_key
);
dispc_mgr_enable_trans_key
(
channel
,
mi
->
trans_enabled
);
dispc_mgr_enable_alpha_fixed_zorder
(
channel
,
mi
->
partial_alpha_enabled
);
if
(
dss_has_feature
(
FEAT_CPR
))
{
dispc_mgr_enable_cpr
(
channel
,
mi
->
cpr_enable
);
dispc_mgr_set_cpr_coef
(
channel
,
&
mi
->
cpr_coefs
);
}
}
/* configure_dispc() tries to write values from cache to shadow registers.
* It writes only to those managers/overlays that are not busy.
* returns 0 if everything could be written to shadow registers.
* returns 1 if not everything could be written to shadow registers. */
static
int
configure_dispc
(
void
)
{
struct
overlay_cache_data
*
oc
;
struct
manager_cache_data
*
mc
;
const
int
num_ovls
=
dss_feat_get_num_ovls
();
const
int
num_mgrs
=
dss_feat_get_num_mgrs
();
int
i
;
int
r
;
bool
mgr_busy
[
MAX_DSS_MANAGERS
];
bool
mgr_go
[
MAX_DSS_MANAGERS
];
bool
busy
;
r
=
0
;
busy
=
false
;
for
(
i
=
0
;
i
<
num_mgrs
;
i
++
)
{
mgr_busy
[
i
]
=
dispc_mgr_go_busy
(
i
);
mgr_go
[
i
]
=
false
;
}
/* Commit overlay settings */
for
(
i
=
0
;
i
<
num_ovls
;
++
i
)
{
oc
=
&
dss_cache
.
overlay_cache
[
i
];
mc
=
&
dss_cache
.
manager_cache
[
oc
->
channel
];
mgr
->
set_device
=
&
dss_mgr_set_device
;
mgr
->
unset_device
=
&
dss_mgr_unset_device
;
mgr
->
apply
=
&
omap_dss_mgr_apply
;
mgr
->
set_manager_info
=
&
dss_mgr_set_info
;
mgr
->
get_manager_info
=
&
dss_mgr_get_info
;
mgr
->
wait_for_go
=
&
dss_mgr_wait_for_go
;
mgr
->
wait_for_vsync
=
&
dss_mgr_wait_for_vsync
;
if
(
!
oc
->
dirty
)
continue
;
mgr
->
caps
=
0
;
mgr
->
supported_displays
=
dss_feat_get_supported_displays
(
mgr
->
id
);
if
(
mc
->
manual_update
&&
!
mc
->
do_manual_update
)
continue
;
INIT_LIST_HEAD
(
&
mgr
->
overlays
);
if
(
mgr_busy
[
oc
->
channel
])
{
busy
=
true
;
continue
;
}
r
=
kobject_init_and_add
(
&
mgr
->
kobj
,
&
manager_ktype
,
&
pdev
->
dev
.
kobj
,
"manager%d"
,
i
);
r
=
configure_overlay
(
i
);
if
(
r
)
DSSERR
(
"configure_overlay %d failed
\n
"
,
i
);
oc
->
dirty
=
false
;
oc
->
shadow_dirty
=
true
;
mgr_go
[
oc
->
channel
]
=
true
;
}
/* Commit manager settings */
for
(
i
=
0
;
i
<
num_mgrs
;
++
i
)
{
mc
=
&
dss_cache
.
manager_cache
[
i
];
if
(
!
mc
->
dirty
)
continue
;
if
(
mc
->
manual_update
&&
!
mc
->
do_manual_update
)
continue
;
if
(
mgr_busy
[
i
])
{
busy
=
true
;
continue
;
}
configure_manager
(
i
);
mc
->
dirty
=
false
;
mc
->
shadow_dirty
=
true
;
mgr_go
[
i
]
=
true
;
}
/* set GO */
for
(
i
=
0
;
i
<
num_mgrs
;
++
i
)
{
mc
=
&
dss_cache
.
manager_cache
[
i
];
if
(
!
mgr_go
[
i
])
continue
;
/* We don't need GO with manual update display. LCD iface will
* always be turned off after frame, and new settings will be
* taken in to use at next update */
if
(
!
mc
->
manual_update
)
dispc_mgr_go
(
i
);
}
if
(
busy
)
r
=
1
;
else
r
=
0
;
return
r
;
}
/* Make the coordinates even. There are some strange problems with OMAP and
* partial DSI update when the update widths are odd. */
static
void
make_even
(
u16
*
x
,
u16
*
w
)
{
u16
x1
,
x2
;
x1
=
*
x
;
x2
=
*
x
+
*
w
;
x1
&=
~
1
;
x2
=
ALIGN
(
x2
,
2
);
*
x
=
x1
;
*
w
=
x2
-
x1
;
}
/* Configure dispc for partial update. Return possibly modified update
* area */
void
dss_setup_partial_planes
(
struct
omap_dss_device
*
dssdev
,
u16
*
xi
,
u16
*
yi
,
u16
*
wi
,
u16
*
hi
,
bool
enlarge_update_area
)
{
struct
overlay_cache_data
*
oc
;
struct
manager_cache_data
*
mc
;
struct
omap_overlay_info
*
oi
;
const
int
num_ovls
=
dss_feat_get_num_ovls
();
struct
omap_overlay_manager
*
mgr
;
int
i
;
u16
x
,
y
,
w
,
h
;
unsigned
long
flags
;
bool
area_changed
;
x
=
*
xi
;
y
=
*
yi
;
w
=
*
wi
;
h
=
*
hi
;
DSSDBG
(
"dispc_setup_partial_planes %d,%d %dx%d
\n
"
,
*
xi
,
*
yi
,
*
wi
,
*
hi
);
mgr
=
dssdev
->
manager
;
if
(
!
mgr
)
{
DSSDBG
(
"no manager
\n
"
);
return
;
DSSERR
(
"failed to create sysfs file
\n
"
);
}
make_even
(
&
x
,
&
w
);
spin_lock_irqsave
(
&
dss_cache
.
lock
,
flags
);
/*
* Execute the outer loop until the inner loop has completed
* once without increasing the update area. This will ensure that
* all scaled overlays end up completely within the update area.
*/
do
{
area_changed
=
false
;
/* We need to show the whole overlay if it is scaled. So look
* for those, and make the update area larger if found.
* Also mark the overlay cache dirty */
for
(
i
=
0
;
i
<
num_ovls
;
++
i
)
{
unsigned
x1
,
y1
,
x2
,
y2
;
unsigned
outw
,
outh
;
oc
=
&
dss_cache
.
overlay_cache
[
i
];
oi
=
&
oc
->
info
;
if
(
oc
->
channel
!=
mgr
->
id
)
continue
;
oc
->
dirty
=
true
;
if
(
!
enlarge_update_area
)
continue
;
if
(
!
oc
->
enabled
)
continue
;
if
(
!
dispc_is_overlay_scaled
(
oc
))
continue
;
outw
=
oi
->
out_width
==
0
?
oi
->
width
:
oi
->
out_width
;
outh
=
oi
->
out_height
==
0
?
oi
->
height
:
oi
->
out_height
;
/* is the overlay outside the update region? */
if
(
!
rectangle_intersects
(
x
,
y
,
w
,
h
,
oi
->
pos_x
,
oi
->
pos_y
,
outw
,
outh
))
continue
;
/* if the overlay totally inside the update region? */
if
(
rectangle_subset
(
oi
->
pos_x
,
oi
->
pos_y
,
outw
,
outh
,
x
,
y
,
w
,
h
))
continue
;
if
(
x
>
oi
->
pos_x
)
x1
=
oi
->
pos_x
;
else
x1
=
x
;
if
(
y
>
oi
->
pos_y
)
y1
=
oi
->
pos_y
;
else
y1
=
y
;
if
((
x
+
w
)
<
(
oi
->
pos_x
+
outw
))
x2
=
oi
->
pos_x
+
outw
;
else
x2
=
x
+
w
;
if
((
y
+
h
)
<
(
oi
->
pos_y
+
outh
))
y2
=
oi
->
pos_y
+
outh
;
else
y2
=
y
+
h
;
x
=
x1
;
y
=
y1
;
w
=
x2
-
x1
;
h
=
y2
-
y1
;
make_even
(
&
x
,
&
w
);
DSSDBG
(
"changing upd area due to ovl(%d) "
"scaling %d,%d %dx%d
\n
"
,
i
,
x
,
y
,
w
,
h
);
area_changed
=
true
;
}
}
while
(
area_changed
);
mc
=
&
dss_cache
.
manager_cache
[
mgr
->
id
];
mc
->
do_manual_update
=
true
;
mc
->
enlarge_update_area
=
enlarge_update_area
;
mc
->
x
=
x
;
mc
->
y
=
y
;
mc
->
w
=
w
;
mc
->
h
=
h
;
configure_dispc
();
mc
->
do_manual_update
=
false
;
spin_unlock_irqrestore
(
&
dss_cache
.
lock
,
flags
);
*
xi
=
x
;
*
yi
=
y
;
*
wi
=
w
;
*
hi
=
h
;
return
0
;
}
void
dss_
start_update
(
struct
omap_dss_device
*
dss
dev
)
void
dss_
uninit_overlay_managers
(
struct
platform_device
*
p
dev
)
{
struct
manager_cache_data
*
mc
;
struct
overlay_cache_data
*
oc
;
const
int
num_ovls
=
dss_feat_get_num_ovls
();
const
int
num_mgrs
=
dss_feat_get_num_mgrs
();
struct
omap_overlay_manager
*
mgr
;
int
i
;
mgr
=
dssdev
->
manager
;
for
(
i
=
0
;
i
<
num_managers
;
++
i
)
{
struct
omap_overlay_manager
*
mgr
=
&
managers
[
i
];
for
(
i
=
0
;
i
<
num_ovls
;
++
i
)
{
oc
=
&
dss_cache
.
overlay_cache
[
i
];
if
(
oc
->
channel
!=
mgr
->
id
)
continue
;
oc
->
shadow_dirty
=
false
;
}
for
(
i
=
0
;
i
<
num_mgrs
;
++
i
)
{
mc
=
&
dss_cache
.
manager_cache
[
i
];
if
(
mgr
->
id
!=
i
)
continue
;
mc
->
shadow_dirty
=
false
;
kobject_del
(
&
mgr
->
kobj
);
kobject_put
(
&
mgr
->
kobj
);
}
dssdev
->
manager
->
enable
(
dssdev
->
manager
);
kfree
(
managers
);
managers
=
NULL
;
num_managers
=
0
;
}
static
void
dss_apply_irq_handler
(
void
*
data
,
u32
mask
)
int
omap_dss_get_num_overlay_managers
(
void
)
{
struct
manager_cache_data
*
mc
;
struct
overlay_cache_data
*
oc
;
const
int
num_ovls
=
dss_feat_get_num_ovls
();
const
int
num_mgrs
=
dss_feat_get_num_mgrs
();
int
i
,
r
;
bool
mgr_busy
[
MAX_DSS_MANAGERS
];
u32
irq_mask
;
for
(
i
=
0
;
i
<
num_mgrs
;
i
++
)
mgr_busy
[
i
]
=
dispc_mgr_go_busy
(
i
);
spin_lock
(
&
dss_cache
.
lock
);
for
(
i
=
0
;
i
<
num_ovls
;
++
i
)
{
oc
=
&
dss_cache
.
overlay_cache
[
i
];
if
(
!
mgr_busy
[
oc
->
channel
])
oc
->
shadow_dirty
=
false
;
}
for
(
i
=
0
;
i
<
num_mgrs
;
++
i
)
{
mc
=
&
dss_cache
.
manager_cache
[
i
];
if
(
!
mgr_busy
[
i
])
mc
->
shadow_dirty
=
false
;
}
r
=
configure_dispc
();
if
(
r
==
1
)
goto
end
;
/* re-read busy flags */
for
(
i
=
0
;
i
<
num_mgrs
;
i
++
)
mgr_busy
[
i
]
=
dispc_mgr_go_busy
(
i
);
/* keep running as long as there are busy managers, so that
* we can collect overlay-applied information */
for
(
i
=
0
;
i
<
num_mgrs
;
++
i
)
{
if
(
mgr_busy
[
i
])
goto
end
;
}
irq_mask
=
DISPC_IRQ_VSYNC
|
DISPC_IRQ_EVSYNC_ODD
|
DISPC_IRQ_EVSYNC_EVEN
;
if
(
dss_has_feature
(
FEAT_MGR_LCD2
))
irq_mask
|=
DISPC_IRQ_VSYNC2
;
omap_dispc_unregister_isr
(
dss_apply_irq_handler
,
NULL
,
irq_mask
);
dss_cache
.
irq_enabled
=
false
;
end:
spin_unlock
(
&
dss_cache
.
lock
);
return
num_managers
;
}
EXPORT_SYMBOL
(
omap_dss_get_num_overlay_managers
);
st
atic
int
omap_dss_mgr_apply
(
struct
omap_overlay_manager
*
mgr
)
st
ruct
omap_overlay_manager
*
omap_dss_get_overlay_manager
(
int
num
)
{
struct
overlay_cache_data
*
oc
;
struct
manager_cache_data
*
mc
;
int
i
;
struct
omap_overlay
*
ovl
;
int
num_planes_enabled
=
0
;
bool
use_fifomerge
;
unsigned
long
flags
;
int
r
;
DSSDBG
(
"omap_dss_mgr_apply(%s)
\n
"
,
mgr
->
name
);
r
=
dispc_runtime_get
();
if
(
r
)
return
r
;
spin_lock_irqsave
(
&
dss_cache
.
lock
,
flags
);
/* Configure overlays */
for
(
i
=
0
;
i
<
omap_dss_get_num_overlays
();
++
i
)
{
struct
omap_dss_device
*
dssdev
;
ovl
=
omap_dss_get_overlay
(
i
);
oc
=
&
dss_cache
.
overlay_cache
[
ovl
->
id
];
if
(
ovl
->
manager_changed
)
{
ovl
->
manager_changed
=
false
;
ovl
->
info_dirty
=
true
;
}
if
(
!
overlay_enabled
(
ovl
))
{
if
(
oc
->
enabled
)
{
oc
->
enabled
=
false
;
oc
->
dirty
=
true
;
}
continue
;
}
if
(
!
ovl
->
info_dirty
)
{
if
(
oc
->
enabled
)
++
num_planes_enabled
;
continue
;
}
dssdev
=
ovl
->
manager
->
device
;
if
(
dss_check_overlay
(
ovl
,
dssdev
))
{
if
(
oc
->
enabled
)
{
oc
->
enabled
=
false
;
oc
->
dirty
=
true
;
}
continue
;
}
ovl
->
info_dirty
=
false
;
oc
->
dirty
=
true
;
oc
->
info
=
ovl
->
info
;
oc
->
replication
=
dss_use_replication
(
dssdev
,
ovl
->
info
.
color_mode
);
oc
->
ilace
=
dssdev
->
type
==
OMAP_DISPLAY_TYPE_VENC
;
oc
->
channel
=
ovl
->
manager
->
id
;
oc
->
enabled
=
true
;
++
num_planes_enabled
;
}
/* Configure managers */
list_for_each_entry
(
mgr
,
&
manager_list
,
list
)
{
struct
omap_dss_device
*
dssdev
;
if
(
num
>=
num_managers
)
return
NULL
;
mc
=
&
dss_cache
.
manager_cache
[
mgr
->
id
];
if
(
mgr
->
device_changed
)
{
mgr
->
device_changed
=
false
;
mgr
->
info_dirty
=
true
;
}
if
(
!
mgr
->
info_dirty
)
continue
;
if
(
!
mgr
->
device
)
continue
;
dssdev
=
mgr
->
device
;
mgr
->
info_dirty
=
false
;
mc
->
dirty
=
true
;
mc
->
info
=
mgr
->
info
;
mc
->
manual_update
=
dssdev
->
caps
&
OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE
;
}
/* XXX TODO: Try to get fifomerge working. The problem is that it
* affects both managers, not individually but at the same time. This
* means the change has to be well synchronized. I guess the proper way
* is to have a two step process for fifo merge:
* fifomerge enable:
* 1. disable other planes, leaving one plane enabled
* 2. wait until the planes are disabled on HW
* 3. config merged fifo thresholds, enable fifomerge
* fifomerge disable:
* 1. config unmerged fifo thresholds, disable fifomerge
* 2. wait until fifo changes are in HW
* 3. enable planes
*/
use_fifomerge
=
false
;
/* Configure overlay fifos */
for
(
i
=
0
;
i
<
omap_dss_get_num_overlays
();
++
i
)
{
struct
omap_dss_device
*
dssdev
;
u32
size
,
burst_size
;
ovl
=
omap_dss_get_overlay
(
i
);
oc
=
&
dss_cache
.
overlay_cache
[
ovl
->
id
];
if
(
!
oc
->
enabled
)
continue
;
dssdev
=
ovl
->
manager
->
device
;
size
=
dispc_ovl_get_fifo_size
(
ovl
->
id
);
if
(
use_fifomerge
)
size
*=
3
;
burst_size
=
dispc_ovl_get_burst_size
(
ovl
->
id
);
switch
(
dssdev
->
type
)
{
case
OMAP_DISPLAY_TYPE_DPI
:
case
OMAP_DISPLAY_TYPE_DBI
:
case
OMAP_DISPLAY_TYPE_SDI
:
case
OMAP_DISPLAY_TYPE_VENC
:
case
OMAP_DISPLAY_TYPE_HDMI
:
default_get_overlay_fifo_thresholds
(
ovl
->
id
,
size
,
burst_size
,
&
oc
->
fifo_low
,
&
oc
->
fifo_high
);
break
;
#ifdef CONFIG_OMAP2_DSS_DSI
case
OMAP_DISPLAY_TYPE_DSI
:
dsi_get_overlay_fifo_thresholds
(
ovl
->
id
,
size
,
burst_size
,
&
oc
->
fifo_low
,
&
oc
->
fifo_high
);
break
;
#endif
default:
BUG
();
}
}
r
=
0
;
if
(
!
dss_cache
.
irq_enabled
)
{
u32
mask
;
mask
=
DISPC_IRQ_VSYNC
|
DISPC_IRQ_EVSYNC_ODD
|
DISPC_IRQ_EVSYNC_EVEN
;
if
(
dss_has_feature
(
FEAT_MGR_LCD2
))
mask
|=
DISPC_IRQ_VSYNC2
;
r
=
omap_dispc_register_isr
(
dss_apply_irq_handler
,
NULL
,
mask
);
dss_cache
.
irq_enabled
=
true
;
}
configure_dispc
();
spin_unlock_irqrestore
(
&
dss_cache
.
lock
,
flags
);
dispc_runtime_put
();
return
r
;
return
&
managers
[
num
];
}
EXPORT_SYMBOL
(
omap_dss_get_overlay_manager
);
static
int
dss_check_manager
(
struct
omap_overlay_manager
*
mgr
)
int
dss_mgr_simple_check
(
struct
omap_overlay_manager
*
mgr
,
const
struct
omap_overlay_manager_info
*
info
)
{
if
(
dss_has_feature
(
FEAT_ALPHA_FIXED_ZORDER
))
{
/*
* OMAP3 supports only graphics source transparency color key
* and alpha blending simultaneously. See TRM 15.4.2.4.2.2
* Alpha Mode
* Alpha Mode
.
*/
if
(
mgr
->
info
.
partial_alpha_enabled
&&
mgr
->
info
.
trans_enabled
&&
mgr
->
info
.
trans_key_type
!=
OMAP_DSS_COLOR_KEY_GFX_DST
)
if
(
info
->
partial_alpha_enabled
&&
info
->
trans_enabled
&&
info
->
trans_key_type
!=
OMAP_DSS_COLOR_KEY_GFX_DST
)
{
DSSERR
(
"check_manager: illegal transparency key
\n
"
);
return
-
EINVAL
;
}
}
return
0
;
}
static
int
omap_dss_mgr_set_info
(
struct
omap_overlay_manager
*
mgr
,
struct
omap_overlay_manager_info
*
info
)
{
int
r
;
struct
omap_overlay_manager_info
old_info
;
old_info
=
mgr
->
info
;
mgr
->
info
=
*
info
;
r
=
dss_check_manager
(
mgr
);
if
(
r
)
{
mgr
->
info
=
old_info
;
return
r
;
}
mgr
->
info_dirty
=
true
;
return
0
;
}
static
void
omap_dss_mgr_get_info
(
struct
omap_overlay_manager
*
mgr
,
struct
omap_overlay_manager_info
*
info
)
static
int
dss_mgr_check_zorder
(
struct
omap_overlay_manager
*
mgr
,
struct
omap_overlay_info
**
overlay_infos
)
{
*
info
=
mgr
->
info
;
}
struct
omap_overlay
*
ovl1
,
*
ovl2
;
struct
omap_overlay_info
*
info1
,
*
info2
;
static
int
dss_mgr_enable
(
struct
omap_overlay_manager
*
mgr
)
{
dispc_mgr_enable
(
mgr
->
id
,
1
);
return
0
;
}
list_for_each_entry
(
ovl1
,
&
mgr
->
overlays
,
list
)
{
info1
=
overlay_infos
[
ovl1
->
id
];
static
int
dss_mgr_disable
(
struct
omap_overlay_manager
*
mgr
)
{
dispc_mgr_enable
(
mgr
->
id
,
0
);
return
0
;
}
static
void
omap_dss_add_overlay_manager
(
struct
omap_overlay_manager
*
manager
)
{
++
num_managers
;
list_add_tail
(
&
manager
->
list
,
&
manager_list
);
}
int
dss_init_overlay_managers
(
struct
platform_device
*
pdev
)
{
int
i
,
r
;
spin_lock_init
(
&
dss_cache
.
lock
);
INIT_LIST_HEAD
(
&
manager_list
);
num_managers
=
0
;
for
(
i
=
0
;
i
<
dss_feat_get_num_mgrs
();
++
i
)
{
struct
omap_overlay_manager
*
mgr
;
mgr
=
kzalloc
(
sizeof
(
*
mgr
),
GFP_KERNEL
);
BUG_ON
(
mgr
==
NULL
);
switch
(
i
)
{
case
0
:
mgr
->
name
=
"lcd"
;
mgr
->
id
=
OMAP_DSS_CHANNEL_LCD
;
break
;
case
1
:
mgr
->
name
=
"tv"
;
mgr
->
id
=
OMAP_DSS_CHANNEL_DIGIT
;
break
;
case
2
:
mgr
->
name
=
"lcd2"
;
mgr
->
id
=
OMAP_DSS_CHANNEL_LCD2
;
break
;
}
mgr
->
set_device
=
&
omap_dss_set_device
;
mgr
->
unset_device
=
&
omap_dss_unset_device
;
mgr
->
apply
=
&
omap_dss_mgr_apply
;
mgr
->
set_manager_info
=
&
omap_dss_mgr_set_info
;
mgr
->
get_manager_info
=
&
omap_dss_mgr_get_info
;
mgr
->
wait_for_go
=
&
dss_mgr_wait_for_go
;
mgr
->
wait_for_vsync
=
&
dss_mgr_wait_for_vsync
;
mgr
->
enable
=
&
dss_mgr_enable
;
mgr
->
disable
=
&
dss_mgr_disable
;
mgr
->
caps
=
0
;
mgr
->
supported_displays
=
dss_feat_get_supported_displays
(
mgr
->
id
);
if
(
info1
==
NULL
)
continue
;
dss_overlay_setup_dispc_manager
(
mgr
);
list_for_each_entry
(
ovl2
,
&
mgr
->
overlays
,
list
)
{
if
(
ovl1
==
ovl2
)
continue
;
omap_dss_add_overlay_manager
(
mgr
)
;
info2
=
overlay_infos
[
ovl2
->
id
]
;
r
=
kobject_init_and_add
(
&
mgr
->
kobj
,
&
manager_ktype
,
&
pdev
->
dev
.
kobj
,
"manager%d"
,
i
)
;
if
(
info2
==
NULL
)
continue
;
if
(
r
)
{
DSSERR
(
"failed to create sysfs file
\n
"
);
continue
;
if
(
info1
->
zorder
==
info2
->
zorder
)
{
DSSERR
(
"overlays %d and %d have the same "
"zorder %d
\n
"
,
ovl1
->
id
,
ovl2
->
id
,
info1
->
zorder
);
return
-
EINVAL
;
}
}
}
return
0
;
}
void
dss_uninit_overlay_managers
(
struct
platform_device
*
pdev
)
int
dss_mgr_check
(
struct
omap_overlay_manager
*
mgr
,
struct
omap_dss_device
*
dssdev
,
struct
omap_overlay_manager_info
*
info
,
struct
omap_overlay_info
**
overlay_infos
)
{
struct
omap_overlay_manager
*
mgr
;
struct
omap_overlay
*
ovl
;
int
r
;
while
(
!
list_empty
(
&
manager_list
))
{
mgr
=
list_first_entry
(
&
manager_list
,
struct
omap_overlay_manager
,
list
);
list_del
(
&
mgr
->
list
);
kobject_del
(
&
mgr
->
kobj
);
kobject_put
(
&
mgr
->
kobj
);
kfree
(
mgr
);
if
(
dss_has_feature
(
FEAT_ALPHA_FREE_ZORDER
))
{
r
=
dss_mgr_check_zorder
(
mgr
,
overlay_infos
);
if
(
r
)
return
r
;
}
num_managers
=
0
;
}
list_for_each_entry
(
ovl
,
&
mgr
->
overlays
,
list
)
{
struct
omap_overlay_info
*
oi
;
int
r
;
int
omap_dss_get_num_overlay_managers
(
void
)
{
return
num_managers
;
}
EXPORT_SYMBOL
(
omap_dss_get_num_overlay_managers
);
oi
=
overlay_infos
[
ovl
->
id
];
struct
omap_overlay_manager
*
omap_dss_get_overlay_manager
(
int
num
)
{
int
i
=
0
;
struct
omap_overlay_manager
*
mgr
;
if
(
oi
==
NULL
)
continue
;
list_for_each_entry
(
mgr
,
&
manager_list
,
list
)
{
if
(
i
++
==
num
)
return
mg
r
;
r
=
dss_ovl_check
(
ovl
,
oi
,
dssdev
);
if
(
r
)
return
r
;
}
return
NULL
;
return
0
;
}
EXPORT_SYMBOL
(
omap_dss_get_overlay_manager
);
drivers/video/omap2/dss/overlay.c
View file @
193984f4
...
...
@@ -38,7 +38,7 @@
#include "dss_features.h"
static
int
num_overlays
;
static
struct
list_head
overlay_list
;
static
struct
omap_overlay
*
overlays
;
static
ssize_t
overlay_name_show
(
struct
omap_overlay
*
ovl
,
char
*
buf
)
{
...
...
@@ -124,19 +124,31 @@ static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf,
static
ssize_t
overlay_input_size_show
(
struct
omap_overlay
*
ovl
,
char
*
buf
)
{
struct
omap_overlay_info
info
;
ovl
->
get_overlay_info
(
ovl
,
&
info
);
return
snprintf
(
buf
,
PAGE_SIZE
,
"%d,%d
\n
"
,
ovl
->
info
.
width
,
ovl
->
info
.
height
);
info
.
width
,
info
.
height
);
}
static
ssize_t
overlay_screen_width_show
(
struct
omap_overlay
*
ovl
,
char
*
buf
)
{
return
snprintf
(
buf
,
PAGE_SIZE
,
"%d
\n
"
,
ovl
->
info
.
screen_width
);
struct
omap_overlay_info
info
;
ovl
->
get_overlay_info
(
ovl
,
&
info
);
return
snprintf
(
buf
,
PAGE_SIZE
,
"%d
\n
"
,
info
.
screen_width
);
}
static
ssize_t
overlay_position_show
(
struct
omap_overlay
*
ovl
,
char
*
buf
)
{
struct
omap_overlay_info
info
;
ovl
->
get_overlay_info
(
ovl
,
&
info
);
return
snprintf
(
buf
,
PAGE_SIZE
,
"%d,%d
\n
"
,
ovl
->
info
.
pos_x
,
ovl
->
info
.
pos_y
);
info
.
pos_x
,
info
.
pos_y
);
}
static
ssize_t
overlay_position_store
(
struct
omap_overlay
*
ovl
,
...
...
@@ -170,8 +182,12 @@ static ssize_t overlay_position_store(struct omap_overlay *ovl,
static
ssize_t
overlay_output_size_show
(
struct
omap_overlay
*
ovl
,
char
*
buf
)
{
struct
omap_overlay_info
info
;
ovl
->
get_overlay_info
(
ovl
,
&
info
);
return
snprintf
(
buf
,
PAGE_SIZE
,
"%d,%d
\n
"
,
ovl
->
info
.
out_width
,
ovl
->
info
.
out_height
);
info
.
out_width
,
info
.
out_height
);
}
static
ssize_t
overlay_output_size_store
(
struct
omap_overlay
*
ovl
,
...
...
@@ -205,7 +221,7 @@ static ssize_t overlay_output_size_store(struct omap_overlay *ovl,
static
ssize_t
overlay_enabled_show
(
struct
omap_overlay
*
ovl
,
char
*
buf
)
{
return
snprintf
(
buf
,
PAGE_SIZE
,
"%d
\n
"
,
ovl
->
i
nfo
.
enabled
);
return
snprintf
(
buf
,
PAGE_SIZE
,
"%d
\n
"
,
ovl
->
i
s_enabled
(
ovl
)
);
}
static
ssize_t
overlay_enabled_store
(
struct
omap_overlay
*
ovl
,
const
char
*
buf
,
...
...
@@ -213,33 +229,30 @@ static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf,
{
int
r
;
bool
enable
;
struct
omap_overlay_info
info
;
ovl
->
get_overlay_info
(
ovl
,
&
info
);
r
=
strtobool
(
buf
,
&
enable
);
if
(
r
)
return
r
;
info
.
enabled
=
enable
;
if
(
enable
)
r
=
ovl
->
enable
(
ovl
);
else
r
=
ovl
->
disable
(
ovl
);
r
=
ovl
->
set_overlay_info
(
ovl
,
&
info
);
if
(
r
)
return
r
;
if
(
ovl
->
manager
)
{
r
=
ovl
->
manager
->
apply
(
ovl
->
manager
);
if
(
r
)
return
r
;
}
return
size
;
}
static
ssize_t
overlay_global_alpha_show
(
struct
omap_overlay
*
ovl
,
char
*
buf
)
{
struct
omap_overlay_info
info
;
ovl
->
get_overlay_info
(
ovl
,
&
info
);
return
snprintf
(
buf
,
PAGE_SIZE
,
"%d
\n
"
,
ovl
->
info
.
global_alpha
);
info
.
global_alpha
);
}
static
ssize_t
overlay_global_alpha_store
(
struct
omap_overlay
*
ovl
,
...
...
@@ -276,8 +289,12 @@ static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
static
ssize_t
overlay_pre_mult_alpha_show
(
struct
omap_overlay
*
ovl
,
char
*
buf
)
{
struct
omap_overlay_info
info
;
ovl
->
get_overlay_info
(
ovl
,
&
info
);
return
snprintf
(
buf
,
PAGE_SIZE
,
"%d
\n
"
,
ovl
->
info
.
pre_mult_alpha
);
info
.
pre_mult_alpha
);
}
static
ssize_t
overlay_pre_mult_alpha_store
(
struct
omap_overlay
*
ovl
,
...
...
@@ -313,7 +330,11 @@ static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl,
static
ssize_t
overlay_zorder_show
(
struct
omap_overlay
*
ovl
,
char
*
buf
)
{
return
snprintf
(
buf
,
PAGE_SIZE
,
"%d
\n
"
,
ovl
->
info
.
zorder
);
struct
omap_overlay_info
info
;
ovl
->
get_overlay_info
(
ovl
,
&
info
);
return
snprintf
(
buf
,
PAGE_SIZE
,
"%d
\n
"
,
info
.
zorder
);
}
static
ssize_t
overlay_zorder_store
(
struct
omap_overlay
*
ovl
,
...
...
@@ -430,183 +451,6 @@ static struct kobj_type overlay_ktype = {
.
default_attrs
=
overlay_sysfs_attrs
,
};
/* Check if overlay parameters are compatible with display */
int
dss_check_overlay
(
struct
omap_overlay
*
ovl
,
struct
omap_dss_device
*
dssdev
)
{
struct
omap_overlay_info
*
info
;
u16
outw
,
outh
;
u16
dw
,
dh
;
int
i
;
if
(
!
dssdev
)
return
0
;
if
(
!
ovl
->
info
.
enabled
)
return
0
;
info
=
&
ovl
->
info
;
if
(
info
->
paddr
==
0
)
{
DSSDBG
(
"check_overlay failed: paddr 0
\n
"
);
return
-
EINVAL
;
}
dssdev
->
driver
->
get_resolution
(
dssdev
,
&
dw
,
&
dh
);
DSSDBG
(
"check_overlay %d: (%d,%d %dx%d -> %dx%d) disp (%dx%d)
\n
"
,
ovl
->
id
,
info
->
pos_x
,
info
->
pos_y
,
info
->
width
,
info
->
height
,
info
->
out_width
,
info
->
out_height
,
dw
,
dh
);
if
((
ovl
->
caps
&
OMAP_DSS_OVL_CAP_SCALE
)
==
0
)
{
outw
=
info
->
width
;
outh
=
info
->
height
;
}
else
{
if
(
info
->
out_width
==
0
)
outw
=
info
->
width
;
else
outw
=
info
->
out_width
;
if
(
info
->
out_height
==
0
)
outh
=
info
->
height
;
else
outh
=
info
->
out_height
;
}
if
(
dw
<
info
->
pos_x
+
outw
)
{
DSSDBG
(
"check_overlay failed 1: %d < %d + %d
\n
"
,
dw
,
info
->
pos_x
,
outw
);
return
-
EINVAL
;
}
if
(
dh
<
info
->
pos_y
+
outh
)
{
DSSDBG
(
"check_overlay failed 2: %d < %d + %d
\n
"
,
dh
,
info
->
pos_y
,
outh
);
return
-
EINVAL
;
}
if
((
ovl
->
supported_modes
&
info
->
color_mode
)
==
0
)
{
DSSERR
(
"overlay doesn't support mode %d
\n
"
,
info
->
color_mode
);
return
-
EINVAL
;
}
if
(
ovl
->
caps
&
OMAP_DSS_OVL_CAP_ZORDER
)
{
if
(
info
->
zorder
<
0
||
info
->
zorder
>
3
)
{
DSSERR
(
"zorder out of range: %d
\n
"
,
info
->
zorder
);
return
-
EINVAL
;
}
/*
* Check that zorder doesn't match with zorder of any other
* overlay which is enabled and is also connected to the same
* manager
*/
for
(
i
=
0
;
i
<
omap_dss_get_num_overlays
();
i
++
)
{
struct
omap_overlay
*
tmp_ovl
=
omap_dss_get_overlay
(
i
);
if
(
tmp_ovl
->
id
!=
ovl
->
id
&&
tmp_ovl
->
manager
==
ovl
->
manager
&&
tmp_ovl
->
info
.
enabled
==
true
&&
tmp_ovl
->
info
.
zorder
==
info
->
zorder
)
{
DSSERR
(
"%s and %s have same zorder: %d
\n
"
,
ovl
->
name
,
tmp_ovl
->
name
,
info
->
zorder
);
return
-
EINVAL
;
}
}
}
return
0
;
}
static
int
dss_ovl_set_overlay_info
(
struct
omap_overlay
*
ovl
,
struct
omap_overlay_info
*
info
)
{
int
r
;
struct
omap_overlay_info
old_info
;
old_info
=
ovl
->
info
;
ovl
->
info
=
*
info
;
if
(
ovl
->
manager
)
{
r
=
dss_check_overlay
(
ovl
,
ovl
->
manager
->
device
);
if
(
r
)
{
ovl
->
info
=
old_info
;
return
r
;
}
}
ovl
->
info_dirty
=
true
;
return
0
;
}
static
void
dss_ovl_get_overlay_info
(
struct
omap_overlay
*
ovl
,
struct
omap_overlay_info
*
info
)
{
*
info
=
ovl
->
info
;
}
static
int
dss_ovl_wait_for_go
(
struct
omap_overlay
*
ovl
)
{
return
dss_mgr_wait_for_go_ovl
(
ovl
);
}
static
int
omap_dss_set_manager
(
struct
omap_overlay
*
ovl
,
struct
omap_overlay_manager
*
mgr
)
{
if
(
!
mgr
)
return
-
EINVAL
;
if
(
ovl
->
manager
)
{
DSSERR
(
"overlay '%s' already has a manager '%s'
\n
"
,
ovl
->
name
,
ovl
->
manager
->
name
);
return
-
EINVAL
;
}
if
(
ovl
->
info
.
enabled
)
{
DSSERR
(
"overlay has to be disabled to change the manager
\n
"
);
return
-
EINVAL
;
}
ovl
->
manager
=
mgr
;
ovl
->
manager_changed
=
true
;
/* XXX: When there is an overlay on a DSI manual update display, and
* the overlay is first disabled, then moved to tv, and enabled, we
* seem to get SYNC_LOST_DIGIT error.
*
* Waiting doesn't seem to help, but updating the manual update display
* after disabling the overlay seems to fix this. This hints that the
* overlay is perhaps somehow tied to the LCD output until the output
* is updated.
*
* Userspace workaround for this is to update the LCD after disabling
* the overlay, but before moving the overlay to TV.
*/
return
0
;
}
static
int
omap_dss_unset_manager
(
struct
omap_overlay
*
ovl
)
{
if
(
!
ovl
->
manager
)
{
DSSERR
(
"failed to detach overlay: manager not set
\n
"
);
return
-
EINVAL
;
}
if
(
ovl
->
info
.
enabled
)
{
DSSERR
(
"overlay has to be disabled to unset the manager
\n
"
);
return
-
EINVAL
;
}
ovl
->
manager
=
NULL
;
ovl
->
manager_changed
=
true
;
return
0
;
}
int
omap_dss_get_num_overlays
(
void
)
{
return
num_overlays
;
...
...
@@ -615,134 +459,65 @@ EXPORT_SYMBOL(omap_dss_get_num_overlays);
struct
omap_overlay
*
omap_dss_get_overlay
(
int
num
)
{
i
nt
i
=
0
;
struct
omap_overlay
*
ovl
;
i
f
(
num
>=
num_overlays
)
return
NULL
;
list_for_each_entry
(
ovl
,
&
overlay_list
,
list
)
{
if
(
i
++
==
num
)
return
ovl
;
}
return
NULL
;
return
&
overlays
[
num
];
}
EXPORT_SYMBOL
(
omap_dss_get_overlay
);
static
void
omap_dss_add_overlay
(
struct
omap_overlay
*
overlay
)
{
++
num_overlays
;
list_add_tail
(
&
overlay
->
list
,
&
overlay_list
);
}
static
struct
omap_overlay
*
dispc_overlays
[
MAX_DSS_OVERLAYS
];
void
dss_overlay_setup_dispc_manager
(
struct
omap_overlay_manager
*
mgr
)
{
mgr
->
num_overlays
=
dss_feat_get_num_ovls
();
mgr
->
overlays
=
dispc_overlays
;
}
#ifdef L4_EXAMPLE
static
struct
omap_overlay
*
l4_overlays
[
1
];
void
dss_overlay_setup_l4_manager
(
struct
omap_overlay_manager
*
mgr
)
{
mgr
->
num_overlays
=
1
;
mgr
->
overlays
=
l4_overlays
;
}
#endif
void
dss_init_overlays
(
struct
platform_device
*
pdev
)
{
int
i
,
r
;
INIT_LIST_HEAD
(
&
overlay_list
);
num_overlays
=
dss_feat_get_num_ovls
(
);
num_overlays
=
0
;
overlays
=
kzalloc
(
sizeof
(
struct
omap_overlay
)
*
num_overlays
,
GFP_KERNEL
);
for
(
i
=
0
;
i
<
dss_feat_get_num_ovls
();
++
i
)
{
struct
omap_overlay
*
ovl
;
ovl
=
kzalloc
(
sizeof
(
*
ovl
),
GFP_KERNEL
);
BUG_ON
(
overlays
==
NULL
);
BUG_ON
(
ovl
==
NULL
);
for
(
i
=
0
;
i
<
num_overlays
;
++
i
)
{
struct
omap_overlay
*
ovl
=
&
overlays
[
i
];
switch
(
i
)
{
case
0
:
ovl
->
name
=
"gfx"
;
ovl
->
id
=
OMAP_DSS_GFX
;
ovl
->
info
.
global_alpha
=
255
;
ovl
->
info
.
zorder
=
0
;
break
;
case
1
:
ovl
->
name
=
"vid1"
;
ovl
->
id
=
OMAP_DSS_VIDEO1
;
ovl
->
info
.
global_alpha
=
255
;
ovl
->
info
.
zorder
=
dss_has_feature
(
FEAT_ALPHA_FREE_ZORDER
)
?
3
:
0
;
break
;
case
2
:
ovl
->
name
=
"vid2"
;
ovl
->
id
=
OMAP_DSS_VIDEO2
;
ovl
->
info
.
global_alpha
=
255
;
ovl
->
info
.
zorder
=
dss_has_feature
(
FEAT_ALPHA_FREE_ZORDER
)
?
2
:
0
;
break
;
case
3
:
ovl
->
name
=
"vid3"
;
ovl
->
id
=
OMAP_DSS_VIDEO3
;
ovl
->
info
.
global_alpha
=
255
;
ovl
->
info
.
zorder
=
dss_has_feature
(
FEAT_ALPHA_FREE_ZORDER
)
?
1
:
0
;
break
;
}
ovl
->
set_manager
=
&
omap_dss_set_manager
;
ovl
->
unset_manager
=
&
omap_dss_unset_manager
;
ovl
->
set_overlay_info
=
&
dss_ovl_set_overlay_info
;
ovl
->
get_overlay_info
=
&
dss_ovl_get_overlay_info
;
ovl
->
wait_for_go
=
&
dss_ovl_wait_for_go
;
ovl
->
is_enabled
=
&
dss_ovl_is_enabled
;
ovl
->
enable
=
&
dss_ovl_enable
;
ovl
->
disable
=
&
dss_ovl_disable
;
ovl
->
set_manager
=
&
dss_ovl_set_manager
;
ovl
->
unset_manager
=
&
dss_ovl_unset_manager
;
ovl
->
set_overlay_info
=
&
dss_ovl_set_info
;
ovl
->
get_overlay_info
=
&
dss_ovl_get_info
;
ovl
->
wait_for_go
=
&
dss_mgr_wait_for_go_ovl
;
ovl
->
caps
=
dss_feat_get_overlay_caps
(
ovl
->
id
);
ovl
->
supported_modes
=
dss_feat_get_supported_color_modes
(
ovl
->
id
);
omap_dss_add_overlay
(
ovl
);
r
=
kobject_init_and_add
(
&
ovl
->
kobj
,
&
overlay_ktype
,
&
pdev
->
dev
.
kobj
,
"overlay%d"
,
i
);
if
(
r
)
{
DSSERR
(
"failed to create sysfs file
\n
"
);
continue
;
}
dispc_overlays
[
i
]
=
ovl
;
}
#ifdef L4_EXAMPLE
{
struct
omap_overlay
*
ovl
;
ovl
=
kzalloc
(
sizeof
(
*
ovl
),
GFP_KERNEL
);
BUG_ON
(
ovl
==
NULL
);
ovl
->
name
=
"l4"
;
ovl
->
supported_modes
=
OMAP_DSS_COLOR_RGB24U
;
ovl
->
set_manager
=
&
omap_dss_set_manager
;
ovl
->
unset_manager
=
&
omap_dss_unset_manager
;
ovl
->
set_overlay_info
=
&
dss_ovl_set_overlay_info
;
ovl
->
get_overlay_info
=
&
dss_ovl_get_overlay_info
;
omap_dss_add_overlay
(
ovl
);
r
=
kobject_init_and_add
(
&
ovl
->
kobj
,
&
overlay_ktype
,
&
pdev
->
dev
.
kobj
,
"overlayl4"
);
if
(
r
)
DSSERR
(
"failed to create sysfs file
\n
"
);
l4_overlays
[
0
]
=
ovl
;
}
#endif
}
/* connect overlays to the new device, if not already connected. if force
...
...
@@ -795,8 +570,8 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force)
ovl
=
omap_dss_get_overlay
(
i
);
if
(
!
ovl
->
manager
||
force
)
{
if
(
ovl
->
manager
)
o
map_dss_
unset_manager
(
ovl
);
o
map_dss_
set_manager
(
ovl
,
mgr
);
o
vl
->
unset_manager
(
ovl
);
o
vl
->
set_manager
(
ovl
,
mgr
);
}
}
...
...
@@ -806,17 +581,95 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force)
void
dss_uninit_overlays
(
struct
platform_device
*
pdev
)
{
struct
omap_overlay
*
ovl
;
int
i
;
for
(
i
=
0
;
i
<
num_overlays
;
++
i
)
{
struct
omap_overlay
*
ovl
=
&
overlays
[
i
];
while
(
!
list_empty
(
&
overlay_list
))
{
ovl
=
list_first_entry
(
&
overlay_list
,
struct
omap_overlay
,
list
);
list_del
(
&
ovl
->
list
);
kobject_del
(
&
ovl
->
kobj
);
kobject_put
(
&
ovl
->
kobj
);
kfree
(
ovl
);
}
kfree
(
overlays
);
overlays
=
NULL
;
num_overlays
=
0
;
}
int
dss_ovl_simple_check
(
struct
omap_overlay
*
ovl
,
const
struct
omap_overlay_info
*
info
)
{
if
(
info
->
paddr
==
0
)
{
DSSERR
(
"check_overlay: paddr cannot be 0
\n
"
);
return
-
EINVAL
;
}
if
((
ovl
->
caps
&
OMAP_DSS_OVL_CAP_SCALE
)
==
0
)
{
if
(
info
->
out_width
!=
0
&&
info
->
width
!=
info
->
out_width
)
{
DSSERR
(
"check_overlay: overlay %d doesn't support "
"scaling
\n
"
,
ovl
->
id
);
return
-
EINVAL
;
}
if
(
info
->
out_height
!=
0
&&
info
->
height
!=
info
->
out_height
)
{
DSSERR
(
"check_overlay: overlay %d doesn't support "
"scaling
\n
"
,
ovl
->
id
);
return
-
EINVAL
;
}
}
if
((
ovl
->
supported_modes
&
info
->
color_mode
)
==
0
)
{
DSSERR
(
"check_overlay: overlay %d doesn't support mode %d
\n
"
,
ovl
->
id
,
info
->
color_mode
);
return
-
EINVAL
;
}
if
(
info
->
zorder
>=
omap_dss_get_num_overlays
())
{
DSSERR
(
"check_overlay: zorder %d too high
\n
"
,
info
->
zorder
);
return
-
EINVAL
;
}
return
0
;
}
int
dss_ovl_check
(
struct
omap_overlay
*
ovl
,
struct
omap_overlay_info
*
info
,
struct
omap_dss_device
*
dssdev
)
{
u16
outw
,
outh
;
u16
dw
,
dh
;
if
(
dssdev
==
NULL
)
return
0
;
dssdev
->
driver
->
get_resolution
(
dssdev
,
&
dw
,
&
dh
);
if
((
ovl
->
caps
&
OMAP_DSS_OVL_CAP_SCALE
)
==
0
)
{
outw
=
info
->
width
;
outh
=
info
->
height
;
}
else
{
if
(
info
->
out_width
==
0
)
outw
=
info
->
width
;
else
outw
=
info
->
out_width
;
if
(
info
->
out_height
==
0
)
outh
=
info
->
height
;
else
outh
=
info
->
out_height
;
}
if
(
dw
<
info
->
pos_x
+
outw
)
{
DSSERR
(
"overlay %d horizontally not inside the display area "
"(%d + %d >= %d)
\n
"
,
ovl
->
id
,
info
->
pos_x
,
outw
,
dw
);
return
-
EINVAL
;
}
if
(
dh
<
info
->
pos_y
+
outh
)
{
DSSERR
(
"overlay %d vertically not inside the display area "
"(%d + %d >= %d)
\n
"
,
ovl
->
id
,
info
->
pos_y
,
outh
,
dh
);
return
-
EINVAL
;
}
return
0
;
}
drivers/video/omap2/dss/rfbi.c
View file @
193984f4
...
...
@@ -784,7 +784,6 @@ int omap_rfbi_prepare_update(struct omap_dss_device *dssdev,
if
(
*
w
==
0
||
*
h
==
0
)
return
-
EINVAL
;
dss_setup_partial_planes
(
dssdev
,
x
,
y
,
w
,
h
,
true
);
dispc_mgr_set_lcd_size
(
dssdev
->
manager
->
id
,
*
w
,
*
h
);
return
0
;
...
...
drivers/video/omap2/dss/sdi.c
View file @
193984f4
...
...
@@ -123,10 +123,14 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
goto
err_sdi_enable
;
mdelay
(
2
);
dssdev
->
manager
->
enable
(
dssdev
->
manager
);
r
=
dss_mgr_enable
(
dssdev
->
manager
);
if
(
r
)
goto
err_mgr_enable
;
return
0
;
err_mgr_enable:
dss_sdi_disable
();
err_sdi_enable:
err_set_dispc_clock_div:
err_set_dss_clock_div:
...
...
@@ -145,7 +149,7 @@ EXPORT_SYMBOL(omapdss_sdi_display_enable);
void
omapdss_sdi_display_disable
(
struct
omap_dss_device
*
dssdev
)
{
dss
dev
->
manager
->
disable
(
dssdev
->
manager
);
dss
_mgr_
disable
(
dssdev
->
manager
);
dss_sdi_disable
();
...
...
drivers/video/omap2/dss/ti_hdmi.h
View file @
193984f4
...
...
@@ -110,6 +110,11 @@ struct ti_hdmi_ip_ops {
void
(
*
dump_phy
)(
struct
hdmi_ip_data
*
ip_data
,
struct
seq_file
*
s
);
#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
void
(
*
audio_enable
)(
struct
hdmi_ip_data
*
ip_data
,
bool
start
);
#endif
};
struct
hdmi_ip_data
{
...
...
@@ -134,5 +139,8 @@ void ti_hdmi_4xxx_wp_dump(struct hdmi_ip_data *ip_data, struct seq_file *s);
void
ti_hdmi_4xxx_pll_dump
(
struct
hdmi_ip_data
*
ip_data
,
struct
seq_file
*
s
);
void
ti_hdmi_4xxx_core_dump
(
struct
hdmi_ip_data
*
ip_data
,
struct
seq_file
*
s
);
void
ti_hdmi_4xxx_phy_dump
(
struct
hdmi_ip_data
*
ip_data
,
struct
seq_file
*
s
);
#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
void
ti_hdmi_4xxx_wp_audio_enable
(
struct
hdmi_ip_data
*
ip_data
,
bool
enable
);
#endif
#endif
drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
View file @
193984f4
...
...
@@ -1204,36 +1204,13 @@ int hdmi_config_audio_acr(struct hdmi_ip_data *ip_data,
return
0
;
}
int
hdmi_audio_trigger
(
struct
hdmi_ip_data
*
ip_data
,
struct
snd_pcm_substream
*
substream
,
int
cmd
,
struct
snd_soc_dai
*
dai
)
void
ti_hdmi_4xxx_wp_audio_enable
(
struct
hdmi_ip_data
*
ip_data
,
bool
enable
)
{
int
err
=
0
;
switch
(
cmd
)
{
case
SNDRV_PCM_TRIGGER_START
:
case
SNDRV_PCM_TRIGGER_RESUME
:
case
SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
REG_FLD_MOD
(
hdmi_av_base
(
ip_data
),
HDMI_CORE_AV_AUD_MODE
,
1
,
0
,
0
);
REG_FLD_MOD
(
hdmi_wp_base
(
ip_data
),
HDMI_WP_AUDIO_CTRL
,
1
,
31
,
31
);
REG_FLD_MOD
(
hdmi_wp_base
(
ip_data
),
HDMI_WP_AUDIO_CTRL
,
1
,
30
,
30
);
break
;
case
SNDRV_PCM_TRIGGER_STOP
:
case
SNDRV_PCM_TRIGGER_SUSPEND
:
case
SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
REG_FLD_MOD
(
hdmi_av_base
(
ip_data
),
HDMI_CORE_AV_AUD_MODE
,
0
,
0
,
0
);
REG_FLD_MOD
(
hdmi_wp_base
(
ip_data
),
HDMI_WP_AUDIO_CTRL
,
0
,
30
,
30
);
REG_FLD_MOD
(
hdmi_wp_base
(
ip_data
),
HDMI_WP_AUDIO_CTRL
,
0
,
31
,
31
);
break
;
default:
err
=
-
EINVAL
;
}
return
err
;
REG_FLD_MOD
(
hdmi_av_base
(
ip_data
),
HDMI_CORE_AV_AUD_MODE
,
enable
,
0
,
0
);
REG_FLD_MOD
(
hdmi_wp_base
(
ip_data
),
HDMI_WP_AUDIO_CTRL
,
enable
,
31
,
31
);
REG_FLD_MOD
(
hdmi_wp_base
(
ip_data
),
HDMI_WP_AUDIO_CTRL
,
enable
,
30
,
30
);
}
#endif
drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h
View file @
193984f4
...
...
@@ -576,9 +576,6 @@ struct hdmi_core_audio_config {
#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
int
hdmi_audio_trigger
(
struct
hdmi_ip_data
*
ip_data
,
struct
snd_pcm_substream
*
substream
,
int
cmd
,
struct
snd_soc_dai
*
dai
);
int
hdmi_config_audio_acr
(
struct
hdmi_ip_data
*
ip_data
,
u32
sample_freq
,
u32
*
n
,
u32
*
cts
);
void
hdmi_core_audio_infoframe_config
(
struct
hdmi_ip_data
*
ip_data
,
...
...
drivers/video/omap2/dss/venc.c
View file @
193984f4
...
...
@@ -417,9 +417,10 @@ static const struct venc_config *venc_timings_to_config(
BUG
();
}
static
void
venc_power_on
(
struct
omap_dss_device
*
dssdev
)
static
int
venc_power_on
(
struct
omap_dss_device
*
dssdev
)
{
u32
l
;
int
r
;
venc_reset
();
venc_write_config
(
venc_timings_to_config
(
&
dssdev
->
panel
.
timings
));
...
...
@@ -447,7 +448,22 @@ static void venc_power_on(struct omap_dss_device *dssdev)
if
(
dssdev
->
platform_enable
)
dssdev
->
platform_enable
(
dssdev
);
dssdev
->
manager
->
enable
(
dssdev
->
manager
);
r
=
dss_mgr_enable
(
dssdev
->
manager
);
if
(
r
)
goto
err
;
return
0
;
err:
venc_write_reg
(
VENC_OUTPUT_CONTROL
,
0
);
dss_set_dac_pwrdn_bgz
(
0
);
if
(
dssdev
->
platform_disable
)
dssdev
->
platform_disable
(
dssdev
);
regulator_disable
(
venc
.
vdda_dac_reg
);
return
r
;
}
static
void
venc_power_off
(
struct
omap_dss_device
*
dssdev
)
...
...
@@ -455,7 +471,7 @@ static void venc_power_off(struct omap_dss_device *dssdev)
venc_write_reg
(
VENC_OUTPUT_CONTROL
,
0
);
dss_set_dac_pwrdn_bgz
(
0
);
dss
dev
->
manager
->
disable
(
dssdev
->
manager
);
dss
_mgr_
disable
(
dssdev
->
manager
);
if
(
dssdev
->
platform_disable
)
dssdev
->
platform_disable
(
dssdev
);
...
...
@@ -504,7 +520,9 @@ static int venc_panel_enable(struct omap_dss_device *dssdev)
if
(
r
)
goto
err1
;
venc_power_on
(
dssdev
);
r
=
venc_power_on
(
dssdev
);
if
(
r
)
goto
err2
;
venc
.
wss_data
=
0
;
...
...
@@ -512,6 +530,8 @@ static int venc_panel_enable(struct omap_dss_device *dssdev)
mutex_unlock
(
&
venc
.
venc_lock
);
return
0
;
err2:
venc_runtime_put
();
err1:
omap_dss_stop_device
(
dssdev
);
err0:
...
...
drivers/video/omap2/omapfb/omapfb-ioctl.c
View file @
193984f4
...
...
@@ -111,28 +111,22 @@ static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
set_fb_fix
(
fbi
);
}
if
(
pi
->
enabled
)
{
struct
omap_overlay_info
info
;
if
(
!
pi
->
enabled
)
{
r
=
ovl
->
disable
(
ovl
);
if
(
r
)
goto
undo
;
}
if
(
pi
->
enabled
)
{
r
=
omapfb_setup_overlay
(
fbi
,
ovl
,
pi
->
pos_x
,
pi
->
pos_y
,
pi
->
out_width
,
pi
->
out_height
);
if
(
r
)
goto
undo
;
ovl
->
get_overlay_info
(
ovl
,
&
info
);
if
(
!
info
.
enabled
)
{
info
.
enabled
=
pi
->
enabled
;
r
=
ovl
->
set_overlay_info
(
ovl
,
&
info
);
if
(
r
)
goto
undo
;
}
}
else
{
struct
omap_overlay_info
info
;
ovl
->
get_overlay_info
(
ovl
,
&
info
);
info
.
enabled
=
pi
->
enabled
;
info
.
pos_x
=
pi
->
pos_x
;
info
.
pos_y
=
pi
->
pos_y
;
info
.
out_width
=
pi
->
out_width
;
...
...
@@ -146,6 +140,12 @@ static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
if
(
ovl
->
manager
)
ovl
->
manager
->
apply
(
ovl
->
manager
);
if
(
pi
->
enabled
)
{
r
=
ovl
->
enable
(
ovl
);
if
(
r
)
goto
undo
;
}
/* Release the locks in a specific order to keep lockdep happy */
if
(
old_rg
->
id
>
new_rg
->
id
)
{
omapfb_put_mem_region
(
old_rg
);
...
...
@@ -189,19 +189,19 @@ static int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
memset
(
pi
,
0
,
sizeof
(
*
pi
));
}
else
{
struct
omap_overlay
*
ovl
;
struct
omap_overlay_info
*
ovli
;
struct
omap_overlay_info
ovli
;
ovl
=
ofbi
->
overlays
[
0
];
ovl
i
=
&
ovl
->
info
;
ovl
->
get_overlay_info
(
ovl
,
&
ovli
)
;
pi
->
pos_x
=
ovli
->
pos_x
;
pi
->
pos_y
=
ovli
->
pos_y
;
pi
->
enabled
=
ovl
i
->
enabled
;
pi
->
pos_x
=
ovli
.
pos_x
;
pi
->
pos_y
=
ovli
.
pos_y
;
pi
->
enabled
=
ovl
->
is_enabled
(
ovl
)
;
pi
->
channel_out
=
0
;
/* xxx */
pi
->
mirror
=
0
;
pi
->
mem_idx
=
get_mem_idx
(
ofbi
);
pi
->
out_width
=
ovli
->
out_width
;
pi
->
out_height
=
ovli
->
out_height
;
pi
->
out_width
=
ovli
.
out_width
;
pi
->
out_height
=
ovli
.
out_height
;
}
return
0
;
...
...
@@ -238,7 +238,9 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
continue
;
for
(
j
=
0
;
j
<
ofbi2
->
num_overlays
;
j
++
)
{
if
(
ofbi2
->
overlays
[
j
]
->
info
.
enabled
)
{
struct
omap_overlay
*
ovl
;
ovl
=
ofbi2
->
overlays
[
j
];
if
(
ovl
->
is_enabled
(
ovl
))
{
r
=
-
EBUSY
;
goto
out
;
}
...
...
drivers/video/omap2/omapfb/omapfb-main.c
View file @
193984f4
...
...
@@ -970,16 +970,20 @@ int omapfb_apply_changes(struct fb_info *fbi, int init)
outh
=
var
->
yres
;
}
}
else
{
outw
=
ovl
->
info
.
out_width
;
outh
=
ovl
->
info
.
out_height
;
struct
omap_overlay_info
info
;
ovl
->
get_overlay_info
(
ovl
,
&
info
);
outw
=
info
.
out_width
;
outh
=
info
.
out_height
;
}
if
(
init
)
{
posx
=
0
;
posy
=
0
;
}
else
{
posx
=
ovl
->
info
.
pos_x
;
posy
=
ovl
->
info
.
pos_y
;
struct
omap_overlay_info
info
;
ovl
->
get_overlay_info
(
ovl
,
&
info
);
posx
=
info
.
pos_x
;
posy
=
info
.
pos_y
;
}
r
=
omapfb_setup_overlay
(
fbi
,
ovl
,
posx
,
posy
,
outw
,
outh
);
...
...
@@ -2067,6 +2071,8 @@ static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
if
(
ofbi
->
num_overlays
>
0
)
{
struct
omap_overlay
*
ovl
=
ofbi
->
overlays
[
0
];
ovl
->
manager
->
apply
(
ovl
->
manager
);
r
=
omapfb_overlay_enable
(
ovl
,
1
);
if
(
r
)
{
...
...
drivers/video/omap2/omapfb/omapfb-sysfs.c
View file @
193984f4
...
...
@@ -473,7 +473,9 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr,
continue
;
for
(
j
=
0
;
j
<
ofbi2
->
num_overlays
;
j
++
)
{
if
(
ofbi2
->
overlays
[
j
]
->
info
.
enabled
)
{
struct
omap_overlay
*
ovl
;
ovl
=
ofbi2
->
overlays
[
j
];
if
(
ovl
->
is_enabled
(
ovl
))
{
r
=
-
EBUSY
;
goto
out
;
}
...
...
drivers/video/omap2/omapfb/omapfb.h
View file @
193984f4
...
...
@@ -181,13 +181,10 @@ static inline void omapfb_unlock(struct omapfb2_device *fbdev)
static
inline
int
omapfb_overlay_enable
(
struct
omap_overlay
*
ovl
,
int
enable
)
{
struct
omap_overlay_info
info
;
ovl
->
get_overlay_info
(
ovl
,
&
info
);
if
(
info
.
enabled
==
enable
)
return
0
;
info
.
enabled
=
enable
;
return
ovl
->
set_overlay_info
(
ovl
,
&
info
);
if
(
enable
)
return
ovl
->
enable
(
ovl
);
else
return
ovl
->
disable
(
ovl
);
}
static
inline
struct
omapfb2_mem_region
*
...
...
include/video/omapdss.h
View file @
193984f4
...
...
@@ -200,6 +200,10 @@ enum omap_dss_clk_source {
OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI
,
/* OMAP4: PLL2_CLK2 */
};
enum
omap_hdmi_flags
{
OMAP_HDMI_SDA_SCL_EXTERNAL_PULLUP
=
1
<<
0
,
};
/* RFBI */
struct
rfbi_timings
{
...
...
@@ -294,8 +298,8 @@ int dsi_vc_set_max_rx_packet_size(struct omap_dss_device *dssdev, int channel,
u16
len
);
int
dsi_vc_send_null
(
struct
omap_dss_device
*
dssdev
,
int
channel
);
int
dsi_vc_send_bta_sync
(
struct
omap_dss_device
*
dssdev
,
int
channel
);
int
dsi_
video_mode_enable
(
struct
omap_dss_device
*
dssdev
,
int
channel
);
void
dsi_
video_mode_disable
(
struct
omap_dss_device
*
dssdev
,
int
channel
);
int
dsi_
enable_video_output
(
struct
omap_dss_device
*
dssdev
,
int
channel
);
void
dsi_
disable_video_output
(
struct
omap_dss_device
*
dssdev
,
int
channel
);
/* Board specific data */
struct
omap_dss_board_info
{
...
...
@@ -309,6 +313,8 @@ struct omap_dss_board_info {
/* Init with the board info */
extern
int
omap_display_init
(
struct
omap_dss_board_info
*
board_data
);
/* HDMI mux init*/
extern
int
omap_hdmi_init
(
enum
omap_hdmi_flags
flags
);
struct
omap_display_platform_data
{
struct
omap_dss_board_info
*
board_data
;
...
...
@@ -352,8 +358,6 @@ struct omap_dss_cpr_coefs {
};
struct
omap_overlay_info
{
bool
enabled
;
u32
paddr
;
u32
p_uv_addr
;
/* for NV12 format */
u16
screen_width
;
...
...
@@ -385,11 +389,21 @@ struct omap_overlay {
/* dynamic fields */
struct
omap_overlay_manager
*
manager
;
struct
omap_overlay_info
info
;
bool
manager_changed
;
/* if true, info has been changed, but not applied() yet */
bool
info_dirty
;
/*
* The following functions do not block:
*
* is_enabled
* set_overlay_info
* get_overlay_info
*
* The rest of the functions may block and cannot be called from
* interrupt context
*/
int
(
*
enable
)(
struct
omap_overlay
*
ovl
);
int
(
*
disable
)(
struct
omap_overlay
*
ovl
);
bool
(
*
is_enabled
)(
struct
omap_overlay
*
ovl
);
int
(
*
set_manager
)(
struct
omap_overlay
*
ovl
,
struct
omap_overlay_manager
*
mgr
);
...
...
@@ -418,23 +432,27 @@ struct omap_overlay_manager_info {
struct
omap_overlay_manager
{
struct
kobject
kobj
;
struct
list_head
list
;
/* static fields */
const
char
*
name
;
enum
omap_channel
id
;
enum
omap_overlay_manager_caps
caps
;
int
num_overlays
;
struct
omap_overlay
**
overlays
;
struct
list_head
overlays
;
enum
omap_display_type
supported_displays
;
/* dynamic fields */
struct
omap_dss_device
*
device
;
struct
omap_overlay_manager_info
info
;
bool
device_changed
;
/* if true, info has been changed but not applied() yet */
bool
info_dirty
;
/*
* The following functions do not block:
*
* set_manager_info
* get_manager_info
* apply
*
* The rest of the functions may block and cannot be called from
* interrupt context
*/
int
(
*
set_device
)(
struct
omap_overlay_manager
*
mgr
,
struct
omap_dss_device
*
dssdev
);
...
...
@@ -448,9 +466,6 @@ struct omap_overlay_manager {
int
(
*
apply
)(
struct
omap_overlay_manager
*
mgr
);
int
(
*
wait_for_go
)(
struct
omap_overlay_manager
*
mgr
);
int
(
*
wait_for_vsync
)(
struct
omap_overlay_manager
*
mgr
);
int
(
*
enable
)(
struct
omap_overlay_manager
*
mgr
);
int
(
*
disable
)(
struct
omap_overlay_manager
*
mgr
);
};
struct
omap_dss_device
{
...
...
@@ -662,12 +677,7 @@ void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel,
bool
enable
);
int
omapdss_dsi_enable_te
(
struct
omap_dss_device
*
dssdev
,
bool
enable
);
int
omap_dsi_prepare_update
(
struct
omap_dss_device
*
dssdev
,
u16
*
x
,
u16
*
y
,
u16
*
w
,
u16
*
h
,
bool
enlarge_update_area
);
int
omap_dsi_update
(
struct
omap_dss_device
*
dssdev
,
int
channel
,
u16
x
,
u16
y
,
u16
w
,
u16
h
,
int
omap_dsi_update
(
struct
omap_dss_device
*
dssdev
,
int
channel
,
void
(
*
callback
)(
int
,
void
*
),
void
*
data
);
int
omap_dsi_request_vc
(
struct
omap_dss_device
*
dssdev
,
int
*
channel
);
int
omap_dsi_set_vc_id
(
struct
omap_dss_device
*
dssdev
,
int
channel
,
int
vc_id
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment