|
@@ -1,5 +1,6 @@
|
|
|
// SPDX-License-Identifier: GPL-2.0-only
|
|
|
/*
|
|
|
+ * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
|
|
|
* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
|
|
|
*/
|
|
|
#include <linux/iopoll.h>
|
|
@@ -616,10 +617,12 @@ static int sde_hw_intf_setup_te_config(struct sde_hw_intf *intf,
|
|
|
{
|
|
|
struct sde_hw_blk_reg_map *c;
|
|
|
u32 cfg = 0;
|
|
|
+ spinlock_t tearcheck_spinlock;
|
|
|
|
|
|
if (!intf)
|
|
|
return -EINVAL;
|
|
|
|
|
|
+ spin_lock_init(&tearcheck_spinlock);
|
|
|
c = &intf->hw;
|
|
|
|
|
|
if (te->hw_vsync_mode)
|
|
@@ -627,6 +630,14 @@ static int sde_hw_intf_setup_te_config(struct sde_hw_intf *intf,
|
|
|
|
|
|
cfg |= te->vsync_count;
|
|
|
|
|
|
+ /*
|
|
|
+ * Local spinlock is acquired here to avoid pre-emption
|
|
|
+ * as below register programming should be completed in
|
|
|
+ * less than 2^16 vsync clk cycles.
|
|
|
+ */
|
|
|
+ spin_lock(&tearcheck_spinlock);
|
|
|
+ SDE_REG_WRITE(c, INTF_TEAR_SYNC_WRCOUNT,
|
|
|
+ (te->start_pos + te->sync_threshold_start + 1));
|
|
|
SDE_REG_WRITE(c, INTF_TEAR_SYNC_CONFIG_VSYNC, cfg);
|
|
|
wmb(); /* disable vsync counter before updating single buffer registers */
|
|
|
SDE_REG_WRITE(c, INTF_TEAR_SYNC_CONFIG_HEIGHT, te->sync_cfg_height);
|
|
@@ -637,10 +648,9 @@ static int sde_hw_intf_setup_te_config(struct sde_hw_intf *intf,
|
|
|
SDE_REG_WRITE(c, INTF_TEAR_SYNC_THRESH,
|
|
|
((te->sync_threshold_continue << 16) |
|
|
|
te->sync_threshold_start));
|
|
|
- SDE_REG_WRITE(c, INTF_TEAR_SYNC_WRCOUNT,
|
|
|
- (te->start_pos + te->sync_threshold_start + 1));
|
|
|
cfg |= BIT(19); /* VSYNC_COUNTER_EN */
|
|
|
SDE_REG_WRITE(c, INTF_TEAR_SYNC_CONFIG_VSYNC, cfg);
|
|
|
+ spin_unlock(&tearcheck_spinlock);
|
|
|
|
|
|
return 0;
|
|
|
}
|