aboutsummaryrefslogtreecommitdiff
path: root/src/drivers/intel/gma/i915.h
blob: 62fe0230e6d86e05e2eb33336fc876144768c265 (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
/*
 * This file is part of the coreboot project.
 *
 * Copyright 2012 Google Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2 of the License.
 *
 * 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include <drivers/intel/gma/i915_reg.h>
#include <drivers/intel/gma/drm_dp_helper.h>
#include <edid.h>

/* port types. We stick with the same defines as the kernel */
#define INTEL_OUTPUT_UNUSED 0
#define INTEL_OUTPUT_ANALOG 1
#define INTEL_OUTPUT_DVO 2
#define INTEL_OUTPUT_SDVO 3
#define INTEL_OUTPUT_LVDS 4
#define INTEL_OUTPUT_TVOUT 5
#define INTEL_OUTPUT_HDMI 6
#define INTEL_OUTPUT_DISPLAYPORT 7
#define INTEL_OUTPUT_EDP 8

/* things that are, strangely, not defined anywhere? */
#define PCH_PP_UNLOCK	0xabcd0000
#define WMx_LP_SR_EN	(1<<31)
#define PRB0_TAIL	0x02030
#define PRB0_HEAD	0x02034
#define PRB0_START	0x02038
#define PRB0_CTL	0x0203c

/* debug enums. These are for printks that, due to their place in the
 * middle of graphics device IO, might change timing.  Use with care
 * or not at all.
 */
enum {
	vio = 2, /* dump every IO */
	vspin = 4, /* print # of times we spun on a register value */
};

/* The mainboard must provide these functions. */
unsigned long io_i915_read32(unsigned long addr);
void io_i915_write32(unsigned long val, unsigned long addr);

/*
 * To communicate to and control the extracted-from-kernel code,
 * we need this struct. It has a counterpart in the ARM code, so
 * there is a precedent.
 */

#define DP_RECEIVER_CAP_SIZE	0xf
#define DP_LINK_STATUS_SIZE	6
#define DP_LINK_CHECK_TIMEOUT	(10 * 1000)

#define DP_LINK_CONFIGURATION_SIZE	9

struct intel_dp_m_n {
	uint32_t	tu;
	uint32_t	gmch_m;
	uint32_t	gmch_n;
	uint32_t	link_m;
	uint32_t	link_n;
};

struct intel_dp {
	int gen; // 6 for link, 7 for wtm2
	int has_pch_split; // 1 for link and wtm2
	int has_pch_cpt; // 1 for everything we know about.
	int is_haswell;
	/* output register offset in MMIO space. Usually DP_A */
	u32 output_reg;
	/* The initial value of the DP register.
	 * Mainboards can set this to a non-zero
	 * value in the case that there are undetectable
	 * but essential parameters.
	 */
	u32 DP;
	uint8_t  link_configuration[DP_LINK_CONFIGURATION_SIZE];
	u32 color_range;
	/* these paramaters are determined after reading the DPCD */
	int dpms_mode;
	uint8_t link_bw;
	uint8_t lane_count;
	/* This data is read from the panel via the AUX channel.*/
	uint8_t dpcd[DP_RECEIVER_CAP_SIZE];
	int type;
	int edp;
	int is_pch_edp;
	/* state related to training. */
	uint8_t	train_set[4];
	/* Determined from EDID or coreboot hard-sets. */
	int panel_power_up_delay;
	int panel_power_down_delay;
	int panel_power_cycle_delay;
	int backlight_on_delay;
	int backlight_off_delay;
	int want_panel_vdd;
	u32 clock;
	int port;
	int pipe;
	int bpp;
	/* i2c on aux is ... interesting.
	 * Before you do an i2c cycle, you need to set the address.
	 * This requires we remember it from one moment to the next.
	 * Remember it here.
	 */
	u16 address;
	/* timing parameters for aux channel IO. They used to compute these on
	 * each and every entry to the functions, which is kind of stupid, and it had
	 * errors anyway.
	 * note: you can get these from watching YABEL output. E.g.:
	 * you see an outb of 0x802300e1 to 64010. the 3 is the precharge
	 * and the e1 is the clock divider.
	 */
	u32 aux_clock_divider;
	u32 precharge;
	/* EDID, raw and processed */
	u8 rawedid[256];
	int edidlen;
	struct edid edid;
	/* computed values needed for "i915" registers */
	int bytes_per_pixel;
	u32 htotal;
	u32 hblank;
	u32 hsync;
	u32 vtotal;
	u32 vblank;
	u32 vsync;
	u32 pfa_sz;
	u32 pfa_pos;
	u32 pfa_ctl;
	u32 pipesrc;
	u32 stride;
	struct intel_dp_m_n m_n;
};

/* we may yet need these. */
void intel_dp_mode_set(struct intel_dp *intel_dp);
void intel_dp_start_link_train(struct intel_dp *intel_dp);
void intel_dp_complete_link_train(struct intel_dp *intel_dp);
void intel_dp_link_down(struct intel_dp *intel_dp);

int intel_dp_i2c_init(struct intel_dp *intel_dp);
int intel_dp_i2c_aux_ch(struct intel_dp *intel_dp,
			int mode, uint8_t write_byte, uint8_t *read_byte);
void
intel_dp_dpms(struct intel_dp *intel_dp, int mode);

int intel_dp_get_dpcd(struct intel_dp *intel_dp);
struct edid *intel_dp_get_edid(struct intel_dp *intel_dp);

void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode);
void ironlake_edp_pll_on(void);
void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp);
void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, int sync);
int intel_dp_get_max_downspread(struct intel_dp *intel_dp, u8 *max_downspread);
void ironlake_edp_panel_on(struct intel_dp *intel_dp);
void ironlake_edp_backlight_on(struct intel_dp *intel_dp);
/* needed only on haswell. */
void intel_prepare_ddi_buffers(int port, int use_fdi_mode);
void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp, int port);
int intel_dp_aux_ch(struct intel_dp *intel_dp,
		    uint8_t *send, int send_bytes,
		    uint8_t *recv, int recv_size);
void unpack_aux(u32 src, uint8_t *dst, int dst_bytes);


/* drm_dp_helper.c */
int drm_dp_channel_eq_ok(u8 link_status[DP_LINK_STATUS_SIZE],
			 int lane_count);
int drm_dp_clock_recovery_ok(u8 link_status[DP_LINK_STATUS_SIZE],
			     int lane_count);
u8 drm_dp_get_adjust_request_voltage(u8 link_status[DP_LINK_STATUS_SIZE],
				     int lane);
u8 drm_dp_get_adjust_request_pre_emphasis(u8 link_status[DP_LINK_STATUS_SIZE],
					  int lane);


void intel_dp_wait_reg(unsigned long addr,
		       unsigned long val);

void intel_dp_wait_panel_power_control(unsigned long val);

void intel_dp_compute_m_n(unsigned int bits_per_pixel,
                          unsigned int nlanes,
                          unsigned int pixel_clock,
                          unsigned int link_clock,
                          struct intel_dp_m_n *m_n);