aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/host1x/syncpt.c
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2016-07-15 21:23:50 -0400
committerDave Airlie <airlied@redhat.com>2016-07-15 21:23:50 -0400
commit877fa9a42ddc087dc46a3a3aac18db8adde2bdf1 (patch)
treec5189830c8d3fed08e92deda8681f0676aaea8a5 /drivers/gpu/host1x/syncpt.c
parente2b80bac213cdfd443df9b6e1c769f98d0553c0c (diff)
parent64ea25c3bc86c05c7da6c683b86663f4c90158d6 (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.c58
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);
110void host1x_syncpt_restore(struct host1x *host) 110void 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)
126void host1x_syncpt_save(struct host1x *host) 128void 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)
146u32 host1x_syncpt_load(struct host1x_syncpt *sp) 148u32 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 */
158u32 host1x_syncpt_load_wait_base(struct host1x_syncpt *sp) 161u32 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);
179static bool syncpt_load_min_is_expired(struct host1x_syncpt *sp, u32 thresh) 181static 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 */
188int host1x_syncpt_wait(struct host1x_syncpt *sp, u32 thresh, long timeout, 191int 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
270done: 285done:
@@ -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}
383EXPORT_SYMBOL(host1x_syncpt_request); 401EXPORT_SYMBOL(host1x_syncpt_request);
@@ -398,8 +416,9 @@ EXPORT_SYMBOL(host1x_syncpt_free);
398 416
399void host1x_syncpt_deinit(struct host1x *host) 417void 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 */
411u32 host1x_syncpt_read_max(struct host1x_syncpt *sp) 430u32 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}
416EXPORT_SYMBOL(host1x_syncpt_read_max); 436EXPORT_SYMBOL(host1x_syncpt_read_max);
@@ -421,6 +441,7 @@ EXPORT_SYMBOL(host1x_syncpt_read_max);
421u32 host1x_syncpt_read_min(struct host1x_syncpt *sp) 441u32 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}
426EXPORT_SYMBOL(host1x_syncpt_read_min); 447EXPORT_SYMBOL(host1x_syncpt_read_min);
@@ -431,25 +452,26 @@ u32 host1x_syncpt_read(struct host1x_syncpt *sp)
431} 452}
432EXPORT_SYMBOL(host1x_syncpt_read); 453EXPORT_SYMBOL(host1x_syncpt_read);
433 454
434int host1x_syncpt_nb_pts(struct host1x *host) 455unsigned 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
439int host1x_syncpt_nb_bases(struct host1x *host) 460unsigned 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
444int host1x_syncpt_nb_mlocks(struct host1x *host) 465unsigned 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
449struct host1x_syncpt *host1x_syncpt_get(struct host1x *host, u32 id) 470struct 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}
455EXPORT_SYMBOL(host1x_syncpt_get); 477EXPORT_SYMBOL(host1x_syncpt_get);