1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Copyright © 2006-2011 Intel Corporation
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Authors:
6*4882a593Smuzhiyun * Eric Anholt <eric@anholt.net>
7*4882a593Smuzhiyun */
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun #include <linux/delay.h>
10*4882a593Smuzhiyun #include <linux/i2c.h>
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun #include <drm/drm_crtc.h>
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun #include "cdv_device.h"
15*4882a593Smuzhiyun #include "framebuffer.h"
16*4882a593Smuzhiyun #include "gma_display.h"
17*4882a593Smuzhiyun #include "power.h"
18*4882a593Smuzhiyun #include "psb_drv.h"
19*4882a593Smuzhiyun #include "psb_intel_drv.h"
20*4882a593Smuzhiyun #include "psb_intel_reg.h"
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun static bool cdv_intel_find_dp_pll(const struct gma_limit_t *limit,
23*4882a593Smuzhiyun struct drm_crtc *crtc, int target,
24*4882a593Smuzhiyun int refclk, struct gma_clock_t *best_clock);
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun #define CDV_LIMIT_SINGLE_LVDS_96 0
28*4882a593Smuzhiyun #define CDV_LIMIT_SINGLE_LVDS_100 1
29*4882a593Smuzhiyun #define CDV_LIMIT_DAC_HDMI_27 2
30*4882a593Smuzhiyun #define CDV_LIMIT_DAC_HDMI_96 3
31*4882a593Smuzhiyun #define CDV_LIMIT_DP_27 4
32*4882a593Smuzhiyun #define CDV_LIMIT_DP_100 5
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun static const struct gma_limit_t cdv_intel_limits[] = {
35*4882a593Smuzhiyun { /* CDV_SINGLE_LVDS_96MHz */
36*4882a593Smuzhiyun .dot = {.min = 20000, .max = 115500},
37*4882a593Smuzhiyun .vco = {.min = 1800000, .max = 3600000},
38*4882a593Smuzhiyun .n = {.min = 2, .max = 6},
39*4882a593Smuzhiyun .m = {.min = 60, .max = 160},
40*4882a593Smuzhiyun .m1 = {.min = 0, .max = 0},
41*4882a593Smuzhiyun .m2 = {.min = 58, .max = 158},
42*4882a593Smuzhiyun .p = {.min = 28, .max = 140},
43*4882a593Smuzhiyun .p1 = {.min = 2, .max = 10},
44*4882a593Smuzhiyun .p2 = {.dot_limit = 200000, .p2_slow = 14, .p2_fast = 14},
45*4882a593Smuzhiyun .find_pll = gma_find_best_pll,
46*4882a593Smuzhiyun },
47*4882a593Smuzhiyun { /* CDV_SINGLE_LVDS_100MHz */
48*4882a593Smuzhiyun .dot = {.min = 20000, .max = 115500},
49*4882a593Smuzhiyun .vco = {.min = 1800000, .max = 3600000},
50*4882a593Smuzhiyun .n = {.min = 2, .max = 6},
51*4882a593Smuzhiyun .m = {.min = 60, .max = 160},
52*4882a593Smuzhiyun .m1 = {.min = 0, .max = 0},
53*4882a593Smuzhiyun .m2 = {.min = 58, .max = 158},
54*4882a593Smuzhiyun .p = {.min = 28, .max = 140},
55*4882a593Smuzhiyun .p1 = {.min = 2, .max = 10},
56*4882a593Smuzhiyun /* The single-channel range is 25-112Mhz, and dual-channel
57*4882a593Smuzhiyun * is 80-224Mhz. Prefer single channel as much as possible.
58*4882a593Smuzhiyun */
59*4882a593Smuzhiyun .p2 = {.dot_limit = 200000, .p2_slow = 14, .p2_fast = 14},
60*4882a593Smuzhiyun .find_pll = gma_find_best_pll,
61*4882a593Smuzhiyun },
62*4882a593Smuzhiyun { /* CDV_DAC_HDMI_27MHz */
63*4882a593Smuzhiyun .dot = {.min = 20000, .max = 400000},
64*4882a593Smuzhiyun .vco = {.min = 1809000, .max = 3564000},
65*4882a593Smuzhiyun .n = {.min = 1, .max = 1},
66*4882a593Smuzhiyun .m = {.min = 67, .max = 132},
67*4882a593Smuzhiyun .m1 = {.min = 0, .max = 0},
68*4882a593Smuzhiyun .m2 = {.min = 65, .max = 130},
69*4882a593Smuzhiyun .p = {.min = 5, .max = 90},
70*4882a593Smuzhiyun .p1 = {.min = 1, .max = 9},
71*4882a593Smuzhiyun .p2 = {.dot_limit = 225000, .p2_slow = 10, .p2_fast = 5},
72*4882a593Smuzhiyun .find_pll = gma_find_best_pll,
73*4882a593Smuzhiyun },
74*4882a593Smuzhiyun { /* CDV_DAC_HDMI_96MHz */
75*4882a593Smuzhiyun .dot = {.min = 20000, .max = 400000},
76*4882a593Smuzhiyun .vco = {.min = 1800000, .max = 3600000},
77*4882a593Smuzhiyun .n = {.min = 2, .max = 6},
78*4882a593Smuzhiyun .m = {.min = 60, .max = 160},
79*4882a593Smuzhiyun .m1 = {.min = 0, .max = 0},
80*4882a593Smuzhiyun .m2 = {.min = 58, .max = 158},
81*4882a593Smuzhiyun .p = {.min = 5, .max = 100},
82*4882a593Smuzhiyun .p1 = {.min = 1, .max = 10},
83*4882a593Smuzhiyun .p2 = {.dot_limit = 225000, .p2_slow = 10, .p2_fast = 5},
84*4882a593Smuzhiyun .find_pll = gma_find_best_pll,
85*4882a593Smuzhiyun },
86*4882a593Smuzhiyun { /* CDV_DP_27MHz */
87*4882a593Smuzhiyun .dot = {.min = 160000, .max = 272000},
88*4882a593Smuzhiyun .vco = {.min = 1809000, .max = 3564000},
89*4882a593Smuzhiyun .n = {.min = 1, .max = 1},
90*4882a593Smuzhiyun .m = {.min = 67, .max = 132},
91*4882a593Smuzhiyun .m1 = {.min = 0, .max = 0},
92*4882a593Smuzhiyun .m2 = {.min = 65, .max = 130},
93*4882a593Smuzhiyun .p = {.min = 5, .max = 90},
94*4882a593Smuzhiyun .p1 = {.min = 1, .max = 9},
95*4882a593Smuzhiyun .p2 = {.dot_limit = 225000, .p2_slow = 10, .p2_fast = 10},
96*4882a593Smuzhiyun .find_pll = cdv_intel_find_dp_pll,
97*4882a593Smuzhiyun },
98*4882a593Smuzhiyun { /* CDV_DP_100MHz */
99*4882a593Smuzhiyun .dot = {.min = 160000, .max = 272000},
100*4882a593Smuzhiyun .vco = {.min = 1800000, .max = 3600000},
101*4882a593Smuzhiyun .n = {.min = 2, .max = 6},
102*4882a593Smuzhiyun .m = {.min = 60, .max = 164},
103*4882a593Smuzhiyun .m1 = {.min = 0, .max = 0},
104*4882a593Smuzhiyun .m2 = {.min = 58, .max = 162},
105*4882a593Smuzhiyun .p = {.min = 5, .max = 100},
106*4882a593Smuzhiyun .p1 = {.min = 1, .max = 10},
107*4882a593Smuzhiyun .p2 = {.dot_limit = 225000, .p2_slow = 10, .p2_fast = 10},
108*4882a593Smuzhiyun .find_pll = cdv_intel_find_dp_pll,
109*4882a593Smuzhiyun }
110*4882a593Smuzhiyun };
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun #define _wait_for(COND, MS, W) ({ \
113*4882a593Smuzhiyun unsigned long timeout__ = jiffies + msecs_to_jiffies(MS); \
114*4882a593Smuzhiyun int ret__ = 0; \
115*4882a593Smuzhiyun while (!(COND)) { \
116*4882a593Smuzhiyun if (time_after(jiffies, timeout__)) { \
117*4882a593Smuzhiyun ret__ = -ETIMEDOUT; \
118*4882a593Smuzhiyun break; \
119*4882a593Smuzhiyun } \
120*4882a593Smuzhiyun if (W && !in_dbg_master()) \
121*4882a593Smuzhiyun msleep(W); \
122*4882a593Smuzhiyun } \
123*4882a593Smuzhiyun ret__; \
124*4882a593Smuzhiyun })
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun #define wait_for(COND, MS) _wait_for(COND, MS, 1)
127*4882a593Smuzhiyun
128*4882a593Smuzhiyun
cdv_sb_read(struct drm_device * dev,u32 reg,u32 * val)129*4882a593Smuzhiyun int cdv_sb_read(struct drm_device *dev, u32 reg, u32 *val)
130*4882a593Smuzhiyun {
131*4882a593Smuzhiyun int ret;
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun ret = wait_for((REG_READ(SB_PCKT) & SB_BUSY) == 0, 1000);
134*4882a593Smuzhiyun if (ret) {
135*4882a593Smuzhiyun DRM_ERROR("timeout waiting for SB to idle before read\n");
136*4882a593Smuzhiyun return ret;
137*4882a593Smuzhiyun }
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun REG_WRITE(SB_ADDR, reg);
140*4882a593Smuzhiyun REG_WRITE(SB_PCKT,
141*4882a593Smuzhiyun SET_FIELD(SB_OPCODE_READ, SB_OPCODE) |
142*4882a593Smuzhiyun SET_FIELD(SB_DEST_DPLL, SB_DEST) |
143*4882a593Smuzhiyun SET_FIELD(0xf, SB_BYTE_ENABLE));
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun ret = wait_for((REG_READ(SB_PCKT) & SB_BUSY) == 0, 1000);
146*4882a593Smuzhiyun if (ret) {
147*4882a593Smuzhiyun DRM_ERROR("timeout waiting for SB to idle after read\n");
148*4882a593Smuzhiyun return ret;
149*4882a593Smuzhiyun }
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun *val = REG_READ(SB_DATA);
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun return 0;
154*4882a593Smuzhiyun }
155*4882a593Smuzhiyun
cdv_sb_write(struct drm_device * dev,u32 reg,u32 val)156*4882a593Smuzhiyun int cdv_sb_write(struct drm_device *dev, u32 reg, u32 val)
157*4882a593Smuzhiyun {
158*4882a593Smuzhiyun int ret;
159*4882a593Smuzhiyun static bool dpio_debug = true;
160*4882a593Smuzhiyun u32 temp;
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun if (dpio_debug) {
163*4882a593Smuzhiyun if (cdv_sb_read(dev, reg, &temp) == 0)
164*4882a593Smuzhiyun DRM_DEBUG_KMS("0x%08x: 0x%08x (before)\n", reg, temp);
165*4882a593Smuzhiyun DRM_DEBUG_KMS("0x%08x: 0x%08x\n", reg, val);
166*4882a593Smuzhiyun }
167*4882a593Smuzhiyun
168*4882a593Smuzhiyun ret = wait_for((REG_READ(SB_PCKT) & SB_BUSY) == 0, 1000);
169*4882a593Smuzhiyun if (ret) {
170*4882a593Smuzhiyun DRM_ERROR("timeout waiting for SB to idle before write\n");
171*4882a593Smuzhiyun return ret;
172*4882a593Smuzhiyun }
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun REG_WRITE(SB_ADDR, reg);
175*4882a593Smuzhiyun REG_WRITE(SB_DATA, val);
176*4882a593Smuzhiyun REG_WRITE(SB_PCKT,
177*4882a593Smuzhiyun SET_FIELD(SB_OPCODE_WRITE, SB_OPCODE) |
178*4882a593Smuzhiyun SET_FIELD(SB_DEST_DPLL, SB_DEST) |
179*4882a593Smuzhiyun SET_FIELD(0xf, SB_BYTE_ENABLE));
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun ret = wait_for((REG_READ(SB_PCKT) & SB_BUSY) == 0, 1000);
182*4882a593Smuzhiyun if (ret) {
183*4882a593Smuzhiyun DRM_ERROR("timeout waiting for SB to idle after write\n");
184*4882a593Smuzhiyun return ret;
185*4882a593Smuzhiyun }
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun if (dpio_debug) {
188*4882a593Smuzhiyun if (cdv_sb_read(dev, reg, &temp) == 0)
189*4882a593Smuzhiyun DRM_DEBUG_KMS("0x%08x: 0x%08x (after)\n", reg, temp);
190*4882a593Smuzhiyun }
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun return 0;
193*4882a593Smuzhiyun }
194*4882a593Smuzhiyun
195*4882a593Smuzhiyun /* Reset the DPIO configuration register. The BIOS does this at every
196*4882a593Smuzhiyun * mode set.
197*4882a593Smuzhiyun */
cdv_sb_reset(struct drm_device * dev)198*4882a593Smuzhiyun void cdv_sb_reset(struct drm_device *dev)
199*4882a593Smuzhiyun {
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun REG_WRITE(DPIO_CFG, 0);
202*4882a593Smuzhiyun REG_READ(DPIO_CFG);
203*4882a593Smuzhiyun REG_WRITE(DPIO_CFG, DPIO_MODE_SELECT_0 | DPIO_CMN_RESET_N);
204*4882a593Smuzhiyun }
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun /* Unlike most Intel display engines, on Cedarview the DPLL registers
207*4882a593Smuzhiyun * are behind this sideband bus. They must be programmed while the
208*4882a593Smuzhiyun * DPLL reference clock is on in the DPLL control register, but before
209*4882a593Smuzhiyun * the DPLL is enabled in the DPLL control register.
210*4882a593Smuzhiyun */
211*4882a593Smuzhiyun static int
cdv_dpll_set_clock_cdv(struct drm_device * dev,struct drm_crtc * crtc,struct gma_clock_t * clock,bool is_lvds,u32 ddi_select)212*4882a593Smuzhiyun cdv_dpll_set_clock_cdv(struct drm_device *dev, struct drm_crtc *crtc,
213*4882a593Smuzhiyun struct gma_clock_t *clock, bool is_lvds, u32 ddi_select)
214*4882a593Smuzhiyun {
215*4882a593Smuzhiyun struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
216*4882a593Smuzhiyun int pipe = gma_crtc->pipe;
217*4882a593Smuzhiyun u32 m, n_vco, p;
218*4882a593Smuzhiyun int ret = 0;
219*4882a593Smuzhiyun int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
220*4882a593Smuzhiyun int ref_sfr = (pipe == 0) ? SB_REF_DPLLA : SB_REF_DPLLB;
221*4882a593Smuzhiyun u32 ref_value;
222*4882a593Smuzhiyun u32 lane_reg, lane_value;
223*4882a593Smuzhiyun
224*4882a593Smuzhiyun cdv_sb_reset(dev);
225*4882a593Smuzhiyun
226*4882a593Smuzhiyun REG_WRITE(dpll_reg, DPLL_SYNCLOCK_ENABLE | DPLL_VGA_MODE_DIS);
227*4882a593Smuzhiyun
228*4882a593Smuzhiyun udelay(100);
229*4882a593Smuzhiyun
230*4882a593Smuzhiyun /* Follow the BIOS and write the REF/SFR Register. Hardcoded value */
231*4882a593Smuzhiyun ref_value = 0x68A701;
232*4882a593Smuzhiyun
233*4882a593Smuzhiyun cdv_sb_write(dev, SB_REF_SFR(pipe), ref_value);
234*4882a593Smuzhiyun
235*4882a593Smuzhiyun /* We don't know what the other fields of these regs are, so
236*4882a593Smuzhiyun * leave them in place.
237*4882a593Smuzhiyun */
238*4882a593Smuzhiyun /*
239*4882a593Smuzhiyun * The BIT 14:13 of 0x8010/0x8030 is used to select the ref clk
240*4882a593Smuzhiyun * for the pipe A/B. Display spec 1.06 has wrong definition.
241*4882a593Smuzhiyun * Correct definition is like below:
242*4882a593Smuzhiyun *
243*4882a593Smuzhiyun * refclka mean use clock from same PLL
244*4882a593Smuzhiyun *
245*4882a593Smuzhiyun * if DPLLA sets 01 and DPLLB sets 01, they use clock from their pll
246*4882a593Smuzhiyun *
247*4882a593Smuzhiyun * if DPLLA sets 01 and DPLLB sets 02, both use clk from DPLLA
248*4882a593Smuzhiyun *
249*4882a593Smuzhiyun */
250*4882a593Smuzhiyun ret = cdv_sb_read(dev, ref_sfr, &ref_value);
251*4882a593Smuzhiyun if (ret)
252*4882a593Smuzhiyun return ret;
253*4882a593Smuzhiyun ref_value &= ~(REF_CLK_MASK);
254*4882a593Smuzhiyun
255*4882a593Smuzhiyun /* use DPLL_A for pipeB on CRT/HDMI */
256*4882a593Smuzhiyun if (pipe == 1 && !is_lvds && !(ddi_select & DP_MASK)) {
257*4882a593Smuzhiyun DRM_DEBUG_KMS("use DPLLA for pipe B\n");
258*4882a593Smuzhiyun ref_value |= REF_CLK_DPLLA;
259*4882a593Smuzhiyun } else {
260*4882a593Smuzhiyun DRM_DEBUG_KMS("use their DPLL for pipe A/B\n");
261*4882a593Smuzhiyun ref_value |= REF_CLK_DPLL;
262*4882a593Smuzhiyun }
263*4882a593Smuzhiyun ret = cdv_sb_write(dev, ref_sfr, ref_value);
264*4882a593Smuzhiyun if (ret)
265*4882a593Smuzhiyun return ret;
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun ret = cdv_sb_read(dev, SB_M(pipe), &m);
268*4882a593Smuzhiyun if (ret)
269*4882a593Smuzhiyun return ret;
270*4882a593Smuzhiyun m &= ~SB_M_DIVIDER_MASK;
271*4882a593Smuzhiyun m |= ((clock->m2) << SB_M_DIVIDER_SHIFT);
272*4882a593Smuzhiyun ret = cdv_sb_write(dev, SB_M(pipe), m);
273*4882a593Smuzhiyun if (ret)
274*4882a593Smuzhiyun return ret;
275*4882a593Smuzhiyun
276*4882a593Smuzhiyun ret = cdv_sb_read(dev, SB_N_VCO(pipe), &n_vco);
277*4882a593Smuzhiyun if (ret)
278*4882a593Smuzhiyun return ret;
279*4882a593Smuzhiyun
280*4882a593Smuzhiyun /* Follow the BIOS to program the N_DIVIDER REG */
281*4882a593Smuzhiyun n_vco &= 0xFFFF;
282*4882a593Smuzhiyun n_vco |= 0x107;
283*4882a593Smuzhiyun n_vco &= ~(SB_N_VCO_SEL_MASK |
284*4882a593Smuzhiyun SB_N_DIVIDER_MASK |
285*4882a593Smuzhiyun SB_N_CB_TUNE_MASK);
286*4882a593Smuzhiyun
287*4882a593Smuzhiyun n_vco |= ((clock->n) << SB_N_DIVIDER_SHIFT);
288*4882a593Smuzhiyun
289*4882a593Smuzhiyun if (clock->vco < 2250000) {
290*4882a593Smuzhiyun n_vco |= (2 << SB_N_CB_TUNE_SHIFT);
291*4882a593Smuzhiyun n_vco |= (0 << SB_N_VCO_SEL_SHIFT);
292*4882a593Smuzhiyun } else if (clock->vco < 2750000) {
293*4882a593Smuzhiyun n_vco |= (1 << SB_N_CB_TUNE_SHIFT);
294*4882a593Smuzhiyun n_vco |= (1 << SB_N_VCO_SEL_SHIFT);
295*4882a593Smuzhiyun } else if (clock->vco < 3300000) {
296*4882a593Smuzhiyun n_vco |= (0 << SB_N_CB_TUNE_SHIFT);
297*4882a593Smuzhiyun n_vco |= (2 << SB_N_VCO_SEL_SHIFT);
298*4882a593Smuzhiyun } else {
299*4882a593Smuzhiyun n_vco |= (0 << SB_N_CB_TUNE_SHIFT);
300*4882a593Smuzhiyun n_vco |= (3 << SB_N_VCO_SEL_SHIFT);
301*4882a593Smuzhiyun }
302*4882a593Smuzhiyun
303*4882a593Smuzhiyun ret = cdv_sb_write(dev, SB_N_VCO(pipe), n_vco);
304*4882a593Smuzhiyun if (ret)
305*4882a593Smuzhiyun return ret;
306*4882a593Smuzhiyun
307*4882a593Smuzhiyun ret = cdv_sb_read(dev, SB_P(pipe), &p);
308*4882a593Smuzhiyun if (ret)
309*4882a593Smuzhiyun return ret;
310*4882a593Smuzhiyun p &= ~(SB_P2_DIVIDER_MASK | SB_P1_DIVIDER_MASK);
311*4882a593Smuzhiyun p |= SET_FIELD(clock->p1, SB_P1_DIVIDER);
312*4882a593Smuzhiyun switch (clock->p2) {
313*4882a593Smuzhiyun case 5:
314*4882a593Smuzhiyun p |= SET_FIELD(SB_P2_5, SB_P2_DIVIDER);
315*4882a593Smuzhiyun break;
316*4882a593Smuzhiyun case 10:
317*4882a593Smuzhiyun p |= SET_FIELD(SB_P2_10, SB_P2_DIVIDER);
318*4882a593Smuzhiyun break;
319*4882a593Smuzhiyun case 14:
320*4882a593Smuzhiyun p |= SET_FIELD(SB_P2_14, SB_P2_DIVIDER);
321*4882a593Smuzhiyun break;
322*4882a593Smuzhiyun case 7:
323*4882a593Smuzhiyun p |= SET_FIELD(SB_P2_7, SB_P2_DIVIDER);
324*4882a593Smuzhiyun break;
325*4882a593Smuzhiyun default:
326*4882a593Smuzhiyun DRM_ERROR("Bad P2 clock: %d\n", clock->p2);
327*4882a593Smuzhiyun return -EINVAL;
328*4882a593Smuzhiyun }
329*4882a593Smuzhiyun ret = cdv_sb_write(dev, SB_P(pipe), p);
330*4882a593Smuzhiyun if (ret)
331*4882a593Smuzhiyun return ret;
332*4882a593Smuzhiyun
333*4882a593Smuzhiyun if (ddi_select) {
334*4882a593Smuzhiyun if ((ddi_select & DDI_MASK) == DDI0_SELECT) {
335*4882a593Smuzhiyun lane_reg = PSB_LANE0;
336*4882a593Smuzhiyun cdv_sb_read(dev, lane_reg, &lane_value);
337*4882a593Smuzhiyun lane_value &= ~(LANE_PLL_MASK);
338*4882a593Smuzhiyun lane_value |= LANE_PLL_ENABLE | LANE_PLL_PIPE(pipe);
339*4882a593Smuzhiyun cdv_sb_write(dev, lane_reg, lane_value);
340*4882a593Smuzhiyun
341*4882a593Smuzhiyun lane_reg = PSB_LANE1;
342*4882a593Smuzhiyun cdv_sb_read(dev, lane_reg, &lane_value);
343*4882a593Smuzhiyun lane_value &= ~(LANE_PLL_MASK);
344*4882a593Smuzhiyun lane_value |= LANE_PLL_ENABLE | LANE_PLL_PIPE(pipe);
345*4882a593Smuzhiyun cdv_sb_write(dev, lane_reg, lane_value);
346*4882a593Smuzhiyun } else {
347*4882a593Smuzhiyun lane_reg = PSB_LANE2;
348*4882a593Smuzhiyun cdv_sb_read(dev, lane_reg, &lane_value);
349*4882a593Smuzhiyun lane_value &= ~(LANE_PLL_MASK);
350*4882a593Smuzhiyun lane_value |= LANE_PLL_ENABLE | LANE_PLL_PIPE(pipe);
351*4882a593Smuzhiyun cdv_sb_write(dev, lane_reg, lane_value);
352*4882a593Smuzhiyun
353*4882a593Smuzhiyun lane_reg = PSB_LANE3;
354*4882a593Smuzhiyun cdv_sb_read(dev, lane_reg, &lane_value);
355*4882a593Smuzhiyun lane_value &= ~(LANE_PLL_MASK);
356*4882a593Smuzhiyun lane_value |= LANE_PLL_ENABLE | LANE_PLL_PIPE(pipe);
357*4882a593Smuzhiyun cdv_sb_write(dev, lane_reg, lane_value);
358*4882a593Smuzhiyun }
359*4882a593Smuzhiyun }
360*4882a593Smuzhiyun return 0;
361*4882a593Smuzhiyun }
362*4882a593Smuzhiyun
cdv_intel_limit(struct drm_crtc * crtc,int refclk)363*4882a593Smuzhiyun static const struct gma_limit_t *cdv_intel_limit(struct drm_crtc *crtc,
364*4882a593Smuzhiyun int refclk)
365*4882a593Smuzhiyun {
366*4882a593Smuzhiyun const struct gma_limit_t *limit;
367*4882a593Smuzhiyun if (gma_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
368*4882a593Smuzhiyun /*
369*4882a593Smuzhiyun * Now only single-channel LVDS is supported on CDV. If it is
370*4882a593Smuzhiyun * incorrect, please add the dual-channel LVDS.
371*4882a593Smuzhiyun */
372*4882a593Smuzhiyun if (refclk == 96000)
373*4882a593Smuzhiyun limit = &cdv_intel_limits[CDV_LIMIT_SINGLE_LVDS_96];
374*4882a593Smuzhiyun else
375*4882a593Smuzhiyun limit = &cdv_intel_limits[CDV_LIMIT_SINGLE_LVDS_100];
376*4882a593Smuzhiyun } else if (gma_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) ||
377*4882a593Smuzhiyun gma_pipe_has_type(crtc, INTEL_OUTPUT_EDP)) {
378*4882a593Smuzhiyun if (refclk == 27000)
379*4882a593Smuzhiyun limit = &cdv_intel_limits[CDV_LIMIT_DP_27];
380*4882a593Smuzhiyun else
381*4882a593Smuzhiyun limit = &cdv_intel_limits[CDV_LIMIT_DP_100];
382*4882a593Smuzhiyun } else {
383*4882a593Smuzhiyun if (refclk == 27000)
384*4882a593Smuzhiyun limit = &cdv_intel_limits[CDV_LIMIT_DAC_HDMI_27];
385*4882a593Smuzhiyun else
386*4882a593Smuzhiyun limit = &cdv_intel_limits[CDV_LIMIT_DAC_HDMI_96];
387*4882a593Smuzhiyun }
388*4882a593Smuzhiyun return limit;
389*4882a593Smuzhiyun }
390*4882a593Smuzhiyun
391*4882a593Smuzhiyun /* m1 is reserved as 0 in CDV, n is a ring counter */
cdv_intel_clock(int refclk,struct gma_clock_t * clock)392*4882a593Smuzhiyun static void cdv_intel_clock(int refclk, struct gma_clock_t *clock)
393*4882a593Smuzhiyun {
394*4882a593Smuzhiyun clock->m = clock->m2 + 2;
395*4882a593Smuzhiyun clock->p = clock->p1 * clock->p2;
396*4882a593Smuzhiyun clock->vco = (refclk * clock->m) / clock->n;
397*4882a593Smuzhiyun clock->dot = clock->vco / clock->p;
398*4882a593Smuzhiyun }
399*4882a593Smuzhiyun
cdv_intel_find_dp_pll(const struct gma_limit_t * limit,struct drm_crtc * crtc,int target,int refclk,struct gma_clock_t * best_clock)400*4882a593Smuzhiyun static bool cdv_intel_find_dp_pll(const struct gma_limit_t *limit,
401*4882a593Smuzhiyun struct drm_crtc *crtc, int target,
402*4882a593Smuzhiyun int refclk,
403*4882a593Smuzhiyun struct gma_clock_t *best_clock)
404*4882a593Smuzhiyun {
405*4882a593Smuzhiyun struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
406*4882a593Smuzhiyun struct gma_clock_t clock;
407*4882a593Smuzhiyun
408*4882a593Smuzhiyun memset(&clock, 0, sizeof(clock));
409*4882a593Smuzhiyun
410*4882a593Smuzhiyun switch (refclk) {
411*4882a593Smuzhiyun case 27000:
412*4882a593Smuzhiyun if (target < 200000) {
413*4882a593Smuzhiyun clock.p1 = 2;
414*4882a593Smuzhiyun clock.p2 = 10;
415*4882a593Smuzhiyun clock.n = 1;
416*4882a593Smuzhiyun clock.m1 = 0;
417*4882a593Smuzhiyun clock.m2 = 118;
418*4882a593Smuzhiyun } else {
419*4882a593Smuzhiyun clock.p1 = 1;
420*4882a593Smuzhiyun clock.p2 = 10;
421*4882a593Smuzhiyun clock.n = 1;
422*4882a593Smuzhiyun clock.m1 = 0;
423*4882a593Smuzhiyun clock.m2 = 98;
424*4882a593Smuzhiyun }
425*4882a593Smuzhiyun break;
426*4882a593Smuzhiyun
427*4882a593Smuzhiyun case 100000:
428*4882a593Smuzhiyun if (target < 200000) {
429*4882a593Smuzhiyun clock.p1 = 2;
430*4882a593Smuzhiyun clock.p2 = 10;
431*4882a593Smuzhiyun clock.n = 5;
432*4882a593Smuzhiyun clock.m1 = 0;
433*4882a593Smuzhiyun clock.m2 = 160;
434*4882a593Smuzhiyun } else {
435*4882a593Smuzhiyun clock.p1 = 1;
436*4882a593Smuzhiyun clock.p2 = 10;
437*4882a593Smuzhiyun clock.n = 5;
438*4882a593Smuzhiyun clock.m1 = 0;
439*4882a593Smuzhiyun clock.m2 = 133;
440*4882a593Smuzhiyun }
441*4882a593Smuzhiyun break;
442*4882a593Smuzhiyun
443*4882a593Smuzhiyun default:
444*4882a593Smuzhiyun return false;
445*4882a593Smuzhiyun }
446*4882a593Smuzhiyun
447*4882a593Smuzhiyun gma_crtc->clock_funcs->clock(refclk, &clock);
448*4882a593Smuzhiyun memcpy(best_clock, &clock, sizeof(struct gma_clock_t));
449*4882a593Smuzhiyun return true;
450*4882a593Smuzhiyun }
451*4882a593Smuzhiyun
452*4882a593Smuzhiyun #define FIFO_PIPEA (1 << 0)
453*4882a593Smuzhiyun #define FIFO_PIPEB (1 << 1)
454*4882a593Smuzhiyun
cdv_intel_pipe_enabled(struct drm_device * dev,int pipe)455*4882a593Smuzhiyun static bool cdv_intel_pipe_enabled(struct drm_device *dev, int pipe)
456*4882a593Smuzhiyun {
457*4882a593Smuzhiyun struct drm_crtc *crtc;
458*4882a593Smuzhiyun struct drm_psb_private *dev_priv = dev->dev_private;
459*4882a593Smuzhiyun struct gma_crtc *gma_crtc = NULL;
460*4882a593Smuzhiyun
461*4882a593Smuzhiyun crtc = dev_priv->pipe_to_crtc_mapping[pipe];
462*4882a593Smuzhiyun gma_crtc = to_gma_crtc(crtc);
463*4882a593Smuzhiyun
464*4882a593Smuzhiyun if (crtc->primary->fb == NULL || !gma_crtc->active)
465*4882a593Smuzhiyun return false;
466*4882a593Smuzhiyun return true;
467*4882a593Smuzhiyun }
468*4882a593Smuzhiyun
cdv_disable_sr(struct drm_device * dev)469*4882a593Smuzhiyun void cdv_disable_sr(struct drm_device *dev)
470*4882a593Smuzhiyun {
471*4882a593Smuzhiyun if (REG_READ(FW_BLC_SELF) & FW_BLC_SELF_EN) {
472*4882a593Smuzhiyun
473*4882a593Smuzhiyun /* Disable self-refresh before adjust WM */
474*4882a593Smuzhiyun REG_WRITE(FW_BLC_SELF, (REG_READ(FW_BLC_SELF) & ~FW_BLC_SELF_EN));
475*4882a593Smuzhiyun REG_READ(FW_BLC_SELF);
476*4882a593Smuzhiyun
477*4882a593Smuzhiyun gma_wait_for_vblank(dev);
478*4882a593Smuzhiyun
479*4882a593Smuzhiyun /* Cedarview workaround to write ovelay plane, which force to leave
480*4882a593Smuzhiyun * MAX_FIFO state.
481*4882a593Smuzhiyun */
482*4882a593Smuzhiyun REG_WRITE(OV_OVADD, 0/*dev_priv->ovl_offset*/);
483*4882a593Smuzhiyun REG_READ(OV_OVADD);
484*4882a593Smuzhiyun
485*4882a593Smuzhiyun gma_wait_for_vblank(dev);
486*4882a593Smuzhiyun }
487*4882a593Smuzhiyun
488*4882a593Smuzhiyun }
489*4882a593Smuzhiyun
cdv_update_wm(struct drm_device * dev,struct drm_crtc * crtc)490*4882a593Smuzhiyun void cdv_update_wm(struct drm_device *dev, struct drm_crtc *crtc)
491*4882a593Smuzhiyun {
492*4882a593Smuzhiyun struct drm_psb_private *dev_priv = dev->dev_private;
493*4882a593Smuzhiyun struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
494*4882a593Smuzhiyun
495*4882a593Smuzhiyun /* Is only one pipe enabled? */
496*4882a593Smuzhiyun if (cdv_intel_pipe_enabled(dev, 0) ^ cdv_intel_pipe_enabled(dev, 1)) {
497*4882a593Smuzhiyun u32 fw;
498*4882a593Smuzhiyun
499*4882a593Smuzhiyun fw = REG_READ(DSPFW1);
500*4882a593Smuzhiyun fw &= ~DSP_FIFO_SR_WM_MASK;
501*4882a593Smuzhiyun fw |= (0x7e << DSP_FIFO_SR_WM_SHIFT);
502*4882a593Smuzhiyun fw &= ~CURSOR_B_FIFO_WM_MASK;
503*4882a593Smuzhiyun fw |= (0x4 << CURSOR_B_FIFO_WM_SHIFT);
504*4882a593Smuzhiyun REG_WRITE(DSPFW1, fw);
505*4882a593Smuzhiyun
506*4882a593Smuzhiyun fw = REG_READ(DSPFW2);
507*4882a593Smuzhiyun fw &= ~CURSOR_A_FIFO_WM_MASK;
508*4882a593Smuzhiyun fw |= (0x6 << CURSOR_A_FIFO_WM_SHIFT);
509*4882a593Smuzhiyun fw &= ~DSP_PLANE_C_FIFO_WM_MASK;
510*4882a593Smuzhiyun fw |= (0x8 << DSP_PLANE_C_FIFO_WM_SHIFT);
511*4882a593Smuzhiyun REG_WRITE(DSPFW2, fw);
512*4882a593Smuzhiyun
513*4882a593Smuzhiyun REG_WRITE(DSPFW3, 0x36000000);
514*4882a593Smuzhiyun
515*4882a593Smuzhiyun /* ignore FW4 */
516*4882a593Smuzhiyun
517*4882a593Smuzhiyun /* Is pipe b lvds ? */
518*4882a593Smuzhiyun if (gma_crtc->pipe == 1 &&
519*4882a593Smuzhiyun gma_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
520*4882a593Smuzhiyun REG_WRITE(DSPFW5, 0x00040330);
521*4882a593Smuzhiyun } else {
522*4882a593Smuzhiyun fw = (3 << DSP_PLANE_B_FIFO_WM1_SHIFT) |
523*4882a593Smuzhiyun (4 << DSP_PLANE_A_FIFO_WM1_SHIFT) |
524*4882a593Smuzhiyun (3 << CURSOR_B_FIFO_WM1_SHIFT) |
525*4882a593Smuzhiyun (4 << CURSOR_FIFO_SR_WM1_SHIFT);
526*4882a593Smuzhiyun REG_WRITE(DSPFW5, fw);
527*4882a593Smuzhiyun }
528*4882a593Smuzhiyun
529*4882a593Smuzhiyun REG_WRITE(DSPFW6, 0x10);
530*4882a593Smuzhiyun
531*4882a593Smuzhiyun gma_wait_for_vblank(dev);
532*4882a593Smuzhiyun
533*4882a593Smuzhiyun /* enable self-refresh for single pipe active */
534*4882a593Smuzhiyun REG_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN);
535*4882a593Smuzhiyun REG_READ(FW_BLC_SELF);
536*4882a593Smuzhiyun gma_wait_for_vblank(dev);
537*4882a593Smuzhiyun
538*4882a593Smuzhiyun } else {
539*4882a593Smuzhiyun
540*4882a593Smuzhiyun /* HW team suggested values... */
541*4882a593Smuzhiyun REG_WRITE(DSPFW1, 0x3f880808);
542*4882a593Smuzhiyun REG_WRITE(DSPFW2, 0x0b020202);
543*4882a593Smuzhiyun REG_WRITE(DSPFW3, 0x24000000);
544*4882a593Smuzhiyun REG_WRITE(DSPFW4, 0x08030202);
545*4882a593Smuzhiyun REG_WRITE(DSPFW5, 0x01010101);
546*4882a593Smuzhiyun REG_WRITE(DSPFW6, 0x1d0);
547*4882a593Smuzhiyun
548*4882a593Smuzhiyun gma_wait_for_vblank(dev);
549*4882a593Smuzhiyun
550*4882a593Smuzhiyun dev_priv->ops->disable_sr(dev);
551*4882a593Smuzhiyun }
552*4882a593Smuzhiyun }
553*4882a593Smuzhiyun
554*4882a593Smuzhiyun /**
555*4882a593Smuzhiyun * Return the pipe currently connected to the panel fitter,
556*4882a593Smuzhiyun * or -1 if the panel fitter is not present or not in use
557*4882a593Smuzhiyun */
cdv_intel_panel_fitter_pipe(struct drm_device * dev)558*4882a593Smuzhiyun static int cdv_intel_panel_fitter_pipe(struct drm_device *dev)
559*4882a593Smuzhiyun {
560*4882a593Smuzhiyun u32 pfit_control;
561*4882a593Smuzhiyun
562*4882a593Smuzhiyun pfit_control = REG_READ(PFIT_CONTROL);
563*4882a593Smuzhiyun
564*4882a593Smuzhiyun /* See if the panel fitter is in use */
565*4882a593Smuzhiyun if ((pfit_control & PFIT_ENABLE) == 0)
566*4882a593Smuzhiyun return -1;
567*4882a593Smuzhiyun return (pfit_control >> 29) & 0x3;
568*4882a593Smuzhiyun }
569*4882a593Smuzhiyun
cdv_intel_crtc_mode_set(struct drm_crtc * crtc,struct drm_display_mode * mode,struct drm_display_mode * adjusted_mode,int x,int y,struct drm_framebuffer * old_fb)570*4882a593Smuzhiyun static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc,
571*4882a593Smuzhiyun struct drm_display_mode *mode,
572*4882a593Smuzhiyun struct drm_display_mode *adjusted_mode,
573*4882a593Smuzhiyun int x, int y,
574*4882a593Smuzhiyun struct drm_framebuffer *old_fb)
575*4882a593Smuzhiyun {
576*4882a593Smuzhiyun struct drm_device *dev = crtc->dev;
577*4882a593Smuzhiyun struct drm_psb_private *dev_priv = dev->dev_private;
578*4882a593Smuzhiyun struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
579*4882a593Smuzhiyun int pipe = gma_crtc->pipe;
580*4882a593Smuzhiyun const struct psb_offset *map = &dev_priv->regmap[pipe];
581*4882a593Smuzhiyun int refclk;
582*4882a593Smuzhiyun struct gma_clock_t clock;
583*4882a593Smuzhiyun u32 dpll = 0, dspcntr, pipeconf;
584*4882a593Smuzhiyun bool ok;
585*4882a593Smuzhiyun bool is_lvds = false, is_tv = false;
586*4882a593Smuzhiyun bool is_dp = false;
587*4882a593Smuzhiyun struct drm_mode_config *mode_config = &dev->mode_config;
588*4882a593Smuzhiyun struct drm_connector *connector;
589*4882a593Smuzhiyun const struct gma_limit_t *limit;
590*4882a593Smuzhiyun u32 ddi_select = 0;
591*4882a593Smuzhiyun bool is_edp = false;
592*4882a593Smuzhiyun
593*4882a593Smuzhiyun list_for_each_entry(connector, &mode_config->connector_list, head) {
594*4882a593Smuzhiyun struct gma_encoder *gma_encoder =
595*4882a593Smuzhiyun gma_attached_encoder(connector);
596*4882a593Smuzhiyun
597*4882a593Smuzhiyun if (!connector->encoder
598*4882a593Smuzhiyun || connector->encoder->crtc != crtc)
599*4882a593Smuzhiyun continue;
600*4882a593Smuzhiyun
601*4882a593Smuzhiyun ddi_select = gma_encoder->ddi_select;
602*4882a593Smuzhiyun switch (gma_encoder->type) {
603*4882a593Smuzhiyun case INTEL_OUTPUT_LVDS:
604*4882a593Smuzhiyun is_lvds = true;
605*4882a593Smuzhiyun break;
606*4882a593Smuzhiyun case INTEL_OUTPUT_TVOUT:
607*4882a593Smuzhiyun is_tv = true;
608*4882a593Smuzhiyun break;
609*4882a593Smuzhiyun case INTEL_OUTPUT_ANALOG:
610*4882a593Smuzhiyun case INTEL_OUTPUT_HDMI:
611*4882a593Smuzhiyun break;
612*4882a593Smuzhiyun case INTEL_OUTPUT_DISPLAYPORT:
613*4882a593Smuzhiyun is_dp = true;
614*4882a593Smuzhiyun break;
615*4882a593Smuzhiyun case INTEL_OUTPUT_EDP:
616*4882a593Smuzhiyun is_edp = true;
617*4882a593Smuzhiyun break;
618*4882a593Smuzhiyun default:
619*4882a593Smuzhiyun DRM_ERROR("invalid output type.\n");
620*4882a593Smuzhiyun return 0;
621*4882a593Smuzhiyun }
622*4882a593Smuzhiyun }
623*4882a593Smuzhiyun
624*4882a593Smuzhiyun if (dev_priv->dplla_96mhz)
625*4882a593Smuzhiyun /* low-end sku, 96/100 mhz */
626*4882a593Smuzhiyun refclk = 96000;
627*4882a593Smuzhiyun else
628*4882a593Smuzhiyun /* high-end sku, 27/100 mhz */
629*4882a593Smuzhiyun refclk = 27000;
630*4882a593Smuzhiyun if (is_dp || is_edp) {
631*4882a593Smuzhiyun /*
632*4882a593Smuzhiyun * Based on the spec the low-end SKU has only CRT/LVDS. So it is
633*4882a593Smuzhiyun * unnecessary to consider it for DP/eDP.
634*4882a593Smuzhiyun * On the high-end SKU, it will use the 27/100M reference clk
635*4882a593Smuzhiyun * for DP/eDP. When using SSC clock, the ref clk is 100MHz.Otherwise
636*4882a593Smuzhiyun * it will be 27MHz. From the VBIOS code it seems that the pipe A choose
637*4882a593Smuzhiyun * 27MHz for DP/eDP while the Pipe B chooses the 100MHz.
638*4882a593Smuzhiyun */
639*4882a593Smuzhiyun if (pipe == 0)
640*4882a593Smuzhiyun refclk = 27000;
641*4882a593Smuzhiyun else
642*4882a593Smuzhiyun refclk = 100000;
643*4882a593Smuzhiyun }
644*4882a593Smuzhiyun
645*4882a593Smuzhiyun if (is_lvds && dev_priv->lvds_use_ssc) {
646*4882a593Smuzhiyun refclk = dev_priv->lvds_ssc_freq * 1000;
647*4882a593Smuzhiyun DRM_DEBUG_KMS("Use SSC reference clock %d Mhz\n", dev_priv->lvds_ssc_freq);
648*4882a593Smuzhiyun }
649*4882a593Smuzhiyun
650*4882a593Smuzhiyun drm_mode_debug_printmodeline(adjusted_mode);
651*4882a593Smuzhiyun
652*4882a593Smuzhiyun limit = gma_crtc->clock_funcs->limit(crtc, refclk);
653*4882a593Smuzhiyun
654*4882a593Smuzhiyun ok = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk,
655*4882a593Smuzhiyun &clock);
656*4882a593Smuzhiyun if (!ok) {
657*4882a593Smuzhiyun DRM_ERROR("Couldn't find PLL settings for mode! target: %d, actual: %d",
658*4882a593Smuzhiyun adjusted_mode->clock, clock.dot);
659*4882a593Smuzhiyun return 0;
660*4882a593Smuzhiyun }
661*4882a593Smuzhiyun
662*4882a593Smuzhiyun dpll = DPLL_VGA_MODE_DIS;
663*4882a593Smuzhiyun if (is_tv) {
664*4882a593Smuzhiyun /* XXX: just matching BIOS for now */
665*4882a593Smuzhiyun /* dpll |= PLL_REF_INPUT_TVCLKINBC; */
666*4882a593Smuzhiyun dpll |= 3;
667*4882a593Smuzhiyun }
668*4882a593Smuzhiyun /* dpll |= PLL_REF_INPUT_DREFCLK; */
669*4882a593Smuzhiyun
670*4882a593Smuzhiyun if (is_dp || is_edp) {
671*4882a593Smuzhiyun cdv_intel_dp_set_m_n(crtc, mode, adjusted_mode);
672*4882a593Smuzhiyun } else {
673*4882a593Smuzhiyun REG_WRITE(PIPE_GMCH_DATA_M(pipe), 0);
674*4882a593Smuzhiyun REG_WRITE(PIPE_GMCH_DATA_N(pipe), 0);
675*4882a593Smuzhiyun REG_WRITE(PIPE_DP_LINK_M(pipe), 0);
676*4882a593Smuzhiyun REG_WRITE(PIPE_DP_LINK_N(pipe), 0);
677*4882a593Smuzhiyun }
678*4882a593Smuzhiyun
679*4882a593Smuzhiyun dpll |= DPLL_SYNCLOCK_ENABLE;
680*4882a593Smuzhiyun /* if (is_lvds)
681*4882a593Smuzhiyun dpll |= DPLLB_MODE_LVDS;
682*4882a593Smuzhiyun else
683*4882a593Smuzhiyun dpll |= DPLLB_MODE_DAC_SERIAL; */
684*4882a593Smuzhiyun /* dpll |= (2 << 11); */
685*4882a593Smuzhiyun
686*4882a593Smuzhiyun /* setup pipeconf */
687*4882a593Smuzhiyun pipeconf = REG_READ(map->conf);
688*4882a593Smuzhiyun
689*4882a593Smuzhiyun pipeconf &= ~(PIPE_BPC_MASK);
690*4882a593Smuzhiyun if (is_edp) {
691*4882a593Smuzhiyun switch (dev_priv->edp.bpp) {
692*4882a593Smuzhiyun case 24:
693*4882a593Smuzhiyun pipeconf |= PIPE_8BPC;
694*4882a593Smuzhiyun break;
695*4882a593Smuzhiyun case 18:
696*4882a593Smuzhiyun pipeconf |= PIPE_6BPC;
697*4882a593Smuzhiyun break;
698*4882a593Smuzhiyun case 30:
699*4882a593Smuzhiyun pipeconf |= PIPE_10BPC;
700*4882a593Smuzhiyun break;
701*4882a593Smuzhiyun default:
702*4882a593Smuzhiyun pipeconf |= PIPE_8BPC;
703*4882a593Smuzhiyun break;
704*4882a593Smuzhiyun }
705*4882a593Smuzhiyun } else if (is_lvds) {
706*4882a593Smuzhiyun /* the BPC will be 6 if it is 18-bit LVDS panel */
707*4882a593Smuzhiyun if ((REG_READ(LVDS) & LVDS_A3_POWER_MASK) == LVDS_A3_POWER_UP)
708*4882a593Smuzhiyun pipeconf |= PIPE_8BPC;
709*4882a593Smuzhiyun else
710*4882a593Smuzhiyun pipeconf |= PIPE_6BPC;
711*4882a593Smuzhiyun } else
712*4882a593Smuzhiyun pipeconf |= PIPE_8BPC;
713*4882a593Smuzhiyun
714*4882a593Smuzhiyun /* Set up the display plane register */
715*4882a593Smuzhiyun dspcntr = DISPPLANE_GAMMA_ENABLE;
716*4882a593Smuzhiyun
717*4882a593Smuzhiyun if (pipe == 0)
718*4882a593Smuzhiyun dspcntr |= DISPPLANE_SEL_PIPE_A;
719*4882a593Smuzhiyun else
720*4882a593Smuzhiyun dspcntr |= DISPPLANE_SEL_PIPE_B;
721*4882a593Smuzhiyun
722*4882a593Smuzhiyun dspcntr |= DISPLAY_PLANE_ENABLE;
723*4882a593Smuzhiyun pipeconf |= PIPEACONF_ENABLE;
724*4882a593Smuzhiyun
725*4882a593Smuzhiyun REG_WRITE(map->dpll, dpll | DPLL_VGA_MODE_DIS | DPLL_SYNCLOCK_ENABLE);
726*4882a593Smuzhiyun REG_READ(map->dpll);
727*4882a593Smuzhiyun
728*4882a593Smuzhiyun cdv_dpll_set_clock_cdv(dev, crtc, &clock, is_lvds, ddi_select);
729*4882a593Smuzhiyun
730*4882a593Smuzhiyun udelay(150);
731*4882a593Smuzhiyun
732*4882a593Smuzhiyun
733*4882a593Smuzhiyun /* The LVDS pin pair needs to be on before the DPLLs are enabled.
734*4882a593Smuzhiyun * This is an exception to the general rule that mode_set doesn't turn
735*4882a593Smuzhiyun * things on.
736*4882a593Smuzhiyun */
737*4882a593Smuzhiyun if (is_lvds) {
738*4882a593Smuzhiyun u32 lvds = REG_READ(LVDS);
739*4882a593Smuzhiyun
740*4882a593Smuzhiyun lvds |=
741*4882a593Smuzhiyun LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP |
742*4882a593Smuzhiyun LVDS_PIPEB_SELECT;
743*4882a593Smuzhiyun /* Set the B0-B3 data pairs corresponding to
744*4882a593Smuzhiyun * whether we're going to
745*4882a593Smuzhiyun * set the DPLLs for dual-channel mode or not.
746*4882a593Smuzhiyun */
747*4882a593Smuzhiyun if (clock.p2 == 7)
748*4882a593Smuzhiyun lvds |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP;
749*4882a593Smuzhiyun else
750*4882a593Smuzhiyun lvds &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP);
751*4882a593Smuzhiyun
752*4882a593Smuzhiyun /* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP)
753*4882a593Smuzhiyun * appropriately here, but we need to look more
754*4882a593Smuzhiyun * thoroughly into how panels behave in the two modes.
755*4882a593Smuzhiyun */
756*4882a593Smuzhiyun
757*4882a593Smuzhiyun REG_WRITE(LVDS, lvds);
758*4882a593Smuzhiyun REG_READ(LVDS);
759*4882a593Smuzhiyun }
760*4882a593Smuzhiyun
761*4882a593Smuzhiyun dpll |= DPLL_VCO_ENABLE;
762*4882a593Smuzhiyun
763*4882a593Smuzhiyun /* Disable the panel fitter if it was on our pipe */
764*4882a593Smuzhiyun if (cdv_intel_panel_fitter_pipe(dev) == pipe)
765*4882a593Smuzhiyun REG_WRITE(PFIT_CONTROL, 0);
766*4882a593Smuzhiyun
767*4882a593Smuzhiyun DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
768*4882a593Smuzhiyun drm_mode_debug_printmodeline(mode);
769*4882a593Smuzhiyun
770*4882a593Smuzhiyun REG_WRITE(map->dpll,
771*4882a593Smuzhiyun (REG_READ(map->dpll) & ~DPLL_LOCK) | DPLL_VCO_ENABLE);
772*4882a593Smuzhiyun REG_READ(map->dpll);
773*4882a593Smuzhiyun /* Wait for the clocks to stabilize. */
774*4882a593Smuzhiyun udelay(150); /* 42 usec w/o calibration, 110 with. rounded up. */
775*4882a593Smuzhiyun
776*4882a593Smuzhiyun if (!(REG_READ(map->dpll) & DPLL_LOCK)) {
777*4882a593Smuzhiyun dev_err(dev->dev, "Failed to get DPLL lock\n");
778*4882a593Smuzhiyun return -EBUSY;
779*4882a593Smuzhiyun }
780*4882a593Smuzhiyun
781*4882a593Smuzhiyun {
782*4882a593Smuzhiyun int sdvo_pixel_multiply = adjusted_mode->clock / mode->clock;
783*4882a593Smuzhiyun REG_WRITE(map->dpll_md, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) | ((sdvo_pixel_multiply - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT));
784*4882a593Smuzhiyun }
785*4882a593Smuzhiyun
786*4882a593Smuzhiyun REG_WRITE(map->htotal, (adjusted_mode->crtc_hdisplay - 1) |
787*4882a593Smuzhiyun ((adjusted_mode->crtc_htotal - 1) << 16));
788*4882a593Smuzhiyun REG_WRITE(map->hblank, (adjusted_mode->crtc_hblank_start - 1) |
789*4882a593Smuzhiyun ((adjusted_mode->crtc_hblank_end - 1) << 16));
790*4882a593Smuzhiyun REG_WRITE(map->hsync, (adjusted_mode->crtc_hsync_start - 1) |
791*4882a593Smuzhiyun ((adjusted_mode->crtc_hsync_end - 1) << 16));
792*4882a593Smuzhiyun REG_WRITE(map->vtotal, (adjusted_mode->crtc_vdisplay - 1) |
793*4882a593Smuzhiyun ((adjusted_mode->crtc_vtotal - 1) << 16));
794*4882a593Smuzhiyun REG_WRITE(map->vblank, (adjusted_mode->crtc_vblank_start - 1) |
795*4882a593Smuzhiyun ((adjusted_mode->crtc_vblank_end - 1) << 16));
796*4882a593Smuzhiyun REG_WRITE(map->vsync, (adjusted_mode->crtc_vsync_start - 1) |
797*4882a593Smuzhiyun ((adjusted_mode->crtc_vsync_end - 1) << 16));
798*4882a593Smuzhiyun /* pipesrc and dspsize control the size that is scaled from,
799*4882a593Smuzhiyun * which should always be the user's requested size.
800*4882a593Smuzhiyun */
801*4882a593Smuzhiyun REG_WRITE(map->size,
802*4882a593Smuzhiyun ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1));
803*4882a593Smuzhiyun REG_WRITE(map->pos, 0);
804*4882a593Smuzhiyun REG_WRITE(map->src,
805*4882a593Smuzhiyun ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1));
806*4882a593Smuzhiyun REG_WRITE(map->conf, pipeconf);
807*4882a593Smuzhiyun REG_READ(map->conf);
808*4882a593Smuzhiyun
809*4882a593Smuzhiyun gma_wait_for_vblank(dev);
810*4882a593Smuzhiyun
811*4882a593Smuzhiyun REG_WRITE(map->cntr, dspcntr);
812*4882a593Smuzhiyun
813*4882a593Smuzhiyun /* Flush the plane changes */
814*4882a593Smuzhiyun {
815*4882a593Smuzhiyun const struct drm_crtc_helper_funcs *crtc_funcs =
816*4882a593Smuzhiyun crtc->helper_private;
817*4882a593Smuzhiyun crtc_funcs->mode_set_base(crtc, x, y, old_fb);
818*4882a593Smuzhiyun }
819*4882a593Smuzhiyun
820*4882a593Smuzhiyun gma_wait_for_vblank(dev);
821*4882a593Smuzhiyun
822*4882a593Smuzhiyun return 0;
823*4882a593Smuzhiyun }
824*4882a593Smuzhiyun
825*4882a593Smuzhiyun /** Derive the pixel clock for the given refclk and divisors for 8xx chips. */
826*4882a593Smuzhiyun
827*4882a593Smuzhiyun /* FIXME: why are we using this, should it be cdv_ in this tree ? */
828*4882a593Smuzhiyun
i8xx_clock(int refclk,struct gma_clock_t * clock)829*4882a593Smuzhiyun static void i8xx_clock(int refclk, struct gma_clock_t *clock)
830*4882a593Smuzhiyun {
831*4882a593Smuzhiyun clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2);
832*4882a593Smuzhiyun clock->p = clock->p1 * clock->p2;
833*4882a593Smuzhiyun clock->vco = refclk * clock->m / (clock->n + 2);
834*4882a593Smuzhiyun clock->dot = clock->vco / clock->p;
835*4882a593Smuzhiyun }
836*4882a593Smuzhiyun
837*4882a593Smuzhiyun /* Returns the clock of the currently programmed mode of the given pipe. */
cdv_intel_crtc_clock_get(struct drm_device * dev,struct drm_crtc * crtc)838*4882a593Smuzhiyun static int cdv_intel_crtc_clock_get(struct drm_device *dev,
839*4882a593Smuzhiyun struct drm_crtc *crtc)
840*4882a593Smuzhiyun {
841*4882a593Smuzhiyun struct drm_psb_private *dev_priv = dev->dev_private;
842*4882a593Smuzhiyun struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
843*4882a593Smuzhiyun int pipe = gma_crtc->pipe;
844*4882a593Smuzhiyun const struct psb_offset *map = &dev_priv->regmap[pipe];
845*4882a593Smuzhiyun u32 dpll;
846*4882a593Smuzhiyun u32 fp;
847*4882a593Smuzhiyun struct gma_clock_t clock;
848*4882a593Smuzhiyun bool is_lvds;
849*4882a593Smuzhiyun struct psb_pipe *p = &dev_priv->regs.pipe[pipe];
850*4882a593Smuzhiyun
851*4882a593Smuzhiyun if (gma_power_begin(dev, false)) {
852*4882a593Smuzhiyun dpll = REG_READ(map->dpll);
853*4882a593Smuzhiyun if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0)
854*4882a593Smuzhiyun fp = REG_READ(map->fp0);
855*4882a593Smuzhiyun else
856*4882a593Smuzhiyun fp = REG_READ(map->fp1);
857*4882a593Smuzhiyun is_lvds = (pipe == 1) && (REG_READ(LVDS) & LVDS_PORT_EN);
858*4882a593Smuzhiyun gma_power_end(dev);
859*4882a593Smuzhiyun } else {
860*4882a593Smuzhiyun dpll = p->dpll;
861*4882a593Smuzhiyun if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0)
862*4882a593Smuzhiyun fp = p->fp0;
863*4882a593Smuzhiyun else
864*4882a593Smuzhiyun fp = p->fp1;
865*4882a593Smuzhiyun
866*4882a593Smuzhiyun is_lvds = (pipe == 1) &&
867*4882a593Smuzhiyun (dev_priv->regs.psb.saveLVDS & LVDS_PORT_EN);
868*4882a593Smuzhiyun }
869*4882a593Smuzhiyun
870*4882a593Smuzhiyun clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT;
871*4882a593Smuzhiyun clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT;
872*4882a593Smuzhiyun clock.n = (fp & FP_N_DIV_MASK) >> FP_N_DIV_SHIFT;
873*4882a593Smuzhiyun
874*4882a593Smuzhiyun if (is_lvds) {
875*4882a593Smuzhiyun clock.p1 =
876*4882a593Smuzhiyun ffs((dpll &
877*4882a593Smuzhiyun DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS) >>
878*4882a593Smuzhiyun DPLL_FPA01_P1_POST_DIV_SHIFT);
879*4882a593Smuzhiyun if (clock.p1 == 0) {
880*4882a593Smuzhiyun clock.p1 = 4;
881*4882a593Smuzhiyun dev_err(dev->dev, "PLL %d\n", dpll);
882*4882a593Smuzhiyun }
883*4882a593Smuzhiyun clock.p2 = 14;
884*4882a593Smuzhiyun
885*4882a593Smuzhiyun if ((dpll & PLL_REF_INPUT_MASK) ==
886*4882a593Smuzhiyun PLLB_REF_INPUT_SPREADSPECTRUMIN) {
887*4882a593Smuzhiyun /* XXX: might not be 66MHz */
888*4882a593Smuzhiyun i8xx_clock(66000, &clock);
889*4882a593Smuzhiyun } else
890*4882a593Smuzhiyun i8xx_clock(48000, &clock);
891*4882a593Smuzhiyun } else {
892*4882a593Smuzhiyun if (dpll & PLL_P1_DIVIDE_BY_TWO)
893*4882a593Smuzhiyun clock.p1 = 2;
894*4882a593Smuzhiyun else {
895*4882a593Smuzhiyun clock.p1 =
896*4882a593Smuzhiyun ((dpll &
897*4882a593Smuzhiyun DPLL_FPA01_P1_POST_DIV_MASK_I830) >>
898*4882a593Smuzhiyun DPLL_FPA01_P1_POST_DIV_SHIFT) + 2;
899*4882a593Smuzhiyun }
900*4882a593Smuzhiyun if (dpll & PLL_P2_DIVIDE_BY_4)
901*4882a593Smuzhiyun clock.p2 = 4;
902*4882a593Smuzhiyun else
903*4882a593Smuzhiyun clock.p2 = 2;
904*4882a593Smuzhiyun
905*4882a593Smuzhiyun i8xx_clock(48000, &clock);
906*4882a593Smuzhiyun }
907*4882a593Smuzhiyun
908*4882a593Smuzhiyun /* XXX: It would be nice to validate the clocks, but we can't reuse
909*4882a593Smuzhiyun * i830PllIsValid() because it relies on the xf86_config connector
910*4882a593Smuzhiyun * configuration being accurate, which it isn't necessarily.
911*4882a593Smuzhiyun */
912*4882a593Smuzhiyun
913*4882a593Smuzhiyun return clock.dot;
914*4882a593Smuzhiyun }
915*4882a593Smuzhiyun
916*4882a593Smuzhiyun /** Returns the currently programmed mode of the given pipe. */
cdv_intel_crtc_mode_get(struct drm_device * dev,struct drm_crtc * crtc)917*4882a593Smuzhiyun struct drm_display_mode *cdv_intel_crtc_mode_get(struct drm_device *dev,
918*4882a593Smuzhiyun struct drm_crtc *crtc)
919*4882a593Smuzhiyun {
920*4882a593Smuzhiyun struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
921*4882a593Smuzhiyun int pipe = gma_crtc->pipe;
922*4882a593Smuzhiyun struct drm_psb_private *dev_priv = dev->dev_private;
923*4882a593Smuzhiyun struct psb_pipe *p = &dev_priv->regs.pipe[pipe];
924*4882a593Smuzhiyun const struct psb_offset *map = &dev_priv->regmap[pipe];
925*4882a593Smuzhiyun struct drm_display_mode *mode;
926*4882a593Smuzhiyun int htot;
927*4882a593Smuzhiyun int hsync;
928*4882a593Smuzhiyun int vtot;
929*4882a593Smuzhiyun int vsync;
930*4882a593Smuzhiyun
931*4882a593Smuzhiyun if (gma_power_begin(dev, false)) {
932*4882a593Smuzhiyun htot = REG_READ(map->htotal);
933*4882a593Smuzhiyun hsync = REG_READ(map->hsync);
934*4882a593Smuzhiyun vtot = REG_READ(map->vtotal);
935*4882a593Smuzhiyun vsync = REG_READ(map->vsync);
936*4882a593Smuzhiyun gma_power_end(dev);
937*4882a593Smuzhiyun } else {
938*4882a593Smuzhiyun htot = p->htotal;
939*4882a593Smuzhiyun hsync = p->hsync;
940*4882a593Smuzhiyun vtot = p->vtotal;
941*4882a593Smuzhiyun vsync = p->vsync;
942*4882a593Smuzhiyun }
943*4882a593Smuzhiyun
944*4882a593Smuzhiyun mode = kzalloc(sizeof(*mode), GFP_KERNEL);
945*4882a593Smuzhiyun if (!mode)
946*4882a593Smuzhiyun return NULL;
947*4882a593Smuzhiyun
948*4882a593Smuzhiyun mode->clock = cdv_intel_crtc_clock_get(dev, crtc);
949*4882a593Smuzhiyun mode->hdisplay = (htot & 0xffff) + 1;
950*4882a593Smuzhiyun mode->htotal = ((htot & 0xffff0000) >> 16) + 1;
951*4882a593Smuzhiyun mode->hsync_start = (hsync & 0xffff) + 1;
952*4882a593Smuzhiyun mode->hsync_end = ((hsync & 0xffff0000) >> 16) + 1;
953*4882a593Smuzhiyun mode->vdisplay = (vtot & 0xffff) + 1;
954*4882a593Smuzhiyun mode->vtotal = ((vtot & 0xffff0000) >> 16) + 1;
955*4882a593Smuzhiyun mode->vsync_start = (vsync & 0xffff) + 1;
956*4882a593Smuzhiyun mode->vsync_end = ((vsync & 0xffff0000) >> 16) + 1;
957*4882a593Smuzhiyun
958*4882a593Smuzhiyun drm_mode_set_name(mode);
959*4882a593Smuzhiyun drm_mode_set_crtcinfo(mode, 0);
960*4882a593Smuzhiyun
961*4882a593Smuzhiyun return mode;
962*4882a593Smuzhiyun }
963*4882a593Smuzhiyun
964*4882a593Smuzhiyun const struct drm_crtc_helper_funcs cdv_intel_helper_funcs = {
965*4882a593Smuzhiyun .dpms = gma_crtc_dpms,
966*4882a593Smuzhiyun .mode_set = cdv_intel_crtc_mode_set,
967*4882a593Smuzhiyun .mode_set_base = gma_pipe_set_base,
968*4882a593Smuzhiyun .prepare = gma_crtc_prepare,
969*4882a593Smuzhiyun .commit = gma_crtc_commit,
970*4882a593Smuzhiyun .disable = gma_crtc_disable,
971*4882a593Smuzhiyun };
972*4882a593Smuzhiyun
973*4882a593Smuzhiyun const struct drm_crtc_funcs cdv_intel_crtc_funcs = {
974*4882a593Smuzhiyun .cursor_set = gma_crtc_cursor_set,
975*4882a593Smuzhiyun .cursor_move = gma_crtc_cursor_move,
976*4882a593Smuzhiyun .gamma_set = gma_crtc_gamma_set,
977*4882a593Smuzhiyun .set_config = gma_crtc_set_config,
978*4882a593Smuzhiyun .destroy = gma_crtc_destroy,
979*4882a593Smuzhiyun .page_flip = gma_crtc_page_flip,
980*4882a593Smuzhiyun .enable_vblank = psb_enable_vblank,
981*4882a593Smuzhiyun .disable_vblank = psb_disable_vblank,
982*4882a593Smuzhiyun .get_vblank_counter = psb_get_vblank_counter,
983*4882a593Smuzhiyun };
984*4882a593Smuzhiyun
985*4882a593Smuzhiyun const struct gma_clock_funcs cdv_clock_funcs = {
986*4882a593Smuzhiyun .clock = cdv_intel_clock,
987*4882a593Smuzhiyun .limit = cdv_intel_limit,
988*4882a593Smuzhiyun .pll_is_valid = gma_pll_is_valid,
989*4882a593Smuzhiyun };
990