diff options
author | Thierry Reding <treding@nvidia.com> | 2014-11-24 11:41:23 -0500 |
---|---|---|
committer | Thierry Reding <treding@nvidia.com> | 2015-01-27 04:14:55 -0500 |
commit | 1503ca47d76e184eaeabe7cfa31de97b5ec36a04 (patch) | |
tree | 8a97feb074e208da908f0b606b413174bc529f38 /drivers/gpu/drm/tegra/dc.c | |
parent | 74f48791ad69789bc70eb4d99233d83e016f5f14 (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.c | 129 |
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 | ||
823 | static 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 | |||
916 | void tegra_dc_enable_vblank(struct tegra_dc *dc) | 823 | void 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 | ||
994 | static 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 | |||
1018 | static void tegra_dc_destroy(struct drm_crtc *crtc) | 901 | static 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 | ||
1058 | static const struct drm_crtc_funcs tegra_crtc_funcs = { | 941 | static 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 | ||
1327 | static void tegra_crtc_atomic_begin(struct drm_crtc *crtc) | 1210 | static 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 | ||
1331 | static void tegra_crtc_atomic_flush(struct drm_crtc *crtc) | 1224 | static void tegra_crtc_atomic_flush(struct drm_crtc *crtc) |