summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/display/intel_dkl_phy.c
blob: 710b030c7ed54dd6869b3c865737191e31f3f8f8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
// SPDX-License-Identifier: MIT
/*
 * Copyright © 2022 Intel Corporation
 */

#include "i915_drv.h"
#include "i915_reg.h"

#include "intel_de.h"
#include "intel_display.h"
#include "intel_dkl_phy.h"

static void
dkl_phy_set_hip_idx(struct drm_i915_private *i915, i915_reg_t reg, int idx)
{
	enum tc_port tc_port = DKL_REG_TC_PORT(reg);

	drm_WARN_ON(&i915->drm, tc_port < TC_PORT_1 || tc_port >= I915_MAX_TC_PORTS);

	intel_de_write(i915,
		       HIP_INDEX_REG(tc_port),
		       HIP_INDEX_VAL(tc_port, idx));
}

/**
 * intel_dkl_phy_read - read a Dekel PHY register
 * @i915: i915 device instance
 * @reg: Dekel PHY register
 * @ln: lane instance of @reg
 *
 * Read the @reg Dekel PHY register.
 *
 * Returns the read value.
 */
u32
intel_dkl_phy_read(struct drm_i915_private *i915, i915_reg_t reg, int ln)
{
	u32 val;

	spin_lock(&i915->display.dkl.phy_lock);

	dkl_phy_set_hip_idx(i915, reg, ln);
	val = intel_de_read(i915, reg);

	spin_unlock(&i915->display.dkl.phy_lock);

	return val;
}

/**
 * intel_dkl_phy_write - write a Dekel PHY register
 * @i915: i915 device instance
 * @reg: Dekel PHY register
 * @ln: lane instance of @reg
 * @val: value to write
 *
 * Write @val to the @reg Dekel PHY register.
 */
void
intel_dkl_phy_write(struct drm_i915_private *i915, i915_reg_t reg, int ln, u32 val)
{
	spin_lock(&i915->display.dkl.phy_lock);

	dkl_phy_set_hip_idx(i915, reg, ln);
	intel_de_write(i915, reg, val);

	spin_unlock(&i915->display.dkl.phy_lock);
}

/**
 * intel_dkl_phy_rmw - read-modify-write a Dekel PHY register
 * @i915: i915 device instance
 * @reg: Dekel PHY register
 * @ln: lane instance of @reg
 * @clear: mask to clear
 * @set: mask to set
 *
 * Read the @reg Dekel PHY register, clearing then setting the @clear/@set bits in it, and writing
 * this value back to the register if the value differs from the read one.
 */
void
intel_dkl_phy_rmw(struct drm_i915_private *i915, i915_reg_t reg, int ln, u32 clear, u32 set)
{
	spin_lock(&i915->display.dkl.phy_lock);

	dkl_phy_set_hip_idx(i915, reg, ln);
	intel_de_rmw(i915, reg, clear, set);

	spin_unlock(&i915->display.dkl.phy_lock);
}

/**
 * intel_dkl_phy_posting_read - do a posting read from a Dekel PHY register
 * @i915: i915 device instance
 * @reg: Dekel PHY register
 * @ln: lane instance of @reg
 *
 * Read the @reg Dekel PHY register without returning the read value.
 */
void
intel_dkl_phy_posting_read(struct drm_i915_private *i915, i915_reg_t reg, int ln)
{
	spin_lock(&i915->display.dkl.phy_lock);

	dkl_phy_set_hip_idx(i915, reg, ln);
	intel_de_posting_read(i915, reg);

	spin_unlock(&i915->display.dkl.phy_lock);
}