aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Cox <alan@linux.intel.com>2011-11-03 14:22:37 -0400
committerDave Airlie <airlied@redhat.com>2011-11-16 06:27:35 -0500
commit6a227d5fd6c4abe6a9226a40f6981825e9da5fbe (patch)
treec9bf4f59f45c84f668d15de32ac7d6420e700578
parent1b082ccf5901108d3acd860a73d8c0442556c0bb (diff)
gma500: Add support for Cedarview
Again this is similar but has some differences so we have a set of plug in support. This does make the driver bigger than is needed in some respects but the tradeoff for maintainability is huge. Signed-off-by: Alan Cox <alan@linux.intel.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r--drivers/gpu/drm/gma500/cdv_device.c351
-rw-r--r--drivers/gpu/drm/gma500/cdv_device.h36
-rw-r--r--drivers/gpu/drm/gma500/cdv_intel_crt.c326
-rw-r--r--drivers/gpu/drm/gma500/cdv_intel_display.c1508
-rw-r--r--drivers/gpu/drm/gma500/cdv_intel_hdmi.c376
-rw-r--r--drivers/gpu/drm/gma500/cdv_intel_lvds.c721
6 files changed, 3318 insertions, 0 deletions
diff --git a/drivers/gpu/drm/gma500/cdv_device.c b/drivers/gpu/drm/gma500/cdv_device.c
new file mode 100644
index 000000000000..87614e0d396a
--- /dev/null
+++ b/drivers/gpu/drm/gma500/cdv_device.c
@@ -0,0 +1,351 @@
1/**************************************************************************
2 * Copyright (c) 2011, Intel Corporation.
3 * All Rights Reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 **************************************************************************/
19
20#include <linux/backlight.h>
21#include <drm/drmP.h>
22#include <drm/drm.h>
23#include "psb_drm.h"
24#include "psb_drv.h"
25#include "psb_reg.h"
26#include "psb_intel_reg.h"
27#include "intel_bios.h"
28#include "cdv_device.h"
29
30#define VGA_SR_INDEX 0x3c4
31#define VGA_SR_DATA 0x3c5
32
33/* FIXME: should check if we are the active VGA device ?? */
34static void cdv_disable_vga(struct drm_device *dev)
35{
36 u8 sr1;
37 u32 vga_reg;
38
39 vga_reg = VGACNTRL;
40
41 outb(1, VGA_SR_INDEX);
42 sr1 = inb(VGA_SR_DATA);
43 outb(sr1 | 1<<5, VGA_SR_DATA);
44 udelay(300);
45
46 REG_WRITE(vga_reg, VGA_DISP_DISABLE);
47 REG_READ(vga_reg);
48}
49
50static int cdv_output_init(struct drm_device *dev)
51{
52 struct drm_psb_private *dev_priv = dev->dev_private;
53 cdv_disable_vga(dev);
54
55 cdv_intel_crt_init(dev, &dev_priv->mode_dev);
56 cdv_intel_lvds_init(dev, &dev_priv->mode_dev);
57
58 /* These bits indicate HDMI not SDVO on CDV, but we don't yet support
59 the HDMI interface */
60 if (REG_READ(SDVOB) & SDVO_DETECTED)
61 cdv_hdmi_init(dev, &dev_priv->mode_dev, SDVOB);
62 if (REG_READ(SDVOC) & SDVO_DETECTED)
63 cdv_hdmi_init(dev, &dev_priv->mode_dev, SDVOC);
64 return 0;
65}
66
67#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
68
69/*
70 * Poulsbo Backlight Interfaces
71 */
72
73#define BLC_PWM_PRECISION_FACTOR 100 /* 10000000 */
74#define BLC_PWM_FREQ_CALC_CONSTANT 32
75#define MHz 1000000
76
77#define PSB_BLC_PWM_PRECISION_FACTOR 10
78#define PSB_BLC_MAX_PWM_REG_FREQ 0xFFFE
79#define PSB_BLC_MIN_PWM_REG_FREQ 0x2
80
81#define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE)
82#define PSB_BACKLIGHT_PWM_CTL_SHIFT (16)
83
84static int cdv_brightness;
85static struct backlight_device *cdv_backlight_device;
86
87static int cdv_get_brightness(struct backlight_device *bd)
88{
89 /* return locally cached var instead of HW read (due to DPST etc.) */
90 /* FIXME: ideally return actual value in case firmware fiddled with
91 it */
92 return cdv_brightness;
93}
94
95
96static int cdv_backlight_setup(struct drm_device *dev)
97{
98 struct drm_psb_private *dev_priv = dev->dev_private;
99 unsigned long core_clock;
100 /* u32 bl_max_freq; */
101 /* unsigned long value; */
102 u16 bl_max_freq;
103 uint32_t value;
104 uint32_t blc_pwm_precision_factor;
105
106 /* get bl_max_freq and pol from dev_priv*/
107 if (!dev_priv->lvds_bl) {
108 dev_err(dev->dev, "Has no valid LVDS backlight info\n");
109 return -ENOENT;
110 }
111 bl_max_freq = dev_priv->lvds_bl->freq;
112 blc_pwm_precision_factor = PSB_BLC_PWM_PRECISION_FACTOR;
113
114 core_clock = dev_priv->core_freq;
115
116 value = (core_clock * MHz) / BLC_PWM_FREQ_CALC_CONSTANT;
117 value *= blc_pwm_precision_factor;
118 value /= bl_max_freq;
119 value /= blc_pwm_precision_factor;
120
121 if (value > (unsigned long long)PSB_BLC_MAX_PWM_REG_FREQ ||
122 value < (unsigned long long)PSB_BLC_MIN_PWM_REG_FREQ)
123 return -ERANGE;
124 else {
125 /* FIXME */
126 }
127 return 0;
128}
129
130static int cdv_set_brightness(struct backlight_device *bd)
131{
132 int level = bd->props.brightness;
133
134 /* Percentage 1-100% being valid */
135 if (level < 1)
136 level = 1;
137
138 /*cdv_intel_lvds_set_brightness(dev, level); FIXME */
139 cdv_brightness = level;
140 return 0;
141}
142
143static const struct backlight_ops cdv_ops = {
144 .get_brightness = cdv_get_brightness,
145 .update_status = cdv_set_brightness,
146};
147
148static int cdv_backlight_init(struct drm_device *dev)
149{
150 struct drm_psb_private *dev_priv = dev->dev_private;
151 int ret;
152 struct backlight_properties props;
153
154 memset(&props, 0, sizeof(struct backlight_properties));
155 props.max_brightness = 100;
156 props.type = BACKLIGHT_PLATFORM;
157
158 cdv_backlight_device = backlight_device_register("psb-bl",
159 NULL, (void *)dev, &cdv_ops, &props);
160 if (IS_ERR(cdv_backlight_device))
161 return PTR_ERR(cdv_backlight_device);
162
163 ret = cdv_backlight_setup(dev);
164 if (ret < 0) {
165 backlight_device_unregister(cdv_backlight_device);
166 cdv_backlight_device = NULL;
167 return ret;
168 }
169 cdv_backlight_device->props.brightness = 100;
170 cdv_backlight_device->props.max_brightness = 100;
171 backlight_update_status(cdv_backlight_device);
172 dev_priv->backlight_device = cdv_backlight_device;
173 return 0;
174}
175
176#endif
177
178/*
179 * Provide the Cedarview specific chip logic and low level methods
180 * for power management
181 *
182 * FIXME: we need to implement the apm/ospm base management bits
183 * for this and the MID devices.
184 */
185
186static inline u32 CDV_MSG_READ32(uint port, uint offset)
187{
188 int mcr = (0x10<<24) | (port << 16) | (offset << 8);
189 uint32_t ret_val = 0;
190 struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
191 pci_write_config_dword(pci_root, 0xD0, mcr);
192 pci_read_config_dword(pci_root, 0xD4, &ret_val);
193 pci_dev_put(pci_root);
194 return ret_val;
195}
196
197static inline void CDV_MSG_WRITE32(uint port, uint offset, u32 value)
198{
199 int mcr = (0x11<<24) | (port << 16) | (offset << 8) | 0xF0;
200 struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
201 pci_write_config_dword(pci_root, 0xD4, value);
202 pci_write_config_dword(pci_root, 0xD0, mcr);
203 pci_dev_put(pci_root);
204}
205
206#define PSB_APM_CMD 0x0
207#define PSB_APM_STS 0x04
208#define PSB_PM_SSC 0x20
209#define PSB_PM_SSS 0x30
210#define PSB_PWRGT_GFX_MASK 0x3
211#define CDV_PWRGT_DISPLAY_CNTR 0x000fc00c
212#define CDV_PWRGT_DISPLAY_STS 0x000fc00c
213
214static void cdv_init_pm(struct drm_device *dev)
215{
216 struct drm_psb_private *dev_priv = dev->dev_private;
217 u32 pwr_cnt;
218 int i;
219
220 dev_priv->apm_base = CDV_MSG_READ32(PSB_PUNIT_PORT,
221 PSB_APMBA) & 0xFFFF;
222 dev_priv->ospm_base = CDV_MSG_READ32(PSB_PUNIT_PORT,
223 PSB_OSPMBA) & 0xFFFF;
224
225 /* Force power on for now */
226 pwr_cnt = inl(dev_priv->apm_base + PSB_APM_CMD);
227 pwr_cnt &= ~PSB_PWRGT_GFX_MASK;
228
229 outl(pwr_cnt, dev_priv->apm_base + PSB_APM_CMD);
230 for (i = 0; i < 5; i++) {
231 u32 pwr_sts = inl(dev_priv->apm_base + PSB_APM_STS);
232 if ((pwr_sts & PSB_PWRGT_GFX_MASK) == 0)
233 break;
234 udelay(10);
235 }
236 pwr_cnt = inl(dev_priv->ospm_base + PSB_PM_SSC);
237 pwr_cnt &= ~CDV_PWRGT_DISPLAY_CNTR;
238 outl(pwr_cnt, dev_priv->ospm_base + PSB_PM_SSC);
239 for (i = 0; i < 5; i++) {
240 u32 pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS);
241 if ((pwr_sts & CDV_PWRGT_DISPLAY_STS) == 0)
242 break;
243 udelay(10);
244 }
245}
246
247/**
248 * cdv_save_display_registers - save registers lost on suspend
249 * @dev: our DRM device
250 *
251 * Save the state we need in order to be able to restore the interface
252 * upon resume from suspend
253 *
254 * FIXME: review
255 */
256static int cdv_save_display_registers(struct drm_device *dev)
257{
258 return 0;
259}
260
261/**
262 * cdv_restore_display_registers - restore lost register state
263 * @dev: our DRM device
264 *
265 * Restore register state that was lost during suspend and resume.
266 *
267 * FIXME: review
268 */
269static int cdv_restore_display_registers(struct drm_device *dev)
270{
271 return 0;
272}
273
274static int cdv_power_down(struct drm_device *dev)
275{
276 return 0;
277}
278
279static int cdv_power_up(struct drm_device *dev)
280{
281 return 0;
282}
283
284/* FIXME ? - shared with Poulsbo */
285static void cdv_get_core_freq(struct drm_device *dev)
286{
287 uint32_t clock;
288 struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
289 struct drm_psb_private *dev_priv = dev->dev_private;
290
291 pci_write_config_dword(pci_root, 0xD0, 0xD0050300);
292 pci_read_config_dword(pci_root, 0xD4, &clock);
293 pci_dev_put(pci_root);
294
295 switch (clock & 0x07) {
296 case 0:
297 dev_priv->core_freq = 100;
298 break;
299 case 1:
300 dev_priv->core_freq = 133;
301 break;
302 case 2:
303 dev_priv->core_freq = 150;
304 break;
305 case 3:
306 dev_priv->core_freq = 178;
307 break;
308 case 4:
309 dev_priv->core_freq = 200;
310 break;
311 case 5:
312 case 6:
313 case 7:
314 dev_priv->core_freq = 266;
315 default:
316 dev_priv->core_freq = 0;
317 }
318}
319
320static int cdv_chip_setup(struct drm_device *dev)
321{
322 cdv_get_core_freq(dev);
323 gma_intel_opregion_init(dev);
324 psb_intel_init_bios(dev);
325 return 0;
326}
327
328/* CDV is much like Poulsbo but has MID like SGX offsets and PM */
329
330const struct psb_ops cdv_chip_ops = {
331 .name = "Cedartrail",
332 .accel_2d = 0,
333 .pipes = 2,
334 .sgx_offset = MRST_SGX_OFFSET,
335 .chip_setup = cdv_chip_setup,
336
337 .crtc_helper = &cdv_intel_helper_funcs,
338 .crtc_funcs = &cdv_intel_crtc_funcs,
339
340 .output_init = cdv_output_init,
341
342#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
343 .backlight_init = cdv_backlight_init,
344#endif
345
346 .init_pm = cdv_init_pm,
347 .save_regs = cdv_save_display_registers,
348 .restore_regs = cdv_restore_display_registers,
349 .power_down = cdv_power_down,
350 .power_up = cdv_power_up,
351};
diff --git a/drivers/gpu/drm/gma500/cdv_device.h b/drivers/gpu/drm/gma500/cdv_device.h
new file mode 100644
index 000000000000..2a88b7beb551
--- /dev/null
+++ b/drivers/gpu/drm/gma500/cdv_device.h
@@ -0,0 +1,36 @@
1/*
2 * Copyright © 2011 Intel Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
16 */
17
18extern const struct drm_crtc_helper_funcs cdv_intel_helper_funcs;
19extern const struct drm_crtc_funcs cdv_intel_crtc_funcs;
20extern void cdv_intel_crt_init(struct drm_device *dev,
21 struct psb_intel_mode_device *mode_dev);
22extern void cdv_intel_lvds_init(struct drm_device *dev,
23 struct psb_intel_mode_device *mode_dev);
24extern void cdv_hdmi_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev,
25 int reg);
26extern struct drm_display_mode *cdv_intel_crtc_mode_get(struct drm_device *dev,
27 struct drm_crtc *crtc);
28
29extern inline void cdv_intel_wait_for_vblank(struct drm_device *dev)
30{
31 /* Wait for 20ms, i.e. one cycle at 50hz. */
32 /* FIXME: msleep ?? */
33 mdelay(20);
34}
35
36
diff --git a/drivers/gpu/drm/gma500/cdv_intel_crt.c b/drivers/gpu/drm/gma500/cdv_intel_crt.c
new file mode 100644
index 000000000000..efda63b97b45
--- /dev/null
+++ b/drivers/gpu/drm/gma500/cdv_intel_crt.c
@@ -0,0 +1,326 @@
1/*
2 * Copyright © 2006-2007 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 *
23 * Authors:
24 * Eric Anholt <eric@anholt.net>
25 */
26
27#include <linux/i2c.h>
28#include <drm/drmP.h>
29
30#include "intel_bios.h"
31#include "psb_drv.h"
32#include "psb_intel_drv.h"
33#include "psb_intel_reg.h"
34#include "power.h"
35#include <linux/pm_runtime.h>
36
37
38static void cdv_intel_crt_dpms(struct drm_encoder *encoder, int mode)
39{
40 struct drm_device *dev = encoder->dev;
41 u32 temp, reg;
42 reg = ADPA;
43
44 temp = REG_READ(reg);
45 temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE);
46 temp &= ~ADPA_DAC_ENABLE;
47
48 switch (mode) {
49 case DRM_MODE_DPMS_ON:
50 temp |= ADPA_DAC_ENABLE;
51 break;
52 case DRM_MODE_DPMS_STANDBY:
53 temp |= ADPA_DAC_ENABLE | ADPA_HSYNC_CNTL_DISABLE;
54 break;
55 case DRM_MODE_DPMS_SUSPEND:
56 temp |= ADPA_DAC_ENABLE | ADPA_VSYNC_CNTL_DISABLE;
57 break;
58 case DRM_MODE_DPMS_OFF:
59 temp |= ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE;
60 break;
61 }
62
63 REG_WRITE(reg, temp);
64}
65
66static int cdv_intel_crt_mode_valid(struct drm_connector *connector,
67 struct drm_display_mode *mode)
68{
69 int max_clock = 0;
70 if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
71 return MODE_NO_DBLESCAN;
72
73 /* The lowest clock for CDV is 20000KHz */
74 if (mode->clock < 20000)
75 return MODE_CLOCK_LOW;
76
77 /* The max clock for CDV is 355 instead of 400 */
78 max_clock = 355000;
79 if (mode->clock > max_clock)
80 return MODE_CLOCK_HIGH;
81
82 if (mode->hdisplay > 1680 || mode->vdisplay > 1050)
83 return MODE_PANEL;
84
85 return MODE_OK;
86}
87
88static bool cdv_intel_crt_mode_fixup(struct drm_encoder *encoder,
89 struct drm_display_mode *mode,
90 struct drm_display_mode *adjusted_mode)
91{
92 return true;
93}
94
95static void cdv_intel_crt_mode_set(struct drm_encoder *encoder,
96 struct drm_display_mode *mode,
97 struct drm_display_mode *adjusted_mode)
98{
99
100 struct drm_device *dev = encoder->dev;
101 struct drm_crtc *crtc = encoder->crtc;
102 struct psb_intel_crtc *psb_intel_crtc =
103 to_psb_intel_crtc(crtc);
104 int dpll_md_reg;
105 u32 adpa, dpll_md;
106 u32 adpa_reg;
107
108 if (psb_intel_crtc->pipe == 0)
109 dpll_md_reg = DPLL_A_MD;
110 else
111 dpll_md_reg = DPLL_B_MD;
112
113 adpa_reg = ADPA;
114
115 /*
116 * Disable separate mode multiplier used when cloning SDVO to CRT
117 * XXX this needs to be adjusted when we really are cloning
118 */
119 {
120 dpll_md = REG_READ(dpll_md_reg);
121 REG_WRITE(dpll_md_reg,
122 dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK);
123 }
124
125 adpa = 0;
126 if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
127 adpa |= ADPA_HSYNC_ACTIVE_HIGH;
128 if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
129 adpa |= ADPA_VSYNC_ACTIVE_HIGH;
130
131 if (psb_intel_crtc->pipe == 0)
132 adpa |= ADPA_PIPE_A_SELECT;
133 else
134 adpa |= ADPA_PIPE_B_SELECT;
135
136 REG_WRITE(adpa_reg, adpa);
137}
138
139
140/**
141 * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect CRT presence.
142 *
143 * \return true if CRT is connected.
144 * \return false if CRT is disconnected.
145 */
146static bool cdv_intel_crt_detect_hotplug(struct drm_connector *connector,
147 bool force)
148{
149 struct drm_device *dev = connector->dev;
150 u32 hotplug_en;
151 int i, tries = 0, ret = false;
152 u32 adpa_orig;
153
154 /* disable the DAC when doing the hotplug detection */
155
156 adpa_orig = REG_READ(ADPA);
157
158 REG_WRITE(ADPA, adpa_orig & ~(ADPA_DAC_ENABLE));
159
160 /*
161 * On a CDV thep, CRT detect sequence need to be done twice
162 * to get a reliable result.
163 */
164 tries = 2;
165
166 hotplug_en = REG_READ(PORT_HOTPLUG_EN);
167 hotplug_en &= ~(CRT_HOTPLUG_DETECT_MASK);
168 hotplug_en |= CRT_HOTPLUG_FORCE_DETECT;
169
170 hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64;
171 hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50;
172
173 for (i = 0; i < tries ; i++) {
174 unsigned long timeout;
175 /* turn on the FORCE_DETECT */
176 REG_WRITE(PORT_HOTPLUG_EN, hotplug_en);
177 timeout = jiffies + msecs_to_jiffies(1000);
178 /* wait for FORCE_DETECT to go off */
179 do {
180 if (!(REG_READ(PORT_HOTPLUG_EN) &
181 CRT_HOTPLUG_FORCE_DETECT))
182 break;
183 msleep(1);
184 } while (time_after(timeout, jiffies));
185 }
186
187 if ((REG_READ(PORT_HOTPLUG_STAT) & CRT_HOTPLUG_MONITOR_MASK) !=
188 CRT_HOTPLUG_MONITOR_NONE)
189 ret = true;
190
191 /* Restore the saved ADPA */
192 REG_WRITE(ADPA, adpa_orig);
193 return ret;
194}
195
196static enum drm_connector_status cdv_intel_crt_detect(
197 struct drm_connector *connector, bool force)
198{
199 if (cdv_intel_crt_detect_hotplug(connector, force))
200 return connector_status_connected;
201 else
202 return connector_status_disconnected;
203}
204
205static void cdv_intel_crt_destroy(struct drm_connector *connector)
206{
207 struct psb_intel_output *intel_output = to_psb_intel_output(connector);
208
209 psb_intel_i2c_destroy(intel_output->ddc_bus);
210 drm_sysfs_connector_remove(connector);
211 drm_connector_cleanup(connector);
212 kfree(connector);
213}
214
215static int cdv_intel_crt_get_modes(struct drm_connector *connector)
216{
217 struct psb_intel_output *intel_output =
218 to_psb_intel_output(connector);
219 return psb_intel_ddc_get_modes(intel_output);
220}
221
222static int cdv_intel_crt_set_property(struct drm_connector *connector,
223 struct drm_property *property,
224 uint64_t value)
225{
226 return 0;
227}
228
229/*
230 * Routines for controlling stuff on the analog port
231 */
232
233static const struct drm_encoder_helper_funcs cdv_intel_crt_helper_funcs = {
234 .dpms = cdv_intel_crt_dpms,
235 .mode_fixup = cdv_intel_crt_mode_fixup,
236 .prepare = psb_intel_encoder_prepare,
237 .commit = psb_intel_encoder_commit,
238 .mode_set = cdv_intel_crt_mode_set,
239};
240
241static const struct drm_connector_funcs cdv_intel_crt_connector_funcs = {
242 .dpms = drm_helper_connector_dpms,
243 .detect = cdv_intel_crt_detect,
244 .fill_modes = drm_helper_probe_single_connector_modes,
245 .destroy = cdv_intel_crt_destroy,
246 .set_property = cdv_intel_crt_set_property,
247};
248
249static const struct drm_connector_helper_funcs
250 cdv_intel_crt_connector_helper_funcs = {
251 .mode_valid = cdv_intel_crt_mode_valid,
252 .get_modes = cdv_intel_crt_get_modes,
253 .best_encoder = psb_intel_best_encoder,
254};
255
256static void cdv_intel_crt_enc_destroy(struct drm_encoder *encoder)
257{
258 drm_encoder_cleanup(encoder);
259}
260
261static const struct drm_encoder_funcs cdv_intel_crt_enc_funcs = {
262 .destroy = cdv_intel_crt_enc_destroy,
263};
264
265void cdv_intel_crt_init(struct drm_device *dev,
266 struct psb_intel_mode_device *mode_dev)
267{
268
269 struct psb_intel_output *psb_intel_output;
270 struct drm_connector *connector;
271 struct drm_encoder *encoder;
272
273 u32 i2c_reg;
274
275 psb_intel_output = kzalloc(sizeof(struct psb_intel_output), GFP_KERNEL);
276 if (!psb_intel_output)
277 return;
278
279 psb_intel_output->mode_dev = mode_dev;
280 connector = &psb_intel_output->base;
281 drm_connector_init(dev, connector,
282 &cdv_intel_crt_connector_funcs, DRM_MODE_CONNECTOR_VGA);
283
284 encoder = &psb_intel_output->enc;
285 drm_encoder_init(dev, encoder,
286 &cdv_intel_crt_enc_funcs, DRM_MODE_ENCODER_DAC);
287
288 drm_mode_connector_attach_encoder(&psb_intel_output->base,
289 &psb_intel_output->enc);
290
291 /* Set up the DDC bus. */
292 i2c_reg = GPIOA;
293 /* Remove the following code for CDV */
294 /*
295 if (dev_priv->crt_ddc_bus != 0)
296 i2c_reg = dev_priv->crt_ddc_bus;
297 }*/
298 psb_intel_output->ddc_bus = psb_intel_i2c_create(dev,
299 i2c_reg, "CRTDDC_A");
300 if (!psb_intel_output->ddc_bus) {
301 dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration "
302 "failed.\n");
303 goto failed_ddc;
304 }
305
306 psb_intel_output->type = INTEL_OUTPUT_ANALOG;
307 /*
308 psb_intel_output->clone_mask = (1 << INTEL_ANALOG_CLONE_BIT);
309 psb_intel_output->crtc_mask = (1 << 0) | (1 << 1);
310 */
311 connector->interlace_allowed = 0;
312 connector->doublescan_allowed = 0;
313
314 drm_encoder_helper_add(encoder, &cdv_intel_crt_helper_funcs);
315 drm_connector_helper_add(connector,
316 &cdv_intel_crt_connector_helper_funcs);
317
318 drm_sysfs_connector_add(connector);
319
320 return;
321failed_ddc:
322 drm_encoder_cleanup(&psb_intel_output->enc);
323 drm_connector_cleanup(&psb_intel_output->base);
324 kfree(psb_intel_output);
325 return;
326}
diff --git a/drivers/gpu/drm/gma500/cdv_intel_display.c b/drivers/gpu/drm/gma500/cdv_intel_display.c
new file mode 100644
index 000000000000..7b97c600eff0
--- /dev/null
+++ b/drivers/gpu/drm/gma500/cdv_intel_display.c
@@ -0,0 +1,1508 @@
1/*
2 * Copyright © 2006-2011 Intel Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
16 *
17 * Authors:
18 * Eric Anholt <eric@anholt.net>
19 */
20
21#include <linux/i2c.h>
22#include <linux/pm_runtime.h>
23
24#include <drm/drmP.h>
25#include "framebuffer.h"
26#include "psb_drv.h"
27#include "psb_intel_drv.h"
28#include "psb_intel_reg.h"
29#include "psb_intel_display.h"
30#include "power.h"
31#include "cdv_device.h"
32
33
34struct cdv_intel_range_t {
35 int min, max;
36};
37
38struct cdv_intel_p2_t {
39 int dot_limit;
40 int p2_slow, p2_fast;
41};
42
43struct cdv_intel_clock_t {
44 /* given values */
45 int n;
46 int m1, m2;
47 int p1, p2;
48 /* derived values */
49 int dot;
50 int vco;
51 int m;
52 int p;
53};
54
55#define INTEL_P2_NUM 2
56
57struct cdv_intel_limit_t {
58 struct cdv_intel_range_t dot, vco, n, m, m1, m2, p, p1;
59 struct cdv_intel_p2_t p2;
60};
61
62#define CDV_LIMIT_SINGLE_LVDS_96 0
63#define CDV_LIMIT_SINGLE_LVDS_100 1
64#define CDV_LIMIT_DAC_HDMI_27 2
65#define CDV_LIMIT_DAC_HDMI_96 3
66
67static const struct cdv_intel_limit_t cdv_intel_limits[] = {
68 { /* CDV_SIGNLE_LVDS_96MHz */
69 .dot = {.min = 20000, .max = 115500},
70 .vco = {.min = 1800000, .max = 3600000},
71 .n = {.min = 2, .max = 6},
72 .m = {.min = 60, .max = 160},
73 .m1 = {.min = 0, .max = 0},
74 .m2 = {.min = 58, .max = 158},
75 .p = {.min = 28, .max = 140},
76 .p1 = {.min = 2, .max = 10},
77 .p2 = {.dot_limit = 200000,
78 .p2_slow = 14, .p2_fast = 14},
79 },
80 { /* CDV_SINGLE_LVDS_100MHz */
81 .dot = {.min = 20000, .max = 115500},
82 .vco = {.min = 1800000, .max = 3600000},
83 .n = {.min = 2, .max = 6},
84 .m = {.min = 60, .max = 160},
85 .m1 = {.min = 0, .max = 0},
86 .m2 = {.min = 58, .max = 158},
87 .p = {.min = 28, .max = 140},
88 .p1 = {.min = 2, .max = 10},
89 /* The single-channel range is 25-112Mhz, and dual-channel
90 * is 80-224Mhz. Prefer single channel as much as possible.
91 */
92 .p2 = {.dot_limit = 200000, .p2_slow = 14, .p2_fast = 14},
93 },
94 { /* CDV_DAC_HDMI_27MHz */
95 .dot = {.min = 20000, .max = 400000},
96 .vco = {.min = 1809000, .max = 3564000},
97 .n = {.min = 1, .max = 1},
98 .m = {.min = 67, .max = 132},
99 .m1 = {.min = 0, .max = 0},
100 .m2 = {.min = 65, .max = 130},
101 .p = {.min = 5, .max = 90},
102 .p1 = {.min = 1, .max = 9},
103 .p2 = {.dot_limit = 225000, .p2_slow = 10, .p2_fast = 5},
104 },
105 { /* CDV_DAC_HDMI_96MHz */
106 .dot = {.min = 20000, .max = 400000},
107 .vco = {.min = 1800000, .max = 3600000},
108 .n = {.min = 2, .max = 6},
109 .m = {.min = 60, .max = 160},
110 .m1 = {.min = 0, .max = 0},
111 .m2 = {.min = 58, .max = 158},
112 .p = {.min = 5, .max = 100},
113 .p1 = {.min = 1, .max = 10},
114 .p2 = {.dot_limit = 225000, .p2_slow = 10, .p2_fast = 5},
115 },
116};
117
118#define _wait_for(COND, MS, W) ({ \
119 unsigned long timeout__ = jiffies + msecs_to_jiffies(MS); \
120 int ret__ = 0; \
121 while (!(COND)) { \
122 if (time_after(jiffies, timeout__)) { \
123 ret__ = -ETIMEDOUT; \
124 break; \
125 } \
126 if (W && !in_dbg_master()) \
127 msleep(W); \
128 } \
129 ret__; \
130})
131
132#define wait_for(COND, MS) _wait_for(COND, MS, 1)
133
134
135static int cdv_sb_read(struct drm_device *dev, u32 reg, u32 *val)
136{
137 int ret;
138
139 ret = wait_for((REG_READ(SB_PCKT) & SB_BUSY) == 0, 1000);
140 if (ret) {
141 DRM_ERROR("timeout waiting for SB to idle before read\n");
142 return ret;
143 }
144
145 REG_WRITE(SB_ADDR, reg);
146 REG_WRITE(SB_PCKT,
147 SET_FIELD(SB_OPCODE_READ, SB_OPCODE) |
148 SET_FIELD(SB_DEST_DPLL, SB_DEST) |
149 SET_FIELD(0xf, SB_BYTE_ENABLE));
150
151 ret = wait_for((REG_READ(SB_PCKT) & SB_BUSY) == 0, 1000);
152 if (ret) {
153 DRM_ERROR("timeout waiting for SB to idle after read\n");
154 return ret;
155 }
156
157 *val = REG_READ(SB_DATA);
158
159 return 0;
160}
161
162static int cdv_sb_write(struct drm_device *dev, u32 reg, u32 val)
163{
164 int ret;
165 static bool dpio_debug = true;
166 u32 temp;
167
168 if (dpio_debug) {
169 if (cdv_sb_read(dev, reg, &temp) == 0)
170 DRM_DEBUG_KMS("0x%08x: 0x%08x (before)\n", reg, temp);
171 DRM_DEBUG_KMS("0x%08x: 0x%08x\n", reg, val);
172 }
173
174 ret = wait_for((REG_READ(SB_PCKT) & SB_BUSY) == 0, 1000);
175 if (ret) {
176 DRM_ERROR("timeout waiting for SB to idle before write\n");
177 return ret;
178 }
179
180 REG_WRITE(SB_ADDR, reg);
181 REG_WRITE(SB_DATA, val);
182 REG_WRITE(SB_PCKT,
183 SET_FIELD(SB_OPCODE_WRITE, SB_OPCODE) |
184 SET_FIELD(SB_DEST_DPLL, SB_DEST) |
185 SET_FIELD(0xf, SB_BYTE_ENABLE));
186
187 ret = wait_for((REG_READ(SB_PCKT) & SB_BUSY) == 0, 1000);
188 if (ret) {
189 DRM_ERROR("timeout waiting for SB to idle after write\n");
190 return ret;
191 }
192
193 if (dpio_debug) {
194 if (cdv_sb_read(dev, reg, &temp) == 0)
195 DRM_DEBUG_KMS("0x%08x: 0x%08x (after)\n", reg, temp);
196 }
197
198 return 0;
199}
200
201/* Reset the DPIO configuration register. The BIOS does this at every
202 * mode set.
203 */
204static void cdv_sb_reset(struct drm_device *dev)
205{
206
207 REG_WRITE(DPIO_CFG, 0);
208 REG_READ(DPIO_CFG);
209 REG_WRITE(DPIO_CFG, DPIO_MODE_SELECT_0 | DPIO_CMN_RESET_N);
210}
211
212/* Unlike most Intel display engines, on Cedarview the DPLL registers
213 * are behind this sideband bus. They must be programmed while the
214 * DPLL reference clock is on in the DPLL control register, but before
215 * the DPLL is enabled in the DPLL control register.
216 */
217static int
218cdv_dpll_set_clock_cdv(struct drm_device *dev, struct drm_crtc *crtc,
219 struct cdv_intel_clock_t *clock)
220{
221 struct psb_intel_crtc *psb_crtc =
222 to_psb_intel_crtc(crtc);
223 int pipe = psb_crtc->pipe;
224 u32 m, n_vco, p;
225 int ret = 0;
226 int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
227 u32 ref_value;
228
229 cdv_sb_reset(dev);
230
231 if ((REG_READ(dpll_reg) & DPLL_SYNCLOCK_ENABLE) == 0) {
232 DRM_ERROR("Attempting to set DPLL with refclk disabled\n");
233 return -EBUSY;
234 }
235
236 /* Follow the BIOS and write the REF/SFR Register. Hardcoded value */
237 ref_value = 0x68A701;
238
239 cdv_sb_write(dev, SB_REF_SFR(pipe), ref_value);
240
241 /* We don't know what the other fields of these regs are, so
242 * leave them in place.
243 */
244 ret = cdv_sb_read(dev, SB_M(pipe), &m);
245 if (ret)
246 return ret;
247 m &= ~SB_M_DIVIDER_MASK;
248 m |= ((clock->m2) << SB_M_DIVIDER_SHIFT);
249 ret = cdv_sb_write(dev, SB_M(pipe), m);
250 if (ret)
251 return ret;
252
253 ret = cdv_sb_read(dev, SB_N_VCO(pipe), &n_vco);
254 if (ret)
255 return ret;
256
257 /* Follow the BIOS to program the N_DIVIDER REG */
258 n_vco &= 0xFFFF;
259 n_vco |= 0x107;
260 n_vco &= ~(SB_N_VCO_SEL_MASK |
261 SB_N_DIVIDER_MASK |
262 SB_N_CB_TUNE_MASK);
263
264 n_vco |= ((clock->n) << SB_N_DIVIDER_SHIFT);
265
266 if (clock->vco < 2250000) {
267 n_vco |= (2 << SB_N_CB_TUNE_SHIFT);
268 n_vco |= (0 << SB_N_VCO_SEL_SHIFT);
269 } else if (clock->vco < 2750000) {
270 n_vco |= (1 << SB_N_CB_TUNE_SHIFT);
271 n_vco |= (1 << SB_N_VCO_SEL_SHIFT);
272 } else if (clock->vco < 3300000) {
273 n_vco |= (0 << SB_N_CB_TUNE_SHIFT);
274 n_vco |= (2 << SB_N_VCO_SEL_SHIFT);
275 } else {
276 n_vco |= (0 << SB_N_CB_TUNE_SHIFT);
277 n_vco |= (3 << SB_N_VCO_SEL_SHIFT);
278 }
279
280 ret = cdv_sb_write(dev, SB_N_VCO(pipe), n_vco);
281 if (ret)
282 return ret;
283
284 ret = cdv_sb_read(dev, SB_P(pipe), &p);
285 if (ret)
286 return ret;
287 p &= ~(SB_P2_DIVIDER_MASK | SB_P1_DIVIDER_MASK);
288 p |= SET_FIELD(clock->p1, SB_P1_DIVIDER);
289 switch (clock->p2) {
290 case 5:
291 p |= SET_FIELD(SB_P2_5, SB_P2_DIVIDER);
292 break;
293 case 10:
294 p |= SET_FIELD(SB_P2_10, SB_P2_DIVIDER);
295 break;
296 case 14:
297 p |= SET_FIELD(SB_P2_14, SB_P2_DIVIDER);
298 break;
299 case 7:
300 p |= SET_FIELD(SB_P2_7, SB_P2_DIVIDER);
301 break;
302 default:
303 DRM_ERROR("Bad P2 clock: %d\n", clock->p2);
304 return -EINVAL;
305 }
306 ret = cdv_sb_write(dev, SB_P(pipe), p);
307 if (ret)
308 return ret;
309
310 /* always Program the Lane Register for the Pipe A*/
311 if (pipe == 0) {
312 /* Program the Lane0/1 for HDMI B */
313 u32 lane_reg, lane_value;
314
315 lane_reg = PSB_LANE0;
316 cdv_sb_read(dev, lane_reg, &lane_value);
317 lane_value &= ~(LANE_PLL_MASK);
318 lane_value |= LANE_PLL_ENABLE;
319 cdv_sb_write(dev, lane_reg, lane_value);
320
321 lane_reg = PSB_LANE1;
322 cdv_sb_read(dev, lane_reg, &lane_value);
323 lane_value &= ~(LANE_PLL_MASK);
324 lane_value |= LANE_PLL_ENABLE;
325 cdv_sb_write(dev, lane_reg, lane_value);
326
327 /* Program the Lane2/3 for HDMI C */
328 lane_reg = PSB_LANE2;
329 cdv_sb_read(dev, lane_reg, &lane_value);
330 lane_value &= ~(LANE_PLL_MASK);
331 lane_value |= LANE_PLL_ENABLE;
332 cdv_sb_write(dev, lane_reg, lane_value);
333
334 lane_reg = PSB_LANE3;
335 cdv_sb_read(dev, lane_reg, &lane_value);
336 lane_value &= ~(LANE_PLL_MASK);
337 lane_value |= LANE_PLL_ENABLE;
338 cdv_sb_write(dev, lane_reg, lane_value);
339 }
340
341 return 0;
342}
343
344/*
345 * Returns whether any output on the specified pipe is of the specified type
346 */
347bool cdv_intel_pipe_has_type(struct drm_crtc *crtc, int type)
348{
349 struct drm_device *dev = crtc->dev;
350 struct drm_mode_config *mode_config = &dev->mode_config;
351 struct drm_connector *l_entry;
352
353 list_for_each_entry(l_entry, &mode_config->connector_list, head) {
354 if (l_entry->encoder && l_entry->encoder->crtc == crtc) {
355 struct psb_intel_output *psb_intel_output =
356 to_psb_intel_output(l_entry);
357 if (psb_intel_output->type == type)
358 return true;
359 }
360 }
361 return false;
362}
363
364static const struct cdv_intel_limit_t *cdv_intel_limit(struct drm_crtc *crtc,
365 int refclk)
366{
367 const struct cdv_intel_limit_t *limit;
368 if (cdv_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
369 /*
370 * Now only single-channel LVDS is supported on CDV. If it is
371 * incorrect, please add the dual-channel LVDS.
372 */
373 if (refclk == 96000)
374 limit = &cdv_intel_limits[CDV_LIMIT_SINGLE_LVDS_96];
375 else
376 limit = &cdv_intel_limits[CDV_LIMIT_SINGLE_LVDS_100];
377 } else {
378 if (refclk == 27000)
379 limit = &cdv_intel_limits[CDV_LIMIT_DAC_HDMI_27];
380 else
381 limit = &cdv_intel_limits[CDV_LIMIT_DAC_HDMI_96];
382 }
383 return limit;
384}
385
386/* m1 is reserved as 0 in CDV, n is a ring counter */
387static void cdv_intel_clock(struct drm_device *dev,
388 int refclk, struct cdv_intel_clock_t *clock)
389{
390 clock->m = clock->m2 + 2;
391 clock->p = clock->p1 * clock->p2;
392 clock->vco = (refclk * clock->m) / clock->n;
393 clock->dot = clock->vco / clock->p;
394}
395
396
397#define INTELPllInvalid(s) { /* ErrorF (s) */; return false; }
398static bool cdv_intel_PLL_is_valid(struct drm_crtc *crtc,
399 const struct cdv_intel_limit_t *limit,
400 struct cdv_intel_clock_t *clock)
401{
402 if (clock->p1 < limit->p1.min || limit->p1.max < clock->p1)
403 INTELPllInvalid("p1 out of range\n");
404 if (clock->p < limit->p.min || limit->p.max < clock->p)
405 INTELPllInvalid("p out of range\n");
406 /* unnecessary to check the range of m(m1/M2)/n again */
407 if (clock->vco < limit->vco.min || limit->vco.max < clock->vco)
408 INTELPllInvalid("vco out of range\n");
409 /* XXX: We may need to be checking "Dot clock"
410 * depending on the multiplier, connector, etc.,
411 * rather than just a single range.
412 */
413 if (clock->dot < limit->dot.min || limit->dot.max < clock->dot)
414 INTELPllInvalid("dot out of range\n");
415
416 return true;
417}
418
419static bool cdv_intel_find_best_PLL(struct drm_crtc *crtc, int target,
420 int refclk,
421 struct cdv_intel_clock_t *best_clock)
422{
423 struct drm_device *dev = crtc->dev;
424 struct cdv_intel_clock_t clock;
425 const struct cdv_intel_limit_t *limit = cdv_intel_limit(crtc, refclk);
426 int err = target;
427
428
429 if (cdv_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
430 (REG_READ(LVDS) & LVDS_PORT_EN) != 0) {
431 /*
432 * For LVDS, if the panel is on, just rely on its current
433 * settings for dual-channel. We haven't figured out how to
434 * reliably set up different single/dual channel state, if we
435 * even can.
436 */
437 if ((REG_READ(LVDS) & LVDS_CLKB_POWER_MASK) ==
438 LVDS_CLKB_POWER_UP)
439 clock.p2 = limit->p2.p2_fast;
440 else
441 clock.p2 = limit->p2.p2_slow;
442 } else {
443 if (target < limit->p2.dot_limit)
444 clock.p2 = limit->p2.p2_slow;
445 else
446 clock.p2 = limit->p2.p2_fast;
447 }
448
449 memset(best_clock, 0, sizeof(*best_clock));
450 clock.m1 = 0;
451 /* m1 is reserved as 0 in CDV, n is a ring counter.
452 So skip the m1 loop */
453 for (clock.n = limit->n.min; clock.n <= limit->n.max; clock.n++) {
454 for (clock.m2 = limit->m2.min; clock.m2 <= limit->m2.max;
455 clock.m2++) {
456 for (clock.p1 = limit->p1.min;
457 clock.p1 <= limit->p1.max;
458 clock.p1++) {
459 int this_err;
460
461 cdv_intel_clock(dev, refclk, &clock);
462
463 if (!cdv_intel_PLL_is_valid(crtc,
464 limit, &clock))
465 continue;
466
467 this_err = abs(clock.dot - target);
468 if (this_err < err) {
469 *best_clock = clock;
470 err = this_err;
471 }
472 }
473 }
474 }
475
476 return err != target;
477}
478
479int cdv_intel_pipe_set_base(struct drm_crtc *crtc,
480 int x, int y, struct drm_framebuffer *old_fb)
481{
482 struct drm_device *dev = crtc->dev;
483 struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
484 struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb);
485 int pipe = psb_intel_crtc->pipe;
486 unsigned long start, offset;
487 int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE);
488 int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF);
489 int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE;
490 int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
491 u32 dspcntr;
492 int ret = 0;
493
494 if (!gma_power_begin(dev, true))
495 return 0;
496
497 /* no fb bound */
498 if (!crtc->fb) {
499 dev_err(dev->dev, "No FB bound\n");
500 goto psb_intel_pipe_cleaner;
501 }
502
503
504 /* We are displaying this buffer, make sure it is actually loaded
505 into the GTT */
506 ret = psb_gtt_pin(psbfb->gtt);
507 if (ret < 0)
508 goto psb_intel_pipe_set_base_exit;
509 start = psbfb->gtt->offset;
510 offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8);
511
512 REG_WRITE(dspstride, crtc->fb->pitch);
513
514 dspcntr = REG_READ(dspcntr_reg);
515 dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
516
517 switch (crtc->fb->bits_per_pixel) {
518 case 8:
519 dspcntr |= DISPPLANE_8BPP;
520 break;
521 case 16:
522 if (crtc->fb->depth == 15)
523 dspcntr |= DISPPLANE_15_16BPP;
524 else
525 dspcntr |= DISPPLANE_16BPP;
526 break;
527 case 24:
528 case 32:
529 dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
530 break;
531 default:
532 dev_err(dev->dev, "Unknown color depth\n");
533 ret = -EINVAL;
534 goto psb_intel_pipe_set_base_exit;
535 }
536 REG_WRITE(dspcntr_reg, dspcntr);
537
538 dev_dbg(dev->dev,
539 "Writing base %08lX %08lX %d %d\n", start, offset, x, y);
540
541 REG_WRITE(dspbase, offset);
542 REG_READ(dspbase);
543 REG_WRITE(dspsurf, start);
544 REG_READ(dspsurf);
545
546psb_intel_pipe_cleaner:
547 /* If there was a previous display we can now unpin it */
548 if (old_fb)
549 psb_gtt_unpin(to_psb_fb(old_fb)->gtt);
550
551psb_intel_pipe_set_base_exit:
552 gma_power_end(dev);
553 return ret;
554}
555
556/**
557 * Sets the power management mode of the pipe and plane.
558 *
559 * This code should probably grow support for turning the cursor off and back
560 * on appropriately at the same time as we're turning the pipe off/on.
561 */
562static void cdv_intel_crtc_dpms(struct drm_crtc *crtc, int mode)
563{
564 struct drm_device *dev = crtc->dev;
565 struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
566 int pipe = psb_intel_crtc->pipe;
567 int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
568 int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
569 int dspbase_reg = (pipe == 0) ? DSPABASE : DSPBBASE;
570 int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
571 u32 temp;
572 bool enabled;
573
574 /* XXX: When our outputs are all unaware of DPMS modes other than off
575 * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC.
576 */
577 switch (mode) {
578 case DRM_MODE_DPMS_ON:
579 case DRM_MODE_DPMS_STANDBY:
580 case DRM_MODE_DPMS_SUSPEND:
581 /* Enable the DPLL */
582 temp = REG_READ(dpll_reg);
583 if ((temp & DPLL_VCO_ENABLE) == 0) {
584 REG_WRITE(dpll_reg, temp);
585 REG_READ(dpll_reg);
586 /* Wait for the clocks to stabilize. */
587 udelay(150);
588 REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE);
589 REG_READ(dpll_reg);
590 /* Wait for the clocks to stabilize. */
591 udelay(150);
592 REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE);
593 REG_READ(dpll_reg);
594 /* Wait for the clocks to stabilize. */
595 udelay(150);
596 }
597
598 /* Jim Bish - switch plan and pipe per scott */
599 /* Enable the plane */
600 temp = REG_READ(dspcntr_reg);
601 if ((temp & DISPLAY_PLANE_ENABLE) == 0) {
602 REG_WRITE(dspcntr_reg,
603 temp | DISPLAY_PLANE_ENABLE);
604 /* Flush the plane changes */
605 REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
606 }
607
608 udelay(150);
609
610 /* Enable the pipe */
611 temp = REG_READ(pipeconf_reg);
612 if ((temp & PIPEACONF_ENABLE) == 0)
613 REG_WRITE(pipeconf_reg, temp | PIPEACONF_ENABLE);
614
615 psb_intel_crtc_load_lut(crtc);
616
617 /* Give the overlay scaler a chance to enable
618 * if it's on this pipe */
619 /* psb_intel_crtc_dpms_video(crtc, true); TODO */
620 break;
621 case DRM_MODE_DPMS_OFF:
622 /* Give the overlay scaler a chance to disable
623 * if it's on this pipe */
624 /* psb_intel_crtc_dpms_video(crtc, FALSE); TODO */
625
626 /* Disable the VGA plane that we never use */
627 REG_WRITE(VGACNTRL, VGA_DISP_DISABLE);
628
629 /* Jim Bish - changed pipe/plane here as well. */
630
631 /* Wait for vblank for the disable to take effect */
632 cdv_intel_wait_for_vblank(dev);
633
634 /* Next, disable display pipes */
635 temp = REG_READ(pipeconf_reg);
636 if ((temp & PIPEACONF_ENABLE) != 0) {
637 REG_WRITE(pipeconf_reg, temp & ~PIPEACONF_ENABLE);
638 REG_READ(pipeconf_reg);
639 }
640
641 /* Wait for vblank for the disable to take effect. */
642 cdv_intel_wait_for_vblank(dev);
643
644 udelay(150);
645
646 /* Disable display plane */
647 temp = REG_READ(dspcntr_reg);
648 if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
649 REG_WRITE(dspcntr_reg,
650 temp & ~DISPLAY_PLANE_ENABLE);
651 /* Flush the plane changes */
652 REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
653 REG_READ(dspbase_reg);
654 }
655
656 temp = REG_READ(dpll_reg);
657 if ((temp & DPLL_VCO_ENABLE) != 0) {
658 REG_WRITE(dpll_reg, temp & ~DPLL_VCO_ENABLE);
659 REG_READ(dpll_reg);
660 }
661
662 /* Wait for the clocks to turn off. */
663 udelay(150);
664 break;
665 }
666 enabled = crtc->enabled && mode != DRM_MODE_DPMS_OFF;
667 /*Set FIFO Watermarks*/
668 REG_WRITE(DSPARB, 0x3F3E);
669}
670
671static void cdv_intel_crtc_prepare(struct drm_crtc *crtc)
672{
673 struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
674 crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
675}
676
677static void cdv_intel_crtc_commit(struct drm_crtc *crtc)
678{
679 struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
680 crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
681}
682
683void cdv_intel_encoder_prepare(struct drm_encoder *encoder)
684{
685 struct drm_encoder_helper_funcs *encoder_funcs =
686 encoder->helper_private;
687 /* lvds has its own version of prepare see cdv_intel_lvds_prepare */
688 encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
689}
690
691void cdv_intel_encoder_commit(struct drm_encoder *encoder)
692{
693 struct drm_encoder_helper_funcs *encoder_funcs =
694 encoder->helper_private;
695 /* lvds has its own version of commit see cdv_intel_lvds_commit */
696 encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
697}
698
699static bool cdv_intel_crtc_mode_fixup(struct drm_crtc *crtc,
700 struct drm_display_mode *mode,
701 struct drm_display_mode *adjusted_mode)
702{
703 return true;
704}
705
706
707/**
708 * Return the pipe currently connected to the panel fitter,
709 * or -1 if the panel fitter is not present or not in use
710 */
711static int cdv_intel_panel_fitter_pipe(struct drm_device *dev)
712{
713 u32 pfit_control;
714
715 pfit_control = REG_READ(PFIT_CONTROL);
716
717 /* See if the panel fitter is in use */
718 if ((pfit_control & PFIT_ENABLE) == 0)
719 return -1;
720 return (pfit_control >> 29) & 0x3;
721}
722
723static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc,
724 struct drm_display_mode *mode,
725 struct drm_display_mode *adjusted_mode,
726 int x, int y,
727 struct drm_framebuffer *old_fb)
728{
729 struct drm_device *dev = crtc->dev;
730 struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
731 int pipe = psb_intel_crtc->pipe;
732 int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
733 int dpll_md_reg = (psb_intel_crtc->pipe == 0) ? DPLL_A_MD : DPLL_B_MD;
734 int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
735 int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
736 int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B;
737 int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B;
738 int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B;
739 int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B;
740 int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B;
741 int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B;
742 int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE;
743 int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS;
744 int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC;
745 int refclk;
746 struct cdv_intel_clock_t clock;
747 u32 dpll = 0, dspcntr, pipeconf;
748 bool ok, is_sdvo = false, is_dvo = false;
749 bool is_crt = false, is_lvds = false, is_tv = false;
750 bool is_hdmi = false;
751 struct drm_mode_config *mode_config = &dev->mode_config;
752 struct drm_connector *connector;
753
754 list_for_each_entry(connector, &mode_config->connector_list, head) {
755 struct psb_intel_output *psb_intel_output =
756 to_psb_intel_output(connector);
757
758 if (!connector->encoder
759 || connector->encoder->crtc != crtc)
760 continue;
761
762 switch (psb_intel_output->type) {
763 case INTEL_OUTPUT_LVDS:
764 is_lvds = true;
765 break;
766 case INTEL_OUTPUT_SDVO:
767 is_sdvo = true;
768 break;
769 case INTEL_OUTPUT_DVO:
770 is_dvo = true;
771 break;
772 case INTEL_OUTPUT_TVOUT:
773 is_tv = true;
774 break;
775 case INTEL_OUTPUT_ANALOG:
776 is_crt = true;
777 break;
778 case INTEL_OUTPUT_HDMI:
779 is_hdmi = true;
780 break;
781 }
782 }
783
784 refclk = 96000;
785
786 /* Hack selection about ref clk for CRT */
787 /* Select 27MHz as the reference clk for HDMI */
788 if (is_crt || is_hdmi)
789 refclk = 27000;
790
791 drm_mode_debug_printmodeline(adjusted_mode);
792
793 ok = cdv_intel_find_best_PLL(crtc, adjusted_mode->clock, refclk,
794 &clock);
795 if (!ok) {
796 dev_err(dev->dev, "Couldn't find PLL settings for mode!\n");
797 return 0;
798 }
799
800 dpll = DPLL_VGA_MODE_DIS;
801 if (is_tv) {
802 /* XXX: just matching BIOS for now */
803/* dpll |= PLL_REF_INPUT_TVCLKINBC; */
804 dpll |= 3;
805 }
806 dpll |= PLL_REF_INPUT_DREFCLK;
807
808 dpll |= DPLL_SYNCLOCK_ENABLE;
809 dpll |= DPLL_VGA_MODE_DIS;
810 if (is_lvds)
811 dpll |= DPLLB_MODE_LVDS;
812 else
813 dpll |= DPLLB_MODE_DAC_SERIAL;
814 /* dpll |= (2 << 11); */
815
816 /* setup pipeconf */
817 pipeconf = REG_READ(pipeconf_reg);
818
819 /* Set up the display plane register */
820 dspcntr = DISPPLANE_GAMMA_ENABLE;
821
822 if (pipe == 0)
823 dspcntr |= DISPPLANE_SEL_PIPE_A;
824 else
825 dspcntr |= DISPPLANE_SEL_PIPE_B;
826
827 dspcntr |= DISPLAY_PLANE_ENABLE;
828 pipeconf |= PIPEACONF_ENABLE;
829
830 REG_WRITE(dpll_reg, dpll | DPLL_VGA_MODE_DIS | DPLL_SYNCLOCK_ENABLE);
831 REG_READ(dpll_reg);
832
833 cdv_dpll_set_clock_cdv(dev, crtc, &clock);
834
835 udelay(150);
836
837
838 /* The LVDS pin pair needs to be on before the DPLLs are enabled.
839 * This is an exception to the general rule that mode_set doesn't turn
840 * things on.
841 */
842 if (is_lvds) {
843 u32 lvds = REG_READ(LVDS);
844
845 lvds |=
846 LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP |
847 LVDS_PIPEB_SELECT;
848 /* Set the B0-B3 data pairs corresponding to
849 * whether we're going to
850 * set the DPLLs for dual-channel mode or not.
851 */
852 if (clock.p2 == 7)
853 lvds |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP;
854 else
855 lvds &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP);
856
857 /* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP)
858 * appropriately here, but we need to look more
859 * thoroughly into how panels behave in the two modes.
860 */
861
862 REG_WRITE(LVDS, lvds);
863 REG_READ(LVDS);
864 }
865
866 dpll |= DPLL_VCO_ENABLE;
867
868 /* Disable the panel fitter if it was on our pipe */
869 if (cdv_intel_panel_fitter_pipe(dev) == pipe)
870 REG_WRITE(PFIT_CONTROL, 0);
871
872 DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
873 drm_mode_debug_printmodeline(mode);
874
875 REG_WRITE(dpll_reg,
876 (REG_READ(dpll_reg) & ~DPLL_LOCK) | DPLL_VCO_ENABLE);
877 REG_READ(dpll_reg);
878 /* Wait for the clocks to stabilize. */
879 udelay(150); /* 42 usec w/o calibration, 110 with. rounded up. */
880
881 if (!(REG_READ(dpll_reg) & DPLL_LOCK)) {
882 dev_err(dev->dev, "Failed to get DPLL lock\n");
883 return -EBUSY;
884 }
885
886 {
887 int sdvo_pixel_multiply = adjusted_mode->clock / mode->clock;
888 REG_WRITE(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) | ((sdvo_pixel_multiply - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT));
889 }
890
891 REG_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) |
892 ((adjusted_mode->crtc_htotal - 1) << 16));
893 REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) |
894 ((adjusted_mode->crtc_hblank_end - 1) << 16));
895 REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) |
896 ((adjusted_mode->crtc_hsync_end - 1) << 16));
897 REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) |
898 ((adjusted_mode->crtc_vtotal - 1) << 16));
899 REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) |
900 ((adjusted_mode->crtc_vblank_end - 1) << 16));
901 REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) |
902 ((adjusted_mode->crtc_vsync_end - 1) << 16));
903 /* pipesrc and dspsize control the size that is scaled from,
904 * which should always be the user's requested size.
905 */
906 REG_WRITE(dspsize_reg,
907 ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1));
908 REG_WRITE(dsppos_reg, 0);
909 REG_WRITE(pipesrc_reg,
910 ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1));
911 REG_WRITE(pipeconf_reg, pipeconf);
912 REG_READ(pipeconf_reg);
913
914 cdv_intel_wait_for_vblank(dev);
915
916 REG_WRITE(dspcntr_reg, dspcntr);
917
918 /* Flush the plane changes */
919 {
920 struct drm_crtc_helper_funcs *crtc_funcs =
921 crtc->helper_private;
922 crtc_funcs->mode_set_base(crtc, x, y, old_fb);
923 }
924
925 cdv_intel_wait_for_vblank(dev);
926
927 return 0;
928}
929
930/** Loads the palette/gamma unit for the CRTC with the prepared values */
931void cdv_intel_crtc_load_lut(struct drm_crtc *crtc)
932{
933 struct drm_device *dev = crtc->dev;
934 struct drm_psb_private *dev_priv =
935 (struct drm_psb_private *)dev->dev_private;
936 struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
937 int palreg = PALETTE_A;
938 int i;
939
940 /* The clocks have to be on to load the palette. */
941 if (!crtc->enabled)
942 return;
943
944 switch (psb_intel_crtc->pipe) {
945 case 0:
946 break;
947 case 1:
948 palreg = PALETTE_B;
949 break;
950 case 2:
951 palreg = PALETTE_C;
952 break;
953 default:
954 dev_err(dev->dev, "Illegal Pipe Number.\n");
955 return;
956 }
957
958 if (gma_power_begin(dev, false)) {
959 for (i = 0; i < 256; i++) {
960 REG_WRITE(palreg + 4 * i,
961 ((psb_intel_crtc->lut_r[i] +
962 psb_intel_crtc->lut_adj[i]) << 16) |
963 ((psb_intel_crtc->lut_g[i] +
964 psb_intel_crtc->lut_adj[i]) << 8) |
965 (psb_intel_crtc->lut_b[i] +
966 psb_intel_crtc->lut_adj[i]));
967 }
968 gma_power_end(dev);
969 } else {
970 for (i = 0; i < 256; i++) {
971 dev_priv->save_palette_a[i] =
972 ((psb_intel_crtc->lut_r[i] +
973 psb_intel_crtc->lut_adj[i]) << 16) |
974 ((psb_intel_crtc->lut_g[i] +
975 psb_intel_crtc->lut_adj[i]) << 8) |
976 (psb_intel_crtc->lut_b[i] +
977 psb_intel_crtc->lut_adj[i]);
978 }
979
980 }
981}
982
983/**
984 * Save HW states of giving crtc
985 */
986static void cdv_intel_crtc_save(struct drm_crtc *crtc)
987{
988 struct drm_device *dev = crtc->dev;
989 /* struct drm_psb_private *dev_priv =
990 (struct drm_psb_private *)dev->dev_private; */
991 struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
992 struct psb_intel_crtc_state *crtc_state = psb_intel_crtc->crtc_state;
993 int pipeA = (psb_intel_crtc->pipe == 0);
994 uint32_t paletteReg;
995 int i;
996
997 if (!crtc_state) {
998 dev_dbg(dev->dev, "No CRTC state found\n");
999 return;
1000 }
1001
1002 crtc_state->saveDSPCNTR = REG_READ(pipeA ? DSPACNTR : DSPBCNTR);
1003 crtc_state->savePIPECONF = REG_READ(pipeA ? PIPEACONF : PIPEBCONF);
1004 crtc_state->savePIPESRC = REG_READ(pipeA ? PIPEASRC : PIPEBSRC);
1005 crtc_state->saveFP0 = REG_READ(pipeA ? FPA0 : FPB0);
1006 crtc_state->saveFP1 = REG_READ(pipeA ? FPA1 : FPB1);
1007 crtc_state->saveDPLL = REG_READ(pipeA ? DPLL_A : DPLL_B);
1008 crtc_state->saveHTOTAL = REG_READ(pipeA ? HTOTAL_A : HTOTAL_B);
1009 crtc_state->saveHBLANK = REG_READ(pipeA ? HBLANK_A : HBLANK_B);
1010 crtc_state->saveHSYNC = REG_READ(pipeA ? HSYNC_A : HSYNC_B);
1011 crtc_state->saveVTOTAL = REG_READ(pipeA ? VTOTAL_A : VTOTAL_B);
1012 crtc_state->saveVBLANK = REG_READ(pipeA ? VBLANK_A : VBLANK_B);
1013 crtc_state->saveVSYNC = REG_READ(pipeA ? VSYNC_A : VSYNC_B);
1014 crtc_state->saveDSPSTRIDE = REG_READ(pipeA ? DSPASTRIDE : DSPBSTRIDE);
1015
1016 /*NOTE: DSPSIZE DSPPOS only for psb*/
1017 crtc_state->saveDSPSIZE = REG_READ(pipeA ? DSPASIZE : DSPBSIZE);
1018 crtc_state->saveDSPPOS = REG_READ(pipeA ? DSPAPOS : DSPBPOS);
1019
1020 crtc_state->saveDSPBASE = REG_READ(pipeA ? DSPABASE : DSPBBASE);
1021
1022 DRM_DEBUG("(%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x)\n",
1023 crtc_state->saveDSPCNTR,
1024 crtc_state->savePIPECONF,
1025 crtc_state->savePIPESRC,
1026 crtc_state->saveFP0,
1027 crtc_state->saveFP1,
1028 crtc_state->saveDPLL,
1029 crtc_state->saveHTOTAL,
1030 crtc_state->saveHBLANK,
1031 crtc_state->saveHSYNC,
1032 crtc_state->saveVTOTAL,
1033 crtc_state->saveVBLANK,
1034 crtc_state->saveVSYNC,
1035 crtc_state->saveDSPSTRIDE,
1036 crtc_state->saveDSPSIZE,
1037 crtc_state->saveDSPPOS,
1038 crtc_state->saveDSPBASE
1039 );
1040
1041 paletteReg = pipeA ? PALETTE_A : PALETTE_B;
1042 for (i = 0; i < 256; ++i)
1043 crtc_state->savePalette[i] = REG_READ(paletteReg + (i << 2));
1044}
1045
1046/**
1047 * Restore HW states of giving crtc
1048 */
1049static void cdv_intel_crtc_restore(struct drm_crtc *crtc)
1050{
1051 struct drm_device *dev = crtc->dev;
1052 /* struct drm_psb_private * dev_priv =
1053 (struct drm_psb_private *)dev->dev_private; */
1054 struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
1055 struct psb_intel_crtc_state *crtc_state = psb_intel_crtc->crtc_state;
1056 /* struct drm_crtc_helper_funcs * crtc_funcs = crtc->helper_private; */
1057 int pipeA = (psb_intel_crtc->pipe == 0);
1058 uint32_t paletteReg;
1059 int i;
1060
1061 if (!crtc_state) {
1062 dev_dbg(dev->dev, "No crtc state\n");
1063 return;
1064 }
1065
1066 DRM_DEBUG(
1067 "current:(%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x)\n",
1068 REG_READ(pipeA ? DSPACNTR : DSPBCNTR),
1069 REG_READ(pipeA ? PIPEACONF : PIPEBCONF),
1070 REG_READ(pipeA ? PIPEASRC : PIPEBSRC),
1071 REG_READ(pipeA ? FPA0 : FPB0),
1072 REG_READ(pipeA ? FPA1 : FPB1),
1073 REG_READ(pipeA ? DPLL_A : DPLL_B),
1074 REG_READ(pipeA ? HTOTAL_A : HTOTAL_B),
1075 REG_READ(pipeA ? HBLANK_A : HBLANK_B),
1076 REG_READ(pipeA ? HSYNC_A : HSYNC_B),
1077 REG_READ(pipeA ? VTOTAL_A : VTOTAL_B),
1078 REG_READ(pipeA ? VBLANK_A : VBLANK_B),
1079 REG_READ(pipeA ? VSYNC_A : VSYNC_B),
1080 REG_READ(pipeA ? DSPASTRIDE : DSPBSTRIDE),
1081 REG_READ(pipeA ? DSPASIZE : DSPBSIZE),
1082 REG_READ(pipeA ? DSPAPOS : DSPBPOS),
1083 REG_READ(pipeA ? DSPABASE : DSPBBASE)
1084 );
1085
1086 DRM_DEBUG(
1087 "saved: (%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x)\n",
1088 crtc_state->saveDSPCNTR,
1089 crtc_state->savePIPECONF,
1090 crtc_state->savePIPESRC,
1091 crtc_state->saveFP0,
1092 crtc_state->saveFP1,
1093 crtc_state->saveDPLL,
1094 crtc_state->saveHTOTAL,
1095 crtc_state->saveHBLANK,
1096 crtc_state->saveHSYNC,
1097 crtc_state->saveVTOTAL,
1098 crtc_state->saveVBLANK,
1099 crtc_state->saveVSYNC,
1100 crtc_state->saveDSPSTRIDE,
1101 crtc_state->saveDSPSIZE,
1102 crtc_state->saveDSPPOS,
1103 crtc_state->saveDSPBASE
1104 );
1105
1106
1107 if (crtc_state->saveDPLL & DPLL_VCO_ENABLE) {
1108 REG_WRITE(pipeA ? DPLL_A : DPLL_B,
1109 crtc_state->saveDPLL & ~DPLL_VCO_ENABLE);
1110 REG_READ(pipeA ? DPLL_A : DPLL_B);
1111 DRM_DEBUG("write dpll: %x\n",
1112 REG_READ(pipeA ? DPLL_A : DPLL_B));
1113 udelay(150);
1114 }
1115
1116 REG_WRITE(pipeA ? FPA0 : FPB0, crtc_state->saveFP0);
1117 REG_READ(pipeA ? FPA0 : FPB0);
1118
1119 REG_WRITE(pipeA ? FPA1 : FPB1, crtc_state->saveFP1);
1120 REG_READ(pipeA ? FPA1 : FPB1);
1121
1122 REG_WRITE(pipeA ? DPLL_A : DPLL_B, crtc_state->saveDPLL);
1123 REG_READ(pipeA ? DPLL_A : DPLL_B);
1124 udelay(150);
1125
1126 REG_WRITE(pipeA ? HTOTAL_A : HTOTAL_B, crtc_state->saveHTOTAL);
1127 REG_WRITE(pipeA ? HBLANK_A : HBLANK_B, crtc_state->saveHBLANK);
1128 REG_WRITE(pipeA ? HSYNC_A : HSYNC_B, crtc_state->saveHSYNC);
1129 REG_WRITE(pipeA ? VTOTAL_A : VTOTAL_B, crtc_state->saveVTOTAL);
1130 REG_WRITE(pipeA ? VBLANK_A : VBLANK_B, crtc_state->saveVBLANK);
1131 REG_WRITE(pipeA ? VSYNC_A : VSYNC_B, crtc_state->saveVSYNC);
1132 REG_WRITE(pipeA ? DSPASTRIDE : DSPBSTRIDE, crtc_state->saveDSPSTRIDE);
1133
1134 REG_WRITE(pipeA ? DSPASIZE : DSPBSIZE, crtc_state->saveDSPSIZE);
1135 REG_WRITE(pipeA ? DSPAPOS : DSPBPOS, crtc_state->saveDSPPOS);
1136
1137 REG_WRITE(pipeA ? PIPEASRC : PIPEBSRC, crtc_state->savePIPESRC);
1138 REG_WRITE(pipeA ? DSPABASE : DSPBBASE, crtc_state->saveDSPBASE);
1139 REG_WRITE(pipeA ? PIPEACONF : PIPEBCONF, crtc_state->savePIPECONF);
1140
1141 cdv_intel_wait_for_vblank(dev);
1142
1143 REG_WRITE(pipeA ? DSPACNTR : DSPBCNTR, crtc_state->saveDSPCNTR);
1144 REG_WRITE(pipeA ? DSPABASE : DSPBBASE, crtc_state->saveDSPBASE);
1145
1146 cdv_intel_wait_for_vblank(dev);
1147
1148 paletteReg = pipeA ? PALETTE_A : PALETTE_B;
1149 for (i = 0; i < 256; ++i)
1150 REG_WRITE(paletteReg + (i << 2), crtc_state->savePalette[i]);
1151}
1152
1153static int cdv_intel_crtc_cursor_set(struct drm_crtc *crtc,
1154 struct drm_file *file_priv,
1155 uint32_t handle,
1156 uint32_t width, uint32_t height)
1157{
1158 struct drm_device *dev = crtc->dev;
1159 struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
1160 int pipe = psb_intel_crtc->pipe;
1161 uint32_t control = (pipe == 0) ? CURACNTR : CURBCNTR;
1162 uint32_t base = (pipe == 0) ? CURABASE : CURBBASE;
1163 uint32_t temp;
1164 size_t addr = 0;
1165 struct gtt_range *gt;
1166 struct drm_gem_object *obj;
1167 int ret;
1168
1169 /* if we want to turn of the cursor ignore width and height */
1170 if (!handle) {
1171 /* turn off the cursor */
1172 temp = CURSOR_MODE_DISABLE;
1173
1174 if (gma_power_begin(dev, false)) {
1175 REG_WRITE(control, temp);
1176 REG_WRITE(base, 0);
1177 gma_power_end(dev);
1178 }
1179
1180 /* unpin the old GEM object */
1181 if (psb_intel_crtc->cursor_obj) {
1182 gt = container_of(psb_intel_crtc->cursor_obj,
1183 struct gtt_range, gem);
1184 psb_gtt_unpin(gt);
1185 drm_gem_object_unreference(psb_intel_crtc->cursor_obj);
1186 psb_intel_crtc->cursor_obj = NULL;
1187 }
1188
1189 return 0;
1190 }
1191
1192 /* Currently we only support 64x64 cursors */
1193 if (width != 64 || height != 64) {
1194 dev_dbg(dev->dev, "we currently only support 64x64 cursors\n");
1195 return -EINVAL;
1196 }
1197
1198 obj = drm_gem_object_lookup(dev, file_priv, handle);
1199 if (!obj)
1200 return -ENOENT;
1201
1202 if (obj->size < width * height * 4) {
1203 dev_dbg(dev->dev, "buffer is to small\n");
1204 return -ENOMEM;
1205 }
1206
1207 gt = container_of(obj, struct gtt_range, gem);
1208
1209 /* Pin the memory into the GTT */
1210 ret = psb_gtt_pin(gt);
1211 if (ret) {
1212 dev_err(dev->dev, "Can not pin down handle 0x%x\n", handle);
1213 return ret;
1214 }
1215
1216 addr = gt->offset; /* Or resource.start ??? */
1217
1218 psb_intel_crtc->cursor_addr = addr;
1219
1220 temp = 0;
1221 /* set the pipe for the cursor */
1222 temp |= (pipe << 28);
1223 temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
1224
1225 if (gma_power_begin(dev, false)) {
1226 REG_WRITE(control, temp);
1227 REG_WRITE(base, addr);
1228 gma_power_end(dev);
1229 }
1230
1231 /* unpin the old GEM object */
1232 if (psb_intel_crtc->cursor_obj) {
1233 gt = container_of(psb_intel_crtc->cursor_obj,
1234 struct gtt_range, gem);
1235 psb_gtt_unpin(gt);
1236 drm_gem_object_unreference(psb_intel_crtc->cursor_obj);
1237 psb_intel_crtc->cursor_obj = obj;
1238 }
1239 return 0;
1240}
1241
1242static int cdv_intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
1243{
1244 struct drm_device *dev = crtc->dev;
1245 struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
1246 int pipe = psb_intel_crtc->pipe;
1247 uint32_t temp = 0;
1248 uint32_t adder;
1249
1250
1251 if (x < 0) {
1252 temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT);
1253 x = -x;
1254 }
1255 if (y < 0) {
1256 temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT);
1257 y = -y;
1258 }
1259
1260 temp |= ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT);
1261 temp |= ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT);
1262
1263 adder = psb_intel_crtc->cursor_addr;
1264
1265 if (gma_power_begin(dev, false)) {
1266 REG_WRITE((pipe == 0) ? CURAPOS : CURBPOS, temp);
1267 REG_WRITE((pipe == 0) ? CURABASE : CURBBASE, adder);
1268 gma_power_end(dev);
1269 }
1270 return 0;
1271}
1272
1273static void cdv_intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red,
1274 u16 *green, u16 *blue, uint32_t start, uint32_t size)
1275{
1276 struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
1277 int i;
1278 int end = (start + size > 256) ? 256 : start + size;
1279
1280 for (i = start; i < end; i++) {
1281 psb_intel_crtc->lut_r[i] = red[i] >> 8;
1282 psb_intel_crtc->lut_g[i] = green[i] >> 8;
1283 psb_intel_crtc->lut_b[i] = blue[i] >> 8;
1284 }
1285
1286 cdv_intel_crtc_load_lut(crtc);
1287}
1288
1289static int cdv_crtc_set_config(struct drm_mode_set *set)
1290{
1291 int ret = 0;
1292 struct drm_device *dev = set->crtc->dev;
1293 struct drm_psb_private *dev_priv = dev->dev_private;
1294
1295 if (!dev_priv->rpm_enabled)
1296 return drm_crtc_helper_set_config(set);
1297
1298 pm_runtime_forbid(&dev->pdev->dev);
1299
1300 ret = drm_crtc_helper_set_config(set);
1301
1302 pm_runtime_allow(&dev->pdev->dev);
1303
1304 return ret;
1305}
1306
1307/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */
1308
1309/* FIXME: why are we using this, should it be cdv_ in this tree ? */
1310
1311static void i8xx_clock(int refclk, struct cdv_intel_clock_t *clock)
1312{
1313 clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2);
1314 clock->p = clock->p1 * clock->p2;
1315 clock->vco = refclk * clock->m / (clock->n + 2);
1316 clock->dot = clock->vco / clock->p;
1317}
1318
1319/* Returns the clock of the currently programmed mode of the given pipe. */
1320static int cdv_intel_crtc_clock_get(struct drm_device *dev,
1321 struct drm_crtc *crtc)
1322{
1323 struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
1324 int pipe = psb_intel_crtc->pipe;
1325 u32 dpll;
1326 u32 fp;
1327 struct cdv_intel_clock_t clock;
1328 bool is_lvds;
1329 struct drm_psb_private *dev_priv = dev->dev_private;
1330
1331 if (gma_power_begin(dev, false)) {
1332 dpll = REG_READ((pipe == 0) ? DPLL_A : DPLL_B);
1333 if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0)
1334 fp = REG_READ((pipe == 0) ? FPA0 : FPB0);
1335 else
1336 fp = REG_READ((pipe == 0) ? FPA1 : FPB1);
1337 is_lvds = (pipe == 1) && (REG_READ(LVDS) & LVDS_PORT_EN);
1338 gma_power_end(dev);
1339 } else {
1340 dpll = (pipe == 0) ?
1341 dev_priv->saveDPLL_A : dev_priv->saveDPLL_B;
1342
1343 if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0)
1344 fp = (pipe == 0) ?
1345 dev_priv->saveFPA0 :
1346 dev_priv->saveFPB0;
1347 else
1348 fp = (pipe == 0) ?
1349 dev_priv->saveFPA1 :
1350 dev_priv->saveFPB1;
1351
1352 is_lvds = (pipe == 1) && (dev_priv->saveLVDS & LVDS_PORT_EN);
1353 }
1354
1355 clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT;
1356 clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT;
1357 clock.n = (fp & FP_N_DIV_MASK) >> FP_N_DIV_SHIFT;
1358
1359 if (is_lvds) {
1360 clock.p1 =
1361 ffs((dpll &
1362 DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS) >>
1363 DPLL_FPA01_P1_POST_DIV_SHIFT);
1364 if (clock.p1 == 0) {
1365 clock.p1 = 4;
1366 dev_err(dev->dev, "PLL %d\n", dpll);
1367 }
1368 clock.p2 = 14;
1369
1370 if ((dpll & PLL_REF_INPUT_MASK) ==
1371 PLLB_REF_INPUT_SPREADSPECTRUMIN) {
1372 /* XXX: might not be 66MHz */
1373 i8xx_clock(66000, &clock);
1374 } else
1375 i8xx_clock(48000, &clock);
1376 } else {
1377 if (dpll & PLL_P1_DIVIDE_BY_TWO)
1378 clock.p1 = 2;
1379 else {
1380 clock.p1 =
1381 ((dpll &
1382 DPLL_FPA01_P1_POST_DIV_MASK_I830) >>
1383 DPLL_FPA01_P1_POST_DIV_SHIFT) + 2;
1384 }
1385 if (dpll & PLL_P2_DIVIDE_BY_4)
1386 clock.p2 = 4;
1387 else
1388 clock.p2 = 2;
1389
1390 i8xx_clock(48000, &clock);
1391 }
1392
1393 /* XXX: It would be nice to validate the clocks, but we can't reuse
1394 * i830PllIsValid() because it relies on the xf86_config connector
1395 * configuration being accurate, which it isn't necessarily.
1396 */
1397
1398 return clock.dot;
1399}
1400
1401/** Returns the currently programmed mode of the given pipe. */
1402struct drm_display_mode *cdv_intel_crtc_mode_get(struct drm_device *dev,
1403 struct drm_crtc *crtc)
1404{
1405 struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
1406 int pipe = psb_intel_crtc->pipe;
1407 struct drm_display_mode *mode;
1408 int htot;
1409 int hsync;
1410 int vtot;
1411 int vsync;
1412 struct drm_psb_private *dev_priv = dev->dev_private;
1413
1414 if (gma_power_begin(dev, false)) {
1415 htot = REG_READ((pipe == 0) ? HTOTAL_A : HTOTAL_B);
1416 hsync = REG_READ((pipe == 0) ? HSYNC_A : HSYNC_B);
1417 vtot = REG_READ((pipe == 0) ? VTOTAL_A : VTOTAL_B);
1418 vsync = REG_READ((pipe == 0) ? VSYNC_A : VSYNC_B);
1419 gma_power_end(dev);
1420 } else {
1421 htot = (pipe == 0) ?
1422 dev_priv->saveHTOTAL_A : dev_priv->saveHTOTAL_B;
1423 hsync = (pipe == 0) ?
1424 dev_priv->saveHSYNC_A : dev_priv->saveHSYNC_B;
1425 vtot = (pipe == 0) ?
1426 dev_priv->saveVTOTAL_A : dev_priv->saveVTOTAL_B;
1427 vsync = (pipe == 0) ?
1428 dev_priv->saveVSYNC_A : dev_priv->saveVSYNC_B;
1429 }
1430
1431 mode = kzalloc(sizeof(*mode), GFP_KERNEL);
1432 if (!mode)
1433 return NULL;
1434
1435 mode->clock = cdv_intel_crtc_clock_get(dev, crtc);
1436 mode->hdisplay = (htot & 0xffff) + 1;
1437 mode->htotal = ((htot & 0xffff0000) >> 16) + 1;
1438 mode->hsync_start = (hsync & 0xffff) + 1;
1439 mode->hsync_end = ((hsync & 0xffff0000) >> 16) + 1;
1440 mode->vdisplay = (vtot & 0xffff) + 1;
1441 mode->vtotal = ((vtot & 0xffff0000) >> 16) + 1;
1442 mode->vsync_start = (vsync & 0xffff) + 1;
1443 mode->vsync_end = ((vsync & 0xffff0000) >> 16) + 1;
1444
1445 drm_mode_set_name(mode);
1446 drm_mode_set_crtcinfo(mode, 0);
1447
1448 return mode;
1449}
1450
1451static void cdv_intel_crtc_destroy(struct drm_crtc *crtc)
1452{
1453 struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
1454
1455 kfree(psb_intel_crtc->crtc_state);
1456 drm_crtc_cleanup(crtc);
1457 kfree(psb_intel_crtc);
1458}
1459
1460const struct drm_crtc_helper_funcs cdv_intel_helper_funcs = {
1461 .dpms = cdv_intel_crtc_dpms,
1462 .mode_fixup = cdv_intel_crtc_mode_fixup,
1463 .mode_set = cdv_intel_crtc_mode_set,
1464 .mode_set_base = cdv_intel_pipe_set_base,
1465 .prepare = cdv_intel_crtc_prepare,
1466 .commit = cdv_intel_crtc_commit,
1467};
1468
1469const struct drm_crtc_funcs cdv_intel_crtc_funcs = {
1470 .save = cdv_intel_crtc_save,
1471 .restore = cdv_intel_crtc_restore,
1472 .cursor_set = cdv_intel_crtc_cursor_set,
1473 .cursor_move = cdv_intel_crtc_cursor_move,
1474 .gamma_set = cdv_intel_crtc_gamma_set,
1475 .set_config = cdv_crtc_set_config,
1476 .destroy = cdv_intel_crtc_destroy,
1477};
1478
1479/*
1480 * Set the default value of cursor control and base register
1481 * to zero. This is a workaround for h/w defect on oaktrail
1482 */
1483void cdv_intel_cursor_init(struct drm_device *dev, int pipe)
1484{
1485 uint32_t control;
1486 uint32_t base;
1487
1488 switch (pipe) {
1489 case 0:
1490 control = CURACNTR;
1491 base = CURABASE;
1492 break;
1493 case 1:
1494 control = CURBCNTR;
1495 base = CURBBASE;
1496 break;
1497 case 2:
1498 control = CURCCNTR;
1499 base = CURCBASE;
1500 break;
1501 default:
1502 return;
1503 }
1504
1505 REG_WRITE(control, 0);
1506 REG_WRITE(base, 0);
1507}
1508
diff --git a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c
new file mode 100644
index 000000000000..cbca2b0c7d58
--- /dev/null
+++ b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c
@@ -0,0 +1,376 @@
1/*
2 * Copyright © 2006-2011 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 *
23 * Authors:
24 * jim liu <jim.liu@intel.com>
25 *
26 * FIXME:
27 * We should probably make this generic and share it with Medfield
28 */
29
30#include <drm/drmP.h>
31#include <drm/drm.h>
32#include <drm/drm_crtc.h>
33#include <drm/drm_edid.h>
34#include "psb_intel_drv.h"
35#include "psb_drv.h"
36#include "psb_intel_reg.h"
37#include <linux/pm_runtime.h>
38
39/* hdmi control bits */
40#define HDMI_NULL_PACKETS_DURING_VSYNC (1 << 9)
41#define HDMI_BORDER_ENABLE (1 << 7)
42#define HDMI_AUDIO_ENABLE (1 << 6)
43#define HDMI_VSYNC_ACTIVE_HIGH (1 << 4)
44#define HDMI_HSYNC_ACTIVE_HIGH (1 << 3)
45/* hdmi-b control bits */
46#define HDMIB_PIPE_B_SELECT (1 << 30)
47
48
49struct mid_intel_hdmi_priv {
50 u32 hdmi_reg;
51 u32 save_HDMIB;
52 bool has_hdmi_sink;
53 bool has_hdmi_audio;
54 /* Should set this when detect hotplug */
55 bool hdmi_device_connected;
56 struct mdfld_hdmi_i2c *i2c_bus;
57 struct i2c_adapter *hdmi_i2c_adapter; /* for control functions */
58 struct drm_device *dev;
59};
60
61static void cdv_hdmi_mode_set(struct drm_encoder *encoder,
62 struct drm_display_mode *mode,
63 struct drm_display_mode *adjusted_mode)
64{
65 struct drm_device *dev = encoder->dev;
66 struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
67 struct mid_intel_hdmi_priv *hdmi_priv = output->dev_priv;
68 u32 hdmib;
69 struct drm_crtc *crtc = encoder->crtc;
70 struct psb_intel_crtc *intel_crtc = to_psb_intel_crtc(crtc);
71
72 hdmib = (2 << 10);
73
74 if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
75 hdmib |= HDMI_VSYNC_ACTIVE_HIGH;
76 if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
77 hdmib |= HDMI_HSYNC_ACTIVE_HIGH;
78
79 if (intel_crtc->pipe == 1)
80 hdmib |= HDMIB_PIPE_B_SELECT;
81
82 if (hdmi_priv->has_hdmi_audio) {
83 hdmib |= HDMI_AUDIO_ENABLE;
84 hdmib |= HDMI_NULL_PACKETS_DURING_VSYNC;
85 }
86
87 REG_WRITE(hdmi_priv->hdmi_reg, hdmib);
88 REG_READ(hdmi_priv->hdmi_reg);
89}
90
91static bool cdv_hdmi_mode_fixup(struct drm_encoder *encoder,
92 struct drm_display_mode *mode,
93 struct drm_display_mode *adjusted_mode)
94{
95 return true;
96}
97
98static void cdv_hdmi_dpms(struct drm_encoder *encoder, int mode)
99{
100 struct drm_device *dev = encoder->dev;
101 struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
102 struct mid_intel_hdmi_priv *hdmi_priv = output->dev_priv;
103 u32 hdmib;
104
105 hdmib = REG_READ(hdmi_priv->hdmi_reg);
106
107 if (mode != DRM_MODE_DPMS_ON)
108 REG_WRITE(hdmi_priv->hdmi_reg, hdmib & ~HDMIB_PORT_EN);
109 else
110 REG_WRITE(hdmi_priv->hdmi_reg, hdmib | HDMIB_PORT_EN);
111 REG_READ(hdmi_priv->hdmi_reg);
112}
113
114static void cdv_hdmi_save(struct drm_connector *connector)
115{
116 struct drm_device *dev = connector->dev;
117 struct psb_intel_output *output = to_psb_intel_output(connector);
118 struct mid_intel_hdmi_priv *hdmi_priv = output->dev_priv;
119
120 hdmi_priv->save_HDMIB = REG_READ(hdmi_priv->hdmi_reg);
121}
122
123static void cdv_hdmi_restore(struct drm_connector *connector)
124{
125 struct drm_device *dev = connector->dev;
126 struct psb_intel_output *output = to_psb_intel_output(connector);
127 struct mid_intel_hdmi_priv *hdmi_priv = output->dev_priv;
128
129 REG_WRITE(hdmi_priv->hdmi_reg, hdmi_priv->save_HDMIB);
130 REG_READ(hdmi_priv->hdmi_reg);
131}
132
133static enum drm_connector_status cdv_hdmi_detect(
134 struct drm_connector *connector, bool force)
135{
136 struct psb_intel_output *psb_intel_output =
137 to_psb_intel_output(connector);
138 struct mid_intel_hdmi_priv *hdmi_priv = psb_intel_output->dev_priv;
139 struct edid *edid = NULL;
140 enum drm_connector_status status = connector_status_disconnected;
141
142 edid = drm_get_edid(&psb_intel_output->base,
143 psb_intel_output->hdmi_i2c_adapter);
144
145 hdmi_priv->has_hdmi_sink = false;
146 hdmi_priv->has_hdmi_audio = false;
147 if (edid) {
148 if (edid->input & DRM_EDID_INPUT_DIGITAL) {
149 status = connector_status_connected;
150 hdmi_priv->has_hdmi_sink =
151 drm_detect_hdmi_monitor(edid);
152 hdmi_priv->has_hdmi_audio =
153 drm_detect_monitor_audio(edid);
154 }
155
156 psb_intel_output->base.display_info.raw_edid = NULL;
157 kfree(edid);
158 }
159 return status;
160}
161
162static int cdv_hdmi_set_property(struct drm_connector *connector,
163 struct drm_property *property,
164 uint64_t value)
165{
166 struct drm_encoder *encoder = connector->encoder;
167
168 if (!strcmp(property->name, "scaling mode") && encoder) {
169 struct psb_intel_crtc *crtc = to_psb_intel_crtc(encoder->crtc);
170 bool centre;
171 uint64_t curValue;
172
173 if (!crtc)
174 return -1;
175
176 switch (value) {
177 case DRM_MODE_SCALE_FULLSCREEN:
178 break;
179 case DRM_MODE_SCALE_NO_SCALE:
180 break;
181 case DRM_MODE_SCALE_ASPECT:
182 break;
183 default:
184 return -1;
185 }
186
187 if (drm_connector_property_get_value(connector,
188 property, &curValue))
189 return -1;
190
191 if (curValue == value)
192 return 0;
193
194 if (drm_connector_property_set_value(connector,
195 property, value))
196 return -1;
197
198 centre = (curValue == DRM_MODE_SCALE_NO_SCALE) ||
199 (value == DRM_MODE_SCALE_NO_SCALE);
200
201 if (crtc->saved_mode.hdisplay != 0 &&
202 crtc->saved_mode.vdisplay != 0) {
203 if (centre) {
204 if (!drm_crtc_helper_set_mode(encoder->crtc, &crtc->saved_mode,
205 encoder->crtc->x, encoder->crtc->y, encoder->crtc->fb))
206 return -1;
207 } else {
208 struct drm_encoder_helper_funcs *helpers
209 = encoder->helper_private;
210 helpers->mode_set(encoder, &crtc->saved_mode,
211 &crtc->saved_adjusted_mode);
212 }
213 }
214 }
215 return 0;
216}
217
218/*
219 * Return the list of HDMI DDC modes if available.
220 */
221static int cdv_hdmi_get_modes(struct drm_connector *connector)
222{
223 struct psb_intel_output *psb_intel_output =
224 to_psb_intel_output(connector);
225 struct edid *edid = NULL;
226 int ret = 0;
227
228 edid = drm_get_edid(&psb_intel_output->base,
229 psb_intel_output->hdmi_i2c_adapter);
230 if (edid) {
231 drm_mode_connector_update_edid_property(&psb_intel_output->
232 base, edid);
233 ret = drm_add_edid_modes(&psb_intel_output->base, edid);
234 kfree(edid);
235 }
236 return ret;
237}
238
239static int cdv_hdmi_mode_valid(struct drm_connector *connector,
240 struct drm_display_mode *mode)
241{
242
243 if (mode->clock > 165000)
244 return MODE_CLOCK_HIGH;
245 if (mode->clock < 20000)
246 return MODE_CLOCK_HIGH;
247
248 /* just in case */
249 if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
250 return MODE_NO_DBLESCAN;
251
252 /* just in case */
253 if (mode->flags & DRM_MODE_FLAG_INTERLACE)
254 return MODE_NO_INTERLACE;
255
256 /*
257 * FIXME: for now we limit the size to 1680x1050 on CDV, otherwise it
258 * will go beyond the stolen memory size allocated to the framebuffer
259 */
260 if (mode->hdisplay > 1680)
261 return MODE_PANEL;
262 if (mode->vdisplay > 1050)
263 return MODE_PANEL;
264 return MODE_OK;
265}
266
267static void cdv_hdmi_destroy(struct drm_connector *connector)
268{
269 struct psb_intel_output *psb_intel_output =
270 to_psb_intel_output(connector);
271
272 if (psb_intel_output->ddc_bus)
273 psb_intel_i2c_destroy(psb_intel_output->ddc_bus);
274 drm_sysfs_connector_remove(connector);
275 drm_connector_cleanup(connector);
276 kfree(connector);
277}
278
279static const struct drm_encoder_helper_funcs cdv_hdmi_helper_funcs = {
280 .dpms = cdv_hdmi_dpms,
281 .mode_fixup = cdv_hdmi_mode_fixup,
282 .prepare = psb_intel_encoder_prepare,
283 .mode_set = cdv_hdmi_mode_set,
284 .commit = psb_intel_encoder_commit,
285};
286
287static const struct drm_connector_helper_funcs
288 cdv_hdmi_connector_helper_funcs = {
289 .get_modes = cdv_hdmi_get_modes,
290 .mode_valid = cdv_hdmi_mode_valid,
291 .best_encoder = psb_intel_best_encoder,
292};
293
294static const struct drm_connector_funcs cdv_hdmi_connector_funcs = {
295 .dpms = drm_helper_connector_dpms,
296 .save = cdv_hdmi_save,
297 .restore = cdv_hdmi_restore,
298 .detect = cdv_hdmi_detect,
299 .fill_modes = drm_helper_probe_single_connector_modes,
300 .set_property = cdv_hdmi_set_property,
301 .destroy = cdv_hdmi_destroy,
302};
303
304void cdv_hdmi_init(struct drm_device *dev,
305 struct psb_intel_mode_device *mode_dev, int reg)
306{
307 struct psb_intel_output *psb_intel_output;
308 struct drm_connector *connector;
309 struct drm_encoder *encoder;
310 struct mid_intel_hdmi_priv *hdmi_priv;
311 int ddc_bus;
312
313 psb_intel_output = kzalloc(sizeof(struct psb_intel_output) +
314 sizeof(struct mid_intel_hdmi_priv), GFP_KERNEL);
315 if (!psb_intel_output)
316 return;
317
318 hdmi_priv = (struct mid_intel_hdmi_priv *)(psb_intel_output + 1);
319 psb_intel_output->mode_dev = mode_dev;
320 connector = &psb_intel_output->base;
321 encoder = &psb_intel_output->enc;
322 drm_connector_init(dev, &psb_intel_output->base,
323 &cdv_hdmi_connector_funcs,
324 DRM_MODE_CONNECTOR_DVID);
325
326 drm_encoder_init(dev, &psb_intel_output->enc, &psb_intel_lvds_enc_funcs,
327 DRM_MODE_ENCODER_TMDS);
328
329 drm_mode_connector_attach_encoder(&psb_intel_output->base,
330 &psb_intel_output->enc);
331 psb_intel_output->type = INTEL_OUTPUT_HDMI;
332 hdmi_priv->hdmi_reg = reg;
333 hdmi_priv->has_hdmi_sink = false;
334 psb_intel_output->dev_priv = hdmi_priv;
335
336 drm_encoder_helper_add(encoder, &cdv_hdmi_helper_funcs);
337 drm_connector_helper_add(connector,
338 &cdv_hdmi_connector_helper_funcs);
339 connector->display_info.subpixel_order = SubPixelHorizontalRGB;
340 connector->interlace_allowed = false;
341 connector->doublescan_allowed = false;
342
343 drm_connector_attach_property(connector,
344 dev->mode_config.scaling_mode_property, DRM_MODE_SCALE_FULLSCREEN);
345
346 switch (reg) {
347 case SDVOB:
348 ddc_bus = GPIOE;
349 break;
350 case SDVOC:
351 ddc_bus = GPIOD;
352 break;
353 default:
354 DRM_ERROR("unknown reg 0x%x for HDMI\n", reg);
355 goto failed_ddc;
356 break;
357 }
358
359 psb_intel_output->ddc_bus = psb_intel_i2c_create(dev,
360 ddc_bus, (reg == SDVOB) ? "HDMIB" : "HDMIC");
361
362 if (!psb_intel_output->ddc_bus) {
363 dev_err(dev->dev, "No ddc adapter available!\n");
364 goto failed_ddc;
365 }
366 psb_intel_output->hdmi_i2c_adapter =
367 &(psb_intel_output->ddc_bus->adapter);
368 hdmi_priv->dev = dev;
369 drm_sysfs_connector_add(connector);
370 return;
371
372failed_ddc:
373 drm_encoder_cleanup(&psb_intel_output->enc);
374 drm_connector_cleanup(&psb_intel_output->base);
375 kfree(psb_intel_output);
376}
diff --git a/drivers/gpu/drm/gma500/cdv_intel_lvds.c b/drivers/gpu/drm/gma500/cdv_intel_lvds.c
new file mode 100644
index 000000000000..988b2d0acf43
--- /dev/null
+++ b/drivers/gpu/drm/gma500/cdv_intel_lvds.c
@@ -0,0 +1,721 @@
1/*
2 * Copyright © 2006-2011 Intel Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
16 *
17 * Authors:
18 * Eric Anholt <eric@anholt.net>
19 * Dave Airlie <airlied@linux.ie>
20 * Jesse Barnes <jesse.barnes@intel.com>
21 */
22
23#include <linux/i2c.h>
24#include <linux/dmi.h>
25#include <drm/drmP.h>
26
27#include "intel_bios.h"
28#include "psb_drv.h"
29#include "psb_intel_drv.h"
30#include "psb_intel_reg.h"
31#include "power.h"
32#include <linux/pm_runtime.h>
33#include "cdv_device.h"
34
35/**
36 * LVDS I2C backlight control macros
37 */
38#define BRIGHTNESS_MAX_LEVEL 100
39#define BRIGHTNESS_MASK 0xFF
40#define BLC_I2C_TYPE 0x01
41#define BLC_PWM_TYPT 0x02
42
43#define BLC_POLARITY_NORMAL 0
44#define BLC_POLARITY_INVERSE 1
45
46#define PSB_BLC_MAX_PWM_REG_FREQ (0xFFFE)
47#define PSB_BLC_MIN_PWM_REG_FREQ (0x2)
48#define PSB_BLC_PWM_PRECISION_FACTOR (10)
49#define PSB_BACKLIGHT_PWM_CTL_SHIFT (16)
50#define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE)
51
52struct cdv_intel_lvds_priv {
53 /**
54 * Saved LVDO output states
55 */
56 uint32_t savePP_ON;
57 uint32_t savePP_OFF;
58 uint32_t saveLVDS;
59 uint32_t savePP_CONTROL;
60 uint32_t savePP_CYCLE;
61 uint32_t savePFIT_CONTROL;
62 uint32_t savePFIT_PGM_RATIOS;
63 uint32_t saveBLC_PWM_CTL;
64};
65
66/*
67 * Returns the maximum level of the backlight duty cycle field.
68 */
69static u32 cdv_intel_lvds_get_max_backlight(struct drm_device *dev)
70{
71 struct drm_psb_private *dev_priv = dev->dev_private;
72 u32 retval;
73
74 if (gma_power_begin(dev, false)) {
75 retval = ((REG_READ(BLC_PWM_CTL) &
76 BACKLIGHT_MODULATION_FREQ_MASK) >>
77 BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
78
79 gma_power_end(dev);
80 } else
81 retval = ((dev_priv->saveBLC_PWM_CTL &
82 BACKLIGHT_MODULATION_FREQ_MASK) >>
83 BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
84
85 return retval;
86}
87
88/*
89 * Set LVDS backlight level by I2C command
90 */
91static int cdv_lvds_i2c_set_brightness(struct drm_device *dev,
92 unsigned int level)
93{
94 struct drm_psb_private *dev_priv = dev->dev_private;
95 struct psb_intel_i2c_chan *lvds_i2c_bus = dev_priv->lvds_i2c_bus;
96 u8 out_buf[2];
97 unsigned int blc_i2c_brightness;
98
99 struct i2c_msg msgs[] = {
100 {
101 .addr = lvds_i2c_bus->slave_addr,
102 .flags = 0,
103 .len = 2,
104 .buf = out_buf,
105 }
106 };
107
108 blc_i2c_brightness = BRIGHTNESS_MASK & ((unsigned int)level *
109 BRIGHTNESS_MASK /
110 BRIGHTNESS_MAX_LEVEL);
111
112 if (dev_priv->lvds_bl->pol == BLC_POLARITY_INVERSE)
113 blc_i2c_brightness = BRIGHTNESS_MASK - blc_i2c_brightness;
114
115 out_buf[0] = dev_priv->lvds_bl->brightnesscmd;
116 out_buf[1] = (u8)blc_i2c_brightness;
117
118 if (i2c_transfer(&lvds_i2c_bus->adapter, msgs, 1) == 1)
119 return 0;
120
121 DRM_ERROR("I2C transfer error\n");
122 return -1;
123}
124
125
126static int cdv_lvds_pwm_set_brightness(struct drm_device *dev, int level)
127{
128 struct drm_psb_private *dev_priv = dev->dev_private;
129
130 u32 max_pwm_blc;
131 u32 blc_pwm_duty_cycle;
132
133 max_pwm_blc = cdv_intel_lvds_get_max_backlight(dev);
134
135 /*BLC_PWM_CTL Should be initiated while backlight device init*/
136 BUG_ON((max_pwm_blc & PSB_BLC_MAX_PWM_REG_FREQ) == 0);
137
138 blc_pwm_duty_cycle = level * max_pwm_blc / BRIGHTNESS_MAX_LEVEL;
139
140 if (dev_priv->lvds_bl->pol == BLC_POLARITY_INVERSE)
141 blc_pwm_duty_cycle = max_pwm_blc - blc_pwm_duty_cycle;
142
143 blc_pwm_duty_cycle &= PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR;
144 REG_WRITE(BLC_PWM_CTL,
145 (max_pwm_blc << PSB_BACKLIGHT_PWM_CTL_SHIFT) |
146 (blc_pwm_duty_cycle));
147
148 return 0;
149}
150
151/*
152 * Set LVDS backlight level either by I2C or PWM
153 */
154void cdv_intel_lvds_set_brightness(struct drm_device *dev, int level)
155{
156 struct drm_psb_private *dev_priv = dev->dev_private;
157
158 if (!dev_priv->lvds_bl) {
159 DRM_ERROR("NO LVDS Backlight Info\n");
160 return;
161 }
162
163 if (dev_priv->lvds_bl->type == BLC_I2C_TYPE)
164 cdv_lvds_i2c_set_brightness(dev, level);
165 else
166 cdv_lvds_pwm_set_brightness(dev, level);
167}
168
169/**
170 * Sets the backlight level.
171 *
172 * level backlight level, from 0 to cdv_intel_lvds_get_max_backlight().
173 */
174static void cdv_intel_lvds_set_backlight(struct drm_device *dev, int level)
175{
176 struct drm_psb_private *dev_priv = dev->dev_private;
177 u32 blc_pwm_ctl;
178
179 if (gma_power_begin(dev, false)) {
180 blc_pwm_ctl =
181 REG_READ(BLC_PWM_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK;
182 REG_WRITE(BLC_PWM_CTL,
183 (blc_pwm_ctl |
184 (level << BACKLIGHT_DUTY_CYCLE_SHIFT)));
185 gma_power_end(dev);
186 } else {
187 blc_pwm_ctl = dev_priv->saveBLC_PWM_CTL &
188 ~BACKLIGHT_DUTY_CYCLE_MASK;
189 dev_priv->saveBLC_PWM_CTL = (blc_pwm_ctl |
190 (level << BACKLIGHT_DUTY_CYCLE_SHIFT));
191 }
192}
193
194/**
195 * Sets the power state for the panel.
196 */
197static void cdv_intel_lvds_set_power(struct drm_device *dev,
198 struct psb_intel_output *output, bool on)
199{
200 u32 pp_status;
201
202 if (!gma_power_begin(dev, true))
203 return;
204
205 if (on) {
206 REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) |
207 POWER_TARGET_ON);
208 do {
209 pp_status = REG_READ(PP_STATUS);
210 } while ((pp_status & PP_ON) == 0);
211
212 cdv_intel_lvds_set_backlight(dev,
213 output->
214 mode_dev->backlight_duty_cycle);
215 } else {
216 cdv_intel_lvds_set_backlight(dev, 0);
217
218 REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) &
219 ~POWER_TARGET_ON);
220 do {
221 pp_status = REG_READ(PP_STATUS);
222 } while (pp_status & PP_ON);
223 }
224 gma_power_end(dev);
225}
226
227static void cdv_intel_lvds_encoder_dpms(struct drm_encoder *encoder, int mode)
228{
229 struct drm_device *dev = encoder->dev;
230 struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
231 if (mode == DRM_MODE_DPMS_ON)
232 cdv_intel_lvds_set_power(dev, output, true);
233 else
234 cdv_intel_lvds_set_power(dev, output, false);
235 /* XXX: We never power down the LVDS pairs. */
236}
237
238static void cdv_intel_lvds_save(struct drm_connector *connector)
239{
240}
241
242static void cdv_intel_lvds_restore(struct drm_connector *connector)
243{
244}
245
246int cdv_intel_lvds_mode_valid(struct drm_connector *connector,
247 struct drm_display_mode *mode)
248{
249 struct psb_intel_output *psb_intel_output =
250 to_psb_intel_output(connector);
251 struct drm_display_mode *fixed_mode =
252 psb_intel_output->mode_dev->panel_fixed_mode;
253
254 /* just in case */
255 if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
256 return MODE_NO_DBLESCAN;
257
258 /* just in case */
259 if (mode->flags & DRM_MODE_FLAG_INTERLACE)
260 return MODE_NO_INTERLACE;
261
262 if (fixed_mode) {
263 if (mode->hdisplay > fixed_mode->hdisplay)
264 return MODE_PANEL;
265 if (mode->vdisplay > fixed_mode->vdisplay)
266 return MODE_PANEL;
267 }
268 return MODE_OK;
269}
270
271bool cdv_intel_lvds_mode_fixup(struct drm_encoder *encoder,
272 struct drm_display_mode *mode,
273 struct drm_display_mode *adjusted_mode)
274{
275 struct psb_intel_mode_device *mode_dev =
276 enc_to_psb_intel_output(encoder)->mode_dev;
277 struct drm_device *dev = encoder->dev;
278 struct drm_encoder *tmp_encoder;
279 struct drm_display_mode *panel_fixed_mode = mode_dev->panel_fixed_mode;
280
281 /* Should never happen!! */
282 list_for_each_entry(tmp_encoder, &dev->mode_config.encoder_list,
283 head) {
284 if (tmp_encoder != encoder
285 && tmp_encoder->crtc == encoder->crtc) {
286 printk(KERN_ERR "Can't enable LVDS and another "
287 "encoder on the same pipe\n");
288 return false;
289 }
290 }
291
292 /*
293 * If we have timings from the BIOS for the panel, put them in
294 * to the adjusted mode. The CRTC will be set up for this mode,
295 * with the panel scaling set up to source from the H/VDisplay
296 * of the original mode.
297 */
298 if (panel_fixed_mode != NULL) {
299 adjusted_mode->hdisplay = panel_fixed_mode->hdisplay;
300 adjusted_mode->hsync_start = panel_fixed_mode->hsync_start;
301 adjusted_mode->hsync_end = panel_fixed_mode->hsync_end;
302 adjusted_mode->htotal = panel_fixed_mode->htotal;
303 adjusted_mode->vdisplay = panel_fixed_mode->vdisplay;
304 adjusted_mode->vsync_start = panel_fixed_mode->vsync_start;
305 adjusted_mode->vsync_end = panel_fixed_mode->vsync_end;
306 adjusted_mode->vtotal = panel_fixed_mode->vtotal;
307 adjusted_mode->clock = panel_fixed_mode->clock;
308 drm_mode_set_crtcinfo(adjusted_mode,
309 CRTC_INTERLACE_HALVE_V);
310 }
311
312 /*
313 * XXX: It would be nice to support lower refresh rates on the
314 * panels to reduce power consumption, and perhaps match the
315 * user's requested refresh rate.
316 */
317
318 return true;
319}
320
321static void cdv_intel_lvds_prepare(struct drm_encoder *encoder)
322{
323 struct drm_device *dev = encoder->dev;
324 struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
325 struct psb_intel_mode_device *mode_dev = output->mode_dev;
326
327 if (!gma_power_begin(dev, true))
328 return;
329
330 mode_dev->saveBLC_PWM_CTL = REG_READ(BLC_PWM_CTL);
331 mode_dev->backlight_duty_cycle = (mode_dev->saveBLC_PWM_CTL &
332 BACKLIGHT_DUTY_CYCLE_MASK);
333
334 cdv_intel_lvds_set_power(dev, output, false);
335
336 gma_power_end(dev);
337}
338
339static void cdv_intel_lvds_commit(struct drm_encoder *encoder)
340{
341 struct drm_device *dev = encoder->dev;
342 struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
343 struct psb_intel_mode_device *mode_dev = output->mode_dev;
344
345 if (mode_dev->backlight_duty_cycle == 0)
346 mode_dev->backlight_duty_cycle =
347 cdv_intel_lvds_get_max_backlight(dev);
348
349 cdv_intel_lvds_set_power(dev, output, true);
350}
351
352static void cdv_intel_lvds_mode_set(struct drm_encoder *encoder,
353 struct drm_display_mode *mode,
354 struct drm_display_mode *adjusted_mode)
355{
356 struct drm_device *dev = encoder->dev;
357 struct drm_psb_private *dev_priv = dev->dev_private;
358 u32 pfit_control;
359
360 /*
361 * The LVDS pin pair will already have been turned on in the
362 * cdv_intel_crtc_mode_set since it has a large impact on the DPLL
363 * settings.
364 */
365
366 /*
367 * Enable automatic panel scaling so that non-native modes fill the
368 * screen. Should be enabled before the pipe is enabled, according to
369 * register description and PRM.
370 */
371 if (mode->hdisplay != adjusted_mode->hdisplay ||
372 mode->vdisplay != adjusted_mode->vdisplay)
373 pfit_control = (PFIT_ENABLE | VERT_AUTO_SCALE |
374 HORIZ_AUTO_SCALE | VERT_INTERP_BILINEAR |
375 HORIZ_INTERP_BILINEAR);
376 else
377 pfit_control = 0;
378
379 if (dev_priv->lvds_dither)
380 pfit_control |= PANEL_8TO6_DITHER_ENABLE;
381
382 REG_WRITE(PFIT_CONTROL, pfit_control);
383}
384
385/**
386 * Detect the LVDS connection.
387 *
388 * This always returns CONNECTOR_STATUS_CONNECTED.
389 * This connector should only have
390 * been set up if the LVDS was actually connected anyway.
391 */
392static enum drm_connector_status cdv_intel_lvds_detect(
393 struct drm_connector *connector, bool force)
394{
395 return connector_status_connected;
396}
397
398/**
399 * Return the list of DDC modes if available, or the BIOS fixed mode otherwise.
400 */
401static int cdv_intel_lvds_get_modes(struct drm_connector *connector)
402{
403 struct drm_device *dev = connector->dev;
404 struct psb_intel_output *psb_intel_output =
405 to_psb_intel_output(connector);
406 struct psb_intel_mode_device *mode_dev =
407 psb_intel_output->mode_dev;
408 int ret;
409
410 ret = psb_intel_ddc_get_modes(psb_intel_output);
411
412 if (ret)
413 return ret;
414
415 /* Didn't get an EDID, so
416 * Set wide sync ranges so we get all modes
417 * handed to valid_mode for checking
418 */
419 connector->display_info.min_vfreq = 0;
420 connector->display_info.max_vfreq = 200;
421 connector->display_info.min_hfreq = 0;
422 connector->display_info.max_hfreq = 200;
423 if (mode_dev->panel_fixed_mode != NULL) {
424 struct drm_display_mode *mode =
425 drm_mode_duplicate(dev, mode_dev->panel_fixed_mode);
426 drm_mode_probed_add(connector, mode);
427 return 1;
428 }
429
430 return 0;
431}
432
433/**
434 * cdv_intel_lvds_destroy - unregister and free LVDS structures
435 * @connector: connector to free
436 *
437 * Unregister the DDC bus for this connector then free the driver private
438 * structure.
439 */
440void cdv_intel_lvds_destroy(struct drm_connector *connector)
441{
442 struct psb_intel_output *psb_intel_output =
443 to_psb_intel_output(connector);
444
445 if (psb_intel_output->ddc_bus)
446 psb_intel_i2c_destroy(psb_intel_output->ddc_bus);
447 drm_sysfs_connector_remove(connector);
448 drm_connector_cleanup(connector);
449 kfree(connector);
450}
451
452int cdv_intel_lvds_set_property(struct drm_connector *connector,
453 struct drm_property *property,
454 uint64_t value)
455{
456 struct drm_encoder *encoder = connector->encoder;
457
458 if (!strcmp(property->name, "scaling mode") && encoder) {
459 struct psb_intel_crtc *crtc =
460 to_psb_intel_crtc(encoder->crtc);
461 uint64_t curValue;
462
463 if (!crtc)
464 return -1;
465
466 switch (value) {
467 case DRM_MODE_SCALE_FULLSCREEN:
468 break;
469 case DRM_MODE_SCALE_NO_SCALE:
470 break;
471 case DRM_MODE_SCALE_ASPECT:
472 break;
473 default:
474 return -1;
475 }
476
477 if (drm_connector_property_get_value(connector,
478 property,
479 &curValue))
480 return -1;
481
482 if (curValue == value)
483 return 0;
484
485 if (drm_connector_property_set_value(connector,
486 property,
487 value))
488 return -1;
489
490 if (crtc->saved_mode.hdisplay != 0 &&
491 crtc->saved_mode.vdisplay != 0) {
492 if (!drm_crtc_helper_set_mode(encoder->crtc,
493 &crtc->saved_mode,
494 encoder->crtc->x,
495 encoder->crtc->y,
496 encoder->crtc->fb))
497 return -1;
498 }
499 } else if (!strcmp(property->name, "backlight") && encoder) {
500 if (drm_connector_property_set_value(connector,
501 property,
502 value))
503 return -1;
504 else {
505#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
506 struct drm_psb_private *dev_priv =
507 encoder->dev->dev_private;
508 struct backlight_device *bd =
509 dev_priv->backlight_device;
510 bd->props.brightness = value;
511 backlight_update_status(bd);
512#endif
513 }
514 } else if (!strcmp(property->name, "DPMS") && encoder) {
515 struct drm_encoder_helper_funcs *helpers =
516 encoder->helper_private;
517 helpers->dpms(encoder, value);
518 }
519 return 0;
520}
521
522static const struct drm_encoder_helper_funcs
523 cdv_intel_lvds_helper_funcs = {
524 .dpms = cdv_intel_lvds_encoder_dpms,
525 .mode_fixup = cdv_intel_lvds_mode_fixup,
526 .prepare = cdv_intel_lvds_prepare,
527 .mode_set = cdv_intel_lvds_mode_set,
528 .commit = cdv_intel_lvds_commit,
529};
530
531static const struct drm_connector_helper_funcs
532 cdv_intel_lvds_connector_helper_funcs = {
533 .get_modes = cdv_intel_lvds_get_modes,
534 .mode_valid = cdv_intel_lvds_mode_valid,
535 .best_encoder = psb_intel_best_encoder,
536};
537
538static const struct drm_connector_funcs cdv_intel_lvds_connector_funcs = {
539 .dpms = drm_helper_connector_dpms,
540 .save = cdv_intel_lvds_save,
541 .restore = cdv_intel_lvds_restore,
542 .detect = cdv_intel_lvds_detect,
543 .fill_modes = drm_helper_probe_single_connector_modes,
544 .set_property = cdv_intel_lvds_set_property,
545 .destroy = cdv_intel_lvds_destroy,
546};
547
548
549static void cdv_intel_lvds_enc_destroy(struct drm_encoder *encoder)
550{
551 drm_encoder_cleanup(encoder);
552}
553
554const struct drm_encoder_funcs cdv_intel_lvds_enc_funcs = {
555 .destroy = cdv_intel_lvds_enc_destroy,
556};
557
558/**
559 * cdv_intel_lvds_init - setup LVDS connectors on this device
560 * @dev: drm device
561 *
562 * Create the connector, register the LVDS DDC bus, and try to figure out what
563 * modes we can display on the LVDS panel (if present).
564 */
565void cdv_intel_lvds_init(struct drm_device *dev,
566 struct psb_intel_mode_device *mode_dev)
567{
568 struct psb_intel_output *psb_intel_output;
569 struct cdv_intel_lvds_priv *lvds_priv;
570 struct drm_connector *connector;
571 struct drm_encoder *encoder;
572 struct drm_display_mode *scan;
573 struct drm_crtc *crtc;
574 struct drm_psb_private *dev_priv = dev->dev_private;
575 u32 lvds;
576 int pipe;
577
578 psb_intel_output = kzalloc(sizeof(struct psb_intel_output) +
579 sizeof(struct cdv_intel_lvds_priv), GFP_KERNEL);
580 if (!psb_intel_output)
581 return;
582
583 lvds_priv = (struct cdv_intel_lvds_priv *)(psb_intel_output + 1);
584
585 psb_intel_output->dev_priv = lvds_priv;
586
587 psb_intel_output->mode_dev = mode_dev;
588 connector = &psb_intel_output->base;
589 encoder = &psb_intel_output->enc;
590
591
592 drm_connector_init(dev, &psb_intel_output->base,
593 &cdv_intel_lvds_connector_funcs,
594 DRM_MODE_CONNECTOR_LVDS);
595
596 drm_encoder_init(dev, &psb_intel_output->enc,
597 &cdv_intel_lvds_enc_funcs,
598 DRM_MODE_ENCODER_LVDS);
599
600
601 drm_mode_connector_attach_encoder(&psb_intel_output->base,
602 &psb_intel_output->enc);
603 psb_intel_output->type = INTEL_OUTPUT_LVDS;
604
605 drm_encoder_helper_add(encoder, &cdv_intel_lvds_helper_funcs);
606 drm_connector_helper_add(connector,
607 &cdv_intel_lvds_connector_helper_funcs);
608 connector->display_info.subpixel_order = SubPixelHorizontalRGB;
609 connector->interlace_allowed = false;
610 connector->doublescan_allowed = false;
611
612 /*Attach connector properties*/
613 drm_connector_attach_property(connector,
614 dev->mode_config.scaling_mode_property,
615 DRM_MODE_SCALE_FULLSCREEN);
616 drm_connector_attach_property(connector,
617 dev_priv->backlight_property,
618 BRIGHTNESS_MAX_LEVEL);
619
620 /**
621 * Set up I2C bus
622 * FIXME: distroy i2c_bus when exit
623 */
624 psb_intel_output->i2c_bus = psb_intel_i2c_create(dev,
625 GPIOB,
626 "LVDSBLC_B");
627 if (!psb_intel_output->i2c_bus) {
628 dev_printk(KERN_ERR,
629 &dev->pdev->dev, "I2C bus registration failed.\n");
630 goto failed_blc_i2c;
631 }
632 psb_intel_output->i2c_bus->slave_addr = 0x2C;
633 dev_priv->lvds_i2c_bus = psb_intel_output->i2c_bus;
634
635 /*
636 * LVDS discovery:
637 * 1) check for EDID on DDC
638 * 2) check for VBT data
639 * 3) check to see if LVDS is already on
640 * if none of the above, no panel
641 * 4) make sure lid is open
642 * if closed, act like it's not there for now
643 */
644
645 /* Set up the DDC bus. */
646 psb_intel_output->ddc_bus = psb_intel_i2c_create(dev,
647 GPIOC,
648 "LVDSDDC_C");
649 if (!psb_intel_output->ddc_bus) {
650 dev_printk(KERN_ERR, &dev->pdev->dev,
651 "DDC bus registration " "failed.\n");
652 goto failed_ddc;
653 }
654
655 /*
656 * Attempt to get the fixed panel mode from DDC. Assume that the
657 * preferred mode is the right one.
658 */
659 psb_intel_ddc_get_modes(psb_intel_output);
660 list_for_each_entry(scan, &connector->probed_modes, head) {
661 if (scan->type & DRM_MODE_TYPE_PREFERRED) {
662 mode_dev->panel_fixed_mode =
663 drm_mode_duplicate(dev, scan);
664 goto out; /* FIXME: check for quirks */
665 }
666 }
667
668 /* Failed to get EDID, what about VBT? do we need this?*/
669 if (dev_priv->lfp_lvds_vbt_mode) {
670 mode_dev->panel_fixed_mode =
671 drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode);
672 if (mode_dev->panel_fixed_mode) {
673 mode_dev->panel_fixed_mode->type |=
674 DRM_MODE_TYPE_PREFERRED;
675 goto out; /* FIXME: check for quirks */
676 }
677 }
678 /*
679 * If we didn't get EDID, try checking if the panel is already turned
680 * on. If so, assume that whatever is currently programmed is the
681 * correct mode.
682 */
683 lvds = REG_READ(LVDS);
684 pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0;
685 crtc = psb_intel_get_crtc_from_pipe(dev, pipe);
686
687 if (crtc && (lvds & LVDS_PORT_EN)) {
688 mode_dev->panel_fixed_mode =
689 cdv_intel_crtc_mode_get(dev, crtc);
690 if (mode_dev->panel_fixed_mode) {
691 mode_dev->panel_fixed_mode->type |=
692 DRM_MODE_TYPE_PREFERRED;
693 goto out; /* FIXME: check for quirks */
694 }
695 }
696
697 /* If we still don't have a mode after all that, give up. */
698 if (!mode_dev->panel_fixed_mode) {
699 DRM_DEBUG
700 ("Found no modes on the lvds, ignoring the LVDS\n");
701 goto failed_find;
702 }
703
704out:
705 drm_sysfs_connector_add(connector);
706 return;
707
708failed_find:
709 printk(KERN_ERR "Failed find\n");
710 if (psb_intel_output->ddc_bus)
711 psb_intel_i2c_destroy(psb_intel_output->ddc_bus);
712failed_ddc:
713 printk(KERN_ERR "Failed DDC\n");
714 if (psb_intel_output->i2c_bus)
715 psb_intel_i2c_destroy(psb_intel_output->i2c_bus);
716failed_blc_i2c:
717 printk(KERN_ERR "Failed BLC\n");
718 drm_encoder_cleanup(encoder);
719 drm_connector_cleanup(connector);
720 kfree(connector);
721}