diff options
author | Dave Airlie <airlied@redhat.com> | 2016-07-15 21:23:50 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2016-07-15 21:23:50 -0400 |
commit | 877fa9a42ddc087dc46a3a3aac18db8adde2bdf1 (patch) | |
tree | c5189830c8d3fed08e92deda8681f0676aaea8a5 /drivers/gpu/host1x/syncpt.c | |
parent | e2b80bac213cdfd443df9b6e1c769f98d0553c0c (diff) | |
parent | 64ea25c3bc86c05c7da6c683b86663f4c90158d6 (diff) |
Merge tag 'drm/tegra/for-4.8-rc1' of git://anongit.freedesktop.org/tegra/linux into drm-next
drm/tegra: Changes for v4.8-rc1
This set of changes contains a bunch of cleanups to the host1x driver as
well as the addition of a pin controller for DPAUX, which is required by
boards to configure the DPAUX pads in AUX mode (for DisplayPort) or I2C
mode (for HDMI and DDC).
Included is also a bit of rework of the SOR driver in preparation to add
DisplayPort support as well as some refactoring and cleanup.
Finally, all output drivers are converted to runtime PM, which greatly
simplifies the handling of clocks and resets.
* tag 'drm/tegra/for-4.8-rc1' of git://anongit.freedesktop.org/tegra/linux: (35 commits)
drm/tegra: sor: Reject HDMI 2.0 modes
drm/tegra: sor: Prepare for generic PM domain support
drm/tegra: dsi: Prepare for generic PM domain support
drm/tegra: sor: Make XBAR configurable per SoC
drm/tegra: sor: Use sor1_src clock to set parent for HDMI
dt-bindings: display: tegra: Add source clock for SOR
drm/tegra: sor: Implement sor1_brick clock
drm/tegra: sor: Implement runtime PM
drm/tegra: hdmi: Implement runtime PM
drm/tegra: dsi: Implement runtime PM
drm/tegra: dc: Implement runtime PM
drm/tegra: hdmi: Enable audio over HDMI
drm/tegra: sor: Do not support deep color modes
drm/tegra: sor: Extract tegra_sor_mode_set()
drm/tegra: sor: Split out tegra_sor_apply_config()
drm/tegra: sor: Rename tegra_sor_calc_config()
drm/tegra: sor: Factor out tegra_sor_set_parent_clock()
drm/tegra: dpaux: Add pinctrl support
dt-bindings: Add bindings for Tegra DPAUX pinctrl driver
drm/tegra: Prepare DPAUX for supporting generic PM domains
...
Diffstat (limited to 'drivers/gpu/host1x/syncpt.c')
-rw-r--r-- | drivers/gpu/host1x/syncpt.c | 58 |
1 files changed, 40 insertions, 18 deletions
diff --git a/drivers/gpu/host1x/syncpt.c b/drivers/gpu/host1x/syncpt.c index 6b7fdc1e2ed0..95589328ad52 100644 --- a/drivers/gpu/host1x/syncpt.c +++ b/drivers/gpu/host1x/syncpt.c | |||
@@ -73,7 +73,7 @@ static struct host1x_syncpt *host1x_syncpt_alloc(struct host1x *host, | |||
73 | return NULL; | 73 | return NULL; |
74 | } | 74 | } |
75 | 75 | ||
76 | name = kasprintf(GFP_KERNEL, "%02d-%s", sp->id, | 76 | name = kasprintf(GFP_KERNEL, "%02u-%s", sp->id, |
77 | dev ? dev_name(dev) : NULL); | 77 | dev ? dev_name(dev) : NULL); |
78 | if (!name) | 78 | if (!name) |
79 | return NULL; | 79 | return NULL; |
@@ -110,12 +110,14 @@ EXPORT_SYMBOL(host1x_syncpt_incr_max); | |||
110 | void host1x_syncpt_restore(struct host1x *host) | 110 | void host1x_syncpt_restore(struct host1x *host) |
111 | { | 111 | { |
112 | struct host1x_syncpt *sp_base = host->syncpt; | 112 | struct host1x_syncpt *sp_base = host->syncpt; |
113 | u32 i; | 113 | unsigned int i; |
114 | 114 | ||
115 | for (i = 0; i < host1x_syncpt_nb_pts(host); i++) | 115 | for (i = 0; i < host1x_syncpt_nb_pts(host); i++) |
116 | host1x_hw_syncpt_restore(host, sp_base + i); | 116 | host1x_hw_syncpt_restore(host, sp_base + i); |
117 | |||
117 | for (i = 0; i < host1x_syncpt_nb_bases(host); i++) | 118 | for (i = 0; i < host1x_syncpt_nb_bases(host); i++) |
118 | host1x_hw_syncpt_restore_wait_base(host, sp_base + i); | 119 | host1x_hw_syncpt_restore_wait_base(host, sp_base + i); |
120 | |||
119 | wmb(); | 121 | wmb(); |
120 | } | 122 | } |
121 | 123 | ||
@@ -126,7 +128,7 @@ void host1x_syncpt_restore(struct host1x *host) | |||
126 | void host1x_syncpt_save(struct host1x *host) | 128 | void host1x_syncpt_save(struct host1x *host) |
127 | { | 129 | { |
128 | struct host1x_syncpt *sp_base = host->syncpt; | 130 | struct host1x_syncpt *sp_base = host->syncpt; |
129 | u32 i; | 131 | unsigned int i; |
130 | 132 | ||
131 | for (i = 0; i < host1x_syncpt_nb_pts(host); i++) { | 133 | for (i = 0; i < host1x_syncpt_nb_pts(host); i++) { |
132 | if (host1x_syncpt_client_managed(sp_base + i)) | 134 | if (host1x_syncpt_client_managed(sp_base + i)) |
@@ -146,6 +148,7 @@ void host1x_syncpt_save(struct host1x *host) | |||
146 | u32 host1x_syncpt_load(struct host1x_syncpt *sp) | 148 | u32 host1x_syncpt_load(struct host1x_syncpt *sp) |
147 | { | 149 | { |
148 | u32 val; | 150 | u32 val; |
151 | |||
149 | val = host1x_hw_syncpt_load(sp->host, sp); | 152 | val = host1x_hw_syncpt_load(sp->host, sp); |
150 | trace_host1x_syncpt_load_min(sp->id, val); | 153 | trace_host1x_syncpt_load_min(sp->id, val); |
151 | 154 | ||
@@ -157,10 +160,9 @@ u32 host1x_syncpt_load(struct host1x_syncpt *sp) | |||
157 | */ | 160 | */ |
158 | u32 host1x_syncpt_load_wait_base(struct host1x_syncpt *sp) | 161 | u32 host1x_syncpt_load_wait_base(struct host1x_syncpt *sp) |
159 | { | 162 | { |
160 | u32 val; | ||
161 | host1x_hw_syncpt_load_wait_base(sp->host, sp); | 163 | host1x_hw_syncpt_load_wait_base(sp->host, sp); |
162 | val = sp->base_val; | 164 | |
163 | return val; | 165 | return sp->base_val; |
164 | } | 166 | } |
165 | 167 | ||
166 | /* | 168 | /* |
@@ -179,6 +181,7 @@ EXPORT_SYMBOL(host1x_syncpt_incr); | |||
179 | static bool syncpt_load_min_is_expired(struct host1x_syncpt *sp, u32 thresh) | 181 | static bool syncpt_load_min_is_expired(struct host1x_syncpt *sp, u32 thresh) |
180 | { | 182 | { |
181 | host1x_hw_syncpt_load(sp->host, sp); | 183 | host1x_hw_syncpt_load(sp->host, sp); |
184 | |||
182 | return host1x_syncpt_is_expired(sp, thresh); | 185 | return host1x_syncpt_is_expired(sp, thresh); |
183 | } | 186 | } |
184 | 187 | ||
@@ -186,7 +189,7 @@ static bool syncpt_load_min_is_expired(struct host1x_syncpt *sp, u32 thresh) | |||
186 | * Main entrypoint for syncpoint value waits. | 189 | * Main entrypoint for syncpoint value waits. |
187 | */ | 190 | */ |
188 | int host1x_syncpt_wait(struct host1x_syncpt *sp, u32 thresh, long timeout, | 191 | int host1x_syncpt_wait(struct host1x_syncpt *sp, u32 thresh, long timeout, |
189 | u32 *value) | 192 | u32 *value) |
190 | { | 193 | { |
191 | DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq); | 194 | DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq); |
192 | void *ref; | 195 | void *ref; |
@@ -201,6 +204,7 @@ int host1x_syncpt_wait(struct host1x_syncpt *sp, u32 thresh, long timeout, | |||
201 | if (host1x_syncpt_is_expired(sp, thresh)) { | 204 | if (host1x_syncpt_is_expired(sp, thresh)) { |
202 | if (value) | 205 | if (value) |
203 | *value = host1x_syncpt_load(sp); | 206 | *value = host1x_syncpt_load(sp); |
207 | |||
204 | return 0; | 208 | return 0; |
205 | } | 209 | } |
206 | 210 | ||
@@ -209,6 +213,7 @@ int host1x_syncpt_wait(struct host1x_syncpt *sp, u32 thresh, long timeout, | |||
209 | if (host1x_syncpt_is_expired(sp, thresh)) { | 213 | if (host1x_syncpt_is_expired(sp, thresh)) { |
210 | if (value) | 214 | if (value) |
211 | *value = val; | 215 | *value = val; |
216 | |||
212 | goto done; | 217 | goto done; |
213 | } | 218 | } |
214 | 219 | ||
@@ -239,32 +244,42 @@ int host1x_syncpt_wait(struct host1x_syncpt *sp, u32 thresh, long timeout, | |||
239 | /* wait for the syncpoint, or timeout, or signal */ | 244 | /* wait for the syncpoint, or timeout, or signal */ |
240 | while (timeout) { | 245 | while (timeout) { |
241 | long check = min_t(long, SYNCPT_CHECK_PERIOD, timeout); | 246 | long check = min_t(long, SYNCPT_CHECK_PERIOD, timeout); |
242 | int remain = wait_event_interruptible_timeout(wq, | 247 | int remain; |
248 | |||
249 | remain = wait_event_interruptible_timeout(wq, | ||
243 | syncpt_load_min_is_expired(sp, thresh), | 250 | syncpt_load_min_is_expired(sp, thresh), |
244 | check); | 251 | check); |
245 | if (remain > 0 || host1x_syncpt_is_expired(sp, thresh)) { | 252 | if (remain > 0 || host1x_syncpt_is_expired(sp, thresh)) { |
246 | if (value) | 253 | if (value) |
247 | *value = host1x_syncpt_load(sp); | 254 | *value = host1x_syncpt_load(sp); |
255 | |||
248 | err = 0; | 256 | err = 0; |
257 | |||
249 | break; | 258 | break; |
250 | } | 259 | } |
260 | |||
251 | if (remain < 0) { | 261 | if (remain < 0) { |
252 | err = remain; | 262 | err = remain; |
253 | break; | 263 | break; |
254 | } | 264 | } |
265 | |||
255 | timeout -= check; | 266 | timeout -= check; |
267 | |||
256 | if (timeout && check_count <= MAX_STUCK_CHECK_COUNT) { | 268 | if (timeout && check_count <= MAX_STUCK_CHECK_COUNT) { |
257 | dev_warn(sp->host->dev, | 269 | dev_warn(sp->host->dev, |
258 | "%s: syncpoint id %d (%s) stuck waiting %d, timeout=%ld\n", | 270 | "%s: syncpoint id %u (%s) stuck waiting %d, timeout=%ld\n", |
259 | current->comm, sp->id, sp->name, | 271 | current->comm, sp->id, sp->name, |
260 | thresh, timeout); | 272 | thresh, timeout); |
261 | 273 | ||
262 | host1x_debug_dump_syncpts(sp->host); | 274 | host1x_debug_dump_syncpts(sp->host); |
275 | |||
263 | if (check_count == MAX_STUCK_CHECK_COUNT) | 276 | if (check_count == MAX_STUCK_CHECK_COUNT) |
264 | host1x_debug_dump(sp->host); | 277 | host1x_debug_dump(sp->host); |
278 | |||
265 | check_count++; | 279 | check_count++; |
266 | } | 280 | } |
267 | } | 281 | } |
282 | |||
268 | host1x_intr_put_ref(sp->host, sp->id, ref); | 283 | host1x_intr_put_ref(sp->host, sp->id, ref); |
269 | 284 | ||
270 | done: | 285 | done: |
@@ -279,7 +294,9 @@ bool host1x_syncpt_is_expired(struct host1x_syncpt *sp, u32 thresh) | |||
279 | { | 294 | { |
280 | u32 current_val; | 295 | u32 current_val; |
281 | u32 future_val; | 296 | u32 future_val; |
297 | |||
282 | smp_rmb(); | 298 | smp_rmb(); |
299 | |||
283 | current_val = (u32)atomic_read(&sp->min_val); | 300 | current_val = (u32)atomic_read(&sp->min_val); |
284 | future_val = (u32)atomic_read(&sp->max_val); | 301 | future_val = (u32)atomic_read(&sp->max_val); |
285 | 302 | ||
@@ -341,14 +358,14 @@ int host1x_syncpt_init(struct host1x *host) | |||
341 | { | 358 | { |
342 | struct host1x_syncpt_base *bases; | 359 | struct host1x_syncpt_base *bases; |
343 | struct host1x_syncpt *syncpt; | 360 | struct host1x_syncpt *syncpt; |
344 | int i; | 361 | unsigned int i; |
345 | 362 | ||
346 | syncpt = devm_kzalloc(host->dev, sizeof(*syncpt) * host->info->nb_pts, | 363 | syncpt = devm_kcalloc(host->dev, host->info->nb_pts, sizeof(*syncpt), |
347 | GFP_KERNEL); | 364 | GFP_KERNEL); |
348 | if (!syncpt) | 365 | if (!syncpt) |
349 | return -ENOMEM; | 366 | return -ENOMEM; |
350 | 367 | ||
351 | bases = devm_kzalloc(host->dev, sizeof(*bases) * host->info->nb_bases, | 368 | bases = devm_kcalloc(host->dev, host->info->nb_bases, sizeof(*bases), |
352 | GFP_KERNEL); | 369 | GFP_KERNEL); |
353 | if (!bases) | 370 | if (!bases) |
354 | return -ENOMEM; | 371 | return -ENOMEM; |
@@ -378,6 +395,7 @@ struct host1x_syncpt *host1x_syncpt_request(struct device *dev, | |||
378 | unsigned long flags) | 395 | unsigned long flags) |
379 | { | 396 | { |
380 | struct host1x *host = dev_get_drvdata(dev->parent); | 397 | struct host1x *host = dev_get_drvdata(dev->parent); |
398 | |||
381 | return host1x_syncpt_alloc(host, dev, flags); | 399 | return host1x_syncpt_alloc(host, dev, flags); |
382 | } | 400 | } |
383 | EXPORT_SYMBOL(host1x_syncpt_request); | 401 | EXPORT_SYMBOL(host1x_syncpt_request); |
@@ -398,8 +416,9 @@ EXPORT_SYMBOL(host1x_syncpt_free); | |||
398 | 416 | ||
399 | void host1x_syncpt_deinit(struct host1x *host) | 417 | void host1x_syncpt_deinit(struct host1x *host) |
400 | { | 418 | { |
401 | int i; | ||
402 | struct host1x_syncpt *sp = host->syncpt; | 419 | struct host1x_syncpt *sp = host->syncpt; |
420 | unsigned int i; | ||
421 | |||
403 | for (i = 0; i < host->info->nb_pts; i++, sp++) | 422 | for (i = 0; i < host->info->nb_pts; i++, sp++) |
404 | kfree(sp->name); | 423 | kfree(sp->name); |
405 | } | 424 | } |
@@ -407,10 +426,11 @@ void host1x_syncpt_deinit(struct host1x *host) | |||
407 | /* | 426 | /* |
408 | * Read max. It indicates how many operations there are in queue, either in | 427 | * Read max. It indicates how many operations there are in queue, either in |
409 | * channel or in a software thread. | 428 | * channel or in a software thread. |
410 | * */ | 429 | */ |
411 | u32 host1x_syncpt_read_max(struct host1x_syncpt *sp) | 430 | u32 host1x_syncpt_read_max(struct host1x_syncpt *sp) |
412 | { | 431 | { |
413 | smp_rmb(); | 432 | smp_rmb(); |
433 | |||
414 | return (u32)atomic_read(&sp->max_val); | 434 | return (u32)atomic_read(&sp->max_val); |
415 | } | 435 | } |
416 | EXPORT_SYMBOL(host1x_syncpt_read_max); | 436 | EXPORT_SYMBOL(host1x_syncpt_read_max); |
@@ -421,6 +441,7 @@ EXPORT_SYMBOL(host1x_syncpt_read_max); | |||
421 | u32 host1x_syncpt_read_min(struct host1x_syncpt *sp) | 441 | u32 host1x_syncpt_read_min(struct host1x_syncpt *sp) |
422 | { | 442 | { |
423 | smp_rmb(); | 443 | smp_rmb(); |
444 | |||
424 | return (u32)atomic_read(&sp->min_val); | 445 | return (u32)atomic_read(&sp->min_val); |
425 | } | 446 | } |
426 | EXPORT_SYMBOL(host1x_syncpt_read_min); | 447 | EXPORT_SYMBOL(host1x_syncpt_read_min); |
@@ -431,25 +452,26 @@ u32 host1x_syncpt_read(struct host1x_syncpt *sp) | |||
431 | } | 452 | } |
432 | EXPORT_SYMBOL(host1x_syncpt_read); | 453 | EXPORT_SYMBOL(host1x_syncpt_read); |
433 | 454 | ||
434 | int host1x_syncpt_nb_pts(struct host1x *host) | 455 | unsigned int host1x_syncpt_nb_pts(struct host1x *host) |
435 | { | 456 | { |
436 | return host->info->nb_pts; | 457 | return host->info->nb_pts; |
437 | } | 458 | } |
438 | 459 | ||
439 | int host1x_syncpt_nb_bases(struct host1x *host) | 460 | unsigned int host1x_syncpt_nb_bases(struct host1x *host) |
440 | { | 461 | { |
441 | return host->info->nb_bases; | 462 | return host->info->nb_bases; |
442 | } | 463 | } |
443 | 464 | ||
444 | int host1x_syncpt_nb_mlocks(struct host1x *host) | 465 | unsigned int host1x_syncpt_nb_mlocks(struct host1x *host) |
445 | { | 466 | { |
446 | return host->info->nb_mlocks; | 467 | return host->info->nb_mlocks; |
447 | } | 468 | } |
448 | 469 | ||
449 | struct host1x_syncpt *host1x_syncpt_get(struct host1x *host, u32 id) | 470 | struct host1x_syncpt *host1x_syncpt_get(struct host1x *host, unsigned int id) |
450 | { | 471 | { |
451 | if (host->info->nb_pts < id) | 472 | if (host->info->nb_pts < id) |
452 | return NULL; | 473 | return NULL; |
474 | |||
453 | return host->syncpt + id; | 475 | return host->syncpt + id; |
454 | } | 476 | } |
455 | EXPORT_SYMBOL(host1x_syncpt_get); | 477 | EXPORT_SYMBOL(host1x_syncpt_get); |