summaryrefslogtreecommitdiff
path: root/drivers/video/tegra/dc/sor.h
blob: e7282d2fd36bb5f9d060a8e3bf23b816f1ea0af2 (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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209

/*
 * drivers/video/tegra/dc/sor.h
 *
 * Copyright (c) 2011-2014, NVIDIA CORPORATION, All rights reserved.
 *
 * This software is licensed under the terms of the GNU General Public
 * License version 2, as published by the Free Software Foundation, and
 * may be copied, distributed, and modified under those terms.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 */

#ifndef __DRIVERS_VIDEO_TEGRA_DC_SOR_H__
#define __DRIVERS_VIDEO_TEGRA_DC_SOR_H__

enum {
	TRAINING_PATTERN_DISABLE = 0,
	TRAINING_PATTERN_1 = 1,
	TRAINING_PATTERN_2 = 2,
	TRAINING_PATTERN_3 = 3,
};

enum tegra_dc_sor_protocol {
	SOR_DP,
	SOR_LVDS,
};

#define SOR_LINK_SPEED_G1_62	6
#define SOR_LINK_SPEED_G2_7	10
#define SOR_LINK_SPEED_G5_4	20
#define SOR_LINK_SPEED_LVDS	7

struct tegra_dc_dp_link_config {
	bool	is_valid;	/*
				 * True if link config adheres to dp spec.
				 * Does not guarantee link training success.
				 */

	/* Supported configuration */
	u8	max_link_bw;
	u8	max_lane_count;
	bool	downspread;
	bool	support_enhanced_framing;
	u32	bits_per_pixel;
	bool	alt_scramber_reset_cap; /* true for eDP */
	bool	only_enhanced_framing;	/* enhanced_frame_en ignored */
	bool	edp_cap;		/* eDP display control capable */
	bool	support_fast_lt;	/* Support fast link training */

	/* Actual configuration */
	u8	link_bw;
	u8	lane_count;
	bool	enhanced_framing;
	bool	scramble_ena;

	u32	activepolarity;
	u32	active_count;
	u32	tu_size;
	u32	active_frac;
	u32	watermark;

	s32	hblank_sym;
	s32	vblank_sym;

	bool	lt_data_valid;	/*
				 * True only if link training passed with this
				 * drive_current, preemphasis and postcursor.
				 */
	u32	drive_current[4];
	u32	preemphasis[4];
	u32	postcursor[4];

	bool	tps3_supported;
	u8	aux_rd_interval;
};

enum {
	TEGRA_SOR_SAFE_CLK = 1,
	TEGRA_SOR_LINK_CLK = 2,
};

struct tegra_dc_sor_data {
	struct tegra_dc	*dc;

	void __iomem	*base;
	struct resource	*base_res;
	struct clk	*sor_clk;

	u8					 portnum;	/* 0 or 1 */
	const struct tegra_dc_dp_link_config	*link_cfg;
	u32	lvds_drive_strength;

	bool   power_is_up;

	u8	clk_type;
};

#define TEGRA_SOR_TIMEOUT_MS		1000
#define TEGRA_SOR_ATTACH_TIMEOUT_MS	100000
#define TEGRA_SOR_SEQ_BUSY_TIMEOUT_MS	10000
#define TEGRA_DC_POLL_TIMEOUT_MS       50

#define CHECK_RET(x)			\
	do {				\
		ret = (x);		\
		if (ret != 0)		\
			return ret;	\
	} while (0)


struct tegra_dc_sor_data *tegra_dc_sor_init(struct tegra_dc *dc,
	const struct tegra_dc_dp_link_config *cfg);

void tegra_dc_sor_destroy(struct tegra_dc_sor_data *sor);
void tegra_dc_sor_enable_dp(struct tegra_dc_sor_data *sor);
void tegra_dc_sor_attach(struct tegra_dc_sor_data *sor);
void tegra_dc_sor_detach(struct tegra_dc_sor_data *sor);
void tegra_dc_sor_enable_lvds(struct tegra_dc_sor_data *sor,
	bool balanced, bool conforming);
void tegra_dc_sor_disable(struct tegra_dc_sor_data *sor, bool is_lvds);

void tegra_dc_sor_set_internal_panel(struct tegra_dc_sor_data *sor,
	bool is_int);
void tegra_dc_sor_read_link_config(struct tegra_dc_sor_data *sor,
	u8 *link_bw, u8 *lane_count);
void tegra_dc_sor_set_link_bandwidth(struct tegra_dc_sor_data *sor,
	u8 link_bw);
void tegra_dc_sor_set_lane_count(struct tegra_dc_sor_data *sor, u8 lane_count);
void tegra_sor_pad_cal_power(struct tegra_dc_sor_data *sor, bool power_up);
void tegra_dc_sor_set_pwm(struct tegra_dc_sor_data *sor, u32 pwm_div,
	u32 pwm_dutycycle, u32 pwm_clksrc);
void tegra_dc_sor_set_dp_lanedata(struct tegra_dc_sor_data *sor,
	u32 lane, u32 pre_emphasis, u32 drive_current, u32 tx_pu);
void tegra_dc_sor_set_dp_linkctl(struct tegra_dc_sor_data *sor, bool ena,
	u8 training_pattern, const struct tegra_dc_dp_link_config *cfg);
void tegra_dc_sor_set_dp_mode(struct tegra_dc_sor_data *sor,
	const struct tegra_dc_dp_link_config *cfg);
void tegra_sor_setup_clk(struct tegra_dc_sor_data *sor, struct clk *clk,
	bool is_lvds);
void tegra_sor_precharge_lanes(struct tegra_dc_sor_data *sor);
int tegra_dc_sor_set_power_state(struct tegra_dc_sor_data *sor,
	int pu_pd);
void tegra_dc_sor_modeset_notifier(struct tegra_dc_sor_data *sor,
	bool is_lvds);
void tegra_sor_tpg(struct tegra_dc_sor_data *sor, u32 tp, u32 n_lanes);
void tegra_sor_port_enable(struct tegra_dc_sor_data *sor, bool enb);
int tegra_sor_power_dp_lanes(struct tegra_dc_sor_data *sor,
					u32 lane_count, bool pu);
void tegra_sor_config_dp_clk(struct tegra_dc_sor_data *sor);
void tegra_sor_stop_dc(struct tegra_dc_sor_data *sor);
void tegra_sor_start_dc(struct tegra_dc_sor_data *sor);

static inline u32 tegra_sor_readl(struct tegra_dc_sor_data *sor, u32 reg)
{
	u32 reg_val = readl(sor->base + reg * 4);
	return reg_val;
}

static inline void tegra_sor_writel(struct tegra_dc_sor_data *sor,
	u32 reg, u32 val)
{
	writel(val, sor->base + reg * 4);
}

static inline void tegra_sor_write_field(struct tegra_dc_sor_data *sor,
	u32 reg, u32 mask, u32 val)
{
	u32 reg_val = tegra_sor_readl(sor, reg);
	reg_val &= ~mask;
	reg_val |= val;
	tegra_sor_writel(sor, reg, reg_val);
}

static inline void tegra_sor_clk_enable(struct tegra_dc_sor_data *sor)
{
	clk_prepare_enable(sor->sor_clk);
}

static inline void tegra_sor_clk_disable(struct tegra_dc_sor_data *sor)
{
	clk_disable_unprepare(sor->sor_clk);
}

static inline int lt_param_idx(int link_bw)
{
	int idx;
	switch (link_bw) {
	case SOR_LINK_SPEED_G1_62:
		idx = 0;
		break;
	case SOR_LINK_SPEED_G2_7:
		idx = 1;
		break;
	case SOR_LINK_SPEED_G5_4:
		idx = 2;
		break;
	default:
		/* Error BW */
		BUG_ON(1);
	}
	return idx;
}

#endif