diff options
| -rw-r--r-- | drivers/gpu/drm/tegra/dc.c | 71 | ||||
| -rw-r--r-- | drivers/gpu/drm/tegra/drm.h | 4 |
2 files changed, 72 insertions, 3 deletions
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index 4fb9048b2f65..b905a4e2bdf9 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c | |||
| @@ -41,6 +41,22 @@ static inline struct tegra_plane *to_tegra_plane(struct drm_plane *plane) | |||
| 41 | return container_of(plane, struct tegra_plane, base); | 41 | return container_of(plane, struct tegra_plane, base); |
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | struct tegra_dc_state { | ||
| 45 | struct drm_crtc_state base; | ||
| 46 | |||
| 47 | struct clk *clk; | ||
| 48 | unsigned long pclk; | ||
| 49 | unsigned int div; | ||
| 50 | }; | ||
| 51 | |||
| 52 | static inline struct tegra_dc_state *to_dc_state(struct drm_crtc_state *state) | ||
| 53 | { | ||
| 54 | if (state) | ||
| 55 | return container_of(state, struct tegra_dc_state, base); | ||
| 56 | |||
| 57 | return NULL; | ||
| 58 | } | ||
| 59 | |||
| 44 | static void tegra_dc_window_commit(struct tegra_dc *dc, unsigned int index) | 60 | static void tegra_dc_window_commit(struct tegra_dc *dc, unsigned int index) |
| 45 | { | 61 | { |
| 46 | u32 value = WIN_A_ACT_REQ << index; | 62 | u32 value = WIN_A_ACT_REQ << index; |
| @@ -1004,13 +1020,48 @@ static void tegra_dc_destroy(struct drm_crtc *crtc) | |||
| 1004 | drm_crtc_cleanup(crtc); | 1020 | drm_crtc_cleanup(crtc); |
| 1005 | } | 1021 | } |
| 1006 | 1022 | ||
| 1023 | static void tegra_crtc_reset(struct drm_crtc *crtc) | ||
| 1024 | { | ||
| 1025 | struct tegra_dc_state *state; | ||
| 1026 | |||
| 1027 | kfree(crtc->state); | ||
| 1028 | crtc->state = NULL; | ||
| 1029 | |||
| 1030 | state = kzalloc(sizeof(*state), GFP_KERNEL); | ||
| 1031 | if (state) | ||
| 1032 | crtc->state = &state->base; | ||
| 1033 | } | ||
| 1034 | |||
| 1035 | static struct drm_crtc_state * | ||
| 1036 | tegra_crtc_atomic_duplicate_state(struct drm_crtc *crtc) | ||
| 1037 | { | ||
| 1038 | struct tegra_dc_state *state = to_dc_state(crtc->state); | ||
| 1039 | struct tegra_dc_state *copy; | ||
| 1040 | |||
| 1041 | copy = kmemdup(state, sizeof(*state), GFP_KERNEL); | ||
| 1042 | if (!copy) | ||
| 1043 | return NULL; | ||
| 1044 | |||
| 1045 | copy->base.mode_changed = false; | ||
| 1046 | copy->base.planes_changed = false; | ||
| 1047 | copy->base.event = NULL; | ||
| 1048 | |||
| 1049 | return ©->base; | ||
| 1050 | } | ||
| 1051 | |||
| 1052 | static void tegra_crtc_atomic_destroy_state(struct drm_crtc *crtc, | ||
| 1053 | struct drm_crtc_state *state) | ||
| 1054 | { | ||
| 1055 | kfree(state); | ||
| 1056 | } | ||
| 1057 | |||
| 1007 | static const struct drm_crtc_funcs tegra_crtc_funcs = { | 1058 | static const struct drm_crtc_funcs tegra_crtc_funcs = { |
| 1008 | .page_flip = tegra_dc_page_flip, | 1059 | .page_flip = tegra_dc_page_flip, |
| 1009 | .set_config = drm_crtc_helper_set_config, | 1060 | .set_config = drm_crtc_helper_set_config, |
| 1010 | .destroy = tegra_dc_destroy, | 1061 | .destroy = tegra_dc_destroy, |
| 1011 | .reset = drm_atomic_helper_crtc_reset, | 1062 | .reset = tegra_crtc_reset, |
| 1012 | .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, | 1063 | .atomic_duplicate_state = tegra_crtc_atomic_duplicate_state, |
| 1013 | .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, | 1064 | .atomic_destroy_state = tegra_crtc_atomic_destroy_state, |
| 1014 | }; | 1065 | }; |
| 1015 | 1066 | ||
| 1016 | static void tegra_dc_stop(struct tegra_dc *dc) | 1067 | static void tegra_dc_stop(struct tegra_dc *dc) |
| @@ -1148,6 +1199,20 @@ int tegra_dc_setup_clock(struct tegra_dc *dc, struct clk *parent, | |||
| 1148 | return 0; | 1199 | return 0; |
| 1149 | } | 1200 | } |
| 1150 | 1201 | ||
| 1202 | int tegra_dc_state_setup_clock(struct tegra_dc *dc, | ||
| 1203 | struct drm_crtc_state *crtc_state, | ||
| 1204 | struct clk *clk, unsigned long pclk, | ||
| 1205 | unsigned int div) | ||
| 1206 | { | ||
| 1207 | struct tegra_dc_state *state = to_dc_state(crtc_state); | ||
| 1208 | |||
| 1209 | state->clk = clk; | ||
| 1210 | state->pclk = pclk; | ||
| 1211 | state->div = div; | ||
| 1212 | |||
| 1213 | return 0; | ||
| 1214 | } | ||
| 1215 | |||
| 1151 | static void tegra_crtc_mode_set_nofb(struct drm_crtc *crtc) | 1216 | static void tegra_crtc_mode_set_nofb(struct drm_crtc *crtc) |
| 1152 | { | 1217 | { |
| 1153 | struct drm_display_mode *mode = &crtc->state->adjusted_mode; | 1218 | struct drm_display_mode *mode = &crtc->state->adjusted_mode; |
diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h index bf1c47ec46b6..3db719de312f 100644 --- a/drivers/gpu/drm/tegra/drm.h +++ b/drivers/gpu/drm/tegra/drm.h | |||
| @@ -180,6 +180,10 @@ void tegra_dc_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file); | |||
| 180 | void tegra_dc_commit(struct tegra_dc *dc); | 180 | void tegra_dc_commit(struct tegra_dc *dc); |
| 181 | int tegra_dc_setup_clock(struct tegra_dc *dc, struct clk *parent, | 181 | int tegra_dc_setup_clock(struct tegra_dc *dc, struct clk *parent, |
| 182 | unsigned long pclk, unsigned int div); | 182 | unsigned long pclk, unsigned int div); |
| 183 | int tegra_dc_state_setup_clock(struct tegra_dc *dc, | ||
| 184 | struct drm_crtc_state *crtc_state, | ||
| 185 | struct clk *clk, unsigned long pclk, | ||
| 186 | unsigned int div); | ||
| 183 | 187 | ||
| 184 | struct tegra_output { | 188 | struct tegra_output { |
| 185 | struct device_node *of_node; | 189 | struct device_node *of_node; |
