1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright © 2012 Intel Corporation
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Permission is hereby granted, free of charge, to any person obtaining a
5*4882a593Smuzhiyun * copy of this software and associated documentation files (the "Software"),
6*4882a593Smuzhiyun * to deal in the Software without restriction, including without limitation
7*4882a593Smuzhiyun * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*4882a593Smuzhiyun * and/or sell copies of the Software, and to permit persons to whom the
9*4882a593Smuzhiyun * Software is furnished to do so, subject to the following conditions:
10*4882a593Smuzhiyun *
11*4882a593Smuzhiyun * The above copyright notice and this permission notice (including the next
12*4882a593Smuzhiyun * paragraph) shall be included in all copies or substantial portions of the
13*4882a593Smuzhiyun * Software.
14*4882a593Smuzhiyun *
15*4882a593Smuzhiyun * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*4882a593Smuzhiyun * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*4882a593Smuzhiyun * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18*4882a593Smuzhiyun * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*4882a593Smuzhiyun * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*4882a593Smuzhiyun * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21*4882a593Smuzhiyun * IN THE SOFTWARE.
22*4882a593Smuzhiyun *
23*4882a593Smuzhiyun * Authors:
24*4882a593Smuzhiyun * Keith Packard <keithp@keithp.com>
25*4882a593Smuzhiyun *
26*4882a593Smuzhiyun */
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun #include <linux/i2c.h>
29*4882a593Smuzhiyun #include <linux/module.h>
30*4882a593Smuzhiyun #include <linux/slab.h>
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun #include <drm/drm_crtc.h>
33*4882a593Smuzhiyun #include <drm/drm_crtc_helper.h>
34*4882a593Smuzhiyun #include <drm/drm_dp_helper.h>
35*4882a593Smuzhiyun #include <drm/drm_simple_kms_helper.h>
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun #include "gma_display.h"
38*4882a593Smuzhiyun #include "psb_drv.h"
39*4882a593Smuzhiyun #include "psb_intel_drv.h"
40*4882a593Smuzhiyun #include "psb_intel_reg.h"
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun /**
43*4882a593Smuzhiyun * struct i2c_algo_dp_aux_data - driver interface structure for i2c over dp
44*4882a593Smuzhiyun * aux algorithm
45*4882a593Smuzhiyun * @running: set by the algo indicating whether an i2c is ongoing or whether
46*4882a593Smuzhiyun * the i2c bus is quiescent
47*4882a593Smuzhiyun * @address: i2c target address for the currently ongoing transfer
48*4882a593Smuzhiyun * @aux_ch: driver callback to transfer a single byte of the i2c payload
49*4882a593Smuzhiyun */
50*4882a593Smuzhiyun struct i2c_algo_dp_aux_data {
51*4882a593Smuzhiyun bool running;
52*4882a593Smuzhiyun u16 address;
53*4882a593Smuzhiyun int (*aux_ch) (struct i2c_adapter *adapter,
54*4882a593Smuzhiyun int mode, uint8_t write_byte,
55*4882a593Smuzhiyun uint8_t *read_byte);
56*4882a593Smuzhiyun };
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun /* Run a single AUX_CH I2C transaction, writing/reading data as necessary */
59*4882a593Smuzhiyun static int
i2c_algo_dp_aux_transaction(struct i2c_adapter * adapter,int mode,uint8_t write_byte,uint8_t * read_byte)60*4882a593Smuzhiyun i2c_algo_dp_aux_transaction(struct i2c_adapter *adapter, int mode,
61*4882a593Smuzhiyun uint8_t write_byte, uint8_t *read_byte)
62*4882a593Smuzhiyun {
63*4882a593Smuzhiyun struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
64*4882a593Smuzhiyun int ret;
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun ret = (*algo_data->aux_ch)(adapter, mode,
67*4882a593Smuzhiyun write_byte, read_byte);
68*4882a593Smuzhiyun return ret;
69*4882a593Smuzhiyun }
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun /*
72*4882a593Smuzhiyun * I2C over AUX CH
73*4882a593Smuzhiyun */
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun /*
76*4882a593Smuzhiyun * Send the address. If the I2C link is running, this 'restarts'
77*4882a593Smuzhiyun * the connection with the new address, this is used for doing
78*4882a593Smuzhiyun * a write followed by a read (as needed for DDC)
79*4882a593Smuzhiyun */
80*4882a593Smuzhiyun static int
i2c_algo_dp_aux_address(struct i2c_adapter * adapter,u16 address,bool reading)81*4882a593Smuzhiyun i2c_algo_dp_aux_address(struct i2c_adapter *adapter, u16 address, bool reading)
82*4882a593Smuzhiyun {
83*4882a593Smuzhiyun struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
84*4882a593Smuzhiyun int mode = MODE_I2C_START;
85*4882a593Smuzhiyun int ret;
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun if (reading)
88*4882a593Smuzhiyun mode |= MODE_I2C_READ;
89*4882a593Smuzhiyun else
90*4882a593Smuzhiyun mode |= MODE_I2C_WRITE;
91*4882a593Smuzhiyun algo_data->address = address;
92*4882a593Smuzhiyun algo_data->running = true;
93*4882a593Smuzhiyun ret = i2c_algo_dp_aux_transaction(adapter, mode, 0, NULL);
94*4882a593Smuzhiyun return ret;
95*4882a593Smuzhiyun }
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun /*
98*4882a593Smuzhiyun * Stop the I2C transaction. This closes out the link, sending
99*4882a593Smuzhiyun * a bare address packet with the MOT bit turned off
100*4882a593Smuzhiyun */
101*4882a593Smuzhiyun static void
i2c_algo_dp_aux_stop(struct i2c_adapter * adapter,bool reading)102*4882a593Smuzhiyun i2c_algo_dp_aux_stop(struct i2c_adapter *adapter, bool reading)
103*4882a593Smuzhiyun {
104*4882a593Smuzhiyun struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
105*4882a593Smuzhiyun int mode = MODE_I2C_STOP;
106*4882a593Smuzhiyun
107*4882a593Smuzhiyun if (reading)
108*4882a593Smuzhiyun mode |= MODE_I2C_READ;
109*4882a593Smuzhiyun else
110*4882a593Smuzhiyun mode |= MODE_I2C_WRITE;
111*4882a593Smuzhiyun if (algo_data->running) {
112*4882a593Smuzhiyun (void) i2c_algo_dp_aux_transaction(adapter, mode, 0, NULL);
113*4882a593Smuzhiyun algo_data->running = false;
114*4882a593Smuzhiyun }
115*4882a593Smuzhiyun }
116*4882a593Smuzhiyun
117*4882a593Smuzhiyun /*
118*4882a593Smuzhiyun * Write a single byte to the current I2C address, the
119*4882a593Smuzhiyun * the I2C link must be running or this returns -EIO
120*4882a593Smuzhiyun */
121*4882a593Smuzhiyun static int
i2c_algo_dp_aux_put_byte(struct i2c_adapter * adapter,u8 byte)122*4882a593Smuzhiyun i2c_algo_dp_aux_put_byte(struct i2c_adapter *adapter, u8 byte)
123*4882a593Smuzhiyun {
124*4882a593Smuzhiyun struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
125*4882a593Smuzhiyun int ret;
126*4882a593Smuzhiyun
127*4882a593Smuzhiyun if (!algo_data->running)
128*4882a593Smuzhiyun return -EIO;
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun ret = i2c_algo_dp_aux_transaction(adapter, MODE_I2C_WRITE, byte, NULL);
131*4882a593Smuzhiyun return ret;
132*4882a593Smuzhiyun }
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun /*
135*4882a593Smuzhiyun * Read a single byte from the current I2C address, the
136*4882a593Smuzhiyun * I2C link must be running or this returns -EIO
137*4882a593Smuzhiyun */
138*4882a593Smuzhiyun static int
i2c_algo_dp_aux_get_byte(struct i2c_adapter * adapter,u8 * byte_ret)139*4882a593Smuzhiyun i2c_algo_dp_aux_get_byte(struct i2c_adapter *adapter, u8 *byte_ret)
140*4882a593Smuzhiyun {
141*4882a593Smuzhiyun struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
142*4882a593Smuzhiyun int ret;
143*4882a593Smuzhiyun
144*4882a593Smuzhiyun if (!algo_data->running)
145*4882a593Smuzhiyun return -EIO;
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun ret = i2c_algo_dp_aux_transaction(adapter, MODE_I2C_READ, 0, byte_ret);
148*4882a593Smuzhiyun return ret;
149*4882a593Smuzhiyun }
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun static int
i2c_algo_dp_aux_xfer(struct i2c_adapter * adapter,struct i2c_msg * msgs,int num)152*4882a593Smuzhiyun i2c_algo_dp_aux_xfer(struct i2c_adapter *adapter,
153*4882a593Smuzhiyun struct i2c_msg *msgs,
154*4882a593Smuzhiyun int num)
155*4882a593Smuzhiyun {
156*4882a593Smuzhiyun int ret = 0;
157*4882a593Smuzhiyun bool reading = false;
158*4882a593Smuzhiyun int m;
159*4882a593Smuzhiyun int b;
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun for (m = 0; m < num; m++) {
162*4882a593Smuzhiyun u16 len = msgs[m].len;
163*4882a593Smuzhiyun u8 *buf = msgs[m].buf;
164*4882a593Smuzhiyun reading = (msgs[m].flags & I2C_M_RD) != 0;
165*4882a593Smuzhiyun ret = i2c_algo_dp_aux_address(adapter, msgs[m].addr, reading);
166*4882a593Smuzhiyun if (ret < 0)
167*4882a593Smuzhiyun break;
168*4882a593Smuzhiyun if (reading) {
169*4882a593Smuzhiyun for (b = 0; b < len; b++) {
170*4882a593Smuzhiyun ret = i2c_algo_dp_aux_get_byte(adapter, &buf[b]);
171*4882a593Smuzhiyun if (ret < 0)
172*4882a593Smuzhiyun break;
173*4882a593Smuzhiyun }
174*4882a593Smuzhiyun } else {
175*4882a593Smuzhiyun for (b = 0; b < len; b++) {
176*4882a593Smuzhiyun ret = i2c_algo_dp_aux_put_byte(adapter, buf[b]);
177*4882a593Smuzhiyun if (ret < 0)
178*4882a593Smuzhiyun break;
179*4882a593Smuzhiyun }
180*4882a593Smuzhiyun }
181*4882a593Smuzhiyun if (ret < 0)
182*4882a593Smuzhiyun break;
183*4882a593Smuzhiyun }
184*4882a593Smuzhiyun if (ret >= 0)
185*4882a593Smuzhiyun ret = num;
186*4882a593Smuzhiyun i2c_algo_dp_aux_stop(adapter, reading);
187*4882a593Smuzhiyun DRM_DEBUG_KMS("dp_aux_xfer return %d\n", ret);
188*4882a593Smuzhiyun return ret;
189*4882a593Smuzhiyun }
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun static u32
i2c_algo_dp_aux_functionality(struct i2c_adapter * adapter)192*4882a593Smuzhiyun i2c_algo_dp_aux_functionality(struct i2c_adapter *adapter)
193*4882a593Smuzhiyun {
194*4882a593Smuzhiyun return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
195*4882a593Smuzhiyun I2C_FUNC_SMBUS_READ_BLOCK_DATA |
196*4882a593Smuzhiyun I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
197*4882a593Smuzhiyun I2C_FUNC_10BIT_ADDR;
198*4882a593Smuzhiyun }
199*4882a593Smuzhiyun
200*4882a593Smuzhiyun static const struct i2c_algorithm i2c_dp_aux_algo = {
201*4882a593Smuzhiyun .master_xfer = i2c_algo_dp_aux_xfer,
202*4882a593Smuzhiyun .functionality = i2c_algo_dp_aux_functionality,
203*4882a593Smuzhiyun };
204*4882a593Smuzhiyun
205*4882a593Smuzhiyun static void
i2c_dp_aux_reset_bus(struct i2c_adapter * adapter)206*4882a593Smuzhiyun i2c_dp_aux_reset_bus(struct i2c_adapter *adapter)
207*4882a593Smuzhiyun {
208*4882a593Smuzhiyun (void) i2c_algo_dp_aux_address(adapter, 0, false);
209*4882a593Smuzhiyun (void) i2c_algo_dp_aux_stop(adapter, false);
210*4882a593Smuzhiyun }
211*4882a593Smuzhiyun
212*4882a593Smuzhiyun static int
i2c_dp_aux_prepare_bus(struct i2c_adapter * adapter)213*4882a593Smuzhiyun i2c_dp_aux_prepare_bus(struct i2c_adapter *adapter)
214*4882a593Smuzhiyun {
215*4882a593Smuzhiyun adapter->algo = &i2c_dp_aux_algo;
216*4882a593Smuzhiyun adapter->retries = 3;
217*4882a593Smuzhiyun i2c_dp_aux_reset_bus(adapter);
218*4882a593Smuzhiyun return 0;
219*4882a593Smuzhiyun }
220*4882a593Smuzhiyun
221*4882a593Smuzhiyun /*
222*4882a593Smuzhiyun * FIXME: This is the old dp aux helper, gma500 is the last driver that needs to
223*4882a593Smuzhiyun * be ported over to the new helper code in drm_dp_helper.c like i915 or radeon.
224*4882a593Smuzhiyun */
225*4882a593Smuzhiyun static int
i2c_dp_aux_add_bus(struct i2c_adapter * adapter)226*4882a593Smuzhiyun i2c_dp_aux_add_bus(struct i2c_adapter *adapter)
227*4882a593Smuzhiyun {
228*4882a593Smuzhiyun int error;
229*4882a593Smuzhiyun
230*4882a593Smuzhiyun error = i2c_dp_aux_prepare_bus(adapter);
231*4882a593Smuzhiyun if (error)
232*4882a593Smuzhiyun return error;
233*4882a593Smuzhiyun error = i2c_add_adapter(adapter);
234*4882a593Smuzhiyun return error;
235*4882a593Smuzhiyun }
236*4882a593Smuzhiyun
237*4882a593Smuzhiyun #define _wait_for(COND, MS, W) ({ \
238*4882a593Smuzhiyun unsigned long timeout__ = jiffies + msecs_to_jiffies(MS); \
239*4882a593Smuzhiyun int ret__ = 0; \
240*4882a593Smuzhiyun while (! (COND)) { \
241*4882a593Smuzhiyun if (time_after(jiffies, timeout__)) { \
242*4882a593Smuzhiyun ret__ = -ETIMEDOUT; \
243*4882a593Smuzhiyun break; \
244*4882a593Smuzhiyun } \
245*4882a593Smuzhiyun if (W && !in_dbg_master()) msleep(W); \
246*4882a593Smuzhiyun } \
247*4882a593Smuzhiyun ret__; \
248*4882a593Smuzhiyun })
249*4882a593Smuzhiyun
250*4882a593Smuzhiyun #define wait_for(COND, MS) _wait_for(COND, MS, 1)
251*4882a593Smuzhiyun
252*4882a593Smuzhiyun #define DP_LINK_CHECK_TIMEOUT (10 * 1000)
253*4882a593Smuzhiyun
254*4882a593Smuzhiyun #define DP_LINK_CONFIGURATION_SIZE 9
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun #define CDV_FAST_LINK_TRAIN 1
257*4882a593Smuzhiyun
258*4882a593Smuzhiyun struct cdv_intel_dp {
259*4882a593Smuzhiyun uint32_t output_reg;
260*4882a593Smuzhiyun uint32_t DP;
261*4882a593Smuzhiyun uint8_t link_configuration[DP_LINK_CONFIGURATION_SIZE];
262*4882a593Smuzhiyun bool has_audio;
263*4882a593Smuzhiyun int force_audio;
264*4882a593Smuzhiyun uint32_t color_range;
265*4882a593Smuzhiyun uint8_t link_bw;
266*4882a593Smuzhiyun uint8_t lane_count;
267*4882a593Smuzhiyun uint8_t dpcd[4];
268*4882a593Smuzhiyun struct gma_encoder *encoder;
269*4882a593Smuzhiyun struct i2c_adapter adapter;
270*4882a593Smuzhiyun struct i2c_algo_dp_aux_data algo;
271*4882a593Smuzhiyun uint8_t train_set[4];
272*4882a593Smuzhiyun uint8_t link_status[DP_LINK_STATUS_SIZE];
273*4882a593Smuzhiyun int panel_power_up_delay;
274*4882a593Smuzhiyun int panel_power_down_delay;
275*4882a593Smuzhiyun int panel_power_cycle_delay;
276*4882a593Smuzhiyun int backlight_on_delay;
277*4882a593Smuzhiyun int backlight_off_delay;
278*4882a593Smuzhiyun struct drm_display_mode *panel_fixed_mode; /* for eDP */
279*4882a593Smuzhiyun bool panel_on;
280*4882a593Smuzhiyun };
281*4882a593Smuzhiyun
282*4882a593Smuzhiyun struct ddi_regoff {
283*4882a593Smuzhiyun uint32_t PreEmph1;
284*4882a593Smuzhiyun uint32_t PreEmph2;
285*4882a593Smuzhiyun uint32_t VSwing1;
286*4882a593Smuzhiyun uint32_t VSwing2;
287*4882a593Smuzhiyun uint32_t VSwing3;
288*4882a593Smuzhiyun uint32_t VSwing4;
289*4882a593Smuzhiyun uint32_t VSwing5;
290*4882a593Smuzhiyun };
291*4882a593Smuzhiyun
292*4882a593Smuzhiyun static struct ddi_regoff ddi_DP_train_table[] = {
293*4882a593Smuzhiyun {.PreEmph1 = 0x812c, .PreEmph2 = 0x8124, .VSwing1 = 0x8154,
294*4882a593Smuzhiyun .VSwing2 = 0x8148, .VSwing3 = 0x814C, .VSwing4 = 0x8150,
295*4882a593Smuzhiyun .VSwing5 = 0x8158,},
296*4882a593Smuzhiyun {.PreEmph1 = 0x822c, .PreEmph2 = 0x8224, .VSwing1 = 0x8254,
297*4882a593Smuzhiyun .VSwing2 = 0x8248, .VSwing3 = 0x824C, .VSwing4 = 0x8250,
298*4882a593Smuzhiyun .VSwing5 = 0x8258,},
299*4882a593Smuzhiyun };
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun static uint32_t dp_vswing_premph_table[] = {
302*4882a593Smuzhiyun 0x55338954, 0x4000,
303*4882a593Smuzhiyun 0x554d8954, 0x2000,
304*4882a593Smuzhiyun 0x55668954, 0,
305*4882a593Smuzhiyun 0x559ac0d4, 0x6000,
306*4882a593Smuzhiyun };
307*4882a593Smuzhiyun /**
308*4882a593Smuzhiyun * is_edp - is the given port attached to an eDP panel (either CPU or PCH)
309*4882a593Smuzhiyun * @intel_dp: DP struct
310*4882a593Smuzhiyun *
311*4882a593Smuzhiyun * If a CPU or PCH DP output is attached to an eDP panel, this function
312*4882a593Smuzhiyun * will return true, and false otherwise.
313*4882a593Smuzhiyun */
is_edp(struct gma_encoder * encoder)314*4882a593Smuzhiyun static bool is_edp(struct gma_encoder *encoder)
315*4882a593Smuzhiyun {
316*4882a593Smuzhiyun return encoder->type == INTEL_OUTPUT_EDP;
317*4882a593Smuzhiyun }
318*4882a593Smuzhiyun
319*4882a593Smuzhiyun
320*4882a593Smuzhiyun static void cdv_intel_dp_start_link_train(struct gma_encoder *encoder);
321*4882a593Smuzhiyun static void cdv_intel_dp_complete_link_train(struct gma_encoder *encoder);
322*4882a593Smuzhiyun static void cdv_intel_dp_link_down(struct gma_encoder *encoder);
323*4882a593Smuzhiyun
324*4882a593Smuzhiyun static int
cdv_intel_dp_max_lane_count(struct gma_encoder * encoder)325*4882a593Smuzhiyun cdv_intel_dp_max_lane_count(struct gma_encoder *encoder)
326*4882a593Smuzhiyun {
327*4882a593Smuzhiyun struct cdv_intel_dp *intel_dp = encoder->dev_priv;
328*4882a593Smuzhiyun int max_lane_count = 4;
329*4882a593Smuzhiyun
330*4882a593Smuzhiyun if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11) {
331*4882a593Smuzhiyun max_lane_count = intel_dp->dpcd[DP_MAX_LANE_COUNT] & 0x1f;
332*4882a593Smuzhiyun switch (max_lane_count) {
333*4882a593Smuzhiyun case 1: case 2: case 4:
334*4882a593Smuzhiyun break;
335*4882a593Smuzhiyun default:
336*4882a593Smuzhiyun max_lane_count = 4;
337*4882a593Smuzhiyun }
338*4882a593Smuzhiyun }
339*4882a593Smuzhiyun return max_lane_count;
340*4882a593Smuzhiyun }
341*4882a593Smuzhiyun
342*4882a593Smuzhiyun static int
cdv_intel_dp_max_link_bw(struct gma_encoder * encoder)343*4882a593Smuzhiyun cdv_intel_dp_max_link_bw(struct gma_encoder *encoder)
344*4882a593Smuzhiyun {
345*4882a593Smuzhiyun struct cdv_intel_dp *intel_dp = encoder->dev_priv;
346*4882a593Smuzhiyun int max_link_bw = intel_dp->dpcd[DP_MAX_LINK_RATE];
347*4882a593Smuzhiyun
348*4882a593Smuzhiyun switch (max_link_bw) {
349*4882a593Smuzhiyun case DP_LINK_BW_1_62:
350*4882a593Smuzhiyun case DP_LINK_BW_2_7:
351*4882a593Smuzhiyun break;
352*4882a593Smuzhiyun default:
353*4882a593Smuzhiyun max_link_bw = DP_LINK_BW_1_62;
354*4882a593Smuzhiyun break;
355*4882a593Smuzhiyun }
356*4882a593Smuzhiyun return max_link_bw;
357*4882a593Smuzhiyun }
358*4882a593Smuzhiyun
359*4882a593Smuzhiyun static int
cdv_intel_dp_link_clock(uint8_t link_bw)360*4882a593Smuzhiyun cdv_intel_dp_link_clock(uint8_t link_bw)
361*4882a593Smuzhiyun {
362*4882a593Smuzhiyun if (link_bw == DP_LINK_BW_2_7)
363*4882a593Smuzhiyun return 270000;
364*4882a593Smuzhiyun else
365*4882a593Smuzhiyun return 162000;
366*4882a593Smuzhiyun }
367*4882a593Smuzhiyun
368*4882a593Smuzhiyun static int
cdv_intel_dp_link_required(int pixel_clock,int bpp)369*4882a593Smuzhiyun cdv_intel_dp_link_required(int pixel_clock, int bpp)
370*4882a593Smuzhiyun {
371*4882a593Smuzhiyun return (pixel_clock * bpp + 7) / 8;
372*4882a593Smuzhiyun }
373*4882a593Smuzhiyun
374*4882a593Smuzhiyun static int
cdv_intel_dp_max_data_rate(int max_link_clock,int max_lanes)375*4882a593Smuzhiyun cdv_intel_dp_max_data_rate(int max_link_clock, int max_lanes)
376*4882a593Smuzhiyun {
377*4882a593Smuzhiyun return (max_link_clock * max_lanes * 19) / 20;
378*4882a593Smuzhiyun }
379*4882a593Smuzhiyun
cdv_intel_edp_panel_vdd_on(struct gma_encoder * intel_encoder)380*4882a593Smuzhiyun static void cdv_intel_edp_panel_vdd_on(struct gma_encoder *intel_encoder)
381*4882a593Smuzhiyun {
382*4882a593Smuzhiyun struct drm_device *dev = intel_encoder->base.dev;
383*4882a593Smuzhiyun struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv;
384*4882a593Smuzhiyun u32 pp;
385*4882a593Smuzhiyun
386*4882a593Smuzhiyun if (intel_dp->panel_on) {
387*4882a593Smuzhiyun DRM_DEBUG_KMS("Skip VDD on because of panel on\n");
388*4882a593Smuzhiyun return;
389*4882a593Smuzhiyun }
390*4882a593Smuzhiyun DRM_DEBUG_KMS("\n");
391*4882a593Smuzhiyun
392*4882a593Smuzhiyun pp = REG_READ(PP_CONTROL);
393*4882a593Smuzhiyun
394*4882a593Smuzhiyun pp |= EDP_FORCE_VDD;
395*4882a593Smuzhiyun REG_WRITE(PP_CONTROL, pp);
396*4882a593Smuzhiyun REG_READ(PP_CONTROL);
397*4882a593Smuzhiyun msleep(intel_dp->panel_power_up_delay);
398*4882a593Smuzhiyun }
399*4882a593Smuzhiyun
cdv_intel_edp_panel_vdd_off(struct gma_encoder * intel_encoder)400*4882a593Smuzhiyun static void cdv_intel_edp_panel_vdd_off(struct gma_encoder *intel_encoder)
401*4882a593Smuzhiyun {
402*4882a593Smuzhiyun struct drm_device *dev = intel_encoder->base.dev;
403*4882a593Smuzhiyun u32 pp;
404*4882a593Smuzhiyun
405*4882a593Smuzhiyun DRM_DEBUG_KMS("\n");
406*4882a593Smuzhiyun pp = REG_READ(PP_CONTROL);
407*4882a593Smuzhiyun
408*4882a593Smuzhiyun pp &= ~EDP_FORCE_VDD;
409*4882a593Smuzhiyun REG_WRITE(PP_CONTROL, pp);
410*4882a593Smuzhiyun REG_READ(PP_CONTROL);
411*4882a593Smuzhiyun
412*4882a593Smuzhiyun }
413*4882a593Smuzhiyun
414*4882a593Smuzhiyun /* Returns true if the panel was already on when called */
cdv_intel_edp_panel_on(struct gma_encoder * intel_encoder)415*4882a593Smuzhiyun static bool cdv_intel_edp_panel_on(struct gma_encoder *intel_encoder)
416*4882a593Smuzhiyun {
417*4882a593Smuzhiyun struct drm_device *dev = intel_encoder->base.dev;
418*4882a593Smuzhiyun struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv;
419*4882a593Smuzhiyun u32 pp, idle_on_mask = PP_ON | PP_SEQUENCE_NONE;
420*4882a593Smuzhiyun
421*4882a593Smuzhiyun if (intel_dp->panel_on)
422*4882a593Smuzhiyun return true;
423*4882a593Smuzhiyun
424*4882a593Smuzhiyun DRM_DEBUG_KMS("\n");
425*4882a593Smuzhiyun pp = REG_READ(PP_CONTROL);
426*4882a593Smuzhiyun pp &= ~PANEL_UNLOCK_MASK;
427*4882a593Smuzhiyun
428*4882a593Smuzhiyun pp |= (PANEL_UNLOCK_REGS | POWER_TARGET_ON);
429*4882a593Smuzhiyun REG_WRITE(PP_CONTROL, pp);
430*4882a593Smuzhiyun REG_READ(PP_CONTROL);
431*4882a593Smuzhiyun
432*4882a593Smuzhiyun if (wait_for(((REG_READ(PP_STATUS) & idle_on_mask) == idle_on_mask), 1000)) {
433*4882a593Smuzhiyun DRM_DEBUG_KMS("Error in Powering up eDP panel, status %x\n", REG_READ(PP_STATUS));
434*4882a593Smuzhiyun intel_dp->panel_on = false;
435*4882a593Smuzhiyun } else
436*4882a593Smuzhiyun intel_dp->panel_on = true;
437*4882a593Smuzhiyun msleep(intel_dp->panel_power_up_delay);
438*4882a593Smuzhiyun
439*4882a593Smuzhiyun return false;
440*4882a593Smuzhiyun }
441*4882a593Smuzhiyun
cdv_intel_edp_panel_off(struct gma_encoder * intel_encoder)442*4882a593Smuzhiyun static void cdv_intel_edp_panel_off (struct gma_encoder *intel_encoder)
443*4882a593Smuzhiyun {
444*4882a593Smuzhiyun struct drm_device *dev = intel_encoder->base.dev;
445*4882a593Smuzhiyun u32 pp, idle_off_mask = PP_ON ;
446*4882a593Smuzhiyun struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv;
447*4882a593Smuzhiyun
448*4882a593Smuzhiyun DRM_DEBUG_KMS("\n");
449*4882a593Smuzhiyun
450*4882a593Smuzhiyun pp = REG_READ(PP_CONTROL);
451*4882a593Smuzhiyun
452*4882a593Smuzhiyun if ((pp & POWER_TARGET_ON) == 0)
453*4882a593Smuzhiyun return;
454*4882a593Smuzhiyun
455*4882a593Smuzhiyun intel_dp->panel_on = false;
456*4882a593Smuzhiyun pp &= ~PANEL_UNLOCK_MASK;
457*4882a593Smuzhiyun /* ILK workaround: disable reset around power sequence */
458*4882a593Smuzhiyun
459*4882a593Smuzhiyun pp &= ~POWER_TARGET_ON;
460*4882a593Smuzhiyun pp &= ~EDP_FORCE_VDD;
461*4882a593Smuzhiyun pp &= ~EDP_BLC_ENABLE;
462*4882a593Smuzhiyun REG_WRITE(PP_CONTROL, pp);
463*4882a593Smuzhiyun REG_READ(PP_CONTROL);
464*4882a593Smuzhiyun DRM_DEBUG_KMS("PP_STATUS %x\n", REG_READ(PP_STATUS));
465*4882a593Smuzhiyun
466*4882a593Smuzhiyun if (wait_for((REG_READ(PP_STATUS) & idle_off_mask) == 0, 1000)) {
467*4882a593Smuzhiyun DRM_DEBUG_KMS("Error in turning off Panel\n");
468*4882a593Smuzhiyun }
469*4882a593Smuzhiyun
470*4882a593Smuzhiyun msleep(intel_dp->panel_power_cycle_delay);
471*4882a593Smuzhiyun DRM_DEBUG_KMS("Over\n");
472*4882a593Smuzhiyun }
473*4882a593Smuzhiyun
cdv_intel_edp_backlight_on(struct gma_encoder * intel_encoder)474*4882a593Smuzhiyun static void cdv_intel_edp_backlight_on (struct gma_encoder *intel_encoder)
475*4882a593Smuzhiyun {
476*4882a593Smuzhiyun struct drm_device *dev = intel_encoder->base.dev;
477*4882a593Smuzhiyun u32 pp;
478*4882a593Smuzhiyun
479*4882a593Smuzhiyun DRM_DEBUG_KMS("\n");
480*4882a593Smuzhiyun /*
481*4882a593Smuzhiyun * If we enable the backlight right away following a panel power
482*4882a593Smuzhiyun * on, we may see slight flicker as the panel syncs with the eDP
483*4882a593Smuzhiyun * link. So delay a bit to make sure the image is solid before
484*4882a593Smuzhiyun * allowing it to appear.
485*4882a593Smuzhiyun */
486*4882a593Smuzhiyun msleep(300);
487*4882a593Smuzhiyun pp = REG_READ(PP_CONTROL);
488*4882a593Smuzhiyun
489*4882a593Smuzhiyun pp |= EDP_BLC_ENABLE;
490*4882a593Smuzhiyun REG_WRITE(PP_CONTROL, pp);
491*4882a593Smuzhiyun gma_backlight_enable(dev);
492*4882a593Smuzhiyun }
493*4882a593Smuzhiyun
cdv_intel_edp_backlight_off(struct gma_encoder * intel_encoder)494*4882a593Smuzhiyun static void cdv_intel_edp_backlight_off (struct gma_encoder *intel_encoder)
495*4882a593Smuzhiyun {
496*4882a593Smuzhiyun struct drm_device *dev = intel_encoder->base.dev;
497*4882a593Smuzhiyun struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv;
498*4882a593Smuzhiyun u32 pp;
499*4882a593Smuzhiyun
500*4882a593Smuzhiyun DRM_DEBUG_KMS("\n");
501*4882a593Smuzhiyun gma_backlight_disable(dev);
502*4882a593Smuzhiyun msleep(10);
503*4882a593Smuzhiyun pp = REG_READ(PP_CONTROL);
504*4882a593Smuzhiyun
505*4882a593Smuzhiyun pp &= ~EDP_BLC_ENABLE;
506*4882a593Smuzhiyun REG_WRITE(PP_CONTROL, pp);
507*4882a593Smuzhiyun msleep(intel_dp->backlight_off_delay);
508*4882a593Smuzhiyun }
509*4882a593Smuzhiyun
510*4882a593Smuzhiyun static enum drm_mode_status
cdv_intel_dp_mode_valid(struct drm_connector * connector,struct drm_display_mode * mode)511*4882a593Smuzhiyun cdv_intel_dp_mode_valid(struct drm_connector *connector,
512*4882a593Smuzhiyun struct drm_display_mode *mode)
513*4882a593Smuzhiyun {
514*4882a593Smuzhiyun struct gma_encoder *encoder = gma_attached_encoder(connector);
515*4882a593Smuzhiyun struct cdv_intel_dp *intel_dp = encoder->dev_priv;
516*4882a593Smuzhiyun int max_link_clock = cdv_intel_dp_link_clock(cdv_intel_dp_max_link_bw(encoder));
517*4882a593Smuzhiyun int max_lanes = cdv_intel_dp_max_lane_count(encoder);
518*4882a593Smuzhiyun struct drm_psb_private *dev_priv = connector->dev->dev_private;
519*4882a593Smuzhiyun
520*4882a593Smuzhiyun if (is_edp(encoder) && intel_dp->panel_fixed_mode) {
521*4882a593Smuzhiyun if (mode->hdisplay > intel_dp->panel_fixed_mode->hdisplay)
522*4882a593Smuzhiyun return MODE_PANEL;
523*4882a593Smuzhiyun if (mode->vdisplay > intel_dp->panel_fixed_mode->vdisplay)
524*4882a593Smuzhiyun return MODE_PANEL;
525*4882a593Smuzhiyun }
526*4882a593Smuzhiyun
527*4882a593Smuzhiyun /* only refuse the mode on non eDP since we have seen some weird eDP panels
528*4882a593Smuzhiyun which are outside spec tolerances but somehow work by magic */
529*4882a593Smuzhiyun if (!is_edp(encoder) &&
530*4882a593Smuzhiyun (cdv_intel_dp_link_required(mode->clock, dev_priv->edp.bpp)
531*4882a593Smuzhiyun > cdv_intel_dp_max_data_rate(max_link_clock, max_lanes)))
532*4882a593Smuzhiyun return MODE_CLOCK_HIGH;
533*4882a593Smuzhiyun
534*4882a593Smuzhiyun if (is_edp(encoder)) {
535*4882a593Smuzhiyun if (cdv_intel_dp_link_required(mode->clock, 24)
536*4882a593Smuzhiyun > cdv_intel_dp_max_data_rate(max_link_clock, max_lanes))
537*4882a593Smuzhiyun return MODE_CLOCK_HIGH;
538*4882a593Smuzhiyun
539*4882a593Smuzhiyun }
540*4882a593Smuzhiyun if (mode->clock < 10000)
541*4882a593Smuzhiyun return MODE_CLOCK_LOW;
542*4882a593Smuzhiyun
543*4882a593Smuzhiyun return MODE_OK;
544*4882a593Smuzhiyun }
545*4882a593Smuzhiyun
546*4882a593Smuzhiyun static uint32_t
pack_aux(uint8_t * src,int src_bytes)547*4882a593Smuzhiyun pack_aux(uint8_t *src, int src_bytes)
548*4882a593Smuzhiyun {
549*4882a593Smuzhiyun int i;
550*4882a593Smuzhiyun uint32_t v = 0;
551*4882a593Smuzhiyun
552*4882a593Smuzhiyun if (src_bytes > 4)
553*4882a593Smuzhiyun src_bytes = 4;
554*4882a593Smuzhiyun for (i = 0; i < src_bytes; i++)
555*4882a593Smuzhiyun v |= ((uint32_t) src[i]) << ((3-i) * 8);
556*4882a593Smuzhiyun return v;
557*4882a593Smuzhiyun }
558*4882a593Smuzhiyun
559*4882a593Smuzhiyun static void
unpack_aux(uint32_t src,uint8_t * dst,int dst_bytes)560*4882a593Smuzhiyun unpack_aux(uint32_t src, uint8_t *dst, int dst_bytes)
561*4882a593Smuzhiyun {
562*4882a593Smuzhiyun int i;
563*4882a593Smuzhiyun if (dst_bytes > 4)
564*4882a593Smuzhiyun dst_bytes = 4;
565*4882a593Smuzhiyun for (i = 0; i < dst_bytes; i++)
566*4882a593Smuzhiyun dst[i] = src >> ((3-i) * 8);
567*4882a593Smuzhiyun }
568*4882a593Smuzhiyun
569*4882a593Smuzhiyun static int
cdv_intel_dp_aux_ch(struct gma_encoder * encoder,uint8_t * send,int send_bytes,uint8_t * recv,int recv_size)570*4882a593Smuzhiyun cdv_intel_dp_aux_ch(struct gma_encoder *encoder,
571*4882a593Smuzhiyun uint8_t *send, int send_bytes,
572*4882a593Smuzhiyun uint8_t *recv, int recv_size)
573*4882a593Smuzhiyun {
574*4882a593Smuzhiyun struct cdv_intel_dp *intel_dp = encoder->dev_priv;
575*4882a593Smuzhiyun uint32_t output_reg = intel_dp->output_reg;
576*4882a593Smuzhiyun struct drm_device *dev = encoder->base.dev;
577*4882a593Smuzhiyun uint32_t ch_ctl = output_reg + 0x10;
578*4882a593Smuzhiyun uint32_t ch_data = ch_ctl + 4;
579*4882a593Smuzhiyun int i;
580*4882a593Smuzhiyun int recv_bytes;
581*4882a593Smuzhiyun uint32_t status;
582*4882a593Smuzhiyun uint32_t aux_clock_divider;
583*4882a593Smuzhiyun int try, precharge;
584*4882a593Smuzhiyun
585*4882a593Smuzhiyun /* The clock divider is based off the hrawclk,
586*4882a593Smuzhiyun * and would like to run at 2MHz. So, take the
587*4882a593Smuzhiyun * hrawclk value and divide by 2 and use that
588*4882a593Smuzhiyun * On CDV platform it uses 200MHz as hrawclk.
589*4882a593Smuzhiyun *
590*4882a593Smuzhiyun */
591*4882a593Smuzhiyun aux_clock_divider = 200 / 2;
592*4882a593Smuzhiyun
593*4882a593Smuzhiyun precharge = 4;
594*4882a593Smuzhiyun if (is_edp(encoder))
595*4882a593Smuzhiyun precharge = 10;
596*4882a593Smuzhiyun
597*4882a593Smuzhiyun if (REG_READ(ch_ctl) & DP_AUX_CH_CTL_SEND_BUSY) {
598*4882a593Smuzhiyun DRM_ERROR("dp_aux_ch not started status 0x%08x\n",
599*4882a593Smuzhiyun REG_READ(ch_ctl));
600*4882a593Smuzhiyun return -EBUSY;
601*4882a593Smuzhiyun }
602*4882a593Smuzhiyun
603*4882a593Smuzhiyun /* Must try at least 3 times according to DP spec */
604*4882a593Smuzhiyun for (try = 0; try < 5; try++) {
605*4882a593Smuzhiyun /* Load the send data into the aux channel data registers */
606*4882a593Smuzhiyun for (i = 0; i < send_bytes; i += 4)
607*4882a593Smuzhiyun REG_WRITE(ch_data + i,
608*4882a593Smuzhiyun pack_aux(send + i, send_bytes - i));
609*4882a593Smuzhiyun
610*4882a593Smuzhiyun /* Send the command and wait for it to complete */
611*4882a593Smuzhiyun REG_WRITE(ch_ctl,
612*4882a593Smuzhiyun DP_AUX_CH_CTL_SEND_BUSY |
613*4882a593Smuzhiyun DP_AUX_CH_CTL_TIME_OUT_400us |
614*4882a593Smuzhiyun (send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) |
615*4882a593Smuzhiyun (precharge << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) |
616*4882a593Smuzhiyun (aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT) |
617*4882a593Smuzhiyun DP_AUX_CH_CTL_DONE |
618*4882a593Smuzhiyun DP_AUX_CH_CTL_TIME_OUT_ERROR |
619*4882a593Smuzhiyun DP_AUX_CH_CTL_RECEIVE_ERROR);
620*4882a593Smuzhiyun for (;;) {
621*4882a593Smuzhiyun status = REG_READ(ch_ctl);
622*4882a593Smuzhiyun if ((status & DP_AUX_CH_CTL_SEND_BUSY) == 0)
623*4882a593Smuzhiyun break;
624*4882a593Smuzhiyun udelay(100);
625*4882a593Smuzhiyun }
626*4882a593Smuzhiyun
627*4882a593Smuzhiyun /* Clear done status and any errors */
628*4882a593Smuzhiyun REG_WRITE(ch_ctl,
629*4882a593Smuzhiyun status |
630*4882a593Smuzhiyun DP_AUX_CH_CTL_DONE |
631*4882a593Smuzhiyun DP_AUX_CH_CTL_TIME_OUT_ERROR |
632*4882a593Smuzhiyun DP_AUX_CH_CTL_RECEIVE_ERROR);
633*4882a593Smuzhiyun if (status & DP_AUX_CH_CTL_DONE)
634*4882a593Smuzhiyun break;
635*4882a593Smuzhiyun }
636*4882a593Smuzhiyun
637*4882a593Smuzhiyun if ((status & DP_AUX_CH_CTL_DONE) == 0) {
638*4882a593Smuzhiyun DRM_ERROR("dp_aux_ch not done status 0x%08x\n", status);
639*4882a593Smuzhiyun return -EBUSY;
640*4882a593Smuzhiyun }
641*4882a593Smuzhiyun
642*4882a593Smuzhiyun /* Check for timeout or receive error.
643*4882a593Smuzhiyun * Timeouts occur when the sink is not connected
644*4882a593Smuzhiyun */
645*4882a593Smuzhiyun if (status & DP_AUX_CH_CTL_RECEIVE_ERROR) {
646*4882a593Smuzhiyun DRM_ERROR("dp_aux_ch receive error status 0x%08x\n", status);
647*4882a593Smuzhiyun return -EIO;
648*4882a593Smuzhiyun }
649*4882a593Smuzhiyun
650*4882a593Smuzhiyun /* Timeouts occur when the device isn't connected, so they're
651*4882a593Smuzhiyun * "normal" -- don't fill the kernel log with these */
652*4882a593Smuzhiyun if (status & DP_AUX_CH_CTL_TIME_OUT_ERROR) {
653*4882a593Smuzhiyun DRM_DEBUG_KMS("dp_aux_ch timeout status 0x%08x\n", status);
654*4882a593Smuzhiyun return -ETIMEDOUT;
655*4882a593Smuzhiyun }
656*4882a593Smuzhiyun
657*4882a593Smuzhiyun /* Unload any bytes sent back from the other side */
658*4882a593Smuzhiyun recv_bytes = ((status & DP_AUX_CH_CTL_MESSAGE_SIZE_MASK) >>
659*4882a593Smuzhiyun DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT);
660*4882a593Smuzhiyun if (recv_bytes > recv_size)
661*4882a593Smuzhiyun recv_bytes = recv_size;
662*4882a593Smuzhiyun
663*4882a593Smuzhiyun for (i = 0; i < recv_bytes; i += 4)
664*4882a593Smuzhiyun unpack_aux(REG_READ(ch_data + i),
665*4882a593Smuzhiyun recv + i, recv_bytes - i);
666*4882a593Smuzhiyun
667*4882a593Smuzhiyun return recv_bytes;
668*4882a593Smuzhiyun }
669*4882a593Smuzhiyun
670*4882a593Smuzhiyun /* Write data to the aux channel in native mode */
671*4882a593Smuzhiyun static int
cdv_intel_dp_aux_native_write(struct gma_encoder * encoder,uint16_t address,uint8_t * send,int send_bytes)672*4882a593Smuzhiyun cdv_intel_dp_aux_native_write(struct gma_encoder *encoder,
673*4882a593Smuzhiyun uint16_t address, uint8_t *send, int send_bytes)
674*4882a593Smuzhiyun {
675*4882a593Smuzhiyun int ret;
676*4882a593Smuzhiyun uint8_t msg[20];
677*4882a593Smuzhiyun int msg_bytes;
678*4882a593Smuzhiyun uint8_t ack;
679*4882a593Smuzhiyun
680*4882a593Smuzhiyun if (send_bytes > 16)
681*4882a593Smuzhiyun return -1;
682*4882a593Smuzhiyun msg[0] = DP_AUX_NATIVE_WRITE << 4;
683*4882a593Smuzhiyun msg[1] = address >> 8;
684*4882a593Smuzhiyun msg[2] = address & 0xff;
685*4882a593Smuzhiyun msg[3] = send_bytes - 1;
686*4882a593Smuzhiyun memcpy(&msg[4], send, send_bytes);
687*4882a593Smuzhiyun msg_bytes = send_bytes + 4;
688*4882a593Smuzhiyun for (;;) {
689*4882a593Smuzhiyun ret = cdv_intel_dp_aux_ch(encoder, msg, msg_bytes, &ack, 1);
690*4882a593Smuzhiyun if (ret < 0)
691*4882a593Smuzhiyun return ret;
692*4882a593Smuzhiyun ack >>= 4;
693*4882a593Smuzhiyun if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_ACK)
694*4882a593Smuzhiyun break;
695*4882a593Smuzhiyun else if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_DEFER)
696*4882a593Smuzhiyun udelay(100);
697*4882a593Smuzhiyun else
698*4882a593Smuzhiyun return -EIO;
699*4882a593Smuzhiyun }
700*4882a593Smuzhiyun return send_bytes;
701*4882a593Smuzhiyun }
702*4882a593Smuzhiyun
703*4882a593Smuzhiyun /* Write a single byte to the aux channel in native mode */
704*4882a593Smuzhiyun static int
cdv_intel_dp_aux_native_write_1(struct gma_encoder * encoder,uint16_t address,uint8_t byte)705*4882a593Smuzhiyun cdv_intel_dp_aux_native_write_1(struct gma_encoder *encoder,
706*4882a593Smuzhiyun uint16_t address, uint8_t byte)
707*4882a593Smuzhiyun {
708*4882a593Smuzhiyun return cdv_intel_dp_aux_native_write(encoder, address, &byte, 1);
709*4882a593Smuzhiyun }
710*4882a593Smuzhiyun
711*4882a593Smuzhiyun /* read bytes from a native aux channel */
712*4882a593Smuzhiyun static int
cdv_intel_dp_aux_native_read(struct gma_encoder * encoder,uint16_t address,uint8_t * recv,int recv_bytes)713*4882a593Smuzhiyun cdv_intel_dp_aux_native_read(struct gma_encoder *encoder,
714*4882a593Smuzhiyun uint16_t address, uint8_t *recv, int recv_bytes)
715*4882a593Smuzhiyun {
716*4882a593Smuzhiyun uint8_t msg[4];
717*4882a593Smuzhiyun int msg_bytes;
718*4882a593Smuzhiyun uint8_t reply[20];
719*4882a593Smuzhiyun int reply_bytes;
720*4882a593Smuzhiyun uint8_t ack;
721*4882a593Smuzhiyun int ret;
722*4882a593Smuzhiyun
723*4882a593Smuzhiyun msg[0] = DP_AUX_NATIVE_READ << 4;
724*4882a593Smuzhiyun msg[1] = address >> 8;
725*4882a593Smuzhiyun msg[2] = address & 0xff;
726*4882a593Smuzhiyun msg[3] = recv_bytes - 1;
727*4882a593Smuzhiyun
728*4882a593Smuzhiyun msg_bytes = 4;
729*4882a593Smuzhiyun reply_bytes = recv_bytes + 1;
730*4882a593Smuzhiyun
731*4882a593Smuzhiyun for (;;) {
732*4882a593Smuzhiyun ret = cdv_intel_dp_aux_ch(encoder, msg, msg_bytes,
733*4882a593Smuzhiyun reply, reply_bytes);
734*4882a593Smuzhiyun if (ret == 0)
735*4882a593Smuzhiyun return -EPROTO;
736*4882a593Smuzhiyun if (ret < 0)
737*4882a593Smuzhiyun return ret;
738*4882a593Smuzhiyun ack = reply[0] >> 4;
739*4882a593Smuzhiyun if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_ACK) {
740*4882a593Smuzhiyun memcpy(recv, reply + 1, ret - 1);
741*4882a593Smuzhiyun return ret - 1;
742*4882a593Smuzhiyun }
743*4882a593Smuzhiyun else if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_DEFER)
744*4882a593Smuzhiyun udelay(100);
745*4882a593Smuzhiyun else
746*4882a593Smuzhiyun return -EIO;
747*4882a593Smuzhiyun }
748*4882a593Smuzhiyun }
749*4882a593Smuzhiyun
750*4882a593Smuzhiyun static int
cdv_intel_dp_i2c_aux_ch(struct i2c_adapter * adapter,int mode,uint8_t write_byte,uint8_t * read_byte)751*4882a593Smuzhiyun cdv_intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
752*4882a593Smuzhiyun uint8_t write_byte, uint8_t *read_byte)
753*4882a593Smuzhiyun {
754*4882a593Smuzhiyun struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
755*4882a593Smuzhiyun struct cdv_intel_dp *intel_dp = container_of(adapter,
756*4882a593Smuzhiyun struct cdv_intel_dp,
757*4882a593Smuzhiyun adapter);
758*4882a593Smuzhiyun struct gma_encoder *encoder = intel_dp->encoder;
759*4882a593Smuzhiyun uint16_t address = algo_data->address;
760*4882a593Smuzhiyun uint8_t msg[5];
761*4882a593Smuzhiyun uint8_t reply[2];
762*4882a593Smuzhiyun unsigned retry;
763*4882a593Smuzhiyun int msg_bytes;
764*4882a593Smuzhiyun int reply_bytes;
765*4882a593Smuzhiyun int ret;
766*4882a593Smuzhiyun
767*4882a593Smuzhiyun /* Set up the command byte */
768*4882a593Smuzhiyun if (mode & MODE_I2C_READ)
769*4882a593Smuzhiyun msg[0] = DP_AUX_I2C_READ << 4;
770*4882a593Smuzhiyun else
771*4882a593Smuzhiyun msg[0] = DP_AUX_I2C_WRITE << 4;
772*4882a593Smuzhiyun
773*4882a593Smuzhiyun if (!(mode & MODE_I2C_STOP))
774*4882a593Smuzhiyun msg[0] |= DP_AUX_I2C_MOT << 4;
775*4882a593Smuzhiyun
776*4882a593Smuzhiyun msg[1] = address >> 8;
777*4882a593Smuzhiyun msg[2] = address;
778*4882a593Smuzhiyun
779*4882a593Smuzhiyun switch (mode) {
780*4882a593Smuzhiyun case MODE_I2C_WRITE:
781*4882a593Smuzhiyun msg[3] = 0;
782*4882a593Smuzhiyun msg[4] = write_byte;
783*4882a593Smuzhiyun msg_bytes = 5;
784*4882a593Smuzhiyun reply_bytes = 1;
785*4882a593Smuzhiyun break;
786*4882a593Smuzhiyun case MODE_I2C_READ:
787*4882a593Smuzhiyun msg[3] = 0;
788*4882a593Smuzhiyun msg_bytes = 4;
789*4882a593Smuzhiyun reply_bytes = 2;
790*4882a593Smuzhiyun break;
791*4882a593Smuzhiyun default:
792*4882a593Smuzhiyun msg_bytes = 3;
793*4882a593Smuzhiyun reply_bytes = 1;
794*4882a593Smuzhiyun break;
795*4882a593Smuzhiyun }
796*4882a593Smuzhiyun
797*4882a593Smuzhiyun for (retry = 0; retry < 5; retry++) {
798*4882a593Smuzhiyun ret = cdv_intel_dp_aux_ch(encoder,
799*4882a593Smuzhiyun msg, msg_bytes,
800*4882a593Smuzhiyun reply, reply_bytes);
801*4882a593Smuzhiyun if (ret < 0) {
802*4882a593Smuzhiyun DRM_DEBUG_KMS("aux_ch failed %d\n", ret);
803*4882a593Smuzhiyun return ret;
804*4882a593Smuzhiyun }
805*4882a593Smuzhiyun
806*4882a593Smuzhiyun switch ((reply[0] >> 4) & DP_AUX_NATIVE_REPLY_MASK) {
807*4882a593Smuzhiyun case DP_AUX_NATIVE_REPLY_ACK:
808*4882a593Smuzhiyun /* I2C-over-AUX Reply field is only valid
809*4882a593Smuzhiyun * when paired with AUX ACK.
810*4882a593Smuzhiyun */
811*4882a593Smuzhiyun break;
812*4882a593Smuzhiyun case DP_AUX_NATIVE_REPLY_NACK:
813*4882a593Smuzhiyun DRM_DEBUG_KMS("aux_ch native nack\n");
814*4882a593Smuzhiyun return -EREMOTEIO;
815*4882a593Smuzhiyun case DP_AUX_NATIVE_REPLY_DEFER:
816*4882a593Smuzhiyun udelay(100);
817*4882a593Smuzhiyun continue;
818*4882a593Smuzhiyun default:
819*4882a593Smuzhiyun DRM_ERROR("aux_ch invalid native reply 0x%02x\n",
820*4882a593Smuzhiyun reply[0]);
821*4882a593Smuzhiyun return -EREMOTEIO;
822*4882a593Smuzhiyun }
823*4882a593Smuzhiyun
824*4882a593Smuzhiyun switch ((reply[0] >> 4) & DP_AUX_I2C_REPLY_MASK) {
825*4882a593Smuzhiyun case DP_AUX_I2C_REPLY_ACK:
826*4882a593Smuzhiyun if (mode == MODE_I2C_READ) {
827*4882a593Smuzhiyun *read_byte = reply[1];
828*4882a593Smuzhiyun }
829*4882a593Smuzhiyun return reply_bytes - 1;
830*4882a593Smuzhiyun case DP_AUX_I2C_REPLY_NACK:
831*4882a593Smuzhiyun DRM_DEBUG_KMS("aux_i2c nack\n");
832*4882a593Smuzhiyun return -EREMOTEIO;
833*4882a593Smuzhiyun case DP_AUX_I2C_REPLY_DEFER:
834*4882a593Smuzhiyun DRM_DEBUG_KMS("aux_i2c defer\n");
835*4882a593Smuzhiyun udelay(100);
836*4882a593Smuzhiyun break;
837*4882a593Smuzhiyun default:
838*4882a593Smuzhiyun DRM_ERROR("aux_i2c invalid reply 0x%02x\n", reply[0]);
839*4882a593Smuzhiyun return -EREMOTEIO;
840*4882a593Smuzhiyun }
841*4882a593Smuzhiyun }
842*4882a593Smuzhiyun
843*4882a593Smuzhiyun DRM_ERROR("too many retries, giving up\n");
844*4882a593Smuzhiyun return -EREMOTEIO;
845*4882a593Smuzhiyun }
846*4882a593Smuzhiyun
847*4882a593Smuzhiyun static int
cdv_intel_dp_i2c_init(struct gma_connector * connector,struct gma_encoder * encoder,const char * name)848*4882a593Smuzhiyun cdv_intel_dp_i2c_init(struct gma_connector *connector,
849*4882a593Smuzhiyun struct gma_encoder *encoder, const char *name)
850*4882a593Smuzhiyun {
851*4882a593Smuzhiyun struct cdv_intel_dp *intel_dp = encoder->dev_priv;
852*4882a593Smuzhiyun int ret;
853*4882a593Smuzhiyun
854*4882a593Smuzhiyun DRM_DEBUG_KMS("i2c_init %s\n", name);
855*4882a593Smuzhiyun
856*4882a593Smuzhiyun intel_dp->algo.running = false;
857*4882a593Smuzhiyun intel_dp->algo.address = 0;
858*4882a593Smuzhiyun intel_dp->algo.aux_ch = cdv_intel_dp_i2c_aux_ch;
859*4882a593Smuzhiyun
860*4882a593Smuzhiyun memset(&intel_dp->adapter, '\0', sizeof (intel_dp->adapter));
861*4882a593Smuzhiyun intel_dp->adapter.owner = THIS_MODULE;
862*4882a593Smuzhiyun intel_dp->adapter.class = I2C_CLASS_DDC;
863*4882a593Smuzhiyun strncpy (intel_dp->adapter.name, name, sizeof(intel_dp->adapter.name) - 1);
864*4882a593Smuzhiyun intel_dp->adapter.name[sizeof(intel_dp->adapter.name) - 1] = '\0';
865*4882a593Smuzhiyun intel_dp->adapter.algo_data = &intel_dp->algo;
866*4882a593Smuzhiyun intel_dp->adapter.dev.parent = connector->base.kdev;
867*4882a593Smuzhiyun
868*4882a593Smuzhiyun if (is_edp(encoder))
869*4882a593Smuzhiyun cdv_intel_edp_panel_vdd_on(encoder);
870*4882a593Smuzhiyun ret = i2c_dp_aux_add_bus(&intel_dp->adapter);
871*4882a593Smuzhiyun if (is_edp(encoder))
872*4882a593Smuzhiyun cdv_intel_edp_panel_vdd_off(encoder);
873*4882a593Smuzhiyun
874*4882a593Smuzhiyun return ret;
875*4882a593Smuzhiyun }
876*4882a593Smuzhiyun
cdv_intel_fixed_panel_mode(struct drm_display_mode * fixed_mode,struct drm_display_mode * adjusted_mode)877*4882a593Smuzhiyun static void cdv_intel_fixed_panel_mode(struct drm_display_mode *fixed_mode,
878*4882a593Smuzhiyun struct drm_display_mode *adjusted_mode)
879*4882a593Smuzhiyun {
880*4882a593Smuzhiyun adjusted_mode->hdisplay = fixed_mode->hdisplay;
881*4882a593Smuzhiyun adjusted_mode->hsync_start = fixed_mode->hsync_start;
882*4882a593Smuzhiyun adjusted_mode->hsync_end = fixed_mode->hsync_end;
883*4882a593Smuzhiyun adjusted_mode->htotal = fixed_mode->htotal;
884*4882a593Smuzhiyun
885*4882a593Smuzhiyun adjusted_mode->vdisplay = fixed_mode->vdisplay;
886*4882a593Smuzhiyun adjusted_mode->vsync_start = fixed_mode->vsync_start;
887*4882a593Smuzhiyun adjusted_mode->vsync_end = fixed_mode->vsync_end;
888*4882a593Smuzhiyun adjusted_mode->vtotal = fixed_mode->vtotal;
889*4882a593Smuzhiyun
890*4882a593Smuzhiyun adjusted_mode->clock = fixed_mode->clock;
891*4882a593Smuzhiyun
892*4882a593Smuzhiyun drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
893*4882a593Smuzhiyun }
894*4882a593Smuzhiyun
895*4882a593Smuzhiyun static bool
cdv_intel_dp_mode_fixup(struct drm_encoder * encoder,const struct drm_display_mode * mode,struct drm_display_mode * adjusted_mode)896*4882a593Smuzhiyun cdv_intel_dp_mode_fixup(struct drm_encoder *encoder, const struct drm_display_mode *mode,
897*4882a593Smuzhiyun struct drm_display_mode *adjusted_mode)
898*4882a593Smuzhiyun {
899*4882a593Smuzhiyun struct drm_psb_private *dev_priv = encoder->dev->dev_private;
900*4882a593Smuzhiyun struct gma_encoder *intel_encoder = to_gma_encoder(encoder);
901*4882a593Smuzhiyun struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv;
902*4882a593Smuzhiyun int lane_count, clock;
903*4882a593Smuzhiyun int max_lane_count = cdv_intel_dp_max_lane_count(intel_encoder);
904*4882a593Smuzhiyun int max_clock = cdv_intel_dp_max_link_bw(intel_encoder) == DP_LINK_BW_2_7 ? 1 : 0;
905*4882a593Smuzhiyun static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 };
906*4882a593Smuzhiyun int refclock = mode->clock;
907*4882a593Smuzhiyun int bpp = 24;
908*4882a593Smuzhiyun
909*4882a593Smuzhiyun if (is_edp(intel_encoder) && intel_dp->panel_fixed_mode) {
910*4882a593Smuzhiyun cdv_intel_fixed_panel_mode(intel_dp->panel_fixed_mode, adjusted_mode);
911*4882a593Smuzhiyun refclock = intel_dp->panel_fixed_mode->clock;
912*4882a593Smuzhiyun bpp = dev_priv->edp.bpp;
913*4882a593Smuzhiyun }
914*4882a593Smuzhiyun
915*4882a593Smuzhiyun for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) {
916*4882a593Smuzhiyun for (clock = max_clock; clock >= 0; clock--) {
917*4882a593Smuzhiyun int link_avail = cdv_intel_dp_max_data_rate(cdv_intel_dp_link_clock(bws[clock]), lane_count);
918*4882a593Smuzhiyun
919*4882a593Smuzhiyun if (cdv_intel_dp_link_required(refclock, bpp) <= link_avail) {
920*4882a593Smuzhiyun intel_dp->link_bw = bws[clock];
921*4882a593Smuzhiyun intel_dp->lane_count = lane_count;
922*4882a593Smuzhiyun adjusted_mode->clock = cdv_intel_dp_link_clock(intel_dp->link_bw);
923*4882a593Smuzhiyun DRM_DEBUG_KMS("Display port link bw %02x lane "
924*4882a593Smuzhiyun "count %d clock %d\n",
925*4882a593Smuzhiyun intel_dp->link_bw, intel_dp->lane_count,
926*4882a593Smuzhiyun adjusted_mode->clock);
927*4882a593Smuzhiyun return true;
928*4882a593Smuzhiyun }
929*4882a593Smuzhiyun }
930*4882a593Smuzhiyun }
931*4882a593Smuzhiyun if (is_edp(intel_encoder)) {
932*4882a593Smuzhiyun /* okay we failed just pick the highest */
933*4882a593Smuzhiyun intel_dp->lane_count = max_lane_count;
934*4882a593Smuzhiyun intel_dp->link_bw = bws[max_clock];
935*4882a593Smuzhiyun adjusted_mode->clock = cdv_intel_dp_link_clock(intel_dp->link_bw);
936*4882a593Smuzhiyun DRM_DEBUG_KMS("Force picking display port link bw %02x lane "
937*4882a593Smuzhiyun "count %d clock %d\n",
938*4882a593Smuzhiyun intel_dp->link_bw, intel_dp->lane_count,
939*4882a593Smuzhiyun adjusted_mode->clock);
940*4882a593Smuzhiyun
941*4882a593Smuzhiyun return true;
942*4882a593Smuzhiyun }
943*4882a593Smuzhiyun return false;
944*4882a593Smuzhiyun }
945*4882a593Smuzhiyun
946*4882a593Smuzhiyun struct cdv_intel_dp_m_n {
947*4882a593Smuzhiyun uint32_t tu;
948*4882a593Smuzhiyun uint32_t gmch_m;
949*4882a593Smuzhiyun uint32_t gmch_n;
950*4882a593Smuzhiyun uint32_t link_m;
951*4882a593Smuzhiyun uint32_t link_n;
952*4882a593Smuzhiyun };
953*4882a593Smuzhiyun
954*4882a593Smuzhiyun static void
cdv_intel_reduce_ratio(uint32_t * num,uint32_t * den)955*4882a593Smuzhiyun cdv_intel_reduce_ratio(uint32_t *num, uint32_t *den)
956*4882a593Smuzhiyun {
957*4882a593Smuzhiyun /*
958*4882a593Smuzhiyun while (*num > 0xffffff || *den > 0xffffff) {
959*4882a593Smuzhiyun *num >>= 1;
960*4882a593Smuzhiyun *den >>= 1;
961*4882a593Smuzhiyun }*/
962*4882a593Smuzhiyun uint64_t value, m;
963*4882a593Smuzhiyun m = *num;
964*4882a593Smuzhiyun value = m * (0x800000);
965*4882a593Smuzhiyun m = do_div(value, *den);
966*4882a593Smuzhiyun *num = value;
967*4882a593Smuzhiyun *den = 0x800000;
968*4882a593Smuzhiyun }
969*4882a593Smuzhiyun
970*4882a593Smuzhiyun static void
cdv_intel_dp_compute_m_n(int bpp,int nlanes,int pixel_clock,int link_clock,struct cdv_intel_dp_m_n * m_n)971*4882a593Smuzhiyun cdv_intel_dp_compute_m_n(int bpp,
972*4882a593Smuzhiyun int nlanes,
973*4882a593Smuzhiyun int pixel_clock,
974*4882a593Smuzhiyun int link_clock,
975*4882a593Smuzhiyun struct cdv_intel_dp_m_n *m_n)
976*4882a593Smuzhiyun {
977*4882a593Smuzhiyun m_n->tu = 64;
978*4882a593Smuzhiyun m_n->gmch_m = (pixel_clock * bpp + 7) >> 3;
979*4882a593Smuzhiyun m_n->gmch_n = link_clock * nlanes;
980*4882a593Smuzhiyun cdv_intel_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n);
981*4882a593Smuzhiyun m_n->link_m = pixel_clock;
982*4882a593Smuzhiyun m_n->link_n = link_clock;
983*4882a593Smuzhiyun cdv_intel_reduce_ratio(&m_n->link_m, &m_n->link_n);
984*4882a593Smuzhiyun }
985*4882a593Smuzhiyun
986*4882a593Smuzhiyun void
cdv_intel_dp_set_m_n(struct drm_crtc * crtc,struct drm_display_mode * mode,struct drm_display_mode * adjusted_mode)987*4882a593Smuzhiyun cdv_intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
988*4882a593Smuzhiyun struct drm_display_mode *adjusted_mode)
989*4882a593Smuzhiyun {
990*4882a593Smuzhiyun struct drm_device *dev = crtc->dev;
991*4882a593Smuzhiyun struct drm_psb_private *dev_priv = dev->dev_private;
992*4882a593Smuzhiyun struct drm_mode_config *mode_config = &dev->mode_config;
993*4882a593Smuzhiyun struct drm_encoder *encoder;
994*4882a593Smuzhiyun struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
995*4882a593Smuzhiyun int lane_count = 4, bpp = 24;
996*4882a593Smuzhiyun struct cdv_intel_dp_m_n m_n;
997*4882a593Smuzhiyun int pipe = gma_crtc->pipe;
998*4882a593Smuzhiyun
999*4882a593Smuzhiyun /*
1000*4882a593Smuzhiyun * Find the lane count in the intel_encoder private
1001*4882a593Smuzhiyun */
1002*4882a593Smuzhiyun list_for_each_entry(encoder, &mode_config->encoder_list, head) {
1003*4882a593Smuzhiyun struct gma_encoder *intel_encoder;
1004*4882a593Smuzhiyun struct cdv_intel_dp *intel_dp;
1005*4882a593Smuzhiyun
1006*4882a593Smuzhiyun if (encoder->crtc != crtc)
1007*4882a593Smuzhiyun continue;
1008*4882a593Smuzhiyun
1009*4882a593Smuzhiyun intel_encoder = to_gma_encoder(encoder);
1010*4882a593Smuzhiyun intel_dp = intel_encoder->dev_priv;
1011*4882a593Smuzhiyun if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT) {
1012*4882a593Smuzhiyun lane_count = intel_dp->lane_count;
1013*4882a593Smuzhiyun break;
1014*4882a593Smuzhiyun } else if (is_edp(intel_encoder)) {
1015*4882a593Smuzhiyun lane_count = intel_dp->lane_count;
1016*4882a593Smuzhiyun bpp = dev_priv->edp.bpp;
1017*4882a593Smuzhiyun break;
1018*4882a593Smuzhiyun }
1019*4882a593Smuzhiyun }
1020*4882a593Smuzhiyun
1021*4882a593Smuzhiyun /*
1022*4882a593Smuzhiyun * Compute the GMCH and Link ratios. The '3' here is
1023*4882a593Smuzhiyun * the number of bytes_per_pixel post-LUT, which we always
1024*4882a593Smuzhiyun * set up for 8-bits of R/G/B, or 3 bytes total.
1025*4882a593Smuzhiyun */
1026*4882a593Smuzhiyun cdv_intel_dp_compute_m_n(bpp, lane_count,
1027*4882a593Smuzhiyun mode->clock, adjusted_mode->clock, &m_n);
1028*4882a593Smuzhiyun
1029*4882a593Smuzhiyun {
1030*4882a593Smuzhiyun REG_WRITE(PIPE_GMCH_DATA_M(pipe),
1031*4882a593Smuzhiyun ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) |
1032*4882a593Smuzhiyun m_n.gmch_m);
1033*4882a593Smuzhiyun REG_WRITE(PIPE_GMCH_DATA_N(pipe), m_n.gmch_n);
1034*4882a593Smuzhiyun REG_WRITE(PIPE_DP_LINK_M(pipe), m_n.link_m);
1035*4882a593Smuzhiyun REG_WRITE(PIPE_DP_LINK_N(pipe), m_n.link_n);
1036*4882a593Smuzhiyun }
1037*4882a593Smuzhiyun }
1038*4882a593Smuzhiyun
1039*4882a593Smuzhiyun static void
cdv_intel_dp_mode_set(struct drm_encoder * encoder,struct drm_display_mode * mode,struct drm_display_mode * adjusted_mode)1040*4882a593Smuzhiyun cdv_intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
1041*4882a593Smuzhiyun struct drm_display_mode *adjusted_mode)
1042*4882a593Smuzhiyun {
1043*4882a593Smuzhiyun struct gma_encoder *intel_encoder = to_gma_encoder(encoder);
1044*4882a593Smuzhiyun struct drm_crtc *crtc = encoder->crtc;
1045*4882a593Smuzhiyun struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
1046*4882a593Smuzhiyun struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv;
1047*4882a593Smuzhiyun struct drm_device *dev = encoder->dev;
1048*4882a593Smuzhiyun
1049*4882a593Smuzhiyun intel_dp->DP = DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0;
1050*4882a593Smuzhiyun intel_dp->DP |= intel_dp->color_range;
1051*4882a593Smuzhiyun
1052*4882a593Smuzhiyun if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
1053*4882a593Smuzhiyun intel_dp->DP |= DP_SYNC_HS_HIGH;
1054*4882a593Smuzhiyun if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
1055*4882a593Smuzhiyun intel_dp->DP |= DP_SYNC_VS_HIGH;
1056*4882a593Smuzhiyun
1057*4882a593Smuzhiyun intel_dp->DP |= DP_LINK_TRAIN_OFF;
1058*4882a593Smuzhiyun
1059*4882a593Smuzhiyun switch (intel_dp->lane_count) {
1060*4882a593Smuzhiyun case 1:
1061*4882a593Smuzhiyun intel_dp->DP |= DP_PORT_WIDTH_1;
1062*4882a593Smuzhiyun break;
1063*4882a593Smuzhiyun case 2:
1064*4882a593Smuzhiyun intel_dp->DP |= DP_PORT_WIDTH_2;
1065*4882a593Smuzhiyun break;
1066*4882a593Smuzhiyun case 4:
1067*4882a593Smuzhiyun intel_dp->DP |= DP_PORT_WIDTH_4;
1068*4882a593Smuzhiyun break;
1069*4882a593Smuzhiyun }
1070*4882a593Smuzhiyun if (intel_dp->has_audio)
1071*4882a593Smuzhiyun intel_dp->DP |= DP_AUDIO_OUTPUT_ENABLE;
1072*4882a593Smuzhiyun
1073*4882a593Smuzhiyun memset(intel_dp->link_configuration, 0, DP_LINK_CONFIGURATION_SIZE);
1074*4882a593Smuzhiyun intel_dp->link_configuration[0] = intel_dp->link_bw;
1075*4882a593Smuzhiyun intel_dp->link_configuration[1] = intel_dp->lane_count;
1076*4882a593Smuzhiyun
1077*4882a593Smuzhiyun /*
1078*4882a593Smuzhiyun * Check for DPCD version > 1.1 and enhanced framing support
1079*4882a593Smuzhiyun */
1080*4882a593Smuzhiyun if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11 &&
1081*4882a593Smuzhiyun (intel_dp->dpcd[DP_MAX_LANE_COUNT] & DP_ENHANCED_FRAME_CAP)) {
1082*4882a593Smuzhiyun intel_dp->link_configuration[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
1083*4882a593Smuzhiyun intel_dp->DP |= DP_ENHANCED_FRAMING;
1084*4882a593Smuzhiyun }
1085*4882a593Smuzhiyun
1086*4882a593Smuzhiyun /* CPT DP's pipe select is decided in TRANS_DP_CTL */
1087*4882a593Smuzhiyun if (gma_crtc->pipe == 1)
1088*4882a593Smuzhiyun intel_dp->DP |= DP_PIPEB_SELECT;
1089*4882a593Smuzhiyun
1090*4882a593Smuzhiyun REG_WRITE(intel_dp->output_reg, (intel_dp->DP | DP_PORT_EN));
1091*4882a593Smuzhiyun DRM_DEBUG_KMS("DP expected reg is %x\n", intel_dp->DP);
1092*4882a593Smuzhiyun if (is_edp(intel_encoder)) {
1093*4882a593Smuzhiyun uint32_t pfit_control;
1094*4882a593Smuzhiyun cdv_intel_edp_panel_on(intel_encoder);
1095*4882a593Smuzhiyun
1096*4882a593Smuzhiyun if (mode->hdisplay != adjusted_mode->hdisplay ||
1097*4882a593Smuzhiyun mode->vdisplay != adjusted_mode->vdisplay)
1098*4882a593Smuzhiyun pfit_control = PFIT_ENABLE;
1099*4882a593Smuzhiyun else
1100*4882a593Smuzhiyun pfit_control = 0;
1101*4882a593Smuzhiyun
1102*4882a593Smuzhiyun pfit_control |= gma_crtc->pipe << PFIT_PIPE_SHIFT;
1103*4882a593Smuzhiyun
1104*4882a593Smuzhiyun REG_WRITE(PFIT_CONTROL, pfit_control);
1105*4882a593Smuzhiyun }
1106*4882a593Smuzhiyun }
1107*4882a593Smuzhiyun
1108*4882a593Smuzhiyun
1109*4882a593Smuzhiyun /* If the sink supports it, try to set the power state appropriately */
cdv_intel_dp_sink_dpms(struct gma_encoder * encoder,int mode)1110*4882a593Smuzhiyun static void cdv_intel_dp_sink_dpms(struct gma_encoder *encoder, int mode)
1111*4882a593Smuzhiyun {
1112*4882a593Smuzhiyun struct cdv_intel_dp *intel_dp = encoder->dev_priv;
1113*4882a593Smuzhiyun int ret, i;
1114*4882a593Smuzhiyun
1115*4882a593Smuzhiyun /* Should have a valid DPCD by this point */
1116*4882a593Smuzhiyun if (intel_dp->dpcd[DP_DPCD_REV] < 0x11)
1117*4882a593Smuzhiyun return;
1118*4882a593Smuzhiyun
1119*4882a593Smuzhiyun if (mode != DRM_MODE_DPMS_ON) {
1120*4882a593Smuzhiyun ret = cdv_intel_dp_aux_native_write_1(encoder, DP_SET_POWER,
1121*4882a593Smuzhiyun DP_SET_POWER_D3);
1122*4882a593Smuzhiyun if (ret != 1)
1123*4882a593Smuzhiyun DRM_DEBUG_DRIVER("failed to write sink power state\n");
1124*4882a593Smuzhiyun } else {
1125*4882a593Smuzhiyun /*
1126*4882a593Smuzhiyun * When turning on, we need to retry for 1ms to give the sink
1127*4882a593Smuzhiyun * time to wake up.
1128*4882a593Smuzhiyun */
1129*4882a593Smuzhiyun for (i = 0; i < 3; i++) {
1130*4882a593Smuzhiyun ret = cdv_intel_dp_aux_native_write_1(encoder,
1131*4882a593Smuzhiyun DP_SET_POWER,
1132*4882a593Smuzhiyun DP_SET_POWER_D0);
1133*4882a593Smuzhiyun if (ret == 1)
1134*4882a593Smuzhiyun break;
1135*4882a593Smuzhiyun udelay(1000);
1136*4882a593Smuzhiyun }
1137*4882a593Smuzhiyun }
1138*4882a593Smuzhiyun }
1139*4882a593Smuzhiyun
cdv_intel_dp_prepare(struct drm_encoder * encoder)1140*4882a593Smuzhiyun static void cdv_intel_dp_prepare(struct drm_encoder *encoder)
1141*4882a593Smuzhiyun {
1142*4882a593Smuzhiyun struct gma_encoder *intel_encoder = to_gma_encoder(encoder);
1143*4882a593Smuzhiyun int edp = is_edp(intel_encoder);
1144*4882a593Smuzhiyun
1145*4882a593Smuzhiyun if (edp) {
1146*4882a593Smuzhiyun cdv_intel_edp_backlight_off(intel_encoder);
1147*4882a593Smuzhiyun cdv_intel_edp_panel_off(intel_encoder);
1148*4882a593Smuzhiyun cdv_intel_edp_panel_vdd_on(intel_encoder);
1149*4882a593Smuzhiyun }
1150*4882a593Smuzhiyun /* Wake up the sink first */
1151*4882a593Smuzhiyun cdv_intel_dp_sink_dpms(intel_encoder, DRM_MODE_DPMS_ON);
1152*4882a593Smuzhiyun cdv_intel_dp_link_down(intel_encoder);
1153*4882a593Smuzhiyun if (edp)
1154*4882a593Smuzhiyun cdv_intel_edp_panel_vdd_off(intel_encoder);
1155*4882a593Smuzhiyun }
1156*4882a593Smuzhiyun
cdv_intel_dp_commit(struct drm_encoder * encoder)1157*4882a593Smuzhiyun static void cdv_intel_dp_commit(struct drm_encoder *encoder)
1158*4882a593Smuzhiyun {
1159*4882a593Smuzhiyun struct gma_encoder *intel_encoder = to_gma_encoder(encoder);
1160*4882a593Smuzhiyun int edp = is_edp(intel_encoder);
1161*4882a593Smuzhiyun
1162*4882a593Smuzhiyun if (edp)
1163*4882a593Smuzhiyun cdv_intel_edp_panel_on(intel_encoder);
1164*4882a593Smuzhiyun cdv_intel_dp_start_link_train(intel_encoder);
1165*4882a593Smuzhiyun cdv_intel_dp_complete_link_train(intel_encoder);
1166*4882a593Smuzhiyun if (edp)
1167*4882a593Smuzhiyun cdv_intel_edp_backlight_on(intel_encoder);
1168*4882a593Smuzhiyun }
1169*4882a593Smuzhiyun
1170*4882a593Smuzhiyun static void
cdv_intel_dp_dpms(struct drm_encoder * encoder,int mode)1171*4882a593Smuzhiyun cdv_intel_dp_dpms(struct drm_encoder *encoder, int mode)
1172*4882a593Smuzhiyun {
1173*4882a593Smuzhiyun struct gma_encoder *intel_encoder = to_gma_encoder(encoder);
1174*4882a593Smuzhiyun struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv;
1175*4882a593Smuzhiyun struct drm_device *dev = encoder->dev;
1176*4882a593Smuzhiyun uint32_t dp_reg = REG_READ(intel_dp->output_reg);
1177*4882a593Smuzhiyun int edp = is_edp(intel_encoder);
1178*4882a593Smuzhiyun
1179*4882a593Smuzhiyun if (mode != DRM_MODE_DPMS_ON) {
1180*4882a593Smuzhiyun if (edp) {
1181*4882a593Smuzhiyun cdv_intel_edp_backlight_off(intel_encoder);
1182*4882a593Smuzhiyun cdv_intel_edp_panel_vdd_on(intel_encoder);
1183*4882a593Smuzhiyun }
1184*4882a593Smuzhiyun cdv_intel_dp_sink_dpms(intel_encoder, mode);
1185*4882a593Smuzhiyun cdv_intel_dp_link_down(intel_encoder);
1186*4882a593Smuzhiyun if (edp) {
1187*4882a593Smuzhiyun cdv_intel_edp_panel_vdd_off(intel_encoder);
1188*4882a593Smuzhiyun cdv_intel_edp_panel_off(intel_encoder);
1189*4882a593Smuzhiyun }
1190*4882a593Smuzhiyun } else {
1191*4882a593Smuzhiyun if (edp)
1192*4882a593Smuzhiyun cdv_intel_edp_panel_on(intel_encoder);
1193*4882a593Smuzhiyun cdv_intel_dp_sink_dpms(intel_encoder, mode);
1194*4882a593Smuzhiyun if (!(dp_reg & DP_PORT_EN)) {
1195*4882a593Smuzhiyun cdv_intel_dp_start_link_train(intel_encoder);
1196*4882a593Smuzhiyun cdv_intel_dp_complete_link_train(intel_encoder);
1197*4882a593Smuzhiyun }
1198*4882a593Smuzhiyun if (edp)
1199*4882a593Smuzhiyun cdv_intel_edp_backlight_on(intel_encoder);
1200*4882a593Smuzhiyun }
1201*4882a593Smuzhiyun }
1202*4882a593Smuzhiyun
1203*4882a593Smuzhiyun /*
1204*4882a593Smuzhiyun * Native read with retry for link status and receiver capability reads for
1205*4882a593Smuzhiyun * cases where the sink may still be asleep.
1206*4882a593Smuzhiyun */
1207*4882a593Smuzhiyun static bool
cdv_intel_dp_aux_native_read_retry(struct gma_encoder * encoder,uint16_t address,uint8_t * recv,int recv_bytes)1208*4882a593Smuzhiyun cdv_intel_dp_aux_native_read_retry(struct gma_encoder *encoder, uint16_t address,
1209*4882a593Smuzhiyun uint8_t *recv, int recv_bytes)
1210*4882a593Smuzhiyun {
1211*4882a593Smuzhiyun int ret, i;
1212*4882a593Smuzhiyun
1213*4882a593Smuzhiyun /*
1214*4882a593Smuzhiyun * Sinks are *supposed* to come up within 1ms from an off state,
1215*4882a593Smuzhiyun * but we're also supposed to retry 3 times per the spec.
1216*4882a593Smuzhiyun */
1217*4882a593Smuzhiyun for (i = 0; i < 3; i++) {
1218*4882a593Smuzhiyun ret = cdv_intel_dp_aux_native_read(encoder, address, recv,
1219*4882a593Smuzhiyun recv_bytes);
1220*4882a593Smuzhiyun if (ret == recv_bytes)
1221*4882a593Smuzhiyun return true;
1222*4882a593Smuzhiyun udelay(1000);
1223*4882a593Smuzhiyun }
1224*4882a593Smuzhiyun
1225*4882a593Smuzhiyun return false;
1226*4882a593Smuzhiyun }
1227*4882a593Smuzhiyun
1228*4882a593Smuzhiyun /*
1229*4882a593Smuzhiyun * Fetch AUX CH registers 0x202 - 0x207 which contain
1230*4882a593Smuzhiyun * link status information
1231*4882a593Smuzhiyun */
1232*4882a593Smuzhiyun static bool
cdv_intel_dp_get_link_status(struct gma_encoder * encoder)1233*4882a593Smuzhiyun cdv_intel_dp_get_link_status(struct gma_encoder *encoder)
1234*4882a593Smuzhiyun {
1235*4882a593Smuzhiyun struct cdv_intel_dp *intel_dp = encoder->dev_priv;
1236*4882a593Smuzhiyun return cdv_intel_dp_aux_native_read_retry(encoder,
1237*4882a593Smuzhiyun DP_LANE0_1_STATUS,
1238*4882a593Smuzhiyun intel_dp->link_status,
1239*4882a593Smuzhiyun DP_LINK_STATUS_SIZE);
1240*4882a593Smuzhiyun }
1241*4882a593Smuzhiyun
1242*4882a593Smuzhiyun static uint8_t
cdv_intel_dp_link_status(uint8_t link_status[DP_LINK_STATUS_SIZE],int r)1243*4882a593Smuzhiyun cdv_intel_dp_link_status(uint8_t link_status[DP_LINK_STATUS_SIZE],
1244*4882a593Smuzhiyun int r)
1245*4882a593Smuzhiyun {
1246*4882a593Smuzhiyun return link_status[r - DP_LANE0_1_STATUS];
1247*4882a593Smuzhiyun }
1248*4882a593Smuzhiyun
1249*4882a593Smuzhiyun static uint8_t
cdv_intel_get_adjust_request_voltage(uint8_t link_status[DP_LINK_STATUS_SIZE],int lane)1250*4882a593Smuzhiyun cdv_intel_get_adjust_request_voltage(uint8_t link_status[DP_LINK_STATUS_SIZE],
1251*4882a593Smuzhiyun int lane)
1252*4882a593Smuzhiyun {
1253*4882a593Smuzhiyun int i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1);
1254*4882a593Smuzhiyun int s = ((lane & 1) ?
1255*4882a593Smuzhiyun DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT :
1256*4882a593Smuzhiyun DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT);
1257*4882a593Smuzhiyun uint8_t l = cdv_intel_dp_link_status(link_status, i);
1258*4882a593Smuzhiyun
1259*4882a593Smuzhiyun return ((l >> s) & 3) << DP_TRAIN_VOLTAGE_SWING_SHIFT;
1260*4882a593Smuzhiyun }
1261*4882a593Smuzhiyun
1262*4882a593Smuzhiyun static uint8_t
cdv_intel_get_adjust_request_pre_emphasis(uint8_t link_status[DP_LINK_STATUS_SIZE],int lane)1263*4882a593Smuzhiyun cdv_intel_get_adjust_request_pre_emphasis(uint8_t link_status[DP_LINK_STATUS_SIZE],
1264*4882a593Smuzhiyun int lane)
1265*4882a593Smuzhiyun {
1266*4882a593Smuzhiyun int i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1);
1267*4882a593Smuzhiyun int s = ((lane & 1) ?
1268*4882a593Smuzhiyun DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT :
1269*4882a593Smuzhiyun DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT);
1270*4882a593Smuzhiyun uint8_t l = cdv_intel_dp_link_status(link_status, i);
1271*4882a593Smuzhiyun
1272*4882a593Smuzhiyun return ((l >> s) & 3) << DP_TRAIN_PRE_EMPHASIS_SHIFT;
1273*4882a593Smuzhiyun }
1274*4882a593Smuzhiyun
1275*4882a593Smuzhiyun #define CDV_DP_VOLTAGE_MAX DP_TRAIN_VOLTAGE_SWING_LEVEL_3
1276*4882a593Smuzhiyun
1277*4882a593Smuzhiyun static void
cdv_intel_get_adjust_train(struct gma_encoder * encoder)1278*4882a593Smuzhiyun cdv_intel_get_adjust_train(struct gma_encoder *encoder)
1279*4882a593Smuzhiyun {
1280*4882a593Smuzhiyun struct cdv_intel_dp *intel_dp = encoder->dev_priv;
1281*4882a593Smuzhiyun uint8_t v = 0;
1282*4882a593Smuzhiyun uint8_t p = 0;
1283*4882a593Smuzhiyun int lane;
1284*4882a593Smuzhiyun
1285*4882a593Smuzhiyun for (lane = 0; lane < intel_dp->lane_count; lane++) {
1286*4882a593Smuzhiyun uint8_t this_v = cdv_intel_get_adjust_request_voltage(intel_dp->link_status, lane);
1287*4882a593Smuzhiyun uint8_t this_p = cdv_intel_get_adjust_request_pre_emphasis(intel_dp->link_status, lane);
1288*4882a593Smuzhiyun
1289*4882a593Smuzhiyun if (this_v > v)
1290*4882a593Smuzhiyun v = this_v;
1291*4882a593Smuzhiyun if (this_p > p)
1292*4882a593Smuzhiyun p = this_p;
1293*4882a593Smuzhiyun }
1294*4882a593Smuzhiyun
1295*4882a593Smuzhiyun if (v >= CDV_DP_VOLTAGE_MAX)
1296*4882a593Smuzhiyun v = CDV_DP_VOLTAGE_MAX | DP_TRAIN_MAX_SWING_REACHED;
1297*4882a593Smuzhiyun
1298*4882a593Smuzhiyun if (p == DP_TRAIN_PRE_EMPHASIS_MASK)
1299*4882a593Smuzhiyun p |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
1300*4882a593Smuzhiyun
1301*4882a593Smuzhiyun for (lane = 0; lane < 4; lane++)
1302*4882a593Smuzhiyun intel_dp->train_set[lane] = v | p;
1303*4882a593Smuzhiyun }
1304*4882a593Smuzhiyun
1305*4882a593Smuzhiyun
1306*4882a593Smuzhiyun static uint8_t
cdv_intel_get_lane_status(uint8_t link_status[DP_LINK_STATUS_SIZE],int lane)1307*4882a593Smuzhiyun cdv_intel_get_lane_status(uint8_t link_status[DP_LINK_STATUS_SIZE],
1308*4882a593Smuzhiyun int lane)
1309*4882a593Smuzhiyun {
1310*4882a593Smuzhiyun int i = DP_LANE0_1_STATUS + (lane >> 1);
1311*4882a593Smuzhiyun int s = (lane & 1) * 4;
1312*4882a593Smuzhiyun uint8_t l = cdv_intel_dp_link_status(link_status, i);
1313*4882a593Smuzhiyun
1314*4882a593Smuzhiyun return (l >> s) & 0xf;
1315*4882a593Smuzhiyun }
1316*4882a593Smuzhiyun
1317*4882a593Smuzhiyun /* Check for clock recovery is done on all channels */
1318*4882a593Smuzhiyun static bool
cdv_intel_clock_recovery_ok(uint8_t link_status[DP_LINK_STATUS_SIZE],int lane_count)1319*4882a593Smuzhiyun cdv_intel_clock_recovery_ok(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane_count)
1320*4882a593Smuzhiyun {
1321*4882a593Smuzhiyun int lane;
1322*4882a593Smuzhiyun uint8_t lane_status;
1323*4882a593Smuzhiyun
1324*4882a593Smuzhiyun for (lane = 0; lane < lane_count; lane++) {
1325*4882a593Smuzhiyun lane_status = cdv_intel_get_lane_status(link_status, lane);
1326*4882a593Smuzhiyun if ((lane_status & DP_LANE_CR_DONE) == 0)
1327*4882a593Smuzhiyun return false;
1328*4882a593Smuzhiyun }
1329*4882a593Smuzhiyun return true;
1330*4882a593Smuzhiyun }
1331*4882a593Smuzhiyun
1332*4882a593Smuzhiyun /* Check to see if channel eq is done on all channels */
1333*4882a593Smuzhiyun #define CHANNEL_EQ_BITS (DP_LANE_CR_DONE|\
1334*4882a593Smuzhiyun DP_LANE_CHANNEL_EQ_DONE|\
1335*4882a593Smuzhiyun DP_LANE_SYMBOL_LOCKED)
1336*4882a593Smuzhiyun static bool
cdv_intel_channel_eq_ok(struct gma_encoder * encoder)1337*4882a593Smuzhiyun cdv_intel_channel_eq_ok(struct gma_encoder *encoder)
1338*4882a593Smuzhiyun {
1339*4882a593Smuzhiyun struct cdv_intel_dp *intel_dp = encoder->dev_priv;
1340*4882a593Smuzhiyun uint8_t lane_align;
1341*4882a593Smuzhiyun uint8_t lane_status;
1342*4882a593Smuzhiyun int lane;
1343*4882a593Smuzhiyun
1344*4882a593Smuzhiyun lane_align = cdv_intel_dp_link_status(intel_dp->link_status,
1345*4882a593Smuzhiyun DP_LANE_ALIGN_STATUS_UPDATED);
1346*4882a593Smuzhiyun if ((lane_align & DP_INTERLANE_ALIGN_DONE) == 0)
1347*4882a593Smuzhiyun return false;
1348*4882a593Smuzhiyun for (lane = 0; lane < intel_dp->lane_count; lane++) {
1349*4882a593Smuzhiyun lane_status = cdv_intel_get_lane_status(intel_dp->link_status, lane);
1350*4882a593Smuzhiyun if ((lane_status & CHANNEL_EQ_BITS) != CHANNEL_EQ_BITS)
1351*4882a593Smuzhiyun return false;
1352*4882a593Smuzhiyun }
1353*4882a593Smuzhiyun return true;
1354*4882a593Smuzhiyun }
1355*4882a593Smuzhiyun
1356*4882a593Smuzhiyun static bool
cdv_intel_dp_set_link_train(struct gma_encoder * encoder,uint32_t dp_reg_value,uint8_t dp_train_pat)1357*4882a593Smuzhiyun cdv_intel_dp_set_link_train(struct gma_encoder *encoder,
1358*4882a593Smuzhiyun uint32_t dp_reg_value,
1359*4882a593Smuzhiyun uint8_t dp_train_pat)
1360*4882a593Smuzhiyun {
1361*4882a593Smuzhiyun
1362*4882a593Smuzhiyun struct drm_device *dev = encoder->base.dev;
1363*4882a593Smuzhiyun int ret;
1364*4882a593Smuzhiyun struct cdv_intel_dp *intel_dp = encoder->dev_priv;
1365*4882a593Smuzhiyun
1366*4882a593Smuzhiyun REG_WRITE(intel_dp->output_reg, dp_reg_value);
1367*4882a593Smuzhiyun REG_READ(intel_dp->output_reg);
1368*4882a593Smuzhiyun
1369*4882a593Smuzhiyun ret = cdv_intel_dp_aux_native_write_1(encoder,
1370*4882a593Smuzhiyun DP_TRAINING_PATTERN_SET,
1371*4882a593Smuzhiyun dp_train_pat);
1372*4882a593Smuzhiyun
1373*4882a593Smuzhiyun if (ret != 1) {
1374*4882a593Smuzhiyun DRM_DEBUG_KMS("Failure in setting link pattern %x\n",
1375*4882a593Smuzhiyun dp_train_pat);
1376*4882a593Smuzhiyun return false;
1377*4882a593Smuzhiyun }
1378*4882a593Smuzhiyun
1379*4882a593Smuzhiyun return true;
1380*4882a593Smuzhiyun }
1381*4882a593Smuzhiyun
1382*4882a593Smuzhiyun
1383*4882a593Smuzhiyun static bool
cdv_intel_dplink_set_level(struct gma_encoder * encoder,uint8_t dp_train_pat)1384*4882a593Smuzhiyun cdv_intel_dplink_set_level(struct gma_encoder *encoder,
1385*4882a593Smuzhiyun uint8_t dp_train_pat)
1386*4882a593Smuzhiyun {
1387*4882a593Smuzhiyun
1388*4882a593Smuzhiyun int ret;
1389*4882a593Smuzhiyun struct cdv_intel_dp *intel_dp = encoder->dev_priv;
1390*4882a593Smuzhiyun
1391*4882a593Smuzhiyun ret = cdv_intel_dp_aux_native_write(encoder,
1392*4882a593Smuzhiyun DP_TRAINING_LANE0_SET,
1393*4882a593Smuzhiyun intel_dp->train_set,
1394*4882a593Smuzhiyun intel_dp->lane_count);
1395*4882a593Smuzhiyun
1396*4882a593Smuzhiyun if (ret != intel_dp->lane_count) {
1397*4882a593Smuzhiyun DRM_DEBUG_KMS("Failure in setting level %d, lane_cnt= %d\n",
1398*4882a593Smuzhiyun intel_dp->train_set[0], intel_dp->lane_count);
1399*4882a593Smuzhiyun return false;
1400*4882a593Smuzhiyun }
1401*4882a593Smuzhiyun return true;
1402*4882a593Smuzhiyun }
1403*4882a593Smuzhiyun
1404*4882a593Smuzhiyun static void
cdv_intel_dp_set_vswing_premph(struct gma_encoder * encoder,uint8_t signal_level)1405*4882a593Smuzhiyun cdv_intel_dp_set_vswing_premph(struct gma_encoder *encoder, uint8_t signal_level)
1406*4882a593Smuzhiyun {
1407*4882a593Smuzhiyun struct drm_device *dev = encoder->base.dev;
1408*4882a593Smuzhiyun struct cdv_intel_dp *intel_dp = encoder->dev_priv;
1409*4882a593Smuzhiyun struct ddi_regoff *ddi_reg;
1410*4882a593Smuzhiyun int vswing, premph, index;
1411*4882a593Smuzhiyun
1412*4882a593Smuzhiyun if (intel_dp->output_reg == DP_B)
1413*4882a593Smuzhiyun ddi_reg = &ddi_DP_train_table[0];
1414*4882a593Smuzhiyun else
1415*4882a593Smuzhiyun ddi_reg = &ddi_DP_train_table[1];
1416*4882a593Smuzhiyun
1417*4882a593Smuzhiyun vswing = (signal_level & DP_TRAIN_VOLTAGE_SWING_MASK);
1418*4882a593Smuzhiyun premph = ((signal_level & DP_TRAIN_PRE_EMPHASIS_MASK)) >>
1419*4882a593Smuzhiyun DP_TRAIN_PRE_EMPHASIS_SHIFT;
1420*4882a593Smuzhiyun
1421*4882a593Smuzhiyun if (vswing + premph > 3)
1422*4882a593Smuzhiyun return;
1423*4882a593Smuzhiyun #ifdef CDV_FAST_LINK_TRAIN
1424*4882a593Smuzhiyun return;
1425*4882a593Smuzhiyun #endif
1426*4882a593Smuzhiyun DRM_DEBUG_KMS("Test2\n");
1427*4882a593Smuzhiyun //return ;
1428*4882a593Smuzhiyun cdv_sb_reset(dev);
1429*4882a593Smuzhiyun /* ;Swing voltage programming
1430*4882a593Smuzhiyun ;gfx_dpio_set_reg(0xc058, 0x0505313A) */
1431*4882a593Smuzhiyun cdv_sb_write(dev, ddi_reg->VSwing5, 0x0505313A);
1432*4882a593Smuzhiyun
1433*4882a593Smuzhiyun /* ;gfx_dpio_set_reg(0x8154, 0x43406055) */
1434*4882a593Smuzhiyun cdv_sb_write(dev, ddi_reg->VSwing1, 0x43406055);
1435*4882a593Smuzhiyun
1436*4882a593Smuzhiyun /* ;gfx_dpio_set_reg(0x8148, 0x55338954)
1437*4882a593Smuzhiyun * The VSwing_PreEmph table is also considered based on the vswing/premp
1438*4882a593Smuzhiyun */
1439*4882a593Smuzhiyun index = (vswing + premph) * 2;
1440*4882a593Smuzhiyun if (premph == 1 && vswing == 1) {
1441*4882a593Smuzhiyun cdv_sb_write(dev, ddi_reg->VSwing2, 0x055738954);
1442*4882a593Smuzhiyun } else
1443*4882a593Smuzhiyun cdv_sb_write(dev, ddi_reg->VSwing2, dp_vswing_premph_table[index]);
1444*4882a593Smuzhiyun
1445*4882a593Smuzhiyun /* ;gfx_dpio_set_reg(0x814c, 0x40802040) */
1446*4882a593Smuzhiyun if ((vswing + premph) == DP_TRAIN_VOLTAGE_SWING_LEVEL_3)
1447*4882a593Smuzhiyun cdv_sb_write(dev, ddi_reg->VSwing3, 0x70802040);
1448*4882a593Smuzhiyun else
1449*4882a593Smuzhiyun cdv_sb_write(dev, ddi_reg->VSwing3, 0x40802040);
1450*4882a593Smuzhiyun
1451*4882a593Smuzhiyun /* ;gfx_dpio_set_reg(0x8150, 0x2b405555) */
1452*4882a593Smuzhiyun /* cdv_sb_write(dev, ddi_reg->VSwing4, 0x2b405555); */
1453*4882a593Smuzhiyun
1454*4882a593Smuzhiyun /* ;gfx_dpio_set_reg(0x8154, 0xc3406055) */
1455*4882a593Smuzhiyun cdv_sb_write(dev, ddi_reg->VSwing1, 0xc3406055);
1456*4882a593Smuzhiyun
1457*4882a593Smuzhiyun /* ;Pre emphasis programming
1458*4882a593Smuzhiyun * ;gfx_dpio_set_reg(0xc02c, 0x1f030040)
1459*4882a593Smuzhiyun */
1460*4882a593Smuzhiyun cdv_sb_write(dev, ddi_reg->PreEmph1, 0x1f030040);
1461*4882a593Smuzhiyun
1462*4882a593Smuzhiyun /* ;gfx_dpio_set_reg(0x8124, 0x00004000) */
1463*4882a593Smuzhiyun index = 2 * premph + 1;
1464*4882a593Smuzhiyun cdv_sb_write(dev, ddi_reg->PreEmph2, dp_vswing_premph_table[index]);
1465*4882a593Smuzhiyun return;
1466*4882a593Smuzhiyun }
1467*4882a593Smuzhiyun
1468*4882a593Smuzhiyun
1469*4882a593Smuzhiyun /* Enable corresponding port and start training pattern 1 */
1470*4882a593Smuzhiyun static void
cdv_intel_dp_start_link_train(struct gma_encoder * encoder)1471*4882a593Smuzhiyun cdv_intel_dp_start_link_train(struct gma_encoder *encoder)
1472*4882a593Smuzhiyun {
1473*4882a593Smuzhiyun struct drm_device *dev = encoder->base.dev;
1474*4882a593Smuzhiyun struct cdv_intel_dp *intel_dp = encoder->dev_priv;
1475*4882a593Smuzhiyun int i;
1476*4882a593Smuzhiyun uint8_t voltage;
1477*4882a593Smuzhiyun bool clock_recovery = false;
1478*4882a593Smuzhiyun int tries;
1479*4882a593Smuzhiyun u32 reg;
1480*4882a593Smuzhiyun uint32_t DP = intel_dp->DP;
1481*4882a593Smuzhiyun
1482*4882a593Smuzhiyun DP |= DP_PORT_EN;
1483*4882a593Smuzhiyun DP &= ~DP_LINK_TRAIN_MASK;
1484*4882a593Smuzhiyun
1485*4882a593Smuzhiyun reg = DP;
1486*4882a593Smuzhiyun reg |= DP_LINK_TRAIN_PAT_1;
1487*4882a593Smuzhiyun /* Enable output, wait for it to become active */
1488*4882a593Smuzhiyun REG_WRITE(intel_dp->output_reg, reg);
1489*4882a593Smuzhiyun REG_READ(intel_dp->output_reg);
1490*4882a593Smuzhiyun gma_wait_for_vblank(dev);
1491*4882a593Smuzhiyun
1492*4882a593Smuzhiyun DRM_DEBUG_KMS("Link config\n");
1493*4882a593Smuzhiyun /* Write the link configuration data */
1494*4882a593Smuzhiyun cdv_intel_dp_aux_native_write(encoder, DP_LINK_BW_SET,
1495*4882a593Smuzhiyun intel_dp->link_configuration,
1496*4882a593Smuzhiyun 2);
1497*4882a593Smuzhiyun
1498*4882a593Smuzhiyun memset(intel_dp->train_set, 0, 4);
1499*4882a593Smuzhiyun voltage = 0;
1500*4882a593Smuzhiyun tries = 0;
1501*4882a593Smuzhiyun clock_recovery = false;
1502*4882a593Smuzhiyun
1503*4882a593Smuzhiyun DRM_DEBUG_KMS("Start train\n");
1504*4882a593Smuzhiyun reg = DP | DP_LINK_TRAIN_PAT_1;
1505*4882a593Smuzhiyun
1506*4882a593Smuzhiyun
1507*4882a593Smuzhiyun for (;;) {
1508*4882a593Smuzhiyun /* Use intel_dp->train_set[0] to set the voltage and pre emphasis values */
1509*4882a593Smuzhiyun DRM_DEBUG_KMS("DP Link Train Set %x, Link_config %x, %x\n",
1510*4882a593Smuzhiyun intel_dp->train_set[0],
1511*4882a593Smuzhiyun intel_dp->link_configuration[0],
1512*4882a593Smuzhiyun intel_dp->link_configuration[1]);
1513*4882a593Smuzhiyun
1514*4882a593Smuzhiyun if (!cdv_intel_dp_set_link_train(encoder, reg, DP_TRAINING_PATTERN_1)) {
1515*4882a593Smuzhiyun DRM_DEBUG_KMS("Failure in aux-transfer setting pattern 1\n");
1516*4882a593Smuzhiyun }
1517*4882a593Smuzhiyun cdv_intel_dp_set_vswing_premph(encoder, intel_dp->train_set[0]);
1518*4882a593Smuzhiyun /* Set training pattern 1 */
1519*4882a593Smuzhiyun
1520*4882a593Smuzhiyun cdv_intel_dplink_set_level(encoder, DP_TRAINING_PATTERN_1);
1521*4882a593Smuzhiyun
1522*4882a593Smuzhiyun udelay(200);
1523*4882a593Smuzhiyun if (!cdv_intel_dp_get_link_status(encoder))
1524*4882a593Smuzhiyun break;
1525*4882a593Smuzhiyun
1526*4882a593Smuzhiyun DRM_DEBUG_KMS("DP Link status %x, %x, %x, %x, %x, %x\n",
1527*4882a593Smuzhiyun intel_dp->link_status[0], intel_dp->link_status[1], intel_dp->link_status[2],
1528*4882a593Smuzhiyun intel_dp->link_status[3], intel_dp->link_status[4], intel_dp->link_status[5]);
1529*4882a593Smuzhiyun
1530*4882a593Smuzhiyun if (cdv_intel_clock_recovery_ok(intel_dp->link_status, intel_dp->lane_count)) {
1531*4882a593Smuzhiyun DRM_DEBUG_KMS("PT1 train is done\n");
1532*4882a593Smuzhiyun clock_recovery = true;
1533*4882a593Smuzhiyun break;
1534*4882a593Smuzhiyun }
1535*4882a593Smuzhiyun
1536*4882a593Smuzhiyun /* Check to see if we've tried the max voltage */
1537*4882a593Smuzhiyun for (i = 0; i < intel_dp->lane_count; i++)
1538*4882a593Smuzhiyun if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0)
1539*4882a593Smuzhiyun break;
1540*4882a593Smuzhiyun if (i == intel_dp->lane_count)
1541*4882a593Smuzhiyun break;
1542*4882a593Smuzhiyun
1543*4882a593Smuzhiyun /* Check to see if we've tried the same voltage 5 times */
1544*4882a593Smuzhiyun if ((intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) {
1545*4882a593Smuzhiyun ++tries;
1546*4882a593Smuzhiyun if (tries == 5)
1547*4882a593Smuzhiyun break;
1548*4882a593Smuzhiyun } else
1549*4882a593Smuzhiyun tries = 0;
1550*4882a593Smuzhiyun voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
1551*4882a593Smuzhiyun
1552*4882a593Smuzhiyun /* Compute new intel_dp->train_set as requested by target */
1553*4882a593Smuzhiyun cdv_intel_get_adjust_train(encoder);
1554*4882a593Smuzhiyun
1555*4882a593Smuzhiyun }
1556*4882a593Smuzhiyun
1557*4882a593Smuzhiyun if (!clock_recovery) {
1558*4882a593Smuzhiyun DRM_DEBUG_KMS("failure in DP patter 1 training, train set %x\n", intel_dp->train_set[0]);
1559*4882a593Smuzhiyun }
1560*4882a593Smuzhiyun
1561*4882a593Smuzhiyun intel_dp->DP = DP;
1562*4882a593Smuzhiyun }
1563*4882a593Smuzhiyun
1564*4882a593Smuzhiyun static void
cdv_intel_dp_complete_link_train(struct gma_encoder * encoder)1565*4882a593Smuzhiyun cdv_intel_dp_complete_link_train(struct gma_encoder *encoder)
1566*4882a593Smuzhiyun {
1567*4882a593Smuzhiyun struct drm_device *dev = encoder->base.dev;
1568*4882a593Smuzhiyun struct cdv_intel_dp *intel_dp = encoder->dev_priv;
1569*4882a593Smuzhiyun int tries, cr_tries;
1570*4882a593Smuzhiyun u32 reg;
1571*4882a593Smuzhiyun uint32_t DP = intel_dp->DP;
1572*4882a593Smuzhiyun
1573*4882a593Smuzhiyun /* channel equalization */
1574*4882a593Smuzhiyun tries = 0;
1575*4882a593Smuzhiyun cr_tries = 0;
1576*4882a593Smuzhiyun
1577*4882a593Smuzhiyun DRM_DEBUG_KMS("\n");
1578*4882a593Smuzhiyun reg = DP | DP_LINK_TRAIN_PAT_2;
1579*4882a593Smuzhiyun
1580*4882a593Smuzhiyun for (;;) {
1581*4882a593Smuzhiyun
1582*4882a593Smuzhiyun DRM_DEBUG_KMS("DP Link Train Set %x, Link_config %x, %x\n",
1583*4882a593Smuzhiyun intel_dp->train_set[0],
1584*4882a593Smuzhiyun intel_dp->link_configuration[0],
1585*4882a593Smuzhiyun intel_dp->link_configuration[1]);
1586*4882a593Smuzhiyun /* channel eq pattern */
1587*4882a593Smuzhiyun
1588*4882a593Smuzhiyun if (!cdv_intel_dp_set_link_train(encoder, reg,
1589*4882a593Smuzhiyun DP_TRAINING_PATTERN_2)) {
1590*4882a593Smuzhiyun DRM_DEBUG_KMS("Failure in aux-transfer setting pattern 2\n");
1591*4882a593Smuzhiyun }
1592*4882a593Smuzhiyun /* Use intel_dp->train_set[0] to set the voltage and pre emphasis values */
1593*4882a593Smuzhiyun
1594*4882a593Smuzhiyun if (cr_tries > 5) {
1595*4882a593Smuzhiyun DRM_ERROR("failed to train DP, aborting\n");
1596*4882a593Smuzhiyun cdv_intel_dp_link_down(encoder);
1597*4882a593Smuzhiyun break;
1598*4882a593Smuzhiyun }
1599*4882a593Smuzhiyun
1600*4882a593Smuzhiyun cdv_intel_dp_set_vswing_premph(encoder, intel_dp->train_set[0]);
1601*4882a593Smuzhiyun
1602*4882a593Smuzhiyun cdv_intel_dplink_set_level(encoder, DP_TRAINING_PATTERN_2);
1603*4882a593Smuzhiyun
1604*4882a593Smuzhiyun udelay(1000);
1605*4882a593Smuzhiyun if (!cdv_intel_dp_get_link_status(encoder))
1606*4882a593Smuzhiyun break;
1607*4882a593Smuzhiyun
1608*4882a593Smuzhiyun DRM_DEBUG_KMS("DP Link status %x, %x, %x, %x, %x, %x\n",
1609*4882a593Smuzhiyun intel_dp->link_status[0], intel_dp->link_status[1], intel_dp->link_status[2],
1610*4882a593Smuzhiyun intel_dp->link_status[3], intel_dp->link_status[4], intel_dp->link_status[5]);
1611*4882a593Smuzhiyun
1612*4882a593Smuzhiyun /* Make sure clock is still ok */
1613*4882a593Smuzhiyun if (!cdv_intel_clock_recovery_ok(intel_dp->link_status, intel_dp->lane_count)) {
1614*4882a593Smuzhiyun cdv_intel_dp_start_link_train(encoder);
1615*4882a593Smuzhiyun cr_tries++;
1616*4882a593Smuzhiyun continue;
1617*4882a593Smuzhiyun }
1618*4882a593Smuzhiyun
1619*4882a593Smuzhiyun if (cdv_intel_channel_eq_ok(encoder)) {
1620*4882a593Smuzhiyun DRM_DEBUG_KMS("PT2 train is done\n");
1621*4882a593Smuzhiyun break;
1622*4882a593Smuzhiyun }
1623*4882a593Smuzhiyun
1624*4882a593Smuzhiyun /* Try 5 times, then try clock recovery if that fails */
1625*4882a593Smuzhiyun if (tries > 5) {
1626*4882a593Smuzhiyun cdv_intel_dp_link_down(encoder);
1627*4882a593Smuzhiyun cdv_intel_dp_start_link_train(encoder);
1628*4882a593Smuzhiyun tries = 0;
1629*4882a593Smuzhiyun cr_tries++;
1630*4882a593Smuzhiyun continue;
1631*4882a593Smuzhiyun }
1632*4882a593Smuzhiyun
1633*4882a593Smuzhiyun /* Compute new intel_dp->train_set as requested by target */
1634*4882a593Smuzhiyun cdv_intel_get_adjust_train(encoder);
1635*4882a593Smuzhiyun ++tries;
1636*4882a593Smuzhiyun
1637*4882a593Smuzhiyun }
1638*4882a593Smuzhiyun
1639*4882a593Smuzhiyun reg = DP | DP_LINK_TRAIN_OFF;
1640*4882a593Smuzhiyun
1641*4882a593Smuzhiyun REG_WRITE(intel_dp->output_reg, reg);
1642*4882a593Smuzhiyun REG_READ(intel_dp->output_reg);
1643*4882a593Smuzhiyun cdv_intel_dp_aux_native_write_1(encoder,
1644*4882a593Smuzhiyun DP_TRAINING_PATTERN_SET, DP_TRAINING_PATTERN_DISABLE);
1645*4882a593Smuzhiyun }
1646*4882a593Smuzhiyun
1647*4882a593Smuzhiyun static void
cdv_intel_dp_link_down(struct gma_encoder * encoder)1648*4882a593Smuzhiyun cdv_intel_dp_link_down(struct gma_encoder *encoder)
1649*4882a593Smuzhiyun {
1650*4882a593Smuzhiyun struct drm_device *dev = encoder->base.dev;
1651*4882a593Smuzhiyun struct cdv_intel_dp *intel_dp = encoder->dev_priv;
1652*4882a593Smuzhiyun uint32_t DP = intel_dp->DP;
1653*4882a593Smuzhiyun
1654*4882a593Smuzhiyun if ((REG_READ(intel_dp->output_reg) & DP_PORT_EN) == 0)
1655*4882a593Smuzhiyun return;
1656*4882a593Smuzhiyun
1657*4882a593Smuzhiyun DRM_DEBUG_KMS("\n");
1658*4882a593Smuzhiyun
1659*4882a593Smuzhiyun
1660*4882a593Smuzhiyun {
1661*4882a593Smuzhiyun DP &= ~DP_LINK_TRAIN_MASK;
1662*4882a593Smuzhiyun REG_WRITE(intel_dp->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE);
1663*4882a593Smuzhiyun }
1664*4882a593Smuzhiyun REG_READ(intel_dp->output_reg);
1665*4882a593Smuzhiyun
1666*4882a593Smuzhiyun msleep(17);
1667*4882a593Smuzhiyun
1668*4882a593Smuzhiyun REG_WRITE(intel_dp->output_reg, DP & ~DP_PORT_EN);
1669*4882a593Smuzhiyun REG_READ(intel_dp->output_reg);
1670*4882a593Smuzhiyun }
1671*4882a593Smuzhiyun
cdv_dp_detect(struct gma_encoder * encoder)1672*4882a593Smuzhiyun static enum drm_connector_status cdv_dp_detect(struct gma_encoder *encoder)
1673*4882a593Smuzhiyun {
1674*4882a593Smuzhiyun struct cdv_intel_dp *intel_dp = encoder->dev_priv;
1675*4882a593Smuzhiyun enum drm_connector_status status;
1676*4882a593Smuzhiyun
1677*4882a593Smuzhiyun status = connector_status_disconnected;
1678*4882a593Smuzhiyun if (cdv_intel_dp_aux_native_read(encoder, 0x000, intel_dp->dpcd,
1679*4882a593Smuzhiyun sizeof (intel_dp->dpcd)) == sizeof (intel_dp->dpcd))
1680*4882a593Smuzhiyun {
1681*4882a593Smuzhiyun if (intel_dp->dpcd[DP_DPCD_REV] != 0)
1682*4882a593Smuzhiyun status = connector_status_connected;
1683*4882a593Smuzhiyun }
1684*4882a593Smuzhiyun if (status == connector_status_connected)
1685*4882a593Smuzhiyun DRM_DEBUG_KMS("DPCD: Rev=%x LN_Rate=%x LN_CNT=%x LN_DOWNSP=%x\n",
1686*4882a593Smuzhiyun intel_dp->dpcd[0], intel_dp->dpcd[1],
1687*4882a593Smuzhiyun intel_dp->dpcd[2], intel_dp->dpcd[3]);
1688*4882a593Smuzhiyun return status;
1689*4882a593Smuzhiyun }
1690*4882a593Smuzhiyun
1691*4882a593Smuzhiyun /**
1692*4882a593Smuzhiyun * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect DP connection.
1693*4882a593Smuzhiyun *
1694*4882a593Smuzhiyun * \return true if DP port is connected.
1695*4882a593Smuzhiyun * \return false if DP port is disconnected.
1696*4882a593Smuzhiyun */
1697*4882a593Smuzhiyun static enum drm_connector_status
cdv_intel_dp_detect(struct drm_connector * connector,bool force)1698*4882a593Smuzhiyun cdv_intel_dp_detect(struct drm_connector *connector, bool force)
1699*4882a593Smuzhiyun {
1700*4882a593Smuzhiyun struct gma_encoder *encoder = gma_attached_encoder(connector);
1701*4882a593Smuzhiyun struct cdv_intel_dp *intel_dp = encoder->dev_priv;
1702*4882a593Smuzhiyun enum drm_connector_status status;
1703*4882a593Smuzhiyun struct edid *edid = NULL;
1704*4882a593Smuzhiyun int edp = is_edp(encoder);
1705*4882a593Smuzhiyun
1706*4882a593Smuzhiyun intel_dp->has_audio = false;
1707*4882a593Smuzhiyun
1708*4882a593Smuzhiyun if (edp)
1709*4882a593Smuzhiyun cdv_intel_edp_panel_vdd_on(encoder);
1710*4882a593Smuzhiyun status = cdv_dp_detect(encoder);
1711*4882a593Smuzhiyun if (status != connector_status_connected) {
1712*4882a593Smuzhiyun if (edp)
1713*4882a593Smuzhiyun cdv_intel_edp_panel_vdd_off(encoder);
1714*4882a593Smuzhiyun return status;
1715*4882a593Smuzhiyun }
1716*4882a593Smuzhiyun
1717*4882a593Smuzhiyun if (intel_dp->force_audio) {
1718*4882a593Smuzhiyun intel_dp->has_audio = intel_dp->force_audio > 0;
1719*4882a593Smuzhiyun } else {
1720*4882a593Smuzhiyun edid = drm_get_edid(connector, &intel_dp->adapter);
1721*4882a593Smuzhiyun if (edid) {
1722*4882a593Smuzhiyun intel_dp->has_audio = drm_detect_monitor_audio(edid);
1723*4882a593Smuzhiyun kfree(edid);
1724*4882a593Smuzhiyun }
1725*4882a593Smuzhiyun }
1726*4882a593Smuzhiyun if (edp)
1727*4882a593Smuzhiyun cdv_intel_edp_panel_vdd_off(encoder);
1728*4882a593Smuzhiyun
1729*4882a593Smuzhiyun return connector_status_connected;
1730*4882a593Smuzhiyun }
1731*4882a593Smuzhiyun
cdv_intel_dp_get_modes(struct drm_connector * connector)1732*4882a593Smuzhiyun static int cdv_intel_dp_get_modes(struct drm_connector *connector)
1733*4882a593Smuzhiyun {
1734*4882a593Smuzhiyun struct gma_encoder *intel_encoder = gma_attached_encoder(connector);
1735*4882a593Smuzhiyun struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv;
1736*4882a593Smuzhiyun struct edid *edid = NULL;
1737*4882a593Smuzhiyun int ret = 0;
1738*4882a593Smuzhiyun int edp = is_edp(intel_encoder);
1739*4882a593Smuzhiyun
1740*4882a593Smuzhiyun
1741*4882a593Smuzhiyun edid = drm_get_edid(connector, &intel_dp->adapter);
1742*4882a593Smuzhiyun if (edid) {
1743*4882a593Smuzhiyun drm_connector_update_edid_property(connector, edid);
1744*4882a593Smuzhiyun ret = drm_add_edid_modes(connector, edid);
1745*4882a593Smuzhiyun kfree(edid);
1746*4882a593Smuzhiyun }
1747*4882a593Smuzhiyun
1748*4882a593Smuzhiyun if (is_edp(intel_encoder)) {
1749*4882a593Smuzhiyun struct drm_device *dev = connector->dev;
1750*4882a593Smuzhiyun struct drm_psb_private *dev_priv = dev->dev_private;
1751*4882a593Smuzhiyun
1752*4882a593Smuzhiyun cdv_intel_edp_panel_vdd_off(intel_encoder);
1753*4882a593Smuzhiyun if (ret) {
1754*4882a593Smuzhiyun if (edp && !intel_dp->panel_fixed_mode) {
1755*4882a593Smuzhiyun struct drm_display_mode *newmode;
1756*4882a593Smuzhiyun list_for_each_entry(newmode, &connector->probed_modes,
1757*4882a593Smuzhiyun head) {
1758*4882a593Smuzhiyun if (newmode->type & DRM_MODE_TYPE_PREFERRED) {
1759*4882a593Smuzhiyun intel_dp->panel_fixed_mode =
1760*4882a593Smuzhiyun drm_mode_duplicate(dev, newmode);
1761*4882a593Smuzhiyun break;
1762*4882a593Smuzhiyun }
1763*4882a593Smuzhiyun }
1764*4882a593Smuzhiyun }
1765*4882a593Smuzhiyun
1766*4882a593Smuzhiyun return ret;
1767*4882a593Smuzhiyun }
1768*4882a593Smuzhiyun if (!intel_dp->panel_fixed_mode && dev_priv->lfp_lvds_vbt_mode) {
1769*4882a593Smuzhiyun intel_dp->panel_fixed_mode =
1770*4882a593Smuzhiyun drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode);
1771*4882a593Smuzhiyun if (intel_dp->panel_fixed_mode) {
1772*4882a593Smuzhiyun intel_dp->panel_fixed_mode->type |=
1773*4882a593Smuzhiyun DRM_MODE_TYPE_PREFERRED;
1774*4882a593Smuzhiyun }
1775*4882a593Smuzhiyun }
1776*4882a593Smuzhiyun if (intel_dp->panel_fixed_mode != NULL) {
1777*4882a593Smuzhiyun struct drm_display_mode *mode;
1778*4882a593Smuzhiyun mode = drm_mode_duplicate(dev, intel_dp->panel_fixed_mode);
1779*4882a593Smuzhiyun drm_mode_probed_add(connector, mode);
1780*4882a593Smuzhiyun return 1;
1781*4882a593Smuzhiyun }
1782*4882a593Smuzhiyun }
1783*4882a593Smuzhiyun
1784*4882a593Smuzhiyun return ret;
1785*4882a593Smuzhiyun }
1786*4882a593Smuzhiyun
1787*4882a593Smuzhiyun static bool
cdv_intel_dp_detect_audio(struct drm_connector * connector)1788*4882a593Smuzhiyun cdv_intel_dp_detect_audio(struct drm_connector *connector)
1789*4882a593Smuzhiyun {
1790*4882a593Smuzhiyun struct gma_encoder *encoder = gma_attached_encoder(connector);
1791*4882a593Smuzhiyun struct cdv_intel_dp *intel_dp = encoder->dev_priv;
1792*4882a593Smuzhiyun struct edid *edid;
1793*4882a593Smuzhiyun bool has_audio = false;
1794*4882a593Smuzhiyun int edp = is_edp(encoder);
1795*4882a593Smuzhiyun
1796*4882a593Smuzhiyun if (edp)
1797*4882a593Smuzhiyun cdv_intel_edp_panel_vdd_on(encoder);
1798*4882a593Smuzhiyun
1799*4882a593Smuzhiyun edid = drm_get_edid(connector, &intel_dp->adapter);
1800*4882a593Smuzhiyun if (edid) {
1801*4882a593Smuzhiyun has_audio = drm_detect_monitor_audio(edid);
1802*4882a593Smuzhiyun kfree(edid);
1803*4882a593Smuzhiyun }
1804*4882a593Smuzhiyun if (edp)
1805*4882a593Smuzhiyun cdv_intel_edp_panel_vdd_off(encoder);
1806*4882a593Smuzhiyun
1807*4882a593Smuzhiyun return has_audio;
1808*4882a593Smuzhiyun }
1809*4882a593Smuzhiyun
1810*4882a593Smuzhiyun static int
cdv_intel_dp_set_property(struct drm_connector * connector,struct drm_property * property,uint64_t val)1811*4882a593Smuzhiyun cdv_intel_dp_set_property(struct drm_connector *connector,
1812*4882a593Smuzhiyun struct drm_property *property,
1813*4882a593Smuzhiyun uint64_t val)
1814*4882a593Smuzhiyun {
1815*4882a593Smuzhiyun struct drm_psb_private *dev_priv = connector->dev->dev_private;
1816*4882a593Smuzhiyun struct gma_encoder *encoder = gma_attached_encoder(connector);
1817*4882a593Smuzhiyun struct cdv_intel_dp *intel_dp = encoder->dev_priv;
1818*4882a593Smuzhiyun int ret;
1819*4882a593Smuzhiyun
1820*4882a593Smuzhiyun ret = drm_object_property_set_value(&connector->base, property, val);
1821*4882a593Smuzhiyun if (ret)
1822*4882a593Smuzhiyun return ret;
1823*4882a593Smuzhiyun
1824*4882a593Smuzhiyun if (property == dev_priv->force_audio_property) {
1825*4882a593Smuzhiyun int i = val;
1826*4882a593Smuzhiyun bool has_audio;
1827*4882a593Smuzhiyun
1828*4882a593Smuzhiyun if (i == intel_dp->force_audio)
1829*4882a593Smuzhiyun return 0;
1830*4882a593Smuzhiyun
1831*4882a593Smuzhiyun intel_dp->force_audio = i;
1832*4882a593Smuzhiyun
1833*4882a593Smuzhiyun if (i == 0)
1834*4882a593Smuzhiyun has_audio = cdv_intel_dp_detect_audio(connector);
1835*4882a593Smuzhiyun else
1836*4882a593Smuzhiyun has_audio = i > 0;
1837*4882a593Smuzhiyun
1838*4882a593Smuzhiyun if (has_audio == intel_dp->has_audio)
1839*4882a593Smuzhiyun return 0;
1840*4882a593Smuzhiyun
1841*4882a593Smuzhiyun intel_dp->has_audio = has_audio;
1842*4882a593Smuzhiyun goto done;
1843*4882a593Smuzhiyun }
1844*4882a593Smuzhiyun
1845*4882a593Smuzhiyun if (property == dev_priv->broadcast_rgb_property) {
1846*4882a593Smuzhiyun if (val == !!intel_dp->color_range)
1847*4882a593Smuzhiyun return 0;
1848*4882a593Smuzhiyun
1849*4882a593Smuzhiyun intel_dp->color_range = val ? DP_COLOR_RANGE_16_235 : 0;
1850*4882a593Smuzhiyun goto done;
1851*4882a593Smuzhiyun }
1852*4882a593Smuzhiyun
1853*4882a593Smuzhiyun return -EINVAL;
1854*4882a593Smuzhiyun
1855*4882a593Smuzhiyun done:
1856*4882a593Smuzhiyun if (encoder->base.crtc) {
1857*4882a593Smuzhiyun struct drm_crtc *crtc = encoder->base.crtc;
1858*4882a593Smuzhiyun drm_crtc_helper_set_mode(crtc, &crtc->mode,
1859*4882a593Smuzhiyun crtc->x, crtc->y,
1860*4882a593Smuzhiyun crtc->primary->fb);
1861*4882a593Smuzhiyun }
1862*4882a593Smuzhiyun
1863*4882a593Smuzhiyun return 0;
1864*4882a593Smuzhiyun }
1865*4882a593Smuzhiyun
1866*4882a593Smuzhiyun static void
cdv_intel_dp_destroy(struct drm_connector * connector)1867*4882a593Smuzhiyun cdv_intel_dp_destroy(struct drm_connector *connector)
1868*4882a593Smuzhiyun {
1869*4882a593Smuzhiyun struct gma_encoder *gma_encoder = gma_attached_encoder(connector);
1870*4882a593Smuzhiyun struct cdv_intel_dp *intel_dp = gma_encoder->dev_priv;
1871*4882a593Smuzhiyun
1872*4882a593Smuzhiyun if (is_edp(gma_encoder)) {
1873*4882a593Smuzhiyun /* cdv_intel_panel_destroy_backlight(connector->dev); */
1874*4882a593Smuzhiyun kfree(intel_dp->panel_fixed_mode);
1875*4882a593Smuzhiyun intel_dp->panel_fixed_mode = NULL;
1876*4882a593Smuzhiyun }
1877*4882a593Smuzhiyun i2c_del_adapter(&intel_dp->adapter);
1878*4882a593Smuzhiyun drm_connector_unregister(connector);
1879*4882a593Smuzhiyun drm_connector_cleanup(connector);
1880*4882a593Smuzhiyun kfree(connector);
1881*4882a593Smuzhiyun }
1882*4882a593Smuzhiyun
1883*4882a593Smuzhiyun static const struct drm_encoder_helper_funcs cdv_intel_dp_helper_funcs = {
1884*4882a593Smuzhiyun .dpms = cdv_intel_dp_dpms,
1885*4882a593Smuzhiyun .mode_fixup = cdv_intel_dp_mode_fixup,
1886*4882a593Smuzhiyun .prepare = cdv_intel_dp_prepare,
1887*4882a593Smuzhiyun .mode_set = cdv_intel_dp_mode_set,
1888*4882a593Smuzhiyun .commit = cdv_intel_dp_commit,
1889*4882a593Smuzhiyun };
1890*4882a593Smuzhiyun
1891*4882a593Smuzhiyun static const struct drm_connector_funcs cdv_intel_dp_connector_funcs = {
1892*4882a593Smuzhiyun .dpms = drm_helper_connector_dpms,
1893*4882a593Smuzhiyun .detect = cdv_intel_dp_detect,
1894*4882a593Smuzhiyun .fill_modes = drm_helper_probe_single_connector_modes,
1895*4882a593Smuzhiyun .set_property = cdv_intel_dp_set_property,
1896*4882a593Smuzhiyun .destroy = cdv_intel_dp_destroy,
1897*4882a593Smuzhiyun };
1898*4882a593Smuzhiyun
1899*4882a593Smuzhiyun static const struct drm_connector_helper_funcs cdv_intel_dp_connector_helper_funcs = {
1900*4882a593Smuzhiyun .get_modes = cdv_intel_dp_get_modes,
1901*4882a593Smuzhiyun .mode_valid = cdv_intel_dp_mode_valid,
1902*4882a593Smuzhiyun .best_encoder = gma_best_encoder,
1903*4882a593Smuzhiyun };
1904*4882a593Smuzhiyun
cdv_intel_dp_add_properties(struct drm_connector * connector)1905*4882a593Smuzhiyun static void cdv_intel_dp_add_properties(struct drm_connector *connector)
1906*4882a593Smuzhiyun {
1907*4882a593Smuzhiyun cdv_intel_attach_force_audio_property(connector);
1908*4882a593Smuzhiyun cdv_intel_attach_broadcast_rgb_property(connector);
1909*4882a593Smuzhiyun }
1910*4882a593Smuzhiyun
1911*4882a593Smuzhiyun /* check the VBT to see whether the eDP is on DP-D port */
cdv_intel_dpc_is_edp(struct drm_device * dev)1912*4882a593Smuzhiyun static bool cdv_intel_dpc_is_edp(struct drm_device *dev)
1913*4882a593Smuzhiyun {
1914*4882a593Smuzhiyun struct drm_psb_private *dev_priv = dev->dev_private;
1915*4882a593Smuzhiyun struct child_device_config *p_child;
1916*4882a593Smuzhiyun int i;
1917*4882a593Smuzhiyun
1918*4882a593Smuzhiyun if (!dev_priv->child_dev_num)
1919*4882a593Smuzhiyun return false;
1920*4882a593Smuzhiyun
1921*4882a593Smuzhiyun for (i = 0; i < dev_priv->child_dev_num; i++) {
1922*4882a593Smuzhiyun p_child = dev_priv->child_dev + i;
1923*4882a593Smuzhiyun
1924*4882a593Smuzhiyun if (p_child->dvo_port == PORT_IDPC &&
1925*4882a593Smuzhiyun p_child->device_type == DEVICE_TYPE_eDP)
1926*4882a593Smuzhiyun return true;
1927*4882a593Smuzhiyun }
1928*4882a593Smuzhiyun return false;
1929*4882a593Smuzhiyun }
1930*4882a593Smuzhiyun
1931*4882a593Smuzhiyun /* Cedarview display clock gating
1932*4882a593Smuzhiyun
1933*4882a593Smuzhiyun We need this disable dot get correct behaviour while enabling
1934*4882a593Smuzhiyun DP/eDP. TODO - investigate if we can turn it back to normality
1935*4882a593Smuzhiyun after enabling */
cdv_disable_intel_clock_gating(struct drm_device * dev)1936*4882a593Smuzhiyun static void cdv_disable_intel_clock_gating(struct drm_device *dev)
1937*4882a593Smuzhiyun {
1938*4882a593Smuzhiyun u32 reg_value;
1939*4882a593Smuzhiyun reg_value = REG_READ(DSPCLK_GATE_D);
1940*4882a593Smuzhiyun
1941*4882a593Smuzhiyun reg_value |= (DPUNIT_PIPEB_GATE_DISABLE |
1942*4882a593Smuzhiyun DPUNIT_PIPEA_GATE_DISABLE |
1943*4882a593Smuzhiyun DPCUNIT_CLOCK_GATE_DISABLE |
1944*4882a593Smuzhiyun DPLSUNIT_CLOCK_GATE_DISABLE |
1945*4882a593Smuzhiyun DPOUNIT_CLOCK_GATE_DISABLE |
1946*4882a593Smuzhiyun DPIOUNIT_CLOCK_GATE_DISABLE);
1947*4882a593Smuzhiyun
1948*4882a593Smuzhiyun REG_WRITE(DSPCLK_GATE_D, reg_value);
1949*4882a593Smuzhiyun
1950*4882a593Smuzhiyun udelay(500);
1951*4882a593Smuzhiyun }
1952*4882a593Smuzhiyun
1953*4882a593Smuzhiyun void
cdv_intel_dp_init(struct drm_device * dev,struct psb_intel_mode_device * mode_dev,int output_reg)1954*4882a593Smuzhiyun cdv_intel_dp_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev, int output_reg)
1955*4882a593Smuzhiyun {
1956*4882a593Smuzhiyun struct gma_encoder *gma_encoder;
1957*4882a593Smuzhiyun struct gma_connector *gma_connector;
1958*4882a593Smuzhiyun struct drm_connector *connector;
1959*4882a593Smuzhiyun struct drm_encoder *encoder;
1960*4882a593Smuzhiyun struct cdv_intel_dp *intel_dp;
1961*4882a593Smuzhiyun const char *name = NULL;
1962*4882a593Smuzhiyun int type = DRM_MODE_CONNECTOR_DisplayPort;
1963*4882a593Smuzhiyun
1964*4882a593Smuzhiyun gma_encoder = kzalloc(sizeof(struct gma_encoder), GFP_KERNEL);
1965*4882a593Smuzhiyun if (!gma_encoder)
1966*4882a593Smuzhiyun return;
1967*4882a593Smuzhiyun gma_connector = kzalloc(sizeof(struct gma_connector), GFP_KERNEL);
1968*4882a593Smuzhiyun if (!gma_connector)
1969*4882a593Smuzhiyun goto err_connector;
1970*4882a593Smuzhiyun intel_dp = kzalloc(sizeof(struct cdv_intel_dp), GFP_KERNEL);
1971*4882a593Smuzhiyun if (!intel_dp)
1972*4882a593Smuzhiyun goto err_priv;
1973*4882a593Smuzhiyun
1974*4882a593Smuzhiyun if ((output_reg == DP_C) && cdv_intel_dpc_is_edp(dev))
1975*4882a593Smuzhiyun type = DRM_MODE_CONNECTOR_eDP;
1976*4882a593Smuzhiyun
1977*4882a593Smuzhiyun connector = &gma_connector->base;
1978*4882a593Smuzhiyun encoder = &gma_encoder->base;
1979*4882a593Smuzhiyun
1980*4882a593Smuzhiyun drm_connector_init(dev, connector, &cdv_intel_dp_connector_funcs, type);
1981*4882a593Smuzhiyun drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_TMDS);
1982*4882a593Smuzhiyun
1983*4882a593Smuzhiyun gma_connector_attach_encoder(gma_connector, gma_encoder);
1984*4882a593Smuzhiyun
1985*4882a593Smuzhiyun if (type == DRM_MODE_CONNECTOR_DisplayPort)
1986*4882a593Smuzhiyun gma_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
1987*4882a593Smuzhiyun else
1988*4882a593Smuzhiyun gma_encoder->type = INTEL_OUTPUT_EDP;
1989*4882a593Smuzhiyun
1990*4882a593Smuzhiyun
1991*4882a593Smuzhiyun gma_encoder->dev_priv=intel_dp;
1992*4882a593Smuzhiyun intel_dp->encoder = gma_encoder;
1993*4882a593Smuzhiyun intel_dp->output_reg = output_reg;
1994*4882a593Smuzhiyun
1995*4882a593Smuzhiyun drm_encoder_helper_add(encoder, &cdv_intel_dp_helper_funcs);
1996*4882a593Smuzhiyun drm_connector_helper_add(connector, &cdv_intel_dp_connector_helper_funcs);
1997*4882a593Smuzhiyun
1998*4882a593Smuzhiyun connector->polled = DRM_CONNECTOR_POLL_HPD;
1999*4882a593Smuzhiyun connector->interlace_allowed = false;
2000*4882a593Smuzhiyun connector->doublescan_allowed = false;
2001*4882a593Smuzhiyun
2002*4882a593Smuzhiyun drm_connector_register(connector);
2003*4882a593Smuzhiyun
2004*4882a593Smuzhiyun /* Set up the DDC bus. */
2005*4882a593Smuzhiyun switch (output_reg) {
2006*4882a593Smuzhiyun case DP_B:
2007*4882a593Smuzhiyun name = "DPDDC-B";
2008*4882a593Smuzhiyun gma_encoder->ddi_select = (DP_MASK | DDI0_SELECT);
2009*4882a593Smuzhiyun break;
2010*4882a593Smuzhiyun case DP_C:
2011*4882a593Smuzhiyun name = "DPDDC-C";
2012*4882a593Smuzhiyun gma_encoder->ddi_select = (DP_MASK | DDI1_SELECT);
2013*4882a593Smuzhiyun break;
2014*4882a593Smuzhiyun }
2015*4882a593Smuzhiyun
2016*4882a593Smuzhiyun cdv_disable_intel_clock_gating(dev);
2017*4882a593Smuzhiyun
2018*4882a593Smuzhiyun cdv_intel_dp_i2c_init(gma_connector, gma_encoder, name);
2019*4882a593Smuzhiyun /* FIXME:fail check */
2020*4882a593Smuzhiyun cdv_intel_dp_add_properties(connector);
2021*4882a593Smuzhiyun
2022*4882a593Smuzhiyun if (is_edp(gma_encoder)) {
2023*4882a593Smuzhiyun int ret;
2024*4882a593Smuzhiyun struct edp_power_seq cur;
2025*4882a593Smuzhiyun u32 pp_on, pp_off, pp_div;
2026*4882a593Smuzhiyun u32 pwm_ctrl;
2027*4882a593Smuzhiyun
2028*4882a593Smuzhiyun pp_on = REG_READ(PP_CONTROL);
2029*4882a593Smuzhiyun pp_on &= ~PANEL_UNLOCK_MASK;
2030*4882a593Smuzhiyun pp_on |= PANEL_UNLOCK_REGS;
2031*4882a593Smuzhiyun
2032*4882a593Smuzhiyun REG_WRITE(PP_CONTROL, pp_on);
2033*4882a593Smuzhiyun
2034*4882a593Smuzhiyun pwm_ctrl = REG_READ(BLC_PWM_CTL2);
2035*4882a593Smuzhiyun pwm_ctrl |= PWM_PIPE_B;
2036*4882a593Smuzhiyun REG_WRITE(BLC_PWM_CTL2, pwm_ctrl);
2037*4882a593Smuzhiyun
2038*4882a593Smuzhiyun pp_on = REG_READ(PP_ON_DELAYS);
2039*4882a593Smuzhiyun pp_off = REG_READ(PP_OFF_DELAYS);
2040*4882a593Smuzhiyun pp_div = REG_READ(PP_DIVISOR);
2041*4882a593Smuzhiyun
2042*4882a593Smuzhiyun /* Pull timing values out of registers */
2043*4882a593Smuzhiyun cur.t1_t3 = (pp_on & PANEL_POWER_UP_DELAY_MASK) >>
2044*4882a593Smuzhiyun PANEL_POWER_UP_DELAY_SHIFT;
2045*4882a593Smuzhiyun
2046*4882a593Smuzhiyun cur.t8 = (pp_on & PANEL_LIGHT_ON_DELAY_MASK) >>
2047*4882a593Smuzhiyun PANEL_LIGHT_ON_DELAY_SHIFT;
2048*4882a593Smuzhiyun
2049*4882a593Smuzhiyun cur.t9 = (pp_off & PANEL_LIGHT_OFF_DELAY_MASK) >>
2050*4882a593Smuzhiyun PANEL_LIGHT_OFF_DELAY_SHIFT;
2051*4882a593Smuzhiyun
2052*4882a593Smuzhiyun cur.t10 = (pp_off & PANEL_POWER_DOWN_DELAY_MASK) >>
2053*4882a593Smuzhiyun PANEL_POWER_DOWN_DELAY_SHIFT;
2054*4882a593Smuzhiyun
2055*4882a593Smuzhiyun cur.t11_t12 = ((pp_div & PANEL_POWER_CYCLE_DELAY_MASK) >>
2056*4882a593Smuzhiyun PANEL_POWER_CYCLE_DELAY_SHIFT);
2057*4882a593Smuzhiyun
2058*4882a593Smuzhiyun DRM_DEBUG_KMS("cur t1_t3 %d t8 %d t9 %d t10 %d t11_t12 %d\n",
2059*4882a593Smuzhiyun cur.t1_t3, cur.t8, cur.t9, cur.t10, cur.t11_t12);
2060*4882a593Smuzhiyun
2061*4882a593Smuzhiyun
2062*4882a593Smuzhiyun intel_dp->panel_power_up_delay = cur.t1_t3 / 10;
2063*4882a593Smuzhiyun intel_dp->backlight_on_delay = cur.t8 / 10;
2064*4882a593Smuzhiyun intel_dp->backlight_off_delay = cur.t9 / 10;
2065*4882a593Smuzhiyun intel_dp->panel_power_down_delay = cur.t10 / 10;
2066*4882a593Smuzhiyun intel_dp->panel_power_cycle_delay = (cur.t11_t12 - 1) * 100;
2067*4882a593Smuzhiyun
2068*4882a593Smuzhiyun DRM_DEBUG_KMS("panel power up delay %d, power down delay %d, power cycle delay %d\n",
2069*4882a593Smuzhiyun intel_dp->panel_power_up_delay, intel_dp->panel_power_down_delay,
2070*4882a593Smuzhiyun intel_dp->panel_power_cycle_delay);
2071*4882a593Smuzhiyun
2072*4882a593Smuzhiyun DRM_DEBUG_KMS("backlight on delay %d, off delay %d\n",
2073*4882a593Smuzhiyun intel_dp->backlight_on_delay, intel_dp->backlight_off_delay);
2074*4882a593Smuzhiyun
2075*4882a593Smuzhiyun
2076*4882a593Smuzhiyun cdv_intel_edp_panel_vdd_on(gma_encoder);
2077*4882a593Smuzhiyun ret = cdv_intel_dp_aux_native_read(gma_encoder, DP_DPCD_REV,
2078*4882a593Smuzhiyun intel_dp->dpcd,
2079*4882a593Smuzhiyun sizeof(intel_dp->dpcd));
2080*4882a593Smuzhiyun cdv_intel_edp_panel_vdd_off(gma_encoder);
2081*4882a593Smuzhiyun if (ret <= 0) {
2082*4882a593Smuzhiyun /* if this fails, presume the device is a ghost */
2083*4882a593Smuzhiyun DRM_INFO("failed to retrieve link info, disabling eDP\n");
2084*4882a593Smuzhiyun drm_encoder_cleanup(encoder);
2085*4882a593Smuzhiyun cdv_intel_dp_destroy(connector);
2086*4882a593Smuzhiyun goto err_connector;
2087*4882a593Smuzhiyun } else {
2088*4882a593Smuzhiyun DRM_DEBUG_KMS("DPCD: Rev=%x LN_Rate=%x LN_CNT=%x LN_DOWNSP=%x\n",
2089*4882a593Smuzhiyun intel_dp->dpcd[0], intel_dp->dpcd[1],
2090*4882a593Smuzhiyun intel_dp->dpcd[2], intel_dp->dpcd[3]);
2091*4882a593Smuzhiyun
2092*4882a593Smuzhiyun }
2093*4882a593Smuzhiyun /* The CDV reference driver moves pnale backlight setup into the displays that
2094*4882a593Smuzhiyun have a backlight: this is a good idea and one we should probably adopt, however
2095*4882a593Smuzhiyun we need to migrate all the drivers before we can do that */
2096*4882a593Smuzhiyun /*cdv_intel_panel_setup_backlight(dev); */
2097*4882a593Smuzhiyun }
2098*4882a593Smuzhiyun return;
2099*4882a593Smuzhiyun
2100*4882a593Smuzhiyun err_priv:
2101*4882a593Smuzhiyun kfree(gma_connector);
2102*4882a593Smuzhiyun err_connector:
2103*4882a593Smuzhiyun kfree(gma_encoder);
2104*4882a593Smuzhiyun }
2105