diff options
| -rw-r--r-- | drivers/gpu/drm/drm_atomic_helper.c | 144 | ||||
| -rw-r--r-- | drivers/gpu/drm/tegra/dc.c | 99 | ||||
| -rw-r--r-- | drivers/gpu/drm/tegra/dc.h | 7 | ||||
| -rw-r--r-- | drivers/gpu/drm/tegra/drm.c | 18 | ||||
| -rw-r--r-- | drivers/gpu/drm/tegra/drm.h | 4 | ||||
| -rw-r--r-- | drivers/gpu/drm/tegra/hdmi.c | 4 | ||||
| -rw-r--r-- | drivers/gpu/drm/tegra/hdmi.h | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/tegra/sor.c | 202 | ||||
| -rw-r--r-- | drivers/gpu/host1x/syncpt.c | 6 | ||||
| -rw-r--r-- | include/drm/drm_atomic_helper.h | 14 | ||||
| -rw-r--r-- | include/linux/host1x.h | 1 | ||||
| -rw-r--r-- | include/uapi/drm/tegra_drm.h | 3 |
12 files changed, 421 insertions, 83 deletions
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index e67d4d69faf7..41c38edade74 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c | |||
| @@ -2069,6 +2069,26 @@ void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc) | |||
| 2069 | EXPORT_SYMBOL(drm_atomic_helper_crtc_reset); | 2069 | EXPORT_SYMBOL(drm_atomic_helper_crtc_reset); |
| 2070 | 2070 | ||
| 2071 | /** | 2071 | /** |
| 2072 | * __drm_atomic_helper_crtc_duplicate_state - copy atomic CRTC state | ||
| 2073 | * @crtc: CRTC object | ||
| 2074 | * @state: atomic CRTC state | ||
| 2075 | * | ||
| 2076 | * Copies atomic state from a CRTC's current state and resets inferred values. | ||
| 2077 | * This is useful for drivers that subclass the CRTC state. | ||
| 2078 | */ | ||
| 2079 | void __drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc, | ||
| 2080 | struct drm_crtc_state *state) | ||
| 2081 | { | ||
| 2082 | memcpy(state, crtc->state, sizeof(*state)); | ||
| 2083 | |||
| 2084 | state->mode_changed = false; | ||
| 2085 | state->active_changed = false; | ||
| 2086 | state->planes_changed = false; | ||
| 2087 | state->event = NULL; | ||
| 2088 | } | ||
| 2089 | EXPORT_SYMBOL(__drm_atomic_helper_crtc_duplicate_state); | ||
| 2090 | |||
| 2091 | /** | ||
| 2072 | * drm_atomic_helper_crtc_duplicate_state - default state duplicate hook | 2092 | * drm_atomic_helper_crtc_duplicate_state - default state duplicate hook |
| 2073 | * @crtc: drm CRTC | 2093 | * @crtc: drm CRTC |
| 2074 | * | 2094 | * |
| @@ -2083,20 +2103,35 @@ drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc) | |||
| 2083 | if (WARN_ON(!crtc->state)) | 2103 | if (WARN_ON(!crtc->state)) |
| 2084 | return NULL; | 2104 | return NULL; |
| 2085 | 2105 | ||
| 2086 | state = kmemdup(crtc->state, sizeof(*crtc->state), GFP_KERNEL); | 2106 | state = kmalloc(sizeof(*state), GFP_KERNEL); |
| 2087 | 2107 | if (state) | |
| 2088 | if (state) { | 2108 | __drm_atomic_helper_crtc_duplicate_state(crtc, state); |
| 2089 | state->mode_changed = false; | ||
| 2090 | state->active_changed = false; | ||
| 2091 | state->planes_changed = false; | ||
| 2092 | state->event = NULL; | ||
| 2093 | } | ||
| 2094 | 2109 | ||
| 2095 | return state; | 2110 | return state; |
| 2096 | } | 2111 | } |
| 2097 | EXPORT_SYMBOL(drm_atomic_helper_crtc_duplicate_state); | 2112 | EXPORT_SYMBOL(drm_atomic_helper_crtc_duplicate_state); |
| 2098 | 2113 | ||
| 2099 | /** | 2114 | /** |
| 2115 | * __drm_atomic_helper_crtc_destroy_state - release CRTC state | ||
| 2116 | * @crtc: CRTC object | ||
| 2117 | * @state: CRTC state object to release | ||
| 2118 | * | ||
| 2119 | * Releases all resources stored in the CRTC state without actually freeing | ||
| 2120 | * the memory of the CRTC state. This is useful for drivers that subclass the | ||
| 2121 | * CRTC state. | ||
| 2122 | */ | ||
| 2123 | void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc, | ||
| 2124 | struct drm_crtc_state *state) | ||
| 2125 | { | ||
| 2126 | /* | ||
| 2127 | * This is currently a placeholder so that drivers that subclass the | ||
| 2128 | * state will automatically do the right thing if code is ever added | ||
| 2129 | * to this function. | ||
| 2130 | */ | ||
| 2131 | } | ||
| 2132 | EXPORT_SYMBOL(__drm_atomic_helper_crtc_destroy_state); | ||
| 2133 | |||
| 2134 | /** | ||
| 2100 | * drm_atomic_helper_crtc_destroy_state - default state destroy hook | 2135 | * drm_atomic_helper_crtc_destroy_state - default state destroy hook |
| 2101 | * @crtc: drm CRTC | 2136 | * @crtc: drm CRTC |
| 2102 | * @state: CRTC state object to release | 2137 | * @state: CRTC state object to release |
| @@ -2107,6 +2142,7 @@ EXPORT_SYMBOL(drm_atomic_helper_crtc_duplicate_state); | |||
| 2107 | void drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc, | 2142 | void drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc, |
| 2108 | struct drm_crtc_state *state) | 2143 | struct drm_crtc_state *state) |
| 2109 | { | 2144 | { |
| 2145 | __drm_atomic_helper_crtc_destroy_state(crtc, state); | ||
| 2110 | kfree(state); | 2146 | kfree(state); |
| 2111 | } | 2147 | } |
| 2112 | EXPORT_SYMBOL(drm_atomic_helper_crtc_destroy_state); | 2148 | EXPORT_SYMBOL(drm_atomic_helper_crtc_destroy_state); |
| @@ -2132,6 +2168,24 @@ void drm_atomic_helper_plane_reset(struct drm_plane *plane) | |||
| 2132 | EXPORT_SYMBOL(drm_atomic_helper_plane_reset); | 2168 | EXPORT_SYMBOL(drm_atomic_helper_plane_reset); |
| 2133 | 2169 | ||
| 2134 | /** | 2170 | /** |
| 2171 | * __drm_atomic_helper_plane_duplicate_state - copy atomic plane state | ||
| 2172 | * @plane: plane object | ||
| 2173 | * @state: atomic plane state | ||
| 2174 | * | ||
| 2175 | * Copies atomic state from a plane's current state. This is useful for | ||
| 2176 | * drivers that subclass the plane state. | ||
| 2177 | */ | ||
| 2178 | void __drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane, | ||
| 2179 | struct drm_plane_state *state) | ||
| 2180 | { | ||
| 2181 | memcpy(state, plane->state, sizeof(*state)); | ||
| 2182 | |||
| 2183 | if (state->fb) | ||
| 2184 | drm_framebuffer_reference(state->fb); | ||
| 2185 | } | ||
| 2186 | EXPORT_SYMBOL(__drm_atomic_helper_plane_duplicate_state); | ||
| 2187 | |||
| 2188 | /** | ||
| 2135 | * drm_atomic_helper_plane_duplicate_state - default state duplicate hook | 2189 | * drm_atomic_helper_plane_duplicate_state - default state duplicate hook |
| 2136 | * @plane: drm plane | 2190 | * @plane: drm plane |
| 2137 | * | 2191 | * |
| @@ -2146,16 +2200,32 @@ drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane) | |||
| 2146 | if (WARN_ON(!plane->state)) | 2200 | if (WARN_ON(!plane->state)) |
| 2147 | return NULL; | 2201 | return NULL; |
| 2148 | 2202 | ||
| 2149 | state = kmemdup(plane->state, sizeof(*plane->state), GFP_KERNEL); | 2203 | state = kmalloc(sizeof(*state), GFP_KERNEL); |
| 2150 | 2204 | if (state) | |
| 2151 | if (state && state->fb) | 2205 | __drm_atomic_helper_plane_duplicate_state(plane, state); |
| 2152 | drm_framebuffer_reference(state->fb); | ||
| 2153 | 2206 | ||
| 2154 | return state; | 2207 | return state; |
| 2155 | } | 2208 | } |
| 2156 | EXPORT_SYMBOL(drm_atomic_helper_plane_duplicate_state); | 2209 | EXPORT_SYMBOL(drm_atomic_helper_plane_duplicate_state); |
| 2157 | 2210 | ||
| 2158 | /** | 2211 | /** |
| 2212 | * __drm_atomic_helper_plane_destroy_state - release plane state | ||
| 2213 | * @plane: plane object | ||
| 2214 | * @state: plane state object to release | ||
| 2215 | * | ||
| 2216 | * Releases all resources stored in the plane state without actually freeing | ||
| 2217 | * the memory of the plane state. This is useful for drivers that subclass the | ||
| 2218 | * plane state. | ||
| 2219 | */ | ||
| 2220 | void __drm_atomic_helper_plane_destroy_state(struct drm_plane *plane, | ||
| 2221 | struct drm_plane_state *state) | ||
| 2222 | { | ||
| 2223 | if (state->fb) | ||
| 2224 | drm_framebuffer_unreference(state->fb); | ||
| 2225 | } | ||
| 2226 | EXPORT_SYMBOL(__drm_atomic_helper_plane_destroy_state); | ||
| 2227 | |||
| 2228 | /** | ||
| 2159 | * drm_atomic_helper_plane_destroy_state - default state destroy hook | 2229 | * drm_atomic_helper_plane_destroy_state - default state destroy hook |
| 2160 | * @plane: drm plane | 2230 | * @plane: drm plane |
| 2161 | * @state: plane state object to release | 2231 | * @state: plane state object to release |
| @@ -2166,9 +2236,7 @@ EXPORT_SYMBOL(drm_atomic_helper_plane_duplicate_state); | |||
| 2166 | void drm_atomic_helper_plane_destroy_state(struct drm_plane *plane, | 2236 | void drm_atomic_helper_plane_destroy_state(struct drm_plane *plane, |
| 2167 | struct drm_plane_state *state) | 2237 | struct drm_plane_state *state) |
| 2168 | { | 2238 | { |
| 2169 | if (state->fb) | 2239 | __drm_atomic_helper_plane_destroy_state(plane, state); |
| 2170 | drm_framebuffer_unreference(state->fb); | ||
| 2171 | |||
| 2172 | kfree(state); | 2240 | kfree(state); |
| 2173 | } | 2241 | } |
| 2174 | EXPORT_SYMBOL(drm_atomic_helper_plane_destroy_state); | 2242 | EXPORT_SYMBOL(drm_atomic_helper_plane_destroy_state); |
| @@ -2192,6 +2260,22 @@ void drm_atomic_helper_connector_reset(struct drm_connector *connector) | |||
| 2192 | EXPORT_SYMBOL(drm_atomic_helper_connector_reset); | 2260 | EXPORT_SYMBOL(drm_atomic_helper_connector_reset); |
| 2193 | 2261 | ||
| 2194 | /** | 2262 | /** |
| 2263 | * __drm_atomic_helper_connector_duplicate_state - copy atomic connector state | ||
| 2264 | * @connector: connector object | ||
| 2265 | * @state: atomic connector state | ||
| 2266 | * | ||
| 2267 | * Copies atomic state from a connector's current state. This is useful for | ||
| 2268 | * drivers that subclass the connector state. | ||
| 2269 | */ | ||
| 2270 | void | ||
| 2271 | __drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector, | ||
| 2272 | struct drm_connector_state *state) | ||
| 2273 | { | ||
| 2274 | memcpy(state, connector->state, sizeof(*state)); | ||
| 2275 | } | ||
| 2276 | EXPORT_SYMBOL(__drm_atomic_helper_connector_duplicate_state); | ||
| 2277 | |||
| 2278 | /** | ||
| 2195 | * drm_atomic_helper_connector_duplicate_state - default state duplicate hook | 2279 | * drm_atomic_helper_connector_duplicate_state - default state duplicate hook |
| 2196 | * @connector: drm connector | 2280 | * @connector: drm connector |
| 2197 | * | 2281 | * |
| @@ -2201,14 +2285,41 @@ EXPORT_SYMBOL(drm_atomic_helper_connector_reset); | |||
| 2201 | struct drm_connector_state * | 2285 | struct drm_connector_state * |
| 2202 | drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector) | 2286 | drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector) |
| 2203 | { | 2287 | { |
| 2288 | struct drm_connector_state *state; | ||
| 2289 | |||
| 2204 | if (WARN_ON(!connector->state)) | 2290 | if (WARN_ON(!connector->state)) |
| 2205 | return NULL; | 2291 | return NULL; |
| 2206 | 2292 | ||
| 2207 | return kmemdup(connector->state, sizeof(*connector->state), GFP_KERNEL); | 2293 | state = kmalloc(sizeof(*state), GFP_KERNEL); |
| 2294 | if (state) | ||
| 2295 | __drm_atomic_helper_connector_duplicate_state(connector, state); | ||
| 2296 | |||
| 2297 | return state; | ||
| 2208 | } | 2298 | } |
| 2209 | EXPORT_SYMBOL(drm_atomic_helper_connector_duplicate_state); | 2299 | EXPORT_SYMBOL(drm_atomic_helper_connector_duplicate_state); |
| 2210 | 2300 | ||
| 2211 | /** | 2301 | /** |
| 2302 | * __drm_atomic_helper_connector_destroy_state - release connector state | ||
| 2303 | * @connector: connector object | ||
| 2304 | * @state: connector state object to release | ||
| 2305 | * | ||
| 2306 | * Releases all resources stored in the connector state without actually | ||
| 2307 | * freeing the memory of the connector state. This is useful for drivers that | ||
| 2308 | * subclass the connector state. | ||
| 2309 | */ | ||
| 2310 | void | ||
| 2311 | __drm_atomic_helper_connector_destroy_state(struct drm_connector *connector, | ||
| 2312 | struct drm_connector_state *state) | ||
| 2313 | { | ||
| 2314 | /* | ||
| 2315 | * This is currently a placeholder so that drivers that subclass the | ||
| 2316 | * state will automatically do the right thing if code is ever added | ||
| 2317 | * to this function. | ||
| 2318 | */ | ||
| 2319 | } | ||
| 2320 | EXPORT_SYMBOL(__drm_atomic_helper_connector_destroy_state); | ||
| 2321 | |||
| 2322 | /** | ||
| 2212 | * drm_atomic_helper_connector_destroy_state - default state destroy hook | 2323 | * drm_atomic_helper_connector_destroy_state - default state destroy hook |
| 2213 | * @connector: drm connector | 2324 | * @connector: drm connector |
| 2214 | * @state: connector state object to release | 2325 | * @state: connector state object to release |
| @@ -2219,6 +2330,7 @@ EXPORT_SYMBOL(drm_atomic_helper_connector_duplicate_state); | |||
| 2219 | void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector, | 2330 | void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector, |
| 2220 | struct drm_connector_state *state) | 2331 | struct drm_connector_state *state) |
| 2221 | { | 2332 | { |
| 2333 | __drm_atomic_helper_connector_destroy_state(connector, state); | ||
| 2222 | kfree(state); | 2334 | kfree(state); |
| 2223 | } | 2335 | } |
| 2224 | EXPORT_SYMBOL(drm_atomic_helper_connector_destroy_state); | 2336 | EXPORT_SYMBOL(drm_atomic_helper_connector_destroy_state); |
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index b7f781573b15..a287e4fec865 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c | |||
| @@ -425,8 +425,8 @@ static void tegra_plane_reset(struct drm_plane *plane) | |||
| 425 | { | 425 | { |
| 426 | struct tegra_plane_state *state; | 426 | struct tegra_plane_state *state; |
| 427 | 427 | ||
| 428 | if (plane->state && plane->state->fb) | 428 | if (plane->state) |
| 429 | drm_framebuffer_unreference(plane->state->fb); | 429 | __drm_atomic_helper_plane_destroy_state(plane, plane->state); |
| 430 | 430 | ||
| 431 | kfree(plane->state); | 431 | kfree(plane->state); |
| 432 | plane->state = NULL; | 432 | plane->state = NULL; |
| @@ -443,12 +443,14 @@ static struct drm_plane_state *tegra_plane_atomic_duplicate_state(struct drm_pla | |||
| 443 | struct tegra_plane_state *state = to_tegra_plane_state(plane->state); | 443 | struct tegra_plane_state *state = to_tegra_plane_state(plane->state); |
| 444 | struct tegra_plane_state *copy; | 444 | struct tegra_plane_state *copy; |
| 445 | 445 | ||
| 446 | copy = kmemdup(state, sizeof(*state), GFP_KERNEL); | 446 | copy = kmalloc(sizeof(*copy), GFP_KERNEL); |
| 447 | if (!copy) | 447 | if (!copy) |
| 448 | return NULL; | 448 | return NULL; |
| 449 | 449 | ||
| 450 | if (copy->base.fb) | 450 | __drm_atomic_helper_plane_duplicate_state(plane, ©->base); |
| 451 | drm_framebuffer_reference(copy->base.fb); | 451 | copy->tiling = state->tiling; |
| 452 | copy->format = state->format; | ||
| 453 | copy->swap = state->swap; | ||
| 452 | 454 | ||
| 453 | return ©->base; | 455 | return ©->base; |
| 454 | } | 456 | } |
| @@ -456,9 +458,7 @@ static struct drm_plane_state *tegra_plane_atomic_duplicate_state(struct drm_pla | |||
| 456 | static void tegra_plane_atomic_destroy_state(struct drm_plane *plane, | 458 | static void tegra_plane_atomic_destroy_state(struct drm_plane *plane, |
| 457 | struct drm_plane_state *state) | 459 | struct drm_plane_state *state) |
| 458 | { | 460 | { |
| 459 | if (state->fb) | 461 | __drm_atomic_helper_plane_destroy_state(plane, state); |
| 460 | drm_framebuffer_unreference(state->fb); | ||
| 461 | |||
| 462 | kfree(state); | 462 | kfree(state); |
| 463 | } | 463 | } |
| 464 | 464 | ||
| @@ -908,6 +908,15 @@ static int tegra_dc_add_planes(struct drm_device *drm, struct tegra_dc *dc) | |||
| 908 | return 0; | 908 | return 0; |
| 909 | } | 909 | } |
| 910 | 910 | ||
| 911 | u32 tegra_dc_get_vblank_counter(struct tegra_dc *dc) | ||
| 912 | { | ||
| 913 | if (dc->syncpt) | ||
| 914 | return host1x_syncpt_read(dc->syncpt); | ||
| 915 | |||
| 916 | /* fallback to software emulated VBLANK counter */ | ||
| 917 | return drm_crtc_vblank_count(&dc->base); | ||
| 918 | } | ||
| 919 | |||
| 911 | void tegra_dc_enable_vblank(struct tegra_dc *dc) | 920 | void tegra_dc_enable_vblank(struct tegra_dc *dc) |
| 912 | { | 921 | { |
| 913 | unsigned long value, flags; | 922 | unsigned long value, flags; |
| @@ -995,6 +1004,9 @@ static void tegra_crtc_reset(struct drm_crtc *crtc) | |||
| 995 | { | 1004 | { |
| 996 | struct tegra_dc_state *state; | 1005 | struct tegra_dc_state *state; |
| 997 | 1006 | ||
| 1007 | if (crtc->state) | ||
| 1008 | __drm_atomic_helper_crtc_destroy_state(crtc, crtc->state); | ||
| 1009 | |||
| 998 | kfree(crtc->state); | 1010 | kfree(crtc->state); |
| 999 | crtc->state = NULL; | 1011 | crtc->state = NULL; |
| 1000 | 1012 | ||
| @@ -1011,14 +1023,15 @@ tegra_crtc_atomic_duplicate_state(struct drm_crtc *crtc) | |||
| 1011 | struct tegra_dc_state *state = to_dc_state(crtc->state); | 1023 | struct tegra_dc_state *state = to_dc_state(crtc->state); |
| 1012 | struct tegra_dc_state *copy; | 1024 | struct tegra_dc_state *copy; |
| 1013 | 1025 | ||
| 1014 | copy = kmemdup(state, sizeof(*state), GFP_KERNEL); | 1026 | copy = kmalloc(sizeof(*copy), GFP_KERNEL); |
| 1015 | if (!copy) | 1027 | if (!copy) |
| 1016 | return NULL; | 1028 | return NULL; |
| 1017 | 1029 | ||
| 1018 | copy->base.mode_changed = false; | 1030 | __drm_atomic_helper_crtc_duplicate_state(crtc, ©->base); |
| 1019 | copy->base.active_changed = false; | 1031 | copy->clk = state->clk; |
| 1020 | copy->base.planes_changed = false; | 1032 | copy->pclk = state->pclk; |
| 1021 | copy->base.event = NULL; | 1033 | copy->div = state->div; |
| 1034 | copy->planes = state->planes; | ||
| 1022 | 1035 | ||
| 1023 | return ©->base; | 1036 | return ©->base; |
| 1024 | } | 1037 | } |
| @@ -1026,6 +1039,7 @@ tegra_crtc_atomic_duplicate_state(struct drm_crtc *crtc) | |||
| 1026 | static void tegra_crtc_atomic_destroy_state(struct drm_crtc *crtc, | 1039 | static void tegra_crtc_atomic_destroy_state(struct drm_crtc *crtc, |
| 1027 | struct drm_crtc_state *state) | 1040 | struct drm_crtc_state *state) |
| 1028 | { | 1041 | { |
| 1042 | __drm_atomic_helper_crtc_destroy_state(crtc, state); | ||
| 1029 | kfree(state); | 1043 | kfree(state); |
| 1030 | } | 1044 | } |
| 1031 | 1045 | ||
| @@ -1152,26 +1166,18 @@ static int tegra_dc_set_timings(struct tegra_dc *dc, | |||
| 1152 | return 0; | 1166 | return 0; |
| 1153 | } | 1167 | } |
| 1154 | 1168 | ||
| 1155 | int tegra_dc_setup_clock(struct tegra_dc *dc, struct clk *parent, | 1169 | /** |
| 1156 | unsigned long pclk, unsigned int div) | 1170 | * tegra_dc_state_setup_clock - check clock settings and store them in atomic |
| 1157 | { | 1171 | * state |
| 1158 | u32 value; | 1172 | * @dc: display controller |
| 1159 | int err; | 1173 | * @crtc_state: CRTC atomic state |
| 1160 | 1174 | * @clk: parent clock for display controller | |
| 1161 | err = clk_set_parent(dc->clk, parent); | 1175 | * @pclk: pixel clock |
| 1162 | if (err < 0) { | 1176 | * @div: shift clock divider |
| 1163 | dev_err(dc->dev, "failed to set parent clock: %d\n", err); | 1177 | * |
| 1164 | return err; | 1178 | * Returns: |
| 1165 | } | 1179 | * 0 on success or a negative error-code on failure. |
| 1166 | 1180 | */ | |
| 1167 | DRM_DEBUG_KMS("rate: %lu, div: %u\n", clk_get_rate(dc->clk), div); | ||
| 1168 | |||
| 1169 | value = SHIFT_CLK_DIVIDER(div) | PIXEL_CLK_DIVIDER_PCD1; | ||
| 1170 | tegra_dc_writel(dc, value, DC_DISP_DISP_CLOCK_CONTROL); | ||
| 1171 | |||
| 1172 | return 0; | ||
| 1173 | } | ||
| 1174 | |||
| 1175 | int tegra_dc_state_setup_clock(struct tegra_dc *dc, | 1181 | int tegra_dc_state_setup_clock(struct tegra_dc *dc, |
| 1176 | struct drm_crtc_state *crtc_state, | 1182 | struct drm_crtc_state *crtc_state, |
| 1177 | struct clk *clk, unsigned long pclk, | 1183 | struct clk *clk, unsigned long pclk, |
| @@ -1179,6 +1185,9 @@ int tegra_dc_state_setup_clock(struct tegra_dc *dc, | |||
| 1179 | { | 1185 | { |
| 1180 | struct tegra_dc_state *state = to_dc_state(crtc_state); | 1186 | struct tegra_dc_state *state = to_dc_state(crtc_state); |
| 1181 | 1187 | ||
| 1188 | if (!clk_has_parent(dc->clk, clk)) | ||
| 1189 | return -EINVAL; | ||
| 1190 | |||
| 1182 | state->clk = clk; | 1191 | state->clk = clk; |
| 1183 | state->pclk = pclk; | 1192 | state->pclk = pclk; |
| 1184 | state->div = div; | 1193 | state->div = div; |
| @@ -1294,9 +1303,7 @@ static void tegra_crtc_atomic_flush(struct drm_crtc *crtc) | |||
| 1294 | static const struct drm_crtc_helper_funcs tegra_crtc_helper_funcs = { | 1303 | static const struct drm_crtc_helper_funcs tegra_crtc_helper_funcs = { |
| 1295 | .disable = tegra_crtc_disable, | 1304 | .disable = tegra_crtc_disable, |
| 1296 | .mode_fixup = tegra_crtc_mode_fixup, | 1305 | .mode_fixup = tegra_crtc_mode_fixup, |
| 1297 | .mode_set = drm_helper_crtc_mode_set, | ||
| 1298 | .mode_set_nofb = tegra_crtc_mode_set_nofb, | 1306 | .mode_set_nofb = tegra_crtc_mode_set_nofb, |
| 1299 | .mode_set_base = drm_helper_crtc_mode_set_base, | ||
| 1300 | .prepare = tegra_crtc_prepare, | 1307 | .prepare = tegra_crtc_prepare, |
| 1301 | .commit = tegra_crtc_commit, | 1308 | .commit = tegra_crtc_commit, |
| 1302 | .atomic_check = tegra_crtc_atomic_check, | 1309 | .atomic_check = tegra_crtc_atomic_check, |
| @@ -1631,7 +1638,6 @@ static int tegra_dc_init(struct host1x_client *client) | |||
| 1631 | struct tegra_drm *tegra = drm->dev_private; | 1638 | struct tegra_drm *tegra = drm->dev_private; |
| 1632 | struct drm_plane *primary = NULL; | 1639 | struct drm_plane *primary = NULL; |
| 1633 | struct drm_plane *cursor = NULL; | 1640 | struct drm_plane *cursor = NULL; |
| 1634 | unsigned int syncpt; | ||
| 1635 | u32 value; | 1641 | u32 value; |
| 1636 | int err; | 1642 | int err; |
| 1637 | 1643 | ||
| @@ -1700,13 +1706,15 @@ static int tegra_dc_init(struct host1x_client *client) | |||
| 1700 | } | 1706 | } |
| 1701 | 1707 | ||
| 1702 | /* initialize display controller */ | 1708 | /* initialize display controller */ |
| 1703 | if (dc->pipe) | 1709 | if (dc->syncpt) { |
| 1704 | syncpt = SYNCPT_VBLANK1; | 1710 | u32 syncpt = host1x_syncpt_id(dc->syncpt); |
| 1705 | else | ||
| 1706 | syncpt = SYNCPT_VBLANK0; | ||
| 1707 | 1711 | ||
| 1708 | tegra_dc_writel(dc, 0x00000100, DC_CMD_GENERAL_INCR_SYNCPT_CNTRL); | 1712 | value = SYNCPT_CNTRL_NO_STALL; |
| 1709 | tegra_dc_writel(dc, 0x100 | syncpt, DC_CMD_CONT_SYNCPT_VSYNC); | 1713 | tegra_dc_writel(dc, value, DC_CMD_GENERAL_INCR_SYNCPT_CNTRL); |
| 1714 | |||
| 1715 | value = SYNCPT_VSYNC_ENABLE | syncpt; | ||
| 1716 | tegra_dc_writel(dc, value, DC_CMD_CONT_SYNCPT_VSYNC); | ||
| 1717 | } | ||
| 1710 | 1718 | ||
| 1711 | value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT | WIN_A_OF_INT; | 1719 | value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT | WIN_A_OF_INT; |
| 1712 | tegra_dc_writel(dc, value, DC_CMD_INT_TYPE); | 1720 | tegra_dc_writel(dc, value, DC_CMD_INT_TYPE); |
| @@ -1874,6 +1882,7 @@ static int tegra_dc_parse_dt(struct tegra_dc *dc) | |||
| 1874 | 1882 | ||
| 1875 | static int tegra_dc_probe(struct platform_device *pdev) | 1883 | static int tegra_dc_probe(struct platform_device *pdev) |
| 1876 | { | 1884 | { |
| 1885 | unsigned long flags = HOST1X_SYNCPT_CLIENT_MANAGED; | ||
| 1877 | const struct of_device_id *id; | 1886 | const struct of_device_id *id; |
| 1878 | struct resource *regs; | 1887 | struct resource *regs; |
| 1879 | struct tegra_dc *dc; | 1888 | struct tegra_dc *dc; |
| @@ -1965,6 +1974,10 @@ static int tegra_dc_probe(struct platform_device *pdev) | |||
| 1965 | return err; | 1974 | return err; |
| 1966 | } | 1975 | } |
| 1967 | 1976 | ||
| 1977 | dc->syncpt = host1x_syncpt_request(&pdev->dev, flags); | ||
| 1978 | if (!dc->syncpt) | ||
| 1979 | dev_warn(&pdev->dev, "failed to allocate syncpoint\n"); | ||
| 1980 | |||
| 1968 | platform_set_drvdata(pdev, dc); | 1981 | platform_set_drvdata(pdev, dc); |
| 1969 | 1982 | ||
| 1970 | return 0; | 1983 | return 0; |
| @@ -1975,6 +1988,8 @@ static int tegra_dc_remove(struct platform_device *pdev) | |||
| 1975 | struct tegra_dc *dc = platform_get_drvdata(pdev); | 1988 | struct tegra_dc *dc = platform_get_drvdata(pdev); |
| 1976 | int err; | 1989 | int err; |
| 1977 | 1990 | ||
| 1991 | host1x_syncpt_free(dc->syncpt); | ||
| 1992 | |||
| 1978 | err = host1x_client_unregister(&dc->client); | 1993 | err = host1x_client_unregister(&dc->client); |
| 1979 | if (err < 0) { | 1994 | if (err < 0) { |
| 1980 | dev_err(&pdev->dev, "failed to unregister host1x client: %d\n", | 1995 | dev_err(&pdev->dev, "failed to unregister host1x client: %d\n", |
diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h index 705c93b00794..55792daabbb5 100644 --- a/drivers/gpu/drm/tegra/dc.h +++ b/drivers/gpu/drm/tegra/dc.h | |||
| @@ -12,6 +12,8 @@ | |||
| 12 | 12 | ||
| 13 | #define DC_CMD_GENERAL_INCR_SYNCPT 0x000 | 13 | #define DC_CMD_GENERAL_INCR_SYNCPT 0x000 |
| 14 | #define DC_CMD_GENERAL_INCR_SYNCPT_CNTRL 0x001 | 14 | #define DC_CMD_GENERAL_INCR_SYNCPT_CNTRL 0x001 |
| 15 | #define SYNCPT_CNTRL_NO_STALL (1 << 8) | ||
| 16 | #define SYNCPT_CNTRL_SOFT_RESET (1 << 0) | ||
| 15 | #define DC_CMD_GENERAL_INCR_SYNCPT_ERROR 0x002 | 17 | #define DC_CMD_GENERAL_INCR_SYNCPT_ERROR 0x002 |
| 16 | #define DC_CMD_WIN_A_INCR_SYNCPT 0x008 | 18 | #define DC_CMD_WIN_A_INCR_SYNCPT 0x008 |
| 17 | #define DC_CMD_WIN_A_INCR_SYNCPT_CNTRL 0x009 | 19 | #define DC_CMD_WIN_A_INCR_SYNCPT_CNTRL 0x009 |
| @@ -23,6 +25,7 @@ | |||
| 23 | #define DC_CMD_WIN_C_INCR_SYNCPT_CNTRL 0x019 | 25 | #define DC_CMD_WIN_C_INCR_SYNCPT_CNTRL 0x019 |
| 24 | #define DC_CMD_WIN_C_INCR_SYNCPT_ERROR 0x01a | 26 | #define DC_CMD_WIN_C_INCR_SYNCPT_ERROR 0x01a |
| 25 | #define DC_CMD_CONT_SYNCPT_VSYNC 0x028 | 27 | #define DC_CMD_CONT_SYNCPT_VSYNC 0x028 |
| 28 | #define SYNCPT_VSYNC_ENABLE (1 << 8) | ||
| 26 | #define DC_CMD_DISPLAY_COMMAND_OPTION0 0x031 | 29 | #define DC_CMD_DISPLAY_COMMAND_OPTION0 0x031 |
| 27 | #define DC_CMD_DISPLAY_COMMAND 0x032 | 30 | #define DC_CMD_DISPLAY_COMMAND 0x032 |
| 28 | #define DISP_CTRL_MODE_STOP (0 << 5) | 31 | #define DISP_CTRL_MODE_STOP (0 << 5) |
| @@ -438,8 +441,4 @@ | |||
| 438 | #define DC_WINBUF_BD_UFLOW_STATUS 0xdca | 441 | #define DC_WINBUF_BD_UFLOW_STATUS 0xdca |
| 439 | #define DC_WINBUF_CD_UFLOW_STATUS 0xfca | 442 | #define DC_WINBUF_CD_UFLOW_STATUS 0xfca |
| 440 | 443 | ||
| 441 | /* synchronization points */ | ||
| 442 | #define SYNCPT_VBLANK0 26 | ||
| 443 | #define SYNCPT_VBLANK1 27 | ||
| 444 | |||
| 445 | #endif /* TEGRA_DC_H */ | 444 | #endif /* TEGRA_DC_H */ |
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c index 5f1880766110..1833abd7d3aa 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c | |||
| @@ -172,6 +172,10 @@ static int tegra_drm_load(struct drm_device *drm, unsigned long flags) | |||
| 172 | */ | 172 | */ |
| 173 | drm->irq_enabled = true; | 173 | drm->irq_enabled = true; |
| 174 | 174 | ||
| 175 | /* syncpoints are used for full 32-bit hardware VBLANK counters */ | ||
| 176 | drm->vblank_disable_immediate = true; | ||
| 177 | drm->max_vblank_count = 0xffffffff; | ||
| 178 | |||
| 175 | err = drm_vblank_init(drm, drm->mode_config.num_crtc); | 179 | err = drm_vblank_init(drm, drm->mode_config.num_crtc); |
| 176 | if (err < 0) | 180 | if (err < 0) |
| 177 | goto device; | 181 | goto device; |
| @@ -813,12 +817,12 @@ static struct drm_crtc *tegra_crtc_from_pipe(struct drm_device *drm, | |||
| 813 | static u32 tegra_drm_get_vblank_counter(struct drm_device *drm, int pipe) | 817 | static u32 tegra_drm_get_vblank_counter(struct drm_device *drm, int pipe) |
| 814 | { | 818 | { |
| 815 | struct drm_crtc *crtc = tegra_crtc_from_pipe(drm, pipe); | 819 | struct drm_crtc *crtc = tegra_crtc_from_pipe(drm, pipe); |
| 820 | struct tegra_dc *dc = to_tegra_dc(crtc); | ||
| 816 | 821 | ||
| 817 | if (!crtc) | 822 | if (!crtc) |
| 818 | return 0; | 823 | return 0; |
| 819 | 824 | ||
| 820 | /* TODO: implement real hardware counter using syncpoints */ | 825 | return tegra_dc_get_vblank_counter(dc); |
| 821 | return drm_crtc_vblank_count(crtc); | ||
| 822 | } | 826 | } |
| 823 | 827 | ||
| 824 | static int tegra_drm_enable_vblank(struct drm_device *drm, int pipe) | 828 | static int tegra_drm_enable_vblank(struct drm_device *drm, int pipe) |
| @@ -879,8 +883,18 @@ static int tegra_debugfs_framebuffers(struct seq_file *s, void *data) | |||
| 879 | return 0; | 883 | return 0; |
| 880 | } | 884 | } |
| 881 | 885 | ||
| 886 | static int tegra_debugfs_iova(struct seq_file *s, void *data) | ||
| 887 | { | ||
| 888 | struct drm_info_node *node = (struct drm_info_node *)s->private; | ||
| 889 | struct drm_device *drm = node->minor->dev; | ||
| 890 | struct tegra_drm *tegra = drm->dev_private; | ||
| 891 | |||
| 892 | return drm_mm_dump_table(s, &tegra->mm); | ||
| 893 | } | ||
| 894 | |||
| 882 | static struct drm_info_list tegra_debugfs_list[] = { | 895 | static struct drm_info_list tegra_debugfs_list[] = { |
| 883 | { "framebuffers", tegra_debugfs_framebuffers, 0 }, | 896 | { "framebuffers", tegra_debugfs_framebuffers, 0 }, |
| 897 | { "iova", tegra_debugfs_iova, 0 }, | ||
| 884 | }; | 898 | }; |
| 885 | 899 | ||
| 886 | static int tegra_debugfs_init(struct drm_minor *minor) | 900 | static int tegra_debugfs_init(struct drm_minor *minor) |
diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h index 8cb2dfeaa957..659b2fcc986d 100644 --- a/drivers/gpu/drm/tegra/drm.h +++ b/drivers/gpu/drm/tegra/drm.h | |||
| @@ -106,6 +106,7 @@ struct tegra_output; | |||
| 106 | 106 | ||
| 107 | struct tegra_dc { | 107 | struct tegra_dc { |
| 108 | struct host1x_client client; | 108 | struct host1x_client client; |
| 109 | struct host1x_syncpt *syncpt; | ||
| 109 | struct device *dev; | 110 | struct device *dev; |
| 110 | spinlock_t lock; | 111 | spinlock_t lock; |
| 111 | 112 | ||
| @@ -180,12 +181,11 @@ struct tegra_dc_window { | |||
| 180 | }; | 181 | }; |
| 181 | 182 | ||
| 182 | /* from dc.c */ | 183 | /* from dc.c */ |
| 184 | u32 tegra_dc_get_vblank_counter(struct tegra_dc *dc); | ||
| 183 | void tegra_dc_enable_vblank(struct tegra_dc *dc); | 185 | void tegra_dc_enable_vblank(struct tegra_dc *dc); |
| 184 | void tegra_dc_disable_vblank(struct tegra_dc *dc); | 186 | void tegra_dc_disable_vblank(struct tegra_dc *dc); |
| 185 | void tegra_dc_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file); | 187 | void tegra_dc_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file); |
| 186 | void tegra_dc_commit(struct tegra_dc *dc); | 188 | void tegra_dc_commit(struct tegra_dc *dc); |
| 187 | int tegra_dc_setup_clock(struct tegra_dc *dc, struct clk *parent, | ||
| 188 | unsigned long pclk, unsigned int div); | ||
| 189 | int tegra_dc_state_setup_clock(struct tegra_dc *dc, | 189 | int tegra_dc_state_setup_clock(struct tegra_dc *dc, |
| 190 | struct drm_crtc_state *crtc_state, | 190 | struct drm_crtc_state *crtc_state, |
| 191 | struct clk *clk, unsigned long pclk, | 191 | struct clk *clk, unsigned long pclk, |
diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c index 7eaaee74a039..06ab1783bba1 100644 --- a/drivers/gpu/drm/tegra/hdmi.c +++ b/drivers/gpu/drm/tegra/hdmi.c | |||
| @@ -952,7 +952,7 @@ static void tegra_hdmi_encoder_mode_set(struct drm_encoder *encoder, | |||
| 952 | } | 952 | } |
| 953 | 953 | ||
| 954 | tegra_hdmi_writel(hdmi, | 954 | tegra_hdmi_writel(hdmi, |
| 955 | SOR_SEQ_CTL_PU_PC(0) | | 955 | SOR_SEQ_PU_PC(0) | |
| 956 | SOR_SEQ_PU_PC_ALT(0) | | 956 | SOR_SEQ_PU_PC_ALT(0) | |
| 957 | SOR_SEQ_PD_PC(8) | | 957 | SOR_SEQ_PD_PC(8) | |
| 958 | SOR_SEQ_PD_PC_ALT(8), | 958 | SOR_SEQ_PD_PC_ALT(8), |
| @@ -1394,8 +1394,8 @@ static int tegra_hdmi_exit(struct host1x_client *client) | |||
| 1394 | 1394 | ||
| 1395 | tegra_output_exit(&hdmi->output); | 1395 | tegra_output_exit(&hdmi->output); |
| 1396 | 1396 | ||
| 1397 | clk_disable_unprepare(hdmi->clk); | ||
| 1398 | reset_control_assert(hdmi->rst); | 1397 | reset_control_assert(hdmi->rst); |
| 1398 | clk_disable_unprepare(hdmi->clk); | ||
| 1399 | 1399 | ||
| 1400 | regulator_disable(hdmi->vdd); | 1400 | regulator_disable(hdmi->vdd); |
| 1401 | regulator_disable(hdmi->pll); | 1401 | regulator_disable(hdmi->pll); |
diff --git a/drivers/gpu/drm/tegra/hdmi.h b/drivers/gpu/drm/tegra/hdmi.h index 919a19df4e1b..a882514389cd 100644 --- a/drivers/gpu/drm/tegra/hdmi.h +++ b/drivers/gpu/drm/tegra/hdmi.h | |||
| @@ -201,7 +201,7 @@ | |||
| 201 | #define HDMI_NV_PDISP_SOR_CRCB 0x5d | 201 | #define HDMI_NV_PDISP_SOR_CRCB 0x5d |
| 202 | #define HDMI_NV_PDISP_SOR_BLANK 0x5e | 202 | #define HDMI_NV_PDISP_SOR_BLANK 0x5e |
| 203 | #define HDMI_NV_PDISP_SOR_SEQ_CTL 0x5f | 203 | #define HDMI_NV_PDISP_SOR_SEQ_CTL 0x5f |
| 204 | #define SOR_SEQ_CTL_PU_PC(x) (((x) & 0xf) << 0) | 204 | #define SOR_SEQ_PU_PC(x) (((x) & 0xf) << 0) |
| 205 | #define SOR_SEQ_PU_PC_ALT(x) (((x) & 0xf) << 4) | 205 | #define SOR_SEQ_PU_PC_ALT(x) (((x) & 0xf) << 4) |
| 206 | #define SOR_SEQ_PD_PC(x) (((x) & 0xf) << 8) | 206 | #define SOR_SEQ_PD_PC(x) (((x) & 0xf) << 8) |
| 207 | #define SOR_SEQ_PD_PC_ALT(x) (((x) & 0xf) << 12) | 207 | #define SOR_SEQ_PD_PC_ALT(x) (((x) & 0xf) << 12) |
diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c index 2afe478ded3b..7591d8901f9a 100644 --- a/drivers/gpu/drm/tegra/sor.c +++ b/drivers/gpu/drm/tegra/sor.c | |||
| @@ -41,6 +41,8 @@ struct tegra_sor { | |||
| 41 | struct mutex lock; | 41 | struct mutex lock; |
| 42 | bool enabled; | 42 | bool enabled; |
| 43 | 43 | ||
| 44 | struct drm_info_list *debugfs_files; | ||
| 45 | struct drm_minor *minor; | ||
| 44 | struct dentry *debugfs; | 46 | struct dentry *debugfs; |
| 45 | }; | 47 | }; |
| 46 | 48 | ||
| @@ -68,13 +70,12 @@ static inline struct tegra_sor *to_sor(struct tegra_output *output) | |||
| 68 | return container_of(output, struct tegra_sor, output); | 70 | return container_of(output, struct tegra_sor, output); |
| 69 | } | 71 | } |
| 70 | 72 | ||
| 71 | static inline unsigned long tegra_sor_readl(struct tegra_sor *sor, | 73 | static inline u32 tegra_sor_readl(struct tegra_sor *sor, unsigned long offset) |
| 72 | unsigned long offset) | ||
| 73 | { | 74 | { |
| 74 | return readl(sor->regs + (offset << 2)); | 75 | return readl(sor->regs + (offset << 2)); |
| 75 | } | 76 | } |
| 76 | 77 | ||
| 77 | static inline void tegra_sor_writel(struct tegra_sor *sor, unsigned long value, | 78 | static inline void tegra_sor_writel(struct tegra_sor *sor, u32 value, |
| 78 | unsigned long offset) | 79 | unsigned long offset) |
| 79 | { | 80 | { |
| 80 | writel(value, sor->regs + (offset << 2)); | 81 | writel(value, sor->regs + (offset << 2)); |
| @@ -83,9 +84,9 @@ static inline void tegra_sor_writel(struct tegra_sor *sor, unsigned long value, | |||
| 83 | static int tegra_sor_dp_train_fast(struct tegra_sor *sor, | 84 | static int tegra_sor_dp_train_fast(struct tegra_sor *sor, |
| 84 | struct drm_dp_link *link) | 85 | struct drm_dp_link *link) |
| 85 | { | 86 | { |
| 86 | unsigned long value; | ||
| 87 | unsigned int i; | 87 | unsigned int i; |
| 88 | u8 pattern; | 88 | u8 pattern; |
| 89 | u32 value; | ||
| 89 | int err; | 90 | int err; |
| 90 | 91 | ||
| 91 | /* setup lane parameters */ | 92 | /* setup lane parameters */ |
| @@ -202,7 +203,7 @@ static void tegra_sor_update(struct tegra_sor *sor) | |||
| 202 | 203 | ||
| 203 | static int tegra_sor_setup_pwm(struct tegra_sor *sor, unsigned long timeout) | 204 | static int tegra_sor_setup_pwm(struct tegra_sor *sor, unsigned long timeout) |
| 204 | { | 205 | { |
| 205 | unsigned long value; | 206 | u32 value; |
| 206 | 207 | ||
| 207 | value = tegra_sor_readl(sor, SOR_PWM_DIV); | 208 | value = tegra_sor_readl(sor, SOR_PWM_DIV); |
| 208 | value &= ~SOR_PWM_DIV_MASK; | 209 | value &= ~SOR_PWM_DIV_MASK; |
| @@ -281,7 +282,7 @@ static int tegra_sor_wakeup(struct tegra_sor *sor) | |||
| 281 | 282 | ||
| 282 | static int tegra_sor_power_up(struct tegra_sor *sor, unsigned long timeout) | 283 | static int tegra_sor_power_up(struct tegra_sor *sor, unsigned long timeout) |
| 283 | { | 284 | { |
| 284 | unsigned long value; | 285 | u32 value; |
| 285 | 286 | ||
| 286 | value = tegra_sor_readl(sor, SOR_PWR); | 287 | value = tegra_sor_readl(sor, SOR_PWR); |
| 287 | value |= SOR_PWR_TRIGGER | SOR_PWR_NORMAL_STATE_PU; | 288 | value |= SOR_PWR_TRIGGER | SOR_PWR_NORMAL_STATE_PU; |
| @@ -674,38 +675,195 @@ static const struct file_operations tegra_sor_crc_fops = { | |||
| 674 | .release = tegra_sor_crc_release, | 675 | .release = tegra_sor_crc_release, |
| 675 | }; | 676 | }; |
| 676 | 677 | ||
| 678 | static int tegra_sor_show_regs(struct seq_file *s, void *data) | ||
| 679 | { | ||
| 680 | struct drm_info_node *node = s->private; | ||
| 681 | struct tegra_sor *sor = node->info_ent->data; | ||
| 682 | |||
| 683 | #define DUMP_REG(name) \ | ||
| 684 | seq_printf(s, "%-38s %#05x %08x\n", #name, name, \ | ||
| 685 | tegra_sor_readl(sor, name)) | ||
| 686 | |||
| 687 | DUMP_REG(SOR_CTXSW); | ||
| 688 | DUMP_REG(SOR_SUPER_STATE_0); | ||
| 689 | DUMP_REG(SOR_SUPER_STATE_1); | ||
| 690 | DUMP_REG(SOR_STATE_0); | ||
| 691 | DUMP_REG(SOR_STATE_1); | ||
| 692 | DUMP_REG(SOR_HEAD_STATE_0(0)); | ||
| 693 | DUMP_REG(SOR_HEAD_STATE_0(1)); | ||
| 694 | DUMP_REG(SOR_HEAD_STATE_1(0)); | ||
| 695 | DUMP_REG(SOR_HEAD_STATE_1(1)); | ||
| 696 | DUMP_REG(SOR_HEAD_STATE_2(0)); | ||
| 697 | DUMP_REG(SOR_HEAD_STATE_2(1)); | ||
| 698 | DUMP_REG(SOR_HEAD_STATE_3(0)); | ||
| 699 | DUMP_REG(SOR_HEAD_STATE_3(1)); | ||
| 700 | DUMP_REG(SOR_HEAD_STATE_4(0)); | ||
| 701 | DUMP_REG(SOR_HEAD_STATE_4(1)); | ||
| 702 | DUMP_REG(SOR_HEAD_STATE_5(0)); | ||
| 703 | DUMP_REG(SOR_HEAD_STATE_5(1)); | ||
| 704 | DUMP_REG(SOR_CRC_CNTRL); | ||
| 705 | DUMP_REG(SOR_DP_DEBUG_MVID); | ||
| 706 | DUMP_REG(SOR_CLK_CNTRL); | ||
| 707 | DUMP_REG(SOR_CAP); | ||
| 708 | DUMP_REG(SOR_PWR); | ||
| 709 | DUMP_REG(SOR_TEST); | ||
| 710 | DUMP_REG(SOR_PLL_0); | ||
| 711 | DUMP_REG(SOR_PLL_1); | ||
| 712 | DUMP_REG(SOR_PLL_2); | ||
| 713 | DUMP_REG(SOR_PLL_3); | ||
| 714 | DUMP_REG(SOR_CSTM); | ||
| 715 | DUMP_REG(SOR_LVDS); | ||
| 716 | DUMP_REG(SOR_CRC_A); | ||
| 717 | DUMP_REG(SOR_CRC_B); | ||
| 718 | DUMP_REG(SOR_BLANK); | ||
| 719 | DUMP_REG(SOR_SEQ_CTL); | ||
| 720 | DUMP_REG(SOR_LANE_SEQ_CTL); | ||
| 721 | DUMP_REG(SOR_SEQ_INST(0)); | ||
| 722 | DUMP_REG(SOR_SEQ_INST(1)); | ||
| 723 | DUMP_REG(SOR_SEQ_INST(2)); | ||
| 724 | DUMP_REG(SOR_SEQ_INST(3)); | ||
| 725 | DUMP_REG(SOR_SEQ_INST(4)); | ||
| 726 | DUMP_REG(SOR_SEQ_INST(5)); | ||
| 727 | DUMP_REG(SOR_SEQ_INST(6)); | ||
| 728 | DUMP_REG(SOR_SEQ_INST(7)); | ||
| 729 | DUMP_REG(SOR_SEQ_INST(8)); | ||
| 730 | DUMP_REG(SOR_SEQ_INST(9)); | ||
| 731 | DUMP_REG(SOR_SEQ_INST(10)); | ||
| 732 | DUMP_REG(SOR_SEQ_INST(11)); | ||
| 733 | DUMP_REG(SOR_SEQ_INST(12)); | ||
| 734 | DUMP_REG(SOR_SEQ_INST(13)); | ||
| 735 | DUMP_REG(SOR_SEQ_INST(14)); | ||
| 736 | DUMP_REG(SOR_SEQ_INST(15)); | ||
| 737 | DUMP_REG(SOR_PWM_DIV); | ||
| 738 | DUMP_REG(SOR_PWM_CTL); | ||
| 739 | DUMP_REG(SOR_VCRC_A_0); | ||
| 740 | DUMP_REG(SOR_VCRC_A_1); | ||
| 741 | DUMP_REG(SOR_VCRC_B_0); | ||
| 742 | DUMP_REG(SOR_VCRC_B_1); | ||
| 743 | DUMP_REG(SOR_CCRC_A_0); | ||
| 744 | DUMP_REG(SOR_CCRC_A_1); | ||
| 745 | DUMP_REG(SOR_CCRC_B_0); | ||
| 746 | DUMP_REG(SOR_CCRC_B_1); | ||
| 747 | DUMP_REG(SOR_EDATA_A_0); | ||
| 748 | DUMP_REG(SOR_EDATA_A_1); | ||
| 749 | DUMP_REG(SOR_EDATA_B_0); | ||
| 750 | DUMP_REG(SOR_EDATA_B_1); | ||
| 751 | DUMP_REG(SOR_COUNT_A_0); | ||
| 752 | DUMP_REG(SOR_COUNT_A_1); | ||
| 753 | DUMP_REG(SOR_COUNT_B_0); | ||
| 754 | DUMP_REG(SOR_COUNT_B_1); | ||
| 755 | DUMP_REG(SOR_DEBUG_A_0); | ||
| 756 | DUMP_REG(SOR_DEBUG_A_1); | ||
| 757 | DUMP_REG(SOR_DEBUG_B_0); | ||
| 758 | DUMP_REG(SOR_DEBUG_B_1); | ||
| 759 | DUMP_REG(SOR_TRIG); | ||
| 760 | DUMP_REG(SOR_MSCHECK); | ||
| 761 | DUMP_REG(SOR_XBAR_CTRL); | ||
| 762 | DUMP_REG(SOR_XBAR_POL); | ||
| 763 | DUMP_REG(SOR_DP_LINKCTL_0); | ||
| 764 | DUMP_REG(SOR_DP_LINKCTL_1); | ||
| 765 | DUMP_REG(SOR_LANE_DRIVE_CURRENT_0); | ||
| 766 | DUMP_REG(SOR_LANE_DRIVE_CURRENT_1); | ||
| 767 | DUMP_REG(SOR_LANE4_DRIVE_CURRENT_0); | ||
| 768 | DUMP_REG(SOR_LANE4_DRIVE_CURRENT_1); | ||
| 769 | DUMP_REG(SOR_LANE_PREEMPHASIS_0); | ||
| 770 | DUMP_REG(SOR_LANE_PREEMPHASIS_1); | ||
| 771 | DUMP_REG(SOR_LANE4_PREEMPHASIS_0); | ||
| 772 | DUMP_REG(SOR_LANE4_PREEMPHASIS_1); | ||
| 773 | DUMP_REG(SOR_LANE_POST_CURSOR_0); | ||
| 774 | DUMP_REG(SOR_LANE_POST_CURSOR_1); | ||
| 775 | DUMP_REG(SOR_DP_CONFIG_0); | ||
| 776 | DUMP_REG(SOR_DP_CONFIG_1); | ||
| 777 | DUMP_REG(SOR_DP_MN_0); | ||
| 778 | DUMP_REG(SOR_DP_MN_1); | ||
| 779 | DUMP_REG(SOR_DP_PADCTL_0); | ||
| 780 | DUMP_REG(SOR_DP_PADCTL_1); | ||
| 781 | DUMP_REG(SOR_DP_DEBUG_0); | ||
| 782 | DUMP_REG(SOR_DP_DEBUG_1); | ||
| 783 | DUMP_REG(SOR_DP_SPARE_0); | ||
| 784 | DUMP_REG(SOR_DP_SPARE_1); | ||
| 785 | DUMP_REG(SOR_DP_AUDIO_CTRL); | ||
| 786 | DUMP_REG(SOR_DP_AUDIO_HBLANK_SYMBOLS); | ||
| 787 | DUMP_REG(SOR_DP_AUDIO_VBLANK_SYMBOLS); | ||
| 788 | DUMP_REG(SOR_DP_GENERIC_INFOFRAME_HEADER); | ||
| 789 | DUMP_REG(SOR_DP_GENERIC_INFOFRAME_SUBPACK_0); | ||
| 790 | DUMP_REG(SOR_DP_GENERIC_INFOFRAME_SUBPACK_1); | ||
| 791 | DUMP_REG(SOR_DP_GENERIC_INFOFRAME_SUBPACK_2); | ||
| 792 | DUMP_REG(SOR_DP_GENERIC_INFOFRAME_SUBPACK_3); | ||
| 793 | DUMP_REG(SOR_DP_GENERIC_INFOFRAME_SUBPACK_4); | ||
| 794 | DUMP_REG(SOR_DP_GENERIC_INFOFRAME_SUBPACK_5); | ||
| 795 | DUMP_REG(SOR_DP_GENERIC_INFOFRAME_SUBPACK_6); | ||
| 796 | DUMP_REG(SOR_DP_TPG); | ||
| 797 | DUMP_REG(SOR_DP_TPG_CONFIG); | ||
| 798 | DUMP_REG(SOR_DP_LQ_CSTM_0); | ||
| 799 | DUMP_REG(SOR_DP_LQ_CSTM_1); | ||
| 800 | DUMP_REG(SOR_DP_LQ_CSTM_2); | ||
| 801 | |||
| 802 | #undef DUMP_REG | ||
| 803 | |||
| 804 | return 0; | ||
| 805 | } | ||
| 806 | |||
| 807 | static const struct drm_info_list debugfs_files[] = { | ||
| 808 | { "regs", tegra_sor_show_regs, 0, NULL }, | ||
| 809 | }; | ||
| 810 | |||
| 677 | static int tegra_sor_debugfs_init(struct tegra_sor *sor, | 811 | static int tegra_sor_debugfs_init(struct tegra_sor *sor, |
| 678 | struct drm_minor *minor) | 812 | struct drm_minor *minor) |
| 679 | { | 813 | { |
| 680 | struct dentry *entry; | 814 | struct dentry *entry; |
| 815 | unsigned int i; | ||
| 681 | int err = 0; | 816 | int err = 0; |
| 682 | 817 | ||
| 683 | sor->debugfs = debugfs_create_dir("sor", minor->debugfs_root); | 818 | sor->debugfs = debugfs_create_dir("sor", minor->debugfs_root); |
| 684 | if (!sor->debugfs) | 819 | if (!sor->debugfs) |
| 685 | return -ENOMEM; | 820 | return -ENOMEM; |
| 686 | 821 | ||
| 822 | sor->debugfs_files = kmemdup(debugfs_files, sizeof(debugfs_files), | ||
| 823 | GFP_KERNEL); | ||
| 824 | if (!sor->debugfs_files) { | ||
| 825 | err = -ENOMEM; | ||
| 826 | goto remove; | ||
| 827 | } | ||
| 828 | |||
| 829 | for (i = 0; i < ARRAY_SIZE(debugfs_files); i++) | ||
| 830 | sor->debugfs_files[i].data = sor; | ||
| 831 | |||
| 832 | err = drm_debugfs_create_files(sor->debugfs_files, | ||
| 833 | ARRAY_SIZE(debugfs_files), | ||
| 834 | sor->debugfs, minor); | ||
| 835 | if (err < 0) | ||
| 836 | goto free; | ||
| 837 | |||
| 687 | entry = debugfs_create_file("crc", 0644, sor->debugfs, sor, | 838 | entry = debugfs_create_file("crc", 0644, sor->debugfs, sor, |
| 688 | &tegra_sor_crc_fops); | 839 | &tegra_sor_crc_fops); |
| 689 | if (!entry) { | 840 | if (!entry) { |
| 690 | dev_err(sor->dev, | ||
| 691 | "cannot create /sys/kernel/debug/dri/%s/sor/crc\n", | ||
| 692 | minor->debugfs_root->d_name.name); | ||
| 693 | err = -ENOMEM; | 841 | err = -ENOMEM; |
| 694 | goto remove; | 842 | goto free; |
| 695 | } | 843 | } |
| 696 | 844 | ||
| 697 | return err; | 845 | return err; |
| 698 | 846 | ||
| 847 | free: | ||
| 848 | kfree(sor->debugfs_files); | ||
| 849 | sor->debugfs_files = NULL; | ||
| 699 | remove: | 850 | remove: |
| 700 | debugfs_remove(sor->debugfs); | 851 | debugfs_remove_recursive(sor->debugfs); |
| 701 | sor->debugfs = NULL; | 852 | sor->debugfs = NULL; |
| 702 | return err; | 853 | return err; |
| 703 | } | 854 | } |
| 704 | 855 | ||
| 705 | static void tegra_sor_debugfs_exit(struct tegra_sor *sor) | 856 | static void tegra_sor_debugfs_exit(struct tegra_sor *sor) |
| 706 | { | 857 | { |
| 707 | debugfs_remove_recursive(sor->debugfs); | 858 | drm_debugfs_remove_files(sor->debugfs_files, ARRAY_SIZE(debugfs_files), |
| 859 | sor->minor); | ||
| 860 | sor->minor = NULL; | ||
| 861 | |||
| 862 | kfree(sor->debugfs_files); | ||
| 708 | sor->debugfs = NULL; | 863 | sor->debugfs = NULL; |
| 864 | |||
| 865 | debugfs_remove_recursive(sor->debugfs); | ||
| 866 | sor->debugfs_files = NULL; | ||
| 709 | } | 867 | } |
| 710 | 868 | ||
| 711 | static void tegra_sor_connector_dpms(struct drm_connector *connector, int mode) | 869 | static void tegra_sor_connector_dpms(struct drm_connector *connector, int mode) |
| @@ -791,8 +949,8 @@ static void tegra_sor_encoder_mode_set(struct drm_encoder *encoder, | |||
| 791 | struct tegra_sor_config config; | 949 | struct tegra_sor_config config; |
| 792 | struct drm_dp_link link; | 950 | struct drm_dp_link link; |
| 793 | struct drm_dp_aux *aux; | 951 | struct drm_dp_aux *aux; |
| 794 | unsigned long value; | ||
| 795 | int err = 0; | 952 | int err = 0; |
| 953 | u32 value; | ||
| 796 | 954 | ||
| 797 | mutex_lock(&sor->lock); | 955 | mutex_lock(&sor->lock); |
| 798 | 956 | ||
| @@ -1354,12 +1512,30 @@ static int tegra_sor_init(struct host1x_client *client) | |||
| 1354 | } | 1512 | } |
| 1355 | } | 1513 | } |
| 1356 | 1514 | ||
| 1515 | /* | ||
| 1516 | * XXX: Remove this reset once proper hand-over from firmware to | ||
| 1517 | * kernel is possible. | ||
| 1518 | */ | ||
| 1519 | err = reset_control_assert(sor->rst); | ||
| 1520 | if (err < 0) { | ||
| 1521 | dev_err(sor->dev, "failed to assert SOR reset: %d\n", err); | ||
| 1522 | return err; | ||
| 1523 | } | ||
| 1524 | |||
| 1357 | err = clk_prepare_enable(sor->clk); | 1525 | err = clk_prepare_enable(sor->clk); |
| 1358 | if (err < 0) { | 1526 | if (err < 0) { |
| 1359 | dev_err(sor->dev, "failed to enable clock: %d\n", err); | 1527 | dev_err(sor->dev, "failed to enable clock: %d\n", err); |
| 1360 | return err; | 1528 | return err; |
| 1361 | } | 1529 | } |
| 1362 | 1530 | ||
| 1531 | usleep_range(1000, 3000); | ||
| 1532 | |||
| 1533 | err = reset_control_deassert(sor->rst); | ||
| 1534 | if (err < 0) { | ||
| 1535 | dev_err(sor->dev, "failed to deassert SOR reset: %d\n", err); | ||
| 1536 | return err; | ||
| 1537 | } | ||
| 1538 | |||
| 1363 | err = clk_prepare_enable(sor->clk_safe); | 1539 | err = clk_prepare_enable(sor->clk_safe); |
| 1364 | if (err < 0) | 1540 | if (err < 0) |
| 1365 | return err; | 1541 | return err; |
diff --git a/drivers/gpu/host1x/syncpt.c b/drivers/gpu/host1x/syncpt.c index b10550ee1d89..6b7fdc1e2ed0 100644 --- a/drivers/gpu/host1x/syncpt.c +++ b/drivers/gpu/host1x/syncpt.c | |||
| @@ -425,6 +425,12 @@ u32 host1x_syncpt_read_min(struct host1x_syncpt *sp) | |||
| 425 | } | 425 | } |
| 426 | EXPORT_SYMBOL(host1x_syncpt_read_min); | 426 | EXPORT_SYMBOL(host1x_syncpt_read_min); |
| 427 | 427 | ||
| 428 | u32 host1x_syncpt_read(struct host1x_syncpt *sp) | ||
| 429 | { | ||
| 430 | return host1x_syncpt_load(sp); | ||
| 431 | } | ||
| 432 | EXPORT_SYMBOL(host1x_syncpt_read); | ||
| 433 | |||
| 428 | int host1x_syncpt_nb_pts(struct host1x *host) | 434 | int host1x_syncpt_nb_pts(struct host1x *host) |
| 429 | { | 435 | { |
| 430 | return host->info->nb_pts; | 436 | return host->info->nb_pts; |
diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h index 829280b56874..d665781eb542 100644 --- a/include/drm/drm_atomic_helper.h +++ b/include/drm/drm_atomic_helper.h | |||
| @@ -87,20 +87,34 @@ void drm_atomic_helper_connector_dpms(struct drm_connector *connector, | |||
| 87 | 87 | ||
| 88 | /* default implementations for state handling */ | 88 | /* default implementations for state handling */ |
| 89 | void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc); | 89 | void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc); |
| 90 | void __drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc, | ||
| 91 | struct drm_crtc_state *state); | ||
| 90 | struct drm_crtc_state * | 92 | struct drm_crtc_state * |
| 91 | drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc); | 93 | drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc); |
| 94 | void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc, | ||
| 95 | struct drm_crtc_state *state); | ||
| 92 | void drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc, | 96 | void drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc, |
| 93 | struct drm_crtc_state *state); | 97 | struct drm_crtc_state *state); |
| 94 | 98 | ||
| 95 | void drm_atomic_helper_plane_reset(struct drm_plane *plane); | 99 | void drm_atomic_helper_plane_reset(struct drm_plane *plane); |
| 100 | void __drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane, | ||
| 101 | struct drm_plane_state *state); | ||
| 96 | struct drm_plane_state * | 102 | struct drm_plane_state * |
| 97 | drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane); | 103 | drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane); |
| 104 | void __drm_atomic_helper_plane_destroy_state(struct drm_plane *plane, | ||
| 105 | struct drm_plane_state *state); | ||
| 98 | void drm_atomic_helper_plane_destroy_state(struct drm_plane *plane, | 106 | void drm_atomic_helper_plane_destroy_state(struct drm_plane *plane, |
| 99 | struct drm_plane_state *state); | 107 | struct drm_plane_state *state); |
| 100 | 108 | ||
| 101 | void drm_atomic_helper_connector_reset(struct drm_connector *connector); | 109 | void drm_atomic_helper_connector_reset(struct drm_connector *connector); |
| 110 | void | ||
| 111 | __drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector, | ||
| 112 | struct drm_connector_state *state); | ||
| 102 | struct drm_connector_state * | 113 | struct drm_connector_state * |
| 103 | drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector); | 114 | drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector); |
| 115 | void | ||
| 116 | __drm_atomic_helper_connector_destroy_state(struct drm_connector *connector, | ||
| 117 | struct drm_connector_state *state); | ||
| 104 | void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector, | 118 | void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector, |
| 105 | struct drm_connector_state *state); | 119 | struct drm_connector_state *state); |
| 106 | 120 | ||
diff --git a/include/linux/host1x.h b/include/linux/host1x.h index 464f33814a94..d2ba7d334039 100644 --- a/include/linux/host1x.h +++ b/include/linux/host1x.h | |||
| @@ -135,6 +135,7 @@ struct host1x_syncpt *host1x_syncpt_get(struct host1x *host, u32 id); | |||
| 135 | u32 host1x_syncpt_id(struct host1x_syncpt *sp); | 135 | u32 host1x_syncpt_id(struct host1x_syncpt *sp); |
| 136 | u32 host1x_syncpt_read_min(struct host1x_syncpt *sp); | 136 | u32 host1x_syncpt_read_min(struct host1x_syncpt *sp); |
| 137 | u32 host1x_syncpt_read_max(struct host1x_syncpt *sp); | 137 | u32 host1x_syncpt_read_max(struct host1x_syncpt *sp); |
| 138 | u32 host1x_syncpt_read(struct host1x_syncpt *sp); | ||
| 138 | int host1x_syncpt_incr(struct host1x_syncpt *sp); | 139 | int host1x_syncpt_incr(struct host1x_syncpt *sp); |
| 139 | u32 host1x_syncpt_incr_max(struct host1x_syncpt *sp, u32 incrs); | 140 | u32 host1x_syncpt_incr_max(struct host1x_syncpt *sp, u32 incrs); |
| 140 | int host1x_syncpt_wait(struct host1x_syncpt *sp, u32 thresh, long timeout, | 141 | int host1x_syncpt_wait(struct host1x_syncpt *sp, u32 thresh, long timeout, |
diff --git a/include/uapi/drm/tegra_drm.h b/include/uapi/drm/tegra_drm.h index c15d781ecc0f..5391780c2b05 100644 --- a/include/uapi/drm/tegra_drm.h +++ b/include/uapi/drm/tegra_drm.h | |||
| @@ -36,7 +36,8 @@ struct drm_tegra_gem_create { | |||
| 36 | 36 | ||
| 37 | struct drm_tegra_gem_mmap { | 37 | struct drm_tegra_gem_mmap { |
| 38 | __u32 handle; | 38 | __u32 handle; |
| 39 | __u32 offset; | 39 | __u32 pad; |
| 40 | __u64 offset; | ||
| 40 | }; | 41 | }; |
| 41 | 42 | ||
| 42 | struct drm_tegra_syncpt_read { | 43 | struct drm_tegra_syncpt_read { |
