diff options
author | Lucas Stach <dev@lynxeye.de> | 2012-12-19 16:38:54 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2012-12-29 23:01:33 -0500 |
commit | 83c0bcb694be31dcd6c04bdd935b96a95a0af548 (patch) | |
tree | f6b6448f3080240513a40208098e99625010a31d /drivers | |
parent | 4026bfb39a3e63e32b3c4a648bb1ac1fd8c6b162 (diff) |
drm: tegra: protect DC register access with mutex
Window properties are programmed through a shared aperture and have to
happen atomically. Also we do the read-update-write dance on some of the
shared regs.
To make sure that different functions don't stumble over each other
protect the register access with a mutex.
Signed-off-by: Lucas Stach <dev@lynxeye.de>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/tegra/dc.c | 13 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/drm.h | 1 |
2 files changed, 14 insertions, 0 deletions
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index 54683e430c77..b256574409e7 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c | |||
@@ -171,6 +171,8 @@ static int tegra_crtc_mode_set(struct drm_crtc *crtc, | |||
171 | return err; | 171 | return err; |
172 | } | 172 | } |
173 | 173 | ||
174 | mutex_lock(&dc->regs_mutex); | ||
175 | |||
174 | /* program display mode */ | 176 | /* program display mode */ |
175 | tegra_dc_set_timings(dc, mode); | 177 | tegra_dc_set_timings(dc, mode); |
176 | 178 | ||
@@ -269,6 +271,8 @@ static int tegra_crtc_mode_set(struct drm_crtc *crtc, | |||
269 | tegra_dc_writel(dc, 0xff00, DC_WIN_BLEND_NOKEY); | 271 | tegra_dc_writel(dc, 0xff00, DC_WIN_BLEND_NOKEY); |
270 | tegra_dc_writel(dc, 0xff00, DC_WIN_BLEND_1WIN); | 272 | tegra_dc_writel(dc, 0xff00, DC_WIN_BLEND_1WIN); |
271 | 273 | ||
274 | mutex_unlock(&dc->regs_mutex); | ||
275 | |||
272 | return 0; | 276 | return 0; |
273 | } | 277 | } |
274 | 278 | ||
@@ -287,6 +291,8 @@ static void tegra_crtc_prepare(struct drm_crtc *crtc) | |||
287 | else | 291 | else |
288 | syncpt = SYNCPT_VBLANK0; | 292 | syncpt = SYNCPT_VBLANK0; |
289 | 293 | ||
294 | mutex_lock(&dc->regs_mutex); | ||
295 | |||
290 | /* initialize display controller */ | 296 | /* initialize display controller */ |
291 | tegra_dc_writel(dc, 0x00000100, DC_CMD_GENERAL_INCR_SYNCPT_CNTRL); | 297 | tegra_dc_writel(dc, 0x00000100, DC_CMD_GENERAL_INCR_SYNCPT_CNTRL); |
292 | tegra_dc_writel(dc, 0x100 | syncpt, DC_CMD_CONT_SYNCPT_VSYNC); | 298 | tegra_dc_writel(dc, 0x100 | syncpt, DC_CMD_CONT_SYNCPT_VSYNC); |
@@ -320,6 +326,8 @@ static void tegra_crtc_prepare(struct drm_crtc *crtc) | |||
320 | 326 | ||
321 | value = VBLANK_INT | WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT; | 327 | value = VBLANK_INT | WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT; |
322 | tegra_dc_writel(dc, value, DC_CMD_INT_ENABLE); | 328 | tegra_dc_writel(dc, value, DC_CMD_INT_ENABLE); |
329 | |||
330 | mutex_unlock(&dc->regs_mutex); | ||
323 | } | 331 | } |
324 | 332 | ||
325 | static void tegra_crtc_commit(struct drm_crtc *crtc) | 333 | static void tegra_crtc_commit(struct drm_crtc *crtc) |
@@ -330,6 +338,8 @@ static void tegra_crtc_commit(struct drm_crtc *crtc) | |||
330 | 338 | ||
331 | update_mask = GENERAL_ACT_REQ | WIN_A_ACT_REQ; | 339 | update_mask = GENERAL_ACT_REQ | WIN_A_ACT_REQ; |
332 | 340 | ||
341 | mutex_lock(&dc->regs_mutex); | ||
342 | |||
333 | tegra_dc_writel(dc, update_mask << 8, DC_CMD_STATE_CONTROL); | 343 | tegra_dc_writel(dc, update_mask << 8, DC_CMD_STATE_CONTROL); |
334 | 344 | ||
335 | value = tegra_dc_readl(dc, DC_CMD_INT_ENABLE); | 345 | value = tegra_dc_readl(dc, DC_CMD_INT_ENABLE); |
@@ -341,6 +351,8 @@ static void tegra_crtc_commit(struct drm_crtc *crtc) | |||
341 | tegra_dc_writel(dc, value, DC_CMD_INT_MASK); | 351 | tegra_dc_writel(dc, value, DC_CMD_INT_MASK); |
342 | 352 | ||
343 | tegra_dc_writel(dc, update_mask, DC_CMD_STATE_CONTROL); | 353 | tegra_dc_writel(dc, update_mask, DC_CMD_STATE_CONTROL); |
354 | |||
355 | mutex_unlock(&dc->regs_mutex); | ||
344 | } | 356 | } |
345 | 357 | ||
346 | static void tegra_crtc_load_lut(struct drm_crtc *crtc) | 358 | static void tegra_crtc_load_lut(struct drm_crtc *crtc) |
@@ -747,6 +759,7 @@ static int tegra_dc_probe(struct platform_device *pdev) | |||
747 | return -ENOMEM; | 759 | return -ENOMEM; |
748 | 760 | ||
749 | INIT_LIST_HEAD(&dc->list); | 761 | INIT_LIST_HEAD(&dc->list); |
762 | mutex_init(&dc->regs_mutex); | ||
750 | dc->dev = &pdev->dev; | 763 | dc->dev = &pdev->dev; |
751 | 764 | ||
752 | dc->clk = devm_clk_get(&pdev->dev, NULL); | 765 | dc->clk = devm_clk_get(&pdev->dev, NULL); |
diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h index 3a843a77ddc7..eae1f564b716 100644 --- a/drivers/gpu/drm/tegra/drm.h +++ b/drivers/gpu/drm/tegra/drm.h | |||
@@ -84,6 +84,7 @@ struct tegra_dc { | |||
84 | 84 | ||
85 | struct clk *clk; | 85 | struct clk *clk; |
86 | 86 | ||
87 | struct mutex regs_mutex; | ||
87 | void __iomem *regs; | 88 | void __iomem *regs; |
88 | int irq; | 89 | int irq; |
89 | 90 | ||