aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
authorTomi Valkeinen <tomi.valkeinen@ti.com>2014-11-10 05:23:00 -0500
committerTomi Valkeinen <tomi.valkeinen@ti.com>2015-02-26 05:15:13 -0500
commitd49cd15550d9d4495f6187425318c245d58cb63f (patch)
treed6981bf56333c72e98075f2360cbcb0a4020a59f /drivers/video
parent4e1d3ca0836b6b44c358c5ace79aa15a091a4142 (diff)
OMAPDSS: DISPC: lock access to DISPC_CONTROL & DISPC_CONFIG
Dispc driver presumes that the callers handle locking for all normal functions. However, omapdrm doesn't handle this, and presumes that all overlay manager registers are private to that overlay manager, and thus presumes that configurations for overlay managers can be written via different threads freely. For many registers the above is true. The exceptions are DISPC_CONTROL and DISPC_CONFIG registers, which contain bits for both LCD and TV overlay managers. Fixing this properly in omapdrm means a big omapdrm rewrite. So, for now, add locking to dispc for the problematic registers. Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com> Reported-by: Somnath Mukherjee <somnath@ti.com>
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/fbdev/omap2/dss/dispc.c14
1 files changed, 14 insertions, 0 deletions
diff --git a/drivers/video/fbdev/omap2/dss/dispc.c b/drivers/video/fbdev/omap2/dss/dispc.c
index 1123111d3940..766c985cbfa7 100644
--- a/drivers/video/fbdev/omap2/dss/dispc.c
+++ b/drivers/video/fbdev/omap2/dss/dispc.c
@@ -123,6 +123,9 @@ static struct {
123 123
124 struct regmap *syscon_pol; 124 struct regmap *syscon_pol;
125 u32 syscon_pol_offset; 125 u32 syscon_pol_offset;
126
127 /* DISPC_CONTROL & DISPC_CONFIG lock*/
128 spinlock_t control_lock;
126} dispc; 129} dispc;
127 130
128enum omap_color_component { 131enum omap_color_component {
@@ -261,7 +264,16 @@ static u32 mgr_fld_read(enum omap_channel channel, enum mgr_reg_fields regfld)
261static void mgr_fld_write(enum omap_channel channel, 264static void mgr_fld_write(enum omap_channel channel,
262 enum mgr_reg_fields regfld, int val) { 265 enum mgr_reg_fields regfld, int val) {
263 const struct dispc_reg_field rfld = mgr_desc[channel].reg_desc[regfld]; 266 const struct dispc_reg_field rfld = mgr_desc[channel].reg_desc[regfld];
267 const bool need_lock = rfld.reg == DISPC_CONTROL || rfld.reg == DISPC_CONFIG;
268 unsigned long flags;
269
270 if (need_lock)
271 spin_lock_irqsave(&dispc.control_lock, flags);
272
264 REG_FLD_MOD(rfld.reg, val, rfld.high, rfld.low); 273 REG_FLD_MOD(rfld.reg, val, rfld.high, rfld.low);
274
275 if (need_lock)
276 spin_unlock_irqrestore(&dispc.control_lock, flags);
265} 277}
266 278
267#define SR(reg) \ 279#define SR(reg) \
@@ -3804,6 +3816,8 @@ static int __init omap_dispchw_probe(struct platform_device *pdev)
3804 3816
3805 dispc.pdev = pdev; 3817 dispc.pdev = pdev;
3806 3818
3819 spin_lock_init(&dispc.control_lock);
3820
3807 r = dispc_init_features(dispc.pdev); 3821 r = dispc_init_features(dispc.pdev);
3808 if (r) 3822 if (r)
3809 return r; 3823 return r;