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
2f1fed12
Commit
2f1fed12
authored
Dec 19, 2016
by
Tomi Valkeinen
Browse files
Options
Browse Files
Download
Plain Diff
Merge omapdrm work from Laurent
omapdrm IRQ rework, fixed vblank count and timestamp, cleanups.
parents
2cf026ae
2f95bc6d
Changes
15
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
431 additions
and
472 deletions
+431
-472
drivers/gpu/drm/drm_drv.c
drivers/gpu/drm/drm_drv.c
+2
-2
drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c
drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c
+1
-1
drivers/gpu/drm/omapdrm/dss/dispc.c
drivers/gpu/drm/omapdrm/dss/dispc.c
+13
-14
drivers/gpu/drm/omapdrm/dss/omapdss-boot-init.c
drivers/gpu/drm/omapdrm/dss/omapdss-boot-init.c
+1
-2
drivers/gpu/drm/omapdrm/dss/omapdss.h
drivers/gpu/drm/omapdrm/dss/omapdss.h
+0
-1
drivers/gpu/drm/omapdrm/omap_connector.c
drivers/gpu/drm/omapdrm/omap_connector.c
+2
-4
drivers/gpu/drm/omapdrm/omap_crtc.c
drivers/gpu/drm/omapdrm/omap_crtc.c
+77
-77
drivers/gpu/drm/omapdrm/omap_dmm_tiler.c
drivers/gpu/drm/omapdrm/omap_dmm_tiler.c
+2
-2
drivers/gpu/drm/omapdrm/omap_drv.c
drivers/gpu/drm/omapdrm/omap_drv.c
+109
-109
drivers/gpu/drm/omapdrm/omap_drv.h
drivers/gpu/drm/omapdrm/omap_drv.h
+5
-46
drivers/gpu/drm/omapdrm/omap_encoder.c
drivers/gpu/drm/omapdrm/omap_encoder.c
+1
-1
drivers/gpu/drm/omapdrm/omap_fb.c
drivers/gpu/drm/omapdrm/omap_fb.c
+84
-80
drivers/gpu/drm/omapdrm/omap_irq.c
drivers/gpu/drm/omapdrm/omap_irq.c
+133
-109
drivers/gpu/drm/omapdrm/omap_plane.c
drivers/gpu/drm/omapdrm/omap_plane.c
+0
-24
include/uapi/drm/Kbuild
include/uapi/drm/Kbuild
+1
-0
No files found.
drivers/gpu/drm/drm_drv.c
View file @
2f1fed12
...
...
@@ -595,6 +595,8 @@ static void drm_dev_release(struct kref *ref)
{
struct
drm_device
*
dev
=
container_of
(
ref
,
struct
drm_device
,
ref
);
drm_vblank_cleanup
(
dev
);
if
(
drm_core_check_feature
(
dev
,
DRIVER_GEM
))
drm_gem_destroy
(
dev
);
...
...
@@ -794,8 +796,6 @@ void drm_dev_unregister(struct drm_device *dev)
if
(
dev
->
agp
)
drm_pci_agp_destroy
(
dev
);
drm_vblank_cleanup
(
dev
);
list_for_each_entry_safe
(
r_list
,
list_temp
,
&
dev
->
maplist
,
head
)
drm_legacy_rmmap
(
dev
,
r_list
->
map
);
...
...
drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c
View file @
2f1fed12
...
...
@@ -1253,7 +1253,7 @@ static int dsicm_probe(struct platform_device *pdev)
dsicm_hw_reset
(
ddata
);
if
(
ddata
->
use_dsi_backlight
)
{
memset
(
&
props
,
0
,
sizeof
(
struct
backlight_propertie
s
));
memset
(
&
props
,
0
,
sizeof
(
prop
s
));
props
.
max_brightness
=
255
;
props
.
type
=
BACKLIGHT_RAW
;
...
...
drivers/gpu/drm/omapdrm/dss/dispc.c
View file @
2f1fed12
...
...
@@ -620,6 +620,19 @@ u32 dispc_wb_get_framedone_irq(void)
return
DISPC_IRQ_FRAMEDONEWB
;
}
void
dispc_mgr_enable
(
enum
omap_channel
channel
,
bool
enable
)
{
mgr_fld_write
(
channel
,
DISPC_MGR_FLD_ENABLE
,
enable
);
/* flush posted write */
mgr_fld_read
(
channel
,
DISPC_MGR_FLD_ENABLE
);
}
EXPORT_SYMBOL
(
dispc_mgr_enable
);
static
bool
dispc_mgr_is_enabled
(
enum
omap_channel
channel
)
{
return
!!
mgr_fld_read
(
channel
,
DISPC_MGR_FLD_ENABLE
);
}
bool
dispc_mgr_go_busy
(
enum
omap_channel
channel
)
{
return
mgr_fld_read
(
channel
,
DISPC_MGR_FLD_GO
)
==
1
;
...
...
@@ -2901,20 +2914,6 @@ enum omap_dss_output_id dispc_mgr_get_supported_outputs(enum omap_channel channe
}
EXPORT_SYMBOL
(
dispc_mgr_get_supported_outputs
);
void
dispc_mgr_enable
(
enum
omap_channel
channel
,
bool
enable
)
{
mgr_fld_write
(
channel
,
DISPC_MGR_FLD_ENABLE
,
enable
);
/* flush posted write */
mgr_fld_read
(
channel
,
DISPC_MGR_FLD_ENABLE
);
}
EXPORT_SYMBOL
(
dispc_mgr_enable
);
bool
dispc_mgr_is_enabled
(
enum
omap_channel
channel
)
{
return
!!
mgr_fld_read
(
channel
,
DISPC_MGR_FLD_ENABLE
);
}
EXPORT_SYMBOL
(
dispc_mgr_is_enabled
);
void
dispc_wb_enable
(
bool
enable
)
{
dispc_ovl_enable
(
OMAP_DSS_WB
,
enable
);
...
...
drivers/gpu/drm/omapdrm/dss/omapdss-boot-init.c
View file @
2f1fed12
...
...
@@ -119,8 +119,7 @@ static void __init omapdss_omapify_node(struct device_node *node)
static
void
__init
omapdss_add_to_list
(
struct
device_node
*
node
,
bool
root
)
{
struct
dss_conv_node
*
n
=
kmalloc
(
sizeof
(
struct
dss_conv_node
),
GFP_KERNEL
);
struct
dss_conv_node
*
n
=
kmalloc
(
sizeof
(
*
n
),
GFP_KERNEL
);
if
(
n
)
{
n
->
node
=
node
;
n
->
root
=
root
;
...
...
drivers/gpu/drm/omapdrm/dss/omapdss.h
View file @
2f1fed12
...
...
@@ -856,7 +856,6 @@ int dispc_runtime_get(void);
void
dispc_runtime_put
(
void
);
void
dispc_mgr_enable
(
enum
omap_channel
channel
,
bool
enable
);
bool
dispc_mgr_is_enabled
(
enum
omap_channel
channel
);
u32
dispc_mgr_get_vsync_irq
(
enum
omap_channel
channel
);
u32
dispc_mgr_get_framedone_irq
(
enum
omap_channel
channel
);
u32
dispc_mgr_get_sync_lost_irq
(
enum
omap_channel
channel
);
...
...
drivers/gpu/drm/omapdrm/omap_connector.c
View file @
2f1fed12
...
...
@@ -162,7 +162,7 @@ static int omap_connector_mode_valid(struct drm_connector *connector,
dssdrv
->
get_timings
(
dssdev
,
&
t
);
if
(
memcmp
(
&
vm
,
&
t
,
sizeof
(
struct
videomode
)))
if
(
memcmp
(
&
vm
,
&
t
,
sizeof
(
vm
)))
r
=
-
EINVAL
;
else
r
=
0
;
...
...
@@ -217,7 +217,7 @@ struct drm_connector *omap_connector_init(struct drm_device *dev,
omap_dss_get_device
(
dssdev
);
omap_connector
=
kzalloc
(
sizeof
(
struct
omap_connector
),
GFP_KERNEL
);
omap_connector
=
kzalloc
(
sizeof
(
*
omap_connector
),
GFP_KERNEL
);
if
(
!
omap_connector
)
goto
fail
;
...
...
@@ -240,8 +240,6 @@ struct drm_connector *omap_connector_init(struct drm_device *dev,
connector
->
interlace_allowed
=
1
;
connector
->
doublescan_allowed
=
0
;
drm_connector_register
(
connector
);
return
connector
;
fail:
...
...
drivers/gpu/drm/omapdrm/omap_crtc.c
View file @
2f1fed12
...
...
@@ -36,26 +36,18 @@ struct omap_crtc {
struct
videomode
vm
;
struct
omap_drm_irq
vblank_irq
;
struct
omap_drm_irq
error_irq
;
bool
ignore_digit_sync_lost
;
bool
enabled
;
bool
pending
;
wait_queue_head_t
pending_wait
;
struct
drm_pending_vblank_event
*
event
;
};
/* -----------------------------------------------------------------------------
* Helper Functions
*/
uint32_t
pipe2vbl
(
struct
drm_crtc
*
crtc
)
{
struct
omap_crtc
*
omap_crtc
=
to_omap_crtc
(
crtc
);
return
dispc_mgr_get_vsync_irq
(
omap_crtc
->
channel
);
}
struct
videomode
*
omap_crtc_timings
(
struct
drm_crtc
*
crtc
)
{
struct
omap_crtc
*
omap_crtc
=
to_omap_crtc
(
crtc
);
...
...
@@ -68,6 +60,19 @@ enum omap_channel omap_crtc_channel(struct drm_crtc *crtc)
return
omap_crtc
->
channel
;
}
static
bool
omap_crtc_is_pending
(
struct
drm_crtc
*
crtc
)
{
struct
omap_crtc
*
omap_crtc
=
to_omap_crtc
(
crtc
);
unsigned
long
flags
;
bool
pending
;
spin_lock_irqsave
(
&
crtc
->
dev
->
event_lock
,
flags
);
pending
=
omap_crtc
->
pending
;
spin_unlock_irqrestore
(
&
crtc
->
dev
->
event_lock
,
flags
);
return
pending
;
}
int
omap_crtc_wait_pending
(
struct
drm_crtc
*
crtc
)
{
struct
omap_crtc
*
omap_crtc
=
to_omap_crtc
(
crtc
);
...
...
@@ -77,7 +82,7 @@ int omap_crtc_wait_pending(struct drm_crtc *crtc)
* a single frame refresh even on slower displays.
*/
return
wait_event_timeout
(
omap_crtc
->
pending_wait
,
!
omap_crtc
->
pending
,
!
omap_crtc
_is_pending
(
crtc
)
,
msecs_to_jiffies
(
250
));
}
...
...
@@ -135,14 +140,15 @@ static void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable)
u32
framedone_irq
,
vsync_irq
;
int
ret
;
if
(
WARN_ON
(
omap_crtc
->
enabled
==
enable
))
return
;
if
(
omap_crtc_output
[
channel
]
->
output_type
==
OMAP_DISPLAY_TYPE_HDMI
)
{
dispc_mgr_enable
(
channel
,
enable
);
omap_crtc
->
enabled
=
enable
;
return
;
}
if
(
dispc_mgr_is_enabled
(
channel
)
==
enable
)
return
;
if
(
omap_crtc
->
channel
==
OMAP_DSS_CHANNEL_DIGIT
)
{
/*
* Digit output produces some sync lost interrupts during the
...
...
@@ -173,6 +179,7 @@ static void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable)
}
dispc_mgr_enable
(
channel
,
enable
);
omap_crtc
->
enabled
=
enable
;
ret
=
omap_irq_wait
(
dev
,
wait
,
msecs_to_jiffies
(
100
));
if
(
ret
)
{
...
...
@@ -259,26 +266,9 @@ static const struct dss_mgr_ops mgr_ops = {
* Setup, Flush and Page Flip
*/
static
void
omap_crtc_complete_page_flip
(
struct
drm_crtc
*
crtc
)
void
omap_crtc_error_irq
(
struct
drm_crtc
*
crtc
,
uint32_t
irqstatus
)
{
struct
drm_pending_vblank_event
*
event
;
struct
drm_device
*
dev
=
crtc
->
dev
;
unsigned
long
flags
;
event
=
crtc
->
state
->
event
;
if
(
!
event
)
return
;
spin_lock_irqsave
(
&
dev
->
event_lock
,
flags
);
drm_crtc_send_vblank_event
(
crtc
,
event
);
spin_unlock_irqrestore
(
&
dev
->
event_lock
,
flags
);
}
static
void
omap_crtc_error_irq
(
struct
omap_drm_irq
*
irq
,
uint32_t
irqstatus
)
{
struct
omap_crtc
*
omap_crtc
=
container_of
(
irq
,
struct
omap_crtc
,
error_irq
);
struct
omap_crtc
*
omap_crtc
=
to_omap_crtc
(
crtc
);
if
(
omap_crtc
->
ignore_digit_sync_lost
)
{
irqstatus
&=
~
DISPC_IRQ_SYNC_LOST_DIGIT
;
...
...
@@ -289,29 +279,38 @@ static void omap_crtc_error_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
DRM_ERROR_RATELIMITED
(
"%s: errors: %08x
\n
"
,
omap_crtc
->
name
,
irqstatus
);
}
static
void
omap_crtc_vblank_irq
(
struct
omap_drm_irq
*
irq
,
uint32_t
irqstatus
)
void
omap_crtc_vblank_irq
(
struct
drm_crtc
*
crtc
)
{
struct
omap_crtc
*
omap_crtc
=
container_of
(
irq
,
struct
omap_crtc
,
vblank_irq
);
struct
drm_device
*
dev
=
omap_crtc
->
base
.
dev
;
struct
omap_crtc
*
omap_crtc
=
to_omap_crtc
(
crtc
);
bool
pending
;
if
(
dispc_mgr_go_busy
(
omap_crtc
->
channel
))
spin_lock
(
&
crtc
->
dev
->
event_lock
);
/*
* If the dispc is busy we're racing the flush operation. Try again on
* the next vblank interrupt.
*/
if
(
dispc_mgr_go_busy
(
omap_crtc
->
channel
))
{
spin_unlock
(
&
crtc
->
dev
->
event_lock
);
return
;
}
DBG
(
"%s: apply done"
,
omap_crtc
->
name
);
__omap_irq_unregister
(
dev
,
&
omap_crtc
->
vblank_irq
);
/* Send the vblank event if one has been requested. */
if
(
omap_crtc
->
event
)
{
drm_crtc_send_vblank_event
(
crtc
,
omap_crtc
->
event
);
omap_crtc
->
event
=
NULL
;
}
rmb
();
WARN_ON
(
!
omap_crtc
->
pending
);
pending
=
omap_crtc
->
pending
;
omap_crtc
->
pending
=
false
;
wmb
(
);
spin_unlock
(
&
crtc
->
dev
->
event_lock
);
/* wake up userspace */
omap_crtc_complete_page_flip
(
&
omap_crtc
->
base
);
if
(
pending
)
drm_crtc_vblank_put
(
crtc
);
/*
wake up omap_atomic_complete
*/
/*
Wake up omap_atomic_complete.
*/
wake_up
(
&
omap_crtc
->
pending_wait
);
DBG
(
"%s: apply done"
,
omap_crtc
->
name
);
}
/* -----------------------------------------------------------------------------
...
...
@@ -324,9 +323,6 @@ static void omap_crtc_destroy(struct drm_crtc *crtc)
DBG
(
"%s"
,
omap_crtc
->
name
);
WARN_ON
(
omap_crtc
->
vblank_irq
.
registered
);
omap_irq_unregister
(
crtc
->
dev
,
&
omap_crtc
->
error_irq
);
drm_crtc_cleanup
(
crtc
);
kfree
(
omap_crtc
);
...
...
@@ -335,17 +331,18 @@ static void omap_crtc_destroy(struct drm_crtc *crtc)
static
void
omap_crtc_enable
(
struct
drm_crtc
*
crtc
)
{
struct
omap_crtc
*
omap_crtc
=
to_omap_crtc
(
crtc
);
int
ret
;
DBG
(
"%s"
,
omap_crtc
->
name
);
rmb
();
spin_lock_irq
(
&
crtc
->
dev
->
event_lock
);
drm_crtc_vblank_on
(
crtc
);
ret
=
drm_crtc_vblank_get
(
crtc
);
WARN_ON
(
ret
!=
0
);
WARN_ON
(
omap_crtc
->
pending
);
omap_crtc
->
pending
=
true
;
wmb
();
omap_irq_register
(
crtc
->
dev
,
&
omap_crtc
->
vblank_irq
);
drm_crtc_vblank_on
(
crtc
);
spin_unlock_irq
(
&
crtc
->
dev
->
event_lock
);
}
static
void
omap_crtc_disable
(
struct
drm_crtc
*
crtc
)
...
...
@@ -390,16 +387,15 @@ static int omap_crtc_atomic_check(struct drm_crtc *crtc,
}
static
void
omap_crtc_atomic_begin
(
struct
drm_crtc
*
crtc
,
struct
drm_crtc_state
*
old_crtc_state
)
struct
drm_crtc_state
*
old_crtc_state
)
{
}
static
void
omap_crtc_atomic_flush
(
struct
drm_crtc
*
crtc
,
struct
drm_crtc_state
*
old_crtc_state
)
struct
drm_crtc_state
*
old_crtc_state
)
{
struct
omap_crtc
*
omap_crtc
=
to_omap_crtc
(
crtc
);
WARN_ON
(
omap_crtc
->
vblank_irq
.
registered
);
int
ret
;
if
(
crtc
->
state
->
color_mgmt_changed
)
{
struct
drm_color_lut
*
lut
=
NULL
;
...
...
@@ -414,18 +410,30 @@ static void omap_crtc_atomic_flush(struct drm_crtc *crtc,
dispc_mgr_set_gamma
(
omap_crtc
->
channel
,
lut
,
length
);
}
if
(
dispc_mgr_is_enabled
(
omap_crtc
->
channel
))
{
/*
* Only flush the CRTC if it is currently enabled. CRTCs that require a
* mode set are disabled prior plane updates and enabled afterwards.
* They are thus not active (regardless of what their CRTC core state
* reports) and the DRM core could thus call this function even though
* the CRTC is currently disabled. Do nothing in that case.
*/
if
(
!
omap_crtc
->
enabled
)
return
;
DBG
(
"%s: GO"
,
omap_crtc
->
name
);
DBG
(
"%s: GO"
,
omap_crtc
->
name
);
ret
=
drm_crtc_vblank_get
(
crtc
);
WARN_ON
(
ret
!=
0
);
rmb
();
WARN_ON
(
omap_crtc
->
pending
);
omap_crtc
->
pending
=
true
;
wmb
();
spin_lock_irq
(
&
crtc
->
dev
->
event_lock
);
dispc_mgr_go
(
omap_crtc
->
channel
);
dispc_mgr_go
(
omap_crtc
->
channel
);
omap_irq_register
(
crtc
->
dev
,
&
omap_crtc
->
vblank_irq
);
}
WARN_ON
(
omap_crtc
->
pending
);
omap_crtc
->
pending
=
true
;
if
(
crtc
->
state
->
event
)
omap_crtc
->
event
=
crtc
->
state
->
event
;
spin_unlock_irq
(
&
crtc
->
dev
->
event_lock
);
}
static
bool
omap_crtc_is_plane_prop
(
struct
drm_crtc
*
crtc
,
...
...
@@ -546,14 +554,6 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev,
omap_crtc
->
channel
=
channel
;
omap_crtc
->
name
=
channel_names
[
channel
];
omap_crtc
->
vblank_irq
.
irqmask
=
pipe2vbl
(
crtc
);
omap_crtc
->
vblank_irq
.
irq
=
omap_crtc_vblank_irq
;
omap_crtc
->
error_irq
.
irqmask
=
dispc_mgr_get_sync_lost_irq
(
channel
);
omap_crtc
->
error_irq
.
irq
=
omap_crtc_error_irq
;
omap_irq_register
(
dev
,
&
omap_crtc
->
error_irq
);
ret
=
drm_crtc_init_with_planes
(
dev
,
crtc
,
plane
,
NULL
,
&
omap_crtc_funcs
,
NULL
);
if
(
ret
<
0
)
{
...
...
drivers/gpu/drm/omapdrm/omap_dmm_tiler.c
View file @
2f1fed12
...
...
@@ -224,7 +224,7 @@ static void dmm_txn_append(struct dmm_txn *txn, struct pat_area *area,
int
rows
=
(
1
+
area
->
y1
-
area
->
y0
);
int
i
=
columns
*
rows
;
pat
=
alloc_dma
(
txn
,
sizeof
(
struct
pat
),
&
pat_pa
);
pat
=
alloc_dma
(
txn
,
sizeof
(
*
pat
),
&
pat_pa
);
if
(
txn
->
last_pat
)
txn
->
last_pat
->
next_pa
=
(
uint32_t
)
pat_pa
;
...
...
@@ -735,7 +735,7 @@ static int omap_dmm_probe(struct platform_device *dev)
/* alloc engines */
omap_dmm
->
engines
=
kcalloc
(
omap_dmm
->
num_engines
,
sizeof
(
struct
refill_engine
),
GFP_KERNEL
);
sizeof
(
*
omap_dmm
->
engines
),
GFP_KERNEL
);
if
(
!
omap_dmm
->
engines
)
{
ret
=
-
ENOMEM
;
goto
fail
;
...
...
drivers/gpu/drm/omapdrm/omap_drv.c
View file @
2f1fed12
...
...
@@ -96,7 +96,8 @@ static void omap_atomic_complete(struct omap_atomic_state_commit *commit)
dispc_runtime_get
();
drm_atomic_helper_commit_modeset_disables
(
dev
,
old_state
);
drm_atomic_helper_commit_planes
(
dev
,
old_state
,
0
);
drm_atomic_helper_commit_planes
(
dev
,
old_state
,
DRM_PLANE_COMMIT_ACTIVE_ONLY
);
drm_atomic_helper_commit_modeset_enables
(
dev
,
old_state
);
omap_atomic_wait_for_completion
(
dev
,
old_state
);
...
...
@@ -315,8 +316,6 @@ static int omap_modeset_init(struct drm_device *dev)
drm_mode_config_init
(
dev
);
omap_drm_irq_install
(
dev
);
ret
=
omap_modeset_init_properties
(
dev
);
if
(
ret
<
0
)
return
ret
;
...
...
@@ -489,12 +488,9 @@ static int omap_modeset_init(struct drm_device *dev)
drm_mode_config_reset
(
dev
);
return
0
;
}
omap_drm_irq_install
(
dev
);
static
void
omap_modeset_free
(
struct
drm_device
*
dev
)
{
drm_mode_config_cleanup
(
dev
);
return
0
;
}
/*
...
...
@@ -632,95 +628,6 @@ static const struct drm_ioctl_desc ioctls[DRM_COMMAND_END - DRM_COMMAND_BASE] =
* drm driver funcs
*/
/**
* load - setup chip and create an initial config
* @dev: DRM device
* @flags: startup flags
*
* The driver load routine has to do several things:
* - initialize the memory manager
* - allocate initial config memory
* - setup the DRM framebuffer with the allocated memory
*/
static
int
dev_load
(
struct
drm_device
*
dev
,
unsigned
long
flags
)
{
struct
omap_drm_platform_data
*
pdata
=
dev
->
dev
->
platform_data
;
struct
omap_drm_private
*
priv
;
unsigned
int
i
;
int
ret
;
DBG
(
"load: dev=%p"
,
dev
);
priv
=
kzalloc
(
sizeof
(
*
priv
),
GFP_KERNEL
);
if
(
!
priv
)
return
-
ENOMEM
;
priv
->
omaprev
=
pdata
->
omaprev
;
dev
->
dev_private
=
priv
;
priv
->
wq
=
alloc_ordered_workqueue
(
"omapdrm"
,
0
);
init_waitqueue_head
(
&
priv
->
commit
.
wait
);
spin_lock_init
(
&
priv
->
commit
.
lock
);
spin_lock_init
(
&
priv
->
list_lock
);
INIT_LIST_HEAD
(
&
priv
->
obj_list
);
omap_gem_init
(
dev
);
ret
=
omap_modeset_init
(
dev
);
if
(
ret
)
{
dev_err
(
dev
->
dev
,
"omap_modeset_init failed: ret=%d
\n
"
,
ret
);
dev
->
dev_private
=
NULL
;
kfree
(
priv
);
return
ret
;
}
/* Initialize vblank handling, start with all CRTCs disabled. */
ret
=
drm_vblank_init
(
dev
,
priv
->
num_crtcs
);
if
(
ret
)
dev_warn
(
dev
->
dev
,
"could not init vblank
\n
"
);
for
(
i
=
0
;
i
<
priv
->
num_crtcs
;
i
++
)
drm_crtc_vblank_off
(
priv
->
crtcs
[
i
]);
priv
->
fbdev
=
omap_fbdev_init
(
dev
);
/* store off drm_device for use in pm ops */
dev_set_drvdata
(
dev
->
dev
,
dev
);
drm_kms_helper_poll_init
(
dev
);
return
0
;
}
static
int
dev_unload
(
struct
drm_device
*
dev
)
{
struct
omap_drm_private
*
priv
=
dev
->
dev_private
;
DBG
(
"unload: dev=%p"
,
dev
);
drm_kms_helper_poll_fini
(
dev
);
if
(
priv
->
fbdev
)
omap_fbdev_free
(
dev
);
omap_modeset_free
(
dev
);
omap_gem_deinit
(
dev
);
destroy_workqueue
(
priv
->
wq
);
drm_vblank_cleanup
(
dev
);
omap_drm_irq_uninstall
(
dev
);
kfree
(
dev
->
dev_private
);
dev
->
dev_private
=
NULL
;
dev_set_drvdata
(
dev
->
dev
,
NULL
);
return
0
;
}
static
int
dev_open
(
struct
drm_device
*
dev
,
struct
drm_file
*
file
)
{
file
->
driver_priv
=
NULL
;
...
...
@@ -805,8 +712,6 @@ static const struct file_operations omapdriver_fops = {
static
struct
drm_driver
omap_drm_driver
=
{
.
driver_features
=
DRIVER_MODESET
|
DRIVER_GEM
|
DRIVER_PRIME
|
DRIVER_ATOMIC
,
.
load
=
dev_load
,
.
unload
=
dev_unload
,
.
open
=
dev_open
,
.
lastclose
=
dev_lastclose
,
.
get_vblank_counter
=
drm_vblank_no_hw_counter
,
...
...
@@ -836,30 +741,125 @@ static struct drm_driver omap_drm_driver = {
.
patchlevel
=
DRIVER_PATCHLEVEL
,
};
static
int
pdev_probe
(
struct
platform_device
*
device
)
static
int
pdev_probe
(
struct
platform_device
*
pdev
)
{
int
r
;
struct
omap_drm_platform_data
*
pdata
=
pdev
->
dev
.
platform_data
;
struct
omap_drm_private
*
priv
;
struct
drm_device
*
ddev
;
unsigned
int
i
;
int
ret
;
DBG
(
"%s"
,
pdev
->
name
);
if
(
omapdss_is_initialized
()
==
false
)
return
-
EPROBE_DEFER
;
omap_crtc_pre_init
();
r
=
omap_connect_dssdevs
();
if
(
r
)
{
omap_crtc_pre_uninit
();
return
r
;
ret
=
omap_connect_dssdevs
();
if
(
ret
)
goto
err_crtc_uninit
;
/* Allocate and initialize the driver private structure. */
priv
=
kzalloc
(
sizeof
(
*
priv
),
GFP_KERNEL
);
if
(
!
priv
)
{
ret
=
-
ENOMEM
;
goto
err_disconnect_dssdevs
;
}
priv
->
omaprev
=
pdata
->
omaprev
;
priv
->
wq
=
alloc_ordered_workqueue
(
"omapdrm"
,
0
);
init_waitqueue_head
(
&
priv
->
commit
.
wait
);
spin_lock_init
(
&
priv
->
commit
.
lock
);
spin_lock_init
(
&
priv
->
list_lock
);
INIT_LIST_HEAD
(
&
priv
->
obj_list
);
/* Allocate and initialize the DRM device. */
ddev
=
drm_dev_alloc
(
&
omap_drm_driver
,
&
pdev
->
dev
);
if
(
IS_ERR
(
ddev
))
{
ret
=
PTR_ERR
(
ddev
);
goto
err_free_priv
;
}
ddev
->
dev_private
=
priv
;
platform_set_drvdata
(
pdev
,
ddev
);
omap_gem_init
(
ddev
);
ret
=
omap_modeset_init
(
ddev
);
if
(
ret
)
{
dev_err
(
&
pdev
->
dev
,
"omap_modeset_init failed: ret=%d
\n
"
,
ret
);
goto
err_free_drm_dev
;
}
/* Initialize vblank handling, start with all CRTCs disabled. */
ret
=
drm_vblank_init
(
ddev
,
priv
->
num_crtcs
);
if
(
ret
)
{
dev_err
(
&
pdev
->
dev
,
"could not init vblank
\n
"
);
goto
err_cleanup_modeset
;
}
DBG
(
"%s"
,
device
->
name
);
return
drm_platform_init
(
&
omap_drm_driver
,
device
);
for
(
i
=
0
;
i
<
priv
->
num_crtcs
;
i
++
)
drm_crtc_vblank_off
(
priv
->
crtcs
[
i
]);
priv
->
fbdev
=
omap_fbdev_init
(
ddev
);
drm_kms_helper_poll_init
(
ddev
);
/*
* Register the DRM device with the core and the connectors with
* sysfs.
*/
ret
=
drm_dev_register
(
ddev
,
0
);
if
(
ret
)
goto
err_cleanup_helpers
;
return
0
;
err_cleanup_helpers:
drm_kms_helper_poll_fini
(
ddev
);
if
(
priv
->
fbdev
)
omap_fbdev_free
(
ddev
);
err_cleanup_modeset:
drm_mode_config_cleanup
(
ddev
);
omap_drm_irq_uninstall
(
ddev
);
err_free_drm_dev:
omap_gem_deinit
(
ddev
);
drm_dev_unref
(
ddev
);
err_free_priv:
destroy_workqueue
(
priv
->
wq
);
kfree
(
priv
);
err_disconnect_dssdevs:
omap_disconnect_dssdevs
();
err_crtc_uninit:
omap_crtc_pre_uninit
();
return
ret
;
}
static
int
pdev_remove
(
struct
platform_device
*
device
)
static
int
pdev_remove
(
struct
platform_device
*
pdev
)
{
struct
drm_device
*
ddev
=
platform_get_drvdata
(
pdev
);
struct
omap_drm_private
*
priv
=
ddev
->
dev_private
;
DBG
(
""
);
drm_put_dev
(
platform_get_drvdata
(
device
));
drm_dev_unregister
(
ddev
);
drm_kms_helper_poll_fini
(
ddev
);
if
(
priv
->
fbdev
)
omap_fbdev_free
(
ddev
);
drm_mode_config_cleanup
(
ddev
);
omap_drm_irq_uninstall
(
ddev
);
omap_gem_deinit
(
ddev
);
drm_dev_unref
(
ddev
);
destroy_workqueue
(
priv
->
wq
);
kfree
(
priv
);
omap_disconnect_dssdevs
();
omap_crtc_pre_uninit
();
...
...
drivers/gpu/drm/omapdrm/omap_drv.h
View file @
2f1fed12
...
...
@@ -48,19 +48,6 @@ struct omap_drm_window {
uint32_t
src_w
,
src_h
;
};
/* For transiently registering for different DSS irqs that various parts
* of the KMS code need during setup/configuration. We these are not
* necessarily the same as what drm_vblank_get/put() are requesting, and
* the hysteresis in drm_vblank_put() is not necessarily desirable for
* internal housekeeping related irq usage.
*/
struct
omap_drm_irq
{
struct
list_head
node
;
uint32_t
irqmask
;
bool
registered
;
void
(
*
irq
)(
struct
omap_drm_irq
*
irq
,
uint32_t
irqstatus
);
};
/* For KMS code that needs to wait for a certain # of IRQs:
*/
struct
omap_irq_wait
;
...
...
@@ -101,9 +88,9 @@ struct omap_drm_private {
struct
drm_property
*
zorder_prop
;
/* irq handling: */
s
truct
list_head
irq_list
;
/* list of omap_drm_irq
*/
uint32_t
vblank_mask
;
/* irq bits set for userspace vblank
*/
struct
omap_drm_irq
error_handler
;
s
pinlock_t
wait_lock
;
/* protects the wait_list
*/
struct
list_head
wait_list
;
/* list of omap_irq_wait
*/
uint32_t
irq_mask
;
/* enabled irqs in addition to wait_list */
/* atomic commit */
struct
{
...
...
@@ -128,10 +115,6 @@ int omap_gem_resume(struct device *dev);
int
omap_irq_enable_vblank
(
struct
drm_device
*
dev
,
unsigned
int
pipe
);
void
omap_irq_disable_vblank
(
struct
drm_device
*
dev
,
unsigned
int
pipe
);
void
__omap_irq_register
(
struct
drm_device
*
dev
,
struct
omap_drm_irq
*
irq
);
void
__omap_irq_unregister
(
struct
drm_device
*
dev
,
struct
omap_drm_irq
*
irq
);
void
omap_irq_register
(
struct
drm_device
*
dev
,
struct
omap_drm_irq
*
irq
);
void
omap_irq_unregister
(
struct
drm_device
*
dev
,
struct
omap_drm_irq
*
irq
);
void
omap_drm_irq_uninstall
(
struct
drm_device
*
dev
);
int
omap_drm_irq_install
(
struct
drm_device
*
dev
);
...
...
@@ -155,6 +138,8 @@ void omap_crtc_pre_uninit(void);
struct
drm_crtc
*
omap_crtc_init
(
struct
drm_device
*
dev
,
struct
drm_plane
*
plane
,
enum
omap_channel
channel
,
int
id
);
int
omap_crtc_wait_pending
(
struct
drm_crtc
*
crtc
);
void
omap_crtc_error_irq
(
struct
drm_crtc
*
crtc
,
uint32_t
irqstatus
);
void
omap_crtc_vblank_irq
(
struct
drm_crtc
*
crtc
);
struct
drm_plane
*
omap_plane_init
(
struct
drm_device
*
dev
,
int
id
,
enum
drm_plane_type
type
,
...
...
@@ -233,32 +218,6 @@ struct drm_gem_object *omap_gem_prime_import(struct drm_device *dev,
struct
dma_buf
*
buffer
);
/* map crtc to vblank mask */
uint32_t
pipe2vbl
(
struct
drm_crtc
*
crtc
);
struct
omap_dss_device
*
omap_encoder_get_dssdev
(
struct
drm_encoder
*
encoder
);
/* should these be made into common util helpers?
*/
static
inline
int
objects_lookup
(
struct
drm_file
*
filp
,
uint32_t
pixel_format
,
struct
drm_gem_object
**
bos
,
const
uint32_t
*
handles
)
{
int
i
,
n
=
drm_format_num_planes
(
pixel_format
);
for
(
i
=
0
;
i
<
n
;
i
++
)
{
bos
[
i
]
=
drm_gem_object_lookup
(
filp
,
handles
[
i
]);
if
(
!
bos
[
i
])
goto
fail
;
}
return
0
;
fail:
while
(
--
i
>
0
)
drm_gem_object_unreference_unlocked
(
bos
[
i
]);
return
-
ENOENT
;
}
#endif
/* __OMAP_DRV_H__ */
drivers/gpu/drm/omapdrm/omap_encoder.c
View file @
2f1fed12
...
...
@@ -117,7 +117,7 @@ static int omap_encoder_update(struct drm_encoder *encoder,
dssdrv
->
get_timings
(
dssdev
,
&
t
);
if
(
memcmp
(
vm
,
&
t
,
sizeof
(
struct
videomode
)))
if
(
memcmp
(
vm
,
&
t
,
sizeof
(
*
vm
)))
ret
=
-
EINVAL
;
else
ret
=
0
;
...
...
drivers/gpu/drm/omapdrm/omap_fb.c
View file @
2f1fed12
...
...
@@ -29,37 +29,30 @@
* framebuffer funcs
*/
/*
per-format info:
*/
st
ruct
forma
t
{
/*
DSS to DRM formats mapping
*/
st
atic
const
struc
t
{
enum
omap_color_mode
dss_format
;
uint32_t
pixel_format
;
struct
{
int
stride_bpp
;
/* this times width is stride */
int
sub_y
;
/* sub-sample in y dimension */
}
planes
[
4
];
bool
yuv
;
};
static
const
struct
format
formats
[]
=
{
}
formats
[]
=
{
/* 16bpp [A]RGB: */
{
OMAP_DSS_COLOR_RGB16
,
DRM_FORMAT_RGB565
,
{{
2
,
1
}},
false
},
/* RGB16-565 */
{
OMAP_DSS_COLOR_RGB12U
,
DRM_FORMAT_RGBX4444
,
{{
2
,
1
}},
false
},
/* RGB12x-4444 */
{
OMAP_DSS_COLOR_RGBX16
,
DRM_FORMAT_XRGB4444
,
{{
2
,
1
}},
false
},
/* xRGB12-4444 */
{
OMAP_DSS_COLOR_RGBA16
,
DRM_FORMAT_RGBA4444
,
{{
2
,
1
}},
false
},
/* RGBA12-4444 */
{
OMAP_DSS_COLOR_ARGB16
,
DRM_FORMAT_ARGB4444
,
{{
2
,
1
}},
false
},
/* ARGB16-4444 */
{
OMAP_DSS_COLOR_XRGB16_1555
,
DRM_FORMAT_XRGB1555
,
{{
2
,
1
}},
false
},
/* xRGB15-1555 */
{
OMAP_DSS_COLOR_ARGB16_1555
,
DRM_FORMAT_ARGB1555
,
{{
2
,
1
}},
false
},
/* ARGB16-1555 */
{
OMAP_DSS_COLOR_RGB16
,
DRM_FORMAT_RGB565
},
/* RGB16-565 */
{
OMAP_DSS_COLOR_RGB12U
,
DRM_FORMAT_RGBX4444
},
/* RGB12x-4444 */
{
OMAP_DSS_COLOR_RGBX16
,
DRM_FORMAT_XRGB4444
},
/* xRGB12-4444 */
{
OMAP_DSS_COLOR_RGBA16
,
DRM_FORMAT_RGBA4444
},
/* RGBA12-4444 */
{
OMAP_DSS_COLOR_ARGB16
,
DRM_FORMAT_ARGB4444
},
/* ARGB16-4444 */
{
OMAP_DSS_COLOR_XRGB16_1555
,
DRM_FORMAT_XRGB1555
},
/* xRGB15-1555 */
{
OMAP_DSS_COLOR_ARGB16_1555
,
DRM_FORMAT_ARGB1555
},
/* ARGB16-1555 */
/* 24bpp RGB: */
{
OMAP_DSS_COLOR_RGB24P
,
DRM_FORMAT_RGB888
,
{{
3
,
1
}},
false
},
/* RGB24-888 */
{
OMAP_DSS_COLOR_RGB24P
,
DRM_FORMAT_RGB888
},
/* RGB24-888 */
/* 32bpp [A]RGB: */
{
OMAP_DSS_COLOR_RGBX32
,
DRM_FORMAT_RGBX8888
,
{{
4
,
1
}},
false
},
/* RGBx24-8888 */
{
OMAP_DSS_COLOR_RGB24U
,
DRM_FORMAT_XRGB8888
,
{{
4
,
1
}},
false
},
/* xRGB24-8888 */
{
OMAP_DSS_COLOR_RGBA32
,
DRM_FORMAT_RGBA8888
,
{{
4
,
1
}},
false
},
/* RGBA32-8888 */
{
OMAP_DSS_COLOR_ARGB32
,
DRM_FORMAT_ARGB8888
,
{{
4
,
1
}},
false
},
/* ARGB32-8888 */
{
OMAP_DSS_COLOR_RGBX32
,
DRM_FORMAT_RGBX8888
},
/* RGBx24-8888 */
{
OMAP_DSS_COLOR_RGB24U
,
DRM_FORMAT_XRGB8888
},
/* xRGB24-8888 */
{
OMAP_DSS_COLOR_RGBA32
,
DRM_FORMAT_RGBA8888
},
/* RGBA32-8888 */
{
OMAP_DSS_COLOR_ARGB32
,
DRM_FORMAT_ARGB8888
},
/* ARGB32-8888 */
/* YUV: */
{
OMAP_DSS_COLOR_NV12
,
DRM_FORMAT_NV12
,
{{
1
,
1
},
{
1
,
2
}},
true
},
{
OMAP_DSS_COLOR_YUV2
,
DRM_FORMAT_YUYV
,
{{
2
,
1
}},
true
},
{
OMAP_DSS_COLOR_UYVY
,
DRM_FORMAT_UYVY
,
{{
2
,
1
}},
true
},
{
OMAP_DSS_COLOR_NV12
,
DRM_FORMAT_NV12
},
{
OMAP_DSS_COLOR_YUV2
,
DRM_FORMAT_YUYV
},
{
OMAP_DSS_COLOR_UYVY
,
DRM_FORMAT_UYVY
},
};
/* convert from overlay's pixel formats bitmask to an array of fourcc's */
...
...
@@ -89,8 +82,9 @@ struct plane {
struct
omap_framebuffer
{
struct
drm_framebuffer
base
;
int
pin_count
;
const
struct
format
*
format
;
struct
plane
planes
[
4
];
const
struct
drm_format_info
*
format
;
enum
omap_color_mode
dss_format
;
struct
plane
planes
[
2
];
/* lock for pinning (pin_count and planes.paddr) */
struct
mutex
lock
;
};
...
...
@@ -128,13 +122,13 @@ static const struct drm_framebuffer_funcs omap_framebuffer_funcs = {
};
static
uint32_t
get_linear_addr
(
struct
plane
*
plane
,
const
struct
format
*
format
,
int
n
,
int
x
,
int
y
)
const
struct
drm_format_info
*
format
,
int
n
,
int
x
,
int
y
)
{
uint32_t
offset
;
offset
=
plane
->
offset
+
(
x
*
format
->
planes
[
n
].
stride_bpp
)
+
(
y
*
plane
->
pitch
/
format
->
planes
[
n
].
sub_y
);
offset
=
plane
->
offset
+
(
x
*
format
->
cpp
[
n
]
/
(
n
==
0
?
1
:
format
->
hsub
))
+
(
y
*
plane
->
pitch
/
(
n
==
0
?
1
:
format
->
vsub
)
);
return
plane
->
paddr
+
offset
;
}
...
...
@@ -153,11 +147,11 @@ void omap_framebuffer_update_scanout(struct drm_framebuffer *fb,
struct
omap_drm_window
*
win
,
struct
omap_overlay_info
*
info
)
{
struct
omap_framebuffer
*
omap_fb
=
to_omap_framebuffer
(
fb
);
const
struct
format
*
format
=
omap_fb
->
format
;
const
struct
drm_format_info
*
format
=
omap_fb
->
format
;
struct
plane
*
plane
=
&
omap_fb
->
planes
[
0
];
uint32_t
x
,
y
,
orient
=
0
;
info
->
color_mode
=
format
->
dss_format
;
info
->
color_mode
=
omap_fb
->
dss_format
;
info
->
pos_x
=
win
->
crtc_x
;
info
->
pos_y
=
win
->
crtc_y
;
...
...
@@ -231,9 +225,9 @@ void omap_framebuffer_update_scanout(struct drm_framebuffer *fb,
}
/* convert to pixels: */
info
->
screen_width
/=
format
->
planes
[
0
].
stride_bpp
;
info
->
screen_width
/=
format
->
cpp
[
0
]
;
if
(
format
->
dss_format
==
OMAP_DSS_COLOR_NV12
)
{
if
(
omap_fb
->
dss_format
==
OMAP_DSS_COLOR_NV12
)
{
plane
=
&
omap_fb
->
planes
[
1
];
if
(
info
->
rotation_type
==
OMAP_DSS_ROT_TILER
)
{
...
...
@@ -360,47 +354,58 @@ void omap_framebuffer_describe(struct drm_framebuffer *fb, struct seq_file *m)
struct
drm_framebuffer
*
omap_framebuffer_create
(
struct
drm_device
*
dev
,
struct
drm_file
*
file
,
const
struct
drm_mode_fb_cmd2
*
mode_cmd
)
{
unsigned
int
num_planes
=
drm_format_num_planes
(
mode_cmd
->
pixel_format
);
struct
drm_gem_object
*
bos
[
4
];
struct
drm_framebuffer
*
fb
;
int
ret
;
int
i
;
ret
=
objects_lookup
(
file
,
mode_cmd
->
pixel_format
,
bos
,
mode_cmd
->
handles
);
if
(
ret
)
return
ERR_PTR
(
ret
);
for
(
i
=
0
;
i
<
num_planes
;
i
++
)
{
bos
[
i
]
=
drm_gem_object_lookup
(
file
,
mode_cmd
->
handles
[
i
]);
if
(
!
bos
[
i
])
{
fb
=
ERR_PTR
(
-
ENOENT
);
goto
error
;
}
}
fb
=
omap_framebuffer_init
(
dev
,
mode_cmd
,
bos
);
if
(
IS_ERR
(
fb
))
{
int
i
,
n
=
drm_format_num_planes
(
mode_cmd
->
pixel_format
);
for
(
i
=
0
;
i
<
n
;
i
++
)
drm_gem_object_unreference_unlocked
(
bos
[
i
]);
return
fb
;
}
if
(
IS_ERR
(
fb
))
goto
error
;
return
fb
;
error:
while
(
--
i
>
0
)
drm_gem_object_unreference_unlocked
(
bos
[
i
]);
return
fb
;
}
struct
drm_framebuffer
*
omap_framebuffer_init
(
struct
drm_device
*
dev
,
const
struct
drm_mode_fb_cmd2
*
mode_cmd
,
struct
drm_gem_object
**
bos
)
{
const
struct
drm_format_info
*
format
=
NULL
;
struct
omap_framebuffer
*
omap_fb
=
NULL
;
struct
drm_framebuffer
*
fb
=
NULL
;
const
struct
format
*
format
=
NULL
;
int
ret
,
i
,
n
=
drm_format_num_planes
(
mode_cmd
->
pixel_format
);
enum
omap_color_mode
dss_format
=
0
;
unsigned
int
pitch
=
mode_cmd
->
pitches
[
0
];
int
ret
,
i
;
DBG
(
"create framebuffer: dev=%p, mode_cmd=%p (%dx%d@%4.4s)"
,
dev
,
mode_cmd
,
mode_cmd
->
width
,
mode_cmd
->
height
,
(
char
*
)
&
mode_cmd
->
pixel_format
);
format
=
drm_format_info
(
mode_cmd
->
pixel_format
);
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
formats
);
i
++
)
{
if
(
formats
[
i
].
pixel_format
==
mode_cmd
->
pixel_format
)
{
format
=
&
formats
[
i
]
;
dss_format
=
formats
[
i
].
dss_format
;
break
;
}
}
if
(
!
format
)
{
dev_
err
(
dev
->
dev
,
"unsupported pixel format: %4.4s
\n
"
,
(
char
*
)
&
mode_cmd
->
pixel_format
);
if
(
!
format
||
!
dss_format
)
{
dev_
dbg
(
dev
->
dev
,
"unsupported pixel format: %4.4s
\n
"
,
(
char
*
)
&
mode_cmd
->
pixel_format
);
ret
=
-
EINVAL
;
goto
fail
;
}
...
...
@@ -413,40 +418,39 @@ struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
fb
=
&
omap_fb
->
base
;
omap_fb
->
format
=
format
;
omap_fb
->
dss_format
=
dss_format
;
mutex_init
(
&
omap_fb
->
lock
);
for
(
i
=
0
;
i
<
n
;
i
++
)
{
struct
plane
*
plane
=
&
omap_fb
->
planes
[
i
];
int
size
,
pitch
=
mode_cmd
->
pitches
[
i
];
if
(
pitch
<
(
mode_cmd
->
width
*
format
->
planes
[
i
].
stride_bpp
))
{
dev_err
(
dev
->
dev
,
"provided buffer pitch is too small! %d < %d
\n
"
,
pitch
,
mode_cmd
->
width
*
format
->
planes
[
i
].
stride_bpp
);
ret
=
-
EINVAL
;
goto
fail
;
}
/*
* The code below assumes that no format use more than two planes, and
* that the two planes of multiplane formats need the same number of
* bytes per pixel.
*/
if
(
format
->
num_planes
==
2
&&
pitch
!=
mode_cmd
->
pitches
[
1
])
{
dev_dbg
(
dev
->
dev
,
"pitches differ between planes 0 and 1
\n
"
);
ret
=
-
EINVAL
;
goto
fail
;
}
if
(
pitch
%
format
->
planes
[
i
].
stride_bpp
!=
0
)
{
dev_err
(
dev
->
dev
,
"buffer pitch (%d bytes) is not a multiple of pixel size (%d
bytes)
\n
"
,
pitch
,
format
->
planes
[
i
].
stride_bpp
);
ret
=
-
EINVAL
;
goto
fail
;
}
if
(
pitch
%
format
->
cpp
[
0
]
)
{
dev_dbg
(
dev
->
dev
,
"buffer pitch (%u bytes) is not a multiple of pixel size (%u
bytes)
\n
"
,
pitch
,
format
->
cpp
[
0
]
);
ret
=
-
EINVAL
;
goto
fail
;
}
size
=
pitch
*
mode_cmd
->
height
/
format
->
planes
[
i
].
sub_y
;
for
(
i
=
0
;
i
<
format
->
num_planes
;
i
++
)
{
struct
plane
*
plane
=
&
omap_fb
->
planes
[
i
];
unsigned
int
vsub
=
i
==
0
?
1
:
format
->
vsub
;
unsigned
int
size
;
if
(
size
>
(
omap_gem_mmap_size
(
bos
[
i
])
-
mode_cmd
->
offsets
[
i
]))
{
dev_err
(
dev
->
dev
,
"provided buffer object is too small! %d < %d
\n
"
,
bos
[
i
]
->
size
-
mode_cmd
->
offsets
[
i
],
size
);
ret
=
-
EINVAL
;
goto
fail
;
}
size
=
pitch
*
mode_cmd
->
height
/
vsub
;
if
(
i
>
0
&&
pitch
!=
mode_cmd
->
pitches
[
i
-
1
])
{
dev_
err
(
dev
->
dev
,
"p
itches are not the same between framebuffer planes %d !=
%d
\n
"
,
pitch
,
mode_cmd
->
pitches
[
i
-
1
]
);
if
(
size
>
omap_gem_mmap_size
(
bos
[
i
])
-
mode_cmd
->
offsets
[
i
])
{
dev_
dbg
(
dev
->
dev
,
"p
rovided buffer object is too small! %d <
%d
\n
"
,
bos
[
i
]
->
size
-
mode_cmd
->
offsets
[
i
],
size
);
ret
=
-
EINVAL
;
goto
fail
;
}
...
...
drivers/gpu/drm/omapdrm/omap_irq.c
View file @
2f1fed12
...
...
@@ -19,25 +19,24 @@
#include "omap_drv.h"
static
DEFINE_SPINLOCK
(
list_lock
);
static
void
omap_irq_error_handler
(
struct
omap_drm_irq
*
irq
,
uint32_t
irqstatus
)
{
DRM_ERROR
(
"errors: %08x
\n
"
,
irqstatus
);
}
struct
omap_irq_wait
{
struct
list_head
node
;
wait_queue_head_t
wq
;
uint32_t
irqmask
;
int
count
;
};
/* call with
lis
t_lock and dispc runtime held */
/* call with
wai
t_lock and dispc runtime held */
static
void
omap_irq_update
(
struct
drm_device
*
dev
)
{
struct
omap_drm_private
*
priv
=
dev
->
dev_private
;
struct
omap_
drm_irq
*
irq
;
uint32_t
irqmask
=
priv
->
vblank
_mask
;
struct
omap_
irq_wait
*
wait
;
uint32_t
irqmask
=
priv
->
irq
_mask
;
assert_spin_locked
(
&
lis
t_lock
);
assert_spin_locked
(
&
priv
->
wai
t_lock
);
list_for_each_entry
(
irq
,
&
priv
->
irq
_list
,
node
)
irqmask
|=
irq
->
irqmask
;
list_for_each_entry
(
wait
,
&
priv
->
wait
_list
,
node
)
irqmask
|=
wait
->
irqmask
;
DBG
(
"irqmask=%08x"
,
irqmask
);
...
...
@@ -45,90 +44,48 @@ static void omap_irq_update(struct drm_device *dev)
dispc_read_irqenable
();
/* flush posted write */
}
void
__omap_irq_register
(
struct
drm_device
*
dev
,
struct
omap_drm_irq
*
irq
)
{
struct
omap_drm_private
*
priv
=
dev
->
dev_private
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
list_lock
,
flags
);
if
(
!
WARN_ON
(
irq
->
registered
))
{
irq
->
registered
=
true
;
list_add
(
&
irq
->
node
,
&
priv
->
irq_list
);
omap_irq_update
(
dev
);
}
spin_unlock_irqrestore
(
&
list_lock
,
flags
);
}
void
omap_irq_register
(
struct
drm_device
*
dev
,
struct
omap_drm_irq
*
irq
)
{
dispc_runtime_get
();
__omap_irq_register
(
dev
,
irq
);
dispc_runtime_put
();
}
void
__omap_irq_unregister
(
struct
drm_device
*
dev
,
struct
omap_drm_irq
*
irq
)
static
void
omap_irq_wait_handler
(
struct
omap_irq_wait
*
wait
)
{
unsigned
long
flags
;
spin_lock_irqsave
(
&
list_lock
,
flags
);
if
(
!
WARN_ON
(
!
irq
->
registered
))
{
irq
->
registered
=
false
;
list_del
(
&
irq
->
node
);
omap_irq_update
(
dev
);
}
spin_unlock_irqrestore
(
&
list_lock
,
flags
);
}
void
omap_irq_unregister
(
struct
drm_device
*
dev
,
struct
omap_drm_irq
*
irq
)
{
dispc_runtime_get
();
__omap_irq_unregister
(
dev
,
irq
);
dispc_runtime_put
();
}
struct
omap_irq_wait
{
struct
omap_drm_irq
irq
;
int
count
;
};
static
DECLARE_WAIT_QUEUE_HEAD
(
wait_event
);
static
void
wait_irq
(
struct
omap_drm_irq
*
irq
,
uint32_t
irqstatus
)
{
struct
omap_irq_wait
*
wait
=
container_of
(
irq
,
struct
omap_irq_wait
,
irq
);
wait
->
count
--
;
wake_up
_all
(
&
wait_event
);
wake_up
(
&
wait
->
wq
);
}
struct
omap_irq_wait
*
omap_irq_wait_init
(
struct
drm_device
*
dev
,
uint32_t
irqmask
,
int
count
)
{
struct
omap_drm_private
*
priv
=
dev
->
dev_private
;
struct
omap_irq_wait
*
wait
=
kzalloc
(
sizeof
(
*
wait
),
GFP_KERNEL
);
wait
->
irq
.
irq
=
wait_irq
;
wait
->
irq
.
irqmask
=
irqmask
;
unsigned
long
flags
;
init_waitqueue_head
(
&
wait
->
wq
);
wait
->
irqmask
=
irqmask
;
wait
->
count
=
count
;
omap_irq_register
(
dev
,
&
wait
->
irq
);
spin_lock_irqsave
(
&
priv
->
wait_lock
,
flags
);
list_add
(
&
wait
->
node
,
&
priv
->
wait_list
);
omap_irq_update
(
dev
);
spin_unlock_irqrestore
(
&
priv
->
wait_lock
,
flags
);
return
wait
;
}
int
omap_irq_wait
(
struct
drm_device
*
dev
,
struct
omap_irq_wait
*
wait
,
unsigned
long
timeout
)
{
int
ret
=
wait_event_timeout
(
wait_event
,
(
wait
->
count
<=
0
),
timeout
);
omap_irq_unregister
(
dev
,
&
wait
->
irq
);
struct
omap_drm_private
*
priv
=
dev
->
dev_private
;
unsigned
long
flags
;
int
ret
;
ret
=
wait_event_timeout
(
wait
->
wq
,
(
wait
->
count
<=
0
),
timeout
);
spin_lock_irqsave
(
&
priv
->
wait_lock
,
flags
);
list_del
(
&
wait
->
node
);
omap_irq_update
(
dev
);
spin_unlock_irqrestore
(
&
priv
->
wait_lock
,
flags
);
kfree
(
wait
);
if
(
ret
==
0
)
return
-
1
;
return
0
;
return
ret
==
0
?
-
1
:
0
;
}
/**
...
...
@@ -152,10 +109,10 @@ int omap_irq_enable_vblank(struct drm_device *dev, unsigned int pipe)
DBG
(
"dev=%p, crtc=%u"
,
dev
,
pipe
);
spin_lock_irqsave
(
&
lis
t_lock
,
flags
);
priv
->
vblank_mask
|=
pipe2vbl
(
crtc
);
spin_lock_irqsave
(
&
priv
->
wai
t_lock
,
flags
);
priv
->
irq_mask
|=
dispc_mgr_get_vsync_irq
(
omap_crtc_channel
(
crtc
)
);
omap_irq_update
(
dev
);
spin_unlock_irqrestore
(
&
lis
t_lock
,
flags
);
spin_unlock_irqrestore
(
&
priv
->
wai
t_lock
,
flags
);
return
0
;
}
...
...
@@ -177,17 +134,66 @@ void omap_irq_disable_vblank(struct drm_device *dev, unsigned int pipe)
DBG
(
"dev=%p, crtc=%u"
,
dev
,
pipe
);
spin_lock_irqsave
(
&
lis
t_lock
,
flags
);
priv
->
vblank_mask
&=
~
pipe2vbl
(
crtc
);
spin_lock_irqsave
(
&
priv
->
wai
t_lock
,
flags
);
priv
->
irq_mask
&=
~
dispc_mgr_get_vsync_irq
(
omap_crtc_channel
(
crtc
)
);
omap_irq_update
(
dev
);
spin_unlock_irqrestore
(
&
list_lock
,
flags
);
spin_unlock_irqrestore
(
&
priv
->
wait_lock
,
flags
);
}
static
void
omap_irq_fifo_underflow
(
struct
omap_drm_private
*
priv
,
u32
irqstatus
)
{
static
DEFINE_RATELIMIT_STATE
(
_rs
,
DEFAULT_RATELIMIT_INTERVAL
,
DEFAULT_RATELIMIT_BURST
);
static
const
struct
{
const
char
*
name
;
u32
mask
;
}
sources
[]
=
{
{
"gfx"
,
DISPC_IRQ_GFX_FIFO_UNDERFLOW
},
{
"vid1"
,
DISPC_IRQ_VID1_FIFO_UNDERFLOW
},
{
"vid2"
,
DISPC_IRQ_VID2_FIFO_UNDERFLOW
},
{
"vid3"
,
DISPC_IRQ_VID3_FIFO_UNDERFLOW
},
};
const
u32
mask
=
DISPC_IRQ_GFX_FIFO_UNDERFLOW
|
DISPC_IRQ_VID1_FIFO_UNDERFLOW
|
DISPC_IRQ_VID2_FIFO_UNDERFLOW
|
DISPC_IRQ_VID3_FIFO_UNDERFLOW
;
unsigned
int
i
;
spin_lock
(
&
priv
->
wait_lock
);
irqstatus
&=
priv
->
irq_mask
&
mask
;
spin_unlock
(
&
priv
->
wait_lock
);
if
(
!
irqstatus
)
return
;
if
(
!
__ratelimit
(
&
_rs
))
return
;
DRM_ERROR
(
"FIFO underflow on "
);
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
sources
);
++
i
)
{
if
(
sources
[
i
].
mask
&
irqstatus
)
pr_cont
(
"%s "
,
sources
[
i
].
name
);
}
pr_cont
(
"(0x%08x)
\n
"
,
irqstatus
);
}
static
void
omap_irq_ocp_error_handler
(
u32
irqstatus
)
{
if
(
!
(
irqstatus
&
DISPC_IRQ_OCP_ERR
))
return
;
DRM_ERROR
(
"OCP error
\n
"
);
}
static
irqreturn_t
omap_irq_handler
(
int
irq
,
void
*
arg
)
{
struct
drm_device
*
dev
=
(
struct
drm_device
*
)
arg
;
struct
omap_drm_private
*
priv
=
dev
->
dev_private
;
struct
omap_
drm_irq
*
handler
,
*
n
;
struct
omap_
irq_wait
*
wait
,
*
n
;
unsigned
long
flags
;
unsigned
int
id
;
u32
irqstatus
;
...
...
@@ -200,24 +206,37 @@ static irqreturn_t omap_irq_handler(int irq, void *arg)
for
(
id
=
0
;
id
<
priv
->
num_crtcs
;
id
++
)
{
struct
drm_crtc
*
crtc
=
priv
->
crtcs
[
id
];
enum
omap_channel
channel
=
omap_crtc_channel
(
crtc
);
if
(
irqstatus
&
pipe2vbl
(
crtc
))
if
(
irqstatus
&
dispc_mgr_get_vsync_irq
(
channel
))
{
drm_handle_vblank
(
dev
,
id
);
omap_crtc_vblank_irq
(
crtc
);
}
if
(
irqstatus
&
dispc_mgr_get_sync_lost_irq
(
channel
))
omap_crtc_error_irq
(
crtc
,
irqstatus
);
}
spin_lock_irqsave
(
&
list_lock
,
flag
s
);
list_for_each_entry_safe
(
handler
,
n
,
&
priv
->
irq_list
,
node
)
{
if
(
handler
->
irqmask
&
irqstatus
)
{
spin_unlock_irqrestore
(
&
lis
t_lock
,
flags
);
handler
->
irq
(
handler
,
handler
->
irqmask
&
irqstatus
);
spin_lock_irqsave
(
&
list_lock
,
flags
);
}
omap_irq_ocp_error_handler
(
irqstatu
s
);
omap_irq_fifo_underflow
(
priv
,
irqstatus
);
spin_lock_irqsave
(
&
priv
->
wai
t_lock
,
flags
);
list_for_each_entry_safe
(
wait
,
n
,
&
priv
->
wait_list
,
node
)
{
if
(
wait
->
irqmask
&
irqstatus
)
omap_irq_wait_handler
(
wait
);
}
spin_unlock_irqrestore
(
&
lis
t_lock
,
flags
);
spin_unlock_irqrestore
(
&
priv
->
wai
t_lock
,
flags
);
return
IRQ_HANDLED
;
}
static
const
u32
omap_underflow_irqs
[]
=
{
[
OMAP_DSS_GFX
]
=
DISPC_IRQ_GFX_FIFO_UNDERFLOW
,
[
OMAP_DSS_VIDEO1
]
=
DISPC_IRQ_VID1_FIFO_UNDERFLOW
,
[
OMAP_DSS_VIDEO2
]
=
DISPC_IRQ_VID2_FIFO_UNDERFLOW
,
[
OMAP_DSS_VIDEO3
]
=
DISPC_IRQ_VID3_FIFO_UNDERFLOW
,
};
/*
* We need a special version, instead of just using drm_irq_install(),
* because we need to register the irq via omapdss. Once omapdss and
...
...
@@ -228,10 +247,25 @@ static irqreturn_t omap_irq_handler(int irq, void *arg)
int
omap_drm_irq_install
(
struct
drm_device
*
dev
)
{
struct
omap_drm_private
*
priv
=
dev
->
dev_private
;
struct
omap_drm_irq
*
error_handler
=
&
priv
->
error_handler
;
unsigned
int
num_mgrs
=
dss_feat_get_num_mgrs
();
unsigned
int
max_planes
;
unsigned
int
i
;
int
ret
;
INIT_LIST_HEAD
(
&
priv
->
irq_list
);
spin_lock_init
(
&
priv
->
wait_lock
);
INIT_LIST_HEAD
(
&
priv
->
wait_list
);
priv
->
irq_mask
=
DISPC_IRQ_OCP_ERR
;
max_planes
=
min
(
ARRAY_SIZE
(
priv
->
planes
),
ARRAY_SIZE
(
omap_underflow_irqs
));
for
(
i
=
0
;
i
<
max_planes
;
++
i
)
{
if
(
priv
->
planes
[
i
])
priv
->
irq_mask
|=
omap_underflow_irqs
[
i
];
}
for
(
i
=
0
;
i
<
num_mgrs
;
++
i
)
priv
->
irq_mask
|=
dispc_mgr_get_sync_lost_irq
(
i
);
dispc_runtime_get
();
dispc_clear_irqstatus
(
0xffffffff
);
...
...
@@ -241,16 +275,6 @@ int omap_drm_irq_install(struct drm_device *dev)
if
(
ret
<
0
)
return
ret
;
error_handler
->
irq
=
omap_irq_error_handler
;
error_handler
->
irqmask
=
DISPC_IRQ_OCP_ERR
;
/* for now ignore DISPC_IRQ_SYNC_LOST_DIGIT.. really I think
* we just need to ignore it while enabling tv-out
*/
error_handler
->
irqmask
&=
~
DISPC_IRQ_SYNC_LOST_DIGIT
;
omap_irq_register
(
dev
,
error_handler
);
dev
->
irq_enabled
=
true
;
return
0
;
...
...
drivers/gpu/drm/omapdrm/omap_plane.c
View file @
2f1fed12
...
...
@@ -43,8 +43,6 @@ struct omap_plane {
uint32_t
nformats
;
uint32_t
formats
[
32
];
struct
omap_drm_irq
error_irq
;
};
struct
omap_plane_state
{
...
...
@@ -204,8 +202,6 @@ static void omap_plane_destroy(struct drm_plane *plane)
DBG
(
"%s"
,
omap_plane
->
name
);
omap_irq_unregister
(
plane
->
dev
,
&
omap_plane
->
error_irq
);
drm_plane_cleanup
(
plane
);
kfree
(
omap_plane
);
...
...
@@ -332,14 +328,6 @@ static const struct drm_plane_funcs omap_plane_funcs = {
.
atomic_get_property
=
omap_plane_atomic_get_property
,
};
static
void
omap_plane_error_irq
(
struct
omap_drm_irq
*
irq
,
uint32_t
irqstatus
)
{
struct
omap_plane
*
omap_plane
=
container_of
(
irq
,
struct
omap_plane
,
error_irq
);
DRM_ERROR_RATELIMITED
(
"%s: errors: %08x
\n
"
,
omap_plane
->
name
,
irqstatus
);
}
static
const
char
*
plane_names
[]
=
{
[
OMAP_DSS_GFX
]
=
"gfx"
,
[
OMAP_DSS_VIDEO1
]
=
"vid1"
,
...
...
@@ -347,13 +335,6 @@ static const char *plane_names[] = {
[
OMAP_DSS_VIDEO3
]
=
"vid3"
,
};
static
const
uint32_t
error_irqs
[]
=
{
[
OMAP_DSS_GFX
]
=
DISPC_IRQ_GFX_FIFO_UNDERFLOW
,
[
OMAP_DSS_VIDEO1
]
=
DISPC_IRQ_VID1_FIFO_UNDERFLOW
,
[
OMAP_DSS_VIDEO2
]
=
DISPC_IRQ_VID2_FIFO_UNDERFLOW
,
[
OMAP_DSS_VIDEO3
]
=
DISPC_IRQ_VID3_FIFO_UNDERFLOW
,
};
/* initialize plane */
struct
drm_plane
*
omap_plane_init
(
struct
drm_device
*
dev
,
int
id
,
enum
drm_plane_type
type
,
...
...
@@ -377,10 +358,6 @@ struct drm_plane *omap_plane_init(struct drm_device *dev,
plane
=
&
omap_plane
->
base
;
omap_plane
->
error_irq
.
irqmask
=
error_irqs
[
id
];
omap_plane
->
error_irq
.
irq
=
omap_plane_error_irq
;
omap_irq_register
(
dev
,
&
omap_plane
->
error_irq
);
ret
=
drm_universal_plane_init
(
dev
,
plane
,
possible_crtcs
,
&
omap_plane_funcs
,
omap_plane
->
formats
,
omap_plane
->
nformats
,
type
,
NULL
);
...
...
@@ -394,7 +371,6 @@ struct drm_plane *omap_plane_init(struct drm_device *dev,
return
plane
;
error:
omap_irq_unregister
(
plane
->
dev
,
&
omap_plane
->
error_irq
);
kfree
(
omap_plane
);
return
NULL
;
}
include/uapi/drm/Kbuild
View file @
2f1fed12
...
...
@@ -9,6 +9,7 @@ header-y += i810_drm.h
header-y += i915_drm.h
header-y += mga_drm.h
header-y += nouveau_drm.h
header-y += omap_drm.h
header-y += qxl_drm.h
header-y += r128_drm.h
header-y += radeon_drm.h
...
...
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