aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/tegra/dc.c
diff options
context:
space:
mode:
authorThierry Reding <treding@nvidia.com>2014-11-24 11:41:23 -0500
committerThierry Reding <treding@nvidia.com>2015-01-27 04:14:55 -0500
commit1503ca47d76e184eaeabe7cfa31de97b5ec36a04 (patch)
tree8a97feb074e208da908f0b606b413174bc529f38 /drivers/gpu/drm/tegra/dc.c
parent74f48791ad69789bc70eb4d99233d83e016f5f14 (diff)
drm/tegra: Atomic conversion, phase 3, step 3
Provide a custom ->atomic_commit() implementation which supports async commits. The generic atomic page-flip helper can use this to implement page-flipping. Signed-off-by: Thierry Reding <treding@nvidia.com>
Diffstat (limited to 'drivers/gpu/drm/tegra/dc.c')
-rw-r--r--drivers/gpu/drm/tegra/dc.c129
1 files changed, 11 insertions, 118 deletions
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index aa66abb57b1c..2f9af13905da 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -820,99 +820,6 @@ static int tegra_dc_add_planes(struct drm_device *drm, struct tegra_dc *dc)
820 return 0; 820 return 0;
821} 821}
822 822
823static int tegra_dc_set_base(struct tegra_dc *dc, int x, int y,
824 struct drm_framebuffer *fb)
825{
826 struct tegra_bo *bo = tegra_fb_get_plane(fb, 0);
827 unsigned int h_offset = 0, v_offset = 0;
828 struct tegra_bo_tiling tiling;
829 unsigned long value, flags;
830 unsigned int format, swap;
831 int err;
832
833 err = tegra_fb_get_tiling(fb, &tiling);
834 if (err < 0)
835 return err;
836
837 spin_lock_irqsave(&dc->lock, flags);
838
839 tegra_dc_writel(dc, WINDOW_A_SELECT, DC_CMD_DISPLAY_WINDOW_HEADER);
840
841 value = fb->offsets[0] + y * fb->pitches[0] +
842 x * fb->bits_per_pixel / 8;
843
844 tegra_dc_writel(dc, bo->paddr + value, DC_WINBUF_START_ADDR);
845 tegra_dc_writel(dc, fb->pitches[0], DC_WIN_LINE_STRIDE);
846
847 format = tegra_dc_format(fb->pixel_format, &swap);
848 tegra_dc_writel(dc, format, DC_WIN_COLOR_DEPTH);
849 tegra_dc_writel(dc, swap, DC_WIN_BYTE_SWAP);
850
851 if (dc->soc->supports_block_linear) {
852 unsigned long height = tiling.value;
853
854 switch (tiling.mode) {
855 case TEGRA_BO_TILING_MODE_PITCH:
856 value = DC_WINBUF_SURFACE_KIND_PITCH;
857 break;
858
859 case TEGRA_BO_TILING_MODE_TILED:
860 value = DC_WINBUF_SURFACE_KIND_TILED;
861 break;
862
863 case TEGRA_BO_TILING_MODE_BLOCK:
864 value = DC_WINBUF_SURFACE_KIND_BLOCK_HEIGHT(height) |
865 DC_WINBUF_SURFACE_KIND_BLOCK;
866 break;
867 }
868
869 tegra_dc_writel(dc, value, DC_WINBUF_SURFACE_KIND);
870 } else {
871 switch (tiling.mode) {
872 case TEGRA_BO_TILING_MODE_PITCH:
873 value = DC_WIN_BUFFER_ADDR_MODE_LINEAR_UV |
874 DC_WIN_BUFFER_ADDR_MODE_LINEAR;
875 break;
876
877 case TEGRA_BO_TILING_MODE_TILED:
878 value = DC_WIN_BUFFER_ADDR_MODE_TILE_UV |
879 DC_WIN_BUFFER_ADDR_MODE_TILE;
880 break;
881
882 case TEGRA_BO_TILING_MODE_BLOCK:
883 DRM_ERROR("hardware doesn't support block linear mode\n");
884 spin_unlock_irqrestore(&dc->lock, flags);
885 return -EINVAL;
886 }
887
888 tegra_dc_writel(dc, value, DC_WIN_BUFFER_ADDR_MODE);
889 }
890
891 /* make sure bottom-up buffers are properly displayed */
892 if (tegra_fb_is_bottom_up(fb)) {
893 value = tegra_dc_readl(dc, DC_WIN_WIN_OPTIONS);
894 value |= V_DIRECTION;
895 tegra_dc_writel(dc, value, DC_WIN_WIN_OPTIONS);
896
897 v_offset += fb->height - 1;
898 } else {
899 value = tegra_dc_readl(dc, DC_WIN_WIN_OPTIONS);
900 value &= ~V_DIRECTION;
901 tegra_dc_writel(dc, value, DC_WIN_WIN_OPTIONS);
902 }
903
904 tegra_dc_writel(dc, h_offset, DC_WINBUF_ADDR_H_OFFSET);
905 tegra_dc_writel(dc, v_offset, DC_WINBUF_ADDR_V_OFFSET);
906
907 value = GENERAL_ACT_REQ | WIN_A_ACT_REQ;
908 tegra_dc_writel(dc, value << 8, DC_CMD_STATE_CONTROL);
909 tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL);
910
911 spin_unlock_irqrestore(&dc->lock, flags);
912
913 return 0;
914}
915
916void tegra_dc_enable_vblank(struct tegra_dc *dc) 823void tegra_dc_enable_vblank(struct tegra_dc *dc)
917{ 824{
918 unsigned long value, flags; 825 unsigned long value, flags;
@@ -991,30 +898,6 @@ void tegra_dc_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file)
991 spin_unlock_irqrestore(&drm->event_lock, flags); 898 spin_unlock_irqrestore(&drm->event_lock, flags);
992} 899}
993 900
994static int tegra_dc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
995 struct drm_pending_vblank_event *event, uint32_t page_flip_flags)
996{
997 unsigned int pipe = drm_crtc_index(crtc);
998 struct tegra_dc *dc = to_tegra_dc(crtc);
999
1000 if (dc->event)
1001 return -EBUSY;
1002
1003 if (event) {
1004 event->pipe = pipe;
1005 dc->event = event;
1006 drm_crtc_vblank_get(crtc);
1007 }
1008
1009 if (crtc->primary->state)
1010 drm_atomic_set_fb_for_plane(crtc->primary->state, fb);
1011
1012 tegra_dc_set_base(dc, 0, 0, fb);
1013 crtc->primary->fb = fb;
1014
1015 return 0;
1016}
1017
1018static void tegra_dc_destroy(struct drm_crtc *crtc) 901static void tegra_dc_destroy(struct drm_crtc *crtc)
1019{ 902{
1020 drm_crtc_cleanup(crtc); 903 drm_crtc_cleanup(crtc);
@@ -1056,7 +939,7 @@ static void tegra_crtc_atomic_destroy_state(struct drm_crtc *crtc,
1056} 939}
1057 940
1058static const struct drm_crtc_funcs tegra_crtc_funcs = { 941static const struct drm_crtc_funcs tegra_crtc_funcs = {
1059 .page_flip = tegra_dc_page_flip, 942 .page_flip = drm_atomic_helper_page_flip,
1060 .set_config = drm_atomic_helper_set_config, 943 .set_config = drm_atomic_helper_set_config,
1061 .destroy = tegra_dc_destroy, 944 .destroy = tegra_dc_destroy,
1062 .reset = tegra_crtc_reset, 945 .reset = tegra_crtc_reset,
@@ -1326,6 +1209,16 @@ static int tegra_crtc_atomic_check(struct drm_crtc *crtc,
1326 1209
1327static void tegra_crtc_atomic_begin(struct drm_crtc *crtc) 1210static void tegra_crtc_atomic_begin(struct drm_crtc *crtc)
1328{ 1211{
1212 struct tegra_dc *dc = to_tegra_dc(crtc);
1213
1214 if (crtc->state->event) {
1215 crtc->state->event->pipe = drm_crtc_index(crtc);
1216
1217 WARN_ON(drm_crtc_vblank_get(crtc) != 0);
1218
1219 dc->event = crtc->state->event;
1220 crtc->state->event = NULL;
1221 }
1329} 1222}
1330 1223
1331static void tegra_crtc_atomic_flush(struct drm_crtc *crtc) 1224static void tegra_crtc_atomic_flush(struct drm_crtc *crtc)